Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

558 lines
11 KiB

  1. sub BackToForwardSlash
  2. {
  3. my( $path ) = shift;
  4. $path =~ s,\\,/,g;
  5. return $path;
  6. }
  7. sub RemoveFileName
  8. {
  9. my( $in ) = shift;
  10. $in = &BackToForwardSlash( $in );
  11. $in =~ s,/[^/]*$,,;
  12. return $in;
  13. }
  14. sub RemovePath
  15. {
  16. my( $in ) = shift;
  17. $in = &BackToForwardSlash( $in );
  18. $in =~ s,^(.*)/([^/]*)$,$2,;
  19. return $in;
  20. }
  21. sub MakeDirHier
  22. {
  23. my( $in ) = shift;
  24. # print "MakeDirHier( $in )\n";
  25. $in = &BackToForwardSlash( $in );
  26. my( @path );
  27. while( $in =~ m,/, ) # while $in still has a slash
  28. {
  29. my( $end ) = &RemovePath( $in );
  30. push @path, $end;
  31. # print $in . "\n";
  32. $in = &RemoveFileName( $in );
  33. }
  34. my( $i );
  35. my( $numelems ) = scalar( @path );
  36. my( $curpath );
  37. for( $i = $numelems - 1; $i >= 0; $i-- )
  38. {
  39. $curpath .= "/" . $path[$i];
  40. my( $dir ) = $in . $curpath;
  41. if( !stat $dir )
  42. {
  43. # print "mkdir $dir\n";
  44. mkdir $dir, 0777;
  45. }
  46. }
  47. }
  48. sub FileExists
  49. {
  50. my $filename = shift;
  51. my @statresult = stat $filename;
  52. my $iswritable = @statresult != 0;
  53. return $iswritable;
  54. }
  55. sub MakeFileWritable
  56. {
  57. my $filename = shift;
  58. if ( &FileExists( $filename ) )
  59. {
  60. chmod 0666, $filename || die;
  61. }
  62. }
  63. sub MakeFileReadOnly
  64. {
  65. my $filename = shift;
  66. chmod 0444, $filename || die;
  67. }
  68. # Run a command and get stdout and stderr to an array
  69. sub RunCommand
  70. {
  71. my $cmd = shift;
  72. # print STDERR "command: $cmd\n";
  73. system "$cmd > cmdout.txt 2>&1" || die;
  74. local( *FILE );
  75. open FILE, "<cmdout.txt" || die;
  76. my @output = <FILE>;
  77. # print STDERR "command output: @output\n";
  78. close FILE;
  79. unlink "cmdout.txt" || die;
  80. return @output;
  81. }
  82. sub PerforceEditOrAdd
  83. {
  84. return;
  85. my $filename = shift;
  86. my $changelistarg = shift;
  87. # Is the file on the client?
  88. my $cmd = "p4 fstat \"$filename\"";
  89. my @p4output = &RunCommand( $cmd );
  90. my $p4output = join "", @p4output;
  91. if( $p4output =~ m/no such file/ )
  92. {
  93. # not on client. . add
  94. my $cmd = "p4 add $changelistarg $filename";
  95. my @p4output = &RunCommand( $cmd );
  96. my $p4output = join "", @p4output;
  97. if( $p4output =~ m/opened for add/ )
  98. {
  99. print $p4output;
  100. return;
  101. }
  102. print "ERROR: $p4output";
  103. return;
  104. }
  105. # The file is known to be on the client at this point.
  106. # Is it open for edit?
  107. if( $p4output =~ m/action edit/ )
  108. {
  109. # Is is open for edit, let's see if it's still different.
  110. # check for opened files that are not different from the revision in the depot.
  111. my $cmd = "p4 diff -sr \"$filename\"";
  112. my @p4output = &RunCommand( $cmd );
  113. my $outputstring = join "", @p4output;
  114. # check for empty string
  115. if( !( $outputstring =~ m/^\s*$/ ) )
  116. {
  117. my $cmd = "p4 revert \"$filename\"";
  118. my @p4output = &RunCommand( $cmd );
  119. my $outputstring = join "", @p4output;
  120. print $outputstring;
  121. return;
  122. }
  123. }
  124. # check for unopened files that are different from the revision in the depot.
  125. my $cmd = "p4 diff -se \"$filename\"";
  126. my @p4output = &RunCommand( $cmd );
  127. my $outputstring = join "", @p4output;
  128. # check for empty string
  129. if( $outputstring =~ m/^\s*$/ )
  130. {
  131. &MakeFileReadOnly( $filename );
  132. return;
  133. }
  134. # We need to edit the file since it is known to be different here.
  135. my $cmd = "p4 edit $changelistarg \"$filename\"";
  136. my @p4output = &RunCommand( $cmd );
  137. my $line;
  138. foreach $line ( @p4output )
  139. {
  140. if( $line =~ m/not on client/ )
  141. {
  142. #print "notonclient...";
  143. print "ERROR: @p4output\n";
  144. return;
  145. }
  146. if( $line =~ m/currently opened for edit/ )
  147. {
  148. return;
  149. }
  150. if( $line =~ m/opened for edit/ )
  151. {
  152. print $line;
  153. }
  154. }
  155. }
  156. sub FileIsWritable
  157. {
  158. local( $filename ) = shift;
  159. local( @statresult ) = stat $filename;
  160. local( $mode, $iswritable );
  161. $mode = oct( $statresult[2] );
  162. $iswritable = ( $mode & 2 ) != 0;
  163. return $iswritable;
  164. }
  165. sub TouchFile
  166. {
  167. my $filename = shift;
  168. if( !&FileExists( $filename ) )
  169. {
  170. if( !open FILE, ">$filename" )
  171. {
  172. die;
  173. }
  174. close FILE;
  175. }
  176. my $now = time;
  177. local( *FILE );
  178. utime $now, $now, $filename;
  179. }
  180. sub FileExistsInPerforce
  181. {
  182. my $filename = shift;
  183. my @output = &RunCommand( "p4 fstat $filename" );
  184. my $line;
  185. foreach $line (@output)
  186. {
  187. if( $line =~ m/no such file/ )
  188. {
  189. return 0;
  190. }
  191. }
  192. return 1;
  193. }
  194. sub PerforceWriteFile
  195. {
  196. my $filename = shift;
  197. my $filecontents = shift;
  198. # my $changelistname = shift;
  199. # Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
  200. # my $changelistnumber = `valve_p4_create_changelist.cmd . \"$changelistname\"`;
  201. # Get rid of the newline
  202. # $changelistnumber =~ s/\n//g;
  203. # my $changelistarg = "";
  204. # if( $changelistnumber != 0 )
  205. # {
  206. # $changelistarg = "-c $changelistnumber"
  207. # }
  208. # Make the target vcs writable if it exists
  209. MakeFileWritable( $filename );
  210. # Write the file.
  211. local( *FP );
  212. open FP, ">$filename";
  213. print FP $filecontents;
  214. close FP;
  215. # Do whatever needs to happen with perforce for this file.
  216. # &PerforceEditOrAdd( $filename, $changelistarg );
  217. }
  218. sub WriteFile
  219. {
  220. my $filename = shift;
  221. my $filecontents = shift;
  222. # Make the target vcs writable if it exists
  223. MakeFileWritable( $filename );
  224. # Write the file.
  225. local( *FP );
  226. open FP, ">$filename";
  227. print FP $filecontents;
  228. close FP;
  229. }
  230. sub PrintCleanPerforceOutput
  231. {
  232. my $line;
  233. while( $line = shift )
  234. {
  235. if( $line =~ m/currently opened/i )
  236. {
  237. next;
  238. }
  239. if( $line =~ m/already opened for edit/i )
  240. {
  241. next;
  242. }
  243. if( $line =~ m/also opened/i )
  244. {
  245. next;
  246. }
  247. if( $line =~ m/add of existing file/i )
  248. {
  249. next;
  250. }
  251. print $line;
  252. }
  253. }
  254. # HACK!!!! Need to pass something in to do this rather than hard coding.
  255. sub NormalizePerforceFilename
  256. {
  257. my $line = shift;
  258. # remove newlines.
  259. $line =~ s/\n//;
  260. # downcase.
  261. $line =~ tr/[A-Z]/[a-z]/;
  262. # backslash to forwardslash
  263. $line =~ s,\\,/,g;
  264. # for inc files HACK!
  265. $line =~ s/^.*(fxctmp9.*)/$1/i;
  266. $line =~ s/^.*(vshtmp9.*)/$1/i;
  267. # for vcs files. HACK!
  268. $line =~ s,^.*game/hl2/shaders/,,i;
  269. return $line;
  270. }
  271. sub MakeSureFileExists
  272. {
  273. local( $filename ) = shift;
  274. local( $testexists ) = shift;
  275. local( $testwrite ) = shift;
  276. local( @statresult ) = stat $filename;
  277. if( !@statresult && $testexists )
  278. {
  279. die "$filename doesn't exist!\n";
  280. }
  281. local( $mode, $iswritable );
  282. $mode = oct( $statresult[2] );
  283. $iswritable = ( $mode & 2 ) != 0;
  284. if( !$iswritable && $testwrite )
  285. {
  286. die "$filename isn't writable!\n";
  287. }
  288. }
  289. sub LoadShaderListFile_GetShaderType
  290. {
  291. my $shadername = shift;
  292. my $shadertype;
  293. if( $shadername =~ m/\.vsh/i )
  294. {
  295. $shadertype = "vsh";
  296. }
  297. elsif( $shadername =~ m/\.psh/i )
  298. {
  299. $shadertype = "psh";
  300. }
  301. elsif( $shadername =~ m/\.fxc/i )
  302. {
  303. $shadertype = "fxc";
  304. }
  305. else
  306. {
  307. die;
  308. }
  309. return $shadertype;
  310. }
  311. sub LoadShaderListFile_GetShaderSrc
  312. {
  313. my $shadername = shift;
  314. if ( $shadername =~ m/^(.*)-----/i )
  315. {
  316. return $1;
  317. }
  318. else
  319. {
  320. return $shadername;
  321. }
  322. }
  323. sub LoadShaderListFile_GetShaderBase
  324. {
  325. my $shadername = shift;
  326. if ( $shadername =~ m/-----(.*)$/i )
  327. {
  328. return $1;
  329. }
  330. else
  331. {
  332. my $shadertype = &LoadShaderListFile_GetShaderType( $shadername );
  333. $shadername =~ s/\.$shadertype//i;
  334. return $shadername;
  335. }
  336. }
  337. sub LoadShaderListFile
  338. {
  339. my $inputbase = shift;
  340. my @srcfiles;
  341. &MakeSureFileExists( "$inputbase.txt", 1, 0 );
  342. open SHADERLISTFILE, "<$inputbase.txt" || die;
  343. my $line;
  344. while( $line = <SHADERLISTFILE> )
  345. {
  346. $line =~ s/\/\/.*$//; # remove comments "//..."
  347. $line =~ s/^\s*//; # trim leading whitespace
  348. $line =~ s/\s*$//; # trim trailing whitespace
  349. next if( $line =~ m/^\s*$/ );
  350. if( $line =~ m/\.fxc/ || $line =~ m/\.vsh/ || $line =~ m/\.psh/ )
  351. {
  352. my $shaderbase = &LoadShaderListFile_GetShaderBase( $line );
  353. if( $ENV{"DIRECTX_FORCE_MODEL"} =~ m/^30$/i ) # forcing all shaders to be ver. 30
  354. {
  355. my $targetbase = $shaderbase;
  356. $targetbase =~ s/_ps2x/_ps30/i;
  357. $targetbase =~ s/_ps20b/_ps30/i;
  358. $targetbase =~ s/_ps20/_ps30/i;
  359. $targetbase =~ s/_vs20/_vs30/i;
  360. $targetbase =~ s/_vsxx/_vs30/i;
  361. push @srcfiles, ( $line . "-----" . $targetbase );
  362. }
  363. else
  364. {
  365. if( $shaderbase =~ m/_ps2x/i )
  366. {
  367. my $targetbase = $shaderbase;
  368. $targetbase =~ s/_ps2x/_ps20/i;
  369. push @srcfiles, ( $line . "-----" . $targetbase );
  370. $targetbase = $shaderbase;
  371. $targetbase =~ s/_ps2x/_ps20b/i;
  372. push @srcfiles, ( $line . "-----" . $targetbase );
  373. }
  374. elsif( $shaderbase =~ m/_vsxx/i )
  375. {
  376. my $targetbase = $shaderbase;
  377. $targetbase =~ s/_vsxx/_vs11/i;
  378. push @srcfiles, ( $line . "-----" . $targetbase );
  379. $targetbase = $shaderbase;
  380. $targetbase =~ s/_vsxx/_vs20/i;
  381. push @srcfiles, ( $line . "-----" . $targetbase );
  382. }
  383. else
  384. {
  385. push @srcfiles, ( $line . "-----" . $shaderbase );
  386. }
  387. }
  388. }
  389. }
  390. close SHADERLISTFILE;
  391. return @srcfiles;
  392. }
  393. sub ReadInputFileWithIncludes
  394. {
  395. local( $filename ) = shift;
  396. # print STDERR "ReadInputFileWithIncludes: $filename\n";
  397. local( *INPUT );
  398. local( $output );
  399. # print STDERR "before open\n";
  400. open INPUT, "<$filename" || die;
  401. # print STDERR "after open\n";
  402. local( $line );
  403. while( $line = <INPUT> )
  404. {
  405. # print STDERR $line;
  406. if( $line =~ m/\#include\s+\"(.*)\"/i )
  407. {
  408. $output.= ReadInputFileWithIncludes( $1 );
  409. }
  410. else
  411. {
  412. $output .= $line;
  413. }
  414. }
  415. close INPUT;
  416. return $output;
  417. }
  418. sub GetCRCFromSourceFile
  419. {
  420. my $filename = shift;
  421. my $data = &ReadInputFileWithIncludes( $filename );
  422. # print STDERR $data;
  423. $crc = crc32( $data );
  424. # print STDERR "GetCRCFromSourceFile: $crc\n";
  425. return $crc;
  426. }
  427. sub GetCRCFromVCSFile
  428. {
  429. my $filename = shift;
  430. # print STDERR "GetCRCFromVCSFile $filename\n";
  431. local( *FP );
  432. open FP, "<$filename" || die "GetCRCFromVCSFile: can't open file $filename\n";
  433. binmode( FP );
  434. # unpack arguments
  435. my $sInt = "i";
  436. my $uInt = "I";
  437. if( $filename =~ m/\.360\./ )
  438. {
  439. # Change arguments to "big endian long"
  440. $sInt = "N";
  441. $uInt = "N";
  442. }
  443. my $header;
  444. read FP, $header, 7 * 4 || die "updateshaders.pl:GetCRCFromVCSFile: can't read header for $filename\n";
  445. my $version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc;
  446. ($version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc) = unpack "$sInt$sInt$sInt$uInt$uInt$uInt$uInt", $header;
  447. unless( $version == 4 || $version == 5 || $version == 6 )
  448. {
  449. print STDERR "ERROR: GetCRCFromVCSFile: $filename is version $version\n";
  450. return 0;
  451. }
  452. # print STDERR "version: $version\n";
  453. # print STDERR "numCombos: $numCombos\n";
  454. # print STDERR "numDynamicCombos: $numDynamicCombos\n";
  455. # print STDERR "flags: $flags\n";
  456. # print STDERR "centroidMask: $centroidMask\n";
  457. # print STDERR "refSize: $refSize\n";
  458. # print STDERR "GetCRCFromVCSFile: $crc\n";
  459. close( FP );
  460. return $crc;
  461. }
  462. sub CheckCRCAgainstTarget
  463. {
  464. my $srcFileName = shift;
  465. my $vcsFileName = shift;
  466. my $warn = shift;
  467. # Make sure both files exist.
  468. # print STDERR "$srcFileName doesn't exist\n" if( !( -e $srcFileName ) );
  469. # print STDERR "$vcsFileName doesn't exist\n" if( !( -e $vcsFileName ) );
  470. if( !( -e $srcFileName ) )
  471. {
  472. if( $warn )
  473. {
  474. print "$srcFileName missing\n";
  475. }
  476. return 0;
  477. }
  478. if( !( -e $vcsFileName ) )
  479. {
  480. if( $warn )
  481. {
  482. print "$vcsFileName missing\n";
  483. }
  484. return 0;
  485. }
  486. # print STDERR "CheckCRCAgainstTarget( $srcFileName, $vcsFileName );\n";
  487. # print STDERR "vcsFileName: $vcsFileName\n";
  488. # print STDERR "vcsFileName: $srcFileName\n";
  489. my $vcsCRC = &GetCRCFromVCSFile( $vcsFileName );
  490. my $srcCRC = &GetCRCFromSourceFile( $srcFileName );
  491. if( $warn && ( $vcsCRC != $srcCRC ) )
  492. {
  493. print "$vcsFileName checksum ($vcsCRC) != $srcFileName checksum: ($srcCRC)\n";
  494. }
  495. # return 0; # use this to skip crc checking.
  496. # if( $vcsCRC == $srcCRC )
  497. # {
  498. # print STDERR "CRC passed for $srcFileName $vcsFileName $vcsCRC\n";
  499. # }
  500. return $vcsCRC == $srcCRC;
  501. }
  502. 1;