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

Diff Legend

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