source: oup/current/Code_OniDataClass.pas @ 43

Last change on this file since 43 was 43, checked in by alloc, 17 years ago

DevTree 0.33a.

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