mirror of
https://github.com/celisej567/source-engine.git
synced 2025-12-31 21:48:22 +03:00
1
This commit is contained in:
73
utils/FileSystemOpenDialog/FileDialogApp.cpp
Normal file
73
utils/FileSystemOpenDialog/FileDialogApp.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//========= Copyright 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 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
|
||||
|
||||
997
utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp
Normal file
997
utils/FileSystemOpenDialog/FileSystemOpenDlg.cpp
Normal file
@@ -0,0 +1,997 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// FileSystemOpenDlg.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "FileSystemOpenDlg.h"
|
||||
#include "jpeglib/jpeglib.h"
|
||||
#include "utldict.h"
|
||||
#include "resource.h"
|
||||
#include "ifilesystemopendialog.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
|
||||
CFileInfo::CFileInfo()
|
||||
{
|
||||
m_pBitmap = NULL;
|
||||
}
|
||||
|
||||
|
||||
CFileInfo::~CFileInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// This caches the thumbnail bitmaps we generate to speed up browsing.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CBitmapCache
|
||||
{
|
||||
public:
|
||||
CBitmapCache()
|
||||
{
|
||||
m_CurMemoryUsage = 0;
|
||||
m_MaxMemoryUsage = 1024 * 1024 * 6;
|
||||
}
|
||||
|
||||
void AddToCache( CBitmap *pBitmap, const char *pName, int memoryUsage, bool bLock )
|
||||
{
|
||||
Assert( m_Bitmaps.Find( pName ) == -1 );
|
||||
m_CurMemoryUsage += memoryUsage;
|
||||
|
||||
CBitmapCacheEntry newEntry;
|
||||
newEntry.m_pBitmap = pBitmap;
|
||||
newEntry.m_MemoryUsage = memoryUsage;
|
||||
newEntry.m_bLocked = bLock;
|
||||
m_Bitmaps.Insert( pName, newEntry );
|
||||
|
||||
EnsureMemoryUsage();
|
||||
}
|
||||
|
||||
CBitmap* Find( const char *pName )
|
||||
{
|
||||
int i = m_Bitmaps.Find( pName );
|
||||
if ( i == -1 )
|
||||
return NULL;
|
||||
else
|
||||
return m_Bitmaps[i].m_pBitmap;
|
||||
}
|
||||
|
||||
void UnlockAll()
|
||||
{
|
||||
for ( int i=m_Bitmaps.First(); i != m_Bitmaps.InvalidIndex(); i=m_Bitmaps.Next( i ) )
|
||||
{
|
||||
m_Bitmaps[i].m_bLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void EnsureMemoryUsage()
|
||||
{
|
||||
while ( m_CurMemoryUsage > m_MaxMemoryUsage )
|
||||
{
|
||||
// Free something.
|
||||
bool bFreed = false;
|
||||
for ( int i=m_Bitmaps.First(); i != m_Bitmaps.InvalidIndex(); i=m_Bitmaps.Next( i ) )
|
||||
{
|
||||
if ( !m_Bitmaps[i].m_bLocked )
|
||||
{
|
||||
delete m_Bitmaps[i].m_pBitmap;
|
||||
m_CurMemoryUsage -= m_Bitmaps[i].m_MemoryUsage;
|
||||
m_Bitmaps.RemoveAt( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing left to free?
|
||||
if ( !bFreed )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
class CBitmapCacheEntry
|
||||
{
|
||||
public:
|
||||
CBitmap *m_pBitmap;
|
||||
int m_MemoryUsage;
|
||||
bool m_bLocked;
|
||||
};
|
||||
|
||||
CUtlDict<CBitmapCacheEntry,int> m_Bitmaps;
|
||||
int m_CurMemoryUsage;
|
||||
int m_MaxMemoryUsage;
|
||||
};
|
||||
|
||||
CBitmapCache g_BitmapCache;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CFileSystemOpenDlg dialog
|
||||
|
||||
CFileSystemOpenDlg::CFileSystemOpenDlg(CreateInterfaceFn factory, CWnd* pParent )
|
||||
: CDialog(CFileSystemOpenDlg::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CFileSystemOpenDlg)
|
||||
//}}AFX_DATA_INIT
|
||||
m_pFileSystem = (IFileSystem*)factory( FILESYSTEM_INTERFACE_VERSION, NULL );
|
||||
if ( !m_pFileSystem )
|
||||
{
|
||||
Error( "Unable to connect to %s!\n", FILESYSTEM_INTERFACE_VERSION );
|
||||
}
|
||||
|
||||
m_bFilterMdlAndJpgFiles = false;
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(CFileSystemOpenDlg)
|
||||
DDX_Control(pDX, IDC_FILENAME_LABEL, m_FilenameLabel);
|
||||
DDX_Control(pDX, IDC_FILENAME, m_FilenameControl);
|
||||
DDX_Control(pDX, IDC_LOOKIN, m_LookInLabel);
|
||||
DDX_Control(pDX, IDC_FILE_LIST, m_FileList);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CFileSystemOpenDlg, CDialog)
|
||||
//{{AFX_MSG_MAP(CFileSystemOpenDlg)
|
||||
ON_WM_CREATE()
|
||||
ON_WM_SIZE()
|
||||
ON_NOTIFY(NM_DBLCLK, IDC_FILE_LIST, OnDblclkFileList)
|
||||
ON_BN_CLICKED(IDC_UP_BUTTON, OnUpButton)
|
||||
ON_NOTIFY(LVN_ITEMCHANGED, IDC_FILE_LIST, OnItemchangedFileList)
|
||||
ON_WM_KEYDOWN()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CFileSystemOpenDlg message handlers
|
||||
|
||||
void CFileSystemOpenDlg::OnOK()
|
||||
{
|
||||
// Make sure it's a valid filename.
|
||||
CString testFilename;
|
||||
m_FilenameControl.GetWindowText( testFilename );
|
||||
|
||||
CString fullFilename = m_CurrentDir + "\\" + testFilename;
|
||||
if ( m_pFileSystem->IsDirectory( fullFilename, GetPathID() ) )
|
||||
{
|
||||
m_CurrentDir = fullFilename;
|
||||
PopulateListControl();
|
||||
}
|
||||
else if ( m_pFileSystem->FileExists( fullFilename, GetPathID() ) )
|
||||
{
|
||||
m_Filename = fullFilename;
|
||||
|
||||
// Translate .jpg to .mdl?
|
||||
if ( m_bFilterMdlAndJpgFiles )
|
||||
{
|
||||
char tempFilename[MAX_PATH];
|
||||
V_strcpy_safe( tempFilename, fullFilename );
|
||||
char *pPos = strrchr( tempFilename, '.' );
|
||||
if ( pPos )
|
||||
{
|
||||
if ( Q_stricmp( pPos, ".jpeg" ) == 0 || Q_stricmp( pPos, ".jpg" ) == 0 )
|
||||
{
|
||||
pPos[0] = 0;
|
||||
V_strcat_safe( tempFilename, ".mdl" );
|
||||
m_Filename = tempFilename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndDialog( IDOK );
|
||||
}
|
||||
else
|
||||
{
|
||||
// No file or directory here.
|
||||
CString str;
|
||||
str.FormatMessage( "File %1!s! doesn't exist.", (const char*)fullFilename );
|
||||
AfxMessageBox( str, MB_OK );
|
||||
}
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::SetInitialDir( const char *pDir, const char *pPathID )
|
||||
{
|
||||
m_CurrentDir = pDir;
|
||||
if ( pPathID )
|
||||
m_PathIDString = pPathID;
|
||||
else
|
||||
m_PathIDString = "";
|
||||
}
|
||||
|
||||
CString CFileSystemOpenDlg::GetFilename() const
|
||||
{
|
||||
return m_Filename;
|
||||
}
|
||||
|
||||
|
||||
BOOL CFileSystemOpenDlg::OnInitDialog()
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// Setup our anchor list.
|
||||
AddAnchor( IDC_FILE_LIST, 2, 2 );
|
||||
AddAnchor( IDC_FILE_LIST, 3, 3 );
|
||||
|
||||
AddAnchor( IDC_FILENAME, 1, 3 );
|
||||
AddAnchor( IDC_FILENAME, 3, 3 );
|
||||
AddAnchor( IDC_FILENAME, 2, 2 );
|
||||
|
||||
AddAnchor( IDC_FILENAME_LABEL, 0, 0 );
|
||||
AddAnchor( IDC_FILENAME_LABEL, 2, 0 );
|
||||
AddAnchor( IDC_FILENAME_LABEL, 1, 3 );
|
||||
AddAnchor( IDC_FILENAME_LABEL, 3, 3 );
|
||||
|
||||
AddAnchor( IDOK, 0, 2 );
|
||||
AddAnchor( IDOK, 2, 2 );
|
||||
AddAnchor( IDOK, 1, 3 );
|
||||
AddAnchor( IDOK, 3, 3 );
|
||||
|
||||
AddAnchor( IDCANCEL, 0, 2 );
|
||||
AddAnchor( IDCANCEL, 2, 2 );
|
||||
AddAnchor( IDCANCEL, 1, 3 );
|
||||
AddAnchor( IDCANCEL, 3, 3 );
|
||||
|
||||
AddAnchor( IDC_LOOKIN, 2, 2 );
|
||||
|
||||
AddAnchor( IDC_UP_BUTTON, 0, 2 );
|
||||
AddAnchor( IDC_UP_BUTTON, 2, 2 );
|
||||
|
||||
|
||||
// Setup our image list.
|
||||
m_ImageList.Create( PREVIEW_IMAGE_SIZE, PREVIEW_IMAGE_SIZE, ILC_COLOR32, 0, 512 );
|
||||
|
||||
m_BitmapFolder.LoadBitmap( IDB_LABEL_FOLDER );
|
||||
m_iLabel_Folder = m_ImageList.Add( &m_BitmapFolder, (CBitmap*)NULL );
|
||||
|
||||
m_BitmapMdl.LoadBitmap( IDB_LABEL_MDL );
|
||||
m_iLabel_Mdl = m_ImageList.Add( &m_BitmapMdl, (CBitmap*)NULL );
|
||||
|
||||
m_BitmapFile.LoadBitmap( IDB_LABEL_FILE );
|
||||
m_iLabel_File = m_ImageList.Add( &m_BitmapFile, (CBitmap*)NULL );
|
||||
|
||||
m_FileList.SetImageList( &m_ImageList, LVSIL_NORMAL );
|
||||
|
||||
// Populate the list with the contents of our current directory.
|
||||
PopulateListControl();
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// EXCEPTION: OCX Property Pages should return FALSE
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::GetEntries( const char *pMask, CUtlVector<CString> &entries, GetEntriesMode_t mode )
|
||||
{
|
||||
CString searchStr = m_CurrentDir + "\\" + pMask;
|
||||
|
||||
// Workaround Steam bug.
|
||||
if ( searchStr == ".\\*.*" )
|
||||
searchStr = "*.*";
|
||||
|
||||
FileFindHandle_t handle;
|
||||
const char *pFile = m_pFileSystem->FindFirst( searchStr, &handle );
|
||||
while ( pFile )
|
||||
{
|
||||
bool bIsDir = m_pFileSystem->FindIsDirectory( handle );
|
||||
if ( (mode == GETENTRIES_DIRECTORIES_ONLY && bIsDir) || (mode == GETENTRIES_FILES_ONLY && !bIsDir) )
|
||||
{
|
||||
entries.AddToTail( pFile );
|
||||
}
|
||||
|
||||
pFile = m_pFileSystem->FindNext( handle );
|
||||
}
|
||||
m_pFileSystem->FindClose( handle );
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CJpegSourceMgr : public jpeg_source_mgr
|
||||
{
|
||||
public:
|
||||
CJpegSourceMgr()
|
||||
{
|
||||
this->init_source = &CJpegSourceMgr::imp_init_source;
|
||||
this->fill_input_buffer = &CJpegSourceMgr::imp_fill_input_buffer;
|
||||
this->skip_input_data = &CJpegSourceMgr::imp_skip_input_data;
|
||||
this->resync_to_restart = &CJpegSourceMgr::imp_resync_to_restart;
|
||||
this->term_source = &CJpegSourceMgr::imp_term_source;
|
||||
|
||||
this->next_input_byte = 0;
|
||||
this->bytes_in_buffer = 0;
|
||||
}
|
||||
|
||||
bool Init( IFileSystem *pFileSystem, FileHandle_t fp )
|
||||
{
|
||||
m_Data.SetSize( pFileSystem->Size( fp ) );
|
||||
return pFileSystem->Read( m_Data.Base(), m_Data.Count(), fp ) == m_Data.Count();
|
||||
}
|
||||
|
||||
static void imp_init_source(j_decompress_ptr cinfo)
|
||||
{
|
||||
}
|
||||
|
||||
static boolean imp_fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
Assert( false ); // They should never need to call these functions since we give them all the data up front.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imp_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
AssertOnce( false ); // They should never need to call these functions since we give them all the data up front.
|
||||
}
|
||||
|
||||
static boolean imp_resync_to_restart(j_decompress_ptr cinfo, int desired)
|
||||
{
|
||||
Assert( false ); // They should never need to call these functions since we give them all the data up front.
|
||||
return false;
|
||||
}
|
||||
|
||||
static void imp_term_source(j_decompress_ptr cinfo)
|
||||
{
|
||||
}
|
||||
|
||||
static void error_exit( j_common_ptr cptr )
|
||||
{
|
||||
CJpegSourceMgr *pInstance = (CJpegSourceMgr*)cptr->client_data;
|
||||
longjmp( pInstance->m_JmpBuf, 1 );
|
||||
}
|
||||
|
||||
public:
|
||||
jmp_buf m_JmpBuf;
|
||||
CUtlVector<char> m_Data;
|
||||
};
|
||||
|
||||
|
||||
bool ReadJpeg( IFileSystem *pFileSystem, const char *pFilename, CUtlVector<unsigned char> &buf, int &width, int &height, const char *pPathID )
|
||||
{
|
||||
width = height = 0;
|
||||
|
||||
// Read the data.
|
||||
FileHandle_t fp = pFileSystem->Open( pFilename, "rb", pPathID );
|
||||
if ( fp == FILESYSTEM_INVALID_HANDLE )
|
||||
return false;
|
||||
|
||||
CJpegSourceMgr sourceMgr;
|
||||
bool bRet = sourceMgr.Init( pFileSystem, fp );
|
||||
pFileSystem->Close( fp );
|
||||
if ( !bRet )
|
||||
return false;
|
||||
|
||||
sourceMgr.bytes_in_buffer = sourceMgr.m_Data.Count();
|
||||
sourceMgr.next_input_byte = (unsigned char*)sourceMgr.m_Data.Base();
|
||||
|
||||
// Load the jpeg.
|
||||
struct jpeg_decompress_struct jpegInfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
memset( &jpegInfo, 0, sizeof( jpegInfo ) );
|
||||
jpegInfo.client_data = &sourceMgr;
|
||||
jpegInfo.err = jpeg_std_error(&jerr);
|
||||
jerr.error_exit = &CJpegSourceMgr::error_exit;
|
||||
jpeg_create_decompress(&jpegInfo);
|
||||
jpegInfo.src = &sourceMgr;
|
||||
|
||||
if ( setjmp( sourceMgr.m_JmpBuf ) == 1 )
|
||||
{
|
||||
jpeg_destroy_decompress(&jpegInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (jpeg_read_header(&jpegInfo, TRUE) != JPEG_HEADER_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// start the decompress with the jpeg engine.
|
||||
if (jpeg_start_decompress(&jpegInfo) != TRUE || jpegInfo.output_components != 3)
|
||||
{
|
||||
jpeg_destroy_decompress(&jpegInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
// now that we've started the decompress with the jpeg lib, we have the attributes of the
|
||||
// image ready to be read out of the decompress struct.
|
||||
int row_stride = jpegInfo.output_width * jpegInfo.output_components;
|
||||
int mem_required = jpegInfo.image_height * jpegInfo.image_width * jpegInfo.output_components;
|
||||
JSAMPROW row_pointer[1];
|
||||
int cur_row = 0;
|
||||
|
||||
width = jpegInfo.output_width;
|
||||
height = jpegInfo.output_height;
|
||||
|
||||
// allocate the memory to read the image data into.
|
||||
buf.SetSize( mem_required );
|
||||
|
||||
// read in all the scan lines of the image into our image data buffer.
|
||||
bool working = true;
|
||||
while (working && (jpegInfo.output_scanline < jpegInfo.output_height))
|
||||
{
|
||||
row_pointer[0] = &(buf[cur_row * row_stride]);
|
||||
if (jpeg_read_scanlines(&jpegInfo, row_pointer, 1) != TRUE)
|
||||
{
|
||||
working = false;
|
||||
}
|
||||
++cur_row;
|
||||
}
|
||||
|
||||
if (!working)
|
||||
{
|
||||
jpeg_destroy_decompress(&jpegInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&jpegInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DownsampleRGBToRGBAImage(
|
||||
CUtlVector<unsigned char> &srcData,
|
||||
int srcWidth,
|
||||
int srcHeight,
|
||||
CUtlVector<unsigned char> &destData,
|
||||
int destWidth,
|
||||
int destHeight )
|
||||
{
|
||||
int srcPixelSize = 3;
|
||||
int destPixelSize = 4;
|
||||
destData.SetSize( destWidth * destHeight * destPixelSize );
|
||||
memset( destData.Base(), 0xFF, destWidth * destHeight * destPixelSize );
|
||||
|
||||
// This preserves the aspect ratio of the image.
|
||||
int scaledDestWidth = destWidth;
|
||||
int scaledDestHeight = destHeight;
|
||||
int destOffsetX = 0, destOffsetY = 0;
|
||||
if ( srcWidth > srcHeight )
|
||||
{
|
||||
scaledDestHeight = (srcHeight * destHeight) / srcWidth;
|
||||
destOffsetY = (destHeight - scaledDestHeight) / 2;
|
||||
}
|
||||
else if ( srcHeight > srcWidth )
|
||||
{
|
||||
scaledDestWidth = (srcWidth * destWidth) / srcHeight;
|
||||
destOffsetX = (destWidth - scaledDestWidth) / 2;
|
||||
}
|
||||
|
||||
for ( int destY=0; destY < scaledDestHeight; destY++ )
|
||||
{
|
||||
unsigned char *pDestLine = &destData[(destY + destOffsetY) * destWidth * destPixelSize + (destOffsetX * destPixelSize)];
|
||||
unsigned char *pDestPos = pDestLine;
|
||||
|
||||
float destYPercent = (float)destY / (scaledDestHeight-1);
|
||||
int srcY = (int)( destYPercent * (srcHeight-1) );
|
||||
|
||||
for ( int destX=0; destX < scaledDestWidth; destX++ )
|
||||
{
|
||||
float destXPercent = (float)destX / (scaledDestWidth-1);
|
||||
|
||||
int srcX = (int)( destXPercent * (srcWidth-1) );
|
||||
unsigned char *pSrcPos = &srcData[(srcY * srcWidth + srcX) * srcPixelSize];
|
||||
pDestPos[0] = pSrcPos[2];
|
||||
pDestPos[1] = pSrcPos[1];
|
||||
pDestPos[2] = pSrcPos[0];
|
||||
pDestPos[3] = 255;
|
||||
|
||||
pDestPos += destPixelSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CBitmap* SetupJpegLabel( IFileSystem *pFileSystem, CString filename, int labelSize, const char *pPathID )
|
||||
{
|
||||
CBitmap *pBitmap = g_BitmapCache.Find( filename );
|
||||
if ( pBitmap )
|
||||
return pBitmap;
|
||||
|
||||
CUtlVector<unsigned char> data;
|
||||
int width, height;
|
||||
if ( !ReadJpeg( pFileSystem, filename, data, width, height, pPathID ) )
|
||||
return NULL;
|
||||
|
||||
CUtlVector<unsigned char> downsampled;
|
||||
DownsampleRGBToRGBAImage( data, width, height, downsampled, labelSize, labelSize );
|
||||
|
||||
pBitmap = new CBitmap;
|
||||
if ( pBitmap->CreateBitmap( labelSize, labelSize, 1, 32, downsampled.Base() ) )
|
||||
{
|
||||
g_BitmapCache.AddToCache( pBitmap, filename, downsampled.Count(), true );
|
||||
return pBitmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pBitmap;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int CFileSystemOpenDlg::SetupLabelImage( CFileInfo *pInfo, CString name, bool bIsDir )
|
||||
{
|
||||
if ( bIsDir )
|
||||
return m_iLabel_Folder;
|
||||
|
||||
CString extension = name.Right( 4 );
|
||||
extension.MakeLower();
|
||||
if ( extension == ".jpg" || extension == ".jpeg" )
|
||||
{
|
||||
pInfo->m_pBitmap = SetupJpegLabel( m_pFileSystem, m_CurrentDir + "\\" + name, PREVIEW_IMAGE_SIZE, GetPathID() );
|
||||
if ( pInfo->m_pBitmap )
|
||||
return m_ImageList.Add( pInfo->m_pBitmap, (CBitmap*)NULL );
|
||||
else
|
||||
return m_iLabel_File;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (extension == ".mdl") ? m_iLabel_Mdl : m_iLabel_File;
|
||||
}
|
||||
}
|
||||
|
||||
void FilterMdlAndJpgFiles( CUtlVector<CString> &files )
|
||||
{
|
||||
// Build a dictionary with all the .jpeg files.
|
||||
CUtlDict<int,int> jpgFiles;
|
||||
for ( int i=0; i < files.Count(); i++ )
|
||||
{
|
||||
CString extension = files[i].Right( 4 );
|
||||
extension.MakeLower();
|
||||
if ( extension == ".jpg" || extension == ".jpeg" )
|
||||
{
|
||||
CString base = files[i].Left( files[i].GetLength() - 4 );
|
||||
jpgFiles.Insert( base, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// Now look for all mdls and remove them if they have a jpg.
|
||||
for ( int i=0; i < files.Count(); i++ )
|
||||
{
|
||||
CString extension = files[i].Right( 4 );
|
||||
extension.MakeLower();
|
||||
if ( extension == ".mdl" )
|
||||
{
|
||||
CString base = files[i].Left( files[i].GetLength() - 4 );
|
||||
if ( jpgFiles.Find( base ) != -1 )
|
||||
{
|
||||
files.Remove( i );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CALLBACK FileListSortCallback( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
|
||||
{
|
||||
CFileSystemOpenDlg *pDlg = (CFileSystemOpenDlg*)lParamSort;
|
||||
CFileInfo *pInfo1 = &pDlg->m_FileInfos[lParam1];
|
||||
CFileInfo *pInfo2 = &pDlg->m_FileInfos[lParam2];
|
||||
if ( pInfo1->m_bIsDir != pInfo2->m_bIsDir )
|
||||
return pInfo1->m_bIsDir ? -1 : 1;
|
||||
|
||||
return Q_stricmp( pInfo1->m_Name, pInfo2->m_Name );
|
||||
}
|
||||
|
||||
|
||||
void RemoveDuplicates( CUtlVector<CString> &files )
|
||||
{
|
||||
CUtlDict<int,int> uniqueFilenames;
|
||||
for ( int i=0; i < files.Count(); i++ )
|
||||
{
|
||||
int iPreviousIndex = uniqueFilenames.Find( files[i] );
|
||||
if ( iPreviousIndex == -1 )
|
||||
{
|
||||
uniqueFilenames.Insert( files[i], i );
|
||||
}
|
||||
else
|
||||
{
|
||||
files.Remove( i );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CFileSystemOpenDlg::PopulateListControl()
|
||||
{
|
||||
m_FileList.DeleteAllItems();
|
||||
g_BitmapCache.UnlockAll();
|
||||
m_LookInLabel.SetWindowText( CString( "[ROOT]\\" ) + m_CurrentDir );
|
||||
|
||||
int iItem = 0;
|
||||
|
||||
// First add directories at the top.
|
||||
CUtlVector<CString> directories;
|
||||
GetEntries( "*.*", directories, GETENTRIES_DIRECTORIES_ONLY );
|
||||
RemoveDuplicates( directories );
|
||||
|
||||
for ( int i=0; i < directories.Count(); i++ )
|
||||
{
|
||||
if ( directories[i] == "." || directories[i] == ".." )
|
||||
continue;
|
||||
|
||||
LVITEM item;
|
||||
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||||
item.iItem = iItem++;
|
||||
item.iSubItem = 0;
|
||||
item.pszText = directories[i].GetBuffer(0);
|
||||
|
||||
item.lParam = m_FileInfos.AddToTail();
|
||||
m_FileInfos[item.lParam].m_bIsDir = true;
|
||||
m_FileInfos[item.lParam].m_Name = directories[i];
|
||||
item.iImage = SetupLabelImage( &m_FileInfos[item.lParam], directories[i], true );
|
||||
|
||||
m_FileList.InsertItem( &item );
|
||||
}
|
||||
|
||||
CUtlVector<CString> files;
|
||||
for ( int iMask=0; iMask < m_FileMasks.Count(); iMask++ )
|
||||
{
|
||||
GetEntries( m_FileMasks[iMask], files, GETENTRIES_FILES_ONLY );
|
||||
}
|
||||
|
||||
RemoveDuplicates( files );
|
||||
if ( m_bFilterMdlAndJpgFiles )
|
||||
FilterMdlAndJpgFiles( files );
|
||||
|
||||
for ( int i=0; i < files.Count(); i++ )
|
||||
{
|
||||
LVITEM item;
|
||||
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||||
item.iItem = iItem++;
|
||||
item.iSubItem = 0;
|
||||
item.iImage = m_iLabel_Mdl;
|
||||
item.pszText = files[i].GetBuffer(0);
|
||||
|
||||
item.lParam = m_FileInfos.AddToTail();
|
||||
m_FileInfos[item.lParam].m_bIsDir = false;
|
||||
m_FileInfos[item.lParam].m_Name = files[i];
|
||||
item.iImage = SetupLabelImage( &m_FileInfos[item.lParam], files[i], false );
|
||||
|
||||
m_FileList.InsertItem( &item );
|
||||
}
|
||||
|
||||
m_FileList.SortItems( FileListSortCallback, (DWORD)this );
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::AddFileMask( const char *pMask )
|
||||
{
|
||||
m_FileMasks.AddToTail( pMask );
|
||||
}
|
||||
|
||||
|
||||
BOOL CFileSystemOpenDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
|
||||
{
|
||||
return CDialog::Create(IDD, pParentWnd);
|
||||
}
|
||||
|
||||
int CFileSystemOpenDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
||||
{
|
||||
if (CDialog::OnCreate(lpCreateStruct) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LONG& GetSideCoord( RECT &rect, int iSide )
|
||||
{
|
||||
if ( iSide == 0 )
|
||||
return rect.left;
|
||||
else if ( iSide == 1 )
|
||||
return rect.top;
|
||||
else if ( iSide == 2 )
|
||||
return rect.right;
|
||||
else
|
||||
return rect.bottom;
|
||||
}
|
||||
|
||||
|
||||
LONG GetSideScreenCoord( CWnd *pWnd, int iSide )
|
||||
{
|
||||
RECT rect;
|
||||
pWnd->GetWindowRect( &rect );
|
||||
return GetSideCoord( rect, iSide );
|
||||
}
|
||||
|
||||
|
||||
void CFileSystemOpenDlg::ProcessAnchor( CWindowAnchor *pAnchor )
|
||||
{
|
||||
RECT rect, parentRect;
|
||||
GetWindowRect( &parentRect );
|
||||
pAnchor->m_pWnd->GetWindowRect( &rect );
|
||||
|
||||
GetSideCoord( rect, pAnchor->m_Side ) = GetSideCoord( parentRect, pAnchor->m_ParentSide ) + pAnchor->m_OriginalDist;
|
||||
|
||||
ScreenToClient( &rect );
|
||||
pAnchor->m_pWnd->MoveWindow( &rect );
|
||||
}
|
||||
|
||||
|
||||
void CFileSystemOpenDlg::AddAnchor( int iDlgItem, int iSide, int iParentSide )
|
||||
{
|
||||
CWnd *pItem = GetDlgItem( iDlgItem );
|
||||
if ( !pItem )
|
||||
return;
|
||||
|
||||
CWindowAnchor *pAnchor = &m_Anchors[m_Anchors.AddToTail()];
|
||||
pAnchor->m_pWnd = pItem;
|
||||
pAnchor->m_Side = iSide;
|
||||
pAnchor->m_ParentSide = iParentSide;
|
||||
pAnchor->m_OriginalDist = GetSideScreenCoord( pItem, iSide ) - GetSideScreenCoord( this, iParentSide );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CFileSystemOpenDlg::OnSize(UINT nType, int cx, int cy)
|
||||
{
|
||||
CDialog::OnSize(nType, cx, cy);
|
||||
|
||||
for ( int i=0; i < m_Anchors.Count(); i++ )
|
||||
ProcessAnchor( &m_Anchors[i] );
|
||||
|
||||
if ( m_FileList.GetSafeHwnd() )
|
||||
PopulateListControl();
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::OnDblclkFileList(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
{
|
||||
/*int iSelected = m_FileList.GetNextItem( -1, LVNI_SELECTED );
|
||||
if ( iSelected != -1 )
|
||||
{
|
||||
DWORD iItem = m_FileList.GetItemData( iSelected );
|
||||
if ( iItem < (DWORD)m_FileInfos.Count() )
|
||||
{
|
||||
CFileInfo *pInfo = &m_FileInfos[iItem];
|
||||
if ( pInfo->m_bIsDir )
|
||||
{
|
||||
m_CurrentDir += "\\" + m_FileInfos[iItem].m_Name;
|
||||
PopulateListControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Filename = m_CurrentDir + "\\" + m_FileInfos[iItem].m_Name;
|
||||
EndDialog( IDOK );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( false );
|
||||
}
|
||||
}*/
|
||||
OnOK();
|
||||
|
||||
*pResult = 0;
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::OnUpButton()
|
||||
{
|
||||
char str[MAX_PATH];
|
||||
V_strcpy_safe( str, m_CurrentDir );
|
||||
Q_StripLastDir( str, sizeof( str ) );
|
||||
|
||||
if ( str[0] == 0 )
|
||||
V_strcpy_safe( str, "." );
|
||||
|
||||
if ( str[strlen(str)-1] == '\\' || str[strlen(str)-1] == '/' )
|
||||
str[strlen(str)-1] = 0;
|
||||
|
||||
m_CurrentDir = str;
|
||||
PopulateListControl();
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::OnItemchangedFileList(NMHDR* pNMHDR, LRESULT* pResult)
|
||||
{
|
||||
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
||||
|
||||
DWORD iItem = m_FileList.GetItemData( pNMListView->iItem );
|
||||
if ( iItem < (DWORD)m_FileInfos.Count() )
|
||||
{
|
||||
CFileInfo *pInfo = &m_FileInfos[iItem];
|
||||
if ( (pNMListView->uChanged & LVIF_STATE) &&
|
||||
(pNMListView->uNewState & LVIS_SELECTED) )
|
||||
{
|
||||
m_FilenameControl.SetWindowText( pInfo->m_Name );
|
||||
}
|
||||
}
|
||||
|
||||
*pResult = 0;
|
||||
}
|
||||
|
||||
void CFileSystemOpenDlg::SetFilterMdlAndJpgFiles( bool bFilter )
|
||||
{
|
||||
m_bFilterMdlAndJpgFiles = bFilter;
|
||||
}
|
||||
|
||||
const char* CFileSystemOpenDlg::GetPathID()
|
||||
{
|
||||
if ( m_PathIDString == "" )
|
||||
return NULL;
|
||||
else
|
||||
return (const char*)m_PathIDString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------ //
|
||||
// Implementation of IFileSystemOpenDialog.
|
||||
// ------------------------------------------------------------------------------------------------ //
|
||||
|
||||
// IFileSystemOpenDialog implementation.
|
||||
class CFileSystemOpenDialogWrapper : public IFileSystemOpenDialog
|
||||
{
|
||||
public:
|
||||
CFileSystemOpenDialogWrapper()
|
||||
{
|
||||
m_pDialog = 0;
|
||||
m_bLastModalWasWindowsDialog = false;
|
||||
}
|
||||
|
||||
virtual void Release()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
delete m_pDialog;
|
||||
delete this;
|
||||
}
|
||||
|
||||
// You must call this first to set the hwnd.
|
||||
virtual void Init( CreateInterfaceFn factory, void *parentHwnd )
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
Assert( !m_pDialog );
|
||||
|
||||
m_hParentWnd = (HWND)parentHwnd;
|
||||
m_pDialog = new CFileSystemOpenDlg( factory, CWnd::FromHandle( m_hParentWnd ) );
|
||||
}
|
||||
|
||||
virtual void AddFileMask( const char *pMask )
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
Assert( m_pDialog );
|
||||
m_pDialog->AddFileMask( pMask );
|
||||
}
|
||||
|
||||
virtual void SetInitialDir( const char *pDir, const char *pPathID )
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
Assert( m_pDialog );
|
||||
m_pDialog->SetInitialDir( pDir, pPathID );
|
||||
}
|
||||
|
||||
virtual void SetFilterMdlAndJpgFiles( bool bFilter )
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
Assert( m_pDialog );
|
||||
m_pDialog->SetFilterMdlAndJpgFiles( bFilter );
|
||||
}
|
||||
|
||||
virtual void GetFilename( char *pOut, int outLen ) const
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
Assert( m_pDialog );
|
||||
|
||||
if ( m_bLastModalWasWindowsDialog )
|
||||
{
|
||||
Q_strncpy( pOut, m_RelativeFilename, outLen );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strncpy( pOut, m_pDialog->GetFilename(), outLen );
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool DoModal()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
Assert( m_pDialog );
|
||||
|
||||
m_bLastModalWasWindowsDialog = false;
|
||||
return m_pDialog->DoModal() == IDOK;
|
||||
}
|
||||
|
||||
virtual bool DoModal_WindowsDialog()
|
||||
{
|
||||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||||
|
||||
Assert( m_pDialog );
|
||||
|
||||
m_bLastModalWasWindowsDialog = true;
|
||||
|
||||
// Get the full filename, then make sure it's a relative path.
|
||||
char defExt[MAX_PATH] = {0};
|
||||
if ( m_pDialog->m_FileMasks.Count() > 0 )
|
||||
{
|
||||
CString ext = m_pDialog->m_FileMasks[m_pDialog->m_FileMasks.Count()-1].Right( 4 );
|
||||
const char *pStr = ext;
|
||||
if ( pStr[0] == '.' )
|
||||
V_strcpy_safe( defExt, pStr+1 );
|
||||
}
|
||||
|
||||
char pFileNameBuf[MAX_PATH];
|
||||
const char *pFileName = m_pDialog->m_pFileSystem->RelativePathToFullPath( m_pDialog->m_CurrentDir, m_pDialog->m_PathIDString, pFileNameBuf, MAX_PATH );
|
||||
V_strcat_safe( pFileNameBuf, "\\" );
|
||||
|
||||
// Build the list of file filters.
|
||||
char filters[1024];
|
||||
if ( m_pDialog->m_FileMasks.Count() == 0 )
|
||||
{
|
||||
V_strcpy_safe( filters, "All Files (*.*)|*.*||" );
|
||||
}
|
||||
else
|
||||
{
|
||||
filters[0] = 0;
|
||||
for ( int i=0; i < m_pDialog->m_FileMasks.Count(); i++ )
|
||||
{
|
||||
if ( i > 0 )
|
||||
V_strcat_safe( filters, "|" );
|
||||
|
||||
V_strcat_safe( filters, m_pDialog->m_FileMasks[i] );
|
||||
V_strcat_safe( filters, "|" );
|
||||
V_strcat_safe( filters, m_pDialog->m_FileMasks[i] );
|
||||
if ( pFileName )
|
||||
{
|
||||
V_strcat_safe( pFileNameBuf, m_pDialog->m_FileMasks[i] );
|
||||
V_strcat_safe( pFileNameBuf, ";" );
|
||||
}
|
||||
|
||||
}
|
||||
V_strcat_safe( filters, "||" );
|
||||
}
|
||||
|
||||
CFileDialog dlg(
|
||||
true, // open dialog?
|
||||
defExt[0]==0 ? NULL : defExt, // default file extension
|
||||
pFileName, // initial filename
|
||||
OFN_ENABLESIZING, // flags
|
||||
filters,
|
||||
CWnd::FromHandle( m_hParentWnd ) );
|
||||
|
||||
while ( dlg.DoModal() == IDOK )
|
||||
{
|
||||
// Make sure we can make this into a relative path.
|
||||
if ( m_pDialog->m_pFileSystem->FullPathToRelativePath( dlg.GetPathName(), m_RelativeFilename, sizeof( m_RelativeFilename ) ) )
|
||||
{
|
||||
// Replace .jpg or .jpeg extension with .mdl?
|
||||
char *pEnd = m_RelativeFilename;
|
||||
while ( Q_stristr( pEnd+1, ".jpeg" ) || Q_stristr( pEnd+1, ".jpg" ) )
|
||||
pEnd = max( Q_stristr( pEnd, ".jpeg" ), Q_stristr( pEnd, ".jpg" ) );
|
||||
|
||||
if ( pEnd && pEnd != m_RelativeFilename )
|
||||
Q_strncpy( pEnd, ".mdl", sizeof( m_RelativeFilename ) - (pEnd - m_RelativeFilename) );
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AfxMessageBox( IDS_NO_RELATIVE_PATH );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
CFileSystemOpenDlg *m_pDialog;
|
||||
HWND m_hParentWnd;
|
||||
|
||||
char m_RelativeFilename[MAX_PATH];
|
||||
bool m_bLastModalWasWindowsDialog;
|
||||
};
|
||||
|
||||
EXPOSE_INTERFACE( CFileSystemOpenDialogWrapper, IFileSystemOpenDialog, FILESYSTEMOPENDIALOG_VERSION );
|
||||
|
||||
146
utils/FileSystemOpenDialog/FileSystemOpenDlg.h
Normal file
146
utils/FileSystemOpenDialog/FileSystemOpenDlg.h
Normal file
@@ -0,0 +1,146 @@
|
||||
//========= Copyright 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 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 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_)
|
||||
76
utils/FileSystemOpenDialog/filesystemopendialog.vpc
Normal file
76
utils/FileSystemOpenDialog/filesystemopendialog.vpc
Normal file
@@ -0,0 +1,76 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// FILESYSTEMOPENDIALOG.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
// Deprecated MBCS MFC libraries for VS 2013 (nafxcw.lib and nafxcwd.lib) can be downloaded from http://go.microsoft.com/?linkid=9832071
|
||||
$PreprocessorDefinitions "$BASE;NO_WARN_MBCS_MFC_DEPRECATION"
|
||||
$AdditionalIncludeDirectories "$BASE,..\common"
|
||||
$PreprocessorDefinitions "$BASE;;WINVER=0x502"
|
||||
$Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)"
|
||||
$PrecompiledHeaderFile "Debug/FileSystemOpenDialog.pch"
|
||||
$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
|
||||
{
|
||||
$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"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib $LIBCOMMON/libjpeg
|
||||
}
|
||||
}
|
||||
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 |
26
utils/FileSystemOpenDialog/resource.h
Normal file
26
utils/FileSystemOpenDialog/resource.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//{{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
|
||||
94
utils/QCGenerator/CQCGenMain.cpp
Normal file
94
utils/QCGenerator/CQCGenMain.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Dialog for selecting game configurations
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <vgui/IVGui.h>
|
||||
#include <vgui/IInput.h>
|
||||
#include <vgui/ISystem.h>
|
||||
#include <vgui_controls/MessageBox.h>
|
||||
|
||||
#include "matsys_controls/QCGenerator.h"
|
||||
#include "CQCGenMain.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
CQCGenMain *g_pCQCGenMain = NULL;
|
||||
|
||||
class CModalPreserveMessageBox : public vgui::MessageBox
|
||||
{
|
||||
public:
|
||||
CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent)
|
||||
: vgui::MessageBox( title, text, parent )
|
||||
{
|
||||
m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
|
||||
}
|
||||
|
||||
~CModalPreserveMessageBox()
|
||||
{
|
||||
vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
|
||||
}
|
||||
|
||||
public:
|
||||
vgui::VPANEL m_PrevAppFocusPanel;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CQCGenMain::CQCGenMain( Panel *parent, const char *pszPath, const char *pszScene , const char *name ) : BaseClass( parent, name ), m_bChanged( false )
|
||||
{
|
||||
Assert( !g_pCQCGenMain );
|
||||
g_pCQCGenMain = this;
|
||||
|
||||
SetMinimizeButtonVisible( true );
|
||||
|
||||
SetSize( 846, 770 );
|
||||
SetMinimumSize(846, 770);
|
||||
char szTitle[MAX_PATH];
|
||||
strcpy( szTitle, pszPath );
|
||||
strcat( szTitle, "\\" );
|
||||
strcat( szTitle, pszScene );
|
||||
SetTitle( szTitle, true );
|
||||
|
||||
m_pQCGenerator = new CQCGenerator( this, pszPath, pszScene );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CQCGenMain::~CQCGenMain()
|
||||
{
|
||||
g_pCQCGenMain = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Kills the whole app on close
|
||||
//-----------------------------------------------------------------------------
|
||||
void CQCGenMain::OnClose( void )
|
||||
{
|
||||
BaseClass::OnClose();
|
||||
ivgui()->Stop();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Parse commands coming in from the VGUI dialog
|
||||
//-----------------------------------------------------------------------------
|
||||
void CQCGenMain::OnCommand( const char *command )
|
||||
{
|
||||
BaseClass::OnCommand( command );
|
||||
}
|
||||
|
||||
void CQCGenMain::OnRefresh()
|
||||
{
|
||||
Repaint();
|
||||
}
|
||||
|
||||
54
utils/QCGenerator/CQCGenMain.h
Normal file
54
utils/QCGenerator/CQCGenMain.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef MDRIPPERMAIN_H
|
||||
#define MDRIPPERMAIN_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "matsys_controls/QCGenerator.h"
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include <FileSystem.h>
|
||||
#include "vgui/IScheme.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Main dialog for media browser
|
||||
//-----------------------------------------------------------------------------
|
||||
class CQCGenMain : public Frame
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CQCGenMain, Frame );
|
||||
|
||||
public:
|
||||
|
||||
CQCGenerator *m_pQCGenerator;
|
||||
CQCGenMain(Panel *parent, const char *name, const char *pszMDParam, const char *pszCollisionParam );
|
||||
virtual ~CQCGenMain();
|
||||
|
||||
protected:
|
||||
|
||||
virtual void OnClose();
|
||||
virtual void OnCommand( const char *command );
|
||||
|
||||
private:
|
||||
|
||||
void SetGlobalConfig( const char *modDir );
|
||||
|
||||
vgui::ComboBox *m_pConfigCombo;
|
||||
bool m_bChanged;
|
||||
vgui::MenuBar *m_pMenuBar;
|
||||
vgui::Panel *m_pClientArea;
|
||||
|
||||
MESSAGE_FUNC( OnRefresh, "refresh" );
|
||||
};
|
||||
|
||||
|
||||
extern CQCGenMain *g_pCQCGenMain;
|
||||
|
||||
|
||||
#endif // MDRIPPERMAIN_H
|
||||
33
utils/QCGenerator/QCGenerator.h
Normal file
33
utils/QCGenerator/QCGenerator.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef ELEMENTVIEWER_H
|
||||
#define ELEMENTVIEWER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class ISurface;
|
||||
class IVGui;
|
||||
class IPanel;
|
||||
}
|
||||
|
||||
class IFileSystem;
|
||||
//class IMaterialSystem;
|
||||
class IMatSystemSurface;
|
||||
|
||||
/*
|
||||
extern IFileSystem *g_pFileSystem;
|
||||
extern IMaterialSystem *g_pMaterialSystem;
|
||||
extern IMatSystemSurface *g_pMatSystemSurface;
|
||||
extern vgui::ISurface *g_pVGuiSurface;
|
||||
extern vgui::IVGui *g_pVGui;
|
||||
extern vgui::IPanel *g_pVGuiPanel;
|
||||
*/
|
||||
#endif // ELEMENTVIEWER_H
|
||||
223
utils/QCGenerator/main.cpp
Normal file
223
utils/QCGenerator/main.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Configuration utility
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui/IVGui.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
|
||||
#include "appframework/tier3app.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "inputsystem/iinputsystem.h"
|
||||
#include "matsys_controls/QCGenerator.h"
|
||||
#include "filesystem_init.h"
|
||||
#include "CQCGenMain.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
#define QCGENERATOR_MAIN_PATH_ID "MAIN"
|
||||
#define QCGENERATOR_WRITE_PATH "DEFAULT_WRITE_PATH"
|
||||
|
||||
CQCGenMain *g_pMainFrame = 0;
|
||||
|
||||
// Dummy window
|
||||
static WNDCLASS staticWndclass = { NULL };
|
||||
static ATOM staticWndclassAtom = 0;
|
||||
static HWND staticHwnd = 0;
|
||||
|
||||
// List of our game configs, as read from the gameconfig.txt file
|
||||
//HANDLE g_dwChangeHandle = NULL;
|
||||
|
||||
char pszPath[MAX_PATH];
|
||||
char pszScene[MAX_PATH];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Copy a string into a CUtlVector of characters
|
||||
//-----------------------------------------------------------------------------
|
||||
void UtlStrcpy( CUtlVector<char> &dest, const char *pSrc )
|
||||
{
|
||||
dest.EnsureCount( (int) (strlen( pSrc ) + 1) );
|
||||
Q_strncpy( dest.Base(), pSrc, dest.Count() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : const char
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *GetBaseDirectory( void )
|
||||
{
|
||||
static char path[MAX_PATH] = {0};
|
||||
if ( path[0] == 0 )
|
||||
{
|
||||
GetModuleFileName( (HMODULE)GetAppInstance(), path, sizeof( path ) );
|
||||
Q_StripLastDir( path, sizeof( path ) ); // Get rid of the filename.
|
||||
Q_StripTrailingSlash( path );
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Setup all our VGUI info
|
||||
//-----------------------------------------------------------------------------
|
||||
void InitializeVGUI( void )
|
||||
{
|
||||
vgui::ivgui()->SetSleep(false);
|
||||
|
||||
// Init the surface
|
||||
vgui::Panel *pPanel = new vgui::Panel( NULL, "TopPanel" );
|
||||
pPanel->SetVisible(true);
|
||||
|
||||
vgui::surface()->SetEmbeddedPanel(pPanel->GetVPanel());
|
||||
|
||||
// load the scheme
|
||||
vgui::scheme()->LoadSchemeFromFile( "resource/sourcescheme.res", NULL );
|
||||
|
||||
// localization
|
||||
g_pVGuiLocalize->AddFile( "resource/platform_%language%.txt");
|
||||
g_pVGuiLocalize->AddFile( "resource/vgui_%language%.txt");
|
||||
g_pVGuiLocalize->AddFile( "QCGenerator_english.txt");
|
||||
|
||||
// Start vgui
|
||||
vgui::ivgui()->Start();
|
||||
|
||||
// add our main window
|
||||
g_pMainFrame = new CQCGenMain( pPanel, pszPath, pszScene, "CQCGenMain" );
|
||||
|
||||
// show main window
|
||||
g_pMainFrame->MoveToCenterOfScreen();
|
||||
g_pMainFrame->Activate();
|
||||
g_pMainFrame->SetSizeable( true );
|
||||
g_pMainFrame->SetMenuButtonVisible( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Stop VGUI
|
||||
//-----------------------------------------------------------------------------
|
||||
void ShutdownVGUI( void )
|
||||
{
|
||||
delete g_pMainFrame;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The application object
|
||||
//-----------------------------------------------------------------------------
|
||||
class CQCGeneratorApp : public CVguiSteamApp
|
||||
{
|
||||
typedef CVguiSteamApp BaseClass;
|
||||
|
||||
public:
|
||||
// Methods of IApplication
|
||||
virtual bool Create();
|
||||
virtual bool PreInit();
|
||||
virtual int Main();
|
||||
virtual void PostShutdown();
|
||||
virtual void Destroy() {}
|
||||
};
|
||||
|
||||
DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( CQCGeneratorApp );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The application object
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CQCGeneratorApp::Create()
|
||||
{
|
||||
AppSystemInfo_t appSystems[] =
|
||||
{
|
||||
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
|
||||
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
|
||||
{ "", "" } // Required to terminate the list
|
||||
};
|
||||
|
||||
return AddSystems( appSystems );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Entry point
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CQCGeneratorApp::PreInit()
|
||||
{
|
||||
if ( !BaseClass::PreInit() )
|
||||
return false;
|
||||
|
||||
FileSystem_SetErrorMode( FS_ERRORMODE_AUTO );
|
||||
|
||||
// We only want to use the gameinfo.txt that is in the bin\vconfig directory.
|
||||
char dirName[MAX_PATH];
|
||||
Q_strncpy( dirName, GetBaseDirectory(), sizeof( dirName ) );
|
||||
Q_AppendSlash( dirName, sizeof( dirName ) );
|
||||
Q_strncat( dirName, "QCGenerator", sizeof( dirName ), COPY_ALL_CHARACTERS );
|
||||
|
||||
if ( !BaseClass::SetupSearchPaths( dirName, true, true ) )
|
||||
{
|
||||
::MessageBox( NULL, "Error", "Unable to initialize file system\n", MB_OK );
|
||||
return false;
|
||||
}
|
||||
|
||||
// the "base dir" so we can scan mod name
|
||||
g_pFullFileSystem->AddSearchPath( GetBaseDirectory(), QCGENERATOR_MAIN_PATH_ID );
|
||||
|
||||
// the main platform dir
|
||||
g_pFullFileSystem->AddSearchPath( "platform", "PLATFORM", PATH_ADD_TO_HEAD );
|
||||
g_pFullFileSystem->AddSearchPath( ".\\QCGenerator\\", QCGENERATOR_WRITE_PATH, PATH_ADD_TO_HEAD );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CQCGeneratorApp::PostShutdown()
|
||||
{
|
||||
BaseClass::PostShutdown();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Entry point
|
||||
//-----------------------------------------------------------------------------
|
||||
int CQCGeneratorApp::Main()
|
||||
{
|
||||
if ( CommandLine()->ParmValue( "-path" ) )
|
||||
{
|
||||
Q_strcpy( pszPath, CommandLine()->ParmValue( "-path" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
::MessageBox( NULL, "Usage: QCGenerator.exe -path [path to smd files] -scene [name of scene]\n", "Error", MB_OK );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( CommandLine()->ParmValue( "-scene" ) )
|
||||
{
|
||||
Q_strcpy( pszScene, CommandLine()->ParmValue( "-scene" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
::MessageBox( NULL, "Usage: QCGenerator.exe -path [path to smd files] -scene [name of scene]\n", "Error", MB_OK );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Run app frame loop
|
||||
InitializeVGUI();
|
||||
|
||||
// Run the app
|
||||
while (vgui::ivgui()->IsRunning())
|
||||
{
|
||||
Sleep( 10 );
|
||||
vgui::ivgui()->RunFrame();
|
||||
}
|
||||
|
||||
ShutdownVGUI();
|
||||
|
||||
return 1;
|
||||
}
|
||||
51
utils/QCGenerator/qcgenerator_launcher.vpc
Normal file
51
utils/QCGenerator/qcgenerator_launcher.vpc
Normal file
@@ -0,0 +1,51 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// QCGENERATOR_LAUNCHER.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
$Macro OUTBINNAME "QCGenerator"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_win_win32_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;$SRCDIR\vgui2\include;$SRCDIR\vgui2\controls;$SRCDIR\..\src\utils\common"
|
||||
$EnableC++Exceptions "Yes (/EHsc)"
|
||||
}
|
||||
|
||||
$Linker
|
||||
{
|
||||
$AdditionalDependencies "$BASE comctl32.lib Rpcrt4.lib dbghelp.lib"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "QCGenerator_Launcher"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "CQCGenMain.cpp"
|
||||
$File "main.cpp"
|
||||
$File "$SRCDIR\public\vgui_controls\vgui_controls.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "CQCGenMain.h"
|
||||
$File "..\common\filesystem_tools.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$DynamicFile "$SRCDIR\lib\public\appframework.lib"
|
||||
$DynamicFile "$SRCDIR\lib\public\matsys_controls.lib"
|
||||
$File "$SRCDIR\lib\common\sqlwrapper.lib"
|
||||
$DynamicFile "$SRCDIR\lib\public\tier2.lib"
|
||||
$DynamicFile "$SRCDIR\lib\public\tier3.lib"
|
||||
$DynamicFile "$SRCDIR\lib\public\vgui_controls.lib"
|
||||
}
|
||||
}
|
||||
18
utils/SteamDebugHelper/DebugSourceBeta.cfg
Normal file
18
utils/SteamDebugHelper/DebugSourceBeta.cfg
Normal file
@@ -0,0 +1,18 @@
|
||||
"debuginfo"
|
||||
{
|
||||
"SourceExeDir" "c:\sourcebeta"
|
||||
"SteamAppDir" "c:\valve\SteamTestPublic\steamapps\mikedussault\counter-strike source"
|
||||
|
||||
"SteamApp.Cfg"
|
||||
{
|
||||
"text" "SteamAppID=270"
|
||||
"text" "SteamAppUser=mikedussault"
|
||||
"text" "MinFootprintAutoRefresh=disable"
|
||||
// SteamInstallPath is added automatically by the SteamDebugHelper program.
|
||||
}
|
||||
|
||||
// These binaries get copied up to the steam directory for debugging.
|
||||
"binary" "bin\engine.dll"
|
||||
"binary" "cstrike\bin\server.dll"
|
||||
"binary" "cstrike\bin\client.dll"
|
||||
}
|
||||
15
utils/SteamDebugHelper/StdAfx.cpp
Normal file
15
utils/SteamDebugHelper/StdAfx.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// SteamDebugHelper.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
|
||||
33
utils/SteamDebugHelper/StdAfx.h
Normal file
33
utils/SteamDebugHelper/StdAfx.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//========= Copyright 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__1427A276_CEDF_4CBC_82F1_31B639DB70A8__INCLUDED_)
|
||||
#define AFX_STDAFX_H__1427A276_CEDF_4CBC_82F1_31B639DB70A8__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <afxwin.h> // MFC core and standard components
|
||||
#include <afxext.h> // MFC extensions
|
||||
#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
|
||||
#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__1427A276_CEDF_4CBC_82F1_31B639DB70A8__INCLUDED_)
|
||||
79
utils/SteamDebugHelper/SteamDebugHelper.cpp
Normal file
79
utils/SteamDebugHelper/SteamDebugHelper.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// SteamDebugHelper.cpp : Defines the class behaviors for the application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SteamDebugHelper.h"
|
||||
#include "SteamDebugHelperDlg.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSteamDebugHelperApp
|
||||
|
||||
BEGIN_MESSAGE_MAP(CSteamDebugHelperApp, CWinApp)
|
||||
//{{AFX_MSG_MAP(CSteamDebugHelperApp)
|
||||
// NOTE - the ClassWizard will add and remove mapping macros here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code!
|
||||
//}}AFX_MSG
|
||||
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSteamDebugHelperApp construction
|
||||
|
||||
CSteamDebugHelperApp::CSteamDebugHelperApp()
|
||||
{
|
||||
// TODO: add construction code here,
|
||||
// Place all significant initialization in InitInstance
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// The one and only CSteamDebugHelperApp object
|
||||
|
||||
CSteamDebugHelperApp theApp;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSteamDebugHelperApp initialization
|
||||
|
||||
BOOL CSteamDebugHelperApp::InitInstance()
|
||||
{
|
||||
// Standard initialization
|
||||
// If you are not using these features and wish to reduce the size
|
||||
// of your final executable, you should remove from the following
|
||||
// the specific initialization routines you do not need.
|
||||
|
||||
#ifdef _AFXDLL
|
||||
Enable3dControls(); // Call this when using MFC in a shared DLL
|
||||
#else
|
||||
Enable3dControlsStatic(); // Call this when linking to MFC statically
|
||||
#endif
|
||||
|
||||
CSteamDebugHelperDlg dlg;
|
||||
m_pMainWnd = &dlg;
|
||||
int nResponse = dlg.DoModal();
|
||||
if (nResponse == IDOK)
|
||||
{
|
||||
// TODO: Place code here to handle when the dialog is
|
||||
// dismissed with OK
|
||||
}
|
||||
else if (nResponse == IDCANCEL)
|
||||
{
|
||||
// TODO: Place code here to handle when the dialog is
|
||||
// dismissed with Cancel
|
||||
}
|
||||
|
||||
// Since the dialog has been closed, return FALSE so that we exit the
|
||||
// application, rather than start the application's message pump.
|
||||
return FALSE;
|
||||
}
|
||||
56
utils/SteamDebugHelper/SteamDebugHelper.h
Normal file
56
utils/SteamDebugHelper/SteamDebugHelper.h
Normal file
@@ -0,0 +1,56 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// SteamDebugHelper.h : main header file for the STEAMDEBUGHELPER application
|
||||
//
|
||||
|
||||
#if !defined(AFX_STEAMDEBUGHELPER_H__C6F4FF3C_B13B_4294_A881_57BC35FC16AF__INCLUDED_)
|
||||
#define AFX_STEAMDEBUGHELPER_H__C6F4FF3C_B13B_4294_A881_57BC35FC16AF__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
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSteamDebugHelperApp:
|
||||
// See SteamDebugHelper.cpp for the implementation of this class
|
||||
//
|
||||
|
||||
class CSteamDebugHelperApp : public CWinApp
|
||||
{
|
||||
public:
|
||||
CSteamDebugHelperApp();
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CSteamDebugHelperApp)
|
||||
public:
|
||||
virtual BOOL InitInstance();
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
|
||||
//{{AFX_MSG(CSteamDebugHelperApp)
|
||||
// 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_STEAMDEBUGHELPER_H__C6F4FF3C_B13B_4294_A881_57BC35FC16AF__INCLUDED_)
|
||||
184
utils/SteamDebugHelper/SteamDebugHelper.rc
Normal file
184
utils/SteamDebugHelper/SteamDebugHelper.rc
Normal file
@@ -0,0 +1,184 @@
|
||||
//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\\SteamDebugHelper.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
|
||||
"#include ""afxres.rc"" // Standard components\r\n"
|
||||
"#endif\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDR_MAINFRAME ICON DISCARDABLE "res\\SteamDebugHelper.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_STEAMDEBUGHELPER_DIALOG DIALOGEX 0, 0, 220, 166
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_APPWINDOW
|
||||
CAPTION "SteamDebugHelper - No File"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "&Setup For Debugging",ID_SETUP_FOR_DEBUGGING,40,19,139,
|
||||
14,WS_DISABLED
|
||||
PUSHBUTTON "&Un-setup For Debugging",ID_UNSETUP_FOR_DEBUGGING,40,38,
|
||||
139,14,WS_DISABLED
|
||||
PUSHBUTTON "&Choose Config File",ID_EDIT_CHOOSE_CONFIG_FILE,40,78,
|
||||
139,14
|
||||
PUSHBUTTON "&Edit Config File",ID_EDIT_CONFIG_FILE,40,97,139,14,
|
||||
WS_DISABLED
|
||||
PUSHBUTTON "&Launch Steam.exe",ID_START_STEAM,40,116,139,14
|
||||
PUSHBUTTON "&Quit",IDCANCEL,7,145,206,14
|
||||
GROUPBOX "Debug",IDC_STATIC,7,7,206,54
|
||||
GROUPBOX "Setup",IDC_STATIC,7,65,206,72
|
||||
END
|
||||
|
||||
|
||||
#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 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "SteamDebugHelper MFC Application\0"
|
||||
VALUE "FileVersion", "1, 0, 0, 1\0"
|
||||
VALUE "InternalName", "SteamDebugHelper\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2004\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "SteamDebugHelper.EXE\0"
|
||||
VALUE "ProductName", "SteamDebugHelper Application\0"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_STEAMDEBUGHELPER_DIALOG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 213
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 159
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#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\SteamDebugHelper.rc2" // non-Microsoft Visual C++ edited resources
|
||||
#include "afxres.rc" // Standard components
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
261
utils/SteamDebugHelper/SteamDebugHelper.vcproj
Normal file
261
utils/SteamDebugHelper/SteamDebugHelper.vcproj
Normal file
@@ -0,0 +1,261 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="SteamDebugHelper"
|
||||
ProjectGUID="{288FA186-3A0A-4003-ACC5-3813D62D6F32}"
|
||||
SccProjectName=""
|
||||
SccAuxPath=""
|
||||
SccLocalPath=""
|
||||
SccProvider=""
|
||||
Keyword="MFCProj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="1"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\public,..\..\public\tier1"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Debug/SteamDebugHelper.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="4"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="if exist ..\..\..\game\bin\SteamDebugHelper.exe del /f ..\..\..\game\bin\SteamDebugHelper.exe
|
||||
copy "$(TargetPath)" ..\..\..\game\bin
|
||||
"
|
||||
Outputs="..\..\..\game\bin\SteamDebugHelper.exe"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="nafxcwd.lib libcmtd.lib"
|
||||
OutputFile=".\Debug/SteamDebugHelper.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Debug/SteamDebugHelper.pdb"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/SteamDebugHelper.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="1"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\public,..\..\public\tier1"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Release/SteamDebugHelper.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="4"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="if exist ..\..\..\game\bin\SteamDebugHelper.exe del /f ..\..\..\game\bin\SteamDebugHelper.exe
|
||||
copy "$(TargetPath)" ..\..\..\game\bin
|
||||
"
|
||||
Outputs="..\..\..\game\bin\SteamDebugHelper.exe"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="nafxcw.lib libcmt.lib"
|
||||
OutputFile=".\Release/SteamDebugHelper.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
ProgramDatabaseFile=".\Release/SteamDebugHelper.pdb"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Release/SteamDebugHelper.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath="..\..\public\tier0\memoverride.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StdAfx.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SteamDebugHelper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SteamDebugHelper.rc">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SteamDebugHelperDlg.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath="Resource.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="StdAfx.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SteamDebugHelper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="SteamDebugHelperDlg.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
<File
|
||||
RelativePath="res\SteamDebugHelper.ico">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="res\SteamDebugHelper.rc2">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="ReadMe.txt">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\tier0.lib">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\tier1.lib">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\vstdlib.lib">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description=""
|
||||
CommandLine=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
384
utils/SteamDebugHelper/SteamDebugHelperDlg.cpp
Normal file
384
utils/SteamDebugHelper/SteamDebugHelperDlg.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// SteamDebugHelperDlg.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SteamDebugHelper.h"
|
||||
#include "SteamDebugHelperDlg.h"
|
||||
#include "filesystem.h"
|
||||
#include "interface.h"
|
||||
#include "filesystem_tools.h"
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include "tier0/icommandline.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
#define CHECK( cmd ) \
|
||||
if ( !(cmd) ) \
|
||||
Error( "%s failed", #cmd );
|
||||
|
||||
#define CHECK_1STR( cmd, a ) \
|
||||
if ( !(cmd) ) \
|
||||
Error( "%s failed (%s)", #cmd, a );
|
||||
|
||||
#define CHECK_2STR( cmd, a, b ) \
|
||||
if ( !(cmd) ) \
|
||||
Error( "%s failed (%s, %s)", #cmd, a, b );
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSteamDebugHelperDlg dialog
|
||||
|
||||
CSteamDebugHelperDlg::CSteamDebugHelperDlg(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(CSteamDebugHelperDlg::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(CSteamDebugHelperDlg)
|
||||
// NOTE: the ClassWizard will add member initialization here
|
||||
//}}AFX_DATA_INIT
|
||||
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
|
||||
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
||||
}
|
||||
|
||||
void CSteamDebugHelperDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(CSteamDebugHelperDlg)
|
||||
// NOTE: the ClassWizard will add DDX and DDV calls here
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(CSteamDebugHelperDlg, CDialog)
|
||||
//{{AFX_MSG_MAP(CSteamDebugHelperDlg)
|
||||
ON_WM_PAINT()
|
||||
ON_WM_QUERYDRAGICON()
|
||||
ON_BN_CLICKED(ID_SETUP_FOR_DEBUGGING, OnSetupForDebugging)
|
||||
ON_BN_CLICKED(ID_UNSETUP_FOR_DEBUGGING, OnUnsetupForDebugging)
|
||||
ON_BN_CLICKED(ID_START_STEAM, OnStartSteam)
|
||||
ON_BN_CLICKED(ID_EDIT_CONFIG_FILE, OnEditConfigFile)
|
||||
ON_BN_CLICKED(ID_EDIT_CHOOSE_CONFIG_FILE, OnEditChooseConfigFile)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSteamDebugHelperDlg message handlers
|
||||
|
||||
SpewRetval_t MySpewOutput( SpewType_t spewType, char const *pMsg )
|
||||
{
|
||||
if ( spewType == SPEW_ERROR )
|
||||
{
|
||||
::MessageBox( NULL, pMsg, "Error", MB_OK | MB_TASKMODAL );
|
||||
TerminateProcess( GetCurrentProcess(), 1 );
|
||||
}
|
||||
|
||||
if ( spewType == SPEW_ASSERT )
|
||||
return SPEW_DEBUGGER;
|
||||
|
||||
return SPEW_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL CSteamDebugHelperDlg::OnInitDialog()
|
||||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// Set the icon for this dialog. The framework does this automatically
|
||||
// when the application's main window is not a dialog
|
||||
SetIcon(m_hIcon, TRUE); // Set big icon
|
||||
SetIcon(m_hIcon, FALSE); // Set small icon
|
||||
|
||||
SpewOutputFunc( MySpewOutput );
|
||||
|
||||
// Load the file system.
|
||||
CommandLine()->CreateCmdLine( __argc, __argv );
|
||||
FileSystem_Init( NULL, 0, FS_INIT_COMPATIBILITY_MODE );
|
||||
|
||||
if ( __argc >= 2 )
|
||||
{
|
||||
SetConfigFilename( __argv[1] );
|
||||
}
|
||||
|
||||
// Make sure the config file parses.
|
||||
KeyValues *pTest = LoadConfigFile();
|
||||
pTest->deleteThis();
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
}
|
||||
|
||||
// If you add a minimize button to your dialog, you will need the code below
|
||||
// to draw the icon. For MFC applications using the document/view model,
|
||||
// this is automatically done for you by the framework.
|
||||
|
||||
void CSteamDebugHelperDlg::OnPaint()
|
||||
{
|
||||
if (IsIconic())
|
||||
{
|
||||
CPaintDC dc(this); // device context for painting
|
||||
|
||||
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
|
||||
|
||||
// Center icon in client rectangle
|
||||
int cxIcon = GetSystemMetrics(SM_CXICON);
|
||||
int cyIcon = GetSystemMetrics(SM_CYICON);
|
||||
CRect rect;
|
||||
GetClientRect(&rect);
|
||||
int x = (rect.Width() - cxIcon + 1) / 2;
|
||||
int y = (rect.Height() - cyIcon + 1) / 2;
|
||||
|
||||
// Draw the icon
|
||||
dc.DrawIcon(x, y, m_hIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
CDialog::OnPaint();
|
||||
}
|
||||
}
|
||||
|
||||
// The system calls this to obtain the cursor to display while the user drags
|
||||
// the minimized window.
|
||||
HCURSOR CSteamDebugHelperDlg::OnQueryDragIcon()
|
||||
{
|
||||
return (HCURSOR) m_hIcon;
|
||||
}
|
||||
|
||||
|
||||
KeyValues* CSteamDebugHelperDlg::LoadConfigFile()
|
||||
{
|
||||
if ( m_ConfigFilename.GetLength() == 0 )
|
||||
return NULL;
|
||||
|
||||
KeyValues *pKV = ::new KeyValues( "" );
|
||||
if ( !pKV->LoadFromFile( g_pFileSystem, m_ConfigFilename ) )
|
||||
{
|
||||
Error( "Error parsing %s.", m_ConfigFilename );
|
||||
}
|
||||
|
||||
|
||||
// Get values from the kv file.
|
||||
m_pSteamAppCfg = pKV->FindKey( "SteamApp.Cfg" );
|
||||
m_pSourceExeDir = pKV->GetString( "SourceExeDir", NULL );
|
||||
m_pSteamAppDir = pKV->GetString( "SteamAppDir", NULL );
|
||||
if ( !m_pSteamAppCfg || !m_pSourceExeDir || !m_pSteamAppDir )
|
||||
Error( "Missing one or more keys in the config file." );
|
||||
|
||||
// Steam base dir is the app dir but 3 slashes back.
|
||||
Q_strncpy( m_SteamBaseDir, m_pSteamAppDir, sizeof( m_SteamBaseDir ) );
|
||||
for ( int i=0; i < 3; i++ )
|
||||
{
|
||||
char *pSlash = strrchr( m_SteamBaseDir, '/' );
|
||||
if ( !pSlash )
|
||||
pSlash = strrchr( m_SteamBaseDir, '\\' );
|
||||
|
||||
if ( !pSlash )
|
||||
Error( "SteamAppDir %s invalid.", m_pSteamAppDir );
|
||||
else
|
||||
*pSlash = 0;
|
||||
}
|
||||
return pKV;
|
||||
}
|
||||
|
||||
|
||||
void CSteamDebugHelperDlg::OnSetupForDebugging()
|
||||
{
|
||||
char src[512], dest[512];
|
||||
KeyValues *pCur;
|
||||
KeyValues *pKV = LoadConfigFile();
|
||||
if ( !pKV )
|
||||
return;
|
||||
|
||||
HCURSOR hOldCursor = GetCursor();
|
||||
SetCursor( LoadCursor( AfxGetInstanceHandle(), IDC_WAIT ) );
|
||||
|
||||
// steam.dll
|
||||
Q_snprintf( src, sizeof( src ), "%s\\steam.dll", m_SteamBaseDir );
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\steam.dll", m_pSteamAppDir );
|
||||
CHECK_2STR( CopyFile( src, dest, false ), src, dest );
|
||||
|
||||
// steam.cfg
|
||||
Q_snprintf( src, sizeof( src ), "%s\\steam.cfg", m_SteamBaseDir );
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\steam.cfg", m_pSteamAppDir );
|
||||
CopyFile( src, dest, false );
|
||||
|
||||
// now build steamapp.cfg
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\SteamApp.cfg", m_pSteamAppDir );
|
||||
FILE *fp = fopen( dest, "wt" );
|
||||
CHECK( fp );
|
||||
for ( pCur=m_pSteamAppCfg->GetFirstValue(); pCur; pCur=pCur->GetNextValue() )
|
||||
{
|
||||
fprintf( fp, "%s\n", pCur->GetString() );
|
||||
}
|
||||
fprintf( fp, "SteamInstallPath=\"%s\"", m_SteamBaseDir );
|
||||
fclose( fp );
|
||||
|
||||
// Now copy each binary up there and make it read-only.
|
||||
for ( pCur=pKV->GetFirstValue(); pCur; pCur=pCur->GetNextValue() )
|
||||
{
|
||||
const char *pName = pCur->GetName();
|
||||
if ( Q_stricmp( pName, "binary" ) == 0 )
|
||||
{
|
||||
Q_snprintf( src, sizeof( src ), "%s\\%s", m_pSourceExeDir, pCur->GetString() );
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\%s", m_pSteamAppDir, pCur->GetString() );
|
||||
|
||||
if ( _access( dest, 0 ) == 0 )
|
||||
{
|
||||
CHECK_1STR( SetFileAttributes( dest, FILE_ATTRIBUTE_NORMAL ), dest );
|
||||
}
|
||||
|
||||
CHECK_2STR( CopyFile( src, dest, false ), src, dest );
|
||||
CHECK_1STR( SetFileAttributes( dest, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_READONLY ), dest );
|
||||
}
|
||||
}
|
||||
|
||||
SetCursor( hOldCursor );
|
||||
|
||||
MessageBox( "Setup successfully!", MB_OK );
|
||||
|
||||
//pKV->deleteThis(); // note: leak the memory here knowingly to avoid warnings from the stupid way keyvalues overload memory allocation
|
||||
}
|
||||
|
||||
void CSteamDebugHelperDlg::OnUnsetupForDebugging()
|
||||
{
|
||||
KeyValues *pKV = LoadConfigFile();
|
||||
|
||||
char dest[512];
|
||||
KeyValues *pCur;
|
||||
|
||||
// Delete the steamapp.cfg, steam.dll, and steam.cfg files.
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\steam.dll", m_pSteamAppDir );
|
||||
CHECK_1STR( SetFileAttributes( dest, FILE_ATTRIBUTE_NORMAL ), dest );
|
||||
CHECK_1STR( DeleteFile( dest ), dest );
|
||||
|
||||
// steam.cfg
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\steam.cfg", m_pSteamAppDir );
|
||||
SetFileAttributes( dest, FILE_ATTRIBUTE_NORMAL );
|
||||
DeleteFile( dest );
|
||||
|
||||
// steamapp.cfg
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\steamapp.cfg", m_pSteamAppDir );
|
||||
CHECK_1STR( SetFileAttributes( dest, FILE_ATTRIBUTE_NORMAL ), dest );
|
||||
CHECK_1STR( DeleteFile( dest ), dest );
|
||||
|
||||
for ( pCur=pKV->GetFirstValue(); pCur; pCur=pCur->GetNextValue() )
|
||||
{
|
||||
const char *pName = pCur->GetName();
|
||||
if ( Q_stricmp( pName, "binary" ) == 0 )
|
||||
{
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\%s", m_pSteamAppDir, pCur->GetString() );
|
||||
if ( _access( dest, 0 ) == 0 )
|
||||
{
|
||||
CHECK_1STR( SetFileAttributes( dest, FILE_ATTRIBUTE_NORMAL ), dest );
|
||||
|
||||
CHECK_1STR( DeleteFile( dest ), dest );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox( "Un-setup successfully!", MB_OK );
|
||||
|
||||
//pKV->deleteThis(); // note: leak the memory here knowingly to avoid warnings from the stupid way keyvalues overload memory allocation
|
||||
}
|
||||
|
||||
void CSteamDebugHelperDlg::OnStartSteam()
|
||||
{
|
||||
STARTUPINFO si;
|
||||
memset( &si, 0, sizeof( si ) );
|
||||
si.cb = sizeof( si );
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
char dest[512];
|
||||
Q_snprintf( dest, sizeof( dest ), "%s\\steam.exe", m_SteamBaseDir );
|
||||
CreateProcess(
|
||||
dest, // app name
|
||||
NULL, // command line
|
||||
NULL, // process attr
|
||||
NULL, // thread attr
|
||||
false, // inherit handles
|
||||
0, // flags
|
||||
NULL, // environment
|
||||
m_SteamBaseDir, // cur directory
|
||||
&si, // startup info
|
||||
&pi // process info
|
||||
);
|
||||
}
|
||||
|
||||
void CSteamDebugHelperDlg::OnEditConfigFile()
|
||||
{
|
||||
char str[512];
|
||||
Q_snprintf( str, sizeof( str ), "notepad \"%s\"", m_ConfigFilename );
|
||||
|
||||
STARTUPINFO si;
|
||||
memset( &si, 0, sizeof( si ) );
|
||||
si.cb = sizeof( si );
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
CreateProcess(
|
||||
NULL, // app name
|
||||
str, // command line
|
||||
NULL, // process attr
|
||||
NULL, // thread attr
|
||||
false, // inherit handles
|
||||
0, // flags
|
||||
NULL, // environment
|
||||
NULL, // cur directory
|
||||
&si, // startup info
|
||||
&pi // process info
|
||||
);
|
||||
}
|
||||
|
||||
void CSteamDebugHelperDlg::OnEditChooseConfigFile()
|
||||
{
|
||||
CFileDialog dlg(
|
||||
true,
|
||||
"cfg",
|
||||
NULL,
|
||||
0,
|
||||
"CFG Files (*.cfg)|*.cfg||",
|
||||
this );
|
||||
|
||||
if ( dlg.DoModal() == IDOK )
|
||||
{
|
||||
SetConfigFilename( dlg.GetPathName() );
|
||||
}
|
||||
}
|
||||
|
||||
void CSteamDebugHelperDlg::SetConfigFilename( const char *pName )
|
||||
{
|
||||
char absPath[MAX_PATH];
|
||||
MakeAbsolutePath( absPath, sizeof( absPath ), pName );
|
||||
|
||||
if ( _access( absPath, 0 ) == 0 )
|
||||
{
|
||||
m_ConfigFilename = absPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[512];
|
||||
Q_snprintf( str, sizeof( str ), "%s doesn't exist.", absPath );
|
||||
AfxMessageBox( str, MB_OK );
|
||||
return;
|
||||
}
|
||||
|
||||
m_ConfigFilename = absPath;
|
||||
|
||||
const char *pConfigFilename = absPath;
|
||||
const char *pTest1 = strrchr( pConfigFilename, '\\' ) + 1;
|
||||
const char *pTest2 = strrchr( pConfigFilename, '/' ) + 1;
|
||||
const char *pBaseName = max( pTest1, max( pTest2, pConfigFilename ) );
|
||||
SetWindowText( CString( "SteamDebugHelper - " ) + pBaseName );
|
||||
|
||||
::EnableWindow( ::GetDlgItem( m_hWnd, ID_EDIT_CONFIG_FILE ), true );
|
||||
::EnableWindow( ::GetDlgItem( m_hWnd, ID_SETUP_FOR_DEBUGGING ), true );
|
||||
::EnableWindow( ::GetDlgItem( m_hWnd, ID_UNSETUP_FOR_DEBUGGING ), true );
|
||||
}
|
||||
76
utils/SteamDebugHelper/SteamDebugHelperDlg.h
Normal file
76
utils/SteamDebugHelper/SteamDebugHelperDlg.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// SteamDebugHelperDlg.h : header file
|
||||
//
|
||||
|
||||
#if !defined(AFX_STEAMDEBUGHELPERDLG_H__E56B9648_8997_47D7_BEE1_CA0B572B380B__INCLUDED_)
|
||||
#define AFX_STEAMDEBUGHELPERDLG_H__E56B9648_8997_47D7_BEE1_CA0B572B380B__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "KeyValues.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSteamDebugHelperDlg dialog
|
||||
|
||||
class CSteamDebugHelperDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
CSteamDebugHelperDlg(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(CSteamDebugHelperDlg)
|
||||
enum { IDD = IDD_STEAMDEBUGHELPER_DIALOG };
|
||||
// NOTE: the ClassWizard will add data members here
|
||||
//}}AFX_DATA
|
||||
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(CSteamDebugHelperDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
void SetConfigFilename( const char *pName );
|
||||
|
||||
CString m_ConfigFilename;
|
||||
KeyValues* LoadConfigFile();
|
||||
|
||||
|
||||
// Extracted from the kv file.
|
||||
const char *m_pSourceExeDir;
|
||||
KeyValues *m_pSteamAppCfg;
|
||||
|
||||
const char *m_pSteamAppDir;
|
||||
char m_SteamBaseDir[512];
|
||||
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
HICON m_hIcon;
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(CSteamDebugHelperDlg)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnPaint();
|
||||
afx_msg HCURSOR OnQueryDragIcon();
|
||||
afx_msg void OnSetupForDebugging();
|
||||
afx_msg void OnUnsetupForDebugging();
|
||||
afx_msg void OnStartSteam();
|
||||
afx_msg void OnEditConfigFile();
|
||||
afx_msg void OnEditChooseConfigFile();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STEAMDEBUGHELPERDLG_H__E56B9648_8997_47D7_BEE1_CA0B572B380B__INCLUDED_)
|
||||
BIN
utils/SteamDebugHelper/res/SteamDebugHelper.ico
Normal file
BIN
utils/SteamDebugHelper/res/SteamDebugHelper.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
13
utils/SteamDebugHelper/res/SteamDebugHelper.rc2
Normal file
13
utils/SteamDebugHelper/res/SteamDebugHelper.rc2
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// STEAMDEBUGHELPER.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...
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
29
utils/SteamDebugHelper/resource.h
Normal file
29
utils/SteamDebugHelper/resource.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by SteamDebugHelper.rc
|
||||
//
|
||||
#define ID_UNSETUP_FOR_DEBUGGING 3
|
||||
#define IDD_STEAMDEBUGHELPER_DIALOG 102
|
||||
#define IDR_MAINFRAME 128
|
||||
#define ID_SETUP_FOR_DEBUGGING 1004
|
||||
#define ID_START_STEAM 1005
|
||||
#define ID_EDIT_CONFIG_FILE 1006
|
||||
#define ID_EDIT_CHOOSE_CONFIG_FILE 1007
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 129
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1005
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
35
utils/Texturesynth/texturesynth.vpc
Normal file
35
utils/Texturesynth/texturesynth.vpc
Normal file
@@ -0,0 +1,35 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// TEXTURESYNTH.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;..\common"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Texturesynth"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
-$File "$SRCDIR\public\tier0\memoverride.cpp"
|
||||
|
||||
$File "tsynth.cpp"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib bitmap
|
||||
$Lib mathlib
|
||||
$Lib tier2
|
||||
}
|
||||
}
|
||||
102
utils/Texturesynth/tsynth.cpp
Normal file
102
utils/Texturesynth/tsynth.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "bitmap/float_bm.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "tier2/tier2.h"
|
||||
#include "bitmap/tgaloader.h"
|
||||
|
||||
#define NEIGHBORHOOD_SIZE 5
|
||||
|
||||
void SynthesizeTexture(FloatBitMap_t & output, FloatBitMap_t const & input)
|
||||
{
|
||||
// init output with histogram-equalized random pixels
|
||||
output.InitializeWithRandomPixelsFromAnotherFloatBM(input);
|
||||
|
||||
// build image pyramids
|
||||
FloatImagePyramid_t input_pyramid(input,PYRAMID_MODE_GAUSSIAN);
|
||||
FloatImagePyramid_t output_pyramid(output,PYRAMID_MODE_GAUSSIAN);
|
||||
|
||||
// now, synthesize texture from lowest res to highest
|
||||
for(int level=min(input_pyramid.m_nLevels,output_pyramid.m_nLevels)-2;level>=0;level--)
|
||||
{
|
||||
FloatBitMap_t & output=*(output_pyramid.Level(level));
|
||||
FloatBitMap_t & output0=*(output_pyramid.Level(level+1));
|
||||
FloatBitMap_t & input=*(input_pyramid.Level(level));
|
||||
FloatBitMap_t & input0=*(input_pyramid.Level(level+1));
|
||||
if (
|
||||
(input.Width < NEIGHBORHOOD_SIZE*3) ||
|
||||
(input.Height < NEIGHBORHOOD_SIZE*3)
|
||||
)
|
||||
{
|
||||
printf("skip level %d\n",level);
|
||||
continue;
|
||||
}
|
||||
// now, synthesize each pixel
|
||||
for(int yloop=0;yloop<output.Height;yloop++)
|
||||
{
|
||||
int yo=((yloop+NEIGHBORHOOD_SIZE) % output.Height);
|
||||
printf("level %d line %d\n",level,yo);
|
||||
for(int xo=0;xo<output.Width;xo++)
|
||||
{
|
||||
int best_pixel_x=-1, best_pixel_y=-1;
|
||||
float best_error=1.0e22;
|
||||
// traverse all neighborhoods of src
|
||||
for(int nblk_y=NEIGHBORHOOD_SIZE;nblk_y<input.Height;nblk_y++)
|
||||
for(int nblk_x=NEIGHBORHOOD_SIZE;nblk_x<input.Width-NEIGHBORHOOD_SIZE;nblk_x++)
|
||||
{
|
||||
float our_error=0;
|
||||
// now, compare this block to the neighborhood around our output pixel
|
||||
for(int oy=-NEIGHBORHOOD_SIZE;oy<=0;oy++)
|
||||
{
|
||||
int xlimit=NEIGHBORHOOD_SIZE/2;
|
||||
if (oy==0)
|
||||
xlimit=-1; // on last line, don't step past our output pixel
|
||||
for(int ox=-NEIGHBORHOOD_SIZE/2;ox<=xlimit;ox++)
|
||||
for(int c=0;c<3;c++)
|
||||
{
|
||||
float pix_diff=
|
||||
output.PixelWrapped(xo+ox,yo+oy,c)-
|
||||
input.Pixel(nblk_x+ox,nblk_y+oy,c);
|
||||
our_error+=pix_diff*pix_diff;
|
||||
float pix_diff0=
|
||||
output0.PixelWrapped(xo+ox,yo+oy,c)-
|
||||
input0.PixelClamped(nblk_x+ox,nblk_y+oy,c);
|
||||
our_error+=pix_diff0*pix_diff0;
|
||||
}
|
||||
}
|
||||
if (our_error < best_error)
|
||||
{
|
||||
best_pixel_x=nblk_x;
|
||||
best_pixel_y=nblk_y;
|
||||
best_error=our_error;
|
||||
}
|
||||
}
|
||||
for(int c=0;c<3;c++)
|
||||
output.Pixel(xo,yo,c)=input.Pixel(best_pixel_x,best_pixel_y,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
output_pyramid.WriteTGAs("synth_out");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main(int argc,char **argv)
|
||||
{
|
||||
InitCommandLineProgram( argc, argv );
|
||||
FloatBitMap_t src_texture(argv[1]);
|
||||
|
||||
int out_width = atoi( argv[2] );
|
||||
int out_height = atoi( argv[3] );
|
||||
|
||||
|
||||
FloatBitMap_t output_map(out_width,out_height);
|
||||
|
||||
SynthesizeTexture(output_map,src_texture);
|
||||
|
||||
}
|
||||
674
utils/blackmarket/blackmarket.cpp
Normal file
674
utils/blackmarket/blackmarket.cpp
Normal file
@@ -0,0 +1,674 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// blackmarket.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <process.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include "interface.h"
|
||||
#include "imysqlwrapper.h"
|
||||
#include "mathlib.h"
|
||||
#include "filesystem.h"
|
||||
#include "filesystem_helpers.h"
|
||||
#include "tier2/tier2.h"
|
||||
#include "utlbuffer.h"
|
||||
|
||||
#include <ATLComTime.h>
|
||||
|
||||
const char *pDBName = "blackmarket_history";
|
||||
const char *pHostName = "gamestats";
|
||||
const char *pUserName = "root";
|
||||
const char *pPassword = "r77GH34p";
|
||||
|
||||
CSysModule *sql = NULL;
|
||||
CreateInterfaceFn factory = NULL;
|
||||
IMySQL *mysql = NULL;
|
||||
|
||||
enum CSWeaponID
|
||||
{
|
||||
WEAPON_NONE = 0,
|
||||
|
||||
WEAPON_P228,
|
||||
WEAPON_GLOCK,
|
||||
WEAPON_SCOUT,
|
||||
WEAPON_HEGRENADE,
|
||||
WEAPON_XM1014,
|
||||
WEAPON_C4,
|
||||
WEAPON_MAC10,
|
||||
WEAPON_AUG,
|
||||
WEAPON_SMOKEGRENADE,
|
||||
WEAPON_ELITE,
|
||||
WEAPON_FIVESEVEN,
|
||||
WEAPON_UMP45,
|
||||
WEAPON_SG550,
|
||||
|
||||
WEAPON_GALIL,
|
||||
WEAPON_FAMAS,
|
||||
WEAPON_USP,
|
||||
WEAPON_AWP,
|
||||
WEAPON_MP5NAVY,
|
||||
WEAPON_M249,
|
||||
WEAPON_M3,
|
||||
WEAPON_M4A1,
|
||||
WEAPON_TMP,
|
||||
WEAPON_G3SG1,
|
||||
WEAPON_FLASHBANG,
|
||||
WEAPON_DEAGLE,
|
||||
WEAPON_SG552,
|
||||
WEAPON_AK47,
|
||||
WEAPON_KNIFE,
|
||||
WEAPON_P90,
|
||||
|
||||
WEAPON_SHIELDGUN, // BOTPORT: Is this still needed?
|
||||
|
||||
WEAPON_KEVLAR,
|
||||
WEAPON_ASSAULTSUIT,
|
||||
WEAPON_NVG,
|
||||
|
||||
WEAPON_MAX, // number of weapons weapon index
|
||||
};
|
||||
|
||||
#define PRICE_BLOB_VERSION 1
|
||||
#define PRICE_BLOB_NAME "weeklyprices.dat"
|
||||
struct weeklyprice_t
|
||||
{
|
||||
short iVersion;
|
||||
short iPreviousPrice[WEAPON_MAX];
|
||||
short iCurrentPrice[WEAPON_MAX];
|
||||
};
|
||||
|
||||
int g_iCurrentWeaponPurchases[WEAPON_MAX];
|
||||
int g_iNewWeaponPrices[WEAPON_MAX];
|
||||
int g_iPriceDelta[WEAPON_MAX];
|
||||
int g_iPurchaseDelta[WEAPON_MAX];
|
||||
int g_iCounter = 0;
|
||||
int g_iResetCounter = 0;
|
||||
bool g_bWeeklyUpdate = false;
|
||||
|
||||
#define PRICE_SCALE 0.01f
|
||||
|
||||
struct weapons_t
|
||||
{
|
||||
int iWeaponType;
|
||||
int iDefaultPrice;
|
||||
int iID;
|
||||
int iPurchaseCount;
|
||||
int iCurrentPrice;
|
||||
};
|
||||
|
||||
#define WEAPON_NOTHING 0
|
||||
#define WEAPON_PISTOL 1
|
||||
#define WEAPON_EVERYTHING 2
|
||||
|
||||
static weapons_t g_Weapons[] =
|
||||
{
|
||||
{ WEAPON_NOTHING, 0, WEAPON_NONE, 0, 0, },
|
||||
{ WEAPON_PISTOL, 600, WEAPON_P228, 0, 0, },
|
||||
{ WEAPON_PISTOL, 400, WEAPON_GLOCK, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 2750, WEAPON_SCOUT, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 300, WEAPON_HEGRENADE, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 3000, WEAPON_XM1014, 0, 0, },
|
||||
{ WEAPON_NOTHING, 0, WEAPON_C4, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 1400, WEAPON_MAC10, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 3500, WEAPON_AUG, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 300, WEAPON_SMOKEGRENADE, 0, 0, },
|
||||
{ WEAPON_PISTOL, 800, WEAPON_ELITE, 0, 0, },
|
||||
{ WEAPON_PISTOL, 750, WEAPON_FIVESEVEN, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 1700, WEAPON_UMP45, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 4200, WEAPON_SG550, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 2000, WEAPON_GALIL, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 2250, WEAPON_FAMAS, 0, 0, },
|
||||
{ WEAPON_PISTOL, 500, WEAPON_USP, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 4750, WEAPON_AWP, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 1500, WEAPON_MP5NAVY, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 5750, WEAPON_M249, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 1700, WEAPON_M3, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 3100, WEAPON_M4A1, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 1250, WEAPON_TMP, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 5000, WEAPON_G3SG1, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 200, WEAPON_FLASHBANG, 0, 0, },
|
||||
{ WEAPON_PISTOL, 650, WEAPON_DEAGLE, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 3500, WEAPON_SG552, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 2500, WEAPON_AK47, 0, 0, },
|
||||
{ WEAPON_NOTHING, 0, WEAPON_KNIFE, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 2350, WEAPON_P90, 0, 0, },
|
||||
{ WEAPON_NOTHING, 0, WEAPON_SHIELDGUN, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 650, WEAPON_KEVLAR, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 1000, WEAPON_ASSAULTSUIT, 0, 0, },
|
||||
{ WEAPON_EVERYTHING, 1250, WEAPON_NVG, 0, 0, },
|
||||
};
|
||||
|
||||
const char * s_WeaponAliasInfo[] =
|
||||
{
|
||||
"none", // WEAPON_NONE
|
||||
"p228", // WEAPON_P228
|
||||
"glock", // WEAPON_GLOCK // old glock
|
||||
"scout", // WEAPON_SCOUT
|
||||
"hegren", // WEAPON_HEGRENADE
|
||||
"xm1014", // WEAPON_XM1014 // auto shotgun
|
||||
"c4", // WEAPON_C4
|
||||
"mac10", // WEAPON_MAC10 // T only
|
||||
"aug", // WEAPON_AUG
|
||||
"sgren", // WEAPON_SMOKEGRENADE
|
||||
"elite", // WEAPON_ELITE
|
||||
"fiveseven",// WEAPON_FIVESEVEN
|
||||
"ump45", // WEAPON_UMP45
|
||||
"sg550", // WEAPON_SG550 // auto-sniper
|
||||
"galil", // WEAPON_GALIL
|
||||
"famas", // WEAPON_FAMAS // CT cheap m4a1
|
||||
"usp", // WEAPON_USP
|
||||
"awp", // WEAPON_AWP
|
||||
"mp5navy", // WEAPON_MP5N
|
||||
"m249", // WEAPON_M249 // big machinegun
|
||||
"m3", // WEAPON_M3 // cheap shotgun
|
||||
"m4a1", // WEAPON_M4A1
|
||||
"tmp", // WEAPON_TMP
|
||||
"g3sg1", // WEAPON_G3SG1 // T auto-sniper
|
||||
"flash", // WEAPON_FLASHBANG
|
||||
"deagle", // WEAPON_DEAGLE
|
||||
"sg552", // WEAPON_SG552 // T aug equivalent
|
||||
"ak47", // WEAPON_AK47
|
||||
"knife", // WEAPON_KNIFE
|
||||
"p90", // WEAPON_P90
|
||||
"shield", // WEAPON_SHIELDGUN
|
||||
"kevlar",
|
||||
"kev+helm",
|
||||
"ngvision",
|
||||
NULL, // WEAPON_NONE
|
||||
};
|
||||
|
||||
|
||||
enum sorttype
|
||||
{
|
||||
SORT_PURCHASE = 0,
|
||||
SORT_NEWPRICE,
|
||||
SORT_PRICEDELTA,
|
||||
SORT_PERCENTCHANGE,
|
||||
};
|
||||
|
||||
void SortWeaponRanks( int iWeaponType, weapons_t *pWeaponsArray, int iSortType );
|
||||
|
||||
bool GetCurrentPurchaseCount( void )
|
||||
{
|
||||
if ( mysql->InitMySQL( "gamestats_cstrike", pHostName, pUserName, pPassword ) )
|
||||
{
|
||||
Msg( "Successfully connected to database %s on host %s, user %s\n", "gamestats_cstrike", pHostName, pUserName );
|
||||
|
||||
//Get purchase counts.
|
||||
mysql->Execute( "select * from weapons;" );
|
||||
|
||||
bool bFoundNext = mysql->SeekToFirstRow();
|
||||
int iIndex = WEAPON_P228;
|
||||
|
||||
while( bFoundNext && iIndex < WEAPON_MAX )
|
||||
{
|
||||
bFoundNext = mysql->NextRow();
|
||||
g_iCurrentWeaponPurchases[iIndex] = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "Count" ) );
|
||||
g_Weapons[iIndex].iPurchaseCount = g_iCurrentWeaponPurchases[iIndex];
|
||||
iIndex++;
|
||||
}
|
||||
|
||||
mysql->Execute( "select * from snapshot_counter;" );
|
||||
mysql->SeekToFirstRow();
|
||||
mysql->NextRow();
|
||||
|
||||
//Get snapshot counter.
|
||||
g_iCounter = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "counter" ) );
|
||||
|
||||
mysql->Execute( "select * from reset_counter;" );
|
||||
mysql->SeekToFirstRow();
|
||||
mysql->NextRow();
|
||||
|
||||
//Get reset snapshot counter.
|
||||
g_iResetCounter = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "counter" ) );
|
||||
|
||||
|
||||
|
||||
//Get current price and purchase count
|
||||
mysql->Execute( "select * from weapon_info;" );
|
||||
|
||||
bFoundNext = mysql->SeekToFirstRow();
|
||||
iIndex = WEAPON_P228;
|
||||
|
||||
while( bFoundNext && iIndex < WEAPON_MAX )
|
||||
{
|
||||
bFoundNext = mysql->NextRow();
|
||||
|
||||
int iWeaponID = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "WeaponID" ) );
|
||||
g_Weapons[iWeaponID].iCurrentPrice = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "current_price" ) );
|
||||
|
||||
if ( g_bWeeklyUpdate == true )
|
||||
{
|
||||
int iPreviousPurchases = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "purchases_thisweek" ) );
|
||||
g_Weapons[iWeaponID].iPurchaseCount = g_iPurchaseDelta[iWeaponID] = iPreviousPurchases;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iPreviousPurchases = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "purchases" ) );
|
||||
int iPurchasesThisWeek = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "purchases_thisweek" ) );
|
||||
|
||||
g_iPurchaseDelta[iWeaponID] = g_iCurrentWeaponPurchases[iWeaponID] - iPreviousPurchases;
|
||||
|
||||
g_Weapons[iWeaponID].iPurchaseCount = g_iPurchaseDelta[iWeaponID] + iPurchasesThisWeek;
|
||||
}
|
||||
|
||||
|
||||
iIndex++;
|
||||
}
|
||||
|
||||
|
||||
if ( g_bWeeklyUpdate == true )
|
||||
{
|
||||
iIndex = WEAPON_P228;
|
||||
|
||||
while( iIndex < WEAPON_MAX )
|
||||
{
|
||||
char szQueryString[512];
|
||||
|
||||
Q_snprintf( szQueryString, 512, "select * from purchases_pricing where snapshot=\"%d_%d\"", g_iCounter, iIndex );
|
||||
|
||||
//Get current price and purchase count
|
||||
mysql->Execute( szQueryString );
|
||||
mysql->SeekToFirstRow();
|
||||
mysql->NextRow();
|
||||
|
||||
g_iPurchaseDelta[iIndex] = mysql->GetColumnValue_Int( mysql->GetColumnIndex( "purchases" ) );
|
||||
|
||||
iIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Msg( "mysql->InitMySQL( %s, %s, %s, [password]) failed\n", "gamestats_cstrike", pHostName, pUserName );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetWeaponTypeCount( int iType )
|
||||
{
|
||||
int iCount = 0;
|
||||
|
||||
for ( int j = 0; j < WEAPON_MAX; j++ )
|
||||
{
|
||||
if ( g_Weapons[j].iWeaponType == iType )
|
||||
{
|
||||
iCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return iCount;
|
||||
}
|
||||
|
||||
weapons_t g_PistolRanks[6];
|
||||
weapons_t g_RifleAndEquipmentRanks[24];
|
||||
|
||||
void PrintNewPrices( void )
|
||||
{
|
||||
int iTotalPistols = 0;
|
||||
int iTotalRiflesEquipment = 0;
|
||||
int iTotalCurrentPistols = 0;
|
||||
int iTotalCurrentRiflesEquipment = 0;
|
||||
|
||||
for ( int j = 0; j < WEAPON_MAX; j++ )
|
||||
{
|
||||
//Msg( "%s - Default Price: %d - New Price: %d\n", s_WeaponAliasInfo[j], g_Weapons[j].iDefaultPrice, g_iNewWeaponPrices[j] );
|
||||
|
||||
if ( g_Weapons[j].iWeaponType == WEAPON_PISTOL )
|
||||
{
|
||||
iTotalPistols += g_Weapons[j].iCurrentPrice;
|
||||
iTotalCurrentPistols += g_iNewWeaponPrices[j];
|
||||
}
|
||||
else if ( g_Weapons[j].iWeaponType == WEAPON_EVERYTHING )
|
||||
{
|
||||
iTotalRiflesEquipment += g_Weapons[j].iCurrentPrice;
|
||||
iTotalCurrentRiflesEquipment += g_iNewWeaponPrices[j];
|
||||
}
|
||||
}
|
||||
|
||||
int iCount = GetWeaponTypeCount( WEAPON_PISTOL );
|
||||
|
||||
SortWeaponRanks( WEAPON_PISTOL, g_PistolRanks, SORT_PERCENTCHANGE );
|
||||
|
||||
Msg( "\n" );
|
||||
Msg( "Pistol Rankings:\n\n");
|
||||
|
||||
for ( int i = 0; i < iCount; i++ )
|
||||
{
|
||||
Msg( "#%d: %s \t\t| Purchases: %d \t| Current Price: %d \t| New Price: %d \t| Price Change: %d\n", i+1, s_WeaponAliasInfo[g_PistolRanks[i].iID], g_Weapons[g_PistolRanks[i].iID].iPurchaseCount, g_PistolRanks[i].iCurrentPrice, g_iNewWeaponPrices[g_PistolRanks[i].iID], g_iPriceDelta[g_PistolRanks[i].iID] );
|
||||
}
|
||||
|
||||
iCount = GetWeaponTypeCount( WEAPON_EVERYTHING );
|
||||
|
||||
SortWeaponRanks( WEAPON_EVERYTHING, g_RifleAndEquipmentRanks, SORT_PERCENTCHANGE );
|
||||
|
||||
Msg( "\n\n" );
|
||||
Msg( "Other Weapons and Equipment Rankings:\n\n");
|
||||
|
||||
for ( int i = 0; i < iCount; i++ )
|
||||
{
|
||||
Msg( "#%d: %s \t\t| Purchases: %d \t| Current Price: %d \t| New Price: %d \t| Price Change: %d\n", i+1, s_WeaponAliasInfo[g_RifleAndEquipmentRanks[i].iID], g_Weapons[g_RifleAndEquipmentRanks[i].iID].iPurchaseCount, g_RifleAndEquipmentRanks[i].iCurrentPrice, g_iNewWeaponPrices[g_RifleAndEquipmentRanks[i].iID], g_iPriceDelta[g_RifleAndEquipmentRanks[i].iID] );
|
||||
}
|
||||
|
||||
Msg( "\n" );
|
||||
Msg( "Total Pistol Baseline: %d\n", iTotalPistols );
|
||||
Msg( "Current Pistol Total: %d\n", iTotalCurrentPistols );
|
||||
Msg( "Total Rifles/Equipment Baseline: %d\n", iTotalRiflesEquipment );
|
||||
Msg( "Current Rifles/Equipment Total: %d\n", iTotalCurrentRiflesEquipment );
|
||||
|
||||
Msg( "\n" );
|
||||
}
|
||||
|
||||
float g_flTotalWeaponPurchasesPistols = 0;
|
||||
float g_flTotalWeaponPurchasesRifleEquipment = 0;
|
||||
float g_flTotalDollarsPistols = 1;
|
||||
float g_flTotalDollarsRifleEquipment = 1;
|
||||
|
||||
void SortWeaponRanks( int iWeaponType, weapons_t *pWeaponsArray, int iSortType )
|
||||
{
|
||||
int iCount = GetWeaponTypeCount( iWeaponType );
|
||||
|
||||
int iTotalPurchases = g_flTotalWeaponPurchasesPistols;
|
||||
|
||||
if ( iWeaponType == WEAPON_EVERYTHING )
|
||||
{
|
||||
iTotalPurchases = g_flTotalWeaponPurchasesRifleEquipment;
|
||||
}
|
||||
|
||||
bool bSorted = 1;
|
||||
|
||||
while ( bSorted )
|
||||
{
|
||||
bSorted = false;
|
||||
|
||||
for ( int i = 1; i < iCount; i++ )
|
||||
{
|
||||
float flSize1 = 0; // (pWeaponsArray[i].iPurchaseCount * PRICE_SCALE) * (pWeaponsArray[i].iCurrentPrice * PRICE_SCALE);
|
||||
float flSize2 = 0; //(pWeaponsArray[i-1].iPurchaseCount * PRICE_SCALE) * (pWeaponsArray[i-1].iCurrentPrice * PRICE_SCALE);
|
||||
|
||||
if ( iSortType == SORT_PURCHASE )
|
||||
{
|
||||
flSize1 = pWeaponsArray[i].iPurchaseCount;
|
||||
flSize2 = pWeaponsArray[i-1].iPurchaseCount;
|
||||
}
|
||||
else if ( iSortType == SORT_NEWPRICE )
|
||||
{
|
||||
flSize1 = g_iNewWeaponPrices[pWeaponsArray[i].iID];
|
||||
flSize2 = g_iNewWeaponPrices[pWeaponsArray[i-1].iID];
|
||||
}
|
||||
else if ( iSortType == SORT_PRICEDELTA )
|
||||
{
|
||||
flSize1 = g_iPriceDelta[pWeaponsArray[i].iID];
|
||||
flSize2 = g_iPriceDelta[pWeaponsArray[i-1].iID];
|
||||
}
|
||||
else if ( iSortType == SORT_PERCENTCHANGE )
|
||||
{
|
||||
flSize1 = (pWeaponsArray[i].iCurrentPrice / g_iNewWeaponPrices[pWeaponsArray[i].iID]) - 1;
|
||||
flSize2 = (pWeaponsArray[i-1].iCurrentPrice / g_iNewWeaponPrices[pWeaponsArray[i-1].iID]) - 1;
|
||||
}
|
||||
if ( flSize1 > flSize2 )
|
||||
{
|
||||
weapons_t temp = pWeaponsArray[i];
|
||||
pWeaponsArray[i] = pWeaponsArray[i-1];
|
||||
pWeaponsArray[i-1] = temp;
|
||||
bSorted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalculateNewPrices( weapons_t *pWeaponsArray, int iWeaponType )
|
||||
{
|
||||
int iTotalDollars = g_flTotalDollarsPistols;
|
||||
int iTotalPurchases = g_flTotalWeaponPurchasesPistols;
|
||||
int iTotalUp = 0;
|
||||
int iTotalDown = 0;
|
||||
|
||||
if ( iWeaponType == WEAPON_EVERYTHING )
|
||||
{
|
||||
iTotalDollars = g_flTotalDollarsRifleEquipment;
|
||||
iTotalPurchases = g_flTotalWeaponPurchasesRifleEquipment;
|
||||
}
|
||||
|
||||
SortWeaponRanks( iWeaponType, pWeaponsArray, SORT_PURCHASE );
|
||||
|
||||
int iCount = GetWeaponTypeCount( iWeaponType );
|
||||
float flPercentage = 0.0f;
|
||||
int iSign = 1;
|
||||
|
||||
for ( int i = 0; i < iCount; i++ )
|
||||
{
|
||||
float flDollarAmount = ((float)pWeaponsArray[i].iCurrentPrice * PRICE_SCALE) * ((float)pWeaponsArray[i].iPurchaseCount * PRICE_SCALE);
|
||||
float flTest = flDollarAmount / (float)iTotalDollars;
|
||||
float flTest2 = (float)pWeaponsArray[i].iPurchaseCount / (float)iTotalPurchases;
|
||||
|
||||
if ( iSign == 1 )
|
||||
{
|
||||
float flMod = (float)pWeaponsArray[i].iDefaultPrice / (float)pWeaponsArray[i].iCurrentPrice;
|
||||
|
||||
g_iNewWeaponPrices[pWeaponsArray[i].iID] = ceil( pWeaponsArray[i].iCurrentPrice + ( ( pWeaponsArray[i].iCurrentPrice * flTest2 ) * flMod ) );
|
||||
iTotalUp += iTotalDollars * flTest;
|
||||
}
|
||||
else
|
||||
{
|
||||
float flMod = (float)pWeaponsArray[i].iCurrentPrice / (float)pWeaponsArray[i].iDefaultPrice;
|
||||
|
||||
g_iNewWeaponPrices[pWeaponsArray[i].iID] = pWeaponsArray[i].iCurrentPrice - (( 1.0f / flTest2 ) * flMod );
|
||||
iTotalDown += iTotalDollars * flTest;
|
||||
}
|
||||
|
||||
if ( g_iNewWeaponPrices[pWeaponsArray[i].iID] <= 0 )
|
||||
{
|
||||
g_iNewWeaponPrices[pWeaponsArray[i].iID] = 1;
|
||||
}
|
||||
|
||||
g_iPriceDelta[pWeaponsArray[i].iID] = g_iNewWeaponPrices[pWeaponsArray[i].iID] - pWeaponsArray[i].iCurrentPrice;
|
||||
|
||||
flPercentage = flPercentage + flTest;
|
||||
|
||||
if ( flPercentage >= 0.5f )
|
||||
{
|
||||
iSign = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessBlackMarket( void )
|
||||
{
|
||||
int iPistol = 0;
|
||||
int iRifles = 0;
|
||||
|
||||
for ( int i = 1; i < WEAPON_MAX; i++ )
|
||||
{
|
||||
if ( g_Weapons[i].iWeaponType == WEAPON_PISTOL )
|
||||
{
|
||||
g_flTotalDollarsPistols += ( (float)g_Weapons[i].iCurrentPrice * PRICE_SCALE) * ( (float)g_Weapons[i].iPurchaseCount * PRICE_SCALE);
|
||||
g_flTotalWeaponPurchasesPistols += g_Weapons[i].iPurchaseCount;
|
||||
|
||||
g_PistolRanks[iPistol] = g_Weapons[i];
|
||||
g_PistolRanks[iPistol].iPurchaseCount = g_Weapons[i].iPurchaseCount; //g_iCurrentWeaponPurchases[i];
|
||||
iPistol++;
|
||||
}
|
||||
else if ( g_Weapons[i].iWeaponType == WEAPON_EVERYTHING )
|
||||
{
|
||||
g_flTotalDollarsRifleEquipment += ( (float)g_Weapons[i].iCurrentPrice * PRICE_SCALE ) * ( (float)g_Weapons[i].iPurchaseCount * PRICE_SCALE );
|
||||
g_flTotalWeaponPurchasesRifleEquipment += g_Weapons[i].iPurchaseCount;
|
||||
|
||||
g_RifleAndEquipmentRanks[iRifles] = g_Weapons[i];
|
||||
g_RifleAndEquipmentRanks[iRifles].iPurchaseCount = g_Weapons[i].iPurchaseCount; //g_iCurrentWeaponPurchases[i];
|
||||
iRifles++;
|
||||
}
|
||||
}
|
||||
|
||||
memset( g_iPriceDelta, 0, sizeof( g_iPriceDelta ) );
|
||||
|
||||
CalculateNewPrices( g_PistolRanks, WEAPON_PISTOL );
|
||||
CalculateNewPrices( g_RifleAndEquipmentRanks, WEAPON_EVERYTHING );
|
||||
}
|
||||
|
||||
|
||||
//=================================
|
||||
// Add the current snapshot to the db
|
||||
//=================================
|
||||
void AddSnapshotToDatabase( void )
|
||||
{
|
||||
char szSnapshot[1024];
|
||||
|
||||
//Only update the prices and close.
|
||||
if ( g_bWeeklyUpdate == true )
|
||||
{
|
||||
weeklyprice_t prices;
|
||||
CUtlBuffer buf;
|
||||
|
||||
prices.iVersion = PRICE_BLOB_VERSION;
|
||||
|
||||
for ( int i = 1; i < WEAPON_MAX; i ++ )
|
||||
{
|
||||
Q_snprintf( szSnapshot, sizeof( szSnapshot ), "update weapon_info set current_price=%d, purchases_thisweek=0 where WeaponID=%d", g_iNewWeaponPrices[i], i );
|
||||
|
||||
int retcode = mysql->Execute( szSnapshot );
|
||||
if ( retcode != 0 )
|
||||
{
|
||||
Msg( "Query:\n %s\n failed - Retcode: %d\n", szSnapshot, retcode );
|
||||
}
|
||||
|
||||
prices.iPreviousPrice[i] = g_Weapons[i].iCurrentPrice;
|
||||
prices.iCurrentPrice[i] = g_iNewWeaponPrices[i];
|
||||
}
|
||||
|
||||
|
||||
buf.Put( &prices, sizeof( weeklyprice_t ) );
|
||||
|
||||
if ( g_pFullFileSystem )
|
||||
{
|
||||
g_pFullFileSystem->WriteFile( PRICE_BLOB_NAME, NULL, buf );
|
||||
}
|
||||
|
||||
Q_snprintf( szSnapshot, sizeof( szSnapshot ), "update reset_counter set counter=counter+1" );
|
||||
|
||||
int retcode = mysql->Execute( szSnapshot );
|
||||
if ( retcode != 0 )
|
||||
{
|
||||
Msg( "Query:\n %s\n failed - Retcode: %d\n", szSnapshot, retcode );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
g_iCounter++;
|
||||
|
||||
for ( int i = 1; i < WEAPON_MAX; i ++ )
|
||||
{
|
||||
Q_snprintf( szSnapshot, sizeof( szSnapshot ), "Insert into purchases_pricing ( snapshot, dt2, weapon_id, purchases, current_price, projected_price, reset_counter ) values ( \"%d_%d\", NOW(), %d, %d, %d, %d, %d );",
|
||||
g_iCounter, i,
|
||||
i,
|
||||
g_iPurchaseDelta[i],
|
||||
g_Weapons[i].iCurrentPrice,
|
||||
g_iNewWeaponPrices[i],
|
||||
g_iResetCounter );
|
||||
|
||||
int retcode = mysql->Execute( szSnapshot );
|
||||
if ( retcode != 0 )
|
||||
{
|
||||
Msg( "Query:\n %s\n failed - Retcode: %d\n", szSnapshot, retcode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Q_snprintf( szSnapshot, sizeof( szSnapshot ), "update snapshot_counter set counter=%d", g_iCounter );
|
||||
|
||||
int retcode = mysql->Execute( szSnapshot );
|
||||
if ( retcode != 0 )
|
||||
{
|
||||
Msg( "Query:\n %s\n failed - Retcode: %d\n", szSnapshot, retcode );
|
||||
}
|
||||
|
||||
for ( int i = 1; i < WEAPON_MAX; i ++ )
|
||||
{
|
||||
Q_snprintf( szSnapshot, sizeof( szSnapshot ), "update weapon_info set purchases=%d, purchases_thisweek=purchases_thisweek+%d where WeaponID=%d", g_iCurrentWeaponPurchases[i], g_iPurchaseDelta[i], i );
|
||||
|
||||
int retcode = mysql->Execute( szSnapshot );
|
||||
if ( retcode != 0 )
|
||||
{
|
||||
Msg( "Query:\n %s\n failed - Retcode: %d\n", szSnapshot, retcode );
|
||||
}
|
||||
}
|
||||
|
||||
Msg( "Added new snapshot to database\n", szSnapshot, retcode );
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
bool bSnapShot = false;
|
||||
|
||||
InitDefaultFileSystem();
|
||||
|
||||
if ( argc > 1 )
|
||||
{
|
||||
for ( int i = 0; i < argc; i++ )
|
||||
{
|
||||
if ( Q_stricmp( "-snapshot", argv[i] ) == 0 )
|
||||
{
|
||||
bSnapShot = true;
|
||||
}
|
||||
|
||||
if( Q_stricmp( "-weeklyupdate", argv[i] ) == 0 )
|
||||
{
|
||||
g_bWeeklyUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now connect to steamweb and update the engineaccess table
|
||||
sql = Sys_LoadModule( "mysql_wrapper" );
|
||||
if ( sql )
|
||||
{
|
||||
factory = Sys_GetFactory( sql );
|
||||
if ( factory )
|
||||
{
|
||||
mysql = ( IMySQL * )factory( MYSQL_WRAPPER_VERSION_NAME, NULL );
|
||||
if ( mysql == NULL )
|
||||
{
|
||||
Msg( "Unable to get MYSQL_WRAPPER_VERSION_NAME(%s) from mysql_wrapper\n", MYSQL_WRAPPER_VERSION_NAME );
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "Sys_GetFactory on mysql_wrapper failed\n" );
|
||||
exit( -1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "Sys_LoadModule( mysql_wrapper ) failed\n" );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
if ( GetCurrentPurchaseCount() == false )
|
||||
exit( -1 );
|
||||
|
||||
ProcessBlackMarket();
|
||||
|
||||
if ( bSnapShot == true )
|
||||
{
|
||||
AddSnapshotToDatabase();
|
||||
}
|
||||
|
||||
PrintNewPrices();
|
||||
|
||||
if ( mysql )
|
||||
{
|
||||
mysql->Release();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
185
utils/blackmarket/blackmarket.vcproj
Normal file
185
utils/blackmarket/blackmarket.vcproj
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="blackmarket"
|
||||
ProjectGUID="{A7B7CC7B-FD61-4695-9521-FB8CE559A3A4}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../public/mathlib;../../utils/vmpi;../../public;../../public/tier1;../../game_shared;../../dlls"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="FALSE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/blackmarket_debug.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/blackmarket.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../public/mathlib;../../utils/vmpi;../../public;../../public/tier1;../../game_shared;../../dlls"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="4"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/blackmarket.exe"
|
||||
LinkIncremental="1"
|
||||
IgnoreAllDefaultLibraries="FALSE"
|
||||
IgnoreDefaultLibraryNames="LIBCMT"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\blackmarket.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\public\filesystem_helpers.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\public\filesystem_helpers.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\stdafx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\mathlib.lib">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\tier0.lib">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\tier1.lib">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\tier2.lib">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\lib\public\vstdlib.lib">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
9
utils/blackmarket/stdafx.cpp
Normal file
9
utils/blackmarket/stdafx.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// blackmarket.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
26
utils/blackmarket/stdafx.h
Normal file
26
utils/blackmarket/stdafx.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//========= Copyright 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__BC019BF6_D3B1_4EA1_AA0E_044EEC919C6D__INCLUDED_)
|
||||
#define AFX_STDAFX_H__BC019BF6_D3B1_4EA1_AA0E_044EEC919C6D__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__BC019BF6_D3B1_4EA1_AA0E_044EEC919C6D__INCLUDED_)
|
||||
112
utils/bsppack/bsppack.cpp
Normal file
112
utils/bsppack/bsppack.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "bsplib.h"
|
||||
#include "ibsppack.h"
|
||||
#include "cmdlib.h"
|
||||
#include "zip_utils.h"
|
||||
|
||||
class CBSPPack : public IBSPPack
|
||||
{
|
||||
public:
|
||||
void LoadBSPFile( IFileSystem *pFileSystem, char *filename );
|
||||
void WriteBSPFile( char *filename );
|
||||
void ClearPackFile( void );
|
||||
void AddFileToPack( const char *relativename, const char *fullpath );
|
||||
void AddBufferToPack( const char *relativename, void *data, int length, bool bTextMode );
|
||||
void SetHDRMode( bool bHDR );
|
||||
bool SwapBSPFile( IFileSystem *pFileSystem, const char *filename, const char *swapFilename, bool bSwapOnLoad, VTFConvertFunc_t pVTFConvertFunc, VHVFixupFunc_t pVHVFixupFunc, CompressFunc_t pCompressFunc );
|
||||
bool RepackBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, eRepackBSPFlags repackFlags );
|
||||
bool GetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, void **pPakData, int *pPakSize );
|
||||
bool SetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, const char *pNewFilename, void *pPakData, int pakSize );
|
||||
bool GetBSPDependants( IFileSystem *pFileSystem, const char *pBSPFilename, CUtlVector< CUtlString > *pList );
|
||||
};
|
||||
|
||||
void CBSPPack::LoadBSPFile( IFileSystem *pFileSystem, char *filename )
|
||||
{
|
||||
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
|
||||
|
||||
// This is shady, but the engine is the only client here and we want the same search paths it has.
|
||||
g_pFileSystem = g_pFullFileSystem = pFileSystem;
|
||||
|
||||
::LoadBSPFile( filename );
|
||||
}
|
||||
|
||||
void CBSPPack::WriteBSPFile( char *filename )
|
||||
{
|
||||
::WriteBSPFile( filename );
|
||||
}
|
||||
|
||||
void CBSPPack::ClearPackFile( void )
|
||||
{
|
||||
::ClearPakFile( GetPakFile() );
|
||||
}
|
||||
|
||||
void CBSPPack::AddFileToPack( const char *relativename, const char *fullpath )
|
||||
{
|
||||
// Compressing at this point would work, but the usual usage is creating a BSP and using RepackBSP() to apply lump
|
||||
// and pack compression as a final pass
|
||||
::AddFileToPak( GetPakFile(), relativename, fullpath, IZip::eCompressionType_None );
|
||||
}
|
||||
|
||||
void CBSPPack::AddBufferToPack( const char *relativename, void *data, int length, bool bTextMode )
|
||||
{
|
||||
// Compressing at this point would work, but the usual usage is creating a BSP and using RepackBSP() to apply lump
|
||||
// and pack compression as a final pass
|
||||
::AddBufferToPak( GetPakFile(), relativename, data, length, bTextMode, IZip::eCompressionType_None );
|
||||
}
|
||||
|
||||
void CBSPPack::SetHDRMode( bool bHDR )
|
||||
{
|
||||
::SetHDRMode( bHDR );
|
||||
}
|
||||
|
||||
bool CBSPPack::SwapBSPFile(
|
||||
IFileSystem *pFileSystem,
|
||||
const char *filename,
|
||||
const char *swapFilename,
|
||||
bool bSwapOnLoad,
|
||||
VTFConvertFunc_t pVTFConvertFunc,
|
||||
VHVFixupFunc_t pVHVFixupFunc,
|
||||
CompressFunc_t pCompressFunc )
|
||||
{
|
||||
// This is shady, but the engine is the only client here and we want the same search paths it has.
|
||||
g_pFileSystem = g_pFullFileSystem = pFileSystem;
|
||||
|
||||
return ::SwapBSPFile( filename, swapFilename, bSwapOnLoad, pVTFConvertFunc, pVHVFixupFunc, pCompressFunc );
|
||||
}
|
||||
|
||||
bool CBSPPack::RepackBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, eRepackBSPFlags repackFlags )
|
||||
{
|
||||
return ::RepackBSP( inputBuffer, outputBuffer,
|
||||
( repackFlags & eRepackBSP_CompressLumps ) ? RepackBSPCallback_LZMA : NULL,
|
||||
( repackFlags & eRepackBSP_CompressPackfile ) ? IZip::eCompressionType_LZMA : IZip::eCompressionType_None );
|
||||
}
|
||||
|
||||
bool CBSPPack::GetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, void **pPakData, int *pPakSize )
|
||||
{
|
||||
g_pFileSystem = g_pFullFileSystem = pFileSystem;
|
||||
|
||||
return ::GetPakFileLump( pBSPFilename, pPakData, pPakSize );
|
||||
}
|
||||
|
||||
bool CBSPPack::SetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, const char *pNewFilename, void *pPakData, int pakSize )
|
||||
{
|
||||
g_pFileSystem = g_pFullFileSystem = pFileSystem;
|
||||
|
||||
return ::SetPakFileLump( pBSPFilename, pNewFilename, pPakData, pakSize );
|
||||
}
|
||||
|
||||
bool CBSPPack::GetBSPDependants( IFileSystem *pFileSystem, const char *pBSPFilename, CUtlVector< CUtlString > *pList )
|
||||
{
|
||||
g_pFileSystem = g_pFullFileSystem = pFileSystem;
|
||||
|
||||
return ::GetBSPDependants( pBSPFilename, pList );
|
||||
}
|
||||
|
||||
EXPOSE_SINGLE_INTERFACE( CBSPPack, IBSPPack, IBSPPACK_VERSION_STRING );
|
||||
|
||||
57
utils/bsppack/bsppack.vpc
Normal file
57
utils/bsppack/bsppack.vpc
Normal file
@@ -0,0 +1,57 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// BSPPACK.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$PreprocessorDefinitions "$BASE;BSPPACK_EXPORTS;ZIP_SUPPORT_LZMA_ENCODE"
|
||||
$PreprocessorDefinitions "$BASE;WIN_ERROR;_USRDLL" [$WIN32]
|
||||
$PreprocessorDefinitions "$BASE;WIN_ERROR;_USRDLL;BSP_USE_LESS_MEMORY" [$X360]
|
||||
$AdditionalIncludeDirectories "..\common;$BASE"
|
||||
}
|
||||
$Linker
|
||||
{
|
||||
$SystemLibraries "iconv" [$OSXALL]
|
||||
}
|
||||
}
|
||||
|
||||
$Project "bsppack"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "..\common\bsplib.cpp"
|
||||
$File "bsppack.cpp"
|
||||
$File "..\common\cmdlib.cpp"
|
||||
$File "$SRCDIR\public\filesystem_helpers.cpp"
|
||||
$File "$SRCDIR\public\filesystem_helpers.h"
|
||||
$File "$SRCDIR\public\filesystem_init.cpp"
|
||||
$File "..\common\filesystem_tools.cpp"
|
||||
$File "..\common\filesystem_tools.h"
|
||||
$File "$SRCDIR\public\lumpfiles.cpp"
|
||||
$File "..\common\scriplib.cpp"
|
||||
$File "$SRCDIR\public\zip_utils.cpp"
|
||||
$File "$SRCDIR\filesystem\linux_support.cpp" [$POSIX]
|
||||
}
|
||||
|
||||
$Folder "Public Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\ibsppack.h"
|
||||
$File "$SRCDIR\public\bspfile.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib mathlib
|
||||
$Lib tier2
|
||||
$Lib "$LIBCOMMON/lzma"
|
||||
}
|
||||
}
|
||||
3
utils/bsppack/xbox/xbox.def
Normal file
3
utils/bsppack/xbox/xbox.def
Normal file
@@ -0,0 +1,3 @@
|
||||
LIBRARY bsppack_360.dll
|
||||
EXPORTS
|
||||
CreateInterface @1
|
||||
552
utils/bspzip/bspzip.cpp
Normal file
552
utils/bspzip/bspzip.cpp
Normal file
@@ -0,0 +1,552 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bsplib.h"
|
||||
#include "cmdlib.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "utlbuffer.h"
|
||||
|
||||
int CopyVariableLump( int lump, void **dest, int size );
|
||||
|
||||
void StripPath( const char* pPath, char* pBuf, int nBufLen )
|
||||
{
|
||||
const char *pSrc;
|
||||
|
||||
// want filename only
|
||||
pSrc = pPath + Q_strlen( pPath ) - 1;
|
||||
while ((pSrc != pPath) && (*(pSrc-1) != '\\') && (*(pSrc-1) != '/') && (*(pSrc-1) != ':'))
|
||||
pSrc--;
|
||||
|
||||
Q_strncpy( pBuf, pSrc, nBufLen );
|
||||
}
|
||||
|
||||
bool RepackBSP( const char *pszMapFile, bool bCompress )
|
||||
{
|
||||
Msg( "Repacking %s\n", pszMapFile );
|
||||
|
||||
if ( !g_pFullFileSystem->FileExists( pszMapFile ) )
|
||||
{
|
||||
Warning( "Couldn't open input file %s - BSP recompress failed\n", pszMapFile );
|
||||
return false;
|
||||
}
|
||||
|
||||
CUtlBuffer inputBuffer;
|
||||
if ( !g_pFullFileSystem->ReadFile( pszMapFile, NULL, inputBuffer ) )
|
||||
{
|
||||
Warning( "Couldn't read file %s - BSP compression failed\n", pszMapFile );
|
||||
return false;
|
||||
}
|
||||
|
||||
CUtlBuffer outputBuffer;
|
||||
|
||||
if ( !RepackBSP( inputBuffer, outputBuffer,
|
||||
bCompress ? RepackBSPCallback_LZMA : NULL,
|
||||
bCompress ? IZip::eCompressionType_LZMA : IZip::eCompressionType_None ) )
|
||||
{
|
||||
Warning( "Internal error compressing BSP\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pFullFileSystem->WriteFile( pszMapFile, NULL, outputBuffer );
|
||||
|
||||
Msg( "Successfully repacked %s -- %u -> %u bytes\n",
|
||||
pszMapFile, inputBuffer.TellPut(), outputBuffer.TellPut() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Usage( void )
|
||||
{
|
||||
fprintf( stderr, "usage: \n" );
|
||||
fprintf( stderr, "bspzip -extract <bspfile> <blah.zip>\n");
|
||||
fprintf( stderr, "bspzip -extractfiles <bspfile> <targetpath>\n");
|
||||
fprintf( stderr, "bspzip -dir <bspfile>\n");
|
||||
fprintf( stderr, "bspzip -addfile <bspfile> <relativepathname> <fullpathname> <newbspfile>\n");
|
||||
fprintf( stderr, "bspzip -addlist <bspfile> <listfile> <newbspfile>\n");
|
||||
fprintf( stderr, "bspzip -addorupdatelist <bspfile> <listfile> <newbspfile>\n");
|
||||
fprintf( stderr, "bspzip -extractcubemaps <bspfile> <targetPath>\n");
|
||||
fprintf( stderr, " Extracts the cubemaps to <targetPath>.\n");
|
||||
fprintf( stderr, "bspzip -deletecubemaps <bspfile>\n");
|
||||
fprintf( stderr, " Deletes the cubemaps from <bspFile>.\n");
|
||||
fprintf( stderr, "bspzip -addfiles <bspfile> <relativePathPrefix> <listfile> <newbspfile>\n");
|
||||
fprintf( stderr, " Adds files to <newbspfile>.\n");
|
||||
fprintf( stderr, "bspzip -repack [ -compress ] <bspfile>\n");
|
||||
fprintf( stderr, " Optimally repacks a BSP file, optionally using compressed BSP format.\n");
|
||||
fprintf( stderr, " Using on a compressed BSP without -compress will effectively decompress\n");
|
||||
fprintf( stderr, " a compressed BSP.\n");
|
||||
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
char* xzpFilename = NULL;
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
::SetHDRMode( false );
|
||||
|
||||
Msg( "\nValve Software - bspzip.exe (%s)\n", __DATE__ );
|
||||
|
||||
int curArg = 1;
|
||||
|
||||
// Options parsing assumes
|
||||
// [ -game foo ] -<action> <action specific args>
|
||||
|
||||
// Skip -game foo
|
||||
if ( argc >= curArg + 2 && stricmp( argv[curArg], "-game" ) == 0 )
|
||||
{
|
||||
// Handled by filesystem code
|
||||
curArg += 2;
|
||||
}
|
||||
|
||||
// Should have at least action
|
||||
if ( curArg >= argc )
|
||||
{
|
||||
// End of args
|
||||
Usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Pointers to the action, the file, and any action args so I can remove all the messy argc pointer math this was
|
||||
// using.
|
||||
char *pAction = argv[curArg];
|
||||
curArg++;
|
||||
char **pActionArgs = &argv[curArg];
|
||||
int nActionArgs = argc - curArg;
|
||||
|
||||
CommandLine()->CreateCmdLine( argc, argv );
|
||||
|
||||
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
|
||||
if( ( stricmp( pAction, "-extract" ) == 0 ) && nActionArgs == 2 )
|
||||
{
|
||||
// bspzip -extract <bspfile> <blah.zip>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension( bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
char zipName[MAX_PATH] = { 0 };
|
||||
V_strncpy( zipName, pActionArgs[1], sizeof( zipName ) );
|
||||
Q_DefaultExtension(zipName, ".zip", sizeof( zipName ) );
|
||||
|
||||
ExtractZipFileFromBSP( bspName, zipName );
|
||||
}
|
||||
else if( ( stricmp( pAction, "-extractfiles" ) == 0 ) && nActionArgs == 2 )
|
||||
{
|
||||
// bsipzip -extractfiles <bspfile> <targetpath>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
|
||||
// necessary for xbox process
|
||||
// only the .vtf are extracted as necessary for streaming and not the .vmt
|
||||
// the .vmt are non-streamed and therefore remain, referenced normally as part of the bsp search path
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension( bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
char targetPathName[MAX_PATH] = { 0 };
|
||||
V_strncpy( targetPathName, pActionArgs[1], sizeof( targetPathName ) );
|
||||
Q_AppendSlash( targetPathName, sizeof( targetPathName ) );
|
||||
|
||||
printf( "\n" );
|
||||
printf( "Opening bsp file: %s\n", bspName );
|
||||
LoadBSPFile( bspName );
|
||||
|
||||
CUtlBuffer buf;
|
||||
char relativeName[MAX_PATH] = { 0 };
|
||||
char targetName[MAX_PATH] = { 0 };
|
||||
int fileSize = 0;
|
||||
int id = -1;
|
||||
int numFilesExtracted = 0;
|
||||
while(true)
|
||||
{
|
||||
id = GetNextFilename( GetPakFile(), id, relativeName, sizeof(relativeName), fileSize );
|
||||
if ( id == -1)
|
||||
break;
|
||||
|
||||
{
|
||||
buf.EnsureCapacity( fileSize );
|
||||
buf.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
ReadFileFromPak( GetPakFile(), relativeName, false, buf );
|
||||
|
||||
V_strncpy( targetName, targetPathName, sizeof(targetName) );
|
||||
V_strncat( targetName, relativeName, sizeof(targetName) );
|
||||
Q_FixSlashes( targetName, '\\' );
|
||||
|
||||
SafeCreatePath( targetName );
|
||||
|
||||
printf( "Writing file: %s\n", targetName );
|
||||
FILE *fp = fopen( targetName, "wb" );
|
||||
if ( !fp )
|
||||
{
|
||||
printf( "Error: Could not write %s\n", targetName);
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
fwrite( buf.Base(), fileSize, 1, fp );
|
||||
fclose( fp );
|
||||
|
||||
numFilesExtracted++;
|
||||
}
|
||||
}
|
||||
printf( "%d files extracted.\n", numFilesExtracted );
|
||||
}
|
||||
else if( ( stricmp( pAction, "-extractcubemaps" ) == 0 ) && nActionArgs == 2 )
|
||||
{
|
||||
// bspzip -extractcubemaps <bspfile> <targetPath>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
// necessary for xbox process
|
||||
// only the .vtf are extracted as necessary for streaming and not the .vmt
|
||||
// the .vmt are non-streamed and therefore remain, referenced normally as part of the bsp search path
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension( bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
char targetPathName[MAX_PATH] = { 0 };
|
||||
V_strncpy( targetPathName, pActionArgs[1], sizeof(targetPathName) );
|
||||
Q_AppendSlash( targetPathName, sizeof( targetPathName ) );
|
||||
|
||||
printf( "\n" );
|
||||
printf( "Opening bsp file: %s\n", bspName );
|
||||
LoadBSPFile( bspName );
|
||||
|
||||
CUtlBuffer buf;
|
||||
char relativeName[MAX_PATH] = { 0 };
|
||||
char targetName[MAX_PATH] = { 0 };
|
||||
int fileSize = 0;
|
||||
int id = -1;
|
||||
int numFilesExtracted = 0;
|
||||
while (1)
|
||||
{
|
||||
id = GetNextFilename( GetPakFile(), id, relativeName, sizeof(relativeName), fileSize );
|
||||
if ( id == -1)
|
||||
break;
|
||||
|
||||
if ( Q_stristr( relativeName, ".vtf" ) )
|
||||
{
|
||||
buf.EnsureCapacity( fileSize );
|
||||
buf.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
ReadFileFromPak( GetPakFile(), relativeName, false, buf );
|
||||
|
||||
V_strncpy( targetName, targetPathName, sizeof( targetName ) );
|
||||
V_strncat( targetName, relativeName, sizeof( targetName ) );
|
||||
Q_FixSlashes( targetName, '\\' );
|
||||
|
||||
SafeCreatePath( targetName );
|
||||
|
||||
printf( "Writing vtf file: %s\n", targetName );
|
||||
FILE *fp = fopen( targetName, "wb" );
|
||||
if ( !fp )
|
||||
{
|
||||
printf( "Error: Could not write %s\n", targetName);
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
fwrite( buf.Base(), fileSize, 1, fp );
|
||||
fclose( fp );
|
||||
|
||||
numFilesExtracted++;
|
||||
}
|
||||
}
|
||||
printf( "%d cubemaps extracted.\n", numFilesExtracted );
|
||||
}
|
||||
else if( ( stricmp( pAction, "-deletecubemaps" ) == 0 ) && nActionArgs == 1 )
|
||||
{
|
||||
// bspzip -deletecubemaps <bspfile>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
// necessary for xbox process
|
||||
// the cubemaps are deleted as they cannot yet be streamed out of the bsp
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension( bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
printf( "\n" );
|
||||
printf( "Opening bsp file: %s\n", bspName );
|
||||
LoadBSPFile( bspName );
|
||||
|
||||
CUtlBuffer buf;
|
||||
char relativeName[MAX_PATH] = { 0 };
|
||||
int fileSize = 0;
|
||||
int id = -1;
|
||||
int numFilesDeleted = 0;
|
||||
while (1)
|
||||
{
|
||||
id = GetNextFilename( GetPakFile(), id, relativeName, sizeof(relativeName), fileSize );
|
||||
if ( id == -1)
|
||||
break;
|
||||
|
||||
if ( Q_stristr( relativeName, ".vtf" ) )
|
||||
{
|
||||
RemoveFileFromPak( GetPakFile(), relativeName );
|
||||
|
||||
numFilesDeleted++;
|
||||
|
||||
// start over
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf( "%d cubemaps deleted.\n", numFilesDeleted );
|
||||
if ( numFilesDeleted )
|
||||
{
|
||||
// save out bsp file
|
||||
printf( "Updating bsp file: %s\n", bspName );
|
||||
WriteBSPFile( bspName );
|
||||
}
|
||||
}
|
||||
else if( ( stricmp( pAction, "-addfiles" ) == 0 ) && nActionArgs == 4 )
|
||||
{
|
||||
// bspzip -addfiles <bspfile> <relativePathPrefix> <listfile> <newbspfile>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension( bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
char relativePrefixName[MAX_PATH] = { 0 };
|
||||
V_strncpy( relativePrefixName, pActionArgs[1], sizeof( relativePrefixName ) );
|
||||
|
||||
char filelistName[MAX_PATH] = { 0 };
|
||||
V_strncpy( filelistName, pActionArgs[2], sizeof( filelistName ) );
|
||||
|
||||
char newbspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( newbspName, sizeof( newbspName ), pActionArgs[3] );
|
||||
Q_DefaultExtension( newbspName, ".bsp", sizeof( newbspName) );
|
||||
|
||||
char fullpathName[MAX_PATH] = { 0 };
|
||||
FILE *fp = fopen(filelistName, "r");
|
||||
if ( fp )
|
||||
{
|
||||
printf("Opening bsp file: %s\n", bspName);
|
||||
LoadBSPFile(bspName);
|
||||
|
||||
while ( !feof(fp) )
|
||||
{
|
||||
if ( ( fgets( fullpathName, sizeof( fullpathName ), fp ) != NULL ) )
|
||||
{
|
||||
if ( *fullpathName && fullpathName[strlen(fullpathName) - 1] == '\n' )
|
||||
{
|
||||
fullpathName[strlen(fullpathName) - 1] = '\0';
|
||||
}
|
||||
|
||||
// strip the path and add relative prefix
|
||||
char fileName[MAX_PATH] = { 0 };
|
||||
char relativeName[MAX_PATH] = { 0 };
|
||||
StripPath( fullpathName, fileName, sizeof( fileName ) );
|
||||
V_strncpy( relativeName, relativePrefixName, sizeof( relativeName ) );
|
||||
V_strncat( relativeName, fileName, sizeof( relativeName ) );
|
||||
|
||||
printf( "Adding file: %s as %s\n", fullpathName, relativeName );
|
||||
|
||||
AddFileToPak( GetPakFile(), relativeName, fullpathName );
|
||||
}
|
||||
else if ( !feof( fp ) )
|
||||
{
|
||||
printf( "Error: Missing full path names\n");
|
||||
fclose( fp );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
printf("Writing new bsp file: %s\n", newbspName);
|
||||
WriteBSPFile(newbspName);
|
||||
fclose( fp );
|
||||
}
|
||||
}
|
||||
else if( ( stricmp( pAction, "-dir" ) == 0 ) && nActionArgs == 1 )
|
||||
{
|
||||
// bspzip -dir <bspfile>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension (bspName, ".bsp", sizeof( bspName ) );
|
||||
LoadBSPFile (bspName);
|
||||
PrintBSPPackDirectory();
|
||||
}
|
||||
else if( ( stricmp( pAction, "-addfile" ) == 0 ) && nActionArgs == 4 )
|
||||
{
|
||||
// bspzip -addfile <bspfile> <relativepathname> <fullpathname> <newbspfile>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension (bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
char relativeName[MAX_PATH] = { 0 };
|
||||
V_strncpy( relativeName, pActionArgs[1], sizeof( relativeName ) );
|
||||
|
||||
char fullpathName[MAX_PATH] = { 0 };
|
||||
V_strncpy( fullpathName, pActionArgs[2], sizeof( fullpathName ) );
|
||||
|
||||
char newbspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( newbspName, sizeof( newbspName ), pActionArgs[3] );
|
||||
Q_DefaultExtension (newbspName, ".bsp", sizeof( newbspName ) );
|
||||
|
||||
// read it in, add pack file, write it back out
|
||||
LoadBSPFile (bspName);
|
||||
AddFileToPak( GetPakFile(), relativeName, fullpathName );
|
||||
WriteBSPFile(newbspName);
|
||||
}
|
||||
else if( ( stricmp( pAction, "-addlist" ) == 0 ) && nActionArgs == 3 )
|
||||
{
|
||||
// bspzip -addlist <bspfile> <listfile> <newbspfile>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension (bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
char filelistName[MAX_PATH] = { 0 };
|
||||
V_strncpy( filelistName, pActionArgs[1], sizeof( filelistName ) );
|
||||
|
||||
char newbspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( newbspName, sizeof( newbspName ), pActionArgs[2] );
|
||||
Q_DefaultExtension (newbspName, ".bsp", sizeof( newbspName) );
|
||||
|
||||
// read it in, add pack file, write it back out
|
||||
|
||||
char relativeName[MAX_PATH] = { 0 };
|
||||
char fullpathName[MAX_PATH] = { 0 };
|
||||
FILE *fp = fopen(filelistName, "r");
|
||||
if ( fp )
|
||||
{
|
||||
printf("Opening bsp file: %s\n", bspName);
|
||||
LoadBSPFile (bspName);
|
||||
|
||||
while ( !feof(fp) )
|
||||
{
|
||||
relativeName[ 0 ] = 0;
|
||||
fullpathName[ 0 ] = 0;
|
||||
if ( ( fgets( relativeName, sizeof( relativeName ), fp ) != NULL ) &&
|
||||
( fgets( fullpathName, sizeof( fullpathName ), fp ) != NULL ) )
|
||||
{
|
||||
int l1 = strlen(relativeName);
|
||||
int l2 = strlen(fullpathName);
|
||||
if ( l1 > 0 )
|
||||
{
|
||||
if ( relativeName[ l1 - 1 ] == '\n' )
|
||||
{
|
||||
relativeName[ l1 - 1 ] = 0;
|
||||
}
|
||||
}
|
||||
if ( l2 > 0 )
|
||||
{
|
||||
if ( fullpathName[ l2 - 1 ] == '\n' )
|
||||
{
|
||||
fullpathName[ l2 - 1 ] = 0;
|
||||
}
|
||||
}
|
||||
printf("Adding file: %s\n", fullpathName);
|
||||
AddFileToPak( GetPakFile(), relativeName, fullpathName );
|
||||
}
|
||||
else if ( !feof( fp ) || ( relativeName[0] && !fullpathName[0] ) )
|
||||
{
|
||||
printf( "Error: Missing paired relative/full path names\n");
|
||||
fclose( fp );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
printf("Writing new bsp file: %s\n", newbspName);
|
||||
WriteBSPFile(newbspName);
|
||||
fclose( fp );
|
||||
}
|
||||
}
|
||||
else if( ( stricmp( pAction, "-addorupdatelist" ) == 0 ) && nActionArgs == 3 )
|
||||
{
|
||||
// bspzip -addorupdatelist <bspfile> <listfile> <newbspfile>
|
||||
CmdLib_InitFileSystem( pActionArgs[0] );
|
||||
char bspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( bspName, sizeof( bspName ), pActionArgs[0] );
|
||||
Q_DefaultExtension (bspName, ".bsp", sizeof( bspName ) );
|
||||
|
||||
char filelistName[MAX_PATH] = { 0 };
|
||||
V_strncpy( filelistName, pActionArgs[1], sizeof( filelistName ) );
|
||||
|
||||
char newbspName[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( newbspName, sizeof( newbspName ), pActionArgs[2] );
|
||||
Q_DefaultExtension (newbspName, ".bsp", sizeof( newbspName) );
|
||||
|
||||
// read it in, add pack file, write it back out
|
||||
|
||||
char relativeName[MAX_PATH] = { 0 };
|
||||
char fullpathName[MAX_PATH] = { 0 };
|
||||
FILE *fp = fopen(filelistName, "r");
|
||||
if ( fp )
|
||||
{
|
||||
printf("Opening bsp file: %s\n", bspName);
|
||||
LoadBSPFile (bspName);
|
||||
|
||||
while ( !feof(fp) )
|
||||
{
|
||||
relativeName[ 0 ] = 0;
|
||||
fullpathName[ 0 ] = 0;
|
||||
if ( ( fgets( relativeName, sizeof( relativeName ), fp ) != NULL ) &&
|
||||
( fgets( fullpathName, sizeof( fullpathName ), fp ) != NULL ) )
|
||||
{
|
||||
int l1 = strlen(relativeName);
|
||||
int l2 = strlen(fullpathName);
|
||||
if ( l1 > 0 )
|
||||
{
|
||||
if ( relativeName[ l1 - 1 ] == '\n' )
|
||||
{
|
||||
relativeName[ l1 - 1 ] = 0;
|
||||
}
|
||||
}
|
||||
if ( l2 > 0 )
|
||||
{
|
||||
if ( fullpathName[ l2 - 1 ] == '\n' )
|
||||
{
|
||||
fullpathName[ l2 - 1 ] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool bUpdating = FileExistsInPak( GetPakFile(), relativeName );
|
||||
printf("%s file: %s\n", bUpdating ? "Updating" : "Adding", fullpathName);
|
||||
if ( bUpdating )
|
||||
{
|
||||
RemoveFileFromPak( GetPakFile(), relativeName );
|
||||
}
|
||||
AddFileToPak( GetPakFile(), relativeName, fullpathName );
|
||||
}
|
||||
else if ( !feof( fp ) || ( relativeName[0] && !fullpathName[0] ) )
|
||||
{
|
||||
printf( "Error: Missing paired relative/full path names\n");
|
||||
fclose( fp );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
printf("Writing new bsp file: %s\n", newbspName);
|
||||
WriteBSPFile(newbspName);
|
||||
fclose( fp );
|
||||
}
|
||||
}
|
||||
else if( ( stricmp( pAction, "-repack" ) == 0 ) && ( nActionArgs == 1 || nActionArgs == 2 ) )
|
||||
{
|
||||
// bspzip -repack [ -compress ] <bspfile>
|
||||
bool bCompress = false;
|
||||
const char *pFile = pActionArgs[0];
|
||||
if ( nActionArgs == 2 && stricmp( pActionArgs[0], "-compress" ) == 0 )
|
||||
{
|
||||
pFile = pActionArgs[1];
|
||||
bCompress = true;
|
||||
}
|
||||
else if ( nActionArgs == 2 )
|
||||
{
|
||||
Usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CmdLib_InitFileSystem( pFile );
|
||||
char szAbsBSPPath[MAX_PATH] = { 0 };
|
||||
Q_MakeAbsolutePath( szAbsBSPPath, sizeof( szAbsBSPPath ), pFile );
|
||||
Q_DefaultExtension( szAbsBSPPath, ".bsp", sizeof( szAbsBSPPath ) );
|
||||
return RepackBSP( szAbsBSPPath, bCompress ) ? 0 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
56
utils/bspzip/bspzip.vpc
Normal file
56
utils/bspzip/bspzip.vpc
Normal file
@@ -0,0 +1,56 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// BSPZIP.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,..\common"
|
||||
$PreprocessorDefinitions "$BASE;ZIP_SUPPORT_LZMA_ENCODE"
|
||||
}
|
||||
|
||||
$Linker [$WIN32]
|
||||
{
|
||||
$EnableLargeAddresses "Support Addresses Larger Than 2 Gigabytes (/LARGEADDRESSAWARE)"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Bspzip"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "..\common\bsplib.cpp"
|
||||
$File "bspzip.cpp"
|
||||
$File "..\common\cmdlib.cpp"
|
||||
$File "$SRCDIR\public\filesystem_helpers.cpp"
|
||||
$File "$SRCDIR\public\filesystem_init.cpp"
|
||||
$File "..\common\filesystem_tools.cpp"
|
||||
$File "$SRCDIR\public\lumpfiles.cpp"
|
||||
$File "..\common\scriplib.cpp"
|
||||
$File "$SRCDIR\public\zip_utils.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\bspfile.h"
|
||||
$File "$SRCDIR\public\tier1\characterset.h"
|
||||
$File "$SRCDIR\public\filesystem_helpers.h"
|
||||
$File "..\common\filesystem_tools.h"
|
||||
$File "$SRCDIR\public\zip_utils.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib mathlib
|
||||
$Lib tier2
|
||||
$Lib "$LIBCOMMON/lzma"
|
||||
}
|
||||
}
|
||||
1180
utils/bugreporter/bugreporter.cpp
Normal file
1180
utils/bugreporter/bugreporter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
57
utils/bugreporter/bugreporter.vpc
Normal file
57
utils/bugreporter/bugreporter.vpc
Normal file
@@ -0,0 +1,57 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// BUGREPORTER.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,..\common"
|
||||
$PreprocessorDefinitions "$BASE;BUGREPORTER_EXPORTS"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Bugreporter"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "bugreporter.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\tier0\basetypes.h"
|
||||
$File "$SRCDIR\common\bugreporter\bugreporter.h"
|
||||
$File "$SRCDIR\public\Color.h"
|
||||
$File "$SRCDIR\public\tier0\commonmacros.h"
|
||||
$File "$SRCDIR\public\tier0\dbg.h"
|
||||
$File "$SRCDIR\public\tier0\fasttimer.h"
|
||||
$File "$SRCDIR\public\filesystem.h"
|
||||
$File "$SRCDIR\public\appframework\IAppSystem.h"
|
||||
$File "$SRCDIR\public\vstdlib\IKeyValuesSystem.h"
|
||||
$File "$SRCDIR\public\tier0\mem.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgoff.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgon.h"
|
||||
$File "$SRCDIR\public\tier0\platform.h"
|
||||
$File "$SRCDIR\public\tier0\protected_things.h"
|
||||
$File "$SRCDIR\public\string_t.h"
|
||||
$File "$SRCDIR\public\tier1\strtools.h"
|
||||
$File "trktool.h"
|
||||
$File "$SRCDIR\public\tier1\utlmemory.h"
|
||||
$File "$SRCDIR\public\tier1\utlrbtree.h"
|
||||
$File "$SRCDIR\public\vstdlib\vstdlib.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$File "$SRCDIR\lib\common\expdlln.lib"
|
||||
$File "$SRCDIR\lib\common\trktooln.lib"
|
||||
}
|
||||
}
|
||||
922
utils/bugreporter_filequeue/bugreporter.cpp
Normal file
922
utils/bugreporter_filequeue/bugreporter.cpp
Normal file
@@ -0,0 +1,922 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
//#define PROTECTED_THINGS_DISABLE
|
||||
#undef PROTECT_FILEIO_FUNCTIONS
|
||||
#undef fopen
|
||||
#include "winlite.h"
|
||||
#include <time.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#define _stat stat
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "basetypes.h"
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "utlsymbol.h"
|
||||
#include "utldict.h"
|
||||
#include "utlbuffer.h"
|
||||
#include "utlmap.h"
|
||||
|
||||
#include "bugreporter/bugreporter.h"
|
||||
#include "filesystem_tools.h"
|
||||
#include "KeyValues.h"
|
||||
#include "vstdlib/random.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define BUGSUB_CONFIG "\\\\bugbait\\bugsub\\config.txt"
|
||||
#else
|
||||
#ifdef OSX
|
||||
#define BUGSUB_CONFIG "/Volumes/bugsub/config.txt"
|
||||
#define BUGSUB_MOUNT "/Volumes/bugsub"
|
||||
#define BUGSUB_MOUNT_COMMAND "mount_smbfs //guest:@bugbait.valvesoftware.com/bugsub " BUGSUB_MOUNT
|
||||
#else
|
||||
// We can't do sudo here, so we rely on /etc/fstab being setup for '/mnt/bugsub'. See comment in CBugReporter::Init().
|
||||
#define BUGSUB_CONFIG "/mnt/bugsub/config.txt"
|
||||
#define BUGSUB_MOUNT "/mnt/bugsub"
|
||||
#define BUGSUB_MOUNT_COMMAND "mount /mnt/bugsub"
|
||||
#endif
|
||||
#define BUGSUB_UNMOUNT_COMMAND "umount " BUGSUB_MOUNT
|
||||
#endif
|
||||
|
||||
class CBugReporter *g_bugreporter = NULL;
|
||||
|
||||
class CBug
|
||||
{
|
||||
public:
|
||||
CBug()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Q_memset( title, 0, sizeof( title ) );
|
||||
Q_memset( desc, 0, sizeof( desc ) );
|
||||
Q_memset( submitter, 0, sizeof( submitter ) );
|
||||
Q_memset( owner, 0, sizeof( owner ) );
|
||||
Q_memset( severity, 0, sizeof( severity ) );
|
||||
Q_memset( priority, 0, sizeof( priority ) );
|
||||
Q_memset( area, 0, sizeof( area ) );
|
||||
Q_memset( mapnumber, 0, sizeof( mapnumber) );
|
||||
Q_memset( reporttype, 0, sizeof( reporttype ) );
|
||||
Q_memset( level, 0, sizeof( level ) );
|
||||
Q_memset( build, 0, sizeof( build ) );
|
||||
Q_memset( position, 0, sizeof( position ) );
|
||||
Q_memset( orientation, 0, sizeof( orientation ) );
|
||||
Q_memset( screenshot_unc, 0, sizeof( screenshot_unc ) );
|
||||
Q_memset( savegame_unc, 0, sizeof( savegame_unc ) );
|
||||
Q_memset( bsp_unc, 0, sizeof( bsp_unc ) );
|
||||
Q_memset( vmf_unc, 0, sizeof( vmf_unc ) );
|
||||
Q_memset( driverinfo, 0, sizeof( driverinfo ) );
|
||||
Q_memset( misc, 0, sizeof( misc ) );
|
||||
|
||||
includedfiles.Purge();
|
||||
}
|
||||
|
||||
char title[ 256 ];
|
||||
char desc[ 8192 ];
|
||||
char owner[ 256 ];
|
||||
char submitter[ 256 ];
|
||||
char severity[ 256 ];
|
||||
char priority[ 256 ];
|
||||
char area[ 256 ];
|
||||
char mapnumber[ 256 ];
|
||||
char reporttype[ 256 ];
|
||||
char level[ 256 ];
|
||||
char build[ 256 ];
|
||||
char position[ 256 ];
|
||||
char orientation[ 256 ];
|
||||
char screenshot_unc[ 256 ];
|
||||
char savegame_unc[ 256 ];
|
||||
char bsp_unc[ 256 ];
|
||||
char vmf_unc[ 256 ];
|
||||
char driverinfo[ 2048 ];
|
||||
char misc[ 1024 ];
|
||||
|
||||
struct incfile
|
||||
{
|
||||
char name[ 256 ];
|
||||
};
|
||||
|
||||
CUtlVector< incfile > includedfiles;
|
||||
};
|
||||
|
||||
class CBugReporter : public IBugReporter
|
||||
{
|
||||
public:
|
||||
|
||||
CBugReporter();
|
||||
virtual ~CBugReporter();
|
||||
|
||||
// Initialize and login with default username/password for this computer (from resource/bugreporter.res)
|
||||
virtual bool Init( CreateInterfaceFn engineFactory );
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual bool IsPublicUI() { return false; }
|
||||
|
||||
virtual char const *GetUserName();
|
||||
virtual char const *GetUserName_Display();
|
||||
|
||||
virtual int GetNameCount();
|
||||
virtual char const *GetName( int index );
|
||||
|
||||
virtual int GetDisplayNameCount();
|
||||
virtual char const *GetDisplayName( int index );
|
||||
virtual char const *GetUserNameForIndex( int index );
|
||||
|
||||
virtual char const *GetDisplayNameForUserName( char const *username );
|
||||
virtual char const *GetUserNameForDisplayName( char const *display );
|
||||
virtual char const *GetAreaMapForArea( char const * area);
|
||||
|
||||
virtual int GetSeverityCount();
|
||||
virtual char const *GetSeverity( int index );
|
||||
|
||||
virtual int GetPriorityCount();
|
||||
virtual char const *GetPriority( int index );
|
||||
|
||||
virtual int GetAreaCount();
|
||||
virtual char const *GetArea( int index );
|
||||
|
||||
virtual int GetAreaMapCount();
|
||||
virtual char const *GetAreaMap( int index );
|
||||
|
||||
virtual int GetMapNumberCount();
|
||||
virtual char const *GetMapNumber( int index );
|
||||
|
||||
virtual int GetReportTypeCount();
|
||||
virtual char const *GetReportType( int index );
|
||||
|
||||
virtual char const *GetRepositoryURL( void );
|
||||
virtual char const *GetSubmissionURL( void );
|
||||
|
||||
virtual int GetLevelCount(int area);
|
||||
virtual char const *GetLevel(int area, int index );
|
||||
|
||||
// Submission API
|
||||
virtual void StartNewBugReport();
|
||||
virtual void CancelNewBugReport();
|
||||
virtual bool CommitBugReport( int& bugSubmissionId );
|
||||
|
||||
virtual void SetTitle( char const *title );
|
||||
virtual void SetDescription( char const *description );
|
||||
|
||||
// NULL for current user
|
||||
virtual void SetSubmitter( char const *username = 0 );
|
||||
virtual void SetOwner( char const *username );
|
||||
virtual void SetSeverity( char const *severity );
|
||||
virtual void SetPriority( char const *priority );
|
||||
virtual void SetArea( char const *area );
|
||||
virtual void SetMapNumber ( char const *mapnumber );
|
||||
virtual void SetReportType( char const *reporttype );
|
||||
|
||||
virtual void SetLevel( char const *levelnamne );
|
||||
virtual void SetPosition( char const *position );
|
||||
virtual void SetOrientation( char const *pitch_yaw_roll );
|
||||
virtual void SetBuildNumber( char const *build_num );
|
||||
|
||||
virtual void SetScreenShot( char const *screenshot_unc_address );
|
||||
virtual void SetSaveGame( char const *savegame_unc_address );
|
||||
|
||||
virtual void SetBSPName( char const *bsp_unc_address );
|
||||
virtual void SetVMFName( char const *vmf_unc_address );
|
||||
|
||||
virtual void AddIncludedFile( char const *filename );
|
||||
virtual void ResetIncludedFiles();
|
||||
|
||||
virtual void SetZipAttachmentName( char const *zipfilename ) {} // only used by public bug reporter
|
||||
|
||||
virtual void SetDriverInfo( char const *info );
|
||||
|
||||
virtual void SetMiscInfo( char const *info );
|
||||
|
||||
// These are stubbed here, but are used by the public version...
|
||||
virtual void SetCSERAddress( const struct netadr_s& adr ) {}
|
||||
virtual void SetExeName( char const *exename ) {}
|
||||
virtual void SetGameDirectory( char const *pchGamedir ) {}
|
||||
virtual void SetRAM( int ram ) {}
|
||||
virtual void SetCPU( int cpu ) {}
|
||||
virtual void SetProcessor( char const *processor ) {}
|
||||
virtual void SetDXVersion( unsigned int high, unsigned int low, unsigned int vendor, unsigned int device ) {}
|
||||
virtual void SetOSVersion( char const *osversion ) {}
|
||||
virtual void SetSteamUserID( void *steamid, int idsize ) {};
|
||||
bool SymbolLessThan(const CUtlSymbol &sym1, const CUtlSymbol &sym2);
|
||||
|
||||
private:
|
||||
|
||||
bool PopulateLists();
|
||||
bool PopulateChoiceList( char const *listname, CUtlVector< CUtlSymbol >& list );
|
||||
|
||||
CUtlSymbolTable m_BugStrings;
|
||||
|
||||
CUtlVector< CUtlSymbol > m_Severity;
|
||||
CUtlVector< CUtlSymbol > m_SortedDisplayNames;
|
||||
CUtlVector< CUtlSymbol > m_SortedUserNames;
|
||||
CUtlVector< CUtlSymbol > m_Priority;
|
||||
CUtlVector< CUtlSymbol > m_Area;
|
||||
CUtlVector< CUtlSymbol > m_AreaMap;
|
||||
CUtlVector< CUtlSymbol > m_MapNumber;
|
||||
CUtlVector< CUtlSymbol > m_ReportType;
|
||||
CUtlMap<CUtlSymbol, CUtlVector< CUtlSymbol > *> m_LevelMap;
|
||||
|
||||
CUtlSymbol m_UserName;
|
||||
|
||||
CBug *m_pBug;
|
||||
|
||||
char m_BugRootDirectory[512];
|
||||
KeyValues *m_OptionsFile;
|
||||
|
||||
int m_CurrentBugID;
|
||||
char m_CurrentBugDirectory[512];
|
||||
bool m_bMountedBugSub;
|
||||
};
|
||||
|
||||
bool CUtlSymbol_LessThan(const CUtlSymbol &sym1, const CUtlSymbol &sym2)
|
||||
{
|
||||
return g_bugreporter->SymbolLessThan(sym1, sym2);
|
||||
}
|
||||
|
||||
CBugReporter::CBugReporter()
|
||||
{
|
||||
m_pBug = NULL;
|
||||
m_CurrentBugID = 0;
|
||||
m_bMountedBugSub = false;
|
||||
m_LevelMap.SetLessFunc(&CUtlSymbol_LessThan);
|
||||
g_bugreporter = this;
|
||||
}
|
||||
|
||||
CBugReporter::~CBugReporter()
|
||||
{
|
||||
m_BugStrings.RemoveAll();
|
||||
m_Severity.Purge();
|
||||
m_SortedDisplayNames.Purge();
|
||||
m_Priority.Purge();
|
||||
m_Area.Purge();
|
||||
m_MapNumber.Purge();
|
||||
m_ReportType.Purge();
|
||||
m_LevelMap.RemoveAll();
|
||||
|
||||
delete m_pBug;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Initialize and login with default username/password for this computer (from resource/bugreporter.res)
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBugReporter::Init( CreateInterfaceFn engineFactory )
|
||||
{
|
||||
// Load our bugreporter_text options file
|
||||
m_OptionsFile = new KeyValues( "OptionsFile" );
|
||||
|
||||
#ifdef POSIX
|
||||
// check if we can see the config file
|
||||
struct _stat mount_info;
|
||||
if (_stat(BUGSUB_CONFIG, &mount_info))
|
||||
{
|
||||
// if not we may need to mount bugbait
|
||||
if ( _stat(BUGSUB_MOUNT, &mount_info ) )
|
||||
{
|
||||
// make the mount dir if needed
|
||||
mkdir( BUGSUB_MOUNT, S_IRWXU | S_IRWXG | S_IRWXO );
|
||||
}
|
||||
|
||||
// now run the smbmount on it
|
||||
system( BUGSUB_MOUNT_COMMAND );
|
||||
|
||||
#ifdef LINUX
|
||||
if( _stat( BUGSUB_CONFIG, &mount_info ) )
|
||||
{
|
||||
Color clr( 255, 100, 50, 255 );
|
||||
|
||||
// The mount failed - probably because the /etc/fstab entry is missing?
|
||||
ConColorMsg( clr, "ERROR: failed to mount '" BUGSUB_MOUNT "' with '" BUGSUB_MOUNT_COMMAND "'.\n" );
|
||||
ConColorMsg( clr, "Bugsub not set up yet? Do 'sudo apt-get install smbfs', 'sudo mkdir /mnt/bugsub', and add this /etc/fstab:\n" );
|
||||
ConColorMsg( clr, " bugbait.valvesoftware.com/bugsub /mnt/bugsub smbfs rw,user,username=guest,password=,noauto 0 0\n" );
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_bMountedBugSub = true;
|
||||
}
|
||||
|
||||
#elif defined(WIN32)
|
||||
|
||||
#else
|
||||
#error "need to get to \\bugbait somehow"
|
||||
#endif
|
||||
|
||||
// open file old skool way to avoid steam filesystem restrictions
|
||||
struct _stat cfg_info;
|
||||
if (_stat(BUGSUB_CONFIG, &cfg_info)) {
|
||||
AssertMsg( 0, "Failed to find bugreporter options file." );
|
||||
return false;
|
||||
}
|
||||
|
||||
int buf_size = (cfg_info.st_size + 1);
|
||||
char *buf = new char[buf_size];
|
||||
FILE *fp = fopen(BUGSUB_CONFIG, "rb");
|
||||
if (!fp) {
|
||||
AssertMsg(0, "failed to open bugreporter options file" );
|
||||
delete [] buf;
|
||||
return false;
|
||||
}
|
||||
|
||||
fread(buf, cfg_info.st_size, 1, fp);
|
||||
fclose(fp);
|
||||
buf[cfg_info.st_size] = 0;
|
||||
if ( !m_OptionsFile->LoadFromBuffer(BUGSUB_CONFIG, buf) )
|
||||
{
|
||||
AssertMsg( 0, "Failed to load bugreporter_text options file." );
|
||||
delete [] buf;
|
||||
return false;
|
||||
}
|
||||
#ifdef WIN32
|
||||
V_strncpy( m_BugRootDirectory, m_OptionsFile->GetString( "bug_directory", "." ), sizeof(m_BugRootDirectory) );
|
||||
#elif defined(OSX)
|
||||
V_strncpy( m_BugRootDirectory, m_OptionsFile->GetString( "bug_directory_osx", BUGSUB_MOUNT ), sizeof(m_BugRootDirectory) );
|
||||
#elif defined(LINUX)
|
||||
V_strncpy( m_BugRootDirectory, m_OptionsFile->GetString( "bug_directory_linux", BUGSUB_MOUNT ), sizeof(m_BugRootDirectory) );
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
PopulateLists();
|
||||
|
||||
#ifdef WIN32
|
||||
m_UserName = m_BugStrings.AddString(getenv( "username" ));
|
||||
#elif POSIX
|
||||
m_UserName = m_BugStrings.AddString(getenv( "USER" ));
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
delete [] buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBugReporter::Shutdown()
|
||||
{
|
||||
#ifdef POSIX
|
||||
if ( m_bMountedBugSub )
|
||||
{
|
||||
system( BUGSUB_UNMOUNT_COMMAND );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserName()
|
||||
{
|
||||
return m_BugStrings.String( m_UserName );
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserName_Display()
|
||||
{
|
||||
return GetDisplayNameForUserName( GetUserName() );
|
||||
}
|
||||
|
||||
int CBugReporter::GetNameCount()
|
||||
{
|
||||
return GetDisplayNameCount();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetName( int index )
|
||||
{
|
||||
return GetDisplayName(index);
|
||||
}
|
||||
|
||||
int CBugReporter::GetDisplayNameCount()
|
||||
{
|
||||
return m_SortedDisplayNames.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetDisplayName( int index )
|
||||
{
|
||||
if ( index < 0 || index >= (int)m_SortedDisplayNames.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_SortedDisplayNames[ index ] );
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserNameForIndex( int index )
|
||||
{
|
||||
if ( index < 0 || index >= (int)m_SortedUserNames.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_SortedUserNames[ index ] );
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetDisplayNameForUserName( char const *username )
|
||||
{
|
||||
CUtlSymbol username_sym = m_BugStrings.Find(username);
|
||||
FOR_EACH_VEC(m_SortedUserNames, index) {
|
||||
if (m_SortedUserNames[index] == username_sym) {
|
||||
return GetDisplayName(index);
|
||||
}
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserNameForDisplayName( char const *display )
|
||||
{
|
||||
CUtlSymbol display_sym = m_BugStrings.Find(display);
|
||||
FOR_EACH_VEC(m_SortedDisplayNames, index) {
|
||||
if (m_SortedDisplayNames[index] == display_sym) {
|
||||
return GetUserNameForIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetAreaMapForArea( char const *area)
|
||||
{
|
||||
CUtlSymbol area_sym = m_BugStrings.Find(area);
|
||||
FOR_EACH_VEC(m_Area, index) {
|
||||
if (m_Area[index] == area_sym && index > 0) {
|
||||
char const *areamap = m_BugStrings.String(m_AreaMap[index-1]);
|
||||
return areamap+1;
|
||||
}
|
||||
}
|
||||
|
||||
return "<<Invalid>>";
|
||||
}
|
||||
|
||||
int CBugReporter::GetSeverityCount()
|
||||
{
|
||||
return m_Severity.Count() ;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetSeverity( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_Severity.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_Severity[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetPriorityCount()
|
||||
{
|
||||
return m_Priority.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetPriority( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_Priority.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_Priority[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetAreaCount()
|
||||
{
|
||||
return m_Area.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetArea( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_Area.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_Area[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetAreaMapCount()
|
||||
{
|
||||
return m_AreaMap.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetAreaMap( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_AreaMap.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_AreaMap[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetMapNumberCount()
|
||||
{
|
||||
return m_MapNumber.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetMapNumber( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_MapNumber.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_MapNumber[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetReportTypeCount()
|
||||
{
|
||||
return m_ReportType.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetReportType( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_ReportType.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_ReportType[ index ] );
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetRepositoryURL( void )
|
||||
{
|
||||
return m_BugRootDirectory;
|
||||
}
|
||||
|
||||
// only valid after calling CBugReporter::StartNewBugReport()
|
||||
char const *CBugReporter::GetSubmissionURL( void )
|
||||
{
|
||||
return m_CurrentBugDirectory;
|
||||
}
|
||||
|
||||
int CBugReporter::GetLevelCount(int area)
|
||||
{
|
||||
CUtlSymbol area_sym = m_AreaMap[area-1];
|
||||
int area_index = m_LevelMap.Find(area_sym);
|
||||
if (m_LevelMap.IsValidIndex(area_index))
|
||||
{
|
||||
CUtlVector<CUtlSymbol> *levels = m_LevelMap[area_index];
|
||||
return levels->Count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetLevel(int area, int index )
|
||||
{
|
||||
CUtlSymbol area_sym = m_AreaMap[area-1];
|
||||
int area_index = m_LevelMap.Find(area_sym);
|
||||
if (m_LevelMap.IsValidIndex(area_index))
|
||||
{
|
||||
CUtlVector<CUtlSymbol> *levels = m_LevelMap[area_index];
|
||||
if (index >= 0 && index < levels->Count())
|
||||
{
|
||||
return m_BugStrings.String((*levels)[index]);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CBugReporter::StartNewBugReport()
|
||||
{
|
||||
if ( !m_pBug )
|
||||
{
|
||||
m_pBug = new CBug();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBug->Clear();
|
||||
}
|
||||
|
||||
// Find the first available bug number by looking
|
||||
// for the next directory that doesn't exist.
|
||||
m_CurrentBugID = 0;
|
||||
struct tm t;
|
||||
|
||||
do
|
||||
{
|
||||
VCRHook_LocalTime( &t );
|
||||
|
||||
Q_snprintf(m_CurrentBugDirectory, sizeof(m_CurrentBugDirectory), "%s%c%04i%02i%02i-%02i%02i%02i-%s",
|
||||
m_BugRootDirectory,
|
||||
CORRECT_PATH_SEPARATOR,
|
||||
t.tm_year + 1900, t.tm_mon+1, t.tm_mday,
|
||||
t.tm_hour, t.tm_min, t.tm_sec,
|
||||
m_BugStrings.String(m_UserName));
|
||||
if (_access(m_CurrentBugDirectory, 0) != 0)
|
||||
break;
|
||||
|
||||
// sleep for a second or two then try again
|
||||
ThreadSleep(RandomInt(1000,2000));
|
||||
} while ( 1 );
|
||||
_mkdir(m_CurrentBugDirectory);
|
||||
}
|
||||
|
||||
void CBugReporter::CancelNewBugReport()
|
||||
{
|
||||
if ( !m_pBug )
|
||||
return;
|
||||
|
||||
m_pBug->Clear();
|
||||
m_CurrentBugID = 0;
|
||||
}
|
||||
|
||||
static void OutputField( CUtlBuffer &outbuf, char const *pFieldName, char const *pFieldValue )
|
||||
{
|
||||
if ( pFieldValue && pFieldValue[0] )
|
||||
{
|
||||
char const *pTmpString = V_AddBackSlashesToSpecialChars( pFieldValue );
|
||||
outbuf.Printf( "%s=\"%s\"\n", pFieldName, pTmpString );
|
||||
delete[] pTmpString;
|
||||
}
|
||||
}
|
||||
|
||||
bool CBugReporter::CommitBugReport( int& bugSubmissionId )
|
||||
{
|
||||
bugSubmissionId = m_CurrentBugID;
|
||||
|
||||
if ( !m_pBug )
|
||||
return false;
|
||||
|
||||
// Now create the bug descriptor file, and dump all the text keys in it
|
||||
CUtlBuffer buf(0, 0, CUtlBuffer::TEXT_BUFFER);
|
||||
|
||||
OutputField( buf, "Title", m_pBug->title );
|
||||
OutputField( buf, "Owner", m_pBug->owner );
|
||||
OutputField( buf, "Submitter", m_pBug->submitter );
|
||||
OutputField( buf, "Severity", m_pBug->severity );
|
||||
// OutputField( buf, "Type", m_pBug->reporttype );
|
||||
// OutputField( buf, "Priority", m_pBug->priority );
|
||||
OutputField( buf, "Area", m_pBug->area );
|
||||
OutputField( buf, "Level", m_pBug->mapnumber );
|
||||
OutputField( buf, "Description", m_pBug->desc );
|
||||
|
||||
//OutputField( buf, "Level", m_pBug->level );
|
||||
OutputField( buf, "Build", m_pBug->build );
|
||||
OutputField( buf, "Position", m_pBug->position );
|
||||
OutputField( buf, "Orientation", m_pBug->orientation );
|
||||
|
||||
OutputField( buf, "Screenshot", m_pBug->screenshot_unc );
|
||||
OutputField( buf, "Savegame", m_pBug->savegame_unc );
|
||||
OutputField( buf, "Bsp", m_pBug->bsp_unc );
|
||||
OutputField( buf, "vmf", m_pBug->vmf_unc );
|
||||
|
||||
// if ( m_pBug->includedfiles.Count() > 0 )
|
||||
// {
|
||||
// int c = m_pBug->includedfiles.Count();
|
||||
// for ( int i = 0 ; i < c; ++i )
|
||||
// {
|
||||
// buf.Printf( "include: %s\n", m_pBug->includedfiles[ i ].name );
|
||||
// }
|
||||
// }
|
||||
OutputField( buf, "DriverInfo", m_pBug->driverinfo );
|
||||
|
||||
OutputField( buf, "Misc", m_pBug->misc );
|
||||
|
||||
|
||||
// Write it out to the file
|
||||
// Need to use native calls to bypass steam filesystem
|
||||
char szBugFileName[1024];
|
||||
Q_snprintf(szBugFileName, sizeof(szBugFileName), "%s%cbug.txt", m_CurrentBugDirectory, CORRECT_PATH_SEPARATOR );
|
||||
FILE *fp = fopen(szBugFileName, "wb");
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
fprintf(fp, "%s", (char *)buf.Base());
|
||||
fclose(fp);
|
||||
|
||||
// Clear the bug
|
||||
m_pBug->Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBugReporter::SetTitle( char const *title )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->title, title, sizeof( m_pBug->title ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetDescription( char const *description )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->desc, description, sizeof( m_pBug->desc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSubmitter( char const *username /* = 0 */)
|
||||
{
|
||||
if ( !username )
|
||||
{
|
||||
username = GetUserName();
|
||||
}
|
||||
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->submitter, username, sizeof( m_pBug->submitter ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetOwner( char const *username )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->owner, username, sizeof( m_pBug->owner ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSeverity( char const *severity )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->severity, severity, sizeof( m_pBug->severity ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetPriority( char const *priority )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->priority, priority, sizeof( m_pBug->priority ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetArea( char const *area )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
char const *game = GetAreaMapForArea(area);
|
||||
Q_strncpy( m_pBug->area, game, sizeof( m_pBug->area ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetMapNumber( char const *mapnumber )
|
||||
{
|
||||
Assert( m_pBug);
|
||||
Q_strncpy( m_pBug->mapnumber, mapnumber, sizeof( m_pBug->mapnumber ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetReportType( char const *reporttype )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->reporttype, reporttype, sizeof( m_pBug->reporttype ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetLevel( char const *levelnamne )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->level, levelnamne, sizeof( m_pBug->level ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetDriverInfo( char const *info )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->driverinfo, info, sizeof( m_pBug->driverinfo ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetMiscInfo( char const *info )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->misc, info, sizeof( m_pBug->misc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetPosition( char const *position )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->position, position, sizeof( m_pBug->position ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetOrientation( char const *pitch_yaw_roll )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->orientation, pitch_yaw_roll, sizeof( m_pBug->orientation ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetBuildNumber( char const *build_num )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->build, build_num, sizeof( m_pBug->build ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetScreenShot( char const *screenshot_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->screenshot_unc, screenshot_unc_address, sizeof( m_pBug->screenshot_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSaveGame( char const *savegame_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->savegame_unc, savegame_unc_address, sizeof( m_pBug->savegame_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetBSPName( char const *bsp_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->bsp_unc, bsp_unc_address, sizeof( m_pBug->bsp_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetVMFName( char const *vmf_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->vmf_unc, vmf_unc_address, sizeof( m_pBug->vmf_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::AddIncludedFile( char const *filename )
|
||||
{
|
||||
CBug::incfile includedfile;
|
||||
Q_strncpy( includedfile.name, filename, sizeof( includedfile.name ) );
|
||||
m_pBug->includedfiles.AddToTail( includedfile );
|
||||
}
|
||||
|
||||
void CBugReporter::ResetIncludedFiles()
|
||||
{
|
||||
m_pBug->includedfiles.Purge();
|
||||
}
|
||||
|
||||
bool CBugReporter::PopulateChoiceList( char const *listname, CUtlVector< CUtlSymbol >& list )
|
||||
{
|
||||
// Read choice lists from text file
|
||||
KeyValues *pKV = m_OptionsFile->FindKey( listname );
|
||||
pKV = pKV->GetFirstSubKey();
|
||||
while ( pKV )
|
||||
{
|
||||
CUtlSymbol sym = m_BugStrings.AddString( pKV->GetName() );
|
||||
list.AddToTail( sym );
|
||||
|
||||
pKV = pKV->GetNextKey();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBugReporter::SymbolLessThan(const CUtlSymbol &sym1, const CUtlSymbol &sym2)
|
||||
{
|
||||
const char *string1 = m_BugStrings.String(sym1);
|
||||
const char *string2 = m_BugStrings.String(sym2);
|
||||
|
||||
return Q_stricmp(string1, string2) < 0;
|
||||
}
|
||||
|
||||
// owner, not required <<Unassigned>>
|
||||
// area <<None>>
|
||||
|
||||
bool CBugReporter::PopulateLists()
|
||||
{
|
||||
CUtlSymbol none = m_BugStrings.AddString( "<<None>>" );
|
||||
m_Area.AddToTail( none );
|
||||
|
||||
PopulateChoiceList( "Severity", m_Severity );
|
||||
|
||||
// Get developer names from text file
|
||||
KeyValues *pKV = m_OptionsFile->FindKey( "Names" );
|
||||
pKV = pKV->GetFirstSubKey();
|
||||
while ( pKV )
|
||||
{
|
||||
// Fill in lookup table
|
||||
CUtlSymbol display_name_sym = m_BugStrings.AddString( pKV->GetName() );
|
||||
CUtlSymbol user_name_sym = m_BugStrings.AddString( pKV->GetString() );
|
||||
m_SortedDisplayNames.AddToTail( display_name_sym );
|
||||
m_SortedUserNames.AddToTail( user_name_sym );
|
||||
pKV = pKV->GetNextKey();
|
||||
}
|
||||
|
||||
pKV = m_OptionsFile->FindKey( "Area" );
|
||||
pKV = pKV->GetFirstSubKey();
|
||||
while(pKV)
|
||||
{
|
||||
char const *area = pKV->GetName();
|
||||
char const *game = pKV->GetString();
|
||||
char areamap[256];
|
||||
Q_snprintf(areamap, sizeof(areamap), "@%s", game);
|
||||
CUtlSymbol area_sym = m_BugStrings.AddString(area);
|
||||
CUtlSymbol area_map_sym = m_BugStrings.AddString(areamap);
|
||||
m_Area.AddToTail( area_sym );
|
||||
m_AreaMap.AddToTail( area_map_sym );
|
||||
pKV = pKV->GetNextKey();
|
||||
}
|
||||
|
||||
pKV = m_OptionsFile->FindKey( "Level" );
|
||||
pKV = pKV->GetFirstSubKey();
|
||||
while(pKV)
|
||||
{
|
||||
char const *level = pKV->GetName();
|
||||
char const *area = pKV->GetString();
|
||||
char areamap[256];
|
||||
Q_snprintf(areamap, sizeof(areamap), "@%s", area);
|
||||
|
||||
CUtlSymbol level_sym = m_BugStrings.AddString(level);
|
||||
CUtlSymbol area_sym = m_BugStrings.Find(areamap);
|
||||
if (!area_sym.IsValid())
|
||||
{
|
||||
area_sym = m_BugStrings.AddString(areamap);
|
||||
}
|
||||
|
||||
unsigned index = m_LevelMap.Find(area_sym);
|
||||
CUtlVector<CUtlSymbol> *levels = 0;
|
||||
|
||||
if (m_LevelMap.IsValidIndex(index))
|
||||
{
|
||||
levels = m_LevelMap[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
levels = new CUtlVector<CUtlSymbol>;
|
||||
Assert(levels);
|
||||
m_LevelMap.Insert(area_sym, levels);
|
||||
}
|
||||
|
||||
if (level)
|
||||
{
|
||||
levels->AddToTail(level_sym);
|
||||
}
|
||||
|
||||
pKV = pKV->GetNextKey();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EXPOSE_SINGLE_INTERFACE( CBugReporter, IBugReporter, INTERFACEVERSION_BUGREPORTER );
|
||||
61
utils/bugreporter_filequeue/bugreporter_filequeue.vpc
Normal file
61
utils/bugreporter_filequeue/bugreporter_filequeue.vpc
Normal file
@@ -0,0 +1,61 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// BUGREPORTER_TEXT.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;..\common"
|
||||
$PreprocessorDefinitions "$BASE;BUGREPORTER_EXPORTS"
|
||||
}
|
||||
$Linker
|
||||
{
|
||||
$SystemLibraries "iconv" [$OSXALL]
|
||||
}
|
||||
}
|
||||
|
||||
$Project "bugreporter_filequeue"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "bugreporter.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\tier0\basetypes.h"
|
||||
$File "$SRCDIR\common\bugreporter\bugreporter.h"
|
||||
$File "$SRCDIR\public\Color.h"
|
||||
$File "$SRCDIR\public\tier0\commonmacros.h"
|
||||
$File "$SRCDIR\public\tier0\dbg.h"
|
||||
$File "$SRCDIR\public\tier0\fasttimer.h"
|
||||
$File "$SRCDIR\public\filesystem.h"
|
||||
$File "$SRCDIR\public\appframework\IAppSystem.h"
|
||||
$File "$SRCDIR\public\vstdlib\IKeyValuesSystem.h"
|
||||
$File "$SRCDIR\public\tier0\mem.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgoff.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgon.h"
|
||||
$File "$SRCDIR\public\tier0\platform.h"
|
||||
$File "$SRCDIR\public\tier0\protected_things.h"
|
||||
$File "$SRCDIR\public\string_t.h"
|
||||
$File "$SRCDIR\public\tier1\strtools.h"
|
||||
$File "..\bugreporter\trktool.h"
|
||||
$File "$SRCDIR\public\tier1\utlmemory.h"
|
||||
$File "$SRCDIR\public\tier1\utlrbtree.h"
|
||||
$File "$SRCDIR\public\vstdlib\vstdlib.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$File "$SRCDIR\lib\common\expdlln.lib" [$WIN32]
|
||||
$File "$SRCDIR\lib\common\trktooln.lib" [$WIN32]
|
||||
}
|
||||
}
|
||||
745
utils/bugreporter_public/bugreporter_public.cpp
Normal file
745
utils/bugreporter_public/bugreporter_public.cpp
Normal file
@@ -0,0 +1,745 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#define PROTECTED_THINGS_DISABLE
|
||||
#undef PROTECT_FILEIO_FUNCTIONS
|
||||
#undef fopen
|
||||
#include "winlite.h"
|
||||
#include "basetypes.h"
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "utlsymbol.h"
|
||||
#include "utldict.h"
|
||||
#include "utlbuffer.h"
|
||||
#include "steamcommon.h"
|
||||
|
||||
#include "bugreporter/bugreporter.h"
|
||||
#include "filesystem_tools.h"
|
||||
#include "KeyValues.h"
|
||||
#include "netadr.h"
|
||||
#include "steam/steamclientpublic.h"
|
||||
|
||||
bool UploadBugReport(
|
||||
const netadr_t& cserIP,
|
||||
const CSteamID& userid,
|
||||
int build,
|
||||
char const *title,
|
||||
char const *body,
|
||||
char const *exename,
|
||||
char const *gamedir,
|
||||
char const *mapname,
|
||||
char const *reporttype,
|
||||
char const *email,
|
||||
char const *accountname,
|
||||
int ram,
|
||||
int cpu,
|
||||
char const *processor,
|
||||
unsigned int high,
|
||||
unsigned int low,
|
||||
unsigned int vendor,
|
||||
unsigned int device,
|
||||
char const *osversion,
|
||||
char const *attachedfile,
|
||||
unsigned int attachedfilesize
|
||||
);
|
||||
|
||||
IBaseFileSystem *g_pFileSystem = NULL;
|
||||
|
||||
class CBug
|
||||
{
|
||||
public:
|
||||
CBug()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Q_memset( title, 0, sizeof( title ) );
|
||||
Q_memset( desc, 0, sizeof( desc ) );
|
||||
Q_memset( submitter, 0, sizeof( submitter ) );
|
||||
Q_memset( owner, 0, sizeof( owner ) );
|
||||
Q_memset( severity, 0, sizeof( severity ) );
|
||||
Q_memset( priority, 0, sizeof( priority ) );
|
||||
Q_memset( area, 0, sizeof( area ) );
|
||||
Q_memset( mapnumber, 0, sizeof( mapnumber) );
|
||||
Q_memset( reporttype, 0, sizeof( reporttype ) );
|
||||
Q_memset( level, 0, sizeof( level ) );
|
||||
Q_memset( build, 0, sizeof( build ) );
|
||||
Q_memset( position, 0, sizeof( position ) );
|
||||
Q_memset( orientation, 0, sizeof( orientation ) );
|
||||
Q_memset( screenshot_unc, 0, sizeof( screenshot_unc ) );
|
||||
Q_memset( savegame_unc, 0, sizeof( savegame_unc ) );
|
||||
Q_memset( bsp_unc, 0, sizeof( bsp_unc ) );
|
||||
Q_memset( vmf_unc, 0, sizeof( vmf_unc ) );
|
||||
Q_memset( driverinfo, 0, sizeof( driverinfo ) );
|
||||
Q_memset( misc, 0, sizeof( misc ) );
|
||||
Q_memset( zip, 0, sizeof( zip ) );
|
||||
|
||||
Q_memset( exename, 0, sizeof( exename ) );
|
||||
Q_memset( gamedir, 0, sizeof( gamedir ) );
|
||||
ram = 0;
|
||||
cpu = 0;
|
||||
Q_memset( processor, 0, sizeof( processor ) );
|
||||
dxversionhigh = 0;
|
||||
dxversionlow = 0;
|
||||
dxvendor = 0;
|
||||
dxdevice = 0;
|
||||
Q_memset( osversion, 0, sizeof( osversion ) );
|
||||
|
||||
includedfiles.Purge();
|
||||
}
|
||||
|
||||
char title[ 256 ];
|
||||
char desc[ 8192 ];
|
||||
char owner[ 256 ];
|
||||
char submitter[ 256 ];
|
||||
char severity[ 256 ];
|
||||
char priority[ 256 ];
|
||||
char area[ 256 ];
|
||||
char mapnumber[ 256 ];
|
||||
char reporttype[ 256 ];
|
||||
char level[ 256 ];
|
||||
char build[ 256 ];
|
||||
char position[ 256 ];
|
||||
char orientation[ 256 ];
|
||||
char screenshot_unc[ 256 ];
|
||||
char savegame_unc[ 256 ];
|
||||
char bsp_unc[ 256 ];
|
||||
char vmf_unc[ 256 ];
|
||||
char driverinfo[ 2048 ];
|
||||
char misc[ 1024 ];
|
||||
|
||||
char exename[ 256 ];
|
||||
char gamedir[ 256 ];
|
||||
unsigned int ram;
|
||||
unsigned int cpu;
|
||||
char processor[ 256 ];
|
||||
unsigned int dxversionhigh;
|
||||
unsigned int dxversionlow;
|
||||
unsigned int dxvendor;
|
||||
unsigned int dxdevice;
|
||||
char osversion[ 256 ];
|
||||
|
||||
char zip[ 256 ];
|
||||
|
||||
struct incfile
|
||||
{
|
||||
char name[ 256 ];
|
||||
};
|
||||
|
||||
CUtlVector< incfile > includedfiles;
|
||||
};
|
||||
|
||||
class CBugReporter : public IBugReporter
|
||||
{
|
||||
public:
|
||||
|
||||
CBugReporter();
|
||||
virtual ~CBugReporter();
|
||||
|
||||
// Initialize and login with default username/password for this computer (from resource/bugreporter.res)
|
||||
virtual bool Init( CreateInterfaceFn engineFactory );
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual bool IsPublicUI() { return true; }
|
||||
|
||||
virtual char const *GetUserName();
|
||||
virtual char const *GetUserName_Display();
|
||||
|
||||
virtual int GetNameCount();
|
||||
virtual char const *GetName( int index );
|
||||
|
||||
virtual int GetDisplayNameCount();
|
||||
virtual char const *GetDisplayName( int index );
|
||||
|
||||
virtual char const *GetDisplayNameForUserName( char const *username );
|
||||
virtual char const *GetUserNameForDisplayName( char const *display );
|
||||
|
||||
virtual int GetSeverityCount();
|
||||
virtual char const *GetSeverity( int index );
|
||||
|
||||
virtual int GetPriorityCount();
|
||||
virtual char const *GetPriority( int index );
|
||||
|
||||
virtual int GetAreaCount();
|
||||
virtual char const *GetArea( int index );
|
||||
|
||||
virtual int GetAreaMapCount();
|
||||
virtual char const *GetAreaMap( int index );
|
||||
|
||||
virtual int GetMapNumberCount();
|
||||
virtual char const *GetMapNumber( int index );
|
||||
|
||||
virtual int GetReportTypeCount();
|
||||
virtual char const *GetReportType( int index );
|
||||
|
||||
virtual char const *GetRepositoryURL( void ) { return NULL; }
|
||||
virtual char const *GetSubmissionURL( void ) { return NULL; }
|
||||
|
||||
virtual int GetLevelCount(int area) { return 0; }
|
||||
virtual char const *GetLevel(int area, int index ) { return ""; }
|
||||
|
||||
// Submission API
|
||||
virtual void StartNewBugReport();
|
||||
virtual void CancelNewBugReport();
|
||||
virtual bool CommitBugReport( int& bugSubmissionId );
|
||||
|
||||
virtual void SetTitle( char const *title );
|
||||
virtual void SetDescription( char const *description );
|
||||
|
||||
// NULL for current user
|
||||
virtual void SetSubmitter( char const *username = 0 );
|
||||
virtual void SetOwner( char const *username );
|
||||
virtual void SetSeverity( char const *severity );
|
||||
virtual void SetPriority( char const *priority );
|
||||
virtual void SetArea( char const *area );
|
||||
virtual void SetMapNumber ( char const *mapnumber );
|
||||
virtual void SetReportType( char const *reporttype );
|
||||
|
||||
virtual void SetLevel( char const *levelnamne );
|
||||
virtual void SetPosition( char const *position );
|
||||
virtual void SetOrientation( char const *pitch_yaw_roll );
|
||||
virtual void SetBuildNumber( char const *build_num );
|
||||
|
||||
virtual void SetScreenShot( char const *screenshot_unc_address );
|
||||
virtual void SetSaveGame( char const *savegame_unc_address );
|
||||
|
||||
virtual void SetBSPName( char const *bsp_unc_address );
|
||||
virtual void SetVMFName( char const *vmf_unc_address );
|
||||
|
||||
virtual void AddIncludedFile( char const *filename );
|
||||
virtual void ResetIncludedFiles();
|
||||
|
||||
virtual void SetDriverInfo( char const *info );
|
||||
|
||||
virtual void SetZipAttachmentName( char const *zipfilename );
|
||||
|
||||
virtual void SetMiscInfo( char const *info );
|
||||
|
||||
virtual void SetCSERAddress( const struct netadr_s& adr );
|
||||
virtual void SetExeName( char const *exename );
|
||||
virtual void SetGameDirectory( char const *gamedir );
|
||||
virtual void SetRAM( int ram );
|
||||
virtual void SetCPU( int cpu );
|
||||
virtual void SetProcessor( char const *processor );
|
||||
virtual void SetDXVersion( unsigned int high, unsigned int low, unsigned int vendor, unsigned int device );
|
||||
virtual void SetOSVersion( char const *osversion );
|
||||
virtual void SetSteamUserID( void *steamid, int idsize );
|
||||
|
||||
private:
|
||||
|
||||
void SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src );
|
||||
|
||||
CUtlSymbolTable m_BugStrings;
|
||||
|
||||
CUtlVector< CUtlSymbol > m_Severity;
|
||||
CUtlVector< CUtlSymbol > m_Area;
|
||||
CUtlVector< CUtlSymbol > m_MapNumber;
|
||||
CUtlVector< CUtlSymbol > m_ReportType;
|
||||
|
||||
CUtlSymbol m_UserName;
|
||||
|
||||
CBug *m_pBug;
|
||||
netadr_t m_cserIP;
|
||||
CSteamID m_SteamID;
|
||||
};
|
||||
|
||||
CBugReporter::CBugReporter()
|
||||
{
|
||||
Q_memset( &m_cserIP, 0, sizeof( m_cserIP ) );
|
||||
m_pBug = NULL;
|
||||
|
||||
m_Severity.AddToTail( m_BugStrings.AddString( "Zero" ) );
|
||||
m_Severity.AddToTail( m_BugStrings.AddString( "Low" ) );
|
||||
m_Severity.AddToTail( m_BugStrings.AddString( "Medium" ) );
|
||||
m_Severity.AddToTail( m_BugStrings.AddString( "High" ) );
|
||||
m_Severity.AddToTail( m_BugStrings.AddString( "Showstopper" ) );
|
||||
|
||||
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "<<Choose Item>>" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "Video / Display Problems" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "Network / Connectivity Problems" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "Download / Installation Problems" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "In-game Crash" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "Game play / Strategy Problems" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "Steam Problems" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "Unlisted Bug" ) );
|
||||
m_ReportType.AddToTail( m_BugStrings.AddString( "Feature Request / Suggestion" ) );
|
||||
}
|
||||
|
||||
CBugReporter::~CBugReporter()
|
||||
{
|
||||
m_BugStrings.RemoveAll();
|
||||
m_Severity.Purge();
|
||||
m_Area.Purge();
|
||||
m_MapNumber.Purge();
|
||||
m_ReportType.Purge();
|
||||
|
||||
delete m_pBug;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Initialize and login with default username/password for this computer (from resource/bugreporter.res)
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBugReporter::Init( CreateInterfaceFn engineFactory )
|
||||
{
|
||||
g_pFileSystem = (IFileSystem *)engineFactory( FILESYSTEM_INTERFACE_VERSION, NULL );
|
||||
if ( !g_pFileSystem )
|
||||
{
|
||||
AssertMsg( 0, "Failed to create/get IFileSystem" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBugReporter::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserName()
|
||||
{
|
||||
return m_UserName.String();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserName_Display()
|
||||
{
|
||||
return GetUserName();
|
||||
}
|
||||
|
||||
int CBugReporter::GetNameCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetName( int index )
|
||||
{
|
||||
if ( index < 0 || index >= 1 )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return GetUserName();
|
||||
}
|
||||
|
||||
int CBugReporter::GetDisplayNameCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetDisplayName( int index )
|
||||
{
|
||||
if ( index < 0 || index >= 1 )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return GetUserName();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetDisplayNameForUserName( char const *username )
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserNameForDisplayName( char const *display )
|
||||
{
|
||||
return display;
|
||||
}
|
||||
|
||||
int CBugReporter::GetSeverityCount()
|
||||
{
|
||||
return m_Severity.Count() ;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetSeverity( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_Severity.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_Severity[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetPriorityCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetPriority( int index )
|
||||
{
|
||||
return "<<Invalid>>";
|
||||
}
|
||||
|
||||
int CBugReporter::GetAreaCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetArea( int index )
|
||||
{
|
||||
return "<<Invalid>>";
|
||||
}
|
||||
|
||||
int CBugReporter::GetAreaMapCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetAreaMap( int index )
|
||||
{
|
||||
return "<<Invalid>>";
|
||||
}
|
||||
|
||||
int CBugReporter::GetMapNumberCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetMapNumber( int index )
|
||||
{
|
||||
return "<<Invalid>>";
|
||||
}
|
||||
|
||||
int CBugReporter::GetReportTypeCount()
|
||||
{
|
||||
return m_ReportType.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetReportType( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_ReportType.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_ReportType[ index ] );
|
||||
}
|
||||
|
||||
void CBugReporter::StartNewBugReport()
|
||||
{
|
||||
if ( !m_pBug )
|
||||
{
|
||||
m_pBug = new CBug();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBug->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CBugReporter::CancelNewBugReport()
|
||||
{
|
||||
if ( !m_pBug )
|
||||
return;
|
||||
|
||||
m_pBug->Clear();
|
||||
}
|
||||
|
||||
void CBugReporter::SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src )
|
||||
{
|
||||
out[ 0 ] = 0;
|
||||
|
||||
char *dest = out;
|
||||
|
||||
src.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
|
||||
char const *replace = "\\BugId\\";
|
||||
int replace_len = Q_strlen( replace );
|
||||
|
||||
for ( int pos = 0; pos <= src.TellPut() && ( ( dest - out ) < outlen ); )
|
||||
{
|
||||
char const *str = ( char const * )src.PeekGet( pos );
|
||||
if ( !Q_strnicmp( str, replace, replace_len ) )
|
||||
{
|
||||
*dest++ = '\\';
|
||||
|
||||
char num[ 32 ];
|
||||
Q_snprintf( num, sizeof( num ), "%i", bugid );
|
||||
char *pnum = num;
|
||||
while ( *pnum )
|
||||
{
|
||||
*dest++ = *pnum++;
|
||||
}
|
||||
|
||||
*dest++ = '\\';
|
||||
pos += replace_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
*dest++ = *str;
|
||||
++pos;
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
bool CBugReporter::CommitBugReport( int& bugSubmissionId )
|
||||
{
|
||||
bugSubmissionId = -1;
|
||||
|
||||
if ( !m_pBug )
|
||||
return false;
|
||||
|
||||
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
||||
|
||||
buf.Printf( "%s\n\n", m_pBug->desc );
|
||||
|
||||
buf.Printf( "level: %s\nbuild: %s\nposition: setpos %s; setang %s\n",
|
||||
m_pBug->level,
|
||||
m_pBug->build,
|
||||
m_pBug->position,
|
||||
m_pBug->orientation );
|
||||
|
||||
if ( m_pBug->screenshot_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "screenshot: %s\n", m_pBug->screenshot_unc );
|
||||
}
|
||||
if ( m_pBug->savegame_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "savegame: %s\n", m_pBug->savegame_unc );
|
||||
}
|
||||
/*
|
||||
if ( m_pBug->bsp_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "bsp: %s\n", m_pBug->bsp_unc );
|
||||
}
|
||||
if ( m_pBug->vmf_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "vmf: %s\n", m_pBug->vmf_unc );
|
||||
}
|
||||
if ( m_pBug->includedfiles.Count() > 0 )
|
||||
{
|
||||
int c = m_pBug->includedfiles.Count();
|
||||
for ( int i = 0 ; i < c; ++i )
|
||||
{
|
||||
buf.Printf( "include: %s\n", m_pBug->includedfiles[ i ].name );
|
||||
}
|
||||
}
|
||||
*/
|
||||
if ( m_pBug->driverinfo[ 0 ] )
|
||||
{
|
||||
buf.Printf( "%s\n", m_pBug->driverinfo );
|
||||
}
|
||||
if ( m_pBug->misc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "%s\n", m_pBug->misc );
|
||||
}
|
||||
|
||||
buf.PutChar( 0 );
|
||||
|
||||
// Store desc
|
||||
|
||||
int bugId = 0;
|
||||
|
||||
bugSubmissionId = (int)bugId;
|
||||
|
||||
int attachedfilesize = ( m_pBug->zip[ 0 ] == 0 ) ? 0 : g_pFileSystem->Size( m_pBug->zip );
|
||||
|
||||
if ( !UploadBugReport(
|
||||
m_cserIP,
|
||||
m_SteamID,
|
||||
atoi( m_pBug->build ),
|
||||
m_pBug->title,
|
||||
(char const *)buf.Base(),
|
||||
m_pBug->exename,
|
||||
m_pBug->gamedir,
|
||||
m_pBug->level,
|
||||
m_pBug->reporttype,
|
||||
m_pBug->owner,
|
||||
m_pBug->submitter,
|
||||
m_pBug->ram,
|
||||
m_pBug->cpu,
|
||||
m_pBug->processor,
|
||||
m_pBug->dxversionhigh,
|
||||
m_pBug->dxversionlow,
|
||||
m_pBug->dxvendor,
|
||||
m_pBug->dxdevice,
|
||||
m_pBug->osversion,
|
||||
m_pBug->zip,
|
||||
attachedfilesize
|
||||
) )
|
||||
{
|
||||
Msg( "Unable to upload bug...\n" );
|
||||
}
|
||||
|
||||
m_pBug->Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBugReporter::SetTitle( char const *title )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->title, title, sizeof( m_pBug->title ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetDescription( char const *description )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->desc, description, sizeof( m_pBug->desc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSubmitter( char const *username /*= 0*/ )
|
||||
{
|
||||
m_UserName = username;
|
||||
/*
|
||||
if ( !username )
|
||||
{
|
||||
username = GetUserName();
|
||||
}
|
||||
*/
|
||||
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->submitter, username ? username : "", sizeof( m_pBug->submitter ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetOwner( char const *username )
|
||||
{
|
||||
Q_strncpy( m_pBug->owner, username, sizeof( m_pBug->owner ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSeverity( char const *severity )
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::SetPriority( char const *priority )
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::SetArea( char const *area )
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::SetMapNumber( char const *mapnumber )
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::SetReportType( char const *reporttype )
|
||||
{
|
||||
Q_strncpy( m_pBug->reporttype, reporttype, sizeof( m_pBug->reporttype ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetLevel( char const *levelnamne )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->level, levelnamne, sizeof( m_pBug->level ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetDriverInfo( char const *info )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->driverinfo, info, sizeof( m_pBug->driverinfo ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetZipAttachmentName( char const *zipfilename )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
|
||||
Q_strncpy( m_pBug->zip, zipfilename, sizeof( m_pBug->zip ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetMiscInfo( char const *info )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->misc, info, sizeof( m_pBug->misc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetPosition( char const *position )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->position, position, sizeof( m_pBug->position ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetOrientation( char const *pitch_yaw_roll )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->orientation, pitch_yaw_roll, sizeof( m_pBug->orientation ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetBuildNumber( char const *build_num )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->build, build_num, sizeof( m_pBug->build ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetScreenShot( char const *screenshot_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->screenshot_unc, screenshot_unc_address, sizeof( m_pBug->screenshot_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSaveGame( char const *savegame_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->savegame_unc, savegame_unc_address, sizeof( m_pBug->savegame_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetBSPName( char const *bsp_unc_address )
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::SetVMFName( char const *vmf_unc_address )
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::AddIncludedFile( char const *filename )
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::ResetIncludedFiles()
|
||||
{
|
||||
}
|
||||
|
||||
void CBugReporter::SetExeName( char const *exename )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->exename, exename, sizeof( m_pBug->exename ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetGameDirectory( char const *pchGamedir )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
|
||||
Q_FileBase( pchGamedir, m_pBug->gamedir, sizeof( m_pBug->gamedir ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetRAM( int ram )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
m_pBug->ram = ram;
|
||||
}
|
||||
|
||||
void CBugReporter::SetCPU( int cpu )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
m_pBug->cpu = cpu;
|
||||
}
|
||||
|
||||
void CBugReporter::SetProcessor( char const *processor )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->processor, processor, sizeof( m_pBug->processor ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetDXVersion( unsigned int high, unsigned int low, unsigned int vendor, unsigned int device )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
m_pBug->dxversionhigh = high;
|
||||
m_pBug->dxversionlow = low;
|
||||
m_pBug->dxvendor = vendor;
|
||||
m_pBug->dxdevice = device;
|
||||
}
|
||||
|
||||
void CBugReporter::SetOSVersion( char const *osversion )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->osversion, osversion, sizeof( m_pBug->osversion ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetCSERAddress( const struct netadr_s& adr )
|
||||
{
|
||||
m_cserIP = adr;
|
||||
}
|
||||
|
||||
void CBugReporter::SetSteamUserID( void *steamid, int idsize )
|
||||
{
|
||||
Assert( idsize == sizeof( uint64 ) );
|
||||
m_SteamID.SetFromUint64( *((uint64*)steamid) );
|
||||
}
|
||||
|
||||
EXPOSE_SINGLE_INTERFACE( CBugReporter, IBugReporter, INTERFACEVERSION_BUGREPORTER );
|
||||
65
utils/bugreporter_public/bugreporter_public.vpc
Normal file
65
utils/bugreporter_public/bugreporter_public.vpc
Normal file
@@ -0,0 +1,65 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// BUGREPORTER_PUBLIC.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,..\common"
|
||||
$PreprocessorDefinitions "$BASE;bugreporter_public_EXPORTS"
|
||||
}
|
||||
|
||||
$Linker
|
||||
{
|
||||
$AdditionalDependencies "$BASE Ws2_32.lib odbc32.lib odbccp32.lib" [$WIN32]
|
||||
$SystemLibraries "iconv" [$OSXALL]
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Bugreporter_public"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "$SRCDIR\public\blockingudpsocket.cpp"
|
||||
$File "bugreporter_public.cpp"
|
||||
$File "bugreporter_upload.cpp"
|
||||
$File "$SRCDIR\public\mathlib\IceKey.H"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\tier0\basetypes.h"
|
||||
$File "$SRCDIR\public\blockingudpsocket.h"
|
||||
$File "$SRCDIR\public\Color.h"
|
||||
$File "$SRCDIR\public\tier0\commonmacros.h"
|
||||
$File "$SRCDIR\public\tier0\dbg.h"
|
||||
$File "$SRCDIR\public\tier0\fasttimer.h"
|
||||
$File "$SRCDIR\public\filesystem.h"
|
||||
$File "$SRCDIR\public\appframework\IAppSystem.h"
|
||||
$File "$SRCDIR\public\vstdlib\IKeyValuesSystem.h"
|
||||
$File "$SRCDIR\public\tier0\mem.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgoff.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgon.h"
|
||||
$File "$SRCDIR\public\tier0\platform.h"
|
||||
$File "$SRCDIR\public\tier0\protected_things.h"
|
||||
$File "$SRCDIR\public\string_t.h"
|
||||
$File "$SRCDIR\public\tier1\strtools.h"
|
||||
$File "$SRCDIR\public\tier1\utlmemory.h"
|
||||
$File "$SRCDIR\public\tier1\utlrbtree.h"
|
||||
$File "$SRCDIR\public\vstdlib\vstdlib.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib mathlib
|
||||
}
|
||||
|
||||
}
|
||||
969
utils/bugreporter_public/bugreporter_upload.cpp
Normal file
969
utils/bugreporter_public/bugreporter_upload.cpp
Normal file
@@ -0,0 +1,969 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "basetypes.h"
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
#elif defined(POSIX)
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#define closesocket close
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
#include "netadr.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "utlbuffer.h"
|
||||
#include "utlvector.h"
|
||||
#include "filesystem_tools.h"
|
||||
#include "cserserverprotocol_engine.h"
|
||||
#include "mathlib/IceKey.H"
|
||||
#include "bitbuf.h"
|
||||
#include "blockingudpsocket.h"
|
||||
#include "steamcommon.h"
|
||||
#include "steam/steamclientpublic.h"
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
|
||||
namespace BugReportHarvester
|
||||
{
|
||||
|
||||
enum EFileType
|
||||
{
|
||||
eFileTypeBugReport,
|
||||
|
||||
eFILETYPECOUNT // Count number of legal values
|
||||
};
|
||||
|
||||
|
||||
enum ESendMethod
|
||||
{
|
||||
eSendMethodWholeRawFileNoBlocks,
|
||||
eSendMethodCompressedBlocks, // TODO: Reenable compressed sending of minidumps
|
||||
|
||||
eSENDMETHODCOUNT // Count number of legal values
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using namespace BugReportHarvester;
|
||||
|
||||
// TODO: cut protocol version down to u8 if possible, to reduce bandwidth usage
|
||||
// for very frequent but tiny commands.
|
||||
typedef u32 ProtocolVersion_t;
|
||||
|
||||
typedef u8 ProtocolAcceptanceFlag_t;
|
||||
typedef u8 ProtocolUnacceptableAck_t;
|
||||
|
||||
typedef u32 MessageSequenceId_t;
|
||||
|
||||
typedef u32 ServerSessionHandle_t;
|
||||
typedef u32 ClientSessionHandle_t;
|
||||
|
||||
typedef u32 NetworkTransactionId_t;
|
||||
|
||||
// Command codes are intentionally as small as possible to minimize bandwidth usage
|
||||
// for very frequent but tiny commands (e.g. GDS 'FindServer' commands).
|
||||
typedef u8 Command_t;
|
||||
|
||||
// ... likewise response codes are as small as possible - we use this when we
|
||||
// ... can and revert to large types on a case by case basis.
|
||||
typedef u8 CommandResponse_t;
|
||||
|
||||
|
||||
// This define our standard type for length prefix for variable length messages
|
||||
// in wire protocols.
|
||||
// This is specifically used by CWSABUFWrapper::PrepareToReceiveLengthPrefixedMessage()
|
||||
// and its supporting functions.
|
||||
// It is defined here for generic (portable) network code to use when constructing
|
||||
// messages to be sent to peers that use the above function.
|
||||
// e.g. SteamValidateUserIDTickets.dll uses this for that purpose.
|
||||
|
||||
// We support u16 or u32 (obviously switching between them breaks existing protocols
|
||||
// unless all components are switched simultaneously).
|
||||
typedef u32 NetworkMessageLengthPrefix_t;
|
||||
|
||||
|
||||
// Similarly, strings should be preceeded by their length.
|
||||
typedef u16 StringLengthPrefix_t;
|
||||
|
||||
|
||||
const ProtocolAcceptanceFlag_t cuProtocolIsNotAcceptable
|
||||
= static_cast<ProtocolAcceptanceFlag_t>( 0 );
|
||||
|
||||
const ProtocolAcceptanceFlag_t cuProtocolIsAcceptable
|
||||
= static_cast<ProtocolAcceptanceFlag_t>( 1 );
|
||||
|
||||
const Command_t cuMaxCommand
|
||||
= static_cast<Command_t>(255);
|
||||
|
||||
const CommandResponse_t cuMaxCommandResponse
|
||||
= static_cast<CommandResponse_t>(255);
|
||||
|
||||
// This is for mapping requests back to error ids for placing into the database appropriately.
|
||||
typedef u32 ContextID_t;
|
||||
|
||||
// This is the version of the protocol used by latest-build clients.
|
||||
const ProtocolVersion_t cuCurrentProtocolVersion = 1;
|
||||
|
||||
// This is the minimum protocol version number that the client must
|
||||
// be able to speak in order to communicate with the server.
|
||||
// The client sends its protocol version this before every command, and if we
|
||||
// don't support that version anymore then we tell it nicely. The client
|
||||
// should respond by doing an auto-update.
|
||||
const ProtocolVersion_t cuRequiredProtocolVersion = 1;
|
||||
|
||||
|
||||
namespace Commands
|
||||
{
|
||||
const Command_t cuGracefulClose = 0;
|
||||
const Command_t cuSendBugReport = 1;
|
||||
const Command_t cuNumCommands = 2;
|
||||
const Command_t cuNoCommandReceivedYet = cuMaxCommand;
|
||||
}
|
||||
|
||||
|
||||
namespace HarvestFileCommand
|
||||
{
|
||||
typedef u32 SenderTypeId_t;
|
||||
typedef u32 SenderTypeUniqueId_t;
|
||||
typedef u32 SenderSourceCodeControlId_t;
|
||||
typedef u32 FileSize_t;
|
||||
|
||||
// Legal values defined by EFileType
|
||||
typedef u32 FileType_t;
|
||||
|
||||
// Legal values defined by ESendMethod
|
||||
typedef u32 SendMethod_t;
|
||||
|
||||
const CommandResponse_t cuOkToSendFile = 0;
|
||||
const CommandResponse_t cuFileTooBig = 1;
|
||||
const CommandResponse_t cuInvalidSendMethod = 2;
|
||||
const CommandResponse_t cuInvalidMaxCompressedChunkSize = 3;
|
||||
const CommandResponse_t cuInvalidBugReportContext = 4;
|
||||
const uint cuNumCommandResponses = 5;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
//
|
||||
// Class declaration: CWin32UploadBugReport
|
||||
//
|
||||
//#############################################################################
|
||||
//
|
||||
// Authors:
|
||||
//
|
||||
// Yahn Bernier
|
||||
//
|
||||
// Description and general notes:
|
||||
//
|
||||
// Handles uploading bug report data blobs to the CSERServer
|
||||
// (Client Stats & Error Reporting Server)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// General status
|
||||
eBugReportUploadSucceeded = 0,
|
||||
eBugReportUploadFailed,
|
||||
|
||||
// Specific status
|
||||
eBugReportBadParameter,
|
||||
eBugReportUnknownStatus,
|
||||
eBugReportSendingBugReportHeaderSucceeded,
|
||||
eBugReportSendingBugReportHeaderFailed,
|
||||
eBugReportReceivingResponseSucceeded,
|
||||
eBugReportReceivingResponseFailed,
|
||||
eBugReportConnectToCSERServerSucceeded,
|
||||
eBugReportConnectToCSERServerFailed,
|
||||
eBugReportUploadingBugReportSucceeded,
|
||||
eBugReportUploadingBugReportFailed
|
||||
} EBugReportUploadStatus;
|
||||
|
||||
struct TBugReportProgress
|
||||
{
|
||||
// A text string describing the current progress
|
||||
char m_sStatus[ 512 ];
|
||||
};
|
||||
|
||||
typedef void ( *BUGREPORTREPORTPROGRESSFUNC )( u32 uContext, const TBugReportProgress & rBugReportProgress );
|
||||
|
||||
static void BugUploadProgress( u32 uContext, const TBugReportProgress & rBugReportProgress )
|
||||
{
|
||||
// DevMsg( "%s\n", rBugReportProgress.m_sStatus );
|
||||
}
|
||||
|
||||
struct TBugReportParameters
|
||||
{
|
||||
// IP Address of the CSERServer to send the report to
|
||||
netadr_t m_ipCSERServer;
|
||||
|
||||
TSteamGlobalUserID m_userid;
|
||||
|
||||
// Source Control Id (or build_number) of the product
|
||||
u32 m_uEngineBuildNumber;
|
||||
// Name of the .exe
|
||||
char m_sExecutableName[ 64 ];
|
||||
// Game directory
|
||||
char m_sGameDirectory[ 64 ];
|
||||
// Map name the server wants to upload statistics about
|
||||
char m_sMapName[ 64 ];
|
||||
|
||||
u32 m_uRAM;
|
||||
u32 m_uCPU;
|
||||
|
||||
char m_sProcessor[ 128 ];
|
||||
|
||||
u32 m_uDXVersionHigh;
|
||||
u32 m_uDXVersionLow;
|
||||
u32 m_uDXVendorId;
|
||||
u32 m_uDXDeviceId;
|
||||
|
||||
char m_sOSVersion[ 64 ];
|
||||
|
||||
char m_sReportType[ 40 ];
|
||||
char m_sEmail[ 80 ];
|
||||
char m_sAccountName[ 64 ];
|
||||
|
||||
char m_sTitle[ 128 ];
|
||||
|
||||
char m_sBody[ 1024 ];
|
||||
|
||||
u32 m_uAttachmentFileSize;
|
||||
char m_sAttachmentFile[ 128 ];
|
||||
|
||||
u32 m_uProgressContext;
|
||||
BUGREPORTREPORTPROGRESSFUNC m_pOptionalProgressFunc;
|
||||
};
|
||||
|
||||
// Note that this API is blocking, though the callback, if passed, can occur during execution.
|
||||
EBugReportUploadStatus Win32UploadBugReportBlocking
|
||||
(
|
||||
const TBugReportParameters & rBugReportParameters // Input
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: encrypts an 8-byte sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void Encrypt8ByteSequence( IceKey& cipher, const unsigned char *plainText, unsigned char *cipherText)
|
||||
{
|
||||
cipher.encrypt(plainText, cipherText);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void EncryptBuffer( IceKey& cipher, unsigned char *bufData, uint bufferSize)
|
||||
{
|
||||
unsigned char *cipherText = bufData;
|
||||
unsigned char *plainText = bufData;
|
||||
uint bytesEncrypted = 0;
|
||||
|
||||
while (bytesEncrypted < bufferSize)
|
||||
{
|
||||
// encrypt 8 byte section
|
||||
Encrypt8ByteSequence( cipher, plainText, cipherText);
|
||||
bytesEncrypted += 8;
|
||||
cipherText += 8;
|
||||
plainText += 8;
|
||||
}
|
||||
}
|
||||
|
||||
bool UploadBugReport(
|
||||
const netadr_t& cserIP,
|
||||
const CSteamID &userid,
|
||||
int build,
|
||||
char const *title,
|
||||
char const *body,
|
||||
char const *exename,
|
||||
char const *pchGamedir,
|
||||
char const *mapname,
|
||||
char const *reporttype,
|
||||
char const *email,
|
||||
char const *accountname,
|
||||
int ram,
|
||||
int cpu,
|
||||
char const *processor,
|
||||
unsigned int high,
|
||||
unsigned int low,
|
||||
unsigned int vendor,
|
||||
unsigned int device,
|
||||
char const *osversion,
|
||||
char const *attachedfile,
|
||||
unsigned int attachedfilesize
|
||||
)
|
||||
{
|
||||
TBugReportParameters params;
|
||||
Q_memset( ¶ms, 0, sizeof( params ) );
|
||||
|
||||
params.m_ipCSERServer = cserIP;
|
||||
params.m_userid.m_SteamLocalUserID.As64bits = userid.ConvertToUint64();
|
||||
|
||||
params.m_uEngineBuildNumber = build;
|
||||
Q_strncpy( params.m_sExecutableName, exename, sizeof( params.m_sExecutableName ) );
|
||||
Q_strncpy( params.m_sGameDirectory, pchGamedir, sizeof( params.m_sGameDirectory ) );
|
||||
Q_strncpy( params.m_sMapName, mapname, sizeof( params.m_sMapName ) );
|
||||
|
||||
params.m_uRAM = ram;
|
||||
params.m_uCPU = cpu;
|
||||
|
||||
Q_strncpy( params.m_sProcessor, processor, sizeof( params.m_sProcessor) );
|
||||
|
||||
params.m_uDXVersionHigh = high;
|
||||
params.m_uDXVersionLow = low;
|
||||
params.m_uDXVendorId = vendor;
|
||||
params.m_uDXDeviceId = device;
|
||||
|
||||
Q_strncpy( params.m_sOSVersion, osversion, sizeof( params.m_sOSVersion ) );
|
||||
|
||||
Q_strncpy( params.m_sReportType, reporttype, sizeof( params.m_sReportType ) );
|
||||
Q_strncpy( params.m_sEmail, email, sizeof( params.m_sEmail ) );
|
||||
Q_strncpy( params.m_sAccountName, accountname, sizeof( params.m_sAccountName ) );
|
||||
|
||||
Q_strncpy( params.m_sTitle, title, sizeof( params.m_sTitle ) );
|
||||
Q_strncpy( params.m_sBody, body, sizeof( params.m_sBody ) );
|
||||
|
||||
Q_strncpy( params.m_sAttachmentFile, attachedfile, sizeof( params.m_sAttachmentFile ) );
|
||||
params.m_uAttachmentFileSize = attachedfilesize;
|
||||
|
||||
params.m_uProgressContext = 1u;
|
||||
params.m_pOptionalProgressFunc = BugUploadProgress;
|
||||
|
||||
EBugReportUploadStatus result = Win32UploadBugReportBlocking( params );
|
||||
return ( result == eBugReportUploadSucceeded ) ? true : false;
|
||||
|
||||
}
|
||||
|
||||
void UpdateProgress( const TBugReportParameters & params, char const *fmt, ... )
|
||||
{
|
||||
if ( !params.m_pOptionalProgressFunc )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char str[ 2048 ];
|
||||
va_list argptr;
|
||||
va_start( argptr, fmt );
|
||||
_vsnprintf( str, sizeof( str ) - 1, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
char outstr[ 2060 ];
|
||||
Q_snprintf( outstr, sizeof( outstr ), "(%u): %s", params.m_uProgressContext, str );
|
||||
|
||||
TBugReportProgress progress;
|
||||
Q_strncpy( progress.m_sStatus, outstr, sizeof( progress.m_sStatus ) );
|
||||
|
||||
// Invoke the callback
|
||||
( *params.m_pOptionalProgressFunc )( params.m_uProgressContext, progress );
|
||||
}
|
||||
|
||||
class CWin32UploadBugReport
|
||||
{
|
||||
public:
|
||||
explicit CWin32UploadBugReport(
|
||||
const netadr_t & harvester,
|
||||
const TBugReportParameters & rBugReportParameters,
|
||||
u32 contextid );
|
||||
~CWin32UploadBugReport();
|
||||
|
||||
EBugReportUploadStatus Upload( CUtlBuffer& buf );
|
||||
|
||||
private:
|
||||
|
||||
enum States
|
||||
{
|
||||
eCreateTCPSocket = 0,
|
||||
eConnectToHarvesterServer,
|
||||
eSendProtocolVersion,
|
||||
eReceiveProtocolOkay,
|
||||
eSendUploadCommand,
|
||||
eReceiveOKToSendFile,
|
||||
eSendWholeFile, // This could push chunks onto the wire, but we'll just use a whole buffer for now.
|
||||
eReceiveFileUploadSuccess,
|
||||
eSendGracefulClose,
|
||||
eCloseTCPSocket
|
||||
};
|
||||
|
||||
bool CreateTCPSocket( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool ConnectToHarvesterServer( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool SendProtocolVersion( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool ReceiveProtocolOkay( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool SendUploadCommand( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool ReceiveOKToSendFile( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool SendWholeFile( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool ReceiveFileUploadSuccess( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool SendGracefulClose( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
bool CloseTCPSocket( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
|
||||
typedef bool ( CWin32UploadBugReport::*pfnProtocolStateHandler )( EBugReportUploadStatus& status, CUtlBuffer& buf );
|
||||
struct FSMState_t
|
||||
{
|
||||
FSMState_t( uint f, pfnProtocolStateHandler s ) :
|
||||
first( f ),
|
||||
second( s )
|
||||
{
|
||||
}
|
||||
|
||||
uint first;
|
||||
pfnProtocolStateHandler second;
|
||||
};
|
||||
|
||||
void AddState( uint StateIndex, pfnProtocolStateHandler handler );
|
||||
void SetNextState( uint StateIndex );
|
||||
bool DoBlockingReceive( uint bytesExpected, CUtlBuffer& buf );
|
||||
|
||||
CUtlVector< FSMState_t > m_States;
|
||||
uint m_uCurrentState;
|
||||
struct sockaddr_in m_HarvesterSockAddr;
|
||||
uint m_SocketTCP;
|
||||
const TBugReportParameters &m_rBugReportParameters; //lint !e1725
|
||||
u32 m_ContextID;
|
||||
};
|
||||
|
||||
CWin32UploadBugReport::CWin32UploadBugReport(
|
||||
const netadr_t & harvester,
|
||||
const TBugReportParameters & rBugReportParameters,
|
||||
u32 contextid ) :
|
||||
m_States(),
|
||||
m_uCurrentState( eCreateTCPSocket ),
|
||||
m_HarvesterSockAddr(),
|
||||
m_SocketTCP( 0 ),
|
||||
m_rBugReportParameters( rBugReportParameters ),
|
||||
m_ContextID( contextid )
|
||||
{
|
||||
harvester.ToSockadr( (struct sockaddr *)&m_HarvesterSockAddr );
|
||||
|
||||
AddState( eCreateTCPSocket, &CWin32UploadBugReport::CreateTCPSocket );
|
||||
AddState( eConnectToHarvesterServer, &CWin32UploadBugReport::ConnectToHarvesterServer );
|
||||
AddState( eSendProtocolVersion, &CWin32UploadBugReport::SendProtocolVersion );
|
||||
AddState( eReceiveProtocolOkay, &CWin32UploadBugReport::ReceiveProtocolOkay );
|
||||
AddState( eSendUploadCommand, &CWin32UploadBugReport::SendUploadCommand );
|
||||
AddState( eReceiveOKToSendFile, &CWin32UploadBugReport::ReceiveOKToSendFile );
|
||||
AddState( eSendWholeFile, &CWin32UploadBugReport::SendWholeFile );
|
||||
AddState( eReceiveFileUploadSuccess, &CWin32UploadBugReport::ReceiveFileUploadSuccess );
|
||||
AddState( eSendGracefulClose, &CWin32UploadBugReport::SendGracefulClose );
|
||||
AddState( eCloseTCPSocket, &CWin32UploadBugReport::CloseTCPSocket );
|
||||
}
|
||||
|
||||
CWin32UploadBugReport::~CWin32UploadBugReport()
|
||||
{
|
||||
if ( m_SocketTCP != 0 )
|
||||
{
|
||||
closesocket( m_SocketTCP ); //lint !e534
|
||||
m_SocketTCP = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Function: DoBlockingReceive()
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWin32UploadBugReport::DoBlockingReceive( uint bytesExpected, CUtlBuffer& buf )
|
||||
{
|
||||
uint totalReceived = 0;
|
||||
|
||||
buf.Purge();
|
||||
for ( ;; )
|
||||
{
|
||||
char temp[ 8192 ];
|
||||
|
||||
int bytesReceived = recv( m_SocketTCP, temp, sizeof( temp ), 0 );
|
||||
if ( bytesReceived <= 0 )
|
||||
return false;
|
||||
|
||||
buf.Put( ( const void * )temp, (u32)bytesReceived );
|
||||
totalReceived = buf.TellPut();
|
||||
if ( totalReceived >= bytesExpected )
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWin32UploadBugReport::AddState( uint StateIndex, pfnProtocolStateHandler handler )
|
||||
{
|
||||
FSMState_t newState( StateIndex, handler );
|
||||
m_States.AddToTail( newState );
|
||||
}
|
||||
|
||||
EBugReportUploadStatus CWin32UploadBugReport::Upload( CUtlBuffer& buf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Commencing bug report upload connection." );
|
||||
|
||||
EBugReportUploadStatus result = eBugReportUploadSucceeded;
|
||||
// Run the state machine
|
||||
while ( 1 )
|
||||
{
|
||||
Assert( m_States[ m_uCurrentState ].first == m_uCurrentState );
|
||||
pfnProtocolStateHandler handler = m_States[ m_uCurrentState ].second;
|
||||
|
||||
if ( !(this->*handler)( result, buf ) )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWin32UploadBugReport::SetNextState( uint StateIndex )
|
||||
{
|
||||
Assert( StateIndex > m_uCurrentState );
|
||||
m_uCurrentState = StateIndex;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::CreateTCPSocket( EBugReportUploadStatus& status, CUtlBuffer& /*buf*/ )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Creating bug report upload socket." );
|
||||
|
||||
m_SocketTCP = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if ( m_SocketTCP == (uint)SOCKET_ERROR )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Socket creation failed." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNextState( eConnectToHarvesterServer );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::ConnectToHarvesterServer( EBugReportUploadStatus& status, CUtlBuffer& /*buf*/ )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Connecting to bug report harvesting server." );
|
||||
|
||||
if ( connect( m_SocketTCP, (const sockaddr *)&m_HarvesterSockAddr, sizeof( m_HarvesterSockAddr ) ) == SOCKET_ERROR )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Connection failed." );
|
||||
|
||||
status = eBugReportConnectToCSERServerFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNextState( eSendProtocolVersion );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::SendProtocolVersion( EBugReportUploadStatus& status, CUtlBuffer& buf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Sending bug report harvester protocol info." );
|
||||
buf.SetBigEndian( true );
|
||||
// Send protocol version
|
||||
buf.Purge();
|
||||
buf.PutInt( cuCurrentProtocolVersion );
|
||||
|
||||
if ( send( m_SocketTCP, (const char *)buf.Base(), (int)buf.TellPut(), 0 ) == SOCKET_ERROR )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Send failed." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNextState( eReceiveProtocolOkay );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::ReceiveProtocolOkay( EBugReportUploadStatus& status, CUtlBuffer& buf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Receiving harvesting protocol acknowledgement." );
|
||||
buf.Purge();
|
||||
|
||||
// Now receive the protocol is acceptable token from the server
|
||||
if ( !DoBlockingReceive( 1, buf ) )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Didn't receive protocol failure data." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool protocolokay = buf.GetChar() ? true : false;
|
||||
if ( !protocolokay )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Server rejected protocol." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateProgress( m_rBugReportParameters, "Protocol OK." );
|
||||
|
||||
SetNextState( eSendUploadCommand );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::SendUploadCommand( EBugReportUploadStatus& status, CUtlBuffer& buf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Sending harvesting protocol upload request." );
|
||||
// Send upload command
|
||||
buf.Purge();
|
||||
|
||||
NetworkMessageLengthPrefix_t messageSize
|
||||
(
|
||||
sizeof( Command_t )
|
||||
+ sizeof( ContextID_t )
|
||||
+ sizeof( HarvestFileCommand::FileSize_t )
|
||||
+ sizeof( HarvestFileCommand::SendMethod_t )
|
||||
+ sizeof( HarvestFileCommand::FileSize_t )
|
||||
);
|
||||
|
||||
// Prefix the length to the command
|
||||
buf.PutInt( (int)messageSize );
|
||||
buf.PutChar( Commands::cuSendBugReport );
|
||||
buf.PutInt( (int)m_ContextID );
|
||||
|
||||
buf.PutInt( (int)m_rBugReportParameters.m_uAttachmentFileSize );
|
||||
buf.PutInt( static_cast<HarvestFileCommand::SendMethod_t>( eSendMethodWholeRawFileNoBlocks ) );
|
||||
buf.PutInt( static_cast<HarvestFileCommand::FileSize_t>( 0 ) );
|
||||
|
||||
// Send command to server
|
||||
if ( send( m_SocketTCP, (const char *)buf.Base(), (int)buf.TellPut(), 0 ) == SOCKET_ERROR )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Send failed." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNextState( eReceiveOKToSendFile );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::ReceiveOKToSendFile( EBugReportUploadStatus& status, CUtlBuffer& buf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Receive bug report harvesting protocol upload permissible." );
|
||||
|
||||
// Now receive the protocol is acceptable token from the server
|
||||
if ( !DoBlockingReceive( 1, buf ) )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Receive failed." );
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dosend = false;
|
||||
CommandResponse_t cmd = (CommandResponse_t)buf.GetChar();
|
||||
switch ( cmd )
|
||||
{
|
||||
case HarvestFileCommand::cuOkToSendFile:
|
||||
{
|
||||
dosend = true;
|
||||
}
|
||||
break;
|
||||
case HarvestFileCommand::cuFileTooBig:
|
||||
case HarvestFileCommand::cuInvalidSendMethod:
|
||||
case HarvestFileCommand::cuInvalidMaxCompressedChunkSize:
|
||||
case HarvestFileCommand::cuInvalidBugReportContext:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !dosend )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Server rejected upload command." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNextState( eSendWholeFile );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::SendWholeFile( EBugReportUploadStatus& status, CUtlBuffer& /*buf*/ )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Uploading bug report data." );
|
||||
// Send to server
|
||||
char *filebuf = NULL;
|
||||
size_t sizeactual = g_pFileSystem->Size( m_rBugReportParameters.m_sAttachmentFile );
|
||||
if ( sizeactual > 0 )
|
||||
{
|
||||
filebuf = new char[ sizeactual + 1 ];
|
||||
if ( filebuf )
|
||||
{
|
||||
FileHandle_t fh;
|
||||
fh = g_pFileSystem->Open( m_rBugReportParameters.m_sAttachmentFile, "rb" );
|
||||
if ( FILESYSTEM_INVALID_HANDLE != fh )
|
||||
{
|
||||
g_pFileSystem->Read( (void *)filebuf, sizeactual, fh );
|
||||
|
||||
g_pFileSystem->Close( fh );
|
||||
}
|
||||
filebuf[ sizeactual ] = 0;
|
||||
}
|
||||
}
|
||||
if ( !sizeactual || !filebuf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "bug .zip file size zero or unable to allocate memory for file." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
if ( filebuf )
|
||||
{
|
||||
delete[] filebuf;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send to server
|
||||
bool bret = true;
|
||||
if ( send( m_SocketTCP, filebuf, (int)sizeactual, 0 ) == SOCKET_ERROR )
|
||||
{
|
||||
bret = false;
|
||||
UpdateProgress( m_rBugReportParameters, "Send failed." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetNextState( eReceiveFileUploadSuccess );
|
||||
}
|
||||
|
||||
delete[] filebuf;
|
||||
|
||||
return bret;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::ReceiveFileUploadSuccess( EBugReportUploadStatus& status, CUtlBuffer& buf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Receiving bug report upload success/fail message." );
|
||||
|
||||
// Now receive the protocol is acceptable token from the server
|
||||
if ( !DoBlockingReceive( 1, buf ) )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Receive failed." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = buf.GetChar() == 1 ? true : false;
|
||||
if ( !success )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Upload failed." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateProgress( m_rBugReportParameters, "Upload OK." );
|
||||
|
||||
SetNextState( eSendGracefulClose );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::SendGracefulClose( EBugReportUploadStatus& status, CUtlBuffer& buf )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Closing connection to server." );
|
||||
|
||||
// Now send disconnect command
|
||||
buf.Purge();
|
||||
|
||||
size_t messageSize = sizeof( Command_t );
|
||||
|
||||
buf.PutInt( (int)messageSize );
|
||||
buf.PutChar( Commands::cuGracefulClose );
|
||||
|
||||
if ( send( m_SocketTCP, (const char *)buf.Base(), (int)buf.TellPut(), 0 ) == SOCKET_ERROR )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Send failed." );
|
||||
|
||||
status = eBugReportUploadFailed;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNextState( eCloseTCPSocket );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWin32UploadBugReport::CloseTCPSocket( EBugReportUploadStatus& status, CUtlBuffer& /*buf*/ )
|
||||
{
|
||||
UpdateProgress( m_rBugReportParameters, "Closing socket, upload succeeded." );
|
||||
|
||||
closesocket( m_SocketTCP );//lint !e534
|
||||
m_SocketTCP = 0;
|
||||
|
||||
status = eBugReportUploadSucceeded;
|
||||
// NOTE: Returning false here ends the state machine!!!
|
||||
return false;
|
||||
}
|
||||
|
||||
EBugReportUploadStatus Win32UploadBugReportBlocking
|
||||
(
|
||||
const TBugReportParameters & rBugReportParameters
|
||||
)
|
||||
{
|
||||
EBugReportUploadStatus status = eBugReportUploadFailed;
|
||||
|
||||
CUtlBuffer buf( 2048 );
|
||||
|
||||
UpdateProgress( rBugReportParameters, "Creating initial report." );
|
||||
|
||||
buf.SetBigEndian( false );
|
||||
|
||||
buf.Purge();
|
||||
buf.PutChar( C2M_BUGREPORT );
|
||||
buf.PutChar( '\n' );
|
||||
buf.PutChar( C2M_BUGREPORT_PROTOCOL_VERSION );
|
||||
|
||||
// See CSERServerProtocol.h for format
|
||||
|
||||
// encryption object
|
||||
IceKey cipher(1); /* medium encryption level */
|
||||
unsigned char ucEncryptionKey[8] = { 200,145,10,149,195,190,108,243 };
|
||||
|
||||
cipher.set( ucEncryptionKey );
|
||||
|
||||
CUtlBuffer encrypted( 2000 );
|
||||
|
||||
u8 corruption_identifier = 0x01;
|
||||
|
||||
encrypted.PutChar( corruption_identifier );
|
||||
|
||||
encrypted.PutInt( rBugReportParameters.m_uEngineBuildNumber ); // build_identifier
|
||||
|
||||
encrypted.PutString( rBugReportParameters.m_sExecutableName );
|
||||
encrypted.PutString( rBugReportParameters.m_sGameDirectory );
|
||||
encrypted.PutString( rBugReportParameters.m_sMapName );
|
||||
|
||||
encrypted.PutInt( rBugReportParameters.m_uRAM ); // ram mb
|
||||
encrypted.PutInt( rBugReportParameters.m_uCPU ); // cpu mhz
|
||||
|
||||
encrypted.PutString( rBugReportParameters.m_sProcessor );
|
||||
|
||||
encrypted.PutInt( rBugReportParameters.m_uDXVersionHigh ); // driver version high part
|
||||
encrypted.PutInt( rBugReportParameters.m_uDXVersionLow ); // driver version low part
|
||||
encrypted.PutInt( rBugReportParameters.m_uDXVendorId ); // dxvendor id
|
||||
encrypted.PutInt( rBugReportParameters.m_uDXDeviceId ); // dxdevice id
|
||||
|
||||
encrypted.PutString( rBugReportParameters.m_sOSVersion );
|
||||
|
||||
encrypted.PutInt( rBugReportParameters.m_uAttachmentFileSize );
|
||||
|
||||
// protocol version 2 stuff
|
||||
{
|
||||
encrypted.PutString( rBugReportParameters.m_sReportType );
|
||||
encrypted.PutString( rBugReportParameters.m_sEmail );
|
||||
encrypted.PutString( rBugReportParameters.m_sAccountName );
|
||||
}
|
||||
|
||||
// protocol version 3 stuff
|
||||
{
|
||||
encrypted.Put( &rBugReportParameters.m_userid, sizeof( rBugReportParameters.m_userid ) );
|
||||
}
|
||||
|
||||
encrypted.PutString( rBugReportParameters.m_sTitle );
|
||||
|
||||
int bodylen = Q_strlen( rBugReportParameters.m_sBody ) + 1;
|
||||
|
||||
encrypted.PutInt( bodylen );
|
||||
encrypted.Put( rBugReportParameters.m_sBody, bodylen );
|
||||
|
||||
while ( encrypted.TellPut() % 8 )
|
||||
{
|
||||
encrypted.PutChar( 0 );
|
||||
}
|
||||
|
||||
EncryptBuffer( cipher, (unsigned char *)encrypted.Base(), encrypted.TellPut() );
|
||||
|
||||
buf.PutShort( (int)encrypted.TellPut() );
|
||||
buf.Put( (unsigned char *)encrypted.Base(), encrypted.TellPut() );
|
||||
|
||||
CBlockingUDPSocket bcs;
|
||||
if ( !bcs.IsValid() )
|
||||
{
|
||||
return eBugReportUploadFailed;
|
||||
}
|
||||
|
||||
struct sockaddr_in sa;
|
||||
rBugReportParameters.m_ipCSERServer.ToSockadr( (struct sockaddr *)&sa );
|
||||
|
||||
UpdateProgress( rBugReportParameters, "Sending bug report to server." );
|
||||
|
||||
bcs.SendSocketMessage( sa, (const u8 *)buf.Base(), buf.TellPut() ); //lint !e534
|
||||
|
||||
UpdateProgress( rBugReportParameters, "Waiting for response." );
|
||||
|
||||
if ( bcs.WaitForMessage( 2.0f ) )
|
||||
{
|
||||
UpdateProgress( rBugReportParameters, "Received response." );
|
||||
|
||||
struct sockaddr_in replyaddress;
|
||||
buf.EnsureCapacity( 2048 );
|
||||
|
||||
uint bytesReceived = bcs.ReceiveSocketMessage( &replyaddress, (u8 *)buf.Base(), 2048 );
|
||||
if ( bytesReceived > 0 )
|
||||
{
|
||||
// Fixup actual size
|
||||
buf.SeekPut( CUtlBuffer::SEEK_HEAD, bytesReceived );
|
||||
|
||||
UpdateProgress( rBugReportParameters, "Checking response." );
|
||||
|
||||
// Parse out data
|
||||
u8 msgtype = (u8)buf.GetChar();
|
||||
if ( M2C_ACKBUGREPORT != msgtype )
|
||||
{
|
||||
UpdateProgress( rBugReportParameters, "Request denied, invalid message type." );
|
||||
return eBugReportSendingBugReportHeaderFailed;
|
||||
}
|
||||
bool validProtocol = (u8)buf.GetChar() == 1 ? true : false;
|
||||
if ( !validProtocol )
|
||||
{
|
||||
UpdateProgress( rBugReportParameters, "Request denied, invalid message protocol." );
|
||||
return eBugReportSendingBugReportHeaderFailed;
|
||||
}
|
||||
|
||||
u8 disposition = (u8)buf.GetChar();
|
||||
if ( BR_REQEST_FILES != disposition )
|
||||
{
|
||||
// Server doesn't want a bug report, oh well
|
||||
if ( rBugReportParameters.m_uAttachmentFileSize > 0 )
|
||||
{
|
||||
UpdateProgress( rBugReportParameters, "Bug report accepted, attachment rejected (server too busy)" );
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateProgress( rBugReportParameters, "Bug report accepted." );
|
||||
}
|
||||
|
||||
return eBugReportUploadSucceeded;
|
||||
}
|
||||
|
||||
// Read in the bug report info parameters
|
||||
u32 harvester_ip = (u32)buf.GetInt();
|
||||
u16 harvester_port = (u16)buf.GetShort();
|
||||
u32 dumpcontext = (u32)buf.GetInt();
|
||||
|
||||
sockaddr_in adr;
|
||||
adr.sin_family = AF_INET;
|
||||
adr.sin_port = htons( harvester_port );
|
||||
#ifdef WIN32
|
||||
adr.sin_addr.S_un.S_addr = harvester_ip;
|
||||
#else
|
||||
adr.sin_addr.s_addr = harvester_ip;
|
||||
#endif
|
||||
netadr_t BugReportHarvesterFSMIPAddress;
|
||||
BugReportHarvesterFSMIPAddress.SetFromSockadr( (struct sockaddr *)&adr );
|
||||
|
||||
UpdateProgress( rBugReportParameters, "Server requested bug report upload." );
|
||||
|
||||
// Keep using the same scratch buffer for messaging
|
||||
CWin32UploadBugReport uploader( BugReportHarvesterFSMIPAddress, rBugReportParameters, dumpcontext );
|
||||
status = uploader.Upload( buf );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateProgress( rBugReportParameters, "No response from server." );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
744
utils/bugreporter_text/bugreporter.cpp
Normal file
744
utils/bugreporter_text/bugreporter.cpp
Normal file
@@ -0,0 +1,744 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#define PROTECTED_THINGS_DISABLE
|
||||
#undef PROTECT_FILEIO_FUNCTIONS
|
||||
#undef fopen
|
||||
#include <windows.h>
|
||||
#include "basetypes.h"
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "utlsymbol.h"
|
||||
#include "utldict.h"
|
||||
#include "utlbuffer.h"
|
||||
|
||||
#include "bugreporter/bugreporter.h"
|
||||
#include "filesystem_tools.h"
|
||||
#include "KeyValues.h"
|
||||
|
||||
IFileSystem *g_filesystem = NULL;
|
||||
|
||||
class CBug
|
||||
{
|
||||
public:
|
||||
CBug()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Q_memset( title, 0, sizeof( title ) );
|
||||
Q_memset( desc, 0, sizeof( desc ) );
|
||||
Q_memset( submitter, 0, sizeof( submitter ) );
|
||||
Q_memset( owner, 0, sizeof( owner ) );
|
||||
Q_memset( severity, 0, sizeof( severity ) );
|
||||
Q_memset( priority, 0, sizeof( priority ) );
|
||||
Q_memset( area, 0, sizeof( area ) );
|
||||
Q_memset( mapnumber, 0, sizeof( mapnumber) );
|
||||
Q_memset( reporttype, 0, sizeof( reporttype ) );
|
||||
Q_memset( level, 0, sizeof( level ) );
|
||||
Q_memset( build, 0, sizeof( build ) );
|
||||
Q_memset( position, 0, sizeof( position ) );
|
||||
Q_memset( orientation, 0, sizeof( orientation ) );
|
||||
Q_memset( screenshot_unc, 0, sizeof( screenshot_unc ) );
|
||||
Q_memset( savegame_unc, 0, sizeof( savegame_unc ) );
|
||||
Q_memset( bsp_unc, 0, sizeof( bsp_unc ) );
|
||||
Q_memset( vmf_unc, 0, sizeof( vmf_unc ) );
|
||||
Q_memset( driverinfo, 0, sizeof( driverinfo ) );
|
||||
Q_memset( misc, 0, sizeof( misc ) );
|
||||
|
||||
includedfiles.Purge();
|
||||
}
|
||||
|
||||
char title[ 256 ];
|
||||
char desc[ 8192 ];
|
||||
char owner[ 256 ];
|
||||
char submitter[ 256 ];
|
||||
char severity[ 256 ];
|
||||
char priority[ 256 ];
|
||||
char area[ 256 ];
|
||||
char mapnumber[ 256 ];
|
||||
char reporttype[ 256 ];
|
||||
char level[ 256 ];
|
||||
char build[ 256 ];
|
||||
char position[ 256 ];
|
||||
char orientation[ 256 ];
|
||||
char screenshot_unc[ 256 ];
|
||||
char savegame_unc[ 256 ];
|
||||
char bsp_unc[ 256 ];
|
||||
char vmf_unc[ 256 ];
|
||||
char driverinfo[ 2048 ];
|
||||
char misc[ 1024 ];
|
||||
|
||||
struct incfile
|
||||
{
|
||||
char name[ 256 ];
|
||||
};
|
||||
|
||||
CUtlVector< incfile > includedfiles;
|
||||
};
|
||||
|
||||
class CBugReporter : public IBugReporter
|
||||
{
|
||||
public:
|
||||
|
||||
CBugReporter();
|
||||
virtual ~CBugReporter();
|
||||
|
||||
// Initialize and login with default username/password for this computer (from resource/bugreporter.res)
|
||||
virtual bool Init( CreateInterfaceFn engineFactory );
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual bool IsPublicUI() { return false; }
|
||||
|
||||
virtual char const *GetUserName();
|
||||
virtual char const *GetUserName_Display();
|
||||
|
||||
virtual int GetNameCount();
|
||||
virtual char const *GetName( int index );
|
||||
|
||||
virtual int GetDisplayNameCount();
|
||||
virtual char const *GetDisplayName( int index );
|
||||
|
||||
virtual char const *GetDisplayNameForUserName( char const *username );
|
||||
virtual char const *GetUserNameForDisplayName( char const *display );
|
||||
|
||||
virtual int GetSeverityCount();
|
||||
virtual char const *GetSeverity( int index );
|
||||
|
||||
virtual int GetPriorityCount();
|
||||
virtual char const *GetPriority( int index );
|
||||
|
||||
virtual int GetAreaCount();
|
||||
virtual char const *GetArea( int index );
|
||||
|
||||
virtual int GetAreaMapCount();
|
||||
virtual char const *GetAreaMap( int index );
|
||||
|
||||
virtual int GetMapNumberCount();
|
||||
virtual char const *GetMapNumber( int index );
|
||||
|
||||
virtual int GetReportTypeCount();
|
||||
virtual char const *GetReportType( int index );
|
||||
|
||||
virtual char const *GetRepositoryURL( void );
|
||||
virtual char const *GetSubmissionURL( void );
|
||||
|
||||
virtual int GetLevelCount(int area) { return 0; }
|
||||
virtual char const *GetLevel(int area, int index ) { return ""; }
|
||||
|
||||
// Submission API
|
||||
virtual void StartNewBugReport();
|
||||
virtual void CancelNewBugReport();
|
||||
virtual bool CommitBugReport( int& bugSubmissionId );
|
||||
|
||||
virtual void SetTitle( char const *title );
|
||||
virtual void SetDescription( char const *description );
|
||||
|
||||
// NULL for current user
|
||||
virtual void SetSubmitter( char const *username = 0 );
|
||||
virtual void SetOwner( char const *username );
|
||||
virtual void SetSeverity( char const *severity );
|
||||
virtual void SetPriority( char const *priority );
|
||||
virtual void SetArea( char const *area );
|
||||
virtual void SetMapNumber ( char const *mapnumber );
|
||||
virtual void SetReportType( char const *reporttype );
|
||||
|
||||
virtual void SetLevel( char const *levelnamne );
|
||||
virtual void SetPosition( char const *position );
|
||||
virtual void SetOrientation( char const *pitch_yaw_roll );
|
||||
virtual void SetBuildNumber( char const *build_num );
|
||||
|
||||
virtual void SetScreenShot( char const *screenshot_unc_address );
|
||||
virtual void SetSaveGame( char const *savegame_unc_address );
|
||||
|
||||
virtual void SetBSPName( char const *bsp_unc_address );
|
||||
virtual void SetVMFName( char const *vmf_unc_address );
|
||||
|
||||
virtual void AddIncludedFile( char const *filename );
|
||||
virtual void ResetIncludedFiles();
|
||||
|
||||
virtual void SetZipAttachmentName( char const *zipfilename ) {} // only used by public bug reporter
|
||||
|
||||
virtual void SetDriverInfo( char const *info );
|
||||
|
||||
virtual void SetMiscInfo( char const *info );
|
||||
|
||||
// These are stubbed here, but are used by the public version...
|
||||
virtual void SetCSERAddress( const struct netadr_s& adr ) {}
|
||||
virtual void SetExeName( char const *exename ) {}
|
||||
virtual void SetGameDirectory( char const *pchGamedir ) {}
|
||||
virtual void SetRAM( int ram ) {}
|
||||
virtual void SetCPU( int cpu ) {}
|
||||
virtual void SetProcessor( char const *processor ) {}
|
||||
virtual void SetDXVersion( unsigned int high, unsigned int low, unsigned int vendor, unsigned int device ) {}
|
||||
virtual void SetOSVersion( char const *osversion ) {}
|
||||
virtual void SetSteamUserID( void *steamid, int idsize ) {};
|
||||
private:
|
||||
|
||||
bool PopulateLists();
|
||||
bool PopulateChoiceList( char const *listname, CUtlVector< CUtlSymbol >& list );
|
||||
|
||||
void SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src );
|
||||
|
||||
CUtlSymbolTable m_BugStrings;
|
||||
|
||||
CUtlVector< CUtlSymbol > m_Severity;
|
||||
CUtlVector< CUtlSymbol > m_SortedDisplayNames;
|
||||
CUtlVector< CUtlSymbol > m_Priority;
|
||||
CUtlVector< CUtlSymbol > m_Area;
|
||||
CUtlVector< CUtlSymbol > m_AreaMap;
|
||||
CUtlVector< CUtlSymbol > m_MapNumber;
|
||||
CUtlVector< CUtlSymbol > m_ReportType;
|
||||
|
||||
CUtlSymbol m_UserName;
|
||||
|
||||
CBug *m_pBug;
|
||||
|
||||
char m_BugRootDirectory[512];
|
||||
KeyValues *m_OptionsFile;
|
||||
|
||||
int m_CurrentBugID;
|
||||
char m_CurrentBugDirectory[512];
|
||||
};
|
||||
|
||||
CBugReporter::CBugReporter()
|
||||
{
|
||||
m_pBug = NULL;
|
||||
m_CurrentBugID = 0;
|
||||
}
|
||||
|
||||
CBugReporter::~CBugReporter()
|
||||
{
|
||||
m_BugStrings.RemoveAll();
|
||||
m_Severity.Purge();
|
||||
m_SortedDisplayNames.Purge();
|
||||
m_Priority.Purge();
|
||||
m_Area.Purge();
|
||||
m_MapNumber.Purge();
|
||||
m_ReportType.Purge();
|
||||
|
||||
delete m_pBug;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Initialize and login with default username/password for this computer (from resource/bugreporter.res)
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBugReporter::Init( CreateInterfaceFn engineFactory )
|
||||
{
|
||||
if ( engineFactory )
|
||||
{
|
||||
g_filesystem = (IFileSystem *)engineFactory( FILESYSTEM_INTERFACE_VERSION, NULL );
|
||||
if ( !g_filesystem )
|
||||
{
|
||||
AssertMsg( 0, "Failed to create/get IFileSystem" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Load our bugreporter_text options file
|
||||
m_OptionsFile = new KeyValues( "OptionsFile" );
|
||||
if ( !m_OptionsFile->LoadFromFile( g_filesystem, "bugreporter_text.txt", "EXECUTABLE_PATH" ) )
|
||||
{
|
||||
AssertMsg( 0, "Failed to load bugreporter_text options file." );
|
||||
return false;
|
||||
}
|
||||
|
||||
strncpy( m_BugRootDirectory, m_OptionsFile->GetString( "bug_directory", "." ), sizeof(m_BugRootDirectory) );
|
||||
|
||||
PopulateLists();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBugReporter::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserName()
|
||||
{
|
||||
return m_BugStrings.String( m_UserName );
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserName_Display()
|
||||
{
|
||||
return GetDisplayNameForUserName( GetUserName() );
|
||||
}
|
||||
|
||||
int CBugReporter::GetNameCount()
|
||||
{
|
||||
return GetDisplayNameCount();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetName( int index )
|
||||
{
|
||||
return GetDisplayName(index);
|
||||
}
|
||||
|
||||
int CBugReporter::GetDisplayNameCount()
|
||||
{
|
||||
return m_SortedDisplayNames.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetDisplayName( int index )
|
||||
{
|
||||
if ( index < 0 || index >= (int)m_SortedDisplayNames.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_SortedDisplayNames[ index ] );
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetDisplayNameForUserName( char const *username )
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetUserNameForDisplayName( char const *display )
|
||||
{
|
||||
return display;
|
||||
}
|
||||
|
||||
int CBugReporter::GetSeverityCount()
|
||||
{
|
||||
return m_Severity.Count() ;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetSeverity( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_Severity.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_Severity[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetPriorityCount()
|
||||
{
|
||||
return m_Priority.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetPriority( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_Priority.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_Priority[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetAreaCount()
|
||||
{
|
||||
return m_Area.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetArea( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_Area.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_Area[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetAreaMapCount()
|
||||
{
|
||||
return m_AreaMap.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetAreaMap( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_AreaMap.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_AreaMap[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetMapNumberCount()
|
||||
{
|
||||
return m_MapNumber.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetMapNumber( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_MapNumber.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_MapNumber[ index ] );
|
||||
}
|
||||
|
||||
int CBugReporter::GetReportTypeCount()
|
||||
{
|
||||
return m_ReportType.Count();
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetReportType( int index )
|
||||
{
|
||||
if ( index < 0 || index >= m_ReportType.Count() )
|
||||
return "<<Invalid>>";
|
||||
|
||||
return m_BugStrings.String( m_ReportType[ index ] );
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetRepositoryURL( void )
|
||||
{
|
||||
return m_BugRootDirectory;
|
||||
}
|
||||
|
||||
char const *CBugReporter::GetSubmissionURL( void )
|
||||
{
|
||||
return m_CurrentBugDirectory;
|
||||
}
|
||||
|
||||
|
||||
void CBugReporter::StartNewBugReport()
|
||||
{
|
||||
if ( !m_pBug )
|
||||
{
|
||||
m_pBug = new CBug();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBug->Clear();
|
||||
}
|
||||
|
||||
// Find the first available bug number by looking
|
||||
// for the next directory that doesn't exist.
|
||||
m_CurrentBugID = 0;
|
||||
do
|
||||
{
|
||||
m_CurrentBugID++;
|
||||
Q_snprintf(m_CurrentBugDirectory, sizeof(m_CurrentBugDirectory), "%s/%d", m_BugRootDirectory, m_CurrentBugID );
|
||||
} while ( g_filesystem->FileExists( m_CurrentBugDirectory ) );
|
||||
g_filesystem->CreateDirHierarchy( m_CurrentBugDirectory );
|
||||
}
|
||||
|
||||
void CBugReporter::CancelNewBugReport()
|
||||
{
|
||||
if ( !m_pBug )
|
||||
return;
|
||||
|
||||
m_pBug->Clear();
|
||||
m_CurrentBugID = 0;
|
||||
}
|
||||
|
||||
void CBugReporter::SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src )
|
||||
{
|
||||
out[ 0 ] = 0;
|
||||
|
||||
char *dest = out;
|
||||
|
||||
src.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
|
||||
char const *replace = "\\BugId\\";
|
||||
int replace_len = Q_strlen( replace );
|
||||
|
||||
for ( int pos = 0; pos <= src.TellPut() && ( ( dest - out ) < outlen ); )
|
||||
{
|
||||
char const *str = ( char const * )src.PeekGet( pos );
|
||||
if ( !Q_strnicmp( str, replace, replace_len ) )
|
||||
{
|
||||
*dest++ = '\\';
|
||||
|
||||
char num[ 32 ];
|
||||
Q_snprintf( num, sizeof( num ), "%i", bugid );
|
||||
char *pnum = num;
|
||||
while ( *pnum )
|
||||
{
|
||||
*dest++ = *pnum++;
|
||||
}
|
||||
|
||||
*dest++ = '\\';
|
||||
pos += replace_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
*dest++ = *str;
|
||||
++pos;
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
bool CBugReporter::CommitBugReport( int& bugSubmissionId )
|
||||
{
|
||||
bugSubmissionId = m_CurrentBugID;
|
||||
|
||||
if ( !m_pBug )
|
||||
return false;
|
||||
|
||||
// Now create the bug descriptor file, and dump all the text keys in it
|
||||
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
||||
|
||||
buf.Printf( "%s\n\n", m_pBug->title );
|
||||
buf.Printf( "Owner: %s\n", m_pBug->owner );
|
||||
buf.Printf( "Submitter: %s\n", m_pBug->submitter );
|
||||
buf.Printf( "Severity: %s\n", m_pBug->severity );
|
||||
buf.Printf( "Type: %s\n", m_pBug->reporttype );
|
||||
buf.Printf( "Priority: %s\n", m_pBug->priority );
|
||||
buf.Printf( "Area: %s\n", m_pBug->area );
|
||||
//buf.Printf( "Map Number: %s\n", m_pBug->mapnumber ); // Ignoring, since the bsp name is in the title
|
||||
buf.Printf( "\n%s\n\n", m_pBug->desc );
|
||||
|
||||
buf.Printf( "level: %s\nbuild: %s\nposition: setpos %s; setang %s\n",
|
||||
m_pBug->level,
|
||||
m_pBug->build,
|
||||
m_pBug->position,
|
||||
m_pBug->orientation );
|
||||
|
||||
if ( m_pBug->screenshot_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "screenshot: %s\n", m_pBug->screenshot_unc );
|
||||
}
|
||||
if ( m_pBug->savegame_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "savegame: %s\n", m_pBug->savegame_unc );
|
||||
}
|
||||
if ( m_pBug->bsp_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "bsp: %s\n", m_pBug->bsp_unc );
|
||||
}
|
||||
if ( m_pBug->vmf_unc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "vmf: %s\n", m_pBug->vmf_unc );
|
||||
}
|
||||
if ( m_pBug->includedfiles.Count() > 0 )
|
||||
{
|
||||
int c = m_pBug->includedfiles.Count();
|
||||
for ( int i = 0 ; i < c; ++i )
|
||||
{
|
||||
buf.Printf( "include: %s\n", m_pBug->includedfiles[ i ].name );
|
||||
}
|
||||
}
|
||||
if ( m_pBug->driverinfo[ 0 ] )
|
||||
{
|
||||
buf.Printf( "%s\n", m_pBug->driverinfo );
|
||||
}
|
||||
if ( m_pBug->misc[ 0 ] )
|
||||
{
|
||||
buf.Printf( "%s\n", m_pBug->misc );
|
||||
}
|
||||
buf.PutChar( 0 );
|
||||
|
||||
// Replace the "BugId" strings in the buffer with the bug ID
|
||||
int textbuflen = 2 * buf.TellPut() + 1;
|
||||
char *textbuf = new char [ textbuflen ];
|
||||
Q_memset( textbuf, 0, textbuflen );
|
||||
SubstituteBugId( bugSubmissionId, textbuf, textbuflen, buf );
|
||||
buf.Clear();
|
||||
buf.PutString( textbuf );
|
||||
|
||||
// Write it out to the file
|
||||
char szBugFileName[1024];
|
||||
Q_snprintf(szBugFileName, sizeof(szBugFileName), "%s/bug.txt", m_CurrentBugDirectory );
|
||||
g_filesystem->WriteFile( szBugFileName, NULL, buf );
|
||||
|
||||
// Clear the bug
|
||||
m_pBug->Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBugReporter::SetTitle( char const *title )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->title, title, sizeof( m_pBug->title ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetDescription( char const *description )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->desc, description, sizeof( m_pBug->desc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSubmitter( char const *username /*= 0*/ )
|
||||
{
|
||||
if ( !username )
|
||||
{
|
||||
username = GetUserName();
|
||||
}
|
||||
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->submitter, username, sizeof( m_pBug->submitter ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetOwner( char const *username )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->owner, username, sizeof( m_pBug->owner ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSeverity( char const *severity )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->severity, severity, sizeof( m_pBug->severity ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetPriority( char const *priority )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->priority, priority, sizeof( m_pBug->priority ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetArea( char const *area )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->area, area, sizeof( m_pBug->area ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetMapNumber( char const *mapnumber )
|
||||
{
|
||||
Assert( m_pBug);
|
||||
Q_strncpy( m_pBug->mapnumber, mapnumber, sizeof( m_pBug->mapnumber ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetReportType( char const *reporttype )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->reporttype, reporttype, sizeof( m_pBug->reporttype ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetLevel( char const *levelnamne )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->level, levelnamne, sizeof( m_pBug->level ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetDriverInfo( char const *info )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->driverinfo, info, sizeof( m_pBug->driverinfo ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetMiscInfo( char const *info )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->misc, info, sizeof( m_pBug->misc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetPosition( char const *position )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->position, position, sizeof( m_pBug->position ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetOrientation( char const *pitch_yaw_roll )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->orientation, pitch_yaw_roll, sizeof( m_pBug->orientation ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetBuildNumber( char const *build_num )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->build, build_num, sizeof( m_pBug->build ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetScreenShot( char const *screenshot_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->screenshot_unc, screenshot_unc_address, sizeof( m_pBug->screenshot_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetSaveGame( char const *savegame_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->savegame_unc, savegame_unc_address, sizeof( m_pBug->savegame_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetBSPName( char const *bsp_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->bsp_unc, bsp_unc_address, sizeof( m_pBug->bsp_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::SetVMFName( char const *vmf_unc_address )
|
||||
{
|
||||
Assert( m_pBug );
|
||||
Q_strncpy( m_pBug->vmf_unc, vmf_unc_address, sizeof( m_pBug->vmf_unc ) );
|
||||
}
|
||||
|
||||
void CBugReporter::AddIncludedFile( char const *filename )
|
||||
{
|
||||
CBug::incfile includedfile;
|
||||
Q_strncpy( includedfile.name, filename, sizeof( includedfile.name ) );
|
||||
m_pBug->includedfiles.AddToTail( includedfile );
|
||||
}
|
||||
|
||||
void CBugReporter::ResetIncludedFiles()
|
||||
{
|
||||
m_pBug->includedfiles.Purge();
|
||||
}
|
||||
|
||||
bool CBugReporter::PopulateChoiceList( char const *listname, CUtlVector< CUtlSymbol >& list )
|
||||
{
|
||||
// Read choice lists from text file
|
||||
KeyValues *pKV = m_OptionsFile->FindKey( listname );
|
||||
pKV = pKV->GetFirstSubKey();
|
||||
while ( pKV )
|
||||
{
|
||||
CUtlSymbol sym = m_BugStrings.AddString( pKV->GetName() );
|
||||
list.AddToTail( sym );
|
||||
|
||||
pKV = pKV->GetNextKey();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// owner, not required <<Unassigned>>
|
||||
// area <<None>>
|
||||
|
||||
bool CBugReporter::PopulateLists()
|
||||
{
|
||||
CUtlSymbol unassigned = m_BugStrings.AddString( "<<Unassigned>>" );
|
||||
CUtlSymbol none = m_BugStrings.AddString( "<<None>>" );
|
||||
|
||||
m_Area.AddToTail( none );
|
||||
m_MapNumber.AddToTail( none );
|
||||
m_SortedDisplayNames.AddToTail( unassigned );
|
||||
|
||||
PopulateChoiceList( "Severity", m_Severity );
|
||||
PopulateChoiceList( "Report Type", m_ReportType );
|
||||
PopulateChoiceList( "Area", m_Area );
|
||||
PopulateChoiceList( "Area@Dir%Map", m_AreaMap );
|
||||
PopulateChoiceList( "Map Number", m_MapNumber );
|
||||
PopulateChoiceList( "Priority", m_Priority );
|
||||
|
||||
// Get developer names from text file
|
||||
|
||||
KeyValues *pKV = m_OptionsFile->FindKey( "Names" );
|
||||
pKV = pKV->GetFirstSubKey();
|
||||
while ( pKV )
|
||||
{
|
||||
// Fill in lookup table
|
||||
CUtlSymbol display_name_sym = m_BugStrings.AddString( pKV->GetName() );
|
||||
m_SortedDisplayNames.AddToTail( display_name_sym );
|
||||
|
||||
pKV = pKV->GetNextKey();
|
||||
}
|
||||
|
||||
/*
|
||||
// Now sort display names
|
||||
int c = m_SortedDisplayNames.Count();
|
||||
for ( int i = 1 ; i < c; i++ )
|
||||
{
|
||||
for ( int j = i + 1; j < c; j++ )
|
||||
{
|
||||
char const *p1 = m_BugStrings.String( m_SortedDisplayNames[ i ] );
|
||||
char const *p2 = m_BugStrings.String( m_SortedDisplayNames[ j ] );
|
||||
|
||||
int cmp = Q_stricmp( p1, p2 );
|
||||
if ( cmp > 0 )
|
||||
{
|
||||
CUtlSymbol t = m_SortedDisplayNames[ i ];
|
||||
m_SortedDisplayNames[ i ] = m_SortedDisplayNames[ j ];
|
||||
m_SortedDisplayNames[ j ] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EXPOSE_SINGLE_INTERFACE( CBugReporter, IBugReporter, INTERFACEVERSION_BUGREPORTER );
|
||||
57
utils/bugreporter_text/bugreporter_text.vpc
Normal file
57
utils/bugreporter_text/bugreporter_text.vpc
Normal file
@@ -0,0 +1,57 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// BUGREPORTER_TEXT.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;..\common"
|
||||
$PreprocessorDefinitions "$BASE;BUGREPORTER_EXPORTS"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Bugreporter_text"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "bugreporter.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\tier0\basetypes.h"
|
||||
$File "$SRCDIR\common\bugreporter\bugreporter.h"
|
||||
$File "$SRCDIR\public\Color.h"
|
||||
$File "$SRCDIR\public\tier0\commonmacros.h"
|
||||
$File "$SRCDIR\public\tier0\dbg.h"
|
||||
$File "$SRCDIR\public\tier0\fasttimer.h"
|
||||
$File "$SRCDIR\public\filesystem.h"
|
||||
$File "$SRCDIR\public\appframework\IAppSystem.h"
|
||||
$File "$SRCDIR\public\vstdlib\IKeyValuesSystem.h"
|
||||
$File "$SRCDIR\public\tier0\mem.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgoff.h"
|
||||
$File "$SRCDIR\public\tier0\memdbgon.h"
|
||||
$File "$SRCDIR\public\tier0\platform.h"
|
||||
$File "$SRCDIR\public\tier0\protected_things.h"
|
||||
$File "$SRCDIR\public\string_t.h"
|
||||
$File "$SRCDIR\public\tier1\strtools.h"
|
||||
$File "..\bugreporter\trktool.h"
|
||||
$File "$SRCDIR\public\tier1\utlmemory.h"
|
||||
$File "$SRCDIR\public\tier1\utlrbtree.h"
|
||||
$File "$SRCDIR\public\vstdlib\vstdlib.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$File "$SRCDIR\lib\common\expdlln.lib"
|
||||
$File "$SRCDIR\lib\common\trktooln.lib"
|
||||
}
|
||||
}
|
||||
9
utils/build_res_list/StdAfx.cpp
Normal file
9
utils/build_res_list/StdAfx.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// build_res_list.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
23
utils/build_res_list/StdAfx.h
Normal file
23
utils/build_res_list/StdAfx.h
Normal file
@@ -0,0 +1,23 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// 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__0BBD59F6_3493_4BAA_8F0F_5B599107F0EF__INCLUDED_)
|
||||
#define AFX_STDAFX_H__0BBD59F6_3493_4BAA_8F0F_5B599107F0EF__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__0BBD59F6_3493_4BAA_8F0F_5B599107F0EF__INCLUDED_)
|
||||
73
utils/build_res_list/build_res_list.cpp
Normal file
73
utils/build_res_list/build_res_list.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// build_res_list.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int PrintUsage()
|
||||
{
|
||||
printf( "build_res_list <source directory> <output filename>\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void ScanDirectories_R( const char *pFullDir, const char *pRelDir, FILE *fp )
|
||||
{
|
||||
char spec[512];
|
||||
_snprintf( spec, sizeof( spec ), "%s\\*.*", pFullDir );
|
||||
|
||||
printf( "\"%s\"\n", pFullDir );
|
||||
|
||||
_finddata_t findInfo;
|
||||
long handle = _findfirst( spec, &findInfo );
|
||||
if ( handle != -1 )
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( !stricmp( findInfo.name, "." ) || !stricmp( findInfo.name, ".." ) )
|
||||
continue;
|
||||
|
||||
char fullName[512], relName[512];
|
||||
_snprintf( fullName, sizeof( fullName ), "%s\\%s", pFullDir, findInfo.name );
|
||||
_snprintf( relName, sizeof( relName ), "%s%s%s", pRelDir, (pRelDir[0] == 0) ? "" : "\\", findInfo.name );
|
||||
|
||||
if ( findInfo.attrib & _A_SUBDIR )
|
||||
{
|
||||
ScanDirectories_R( fullName, relName, fp );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( fp, "\"%s\"\n", relName );
|
||||
}
|
||||
} while ( !_findnext( handle, &findInfo ) );
|
||||
|
||||
_findclose( handle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if ( argc < 3 )
|
||||
return PrintUsage();
|
||||
|
||||
const char *pSourceDir = argv[1];
|
||||
const char *pOutputFilename = argv[2];
|
||||
|
||||
FILE *fp = fopen( pOutputFilename, "wt" );
|
||||
if ( !fp )
|
||||
{
|
||||
printf( "Can't open %s for writing.\n", pOutputFilename );
|
||||
return PrintUsage();
|
||||
}
|
||||
|
||||
ScanDirectories_R( pSourceDir, "", fp );
|
||||
|
||||
fclose( fp );
|
||||
return 0;
|
||||
}
|
||||
|
||||
133
utils/build_res_list/build_res_list.dsp
Normal file
133
utils/build_res_list/build_res_list.dsp
Normal file
@@ -0,0 +1,133 @@
|
||||
# Microsoft Developer Studio Project File - Name="build_res_list" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=build_res_list - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "build_res_list.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "build_res_list.mak" CFG="build_res_list - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "build_res_list - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "build_res_list - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "build_res_list - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# Begin Custom Build
|
||||
TargetPath=.\Release\build_res_list.exe
|
||||
InputPath=.\Release\build_res_list.exe
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"..\..\..\game\bin\build_res_list.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
if exist ..\..\..\game\bin\build_res_list.exe del /f ..\..\..\game\bin\build_res_list.exe
|
||||
copy $(TargetPath) ..\..\..\game\bin
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ELSEIF "$(CFG)" == "build_res_list - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# Begin Custom Build
|
||||
TargetPath=.\Debug\build_res_list.exe
|
||||
InputPath=.\Debug\build_res_list.exe
|
||||
SOURCE="$(InputPath)"
|
||||
|
||||
"..\..\..\game\bin\build_res_list.exe" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
if exist ..\..\..\game\bin\build_res_list.exe del /f ..\..\..\game\bin\build_res_list.exe
|
||||
copy $(TargetPath) ..\..\..\game\bin
|
||||
|
||||
# End Custom Build
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "build_res_list - Win32 Release"
|
||||
# Name "build_res_list - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\build_res_list.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.cpp
|
||||
# ADD CPP /Yc"stdafx.h"
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ReadMe.txt
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
1141
utils/bzip2/blocksort.c
Normal file
1141
utils/bzip2/blocksort.c
Normal file
File diff suppressed because it is too large
Load Diff
2108
utils/bzip2/bzip2.c
Normal file
2108
utils/bzip2/bzip2.c
Normal file
File diff suppressed because it is too large
Load Diff
40
utils/bzip2/bzip2.vpc
Normal file
40
utils/bzip2/bzip2.vpc
Normal file
@@ -0,0 +1,40 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// BZIP2.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTLIBDIR "$LIBCOMMON"
|
||||
$Include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$ForceIncludes " "
|
||||
$CompileAs "Compile as C Code (/TC)" [!$POSIX]
|
||||
}
|
||||
}
|
||||
|
||||
$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"
|
||||
}
|
||||
}
|
||||
|
||||
1578
utils/bzip2/bzlib.c
Normal file
1578
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 ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
558
utils/bzip2/bzlib_private.h
Normal file
558
utils/bzip2/bzlib_private.h
Normal file
@@ -0,0 +1,558 @@
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- 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__ __forceinline
|
||||
#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. --*/
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab )
|
||||
{
|
||||
Int32 nb, na, mid;
|
||||
nb = 0;
|
||||
na = 256;
|
||||
do {
|
||||
mid = (nb + na) >> 1;
|
||||
if (indx >= cftab[mid]) nb = mid; else na = mid;
|
||||
}
|
||||
while (na - nb != 1);
|
||||
return nb;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- 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;
|
||||
}
|
||||
{
|
||||
UChar rtmp;
|
||||
UChar* ryy_j;
|
||||
UChar rll_i;
|
||||
rtmp = yy[1];
|
||||
yy[1] = yy[0];
|
||||
ryy_j = &(yy[1]);
|
||||
rll_i = ll_i;
|
||||
while ( rll_i != rtmp ) {
|
||||
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 ---*/
|
||||
UInt32 cost01, cost23, cost45;
|
||||
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 ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
588
utils/captioncompiler/captioncompiler.cpp
Normal file
588
utils/captioncompiler/captioncompiler.cpp
Normal file
@@ -0,0 +1,588 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: vcd_sound_check.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
//===========================================================================//
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/utldict.h"
|
||||
#include "filesystem.h"
|
||||
#include "cmdlib.h"
|
||||
#include "scriplib.h"
|
||||
#include "vstdlib/random.h"
|
||||
#include "tier1/UtlBuffer.h"
|
||||
#include "pacifier.h"
|
||||
#include "appframework/tier3app.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "vgui/IVGui.h"
|
||||
#include "vgui_controls/controls.h"
|
||||
#include "vgui/ILocalize.h"
|
||||
#include "tier1/checksum_crc.h"
|
||||
#include "tier1/UtlSortVector.h"
|
||||
#include "tier1/utlmap.h"
|
||||
#include "captioncompiler.h"
|
||||
|
||||
#include "tier0/fasttimer.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
// #define TESTING 1
|
||||
|
||||
|
||||
bool uselogfile = false;
|
||||
bool bX360 = false;
|
||||
|
||||
struct AnalysisData
|
||||
{
|
||||
CUtlSymbolTable symbols;
|
||||
};
|
||||
|
||||
static AnalysisData g_Analysis;
|
||||
|
||||
IBaseFileSystem *filesystem = NULL;
|
||||
|
||||
static bool spewed = false;
|
||||
|
||||
SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg )
|
||||
{
|
||||
spewed = true;
|
||||
|
||||
printf( "%s", pMsg );
|
||||
OutputDebugString( pMsg );
|
||||
|
||||
if ( type == SPEW_ERROR )
|
||||
{
|
||||
printf( "\n" );
|
||||
OutputDebugString( "\n" );
|
||||
}
|
||||
|
||||
return SPEW_CONTINUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : depth -
|
||||
// *fmt -
|
||||
// ... -
|
||||
//-----------------------------------------------------------------------------
|
||||
void vprint( int depth, const char *fmt, ... )
|
||||
{
|
||||
char string[ 8192 ];
|
||||
va_list va;
|
||||
va_start( va, fmt );
|
||||
vsprintf( string, fmt, va );
|
||||
va_end( va );
|
||||
|
||||
FILE *fp = NULL;
|
||||
|
||||
if ( uselogfile )
|
||||
{
|
||||
fp = fopen( "log.txt", "ab" );
|
||||
}
|
||||
|
||||
while ( depth-- > 0 )
|
||||
{
|
||||
printf( " " );
|
||||
OutputDebugString( " " );
|
||||
if ( fp )
|
||||
{
|
||||
fprintf( fp, " " );
|
||||
}
|
||||
}
|
||||
|
||||
::printf( "%s", string );
|
||||
OutputDebugString( string );
|
||||
|
||||
if ( fp )
|
||||
{
|
||||
char *p = string;
|
||||
while ( *p )
|
||||
{
|
||||
if ( *p == '\n' )
|
||||
{
|
||||
fputc( '\r', fp );
|
||||
}
|
||||
fputc( *p, fp );
|
||||
p++;
|
||||
}
|
||||
fclose( fp );
|
||||
}
|
||||
}
|
||||
|
||||
void logprint( char const *logfile, const char *fmt, ... )
|
||||
{
|
||||
char string[ 8192 ];
|
||||
va_list va;
|
||||
va_start( va, fmt );
|
||||
vsprintf( string, fmt, va );
|
||||
va_end( va );
|
||||
|
||||
FILE *fp = NULL;
|
||||
static bool first = true;
|
||||
if ( first )
|
||||
{
|
||||
first = false;
|
||||
fp = fopen( logfile, "wb" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = fopen( logfile, "ab" );
|
||||
}
|
||||
if ( fp )
|
||||
{
|
||||
char *p = string;
|
||||
while ( *p )
|
||||
{
|
||||
if ( *p == '\n' )
|
||||
{
|
||||
fputc( '\r', fp );
|
||||
}
|
||||
fputc( *p, fp );
|
||||
p++;
|
||||
}
|
||||
fclose( fp );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Con_Printf( const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
static char output[1024];
|
||||
|
||||
va_start( args, fmt );
|
||||
vprintf( fmt, args );
|
||||
vsprintf( output, fmt, args );
|
||||
|
||||
vprint( 0, output );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void printusage( void )
|
||||
{
|
||||
vprint( 0, "usage: captioncompiler closecaptionfile.txt\n\
|
||||
\t-v = verbose output\n\
|
||||
\t-l = log to file log.txt\n\
|
||||
\ne.g.: kvc -l u:/xbox/game/hl2x/resource/closecaption_english.txt" );
|
||||
|
||||
// Exit app
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CheckLogFile( void )
|
||||
{
|
||||
if ( uselogfile )
|
||||
{
|
||||
_unlink( "log.txt" );
|
||||
vprint( 0, " Outputting to log.txt\n" );
|
||||
}
|
||||
}
|
||||
|
||||
void PrintHeader()
|
||||
{
|
||||
vprint( 0, "Valve Software - captioncompiler.exe (%s)\n", __DATE__ );
|
||||
vprint( 0, "--- Close Caption File compiler ---\n" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The application object
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCompileCaptionsApp : public CTier3SteamApp
|
||||
{
|
||||
typedef CTier3SteamApp BaseClass;
|
||||
|
||||
public:
|
||||
// Methods of IApplication
|
||||
virtual bool Create();
|
||||
virtual bool PreInit();
|
||||
virtual int Main();
|
||||
virtual void PostShutdown();
|
||||
virtual void Destroy();
|
||||
|
||||
private:
|
||||
// Sets up the search paths
|
||||
bool SetupSearchPaths();
|
||||
|
||||
void CompileCaptionFile( char const *infile, char const *outfile );
|
||||
void DescribeCaptions( char const *file );
|
||||
};
|
||||
|
||||
|
||||
bool CCompileCaptionsApp::Create()
|
||||
{
|
||||
SpewOutputFunc( SpewFunc );
|
||||
SpewActivate( "kvc", 2 );
|
||||
|
||||
AppSystemInfo_t appSystems[] =
|
||||
{
|
||||
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
|
||||
{ "", "" } // Required to terminate the list
|
||||
};
|
||||
|
||||
return AddSystems( appSystems );
|
||||
}
|
||||
|
||||
void CCompileCaptionsApp::Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets up the game path
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCompileCaptionsApp::SetupSearchPaths()
|
||||
{
|
||||
if ( !BaseClass::SetupSearchPaths( NULL, false, true ) )
|
||||
return false;
|
||||
|
||||
// Set gamedir.
|
||||
Q_MakeAbsolutePath( gamedir, sizeof( gamedir ), GetGameInfoPath() );
|
||||
Q_AppendSlash( gamedir, sizeof( gamedir ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Init, shutdown
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CCompileCaptionsApp::PreInit( )
|
||||
{
|
||||
if ( !BaseClass::PreInit() )
|
||||
return false;
|
||||
|
||||
g_pFileSystem = g_pFullFileSystem;
|
||||
if ( !g_pFileSystem || !g_pVGui || !g_pVGuiLocalize )
|
||||
{
|
||||
Error( "Unable to load required library interface!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
|
||||
g_pFullFileSystem->SetWarningFunc( Warning );
|
||||
|
||||
// Add paths...
|
||||
if ( !SetupSearchPaths() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCompileCaptionsApp::PostShutdown()
|
||||
{
|
||||
g_pFileSystem = NULL;
|
||||
BaseClass::PostShutdown();
|
||||
}
|
||||
|
||||
void CCompileCaptionsApp::CompileCaptionFile( char const *infile, char const *outfile )
|
||||
{
|
||||
StringIndex_t maxindex = (StringIndex_t)-1;
|
||||
int maxunicodesize = 0;
|
||||
int totalsize = 0;
|
||||
|
||||
int c = 0;
|
||||
|
||||
int curblock = 0;
|
||||
int usedBytes = 0;
|
||||
int blockSize = MAX_BLOCK_SIZE;
|
||||
|
||||
int freeSpace = 0;
|
||||
|
||||
CUtlVector< CaptionLookup_t > directory;
|
||||
CUtlBuffer data;
|
||||
|
||||
CUtlRBTree< unsigned int > hashcollision( 0, 0, DefLessFunc( unsigned int ) );
|
||||
|
||||
for ( StringIndex_t i = g_pVGuiLocalize->GetFirstStringIndex(); i != INVALID_LOCALIZE_STRING_INDEX; i = g_pVGuiLocalize->GetNextStringIndex( i ), ++c )
|
||||
{
|
||||
char const *entryName = g_pVGuiLocalize->GetNameByIndex( i );
|
||||
CaptionLookup_t entry;
|
||||
entry.SetHash( entryName );
|
||||
|
||||
// vprint( 0, "%d / %d: %s == %u\n", c, i, g_pVGuiLocalize->GetNameByIndex( i ), entry.hash );
|
||||
|
||||
if ( hashcollision.Find( entry.hash ) != hashcollision.InvalidIndex() )
|
||||
{
|
||||
Error( "Hash name collision on %s!!!\n", g_pVGuiLocalize->GetNameByIndex( i ) );
|
||||
}
|
||||
|
||||
hashcollision.Insert( entry.hash );
|
||||
|
||||
const wchar_t *text = g_pVGuiLocalize->GetValueByIndex( i );
|
||||
if ( verbose )
|
||||
{
|
||||
vprint( 0, "Processing: '%30.30s' = '%S'\n", entryName, text );
|
||||
}
|
||||
int len = text ? ( wcslen( text ) + 1 ) * sizeof( short ) : 0;
|
||||
if ( len > maxunicodesize )
|
||||
{
|
||||
maxindex = i;
|
||||
maxunicodesize = len;
|
||||
}
|
||||
|
||||
if ( len > blockSize )
|
||||
{
|
||||
Error( "Caption text file '%s' contains a single caption '%s' of %d bytes (%d is max), change MAX_BLOCK_SIZE in captioncompiler.h to fix!!!\n", g_pVGuiLocalize->GetNameByIndex( i ),
|
||||
entryName, len, blockSize );
|
||||
}
|
||||
totalsize += len;
|
||||
|
||||
if ( usedBytes + len >= blockSize )
|
||||
{
|
||||
++curblock;
|
||||
|
||||
int leftover = ( blockSize - usedBytes );
|
||||
|
||||
totalsize += leftover;
|
||||
|
||||
freeSpace += leftover;
|
||||
|
||||
while ( --leftover >= 0 )
|
||||
{
|
||||
data.PutChar( 0 );
|
||||
}
|
||||
|
||||
usedBytes = len;
|
||||
entry.offset = 0;
|
||||
|
||||
data.Put( (const void *)text, len );
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.offset = usedBytes;
|
||||
usedBytes += len;
|
||||
data.Put( (const void *)text, len );
|
||||
}
|
||||
|
||||
entry.length = len;
|
||||
entry.blockNum = curblock;
|
||||
|
||||
directory.AddToTail( entry );
|
||||
}
|
||||
|
||||
int leftover = ( blockSize - usedBytes );
|
||||
totalsize += leftover;
|
||||
freeSpace += leftover;
|
||||
while ( --leftover >= 0 )
|
||||
{
|
||||
data.PutChar( 0 );
|
||||
}
|
||||
|
||||
vprint( 0, "Found %i strings in '%s'\n", c, infile );
|
||||
|
||||
if ( maxindex != INVALID_LOCALIZE_STRING_INDEX )
|
||||
{
|
||||
vprint( 0, "Longest string '%s' = (%i) bytes average(%.3f)\n%",
|
||||
g_pVGuiLocalize->GetNameByIndex( maxindex ), maxunicodesize, (float)totalsize/(float)c );
|
||||
}
|
||||
|
||||
vprint( 0, "%d blocks (%d bytes each), %d bytes wasted (%.3f per block average), total bytes %d\n",
|
||||
curblock + 1, blockSize, freeSpace, (float)freeSpace/(float)( curblock + 1 ), totalsize );
|
||||
|
||||
vprint( 0, "directory size %d entries, %d bytes, data size %d bytes\n",
|
||||
directory.Count(), directory.Count() * sizeof( CaptionLookup_t ), data.TellPut() );
|
||||
|
||||
CompiledCaptionHeader_t header;
|
||||
header.magic = COMPILED_CAPTION_FILEID;
|
||||
header.version = COMPILED_CAPTION_VERSION;
|
||||
header.numblocks = curblock + 1;
|
||||
header.blocksize = blockSize;
|
||||
header.directorysize = directory.Count();
|
||||
header.dataoffset = 0;
|
||||
|
||||
// Now write the outfile
|
||||
CUtlBuffer out;
|
||||
out.Put( &header, sizeof( header ) );
|
||||
out.Put( directory.Base(), directory.Count() * sizeof( CaptionLookup_t ) );
|
||||
int curOffset = out.TellPut();
|
||||
// Round it up to the next 512 byte boundary
|
||||
int nBytesDestBuffer = AlignValue( curOffset, 512 ); // align to HD sector
|
||||
int nPadding = nBytesDestBuffer - curOffset;
|
||||
while ( --nPadding >= 0 )
|
||||
{
|
||||
out.PutChar( 0 );
|
||||
}
|
||||
out.Put( data.Base(), data.TellPut() );
|
||||
|
||||
// Write out a corrected header
|
||||
header.dataoffset = nBytesDestBuffer;
|
||||
int savePos = out.TellPut();
|
||||
out.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
out.Put( &header, sizeof( header ) );
|
||||
out.SeekPut( CUtlBuffer::SEEK_HEAD, savePos );
|
||||
|
||||
g_pFullFileSystem->WriteFile( outfile, NULL, out );
|
||||
|
||||
// Jeep: this function no longer exisits
|
||||
/*if ( bX360 )
|
||||
{
|
||||
UpdateOrCreateCaptionFile_X360( g_pFullFileSystem, outfile, NULL, true );
|
||||
}*/
|
||||
}
|
||||
|
||||
void CCompileCaptionsApp::DescribeCaptions( char const *file )
|
||||
{
|
||||
CUtlBuffer buf;
|
||||
if ( !g_pFullFileSystem->ReadFile( file, NULL, buf ) )
|
||||
{
|
||||
Error( "Unable to read '%s' into buffer\n", file );
|
||||
}
|
||||
|
||||
CompiledCaptionHeader_t header;
|
||||
buf.Get( &header, sizeof( header ) );
|
||||
if ( header.magic != COMPILED_CAPTION_FILEID )
|
||||
Error( "Invalid file id for %s\n", file );
|
||||
if ( header.version != COMPILED_CAPTION_VERSION )
|
||||
Error( "Invalid file version for %s\n", file );
|
||||
|
||||
// Read the directory
|
||||
CUtlSortVector< CaptionLookup_t, CCaptionLookupLess > directory;
|
||||
directory.EnsureCapacity( header.directorysize );
|
||||
directory.CopyArray( (const CaptionLookup_t *)buf.PeekGet(), header.directorysize );
|
||||
directory.RedoSort( true );
|
||||
buf.SeekGet( CUtlBuffer::SEEK_HEAD, header.dataoffset );
|
||||
|
||||
int i;
|
||||
CUtlVector< CaptionBlock_t > blocks;
|
||||
for ( i = 0; i < header.numblocks; ++i )
|
||||
{
|
||||
CaptionBlock_t& newBlock = blocks[ blocks.AddToTail() ];
|
||||
Q_memset( newBlock.data, 0, sizeof( newBlock.data ) );
|
||||
buf.Get( newBlock.data, header.blocksize );
|
||||
}
|
||||
|
||||
CUtlMap< unsigned int, StringIndex_t > inverseMap( 0, 0, DefLessFunc( unsigned int ) );
|
||||
for ( StringIndex_t idx = g_pVGuiLocalize->GetFirstStringIndex(); idx != INVALID_LOCALIZE_STRING_INDEX; idx = g_pVGuiLocalize->GetNextStringIndex( idx ) )
|
||||
{
|
||||
const char *name = g_pVGuiLocalize->GetNameByIndex( idx );
|
||||
CaptionLookup_t dummy;
|
||||
dummy.SetHash( name );
|
||||
|
||||
inverseMap.Insert( dummy.hash, idx );
|
||||
}
|
||||
|
||||
// Now print everything out...
|
||||
for ( i = 0; i < header.directorysize; ++i )
|
||||
{
|
||||
const CaptionLookup_t& entry = directory[ i ];
|
||||
char const *name = g_pVGuiLocalize->GetNameByIndex( inverseMap.Element( inverseMap.Find( entry.hash ) ) );
|
||||
const CaptionBlock_t& block = blocks[ entry.blockNum ];
|
||||
const wchar_t *data = (const wchar_t *)&block.data[ entry.offset ];
|
||||
wchar_t *temp = ( wchar_t * )_alloca( entry.length * sizeof( short ) );
|
||||
wcsncpy( temp, data, ( entry.length / sizeof( short ) ) - 1 );
|
||||
|
||||
vprint( 0, "%3.3d: (%40.40s) hash(%15.15u), block(%4.4d), offset(%4.4d), len(%4.4d) %S\n",
|
||||
i, name, entry.hash, entry.blockNum, entry.offset, entry.length, temp );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// main application
|
||||
//-----------------------------------------------------------------------------
|
||||
int CCompileCaptionsApp::Main()
|
||||
{
|
||||
CUtlVector< CUtlSymbol > worklist;
|
||||
|
||||
int i = 1;
|
||||
for ( i ; i<CommandLine()->ParmCount() ; i++)
|
||||
{
|
||||
if ( CommandLine()->GetParm( i )[ 0 ] == '-' )
|
||||
{
|
||||
switch( CommandLine()->GetParm( i )[ 1 ] )
|
||||
{
|
||||
case 'l':
|
||||
uselogfile = true;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
case 'x':
|
||||
bX360 = true;
|
||||
break;
|
||||
case 'g': // -game
|
||||
++i;
|
||||
break;
|
||||
default:
|
||||
printusage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( i != 0 )
|
||||
{
|
||||
char fn[ 512 ];
|
||||
Q_strncpy( fn, CommandLine()->GetParm( i ), sizeof( fn ) );
|
||||
Q_FixSlashes( fn );
|
||||
Q_strlower( fn );
|
||||
|
||||
CUtlSymbol sym;
|
||||
sym = fn;
|
||||
worklist.AddToTail( sym );
|
||||
}
|
||||
}
|
||||
|
||||
if ( CommandLine()->ParmCount() < 2 || ( i != CommandLine()->ParmCount() ) || worklist.Count() != 1 )
|
||||
{
|
||||
PrintHeader();
|
||||
printusage();
|
||||
}
|
||||
|
||||
CheckLogFile();
|
||||
|
||||
PrintHeader();
|
||||
|
||||
char binaries[MAX_PATH];
|
||||
Q_strncpy( binaries, gamedir, MAX_PATH );
|
||||
Q_StripTrailingSlash( binaries );
|
||||
Q_strncat( binaries, "/../bin", MAX_PATH, MAX_PATH );
|
||||
|
||||
char outfile[ 512 ];
|
||||
if ( Q_stristr( worklist[ worklist.Count() - 1 ].String(), gamedir ) )
|
||||
{
|
||||
Q_strncpy( outfile, &worklist[ worklist.Count() - 1 ].String()[ Q_strlen( gamedir ) ] , sizeof( outfile ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_snprintf( outfile, sizeof( outfile ), "resource\\%s", worklist[ worklist.Count() - 1 ].String() );
|
||||
}
|
||||
|
||||
char infile[ 512 ];
|
||||
Q_strncpy( infile, outfile, sizeof( infile ) );
|
||||
|
||||
Q_SetExtension( outfile, ".dat", sizeof( outfile ) );
|
||||
|
||||
vprint( 0, "gamedir[ %s ]\n", gamedir );
|
||||
vprint( 0, "infile[ %s ]\n", infile );
|
||||
vprint( 0, "outfile[ %s ]\n", outfile );
|
||||
|
||||
g_pFullFileSystem->AddSearchPath( binaries, "EXECUTABLE_PATH" );
|
||||
|
||||
if ( !g_pVGuiLocalize->AddFile( infile, "MOD", false ) )
|
||||
{
|
||||
Error( "Unable to add localization file '%s'\n", infile );
|
||||
}
|
||||
|
||||
vprint( 0, " Compiling Captions for '%s'...\n", infile );
|
||||
|
||||
CompileCaptionFile( infile, outfile );
|
||||
|
||||
if ( verbose )
|
||||
{
|
||||
DescribeCaptions( outfile );
|
||||
}
|
||||
|
||||
g_pVGuiLocalize->RemoveAll();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Main entry point
|
||||
//-----------------------------------------------------------------------------
|
||||
DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT( CCompileCaptionsApp )
|
||||
60
utils/captioncompiler/captioncompiler.vpc
Normal file
60
utils/captioncompiler/captioncompiler.vpc
Normal file
@@ -0,0 +1,60 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAPTIONCOMPILER.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,..\common,$SRCDIR\game\shared,.\"
|
||||
$PreprocessorDefinitions "$BASE;captioncompiler"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Captioncompiler"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "captioncompiler.cpp"
|
||||
$File "$SRCDIR\common\compiledcaptionswap.cpp"
|
||||
$File "..\common\filesystem_tools.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "cbase.h"
|
||||
$File "..\common\filesystem_tools.h"
|
||||
}
|
||||
|
||||
$Folder "Shared Code"
|
||||
{
|
||||
$File "..\common\cmdlib.cpp"
|
||||
$File "..\common\cmdlib.h"
|
||||
$File "$SRCDIR\public\filesystem_helpers.cpp"
|
||||
$File "$SRCDIR\public\filesystem_helpers.h"
|
||||
$File "$SRCDIR\public\filesystem_init.cpp"
|
||||
$File "$SRCDIR\public\filesystem_init.h"
|
||||
$File "$SRCDIR\public\mathlib\mathlib.h"
|
||||
$File "..\common\pacifier.cpp"
|
||||
$File "..\common\pacifier.h"
|
||||
$File "..\common\scriplib.cpp"
|
||||
$File "..\common\scriplib.h"
|
||||
$File "$SRCDIR\public\stringregistry.cpp"
|
||||
$File "$SRCDIR\public\stringregistry.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib appframework
|
||||
$Lib mathlib
|
||||
$Lib tier2
|
||||
$Lib tier3
|
||||
}
|
||||
}
|
||||
19
utils/captioncompiler/cbase.h
Normal file
19
utils/captioncompiler/cbase.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef CBASE_H
|
||||
#define CBASE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "basetypes.h"
|
||||
|
||||
// This is just a dummy file to make this tool compile
|
||||
#include "ai_activity.h"
|
||||
#include "utlvector.h"
|
||||
|
||||
#endif // CBASE_H
|
||||
1581
utils/classcheck/class.cpp
Normal file
1581
utils/classcheck/class.cpp
Normal file
File diff suppressed because it is too large
Load Diff
196
utils/classcheck/class.h
Normal file
196
utils/classcheck/class.h
Normal file
@@ -0,0 +1,196 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( CLASS_H )
|
||||
#define CLASS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
class CTypeDescriptionField
|
||||
{
|
||||
public:
|
||||
CTypeDescriptionField()
|
||||
{
|
||||
m_szVariableName[ 0 ] = 0;
|
||||
m_szType[ 0 ] = 0;
|
||||
m_szDefineType[ 0 ] = 0;
|
||||
m_bCommentedOut = false;
|
||||
m_bRepresentedInRecvTable = false;
|
||||
}
|
||||
|
||||
char m_szVariableName[ 128 ];
|
||||
char m_szType[ 128 ];
|
||||
char m_szDefineType[ 128 ];
|
||||
bool m_bCommentedOut;
|
||||
bool m_bRepresentedInRecvTable;
|
||||
};
|
||||
|
||||
class CClassVariable
|
||||
{
|
||||
public:
|
||||
CClassVariable()
|
||||
{
|
||||
m_szName[ 0 ] = 0;
|
||||
m_szType[ 0 ] = 0;
|
||||
|
||||
m_Type = TPUBLIC;
|
||||
|
||||
m_bKnownType = false;
|
||||
m_nTypeSize = 0;
|
||||
|
||||
m_bIsArray = false;
|
||||
m_szArraySize[ 0 ] = 0;
|
||||
|
||||
m_bInRecvTable = false;
|
||||
|
||||
m_TypeSize = 0;
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TPUBLIC = 0,
|
||||
TPROTECTED,
|
||||
TPRIVATE
|
||||
} VARTYPE;
|
||||
|
||||
char m_szName[ 128 ];
|
||||
char m_szType[ 128 ];
|
||||
|
||||
VARTYPE m_Type;
|
||||
|
||||
bool m_bKnownType;
|
||||
int m_nTypeSize;
|
||||
|
||||
bool m_bIsArray;
|
||||
char m_szArraySize[ 128 ];
|
||||
|
||||
bool m_bInRecvTable;
|
||||
|
||||
int m_TypeSize;
|
||||
};
|
||||
|
||||
class CClassMemberFunction
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
TPUBLIC = 0,
|
||||
TPROTECTED,
|
||||
TPRIVATE
|
||||
} MEMBERTYPE;
|
||||
|
||||
char m_szName[ 128 ];
|
||||
// Return type
|
||||
char m_szType[ 128 ];
|
||||
|
||||
MEMBERTYPE m_Type;
|
||||
|
||||
};
|
||||
|
||||
class CClassTypedef
|
||||
{
|
||||
public:
|
||||
char m_szTypeName[ 128 ];
|
||||
char m_szAlias[ 128 ];
|
||||
|
||||
// bool m_bIsTypedefForBaseClass;
|
||||
};
|
||||
|
||||
class CClass
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_VARIABLES = 1024,
|
||||
MAX_MEMBERS = 1024,
|
||||
MAX_TDFIELDS = 1024,
|
||||
};
|
||||
|
||||
CClass( const char *name );
|
||||
~CClass( void );
|
||||
|
||||
char *ParseClassDeclaration( char *input );
|
||||
|
||||
|
||||
void SetBaseClass( const char *name );
|
||||
void CheckChildOfBaseEntity( const char *baseentityclass );
|
||||
bool CheckForMissingTypeDescriptionFields( int& missingcount, bool createtds = false );
|
||||
bool CheckForMissingPredictionFields( int& missingcount, bool createtds = false );
|
||||
bool CheckForPredictionFieldsInRecvTableNotMarkedAsSuchCorrectly( int& missingcount );
|
||||
void AddVariable( int protection, char *type, char *name, bool array, char *arraysize = 0 );
|
||||
|
||||
// Parsing helper methods
|
||||
bool ParseProtection( char *&input, int &protection );
|
||||
bool ParseNestedClass( char *&input );
|
||||
bool ParseBaseClass( char *&input );
|
||||
bool ParseClassMember( char *&input, int protection );
|
||||
bool ParseNetworkVar( char *&input, int protection );
|
||||
void ReportTypeMismatches( CClassVariable *var, CTypeDescriptionField *td );
|
||||
|
||||
void CheckForHungarianErrors( int& warnings );
|
||||
|
||||
char m_szName[ 128 ];
|
||||
char m_szBaseClass[ 128 ];
|
||||
char m_szTypedefBaseClass[ 128 ];
|
||||
|
||||
CClassVariable *FindVar( const char *name, bool checkbaseclasses = false );
|
||||
CClassVariable *AddVar( const char *name );
|
||||
int m_nVarCount;
|
||||
CClassVariable *m_Variables[ MAX_VARIABLES ];
|
||||
|
||||
CClassMemberFunction *FindMember( const char *name );
|
||||
CClassMemberFunction *AddMember( const char *name );
|
||||
int m_nMemberCount;
|
||||
CClassMemberFunction *m_Members[ MAX_MEMBERS ];
|
||||
|
||||
CTypeDescriptionField *FindTD( const char *name );
|
||||
CTypeDescriptionField *AddTD( const char *name, const char *type, const char *definetype, bool incomments );
|
||||
int m_nTDCount;
|
||||
CTypeDescriptionField *m_TDFields[ MAX_TDFIELDS ];
|
||||
|
||||
CTypeDescriptionField *FindPredTD( const char *name );
|
||||
CTypeDescriptionField *AddPredTD( const char *name, const char *type, const char *definetype, bool incomments, bool inrecvtable );
|
||||
int m_nPredTDCount;
|
||||
CTypeDescriptionField *m_PredTDFields[ MAX_TDFIELDS ];
|
||||
|
||||
|
||||
CClass *m_pBaseClass;
|
||||
|
||||
CClass *m_pNext;
|
||||
|
||||
bool m_bDerivedFromCBaseEntity;
|
||||
bool m_bHasSaveRestoreData;
|
||||
bool m_bHasPredictionData;
|
||||
bool m_bHasRecvTableData;
|
||||
bool m_bConstructPredictableCalled;
|
||||
|
||||
int m_nClassDataSize;
|
||||
|
||||
private:
|
||||
struct MemberVarParse_t
|
||||
{
|
||||
char m_pType[256];
|
||||
char m_pTypeModifier[256];
|
||||
char m_pName[256];
|
||||
char m_pArraySize[ 128 ];
|
||||
bool m_bArray;
|
||||
|
||||
MemberVarParse_t() { Reset(); }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_pType[0] = 0;
|
||||
m_pTypeModifier[0] = 0;
|
||||
m_pName[0] = 0;
|
||||
m_pArraySize[0] = 0;
|
||||
m_bArray = false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // CLASS_H
|
||||
216
utils/classcheck/classcheck.cpp
Normal file
216
utils/classcheck/classcheck.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include "classcheck_util.h"
|
||||
#include "icodeprocessor.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
|
||||
SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg )
|
||||
{
|
||||
printf( "%s", pMsg );
|
||||
OutputDebugString( pMsg );
|
||||
|
||||
if ( type == SPEW_ERROR )
|
||||
{
|
||||
printf( "\n" );
|
||||
OutputDebugString( "\n" );
|
||||
}
|
||||
|
||||
return SPEW_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void printusage( void )
|
||||
{
|
||||
vprint( 0, "usage: classcheck -q -h -m -t <root source directory> <game: hl2 | tf2>\n\
|
||||
\t-q = quiet\n\
|
||||
\t-h = print class hierarchy\n\
|
||||
\t-m = don't print member functions/variables of class\n\
|
||||
\t-t = don't print type description errors\n\
|
||||
\t-p = don't print prediction description errors\n\
|
||||
\t-c = create missing save descriptions\n\
|
||||
\t-x = create missing prediction descriptions\n\
|
||||
\t-i = specify specific input file to parse\n\
|
||||
\t-b = similar to -i, allows specifying files outside client\\server directories\n\
|
||||
\t-j = check for Crazy Jay Stelly's mismatched Hungarian notation errors\n\
|
||||
\t-l = log to file log.txt\n" );
|
||||
|
||||
// Exit app
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *sourcetreebase -
|
||||
// *subdir -
|
||||
// *baseentityclass -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ProcessDirectory( const char *game, const char *sourcetreebase, const char *subdir, const char *baseentityclass )
|
||||
{
|
||||
char rootdirectory[ 256 ];
|
||||
sprintf( rootdirectory, "%s\\%s", sourcetreebase, subdir );
|
||||
|
||||
// check for existence
|
||||
if ( COM_DirectoryExists( rootdirectory ) )
|
||||
{
|
||||
processor->Process( baseentityclass, game, sourcetreebase, subdir );
|
||||
}
|
||||
else
|
||||
{
|
||||
vprint( 0, "Couldn't find directory %s, check path %s\n", rootdirectory, sourcetreebase );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *sourcetreebase -
|
||||
// *subdir -
|
||||
// *baseentityclass -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ProcessFile( const char *game, const char *sourcetreebase, const char *subdir, const char *baseentityclass, const char *pFileName )
|
||||
{
|
||||
char rootdirectory[ 256 ];
|
||||
sprintf( rootdirectory, "%s\\%s", sourcetreebase, subdir );
|
||||
|
||||
// check for existence
|
||||
if ( COM_DirectoryExists( rootdirectory ) )
|
||||
{
|
||||
processor->Process( baseentityclass, game, sourcetreebase, subdir, pFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
vprint( 0, "Couldn't find directory %s, check path %s\n", rootdirectory, sourcetreebase );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CheckLogFile( void )
|
||||
{
|
||||
if ( processor->GetLogFile() )
|
||||
{
|
||||
_unlink( "log.txt" );
|
||||
vprint( 0, " Outputting to log.txt\n" );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : argc -
|
||||
// argv[] -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
SpewOutputFunc( SpewFunc );
|
||||
|
||||
vprint( 0, "Valve Software - classcheck.exe (%s)\n", __DATE__ );
|
||||
vprint( 0, "--- Game Code Static Analysis ---\n" );
|
||||
char *pSpecificFile = NULL;
|
||||
bool bOutsideGamedir = false;
|
||||
|
||||
int i = 1;
|
||||
for ( i ; i<argc ; i++)
|
||||
{
|
||||
if ( argv[ i ][ 0 ] == '-' )
|
||||
{
|
||||
switch( argv[ i ][ 1 ] )
|
||||
{
|
||||
case 'q':
|
||||
processor->SetQuiet( true );
|
||||
break;
|
||||
case 'h':
|
||||
processor->SetPrintHierarchy( true );
|
||||
break;
|
||||
case 'm':
|
||||
processor->SetPrintMembers( false );
|
||||
break;
|
||||
case 't':
|
||||
processor->SetPrintTDs( false );
|
||||
break;
|
||||
case 'p':
|
||||
processor->SetPrintPredTDs( false );
|
||||
break;
|
||||
case 'c':
|
||||
processor->SetPrintCreateMissingTDs( true );
|
||||
break;
|
||||
case 'x':
|
||||
processor->SetPrintCreateMissingPredTDs( true );
|
||||
break;
|
||||
case 'i':
|
||||
if (i < argc-1)
|
||||
{
|
||||
pSpecificFile = argv[i+1];
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (i < argc-1)
|
||||
{
|
||||
pSpecificFile = argv[i+1];
|
||||
bOutsideGamedir = true;
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
processor->SetLogFile( true );
|
||||
break;
|
||||
case 'j':
|
||||
processor->SetCheckHungarian( true );
|
||||
break;
|
||||
default:
|
||||
printusage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( argc < 3 || ( i != argc ) )
|
||||
{
|
||||
printusage();
|
||||
}
|
||||
|
||||
CheckLogFile();
|
||||
|
||||
vprint( 0, " Looking for obvious screwups and boneheaded mistakes...\n" );
|
||||
|
||||
char sourcetreebase[ 256 ];
|
||||
strcpy( sourcetreebase, argv[i-2] );
|
||||
|
||||
Q_StripTrailingSlash( sourcetreebase );
|
||||
|
||||
if ( !pSpecificFile )
|
||||
{
|
||||
ProcessDirectory( argv[ i-1 ], sourcetreebase, "server", "CBaseEntity" );
|
||||
ProcessDirectory( argv[ i-1 ], sourcetreebase, "client", "C_BaseEntity" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bOutsideGamedir )
|
||||
{
|
||||
ProcessFile( argv[ i-1 ], sourcetreebase, "", "", pSpecificFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessFile( argv[ i-1 ], sourcetreebase, "server", "CBaseEntity", pSpecificFile );
|
||||
ProcessFile( argv[ i-1 ], sourcetreebase, "client", "C_BaseEntity", pSpecificFile );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
39
utils/classcheck/classcheck.vpc
Normal file
39
utils/classcheck/classcheck.vpc
Normal file
@@ -0,0 +1,39 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// CLASSCHECK.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,..\common"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Classcheck"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "class.cpp"
|
||||
$File "classcheck.cpp"
|
||||
$File "classcheck_util.cpp"
|
||||
$File "processmodule.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\tier0\basetypes.h"
|
||||
$File "class.h"
|
||||
$File "classcheck_util.h"
|
||||
$File "codeprocessor.h"
|
||||
$File "icodeprocessor.h"
|
||||
$File "$SRCDIR\public\tier1\utldict.h"
|
||||
}
|
||||
}
|
||||
369
utils/classcheck/classcheck_util.cpp
Normal file
369
utils/classcheck/classcheck_util.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "stdafx.h"
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include "classcheck_util.h"
|
||||
#include "icodeprocessor.h"
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : depth -
|
||||
// *fmt -
|
||||
// ... -
|
||||
//-----------------------------------------------------------------------------
|
||||
void vprint( int depth, const char *fmt, ... )
|
||||
{
|
||||
char string[ 8192 ];
|
||||
va_list va;
|
||||
va_start( va, fmt );
|
||||
vsprintf( string, fmt, va );
|
||||
va_end( va );
|
||||
|
||||
FILE *fp = NULL;
|
||||
|
||||
if ( processor->GetLogFile() )
|
||||
{
|
||||
fp = fopen( "log.txt", "ab" );
|
||||
}
|
||||
|
||||
while ( depth-- > 0 )
|
||||
{
|
||||
printf( " " );
|
||||
OutputDebugString( " " );
|
||||
if ( fp )
|
||||
{
|
||||
fprintf( fp, " " );
|
||||
}
|
||||
}
|
||||
|
||||
::printf( "%s", string );
|
||||
OutputDebugString( string );
|
||||
|
||||
if ( fp )
|
||||
{
|
||||
char *p = string;
|
||||
while ( *p )
|
||||
{
|
||||
if ( *p == '\n' )
|
||||
{
|
||||
fputc( '\r', fp );
|
||||
}
|
||||
fputc( *p, fp );
|
||||
p++;
|
||||
}
|
||||
fclose( fp );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool com_ignorecolons = false; // YWB: Ignore colons as token separators in COM_Parse
|
||||
bool com_ignoreinlinecomment = false;
|
||||
static bool s_com_token_unget = false;
|
||||
char com_token[1024];
|
||||
int linesprocessed = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_UngetToken( void )
|
||||
{
|
||||
s_com_token_unget = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : ch -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CC_IsBreakChar( char ch )
|
||||
{
|
||||
bool brk = false;
|
||||
switch ( ch )
|
||||
{
|
||||
case '{':
|
||||
case '}':
|
||||
case ')':
|
||||
case '(':
|
||||
case '[':
|
||||
case ']':
|
||||
case '\'':
|
||||
case '/':
|
||||
case ',':
|
||||
case ';':
|
||||
case '<':
|
||||
case '>':
|
||||
brk = true;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if ( !com_ignorecolons )
|
||||
brk = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return brk;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *data -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char *CC_ParseToken(char *data)
|
||||
{
|
||||
int c;
|
||||
int len;
|
||||
|
||||
if ( s_com_token_unget )
|
||||
{
|
||||
s_com_token_unget = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
com_token[0] = 0;
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while ( (c = *data) <= ' ')
|
||||
{
|
||||
if (c == 0)
|
||||
return NULL; // end of file;
|
||||
if ( c== '\n' )
|
||||
{
|
||||
linesprocessed++;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
// skip // comments
|
||||
if ( !com_ignoreinlinecomment )
|
||||
{
|
||||
if (c=='/' && data[1] == '/')
|
||||
{
|
||||
while (*data && *data != '\n')
|
||||
data++;
|
||||
goto skipwhite;
|
||||
}
|
||||
}
|
||||
|
||||
if ( c == '/' && data[1] == '*' )
|
||||
{
|
||||
while (data[0] && data[1] && !( data[0] == '*' && data[1] == '/' ) )
|
||||
{
|
||||
if ( *data == '\n' )
|
||||
{
|
||||
linesprocessed++;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
if ( data[0] == '*' && data[1] == '/' )
|
||||
{
|
||||
data+=2;
|
||||
}
|
||||
goto skipwhite;
|
||||
}
|
||||
|
||||
// handle quoted strings specially
|
||||
bool isLstring = data[0] == 'L' && (data[1] == '\"' );
|
||||
if ( isLstring )
|
||||
{
|
||||
com_token[len++] = (char)c;
|
||||
return data+1;
|
||||
}
|
||||
|
||||
if ( c == '\"' )
|
||||
{
|
||||
data++;
|
||||
bool bEscapeSequence = false;
|
||||
while (1)
|
||||
{
|
||||
Assert( len < 1024 );
|
||||
if ( len >= 1024 )
|
||||
{
|
||||
com_token[ len -1 ] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
c = *data++;
|
||||
if ( (c=='\"' && !bEscapeSequence) || !c && len < sizeof( com_token ) - 1 )
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
bEscapeSequence = ( c == '\\' );
|
||||
com_token[len] = (char)c;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
// parse single characters
|
||||
if ( CC_IsBreakChar( (char)c ) )
|
||||
{
|
||||
Assert( len < 1024 );
|
||||
|
||||
com_token[len] = (char)c;
|
||||
len++;
|
||||
com_token[len] = 0;
|
||||
return data+1;
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
Assert( len < 1024 );
|
||||
|
||||
com_token[len] = (char)c;
|
||||
data++;
|
||||
len++;
|
||||
c = *data;
|
||||
|
||||
if ( CC_IsBreakChar( (char)c ) )
|
||||
break;
|
||||
} while (c>32 && len < sizeof( com_token ) - 1);
|
||||
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *name -
|
||||
// *len -
|
||||
// Output : unsigned char
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned char *COM_LoadFile( const char *name, int *len)
|
||||
{
|
||||
FILE *fp;
|
||||
fp = fopen( name, "rb" );
|
||||
if ( !fp )
|
||||
{
|
||||
*len = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek( fp, 0, SEEK_END );
|
||||
*len = ftell( fp );
|
||||
fseek( fp, 0, SEEK_SET );
|
||||
|
||||
unsigned char *buffer = new unsigned char[ *len + 1 ];
|
||||
fread( buffer, *len, 1, fp );
|
||||
fclose( fp );
|
||||
buffer[ *len ] = 0;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *buffer -
|
||||
//-----------------------------------------------------------------------------
|
||||
void COM_FreeFile( unsigned char *buffer )
|
||||
{
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *dir -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool COM_DirectoryExists( const char *dir )
|
||||
{
|
||||
if ( !_access( dir, 0 ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *input -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char *CC_ParseUntilEndOfLine( char *input )
|
||||
{
|
||||
while (*input && *input != '\n')
|
||||
input++;
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *input -
|
||||
// *ch -
|
||||
// *breakchar -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char *CC_RawParseChar( char *input, const char *ch, char *breakchar )
|
||||
{
|
||||
bool done = false;
|
||||
int listlen = strlen( ch );
|
||||
|
||||
do
|
||||
{
|
||||
input = CC_ParseToken( input );
|
||||
if ( strlen( com_token ) <= 0 )
|
||||
break;
|
||||
|
||||
if ( strlen( com_token ) == 1 )
|
||||
{
|
||||
for ( int i = 0; i < listlen; i++ )
|
||||
{
|
||||
if ( com_token[ 0 ] == ch[ i ] )
|
||||
{
|
||||
*breakchar = ch [ i ];
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( !done );
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *input -
|
||||
// *pairing -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char *CC_DiscardUntilMatchingCharIncludingNesting( char *input, const char *pairing )
|
||||
{
|
||||
int nestcount = 1;
|
||||
|
||||
do
|
||||
{
|
||||
input = CC_ParseToken( input );
|
||||
if ( strlen( com_token ) <= 0 )
|
||||
break;
|
||||
|
||||
if ( strlen( com_token ) == 1 )
|
||||
{
|
||||
if ( com_token[ 0 ] == pairing[ 0 ] )
|
||||
{
|
||||
nestcount++;
|
||||
}
|
||||
else if ( com_token[ 0 ] == pairing[ 1 ] )
|
||||
{
|
||||
nestcount--;
|
||||
}
|
||||
}
|
||||
} while ( nestcount != 0 );
|
||||
|
||||
return input;
|
||||
}
|
||||
29
utils/classcheck/classcheck_util.h
Normal file
29
utils/classcheck/classcheck_util.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#ifndef CLASSCHECK_UTIL_H
|
||||
#define CLASSCHECK_UTIL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
void vprint( int depth, const char *fmt, ... );
|
||||
void CC_UngetToken( void );
|
||||
char *CC_ParseToken(char *data);
|
||||
char *CC_DiscardUntilMatchingCharIncludingNesting( char *input, const char *pairing );
|
||||
char *CC_RawParseChar( char *input, const char *ch, char *breakchar );
|
||||
char *CC_ParseUntilEndOfLine( char *input );
|
||||
|
||||
extern char com_token[1024];
|
||||
extern bool com_ignoreinlinecomment;
|
||||
extern int linesprocessed;
|
||||
|
||||
unsigned char *COM_LoadFile( const char *name, int *len);
|
||||
void COM_FreeFile( unsigned char *buffer );
|
||||
bool COM_DirectoryExists( const char *dir );
|
||||
|
||||
#endif // CLASSCHECK_UTIL_H
|
||||
129
utils/classcheck/codeprocessor.h
Normal file
129
utils/classcheck/codeprocessor.h
Normal file
@@ -0,0 +1,129 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( CODEPROCESSOR_H )
|
||||
#define CODEPROCESSOR_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "class.h"
|
||||
#include "icodeprocessor.h"
|
||||
|
||||
#include "utldict.h"
|
||||
|
||||
class CCodeProcessor : public ICodeProcessor
|
||||
{
|
||||
public:
|
||||
CCodeProcessor( void );
|
||||
~CCodeProcessor( void );
|
||||
|
||||
void Process( const char *baseentityclass, const char *gamespecific, const char *sourcetreebase, const char *subdir );
|
||||
void Process( const char *baseentityclass, const char *gamespecific, const char *sourcetreebase, const char *subdir, const char *pFileName );
|
||||
CClass *AddClass( const char *classname );
|
||||
|
||||
void SetQuiet( bool quiet );
|
||||
bool GetQuiet( void ) const;
|
||||
|
||||
void SetPrintHierarchy( bool print );
|
||||
bool GetPrintHierarchy( void ) const;
|
||||
|
||||
void SetPrintMembers( bool print );
|
||||
bool GetPrintMembers( void ) const;
|
||||
|
||||
void SetPrintTDs( bool print );
|
||||
bool GetPrintTDs( void ) const;
|
||||
|
||||
void SetPrintPredTDs( bool print );
|
||||
bool GetPrintPredTDs( void ) const;
|
||||
|
||||
void SetPrintCreateMissingTDs( bool print );
|
||||
bool GetPrintCreateMissingTDs( void ) const;
|
||||
|
||||
void SetPrintCreateMissingPredTDs( bool print );
|
||||
bool GetPrintCreateMissingPredTDs( void ) const;
|
||||
|
||||
void SetLogFile( bool log );
|
||||
bool GetLogFile( void ) const;
|
||||
|
||||
void SetCheckHungarian( bool check );
|
||||
bool GetCheckHungarian() const;
|
||||
|
||||
CClass *FindClass( const char *name ) const;
|
||||
|
||||
void ResolveBaseClasses( const char *baseentityclass );
|
||||
void Clear( void );
|
||||
void PrintClassList( void ) const;
|
||||
void PrintMissingTDFields( void ) const;
|
||||
void ReportHungarianNotationErrors();
|
||||
|
||||
int Count( void ) const;
|
||||
|
||||
void SortClassList( void );
|
||||
|
||||
private:
|
||||
char *ParseTypeDescription( char *current, bool fIsMacroized );
|
||||
char *ParsePredictionTypeDescription( char *current );
|
||||
char *ParseReceiveTable( char *current );
|
||||
|
||||
void ProcessModule( bool forcequiet, int depth, int& maxdepth, int& numheaders, int& skippedfiles,
|
||||
const char *srcroot, const char *baseroot, const char *root, const char *module );
|
||||
void ProcessModules( const char *srcroot, const char *root, const char *rootmodule );
|
||||
void PrintResults( const char *baseentityclass );
|
||||
void ConstructModuleList_R( int level, const char *baseentityclass, const char *gamespecific, const char *root, char const *srcroot );
|
||||
|
||||
void AddHeader( int depth, const char *filename, const char *rootmodule );
|
||||
|
||||
bool CheckShouldSkip( bool forcequiet, int depth, char const *filename, int& numheaders, int& skippedfiles);
|
||||
bool LoadFile( char **buffer, char *filename, char const *module, bool forcequiet,
|
||||
int depth, int& filelength, int& numheaders, int& skippedfiles,
|
||||
char const *srcroot, char const *root, char const *baseroot );
|
||||
|
||||
// include file path
|
||||
void CleanupIncludePath();
|
||||
void AddIncludePath( const char *pPath );
|
||||
void SetupIncludePath( const char *sourcetreebase, const char *subdir, const char *gamespecific );
|
||||
|
||||
CClass *m_pClassList;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool skipped;
|
||||
} CODE_MODULE;
|
||||
|
||||
CUtlDict< CODE_MODULE, int > m_Modules;
|
||||
CUtlDict< CODE_MODULE, int > m_Headers;
|
||||
|
||||
CUtlVector< char * > m_IncludePath;
|
||||
|
||||
bool m_bQuiet;
|
||||
bool m_bPrintHierarchy;
|
||||
bool m_bPrintMembers;
|
||||
bool m_bPrintTypedescriptionErrors;
|
||||
bool m_bPrintPredictionDescErrors;
|
||||
bool m_bCreateMissingTDs;
|
||||
bool m_bCreateMissingPredTDs;
|
||||
bool m_bLogToFile;
|
||||
bool m_bCheckHungarian;
|
||||
|
||||
int m_nFilesProcessed;
|
||||
int m_nHeadersProcessed;
|
||||
int m_nClassesParsed;
|
||||
int m_nOffset;
|
||||
int m_nBytesProcessed;
|
||||
int m_nLinesOfCode;
|
||||
|
||||
double m_flStart;
|
||||
double m_flEnd;
|
||||
|
||||
char m_szCurrentCPP[ 128 ];
|
||||
char m_szBaseEntityClass[ 256 ];
|
||||
|
||||
};
|
||||
|
||||
extern ICodeProcessor *processor;
|
||||
|
||||
#endif // CODEPROCESSOR_H
|
||||
59
utils/classcheck/icodeprocessor.h
Normal file
59
utils/classcheck/icodeprocessor.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( ICODEPROCESSOR_H )
|
||||
#define ICODEPROCESSOR_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#pragma warning( disable : 4127 )
|
||||
|
||||
class CClass;
|
||||
|
||||
class ICodeProcessor
|
||||
{
|
||||
public:
|
||||
// Process all files in a directory
|
||||
virtual void Process( const char *baseentityclass, const char *gamespecific, const char *sourcetreebase, const char *subdir ) = 0;
|
||||
|
||||
// Process a single file
|
||||
virtual void Process( const char *baseentityclass, const char *gamespecific, const char *sourcetreebase, const char *subdir, const char *pFileName ) = 0;
|
||||
|
||||
virtual CClass *AddClass( const char *classname ) = 0;
|
||||
virtual CClass *FindClass( const char *name ) const = 0;
|
||||
|
||||
virtual void SetQuiet( bool quiet ) = 0;
|
||||
virtual bool GetQuiet( void ) const = 0;
|
||||
|
||||
virtual void SetPrintHierarchy( bool print ) = 0;
|
||||
virtual bool GetPrintHierarchy( void ) const = 0;
|
||||
|
||||
virtual void SetPrintMembers( bool print ) = 0;
|
||||
virtual bool GetPrintMembers( void ) const = 0;
|
||||
|
||||
virtual void SetPrintTDs( bool print ) = 0;
|
||||
virtual bool GetPrintTDs( void ) const = 0;
|
||||
|
||||
virtual void SetPrintPredTDs( bool print ) = 0;
|
||||
virtual bool GetPrintPredTDs( void ) const = 0;
|
||||
|
||||
virtual void SetPrintCreateMissingTDs( bool print ) = 0;
|
||||
virtual bool GetPrintCreateMissingTDs( void ) const = 0;
|
||||
|
||||
virtual void SetPrintCreateMissingPredTDs( bool print ) = 0;
|
||||
virtual bool GetPrintCreateMissingPredTDs( void ) const = 0;
|
||||
|
||||
virtual void SetLogFile( bool log ) = 0;
|
||||
virtual bool GetLogFile( void ) const = 0;
|
||||
|
||||
virtual void SetCheckHungarian( bool check ) = 0;
|
||||
virtual bool GetCheckHungarian() const = 0;
|
||||
};
|
||||
|
||||
extern ICodeProcessor *processor;
|
||||
|
||||
#endif // ICODEPROCESSOR_H
|
||||
1866
utils/classcheck/processmodule.cpp
Normal file
1866
utils/classcheck/processmodule.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
utils/classcheck/stdafx.cpp
Normal file
15
utils/classcheck/stdafx.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// classcheck.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
26
utils/classcheck/stdafx.h
Normal file
26
utils/classcheck/stdafx.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//========= Copyright 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__50E4147E_A508_4D85_BF0A_BA26676063F0__INCLUDED_)
|
||||
#define AFX_STDAFX_H__50E4147E_A508_4D85_BF0A_BA26676063F0__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__50E4147E_A508_4D85_BF0A_BA26676063F0__INCLUDED_)
|
||||
29
utils/common/ISQLDBReplyTarget.h
Normal file
29
utils/common/ISQLDBReplyTarget.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//========= Copyright 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 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 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
|
||||
5247
utils/common/bsplib.cpp
Normal file
5247
utils/common/bsplib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
407
utils/common/bsplib.h
Normal file
407
utils/common/bsplib.h
Normal file
@@ -0,0 +1,407 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BSPLIB_H
|
||||
#define BSPLIB_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "zip_utils.h"
|
||||
#include "bspfile.h"
|
||||
#include "utlvector.h"
|
||||
#include "utlstring.h"
|
||||
#include "utllinkedlist.h"
|
||||
#include "byteswap.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 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 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 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, IZip::eCompressionType compressionType = IZip::eCompressionType_None );
|
||||
void AddBufferToPak( IZip *pak, const char *pRelativeName, void *data, int length, bool bTextMode, IZip::eCompressionType compressionType = IZip::eCompressionType_None );
|
||||
void AddDirToPak( IZip *pak, const char *pDirPath, const char *pPakPrefix = NULL );
|
||||
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 );
|
||||
typedef bool (*VHVFixupFunc_t)( const char *pVhvFilename, const char *pModelName, CUtlBuffer &sourceBuf, CUtlBuffer &targetBuf );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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( dheader_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 RepackBSPCallback_LZMA( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer );
|
||||
bool RepackBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, CompressFunc_t pCompressFunc, IZip::eCompressionType packfileCompression );
|
||||
bool SwapBSPFile( const char *filename, const char *swapFilename, bool bSwapOnLoad, VTFConvertFunc_t pVTFConvertFunc, VHVFixupFunc_t pVHVFixupFunc, CompressFunc_t pCompressFunc );
|
||||
|
||||
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 );
|
||||
void WriteLumpToFile( char *filename, int lump, int nLumpVersion, void *pBuffer, size_t nBufLen );
|
||||
bool GetBSPDependants( const char *pBSPFilename, CUtlVector< CUtlString > *pList );
|
||||
void UnloadBSPFile();
|
||||
|
||||
void ParseEntities (void);
|
||||
void UnparseEntities (void);
|
||||
void PrintEntity (entity_t *ent);
|
||||
|
||||
void SetKeyValue (entity_t *ent, const char *key, const char *value);
|
||||
char *ValueForKey (entity_t *ent, char *key);
|
||||
// will return "" if not present
|
||||
int IntForKey (entity_t *ent, char *key);
|
||||
int IntForKeyWithDefault(entity_t *ent, char *key, int nDefault );
|
||||
vec_t FloatForKey (entity_t *ent, char *key);
|
||||
vec_t FloatForKeyWithDefault (entity_t *ent, char *key, float default_value);
|
||||
void GetVectorForKey (entity_t *ent, char *key, Vector& vec);
|
||||
void GetVector2DForKey (entity_t *ent, char *key, Vector2D& vec);
|
||||
void GetAnglesForKey (entity_t *ent, char *key, QAngle& vec);
|
||||
epair_t *ParseEpair (void);
|
||||
void StripTrailing (char *e);
|
||||
|
||||
// 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, int context ) = 0;
|
||||
|
||||
// call back with a leaf and a context
|
||||
virtual bool EnumerateLeaf( int leaf, Ray_t const& ray, float start, float end, int context ) = 0;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Enumerates nodes + leafs in front to back order...
|
||||
//-----------------------------------------------------------------------------
|
||||
bool EnumerateNodesAlongRay( Ray_t const& ray, IBSPNodeEnumerator* pEnum, int 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 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
|
||||
1009
utils/common/cmdlib.cpp
Normal file
1009
utils/common/cmdlib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
178
utils/common/cmdlib.h
Normal file
178
utils/common/cmdlib.h
Normal file
@@ -0,0 +1,178 @@
|
||||
//========= Copyright 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( PRINTF_FORMAT_STRING 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"
|
||||
#include "tier1/utlstring.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, PRINTF_FORMAT_STRING 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, PRINTF_FORMAT_STRING char const *pFormat, ... );
|
||||
|
||||
// Initialize spew output.
|
||||
void InstallSpewFunction();
|
||||
|
||||
// This registers an extra callback for spew output.
|
||||
typedef void (*SpewHookFn)( const char * );
|
||||
void InstallExtraSpewHook( SpewHookFn pFn );
|
||||
|
||||
// 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();
|
||||
void CmdLib_Exit( int exitCode ); // Use this to cleanup and call exit().
|
||||
|
||||
// entrypoint if chaining spew functions
|
||||
SpewRetval_t CmdLib_SpewOutputFunc( SpewType_t type, char const *pMsg );
|
||||
unsigned short SetConsoleTextColor( int red, int green, int blue, int intensity );
|
||||
void RestoreConsoleTextColor( unsigned short color );
|
||||
|
||||
// Append all spew output to the specified file.
|
||||
void SetSpewFunctionLogFile( char const *pFilename );
|
||||
|
||||
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( PRINTF_FORMAT_STRING const char *format, ... );
|
||||
|
||||
void ExpandWildcards (int *argc, char ***argv);
|
||||
|
||||
void CmdLib_AddBasePath( const char *pBasePath );
|
||||
bool CmdLib_HasBasePath( const char *pFileName, int &pathLength );
|
||||
int CmdLib_GetNumBasePaths( void );
|
||||
const char *CmdLib_GetBasePath( int i );
|
||||
// Like ExpandPath but expands the path for each base path like SafeOpenRead
|
||||
int CmdLib_ExpandWithBasePaths( CUtlVector< CUtlString > &expandedPathList, const char *pszPath );
|
||||
|
||||
extern bool g_bStopOnExit;
|
||||
|
||||
// for compression routines
|
||||
typedef struct
|
||||
{
|
||||
byte *data;
|
||||
int count;
|
||||
} cblock_t;
|
||||
|
||||
|
||||
#endif // CMDLIB_H
|
||||
333
utils/common/consolewnd.cpp
Normal file
333
utils/common/consolewnd.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
//========= Copyright 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;
|
||||
|
||||
int nLen = (int)SendMessage( m_hEditControl, EM_GETLIMITTEXT, 0, 0 );
|
||||
SendMessage( m_hEditControl, EM_SETSEL, 0, nLen );
|
||||
SendMessage( m_hEditControl, EM_REPLACESEL, FALSE, (LPARAM)"" );
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
45
utils/common/consolewnd.h
Normal file
45
utils/common/consolewnd.h
Normal file
@@ -0,0 +1,45 @@
|
||||
//========= Copyright 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.
|
||||
|
||||
// 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
|
||||
206
utils/common/filesystem_tools.cpp
Normal file
206
utils/common/filesystem_tools.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#if defined( _WIN32 ) && !defined( _X360 )
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <io.h> // _chmod
|
||||
#elif _LINUX
|
||||
#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;
|
||||
|
||||
// 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 );
|
||||
}
|
||||
59
utils/common/filesystem_tools.h
Normal file
59
utils/common/filesystem_tools.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//========= Copyright 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();
|
||||
|
||||
// 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;
|
||||
extern 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
|
||||
136
utils/common/map_shared.cpp
Normal file
136
utils/common/map_shared.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
//========= Copyright 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
|
||||
g_MapRevision = atoi( szValue );
|
||||
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 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 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_
|
||||
839
utils/common/mpi_stats.cpp
Normal file
839
utils/common/mpi_stats.cpp
Normal file
@@ -0,0 +1,839 @@
|
||||
//========= Copyright 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 );
|
||||
|
||||
|
||||
void VMPI_Stats_SpewHook( const char *pMsg )
|
||||
{
|
||||
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( pMsg ), pMsg );
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
InstallExtraSpewHook( VMPI_Stats_SpewHook );
|
||||
}
|
||||
|
||||
|
||||
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, %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 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 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 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
|
||||
);
|
||||
|
||||
63
utils/common/pacifier.cpp
Normal file
63
utils/common/pacifier.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//========= Copyright 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;
|
||||
|
||||
#define clamp(a,b,c) ( (a) > (c) ? (c) : ( (a) < (b) ? (b) : (a) ) )
|
||||
|
||||
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 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 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 );
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user