Skip to content

Commit

Permalink
47. Once again rewritten FarCry2.exe search function for better Uplay…
Browse files Browse the repository at this point in the history
… support

Constant numbers of Sizes, CRC etc. packed together in one variable - gathered info of all three versions: Steam, Retail(GOG), Uplay. Seems like Uplay's FarCry2.exe was not recognized by launcher as valid all this time - Uplay game has all different sizes and CRC, but same patching offsets in Dunia.dll.
FarCry2.exe search function now tries to find the best match: comparing name, then size and then CRC. If for some reason size and checksum don't match then at least the file name should be enough.
And, finally, on launching the game FarCry2.exe no more checked for size - only dunia.dll is checked providing info about game version.
  • Loading branch information
FoxAhead committed May 31, 2020
1 parent 4e77976 commit 126eb0c
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/FarCry2MF.dof
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ AutoIncBuild=1
MajorVer=1
MinorVer=0
Release=0
Build=19
Build=20
Debug=0
PreRelease=0
Special=0
Expand All @@ -126,7 +126,7 @@ CodePage=1252
[Version Info Keys]
CompanyName=
FileDescription=
FileVersion=1.0.0.19
FileVersion=1.0.0.20
InternalName=
LegalCopyright=
LegalTrademarks=
Expand Down
8 changes: 7 additions & 1 deletion src/FarCry2MF.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,12 @@ end;

procedure Attach(HProcess: Cardinal);
begin
GVer := FC2MFOptions.Version;
case FC2MFOptions.Version of
GAME_VERSION_STEAM, GAME_VERSION_UPLAY:
GVer := 1;
GAME_VERSION_RETAIL:
GVer := 2;
end;
if FC2MFOptions.bJackalTapesFix then
begin
WriteMemory(HProcess, GAddr[GVer, 1], [$14]);
Expand Down Expand Up @@ -242,3 +247,4 @@ begin
DllProc := @DllMain;
DllProc(DLL_PROCESS_ATTACH);
end.

Binary file modified src/FarCry2MF.res
Binary file not shown.
130 changes: 83 additions & 47 deletions src/FarCry2MFL_Proc.pas
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,33 @@ TCommandLineOptions = record
sExec: string;
end;

TGameFilesInfo = record
FarCry2ExeSize: Integer;
FarCry2ExeCRC32: Cardinal;
DuniaDllSize: Integer;
VersionStringOffset: Integer;
end;

const
FAR_CRY_2_EXE_SIZE = 28296;
FAR_CRY_2_EXE_CRC32_STEAM = $5F78917A;
FAR_CRY_2_EXE_CRC32_RETAIL = $0FC58B66;
GameFilesInfo: array[1..3] of TGameFilesInfo =((
// Steam
FarCry2ExeSize: 28296;
FarCry2ExeCRC32: $5F78917A;
DuniaDllSize: 20183176;
VersionStringOffset: $00E37F54
),(
// Retail
FarCry2ExeSize: 28296;
FarCry2ExeCRC32: $0FC58B66;
DuniaDllSize: 19412104;
VersionStringOffset: $00DB1FC4
), (
// Uplay
FarCry2ExeSize: 29864;
FarCry2ExeCRC32: $8CF778F0;
DuniaDllSize: 20184168;
VersionStringOffset: $00E37F54
));

var
FarCry2ExeName: string;
Expand Down Expand Up @@ -101,6 +124,8 @@ procedure TrySetFarCry2ExeName(Path: string);

function CalcFileCRC32(FileName: string): Cardinal;

function IndexByGameFilesInfo(FarCry2ExeSize: Integer; FarCry2ExeCRC32: Cardinal; DuniaDllSize: Integer): Integer;

function GetGameVersion(): Integer;

//--------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -169,20 +194,20 @@ function QuoteIfSpaces(const S: string): string;

