]> icculus.org git repositories - divverent/nexuiz.git/blob - misc/demotc.pl
add a trivial patch to write BSP version 46 again
[divverent/nexuiz.git] / misc / demotc.pl
1 #!/usr/bin/perl
2
3 # Fake demo "cutting" tool
4 # works by looking for time codes in the demo
5 # and injecting playback speed commands
6
7 # usage:
8 #   ./demotc.pl infile outfile tc0 tc1 - cuts the demo file for playback
9 #   ./demotc.pl infile outfile tc0 tc1 --capture - cuts the demo file for video capture (it will automatically write a dpvideo001.avi file of the selected time range when playing)
10 #   ./demotc.pl infile pattern - looks for a pattern, prints parentheses matches
11
12 use strict;
13 use warnings;
14
15 sub sanitize($)
16 {
17         my ($str) = @_;
18         $str =~ y/\000-\037//d;
19         return $str;
20 }
21
22 # opening the files
23
24 die "Usage: $0 infile outfile tc_start tc_end [--capture], or $0 infile pattern"
25         if @ARGV != 2 && @ARGV != 4 && @ARGV != 5;
26 my ($in, $out, $tc0, $tc1, $capture) = (@ARGV, undef, undef, undef);
27
28 $in ne $out
29         or die "Input and output file may not be the same!";
30
31 open my $infh, "<", $in
32         or die "open $in: $!";
33 binmode $infh;
34
35 my $outfh;
36 if(defined $tc0) # cutting
37 {
38         open $outfh, ">", $out
39                 or die "open $out: $!";
40         binmode $outfh;
41 }
42
43 # 1. CD track
44
45 $/ = "\012";
46 my $cdtrack = <$infh>;
47 print $outfh $cdtrack if $outfh;
48
49 # 2. packets
50
51 my $tc = 0;
52
53 my $first = 1;
54 my $demo_started = 0;
55 my $demo_stopped = 0;
56 my $inject_buffer = "";
57
58 for(;;)
59 {
60         last
61                 unless 4 == read $infh, my $length, 4;
62         $length = unpack("V", $length);
63         die "Invalid demo packet"
64                 unless 12 == read $infh, my $angles, 12;
65         die "Invalid demo packet"
66                 unless $length == read $infh, my($data), $length;
67         
68         if(substr($data, 0, 1) eq "\007") # svc_time
69         {
70                 $tc = unpack "f", substr $data, 1, 4;
71         }
72
73         if(defined $tc0)
74         {
75                 if($first)
76                 {
77                         $inject_buffer = "\011\nslowmo 100\n\000";
78                         $first = 0;
79                 }
80                 if($demo_started < 1 && $tc > $tc0 - 50)
81                 {
82                         $inject_buffer = "\011\nslowmo 10\n\000";
83                         $demo_started = 1;
84                 }
85                 if($demo_started < 2 && $tc > $tc0 - 5)
86                 {
87                         $inject_buffer = "\011\nslowmo 1\n\000";
88                         $demo_started = 2;
89                 }
90                 if($demo_started < 3 && $tc > $tc0)
91                 {
92                         if($capture)
93                         {
94                                 $inject_buffer = "\011\ncl_capturevideo 1\n\000";
95                         }
96                         else
97                         {
98                                 $inject_buffer = "\011\nslowmo 0; defer 1 \"slowmo 1\"\n\000";
99                         }
100                         $demo_started = 3;
101                 }
102                 if(!$demo_stopped && $tc > $tc1)
103                 {
104                         if($capture)
105                         {
106                                 $inject_buffer = "\011\ncl_capturevideo 0; defer 0.5 \"disconnect\"\n\000";
107                         }
108                         else
109                         {
110                                 $inject_buffer = "\011\ndefer 0.5 \"disconnect\"\n\000";
111                         }
112                         $demo_stopped = 1;
113                 }
114         }
115         else
116         {
117                 if(my @l = ($data =~ /$out/))
118                 {
119                         print "$tc:";
120                         for(@l)
121                         {
122                                 print " \"", sanitize($_), "\"";
123                         }
124                         print "\n";
125                 }
126         }
127         
128         next unless $outfh;
129         if(length($data . $inject_buffer) < 65536)
130         {
131                 $data .= $inject_buffer;
132                 $inject_buffer = "";
133         }
134         print $outfh pack("V", length $data);
135         print $outfh $angles;
136         print $outfh $data;
137 }
138
139 close $outfh if $outfh;
140 close $infh;