#!/usr/bin/perl # # Usage: minimized-SDL-crash-fix.pl nvidia_drv.so # # Patches nvidia_drv.so from the NVIDIA Linux/X11 driver distribution, # version 169.12, to avoid a bug that causes crashes when switching to # another virtual console while an SDL program is minimized. Renames # the original file to nvidia_drv.so~ before creating the patched file. use strict; use Digest::MD5 qw(md5_hex); if (@ARGV < 1) { die "Usage: $0 nvidia_drv.so\n"; } my $filename = $ARGV[0]; open F, "<$filename" or die "$filename: $!\n"; binmode F; seek F, 0, 2 or die "seek($filename,0,SEEK_END): $!\n"; my $filesize = tell(F); seek F, 0, 0 or die "seek($filename,0,SEEK_SET): $!\n"; my $data; read(F, $data, $filesize) == $filesize or die "$filename: Short read\n"; close F; die "$filename: Invalid checksum\n" if md5_hex($data) ne "55780dd627bcc5b1549f3d64d4b98dc9"; my $newdata = $data; die "$filename: Invalid data 1\n" if substr($newdata, 0x1CC84, 4) ne "\xC4\xA5\x0C\x00"; $newdata = substr($newdata, 0, 0x1CC84) . "\xC2" . substr($newdata, 0x1CC85); die "$filename: Invalid data 2\n" if substr($newdata, 0xCA570, 0xA0) ne "\x55\x89\xE5\x83\xEC\x2C\x57\x56\x53\x8B\x55\x0C\x8B\x02\x8B\x15" . "\xD0\x2F\x16\x00\x8B\x80\x68\x01\x00\x00\x8B\x7D\x08\x8B\x75\x24" . "\x8B\x14\x90\x89\x55\xE4\x80\x3F\x01\x74\x16\x8B\x47\x10\x83\xC4" . "\xF4\x57\x8B\x80\x74\x01\x00\x00\xFF\xD0\x83\xC4\x10\x89\xC3\xEB" . "\x02\x89\xFB\x8D\x45\xFC\x50\x8D\x45\xF8\x50\x53\x57\xE8\xD6\xB5" . "\xFF\xFF\x8B\x15\xC8\x2F\x16\x00\x8B\x43\x24\x8B\x04\x90\x8B\x40" . "\x28\x8B\x00\x8B\x4D\x0C\x89\x45\xEC\x0F\xB6\x40\x15\x8B\x55\x0C" . "\x8B\x49\x14\x8B\x04\x85\xDC\x2F\x16\x00\xF7\xD0\x09\xC8\x89\x45" . "\xE8\x8B\x42\x54\x83\xC4\x10\x8B\x40\x08\x85\xC0\x74\x0A\x83\x78" . "\x04\x00\x0F\x84\x4F\x02\x00\x00\x0F\xB7\x4D\x14\x0F\xB7\x55\x1C"; my $newdata = substr($newdata, 0, 0xCA59A) . "\x14" . substr($newdata, 0xCA59B, 7) . "\xFF\x90" . substr($newdata, 0xCA5A4, 4) . substr($newdata, 0xCA5AA, 0x27) . "\x85\xC0\x74\x2F\x90\x8B\x00" . substr($newdata, 0xCA5D6, 11) . "\x4A" . substr($newdata, 0xCA5E2); die "$filename: Invalid checksum after patching\n" if md5_hex($newdata) ne "b21120ba0cd1b02b97f9f9f729115dcf"; rename $filename, "$filename~" or die "rename($filename, $filename~): $!\n"; open F, ">$filename" or die "open $filename for writing: $!\n"; binmode F; print F $newdata or die "write to $filename: $!\n"; close F; exit 0;