function CurrentFileInfo(NameApp: string): string;
var
dump: DWORD;
size: Integer;
buffer: PChar;
Dump: DWORD;
Size: Integer;
Buffer: PChar;
VersionPointer, TransBuffer: PChar;
Temp: Integer;
CalcLangCharSet: string;
begin
size := GetFileVersionInfoSize(PChar(NameApp), dump);
buffer := StrAlloc(size + 1);
Size := GetFileVersionInfoSize(PChar(NameApp), Dump);
Buffer := StrAlloc(Size + 1);
try
GetFileVersionInfo(PChar(NameApp), 0, size, buffer);
GetFileVersionInfo(PChar(NameApp), 0, Size, Buffer);

VerQueryValue(buffer, '\VarFileInfo\Translation', Pointer(TransBuffer), dump);
if dump >= 4 then
VerQueryValue(Buffer, '\VarFileInfo\Translation', Pointer(TransBuffer), Dump);
if Dump >= 4 then
begin
Temp := 0;
StrLCopy(@Temp, TransBuffer, 2);
Expand All @@ -191,16 +216,16 @@ function CurrentFileInfo(NameApp: string): string;
CalcLangCharSet := CalcLangCharSet + IntToHex(Temp, 4);
end;

VerQueryValue(buffer, PChar('\StringFileInfo\' + CalcLangCharSet + '\' + 'FileVersion'), Pointer(VersionPointer), dump);
if (dump > 1) then
VerQueryValue(Buffer, PChar('\StringFileInfo\' + CalcLangCharSet + '\' + 'FileVersion'), Pointer(VersionPointer), Dump);
if (Dump > 1) then
begin
SetLength(Result, dump);
StrLCopy(PChar(Result), VersionPointer, dump);
SetLength(Result, Dump);
StrLCopy(PChar(Result), VersionPointer, Dump);
end
else
Result := '0.0.0.0';
finally
StrDispose(buffer);
StrDispose(Buffer);
end;
end;

Expand Down Expand Up @@ -521,7 +546,7 @@ function GetFileSize(FileName: string): Cardinal;
Result := 0;
if SysUtils.FindFirst(FileName, faAnyFile, sr) = 0 then
begin
Result := sr.size;
Result := sr.Size;
SysUtils.FindClose(sr);
end;
end;
Expand Down Expand Up @@ -585,7 +610,8 @@ procedure TrySetFarCry2ExeName(Path: string);
SearchRec: TSearchRec;
SearchMask: string;
FileName: string;
FileCRC32: Cardinal;
BestMatch: Integer;
CurrentMatch: Integer;
begin
if FarCry2ExeName = '' then
begin
Expand All @@ -594,17 +620,20 @@ procedure TrySetFarCry2ExeName(Path: string);
SearchMask := Path + '*.exe';
if SysUtils.FindFirst(SearchMask, faAnyFile, SearchRec) = 0 then
begin
BestMatch := 0;
repeat
if SearchRec.Size = FAR_CRY_2_EXE_SIZE then
CurrentMatch := 0;
FileName := Path + SearchRec.Name;
if SameText(SearchRec.Name, 'FarCry2.exe') then
CurrentMatch := CurrentMatch + 1;
if IndexByGameFilesInfo(SearchRec.Size, 0, 0) > 0 then
CurrentMatch := CurrentMatch + 2;
if IndexByGameFilesInfo(0, CalcFileCRC32(FileName), 0) > 0 then
CurrentMatch := CurrentMatch + 4;
if CurrentMatch > BestMatch then
begin
FileName := Path + SearchRec.Name;
FileCRC32 := CalcFileCRC32(FileName);
if (FileCRC32 = FAR_CRY_2_EXE_CRC32_STEAM) or (FileCRC32 = FAR_CRY_2_EXE_CRC32_RETAIL) then
begin
FarCry2ExeName := FileName;
if SameText(SearchRec.Name, 'FarCry2.exe') then
Break;
end;
BestMatch := CurrentMatch;
FarCry2ExeName := FileName;
end;
until SysUtils.FindNext(SearchRec) <> 0;
SysUtils.FindClose(SearchRec);
Expand All @@ -626,41 +655,47 @@ function CalcFileCRC32(FileName: string): Cardinal;
Result := TCRC32.Calc(FileBuffer, Length(FileBuffer));
end;

function IndexByGameFilesInfo(FarCry2ExeSize: Integer; FarCry2ExeCRC32: Cardinal; DuniaDllSize: Integer): Integer;
var
i: Integer;
begin
Result := 0;
for i := Low(GameFilesInfo) to High(GameFilesInfo) do
begin
{(*}
if (FarCry2ExeSize <> 0) and (GameFilesInfo[i].FarCry2ExeSize = FarCry2ExeSize) or
(FarCry2ExeCRC32 <> 0) and (GameFilesInfo[i].FarCry2ExeCRC32 = FarCry2ExeCRC32) or
(DuniaDllSize <> 0) and (GameFilesInfo[i].DuniaDllSize = DuniaDllSize) then
{*)}
begin
Result := i;
Break;
end;
end;
end;

function GetGameVersion(): Integer;
var
FarCry2ExeSize: Integer;
DuniaDllSize: Integer;
IndexByDuniaDll: Integer;
FileStream: TFileStream;
UpdateVersionPosition: Integer;
VersionStringOffset: Integer;
UpdateVersion: array[0..3] of Char;
GameVersion: Integer;
begin
Result := 0;
FarCry2ExeSize := GetFileSize(FarCry2ExeName);
DuniaDllSize := GetFileSize(DuniaDllName);
if FarCry2ExeSize <> FAR_CRY_2_EXE_SIZE then
raise Exception.Create(Format('Wrong size of FarCry2.exe file (%d). Game version v1.03 supported only.', [FarCry2ExeSize]));
case DuniaDllSize of
20183176, 20184168:
begin
GameVersion := GAME_VERSION_STEAM;
UpdateVersionPosition := $00E37F54;
end;
19412104:
begin
GameVersion := GAME_VERSION_RETAIL;
UpdateVersionPosition := $00DB1FC4;
end;
IndexByDuniaDll := IndexByGameFilesInfo(0, 0, DuniaDllSize);
if (IndexByDuniaDll >= Low(GameFilesInfo)) and (IndexByDuniaDll <= High(GameFilesInfo)) then
VersionStringOffset := GameFilesInfo[IndexByDuniaDll].VersionStringOffset
else
raise Exception.Create(Format('Wrong size of Dunia.dll file (%d). Game version v1.03 supported only.', [DuniaDllSize]));
end;
FileStream := TFileStream.Create(DuniaDllName, fmOpenRead or fmShareDenyNone);
FileStream.Seek(UpdateVersionPosition, soFromBeginning);
FileStream.Seek(VersionStringOffset, soFromBeginning);
FileStream.ReadBuffer(UpdateVersion, 4);
FileStream.Free;
if UpdateVersion <> '1.03' then
raise Exception.Create('Wrong version of Dunia.dll file. Game version v1.03 supported only.');
Result := GameVersion;
Result := IndexByDuniaDll;
end;

procedure FormOptionsAddSubItems(Nodes: IXMLNodeList; var SubItems: TOptionSubItems);
Expand Down Expand Up @@ -830,3 +865,4 @@ procedure SetOptionByKey(Key: string; Value: Variant);
end;

end.

6 changes: 3 additions & 3 deletions src/FarCry2MFLauncher.dof
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ RootDir=
IncludeVerInfo=1
AutoIncBuild=1
MajorVer=1
MinorVer=6
MinorVer=7
Release=0
Build=46
Build=47
Debug=0
PreRelease=0
Special=0
Expand All @@ -126,7 +126,7 @@ CodePage=1252
[Version Info Keys]
CompanyName=
FileDescription=
FileVersion=1.6.0.46
FileVersion=1.7.0.47
InternalName=
LegalCopyright=
LegalTrademarks=
Expand Down
Binary file modified src/FarCry2MFLauncher.res
Binary file not shown.
1 change: 1 addition & 0 deletions src/FarCry2MF_Options.pas
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface
const
GAME_VERSION_STEAM = 1;
GAME_VERSION_RETAIL = 2;
GAME_VERSION_UPLAY = 3;

var
Options: TFC2MFOptions;
Expand Down

0 comments on commit 126eb0c

Please sign in to comment.