initial
This commit is contained in:
73
utils/FileSystemOpenDialog/FileDialogApp.cpp
Normal file
73
utils/FileSystemOpenDialog/FileDialogApp.cpp
Normal 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;
|
||||
|
||||
|
||||
|
||||
52
utils/FileSystemOpenDialog/FileDialogApp.h
Normal file
52
utils/FileSystemOpenDialog/FileDialogApp.h
Normal 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_)
|
||||
192
utils/FileSystemOpenDialog/FileSystemOpenDialog.rc
Normal file
192
utils/FileSystemOpenDialog/FileSystemOpenDialog.rc
Normal 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
|
||||
|
||||
1064
utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp
Normal file
1064
utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
146
utils/FileSystemOpenDialog/FileSystemOpenDlg.h
Normal file
146
utils/FileSystemOpenDialog/FileSystemOpenDlg.h
Normal 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_)
|
||||
15
utils/FileSystemOpenDialog/StdAfx.cpp
Normal file
15
utils/FileSystemOpenDialog/StdAfx.cpp
Normal 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"
|
||||
|
||||
|
||||
|
||||
52
utils/FileSystemOpenDialog/StdAfx.h
Normal file
52
utils/FileSystemOpenDialog/StdAfx.h
Normal 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_)
|
||||
@@ -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:
|
||||
|
||||
82
utils/FileSystemOpenDialog/filesystemopendialog.vpc
Normal file
82
utils/FileSystemOpenDialog/filesystemopendialog.vpc
Normal 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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
"vpc_cache"
|
||||
{
|
||||
"CacheVersion" "1"
|
||||
"win32"
|
||||
{
|
||||
"CRCFile" "FileSystemOpenDialog.vcxproj.vpc_crc"
|
||||
"OutputFiles"
|
||||
{
|
||||
"0" "FileSystemOpenDialog.vcxproj"
|
||||
"1" "FileSystemOpenDialog.vcxproj.filters"
|
||||
}
|
||||
}
|
||||
}
|
||||
13
utils/FileSystemOpenDialog/res/SteamFileDialog.rc2
Normal file
13
utils/FileSystemOpenDialog/res/SteamFileDialog.rc2
Normal 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...
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
BIN
utils/FileSystemOpenDialog/res/label_file.bmp
Normal file
BIN
utils/FileSystemOpenDialog/res/label_file.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
utils/FileSystemOpenDialog/res/label_fo.bmp
Normal file
BIN
utils/FileSystemOpenDialog/res/label_fo.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
utils/FileSystemOpenDialog/res/label_mdl.bmp
Normal file
BIN
utils/FileSystemOpenDialog/res/label_mdl.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
25
utils/FileSystemOpenDialog/resource.h
Normal file
25
utils/FileSystemOpenDialog/resource.h
Normal 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
|
||||
356
utils/binlaunch/binlaunch.cpp
Normal file
356
utils/binlaunch/binlaunch.cpp
Normal 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 );
|
||||
}
|
||||
|
||||
|
||||
56
utils/binlaunch/binlaunch.vpc
Normal file
56
utils/binlaunch/binlaunch.vpc
Normal 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
|
||||
}
|
||||
}
|
||||
58
utils/bzip2/_vpc_/manifest_bzip2/win32/manifest.txt
Normal file
58
utils/bzip2/_vpc_/manifest_bzip2/win32/manifest.txt
Normal 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
1141
utils/bzip2/blocksort.c
Normal file
File diff suppressed because it is too large
Load Diff
2142
utils/bzip2/bzip2.c
Normal file
2142
utils/bzip2/bzip2.c
Normal file
File diff suppressed because it is too large
Load Diff
46
utils/bzip2/bzip2.vpc
Normal file
46
utils/bzip2/bzip2.vpc
Normal 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"
|
||||
}
|
||||
}
|
||||
|
||||
13
utils/bzip2/bzip2.vpc.vpc_cache
Normal file
13
utils/bzip2/bzip2.vpc.vpc_cache
Normal 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
1593
utils/bzip2/bzlib.c
Normal file
File diff suppressed because it is too large
Load Diff
321
utils/bzip2/bzlib.h
Normal file
321
utils/bzip2/bzlib.h
Normal 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
550
utils/bzip2/bzlib_private.h
Normal 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
714
utils/bzip2/compress.c
Normal 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
144
utils/bzip2/crctable.c
Normal 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
660
utils/bzip2/decompress.c
Normal 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
228
utils/bzip2/huffman.c
Normal 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
124
utils/bzip2/randtable.c
Normal 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
2
utils/bzip2/vsi.nul
Normal 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
BIN
utils/common.zip
Normal file
Binary file not shown.
29
utils/common/ISQLDBReplyTarget.h
Normal file
29
utils/common/ISQLDBReplyTarget.h
Normal 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
|
||||
192
utils/common/MySqlDatabase.cpp
Normal file
192
utils/common/MySqlDatabase.cpp
Normal 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();
|
||||
}
|
||||
104
utils/common/MySqlDatabase.h
Normal file
104
utils/common/MySqlDatabase.h
Normal 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
6089
utils/common/bsplib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
410
utils/common/bsplib.h
Normal file
410
utils/common/bsplib.h
Normal 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
1062
utils/common/cmdlib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
189
utils/common/cmdlib.h
Normal file
189
utils/common/cmdlib.h
Normal 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
339
utils/common/consolewnd.cpp
Normal 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
48
utils/common/consolewnd.h
Normal 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
470
utils/common/datalinker.cpp
Normal 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
180
utils/common/datalinker.h
Normal 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
|
||||
223
utils/common/filesystem_tools.cpp
Normal file
223
utils/common/filesystem_tools.cpp
Normal 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 );
|
||||
}
|
||||
|
||||
60
utils/common/filesystem_tools.h
Normal file
60
utils/common/filesystem_tools.h
Normal 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
|
||||
147
utils/common/instancing_helper.h
Normal file
147
utils/common/instancing_helper.h
Normal 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
141
utils/common/map_shared.cpp
Normal 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
91
utils/common/map_shared.h
Normal 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
34
utils/common/movie.h
Normal 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
845
utils/common/mpi_stats.cpp
Normal 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
59
utils/common/mpi_stats.h
Normal 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
930
utils/common/mstristrip.cpp
Normal 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
43
utils/common/mstristrip.h
Normal 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
62
utils/common/pacifier.cpp
Normal 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
23
utils/common/pacifier.h
Normal 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
31
utils/common/physdll.cpp
Normal 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
30
utils/common/physdll.h
Normal 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
915
utils/common/polylib.cpp
Normal 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 ¢er)
|
||||
{
|
||||
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 ¢er )
|
||||
{
|
||||
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
78
utils/common/polylib.h
Normal 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 ¢er);
|
||||
vec_t WindingAreaAndBalancePoint( winding_t *w, Vector ¢er );
|
||||
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
42
utils/common/qfiles.h
Normal 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
|
||||
103
utils/common/scratchpad_helpers.cpp
Normal file
103
utils/common/scratchpad_helpers.cpp
Normal 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 );
|
||||
}
|
||||
25
utils/common/scratchpad_helpers.h
Normal file
25
utils/common/scratchpad_helpers.h
Normal 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
1389
utils/common/scriplib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
94
utils/common/scriplib.h
Normal file
94
utils/common/scriplib.h
Normal 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
257
utils/common/threads.cpp
Normal 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
65
utils/common/threads.h
Normal 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
|
||||
61
utils/common/tools_minidump.cpp
Normal file
61
utils/common/tools_minidump.cpp
Normal 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 );
|
||||
}
|
||||
35
utils/common/tools_minidump.h
Normal file
35
utils/common/tools_minidump.h
Normal 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
187
utils/common/utilmatlib.cpp
Normal 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
43
utils/common/utilmatlib.h
Normal 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
|
||||
376
utils/common/vmpi_tools_shared.cpp
Normal file
376
utils/common/vmpi_tools_shared.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
46
utils/common/vmpi_tools_shared.h
Normal file
46
utils/common/vmpi_tools_shared.h
Normal 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
334
utils/common/wadlib.c
Normal 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
46
utils/common/wadlib.h
Normal 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
363
utils/dx_proxy/dx_proxy.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
38
utils/dx_proxy/dx_proxy_all.vgc
Normal file
38
utils/dx_proxy/dx_proxy_all.vgc
Normal 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"
|
||||
}
|
||||
76
utils/dx_proxy/dx_proxy_base.vpc
Normal file
76
utils/dx_proxy/dx_proxy_base.vpc
Normal 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"
|
||||
}
|
||||
}
|
||||
17
utils/dx_proxy/dx_proxy_dx10_v00_pc.vpc
Normal file
17
utils/dx_proxy/dx_proxy_dx10_v00_pc.vpc
Normal 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)"
|
||||
{
|
||||
}
|
||||
17
utils/dx_proxy/dx_proxy_dx9_v00_pc.vpc
Normal file
17
utils/dx_proxy/dx_proxy_dx9_v00_pc.vpc
Normal 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)"
|
||||
{
|
||||
}
|
||||
55
utils/dx_proxy/dx_proxy_dx9_v00_x360.vpc
Normal file
55
utils/dx_proxy/dx_proxy_dx9_v00_x360.vpc
Normal 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)"
|
||||
{
|
||||
}
|
||||
17
utils/dx_proxy/dx_proxy_dx9_v30_pc.vpc
Normal file
17
utils/dx_proxy/dx_proxy_dx9_v30_pc.vpc
Normal 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)"
|
||||
{
|
||||
}
|
||||
1010
utils/dx_proxy/dx_proxy_ps3.cpp
Normal file
1010
utils/dx_proxy/dx_proxy_ps3.cpp
Normal file
File diff suppressed because it is too large
Load Diff
34
utils/dx_proxy/dx_proxy_ps3.vpc
Normal file
34
utils/dx_proxy/dx_proxy_ps3.vpc
Normal 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"
|
||||
}
|
||||
}
|
||||
52
utils/dx_proxy/dxincludeimpl.h
Normal file
52
utils/dx_proxy/dxincludeimpl.h
Normal 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
|
||||
118
utils/dx_proxy/filememcache.cpp
Normal file
118
utils/dx_proxy/filememcache.cpp
Normal 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();
|
||||
}
|
||||
|
||||
68
utils/dx_proxy/filememcache.h
Normal file
68
utils/dx_proxy/filememcache.h
Normal 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
36
utils/fbx2dmx/fbx2dmx.vpc
Normal 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
771
utils/fbx2dmx/main.cpp
Normal 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 ) );
|
||||
}
|
||||
1500
utils/hlfaceposer/AnimationBrowser.cpp
Normal file
1500
utils/hlfaceposer/AnimationBrowser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
187
utils/hlfaceposer/AnimationBrowser.h
Normal file
187
utils/hlfaceposer/AnimationBrowser.h
Normal 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
|
||||
993
utils/hlfaceposer/CloseCaptionTool.cpp
Normal file
993
utils/hlfaceposer/CloseCaptionTool.cpp
Normal 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;
|
||||
}
|
||||
74
utils/hlfaceposer/CloseCaptionTool.h
Normal file
74
utils/hlfaceposer/CloseCaptionTool.h
Normal 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
|
||||
271
utils/hlfaceposer/EdgeProperties.cpp
Normal file
271
utils/hlfaceposer/EdgeProperties.cpp
Normal 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;
|
||||
}
|
||||
42
utils/hlfaceposer/EdgeProperties.h
Normal file
42
utils/hlfaceposer/EdgeProperties.h
Normal 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
|
||||
82
utils/hlfaceposer/EditPhrase.cpp
Normal file
82
utils/hlfaceposer/EditPhrase.cpp
Normal 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;
|
||||
}
|
||||
39
utils/hlfaceposer/EditPhrase.h
Normal file
39
utils/hlfaceposer/EditPhrase.h
Normal 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
|
||||
1986
utils/hlfaceposer/GestureTool.cpp
Normal file
1986
utils/hlfaceposer/GestureTool.cpp
Normal file
File diff suppressed because it is too large
Load Diff
174
utils/hlfaceposer/GestureTool.h
Normal file
174
utils/hlfaceposer/GestureTool.h
Normal 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
|
||||
33
utils/hlfaceposer/ICloseCaptionManager.h
Normal file
33
utils/hlfaceposer/ICloseCaptionManager.h
Normal 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
|
||||
243
utils/hlfaceposer/ProgressDialog.cpp
Normal file
243
utils/hlfaceposer/ProgressDialog.cpp
Normal 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
Reference in New Issue
Block a user