#!/usr/bin/perl use strict; use warnings; # pokeFile # This script edits a binary file by replacing the bytes at specified offsets # with the supplied values. # The name 'pokeFile' is supposed to suggest the 'poke' command of BASIC # The first command-line arg is the name of the file to be edited # The remaining args supplies an array of alternating offsets and values # For example: # pokeFile myDataFile 53 0x67 105 0x72 # would replace whatever is at byte-offset 53 with the value 0x67 # and whatever is at byte-offset 105 with the value 0x72 # Offsets and values can be given in decimal, octal, or hexadecimal # (in the above example, the offsets were given in decimal and the values in hex # but that was just for clarity) # # Cameron Hayne (macdev@hayne.net) August 2006 my $scriptName = "pokeFile"; if (scalar(@ARGV) < 3) { die "Usage: $scriptName filename offset1 value1 [offset2 value2 ...]\n"; } my $verbose = 1; my $filename = shift @ARGV; die "Missing value\n" if (scalar(@ARGV) % 2 != 0); my %values = @ARGV; sub convertToDec($) { my ($value) = @_; if ($value =~ /^0/) { return oct($value); # does both oct and hex } else { return $value; } } use Fcntl qw(:seek); open(FILE, "+<$filename") or die "Can't open file $filename: $!\n"; foreach my $offset (sort keys(%values)) { my $value = $values{$offset}; my $decOffset = convertToDec($offset); my $decValue = convertToDec($value); my $oldValue; if ($verbose) { my $numBytesToRead = 1; seek(FILE, $decOffset, SEEK_SET) or die "seek failed: $!"; read(FILE, $oldValue, $numBytesToRead) == $numBytesToRead or die "Failed to read value from file: $!\n"; $oldValue = unpack("C", $oldValue); } seek(FILE, $decOffset, SEEK_SET) or die "seek failed: $!"; print FILE pack("C", $decValue) or die "Failed to write value into file: $!\n"; if ($verbose) { printf("Offset $offset: 0x%x (was 0x%x)\n", $decValue, $oldValue); } } close(FILE);