Apophysis-AV/Core/Chaotica.pas

299 lines
8.4 KiB
ObjectPascal
Raw Normal View History

2022-03-08 12:25:51 -05:00
unit Chaotica;
interface
uses Global, RegularExpressionsCore, RegexHelper, Classes, SysUtils,
Windows, ShellAPI, ControlPoint, Translation;
const
export_flame = 'chaotica_export.flame';
2022-03-08 12:25:51 -05:00
function C_GetPathOf(filename: string; usex64: boolean): string;
function C_SupportsDllPlugins(usex64: boolean): boolean;
function C_IsDllPluginBlacklisted(filename: string; usex64: boolean): boolean;
function C_IsVariationNative(name: string; usex64: boolean): boolean;
function C_IsDllPluginInstalled(filename: string): boolean;
procedure C_SyncDllPlugins;
procedure C_ExecuteChaotica(flamexml: string; plugins: TStringList; usex64: boolean);
//procedure C_InstallVariation(name: string);
2022-03-08 12:25:51 -05:00
implementation
(* // AV: rewrote and moved to Global unit
function CheckX64: Boolean;
var
SEInfo: TShellExecuteInfo;
ExitCode: DWORD;
ExecuteFile, ParamString, StartInString: string;
begin
{$ifdef Apo7X64}
Result := true;
exit;
{$endif}
ExecuteFile := ExtractFilePath(Application.ExeName) + 'chk64.exe';
FillChar(SEInfo, SizeOf(SEInfo), 0);
SEInfo.cbSize := SizeOf(TShellExecuteInfo);
with SEInfo do begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Application.Handle;
lpFile := PChar(ExecuteFile) ;
nShow := SW_SHOWNORMAL;
end;
if ShellExecuteEx(@SEInfo) then
begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(SEInfo.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
Result := (ExitCode = 0);
end else begin
Result := false;
end;
end;
*)
function C_GetPathOf(filename: string; usex64: boolean): string;
begin
Result := ChaoticaPath + '\' + filename;
end;
function C_SupportsDllPlugins(usex64: boolean): boolean;
const
re_root : string = '<variation_compatibility\s+(.*?)>.*?</variation_compatibility>';
re_attrib : string = 'supports_dll_plugins="(.*?)"';
var
xml_file : TStringList;
xml_text, attrib, value : string;
begin
if usex64 then begin
Result := false;
Exit;
end;
xml_file := TStringList.Create;
// AV: for compatibility with new Chaotica versions
if not FileExists(ChaoticaPath + '\variation_compatibility.xml') then
begin
xml_file.Add('<variation_compatibility >' + #13#10 + '</variation_compatibility>');
xml_file.SaveToFile(ChaoticaPath + '\variation_compatibility.xml');
xml_file.Clear;
end;
xml_file.LoadFromFile(C_GetPathOf('variation_compatibility.xml', false));
xml_text := xml_file.Text;
xml_file.Free;
attrib := GetStringPart(xml_text, re_root, 1, 'supports_dll_plugins="false"');
value := GetStringPart(attrib, re_attrib, 1, 'false');
Result := (value = 'true');
end;
function C_IsDllPluginBlacklisted(filename: string; usex64: boolean): boolean;
var
i: integer;
blacklist: TStringList;
begin
blacklist := TStringList.Create;
if not FileExists(ChaoticaPath + '\plugin_dll_blacklist.txt') then
begin
blacklist.Add('avMobius.dll');
blacklist.Add('Cross.dll');
blacklist.Add('Epispiral.dll');
blacklist.Add('EpispiralVariationPlugin.dll');
blacklist.Add('FlowerVariationPlugin.dll');
blacklist.Add('Lissajous.dll');
blacklist.Add('Mandelbrot.dll');
blacklist.Add('ShapeVariationPlugin.dll');
blacklist.Add('slinky.dll');
blacklist.Add('Spirograph.dll');
blacklist.Add('Square.dll');
blacklist.Add('Stretchy Pants.dll');
blacklist.Add('Waffle.dll');
2022-03-08 12:25:51 -05:00
blacklist.SaveToFile(ChaoticaPath + '\plugin_dll_blacklist.txt');
end;
blacklist.LoadFromFile(C_GetPathOf('plugin_dll_blacklist.txt', usex64));
for i := 0 to blacklist.Count - 1 do begin
if LowerCase(filename) = LowerCase(blacklist.Strings[i]) then begin
Result := true;
blacklist.Free;
Exit;
end;
end;
blacklist.Free;
Result := false;
end;
function C_IsVariationNative(name: string; usex64: boolean): boolean;
const
re_root : string = '<variation_compatibility.*?>(.*?)</variation_compatibility>';
re_var : string = '<variation name="(.*?)".*?/>';
var
xml, var_name : string;
xml_file : TStringList;
find_var : TPerlRegEx;
found_var : boolean;
begin
xml_file := TStringList.Create;
// AV: for compatibility with new Chaotica versions
if not FileExists(ChaoticaPath + '\variation_compatibility.xml') then
begin
xml_file.Add('<variation_compatibility >' + #13#10 + '</variation_compatibility>');
xml_file.SaveToFile(ChaoticaPath + '\variation_compatibility.xml');
xml_file.Clear;
end;
xml_file.LoadFromFile(C_GetPathOf('variation_compatibility.xml', false));
xml := xml_file.Text;
xml_file.Free;
find_var := TPerlRegEx.Create;
find_var.RegEx := re_var;
find_var.Options := [preSingleLine, preCaseless];
find_var.Subject := GetStringPart(xml, re_root, 1, '');
found_var := find_var.Match;
while found_var do begin
var_name := String(find_var.Groups[1]);
found_var := find_var.MatchAgain;
if LowerCase(name) = var_name then begin
find_var.Destroy;
Result := true;
Exit;
end;
end;
find_var.Destroy;
Result := false;
end;
function C_IsDllPluginInstalled(filename: string): boolean;
var
path : string;
begin
path := C_GetPathOf('plugins\' + filename, false);
Result := FileExists(path);
end;
////////////////////////////////////////////////////////////////////
(*
2022-03-08 12:25:51 -05:00
procedure C_InstallVariation(name: string);
var
filename: string;
begin
filename := GetFileNameOfVariation(name);
if (filename = '') then Exit;
if C_IsDllPluginInstalled(filename) then Exit;
CopyFile(PCHAR(filename), PCHAR(C_GetPathOf('plugins\' +
ExtractFileName(filename), false)), false);
end;
*)
2022-03-08 12:25:51 -05:00
procedure C_SyncDllPlugins;
var
src_dir: string;
tgt_dir: string;
searchResult: TSearchRec;
begin
src_dir := PluginPath;
tgt_dir := C_GetPathOf('Plugins', false);
if (not DirectoryExists(src_dir)) then Exit;
if (not DirectoryExists(tgt_dir)) then Exit;
//CreateDir(ChaoticaPath + '\Plugins');
// First clear all plugins on Chaotica side
if FindFirst(tgt_dir + '\*.dll', faAnyFile, searchResult) = 0 then
begin
repeat
DeleteFile(PCHAR(tgt_dir + '\' + searchResult.Name)) ;
until (FindNext(searchResult) <> 0);
SysUtils.FindClose(searchResult);
end;
// Then copy all plugins from Apophysis to Chaotica
if FindFirst(src_dir + '*.dll', faAnyFile, searchResult) = 0 then
begin
repeat
if not C_IsDllPluginBlacklisted(searchResult.Name, false)
then CopyFile(
PCHAR(src_dir + '\' + searchResult.Name),
PCHAR(tgt_dir + '\' + searchResult.Name),
false);
until (FindNext(searchResult) <> 0);
SysUtils.FindClose(searchResult);
end;
end;
procedure C_ExecuteChaotica(flamexml: string; plugins: TStringList; usex64: boolean);
var
i: integer;
name, fname: string;
fails: TStringList;
txt: TStringList;
fin_usex64: boolean;
begin
fails := TStringList.Create;
{$ifdef CPUX64}
2022-03-08 12:25:51 -05:00
fin_usex64 := true;
{$else}
fin_usex64 := usex64; // currently useless...
2022-03-08 12:25:51 -05:00
for i := 0 to plugins.Count - 1 do begin
name := plugins.Strings[i];
2022-03-08 12:25:51 -05:00
fin_usex64 := fin_usex64 and C_IsVariationNative(name, usex64);
end;
for i := 0 to plugins.Count - 1 do begin
name := plugins.Strings[i]; // assume built-in
2022-03-08 12:25:51 -05:00
if not C_IsVariationNative(name, fin_usex64) then begin // not native -> try install
if C_SupportsDllPlugins(fin_usex64) then // dll unsupported -> fail
fails.Add(plugins.Strings[i])
else if C_IsDllPluginBlacklisted(name, fin_usex64) then // dll supported and blacklisted -> fail
fails.Add(plugins.Strings[i]);
//else C_InstallVariation(plugins.Strings[i]); // dll supported and not blacklisted -> install
// ^^^ this is done on Apophysis startup now!
end;
end;
{$endif}
name := C_GetPathOf('chaotica.exe', fin_usex64);
if (not FileExists(name)) then begin
messagebox(0, PCHAR(TextByKey('main-status-nochaotica')),
'Apophysis AV', MB_ICONHAND);
fails.Free; // AV: fixed possible memory leak
2022-03-08 12:25:51 -05:00
Exit;
end;
if (fails.Count > 0) then begin
messagebox(0, PCHAR(TextByKey('main-status-oldchaotica')),
'Apophysis AV', MB_ICONHAND or MB_OK);
2022-03-08 12:25:51 -05:00
end;
// TODO: add directory cleaning // <-- AV: done
fname := APPDATA + export_flame; // AV: moved into app folder
2022-03-08 12:25:51 -05:00
txt := TStringList.Create;
txt.Text := flamexml;
txt.SaveToFile(fname);
txt.Free;
fails.Free;
ShellExecute(0, PChar('open'), pchar(name), PChar('"' + fname + '"'),
PChar(ExtractFilePath(name)), SW_SHOWNORMAL);
2022-03-08 12:25:51 -05:00
end;
end.