299 lines
8.4 KiB
ObjectPascal
299 lines
8.4 KiB
ObjectPascal
unit Chaotica;
|
|
|
|
interface
|
|
|
|
uses Global, RegularExpressionsCore, RegexHelper, Classes, SysUtils,
|
|
Windows, ShellAPI, ControlPoint, Translation;
|
|
|
|
const
|
|
export_flame = 'chaotica_export.flame';
|
|
|
|
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);
|
|
|
|
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');
|
|
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;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
(*
|
|
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;
|
|
*)
|
|
|
|
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}
|
|
fin_usex64 := true;
|
|
{$else}
|
|
fin_usex64 := usex64; // currently useless...
|
|
for i := 0 to plugins.Count - 1 do begin
|
|
name := plugins.Strings[i];
|
|
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
|
|
|
|
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
|
|
Exit;
|
|
end;
|
|
|
|
if (fails.Count > 0) then begin
|
|
messagebox(0, PCHAR(TextByKey('main-status-oldchaotica')),
|
|
'Apophysis AV', MB_ICONHAND or MB_OK);
|
|
end;
|
|
|
|
// TODO: add directory cleaning // <-- AV: done
|
|
fname := APPDATA + export_flame; // AV: moved into app folder
|
|
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);
|
|
end;
|
|
|
|
end.
|