diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /devtools/bin | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'devtools/bin')
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 Binary files differnew file mode 100644 index 0000000..ba9522f --- /dev/null +++ b/devtools/bin/LicenseViewed.dll 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 Binary files differnew file mode 100644 index 0000000..d0da70f --- /dev/null +++ b/devtools/bin/UpdateProgress.exe diff --git a/devtools/bin/VProject.exe b/devtools/bin/VProject.exe Binary files differnew file mode 100644 index 0000000..9c64ddf --- /dev/null +++ b/devtools/bin/VProject.exe 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 Binary files differnew file mode 100644 index 0000000..05342c8 --- /dev/null +++ b/devtools/bin/d3dx10_33.dll diff --git a/devtools/bin/d3dx9_33.dll b/devtools/bin/d3dx9_33.dll Binary files differnew file mode 100644 index 0000000..a005f8f --- /dev/null +++ b/devtools/bin/d3dx9_33.dll diff --git a/devtools/bin/dbmon.exe b/devtools/bin/dbmon.exe Binary files differnew file mode 100644 index 0000000..ef8c64a --- /dev/null +++ b/devtools/bin/dbmon.exe diff --git a/devtools/bin/diff.exe b/devtools/bin/diff.exe Binary files differnew file mode 100644 index 0000000..2797ffd --- /dev/null +++ b/devtools/bin/diff.exe diff --git a/devtools/bin/diff3.exe b/devtools/bin/diff3.exe Binary files differnew file mode 100644 index 0000000..9ee2632 --- /dev/null +++ b/devtools/bin/diff3.exe diff --git a/devtools/bin/diffmemstats.exe b/devtools/bin/diffmemstats.exe Binary files differnew file mode 100644 index 0000000..5f4e329 --- /dev/null +++ b/devtools/bin/diffmemstats.exe 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 Binary files differnew file mode 100644 index 0000000..350aee9 --- /dev/null +++ b/devtools/bin/fontmaker.exe diff --git a/devtools/bin/fontmaker.pdb b/devtools/bin/fontmaker.pdb Binary files differnew file mode 100644 index 0000000..ee89fcb --- /dev/null +++ b/devtools/bin/fontmaker.pdb 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 Binary files differnew file mode 100644 index 0000000..747073f --- /dev/null +++ b/devtools/bin/gnu/libiconv2.dll diff --git a/devtools/bin/gnu/libintl3.dll b/devtools/bin/gnu/libintl3.dll Binary files differnew file mode 100644 index 0000000..4f309be --- /dev/null +++ b/devtools/bin/gnu/libintl3.dll diff --git a/devtools/bin/gnu/touch.exe b/devtools/bin/gnu/touch.exe Binary files differnew file mode 100644 index 0000000..b1385cd --- /dev/null +++ b/devtools/bin/gnu/touch.exe diff --git a/devtools/bin/grep.exe b/devtools/bin/grep.exe Binary files differnew file mode 100644 index 0000000..6931618 --- /dev/null +++ b/devtools/bin/grep.exe 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 Binary files differnew file mode 100644 index 0000000..b275e56 --- /dev/null +++ b/devtools/bin/linux/ccache diff --git a/devtools/bin/linux/p4 b/devtools/bin/linux/p4 Binary files differnew file mode 100644 index 0000000..a3c980c --- /dev/null +++ b/devtools/bin/linux/p4 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 Binary files differnew file mode 100644 index 0000000..ede7e38 --- /dev/null +++ b/devtools/bin/makewav.exe diff --git a/devtools/bin/masm.exe b/devtools/bin/masm.exe Binary files differnew file mode 100644 index 0000000..c487faf --- /dev/null +++ b/devtools/bin/masm.exe diff --git a/devtools/bin/mc.exe b/devtools/bin/mc.exe Binary files differnew file mode 100644 index 0000000..c2f9b6d --- /dev/null +++ b/devtools/bin/mc.exe diff --git a/devtools/bin/md5.exe b/devtools/bin/md5.exe Binary files differnew file mode 100644 index 0000000..0e744f0 --- /dev/null +++ b/devtools/bin/md5.exe 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 Binary files differnew file mode 100644 index 0000000..fe038ac --- /dev/null +++ b/devtools/bin/ml.exe diff --git a/devtools/bin/oldfxc.exe b/devtools/bin/oldfxc.exe Binary files differnew file mode 100644 index 0000000..21b640a --- /dev/null +++ b/devtools/bin/oldfxc.exe diff --git a/devtools/bin/osx32/ccache b/devtools/bin/osx32/ccache Binary files differnew file mode 100644 index 0000000..9b40bf9 --- /dev/null +++ b/devtools/bin/osx32/ccache diff --git a/devtools/bin/osx32/protoc b/devtools/bin/osx32/protoc Binary files differnew file mode 100644 index 0000000..f111cb2 --- /dev/null +++ b/devtools/bin/osx32/protoc 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 Binary files differnew file mode 100644 index 0000000..ea2379b --- /dev/null +++ b/devtools/bin/putty/pageant.exe diff --git a/devtools/bin/putty/plink.exe b/devtools/bin/putty/plink.exe Binary files differnew file mode 100644 index 0000000..a27bf36 --- /dev/null +++ b/devtools/bin/putty/plink.exe diff --git a/devtools/bin/putty/pscp.exe b/devtools/bin/putty/pscp.exe Binary files differnew file mode 100644 index 0000000..e511e5b --- /dev/null +++ b/devtools/bin/putty/pscp.exe diff --git a/devtools/bin/putty/psftp.exe b/devtools/bin/putty/psftp.exe Binary files differnew file mode 100644 index 0000000..1f986e7 --- /dev/null +++ b/devtools/bin/putty/psftp.exe 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 Binary files differnew file mode 100644 index 0000000..38b49b6 --- /dev/null +++ b/devtools/bin/putty/putty.exe diff --git a/devtools/bin/putty/putty.hlp b/devtools/bin/putty/putty.hlp Binary files differnew file mode 100644 index 0000000..92cfc98 --- /dev/null +++ b/devtools/bin/putty/putty.hlp diff --git a/devtools/bin/putty/puttycm.exe b/devtools/bin/putty/puttycm.exe Binary files differnew file mode 100644 index 0000000..cfb5ee9 --- /dev/null +++ b/devtools/bin/putty/puttycm.exe diff --git a/devtools/bin/putty/puttygen.exe b/devtools/bin/putty/puttygen.exe Binary files differnew file mode 100644 index 0000000..c548873 --- /dev/null +++ b/devtools/bin/putty/puttygen.exe 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 Binary files differnew file mode 100644 index 0000000..88b081b --- /dev/null +++ b/devtools/bin/robocopy.exe 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 Binary files differnew file mode 100644 index 0000000..db6416f --- /dev/null +++ b/devtools/bin/sed.exe 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 Binary files differnew file mode 100644 index 0000000..c84c55f --- /dev/null +++ b/devtools/bin/signcode.exe diff --git a/devtools/bin/smtpmail.exe b/devtools/bin/smtpmail.exe Binary files differnew file mode 100644 index 0000000..dd8ac1f --- /dev/null +++ b/devtools/bin/smtpmail.exe 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 Binary files differnew file mode 100644 index 0000000..02bbb12 --- /dev/null +++ b/devtools/bin/sscode.exe 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 Binary files differnew file mode 100644 index 0000000..7b32b2a --- /dev/null +++ b/devtools/bin/tee.exe diff --git a/devtools/bin/test_binaries.exe b/devtools/bin/test_binaries.exe Binary files differnew file mode 100644 index 0000000..0bd7b0c --- /dev/null +++ b/devtools/bin/test_binaries.exe 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 Binary files differnew file mode 100644 index 0000000..93371e0 --- /dev/null +++ b/devtools/bin/timeprecise.exe diff --git a/devtools/bin/timethis.exe b/devtools/bin/timethis.exe Binary files differnew file mode 100644 index 0000000..45b5179 --- /dev/null +++ b/devtools/bin/timethis.exe diff --git a/devtools/bin/uniqexe.exe b/devtools/bin/uniqexe.exe Binary files differnew file mode 100644 index 0000000..4164b29 --- /dev/null +++ b/devtools/bin/uniqexe.exe 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 Binary files differnew file mode 100644 index 0000000..e611043 --- /dev/null +++ b/devtools/bin/vpc.exe diff --git a/devtools/bin/vpc.pdb b/devtools/bin/vpc.pdb Binary files differnew file mode 100644 index 0000000..9ead163 --- /dev/null +++ b/devtools/bin/vpc.pdb 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 Binary files differnew file mode 100644 index 0000000..5a151b0 --- /dev/null +++ b/devtools/bin/vpccrccheck.exe 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 Binary files differnew file mode 100644 index 0000000..99011ea --- /dev/null +++ b/devtools/bin/vpesign.exe 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 Binary files differnew file mode 100644 index 0000000..d4f9f7d --- /dev/null +++ b/devtools/bin/vzip.exe 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 Binary files differnew file mode 100644 index 0000000..ecf2ab2 --- /dev/null +++ b/devtools/bin/xbspinfo.exe 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 |