Алгоритм разгадан верно, большое спасибо.
Вот что удалось выяснить:
-Оказывается используется еще 2 ключа кроме "120", они были подобраны по представленному примеру, так же известно что данный алгоритм используется еще в 3х частях этой игры(и возможно во всех остальных), была написана процедура поиска ключа(нужно знать хотя бы одно слово в шифрованном и расшифрованном виде).
-Была написана процедура расшифровки.
-Выяснено за что отвечает левая системная часть строки. Пример строки расшифрованной вместе с левой частью: 160-3 ->160 Кто ты? Что с тобой случилось? Может расскажешь, что все это значит?
где 160-3 Номер сцены-номер диалога, ->160 к какой сцене ведет диалог(если числа одинаковые значит выбор варианта не верный и игрок не продвигается дальше).
-Некоторые строки разбиты на 2 части, каждая вторая часть начинается на * то есть если во время чтения и расшифровки файла обнаруживается что строка начинается на * то значит ее надо склеить с предыдущей.
Код расшифровки:
Код:
function Encrypt_(s:string; EncodeTable:array of Integer):string;
var
i,KeyL:Integer;
begin
Result:='';
KeyL:=0;
for i:=1 to Length(s) do
begin
if KeyL>2 then KeyL:=0;
Result:=Result+Char(Ord(s[i])+EncodeTable[KeyL]);
Inc(KeyL);
end;
end;
function Encrypt(s:string):string;
const Key1:array[0..2] of Integer=(1,2,0);
Key2:array[0..2] of Integer=(2,3,1);
Key3:array[0..2] of Integer=(3,4,2);
begin
Result:=Encrypt_(s,Key1);//Подставить нужный ключ
end;
Расшифровывается полностью вся строка включая знаки препинания, пробелы, и заглавные буквы.
Код поиска ключа:
Код:
procedure FindKey;
var
i:Integer;
Key:array of Integer;
EncS,DecS,Check:string;
begin
EncS:='кдираЮ';//Шифрованная
DecS:='никуда';//Расшифрованная
SetLength(Key,3);
Key[0]:=0;
Key[1]:=0;
Key[2]:=0;
for i:=1 to 1000 do
begin
if (Key[0]>=9) and (Key[1]>=9) and (Key[2]>=9) then Break;
if Key[2]<9 then Inc(Key[2]) else
begin
Key[2]:=0;
if Key[1]<9 then Inc(Key[1]) else
begin
Key[1]:=0;
if Key[0]<9 then Inc(Key[0]);
end;
end;
Check:=Encrypt_(EncS,Key);
if Check=DecS then
WriteLn('Key Found - '+IntToStr(Key[0])+IntToStr(Key[1])+IntToStr(Key[2]));
end;
end;
Еще как я уже говорил видео зашифровано заменой первого байта, оно мне в принципе было не нужно но ради интереса сделал, пусть оно тут полежит, а то как выяснилось в поисковиках относительно этой серии игр, расшифровка видео самый популярный запрос.
Код расшифровки видео:
Код:
procedure EncodeVideo;
var
ms:TMemoryStream;
B:Byte;
begin
ms:=TMemoryStream.Create;
ms.LoadFromFile('Video.cmk');
ms.Position:=1;
ms.ReadBuffer(B,SizeOf(B));
if B=$7C then
begin
B:=$49;
ms.Position:=1;
ms.WriteBuffer(B,SizeOf(B));
ms.SaveToFile('Video.avi');
end;
ms.Free;
end;
Осталось неразгаданным почему игра зависала при изменении длины шифрованной строки, игра просто валится и все, никаких ошибок не выдает, если запускать в OllyDbg то олька выдает '' is not a valid integer value. Но это в принципе уже не важно, то что мне нужно было изменить я изменил, и все нормально работает. Еще раз всем большое спасибо за помощь!
P.S. Код представленный Alegun, проверен, работает, расшифровывает весь файл целиком, но назад зашифровать не удается, в некоторых строках системная часть не вся, без системной части игра отказывается показывать диалог, не зависает, просто на его месте пусто.