You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1576 lines
43 KiB
1576 lines
43 KiB
//========= 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( <ime ); |
|
tm *pTime = localtime( <ime ); |
|
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; |
|
} |
|
|
|
|