summaryrefslogtreecommitdiff
path: root/devtools/bin
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /devtools/bin
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'devtools/bin')
-rw-r--r--devtools/bin/IntegrateOpenVR.bat77
-rw-r--r--devtools/bin/IntegratePanorama.bat85
-rw-r--r--devtools/bin/IntegrateSteamNetworkingSocketsSDK.bat34
-rw-r--r--devtools/bin/LicenseViewed.dllbin0 -> 45056 bytes
-rw-r--r--devtools/bin/McCopy.pl1321
-rw-r--r--devtools/bin/UpdateProgress.exebin0 -> 45056 bytes
-rw-r--r--devtools/bin/VProject.exebin0 -> 77824 bytes
-rw-r--r--devtools/bin/build_sdk_vcproj.py11
-rw-r--r--devtools/bin/buildshaderlist.pl22
-rw-r--r--devtools/bin/buildtest.pl83
-rw-r--r--devtools/bin/check_gcc_compile.pl23
-rw-r--r--devtools/bin/checkin.pl660
-rw-r--r--devtools/bin/checkshaderchecksums.pl116
-rw-r--r--devtools/bin/copyshaderincfiles.pl86
-rw-r--r--devtools/bin/copyshaders.pl172
-rw-r--r--devtools/bin/crc32filewithincludes.pl41
-rw-r--r--devtools/bin/d3dx10_33.dllbin0 -> 443752 bytes
-rw-r--r--devtools/bin/d3dx9_33.dllbin0 -> 3495784 bytes
-rw-r--r--devtools/bin/dbmon.exebin0 -> 100352 bytes
-rw-r--r--devtools/bin/diff.exebin0 -> 68096 bytes
-rw-r--r--devtools/bin/diff3.exebin0 -> 49664 bytes
-rw-r--r--devtools/bin/diffmemstats.exebin0 -> 172032 bytes
-rw-r--r--devtools/bin/ezxmlfile.py175
-rw-r--r--devtools/bin/fix_particle_operator_names.pl110
-rw-r--r--devtools/bin/fixcopyrights.py177
-rw-r--r--devtools/bin/fontmaker.exebin0 -> 339968 bytes
-rw-r--r--devtools/bin/fontmaker.pdbbin0 -> 5303296 bytes
-rw-r--r--devtools/bin/fxc_prep.pl949
-rw-r--r--devtools/bin/gnu/libiconv2.dllbin0 -> 898048 bytes
-rw-r--r--devtools/bin/gnu/libintl3.dllbin0 -> 101888 bytes
-rw-r--r--devtools/bin/gnu/touch.exebin0 -> 78848 bytes
-rw-r--r--devtools/bin/grep.exebin0 -> 82944 bytes
-rw-r--r--devtools/bin/limit_vtf_sizes.pl94
-rw-r--r--devtools/bin/linux/ccachebin0 -> 220410 bytes
-rw-r--r--devtools/bin/linux/p4bin0 -> 2614024 bytes
-rw-r--r--devtools/bin/make360def.pl329
-rw-r--r--devtools/bin/makewav.exebin0 -> 905216 bytes
-rw-r--r--devtools/bin/masm.exebin0 -> 49152 bytes
-rw-r--r--devtools/bin/mc.exebin0 -> 650048 bytes
-rw-r--r--devtools/bin/md5.exebin0 -> 17845 bytes
-rw-r--r--devtools/bin/mksln.pl388
-rw-r--r--devtools/bin/ml.err280
-rw-r--r--devtools/bin/ml.exebin0 -> 366080 bytes
-rw-r--r--devtools/bin/oldfxc.exebin0 -> 753664 bytes
-rw-r--r--devtools/bin/osx32/ccachebin0 -> 138984 bytes
-rw-r--r--devtools/bin/osx32/protocbin0 -> 1382408 bytes
-rw-r--r--devtools/bin/osx32/xcode_ccache_wrapper3
-rw-r--r--devtools/bin/playback_getframe.pl24
-rw-r--r--devtools/bin/playback_getstate.pl169
-rw-r--r--devtools/bin/playback_gettexlock.pl27
-rw-r--r--devtools/bin/playback_getvb.pl23
-rw-r--r--devtools/bin/playback_numframes.bat1
-rw-r--r--devtools/bin/playback_numprims.pl27
-rw-r--r--devtools/bin/psh_prep.pl333
-rw-r--r--devtools/bin/putty/LICENCE25
-rw-r--r--devtools/bin/putty/README.txt40
-rw-r--r--devtools/bin/putty/pageant.exebin0 -> 135168 bytes
-rw-r--r--devtools/bin/putty/plink.exebin0 -> 282624 bytes
-rw-r--r--devtools/bin/putty/pscp.exebin0 -> 294912 bytes
-rw-r--r--devtools/bin/putty/psftp.exebin0 -> 307200 bytes
-rw-r--r--devtools/bin/putty/putty.cnt492
-rw-r--r--devtools/bin/putty/putty.exebin0 -> 454656 bytes
-rw-r--r--devtools/bin/putty/putty.hlpbin0 -> 629483 bytes
-rw-r--r--devtools/bin/putty/puttycm.exebin0 -> 1916928 bytes
-rw-r--r--devtools/bin/putty/puttygen.exebin0 -> 172032 bytes
-rw-r--r--devtools/bin/recentchanges.pl79
-rw-r--r--devtools/bin/robocopy.exebin0 -> 188416 bytes
-rw-r--r--devtools/bin/run_unit_tests.pl137
-rw-r--r--devtools/bin/sed.exebin0 -> 46080 bytes
-rw-r--r--devtools/bin/separate_vcprojs.py27
-rw-r--r--devtools/bin/setup_vmpi.pl60
-rw-r--r--devtools/bin/shaderinfo.pl36
-rw-r--r--devtools/bin/signcode.exebin0 -> 25872 bytes
-rw-r--r--devtools/bin/smtpmail.exebin0 -> 116224 bytes
-rw-r--r--devtools/bin/splitdiff3.pl54
-rw-r--r--devtools/bin/srgb_colorspace.pl451
-rw-r--r--devtools/bin/sscode.exebin0 -> 241724 bytes
-rw-r--r--devtools/bin/steamlicense.txt14
-rw-r--r--devtools/bin/tee.exebin0 -> 16896 bytes
-rw-r--r--devtools/bin/test_binaries.exebin0 -> 40960 bytes
-rw-r--r--devtools/bin/test_linux_compile.pl64
-rw-r--r--devtools/bin/timeprecise.exebin0 -> 49152 bytes
-rw-r--r--devtools/bin/timethis.exebin0 -> 8192 bytes
-rw-r--r--devtools/bin/uniqexe.exebin0 -> 23552 bytes
-rw-r--r--devtools/bin/uniqifylist.pl6
-rw-r--r--devtools/bin/updatecef.bat14
-rw-r--r--devtools/bin/updatecef.sh11
-rw-r--r--devtools/bin/updateshaders.pl305
-rw-r--r--devtools/bin/valve_p4_create_changelist.cmd65
-rw-r--r--devtools/bin/valve_p4_edit_to_changelist.cmd99
-rw-r--r--devtools/bin/valve_perl_helpers.pl558
-rw-r--r--devtools/bin/vmpi_chpass.pl116
-rw-r--r--devtools/bin/vmpi_test.pl385
-rw-r--r--devtools/bin/vpc46
-rw-r--r--devtools/bin/vpc.exebin0 -> 1843712 bytes
-rw-r--r--devtools/bin/vpc.pdbbin0 -> 14708736 bytes
-rw-r--r--devtools/bin/vpc2linuxmake.pl684
-rw-r--r--devtools/bin/vpcall.bat1
-rw-r--r--devtools/bin/vpccrccheck.exebin0 -> 83296 bytes
-rw-r--r--devtools/bin/vpcgames.bat1
-rw-r--r--devtools/bin/vpesign.exebin0 -> 360448 bytes
-rw-r--r--devtools/bin/vsdotnetxmlparser.py218
-rw-r--r--devtools/bin/vsh_prep.pl1106
-rw-r--r--devtools/bin/vtf_flags_convert.pl80
-rw-r--r--devtools/bin/vtfscrewtree.pl83
-rw-r--r--devtools/bin/vzip.exebin0 -> 94208 bytes
-rw-r--r--devtools/bin/wtf.pl221
-rw-r--r--devtools/bin/wtf.txt18
-rw-r--r--devtools/bin/xbspinfo.exebin0 -> 81920 bytes
-rw-r--r--devtools/bin/xsync.bat163
110 files changed, 11499 insertions, 0 deletions
diff --git a/devtools/bin/IntegrateOpenVR.bat b/devtools/bin/IntegrateOpenVR.bat
new file mode 100644
index 0000000..767a8c8
--- /dev/null
+++ b/devtools/bin/IntegrateOpenVR.bat
@@ -0,0 +1,77 @@
+@echo off
+
+:: Use this batch file to integrate steam client binaries directly from
+:: //steam/rel/client. This only really affects the binaries that gameservers
+:: use. (The client should use the binaries from the steam client that is
+:: running.) We do this when we want some feature or bugfix in the steam
+:: binaries, but don't want to integarte a whole new SDK.
+
+::
+:: Set source paths
+::
+
+SET VRP4Path=%1
+SET IntegDate=%2
+set BINS_ONLY=0
+
+if !%IntegDate%!==!/bins! (
+SET IntegDate=
+SET BINS_ONLY=1
+)
+
+
+if !%VRP4Path%!==!! (
+ echo Usage: %0 VRP4Path
+ echo.
+ echo VRP4Path should be the perforce server path to the branch you want to integrate from,
+ echo e.g. "//vr/steamvr/sdk_release/"
+ goto :end
+)
+
+:: Use this when copying from official distribution.
+SET DestRoot=..\..\..
+set P4Root=%VRP4Path%
+set SRCDIR_HEADERS=headers/...
+set SRCDIR_DLL=bin
+set SRCDIR_LIB=lib
+
+::
+:: Copy files
+::
+
+:: Client Win32 binaries
+call :CopyOneFile %SRCDIR_DLL%/win32 openvr_api.dll game\bin
+call :CopyOneFile %SRCDIR_LIB%/win32 openvr_api.lib src\lib\public
+
+:: Client Linux binaries
+call :CopyOneFile %SRCDIR_DLL%/linux32 libopenvr_api.so game\bin
+call :CopyOneFile %SRCDIR_LIB%/linux32 libopenvr_api.so src\lib\public\linux32
+
+:: Client Mac binaries. Note that there's no dedicated server on the Mac,
+:: so we can ship a smaller set
+call :CopyOneFile %SRCDIR_DLL%/osx32 libopenvr_api.dylib game\bin
+call :CopyOneFile %SRCDIR_LIB%/osx32 libopenvr_api.dylib src\lib\public\osx32
+
+if !%BINS_ONLY%!==!1! (
+ goto :end
+)
+
+:: Headers
+ECHO ---------------------------------------------
+ECHO Integrating Steam Headers from %P4Root%/%SRCDIR_HEADERS%
+ECHO to %DestRoot%\src\public\steam\...
+
+p4 integrate -d -i %P4Root%/%SRCDIR_HEADERS%%IntegDate% %DestRoot%\src\public\openvr\...
+p4 resolve -at %DestRoot%\src\public\openvr\...
+
+goto :end
+
+:CopyOneFile
+ ECHO ---------------------------------------------
+ ECHO Integrating %P4Root%/%1/%2
+ ECHO to %DestRoot%\%3\%2
+ P4 integrate -d -i %P4Root%/%1/%2%IntegDate% %DestRoot%\%3\%2
+ P4 resolve -at %DestRoot%\%3\%2
+ echo.
+
+:end
diff --git a/devtools/bin/IntegratePanorama.bat b/devtools/bin/IntegratePanorama.bat
new file mode 100644
index 0000000..7131a2e
--- /dev/null
+++ b/devtools/bin/IntegratePanorama.bat
@@ -0,0 +1,85 @@
+@echo off
+
+:: Use this batch file to integrate panorama and associated libs from //Steam/main/
+
+::
+:: Set source paths
+::
+
+SET SteamP4Path=%1
+
+if !%SteamP4Path%!==!! (
+ echo Usage: %0 SteamP4Path
+ echo.
+ echo SteamP4Path should be the perforce server path to the branch you want to integrate from,
+ echo e.g. "//Steam/rel/client" or "//Steam/main"
+ goto :end
+)
+
+set ThirdPartyPath=//thirdpartycode/nonredist
+set V8Path=%ThirdPartyPath%/v8
+set V8Bin=%V8Path%/out/ia32.release
+set V8Headers=%V8Path%/include
+
+set DestRoot=../../..
+set DestLibs=%DestRoot%/src/lib/common/linux32/release
+set DestHeaders=%DestRoot%/src/public/panorama
+set DestSrc=%DestRoot%/src/panorama/...
+set DestV8Headers=%DestRoot%/src/external/v8/include
+
+set SrcHeaders=src/public/panorama
+set SrcMain=src/panorama/...
+
+::
+:: Copy files
+::
+
+:: Client Linux binaries
+call :CopyOneFile %V8Bin% libicudata.a %DestLibs%
+call :CopyOneFile %V8Bin% libv8_libplatform.a %DestLibs%
+call :CopyOneFile %V8Bin%/lib.target libicui18n.so %DestLibs%
+call :CopyOneFile %V8Bin%/lib.target libv8.so %DestLibs%
+call :CopyOneFile %V8Bin%/lib.target libicuuc.so %DestLibs%
+
+:: Client Win32 binaries
+:: TODO
+
+:: Client Mac binaries. Note that there's no dedicated server on the Mac,
+:: so we can ship a smaller set
+:: TODO
+
+:: V8 Headers
+ECHO ---------------------------------------------
+ECHO Integrating V8 Headers from %V8Headers%/...
+ECHO to %DestV8Headers%/...
+
+p4 integrate -d -i %V8Headers%/... %DestV8Headers%/...
+p4 resolve -at %DestV8Headers%/...
+
+:: Headers
+ECHO ---------------------------------------------
+ECHO Integrating Panorama Headers from %SteamP4Path%/%SrcHeaders%/...
+ECHO to %DestHeaders%/...
+
+p4 integrate -d -i %SteamP4Path%/%SrcHeaders%/... %DestHeaders%/...
+p4 resolve -at %DestHeaders%/...
+
+:: Src
+ECHO ---------------------------------------------
+ECHO Integrating Panorama Sources from %SteamP4Path%/%SrcMain%/...
+ECHO to %DestSrc%/...
+
+p4 integrate -d -i %SteamP4Path%/%SrcMain%/... %DestSrc%/...
+p4 resolve -at %DestSrc%/...
+
+goto :end
+
+:CopyOneFile
+ ECHO ---------------------------------------------
+ ECHO Integrating %1/%2
+ ECHO to %3
+ P4 integrate -d -i %1/%2 %3/%2
+ P4 resolve -at %3/%2
+ echo.
+
+:end
diff --git a/devtools/bin/IntegrateSteamNetworkingSocketsSDK.bat b/devtools/bin/IntegrateSteamNetworkingSocketsSDK.bat
new file mode 100644
index 0000000..51b8433
--- /dev/null
+++ b/devtools/bin/IntegrateSteamNetworkingSocketsSDK.bat
@@ -0,0 +1,34 @@
+SET SRC=//Steam/sdr_public
+SET DEST=../../..
+
+:: 32 bit windows
+p4 copy %SRC%/bin/win32/steamnetworkingsockets.lib %DEST%/src/lib/public/steamnetworkingsockets.lib
+p4 copy %SRC%/bin/win32/steamnetworkingsockets.dll %DEST%/game/bin/steamnetworkingsockets.dll
+
+:: 64-bit windows
+::p4 copy %SRC%/bin/win64/steamnetworkingsockets.lib %DEST%/src/lib/public/x64/steamnetworkingsockets.lib
+::p4 copy %SRC%/bin/win64/steamnetworkingsockets.dll %DEST%/game/bin/x64/steamnetworkingsockets.dll
+
+:: GC. TF doesn't use SDR for actual connectivity, so we don't need to generate any tickets
+::p4 copy %SRC%/bin/win64/steamdatagram_ticketgen.lib %DEST%/src/lib/public/x64/steamdatagram_ticketgen.lib
+::p4 copy %SRC%/bin/win64/steamdatagram_ticketgen.dll %DEST%/game/csgo/bin/gc/x64/steamdatagram_ticketgen.dll
+::p4 copy %SRC%/bin/win32/steamdatagram_ticketgen.lib %DEST%/src/lib/public/steamdatagram_ticketgen.lib
+::p4 copy %SRC%/bin/win32/steamdatagram_ticketgen.dll %DEST%/game/csgo/bin/gc/steamdatagram_ticketgen.dll
+
+:: 32-bit Linux, older toolchain. That should work just fine for the linux client.
+p4 copy %SRC%/bin/linux32/libsteamnetworkingsockets.so %DEST%/game/bin/libsteamnetworkingsockets.so
+p4 copy %SRC%/bin/linux32/libsteamnetworkingsockets.so %DEST%/src/lib/public/linux32/libsteamnetworkingsockets.so
+
+:: 64-bit Linux, depends on Steam runtime
+::p4 copy %SRC%/bin/ubuntu12_64/libsteamnetworkingsockets.so %DEST%/game/bin/linux64/libsteamnetworkingsockets.so
+::p4 copy %SRC%/bin/ubuntu12_64/libsteamnetworkingsockets.so %DEST%/src/lib/public/linux64/libsteamnetworkingsockets.so
+
+:: OSX (32- and 64-bit fat binaries)
+p4 copy %SRC%/client/Steam.AppBundle/Steam/Contents/MacOS/libsteamnetworkingsockets.dylib %DEST%/game/bin/libsteamnetworkingsockets.dylib
+p4 copy %SRC%/client/Steam.AppBundle/Steam/Contents/MacOS/libsteamnetworkingsockets.dylib %DEST%/src/lib/public/osx32/libsteamnetworkingsockets.dylib
+
+:: Tool
+::p4 copy %SRC%/bin/win64/steamdatagram_certtool.exe %DEST%/src/devtools/bin/steamdatagram_certtool.exe
+
+p4 integrate %SRC%/src/public/steamnetworkingsockets/... %DEST%/src/public/steamnetworkingsockets/...
+p4 resolve -as
diff --git a/devtools/bin/LicenseViewed.dll b/devtools/bin/LicenseViewed.dll
new file mode 100644
index 0000000..ba9522f
--- /dev/null
+++ b/devtools/bin/LicenseViewed.dll
Binary files differ
diff --git a/devtools/bin/McCopy.pl b/devtools/bin/McCopy.pl
new file mode 100644
index 0000000..a5ddd2a
--- /dev/null
+++ b/devtools/bin/McCopy.pl
@@ -0,0 +1,1321 @@
+use strict;
+
+# todo: make sure and create the target directory if it doesn't exist.
+# todo: make this work either direction
+# todo: fix any case problems
+
+my $g_protocol_version = "mccopy1\n";
+my $g_opt_port = 7070;
+my $g_server_md5 = 0;
+
+use IO::Socket;
+
+sub GetMD5
+{
+ my $filename = shift;
+ $filename =~ s,/,\\,g;
+# print "$filename\n";
+ print ".";
+ my( $cmd ) = "md5.exe < \"$filename\"";
+# print $cmd . "\n";
+ open MD5, "$cmd|";
+ my $out = <MD5>;
+ close MD5;
+ $out =~ s/^.*\=\s+//;
+ $out =~ s/\n//g;
+# print "'" . $out . "'" . "\n";
+ return $out;
+}
+
+################################################################################################
+# SERVER CODE
+################################################################################################
+sub SendFileName
+{
+ my( $sock ) = shift;
+ my( $file ) = shift;
+ my( $isdir ) = -d $file;
+
+ if( $isdir )
+ {
+ if( $file =~ m/\/\.$/ || # "."
+ $file =~ m/\/\.\.$/ ) # ".."
+ {
+ return;
+ }
+ }
+
+ my( @statinfo ) = stat $file;
+ if( @statinfo )
+ {
+ my( $mtime ) = $statinfo[9];
+ my( $mode ) = $statinfo[2];
+# my( $mtimestr ) = scalar( localtime( $mtime ) );
+ my( $size ) = $statinfo[7];
+ if( $isdir )
+ {
+ print $sock "d\n";
+ }
+ else
+ {
+ print $sock "f\n";
+ }
+ print $sock &RemoveBaseDir( $file ) . "\n";
+ print $sock $mtime . "\n";
+ printf $sock "%o\n", $mode;
+ print $sock $size . "\n";
+ if( !$isdir && $g_server_md5 )
+ {
+ print $sock &GetMD5( $file ) . "\n";
+ }
+# print $file . "\n";
+# print $mtime . "\n";
+# print $mode . "\n";
+# print $md5 . "\n";
+ }
+ else
+ {
+ print "CAN'T STAT $file\n";
+ }
+
+ if( $isdir )
+ {
+ SendDirName( $sock, $file );
+ }
+}
+
+
+sub SendDirName
+{
+ my( $sock ) = shift;
+ my( $dirname ) = shift;
+ if( $dirname =~ m/\/\.$/ || # "."
+ $dirname =~ m/\/\.\.$/ ) # ".."
+ {
+ return;
+ }
+
+ local( *SRCDIR );
+ opendir SRCDIR, $dirname;
+ my( @dir ) = readdir SRCDIR;
+ closedir SRCDIR;
+
+ my( $item );
+ while( $item = shift @dir )
+ {
+ &SendFileName( $sock, $dirname . "/" . $item );
+ }
+}
+
+sub GetFile
+{
+ my( $sock ) = shift;
+ my( $filename ) = shift;
+ my( $localfilename ) = &AddBaseDir( $filename );
+ print "GetFile: $filename ($localfilename)\n";
+ local( *FILE );
+ open FILE, "<$localfilename";
+ binmode( FILE );
+ my( $filebits );
+ seek FILE, 0, 2;
+ my( $size ) = tell FILE;
+ if( $size < 0 )
+ {
+ die "$filename \$size == $size\n";
+ }
+ seek FILE, 0, 0;
+ read FILE, $filebits, $size;
+ close FILE;
+# print "sending $filename: $size\n";
+ print $sock $filebits;
+# print "finished sending $filename\n";
+}
+
+sub HandleCommand
+{
+ my( $sock ) = shift;
+ my( $cmd ) = shift;
+
+ if( $cmd =~ m/dirlistmd5\s+(.*)$/ )
+ {
+ $g_server_md5 = 1;
+ &SetBaseDir( $1 );
+ &SendDirName( $sock, $1 );
+ print $sock "\n"; # terminating newline to end reply
+ }
+ elsif( $cmd =~ m/dirlist\s+(.*)$/ )
+ {
+ $g_server_md5 = 0;
+ &SetBaseDir( $1 );
+ &SendDirName( $sock, $1 );
+ print $sock "\n"; # terminating newline to end reply
+ }
+ elsif( $cmd =~ m/getfile\s+(.*)$/ )
+ {
+ &GetFile( $sock, $1 );
+ }
+}
+
+sub RunServer
+{
+ my( $hostname ) = `hostname`;
+# my( $hostname ) = "localhost";
+ $hostname =~ s/\n//; # remove newlines
+
+ my $sock = new IO::Socket::INET (
+ LocalHost => $hostname,
+ LocalPort => $g_opt_port,
+ Proto => 'tcp',
+ Listen => 1,
+ Reuse => 1,
+ );
+ die "Could not create socket: $!\n" unless $sock;
+
+ my( $clientnum ) = 0;
+ while( 1 )
+ {
+ my $new_sock = $sock->accept();
+ print "accept!\n";
+ if( fork() == 0 )
+ {
+ print "$clientnum: opening connection...\n";
+ my $version = <$new_sock>;
+ if( $version ne $g_protocol_version )
+ {
+ die "wrong protocol version: server: $g_protocol_version client: %version\n";
+ }
+ my $command;
+ while(defined($command = <$new_sock>))
+ {
+ print "$clientnum: command: $command";
+ &HandleCommand( $new_sock, $command );
+ print "$clientnum: done with $command";
+ }
+ print "$clientnum: closing connection...\n";
+ close( $new_sock );
+ exit;
+ }
+ $clientnum++;
+ }
+
+ close($sock); # never get here.
+}
+
+################################################################################################
+# CLIENT CODE
+################################################################################################
+
+
+# all options that we might care about from rsync:
+# -v, --verbose increase verbosity
+# -q, --quiet decrease verbosity
+# -c, --checksum always checksum
+# -a, --archive archive mode
+# -r, --recursive recurse into directories
+# -R, --relative use relative path names
+# -b, --backup make backups (default ~ suffix)
+# --backup-dir=DIR put backups in the specified directory
+# --suffix=SUFFIX override backup suffix
+# -u, --update update only (don't overwrite newer files)
+# -p, --perms preserve permissions
+# -t, --times preserve times
+# -n, --dry-run show what would have been transferred
+# --existing only update files that already exist
+# --delete delete files that don't exist on the sending side
+# --delete-excluded also delete excluded files on the receiving side
+# --delete-after delete after transferring, not before
+# --max-delete=NUM don't delete more than NUM files
+# --force force deletion of directories even if not empty
+# --timeout=TIME set IO timeout in seconds
+# -I, --ignore-times don't exclude files that match length and time
+# --size-only only use file size when determining if a file should be transferred
+# -T --temp-dir=DIR create temporary files in directory DIR
+# --compare-dest=DIR also compare destination files relative to DIR
+# -P equivalent to --partial --progress
+# -z, --compress compress file data
+# --exclude=PATTERN exclude files matching PATTERN
+# --exclude-from=FILE exclude patterns listed in FILE
+# --include=PATTERN don't exclude files matching PATTERN
+# --include-from=FILE don't exclude patterns listed in FILE
+# --version print version number
+# --daemon run as a rsync daemon
+# --address bind to the specified address
+# --stats give some file transfer stats
+# --progress show progress during transfer
+# -h, --help show this help screen
+
+# options that are actually implemented:
+#
+sub Usage
+{
+ print "\n";
+ print "Usage:\n";
+ print "perl McCopy.pl --server\n";
+ print "or\n";
+ print "perl McCopy.pl [options] srcdir dstdir\n";
+ print "\n";
+ print "ie:\n";
+ print "perl McCopy.pl --verbose --recursive remotemachine:u:/hl u:/hl.work\n";
+ print "\n";
+ print "where \"remotemachine\" is running a McCopy server\n";
+ print "\n";
+ print "options are:\n";
+ print "--server run as server (ignores other options)\n";
+ print "--port N (default 7070)\n";
+ print "--verbose\n";
+ print "--test don't actually copy or delete any files\n";
+ print "--ignore-time don't use file mtimes as a criterion for file that need\n";
+ print " to be copied.\n";
+ print "--ignore-permissions don't use file permissions as a criterion for file that\n";
+ print " need to be copied.\n";
+ print "--ignore-size don't use file size as a criterion for file that need\n";
+ print " to be copied.\n";
+ print "--md5 Use md5 checksums\n";
+ print "--recursive\n";
+ print "--delete-readonly delete readonly files in dst\n";
+ print " that don't exist in src\n";
+ print "--delete-writable delete writable files in dst\n";
+ print "--delete-dirs delete directories in dst that don't exist in src\n";
+ print "--clobber-writable-newer\n";
+ print " write over upon copy files that have been modified locally\n";
+ print "--delete-excluded delete files on dst that are excluded using --exclude\n";
+ print "--exclude exclude files containing perl regular expression, ie:\n";
+ print " --exclude /.*release.*/i\n";
+ print "--include override --exclude for files containing perl regular expression, ie:\n";
+ print " --include /.*debughlp.*/i\n";
+ print "--mirror same as --recursive --delete-readonly --delete-writable\n";
+ print " --clobber-writable-newer --delete-excluded --delete-dirs\n";
+ print "--mirror-safe same as --recursive --delete-readonly --delete-dirs\n";
+ exit;
+}
+
+# default command line options
+my $g_opt_server = 0;
+my $g_opt_test = 0;
+my $g_opt_verbose = 0;
+my $g_opt_recursive = 0;
+my $g_opt_deletereadonly = 0;
+my $g_opt_deletewritable = 0;
+my $g_opt_clobberwritablenewer = 0;
+my $g_opt_deleteexcluded = 0;
+my $g_opt_deletedirs = 0;
+my $g_opt_ignoretime = 0;
+my $g_opt_ignoreperms = 0;
+my $g_opt_ignoresize = 0;
+my @g_opt_exclude;
+my @g_opt_include;
+my $g_opt_src;
+my $g_opt_dst;
+my $g_opt_md5;
+
+my $g_src_is_local;
+my $g_src_machine = "";
+my $g_src_path;
+
+my $g_dst_is_local;
+my $g_dst_machine = "";
+my $g_dst_path;
+
+# indexed by $filename
+my %g_remote_mtime;
+my %g_remote_mode;
+my %g_remote_isdir;
+my %g_remote_size;
+my %g_remote_md5;
+
+my %g_local_mtime;
+my %g_local_mode;
+my %g_local_isdir;
+my %g_local_size;
+my %g_local_md5;
+
+my %g_alreadycomparedtime;
+my %g_alreadycomparedpermissions;
+my %g_alreadycomparedsize;
+my %g_alreadycomparedmd5;
+
+my %g_files_to_delete;
+my %g_dirs_to_delete;
+my %g_files_to_copy;
+my %g_dirs_to_create;
+
+my $g_max_time_delta = 2; # in seconds
+
+my $g_basedir;
+
+sub BackToForwardSlash
+{
+ my( $path ) = shift;
+ $path =~ s,\\,/,g;
+ return $path;
+}
+
+sub ForwardToBackSlash
+{
+ my( $path ) = shift;
+ $path =~ s,/,\\,g;
+ return $path;
+}
+
+sub SetBaseDir
+{
+ $g_basedir = shift;
+# print "\$g_basedir: $g_basedir\n";
+}
+
+sub RemoveFileName
+{
+ my( $in ) = shift;
+ $in = &BackToForwardSlash( $in );
+ $in =~ s,/[^/]*$,,;
+ return $in;
+}
+
+sub RemovePath
+{
+ my( $in ) = shift;
+ $in = &BackToForwardSlash( $in );
+ $in =~ s,^(.*)/([^/]*)$,$2,;
+ return $in;
+}
+
+
+sub MakeDirHier
+{
+ my( $in ) = shift;
+# print "MakeDirHier( $in )\n";
+ $in = &BackToForwardSlash( $in );
+ my( @path );
+ while( $in =~ m,/, ) # while $in still has a slash
+ {
+ my( $end ) = &RemovePath( $in );
+ push @path, $end;
+# print $in . "\n";
+ $in = &RemoveFileName( $in );
+ }
+ my( $i );
+ my( $numelems ) = scalar( @path );
+ my( $curpath );
+ for( $i = $numelems - 1; $i >= 0; $i-- )
+ {
+ $curpath .= "/" . $path[$i];
+ my( $dir ) = $in . $curpath;
+ if( !stat $dir )
+ {
+ print "mkdir $dir\n";
+ mkdir $dir, 0777;
+ }
+ }
+}
+
+sub RemoveBaseDir
+{
+ my( $path ) = shift;
+# print "removebasedir: $path ";
+ $path =~ s,^$g_basedir/,,;
+# print "$path\n";
+ return $path;
+}
+
+sub AddBaseDir
+{
+ my( $path ) = shift;
+ return $g_basedir . "/" . $path;
+}
+
+sub FixPath
+{
+ my( $path ) = shift;
+ # backslash to forward slash
+ $path =~ s,\\,/,g;
+ # remove trailing slash
+ $path =~ s,/$,,;
+ return $path;
+}
+
+sub ProcessLongCommand
+{
+ my( $cmd ) = shift;
+ if( $cmd =~ m/--verbose/ )
+ {
+ $g_opt_verbose = 1;
+ }
+ elsif( $cmd =~ m/--server/ )
+ {
+ $g_opt_server = 1;
+ }
+ elsif( $cmd =~ m/--test/ )
+ {
+ $g_opt_test = 1;
+ }
+ elsif( $cmd =~ m/--ignore-time/ )
+ {
+ $g_opt_ignoretime = 1;
+ }
+ elsif( $cmd =~ m/--ignore-permissions/ )
+ {
+ $g_opt_ignoreperms = 1;
+ }
+ elsif( $cmd =~ m/--ignore-size/ )
+ {
+ $g_opt_ignoresize = 1;
+ }
+ elsif( $cmd =~ m/--md5/ )
+ {
+ $g_opt_md5 = 1;
+ }
+ elsif( $cmd =~ m/--recursive/ )
+ {
+ $g_opt_recursive = 1;
+ }
+ elsif( $cmd =~ m/--mirror-safe/ )
+ {
+ $g_opt_recursive = 1;
+ $g_opt_deletereadonly = 1;
+ $g_opt_deletewritable = 0;
+ $g_opt_clobberwritablenewer = 0;
+ $g_opt_deleteexcluded = 0;
+ $g_opt_deletedirs = 1;
+ }
+ elsif( $cmd =~ m/--mirror/ )
+ {
+ $g_opt_recursive = 1;
+ $g_opt_deletereadonly = 1;
+ $g_opt_deletewritable = 1;
+ $g_opt_clobberwritablenewer = 1;
+ $g_opt_deleteexcluded = 1;
+ $g_opt_deletedirs = 1;
+ }
+ elsif( $cmd =~ m/--delete-readonly/ )
+ {
+ $g_opt_deletereadonly = 1;
+ }
+ elsif( $cmd =~ m/--delete-writable/ )
+ {
+ $g_opt_deletewritable = 1;
+ }
+ elsif( $cmd =~ m/--clobber-writable-newer/ )
+ {
+ $g_opt_clobberwritablenewer = 1;
+ }
+ elsif( $cmd =~ m/--delete-excluded/ )
+ {
+ $g_opt_deleteexcluded = 1;
+ }
+ elsif( $cmd =~ m/--delete-dirs/ )
+ {
+ $g_opt_deletedirs = 1;
+ }
+}
+
+sub ProcessCommandLine
+{
+ my( $cmd );
+ while( $cmd = shift )
+ {
+ # hack - special case for exclude since it has an argument
+ if( $cmd =~ m/^--exclude/ )
+ {
+ push @g_opt_exclude, shift;
+ }
+ elsif( $cmd =~ m/^--include/ )
+ {
+ push @g_opt_include, shift;
+ }
+ elsif( $cmd =~ m/^--port/ )
+ {
+ $g_opt_port = shift;
+ }
+ elsif( $cmd =~ m/^--/ )
+ {
+ &ProcessLongCommand( $cmd );
+ }
+ elsif( $cmd =~ m/^-/ )
+ {
+ print "short command $cmd\n";
+ }
+ else
+ {
+ if( !defined( $g_opt_src ) )
+ {
+ $g_opt_src = &FixPath( $cmd );
+ }
+ elsif( !defined( $g_opt_dst ) )
+ {
+ $g_opt_dst = &FixPath( $cmd );
+ }
+ else
+ {
+ print "Don't understand $cmd\n";
+ &Usage();
+ }
+ }
+ }
+}
+
+sub PrintOptions
+{
+ if( $g_opt_verbose )
+ {
+ print "\n";
+ print "Options:\n";
+ print "\$g_opt_src = $g_opt_src\n";
+ print "\$g_opt_dst = $g_opt_dst\n";
+ print "\$g_opt_test = $g_opt_test\n";
+ print "\$g_opt_ignoretime = $g_opt_ignoretime\n";
+ print "\$g_opt_ignoreperms = $g_opt_ignoreperms\n";
+ print "\$g_opt_ignoresize = $g_opt_ignoresize\n";
+ print "\$g_opt_verbose = $g_opt_verbose\n";
+ print "\$g_opt_recursive = $g_opt_recursive\n";
+ print "\$g_opt_deletereadonly = $g_opt_deletereadonly\n";
+ print "\$g_opt_deletewritable = $g_opt_deletewritable\n";
+ print "\$g_opt_clobberwritablenewer = $g_opt_clobberwritablenewer\n";
+ print "\$g_opt_deleteexcluded = $g_opt_deleteexcluded\n";
+ print "\@g_opt_exclude = @g_opt_exclude\n";
+ print "\n";
+ }
+}
+
+sub ValidateOptions
+{
+ if( $g_opt_server )
+ {
+ return;
+ }
+ if( !defined( $g_opt_src ) )
+ {
+ print "src not defined\n";
+ Usage();
+ }
+ if( !defined( $g_opt_dst ) )
+ {
+ print "dst not defined\n";
+ Usage();
+ }
+ if( !$g_opt_recursive )
+ {
+ print "--recursive must be used. . non-recursive operation not supported\n";
+ Usage();
+ }
+}
+
+# src/dst looks like:
+# gary:u:/hl2/hl2
+# u:/hl2/hl2
+# /hl2/hl2
+
+sub ParseSrcDstPaths
+{
+# print $g_opt_src . "\n";
+ if( $g_opt_src =~ m/(\S+)\:(\S\:\S*)/ )
+ {
+ $g_src_is_local = 0;
+ $g_src_machine = $1;
+ $g_src_path = $2;
+ }
+ elsif( $g_opt_src =~ m/(\S+)\:(\/\/.*)/ )
+ {
+ # //gary://maxwell/common/
+ $g_src_is_local = 0;
+ $g_src_machine = $1;
+ $g_src_path = $2;
+ }
+ elsif( $g_opt_src =~ m/^(\S:.*)/ )
+ {
+ $g_src_is_local = 1;
+ $g_src_path = $1;
+ }
+ else
+ {
+ $g_src_is_local = 1;
+ $g_src_path = $1;
+ }
+
+ if( $g_opt_dst =~ m/(\S+):(\S:\S+)/ )
+ {
+ $g_dst_is_local = 0;
+ $g_dst_machine = $1;
+ $g_dst_path = $2;
+ }
+ elsif( $g_opt_dst =~ m/^(\S:\S+)/ )
+ {
+ $g_dst_is_local = 1;
+ $g_dst_path = $1;
+ }
+ else
+ {
+ $g_dst_is_local = 1;
+ $g_dst_path = $1;
+ }
+
+ if( $g_src_is_local )
+ {
+ die "my src directories not supported yet. . run the server on the other end.\n";
+ }
+ if( !$g_dst_is_local )
+ {
+ die "remote dst directories not supported yet. . run the server on the other end.\n";
+ }
+ if( $g_src_is_local == $g_dst_is_local )
+ {
+ die "src and dst on the same machine not supported. . use robocopy\n";
+ }
+
+ &MakeDirHier( $g_dst_path );
+
+ &SetBaseDir( $g_dst_path );
+
+ if( $g_opt_verbose )
+ {
+ print "\n\$g_src_is_local = $g_src_is_local\n";
+ print "\$g_src_machine = $g_src_machine\n";
+ print "\$g_src_path = $g_src_path\n";
+ print "\$g_dst_is_local = $g_dst_is_local\n";
+ print "\$g_dst_machine = $g_dst_machine\n";
+ print "\$g_dst_path = $g_dst_path\n\n";
+ }
+}
+
+&ProcessCommandLine( @ARGV );
+&ValidateOptions();
+&PrintOptions();
+
+if( $g_opt_server )
+{
+ &RunServer();
+ exit;
+}
+
+&ParseSrcDstPaths();
+
+sub GetRemoteDirList
+{
+ my( $sock ) = shift;
+ my( $remotedirname ) = shift;
+ if( $g_opt_md5 )
+ {
+ print $sock "dirlistmd5 $remotedirname\n";
+ }
+ else
+ {
+ print $sock "dirlist $remotedirname\n";
+ }
+ my( $filename, $mtime, $mode, $size );
+ my $fileordir;
+# while( defined( $fileordir = <$sock> ) )
+ while( 1 )
+ {
+ $fileordir = <$sock>;
+ die "Lost connection!!!" if !defined( $fileordir );
+ last if $fileordir=~ m/^\n$/;
+
+ $filename = <$sock>;
+ $mtime = <$sock>;
+ $mode = <$sock>;
+ $size = <$sock>;
+ my $md5 = "";
+ if( ( $fileordir =~ /f/i ) && $g_opt_md5 )
+ {
+ $md5 = <$sock>;
+ }
+ if( 0 )
+ {
+ print "file: $filename";
+ print "fileordir: $fileordir";
+ print "mtime: $mtime";
+ print "mode: $mode";
+ print "size: $size\n";
+ }
+ $filename =~ s/\n//;
+ $mtime =~ s/\n//;
+ $mode =~ s/\n//;
+ $size =~ s/\n//;
+ $md5 =~ s/\n//;
+ if( $fileordir =~ m/d/ )
+ {
+# print $filename . " is a dir\n";
+ $g_remote_isdir{$filename} = 1;
+ }
+ else
+ {
+ $g_remote_isdir{$filename} = 0;
+ }
+ $g_remote_mtime{$filename} = $mtime;
+# print $g_remote_mtime{$filename};
+ $g_remote_mode{$filename} = $mode;
+ $g_remote_size{$filename} = $size;
+ if( $g_opt_md5 )
+ {
+ $g_remote_md5{$filename} = $md5;
+ }
+ }
+}
+
+sub GetLocalDirList_File
+{
+ my( $filename ) = shift;
+ my( $isdir ) = -d $filename;
+ if( $isdir )
+ {
+ if( $filename =~ m/\/\.$/ || # "."
+ $filename =~ m/\/\.\.$/ ) # ".."
+ {
+ return;
+ }
+ }
+
+ if( $isdir )
+ {
+ GetLocalDirList_Dir( $filename );
+ }
+ my( @statinfo ) = stat $filename;
+ if( @statinfo )
+ {
+ my( $mtime ) = $statinfo[9];
+ my( $mode ) = $statinfo[2];
+# my( $mtimestr ) = scalar( localtime( $mtime ) );
+ my( $size ) = $statinfo[7];
+ my( $filename_nobase ) = &RemoveBaseDir( $filename );
+ $g_local_isdir{$filename_nobase} = $isdir;
+ $g_local_mtime{$filename_nobase} = $mtime;
+ $g_local_mode{$filename_nobase} = sprintf "%o", $mode;
+ $g_local_size{$filename_nobase} = $size;
+ if( !$isdir && $g_opt_md5 )
+ {
+ $g_local_md5{$filename_nobase} = &GetMD5( $filename );
+ }
+ }
+ else
+ {
+ print "CAN'T STAT $filename\n";
+ }
+}
+
+sub GetLocalDirList_Dir
+{
+ my( $dirname ) = shift;
+ if( $dirname =~ m/\/\.$/ || # "."
+ $dirname =~ m/\/\.\.$/ ) # ".."
+ {
+ return;
+ }
+
+ local( *SRCDIR );
+ opendir SRCDIR, $dirname;
+ my( @dir ) = readdir SRCDIR;
+ closedir SRCDIR;
+
+ my( $item );
+ while( $item = shift @dir )
+ {
+ &GetLocalDirList_File( $dirname . "/" . $item );
+ }
+}
+
+sub IsExcluded
+{
+ my( $filename ) = shift;
+ my( $regexp );
+ foreach $regexp ( @g_opt_include )
+ {
+ if( eval "\$filename =~ $regexp" )
+ {
+ return 0;
+ }
+ }
+ foreach $regexp ( @g_opt_exclude )
+ {
+ if( eval "\$filename =~ $regexp" )
+ {
+ if( defined( $g_local_mtime{$filename} ) )
+ {
+ if( $g_opt_deleteexcluded )
+ {
+ print "excluding and deleting $filename\n" if( $g_opt_verbose );
+ if( defined $g_remote_isdir{$filename} )
+ {
+ if( $g_remote_isdir{$filename} )
+ {
+ $g_dirs_to_delete{$filename} = 1;
+ }
+ else
+ {
+ $g_files_to_delete{$filename} = 1;
+ }
+ }
+ elsif( defined $g_local_isdir{$filename} )
+ {
+ if( $g_local_isdir{$filename} )
+ {
+ $g_dirs_to_delete{$filename} = 1;
+ }
+ else
+ {
+ $g_files_to_delete{$filename} = 1;
+ }
+ }
+ else
+ {
+ die;
+ }
+ }
+ else
+ {
+ print "excluding but keeping my copy of $filename\n" if( $g_opt_verbose );
+ }
+ }
+ else
+ {
+ print "excluding $filename, which doesn't exist locally\n" if( $g_opt_verbose );
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub CompareTime
+{
+ if( $g_opt_ignoretime )
+ {
+ return;
+ }
+ my( $filename ) = shift;
+ # hack! ignore directories. . seems like robocopy does too.
+ if( $g_remote_isdir{$filename} || $g_local_isdir{$filename} )
+ {
+ return;
+ }
+
+ if( defined( $g_alreadycomparedtime{$filename} ) )
+ {
+ return;
+ }
+ $g_alreadycomparedtime{$filename} = 1;
+
+ # compare times
+ my( $deltatime ) = $g_local_mtime{$filename} - $g_remote_mtime{$filename};
+# print "g_remote_mtime: " . $g_remote_mtime{$filename} . "\n";
+# print "g_local_mtime: " . $g_local_mtime{$filename} . "\n";
+# print "deltatime: $deltatime\n";
+ if( !( ( $deltatime >= -$g_max_time_delta && $deltatime <= $g_max_time_delta ) ||
+ ( $deltatime + 3600 >= -$g_max_time_delta && $deltatime + 3600 <= $g_max_time_delta ) ||
+ ( $deltatime - 3600 >= -$g_max_time_delta && $deltatime - 3600 <= $g_max_time_delta ) ) )
+ {
+ $g_files_to_copy{$filename} = 1;
+ if( $g_opt_verbose )
+ {
+ print "timedelta of $deltatime for $filename\n";
+ }
+ }
+}
+
+sub ComparePermissions
+{
+ if( $g_opt_ignoreperms )
+ {
+ return;
+ }
+ my( $filename ) = shift;
+ if( defined( $g_alreadycomparedpermissions{$filename} ) )
+ {
+ return;
+ }
+ $g_alreadycomparedpermissions{$filename} = 1;
+
+ # compare permissions
+ if( $g_remote_mode{$filename} != $g_local_mode{$filename} )
+ {
+ if( !$g_remote_isdir{$filename} )
+ {
+ $g_files_to_copy{$filename} = 1;
+ }
+ else
+ {
+ MakeLocalFileAttribsMatchRemote( $filename );
+ }
+ if( $g_opt_verbose )
+ {
+ printf "permissions different for $filename: %s %s\n", $g_remote_mode{$filename}, $g_local_mode{$filename};
+ }
+ }
+}
+
+sub CompareSize
+{
+ if( $g_opt_ignoresize )
+ {
+ return;
+ }
+ my( $filename ) = shift;
+ if( defined( $g_alreadycomparedsize{$filename} ) )
+ {
+ return;
+ }
+ $g_alreadycomparedsize{$filename} = 1;
+
+ # compare permissions
+ if( $g_remote_size{$filename} != $g_local_size{$filename} )
+ {
+ $g_files_to_copy{$filename} = 1;
+ if( $g_opt_verbose )
+ {
+ printf "size different for $filename: %d!=%d\n", $g_remote_size{$filename}, $g_local_size{$filename};
+ }
+ }
+}
+
+sub CompareMD5
+{
+ if( !$g_opt_md5 )
+ {
+ return;
+ }
+ my( $filename ) = shift;
+ if( defined( $g_alreadycomparedmd5{$filename} ) )
+ {
+ return;
+ }
+ $g_alreadycomparedmd5{$filename} = 1;
+
+ # compare md5
+ if( $g_remote_md5{$filename} ne $g_local_md5{$filename} )
+ {
+ $g_files_to_copy{$filename} = 1;
+ if( $g_opt_verbose )
+ {
+ printf "md5 different for $filename: %s!=%s\n", $g_remote_md5{$filename}, $g_local_md5{$filename};
+ }
+ }
+ else
+ {
+ my( $diff ) = 0;
+ my( $deltatime ) = $g_local_mtime{$filename} - $g_remote_mtime{$filename};
+ if( $g_remote_size{$filename} != $g_local_size{$filename} )
+ {
+ $diff = 1;
+ print "size different\n";
+ }
+ if( $g_remote_mode{$filename} != $g_local_mode{$filename} )
+ {
+ $diff = 1;
+ print "mode different\n";
+ }
+ if( !( ( $deltatime >= -$g_max_time_delta && $deltatime <= $g_max_time_delta ) ||
+ ( $deltatime + 3600 >= -$g_max_time_delta && $deltatime + 3600 <= $g_max_time_delta ) ||
+ ( $deltatime - 3600 >= -$g_max_time_delta && $deltatime - 3600 <= $g_max_time_delta ) ) )
+ {
+ $diff = 1;
+ print "time different\n";
+ }
+ if( $diff )
+ {
+ print "fixing up file attribs for $filename\n";
+ MakeLocalFileAttribsMatchRemote( $filename );
+ }
+ }
+}
+
+#print "socket: PeerAddr: \"$g_src_machine\"\n";
+my $sock = new IO::Socket::INET (
+ PeerAddr => $g_src_machine,
+ PeerPort => $g_opt_port,
+ Proto => 'tcp',
+ );
+die "Could not create socket: $!\n" unless $sock;
+
+print $sock $g_protocol_version;
+my $remotedirname = $g_src_path;
+print "Getting remote dirlist for $remotedirname\n";
+&GetRemoteDirList( $sock, $remotedirname );
+
+my $localdirname = $g_dst_path;
+print "Getting local dirlist for $localdirname\n";
+&GetLocalDirList_Dir( $localdirname );
+
+my $remote_filename;
+foreach $remote_filename (keys %g_remote_mtime)
+{
+ next if( &IsExcluded( $remote_filename ) );
+ if( !defined( $g_local_mtime{$remote_filename} ) )
+ {
+ if( $g_remote_isdir{$remote_filename} )
+ {
+# print "dir ";
+ $g_dirs_to_create{$remote_filename} = 1;
+ }
+ else
+ {
+# print "file ";
+ $g_files_to_copy{$remote_filename} = 1;
+ }
+ if( $g_opt_verbose )
+ {
+ print "doesn't exist locally and will be copied: $remote_filename\n";
+ }
+ }
+ else
+ {
+ &CompareTime( $remote_filename );
+ &ComparePermissions( $remote_filename );
+ &CompareSize( $remote_filename );
+ &CompareMD5( $remote_filename );
+ }
+}
+
+my $local_filename;
+foreach $local_filename (keys %g_local_mtime)
+{
+ next if( &IsExcluded( $local_filename ) );
+ if( !defined( $g_remote_mtime{$local_filename} ) )
+ {
+ if( $g_local_isdir{$local_filename} )
+ {
+ $g_dirs_to_delete{$local_filename} = 1;
+# print "dir ";
+ }
+ else
+ {
+ $g_files_to_delete{$local_filename} = 1;
+# print "file ";
+ }
+# print $local_filename . " doesn't exist remotely\n";
+ }
+ else
+ {
+ &CompareTime( $local_filename );
+ &ComparePermissions( $local_filename );
+ &CompareSize( $local_filename );
+ }
+}
+
+#%g_files_to_delete;
+#%g_dirs_to_delete;
+#%g_files_to_copy;
+#%g_dirs_to_create;
+
+sub IsWritable
+{
+ my( $file ) = shift;
+ my( $perms ) = oct( $g_local_mode{$file} );
+ if( $perms & 2 )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+sub UnlinkFile
+{
+ my( $file ) = shift;
+
+ print "del " . &ForwardToBackSlash( $file ) . "\n";
+ if( !$g_opt_test )
+ {
+ chmod 0666, $file || die;
+ unlink $file || die;
+ }
+}
+
+sub UnlinkDir
+{
+ my( $file ) = shift;
+
+ print "rmdir " . &ForwardToBackSlash( $file ) . "\n";
+ if( !$g_opt_test )
+ {
+ chmod 0777, $file || die;
+ if( !( rmdir $file ) )
+ {
+ print "Couldn't rmdir " . &ForwardToBackSlash( $file ) . "\n";
+ }
+ }
+}
+
+sub DeleteOrphanFile
+{
+ my( $file ) = shift;
+# print "\$g_local_isdir{$file} = $g_local_isdir{$file}\n";
+ # print "DeleteOrphanFile( $file )\n";
+ my( $localfile ) = &AddBaseDir( $file );
+ my( $iswritable ) = &IsWritable( $file );
+ if( $iswritable )
+ {
+ if( $g_opt_deletewritable )
+ {
+ &UnlinkFile( &AddBaseDir( $file ) );
+ }
+ else
+ {
+ print "Would have deleted \"$file\" (use --delete-writable to delete)\n";
+ }
+ }
+ else
+ {
+ if( $g_opt_deletereadonly )
+ {
+ &UnlinkFile( &AddBaseDir( $file ) );
+ }
+ else
+ {
+ print "Would have deleted \"$file\" (use --delete-readonly to delete)\n";
+ }
+ }
+}
+
+sub DeleteOrphanDir
+{
+ my $dir = shift;
+ my( $localdir ) = &AddBaseDir( $dir );
+ if( $g_opt_deletedirs )
+ {
+ &UnlinkDir( $localdir );
+ }
+ else
+ {
+ print "Would have deleted \"$dir\" (use --delete-dirs to delete)\n";
+ }
+}
+
+sub MakeLocalFileAttribsMatchRemote
+{
+ return if( $g_opt_test );
+ my( $file ) = shift;
+ my( $localfilename ) = &AddBaseDir( $file );
+
+ # Make it writable so that we can tweak permissions/time.
+ chmod 0666, $localfilename || die $!;
+
+ # Set the time on the file to match the remote
+ my( @statresult );
+ if( !( @statresult = stat $localfilename ) )
+ {
+ die "couldn't stat $localfilename locally\n";
+ }
+ # @statresult[8] == access time. . we don't care to change this.
+ utime $statresult[8], $g_remote_mtime{$file}, $localfilename || die $!;
+
+ # Set the permissions on the file to match the remote
+ chmod oct( $g_remote_mode{$file} ), $localfilename || die $!;
+}
+
+sub CopyFileFromRemote
+{
+ my( $file ) = shift;
+ if( &IsWritable( $file ) && !$g_opt_clobberwritablenewer && $g_local_mtime{$file} > $g_remote_mtime{$file} )
+ {
+ print "Would have copied \"$file\" (use --clobber-writable-newer to copy)\n";
+ return;
+ }
+ print "copy $file from remote ($g_remote_size{$file} bytes)\n";
+ if( !$g_opt_test )
+ {
+ my( $localfilename ) = &AddBaseDir( $file );
+ # make the my version writable so that we can write over it, if it exists
+ if( $g_local_mtime{$file} )
+ {
+ chmod 0666, $localfilename || die $!;
+ }
+ print $sock "getfile $file\n";
+ my( $size ) = $g_remote_size{$file};
+ my( $filebits );
+# print "reading $file: $size\n";
+ my( $readsize ) = read $sock, $filebits, $size;
+ if( $readsize != $size )
+ {
+ die "read size ($readsize) != expected size ($size) for $file\nYou either:\n\t1) lost your connection\n\t2) the remote file has changed since start of mccopy\n";
+ }
+
+# print "finished with $file\n";
+ local( *FILE );
+# print "opening $localfilename\n";
+ open FILE, ">$localfilename" || die $!;
+# print "binmode $localfilename";
+ binmode( FILE ) || die $!;
+# print "after binmode $localfilename";
+ print FILE $filebits;
+ close FILE || die $!;
+# print "closed $localfilename\n";
+
+ MakeLocalFileAttribsMatchRemote( $file );
+ }
+}
+
+sub PrettifyTime
+{
+ my( $inseconds ) = shift;
+ my( $hours, $minutes, $seconds );
+ my( @blah ) = gmtime( $inseconds );
+ $hours = $blah[2];
+ $minutes = $blah[1];
+ $seconds = $blah[0];
+ return sprintf "%02d:%02d:%02d", $hours, $minutes, $seconds;
+}
+
+# remove my files that aren't on remote
+my $file;
+foreach $file (keys %g_files_to_delete)
+{
+ &DeleteOrphanFile( $file );
+}
+
+# remove my dirs that aren't on remote
+my $dir;
+foreach $dir (sort { length $b <=> length $a } keys( %g_dirs_to_delete ) )
+{
+ &DeleteOrphanDir( $dir );
+}
+
+
+# create my dirs that are only on remote
+foreach $dir (sort { length $a <=> length $b } keys( %g_dirs_to_create) )
+{
+ my( $localdir ) = &AddBaseDir( $dir );
+ print "mkdir $localdir, 0777\n";
+ if( !$g_opt_test )
+ {
+ mkdir $localdir, 0777 || die $!;
+ }
+}
+
+# calculate the total size of files to transfer
+my $totalbytes = 0;
+foreach $file ( keys %g_files_to_copy )
+{
+ $totalbytes += $g_remote_size{$file};
+}
+
+print "$totalbytes bytes to copy\n";
+
+# copy files from remote that are different
+my $bytescopied = 0;
+my $starttime = time;
+foreach $file (sort( keys %g_files_to_copy ) )
+{
+ &CopyFileFromRemote( $file );
+ $bytescopied += $g_remote_size{$file};
+ my $curtime = time;
+ my $deltatime = $curtime - $starttime;
+ my $percentdone;
+ if( $totalbytes )
+ {
+ $percentdone = ( $bytescopied * 1.0 ) / $totalbytes;
+ }
+ if( $totalbytes && $percentdone && $deltatime )
+ {
+ printf "progress: %.1f%% %s/%s %d bytes/sec\n",
+ $percentdone * 100,
+ &PrettifyTime( $deltatime ),
+ &PrettifyTime( 1.0 / $percentdone * $deltatime ),
+ $bytescopied / $deltatime;
+ }
+}
+
+print "done!\n";
+
+close($sock);
+
+
diff --git a/devtools/bin/UpdateProgress.exe b/devtools/bin/UpdateProgress.exe
new file mode 100644
index 0000000..d0da70f
--- /dev/null
+++ b/devtools/bin/UpdateProgress.exe
Binary files differ
diff --git a/devtools/bin/VProject.exe b/devtools/bin/VProject.exe
new file mode 100644
index 0000000..9c64ddf
--- /dev/null
+++ b/devtools/bin/VProject.exe
Binary files differ
diff --git a/devtools/bin/build_sdk_vcproj.py b/devtools/bin/build_sdk_vcproj.py
new file mode 100644
index 0000000..b8759e0
--- /dev/null
+++ b/devtools/bin/build_sdk_vcproj.py
@@ -0,0 +1,11 @@
+
+from vsdotnetxmlparser import *
+
+
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug SDK|Win32", "Release SDK|Win32"], 'cl_dll\\client_sdk.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug HL2|Win32", "Release HL2|Win32"], 'cl_dll\\client_sdk_hl2.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug HL2MP|Win32", "Release HL2MP|Win32"], 'cl_dll\\client_sdk_hl2mp.vcproj' )
+
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug SDK|Win32", "Release SDK|Win32"], 'dlls\\hl_sdk.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug HL2|Win32", "Release HL2|Win32"], 'dlls\\hl_sdk_hl2.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug HL2MP|Win32", "Release HL2MP|Win32"], 'dlls\\hl_sdk_hl2mp.vcproj' )
diff --git a/devtools/bin/buildshaderlist.pl b/devtools/bin/buildshaderlist.pl
new file mode 100644
index 0000000..98a4051
--- /dev/null
+++ b/devtools/bin/buildshaderlist.pl
@@ -0,0 +1,22 @@
+use File::DosGlob;
+@ARGV = map {
+ my @g = File::DosGlob::glob($_) if /[*?]/;
+ @g ? @g : $_;
+ } @ARGV;
+
+open FILE, ">__tmpshaderlist.txt";
+
+foreach $arg (@ARGV)
+{
+ if( $arg =~ m/\.fxc$/i || $arg =~ m/\.vsh$/i || $arg =~ m/\.psh$/i )
+ {
+ print $arg . "\n";
+ print FILE $arg . "\n";
+ }
+}
+
+close FILE;
+
+system "buildshaders.bat __tmpshaderlist";
+
+unlink "__tmpshaderlist.txt"; \ No newline at end of file
diff --git a/devtools/bin/buildtest.pl b/devtools/bin/buildtest.pl
new file mode 100644
index 0000000..16730b5
--- /dev/null
+++ b/devtools/bin/buildtest.pl
@@ -0,0 +1,83 @@
+use strict;
+
+sub DoBuild
+{
+ my @output;
+ my $buildtype = shift;
+ if( $buildtype eq "release" )
+ {
+ open BUILD, "dev_build_all.bat|";
+ }
+ elsif( $buildtype eq "debug" )
+ {
+ open BUILD, "dev_build_all.bat debug|";
+ }
+ else
+ {
+ die;
+ }
+ my $buildfailed = 0;
+ while( <BUILD> )
+ {
+ if( /Build Errors\!/ )
+ {
+ $buildfailed = 1;
+ }
+ print;
+ push @output, $_;
+ }
+ close build;
+
+ if( $buildfailed )
+ {
+ open CHANGES, "p4 changes -m 10 -s submitted //ValveGames/main/src/...|";
+ my @changes = <CHANGES>;
+ close CHANGES;
+ open EMAIL, ">email.txt";
+ print EMAIL "LAST 10 SUBMITS TO MAIN:\n";
+ print EMAIL @changes;
+ print EMAIL "\n";
+ my $line;
+ foreach $line ( @output )
+ {
+ if( $line =~ m/error/i )
+ {
+ print EMAIL $line;
+ }
+ }
+ print EMAIL "--------------------------------------------\n\n\n\n";
+ print EMAIL @output;
+ close EMAIL;
+ system "devtools\\bin\\smtpmail.exe -to srcdev\@valvesoftware.com -from srcdev\@valvesoftware.com -subject \"FIX THE BUILD\! ($buildtype)\" -verbose email.txt";
+# system "devtools\\bin\\smtpmail.exe -to gary\@valvesoftware.com -from srcdev\@valvesoftware.com -subject \"FIX THE BUILD\! ($buildtype)\" -verbose email.txt";
+ }
+}
+
+while( 1 )
+{
+ $ENV{"USE_INCREDIBUILD"} = "1";
+ system "p4 sync > sync.txt 2>&1";
+ my $hasChange = 1;
+ my $line;
+ open SYNC, "<sync.txt";
+ while( <SYNC> )
+ {
+ if( m/File\(s\) up-to-date/ )
+ {
+ $hasChange = 0;
+ }
+ print;
+ }
+ close SYNC;
+ if( $hasChange )
+ {
+ print "changes checked in\n";
+ &DoBuild( "release" );
+ &DoBuild( "debug" );
+ }
+ else
+ {
+ print "no changes checked in\n";
+ sleep 30;
+ }
+} \ No newline at end of file
diff --git a/devtools/bin/check_gcc_compile.pl b/devtools/bin/check_gcc_compile.pl
new file mode 100644
index 0000000..4d70637
--- /dev/null
+++ b/devtools/bin/check_gcc_compile.pl
@@ -0,0 +1,23 @@
+#! perl
+
+# scan all .o files for illegal instructions from passing aggregates to varargs functions.
+
+use File::Find;
+
+find( \&CheckFile, "." );
+
+sub CheckFile
+ {
+ return unless (/\.o$/ );
+ open( DIS, "objdump --disassemble -C $_|" ) || die "can't process $_";
+ while( <DIS> )
+ {
+ $symbol = $1 if ( /^[0-9]+ \<(.*)\>:/ );
+ if ( /\s+ud2a/ )
+ {
+ print "Illegal instruction in $symbol in ", $File::Find::name, "\n";
+ }
+
+ }
+
+ }
diff --git a/devtools/bin/checkin.pl b/devtools/bin/checkin.pl
new file mode 100644
index 0000000..8b4eddd
--- /dev/null
+++ b/devtools/bin/checkin.pl
@@ -0,0 +1,660 @@
+use strict;
+
+###################################################
+# CONFIG VARS
+###################################################
+
+# FIXME: load these from a separate file so that each user can have their own config without editingthis file.
+my $g_P4UserName = "gary";
+
+my $g_LocalBaseDir = "u:\\hl2";
+my $g_LocalBranchSubdir = "src5";
+my $g_LocalBranchName = "gary_src5";
+my $g_LocalBranchClient = "gary_work_src5";
+
+my $g_MainCopyBaseDir = "u:\\hl2";
+my $g_LocalBranchMainCopySubdir = "src5_main";
+my $g_LocalBranchMainCopyName = "gary_src5_main";
+#my $g_LocalBranchMainCopyClient = "gary_work_src5_main";
+
+my $g_MainBaseDir = "u:\\hl2_main";
+my $g_MainBranchSubdir = "src_main";
+#my $g_MainBranchName = "gary_src_main";
+#my $g_MainBranchClient = "gary_work_src_main";
+
+my $g_UseIncredibuildForMain = 1;
+
+# FIXME: need to make this work for those that don't work on HL2.
+my $g_LocalBranchHasHL1Port = 0;
+my $g_LocalBranchHasCSPort = 0;
+my $g_LocalBranchHasTF2 = 0;
+
+my $g_CheckinFileStampTimes = "c:\\checkin_filetimes.txt";
+
+# either use VSS directly via the command-line, or use Tom's tool.
+my $g_UseVSS = 0;
+
+###################################################
+# Helper vars made up of config vars
+###################################################
+
+my $g_LocalBranchDir = "$g_LocalBaseDir\\$g_LocalBranchSubdir";
+my $g_LocalBranchMainCopyDir = "$g_MainCopyBaseDir\\$g_LocalBranchMainCopySubdir";
+my $g_MainBranchDir = "$g_MainBaseDir\\$g_MainBranchSubdir";
+
+###################################################
+
+my $g_DebugStub = 0;
+
+my $stage = shift;
+if( $stage != 1 &&
+ $stage != 2 &&
+ $stage != 3 &&
+ $stage ne "syncmain" &&
+ $stage ne "syncmainsrc" &&
+ $stage ne "synclocal" &&
+ $stage ne "synclocalrelease" &&
+ $stage ne "synclocaldebug" &&
+ $stage ne "synclocalsrc" &&
+ $stage ne "synclocalsrcrelease" &&
+ $stage ne "sync" &&
+ $stage ne "syncmaincontent" )
+{
+ print "checkin.pl 1 : to get started with a checkin\n";
+ print "checkin.pl 2 : second stage of checkin\n";
+ print "checkin.pl 3 : third stage of checkin\n";
+ print "checkin.pl syncmain : sync main source and content, then build\n";
+ print "checkin.pl syncmainsrc : sync main source then build\n";
+ print "checkin.pl syncmaincontent : sync main content only\n";
+ print "checkin.pl synclocal : merge personal branch, sync content,\n";
+ print " then build.\n";
+ print "checkin.pl synclocalrelease : merge personal branch, sync content,\n";
+ print " then build (release only).\n";
+ print "checkin.pl synclocaldebug : merge personal branch, sync content,\n";
+ print " then build (debug only).\n";
+ print "checkin.pl synclocalsrc : merge personal branch, then build.\n";
+ print "checkin.pl synclocalsrcrelease : merge personal branch, then build\n";
+ print " (release only).\n";
+ print "checkin.pl sync : merge personal branch, sync main src,\n";
+ print " sync content for both, and then build\n";
+ print " the whole thing.\n";
+ die;
+}
+
+sub RunCmd
+{
+ my $cmd = shift;
+ print $cmd . "\n";
+ if( !$g_DebugStub )
+ {
+ return system $cmd;
+ }
+}
+
+sub CD
+{
+ my $dir = shift;
+ print "cd $dir\n";
+ if( !$g_DebugStub )
+ {
+ chdir $dir;
+ }
+}
+
+sub SSGet
+{
+ my $vssdir = shift;
+ my $localdir = shift;
+
+ &CD( $localdir );
+ &RunCmd( "ss WorkFold $vssdir $localdir" );
+ print "\n";
+ my $cmd = "ss get $vssdir -R";
+ local( *SS );
+ open SS, "$cmd|";
+ my $workingdir;
+ while( <SS> )
+ {
+ # FIXME: clean up this output.
+ $_ =~ s/\n//;
+ if( m/^\$/ )
+ {
+ $workingdir = $_;
+# print "WORKING DIR: $_\n";
+ }
+ elsif( m/^getting/i )
+ {
+ print "GETTING: $workingdir $_\n";
+ }
+ elsif( m/^replacing local file/i )
+ {
+ print "REPLACING: $workingdir $_\n";
+ }
+ elsif( m/^File/ )
+ {
+ print "ALREADY EXISTS: $workingdir $_\n";
+ }
+ else
+ {
+# print "WTF: $_\n";
+ }
+ }
+ close SS;
+}
+
+sub FastSSGet
+{
+ my $localdir = shift;
+ my $option = shift;
+
+ &RunCmd( "\\\\hl2vss\\hl2vss\\win32\\syncfrommirror.bat $option $localdir" );
+}
+
+sub FileIsWritable
+{
+ my $file = shift;
+
+ my @statresult = stat $file;
+ die if !@statresult;
+ my $perms = oct( $statresult[2] );
+ if( $perms & 2 )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+sub CompareDirs
+{
+ my $filesThatHaveChanged = shift;
+ my $filesThatHaveNotChanged = shift;
+ my @out = `robocopy $g_MainBaseDir\\checkinbins\\. $g_MainBaseDir\\. /S /L /V`;
+ my $line;
+ my $cwd;
+ foreach $line ( @out )
+ {
+ next if( $line =~ /\*EXTRA Dir/ );
+ next if( $line =~ /\*EXTRA Dir/ );
+ next if( $line =~ /\*EXTRA File/ );
+ if( $line =~ m/\s*\d+\s+(\S+\\)/ )
+ {
+ $cwd = $1;
+ next;
+ }
+ if( $line =~ m/\s+Older\s+\d+\s+(\S+)/ )
+ {
+ my $testfilename = $cwd . $1;
+ my $filename = $testfilename;
+ $filename =~ s/\\checkinbins//i;
+ my $diffresult = system "diff $testfilename $filename > nil";
+ if( $diffresult != 0 )
+ {
+ push @{$filesThatHaveChanged}, $filename;
+ }
+ else
+ {
+ if( &FileIsWritable( $filename ) )
+ {
+ push @{$filesThatHaveNotChanged}, $filename;
+ }
+ }
+ next;
+ }
+ elsif( $line =~ m/\s+same\s+\d+\s+(\S+)/ )
+ {
+ my $filename = $cwd . $1;
+ $filename =~ s/\\checkinbins//i;
+ if( &FileIsWritable( $filename ) )
+ {
+ push @{$filesThatHaveNotChanged}, $filename;
+ }
+ next;
+ }
+ if( $line =~ m/\s+New File\s+\d+\s+(\S+)/ )
+ {
+ die "$cwd $1 didn't build!\n";
+ }
+ print "DEBUG: unhandled line: $line\n";
+ }
+}
+
+sub CheckoutFile
+{
+ my $file = shift;
+ print "-----------------\nchecking out $file\n";
+ if( $file =~ /src_main/i )
+ {
+ # need to use p4 to check this one out.
+ my $dir = $file;
+ $dir =~ s/\\([^\\]*)$//;
+ &CD( $dir );
+ &RunCmd( "p4 edit $1" );
+ }
+ else
+ {
+ my $dir = $file;
+ $dir =~ s/\\([^\\]*)$//;
+ &CD( $dir );
+ $file =~ s,\\,/,g;
+ if( $file =~ m/cstrike/i || $file =~ m/hl1/i )
+ {
+ $file =~ s,u:/hl2_main/,\$/hl1ports/release/dev/,gi;
+ &RunCmd( "ss WorkFold \$/hl1ports/release/dev $g_MainBaseDir" );
+ }
+ elsif( $file =~ m/\/tf2/i )
+ {
+ $file =~ s,u:/hl2_main/,\$/tf2/release/dev/,gi;
+ &RunCmd( "ss WorkFold \$/tf2/release/dev $g_MainBaseDir" );
+ }
+ else
+ {
+ $file =~ s,u:/hl2_main/,\$/hl2/release/dev/,gi;
+ &RunCmd( "ss WorkFold \$/hl2/release/dev $g_MainBaseDir" );
+ }
+ print "\n";
+ &RunCmd( "ss Checkout -G- $file" );
+ }
+}
+
+sub RevertFile
+{
+ my $file = shift;
+ print "-----------------\nreverting $file\n";
+ if( $file =~ /src_main/i )
+ {
+ # need to use p4 to revert this one
+ my $dir = $file;
+ $dir =~ s/\\([^\\]*)$//;
+ &CD( $dir );
+ &RunCmd( "p4 sync -f $1" );
+ }
+ else
+ {
+ my $dir = $file;
+ $dir =~ s/\\([^\\]*)$//;
+ &CD( $dir );
+ $file =~ s,\\,/,g;
+ my $vssfile = $file;
+ if( $file =~ m/cstrike/i || $file =~ m/hl1/i )
+ {
+ $vssfile =~ s,u:/hl2_main/,\$/hl1ports/release/dev/,gi;
+ &RunCmd( "ss WorkFold \$/hl1ports/release/dev $g_MainBaseDir" );
+ }
+ elsif( $file =~ m/\/tf2/i )
+ {
+ $vssfile =~ s,u:/hl2_main/,\$/tf2/release/dev/,gi;
+ &RunCmd( "ss WorkFold \$/tf2/release/dev $g_MainBaseDir" );
+ }
+ else
+ {
+ $vssfile =~ s,u:/hl2_main/,\$/hl2/release/dev/,gi;
+ &RunCmd( "ss WorkFold \$/hl2/release/dev $g_MainBaseDir" );
+ }
+ print "\n";
+ unlink $file;
+ &RunCmd( "ss Get -I- $vssfile" );
+ }
+}
+
+sub SyncMainSource
+{
+ # SYNC MAIN
+ &CD( $g_MainBranchDir );
+ &RunCmd( "p4 sync" );
+}
+
+sub SyncMainContent
+{
+ # SYNC VSS
+ &CD( $g_MainBranchDir );
+ &RunCmd( "clean.bat" );
+ if( $g_UseVSS )
+ {
+ &SSGet( "\$/hl2/release/dev", $g_MainBaseDir );
+ &SSGet( "\$/hl1ports/release/dev", $g_MainBaseDir );
+ # NOTE: only get tf2 bin since we aren't testing tf2 right now
+ &SSGet( "\$/tf2/release/dev/tf2/bin", "$g_MainBaseDir/tf2/bin" );
+ }
+ else
+ {
+ &FastSSGet( $g_MainBaseDir, "all" );
+ }
+}
+
+sub BuildMain
+{
+ if( $g_UseIncredibuildForMain )
+ {
+ $ENV{"USE_INCREDIBUILD"} = "1";
+ }
+ &CD( $g_MainBranchDir );
+ &RunCmd( "clean.bat" );
+ &RunCmd( "build_hl2.bat" );
+ &RunCmd( "build_hl1_game.bat" );
+ &RunCmd( "build_cs_game.bat" );
+ &RunCmd( "build_tf2_game.bat" );
+ if( $g_UseIncredibuildForMain )
+ {
+ undef $ENV{"USE_INCREDIBUILD"};
+ }
+}
+
+sub SyncLocalBranchSource
+{
+ &CD( $g_LocalBranchDir );
+ &RunCmd( "p4mf.bat $g_LocalBranchName $g_LocalBranchClient pause" );
+ # FIXME: This needs to specify the changelist since p4mf makes a new changelist.
+# &RunCmd( "p4 submit" );
+
+}
+
+sub SyncMainCopySource
+{
+ &CD( $g_LocalBranchMainCopyDir );
+ &RunCmd( "p4 integrate -d -i -b $g_LocalBranchMainCopyName" );
+ &RunCmd( "p4 resolve -at ..." );
+ # Update the changelist and submit
+ &RunCmd( "p4 change -o | sed -e \"s/<enter description here>/Merge from main/g\" | p4 submit -i" );
+}
+
+sub SyncLocalBranchContent
+{
+ &CD( $g_LocalBranchDir );
+
+ # CLEAN LOCAL BRANCH
+ &RunCmd( "clean.bat" );
+
+ # SYNC VSS
+ if( $g_UseVSS )
+ {
+ &SSGet( "\$/hl2/release/dev", $g_LocalBaseDir );
+ if( $g_LocalBranchHasHL1Port || $g_LocalBranchHasCSPort )
+ {
+ &SSGet( "\$/hl1ports/release/dev", $g_LocalBaseDir );
+ }
+ if( $g_LocalBranchHasTF2 )
+ {
+ &SSGet( "\$/tf2/release/dev", $g_LocalBaseDir );
+ }
+ }
+ else
+ {
+ if( $g_LocalBranchHasHL1Port || $g_LocalBranchHasCSPort )
+ {
+ &FastSSGet( $g_LocalBaseDir, "all" );
+ }
+ else
+ {
+ &FastSSGet( $g_LocalBaseDir, "hl2" );
+ }
+ # FIXME: screwed on tf2 here.
+ }
+}
+
+sub BuildLocalBranch
+{
+ &CD( $g_LocalBranchDir );
+
+ # BUILD DEBUG if we don't want release only
+ if( !( $stage =~ /release/i ) )
+ {
+ # CLEAN LOCAL BRANCH
+ &RunCmd( "clean.bat" );
+
+ &RunCmd( "build_hl2.bat debug" );
+ if( $g_LocalBranchHasHL1Port )
+ {
+ &RunCmd( "build_hl1_game.bat debug" );
+ }
+ if( $g_LocalBranchHasCSPort )
+ {
+ &RunCmd( "build_cs_game.bat debug" );
+ }
+ if( $g_LocalBranchHasTF2 )
+ {
+ &RunCmd( "build_tf2_game.bat debug" );
+ }
+ }
+
+ if( !( $stage =~ /debug/i ) )
+ {
+ # CLEAN LOCAL BRANCH
+ &RunCmd( "clean.bat" );
+
+ # BUILD RELEASE
+ &RunCmd( "build_hl2.bat" );
+ if( $g_LocalBranchHasHL1Port )
+ {
+ &RunCmd( "build_hl1_game.bat" );
+ }
+ if( $g_LocalBranchHasCSPort )
+ {
+ &RunCmd( "build_cs_game.bat" );
+ }
+ if( $g_LocalBranchHasTF2 )
+ {
+ &RunCmd( "build_tf2_game.bat" );
+ }
+ }
+}
+
+sub GetMainUpToDate
+{
+ &SyncMainSource();
+ &SyncMainContent();
+ &BuildMain();
+}
+
+sub LockPerforce
+{
+ while( 1 )
+ {
+ my $thing = `p4mutex lock main_src 0 $g_P4UserName 207.173.178.12:1666`;
+ print $thing;
+ last if $thing =~ /Success/;
+ sleep 30;
+ }
+}
+
+sub SaveMainTimeStampsBeforeIntegrate
+{
+ &CD( $g_MainBranchDir );
+ # Get a list of files that are going to be integrated into main so that we can save off their time stamp info.
+ my @filestointegrate = `p4 integrate -n -r -b $g_LocalBranchName`;
+ my $file;
+ local( * TIMESTAMPS );
+ open TIMESTAMPS, ">$g_CheckinFileStampTimes";
+ foreach $file ( @filestointegrate )
+ {
+ $file =~ s,//ValveGames/main/src/([^#]*)\#.*,$1,gi;
+ $file =~ s/\n//;
+ $file =~ s,\\,/,g;
+ my $localfilename = "$g_MainBranchDir/$file";
+ my @statinfo = stat $localfilename;
+ next if !@statinfo;
+ my $mtime = $statinfo[9];
+ print TIMESTAMPS $file . "|" . $mtime . "\n";
+ }
+ close TIMESTAMPS;
+}
+
+sub SetMainTimeStampsOnRevertedFiles
+{
+ &CD( $g_MainBranchDir );
+ # Get a list of files that we might have to revert times on if they aren't in the changelist.
+ local( *TIMESTAMPS );
+ open TIMESTAMPS, "<$g_CheckinFileStampTimes";
+ my @timestamps = <TIMESTAMPS>;
+ my %filetotimestamp;
+ my $i;
+ for( $i = 0; $i < scalar( @timestamps ); $i++ )
+ {
+ $timestamps[$i] =~ s/\n//;
+ $timestamps[$i] =~ m/^(.*)\|(.*)$/;
+ $filetotimestamp{$1} = $2;
+ }
+ close TIMESTAMPS;
+
+ my $key;
+ foreach $key( keys( %filetotimestamp ) )
+ {
+ print "before: \'$key\" \"$filetotimestamp{$key}\"\n";
+ }
+
+ local( *CHANGELIST );
+ open CHANGELIST, "p4 change -o|";
+ while( <CHANGELIST> )
+ {
+ if( m,//ValveGames/main/src/(.*)\s+\#,i )
+ {
+ if( defined $filetotimestamp{$1} )
+ {
+ undef $filetotimestamp{$1};
+ }
+ }
+ }
+ close CHANGELIST;
+
+ foreach $key( keys( %filetotimestamp ) )
+ {
+ if( defined $filetotimestamp{$key} )
+ {
+ my $filename = $g_MainBranchDir . "/" . $key;
+ $filename =~ s,/,\\,g;
+ my @statresults;
+ if( @statresults = stat $filename )
+ {
+ my $mode = $statresults[2];
+ my $atime = $statresults[8];
+ my $mtime = $statresults[9];
+
+ print "reverting timestamp for $filename\n";
+
+ chmod 0666, $filename || die $!;
+
+ utime $atime, $filetotimestamp{$key}, $filename || die $!;
+
+ chmod $mode, $filename || die $!;
+ }
+ }
+ }
+}
+
+
+if( $stage eq "synclocal" || $stage eq "synclocalrelease" || $stage eq "synclocaldebug" || $stage eq "sync" )
+{
+ &SyncLocalBranchSource();
+ &SyncMainCopySource();
+ &SyncLocalBranchContent();
+ &BuildLocalBranch();
+}
+
+if( $stage eq "synclocalsrc" || $stage eq "synclocalsrcrelease" )
+{
+ &SyncLocalBranchSource();
+ &SyncMainCopySource();
+ &BuildLocalBranch();
+}
+
+if( $stage eq "syncmainsrc" )
+{
+ &SyncMainSource();
+ &BuildMain();
+}
+
+if( $stage eq "syncmain" || $stage eq "sync" )
+{
+ &GetMainUpToDate();
+}
+
+if( $stage eq "syncmaincontent" )
+{
+ &SyncMainContent();
+}
+
+if( $stage == 1 )
+{
+ # lock p4
+# &LockPerforce();
+
+ &GetMainUpToDate();
+
+ # merge main into local branch
+ &SyncLocalBranchSource();
+
+ # TODO: need a way to detect if there are conflicts or not. If there are, pause here.
+
+ # Make a copy of targets so that we can tell which ones changed.
+ &RunCmd( "robocopy $g_MainBaseDir\\ $g_MainBaseDir\\checkinbins\\ /purge" );
+ &RunCmd( "robocopy $g_MainBaseDir\\bin\\. $g_MainBaseDir\\checkinbins\\bin\\. /mir" );
+ &RunCmd( "robocopy $g_MainBaseDir\\hl2\\bin\\. $g_MainBaseDir\\checkinbins\\hl2\\bin\\. /mir" );
+ &RunCmd( "robocopy $g_MainBaseDir\\hl1\\bin\\. $g_MainBaseDir\\checkinbins\\hl1\\bin\\. /mir" );
+ &RunCmd( "robocopy $g_MainBaseDir\\cstrike\\bin\\. $g_MainBaseDir\\checkinbins\\cstrike\\bin\\. /mir" );
+ &RunCmd( "robocopy $g_MainBaseDir\\tf2\\bin\\. $g_MainBaseDir\\checkinbins\\tf2\\bin\\. /mir" );
+ &RunCmd( "robocopy $g_MainBaseDir\\platform\\servers\\. $g_MainBaseDir\\checkinbins\\platform\\servers\\. /mir" );
+ &RunCmd( "robocopy $g_MainBranchDir\\lib\\. $g_MainBaseDir\\checkinbins\\$g_MainBranchSubdir\\lib\\. /mir" );
+
+ # integrate from personal branch into main. . accept theirs.
+ # TODO: need to check if main has a changelist or not and warn!
+ &CD( $g_MainBranchDir );
+
+ &SaveMainTimeStampsBeforeIntegrate();
+
+ &RunCmd( "p4 integrate -r -b $g_LocalBranchName" );
+
+ &RunCmd( "p4 resolve -at ..." );
+
+ # revert unchanged files.
+ my @unchanged = `p4 diff -sr`;
+ my $file;
+ foreach $file ( @unchanged )
+ {
+ &RunCmd( "p4 revert $file" );
+ }
+
+ print "Do \"checkin.pl 2\" when you are done reverting unchanging files and fixing up any other diffs in your main client.\n";
+}
+elsif( $stage == 2 )
+{
+ &SetMainTimeStampsOnRevertedFiles();
+
+ # build main with the new changes
+ &BuildMain();
+
+ # compare what we just built to what we saved off earlier
+ my @filesToCheckOut;
+ my @filesThatHaveNotChanged;
+ &CompareDirs( \@filesToCheckOut, \@filesThatHaveNotChanged );
+
+ my $file;
+# $g_DebugStub = 1;
+ foreach $file ( @filesThatHaveNotChanged )
+ {
+ &RevertFile( $file );
+ }
+
+ foreach $file ( @filesToCheckOut )
+ {
+ &CheckoutFile( $file );
+ }
+
+ print "-----------------\n";
+ print "Do \"checkin.pl 3\" when you are finished testing to checkin files and release the mutex.\n";
+}
+elsif( $stage == 3 )
+{
+ my @filesToCheckOut;
+ my @filesThatHaveNotChanged;
+ &CompareDirs( \@filesToCheckOut, \@filesThatHaveNotChanged );
+
+ # TODO: check stuff in here and unlock p4
+ # TODO: go ahead and sync src_main to main so that they match
+ # TODO: merge main into src again so any changes that you made while checking in are propogated
+
+ &SyncMainCopySource();
+}
+
+
diff --git a/devtools/bin/checkshaderchecksums.pl b/devtools/bin/checkshaderchecksums.pl
new file mode 100644
index 0000000..26841cb
--- /dev/null
+++ b/devtools/bin/checkshaderchecksums.pl
@@ -0,0 +1,116 @@
+use String::CRC32;
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+
+sub GetShaderType
+{
+ my $shadername = shift;
+ my $shadertype;
+ if( $shadername =~ m/\.vsh/i )
+ {
+ $shadertype = "vsh";
+ }
+ elsif( $shadername =~ m/\.psh/i )
+ {
+ $shadertype = "psh";
+ }
+ elsif( $shadername =~ m/\.fxc/i )
+ {
+ $shadertype = "fxc";
+ }
+ else
+ {
+ die;
+ }
+ return $shadertype;
+}
+
+sub GetShaderSrc
+{
+ my $shadername = shift;
+ if ( $shadername =~ m/^(.*)-----/i )
+ {
+ return $1;
+ }
+ else
+ {
+ return $shadername;
+ }
+}
+
+sub GetShaderType
+{
+ my $shadername = shift;
+ my $shadertype;
+ if( $shadername =~ m/\.vsh/i )
+ {
+ $shadertype = "vsh";
+ }
+ elsif( $shadername =~ m/\.psh/i )
+ {
+ $shadertype = "psh";
+ }
+ elsif( $shadername =~ m/\.fxc/i )
+ {
+ $shadertype = "fxc";
+ }
+ else
+ {
+ die;
+ }
+ return $shadertype;
+}
+
+sub GetShaderBase
+{
+ my $shadername = shift;
+ if ( $shadername =~ m/-----(.*)$/i )
+ {
+ return $1;
+ }
+ else
+ {
+ my $shadertype = &GetShaderType( $shadername );
+ $shadername =~ s/\.$shadertype//i;
+ return $shadername;
+ }
+}
+
+$g_x360 = 0;
+$g_vcsext = ".vcs";
+
+while( 1 )
+{
+ $inputbase = shift;
+
+ if( $inputbase =~ m/-x360/ )
+ {
+ $g_x360 = 1;
+ $g_vcsext = ".360.vcs";
+ }
+ else
+ {
+ last;
+ }
+}
+
+# rip the txt off the end if it's there.
+$inputbase =~ s/\.txt//i;
+
+my @srcfiles = &LoadShaderListFile( $inputbase );
+
+foreach $srcfile ( @srcfiles )
+{
+ my $shadertype = &GetShaderType( $srcfile );
+ my $shaderbase = &GetShaderBase( $srcfile );
+ my $shadersrc = &GetShaderSrc( $srcfile );
+ my $vcsFileName = "..\\..\\..\\game\\hl2\\shaders\\$shadertype\\$shaderbase" . $g_vcsext;
+# print "shadersrc: $shadersrc vcsFileName: $vcsFileName\n";
+
+ if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) )
+ {
+ next; # skip _ps20 files for 360
+ }
+
+ &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 1 );
+}
diff --git a/devtools/bin/copyshaderincfiles.pl b/devtools/bin/copyshaderincfiles.pl
new file mode 100644
index 0000000..0625833
--- /dev/null
+++ b/devtools/bin/copyshaderincfiles.pl
@@ -0,0 +1,86 @@
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+use Cwd;
+use String::CRC32;
+
+my $txtfilename = shift;
+my $arg = shift;
+
+my $is360 = 0;
+my $platformextension = "";
+if( $arg =~ m/-x360/i )
+{
+ $is360 = 1;
+ $platformextension = ".360";
+}
+
+# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
+my $changelistnumber = `valve_p4_create_changelist.cmd ..\\..\\..\\game\\hl2\\shaders \"Shader Auto Checkout VCS\"`;
+# Get rid of the newline
+$changelistnumber =~ s/\n//g;
+
+my $changelistarg = "";
+if( $changelistnumber != 0 )
+{
+ $changelistarg = "-c $changelistnumber"
+}
+
+open TXTFILE, "<$txtfilename";
+
+my $src;
+my $dst;
+while( $src = <TXTFILE> )
+{
+ # get rid of comments
+ $src =~ s,//.*,,g;
+
+ # skip blank lines
+ if( $src =~ m/^\s*$/ )
+ {
+ next;
+ }
+
+ # Get rid of newlines.
+ $src =~ s/\n//g;
+
+ # Save off the shader source filename.
+ my $dst = $src;
+
+ $dst =~ s/_tmp//gi;
+
+ # Does the dst exist?
+ my $dstexists = -e $dst;
+ my $srcexists = -e $src;
+ # What are the time stamps for the src and dst?
+ my $srcmodtime = ( stat $src )[9];
+ my $dstmodtime = ( stat $dst )[9];
+
+ # Open for edit or add if different than what is in perforce already.
+ if( !$dstexists || ( $srcmodtime != $dstmodtime ) )
+ {
+ # Make the target writable if it exists
+ if( $dstexists )
+ {
+ MakeFileWritable( $dst );
+ }
+
+ my $dir = $dst;
+ $dir =~ s,([^/\\]*$),,; # rip the filename off the end
+ my $filename = $1;
+
+ # create the target directory if it doesn't exist
+ if( !$dstexists )
+ {
+ &MakeDirHier( $dir, 0777 );
+ }
+
+ # copy the file to its targets. . . we want to see STDERR here if there is an error.
+ my $cmd = "copy $src $dst > nul";
+# print STDERR "$cmd\n";
+ system $cmd;
+
+ MakeFileReadOnly( $dst );
+ }
+}
+
+close TXTFILE;
diff --git a/devtools/bin/copyshaders.pl b/devtools/bin/copyshaders.pl
new file mode 100644
index 0000000..cb849a8
--- /dev/null
+++ b/devtools/bin/copyshaders.pl
@@ -0,0 +1,172 @@
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+use Cwd;
+use String::CRC32;
+
+sub ReadInputFileWithIncludes
+{
+ local( $filename ) = shift;
+
+ local( *INPUT );
+ local( $output );
+
+ open INPUT, "<$filename" || die;
+
+ local( $line );
+ local( $linenum ) = 1;
+ while( $line = <INPUT> )
+ {
+ if( $line =~ m/\#include\s+\"(.*)\"/i )
+ {
+ $output.= ReadInputFileWithIncludes( $1 );
+ }
+ else
+ {
+ $output .= $line;
+ }
+ }
+
+ close INPUT;
+ return $output;
+}
+
+sub PatchCRC
+{
+ my $filename = shift;
+ my $crc = shift;
+# print STDERR "PatchCRC( $filename, $crc )\n";
+ local( *FP );
+ open FP, "+<$filename" || die;
+ binmode( FP );
+ seek FP, 6 * 4, 0;
+ my $uInt = "I";
+ if( $filename =~ m/360/ )
+ {
+ $uInt = "N";
+ }
+ print FP pack $uInt, $crc;
+ close FP;
+}
+
+my $txtfilename = shift;
+my $arg = shift;
+
+my $is360 = 0;
+my $platformextension = "";
+if( $arg =~ m/-x360/i )
+{
+ $is360 = 1;
+ $platformextension = ".360";
+}
+
+# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
+my $changelistnumber = `valve_p4_create_changelist.cmd ..\\..\\..\\game\\hl2\\shaders \"Shader Auto Checkout VCS\"`;
+# Get rid of the newline
+$changelistnumber =~ s/\n//g;
+
+my $changelistarg = "";
+if( $changelistnumber != 0 )
+{
+ $changelistarg = "-c $changelistnumber"
+}
+
+open TXTFILE, "<$txtfilename";
+
+my $src;
+my $dst;
+while( $src = <TXTFILE> )
+{
+ # get rid of comments
+ $src =~ s,//.*,,g;
+
+ # skip blank lines
+ if( $src =~ m/^\s*$/ )
+ {
+ next;
+ }
+
+ # Get rid of newlines.
+ $src =~ s/\n//g;
+
+ # Save off the shader source filename.
+ my $shadersrcfilename = $src;
+ $shadersrcfilename =~ s/-----.*$//;
+ # use only target basename.
+ $src =~ s/^.*-----//;
+
+ # where the binary vcs file is
+ my $spath = "";
+
+ if ( $shadersrcfilename =~ m@\.fxc@i )
+ {
+ $spath = "shaders\\fxc\\";
+ }
+ if ( $shadersrcfilename =~ m@\.vsh@i )
+ {
+ $spath = "shaders\\vsh\\";
+ }
+ if ( $shadersrcfilename =~ m@\.psh@i )
+ {
+ $spath = "shaders\\psh\\";
+ }
+
+ # make the source have path and extension
+ $src = $spath . $src . $platformextension . ".vcs";
+
+ # build the dest filename.
+ $dst = $src;
+
+ $dst =~ s/shaders\\/..\\..\\..\\game\\hl2\\shaders\\/i;
+
+ # Does the dst exist?
+ my $dstexists = -e $dst;
+ my $srcexists = -e $src;
+ # What are the time stamps for the src and dst?
+ my $srcmodtime = ( stat $src )[9];
+ my $dstmodtime = ( stat $dst )[9];
+
+ # Write $dst to a file so that we can do perforce stuff to it later.
+ local( *VCSLIST );
+ open VCSLIST, ">>vcslist.txt" || die;
+ print VCSLIST $dst . "\n";
+ close VCSLIST;
+
+ # Open for edit or add if different than what is in perforce already.
+ if( !$dstexists || ( $srcmodtime != $dstmodtime ) )
+ {
+ if ( $srcexists && $shadersrcfilename =~ m@\.fxc@i )
+ {
+ # Get the CRC for the source file.
+ my $srccode = ReadInputFileWithIncludes( $shadersrcfilename );
+ my $crc = crc32( $srccode );
+
+ # Patch the source VCS file with the CRC32 of the source code used to build that file.
+ PatchCRC( $src, $crc );
+ }
+
+ # Make the target vcs writable if it exists
+ if( $dstexists )
+ {
+ MakeFileWritable( $dst );
+ }
+
+ my $dir = $dst;
+ $dir =~ s,([^/\\]*$),,; # rip the filename off the end
+ my $filename = $1;
+
+ # create the target directory if it doesn't exist
+ if( !$dstexists )
+ {
+ &MakeDirHier( $dir, 0777 );
+ }
+
+ # copy the file to its targets. . . we want to see STDERR here if there is an error.
+ my $cmd = "copy $src $dst > nul";
+# print STDERR "$cmd\n";
+ system $cmd;
+
+ MakeFileReadOnly( $dst );
+ }
+}
+
+close TXTFILE;
diff --git a/devtools/bin/crc32filewithincludes.pl b/devtools/bin/crc32filewithincludes.pl
new file mode 100644
index 0000000..6c90778
--- /dev/null
+++ b/devtools/bin/crc32filewithincludes.pl
@@ -0,0 +1,41 @@
+use String::CRC32;
+
+sub ReadInputFileWithIncludes
+{
+ local( $filename ) = shift;
+
+ local( *INPUT );
+ local( $output );
+
+ open INPUT, "<$filename" || die;
+
+ local( $line );
+ local( $linenum ) = 1;
+ while( $line = <INPUT> )
+ {
+ if( $line =~ m/\#include\s+\"(.*)\"/i )
+ {
+ $output.= ReadInputFileWithIncludes( $1 );
+ }
+ else
+ {
+ $output .= $line;
+ }
+ }
+
+ close INPUT;
+ return $output;
+}
+
+if( !scalar( @ARGV ) )
+{
+ die "Usage: crc32filewithincludes.pl filename\n";
+}
+
+$data = &ReadInputFileWithIncludes( shift );
+
+#print "data: $data\n";
+
+$crc = crc32( $data );
+print $crc;
+exit 0;
diff --git a/devtools/bin/d3dx10_33.dll b/devtools/bin/d3dx10_33.dll
new file mode 100644
index 0000000..05342c8
--- /dev/null
+++ b/devtools/bin/d3dx10_33.dll
Binary files differ
diff --git a/devtools/bin/d3dx9_33.dll b/devtools/bin/d3dx9_33.dll
new file mode 100644
index 0000000..a005f8f
--- /dev/null
+++ b/devtools/bin/d3dx9_33.dll
Binary files differ
diff --git a/devtools/bin/dbmon.exe b/devtools/bin/dbmon.exe
new file mode 100644
index 0000000..ef8c64a
--- /dev/null
+++ b/devtools/bin/dbmon.exe
Binary files differ
diff --git a/devtools/bin/diff.exe b/devtools/bin/diff.exe
new file mode 100644
index 0000000..2797ffd
--- /dev/null
+++ b/devtools/bin/diff.exe
Binary files differ
diff --git a/devtools/bin/diff3.exe b/devtools/bin/diff3.exe
new file mode 100644
index 0000000..9ee2632
--- /dev/null
+++ b/devtools/bin/diff3.exe
Binary files differ
diff --git a/devtools/bin/diffmemstats.exe b/devtools/bin/diffmemstats.exe
new file mode 100644
index 0000000..5f4e329
--- /dev/null
+++ b/devtools/bin/diffmemstats.exe
Binary files differ
diff --git a/devtools/bin/ezxmlfile.py b/devtools/bin/ezxmlfile.py
new file mode 100644
index 0000000..a32ea5e
--- /dev/null
+++ b/devtools/bin/ezxmlfile.py
@@ -0,0 +1,175 @@
+
+import sys, re, vsdotnetxmlparser
+
+
+
+class EZXMLError:
+ pass
+
+
+class EZXMLElement:
+ """
+ Members:
+ Name : string
+ Attrs : list with attributes [(name,value), (name, value), ...]
+ Children : list of XMLElements
+ Parent : parent XMLElement
+ """
+ def GetAttributeValue( self, attrName ):
+ for a in self.Attrs:
+ if a[0] == attrName:
+ return a[1]
+ return None
+
+ def RemoveAttribute( self, attrName ):
+ for i,a in enumerate( self.Attrs ):
+ if a[0] == attrName:
+ self.Attrs.pop( i )
+ return 1
+
+ return 0
+
+ def RemoveFromParent( self ):
+ if not self.Parent:
+ raise EZXMLError
+
+ self.Parent.Children.remove( self )
+
+
+class EZXMLFile:
+ #
+ # PUBLIC INTERFACE
+ #
+ def __init__( self, data ):
+ self.Version = ''
+ self.Encoding = ''
+ self.RootElement = None
+ self.__CurElement = None
+ self.__ElementIndexRE = re.compile( r'<(?P<index>.+)>(?P<name>.+)' )
+
+ #p = xml.parsers.expat.ParserCreate()
+ p = vsdotnetxmlparser.VSDotNetXMLParser()
+
+ p.ordered_attributes = 1
+ p.XmlDeclHandler = self.__xml_decl_handler
+ p.StartElementHandler = self.__start_element
+ p.EndElementHandler = self.__end_element
+
+ p.Parse( data, 1 )
+
+
+ # Write the current contents to a file.
+ def WriteFile( self, file ):
+ file.write( '<?xml version="%s" encoding="%s"?>\r\n' % (self.Version, self.Encoding) )
+ if self.RootElement:
+ self.__WriteFile_R( file, self.RootElement, 0 )
+
+ """
+ Find an element (starting at the root).
+ If elementName has backslashes in it (like 'VisualStudioProject\Configurations\Tool'), then it will recurse into each element.
+ Each element can also have an optional count telling which element to find:
+ 'VisualStudioProject\Configurations\<3>Tool'
+ """
+ def GetElement( self, elementName ):
+ if not self.RootElement:
+ return None
+
+ pathList = elementName.split( '\\' )
+ return self.__GetElementByPath_R( [self.RootElement], pathList, 0 )
+
+
+ """
+ AttributePath is specified the same way as GetElement.
+ Returns None if the path to the element or attribute doesn't exist.
+ """
+ def GetAttribute( self, attributePath ):
+ if not self.RootElement:
+ return None
+
+ pathList = attributePath.split( '\\' )
+ attributeName = pathList.pop()
+ e = self.__GetElementByPath_R( [self.RootElement], pathList, 0 )
+ if e:
+ return e.GetAttributeValue( attributeName )
+ else:
+ return None
+
+
+
+ #
+ # INTERNAL STUFF
+ #
+ def __GetElementByPath_R( self, curElementList, pathList, index ):
+ indexToFind = 1
+ indexFound = 0
+ m = self.__ElementIndexRE.match( pathList[index] )
+ if m:
+ nameToFind = m.group('name').upper()
+ indexToFind = int( m.group('index') )
+ else:
+ nameToFind = pathList[index].upper()
+
+ for x in curElementList:
+ if x.Name.upper() == nameToFind:
+ indexFound += 1
+ if indexFound == indexToFind:
+ if index == len( pathList ) - 1:
+ return x
+ else:
+ return self.__GetElementByPath_R( x.Children, pathList, index+1 )
+
+ return None
+
+ def __WriteFile_R( self, file, curElement, indentLevel ):
+ tabChars = ""
+ for i in xrange(0,indentLevel):
+ tabChars = tabChars + '\t'
+ file.write( tabChars )
+
+ keyListLen = len( curElement.Attrs )
+ if keyListLen == 0:
+ file.write( '<%s>\r\n' % (curElement.Name) )
+ else:
+ file.write( '<%s\r\n' % (curElement.Name) )
+
+ bClosedBlock = 0
+ for i,e in enumerate( curElement.Attrs ):
+ file.write( tabChars + '\t' )
+ file.write( '%s="%s"' % (e[0], e[1]) )
+
+ # VS.NET XML files use this special syntax on elements that have attributes and no children.
+ if len( curElement.Children ) == 0 and i == keyListLen-1 and curElement.Name != 'File':
+ file.write( '/>\r\n' )
+ bClosedBlock = 1
+ elif i == keyListLen-1:
+ file.write( '>\r\n' )
+ else:
+ file.write( '\r\n' )
+
+ for child in curElement.Children:
+ self.__WriteFile_R( file, child, indentLevel+1 )
+
+ if not bClosedBlock:
+ file.write( tabChars )
+ file.write( '</%s>\r\n' % (curElement.Name) )
+
+ # XML parser handler functions
+ def __xml_decl_handler( self, version, encoding, standalone ):
+ self.Version = version
+ self.Encoding = encoding
+
+ def __start_element( self, name, attrs ):
+ e = EZXMLElement()
+ e.Name = name
+ e.Attrs = zip( attrs[::2], attrs[1::2] ) # Cool slicing trick.. this takes a list like [1,2,3,4] and makes it into [[1,2], [3,4]]
+ e.Children = None
+ e.Parent = self.__CurElement
+ e.Children = []
+ if self.__CurElement:
+ self.__CurElement.Children.append( e )
+ else:
+ self.RootElement = e
+ self.__CurElement = e
+
+ def __end_element( self, name ):
+ self.__CurElement = self.__CurElement.Parent
diff --git a/devtools/bin/fix_particle_operator_names.pl b/devtools/bin/fix_particle_operator_names.pl
new file mode 100644
index 0000000..c0f5ee0
--- /dev/null
+++ b/devtools/bin/fix_particle_operator_names.pl
@@ -0,0 +1,110 @@
+#!perl
+use File::Find;
+
+&BuildRemapTable;
+
+find(\&convert, "." );
+
+
+sub convert
+ {
+ return unless (/\.pcf$/i);
+ return if (/^tmp\.pcf$/i);
+ return if (/^tmp2\.pcf$/i);
+ return if (/360\.pcf$/i);
+ print STDERR "process ", $File::Find::name," ($_) dir=",`cd`," \n";
+ my $fname=$_;
+ print `p4 edit $fname`;
+ print `dmxconvert -i $_ -o tmp.pcf -oe keyvalues2`;
+ open(TMP, "tmp.pcf" ) || return;
+ open(OUT, ">tmp2.pcf" ) || die;
+ while(<TMP>)
+ {
+ s/[\n\r]//g;
+ if ( (/^(\s*\"functionName\"\s*\"string\"\s*\")(.*)\"(.*)$/) &&
+ length($map{$2}) )
+ {
+ $_=$1.$map{$2}.'"'.$3;
+ }
+ if ( (/^(\s*\"name\"\s*\"string\"\s*\")(.*)\"(.*)$/) &&
+ length($map{$2}) )
+ {
+ $_=$1.$map{$2}.'"'.$3;
+ }
+ print OUT "$_\n";
+ }
+ close OUT;
+ close TMP;
+ print `dmxconvert -i tmp2.pcf -o $fname -ie keyvalues2 -oe binary`;
+ unlink "tmp.pcf";
+ unlink "tmp2.pcf";
+}
+
+
+
+
+
+
+
+
+
+
+
+
+sub BuildRemapTable
+{
+ $map{"alpha_fade"}= "Alpha Fade and Decay";
+ $map{"alpha_fade_in_random"}= "Alpha Fade In Random";
+ $map{"alpha_fade_out_random"}= "Alpha Fade Out Random";
+ $map{"basic_movement"}= "Movement Basic";
+ $map{"color_fade"}= "Color Fade";
+ $map{"controlpoint_light"}= "Color Light From Control Point";
+ $map{"Dampen Movement Relative to Control Point"}= "Movement Dampen Relative to Control Point";
+ $map{"Distance Between Control Points Scale"}= "Remap Distance Between Two Control Points to Scalar";
+ $map{"Distance to Control Points Scale"}= "Remap Distance to Control Point to Scalar";
+ $map{"lifespan_decay"}= "Lifespan Decay";
+ $map{"lock to bone"}= "Movement Lock to Bone";
+ $map{"postion_lock_to_controlpoint"}= "Movement Lock to Control Point";
+ $map{"maintain position along path"}= "Movement Maintain Position Along Path";
+ $map{"Match Particle Velocities"}= "Movement Match Particle Velocities";
+ $map{"Max Velocity"}= "Movement Max Velocity";
+ $map{"noise"}= "Noise Scalar";
+ $map{"vector noise"}= "Noise Vector";
+ $map{"oscillate_scalar"}= "Oscillate Scalar";
+ $map{"oscillate_vector"}= "Oscillate Vector";
+ $map{"Orient Rotation to 2D Direction"}= "Rotation Orient to 2D Direction";
+ $map{"radius_scale"}= "Radius Scale";
+ $map{"Random Cull"}= "Cull Random";
+ $map{"remap_scalar"}= "Remap Scalar";
+ $map{"rotation_movement"}= "Rotation Basic";
+ $map{"rotation_spin"}= "Rotation Spin Roll";
+ $map{"rotation_spin yaw"}= "Rotation Spin Yaw";
+ $map{"alpha_random"}= "Alpha Random";
+ $map{"color_random"}= "Color Random";
+ $map{"create from parent particles"}= "Position From Parent Particles";
+ $map{"Create In Hierarchy"}= "Position In CP Hierarchy";
+ $map{"random position along path"}= "Position Along Path Random";
+ $map{"random position on model"}= "Position on Model Random";
+ $map{"sequential position along path"}= "Position Along Path Sequential";
+ $map{"position_offset_random"}= "Position Modify Offset Random";
+ $map{"position_warp_random"}= "Position Modify Warp Random";
+ $map{"position_within_box"}= "Position Within Box Random";
+ $map{"position_within_sphere"}= "Position Within Sphere Random";
+ $map{"Inherit Velocity"}= "Velocity Inherit from Control Point";
+ $map{"Initial Repulsion Velocity"}= "Velocity Repulse from World";
+ $map{"Initial Velocity Noise"}= "Velocity Noise";
+ $map{"Initial Scalar Noise"}= "Remap Noise to Scalar";
+ $map{"Lifespan from distance to world"}= "Lifetime from Time to Impact";
+ $map{"Pre-Age Noise"}= "Lifetime Pre-Age Noise";
+ $map{"lifetime_random"}= "Lifetime Random";
+ $map{"radius_random"}= "Radius Random";
+ $map{"random yaw"}= "Rotation Yaw Random";
+ $map{"Randomly Flip Yaw"}= "Rotation Yaw Flip Random";
+ $map{"rotation_random"}= "Rotation Random";
+ $map{"rotation_speed_random"}= "Rotation Speed Random";
+ $map{"sequence_random"}= "Sequence Random";
+ $map{"second_sequence_random"}= "Sequence Two Random";
+ $map{"trail_length_random"}= "Trail Length Random";
+ $map{"velocity_random"}= "Velocity Random";
+}
+
diff --git a/devtools/bin/fixcopyrights.py b/devtools/bin/fixcopyrights.py
new file mode 100644
index 0000000..ba43986
--- /dev/null
+++ b/devtools/bin/fixcopyrights.py
@@ -0,0 +1,177 @@
+#!/usr/bin/python
+# ========= Copyright Valve Corporation, All rights reserved. ============
+
+import subprocess
+import re
+import os
+import sys
+
+reValve = re.compile( "valve", flags = re.IGNORECASE )
+reTurtleRock = re.compile( "turtle rock", flags = re.IGNORECASE )
+reCopyright = re.compile( "copyright", flags = re.IGNORECASE )
+sOutputCopyright = "//========= Copyright Valve Corporation, All rights reserved. ============//\n"
+
+def IsOldCopyrightLine( line ):
+ if( len( reCopyright.findall( line ) ) == 0 ):
+ return False
+ if( len( reValve.findall( line ) ) == 0
+ and len( reTurtleRock.findall( line ) ) == 0 ):
+ return False
+
+ return True
+
+
+rFilesWithNoCopyrightNotice = []
+
+def FixCopyrightNotice( sFullPath ):
+ nLine = 0
+
+ f = open( sFullPath, "r" )
+ if( not f ):
+ print( "Unable to open file " + sFullPath + "\n" )
+ return
+
+ rFileContents = f.readlines()
+ f.close()
+ nOldCopyright = -1
+ for line in rFileContents:
+ if( nLine < 10 ):
+ if( line == sOutputCopyright ):
+ # File already has the right notice
+ return
+ if( IsOldCopyrightLine( line ) ):
+ nOldCopyright = nLine
+ break
+
+ nLine += 1
+ if( nOldCopyright == -1 ):
+ rFilesWithNoCopyrightNotice.append( sFullPath )
+ rFileContents.insert( 0, sOutputCopyright )
+ else:
+ rFileContents[ nOldCopyright ] = sOutputCopyright
+
+ # open the file for edit
+ subprocess.call( [ "p4", "edit", sFullPath ], stdout = subprocess.PIPE )
+
+ # open the file for writing
+ f = open( sFullPath, "w" )
+ f.writelines( rFileContents )
+ f.close()
+
+rDirsToSkip = [
+ 'thirdparty',
+ 'external',
+ 'BinkSDK',
+ 'bink',
+ 'bink_x360',
+ 'freetype',
+ 'GL',
+ 'maya',
+ 'miles',
+ 'curl',
+ 'ihfx',
+ 'lxma',
+ 'modo',
+ 'openal',
+ 'opengl',
+ 'p4api',
+ 'python',
+ 'quicktime_win32',
+ 'xsi',
+ 'speex',
+ 'ocaml',
+ 'perl5',
+ 'dx10sdk',
+ 'dx11sdk',
+ 'dx9sdk',
+ 'haptics',
+ 'ajb',
+ 'stb',
+ 'havok',
+ 'hk_physics',
+ 'lua',
+ 'maxsdk',
+ 'x360xdk',
+ 'swigwin-1.3.34',
+ 'sapi51',
+ 'WMPSDK10',
+ 'FontMaker',
+ 'mxtk',
+ 'nvtristriplib',
+ 'g15',
+ 'lzma',
+ 'libparsifal-0.8.3',
+ 'parsifal',
+ 'libpng',
+ 'mysql',
+ 'zip',
+ 'zlib',
+ 'Zlib',
+ 'windowssdk',
+ 'bzip2',
+ 'jpeglib',
+ 'MakeGameData',
+ 'toollib',
+ ]
+
+rFileExtensionsToSkip = [
+ '.pb.h',
+ '.pb.cpp',
+ '.spa.h',
+ 'ATI_Compress.h',
+ 'luaxlib.h',
+ 'lua.h',
+ 'luaconf.h',
+ 'lualib.h',
+ 'eax.h',
+ 'IceKey.cpp',
+ 'nvtc.h',
+ 'amd3dx.h',
+ 'halton.h',
+ 'snappy',
+ 'extendedtrace',
+ ]
+
+def FixCopyrightNoticeWalk( sPath ):
+ for root, dirs, files in os.walk( sPath ):
+ print "Walking directory", root
+ #print root, dirs
+ for sDir in rDirsToSkip:
+ if sDir in dirs:
+ print "Skipping dir ", os.path.join( root, sDir )
+ dirs.remove( sDir )
+
+ for sFilename in files:
+ sShortFilename, sFileExt = os.path.splitext( sFilename )
+
+ if( sFileExt in [ '.cpp', '.h' ] ):
+ bSkip = False
+ for sExt in rFileExtensionsToSkip:
+ if sExt in sFilename:
+ bSkip = True
+
+ #print "filename=", sFilename
+ if( bSkip ):
+ print "Skipping ", sFilename, "because of its extension"
+ else:
+ FixCopyrightNotice( os.path.join( root, sFilename ) )
+
+
+#FixCopyrightNotice( os.path.join( "..", "..", "bitmap", "bitmap.cpp" ) )
+#FixCopyrightNoticeWalk( os.path.join( "..", "..", "bitmap" ) )
+
+if( len( sys.argv ) != 2 ):
+ print "Usage: fixcopyrights.py <path>"
+ sys.exit(1)
+
+FixCopyrightNoticeWalk( sys.argv[1] )
+
+if( len( rFilesWithNoCopyrightNotice ) ):
+
+ f = open( "newcopyrights.txt", "w" )
+ for file in rFilesWithNoCopyrightNotice:
+ f.write( file + "\n" )
+ f.close()
+
+ print "Copyright notices added to", len( rFilesWithNoCopyrightNotice ), "files. See newcopyrights.txt for a list\n"
+
diff --git a/devtools/bin/fontmaker.exe b/devtools/bin/fontmaker.exe
new file mode 100644
index 0000000..350aee9
--- /dev/null
+++ b/devtools/bin/fontmaker.exe
Binary files differ
diff --git a/devtools/bin/fontmaker.pdb b/devtools/bin/fontmaker.pdb
new file mode 100644
index 0000000..ee89fcb
--- /dev/null
+++ b/devtools/bin/fontmaker.pdb
Binary files differ
diff --git a/devtools/bin/fxc_prep.pl b/devtools/bin/fxc_prep.pl
new file mode 100644
index 0000000..9f67ca5
--- /dev/null
+++ b/devtools/bin/fxc_prep.pl
@@ -0,0 +1,949 @@
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+
+sub ReadInputFile
+{
+ local( $filename ) = shift;
+ local( *INPUT );
+ local( @output );
+ open INPUT, "<$filename" || die;
+
+ local( $line );
+ local( $linenum ) = 1;
+ while( $line = <INPUT> )
+ {
+# print "LINE: $line";
+# $line =~ s/\n//g;
+# local( $postfix ) = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+# $postfix .= "; LINEINFO($filename)($linenum)\n";
+ if( $line =~ m/\#include\s+\"(.*)\"/i )
+ {
+ push @output, &ReadInputFile( $1 );
+ }
+ else
+ {
+# push @output, $line . $postfix;
+ push @output, $line;
+ }
+ $linenum++;
+ }
+
+ close INPUT;
+# print "-----------------\n";
+# print @output;
+# print "-----------------\n";
+ return @output;
+}
+
+$dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0;
+$generateListingFile = 0;
+$spewCombos = 0;
+
+@startTimes = times;
+$startTime = time;
+
+$g_produceCppClasses = 1;
+$g_produceCompiledVcs = 1;
+
+while( 1 )
+{
+ $fxc_filename = shift;
+ if( $fxc_filename =~ m/-source/ )
+ {
+ shift;
+ }
+ elsif( $fxc_filename =~ m/-nv3x/i )
+ {
+ $nvidia = 1;
+ }
+ elsif( $fxc_filename =~ m/-ps20a/i )
+ {
+ $ps2a = 1;
+ }
+ elsif( $fxc_filename =~ m/-x360/i )
+ {
+ # enable x360
+ $g_x360 = 1;
+ }
+ elsif( $fxc_filename =~ m/-novcs/i )
+ {
+ $g_produceCompiledVcs = 0;
+ }
+ elsif( $fxc_filename =~ m/-nocpp/i )
+ {
+ $g_produceCppClasses = 0;
+ }
+ else
+ {
+ last;
+ }
+}
+
+$argstring = $fxc_filename;
+$fxc_basename = $fxc_filename;
+$fxc_basename =~ s/^.*-----//;
+$fxc_filename =~ s/-----.*$//;
+
+$debug = 0;
+$forcehalf = 0;
+
+sub ToUpper
+{
+ local( $in ) = shift;
+ $in =~ tr/a-z/A-Z/;
+ return $in;
+}
+
+sub CreateCCodeToSpewDynamicCombo
+{
+ local( $out ) = "";
+
+ $out .= "\t\tOutputDebugString( \"src:$fxc_filename vcs:$fxc_basename dynamic index\" );\n";
+ $out .= "\t\tchar tmp[128];\n";
+ $out .= "\t\tint shaderID = ";
+ local( $scale ) = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ local( $name ) = @dynamicDefineNames[$i];
+ local( $varname ) = "m_n" . $name;
+ $out .= "( $scale * $varname ) + ";
+ $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ $out .= "0;\n";
+ if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 )
+ {
+ $out .= "\t\tint nCombo = shaderID;\n";
+ }
+
+ my $type = GetShaderType( $fxc_filename );
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $out .= "\t\tint n$dynamicDefineNames[$i] = nCombo % ";
+ $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
+ $out .= ";\n";
+
+ $out .= "\t\tsprintf( tmp, \"\%d\", n$dynamicDefineNames[$i] );\n";
+ $out .= "\t\tOutputDebugString( \" $dynamicDefineNames[$i]";
+ $out .= "=\" );\n";
+ $out .= "\t\tOutputDebugString( tmp );\n";
+
+ $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
+ $out .= "\n";
+ }
+ $out .= "\t\tOutputDebugString( \"\\n\" );\n";
+ return $out;
+}
+
+sub CreateCCodeToSpewStaticCombo
+{
+ local( $out ) = "";
+
+ $out .= "\t\tOutputDebugString( \"src:$fxc_filename vcs:$fxc_basename static index\" );\n";
+ $out .= "\t\tchar tmp[128];\n";
+ $out .= "\t\tint shaderID = ";
+
+ local( $scale ) = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ local( $name ) = @staticDefineNames[$i];
+ local( $varname ) = "m_n" . $name;
+ $out .= "( $scale * $varname ) + ";
+ $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
+ }
+ $out .= "0;\n";
+
+# $out .= "\t\tsprintf( tmp, \"\%d\\n\", shaderID );\n";
+# $out .= "\t\tOutputDebugString( tmp );\n\n";
+ if( scalar( @staticDefineNames ) + scalar( @staticDefineNames ) > 0 )
+ {
+ $out .= "\t\tint nCombo = shaderID;\n";
+ }
+
+ my $type = GetShaderType( $fxc_filename );
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $out .= "\t\tint n$staticDefineNames[$i] = nCombo % ";
+ $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
+ $out .= ";\n";
+
+ $out .= "\t\tsprintf( tmp, \"\%d\", n$staticDefineNames[$i] );\n";
+ $out .= "\t\tOutputDebugString( \" $staticDefineNames[$i]";
+ $out .= "=\" );\n";
+ $out .= "\t\tOutputDebugString( tmp );\n";
+
+ $out .= "\t\tnCombo = nCombo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n";
+ $out .= "\n";
+ }
+ $out .= "\t\tOutputDebugString( \"\\n\" );\n";
+ return $out;
+}
+
+sub WriteHelperVar
+{
+ local( $name ) = shift;
+ local( $min ) = shift;
+ local( $max ) = shift;
+ local( $varname ) = "m_n" . $name;
+ local( $boolname ) = "m_b" . $name;
+ push @outputHeader, "private:\n";
+ push @outputHeader, "\tint $varname;\n";
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\tbool $boolname;\n";
+ push @outputHeader, "#endif\n";
+ push @outputHeader, "public:\n";
+ # int version of set function
+ push @outputHeader, "\tvoid Set" . $name . "( int i )\n";
+ push @outputHeader, "\t{\n";
+ push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
+ push @outputHeader, "\t\t$varname = i;\n";
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\t\t$boolname = true;\n";
+ push @outputHeader, "#endif\n";
+ push @outputHeader, "\t}\n";
+ # bool version of set function
+ push @outputHeader, "\tvoid Set" . $name . "( bool i )\n";
+ push @outputHeader, "\t{\n";
+# push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
+ push @outputHeader, "\t\t$varname = i ? 1 : 0;\n";
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\t\t$boolname = true;\n";
+ push @outputHeader, "#endif\n";
+ push @outputHeader, "\t}\n";
+}
+
+sub WriteStaticBoolExpression
+{
+ local( $prefix ) = shift;
+ local( $operator ) = shift;
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ if( $i )
+ {
+ push @outputHeader, " $operator ";
+ }
+ local( $name ) = @staticDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ push @outputHeader, "$prefix$boolname";
+ }
+ push @outputHeader, ";\n";
+}
+
+sub WriteDynamicBoolExpression
+{
+ local( $prefix ) = shift;
+ local( $operator ) = shift;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ if( $i )
+ {
+ push @outputHeader, " $operator ";
+ }
+ local( $name ) = @dynamicDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ push @outputHeader, "$prefix$boolname";
+ }
+ push @outputHeader, ";\n";
+}
+
+sub WriteDynamicHelperClasses
+{
+ local( $basename ) = $fxc_basename;
+ $basename =~ tr/A-Z/a-z/;
+ local( $classname ) = $basename . "_Dynamic_Index";
+ push @outputHeader, "class $classname\n";
+ push @outputHeader, "{\n";
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $name = $dynamicDefineNames[$i];
+ $min = $dynamicDefineMin[$i];
+ $max = $dynamicDefineMax[$i];
+ &WriteHelperVar( $name, $min, $max );
+ }
+ push @outputHeader, "public:\n";
+# push @outputHeader, "void SetPixelShaderIndex( IShaderAPI *pShaderAPI ) { pShaderAPI->SetPixelShaderIndex( GetIndex() ); }\n";
+ push @outputHeader, "\t$classname()\n";
+ push @outputHeader, "\t{\n";
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ local( $name ) = @dynamicDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ local( $varname ) = "m_n" . $name;
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\t\t$boolname = false;\n";
+ push @outputHeader, "#endif // _DEBUG\n";
+ push @outputHeader, "\t\t$varname = 0;\n";
+ }
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "\tint GetIndex()\n";
+ push @outputHeader, "\t{\n";
+ push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
+ foreach $skip (@perlskipcodeindividual)
+ {
+ # can't do this static and dynamic can see each other.
+# $skip =~ s/\$/m_n/g;
+# $skip =~ s/defined//g;
+# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
+# print "\t\tAssert( !( $skip ) );\n";
+ }
+ push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
+
+ push @outputHeader, "#ifdef _DEBUG\n";
+ if( scalar( @dynamicDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tbool bAllDynamicVarsDefined = ";
+ WriteDynamicBoolExpression( "", "&&" );
+ }
+ if( scalar( @dynamicDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tAssert( bAllDynamicVarsDefined );\n";
+ }
+ push @outputHeader, "#endif // _DEBUG\n";
+
+ if( $spewCombos && scalar( @dynamicDefineNames ) )
+ {
+ push @outputHeader, &CreateCCodeToSpewDynamicCombo();
+ }
+ push @outputHeader, "\t\treturn ";
+ local( $scale ) = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ local( $name ) = @dynamicDefineNames[$i];
+ local( $varname ) = "m_n" . $name;
+ push @outputHeader, "( $scale * $varname ) + ";
+ $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ push @outputHeader, "0;\n";
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "};\n";
+ push @outputHeader, "\#define shaderDynamicTest_" . $basename . " ";
+ my $prefix;
+ my $shaderType = &GetShaderType( $fxc_filename );
+ if( $shaderType =~ m/^vs/i )
+ {
+ $prefix = "vsh_";
+ }
+ else
+ {
+ $prefix = "psh_";
+ }
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ local( $name ) = @dynamicDefineNames[$i];
+ push @outputHeader, $prefix . "forgot_to_set_dynamic_" . $name . " + ";
+ }
+ push @outputHeader, "0\n";
+}
+
+sub WriteStaticHelperClasses
+{
+ local( $basename ) = $fxc_basename;
+ $basename =~ tr/A-Z/a-z/;
+ local( $classname ) = $basename . "_Static_Index";
+ push @outputHeader, "#include \"shaderlib/cshader.h\"\n";
+ push @outputHeader, "class $classname\n";
+ push @outputHeader, "{\n";
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $name = $staticDefineNames[$i];
+ $min = $staticDefineMin[$i];
+ $max = $staticDefineMax[$i];
+ &WriteHelperVar( $name, $min, $max );
+ }
+ push @outputHeader, "public:\n";
+# push @outputHeader, "void SetShaderIndex( IShaderShadow *pShaderShadow ) { pShaderShadow->SetPixelShaderIndex( GetIndex() ); }\n";
+ push @outputHeader, "\t$classname( )\n";
+ push @outputHeader, "\t{\n";
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ local( $name ) = @staticDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ local( $varname ) = "m_n" . $name;
+ if ( length( $staticDefineInit{$name} ) )
+ {
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\t\t$boolname = true;\n";
+ push @outputHeader, "#endif // _DEBUG\n";
+ push @outputHeader, "\t\t$varname = $staticDefineInit{$name};\n";
+ }
+ else
+ {
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\t\t$boolname = false;\n";
+ push @outputHeader, "#endif // _DEBUG\n";
+ push @outputHeader, "\t\t$varname = 0;\n";
+ }
+ }
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "\tint GetIndex()\n";
+ push @outputHeader, "\t{\n";
+ push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
+ foreach $skip (@perlskipcodeindividual)
+ {
+ $skip =~ s/\$/m_n/g;
+# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
+ }
+ push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
+
+ push @outputHeader, "#ifdef _DEBUG\n";
+ if( scalar( @staticDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tbool bAllStaticVarsDefined = ";
+ WriteStaticBoolExpression( "", "&&" );
+
+ }
+ if( scalar( @staticDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tAssert( bAllStaticVarsDefined );\n";
+ }
+ push @outputHeader, "#endif // _DEBUG\n";
+
+ if( $spewCombos && scalar( @staticDefineNames ) )
+ {
+ push @outputHeader, &CreateCCodeToSpewStaticCombo();
+ }
+ push @outputHeader, "\t\treturn ";
+ local( $scale ) = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ local( $name ) = @staticDefineNames[$i];
+ local( $varname ) = "m_n" . $name;
+ push @outputHeader, "( $scale * $varname ) + ";
+ $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
+ }
+ push @outputHeader, "0;\n";
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "};\n";
+ push @outputHeader, "\#define shaderStaticTest_" . $basename . " ";
+ my $prefix;
+ my $shaderType = &GetShaderType( $fxc_filename );
+ if( $shaderType =~ m/^vs/i )
+ {
+ $prefix = "vsh_";
+ }
+ else
+ {
+ $prefix = "psh_";
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ local( $name ) = @staticDefineNames[$i];
+ push @outputHeader, $prefix . "forgot_to_set_static_" . $name . " + " unless (length($staticDefineInit{$name} ));
+ }
+ push @outputHeader, "0\n";
+}
+
+sub GetNewMainName
+{
+ local( $shadername ) = shift;
+ local( $combo ) = shift;
+ local( $i );
+ $shadername =~ s/\./_/g;
+ local( $name ) = $shadername;
+ for( $i = 0; $i < scalar( @defineNames ); $i++ )
+ {
+ local( $val ) = ( $combo % ( $defineMax[$i] - $defineMin[$i] + 1 ) ) + $defineMin[$i];
+ $name .= "_" . $defineNames[$i] . "_" . $val;
+ $combo = $combo / ( $defineMax[$i] - $defineMin[$i] + 1 );
+ }
+# return $name;
+ return "main";
+}
+
+sub RenameMain
+{
+ local( $shadername ) = shift;
+ local( $combo ) = shift;
+ local( $name ) = &GetNewMainName( $shadername, $combo );
+ return "/Dmain=$name /E$name ";
+}
+
+sub GetShaderType
+{
+ local( $shadername ) = shift; # hack - use global variables
+ $shadername = $fxc_basename;
+ if( $shadername =~ m/ps30/i )
+ {
+ if( $debug )
+ {
+ return "ps_3_sw";
+ }
+ else
+ {
+ return "ps_3_0";
+ }
+ }
+ elsif( $shadername =~ m/ps20b/i )
+ {
+ return "ps_2_b";
+ }
+ elsif( $shadername =~ m/ps20/i )
+ {
+ if( $debug )
+ {
+ return "ps_2_sw";
+ }
+ else
+ {
+ if( $ps2a )
+ {
+ return "ps_2_a";
+ }
+ else
+ {
+ return "ps_2_0";
+ }
+ }
+ }
+ elsif( $shadername =~ m/ps14/i )
+ {
+ return "ps_1_4";
+ }
+ elsif( $shadername =~ m/ps11/i )
+ {
+ return "ps_1_1";
+ }
+ elsif( $shadername =~ m/vs30/i )
+ {
+ if( $debug )
+ {
+ return "vs_3_sw";
+ }
+ else
+ {
+ return "vs_3_0";
+ }
+ }
+ elsif( $shadername =~ m/vs20/i )
+ {
+ if( $debug )
+ {
+ return "vs_2_sw";
+ }
+ else
+ {
+ return "vs_2_0";
+ }
+ }
+ elsif( $shadername =~ m/vs14/i )
+ {
+ return "vs_1_1";
+ }
+ elsif( $shadername =~ m/vs11/i )
+ {
+ return "vs_1_1";
+ }
+ else
+ {
+ die "\n\nSHADERNAME = $shadername\n\n";
+ }
+}
+
+sub CalcNumCombos
+{
+ local( $i, $numCombos );
+ $numCombos = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
+ }
+ return $numCombos;
+}
+
+sub CalcNumDynamicCombos
+{
+ local( $i, $numCombos );
+ $numCombos = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ return $numCombos;
+}
+
+sub CreateCFuncToCreateCompileCommandLine
+{
+ local( $out ) = "";
+
+ $out .= "\t\tOutputDebugString( \"compiling src:$fxc_filename vcs:$fxc_basename \" );\n";
+ $out .= "\t\tchar tmp[128];\n";
+ $out .= "\t\tsprintf( tmp, \"\%d\\n\", shaderID );\n";
+ $out .= "\t\tOutputDebugString( tmp );\n";
+ $out .= "\t\tstatic PrecompiledShaderByteCode_t byteCode;\n";
+ if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 )
+ {
+ $out .= "\t\tint nCombo = shaderID;\n";
+ }
+
+# $out .= "\tvoid BuildCompileCommandLine( int nCombo, char *pResult, int maxLength )\n";
+# $out .= "\t{\n";
+ $out .= "\t\tD3DXMACRO ";
+ $out .= "defineMacros";
+ $out .= "[";
+ $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) + 1; # add 1 for null termination
+ $out .= "];\n";
+ if( scalar( @dynamicDefineNames ) + scalar( @staticDefineNames ) > 0 )
+ {
+ $out .= "\t\tchar tmpStringBuf[1024];\n";
+ $out .= "\t\tchar *pTmpString = tmpStringBuf;\n\n";
+ }
+
+ local( $i );
+ my $type = GetShaderType( $fxc_filename );
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $out .= "\t\tsprintf( pTmpString, \"%d\", nCombo % ";
+ $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
+ $out .= " );\n";
+ $out .= "\t\tdefineMacros";
+ $out .= "[";
+ $out .= $i;
+ $out .= "]";
+ $out .= "\.Name = ";
+ $out .= "\"$dynamicDefineNames[$i]\";\n";
+
+ $out .= "\t\tint n$dynamicDefineNames[$i] = nCombo % ";
+ $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
+ $out .= ";\n";
+ $out .= "\t\tUNUSED( n$dynamicDefineNames[$i] );\n";
+
+ $out .= "\t\tdefineMacros";
+ $out .= "[";
+ $out .= $i;
+ $out .= "]";
+ $out .= "\.Definition = ";
+ $out .= "pTmpString;\n";
+ $out .= "\t\tpTmpString += strlen( pTmpString ) + 1;\n";
+
+ $out .= "\t\tsprintf( tmp, \"\%d\", n$dynamicDefineNames[$i] );\n";
+ $out .= "\t\tOutputDebugString( \" $dynamicDefineNames[$i]";
+ $out .= "=\" );\n";
+ $out .= "\t\tOutputDebugString( tmp );\n";
+
+ $out .= "\t\tnCombo = nCombo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
+ $out .= "\n";
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $out .= "\t\tsprintf( pTmpString, \"%d\", nCombo % ";
+ $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
+ $out .= " );\n";
+ $out .= "\t\tdefineMacros";
+ $out .= "[";
+ $out .= $i + scalar( @dynamicDefineNames );
+ $out .= "]";
+ $out .= "\.Name = ";
+ $out .= "\"$staticDefineNames[$i]\";\n";
+
+ $out .= "\t\tint n$staticDefineNames[$i] = nCombo % ";
+ $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
+ $out .= ";\n";
+ $out .= "\t\tUNUSED( n$staticDefineNames[$i] );\n";
+
+ $out .= "\t\tdefineMacros";
+ $out .= "[";
+ $out .= $i + scalar( @dynamicDefineNames );
+ $out .= "]";
+ $out .= "\.Definition = ";
+ $out .= "pTmpString;\n";
+ $out .= "\t\tpTmpString += strlen( pTmpString ) + 1;\n";
+
+ $out .= "\t\tsprintf( tmp, \"\%d\", n$staticDefineNames[$i] );\n";
+ $out .= "\t\tOutputDebugString( \" $staticDefineNames[$i]";
+ $out .= "=\" );\n";
+ $out .= "\t\tOutputDebugString( tmp );\n";
+
+ $out .= "\t\tnCombo = nCombo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n";
+ $out .= "\n";
+ }
+
+ $out .= "\t\tOutputDebugString( \"\\n\" );\n";
+
+ $cskipcode = $perlskipcode;
+ $cskipcode =~ s/\$/n/g;
+ $out .= "\t\tif( $cskipcode )\n\t\t{\n";
+ $out .= "\t\t\tstatic char blah[4] = { 0, 0, 0, 0 };\n";
+ $out .= "\t\t\tbyteCode.m_pRawData = blah;\n";
+ $out .= "\t\t\tbyteCode.m_nSizeInBytes = 4;\n";
+ $out .= "\t\t\treturn byteCode;\n";
+ $out .= "\t\t}\n";
+
+
+
+ $out .= "\t\t// Must null terminate macros.\n";
+ $out .= "\t\tdefineMacros[";
+ $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames );
+ $out .= "]";
+ $out .= ".Name = NULL;\n";
+ $out .= "\t\tdefineMacros[";
+ $out .= scalar( @dynamicDefineNames ) + scalar( @staticDefineNames );
+ $out .= "]";
+ $out .= ".Definition = NULL;\n\n";
+
+
+ $out .= "\t\tLPD3DXBUFFER pShader; // NOTE: THESE LEAK!!!\n";
+ $out .= "\t\tLPD3DXBUFFER pErrorMessages; // NOTE: THESE LEAK!!!\n";
+ $out .= "\t\tHRESULT hr = D3DXCompileShaderFromFile( \"u:\\\\hl2_e3_2004\\\\src_e3_2004\\\\materialsystem\\\\stdshaders\\\\$fxc_filename\",\n\t\t\tdefineMacros,\n\t\t\tNULL, // LPD3DXINCLUDE \n\t\t\t\"main\",\n\t\t\t\"$type\",\n\t\t\t0, // DWORD Flags\n\t\t\t&pShader,\n\t\t\t&pErrorMessages,\n\t\t\tNULL // LPD3DXCONSTANTTABLE *ppConstantTable\n\t\t\t );\n";
+ $out .= "\t\tif( hr != D3D_OK )\n";
+ $out .= "\t\t{\n";
+ $out .= "\t\t\tconst char *pErrorMessageString = ( const char * )pErrorMessages->GetBufferPointer();\n";
+ $out .= "\t\t\tOutputDebugString( pErrorMessageString );\n";
+ $out .= "\t\t\tOutputDebugString( \"\\n\" );\n";
+ $out .= "\t\t\tAssert( 0 );\n";
+ $out .= "\t\t\tstatic char blah[4] = { 0, 0, 0, 0 };\n";
+ $out .= "\t\t\tbyteCode.m_pRawData = blah;\n";
+ $out .= "\t\t\tbyteCode.m_nSizeInBytes = 4;\n";
+ $out .= "\t\t}\n";
+ $out .= "\t\telse\n";
+ $out .= "\t\t{\n";
+ $out .= "\t\t\tbyteCode.m_pRawData = pShader->GetBufferPointer();\n";
+ $out .= "\t\t\tbyteCode.m_nSizeInBytes = pShader->GetBufferSize();\n";
+ $out .= "\t\t}\n";
+ $out .= "\t\treturn byteCode;\n";
+ return $out;
+}
+
+#print "--------\n";
+
+if ( $g_x360 )
+{
+ $fxctmp = "fxctmp9_360_tmp";
+}
+else
+{
+ $fxctmp = "fxctmp9_tmp";
+}
+
+if( !stat $fxctmp )
+{
+ mkdir $fxctmp, 0777 || die $!;
+}
+
+# suck in an input file (using includes)
+#print "$fxc_filename...";
+@fxc = ReadInputFile( $fxc_filename );
+
+# READ THE TOP OF THE FILE TO FIND SHADER COMBOS
+foreach $line ( @fxc )
+{
+ $line="" if ($g_x360 && ($line=~/\[PC\]/)); # line marked as [PC] when building for x360
+ $line="" if (($g_x360 == 0) && ($line=~/\[XBOX\]/)); # line marked as [XBOX] when building for pc
+
+ if ( $fxc_basename =~ m/_ps(\d+\w?)$/i )
+ {
+ my $psver = $1;
+ $line="" if (($line =~/\[ps\d+\w?\]/i) && ($line!~/\[ps$psver\]/i)); # line marked for a version of compiler and not what we build
+ }
+ if ( $fxc_basename =~ m/_vs(\d+\w?)$/i )
+ {
+ my $vsver = $1;
+ $line="" if (($line =~/\[vs\d+\w?\]/i) && ($line!~/\[vs$vsver\]/i)); # line marked for a version of compiler and not what we build
+ }
+
+ my $init_expr;
+
+ $init_expr = $1 if ( $line=~/\[\=([^\]]+)\]/); # parse default init expression for combos
+
+ $line=~s/\[[^\[\]]*\]//; # cut out all occurrences of
+ # square brackets and whatever is
+ # inside all these modifications
+ # to the line are seen later when
+ # processing skips and centroids
+
+ next if( $line =~ m/^\s*$/ );
+
+ if( $line =~ m/^\s*\/\/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
+ {
+ local( $name, $min, $max );
+ $name = $1;
+ $min = $2;
+ $max = $3;
+ # print STDERR "STATIC: \"$name\" \"$min..$max\"\n";
+ push @staticDefineNames, $name;
+ push @staticDefineMin, $min;
+ push @staticDefineMax, $max;
+ $staticDefineInit{$name}=$init_expr;
+ }
+ elsif( $line =~ m/^\s*\/\/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
+ {
+ local( $name, $min, $max );
+ $name = $1;
+ $min = $2;
+ $max = $3;
+ # print STDERR "DYNAMIC: \"$name\" \"$min..$max\"\n";
+ push @dynamicDefineNames, $name;
+ push @dynamicDefineMin, $min;
+ push @dynamicDefineMax, $max;
+ }
+}
+# READ THE WHOLE FILE AND FIND SKIP STATEMENTS
+foreach $line ( @fxc )
+{
+ if( $line =~ m/^\s*\/\/\s*SKIP\s*\s*\:\s*(.*)$/ )
+ {
+ # print $1 . "\n";
+ $perlskipcode .= "(" . $1 . ")||";
+ push @perlskipcodeindividual, $1;
+ }
+}
+
+if( defined $perlskipcode )
+{
+ $perlskipcode .= "0";
+ $perlskipcode =~ s/\n//g;
+}
+else
+{
+ $perlskipcode = "0";
+}
+
+# READ THE WHOLE FILE AND FIND CENTROID STATEMENTS
+foreach $line ( @fxc )
+{
+ if( $line =~ m/^\s*\/\/\s*CENTROID\s*\:\s*TEXCOORD(\d+)\s*$/ )
+ {
+ $centroidEnable{$1} = 1;
+# print "CENTROID: $1\n";
+ }
+}
+
+if( $spewCombos )
+{
+ push @outputHeader, "#include \"windows.h\"\n";
+}
+
+#push @outputHeader, "\#include \"shaderlib\\baseshader.h\"\n";
+#push @outputHeader, "IShaderDynamicAPI *CBaseShader::s_pShaderAPI;\n";
+
+# Go ahead an compute the mask of samplers that need to be centroid sampled
+$centroidMask = 0;
+foreach $centroidRegNum ( keys( %centroidEnable ) )
+{
+# print "THING: $samplerName $centroidRegNum\n";
+ $centroidMask += 1 << $centroidRegNum;
+}
+
+#printf "0x%x\n", $centroidMask;
+
+$numCombos = &CalcNumCombos();
+#print "$numCombos combos\n";
+
+
+if( $g_produceCompiledVcs && !$dynamic_compile )
+{
+ open FOUT, ">>filelistgen.txt" || die "can't open filelistgen.txt";
+
+ print FOUT "**** generated by fxc_prep.pl ****\n";
+ print FOUT "#BEGIN " . $fxc_basename . "\n";
+ print FOUT "$fxc_filename" . "\n";
+ print FOUT "#DEFINES-D:\n";
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); \$i++ )
+ {
+ print FOUT "$dynamicDefineNames[$i]=";
+ print FOUT $dynamicDefineMin[$i];
+ print FOUT "..";
+ print FOUT $dynamicDefineMax[$i];
+ print FOUT "\n";
+ }
+ print FOUT "#DEFINES-S:\n";
+ for( $i = 0; $i < scalar( @staticDefineNames ); \$i++ )
+ {
+ print FOUT "$staticDefineNames[$i]=";
+ print FOUT $staticDefineMin[$i];
+ print FOUT "..";
+ print FOUT $staticDefineMax[$i];
+ print FOUT "\n";
+ }
+ print FOUT "#SKIP:\n";
+ print FOUT "$perlskipcode\n";
+ print FOUT "#COMMAND:\n";
+ # first line
+ print FOUT "fxc.exe ";
+ print FOUT "/DTOTALSHADERCOMBOS=$numCombos ";
+ print FOUT "/DCENTROIDMASK=$centroidMask ";
+ print FOUT "/DNUMDYNAMICCOMBOS=" . &CalcNumDynamicCombos() . " ";
+ print FOUT "/DFLAGS=0x0 "; # Nothing here for now.
+ print FOUT "\n";
+#defines go here
+# second line
+ print FOUT &RenameMain( $fxc_filename, $i );
+ print FOUT "/T" . &GetShaderType( $fxc_filename ) . " ";
+ print FOUT "/DSHADER_MODEL_" . &ToUpper( &GetShaderType( $fxc_filename ) ) . "=1 ";
+ if( $nvidia )
+ {
+ print FOUT "/DNV3X=1 "; # enable NV3X codepath
+ }
+ if ( $g_x360 )
+ {
+ print FOUT "/D_X360=1 "; # shaders can identify X360 centric code
+ # print FOUT "/Xbe:2- "; # use the less-broken old back end
+ }
+ if( $debug )
+ {
+ print FOUT "/Od "; # disable optimizations
+ print FOUT "/Zi "; # enable debug info
+ }
+# print FOUT "/Zi "; # enable debug info
+ print FOUT "/nologo ";
+# print FOUT "/Fhtmpshader.h ";
+ print FOUT "/Foshader.o ";
+ print FOUT "$fxc_filename";
+ print FOUT ">output.txt 2>&1";
+ print FOUT "\n";
+ #end of command line
+ print FOUT "#END\n";
+ print FOUT "**** end ****\n";
+
+ close FOUT;
+}
+
+if ( $g_produceCppClasses )
+{
+ # Write out the C++ helper class for picking shader combos
+ &WriteStaticHelperClasses();
+ &WriteDynamicHelperClasses();
+ my $incfilename = "$fxctmp\\$fxc_basename" . ".inc";
+ &WriteFile( $incfilename, join( "", @outputHeader ) );
+}
+
+
+
+if( $generateListingFile )
+{
+ my $listFileName = "$fxctmp/$fxc_basename" . ".lst";
+ print "writing $listFileName\n";
+ if( !open FILE, ">$listFileName" )
+ {
+ die;
+ }
+ print FILE @listingOutput;
+ close FILE;
+}
+
+
+@endTimes = times;
+
+$endTime = time;
+
+#printf "Elapsed user time: %.2f seconds!\n", $endTimes[0] - $startTimes[0];
+#printf "Elapsed system time: %.2f seconds!\n", $endTimes[1] - $startTimes[1];
+#printf "Elapsed child user time: %.2f seconds!\n", $endTimes[2] - $startTimes[2];
+#printf "Elapsed child system time: %.2f seconds!\n", $endTimes[3] - $startTimes[3];
+
+#printf "Elapsed total time: %.2f seconds!\n", $endTime - $startTime;
+
diff --git a/devtools/bin/gnu/libiconv2.dll b/devtools/bin/gnu/libiconv2.dll
new file mode 100644
index 0000000..747073f
--- /dev/null
+++ b/devtools/bin/gnu/libiconv2.dll
Binary files differ
diff --git a/devtools/bin/gnu/libintl3.dll b/devtools/bin/gnu/libintl3.dll
new file mode 100644
index 0000000..4f309be
--- /dev/null
+++ b/devtools/bin/gnu/libintl3.dll
Binary files differ
diff --git a/devtools/bin/gnu/touch.exe b/devtools/bin/gnu/touch.exe
new file mode 100644
index 0000000..b1385cd
--- /dev/null
+++ b/devtools/bin/gnu/touch.exe
Binary files differ
diff --git a/devtools/bin/grep.exe b/devtools/bin/grep.exe
new file mode 100644
index 0000000..6931618
--- /dev/null
+++ b/devtools/bin/grep.exe
Binary files differ
diff --git a/devtools/bin/limit_vtf_sizes.pl b/devtools/bin/limit_vtf_sizes.pl
new file mode 100644
index 0000000..66df3c3
--- /dev/null
+++ b/devtools/bin/limit_vtf_sizes.pl
@@ -0,0 +1,94 @@
+#!perl
+
+use File::Find;
+use File::Basename;
+
+$dir_to_run_on = shift;
+$max_size = shift;
+
+if ( (! length( $dir_to_run_on ) || (! $max_size ) ) )
+ {
+ die "format is 'limit_vtf_sizes game_dir_to_run_on size'. maxisze -1 to unlimit";
+ }
+
+open(CMDOUT,">\runit.cmd");
+
+find(\&ProcessFile, $dir_to_run_on);
+
+close CMDOUT;
+
+sub ProcessFile
+ {
+ local($_) = $File::Find::name;
+ my $origname=$_;
+ my $srcname;
+ s@\\@/@g;
+ if (/\.vtf$/i) # is a vtf?
+ {
+ next if (m@/hud/@i); # don't shrink hud textures
+ next if (m@/vgui/@i); # don't shrink hud textures
+ my $vtex_it=0;
+ if ( s@game/(.*)/materials/@content/\1/materialsrc/@i )
+ {
+ $srcname=$_;
+ s/\.vtf$/\.txt/i;
+ if (-e $_ )
+ {
+ my $txtname=$_;
+ # decide whether or not to add the limits
+ open(TXTIN,$txtname) || die "can't open $_ for read something weird has happened";
+ my $txtout;
+ my $should_add_it=1;
+ while( <TXTIN>)
+ {
+ next if ( ( $max_size == -1) && (/maxwidth/i || /maxheight/i) ); # lose this line
+ $txtout.=$_;
+ $should_add_it = 0 if (/maxwidth/i || /maxheight/i || /nomip/i || /reduce/i );
+ }
+ close TXTIN;
+ if ($should_add_it )
+ {
+ print `p4 edit $txtname`;
+ open(TXTOUT,">$txtname");
+ print TXTOUT $txtout;
+ print TXTOUT "maxwidth $max_size\nmaxheight $max_size\n" if ($max_size != -1);
+ close TXTOUT;
+ $vtex_it = 1;
+ }
+ }
+ else
+ {
+ if (-d dirname($_) )
+ {
+ print "$_ not found. Creating it\n";
+ open(TXTOUT,">$_" ) || die "can't create $_?";
+ print TXTOUT "maxwidth $max_size\nmaxheight $max_size\n" if( $max_size != -1);
+ close TXTOUT;
+ print `p4 add $_`;
+ $vtex_it=1;
+ }
+ else
+ {
+ print "directory does not exist in content for $_\n";
+ }
+ }
+ }
+ else
+ {
+ die "I dont understand the file $_ : bad path?";
+ }
+ if ($vtex_it)
+ {
+ my $name=$srcname;
+ $name=~s@\..*$@@; # kill extension
+ $cmd="vtex -nopause $name";
+ $cmd=~s@/@\\@g;
+ print "execute:$cmd\n";
+ print CMDOUT "$cmd\n";
+# print `$cmd`."\n";
+
+ }
+
+ }
+ }
+
diff --git a/devtools/bin/linux/ccache b/devtools/bin/linux/ccache
new file mode 100644
index 0000000..b275e56
--- /dev/null
+++ b/devtools/bin/linux/ccache
Binary files differ
diff --git a/devtools/bin/linux/p4 b/devtools/bin/linux/p4
new file mode 100644
index 0000000..a3c980c
--- /dev/null
+++ b/devtools/bin/linux/p4
Binary files differ
diff --git a/devtools/bin/make360def.pl b/devtools/bin/make360def.pl
new file mode 100644
index 0000000..38aad9f
--- /dev/null
+++ b/devtools/bin/make360def.pl
@@ -0,0 +1,329 @@
+###############################################################
+#
+# generateDEF.pl
+#
+# Parses a .map file and generates a .def file
+# for exporting functions from a dll.
+#
+# Note: Map Exports must be enabled in the project properties
+#
+###############################################################
+
+my @baselist;
+my @output;
+my $baseLen = 63;
+
+######################################
+# Adds tabs for better formatting
+
+sub Add_Tabs
+{
+ my $name = shift;
+ my $num = int( ($baseLen - length( $name )) / 8 );
+
+ for( $i = 0; $i < $num; $i++ )
+ {
+ push( @output, "\t" );
+ }
+}
+
+######################################
+# Open, validate, and read a file (not implemented yet)
+
+sub Read_File
+{
+ my $name = shift;
+ my @file = shift;
+
+ # read in the file
+ if ( open(INFILE, "$name" ) )
+ {
+ @file = <INFILE>;
+ close( INFILE );
+ }
+ else
+ {
+ print( "Error opening file $name\n" );
+ exit 1;
+ }
+}
+
+#####################################
+# Start of script
+
+print( "Valve Software - make360def.pl\n" );
+print( "Copyright (c) 1996-2006, Valve LLC, All rights reserved.\n" );
+
+my $filename = $ARGV[0];
+my $numArgs = 1;
+my @lines = ();
+my @deflines = ();
+
+if ( $ARGV[0] =~ /-check$/i )
+{
+ $numArgs = 3;
+ $check = 1;
+ $filename = $ARGV[1];
+ $defname = $ARGV[2];
+}
+elsif ( $ARGV[0] =~ /-checkauto/i )
+{
+ $defname = $ARGV[1];
+ $check = 2;
+}
+
+if ( @ARGV < $numArgs )
+{
+ print( "ERROR: Missing filename(s)\n" );
+ exit 1;
+}
+
+if ( $check == 1 )
+{
+ # swap filenames if necessary
+ if ( $filename =~ /.def/ )
+ {
+ my $temp = $filename;
+ $filename = $defname;
+ $defname = $temp;
+ }
+
+ # validate extensions
+ unless ( $filename =~ /.map/ && $defname =~ /.def/ )
+ {
+ print( "ERROR: Invalid file extensions. -check requires a .map file and a .def file.\n" );
+ exit 1;
+ }
+
+ # read in the def file
+ if ( open(INFILE, "$defname" ) )
+ {
+ @deflines = <INFILE>;
+ close( INFILE );
+ }
+ else
+ {
+ print( "ERROR: Couldn't open file $defname.\n" );
+ exit 1;
+ }
+}
+elsif ( $check == 2 )
+{
+ # read in the def file
+ if ( open(INFILE, "$defname" ) )
+ {
+ @deflines = <INFILE>;
+ close( INFILE );
+ }
+ else
+ {
+ print( "ERROR: Couldn't open file $defname.\n" );
+ exit 1;
+ }
+
+ # validate that the first export is CreateInterface*
+ # validate that the export ordinals are sequential and ordered
+
+ my $line;
+ my $start = false;
+ my $idx = 1;
+ for ( @deflines )
+ {
+ $line = $_;
+
+ if ( $line =~ /@(\d+)[ |\n]/ )
+ {
+ if ( $1 == 1 )
+ {
+ unless ( $line =~ /CreateInterface/ )
+ {
+ # first export must be CreateInterface*
+ $line =~ /\s+([\S]*)/;
+
+ print( "**************************************************\n" );
+ print( " ERROR: First export must be CreateInterface*. \n" );
+ print( " Export \"", $1, "\" found instead! \n" );
+ print( " This is a FATAL ERROR with the def file. \n" );
+ print( " Please contact an Xbox 360 engineer immediately.\n" );
+ print( "**************************************************\n" );
+ exit 1;
+ }
+ }
+
+ if ( $1 != $idx )
+ {
+ # exports are out of order
+ print( "**************************************************\n" );
+ print( " ERROR: Def file exports are not sequential \n" );
+ print( " This may cause unexpected behavior at runtime. \n" );
+ print( " Please contact an Xbox 360 engineer immediately.\n" );
+ print( "**************************************************\n" );
+ exit 1;
+ }
+
+ ++$idx;
+ }
+ }
+
+ exit 0;
+}
+
+# Get the base name
+
+$filename =~ /(\w+(\.360)?).map/;
+my $basename = $1;
+
+# Read in the source file
+
+if ( open(INFILE, "$filename" ) )
+{
+ @lines = <INFILE>;
+ close( INFILE );
+}
+else
+{
+ print( "ERROR: Couldn't open file $filename.\n" );
+ exit 1;
+}
+
+# Delete the lines up to the exports section
+
+my $len = 0;
+my $exportsFound = 0;
+for( @lines )
+{
+ $len++;
+ if( /^ Exports$/ )
+ {
+ splice( @lines, 0, $len+3 );
+ $exportsFound = 1;
+ }
+}
+
+if ( $exportsFound == 0 )
+{
+ print( "ERROR: No Exports section found in $filename. " );
+ print( "Relink the project with 'Map Exports' enabled.\n" );
+ exit 1;
+}
+
+if ( $check == 1 )
+{
+ # Check for exports in the map that aren't in the def
+ print( "make360def: Comparing $filename and $defname\n" );
+
+ # strip the first 2 lines from the def
+ splice( @deflines, 0, 2 );
+
+ my $defEntryCt = $#deflines + 1;
+ my $defMatches = 0;
+
+ # for each line in the map
+ for( @lines )
+ {
+ my $found = 0;
+
+ # Pull the export name from the map line
+
+ my $mapline;
+ if ( /(\d+)\s+(\S+)/ )
+ {
+ $mapline = $2;
+ }
+ else
+ {
+ # ignore this line
+ next;
+ }
+
+ # for each line in the def
+ for( @deflines )
+ {
+ /(\S+)/;
+
+ if ( $1 =~ /^\Q$mapline\E$/ )
+ {
+ $found = 1;
+ $defMatches++;
+ last;
+ }
+ }
+
+ if ( $found == 0 )
+ {
+ print( "ERROR: New export found in $filename, " );
+ print( "so the map file and def file are out of sync. " );
+ print( "You must relink the project to generate a new def file.\n" );
+ exit 1;
+ }
+ }
+
+ # Make sure all the def lines were matched
+ if ( $defMatches != $defEntryCt )
+ {
+ print( "ERROR: An export was removed from $filename, " );
+ print( "so the map file and def file are out of sync. " );
+ print( "You must relink the project to generate a new def file.\n" );
+ exit 1;
+ }
+
+ print( "make360def: Comparison complete, files match.\n" );
+ exit 0;
+}
+
+# start the def file
+
+print( "make360def: Generating $basename.def\n" );
+
+push( @output, "LIBRARY\t$basename.dll\n" );
+push( @output, "EXPORTS\n" );
+
+# process each line in the export section
+
+my $interfacePrefix = "0000000000";
+for( @lines )
+{
+ if ( /(\d+)\s+(\S+)/ )
+ {
+ my $func = $2;
+ if ( $func =~ /CreateInterface/ )
+ {
+ # Force createInterface to sort first
+ $func = join( '', $interfacePrefix, $func );
+ }
+
+ push( @baselist, $func );
+ }
+}
+
+# sort the list
+my @sortedlist = sort {uc($a) cmp uc($b)} @baselist;
+#my @sortedlist = @baselist;
+
+my $ordinal = 1;
+for( @sortedlist )
+{
+ my $func = $_;
+ if ( /$interfacePrefix(.*)/ )
+ {
+ # Strip the added characters
+ $func = $1;
+ }
+
+ push( @output, "\t$func\t" );
+ Add_Tabs( $func );
+ push( @output, "\@$ordinal\n" );
+ $ordinal++;
+}
+
+# write the def file
+
+print( "make360def: Saving $basename.def.\n" );
+
+open ( OUTFILE, ">$basename.def" );
+print OUTFILE @output;
+close ( OUTFILE );
+
+print( "make360def: Finished.\n" );
+
+exit 0;
diff --git a/devtools/bin/makewav.exe b/devtools/bin/makewav.exe
new file mode 100644
index 0000000..ede7e38
--- /dev/null
+++ b/devtools/bin/makewav.exe
Binary files differ
diff --git a/devtools/bin/masm.exe b/devtools/bin/masm.exe
new file mode 100644
index 0000000..c487faf
--- /dev/null
+++ b/devtools/bin/masm.exe
Binary files differ
diff --git a/devtools/bin/mc.exe b/devtools/bin/mc.exe
new file mode 100644
index 0000000..c2f9b6d
--- /dev/null
+++ b/devtools/bin/mc.exe
Binary files differ
diff --git a/devtools/bin/md5.exe b/devtools/bin/md5.exe
new file mode 100644
index 0000000..0e744f0
--- /dev/null
+++ b/devtools/bin/md5.exe
Binary files differ
diff --git a/devtools/bin/mksln.pl b/devtools/bin/mksln.pl
new file mode 100644
index 0000000..aec1c88
--- /dev/null
+++ b/devtools/bin/mksln.pl
@@ -0,0 +1,388 @@
+#!perl
+use XML::Simple;
+use Data::Dumper;
+use Getopt::Long;
+use File::Basename;
+use Cwd 'abs_path';
+use Cwd;
+use Digest::MD5 qw(md5 md5_hex md5_base64);
+
+
+GetOptions( "verbose"=>\$verbose,
+ "projlist"=>\$projlist,
+ "x360"=>\$x360 );
+
+$sln_name=shift || &PrintArgumentSummaryAndExit;
+
+my $curdir=cwd;
+
+$curdir=~ (m@(^.*/[a-z_]*src[0-9]?)@i) || die "Can't determine srcroot from current directory $curdir";
+
+$srcroot=lc($1);
+
+$linker_tool_name="VCLinkerTool";
+$linker_tool_name="VCX360LinkerTool" if ($x360);
+
+@output_only_projects_dependent_upon = ();
+
+&ReadVPCProjects;
+if ( $sln_name =~ /^\@(\S+)/)
+{
+ $sln_name=$1;
+ &ReadGroup($1);
+ foreach $proj (@PROJS)
+ {
+ &AddProject(lc(abs_path($proj)),1);
+ }
+ if ( $projlist )
+ {
+ &WriteProjectListFile( $sln_name );
+ }
+ else
+ {
+ &WriteSolutionFile($sln_name);
+ }
+}
+else
+{
+ # normal mode
+ while($_ = shift )
+ {
+ if ( /^\@(\S+)/)
+ {
+ # accept group names
+ &ReadGroup($1);
+ foreach $proj (@PROJS)
+ {
+ &AddProject(lc(abs_path($proj)),1);
+ }
+ }
+ elsif ( /^\*(\S+)/)
+ {
+ push( @output_only_projects_dependent_upon, lc( $1 ) );
+ &ReadGroup("everything");
+ foreach $proj (@PROJS)
+ {
+ &AddProject(lc(abs_path($proj)),0);
+ }
+ }
+ else
+ {
+ unless(/\.vcproj/) # if no extension specified, assume its a project name from projects.vgc
+ {
+ $_=$projpath{lc($_)} if length($projpath{lc($_)});
+ }
+ foreach $path (split(/\s+/,$_))
+ {
+ $path=~s@\s+@@g;
+ &AddProject(lc(abs_path($path)),1) if length($path);
+ }
+ }
+ }
+ if ( $projlist )
+ {
+ &WriteProjectListFile( $sln_name );
+ }
+ else
+ {
+ &WriteSolutionFile($sln_name);
+ }
+}
+
+
+sub WriteSolutionFile
+{
+ local($sln)=@_;
+ $sln="$sln.sln" unless ( $sln=~/\./); # add extension if needed
+ if ( ( -e $sln && ( ! ( -w $sln ) ) ) )
+ {
+ print STDERR "$sln is write-protected. Doing p4 edit.\n";
+ print `p4 edit $sln`;
+ die "Failed to make $sln writeable" if ( ! ( -w $sln ) );
+ }
+ open(SLN,">$sln" ) || die "can't open output $sln";
+ # generate a guid for the sln
+ my $sln_guid="8BC9CEB8-8B4A-11D0-8D11-".substr(uc(md5_hex(basename($sln))),0,12);
+
+ print SLN "\xef\xbb\xbf\nMicrosoft Visual Studio Solution File, Format Version 9.00\n# Visual Studio 2005\n";
+ foreach $proj (@PROJECTS)
+ {
+ # check dependencies for "*" projects
+ if ( (! length( $force_project_inclusion{$proj} ) ) &&
+ ( @output_only_projects_dependent_upon ))
+ {
+ my $skip_it = 1;
+ foreach $output_only ( @output_only_projects_dependent_upon )
+ {
+ $skip_it = 0 if ( $output_only eq lc( $proj ) );
+ foreach $lib (split(/,/,$depends_on{$proj}))
+ {
+ $skip_it = 0 if ( $output_only eq lc($lib) );
+ foreach $prvd (split(/,/,$provider{$lib}))
+ {
+ $skip_it = 0 if ( $output_only eq $prvd );
+ }
+ }
+ }
+ next if ( $skip_it );
+ }
+
+ print SLN "Project(\"{",$sln_guid,"}\") = \"$proj\", \"$relpath{$proj}\", \"$guid{$proj}\"\n";
+
+ #, now do dependencies
+ if ( length($depends_on{$proj} ) )
+ {
+ print SLN "\tProjectSection(ProjectDependencies) = postProject\n";
+ foreach $lib (split(/,/,$depends_on{$proj}))
+ {
+ if ( length($provider{$lib}) )
+ {
+ foreach $prvd (split(/,/,$provider{$lib}))
+ {
+ print SLN "\t\t$guid{$prvd} = $guid{$prvd}\n" if ( length($prvd) );
+ }
+ }
+ else
+ {
+ print "I don't know who provides $lib for $proj\n" if ( $verbose && length($lib) );
+ }
+
+ }
+ print SLN "\tEndProjectSection\n";
+ }
+ print SLN "EndProject\n";
+ }
+
+ print SLN "Global\n";
+ print SLN "\tGlobalSection(SolutionProperties) = preSolution\n";
+ print SLN "\t\tHideSolutionNode = FALSE\n";
+ print SLN "\tEndGlobalSection\n";
+ print SLN "EndGlobal\n";
+ close SLN;
+}
+
+sub WriteProjectListFile
+{
+ local($txtfile) = @_;
+ $txtfile = "$txtfile.txt" unless ( $txtfile=~/\./); # add extension if needed
+ open(SLN,">$txtfile" ) || die "can't open output $txtfile";
+
+ foreach $proj (@PROJECTS)
+ {
+ # check dependencies for "*" projects
+ if ( (! length( $force_project_inclusion{$proj} ) ) &&
+ ( @output_only_projects_dependent_upon ))
+ {
+ my $skip_it = 1;
+ foreach $output_only ( @output_only_projects_dependent_upon )
+ {
+ $skip_it = 0 if ( $output_only eq lc( $proj ) );
+ foreach $lib (split(/,/,$depends_on{$proj}))
+ {
+ $skip_it = 0 if ( $output_only eq lc($lib) );
+ foreach $prvd (split(/,/,$provider{$lib}))
+ {
+ $skip_it = 0 if ( $output_only eq $prvd );
+ }
+ }
+ }
+ next if ( $skip_it );
+ }
+
+ push @plist, $proj;
+ }
+ # now, we need to satisfy all dependencies
+ while( $#plist >= 0)
+ {
+ @worklist=@plist;
+ undef @plist;
+ PROJECT: foreach $proj( @worklist )
+ {
+ if ( length($depends_on{$proj} ) )
+ {
+ foreach $lib (split(/,/,$depends_on{$proj}))
+ {
+ if ( length($provider{$lib}) )
+ {
+ foreach $prvd (split(/,/,$provider{$lib}))
+ {
+ if ( length( $prvd ) && ( !$already_did{$prvd} ) )
+ {
+ push @plist, $proj; # can't do it yet
+ next PROJECT;
+ }
+ }
+ }
+ }
+ }
+ $already_did{$proj} = 1;
+ print SLN "$relpath{$proj}\n";
+ }
+ }
+ close SLN;
+}
+
+sub PrintArgumentSummaryAndExit
+{
+ print "Format of command is\n";
+ my $switches="[ -projlist -verbose -x360 ]";
+ print "\t MKSLN $switches <solutionname.sln > proj1.vcproj proj2.vcproj ...\n";
+ print "OR\t MKSLN $switches \@vpcgroupname\n";
+ print "OR\t MKSLN $switches sln_name \@vpcgroupname\n";
+ print "OR\t MKSLN $switches sln_name *project create a solution including only that project and things dependent on it.\n";
+}
+
+
+sub AddProject
+{
+ local($fname, $force )=@_;
+ local($/);
+ print "add project $fname\n" if ( $verbose );
+ open( VCP_IN, $fname ) || die "can't open $fname";
+ my $xmltext=<VCP_IN>;
+ close VCP_IN;
+ my $xml=XMLin($xmltext, forcearray => [ 'File', 'Filter' ] ); #, keyattr =>[ 'name', 'key', 'id', 'Name']);
+ my $pname=lc($xml->{Name});
+ $force_project_inclusion{$pname} = "yes" if ( $force );
+ return if ($already_processed{$pname} );
+ $already_processed{$pname}=1;
+ my $id=$xml->{ProjectGUID};
+ unless( length($id) )
+ {
+ die "project $fname doesn't have a guid. Generated by an old VPC?";
+ }
+ $id = "{".$id."}" unless( $id=~ /}/);
+ $guid{$pname}=$id;
+ push @PROJECTS,$pname;
+ $vcprojpath{$pname}=$fname;
+
+ #get targetname
+ my $targetname=$xml->{Name};
+ # get output target
+
+ my $tools=$xml->{Configurations}->{Configuration}[0];
+ # walk the tool list to see if this project outpus a .lib that something might depend on
+ my $outputtarget;
+ foreach $tool (@{$tools->{'Tool'}})
+ {
+ if ( $tool->{Name} eq "VCLibrarianTool" )
+ {
+ my $outputtarget=lc(basename($tool->{OutputFile}));
+ $provider{$outputtarget}.=",$pname";
+ print "$pname provides $outputtarget\n" if ($verbose);
+ }
+ if ( $tool->{Name} eq $linker_tool_name )
+ {
+ my $outputtarget=$tool->{'ImportLibrary'};
+ if ( length($outputtarget) )
+ {
+ $outputtarget=~s/\$\(TargetName\)/$targetname/i;
+ $outputtarget=lc(basename($outputtarget));
+ $outputtarget =~ s/\.lib/_360.lib/ if ( $x360 );
+ $provider{$outputtarget}=basename($pname);
+ print "$pname provides $outputtarget\n" if ($verbose);
+ }
+ }
+ }
+
+ foreach $filter (@{$xml->{Files}->{Filter}})
+ {
+ foreach $file (@{$filter->{File}})
+ {
+ my $f = lc($file->{RelativePath});
+ if ( $f=~/\.lib$/i) # library dependency
+ {
+ my $libname=basename($f);
+ $depends_on{$pname}.=",".$libname;
+ print "$pname depends on $libname\n" if ($verbose);
+ }
+ }
+ }
+ # generate relative pathname
+ $fname=~s@^$srcroot/@@i;
+ $fname=~s@/@\\@g;
+ $relpath{$pname}=$fname;
+
+}
+
+sub ReadGroup
+{
+ local($matchgroup)=@_;
+ my $curmatch=0;
+ open(GROUPS,"$srcroot/vpc_scripts/groups.vgc") || die "can't open groups.vgc";
+ while(<GROUPS>)
+ {
+ &FixupVPCLine;
+ if (/^\$Group\s+(.*)$/)
+ {
+ my $groups=" $1 ";
+ $groups=~s@\"@@g;
+ $curmatch=0;
+ $curmatch=1 if ( $groups=~/ $matchgroup /i );
+ }
+ elsif ( $curmatch && (/^\s*\"([^\"]+)\"/) )
+ {
+ my $proj=lc($1);
+ my $path=$projpath{$proj};
+ if (length($path))
+ {
+ foreach $prj (split(/\s+/, $path))
+ {
+ $prj=~s@\s+@@g;
+ next unless (length($prj));
+ if ( -e $prj )
+ {
+ push @PROJS,$prj;
+ print "found proj $prj\n" if ($verbose);
+ }
+ else
+ {
+ print STDERR "can't find $prj\n";
+ }
+
+ }
+ }
+ else
+ {
+ print STDERR "couldn't find project name $proj (group = $matchgroup )\n";
+ }
+ }
+ else
+ {
+ $curmatch = 0 if (/\}/);
+ }
+
+ }
+}
+
+sub ReadVPCProjects
+{
+ # group mode. ugh 100x harder to parse vpc than .vcproj
+ open(PROJS,"$srcroot/vpc_scripts/projects.vgc" ) || die "can't open projects.vgc";
+ while(<PROJS>)
+ {
+ &FixupVPCLine;
+ if (/^\s*\$Project\s+\"([^\"]+)\"/)
+ {
+ $curproj=$1;
+ }
+ elsif (/^\s*\"([^\"]+)\.vpc\"/)
+ {
+ my $base = $1;
+ $base="$base"."_x360" if ( $x360 );
+ $projpath{lc($curproj)}.=" $base.vcproj";
+ }
+ }
+ close PROJS;
+}
+
+sub FixupVPCLine
+{
+ s@[\n\r]@@g;
+ s@//.*$@@g; # kill comments
+
+ # use [] skips. need something smarter here. for now, implicit /allgames except hl1 and portalmp
+ $_=undef if ( /\$HL1/);
+ $_=undef if ( /\$PORTALMP/);
+}
+
diff --git a/devtools/bin/ml.err b/devtools/bin/ml.err
new file mode 100644
index 0000000..4aae01e
--- /dev/null
+++ b/devtools/bin/ml.err
@@ -0,0 +1,280 @@
+FATAL
+cannot open file
+I/O error closing file
+I/O error writing file
+I/O error reading file
+out of memory
+assembler limit : macro parameter name table full
+invalid command-line option
+nesting level too deep
+unmatched macro nesting
+line too long
+unmatched block nesting
+directive must be in control block
+error count exceeds 100; stopping assembly
+invalid numerical command-line argument
+too many arguments
+statement too complex
+N/A
+missing source filename
+COFF error writing file
+invalid debug and browser data; file exceeds line limit
+cannot find link.exe
+cannot find cvpack.exe
+SEVERE
+memory operand not allowed in context
+immediate operand not allowed
+cannot have more than one ELSE clause per IF block
+extra characters after statement
+symbol type conflict
+symbol redefinition
+undefined symbol
+non-benign record redefinition
+syntax error
+syntax error in expression
+invalid type expression
+distance invalid for word size of current segment
+PROC, MACRO, or macro repeat directive must precede LOCAL
+.MODEL must precede this directive
+cannot define as public or external
+segment attributes cannot change
+expression expected
+operator expected
+invalid use of external symbol
+operand must be RECORD type or field
+identifier not a record
+record constants may not span line breaks
+instruction operands must be the same size
+instruction operand must have size
+invalid operand size for instruction
+operands must be in same segment
+constant expected
+operand must be a memory expression
+expression must be a code address
+multiple base registers not allowed
+multiple index registers not allowed
+must be index or base register
+invalid use of register
+invalid INVOKE argument
+must be in segment block
+DUP too complex
+too many initial values for structure
+statement not allowed inside structure definition
+missing operand for macro operator
+line too long
+segment register not allowed in context
+string or text literal too long
+statement too complex
+identifier too long
+invalid character in file
+missing angle bracket or brace in literal
+missing single or double quotation mark in string
+empty (null) string
+nondigit in number
+syntax error in floating-point constant
+real or BCD number not allowed
+text item required
+forced error
+forced error : value equal to 0
+forced error : value not equal to 0
+forced error : symbol not defined
+forced error : symbol defined
+forced error : string blank
+forced error : string not blank
+forced error : strings equal
+forced error : strings not equal
+[ELSE]IF2/.ERR2 not allowed : single-pass assembler
+expression too complex for .UNTILCXZ
+can ALIGN only to power of 2
+structure alignment must be 1, 2, 4, 8, or 16
+expected
+incompatible CPU mode and segment size
+LOCK must be followed by a memory operation
+instruction prefix not allowed
+no operands allowed for this instruction
+invalid instruction operands
+initializer magnitude too large for specified size
+cannot access symbol in given segment or group
+operands have different frames
+cannot access label through segment registers
+jump destination too far
+jump destination must specify a label
+instruction does not allow NEAR indirect addressing
+instruction does not allow FAR indirect addressing
+instruction does not allow FAR direct addressing
+jump distance not possible in current CPU mode
+missing operand after unary operator
+cannot mix 16- and 32-bit registers
+invalid scale value
+constant value too large
+instruction or register not accepted in current CPU mode
+reserved word expected
+instruction form requires 80386/486
+END directive required at end of file
+too many bits in RECORD
+positive value expected
+index value past end of string
+count must be positive or zero
+count value too large
+operand must be relocatable
+constant or relocatable label expected
+segment, group, or segment register expected
+segment expected
+invalid operand for OFFSET
+invalid use of external absolute
+segment or group not allowed
+cannot add two relocatable labels
+cannot add memory expression and code label
+segment exceeds 64K limit
+invalid type for a data declaration
+HIGH and LOW require immediate operands
+N/A
+cannot have implicit far jump or call to near label
+use of register assumed to ERROR
+only white space or comment can follow backslash
+COMMENT delimiter expected
+conflicting parameter definition
+PROC and prototype calling conventions conflict
+invalid radix tag
+INVOKE argument type mismatch : argument
+invalid coprocessor register
+instructions and initialized data not allowed in AT segments
+/AT switch requires the TINY memory model
+cannot have segment address references with TINY model
+language type must be specified
+PROLOGUE must be macro function
+EPILOGUE must be macro procedure
+alternate identifier not allowed with EXTERNDEF
+text macro nesting level too deep
+N/A
+missing macro argument
+EXITM used inconsistently
+macro function argument list too long
+N/A
+VARARG parameter must be last parameter
+VARARG parameter not allowed with LOCAL
+VARARG parameter requires C calling convention
+ORG needs a constant or local offset
+register value overwritten by INVOKE
+structure too large to pass with INVOKE : argument
+not overriding private proc as public
+too many arguments to INVOKE
+too few arguments to INVOKE
+invalid data initializer
+N/A
+RET operand too large
+too many operands to instruction
+cannot have more than one .ELSE clause per .IF block
+expected data label
+cannot nest procedures
+EXPORT must be FAR
+procedure declared with two visibility attributes
+macro label not defined
+invalid symbol type in expression
+byte register cannot be first operand
+word register cannot be first operand
+special register cannot be first operand
+coprocessor register cannot be first operand
+cannot change size of expression computations
+syntax error in control-flow directive
+cannot use 16-bit register with a 32-bit address
+constant value out of range
+missing right parenthesis
+type is wrong size for register
+structure cannot be instanced
+non-benign structure redefinition: label incorrect
+non-benign structure redefinition: too few labels
+OLDSTRUCTS/NOOLDSTRUCTS state cannot be changed
+non-benign structure redefinition: incorrect initializers
+non-benign structure redefinition: too few initializers
+non-benign structure redefinition: label has incorrect offset
+structure field expected
+unexpected literal found in expression
+N/A
+divide by zero in expression
+directive must appear inside a macro
+cannot expand macro function
+too few bits in RECORD
+macro function cannot redefine itself
+N/A
+invalid qualified type
+floating-point initializer on an integer variable
+nested structure improperly initialized
+invalid use of FLAT
+structure improperly initialized
+improper list initialization
+initializer must be a string or single item
+initializer must be a single item
+initializer must be a single byte
+improper use of list initializer
+improper literal initialization
+extra characters in literal initialization
+must use floating-point initializer
+cannot use .EXIT for OS_OS2 with .8086
+invalid combination with segment alignment
+INVOKE requires prototype for procedure
+cannot include structure in self
+symbol language attribute conflict
+non-benign COMM redefinition
+COMM variable exceeds 64K
+parameter or local cannot have void type
+cannot use TINY model with OS_OS2
+expression size must be 32 bits
+.EXIT does not work with 32-bit segments
+.STARTUP does not work with 32-bit segments
+ORG directive not allowed in unions
+D/T
+illegal use of segment register
+cannot declare scoped code label as PUBLIC
+.MSFLOAT directive is obsolete : .MSFLOAT ignored
+ESC instruction is obsolete : ESC ignored
+missing operator in expression
+missing right parenthesis in expression
+missing left parenthesis in expression
+reference to forward macro definition
+16 bit segments not allowed with /coff option
+FAR not allowed in flat model comm variables
+invalid .model parameter for flat model
+ALIAS name is empty
+GROUP directive not allowed with /coff option
+.FPO is not compatible with nested procedures
+LEVEL 1
+cannot modify READONLY segment
+N/A
+non-unique STRUCT/UNION field used without qualification
+start address on END directive ignored with .STARTUP
+cannot ASSUME CS
+unknown default prologue argument
+too many arguments in macro call
+option untranslated, directive required
+invalid command-line option value, default is used
+insufficent memory for /EP : /EP ignored
+expected '>' on text literal
+multiple .MODEL directives found : .MODEL ignored
+line number information for segment without class 'CODE'
+instructions and initialized data not supported in AT segments
+directive ignored with /coff switch
+/Gc switch incompatible with flat model
+/AT switch incompatible with flat model
+invalid command-line option
+directive ignored without /coff switch
+directive ignored outside a procedure
+LOADDS ignored in flat model
+debug information too complex for
+with /coff switch, leading underscore required for start address
+LEVEL 2
+@@: label defined but not referenced
+expression expected, assume value 0
+EXTERNDEF previously assumed to be external
+length of symbol previously assumed to be different
+symbol previously assumed to not be in a group
+types are different
+calling convention not supported in flat model
+LEVEL 3
+N/A
+no return from procedure
+N/A
+conditional jump lengthened
+procedure argument or local not referenced
+expression may be pass-dependent
+structure contains no members
diff --git a/devtools/bin/ml.exe b/devtools/bin/ml.exe
new file mode 100644
index 0000000..fe038ac
--- /dev/null
+++ b/devtools/bin/ml.exe
Binary files differ
diff --git a/devtools/bin/oldfxc.exe b/devtools/bin/oldfxc.exe
new file mode 100644
index 0000000..21b640a
--- /dev/null
+++ b/devtools/bin/oldfxc.exe
Binary files differ
diff --git a/devtools/bin/osx32/ccache b/devtools/bin/osx32/ccache
new file mode 100644
index 0000000..9b40bf9
--- /dev/null
+++ b/devtools/bin/osx32/ccache
Binary files differ
diff --git a/devtools/bin/osx32/protoc b/devtools/bin/osx32/protoc
new file mode 100644
index 0000000..f111cb2
--- /dev/null
+++ b/devtools/bin/osx32/protoc
Binary files differ
diff --git a/devtools/bin/osx32/xcode_ccache_wrapper b/devtools/bin/osx32/xcode_ccache_wrapper
new file mode 100644
index 0000000..475f508
--- /dev/null
+++ b/devtools/bin/osx32/xcode_ccache_wrapper
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec $(dirname $0)/ccache "${DT_TOOLCHAIN_DIR}"/usr/bin/clang -Qunused-arguments "$@"
diff --git a/devtools/bin/playback_getframe.pl b/devtools/bin/playback_getframe.pl
new file mode 100644
index 0000000..137c598
--- /dev/null
+++ b/devtools/bin/playback_getframe.pl
@@ -0,0 +1,24 @@
+if( scalar( @ARGV ) != 2 )
+{
+ die "Usage: playback_getframe.pl framenum blah.txt\n";
+}
+
+# getframe.pl framenum blah.txt
+$line = 0;
+$desiredFrame = shift;
+$frame = 1;
+open INPUT, shift || die;
+while( <INPUT> )
+{
+ $line++;
+ if( /Dx8Present/ )
+ {
+ $frame++;
+ }
+ if( $frame == $desiredFrame )
+ {
+ print "$line: $_";
+ }
+ last if $frame > $desiredFrame;
+}
+close INPUT;
diff --git a/devtools/bin/playback_getstate.pl b/devtools/bin/playback_getstate.pl
new file mode 100644
index 0000000..0796e4e
--- /dev/null
+++ b/devtools/bin/playback_getstate.pl
@@ -0,0 +1,169 @@
+# getfinalstate.pl blah.txt line
+# note: the state is *before* the line that you specify
+die "Usage: playback_getstate.pl blah.txt cmd\n" if scalar( @ARGV ) != 2;
+
+open INPUT, shift || die;
+$desiredcmd = shift;
+$line = 0;
+
+sub PadNumber
+{
+ local( $str ) = shift;
+ local( $desiredLen ) = shift;
+ local( $len ) = length $str;
+ while( $len < $desiredLen )
+ {
+ $str = "0" . $str;
+ $len++;
+ }
+ return $str;
+}
+
+
+while( <INPUT> )
+{
+ m/^cmd: (\d+) /;
+ $cmdnum = $1;
+# print "$cmdnum\n";
+ if( $cmdnum == $desiredcmd )
+ {
+ print "$_";
+ last;
+ }
+ if( /Dx8SetTextureStageState:\s*stage:\s*(\d+)\s*state:\s*(\S+)\s*,\s*value:\s*(\S+)/ )
+ {
+ $texturestate{"$2 $1"} = $3;
+# print "$1 $2 $3\n";
+ }
+# elsif( /Dx8SetTextureStageState/i )
+# {
+# die "$_";
+# }
+
+ if( /Dx8SetRenderState:\s*(\S+)\s+(\S+.*)*$/ )
+ {
+ $renderstate{$1} = $2;
+ }
+# elsif( /Dx8SetRenderState/i )
+# {
+# die "$_";
+# }
+
+ if( /Dx8SetVertexShaderConstant:\s*reg:\s*(\d+)\s*numvecs:\s*(\d+)\s*val:\s*(.*)$/ )
+ {
+ local( $reg ) = $1;
+ local( $count ) = $2;
+ local( $val ) = $3;
+ local( $i );
+ for( $i = 0; $i < $count; $i++, $reg++ )
+ {
+ $val =~ s/^\s*(\[\s*\S+\s+\S+\s+\S+\s+\S+\s*\])(.*$)/$2/;
+ $vertconst{ "vshconst " . &PadNumber( $reg, 2 ) } = $1;
+ }
+ }
+# elsif( /Dx8SetVertexShaderConstant/i )
+# {
+# die "$_";
+# }
+
+ if( /Dx8SetPixelShaderConstant:\s*reg:\s*(\d+)\s*numvecs:\s*(\d+)\s*val:\s*(.*)$/ )
+ {
+ local( $reg ) = $1;
+ local( $count ) = $2;
+ local( $val ) = $3;
+ local( $i );
+ for( $i = 0; $i < $count; $i++, $reg++ )
+ {
+ $val =~ s/^\s*(\[\s*\S+\s+\S+\s+\S+\s+\S+\s*\])(.*$)/$2/;
+ $pixelconst{ "pshconst " . &PadNumber( $reg, 2 ) } = $1;
+ }
+ }
+# elsif( /Dx8SetPixelShaderConstant/i )
+# {
+# die "$_";
+# }
+
+ if( /Dx8SetStreamSource:\s*vertexBufferID:\s*(\d+)\s*streamID:\s*(\d+)\s*vertexSize:\s*(\d+)\s*$/ )
+ {
+ $streamsrc{$2} = "vertexBufferID: $1 vertexSize: $3";
+ }
+# elsif( /Dx8SetStreamSource/i )
+# {
+# die "$_";
+# }
+
+ if( /Dx8CreateVertexShader:\s*id:\s*(\d+)\s+dwDecl:\s*(.*)$/ )
+ {
+ $vshdecl{$1} = $2;
+ }
+ elsif( /Dx8CreateVertexShader/i )
+ {
+ die "$_";
+ }
+
+ if( /Dx8SetVertexShader:\s*vertexShader:\s*(\d+)\s*$/ )
+ {
+ $currentVertexShader = $1;
+ }
+ elsif( /Dx8SetVertexShader:/i )
+ {
+ die "$_";
+ }
+
+ if( /Dx8SetPixelShader:\s*pixelShader:\s*(\d+)\s*$/ )
+ {
+ $currentPixelShader = $1;
+ }
+ elsif( /Dx8SetPixelShader:/i )
+ {
+ die "$_";
+ }
+
+ if( /Dx8SetVertexBufferFormat:\s*id:\s*(\d+)\s*vertexFormat:\s*(.*)$/ )
+ {
+ $vbformat{$1} = $2;
+ }
+ elsif( /Dx8SetVertexBufferFormat/i )
+ {
+ die "$_";
+ }
+}
+close INPUT;
+
+foreach $state ( sort( keys( %texturestate ) ) )
+{
+ print "$state = $texturestate{$state}\n";
+}
+
+foreach $state ( sort( keys( %renderstate ) ) )
+{
+ print "$state = $renderstate{$state}\n";
+}
+
+foreach $state ( sort( keys( %vertconst ) ) )
+{
+ print "$state = $vertconst{$state}\n";
+}
+
+foreach $state ( sort( keys( %pixelconst ) ) )
+{
+ print "$state = $pixelconst{$state}\n";
+}
+
+foreach $state ( sort( keys( %streamsrc ) ) )
+{
+ $streamsrc{$state} =~ m/vertexBufferID:\s*(\d+)\s+/;
+ local( $vertbufid ) = $1;
+ print "stream $state = $streamsrc{$state} vbformat: $vbformat{$vertbufid}\n";
+}
+
+#foreach $state ( sort( keys( %vbformat ) ) )
+#{
+# print "vbformat $state = $vbformat{$state}\n";
+#}
+
+print "current vsh: $currentVertexShader vshdecl: $vshdecl{$currentVertexShader}\n";
+print "current psh: $currentPixelShader\n";
+
+
+
diff --git a/devtools/bin/playback_gettexlock.pl b/devtools/bin/playback_gettexlock.pl
new file mode 100644
index 0000000..bf03c6a
--- /dev/null
+++ b/devtools/bin/playback_gettexlock.pl
@@ -0,0 +1,27 @@
+# This gives you all calls between lock and unlock for the specified texture.
+# gettexlock.pl texid blah.txt
+$desiredTexture = shift;
+open INPUT, shift || die;
+while( <INPUT> )
+{
+ if( /Dx8LockTexture: id: (\d+)\s+/ )
+ {
+ if( $1 == $desiredTexture )
+ {
+ print "----------------------------------------------------\n";
+ print;
+ $gotit = 1;
+ }
+ }
+ elsif( $gotit && /Dx8UnlockTexture: id: (\d+)\s+/ )
+ {
+ die if $1 != $desiredTexture;
+ print;
+ $gotit = 0;
+ }
+ else
+ {
+ print if( $gotit );
+ }
+}
+close INPUT;
diff --git a/devtools/bin/playback_getvb.pl b/devtools/bin/playback_getvb.pl
new file mode 100644
index 0000000..c2ac79b
--- /dev/null
+++ b/devtools/bin/playback_getvb.pl
@@ -0,0 +1,23 @@
+# getframe.pl vbid blah.txt
+$desiredVB = shift;
+open INPUT, shift || die;
+while( <INPUT> )
+{
+ if( /Dx8VertexData: id: (\d+)\s+/ )
+ {
+ if( $1 == $desiredVB )
+ {
+ print;
+ $gotit = 1;
+ }
+ }
+ elsif( $gotit && /^vertex:/ )
+ {
+ print;
+ }
+ else
+ {
+ $gotit = 0;
+ }
+}
+close INPUT;
diff --git a/devtools/bin/playback_numframes.bat b/devtools/bin/playback_numframes.bat
new file mode 100644
index 0000000..cc1f493
--- /dev/null
+++ b/devtools/bin/playback_numframes.bat
@@ -0,0 +1 @@
+grep Dx8Present %1 | wc -l
diff --git a/devtools/bin/playback_numprims.pl b/devtools/bin/playback_numprims.pl
new file mode 100644
index 0000000..f90946f
--- /dev/null
+++ b/devtools/bin/playback_numprims.pl
@@ -0,0 +1,27 @@
+if( scalar( @ARGV ) != 1 )
+{
+ die "Usage: playback_numprims.pl frame.txt\n";
+}
+open INPUT, shift || die;
+$numprims = 0;
+$numcalls = 0;
+while( <INPUT> )
+{
+ if( /DrawIndexedPrimitive.*numPrimitives:\s*(\d+)\s*$/i )
+ {
+ $numprims += $1;
+ if( $1 > 85 )
+ {
+ $numfreeprims += $1;
+ }
+ else
+ {
+ $numfreeprims += 85;
+ }
+ $numcalls++;
+ }
+}
+close INPUT;
+print "$numprims primitives\n";
+print "$numfreeprims freeprimitives\n";
+print "$numcalls calls\n";
diff --git a/devtools/bin/psh_prep.pl b/devtools/bin/psh_prep.pl
new file mode 100644
index 0000000..1c44c41
--- /dev/null
+++ b/devtools/bin/psh_prep.pl
@@ -0,0 +1,333 @@
+use String::CRC32;
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+
+sub BuildDefineOptions
+{
+ local( $output );
+ local( $combo ) = shift;
+ local( $i );
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ local( $val ) = ( $combo % ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) ) + $dynamicDefineMin[$i];
+ $output .= "/D$dynamicDefineNames[$i]=$val ";
+ $combo = $combo / ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 );
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ local( $val ) = ( $combo % ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) ) + $staticDefineMin[$i];
+ $output .= "/D$staticDefineNames[$i]=$val ";
+ $combo = $combo / ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 );
+ }
+ return $output;
+}
+
+sub CalcNumCombos
+{
+ local( $i, $numCombos );
+ $numCombos = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
+ }
+ return $numCombos;
+}
+
+sub CalcNumDynamicCombos
+{
+ local( $i, $numCombos );
+ $numCombos = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ return $numCombos;
+}
+
+$g_dx9 = 1;
+
+while( 1 )
+{
+ $psh_filename = shift;
+
+ if( $psh_filename =~ m/-source/ )
+ {
+ $g_SourceDir = shift;
+ }
+ elsif( $psh_filename =~ m/-x360/ )
+ {
+ $g_x360 = 1;
+ }
+ else
+ {
+ last;
+ }
+}
+
+$psh_filename =~ s/-----.*$//;
+
+
+# Get the shader binary version number from a header file.
+open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die;
+while( $line = <FILE> )
+{
+ if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ )
+ {
+ $shaderVersion = $1;
+ last;
+ }
+}
+if( !defined $shaderVersion )
+{
+ die "couldn't get shader version from shader_vcs_version.h";
+}
+close FILE;
+
+
+
+local( @staticDefineNames );
+local( @staticDefineMin );
+local( @staticDefineMax );
+local( @dynamicDefineNames );
+local( @dynamicDefineMin );
+local( @dynamicDefineMax );
+
+# Parse the combos.
+open PSH, "<$psh_filename";
+while( <PSH> )
+{
+ last if( !m,^;, );
+ s,^;\s*,,;
+ if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
+ {
+ local( $name, $min, $max );
+ $name = $1;
+ $min = $2;
+ $max = $3;
+# print "\"STATIC: $name\" \"$min..$max\"\n";
+ if (/\[(.*)\]/)
+ {
+ $platforms=$1;
+ next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
+ next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
+ }
+ push @staticDefineNames, $name;
+ push @staticDefineMin, $min;
+ push @staticDefineMax, $max;
+ }
+ elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
+ {
+ local( $name, $min, $max );
+ $name = $1;
+ $min = $2;
+ $max = $3;
+# print "\"DYNAMIC: $name\" \"$min..$max\"\n";
+ if (/\[(.*)\]/)
+ {
+ $platforms=$1;
+ next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
+ next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
+ }
+ push @dynamicDefineNames, $name;
+ push @dynamicDefineMin, $min;
+ push @dynamicDefineMax, $max;
+ }
+}
+close PSH;
+
+$numCombos = &CalcNumCombos();
+$numDynamicCombos = &CalcNumDynamicCombos();
+print "$psh_filename\n";
+#print "$numCombos combos\n";
+#print "$numDynamicCombos dynamic combos\n";
+
+if( $g_x360 )
+{
+ $pshtmp = "pshtmp9_360";
+}
+elsif( $g_dx9 )
+{
+ $pshtmp = "pshtmp9";
+}
+else
+{
+ $pshtmp = "pshtmp8";
+}
+$basename = $psh_filename;
+$basename =~ s/\.psh$//i;
+
+for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
+{
+ my $tempFilename = "shader$shaderCombo.o";
+ unlink $tempFilename;
+
+ if( $g_x360 )
+ {
+ $cmd = "$g_SourceDir\\x360xdk\\bin\\win32\\psa /D_X360=1 /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL";
+ }
+ else
+ {
+ $cmd = "$g_SourceDir\\dx9sdk\\utilities\\psa /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL";
+ }
+
+ if( !stat $pshtmp )
+ {
+ mkdir $pshtmp, 0777 || die $!;
+ }
+
+# print $cmd . "\n";
+ system $cmd || die $!;
+
+ # Make sure a file got generated because sometimes the die above won't happen on compile errors.
+ my $filesize = (stat $tempFilename)[7];
+ if ( !$filesize )
+ {
+ die "Error compiling shader$shaderCombo.o";
+ }
+
+ push @outputHeader, @hdr;
+}
+
+$basename =~ s/\.fxc//gi;
+push @outputHeader, "static PrecompiledShaderByteCode_t " . $basename . "_pixel_shaders[" . $numCombos . "] = \n";
+push @outputHeader, "{\n";
+local( $j );
+for( $j = 0; $j < $numCombos; $j++ )
+{
+ local( $thing ) = "pixelShader_" . $basename . "_" . $j;
+ push @outputHeader, "\t{ " . "$thing, sizeof( $thing ) },\n";
+}
+push @outputHeader, "};\n";
+
+push @outputHeader, "struct $basename" . "PixelShader_t : public PrecompiledShader_t\n";
+push @outputHeader, "{\n";
+push @outputHeader, "\t$basename" . "PixelShader_t()\n";
+push @outputHeader, "\t{\n";
+push @outputHeader, "\t\tm_nFlags = 0;\n";
+push @outputHeader, "\t\tm_pByteCode = " . $basename . "_pixel_shaders;\n";
+push @outputHeader, "\t\tm_nShaderCount = $numCombos;\n";
+#push @outputHeader, "\t\tm_nDynamicCombos = m_nShaderCount;\n";
+push @outputHeader, "\t\t// NOTE!!! psh_prep.pl shaders are always static combos!\n";
+push @outputHeader, "\t\tm_nDynamicCombos = 1;\n";
+push @outputHeader, "\t\tm_pName = \"$basename\";\n";
+if( $basename =~ /vs\d\d/ ) # hack
+{
+ push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n";
+}
+else
+{
+ push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_PIXEL_SHADER, this );\n";
+}
+push @outputHeader, "\t}\n";
+push @outputHeader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n";
+push @outputHeader, "\t{\n";
+push @outputHeader, "\t\treturn m_pByteCode[shaderID];\n";
+push @outputHeader, "\t}\n";
+push @outputHeader, "};\n";
+
+push @outputHeader, "static $basename" . "PixelShader_t $basename" . "_PixelShaderInstance;\n";
+
+
+&MakeDirHier( "shaders/psh" );
+
+my $vcsName = "";
+if( $g_x360 )
+{
+ $vcsName = $basename . ".360.vcs";
+}
+else
+{
+ $vcsName = $basename . ".vcs";
+}
+
+open COMPILEDSHADER, ">shaders/psh/$vcsName" || die;
+binmode( COMPILEDSHADER );
+
+#
+# Write out the part of the header that we know. . we'll write the rest after writing the object code.
+#
+
+#print $numCombos . "\n";
+
+# Pack arguments
+my $sInt = "i";
+my $uInt = "I";
+if ( $g_x360 )
+{
+ # Change arguments to "big endian long"
+ $sInt = "N";
+ $uInt = "N";
+}
+
+open PSH, "<$psh_filename";
+my $crc = crc32( *PSH );
+close PSH;
+#print STDERR "crc for $psh_filename: $crc\n";
+
+# version
+print COMPILEDSHADER pack $sInt, 4;
+# totalCombos
+print COMPILEDSHADER pack $sInt, $numCombos;
+# dynamic combos
+print COMPILEDSHADER pack $sInt, $numDynamicCombos;
+# flags
+print COMPILEDSHADER pack $uInt, 0x0; # nothing here for now.
+# centroid mask
+print COMPILEDSHADER pack $uInt, 0;
+# reference size for diffs
+print COMPILEDSHADER pack $uInt, 0;
+# crc32 of the source code
+print COMPILEDSHADER pack $uInt, $crc;
+
+my $beginningOfDir = tell COMPILEDSHADER;
+
+# Write out a blank directionary. . we'll fill it in later.
+for( $i = 0; $i < $numCombos; $i++ )
+{
+ # offset from beginning of file.
+ print COMPILEDSHADER pack $sInt, 0;
+ # size
+ print COMPILEDSHADER pack $sInt, 0;
+}
+
+my $startByteCode = tell COMPILEDSHADER;
+my @byteCodeStart;
+my @byteCodeSize;
+
+# Write out the shader object code.
+for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
+{
+ my $filename = "shader$shaderCombo\.o";
+ my $filesize = (stat $filename)[7];
+
+ $byteCodeStart[$shaderCombo] = tell COMPILEDSHADER;
+ $byteCodeSize[$shaderCombo] = $filesize;
+ open SHADERBYTECODE, "<$filename";
+ binmode SHADERBYTECODE;
+
+ my $bin;
+ my $numread = read SHADERBYTECODE, $bin, $filesize;
+# print "filename: $filename numread: $numread filesize: $filesize\n";
+ close SHADERBYTECODE;
+ unlink $filename;
+
+ print COMPILEDSHADER $bin;
+}
+
+# Seek back to the directory and write it out.
+seek COMPILEDSHADER, $beginningOfDir, 0;
+for( $i = 0; $i < $numCombos; $i++ )
+{
+ # offset from beginning of file.
+ print COMPILEDSHADER pack $sInt, $byteCodeStart[$i];
+ # size
+ print COMPILEDSHADER pack $sInt, $byteCodeSize[$i];
+}
+
+close COMPILEDSHADER;
+
+
diff --git a/devtools/bin/putty/LICENCE b/devtools/bin/putty/LICENCE
new file mode 100644
index 0000000..1960cc2
--- /dev/null
+++ b/devtools/bin/putty/LICENCE
@@ -0,0 +1,25 @@
+PuTTY is copyright 1997-2007 Simon Tatham.
+
+Portions copyright Robert de Bath, Joris van Rantwijk, Delian
+Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
+Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
+Kuhn, and CORE SDI S.A.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/devtools/bin/putty/README.txt b/devtools/bin/putty/README.txt
new file mode 100644
index 0000000..b4b5fba
--- /dev/null
+++ b/devtools/bin/putty/README.txt
@@ -0,0 +1,40 @@
+PuTTY README
+============
+
+This is the README file for the PuTTY installer distribution. If
+you're reading this, you've probably just run our installer and
+installed PuTTY on your system.
+
+What should I do next?
+----------------------
+
+If you want to use PuTTY to connect to other computers, or use PSFTP
+to transfer files, you should just be able to run them from the
+Start menu.
+
+If you want to use the command-line-only file transfer utility PSCP,
+you will probably want to put the PuTTY installation directory on
+your PATH. How you do this depends on your version of Windows. On
+Windows NT, 2000, and XP, you can set it using Control Panel > System;
+on Windows 95, 98, and Me, you will need to edit AUTOEXEC.BAT. Consult
+your Windows manuals for details.
+
+Some versions of Windows will refuse to run HTML Help files (.CHM)
+if they are installed on a network drive. If you have installed
+PuTTY on a network drive, you might want to check that the help file
+works properly. If not, see http://support.microsoft.com/kb/896054
+for information on how to solve this problem.
+
+What do I do if it doesn't work?
+--------------------------------
+
+The PuTTY home web site is
+
+ http://www.chiark.greenend.org.uk/~sgtatham/putty/
+
+Here you will find our list of known bugs and pending feature
+requests. If your problem is not listed in there, or in the FAQ, or
+in the manuals, read the Feedback page to find out how to report
+bugs to us. PLEASE read the Feedback page carefully: it is there to
+save you time as well as us. Do not send us one-line bug reports
+telling us `it doesn't work'.
diff --git a/devtools/bin/putty/pageant.exe b/devtools/bin/putty/pageant.exe
new file mode 100644
index 0000000..ea2379b
--- /dev/null
+++ b/devtools/bin/putty/pageant.exe
Binary files differ
diff --git a/devtools/bin/putty/plink.exe b/devtools/bin/putty/plink.exe
new file mode 100644
index 0000000..a27bf36
--- /dev/null
+++ b/devtools/bin/putty/plink.exe
Binary files differ
diff --git a/devtools/bin/putty/pscp.exe b/devtools/bin/putty/pscp.exe
new file mode 100644
index 0000000..e511e5b
--- /dev/null
+++ b/devtools/bin/putty/pscp.exe
Binary files differ
diff --git a/devtools/bin/putty/psftp.exe b/devtools/bin/putty/psftp.exe
new file mode 100644
index 0000000..1f986e7
--- /dev/null
+++ b/devtools/bin/putty/psftp.exe
Binary files differ
diff --git a/devtools/bin/putty/putty.cnt b/devtools/bin/putty/putty.cnt
new file mode 100644
index 0000000..84d15ef
--- /dev/null
+++ b/devtools/bin/putty/putty.cnt
@@ -0,0 +1,492 @@
+:Title PuTTY User Manual
+1 Title page=Top
+1 Chapter 1: Introduction to PuTTY
+2 Chapter 1: Introduction to PuTTY=t00000000
+2 Section 1.1: What are SSH, Telnet and Rlogin?=t00000001
+2 Section 1.2: How do SSH, Telnet and Rlogin differ?=t00000002
+1 Chapter 2: Getting started with PuTTY
+2 Chapter 2: Getting started with PuTTY=t00000003
+2 Section 2.1: Starting a session=t00000004
+2 Section 2.2: Verifying the host key (SSH only)=t00000005
+2 Section 2.3: Logging in=t00000006
+2 Section 2.4: After logging in=t00000007
+2 Section 2.5: Logging out=t00000008
+1 Chapter 3: Using PuTTY
+2 Chapter 3: Using PuTTY=t00000009
+2 Section 3.1: During your session
+3 Section 3.1: During your session=t00000010
+3 Section 3.1.1: Copying and pasting text=t00000011
+3 Section 3.1.2: Scrolling the screen back=t00000012
+3 Section 3.1.3: The System menu
+4 Section 3.1.3: The System menu=t00000013
+4 Section 3.1.3.1: The PuTTY Event Log=t00000014
+4 Section 3.1.3.2: Special commands=t00000015
+4 Section 3.1.3.3: Starting new sessions=t00000016
+4 Section 3.1.3.4: Changing your session settings=t00000017
+4 Section 3.1.3.5: Copy All to Clipboard=t00000018
+4 Section 3.1.3.6: Clearing and resetting the terminal=t00000019
+4 Section 3.1.3.7: Full screen mode=t00000020
+1 Section 3.2: Creating a log file of your session=t00000021
+1 Section 3.3: Altering your character set configuration=t00000022
+1 Section 3.4: Using X11 forwarding in SSH=t00000023
+1 Section 3.5: Using port forwarding in SSH=t00000024
+1 Section 3.6: Making raw TCP connections=t00000025
+1 Section 3.7: Connecting to a local serial line=t00000026
+2 Section 3.8: The PuTTY command line
+3 Section 3.8: The PuTTY command line=t00000027
+3 Section 3.8.1: Starting a session from the command line=t00000028
+3 Section 3.8.2: -cleanup=options.cleanup
+3 Section 3.8.3: Standard command-line options
+4 Section 3.8.3: Standard command-line options=t00000029
+4 Section 3.8.3.1: -load: load a saved session=t00000030
+4 Section 3.8.3.2: Selecting a protocol: -ssh, -telnet, -rlogin, -raw=t00000031
+4 Section 3.8.3.3: -v: increase verbosity=t00000032
+4 Section 3.8.3.4: -l: specify a login name=t00000033
+4 Section 3.8.3.5: -L, -R and -D: set up port forwardings=t00000034
+4 Section 3.8.3.6: -m: read a remote command or script from a file=t00000035
+4 Section 3.8.3.7: -P: specify a port number=t00000036
+4 Section 3.8.3.8: -pw: specify a password=t00000037
+4 Section 3.8.3.9: -agent and -noagent: control use of Pageant for authentication=t00000038
+4 Section 3.8.3.10: -A and -a: control agent forwarding=t00000039
+4 Section 3.8.3.11: -X and -x: control X11 forwarding=t00000040
+4 Section 3.8.3.12: -t and -T: control pseudo-terminal allocation=t00000041
+4 Section 3.8.3.13: -N: suppress starting a shell or command=t00000042
+4 Section 3.8.3.14: -nc: make a remote network connection in place of a remote shell or command=t00000043
+4 Section 3.8.3.15: -C: enable compression=t00000044
+4 Section 3.8.3.16: -1 and -2: specify an SSH protocol version=t00000045
+4 Section 3.8.3.17: -4 and -6: specify an Internet protocol version=t00000046
+4 Section 3.8.3.18: -i: specify an SSH private key=t00000047
+4 Section 3.8.3.19: -pgpfp: display PGP key fingerprints=t00000048
+1 Chapter 4: Configuring PuTTY
+2 Chapter 4: Configuring PuTTY=t00000049
+2 Section 4.1: The Session panel
+3 Section 4.1: The Session panel=t00000050
+3 Section 4.1.1: The host name section=session.hostname
+3 Section 4.1.2: Loading and storing saved sessions=session.saved
+3 Section 4.1.3: �Close Window on Exit�=session.coe
+2 Section 4.2: The Logging panel
+3 Section 4.2: The Logging panel=logging.main
+3 Section 4.2.1: �Log file name�=logging.filename
+3 Section 4.2.2: �What to do if the log file already exists�=logging.exists
+3 Section 4.2.3: �Flush log file frequently�=logging.flush
+3 Section 4.2.4: Options specific to SSH packet logging
+4 Section 4.2.4: Options specific to SSH packet logging=t00000051
+4 Section 4.2.4.1: �Omit known password fields�=logging.ssh.omitpassword
+4 Section 4.2.4.2: �Omit session data�=logging.ssh.omitdata
+2 Section 4.3: The Terminal panel
+3 Section 4.3: The Terminal panel=t00000052
+3 Section 4.3.1: �Auto wrap mode initially on�=terminal.autowrap
+3 Section 4.3.2: �DEC Origin Mode initially on�=terminal.decom
+3 Section 4.3.3: �Implicit CR in every LF�=terminal.lfhascr
+3 Section 4.3.4: �Use background colour to erase screen�=terminal.bce
+3 Section 4.3.5: �Enable blinking text�=terminal.blink
+3 Section 4.3.6: �Answerback to ^E�=terminal.answerback
+3 Section 4.3.7: �Local echo�=terminal.localecho
+3 Section 4.3.8: �Local line editing�=terminal.localedit
+3 Section 4.3.9: Remote-controlled printing=terminal.printing
+2 Section 4.4: The Keyboard panel
+3 Section 4.4: The Keyboard panel=t00000053
+3 Section 4.4.1: Changing the action of the Backspace key=keyboard.backspace
+3 Section 4.4.2: Changing the action of the Home and End keys=keyboard.homeend
+3 Section 4.4.3: Changing the action of the function keys and keypad=keyboard.funkeys
+3 Section 4.4.4: Controlling Application Cursor Keys mode=keyboard.appcursor
+3 Section 4.4.5: Controlling Application Keypad mode=keyboard.appkeypad
+3 Section 4.4.6: Using NetHack keypad mode=keyboard.nethack
+3 Section 4.4.7: Enabling a DEC-like Compose key=keyboard.compose
+3 Section 4.4.8: �Control-Alt is different from AltGr�=keyboard.ctrlalt
+2 Section 4.5: The Bell panel
+3 Section 4.5: The Bell panel=t00000054
+3 Section 4.5.1: �Set the style of bell�=bell.style
+3 Section 4.5.2: �Taskbar/caption indication on bell�=bell.taskbar
+3 Section 4.5.3: �Control the bell overload behaviour�=bell.overload
+2 Section 4.6: The Features panel
+3 Section 4.6: The Features panel=t00000055
+3 Section 4.6.1: Disabling application keypad and cursor keys=features.application
+3 Section 4.6.2: Disabling xterm-style mouse reporting=features.mouse
+3 Section 4.6.3: Disabling remote terminal resizing=features.resize
+3 Section 4.6.4: Disabling switching to the alternate screen=features.altscreen
+3 Section 4.6.5: Disabling remote window title changing=features.retitle
+3 Section 4.6.6: Response to remote window title querying=features.qtitle
+3 Section 4.6.7: Disabling destructive backspace=features.dbackspace
+3 Section 4.6.8: Disabling remote character set configuration=features.charset
+3 Section 4.6.9: Disabling Arabic text shaping=features.arabicshaping
+3 Section 4.6.10: Disabling bidirectional text display=features.bidi
+2 Section 4.7: The Window panel
+3 Section 4.7: The Window panel=t00000056
+3 Section 4.7.1: Setting the size of the PuTTY window=window.size
+3 Section 4.7.2: What to do when the window is resized=window.resize
+3 Section 4.7.3: Controlling scrollback=window.scrollback
+3 Section 4.7.4: �Push erased text into scrollback�=window.erased
+2 Section 4.8: The Appearance panel
+3 Section 4.8: The Appearance panel=t00000057
+3 Section 4.8.1: Controlling the appearance of the cursor=appearance.cursor
+3 Section 4.8.2: Controlling the font used in the terminal window=appearance.font
+3 Section 4.8.3: �Hide mouse pointer when typing in window�=appearance.hidemouse
+3 Section 4.8.4: Controlling the window border=appearance.border
+2 Section 4.9: The Behaviour panel
+3 Section 4.9: The Behaviour panel=t00000058
+3 Section 4.9.1: Controlling the window title=appearance.title
+3 Section 4.9.2: �Warn before closing window�=behaviour.closewarn
+3 Section 4.9.3: �Window closes on ALT-F4�=behaviour.altf4
+3 Section 4.9.4: �System menu appears on ALT-Space�=behaviour.altspace
+3 Section 4.9.5: �System menu appears on Alt alone�=behaviour.altonly
+3 Section 4.9.6: �Ensure window is always on top�=behaviour.alwaysontop
+3 Section 4.9.7: �Full screen on Alt-Enter�=behaviour.altenter
+2 Section 4.10: The Translation panel
+3 Section 4.10: The Translation panel=t00000059
+3 Section 4.10.1: Controlling character set translation=translation.codepage
+3 Section 4.10.2: �Treat CJK ambiguous characters as wide�=translation.cjkambigwide
+3 Section 4.10.3: �Caps Lock acts as Cyrillic switch�=translation.cyrillic
+3 Section 4.10.4: Controlling display of line-drawing characters=translation.linedraw
+3 Section 4.10.5: Controlling copy and paste of line drawing characters=selection.linedraw
+2 Section 4.11: The Selection panel
+3 Section 4.11: The Selection panel=t00000060
+3 Section 4.11.1: Pasting in Rich Text Format=selection.rtf
+3 Section 4.11.2: Changing the actions of the mouse buttons=selection.buttons
+3 Section 4.11.3: �Shift overrides application's use of mouse�=selection.shiftdrag
+3 Section 4.11.4: Default selection mode=selection.rect
+3 Section 4.11.5: Configuring word-by-word selection=selection.charclasses
+2 Section 4.12: The Colours panel
+3 Section 4.12: The Colours panel=t00000061
+3 Section 4.12.1: �Allow terminal to specify ANSI colours�=colours.ansi
+3 Section 4.12.2: �Allow terminal to use xterm 256-colour mode�=colours.xterm256
+3 Section 4.12.3: �Bolded text is a different colour�=colours.bold
+3 Section 4.12.4: �Attempt to use logical palettes�=colours.logpal
+3 Section 4.12.5: �Use system colours�=colours.system
+3 Section 4.12.6: Adjusting the colours in the terminal window=colours.config
+2 Section 4.13: The Connection panel
+3 Section 4.13: The Connection panel=t00000062
+3 Section 4.13.1: Using keepalives to prevent disconnection=connection.keepalive
+3 Section 4.13.2: �Disable Nagle's algorithm�=connection.nodelay
+3 Section 4.13.3: �Enable TCP keepalives�=connection.tcpkeepalive
+3 Section 4.13.4: �Internet protocol�=connection.ipversion
+2 Section 4.14: The Data panel
+3 Section 4.14: The Data panel=t00000063
+3 Section 4.14.1: �Auto-login username�=connection.username
+3 Section 4.14.2: �Terminal-type string�=connection.termtype
+3 Section 4.14.3: �Terminal speeds�=connection.termspeed
+3 Section 4.14.4: Setting environment variables on the server=telnet.environ
+2 Section 4.15: The Proxy panel
+3 Section 4.15: The Proxy panel=proxy.main
+3 Section 4.15.1: Setting the proxy type=proxy.type
+3 Section 4.15.2: Excluding parts of the network from proxying=proxy.exclude
+3 Section 4.15.3: Name resolution when using a proxy=proxy.dns
+3 Section 4.15.4: Username and password=proxy.auth
+3 Section 4.15.5: Specifying the Telnet or Local proxy command=proxy.command
+2 Section 4.16: The Telnet panel
+3 Section 4.16: The Telnet panel=t00000064
+3 Section 4.16.1: �Handling of OLD_ENVIRON ambiguity�=telnet.oldenviron
+3 Section 4.16.2: Passive and active Telnet negotiation modes=telnet.passive
+3 Section 4.16.3: �Keyboard sends Telnet special commands�=telnet.specialkeys
+3 Section 4.16.4: �Return key sends Telnet New Line instead of ^M�=telnet.newline
+2 Section 4.17: The Rlogin panel
+3 Section 4.17: The Rlogin panel=t00000065
+3 Section 4.17.1: �Local username�=rlogin.localuser
+2 Section 4.18: The SSH panel
+3 Section 4.18: The SSH panel=t00000066
+3 Section 4.18.1: Executing a specific command on the server=ssh.command
+3 Section 4.18.2: �Don't start a shell or command at all�=ssh.noshell
+3 Section 4.18.3: �Enable compression�=ssh.compress
+3 Section 4.18.4: �Preferred SSH protocol version�=ssh.protocol
+3 Section 4.18.5: Encryption algorithm selection=ssh.ciphers
+2 Section 4.19: The Kex panel
+3 Section 4.19: The Kex panel=t00000067
+3 Section 4.19.1: Key exchange algorithm selection=ssh.kex.order
+3 Section 4.19.2: Repeat key exchange=ssh.kex.repeat
+2 Section 4.20: The Auth panel
+3 Section 4.20: The Auth panel=t00000068
+3 Section 4.20.1: �Bypass authentication entirely�=ssh.auth.bypass
+3 Section 4.20.2: �Attempt authentication using Pageant�=ssh.auth.pageant
+3 Section 4.20.3: �Attempt TIS or CryptoCard authentication�=ssh.auth.tis
+3 Section 4.20.4: �Attempt keyboard-interactive authentication�=ssh.auth.ki
+3 Section 4.20.5: �Allow agent forwarding�=ssh.auth.agentfwd
+3 Section 4.20.6: �Allow attempted changes of username in SSH-2�=ssh.auth.changeuser
+3 Section 4.20.7: �Private key file for authentication�=ssh.auth.privkey
+2 Section 4.21: The TTY panel
+3 Section 4.21: The TTY panel=t00000069
+3 Section 4.21.1: �Don't allocate a pseudo-terminal�=ssh.nopty
+3 Section 4.21.2: Sending terminal modes=ssh.ttymodes
+2 Section 4.22: The X11 panel
+3 Section 4.22: The X11 panel=ssh.tunnels.x11
+3 Section 4.22.1: Remote X11 authentication=ssh.tunnels.x11auth
+2 Section 4.23: The Tunnels panel
+3 Section 4.23: The Tunnels panel=ssh.tunnels.portfwd
+3 Section 4.23.1: Controlling the visibility of forwarded ports=ssh.tunnels.portfwd.localhost
+3 Section 4.23.2: Selecting Internet protocol version for forwarded ports=ssh.tunnels.portfwd.ipversion
+2 Section 4.24: The Bugs panel
+3 Section 4.24: The Bugs panel=t00000070
+3 Section 4.24.1: �Chokes on SSH-1 ignore messages�=ssh.bugs.ignore1
+3 Section 4.24.2: �Refuses all SSH-1 password camouflage�=ssh.bugs.plainpw1
+3 Section 4.24.3: �Chokes on SSH-1 RSA authentication�=ssh.bugs.rsa1
+3 Section 4.24.4: �Miscomputes SSH-2 HMAC keys�=ssh.bugs.hmac2
+3 Section 4.24.5: �Miscomputes SSH-2 encryption keys�=ssh.bugs.derivekey2
+3 Section 4.24.6: �Requires padding on SSH-2 RSA signatures�=ssh.bugs.rsapad2
+3 Section 4.24.7: �Misuses the session ID in SSH-2 PK auth�=ssh.bugs.pksessid2
+3 Section 4.24.8: �Handles SSH-2 key re-exchange badly�=ssh.bugs.rekey2
+2 Section 4.25: The Serial panel
+3 Section 4.25: The Serial panel=t00000071
+3 Section 4.25.1: Selecting a serial line to connect to=serial.line
+3 Section 4.25.2: Selecting the speed of your serial line=serial.speed
+3 Section 4.25.3: Selecting the number of data bits=serial.databits
+3 Section 4.25.4: Selecting the number of stop bits=serial.stopbits
+3 Section 4.25.5: Selecting the serial parity checking scheme=serial.parity
+3 Section 4.25.6: Selecting the serial flow control scheme=serial.flow
+1 Section 4.26: Storing configuration in a file=t00000072
+1 Chapter 5: Using PSCP to transfer files securely
+2 Chapter 5: Using PSCP to transfer files securely=t00000073
+2 Section 5.1: Starting PSCP=t00000074
+2 Section 5.2: PSCP Usage
+3 Section 5.2: PSCP Usage=t00000075
+3 Section 5.2.1: The basics
+4 Section 5.2.1: The basics=t00000076
+4 Section 5.2.1.1: user=t00000077
+4 Section 5.2.1.2: host=t00000078
+4 Section 5.2.1.3: source=t00000079
+4 Section 5.2.1.4: target=t00000080
+3 Section 5.2.2: Options
+4 Section 5.2.2: Options=t00000081
+4 Section 5.2.2.1: -ls list remote files=t00000082
+4 Section 5.2.2.2: -p preserve file attributes=t00000083
+4 Section 5.2.2.3: -q quiet, don't show statistics=t00000084
+4 Section 5.2.2.4: -r copies directories recursively=t00000085
+4 Section 5.2.2.5: -batch avoid interactive prompts=t00000086
+4 Section 5.2.2.6: -sftp, -scp force use of particular protocol=t00000087
+2 Section 5.2.3: Return value=t00000088
+2 Section 5.2.4: Using public key authentication with PSCP=t00000089
+1 Chapter 6: Using PSFTP to transfer files securely
+2 Chapter 6: Using PSFTP to transfer files securely=t00000090
+2 Section 6.1: Starting PSFTP
+3 Section 6.1: Starting PSFTP=t00000091
+3 Section 6.1.1: -b: specify a file containing batch commands=t00000092
+3 Section 6.1.2: -bc: display batch commands as they are run=t00000093
+3 Section 6.1.3: -be: continue batch processing on errors=t00000094
+3 Section 6.1.4: -batch: avoid interactive prompts=t00000095
+2 Section 6.2: Running PSFTP
+3 Section 6.2: Running PSFTP=t00000096
+3 Section 6.2.1: General quoting rules for PSFTP commands=t00000097
+3 Section 6.2.2: Wildcards in PSFTP=t00000098
+3 Section 6.2.3: The open command: start a session=t00000099
+3 Section 6.2.4: The quit command: end your session=t00000100
+3 Section 6.2.5: The close command: close your connection=t00000101
+3 Section 6.2.6: The help command: get quick online help=t00000102
+3 Section 6.2.7: The cd and pwd commands: changing the remote working directory=t00000103
+3 Section 6.2.8: The lcd and lpwd commands: changing the local working directory=t00000104
+3 Section 6.2.9: The get command: fetch a file from the server=t00000105
+3 Section 6.2.10: The put command: send a file to the server=t00000106
+3 Section 6.2.11: The mget and mput commands: fetch or send multiple files=t00000107
+3 Section 6.2.12: The reget and reput commands: resuming file transfers=t00000108
+3 Section 6.2.13: The dir command: list remote files=t00000109
+3 Section 6.2.14: The chmod command: change permissions on remote files=t00000110
+3 Section 6.2.15: The del command: delete remote files=t00000111
+3 Section 6.2.16: The mkdir command: create remote directories=t00000112
+3 Section 6.2.17: The rmdir command: remove remote directories=t00000113
+3 Section 6.2.18: The mv command: move and rename remote files=t00000114
+3 Section 6.2.19: The ! command: run a local Windows command=t00000115
+1 Section 6.3: Using public key authentication with PSFTP=t00000116
+1 Chapter 7: Using the command-line connection tool Plink
+2 Chapter 7: Using the command-line connection tool Plink=t00000117
+2 Section 7.1: Starting Plink=t00000118
+2 Section 7.2: Using Plink
+3 Section 7.2: Using Plink=t00000119
+3 Section 7.2.1: Using Plink for interactive logins=t00000120
+3 Section 7.2.2: Using Plink for automated connections=t00000121
+3 Section 7.2.3: Plink command line options
+4 Section 7.2.3: Plink command line options=t00000122
+4 Section 7.2.3.1: -batch: disable all interactive prompts=t00000123
+4 Section 7.2.3.2: -s: remote command is SSH subsystem=t00000124
+1 Section 7.3: Using Plink in batch files and scripts=t00000125
+1 Section 7.4: Using Plink with CVS=t00000126
+1 Section 7.5: Using Plink with WinCVS=t00000127
+1 Chapter 8: Using public keys for SSH authentication
+2 Chapter 8: Using public keys for SSH authentication=t00000128
+2 Section 8.1: Public key authentication - an introduction=t00000129
+2 Section 8.2: Using PuTTYgen, the PuTTY key generator
+3 Section 8.2: Using PuTTYgen, the PuTTY key generator=puttygen.general
+3 Section 8.2.1: Generating a new key=t00000130
+3 Section 8.2.2: Selecting the type of key=puttygen.keytype
+3 Section 8.2.3: Selecting the size (strength) of the key=puttygen.bits
+3 Section 8.2.4: The �Generate� button=puttygen.generate
+3 Section 8.2.5: The �Key fingerprint� box=puttygen.fingerprint
+3 Section 8.2.6: Setting a comment for your key=puttygen.comment
+3 Section 8.2.7: Setting a passphrase for your key=puttygen.passphrase
+3 Section 8.2.8: Saving your private key to a disk file=puttygen.savepriv
+3 Section 8.2.9: Saving your public key to a disk file=puttygen.savepub
+3 Section 8.2.10: �Public key for pasting into authorized_keys file�=puttygen.pastekey
+3 Section 8.2.11: Reloading a private key=puttygen.load
+3 Section 8.2.12: Dealing with private keys in other formats=puttygen.conversions
+1 Section 8.3: Getting ready for public key authentication=t00000131
+1 Chapter 9: Using Pageant for authentication
+2 Chapter 9: Using Pageant for authentication=pageant.general
+2 Section 9.1: Getting started with Pageant=t00000132
+2 Section 9.2: The Pageant main window
+3 Section 9.2: The Pageant main window=t00000133
+3 Section 9.2.1: The key list box=pageant.keylist
+3 Section 9.2.2: The �Add Key� button=pageant.addkey
+3 Section 9.2.3: The �Remove Key� button=pageant.remkey
+2 Section 9.3: The Pageant command line
+3 Section 9.3: The Pageant command line=t00000134
+3 Section 9.3.1: Making Pageant automatically load keys on startup=t00000135
+3 Section 9.3.2: Making Pageant run another program=t00000136
+1 Section 9.4: Using agent forwarding=t00000137
+1 Section 9.5: Security considerations=t00000138
+1 Chapter 10: Common error messages
+2 Chapter 10: Common error messages=t00000139
+2 Section 10.1: �The server's host key is not cached in the registry�=errors.hostkey.absent
+2 Section 10.2: �WARNING - POTENTIAL SECURITY BREACH!�=errors.hostkey.changed
+2 Section 10.3: �Out of space for port forwardings�=t00000140
+2 Section 10.4: �The first cipher supported by the server is ... below the configured warning threshold�=t00000141
+2 Section 10.5: �Server sent disconnect message type 2 (protocol error): "Too many authentication failures for root"�=t00000142
+2 Section 10.6: �Out of memory�=t00000143
+2 Section 10.7: �Internal error�, �Internal fault�, �Assertion failed�=t00000144
+2 Section 10.8: �Unable to use this private key file�, �Couldn't load private key�, �Key is of wrong type�=errors.cantloadkey
+2 Section 10.9: �Server refused our public key� or �Key refused�=t00000145
+2 Section 10.10: �Access denied�, �Authentication refused�=t00000146
+2 Section 10.11: �Incorrect CRC received on packet� or �Incorrect MAC received on packet�=t00000147
+2 Section 10.12: �Incoming packet was garbled on decryption�=t00000148
+2 Section 10.13: �PuTTY X11 proxy: various errors�=t00000149
+2 Section 10.14: �Network error: Software caused connection abort�=t00000150
+2 Section 10.15: �Network error: Connection reset by peer�=t00000151
+2 Section 10.16: �Network error: Connection refused�=t00000152
+2 Section 10.17: �Network error: Connection timed out�=t00000153
+1 Appendix A: PuTTY FAQ
+2 Appendix A: PuTTY FAQ=t00000154
+2 Section A.1: Introduction
+3 Section A.1: Introduction=t00000155
+3 Question A.1.1: What is PuTTY?=t00000156
+2 Section A.2: Features supported in PuTTY
+3 Section A.2: Features supported in PuTTY=t00000157
+3 Question A.2.1: Does PuTTY support SSH-2?=t00000158
+3 Question A.2.2: Does PuTTY support reading OpenSSH or ssh.com SSH-2 private key files?=t00000159
+3 Question A.2.3: Does PuTTY support SSH-1?=t00000160
+3 Question A.2.4: Does PuTTY support local echo?=t00000161
+3 Question A.2.5: Does PuTTY support storing settings, so I don't have to change them every time?=t00000162
+3 Question A.2.6: Does PuTTY support storing its settings in a disk file?=t00000163
+3 Question A.2.7: Does PuTTY support full-screen mode, like a DOS box?=t00000164
+3 Question A.2.8: Does PuTTY have the ability to remember my password so I don't have to type it every time?=t00000165
+3 Question A.2.9: Is there an option to turn off the annoying host key prompts?=t00000166
+3 Question A.2.10: Will you write an SSH server for the PuTTY suite, to go with the client?=t00000167
+3 Question A.2.11: Can PSCP or PSFTP transfer files in ASCII mode?=t00000168
+2 Section A.3: Ports to other operating systems
+3 Section A.3: Ports to other operating systems=t00000169
+3 Question A.3.1: What ports of PuTTY exist?=t00000170
+3 Question A.3.2: Is there a port to Unix?=t00000171
+3 Question A.3.3: What's the point of the Unix port? Unix has OpenSSH.=t00000172
+3 Question A.3.4: Will there be a port to Windows CE or PocketPC?=t00000173
+3 Question A.3.5: Is there a port to Windows 3.1?=t00000174
+3 Question A.3.6: Will there be a port to the Mac?=t00000175
+3 Question A.3.7: Will there be a port to EPOC?=t00000176
+2 Section A.4: Embedding PuTTY in other programs
+3 Section A.4: Embedding PuTTY in other programs=t00000177
+3 Question A.4.1: Is the SSH or Telnet code available as a DLL?=t00000178
+3 Question A.4.2: Is the SSH or Telnet code available as a Visual Basic component?=t00000179
+3 Question A.4.3: How can I use PuTTY to make an SSH connection from within another program?=t00000180
+2 Section A.5: Details of PuTTY's operation
+3 Section A.5: Details of PuTTY's operation=t00000181
+3 Question A.5.1: What terminal type does PuTTY use?=t00000182
+3 Question A.5.2: Where does PuTTY store its data?=t00000183
+2 Section A.6: HOWTO questions
+3 Section A.6: HOWTO questions=t00000184
+3 Question A.6.1: What login name / password should I use?=t00000185
+3 Question A.6.2: What commands can I type into my PuTTY terminal window?=t00000186
+3 Question A.6.3: How can I make PuTTY start up maximised?=t00000187
+3 Question A.6.4: How can I create a Windows shortcut to start a particular saved session directly?=t00000188
+3 Question A.6.5: How can I start an SSH session straight from the command line?=t00000189
+3 Question A.6.6: How do I copy and paste between PuTTY and other Windows applications?=t00000190
+3 Question A.6.7: How do I use all PuTTY's features (public keys, proxying, cipher selection, etc.) in PSCP, PSFTP and Plink?=t00000191
+3 Question A.6.8: How do I use PSCP.EXE? When I double-click it gives me a command prompt window which then closes instantly.=t00000192
+3 Question A.6.9: How do I use PSCP to copy a file whose name has spaces in?=t00000193
+2 Section A.7: Troubleshooting
+3 Section A.7: Troubleshooting=t00000194
+3 Question A.7.1: Why do I see �Incorrect MAC received on packet�?=t00000195
+3 Question A.7.2: Why do I see �Fatal: Protocol error: Expected control record� in PSCP?=t00000196
+3 Question A.7.3: I clicked on a colour in the Colours panel, and the colour didn't change in my terminal.=t00000197
+3 Question A.7.4: Plink on Windows 95 says it can't find WS2_32.DLL.=t00000198
+3 Question A.7.5: After trying to establish an SSH-2 connection, PuTTY says �Out of memory� and dies.=t00000199
+3 Question A.7.6: When attempting a file transfer, either PSCP or PSFTP says �Out of memory� and dies.=t00000200
+3 Question A.7.7: PSFTP transfers files much slower than PSCP.=t00000201
+3 Question A.7.8: When I run full-colour applications, I see areas of black space where colour ought to be, or vice versa.=t00000202
+3 Question A.7.9: When I change some terminal settings, nothing happens.=t00000203
+3 Question A.7.10: My PuTTY sessions unexpectedly close after they are idle for a while.=t00000204
+3 Question A.7.11: PuTTY's network connections time out too quickly when network connectivity is temporarily lost.=t00000205
+3 Question A.7.12: When I cat a binary file, I get �PuTTYPuTTYPuTTY� on my command line.=t00000206
+3 Question A.7.13: When I cat a binary file, my window title changes to a nonsense string.=t00000207
+3 Question A.7.14: My keyboard stops working once PuTTY displays the password prompt.=t00000208
+3 Question A.7.15: One or more function keys don't do what I expected in a server-side application.=t00000209
+3 Question A.7.16: Since my SSH server was upgraded to OpenSSH 3.1p1/3.4p1, I can no longer connect with PuTTY.=t00000210
+3 Question A.7.17: Why do I see �Couldn't load private key from ...�? Why can PuTTYgen load my key but not PuTTY?=t00000211
+3 Question A.7.18: When I'm connected to a Red Hat Linux 8.0 system, some characters don't display properly.=t00000212
+3 Question A.7.19: Since I upgraded to PuTTY 0.54, the scrollback has stopped working when I run screen.=t00000213
+3 Question A.7.20: Since I upgraded Windows XP to Service Pack 2, I can't use addresses like 127.0.0.2.=t00000214
+3 Question A.7.21: PSFTP commands seem to be missing a directory separator (slash).=t00000215
+3 Question A.7.22: Do you want to hear about �Software caused connection abort�?=t00000216
+3 Question A.7.23: My SSH-2 session locks up for a few seconds every so often.=t00000217
+3 Question A.7.24: PuTTY fails to start up. Windows claims that �the application configuration is incorrect�.=t00000218
+2 Section A.8: Security questions
+3 Section A.8: Security questions=t00000219
+3 Question A.8.1: Is it safe for me to download PuTTY and use it on a public PC?=t00000220
+3 Question A.8.2: What does PuTTY leave on a system? How can I clean up after it?=t00000221
+3 Question A.8.3: How come PuTTY now supports DSA, when the website used to say how insecure it was?=t00000222
+3 Question A.8.4: Couldn't Pageant use VirtualLock() to stop private keys being written to disk?=t00000223
+2 Section A.9: Administrative questions
+3 Section A.9: Administrative questions=t00000224
+3 Question A.9.1: Would you like me to register you a nicer domain name?=t00000225
+3 Question A.9.2: Would you like free web hosting for the PuTTY web site?=t00000226
+3 Question A.9.3: Would you link to my web site from the PuTTY web site?=t00000227
+3 Question A.9.4: Why don't you move PuTTY to SourceForge?=t00000228
+3 Question A.9.5: Why can't I subscribe to the putty-bugs mailing list?=t00000229
+3 Question A.9.6: If putty-bugs isn't a general-subscription mailing list, what is?=t00000230
+3 Question A.9.7: How can I donate to PuTTY development?=t00000231
+3 Question A.9.8: Can I have permission to put PuTTY on a cover disk / distribute it with other software / etc?=t00000232
+3 Question A.9.9: Can you sign an agreement indemnifying us against security problems in PuTTY?=t00000233
+3 Question A.9.10: Can you sign this form granting us permission to use/distribute PuTTY?=t00000234
+3 Question A.9.11: Can you write us a formal notice of permission to use PuTTY?=t00000235
+3 Question A.9.12: Can you sign anything for us?=t00000236
+3 Question A.9.13: If you won't sign anything, can you give us some sort of assurance that you won't make PuTTY closed-source in future?=t00000237
+3 Question A.9.14: Can you provide us with export control information / FIPS certification for PuTTY?=t00000238
+2 Section A.10: Miscellaneous questions
+3 Section A.10: Miscellaneous questions=t00000239
+3 Question A.10.1: Is PuTTY a port of OpenSSH, or based on OpenSSH?=t00000240
+3 Question A.10.2: Where can I buy silly putty?=t00000241
+3 Question A.10.3: What does �PuTTY� mean?=t00000242
+3 Question A.10.4: How do I pronounce �PuTTY�?=t00000243
+1 Appendix B: Feedback and bug reporting
+2 Appendix B: Feedback and bug reporting=t00000244
+2 Section B.1: General guidelines
+3 Section B.1: General guidelines=t00000245
+3 Section B.1.1: Sending large attachments=t00000246
+3 Section B.1.2: Other places to ask for help=t00000247
+1 Section B.2: Reporting bugs=t00000248
+1 Section B.3: Requesting extra features=t00000249
+1 Section B.4: Requesting features that have already been requested=t00000250
+1 Section B.5: Support requests=t00000251
+1 Section B.6: Web server administration=t00000252
+1 Section B.7: Asking permission for things=t00000253
+1 Section B.8: Mirroring the PuTTY web site=t00000254
+1 Section B.9: Praise and compliments=t00000255
+1 Section B.10: E-mail address=t00000256
+1 Appendix C: PuTTY Licence
+2 Appendix C: PuTTY Licence=t00000257
+1 Appendix D: PuTTY hacking guide
+2 Appendix D: PuTTY hacking guide=t00000258
+2 Section D.1: Cross-OS portability=t00000259
+2 Section D.2: Multiple backends treated equally=t00000260
+2 Section D.3: Multiple sessions per process on some platforms=t00000261
+2 Section D.4: C, not C++=t00000262
+2 Section D.5: Security-conscious coding=t00000263
+2 Section D.6: Independence of specific compiler=t00000264
+2 Section D.7: Small code size=t00000265
+2 Section D.8: Single-threaded code=t00000266
+2 Section D.9: Keystrokes sent to the server wherever possible=t00000267
+2 Section D.10: 640�480 friendliness in configuration panels=t00000268
+2 Section D.11: Automatically generated Makefiles=t00000269
+2 Section D.12: Coroutines in ssh.c=t00000270
+2 Section D.13: Single compilation of each source file=t00000271
+2 Section D.14: Do as we say, not as we do=t00000272
+1 Appendix E: PuTTY download keys and signatures
+2 Appendix E: PuTTY download keys and signatures=pgpfingerprints
+2 Section E.1: Public keys=t00000273
+2 Section E.2: Security details
+3 Section E.2: Security details=t00000274
+3 Section E.2.1: The Development Snapshots keys=t00000275
+3 Section E.2.2: The Releases keys=t00000276
+3 Section E.2.3: The Master Keys=t00000277
diff --git a/devtools/bin/putty/putty.exe b/devtools/bin/putty/putty.exe
new file mode 100644
index 0000000..38b49b6
--- /dev/null
+++ b/devtools/bin/putty/putty.exe
Binary files differ
diff --git a/devtools/bin/putty/putty.hlp b/devtools/bin/putty/putty.hlp
new file mode 100644
index 0000000..92cfc98
--- /dev/null
+++ b/devtools/bin/putty/putty.hlp
Binary files differ
diff --git a/devtools/bin/putty/puttycm.exe b/devtools/bin/putty/puttycm.exe
new file mode 100644
index 0000000..cfb5ee9
--- /dev/null
+++ b/devtools/bin/putty/puttycm.exe
Binary files differ
diff --git a/devtools/bin/putty/puttygen.exe b/devtools/bin/putty/puttygen.exe
new file mode 100644
index 0000000..c548873
--- /dev/null
+++ b/devtools/bin/putty/puttygen.exe
Binary files differ
diff --git a/devtools/bin/recentchanges.pl b/devtools/bin/recentchanges.pl
new file mode 100644
index 0000000..b0674b2
--- /dev/null
+++ b/devtools/bin/recentchanges.pl
@@ -0,0 +1,79 @@
+# usage: recentchanges.pl <changelist number> <filespec>
+#
+# Outputs changelist notes for changelists starting at the changelist number until now
+# that involve files in the filespec, grouped by user.
+#
+# Output file is recentchanges.txt, output to the current working dir.
+
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+
+# take in the revision number we want and the filespec to look at
+my $from_changelist = shift;
+my $branch = shift;
+
+if ( length($from_changelist) < 1 || length($branch) < 1 )
+{
+ die "usage: recentchanges.pl <'from' changelist number> <filespec>";
+}
+
+my $cmd = "p4 changes -l $branch\@$from_changelist,\@now";
+my @fstat = &RunCommand( $cmd );
+
+my $lastuser;
+my %changes;
+
+foreach $line ( @fstat )
+{
+ #if the line starts with "Change"
+ #then store the user, all lines after this are changes by this user
+ if ( $line =~ m/^Change/ )
+ {
+ my $data = 'Change (1234) on (date) by (name)@(clientspec)';
+
+ my @values = split(' ', $line);
+
+ @usersplit = split('@', $values[5]);
+
+ $lastuser = $usersplit[0];
+ }
+ else
+ {
+ #this is a change line, associate it with the user in our %changes hash
+
+ chomp($line);
+
+ # skip empty and 'merge from main' lines
+ if ( length($line) > 0 && $line !~ m/Merge from main/ )
+ {
+ #strip leading whitespace
+ $line =~ s/^\s+//;
+
+ # if the first char is not '-', add '- ' to the front
+ if ( $line !~ m/^-/ )
+ {
+ $line = "- $line";
+ }
+
+ push @{ $changes{$lastuser} }, $line;
+ }
+ }
+}
+
+chdir();
+open(OUTFILE, ">recentchanges.txt");
+
+foreach $user ( keys %changes )
+{
+ print "$user\n";
+ print OUTFILE "$user\n";
+ foreach $i ( 0 .. $#{ $changes{$user} } )
+ {
+ print "$changes{$user}[$i]\n";
+ print OUTFILE "$changes{$user}[$i]\n";
+ }
+ print "\n";
+ print OUTFILE "\n";
+}
+
+close(OUTFILE); \ No newline at end of file
diff --git a/devtools/bin/robocopy.exe b/devtools/bin/robocopy.exe
new file mode 100644
index 0000000..88b081b
--- /dev/null
+++ b/devtools/bin/robocopy.exe
Binary files differ
diff --git a/devtools/bin/run_unit_tests.pl b/devtools/bin/run_unit_tests.pl
new file mode 100644
index 0000000..4b70292
--- /dev/null
+++ b/devtools/bin/run_unit_tests.pl
@@ -0,0 +1,137 @@
+#! perl
+
+use File::Find;
+use Cwd;
+use File::Basename;
+use Getopt::Long;
+
+
+
+$last_errors="";
+$nosync = 0;
+$mail = 0;
+$daemon = 0;
+$mailto="cgreen";
+$mailfrom="autotest";
+$ignoremutex = 0;
+
+$result = GetOptions(
+ "nosync" => \$nosync,
+ "daemon" => \$daemon,
+ "mailto:s" => \$mailto,
+ "mailfrom:s" => \$mailfrom,
+ "ignoremutex" => \$ignoremutex,
+ "mail" => \$mail );
+
+$iter = 0;
+while( 1 )
+{
+ my $hasChange = 1;
+ my $mutex_held = 0;
+ unless($nosync)
+ {
+ # check for mutex held
+ unless( $ignoremutex || $nosync )
+ {
+ open(MUTEX,"p4 counters|") || die "cant' run p4";
+ while(<MUTEX>)
+ {
+ $mutex_held = 1 if ( /main_src_lock_\S+\s*=\s*1/);
+ }
+ close MUTEX;
+ }
+ unless( $mutex_held )
+ {
+ print STDERR "Syncing...\n";
+ system "p4 sync > sync.txt 2>&1";
+ open SYNC, "<sync.txt";
+ while( <SYNC> )
+ {
+ if( m/File\(s\) up-to-date/ )
+ {
+ $hasChange = 0;
+ }
+ print;
+ }
+ close SYNC;
+ }
+ }
+ if ( $mutex_held )
+ {
+ print STDERR "mutex held, waiting\n";
+ }
+ else
+ {
+ if( $hasChange || ($iter == 0 ) )
+ {
+ print "Running tests\n";
+ &RunUnitTests;
+ }
+ else
+ {
+ print "no changes\n";
+ }
+ $iter++;
+ last unless ($daemon);
+ }
+ sleep 30;
+}
+
+
+
+sub RunUnitTests
+{
+ $error_output ="";
+ find(\&Visitfile,".");
+ if ( length($error_output ) )
+ {
+ print STDERR "errors detected\n";
+ open CHANGES, "p4 changes -m 10 -s submitted //ValveGames/main/src/...|";
+ my @changes = <CHANGES>;
+ close CHANGES;
+
+ if ( $mail && ($error_output ne $last_errors ) )
+ {
+ use Net::SMTP;
+
+ $smtp = Net::SMTP->new('exchange2.valvesoftware.com');
+ $smtp->mail($mailfrom);
+ $smtp->to($mailto);
+
+ $smtp->data();
+ $smtp->datasend("To: $mailto\n");
+ $smtp->datasend("Subject: Errors from Unit tests\n");
+ $smtp->datasend($error_output);
+ $smtp->datasend("-" x 75);
+ $smtp->datasend("\nLAST 10 SUBMITS TO MAIN:\n");
+ $smtp->datasend(join("",@changes ) );
+ $smtp->dataend();
+ $smtp->quit;
+ }
+ }
+ $last_errors = $error_output;
+}
+
+sub Visitfile
+ {
+ local($_)= $File::Find::name;
+ next unless( -e "test_error_reporting.pl" );
+ if (/\.(pl|exe|bat)$/i)
+ {
+ unlink("errors.txt");
+ my $extension=$1;
+ $extension=~tr/A-Z/a-z/;
+ my $cmd;
+ $cmd="perl $_" if ( $extension eq "pl");
+ $cmd="$_" if ( $extension eq "exe");
+ $cmd="$_" if ( $extension eq "bat");
+ print STDERR "run $cmd: ",`$cmd`,"\n";
+ if (open(ERRIN,"errors.txt" ) )
+ {
+ local($/);
+ print STDERR "errors found!\n";
+ $error_output.="* Failed test: $cmd: ".<ERRIN>."\n";
+ close ERRIN;
+ }
+ }
+}
diff --git a/devtools/bin/sed.exe b/devtools/bin/sed.exe
new file mode 100644
index 0000000..db6416f
--- /dev/null
+++ b/devtools/bin/sed.exe
Binary files differ
diff --git a/devtools/bin/separate_vcprojs.py b/devtools/bin/separate_vcprojs.py
new file mode 100644
index 0000000..59c7608
--- /dev/null
+++ b/devtools/bin/separate_vcprojs.py
@@ -0,0 +1,27 @@
+
+
+from vsdotnetxmlparser import *
+
+
+#print f.GetAttribute( 'VisualStudioProject\\Configurations\\Configuration\\<2>Tool\\CommandLine' )
+
+
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug DoD|Win32", "Release DoD|Win32"], 'cl_dll\\client_dod.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug CounterStrike|Win32", "Release CounterStrike|Win32"], 'cl_dll\\client_cs.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug HL1|Win32", "Release HL1|Win32"], 'cl_dll\\client_hl1.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug HL2|Win32", "Release HL2|Win32"], 'cl_dll\\client_hl2.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug TF2|Win32", "Release TF2|Win32"], 'cl_dll\\client_tf2.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug SDK|Win32", "Release SDK|Win32"], 'cl_dll\\client_temp_sdk.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug HL2MP|Win32", "Release HL2MP|Win32"], 'cl_dll\\client_hl2mp.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'cl_dll\\client.vcproj' ), ["Debug Episodic HL2|Win32", "Release Episodic HL2|Win32"], 'cl_dll\\client_episodic.vcproj' )
+
+
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug DoD|Win32", "Release DoD|Win32"], 'dlls\\hl_dod.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug CounterStrike|Win32", "Release CounterStrike|Win32"], 'dlls\\hl_cs.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug HL1|Win32", "Release HL1|Win32"], 'dlls\\hl_hl1.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug HL2|Win32", "Release HL2|Win32"], 'dlls\\hl_hl2.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug TF2|Win32", "Release TF2|Win32"], 'dlls\\hl_tf2.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug SDK|Win32", "Release SDK|Win32"], 'dlls\\hl_temp_sdk.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug HL2MP|Win32", "Release HL2MP|Win32"], 'dlls\\hl_hl2mp.vcproj' )
+WriteSeparateVCProj( LoadVCProj( 'dlls\\hl.vcproj' ), ["Debug Episodic HL2|Win32", "Release Episodic HL2|Win32"], 'dlls\\hl_episodic.vcproj' )
+
diff --git a/devtools/bin/setup_vmpi.pl b/devtools/bin/setup_vmpi.pl
new file mode 100644
index 0000000..63fe12e
--- /dev/null
+++ b/devtools/bin/setup_vmpi.pl
@@ -0,0 +1,60 @@
+
+# This script sets up VMPI.
+
+$pathToExes = "..\\..\\..\\game\\bin"; # assuming we're under hl2\src\devtools\bin.
+my $baseNetworkPath = @ARGV[0];
+
+if ( $baseNetworkPath )
+{
+ my @filesToCopy = (
+ "tier0.dll",
+ "vstdlib.dll",
+ "vmpi_service.exe",
+ "vmpi_service_ui.exe",
+ "vmpi_service_install.exe",
+ "WaitAndRestart.exe",
+ "vmpi_transfer.exe",
+ "filesystem_stdio.dll" );
+
+ # Verify that the files we're interested in exist.
+ foreach $filename ( @filesToCopy )
+ {
+ my $fullFilename = "$pathToExes\\$filename";
+ if ( !( -e $fullFilename ) )
+ {
+ die "Missing $fullFilename.\n";
+ }
+ }
+
+ # Create the directories on the network.
+ if ( !( -e $baseNetworkPath ) )
+ {
+ mkdir $baseNetworkPath or die "Can't create directory: $baseNetworkPath";
+ }
+
+ if ( !( -e "$baseNetworkPath\\services" ) )
+ {
+ mkdir( "$baseNetworkPath\\services" ) or die "ERROR: Can't create directory: $baseNetworkPath\\services";
+ }
+
+
+ # Now copy all the files up.
+ foreach $filename ( @filesToCopy )
+ {
+ my $fullFilename = "$pathToExes\\$filename";
+ `"copy $fullFilename $baseNetworkPath\\services"`;
+ }
+
+ print "\n";
+ print "Finished installing VMPI into $baseNetworkPath.\n\n";
+ print "Have all available worker machines run:\n";
+ print " $baseNetworkPath\\services\\vmpi_service_install.exe\n";
+ print "to setup the worker service.\n";
+}
+else
+{
+ print "setup_vmpi.pl <UNC path to a server all machines can access>\n";
+ print "example: setup_vmpi.pl \\\\ftknox\\scratch\\vmpi\n";
+}
+
+
diff --git a/devtools/bin/shaderinfo.pl b/devtools/bin/shaderinfo.pl
new file mode 100644
index 0000000..57a8157
--- /dev/null
+++ b/devtools/bin/shaderinfo.pl
@@ -0,0 +1,36 @@
+#! perl
+
+my $fname=shift || die "format is shaderinfo blah.vcs";
+
+open(SHADER, $fname) || die "can't open $fname";
+binmode SHADER;
+
+read(SHADER,$header,20);
+($ver,$ntotal,$ndynamic,$flags,$centroidmask)=unpack("LLLLL",$header);
+
+#print "Version $ver total combos=$ntotal, num dynamic combos=$ndynamic,\n flags=$flags, centroid mask=$centroidmask\n";
+
+read(SHADER,$refsize,4);
+$refsize=unpack("L",$refsize);
+#print "Size of reference shader for diffing=$refsize\n";
+
+seek(SHADER,$refsize,1);
+
+$nskipped_combos=0;
+for(1..$ntotal)
+ {
+ read(SHADER,$combodata,8);
+ ($ofs,$combosize)=unpack("LL",$combodata);
+ if ( $ofs == 0xffffffff)
+ {
+ $nskipped_combos++;
+ }
+ else
+ {
+ }
+ }
+#print "$nskipped_combos skipped, for an actual total of ",$ntotal-$nskipped_combos,"\n";
+#print "Real to skipped ratio = ",($ntotal-$nskipped_combos)/$ntotal,"\n";
+# csv output - name, real combos, virtual combos, dynamic combos
+my $real_combos=$ntotal-$nskipped_combos;
+print "$fname,$real_combos,$ntotal,$ndynamic\n";
diff --git a/devtools/bin/signcode.exe b/devtools/bin/signcode.exe
new file mode 100644
index 0000000..c84c55f
--- /dev/null
+++ b/devtools/bin/signcode.exe
Binary files differ
diff --git a/devtools/bin/smtpmail.exe b/devtools/bin/smtpmail.exe
new file mode 100644
index 0000000..dd8ac1f
--- /dev/null
+++ b/devtools/bin/smtpmail.exe
Binary files differ
diff --git a/devtools/bin/splitdiff3.pl b/devtools/bin/splitdiff3.pl
new file mode 100644
index 0000000..ccba3a9
--- /dev/null
+++ b/devtools/bin/splitdiff3.pl
@@ -0,0 +1,54 @@
+$infilename = shift;
+$outfilename1 = shift;
+$outfilename2 = shift;
+open INPUT, $infilename || die;
+@input = <INPUT>;
+close INPUT;
+
+open MERGEDMINE, ">$outfilename1" || die;
+open MERGEDTHEIRS, ">$outfilename2" || die;
+
+for( $i = 0; $i < scalar( @input ); $i++ )
+{
+ $line = $input[$i];
+
+ if( $line =~ m/^(.*)<<<<<<</ )
+ {
+ $first = 1;
+ $second = 0;
+ print MERGEDMINE $1;
+ print MERGEDTHEIRS $1;
+ next;
+ }
+ # Make sure that we are in a split block so that comments with ======= don't mess us up.
+ if( $line =~ m/^(.*)=======$/ && $first == 1 )
+ {
+ $first = 0;
+ $second = 1;
+ print MERGEDMINE $1;
+ next;
+ }
+ if( $line =~ m/^(.*)>>>>>>>/ )
+ {
+ $first = $second = 0;
+ print MERGEDTHEIRS $1;
+ next;
+ }
+
+ if( $first )
+ {
+ print MERGEDMINE $line;
+ }
+ elsif( $second )
+ {
+ print MERGEDTHEIRS $line;
+ }
+ else
+ {
+ print MERGEDMINE $line;
+ print MERGEDTHEIRS $line;
+ }
+}
+
+close MERGEDMINE;
+close MERGEDTHEIRS;
diff --git a/devtools/bin/srgb_colorspace.pl b/devtools/bin/srgb_colorspace.pl
new file mode 100644
index 0000000..3c5404c
--- /dev/null
+++ b/devtools/bin/srgb_colorspace.pl
@@ -0,0 +1,451 @@
+
+#
+# Arguments parsing
+#
+
+local $script = $0;
+
+while ( 1 )
+{
+ local $arg = shift;
+ if ( $arg =~ /-catsrgb1/i )
+ { goto RUN_CAT_SRGB_1; }
+ if ( $arg =~ /-safecat/i )
+ { goto RUN_SAFE_CAT; }
+ if ( $arg =~ /-delaywrite/i )
+ { goto RUN_DELAY_WRITE; }
+ if ( $arg =~ /-processvmts/i )
+ { goto RUN_PROCESS_VMTS; }
+
+ # default mode - forward to processvmts:
+ # exit system( "dir" );
+ exit system( "dir /s /b *.vmt | perl $script -processvmts" );
+}
+
+
+
+
+RUN_CAT_SRGB_1:
+#
+# ----------- Adding "srgb 1" to options list --------
+#
+
+local $bAlreadyHasSrgb1 = 0;
+while ( <> )
+{
+ local $line = $_;
+ print $line;
+ $bAlreadyHasSrgb1 = 1 if $line =~ /srgb(.*)1/i;
+}
+print "\nsrgb 1\n" if !$bAlreadyHasSrgb1;
+exit 0;
+
+
+
+RUN_DELAY_WRITE:
+#
+# ----------- Delay write to a file (essentially delayed shell redirection) ----
+#
+local *fileptr;
+local $filename = shift;
+
+local @lines;
+while ( <> ) { push( @lines, $_ ); }
+
+open( fileptr, ">$filename" );
+foreach ( @lines ) { print fileptr $_ ; }
+close( fileptr );
+
+exit 0;
+
+
+
+RUN_SAFE_CAT:
+#
+# ----------- Cat of a non-existing file will succeed ----
+#
+local *fileptr;
+local $filename = shift;
+
+exit 1 if !open( fileptr, "<$filename" );
+while ( <fileptr> ) { print $_ ; }
+close( fileptr );
+
+exit 0;
+
+
+
+
+RUN_PROCESS_VMTS:
+#
+# ----------- Processing the list of vmts ------------
+#
+
+
+#
+# Lookup array of directories under which to search for
+# textures when resolving texture paths from vmt.
+#
+local @textureslookup = (
+# "u:/data/content/tf/",
+# "u:/data/content/portal/",
+
+# "u:/data/content/ep2/",
+# "u:/data/content/episodic/",
+ "u:/data/content/hl2/",
+);
+
+#
+# Mapping of shaders that require srgb conversion for
+# basetextures. Entries listed lowercase, mapped to 1.
+#
+local %srgbshaders = (
+ vertexlitgeneric => 1,
+ lightmappedgeneric => 1,
+ unlitgeneric => 1,
+ eyerefract => 1,
+ portalrefract => 1,
+ aftershock => 1,
+ sky => 1,
+ lightmappedreflective => 1,
+ portalstaticoverlay => 1,
+ particlesphere => 1,
+ shatteredglass => 1,
+ sprite => 1,
+ spritecard => 1,
+ teeth => 1,
+ treeleaf => 1,
+ vortwarp => 1,
+ water => 1,
+ windowimposter => 1,
+ worldtwotextureblend => 1,
+ worldvertexalpha => 1,
+);
+
+#
+# Mapping of variables that we will be looking for.
+#
+local %shadervarscheck = (
+ basetexture => 1,
+ basetexture2 => 1,
+ basetexture3 => 1,
+ basetexture4 => 1,
+ envmap => 1,
+ iris => 1,
+ ambientoccltexture => 1,
+ refracttinttexture => 1,
+ albedo => 1,
+ compress => 1,
+ stretch => 1,
+ emissiveblendbasetexture => 1,
+ emissiveblendtexture => 1,
+ fleshinteriortexture => 1,
+ fleshbordertexture1d => 1,
+ fleshsubsurfacetexture => 1,
+ fleshcubetexture => 1,
+ texture2 => 1,
+ hdrcompressedtexture => 1,
+ hdrcompressedtexture0 => 1,
+ hdrcompressedtexture1 => 1,
+ hdrcompressedtexture2 => 1,
+ portalcolortexture => 1,
+ monitorscreen => 1,
+ staticblendtexture => 1,
+ refracttexture => 1,
+ reflecttexture => 1,
+);
+
+#
+# After parsing the list of vmt files contains a map of
+# texture names as keys to the list of two elements:
+# [0]
+# 0: texture is non-srgb
+# 1: texture is srgb and needs conversion
+# -1: texture is ambiguous
+# [1]
+# list of vmts referring to the texture
+#
+local %textures2convert;
+
+
+#
+# Parse our list of vmt files
+# Generate the list with "dir /s /b *.vmt"
+#
+while ( <> )
+{
+
+ local $fname = $_;
+ $fname =~ s/^\s*(.*)\s*$/$1/;
+ $fname =~ s/\\/\//g;
+# print "-" . $fname . "-\n";
+
+ # Open the file
+ local *vmtfileptr;
+ open( vmtfileptr, "<$fname" ) || die;
+
+ local $line;
+ local $shadername;
+ local %basetexture;
+ local $basetexture_real;
+ local $basetexture_blacklisted = 0;
+
+ # Find shadername and textures
+ while ( $line = <vmtfileptr> )
+ {
+ $line =~ s/^\s*(.*)\s*$/$1/;
+ $line = lc( $line );
+
+ if ( $. == 1 )
+ {
+ $shadername = $line;
+ $shadername =~ s/\"//g;
+ }
+
+ while ( ( $varname, undef ) = each %shadervarscheck )
+ {
+ next if $line !~ /^\s*["]?\$$varname["]?\s+(.*)$/i;
+
+ $line = $1;
+ if ( $line =~ /^\"([^\"])*\"(.*)$/ ) {
+ $line =~ s/^\"([^\"]*)\"(.*)$/$1/;
+ } else {
+ $line =~ s/^(\S*)(.*)$/$1/;
+ }
+ $line =~ s/^\s*(.*)\s*$/$1/;
+ $line =~ s/\\/\//g;
+
+ next if $line =~ /^\_rt/i;
+
+ $basetexture{ $line } = 1;
+ $basetexture_real = $line if $varname =~ /^basetexture$/i;
+ last;
+ }
+
+ # blacklist stuff
+ $basetexture_blacklisted = 1 if $line =~ /^\s*["]?\$extractgreenalpha["]?\s*(.*)$/i;
+ print ">>> $fname blacklisted by >>> $line >>>\n" if $line =~ /^\s*["]?\$extractgreenalpha["]?\s*(.*)$/i;
+ }
+
+ delete $basetexture{ $basetexture_real } if $basetexture_blacklisted;
+ print ">>> blacklisted texture: $basetexture_real .\n" if $basetexture_blacklisted;
+ delete $basetexture{ "env_cubemap" };
+
+ close vmtfileptr;
+
+ # Print the shader and the base texture
+# print "\tshader = " . $shadername . "\n";
+# foreach ( keys %basetexture ) { print "\ttexture = " . $_ . "\n" };
+
+ # If the texture needs a conversion stick it into the map
+ local $isSrgb = 1; #--shadercheck--( exists $srgbshaders{ $shadername } ? 1 : 0 );
+
+ foreach ( keys %basetexture )
+ {
+ local $basetexture = $_;
+ if ( exists $textures2convert{ $basetexture } )
+ {
+ # Check for validity
+ $isSrgb = -1 if $textures2convert{ $basetexture }->[0] != $isSrgb;
+ }
+ else
+ {
+ $textures2convert{ $basetexture } = [ $isSrgb, [] ];
+ }
+
+ $textures2convert{ $basetexture }->[0] = $isSrgb;
+ push( @{ $textures2convert{ $basetexture }->[1] }, $fname );
+ }
+
+}
+
+
+#
+# Now walk over the accumulated textures and establish the srgb mapping
+#
+local @failedtextures;
+while ( ( $basetexture, $value ) = each %textures2convert )
+{
+
+ local $isSrgb = $value->[0];
+
+ if ( -1 == $isSrgb )
+ {
+ print "Warning: Ambiguity for ";
+ print "$basetexture from ";
+ foreach ( @{ $value->[1] } ) { print " $_"; };
+ print "!\n";
+ }
+
+ next if 1 != $isSrgb;
+
+ #
+ # Need to convert this texture
+ #
+ local $res = ConvertTexture( $basetexture );
+ push( @failedtextures, $basetexture ) if !$res;
+
+}
+
+# Dump failed textures
+if ( $#failedtextures > 0 )
+{
+ print "\n---- errors ----\n";
+ foreach ( @failedtextures )
+ {
+ local $basetexture = $_;
+ print "ERROR: $basetexture in ";
+ foreach ( @{ $textures2convert{ $basetexture }->[1] } ) { print " $_"; }
+ print ";\n";
+ }
+ print "---- end ----\n";
+}
+
+
+#
+# Converts a texture.
+# Returns 1 for txt, 2 for psd, 3 for newly created txt.
+# Returns 0 when nothing found.
+#
+sub ConvertTexture
+{
+
+ local $basetexture = shift;
+ local $result = 0;
+ print "-- $basetexture ... ";
+
+ foreach ( @textureslookup )
+ {
+ # Try to open the txt file
+ local $txpath = $_ . "materialsrc/" . $basetexture;
+ if ( -f "$txpath.txt" || -f "$txpath.tga" )
+ {
+ # Check it out
+ print "txt, p4 ... ";
+ `p4 edit "$txpath.txt" >nul 2>&1`;
+ `p4 lock "$txpath.txt" >nul 2>&1`;
+
+ `perl $script -safecat "$txpath.txt" | perl $script -catsrgb1 | perl $script -delaywrite "$txpath.txt"`;
+
+ `p4 add "$txpath.txt" >nul 2>&1` if -f "$txpath.txt";
+
+ # Also patch the VTF
+ $txpath =~ s,/content/,/game/,;
+ $txpath =~ s,/materialsrc/,/materials/,;
+ #PatchVtfFile( "$txpath.vtf" );
+
+ print "done ... ";
+ ++ $result;
+ }
+ if ( -f "$txpath.psd" )
+ {
+ # Check it out
+ print "psd, p4 ... ";
+ `p4 edit "$txpath.psd" >nul 2>&1`;
+ `p4 lock "$txpath.psd" >nul 2>&1`;
+
+ `psdinfo -read "$txpath.psd" | perl $script -catsrgb1 | psdinfo -write "$txpath.psd"`;
+
+ `p4 add "$txpath.psd" >nul 2>&1`;
+
+ # Also patch the VTF
+ $txpath =~ s,/content/,/game/,;
+ $txpath =~ s,/materialsrc/,/materials/,;
+ #PatchVtfFile( "$txpath.vtf" );
+
+ print "done ... ";
+ ++ $result;
+ }
+ }
+
+ foreach ( @textureslookup )
+ {
+ # Try to find the vtf file
+ local $txpath = $_ . "materials/" . $basetexture;
+ $txpath =~ s,/content/,/game/,i;
+ if ( -f "$txpath.vtf" )
+ {
+ if ( !$result )
+ {
+ # Create the text file then
+ print "src missing ... ";
+ $txpath =~ s,/game/,/content/,,i;
+ $txpath =~ s,/materials/,/materialsrc/,;
+
+ `p4 edit "$txpath.txt" >nul 2>&1`;
+ `p4 lock "$txpath.txt" >nul 2>&1`;
+
+ `perl $script -safecat "$txpath.txt" | perl $script -catsrgb1 | perl $script -delaywrite "$txpath.txt"`;
+
+ `p4 add "$txpath.txt" >nul 2>&1` if -f "$txpath.txt";
+
+ # Also patch the VTF
+ $txpath =~ s,/content/,/game/,;
+ $txpath =~ s,/materialsrc/,/materials/,;
+ }
+ PatchVtfFile( "$txpath.vtf" );
+
+ print "done ... ";
+ ++ $result;
+ }
+ }
+
+ if ( !$result )
+ {
+ print "ERROR: not found.\n";
+ }
+ else
+ {
+ print "ok.\n";
+ }
+ return $result;
+
+}
+
+exit 0;
+
+
+RUN_PATCH_VTF:
+#
+# ----------- Patch a VTF file --------
+#
+
+local $filename = shift;
+exit PatchVtfFile( $filename );
+
+sub PatchVtfFile
+{
+
+ local *fileptr;
+ local $filename = shift;
+ local $vtfFlags;
+
+ print "vtf, p4 ... ";
+ `p4 edit "$filename" >nul 2>&1`;
+ `p4 lock "$filename" >nul 2>&1`;
+
+ if ( !open( fileptr, "+<$filename" ) )
+ {
+ print "VTF missing ... ";
+ return 1;
+ }
+ binmode( fileptr );
+
+ seek( fileptr, 5 * 4, 0 );
+ read( fileptr, $vtfFlags, 4 );
+ $vtfFlags = unpack( "I", $vtfFlags );
+
+ # adding SRGB flag
+ $vtfFlags = $vtfFlags | 0x00000040; # mask or
+
+ seek( fileptr, 5 * 4, 0 );
+ print fileptr pack( "I", $vtfFlags );
+
+ close( fileptr );
+
+ print "vtf ok ... ";
+ return 0;
+
+}
+
+
diff --git a/devtools/bin/sscode.exe b/devtools/bin/sscode.exe
new file mode 100644
index 0000000..02bbb12
--- /dev/null
+++ b/devtools/bin/sscode.exe
Binary files differ
diff --git a/devtools/bin/steamlicense.txt b/devtools/bin/steamlicense.txt
new file mode 100644
index 0000000..cafa009
--- /dev/null
+++ b/devtools/bin/steamlicense.txt
@@ -0,0 +1,14 @@
+"Universe"
+{
+ "Public"
+ {
+ "Keys"
+ {
+ "CodeSignature"
+ {
+ "EncryptedPrivateKey" "6DA7F10F1B16A4012FFDE4BB09B857A8E3254573CDE9C0E91B12AEF01E8B1624FB8606058946D7D45AEE3C73EE69F6BC30CE703D25ACAC7C96DC5A87EB8DE6B2820AF5BDD5835E3BBA8C6BF679595323212E82E1BCEF57EAF06338084D3E0592F7B9A6F1BBE752947F72BC80C4A50493F7ECBA39FD73CF02BBEFF407BFCD9D956E0F337D4A68D82998979BD11409BC2A908580DB2DB3FECB96D1F95DB4C28E50900B0413D02D5073E669B54A090F5B19CA6B8A918B81CEC7EEF105E181235713B8BE293E149CF6F3CBA0AAC96B6017ECC51B00C31526F357CCD3F5889FC5895C3787399AE22CCA53B3AADEBC2D1FE3A6C1D628A0CF8D68808A08BDADA904555613B00889CD4A59F1B42FC88ACEE2C350CB4EA12B8A9CD3CE16A7E4832817D2A4C7B420AFC3BC3596513B4E3690508848AF55D83693E30199E97A42467B24585DEA5C6311D94BDE922FD7795B434D6ACCB544A04E290D3D944727D35C1A9478F33E82D3C6B97EE615FAFD0A82CCCB65EABD07580630FA6C654631695B5A0F1B9AD1E86297499E1DDC992D82D782B67AA809B8102780327A7DB4EB56FBA0FB5614D65E88A88BF322CE21DB5651CBABB0A01DAC97F78E1A92EA3CF5C2EA23A4921264137F2CCE3417857FD93347BD9C46EFD89E0016912BD7ED807252EEF43C88573EE3D66F345E55B185A9372D0A84DF574895EC4D2BF4572A1D1250D6BAB76C528B17957DA67201331C3CE20D255C2A01CA704E05F65FA9DFCF498B84F3E4E0C3D42F9D6FDAC0DD5708512F609FFF6290BEA8B00B758474E03391C475E376DD3A4586939E08454D293BF3D365D8472AF36125008630BE95339D893BF061E178CC46BC0BEB6D8420BF366E612718D4C30F39B6276DBE155F744A88663E2BAE53DC83B5BF60704BEAF9002EE1AB64E5E644"
+ "PublicKey" "30819D300D06092A864886F70D010101050003818B0030818702818100B1260881BDFE84463D88C6AB8DB914A2E593893C10508B8A5ABDF692E9A5419A3EDBAE86A052849983B75E3B425C18178B260003D857DF0B6505C6CF9C84F5859FCE3B63F1FB2D4818501F6C5FA4AD1430EEB081A74ABD74CD1F4AA1FCCA3B88DD0548AED34443CEB52444EAE9099AA4FE66B2E6224D02381C248025C7044079020111"
+ }
+ }
+ }
+}
diff --git a/devtools/bin/tee.exe b/devtools/bin/tee.exe
new file mode 100644
index 0000000..7b32b2a
--- /dev/null
+++ b/devtools/bin/tee.exe
Binary files differ
diff --git a/devtools/bin/test_binaries.exe b/devtools/bin/test_binaries.exe
new file mode 100644
index 0000000..0bd7b0c
--- /dev/null
+++ b/devtools/bin/test_binaries.exe
Binary files differ
diff --git a/devtools/bin/test_linux_compile.pl b/devtools/bin/test_linux_compile.pl
new file mode 100644
index 0000000..b04d2bb
--- /dev/null
+++ b/devtools/bin/test_linux_compile.pl
@@ -0,0 +1,64 @@
+#perl
+
+#! perl
+
+use Getopt::Long;
+
+$mail = 1;
+$mailto="cgreen";
+$mailfrom="cgreen\@valvesoftware.com";
+$branch="main";
+
+
+$result = GetOptions(
+ "nosync" => \$nosync,
+ "clean" => \$clean,
+ "mailto:s" => \$mailto,
+ "branch:s" => \$branch,
+ "mailfrom:s" => \$mailfrom,
+ "mail" => \$mail );
+
+print STDERR `p4 sync` unless ($nosync);
+print STDERR `perl devtools/bin/vpc2linuxmake.pl`;
+print STDERR `make clean` if ($clean);
+
+open(ERROROUT, "./linux_makeinorder.sh 2>&1 |" ) || die "can't create pipe to compile";
+while(<ERROROUT>)
+ {
+ my $iserror = /error:/;
+ $iserror = 1 if (/^.*:\d+:\d+:/);
+ $errtxt .= $_ if ($iserror );
+ print $_;
+ }
+if (length($errtxt) )
+ {
+ if ($mail)
+ {
+ use Net::SMTP;
+
+ open CHANGES, "p4 changes -m 10 -s submitted //ValveGames/$branch/src/...|";
+ my @changes = <CHANGES>;
+ close CHANGES;
+
+ $smtp = Net::SMTP->new('exchange2.valvesoftware.com');
+ $smtp->mail($mailfrom);
+ $smtp->to($mailto);
+
+ $smtp->data();
+ $smtp->datasend("To: $mailto\n");
+ $smtp->datasend("Subject: [$branch broken in linux]\n");
+ $smtp->datasend("\nThere are errors building $branch for linux.\nSome help is available at http://intranet.valvesoftware.com/wiki/index.php/Writing_code_that_is_compatible_between_gcc_and_visual_studio\n\n$errtxt");
+ $smtp->datasend("-" x 75);
+ $smtp->datasend("\nLAST 10 SUBMITS TO MAIN:\n");
+ $smtp->datasend(join("",@changes ) );
+ $smtp->dataend();
+ $smtp->quit;
+ }
+ else
+ {
+ print STDERR "*****ERRORS****\n$errtxt\n";
+ }
+ }
+
+
+
diff --git a/devtools/bin/timeprecise.exe b/devtools/bin/timeprecise.exe
new file mode 100644
index 0000000..93371e0
--- /dev/null
+++ b/devtools/bin/timeprecise.exe
Binary files differ
diff --git a/devtools/bin/timethis.exe b/devtools/bin/timethis.exe
new file mode 100644
index 0000000..45b5179
--- /dev/null
+++ b/devtools/bin/timethis.exe
Binary files differ
diff --git a/devtools/bin/uniqexe.exe b/devtools/bin/uniqexe.exe
new file mode 100644
index 0000000..4164b29
--- /dev/null
+++ b/devtools/bin/uniqexe.exe
Binary files differ
diff --git a/devtools/bin/uniqifylist.pl b/devtools/bin/uniqifylist.pl
new file mode 100644
index 0000000..1c3fd9c
--- /dev/null
+++ b/devtools/bin/uniqifylist.pl
@@ -0,0 +1,6 @@
+foreach $_ (sort <> )
+{
+ next if( defined( $prevline ) && $_ eq $prevline );
+ $prevline = $_;
+ print;
+}
diff --git a/devtools/bin/updatecef.bat b/devtools/bin/updatecef.bat
new file mode 100644
index 0000000..5e296f9
--- /dev/null
+++ b/devtools/bin/updatecef.bat
@@ -0,0 +1,14 @@
+rem script to update libcef from Steam/main to this project
+rem brings over all the dll's and import libraries and support libraries plus updates the header files
+rem run this, then resolve the changelist in perforce and submit
+SET SRCDIR=//Steam/main
+SET PUBLISH_SCRIPT=//thirdpartycode/nonredist/chromeemb/dev/publish_cef_to_steam.py
+
+rem Resolve this to an absolute path
+pushd %~dp0..\..\..
+SET DSTDIR=%CD%
+popd
+
+p4 print -q -o "%TMP%\publish.py" %PUBLISH_SCRIPT%
+python "%TMP%\publish.py" --game=tf2 "%DSTDIR%" "%SRCDIR%"
+p4 merge %SRCDIR%/client/bin/icudt.dll %DSTDIR%/game/bin/icudt.dll
diff --git a/devtools/bin/updatecef.sh b/devtools/bin/updatecef.sh
new file mode 100644
index 0000000..27ced7b
--- /dev/null
+++ b/devtools/bin/updatecef.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Bash script to update libcef from Steam/main to this project
+# brings over all the dll's and import libraries and support libraries plus updates the header files
+# run this, then resolve the changelist in perforce and submit
+
+SRCDIR=//Steam/main
+PUBLISH_SCRIPT=//thirdpartycode/nonredist/chromeemb/dev/publish_cef_to_steam.py
+DSTDIR="$(cd $(dirname "$0")/../../.. && echo $PWD)"
+
+p4 print -q $PUBLISH_SCRIPT | python - --game=tf2 "$DSTDIR" "$SRCDIR"
+p4 merge $SRCDIR/client/bin/icudt.dll $DSTDIR/game/bin/icudt.dll
diff --git a/devtools/bin/updateshaders.pl b/devtools/bin/updateshaders.pl
new file mode 100644
index 0000000..93f57ff
--- /dev/null
+++ b/devtools/bin/updateshaders.pl
@@ -0,0 +1,305 @@
+use String::CRC32;
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+
+$dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0;
+
+$depnum = 0;
+$baseSourceDir = ".";
+
+my %dep;
+
+sub GetAsmShaderDependencies_R
+{
+ local( $shadername ) = shift;
+ local( *SHADER );
+
+ open SHADER, "<$shadername";
+ while( <SHADER> )
+ {
+ if( m/^\s*\#\s*include\s+\"(.*)\"/ )
+ {
+ # make sure it isn't in there already.
+ if( !defined( $dep{$1} ) )
+ {
+ $dep{$1} = 1;
+ GetAsmShaderDependencies_R( $1 );
+ }
+ }
+ }
+ close SHADER;
+}
+
+sub GetAsmShaderDependencies
+{
+ local( $shadername ) = shift;
+ undef %dep;
+ GetAsmShaderDependencies_R( $shadername );
+# local( $i );
+# foreach $i ( keys( %dep ) )
+# {
+# print "$shadername depends on $i\n";
+# }
+ return keys( %dep );
+}
+
+sub GetShaderType
+{
+ my $shadername = shift;
+ my $shadertype;
+ if( $shadername =~ m/\.vsh/i )
+ {
+ $shadertype = "vsh";
+ }
+ elsif( $shadername =~ m/\.psh/i )
+ {
+ $shadertype = "psh";
+ }
+ elsif( $shadername =~ m/\.fxc/i )
+ {
+ $shadertype = "fxc";
+ }
+ else
+ {
+ die;
+ }
+ return $shadertype;
+}
+
+sub GetShaderSrc
+{
+ my $shadername = shift;
+ if ( $shadername =~ m/^(.*)-----/i )
+ {
+ return $1;
+ }
+ else
+ {
+ return $shadername;
+ }
+}
+
+sub GetShaderBase
+{
+ my $shadername = shift;
+ if ( $shadername =~ m/-----(.*)$/i )
+ {
+ return $1;
+ }
+ else
+ {
+ my $shadertype = &GetShaderType( $shadername );
+ $shadername =~ s/\.$shadertype//i;
+ return $shadername;
+ }
+}
+
+sub DoAsmShader
+{
+ my $argstring = shift;
+ my $shadername = &GetShaderSrc( $argstring );
+ my $shaderbase = &GetShaderBase( $argstring );
+ my $shadertype = &GetShaderType( $argstring );
+ my $incfile = "";
+ if( $shadertype eq "fxc" || $shadertype eq "vsh" )
+ {
+ $incfile = $shadertype . "tmp9" . $g_tmpfolder . "\\$shaderbase.inc ";
+ }
+
+ my $vcsfile = $shaderbase . $g_vcsext;
+ my $bWillCompileVcs = 1;
+ if( ( $shadertype eq "fxc") && $dynamic_compile )
+ {
+ $bWillCompileVcs = 0;
+ }
+ if( $shadercrcpass{$argstring} )
+ {
+ $bWillCompileVcs = 0;
+ }
+
+ if( $bWillCompileVcs )
+ {
+ &output_makefile_line( $incfile . "shaders\\$shadertype\\$vcsfile: $shadername @dep\n") ;
+ }
+ else
+ {
+ # psh files don't need a rule at this point since they don't have inc files and we aren't compiling a vcs.
+ if( $shadertype eq "fxc" || $shadertype eq "vsh" )
+ {
+ &output_makefile_line( $incfile . ": $shadername @dep\n") ;
+ }
+ }
+
+
+ my $x360switch = "";
+ my $moreswitches = "";
+ if( !$bWillCompileVcs && $shadertype eq "fxc" )
+ {
+ $moreswitches .= "-novcs ";
+ }
+ if( $g_x360 )
+ {
+ $x360switch = "-x360";
+
+ if( $bWillCompileVcs && ( $shaderbase =~ m/_ps20$/i ) )
+ {
+ $moreswitches .= "-novcs ";
+ $bWillCompileVcs = 0;
+ }
+ }
+
+ # if we are psh and we are compiling the vcs, we don't need this rule.
+ if( !( $shadertype eq "psh" && !$bWillCompileVcs ) )
+ {
+ &output_makefile_line( "\tperl $g_SourceDir\\devtools\\bin\\" . $shadertype . "_prep.pl $moreswitches $x360switch -source \"$g_SourceDir\" $argstring\n") ;
+ }
+
+ if( $bWillCompileVcs )
+ {
+ &output_makefile_line( "\techo $shadername>> filestocopy.txt\n") ;
+ my $dep;
+ foreach $dep( @dep )
+ {
+ &output_makefile_line( "\techo $dep>> filestocopy.txt\n") ;
+ }
+ }
+ &output_makefile_line( "\n") ;
+}
+
+if( scalar( @ARGV ) == 0 )
+{
+ die "Usage updateshaders.pl shaderprojectbasename\n\tie: updateshaders.pl stdshaders_dx6\n";
+}
+
+$g_x360 = 0;
+$g_tmpfolder = "_tmp";
+$g_vcsext = ".vcs";
+
+while( 1 )
+{
+ $inputbase = shift;
+
+ if( $inputbase =~ m/-source/ )
+ {
+ $g_SourceDir = shift;
+ }
+ elsif( $inputbase =~ m/-x360/ )
+ {
+ $g_x360 = 1;
+ $g_tmpfolder = "_360_tmp";
+ $g_vcsext = ".360.vcs";
+ }
+ elsif( $inputbase =~ m/-execute/ )
+ {
+ $g_execute = 1;
+ }
+ elsif( $inputbase =~ m/-nv3x/ )
+ {
+ $nv3x = 1;
+ }
+ else
+ {
+ last;
+ }
+}
+
+my @srcfiles = &LoadShaderListFile( $inputbase );
+
+open MAKEFILE, ">makefile\.$inputbase";
+open COPYFILE, ">makefile\.$inputbase\.copy";
+open INCLIST, ">inclist.txt";
+open VCSLIST, ">vcslist.txt";
+
+# make a default dependency that depends on all of the shaders.
+&output_makefile_line( "default: ") ;
+foreach $shader ( @srcfiles )
+{
+ my $shadertype = &GetShaderType( $shader );
+ my $shaderbase = &GetShaderBase( $shader );
+ my $shadersrc = &GetShaderSrc( $shader );
+ if( $shadertype eq "fxc" || $shadertype eq "vsh" )
+ {
+ # We only generate inc files for fxc and vsh files.
+ my $incFileName = "$shadertype" . "tmp9" . $g_tmpfolder . "\\" . $shaderbase . "\.inc";
+ &output_makefile_line( " $incFileName" );
+ &output_inclist_line( "$incFileName\n" );
+ }
+
+ my $vcsfile = $shaderbase . $g_vcsext;
+
+ my $compilevcs = 1;
+ if( $shadertype eq "fxc" && $dynamic_compile )
+ {
+ $compilevcs = 0;
+ }
+ if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) )
+ {
+ $compilevcs = 0;
+ }
+ if( $compilevcs )
+ {
+ my $vcsFileName = "..\\..\\..\\game\\hl2\\shaders\\$shadertype\\$shaderbase" . $g_vcsext;
+ # We want to check for perforce operations even if the crc matches in the event that a file has been manually reverted and needs to be checked out again.
+ &output_vcslist_line( "$vcsFileName\n" );
+ $shadercrcpass{$shader} = &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 0 );
+ if( $shadercrcpass{$shader} )
+ {
+ $compilevcs = 0;
+ }
+ }
+ if( $compilevcs )
+ {
+ &output_makefile_line( " shaders\\$shadertype\\$vcsfile" );
+ # emit a list of vcs files to copy to the target since we want to build them.
+ &output_copyfile_line( GetShaderSrc($shader) . "-----" . GetShaderBase($shader) . "\n" );
+ }
+}
+&output_makefile_line( "\n\n") ;
+
+# Insert all of our vertex shaders and depencencies
+$lastshader = "";
+foreach $shader ( @srcfiles )
+{
+ my $currentshader = &GetShaderSrc( $shader );
+ if ( $lastshader ne $currentshader )
+ {
+ $lastshader = $currentshader;
+ @dep = &GetAsmShaderDependencies( $lastshader );
+ }
+ &DoAsmShader( $shader );
+}
+close VCSLIST;
+close INCLIST;
+close COPYFILE;
+close MAKEFILE;
+
+# nuke the copyfile if it is zero length
+if( ( stat "makefile\.$inputbase\.copy" )[7] == 0 )
+{
+ unlink "makefile\.$inputbase\.copy";
+}
+
+sub output_makefile_line
+{
+ local ($_)=@_;
+ print MAKEFILE $_;
+}
+
+sub output_copyfile_line
+{
+ local ($_)=@_;
+ print COPYFILE $_;
+}
+
+sub output_vcslist_line
+{
+ local ($_)=@_;
+ print VCSLIST $_;
+}
+
+sub output_inclist_line
+{
+ local ($_)=@_;
+ print INCLIST $_;
+}
+
diff --git a/devtools/bin/valve_p4_create_changelist.cmd b/devtools/bin/valve_p4_create_changelist.cmd
new file mode 100644
index 0000000..2fe364a
--- /dev/null
+++ b/devtools/bin/valve_p4_create_changelist.cmd
@@ -0,0 +1,65 @@
+@echo off
+
+:: // This will make all new env variables local to this script
+setlocal
+
+:: // Make sure we have 2 args
+if .%2.==.. (
+ echo *** [valve_p4_create_changelist] Error calling command! No file or changelist specified for checkout! Usage: valve_p4_create_changelist.cmd fileOrPath "Description"
+ endlocal
+ exit /b 1
+)
+
+:: // Get file info
+set valveTmpPathOnly="%~d1%~p1"
+if "%valveTmpPathOnly%"=="" (
+ echo *** [valve_p4_create_changelist] Error! Can't parse file or path "%1"!
+ endlocal
+ exit /b 1
+)
+
+:: // Change directories so that the p4 set commands give use useful data
+pushd %valveTmpPathOnly%
+
+:: // Find user
+for /f "tokens=2 delims== " %%A in ('p4 set ^| find /i "P4USER="') do set valveP4User=%%A
+if "%valveP4User%"=="" goto RegularCheckout
+rem //echo User="%valveP4User%"
+
+:: // Find client
+for /f "tokens=2 delims== " %%A in ('p4 set ^| find /i "P4CLIENT="') do set valveP4Client=%%A
+if "%valveP4Client%"=="" goto RegularCheckout
+rem //echo Client="%valveP4Client%"
+
+:: // Search for existing changelist that matches command line arg
+set valveP4ChangelistName=%2%
+set valveP4ChangelistName=%valveP4ChangelistName:~1,-1%
+for /f "tokens=2 delims= " %%A in ('p4 changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
+if NOT "%valveP4ChangelistNumber%"=="" goto HaveChangelist
+
+:: // We didn't find a matching changelist but we did figure enough out to create a new changelist
+rem //echo Creating New Changelist
+for /f "tokens=2 delims= " %%A in ('^( echo Change: new ^& echo Client: %valveP4Client% ^& echo User: %valveP4User% ^& echo Status: new ^& echo Description: %valveP4ChangelistName%^&echo.^) ^| p4 change -i') do set valveP4ChangelistNumberJustCreated=%%A
+if "%valveP4ChangelistNumberJustCreated%"=="" goto RegularCheckout
+
+:: // Now search for the changelist number even though we already have it to try to clean up after the race condition when it's hit
+:: // This way, if more than one changelist is created in parallel, this will hopefully cause them to be checked out into the same changelist and the empty one deleted
+for /f "tokens=2 delims= " %%A in ('p4 changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
+if "%valveP4ChangelistNumber%"=="" goto RegularCheckout
+
+if NOT "%valveP4ChangelistNumber%"=="%valveP4ChangelistNumberJustCreated%" p4 change -d %valveP4ChangelistNumberJustCreated% 2>&1 >nul
+
+:: // We have a changelist number
+:HaveChangelist
+echo %valveP4ChangelistNumber%
+goto End
+
+:: // Can't find or create the changelist, output 0
+:RegularCheckout
+echo 0
+goto End
+
+:End
+popd
+endlocal
+exit /b 0
diff --git a/devtools/bin/valve_p4_edit_to_changelist.cmd b/devtools/bin/valve_p4_edit_to_changelist.cmd
new file mode 100644
index 0000000..5c8c2ea
--- /dev/null
+++ b/devtools/bin/valve_p4_edit_to_changelist.cmd
@@ -0,0 +1,99 @@
+@echo off
+
+:: // This will make all new env variables local to this script
+setlocal
+
+:: // If called with the start command, we need to exit, so also make sure you pass EXIT as the third param!
+:: // Also, if you modify this script, make sure that endlocal and exit are within ()'s so valveExitArg works!
+:: // Type 'help set' at a command prompt if you don't understand why.
+if NOT "%3"=="EXIT" set valveExitArg=/b
+
+:: // Make sure we have 2 args
+if .%2.==.. (
+ echo *** [valve_p4_edit_to_changelist] Error calling command! No file or changelist specified for checkout! Usage: valve_p4_edit_to_changelist.cmd file "Description" [EXIT]
+ endlocal
+ exit %valveExitArg% 1
+)
+
+:: // Get file info
+set valveTmpFileName="%~n1%~x1"
+set valveTmpFullFilePath="%~f1"
+set valveTmpPathOnly="%~d1%~p1"
+
+if "%valveTmpFileName%"=="" (
+ echo *** [valve_p4_edit_to_changelist] Error! Can't parse filename "%1"!
+ endlocal
+ exit %valveExitArg% 1
+)
+
+if "%valveTmpFullFilePath%"=="" (
+ echo *** [valve_p4_edit_to_changelist] Error! Can't parse filename "%1"!
+ endlocal
+ exit %valveExitArg% 1
+)
+
+if "%valveTmpPathOnly%"=="" (
+ echo *** [valve_p4_edit_to_changelist] Error! Can't parse filename "%1"!
+ endlocal
+ exit %valveExitArg% 1
+)
+
+:: // Change directories so that the p4 set commands give use useful data
+pushd %valveTmpPathOnly%
+
+:: // Find user
+for /f "tokens=2 delims== " %%A in ('p4 set ^| find /i "P4USER="') do set valveP4User=%%A
+if "%valveP4User%"=="" goto RegularCheckout
+rem //echo User="%valveP4User%"
+
+:: // Find client
+for /f "tokens=2 delims== " %%A in ('p4 set ^| find /i "P4CLIENT="') do set valveP4Client=%%A
+if "%valveP4Client%"=="" goto RegularCheckout
+rem //echo Client="%valveP4Client%"
+
+:: // Search for existing changelist that matches command line arg
+set valveP4ChangelistName=%2%
+set valveP4ChangelistName=%valveP4ChangelistName:~1,-1%
+for /f "tokens=2 delims= " %%A in ('p4 changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
+if NOT "%valveP4ChangelistNumber%"=="" goto HaveChangelist
+
+:: // We didn't find a matching changelist but we did figure enough out to create a new changelist
+rem //echo Creating New Changelist
+for /f "tokens=2 delims= " %%A in ('^( echo Change: new ^& echo Client: %valveP4Client% ^& echo User: %valveP4User% ^& echo Status: new ^& echo Description: %valveP4ChangelistName%^&echo.^) ^| p4 change -i') do set valveP4ChangelistNumberJustCreated=%%A
+if "%valveP4ChangelistNumberJustCreated%"=="" goto RegularCheckout
+
+:: // Now search for the changelist number even though we already have it to try to clean up after the race condition when it's hit
+:: // This way, if more than one changelist is created in parallel, this will hopefully cause them to be checked out into the same changelist and the empty one deleted
+for /f "tokens=2 delims= " %%A in ('p4 changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
+if "%valveP4ChangelistNumber%"=="" goto RegularCheckout
+
+if NOT "%valveP4ChangelistNumber%"=="%valveP4ChangelistNumberJustCreated%" p4 change -d %valveP4ChangelistNumberJustCreated% 2>&1 >nul
+
+:: // We have a changelist number
+:HaveChangelist
+set valveP4ChangelistArg=-c %valveP4ChangelistNumber%
+rem //echo valveP4ChangelistArg="%valveP4ChangelistArg%"
+rem //echo ChangelistNumber="%valveP4ChangelistNumber%"
+rem //echo ChangelistName="%valveP4ChangelistName%"
+
+:: // Check the file out
+:RegularCheckout
+SET SEDPATH=%~dp0sed.exe
+rem The sed command replaces '//' with the empty string and replaces '...' with '---'
+rem This is necessary so that VS will not interpret "//source2/main" or "... source2/main" as
+rem a path. Interpreting it as a path means that pressing F8 in the VS error window will stop on
+rem these output lines, which is a nuisance when looking for real errors and warnings, and it means
+rem that VS will try to open \\source2\main\... which will often cause a 2-3 second hang!
+if "%VALVE_WAIT_ON_P4%"=="" (
+ p4 edit %valveP4ChangelistArg% %valveTmpFullFilePath% 2>&1 | %SEDPATH% -e s!//!! -e s!\.\.\.!---! | find /v /i "- currently opened for edit" | find /v /i "- also opened by" | find /v /i "- file(s) not on client" | find /v /i "- can't change from"
+) ELSE (
+ :: // Filter out largely benign messages unless we're explicitly waiting on p4 results a la buildbot
+ p4 edit %valveP4ChangelistArg% %valveTmpFullFilePath% 2>&1 | %SEDPATH% -e s!//!! -e s!\.\.\.!---! | find /v /i "- also opened by"
+)
+
+goto End
+
+:End
+popd
+( endlocal
+ exit %valveExitArg% 0 )
diff --git a/devtools/bin/valve_perl_helpers.pl b/devtools/bin/valve_perl_helpers.pl
new file mode 100644
index 0000000..9257767
--- /dev/null
+++ b/devtools/bin/valve_perl_helpers.pl
@@ -0,0 +1,558 @@
+sub BackToForwardSlash
+{
+ my( $path ) = shift;
+ $path =~ s,\\,/,g;
+ return $path;
+}
+
+sub RemoveFileName
+{
+ my( $in ) = shift;
+ $in = &BackToForwardSlash( $in );
+ $in =~ s,/[^/]*$,,;
+ return $in;
+}
+
+sub RemovePath
+{
+ my( $in ) = shift;
+ $in = &BackToForwardSlash( $in );
+ $in =~ s,^(.*)/([^/]*)$,$2,;
+ return $in;
+}
+
+sub MakeDirHier
+{
+ my( $in ) = shift;
+# print "MakeDirHier( $in )\n";
+ $in = &BackToForwardSlash( $in );
+ my( @path );
+ while( $in =~ m,/, ) # while $in still has a slash
+ {
+ my( $end ) = &RemovePath( $in );
+ push @path, $end;
+# print $in . "\n";
+ $in = &RemoveFileName( $in );
+ }
+ my( $i );
+ my( $numelems ) = scalar( @path );
+ my( $curpath );
+ for( $i = $numelems - 1; $i >= 0; $i-- )
+ {
+ $curpath .= "/" . $path[$i];
+ my( $dir ) = $in . $curpath;
+ if( !stat $dir )
+ {
+# print "mkdir $dir\n";
+ mkdir $dir, 0777;
+ }
+ }
+}
+
+sub FileExists
+{
+ my $filename = shift;
+ my @statresult = stat $filename;
+ my $iswritable = @statresult != 0;
+ return $iswritable;
+}
+
+sub MakeFileWritable
+{
+ my $filename = shift;
+ if ( &FileExists( $filename ) )
+ {
+ chmod 0666, $filename || die;
+ }
+}
+
+sub MakeFileReadOnly
+{
+ my $filename = shift;
+ chmod 0444, $filename || die;
+}
+
+# Run a command and get stdout and stderr to an array
+sub RunCommand
+{
+ my $cmd = shift;
+# print STDERR "command: $cmd\n";
+ system "$cmd > cmdout.txt 2>&1" || die;
+ local( *FILE );
+ open FILE, "<cmdout.txt" || die;
+ my @output = <FILE>;
+# print STDERR "command output: @output\n";
+ close FILE;
+ unlink "cmdout.txt" || die;
+ return @output;
+}
+
+sub PerforceEditOrAdd
+{
+ return;
+ my $filename = shift;
+ my $changelistarg = shift;
+
+ # Is the file on the client?
+ my $cmd = "p4 fstat \"$filename\"";
+ my @p4output = &RunCommand( $cmd );
+ my $p4output = join "", @p4output;
+ if( $p4output =~ m/no such file/ )
+ {
+ # not on client. . add
+ my $cmd = "p4 add $changelistarg $filename";
+ my @p4output = &RunCommand( $cmd );
+ my $p4output = join "", @p4output;
+ if( $p4output =~ m/opened for add/ )
+ {
+ print $p4output;
+ return;
+ }
+ print "ERROR: $p4output";
+ return;
+ }
+
+ # The file is known to be on the client at this point.
+
+ # Is it open for edit?
+ if( $p4output =~ m/action edit/ )
+ {
+ # Is is open for edit, let's see if it's still different.
+ # check for opened files that are not different from the revision in the depot.
+ my $cmd = "p4 diff -sr \"$filename\"";
+ my @p4output = &RunCommand( $cmd );
+ my $outputstring = join "", @p4output;
+ # check for empty string
+ if( !( $outputstring =~ m/^\s*$/ ) )
+ {
+ my $cmd = "p4 revert \"$filename\"";
+ my @p4output = &RunCommand( $cmd );
+ my $outputstring = join "", @p4output;
+ print $outputstring;
+ return;
+ }
+ }
+
+ # check for unopened files that are different from the revision in the depot.
+ my $cmd = "p4 diff -se \"$filename\"";
+ my @p4output = &RunCommand( $cmd );
+ my $outputstring = join "", @p4output;
+ # check for empty string
+ if( $outputstring =~ m/^\s*$/ )
+ {
+ &MakeFileReadOnly( $filename );
+ return;
+ }
+
+ # We need to edit the file since it is known to be different here.
+ my $cmd = "p4 edit $changelistarg \"$filename\"";
+ my @p4output = &RunCommand( $cmd );
+
+ my $line;
+ foreach $line ( @p4output )
+ {
+ if( $line =~ m/not on client/ )
+ {
+ #print "notonclient...";
+ print "ERROR: @p4output\n";
+ return;
+ }
+ if( $line =~ m/currently opened for edit/ )
+ {
+ return;
+ }
+ if( $line =~ m/opened for edit/ )
+ {
+ print $line;
+ }
+ }
+}
+
+sub FileIsWritable
+{
+ local( $filename ) = shift;
+ local( @statresult ) = stat $filename;
+ local( $mode, $iswritable );
+ $mode = oct( $statresult[2] );
+ $iswritable = ( $mode & 2 ) != 0;
+ return $iswritable;
+}
+
+sub TouchFile
+{
+ my $filename = shift;
+ if( !&FileExists( $filename ) )
+ {
+ if( !open FILE, ">$filename" )
+ {
+ die;
+ }
+ close FILE;
+ }
+ my $now = time;
+ local( *FILE );
+ utime $now, $now, $filename;
+}
+
+sub FileExistsInPerforce
+{
+ my $filename = shift;
+ my @output = &RunCommand( "p4 fstat $filename" );
+ my $line;
+ foreach $line (@output)
+ {
+ if( $line =~ m/no such file/ )
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+sub PerforceWriteFile
+{
+ my $filename = shift;
+ my $filecontents = shift;
+# my $changelistname = shift;
+
+ # Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
+# my $changelistnumber = `valve_p4_create_changelist.cmd . \"$changelistname\"`;
+ # Get rid of the newline
+# $changelistnumber =~ s/\n//g;
+
+# my $changelistarg = "";
+# if( $changelistnumber != 0 )
+# {
+# $changelistarg = "-c $changelistnumber"
+# }
+
+ # Make the target vcs writable if it exists
+ MakeFileWritable( $filename );
+
+ # Write the file.
+ local( *FP );
+ open FP, ">$filename";
+ print FP $filecontents;
+ close FP;
+
+ # Do whatever needs to happen with perforce for this file.
+# &PerforceEditOrAdd( $filename, $changelistarg );
+}
+
+sub WriteFile
+{
+ my $filename = shift;
+ my $filecontents = shift;
+
+ # Make the target vcs writable if it exists
+ MakeFileWritable( $filename );
+
+ # Write the file.
+ local( *FP );
+ open FP, ">$filename";
+ print FP $filecontents;
+ close FP;
+}
+
+sub PrintCleanPerforceOutput
+{
+ my $line;
+ while( $line = shift )
+ {
+ if( $line =~ m/currently opened/i )
+ {
+ next;
+ }
+ if( $line =~ m/already opened for edit/i )
+ {
+ next;
+ }
+ if( $line =~ m/also opened/i )
+ {
+ next;
+ }
+ if( $line =~ m/add of existing file/i )
+ {
+ next;
+ }
+ print $line;
+ }
+}
+
+# HACK!!!! Need to pass something in to do this rather than hard coding.
+sub NormalizePerforceFilename
+{
+ my $line = shift;
+
+ # remove newlines.
+ $line =~ s/\n//;
+ # downcase.
+ $line =~ tr/[A-Z]/[a-z]/;
+ # backslash to forwardslash
+ $line =~ s,\\,/,g;
+
+ # for inc files HACK!
+ $line =~ s/^.*(fxctmp9.*)/$1/i;
+ $line =~ s/^.*(vshtmp9.*)/$1/i;
+
+ # for vcs files. HACK!
+ $line =~ s,^.*game/hl2/shaders/,,i;
+
+ return $line;
+}
+
+sub MakeSureFileExists
+{
+ local( $filename ) = shift;
+ local( $testexists ) = shift;
+ local( $testwrite ) = shift;
+
+ local( @statresult ) = stat $filename;
+ if( !@statresult && $testexists )
+ {
+ die "$filename doesn't exist!\n";
+ }
+ local( $mode, $iswritable );
+ $mode = oct( $statresult[2] );
+ $iswritable = ( $mode & 2 ) != 0;
+ if( !$iswritable && $testwrite )
+ {
+ die "$filename isn't writable!\n";
+ }
+}
+
+sub LoadShaderListFile_GetShaderType
+{
+ my $shadername = shift;
+ my $shadertype;
+ if( $shadername =~ m/\.vsh/i )
+ {
+ $shadertype = "vsh";
+ }
+ elsif( $shadername =~ m/\.psh/i )
+ {
+ $shadertype = "psh";
+ }
+ elsif( $shadername =~ m/\.fxc/i )
+ {
+ $shadertype = "fxc";
+ }
+ else
+ {
+ die;
+ }
+ return $shadertype;
+}
+
+sub LoadShaderListFile_GetShaderSrc
+{
+ my $shadername = shift;
+ if ( $shadername =~ m/^(.*)-----/i )
+ {
+ return $1;
+ }
+ else
+ {
+ return $shadername;
+ }
+}
+
+sub LoadShaderListFile_GetShaderBase
+{
+ my $shadername = shift;
+ if ( $shadername =~ m/-----(.*)$/i )
+ {
+ return $1;
+ }
+ else
+ {
+ my $shadertype = &LoadShaderListFile_GetShaderType( $shadername );
+ $shadername =~ s/\.$shadertype//i;
+ return $shadername;
+ }
+}
+
+sub LoadShaderListFile
+{
+ my $inputbase = shift;
+
+ my @srcfiles;
+ &MakeSureFileExists( "$inputbase.txt", 1, 0 );
+
+ open SHADERLISTFILE, "<$inputbase.txt" || die;
+ my $line;
+ while( $line = <SHADERLISTFILE> )
+ {
+ $line =~ s/\/\/.*$//; # remove comments "//..."
+ $line =~ s/^\s*//; # trim leading whitespace
+ $line =~ s/\s*$//; # trim trailing whitespace
+ next if( $line =~ m/^\s*$/ );
+ if( $line =~ m/\.fxc/ || $line =~ m/\.vsh/ || $line =~ m/\.psh/ )
+ {
+ my $shaderbase = &LoadShaderListFile_GetShaderBase( $line );
+
+ if( $ENV{"DIRECTX_FORCE_MODEL"} =~ m/^30$/i ) # forcing all shaders to be ver. 30
+ {
+ my $targetbase = $shaderbase;
+ $targetbase =~ s/_ps2x/_ps30/i;
+ $targetbase =~ s/_ps20b/_ps30/i;
+ $targetbase =~ s/_ps20/_ps30/i;
+ $targetbase =~ s/_vs20/_vs30/i;
+ $targetbase =~ s/_vsxx/_vs30/i;
+ push @srcfiles, ( $line . "-----" . $targetbase );
+ }
+ else
+ {
+ if( $shaderbase =~ m/_ps2x/i )
+ {
+ my $targetbase = $shaderbase;
+ $targetbase =~ s/_ps2x/_ps20/i;
+ push @srcfiles, ( $line . "-----" . $targetbase );
+
+ $targetbase = $shaderbase;
+ $targetbase =~ s/_ps2x/_ps20b/i;
+ push @srcfiles, ( $line . "-----" . $targetbase );
+ }
+ elsif( $shaderbase =~ m/_vsxx/i )
+ {
+ my $targetbase = $shaderbase;
+ $targetbase =~ s/_vsxx/_vs11/i;
+ push @srcfiles, ( $line . "-----" . $targetbase );
+
+ $targetbase = $shaderbase;
+ $targetbase =~ s/_vsxx/_vs20/i;
+ push @srcfiles, ( $line . "-----" . $targetbase );
+ }
+ else
+ {
+ push @srcfiles, ( $line . "-----" . $shaderbase );
+ }
+ }
+ }
+ }
+ close SHADERLISTFILE;
+ return @srcfiles;
+}
+
+sub ReadInputFileWithIncludes
+{
+ local( $filename ) = shift;
+# print STDERR "ReadInputFileWithIncludes: $filename\n";
+
+ local( *INPUT );
+ local( $output );
+
+# print STDERR "before open\n";
+ open INPUT, "<$filename" || die;
+# print STDERR "after open\n";
+
+ local( $line );
+ while( $line = <INPUT> )
+ {
+# print STDERR $line;
+ if( $line =~ m/\#include\s+\"(.*)\"/i )
+ {
+ $output.= ReadInputFileWithIncludes( $1 );
+ }
+ else
+ {
+ $output .= $line;
+ }
+ }
+
+ close INPUT;
+ return $output;
+}
+
+sub GetCRCFromSourceFile
+{
+ my $filename = shift;
+ my $data = &ReadInputFileWithIncludes( $filename );
+# print STDERR $data;
+ $crc = crc32( $data );
+# print STDERR "GetCRCFromSourceFile: $crc\n";
+ return $crc;
+}
+
+sub GetCRCFromVCSFile
+{
+ my $filename = shift;
+# print STDERR "GetCRCFromVCSFile $filename\n";
+ local( *FP );
+ open FP, "<$filename" || die "GetCRCFromVCSFile: can't open file $filename\n";
+ binmode( FP );
+
+ # unpack arguments
+ my $sInt = "i";
+ my $uInt = "I";
+ if( $filename =~ m/\.360\./ )
+ {
+ # Change arguments to "big endian long"
+ $sInt = "N";
+ $uInt = "N";
+ }
+
+ my $header;
+ read FP, $header, 7 * 4 || die "updateshaders.pl:GetCRCFromVCSFile: can't read header for $filename\n";
+ my $version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc;
+ ($version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc) = unpack "$sInt$sInt$sInt$uInt$uInt$uInt$uInt", $header;
+ unless( $version == 4 || $version == 5 || $version == 6 )
+ {
+ print STDERR "ERROR: GetCRCFromVCSFile: $filename is version $version\n";
+ return 0;
+ }
+# print STDERR "version: $version\n";
+# print STDERR "numCombos: $numCombos\n";
+# print STDERR "numDynamicCombos: $numDynamicCombos\n";
+# print STDERR "flags: $flags\n";
+# print STDERR "centroidMask: $centroidMask\n";
+# print STDERR "refSize: $refSize\n";
+# print STDERR "GetCRCFromVCSFile: $crc\n";
+ close( FP );
+ return $crc;
+}
+
+sub CheckCRCAgainstTarget
+{
+ my $srcFileName = shift;
+ my $vcsFileName = shift;
+ my $warn = shift;
+
+ # Make sure both files exist.
+# print STDERR "$srcFileName doesn't exist\n" if( !( -e $srcFileName ) );
+# print STDERR "$vcsFileName doesn't exist\n" if( !( -e $vcsFileName ) );
+ if( !( -e $srcFileName ) )
+ {
+ if( $warn )
+ {
+ print "$srcFileName missing\n";
+ }
+ return 0;
+ }
+ if( !( -e $vcsFileName ) )
+ {
+ if( $warn )
+ {
+ print "$vcsFileName missing\n";
+ }
+ return 0;
+ }
+# print STDERR "CheckCRCAgainstTarget( $srcFileName, $vcsFileName );\n";
+# print STDERR "vcsFileName: $vcsFileName\n";
+# print STDERR "vcsFileName: $srcFileName\n";
+ my $vcsCRC = &GetCRCFromVCSFile( $vcsFileName );
+ my $srcCRC = &GetCRCFromSourceFile( $srcFileName );
+ if( $warn && ( $vcsCRC != $srcCRC ) )
+ {
+ print "$vcsFileName checksum ($vcsCRC) != $srcFileName checksum: ($srcCRC)\n";
+ }
+
+# return 0; # use this to skip crc checking.
+# if( $vcsCRC == $srcCRC )
+# {
+# print STDERR "CRC passed for $srcFileName $vcsFileName $vcsCRC\n";
+# }
+ return $vcsCRC == $srcCRC;
+}
+
+1;
diff --git a/devtools/bin/vmpi_chpass.pl b/devtools/bin/vmpi_chpass.pl
new file mode 100644
index 0000000..12ccf8a
--- /dev/null
+++ b/devtools/bin/vmpi_chpass.pl
@@ -0,0 +1,116 @@
+#!/usr/bin/perl -w
+use IO::Socket::INET;
+use Sys::Hostname;
+use Data::Dumper;
+use Getopt::Long;
+use Pod::Usage;
+use strict;
+
+use constant VMPI_PROTOCOL_VERSION => 5;
+
+use constant VMPI_MESSAGE_BASE => 71;
+use constant VMPI_PING_REQUEST => VMPI_MESSAGE_BASE+2;
+use constant VMPI_PING_RESPONSE => VMPI_MESSAGE_BASE+3;
+use constant VMPI_FORCE_PASSWORD_CHANGE => VMPI_MESSAGE_BASE+11;
+
+use constant VMPI_PASSWORD_OVERRIDE => -111;
+
+use constant VMPI_SERVICE_PORT => 23397;
+use constant VMPI_LAST_SERVICE_PORT => VMPI_SERVICE_PORT + 15;
+
+my $list = undef;
+my $pass = "";
+my $help = 0;
+my $man = 0;
+
+GetOptions("file=s" => \$list,
+ "pass=s" => \$pass,
+ "help|?" => \$help,
+ "man" => \$man) or pod2usage(1);
+pod2usage(2) if $help;
+pod2usage(-exitstatus=>0, -verbose=>2) if $man;
+
+my @machines = @ARGV;
+if ($list) {
+ if (open(my $listfh, $list)) {
+ while(my $line = <$listfh>) {
+ chomp($line);
+ next unless $line =~ /\S/;
+ push @machines, $line;
+ }
+ }
+}
+
+if (!@machines) {
+ warn "No machines specified\n";
+ pod2usage(3);
+}
+
+my $message = BuildMessage(VMPI_PROTOCOL_VERSION, VMPI_FORCE_PASSWORD_CHANGE);
+$message .= pack("Z*", $pass);
+my $length = length($message);
+
+my $socket = CreateSocket();
+# send the message 3 times to make sure it gets it
+for (1..3) {
+ for my $host (@machines) {
+ SendMessage($socket, $host, $message);
+ }
+ sleep(1);
+}
+
+
+sub CreateSocket {
+ return IO::Socket::INET->new(Proto=>'udp');
+}
+
+sub BuildMessage {
+ my $ver = shift;
+ my $type = shift;
+
+ my $message = pack("CcCC", $ver, VMPI_PASSWORD_OVERRIDE, 0, $type);
+ return $message;
+}
+
+sub SendMessage {
+ my $socket = shift;
+ my $host = shift;
+ my $message = shift;
+
+ my $ip = gethostbyname($host);
+ if (!$ip) {
+ warn "Can't resolve: $host\n";
+ return;
+ }
+
+ for my $port (VMPI_SERVICE_PORT..VMPI_LAST_SERVICE_PORT) {
+ my $ipaddr = sockaddr_in($port, $ip);
+ defined(send($socket, $message, 0, $ipaddr)) || warn("SEND: $!\n");
+ }
+}
+
+__END__
+
+=head1 NAME
+
+vmpi_chpass.pl - Sets the VMPI password on a set of machines
+
+=head1 SYNOPSIS
+
+vmpi_chpass.pl [-pass <password>] [-help|-?] [-man]
+ -file <host file> | <host> ...
+
+ Options:
+ -file A file that contains the names of machines to use
+ -pass Password to set
+ -help|-? Display command line usage
+ -man Display full documentation
+
+=head1 DESCRIPTION
+
+B<vmpi_chpass.pl> sets the password on the given list of machines. The
+machines can be given as separate arguments on the command line or as
+a list in a text file. If the password is not given, the password is
+removed from the machines, opening them up for general use.
+
+=cut
diff --git a/devtools/bin/vmpi_test.pl b/devtools/bin/vmpi_test.pl
new file mode 100644
index 0000000..4fe22d2
--- /dev/null
+++ b/devtools/bin/vmpi_test.pl
@@ -0,0 +1,385 @@
+#!/usr/bin/perl -w
+use Getopt::Long;
+use Pod::Usage;
+use Sys::Hostname;
+use File::Copy;
+use File::Path;
+use Time::HiRes qw(gettimeofday tv_interval);
+use Cwd;
+use strict;
+
+use vars qw(%TESTS %STATS $ABORT_RUN $MPI_GRAPHICS);
+
+# To add a new test, just create a new hash entry that has code
+# references for the Prep, Run and Clean stages of the test.
+# The new test can be selected using the -test option.
+
+%TESTS = (
+ 'vrad' => {
+ 'PREP' => \&VRADPrep,
+ 'RUN' => \&VRADRun,
+ 'CLEAN' => \&VRADClean,
+ },
+
+ 'vvis' => {
+ 'PREP' => \&VVISPrep,
+ 'RUN' => \&VVISRun,
+ 'CLEAN' => \&VVISClean,
+ },
+
+ 'shadercompile' => {
+ 'PREP' => \&ShaderPrep,
+ 'RUN' => \&ShaderRun,
+ 'CLEAN' => \&ShaderClean,
+ }
+ );
+
+%STATS = ();
+$ABORT_RUN = 0;
+$MPI_GRAPHICS = 0;
+
+local $SIG{INT} = sub {
+ $ABORT_RUN = 1;
+};
+
+my $start = 4;
+my $stop = 32;
+my $step = 4;
+my $test = "vrad";
+my $list = undef;
+my $help = 0;
+my $man = 0;
+
+my @work_list = ();
+GetOptions("file=s" => \$list,
+ "test=s" => \$test,
+ "workerlist=s" => sub {
+ shift; local $_ = shift;
+ @work_list = split(',', $_)
+ },
+ "start|s=i" => \$start,
+ "stop|e=i" => \$stop,
+ "step=i" => \$step,
+ "graphics" => \$MPI_GRAPHICS,
+ "help|?" => \$help,
+ "man" => \$man) or pod2usage(2);
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+my @extra_args = @ARGV;
+
+unless (@work_list) {
+ for (my $workers = $stop; $workers >= $start; $workers -= $step) {
+ push @work_list, $workers;
+ }
+}
+
+if (defined($list)) {
+ @work_list = ReadMachineList($list, \@work_list);
+}
+
+unless (@work_list) {
+ die "No workers in list\n";
+}
+
+my $logfile = "$test-$$.log";
+print "Testing: ", join(", ", @work_list), "\n";
+print "Logging to $logfile\n";
+
+# Redirect console to log file and unbuffer the output
+open STDOUT, ">$logfile";
+open STDERR, ">>$logfile";
+my $oldfh = select(STDOUT); $| = 1;
+select(STDERR); $| = 1;
+select($oldfh);
+
+# Lock the list of machines if given
+# Prepare for the test
+# Run the test over the work list
+# Clean up after the test
+# Release lock on list of machines if given
+
+my $pass = defined($list) ? ReserveMachines($list, $test) : '';
+TestPrep($test, @extra_args);
+for my $workers (@work_list) {
+ last if $ABORT_RUN;
+ TestRun($test, $workers, $pass, @extra_args);
+}
+TestClean($test, @extra_args);
+ReleaseMachines($list) if defined($list);
+
+sub ReadMachineList
+{
+ my $list = shift;
+ my $work_list = shift;
+
+ my @machines = ();
+
+ if (open(my $listfh, $list)) {
+ while(my $line = <$listfh>) {
+ chomp($line);
+ next unless $line =~ /\S/;
+ push @machines, $line;
+ }
+ }
+
+ my @capped_list = grep { $_ <= scalar(@machines) } @{$work_list};
+ if ($#{$work_list} > $#capped_list) {
+ print "Not enough machines to run test\n";
+ print "Reducing max workers\n\n";
+ }
+ return @capped_list;
+}
+
+sub SetVMPIPass {
+ my $machines = shift;
+ my $pass = shift;
+
+ system("vmpi_chpass.pl", "-p", $pass, "-f", $machines);
+}
+
+sub ReserveMachines
+{
+ my $list = shift;
+ my $pass = shift;
+
+ my $host = lc hostname();
+ $pass .= "-test-$host-$$";
+ SetVMPIPass($list, $pass);
+ return $pass;
+}
+
+sub ReleaseMachines
+{
+ my $machines = shift;
+ SetVMPIPass($machines, '');
+}
+
+sub DoTestFunc
+{
+ my $test = shift;
+ my $func = shift;
+ my $workers = $_[0];
+
+ if (exists($TESTS{$test}{$func})) {
+ my $start = [gettimeofday];
+ &{$TESTS{$test}{$func}}(@_);
+ my $stop = [gettimeofday];
+ my $time = tv_interval($start, $stop);
+ $STATS{$func}{$workers} = $time / 60;
+ }
+ else {
+ die "Failed to locate test function for: $test($func)\n";
+ }
+}
+
+sub TestPrep
+{
+ my $test = shift;
+ DoTestFunc($test, 'PREP', 0, '', @_);
+}
+
+sub TestRun
+{
+ my $test = shift;
+ DoTestFunc($test, 'RUN', @_);
+}
+
+sub TestClean
+{
+ my $test = shift;
+ DoTestFunc($test, 'CLEAN', 0, '', @_);
+}
+
+sub GetMPIArgs
+{
+ my $n_workers = shift;
+ my $pass = shift;
+
+ my @args = ("-mpi");
+ push(@args, "-mpi_workercount", $n_workers) if $n_workers > 0;
+ push(@args, "-mpi_pw", $pass) if $pass;
+ push(@args, "-mpi_graphics", "-mpi_trackevents") if $MPI_GRAPHICS;
+ return @args;
+}
+
+
+sub VRADPrep
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+ my @extra_args = @_;
+ my @mpi_args = GetMPIArgs($n_workers, $pass);
+
+ system("vbsp", $basename);
+ system("vvis", @mpi_args, @extra_args, $basename);
+ copy("$basename.bsp", "$basename-$$.bsp");
+}
+
+sub VRADRun
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+ my @extra_args = @_;
+ my @mpi_args = GetMPIArgs($n_workers, $pass);
+
+ copy("$basename-$$.bsp", "$basename.bsp");
+ system("vrad", "-final", "-staticproppolys", "-staticproplighting",
+ @mpi_args, @extra_args, $basename);
+
+}
+
+sub VRADClean
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+
+ unlink("$basename.bsp", "$basename-$$.bsp");
+}
+
+
+sub VVISPrep
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+ my @mpi_args = GetMPIArgs($n_workers, $pass);
+
+ system("vbsp", $basename);
+ copy("$basename.bsp", "$basename-$$.bsp");
+}
+
+sub VVISRun
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+ my @extra_args = @_;
+ my @mpi_args = GetMPIArgs($n_workers, $pass);
+
+ copy("$basename-$$.bsp", "$basename.bsp");
+ system("vvis", @mpi_args, $pass, @extra_args, $basename);
+}
+
+sub VVISClean
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+
+ unlink("$basename.bsp", "$basename-$$.bsp");
+}
+
+sub ShaderPrep
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+
+ $ENV{DIRECTX_SDK_VER}='pc09.00';
+ $ENV{DIRECTX_SDK_BIN_DIR}='dx9sdk\\utilities';
+ $ENV{PATH} .= ";..\\..\\devtools\\bin";
+
+ my $src_base = "../..";
+ my $dos_base = $src_base;
+ $dos_base =~ s|/|\\|g;
+
+ unlink("makefile.$basename");
+ unlink(qw(filelist.txt filestocopy.txt filelistgen.txt inclist.txt vcslist.txt));
+ rmtree("shaders");
+ mkpath(["shaders/fxc", "shaders/vsh", "shaders/psh"]);
+
+ print "Update Shaders\n";
+ system("updateshaders.pl", "-source", $dos_base, $basename);
+
+ print "Prep Shaders\n";
+ system("nmake", "/S", "/C", "-f", "makefile.$basename");
+ if (open(my $fh, ">>filestocopy.txt")) {
+ print $fh "$dos_base\\$ENV{DIRECTX_SDK_BIN_DIR}\\dx_proxy.dll\n";
+ print $fh "$dos_base\\..\\game\\bin\\shadercompile.exe\n";
+ print $fh "$dos_base\\..\\game\\bin\\shadercompile_dll.dll\n";
+ print $fh "$dos_base\\..\\game\\bin\\vstdlib.dll\n";
+ print $fh "$dos_base\\..\\game\\bin\\tier0.dll\n";
+ }
+
+ print "Uniqify List\n";
+ system("uniqifylist.pl < filestocopy.txt > uniquefilestocopy.txt");
+ copy("filelistgen.txt", "filelist.txt");
+ print "Done Prep\n";
+}
+
+sub ShaderRun
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+ my @extra_args = @_;
+ my @mpi_args = GetMPIArgs($n_workers, $pass);
+
+ my $old_dir = getcwd();
+ my $dos_dir = $old_dir;
+ $dos_dir =~ s|/|\\|g;
+
+ system("shadercompile", "-allowdebug", "-shaderpath", $dos_dir, @mpi_args, @extra_args);
+}
+
+sub ShaderClean
+{
+ my $n_workers = shift;
+ my $pass = shift;
+ my $basename = shift;
+
+ unlink("makefile.$basename");
+ unlink(qw(filelist.txt filestocopy.txt filelistgen.txt inclist.txt vcslist.txt));
+ mkpath(["shaders/fxc", "shaders/vsh", "shaders/psh"]);
+}
+
+END {
+ if (%STATS) {
+ print "\n\n", "-"x70, "\n\n";
+ for my $func (qw(PREP RUN CLEAN)) {
+ print "$func\n";
+ print "="x length($func), "\n";
+ for my $workers (sort {$a <=> $b} keys %{$STATS{$func}}) {
+ printf("%3d, %6.3f\n", $workers, $STATS{$func}{$workers});
+ }
+ print "\n";
+ }
+ }
+}
+
+__END__
+
+=head1 NAME
+
+vmpi_test.pl - Test utility to automate execution of VMPI tools
+
+=head1 SYNOPSIS
+
+vmpi_test.pl [-test <test name>] [-file <host file>] [-start <num>] [-stop <num>] [-step <num>] [-workerlist <list>] [-graphics] [-help|-?] [-man]
+
+ Options:
+ -test The name of the test to run
+ -file A file that contains the names of machines to use
+ -start Lowest worker count to test
+ -stop Highest worker count to test
+ -step Interval to increment worker count
+ -workerlist A comma separated list of worker counts to test
+ -graphics Enable MPI visual work unit tracker
+ -help|-? Display command line usage
+ -man Display full documentation
+
+=head1 DESCRIPTION
+
+B<vmpi_test.pl> executes a specified test for each number of worker
+counts given on the command line. The worker counts can be provided as
+a start, stop and step relationship, or it can be specified using a
+comma separated list. An optional host list file can be provided to
+restrict the test to a given set of machines. These machines will have
+a VMPI password applied to them so that you will get exclusive access
+to them.
+
+=cut
diff --git a/devtools/bin/vpc b/devtools/bin/vpc
new file mode 100644
index 0000000..de694fd
--- /dev/null
+++ b/devtools/bin/vpc
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+OS=`uname`
+SCRIPTPATH=`dirname $0`
+FORCEARG=""
+
+case $OS in
+"Darwin")
+ BINNAME=vpc_osx
+ ;;
+"Linux")
+ BINNAME=vpc_linux
+ ;;
+*)
+ echo "Couldn't find appropriate VPC binary, fix the script."
+ exit -1
+ ;;
+esac
+
+CWD=`pwd`
+cd $SCRIPTPATH/../../external/vpc/utils/vpc
+# ask make if we need to do any work, returns 0 if we don't,
+# non zero if we do.
+make -q
+RC=$?
+if [ $RC -eq 1 ]; then
+ FORCEARG="/f"
+elif [ $RC -eq 2 ]; then
+ FORCEARG="/f"
+ make clean
+fi
+make -j4
+if [ $? -ne 0 ]; then
+ exit -1
+fi
+
+cd $CWD
+
+if [ $OS == "Darwin" ]; then
+ $SCRIPTPATH/$BINNAME $FORCEARG $@
+elif [ $OS == "Linux" ]; then
+ $SCRIPTPATH/$BINNAME $FORCEARG $@
+else
+ echo "Couldn't find appropriate VPC binary, fix the script."
+ exit -1
+fi
diff --git a/devtools/bin/vpc.exe b/devtools/bin/vpc.exe
new file mode 100644
index 0000000..e611043
--- /dev/null
+++ b/devtools/bin/vpc.exe
Binary files differ
diff --git a/devtools/bin/vpc.pdb b/devtools/bin/vpc.pdb
new file mode 100644
index 0000000..9ead163
--- /dev/null
+++ b/devtools/bin/vpc.pdb
Binary files differ
diff --git a/devtools/bin/vpc2linuxmake.pl b/devtools/bin/vpc2linuxmake.pl
new file mode 100644
index 0000000..1a94f16
--- /dev/null
+++ b/devtools/bin/vpc2linuxmake.pl
@@ -0,0 +1,684 @@
+#!perl
+use IO::File;
+use File::Basename;
+use File::Find;
+use Cwd;
+use Cwd 'abs_path';
+
+
+
+$nprocs=`grep vendor_id /proc/cpuinfo | wc -l `;
+$nprocs=~s/[\n\r]//g;
+print "$nprocs processors found\n";
+
+#find where to include master make file from
+$srcdir=getcwd;
+die "can't determine path to src"
+ unless ($srcdir=~s@/src.*$@/src@);
+
+
+find( { wanted=> \&handle_vpc_file } ,"$srcdir"); # search through all directories for .vpc files
+
+@MAINTARGETS=("all", "clean", "objs");
+@TARGETS=("all", "clean", "objs", "tags");
+
+
+
+# now, write a master makefile in each dir, and a master-master makefile in ~/src
+foreach $dir ( keys %dir_written )
+{
+ open( MAKEOUT,">$dir/Makefile" ) || die "can't write $dir/Makefile";
+ foreach $target ( @TARGETS )
+ {
+ print MAKEOUT "$target:\n";
+ foreach $_ (split(/,/,$dir_written{$dir}) )
+ {
+ print MAKEOUT "\tmake -j $nprocs -f $_ $target\n" if length($_);
+ }
+ }
+ close MAKEOUT;
+}
+
+# now, write a master makefile in ~/src
+open( MAKEOUT,">$srcdir/Makefile" ) || die "can't write master makefile to $srcdir";
+foreach $target ( @MAINTARGETS )
+{
+ print MAKEOUT "$target:\n";
+ foreach $dir ( keys %dir_written )
+ {
+ print MAKEOUT "\tmake -j $nprocs -C $dir $target #$dir_conf_type{$dir}\n" if ($dir_conf_type{$dir} eq "lib");
+ }
+ foreach $dir ( keys %dir_written )
+ {
+ print MAKEOUT "\tmake -j $nprocs -C $dir $target #$dir_conf_type{$dir}\n" if ($dir_conf_type{$dir} ne "lib");
+ }
+
+}
+print MAKEOUT "\n\nmakefiles:\n\tperl $srcdir/devtools/bin/vpc2linuxmake.pl\n";
+print MAKEOUT "\ntags:\n\trm -f $srcdir/TAGS\n";
+print MAKEOUT "\tetags -a -C -o $srcdir/TAGS public/*.cpp public/*.h public/*/*.cpp public/*/*.h common/*.cpp common/*.h\n";
+
+foreach $dir ( keys %dir_written )
+{
+ print MAKEOUT "\tmake -C $dir tags\n";
+}
+
+
+close MAKEOUT;
+
+sub handle_vpc_file
+{
+ # called for each file in the callers dir tree
+ my $dir=$File::Find::dir;
+ return if ( $dir=~/vpc_scripts/i );
+ if ( /_base\.vpc$/i )
+ {
+ unless ( /hk_base\.vpc$/i )
+ {
+ return;
+ }
+ }
+
+ if ( /_include\.vpc$/i )
+ {
+ unless ( /hk_base\.vpc$/i )
+ {
+ return;
+ }
+ }
+
+ if (/\.vpc$/)
+ {
+ (%ignore_file,@DEFINES, @CPPFILES, @CXXFILES,@CFILES, @LITERAL_LIBFILES,@LIBFILES, %define_seen,%macros,%include_seen,@INCLUDEDIRS)=undef;
+ undef $buildforlinux;
+ undef $conf_type;
+ $OptimizerLevel='$(SAFE_OPTFLAGS_GCC_422)';
+ $SymbolVisibility='hidden';
+
+
+ # some defines to ignore in vpc files when generating linux include files
+
+ $define_seen{'WIN32'}=1;
+ $define_seen{'_WIN32'}=1;
+ $define_seen{'_WINDOWS'}=1;
+ $define_seen{'_USRDLL'}=1;
+ $define_seen{'DEBUG'}=1;
+ $define_seen{'_DEBUG'}=1;
+ $define_seen{'NDEBUG'}=1;
+ $define_seen{'_CRT_SECURE_NO_DEPRECATE'}=1;
+ $define_seen{'_CRT_NONSTDC_NO_DEPRECATE'}=1;
+ $define_seen{'fopen'}=1;
+ #print "$_\n";
+ &ParseVPC($_);
+
+ $pname=lc($pname);
+ $pname=~s/\s+/_/g;
+ $pname=~s/[\(\)]//g;
+ # if anything seen, output a makefile
+ if ( $buildforlinux && ( @CPPFILES || @CXXFILES || @CFILES || @LIBFILES ) )
+ {
+ print STDERR "writing project $pname\n";
+ $projdir=getcwd;
+ $projdir=~s@/$@@;
+ $dir_written{$projdir}.=",$pname.mak";
+ $dir_conf_type{$projdir}=$conf_type;
+ &WriteMakefile("$projdir/$pname.mak");
+ &WriteCodeBlocksProj("$projdir/$pname.cbp");
+ }
+ else
+ {
+ die "no .lib or source files found in .vpc" if ( $buildforlinux );
+ }
+ }
+}
+
+
+sub WriteCodeBlocksProj
+{
+ local($_)=@_;
+
+ open(CBPROJ,">$_") || die "can't write $_";
+
+ print CBPROJ <<HEADER
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+<FileVersion major="1" minor="6" />
+<Project>
+<Option title="$pname" />
+<Option pch_mode="2" />
+<Option compiler="gcc" />
+<Build>
+ <Target title="Release">
+
+ </Target>
+</Build>
+HEADER
+;
+
+ foreach $fl (@CPPFILES)
+ {
+ push @cppfiles2, $fl unless ( $ignore_file{$fl} > 0 );
+ }
+
+ foreach $fl (@CXXFILES)
+ {
+ push @cxxfiles2, $fl unless ( $ignore_file{$fl} > 0 );
+ }
+
+ printf CBPROJ "\t\t<Compiler>\n";
+
+ foreach $_ (@DEFINES)
+ {
+ print CBPROJ "\t\t\t<Add option=\"-DSWDS\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-D_LINUX\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-fpermissive\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-Dstricmp=strcasecmp\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-D_stricmp=strcasecmp\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-D_strnicmp=strncasecmp\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-Dstrnicmp=strncasecmp\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-D_snprintf=snprintf\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-D_vsnprintf=vsnprintf\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-D_alloca=alloca\" />\n";
+ print CBPROJ "\t\t\t<Add option=\"-Dstrcmpi=strcasecmp\" />\n";
+
+ print CBPROJ "\t\t\t<Add option=\"-D$_\" />\n";
+ }
+
+ foreach $_ (@INCLUDEDIRS)
+ {
+ print CBPROJ "\t\t\t<Add directory=\"$_\" />\n";
+ }
+
+ printf CBPROJ "\t\t</Compiler>\n";
+
+ @CPPFILES = sort(@CPPFILES);
+ @CXXFILES = sort(@CXXFILES);
+ @CFILES = sort(@CFILES);
+
+ # now, output obj dependencies
+ foreach $_ (@CPPFILES, @CFILES, @CXXFILES)
+ {
+ unless (( $ignore_file{$_} > 0 ) || ( length($_) < 2 ) )
+ {
+ ($filename,$dir,$suffix) = fileparse($_,qr/\.[^.]*/);
+
+ print CBPROJ "\t\t<Unit filename=\"".$dir . $filename. ".cpp\" />\n";
+ }
+ }
+
+ print CBPROJ <<FOOTER
+<Extensions>
+ <code_completion />
+</Extensions>
+</Project>
+</CodeBlocks_project_file>
+FOOTER
+;
+
+ close CBPROJ;
+
+}
+
+
+sub WriteMakefile
+{
+ local($_)=@_;
+ my $objdir ="obj";
+ open(MAKEFILE,">$_") || die "can't write $_";
+ print MAKEFILE "NAME=$pname\n\n";
+ if ( $pname =~ /(server|client)_(\S+)/i )
+ {
+ print MAKEFILE "OBJSUFFIX=_$2\n";
+ $objdir .= "_$2";
+ }
+ print MAKEFILE "SRCROOT=$srcdir\n";
+ print MAKEFILE "PROJDIR=$projdir\n";
+ print MAKEFILE "CONFTYPE=$conf_type\n";
+ print MAKEFILE "OptimizerLevel=$OptimizerLevel\n";
+ print MAKEFILE "SymbolVisibility=$SymbolVisibility\n";
+
+
+ if (@DEFINES)
+ {
+ print MAKEFILE "DEFINES= -D",join(" -D", @DEFINES),"\n";
+ }
+ if (@INCLUDEDIRS)
+ {
+ print MAKEFILE "INCLUDEDIRS= -I",join(" -I", @INCLUDEDIRS),"\n";
+ }
+ undef @cppfiles2;
+ undef @cxxfiles2;
+ foreach $fl (@CPPFILES)
+ {
+ if ( length($fl) )
+ {
+ print "warning file $fl does not exist\n" unless( -e $fl);
+ push @cppfiles2, $fl unless ( $ignore_file{$fl} > 0 );
+ }
+ }
+ foreach $fl (@CXXFILES)
+ {
+ push @cxxfiles2, $fl unless ( $ignore_file{$fl} > 0 );
+ }
+
+ if (@cppfiles2)
+ {
+ print MAKEFILE "CPPFILES= \\\n ", join(" \\\n ",@cppfiles2), "\n";
+ }
+ if (@cxxfiles2)
+ {
+ print MAKEFILE "CXXFILES= \\\n ", join(" \\\n ",@cxxfiles2), "\n";
+ }
+ if (@CFILES)
+ {
+ print MAKEFILE "CFILES= \\\n ", join(" \\\n ",@CFILES), "\n";
+ }
+ if (@LIBFILES)
+ {
+ undef @LIBNAMES;
+ print MAKEFILE "\nLIBFILES= \\\n";
+ unless( $pname=~/(tier0)|(mathlib)|(tier1)/i)
+ {
+ print MAKEFILE " $srcdir/lib/linux/tier1_486.a \\\n"
+ }
+ foreach $lib (@LIBFILES)
+ {
+ my @DLLNAMES=("tier0", "vstdlib", "steam_api");
+ unless ( $ignore_file{$lib} > 0 )
+ {
+ $lib=lc($lib);
+ my ($filename,$dir,$suffix) = fileparse($lib,qr/\.[^.]*/);
+ my $dll=0;
+ foreach $dllname (@DLLNAMES)
+ {
+ $dll=1 if ( $dllname eq $filename);
+ }
+ if ( $dll )
+ {
+ $lib=~s@^.*/([^/]+)\.lib@$1_i486.so@i;
+ $lib=~s@^.*/lib/(\S+)@$1@g;
+ }
+ else
+ {
+ $lib=~s/\.lib/_486.a/i;
+ $lib=~s@/lib/(\S+)/@/lib/linux/@g;
+ }
+ push @LIBNAMES, $lib;
+ }
+ }
+ foreach $lib (@LITERAL_LIBFILES)
+ {
+ unless ( $ignore_file{$lib} > 0 )
+ {
+ $lib=~s/\\/\//g;
+ $lib=~s@/linux/([a-zA-Z_0-9\.]+)$@/linux/$1@;
+ $lib=~s@^.*/linux/([a-zA-Z_0-9]+)\.so$@$1.so@;
+ push @LIBNAMES, $lib;
+ }
+ }
+ # now, sort libs for link order
+ foreach $lib ( sort bypriority @LIBNAMES )
+ {
+ print MAKEFILE " $lib \\\n";
+ }
+ print MAKEFILE "\n\n";
+ }
+
+ if ( $conf_type eq "dll" )
+ {
+ print MAKEFILE "OUTPUT_SO_FILE=$srcdir/linux/$pname","_i486.so\n\n";
+ }
+ elsif ( $conf_type eq "exe" )
+ {
+ if ( $macros{'OUTBINNAME'} eq "" )
+ {
+ die "Missing OUTBINNAME macro";
+ }
+
+ print MAKEFILE "OUTPUT_EXECUTABLE=$srcdir/linux/$macros{'OUTBINNAME'}\n\n";
+ }
+
+ print MAKEFILE "\n\n\# include base make file\ninclude $srcdir/devtools/makefile_base_linux.mak\n";
+
+ # now, output obj dependencies
+ foreach $_ (@CPPFILES, @CFILES)
+ {
+ unless (( $ignore_file{$_} > 0 ) || ( length($_) < 2 ) )
+ {
+ ($filename) = fileparse($_,qr/\.[^.]*/);
+ print MAKEFILE getcwd,"/$objdir/$filename.o : $_\n\t\$(DO_CC)\n";
+ }
+ }
+ foreach $_ (@CXXFILES)
+ {
+ unless (( $ignore_file{$_} > 0 ) || ( length($_) < 2 ) )
+ {
+ ($filename) = fileparse($_,qr/\.[^.]*/);
+ print MAKEFILE getcwd,"/$objdir/$filename.oxx : $_\n\t\$(DO_CC)\n";
+ }
+ }
+
+ close MAKEFILE;
+}
+
+sub bypriority
+{
+# sort libs for gcc linkgoodness
+ $priority{"mathlib"}="0005";
+ $priority{"tier1"}="0010";
+ $priority{"tier2"}="0020";
+ $priority{"tier3"}="0030";
+
+ my ($filenamea) = fileparse($a,qr/\.[^.]*/);
+ my ($filenameb) = fileparse($b,qr/\.[^.]*/);
+ $filenamea =~ s/_.86.*$//; # lose _i486
+ $filenameb =~ s/_.86.*$//;
+ my $pa=$priority{$filenamea} || 1000;
+ my $pb=$priority{$filenameb} || 1000;
+ return $pb cmp $pa;
+}
+
+sub ParseVPC
+{
+ local($fname)=@_;
+ &startreading($fname);
+ while(&nextvpcline)
+ {
+# print "$fname - $_\n";
+ if ( (/^\$linux/i) )
+ {
+ &skipblock(0,\&handlelinuxline);
+ }
+ if ( (/^\$configuration/i) )
+ {
+ &skipblock(0,\&handleconfigline);
+ }
+ elsif (/^\s*\$project/i)
+ {
+ &parseproject;
+ }
+ }
+}
+
+sub massageline
+{
+ # strip leading and trailing spaces and carriage returns and comments from vpc lines
+ s/[\n\r]//g;
+ s@//.*$@@g;
+ s@^\s*@@g;
+ s@\s*$@@g;
+}
+
+sub submacros
+{
+ # replace all macros within a line
+ my $mac;
+ foreach $mac (keys %macros)
+ {
+ s/\$$mac/$macros{$mac}/g;
+ }
+}
+
+
+sub startreading
+{
+ # initialize recursive file reader
+ my( $fname)=@_;
+ #print STDERR "opening $fname\n";
+ $curfile=IO::File->new($fname) || die "can't open $fname";
+}
+
+sub nextvpcline
+{
+ # get the next line from the file, handling line continuations, macro substitution, and $include
+ # return 0 if out of lines
+ my $ret=0;
+ if ( $_ = <$curfile> )
+ {
+ $ret=1;
+ &massageline;
+ while(s@\\$@ @)
+ {
+ my $old=$_;
+ $_=<$curfile>;
+ &massageline;
+ $_=$old.$_;
+ }
+ s@\s+@ @g;
+ my $old=$_;
+ &submacros;
+ # now, parse
+ if (/\$macro (\S+) \"(\S+)\"$/i)
+ {
+ $macros{$1}=$2;
+ return &nextvpcline;
+ }
+ s/\[\$WIN32\]//g;
+ return &nextvpcline if (/\[\$X360\]/);
+ if ( /^\s*\$include\s+\"(.*)\"/i)
+ {
+ # process $include
+ my $incfile=$1;
+ push @filestack, $curfile;
+ $incfile=~s@\\@/@g;
+ #print STDERR "opening $incfile\n";
+ #$curfile=IO::File->new($incfile) || die "can't open include $incfile ($pname)";
+ if ( -e $incfile )
+ {
+ push @filestack, $curfile;
+ #print STDERR "opening $incfile\n";
+ $curfile=IO::File->new($incfile) || die "can't open include $incfile";
+ }
+ else
+ {
+ print "can't find include $incfile, ignoring\n";
+ }
+
+ return &nextvpcline;
+ }
+ }
+ else
+ {
+ $curfile->close;
+ if (@filestack)
+ {
+ $curfile=pop(@filestack);
+ return &nextvpcline;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ return $ret;
+}
+
+sub skipblock
+{
+ # skip a named block in the key values, handling nested {} pairs
+ my($empty_ok, $callback)=@_;
+ my $lnstat=&nextvpcline;
+ die "parse error eof in block" if ( (! $lnstat) && ( ! $empty_ok) );
+
+ my $nest=0;
+ if (/^\{/)
+ {
+ $nest++;
+ }
+ else
+ {
+ die "no start block found, $_ found instead" unless($empty_ok);
+ }
+ while ($nest)
+ {
+ die "prematur eof" unless &nextvpcline;
+ &$callback($_) if ( $callback );
+ $nest++ if (/^\{/);
+ $nest-- if (/^\}/);
+ }
+}
+
+sub parseproject
+{
+ # handle a project block, picking up files mentioned
+ $pname="";
+ $pname=$1 if (/^\s*\$project\s*\"(.*)\"/i);
+ local($_);
+ my $nest=0;
+ &nextvpcline || die "empty project?";
+ $nest++ if (/^\s*\{/);
+ while($nest )
+ {
+ &nextvpcline || die "premature eof in project?";
+ $nest++ if (/^\{/);
+ $nest-- if (/^\}/);
+ &CheckForFileLine($_);
+ }
+}
+
+sub CheckForFileLine
+{
+ local($_)=@_;
+ if (/^\s*\-\$File\s+(.*$)/i)
+ {
+ foreach $_ (split(/ /,$1))
+ {
+ s/\"//g;
+ $ignore_file{&process_path($_)} = 1;
+ }
+ }
+
+ elsif (/^\s*\$File\s+(.*$)/i)
+ {
+ foreach $_ (split(/ /,$1))
+ {
+ s/\"//g;
+ &handlefile($_);
+ }
+ }
+}
+
+sub handlefile
+{
+ # given a project file (.cpp, etc), figure out what to do with it
+ local($_)=@_;
+
+ # hardcoded exclusions for linux
+ return if (/dx9sdk/i);
+ return if (/_360/i);
+ return if (/xbox_console.cpp/i);
+ return if (/xbox_system.cpp/i);
+ return if (/xbox_win32stubs.cpp/i);
+ return if (/binkw32/i || /binkxenon/i );
+
+ if (/\.cpp$/)
+ {
+ push @CPPFILES,process_path($_);
+ }
+ if (/\.cxx$/)
+ {
+ push @CXXFILES,process_path($_);
+ }
+ elsif (/\.c$/)
+ {
+ push @CFILES,process_path($_);
+ }
+ elsif (/\.lib$/)
+ {
+ push @LIBFILES,process_path($_);
+ }
+ elsif (/\.a$/)
+ {
+ push @LITERAL_LIBFILES, process_path($_);
+ }
+ elsif (/\.so$/)
+ {
+ push @LITERAL_LIBFILES, process_path($_);
+ }
+}
+
+sub process_path
+{
+ local($_)=@_;
+ s@\\@/@g;
+ if ( (! -e $_) && ( -e lc($_)) )
+ {
+# print STDERR "$_ does not exist try lc($_)\n";
+ $_=lc($_);
+ }
+ my $ap=abs_path($_);
+ if ( (! length($ap) ) && length($_))
+ {
+# print "abs path of $_ is empty. bad dir?\n";
+ }
+ $_=$ap;
+ s@i686@i486@g;
+ if ( (! -e $_) && ( -e lc($_)) )
+ {
+# print STDERR "$_ does not exist try lc($_)\n";
+ $_=lc($_);
+ }
+ # kill ..s for prettyness
+ s@/[^/]+/\.\./@/@g;
+ if (! -e $_)
+ {
+# print STDERR "$_ does not exist\n";
+ }
+ return $_;
+}
+
+sub handlelinuxline
+{
+ local($_)=@_;
+ $buildforlinux = 1 if ( /^\s*\$buildforlinux.*1/i);
+ $OptimizerLevel= $1 if (/^\s*\$OptimizerLevel\s+(.+)/i);
+ $SymbolVisibility = $1 if (/^\s*\$SymbolVisibility\s+(.+)/i);
+ $buildforlinux = 1 if ( /^\s*\$buildforlinux.*1/i);
+ &CheckForFileLine($_); # allows linux-specific file includes and excludes
+ &handleconfigline($_); # allow linux-specific #defines
+
+}
+
+
+sub CheckPreprocessorDefs
+{
+ local($_)=@_;
+ if (/^\s*\$PreprocessorDefinitions\s+\"(.*)\"/i)
+ {
+ foreach $_ (split(/[;,]/,$1) )
+ {
+ unless( /\$/ || $define_seen{$_} || /fopen/i)
+ {
+ push(@DEFINES,$_);
+ $define_seen{$_}=1;
+ }
+ }
+ }
+}
+sub handleconfigline
+{
+ # handle a line within a $Configuration block
+ local($_)=@_; # the line
+ if (/^\s*\$AdditionalIncludeDirectories\s+\"(.*)\"/i)
+ {
+ foreach $_ (split(/[;,]/,$1) )
+ {
+ unless( /\$/ || $include_seen{$_} )
+ {
+ push(@INCLUDEDIRS,process_path($_));
+ $include_seen{$_}=1;
+ }
+ }
+ }
+ if (/^\s*\$ConfigurationType\s*\"(.*)\"/)
+ {
+ undef $conf_type;
+ $conf_type="lib" if ($1 =~ /Static Library/i);
+ $conf_type="dll" if ($1 =~ /Dynamic Library/i);
+ $conf_type="exe" if ($1 =~ /Application/i);
+ print STDERR " unknown conf type $1\n" if (! length($conf_type) );
+
+ }
+
+ &CheckPreprocessorDefs($_);
+}
diff --git a/devtools/bin/vpcall.bat b/devtools/bin/vpcall.bat
new file mode 100644
index 0000000..02fe250
--- /dev/null
+++ b/devtools/bin/vpcall.bat
@@ -0,0 +1 @@
+vpc /allgames +everything %*
diff --git a/devtools/bin/vpccrccheck.exe b/devtools/bin/vpccrccheck.exe
new file mode 100644
index 0000000..5a151b0
--- /dev/null
+++ b/devtools/bin/vpccrccheck.exe
Binary files differ
diff --git a/devtools/bin/vpcgames.bat b/devtools/bin/vpcgames.bat
new file mode 100644
index 0000000..d6f81ee
--- /dev/null
+++ b/devtools/bin/vpcgames.bat
@@ -0,0 +1 @@
+vpc +gamedlls /allgames
diff --git a/devtools/bin/vpesign.exe b/devtools/bin/vpesign.exe
new file mode 100644
index 0000000..99011ea
--- /dev/null
+++ b/devtools/bin/vpesign.exe
Binary files differ
diff --git a/devtools/bin/vsdotnetxmlparser.py b/devtools/bin/vsdotnetxmlparser.py
new file mode 100644
index 0000000..e9e643a
--- /dev/null
+++ b/devtools/bin/vsdotnetxmlparser.py
@@ -0,0 +1,218 @@
+
+import re
+import os, ezxmlfile
+
+
+# Until I find a better XML parser, this one acts like xml.parsers.expat but it preserves the \r's and \n's inside
+# attribute strings in .vcproj files.
+class VSDotNetXMLParserError:
+ pass
+
+
+def GetLineNumber( data, filePos ):
+ lines = data.split( '\n' )
+ testOffset = 0
+ for i,x in enumerate( lines ):
+ testOffset += len(x) + 1
+ if testOffset >= filePos:
+ return i+1
+ return -1
+
+
+verbose = 0
+
+class VSDotNetXMLParser:
+ def __init__( self ):
+ self.XmlDeclHandler = None
+ self.StartElementHandler = None
+ self.EndElementHandler = None
+
+ self.reStartElement = re.compile( r'\s*<(?P<blockName>[^ /\t\n\r\f\v>]+)(?P<noAttrs>>)?' )
+ self.reEndElement = re.compile( r'\s*</(?P<blockName>\S+)>' )
+ self.reAttribute = re.compile( r'\s*(?P<attrName>\S+)="(?P<attrValue>.*?)"', re.DOTALL )
+ self.reEndAttributes = re.compile( r'\s*>' )
+ self.reEndAttributesNoSubElements = re.compile( r'\s*(\/|\?)>' )
+
+ def Parse( self, data, final ):
+ curFilePos = 0
+ elementDepth = 0
+ self.__bReadXMLHeader = 0
+
+ # First read the XML header.
+ while 1:
+ m = self.reStartElement.match( data, curFilePos )
+ if m:
+ curFilePos = m.end()
+
+ # Read the element name and get all its attributes.
+ elementName = m.group('blockName')
+ attributes = []
+
+ # No attributes?
+ if m.group('noAttrs') == '>':
+ elementDepth += 1
+ self.__CallElementHandler( elementName, [], 0 )
+ continue
+
+ if verbose:
+ print 'elem: ' + elementName
+
+ while 1:
+ m = self.reAttribute.match( data, curFilePos )
+ if m:
+ if verbose:
+ print 'attr: %s, value: %s' % (m.group('attrName'), m.group('attrValue'))
+ curFilePos = m.end()
+ attributes.append( m.group('attrName') )
+ attributes.append( m.group('attrValue') )
+ continue
+
+ m = self.reEndAttributesNoSubElements.match( data, curFilePos )
+ if m:
+ if verbose:
+ print 'endattr'
+ curFilePos = m.end()
+ self.__CallElementHandler( elementName, attributes, 1 )
+ break
+
+ m = self.reEndAttributes.match( data, curFilePos )
+ if m:
+ if verbose:
+ print 'endattr2'
+ curFilePos = m.end()
+ elementDepth += 1
+ self.__CallElementHandler( elementName, attributes, 0 )
+ break
+ else:
+ raise VSDotNetXMLParserError
+
+ else:
+ m = self.reEndElement.match( data, curFilePos )
+ if m:
+ if verbose:
+ print 'endelem'
+ curFilePos = m.end()
+ elementDepth -= 1
+ self.EndElementHandler( '<end element name not supported>' )
+ else:
+ # When we're done with the file, the depth should be 0.
+ if elementDepth != 0:
+ print 'line %d, depth: %d' % (GetLineNumber( data, curFilePos ), elementDepth)
+ raise VSDotNetXMLParserError
+ break
+
+ # Must at least have a header!
+ if not self.__bReadXMLHeader:
+ raise VSDotNetXMLParserError
+
+
+ def __CallElementHandler( self, elementName, attributes, bEnd ):
+ if self.__bReadXMLHeader:
+ self.StartElementHandler( elementName, attributes )
+ if bEnd:
+ self.EndElementHandler( '<end element name not supported>' )
+ else:
+ # First element must be the XML header.
+ if elementName != '?xml' or not bEnd:
+ raise VSDotNetXMLParserError
+
+ versionString = encodingString = None
+ for(i,a) in enumerate( attributes ):
+ if (i & 1) == 0:
+ if a == 'version':
+ versionString = attributes[i+1]
+ elif a == 'encoding':
+ encodingString = attributes[i+1]
+
+ if not versionString or not encodingString:
+ raise VSDotNetXMLParserError
+
+ self.XmlDeclHandler( versionString, encodingString, 1 )
+ self.__bReadXMLHeader = 1
+
+
+
+def LoadVCProj( filename ):
+ f = open( filename, 'rb' )
+ return ezxmlfile.EZXMLFile( f.read() )
+
+
+def FindInList( theList, elem ):
+ for i,val in enumerate( theList ):
+ if val == elem:
+ return i
+ return -1
+
+
+def IsExcludedFromProjects( e, validProjects ):
+ for c in e.Children:
+ if c.Name == "FileConfiguration":
+ if FindInList( validProjects, c.GetAttributeValue( 'Name' ) ) != -1:
+ if c.GetAttributeValue( 'ExcludedFromBuild' ) == 'TRUE':
+ return 1
+ return 0
+
+
+def StripConfigBlocks_R( e, validProjects ):
+ newChildren = []
+
+ # Strip out unwanted configuration blocks.
+ if e.Name == 'Configuration' or e.Name == 'FileConfiguration':
+ bValid = 0
+ v = e.GetAttributeValue( 'Name' )
+ for p in validProjects:
+ if p == v:
+ bValid = 1
+ break
+
+ if not bValid:
+ return 0
+
+ # Strip out files that are excluded from the validProjects.
+ if e.Name == "File":
+ if IsExcludedFromProjects( e, validProjects ):
+ return 0
+
+
+ # Recurse..
+ newChildren = []
+ for child in e.Children:
+ if StripConfigBlocks_R( child, validProjects ):
+ newChildren.append( child )
+ e.Children = newChildren
+ return 1
+
+
+def RemoveEmptyFilterBlocks_R( e ):
+ if e.Name == "Filter" and len( e.Children ) == 0:
+ return 0
+
+ # Recurse..
+ newChildren = []
+ for child in e.Children:
+ if RemoveEmptyFilterBlocks_R( child ):
+ newChildren.append( child )
+ e.Children = newChildren
+ return 1
+
+
+def WriteSeparateVCProj( f, validProjects, outFilename ):
+ outFile = open( outFilename, 'wb' )
+
+ # Make a copy of f so we're not trashing its data.
+ #f = copy.deepcopy( f )
+
+ # Strip out the source control crap.
+ e = f.GetElement( 'VisualStudioProject' )
+ e.RemoveAttribute( 'SccProjectName' )
+ e.RemoveAttribute( 'SccAuxPath' )
+ e.RemoveAttribute( 'SccLocalPath' )
+ e.RemoveAttribute( 'SccProvider' )
+
+ # Now strip out blocks that are for
+ StripConfigBlocks_R( f.RootElement, validProjects )
+ RemoveEmptyFilterBlocks_R( f.RootElement )
+
+ f.WriteFile( outFile )
+ outFile.close()
+ print "Wrote %s" % outFilename
diff --git a/devtools/bin/vsh_prep.pl b/devtools/bin/vsh_prep.pl
new file mode 100644
index 0000000..8161c49
--- /dev/null
+++ b/devtools/bin/vsh_prep.pl
@@ -0,0 +1,1106 @@
+use String::CRC32;
+BEGIN {use File::Basename; push @INC, dirname($0); }
+require "valve_perl_helpers.pl";
+
+sub WriteHelperVar
+{
+ local( $name ) = shift;
+ local( $min ) = shift;
+ local( $max ) = shift;
+ local( $varname ) = "m_n" . $name;
+ local( $boolname ) = "m_b" . $name;
+ push @outputHeader, "private:\n";
+ push @outputHeader, "\tint $varname;\n";
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\tbool $boolname;\n";
+ push @outputHeader, "#endif\n";
+ push @outputHeader, "public:\n";
+ # int version of set function
+ push @outputHeader, "\tvoid Set" . $name . "( int i )\n";
+ push @outputHeader, "\t{\n";
+ if ( $min != $max )
+ {
+ push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
+ push @outputHeader, "\t\t$varname = i;\n";
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\t\t$boolname = true;\n";
+ push @outputHeader, "#endif\n";
+ }
+ push @outputHeader, "\t}\n";
+ # bool version of set function
+ push @outputHeader, "\tvoid Set" . $name . "( bool i )\n";
+ push @outputHeader, "\t{\n";
+ if ( $min != $max )
+ {
+# push @outputHeader, "\t\tAssert( i >= $min && i <= $max );\n";
+ push @outputHeader, "\t\t$varname = i ? 1 : 0;\n";
+ push @outputHeader, "#ifdef _DEBUG\n";
+ push @outputHeader, "\t\t$boolname = true;\n";
+ push @outputHeader, "#endif\n";
+ }
+ push @outputHeader, "\t}\n";
+}
+
+sub WriteStaticBoolExpression
+{
+ local( $prefix ) = shift;
+ local( $operator ) = shift;
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ if( $i )
+ {
+ push @outputHeader, " $operator ";
+ }
+ local( $name ) = @staticDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ push @outputHeader, "$prefix$boolname";
+ }
+ push @outputHeader, ";\n";
+}
+
+sub WriteDynamicBoolExpression
+{
+ local( $prefix ) = shift;
+ local( $operator ) = shift;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ if( $i )
+ {
+ push @outputHeader, " $operator ";
+ }
+ local( $name ) = @dynamicDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ push @outputHeader, "$prefix$boolname";
+ }
+ push @outputHeader, ";\n";
+}
+
+sub WriteDynamicHelperClasses
+{
+ local( $basename ) = $fxc_filename;
+ $basename =~ s/\.fxc//i;
+ $basename =~ tr/A-Z/a-z/;
+ local( $classname ) = $basename . "_Dynamic_Index";
+ push @outputHeader, "class $classname\n";
+ push @outputHeader, "{\n";
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $name = $dynamicDefineNames[$i];
+ $min = $dynamicDefineMin[$i];
+ $max = $dynamicDefineMax[$i];
+ &WriteHelperVar( $name, $min, $max );
+ }
+ push @outputHeader, "public:\n";
+ push @outputHeader, "\t$classname()\n";
+ push @outputHeader, "\t{\n";
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $min = $dynamicDefineMin[$i];
+ $max = $dynamicDefineMax[$i];
+
+ local( $name ) = @dynamicDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ local( $varname ) = "m_n" . $name;
+ push @outputHeader, "#ifdef _DEBUG\n";
+ if ( $min != $max )
+ {
+ push @outputHeader, "\t\t$boolname = false;\n";
+ }
+ else
+ {
+ push @outputHeader, "\t\t$boolname = true;\n";
+ }
+ push @outputHeader, "#endif // _DEBUG\n";
+ push @outputHeader, "\t\t$varname = 0;\n";
+ }
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "\tint GetIndex()\n";
+ push @outputHeader, "\t{\n";
+ push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
+ foreach $skip (@perlskipcodeindividual)
+ {
+ $skip =~ s/\$/m_n/g;
+# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
+ }
+ push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
+
+ push @outputHeader, "#ifdef _DEBUG\n";
+ if( scalar( @dynamicDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tbool bAllDynamicVarsDefined = ";
+ WriteDynamicBoolExpression( "", "&&" );
+ }
+ if( scalar( @dynamicDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tAssert( bAllDynamicVarsDefined );\n";
+ }
+ push @outputHeader, "#endif // _DEBUG\n";
+
+ if( $spewCombos && scalar( @dynamicDefineNames ) )
+ {
+ push @outputHeader, &CreateCCodeToSpewDynamicCombo();
+ }
+ push @outputHeader, "\t\treturn ";
+ local( $scale ) = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ local( $name ) = @dynamicDefineNames[$i];
+ local( $varname ) = "m_n" . $name;
+ push @outputHeader, "( $scale * $varname ) + ";
+ $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ push @outputHeader, "0;\n";
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "};\n";
+}
+
+sub WriteStaticHelperClasses
+{
+ local( $basename ) = $fxc_filename;
+ $basename =~ s/\.fxc//i;
+ $basename =~ tr/A-Z/a-z/;
+ local( $classname ) = $basename . "_Static_Index";
+ push @outputHeader, "class $classname\n";
+ push @outputHeader, "{\n";
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $name = $staticDefineNames[$i];
+ $min = $staticDefineMin[$i];
+ $max = $staticDefineMax[$i];
+ &WriteHelperVar( $name, $min, $max );
+ }
+ push @outputHeader, "public:\n";
+ push @outputHeader, "\t$classname()\n";
+ push @outputHeader, "\t{\n";
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $min = $staticDefineMin[$i];
+ $max = $staticDefineMax[$i];
+
+ local( $name ) = @staticDefineNames[$i];
+ local( $boolname ) = "m_b" . $name;
+ local( $varname ) = "m_n" . $name;
+
+ push @outputHeader, "#ifdef _DEBUG\n";
+ if ( $min != $max )
+ {
+ push @outputHeader, "\t\t$boolname = false;\n";
+ }
+ else
+ {
+ push @outputHeader, "\t\t$boolname = true;\n";
+ }
+ push @outputHeader, "#endif // _DEBUG\n";
+ push @outputHeader, "\t\t$varname = 0;\n";
+ }
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "\tint GetIndex()\n";
+ push @outputHeader, "\t{\n";
+ push @outputHeader, "\t\t// Asserts to make sure that we aren't using any skipped combinations.\n";
+ foreach $skip (@perlskipcodeindividual)
+ {
+ $skip =~ s/\$/m_n/g;
+# push @outputHeader, "\t\tAssert( !( $skip ) );\n";
+ }
+ push @outputHeader, "\t\t// Asserts to make sure that we are setting all of the combination vars.\n";
+
+ push @outputHeader, "#ifdef _DEBUG\n";
+ if( scalar( @staticDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tbool bAllStaticVarsDefined = ";
+ WriteStaticBoolExpression( "", "&&" );
+
+ }
+ if( scalar( @staticDefineNames ) > 0 )
+ {
+ push @outputHeader, "\t\tAssert( bAllStaticVarsDefined );\n";
+ }
+ push @outputHeader, "#endif // _DEBUG\n";
+
+ if( $spewCombos && scalar( @staticDefineNames ) )
+ {
+ push @outputHeader, &CreateCCodeToSpewStaticCombo();
+ }
+ push @outputHeader, "\t\treturn ";
+ local( $scale ) = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $scale *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ local( $name ) = @staticDefineNames[$i];
+ local( $varname ) = "m_n" . $name;
+ push @outputHeader, "( $scale * $varname ) + ";
+ $scale *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
+ }
+ push @outputHeader, "0;\n";
+ push @outputHeader, "\t}\n";
+ push @outputHeader, "};\n";
+}
+
+sub CreateFuncToSetPerlVars
+{
+ local( $out ) = "";
+
+ $out .= "sub SetPerlVarsFunc\n";
+ $out .= "{\n";
+ $out .= " local( \$combo ) = shift;\n";
+ $out .= " local( \$i );\n";
+ local( $i );
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); \$i++ )
+ {
+ $out .= " \$$dynamicDefineNames[$i] = \$combo % ";
+ $out .= ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) + $dynamicDefineMin[$i];
+ $out .= ";\n";
+ $out .= " \$combo = \$combo / " . ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) . ";\n";
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); \$i++ )
+ {
+ $out .= " \$$staticDefineNames[$i] = \$combo % ";
+ $out .= ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) + $staticDefineMin[$i];
+ $out .= ";\n";
+ $out .= " \$combo = \$combo / " . ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) . ";\n";
+ }
+ $out .= "}\n";
+
+# print $out;
+ eval $out;
+}
+
+# These sections can be interchanged to enable profiling.
+#$ShowTimers = 1;
+#use Time::HiRes;
+#sub SampleTime()
+#{
+# return Time::HiRes::time();
+#}
+
+$ShowTimers = 0;
+sub SampleTime() { return 0; }
+
+$total_start_time = SampleTime();
+
+# NOTE: These must match the same values in macros.vsh!
+$vPos = "v0";
+$vBoneWeights = "v1";
+$vBoneIndices = "v2";
+$vNormal = "v3";
+if( $g_x360 )
+{
+ $vPosFlex = "v4";
+ $vNormalFlex = "v13";
+}
+$vColor = "v5";
+$vSpecular = "v6";
+$vTexCoord0 = "v7";
+$vTexCoord1 = "v8";
+$vTexCoord2 = "v9";
+$vTexCoord3 = "v10";
+$vTangentS = "v11";
+$vTangentT = "v12";
+$vUserData = "v14";
+
+sub ReadInputFileWithLineInfo
+{
+ local( $base_filename ) = shift;
+
+ local( *INPUT );
+ local( @output );
+
+ # Look in the stdshaders directory, followed by the current directory.
+ # (This is for the SDK, since some of its files are under stdshaders).
+ local( $filename ) = $base_filename;
+ if ( !-e $filename )
+ {
+ $filename = "$g_SourceDir\\materialsystem\\stdshaders\\$base_filename";
+ if ( !-e $filename )
+ {
+ die "\nvsh_prep.pl ERROR: missing include file: $filename.\n\n";
+ }
+ }
+
+ open INPUT, "<$filename" || die;
+
+ local( $line );
+ local( $linenum ) = 1;
+ while( $line = <INPUT> )
+ {
+ $line =~ s/\n//g;
+ local( $postfix ) = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+ $postfix .= "; LINEINFO($filename)($linenum)\n";
+ if( $line =~ m/\#include\s+\"(.*)\"/i )
+ {
+ push @output, &ReadInputFileWithLineInfo( $1 );
+ }
+ else
+ {
+ push @output, $line . $postfix;
+ }
+ $linenum++;
+ }
+
+ close INPUT;
+ return @output;
+}
+
+sub ReadInputFileWithoutLineInfo
+{
+ local( $base_filename ) = shift;
+
+ local( *INPUT );
+ local( @output );
+
+ # Look in the stdshaders directory, followed by the current directory.
+ # (This is for the SDK, since some of its files are under stdshaders).
+ local( $filename ) = $base_filename;
+ if ( !-e $filename )
+ {
+ $filename = "$g_SourceDir\\materialsystem\\stdshaders\\$base_filename";
+ if ( !-e $filename )
+ {
+ die "\nERROR: missing include file: $filename.\n\n";
+ }
+ }
+
+ open INPUT, "<$filename" || die;
+
+ local( $line );
+ while( $line = <INPUT> )
+ {
+ if( $line =~ m/\#include\s+\"(.*)\"/i )
+ {
+ push @output, &ReadInputFileWithoutLineInfo( $1 );
+ }
+ else
+ {
+ push @output, $line;
+ }
+ }
+
+ close INPUT;
+ return @output;
+}
+
+sub IsPerl
+{
+ local( $line ) = shift;
+ if( $line =~ m/^\s*sub.*\,/ )
+ {
+ return 0;
+ }
+ if( $line =~ m/^\#include/ ||
+ $line =~ m/^\#define/ ||
+ $line =~ m/^\#undef/ ||
+ $line =~ m/^\#ifdef/ ||
+ $line =~ m/^\#ifndef/ ||
+ $line =~ m/^\#else/ ||
+ $line =~ m/^\#endif/ ||
+ $line =~ m/^\#error/
+ )
+ {
+ return 0;
+ }
+ if( $line =~ m/^\s*if\s*\(/ ||
+ $line =~ m/^\s*else/ ||
+ $line =~ m/^\s*elsif/ ||
+ $line =~ m/^\s*for\s*\(/ ||
+ $line =~ m/^\s*\{/ ||
+ $line =~ m/^sub\s*/ ||
+ $line =~ m/^\s*\}/ ||
+ $line =~ m/^\s*\&/ ||
+ $line =~ m/^\s*\#/ ||
+ $line =~ m/^\s*\$/ ||
+ $line =~ m/^\s*print/ ||
+ $line =~ m/^\s*return/ ||
+ $line =~ m/^\s*exit/ ||
+ $line =~ m/^\s*die/ ||
+ $line =~ m/^\s*eval/ ||
+ $line =~ m/^\s*local/ ||
+ $line =~ m/^\s*my\s+/ ||
+ $line =~ m/^\s*@/ ||
+ $line =~ m/^\s*alloc\s+/ ||
+ $line =~ m/^\s*free\s+/
+ )
+ {
+ return 1;
+ }
+ return 0;
+}
+
+# translate the output into something that takes us back to the source line
+# that we care about in msdev
+sub TranslateErrorMessages
+{
+ local( $origline );
+ while( $origline = shift )
+ {
+ if( $origline =~ m/(.*)\((\d+)\)\s*:\s*(.*)$/i )
+ {
+ local( $filename ) = $1;
+ local( $linenum ) = $2;
+ local( $error ) = $3;
+ local( *FILE );
+ open FILE, "<$filename" || die;
+ local( $i );
+ local( $line );
+ for( $i = 1; $i < $linenum; $i++ )
+ {
+ $line = <FILE>;
+ }
+ if( $line =~ m/LINEINFO\((.*)\)\((.*)\)/ )
+ {
+ print "$1\($2\) : $error\n";
+ my $num = $linenum - 1;
+ print "$filename\($num\) : original error location\n";
+ }
+ close FILE;
+ }
+ else
+ {
+ $origline =~ s/successful compile\!.*//gi;
+ if( !( $origline =~ m/^\s*$/ ) )
+ {
+# print "WTF: $origline\n";
+ }
+ }
+ }
+}
+
+
+sub CountInstructions
+{
+ local( $line );
+ local( $count ) = 0;
+ while( $line = shift )
+ {
+ # get rid of comments
+ $line =~ s/;.*//gi;
+ $line =~ s/\/\/.*//gi;
+ # skip the vs1.1 statement
+ $line =~ s/^\s*vs.*//gi;
+ # if there's any text left, it's an instruction
+ if( $line =~ /\S/gi )
+ {
+ $count++;
+ }
+ }
+ return $count;
+}
+
+
+%compiled = ();
+
+sub UsesRegister
+{
+ my $registerName = shift;
+ my $str = shift;
+
+ # Cache a compiled RE for each register name. This makes UsesRegister about 2.5x faster.
+ if ( !$compiled{$registerName} )
+ {
+ $compiled{$registerName} = qr/\b$registerName\b/;
+ }
+
+ $ret = 0;
+ if( $str =~ /$compiled{$registerName}/gi )
+ {
+ $ret = 1;
+ }
+
+ return $ret;
+}
+
+sub PadString
+{
+ local( $str ) = shift;
+ local( $desiredLen ) = shift;
+ local( $len ) = length $str;
+ while( $len < $desiredLen )
+ {
+ $str .= " ";
+ $len++;
+ }
+ return $str;
+}
+
+sub FixupAllocateFree
+{
+ local( $line ) = shift;
+ $line =~ s/\&AllocateRegister\s*\(\s*\\(\S+)\s*\)/&AllocateRegister( \\$1, \"\\$1\" )/g;
+ $line =~ s/\&FreeRegister\s*\(\s*\\(\S+)\s*\)/&FreeRegister( \\$1, \"\\$1\" )/g;
+ $line =~ s/alloc\s+(\S+)\s*/local( $1 ); &AllocateRegister( \\$1, \"\\$1\" );/g;
+ $line =~ s/free\s+(\S+)\s*/&FreeRegister( \\$1, \"\\$1\" );/g;
+ return $line;
+}
+
+sub TranslateDXKeywords
+{
+ local( $line ) = shift;
+ $line =~ s/\bENDIF\b/endif/g;
+ $line =~ s/\bIF\b/if/g;
+ $line =~ s/\bELSE\b/else/g;
+
+ return $line;
+}
+
+# This is used to make the generated pl files all pretty.
+sub GetLeadingWhiteSpace
+{
+ local( $str ) = shift;
+ if( $str =~ m/^;\S/ || $str =~ m/^; \S/ )
+ {
+ return "";
+ }
+ $str =~ s/^;/ /g; # count a leading ";" as whitespace as far as this is concerned.
+ $str =~ m/^(\s*)/;
+ return $1;
+}
+
+$g_dx9 = 1;
+$g_SourceDir = "..\\..";
+
+while( 1 )
+{
+ $filename = shift;
+
+ if ( $filename =~ m/-source/i )
+ {
+ $g_SourceDir = shift;
+ }
+ elsif( $filename =~ m/-x360/i )
+ {
+ $g_x360 = 1;
+ }
+ else
+ {
+ last;
+ }
+}
+
+$filename =~ s/-----.*$//;
+
+
+#
+# Get the shader binary version number from a header file.
+#
+open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die;
+while( $line = <FILE> )
+{
+ if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ )
+ {
+ $shaderVersion = $1;
+ last;
+ }
+}
+if( !defined $shaderVersion )
+{
+ die "couldn't get shader version from shader_vcs_version.h";
+}
+close FILE;
+
+
+if( $g_x360 )
+{
+ $vshtmp = "vshtmp9_360_tmp";
+}
+else
+{
+ $vshtmp = "vshtmp9_tmp";
+}
+
+if( !stat $vshtmp )
+{
+ mkdir $vshtmp, 0777 || die $!;
+}
+
+# suck in all files, including $include files.
+@input = &ReadInputFileWithLineInfo( $filename );
+
+sub CalcNumCombos
+{
+ local( $i, $numCombos );
+ $numCombos = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
+ {
+ $numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
+ }
+ return $numCombos;
+}
+
+sub CalcNumDynamicCombos
+{
+ local( $i, $numCombos );
+ $numCombos = 1;
+ for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
+ {
+ $numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
+ }
+ return $numCombos;
+}
+
+# READ THE TOP OF THE FILE TO FIND SHADER COMBOS
+foreach $_ ( @input )
+{
+ next if( m/^\s*$/ );
+# last if( !m,^//, );
+ s,^//\s*,,;
+ if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
+ {
+ local( $name, $min, $max );
+ $name = $1;
+ $min = $2;
+ $max = $3;
+# print "\"$name\" \"$min..$max\"\n";
+ if (/\[(.*)\]/)
+ {
+ $platforms=$1;
+ next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
+ next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
+ }
+ push @staticDefineNames, $name;
+ push @staticDefineMin, $min;
+ push @staticDefineMax, $max;
+ }
+ elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
+ {
+ local( $name, $min, $max );
+ $name = $1;
+ $min = $2;
+ $max = $3;
+ if (/\[(.*)\]/)
+ {
+ $platforms=$1;
+ next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
+ next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
+ }
+# print "\"$name\" \"$min..$max\"\n";
+ push @dynamicDefineNames, $name;
+ push @dynamicDefineMin, $min;
+ push @dynamicDefineMax, $max;
+ }
+}
+
+# READ THE WHOLE FILE AND FIND SKIP STATEMENTS
+foreach $_ ( @input )
+{
+ if( m/^\s*\#\s*SKIP\s*\:\s*(.*\S+)\s*\; LINEINFO.*$/ )
+ {
+ $perlskipcode .= "(" . $1 . ")||";
+ push @perlskipcodeindividual, $1;
+ }
+}
+if( defined $perlskipcode )
+{
+ $perlskipcode .= "0";
+ $perlskipcode =~ s/\n//g;
+}
+else
+{
+ $perlskipcode = "0";
+}
+
+#print $perlskipcode . "\n";
+
+
+# Translate the input into a perl program that'll unroll everything and
+# substitute variables.
+while( $inputLine = shift @input )
+{
+ $inputLine =~ s/\n//g;
+ # leave out lines that are only whitespace.
+ if( $inputLine =~ m/^\s*; LINEINFO.*$/ )
+ {
+ next;
+ }
+ local( $inputLineNoLineNum ) = $inputLine;
+ $inputLineNoLineNum =~ s/; LINEINFO.*//gi;
+ if( &IsPerl( $inputLineNoLineNum ) )
+ {
+ $inputLineNoLineNum = &FixupAllocateFree( $inputLineNoLineNum );
+ push @outputProgram, $inputLineNoLineNum . "\n";
+ }
+ else
+ {
+ # make asm lines that have quotes in them not barf.
+ $inputLine =~ s/\"/\\\"/g;
+ $inputLine = &TranslateDXKeywords( $inputLine );
+ push @outputProgram, &GetLeadingWhiteSpace( $inputLine ) . "push \@output, \"" .
+ $inputLine . "\\n\";\n";
+ }
+}
+
+$outputProgram = join "", @outputProgram;
+
+$filename_base = $filename;
+$filename_base =~ s/\.vsh//i;
+
+open DEBUGOUT, ">$vshtmp" . "/$filename_base.pl" || die;
+print DEBUGOUT $outputProgram;
+close DEBUGOUT;
+
+# Make a function called OutputProgram()
+$bigProg = "sub OutputProgram { " . $outputProgram . "}";
+eval( $bigProg );
+
+
+#print $outputProgram;
+
+#push @finalheader, "// hack to force dependency checking\n";
+#push @finalheader, "\#ifdef NEVER\n";
+#push @finalheader, "\#include \"" . $filename_base . "\.vsh\"\n";
+#push @finalheader, "\#include \"..\\..\\devtools\\bin\\vsh_prep.pl\"\n";
+#push @finalheader, "\#endif\n";
+
+%g_TimingBlocks = ();
+$main_start_time = SampleTime();
+
+$numCombos = &CalcNumCombos();
+$numDynamicCombos = &CalcNumDynamicCombos();
+#print "$numCombos total combos\n";
+#print "$numDynamicCombos dynamic combos\n";
+#print $numCombos / $numDynamicCombos . " static combos\n";
+
+# Write out the C++ helper class for picking shader combos
+$fxc_filename = $filename_base;
+&WriteStaticHelperClasses();
+&WriteDynamicHelperClasses();
+
+# Create a subroutine out of $perlskipcode
+$perlskipfunc = "sub SkipCombo { return $perlskipcode; }\n";
+#print $perlskipfunc;
+
+eval $perlskipfunc;
+&CreateFuncToSetPerlVars();
+
+my $incfilename = "$vshtmp/$filename_base" . ".inc";
+
+# Write the inc file that has indexing helpers, etc.
+&WriteFile( $incfilename, join( "", @outputHeader ) );
+
+
+# Run the output program for all the combinations of bones and lights.
+print "$filename_base.vsh\n";
+for( $i = 0; $i < $numCombos; $i++ )
+{
+# print "combo $i\n";
+ &SetPerlVarsFunc( $i );
+ local( $compileFailed );
+ $ret = &SkipCombo;
+ if( !defined $ret )
+ {
+ die "$@\n";
+ }
+ if( $ret )
+ {
+ # skip this combo!
+ $compileFailed = 1;
+ $numSkipped++;
+ next;
+ }
+
+ $start = SampleTime();
+
+ $g_usesPos = 0;
+ $g_usesPosFlex = 0;
+ $g_usesBoneWeights = 0;
+ $g_usesBoneIndices = 0;
+ $g_usesNormal = 0;
+ $g_usesNormalFlex = 0;
+ $g_usesColor = 0;
+ $g_usesSpecular = 0;
+ $g_usesTexCoord0 = 0;
+ $g_usesTexCoord1 = 0;
+ $g_usesTexCoord2 = 0;
+ $g_usesTexCoord3 = 0;
+ $g_usesTangentS = 0;
+ $g_usesTangentT = 0;
+ $g_usesUserData = 0;
+
+ undef @output;
+
+ $g_TimingBlocks{"inner1"} += SampleTime() - $start;
+
+ $eval_start_time = SampleTime();
+ &OutputProgram();
+ $eval_total_time += (SampleTime() - $eval_start_time);
+
+ $start = SampleTime();
+
+ # Strip out comments once so we don't have to do it in all the UsesRegister calls.
+ @stripped = @output;
+ map
+ {
+ $_ =~ s/;.*//gi;
+ $_ =~ s/\/\/.*//gi;
+ } @stripped;
+ my $strippedStr = join( "", @stripped );
+
+ $g_TimingBlocks{"inner2"} += SampleTime() - $start;
+
+ $start = SampleTime();
+
+ # Have to make another pass through after we know which v registers are used. . yuck.
+ $g_usesPos = &UsesRegister( $vPos, $strippedStr );
+ if( $g_x360 )
+ {
+ $g_usesPosFlex = &UsesRegister( $vPosFlex, $strippedStr );
+ $g_usesNormalFlex = &UsesRegister( $vNormalFlex, $strippedStr );
+ }
+ $g_usesBoneWeights = &UsesRegister( $vBoneWeights, $strippedStr );
+ $g_usesBoneIndices = &UsesRegister( $vBoneIndices, $strippedStr );
+ $g_usesNormal = &UsesRegister( $vNormal, $strippedStr );
+ $g_usesColor = &UsesRegister( $vColor, $strippedStr );
+ $g_usesSpecular = &UsesRegister( $vSpecular, $strippedStr );
+ $g_usesTexCoord0 = &UsesRegister( $vTexCoord0, $strippedStr );
+ $g_usesTexCoord1 = &UsesRegister( $vTexCoord1, $strippedStr );
+ $g_usesTexCoord2 = &UsesRegister( $vTexCoord2, $strippedStr );
+ $g_usesTexCoord3 = &UsesRegister( $vTexCoord3, $strippedStr );
+ $g_usesTangentS = &UsesRegister( $vTangentS, $strippedStr );
+ $g_usesTangentT = &UsesRegister( $vTangentT, $strippedStr );
+ $g_usesUserData = &UsesRegister( $vUserData, $strippedStr );
+ undef @output;
+
+ $g_TimingBlocks{"inner2"} += SampleTime() - $start;
+
+ $eval_start_time = SampleTime();
+ # Running OutputProgram generates $outfilename
+ &OutputProgram();
+ $eval_total_time += (SampleTime() - $eval_start_time);
+
+ $start = SampleTime();
+
+ &CheckUnfreedRegisters();
+
+ for( $j = 0; $j < scalar( @output ); $j++ )
+ {
+ # remove whitespace from the beginning of each line.
+ $output[$j] =~ s/^\s+//;
+ # remove LINEINFO from empty lines.
+ $output[$j] =~ s/^; LINEINFO.*//;
+ }
+
+ $g_TimingBlocks{"inner3"} += SampleTime() - $start;
+ $start = SampleTime();
+
+
+ $outfilename_base = $filename_base . "_" . $i;
+
+ # $outfilename is the name of the file generated from executing the perl code
+ # for this shader. This file is generated once per combo.
+ # We will assemble this shader with vsa.exe.
+ $outfilename = "$vshtmp\\" . $outfilename_base . ".tmp";
+
+# $outhdrfilename = "$vshtmp\\" . $outfilename_base . ".h";
+# unlink $outhdrfilename;
+
+ open OUTPUT, ">$outfilename" || die;
+ print OUTPUT @output;
+ close OUTPUT;
+
+ $g_TimingBlocks{"inner4"} += SampleTime() - $start;
+ $start = SampleTime();
+
+ local( $instructionCount ) = &CountInstructions( @output );
+ $g_TimingBlocks{"inner5"} += SampleTime() - $start;
+
+ local( $debug );
+
+ $debug = 1;
+# for( $debug = 1; $debug >= 0; $debug-- )
+ {
+ # assemble the vertex shader
+ unlink "shader$i.o";
+ if( $g_x360 )
+ {
+ $vsa = "..\\..\\x360xdk\\bin\\win32\\vsa";
+ }
+ else
+ {
+ $vsa = "..\\..\\dx9sdk\\utilities\\vsa";
+ }
+ $vsadebug = "$vsa /nologo /Foshader$i.o $outfilename";
+ $vsanodebug = "$vsa /nologo /Foshader$i.o $outfilename";
+
+ $vsa_start_time = SampleTime();
+
+ if( $debug )
+ {
+# print $vsadebug . "\n";
+ @vsaoutput = `$vsadebug 2>&1`;
+# print @vsaoutput;
+ }
+ else
+ {
+ @vsaoutput = `$vsanodebug 2>&1`;
+ }
+
+ $vsa_total_time += SampleTime() - $vsa_start_time;
+
+ $start = SampleTime();
+
+ &TranslateErrorMessages( @vsaoutput );
+
+ $g_TimingBlocks{"inner6"} += SampleTime() - $start;
+
+ push @finalheader, @hdr;
+ }
+}
+
+
+$main_total_time = SampleTime() - $main_start_time;
+
+# stick info about the shaders at the end of the inc file.
+push @finalheader, "static PrecompiledShaderByteCode_t $filename_base" . "_vertex_shaders[] = {\n";
+for( $i = 0; $i < $numCombos; $i++ )
+{
+ $outfilename_base = $filename_base . "_" . $i;
+ push @finalheader, "{ $outfilename_base, sizeof( $outfilename_base ) },\n";
+}
+push @finalheader, "};\n";
+
+
+push @finalheader, "struct $filename_base" . "_VertexShader_t : public PrecompiledShader_t\n";
+push @finalheader, "{\n";
+push @finalheader, "\t$filename_base" . "_VertexShader_t()\n";
+push @finalheader, "\t{\n";
+push @finalheader, "\t\tm_nFlags = 0;\n";
+
+$flags = 0;
+#push @finalheader, "\t\tppVertexShaders = $filename_base" . "_vertex_shaders;\n";
+push @finalheader, "\t\tm_pByteCode = $filename_base" . "_vertex_shaders;\n";
+push @finalheader, "\t\tm_pName = \"$filename_base\";\n";
+push @finalheader, "\t\tm_nShaderCount = " . ( $maxNumBones + 1 ) * $totalFogCombos * $totalLightCombos . ";\n";
+push @finalheader, "\t\tm_nDynamicCombos = m_nShaderCount;\n";
+push @finalheader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n";
+push @finalheader, "\t}\n";
+push @finalheader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n";
+push @finalheader, "\t{\n";
+push @finalheader, "\t\treturn m_pByteCode[shaderID];\n";
+push @finalheader, "\t}\n";
+push @finalheader, "};\n";
+push @finalheader, "static $filename_base" . "_VertexShader_t $filename_base" . "_VertexShaderInstance;\n";
+
+# Write the final header file with the compiled vertex shader programs.
+$finalheadername = "$vshtmp\\" . $filename_base . ".inc";
+#print "writing $finalheadername\n";
+#open FINALHEADER, ">$finalheadername" || die;
+#print FINALHEADER @finalheader;
+#close FINALHEADER;
+
+&MakeDirHier( "shaders/vsh" );
+
+my $vcsName = "";
+if( $g_x360 )
+{
+ $vcsName = $filename_base . ".360.vcs";
+}
+else
+{
+ $vcsName = $filename_base . ".vcs";
+}
+open COMPILEDSHADER, ">shaders/vsh/$vcsName" || die;
+binmode( COMPILEDSHADER );
+
+#
+# Write out the part of the header that we know. . we'll write the rest after writing the object code.
+#
+
+# Pack arguments
+my $sInt = "i";
+my $uInt = "I";
+if ( $g_x360 )
+{
+ # Change arguments to "big endian long"
+ $sInt = "N";
+ $uInt = "N";
+}
+
+my $undecoratedinput = join "", &ReadInputFileWithoutLineInfo( $filename );
+#print STDERR "undecoratedinput: $undecoratedinput\n";
+my $crc = crc32( $undecoratedinput );
+#print STDERR "crc for $filename: $crc\n";
+
+# version
+print COMPILEDSHADER pack $sInt, 4;
+# totalCombos
+print COMPILEDSHADER pack $sInt, $numCombos;
+# dynamic combos
+print COMPILEDSHADER pack $sInt, $numDynamicCombos;
+# flags
+print COMPILEDSHADER pack $uInt, $flags;
+# centroid mask
+print COMPILEDSHADER pack $uInt, 0;
+# reference size
+print COMPILEDSHADER pack $uInt, 0;
+# crc32 of the source code
+print COMPILEDSHADER pack $uInt, $crc;
+
+my $beginningOfDir = tell COMPILEDSHADER;
+
+# Write out a blank directionary. . we'll fill it in later.
+for( $i = 0; $i < $numCombos; $i++ )
+{
+ # offset from beginning of file.
+ print COMPILEDSHADER pack $sInt, 0;
+ # size
+ print COMPILEDSHADER pack $sInt, 0;
+}
+
+my $startByteCode = tell COMPILEDSHADER;
+my @byteCodeStart;
+my @byteCodeSize;
+
+# Write out the shader object code.
+for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
+{
+ my $filename = "shader$shaderCombo\.o";
+ my $filesize = (stat $filename)[7];
+ $byteCodeStart[$shaderCombo] = tell COMPILEDSHADER;
+ $byteCodeSize[$shaderCombo] = $filesize;
+ open SHADERBYTECODE, "<$filename" || die;
+ binmode SHADERBYTECODE;
+ my $bin;
+ my $numread = read SHADERBYTECODE, $bin, $filesize;
+# print "filename: $filename numread: $numread filesize: $filesize\n";
+ close SHADERBYTECODE;
+ unlink $filename;
+
+ print COMPILEDSHADER $bin;
+}
+
+# Seek back to the directory and write it out.
+seek COMPILEDSHADER, $beginningOfDir, 0;
+for( $i = 0; $i < $numCombos; $i++ )
+{
+ # offset from beginning of file.
+ print COMPILEDSHADER pack $sInt, $byteCodeStart[$i];
+ # size
+ print COMPILEDSHADER pack $sInt, $byteCodeSize[$i];
+}
+
+close COMPILEDSHADER;
+
+$total_time = SampleTime() - $total_start_time;
+
+if ( $ShowTimers )
+{
+ print "\n\n";
+ print sprintf( "Main loop time : %0.4f sec, (%0.2f%%)\n", $main_total_time, 100*$main_total_time / $total_time );
+ print sprintf( "Inner1 time : %0.4f sec, (%0.2f%%)\n", $inner1_total_time, 100*$inner1_total_time / $total_time );
+ print sprintf( "VSA time : %0.4f sec, (%0.2f%%)\n", $vsa_total_time, 100*$vsa_total_time / $total_time );
+ print sprintf( "eval() time : %0.4f sec, (%0.2f%%)\n", $eval_total_time, 100*$eval_total_time / $total_time );
+ print sprintf( "UsesRegister time: %0.4f sec, (%0.2f%%)\n", $usesr_total_time, 100*$usesr_total_time / $total_time );
+
+ foreach $key ( keys %g_TimingBlocks )
+ {
+ print sprintf( "$key time: %0.4f sec, (%0.2f%%)\n", $g_TimingBlocks{$key}, 100*$g_TimingBlocks{$key} / $total_time );
+ }
+
+ print sprintf( "Total time : %0.4f sec\n", $total_time );
+}
+
diff --git a/devtools/bin/vtf_flags_convert.pl b/devtools/bin/vtf_flags_convert.pl
new file mode 100644
index 0000000..033e58a
--- /dev/null
+++ b/devtools/bin/vtf_flags_convert.pl
@@ -0,0 +1,80 @@
+
+#
+# Arguments parsing
+#
+
+local $script = $0;
+
+while ( 1 )
+{
+ local $arg = shift;
+ if ( $arg =~ /^-patch$/i )
+ { goto RUN_PATCH; }
+ if ( $arg =~ /^-patchall$/i )
+ { goto RUN_PATCH_ALL; }
+
+ # default mode - forward to -patch:
+ exit system( "dir /s /b *.vtf | perl $script -patchall" );
+}
+
+
+
+
+RUN_PATCH_ALL:
+#
+# ----------- Patch a list of VTF files --------
+#
+
+while ( <> )
+{
+ local $line = $_;
+ $line =~ s/^\s*(.*)\s*$/$1/;
+ PatchVtfFile( $line );
+}
+exit 0;
+
+
+RUN_PATCH:
+#
+# ----------- Patch a VTF file --------
+#
+
+local $filename = shift;
+exit PatchVtfFile( $filename );
+
+sub PatchVtfFile
+{
+
+local *fileptr;
+local $filename = shift;
+local $vtfFlags;
+
+print "$filename ... ";
+`p4 edit "$filename" >nul 2>&1`;
+
+if ( !open( fileptr, "+<$filename" ) )
+{
+ print "ERROR!\n";
+ return 1;
+}
+binmode( fileptr );
+
+seek( fileptr, 5 * 4, 0 );
+read( fileptr, $vtfFlags, 4 );
+$vtfFlags = unpack( "I", $vtfFlags );
+
+# dropping the NOCOMPRESS flag that will be used for SRGB
+# dropping all the removed flags too
+$vtfFlags = $vtfFlags & 0x2E87FFBF; # mask and
+
+seek( fileptr, 5 * 4, 0 );
+print fileptr pack( "I", $vtfFlags );
+
+close( fileptr );
+
+print "ok.\n";
+return 0;
+
+}
+
+
diff --git a/devtools/bin/vtfscrewtree.pl b/devtools/bin/vtfscrewtree.pl
new file mode 100644
index 0000000..89d1765
--- /dev/null
+++ b/devtools/bin/vtfscrewtree.pl
@@ -0,0 +1,83 @@
+sub CreateFile
+{
+ local( $filename ) = shift;
+ local( *FILE );
+
+ open FILE, ">$filename";
+ close FILE;
+}
+
+sub ProcessFile
+{
+ local( $filename ) = shift;
+ local( @fileContents );
+# print "$filename\n";
+ if( $filename =~ /\.vtf/i )
+ {
+ return if( $filename =~ /_normal/i );
+ return if( $filename =~ /_dudv/i );
+ local( $cmd ) = "..\\..\\..\\bin\\vtfscrew \"$filename\" $r $g $b";
+ print $cmd . "\n";
+ system $cmd;
+ }
+}
+
+sub ProcessFileOrDirectory
+{
+ local( $name ) = shift;
+
+# If the file has "." at the end, skip it.
+ if( $name eq "." || $name eq ".." || $name =~ /\.$/ )
+ {
+# print "skipping: $name\n";
+ return;
+ }
+
+# Figure out if it's a file or a directory.
+ if( -d $name )
+ {
+ local( *SRCDIR );
+# print "$name is a directory\n";
+ opendir SRCDIR, $name;
+ local( @dir ) = readdir SRCDIR;
+ closedir SRCDIR;
+
+ local( $item );
+ while( $item = shift @dir )
+ {
+ &ProcessFileOrDirectory( $name . "/" . $item );
+ }
+ }
+ elsif( -f $name )
+ {
+ &ProcessFile( $name );
+ }
+ else
+ {
+ print "$name is neither a file or a directory\n";
+ }
+ return;
+}
+
+$baseDirectory = shift;
+$r = shift;
+$g = shift;
+$b = shift;
+
+if( !$baseDirectory )
+{
+ die "Usage: createvmt.pl baseDir";
+}
+
+print "baseDirectory = \"$baseDirectory\"\n";
+
+opendir SRCDIR, $baseDirectory;
+@dir = readdir SRCDIR;
+closedir SRCDIR;
+
+while( $item = shift @dir )
+{
+ &ProcessFileOrDirectory( "$baseDirectory/$item" );
+}
+
+
diff --git a/devtools/bin/vzip.exe b/devtools/bin/vzip.exe
new file mode 100644
index 0000000..d4f9f7d
--- /dev/null
+++ b/devtools/bin/vzip.exe
Binary files differ
diff --git a/devtools/bin/wtf.pl b/devtools/bin/wtf.pl
new file mode 100644
index 0000000..277bc4d
--- /dev/null
+++ b/devtools/bin/wtf.pl
@@ -0,0 +1,221 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+ # Ensure that we have the MIME::Entity package installed first
+ eval { require MIME::Entity };
+ if ($@) {
+ $ENV{http_proxy}='http://squid.valvesoftware.com/';
+ system('ppm', 'install', 'MIME::Entity');
+ }
+}
+
+use Getopt::Long;
+use Pod::Usage;
+use MIME::Entity;
+use File::Basename;
+use Archive::Zip;
+use FindBin;
+use Win32;
+use strict;
+
+my @NOTIFICATION_LIST = qw([email protected] [email protected]);
+my $LOGMAN_EXE = "$ENV{SystemRoot}\\System32\\logman.exe";
+
+my $log = undef;
+my $help = 0;
+my $man = 0;
+my $collection = "bad";
+my $run_for = 15;
+
+GetOptions("log=s" => \$log,
+ "bad" => sub { $collection = "bad" },
+ "ok" => sub { $collection = "ok" },
+ "runfor=i" => \$run_for,
+ "help|?" => \$help,
+ "man" => \$man) or pod2usage(2);
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+
+if ($log) {
+ SendLog($log);
+}
+else {
+ StartLogging($collection);
+}
+exit 0;
+
+sub SendLog {
+ my $log = shift;
+ my $logname = basename($log, ".blg");
+
+ print "Compressing $log to $logname.zip\n";
+ my $zip = Archive::Zip->new();
+ $zip->addFile($log);
+ $zip->writeToFileNamed("$logname.zip");
+
+ my $user = Win32::LoginName();
+ $user =~ s|^\\valve\\||i;
+
+ my $machine = uc Win32::NodeName();
+
+ print "Sending: $logname.zip from $user\@$machine\n";
+
+ my $message = MIME::Entity->build(Type => "multipart/mixed",
+ From => "$user\@valvesoftware.com",
+ To => join(", ", @NOTIFICATION_LIST),
+ Subject => "WTF: $machine: $logname");
+ $message->attach(Path => "$logname.zip",
+ Type => "binary/octet-stream",
+ Encoding => "base64");
+
+ $message->send("smtp", Server => "exchange3.valvesoftware.com");
+ unlink("$logname.zip");
+}
+
+sub StartLogging {
+ my $collection = shift;
+
+ unless (CheckCollection($collection)) {
+ InstallCollection($collection) || die "Failed to install collection\n";
+ }
+
+ StopCollection($collection);
+ if (StartCollection($collection)) {
+ local $| = 1;
+ print "Collecting samples: ";
+ while($run_for > 0) {
+ print $run_for % 5 ? "." : $run_for;
+ #IsRunningCollection($collection);
+ sleep(1);
+ $run_for--;
+ }
+ print "Done\n";
+ if (StopCollection($collection)) {
+ my $log = FindLog($collection);
+ if ($log) {
+ SendLog($log);
+ }
+ }
+ }
+}
+
+sub CheckCollection {
+ my $collection = shift;
+
+ if (open(my $pipe, "$LOGMAN_EXE query WTF-$collection |")) {
+ while(my $line = <$pipe>) {
+ if ($line =~ /Collection "WTF-$collection" does not exist/) {
+ return;
+ }
+ elsif ($line =~ /Name:\s+WTF-$collection/) {
+ return 1;
+ }
+ }
+ }
+ return;
+}
+
+sub IsRunningCollection {
+ my $collection = shift;
+
+ if (open(my $pipe, "$LOGMAN_EXE query WTF-$collection |")) {
+ while(my $line = <$pipe>) {
+ if ($line =~ /^Status:\s+(\w+)/) {
+ my $status = $1;
+ print "STATUS: $status\n";
+ return 1 if ($status eq 'Running');
+ return 1 if ($status eq 'Pending');
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+sub InstallCollection {
+ my $collection = shift;
+
+ print "Create WTF-$collection collection\n";
+ system("$LOGMAN_EXE", "create", "counter", "WTF-$collection", "-si", 1, "-cf", "$FindBin::Bin\\wtf.txt");
+ return if ($?);
+ return 1;
+}
+
+sub StartCollection {
+ my $collection = shift;
+
+ print "Start WTF-$collection collection\n";
+ eval {
+ system("$LOGMAN_EXE", "start", "WTF-$collection");
+ die "Starting Collection: $!\n" if ($?);
+ };
+ return 1;
+}
+
+sub StopCollection {
+ my $collection = shift;
+
+ print "Stop WTF-$collection collection\n";
+ eval {
+ system("$LOGMAN_EXE", "stop", "WTF-$collection");
+ die "Stopping Collection: $!\n" if ($?);
+ while (IsRunningCollection($collection)) {
+ sleep 1;
+ }
+ };
+ return 1;
+}
+
+sub FindLog {
+ my $collection = shift;
+ if (opendir(my $dirh, "C:\\PerfLogs")) {
+ my @files = sort { (stat("c:\\PerfLogs\\$a"))[9] <=> (stat("c:\\PerfLogs\\$b"))[9] } grep {
+ /^WTF-$collection\_\d+\.blg$/
+ } readdir($dirh);
+ my $log = $files[-1];
+ print "Located latest log: $log\n";
+ return "C:\\PerfLogs\\$log";
+ }
+ print "No log found\n";
+ return;
+}
+
+END {
+ if (IsRunningCollection($collection)) {
+ StopCollection($collection);
+ }
+}
+
+__END__
+
+=head1 NAME
+
+wtf.pl - Grabs a small capture of the performance data for the local machine and sends the information to the VMPI maintainers
+
+=head1 SYNOPSIS
+
+wtf.pl [-runfor <time>] [-help|-?] [-man] -log <log> | -bad | -good
+
+ Options:
+ -bad Captures the data to the "bad" log (default)
+ -good Captures the data to the "good" log
+ -log Specifies the log to send
+ -runfor Specified the amount of time to sample for
+ -help|-? Display command line usage
+ -man Display full documentation
+
+=head1 DESCRIPTION
+
+B<wtf.pl> is for capturing information about your system when VMPI is
+doing something "bad". The default behaviour is to capture 15 seconds
+of data and send the performance log to the VMPI maintainers. You can
+optionally run another capture to show a "good" situation for a
+baseline to compare against.
+
+=head1 BUGS
+
+The logman program that is used by wtf.pl does not support the -rc
+command properly, so I cannot register wtf.pl to automatically send
+the log when the capture ends. Instead I must manually start/wait/stop.
+
+=cut
diff --git a/devtools/bin/wtf.txt b/devtools/bin/wtf.txt
new file mode 100644
index 0000000..2bdf4ef
--- /dev/null
+++ b/devtools/bin/wtf.txt
@@ -0,0 +1,18 @@
+\Browser\*
+\Cache\*
+\LogicalDisk(*)\*
+\Memory\*
+\Network Interface(*)\*
+\Paging File(*)\*
+\PhysicalDisk(*)\*
+\Process(*)\*
+\Processor(*)\*
+\ProcessorPerformance(*)\*
+\PSched Pipe(*)\*
+\Redirector\*
+\Server Work Queues(*)\*
+\Server\*
+\System\*
+\TCP\*
+\Thread(*)\*
+
diff --git a/devtools/bin/xbspinfo.exe b/devtools/bin/xbspinfo.exe
new file mode 100644
index 0000000..ecf2ab2
--- /dev/null
+++ b/devtools/bin/xbspinfo.exe
Binary files differ
diff --git a/devtools/bin/xsync.bat b/devtools/bin/xsync.bat
new file mode 100644
index 0000000..ae4bdb6
--- /dev/null
+++ b/devtools/bin/xsync.bat
@@ -0,0 +1,163 @@
+echo off
+setlocal
+
+rem look for prevention of building zips
+if /i .%4.==.-nobuild. set no_build=yes
+if /i .%4.==.-nobuild. shift /4
+if /i .%3.==.-nobuild. set no_build=yes
+if /i .%3.==.-nobuild. shift /3
+if /i .%2.==.-nobuild. set no_build=yes
+if /i .%2.==.-nobuild. shift /2
+if /i .%1.==.-nobuild. set no_build=yes
+if /i .%1.==.-nobuild. shift /1
+
+rem look for prevention of copying binaries up to the xbox
+if /i .%3.==.-nocopy. set no_copy=yes
+if /i .%3.==.-nocopy. shift /3
+if /i .%2.==.-nocopy. set no_copy=yes
+if /i .%2.==.-nocopy. shift /2
+if /i .%1.==.-nocopy. set no_copy=yes
+if /i .%1.==.-nocopy. shift /1
+
+rem look for stuff that prevents dependencies from being built
+if /i .%2.==.-nodep. set no_dependency=yes
+if /i .%2.==.-nodep. shift /2
+if /i .%1.==.-nodep. set no_dependency=yes
+if /i .%1.==.-nodep. shift /1
+
+rem Deal with all of the different configs
+if /i .%1.==.-all. set do_platform=yes
+if /i .%1.==.-all. set do_hl2=yes
+if /i .%1.==.-all. set do_episodic=yes
+if /i .%1.==.-all. set do_ep2=yes
+if /i .%1.==.-all. set do_tf=yes
+if /i .%1.==.-all. set do_portal=yes
+
+if /i .%1.==.-episodic. set do_episodic=yes
+if /i .%1.==.-ep2. set do_ep2=yes
+if /i .%1.==.-tf. set do_tf=yes
+if /i .%1.==.-portal. set do_portal=yes
+if /i .%1.==.-hl2. set do_hl2=yes
+if /i .%1.==.-platform. set do_platform=yes
+
+rem skip these if no dependencies should be built
+if .%no_dependency%.==.yes. goto START
+if /i .%1.==.-ep2. set do_episodic=yes
+if /i .%1.==.-ep2. set do_hl2=yes
+if /i .%1.==.-episodic. set do_hl2=yes
+if /i .%1.==.-tf. set do_hl2=yes
+if /i .%1.==.-portal. set do_hl2=yes
+set do_platform=yes
+
+:START
+pushd.
+cd %VPROJECT%\..
+set XBCP="%XEDK%\bin\win32\xbcp.exe"
+set ZIPDIR=%TEMP%\xzips
+if not exist %ZIPDIR% mkdir %ZIPDIR%
+
+:PLATFORM
+if not .%do_platform%.==.yes. goto HL2
+
+REM
+REM PLATFORM
+REM
+echo Builing platform zip...
+pushd.
+cd platform
+if not exist %ZIPDIR%\platform mkdir %ZIPDIR%\platform
+if .%no_build%.==.yes. goto PLATFORMCOPY
+if exist %ZIPDIR%\platform\zip0.360.zip del %ZIPDIR%\platform\zip0.360.zip
+makegamedata -q -z %ZIPDIR%\platform\zip0.360.zip
+:PLATFORMCOPY
+if not .%no_copy%.==.yes. %XBCP% /Y %ZIPDIR%\platform\zip0.360.zip xe:\valve\platform\zip0.360.zip
+popd.
+
+:HL2
+if not .%do_hl2%.==.yes. goto EPISODIC
+
+REM
+REM HL2
+REM
+echo Builing hl2 zip...
+pushd.
+cd hl2
+if not exist %ZIPDIR%\hl2 mkdir %ZIPDIR%\hl2
+if .%no_build%.==.yes. goto HL2COPY
+if exist %ZIPDIR%\hl2\zip0.360.zip del %ZIPDIR%\hl2\zip0.360.zip
+makegamedata -q -z %ZIPDIR%\hl2\zip0.360.zip
+:HL2COPY
+if not .%no_copy%.==.yes. %XBCP% /Y %ZIPDIR%\hl2\zip0.360.zip xe:\valve\hl2\zip0.360.zip
+popd.
+
+:EPISODIC
+if not .%do_episodic%.==.yes. goto EP2
+
+REM
+REM EPISODIC
+REM
+echo Builing episodic zip...
+pushd.
+cd episodic
+if not exist %ZIPDIR%\episodic mkdir %ZIPDIR%\episodic
+if .%no_build%.==.yes. goto EPISODICCOPY
+if exist %ZIPDIR%\episodic\zip0.360.zip del %ZIPDIR%\episodic\zip0.360.zip
+makegamedata -q -z %ZIPDIR%\episodic\zip0.360.zip
+:EPISODICCOPY
+if not .%no_copy%.==.yes. %XBCP% /Y %ZIPDIR%\episodic\zip0.360.zip xe:\valve\episodic\zip0.360.zip
+popd.
+
+:EP2
+if not .%do_ep2%.==.yes. goto TF
+
+REM
+REM EP2
+REM
+echo Builing ep2 zip...
+pushd.
+cd ep2
+if not exist %ZIPDIR%\ep2 mkdir %ZIPDIR%\ep2
+if .%no_build%.==.yes. goto EP2COPY
+if exist %ZIPDIR%\ep2\zip0.360.zip del %ZIPDIR%\ep2\zip0.360.zip
+makegamedata -q -z %ZIPDIR%\ep2\zip0.360.zip
+:EP2COPY
+if not .%no_copy%.==.yes. %XBCP% /Y %ZIPDIR%\ep2\zip0.360.zip xe:\valve\ep2\zip0.360.zip
+popd.
+
+:TF
+if not .%do_tf%.==.yes. goto PORTAL
+
+REM
+REM TF
+REM
+echo Builing tf2 zip...
+pushd.
+cd tf
+if not exist %ZIPDIR%\tf mkdir %ZIPDIR%\tf
+if .%no_build%.==.yes. goto TFCOPY
+if exist %ZIPDIR%\tf\zip0.360.zip del %ZIPDIR%\tf\zip0.360.zip
+makegamedata -q -z %ZIPDIR%\tf\zip0.360.zip
+:TFCOPY
+if not .%no_copy%.==.yes. %XBCP% /Y %ZIPDIR%\tf\zip0.360.zip xe:\valve\tf\zip0.360.zip
+popd.
+
+:PORTAL
+if not .%do_portal%.==.yes. goto END
+
+REM
+REM PORTAL
+REM
+echo Builing portal zip...
+pushd.
+cd portal
+if not exist %ZIPDIR%\portal mkdir %ZIPDIR%\portal
+if .%no_build%.==.yes. goto PORTALCOPY
+if exist %ZIPDIR%\portal\zip0.360.zip del %ZIPDIR%\portal\zip0.360.zip
+makegamedata -q -z %ZIPDIR%\portal\zip0.360.zip
+:PORTALCOPY
+if not .%no_copy%.==.yes. %XBCP% /Y %ZIPDIR%\portal\zip0.360.zip xe:\valve\portal\zip0.360.zip
+popd.
+
+:END
+popd.
+endlocal