source: oup/current/Unit15_Classes.pas @ 10

Last change on this file since 10 was 10, checked in by alloc, 17 years ago
  • Property svn:executable set to *
File size: 35.0 KB
Line 
1unit Unit15_Classes;
2interface
3uses Unit3_data, Unit9_data_structures, Classes, SysUtils, StrUtils, Dialogs, ABSDecUtil, ABSMain, DB;
4
5
6type
7  TOniData = class
8    private
9      FFileName:String;
10      FLevelInfo:TLevelInfo;
11      FBackend:Integer;
12      Fos_mac:Boolean;
13    protected
14    public
15      property FileName:String read FFileName write FFileName;
16      property Backend:Integer read FBackend write FBackend;
17      property OSisMac:Boolean read Fos_mac write Fos_mac;
18      property LevelInfo:TLevelinfo read FLevelInfo write FLevelInfo;
19
20      constructor Create(filename:String; var Result:Boolean); virtual; abstract;
21      procedure Close; virtual; abstract;
22
23      function GetFileInfo(fileid:LongWord):TFileInfo; virtual; abstract;
24      function GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray; virtual; abstract;
25      function GetFilesCount:LongWord; virtual; abstract;
26      function GetExtensionsList:TStringArray; virtual; abstract;
27      function GetExtendedExtensionsList:TExtensionsMap; virtual; abstract;
28      function ExtractFileID(name:String):Integer;
29      function GetFileIDByName(name:String):Integer;
30
31      function LoadDatFile(fileid:LongWord):Tdata; virtual; abstract;
32      procedure UpdateDatFile(fileid:LongWord; data:Tdata); virtual; abstract;
33      procedure LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer); virtual; abstract;
34      procedure UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer); virtual; abstract;
35
36      function GetRawList(fileid:LongWord):TRawList; virtual; abstract;
37      function GetRawInfo(fileid,dat_offset:LongWord):TRawInfo;
38      procedure LoadRawFile(fileid,dat_offset:LongWord; target:Pointer); virtual; abstract;
39      procedure UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer); virtual; abstract;
40      procedure LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); virtual; abstract;
41      procedure UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); virtual; abstract;
42      function AppendRawFile(loc_sep:Boolean; size:LongWord; target:Pointer):LongWord; virtual; abstract;//Returns new Address
43    published
44  end;
45
46  TOniDataDat = class(TOniData)
47    private
48      Fdat_file:TFileStream;
49      Fraw_file:TFileStream;
50      Fsep_file:TFileStream;
51      Fdat_header:THeader;
52      Fdat_filesmap:TFilesMap;
53      Fdat_files:TFiles;
54      Fdat_namedfilesmap:TNamedFilesMap;
55      Fdat_extensionsmap:TExtensionsMap;
56      FUnloadWhenUnused:Boolean;
57      FDatOpened:Boolean;
58      FRawOpened:Boolean;
59      FSepOpened:Boolean;
60    protected
61    public
62      property UnloadWhenUnused:Boolean read FUnloadWhenUnused write FUnloadWhenUnused;
63
64      constructor Create(DatFilename:String; var Result:Boolean); override;
65      procedure Close; override;
66
67      function GetFileInfo(fileid:LongWord):TFileInfo; override;
68      function GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray; override;
69      function GetFilesCount:LongWord; override;
70      function GetExtensionsList:TStringArray; override;
71      function GetExtendedExtensionsList:TExtensionsMap; override;
72
73      function LoadDatFile(fileid:LongWord):Tdata; override;
74      procedure UpdateDatFile(fileid:LongWord; data:Tdata); override;
75      procedure LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
76      procedure UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
77
78      procedure LoadRawOffset(loc_sep:Boolean; raw_addr,size:LongWord; target:Pointer);
79      function GetRawList(fileid:LongWord):TRawList; override;
80      procedure LoadRawFile(fileid,dat_offset:LongWord; target:Pointer); override;
81      procedure UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer); override;
82      procedure LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
83      procedure UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
84      function AppendRawFile(loc_sep:Boolean; size:LongWord; target:Pointer):LongWord; override;//Returns new Address
85    published
86  end;
87
88  TOniDataADB = class(TOniData)
89    private
90      FDatabase:TABSDatabase;
91      FQuery:TABSQuery;
92    protected
93    public
94      constructor Create(OLDBFilename:String; var Result:Boolean); override;
95      procedure Close; override;
96
97//      function GetDatLinks(srcid:LongWord):TDatLinks;
98      function GetFileInfo(fileid:LongWord):TFileInfo; override;
99      function GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray; override;
100      function GetFilesCount:LongWord; override;
101      function GetExtensionsList:TStringArray; override;
102      function GetExtendedExtensionsList:TExtensionsMap; override;
103      function GetNamedFilesMap:TNamedFilesMap;
104
105      function LoadDatFile(fileid:LongWord):Tdata; override;
106      procedure UpdateDatFile(fileid:LongWord; data:Tdata); override;
107      procedure LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
108      procedure UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
109
110      function GetRawList(fileid:LongWord):TRawList; override;
111      procedure LoadRawFile(fileid,dat_offset:LongWord; target:Pointer); override;
112      procedure UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer); override;
113      procedure LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
114      procedure UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
115    published
116  end;
117
118
119const
120  ODB_None=-1;
121  ODB_Dat=0;
122  ODB_ADB=1;
123
124var
125  OniDataConnection:TOniData;
126
127function CreateDataConnection(filename:String; backend:Integer):Boolean;
128procedure CloseDataConnection;
129
130
131
132
133implementation
134uses Unit2_Functions;
135
136
137
138(*
139  Implementation of  TOniData
140*)
141
142function TOniData.GetFileIDByName(name:String):Integer;
143  var
144    files:TStringArray;
145    i: Integer;
146  begin
147    Result:=-1;
148    files:=Self.GetFilesList('',name,false);
149    if Length(files)>0 then
150      for i:=0 to High(files) do
151        if Pos(name,files[i])=Pos('-',files[i])+1 then begin
152//        if MidStr(files[i],Pos('-',files[i])+1,Length(files[i])-Pos('-',files[i])-5)=name then begin
153          Result:=Self.ExtractFileID(files[i]);
154          Break;
155        end;
156  end;
157
158function TOniData.ExtractFileID(name:String):Integer;
159  begin
160    if name[5]='-' then
161      Result:=HexToLong(MidStr(name,1,4))
162    else
163      Result:=StrToInt(MidStr(name,1,5));
164  end;
165
166function TOniData.GetRawInfo(fileid,dat_offset:LongWord):TRawInfo;
167  var
168    i:LongWord;
169    raw_list:TRawList;
170  begin
171    raw_list:=Self.GetRawList(fileid);
172    Result.src_id:=0;
173    Result.src_offset:=0;
174    Result.raw_addr:=0;
175    Result.raw_size:=0;
176    for i:=0 to High(raw_list) do begin
177      if raw_list[i].src_offset=dat_offset then begin
178        Result.src_id:=fileid;
179        Result.src_offset:=raw_list[i].src_offset;
180        Result.raw_addr:=raw_list[i].raw_addr;
181        Result.raw_size:=raw_list[i].raw_size;
182        Result.loc_sep:=raw_list[i].loc_sep;
183        Break;
184      end;
185    end;
186  end;
187
188
189
190
191
192
193
194(*
195================================================================================
196                      Implementation of  TOniDataDat
197*)
198
199constructor TOniDataDat.Create(DatFilename:String; var Result:Boolean);
200  const
201    header_ident1_pc:Array[0..$13] of Byte=
202        ($1F,$27,$DC, $33,  $DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
203    header_ident1_mac:Array[0..$13] of Byte=
204        ($61,$30,$C1, $23,  $DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
205    header_ident1_macbeta:Array[0..$13] of Byte=
206        ($81,$11,$8D, $23,  $DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
207    header_ident2:Array[0..$F] of Byte=
208        ($99,$CF,$40,$00,$90,$4F,$63,$00,$F4,$55,$5F,$00,$90,$4F,$63,$00);
209  var
210    i:LongWord;
211    header_pc,header_mac:Boolean;
212  begin
213    FUnloadWhenUnused:=True;
214    FDatOpened:=False;
215    FRawOpened:=False;
216    if not FileExists(DatFilename) then begin
217      ShowMessage('File doesn''t exist!!!');
218      Result:=False;
219      Exit;
220    end;
221    FFileName:=DatFilename;
222    Fdat_file:=TFileStream.Create(FFileName, fmOpenRead);
223    Fdat_file.Read(Fdat_header,SizeOf(Fdat_header));
224    header_pc:=True;
225    header_mac:=True;
226    for i:=0 to High(Fdat_header.Ident) do begin
227      FLevelInfo.Ident[i]:=Fdat_header.Ident[i];
228      if Fdat_header.Ident[i]<>header_ident1_pc[i] then
229        header_pc:=False;
230      if Fdat_header.Ident[i]<>header_ident1_mac[i] then
231        header_mac:=False;
232    end;
233    if not (header_pc xor header_mac) then begin
234      Result:=False;
235      Exit;
236    end else begin
237      if (header_pc and not header_mac) then
238        Fos_mac:=False
239      else
240        Fos_mac:=True;
241    end;
242    SetLength(Fdat_filesmap,Fdat_header.Files);
243    SetLength(Fdat_files,Fdat_header.Files);
244    for i:=0 to Fdat_header.Files-1 do
245      Fdat_file.Read(Fdat_filesmap[i],SizeOf(Fdat_filesmap[i]));
246    for i:=0 to Fdat_header.Files-1 do begin
247      Fdat_files[i].Extension:=Fdat_filesmap[i].Extension;
248      Fdat_files[i].Extension:=ReverseString(Fdat_files[i].Extension);
249      Fdat_files[i].Size:=Fdat_filesmap[i].FileSize;
250      Fdat_files[i].FileType:=Fdat_filesmap[i].FileType;
251      Fdat_files[i].DatAddr:=Fdat_filesmap[i].DataAddr-8+Fdat_header.DataAddr;
252      if (Fdat_filesmap[i].FileType and $01)=0 then begin
253        Fdat_file.Seek(Fdat_filesmap[i].NameAddr+Fdat_header.NamesAddr,soFromBeginning);
254        SetLength(Fdat_files[i].Name,100);
255        Fdat_file.Read(Fdat_files[i].Name[1],100);
256        Fdat_files[i].Name:=MidStr(Fdat_files[i].Name,1+4,Pos(#0,Fdat_files[i].Name)-1-4);
257      end else begin
258        Fdat_files[i].Name:='';
259      end;
260      Fdat_files[i].FileName:=FormatNumber(i,5,'0')+'-'+Fdat_files[i].Name+'.'+Fdat_files[i].Extension;
261      Fdat_files[i].FileNameHex:=IntToHex(i,4)+'-'+Fdat_files[i].Name+'.'+Fdat_files[i].Extension;
262    end;
263    Fdat_file.Seek($40+Fdat_header.Files*$14,soFromBeginning);
264    SetLength(Fdat_namedfilesmap,Fdat_header.NamedFiles);
265    for i:=0 to Fdat_header.NamedFiles-1 do
266      Fdat_file.Read(Fdat_namedfilesmap[i],SizeOf(Fdat_namedfilesmap[i]));
267
268    Fdat_file.Seek($40+Fdat_header.Files*$14+Fdat_header.NamedFiles*$8,soFromBeginning);
269    SetLength(Fdat_extensionsmap,Fdat_header.Extensions);
270    for i:=0 to Fdat_header.Extensions-1 do
271      Fdat_file.Read(Fdat_extensionsmap[i],SizeOf(Fdat_extensionsmap[i]));
272
273    Fdat_file.Seek(Fdat_files[0].DatAddr+7,soFromBeginning);
274    Fdat_file.Read(FLevelInfo.LevelNumber,1);
275    FLevelInfo.LevelNumber:=FLevelInfo.LevelNumber DIV 2;
276
277    Fdat_file.Free;
278
279    Result:=True;
280    FBackend:=ODB_Dat;
281  end;
282
283procedure TOniDataDat.Close;
284  begin
285    if not FUnloadWhenUnused and FDatOpened then
286      Fdat_file.Free;
287    if not FUnloadWhenUnused and FRawOpened then
288      Fraw_file.Free;
289    if not FUnloadWhenUnused and FSepOpened then
290      Fsep_file.Free;
291    Self.Free;
292  end;
293
294
295
296function TOniDataDat.GetFileInfo(fileid:LongWord):TFileInfo;
297  begin
298    if fileid<Self.GetFilesCount then
299      Result:=Fdat_files[fileid]
300    else
301      Result.ID:=-1;
302  end;
303
304function TOniDataDat.GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray;
305  var
306    i:LongWord;
307  begin
308    SetLength(Result,0);
309    for i:=0 to Fdat_header.Files-1 do begin
310      if ( (Length(ext)=0) or (Pos(Fdat_files[i].Extension,ext)>0) ) and
311          ( (Length(pattern)=0) or (Pos(UpperCase(pattern),UpperCase(Fdat_files[i].Name))>0) ) then begin
312          if (NoEmptyFiles=false) or ((Fdat_files[i].FileType and $02)=0) then begin
313            SetLength(Result,Length(Result)+1);
314            if AppSettings.FilenumbersAsHex then
315              Result[High(Result)]:=Fdat_files[i].FileNameHex
316            else
317              Result[High(Result)]:=Fdat_files[i].FileName;
318          end;
319      end;
320    end;
321  end;
322
323function TOniDataDat.GetFilesCount:LongWord;
324  begin
325    Result:=Fdat_header.Files;
326  end;
327
328function TOniDataDat.GetExtensionsList:TStringArray;
329  var
330    i:LongWord;
331  begin
332    SetLength(Result,Fdat_header.Extensions);
333    for i:=0 to Fdat_header.Extensions-1 do begin
334      with Fdat_extensionsmap[i] do begin
335        Result[i]:=Extension[3]+Extension[2]+Extension[1]+Extension[0]+' ('+IntToStr(ExtCount)+')';
336      end;
337    end;
338  end;
339
340function TOniDataDat.GetExtendedExtensionsList:TExtensionsMap;
341  var
342    i:LongWord;
343  begin
344    SetLength(Result,Fdat_header.Extensions);
345    for i:=0 to Fdat_header.Extensions-1 do begin
346      Result[i]:=Fdat_extensionsmap[i];
347    end;
348  end;
349
350
351function TOniDataDat.LoadDatFile(fileid:LongWord):Tdata;
352  begin
353    if fileid<Self.GetFilesCount then begin
354      if FUnloadWhenUnused or not FDatOpened then
355        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
356      Fdat_file.Seek(Fdat_files[fileid].DatAddr,soFromBeginning);
357      SetLength(Result,Fdat_files[fileid].Size);
358      Fdat_file.Read(Result[0],Fdat_files[fileid].Size);
359      if UnloadWhenUnused then
360        Fdat_file.Free
361      else
362        FDatOpened:=True;
363    end;
364  end;
365
366procedure TOniDataDat.UpdateDatFile(fileid:LongWord; data:Tdata);
367  begin
368    if fileid<Self.GetFilesCount then begin
369      if FUnloadWhenUnused or not FDatOpened then
370        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
371      Fdat_file.Seek(Fdat_files[fileid].DatAddr,soFromBeginning);
372      Fdat_file.Write(data[0],Length(data));
373      if UnloadWhenUnused then
374        Fdat_file.Free
375      else
376        FDatOpened:=True;
377    end;
378  end;
379
380procedure TOniDataDat.LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer);
381  begin
382    if fileid<Self.GetFilesCount then begin
383      if FUnloadWhenUnused or not FDatOpened then
384        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
385      Fdat_file.Seek(Fdat_files[fileid].DatAddr+offset,soFromBeginning);
386      Fdat_file.Read(target^,size);
387      if UnloadWhenUnused then
388        Fdat_file.Free
389      else
390        FDatOpened:=True;
391    end;
392  end;
393
394procedure TOniDataDat.UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer);
395  begin
396    if fileid<Self.GetFilesCount then begin
397      if FUnloadWhenUnused or not FDatOpened then
398        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
399      Fdat_file.Seek(Fdat_files[fileid].DatAddr+offset,soFromBeginning);
400      Fdat_file.Write(target^,size);
401      if UnloadWhenUnused then
402        Fdat_file.Free
403      else
404        FDatOpened:=True;
405    end;
406  end;
407
408
409
410function TOniDataDat.GetRawList(fileid:LongWord):TRawList;
411  var
412    i:LongWord;
413  begin
414    SetLength(Result,0);
415    for i:=0 to High(RawListHandlers) do
416      if UpperCase(RawListHandlers[i].Ext)=UpperCase(Fdat_files[fileid].extension) then
417        if RawListHandlers[i].needed then begin
418          Result:=RawListHandlers[i].Handler(fileid);
419          Break;
420        end else
421          Break;
422  end;
423
424procedure TOniDataDat.LoadRawOffset(loc_sep:Boolean; raw_addr,size:LongWord; target:Pointer);
425  begin
426    if not loc_sep then begin
427      if FUnloadWhenUnused or not FRawOpened then
428        Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
429      if raw_addr<=Fraw_file.Size then begin
430        Fraw_file.Seek(raw_addr,soFromBeginning);
431        Fraw_file.Read(target^,size);
432      end;
433      if UnloadWhenUnused then
434        Fraw_file.Free
435      else
436        FRawOpened:=True
437    end else begin
438      if FUnloadWhenUnused or not FSepOpened then
439        Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
440      if raw_addr<=Fsep_file.Size then begin
441        Fsep_file.Seek(raw_addr,soFromBeginning);
442        Fsep_file.Read(target^,size);
443      end;
444      if UnloadWhenUnused then
445        Fsep_file.Free
446      else
447        FSepOpened:=True;
448    end;
449  end;
450
451procedure TOniDataDat.LoadRawFile(fileid,dat_offset:LongWord; target:Pointer);
452  var
453    raw_info:TRawInfo;
454  begin
455    if fileid<Self.GetFilesCount then begin
456      raw_info:=Self.GetRawInfo(fileid,dat_offset);
457      if not raw_info.loc_sep then begin
458        if FUnloadWhenUnused or not FRawOpened then
459          Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
460        Fraw_file.Seek(raw_info.raw_addr,soFromBeginning);
461        Fraw_file.Read(target^,raw_info.raw_size);
462        if UnloadWhenUnused then
463          Fraw_file.Free
464        else
465          FRawOpened:=True
466      end else begin
467        if FUnloadWhenUnused or not FSepOpened then
468          Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
469        Fsep_file.Seek(raw_info.raw_addr,soFromBeginning);
470        Fsep_file.Read(target^,raw_info.raw_size);
471        if UnloadWhenUnused then
472          Fsep_file.Free
473        else
474          FSepOpened:=True;
475      end;
476    end;
477  end;
478
479procedure TOniDataDat.UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer);
480  var
481    raw_info:TRawInfo;
482  begin
483    if fileid<Self.GetFilesCount then begin
484      raw_info:=Self.GetRawInfo(fileid,dat_offset);
485      if not raw_info.loc_sep then begin
486        if FUnloadWhenUnused or not FRawOpened then
487          Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
488        Fraw_file.Seek(raw_info.raw_addr,soFromBeginning);
489        Fraw_file.Write(target^,raw_info.raw_size);
490        if UnloadWhenUnused then
491          Fraw_file.Free
492        else
493          FRawOpened:=True
494      end else begin
495        if FUnloadWhenUnused or not FSepOpened then
496          Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
497        Fsep_file.Seek(raw_info.raw_addr,soFromBeginning);
498        Fsep_file.Write(target^,raw_info.raw_size);
499        if UnloadWhenUnused then
500          Fsep_file.Free
501        else
502          FSepOpened:=True;
503      end;
504    end;
505  end;
506
507procedure TOniDataDat.LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
508  var
509    raw_info:TRawInfo;
510    data:Tdata;
511    mem:TMemoryStream;
512  begin
513    if fileid<Self.GetFilesCount then begin
514      raw_info:=Self.GetRawInfo(fileid,dat_offset);
515      SetLength(data, raw_info.raw_size);
516      Self.LoadRawFile(fileid,dat_offset,@data[0]);
517      mem:=TMemoryStream.Create;
518      mem.Write(data[offset],size);
519      mem.Read(target^,size);
520      mem.Free;
521    end;
522  end;
523
524procedure TOniDataDat.UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
525  var
526    raw_info:TRawInfo;
527  begin
528    if fileid<Self.GetFilesCount then begin
529      raw_info:=Self.GetRawInfo(fileid,dat_offset);
530      if not raw_info.loc_sep then begin
531        if FUnloadWhenUnused or not FRawOpened then
532          Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
533        Fraw_file.Seek(raw_info.raw_addr+offset,soFromBeginning);
534        Fraw_file.Write(target^,raw_info.raw_size);
535        if UnloadWhenUnused then
536          Fraw_file.Free
537        else
538          FRawOpened:=True
539      end else begin
540        if FUnloadWhenUnused or not FSepOpened then
541          Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
542        Fsep_file.Seek(raw_info.raw_addr+offset,soFromBeginning);
543        Fsep_file.Write(target^,raw_info.raw_size);
544        if UnloadWhenUnused then
545          Fsep_file.Free
546        else
547          FSepOpened:=True;
548      end;
549    end;
550  end;
551
552function TOniDataDat.AppendRawFile(loc_sep:Boolean; size:LongWord; target:Pointer):LongWord; //Returns new Address
553  begin
554    if not loc_sep then begin
555      if FUnloadWhenUnused or not FRawOpened then
556        Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
557      Result:=Fraw_file.Size;
558      Fraw_file.Seek(0,soFromEnd);
559      Fraw_file.Write(target^,size);
560      if UnloadWhenUnused then
561        Fraw_file.Free
562      else
563        FRawOpened:=True
564    end else begin
565      if FUnloadWhenUnused or not FSepOpened then
566        Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
567      Result:=Fsep_file.Size;
568      Fsep_file.Seek(0,soFromEnd);
569      Fsep_file.Write(target^,size);
570      if UnloadWhenUnused then
571        Fsep_file.Free
572      else
573        FSepOpened:=True;
574    end;
575  end;
576
577
578
579
580
581
582
583
584
585
586
587(*
588================================================================================
589                     Implementation of  TOniDataADB
590*)
591
592constructor TOniDataADB.Create(OLDBFilename:String; var Result:Boolean);
593  var
594    i,j:Byte;
595    temps:String;
596  begin
597    if not FileExists(OLDBFilename) then begin
598      ShowMessage('File doesn''t exist!!!');
599      Result:=False;
600      Exit;
601    end;
602    FFileName:=OLDBFilename;
603    FDatabase:=TABSDatabase.Create(nil);
604    FDatabase.DatabaseName:='OLDBcon';
605    FDatabase.DatabaseFileName:=OLDBFilename;
606    FDatabase.Open;
607    FQuery:=TABSQuery.Create(FDatabase);
608    FQuery.DatabaseName:='OLDBcon';
609    FQuery.SQL.Text:='SELECT [name],[value] FROM globals ORDER BY [name] ASC';
610    FQuery.Open;
611    FQuery.First;
612    repeat
613      if FQuery.FieldByName('name').AsString='dbversion' then begin
614        if FQuery.FieldByName('value').AsString<>DBversion then begin
615          ShowMessage('Database-file '+#13+#10+
616                      '"'+OLDBFilename+'"'+#13+#10+
617                      'has wrong version. (Required: '+DBversion+'; found: '+
618                        FQuery.FieldByName('value').AsString+')');
619          FQuery.Close;
620          Result:=False;
621          Exit;
622        end;
623      end;
624      if FQuery.FieldByName('name').AsString='lvl' then begin
625        FLevelInfo.LevelNumber:=StrToInt(FQuery.FieldByName('value').AsString);
626      end;
627      if FQuery.FieldByName('name').AsString='ident' then begin
628        temps:=FQuery.FieldByName('value').AsString;
629        for i:=0 to High(FLevelInfo.Ident) do begin
630          j:=i*2+1;
631          case temps[j] of
632            '0'..'9': FLevelInfo.Ident[i]:=Ord(temps[j])-48;
633            'A'..'F': FLevelInfo.Ident[i]:=Ord(temps[j])-55;
634          end;
635          FLevelInfo.Ident[i]:=FLevelInfo.Ident[i]*16;
636          case temps[j+1] of
637            '0'..'9': FLevelInfo.Ident[i]:=FLevelInfo.Ident[i]+Ord(temps[j+1])-48;
638            'A'..'F': FLevelInfo.Ident[i]:=FLevelInfo.Ident[i]+Ord(temps[j+1])-55;
639          end;
640        end;
641      end;
642      if FQuery.FieldByName('name').AsString='ident' then begin
643        temps:=FQuery.FieldByName('value').AsString;
644        Fos_mac:=temps='MAC';
645      end;
646      FQuery.Next;
647    until FQuery.EoF;
648    FQuery.Close;
649
650    Result:=True;
651    FBackend:=ODB_ADB;
652  end;
653
654procedure TOniDataADB.Close;
655  begin
656    FDatabase.Close;
657    FDatabase.Free;
658    Self.Free;
659  end;
660
661
662
663function TOniDataADB.GetFileInfo(fileid:LongWord):TFileInfo;
664  begin
665    if fileid<Self.GetFilesCount then begin
666      FQuery.SQL.Text:='SELECT * FROM datfiles WHERE id='+IntToStr(fileid)+' ORDER BY id ASC;';
667      FQuery.Open;
668      if FQuery.RecordCount=1 then begin
669        FQuery.First;
670        Result.ID:=FQuery.FieldByName('id').AsInteger;
671        Result.Name:=FQuery.FieldByName('name').AsString;
672        Result.Extension:=FQuery.FieldByName('extension').AsString;
673        Result.FileName:=FormatNumber(Result.ID,5,'0')+'-'+Result.Name+'.'+Result.Extension;
674        Result.Size:=FQuery.FieldByName('size').AsInteger;
675        Result.FileType:=HexToLong(FQuery.FieldByName('contenttype').AsString);
676        Result.DatAddr:=0;
677        Result.opened:=False;
678      end;
679      FQuery.Close;
680    end else begin
681      Result.ID:=-1;
682    end;
683  end;
684
685function TOniDataADB.GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray;
686  var
687    i:LongWord;
688    where:String;
689    where_ext:String;
690  begin
691    where:='';
692    if Length(ext)>0 then begin
693      if Length(where)>0 then
694        where:=where+' AND ';
695      if Pos(',',ext)>0 then begin
696        i:=1;
697        where_ext:='';
698        while i<Length(ext) do begin
699          if Length(where_ext)>0 then
700            where_ext:=where_ext+' OR ';
701          where_ext:=where_ext+'(extension="'+MidStr(ext,i,4)+'")';
702          i:=i+5;
703        end;
704        where:=where+'('+where_ext+')';
705      end else begin
706        where:=where+'(extension="'+ext+'")';
707      end;
708    end;
709    if Length(pattern)>0 then begin
710      if Length(where)>0 then
711        where:=where+' AND ';
712      where:=where+'(name LIKE "%'+pattern+'%")';
713    end;
714    if NoEmptyFiles then begin
715      if Length(where)>0 then
716        where:=where+' AND ';
717      where:=where+'(contenttype<>2)';
718    end;
719    if Length(where)>0 then
720      where:=' WHERE '+where;
721    FQuery.SQL.Text:='SELECT id,name,extension FROM datfiles'+where+' ORDER BY id ASC;';
722    FQuery.Open;
723    if FQuery.RecordCount>0 then begin
724      FQuery.First;
725      SetLength(Result,FQuery.RecordCount);
726      i:=0;
727      repeat
728        Result[i]:=FormatNumber(FQuery.FieldByName('id').AsInteger,5,'0')+'-'+FQuery.FieldByName('name').AsString+'.'+FQuery.FieldByName('extension').AsString;
729        Inc(i);
730        FQuery.Next;
731      until FQuery.EOF;
732    end;
733    FQuery.Close;
734  end;
735
736function TOniDataADB.GetFilesCount:LongWord;
737  begin
738    FQuery.SQL.Text:='SELECT Count(*) AS cnumber FROM datfiles;';
739    FQuery.Open;
740    if FQuery.RecordCount>0 then begin
741      FQuery.First;
742      Result:=FQuery.FieldByName('cnumber').AsInteger;
743    end else Result:=0;
744    FQuery.Close;
745  end;
746
747function TOniDataADB.GetExtensionsList:TStringArray;
748  var
749    i:LongWord;
750  begin
751    SetLength(Result,0);
752    FQuery.SQL.Text:='SELECT extension,count(extension) AS x FROM datfiles GROUP BY extension ORDER BY extension ASC;';
753    FQuery.Open;
754    if FQuery.RecordCount>0 then begin
755      SetLength(Result,FQuery.RecordCount);
756      i:=0;
757      repeat
758        Result[i]:=FQuery.FieldByName('extension').AsString+' ('+IntToStr(FQuery.FieldByName('x').AsInteger)+')';
759        Inc(i);
760        FQuery.Next;
761      until FQuery.EOF;
762    end;
763    FQuery.Close;
764  end;
765
766function TOniDataADB.GetExtendedExtensionsList:TExtensionsMap;
767  var
768    i,j:LongWord;
769    temps:String;
770    data:Tdata;
771  begin
772    SetLength(Result,0);
773    FQuery.SQL.Text:='SELECT ext,ident FROM extlist ORDER BY ext ASC;';
774    FQuery.Open;
775    if FQuery.RecordCount>0 then begin
776      SetLength(Result,FQuery.RecordCount);
777      i:=0;
778      repeat
779        temps:=FQuery.FieldByName('ext').AsString;
780        for j:=0 to 3 do Result[i].Extension[j]:=temps[4-j];
781        data:=DecodeHexString(FQuery.FieldByName('ident').AsString);
782        for j:=0 to 7 do Result[i].Ident[j]:=data[j];
783        Inc(i);
784        FQuery.Next;
785      until FQuery.EOF;
786    end;
787    FQuery.Close;
788  end;
789
790function TOniDataADB.GetNamedFilesMap:TNamedFilesMap;
791  var
792    i:LongWord;
793    temp:Integer;
794    temps:String;
795    temparray:Array of Record
796        id:Integer;
797        fullname:String[50];
798      end;
799  begin
800    SetLength(temparray,0);
801    FQuery.SQL.Text:='SELECT id,(extension+name) AS xname FROM datfiles WHERE Length(name)>0 ORDER BY extension,name ASC;';
802    FQuery.Open;
803    if FQuery.RecordCount>0 then begin
804      repeat
805        temp:=FQuery.FieldByName('id').AsInteger;
806        temps:=FQuery.FieldByName('xname').AsString;
807
808        SetLength(temparray,Length(temparray)+1);
809        if Length(temparray)>1 then begin
810          for i:=High(temparray)-1 downto 0 do begin
811            if StringSmaller(temps,temparray[i].fullname) then begin
812              temparray[i+1]:=temparray[i];
813              if i=0 then begin
814                temparray[i].id:=temp;
815                temparray[i].fullname:=temps;
816              end;
817            end else begin
818              temparray[i+1].id:=temp;
819              temparray[i+1].fullname:=temps;
820              Break;
821            end;
822          end;
823        end else begin
824          temparray[0].id:=temp;
825          temparray[0].fullname:=temps;
826        end;
827        FQuery.Next;
828      until FQuery.Eof;
829    end;
830    FQuery.Close;
831    SetLength(Result,Length(temparray));
832    for i:=0 to High(temparray) do begin
833      Result[i].FileNumber:=temparray[i].id;
834      Result[i].blubb:=0;
835    end;
836  end;
837
838
839
840function TOniDataADB.LoadDatFile(fileid:LongWord):Tdata;
841  var
842    mem:TStream;
843  begin
844    if fileid<Self.GetFilesCount then begin
845      FQuery.SQL.Text:='SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';';
846      FQuery.Open;
847      if FQuery.RecordCount>0 then begin
848        mem:=FQuery.CreateBlobStream(FQuery.FieldByName('data'),bmRead);
849        SetLength(Result,mem.Size);
850        mem.Seek(0,soFromBeginning);
851        mem.Read(Result[0],mem.Size);
852        mem.Free;
853      end;
854      FQuery.Close;
855    end;
856  end;
857
858procedure TOniDataADB.UpdateDatFile(fileid:LongWord; data:Tdata);
859  var
860    MimeCoder: TStringFormat_MIME64;
861    mem:TMemoryStream;
862  begin
863    if fileid<Self.GetFilesCount then begin
864      mimecoder:=TStringFormat_MIME64.Create;
865      mem:=TMemoryStream.Create;
866      mem.Write(data[0],Length(data));
867      mem.Seek(0,soFromBeginning);
868      FQuery.SQL.Text:='UPDATE datfiles SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE id='+IntToStr(fileid)+';';
869      FQuery.ExecSQL;
870      mem.Free;
871      mimecoder.Free;
872    end;
873  end;
874
875procedure TOniDataADB.LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer);
876  var
877    mem:TStream;
878  begin
879    if fileid<Self.GetFilesCount then begin
880      FQuery.SQL.Text:='SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';';
881      FQuery.Open;
882      IF FQuery.RecordCount>0 THEN BEGIN
883        mem:=FQuery.CreateBlobStream(FQuery.FieldByName('data'),bmRead);
884        mem.Seek(offset,soFromBeginning);
885        mem.Read(target^,size);
886        mem.Free;
887      END;
888      FQuery.Close;
889    END;
890  END;
891
892procedure TOniDataADB.UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer);
893  var
894    MimeCoder: TStringFormat_MIME64;
895    mem:TMemoryStream;
896    data:Tdata;
897  begin
898    if fileid<Self.GetFilesCount then begin
899      data:=Self.LoadDatFile(fileid);
900      mimecoder:=TStringFormat_MIME64.Create;
901      mem:=TMemoryStream.Create;
902      mem.Write(data[0],Length(data));
903      mem.Seek(offset,soFromBeginning);
904      mem.Write(target^,size);
905      mem.Seek(0,soFromBeginning);
906      FQuery.SQL.Text:='UPDATE datfiles SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE id='+IntToStr(fileid)+';';
907      FQuery.ExecSQL;
908      mem.Free;
909      mimecoder.Free;
910    end;
911  end;
912
913
914
915function TOniDataADB.GetRawList(fileid:LongWord):TRawList;
916  var
917    i:LongWord;
918  begin
919    SetLength(Result,0);
920    FQuery.SQL.Text:='SELECT [src_link_offset],[size],[sep] FROM rawmap WHERE [src_id]='+IntToStr(fileid)+' ORDER BY src_link_offset ASC;';
921    FQuery.Open;
922    if FQuery.RecordCount>0 then begin
923      FQuery.First;
924      SetLength(Result,FQuery.RecordCount);
925      i:=0;
926      repeat
927        Result[i].src_id:=fileid;
928        Result[i].src_offset:=FQuery.FieldByName('src_link_offset').AsInteger;
929        Result[i].raw_addr:=0;
930        Result[i].raw_size:=FQuery.FieldByName('size').AsInteger;
931        Result[i].loc_sep:=FQuery.FieldByName('sep').AsBoolean;
932        Inc(i);
933        FQuery.Next;
934      until FQuery.EOF;
935    end;
936    FQuery.Close;
937  end;
938
939procedure TOniDataADB.LoadRawFile(fileid,dat_offset:LongWord; target:Pointer);
940  var
941    mem:TStream;
942  begin
943    if fileid<Self.GetFilesCount then begin
944      FQuery.SQL.Text:='SELECT data FROM rawmap WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(dat_offset)+');';
945      FQuery.Open;
946      if FQuery.RecordCount>0 then begin
947        mem:=FQuery.CreateBlobStream(FQuery.FieldByName('data'),bmRead);
948        mem.Seek(0,soFromBeginning);
949        mem.Read(target^,mem.size);
950        mem.Free;
951      end;
952      FQuery.Close;
953    end;
954  end;
955
956procedure TOniDataADB.UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer);
957  var
958    MimeCoder: TStringFormat_MIME64;
959    mem:TMemoryStream;
960  begin
961    if fileid<Self.GetFilesCount then begin
962      mimecoder:=TStringFormat_MIME64.Create;
963      mem:=TMemoryStream.Create;
964      mem.Write(target^,size);
965      mem.Seek(0,soFromBeginning);
966      FQuery.SQL.Text:='UPDATE rawmap SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(dat_offset)+');';
967      FQuery.ExecSQL;
968      mem.Free;
969      mimecoder.Free;
970    end;
971  end;
972
973procedure TOniDataADB.LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
974  var
975    data:Tdata;
976    mem:TMemoryStream;
977  begin
978    if fileid<Self.GetFilesCount then begin
979      SetLength(data, Self.GetRawInfo(fileid,dat_offset).raw_size);
980      Self.LoadRawFile(fileid,dat_offset,@data[0]);
981      mem:=TMemoryStream.Create;
982      mem.Write(data[offset],size);
983      mem.Read(target^,size);
984      mem.Free;
985    end;
986  end;
987
988procedure TOniDataADB.UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
989  var
990    MimeCoder: TStringFormat_MIME64;
991    mem:TMemoryStream;
992    data:Tdata;
993  begin
994    if fileid<Self.GetFilesCount then begin
995      SetLength(data, Self.GetRawInfo(fileid,offset).raw_size);
996      Self.LoadRawFile(fileid,offset,@data[0]);
997      mimecoder:=TStringFormat_MIME64.Create;
998      mem:=TMemoryStream.Create;
999      mem.Write(data[0],Length(data));
1000      mem.Seek(offset,soFromBeginning);
1001      mem.Write(target^,size);
1002      mem.Seek(0,soFromBeginning);
1003      FQuery.SQL.Text:='UPDATE rawmap SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(dat_offset)+');';
1004      FQuery.ExecSQL;
1005      mem.Free;
1006      mimecoder.Free;
1007    end;
1008  end;
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020function CreateDataConnection(filename:String; backend:Integer):Boolean;
1021  var
1022    answer:Boolean;
1023  begin
1024    if Assigned(OniDataConnection) then begin
1025      OniDataConnection.Close;
1026      OniDataConnection.Free;
1027      OniDataConnection:=Nil;
1028    end;
1029    case backend of
1030      ODB_Dat: OniDataConnection:=TOniDataDat.Create(filename, answer);
1031      ODB_ADB: OniDataConnection:=TOniDataADB.Create(filename, answer);
1032    else
1033      ShowMessage('Unknown Backend');
1034      Result:=False;
1035      Exit;
1036    end;
1037
1038    if answer then begin
1039//      ShowMessage('file loaded');
1040//      ShowMessage('Files: '+IntToStr(OniDataConnection.GetFilesCount));
1041      Result:=True;
1042    end else begin
1043      ShowMessage('File not loaded');
1044      OniDataConnection.Close;
1045      OniDataConnection.Free;
1046      Result:=False;
1047    end;
1048  end;
1049
1050procedure CloseDataConnection;
1051  begin
1052    if Assigned(OniDataConnection) then begin
1053      OniDataConnection.Close;
1054      OniDataConnection:=Nil;
1055    end;
1056  end;
1057
1058end.
Note: See TracBrowser for help on using the repository browser.