Почитал первый файл. Внес в него комментарии. Вроде все ясно:
Код:
#!/usr/bin/perl
# Функция readi считывает 4 байта как единое число
sub readi($) {
my $f = shift;
my $a= 0;
my $b=0;
my $c=0;
my $d=0;
read($f, $a, 1);
read($f, $b, 1);
read($f, $c, 1);
read($f, $d, 1);
return ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24);
}
# имя файла - первый аргумент коммандной строки
$fn = shift;
#значение по умолчанию
if (!$fn) {
$fn = "test.lgn";
}
open(C, $fn) || die "Can't open character file: $!!\n";
#Работаем с открытым файлом *.lgn в бинароном режиме
binmode(C);
# id1 - второй аргумент коммандной строки
$id1 = shift;
# id2 - третий аргумент коммандной строки
$id2 = shift;
#значение по умолчанию
if (!$id1 && !$id2) {
$id1 = 0xFE72C55B;
$id2 = 0;
}
#видимо, по адресу 0x104 в файле .lgn находится количество .a2c файлов
seek(C, 0x104, 0);
my $c = readi(C);
$found = 0;
#print("$c characters total\n");
#цикл перебирает подряд идущие id1,id2 персонажей с логина и сравнивает id1,id2 с теми, что были даны в качестве аргументов коммандной строки
for ($i = 0; $i < $c; ++$i) {
$i1 = readi(C);
$i2 = readi(C);
#Переводим числа в соответствующий 16_ти ричный формат
$i1h = sprintf("0x%.8X",$i1);
$i2h = sprintf("0x%.8X",$i2);
$id1h = sprintf("0x%.8X",$id1);
$id2h = sprintf("0x%.8X",$id2);
# print("$id1h, $id2h -- $i1h, $i2h $i,$c\n");
if (($i1 == $id1) && ($i2 == $id2)) {
$found = 1;
last;
}
}
if (!$found) { die "Character ($id1, $id2) not found!\n"; }
#по адресу 0x188 находятся данные о смещениях относительно 0x234 и размерах файлов a2c соответствующих персонажей
seek(C, 0x188, 0);
$offs = 0x234;
#в каждом блоке по 4 байта хранится информация о том, сколько занимает a2c с текущим порядковым номером
for ($j = 0; $j < $i; ++$j) {
$offs += readi(C);
}
#итого к 0x234 прибавили размеры всех предыдущих персонажей - это получилось $offs - смещение относительно начала файла - тут начинается .a2c. Считаем в $sz размер a2c файла, который отвечает нашим id1, id2
$sz = readi(C);
seek(C, $offs, 0);
read(C, $buf, $sz);
binmode(STDOUT);
print STDOUT $buf;