This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,73 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// SteamFileDialog.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "FileDialogApp.h"
#include "interface.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
//
/////////////////////////////////////////////////////////////////////////////
// CSteamFileDialogApp
BEGIN_MESSAGE_MAP(CSteamFileDialogApp, CWinApp)
//{{AFX_MSG_MAP(CSteamFileDialogApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSteamFileDialogApp construction
CSteamFileDialogApp::CSteamFileDialogApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CSteamFileDialogApp object
CSteamFileDialogApp theApp;

View File

@@ -0,0 +1,52 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// SteamFileDialog.h : main header file for the STEAMFILEDIALOG DLL
//
#if !defined(AFX_STEAMFILEDIALOG_H__BF4B825D_4E34_443E_84D2_6212C043388D__INCLUDED_)
#define AFX_STEAMFILEDIALOG_H__BF4B825D_4E34_443E_84D2_6212C043388D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CSteamFileDialogApp
// See SteamFileDialog.cpp for the implementation of this class
//
class CSteamFileDialogApp : public CWinApp
{
public:
CSteamFileDialogApp();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSteamFileDialogApp)
//}}AFX_VIRTUAL
//{{AFX_MSG(CSteamFileDialogApp)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STEAMFILEDIALOG_H__BF4B825D_4E34_443E_84D2_6212C043388D__INCLUDED_)

View File

@@ -0,0 +1,192 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
"#define _AFX_NO_OLE_RESOURCES\r\n"
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
"\r\n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
"#ifdef _WIN32\r\n"
"LANGUAGE 9, 1\r\n"
"#pragma code_page(1252)\r\n"
"#endif //_WIN32\r\n"
"#include ""res\\SteamFileDialog.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
"#include ""afxres.rc"" // Standard components\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SteamFileDialog DLL\0"
VALUE "FileVersion", "1, 0, 0, 1\0"
VALUE "InternalName", "SteamFileDialog\0"
VALUE "LegalCopyright", "Copyright (C) 2004\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "SteamFileDialog.DLL\0"
VALUE "ProductName", "SteamFileDialog Dynamic Link Library\0"
VALUE "ProductVersion", "1, 0, 0, 1\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_FILESYSTEM_OPENDIALOG DIALOG DISCARDABLE 0, 0, 573, 374
STYLE WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Open"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "List1",IDC_FILE_LIST,"SysListView32",LVS_OWNERDRAWFIXED |
WS_BORDER | WS_TABSTOP,7,29,559,301
EDITTEXT IDC_FILENAME,48,335,362,14,ES_AUTOHSCROLL
DEFPUSHBUTTON "&Open",IDOK,516,335,50,14
PUSHBUTTON "Cancel",IDCANCEL,516,353,50,14
PUSHBUTTON "&Up",IDC_UP_BUTTON,416,7,19,14
LTEXT "File &name:",IDC_FILENAME_LABEL,7,338,33,8
LTEXT "Look in:",IDC_STATIC,7,10,26,8
EDITTEXT IDC_LOOKIN,48,7,362,14,ES_AUTOHSCROLL | ES_READONLY |
NOT WS_TABSTOP
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_FILESYSTEM_OPENDIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 566
TOPMARGIN, 7
BOTTOMMARGIN, 367
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_LABEL_MDL BITMAP DISCARDABLE "res\\label_mdl.bmp"
IDB_LABEL_FOLDER BITMAP DISCARDABLE "res\\label_fo.bmp"
IDB_LABEL_FILE BITMAP DISCARDABLE "res\\label_file.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_NO_RELATIVE_PATH "The selected file is not under your game's directory, so it can't be used."
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE 9, 1
#pragma code_page(1252)
#endif //_WIN32
#include "res\SteamFileDialog.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#endif
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,146 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined(AFX_FILESYSTEMOPENDLG_H__01CFDE04_321F_4F1E_94ED_933B2B32C193__INCLUDED_)
#define AFX_FILESYSTEMOPENDLG_H__01CFDE04_321F_4F1E_94ED_933B2B32C193__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// FileSystemOpenDlg.h : header file
//
#include "utlvector.h"
#include "resource.h"
#include "filesystem.h"
/////////////////////////////////////////////////////////////////////////////
// CFileSystemOpenDlg dialog
class CWindowAnchor
{
public:
CWnd *m_pWnd;
int m_Side; //0=left, 1=top, 2=right, 3=bottom
int m_ParentSide; //which side to anchor to parent
int m_OriginalDist; //original distance from the parent side
};
class CFileInfo
{
public:
CFileInfo();
~CFileInfo();
bool m_bIsDir;
CString m_Name;
CBitmap *m_pBitmap;
};
class CFileSystemOpenDlg : public CDialog
{
friend class CFileSystemOpenDialogWrapper;
// Construction
public:
CFileSystemOpenDlg(CreateInterfaceFn factory, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CFileSystemOpenDlg)
enum { IDD = IDD_FILESYSTEM_OPENDIALOG };
CEdit m_FilenameLabel;
CEdit m_FilenameControl;
CEdit m_LookInLabel;
CListCtrl m_FileList;
//}}AFX_DATA
void AddFileMask( const char *pMask );
void SetInitialDir( const char *pDir, const char *pPathID = NULL );
void SetFilterMdlAndJpgFiles( bool bFilter );
CString GetFilename() const; // Get the filename they chose.
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CFileSystemOpenDlg)
public:
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
private:
enum GetEntriesMode_t
{
GETENTRIES_FILES_ONLY,
GETENTRIES_DIRECTORIES_ONLY
};
void GetEntries( const char *pMask, CUtlVector<CString> &entries, GetEntriesMode_t mode );
void PopulateListControl();
int SetupLabelImage( CFileInfo *pInfo, CString name, bool bIsDir );
void AddAnchor( int iDlgItem, int iSide, int anchorSide );
void ProcessAnchor( CWindowAnchor *pAnchor );
// Implementation
protected:
const char* GetPathID();
friend int CALLBACK FileListSortCallback( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort );
friend class CFilenameShortcut;
CUtlVector<CWindowAnchor> m_Anchors;
enum
{
PREVIEW_IMAGE_SIZE=96
};
IFileSystem *m_pFileSystem;
// These are indexed by the lParam or userdata of each item in m_FileList.
CUtlVector<CFileInfo> m_FileInfos;
int m_iLabel_Folder;
int m_iLabel_Mdl;
int m_iLabel_File;
CBitmap m_BitmapMdl;
CBitmap m_BitmapFile;
CBitmap m_BitmapFolder;
CImageList m_ImageList;
CString m_CurrentDir;
CString m_Filename;
CString m_PathIDString;
CUtlVector<CString> m_FileMasks;
// If this is true, then we get rid of .mdl files if there is a corresponding .jpg file.
bool m_bFilterMdlAndJpgFiles;
// Generated message map functions
//{{AFX_MSG(CFileSystemOpenDlg)
virtual void OnOK();
virtual BOOL OnInitDialog();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnDblclkFileList(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnUpButton();
afx_msg void OnItemchangedFileList(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_FILESYSTEMOPENDLG_H__01CFDE04_321F_4F1E_94ED_933B2B32C193__INCLUDED_)

View File

@@ -0,0 +1,15 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// stdafx.cpp : source file that includes just the standard includes
// SteamFileDialog.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

View File

@@ -0,0 +1,52 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__4F9B2A8A_E38D_4917_BA99_46DF8EC095C9__INCLUDED_)
#define AFX_STDAFX_H__4F9B2A8A_E38D_4917_BA99_46DF8EC095C9__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "tier0/wchartypes.h"
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxole.h> // MFC OLE classes
#include <afxodlgs.h> // MFC OLE dialog classes
#include <afxdisp.h> // MFC Automation classes
#endif // _AFX_NO_OLE_SUPPORT
#ifndef _AFX_NO_DB_SUPPORT
#include <afxdb.h> // MFC ODBC database classes
#endif // _AFX_NO_DB_SUPPORT
#ifndef _AFX_NO_DAO_SUPPORT
#include <afxdao.h> // MFC DAO database classes
#endif // _AFX_NO_DAO_SUPPORT
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#include <afxpriv.h>
#endif // _AFX_NO_AFXCMN_SUPPORT
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__4F9B2A8A_E38D_4917_BA99_46DF8EC095C9__INCLUDED_)

View File

@@ -0,0 +1,40 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\public\tier0\afxmem_override.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\tier0\afxmem_override.cpp
Release output file: F:\csgo_64\cstrike15_src\public\tier0\afxmem_override.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\FileDialogApp.cpp
Debug output file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\FileDialogApp.cpp
Release output file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\FileDialogApp.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\FileSystemOpenDlg.cpp
Debug output file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\FileSystemOpenDlg.cpp
Release output file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\FileSystemOpenDlg.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Release output file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\StdAfx.cpp
Debug output file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\StdAfx.cpp
Release output file: F:\csgo_64\cstrike15_src\utils\FileSystemOpenDialog\StdAfx.cpp
Containing unity file:
PCH file:

View File

@@ -0,0 +1,82 @@
//-----------------------------------------------------------------------------
// FILESYSTEMOPENDIALOG.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_win32_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,..\common"
$PreprocessorDefinitions "$BASE;;WINVER=0x502;NO_WARN_MBCS_MFC_DEPRECATION"
$Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)"
$EnableC++Exceptions "Yes (/EHsc)"
}
}
$Project "FileSystemOpenDialog"
{
$Folder "Source Files"
{
$File "$SRCDIR\public\tier0\afxmem_override.cpp"
$File "FileDialogApp.cpp"
$File "FileDialogApp.h"
$File "FileSystemOpenDlg.cpp"
$File "FileSystemOpenDlg.h"
$File "$SRCDIR\common\IFileSystemOpenDialog.h"
-$File "$SRCDIR\public\tier0\memoverride.cpp"
$File "$SRCDIR\public\tier0\memoverride.cpp"
{
$Configuration "Release"
{
$Compiler
{
$PreprocessorDefinitions "$BASE;NO_MEMOVERRIDE_NEW_DELETE"
$Create/UsePrecompiledHeader "Not Using Precompiled Headers"
}
}
$Configuration "Debug"
{
$Compiler
{
$PreprocessorDefinitions "$BASE;NO_MEMOVERRIDE_NEW_DELETE"
$Create/UsePrecompiledHeader "Not Using Precompiled Headers"
}
}
}
$File "StdAfx.cpp"
{
$Configuration
{
$Compiler
{
$Create/UsePrecompiledHeader "Create Precompiled Header (/Yc)"
}
}
}
}
$Folder "Header Files"
{
$File "resource.h"
$File "StdAfx.h"
}
$Folder "Resource Files"
{
$File "FileSystemOpenDialog.rc"
$DynamicFile "res\FileSystemOpenDialog.rc2"
}
$Folder "Link Libraries"
{
$File "$SRCDIR\lib\common\jpeglib.lib"
}
}

View File

@@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "FileSystemOpenDialog.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "FileSystemOpenDialog.vcxproj"
"1" "FileSystemOpenDialog.vcxproj.filters"
}
}
}

View File

@@ -0,0 +1,13 @@
//
// STEAMFILEDIALOG.RC2 - resources Microsoft Visual C++ does not edit directly
//
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Microsoft Visual C++
#endif //APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// Add manually edited resources here...
/////////////////////////////////////////////////////////////////////////////

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,25 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by FileSystemOpenDialog.rc
//
#define IDS_NO_RELATIVE_PATH 1
#define IDD_FILESYSTEM_OPENDIALOG 327
#define IDB_LABEL_MDL 328
#define IDB_LABEL_FOLDER 329
#define IDB_LABEL_FILE 331
#define IDC_FILENAME 1009
#define IDC_UP_BUTTON 1010
#define IDC_LOOKIN 1011
#define IDC_FILE_LIST 1098
#define IDC_FILENAME_LABEL 1644
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 1000
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 1000
#endif
#endif

View File

@@ -0,0 +1,356 @@
//================ Copyright (c) 1996-2009 Valve Corporation. All Rights Reserved. =================
//
//
//
//==================================================================================================
#ifdef _WIN32
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <io.h>
#else
#include <stdarg.h>
#include <dlfcn.h>
#endif
#include <stdio.h>
#include "tier0/platform.h"
#include "tier0/basetypes.h"
#include "ilaunchabledll.h"
#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/')
#ifdef PLATFORM_WINDOWS
#pragma warning(disable : 4127)
#define CORRECT_PATH_SEPARATOR_S "\\"
#define CORRECT_PATH_SEPARATOR '\\'
#define INCORRECT_PATH_SEPARATOR '/'
#else
#define CORRECT_PATH_SEPARATOR '/'
#define CORRECT_PATH_SEPARATOR_S "/"
#define INCORRECT_PATH_SEPARATOR '\\'
#endif
#undef stricmp
#ifdef COMPILER_MSVC
#define V_stricmp stricmp
#else
#define V_stricmp strcasecmp
#endif
#define CREATEINTERFACE_PROCNAME "CreateInterface"
typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode);
static void V_strncpy( char *pDest, char const *pSrc, int maxLen )
{
strncpy( pDest, pSrc, maxLen );
if ( maxLen > 0 )
{
pDest[maxLen-1] = 0;
}
}
static int V_strlen( const char *pStr )
{
return (int)strlen( pStr );
}
static void V_strncat( char *pDest, const char *pSrc, int destSize )
{
strncat( pDest, pSrc, destSize );
pDest[destSize-1] = 0;
}
static void V_AppendSlash( char *pStr, int strSize )
{
int len = V_strlen( pStr );
if ( len > 0 && !PATHSEPARATOR(pStr[len-1]) )
{
if ( len+1 >= strSize )
{
fprintf( stderr, "V_AppendSlash: ran out of space on %s.", pStr );
exit( 1 );
}
pStr[len] = CORRECT_PATH_SEPARATOR;
pStr[len+1] = 0;
}
}
static void V_FixSlashes( char *pStr )
{
for ( ; *pStr; ++pStr )
{
if ( *pStr == INCORRECT_PATH_SEPARATOR )
*pStr = CORRECT_PATH_SEPARATOR;
}
}
static void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize )
{
V_strncpy( dest, path, destSize );
V_AppendSlash( dest, destSize );
V_strncat( dest, filename, destSize );
V_FixSlashes( dest );
}
static int V_snprintf( char *pDest, int maxLen, const char *pFormat, ... )
{
va_list marker;
va_start( marker, pFormat );
#ifdef _WIN32
int len = _vsnprintf( pDest, maxLen, pFormat, marker );
#elif POSIX
int len = vsnprintf( pDest, maxLen, pFormat, marker );
#else
#error "define vsnprintf type."
#endif
va_end( marker );
// Len < 0 represents an overflow
if( len < 0 )
{
len = maxLen;
pDest[maxLen-1] = 0;
}
return len;
}
static bool V_StripLastDir( char *dirName, int maxlen )
{
if( dirName[0] == 0 || !V_stricmp( dirName, "./" ) || !V_stricmp( dirName, ".\\" ) )
{
return false;
}
int len = V_strlen( dirName );
// skip trailing slash
if ( PATHSEPARATOR( dirName[len-1] ) )
{
len--;
}
while ( len > 0 )
{
if ( PATHSEPARATOR( dirName[len-1] ) )
{
dirName[len] = 0;
V_FixSlashes( dirName );
return true;
}
len--;
}
// Allow it to return an empty string and true. This can happen if something like "tf2/" is passed in.
// The correct behavior is to strip off the last directory ("tf2") and return true.
if( len == 0 )
{
V_snprintf( dirName, maxlen, ".%c", CORRECT_PATH_SEPARATOR );
return true;
}
return true;
}
#ifdef _WIN32
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
#define IO_REPARSE_TAG_SYMLINK 0xa0000003
void TranslateSymlink( const char *pInDir, char *pOutDir, int len )
{
// This is the default. If it's a reparse point, it'll get replaced below.
V_strncpy( pOutDir, pInDir, len );
// The equivalent of symlinks in Win32 is "NTFS reparse points".
DWORD nAttribs = GetFileAttributes( pInDir );
if ( nAttribs & FILE_ATTRIBUTE_REPARSE_POINT )
{
HANDLE hDir = CreateFile( pInDir, FILE_READ_EA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL );
if ( hDir )
{
DWORD dwBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
REPARSE_DATA_BUFFER *pReparseData = (REPARSE_DATA_BUFFER*)malloc( dwBufSize );
DWORD nBytesReturned = 0;
BOOL bSuccess = DeviceIoControl( hDir, FSCTL_GET_REPARSE_POINT, NULL, 0, pReparseData, dwBufSize, &nBytesReturned, NULL );
CloseHandle( hDir );
if ( bSuccess )
{
if ( IsReparseTagMicrosoft( pReparseData->ReparseTag ) )
{
if ( pReparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK )
{
REPARSE_DATA_BUFFER *rdata = pReparseData;
// Pull out the substitution name.
char szSubName[MAX_PATH*2];
wchar_t *pSrcString = &rdata->SymbolicLinkReparseBuffer.PathBuffer[rdata->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)];
size_t nConvertedChars;
wcstombs_s( &nConvertedChars, szSubName, wcslen( pSrcString ) + 1, pSrcString, _TRUNCATE );
// Look for the drive letter and start there.
const char *pColon = strchr( szSubName, ':' );
if ( pColon && pColon > szSubName )
{
const char *pRemappedName = ( pColon - 1 );
V_strncpy( pOutDir, pRemappedName, len );
}
}
}
}
free( pReparseData );
}
else
{
printf( "Warning: Found a reparse point (ntfs symlink) for %s but CreateFile failed\n", pInDir );
}
}
}
#endif
int main( int argc, char **argv )
{
// Find the game\bin directory and setup the DLL path.
char szModuleFilename[MAX_PATH], szModuleParts[MAX_PATH], szCurDir[MAX_PATH];
#ifdef WIN32
GetModuleFileName( NULL, szModuleFilename, sizeof( szModuleFilename ) );
V_FixSlashes( szModuleFilename );
#else
V_strncpy( szModuleFilename, argv[0], sizeof(szModuleFilename) );
#endif
V_strncpy( szModuleParts, szModuleFilename, sizeof( szModuleParts ) );
char *pFilename = strrchr( szModuleParts, CORRECT_PATH_SEPARATOR );
if ( !pFilename )
{
fprintf( stderr, "%s (binlaunch): Can't get filename from GetModuleFilename (%s).\n", argv[0], szModuleFilename );
return 1;
}
*pFilename = 0;
++pFilename;
const char *pBaseDir = szModuleParts;
#ifdef WIN32
TranslateSymlink( pBaseDir, szCurDir, sizeof( szCurDir ) );
#else
V_strncpy( szCurDir, pBaseDir, sizeof(szCurDir) );
#endif
char szGameBinDir[MAX_PATH];
while ( 1 )
{
V_ComposeFileName( szCurDir, "game" CORRECT_PATH_SEPARATOR_S "bin", szGameBinDir, sizeof( szGameBinDir ) );
// Look for stuff we know about in game\bin.
char szTestFile1[MAX_PATH], szTestFile2[MAX_PATH];
V_ComposeFileName( szGameBinDir, "tier0.dll", szTestFile1, sizeof( szTestFile1 ) );
V_ComposeFileName( szGameBinDir, "vstdlib.dll", szTestFile2, sizeof( szTestFile2 ) );
if ( _access( szTestFile1, 0 ) == 0 && _access( szTestFile2, 0 ) == 0 )
{
break;
}
// Backup a directory.
if ( !V_StripLastDir( szCurDir, sizeof( szCurDir ) ) )
{
fprintf( stderr, "%s (binlaunch): Unable to find game\\bin directory anywhere up the tree from %s.\n", argv[0], pBaseDir );
return 1;
}
}
// Setup the path to include the specified directory.
int nGameBinDirLen = V_strlen( szGameBinDir );
char *pOldPath = getenv( "PATH" );
int nNewLen = V_strlen( pOldPath ) + nGameBinDirLen + 5 + 1 + 1; // 5 for PATH=, 1 for the semicolon, and 1 for the null terminator.
char *pNewPath = new char[nNewLen];
V_snprintf( pNewPath, nNewLen, "PATH=%s;%s", szGameBinDir, pOldPath );
_putenv( pNewPath );
delete [] pNewPath;
// Get rid of the file extension on our executable name.
#ifdef WIN32
char *pDot = strchr( &szModuleFilename[pFilename-szModuleParts], '.' );
if ( !pDot )
{
fprintf( stderr, "%s (binlaunch): No dot character in the filename.\n", argv[0] );
return 1;
}
*pDot = 0;
#endif
char szDLLName[MAX_PATH];
V_snprintf( szDLLName, sizeof( szDLLName ), "%s%s", szModuleFilename, DLL_EXT_STRING );
//
// Now go load their DLL and launch it.
//
#ifdef WIN32
HMODULE hModule = LoadLibrary( szDLLName );
#else
HMODULE hModule = dlopen( szDLLName, RTLD_NOW );
#endif
if ( !hModule )
{
fprintf( stderr, "%s (binlaunch): Unable to load module %s\n\n", argv[0], szDLLName );
return 9998;
}
CreateInterfaceFn fn = (CreateInterfaceFn)GetProcAddress( hModule, CREATEINTERFACE_PROCNAME );
ILaunchableDLL *pLaunchable;
if ( !fn )
{
fprintf( stderr, "%s (binlaunch): Can't get function %s from %s\n\n", argv[0], CREATEINTERFACE_PROCNAME, szDLLName );
return 9997;
}
pLaunchable = (ILaunchableDLL*)fn( LAUNCHABLE_DLL_INTERFACE_VERSION, NULL );
if ( !pLaunchable )
{
fprintf( stderr, "%s (binlaunch): Can't get interface %s from from %s\n\n", argv[0], LAUNCHABLE_DLL_INTERFACE_VERSION, szDLLName );
return 9996;
}
return pLaunchable->main( argc, argv );
}

View File

@@ -0,0 +1,56 @@
//-----------------------------------------------------------------------------
// BINLAUNCH.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\devtools\bin"
$Include "$SRCDIR\vpc_scripts\source_exe_con_win32_base.vpc"
$Configuration
{
$PostBuildEvent
{
// Various projects like vpc and remotemirror use copies of the binlaunch.exe, so when binlaunch is built,
// it copies to those exes.
$CommandLine "$BASE" "\n" \
"\n" \
"echo ... Copying BINLAUNCH.EXE to REMOTEMIRROR.EXE" "\n" \
"call $SRCDIR\vpc_scripts\valve_p4_edit.cmd $SRCDIR\devtools\bin\remotemirror.exe $SRCDIR" "\n" \
"copy $OUTBINDIR\$(TargetFileName) $SRCDIR\devtools\bin\remotemirror.exe" "\n" \
"if ERRORLEVEL 1 goto BinLaunchCopyFailed" "\n" \
"\n" \
"echo ... Copying BINLAUNCH.EXE to SCHEMACOMPILER.EXE" "\n" \
"call $SRCDIR\vpc_scripts\valve_p4_edit.cmd $SRCDIR\devtools\bin\schemacompiler.exe $SRCDIR" "\n" \
"copy $OUTBINDIR\$(TargetFileName) $SRCDIR\devtools\bin\schemacompiler.exe" "\n" \
"if ERRORLEVEL 1 goto BinLaunchCopyFailed" "\n" \
"\n" \
"goto BinLaunchCopyOK" "\n" \
"\n" \
":BinLaunchCopyFailed" "\n" \
"echo *** ERROR! binlaunch copy step failed." "\n" \
"del /q $QUOTE$(TargetDir)$QUOTE$(TargetFileName)" "\n" \
"exit 1" "\n" \
"\n" \
":BinLaunchCopyOK" "\n" \
"\n"
}
}
$Project "binlaunch"
{
$Folder "Source Files"
{
$File "binlaunch.cpp"
-$File "$SRCDIR\public\tier0\memoverride.cpp"
}
$Folder "Link Libraries"
{
-$ImpLib tier0
-$Lib tier1
-$ImpLib vstdlib
}
}

View File

@@ -0,0 +1,58 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\blocksort.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\blocksort.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\blocksort.c
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\bzip2.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\bzip2.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\bzip2.c
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\bzlib.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\bzlib.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\bzlib.c
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\compress.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\compress.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\compress.c
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\crctable.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\crctable.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\crctable.c
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\decompress.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\decompress.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\decompress.c
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\huffman.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\huffman.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\huffman.c
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\utils\bzip2\randtable.c
Debug output file: F:\csgo_64\cstrike15_src\utils\bzip2\randtable.c
Release output file: F:\csgo_64\cstrike15_src\utils\bzip2\randtable.c
Containing unity file:
PCH file:

1141
utils/bzip2/blocksort.c Normal file

File diff suppressed because it is too large Load Diff

2142
utils/bzip2/bzip2.c Normal file

File diff suppressed because it is too large Load Diff

46
utils/bzip2/bzip2.vpc Normal file
View File

@@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// BZIP2.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTLIBDIR "$OUTLIBCOMMONDIR"
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler [$PS3]
{
$PreprocessorDefinitions "$BASE;_PS3"
$ForceIncludes " "
}
$Compiler [!$PS3]
{
$ForceIncludes " "
$CompileAs "Compile as C Code (/TC)"
}
}
$Project "Bzip2"
{
$Folder "Source Files"
{
$File "blocksort.c"
$File "bzip2.c"
$File "bzlib.c"
$File "compress.c"
$File "crctable.c"
$File "decompress.c"
$File "huffman.c"
$File "randtable.c"
}
$Folder "Header Files"
{
$File "bzlib.h"
$File "bzlib_private.h"
}
}

View File

@@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "bzip2.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "bzip2.vcxproj"
"1" "bzip2.vcxproj.filters"
}
}
}

1593
utils/bzip2/bzlib.c Normal file

File diff suppressed because it is too large Load Diff

321
utils/bzip2/bzlib.h Normal file
View File

@@ -0,0 +1,321 @@
/*-------------------------------------------------------------*/
/*--- Public header file for the library. ---*/
/*--- bzlib.h ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
#ifndef _BZLIB_H
#define _BZLIB_H
#ifdef __cplusplus
extern "C" {
#endif
#define BZ_RUN 0
#define BZ_FLUSH 1
#define BZ_FINISH 2
#define BZ_OK 0
#define BZ_RUN_OK 1
#define BZ_FLUSH_OK 2
#define BZ_FINISH_OK 3
#define BZ_STREAM_END 4
#define BZ_SEQUENCE_ERROR (-1)
#define BZ_PARAM_ERROR (-2)
#define BZ_MEM_ERROR (-3)
#define BZ_DATA_ERROR (-4)
#define BZ_DATA_ERROR_MAGIC (-5)
#define BZ_IO_ERROR (-6)
#define BZ_UNEXPECTED_EOF (-7)
#define BZ_OUTBUFF_FULL (-8)
#define BZ_CONFIG_ERROR (-9)
typedef
struct {
char *next_in;
unsigned int avail_in;
unsigned int total_in_lo32;
unsigned int total_in_hi32;
char *next_out;
unsigned int avail_out;
unsigned int total_out_lo32;
unsigned int total_out_hi32;
void *state;
void *(*bzalloc)(void *,int,int);
void (*bzfree)(void *,void *);
void *opaque;
}
bz_stream;
#ifndef BZ_IMPORT
#define BZ_EXPORT
#endif
/* Need a definitition for FILE */
#include <stdio.h>
#if defined(_WIN32) && !defined(_X360)
# include <windows.h>
# ifdef small
/* windows.h define small to char */
# undef small
# endif
# ifdef BZ_EXPORT
# define BZ_API(func) WINAPI func
# define BZ_EXTERN extern
# else
/* import windows dll dynamically */
# define BZ_API(func) (WINAPI * func)
# define BZ_EXTERN
# endif
#else
# define BZ_API(func) func
# define BZ_EXTERN extern
#endif
/*-- Core (low-level) library functions --*/
BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
bz_stream* strm,
int blockSize100k,
int verbosity,
int workFactor
);
BZ_EXTERN int BZ_API(BZ2_bzCompress) (
bz_stream* strm,
int action
);
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
bz_stream* strm
);
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
bz_stream *strm,
int verbosity,
int small
);
BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
bz_stream* strm
);
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
bz_stream *strm
);
/*-- High(er) level library functions --*/
#ifndef BZ_NO_STDIO
#define BZ_MAX_UNUSED 5000
typedef void BZFILE;
BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
int* bzerror,
FILE* f,
int verbosity,
int small,
void* unused,
int nUnused
);
BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
int* bzerror,
BZFILE* b
);
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
int* bzerror,
BZFILE* b,
void** unused,
int* nUnused
);
BZ_EXTERN int BZ_API(BZ2_bzRead) (
int* bzerror,
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
int* bzerror,
FILE* f,
int blockSize100k,
int verbosity,
int workFactor
);
BZ_EXTERN void BZ_API(BZ2_bzWrite) (
int* bzerror,
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in,
unsigned int* nbytes_out
);
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in_lo32,
unsigned int* nbytes_in_hi32,
unsigned int* nbytes_out_lo32,
unsigned int* nbytes_out_hi32
);
#endif
/*-- Utility functions --*/
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int blockSize100k,
int verbosity,
int workFactor
);
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int small,
int verbosity
);
/*--
Code contributed by Yoshioka Tsuneo
(QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp),
to support better zlib compatibility.
This code is not _officially_ part of libbzip2 (yet);
I haven't tested it, documented it, or considered the
threading-safeness of it.
If this code breaks, please contact both Yoshioka and me.
--*/
BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
void
);
#ifndef BZ_NO_STDIO
BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
const char *path,
const char *mode
);
BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
int fd,
const char *mode
);
BZ_EXTERN int BZ_API(BZ2_bzread) (
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN int BZ_API(BZ2_bzwrite) (
BZFILE* b,
void* buf,
int len
);
BZ_EXTERN int BZ_API(BZ2_bzflush) (
BZFILE* b
);
BZ_EXTERN void BZ_API(BZ2_bzclose) (
BZFILE* b
);
BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
BZFILE *b,
int *errnum
);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*-------------------------------------------------------------*/
/*--- end bzlib.h ---*/
/*-------------------------------------------------------------*/

550
utils/bzip2/bzlib_private.h Normal file
View File

@@ -0,0 +1,550 @@
/*-------------------------------------------------------------*/
/*--- Private header file for the library. ---*/
/*--- bzlib_private.h ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
#ifndef _BZLIB_PRIVATE_H
#define _BZLIB_PRIVATE_H
#include <stdlib.h>
#ifndef BZ_NO_STDIO
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#endif
#include "bzlib.h"
/*-- General stuff. --*/
#define BZ_VERSION "1.0.2, 30-Dec-2001"
typedef char Char;
typedef unsigned char Bool;
typedef unsigned char UChar;
typedef int Int32;
typedef unsigned int UInt32;
typedef short Int16;
typedef unsigned short UInt16;
#define True ((Bool)1)
#define False ((Bool)0)
#ifndef __GNUC__
#define __inline__ /* */
#endif
#ifndef BZ_NO_STDIO
extern void BZ2_bz__AssertH__fail ( int errcode );
#define AssertH(cond,errcode) \
{ if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
#if BZ_DEBUG
#define AssertD(cond,msg) \
{ if (!(cond)) { \
fprintf ( stderr, \
"\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
exit(1); \
}}
#else
#define AssertD(cond,msg) /* */
#endif
#define VPrintf0(zf) \
fprintf(stderr,zf)
#define VPrintf1(zf,za1) \
fprintf(stderr,zf,za1)
#define VPrintf2(zf,za1,za2) \
fprintf(stderr,zf,za1,za2)
#define VPrintf3(zf,za1,za2,za3) \
fprintf(stderr,zf,za1,za2,za3)
#define VPrintf4(zf,za1,za2,za3,za4) \
fprintf(stderr,zf,za1,za2,za3,za4)
#define VPrintf5(zf,za1,za2,za3,za4,za5) \
fprintf(stderr,zf,za1,za2,za3,za4,za5)
#else
extern void bz_internal_error ( int errcode );
#define AssertH(cond,errcode) \
{ if (!(cond)) bz_internal_error ( errcode ); }
#define AssertD(cond,msg) /* */
#define VPrintf0(zf) /* */
#define VPrintf1(zf,za1) /* */
#define VPrintf2(zf,za1,za2) /* */
#define VPrintf3(zf,za1,za2,za3) /* */
#define VPrintf4(zf,za1,za2,za3,za4) /* */
#define VPrintf5(zf,za1,za2,za3,za4,za5) /* */
#endif
#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp))
/*-- Header bytes. --*/
#define BZ_HDR_B 0x42 /* 'B' */
#define BZ_HDR_Z 0x5a /* 'Z' */
#define BZ_HDR_h 0x68 /* 'h' */
#define BZ_HDR_0 0x30 /* '0' */
/*-- Constants for the back end. --*/
#define BZ_MAX_ALPHA_SIZE 258
#define BZ_MAX_CODE_LEN 23
#define BZ_RUNA 0
#define BZ_RUNB 1
#define BZ_N_GROUPS 6
#define BZ_G_SIZE 50
#define BZ_N_ITERS 4
#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
/*-- Stuff for randomising repetitive blocks. --*/
extern Int32 BZ2_rNums[512];
#define BZ_RAND_DECLS \
Int32 rNToGo; \
Int32 rTPos \
#define BZ_RAND_INIT_MASK \
s->rNToGo = 0; \
s->rTPos = 0 \
#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
#define BZ_RAND_UPD_MASK \
if (s->rNToGo == 0) { \
s->rNToGo = BZ2_rNums[s->rTPos]; \
s->rTPos++; \
if (s->rTPos == 512) s->rTPos = 0; \
} \
s->rNToGo--;
/*-- Stuff for doing CRCs. --*/
extern UInt32 BZ2_crc32Table[256];
#define BZ_INITIALISE_CRC(crcVar) \
{ \
crcVar = 0xffffffffL; \
}
#define BZ_FINALISE_CRC(crcVar) \
{ \
crcVar = ~(crcVar); \
}
#define BZ_UPDATE_CRC(crcVar,cha) \
{ \
crcVar = (crcVar << 8) ^ \
BZ2_crc32Table[(crcVar >> 24) ^ \
((UChar)cha)]; \
}
/*-- States and modes for compression. --*/
#define BZ_M_IDLE 1
#define BZ_M_RUNNING 2
#define BZ_M_FLUSHING 3
#define BZ_M_FINISHING 4
#define BZ_S_OUTPUT 1
#define BZ_S_INPUT 2
#define BZ_N_RADIX 2
#define BZ_N_QSORT 12
#define BZ_N_SHELL 18
#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
/*-- Structure holding all the compression-side stuff. --*/
typedef
struct {
/* pointer back to the struct bz_stream */
bz_stream* strm;
/* mode this stream is in, and whether inputting */
/* or outputting data */
Int32 mode;
Int32 state;
/* remembers avail_in when flush/finish requested */
UInt32 avail_in_expect;
/* for doing the block sorting */
UInt32* arr1;
UInt32* arr2;
UInt32* ftab;
Int32 origPtr;
/* aliases for arr1 and arr2 */
UInt32* ptr;
UChar* block;
UInt16* mtfv;
UChar* zbits;
/* for deciding when to use the fallback sorting algorithm */
Int32 workFactor;
/* run-length-encoding of the input */
UInt32 state_in_ch;
Int32 state_in_len;
BZ_RAND_DECLS;
/* input and output limits and current posns */
Int32 nblock;
Int32 nblockMAX;
Int32 numZ;
Int32 state_out_pos;
/* map of bytes used in block */
Int32 nInUse;
Bool inUse[256];
UChar unseqToSeq[256];
/* the buffer for bit stream creation */
UInt32 bsBuff;
Int32 bsLive;
/* block and combined CRCs */
UInt32 blockCRC;
UInt32 combinedCRC;
/* misc administratium */
Int32 verbosity;
Int32 blockNo;
Int32 blockSize100k;
/* stuff for coding the MTF values */
Int32 nMTF;
Int32 mtfFreq [BZ_MAX_ALPHA_SIZE];
UChar selector [BZ_MAX_SELECTORS];
UChar selectorMtf[BZ_MAX_SELECTORS];
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
/* second dimension: only 3 needed; 4 makes index calculations faster */
UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
}
EState;
/*-- externs for compression. --*/
extern void
BZ2_blockSort ( EState* );
extern void
BZ2_compressBlock ( EState*, Bool );
extern void
BZ2_bsInitWrite ( EState* );
extern void
BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
extern void
BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
/*-- states for decompression. --*/
#define BZ_X_IDLE 1
#define BZ_X_OUTPUT 2
#define BZ_X_MAGIC_1 10
#define BZ_X_MAGIC_2 11
#define BZ_X_MAGIC_3 12
#define BZ_X_MAGIC_4 13
#define BZ_X_BLKHDR_1 14
#define BZ_X_BLKHDR_2 15
#define BZ_X_BLKHDR_3 16
#define BZ_X_BLKHDR_4 17
#define BZ_X_BLKHDR_5 18
#define BZ_X_BLKHDR_6 19
#define BZ_X_BCRC_1 20
#define BZ_X_BCRC_2 21
#define BZ_X_BCRC_3 22
#define BZ_X_BCRC_4 23
#define BZ_X_RANDBIT 24
#define BZ_X_ORIGPTR_1 25
#define BZ_X_ORIGPTR_2 26
#define BZ_X_ORIGPTR_3 27
#define BZ_X_MAPPING_1 28
#define BZ_X_MAPPING_2 29
#define BZ_X_SELECTOR_1 30
#define BZ_X_SELECTOR_2 31
#define BZ_X_SELECTOR_3 32
#define BZ_X_CODING_1 33
#define BZ_X_CODING_2 34
#define BZ_X_CODING_3 35
#define BZ_X_MTF_1 36
#define BZ_X_MTF_2 37
#define BZ_X_MTF_3 38
#define BZ_X_MTF_4 39
#define BZ_X_MTF_5 40
#define BZ_X_MTF_6 41
#define BZ_X_ENDHDR_2 42
#define BZ_X_ENDHDR_3 43
#define BZ_X_ENDHDR_4 44
#define BZ_X_ENDHDR_5 45
#define BZ_X_ENDHDR_6 46
#define BZ_X_CCRC_1 47
#define BZ_X_CCRC_2 48
#define BZ_X_CCRC_3 49
#define BZ_X_CCRC_4 50
/*-- Constants for the fast MTF decoder. --*/
#define MTFA_SIZE 4096
#define MTFL_SIZE 16
/*-- Structure holding all the decompression-side stuff. --*/
typedef
struct {
/* pointer back to the struct bz_stream */
bz_stream* strm;
/* state indicator for this stream */
Int32 state;
/* for doing the final run-length decoding */
UChar state_out_ch;
Int32 state_out_len;
Bool blockRandomised;
BZ_RAND_DECLS;
/* the buffer for bit stream reading */
UInt32 bsBuff;
Int32 bsLive;
/* misc administratium */
Int32 blockSize100k;
Bool smallDecompress;
Int32 currBlockNo;
Int32 verbosity;
/* for undoing the Burrows-Wheeler transform */
Int32 origPtr;
UInt32 tPos;
Int32 k0;
Int32 unzftab[256];
Int32 nblock_used;
Int32 cftab[257];
Int32 cftabCopy[257];
/* for undoing the Burrows-Wheeler transform (FAST) */
UInt32 *tt;
/* for undoing the Burrows-Wheeler transform (SMALL) */
UInt16 *ll16;
UChar *ll4;
/* stored and calculated CRCs */
UInt32 storedBlockCRC;
UInt32 storedCombinedCRC;
UInt32 calculatedBlockCRC;
UInt32 calculatedCombinedCRC;
/* map of bytes used in block */
Int32 nInUse;
Bool inUse[256];
Bool inUse16[16];
UChar seqToUnseq[256];
/* for decoding the MTF values */
UChar mtfa [MTFA_SIZE];
Int32 mtfbase[256 / MTFL_SIZE];
UChar selector [BZ_MAX_SELECTORS];
UChar selectorMtf[BZ_MAX_SELECTORS];
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 minLens[BZ_N_GROUPS];
/* save area for scalars in the main decompress code */
Int32 save_i;
Int32 save_j;
Int32 save_t;
Int32 save_alphaSize;
Int32 save_nGroups;
Int32 save_nSelectors;
Int32 save_EOB;
Int32 save_groupNo;
Int32 save_groupPos;
Int32 save_nextSym;
Int32 save_nblockMAX;
Int32 save_nblock;
Int32 save_es;
Int32 save_N;
Int32 save_curr;
Int32 save_zt;
Int32 save_zn;
Int32 save_zvec;
Int32 save_zj;
Int32 save_gSel;
Int32 save_gMinlen;
Int32* save_gLimit;
Int32* save_gBase;
Int32* save_gPerm;
}
DState;
/*-- Macros for decompression. --*/
#define BZ_GET_FAST(cccc) \
s->tPos = s->tt[s->tPos]; \
cccc = (UChar)(s->tPos & 0xff); \
s->tPos >>= 8;
#define BZ_GET_FAST_C(cccc) \
c_tPos = c_tt[c_tPos]; \
cccc = (UChar)(c_tPos & 0xff); \
c_tPos >>= 8;
#define SET_LL4(i,n) \
{ if (((i) & 0x1) == 0) \
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
}
#define GET_LL4(i) \
((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
#define SET_LL(i,n) \
{ s->ll16[i] = (UInt16)(n & 0x0000ffff); \
SET_LL4(i, n >> 16); \
}
#define GET_LL(i) \
(((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
#define BZ_GET_SMALL(cccc) \
cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
s->tPos = GET_LL(s->tPos);
/*-- externs for decompression. --*/
extern Int32
BZ2_indexIntoF ( Int32, Int32* );
extern Int32
BZ2_decompress ( DState* );
extern void
BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
Int32, Int32, Int32 );
#endif
/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
#ifdef BZ_NO_STDIO
#ifndef NULL
#define NULL 0
#endif
#endif
// turn off some compiler warnings - imported from tier0/platform.h
#ifdef _MSC_VER
#pragma warning(disable : 4127) // warning C4127: conditional expression is constant
#pragma warning(disable : 4702) // warning C4702: unreachable code
#pragma warning(disable : 4244) // type conversion warning.
#pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter
#pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
#endif
// We use this Valve func as an optimization:
extern int V_isspace(int c);
/*-------------------------------------------------------------*/
/*--- end bzlib_private.h ---*/
/*-------------------------------------------------------------*/

714
utils/bzip2/compress.c Normal file
View File

@@ -0,0 +1,714 @@
/*-------------------------------------------------------------*/
/*--- Compression machinery (not incl block sorting) ---*/
/*--- compress.c ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
/*--
CHANGES
~~~~~~~
0.9.0 -- original version.
0.9.0a/b -- no changes in this file.
0.9.0c
* changed setting of nGroups in sendMTFValues() so as to
do a bit better on small files
--*/
#include "bzlib_private.h"
/*---------------------------------------------------*/
/*--- Bit stream I/O ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
void BZ2_bsInitWrite ( EState* s )
{
s->bsLive = 0;
s->bsBuff = 0;
}
/*---------------------------------------------------*/
static
void bsFinishWrite ( EState* s )
{
while (s->bsLive > 0) {
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
s->numZ++;
s->bsBuff <<= 8;
s->bsLive -= 8;
}
}
/*---------------------------------------------------*/
#define bsNEEDW(nz) \
{ \
while (s->bsLive >= 8) { \
s->zbits[s->numZ] \
= (UChar)(s->bsBuff >> 24); \
s->numZ++; \
s->bsBuff <<= 8; \
s->bsLive -= 8; \
} \
}
/*---------------------------------------------------*/
static
__inline__
void bsW ( EState* s, Int32 n, UInt32 v )
{
bsNEEDW ( n );
s->bsBuff |= (v << (32 - s->bsLive - n));
s->bsLive += n;
}
/*---------------------------------------------------*/
static
void bsPutUInt32 ( EState* s, UInt32 u )
{
bsW ( s, 8, (u >> 24) & 0xffL );
bsW ( s, 8, (u >> 16) & 0xffL );
bsW ( s, 8, (u >> 8) & 0xffL );
bsW ( s, 8, u & 0xffL );
}
/*---------------------------------------------------*/
static
void bsPutUChar ( EState* s, UChar c )
{
bsW( s, 8, (UInt32)c );
}
/*---------------------------------------------------*/
/*--- The back end proper ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
static
void makeMaps_e ( EState* s )
{
Int32 i;
s->nInUse = 0;
for (i = 0; i < 256; i++)
if (s->inUse[i]) {
s->unseqToSeq[i] = s->nInUse;
s->nInUse++;
}
}
/*---------------------------------------------------*/
static
void generateMTFValues ( EState* s )
{
UChar yy[256];
Int32 i, j;
Int32 zPend;
Int32 wr;
Int32 EOB;
/*
After sorting (eg, here),
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
and
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
holds the original block data.
The first thing to do is generate the MTF values,
and put them in
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
Because there are strictly fewer or equal MTF values
than block values, ptr values in this area are overwritten
with MTF values only when they are no longer needed.
The final compressed bitstream is generated into the
area starting at
(UChar*) (&((UChar*)s->arr2)[s->nblock])
These storage aliases are set up in bzCompressInit(),
except for the last one, which is arranged in
compressBlock().
*/
UInt32* ptr = s->ptr;
UChar* block = s->block;
UInt16* mtfv = s->mtfv;
makeMaps_e ( s );
EOB = s->nInUse+1;
for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
wr = 0;
zPend = 0;
for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
for (i = 0; i < s->nblock; i++) {
UChar ll_i;
AssertD ( wr <= i, "generateMTFValues(1)" );
j = ptr[i]-1; if (j < 0) j += s->nblock;
ll_i = s->unseqToSeq[block[j]];
AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
if (yy[0] == ll_i) {
zPend++;
} else {
if (zPend > 0) {
zPend--;
while (True) {
if (zPend & 1) {
mtfv[wr] = BZ_RUNB; wr++;
s->mtfFreq[BZ_RUNB]++;
} else {
mtfv[wr] = BZ_RUNA; wr++;
s->mtfFreq[BZ_RUNA]++;
}
if (zPend < 2) break;
zPend = (zPend - 2) / 2;
};
zPend = 0;
}
{
register UChar rtmp;
register UChar* ryy_j;
register UChar rll_i;
rtmp = yy[1];
yy[1] = yy[0];
ryy_j = &(yy[1]);
rll_i = ll_i;
while ( rll_i != rtmp ) {
register UChar rtmp2;
ryy_j++;
rtmp2 = rtmp;
rtmp = *ryy_j;
*ryy_j = rtmp2;
};
yy[0] = rtmp;
j = ryy_j - &(yy[0]);
mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
}
}
}
if (zPend > 0) {
zPend--;
while (True) {
if (zPend & 1) {
mtfv[wr] = BZ_RUNB; wr++;
s->mtfFreq[BZ_RUNB]++;
} else {
mtfv[wr] = BZ_RUNA; wr++;
s->mtfFreq[BZ_RUNA]++;
}
if (zPend < 2) break;
zPend = (zPend - 2) / 2;
};
zPend = 0;
}
mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
s->nMTF = wr;
}
/*---------------------------------------------------*/
#define BZ_LESSER_ICOST 0
#define BZ_GREATER_ICOST 15
static
void sendMTFValues ( EState* s )
{
Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
Int32 nSelectors=0, alphaSize, minLen, maxLen, selCtr;
Int32 nGroups, nBytes;
/*--
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
is a global since the decoder also needs it.
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
are also globals only used in this proc.
Made global to keep stack frame size small.
--*/
UInt16 cost[BZ_N_GROUPS];
Int32 fave[BZ_N_GROUPS];
UInt16* mtfv = s->mtfv;
if (s->verbosity >= 3)
VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
"%d+2 syms in use\n",
s->nblock, s->nMTF, s->nInUse );
alphaSize = s->nInUse+2;
for (t = 0; t < BZ_N_GROUPS; t++)
for (v = 0; v < alphaSize; v++)
s->len[t][v] = BZ_GREATER_ICOST;
/*--- Decide how many coding tables to use ---*/
AssertH ( s->nMTF > 0, 3001 );
if (s->nMTF < 200) nGroups = 2; else
if (s->nMTF < 600) nGroups = 3; else
if (s->nMTF < 1200) nGroups = 4; else
if (s->nMTF < 2400) nGroups = 5; else
nGroups = 6;
/*--- Generate an initial set of coding tables ---*/
{
Int32 nPart, remF, tFreq, aFreq;
nPart = nGroups;
remF = s->nMTF;
gs = 0;
while (nPart > 0) {
tFreq = remF / nPart;
ge = gs-1;
aFreq = 0;
while (aFreq < tFreq && ge < alphaSize-1) {
ge++;
aFreq += s->mtfFreq[ge];
}
if (ge > gs
&& nPart != nGroups && nPart != 1
&& ((nGroups-nPart) % 2 == 1)) {
aFreq -= s->mtfFreq[ge];
ge--;
}
if (s->verbosity >= 3)
VPrintf5( " initial group %d, [%d .. %d], "
"has %d syms (%4.1f%%)\n",
nPart, gs, ge, aFreq,
(100.0 * (float)aFreq) / (float)(s->nMTF) );
for (v = 0; v < alphaSize; v++)
if (v >= gs && v <= ge)
s->len[nPart-1][v] = BZ_LESSER_ICOST; else
s->len[nPart-1][v] = BZ_GREATER_ICOST;
nPart--;
gs = ge+1;
remF -= aFreq;
}
}
/*---
Iterate up to BZ_N_ITERS times to improve the tables.
---*/
for (iter = 0; iter < BZ_N_ITERS; iter++) {
for (t = 0; t < nGroups; t++) fave[t] = 0;
for (t = 0; t < nGroups; t++)
for (v = 0; v < alphaSize; v++)
s->rfreq[t][v] = 0;
/*---
Set up an auxiliary length table which is used to fast-track
the common case (nGroups == 6).
---*/
if (nGroups == 6) {
for (v = 0; v < alphaSize; v++) {
s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
}
}
nSelectors = 0;
totc = 0;
gs = 0;
while (True) {
/*--- Set group start & end marks. --*/
if (gs >= s->nMTF) break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF) ge = s->nMTF-1;
/*--
Calculate the cost of this group as coded
by each of the coding tables.
--*/
for (t = 0; t < nGroups; t++) cost[t] = 0;
if (nGroups == 6 && 50 == ge-gs+1) {
/*--- fast track the common case ---*/
register UInt32 cost01, cost23, cost45;
register UInt16 icv;
cost01 = cost23 = cost45 = 0;
# define BZ_ITER(nn) \
icv = mtfv[gs+(nn)]; \
cost01 += s->len_pack[icv][0]; \
cost23 += s->len_pack[icv][1]; \
cost45 += s->len_pack[icv][2]; \
BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
# undef BZ_ITER
cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
} else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++) {
UInt16 icv = mtfv[i];
for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
}
}
/*--
Find the coding table which is best for this group,
and record its identity in the selector table.
--*/
bc = 999999999; bt = -1;
for (t = 0; t < nGroups; t++)
if (cost[t] < bc) { bc = cost[t]; bt = t; };
totc += bc;
fave[bt]++;
s->selector[nSelectors] = bt;
nSelectors++;
/*--
Increment the symbol frequencies for the selected table.
--*/
if (nGroups == 6 && 50 == ge-gs+1) {
/*--- fast track the common case ---*/
# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
# undef BZ_ITUR
} else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++)
s->rfreq[bt][ mtfv[i] ]++;
}
gs = ge+1;
}
if (s->verbosity >= 3) {
VPrintf2 ( " pass %d: size is %d, grp uses are ",
iter+1, totc/8 );
for (t = 0; t < nGroups; t++)
VPrintf1 ( "%d ", fave[t] );
VPrintf0 ( "\n" );
}
/*--
Recompute the tables based on the accumulated frequencies.
--*/
for (t = 0; t < nGroups; t++)
BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
alphaSize, 20 );
}
AssertH( nGroups < 8, 3002 );
AssertH( nSelectors < 32768 &&
nSelectors <= (2 + (900000 / BZ_G_SIZE)),
3003 );
/*--- Compute MTF values for the selectors. ---*/
{
UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
for (i = 0; i < nGroups; i++) pos[i] = i;
for (i = 0; i < nSelectors; i++) {
ll_i = s->selector[i];
j = 0;
tmp = pos[j];
while ( ll_i != tmp ) {
j++;
tmp2 = tmp;
tmp = pos[j];
pos[j] = tmp2;
};
pos[0] = tmp;
s->selectorMtf[i] = j;
}
};
/*--- Assign actual codes for the tables. --*/
for (t = 0; t < nGroups; t++) {
minLen = 32;
maxLen = 0;
for (i = 0; i < alphaSize; i++) {
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
if (s->len[t][i] < minLen) minLen = s->len[t][i];
}
AssertH ( !(maxLen > 20), 3004 );
AssertH ( !(minLen < 1), 3005 );
BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
minLen, maxLen, alphaSize );
}
/*--- Transmit the mapping table. ---*/
{
Bool inUse16[16];
for (i = 0; i < 16; i++) {
inUse16[i] = False;
for (j = 0; j < 16; j++)
if (s->inUse[i * 16 + j]) inUse16[i] = True;
}
nBytes = s->numZ;
for (i = 0; i < 16; i++)
if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
for (i = 0; i < 16; i++)
if (inUse16[i])
for (j = 0; j < 16; j++) {
if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
}
if (s->verbosity >= 3)
VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
}
/*--- Now the selectors. ---*/
nBytes = s->numZ;
bsW ( s, 3, nGroups );
bsW ( s, 15, nSelectors );
for (i = 0; i < nSelectors; i++) {
for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
bsW(s,1,0);
}
if (s->verbosity >= 3)
VPrintf1( "selectors %d, ", s->numZ-nBytes );
/*--- Now the coding tables. ---*/
nBytes = s->numZ;
for (t = 0; t < nGroups; t++) {
Int32 curr = s->len[t][0];
bsW ( s, 5, curr );
for (i = 0; i < alphaSize; i++) {
while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
bsW ( s, 1, 0 );
}
}
if (s->verbosity >= 3)
VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
/*--- And finally, the block data proper ---*/
nBytes = s->numZ;
selCtr = 0;
gs = 0;
while (True) {
if (gs >= s->nMTF) break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF) ge = s->nMTF-1;
AssertH ( s->selector[selCtr] < nGroups, 3006 );
if (nGroups == 6 && 50 == ge-gs+1) {
/*--- fast track the common case ---*/
UInt16 mtfv_i;
UChar* s_len_sel_selCtr
= &(s->len[s->selector[selCtr]][0]);
Int32* s_code_sel_selCtr
= &(s->code[s->selector[selCtr]][0]);
# define BZ_ITAH(nn) \
mtfv_i = mtfv[gs+(nn)]; \
bsW ( s, \
s_len_sel_selCtr[mtfv_i], \
s_code_sel_selCtr[mtfv_i] )
BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
# undef BZ_ITAH
} else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++) {
bsW ( s,
s->len [s->selector[selCtr]] [mtfv[i]],
s->code [s->selector[selCtr]] [mtfv[i]] );
}
}
gs = ge+1;
selCtr++;
}
AssertH( selCtr == nSelectors, 3007 );
if (s->verbosity >= 3)
VPrintf1( "codes %d\n", s->numZ-nBytes );
}
/*---------------------------------------------------*/
void BZ2_compressBlock ( EState* s, Bool is_last_block )
{
if (s->nblock > 0) {
BZ_FINALISE_CRC ( s->blockCRC );
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
s->combinedCRC ^= s->blockCRC;
if (s->blockNo > 1) s->numZ = 0;
if (s->verbosity >= 2)
VPrintf4( " block %d: crc = 0x%8x, "
"combined CRC = 0x%8x, size = %d\n",
s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
BZ2_blockSort ( s );
}
s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
/*-- If this is the first block, create the stream header. --*/
if (s->blockNo == 1) {
BZ2_bsInitWrite ( s );
bsPutUChar ( s, BZ_HDR_B );
bsPutUChar ( s, BZ_HDR_Z );
bsPutUChar ( s, BZ_HDR_h );
bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
}
if (s->nblock > 0) {
bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
/*-- Now the block's CRC, so it is in a known place. --*/
bsPutUInt32 ( s, s->blockCRC );
/*--
Now a single bit indicating (non-)randomisation.
As of version 0.9.5, we use a better sorting algorithm
which makes randomisation unnecessary. So always set
the randomised bit to 'no'. Of course, the decoder
still needs to be able to handle randomised blocks
so as to maintain backwards compatibility with
older versions of bzip2.
--*/
bsW(s,1,0);
bsW ( s, 24, s->origPtr );
generateMTFValues ( s );
sendMTFValues ( s );
}
/*-- If this is the last block, add the stream trailer. --*/
if (is_last_block) {
bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
bsPutUInt32 ( s, s->combinedCRC );
if (s->verbosity >= 2)
VPrintf1( " final combined CRC = 0x%x\n ", s->combinedCRC );
bsFinishWrite ( s );
}
}
/*-------------------------------------------------------------*/
/*--- end compress.c ---*/
/*-------------------------------------------------------------*/

144
utils/bzip2/crctable.c Normal file
View File

@@ -0,0 +1,144 @@
/*-------------------------------------------------------------*/
/*--- Table for doing CRCs ---*/
/*--- crctable.c ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
#include "bzlib_private.h"
/*--
I think this is an implementation of the AUTODIN-II,
Ethernet & FDDI 32-bit CRC standard. Vaguely derived
from code by Rob Warnock, in Section 51 of the
comp.compression FAQ.
--*/
UInt32 BZ2_crc32Table[256] = {
/*-- Ugly, innit? --*/
0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
};
/*-------------------------------------------------------------*/
/*--- end crctable.c ---*/
/*-------------------------------------------------------------*/

660
utils/bzip2/decompress.c Normal file
View File

@@ -0,0 +1,660 @@
/*-------------------------------------------------------------*/
/*--- Decompression machinery ---*/
/*--- decompress.c ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
#include "bzlib_private.h"
/*---------------------------------------------------*/
static
void makeMaps_d ( DState* s )
{
Int32 i;
s->nInUse = 0;
for (i = 0; i < 256; i++)
if (s->inUse[i]) {
s->seqToUnseq[s->nInUse] = i;
s->nInUse++;
}
}
/*---------------------------------------------------*/
#define RETURN(rrr) \
{ retVal = rrr; goto save_state_and_return; };
#define GET_BITS(lll,vvv,nnn) \
case lll: s->state = lll; \
while (True) { \
if (s->bsLive >= nnn) { \
UInt32 v; \
v = (s->bsBuff >> \
(s->bsLive-nnn)) & ((1 << nnn)-1); \
s->bsLive -= nnn; \
vvv = v; \
break; \
} \
if (s->strm->avail_in == 0) RETURN(BZ_OK); \
s->bsBuff \
= (s->bsBuff << 8) | \
((UInt32) \
(*((UChar*)(s->strm->next_in)))); \
s->bsLive += 8; \
s->strm->next_in++; \
s->strm->avail_in--; \
s->strm->total_in_lo32++; \
if (s->strm->total_in_lo32 == 0) \
s->strm->total_in_hi32++; \
}
#define GET_UCHAR(lll,uuu) \
GET_BITS(lll,uuu,8)
#define GET_BIT(lll,uuu) \
GET_BITS(lll,uuu,1)
/*---------------------------------------------------*/
#define GET_MTF_VAL(label1,label2,lval) \
{ \
if (groupPos == 0) { \
groupNo++; \
if (groupNo >= nSelectors) \
RETURN(BZ_DATA_ERROR); \
groupPos = BZ_G_SIZE; \
gSel = s->selector[groupNo]; \
gMinlen = s->minLens[gSel]; \
gLimit = &(s->limit[gSel][0]); \
gPerm = &(s->perm[gSel][0]); \
gBase = &(s->base[gSel][0]); \
} \
groupPos--; \
zn = gMinlen; \
GET_BITS(label1, zvec, zn); \
while (1) { \
if (zn > 20 /* the longest code */) \
RETURN(BZ_DATA_ERROR); \
if (zvec <= gLimit[zn]) break; \
zn++; \
GET_BIT(label2, zj); \
zvec = (zvec << 1) | zj; \
}; \
if (zvec - gBase[zn] < 0 \
|| zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
RETURN(BZ_DATA_ERROR); \
lval = gPerm[zvec - gBase[zn]]; \
}
/*---------------------------------------------------*/
Int32 BZ2_decompress ( DState* s )
{
UChar uc;
Int32 retVal;
Int32 minLen, maxLen;
bz_stream* strm = s->strm;
/* stuff that needs to be saved/restored */
Int32 i;
Int32 j;
Int32 t;
Int32 alphaSize;
Int32 nGroups;
Int32 nSelectors;
Int32 EOB;
Int32 groupNo;
Int32 groupPos;
Int32 nextSym;
Int32 nblockMAX;
Int32 nblock;
Int32 es;
Int32 N;
Int32 curr;
Int32 zt;
Int32 zn;
Int32 zvec;
Int32 zj;
Int32 gSel;
Int32 gMinlen;
Int32* gLimit;
Int32* gBase;
Int32* gPerm;
if (s->state == BZ_X_MAGIC_1) {
/*initialise the save area*/
s->save_i = 0;
s->save_j = 0;
s->save_t = 0;
s->save_alphaSize = 0;
s->save_nGroups = 0;
s->save_nSelectors = 0;
s->save_EOB = 0;
s->save_groupNo = 0;
s->save_groupPos = 0;
s->save_nextSym = 0;
s->save_nblockMAX = 0;
s->save_nblock = 0;
s->save_es = 0;
s->save_N = 0;
s->save_curr = 0;
s->save_zt = 0;
s->save_zn = 0;
s->save_zvec = 0;
s->save_zj = 0;
s->save_gSel = 0;
s->save_gMinlen = 0;
s->save_gLimit = NULL;
s->save_gBase = NULL;
s->save_gPerm = NULL;
}
/*restore from the save area*/
i = s->save_i;
j = s->save_j;
t = s->save_t;
alphaSize = s->save_alphaSize;
nGroups = s->save_nGroups;
nSelectors = s->save_nSelectors;
EOB = s->save_EOB;
groupNo = s->save_groupNo;
groupPos = s->save_groupPos;
nextSym = s->save_nextSym;
nblockMAX = s->save_nblockMAX;
nblock = s->save_nblock;
es = s->save_es;
N = s->save_N;
curr = s->save_curr;
zt = s->save_zt;
zn = s->save_zn;
zvec = s->save_zvec;
zj = s->save_zj;
gSel = s->save_gSel;
gMinlen = s->save_gMinlen;
gLimit = s->save_gLimit;
gBase = s->save_gBase;
gPerm = s->save_gPerm;
retVal = BZ_OK;
switch (s->state) {
GET_UCHAR(BZ_X_MAGIC_1, uc);
if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
GET_UCHAR(BZ_X_MAGIC_2, uc);
if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
GET_UCHAR(BZ_X_MAGIC_3, uc)
if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
if (s->blockSize100k < (BZ_HDR_0 + 1) ||
s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
s->blockSize100k -= BZ_HDR_0;
if (s->smallDecompress) {
s->ll16 = (UInt16 *)BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
s->ll4 = (UChar *)BZALLOC(
((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
);
if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
} else {
s->tt = (UInt32 *)BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
}
GET_UCHAR(BZ_X_BLKHDR_1, uc);
if (uc == 0x17) goto endhdr_2;
if (uc != 0x31) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_2, uc);
if (uc != 0x41) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_3, uc);
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_4, uc);
if (uc != 0x26) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_5, uc);
if (uc != 0x53) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_6, uc);
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
s->currBlockNo++;
if (s->verbosity >= 2)
VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
s->storedBlockCRC = 0;
GET_UCHAR(BZ_X_BCRC_1, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_BCRC_2, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_BCRC_3, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_BCRC_4, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
s->origPtr = 0;
GET_UCHAR(BZ_X_ORIGPTR_1, uc);
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
GET_UCHAR(BZ_X_ORIGPTR_2, uc);
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
GET_UCHAR(BZ_X_ORIGPTR_3, uc);
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
if (s->origPtr < 0)
RETURN(BZ_DATA_ERROR);
if (s->origPtr > 10 + 100000*s->blockSize100k)
RETURN(BZ_DATA_ERROR);
/*--- Receive the mapping table ---*/
for (i = 0; i < 16; i++) {
GET_BIT(BZ_X_MAPPING_1, uc);
if (uc == 1)
s->inUse16[i] = True; else
s->inUse16[i] = False;
}
for (i = 0; i < 256; i++) s->inUse[i] = False;
for (i = 0; i < 16; i++)
if (s->inUse16[i])
for (j = 0; j < 16; j++) {
GET_BIT(BZ_X_MAPPING_2, uc);
if (uc == 1) s->inUse[i * 16 + j] = True;
}
makeMaps_d ( s );
if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
alphaSize = s->nInUse+2;
/*--- Now the selectors ---*/
GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
for (i = 0; i < nSelectors; i++) {
j = 0;
while (True) {
GET_BIT(BZ_X_SELECTOR_3, uc);
if (uc == 0) break;
j++;
if (j >= nGroups) RETURN(BZ_DATA_ERROR);
}
s->selectorMtf[i] = j;
}
/*--- Undo the MTF values for the selectors. ---*/
{
UChar pos[BZ_N_GROUPS], tmp, v;
for (v = 0; v < nGroups; v++) pos[v] = v;
for (i = 0; i < nSelectors; i++) {
v = s->selectorMtf[i];
tmp = pos[v];
while (v > 0) { pos[v] = pos[v-1]; v--; }
pos[0] = tmp;
s->selector[i] = tmp;
}
}
/*--- Now the coding tables ---*/
for (t = 0; t < nGroups; t++) {
GET_BITS(BZ_X_CODING_1, curr, 5);
for (i = 0; i < alphaSize; i++) {
while (True) {
if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
GET_BIT(BZ_X_CODING_2, uc);
if (uc == 0) break;
GET_BIT(BZ_X_CODING_3, uc);
if (uc == 0) curr++; else curr--;
}
s->len[t][i] = curr;
}
}
/*--- Create the Huffman decoding tables ---*/
for (t = 0; t < nGroups; t++) {
minLen = 32;
maxLen = 0;
for (i = 0; i < alphaSize; i++) {
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
if (s->len[t][i] < minLen) minLen = s->len[t][i];
}
BZ2_hbCreateDecodeTables (
&(s->limit[t][0]),
&(s->base[t][0]),
&(s->perm[t][0]),
&(s->len[t][0]),
minLen, maxLen, alphaSize
);
s->minLens[t] = minLen;
}
/*--- Now the MTF values ---*/
EOB = s->nInUse+1;
nblockMAX = 100000 * s->blockSize100k;
groupNo = -1;
groupPos = 0;
for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
/*-- MTF init --*/
{
Int32 ii, jj, kk;
kk = MTFA_SIZE-1;
for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
kk--;
}
s->mtfbase[ii] = kk + 1;
}
}
/*-- end MTF init --*/
nblock = 0;
GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
while (True) {
if (nextSym == EOB) break;
if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
es = -1;
N = 1;
do {
if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
if (nextSym == BZ_RUNB) es = es + (1+1) * N;
N = N * 2;
GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
}
while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
es++;
uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
s->unzftab[uc] += es;
if (s->smallDecompress)
while (es > 0) {
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
s->ll16[nblock] = (UInt16)uc;
nblock++;
es--;
}
else
while (es > 0) {
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
s->tt[nblock] = (UInt32)uc;
nblock++;
es--;
};
continue;
} else {
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
/*-- uc = MTF ( nextSym-1 ) --*/
{
Int32 ii, jj, kk, pp, lno, off;
UInt32 nn;
nn = (UInt32)(nextSym - 1);
if (nn < MTFL_SIZE) {
/* avoid general-case expense */
pp = s->mtfbase[0];
uc = s->mtfa[pp+nn];
while (nn > 3) {
Int32 z = pp+nn;
s->mtfa[(z) ] = s->mtfa[(z)-1];
s->mtfa[(z)-1] = s->mtfa[(z)-2];
s->mtfa[(z)-2] = s->mtfa[(z)-3];
s->mtfa[(z)-3] = s->mtfa[(z)-4];
nn -= 4;
}
while (nn > 0) {
s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
};
s->mtfa[pp] = uc;
} else {
/* general case */
lno = nn / MTFL_SIZE;
off = nn % MTFL_SIZE;
pp = s->mtfbase[lno] + off;
uc = s->mtfa[pp];
while (pp > s->mtfbase[lno]) {
s->mtfa[pp] = s->mtfa[pp-1]; pp--;
};
s->mtfbase[lno]++;
while (lno > 0) {
s->mtfbase[lno]--;
s->mtfa[s->mtfbase[lno]]
= s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
lno--;
}
s->mtfbase[0]--;
s->mtfa[s->mtfbase[0]] = uc;
if (s->mtfbase[0] == 0) {
kk = MTFA_SIZE-1;
for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
kk--;
}
s->mtfbase[ii] = kk + 1;
}
}
}
}
/*-- end uc = MTF ( nextSym-1 ) --*/
s->unzftab[s->seqToUnseq[uc]]++;
if (s->smallDecompress)
s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
nblock++;
GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
continue;
}
}
/* Now we know what nblock is, we can do a better sanity
check on s->origPtr.
*/
if (s->origPtr < 0 || s->origPtr >= nblock)
RETURN(BZ_DATA_ERROR);
s->state_out_len = 0;
s->state_out_ch = 0;
BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
s->state = BZ_X_OUTPUT;
if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
/*-- Set up cftab to facilitate generation of T^(-1) --*/
s->cftab[0] = 0;
for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
if (s->smallDecompress) {
/*-- Make a copy of cftab, used in generation of T --*/
for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
/*-- compute the T vector --*/
for (i = 0; i < nblock; i++) {
uc = (UChar)(s->ll16[i]);
SET_LL(i, s->cftabCopy[uc]);
s->cftabCopy[uc]++;
}
/*-- Compute T^(-1) by pointer reversal on T --*/
i = s->origPtr;
j = GET_LL(i);
do {
Int32 tmp = GET_LL(j);
SET_LL(j, i);
i = j;
j = tmp;
}
while (i != s->origPtr);
s->tPos = s->origPtr;
s->nblock_used = 0;
if (s->blockRandomised) {
BZ_RAND_INIT_MASK;
BZ_GET_SMALL(s->k0); s->nblock_used++;
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
} else {
BZ_GET_SMALL(s->k0); s->nblock_used++;
}
} else {
/*-- compute the T^(-1) vector --*/
for (i = 0; i < nblock; i++) {
uc = (UChar)(s->tt[i] & 0xff);
s->tt[s->cftab[uc]] |= (i << 8);
s->cftab[uc]++;
}
s->tPos = s->tt[s->origPtr] >> 8;
s->nblock_used = 0;
if (s->blockRandomised) {
BZ_RAND_INIT_MASK;
BZ_GET_FAST(s->k0); s->nblock_used++;
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
} else {
BZ_GET_FAST(s->k0); s->nblock_used++;
}
}
RETURN(BZ_OK);
endhdr_2:
GET_UCHAR(BZ_X_ENDHDR_2, uc);
if (uc != 0x72) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_3, uc);
if (uc != 0x45) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_4, uc);
if (uc != 0x38) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_5, uc);
if (uc != 0x50) RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_6, uc);
if (uc != 0x90) RETURN(BZ_DATA_ERROR);
s->storedCombinedCRC = 0;
GET_UCHAR(BZ_X_CCRC_1, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_CCRC_2, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_CCRC_3, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_CCRC_4, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
s->state = BZ_X_IDLE;
RETURN(BZ_STREAM_END);
default: AssertH ( False, 4001 );
}
AssertH ( False, 4002 );
save_state_and_return:
s->save_i = i;
s->save_j = j;
s->save_t = t;
s->save_alphaSize = alphaSize;
s->save_nGroups = nGroups;
s->save_nSelectors = nSelectors;
s->save_EOB = EOB;
s->save_groupNo = groupNo;
s->save_groupPos = groupPos;
s->save_nextSym = nextSym;
s->save_nblockMAX = nblockMAX;
s->save_nblock = nblock;
s->save_es = es;
s->save_N = N;
s->save_curr = curr;
s->save_zt = zt;
s->save_zn = zn;
s->save_zvec = zvec;
s->save_zj = zj;
s->save_gSel = gSel;
s->save_gMinlen = gMinlen;
s->save_gLimit = gLimit;
s->save_gBase = gBase;
s->save_gPerm = gPerm;
return retVal;
}
/*-------------------------------------------------------------*/
/*--- end decompress.c ---*/
/*-------------------------------------------------------------*/

228
utils/bzip2/huffman.c Normal file
View File

@@ -0,0 +1,228 @@
/*-------------------------------------------------------------*/
/*--- Huffman coding low-level stuff ---*/
/*--- huffman.c ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
#include "bzlib_private.h"
/*---------------------------------------------------*/
#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
#define ADDWEIGHTS(zw1,zw2) \
(WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
(1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
#define UPHEAP(z) \
{ \
Int32 zz, tmp; \
zz = z; tmp = heap[zz]; \
while (weight[tmp] < weight[heap[zz >> 1]]) { \
heap[zz] = heap[zz >> 1]; \
zz >>= 1; \
} \
heap[zz] = tmp; \
}
#define DOWNHEAP(z) \
{ \
Int32 zz, yy, tmp; \
zz = z; tmp = heap[zz]; \
while (True) { \
yy = zz << 1; \
if (yy > nHeap) break; \
if (yy < nHeap && \
weight[heap[yy+1]] < weight[heap[yy]]) \
yy++; \
if (weight[tmp] < weight[heap[yy]]) break; \
heap[zz] = heap[yy]; \
zz = yy; \
} \
heap[zz] = tmp; \
}
/*---------------------------------------------------*/
void BZ2_hbMakeCodeLengths ( UChar *len,
Int32 *freq,
Int32 alphaSize,
Int32 maxLen )
{
/*--
Nodes and heap entries run from 1. Entry 0
for both the heap and nodes is a sentinel.
--*/
Int32 nNodes, nHeap, n1, n2, i, j, k;
Bool tooLong;
Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ];
Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ];
for (i = 0; i < alphaSize; i++)
weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
while (True) {
nNodes = alphaSize;
nHeap = 0;
heap[0] = 0;
weight[0] = 0;
parent[0] = -2;
for (i = 1; i <= alphaSize; i++) {
parent[i] = -1;
nHeap++;
heap[nHeap] = i;
UPHEAP(nHeap);
}
AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
while (nHeap > 1) {
n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
nNodes++;
parent[n1] = parent[n2] = nNodes;
weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
parent[nNodes] = -1;
nHeap++;
heap[nHeap] = nNodes;
UPHEAP(nHeap);
}
AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
tooLong = False;
for (i = 1; i <= alphaSize; i++) {
j = 0;
k = i;
while (parent[k] >= 0) { k = parent[k]; j++; }
len[i-1] = j;
if (j > maxLen) tooLong = True;
}
if (! tooLong) break;
for (i = 1; i < alphaSize; i++) {
j = weight[i] >> 8;
j = 1 + (j / 2);
weight[i] = j << 8;
}
}
}
/*---------------------------------------------------*/
void BZ2_hbAssignCodes ( Int32 *code,
UChar *length,
Int32 minLen,
Int32 maxLen,
Int32 alphaSize )
{
Int32 n, vec, i;
vec = 0;
for (n = minLen; n <= maxLen; n++) {
for (i = 0; i < alphaSize; i++)
if (length[i] == n) { code[i] = vec; vec++; };
vec <<= 1;
}
}
/*---------------------------------------------------*/
void BZ2_hbCreateDecodeTables ( Int32 *limit,
Int32 *base,
Int32 *perm,
UChar *length,
Int32 minLen,
Int32 maxLen,
Int32 alphaSize )
{
Int32 pp, i, j, vec;
pp = 0;
for (i = minLen; i <= maxLen; i++)
for (j = 0; j < alphaSize; j++)
if (length[j] == i) { perm[pp] = j; pp++; };
for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
vec = 0;
for (i = minLen; i <= maxLen; i++) {
vec += (base[i+1] - base[i]);
limit[i] = vec-1;
vec <<= 1;
}
for (i = minLen + 1; i <= maxLen; i++)
base[i] = ((limit[i-1] + 1) << 1) - base[i];
}
/*-------------------------------------------------------------*/
/*--- end huffman.c ---*/
/*-------------------------------------------------------------*/

124
utils/bzip2/randtable.c Normal file
View File

@@ -0,0 +1,124 @@
/*-------------------------------------------------------------*/
/*--- Table for randomising repetitive blocks ---*/
/*--- randtable.c ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
#include "bzlib_private.h"
/*---------------------------------------------*/
Int32 BZ2_rNums[512] = {
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
936, 638
};
/*-------------------------------------------------------------*/
/*--- end randtable.c ---*/
/*-------------------------------------------------------------*/

2
utils/bzip2/vsi.nul Normal file
View File

@@ -0,0 +1,2 @@
SN Visual Studio Integration
IMPORTANT: Do not remove the custom build step for this file

BIN
utils/common.zip Normal file

Binary file not shown.

View File

@@ -0,0 +1,29 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ISQLDLREPLYTARGET_H
#define ISQLDLREPLYTARGET_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Interface to handle results of SQL queries
//-----------------------------------------------------------------------------
class ISQLDBReplyTarget
{
public:
// handles a response from the database
virtual void SQLDBResponse(int cmdID, int returnState, int returnVal, void *data) = 0;
// called from a seperate thread; tells the reply target that a message is waiting for it
virtual void WakeUp() = 0;
};
#endif // ISQLDLREPLYTARGET_H

View File

@@ -0,0 +1,192 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "MySqlDatabase.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CMySqlDatabase::CMySqlDatabase()
{
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
// blocks until db process thread has stopped
//-----------------------------------------------------------------------------
CMySqlDatabase::~CMySqlDatabase()
{
// flag the thread to stop
m_bRunThread = false;
// pulse the thread to make it run
::SetEvent(m_hEvent);
// make sure it's done
::EnterCriticalSection(&m_csThread);
::LeaveCriticalSection(&m_csThread);
}
//-----------------------------------------------------------------------------
// Purpose: Thread access function
//-----------------------------------------------------------------------------
static DWORD WINAPI staticThreadFunc(void *param)
{
((CMySqlDatabase *)param)->RunThread();
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Establishes connection to the database and sets up this object to handle db command
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CMySqlDatabase::Initialize()
{
// prepare critical sections
//!! need to download SDK and replace these with InitializeCriticalSectionAndSpinCount() calls
::InitializeCriticalSection(&m_csThread);
::InitializeCriticalSection(&m_csInQueue);
::InitializeCriticalSection(&m_csOutQueue);
::InitializeCriticalSection(&m_csDBAccess);
// initialize wait calls
m_hEvent = ::CreateEvent(NULL, false, true, NULL);
// start the DB-access thread
m_bRunThread = true;
unsigned long threadID;
::CreateThread(NULL, 0, staticThreadFunc, this, 0, &threadID);
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Main thread loop
//-----------------------------------------------------------------------------
void CMySqlDatabase::RunThread()
{
::EnterCriticalSection(&m_csThread);
while (m_bRunThread)
{
if (m_InQueue.Count() > 0)
{
// get a dispatched DB request
::EnterCriticalSection(&m_csInQueue);
// pop the front of the queue
int headIndex = m_InQueue.Head();
msg_t msg = m_InQueue[headIndex];
m_InQueue.Remove(headIndex);
::LeaveCriticalSection(&m_csInQueue);
::EnterCriticalSection(&m_csDBAccess);
// run sqldb command
msg.result = msg.cmd->RunCommand();
::LeaveCriticalSection(&m_csDBAccess);
if (msg.replyTarget)
{
// put the results in the outgoing queue
::EnterCriticalSection(&m_csOutQueue);
m_OutQueue.AddToTail(msg);
::LeaveCriticalSection(&m_csOutQueue);
// wake up out queue
msg.replyTarget->WakeUp();
}
else
{
// there is no return data from the call, so kill the object now
msg.cmd->deleteThis();
}
}
else
{
// nothing in incoming queue, so wait until we get the signal
::WaitForSingleObject(m_hEvent, INFINITE);
}
// check the size of the outqueue; if it's getting too big, sleep to let the main thread catch up
if (m_OutQueue.Count() > 50)
{
::Sleep(2);
}
}
::LeaveCriticalSection(&m_csThread);
}
//-----------------------------------------------------------------------------
// Purpose: Adds a database command to the queue, and wakes the db thread
//-----------------------------------------------------------------------------
void CMySqlDatabase::AddCommandToQueue(ISQLDBCommand *cmd, ISQLDBReplyTarget *replyTarget, int returnState)
{
::EnterCriticalSection(&m_csInQueue);
// add to the queue
msg_t msg = { cmd, replyTarget, 0, returnState };
m_InQueue.AddToTail(msg);
::LeaveCriticalSection(&m_csInQueue);
// signal the thread to start running
::SetEvent(m_hEvent);
}
//-----------------------------------------------------------------------------
// Purpose: Dispatches responses to SQLDB queries
//-----------------------------------------------------------------------------
bool CMySqlDatabase::RunFrame()
{
bool doneWork = false;
while (m_OutQueue.Count() > 0)
{
::EnterCriticalSection(&m_csOutQueue);
// pop the first item in the queue
int headIndex = m_OutQueue.Head();
msg_t msg = m_OutQueue[headIndex];
m_OutQueue.Remove(headIndex);
::LeaveCriticalSection(&m_csOutQueue);
// run result
if (msg.replyTarget)
{
msg.replyTarget->SQLDBResponse(msg.cmd->GetID(), msg.returnState, msg.result, msg.cmd->GetReturnData());
// kill command
// it would be a good optimization to be able to reuse these
msg.cmd->deleteThis();
}
doneWork = true;
}
return doneWork;
}
//-----------------------------------------------------------------------------
// Purpose: load info - returns the number of sql db queries waiting to be processed
//-----------------------------------------------------------------------------
int CMySqlDatabase::QueriesInOutQueue()
{
// the queue names are from the DB point of view, not the server - thus the reversal
return m_InQueue.Count();
}
//-----------------------------------------------------------------------------
// Purpose: number of queries finished processing, waiting to be responded to
//-----------------------------------------------------------------------------
int CMySqlDatabase::QueriesInFinishedQueue()
{
return m_OutQueue.Count();
}

View File

@@ -0,0 +1,104 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef MYSQLDATABASE_H
#define MYSQLDATABASE_H
#ifdef _WIN32
#pragma once
#endif
#include <windows.h>
#include "ISQLDBReplyTarget.h"
#include "UtlVector.h"
#include "UtlLinkedList.h"
class ISQLDBCommand;
//-----------------------------------------------------------------------------
// Purpose: Generic MySQL accessing database
// Provides threaded I/O queue functionality for accessing a mysql db
//-----------------------------------------------------------------------------
class CMySqlDatabase
{
public:
// constructor
CMySqlDatabase();
~CMySqlDatabase();
// initialization - must be called before this object can be used
bool Initialize();
// Dispatches responses to SQLDB queries
bool RunFrame();
// load info - returns the number of sql db queries waiting to be processed
virtual int QueriesInOutQueue();
// number of queries finished processing, waiting to be responded to
virtual int QueriesInFinishedQueue();
// activates the thread
void RunThread();
// command queues
void AddCommandToQueue(ISQLDBCommand *cmd, ISQLDBReplyTarget *replyTarget, int returnState = 0);
private:
// threading data
bool m_bRunThread;
CRITICAL_SECTION m_csThread;
CRITICAL_SECTION m_csInQueue;
CRITICAL_SECTION m_csOutQueue;
CRITICAL_SECTION m_csDBAccess;
// wait event
HANDLE m_hEvent;
struct msg_t
{
ISQLDBCommand *cmd;
ISQLDBReplyTarget *replyTarget;
int result;
int returnState;
};
// command queues
CUtlLinkedList<msg_t, int> m_InQueue;
CUtlLinkedList<msg_t, int> m_OutQueue;
};
class Connection;
//-----------------------------------------------------------------------------
// Purpose: Interface to a command
//-----------------------------------------------------------------------------
class ISQLDBCommand
{
public:
// makes the command run (blocking), returning the success code
virtual int RunCommand() = 0;
// return data
virtual void *GetReturnData() { return NULL; }
// returns the command ID
virtual int GetID() { return 0; }
// gets information about the command for if it failed
virtual void GetDebugInfo(char *buf, int bufSize) { buf[0] = 0; }
// use to delete
virtual void deleteThis() = 0;
protected:
// protected destructor, so that it has to be deleted through deleteThis()
virtual ~ISQLDBCommand() {}
};
#endif // MYSQLDATABASE_H

6089
utils/common/bsplib.cpp Normal file

File diff suppressed because it is too large Load Diff

410
utils/common/bsplib.h Normal file
View File

@@ -0,0 +1,410 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef BSPLIB_H
#define BSPLIB_H
#ifdef _WIN32
#pragma once
#endif
#include "bspfile.h"
#include "utlvector.h"
#include "utlstring.h"
#include "utllinkedlist.h"
#include "byteswap.h"
#include "mathlib/vector4d.h"
#ifdef ENGINE_DLL
#include "zone.h"
#endif
#ifdef ENGINE_DLL
typedef CUtlVector<unsigned char, CHunkMemory<unsigned char> > CDispLightmapSamplePositions;
#else
typedef CUtlVector<unsigned char> CDispLightmapSamplePositions;
#endif
class ISpatialQuery;
struct Ray_t;
class Vector2D;
struct portal_t;
class CUtlBuffer;
class IZip;
// this is only true in vrad
extern bool g_bHDR;
// default width/height of luxels in world units.
#define DEFAULT_LUXEL_SIZE ( 16.0f )
#define SINGLE_BRUSH_MAP (MAX_BRUSH_LIGHTMAP_DIM_INCLUDING_BORDER*MAX_BRUSH_LIGHTMAP_DIM_INCLUDING_BORDER)
#define SINGLEMAP (MAX_LIGHTMAP_DIM_INCLUDING_BORDER*MAX_LIGHTMAP_DIM_INCLUDING_BORDER)
struct entity_t
{
Vector origin;
int firstbrush;
int numbrushes;
epair_t *epairs;
// only valid for func_areaportals
int areaportalnum;
int portalareas[2];
portal_t *m_pPortalsLeadingIntoAreas[2]; // portals leading into portalareas
};
extern int num_entities;
extern entity_t entities[MAX_MAP_ENTITIES];
extern int nummodels;
extern dmodel_t dmodels[MAX_MAP_MODELS];
extern int visdatasize;
extern byte dvisdata[MAX_MAP_VISIBILITY];
extern dvis_t *dvis;
extern CUtlVector<byte> dlightdataHDR;
extern CUtlVector<byte> dlightdataLDR;
extern CUtlVector<byte> *pdlightdata;
extern CUtlVector<char> dentdata;
extern int numleafs;
#if !defined( _X360 )
extern dleaf_t dleafs[MAX_MAP_LEAFS];
#else
extern dleaf_t *dleafs;
#endif
extern CUtlVector<dleafambientlighting_t> *g_pLeafAmbientLighting;
extern CUtlVector<dleafambientindex_t> *g_pLeafAmbientIndex;
extern unsigned short g_LeafMinDistToWater[MAX_MAP_LEAFS];
extern int numplanes;
extern dplane_t dplanes[MAX_MAP_PLANES];
extern int numvertexes;
extern dvertex_t dvertexes[MAX_MAP_VERTS];
extern int g_numvertnormalindices; // dfaces reference these. These index g_vertnormals.
extern unsigned short g_vertnormalindices[MAX_MAP_VERTNORMALS];
extern int g_numvertnormals;
extern Vector g_vertnormals[MAX_MAP_VERTNORMALS];
extern int numnodes;
extern dnode_t dnodes[MAX_MAP_NODES];
extern CUtlVector<texinfo_t> texinfo;
extern int numtexdata;
extern dtexdata_t dtexdata[MAX_MAP_TEXDATA];
// displacement map .bsp file info
extern CUtlVector<ddispinfo_t> g_dispinfo;
extern CUtlVector<CDispVert> g_DispVerts;
extern CUtlVector<CDispTri> g_DispTris;
extern CUtlVector<CDispMultiBlend> g_DispMultiBlend;
extern CDispLightmapSamplePositions g_DispLightmapSamplePositions; // LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS
extern int numorigfaces;
extern dface_t dorigfaces[MAX_MAP_FACES];
extern int g_numprimitives;
extern dprimitive_t g_primitives[MAX_MAP_PRIMITIVES];
extern int g_numprimverts;
extern dprimvert_t g_primverts[MAX_MAP_PRIMVERTS];
extern int g_numprimindices;
extern unsigned short g_primindices[MAX_MAP_PRIMINDICES];
extern int numfaces;
extern dface_t dfaces[MAX_MAP_FACES];
extern int numfaceids;
extern CUtlVector<dfaceid_t> dfaceids;
extern CUtlVector<uint16> dfacebrushes;
extern CUtlVector<dfacebrushlist_t> dfacebrushlists;
extern int numfaces_hdr;
extern dface_t dfaces_hdr[MAX_MAP_FACES];
extern int numedges;
extern dedge_t dedges[MAX_MAP_EDGES];
extern int numleaffaces;
extern unsigned short dleaffaces[MAX_MAP_LEAFFACES];
extern int numleafbrushes;
extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
extern int numsurfedges;
extern int dsurfedges[MAX_MAP_SURFEDGES];
extern int numareas;
extern darea_t dareas[MAX_MAP_AREAS];
extern int numareaportals;
extern dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
extern int numbrushes;
extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
extern int numbrushsides;
extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
extern int *pNumworldlights;
extern dworldlight_t *dworldlights;
extern Vector g_ClipPortalVerts[MAX_MAP_PORTALVERTS];
extern int g_nClipPortalVerts;
extern dcubemapsample_t g_CubemapSamples[MAX_MAP_CUBEMAPSAMPLES];
extern int g_nCubemapSamples;
extern int g_nOverlayCount;
extern doverlay_t g_Overlays[MAX_MAP_OVERLAYS];
extern doverlayfade_t g_OverlayFades[MAX_MAP_OVERLAYS]; // Parallel array of fade info in a separate lump to avoid breaking backwards compat
extern doverlaysystemlevel_t g_OverlaySystemLevels[MAX_MAP_OVERLAYS]; // Parallel array of system level info in a separate lump to avoid breaking backwards compat
extern int g_nWaterOverlayCount;
extern dwateroverlay_t g_WaterOverlays[MAX_MAP_WATEROVERLAYS];
extern CUtlVector<char> g_TexDataStringData;
extern CUtlVector<int> g_TexDataStringTable;
extern int numleafwaterdata;
extern dleafwaterdata_t dleafwaterdata[MAX_MAP_LEAFWATERDATA];
extern CUtlVector<CFaceMacroTextureInfo> g_FaceMacroTextureInfos;
extern CUtlVector<doccluderdata_t> g_OccluderData;
extern CUtlVector<doccluderpolydata_t> g_OccluderPolyData;
extern CUtlVector<int> g_OccluderVertexIndices;
// level flags - see LVLFLAGS_xxx in bspfile.h
extern uint32 g_LevelFlags;
// physics collision data
extern byte *g_pPhysCollide;
extern int g_PhysCollideSize;
extern byte *g_pPhysDisp;
extern int g_PhysDispSize;
// Embedded pack/pak file
IZip *GetPakFile( void );
IZip *GetSwapPakFile( void );
void ClearPakFile( IZip *pak );
void AddFileToPak( IZip *pak, const char *pRelativeName, const char *fullpath );
void AddBufferToPak( IZip *pak, const char *pRelativeName, void *data, int length, bool bTextMode );
bool FileExistsInPak( IZip *pak, const char *pRelativeName );
bool ReadFileFromPak( IZip *pak, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf );
void RemoveFileFromPak( IZip *pak, const char *pRelativeName );
int GetNextFilename( IZip *pak, int id, char *pBuffer, int bufferSize, int &fileSize );
void ForceAlignment( IZip *pak, bool bAlign, bool bCompatibleFormat, unsigned int alignmentSize );
typedef bool (*CompressFunc_t)( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer );
typedef bool (*VTFConvertFunc_t)( const char *pDebugName, CUtlBuffer &sourceBuf, CUtlBuffer &targetBuf, CompressFunc_t pCompressFunc, int nMaxMip );
typedef bool (*VHVFixupFunc_t)( const char *pVhvFilename, const char *pModelName, CUtlBuffer &sourceBuf, CUtlBuffer &targetBuf );
typedef bool (*StudioConvertFunc_t)( const char *pDebugName, CUtlBuffer &sourceBuf, CUtlBuffer &targetBuf /*, CompressFunc_t pCompressFunc */ );
//-----------------------------------------------------------------------------
// Game lump memory storage
//-----------------------------------------------------------------------------
// NOTE: This is not optimal at all; since I expect client lumps to
// not be accessed all that often.
struct GameLump_t
{
GameLumpId_t m_Id;
unsigned short m_Flags;
unsigned short m_Version;
CUtlMemory< unsigned char > m_Memory;
};
//-----------------------------------------------------------------------------
// Handle to a game lump
//-----------------------------------------------------------------------------
typedef unsigned short GameLumpHandle_t;
class CGameLump
{
public:
//-----------------------------------------------------------------------------
// Convert four-CC code to a handle + back
//-----------------------------------------------------------------------------
GameLumpHandle_t GetGameLumpHandle( GameLumpId_t id );
GameLumpId_t GetGameLumpId( GameLumpHandle_t handle );
int GetGameLumpFlags( GameLumpHandle_t handle );
int GetGameLumpVersion( GameLumpHandle_t handle );
void ComputeGameLumpSizeAndCount( int& size, int& clumpCount );
void ParseGameLump( BSPHeader_t *pHeader );
void SwapGameLump( GameLumpId_t id, int version, byte *dest, byte *src, int size );
//-----------------------------------------------------------------------------
// Game lump accessor methods
//-----------------------------------------------------------------------------
void* GetGameLump( GameLumpHandle_t handle );
int GameLumpSize( GameLumpHandle_t handle );
//-----------------------------------------------------------------------------
// Game lump iteration methods
//-----------------------------------------------------------------------------
GameLumpHandle_t FirstGameLump();
GameLumpHandle_t NextGameLump( GameLumpHandle_t handle );
GameLumpHandle_t InvalidGameLump();
//-----------------------------------------------------------------------------
// Game lump creation/destruction method
//-----------------------------------------------------------------------------
GameLumpHandle_t CreateGameLump( GameLumpId_t id, int size, int flags, int version );
void DestroyGameLump( GameLumpHandle_t handle );
void DestroyAllGameLumps();
private:
CUtlLinkedList< GameLump_t, GameLumpHandle_t > m_GameLumps;
};
extern CGameLump g_GameLumps;
extern CByteswap g_Swap;
//-----------------------------------------------------------------------------
// Helper for the bspzip tool
//-----------------------------------------------------------------------------
void ExtractZipFileFromBSP( char *pBSPFileName, char *pZipFileName );
//-----------------------------------------------------------------------------
// String table methods
//-----------------------------------------------------------------------------
const char * TexDataStringTable_GetString( int stringID );
int TexDataStringTable_AddOrFindString( const char *pString );
void DecompressVis (byte *in, byte *decompressed);
int CompressVis (byte *vis, byte *dest);
void OpenBSPFile( const char *filename );
void CloseBSPFile(void);
void LoadBSPFile( const char *filename );
void LoadBSPFile_FileSystemOnly( const char *filename );
void LoadBSPFileTexinfo( const char *filename );
void WriteBSPFile( const char *filename, char *pUnused = NULL );
void PrintBSPFileSizes(void);
void PrintBSPPackDirectory(void);
void ReleasePakFileLumps(void);
bool SwapBSPFile( const char *filename, const char *swapFilename, bool bSwapOnLoad, VTFConvertFunc_t pVTFConvertFunc, VHVFixupFunc_t pVHVFixupFunc, StudioConvertFunc_t pStudioConvertFunc, CompressFunc_t pCompressFunc, char const *szPlatform );
bool GetPakFileLump( const char *pBSPFilename, void **pPakData, int *pPakSize );
bool SetPakFileLump( const char *pBSPFilename, const char *pNewFilename, void *pPakData, int pakSize );
void WriteLumpToFile( char *filename, int lump );
bool GetBSPDependants( const char *pBSPFilename, CUtlVector< CUtlString > *pList );
void UnloadBSPFile();
void ParseEntities (void);
void UnparseEntities (void);
void PrintEntity (entity_t *ent);
epair_t *SetKeyValue ( entity_t *ent, const char *key, const char *value, bool bAllowDuplicates = false );
void RemoveKey( entity_t *pMapEnt, const char *pKey );
char *ValueForKey (entity_t *ent, const char *key);
// will return "" if not present
int IntForKey (entity_t *ent, const char *key);
vec_t FloatForKey (entity_t *ent, const char *key);
vec_t FloatForKeyWithDefault (entity_t *ent, const char *key, float default_value);
void GetVectorForKey (entity_t *ent, const char *key, Vector& vec);
void GetVector2DForKey (entity_t *ent, const char *key, Vector2D& vec);
void GetAnglesForKey (entity_t *ent, const char *key, QAngle& vec);
epair_t *ParseEpair (void);
// Build a list of the face's vertices (index into dvertexes).
// points must be able to hold pFace->numedges indices.
void BuildFaceCalcWindingData( dface_t *pFace, int *points );
// Convert a tristrip to a trilist.
// Removes degenerates.
// Fills in pTriListIndices and pnTriListIndices.
// You must free pTriListIndices with delete[].
void TriStripToTriList(
unsigned short const *pTriStripIndices,
int nTriStripIndices,
unsigned short **pTriListIndices,
int *pnTriListIndices );
// Calculates the lightmap coordinates at a given set of positions given the
// lightmap basis information.
void CalcTextureCoordsAtPoints(
float const texelsPerWorldUnits[2][4],
int const subtractOffset[2],
Vector const *pPoints,
int const nPoints,
Vector2D *pCoords );
// Figure out lightmap extents on all (lit) faces.
void UpdateAllFaceLightmapExtents();
//-----------------------------------------------------------------------------
// Gets at an interface for the tree for enumeration of leaves in volumes.
//-----------------------------------------------------------------------------
ISpatialQuery* ToolBSPTree();
class IBSPNodeEnumerator
{
public:
// call back with a node and a context
virtual bool EnumerateNode( int node, Ray_t const& ray, float f, intp context ) = 0;
// call back with a leaf and a context
virtual bool EnumerateLeaf( int leaf, Ray_t const& ray, float start, float end, intp context ) = 0;
};
//-----------------------------------------------------------------------------
// Enumerates nodes + leafs in front to back order...
//-----------------------------------------------------------------------------
bool EnumerateNodesAlongRay( Ray_t const& ray, IBSPNodeEnumerator* pEnum, intp context );
//-----------------------------------------------------------------------------
// Helps us find all leaves associated with a particular cluster
//-----------------------------------------------------------------------------
struct clusterlist_t
{
int leafCount;
CUtlVector<int> leafs;
};
extern CUtlVector<clusterlist_t> g_ClusterLeaves;
// Call this to build the mapping from cluster to leaves
void BuildClusterTable( );
void GetPlatformMapPath( const char *pMapPath, char *pPlatformMapPath, int dxlevel, int maxLength );
void SetHDRMode( bool bHDR );
// ----------------------------------------------------------------------------- //
// Helper accessors for the various structures.
// ----------------------------------------------------------------------------- //
inline ColorRGBExp32* dface_AvgLightColor( dface_t *pFace, int nLightStyleIndex )
{
return (ColorRGBExp32*)&(*pdlightdata)[pFace->lightofs - (nLightStyleIndex+1) * 4];
}
inline const char* TexInfo_TexName( int iTexInfo )
{
return TexDataStringTable_GetString( dtexdata[texinfo[iTexInfo].texdata].nameStringTableID );
}
#endif // BSPLIB_H

1062
utils/common/cmdlib.cpp Normal file

File diff suppressed because it is too large Load Diff

189
utils/common/cmdlib.h Normal file
View File

@@ -0,0 +1,189 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef CMDLIB_H
#define CMDLIB_H
#ifdef _WIN32
#pragma once
#endif
// cmdlib.h
#include "basetypes.h"
// This can go away when everything is in bin.
#if defined( CMDLIB_NODBGLIB )
void Error( char const *pMsg, ... );
#else
#include "tier0/dbg.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <stdarg.h>
#include "filesystem.h"
#include "filesystem_tools.h"
// Tools should use this as the read path ID. It'll look into the paths specified by gameinfo.txt
#define TOOLS_READ_PATH_ID "GAME"
// Tools should use this to fprintf data to files.
void CmdLib_FPrintf( FileHandle_t hFile, const char *pFormat, ... );
char* CmdLib_FGets( char *pOut, int outSize, FileHandle_t hFile );
// This can be set so Msg() sends output to hook functions (like the VMPI MySQL database),
// but doesn't actually printf the output.
extern bool g_bSuppressPrintfOutput;
extern IBaseFileSystem *g_pFileSystem;
// These call right into the functions in filesystem_tools.h
void CmdLib_InitFileSystem( const char *pFilename, int maxMemoryUsage = 0 );
void CmdLib_TermFileSystem(); // GracefulExit calls this.
CreateInterfaceFn CmdLib_GetFileSystemFactory();
#ifdef _WIN32
#pragma warning(disable : 4244) // MIPS
#pragma warning(disable : 4136) // X86
#pragma warning(disable : 4051) // ALPHA
#pragma warning(disable : 4018) // signed/unsigned mismatch
#pragma warning(disable : 4305) // truncate from double to float
#pragma warning(disable : 4389) // singned/unsigned mismatch in ==
#pragma warning(disable: 4512) // assignment operator could not be generated
#endif
// the dec offsetof macro doesnt work very well...
#define myoffsetof(type,identifier) offsetof( type, identifier )
// set these before calling CheckParm
extern int myargc;
extern char **myargv;
int Q_filelength (FileHandle_t f);
int FileTime (char *path);
void Q_mkdir( char *path );
char *ExpandArg (char *path); // expand relative to CWD
char *ExpandPath (char *path); // expand relative to gamedir
char *ExpandPathAndArchive (char *path);
// Fills in pOut with "X hours, Y minutes, Z seconds". Leaves out hours or minutes if they're zero.
void GetHourMinuteSecondsString( int nInputSeconds, char *pOut, int outLen );
int CheckParm (char *check);
FileHandle_t SafeOpenWrite ( const char *filename );
FileHandle_t SafeOpenRead ( const char *filename );
void SafeRead( FileHandle_t f, void *buffer, int count);
void SafeWrite( FileHandle_t f, void *buffer, int count);
int LoadFile ( const char *filename, void **bufferptr );
void SaveFile ( const char *filename, void *buffer, int count );
qboolean FileExists ( const char *filename );
int ParseNum (char *str);
// Do a printf in the specified color.
#define CP_ERROR stderr, 1, 0, 0, 1 // default colors..
#define CP_WARNING stderr, 1, 1, 0, 1
#define CP_STARTUP stdout, 0, 1, 1, 1
#define CP_NOTIFY stdout, 1, 1, 1, 1
void ColorPrintf( FILE *pFile, bool red, bool green, bool blue, bool intensity, char const *pFormat, ... );
// Initialize spew output.
void InstallSpewFunction();
// Install allocation hooks so we error out if an allocation can't happen.
void InstallAllocationFunctions();
// This shuts down mgrs that use threads gracefully. If you just call exit(), the threads can
// get in a state where you can't tell if they are shutdown or not, and it can stall forever.
typedef void (*CleanupFn)();
void CmdLib_AtCleanup( CleanupFn pFn ); // register a callback when Cleanup() is called.
void CmdLib_Cleanup();
// entrypoint if chaining spew functions
unsigned short SetConsoleTextColor( int red, int green, int blue, int intensity );
void RestoreConsoleTextColor( unsigned short color );
class CCmdLibStandardLoggingListener : public ILoggingListener
{
public:
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage );
};
class CCmdLibFileLoggingListener : public ILoggingListener
{
public:
CCmdLibFileLoggingListener();
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage );
void Open( char const *pFilename );
void Close();
private:
FileHandle_t m_pLogFile;
};
extern CCmdLibStandardLoggingListener g_CmdLibOutputLoggingListener;
extern CCmdLibFileLoggingListener g_CmdLibFileLoggingListener;
char *COM_Parse (char *data);
extern char com_token[1024];
char *copystring(const char *s);
void CreatePath( char *path );
void QCopyFile( char *from, char *to );
void SafeCreatePath( char *path );
extern qboolean archive;
extern char archivedir[1024];
extern qboolean verbose;
void qprintf( char *format, ... );
void ExpandWildcards (int *argc, char ***argv);
void CmdLib_AddBasePath( const char *pBasePath );
void CmdLib_AddNewSearchPath( const char *pBasePath );
bool CmdLib_HasBasePath( const char *pFileName, int &pathLength );
int CmdLib_GetNumBasePaths( void );
const char *CmdLib_GetBasePath( int i );
extern bool g_bStopOnExit;
// for compression routines
typedef struct
{
byte *data;
int count;
} cblock_t;
#endif // CMDLIB_H

339
utils/common/consolewnd.cpp Normal file
View File

@@ -0,0 +1,339 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <windows.h>
#include "consolewnd.h"
#pragma warning( disable : 4311 ) // warning C4311: 'reinterpret_cast' : pointer truncation from 'CConsoleWnd *const ' to 'LONG'
#pragma warning( disable : 4312 ) // warning C4312: 'type cast' : conversion from 'LONG' to 'CConsoleWnd *' of greater size
#define EDITCONTROL_BORDER_SIZE 5
// ------------------------------------------------------------------------------------------------ //
// Functions to manage the console window.
// ------------------------------------------------------------------------------------------------ //
class CConsoleWnd : public IConsoleWnd
{
public:
CConsoleWnd();
~CConsoleWnd();
bool Init( void *hInstance, int dialogResourceID, int editControlID, bool bVisible );
void Term();
virtual void Release();
virtual void SetVisible( bool bVisible );
virtual bool IsVisible() const;
virtual void PrintToConsole( const char *pMsg );
virtual void SetTitle( const char *pTitle );
virtual void SetDeleteOnClose( bool bDelete );
private:
int WindowProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
static int CALLBACK StaticWindowProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
void RepositionEditControl();
private:
HWND m_hWnd;
HWND m_hEditControl;
bool m_bVisible;
bool m_bDeleteOnClose;
int m_nCurrentChars;
};
CConsoleWnd::CConsoleWnd()
{
m_hWnd = m_hEditControl = NULL;
m_bVisible = false;
m_bDeleteOnClose = false;
m_nCurrentChars = 0;
}
CConsoleWnd::~CConsoleWnd()
{
Term();
}
bool CConsoleWnd::Init( void *hInstance, int dialogResourceID, int editControlID, bool bVisible )
{
// Create the window.
m_hWnd = CreateDialog(
(HINSTANCE)hInstance,
MAKEINTRESOURCE( dialogResourceID ),
NULL,
&CConsoleWnd::StaticWindowProc );
if ( !m_hWnd )
return false;
SetWindowLong( m_hWnd, GWL_USERDATA, reinterpret_cast< LONG >( this ) );
if ( bVisible )
ShowWindow( m_hWnd, SW_SHOW );
// Get a handle to the edit control.
m_hEditControl = GetDlgItem( m_hWnd, editControlID );
if ( !m_hEditControl )
return false;
RepositionEditControl();
m_bVisible = bVisible;
return true;
}
void CConsoleWnd::Term()
{
if ( m_hWnd )
{
DestroyWindow( m_hWnd );
m_hWnd = NULL;
}
}
void CConsoleWnd::Release()
{
delete this;
}
void CConsoleWnd::SetVisible( bool bVisible )
{
ShowWindow( m_hWnd, bVisible ? SW_RESTORE : SW_HIDE );
if ( bVisible )
{
ShowWindow( m_hWnd, SW_SHOW );
SetWindowPos( m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
UpdateWindow( m_hWnd );
int nLen = (int)SendMessage( m_hEditControl, EM_GETLIMITTEXT, 0, 0 );
SendMessage( m_hEditControl, EM_SETSEL, nLen, nLen );
}
else
{
SetWindowPos( m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_NOOWNERZORDER );
}
m_bVisible = bVisible;
}
bool CConsoleWnd::IsVisible() const
{
return m_bVisible;
}
void CConsoleWnd::PrintToConsole( const char *pMsg )
{
if ( m_nCurrentChars >= 16*1024 )
{
// Clear the edit control otherwise it'll stop outputting anything.
m_nCurrentChars = 0;
ClearEditControl( m_hEditControl );
}
FormatAndSendToEditControl( m_hEditControl, pMsg );
m_nCurrentChars += (int)strlen( pMsg );
}
void CConsoleWnd::SetTitle( const char *pTitle )
{
SetWindowText( m_hWnd, pTitle );
}
int CConsoleWnd::WindowProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
lParam = lParam; // avoid compiler warning
if ( hwndDlg != m_hWnd )
return false;
switch ( uMsg )
{
case WM_SYSCOMMAND:
{
if ( wParam == SC_CLOSE )
{
if ( m_bDeleteOnClose )
{
Release();
}
else
{
SetVisible( false );
return true;
}
}
}
break;
case WM_SHOWWINDOW:
{
m_bVisible = (wParam != 0);
}
break;
case WM_SIZE:
case WM_INITDIALOG:
{
RepositionEditControl();
}
break;
}
return false;
}
int CConsoleWnd::StaticWindowProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
CConsoleWnd *pDlg = (CConsoleWnd*)GetWindowLong( hwndDlg, GWL_USERDATA );
if ( pDlg )
return pDlg->WindowProc( hwndDlg, uMsg, wParam, lParam );
else
return false;
}
void CConsoleWnd::RepositionEditControl()
{
RECT rcMain;
GetClientRect( m_hWnd, &rcMain );
RECT rcNew;
rcNew.left = rcMain.left + EDITCONTROL_BORDER_SIZE;
rcNew.right = rcMain.right - EDITCONTROL_BORDER_SIZE;
rcNew.top = rcMain.top + EDITCONTROL_BORDER_SIZE;
rcNew.bottom = rcMain.bottom - EDITCONTROL_BORDER_SIZE;
SetWindowPos(
m_hEditControl,
NULL,
rcNew.left,
rcNew.top,
rcNew.right - rcNew.left,
rcNew.bottom - rcNew.top,
SWP_NOZORDER );
}
void CConsoleWnd::SetDeleteOnClose( bool bDelete )
{
m_bDeleteOnClose = bDelete;
}
// ------------------------------------------------------------------------------------ //
// Module interface.
// ------------------------------------------------------------------------------------ //
void ClearEditControl( void *hWnd )
{
HWND hEditControl = (HWND)hWnd;
int nLen = (int)SendMessage( hEditControl, EM_GETLIMITTEXT, 0, 0 );
SendMessage( hEditControl, EM_SETSEL, 0, nLen );
SendMessage( hEditControl, EM_REPLACESEL, FALSE, (LPARAM)"" );
}
void SendToEditControl( HWND hEditControl, const char *pText )
{
int nLen = (int)SendMessage( hEditControl, EM_GETLIMITTEXT, 0, 0 );
SendMessage( hEditControl, EM_SETSEL, nLen, nLen );
SendMessage( hEditControl, EM_REPLACESEL, FALSE, (LPARAM)pText );
}
void FormatAndSendToEditControl( void *hWnd, const char *pText )
{
HWND hEditControl = (HWND)hWnd;
// Translate \n to \r\n.
char outMsg[1024];
const char *pIn = pText;
char *pOut = outMsg;
while ( *pIn )
{
if ( *pIn == '\n' )
{
*pOut = '\r';
pOut++;
}
*pOut = *pIn;
++pIn;
++pOut;
if ( pOut - outMsg >= 1020 )
{
*pOut = 0;
SendToEditControl( hEditControl, outMsg );
pOut = outMsg;
}
}
*pOut = 0;
SendToEditControl( hEditControl, outMsg );
}
IConsoleWnd* CreateConsoleWnd( void *hInstance, int dialogResourceID, int editControlID, bool bVisible )
{
CConsoleWnd *pWnd = new CConsoleWnd;
if ( pWnd->Init( hInstance, dialogResourceID, editControlID, bVisible ) )
{
return pWnd;
}
else
{
pWnd->Release();
return NULL;
}
}

48
utils/common/consolewnd.h Normal file
View File

@@ -0,0 +1,48 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CONSOLEWND_H
#define CONSOLEWND_H
#ifdef _WIN32
#pragma once
#endif
class IConsoleWnd
{
public:
virtual void Release() = 0;
// Print a message to the console.
virtual void PrintToConsole( const char *pMsg ) = 0;
// Set the window title.
virtual void SetTitle( const char *pTitle ) = 0;
// Show and hide the console window.
virtual void SetVisible( bool bVisible ) = 0;
virtual bool IsVisible() const = 0;
// Normally, the window just hides itself when closed. You can use this to make the window
// automatically go away when they close it.
virtual void SetDeleteOnClose( bool bDelete ) = 0;
};
// Utility functions.
// Clear the contents of the edit control.
void ClearEditControl( void *hWnd );
// This converts adds \r's where necessary and sends the text to the edit control.
void FormatAndSendToEditControl( void *hWnd, const char *pText );
IConsoleWnd* CreateConsoleWnd( void *hInstance, int dialogResourceID, int editControlID, bool bVisible );
#endif // CONSOLEWND_H

470
utils/common/datalinker.cpp Normal file
View File

@@ -0,0 +1,470 @@
//========= Copyright c 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "datalinker.h"
#include "dbg.h"
#include "memalloc.h"
namespace DataLinker
{
const char g_cFillChar = '\xDE';
Stream::Stream()
{
m_data.reserve( 16 );
m_lastTarget = 1; // target 0 and 1 are special targets
m_alignBits = 3; // alignment 4 is default
m_size = 0;
m_stackBlocks.reserve( 4 ); // we'll probably never nest deeper than this
}
Chunk::Chunk( uint reserve, uint offset )
{
m_offset = offset;
m_capacity = reserve;
m_size = 0;
m_recentSize = 0;
m_data = ( byte* )MemAlloc_AllocAligned( reserve, 16 );
memset( m_data, g_cFillChar, reserve );
}
void Chunk::Free()
{
MemAlloc_FreeAligned( m_data );
}
Stream::~Stream()
{
for ( std::vector<Chunk>::iterator it = m_data.begin(); it != m_data.end(); ++it )
it->Free();
}
void* Stream::WriteBytes( uint numBytes )
{
EnsureAvailable( numBytes );
Chunk &chunk = m_data.back();
byte *p = chunk.m_data + chunk.m_size;
memset( p, 0, numBytes );
chunk.m_recentSize = m_size;
chunk.m_size += numBytes;
m_size += numBytes;
return p;
}
void Stream::EnsureAvailable( uint addCapacity )
{
Assert( addCapacity < 0x10000000 ); // we don't support >1Gb of data yet
if ( m_data.empty() )
{
// first allocation
m_data.push_back( Chunk( MAX( addCapacity*4u, 4096u ), 0 ) );
}
else if ( m_data.back().GetAvailable() < addCapacity )
{
m_data.push_back( Chunk( MAX( addCapacity*4u, m_data.back().m_capacity*2u ), m_size ) );
}
}
int Stream::GetOffsetTo( const void *ptr )const
{
for ( std::vector<Chunk>::const_reverse_iterator it = m_data.rbegin(); it != m_data.rend(); ++it )
{
uint offsetOfPtr = ( uint )( ( ( const byte* )ptr ) - it->m_data );
if ( offsetOfPtr <= it->m_size )
return offsetOfPtr + it->m_offset;
}
return -1; // invalid offset
}
bool Stream::Compile( void *pBuffer )
{
{
byte *p = ( byte* )pBuffer;
uint offset = 0;
for ( std::vector<Chunk>::const_iterator it = m_data.begin(); it != m_data.end(); ++it )
{
Assert( it->m_offset == offset );
memcpy( p + offset, it->m_data, it->m_size );
offset += it->m_size;
}
Assert( m_size == offset );
}
byte *data = ( byte* )pBuffer;
// for all link sources, try to resolve them
uint numUnresolved = 0;
for ( LinkSourceMap::const_iterator it = m_mapSources.begin(); it != m_mapSources.end(); ++it )
{
const LinkSourceDesc_t &source = it->second;
int offsetOfSource = it->first;
Assert( uint( offsetOfSource ) < m_size ); // check alignment?
int* pOffset = ( int* )( data + offsetOfSource );
if ( source.m_targetId == kSpecialTargetNull )
{
*pOffset = 0; // special case of target fixed to NULL
}
else if ( source.m_targetId < 0 || source.m_targetId > m_lastTarget )
{
Msg( "Unresolved link source @0x%X '%s'\n", offsetOfSource, source.m_pDescription );
numUnresolved ++;
}
else
{
// try to find the target
// if special target (id == 0): target is not in the target map; all the information is resolved directly through the LinkSourceDesc_t
const LinkTargetDesc_t &target = source.m_targetId == kSpecialTargetDefault ? source.m_defaultTarget : m_mapTargets[source.m_targetId];
switch ( target.m_type )
{
case kTargetNull:
*pOffset = 0; // special case of target set to NULL later
break;
case kTargetResolved:
switch ( source.m_type )
{
case kOtRelative32bit:
*pOffset = target.m_resolvedOffset - offsetOfSource;
break;
case kOtRelative16bit:
{
int offset = target.m_resolvedOffset - offsetOfSource;
if ( offset > 0x7FFF || offset < -0x8000 )
{
Msg( "Link source @%d '%s' is out of range (%d doesn't fit to 16 bits)\n", offsetOfSource, source.m_pDescription, offset );
numUnresolved++;
}
else
{
*( short* )pOffset = ( short )offset;
}
}
break;
case kOtAbsolute32bit:
*pOffset = target.m_resolvedOffset;
break;
}
break;
default:
Msg( "Unresolved link source @%d '%s'\n", offsetOfSource, source.m_pDescription );
numUnresolved++;
break;
}
}
}
if ( numUnresolved )
{
Error( "%u unresolved links found\n", numUnresolved );
return false;
}
else
return true;
}
void Stream::Align( uint nAlignment, int nOffset )
{
if ( nAlignment & ( nAlignment - 1 ) )
{
Error( "Wrong alignment %d\n", nAlignment );
}
//WriteBytes(((m_size+nAlignment-1) & ~(nAlignment-1)) - m_size);
WriteBytes( ( nOffset - m_size ) & ( nAlignment - 1 ) );
}
void Stream::Link( LinkSource_t linkSource, LinkTarget_t linkTarget, const char *szDescription )
{
LinkSourceMap::iterator itFind = m_mapSources.find( linkSource.m_offset );
if ( itFind == m_mapSources.end() )
{
Error( "cannot find source @%d - %s\n", linkSource.m_offset, szDescription );
}
itFind->second.m_targetId = linkTarget.m_id;
itFind->second.m_defaultTarget.m_type = kTargetUnresolved; // un-set default target for validation; we are not referring to it any more
Assert( linkTarget.m_id != kSpecialTargetDefault );
}
LinkSource_t Stream::LinkToHere( int *pOffset, const char *szDescription )
{
return Link( pOffset, NewTargetHere(), szDescription );
}
LinkSource_t Stream::Link( int32 *pOffset, LinkTarget_t linkTarget, const char *szDescription )
{
int offsetToOffset = GetOffsetTo( pOffset );
LinkSource_t linkSource = NewLinkSource( offsetToOffset, kOtRelative32bit, linkTarget.m_id, szDescription );
return linkSource;
}
void Stream::Link( int32 *pOffset, const void *pTarget )
{
if ( !pTarget )
{
*pOffset = 0;
return;
}
int offsetToOffset = GetOffsetTo( pOffset );
int offsetToTarget = GetOffsetTo( pTarget );
if ( offsetToOffset < 0 || offsetToTarget < 0 )
{
Error( "Link(%p,%p) can't find offsets (%d,%d)\n", pOffset, pTarget, offsetToOffset, offsetToTarget );
}
if ( offsetToOffset == offsetToTarget )
{
Warning( "Link(%p,%p) is self-referencing (%d==%d), this is prohibited by this kind of offset. It'll be interpreted as Null offset at runtime\n", pOffset, pTarget, offsetToOffset, offsetToTarget );
}
*pOffset = offsetToTarget - offsetToOffset;
}
void Stream::Link( int16 *pOffset, const void *pTarget )
{
if ( !pTarget )
{
*pOffset = 0;
return;
}
int offsetToOffset = GetOffsetTo( pOffset );
int offsetToTarget = GetOffsetTo( pTarget );
if ( offsetToOffset < 0 || offsetToTarget < 0 )
{
Error( "Link(%p,%p) can't find offsets (%d,%d)\n", pOffset, pTarget, offsetToOffset, offsetToTarget );
}
int offset = offsetToTarget - offsetToOffset;
int16 offset16 = ( int16 )offset;
if ( offset != ( int )offset16 )
{
Error( "Link16(%p,%p) offsets are too far (%d,%d)\n", pOffset, pTarget, offsetToOffset, offsetToTarget );
}
*pOffset = offset16;
}
LinkSource_t Stream::NewOffset( int *pOffset, const char *szDescription )
{
return NewLinkSource( GetOffsetTo( pOffset ), kOtRelative32bit, kSpecialTargetUndefined, szDescription );
}
LinkSource_t Stream::NewLinkSource( int offsetToOffset, OffsetTypeEnum type, int linkTargetId, const char *szDescription )
{
Assert( !( offsetToOffset & 3 ) );
if ( offsetToOffset < 0 && offsetToOffset + sizeof( int ) > m_size )
{
Error( "Wrong offset spec. Most probably you called an extra Write() before calling WriteOffset() - %s\n", szDescription );
}
LinkSource_t linkSource;
linkSource.m_offset = offsetToOffset;
LinkSourceDesc_t &lsd = m_mapSources[offsetToOffset];
lsd.m_targetId = linkTargetId;
lsd.m_type = type;
lsd.m_pDescription = szDescription;
return linkSource;
}
LinkSource_t Stream::WriteOffset( const char *szDescription )
{
return WriteOffset( LinkTarget_t(), szDescription );
}
LinkSource_t Stream::WriteOffset( LinkTarget_t linkTarget, const char *szDescription )
{
int offsetToOffset = m_size;
Write<int32>();
return NewLinkSource( offsetToOffset, kOtRelative32bit, linkTarget.m_id, szDescription );
}
LinkTarget_t Stream::NewTarget()// create new, unresolved target
{
LinkTarget_t linkTarget;
linkTarget.m_id = ++m_lastTarget; // shouldn't be 0 or -1
return linkTarget;
}
LinkTarget_t Stream::NewTarget( void *pWhere )
{
int offsetToTarget = GetOffsetTo( pWhere );
if ( offsetToTarget < 0 )
Error( "Invalid new target @%p\n", pWhere );
LinkTarget_t linkTarget = NewTarget();
SetTarget( linkTarget, offsetToTarget );
return linkTarget;
}
LinkTarget_t Stream::NewTargetHere() // creates a target right here
{
LinkTarget_t linkTarget = NewTarget();
SetTargetHere( linkTarget );
return linkTarget;
}
void Stream::SetTarget( LinkTarget_t linkTarget, int offsetToTarget ) // sets the given target to point to offsetToTarget
{
LinkTargetDesc_t &target = m_mapTargets[linkTarget.m_id];
target.m_type = kTargetResolved;
target.m_resolvedOffset = offsetToTarget;
}
void Stream::SetTargetHere( LinkTarget_t linkTarget ) // sets the given target to point to right here
{
if ( linkTarget.m_id > 0 && linkTarget.m_id <= m_lastTarget )
{
SetTarget( linkTarget, m_size );
}
else
{
Warning( "Trying to set invalid target %d to here (absolute offset %d)\n", linkTarget.m_id, m_size );
}
}
void Stream::SetTargetNull( LinkTarget_t linkTarget ) // set this target to point to NULL
{
if ( linkTarget.m_id > 0 && linkTarget.m_id <= m_lastTarget )
{
m_mapTargets[linkTarget.m_id].m_type = kTargetNull;
}
else
{
Warning( "Trying to set invalid target %d to null\n", linkTarget.m_id );
}
}
bool Stream::IsDeclared( LinkTarget_t linkTarget )const
{
return m_mapTargets.find( linkTarget.m_id ) != m_mapTargets.end();
}
bool Stream::IsSet( LinkTarget_t linkTarget )const
{
LinkTargetMap::const_iterator itFind = m_mapTargets.find( linkTarget.m_id );
if ( itFind == m_mapTargets.end() )
return false; // it can't be set when it hasn't been declared
return itFind->second.m_resolvedOffset >= 0;
}
bool Stream::IsDefined( LinkSource_t linkSource )const
{
LinkSourceMap::const_iterator itFind = m_mapSources.find( linkSource.m_offset );
return itFind != m_mapSources.end();
}
bool Stream::IsLinked( LinkSource_t linkSource )const
{
LinkSourceMap::const_iterator itFind = m_mapSources.find( linkSource.m_offset );
if ( itFind == m_mapSources.end() )
return false;
return itFind->second.m_targetId >= 0;
}
void Stream::Begin( const char *szName, uint flags )
{
Block_t newBlock;
if ( !m_stackBlocks.empty() )
newBlock.m_name = m_stackBlocks.back().m_name + ":" + szName;
else
newBlock.m_name = szName;
newBlock.m_tell = Tell();
m_stackBlocks.push_back( newBlock );
}
void Stream::End()
{
if ( !m_stackBlocks.empty() )
{
const Block_t &curBlock = m_stackBlocks.back();
m_mapBlockStats[curBlock.m_name].m_size += Tell() - curBlock.m_tell;
m_stackBlocks.pop_back();
}
}
void Stream::PrintStats()
{
for ( BlockStatsMap::const_iterator it = m_mapBlockStats.begin(); it != m_mapBlockStats.end(); ++it )
Msg( "%-60s %7.1f KiB\n", it->first.c_str(), it->second.m_size / 1024. );
Msg( "%-60s -----------\n", "" );
Msg( "%-60s %7.1f KiB\n", "DataLinker total stream size", m_size / 1024. );
}
void Stream::ClearStats()
{
m_mapBlockStats.clear();
}
const char* Stream::WriteAndLinkString( Offset_t<char> *pOffset, const char *pString )
{
if ( pString )
{
StringTableElement_t &ste = m_stringTable[pString];
if ( !ste.m_pString )
{
int nLen = Q_strlen( pString );
ste.m_nOffset = Tell();
ste.m_pString = ( char* )this->WriteBytes( nLen + 1 );
Q_memcpy( ste.m_pString, pString, nLen + 1 );
}
Assert( !Q_strcmp( ste.m_pString, pString ) );
int offsetToOffset = GetOffsetTo( pOffset );
pOffset->offset = ste.m_nOffset - offsetToOffset;
return ste.m_pString;
}
else
{
pOffset->offset = 0; // make the offset NULL
return NULL;
}
}
}

180
utils/common/datalinker.h Normal file
View File

@@ -0,0 +1,180 @@
//========= Copyright c 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DATA_LINKER_H
#define DATA_LINKER_H
#include "datalinker_interface.h"
#include <map>
#include <vector>
#include <string>
#include "tier1/UtlStringMap.h"
namespace DataLinker
{
enum LinkTargetEnum
{
kTargetResolved,
kTargetUnresolved,
kTargetNull
};
struct LinkTargetDesc_t
{
LinkTargetEnum m_type;
int m_resolvedOffset;
LinkTargetDesc_t()
{
m_resolvedOffset = -1;
m_type = kTargetUnresolved;
}
};
struct LinkSourceDesc_t
{
int m_targetId; // when this is 0, we use the embedded structure
OffsetTypeEnum m_type;
const char *m_pDescription;
LinkTargetDesc_t m_defaultTarget;
};
typedef std::map<int, LinkSourceDesc_t> LinkSourceMap;
typedef std::map<int, LinkTargetDesc_t> LinkTargetMap;
class Chunk
{
public:
Chunk() {}
Chunk( uint reserve, uint offset );
void Free();
uint GetAvailable()const
{
return m_capacity - m_size;
}
uint m_offset;
uint m_size;
uint m_capacity;
uint m_recentSize;
byte *m_data;
};
//////////////////////////////////////////////////////////////////////////
// This writer uses malloc() to allocate memory for the binary data
class Stream: public ILinkStream
{
public:
Stream();
~Stream();
void* WriteBytes( uint numBytes );
void EnsureAvailable( uint addCapacity );
void Link( LinkSource_t, LinkTarget_t, const char *szDescription );
void Align( uint nAlignment, int nOffset = 0 );
long Tell()
{
return m_size;
}
LinkSource_t WriteOffset( const char *szDescription );
LinkSource_t WriteOffset( LinkTarget_t linkTarget, const char *szDescription );
LinkSource_t WriteNullOffset( const char *szDescription )
{
return WriteOffset( LinkTargetNull_t(), szDescription );
}
LinkSource_t NewOffset( int *pOffset, const char *szDescription );
LinkSource_t LinkToHere( int *pOffset, const char *szDescription );
LinkSource_t Link( int32 *pOffset, LinkTarget_t linkTarget, const char *szDescription );
void Link( int32 *pOffset, const void *pTarget );
void Link( int16 *pOffset, const void *pTarget );
LinkTarget_t NewTarget(); // create new, unresolved target
LinkTarget_t NewTarget( void *pWhere );
LinkTarget_t NewTargetHere(); // creates a target right here
void SetTargetHere( LinkTarget_t ); // sets the given target to point to right here
void SetTargetNull( LinkTarget_t ); // set this target to point to NULL
// make the targets point to the same place
//void Assign(LinkTarget_t assignee, LinkTarget_t assignor);
bool Compile( void *pBuffer );
uint GetTotalSize()const
{
return m_size;
}
bool IsDeclared( LinkTarget_t linkTarget )const;
bool IsSet( LinkTarget_t linkTarget )const;
bool IsDefined( LinkSource_t linkSource )const;
bool IsLinked( LinkSource_t linkSource )const;
const char* WriteAndLinkString( Offset_t<char> *pOffset, const char *pString );
long Tell()const
{
return m_size;
}
void Begin( const char *nName, uint flags = 0 );
void End();
void PrintStats();
void ClearStats();
protected:
LinkSource_t NewLinkSource( int offsetOfOffset, OffsetTypeEnum type, int linkTargetId, const char *szDescription );
int GetOffsetTo( const void *ptr )const;
void SetTarget( LinkTarget_t linkTarget, int offsetToTarget );
protected:
std::vector<Chunk> m_data;
struct StringTableElement_t
{
char *m_pString;
int m_nOffset;
StringTableElement_t(): m_pString( NULL ), m_nOffset( NULL ) {}
};
CUtlStringMap<StringTableElement_t> m_stringTable; // each string offset
uint m_size; // this is the currently used data
int m_lastTarget; // the last id of LinkTarget
uint m_alignBits; // the ( max alignment - 1 ) of the current block of data
// LinkSource_t::m_offset -> ...
LinkSourceMap m_mapSources;
//
LinkTargetMap m_mapTargets;
struct BlockStats_t
{
BlockStats_t(): m_size( 0 ) {}
long m_size;
};
typedef std::map<std::string, BlockStats_t>BlockStatsMap;
BlockStatsMap m_mapBlockStats;
struct Block_t
{
std::string m_name;
long m_tell;
};
std::vector<Block_t> m_stackBlocks;
};
}
#endif

View File

@@ -0,0 +1,223 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#if defined( _WIN32 ) && !defined( _X360 )
#include <windows.h>
#include <direct.h>
#include <io.h> // _chmod
#elif POSIX
#include <unistd.h>
#endif
#include <stdio.h>
#include <sys/stat.h>
#include "tier1/strtools.h"
#include "filesystem_tools.h"
#include "tier0/icommandline.h"
#include "keyvalues.h"
#include "tier2/tier2.h"
#ifdef MPI
#include "vmpi.h"
#include "vmpi_tools_shared.h"
#include "vmpi_filesystem.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
// ---------------------------------------------------------------------------------------------------- //
// Module interface.
// ---------------------------------------------------------------------------------------------------- //
IBaseFileSystem *g_pFileSystem = NULL;
// These are only used for tools that need the search paths that the engine's file system provides.
CSysModule *g_pFullFileSystemModule = NULL;
// ---------------------------------------------------------------------------
//
// These are the base paths that everything will be referenced relative to (textures especially)
// All of these directories include the trailing slash
//
// ---------------------------------------------------------------------------
// This is the the path of the initial source file (relative to the cwd)
char qdir[1024];
// This is the base engine + mod-specific game dir (e.g. "c:\tf2\mytfmod\")
char gamedir[1024];
void FileSystem_SetupStandardDirectories( const char *pFilename, const char *pGameInfoPath )
{
// Set qdir.
if ( !pFilename )
{
pFilename = ".";
}
Q_MakeAbsolutePath( qdir, sizeof( qdir ), pFilename, NULL );
Q_StripFilename( qdir );
Q_strlower( qdir );
if ( qdir[0] != 0 )
{
Q_AppendSlash( qdir, sizeof( qdir ) );
}
// Set gamedir.
Q_MakeAbsolutePath( gamedir, sizeof( gamedir ), pGameInfoPath );
Q_AppendSlash( gamedir, sizeof( gamedir ) );
}
bool FileSystem_Init_Normal( const char *pFilename, FSInitType_t initType, bool bOnlyUseDirectoryName )
{
if ( initType == FS_INIT_FULL )
{
// First, get the name of the module
char fileSystemDLLName[MAX_PATH];
bool bSteam;
if ( FileSystem_GetFileSystemDLLName( fileSystemDLLName, MAX_PATH, bSteam ) != FS_OK )
return false;
// If we're under Steam we need extra setup to let us find the proper modules
FileSystem_SetupSteamInstallPath();
// Next, load the module, call Connect/Init.
CFSLoadModuleInfo loadModuleInfo;
loadModuleInfo.m_pFileSystemDLLName = fileSystemDLLName;
loadModuleInfo.m_pDirectoryName = pFilename;
loadModuleInfo.m_bOnlyUseDirectoryName = bOnlyUseDirectoryName;
loadModuleInfo.m_ConnectFactory = Sys_GetFactoryThis();
loadModuleInfo.m_bSteam = bSteam;
loadModuleInfo.m_bToolsMode = true;
if ( FileSystem_LoadFileSystemModule( loadModuleInfo ) != FS_OK )
return false;
// Next, mount the content
CFSMountContentInfo mountContentInfo;
mountContentInfo.m_pDirectoryName= loadModuleInfo.m_GameInfoPath;
mountContentInfo.m_pFileSystem = loadModuleInfo.m_pFileSystem;
mountContentInfo.m_bToolsMode = true;
if ( FileSystem_MountContent( mountContentInfo ) != FS_OK )
return false;
// Finally, load the search paths.
CFSSearchPathsInit searchPathsInit;
searchPathsInit.m_pDirectoryName = loadModuleInfo.m_GameInfoPath;
searchPathsInit.m_pFileSystem = loadModuleInfo.m_pFileSystem;
if ( FileSystem_LoadSearchPaths( searchPathsInit ) != FS_OK )
return false;
// Store the data we got from filesystem_init.
g_pFileSystem = g_pFullFileSystem = loadModuleInfo.m_pFileSystem;
g_pFullFileSystemModule = loadModuleInfo.m_pModule;
FileSystem_AddSearchPath_Platform( g_pFullFileSystem, loadModuleInfo.m_GameInfoPath );
FileSystem_SetupStandardDirectories( pFilename, loadModuleInfo.m_GameInfoPath );
}
else
{
if ( !Sys_LoadInterface(
"filesystem_stdio",
FILESYSTEM_INTERFACE_VERSION,
&g_pFullFileSystemModule,
(void**)&g_pFullFileSystem ) )
{
return false;
}
if ( g_pFullFileSystem->Init() != INIT_OK )
return false;
g_pFullFileSystem->RemoveAllSearchPaths();
g_pFullFileSystem->AddSearchPath( "../platform", "PLATFORM" );
g_pFullFileSystem->AddSearchPath( ".", "GAME" );
g_pFileSystem = g_pFullFileSystem;
}
return true;
}
bool FileSystem_Init( const char *pBSPFilename, int maxMemoryUsage, FSInitType_t initType, bool bOnlyUseFilename )
{
Assert( CommandLine()->GetCmdLine() != NULL ); // Should have called CreateCmdLine by now.
// If this app uses VMPI, then let VMPI intercept all filesystem calls.
#if defined( MPI )
if ( g_bUseMPI )
{
if ( g_bMPIMaster )
{
if ( !FileSystem_Init_Normal( pBSPFilename, initType, bOnlyUseFilename ) )
return false;
g_pFileSystem = g_pFullFileSystem = VMPI_FileSystem_Init( maxMemoryUsage, g_pFullFileSystem );
SendQDirInfo();
}
else
{
g_pFileSystem = g_pFullFileSystem = VMPI_FileSystem_Init( maxMemoryUsage, NULL );
RecvQDirInfo();
}
return true;
}
#endif
return FileSystem_Init_Normal( pBSPFilename, initType, bOnlyUseFilename );
}
void FileSystem_Term()
{
#if defined( MPI )
if ( g_bUseMPI )
{
g_pFileSystem = g_pFullFileSystem = VMPI_FileSystem_Term();
}
#endif
if ( g_pFullFileSystem )
{
g_pFullFileSystem->Shutdown();
g_pFullFileSystem = NULL;
g_pFileSystem = NULL;
}
if ( g_pFullFileSystemModule )
{
Sys_UnloadModule( g_pFullFileSystemModule );
g_pFullFileSystemModule = NULL;
}
}
CreateInterfaceFn FileSystem_GetFactory()
{
#if defined( MPI )
if ( g_bUseMPI )
return VMPI_FileSystem_GetFactory();
#endif
return Sys_GetFactory( g_pFullFileSystemModule );
}
bool FileSystem_SetGame( const char *szModDir )
{
g_pFullFileSystem->RemoveAllSearchPaths();
if ( FileSystem_SetBasePaths( g_pFullFileSystem ) != FS_OK )
return false;
CFSSearchPathsInit fsInit;
fsInit.m_pDirectoryName = szModDir;
fsInit.m_pFileSystem = g_pFullFileSystem;
return ( FileSystem_LoadSearchPaths( fsInit ) == FS_OK );
}

View File

@@ -0,0 +1,60 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef FILESYSTEM_TOOLS_H
#define FILESYSTEM_TOOLS_H
#ifdef _WIN32
#pragma once
#endif
#include "filesystem.h"
#include "filesystem_init.h"
// This is the the path of the initial source file
extern char qdir[1024];
// This is the base engine + mod-specific game dir (e.g. "d:\tf2\mytfmod\")
extern char gamedir[1024];
// ---------------------------------------------------------------------------------------- //
// Filesystem initialization.
// ---------------------------------------------------------------------------------------- //
enum FSInitType_t
{
FS_INIT_FULL, // Load gameinfo.txt, maybe use filesystem_steam, and setup search paths.
FS_INIT_COMPATIBILITY_MODE // Load filesystem_stdio and that's it.
};
//
// Initializes qdir, and gamedir. Also initializes the VMPI filesystem if MPI is defined.
//
// pFilename can be NULL if you want to rely on vproject and qproject. If it's specified, FileSystem_Init
// will go up directories from pFilename looking for gameinfo.txt (if vproject isn't specified).
//
// If bOnlyUseFilename is true, then it won't use any alternative methods of finding the vproject dir
// (ie: it won't use -game or -vproject or the vproject env var or qproject).
//
bool FileSystem_Init( const char *pFilename, int maxMemoryUsage=0, FSInitType_t initType=FS_INIT_FULL, bool bOnlyUseFilename=false );
void FileSystem_Term();
bool FileSystem_SetGame( const char *szModDir );
// Used to connect app-framework based console apps to the filesystem tools
void FileSystem_SetupStandardDirectories( const char *pFilename, const char *pGameInfoPath );
CreateInterfaceFn FileSystem_GetFactory( void );
extern IBaseFileSystem *g_pFileSystem;
DECLARE_TIER2_INTERFACE( IFileSystem, g_pFullFileSystem ); // NOTE: this is here when VMPI is being used, but a VMPI app can
// ONLY use LoadModule/UnloadModule.
#endif // FILESYSTEM_TOOLS_H

View File

@@ -0,0 +1,147 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// Functions to help with map instancing.
//
//===============================================================================
#ifndef INSTANCINGHELPER_H
#define INSTANCINGHELPER_H
#if defined( COMPILER_MSVC )
#pragma once
#endif
class CInstancingHelper
{
public:
//-----------------------------------------------------------------------------
// Attempts to locate an instance by its filename, given the
// location of the root-level VMF file, the instance directory specified in
// the gameinfo.txt file, and the GAME directory.
//
// pFileSystem - pointer to file system object
// pBaseFilename - path of the file including the instance
// pInstanceFilename - relative filename of the instance, as read from
// a func_instance entity
// pInstanceDirectory - instance directory, specified by gameinfo.txt
// pResolvedInstanceFilename - pointer to buffer to receive resolved
// filename (only valid if function returns true)
// nBufferSize - size of the buffer. Should be at least MAX_PATH.
//
// Returns true on success, false on failure.
//-----------------------------------------------------------------------------
static bool ResolveInstancePath( IFileSystem *pFileSystem, const char *pBaseFilename, const char *pInstanceFilename, const char *pInstanceDirectory, char *pResolvedInstanceFilename, int nBufferSize )
{
Assert( nBufferSize >= MAX_PATH );
char fixedInstanceFilename[MAX_PATH];
Q_strncpy( fixedInstanceFilename, pInstanceFilename, MAX_PATH );
Q_SetExtension( fixedInstanceFilename, ".vmf", MAX_PATH );
Q_FixSlashes( fixedInstanceFilename );
V_FixDoubleSlashes( fixedInstanceFilename );
// Try to locate the instance file relative to the current file's path
Q_strncpy( pResolvedInstanceFilename, pBaseFilename, nBufferSize );
Q_StripFilename( pResolvedInstanceFilename );
Q_strncat( pResolvedInstanceFilename, "\\", nBufferSize );
Q_strncat( pResolvedInstanceFilename, fixedInstanceFilename, nBufferSize );
Q_RemoveDotSlashes( pResolvedInstanceFilename );
V_FixDoubleSlashes( pResolvedInstanceFilename );
Q_FixSlashes( pResolvedInstanceFilename );
if ( pFileSystem->FileExists( pResolvedInstanceFilename ) )
{
return true;
}
#ifdef __IN_HAMMER
if ( CMapInstance::IsMapInVersionControl( pResolvedInstanceFilename ) == true )
{
return true;
}
#endif // #ifdef __IN_HAMMER
// Try to locate the instance file relative to the "maps\" directory
const char *pMapPath = "\\maps\\";
char *pMapPathPosition = Q_stristr( pResolvedInstanceFilename, pMapPath );
if ( pMapPathPosition != NULL )
{
pMapPathPosition += Q_strlen( pMapPath );
}
else if ( pMapPathPosition == NULL && Q_strnicmp( pResolvedInstanceFilename, "maps\\", 5 ) == 0 )
{
pMapPathPosition = pResolvedInstanceFilename + 5;
}
// Assuming we found a maps\ directory of some kind
if ( pMapPathPosition != NULL )
{
*pMapPathPosition = 0;
Q_strncat( pResolvedInstanceFilename, fixedInstanceFilename, nBufferSize );
if ( pFileSystem->FileExists( pResolvedInstanceFilename ) )
{
return true;
}
#ifdef __IN_HAMMER
if ( CMapInstance::IsMapInVersionControl( pResolvedInstanceFilename ) == true )
{
return true;
}
#endif // #ifdef __IN_HAMMER
}
if ( pInstanceDirectory[0] != '\0' )
{
char instanceDirectoryRelativeFilename[MAX_PATH];
Q_snprintf( instanceDirectoryRelativeFilename, nBufferSize, "%s/%s", pInstanceDirectory, fixedInstanceFilename );
Q_SetExtension( instanceDirectoryRelativeFilename, ".vmf", MAX_PATH );
Q_FixSlashes( instanceDirectoryRelativeFilename );
Q_RemoveDotSlashes( instanceDirectoryRelativeFilename );
V_FixDoubleSlashes( instanceDirectoryRelativeFilename );
pFileSystem->RelativePathToFullPath( instanceDirectoryRelativeFilename, "CONTENT", pResolvedInstanceFilename, nBufferSize );
if ( pFileSystem->FileExists( instanceDirectoryRelativeFilename, "CONTENT" ) )
{
return true;
}
#ifdef __IN_HAMMER
if ( CMapInstance::IsMapInVersionControl( pResolvedInstanceFilename ) == true )
{
return true;
}
#endif // #ifdef __IN_HAMMER
}
int searchPathLen = pFileSystem->GetSearchPath( "CONTENT", true, NULL, 0 );
char *searchPaths = (char *)stackalloc( searchPathLen + 1 );
pFileSystem->GetSearchPath( "CONTENT", true, searchPaths, searchPathLen );
for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) )
{
Q_strncpy( pResolvedInstanceFilename, path, nBufferSize );
Q_strncat( pResolvedInstanceFilename, "maps\\", nBufferSize );
Q_strncat( pResolvedInstanceFilename, fixedInstanceFilename, nBufferSize );
if ( pFileSystem->FileExists( pResolvedInstanceFilename ) )
{
return true;
}
}
#ifdef __IN_HAMMER
if ( CMapInstance::IsMapInVersionControl( pResolvedInstanceFilename ) == true )
{
return true;
}
#endif // #ifdef __IN_HAMMER
if ( nBufferSize > 0 )
{
pResolvedInstanceFilename[0] = '\0';
}
return false;
}
};
#endif // INSTANCINGHELPER_H

141
utils/common/map_shared.cpp Normal file
View File

@@ -0,0 +1,141 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "map_shared.h"
#include "bsplib.h"
#include "cmdlib.h"
CMapError g_MapError;
int g_nMapFileVersion;
//-----------------------------------------------------------------------------
// Purpose:
// Input : *szKey -
// *szValue -
// *pLoadEntity -
// Output : ChunkFileResult_t
//-----------------------------------------------------------------------------
ChunkFileResult_t LoadEntityKeyCallback(const char *szKey, const char *szValue, LoadEntity_t *pLoadEntity)
{
if (!stricmp(szKey, "classname"))
{
if (!stricmp(szValue, "func_detail"))
{
pLoadEntity->nBaseContents = CONTENTS_DETAIL;
}
else if (!stricmp(szValue, "func_ladder"))
{
pLoadEntity->nBaseContents = CONTENTS_LADDER;
}
else if (!stricmp(szValue, "func_water"))
{
pLoadEntity->nBaseContents = CONTENTS_WATER;
}
}
else if (!stricmp(szKey, "id"))
{
// UNDONE: flag entity errors by ID instead of index
//g_MapError.EntityState( atoi( szValue ) );
// rename this field since DME code uses this name
SetKeyValue( pLoadEntity->pEntity, "hammerid", szValue );
return(ChunkFile_Ok);
}
else if( !stricmp( szKey, "mapversion" ) )
{
// .vmf map revision number
if ( g_MapRevision == 0 )
{
// only take the first occurrence of this. func_instance will each have another occurrence but we want the root map's revision
g_MapRevision = atoi( szValue );
Msg("Map revision %d\n", g_MapRevision );
}
SetKeyValue( pLoadEntity->pEntity, szKey, szValue );
return ( ChunkFile_Ok );
}
SetKeyValue( pLoadEntity->pEntity, szKey, szValue );
return(ChunkFile_Ok);
}
static ChunkFileResult_t LoadEntityCallback( CChunkFile *pFile, int nParam )
{
if (num_entities == MAX_MAP_ENTITIES)
{
// Exits.
g_MapError.ReportError ("num_entities == MAX_MAP_ENTITIES");
}
entity_t *mapent = &entities[num_entities];
num_entities++;
memset(mapent, 0, sizeof(*mapent));
mapent->numbrushes = 0;
LoadEntity_t LoadEntity;
LoadEntity.pEntity = mapent;
// No default flags/contents
LoadEntity.nBaseFlags = 0;
LoadEntity.nBaseContents = 0;
//
// Read the entity chunk.
//
ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadEntityKeyCallback, &LoadEntity);
return eResult;
}
bool LoadEntsFromMapFile( char const *pFilename )
{
//
// Dummy this up for the texture handling. This can be removed when old .MAP file
// support is removed.
//
g_nMapFileVersion = 400;
//
// Open the file.
//
CChunkFile File;
ChunkFileResult_t eResult = File.Open( pFilename, ChunkFile_Read );
if(eResult == ChunkFile_Ok)
{
num_entities = 0;
//
// Set up handlers for the subchunks that we are interested in.
//
CChunkHandlerMap Handlers;
Handlers.AddHandler("entity", (ChunkHandler_t)LoadEntityCallback, 0);
File.PushHandlers(&Handlers);
//
// Read the sub-chunks. We ignore keys in the root of the file.
//
while (eResult == ChunkFile_Ok)
{
eResult = File.ReadChunk();
}
File.PopHandlers();
return true;
}
else
{
Error("Error in LoadEntsFromMapFile (in-memory file): %s.\n", File.GetErrorText(eResult));
return false;
}
}

91
utils/common/map_shared.h Normal file
View File

@@ -0,0 +1,91 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef MAP_SHARED_H
#define MAP_SHARED_H
#ifdef _WIN32
#pragma once
#endif
#include "ChunkFile.h"
#include "bsplib.h"
#include "cmdlib.h"
struct LoadEntity_t
{
entity_t *pEntity;
int nID;
int nBaseFlags;
int nBaseContents;
};
class CMapError
{
public:
void BrushState( int brushID )
{
m_brushID = brushID;
}
void BrushSide( int side )
{
m_sideIndex = side;
}
void TextureState( const char *pTextureName )
{
Q_strncpy( m_textureName, pTextureName, sizeof( m_textureName ) );
}
void ClearState( void )
{
BrushState( 0 );
BrushSide( 0 );
TextureState( "Not a Parse error!" );
}
//-----------------------------------------------------------------------------
// Purpose: Hook the map parse errors and report brush/ent/texture state
// Input : *pErrorString -
//-----------------------------------------------------------------------------
void ReportError( const char *pErrorString )
{
Error( "Brush %i: %s\nSide %i\nTexture: %s\n", m_brushID, pErrorString, m_sideIndex, m_textureName );
}
//-----------------------------------------------------------------------------
// Purpose: Hook the map parse errors and report brush/ent/texture state without exiting.
// Input : pWarningString -
//-----------------------------------------------------------------------------
void ReportWarning( const char *pWarningString )
{
printf( "Brush %i, Side %i: %s\n", m_brushID, m_sideIndex, pWarningString );
}
private:
int m_brushID;
int m_sideIndex;
char m_textureName[80];
};
extern CMapError g_MapError;
extern int g_nMapFileVersion;
// Shared mapload code.
ChunkFileResult_t LoadEntityKeyCallback( const char *szKey, const char *szValue, LoadEntity_t *pLoadEntity );
// Used by VRAD incremental lighting - only load ents from the file and
// fill in the global entities/num_entities array.
bool LoadEntsFromMapFile( char const *pFilename );
#endif // MAP_SHARED_H

34
utils/common/movie.h Normal file
View File

@@ -0,0 +1,34 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef _MOVIE_H_
#define _MOVIE_H_
/*
movie.h
definitions and such for dumping screen shots to make a movie
*/
typedef struct
{
unsigned long tag;
unsigned long size;
} movieblockheader_t;
typedef struct
{
short width;
short height;
short depth;
} movieframe_t;
#endif _MOVIE_H_

845
utils/common/mpi_stats.cpp Normal file
View File

@@ -0,0 +1,845 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Nasty headers!
#include "MySqlDatabase.h"
#include "tier1/strtools.h"
#include "vmpi.h"
#include "vmpi_dispatch.h"
#include "mpi_stats.h"
#include "cmdlib.h"
#include "imysqlwrapper.h"
#include "threadhelpers.h"
#include "vmpi_tools_shared.h"
#include "tier0/icommandline.h"
/*
-- MySQL code to create the databases, create the users, and set access privileges.
-- You only need to ever run this once.
create database vrad;
use mysql;
create user vrad_worker;
create user vmpi_browser;
-- This updates the "user" table, which is checked when someone tries to connect to the database.
grant select,insert,update on vrad.* to vrad_worker;
grant select on vrad.* to vmpi_browser;
flush privileges;
/*
-- SQL code to (re)create the tables.
-- Master generates a unique job ID (in job_master_start) and sends it to workers.
-- Each worker (and the master) make a job_worker_start, link it to the primary job ID,
-- get their own unique ID, which represents that process in that job.
-- All JobWorkerID fields link to the JobWorkerID field in job_worker_start.
-- NOTE: do a "use vrad" or "use vvis" first, depending on the DB you want to create.
use vrad;
drop table job_master_start;
create table job_master_start (
JobID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, index id( JobID, MachineName(5) ),
BSPFilename TINYTEXT NOT NULL,
StartTime TIMESTAMP NOT NULL,
MachineName TEXT NOT NULL,
RunningTimeMS INTEGER UNSIGNED NOT NULL,
NumWorkers INTEGER UNSIGNED NOT NULL default 0
);
drop table job_master_end;
create table job_master_end (
JobID INTEGER UNSIGNED NOT NULL, PRIMARY KEY ( JobID ),
NumWorkersConnected SMALLINT UNSIGNED NOT NULL,
NumWorkersDisconnected SMALLINT UNSIGNED NOT NULL,
ErrorText TEXT NOT NULL
);
drop table job_worker_start;
create table job_worker_start (
JobWorkerID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
index index_jobid( JobID ),
index index_jobworkerid( JobWorkerID ),
JobID INTEGER UNSIGNED NOT NULL, -- links to job_master_start::JobID
IsMaster BOOL NOT NULL, -- Set to 1 if this "worker" is the master process.
RunningTimeMS INTEGER UNSIGNED NOT NULL default 0,
MachineName TEXT NOT NULL,
WorkerState SMALLINT UNSIGNED NOT NULL default 0, -- 0 = disconnected, 1 = connected
NumWorkUnits INTEGER UNSIGNED NOT NULL default 0, -- how many work units this worker has completed
CurrentStage TINYTEXT NOT NULL, -- which compile stage is it on
Thread0WU INTEGER NOT NULL default 0, -- which WU thread 0 is on
Thread1WU INTEGER NOT NULL default 0, -- which WU thread 1 is on
Thread2WU INTEGER NOT NULL default 0, -- which WU thread 2 is on
Thread3WU INTEGER NOT NULL default 0 -- which WU thread 3 is on
);
drop table text_messages;
create table text_messages (
JobWorkerID INTEGER UNSIGNED NOT NULL, index id( JobWorkerID, MessageIndex ),
MessageIndex INTEGER UNSIGNED NOT NULL,
Text TEXT NOT NULL
);
drop table graph_entry;
create table graph_entry (
JobWorkerID INTEGER UNSIGNED NOT NULL, index id( JobWorkerID ),
MSSinceJobStart INTEGER UNSIGNED NOT NULL,
BytesSent INTEGER UNSIGNED NOT NULL,
BytesReceived INTEGER UNSIGNED NOT NULL
);
drop table events;
create table events (
JobWorkerID INTEGER UNSIGNED NOT NULL, index id( JobWorkerID ),
Text TEXT NOT NULL
);
*/
// Stats set by the app.
int g_nWorkersConnected = 0;
int g_nWorkersDisconnected = 0;
DWORD g_StatsStartTime;
CMySqlDatabase *g_pDB = NULL;
IMySQL *g_pSQL = NULL;
CSysModule *g_hMySQLDLL = NULL;
char g_BSPFilename[256];
bool g_bMaster = false;
unsigned long g_JobPrimaryID = 0; // This represents this job, but doesn't link to a particular machine.
unsigned long g_JobWorkerID = 0; // A unique key in the DB that represents this machine in this job.
char g_MachineName[MAX_COMPUTERNAME_LENGTH+1] = {0};
unsigned long g_CurrentMessageIndex = 0;
HANDLE g_hPerfThread = NULL;
DWORD g_PerfThreadID = 0xFEFEFEFE;
HANDLE g_hPerfThreadExitEvent = NULL;
// These are set by the app and they go into the database.
extern uint64 g_ThreadWUs[4];
extern uint64 VMPI_GetNumWorkUnitsCompleted( int iProc );
// ---------------------------------------------------------------------------------------------------- //
// This is a helper class to build queries like the stream IO.
// ---------------------------------------------------------------------------------------------------- //
class CMySQLQuery
{
friend class CMySQL;
public:
// This is like a sprintf, but it will grow the string as necessary.
void Format( const char *pFormat, ... );
int Execute( IMySQL *pDB );
private:
CUtlVector<char> m_QueryText;
};
void CMySQLQuery::Format( const char *pFormat, ... )
{
#define QUERYTEXT_GROWSIZE 1024
// This keeps growing the buffer and calling _vsnprintf until the buffer is
// large enough to hold all the data.
m_QueryText.SetSize( QUERYTEXT_GROWSIZE );
while ( 1 )
{
va_list marker;
va_start( marker, pFormat );
int ret = _vsnprintf( m_QueryText.Base(), m_QueryText.Count(), pFormat, marker );
va_end( marker );
if ( ret < 0 )
{
m_QueryText.SetSize( m_QueryText.Count() + QUERYTEXT_GROWSIZE );
}
else
{
m_QueryText[ m_QueryText.Count() - 1 ] = 0;
break;
}
}
}
int CMySQLQuery::Execute( IMySQL *pDB )
{
int ret = pDB->Execute( m_QueryText.Base() );
m_QueryText.Purge();
return ret;
}
// ---------------------------------------------------------------------------------------------------- //
// This inserts the necessary backslashes in front of backslashes or quote characters.
// ---------------------------------------------------------------------------------------------------- //
char* FormatStringForSQL( const char *pText )
{
// First, count the quotes in the string. We need to put a backslash in front of each one.
int nChars = 0;
const char *pCur = pText;
while ( *pCur != 0 )
{
if ( *pCur == '\"' || *pCur == '\\' )
++nChars;
++pCur;
++nChars;
}
pCur = pText;
char *pRetVal = new char[nChars+1];
for ( int i=0; i < nChars; )
{
if ( *pCur == '\"' || *pCur == '\\' )
pRetVal[i++] = '\\';
pRetVal[i++] = *pCur;
++pCur;
}
pRetVal[nChars] = 0;
return pRetVal;
}
// -------------------------------------------------------------------------------- //
// Commands to add data to the database.
// -------------------------------------------------------------------------------- //
class CSQLDBCommandBase : public ISQLDBCommand
{
public:
virtual ~CSQLDBCommandBase()
{
}
virtual void deleteThis()
{
delete this;
}
};
class CSQLDBCommand_WorkerStats : public CSQLDBCommandBase
{
public:
virtual int RunCommand()
{
int nCurConnections = VMPI_GetCurrentNumberOfConnections();
// Update the NumWorkers entry.
char query[2048];
Q_snprintf( query, sizeof( query ), "update job_master_start set NumWorkers=%d where JobID=%lu",
nCurConnections,
g_JobPrimaryID );
g_pSQL->Execute( query );
// Update the job_master_worker_stats stuff.
for ( int i=1; i < nCurConnections; i++ )
{
unsigned long jobWorkerID = VMPI_GetJobWorkerID( i );
if ( jobWorkerID != 0xFFFFFFFF )
{
Q_snprintf( query, sizeof( query ), "update "
"job_worker_start set WorkerState=%d, NumWorkUnits=%d where JobWorkerID=%lu",
VMPI_IsProcConnected( i ),
(int) VMPI_GetNumWorkUnitsCompleted( i ),
VMPI_GetJobWorkerID( i )
);
g_pSQL->Execute( query );
}
}
return 1;
}
};
class CSQLDBCommand_JobMasterEnd : public CSQLDBCommandBase
{
public:
virtual int RunCommand()
{
CMySQLQuery query;
query.Format( "insert into job_master_end values ( %lu, %d, %d, \"no errors\" )", g_JobPrimaryID, g_nWorkersConnected, g_nWorkersDisconnected );
query.Execute( g_pSQL );
// Now set RunningTimeMS.
unsigned long runningTimeMS = GetTickCount() - g_StatsStartTime;
query.Format( "update job_master_start set RunningTimeMS=%lu where JobID=%lu", runningTimeMS, g_JobPrimaryID );
query.Execute( g_pSQL );
return 1;
}
};
void UpdateJobWorkerRunningTime()
{
unsigned long runningTimeMS = GetTickCount() - g_StatsStartTime;
char curStage[256];
VMPI_GetCurrentStage( curStage, sizeof( curStage ) );
CMySQLQuery query;
query.Format( "update job_worker_start set RunningTimeMS=%lu, CurrentStage=\"%s\", "
"Thread0WU=%d, Thread1WU=%d, Thread2WU=%d, Thread3WU=%d where JobWorkerID=%lu",
runningTimeMS,
curStage,
(int) g_ThreadWUs[0],
(int) g_ThreadWUs[1],
(int) g_ThreadWUs[2],
(int) g_ThreadWUs[3],
g_JobWorkerID );
query.Execute( g_pSQL );
}
class CSQLDBCommand_GraphEntry : public CSQLDBCommandBase
{
public:
CSQLDBCommand_GraphEntry( DWORD msTime, DWORD nBytesSent, DWORD nBytesReceived )
{
m_msTime = msTime;
m_nBytesSent = nBytesSent;
m_nBytesReceived = nBytesReceived;
}
virtual int RunCommand()
{
CMySQLQuery query;
query.Format( "insert into graph_entry (JobWorkerID, MSSinceJobStart, BytesSent, BytesReceived) "
"values ( %lu, %lu, %lu, %lu )",
g_JobWorkerID,
m_msTime,
m_nBytesSent,
m_nBytesReceived );
query.Execute( g_pSQL );
UpdateJobWorkerRunningTime();
++g_CurrentMessageIndex;
return 1;
}
DWORD m_nBytesSent;
DWORD m_nBytesReceived;
DWORD m_msTime;
};
class CSQLDBCommand_TextMessage : public CSQLDBCommandBase
{
public:
CSQLDBCommand_TextMessage( const char *pText )
{
m_pText = FormatStringForSQL( pText );
}
virtual ~CSQLDBCommand_TextMessage()
{
delete [] m_pText;
}
virtual int RunCommand()
{
CMySQLQuery query;
query.Format( "insert into text_messages (JobWorkerID, MessageIndex, Text) values ( %lu, %lu, \"%s\" )", g_JobWorkerID, g_CurrentMessageIndex, m_pText );
query.Execute( g_pSQL );
++g_CurrentMessageIndex;
return 1;
}
char *m_pText;
};
// -------------------------------------------------------------------------------- //
// Internal helpers.
// -------------------------------------------------------------------------------- //
// This is the spew output before it has connected to the MySQL database.
CCriticalSection g_SpewTextCS;
CUtlVector<char> g_SpewText( 1024 );
class CLoggingListener_VMPIStats : public ILoggingListener
{
public:
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
{
CCriticalSectionLock csLock( &g_SpewTextCS );
csLock.Lock();
// Queue the text up so we can send it to the DB right away when we connect.
g_SpewText.AddMultipleToTail( strlen( pMessage ), pMessage );
csLock.Unlock();
}
};
CLoggingListener_VMPIStats g_VMPIStatsLoggingListener;
void PerfThread_SendSpewText()
{
// Send the spew text to the database.
CCriticalSectionLock csLock( &g_SpewTextCS );
csLock.Lock();
if ( g_SpewText.Count() > 0 )
{
g_SpewText.AddToTail( 0 );
if ( g_bMPI_StatsTextOutput )
{
g_pDB->AddCommandToQueue( new CSQLDBCommand_TextMessage( g_SpewText.Base() ), NULL );
}
else
{
// Just show one message in the vmpi_job_watch window to let them know that they need
// to use a command line option to get the output.
static bool bFirst = true;
if ( bFirst )
{
char msg[512];
V_snprintf( msg, sizeof( msg ), "%s not enabled", VMPI_GetParamString( mpi_Stats_TextOutput ) );
bFirst = false;
g_pDB->AddCommandToQueue( new CSQLDBCommand_TextMessage( msg ), NULL );
}
}
g_SpewText.RemoveAll();
}
csLock.Unlock();
}
void PerfThread_AddGraphEntry( DWORD startTicks, DWORD &lastSent, DWORD &lastReceived )
{
// Send the graph entry with data transmission info.
DWORD curSent = g_nBytesSent + g_nMulticastBytesSent;
DWORD curReceived = g_nBytesReceived + g_nMulticastBytesReceived;
g_pDB->AddCommandToQueue(
new CSQLDBCommand_GraphEntry(
GetTickCount() - startTicks,
curSent - lastSent,
curReceived - lastReceived ),
NULL );
lastSent = curSent;
lastReceived = curReceived;
}
// This function adds a graph_entry into the database periodically.
DWORD WINAPI PerfThreadFn( LPVOID pParameter )
{
DWORD lastSent = 0;
DWORD lastReceived = 0;
DWORD startTicks = GetTickCount();
while ( WaitForSingleObject( g_hPerfThreadExitEvent, 1000 ) != WAIT_OBJECT_0 )
{
PerfThread_AddGraphEntry( startTicks, lastSent, lastReceived );
// Send updates for text output.
PerfThread_SendSpewText();
// If we're the master, update all the worker stats.
if ( g_bMaster )
{
g_pDB->AddCommandToQueue(
new CSQLDBCommand_WorkerStats,
NULL );
}
}
// Add the remaining text and one last graph entry (which will include the current stage info).
PerfThread_SendSpewText();
PerfThread_AddGraphEntry( startTicks, lastSent, lastReceived );
SetEvent( g_hPerfThreadExitEvent );
return 0;
}
// -------------------------------------------------------------------------------- //
// VMPI_Stats interface.
// -------------------------------------------------------------------------------- //
void VMPI_Stats_InstallSpewHook()
{
LoggingSystem_RegisterLoggingListener( &g_VMPIStatsLoggingListener );
}
void UnloadMySQLWrapper()
{
if ( g_hMySQLDLL )
{
if ( g_pSQL )
{
g_pSQL->Release();
g_pSQL = NULL;
}
Sys_UnloadModule( g_hMySQLDLL );
g_hMySQLDLL = NULL;
}
}
bool LoadMySQLWrapper(
const char *pHostName,
const char *pDBName,
const char *pUserName
)
{
UnloadMySQLWrapper();
// Load the DLL and the interface.
if ( !Sys_LoadInterface( "mysql_wrapper", MYSQL_WRAPPER_VERSION_NAME, &g_hMySQLDLL, (void**)&g_pSQL ) )
return false;
// Try to init the database.
if ( !g_pSQL->InitMySQL( pDBName, pHostName, pUserName ) )
{
UnloadMySQLWrapper();
return false;
}
return true;
}
bool VMPI_Stats_Init_Master(
const char *pHostName,
const char *pDBName,
const char *pUserName,
const char *pBSPFilename,
unsigned long *pDBJobID )
{
Assert( !g_pDB );
g_bMaster = true;
// Connect the database.
g_pDB = new CMySqlDatabase;
if ( !g_pDB || !g_pDB->Initialize() || !LoadMySQLWrapper( pHostName, pDBName, pUserName ) )
{
delete g_pDB;
g_pDB = NULL;
return false;
}
DWORD size = sizeof( g_MachineName );
GetComputerName( g_MachineName, &size );
// Create the job_master_start row.
Q_FileBase( pBSPFilename, g_BSPFilename, sizeof( g_BSPFilename ) );
g_JobPrimaryID = 0;
CMySQLQuery query;
query.Format( "insert into job_master_start ( BSPFilename, StartTime, MachineName, RunningTimeMS ) values ( \"%s\", null, \"%s\", %lu )", g_BSPFilename, g_MachineName, RUNNINGTIME_MS_SENTINEL );
query.Execute( g_pSQL );
g_JobPrimaryID = g_pSQL->InsertID();
if ( g_JobPrimaryID == 0 )
{
delete g_pDB;
g_pDB = NULL;
return false;
}
// Now init the worker portion.
*pDBJobID = g_JobPrimaryID;
return VMPI_Stats_Init_Worker( NULL, NULL, NULL, g_JobPrimaryID );
}
bool VMPI_Stats_Init_Worker( const char *pHostName, const char *pDBName, const char *pUserName, unsigned long DBJobID )
{
g_StatsStartTime = GetTickCount();
// If pDBServerName is null, then we're the master and we just want to make the job_worker_start entry.
if ( pHostName )
{
Assert( !g_pDB );
// Connect the database.
g_pDB = new CMySqlDatabase;
if ( !g_pDB || !g_pDB->Initialize() || !LoadMySQLWrapper( pHostName, pDBName, pUserName ) )
{
delete g_pDB;
g_pDB = NULL;
return false;
}
// Get our machine name to store in the database.
DWORD size = sizeof( g_MachineName );
GetComputerName( g_MachineName, &size );
}
g_JobPrimaryID = DBJobID;
g_JobWorkerID = 0;
CMySQLQuery query;
query.Format( "insert into job_worker_start ( JobID, CurrentStage, IsMaster, MachineName ) values ( %lu, \"none\", %d, \"%s\" )",
g_JobPrimaryID, g_bMaster, g_MachineName );
query.Execute( g_pSQL );
g_JobWorkerID = g_pSQL->InsertID();
if ( g_JobWorkerID == 0 )
{
delete g_pDB;
g_pDB = NULL;
return false;
}
// Now create a thread that samples perf data and stores it in the database.
g_hPerfThreadExitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
g_hPerfThread = CreateThread(
NULL,
0,
PerfThreadFn,
NULL,
0,
&g_PerfThreadID );
return true;
}
void VMPI_Stats_Term()
{
if ( !g_pDB )
return;
// Stop the thread.
SetEvent( g_hPerfThreadExitEvent );
WaitForSingleObject( g_hPerfThread, INFINITE );
CloseHandle( g_hPerfThreadExitEvent );
g_hPerfThreadExitEvent = NULL;
CloseHandle( g_hPerfThread );
g_hPerfThread = NULL;
if ( g_bMaster )
{
// (Write a job_master_end entry here).
g_pDB->AddCommandToQueue( new CSQLDBCommand_JobMasterEnd, NULL );
}
// Wait for up to a second for the DB to finish writing its data.
DWORD startTime = GetTickCount();
while ( GetTickCount() - startTime < 1000 )
{
if ( g_pDB->QueriesInOutQueue() == 0 )
break;
}
delete g_pDB;
g_pDB = NULL;
UnloadMySQLWrapper();
}
static bool ReadStringFromFile( FILE *fp, char *pStr, int strSize )
{
int i=0;
for ( i; i < strSize-2; i++ )
{
if ( fread( &pStr[i], 1, 1, fp ) != 1 ||
pStr[i] == '\n' )
{
break;
}
}
pStr[i] = 0;
return i != 0;
}
// This looks for pDBInfoFilename in the same path as pBaseExeFilename.
// The file has 3 lines: machine name (with database), database name, username
void GetDBInfo( const char *pDBInfoFilename, CDBInfo *pInfo )
{
char baseExeFilename[512];
if ( !GetModuleFileName( GetModuleHandle( NULL ), baseExeFilename, sizeof( baseExeFilename ) ) )
Error( "GetModuleFileName failed." );
// Look for the info file in the same directory as the exe.
char dbInfoFilename[512];
Q_strncpy( dbInfoFilename, baseExeFilename, sizeof( dbInfoFilename ) );
Q_StripFilename( dbInfoFilename );
if ( dbInfoFilename[0] == 0 )
Q_strncpy( dbInfoFilename, ".", sizeof( dbInfoFilename ) );
Q_strncat( dbInfoFilename, "/", sizeof( dbInfoFilename ), COPY_ALL_CHARACTERS );
Q_strncat( dbInfoFilename, pDBInfoFilename, sizeof( dbInfoFilename ), COPY_ALL_CHARACTERS );
FILE *fp = fopen( dbInfoFilename, "rt" );
if ( !fp )
{
Error( "Can't open %s for database info.\n", dbInfoFilename );
}
if ( !ReadStringFromFile( fp, pInfo->m_HostName, sizeof( pInfo->m_HostName ) ) ||
!ReadStringFromFile( fp, pInfo->m_DBName, sizeof( pInfo->m_DBName ) ) ||
!ReadStringFromFile( fp, pInfo->m_UserName, sizeof( pInfo->m_UserName ) )
)
{
Error( "%s is not a valid database info file.\n", dbInfoFilename );
}
fclose( fp );
}
void RunJobWatchApp( char *pCmdLine )
{
STARTUPINFO si;
memset( &si, 0, sizeof( si ) );
si.cb = sizeof( si );
PROCESS_INFORMATION pi;
memset( &pi, 0, sizeof( pi ) );
// Working directory should be the same as our exe's directory.
char dirName[512];
if ( GetModuleFileName( NULL, dirName, sizeof( dirName ) ) != 0 )
{
char *s1 = V_strrchr( dirName, '\\' );
char *s2 = V_strrchr( dirName, '/' );
if ( s1 || s2 )
{
// Get rid of the last slash.
s1 = max( s1, s2 );
s1[0] = 0;
if ( !CreateProcess(
NULL,
pCmdLine,
NULL, // security
NULL,
TRUE,
0, // flags
NULL, // environment
dirName, // current directory
&si,
&pi ) )
{
Warning( "%s - error launching '%s'\n", VMPI_GetParamString( mpi_Job_Watch ), pCmdLine );
}
}
}
}
void StatsDB_InitStatsDatabase(
int argc,
char **argv,
const char *pDBInfoFilename )
{
// Did they disable the stats database?
if ( !g_bMPI_Stats && !VMPI_IsParamUsed( mpi_Job_Watch ) )
return;
unsigned long jobPrimaryID;
// Now open the DB.
if ( g_bMPIMaster )
{
CDBInfo dbInfo;
GetDBInfo( pDBInfoFilename, &dbInfo );
if ( !VMPI_Stats_Init_Master( dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName, argv[argc-1], &jobPrimaryID ) )
{
Warning( "VMPI_Stats_Init_Master( %s, %s, %s ) failed.\n", dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName );
// Tell the workers not to use stats.
dbInfo.m_HostName[0] = 0;
}
char cmdLine[2048];
Q_snprintf( cmdLine, sizeof( cmdLine ), "vmpi_job_watch -JobID %d", jobPrimaryID );
Msg( "\nTo watch this job, run this command line:\n%s\n\n", cmdLine );
if ( VMPI_IsParamUsed( mpi_Job_Watch ) )
{
// Convenience thing to automatically launch the job watch for this job.
RunJobWatchApp( cmdLine );
}
// Send the database info to all the workers.
SendDBInfo( &dbInfo, jobPrimaryID );
}
else
{
// Wait to get DB info so we can connect to the MySQL database.
CDBInfo dbInfo;
unsigned long jobPrimaryID;
RecvDBInfo( &dbInfo, &jobPrimaryID );
if ( dbInfo.m_HostName[0] != 0 )
{
if ( !VMPI_Stats_Init_Worker( dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName, jobPrimaryID ) )
Error( "VMPI_Stats_Init_Worker( %s, %s, %d ) failed.\n", dbInfo.m_HostName, dbInfo.m_DBName, dbInfo.m_UserName, jobPrimaryID );
}
}
}
unsigned long StatsDB_GetUniqueJobID()
{
return g_JobPrimaryID;
}
unsigned long VMPI_Stats_GetJobWorkerID()
{
return g_JobWorkerID;
}

59
utils/common/mpi_stats.h Normal file
View File

@@ -0,0 +1,59 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef MPI_STATS_H
#define MPI_STATS_H
#ifdef _WIN32
#pragma once
#endif
// The VMPI stats module reports a bunch of statistics to a MySQL server, and the
// stats can be used to trace and graph a compile session.
//
// Call this as soon as possible to initialize spew hooks.
void VMPI_Stats_InstallSpewHook();
//
// pDBServerName is the hostname (or dotted IP address) of the MySQL server to connect to.
// pBSPFilename is the last argument on the command line.
// pMachineIP is the dotted IP address of this machine.
// jobID is an 8-byte unique identifier for this job.
//
bool VMPI_Stats_Init_Master( const char *pHostName, const char *pDBName, const char *pUserName, const char *pBSPFilename, unsigned long *pDBJobID );
bool VMPI_Stats_Init_Worker( const char *pHostName, const char *pDBName, const char *pUserName, unsigned long DBJobID );
void VMPI_Stats_Term();
// Add a generic text event to the database.
void VMPI_Stats_AddEventText( const char *pText );
class CDBInfo
{
public:
char m_HostName[128];
char m_DBName[128];
char m_UserName[128];
};
// If you're the master, this loads pDBInfoFilename, sends that info to the workers, and
// connects to the database.
//
// If you're a worker, this waits for the DB info, then connects to the database.
void StatsDB_InitStatsDatabase(
int argc,
char **argv,
const char *pDBInfoFilename );
// The database gives back a unique ID for the job.
unsigned long StatsDB_GetUniqueJobID();
// Get the worker ID (used for the JobWorkerID fields in the database).
unsigned long VMPI_Stats_GetJobWorkerID();
#endif // MPI_STATS_H

930
utils/common/mstristrip.cpp Normal file
View File

@@ -0,0 +1,930 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
//-----------------------------------------------------------------------------
// FILE: TRISTRIP.CPP
//
// Desc: Xbox tristripper
//
// Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
// identifier was truncated to '255' characters in the debug information
#pragma warning(disable: 4786)
// conversion from 'double' to 'float'
#pragma warning(disable: 4244)
#pragma warning(disable: 4530)
#include <stdio.h>
#include <stdarg.h>
#include <algorithm>
#include <list>
#include <vector>
#include <assert.h>
#ifdef _DEBUG
#include <crtdbg.h>
#endif
#include "mstristrip.h"
using namespace std;
//=========================================================================
// structs
//=========================================================================
typedef vector<WORD> STRIPVERTS;
typedef list<STRIPVERTS *> STRIPLIST;
typedef WORD (*TRIANGLELIST)[3];
struct TRIANGLEINFO
{
int neighbortri[3];
int neighboredge[3];
};
// return true if strip starts clockwise
inline bool FIsStripCW(const STRIPVERTS &stripvertices)
{
// last index should have cw/ccw bool
return !!stripvertices[stripvertices.size() - 1];
}
// return length of strip
inline int StripLen(const STRIPVERTS &stripvertices)
{
return (int)stripvertices.size() - 1;
}
// free all stripverts and clear the striplist
inline void FreeStripListVerts(STRIPLIST *pstriplist)
{
STRIPLIST::iterator istriplist = pstriplist->begin();
while(istriplist != pstriplist->end())
{
STRIPVERTS *pstripverts = *istriplist;
delete pstripverts;
pstriplist->erase(istriplist++);
}
}
//=========================================================================
// main stripper class
//=========================================================================
class CStripper
{
public:
// ctors/dtors
CStripper(int numtris, TRIANGLELIST ptriangles);
~CStripper();
// initialize tri info
void InitTriangleInfo(int tri, int vert);
// get maximum length strip from tri/vert
int CreateStrip(int tri, int vert, int maxlen, int *pswaps,
bool flookahead, bool fstartcw, int *pstriptris, int *pstripverts);
// stripify entire mesh
void BuildStrips(STRIPLIST *pstriplist, int maxlen, bool flookahead);
// blast strip indices to ppstripindices
int CreateManyStrips(STRIPLIST *pstriplist, WORD **ppstripindices);
int CreateLongStrip(STRIPLIST *pstriplist, WORD **ppstripindices);
inline int GetNeighborCount(int tri)
{
int count = 0;
for(int vert = 0; vert < 3; vert++)
{
int neighbortri = m_ptriinfo[tri].neighbortri[vert];
count += (neighbortri != -1) && !m_pused[neighbortri];
}
return count;
}
// from callee
int m_numtris; // # tris
TRIANGLELIST m_ptriangles; // trilist
TRIANGLEINFO *m_ptriinfo; // tri edge, neighbor info
int *m_pused; // tri used flag
};
//=========================================================================
// vertex cache class
//=========================================================================
class CVertCache
{
public:
CVertCache()
{ Reset(); }
~CVertCache()
{};
// reset cache
void Reset()
{
m_iCachePtr = 0;
m_cachehits = 0;
memset(m_rgCache, 0xff, sizeof(m_rgCache));
}
// add vertindex to cache
bool Add(int strip, int vertindex);
int NumCacheHits() const
{ return m_cachehits; }
// enum { CACHE_SIZE = 10 };
enum { CACHE_SIZE = 18 };
private:
int m_cachehits; // current # of cache hits
WORD m_rgCache[CACHE_SIZE]; // vertex cache
int m_rgCacheStrip[CACHE_SIZE]; // strip # which added vert
int m_iCachePtr; // fifo ptr
};
//=========================================================================
// Get maximum length of strip starting at tri/vert
//=========================================================================
int CStripper::CreateStrip(int tri, int vert, int maxlen, int *pswaps,
bool flookahead, bool fstartcw, int *pstriptris, int *pstripverts)
{
*pswaps = 0;
// this guy has already been used?
if(m_pused[tri])
return 0;
// mark tri as used
m_pused[tri] = 1;
int swaps = 0;
// add first tri info
pstriptris[0] = tri;
pstriptris[1] = tri;
pstriptris[2] = tri;
if(fstartcw)
{
pstripverts[0] = (vert) % 3;
pstripverts[1] = (vert + 1) % 3;
pstripverts[2] = (vert + 2) % 3;
}
else
{
pstripverts[0] = (vert + 1) % 3;
pstripverts[1] = (vert + 0) % 3;
pstripverts[2] = (vert + 2) % 3;
}
fstartcw = !fstartcw;
// get next tri information
int edge = (fstartcw ? vert + 2 : vert + 1) % 3;
int nexttri = m_ptriinfo[tri].neighbortri[edge];
int nextvert = m_ptriinfo[tri].neighboredge[edge];
// start building the strip until we run out of room or indices
int stripcount;
for( stripcount = 3; stripcount < maxlen; stripcount++)
{
// dead end?
if(nexttri == -1 || m_pused[nexttri])
break;
// move to next tri
tri = nexttri;
vert = nextvert;
// toggle orientation
fstartcw = !fstartcw;
// find the next natural edge
int edge = (fstartcw ? vert + 2 : vert + 1) % 3;
nexttri = m_ptriinfo[tri].neighbortri[edge];
nextvert = m_ptriinfo[tri].neighboredge[edge];
bool fswap = false;
if(nexttri == -1 || m_pused[nexttri])
{
// if the next tri is a dead end - try swapping orientation
fswap = true;
}
else if(flookahead)
{
// try a swap and see who our new neighbor would be
int edgeswap = (fstartcw ? vert + 1 : vert + 2) % 3;
int nexttriswap = m_ptriinfo[tri].neighbortri[edgeswap];
int nextvertswap = m_ptriinfo[tri].neighboredge[edgeswap];
if(nexttriswap != -1 && !m_pused[nexttriswap])
{
assert(nexttri != -1);
// if the swap neighbor has a lower count, change directions
if(GetNeighborCount(nexttriswap) < GetNeighborCount(nexttri))
{
fswap = true;
}
else if(GetNeighborCount(nexttriswap) == GetNeighborCount(nexttri))
{
// if they have the same number of neighbors - check their neighbors
edgeswap = (fstartcw ? nextvertswap + 2 : nextvertswap + 1) % 3;
nexttriswap = m_ptriinfo[nexttriswap].neighbortri[edgeswap];
int edge1 = (fstartcw ? nextvert + 1 : nextvert + 2) % 3;
int nexttri1 = m_ptriinfo[nexttri].neighbortri[edge1];
if(nexttri1 == -1 || m_pused[nexttri1])
{
// natural winding order leads us to a dead end so turn
fswap = true;
}
else if(nexttriswap != -1 && !m_pused[nexttriswap])
{
// check neighbor counts on both directions and swap if it's better
if(GetNeighborCount(nexttriswap) < GetNeighborCount(nexttri1))
fswap = true;
}
}
}
}
if(fswap)
{
// we've been told to change directions so make sure we actually can
// and then add the swap vertex
int edgeswap = (fstartcw ? vert + 1 : vert + 2) % 3;
nexttri = m_ptriinfo[tri].neighbortri[edgeswap];
nextvert = m_ptriinfo[tri].neighboredge[edgeswap];
if(nexttri != -1 && !m_pused[nexttri])
{
pstriptris[stripcount] = pstriptris[stripcount - 2];
pstripverts[stripcount] = pstripverts[stripcount - 2];
stripcount++;
swaps++;
fstartcw = !fstartcw;
}
}
// record index information
pstriptris[stripcount] = tri;
pstripverts[stripcount] = (vert + 2) % 3;
// mark triangle as used
m_pused[tri] = 1;
}
// clear the used flags
for(int j = 2; j < stripcount; j++)
m_pused[pstriptris[j]] = 0;
// return swap count and striplen
*pswaps = swaps;
return stripcount;
}
//=========================================================================
// Given a striplist and current cache state, pick the best next strip
//=========================================================================
STRIPLIST::iterator FindBestCachedStrip(STRIPLIST *pstriplist,
const CVertCache &vertcachestate)
{
if(pstriplist->empty())
return pstriplist->end();
bool fFlipStrip = false;
int maxcachehits = -1;
STRIPLIST::iterator istriplistbest = pstriplist->begin();
int striplen = StripLen(**istriplistbest);
bool fstartcw = FIsStripCW(**istriplistbest);
// go through all the other strips looking for the best caching
for(STRIPLIST::iterator istriplist = pstriplist->begin();
istriplist != pstriplist->end();
++istriplist)
{
bool fFlip = false;
const STRIPVERTS &stripverts = **istriplist;
int striplennew = StripLen(stripverts);
// check cache if this strip is the same type as us (ie: cw/odd)
if((FIsStripCW(stripverts) == fstartcw) &&
((striplen & 0x1) == (striplennew & 0x1)))
{
// copy current state of cache
CVertCache vertcachenew = vertcachestate;
// figure out what this guy would do to our cache
for(int ivert = 0; ivert < striplennew; ivert++)
vertcachenew.Add(2, stripverts[ivert]);
// even length strip - see if better cache hits reversed
if(!(striplennew & 0x1))
{
CVertCache vertcacheflipped = vertcachestate;
for(int ivert = StripLen(stripverts) - 1; ivert >= 0; ivert--)
vertcacheflipped.Add(2, stripverts[ivert]);
if(vertcacheflipped.NumCacheHits() > vertcachenew.NumCacheHits())
{
vertcachenew = vertcacheflipped;
fFlip = true;
}
}
// record the best number of cache hits to date
int numcachehits = vertcachenew.NumCacheHits() - vertcachestate.NumCacheHits();
if(numcachehits > maxcachehits)
{
maxcachehits = numcachehits;
istriplistbest = istriplist;
fFlipStrip = fFlip;
}
}
}
if(fFlipStrip)
{
STRIPVERTS &stripverts = **istriplistbest;
STRIPVERTS::iterator vend = stripverts.end();
reverse(stripverts.begin(), --vend);
}
// make sure we keep the list in order and always pull off
// the first dude.
if(istriplistbest != pstriplist->begin())
swap(*istriplistbest, *pstriplist->begin());
return pstriplist->begin();
}
//=========================================================================
// Don't merge the strips - just blast em into the stripbuffer one by one
// (useful for debugging)
//=========================================================================
int CStripper::CreateManyStrips(STRIPLIST *pstriplist, WORD **ppstripindices)
{
// allow room for each of the strips size plus the final 0
int indexcount = (int)pstriplist->size() + 1;
// we're storing the strips in [size1 i1 i2 i3][size2 i4 i5 i6][0] format
STRIPLIST::iterator istriplist;
for( istriplist = pstriplist->begin(); istriplist != pstriplist->end(); ++istriplist)
{
// add striplength plus potential degenerate to swap ccw --> cw
indexcount += StripLen(**istriplist) + 1;
}
// alloc the space for all this stuff
WORD *pstripindices = new WORD [indexcount];
assert(pstripindices);
CVertCache vertcache;
int numstripindices = 0;
for(istriplist = pstriplist->begin();
!pstriplist->empty();
istriplist = FindBestCachedStrip(pstriplist, vertcache))
{
const STRIPVERTS &stripverts = **istriplist;
if(!FIsStripCW(stripverts))
{
// add an extra index if it's ccw
pstripindices[numstripindices++] = StripLen(stripverts) + 1;
pstripindices[numstripindices++] = stripverts[0];
}
else
{
// add the strip length
pstripindices[numstripindices++] = StripLen(stripverts);
}
// add all the strip indices
for(int i = 0; i < StripLen(stripverts); i++)
{
pstripindices[numstripindices++] = stripverts[i];
vertcache.Add(1, stripverts[i]);
}
// free this guy and pop him off the list
delete &stripverts;
pstriplist->pop_front();
}
// add terminating zero
pstripindices[numstripindices++] = 0;
*ppstripindices = pstripindices;
return numstripindices;
}
//=========================================================================
// Merge striplist into one big uberlist with (hopefully) optimal caching
//=========================================================================
int CStripper::CreateLongStrip(STRIPLIST *pstriplist, WORD **ppstripindices)
{
// allow room for one strip length plus a possible 3 extra indices per
// concatenated strip list plus the final 0
int indexcount = ((int)pstriplist->size() * 3) + 2;
// we're storing the strips in [size1 i1 i2 i3][size2 i4 i5 i6][0] format
STRIPLIST::iterator istriplist;
for( istriplist = pstriplist->begin(); istriplist != pstriplist->end(); ++istriplist)
{
indexcount += StripLen(**istriplist);
}
// alloc the space for all this stuff
WORD *pstripindices = new WORD [indexcount];
assert(pstripindices);
CVertCache vertcache;
int numstripindices = 0;
// add first strip
istriplist = pstriplist->begin();
const STRIPVERTS &stripverts = **istriplist;
// first strip should be cw
assert(FIsStripCW(stripverts));
for(int ivert = 0; ivert < StripLen(stripverts); ivert++)
{
pstripindices[numstripindices++] = stripverts[ivert];
vertcache.Add(1, stripverts[ivert]);
}
// kill first dude
delete &stripverts;
pstriplist->erase(istriplist);
// add all the others
while(pstriplist->size())
{
istriplist = FindBestCachedStrip(pstriplist, vertcache);
STRIPVERTS &stripverts = **istriplist;
short lastvert = pstripindices[numstripindices - 1];
short firstvert = stripverts[0];
if(firstvert != lastvert)
{
// add degenerate from last strip
pstripindices[numstripindices++] = lastvert;
// add degenerate from our strip
pstripindices[numstripindices++] = firstvert;
}
// if we're not orientated correctly, we need to add a degenerate
if(FIsStripCW(stripverts) != !(numstripindices & 0x1))
{
// This shouldn't happen - we're currently trying very hard
// to keep everything oriented correctly.
assert(false);
pstripindices[numstripindices++] = firstvert;
}
// add these verts
for(int ivert = 0; ivert < StripLen(stripverts); ivert++)
{
pstripindices[numstripindices++] = stripverts[ivert];
vertcache.Add(1, stripverts[ivert]);
}
// free these guys
delete &stripverts;
pstriplist->erase(istriplist);
}
*ppstripindices = pstripindices;
return numstripindices;
}
//=========================================================================
// Build a (hopefully) optimal set of strips from a trilist
//=========================================================================
void CStripper::BuildStrips(STRIPLIST *pstriplist, int maxlen, bool flookahead)
{
// temp indices storage
const int ctmpverts = 1024;
int pstripverts[ctmpverts + 1];
int pstriptris[ctmpverts + 1];
assert(maxlen <= ctmpverts);
// clear all the used flags for the tris
memset(m_pused, 0, sizeof(m_pused[0]) * m_numtris);
bool fstartcw = true;
for(;;)
{
int besttri = 0;
int bestvert = 0;
float bestratio = 2.0f;
int bestneighborcount = INT_MAX;
int tri;
for( tri = 0; tri < m_numtris; tri++)
{
// if used the continue
if(m_pused[tri])
continue;
// get the neighbor count
int curneightborcount = GetNeighborCount(tri);
assert(curneightborcount >= 0 && curneightborcount <= 3);
// push all the singletons to the very end
if(!curneightborcount)
curneightborcount = 4;
// if this guy has more neighbors than the current best - bail
if(curneightborcount > bestneighborcount)
continue;
// try starting the strip with each of this tris verts
for(int vert = 0; vert < 3; vert++)
{
int swaps;
int len = CreateStrip(tri, vert, maxlen, &swaps, flookahead,
fstartcw, pstriptris, pstripverts);
assert(len);
float ratio = (len == 3) ? 1.0f : (float)swaps / len;
// check if this ratio is better than what we've already got for
// this neighborcount
if((curneightborcount < bestneighborcount) ||
((curneightborcount == bestneighborcount) && (ratio < bestratio)))
{
bestneighborcount = curneightborcount;
besttri = tri;
bestvert = vert;
bestratio = ratio;
}
}
}
// no strips found?
if(bestneighborcount == INT_MAX)
break;
// recreate this strip
int swaps;
int len = CreateStrip(besttri, bestvert, maxlen,
&swaps, flookahead, fstartcw, pstriptris, pstripverts);
assert(len);
// mark the tris on the best strip as used
for(tri = 0; tri < len; tri++)
m_pused[pstriptris[tri]] = 1;
// create a new STRIPVERTS and stuff in the indices
STRIPVERTS *pstripvertices = new STRIPVERTS(len + 1);
assert(pstripvertices);
// store orientation in first entry
for(tri = 0; tri < len; tri++)
(*pstripvertices)[tri] = m_ptriangles[pstriptris[tri]][pstripverts[tri]];
(*pstripvertices)[len] = fstartcw;
// store the STRIPVERTS
pstriplist->push_back(pstripvertices);
// if strip was odd - swap orientation
if((len & 0x1))
fstartcw = !fstartcw;
}
#ifdef _DEBUG
// make sure all tris are used
for(int t = 0; t < m_numtris; t++)
assert(m_pused[t]);
#endif
}
//=========================================================================
// Guesstimate on the total index count for this list of strips
//=========================================================================
int EstimateStripCost(STRIPLIST *pstriplist)
{
int count = 0;
for(STRIPLIST::iterator istriplist = pstriplist->begin();
istriplist != pstriplist->end();
++istriplist)
{
// add count of indices
count += StripLen(**istriplist);
}
// assume 2 indices per strip to tack all these guys together
return count + ((int)pstriplist->size() - 1) * 2;
}
//=========================================================================
// Initialize triangle information (edges, #neighbors, etc.)
//=========================================================================
void CStripper::InitTriangleInfo(int tri, int vert)
{
WORD *ptriverts = &m_ptriangles[tri + 1][0];
int vert1 = m_ptriangles[tri][(vert + 1) % 3];
int vert2 = m_ptriangles[tri][vert];
for(int itri = tri + 1; itri < m_numtris; itri++, ptriverts += 3)
{
if(m_pused[itri] != 0x7)
{
for(int ivert = 0; ivert < 3; ivert++)
{
if((ptriverts[ivert] == vert1) &&
(ptriverts[(ivert + 1) % 3] == vert2))
{
// add the triangle info
m_ptriinfo[tri].neighbortri[vert] = itri;
m_ptriinfo[tri].neighboredge[vert] = ivert;
m_pused[tri] |= (1 << vert);
m_ptriinfo[itri].neighbortri[ivert] = tri;
m_ptriinfo[itri].neighboredge[ivert] = vert;
m_pused[itri] |= (1 << ivert);
return;
}
}
}
}
}
//=========================================================================
// CStripper ctor
//=========================================================================
CStripper::CStripper(int numtris, TRIANGLELIST ptriangles)
{
// store trilist info
m_numtris = numtris;
m_ptriangles = ptriangles;
m_pused = new int[numtris];
assert(m_pused);
m_ptriinfo = new TRIANGLEINFO[numtris];
assert(m_ptriinfo);
// init triinfo
int itri;
for( itri = 0; itri < numtris; itri++)
{
m_ptriinfo[itri].neighbortri[0] = -1;
m_ptriinfo[itri].neighbortri[1] = -1;
m_ptriinfo[itri].neighbortri[2] = -1;
}
// clear the used flag
memset(m_pused, 0, sizeof(m_pused[0]) * m_numtris);
// go through all the triangles and find edges, neighbor counts
for(itri = 0; itri < numtris; itri++)
{
for(int ivert = 0; ivert < 3; ivert++)
{
if(!(m_pused[itri] & (1 << ivert)))
InitTriangleInfo(itri, ivert);
}
}
// clear the used flags from InitTriangleInfo
memset(m_pused, 0, sizeof(m_pused[0]) * m_numtris);
}
//=========================================================================
// CStripper dtor
//=========================================================================
CStripper::~CStripper()
{
// free stuff
delete [] m_pused;
m_pused = NULL;
delete [] m_ptriinfo;
m_ptriinfo = NULL;
}
//=========================================================================
// Add an index to the cache - returns true if it was added, false otherwise
//=========================================================================
bool CVertCache::Add(int strip, int vertindex)
{
// find index in cache
for(int iCache = 0; iCache < CACHE_SIZE; iCache++)
{
if(vertindex == m_rgCache[iCache])
{
// if it's in the cache and it's from a different strip
// change the strip to the new one and count the cache hit
if(strip != m_rgCacheStrip[iCache])
{
m_cachehits++;
m_rgCacheStrip[iCache] = strip;
return true;
}
// we added this item to the cache earlier - carry on
return false;
}
}
// not in cache, add vert and strip
m_rgCache[m_iCachePtr] = vertindex;
m_rgCacheStrip[m_iCachePtr] = strip;
m_iCachePtr = (m_iCachePtr + 1) % CACHE_SIZE;
return true;
}
#ifdef _DEBUG
//=========================================================================
// Turn on c runtime leak checking, etc.
//=========================================================================
void EnableLeakChecking()
{
int flCrtDbgFlags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
flCrtDbgFlags &=
~(_CRTDBG_LEAK_CHECK_DF |
_CRTDBG_CHECK_ALWAYS_DF |
_CRTDBG_DELAY_FREE_MEM_DF);
// always check for memory leaks
flCrtDbgFlags |= _CRTDBG_LEAK_CHECK_DF;
// others you may / may not want to set
flCrtDbgFlags |= _CRTDBG_CHECK_ALWAYS_DF;
flCrtDbgFlags |= _CRTDBG_DELAY_FREE_MEM_DF;
_CrtSetDbgFlag(flCrtDbgFlags);
// all types of reports go via OutputDebugString
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
// big errors and asserts get their own assert window
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_WNDW);
// _CrtSetBreakAlloc(0);
}
#endif
//=========================================================================
// Main Stripify routine
//=========================================================================
int Stripify(int numtris, WORD *ptriangles, int *pnumindices, WORD **ppstripindices)
{
if(!numtris || !ptriangles)
return 0;
#ifdef _DEBUG
// EnableLeakChecking();
#endif
CStripper stripper(numtris, (TRIANGLELIST)ptriangles);
// map of various args to try stripifying mesh with
struct ARGMAP
{
int maxlen; // maximum length of strips
bool flookahead; // use sgi greedy lookahead (or not)
} rgargmap[] =
{
{ 1024, true },
{ 1024, false },
};
static const int cargmaps = sizeof(rgargmap) / sizeof(rgargmap[0]);
STRIPLIST striplistbest;
int bestlistcost = 0;
for(int imap = 0; imap < cargmaps; imap++)
{
STRIPLIST striplist;
// build the strip with the various args
stripper.BuildStrips(&striplist, rgargmap[imap].maxlen,
rgargmap[imap].flookahead);
// guesstimate the list cost and store it if it's good
int listcost = EstimateStripCost(&striplist);
if(!bestlistcost || (listcost < bestlistcost))
{
// free the old best list
FreeStripListVerts(&striplistbest);
// store the new best list
striplistbest = striplist;
bestlistcost = listcost;
assert(bestlistcost > 0);
}
else
{
FreeStripListVerts(&striplist);
}
}
#ifdef NEVER
// Return the strips in [size1 i1 i2 i3][size2 i4 i5 i6]...[0] format
// Very useful for debugging...
return stripper.CreateManyStrips(&striplistbest, ppstripindices);
#endif // NEVER
// return one big long strip
int numindices = stripper.CreateLongStrip(&striplistbest, ppstripindices);
if(pnumindices)
*pnumindices = numindices;
return numindices;
}
//=========================================================================
// Class used to vertices for locality of access.
//=========================================================================
struct SortEntry
{
public:
int iFirstUsed;
int iOrigIndex;
bool operator<(const SortEntry& rhs)
{
return iFirstUsed < rhs.iFirstUsed;
}
};
//=========================================================================
// Reorder the vertices
//=========================================================================
void ComputeVertexPermutation(int numstripindices, WORD* pstripindices,
int* pnumverts, WORD** ppvertexpermutation)
{
// Sort verts to maximize locality.
SortEntry* pSortTable = new SortEntry[*pnumverts];
// Fill in original index.
int i;
for( i = 0; i < *pnumverts; i++)
{
pSortTable[i].iOrigIndex = i;
pSortTable[i].iFirstUsed = -1;
}
// Fill in first used flag.
for(i = 0; i < numstripindices; i++)
{
int index = pstripindices[i];
if(pSortTable[index].iFirstUsed == -1)
pSortTable[index].iFirstUsed = i;
}
// Sort the table.
sort(pSortTable, pSortTable + *pnumverts);
// Copy re-mapped to orignal vertex permutaion into output array.
*ppvertexpermutation = new WORD[*pnumverts];
for(i = 0; i < *pnumverts; i++)
{
(*ppvertexpermutation)[i] = pSortTable[i].iOrigIndex;
}
// Build original to re-mapped permutation.
WORD* pInversePermutation = new WORD[numstripindices];
for(i = 0; i < *pnumverts; i++)
{
pInversePermutation[pSortTable[i].iOrigIndex] = i;
}
// We need to remap indices as well.
for(i = 0; i < numstripindices; i++)
{
pstripindices[i] = pInversePermutation[pstripindices[i]];
}
delete[] pSortTable;
delete[] pInversePermutation;
}

43
utils/common/mstristrip.h Normal file
View File

@@ -0,0 +1,43 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
//-----------------------------------------------------------------------------
// FILE: TRISTRIP.H
//
// Desc: tristrip header file
//
// Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
typedef unsigned short WORD;
//
// Main Stripify routine. Returns number of strip indices contained
// in ppstripindices. Caller must delete [] ppstripindices.
//
int Stripify(
int numtris, // Number of triangles
WORD *ptriangles, // triangle indices pointer
int *pnumindices, // number of indices in ppstripindices (out)
WORD **ppstripindices // triangle strip indices
);
//
// Re-arrange vertices so that they occur in the order that they are first
// used. This function doesn't actually move vertex data around, it returns
// an array that specifies where in the new vertex array each old vertex
// should go. It also re-maps the strip indices to use the new vertex
// locations. Caller must delete [] pVertexPermutation.
//
void ComputeVertexPermutation
(
int numstripindices, // Number of strip indices
WORD *pstripindices, // Strip indices
int *pnumverts, // Number of verts (in and out)
WORD **ppvertexpermutation // Map from orignal index to remapped index
);

62
utils/common/pacifier.cpp Normal file
View File

@@ -0,0 +1,62 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include "basetypes.h"
#include "pacifier.h"
#include "tier0/dbg.h"
static int g_LastPacifierDrawn = -1;
static bool g_bPacifierSuppressed = false;
void StartPacifier( char const *pPrefix )
{
Msg( "%s", pPrefix );
g_LastPacifierDrawn = -1;
UpdatePacifier( 0.001f );
}
void UpdatePacifier( float flPercent )
{
int iCur = (int)(flPercent * 40.0f);
iCur = clamp( iCur, g_LastPacifierDrawn, 40 );
if( iCur != g_LastPacifierDrawn && !g_bPacifierSuppressed )
{
for( int i=g_LastPacifierDrawn+1; i <= iCur; i++ )
{
if ( !( i % 4 ) )
{
Msg("%d", i/4);
}
else
{
if( i != 40 )
{
Msg(".");
}
}
}
g_LastPacifierDrawn = iCur;
}
}
void EndPacifier( bool bCarriageReturn )
{
UpdatePacifier(1);
if( bCarriageReturn && !g_bPacifierSuppressed )
Msg("\n");
}
void SuppressPacifier( bool bSuppress )
{
g_bPacifierSuppressed = bSuppress;
}

23
utils/common/pacifier.h Normal file
View File

@@ -0,0 +1,23 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef PACIFIER_H
#define PACIFIER_H
#ifdef _WIN32
#pragma once
#endif
// Use these to display a pacifier like:
// ProcessBlock_Thread: 0...1...2...3...4...5...6...7...8...9... (0)
void StartPacifier( char const *pPrefix ); // Prints the prefix and resets the pacifier
void UpdatePacifier( float flPercent ); // percent value between 0 and 1.
void EndPacifier( bool bCarriageReturn = true ); // Completes pacifier as if 100% was done
void SuppressPacifier( bool bSuppress = true ); // Suppresses pacifier updates if another thread might still be firing them
#endif // PACIFIER_H

31
utils/common/physdll.cpp Normal file
View File

@@ -0,0 +1,31 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include <stdio.h>
#include "physdll.h"
#include "filesystem_tools.h"
static CSysModule *pPhysicsModule = NULL;
CreateInterfaceFn GetPhysicsFactory( void )
{
if ( !pPhysicsModule )
{
pPhysicsModule = g_pFullFileSystem->LoadModule( "VPHYSICS.DLL" );
if ( !pPhysicsModule )
return NULL;
}
return Sys_GetFactory( pPhysicsModule );
}
void PhysicsDLLPath( const char *pPathname )
{
if ( !pPhysicsModule )
{
pPhysicsModule = g_pFullFileSystem->LoadModule( pPathname );
}
}

30
utils/common/physdll.h Normal file
View File

@@ -0,0 +1,30 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef PHYSDLL_H
#define PHYSDLL_H
#pragma once
#ifdef __cplusplus
#include "vphysics_interface.h"
class IPhysics;
class IPhysicsCollision;
extern CreateInterfaceFn GetPhysicsFactory( void );
extern "C" {
#endif
// tools need to force the path
void PhysicsDLLPath( const char *pPathname );
#ifdef __cplusplus
}
#endif
#endif // PHYSDLL_H

915
utils/common/polylib.cpp Normal file
View File

@@ -0,0 +1,915 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cmdlib.h"
#include "mathlib/mathlib.h"
#include "polylib.h"
#include "worldsize.h"
#include "threads.h"
#include "tier0/dbg.h"
// doesn't seem to need to be here? -- in threads.h
//extern int numthreads;
// counters are only bumped when running single threaded,
// because they are an awefull coherence problem
int c_active_windings;
int c_peak_windings;
int c_winding_allocs;
int c_winding_points;
void pw(winding_t *w)
{
int i;
for (i=0 ; i<w->numpoints ; i++)
printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
}
winding_t *winding_pool[MAX_POINTS_ON_WINDING+4];
/*
=============
AllocWinding
=============
*/
winding_t *AllocWinding (int points)
{
winding_t *w;
if (numthreads == 1)
{
c_winding_allocs++;
c_winding_points += points;
c_active_windings++;
if (c_active_windings > c_peak_windings)
c_peak_windings = c_active_windings;
}
ThreadLock();
if (winding_pool[points])
{
w = winding_pool[points];
winding_pool[points] = w->next;
}
else
{
w = (winding_t *)malloc(sizeof(*w));
w->p = (Vector *)calloc( points, sizeof(Vector) );
}
ThreadUnlock();
w->numpoints = 0; // None are occupied yet even though allocated.
w->maxpoints = points;
w->next = NULL;
return w;
}
void FreeWinding (winding_t *w)
{
if (w->numpoints == 0xdeaddead)
Error ("FreeWinding: freed a freed winding");
ThreadLock();
w->numpoints = 0xdeaddead; // flag as freed
w->next = winding_pool[w->maxpoints];
winding_pool[w->maxpoints] = w;
ThreadUnlock();
}
/*
============
RemoveColinearPoints
============
*/
int c_removed;
void RemoveColinearPoints (winding_t *w)
{
int i, j, k;
Vector v1, v2;
int nump;
Vector p[MAX_POINTS_ON_WINDING];
nump = 0;
for (i=0 ; i<w->numpoints ; i++)
{
j = (i+1)%w->numpoints;
k = (i+w->numpoints-1)%w->numpoints;
VectorSubtract (w->p[j], w->p[i], v1);
VectorSubtract (w->p[i], w->p[k], v2);
VectorNormalize(v1);
VectorNormalize(v2);
if (DotProduct(v1, v2) < 0.999)
{
VectorCopy (w->p[i], p[nump]);
nump++;
}
}
if (nump == w->numpoints)
return;
if (numthreads == 1)
c_removed += w->numpoints - nump;
w->numpoints = nump;
memcpy (w->p, p, nump*sizeof(p[0]));
}
/*
============
WindingPlane
============
*/
void WindingPlane (winding_t *w, Vector &normal, vec_t *dist)
{
Vector v1, v2;
VectorSubtract (w->p[1], w->p[0], v1);
// HACKHACK: Avoid potentially collinear verts
if ( w->numpoints > 3 )
{
VectorSubtract (w->p[3], w->p[0], v2);
}
else
{
VectorSubtract (w->p[2], w->p[0], v2);
}
CrossProduct (v2, v1, normal);
VectorNormalize (normal);
*dist = DotProduct (w->p[0], normal);
}
/*
=============
WindingArea
=============
*/
vec_t WindingArea(winding_t *w)
{
int i;
Vector d1, d2, cross;
vec_t total;
total = 0;
for (i=2 ; i<w->numpoints ; i++)
{
VectorSubtract (w->p[i-1], w->p[0], d1);
VectorSubtract (w->p[i], w->p[0], d2);
CrossProduct (d1, d2, cross);
total += VectorLength ( cross );
}
return total * 0.5;
}
void WindingBounds (winding_t *w, Vector &mins, Vector &maxs)
{
vec_t v;
int i,j;
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
for (i=0 ; i<w->numpoints ; i++)
{
for (j=0 ; j<3 ; j++)
{
v = w->p[i][j];
if (v < mins[j])
mins[j] = v;
if (v > maxs[j])
maxs[j] = v;
}
}
}
/*
=============
WindingCenter
=============
*/
void WindingCenter (winding_t *w, Vector &center)
{
int i;
float scale;
VectorCopy (vec3_origin, center);
for (i=0 ; i<w->numpoints ; i++)
VectorAdd (w->p[i], center, center);
scale = 1.0/w->numpoints;
VectorScale (center, scale, center);
}
/*
=============
WindingCenter
=============
*/
vec_t WindingAreaAndBalancePoint( winding_t *w, Vector &center )
{
int i;
Vector d1, d2, cross;
vec_t total;
VectorCopy (vec3_origin, center);
if ( !w )
return 0.0f;
total = 0;
for (i=2 ; i<w->numpoints ; i++)
{
VectorSubtract (w->p[i-1], w->p[0], d1);
VectorSubtract (w->p[i], w->p[0], d2);
CrossProduct (d1, d2, cross);
float area = VectorLength ( cross );
total += area;
// center of triangle, weighed by area
VectorMA( center, area / 3.0, w->p[i-1], center );
VectorMA( center, area / 3.0, w->p[i], center );
VectorMA( center, area / 3.0, w->p[0], center );
}
if (total)
{
VectorScale( center, 1.0 / total, center );
}
return total * 0.5;
}
/*
=================
BaseWindingForPlane
=================
*/
winding_t *BaseWindingForPlane (const Vector &normal, vec_t dist)
{
int i, x;
vec_t max, v;
Vector org, vright, vup;
winding_t *w;
// find the major axis
max = -1;
x = -1;
for (i=0 ; i<3; i++)
{
v = fabs(normal[i]);
if (v > max)
{
x = i;
max = v;
}
}
if (x==-1)
Error ("BaseWindingForPlane: no axis found");
VectorCopy (vec3_origin, vup);
switch (x)
{
case 0:
case 1:
vup[2] = 1;
break;
case 2:
vup[0] = 1;
break;
}
v = DotProduct (vup, normal);
VectorMA (vup, -v, normal, vup);
VectorNormalize (vup);
VectorScale (normal, dist, org);
CrossProduct (vup, normal, vright);
VectorScale (vup, (MAX_COORD_INTEGER*4), vup);
VectorScale (vright, (MAX_COORD_INTEGER*4), vright);
// project a really big axis aligned box onto the plane
w = AllocWinding (4);
VectorSubtract (org, vright, w->p[0]);
VectorAdd (w->p[0], vup, w->p[0]);
VectorAdd (org, vright, w->p[1]);
VectorAdd (w->p[1], vup, w->p[1]);
VectorAdd (org, vright, w->p[2]);
VectorSubtract (w->p[2], vup, w->p[2]);
VectorSubtract (org, vright, w->p[3]);
VectorSubtract (w->p[3], vup, w->p[3]);
w->numpoints = 4;
return w;
}
/*
==================
CopyWinding
==================
*/
winding_t *CopyWinding (winding_t *w)
{
int size;
winding_t *c;
c = AllocWinding (w->numpoints);
c->numpoints = w->numpoints;
size = w->numpoints*sizeof(w->p[0]);
memcpy (c->p, w->p, size);
return c;
}
/*
==================
ReverseWinding
==================
*/
winding_t *ReverseWinding (winding_t *w)
{
int i;
winding_t *c;
c = AllocWinding (w->numpoints);
for (i=0 ; i<w->numpoints ; i++)
{
VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
}
c->numpoints = w->numpoints;
return c;
}
// BUGBUG: Hunt this down - it's causing CSG errors
#pragma optimize("g", off)
/*
=============
ClipWindingEpsilon
=============
*/
void ClipWindingEpsilon (winding_t *in, const Vector &normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back)
{
vec_t dists[MAX_POINTS_ON_WINDING+4];
int sides[MAX_POINTS_ON_WINDING+4];
int counts[3];
vec_t dot;
int i, j;
Vector mid = vec3_origin;
winding_t *f, *b;
int maxpts;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->p[i], normal);
dot -= dist;
dists[i] = dot;
if (dot > epsilon)
sides[i] = SIDE_FRONT;
else if (dot < -epsilon)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
*front = *back = NULL;
if (!counts[0])
{
*back = CopyWinding (in);
return;
}
if (!counts[1])
{
*front = CopyWinding (in);
return;
}
maxpts = in->numpoints+4; // cant use counts[0]+2 because
// of fp grouping errors
*front = f = AllocWinding (maxpts);
*back = b = AllocWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
Vector& p1 = in->p[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
}
if (sides[i] == SIDE_BACK)
{
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
Vector& p2 = in->p[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (normal[j] == 1)
mid[j] = dist;
else if (normal[j] == -1)
mid[j] = -dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (mid, b->p[b->numpoints]);
b->numpoints++;
}
if (f->numpoints > maxpts || b->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
}
#pragma optimize("", on)
// NOTE: This is identical to ClipWindingEpsilon, but it does a pre/post translation to improve precision
void ClipWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, vec_t epsilon, winding_t **front, winding_t **back, const Vector &offset )
{
TranslateWinding( in, offset );
ClipWindingEpsilon( in, normal, dist+DotProduct(offset,normal), epsilon, front, back );
TranslateWinding( in, -offset );
if ( front && *front )
{
TranslateWinding( *front, -offset );
}
if ( back && *back )
{
TranslateWinding( *back, -offset );
}
}
void ClassifyWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, vec_t epsilon, winding_t **front, winding_t **back, winding_t **on, const Vector &offset)
{
TranslateWinding( in, offset );
ClassifyWindingEpsilon( in, normal, dist+DotProduct(offset,normal), epsilon, front, back, on );
TranslateWinding( in, -offset );
if ( front && *front )
{
TranslateWinding( *front, -offset );
}
if ( back && *back )
{
TranslateWinding( *back, -offset );
}
if ( on && *on )
{
TranslateWinding( *on, -offset );
}
}
/*
=============
ClassifyWindingEpsilon
=============
*/
// This version returns the winding as "on" if all verts lie in the plane
void ClassifyWindingEpsilon( winding_t *in, const Vector &normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back, winding_t **on)
{
vec_t dists[MAX_POINTS_ON_WINDING+4];
int sides[MAX_POINTS_ON_WINDING+4];
int counts[3];
vec_t dot;
int i, j;
Vector mid = vec3_origin;
winding_t *f, *b;
int maxpts;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->p[i], normal);
dot -= dist;
dists[i] = dot;
if (dot > epsilon)
sides[i] = SIDE_FRONT;
else if (dot < -epsilon)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
*front = *back = *on = NULL;
if ( !counts[0] && !counts[1] )
{
*on = CopyWinding(in);
return;
}
if (!counts[0])
{
*back = CopyWinding(in);
return;
}
if (!counts[1])
{
*front = CopyWinding(in);
return;
}
maxpts = in->numpoints+4; // cant use counts[0]+2 because
// of fp grouping errors
*front = f = AllocWinding (maxpts);
*back = b = AllocWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
Vector& p1 = in->p[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
}
if (sides[i] == SIDE_BACK)
{
VectorCopy (p1, b->p[b->numpoints]);
b->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
Vector& p2 = in->p[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (normal[j] == 1)
mid[j] = dist;
else if (normal[j] == -1)
mid[j] = -dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, f->p[f->numpoints]);
f->numpoints++;
VectorCopy (mid, b->p[b->numpoints]);
b->numpoints++;
}
if (f->numpoints > maxpts || b->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
}
/*
=============
ChopWindingInPlace
=============
*/
void ChopWindingInPlace (winding_t **inout, const Vector &normal, vec_t dist, vec_t epsilon)
{
winding_t *in;
vec_t dists[MAX_POINTS_ON_WINDING+4];
int sides[MAX_POINTS_ON_WINDING+4];
int counts[3];
vec_t dot;
int i, j;
Vector mid = vec3_origin;
winding_t *f;
int maxpts;
in = *inout;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->p[i], normal);
dot -= dist;
dists[i] = dot;
if (dot > epsilon)
{
sides[i] = SIDE_FRONT;
}
else if (dot < -epsilon)
{
sides[i] = SIDE_BACK;
}
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
if (!counts[0])
{
FreeWinding (in);
*inout = NULL;
return;
}
if (!counts[1])
return; // inout stays the same
maxpts = in->numpoints+4; // cant use counts[0]+2 because
// of fp grouping errors
f = AllocWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
Vector& p1 = in->p[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, f->p[f->numpoints]);
f->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
Vector& p2 = in->p[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (normal[j] == 1)
mid[j] = dist;
else if (normal[j] == -1)
mid[j] = -dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, f->p[f->numpoints]);
f->numpoints++;
}
if (f->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
if (f->numpoints > MAX_POINTS_ON_WINDING)
Error ("ClipWinding: MAX_POINTS_ON_WINDING");
FreeWinding (in);
*inout = f;
}
/*
=================
ChopWinding
Returns the fragment of in that is on the front side
of the cliping plane. The original is freed.
=================
*/
winding_t *ChopWinding (winding_t *in, const Vector &normal, vec_t dist)
{
winding_t *f, *b;
ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
FreeWinding (in);
if (b)
FreeWinding (b);
return f;
}
/*
=================
CheckWinding
=================
*/
void CheckWinding (winding_t *w)
{
int i, j;
vec_t d, edgedist;
Vector dir, edgenormal, facenormal;
vec_t area;
vec_t facedist;
if (w->numpoints < 3)
Error ("CheckWinding: %i points",w->numpoints);
area = WindingArea(w);
if (area < 1)
Error ("CheckWinding: %f area", area);
WindingPlane (w, facenormal, &facedist);
for (i=0 ; i<w->numpoints ; i++)
{
Vector& p1 = w->p[i];
for (j=0 ; j<3 ; j++)
{
if (p1[j] > MAX_COORD_INTEGER || p1[j] < MIN_COORD_INTEGER)
Error ("CheckFace: out of range: %f",p1[j]);
}
j = i+1 == w->numpoints ? 0 : i+1;
// check the point is on the face plane
d = DotProduct (p1, facenormal) - facedist;
if (d < -ON_EPSILON || d > ON_EPSILON)
Error ("CheckWinding: point off plane");
// check the edge isnt degenerate
Vector& p2 = w->p[j];
VectorSubtract (p2, p1, dir);
if (VectorLength (dir) < ON_EPSILON)
Error ("CheckWinding: degenerate edge");
CrossProduct (facenormal, dir, edgenormal);
VectorNormalize (edgenormal);
edgedist = DotProduct (p1, edgenormal);
edgedist += ON_EPSILON;
// all other points must be on front side
for (j=0 ; j<w->numpoints ; j++)
{
if (j == i)
continue;
d = DotProduct (w->p[j], edgenormal);
if (d > edgedist)
Error ("CheckWinding: non-convex");
}
}
}
/*
============
WindingOnPlaneSide
============
*/
int WindingOnPlaneSide (winding_t *w, const Vector &normal, vec_t dist)
{
qboolean front, back;
int i;
vec_t d;
front = false;
back = false;
for (i=0 ; i<w->numpoints ; i++)
{
d = DotProduct (w->p[i], normal) - dist;
if (d < -ON_EPSILON)
{
if (front)
return SIDE_CROSS;
back = true;
continue;
}
if (d > ON_EPSILON)
{
if (back)
return SIDE_CROSS;
front = true;
continue;
}
}
if (back)
return SIDE_BACK;
if (front)
return SIDE_FRONT;
return SIDE_ON;
}
//-----------------------------------------------------------------------------
// Purpose: 2d point inside of winding test (assumes the point resides in the
// winding plane)
//-----------------------------------------------------------------------------
bool PointInWinding( const Vector &pt, winding_t *pWinding )
{
if( !pWinding )
return false;
#if 0
//
// NOTE: this will be a quicker way to calculate this, however I don't
// know the trick off hand (post dot product tests??)
// TODO: look in graphics gems!!!! (cab)
//
Vector edge1, edge2;
for( int ndxPt = 0; ndxPt < pWinding->numpoints; ndxPt++ )
{
edge1 = pWinding->p[ndxPt] - pt;
edge2 = pWinding->p[(ndxPt+1)%pWinding->numpoints] - pt;
VectorNormalize( edge1 );
VectorNormalize( edge2 );
if( edge2.Dot( edge1 ) < 0.0f )
return false;
}
return true;
#else
Vector edge, toPt, cross, testCross;
//
// get the first normal to test
//
toPt = pt - pWinding->p[0];
edge = pWinding->p[1] - pWinding->p[0];
testCross = edge.Cross( toPt );
VectorNormalize( testCross );
for( int ndxPt = 1; ndxPt < pWinding->numpoints; ndxPt++ )
{
toPt = pt - pWinding->p[ndxPt];
edge = pWinding->p[(ndxPt+1)%pWinding->numpoints] - pWinding->p[ndxPt];
cross = edge.Cross( toPt );
VectorNormalize( cross );
if( cross.Dot( testCross ) < 0.0f )
return false;
}
return true;
#endif
}
void TranslateWinding( winding_t *pWinding, const Vector &offset )
{
for ( int i = 0; i < pWinding->numpoints; i++ )
{
pWinding->p[i] += offset;
}
}

78
utils/common/polylib.h Normal file
View File

@@ -0,0 +1,78 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef POLYLIB_H
#define POLYLIB_H
#pragma once
#ifndef MATHLIB_H
#include "mathlib/mathlib.h"
#endif
struct winding_t
{
int numpoints;
Vector *p; // variable sized
int maxpoints;
winding_t *next;
};
#define MAX_POINTS_ON_WINDING 64
// you can define on_epsilon in the makefile as tighter
// point on plane side epsilon
// todo: need a world-space epsilon, a lightmap-space epsilon, and a texture space epsilon
// or at least convert from a world-space epsilon to lightmap and texture space epsilons
#ifndef ON_EPSILON
#define ON_EPSILON 0.1
#endif
winding_t *AllocWinding (int points);
vec_t WindingArea (winding_t *w);
void WindingCenter (winding_t *w, Vector &center);
vec_t WindingAreaAndBalancePoint( winding_t *w, Vector &center );
void ClipWindingEpsilon (winding_t *in, const Vector &normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back);
// translates everything by offset, then does the clip, then translates back (to keep precision)
void ClipWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist, vec_t epsilon, winding_t **front, winding_t **back, const Vector &offset );
void ClassifyWindingEpsilon( winding_t *in, const Vector &normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back, winding_t **on);
void ClassifyWindingEpsilon_Offset( winding_t *in, const Vector &normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back, winding_t **on, const Vector &offset);
winding_t *ChopWinding (winding_t *in, const Vector &normal, vec_t dist);
winding_t *CopyWinding (winding_t *w);
winding_t *ReverseWinding (winding_t *w);
winding_t *BaseWindingForPlane (const Vector &normal, vec_t dist);
void CheckWinding (winding_t *w);
void WindingPlane (winding_t *w, Vector &normal, vec_t *dist);
void RemoveColinearPoints (winding_t *w);
int WindingOnPlaneSide (winding_t *w, const Vector &normal, vec_t dist);
void FreeWinding (winding_t *w);
void WindingBounds (winding_t *w, Vector &mins, Vector &maxs);
void ChopWindingInPlace (winding_t **w, const Vector &normal, vec_t dist, vec_t epsilon);
// frees the original if clipped
bool PointInWinding( Vector const &pt, winding_t *pWinding );
// translates a winding by offset
void TranslateWinding( winding_t *pWinding, const Vector &offset );
void pw(winding_t *w);
#endif // POLYLIB_H

42
utils/common/qfiles.h Normal file
View File

@@ -0,0 +1,42 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef QFILES_H
#define QFILES_H
#pragma once
//
// qfiles.h: quake file formats
// This file must be identical in the quake and utils directories
//
#include "basetypes.h"
#include "commonmacros.h"
#include "worldsize.h"
#include "bspfile.h"
#define MAX_OSPATH 260
#define MAX_QPATH 64
/*
========================================================================
The .pak files are just a linear collapse of a directory tree
========================================================================
*/
#define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P')
#endif // QFILES_H

View File

@@ -0,0 +1,103 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "scratchpad_helpers.h"
#include "bspfile.h"
#include "bsplib.h"
void ScratchPad_DrawWinding(
IScratchPad3D *pPad,
int nPoints,
Vector *pPoints,
Vector vColor,
Vector vOffset )
{
for ( int i=0; i < nPoints; i++ )
{
pPad->DrawLine( CSPVert( pPoints[i]+vOffset, vColor ), CSPVert( pPoints[(i+1)%nPoints]+vOffset, vColor ) );
}
}
void ScratchPad_DrawFace( IScratchPad3D *pPad, dface_t *f, int iFaceNumber, const CSPColor &faceColor, const Vector &vOffset )
{
// Draw the face's outline, then put text for its face index on it too.
CUtlVector<Vector> points;
for ( int iEdge = 0; iEdge < f->numedges; iEdge++ )
{
int v;
int se = dsurfedges[f->firstedge + iEdge];
if ( se < 0 )
v = dedges[-se].v[1];
else
v = dedges[se].v[0];
dvertex_t *dv = &dvertexes[v];
points.AddToTail( dv->point );
}
// Draw the outline.
Vector vCenter( 0, 0, 0 );
for ( int iEdge=0; iEdge < points.Count(); iEdge++ )
{
pPad->DrawLine( CSPVert( points[iEdge]+vOffset, faceColor ), CSPVert( points[(iEdge+1)%points.Count()]+vOffset, faceColor ) );
vCenter += points[iEdge];
}
vCenter /= points.Count();
vCenter += vOffset;
// Draw the text.
if ( iFaceNumber != -1 )
{
char str[64];
Q_snprintf( str, sizeof( str ), "%d", iFaceNumber );
CTextParams params;
params.m_bCentered = true;
params.m_bOutline = true;
params.m_flLetterWidth = 2;
params.m_vColor.Init( 1, 0, 0 );
VectorAngles( dplanes[f->planenum].normal, params.m_vAngles );
params.m_bTwoSided = true;
params.m_vPos = vCenter;
pPad->DrawText( str, params );
}
}
void ScratchPad_DrawWorld( IScratchPad3D *pPad, bool bDrawFaceNumbers, const CSPColor &faceColor )
{
bool bAutoFlush = pPad->GetAutoFlush();
pPad->SetAutoFlush( false );
for ( int i=0; i < numleafs; i++ )
{
dleaf_t *l = &dleafs[i];
if ( l->contents & CONTENTS_DETAIL )
continue;
for ( int z=0; z < l->numleaffaces; z++ )
{
int iFace = dleaffaces[l->firstleafface+z];
dface_t *f = &dfaces[iFace];
ScratchPad_DrawFace( pPad, f, bDrawFaceNumbers ? i : -1 );
}
}
pPad->SetAutoFlush( bAutoFlush );
}
void ScratchPad_DrawWorld( bool bDrawFaceNumbers, const CSPColor &faceColor )
{
IScratchPad3D *pPad = ScratchPad3D_Create();
ScratchPad_DrawWorld( pPad, bDrawFaceNumbers );
}

View File

@@ -0,0 +1,25 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef SCRATCHPAD_HELPERS_H
#define SCRATCHPAD_HELPERS_H
#ifdef _WIN32
#pragma once
#endif
#include "iscratchpad3d.h"
#include "bspfile.h"
void ScratchPad_DrawWinding( IScratchPad3D *pPad, int nPoints, Vector *pPoints, Vector vColor, Vector vOffset = Vector(0,0,0) );
void ScratchPad_DrawFace( IScratchPad3D *pPad, dface_t *f, int iFaceNumber = -1, const CSPColor &faceColor=CSPColor(1,1,1,1), const Vector &vOffset=Vector(0,0,0) );
void ScratchPad_DrawWorld( IScratchPad3D *pPad, bool bDrawFaceNumbers, const CSPColor &faceColor=CSPColor(1,1,1,1) );
void ScratchPad_DrawWorld( bool bDrawFaceNumbers, const CSPColor &faceColor=CSPColor(1,1,1,1) );
#endif // SCRATCHPAD_HELPERS_H

1389
utils/common/scriplib.cpp Normal file

File diff suppressed because it is too large Load Diff

94
utils/common/scriplib.h Normal file
View File

@@ -0,0 +1,94 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef SCRIPLIB_H
#define SCRIPLIB_H
#ifdef _WIN32
#pragma once
#endif
enum ScriptPathMode_t
{
SCRIPT_USE_ABSOLUTE_PATH,
SCRIPT_USE_RELATIVE_PATH
};
// scriplib.h
#define MAXTOKEN 1024
extern char token[MAXTOKEN];
//extern char *scriptbuffer,*script_p,*scriptend_p;
extern int grabbed;
extern int scriptline;
extern qboolean endofscript;
// If pathMode is SCRIPT_USE_ABSOLUTE_PATH, then it uses ExpandPath() on the filename before
// trying to open it. Otherwise, it passes the filename straight into the filesystem
// (so you can leave it as a relative path).
void LoadScriptFile (char *filename, ScriptPathMode_t pathMode=SCRIPT_USE_ABSOLUTE_PATH);
void ParseFromMemory (char *buffer, int size);
qboolean GetToken (qboolean crossline);
qboolean GetExprToken (qboolean crossline);
void UnGetToken (void);
qboolean TokenAvailable (void);
qboolean GetTokenizerStatus( char **pFilename, int *pLine );
// SCRIPT_LOADED_CALLBACK:
// Is called after the contents of a file is loaded.
// pFilenameLoaded is the path of a file that got loaded.
// pIncludedFromFileName is the name of the parent file or NULL if loaded because of "LoadScriptFile" toplevel call.
// nIncludeLineNumber is the number of the line in the parent file with $include statement or 0 in case of "LoadScriptFile"
typedef void ( * SCRIPT_LOADED_CALLBACK )( char const *pFilenameLoaded, char const *pIncludedFromFileName, int nIncludeLineNumber );
// SetScriptLoadedCallback:
// Sets the new callback for script loading.
// Returns the previous callback function.
SCRIPT_LOADED_CALLBACK SetScriptLoadedCallback( SCRIPT_LOADED_CALLBACK pfnNewScriptLoadedCallback );
#include "tier1/utlstring.h"
#include "tier1/utlvector.h"
class CUtlBuffer;
enum DiskWriteMode_t
{
WRITE_TO_DISK_NEVER,
WRITE_TO_DISK_ALWAYS,
WRITE_TO_DISK_UPDATE, // file must exist
};
struct fileList_t
{
CUtlString fileName;
time_t timeWrite;
};
class IScriptLib
{
public:
virtual bool ReadFileToBuffer( const char *pSourceName, CUtlBuffer &buffer, bool bText = false, bool bNoOpenFailureWarning = false ) = 0;
virtual bool WriteBufferToFile( const char *pTargetName, CUtlBuffer &buffer, DiskWriteMode_t writeMode ) = 0;
virtual int FindFiles( char* pFileMask, bool bRecurse, CUtlVector<fileList_t> &fileList ) = 0;
virtual char *MakeTemporaryFilename( char const *pchModPath, char *pPath, int pathSize ) = 0;
virtual void DeleteTemporaryFiles( const char *pFileMask ) = 0;
virtual int CompareFileTime( const char *pFilenameA, const char *pFilenameB ) = 0;
virtual bool DoesFileExist( const char *pFilename ) = 0;
};
extern IScriptLib *scriptlib;
extern IScriptLib *g_pScriptLib;
#endif // SCRIPLIB_H

257
utils/common/threads.cpp Normal file
View File

@@ -0,0 +1,257 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#define USED
#include <windows.h>
#include "cmdlib.h"
#define NO_THREAD_NAMES
#include "threads.h"
#include "pacifier.h"
#define MAX_THREADS 16
class CRunThreadsData
{
public:
int m_iThread;
void *m_pUserData;
RunThreadsFn m_Fn;
};
CRunThreadsData g_RunThreadsData[MAX_THREADS];
int dispatch;
int workcount;
qboolean pacifier;
qboolean threaded;
bool g_bLowPriorityThreads = false;
HANDLE g_ThreadHandles[MAX_THREADS];
/*
=============
GetThreadWork
=============
*/
int GetThreadWork (void)
{
int r;
ThreadLock ();
if (dispatch == workcount)
{
ThreadUnlock ();
return -1;
}
UpdatePacifier( (float)dispatch / workcount );
r = dispatch;
dispatch++;
ThreadUnlock ();
return r;
}
ThreadWorkerFn workfunction;
void ThreadWorkerFunction( int iThread, void *pUserData )
{
int work;
while (1)
{
work = GetThreadWork ();
if (work == -1)
break;
workfunction( iThread, work );
}
}
void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, ThreadWorkerFn func)
{
if (numthreads == -1)
ThreadSetDefault ();
workfunction = func;
RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
}
/*
===================================================================
WIN32
===================================================================
*/
int numthreads = -1;
CRITICAL_SECTION crit;
static int enter;
class CCritInit
{
public:
CCritInit()
{
InitializeCriticalSection (&crit);
}
} g_CritInit;
void SetLowPriority()
{
SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
}
void ThreadSetDefault (void)
{
SYSTEM_INFO info;
if (numthreads == -1) // not set manually
{
GetSystemInfo (&info);
numthreads = info.dwNumberOfProcessors;
if (numthreads < 1 || numthreads > 32)
numthreads = 1;
}
Msg ("%i threads\n", numthreads);
}
void ThreadLock (void)
{
if (!threaded)
return;
EnterCriticalSection (&crit);
if (enter)
Error ("Recursive ThreadLock\n");
enter = 1;
}
void ThreadUnlock (void)
{
if (!threaded)
return;
if (!enter)
Error ("ThreadUnlock without lock\n");
enter = 0;
LeaveCriticalSection (&crit);
}
// This runs in the thread and dispatches a RunThreadsFn call.
DWORD WINAPI InternalRunThreadsFn( LPVOID pParameter )
{
CRunThreadsData *pData = (CRunThreadsData*)pParameter;
pData->m_Fn( pData->m_iThread, pData->m_pUserData );
return 0;
}
void RunThreads_Start( RunThreadsFn fn, void *pUserData, ERunThreadsPriority ePriority )
{
Assert( numthreads > 0 );
threaded = true;
if ( numthreads > MAX_TOOL_THREADS )
numthreads = MAX_TOOL_THREADS;
for ( int i=0; i < numthreads ;i++ )
{
g_RunThreadsData[i].m_iThread = i;
g_RunThreadsData[i].m_pUserData = pUserData;
g_RunThreadsData[i].m_Fn = fn;
DWORD dwDummy;
g_ThreadHandles[i] = CreateThread(
NULL, // LPSECURITY_ATTRIBUTES lpsa,
0, // DWORD cbStack,
InternalRunThreadsFn, // LPTHREAD_START_ROUTINE lpStartAddr,
&g_RunThreadsData[i], // LPVOID lpvThreadParm,
0, // DWORD fdwCreate,
&dwDummy );
if ( ePriority == k_eRunThreadsPriority_UseGlobalState )
{
if( g_bLowPriorityThreads )
SetThreadPriority( g_ThreadHandles[i], THREAD_PRIORITY_LOWEST );
}
else if ( ePriority == k_eRunThreadsPriority_Idle )
{
SetThreadPriority( g_ThreadHandles[i], THREAD_PRIORITY_IDLE );
}
}
}
void RunThreads_End()
{
WaitForMultipleObjects( numthreads, g_ThreadHandles, TRUE, INFINITE );
for ( int i=0; i < numthreads; i++ )
CloseHandle( g_ThreadHandles[i] );
threaded = false;
}
/*
=============
RunThreadsOn
=============
*/
void RunThreadsOn( int workcnt, qboolean showpacifier, RunThreadsFn fn, void *pUserData )
{
int start, end;
start = Plat_FloatTime();
dispatch = 0;
workcount = workcnt;
StartPacifier("");
pacifier = showpacifier;
#ifdef _PROFILE
threaded = false;
(*func)( 0 );
return;
#endif
RunThreads_Start( fn, pUserData );
RunThreads_End();
end = Plat_FloatTime();
if (pacifier)
{
EndPacifier(false);
printf (" (%i)\n", end-start);
}
}

65
utils/common/threads.h Normal file
View File

@@ -0,0 +1,65 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef THREADS_H
#define THREADS_H
#pragma once
// Arrays that are indexed by thread should always be MAX_TOOL_THREADS+1
// large so THREADINDEX_MAIN can be used from the main thread.
#define MAX_TOOL_THREADS 16
#define THREADINDEX_MAIN (MAX_TOOL_THREADS)
extern int numthreads;
// If set to true, then all the threads that are created are low priority.
extern bool g_bLowPriorityThreads;
typedef void (*ThreadWorkerFn)( int iThread, int iWorkItem );
typedef void (*RunThreadsFn)( int iThread, void *pUserData );
enum ERunThreadsPriority
{
k_eRunThreadsPriority_UseGlobalState=0, // Default.. uses g_bLowPriorityThreads to decide what to set the priority to.
k_eRunThreadsPriority_Normal, // Doesn't touch thread priorities.
k_eRunThreadsPriority_Idle // Sets threads to idle priority.
};
// Put the process into an idle priority class so it doesn't hog the UI.
void SetLowPriority();
void ThreadSetDefault (void);
int GetThreadWork (void);
void RunThreadsOnIndividual ( int workcnt, qboolean showpacifier, ThreadWorkerFn fn );
void RunThreadsOn ( int workcnt, qboolean showpacifier, RunThreadsFn fn, void *pUserData=NULL );
// This version doesn't track work items - it just runs your function and waits for it to finish.
void RunThreads_Start( RunThreadsFn fn, void *pUserData, ERunThreadsPriority ePriority=k_eRunThreadsPriority_UseGlobalState );
void RunThreads_End();
void ThreadLock (void);
void ThreadUnlock (void);
#ifndef NO_THREAD_NAMES
#define RunThreadsOn(n,p,f) { if (p) printf("%-20s ", #f ":"); RunThreadsOn(n,p,f); }
#define RunThreadsOnIndividual(n,p,f) { if (p) printf("%-20s ", #f ":"); RunThreadsOnIndividual(n,p,f); }
#endif
#endif // THREADS_H

View File

@@ -0,0 +1,61 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <windows.h>
#include "tier0/minidump.h"
#include "tools_minidump.h"
static bool g_bToolsWriteFullMinidumps = false;
static ToolsExceptionHandler g_pCustomExceptionHandler = NULL;
// --------------------------------------------------------------------------------- //
// Internal helpers.
// --------------------------------------------------------------------------------- //
static void ToolsExceptionFilter( uint uStructuredExceptionCode, ExceptionInfo_t * pExceptionInfo, const char *pszFilenameSuffix )
{
// Non VMPI workers write a minidump and show a crash dialog like normal.
uint32 iType = MINIDUMP_Normal;
if ( g_bToolsWriteFullMinidumps )
{
iType |= MINIDUMP_WithDataSegs | MINIDUMP_WithIndirectlyReferencedMemory;
}
WriteMiniDumpUsingExceptionInfo( uStructuredExceptionCode, pExceptionInfo, iType, pszFilenameSuffix );
}
static void ToolsExceptionFilter_Custom( uint uStructuredExceptionCode, ExceptionInfo_t * pExceptionInfo, const char *pszFilenameSuffix )
{
// Run their custom handler.
g_pCustomExceptionHandler( uStructuredExceptionCode, pExceptionInfo );
}
// --------------------------------------------------------------------------------- //
// Interface functions.
// --------------------------------------------------------------------------------- //
void EnableFullMinidumps( bool bFull )
{
g_bToolsWriteFullMinidumps = bFull;
}
void SetupDefaultToolsMinidumpHandler()
{
MinidumpSetUnhandledExceptionFunction( ToolsExceptionFilter );
}
void SetupToolsMinidumpHandler( ToolsExceptionHandler fn )
{
g_pCustomExceptionHandler = fn;
MinidumpSetUnhandledExceptionFunction( ToolsExceptionFilter_Custom );
}

View File

@@ -0,0 +1,35 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef TOOLS_MINIDUMP_H
#define TOOLS_MINIDUMP_H
#ifdef _WIN32
#pragma once
#endif
// Defaults to false. If true, it'll write larger minidump files with the contents
// of global variables and following pointers from where the crash occurred.
void EnableFullMinidumps( bool bFull );
// This handler catches any crash, writes a minidump, and runs the default system
// crash handler (which usually shows a dialog).
void SetupDefaultToolsMinidumpHandler();
// (Used by VMPI) - you specify your own crash handler.
// Arguments passed to ToolsExceptionHandler
// exceptionCode - exception code
// pvExceptionInfo - on Win32 platform points to "struct _EXCEPTION_POINTERS"
// otherwise NULL
//
typedef void (*ToolsExceptionHandler)( unsigned long exceptionCode, void *pvExceptionInfo );
void SetupToolsMinidumpHandler( ToolsExceptionHandler fn );
#endif // MINIDUMP_H

187
utils/common/utilmatlib.cpp Normal file
View File

@@ -0,0 +1,187 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
// C callable material system interface for the utils.
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include <cmdlib.h>
#include "utilmatlib.h"
#include "tier0/dbg.h"
#ifndef POSIX
#include <windows.h>
#endif
#include "filesystem.h"
#include "materialsystem/materialsystem_config.h"
#include "mathlib/mathlib.h"
#include "tier2/tier2.h"
void LoadMaterialSystemInterface( CreateInterfaceFn fileSystemFactory )
{
if( g_pMaterialSystem )
return;
// materialsystem.dll should be in the path, it's in bin along with vbsp.
const char *pDllName = "materialsystem.dll";
CSysModule *materialSystemDLLHInst;
materialSystemDLLHInst = g_pFullFileSystem->LoadModule( pDllName );
if( !materialSystemDLLHInst )
{
Error( "Can't load MaterialSystem.dll\n" );
}
CreateInterfaceFn clientFactory = Sys_GetFactory( materialSystemDLLHInst );
if ( clientFactory )
{
g_pMaterialSystem = (IMaterialSystem *)clientFactory( MATERIAL_SYSTEM_INTERFACE_VERSION, NULL );
if ( !g_pMaterialSystem )
{
Error( "Could not get the material system interface from materialsystem.dll (" __FILE__ ")" );
}
}
else
{
Error( "Could not find factory interface in library MaterialSystem.dll" );
}
if (!g_pMaterialSystem->Init( "shaderapiempty.dll", 0, fileSystemFactory ))
{
Error( "Could not start the empty shader (shaderapiempty.dll)!" );
}
}
void InitMaterialSystem( const char *materialBaseDirPath, CreateInterfaceFn fileSystemFactory )
{
LoadMaterialSystemInterface( fileSystemFactory );
MaterialSystem_Config_t config;
g_pMaterialSystem->OverrideConfig( config, false );
}
void ShutdownMaterialSystem( )
{
if ( g_pMaterialSystem )
{
g_pMaterialSystem->Shutdown();
g_pMaterialSystem = NULL;
}
}
MaterialSystemMaterial_t FindMaterial( const char *materialName, bool *pFound, bool bComplain )
{
IMaterial *pMat = g_pMaterialSystem->FindMaterial( materialName, TEXTURE_GROUP_OTHER, bComplain );
MaterialSystemMaterial_t matHandle = pMat;
if ( pFound )
{
*pFound = true;
if ( IsErrorMaterial( pMat ) )
*pFound = false;
}
return matHandle;
}
void GetMaterialDimensions( MaterialSystemMaterial_t materialHandle, int *width, int *height )
{
PreviewImageRetVal_t retVal;
ImageFormat dummyImageFormat;
IMaterial *material = ( IMaterial * )materialHandle;
bool translucent;
retVal = material->GetPreviewImageProperties( width, height, &dummyImageFormat, &translucent );
if (retVal != MATERIAL_PREVIEW_IMAGE_OK )
{
#if 0
if (retVal == MATERIAL_PREVIEW_IMAGE_BAD )
{
Error( "problem getting preview image for %s",
g_pMaterialSystem->GetMaterialName( materialInfo[matID].materialHandle ) );
}
#else
*width = 128;
*height = 128;
#endif
}
}
void GetMaterialReflectivity( MaterialSystemMaterial_t materialHandle, float *reflectivityVect )
{
IMaterial *material = ( IMaterial * )materialHandle;
const IMaterialVar *reflectivityVar;
bool found;
reflectivityVar = material->FindVar( "$reflectivity", &found, false );
if( !found )
{
Vector tmp;
material->GetReflectivity( tmp );
VectorCopy( tmp.Base(), reflectivityVect );
}
else
{
reflectivityVar->GetVecValue( reflectivityVect, 3 );
}
}
int GetMaterialShaderPropertyBool( MaterialSystemMaterial_t materialHandle, int propID )
{
IMaterial *material = ( IMaterial * )materialHandle;
switch( propID )
{
case UTILMATLIB_NEEDS_BUMPED_LIGHTMAPS:
return material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS );
case UTILMATLIB_NEEDS_LIGHTMAP:
return material->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_LIGHTMAP );
default:
Assert( 0 );
return 0;
}
}
int GetMaterialShaderPropertyInt( MaterialSystemMaterial_t materialHandle, int propID )
{
IMaterial *material = ( IMaterial * )materialHandle;
switch( propID )
{
case UTILMATLIB_OPACITY:
if (material->IsTranslucent())
return UTILMATLIB_TRANSLUCENT;
if (material->IsAlphaTested())
return UTILMATLIB_ALPHATEST;
return UTILMATLIB_OPAQUE;
default:
Assert( 0 );
return 0;
}
}
const char *GetMaterialVar( MaterialSystemMaterial_t materialHandle, const char *propertyName )
{
IMaterial *material = ( IMaterial * )materialHandle;
IMaterialVar *var;
bool found;
var = material->FindVar( propertyName, &found, false );
if( found )
{
return var->GetStringValue();
}
else
{
return NULL;
}
}
const char *GetMaterialShaderName( MaterialSystemMaterial_t materialHandle )
{
IMaterial *material = ( IMaterial * )materialHandle;
return material->GetShaderName();
}

43
utils/common/utilmatlib.h Normal file
View File

@@ -0,0 +1,43 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef UTILMATLIB_H
#define UTILMATLIB_H
#ifdef _WIN32
#pragma once
#endif
#include "interfaces/interfaces.h"
#define MATERIAL_NOT_FOUND NULL
class IMaterialSystem;
DECLARE_TIER2_INTERFACE( IMaterialSystem, g_pMaterialSystem );
typedef void *MaterialSystemMaterial_t;
#define UTILMATLIB_NEEDS_BUMPED_LIGHTMAPS 0
#define UTILMATLIB_NEEDS_LIGHTMAP 1
#define UTILMATLIB_OPACITY 2
enum { UTILMATLIB_ALPHATEST = 0, UTILMATLIB_OPAQUE, UTILMATLIB_TRANSLUCENT };
void InitMaterialSystem( const char *materialBaseDirPath, CreateInterfaceFn fileSystemFactory );
void ShutdownMaterialSystem( );
MaterialSystemMaterial_t FindMaterial( const char *materialName, bool *pFound, bool bComplain = true );
void GetMaterialDimensions( MaterialSystemMaterial_t materialHandle, int *width, int *height );
int GetMaterialShaderPropertyBool( MaterialSystemMaterial_t materialHandle, int propID );
int GetMaterialShaderPropertyInt( MaterialSystemMaterial_t materialHandle, int propID );
const char *GetMaterialVar( MaterialSystemMaterial_t materialHandle, const char *propertyName );
void GetMaterialReflectivity( MaterialSystemMaterial_t materialHandle, float *reflectivityVect );
const char *GetMaterialShaderName( MaterialSystemMaterial_t materialHandle );
#endif // UTILMATLIB_H

View File

@@ -0,0 +1,376 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include <windows.h>
#include "vmpi.h"
#include "cmdlib.h"
#include "vmpi_tools_shared.h"
#include "tier1/strtools.h"
#include "mpi_stats.h"
#include "iphelpers.h"
#include "tier0/minidump.h"
// ----------------------------------------------------------------------------- //
// Globals.
// ----------------------------------------------------------------------------- //
static bool g_bReceivedDirectoryInfo = false; // Have we gotten the qdir info yet?
static bool g_bReceivedDBInfo = false;
static CDBInfo g_DBInfo;
static unsigned long g_JobPrimaryID;
static int g_nDisconnects = 0; // Tracks how many remote processes have disconnected ungracefully.
// ----------------------------------------------------------------------------- //
// Shared dispatch code.
// ----------------------------------------------------------------------------- //
bool SharedDispatch( MessageBuffer *pBuf, int iSource, int iPacketID )
{
char *pInPos = &pBuf->data[2];
switch ( pBuf->data[1] )
{
case VMPI_SUBPACKETID_DIRECTORIES:
{
Q_strncpy( gamedir, pInPos, sizeof( gamedir ) );
pInPos += strlen( pInPos ) + 1;
Q_strncpy( qdir, pInPos, sizeof( qdir ) );
g_bReceivedDirectoryInfo = true;
}
return true;
case VMPI_SUBPACKETID_DBINFO:
{
g_DBInfo = *((CDBInfo*)pInPos);
pInPos += sizeof( CDBInfo );
g_JobPrimaryID = *((unsigned long*)pInPos);
g_bReceivedDBInfo = true;
}
return true;
case VMPI_SUBPACKETID_CRASH:
{
char const chCrashInfoType = *pInPos;
pInPos += 2;
switch ( chCrashInfoType )
{
case 't':
Warning( "\nWorker '%s' dead: %s\n", VMPI_GetMachineName( iSource ), pInPos );
break;
case 'f':
{
int iFileSize = * reinterpret_cast< int const * >( pInPos );
pInPos += sizeof( iFileSize );
// Temp folder
char const *szFolder = NULL;
if ( !szFolder ) szFolder = getenv( "TEMP" );
if ( !szFolder ) szFolder = getenv( "TMP" );
if ( !szFolder ) szFolder = "c:";
// Base module name
char chModuleName[_MAX_PATH], *pModuleName = chModuleName;
::GetModuleFileName( NULL, chModuleName, sizeof( chModuleName ) / sizeof( chModuleName[0] ) );
if ( char *pch = strrchr( chModuleName, '.' ) )
*pch = 0;
if ( char *pch = strrchr( chModuleName, '\\' ) )
*pch = 0, pModuleName = pch + 1;
// Current time
struct tm curTime;
Plat_GetLocalTime( &curTime );
// Number of minidumps this run
static int s_numMiniDumps = 0;
++ s_numMiniDumps;
// Prepare the filename
char chSaveFileName[ 2 * _MAX_PATH ] = { 0 };
sprintf( chSaveFileName, "%s\\vmpi_%s_on_%s_%d%.2d%2d%.2d%.2d%.2d_%d.mdmp",
szFolder,
pModuleName,
VMPI_GetMachineName( iSource ),
curTime.tm_year + 1900, /* Year less 2000 */
curTime.tm_mon + 1, /* month (0 - 11 : 0 = January) */
curTime.tm_mday, /* day of month (1 - 31) */
curTime.tm_hour, /* hour (0 - 23) */
curTime.tm_min, /* minutes (0 - 59) */
curTime.tm_sec, /* seconds (0 - 59) */
s_numMiniDumps
);
if ( FILE *fDump = fopen( chSaveFileName, "wb" ) )
{
fwrite( pInPos, 1, iFileSize, fDump );
fclose( fDump );
Warning( "\nSaved worker crash minidump '%s', size %d byte(s).\n",
chSaveFileName, iFileSize );
}
else
{
Warning( "\nReceived worker crash minidump size %d byte(s), failed to save.\n", iFileSize );
}
}
break;
}
}
return true;
}
return false;
}
CDispatchReg g_SharedDispatchReg( VMPI_SHARED_PACKET_ID, SharedDispatch );
VMPI_REGISTER_PACKET_ID( VMPI_SHARED_PACKET_ID );
VMPI_REGISTER_SUBPACKET_ID( VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_DIRECTORIES );
VMPI_REGISTER_SUBPACKET_ID( VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_DBINFO );
VMPI_REGISTER_SUBPACKET_ID( VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_CRASH );
VMPI_REGISTER_SUBPACKET_ID( VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_MULTICAST_ADDR );
// ----------------------------------------------------------------------------- //
// Module interfaces.
// ----------------------------------------------------------------------------- //
void SendQDirInfo()
{
char cPacketID[2] = { VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_DIRECTORIES };
MessageBuffer mb;
mb.write( cPacketID, 2 );
mb.write( gamedir, strlen( gamedir ) + 1 );
mb.write( qdir, strlen( qdir ) + 1 );
VMPI_SendData( mb.data, mb.getLen(), VMPI_PERSISTENT );
}
void RecvQDirInfo()
{
while ( !g_bReceivedDirectoryInfo )
VMPI_DispatchNextMessage();
}
void SendDBInfo( const CDBInfo *pInfo, unsigned long jobPrimaryID )
{
char cPacketInfo[2] = { VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_DBINFO };
const void *pChunks[] = { cPacketInfo, pInfo, &jobPrimaryID };
int chunkLengths[] = { 2, sizeof( CDBInfo ), sizeof( jobPrimaryID ) };
VMPI_SendChunks( pChunks, chunkLengths, ARRAYSIZE( pChunks ), VMPI_PERSISTENT );
}
void RecvDBInfo( CDBInfo *pInfo, unsigned long *pJobPrimaryID )
{
while ( !g_bReceivedDBInfo )
VMPI_DispatchNextMessage();
*pInfo = g_DBInfo;
*pJobPrimaryID = g_JobPrimaryID;
}
// If the file is successfully opened, read and sent returns the size of the file in bytes
// otherwise returns 0 and nothing is sent
int VMPI_SendFileChunk( const void *pvChunkPrefix, int lenPrefix, tchar const *ptchFileName )
{
HANDLE hFile = NULL;
HANDLE hMapping = NULL;
void const *pvMappedData = NULL;
int iResult = 0;
hFile = ::CreateFile( ptchFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( !hFile || ( hFile == INVALID_HANDLE_VALUE ) )
goto done;
hMapping = ::CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
if ( !hMapping || ( hMapping == INVALID_HANDLE_VALUE ) )
goto done;
pvMappedData = ::MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
if ( !pvMappedData )
goto done;
int iMappedFileSize = ::GetFileSize( hFile, NULL );
if ( INVALID_FILE_SIZE == iMappedFileSize )
goto done;
// Send the data over VMPI
if ( VMPI_Send3Chunks(
pvChunkPrefix, lenPrefix,
&iMappedFileSize, sizeof( iMappedFileSize ),
pvMappedData, iMappedFileSize,
VMPI_MASTER_ID ) )
iResult = iMappedFileSize;
// Fall-through for cleanup code to execute
done:
if ( pvMappedData )
::UnmapViewOfFile( pvMappedData );
if ( hMapping && ( hMapping != INVALID_HANDLE_VALUE ) )
::CloseHandle( hMapping );
if ( hFile && ( hFile != INVALID_HANDLE_VALUE ) )
::CloseHandle( hFile );
return iResult;
}
void VMPI_HandleCrash( const char *pMessage, uint uCode, void *pvExceptionInfo, bool bAssert )
{
static LONG crashHandlerCount = 0;
if ( InterlockedIncrement( &crashHandlerCount ) == 1 )
{
Msg( "\nFAILURE: '%s' (assert: %d)\n", pMessage, bAssert );
// Send a message to the master.
char crashMsg[4] = { VMPI_SHARED_PACKET_ID, VMPI_SUBPACKETID_CRASH, 't', ':' };
VMPI_Send2Chunks(
crashMsg,
sizeof( crashMsg ),
pMessage,
strlen( pMessage ) + 1,
VMPI_MASTER_ID );
// Now attempt to create a minidump with the given exception information
if ( pvExceptionInfo )
{
tchar tchMinidumpFileName[_MAX_PATH] = { 0 };
bool bSucceededWritingMinidump = WriteMiniDumpUsingExceptionInfo(
uCode, (ExceptionInfo_t*)pvExceptionInfo,
MINIDUMP_WithDataSegs | MINIDUMP_WithIndirectlyReferencedMemory | MINIDUMP_WithProcessThreadData,
// MINIDUMP_WithDataSegs | MINIDUMP_WithFullMemory | MINIDUMP_WithHandleData | MINIDUMP_WithUnloadedModules | MINIDUMP_WithIndirectlyReferencedMemory | MINIDUMP_WithProcessThreadData | MINIDUMP_WithPrivateReadWriteMemory,
// MINIDUMP_Normal,
tchMinidumpFileName );
if ( bSucceededWritingMinidump )
{
crashMsg[2] = 'f';
VMPI_SendFileChunk( crashMsg, sizeof( crashMsg ), tchMinidumpFileName );
::DeleteFile( tchMinidumpFileName );
}
}
// Let the messages go out.
Sleep( 500 );
}
InterlockedDecrement( &crashHandlerCount );
}
// This is called if we crash inside our crash handler. It just terminates the process immediately.
LONG __stdcall VMPI_SecondExceptionFilter( struct _EXCEPTION_POINTERS *ExceptionInfo )
{
TerminateProcess( GetCurrentProcess(), 2 );
return EXCEPTION_EXECUTE_HANDLER; // (never gets here anyway)
}
void VMPI_ExceptionFilter( unsigned long uCode, void *pvExceptionInfo )
{
// This is called if we crash inside our crash handler. It just terminates the process immediately.
SetUnhandledExceptionFilter( VMPI_SecondExceptionFilter );
//DWORD code = ExceptionInfo->ExceptionRecord->ExceptionCode;
#define ERR_RECORD( name ) { name, #name }
struct
{
int code;
char *pReason;
} errors[] =
{
ERR_RECORD( EXCEPTION_ACCESS_VIOLATION ),
ERR_RECORD( EXCEPTION_ARRAY_BOUNDS_EXCEEDED ),
ERR_RECORD( EXCEPTION_BREAKPOINT ),
ERR_RECORD( EXCEPTION_DATATYPE_MISALIGNMENT ),
ERR_RECORD( EXCEPTION_FLT_DENORMAL_OPERAND ),
ERR_RECORD( EXCEPTION_FLT_DIVIDE_BY_ZERO ),
ERR_RECORD( EXCEPTION_FLT_INEXACT_RESULT ),
ERR_RECORD( EXCEPTION_FLT_INVALID_OPERATION ),
ERR_RECORD( EXCEPTION_FLT_OVERFLOW ),
ERR_RECORD( EXCEPTION_FLT_STACK_CHECK ),
ERR_RECORD( EXCEPTION_FLT_UNDERFLOW ),
ERR_RECORD( EXCEPTION_ILLEGAL_INSTRUCTION ),
ERR_RECORD( EXCEPTION_IN_PAGE_ERROR ),
ERR_RECORD( EXCEPTION_INT_DIVIDE_BY_ZERO ),
ERR_RECORD( EXCEPTION_INT_OVERFLOW ),
ERR_RECORD( EXCEPTION_INVALID_DISPOSITION ),
ERR_RECORD( EXCEPTION_NONCONTINUABLE_EXCEPTION ),
ERR_RECORD( EXCEPTION_PRIV_INSTRUCTION ),
ERR_RECORD( EXCEPTION_SINGLE_STEP ),
ERR_RECORD( EXCEPTION_STACK_OVERFLOW ),
ERR_RECORD( EXCEPTION_ACCESS_VIOLATION ),
};
int nErrors = sizeof( errors ) / sizeof( errors[0] );
int i=0;
char *pchReason = NULL;
char chUnknownBuffer[32];
for ( i; ( i < nErrors ) && !pchReason; i++ )
{
if ( errors[i].code == uCode )
pchReason = errors[i].pReason;
}
if ( i == nErrors )
{
sprintf( chUnknownBuffer, "Error code 0x%08X", uCode );
pchReason = chUnknownBuffer;
}
VMPI_HandleCrash( pchReason, uCode, pvExceptionInfo, true );
TerminateProcess( GetCurrentProcess(), 1 );
}
void HandleMPIDisconnect( int procID, const char *pReason )
{
int nLiveWorkers = VMPI_GetCurrentNumberOfConnections() - g_nDisconnects - 1;
// We ran into the size limit before and it wasn't readily apparent that the size limit had
// been breached, so make sure to show errors about invalid packet sizes..
bool bOldSuppress = g_bSuppressPrintfOutput;
g_bSuppressPrintfOutput = ( Q_stristr( pReason, "invalid packet size" ) == 0 );
Warning( "\n\n--- WARNING: lost connection to '%s' (%s).\n", VMPI_GetMachineName( procID ), pReason );
if ( g_bMPIMaster )
{
Warning( "%d workers remain.\n\n", nLiveWorkers );
++g_nDisconnects;
/*
if ( VMPI_GetCurrentNumberOfConnections() - g_nDisconnects <= 1 )
{
Error( "All machines disconnected!" );
}
*/
}
else
{
VMPI_HandleAutoRestart();
Error( "Worker quitting." );
}
g_bSuppressPrintfOutput = bOldSuppress;
}

View File

@@ -0,0 +1,46 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef VMPI_TOOLS_SHARED_H
#define VMPI_TOOLS_SHARED_H
#ifdef _WIN32
#pragma once
#endif
// Packet IDs.
// Be sure to register new ones with VMPI_REGISTER_SUBPACKET_ID.
#define VMPI_SUBPACKETID_DIRECTORIES 0 // qdir directories.
#define VMPI_SUBPACKETID_DBINFO 1 // MySQL database info.
#define VMPI_SUBPACKETID_CRASH 3 // A worker saying it crashed.
#define VMPI_SUBPACKETID_MULTICAST_ADDR 4 // Filesystem multicast address.
class CDBInfo;
class CIPAddr;
// Send/receive the qdir info.
void SendQDirInfo();
void RecvQDirInfo();
void SendDBInfo( const CDBInfo *pInfo, unsigned long jobPrimaryID );
void RecvDBInfo( CDBInfo *pInfo, unsigned long *pJobPrimaryID );
void SendMulticastIP( const CIPAddr *pAddr );
void RecvMulticastIP( CIPAddr *pAddr );
void VMPI_HandleCrash( const char *pMessage, uint uCode, void *pvExceptionInfo, bool bAssert );
// Call this from an exception handler (set by SetUnhandledExceptionHandler).
// uCode = ExceptionInfo->ExceptionRecord->ExceptionCode.
// pvExceptionInfo = ExceptionInfo
void VMPI_ExceptionFilter( unsigned long uCode, void *pvExceptionInfo );
void HandleMPIDisconnect( int procID, const char *pReason );
#endif // VMPI_TOOLS_SHARED_H

334
utils/common/wadlib.c Normal file
View File

@@ -0,0 +1,334 @@
//========= Copyright © 1996-2005, Valve LLC, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// wad2lib.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <sys/file.h>
#include <stdarg.h>
#ifdef NeXT
#include <libc.h>
#endif
#include "cmdlib.h"
#include "wadlib.h"
#include "commonmacros.h"
/*
============================================================================
WAD READING
============================================================================
*/
lumpinfo_t *lumpinfo; // location of each lump on disk
int numlumps;
wadinfo_t header;
FILE *wadhandle;
/*
====================
W_OpenWad
====================
*/
void W_OpenWad (char *filename)
{
lumpinfo_t *lump_p;
unsigned i;
int length;
//
// open the file and add to directory
//
wadhandle = SafeOpenRead (filename);
SafeRead (wadhandle, &header, sizeof(header));
if (!STRING_MATCHES_ID(header.identification,WAD_ID))
Error ("Wad file %s doesn't have %s identifier\n",filename, WAD_IDNAME);
header.numlumps = LittleLong(header.numlumps);
header.infotableofs = LittleLong(header.infotableofs);
numlumps = header.numlumps;
length = numlumps*sizeof(lumpinfo_t);
lumpinfo = malloc (length);
lump_p = lumpinfo;
fseek (wadhandle, header.infotableofs, SEEK_SET);
SafeRead (wadhandle, lumpinfo, length);
//
// Fill in lumpinfo
//
for (i=0 ; i<numlumps ; i++,lump_p++)
{
lump_p->filepos = LittleLong(lump_p->filepos);
lump_p->size = LittleLong(lump_p->size);
}
}
void CleanupName (char *in, char *out)
{
int i;
for (i=0 ; i<sizeof( ((lumpinfo_t *)0)->name ) ; i++ )
{
if (!in[i])
break;
out[i] = toupper(in[i]);
}
for ( ; i<sizeof( ((lumpinfo_t *)0)->name ); i++ )
out[i] = 0;
}
/*
====================
W_CheckNumForName
Returns -1 if name not found
====================
*/
int W_CheckNumForName (char *name)
{
char cleanname[TEXTURE_NAME_LENGTH];
int v1,v2, v3, v4;
int i;
lumpinfo_t *lump_p;
CleanupName (name, cleanname);
// make the name into four integers for easy compares
v1 = *(int *)cleanname;
v2 = *(int *)&cleanname[4];
v3 = *(int *)&cleanname[8];
v4 = *(int *)&cleanname[12];
// find it
lump_p = lumpinfo;
for (i=0 ; i<numlumps ; i++, lump_p++)
{
if ( *(int *)lump_p->name == v1
&& *(int *)&lump_p->name[4] == v2
&& *(int *)&lump_p->name[8] == v3
&& *(int *)&lump_p->name[12] == v4
&& !strcmp( lump_p->name, cleanname ) )
return i;
}
return -1;
}
/*
====================
W_GetNumForName
Calls W_CheckNumForName, but bombs out if not found
====================
*/
int W_GetNumForName (char *name)
{
int i;
i = W_CheckNumForName (name);
if (i != -1)
return i;
Error ("W_GetNumForName: %s not found!",name);
return -1;
}
/*
====================
W_LumpLength
Returns the buffer size needed to load the given lump
====================
*/
int W_LumpLength (int lump)
{
if (lump >= numlumps)
Error ("W_LumpLength: %i >= numlumps",lump);
return lumpinfo[lump].size;
}
/*
====================
W_ReadLumpNum
Loads the lump into the given buffer, which must be >= W_LumpLength()
====================
*/
void W_ReadLumpNum (int lump, void *dest)
{
lumpinfo_t *l;
if (lump >= numlumps)
Error ("W_ReadLump: %i >= numlumps",lump);
l = lumpinfo+lump;
fseek (wadhandle, l->filepos, SEEK_SET);
SafeRead (wadhandle, dest, l->size);
}
/*
====================
W_LoadLumpNum
====================
*/
void *W_LoadLumpNum (int lump)
{
void *buf;
if ((unsigned)lump >= numlumps)
Error ("W_CacheLumpNum: %i >= numlumps",lump);
buf = malloc (W_LumpLength (lump));
W_ReadLumpNum (lump, buf);
return buf;
}
/*
====================
W_LoadLumpName
====================
*/
void *W_LoadLumpName (char *name)
{
return W_LoadLumpNum (W_GetNumForName(name));
}
/*
===============================================================================
WAD CREATION
===============================================================================
*/
FILE *outwad;
lumpinfo_t outinfo[4096];
int outlumps;
short (*wadshort) (short l);
int (*wadlong) (int l);
/*
===============
NewWad
===============
*/
void NewWad (char *pathname, qboolean bigendien)
{
outwad = SafeOpenWrite (pathname);
fseek (outwad, sizeof(wadinfo_t), SEEK_SET);
memset (outinfo, 0, sizeof(outinfo));
if (bigendien)
{
wadshort = BigShort;
wadlong = BigLong;
}
else
{
wadshort = LittleShort;
wadlong = LittleLong;
}
outlumps = 0;
}
/*
===============
AddLump
===============
*/
void AddLump (char *name, void *buffer, int length, int type, int compress)
{
lumpinfo_t *info;
int ofs;
info = &outinfo[outlumps];
outlumps++;
memset (info,0,sizeof(info));
strcpy (info->name, name);
Q_strupr (info->name);
ofs = ftell(outwad);
info->filepos = wadlong(ofs);
info->size = info->disksize = wadlong(length);
info->type = type;
info->compression = compress;
// FIXME: do compression
SafeWrite (outwad, buffer, length);
}
/*
===============
WriteWad
===============
*/
void WriteWad (int wad3)
{
wadinfo_t header;
int ofs;
// write the lumpingo
ofs = ftell(outwad);
SafeWrite (outwad, outinfo, outlumps*sizeof(lumpinfo_t) );
// write the header
// a program will be able to tell the ednieness of a wad by the id
ID_TO_STRING( WAD_ID, header.identification );
header.numlumps = wadlong(outlumps);
header.infotableofs = wadlong(ofs);
fseek (outwad, 0, SEEK_SET);
SafeWrite (outwad, &header, sizeof(header));
fclose (outwad);
}

46
utils/common/wadlib.h Normal file
View File

@@ -0,0 +1,46 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// wadlib.h
//
// wad reading
//
#define CMP_NONE 0
#define CMP_LZSS 1
#define TYP_NONE 0
#define TYP_LABEL 1
#define TYP_LUMPY 64 // 64 + grab command number
#ifndef WADTYPES_H
#include "wadtypes.h"
#endif
extern lumpinfo_t *lumpinfo; // location of each lump on disk
extern int numlumps;
extern wadinfo_t header;
void W_OpenWad (char *filename);
int W_CheckNumForName (char *name);
int W_GetNumForName (char *name);
int W_LumpLength (int lump);
void W_ReadLumpNum (int lump, void *dest);
void *W_LoadLumpNum (int lump);
void *W_LoadLumpName (char *name);
void CleanupName (char *in, char *out);
//
// wad creation
//
void NewWad (char *pathname, qboolean bigendien);
void AddLump (char *name, void *buffer, int length, int type, int compress);
void WriteWad (int wad3);

363
utils/dx_proxy/dx_proxy.cpp Normal file
View File

@@ -0,0 +1,363 @@
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
//
// Purpose: Proxy for D3DX routines
//
// $NoKeywords: $
//
//=============================================================================//
//
#include <windows.h>
#include <vector>
// Aux function prototype
const char * WINAPI GetDllVersion( void );
#ifdef _DEBUG
#define D3D_DEBUG_INFO 1
#endif
//
// DX9_V00_PC
//
// D3DX static library
// MSFT file version: 5.3.0000001.0904
//
#ifdef DX9_V00_PC
#ifdef DX_PROXY_INC_CONFIG
# error "DX9_V00_PC: Multiple DX_PROXY configurations disallowed!"
#endif
#define DX_PROXY_INC_CONFIG
#pragma message ( "Compiling DX_PROXY for DX9_V00_PC" )
#pragma comment ( lib, "../../dx9sdk/lib/d3dx9" )
#include "../../dx9sdk/include/d3dx9shader.h"
#endif // #ifdef DX9_V00_PC
//
// DX9_X360
//
// D3DX win32 static library
// MSFT X360 SDK
//
#ifdef DX9_V00_X360
#ifdef DX_PROXY_INC_CONFIG
# error "DX9_V00_X360: Multiple DX_PROXY configurations disallowed!"
#endif
#define DX_PROXY_INC_CONFIG
#pragma message ( "Compiling DX_PROXY for DX9_V00_X360" )
// Avoid including XBOX math stuff
#define _NO_XBOXMATH
#define __D3DX9MATH_INL__
#include "d3dx9shader.h"
#endif // #ifdef DX9_V00_X360
//
// DX9_V30_PC
//
// 1. D3DX static import library
// 2. resource dynamic library d3dx9_33.dll
//
// MSFT file version: 9.16.843.0000
// Distribution: Dec 2006 DirectX SDK
//
// Implementation note: need to delayload d3dx9_33
// because the module should be extracted from resources first.
// Make sure "/DELAYLOAD:d3dx9_33.dll" is passed to linker.
//
#ifdef DX9_V30_PC
#ifdef DX_PROXY_INC_CONFIG
# error "DX9_V30_PC: Multiple DX_PROXY configurations disallowed!"
#endif
#define DX_PROXY_INC_CONFIG
#pragma message ( "Compiling DX_PROXY for DX9_V30_PC" )
#pragma comment( lib, "delayimp" )
#pragma comment ( lib, "../../dx10sdk/lib/x86/d3dx9" )
#include "../../dx10sdk/include/d3dx9shader.h"
#endif // #ifdef DX9_V30_PC
//
// DX10_V00_PC
//
// 1. D3DX static import library
// 2. resource dynamic library d3dx10.dll
//
// MSFT file version: 9.16.843.0000
// Distribution: Dec 2006 DirectX SDK
//
// Implementation note: need to delayload d3dx10
// because the module should be extracted from resources first.
// Make sure "/DELAYLOAD:d3dx10.dll" is passed to linker.
//
#ifdef DX10_V00_PC
#ifdef DX_PROXY_INC_CONFIG
# error "DX10_V00_PC: Multiple DX_PROXY configurations disallowed!"
#endif
#define DX_PROXY_INC_CONFIG
#pragma message ( "Compiling DX_PROXY for DX10_V00_PC" )
#pragma comment( lib, "delayimp" )
#pragma comment ( lib, "../../dx10sdk/lib/x86/d3dx10" )
#include "../../dx10sdk/include/d3dx10.h"
typedef D3D10_SHADER_MACRO D3DXMACRO;
typedef LPD3D10INCLUDE LPD3DXINCLUDE;
typedef ID3D10Include ID3DXInclude;
typedef D3D10_INCLUDE_TYPE D3DXINCLUDE_TYPE;
typedef ID3D10Blob* LPD3DXBUFFER;
typedef void* LPD3DXCONSTANTTABLE;
#endif // #ifdef DX10_V00_PC
//
// No DX configuration
#ifndef DX_PROXY_INC_CONFIG
# error "DX9_PC or DX9_X360 must be defined!"
#endif // #ifndef DX_PROXY_INC_CONFIG
//
// ExtractDependencies
//
// Retrieves all the additional required binaries from the resources and
// places them to a temporary location. Then the binaries are mapped into
// the address space of the calling process.
//
static BOOL ExtractDependencies( void )
{
return TRUE;
/*
BOOL bResult = TRUE;
char chSyncName[0x30];
char const *szDllVersion = GetDllVersion();
sprintf( chSyncName, "%s_MTX", szDllVersion );
HANDLE hMutex = ::CreateMutex( NULL, FALSE, chSyncName );
if ( !hMutex )
return FALSE;
DWORD dwWaitResult = ::WaitForSingleObject( hMutex, INFINITE );
if ( dwWaitResult != WAIT_OBJECT_0 )
return FALSE;
// Now we own the mutex
char chExtractPath[0x100] = { 0 };
if ( char const *pszTemp = getenv( "TEMP" ) )
sprintf( chExtractPath, "%s\\", pszTemp );
else if ( char const *pszTmp = getenv( "TMP" ) )
sprintf( chExtractPath, "%s\\", pszTmp );
else
bResult = FALSE;
if ( bResult )
{
sprintf( chExtractPath + strlen( chExtractPath ), "%s", szDllVersion );
bResult = ::CreateDirectory( chExtractPath, NULL );
if ( bResult )
{
sprintf( chExtractPath + strlen( chExtractPath ), "\\" );
char const * const arrNames[] = {
#ifdef DX9_V33_PC
"d3dx9_33.dll", MAKEINTRESOURCE( 1 ),
#else
#endif
NULL
};
// Now loop over the names
for ( int k = 0; k < sizeof( arrNames ) / ( 2 * sizeof( arrNames[0] ) ); ++ k )
{
char const * const &szName = arrNames[ 2 * k ];
char const * const &szResource = 1[ &szName ];
char chCreateFileName[0x200];
sprintf( chCreateFileName, "%s%s", chExtractPath, szName );
HANDLE hFile = CreateFile( chCreateFileName, FILE_ALL_ACCESS, FILE_SHARE_READ, NULL, CREATE_NEW,
FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_DELETE_ON_CLOSE, NULL );
#error "This is how you can create temp needed resources"
}
}
}
::ReleaseMutex( hMutex );
::CloseHandle( hMutex );
return bResult;
*/
}
// DLL entry point: DllMain
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
)
{
/*UNUSED_ALWAYS*/( hinstDLL );
/*UNUSED_ALWAYS*/( lpvReserved );
switch ( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Process is attaching - make sure it can find the dependencies
return ExtractDependencies();
}
return TRUE;
}
// Obtain DLL version
#pragma comment(linker, "/EXPORT:GetDllVersionLong=?GetDllVersionLong@@YGPBDXZ")
const char * WINAPI GetDllVersionLong( void )
{
#if defined( DX9_V00_PC ) && defined( _DEBUG )
return "{DX_PROXY for DX9_V00_PC DEBUG}";
#endif
#if defined( DX9_V00_PC ) && defined( NDEBUG )
return "{DX_PROXY for DX9_V00_PC RELEASE}";
#endif
#if defined( DX9_V00_X360 ) && defined( _DEBUG )
return "{DX_PROXY for DX9_V00_X360 DEBUG}";
#endif
#if defined( DX9_V00_X360 ) && defined( NDEBUG )
return "{DX_PROXY for DX9_V00_X360 RELEASE}";
#endif
#if defined( DX9_V30_PC ) && defined( _DEBUG )
return "{DX_PROXY for DX9_V30_PC DEBUG}";
#endif
#if defined( DX9_V30_PC ) && defined( NDEBUG )
return "{DX_PROXY for DX9_V30_PC RELEASE}";
#endif
#if defined( DX10_V00_PC ) && defined( _DEBUG )
return "{DX_PROXY for DX10_V00_PC DEBUG}";
#endif
#if defined( DX10_V00_PC ) && defined( NDEBUG )
return "{DX_PROXY for DX10_V00_PC RELEASE}";
#endif
}
#pragma comment(linker, "/EXPORT:GetDllVersion=?GetDllVersion@@YGPBDXZ")
const char * WINAPI GetDllVersion( void )
{
#if defined( DX9_V00_PC ) && defined( _DEBUG )
return "DXPRX_DX9_V00_PC_d";
#endif
#if defined( DX9_V00_PC ) && defined( NDEBUG )
return "DXPRX_DX9_V00_PC_r";
#endif
#if defined( DX9_V00_X360 ) && defined( _DEBUG )
return "DXPRX_DX9_V00_X360_d";
#endif
#if defined( DX9_V00_X360 ) && defined( NDEBUG )
return "DXPRX_DX9_V00_X360_r";
#endif
#if defined( DX9_V30_PC ) && defined( _DEBUG )
return "DXPRX_DX9_V30_PC_d";
#endif
#if defined( DX9_V30_PC ) && defined( NDEBUG )
return "DXPRX_DX9_V30_PC_r";
#endif
#if defined( DX10_V00_PC ) && defined( _DEBUG )
return "DXPRX_DX10_V00_PC_d";
#endif
#if defined( DX10_V00_PC ) && defined( NDEBUG )
return "DXPRX_DX10_V00_PC_r";
#endif
}
#include "filememcache.h"
#include "dxincludeimpl.h"
char s_dummyBuffer[ 512 ];
// Proxied routines
//__declspec(dllexport) - undef this to figure out the new decorated name in case you update the direct3d headers
HRESULT WINAPI
Proxy_D3DXCompileShaderFromFile(
LPCSTR pSrcFile,
CONST D3DXMACRO* pDefines,
LPD3DXINCLUDE pInclude,
LPCSTR pFunctionName,
LPCSTR pProfile,
DWORD Flags,
LPD3DXBUFFER* ppShader,
LPD3DXBUFFER* ppErrorMsgs,
LPD3DXCONSTANTTABLE* ppConstantTable )
{
if ( !pInclude )
pInclude = &s_incDxImpl;
// Open the top-level file via our include interface
LPCVOID lpcvData;
UINT numBytes;
HRESULT hr = pInclude->Open( ( D3DXINCLUDE_TYPE ) 0, pSrcFile, NULL, &lpcvData, &numBytes
#if defined( DX9_V00_X360 )
, s_dummyBuffer, sizeof( s_dummyBuffer )
#endif
);
if ( FAILED( hr ) )
return hr;
LPCSTR pShaderData = ( LPCSTR ) lpcvData;
#if defined( DX9_V00_PC ) || defined( DX9_V30_PC ) || defined( DX9_V00_X360 )
#pragma comment(linker, "/EXPORT:Proxy_D3DXCompileShaderFromFile=?Proxy_D3DXCompileShaderFromFile@@YGJPBDPBU_D3DXMACRO@@PAUID3DXInclude@@00KPAPAUID3DXBuffer@@3PAPAUID3DXConstantTable@@@Z")
hr = D3DXCompileShader( pShaderData, numBytes, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable );
#endif
#if defined( DX10_V00_PC )
#pragma comment(linker, "/EXPORT:Proxy_D3DXCompileShaderFromFile=?Proxy_D3DXCompileShaderFromFile@@YGJPBDPBU_D3D_SHADER_MACRO@@PAUID3DInclude@@00KPAPAUID3D10Blob@@3PAPAX@Z")
hr = D3DX10CompileFromMemory( pShaderData, numBytes, pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, 0, NULL, ppShader, ppErrorMsgs, NULL );
#endif
// Close the file
pInclude->Close( lpcvData );
return hr;
}

View File

@@ -0,0 +1,38 @@
$Project "dx_proxy_dx9_v00_pc"
{
"utils\dx_proxy\dx_proxy_dx9_v00_pc.vpc" [$WINDOWS]
}
$Project "dx_proxy_dx9_v30_pc"
{
"utils\dx_proxy\dx_proxy_dx9_v30_pc.vpc" [$WINDOWS]
}
$Project "dx_proxy_dx9_v00_x360"
{
"utils\dx_proxy\dx_proxy_dx9_v00_x360.vpc" [$WINDOWS]
}
$Project "dx_proxy_dx10_v00_pc"
{
"utils\dx_proxy\dx_proxy_dx10_v00_pc.vpc" [$WINDOWS]
}
$Project "dx_proxy_ps3"
{
"utils\dx_proxy\dx_proxy_ps3.vpc" [$WINDOWS]
}
$Group "dx_proxy" "source" "everything"
{
"dx_proxy_dx10_v00_pc"
"dx_proxy_dx9_v00_pc"
"dx_proxy_dx9_v30_pc"
//"dx_proxy_dx9_v00_x360"
"dx_proxy_ps3"
}

View File

@@ -0,0 +1,76 @@
//
// dx_proxy_base.vpc
//
// Base script for generating dx_proxy.dll for different
// versions of Microsoft DirectX SDK
//
$MacroRequired "SRCDIR"
$MacroRequired "OUTBINDIR"
$MacroRequired "DX_SDK_VER"
$Macro OUTBINNAME "dx_proxy"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration "Debug"
{
$General
{
$OutputDirectory ".\Debug_$DX_SDK_VER"
$IntermediateDirectory ".\Debug_$DX_SDK_VER"
}
}
$Configuration "Release"
{
$General
{
$OutputDirectory ".\Release_$DX_SDK_VER"
$IntermediateDirectory ".\Release_$DX_SDK_VER"
}
}
$Configuration
{
$General
{
$TargetName "dx_proxy"
}
$Compiler
{
$PreprocessorDefinitions "$BASE;DX_PROXY_EXPORTS;$DX_SDK_VER"
$EnableC++Exceptions "Yes (/EHsc)"
}
$Linker
{
$IgnoreSpecificLibrary "libcp.lib; libcpd.lib"
}
}
$Project
{
$Folder "Source Files"
{
-$File "$SRCDIR\public\tier0\memoverride.cpp"
$File "dx_proxy.cpp"
$File "filememcache.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\common\dx_proxy\dx_proxy.h"
$File "dxincludeimpl.h"
$File "filememcache.h"
}
$Folder "Link Libraries"
{
-$File "$SRCDIR\lib\public\tier0.lib"
-$File "$SRCDIR\lib\public\tier1.lib"
-$File "$SRCDIR\lib\public\vstdlib.lib"
}
}

View File

@@ -0,0 +1,17 @@
//
// dx_proxy_dx10_v00_pc.vpc
//
// Base script for generating dx_proxy.dll for specific
// version of Microsoft DirectX SDK:
// DirectX10 from April 2007 SDK
//
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\dx10sdk\utilities\dx10_40"
$Macro DX_SDK_VER "DX10_V00_PC"
$Include "dx_proxy_base.vpc"
$Project "DX_Proxy ($DX_SDK_VER)"
{
}

View File

@@ -0,0 +1,17 @@
//
// dx_proxy_dx9_v00_pc.vpc
//
// Base script for generating dx_proxy.dll for specific
// version of Microsoft DirectX SDK:
// DirectX9 - oldest legacy version
//
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\dx9sdk\utilities"
$Macro DX_SDK_VER "DX9_V00_PC"
$Include "dx_proxy_base.vpc"
$Project "DX_Proxy ($DX_SDK_VER)"
{
}

View File

@@ -0,0 +1,55 @@
//
// dx_proxy_dx9_v00_x360.vpc
//
// Base script for generating dx_proxy.dll for specific
// version of Microsoft DirectX SDK:
// DirectX9 XBox 360 XDK
//
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\x360xdk\bin\win32"
$Macro DX_SDK_VER "DX9_V00_X360"
$Include "dx_proxy_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;$(XEDK)\include\win32"
}
$Linker
{
$AdditionalLibraryDirectories "$BASE;$(XEDK)\lib\win32\vs2010"
}
}
$Configuration "Debug"
{
$Linker
{
$AdditionalDependencies "$BASE d3d9d.lib d3dx9d.lib xgraphicsd.lib"
}
$Compiler
{
$PreprocessorDefinitions "$BASE;_HAS_ITERATOR_DEBUGGING=1" // _HAS_ITERATOR_DEBUGGING=0 was in source_dll_win32_debug.vpc, but we need it to be 1
// to work with DirectX debug libs. This builds fine for me, and AaronS agrees overriding
// the value here is a better pattern than manually copying everything from all included
// vpc scripts. However, neither of us would be surprised if this breaks.
// -Ted Rivera
}
}
$Configuration "Release"
{
$Linker
{
$AdditionalDependencies "$BASE d3d9.lib d3dx9.lib xgraphics.lib"
}
}
$Project "DX_Proxy ($DX_SDK_VER)"
{
}

View File

@@ -0,0 +1,17 @@
//
// dx_proxy_dx9_v30_pc.vpc
//
// Base script for generating dx_proxy.dll for specific
// version of Microsoft DirectX SDK:
// DirectX9 ver 33 from April 2007 SDK
//
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\dx10sdk\utilities\dx9_30"
$Macro DX_SDK_VER "DX9_V30_PC"
$Include "dx_proxy_base.vpc"
$Project "DX_Proxy ($DX_SDK_VER)"
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
//
// dx_proxy_dx9_v30_pc.vpc
//
// Base script for generating dx_proxy.dll for specific
// version of Microsoft DirectX SDK:
// DirectX9 ver 33 from April 2007 SDK
//
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\ps3sdk\utilities"
$Macro DX_SDK_VER "DX_PS3"
$Include "dx_proxy_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;$SRCDIR\ps3sdk\cell\host-win32\cg\include;$SRCDIR\ps3sdk\cell\host-common\include"
}
$Linker
{
$AdditionalDependencies "$BASE $SRCDIR\ps3sdk\cell\host-win32\cg\lib\libcgc.lib $SRCDIR\dx10sdk\Lib\x86\dxguid.lib $SRCDIR\ps3sdk\cell\host-win32\cg\lib\SCEShaderPerf.lib"
}
}
$Project "DX_Proxy ($DX_SDK_VER)"
{
$Folder "Source Files"
{
-$File "dx_proxy.cpp"
$File "dx_proxy_ps3.cpp"
}
}

View File

@@ -0,0 +1,52 @@
//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef DXINCLUDEIMPL_H
#define DXINCLUDEIMPL_H
#ifdef _WIN32
#pragma once
#endif
FileCache s_incFileCache;
struct DxIncludeImpl : public ID3DXInclude
{
STDMETHOD(Open)(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
{
CachedFileData *pFileData = s_incFileCache.Get( pFileName );
if ( !pFileData || !pFileData->IsValid() )
return E_FAIL;
*ppData = pFileData->GetDataPtr();
*pBytes = pFileData->GetDataLen();
pFileData->UpdateRefCount( +1 );
return S_OK;
}
STDMETHOD(Open)(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData,
LPCVOID *ppData, UINT *pBytes,
/* OUT */ LPSTR pFullPath, DWORD cbFullPath)
{
if ( pFullPath && cbFullPath ) strncpy( pFullPath, pFileName, cbFullPath );
return Open( IncludeType, pFileName, pParentData, ppData, pBytes );
}
STDMETHOD(Close)(THIS_ LPCVOID pData)
{
if ( CachedFileData *pFileData = CachedFileData::GetByDataPtr( pData ) )
pFileData->UpdateRefCount( -1 );
return S_OK;
}
};
DxIncludeImpl s_incDxImpl;
#endif // #ifndef DXINCLUDEIMPL_H

View File

@@ -0,0 +1,118 @@
//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "filememcache.h"
namespace {
unsigned long s_ulCachedFileSignature = 0xCACEF11E;
};
//
// Cached file data implementation
//
CachedFileData * CachedFileData::Create( char const *szFilename )
{
FILE *f = fopen( szFilename, "rb" );
int nSize = -1;
if ( f )
{
fseek( f, 0, SEEK_END );
nSize = ftell( f );
fseek( f, 0, SEEK_SET );
}
CachedFileData *pData = ( CachedFileData * ) malloc( eHeaderSize + MAX( nSize + 1, 0 ) );
strcpy( pData->m_chFilename, szFilename );
pData->m_numRefs = 0;
pData->m_numDataBytes = nSize;
pData->m_signature = s_ulCachedFileSignature;
if ( f )
{
fread( pData->m_data, 1, nSize, f );
pData->m_data[nSize] = '\0';
fclose( f );
}
return pData;
}
void CachedFileData::Free( void )
{
free( this );
}
CachedFileData *CachedFileData::GetByDataPtr( void const *pvDataPtr )
{
unsigned char const *pbBuffer = reinterpret_cast< unsigned char const * >( pvDataPtr );
// Assert( pbBuffer );
CachedFileData const *pData = reinterpret_cast< CachedFileData const * >( pbBuffer - eHeaderSize );
// Assert( pData->m_signature == s_ulCachedFileSignature );
return const_cast< CachedFileData * >( pData );
}
char const * CachedFileData::GetFileName() const
{
return m_chFilename;
}
void const * CachedFileData::GetDataPtr() const
{
return m_data;
}
int CachedFileData::GetDataLen() const
{
return MAX( m_numDataBytes, 0 );
}
bool CachedFileData::IsValid() const
{
return ( m_numDataBytes >= 0 );
}
//
// File cache implementation
//
FileCache::FileCache()
{
NULL;
}
CachedFileData * FileCache::Get( char const *szFilename )
{
// Search the cache first
Mapping::iterator it = m_map.find( szFilename );
if ( it != m_map.end() )
return it->second;
// Create the cached file data
CachedFileData *pData = CachedFileData::Create( szFilename );
if ( pData )
m_map.insert( Mapping::value_type( pData->GetFileName(), pData ) );
return pData;
}
void FileCache::Clear()
{
for ( Mapping::iterator it = m_map.begin(), itEnd = m_map.end(); it != itEnd; ++ it )
{
it->second->Free();
}
m_map.clear();
}

View File

@@ -0,0 +1,68 @@
//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef FILEMEMCACHE_H
#define FILEMEMCACHE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
#include "tier0/basetypes.h"
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
#include <hash_map>
#pragma warning ( disable : 4200 )
class CachedFileData
{
friend class FileCache;
protected: // Constructed by FileCache
CachedFileData() {}
static CachedFileData *Create( char const *szFilename );
void Free( void );
public:
static CachedFileData *GetByDataPtr( void const *pvDataPtr );
char const * GetFileName() const;
void const * GetDataPtr() const;
int GetDataLen() const;
int UpdateRefCount( int iDeltaRefCount ) { return m_numRefs += iDeltaRefCount; }
bool IsValid() const;
protected:
enum { eHeaderSize = 256 };
char m_chFilename[256 - 12];
int m_numRefs;
int m_numDataBytes;
int m_signature;
unsigned char m_data[0]; // file data spans further
};
class FileCache
{
public:
FileCache();
~FileCache() { Clear(); }
public:
CachedFileData *Get( char const *szFilename );
void Clear( void );
protected:
struct icmp { bool operator()( char const *x, char const *y ) const { return _stricmp( x, y ) < 0; } };
typedef stdext::hash_map< char const *, CachedFileData *, stdext::hash_compare< char const *, icmp > > Mapping;
Mapping m_map;
};
#endif // #ifndef FILEMEMCACHE_H

36
utils/fbx2dmx/fbx2dmx.vpc Normal file
View File

@@ -0,0 +1,36 @@
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
$Include "$SRCDIR\vpc_scripts\fbx.vpc"
$Project "fbx2dmx"
{
$Folder "Source Files"
{
$File "main.cpp"
}
$Folder "Link Libraries"
{
$Lib appframework
$Lib bitmap
$Lib bonesetup
$Lib mathlib_extended
$Lib mathlib
$Lib datamodel
$Lib dmserializers
$Lib dmeutils
$Lib fbxutils
$Lib meshutils
$Lib movieobjects
$Lib resourcefile
$Lib tier2
}
}

771
utils/fbx2dmx/main.cpp Normal file
View File

@@ -0,0 +1,771 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ==========++;
//
//=============================================================================
// Valve includes
#include "appframework/appframework.h"
#include "appframework/tier3app.h"
#include "datamodel/dmelement.h"
#include "datamodel/dmelementfactoryhelper.h"
#include "datamodel/idatamodel.h"
#include "fbxsystem/ifbxsystem.h"
#include "fbxutils/dmfbxserializer.h"
#include "filesystem.h"
#include "icommandline.h"
#include "mathlib/mathlib.h"
#include "movieobjects/dmeaxissystem.h"
#include "movieobjects/dmefaceset.h"
#include "movieobjects/dmematerial.h"
#include "movieobjects/dmemesh.h"
#include "movieobjects/dmemodel.h"
#include "movieobjects/dmobjserializer.h"
#include "dmserializers/idmserializers.h"
#include "istudiorender.h"
#ifdef SOURCE2
#include "resourcesystem/resourcehandletypes.h"
#endif
#include "tier1/tier1.h"
#include "tier2/tier2.h"
#include "tier2/tier2dm.h"
#include "tier3/tier3.h"
#include "tier2/p4helpers.h"
#include "p4lib/ip4.h"
// Last include
#include "tier0/memdbgon.h"
class CStudioDataCache : public CBaseAppSystem < IStudioDataCache >
{
public:
bool VerifyHeaders( studiohdr_t *pStudioHdr );
vertexFileHeader_t *CacheVertexData( studiohdr_t *pStudioHdr );
};
static CStudioDataCache g_StudioDataCache;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CStudioDataCache, IStudioDataCache, STUDIO_DATA_CACHE_INTERFACE_VERSION, g_StudioDataCache );
/*
=================
VerifyHeaders
Minimal presence and header validation, no data loads
Return true if successful, false otherwise.
=================
*/
bool CStudioDataCache::VerifyHeaders( studiohdr_t *pStudioHdr )
{
// default valid
return true;
}
/*
=================
CacheVertexData
Cache model's specified dynamic data
=================
*/
vertexFileHeader_t *CStudioDataCache::CacheVertexData( studiohdr_t *pStudioHdr )
{
// minimal implementation - return persisted data
return ( vertexFileHeader_t* )pStudioHdr->VertexBase();
}
//-----------------------------------------------------------------------------
//
// Search for a material by name by generating resource names and seeing if
// the resource exists on disk in content and then game and then on user
// specified material search paths
//
// If a material file cannot be found, the original name is copied and false
// is returned
//
//-----------------------------------------------------------------------------
template <size_t maxLenInChars> bool FindMaterialResource( OUT_Z_ARRAY char (&szMaterialResourceName)[maxLenInChars], const char *pszMaterialName, const CUtlVector< CUtlString > &materialSearchPathList )
{
#ifdef SOURCE2
char szResourceName[MAX_PATH] = { 0 };
char szResourceFullPath[MAX_PATH] = { 0 };
char szMaterialPath[MAX_PATH] = { 0 };
ResourcePathGenerationType_t pSearchPaths[] =
{
RESOURCE_PATH_CONTENT,
RESOURCE_PATH_GAME
};
for ( int s = 0; s < ARRAYSIZE( pSearchPaths ); ++s )
{
// Check if current material is valid
FixupResourceName( pszMaterialName, RESOURCE_TYPE_MATERIAL, szResourceName, ARRAYSIZE( szResourceName ) );
if ( GenerateStandardFullPathForResourceName( szResourceName, pSearchPaths[s], szResourceFullPath, ARRAYSIZE( szResourceFullPath ) ) )
{
V_strcpy_safe( szMaterialResourceName, szResourceName );
return true;
}
}
// Loop through material search paths and try to find the material
for ( int s = 0; s < ARRAYSIZE( pSearchPaths ); s++ )
{
for ( int i = 0; i < materialSearchPathList.Count(); ++i )
{
V_ComposeFileName( materialSearchPathList[i].Get(), pszMaterialName, szMaterialPath, ARRAYSIZE( szMaterialPath ) );
FixupResourceName( szMaterialPath, RESOURCE_TYPE_MATERIAL, szResourceName, ARRAYSIZE( szResourceName ) );
if ( GenerateStandardFullPathForResourceName( szResourceName, pSearchPaths[s], szResourceFullPath, ARRAYSIZE( szResourceFullPath ) ) )
{
V_strcpy_safe( szMaterialResourceName, szResourceName );
return true;
}
}
}
V_strcpy_safe( szMaterialResourceName, pszMaterialName );
#endif
return false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
static void RemapMaterials( const CUtlVector< CUtlString > &materialSearchPathList )
{
char szResourceName[MAX_PATH] = {};
char szMaterialName[MAX_PATH] = {};
// Loop through all nodes in the
for ( DmElementHandle_t hElement = g_pDataModel->FirstAllocatedElement(); hElement != DMELEMENT_HANDLE_INVALID; hElement = g_pDataModel->NextAllocatedElement( hElement ) )
{
CDmeMesh *pDmeMesh = CastElement< CDmeMesh >( g_pDataModel->GetElement( hElement ) );
if ( !pDmeMesh )
continue;
for ( int i = 0; i < pDmeMesh->FaceSetCount(); ++i )
{
CDmeFaceSet *pDmeFaceSet = pDmeMesh->GetFaceSet( i );
CDmeMaterial *pDmeMaterial = pDmeFaceSet->GetMaterial();
// Check if current material is valid, and just set the standard name found anyway
if ( FindMaterialResource( szResourceName, pDmeMaterial->GetMaterialName(), materialSearchPathList ) )
{
V_FileBase( szResourceName, szMaterialName, ARRAYSIZE( szMaterialName ) );
pDmeMaterial->SetName( szMaterialName );
pDmeMaterial->SetMaterial( szResourceName );
continue;
}
{
bool bFound = false;
const char *szSuffixes[] = { "_color." };
FbxString sTmpResourceName = pDmeMaterial->GetMaterialName();
for ( int i = 0; i < ARRAYSIZE( szSuffixes ); ++i )
{
if ( sTmpResourceName.FindAndReplace( szSuffixes[i], "." ) )
{
if ( FindMaterialResource( szResourceName, sTmpResourceName.Buffer(), materialSearchPathList ) )
{
V_FileBase( szResourceName, szMaterialName, ARRAYSIZE( szMaterialName ) );
pDmeMaterial->SetName( szMaterialName );
pDmeMaterial->SetMaterial( szResourceName );
bFound = 1;
break;
}
}
}
if ( bFound )
continue;
}
Warning( "Warning! Cannot find a material resource for material \"%s\" on mesh \"%s\"\n", pDmeMaterial->GetMaterialName(), pDmeMesh->GetName() );
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int DoIt( CDmElement *pDmRoot, const char *pszOutFilename, const CUtlVector< CUtlString > &materialSearchPathList )
{
RemapMaterials( materialSearchPathList );
CP4AutoAddFile outfile( pszOutFilename );
char szDmxFilename[MAX_PATH];
V_strncpy( szDmxFilename, pszOutFilename, ARRAYSIZE( szDmxFilename ) );
V_SetExtension( szDmxFilename, ".dmx", ARRAYSIZE( szDmxFilename ) );
CP4AutoEditAddFile dmxFile( szDmxFilename );
CDmeModel *pDmeModel = pDmRoot->GetValueElement< CDmeModel >( "model" );
if ( !pDmeModel )
{
pDmeModel = pDmRoot->GetValueElement< CDmeModel >( "skeleton" );
}
Assert( pDmeModel );
CDmeAxisSystem *pDmeAxisSystem = pDmeModel->GetValueElement< CDmeAxisSystem >( "axisSystem" );
Assert( pDmeAxisSystem );
const bool bReturn = g_pDataModel->SaveToFile( szDmxFilename, NULL, "keyvalues2", "model", pDmRoot );
g_pDataModel->UnloadFile( pDmRoot->GetFileId() );
return bReturn ? 0 : -1;
}
bool ProcessAxisSystem( CDmFbxSerializer &dmFbxSerializer );
//-----------------------------------------------------------------------------
// DEFINE_CONSOLE_APPLICATION in Source2
//-----------------------------------------------------------------------------
class CFbx2DmxApp : public CDefaultAppSystemGroup < CSteamAppSystemGroup >
{
typedef CDefaultAppSystemGroup< CSteamAppSystemGroup > BaseClass;
public:
CFbx2DmxApp()
{
m_pszOptForceMod = NULL;
m_bOptUFC = false;
m_nOptVerbosity = 0;
m_bOptAnimation = false;
m_bOptPrintSearchPaths = false;
m_pszOptFilename = NULL;
m_pszOptOutFilename = NULL;
}
virtual bool Create() OVERRIDE;
virtual int Main() OVERRIDE;
virtual bool PreInit() OVERRIDE
{
CreateInterfaceFn factory = GetFactory();
ConnectTier1Libraries( &factory, 1 );
ConnectTier2Libraries( &factory, 1 );
if ( !g_pFullFileSystem )
return false;
if ( !g_pCVar )
return false;
ConVar_Register();
return true;
}
virtual void PostShutdown() OVERRIDE
{
ConVar_Unregister();
DisconnectTier2Libraries();
DisconnectTier1Libraries();
}
protected:
const char *m_pszOptFilename;
int m_nOptVerbosity;
bool m_bOptAnimation;
bool m_bOptPrintSearchPaths;
bool m_bOptUFC;
const char *m_pszOptForceMod;
CUtlVector< CUtlString > m_sOptMaterialSearchPaths;
const char *m_pszOptOutFilename;
protected:
bool ParseArguments();
};
static bool CStudioMDLApp_SuggestGameInfoDirFn( CFSSteamSetupInfo const *pFsSteamSetupInfo, char *pchPathBuffer, int nBufferLength, bool *pbBubbleDirectories )
{
const char *pProcessFileName = NULL;
int nParmCount = CommandLine()->ParmCount();
if ( nParmCount > 1 )
{
pProcessFileName = CommandLine()->GetParm( nParmCount - 1 );
}
if ( pProcessFileName )
{
Q_MakeAbsolutePath( pchPathBuffer, nBufferLength, pProcessFileName );
if ( pbBubbleDirectories )
*pbBubbleDirectories = true;
return true;
}
return false;
}
int main( int argc, char **argv )
{
SetSuggestGameInfoDirFn( CStudioMDLApp_SuggestGameInfoDirFn );
CFbx2DmxApp s_ApplicationObject;
CSteamApplication s_SteamApplicationObject( &s_ApplicationObject );
return AppMain( argc, argv, &s_SteamApplicationObject );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
static void PrintUsage()
{
Msg( "\n" );
Msg( "NAME\n" );
Msg( " fbx2dmx - Converts an FBX file to a DMX file\n" );
Msg( "\n" );
Msg( "SYNOPSIS\n" );
Msg( " fbx2dmx [ opts ... ] < filename.fbx >\n" );
Msg( "\n" );
Msg( " -h | -help . . . . . . . . . . . Prints this information\n" );
Msg( " -nop4 . . . . . . . . . . . . . Turns off Perforce integration\n" );
Msg( " -i | -input <$> . . . . . . . . Specifies the input filename\n" );
Msg( " -o | -output <$> . . . . . . . Specifies the output filename\n" );
Msg( " -ufc . . . . . . . . . . . . . . _'s in delta names means they are\n"
" corrective states\n" );
Msg( " -v . . . . . . . . . . . . . . . Each -v increases verbosity\n" );
Msg( " -a . . . . . . . . . . . . . . . Convert animation, normally models are\n"
" converted\n" );
Msg( " -msp | -materialSearchPath <$> . Specify a material search path to remap\n"
" materials to\n" );
Msg( " -psp . . . . . . . . . . . . . . Print the search paths that will be used\n" );
Msg( " -up . . . . . . . . . . . . . . One of [ x, y, z, -x, -y, -z ], Def: y\n" );
Msg( " -fp | -forwardParity . . . . . One of [ even, odd, -even, -odd ], Def: x\n" );
Msg( "\n" );
Msg( "DESCRIPTION\n" );
Msg( " Converts an FBX file to a DMX file. File is saved in same location as FBX\n"
" file with extension changed\n" );
Msg( "\n" );
Msg( " If -i isn't specified then any argument that isn't associated with a command\n"
" line switch is considered to be the input.\n" );
Msg( "\n" );
Msg( " If -o isn't specified then the extension of the input is changed to be .fbx\n"
" and used as the output filename.\n" );
Msg( "\n" );
Msg( "AXIS SYSTEM\n" );
Msg( " To specify the axis system the resulting DMX file will contain, the\n"
" combination of -up & -parity is used. -up specifies which axis is to be\n"
" the up axis, prefix the x, y, or z with a minus to specify the negative\n"
" axis. -forwardParity specifies the forward axis. Of the remaining two\n"
" axes left after up is specified, parity specifies which of them,\n"
" alphabetically, will be the forward, even being the first odd being the\n"
" second. i.e. If Y is up, then even means X, odd means Z. Again prefix\n"
" with a minus for the negative axis.\n"
"\n"
" e.g. To specify Maya Y Up which is +Y up and +Z forward: -up y -fp odd\n"
" To specify Valve Engine which is +Z up and +X forward: -up z -fp even\n" );
Msg( "\n" );
Msg( "\n" );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool ProcessAxisSystem( CDmFbxSerializer &dmFbxSerializer )
{
// Defaults
dmFbxSerializer.m_eOptUpAxis = CDmeAxisSystem::AS_AXIS_Y;
dmFbxSerializer.m_eOptForwardParity = CDmeAxisSystem::AS_PARITY_ODD;
const int nParmCount = CommandLine()->ParmCount();
const int nUpIndex = CommandLine()->FindParm( "-up" );
if ( nUpIndex > 0 )
{
if ( nUpIndex < ( nParmCount - 1 ) ) // Ensure there's a parameter value after -up
{
const char *pszUp = CommandLine()->GetParm( nUpIndex + 1 );
if ( pszUp )
{
if ( StringHasPrefix( pszUp, "x" ) )
{
dmFbxSerializer.m_eOptUpAxis = CDmeAxisSystem::AS_AXIS_X;
}
else if ( StringHasPrefix( pszUp, "y" ) )
{
dmFbxSerializer.m_eOptUpAxis = CDmeAxisSystem::AS_AXIS_Y;
}
else if ( StringHasPrefix( pszUp, "z" ) )
{
dmFbxSerializer.m_eOptUpAxis = CDmeAxisSystem::AS_AXIS_Z;
}
else if ( StringHasPrefix( pszUp, "-x" ) )
{
dmFbxSerializer.m_eOptUpAxis = CDmeAxisSystem::AS_AXIS_NX;
}
else if ( StringHasPrefix( pszUp, "-y" ) )
{
dmFbxSerializer.m_eOptUpAxis = CDmeAxisSystem::AS_AXIS_NY;
}
else if ( StringHasPrefix( pszUp, "-z" ) )
{
dmFbxSerializer.m_eOptUpAxis = CDmeAxisSystem::AS_AXIS_NZ;
}
else
{
Warning( "Error! Invalid -up value specified, must be one of -up [ x, y, z, -x, -y, -z ]: \"%s\"\n", pszUp );
return false;
}
}
else
{
Warning( "Error! No parameter specified after -up, must be one of -up [ x, y, z, -x, -y, -z ]\n" );
return false;
}
}
else
{
Warning( "Error! No parameter specified after -up, must be one of -up [ x, y, z, -x, -y, -z ]\n" );
return false;
}
}
int nFpIndex = 0;
const char *szFp[] = { "-fp", "-forwardParity", "-forwardParity" };
for ( int i = 0; i < ARRAYSIZE( szFp ); ++i )
{
const int nTmpFpIndex = CommandLine()->FindParm( szFp[i] );
if ( nTmpFpIndex > 0 )
{
if ( nTmpFpIndex < nParmCount - 1 )
{
nFpIndex = nTmpFpIndex;
break;
}
else
{
Warning( "Error! No parameter specified after %s, must be one of %s [ even, odd, -even, -odd ]\n", CommandLine()->GetParm( nTmpFpIndex ), CommandLine()->GetParm( nTmpFpIndex ) );
return false;
}
}
}
if ( nFpIndex > 0 )
{
const char *pszFp = CommandLine()->GetParm( nFpIndex + 1 );
if ( pszFp )
{
if ( StringHasPrefix( pszFp, "e" ) )
{
dmFbxSerializer.m_eOptForwardParity = CDmeAxisSystem::AS_PARITY_EVEN;
}
else if ( StringHasPrefix( pszFp, "o" ) )
{
dmFbxSerializer.m_eOptForwardParity = CDmeAxisSystem::AS_PARITY_ODD;
}
else if ( StringHasPrefix( pszFp, "-e" ) )
{
dmFbxSerializer.m_eOptForwardParity = CDmeAxisSystem::AS_PARITY_NEVEN;
}
else if ( StringHasPrefix( pszFp, "-o" ) )
{
dmFbxSerializer.m_eOptForwardParity = CDmeAxisSystem::AS_PARITY_NODD;
}
else
{
Warning( "Error! Invalid -forwardParity value specified, must be one of [ even, odd, -even, -odd ]: \"%s\"\n", pszFp );
return false;
}
}
else
{
Warning( "Error! No parameter specified after %s, must be one of %s [ even, odd, -even, -odd ]\n", CommandLine()->GetParm( nFpIndex ), CommandLine()->GetParm( nFpIndex ) );
return false;
}
}
return true;
}
bool CFbx2DmxApp::Create()
{
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
if ( !ParseArguments() )
{
return false;
}
AppSystemInfo_t appSystems[] =
{
{ "vstdlib.dll", PROCESS_UTILS_INTERFACE_VERSION },
{ "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
{ "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
{ "mdllib.dll", MDLLIB_INTERFACE_VERSION },
{ "filesystem_stdio.dll", FILESYSTEM_INTERFACE_VERSION },
{ "p4lib.dll", P4_INTERFACE_VERSION },
{ "", "" } // Required to terminate the list
};
AddSystem( g_pDataModel, VDATAMODEL_INTERFACE_VERSION );
AddSystem( g_pDmElementFramework, VDMELEMENTFRAMEWORK_VERSION );
AddSystem( g_pDmSerializers, DMSERIALIZERS_INTERFACE_VERSION );
// Add in the locally-defined studio data cache
AppModule_t studioDataCacheModule = LoadModule( Sys_GetFactoryThis() );
AddSystem( studioDataCacheModule, STUDIO_DATA_CACHE_INTERFACE_VERSION );
// Add the P4 module separately so that if it is absent (say in the SDK) then the other system will initialize properly
if ( !CommandLine()->FindParm( "-nop4" ) )
{
AppModule_t p4Module = LoadModule( "p4lib.dll" );
AddSystem( p4Module, P4_INTERFACE_VERSION );
}
AddSystem( g_pFbx, FBX_INTERFACE_VERSION );
bool bOk = AddSystems( appSystems );
if ( !bOk )
return false;
IMaterialSystem *pMaterialSystem = ( IMaterialSystem* )FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
if ( !pMaterialSystem )
return false;
pMaterialSystem->SetShaderAPI( "shaderapiempty.dll" );
return true;
}
int CFbx2DmxApp::Main()
{
char szOptFilename[ MAX_PATH ];
// Globally disable DMX undo
g_pDataModel->SetUndoEnabled( false );
// This bit of hackery allows us to access files on the harddrive
if ( m_bOptPrintSearchPaths )
{
g_pFullFileSystem->PrintSearchPaths();
}
//p4->SetVerbose( false );
p4->SetOpenFileChangeList( "fbx2dmx" );
int nRetVal = -1;
char szExt[ MAX_PATH ] = { };
V_ExtractFileExtension( szOptFilename, szExt, ARRAYSIZE( szExt ) );
CDisableUndoScopeGuard noUndo;
CDmElement *pDmRoot = NULL;
if ( !V_stricmp( szExt, "obj" ) )
{
CDmObjSerializer dmObjSerializer;
pDmRoot = dmObjSerializer.ReadOBJ( szOptFilename );
if ( !pDmRoot )
{
Warning( "Couldn't load OBJ file: %s\n", szOptFilename );
}
}
else
{
CDmFbxSerializer dmFbxSerializer;
dmFbxSerializer.m_bOptUnderscoreForCorrectors = m_bOptUFC;
dmFbxSerializer.m_nOptVerbosity = m_nOptVerbosity;
dmFbxSerializer.m_bAnimation = m_bOptAnimation;
dmFbxSerializer.m_sOptMaterialSearchPathList = m_sOptMaterialSearchPaths;
if ( ProcessAxisSystem( dmFbxSerializer ) )
{
pDmRoot = dmFbxSerializer.ReadFBX( m_pszOptFilename );
if ( !pDmRoot )
{
Warning( "Couldn't load FBX file: %s\n", szOptFilename );
}
}
}
if ( pDmRoot )
{
if ( m_pszOptOutFilename )
{
nRetVal = DoIt( pDmRoot, m_pszOptOutFilename, m_sOptMaterialSearchPaths );
}
else
{
nRetVal = DoIt( pDmRoot, m_pszOptFilename, m_sOptMaterialSearchPaths );
}
}
return nRetVal;
}
bool CFbx2DmxApp::ParseArguments()
{
if ( CommandLine()->CheckParm( "-h" ) || CommandLine()->CheckParm( "--help" ) || CommandLine()->CheckParm( "-help" ) )
{
PrintUsage();
return false;
}
for ( int i = 1; i < CommandLine()->ParmCount(); ++i )
{
const char *pszParam = CommandLine()->GetParm( i );
if ( !V_stricmp( pszParam, "-game" ) )
{
m_pszOptForceMod = CommandLine()->GetParm( ++i );
continue;
}
if ( !V_stricmp( pszParam, "-nop4" ) )
{
continue;
}
if ( !V_stricmp( pszParam, "-ufc" ) )
{
m_bOptUFC = true;
continue;
}
if ( !V_stricmp( pszParam, "-v" ) )
{
++m_nOptVerbosity;
continue;
}
if ( !V_stricmp( pszParam, "-a" ) )
{
m_bOptAnimation = true;
continue;
}
if ( !V_stricmp( pszParam, "-msp" ) || !V_stricmp( pszParam, "-materialSearchPath" ) )
{
m_sOptMaterialSearchPaths.AddToTail( CommandLine()->GetParm( ++i ) );
continue;
}
if ( !V_stricmp( pszParam, "-psp" ) )
{
m_bOptPrintSearchPaths = true;
continue;
}
if ( !V_stricmp( pszParam, "-up" ) )
{
++i;
continue;
}
if ( !V_stricmp( pszParam, "-fp" ) || !V_stricmp( pszParam, "-forwardParity" ) || !V_stricmp( pszParam, "-forwardparity" ) )
{
++i;
continue;
}
if ( !V_stricmp( pszParam, "-i" ) || !V_stricmp( pszParam, "-input" ) )
{
++i;
pszParam = CommandLine()->GetParm( i );
if ( m_pszOptFilename )
{
Warning( "Warning! Filename was already specified as: \"%s\", using -i \"%s\"\n", m_pszOptFilename, pszParam );
}
m_pszOptFilename = pszParam;
continue;
}
if ( !V_stricmp( pszParam, "-o" ) || !V_stricmp( pszParam, "-output" ) )
{
++i;
pszParam = CommandLine()->GetParm( i );
if ( m_pszOptOutFilename )
{
Warning( "Warning! Output filename was already specified as: \"%s\", using -o \"%s\"\n", m_pszOptOutFilename, pszParam );
}
m_pszOptOutFilename = pszParam;
continue;
}
if ( StringHasPrefix( pszParam, "-" ) )
{
Warning( "Warning! Unknown command line switch \"%s\"\n", pszParam );
continue;
}
if ( m_pszOptFilename )
{
Warning( "Warning! Filename already specified: \"%s\", ignoring \"%s\"\n", m_pszOptFilename, pszParam );
}
else
{
m_pszOptFilename = pszParam;
}
}
if ( !m_pszOptFilename )
{
Warning( "Error! Cannot find any file to execute from passed command line arguments\n\n" );
PrintUsage();
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: bind studiohdr_t support functions to fbx2dmx utility
// FIXME: This should be moved into studio.cpp?
//-----------------------------------------------------------------------------
const studiohdr_t *studiohdr_t::FindModel( void **cache, char const *pModelName ) const
{
MDLHandle_t handle = g_pMDLCache->FindMDL( pModelName );
*cache = ( void* )( uintp )handle;
return g_pMDLCache->GetStudioHdr( handle );
}
virtualmodel_t *studiohdr_t::GetVirtualModel( void ) const
{
if ( numincludemodels == 0 )
return NULL;
return g_pMDLCache->GetVirtualModelFast( this, VoidPtrToMDLHandle( VirtualModel() ) );
}
byte *studiohdr_t::GetAnimBlock( int i, bool preloadIfMissing ) const
{
return g_pMDLCache->GetAnimBlock( VoidPtrToMDLHandle( VirtualModel() ), i, preloadIfMissing );
}
bool studiohdr_t::hasAnimBlockBeenPreloaded( int i ) const
{
return g_pMDLCache->HasAnimBlockBeenPreloaded( VoidPtrToMDLHandle( VirtualModel() ), i );
}
int studiohdr_t::GetAutoplayList( unsigned short **pOut ) const
{
return g_pMDLCache->GetAutoplayList( VoidPtrToMDLHandle( VirtualModel() ), pOut );
}
const studiohdr_t *virtualgroup_t::GetStudioHdr( void ) const
{
return g_pMDLCache->GetStudioHdr( VoidPtrToMDLHandle( cache ) );
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,187 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if !defined( ANIMATIONBROWSER_H )
#define ANIMATIONBROWSER_H
#ifdef _WIN32
#pragma once
#endif
#define IDC_AB_TRAYSCROLL 1001
#define IDC_AB_THUMBNAIL_INCREASE 1002
#define IDC_AB_THUMBNAIL_DECREASE 1003
#define IDC_AB_CONTEXT_CREATEBITMAP 1004
#define IDC_AB_CONTEXT_CREATEALLBITMAPS 1005
#define IDC_AB_FILTERTAB 1006
#define IDC_AB_CREATE_CUSTOM 1007
#define IDC_AB_ADDTOGROUPSTART 1100
#define IDC_AB_ADDTOGROUPEND 1199
#define IDC_AB_REMOVEFROMGROUPSTART 1200
#define IDC_AB_REMOVEFROMGROUPEND 1299
#define IDC_AB_DELETEGROUPSTART 1300
#define IDC_AB_DELETEGROUPEND 1399
#define IDC_AB_RENAMEGROUPSTART 1400
#define IDC_AB_RENAMEGROUPEND 1499
#define COLOR_TRAYBACKGROUND Color( 240, 240, 220 )
#include "faceposertoolwindow.h"
#include "StudioModel.h"
class CAnimBrowserTab;
class CCustomAnim
{
public:
CCustomAnim( const FileNameHandle_t &h )
:
m_bDirty( false ),
m_ShortName( UTL_INVAL_SYMBOL )
{
m_Handle = h;
}
void LoadFromFile();
void SaveToFile();
bool HasAnimation( char const *search );
bool m_bDirty;
CUtlSymbol m_ShortName;
FileNameHandle_t m_Handle;
CUtlVector< CUtlSymbol > m_Animations;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class AnimationBrowser : public mxWindow, public IFacePoserToolWindow
{
public:
enum
{
FILTER_NONE = 0,
FILTER_GESTURES,
FILTER_POSTURES,
FILTER_STRING,
FILTER_FIRST_CUSTOM
};
AnimationBrowser( mxWindow *parent, int id = 0 );
virtual ~AnimationBrowser ( void );
virtual void Shutdown();
virtual void redraw ();
virtual bool PaintBackground( void );
virtual int handleEvent (mxEvent *event);
virtual void Think( float dt );
void ThumbnailIncrease( void );
void ThumbnailDecrease( void );
void RestoreThumbnailSize( void );
void Select( int sequence );
void Deselect( void );
void SetCellSize( int cellsize );
void ReloadBitmaps( void );
virtual void OnModelChanged();
void OnAddCustomAnimationFilter();
private: // Methods
void OnFilter();
bool SequencePassesFilter( StudioModel *model, int sequence, mstudioseqdesc_t &seqdesc );
int GetSequenceCount();
mstudioseqdesc_t *GetSeqDesc( int index );
int TranslateSequenceNumber( int index );
int GetCellUnderPosition( int x, int y );
bool ComputeRect( int cell, int& rcx, int& rcy, int& rcw, int& rch );
int ComputePixelsNeeded( void );
void RepositionSlider();
void SetClickedCell( int cell );
void ShowRightClickMenu( int mx, int my );
void DrawThumbNail( int sequence, CChoreoWidgetDrawHelper& helper,
int rcx, int rcy, int rcw, int rch );
void DrawSequenceFocusRect( CChoreoWidgetDrawHelper& helper, int x, int y, int w, int h, const Color& clr );
void DrawSequenceDescription( CChoreoWidgetDrawHelper& helper, int x, int y, int w, int h, int sequence, mstudioseqdesc_t &seqdesc );
void DrawFocusRect( void );
// Custom group tab stuff
void FindCustomFiles( char const *subdir, CUtlVector< FileNameHandle_t >& files );
void AddCustomFile( const FileNameHandle_t& handle );
void RenameCustomFile( int index );
void DeleteCustomFile( int index );
void PurgeCustom();
void BuildCustomFromFiles( CUtlVector< FileNameHandle_t >& files );
void UpdateCustomTabs();
int FindCustomFile( char const *shortName );
void AddAnimationToCustomFile( int index, char const *animationName );
void RemoveAnimationFromCustomFile( int index, char const *animationName );
void RemoveAllAnimationsFromCustomFile( int index );
private: // Data
mxScrollbar *slScrollbar;
CAnimBrowserTab *m_pFilterTab;
mxLineEdit *m_pSearchEntry;
int m_nTopOffset;
int m_nLastNumAnimations;
int m_nGranularity;
int m_nCurCell;
int m_nClickedCell;
// Formatting
int m_nButtonSquare;
int m_nGap;
int m_nDescriptionHeight;
int m_nSnapshotWidth;
int m_nSnapshotHeight;
bool m_bDragging;
RECT m_rcFocus;
RECT m_rcOrig;
int m_nDragCell;
int m_nXStart;
int m_nYStart;
mxButton *m_pThumbnailIncreaseButton;
mxButton *m_pThumbnailDecreaseButton;
CUtlVector< int > m_Filtered;
int m_nCurFilter;
char m_szSearchString[ 256 ];
float m_flDragTime;
CUtlVector< CCustomAnim * > m_CustomAnimationTabs;
};
extern AnimationBrowser *g_pAnimationBrowserTool;
#endif // ANIMATIONBROWSER_H

View File

@@ -0,0 +1,993 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include <stdio.h>
#include "hlfaceposer.h"
#include "CloseCaptionTool.h"
#include "choreowidgetdrawhelper.h"
#include <vgui/ILocalize.h>
using namespace vgui;
CloseCaptionTool *g_pCloseCaptionTool = 0;
#define STREAM_FONT "Tahoma"
#define STREAM_POINTSIZE 12
#define STREAM_LINEHEIGHT ( STREAM_POINTSIZE + 2 )
#define STREAM_WEIGHT FW_NORMAL
#define CAPTION_LINGER_TIME 1.5f
// FIXME: Yahn, what is this, it's coded up as a DELAY before when the closed caption is displayed. That seems odd.
#define CAPTION_PREDISPLAY_TIME 0.0f // 0.5f
// A work unit is a pre-processed chunk of CC text to display
// Any state changes (font/color/etc) cause a new work unit to be precomputed
// Moving onto a new line also causes a new Work Unit
// The width and height are stored so that layout can be quickly recomputed each frame
class CCloseCaptionWorkUnit
{
public:
CCloseCaptionWorkUnit();
~CCloseCaptionWorkUnit();
void SetWidth( int w );
int GetWidth() const;
void SetHeight( int h );
int GetHeight() const;
void SetPos( int x, int y );
void GetPos( int& x, int &y ) const;
void SetBold( bool bold );
bool GetBold() const;
void SetItalic( bool ital );
bool GetItalic() const;
void SetStream( const wchar_t *stream );
const wchar_t *GetStream() const;
void SetColor( const Color& clr );
const Color& GetColor() const;
int GetFontNumber() const
{
return CloseCaptionTool::GetFontNumber( m_bBold, m_bItalic );
}
void Dump()
{
char buf[ 2048 ];
g_pLocalize->ConvertUnicodeToANSI( GetStream(), buf, sizeof( buf ) );
Msg( "x = %i, y = %i, w = %i h = %i text %s\n", m_nX, m_nY, m_nWidth, m_nHeight, buf );
}
private:
int m_nX;
int m_nY;
int m_nWidth;
int m_nHeight;
bool m_bBold;
bool m_bItalic;
wchar_t *m_pszStream;
Color m_Color;
};
CCloseCaptionWorkUnit::CCloseCaptionWorkUnit() :
m_nWidth(0),
m_nHeight(0),
m_bBold(false),
m_bItalic(false),
m_pszStream(0),
m_Color( Color( 255, 255, 255 ) )
{
}
CCloseCaptionWorkUnit::~CCloseCaptionWorkUnit()
{
delete[] m_pszStream;
m_pszStream = NULL;
}
void CCloseCaptionWorkUnit::SetWidth( int w )
{
m_nWidth = w;
}
int CCloseCaptionWorkUnit::GetWidth() const
{
return m_nWidth;
}
void CCloseCaptionWorkUnit::SetHeight( int h )
{
m_nHeight = h;
}
int CCloseCaptionWorkUnit::GetHeight() const
{
return m_nHeight;
}
void CCloseCaptionWorkUnit::SetPos( int x, int y )
{
m_nX = x;
m_nY = y;
}
void CCloseCaptionWorkUnit::GetPos( int& x, int &y ) const
{
x = m_nX;
y = m_nY;
}
void CCloseCaptionWorkUnit::SetBold( bool bold )
{
m_bBold = bold;
}
bool CCloseCaptionWorkUnit::GetBold() const
{
return m_bBold;
}
void CCloseCaptionWorkUnit::SetItalic( bool ital )
{
m_bItalic = ital;
}
bool CCloseCaptionWorkUnit::GetItalic() const
{
return m_bItalic;
}
void CCloseCaptionWorkUnit::SetStream( const wchar_t *stream )
{
delete[] m_pszStream;
m_pszStream = NULL;
int len = wcslen( stream );
Assert( len < 4096 );
m_pszStream = new wchar_t[ len + 1 ];
wcsncpy( m_pszStream, stream, len );
m_pszStream[ len ] = L'\0';
}
const wchar_t *CCloseCaptionWorkUnit::GetStream() const
{
return m_pszStream ? m_pszStream : L"";
}
void CCloseCaptionWorkUnit::SetColor( const Color& clr )
{
m_Color = clr;
}
const Color &CCloseCaptionWorkUnit::GetColor() const
{
return m_Color;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCloseCaptionItem
{
public:
CCloseCaptionItem(
wchar_t *stream,
float timetolive,
float predisplay,
bool valid
) :
m_flTimeToLive( 0.0f ),
m_bValid( false ),
m_nTotalWidth( 0 ),
m_nTotalHeight( 0 ),
m_bSizeComputed( false )
{
SetStream( stream );
SetTimeToLive( timetolive );
SetPreDisplayTime( CAPTION_PREDISPLAY_TIME + predisplay );
m_bValid = valid;
m_bSizeComputed = false;
}
CCloseCaptionItem( const CCloseCaptionItem& src )
{
SetStream( src.m_szStream );
m_flTimeToLive = src.m_flTimeToLive;
m_bValid = src.m_bValid;
}
~CCloseCaptionItem( void )
{
while ( m_Work.Count() > 0 )
{
CCloseCaptionWorkUnit *unit = m_Work[ 0 ];
m_Work.Remove( 0 );
delete unit;
}
}
void SetStream( const wchar_t *stream)
{
wcsncpy( m_szStream, stream, sizeof( m_szStream ) / sizeof( wchar_t ) );
}
const wchar_t *GetStream() const
{
return m_szStream;
}
void SetTimeToLive( float ttl )
{
m_flTimeToLive = ttl;
}
float GetTimeToLive( void ) const
{
return m_flTimeToLive;
}
bool IsValid() const
{
return m_bValid;
}
void SetHeight( int h )
{
m_nTotalHeight = h;
}
int GetHeight() const
{
return m_nTotalHeight;
}
void SetWidth( int w )
{
m_nTotalWidth = w;
}
int GetWidth() const
{
return m_nTotalWidth;
}
void AddWork( CCloseCaptionWorkUnit *unit )
{
m_Work.AddToTail( unit );
}
int GetNumWorkUnits() const
{
return m_Work.Count();
}
CCloseCaptionWorkUnit *GetWorkUnit( int index )
{
Assert( index >= 0 && index < m_Work.Count() );
return m_Work[ index ];
}
void SetSizeComputed( bool computed )
{
m_bSizeComputed = computed;
}
bool GetSizeComputed() const
{
return m_bSizeComputed;
}
void SetPreDisplayTime( float t )
{
m_flPreDisplayTime = t;
}
float GetPreDisplayTime() const
{
return m_flPreDisplayTime;
}
private:
wchar_t m_szStream[ 256 ];
float m_flPreDisplayTime;
float m_flTimeToLive;
bool m_bValid;
int m_nTotalWidth;
int m_nTotalHeight;
bool m_bSizeComputed;
CUtlVector< CCloseCaptionWorkUnit * > m_Work;
};
ICloseCaptionManager *closecaptionmanager = NULL;
CloseCaptionTool::CloseCaptionTool( mxWindow *parent )
: IFacePoserToolWindow( "CloseCaptionTool", "Close Caption" ), mxWindow( parent, 0, 0, 0, 0 )
{
m_nLastItemCount = -1;
closecaptionmanager = this;
m_hFonts[ CCFONT_NORMAL ] = CreateFont(
-STREAM_POINTSIZE,
0,
0,
0,
STREAM_WEIGHT,
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
DEFAULT_PITCH,
STREAM_FONT );
m_hFonts[ CCFONT_ITALIC ] = CreateFont(
-STREAM_POINTSIZE,
0,
0,
0,
STREAM_WEIGHT,
TRUE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
DEFAULT_PITCH,
STREAM_FONT );
m_hFonts[ CCFONT_BOLD ] = CreateFont(
-STREAM_POINTSIZE,
0,
0,
0,
700,
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
DEFAULT_PITCH,
STREAM_FONT );
m_hFonts[ CCFONT_ITALICBOLD ] = CreateFont(
-STREAM_POINTSIZE,
0,
0,
0,
700,
TRUE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_TT_PRECIS,
CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,
DEFAULT_PITCH,
STREAM_FONT );
}
CloseCaptionTool::~CloseCaptionTool( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : dt -
//-----------------------------------------------------------------------------
void CloseCaptionTool::Think( float dt )
{
int c = m_Items.Count();
int i;
// Pass one decay all timers
for ( i = 0 ; i < c ; ++i )
{
CCloseCaptionItem *item = m_Items[ i ];
float predisplay = item->GetPreDisplayTime();
if ( predisplay > 0.0f )
{
predisplay -= dt;
predisplay = max( 0.0f, predisplay );
item->SetPreDisplayTime( predisplay );
}
else
{
// remove time from actual playback
float ttl = item->GetTimeToLive();
ttl -= dt;
ttl = max( 0.0f, ttl );
item->SetTimeToLive( ttl );
}
}
// Pass two, remove from head until we get to first item with time remaining
bool foundfirstnondeletion = false;
for ( i = 0 ; i < c ; ++i )
{
CCloseCaptionItem *item = m_Items[ i ];
// Skip items not yet showing...
float predisplay = item->GetPreDisplayTime();
if ( predisplay > 0.0f )
{
continue;
}
float ttl = item->GetTimeToLive();
if ( ttl > 0.0f )
{
foundfirstnondeletion = true;
continue;
}
// Skip the remainder of the items after we find the first/oldest active item
if ( foundfirstnondeletion )
{
continue;
}
delete item;
m_Items.Remove( i );
--i;
--c;
}
if ( m_Items.Count() != m_nLastItemCount )
{
redraw();
}
m_nLastItemCount = m_Items.Count();
}
struct VisibleStreamItem
{
int height;
CCloseCaptionItem *item;
};
void CloseCaptionTool::redraw()
{
if ( !ToolCanDraw() )
return;
CChoreoWidgetDrawHelper drawHelper( this );
HandleToolRedraw( drawHelper );
RECT rcOutput;
drawHelper.GetClientRect( rcOutput );
RECT rcText = rcOutput;
drawHelper.DrawFilledRect( Color( 0, 0, 0 ), rcText );
drawHelper.DrawOutlinedRect( Color( 200, 245, 150 ), PS_SOLID, 2, rcText );
InflateRect( &rcText, -4, 0 );
int avail_width = rcText.right - rcText.left;
int totalheight = 0;
int i;
CUtlVector< VisibleStreamItem > visibleitems;
int c = m_Items.Count();
for ( i = 0; i < c; i++ )
{
CCloseCaptionItem *item = m_Items[ i ];
// Not ready for display yet.
if ( item->GetPreDisplayTime() > 0.0f )
{
continue;
}
if ( !item->GetSizeComputed() )
{
ComputeStreamWork( drawHelper, avail_width, item );
}
int itemheight = item->GetHeight();
totalheight += itemheight;
VisibleStreamItem si;
si.height = itemheight;
si.item = item;
visibleitems.AddToTail( si );
}
rcText.bottom -= 2;
rcText.top = rcText.bottom - totalheight;
// Now draw them
c = visibleitems.Count();
for ( i = 0; i < c; i++ )
{
VisibleStreamItem *si = &visibleitems[ i ];
int height = si->height;
CCloseCaptionItem *item = si->item;
rcText.bottom = rcText.top + height;
DrawStream( drawHelper, rcText, item );
OffsetRect( &rcText, 0, height );
if ( rcText.top >= rcOutput.bottom )
break;
}
}
int CloseCaptionTool::handleEvent( mxEvent *event )
{
//MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
int iret = 0;
if ( HandleToolEvent( event ) )
{
return iret;
}
return iret;
}
bool CloseCaptionTool::PaintBackground()
{
redraw();
return false;
}
void CloseCaptionTool::Reset( void )
{
while ( m_Items.Count() > 0 )
{
CCloseCaptionItem *i = m_Items[ 0 ];
delete i;
m_Items.Remove( 0 );
}
}
void CloseCaptionTool::Process( char const *tokenname, float duration, int languageid )
{
bool valid = true;
wchar_t stream[ 256 ];
if ( !LookupUnicodeText( languageid, tokenname, stream, sizeof( stream ) / sizeof( wchar_t ) ) )
{
valid = false;
g_pLocalize->ConvertANSIToUnicode( va( "--> Missing Caption[%s]", tokenname ), stream, sizeof( stream ) );
}
if ( !wcsncmp( stream, L"!!!", wcslen( L"!!!" ) ) )
{
// It's in the text file, but hasn't been translated...
valid = false;
}
// Nothing to do...
if ( wcslen( stream ) == 0 )
{
return;
}
float delay = 0.0f;
wchar_t phrase[ 1024 ];
wchar_t *out = phrase;
for ( const wchar_t *curpos = stream; curpos && *curpos != L'\0'; ++curpos )
{
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
{
if ( !wcscmp( cmd, L"delay" ) )
{
// End current phrase
*out = L'\0';
if ( wcslen( phrase ) > 0 )
{
CCloseCaptionItem *item = new CCloseCaptionItem( phrase, duration + CAPTION_LINGER_TIME, delay, valid );
m_Items.AddToTail( item );
}
// Start new phrase
out = phrase;
// Delay must be positive
delay = max( 0.0f, (float)wcstod( args, NULL ) );
continue;
}
}
*out++ = *curpos;
}
// End final phrase, if any
*out = L'\0';
if ( wcslen( phrase ) > 0 )
{
CCloseCaptionItem *item = new CCloseCaptionItem( phrase, duration + CAPTION_LINGER_TIME, delay, valid );
m_Items.AddToTail( item );
}
}
bool CloseCaptionTool::LookupUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count )
{
wchar_t *outstr = g_pLocalize->Find( token );
if ( !outstr )
{
wcsncpy( outbuf, L"<can't find entry>", count );
return false;
}
wcsncpy( outbuf, outstr, count );
return true;
}
bool CloseCaptionTool::LookupStrippedUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count )
{
wchar_t *outstr = g_pLocalize->Find( token );
if ( !outstr )
{
wcsncpy( outbuf, L"<can't find entry>", count );
return false;
}
const wchar_t *curpos = outstr;
wchar_t *out = outbuf;
size_t outlen = 0;
for ( ;
curpos && *curpos != L'\0' && outlen < count;
++curpos )
{
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
{
continue;
}
*out++ = *curpos;
++outlen;
}
*out = L'\0';
return true;
}
bool CloseCaptionTool::SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t *args ) const
{
const wchar_t *in = *ppIn;
const wchar_t *oldin = in;
if ( in[0] != L'<' )
{
*ppIn += ( oldin - in );
return false;
}
args[ 0 ] = 0;
cmd[ 0 ]= 0;
wchar_t *out = cmd;
in++;
while ( *in != L'\0' && *in != L':' && *in != L'>' && !V_isspace( *in ) )
{
*out++ = *in++;
}
*out = L'\0';
if ( *in != L':' )
{
*ppIn += ( in - oldin );
return true;
}
in++;
out = args;
while ( *in != L'\0' && *in != L'>' )
{
*out++ = *in++;
}
*out = L'\0';
//if ( *in == L'>' )
// in++;
*ppIn += ( in - oldin );
return true;
}
struct WorkUnitParams
{
WorkUnitParams()
{
Q_memset( stream, 0, sizeof( stream ) );
out = stream;
x = 0;
y = 0;
width = 0;
bold = italic = false;
clr = Color( 255, 255, 255 );
newline = false;
}
~WorkUnitParams()
{
}
void Finalize()
{
*out = L'\0';
}
void Next()
{
// Restart output
Q_memset( stream, 0, sizeof( stream ) );
out = stream;
x += width;
width = 0;
// Leave bold, italic and color alone!!!
if ( newline )
{
newline = false;
x = 0;
y += STREAM_LINEHEIGHT;
}
}
int GetFontNumber()
{
return CloseCaptionTool::GetFontNumber( bold, italic );
}
wchar_t stream[ 1024 ];
wchar_t *out;
int x;
int y;
int width;
bool bold;
bool italic;
Color clr;
bool newline;
};
void CloseCaptionTool::AddWorkUnit( CCloseCaptionItem *item,
WorkUnitParams& params )
{
params.Finalize();
if ( wcslen( params.stream ) > 0 )
{
CCloseCaptionWorkUnit *wu = new CCloseCaptionWorkUnit();
wu->SetStream( params.stream );
wu->SetColor( params.clr );
wu->SetBold( params.bold );
wu->SetItalic( params.italic );
wu->SetWidth( params.width );
wu->SetHeight( STREAM_LINEHEIGHT );
wu->SetPos( params.x, params.y );
int curheight = item->GetHeight();
int curwidth = item->GetWidth();
curheight = max( curheight, params.y + wu->GetHeight() );
curwidth = max( curwidth, params.x + params.width );
item->SetHeight( curheight );
item->SetWidth( curwidth );
// Add it
item->AddWork( wu );
params.Next();
}
}
void CloseCaptionTool::ComputeStreamWork( CChoreoWidgetDrawHelper &helper, int available_width, CCloseCaptionItem *item )
{
// Start with a clean param block
WorkUnitParams params;
const wchar_t *curpos = item->GetStream();
CUtlVector< Color > colorStack;
for ( ; curpos && *curpos != L'\0'; ++curpos )
{
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
{
if ( !wcscmp( cmd, L"cr" ) )
{
params.newline = true;
AddWorkUnit( item, params);
}
else if ( !wcscmp( cmd, L"clr" ) )
{
AddWorkUnit( item, params );
if ( args[0] == 0 && colorStack.Count()>= 2)
{
colorStack.Remove( colorStack.Count() - 1 );
params.clr = colorStack[ colorStack.Count() - 1 ];
}
else
{
int r, g, b;
Color newcolor;
if ( 3 == swscanf( args, L"%i,%i,%i", &r, &g, &b ) )
{
newcolor = Color( r, g, b );
colorStack.AddToTail( newcolor );
params.clr = colorStack[ colorStack.Count() - 1 ];
}
}
}
else if ( !wcscmp( cmd, L"playerclr" ) )
{
AddWorkUnit( item, params );
if ( args[0] == 0 && colorStack.Count()>= 2)
{
colorStack.Remove( colorStack.Count() - 1 );
params.clr = colorStack[ colorStack.Count() - 1 ];
}
else
{
// player and npc color selector
// e.g.,. 255,255,255:200,200,200
int pr, pg, pb, nr, ng, nb;
Color newcolor;
if ( 6 == swscanf( args, L"%i,%i,%i:%i,%i,%i", &pr, &pg, &pb, &nr, &ng, &nb ) )
{
// FIXME: nothing in .vcds is ever from the player...
newcolor = /*item->IsFromPlayer()*/ false ? Color( pr, pg, pb ) : Color( nr, ng, nb );
colorStack.AddToTail( newcolor );
params.clr = colorStack[ colorStack.Count() - 1 ];
}
}
}
else if ( !wcscmp( cmd, L"I" ) )
{
AddWorkUnit( item, params );
params.italic = !params.italic;
}
else if ( !wcscmp( cmd, L"B" ) )
{
AddWorkUnit( item, params );
params.bold = !params.bold;
}
continue;
}
HFONT useF = m_hFonts[ params.GetFontNumber() ];
int w = helper.CalcTextWidthW( useF, L"%c", *curpos );
if ( ( params.x + params.width ) + w > available_width )
{
params.newline = true;
AddWorkUnit( item, params );
}
*params.out++ = *curpos;
params.width += w;
}
// Add the final unit.
params.newline = true;
AddWorkUnit( item, params );
item->SetSizeComputed( true );
// DumpWork( item );
}
void CloseCaptionTool:: DumpWork( CCloseCaptionItem *item )
{
int c = item->GetNumWorkUnits();
for ( int i = 0 ; i < c; ++i )
{
CCloseCaptionWorkUnit *wu = item->GetWorkUnit( i );
wu->Dump();
}
}
void CloseCaptionTool::DrawStream( CChoreoWidgetDrawHelper &helper, RECT &rcText, CCloseCaptionItem *item )
{
int c = item->GetNumWorkUnits();
RECT rcOut;
rcOut.left = rcText.left;
for ( int i = 0 ; i < c; ++i )
{
int x = 0;
int y = 0;
CCloseCaptionWorkUnit *wu = item->GetWorkUnit( i );
HFONT useF = m_hFonts[ wu->GetFontNumber() ];
wu->GetPos( x, y );
rcOut.left = rcText.left + x;
rcOut.right = rcOut.left + wu->GetWidth();
rcOut.top = rcText.top + y;
rcOut.bottom = rcOut.top + wu->GetHeight();
Color useColor = wu->GetColor();
if ( !item->IsValid() )
{
useColor = Color( 255, 255, 255 );
rcOut.right += 2;
helper.DrawFilledRect( Color( 100, 100, 40 ), rcOut );
}
helper.DrawColoredTextW( useF, useColor,
rcOut, L"%s", wu->GetStream() );
}
}
int CloseCaptionTool::GetFontNumber( bool bold, bool italic )
{
if ( bold || italic )
{
if( bold && italic )
{
return CloseCaptionTool::CCFONT_ITALICBOLD;
}
if ( bold )
{
return CloseCaptionTool::CCFONT_BOLD;
}
if ( italic )
{
return CloseCaptionTool::CCFONT_ITALIC;
}
}
return CloseCaptionTool::CCFONT_NORMAL;
}

View File

@@ -0,0 +1,74 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef CLOSECAPTIONTOOL_H
#define CLOSECAPTIONTOOL_H
#ifdef _WIN32
#pragma once
#endif
#include <mxtk/mx.h>
#include "UtlVector.h"
#include "faceposertoolwindow.h"
#include "iclosecaptionmanager.h"
class CCloseCaptionItem;
struct WorkUnitParams;
class CloseCaptionTool : public mxWindow, public IFacePoserToolWindow, public ICloseCaptionManager
{
public:
// Construction
CloseCaptionTool( mxWindow *parent );
~CloseCaptionTool( void );
// ICloseCaptionManager
virtual void Reset( void );
virtual void Process( char const *tokenname, float duration, int languageid );
virtual bool LookupUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count );
virtual bool LookupStrippedUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count );
// End ICloseCaptionManager
virtual void Think( float dt );
virtual int handleEvent( mxEvent *event );
virtual void redraw( void );
virtual bool PaintBackground();
enum
{
CCFONT_NORMAL = 0,
CCFONT_ITALIC,
CCFONT_BOLD,
CCFONT_ITALICBOLD
};
static int GetFontNumber( bool bold, bool italic );
private:
void ComputeStreamWork( CChoreoWidgetDrawHelper &helper, int available_width, CCloseCaptionItem *item );
void DrawStream( CChoreoWidgetDrawHelper &helper, RECT &rcText, CCloseCaptionItem *item );
bool SplitCommand( const wchar_t **in, wchar_t *cmd, wchar_t *args ) const;
void ParseCloseCaptionStream( const wchar_t *in, int available_width );
void DumpWork( CCloseCaptionItem *item );
void AddWorkUnit(
CCloseCaptionItem *item,
WorkUnitParams& params );
CUtlVector< CCloseCaptionItem * > m_Items;
HFONT m_hFonts[ 4 ]; // normal, italic, bold, bold + italic
int m_nLastItemCount;
};
extern CloseCaptionTool *g_pCloseCaptionTool;
#endif // CLOSECAPTIONTOOL_H

View File

@@ -0,0 +1,271 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <mxtk/mx.h>
#include <stdio.h>
#include "resource.h"
#include "EdgeProperties.h"
#include "mdlviewer.h"
#include "hlfaceposer.h"
#include "choreoevent.h"
#include "choreoscene.h"
#include "expressions.h"
#include "choreoactor.h"
#include "ifaceposersound.h"
#include "expclass.h"
#include "scriplib.h"
static CEdgePropertiesParams g_Params;
void CEdgePropertiesParams::SetFromFlexTrack( CFlexAnimationTrack *track )
{
for ( int i = 0 ; i < 2; ++i )
{
m_bActive[ i ] = track->IsEdgeActive( i == 0 ? true : false );
int curveType = 0;
track->GetEdgeInfo( i == 0 ? true : false, curveType, m_flValue[ i ] );
if ( i == 0 )
{
m_InterpolatorType[ i ] = GET_RIGHT_CURVE( curveType );
}
else
{
m_InterpolatorType[ i ] = GET_LEFT_CURVE( curveType );
}
}
}
void CEdgePropertiesParams::ApplyToTrack( CFlexAnimationTrack *track )
{
for ( int i = 0 ; i < 2; ++i )
{
track->SetEdgeActive( i == 0 ? true : false, m_bActive[ i ] );
int curveType = 0;
if ( i == 0 )
{
curveType = MAKE_CURVE_TYPE( 0, m_InterpolatorType[ i ] );
}
else
{
curveType = MAKE_CURVE_TYPE( m_InterpolatorType[ i ], 0 );
}
track->SetEdgeInfo( i == 0 ? true : false, curveType, m_flValue[ i ] );
}
}
void CEdgePropertiesParams::SetFromCurve( CCurveData *ramp )
{
for ( int i = 0 ; i < 2; ++i )
{
m_bActive[ i ] = ramp->IsEdgeActive( i == 0 ? true : false );
int curveType = 0;
ramp->GetEdgeInfo( i == 0 ? true : false, curveType, m_flValue[ i ] );
if ( i == 0 )
{
m_InterpolatorType[ i ] = GET_RIGHT_CURVE( curveType );
}
else
{
m_InterpolatorType[ i ] = GET_LEFT_CURVE( curveType );
}
}
}
void CEdgePropertiesParams::ApplyToCurve( CCurveData *ramp )
{
for ( int i = 0 ; i < 2; ++i )
{
ramp->SetEdgeActive( i == 0 ? true : false, m_bActive[ i ] );
int curveType = 0;
if ( i == 0 )
{
curveType = MAKE_CURVE_TYPE( 0, m_InterpolatorType[ i ] );
}
else
{
curveType = MAKE_CURVE_TYPE( m_InterpolatorType[ i ], 0 );
}
ramp->SetEdgeInfo( i == 0 ? true : false, curveType, m_flValue[ i ] );
}
}
static void PopulateCurveType( HWND control, CEdgePropertiesParams *params, bool isLeftEdge )
{
SendMessage( control, CB_RESETCONTENT, 0, 0 );
for ( int i = 0; i < NUM_INTERPOLATE_TYPES; ++i )
{
SendMessage( control, CB_ADDSTRING, 0, (LPARAM)Interpolator_NameForInterpolator( i, true ) );
}
SendMessage( control, CB_SETCURSEL , params->m_InterpolatorType[ isLeftEdge ? 0 : 1 ], 0 );
}
static void Reset( HWND hwndDlg, bool left )
{
SendMessage( GetDlgItem( hwndDlg, left ? IDC_LEFT_ACTIVE : IDC_RIGHT_ACTIVE ), BM_SETCHECK,
( WPARAM )BST_UNCHECKED,
( LPARAM )0 );
SendMessage( GetDlgItem( hwndDlg, left ? IDC_LEFT_CURVETYPE : IDC_RIGHT_CURVETYPE ), CB_SETCURSEL, 0, 0 );
SetDlgItemText( hwndDlg, left ? IDC_LEFT_ZEROVALUE : IDC_RIGHT_ZEROVALUE, "0.0" );
SendMessage( GetDlgItem( hwndDlg, IDC_HOLD_OUT ), BM_SETCHECK,
( WPARAM )BST_UNCHECKED,
( LPARAM )0 );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : hwndDlg -
// uMsg -
// wParam -
// lParam -
// Output : static BOOL CALLBACK
//-----------------------------------------------------------------------------
static BOOL CALLBACK EdgePropertiesDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch(uMsg)
{
case WM_INITDIALOG:
{
g_Params.PositionSelf( hwndDlg );
PopulateCurveType( GetDlgItem( hwndDlg, IDC_LEFT_CURVETYPE ), &g_Params, true );
PopulateCurveType( GetDlgItem( hwndDlg, IDC_RIGHT_CURVETYPE ), &g_Params, false );
SetDlgItemText( hwndDlg, IDC_LEFT_ZEROVALUE, va( "%f", g_Params.m_flValue[ 0 ] ) );
SetDlgItemText( hwndDlg, IDC_RIGHT_ZEROVALUE, va( "%f", g_Params.m_flValue[ 1 ] ) );
SendMessage( GetDlgItem( hwndDlg, IDC_LEFT_ACTIVE ), BM_SETCHECK,
( WPARAM ) g_Params.m_bActive[ 0 ] ? BST_CHECKED : BST_UNCHECKED,
( LPARAM )0 );
SendMessage( GetDlgItem( hwndDlg, IDC_RIGHT_ACTIVE ), BM_SETCHECK,
( WPARAM ) g_Params.m_bActive[ 1 ] ? BST_CHECKED : BST_UNCHECKED,
( LPARAM )0 );
SetWindowText( hwndDlg, g_Params.m_szDialogTitle );
SetFocus( GetDlgItem( hwndDlg, IDC_LEFT_ZEROVALUE ) );
}
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_LEFT_RESET:
{
Reset( hwndDlg, true );
}
break;
case IDC_RIGHT_RESET:
{
Reset( hwndDlg, false );
}
break;
case IDC_LEFT_CURVETYPE:
{
if ( HIWORD( wParam ) == CBN_SELCHANGE )
{
SendMessage( GetDlgItem( hwndDlg, IDC_LEFT_ACTIVE ), BM_SETCHECK,
( WPARAM ) BST_CHECKED,
( LPARAM )0 );
}
}
break;
case IDC_RIGHT_CURVETYPE:
{
if ( HIWORD( wParam ) == CBN_SELCHANGE )
{
SendMessage( GetDlgItem( hwndDlg, IDC_RIGHT_ACTIVE ), BM_SETCHECK,
( WPARAM ) BST_CHECKED,
( LPARAM )0 );
}
}
break;
case IDC_LEFT_ZEROVALUE:
{
if ( HIWORD( wParam ) == EN_CHANGE )
{
SendMessage( GetDlgItem( hwndDlg, IDC_LEFT_ACTIVE ), BM_SETCHECK,
( WPARAM ) BST_CHECKED,
( LPARAM )0 );
}
}
break;
case IDC_RIGHT_ZEROVALUE:
{
if ( HIWORD( wParam ) == EN_CHANGE )
{
SendMessage( GetDlgItem( hwndDlg, IDC_RIGHT_ACTIVE ), BM_SETCHECK,
( WPARAM ) BST_CHECKED,
( LPARAM )0 );
}
}
break;
case IDOK:
{
char sz[ 64 ];
GetDlgItemText( hwndDlg, IDC_LEFT_ZEROVALUE, sz, sizeof( sz ) );
g_Params.m_flValue[ 0 ] = clamp( Q_atof( sz ), 0.0f, 1.0f );
GetDlgItemText( hwndDlg, IDC_RIGHT_ZEROVALUE, sz, sizeof( sz ) );
g_Params.m_flValue[ 1 ] = clamp( Q_atof( sz ), 0.0f, 1.0f );
g_Params.m_bActive[ 0 ] = SendMessage( GetDlgItem( hwndDlg, IDC_LEFT_ACTIVE ), BM_GETCHECK, 0, 0 ) == BST_CHECKED ? true : false;
g_Params.m_bActive[ 1 ] = SendMessage( GetDlgItem( hwndDlg, IDC_RIGHT_ACTIVE ), BM_GETCHECK, 0, 0 ) == BST_CHECKED ? true : false;
int interpolatorType;
interpolatorType = SendMessage( GetDlgItem( hwndDlg, IDC_LEFT_CURVETYPE ), CB_GETCURSEL, 0, 0 );
if ( interpolatorType != CB_ERR )
{
g_Params.m_InterpolatorType[ 0 ] = interpolatorType;
}
interpolatorType = SendMessage( GetDlgItem( hwndDlg, IDC_RIGHT_CURVETYPE ), CB_GETCURSEL, 0, 0 );
if ( interpolatorType != CB_ERR )
{
g_Params.m_InterpolatorType[ 1 ] = interpolatorType;
}
EndDialog( hwndDlg, 1 );
}
break;
case IDCANCEL:
EndDialog( hwndDlg, 0 );
break;
}
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *view -
// *actor -
// Output : int
//-----------------------------------------------------------------------------
int EdgeProperties( CEdgePropertiesParams *params )
{
g_Params = *params;
int retval = DialogBox( (HINSTANCE)GetModuleHandle( 0 ),
MAKEINTRESOURCE( IDD_EDGEPROPERTIES ),
(HWND)g_MDLViewer->getHandle(),
(DLGPROC)EdgePropertiesDialogProc );
*params = g_Params;
return retval;
}

View File

@@ -0,0 +1,42 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef EDGEPROPERTIES_H
#define EDGEPROPERTIES_H
#ifdef _WIN32
#pragma once
#endif
class CCurveData;
class ChoreoScene;
class CChoreoEvent;
class CFlexAnimationTrack;
#include "basedialogparams.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct CEdgePropertiesParams : public CBaseDialogParams
{
// GlobalEvent descriptive name
char m_szName[ 256 ];
void SetFromFlexTrack( CFlexAnimationTrack *track );
void ApplyToTrack( CFlexAnimationTrack *track );
void SetFromCurve( CCurveData *ramp );
void ApplyToCurve( CCurveData *ramp );
bool m_bActive[ 2 ];
int m_InterpolatorType[ 2 ];
float m_flValue[ 2 ];
};
int EdgeProperties( CEdgePropertiesParams *params );
#endif // EDGEPROPERTIES_H

View File

@@ -0,0 +1,82 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#define UNICODE
#include "resource.h"
#include "EditPhrase.h"
#include "mxtk/mx.h"
#include "mdlviewer.h"
static CEditPhraseParams g_Params;
//-----------------------------------------------------------------------------
// Purpose:
// Input : hwndDlg -
// uMsg -
// wParam -
// lParam -
// Output : static BOOL CALLBACK
//-----------------------------------------------------------------------------
static BOOL CALLBACK EditPhraseDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch(uMsg)
{
case WM_INITDIALOG:
// Insert code here to put the string (to find and replace with)
// into the edit controls.
// ...
{
g_Params.PositionSelf( hwndDlg );
SetDlgItemTextW( hwndDlg, IDC_INPUTSTRING, g_Params.m_szInputText );
SetDlgItemTextA( hwndDlg, IDC_STATIC_PROMPT, g_Params.m_szPrompt );
SetWindowTextA( hwndDlg, g_Params.m_szDialogTitle );
SetFocus( GetDlgItem( hwndDlg, IDC_INPUTSTRING ) );
SendMessage( GetDlgItem( hwndDlg, IDC_INPUTSTRING ), EM_SETSEL, 0, MAKELONG(0, 0xffff) );
}
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
g_Params.m_szInputText[ 0 ] = 0;
GetDlgItemTextW( hwndDlg, IDC_INPUTSTRING, g_Params.m_szInputText, sizeof( g_Params.m_szInputText ) );
EndDialog( hwndDlg, 1 );
break;
case IDCANCEL:
EndDialog( hwndDlg, 0 );
break;
}
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *view -
// *actor -
// Output : int
//-----------------------------------------------------------------------------
int EditPhrase( CEditPhraseParams *params )
{
g_Params = *params;
int retval = DialogBox( (HINSTANCE)GetModuleHandle( 0 ),
MAKEINTRESOURCE( IDD_EDITPHRASE ),
(HWND)g_MDLViewer->getHandle(),
(DLGPROC)EditPhraseDialogProc );
*params = g_Params;
return retval;
}

View File

@@ -0,0 +1,39 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef EDITPHRASE_H
#define EDITPHRASE_H
#ifdef _WIN32
#pragma once
#endif
#include <stdio.h>
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "basedialogparams.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct CEditPhraseParams : public CBaseDialogParams
{
char m_szPrompt[ 256 ];
// i/o input text
wchar_t m_szInputText[ 1024 ];
};
// Display/create dialog
int EditPhrase( CEditPhraseParams *params );
#endif // EDITPHRASE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GESTURETOOL_H
#define GESTURETOOL_H
#ifdef _WIN32
#pragma once
#endif
#include <mxtk/mx.h>
#include "studio.h"
#include "UtlVector.h"
#include "faceposertoolwindow.h"
class CChoreoEvent;
class CChoreoWidgetDrawHelper;
class CChoreoView;
class CEventAbsoluteTag;
#define IDC_REDO_GT 1000
#define IDC_UNDO_GT 1001
#define IDC_GT_DELETE_TAG 1002
#define IDC_GT_INSERT_TAG 1003
#define IDC_GT_REVERT 1004
#define IDC_GT_CHANGESCALE 1005
#define IDC_GESTUREHSCROLL 1006
class GestureTool : public mxWindow, public IFacePoserToolWindow
{
public:
// Construction
GestureTool( mxWindow *parent );
~GestureTool( void );
virtual void Think( float dt );
void ScrubThink( float dt, bool scrubbing );
virtual bool IsScrubbing( void ) const;
virtual bool IsProcessing( void );
virtual int handleEvent( mxEvent *event );
virtual void redraw( void );
virtual bool PaintBackground();
void SetEvent( CChoreoEvent *event );
void GetScrubHandleRect( RECT& rcHandle, float scrub, bool clipped = false );
void GetScrubHandleReferenceRect( RECT& rcHandle, float scrub, bool clipped = false );
void DrawScrubHandle( CChoreoWidgetDrawHelper& drawHelper, RECT& rcHandle, float scrub, bool reference );
void DrawTimeLine( CChoreoWidgetDrawHelper& drawHelper, RECT& rc, float left, float right );
void DrawEventEnd( CChoreoWidgetDrawHelper& drawHelper );
void DrawAbsoluteTags( CChoreoWidgetDrawHelper& drawHelper );
bool GetAbsTagRect( RECT& rcClient, CChoreoEvent *event, int tagtype, CEventAbsoluteTag *tag, RECT& rcTag );
void GetTagTrayRect( RECT &rcClient, int tagtype, RECT& rcTray );
void SetMouseOverPos( int x, int y );
void GetMouseOverPos( int &x, int& y );
void GetMouseOverPosRect( RECT& rcPos );
void DrawMouseOverPos( CChoreoWidgetDrawHelper& drawHelper, RECT& rcPos );
void DrawMouseOverPos();
void DrawScrubHandles();
CChoreoEvent *GetSafeEvent( void );
bool IsMouseOverScrubHandle( mxEvent *event );
void ForceScrubPosition( float newtime );
void ForceScrubPositionFromSceneTime( float scenetime );
void SetScrubTime( float t );
void SetScrubTargetTime( float t );
virtual void OnModelChanged();
private:
void StartDragging( int dragtype, int startx, int starty, HCURSOR cursor );
void AddFocusRect( RECT& rc );
void OnMouseMove( mxEvent *event );
void DrawFocusRect( void );
void ShowContextMenu( mxEvent *event, bool include_track_menus );
void GetWorkspaceLeftRight( int& left, int& right );
void SetClickedPos( int x, int y );
float GetTimeForClickedPos( void );
void ApplyBounds( int& mx, int& my );
void CalcBounds( int movetype );
void OnUndo( void );
void OnRedo( void );
CEventAbsoluteTag *IsMouseOverTag( int mx, int my );
int GetTagTypeForMouse( int mx, int my );
int GetTagTypeForTag( CEventAbsoluteTag const *tag );
void OnInsertTag( void );
void OnDeleteTag( void );
void OnRevert( void );
void DrawRelativeTags( CChoreoWidgetDrawHelper& drawHelper, RECT& rc );
void DrawRelativeTagsForEvent( CChoreoWidgetDrawHelper& drawHelper, RECT& rc, CChoreoEvent *gesture, CChoreoEvent *event, float starttime, float endtime );
// Readjust slider
void MoveTimeSliderToPos( int x );
void OnChangeScale();
int ComputeHPixelsNeeded( void );
float GetPixelsPerSecond( void );
void InvalidateLayout( void );
void RepositionHSlider( void );
void GetStartAndEndTime( float& st, float& ed );
float GetEventEndTime();
float GetTimeValueForMouse( int mx, bool clip = false );
int GetPixelForTimeValue( float time, bool *clipped = NULL );
float m_flScrub;
float m_flScrubTarget;
enum
{
DRAGTYPE_NONE = 0,
DRAGTYPE_SCRUBBER,
DRAGTYPE_ABSOLUTE_TIMING_TAG,
};
int m_nFocusEventGlobalID;
int m_nMousePos[ 2 ];
bool m_bUseBounds;
int m_nMinX;
int m_nMaxX;
HCURSOR m_hPrevCursor;
int m_nDragType;
int m_nStartX;
int m_nStartY;
int m_nLastX;
int m_nLastY;
int m_nClickedX;
int m_nClickedY;
struct CFocusRect
{
RECT m_rcOrig;
RECT m_rcFocus;
};
CUtlVector < CFocusRect > m_FocusRects;
CChoreoEvent *m_pLastEvent;
bool m_bSuppressLayout;
// Height/width of scroll bars
int m_nScrollbarHeight;
float m_flLeftOffset;
mxScrollbar *m_pHorzScrollBar;
int m_nLastHPixelsNeeded;
// How many pixels per second we are showing in the UI
float m_flPixelsPerSecond;
// Do we need to move controls?
bool m_bLayoutIsValid;
float m_flLastDuration;
bool m_bInSetEvent;
float m_flScrubberTimeOffset;
friend class CChoreoView;
};
extern GestureTool *g_pGestureTool;
#endif // GESTURETOOL_H

View File

@@ -0,0 +1,33 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ICLOSECAPTIONMANAGER_H
#define ICLOSECAPTIONMANAGER_H
#ifdef _WIN32
#pragma once
#endif
typedef struct tagRECT RECT;
class CSentence;
class StudioModel;
class CChoreoWidgetDrawHelper;
class ICloseCaptionManager
{
public:
virtual void Reset( void ) = 0;
virtual void Process( char const *tokenname, float duration, int languageid ) = 0;
virtual bool LookupUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count ) = 0;
// Same as above, except strips out <> command tokens
virtual bool LookupStrippedUnicodeText( int languageId, char const *token, wchar_t *outbuf, size_t count ) = 0;
};
extern ICloseCaptionManager *closecaptionmanager;
#endif // ICLOSECAPTIONMANAGER_H

View File

@@ -0,0 +1,243 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "resource.h"
#include "ProgressDialog.h"
#include "mxtk/mx.h"
#include "mdlviewer.h"
#include "tier1/utlstring.h"
#include "tier1/strtools.h"
#include "tier1/fmtstr.h"
#include <CommCtrl.h>
class CProgressDialog : public IProgressDialog
{
public:
CProgressDialog();
void Start( char const *pchTitle, char const *pchText, bool bShowCancel );
void Update( float flZeroToOneFraction );
void UpdateText( char const *pchFmt, ... );
bool IsCancelled();
void Finish();
static BOOL CALLBACK ProgressDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
private:
BOOL ProgressDialogProcImpl( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
CUtlString m_sTitle;
CUtlString m_sStatus;
float m_flFraction;
bool m_bShowCancel;
bool m_bWantsCancel;
HWND m_hwndDlg;
double m_flStartTime;
};
static CProgressDialog g_ProgressDialog;
IProgressDialog *g_pProgressDialog = &g_ProgressDialog;
CProgressDialog::CProgressDialog() :
m_flFraction( 0.0f ), m_hwndDlg( 0 ), m_bShowCancel( false ), m_bWantsCancel( false ), m_flStartTime( 0.0f )
{
}
bool CProgressDialog::IsCancelled()
{
return m_bShowCancel && m_bWantsCancel;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : hwndDlg -
// uMsg -
// wParam -
// lParam -
// Output : static BOOL CALLBACK
//-----------------------------------------------------------------------------
BOOL CALLBACK CProgressDialog::ProgressDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
return g_ProgressDialog.ProgressDialogProcImpl( hwndDlg, uMsg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *view -
// *actor -
// Output : int
//-----------------------------------------------------------------------------
void CProgressDialog::Start( char const *pchTitle, char const *pchText, bool bShowCancel )
{
if ( m_hwndDlg )
{
Finish();
}
Assert( NULL == m_hwndDlg );
m_sTitle = pchTitle;
m_sStatus = pchText;
m_flFraction = 0.0f;
m_bShowCancel = bShowCancel;
m_bWantsCancel = false;
m_flStartTime = Plat_FloatTime();
m_hwndDlg = CreateDialog( (HINSTANCE)GetModuleHandle( 0 ),
MAKEINTRESOURCE( IDD_PROGRESS ),
(HWND)g_MDLViewer->getHandle(),
(DLGPROC)ProgressDialogProc );
}
void CProgressDialog::Update( float flZeroToOneFraction )
{
m_flFraction = clamp( flZeroToOneFraction, 0.0f, 1.0f );
// Update the progress bar
HWND pb = GetDlgItem( m_hwndDlg, IDC_FP_PROGRESS );
int pos = clamp( (int)( 1000.0f * flZeroToOneFraction ), 0, 1000 );
SendMessage( pb, (UINT) PBM_SETPOS, pos, 0 );
HWND btn = GetDlgItem( m_hwndDlg, IDCANCEL );
LRESULT lr = SendMessage( btn, BM_GETSTATE, 0, 0 );
if ( lr & BST_PUSHED )
{
m_bWantsCancel = true;
}
if ( GetAsyncKeyState( VK_ESCAPE ) )
{
m_bWantsCancel = true;
}
mx::check();
}
void CProgressDialog::UpdateText( char const *pchFmt, ... )
{
char buf[ 2048 ];
va_list argptr;
va_start( argptr, pchFmt );
Q_vsnprintf( buf, sizeof( buf ), pchFmt, argptr );
va_end( argptr );
m_sStatus = buf;
SetDlgItemText( m_hwndDlg, IDC_FP_PROGRESS_TEXT, CFmtStr( "%s", m_sStatus.String() ) );
SetDlgItemText( m_hwndDlg, IDC_FP_PROGRESS_PERCENT, CFmtStr( "%.2f %%", m_flFraction * 100.0f ) );
double elapsed = Plat_FloatTime() - m_flStartTime;
double flPercentagePerSecond = 0.0f;
if ( m_flFraction > 0.0f )
{
flPercentagePerSecond = elapsed / m_flFraction;
}
double flSecondsRemaining = flPercentagePerSecond * ( 1.0f - m_flFraction );
int seconds = (int)flSecondsRemaining;
CFmtStr string;
int hours = 0;
int minutes = seconds / 60;
if ( minutes > 0 )
{
seconds -= (minutes * 60);
hours = minutes / 60;
if ( hours > 0 )
{
minutes -= (hours * 60);
}
}
if ( hours > 0 )
{
string.sprintf( "Time Remaining: %2i:%02i:%02i", hours, minutes, seconds );
}
else
{
string.sprintf( "Time Remaining: %02i:%02i", minutes, seconds );
}
SetDlgItemText( m_hwndDlg, IDC_FP_PROGRESS_ETA, string.Access() );
}
void CProgressDialog::Finish()
{
if ( !m_hwndDlg )
return;
DestroyWindow( m_hwndDlg );
m_hwndDlg = NULL;
}
BOOL CProgressDialog::ProgressDialogProcImpl( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch(uMsg)
{
case WM_INITDIALOG:
// Insert code here to put the string (to find and replace with)
// into the edit controls.
// ...
{
RECT rcDlg;
GetWindowRect( hwndDlg, &rcDlg );
// Get relative to primary monitor instead of actual window parent
RECT rcParent;
rcParent.left = 0;
rcParent.right = rcParent.left + GetSystemMetrics( SM_CXFULLSCREEN );
rcParent.top = 0;
rcParent.bottom = rcParent.top + GetSystemMetrics( SM_CYFULLSCREEN );
int dialogw, dialogh;
int parentw, parenth;
parentw = rcParent.right - rcParent.left;
parenth = rcParent.bottom - rcParent.top;
dialogw = rcDlg.right - rcDlg.left;
dialogh = rcDlg.bottom - rcDlg.top;
int dlgleft, dlgtop;
dlgleft = ( parentw - dialogw ) / 2;
dlgtop = ( parenth - dialogh ) / 2;
MoveWindow( hwndDlg,
dlgleft,
dlgtop,
dialogw,
dialogh,
TRUE
);
SetDlgItemText( hwndDlg, IDC_FP_PROGRESS_TITLE, m_sTitle.String() );
SetDlgItemText( hwndDlg, IDC_FP_PROGRESS_TEXT, m_sStatus.String() );
HWND pb = GetDlgItem( hwndDlg, IDC_FP_PROGRESS );
SendMessage( pb, (UINT) PBM_SETRANGE, 0, MAKELPARAM( 0, 1000 ) );
ShowWindow( GetDlgItem( hwndDlg, IDCANCEL ), m_bShowCancel ? SW_SHOW : SW_HIDE );
Update( 0.0f );
}
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
m_bWantsCancel = true;
break;
}
return TRUE;
}
return FALSE;
}

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