ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/oup/current/DataAccess/Access_OniArchive.pas
(Generate patch)

Comparing:
oup/rewrite/DataAccess/Access_OniArchive.pas (file contents), Revision 93 by alloc, Thu Jan 18 17:15:59 2007 UTC vs.
oup/current/DataAccess/Access_OniArchive.pas (file contents), Revision 192 by alloc, Thu May 24 17:48:18 2007 UTC

# Line 1 | Line 1
1   unit Access_OniArchive;
2   interface
3  
4 < uses DataAccess, Classes;
4 > uses DataAccess, Classes, TypeDefs;
5  
6   type
7 {
8  THeader = packed record
9    Ident:      array[0..$13] of Byte;
10    Files:      LongWord;
11    NamedFiles: LongWord;
12    Extensions: LongWord;
13    DataAddr:   LongWord;
14    DataSize:   LongWord;
15    NamesAddr:  LongWord;
16    NamesSize:  LongWord;
17    Ident2:     array[0..$F] of Byte;
18  end;
19  TFilesMap = array of packed record
20    Extension: array[0..$3] of Char;
21    DataAddr:  LongWord;
22    NameAddr:  LongWord;
23    FileSize:  LongWord;
24    FileType:  LongWord;
25  end;
26
27  TFileInfo = packed record
28    ID:      Integer;
29    FileName: String;
30    FileNameHex: String;
31    Extension: String[4];
32    Name:    String;
33    Size:    LongWord;
34    FileType: LongWord;
35    DatAddr: LongWord;
36    opened:  Boolean;
37  end;
38  TFiles = array of TFileInfo;
39
40  TNamedFilesMap = array of packed record
41    FileNumber: LongWord;
42    blubb:      LongWord;
43  end;
44  TExtensionsMap = array of packed record
45    Ident:     array[0..$7] of Byte;
46    Extension: array[0..$3] of Char;
47    ExtCount:  LongWord;
48  end;
49 }
50
7    TAccess_OniArchive = class(TDataAccess)
8    private
9 < {    Fdat_file:     TFileStream;
10 <    Fraw_file:     TFileStream;
11 <    Fsep_file:     TFileStream;
12 <    Fdat_header:   THeader;
13 <    Fdat_filesmap: TFilesMap;
14 <    Fdat_files:    TFiles;
15 <    Fdat_namedfilesmap: TNamedFilesMap;
16 <    Fdat_extensionsmap: TExtensionsMap;
17 <    FUnloadWhenUnused: Boolean;
62 <    FDatOpened:    Boolean;
63 <    FRawOpened:    Boolean;
64 <    FSepOpened:    Boolean;
9 >    Fdat_file:           TFileStream;
10 >    Fraw_file:           TFileStream;
11 >    Fsep_file:           TFileStream;
12 >    Fdat_files:          TFiles;
13 >    Fdat_extensionsmap:  TExtensionsMap;
14 >    FUnloadWhenUnused:   Boolean;
15 >    FDatOpened:          Boolean;
16 >    FRawOpened:          Boolean;
17 >    FSepOpened:          Boolean;
18    protected
19    public
20      property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write FUnloadWhenUnused;
21  
22 <    constructor Create(DatFilename: String; var Result: Boolean); override;
22 >    constructor Create(DatFilename: String; ConnectionID: Integer; var Msg: TStatusMessages); override;
23      procedure Close; override;
24  
25 <    function GetFileInfo(fileid: Integer): TFileInfo; override;
26 <    function GetFilesList(ext: String; pattern: String;
27 <      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; override;
28 <    function GetFilesCount: LongWord; override;
29 <    function GetExtensionsList: TStringArray; override;
30 <    function GetExtendedExtensionsList: TExtensionsMap; override;
31 <
32 <    function LoadDatFile(fileid: LongWord): Tdata; override;
33 <    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
34 <    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
35 <    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
36 <
37 <    procedure LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord; target: Pointer);
38 <    function GetRawList(fileid: LongWord): TRawList; override;
39 <    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
40 <    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
41 <      target: Pointer); override;
42 <    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
43 <      offset, size: LongWord; target: Pointer); override;
44 <    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
45 <      offset, size: LongWord; target: Pointer); override;
46 <    function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
47 <      override;//Returns new Address
25 >    function GetFileInfo(FileID: Integer): TFileInfo; override;
26 >    function GetFilesList(Ext: String; Pattern: String;
27 >      NoEmptyFiles: Boolean; SortType: TSortType): TStrings; override;
28 >    function GetFileCount: Integer; override;
29 >    function GetExtensionsList(ExtListFormat: TExtensionFormat): TStrings; override;
30 >
31 >    procedure LoadDatFile(FileID: Integer; var Target: TStream); overload; override;
32 >    procedure UpdateDatFile(FileID: Integer; Src: TStream); overload; override;
33 >    procedure LoadDatFilePart(FileID, Offset, Size: Integer; var Target: TStream); overload; override;
34 >    procedure UpdateDatFilePart(FileID, Offset, Size: Integer; Src: TStream); overload; override;
35 >
36 >    function GetDatLinks(FileID: Integer): TDatLinkList; override;
37 >    function GetDatLink(FileID, DatOffset: Integer): TDatLink; override;
38 >    function GetRawList(FileID: Integer): TRawDataList; override;
39 >    function GetRawInfo(FileID, DatOffset: Integer): TRawDataInfo; override;
40 >
41 >    procedure LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; var target: TStream); overload;
42 >    procedure LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; target: Pointer); overload;
43 >    procedure LoadRawFile(FileID, DatOffset: Integer; var Target: TStream); overload; override;
44 >    procedure UpdateRawFile(FileID, DatOffset: Integer; Src: TStream); overload; override;
45 >    procedure LoadRawFilePart(FileID, DatOffset, Offset, Size: Integer; var Target: TStream); overload; override;
46 >    procedure UpdateRawFilePart(FileID, DatOffset, Offset, Size: Integer; Src: TStream); overload; override;
47 >
48 >    function AppendRawFile(LocSep: Boolean; Src: TStream): Integer; overload; override;
49    published
50 < }  end;
50 >  end;
51  
52   implementation
53  
54 + uses
55 +  SysUtils, StrUtils, Data, Functions, RawList, DatLinks, Math;
56 +
57  
58   (*
59   ================================================================================
60                        Implementation of  TOniDataDat
61   *)
62  
63 < {
64 < constructor TOniDataDat.Create(DatFilename: String; var Result: Boolean);
108 < const
109 <  header_ident1_pc: array[0..$13] of Byte =
110 <    ($1F, $27, $DC, $33, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
111 <    $14, $00, $10, $00, $08, $00);
112 <  header_ident1_mac: array[0..$13] of Byte =
113 <    ($61, $30, $C1, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
114 <    $14, $00, $10, $00, $08, $00);
115 <  header_ident1_macbeta: array[0..$13] of Byte =
116 <    ($81, $11, $8D, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
117 <    $14, $00, $10, $00, $08, $00);
118 <  header_ident2: array[0..$F] of Byte =
119 <    ($99, $CF, $40, $00, $90, $4F, $63, $00, $F4, $55, $5F, $00, $90, $4F, $63, $00);
63 >
64 > constructor TAccess_OniArchive.Create(DatFilename: String; ConnectionID: Integer; var Msg: TStatusMessages);
65   var
66 <  i: LongWord;
67 <  header_pc, header_mac: Boolean;
66 >  i: Integer;
67 >  header_pc, header_mac, header_macbeta: Boolean;
68 >  Fdat_header:   THeader;
69 >  Fdat_filesmap: TFilesMap;
70 >  Fdat_namedfilesmap: TNamedFilesMap;
71   begin
72    FUnloadWhenUnused := True;
73    FDatOpened := False;
74    FRawOpened := False;
75 +  Msg := SM_UnknownError;
76    if not FileExists(DatFilename) then
77    begin
78 <    ShowMessage('File doesn''t exist!!!');
130 <    Result := False;
78 >    Msg := SM_FileNotFound;
79      Exit;
80    end;
81    FFileName := DatFilename;
# Line 135 | Line 83 | begin
83    Fdat_file.Read(Fdat_header, SizeOf(Fdat_header));
84    header_pc  := True;
85    header_mac := True;
86 <  for i := 0 to High(Fdat_header.Ident) do
86 >  header_macbeta := True;
87 >  for i := 0 to High(Fdat_header.GlobalIdent) do
88 >    if Fdat_header.GlobalIdent[i] <> HeaderGlobalIdent[i] then
89 >    begin
90 >      Msg := SM_IncompatibleFile;
91 >      Exit;
92 >    end;
93 >
94 >  for i := 0 to High(Fdat_header.OSIdent) do
95    begin
96 <    FLevelInfo.Ident[i] := Fdat_header.Ident[i];
141 <    if Fdat_header.Ident[i] <> header_ident1_pc[i] then
96 >    if Fdat_header.OSIdent[i] <> HeaderOSIdentWin[i] then
97        header_pc := False;
98 <    if Fdat_header.Ident[i] <> header_ident1_mac[i] then
98 >    if Fdat_header.OSIdent[i] <> HeaderOSIdentMac[i] then
99        header_mac := False;
100 +    if Fdat_header.OSIdent[i] <> HeaderOSIdentMacBeta[i] then
101 +      header_macbeta := False;
102    end;
103 <  if not (header_pc xor header_mac) then
103 >  if not (header_pc xor header_mac xor header_macbeta) then
104    begin
105 <    Result := False;
105 >    Msg := SM_IncompatibleFile;
106      Exit;
107    end
108    else
109    begin
110 <    if (header_pc and not header_mac) then
111 <      Fos_mac := False
112 <    else
113 <      Fos_mac := True;
110 >    if (header_pc and not header_mac and not header_macbeta) then
111 >      FDataOS := DOS_WIN
112 >    else if (not header_pc and header_mac and not header_macbeta) then
113 >      FDataOS := DOS_MAC
114 >    else if (not header_pc and not header_mac and header_macbeta) then
115 >      FDataOS := DOS_MACBETA;
116    end;
117    SetLength(Fdat_filesmap, Fdat_header.Files);
118    SetLength(Fdat_files, Fdat_header.Files);
# Line 179 | Line 138 | begin
138      begin
139        Fdat_files[i].Name := '';
140      end;
182    Fdat_files[i].FileName    :=
183      FormatNumber(i, 5, '0') + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
184    Fdat_files[i].FileNameHex :=
185      IntToHex(i, 4) + '-' + Fdat_files[i].Name + '.' + Fdat_files[i].Extension;
141    end;
142    Fdat_file.Seek($40 + Fdat_header.Files * $14, soFromBeginning);
143    SetLength(Fdat_namedfilesmap, Fdat_header.NamedFiles);
# Line 195 | Line 150 | begin
150      Fdat_file.Read(Fdat_extensionsmap[i], SizeOf(Fdat_extensionsmap[i]));
151  
152    Fdat_file.Seek(Fdat_files[0].DatAddr + 7, soFromBeginning);
153 <  Fdat_file.Read(FLevelInfo.LevelNumber, 1);
154 <  FLevelInfo.LevelNumber := FLevelInfo.LevelNumber div 2;
153 >  Fdat_file.Read(FLevelNumber, 1);
154 >  FLevelNumber := FLevelNumber div 2;
155  
156    Fdat_file.Free;
157  
158 <  Result   := True;
159 <  FBackend := ODB_Dat;
158 >  Msg := SM_OK;
159 >  FBackend := DB_ONI;
160 >  FConnectionID := ConnectionID;
161 >  FChangeRights := [CR_EditDat, CR_EditRaw, CR_AppendRaw];
162   end;
163  
164  
165  
166  
167 < procedure TOniDataDat.Close;
167 > procedure TAccess_OniArchive.Close;
168   begin
169 <  if not FUnloadWhenUnused and FDatOpened then
169 >  if FDatOpened then
170      Fdat_file.Free;
171 <  if not FUnloadWhenUnused and FRawOpened then
171 >  if FRawOpened then
172      Fraw_file.Free;
173 <  if not FUnloadWhenUnused and FSepOpened then
173 >  if FSepOpened then
174      Fsep_file.Free;
175    Self.Free;
176   end;
# Line 221 | Line 178 | end;
178  
179  
180  
181 < function TOniDataDat.GetFileInfo(fileid: Integer): TFileInfo;
181 > function TAccess_OniArchive.GetFileInfo(fileid: Integer): TFileInfo;
182   begin
183    if fileid = -1 then
184    begin
185      Result := inherited GetFileInfo(fileid);
186      Exit;
187    end;
188 <  if fileid < Self.GetFilesCount then
188 >  if fileid < Self.GetFileCount then
189      Result    := Fdat_files[fileid]
190    else
191      Result.ID := -1;
# Line 237 | Line 194 | end;
194  
195  
196  
197 < function TOniDataDat.GetFilesList(ext: String; pattern: String;
198 <  NoEmptyFiles: Boolean; sort: TSortType): TStringArray;
197 > function TAccess_OniArchive.GetFilesList(ext: String; pattern: String;
198 >  NoEmptyFiles: Boolean; SortType: TSortType): TStrings;
199   var
200 <  i: LongWord;
201 <  list: TStringList;
200 >  i:      Integer;
201 >  list:   TStringList;
202    id, name, extension: String;
203    fields: TStrings;
204  
205    procedure getfields;
206    begin
207 <     fields.CommaText := StringReplace(AnsiQuotedStr(list.Strings[i], '"'), ';', '","', [rfReplaceAll]);
208 <    if sort in [stIDAsc, stIDDesc] then
207 >    fields.CommaText := StringReplace(AnsiQuotedStr(list.Strings[i], '"'), ';', '","', [rfReplaceAll]);
208 >    if SortType in [ST_IDAsc, ST_IDDesc] then
209      begin
210        id := fields.Strings[0];
211        name := fields.Strings[1];
212        extension := fields.Strings[2];
213      end;
214 <    if sort in [stNameAsc, stNameDesc] then
214 >    if SortType in [ST_NameAsc, ST_NameDesc] then
215      begin
216        id := fields.Strings[1];
217        name := fields.Strings[0];
218        extension := fields.Strings[2];
219      end;
220 <    if sort in [stExtAsc, stExtDesc] then
220 >    if SortType in [ST_ExtAsc, ST_ExtDesc] then
221      begin
222        id := fields.Strings[1];
223        name := fields.Strings[2];
224        extension := fields.Strings[0];
225      end;
226 +    if SortType in [ST_ExtNameAsc, ST_ExtNameDesc] then
227 +    begin
228 +      id := fields.Strings[2];
229 +      name := fields.Strings[1];
230 +      extension := fields.Strings[0];
231 +    end;
232    end;
233  
234   begin
235    list := TStringList.Create;
236    list.Sorted := True;
237 <  for i := 0 to Fdat_header.Files - 1 do
237 >  for i := 0 to GetFileCount - 1 do
238    begin
239      if ((Length(ext) = 0) or (Pos(Fdat_files[i].Extension, ext) > 0)) and
240        ((Length(pattern) = 0) or
# Line 279 | Line 242 | begin
242      begin
243        if (NoEmptyFiles = False) or ((Fdat_files[i].FileType and $02) = 0) then
244        begin
245 <        if AppSettings.FilenumbersAsHex then
283 <          id := IntToHex(Fdat_files[i].ID, 4)
284 <        else
285 <          id := FormatNumber(Fdat_files[i].ID, 5, '0');
245 >        id := FormatNumber(Fdat_files[i].ID, 5, '0');
246          name := Fdat_files[i].Name;
247          extension := Fdat_files[i].Extension;
248  
249 <        case sort of
250 <          stIDAsc, stIDDesc:     list.Add(id + ';' + name + ';' + extension);
251 <          stNameAsc, stNameDesc: list.Add(name + ';' + id + ';' + extension);
252 <          stExtAsc, stExtDesc:   list.Add(extension + ';' + id + ';' + name);
249 >        case SortType of
250 >          ST_IDAsc, ST_IDDesc:     list.Add(id + ';' + name + ';' + extension);
251 >          ST_NameAsc, ST_NameDesc: list.Add(name + ';' + id + ';' + extension);
252 >          ST_ExtAsc, ST_ExtDesc:   list.Add(extension + ';' + id + ';' + name);
253 >          ST_ExtNameAsc, ST_ExtNameDesc: list.Add(name + ';' + extension + ';' + id);
254          end;
255        end;
256      end;
257    end;
258 <  SetLength(Result, list.Count);
259 <  if Length(Result) > 0 then
258 >  if not Assigned(Result) then
259 >    Result := TStringList.Create;
260 >  if list.Count > 0 then
261    begin
262      fields := TStringList.Create;
263 <    if sort in [stIDAsc, stNameAsc, stExtAsc] then
263 >    if SortType in [ST_IDAsc, ST_NameAsc, ST_ExtAsc, ST_ExtNameAsc] then
264        for i := 0 to list.Count - 1 do
265        begin
266          getfields;
267 <        Result[i] := id + '-' + name + '.' + extension;
267 >        Result.Add(id + '-' + name + '.' + extension);
268        end
269      else
270        for i := list.Count - 1 downto 0 do
271        begin
272          getfields;
273 <        Result[list.Count - i - 1] := id + '-' + name + '.' + extension;
273 >        Result.Add(id + '-' + name + '.' + extension);
274        end;
275      fields.Free;
276    end;
# Line 318 | Line 280 | end;
280  
281  
282  
283 < function TOniDataDat.GetFilesCount: LongWord;
283 > function TAccess_OniArchive.GetFileCount: Integer;
284   begin
285 <  Result := Fdat_header.Files;
285 >  Result := Length(Fdat_files);
286   end;
287  
288  
289  
290  
291 < function TOniDataDat.GetExtensionsList: TStringArray;
291 > function TAccess_OniArchive.GetExtensionsList(ExtListFormat: TExtensionFormat): TStrings;
292   var
293 <  i: LongWord;
293 >  i: Integer;
294   begin
295 <  SetLength(Result, Fdat_header.Extensions);
296 <  for i := 0 to Fdat_header.Extensions - 1 do
295 >  if not Assigned(Result) then
296 >    Result := TStringList.Create;
297 >  if Result is TStringList then
298 >    TStringList(Result).Sorted := True;
299 >  for i := 0 to Length(Fdat_extensionsmap) - 1 do
300    begin
301      with Fdat_extensionsmap[i] do
302      begin
303 <      Result[i] := Extension[3] + Extension[2] + Extension[1] + Extension[0] +
304 <        ' (' + IntToStr(ExtCount) + ')';
303 >      case ExtListFormat of
304 >        EF_ExtOnly:
305 >          Result.Add(Extension[3] + Extension[2] + Extension[1] + Extension[0]);
306 >        EF_ExtCount:
307 >          Result.Add(Extension[3] + Extension[2] + Extension[1] + Extension[0] +
308 >                ' (' + IntToStr(ExtCount) + ')');
309 >      end;
310      end;
311    end;
312   end;
313  
314  
315  
316 <
347 < function TOniDataDat.GetExtendedExtensionsList: TExtensionsMap;
316 > procedure TAccess_OniArchive.LoadDatFile(FileID: Integer; var Target: TStream);
317   var
318 <  i: LongWord;
318 >  streampos: Integer;
319   begin
320 <  SetLength(Result, Fdat_header.Extensions);
352 <  for i := 0 to Fdat_header.Extensions - 1 do
320 >  if fileid < GetFileCount then
321    begin
322 <    Result[i] := Fdat_extensionsmap[i];
323 <  end;
324 < end;
357 <
358 <
359 <
360 <
361 < function TOniDataDat.LoadDatFile(fileid: LongWord): Tdata;
362 < begin
363 <  if fileid < Self.GetFilesCount then
364 <  begin
365 <    if FUnloadWhenUnused or not FDatOpened then
322 >    if not Assigned(Target) then
323 >      Target := TMemoryStream.Create;
324 >    if not FDatOpened then
325        Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
326      Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
327 <    SetLength(Result, Fdat_files[fileid].Size);
328 <    Fdat_file.Read(Result[0], Fdat_files[fileid].Size);
327 >    streampos := Target.Position;
328 >    Target.CopyFrom(Fdat_file, Fdat_files[fileid].Size);
329 >    Target.Seek(streampos, soFromBeginning);
330      if UnloadWhenUnused then
331 <      Fdat_file.Free
331 >    begin
332 >      Fdat_file.Free;
333 >      FDatOpened := False;
334 >    end
335      else
336        FDatOpened := True;
337    end;
338   end;
339  
340 <
378 <
379 <
380 < procedure TOniDataDat.UpdateDatFile(fileid: LongWord; Data: Tdata);
340 > procedure TAccess_OniArchive.UpdateDatFile(FileID: Integer; Src: TStream);
341   begin
342 <  if fileid < Self.GetFilesCount then
342 >  if fileid < GetFileCount then
343    begin
344 <    if FUnloadWhenUnused or not FDatOpened then
344 >    if not FDatOpened then
345        Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
346      Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
347 <    Fdat_file.Write(Data[0], Length(Data));
347 >    Fdat_file.CopyFrom(Src, Fdat_files[fileid].Size);
348      if UnloadWhenUnused then
349 <      Fdat_file.Free
349 >    begin
350 >      Fdat_file.Free;
351 >      FDatOpened := False;
352 >    end
353      else
354        FDatOpened := True;
355    end;
356   end;
357  
358 <
359 <
360 <
398 < procedure TOniDataDat.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
358 > procedure TAccess_OniArchive.LoadDatFilePart(FileID, Offset, Size: Integer; var Target: TStream);
359 > var
360 >  streampos: Integer;
361   begin
362 <  if fileid < Self.GetFilesCount then
362 >  if fileid < GetFileCount then
363    begin
364 <    if FUnloadWhenUnused or not FDatOpened then
364 >    if not Assigned(Target) then
365 >      Target := TMemoryStream.Create;
366 >    if not FDatOpened then
367        Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
368      Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
369 <    Fdat_file.Read(target^, size);
369 >    streampos := Target.Position;
370 >    Target.CopyFrom(Fdat_file, size);
371 >    Target.Seek(streampos, soFromBeginning);
372      if UnloadWhenUnused then
373 <      Fdat_file.Free
373 >    begin
374 >      FDatOpened := False;
375 >      Fdat_file.Free;
376 >    end
377      else
378        FDatOpened := True;
379    end;
380   end;
381  
382 <
414 <
415 <
416 < procedure TOniDataDat.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
382 > procedure TAccess_OniArchive.UpdateDatFilePart(FileID, Offset, Size: Integer; Src: TStream);
383   begin
384 <  if fileid < Self.GetFilesCount then
384 >  if fileid < GetFileCount then
385    begin
386 <    if FUnloadWhenUnused or not FDatOpened then
386 >    if not FDatOpened then
387        Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
388      Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
389 <    Fdat_file.Write(target^, size);
389 >    Fdat_file.CopyFrom(Src, Size);
390      if UnloadWhenUnused then
391 <      Fdat_file.Free
391 >    begin
392 >      Fdat_file.Free;
393 >      FDatOpened := False;
394 >    end
395      else
396        FDatOpened := True;
397    end;
# Line 430 | Line 399 | end;
399  
400  
401  
402 + function TAccess_OniArchive.GetDatLink(FileID, DatOffset: Integer): TDatLink;
403 + var
404 +  link: Integer;
405 + begin
406 +  Result := DatLinksManager.GetDatLink(FConnectionID, FileID, DatOffset);
407 +  LoadDatFilePart(fileid, Result.SrcOffset, 4, @link);
408 +  if link > 0 then
409 +    Result.DestID := link div 256
410 +  else
411 +    Result.DestID := -1;
412 + end;
413 +
414  
415 < function TOniDataDat.GetRawList(fileid: LongWord): TRawList;
415 > function TAccess_OniArchive.GetDatLinks(FileID: Integer): TDatLinkList;
416   var
417 <  i: LongWord;
417 >  i: Integer;
418 >  link: Integer;
419   begin
420 <  SetLength(Result, 0);
421 <  for i := 0 to High(RawListHandlers) do
422 <    if UpperCase(RawListHandlers[i].Ext) = UpperCase(Fdat_files[fileid].extension) then
423 <      if RawListHandlers[i].needed then
424 <      begin
425 <        Result := RawListHandlers[i].Handler(Self, fileid);
426 <        Break;
427 <      end
420 >  Result := DatLinksManager.GetDatLinks(FConnectionID, FileID);
421 >  if Length(Result) > 0 then
422 >  begin
423 >    for i := 0 to High(Result) do
424 >    begin
425 >      LoadDatFilePart(fileid, Result[i].SrcOffset, 4, @link);
426 >      if link > 0 then
427 >        Result[i].DestID := link div 256
428        else
429 <        Break;
429 >        Result[i].DestID := -1;
430 >    end;
431 >  end;
432 > end;
433 >
434 >
435 > function TAccess_OniArchive.GetRawList(FileID: Integer): TRawDataList;
436 > begin
437 >  Result := RawLists.GetRawList(FConnectionID, FileID);
438   end;
439  
440  
441 + function TAccess_OniArchive.GetRawInfo(FileID, DatOffset: Integer): TRawDataInfo;
442 + begin
443 +  Result := RawLists.GetRawInfo(FConnectionID, FileID, DatOffset);
444 + end;
445 +
446  
447  
448 < procedure TOniDataDat.LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord;
454 <  target: Pointer);
448 > procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; var target: TStream);
449   begin
450 <  if not loc_sep then
450 >  if not Assigned(Target) then
451 >    Target := TMemoryStream.Create;
452 >  if not LocSep then
453    begin
454 <    if FUnloadWhenUnused or not FRawOpened then
454 >    if not FRawOpened then
455        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
456          fmOpenReadWrite);
457 <    if raw_addr <= Fraw_file.Size then
457 >    if RawAddr <= Fraw_file.Size then
458      begin
459 <      Fraw_file.Seek(raw_addr, soFromBeginning);
460 <      Fraw_file.Read(target^, size);
459 >      Fraw_file.Seek(RawAddr, soFromBeginning);
460 >      Target.CopyFrom(Fraw_file, size);
461 >      Target.Seek(0, soFromBeginning);
462      end;
463      if UnloadWhenUnused then
464 <      Fraw_file.Free
464 >    begin
465 >      FRawOpened := False;
466 >      Fraw_file.Free;
467 >    end
468      else
469        FRawOpened := True;
470    end
471    else
472    begin
473 <    if FUnloadWhenUnused or not FSepOpened then
473 >    if not FSepOpened then
474        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
475          fmOpenReadWrite);
476 <    if raw_addr <= Fsep_file.Size then
476 >    if RawAddr <= Fsep_file.Size then
477      begin
478 <      Fsep_file.Seek(raw_addr, soFromBeginning);
479 <      Fsep_file.Read(target^, size);
478 >      Fsep_file.Seek(RawAddr, soFromBeginning);
479 >      Target.CopyFrom(Fsep_file, size);
480 >      Target.Seek(0, soFromBeginning);
481      end;
482      if UnloadWhenUnused then
483 <      Fsep_file.Free
483 >    begin
484 >      FSepOpened := False;
485 >      Fsep_file.Free;
486 >    end
487      else
488        FSepOpened := True;
489    end;
490   end;
491  
492 + procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; target: Pointer);
493 + var
494 +  data: TStream;
495 + begin
496 +  data := nil;
497 +  LoadRawOffset(LocSep, RawAddr, Size, data);
498 +  data.Read(Target^, Size);
499 +  data.Free;
500 + end;
501  
502 <
490 <
491 < procedure TOniDataDat.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
502 > procedure TAccess_OniArchive.LoadRawFile(FileID, DatOffset: Integer; var Target: TStream);
503   var
504 <  raw_info: TRawInfo;
504 >  raw_info: TRawDataInfo;
505 >  streampos: Integer;
506   begin
507 <  if fileid < Self.GetFilesCount then
507 >  if not Assigned(Target) then
508 >    Target := TMemoryStream.Create;
509 >  if fileid < GetFileCount then
510    begin
511 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
512 <    if not raw_info.loc_sep then
511 >    raw_info := Self.GetRawInfo(FileID, DatOffset);
512 >    if not raw_info.LocSep then
513      begin
514 <      if FUnloadWhenUnused or not FRawOpened then
514 >      if not FRawOpened then
515          Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
516            fmOpenReadWrite);
517 <      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
518 <      Fraw_file.Read(target^, raw_info.raw_size);
517 >      Fraw_file.Seek(raw_info.RawAddr, soFromBeginning);
518 >      streampos := Target.Position;
519 >      Target.CopyFrom(Fraw_file, raw_info.RawSize);
520 >      Target.Seek(streampos, soFromBeginning);
521        if UnloadWhenUnused then
522 <        Fraw_file.Free
522 >      begin
523 >        FRawOpened := False;
524 >        Fraw_file.Free;
525 >      end
526        else
527          FRawOpened := True;
528      end
# Line 512 | Line 531 | begin
531        if FUnloadWhenUnused or not FSepOpened then
532          Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
533            fmOpenReadWrite);
534 <      Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
535 <      Fsep_file.Read(target^, raw_info.raw_size);
534 >      Fsep_file.Seek(raw_info.RawAddr, soFromBeginning);
535 >      streampos := Target.Position;
536 >      Target.CopyFrom(Fsep_file, raw_info.RawSize);
537 >      Target.Seek(streampos, soFromBeginning);
538        if UnloadWhenUnused then
539 <        Fsep_file.Free
539 >      begin
540 >        FSepOpened := False;
541 >        Fsep_file.Free;
542 >      end
543        else
544          FSepOpened := True;
545      end;
546    end;
547   end;
548  
549 <
526 <
527 <
528 < procedure TOniDataDat.UpdateRawFile(fileid, dat_offset: LongWord;
529 <  size: LongWord; target: Pointer);
549 > procedure TAccess_OniArchive.UpdateRawFile(FileID, DatOffset: Integer; Src: TStream);
550   var
551 <  raw_info: TRawInfo;
551 >  raw_info: TRawDataInfo;
552   begin
553 <  if fileid < Self.GetFilesCount then
553 >  if fileid < GetFileCount then
554    begin
555 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
556 <    if not raw_info.loc_sep then
555 >    raw_info := GetRawInfo(FileID, DatOffset);
556 >    if not raw_info.LocSep then
557      begin
558 <      if FUnloadWhenUnused or not FRawOpened then
558 >      if not FRawOpened then
559          Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
560            fmOpenReadWrite);
561 <      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
562 <      Fraw_file.Write(target^, raw_info.raw_size);
561 >      Fraw_file.Seek(raw_info.RawAddr, soFromBeginning);
562 >      Fraw_file.CopyFrom(Src, Min(raw_info.RawSize, Src.Size));
563        if UnloadWhenUnused then
564 <        Fraw_file.Free
564 >      begin
565 >        FRawOpened := False;
566 >        Fraw_file.Free;
567 >      end
568        else
569          FRawOpened := True;
570      end
571      else
572      begin
573 <      if FUnloadWhenUnused or not FSepOpened then
573 >      if 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.Write(target^, raw_info.raw_size);
576 >      Fsep_file.Seek(raw_info.RawAddr, soFromBeginning);
577 >      Fsep_file.CopyFrom(Src, raw_info.RawSize);
578        if UnloadWhenUnused then
579 <        Fsep_file.Free
579 >      begin
580 >        FSepOpened := False;
581 >        Fsep_file.Free;
582 >      end
583        else
584          FSepOpened := True;
585      end;
586    end;
587   end;
588  
589 <
564 <
565 <
566 < procedure TOniDataDat.LoadRawFilePart(fileid, dat_offset: LongWord;
567 <  offset, size: LongWord; target: Pointer);
589 > procedure TAccess_OniArchive.LoadRawFilePart(FileID, DatOffset, Offset, Size: Integer; var Target: TStream);
590   var
591 <  raw_info: TRawInfo;
592 <  Data:     Tdata;
571 <  mem:      TMemoryStream;
591 >  Data: TStream;
592 >  streampos: Integer;
593   begin
594 <  if fileid < Self.GetFilesCount then
594 >  if not Assigned(Target) then
595 >    Target := TMemoryStream.Create;
596 >  if fileid < Self.GetFileCount then
597    begin
598 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
599 <    SetLength(Data, raw_info.raw_size);
600 <    Self.LoadRawFile(fileid, dat_offset, @Data[0]);
601 <    mem := TMemoryStream.Create;
602 <    mem.Write(Data[offset], size);
603 <    mem.Read(target^, size);
581 <    mem.Free;
598 >    data := nil;
599 >    LoadRawFile(FileID, DatOffset, Data);
600 >    Data.Seek(Offset, soFromBeginning);
601 >    streampos := Target.Position;
602 >    Target.CopyFrom(Data, Size);
603 >    Target.Seek(streampos, soFromBeginning);
604    end;
605   end;
606  
607  
608 <
587 <
588 < procedure TOniDataDat.UpdateRawFilePart(fileid, dat_offset: LongWord;
589 <  offset, size: LongWord; target: Pointer);
608 > procedure TAccess_OniArchive.UpdateRawFilePart(FileID, DatOffset, Offset, Size: Integer; Src: TStream);
609   var
610 <  raw_info: TRawInfo;
610 >  raw_info: TRawDataInfo;
611   begin
612 <  if fileid < Self.GetFilesCount then
612 >  if fileid < GetFileCount then
613    begin
614 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
615 <    if not raw_info.loc_sep then
614 >    raw_info := GetRawInfo(FileID, DatOffset);
615 >    if not raw_info.LocSep then
616      begin
617 <      if FUnloadWhenUnused or not FRawOpened then
617 >      if not FRawOpened then
618          Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
619            fmOpenReadWrite);
620 <      Fraw_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
621 <      Fraw_file.Write(target^, raw_info.raw_size);
620 >      Fraw_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
621 >      Fraw_file.CopyFrom(Src, Size);
622        if UnloadWhenUnused then
623 <        Fraw_file.Free
623 >      begin
624 >        FRawOpened := False;
625 >        Fraw_file.Free;
626 >      end
627        else
628          FRawOpened := True;
629      end
630      else
631      begin
632 <      if FUnloadWhenUnused or not FSepOpened then
632 >      if not FSepOpened then
633          Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
634            fmOpenReadWrite);
635 <      Fsep_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
636 <      Fsep_file.Write(target^, raw_info.raw_size);
635 >      Fsep_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
636 >      Fsep_file.CopyFrom(Src, Size);
637        if UnloadWhenUnused then
638 <        Fsep_file.Free
638 >      begin
639 >        FSepOpened := False;
640 >        Fsep_file.Free;
641 >      end
642        else
643          FSepOpened := True;
644      end;
645    end;
646   end;
647  
648 <
649 <
650 <
651 < function TOniDataDat.AppendRawFile(loc_sep: Boolean; size: LongWord;
627 <  target: Pointer): LongWord; //Returns new Address
648 > function TAccess_OniArchive.AppendRawFile(LocSep: Boolean; Src: TStream): Integer;
649 > const
650 >  EmptyBytes: Array[0..31] of Byte = (
651 >      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 );
652   begin
653 <  if not loc_sep then
653 >  if not LocSep then
654    begin
655 <    if FUnloadWhenUnused or not FRawOpened then
655 >    if not FRawOpened then
656        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
657          fmOpenReadWrite);
658 +    if (Fraw_file.Size mod 32) > 0 then
659 +      Fraw_file.Write(EmptyBytes[0], 32 - (Fraw_file.Size mod 32));
660      Result := Fraw_file.Size;
661      Fraw_file.Seek(0, soFromEnd);
662 <    Fraw_file.Write(target^, size);
662 >    Fraw_file.CopyFrom(Src, Src.Size);
663 >    if (Fraw_file.Size mod 32) > 0 then
664 >      Fraw_file.Write(EmptyBytes[0], 32 - (Fraw_file.Size mod 32));
665      if UnloadWhenUnused then
666 <      Fraw_file.Free
666 >    begin
667 >      FRawOpened := False;
668 >      Fraw_file.Free;
669 >    end
670      else
671        FRawOpened := True;
672    end
673    else
674    begin
675 <    if FUnloadWhenUnused or not FSepOpened then
675 >    if not FSepOpened then
676        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
677          fmOpenReadWrite);
678 +    if (Fsep_file.Size mod 32) > 0 then
679 +      Fsep_file.Write(EmptyBytes[0], 32 - (Fsep_file.Size mod 32));
680      Result := Fsep_file.Size;
681      Fsep_file.Seek(0, soFromEnd);
682 <    Fsep_file.Write(target^, size);
682 >    Fsep_file.CopyFrom(Src, Src.Size);
683 >    if (Fsep_file.Size mod 32) > 0 then
684 >      Fsep_file.Write(EmptyBytes[0], 32 - (Fsep_file.Size mod 32));
685      if UnloadWhenUnused then
686 <      Fsep_file.Free
686 >    begin
687 >      FSepOpened := False;
688 >      Fsep_file.Free;
689 >    end
690      else
691        FSepOpened := True;
692    end;
693   end;
694  
657
658 }
659
660
661
662
695   end.

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)