Маленькая утилита, для заданного сохраненного сима ищет нестандартые элементы CAS на которые он ссылается.
unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DBPF2Decoder, StdCtrls, AdvMemo;
type
TCASFindRecord = record
T, G: DWORD;
ILo, iHi: DWORD;
path: string;
end;
TCASFindRecords = array of TCASFindRecord;
TARLogStyler = class(TAdvCustomMemoStyler)
public
constructor Create(AOwner: TComponent); override;
end;
TfrmMain = class(TForm)
DBPF2Decoder: TDBPF2Decoder;
btnOpen: TButton;
btnFind: TButton;
btnSaveReport: TButton;
dlgOpenS3Pack: TOpenDialog;
dlgOpenDBPF: TOpenDialog;
lstReport: TAdvMemo;
procedure btnOpenClick(Sender: TObject);
procedure btnFindClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
Records: TCASFindRecords;
Count: integer;
bSearchAbort: boolean;
procedure Add(const AFormat: string; const Arg: array of const);
public
procedure BkEnumDir(const FileName: string);
procedure BkEnumFile(const Directory: string; const FileInfo: TSearchRec);
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
uses
DBPF2Utils, jclFileUtils;
const
sep: string = '---------------------------';
procedure TfrmMain.Add(const AFormat: string; const Arg: array of const);
begin
with frmMain.lstReport.Lines do begin
BeginUpdate;
Add(Format(AFormat, Arg));
frmMain.lstReport.UpdateWrap;
EndUpdate
end
end;
procedure AddLast(const AFormat: string; const Arg: array of const);
var
i: integer;
begin
with frmMain.lstReport.Lines do
begin
BeginUpdate;
i:= frmMain.lstReport.Lines.Count-1;
if i<0 then exit;
frmMain.lstReport.Lines[i]:= frmMain.lstReport.Lines[i]+' '+Format(AFormat, Arg);
frmMain.lstReport.UpdateWrap;
EndUpdate
end
end;
procedure TfrmMain.btnFindClick(Sender: TObject);
var
lst: TStringList;
s: string;
i: integer;
begin
Add(sep, []);
Add('>> Search', []);
lst:= TStringList.Create;
lst.LoadFromFile(AppRunPath+'folders.txt');
for i:= 0 to lst.Count-1 do begin
s:= Trim(lst[i]);
if not DirectoryExists(s) then continue;
Add(' at "%s"', [s]);
bSearchAbort:= false;
EnumDirectories(s, frmMain.BkEnumDir, true, '', @bSearchAbort);
end;
lst.Free;
Add(sep, []);
for i:= 0 to Count-1 do with Records[i] do begin
Add(' CASP >> {%.8X-%.8X-%.8X%.8X}', [T, G, IHi, ILo]);
if Records[i].Path='' then
AddLast('>> not found', [])
else
AddLast('>> %s', [Records[i].Path])
end;
Add(sep, []);
Add(' Ready', []);
end;
procedure TfrmMain.btnOpenClick(Sender: TObject);
var
i, j, k, l, m: integer;
n: WORD;
off: DWORD;
tHi, tLo, tG, tT: DWORD;
b: byte;
f: boolean;
begin
if not dlgOpenDBPF.Execute then exit;
lstReport.Clear;
Count:= 0;
SetLength(Records, 0);
Add('>> Open >> "%s"', [dlgOpenDBPF.FileName]);
DBPF2Decoder.Decode(TFileStream.Create(dlgOpenDBPF.FileName, fmOpenRead));
for i:= 0 to DBPF2Decoder.Count-1 do with DBPF2Decoder.Items[i] do
if (ResourceType=$04F88964) then begin // SIME
Add(' SIME >> {%s}', [TGIName]);
Decode(TMemoryStream.Create);
Stream.Seek(2, soBeginning);
Stream.ReadBuffer(n, 2);
AddLast('>> TGICount=%d', [n]);
for j:= 0 to n-1 do begin
Stream.ReadBuffer(tLo, 4);
Stream.ReadBuffer(tHi, 4);
Stream.ReadBuffer(tG, 4);
Stream.ReadBuffer(tT, 4);
if (tT=$025ED6F4) then Add('.. SIMO', [])
else Add('.. UNKN', []);
AddLast('>> {%.8X-%.8X-%.8X%.8X}', [tT, tG, tHi, tLo]);
k:= DBPF2Decoder.Find(tT, tG, tHi, tLo);
if k<0 then AddLast('>> not founded in file', [])
else AddLast('>> in file', []);
if (k>=0) and (tT=$025ED6F4) then with DBPF2Decoder.Items[k] do begin // SIMO
Decode(TMemoryStream.Create);
Stream.Seek(4, soBeginning);
Stream.ReadBuffer(off, 4);
AddLast('>> offset=0x%.8X,', [off+8]);
Stream.Seek(off+8, soBeginning);
Stream.ReadBuffer(b, 1);
AddLast('count=%d', [b]);
for l:= 0 to b-1 do begin // SIMO TGI
Stream.ReadBuffer(tLo, 4);
Stream.ReadBuffer(tHi, 4);
Stream.ReadBuffer(tG, 4);
Stream.ReadBuffer(tT, 4);
if (tT=$034AEECB) then begin // CASP
Add('.... CASP >> {%.8X-%.8X-%.8X%.8X}', [tT, tG, tHi, tLo]);
f:= false;
for m:= 0 to Count-1 do
if (Records[m].G=tG) and (Records[m].ILo=tLo)
and (Records[m].IHi=tHi) then begin
f:= true;
break;
end;
if not f then begin
inc(Count);
SetLength(Records, Count);
Records[Count-1].T:= tT;
Records[Count-1].G:= tG;
Records[Count-1].ILo:= tLo;
Records[Count-1].IHi:= tHi;
Records[Count-1].path:= '';
AddLast('>> add to list', []);
end
else
AddLast('>> already in list', []);
end;
end;
DBPF2Decoder.Items[k].FreeStream;
end; // SIMO
end;
FreeStream;
Add(sep, []); // SIME
end; //
DBPF2Decoder.FreeStream;
Add(' Summary %d CASP in list', [Count]);
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
lstReport.SyntaxStyles:= TARLogStyler.Create(self);
end;
procedure TfrmMain.BkEnumFile(const Directory: string; const FileInfo: TSearchRec);
var
i, j, k: integer;
s, dst: string;
fs: TFileStream;
fs2: TFileStream;
begin
s:= Directory+FileInfo.Name;
fs:= TFileStream.Create(s, fmOpenRead);
DBPF2Decoder.Decode(fs);
for j:= 0 to Count-1 do begin
for i:= 0 to DBPF2Decoder.Count-1 do with DBPF2Decoder.Items[i] do begin
if (InstanceLo=Records[j].ILo) and (InstanceLo=Records[j].ILo) and (ResourceType=Records[j].T) then begin
Add('.... {%s} in "%s"', [DBPF2Decoder.Items[i].TGIName, s]);
if Pos(s, Records[j].Path)=0 then begin
if Records[j].Path<>'' then Records[j].Path:= Records[j].Path+'; ';
Records[j].Path:= Records[j].Path+'"'+s+'"';
end;
dst:= AppRunPath+PathExtractFileNameNoExt(dlgOpenDBPF.FileName);
ForceDirectories(dst);
if FileExists(dst+'\'+FileInfo.Name) then
AddLast('>> file aldready copied', []);
if (fs.Size>=50*1024*1024) then
AddLast('>> file too big', []);
if not FileExists(dst+'\'+FileInfo.Name) and (fs.Size<50*1024*1024) then begin
fs2:= TFileStream.Create(dst+'\'+FileInfo.Name, fmCreate);
fs.Seek(0, soBeginning);
fs2.CopyFrom(fs, fs.Size);
AddLast('>> copy to %s', [dst+'\'+FileInfo.Name]);
fs2.Free;
end;
end;
end;
end;
DBPF2Decoder.FreeStream;
end;
procedure TfrmMain.BkEnumDir(const FileName: string);
begin
Add('.. subfolder "%s"', [FileName]);
Application.ProcessMessages;
EnumFiles(FileName+'*.package', BkEnumFile);
end;
constructor TARLogStyler.Create(AOwner: TComponent);
var
itm:TElementStyle;
begin
inherited;
Description := 'Log';
Filter := '';
DefaultExtension := '.log';
StylerName := 'Log';
Extensions := 'log';
LineComment := '--';
MultiCommentLeft := '/*';
MultiCommentRight := '*/';
CommentStyle.TextColor := clNavy;
CommentStyle.BkColor := clNone;
CommentStyle.Style := [fsItalic];
NumberStyle.TextColor := $00C000;
NumberStyle.BkColor := clNone;
NumberStyle.Style := [fsBold];
BlockStart := 'simo,try,case,class,record';
BlockEnd := 'end';
HexIdentifier := '0x';
//------------Pascal Standard Default-------------
itm := AllStyles.Add;
itm.Font.Color := clPurple;
itm.Font.Style := [fsBold];
with itm.KeyWords do begin
Add('SIMO');
Add('SIME');
Add('CASP');
Add('UNKN');
end;
itm.BGColor:= clNone;
itm := AllStyles.Add;
itm.Font.Color := clRed;
itm.Font.Style := [fsBold];
with itm.KeyWords do begin
Add('>>');
Add('***');
Add('Исключение');
end;
itm.BGColor:= clNone;
//------------Simple Quote ' '----------------
itm := AllStyles.Add;
itm.StyleType := stBracket;
itm.Info := 'Simple Quote';
itm.Font.Color := clBlue;
itm.Font.Style := [];
itm.BracketStart := #39;
itm.BracketEnd := #39;
itm.BGColor:= clNone;
//------------Double Quote " "----------------
itm := AllStyles.Add;
itm.StyleType := stBracket;
itm.Info := 'Double Quote';
itm.Font.Color := clBlue;
itm.Font.Style := [];
itm.BracketStart := '"';
itm.BracketEnd := '"';
itm.BGColor:= clNone;
itm := AllStyles.Add;
itm.StyleType := stBracket;
itm.Info := 'Double {}';
itm.Font.Color := clBlue;
itm.Font.Style := [fsItalic];
itm.BracketStart := '{';
itm.BracketEnd := '}';
itm.BGColor:= clNone;
//----------SYMBOL --------------
itm := AllStyles.Add;
itm.StyleType := stSymbol;
itm.Info := 'Symbols Delimiters';
itm.Font.Color := clNavy;
itm.Font.Style := [];
itm.Symbols := #32+',;:.(){}[]=-/^%<#'+#13+#10;
itm.BGColor:= clNone;
end;
end.