source-engine/utils/xbox/vxconsole/bug.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

1577 lines
43 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// BUG.CPP
//
// Tracker bridge
//=====================================================================================//
#include "vxconsole.h"
// two bug systems, certain games are tied to a specific system
#define BUG_REPORTER_DLLNAME_1 "bugreporter.dll"
#define BUG_REPORTER_DLLNAME_2 "bugreporter_filequeue.dll"
#define BUG_REPOSITORY_URL "\\\\fileserver\\bugs"
#define REPOSITORY_VALIDATION_FILE "info.txt"
#define BUG_ERRORTITLE "Bug Error"
#define BUG_COLOR ( RGB( 0,255,255 ) )
HWND g_bug_hWnd;
HMODULE g_bug_hBugReporter1;
HMODULE g_bug_hBugReporter2;
IBugReporter *g_bug_pReporter1;
IBugReporter *g_bug_pReporter2;
IBugReporter *g_bug_pReporter;
char g_bug_szTitle[512];
char g_bug_szDescription[1024];
char g_bug_szOwner[128];
char g_bug_szSeverity[128];
char g_bug_szReportType[128];
char g_bug_szPriority[128];
char g_bug_szArea[128];
char g_bug_szMapNumber[128];
int g_bug_GameType;
bool g_bug_bActive;
char g_bug_szScreenshot[MAX_PATH];
char g_bug_szSavegame[MAX_PATH];
char g_bug_szBSPName[MAX_PATH];
xrMapInfo_t g_bug_mapInfo;
bool g_bug_bCompressScreenshot;
bool g_bug_bFirstCommand;
struct GameSystem_t
{
const char *pFriendlyName;
const char *pGameName;
bool bUsesSystem1;
};
GameSystem_t g_Games[] =
{
{ "Half Life 2", "hl2", true },
{ "Episode 1", "episodic", true },
{ "Episode 2", "ep2", true },
{ "Portal", "portal", false },
{ "Team Fortress 2", "tf", false },
};
static const char *GetRepositoryURL( void )
{
const char *pURL = g_bug_pReporter->GetRepositoryURL();
if ( pURL )
{
return pURL;
}
return BUG_REPOSITORY_URL;
}
const char *GetSubmissionURL( int bugid )
{
const char *pURL = g_bug_pReporter->GetSubmissionURL();
if ( pURL )
{
return pURL;
}
static char url[MAX_PATH];
Q_snprintf( url, sizeof(url), "%s/%i", GetRepositoryURL(), bugid );
return url;
}
//-----------------------------------------------------------------------------
// BugReporter_SelectReporter
//
//-----------------------------------------------------------------------------
bool BugReporter_SelectReporter( const char *pGameName )
{
int system = -1;
for ( int i = 0; i < ARRAYSIZE( g_Games ); i++ )
{
if ( pGameName && !V_stricmp( g_Games[i].pGameName, pGameName ) )
{
system = i;
break;
}
}
if ( system == -1 )
{
// not found, slam to first
system = 0;
}
// games uses different systems
int oldGameType = g_bug_GameType;
g_bug_GameType = system;
if ( g_Games[system].bUsesSystem1 )
{
g_bug_pReporter = g_bug_pReporter1;
}
else
{
g_bug_pReporter = g_bug_pReporter2;
}
// force the game area
if ( g_Games[g_bug_GameType].bUsesSystem1 )
{
strcpy( g_bug_szArea, "XBOX 360" );
}
else
{
strcpy( g_bug_szArea, g_Games[g_bug_GameType].pFriendlyName );
}
bool bChanged = ( oldGameType != g_bug_GameType );
return bChanged;
}
//-----------------------------------------------------------------------------
// BugReporter_LoadDLL
//
//-----------------------------------------------------------------------------
IBugReporter *BugReporter_LoadDLL( const char *pDLLName, HMODULE *phModule )
{
HMODULE hModule;
IBugReporter *pBugReporter;
*phModule = NULL;
hModule = LoadLibrary( pDLLName );
if ( !hModule )
{
Sys_MessageBox( BUG_ERRORTITLE, "Could not open '%s'\n", pDLLName );
return NULL;
}
FARPROC pCreateInterface = GetProcAddress( hModule, CREATEINTERFACE_PROCNAME );
if ( !pCreateInterface )
{
Sys_MessageBox( BUG_ERRORTITLE, "Missing '%s' interface for '%s'\n", CREATEINTERFACE_PROCNAME, pDLLName );
return NULL;
}
pBugReporter = (IBugReporter *)((CreateInterfaceFn)pCreateInterface)( INTERFACEVERSION_BUGREPORTER, NULL );
if ( !pBugReporter )
{
Sys_MessageBox( BUG_ERRORTITLE, "Missing interface '%s' for '%s'\n", INTERFACEVERSION_BUGREPORTER, pDLLName );
return NULL;
}
bool bSuccess = pBugReporter->Init( NULL );
if ( !bSuccess )
{
return NULL;
}
*phModule = hModule;
return pBugReporter;
}
//-----------------------------------------------------------------------------
// BugReporter_GetInterfaces
//
//-----------------------------------------------------------------------------
bool BugReporter_GetInterfaces()
{
if ( !g_bug_pReporter1 )
{
g_bug_pReporter1 = BugReporter_LoadDLL( BUG_REPORTER_DLLNAME_1, &g_bug_hBugReporter1 );
if ( !g_bug_pReporter1 )
{
Sys_MessageBox( BUG_ERRORTITLE, "PVCS intialization failed!\n" );
}
}
if ( !g_bug_pReporter2 )
{
g_bug_pReporter2 = BugReporter_LoadDLL( BUG_REPORTER_DLLNAME_2, &g_bug_hBugReporter2 );
if ( !g_bug_pReporter2 )
{
Sys_MessageBox( BUG_ERRORTITLE, "BugBait intialization failed!\n" );
}
}
if ( g_bug_pReporter1 )
{
// determine submitter name
ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: PVCS Username: '%s' Display As: '%s'\n", g_bug_pReporter1->GetUserName(), g_bug_pReporter1->GetUserName_Display() );
}
if ( g_bug_pReporter2 )
{
// determine submitter name
ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: BugBait Username: '%s' Display As: '%s'\n", g_bug_pReporter2->GetUserName(), g_bug_pReporter2->GetUserName_Display() );
}
BugReporter_SelectReporter( NULL );
// See if we can see the bug repository right now
char fn[MAX_PATH];
V_snprintf( fn, sizeof( fn ), "%s/%s", GetRepositoryURL(), REPOSITORY_VALIDATION_FILE );
Sys_NormalizePath( fn, false );
FILE *fp = fopen( fn, "rb" );
if ( fp )
{
ConsoleWindowPrintf( BUG_COLOR, "PVCS Repository '%s'\n", GetRepositoryURL() );
fclose( fp );
}
else
{
Sys_MessageBox( BUG_ERRORTITLE, "Unable to see '%s', check permissions and network connectivity.\n", fn );
return false;
}
// success
return true;
}
//-----------------------------------------------------------------------------
// BugReporter_FreeInterfaces
//
//-----------------------------------------------------------------------------
void BugReporter_FreeInterfaces()
{
if ( g_bug_pReporter1 )
{
g_bug_pReporter1->Shutdown();
g_bug_pReporter1 = NULL;
FreeLibrary( g_bug_hBugReporter1 );
g_bug_hBugReporter1 = NULL;
}
if ( g_bug_pReporter2 )
{
g_bug_pReporter2->Shutdown();
g_bug_pReporter2 = NULL;
FreeLibrary( g_bug_hBugReporter2 );
g_bug_hBugReporter2 = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Expanded data destination object for CUtlBuffer output
//-----------------------------------------------------------------------------
struct JPEGDestinationManager_t
{
struct jpeg_destination_mgr pub; // public fields
CUtlBuffer *pBuffer; // target/final buffer
byte *buffer; // start of temp buffer
};
// choose an efficiently bufferaable size
#define OUTPUT_BUF_SIZE 4096
//-----------------------------------------------------------------------------
// Purpose: Initialize destination --- called by jpeg_start_compress
// before any data is actually written.
//-----------------------------------------------------------------------------
void init_destination( j_compress_ptr cinfo )
{
JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t *) cinfo->dest;
// Allocate the output buffer --- it will be released when done with image
dest->buffer = (byte *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
OUTPUT_BUF_SIZE * sizeof(byte));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
}
//-----------------------------------------------------------------------------
// Purpose: Empty the output buffer --- called whenever buffer fills up.
// Input : boolean -
//-----------------------------------------------------------------------------
boolean empty_output_buffer( j_compress_ptr cinfo )
{
JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t * ) cinfo->dest;
CUtlBuffer *buf = dest->pBuffer;
// Add some data
buf->Put( dest->buffer, OUTPUT_BUF_SIZE );
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
return TRUE;
}
//-----------------------------------------------------------------------------
// Purpose: Terminate destination --- called by jpeg_finish_compress
// after all data has been written. Usually needs to flush buffer.
//
// NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
// application must deal with any cleanup that should happen even
// for error exit.
//-----------------------------------------------------------------------------
void term_destination( j_compress_ptr cinfo )
{
JPEGDestinationManager_t *dest = (JPEGDestinationManager_t *) cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
CUtlBuffer *buf = dest->pBuffer;
/* Write any data remaining in the buffer */
if (datacount > 0)
{
buf->Put( dest->buffer, datacount );
}
}
//-----------------------------------------------------------------------------
// Purpose: Set up functions for writing data to a CUtlBuffer instead of FILE *
//-----------------------------------------------------------------------------
void jpeg_UtlBuffer_dest( j_compress_ptr cinfo, CUtlBuffer *pBuffer )
{
JPEGDestinationManager_t *dest;
/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof(JPEGDestinationManager_t));
}
dest = ( JPEGDestinationManager_t * ) cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
dest->pBuffer = pBuffer;
}
//-----------------------------------------------------------------------------
// BugDlg_CompressScreenshot
//
// Compress .BMP to .JPG, Delete .BMP
//-----------------------------------------------------------------------------
bool BugDlg_CompressScreenshot()
{
if ( !g_bug_szScreenshot[0] )
{
return false;
}
bool bSuccess = false;
HBITMAP hBitmap = NULL;
HDC hDC = NULL;
char *pBMPBits = NULL;
CUtlBuffer buf( 0, 0 );
hBitmap = (HBITMAP)LoadImage( NULL, g_bug_szScreenshot, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE );
if ( !hBitmap )
goto cleanUp;
hDC = CreateCompatibleDC( NULL );
if ( !hDC )
goto cleanUp;
BITMAPINFO bitmapInfo;
ZeroMemory( &bitmapInfo, sizeof( BITMAPINFO ) );
bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
// populate the bmp info
if ( !GetDIBits( hDC, hBitmap, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS ) )
goto cleanUp;
pBMPBits = (char *)Sys_Alloc( bitmapInfo.bmiHeader.biSizeImage );
if ( !pBMPBits )
goto cleanUp;
// could be bottom-up or top-down
int nHeight = abs( bitmapInfo.bmiHeader.biHeight );
if ( bitmapInfo.bmiHeader.biBitCount != 32 )
{
// unexpected format
goto cleanUp;
}
if ( bitmapInfo.bmiHeader.biCompression != BI_RGB && bitmapInfo.bmiHeader.biCompression != BI_BITFIELDS )
{
// unexpected format
goto cleanUp;
}
// don't want color masks
bitmapInfo.bmiHeader.biCompression = BI_RGB;
// get the raw bits
if ( !GetDIBits( hDC, hBitmap, 0, nHeight, pBMPBits, &bitmapInfo, DIB_RGB_COLORS ) )
goto cleanUp;
JSAMPROW row_pointer[1];
// compression data structure
struct jpeg_compress_struct cinfo;
ZeroMemory( &cinfo, sizeof( jpeg_compress_struct ) );
// point at stderr
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error( &jerr );
// create compressor
jpeg_create_compress( &cinfo );
// Hook CUtlBuffer to compression
jpeg_UtlBuffer_dest( &cinfo, &buf );
// image width and height, in pixels
cinfo.image_width = bitmapInfo.bmiHeader.biWidth;
cinfo.image_height = nHeight;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
// Apply settings
jpeg_set_defaults( &cinfo );
jpeg_set_quality( &cinfo, 50, TRUE );
// Start compressor
jpeg_start_compress( &cinfo, TRUE);
char *pRowBuffer = (char*)_alloca( bitmapInfo.bmiHeader.biWidth * 3 );
row_pointer[0] = (JSAMPROW)pRowBuffer;
// Write scanlines
while ( cinfo.next_scanline < cinfo.image_height )
{
char *pSrc;
if ( bitmapInfo.bmiHeader.biHeight < 0 )
{
// top down
pSrc = &pBMPBits[cinfo.next_scanline * bitmapInfo.bmiHeader.biWidth * 4];
}
else
{
// bottom up
pSrc = &pBMPBits[(nHeight-1 - cinfo.next_scanline) * bitmapInfo.bmiHeader.biWidth * 4];
}
// convert to BGR to RGB
char *pDst = pRowBuffer;
for ( int i=0; i<bitmapInfo.bmiHeader.biWidth; i++ )
{
pDst[0] = pSrc[2];
pDst[1] = pSrc[1];
pDst[2] = pSrc[0];
pSrc += 4;
pDst += 3;
}
jpeg_write_scanlines( &cinfo, row_pointer, 1 );
}
// Finalize image
jpeg_finish_compress( &cinfo );
char jpgFilename[MAX_PATH];
Sys_StripExtension( g_bug_szScreenshot, jpgFilename, sizeof( jpgFilename ) );
Sys_AddExtension( ".jpg", jpgFilename, sizeof( jpgFilename ) );
if ( !Sys_SaveFile( jpgFilename, buf.Base(), buf.TellMaxPut() ) )
goto cleanUp;
// remove the uncompressed version
unlink( g_bug_szScreenshot );
strcpy( g_bug_szScreenshot, jpgFilename );
bSuccess = true;
cleanUp:
if ( hBitmap )
DeleteObject( hBitmap );
if ( hDC )
DeleteDC( hDC );
if ( pBMPBits )
Sys_Free( pBMPBits );
return bSuccess;
}
//-----------------------------------------------------------------------------
// BugDlg_GetAppData
//
//-----------------------------------------------------------------------------
void BugDlg_GetAppData( HWND hWnd )
{
// clear stale data from previous query
memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
SetDlgItemText( hWnd, IDC_BUG_POSITION_LABEL, "" );
SetDlgItemText( hWnd, IDC_BUG_ORIENTATION_LABEL, "" );
SetDlgItemText( hWnd, IDC_BUG_MAP_LABEL, "" );
SetDlgItemText( hWnd, IDC_BUG_BUILD_LABEL, "" );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_SAVEGAME ), false );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_INCLUDEBSP ), false );
if ( g_connectedToApp )
{
// send to app, responds with position info
if ( !g_bug_bFirstCommand )
{
// first command must send pause and status to be processed correctly
g_bug_bFirstCommand = true;
ProcessCommand( "pause ; status" );
}
else
{
ProcessCommand( "status" );
}
}
}
//-----------------------------------------------------------------------------
// BugDlg_GetDataFileBase
//
//-----------------------------------------------------------------------------
void BugDlg_GetDataFileBase( char const *suffix, bool bLocalPath, char *buf, int bufsize )
{
char filepath[MAX_PATH];
char filename[MAX_PATH];
struct tm t;
time_t ltime;
time( &ltime );
tm *pTime = localtime( &ltime );
memcpy( &t, pTime, sizeof( t ) );
char who[128];
strncpy( who, suffix, sizeof( who ) );
_strlwr( who );
if ( bLocalPath )
{
// add a qualified local path
// used as a gathering store before uploading to server
strcpy( filepath, g_localPath );
Sys_AddFileSeperator( filepath, sizeof( filepath ) );
strcat( filepath, "bug/" );
Sys_NormalizePath( filepath, false );
Sys_CreatePath( filepath );
}
else
{
filepath[0] = '\0';
}
sprintf( filename, "%i_%02i_%02i_%s", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, who );
V_snprintf( buf, bufsize, "%s%s", filepath, filename );
}
//-----------------------------------------------------------------------------
// BugDlg_CheckSubmit
//
//-----------------------------------------------------------------------------
bool BugDlg_CheckSubmit( HWND hWnd )
{
bool bEnableSubmit = false;
if ( g_Games[g_bug_GameType].bUsesSystem1 )
{
if ( g_bug_szTitle[0] &&
g_bug_szDescription[0] &&
g_bug_szSeverity[0] &&
g_bug_szOwner[0] &&
g_bug_szReportType[0] &&
g_bug_szPriority[0] &&
g_bug_szArea[0] )
{
bEnableSubmit = true;
}
}
else
{
if ( g_bug_szTitle[0] &&
g_bug_szDescription[0] &&
g_bug_szSeverity[0] &&
g_bug_szOwner[0] &&
g_bug_szArea[0] &&
g_bug_szMapNumber[0] )
{
bEnableSubmit = true;
}
}
EnableWindow( GetDlgItem( hWnd, IDC_BUG_SUBMIT ), bEnableSubmit );
return bEnableSubmit;
}
//-----------------------------------------------------------------------------
// BugDlg_GetChanges
//
//-----------------------------------------------------------------------------
bool BugDlg_GetChanges( HWND hWnd )
{
int curSel;
// title
GetDlgItemText( hWnd, IDC_BUG_TITLE, g_bug_szTitle, sizeof( g_bug_szTitle ) );
// description
GetDlgItemText( hWnd, IDC_BUG_DESCRIPTION, g_bug_szDescription, sizeof( g_bug_szDescription ) );
// owner
curSel = SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_GETCURSEL, 0, 0 );
if ( curSel == CB_ERR )
{
g_bug_szOwner[0] = '\0';
}
else
{
strncpy( g_bug_szOwner, g_bug_pReporter->GetDisplayName( curSel ), sizeof( g_bug_szOwner ) );
g_bug_szOwner[sizeof( g_bug_szOwner )-1] = '\0';
if ( V_stristr( g_bug_szOwner, "unassigned" ) )
{
g_bug_szOwner[0] = '\0';
}
}
// severity
curSel = SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_GETCURSEL, 0, 0 );
if ( curSel == CB_ERR )
{
g_bug_szSeverity[0] = '\0';
}
else
{
V_strncpy( g_bug_szSeverity, g_bug_pReporter->GetSeverity( curSel ), sizeof( g_bug_szSeverity ) );
}
// report type
curSel = SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_GETCURSEL, 0, 0 );
if ( curSel == CB_ERR )
{
g_bug_szReportType[0] = '\0';
}
else
{
V_strncpy( g_bug_szReportType, g_bug_pReporter->GetReportType( curSel ), sizeof( g_bug_szReportType ) );
}
// priority
curSel = SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_GETCURSEL, 0, 0 );
if ( curSel == CB_ERR )
{
g_bug_szPriority[0] = '\0';
}
else
{
V_strncpy( g_bug_szPriority, g_bug_pReporter->GetPriority( curSel ), sizeof( g_bug_szPriority ) );
}
// area
curSel = SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_GETCURSEL, 0, 0 );
int areaIndex = 0;
if ( curSel == CB_ERR )
{
g_bug_szArea[0] = '\0';
}
else
{
V_strncpy( g_bug_szArea, g_bug_pReporter->GetArea( curSel ), sizeof( g_bug_szArea ) );
areaIndex = curSel;
}
if ( !g_Games[g_bug_GameType].bUsesSystem1 )
{
// map number
curSel = SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_GETCURSEL, 0, 0 );
if ( curSel == CB_ERR )
{
g_bug_szMapNumber[0] = '\0';
}
else
{
V_strncpy( g_bug_szMapNumber, g_bug_pReporter->GetLevel( areaIndex, curSel ), sizeof( g_bug_szMapNumber ) );
}
}
g_bug_bCompressScreenshot = ( IsDlgButtonChecked( hWnd, IDC_BUG_COMPRESS_SCREENSHOT ) != 0 );
BugDlg_CheckSubmit( hWnd );
// success
return true;
}
//-----------------------------------------------------------------------------
// BugDlg_UpdateReporter
//
//-----------------------------------------------------------------------------
bool BugDlg_UpdateReporter( HWND hWnd )
{
// game
int newGameType;
int curSel = SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_GETCURSEL, 0, 0 );
if ( curSel == CB_ERR )
{
newGameType = 0;
}
else
{
newGameType = curSel;
}
return BugReporter_SelectReporter( g_Games[newGameType].pGameName );
}
//-----------------------------------------------------------------------------
// BugDlg_Populate
//
//-----------------------------------------------------------------------------
void BugDlg_Populate( HWND hWnd )
{
int i;
int count;
int curSel;
g_bug_bActive = false;
// title
SendDlgItemMessage( hWnd, IDC_BUG_TITLE, EM_LIMITTEXT, sizeof( g_bug_szTitle )-1, 0 );
SetDlgItemText( hWnd, IDC_BUG_TITLE, g_bug_szTitle );
// description
SendDlgItemMessage( hWnd, IDC_BUG_DESCRIPTION, EM_LIMITTEXT, sizeof( g_bug_szDescription )-1, 0 );
SetDlgItemText( hWnd, IDC_BUG_DESCRIPTION, g_bug_szDescription );
// submitter
SetDlgItemText( hWnd, IDC_BUG_SUBMITTER_LABEL, g_bug_pReporter->GetUserName_Display() );
// owner
SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_RESETCONTENT, 0, 0 );
count = g_bug_pReporter->GetDisplayNameCount();
for ( i = 0; i < count; i++ )
{
SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetDisplayName( i ) );
}
if ( count )
{
curSel = SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szOwner );
if ( curSel != CB_ERR )
{
SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_SETCURSEL, curSel, 0 );
}
}
// severity
SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_RESETCONTENT, 0, 0 );
count = g_bug_pReporter->GetSeverityCount();
for ( i = 0; i < count; i++ )
{
SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetSeverity( i ) );
}
if ( count )
{
curSel = SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szSeverity );
if ( curSel != CB_ERR )
{
SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_SETCURSEL, curSel, 0 );
}
}
// report type
SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_RESETCONTENT, 0, 0 );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_REPORTTYPE ), g_Games[g_bug_GameType].bUsesSystem1 );
if ( g_Games[g_bug_GameType].bUsesSystem1 )
{
count = g_bug_pReporter->GetReportTypeCount();
for ( i = 0; i < count; i++ )
{
SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetReportType( i ) );
}
if ( count )
{
curSel = SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szReportType );
if ( curSel != CB_ERR )
{
SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_SETCURSEL, curSel, 0 );
}
}
}
// priority
SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_RESETCONTENT, 0, 0 );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_PRIORITY ), g_Games[g_bug_GameType].bUsesSystem1 );
if ( g_Games[g_bug_GameType].bUsesSystem1 )
{
count = g_bug_pReporter->GetPriorityCount();
for ( i = 0; i < count; i++ )
{
SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetPriority( i ) );
}
if ( count )
{
curSel = SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szPriority );
if ( curSel != CB_ERR )
{
SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_SETCURSEL, curSel, 0 );
}
}
}
// area
SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_RESETCONTENT, 0, 0 );
count = g_bug_pReporter->GetAreaCount();
int areaIndex = 0;
for ( i = 0; i < count; i++ )
{
SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetArea( i ) );
}
if ( count )
{
curSel = SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szArea );
if ( curSel != CB_ERR )
{
SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_SETCURSEL, curSel, 0 );
areaIndex = curSel;
}
}
// map name or number
SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_RESETCONTENT, 0, 0 );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_MAPNUMBER ), g_Games[g_bug_GameType].bUsesSystem1 == false );
if ( !g_Games[g_bug_GameType].bUsesSystem1 )
{
// new system has map names
count = g_bug_pReporter->GetLevelCount( areaIndex );
for ( i = 0; i < count; i++ )
{
SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetLevel( areaIndex, i ) );
}
}
if ( count )
{
curSel = SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szMapNumber );
if ( curSel != CB_ERR )
{
SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_SETCURSEL, curSel, 0 );
}
}
// game
SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_RESETCONTENT, 0, 0 );
count = ARRAYSIZE( g_Games );
for ( i = 0; i < count; i++ )
{
SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_Games[i].pFriendlyName );
}
if ( count )
{
curSel = SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_Games[g_bug_GameType].pFriendlyName );
if ( curSel != CB_ERR )
{
SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_SETCURSEL, curSel, 0 );
}
}
CheckDlgButton( hWnd, IDC_BUG_COMPRESS_SCREENSHOT, g_bug_bCompressScreenshot ? BST_CHECKED : BST_UNCHECKED );
SetDlgItemText( hWnd, IDC_BUG_TAKESHOT_LABEL, g_bug_szScreenshot );
SetDlgItemText( hWnd, IDC_BUG_SAVEGAME_LABEL, g_bug_szSavegame );
SetDlgItemText( hWnd, IDC_BUG_INCLUDEBSP_LABEL, g_bug_szBSPName );
SetDlgItemText( hWnd, IDC_BUG_INCLUDEVMF_LABEL, "" );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_TAKESHOT ), g_connectedToApp );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_INCLUDEVMF ), false );
EnableWindow( GetDlgItem( hWnd, IDC_BUG_UPDATE ), g_connectedToApp );
BugDlg_GetAppData( hWnd );
BugDlg_CheckSubmit( hWnd );
g_bug_bActive = true;
}
//-----------------------------------------------------------------------------
// BugDlg_TakeScreenshot
//
//-----------------------------------------------------------------------------
void BugDlg_TakeScreenshot( HWND hWnd )
{
char buff[1024];
SetDlgItemText( hWnd, IDC_BUG_TAKESHOT_LABEL, "Working..." );
BugDlg_GetDataFileBase( g_bug_pReporter->GetUserName(), true, g_bug_szScreenshot, sizeof( g_bug_szScreenshot ) );
strcat( g_bug_szScreenshot, ".bmp" );
// remove local version
unlink( g_bug_szScreenshot );
sprintf( buff, "*screenshot \"%s\"", g_bug_szScreenshot );
if ( !ProcessCommand( buff ) )
{
g_bug_szScreenshot[0] = '\0';
}
SetDlgItemText( hWnd, IDC_BUG_TAKESHOT_LABEL, g_bug_szScreenshot );
}
//-----------------------------------------------------------------------------
// BugDlg_SaveGame
//
//-----------------------------------------------------------------------------
void BugDlg_SaveGame( HWND hWnd )
{
char buff[1024];
char savename[MAX_PATH];
char remoteFile[MAX_PATH];
if ( !g_bug_mapInfo.savePath[0] )
{
return;
}
SetDlgItemText( hWnd, IDC_BUG_SAVEGAME_LABEL, "Working..." );
BugDlg_GetDataFileBase( g_bug_pReporter->GetUserName(), true, g_bug_szSavegame, sizeof( g_bug_szSavegame ) );
Sys_StripPath( g_bug_szSavegame, savename, sizeof( savename ) );
strcat( g_bug_szSavegame, ".360.sav" );
sprintf( remoteFile, "%s\\%s.360.sav", g_bug_mapInfo.savePath, savename );
// delete file locally
unlink( g_bug_szSavegame );
// delete file remotely
DmDeleteFile( remoteFile, false );
// save, and wait to ensure async completes
sprintf( buff, "save \"%s\" notmostrecent wait", savename );
if ( !ProcessCommand( buff ) )
{
// failed
g_bug_szSavegame[0] = '\0';
}
else
{
DM_FILE_ATTRIBUTES fileAttributes;
for (int i=0; i<5; i++)
{
// wait for the save file to appear
HRESULT hr = DmGetFileAttributes( remoteFile, &fileAttributes );
if ( hr == XBDM_NOERR )
break;
// wait for it
Sleep( 1000 );
}
HRESULT hr = DmReceiveFile( g_bug_szSavegame, remoteFile );
if ( hr != XBDM_NOERR )
{
// failed
g_bug_szSavegame[0] = '\0';
}
}
SetDlgItemText( hWnd, IDC_BUG_SAVEGAME_LABEL, g_bug_szSavegame );
}
//-----------------------------------------------------------------------------
// BugDlg_IncludeBSP
//
//-----------------------------------------------------------------------------
void BugDlg_IncludeBSP( HWND hWnd )
{
if ( !g_bug_mapInfo.mapPath[0] )
{
return;
}
SetDlgItemText( hWnd, IDC_BUG_INCLUDEBSP_LABEL, "Working..." );
BugDlg_GetDataFileBase( g_bug_pReporter->GetUserName(), true, g_bug_szBSPName, sizeof( g_bug_szBSPName ) );
strcat( g_bug_szBSPName, ".360.bsp" );
// remove local version
unlink( g_bug_szBSPName );
// get the file locally
HRESULT hr = DmReceiveFile( g_bug_szBSPName, g_bug_mapInfo.mapPath );
if ( hr != XBDM_NOERR )
{
// failed
g_bug_szBSPName[0] = '\0';
}
SetDlgItemText( hWnd, IDC_BUG_INCLUDEBSP_LABEL, g_bug_szBSPName );
}
//-----------------------------------------------------------------------------
// BugDlg_ResetAndPopulate
//
//-----------------------------------------------------------------------------
void BugDlg_ResetAndPopulate( HWND hWnd, bool bFullReset = true )
{
// reset all fields
if ( bFullReset )
{
g_bug_szTitle[0] = '\0';
g_bug_szDescription[0] = '\0';
}
g_bug_szOwner[0] = '\0';
g_bug_szSeverity[0] = '\0';
g_bug_szReportType[0] = '\0';
g_bug_szPriority[0] = '\0';
g_bug_szMapNumber[0] = '\0';
if ( bFullReset )
{
g_bug_szScreenshot[0] = '\0';
g_bug_szSavegame[0] = '\0';
g_bug_szBSPName[0] = '\0';
}
g_bug_bCompressScreenshot = true;
memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
// populate with reset fields
BugDlg_Populate( hWnd );
}
//-----------------------------------------------------------------------------
// BugDlg_Setup
//
//-----------------------------------------------------------------------------
void BugDlg_Setup( HWND hWnd )
{
g_bug_hWnd = hWnd;
// clear stale data from app
g_bug_bFirstCommand = false;
memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
// always reset these fields
g_bug_szTitle[0] = '\0';
g_bug_szDescription[0] = '\0';
g_bug_szScreenshot[0] = '\0';
g_bug_szSavegame[0] = '\0';
g_bug_szBSPName[0] = '\0';
g_bug_bCompressScreenshot = true;
memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
BugDlg_Populate( hWnd );
}
//-----------------------------------------------------------------------------
// BugDlg_UploadFile
//
//-----------------------------------------------------------------------------
bool BugDlg_UploadFile( char const *pLocalName, char const *pRemoteName, bool bDeleteLocal )
{
FILE *fp;
int len;
void *pLocalData;
ConsoleWindowPrintf( BUG_COLOR, "Uploading %s to %s\n", pLocalName, pRemoteName );
len = Sys_LoadFile( pLocalName, &pLocalData );
if ( !pLocalData || !len )
{
ConsoleWindowPrintf( XBX_CLR_RED, "UploadFile: Unable to open local path '%s'\n", pLocalName );
return false;
}
Sys_CreatePath( pRemoteName );
fp = fopen( pRemoteName, "wb" );
if ( !fp )
{
ConsoleWindowPrintf( XBX_CLR_RED, "UploadFile: Unable to open remote path '%s'\n", pRemoteName );
Sys_Free( pLocalData );
return false;
}
fwrite( pLocalData, len, 1, fp );
fclose( fp );
Sys_Free( pLocalData );
if ( bDeleteLocal )
{
unlink( pLocalName );
}
return true;
}
//-----------------------------------------------------------------------------
// BugDlg_UploadBugSubmission
//
// Expects fully qualified source paths
//-----------------------------------------------------------------------------
bool BugDlg_UploadBugSubmission( int bugID, char const *pSavefile, char const *pScreenshot, char const *pBspFile, char const *pVmfFile )
{
char szFilename[MAX_PATH];
char szLocalfile[MAX_PATH];
char szRemotefile[MAX_PATH];
bool bSuccess = true;
if ( pSavefile && pSavefile[0] )
{
V_snprintf( szLocalfile, sizeof( szLocalfile ), "%s", pSavefile );
Sys_StripPath( pSavefile, szFilename, sizeof( szFilename ) );
V_snprintf( szRemotefile, sizeof( szRemotefile ), "%s/%s", GetSubmissionURL( bugID ), szFilename );
Sys_NormalizePath( szLocalfile, false );
Sys_NormalizePath( szRemotefile, false );
if ( !BugDlg_UploadFile( szLocalfile, szRemotefile, false ) )
{
bSuccess = false;
}
}
if ( pScreenshot && pScreenshot[0] )
{
V_snprintf( szLocalfile, sizeof( szLocalfile ), "%s", pScreenshot );
Sys_StripPath( pScreenshot, szFilename, sizeof( szFilename ) );
V_snprintf( szRemotefile, sizeof( szRemotefile ), "%s/%s", GetSubmissionURL( bugID ), szFilename );
Sys_NormalizePath( szLocalfile, false );
Sys_NormalizePath( szRemotefile, false );
if ( !BugDlg_UploadFile( szLocalfile, szRemotefile, true ) )
{
bSuccess = false;
}
}
if ( pBspFile && pBspFile[0] )
{
V_snprintf( szLocalfile, sizeof( szLocalfile ), "%s", pBspFile );
Sys_StripPath( pBspFile, szFilename, sizeof( szFilename ) );
V_snprintf( szRemotefile, sizeof( szRemotefile ), "%s/%s", GetSubmissionURL( bugID ), szFilename );
Sys_NormalizePath( szLocalfile, false );
Sys_NormalizePath( szRemotefile, false );
if ( !BugDlg_UploadFile( szLocalfile, szRemotefile, true ) )
{
bSuccess = false;
}
}
return bSuccess;
}
//-----------------------------------------------------------------------------
// BugDlg_Submit
//
//-----------------------------------------------------------------------------
bool BugDlg_Submit( HWND hWnd )
{
char title[1024];
char miscInfo[1024];
char basename[MAX_PATH];
char filename[MAX_PATH];
char positionName[MAX_PATH];
char orientationName[MAX_PATH];
char buildName[MAX_PATH];
char mapName[MAX_PATH];
bool bSuccess = false;
sprintf( positionName, "%f %f %f", g_bug_mapInfo.position[0], g_bug_mapInfo.position[1], g_bug_mapInfo.position[2] );
SetDlgItemText( g_bug_hWnd, IDC_BUG_POSITION_LABEL, positionName );
sprintf( orientationName, "%f %f %f", g_bug_mapInfo.angle[0], g_bug_mapInfo.angle[1], g_bug_mapInfo.angle[2] );
SetDlgItemText( g_bug_hWnd, IDC_BUG_ORIENTATION_LABEL, orientationName );
sprintf( buildName, "%d", g_bug_mapInfo.build );
SetDlgItemText( g_bug_hWnd, IDC_BUG_BUILD_LABEL, buildName );
V_FileBase( g_bug_mapInfo.mapPath, mapName, sizeof( mapName ) );
char *pExtension = V_stristr( mapName, ".bsp" );
if ( pExtension )
{
*pExtension = '\0';
}
pExtension = V_stristr( mapName, ".360" );
if ( pExtension )
{
*pExtension = '\0';
}
V_snprintf( miscInfo, sizeof( miscInfo ), "skill %d", g_bug_mapInfo.skill );
// Stuff bug data files up to server
g_bug_pReporter->StartNewBugReport();
g_bug_pReporter->SetOwner( g_bug_pReporter->GetUserNameForDisplayName( g_bug_szOwner ) );
g_bug_pReporter->SetSubmitter( NULL );
if ( mapName[0] )
V_snprintf( title, sizeof( title ), "%s: %s", mapName, g_bug_szTitle );
else
V_snprintf( title, sizeof( title ), "%s", g_bug_szTitle );
g_bug_pReporter->SetTitle( title );
g_bug_pReporter->SetDescription( g_bug_szDescription );
g_bug_pReporter->SetLevel( mapName );
g_bug_pReporter->SetPosition( positionName );
g_bug_pReporter->SetOrientation( orientationName );
g_bug_pReporter->SetBuildNumber( buildName );
g_bug_pReporter->SetSeverity( g_bug_szSeverity );
g_bug_pReporter->SetPriority( g_bug_szPriority );
g_bug_pReporter->SetArea( g_bug_szArea );
g_bug_pReporter->SetMapNumber( g_bug_szMapNumber );
g_bug_pReporter->SetReportType( g_bug_szReportType );
g_bug_pReporter->SetMiscInfo( miscInfo );
g_bug_pReporter->SetDriverInfo( "" );
g_bug_pReporter->SetExeName( "" );
g_bug_pReporter->SetGameDirectory( "" );
g_bug_pReporter->SetRAM( 0 );
g_bug_pReporter->SetCPU( 0 );
g_bug_pReporter->SetProcessor( "" );
g_bug_pReporter->SetDXVersion( 0, 0, 0, 0 );
g_bug_pReporter->SetOSVersion( "" );
g_bug_pReporter->ResetIncludedFiles();
g_bug_pReporter->SetZipAttachmentName( "" );
if ( g_bug_szScreenshot[0] )
{
if ( g_bug_bCompressScreenshot )
{
BugDlg_CompressScreenshot();
}
// strip the fully qualified path into filename only
Sys_StripPath( g_bug_szScreenshot, basename, sizeof( basename ) );
V_snprintf( filename, sizeof( filename ), "%s/BugId/%s", GetRepositoryURL(), basename );
Sys_NormalizePath( filename, false );
g_bug_pReporter->SetScreenShot( filename );
}
if ( g_bug_szSavegame[0] )
{
// strip the fully qualified path into filename only
Sys_StripPath( g_bug_szSavegame, basename, sizeof( basename ) );
V_snprintf( filename, sizeof( filename ), "%s/BugId/%s", GetRepositoryURL(), basename );
Sys_NormalizePath( filename, false );
g_bug_pReporter->SetSaveGame( filename );
}
if ( g_bug_szBSPName[0] )
{
// strip the fully qualified path into filename only
Sys_StripPath( g_bug_szBSPName, basename, sizeof( basename ) );
V_snprintf( filename, sizeof( filename ), "%s/BugId/%s", GetRepositoryURL(), basename );
Sys_NormalizePath( filename, false );
g_bug_pReporter->SetBSPName( filename );
}
int bugID = -1;
bSuccess = g_bug_pReporter->CommitBugReport( bugID );
if ( bSuccess )
{
if ( !BugDlg_UploadBugSubmission( bugID, g_bug_szSavegame, g_bug_szScreenshot, g_bug_szBSPName, NULL ) )
{
Sys_MessageBox( BUG_ERRORTITLE, "Unable to upload files to bug repository!\n" );
bSuccess = false;
}
}
else
{
Sys_MessageBox( BUG_ERRORTITLE, "Unable to post bug report to database!\n" );
}
if ( bSuccess )
{
if ( g_Games[g_bug_GameType].bUsesSystem1 )
{
ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: PVCS submission succeeded for bug! (%d)\n", bugID );
}
else
{
ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: BugBait submission succeeded for bug!\n" );
}
}
else
{
ConsoleWindowPrintf( XBX_CLR_RED, "Bug Reporter: Submission failed\n" );
}
return bSuccess;
}
//-----------------------------------------------------------------------------
// BugDlg_Proc
//
//-----------------------------------------------------------------------------
BOOL CALLBACK BugDlg_Proc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_INITDIALOG:
BugDlg_Setup( hwnd );
return ( TRUE );
case WM_COMMAND:
switch ( LOWORD( wParam ) )
{
case IDC_BUG_TAKESHOT:
BugDlg_TakeScreenshot( hwnd );
break;
case IDC_BUG_SAVEGAME:
BugDlg_SaveGame( hwnd );
break;
case IDC_BUG_INCLUDEBSP:
BugDlg_IncludeBSP( hwnd );
break;
case IDC_BUG_INCLUDEVMF:
// not implemented, no reason to
break;
case IDC_BUG_CLEARFORM:
BugDlg_ResetAndPopulate( hwnd );
return TRUE;
case IDC_BUG_UPDATE:
BugDlg_GetAppData( hwnd );
return TRUE;
case IDC_BUG_OWNER:
case IDC_BUG_SEVERITY:
case IDC_BUG_REPORTTYPE:
case IDC_BUG_PRIORITY:
case IDC_BUG_AREA:
case IDC_BUG_MAPNUMBER:
if ( g_bug_bActive && HIWORD( wParam ) == CBN_CLOSEUP )
{
BugDlg_GetChanges( hwnd );
return TRUE;
}
break;
case IDC_BUG_GAME:
if ( HIWORD( wParam ) == CBN_CLOSEUP )
{
if ( BugDlg_UpdateReporter( hwnd ) )
{
// reporter changed, clear critical parts of form
BugDlg_ResetAndPopulate( hwnd, false );
}
return TRUE;
}
break;
case IDC_BUG_TITLE:
case IDC_BUG_DESCRIPTION:
if ( g_bug_bActive && HIWORD( wParam ) == EN_CHANGE )
{
BugDlg_GetChanges( hwnd );
return TRUE;
}
break;
case IDC_BUG_COMPRESS_SCREENSHOT:
BugDlg_GetChanges( hwnd );
return TRUE;
case IDC_BUG_SUBMIT:
if ( !BugDlg_Submit( hwnd ) )
break;
// fall through
case IDCANCEL:
case IDC_CANCEL:
if ( g_connectedToApp && g_bug_bFirstCommand )
{
ProcessCommand( "unpause" );
}
EndDialog( hwnd, wParam );
return ( TRUE );
}
break;
}
return ( FALSE );
}
//-----------------------------------------------------------------------------
// BugDlg_SaveConfig
//
//-----------------------------------------------------------------------------
void BugDlg_SaveConfig()
{
Sys_SetRegistryString( "bug_owner", g_bug_szOwner );
Sys_SetRegistryString( "bug_severity", g_bug_szSeverity );
Sys_SetRegistryString( "bug_reporttype", g_bug_szReportType );
Sys_SetRegistryString( "bug_priority", g_bug_szPriority );
Sys_SetRegistryInteger( "bug_gametype", g_bug_GameType );
}
//-----------------------------------------------------------------------------
// BugDlg_LoadConfig
//
//-----------------------------------------------------------------------------
void BugDlg_LoadConfig()
{
// get our config
Sys_GetRegistryString( "bug_owner", g_bug_szOwner, "", sizeof( g_bug_szOwner ) );
Sys_GetRegistryString( "bug_severity", g_bug_szSeverity, "", sizeof( g_bug_szSeverity ) );
Sys_GetRegistryString( "bug_reporttype", g_bug_szReportType, "", sizeof( g_bug_szReportType ) );
Sys_GetRegistryString( "bug_priority", g_bug_szPriority, "", sizeof( g_bug_szPriority ) );
Sys_GetRegistryInteger( "bug_gametype", 0, g_bug_GameType );
// start with expected reporter
BugReporter_SelectReporter( g_Games[g_bug_GameType].pGameName );
}
//-----------------------------------------------------------------------------
// BugDlg_Open
//
//-----------------------------------------------------------------------------
void BugDlg_Open( void )
{
int result;
// need access to bug databases via DLLs
if ( !BugReporter_GetInterfaces() )
{
return;
}
BugDlg_LoadConfig();
result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_BUG ), g_hDlgMain, ( DLGPROC )BugDlg_Proc );
if ( LOWORD( result ) == IDC_BUG_SUBMIT )
{
BugDlg_SaveConfig();
}
g_bug_hWnd = NULL;
}
//-----------------------------------------------------------------------------
// BugDlg_Init
//
//-----------------------------------------------------------------------------
bool BugDlg_Init()
{
return true;
}
//-----------------------------------------------------------------------------
// rc_MapInfo
//
// Sent from application with bug dialog info
//-----------------------------------------------------------------------------
int rc_MapInfo( char* commandPtr )
{
char* cmdToken;
int errCode;
int infoAddr;
int retVal;
int retAddr;
char buff[128];
// success
errCode = 0;
// get address of data
cmdToken = GetToken( &commandPtr );
if ( !cmdToken[0] )
goto cleanUp;
sscanf( cmdToken, "%x", &infoAddr );
// get retAddr
cmdToken = GetToken( &commandPtr );
if ( !cmdToken[0] )
goto cleanUp;
sscanf( cmdToken, "%x", &retAddr );
// get the caller's info data
DmGetMemory( ( void* )infoAddr, sizeof( xrMapInfo_t ), &g_bug_mapInfo, NULL );
// swap the structure
BigFloat( &g_bug_mapInfo.position[0], &g_bug_mapInfo.position[0] );
BigFloat( &g_bug_mapInfo.position[1], &g_bug_mapInfo.position[1] );
BigFloat( &g_bug_mapInfo.position[2], &g_bug_mapInfo.position[2] );
BigFloat( &g_bug_mapInfo.angle[0], &g_bug_mapInfo.angle[0] );
BigFloat( &g_bug_mapInfo.angle[1], &g_bug_mapInfo.angle[1] );
BigFloat( &g_bug_mapInfo.angle[2], &g_bug_mapInfo.angle[2] );
g_bug_mapInfo.build = BigDWord( g_bug_mapInfo.build );
g_bug_mapInfo.skill = BigDWord( g_bug_mapInfo.skill );
Sys_NormalizePath( g_bug_mapInfo.savePath, false );
Sys_NormalizePath( g_bug_mapInfo.mapPath, false );
if ( g_bug_hWnd )
{
if ( g_bug_mapInfo.mapPath[0] )
{
Sys_StripPath( g_bug_mapInfo.mapPath, buff, sizeof( buff ) );
SetDlgItemText( g_bug_hWnd, IDC_BUG_MAP_LABEL, buff );
if ( !g_Games[g_bug_GameType].bUsesSystem1 )
{
char *pExtension = V_stristr( buff, ".bsp" );
if ( pExtension )
{
*pExtension = '\0';
}
pExtension = V_stristr( buff, ".360" );
if ( pExtension )
{
*pExtension = '\0';
}
V_strncpy( g_bug_szMapNumber, buff, sizeof( g_bug_szMapNumber ) );
int curSel = SendDlgItemMessage( g_bug_hWnd, IDC_BUG_MAPNUMBER, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szMapNumber );
if ( curSel == CB_ERR )
curSel = 0;
SendDlgItemMessage( g_bug_hWnd, IDC_BUG_MAPNUMBER, CB_SETCURSEL, curSel, 0 );
}
sprintf( buff, "%.2f %.2f %.2f", g_bug_mapInfo.position[0], g_bug_mapInfo.position[1], g_bug_mapInfo.position[2] );
SetDlgItemText( g_bug_hWnd, IDC_BUG_POSITION_LABEL, buff );
sprintf( buff, "%.2f %.2f %.2f", g_bug_mapInfo.angle[0], g_bug_mapInfo.angle[1], g_bug_mapInfo.angle[2] );
SetDlgItemText( g_bug_hWnd, IDC_BUG_ORIENTATION_LABEL, buff );
}
else
{
SetDlgItemText( g_bug_hWnd, IDC_BUG_MAP_LABEL, "" );
SetDlgItemText( g_bug_hWnd, IDC_BUG_POSITION_LABEL, "" );
SetDlgItemText( g_bug_hWnd, IDC_BUG_ORIENTATION_LABEL, "" );
}
sprintf( buff, "%d", g_bug_mapInfo.build );
SetDlgItemText( g_bug_hWnd, IDC_BUG_BUILD_LABEL, buff );
EnableWindow( GetDlgItem( g_bug_hWnd, IDC_BUG_SAVEGAME ), g_bug_mapInfo.savePath[0] != '\0' && g_bug_mapInfo.mapPath[0] != '\0' );
EnableWindow( GetDlgItem( g_bug_hWnd, IDC_BUG_INCLUDEBSP ), g_bug_mapInfo.mapPath[0] != '\0' );
}
// return the result
retVal = 0;
int xboxRetVal = BigDWord( retVal );
DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
DebugCommand( "0x%8.8x = MapInfo( 0x%8.8x )\n", retVal, infoAddr );
cleanUp:
return errCode;
}