From: Ant Zucaro Date: Tue, 23 Jun 2015 12:56:37 +0000 (+0000) Subject: Merge branch 'BuddyFriendGuy/fixVolumeReset' into 'master' X-Git-Tag: xonotic-v0.8.1~12 X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fxonotic.git;a=commitdiff_plain;h=97c6fdd825aae064575e394db308d8ceed22fefb;hp=01e628f1e0d7a2e6bdbe976ea8dc859024008469 Merge branch 'BuddyFriendGuy/fixVolumeReset' into 'master' fix volume value preservation bug in NexuizDemoRecorder Symptom: In the original code, the user's original volume value is not preserved (the default behavior is to mute the volume during fast forward) so the program fails to set the correct volume value back -- in fact it sets it to an illegal variable name. Code problem: This bug happens in the case of user choosing to record the demo early on, i.e. the loop enters the second stage right away, so injectAtStart was never executed. Besides, srvLoop and firstLoop seem to do the same thing. Fix: Make sure injectAtStart is executed exactly once. See merge request !12 --- diff --git a/data/font-dejavu.pk3dir/font-dejavu.cfg b/data/font-dejavu.pk3dir/font-dejavu.cfg index 1c8f2bb5..a53420f7 100644 --- a/data/font-dejavu.pk3dir/font-dejavu.cfg +++ b/data/font-dejavu.pk3dir/font-dejavu.cfg @@ -8,5 +8,5 @@ loadfont infobar fonts/DejaVuSansMono,gfx/conchars 8 12 $scr_loadingscreen_barhe loadfont user0 fonts/DejaVuSans-Bold,gfx/vera-sans 12 loadfont user1 fonts/DejaVuSans-Bold,gfx/vera-sans 4 6 8 10 12 14 16 20 24 28 32 $hud_fontsize // csqc font loadfont user2 fonts/DejaVuSans-Bold,gfx/vera-sans 4 6 8 10 12 14 16 20 24 28 32 $hud_fontsize // csqc boldfont -loadfont user3 fonts/DejaVuSans-Bold,gfx/vera-sans 16 +loadfont user3 fonts/DejaVuSans-Bold,gfx/vera-sans 12 16 scoreboard_columns_set diff --git a/data/font-nimbussansl.pk3dir/font-nimbussansl.cfg b/data/font-nimbussansl.pk3dir/font-nimbussansl.cfg index 92320862..11f25d90 100644 --- a/data/font-nimbussansl.pk3dir/font-nimbussansl.cfg +++ b/data/font-nimbussansl.pk3dir/font-nimbussansl.cfg @@ -8,5 +8,5 @@ loadfont infobar fonts/n019004l.pfb,fonts/unifont-5.1.20080907,gfx/vera-sans 8 1 loadfont user0 fonts/n019004l.pfb,fonts/unifont-5.1.20080907,gfx/vera-sans 12 // menu font loadfont user1 fonts/n019004l.pfb,fonts/unifont-5.1.20080907,gfx/vera-sans 4 6 8 10 12 14 16 20 24 28 32 $hud_fontsize // csqc font loadfont user2 fonts/n019004l.pfb,fonts/unifont-5.1.20080907,gfx/vera-sans 4 6 8 10 12 14 16 20 24 28 32 $hud_fontsize // csqc boldfont -loadfont user3 fonts/n019004l.pfb,fonts/unifont-5.1.20080907,gfx/vera-sans 16 // menu boldfont +loadfont user3 fonts/n019004l.pfb,fonts/unifont-5.1.20080907,gfx/vera-sans 12 16 // menu boldfont scoreboard_columns_set diff --git a/misc/tools/progs-analyzer.pl b/misc/tools/progs-analyzer.pl index d0df1c42..73a1e528 100755 --- a/misc/tools/progs-analyzer.pl +++ b/misc/tools/progs-analyzer.pl @@ -191,6 +191,19 @@ use constant DFUNCTION_T => [ [uchar8 => 'parm_size'], ]; +use constant LNOHEADER_T => [ + [int => 'lnotype'], + [int => 'version'], + [int => 'numglobaldefs'], + [int => 'numglobals'], + [int => 'numfielddefs'], + [int => 'numstatements'], +]; + +use constant LNO_T => [ + [int => 'v'], +]; + sub get_section($$$) { my ($fh, $start, $len) = @_; @@ -283,9 +296,8 @@ sub run_nfa($$$$$$) elsif($c->{iscall}) { my $func = $s->{a}; - my $funcid = $progs->{globals}[$func]{v}{int}; last - if $progs->{error_func}{$funcid}; + if $progs->{builtins}{error}{$func}; $ip += 1; } elsif($c->{isjump}) @@ -323,28 +335,32 @@ sub run_nfa($$$$$$) $nfa->($ip, $copy_handler->($state)); } -sub get_constant($$) +sub get_constant($$$) { - my ($progs, $g) = @_; - if($g->{int} == 0) - { - return 0; - } - elsif($g->{int} > 0 && $g->{int} < 8388608) - { - if($g->{int} < length $progs->{strings} && $g->{int} > 0) - { - return str($progs->{getstring}->($g->{int})); - } - else - { - return $g->{int} . "i"; - } - } - else - { - return $g->{float}; + my ($progs, $g, $type) = @_; + + if (!defined $type) { + $type = 'float'; + $type = 'int' + if $g->{int} > 0 && $g->{int} < 8388608; + $type = 'string' + if $g->{int} > 0 && $g->{int} < length $progs->{strings}; } + + return str($progs->{getstring}->($g->{int})) + if $type eq 'string'; + return $g->{float} + if $type eq 'float'; + return "'$g->{float} _ _'" + if $type eq 'vector'; + return "entity $g->{int}" + if $type eq 'entity'; + return ".$progs->{entityfieldnames}[$g->{int}][0]" + if $type eq 'field' and defined $progs->{entityfieldnames}[$g->{int}][0]; + return "$g->{int}i" + if $type eq 'int'; + + return "$type($g->{int})"; } use constant PRE_MARK_STATEMENT => ""; @@ -364,6 +380,20 @@ sub str($) return "\"$str\""; } +sub debugpos($$$) { + my ($progs, $func, $ip) = @_; + my $s = $func->{debugname}; + if ($progs->{cno}) { + my $column = $progs->{cno}[$ip]{v}; + $s =~ s/:/:$column:/; + } + if ($progs->{lno}) { + my $line = $progs->{lno}[$ip]{v}; + $s =~ s/:/:$line:/; + } + return $s; +} + sub disassemble_function($$;$) { my ($progs, $func, $highlight) = @_; @@ -381,7 +411,8 @@ sub disassemble_function($$;$) my $initializer = sub { my ($ofs) = @_; - my $g = get_constant($progs, $progs->{globals}[$ofs]{v}); + # TODO: Can we know its type? + my $g = get_constant($progs, $progs->{globals}[$ofs]{v}, undef); print " = $g" if defined $g; }; @@ -511,7 +542,8 @@ sub disassemble_function($$;$) { print PRE_MARK_STATEMENT; printf INSTRUCTION_FORMAT, '', '', '.WARN'; - printf OPERAND_FORMAT, "$_ (in $func->{debugname})"; + my $pos = debugpos $progs, $func, $ip; + printf OPERAND_FORMAT, "$_ (in $pos)"; print INSTRUCTION_SEPARATOR; } } @@ -850,7 +882,59 @@ sub find_uninitialized_locals($$) } } } - + + my %solid_seen = (); + run_nfa $progs, $func->{first_statement}, do { my $state = -1; \$state; }, + sub + { + my $state = ${$_[0]}; + return \$state; + }, + sub + { + my ($ip, $state) = @_; + return $solid_seen{"$ip $$state"}++; + }, + sub + { + my ($ip, $state, $s, $c) = @_; + + if($s->{op} eq 'ADDRESS') + { + my $field_ptr_ofs = $s->{b}; + my $def = $progs->{globaldef_byoffset}->($field_ptr_ofs); + use Data::Dumper; + if (($def->{globaltype} eq 'read_only' || $def->{globaltype} eq 'const') && + grep { $_ eq 'solid' } @{$progs->{entityfieldnames}[$progs->{globals}[$field_ptr_ofs]{v}{int}]}) + { + # Taking address of 'solid' for subsequent write! + # TODO check if this address is then actually used in STOREP. + $$state = $ip; + } + } + + if($c->{iscall}) + { + # TODO check if the entity passed is actually the one on which solid was set. + my $func = $s->{a}; + if ($progs->{builtins}{setmodel}{$func} || $progs->{builtins}{setmodelindex}{$func} || $progs->{builtins}{setorigin}{$func} || $progs->{builtins}{setsize}{$func}) + { + # All is clean. + $$state = -1; + } + } + + if($c->{isreturn}) + { + if ($$state >= 0) { + ++$warned{$$state}{''}{"Changing .solid without setmodel/setmodelindex/setorigin/setsize breaks area grid linking in Quake [write is here]"}; + ++$warned{$ip}{''}{"Changing .solid without setmodel/setmodelindex/setorigin/setsize breaks area grid linking in Quake [return is here]"}; + } + } + + return 0; + }; + disassemble_function($progs, $func, \%warned) if keys %warned; } @@ -987,7 +1071,7 @@ sub detect_constants($) my $type = $_->{type}; my $name = $progs->{getstring}->($_->{s_name}); $name = '' - if $name eq 'IMMEDIATE' or $name =~ /^\./; + if $name eq 'IMMEDIATE'; # for fteqcc I had: or $name =~ /^\./; $_->{debugname} = $name if $name ne ''; $globalflags[$_->{ofs}] |= GLOBALFLAG_D; @@ -1137,7 +1221,7 @@ sub detect_constants($) } elsif($_->{globaltype} eq 'const') { - $_->{debugname} = get_constant($progs, $progs->{globals}[$_->{ofs}]{v}); + $_->{debugname} = get_constant($progs, $progs->{globals}[$_->{ofs}]{v}, $_->{type}{type}); } else { @@ -1160,15 +1244,40 @@ sub detect_constants($) }; } -sub parse_progs($) +sub parse_progs($$) { - my ($fh) = @_; + my ($fh, $lnofh) = @_; my %p = (); print STDERR "Parsing header...\n"; $p{header} = parse_section $fh, DPROGRAMS_T, 0, undef, 1; + if (defined $lnofh) { + print STDERR "Parsing LNO...\n"; + my $lnoheader = parse_section $lnofh, LNOHEADER_T, 0, undef, 1; + eval { + die "Not a LNOF" + if $lnoheader->{lnotype} != unpack 'V', 'LNOF'; + die "Not version 1" + if $lnoheader->{version} != 1; + die "Not same count of globaldefs" + if $lnoheader->{numglobaldefs} != $p{header}{numglobaldefs}; + die "Not same count of globals" + if $lnoheader->{numglobals} != $p{header}{numglobals}; + die "Not same count of fielddefs" + if $lnoheader->{numfielddefs} != $p{header}{numfielddefs}; + die "Not same count of statements" + if $lnoheader->{numstatements} != $p{header}{numstatements}; + $p{lno} = [parse_section $lnofh, LNO_T, 24, undef, $lnoheader->{numstatements}]; + eval { + $p{lno} = [parse_section $lnofh, LNO_T, 24, undef, $lnoheader->{numstatements} * 2]; + $p{cno} = [splice $p{lno}, $lnoheader->{numstatements}]; + print STDERR "Cool, this LNO even has column number info!\n"; + }; + } or warn "Skipping LNO: $@"; + } + print STDERR "Parsing strings...\n"; $p{strings} = get_section $fh, $p{header}{ofs_strings}, $p{header}{numstrings}; $p{getstring} = sub @@ -1207,6 +1316,7 @@ sub parse_progs($) my $name = $p{getstring}->($g->{s_name}); die "Out of range ofs $g->{ofs} in fielddef $_ (name: \"$name\")" if $g->{ofs} >= $p{header}{entityfields}; + push @{$p{entityfieldnames}[$g->{ofs}]}, $name; } print STDERR "Parsing statements...\n"; @@ -1303,20 +1413,21 @@ sub parse_progs($) } } - print STDERR "Looking for error()...\n"; - $p{error_func} = {}; + print STDERR "Looking for error(), setmodel(), setmodelindex(), setorigin(), setsize()...\n"; + $p{builtins} = { error => {}, setmodel => {}, setmodelindex => {}, setorigin => {}, setsize => {} }; for(@{$p{globaldefs}}) { + my $name = $p{getstring}($_->{s_name}); next - if $p{getstring}($_->{s_name}) ne 'error'; + if not exists $p{builtins}{$name}; my $v = $p{globals}[$_->{ofs}]{v}{int}; next if $v <= 0 || $v >= @{$p{functions}}; my $first = $p{functions}[$v]{first_statement}; next if $first >= 0; - print STDERR "Detected error() at offset $_->{ofs} (builtin #@{[-$first]})\n"; - $p{error_func}{$_->{ofs}} = 1; + print STDERR "Detected $name() at offset $_->{ofs} (builtin #@{[-$first]})\n"; + $p{builtins}{$name}{$_->{ofs}} = 1; } print STDERR "Scanning functions...\n"; @@ -1430,5 +1541,15 @@ sub parse_progs($) } } -open my $fh, '<', $ARGV[0]; -parse_progs $fh; +for my $progs (@ARGV) { + my $lno = "$progs.lno"; + $lno =~ s/\.dat\.lno$/.lno/; + + open my $fh, '<', $progs + or die "$progs: $!"; + + open my $lnofh, '<', $lno + or warn "$lno: $!"; + + parse_progs $fh, $lnofh; +}