source: oup/current/Code/OniDataClass.pas @ 46

Last change on this file since 46 was 46, checked in by alloc, 16 years ago
File size: 37.7 KB
Line 
1unit OniDataClass;
2interface
3uses Data, DataStructures, Classes, SysUtils, StrUtils,
4  Dialogs, ABSDecUtil, ABSMain, DB;
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;
25      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; virtual; abstract;
26    function GetFilesCount: LongWord; virtual; abstract;
27    function GetExtensionsList: TStringArray; virtual; abstract;
28    function GetExtendedExtensionsList: TExtensionsMap; virtual; abstract;
29    function ExtractFileID(Name: String): Integer;
30    function GetFileIDByName(Name: String): Integer;
31
32    function LoadDatFile(fileid: LongWord): Tdata; virtual; abstract;
33    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); virtual; abstract;
34    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
35      virtual; abstract;
36    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
37      virtual; abstract;
38
39    function GetRawList(fileid: LongWord): TRawList; virtual; abstract;
40    function GetRawInfo(fileid, dat_offset: LongWord): TRawInfo;
41    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
42      virtual; abstract;
43    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord; target: Pointer);
44      virtual; abstract;
45    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
46      offset, size: LongWord; target: Pointer); virtual; abstract;
47    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
48      offset, size: LongWord; target: Pointer); virtual; abstract;
49    function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
50      virtual; abstract;//Returns new Address
51  published
52  end;
53
54  TOniDataDat = class(TOniData)
55  private
56    Fdat_file:     TFileStream;
57    Fraw_file:     TFileStream;
58    Fsep_file:     TFileStream;
59    Fdat_header:   THeader;
60    Fdat_filesmap: TFilesMap;
61    Fdat_files:    TFiles;
62    Fdat_namedfilesmap: TNamedFilesMap;
63    Fdat_extensionsmap: TExtensionsMap;
64    FUnloadWhenUnused: Boolean;
65    FDatOpened:    Boolean;
66    FRawOpened:    Boolean;
67    FSepOpened:    Boolean;
68  protected
69  public
70    property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write FUnloadWhenUnused;
71
72    constructor Create(DatFilename: String; var Result: Boolean); override;
73    procedure Close; override;
74
75    function GetFileInfo(fileid: LongWord): TFileInfo; override;
76    function GetFilesList(ext: String; pattern: String;
77      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; override;
78    function GetFilesCount: LongWord; override;
79    function GetExtensionsList: TStringArray; override;
80    function GetExtendedExtensionsList: TExtensionsMap; override;
81
82    function LoadDatFile(fileid: LongWord): Tdata; override;
83    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
84    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
85    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
86
87    procedure LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord; target: Pointer);
88    function GetRawList(fileid: LongWord): TRawList; override;
89    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
90    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
91      target: Pointer); override;
92    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
93      offset, size: LongWord; target: Pointer); override;
94    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
95      offset, size: LongWord; target: Pointer); override;
96    function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
97      override;//Returns new Address
98  published
99  end;
100
101  TOniDataADB = class(TOniData)
102  private
103    FDatabase: TABSDatabase;
104    FQuery:    TABSQuery;
105  protected
106  public
107    constructor Create(OLDBFilename: String; var Result: Boolean); override;
108    procedure Close; override;
109
110    //      function GetDatLinks(srcid:LongWord):TDatLinks;
111    function GetFileInfo(fileid: LongWord): TFileInfo; override;
112    function GetFilesList(ext: String; pattern: String;
113      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; override;
114    function GetFilesCount: LongWord; override;
115    function GetExtensionsList: TStringArray; override;
116    function GetExtendedExtensionsList: TExtensionsMap; override;
117    function GetNamedFilesMap: TNamedFilesMap;
118
119    function LoadDatFile(fileid: LongWord): Tdata; override;
120    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
121    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
122    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
123
124    function GetRawList(fileid: LongWord): TRawList; override;
125    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
126    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
127      target: Pointer); override;
128    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
129      offset, size: LongWord; target: Pointer); override;
130    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
131      offset, size: LongWord; target: Pointer); override;
132  published
133  end;
134
135
136const
137  ODB_None = -1;
138  ODB_Dat  = 0;
139  ODB_ADB  = 1;
140
141var
142  OniDataConnection: TOniData;
143
144function CreateDataConnection(filename: String; backend: Integer): Boolean;
145procedure CloseDataConnection;
146
147
148
149
150implementation
151uses Functions;
152
153
154
155(*
156  Implementation of  TOniData
157*)
158
159function TOniData.GetFileIDByName(Name: String): Integer;
160var
161  files: TStringArray;
162  i:     Integer;
163begin
164  Result := -1;
165  files  := Self.GetFilesList('', Name, False, stIDAsc);
166  if Length(files) > 0 then
167    for i := 0 to High(files) do
168      if Pos(Name, files[i]) = Pos('-', files[i]) + 1 then
169      begin
170        //        if MidStr(files[i],Pos('-',files[i])+1,Length(files[i])-Pos('-',files[i])-5)=name then begin
171        Result := Self.ExtractFileID(files[i]);
172        Break;
173      end;
174end;
175
176
177
178
179function TOniData.ExtractFileID(Name: String): Integer;
180begin
181  if Name[5] = '-' then
182    Result := HexToLong(MidStr(Name, 1, 4))
183  else
184    Result := StrToInt(MidStr(Name, 1, 5));
185end;
186
187
188
189
190function TOniData.GetRawInfo(fileid, dat_offset: LongWord): TRawInfo;
191var
192  i: LongWord;
193  raw_list: TRawList;
194begin
195  raw_list      := Self.GetRawList(fileid);
196  Result.src_id := 0;
197  Result.src_offset := 0;
198  Result.raw_addr := 0;
199  Result.raw_size := 0;
200  for i := 0 to High(raw_list) do
201  begin
202    if raw_list[i].src_offset = dat_offset then
203    begin
204      Result.src_id     := fileid;
205      Result.src_offset := raw_list[i].src_offset;
206      Result.raw_addr   := raw_list[i].raw_addr;
207      Result.raw_size   := raw_list[i].raw_size;
208      Result.loc_sep    := raw_list[i].loc_sep;
209      Break;
210    end;
211  end;
212end;
213
214
215
216
217
218
219
220(*
221================================================================================
222                      Implementation of  TOniDataDat
223*)
224
225constructor TOniDataDat.Create(DatFilename: String; var Result: Boolean);
226const
227  header_ident1_pc: array[0..$13] of Byte =
228    ($1F, $27, $DC, $33, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
229    $14, $00, $10, $00, $08, $00);
230  header_ident1_mac: array[0..$13] of Byte =
231    ($61, $30, $C1, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
232    $14, $00, $10, $00, $08, $00);
233  header_ident1_macbeta: array[0..$13] of Byte =
234    ($81, $11, $8D, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
235    $14, $00, $10, $00, $08, $00);
236  header_ident2: array[0..$F] of Byte =
237    ($99, $CF, $40, $00, $90, $4F, $63, $00, $F4, $55, $5F, $00, $90, $4F, $63, $00);
238var
239  i: LongWord;
240  header_pc, header_mac: Boolean;
241begin
242  FUnloadWhenUnused := True;
243  FDatOpened := False;
244  FRawOpened := False;
245  if not FileExists(DatFilename) then
246  begin
247    ShowMessage('File doesn''t exist!!!');
248    Result := False;
249    Exit;
250  end;
251  FFileName := DatFilename;
252  Fdat_file := TFileStream.Create(FFileName, fmOpenRead);
253  Fdat_file.Read(Fdat_header, SizeOf(Fdat_header));
254  header_pc  := True;
255  header_mac := True;
256  for i := 0 to High(Fdat_header.Ident) do
257  begin
258    FLevelInfo.Ident[i] := Fdat_header.Ident[i];
259    if Fdat_header.Ident[i] <> header_ident1_pc[i] then
260      header_pc := False;
261    if Fdat_header.Ident[i] <> header_ident1_mac[i] then
262      header_mac := False;
263  end;
264  if not (header_pc xor header_mac) then
265  begin
266    Result := False;
267    Exit;
268  end
269  else
270  begin
271    if (header_pc and not header_mac) then
272      Fos_mac := False
273    else
274      Fos_mac := True;
275  end;
276  SetLength(Fdat_filesmap, Fdat_header.Files);
277  SetLength(Fdat_files, Fdat_header.Files);
278  for i := 0 to Fdat_header.Files - 1 do
279    Fdat_file.Read(Fdat_filesmap[i], SizeOf(Fdat_filesmap[i]));
280  for i := 0 to Fdat_header.Files - 1 do
281  begin
282    Fdat_files[i].ID := i;
283    Fdat_files[i].Extension := Fdat_filesmap[i].Extension;
284    Fdat_files[i].Extension := ReverseString(Fdat_files[i].Extension);
285    Fdat_files[i].Size      := Fdat_filesmap[i].FileSize;
286    Fdat_files[i].FileType  := Fdat_filesmap[i].FileType;
287    Fdat_files[i].DatAddr   := Fdat_filesmap[i].DataAddr - 8 + Fdat_header.DataAddr;
288    if (Fdat_filesmap[i].FileType and $01) = 0 then
289    begin
290      Fdat_file.Seek(Fdat_filesmap[i].NameAddr + Fdat_header.NamesAddr, soFromBeginning);
291      SetLength(Fdat_files[i].Name, 100);
292      Fdat_file.Read(Fdat_files[i].Name[1], 100);
293      Fdat_files[i].Name := MidStr(Fdat_files[i].Name, 1 + 4, Pos(
294        #0, Fdat_files[i].Name) - 1 - 4);
295    end
296    else
297    begin
298      Fdat_files[i].Name := '';
299    end;
300    Fdat_files[i].FileName    :=
301      FormatNumber(i, 5, '0') + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
302    Fdat_files[i].FileNameHex :=
303      IntToHex(i, 4) + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
304  end;
305  Fdat_file.Seek($40 + Fdat_header.Files * $14, soFromBeginning);
306  SetLength(Fdat_namedfilesmap, Fdat_header.NamedFiles);
307  for i := 0 to Fdat_header.NamedFiles - 1 do
308    Fdat_file.Read(Fdat_namedfilesmap[i], SizeOf(Fdat_namedfilesmap[i]));
309
310  Fdat_file.Seek($40 + Fdat_header.Files * $14 + Fdat_header.NamedFiles * $8, soFromBeginning);
311  SetLength(Fdat_extensionsmap, Fdat_header.Extensions);
312  for i := 0 to Fdat_header.Extensions - 1 do
313    Fdat_file.Read(Fdat_extensionsmap[i], SizeOf(Fdat_extensionsmap[i]));
314
315  Fdat_file.Seek(Fdat_files[0].DatAddr + 7, soFromBeginning);
316  Fdat_file.Read(FLevelInfo.LevelNumber, 1);
317  FLevelInfo.LevelNumber := FLevelInfo.LevelNumber div 2;
318
319  Fdat_file.Free;
320
321  Result   := True;
322  FBackend := ODB_Dat;
323end;
324
325
326
327
328procedure TOniDataDat.Close;
329begin
330  if not FUnloadWhenUnused and FDatOpened then
331    Fdat_file.Free;
332  if not FUnloadWhenUnused and FRawOpened then
333    Fraw_file.Free;
334  if not FUnloadWhenUnused and FSepOpened then
335    Fsep_file.Free;
336  Self.Free;
337end;
338
339
340
341
342function TOniDataDat.GetFileInfo(fileid: LongWord): TFileInfo;
343begin
344  if fileid < Self.GetFilesCount then
345    Result    := Fdat_files[fileid]
346  else
347    Result.ID := -1;
348end;
349
350
351
352
353function TOniDataDat.GetFilesList(ext: String; pattern: String;
354  NoEmptyFiles: Boolean; sort: TSortType): TStringArray;
355var
356  i: LongWord;
357  list: TStringList;
358  id, name, extension: String;
359  fields: TStrings;
360
361  procedure getfields;
362  begin
363     fields.CommaText := StringReplace(AnsiQuotedStr(list.Strings[i], '"'), ';', '","', [rfReplaceAll]);
364    if sort in [stIDAsc, stIDDesc] then
365    begin
366      id := fields.Strings[0];
367      name := fields.Strings[1];
368      extension := fields.Strings[2];
369    end;
370    if sort in [stNameAsc, stNameDesc] then
371    begin
372      id := fields.Strings[1];
373      name := fields.Strings[0];
374      extension := fields.Strings[2];
375    end;
376    if sort in [stExtAsc, stExtDesc] then
377    begin
378      id := fields.Strings[1];
379      name := fields.Strings[2];
380      extension := fields.Strings[0];
381    end;
382  end;
383
384begin
385  list := TStringList.Create;
386  list.Sorted := True;
387  for i := 0 to Fdat_header.Files - 1 do
388  begin
389    if ((Length(ext) = 0) or (Pos(Fdat_files[i].Extension, ext) > 0)) and
390      ((Length(pattern) = 0) or
391      (Pos(UpperCase(pattern), UpperCase(Fdat_files[i].Name)) > 0)) then
392    begin
393      if (NoEmptyFiles = False) or ((Fdat_files[i].FileType and $02) = 0) then
394      begin
395        if AppSettings.FilenumbersAsHex then
396          id := IntToHex(Fdat_files[i].ID, 4)
397        else
398          id := FormatNumber(Fdat_files[i].ID, 5, '0');
399        name := Fdat_files[i].Name;
400        extension := Fdat_files[i].Extension;
401
402        case sort of
403          stIDAsc, stIDDesc:     list.Add(id + ';' + name + ';' + extension);
404          stNameAsc, stNameDesc: list.Add(name + ';' + id + ';' + extension);
405          stExtAsc, stExtDesc:   list.Add(extension + ';' + id + ';' + name);
406        end;
407      end;
408    end;
409  end;
410  SetLength(Result, list.Count);
411  fields := TStringList.Create;
412  if sort in [stIDAsc, stNameAsc, stExtAsc] then
413    for i := 0 to list.Count - 1 do
414    begin
415      getfields;
416      Result[i] := id + '-' + name + '.' + extension;
417    end
418  else
419    for i := list.Count - 1 downto 0 do
420    begin
421      getfields;
422      Result[list.Count - i - 1] := id + '-' + name + '.' + extension;
423    end;
424  list.Free;
425  fields.Free;
426end;
427
428
429
430
431function TOniDataDat.GetFilesCount: LongWord;
432begin
433  Result := Fdat_header.Files;
434end;
435
436
437
438
439function TOniDataDat.GetExtensionsList: TStringArray;
440var
441  i: LongWord;
442begin
443  SetLength(Result, Fdat_header.Extensions);
444  for i := 0 to Fdat_header.Extensions - 1 do
445  begin
446    with Fdat_extensionsmap[i] do
447    begin
448      Result[i] := Extension[3] + Extension[2] + Extension[1] + Extension[0] +
449        ' (' + IntToStr(ExtCount) + ')';
450    end;
451  end;
452end;
453
454
455
456
457function TOniDataDat.GetExtendedExtensionsList: TExtensionsMap;
458var
459  i: LongWord;
460begin
461  SetLength(Result, Fdat_header.Extensions);
462  for i := 0 to Fdat_header.Extensions - 1 do
463  begin
464    Result[i] := Fdat_extensionsmap[i];
465  end;
466end;
467
468
469
470
471function TOniDataDat.LoadDatFile(fileid: LongWord): Tdata;
472begin
473  if fileid < Self.GetFilesCount then
474  begin
475    if FUnloadWhenUnused or not FDatOpened then
476      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
477    Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
478    SetLength(Result, Fdat_files[fileid].Size);
479    Fdat_file.Read(Result[0], Fdat_files[fileid].Size);
480    if UnloadWhenUnused then
481      Fdat_file.Free
482    else
483      FDatOpened := True;
484  end;
485end;
486
487
488
489
490procedure TOniDataDat.UpdateDatFile(fileid: LongWord; Data: Tdata);
491begin
492  if fileid < Self.GetFilesCount then
493  begin
494    if FUnloadWhenUnused or not FDatOpened then
495      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
496    Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
497    Fdat_file.Write(Data[0], Length(Data));
498    if UnloadWhenUnused then
499      Fdat_file.Free
500    else
501      FDatOpened := True;
502  end;
503end;
504
505
506
507
508procedure TOniDataDat.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
509begin
510  if fileid < Self.GetFilesCount then
511  begin
512    if FUnloadWhenUnused or not FDatOpened then
513      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
514    Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
515    Fdat_file.Read(target^, size);
516    if UnloadWhenUnused then
517      Fdat_file.Free
518    else
519      FDatOpened := True;
520  end;
521end;
522
523
524
525
526procedure TOniDataDat.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
527begin
528  if fileid < Self.GetFilesCount then
529  begin
530    if FUnloadWhenUnused or not FDatOpened then
531      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
532    Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
533    Fdat_file.Write(target^, size);
534    if UnloadWhenUnused then
535      Fdat_file.Free
536    else
537      FDatOpened := True;
538  end;
539end;
540
541
542
543
544function TOniDataDat.GetRawList(fileid: LongWord): TRawList;
545var
546  i: LongWord;
547begin
548  SetLength(Result, 0);
549  for i := 0 to High(RawListHandlers) do
550    if UpperCase(RawListHandlers[i].Ext) = UpperCase(Fdat_files[fileid].extension) then
551      if RawListHandlers[i].needed then
552      begin
553        Result := RawListHandlers[i].Handler(fileid);
554        Break;
555      end
556      else
557        Break;
558end;
559
560
561
562
563procedure TOniDataDat.LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord;
564  target: Pointer);
565begin
566  if not loc_sep then
567  begin
568    if FUnloadWhenUnused or not FRawOpened then
569      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
570        fmOpenReadWrite);
571    if raw_addr <= Fraw_file.Size then
572    begin
573      Fraw_file.Seek(raw_addr, soFromBeginning);
574      Fraw_file.Read(target^, size);
575    end;
576    if UnloadWhenUnused then
577      Fraw_file.Free
578    else
579      FRawOpened := True;
580  end
581  else
582  begin
583    if FUnloadWhenUnused or not FSepOpened then
584      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
585        fmOpenReadWrite);
586    if raw_addr <= Fsep_file.Size then
587    begin
588      Fsep_file.Seek(raw_addr, soFromBeginning);
589      Fsep_file.Read(target^, size);
590    end;
591    if UnloadWhenUnused then
592      Fsep_file.Free
593    else
594      FSepOpened := True;
595  end;
596end;
597
598
599
600
601procedure TOniDataDat.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
602var
603  raw_info: TRawInfo;
604begin
605  if fileid < Self.GetFilesCount then
606  begin
607    raw_info := Self.GetRawInfo(fileid, dat_offset);
608    if not raw_info.loc_sep then
609    begin
610      if FUnloadWhenUnused or not FRawOpened then
611        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
612          fmOpenReadWrite);
613      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
614      Fraw_file.Read(target^, raw_info.raw_size);
615      if UnloadWhenUnused then
616        Fraw_file.Free
617      else
618        FRawOpened := True;
619    end
620    else
621    begin
622      if FUnloadWhenUnused or not FSepOpened then
623        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
624          fmOpenReadWrite);
625      Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
626      Fsep_file.Read(target^, raw_info.raw_size);
627      if UnloadWhenUnused then
628        Fsep_file.Free
629      else
630        FSepOpened := True;
631    end;
632  end;
633end;
634
635
636
637
638procedure TOniDataDat.UpdateRawFile(fileid, dat_offset: LongWord;
639  size: LongWord; target: Pointer);
640var
641  raw_info: TRawInfo;
642begin
643  if fileid < Self.GetFilesCount then
644  begin
645    raw_info := Self.GetRawInfo(fileid, dat_offset);
646    if not raw_info.loc_sep then
647    begin
648      if FUnloadWhenUnused or not FRawOpened then
649        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
650          fmOpenReadWrite);
651      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
652      Fraw_file.Write(target^, raw_info.raw_size);
653      if UnloadWhenUnused then
654        Fraw_file.Free
655      else
656        FRawOpened := True;
657    end
658    else
659    begin
660      if FUnloadWhenUnused or not FSepOpened then
661        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
662          fmOpenReadWrite);
663      Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
664      Fsep_file.Write(target^, raw_info.raw_size);
665      if UnloadWhenUnused then
666        Fsep_file.Free
667      else
668        FSepOpened := True;
669    end;
670  end;
671end;
672
673
674
675
676procedure TOniDataDat.LoadRawFilePart(fileid, dat_offset: LongWord;
677  offset, size: LongWord; target: Pointer);
678var
679  raw_info: TRawInfo;
680  Data:     Tdata;
681  mem:      TMemoryStream;
682begin
683  if fileid < Self.GetFilesCount then
684  begin
685    raw_info := Self.GetRawInfo(fileid, dat_offset);
686    SetLength(Data, raw_info.raw_size);
687    Self.LoadRawFile(fileid, dat_offset, @Data[0]);
688    mem := TMemoryStream.Create;
689    mem.Write(Data[offset], size);
690    mem.Read(target^, size);
691    mem.Free;
692  end;
693end;
694
695
696
697
698procedure TOniDataDat.UpdateRawFilePart(fileid, dat_offset: LongWord;
699  offset, size: LongWord; target: Pointer);
700var
701  raw_info: TRawInfo;
702begin
703  if fileid < Self.GetFilesCount then
704  begin
705    raw_info := Self.GetRawInfo(fileid, dat_offset);
706    if not raw_info.loc_sep then
707    begin
708      if FUnloadWhenUnused or not FRawOpened then
709        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
710          fmOpenReadWrite);
711      Fraw_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
712      Fraw_file.Write(target^, raw_info.raw_size);
713      if UnloadWhenUnused then
714        Fraw_file.Free
715      else
716        FRawOpened := True;
717    end
718    else
719    begin
720      if FUnloadWhenUnused or not FSepOpened then
721        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
722          fmOpenReadWrite);
723      Fsep_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
724      Fsep_file.Write(target^, raw_info.raw_size);
725      if UnloadWhenUnused then
726        Fsep_file.Free
727      else
728        FSepOpened := True;
729    end;
730  end;
731end;
732
733
734
735
736function TOniDataDat.AppendRawFile(loc_sep: Boolean; size: LongWord;
737  target: Pointer): LongWord; //Returns new Address
738begin
739  if not loc_sep then
740  begin
741    if FUnloadWhenUnused or not FRawOpened then
742      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
743        fmOpenReadWrite);
744    Result := Fraw_file.Size;
745    Fraw_file.Seek(0, soFromEnd);
746    Fraw_file.Write(target^, size);
747    if UnloadWhenUnused then
748      Fraw_file.Free
749    else
750      FRawOpened := True;
751  end
752  else
753  begin
754    if FUnloadWhenUnused or not FSepOpened then
755      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
756        fmOpenReadWrite);
757    Result := Fsep_file.Size;
758    Fsep_file.Seek(0, soFromEnd);
759    Fsep_file.Write(target^, size);
760    if UnloadWhenUnused then
761      Fsep_file.Free
762    else
763      FSepOpened := True;
764  end;
765end;
766
767
768
769
770
771
772
773
774
775
776
777(*
778================================================================================
779                     Implementation of  TOniDataADB
780*)
781
782constructor TOniDataADB.Create(OLDBFilename: String; var Result: Boolean);
783var
784  i, j:  Byte;
785  temps: String;
786begin
787  if not FileExists(OLDBFilename) then
788  begin
789    ShowMessage('File doesn''t exist!!!');
790    Result := False;
791    Exit;
792  end;
793  FFileName := OLDBFilename;
794  FDatabase := TABSDatabase.Create(nil);
795  FDatabase.DatabaseName := 'OLDBcon';
796  FDatabase.DatabaseFileName := OLDBFilename;
797  FDatabase.Open;
798  FQuery := TABSQuery.Create(FDatabase);
799  FQuery.DatabaseName := 'OLDBcon';
800  FQuery.SQL.Text := 'SELECT [name],[value] FROM globals ORDER BY [name] ASC';
801  FQuery.Open;
802  FQuery.First;
803  repeat
804    if FQuery.FieldByName('name').AsString = 'dbversion' then
805    begin
806      if FQuery.FieldByName('value').AsString <> DBversion then
807      begin
808        ShowMessage('Database-file ' + #13 + #10 +
809          '"' + OLDBFilename + '"' + #13 + #10 +
810          'has wrong version. (Required: ' + DBversion + '; found: ' +
811          FQuery.FieldByName('value').AsString + ')');
812        FQuery.Close;
813        Result := False;
814        Exit;
815      end;
816    end;
817    if FQuery.FieldByName('name').AsString = 'lvl' then
818    begin
819      FLevelInfo.LevelNumber := StrToInt(FQuery.FieldByName('value').AsString);
820    end;
821    if FQuery.FieldByName('name').AsString = 'ident' then
822    begin
823      temps := FQuery.FieldByName('value').AsString;
824      for i := 0 to High(FLevelInfo.Ident) do
825      begin
826        j := i * 2 + 1;
827        case temps[j] of
828          '0'..'9':
829            FLevelInfo.Ident[i] := Ord(temps[j]) - 48;
830          'A'..'F':
831            FLevelInfo.Ident[i] := Ord(temps[j]) - 55;
832        end;
833        FLevelInfo.Ident[i] := FLevelInfo.Ident[i] * 16;
834        case temps[j + 1] of
835          '0'..'9':
836            FLevelInfo.Ident[i] := FLevelInfo.Ident[i] + Ord(temps[j + 1]) - 48;
837          'A'..'F':
838            FLevelInfo.Ident[i] := FLevelInfo.Ident[i] + Ord(temps[j + 1]) - 55;
839        end;
840      end;
841    end;
842    if FQuery.FieldByName('name').AsString = 'ident' then
843    begin
844      temps   := FQuery.FieldByName('value').AsString;
845      Fos_mac := temps = 'MAC';
846    end;
847    FQuery.Next;
848  until FQuery.EOF;
849  FQuery.Close;
850
851  Result   := True;
852  FBackend := ODB_ADB;
853end;
854
855
856
857
858procedure TOniDataADB.Close;
859begin
860  FDatabase.Close;
861  FDatabase.Free;
862  Self.Free;
863end;
864
865
866
867
868function TOniDataADB.GetFileInfo(fileid: LongWord): TFileInfo;
869begin
870  if fileid < Self.GetFilesCount then
871  begin
872    FQuery.SQL.Text := 'SELECT * FROM datfiles WHERE id=' + IntToStr(
873      fileid) + ' ORDER BY id ASC;';
874    FQuery.Open;
875    if FQuery.RecordCount = 1 then
876    begin
877      FQuery.First;
878      Result.ID      := FQuery.FieldByName('id').AsInteger;
879      Result.Name    := FQuery.FieldByName('name').AsString;
880      Result.Extension := FQuery.FieldByName('extension').AsString;
881      Result.FileName := FormatNumber(Result.ID, 5, '0') + '-' + Result.Name + '.' +
882        Result.Extension;
883      Result.Size    := FQuery.FieldByName('size').AsInteger;
884      Result.FileType := HexToLong(FQuery.FieldByName('contenttype').AsString);
885      Result.DatAddr := 0;
886      Result.opened  := False;
887    end;
888    FQuery.Close;
889  end
890  else
891  begin
892    Result.ID := -1;
893  end;
894end;
895
896
897
898
899function TOniDataADB.GetFilesList(ext: String; pattern: String;
900  NoEmptyFiles: Boolean; sort: TSortType): TStringArray;
901var
902  i:     LongWord;
903  where: String;
904  where_ext: String;
905  order: String;
906begin
907  where := '';
908  if Length(ext) > 0 then
909  begin
910    if Length(where) > 0 then
911      where := where + ' AND ';
912    if Pos(',', ext) > 0 then
913    begin
914      i := 1;
915      where_ext := '';
916      while i < Length(ext) do
917      begin
918        if Length(where_ext) > 0 then
919          where_ext := where_ext + ' OR ';
920        where_ext := where_ext + '(extension="' + MidStr(ext, i, 4) + '")';
921        i := i + 5;
922      end;
923      where := where + '(' + where_ext + ')';
924    end
925    else
926    begin
927      where := where + '(extension="' + ext + '")';
928    end;
929  end;
930  if Length(pattern) > 0 then
931  begin
932    if Length(where) > 0 then
933      where := where + ' AND ';
934    where := where + '(name LIKE "%' + pattern + '%")';
935  end;
936  if NoEmptyFiles then
937  begin
938    if Length(where) > 0 then
939      where := where + ' AND ';
940    where := where + '(contenttype<>2)';
941  end;
942  if Length(where) > 0 then
943    where := ' WHERE ' + where;
944  case sort of
945    stIDAsc:    order := ' ORDER BY id ASC';
946    stIDDesc:   order := ' ORDER BY id DESC';
947    stNameAsc:  order := ' ORDER BY name ASC, id ASC';
948    stNameDesc: order := ' ORDER BY name DESC, id ASC';
949    stExtAsc:   order := ' ORDER BY extension ASC, id ASC';
950    stExtDesc:  order := ' ORDER BY extension DESC, id ASC';
951  end;
952  FQuery.SQL.Text := 'SELECT id,name,extension FROM datfiles' + where + order + ';';
953  FQuery.Open;
954  if FQuery.RecordCount > 0 then
955  begin
956    FQuery.First;
957    SetLength(Result, FQuery.RecordCount);
958    i := 0;
959    repeat
960      Result[i] := FormatNumber(FQuery.FieldByName('id').AsInteger, 5, '0') + '-' +
961        FQuery.FieldByName('name').AsString + '.' + FQuery.FieldByName('extension').AsString;
962      Inc(i);
963      FQuery.Next;
964    until FQuery.EOF;
965  end;
966  FQuery.Close;
967end;
968
969
970
971
972function TOniDataADB.GetFilesCount: LongWord;
973begin
974  FQuery.SQL.Text := 'SELECT Count(*) AS cnumber FROM datfiles;';
975  FQuery.Open;
976  if FQuery.RecordCount > 0 then
977  begin
978    FQuery.First;
979    Result := FQuery.FieldByName('cnumber').AsInteger;
980  end
981  else
982    Result := 0;
983  FQuery.Close;
984end;
985
986
987
988
989function TOniDataADB.GetExtensionsList: TStringArray;
990var
991  i: LongWord;
992begin
993  SetLength(Result, 0);
994  FQuery.SQL.Text :=
995    'SELECT extension,count(extension) AS x FROM datfiles GROUP BY extension ORDER BY extension ASC;';
996  FQuery.Open;
997  if FQuery.RecordCount > 0 then
998  begin
999    SetLength(Result, FQuery.RecordCount);
1000    i := 0;
1001    repeat
1002      Result[i] := FQuery.FieldByName('extension').AsString + ' (' +
1003        IntToStr(FQuery.FieldByName('x').AsInteger) + ')';
1004      Inc(i);
1005      FQuery.Next;
1006    until FQuery.EOF;
1007  end;
1008  FQuery.Close;
1009end;
1010
1011
1012
1013
1014function TOniDataADB.GetExtendedExtensionsList: TExtensionsMap;
1015var
1016  i, j:  LongWord;
1017  temps: String;
1018  Data:  Tdata;
1019begin
1020  SetLength(Result, 0);
1021  FQuery.SQL.Text := 'SELECT ext,ident FROM extlist ORDER BY ext ASC;';
1022  FQuery.Open;
1023  if FQuery.RecordCount > 0 then
1024  begin
1025    SetLength(Result, FQuery.RecordCount);
1026    i := 0;
1027    repeat
1028      temps := FQuery.FieldByName('ext').AsString;
1029      for j := 0 to 3 do
1030        Result[i].Extension[j] := temps[4 - j];
1031      Data := DecodeHexString(FQuery.FieldByName('ident').AsString);
1032      for j := 0 to 7 do
1033        Result[i].Ident[j] := Data[j];
1034      Inc(i);
1035      FQuery.Next;
1036    until FQuery.EOF;
1037  end;
1038  FQuery.Close;
1039end;
1040
1041
1042
1043
1044function TOniDataADB.GetNamedFilesMap: TNamedFilesMap;
1045var
1046  i:     LongWord;
1047  temp:  Integer;
1048  temps: String;
1049  temparray: array of record
1050    id: Integer;
1051    fullname: String[50];
1052  end;
1053begin
1054  SetLength(temparray, 0);
1055  FQuery.SQL.Text :=
1056    'SELECT id,(extension+name) AS xname FROM datfiles WHERE Length(name)>0 ORDER BY extension,name ASC;';
1057  FQuery.Open;
1058  if FQuery.RecordCount > 0 then
1059  begin
1060    repeat
1061      temp  := FQuery.FieldByName('id').AsInteger;
1062      temps := FQuery.FieldByName('xname').AsString;
1063
1064      SetLength(temparray, Length(temparray) + 1);
1065      if Length(temparray) > 1 then
1066      begin
1067        for i := High(temparray) - 1 downto 0 do
1068        begin
1069          if StringSmaller(temps, temparray[i].fullname) then
1070          begin
1071            temparray[i + 1] := temparray[i];
1072            if i = 0 then
1073            begin
1074              temparray[i].id := temp;
1075              temparray[i].fullname := temps;
1076            end;
1077          end
1078          else
1079          begin
1080            temparray[i + 1].id := temp;
1081            temparray[i + 1].fullname := temps;
1082            Break;
1083          end;
1084        end;
1085      end
1086      else
1087      begin
1088        temparray[0].id := temp;
1089        temparray[0].fullname := temps;
1090      end;
1091      FQuery.Next;
1092    until FQuery.EOF;
1093  end;
1094  FQuery.Close;
1095  SetLength(Result, Length(temparray));
1096  for i := 0 to High(temparray) do
1097  begin
1098    Result[i].FileNumber := temparray[i].id;
1099    Result[i].blubb      := 0;
1100  end;
1101end;
1102
1103
1104
1105
1106function TOniDataADB.LoadDatFile(fileid: LongWord): Tdata;
1107var
1108  mem: TStream;
1109begin
1110  if fileid < Self.GetFilesCount then
1111  begin
1112    FQuery.SQL.Text := 'SELECT data FROM datfiles WHERE id=' + IntToStr(fileid) + ';';
1113    FQuery.Open;
1114    if FQuery.RecordCount > 0 then
1115    begin
1116      mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
1117      SetLength(Result, mem.Size);
1118      mem.Seek(0, soFromBeginning);
1119      mem.Read(Result[0], mem.Size);
1120      mem.Free;
1121    end;
1122    FQuery.Close;
1123  end;
1124end;
1125
1126
1127
1128
1129procedure TOniDataADB.UpdateDatFile(fileid: LongWord; Data: Tdata);
1130var
1131  MimeCoder: TStringFormat_MIME64;
1132  mem: TMemoryStream;
1133begin
1134  if fileid < Self.GetFilesCount then
1135  begin
1136    mimecoder := TStringFormat_MIME64.Create;
1137    mem := TMemoryStream.Create;
1138    mem.Write(Data[0], Length(Data));
1139    mem.Seek(0, soFromBeginning);
1140    FQuery.SQL.Text := 'UPDATE datfiles SET data=MimeToBin("' +
1141      MimeCoder.StrTo(mem.Memory, mem.Size) + '") WHERE id=' + IntToStr(fileid) + ';';
1142    FQuery.ExecSQL;
1143    mem.Free;
1144    mimecoder.Free;
1145  end;
1146end;
1147
1148
1149
1150
1151procedure TOniDataADB.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
1152var
1153  mem: TStream;
1154begin
1155  if fileid < Self.GetFilesCount then
1156  begin
1157    FQuery.SQL.Text := 'SELECT data FROM datfiles WHERE id=' + IntToStr(fileid) + ';';
1158    FQuery.Open;
1159    if FQuery.RecordCount > 0 then
1160    begin
1161      mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
1162      mem.Seek(offset, soFromBeginning);
1163      mem.Read(target^, size);
1164      mem.Free;
1165    end;
1166    FQuery.Close;
1167  end;
1168end;
1169
1170
1171
1172
1173procedure TOniDataADB.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
1174var
1175  MimeCoder: TStringFormat_MIME64;
1176  mem:  TMemoryStream;
1177  Data: Tdata;
1178begin
1179  if fileid < Self.GetFilesCount then
1180  begin
1181    Data := Self.LoadDatFile(fileid);
1182    mimecoder := TStringFormat_MIME64.Create;
1183    mem := TMemoryStream.Create;
1184    mem.Write(Data[0], Length(Data));
1185    mem.Seek(offset, soFromBeginning);
1186    mem.Write(target^, size);
1187    mem.Seek(0, soFromBeginning);
1188    FQuery.SQL.Text := 'UPDATE datfiles SET data=MimeToBin("' +
1189      MimeCoder.StrTo(mem.Memory, mem.Size) + '") WHERE id=' + IntToStr(fileid) + ';';
1190    FQuery.ExecSQL;
1191    mem.Free;
1192    mimecoder.Free;
1193  end;
1194end;
1195
1196
1197
1198
1199function TOniDataADB.GetRawList(fileid: LongWord): TRawList;
1200var
1201  i: LongWord;
1202begin
1203  SetLength(Result, 0);
1204  FQuery.SQL.Text := 'SELECT [src_link_offset],[size],[sep] FROM rawmap WHERE [src_id]=' +
1205    IntToStr(fileid) + ' ORDER BY src_link_offset ASC;';
1206  FQuery.Open;
1207  if FQuery.RecordCount > 0 then
1208  begin
1209    FQuery.First;
1210    SetLength(Result, FQuery.RecordCount);
1211    i := 0;
1212    repeat
1213      Result[i].src_id     := fileid;
1214      Result[i].src_offset := FQuery.FieldByName('src_link_offset').AsInteger;
1215      Result[i].raw_addr   := 0;
1216      Result[i].raw_size   := FQuery.FieldByName('size').AsInteger;
1217      Result[i].loc_sep    := FQuery.FieldByName('sep').AsBoolean;
1218      Inc(i);
1219      FQuery.Next;
1220    until FQuery.EOF;
1221  end;
1222  FQuery.Close;
1223end;
1224
1225
1226
1227
1228procedure TOniDataADB.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
1229var
1230  mem: TStream;
1231begin
1232  if fileid < Self.GetFilesCount then
1233  begin
1234    FQuery.SQL.Text := 'SELECT data FROM rawmap WHERE (src_id=' +
1235      IntToStr(fileid) + ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
1236    FQuery.Open;
1237    if FQuery.RecordCount > 0 then
1238    begin
1239      mem := FQuery.CreateBlobStream(FQuery.FieldByName('data'), bmRead);
1240      mem.Seek(0, soFromBeginning);
1241      mem.Read(target^, mem.size);
1242      mem.Free;
1243    end;
1244    FQuery.Close;
1245  end;
1246end;
1247
1248
1249
1250
1251procedure TOniDataADB.UpdateRawFile(fileid, dat_offset: LongWord;
1252  size: LongWord; target: Pointer);
1253var
1254  MimeCoder: TStringFormat_MIME64;
1255  mem: TMemoryStream;
1256begin
1257  if fileid < Self.GetFilesCount then
1258  begin
1259    mimecoder := TStringFormat_MIME64.Create;
1260    mem := TMemoryStream.Create;
1261    mem.Write(target^, size);
1262    mem.Seek(0, soFromBeginning);
1263    FQuery.SQL.Text := 'UPDATE rawmap SET data=MimeToBin("' + MimeCoder.StrTo(
1264      mem.Memory, mem.Size) + '") WHERE (src_id=' + IntToStr(fileid) +
1265      ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
1266    FQuery.ExecSQL;
1267    mem.Free;
1268    mimecoder.Free;
1269  end;
1270end;
1271
1272
1273
1274
1275procedure TOniDataADB.LoadRawFilePart(fileid, dat_offset: LongWord;
1276  offset, size: LongWord; target: Pointer);
1277var
1278  Data: Tdata;
1279  mem:  TMemoryStream;
1280begin
1281  if fileid < Self.GetFilesCount then
1282  begin
1283    SetLength(Data, Self.GetRawInfo(fileid, dat_offset).raw_size);
1284    Self.LoadRawFile(fileid, dat_offset, @Data[0]);
1285    mem := TMemoryStream.Create;
1286    mem.Write(Data[offset], size);
1287    mem.Read(target^, size);
1288    mem.Free;
1289  end;
1290end;
1291
1292
1293
1294
1295procedure TOniDataADB.UpdateRawFilePart(fileid, dat_offset: LongWord;
1296  offset, size: LongWord; target: Pointer);
1297var
1298  MimeCoder: TStringFormat_MIME64;
1299  mem:  TMemoryStream;
1300  Data: Tdata;
1301begin
1302  if fileid < Self.GetFilesCount then
1303  begin
1304    SetLength(Data, Self.GetRawInfo(fileid, offset).raw_size);
1305    Self.LoadRawFile(fileid, offset, @Data[0]);
1306    mimecoder := TStringFormat_MIME64.Create;
1307    mem := TMemoryStream.Create;
1308    mem.Write(Data[0], Length(Data));
1309    mem.Seek(offset, soFromBeginning);
1310    mem.Write(target^, size);
1311    mem.Seek(0, soFromBeginning);
1312    FQuery.SQL.Text := 'UPDATE rawmap SET data=MimeToBin("' + MimeCoder.StrTo(
1313      mem.Memory, mem.Size) + '") WHERE (src_id=' + IntToStr(fileid) +
1314      ') AND (src_link_offset=' + IntToStr(dat_offset) + ');';
1315    FQuery.ExecSQL;
1316    mem.Free;
1317    mimecoder.Free;
1318  end;
1319end;
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331function CreateDataConnection(filename: String; backend: Integer): Boolean;
1332var
1333  answer: Boolean;
1334begin
1335  if Assigned(OniDataConnection) then
1336  begin
1337    OniDataConnection.Close;
1338    OniDataConnection.Free;
1339    OniDataConnection := nil;
1340  end;
1341  case backend of
1342    ODB_Dat:
1343      OniDataConnection := TOniDataDat.Create(filename, answer);
1344    ODB_ADB:
1345      OniDataConnection := TOniDataADB.Create(filename, answer);
1346    else
1347      ShowMessage('Unknown Backend');
1348      Result := False;
1349      Exit;
1350  end;
1351
1352  if answer then
1353  begin
1354    //      ShowMessage('file loaded');
1355    //      ShowMessage('Files: '+IntToStr(OniDataConnection.GetFilesCount));
1356    Result := True;
1357  end
1358  else
1359  begin
1360    ShowMessage('File not loaded');
1361    OniDataConnection.Close;
1362    OniDataConnection.Free;
1363    Result := False;
1364  end;
1365end;
1366
1367
1368
1369
1370procedure CloseDataConnection;
1371begin
1372  if Assigned(OniDataConnection) then
1373  begin
1374    OniDataConnection.Close;
1375    OniDataConnection := nil;
1376  end;
1377end;
1378
1379end.
Note: See TracBrowser for help on using the repository browser.