This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

View 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;

View 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_)

View File

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

View 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 );

View 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_)

View 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"

View 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_)

View 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
}
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,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

View 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();
}

View 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

View 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
View 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;
}

View 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"
}
}

View 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"
}

View 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"

View 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_)

View 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;
}

View 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_)

View 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

View 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 &quot;$(TargetPath)&quot; ..\..\..\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 &quot;$(TargetPath)&quot; ..\..\..\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>

View 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 );
}

View 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_)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View 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...
/////////////////////////////////////////////////////////////////////////////

View 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

View 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
}
}

View 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);
}

View 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;
}

View 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>

View 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

View 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
View 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
View 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"
}
}

View File

@@ -0,0 +1,3 @@
LIBRARY bsppack_360.dll
EXPORTS
CreateInterface @1

552
utils/bspzip/bspzip.cpp Normal file
View 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
View 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"
}
}

File diff suppressed because it is too large Load Diff

View 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"
}
}

View 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 );

View 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]
}
}

View 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 );

View 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
}
}

View 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( &params, 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;
}

View 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 );

View 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"
}
}

View 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

View 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_)

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

2108
utils/bzip2/bzip2.c Normal file

File diff suppressed because it is too large Load Diff

40
utils/bzip2/bzip2.vpc Normal file
View 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

File diff suppressed because it is too large Load Diff

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

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

558
utils/bzip2/bzlib_private.h Normal file
View 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
View File

@@ -0,0 +1,714 @@
/*-------------------------------------------------------------*/
/*--- Compression machinery (not incl block sorting) ---*/
/*--- compress.c ---*/
/*-------------------------------------------------------------*/
/*--
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@acm.org
bzip2/libbzip2 version 1.0 of 21 March 2000
This program is based on (at least) the work of:
Mike Burrows
David Wheeler
Peter Fenwick
Alistair Moffat
Radford Neal
Ian H. Witten
Robert Sedgewick
Jon L. Bentley
For more information on these sources, see the manual.
--*/
/*--
CHANGES
~~~~~~~
0.9.0 -- original version.
0.9.0a/b -- no changes in this file.
0.9.0c
* changed setting of nGroups in sendMTFValues() so as to
do a bit better on small files
--*/
#include "bzlib_private.h"
/*---------------------------------------------------*/
/*--- Bit stream I/O ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
void BZ2_bsInitWrite ( EState* s )
{
s->bsLive = 0;
s->bsBuff = 0;
}
/*---------------------------------------------------*/
static
void bsFinishWrite ( EState* s )
{
while (s->bsLive > 0) {
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
s->numZ++;
s->bsBuff <<= 8;
s->bsLive -= 8;
}
}
/*---------------------------------------------------*/
#define bsNEEDW(nz) \
{ \
while (s->bsLive >= 8) { \
s->zbits[s->numZ] \
= (UChar)(s->bsBuff >> 24); \
s->numZ++; \
s->bsBuff <<= 8; \
s->bsLive -= 8; \
} \
}
/*---------------------------------------------------*/
static
__inline__
void bsW ( EState* s, Int32 n, UInt32 v )
{
bsNEEDW ( n );
s->bsBuff |= (v << (32 - s->bsLive - n));
s->bsLive += n;
}
/*---------------------------------------------------*/
static
void bsPutUInt32 ( EState* s, UInt32 u )
{
bsW ( s, 8, (u >> 24) & 0xffL );
bsW ( s, 8, (u >> 16) & 0xffL );
bsW ( s, 8, (u >> 8) & 0xffL );
bsW ( s, 8, u & 0xffL );
}
/*---------------------------------------------------*/
static
void bsPutUChar ( EState* s, UChar c )
{
bsW( s, 8, (UInt32)c );
}
/*---------------------------------------------------*/
/*--- The back end proper ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
static
void makeMaps_e ( EState* s )
{
Int32 i;
s->nInUse = 0;
for (i = 0; i < 256; i++)
if (s->inUse[i]) {
s->unseqToSeq[i] = s->nInUse;
s->nInUse++;
}
}
/*---------------------------------------------------*/
static
void generateMTFValues ( EState* s )
{
UChar yy[256];
Int32 i, j;
Int32 zPend;
Int32 wr;
Int32 EOB;
/*
After sorting (eg, here),
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
and
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
holds the original block data.
The first thing to do is generate the MTF values,
and put them in
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
Because there are strictly fewer or equal MTF values
than block values, ptr values in this area are overwritten
with MTF values only when they are no longer needed.
The final compressed bitstream is generated into the
area starting at
(UChar*) (&((UChar*)s->arr2)[s->nblock])
These storage aliases are set up in bzCompressInit(),
except for the last one, which is arranged in
compressBlock().
*/
UInt32* ptr = s->ptr;
UChar* block = s->block;
UInt16* mtfv = s->mtfv;
makeMaps_e ( s );
EOB = s->nInUse+1;
for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
wr = 0;
zPend = 0;
for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
for (i = 0; i < s->nblock; i++) {
UChar ll_i;
AssertD ( wr <= i, "generateMTFValues(1)" );
j = ptr[i]-1; if (j < 0) j += s->nblock;
ll_i = s->unseqToSeq[block[j]];
AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
if (yy[0] == ll_i) {
zPend++;
} else {
if (zPend > 0) {
zPend--;
while (True) {
if (zPend & 1) {
mtfv[wr] = BZ_RUNB; wr++;
s->mtfFreq[BZ_RUNB]++;
} else {
mtfv[wr] = BZ_RUNA; wr++;
s->mtfFreq[BZ_RUNA]++;
}
if (zPend < 2) break;
zPend = (zPend - 2) / 2;
};
zPend = 0;
}
{
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
View File

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

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

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

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

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

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

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

View 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 )

View 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
}
}

View 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

File diff suppressed because it is too large Load Diff

196
utils/classcheck/class.h Normal file
View 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

View 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;
}

View 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"
}
}

View 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;
}

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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
View 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_)

View 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

View 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();
}

View 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

File diff suppressed because it is too large Load Diff

407
utils/common/bsplib.h Normal file
View 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

File diff suppressed because it is too large Load Diff

178
utils/common/cmdlib.h Normal file
View 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
View 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
View 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

View 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 );
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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