line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
# vim: set sw=2 expandtab : # |
3
|
|
|
|
|
|
|
# Master version is at https://developer.berlios.de/projects/games-hack/ |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
package Games::Hack::Patch::i686; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
$VERSION=0.52; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
require Exporter; |
10
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
11
|
|
|
|
|
|
|
@EXPORT = qw(GetNOP); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub GetNOP |
17
|
|
|
|
|
|
|
{ |
18
|
8
|
|
|
8
|
1
|
3096
|
my($adr_start, $adr_end, $disass)=@_; |
19
|
8
|
|
|
|
|
13
|
my($binary, $diff); |
20
|
|
|
|
|
|
|
|
21
|
8
|
|
|
|
|
21
|
$binary=""; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
### Floating point store? Stores always %ST(0). |
24
|
8
|
100
|
|
|
|
48
|
if ($disass =~ m#^f[bi]?st(p)?[sl]? #) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
25
|
|
|
|
|
|
|
{ |
26
|
3
|
100
|
|
|
|
12
|
if ($1) |
27
|
|
|
|
|
|
|
{ |
28
|
|
|
|
|
|
|
# If the "Pop" flag is given in the "fst" ("floating point store") |
29
|
|
|
|
|
|
|
# operation, we need to clean the floating point stack. |
30
|
|
|
|
|
|
|
# We use the "ffreep st(0)" instruction, . |
31
|
2
|
|
|
|
|
3
|
$binary .= "\xdf\xc0"; |
32
|
|
|
|
|
|
|
|
33
|
2
|
|
|
|
|
5
|
$adr_start += 2; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
# Rest gets done by jump. |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
# Popping values from the stack |
38
|
|
|
|
|
|
|
elsif ($disass =~ m#^pop#) |
39
|
|
|
|
|
|
|
{ |
40
|
|
|
|
|
|
|
# increment esp; rest done by jump. |
41
|
|
|
|
|
|
|
# is there a 64bit pop? |
42
|
1
|
|
|
|
|
3
|
$binary .= "\x83\xc4\x04"; |
43
|
1
|
|
|
|
|
2
|
$adr_start += 3; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
### Integer move or direct modification |
46
|
|
|
|
|
|
|
elsif ($disass =~ m#^(mov|or|and)#) |
47
|
|
|
|
|
|
|
{ |
48
|
|
|
|
|
|
|
# done by jump. |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
else |
51
|
|
|
|
|
|
|
{ |
52
|
2
|
|
|
|
|
21
|
warn "Unknown instruction '" . $disass . "', patching unsafe!"; |
53
|
2
|
|
|
|
|
11
|
return undef; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
### short jump |
58
|
6
|
100
|
|
|
|
16
|
if (($diff=$adr_end-$adr_start) >= 2) |
59
|
|
|
|
|
|
|
{ |
60
|
|
|
|
|
|
|
# The opcode needs two bytes; these are already consumed, and so the jump |
61
|
|
|
|
|
|
|
# distance has to be reduced. |
62
|
4
|
|
|
|
|
41
|
$binary .= "\xeb" . pack("C", $diff-2); |
63
|
4
|
|
|
|
|
6
|
$adr_end=$adr_start; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
### NOP. |
67
|
|
|
|
|
|
|
# That should never be needed ... all instructions involving memory access |
68
|
|
|
|
|
|
|
# (even via a register) have at least 2 bytes. |
69
|
|
|
|
|
|
|
# (If some value would be persistently stored in a register, we wouldn't |
70
|
|
|
|
|
|
|
# find it by looking at the memory contents.) |
71
|
6
|
100
|
|
|
|
19
|
$binary .= "\x90" x $diff |
72
|
|
|
|
|
|
|
if ($diff=$adr_end-$adr_start) >= 1; |
73
|
|
|
|
|
|
|
|
74
|
6
|
|
|
|
|
21
|
return $binary; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
__END__ |