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 252 by alloc, Sun Dec 16 14:44:16 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;
58 <    Fdat_files:    TFiles;
59 <    Fdat_namedfilesmap: TNamedFilesMap;
60 <    Fdat_extensionsmap: TExtensionsMap;
61 <    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    protected
15    public
16 <    property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write FUnloadWhenUnused;
68 <
69 <    constructor Create(DatFilename: String; var Result: Boolean); override;
16 >    constructor Create(DatFilename: String; ConnectionID: Integer; var Msg: TStatusMessages); override;
17      procedure Close; override;
18  
19 <    function GetFileInfo(fileid: Integer): TFileInfo; override;
20 <    function GetFilesList(ext: String; pattern: String;
21 <      NoEmptyFiles: Boolean; sort: TSortType): TStringArray; override;
22 <    function GetFilesCount: LongWord; override;
23 <    function GetExtensionsList: TStringArray; override;
24 <    function GetExtendedExtensionsList: TExtensionsMap; override;
25 <
26 <    function LoadDatFile(fileid: LongWord): Tdata; override;
27 <    procedure UpdateDatFile(fileid: LongWord; Data: Tdata); override;
28 <    procedure LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
29 <    procedure UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer); override;
30 <
31 <    procedure LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord; target: Pointer);
32 <    function GetRawList(fileid: LongWord): TRawList; override;
33 <    procedure LoadRawFile(fileid, dat_offset: LongWord; target: Pointer); override;
34 <    procedure UpdateRawFile(fileid, dat_offset: LongWord; size: LongWord;
35 <      target: Pointer); override;
36 <    procedure LoadRawFilePart(fileid, dat_offset: LongWord;
37 <      offset, size: LongWord; target: Pointer); override;
38 <    procedure UpdateRawFilePart(fileid, dat_offset: LongWord;
39 <      offset, size: LongWord; target: Pointer); override;
40 <    function AppendRawFile(loc_sep: Boolean; size: LongWord; target: Pointer): LongWord;
41 <      override;//Returns new Address
19 >    function GetFileInfo(FileID: Integer): TFileInfo; override;
20 >    function GetFilesList(Ext: String; Pattern: String;
21 >      NoEmptyFiles: Boolean; SortType: TSortType): TStrings; override;
22 >    function GetFileCount: Integer; override;
23 >    function GetExtensionsList(ExtListFormat: TExtensionFormat): TStrings; override;
24 >
25 >    procedure LoadDatFile(FileID: Integer; var Target: TStream); overload; override;
26 >    procedure UpdateDatFile(FileID: Integer; Src: TStream); overload; override;
27 >    procedure LoadDatFilePart(FileID, Offset, Size: Integer; var Target: TStream); overload; override;
28 >    procedure UpdateDatFilePart(FileID, Offset, Size: Integer; Src: TStream); overload; override;
29 >
30 >    function GetDatLinks(FileID: Integer): TDatLinkList; override;
31 >    function GetDatLink(FileID, DatOffset: Integer): TDatLink; override;
32 >    function GetRawList(FileID: Integer): TRawDataList; override;
33 >    function GetRawInfo(FileID, DatOffset: Integer): TRawDataInfo; override;
34 >    function GetRawsForType(RawType: String): TRawDataList; override;
35 >
36 >    procedure LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; var target: TStream); overload;
37 >    procedure LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; target: Pointer); overload;
38 >    procedure LoadRawFile(FileID, DatOffset: Integer; var Target: TStream); overload; override;
39 >    procedure UpdateRawFile(FileID, DatOffset: Integer; Src: TStream); overload; override;
40 >    procedure LoadRawFilePart(FileID, DatOffset, Offset, Size: Integer; var Target: TStream); overload; override;
41 >    procedure UpdateRawFilePart(FileID, DatOffset, Offset, Size: Integer; Src: TStream); overload; override;
42 >
43 >    function AppendRawFile(LocSep: Boolean; Src: TStream): Integer; overload; override;
44    published
45 < }  end;
45 >  end;
46  
47   implementation
48  
49 + uses
50 +  SysUtils, StrUtils, Data, Functions, RawList, DatLinks, Math;
51 +
52  
53   (*
54   ================================================================================
55                        Implementation of  TOniDataDat
56   *)
57  
58 < {
59 < constructor TOniDataDat.Create(DatFilename: String; var Result: Boolean);
60 < const
61 <  header_ident1_pc: array[0..$13] of Byte =
62 <    ($1F, $27, $DC, $33, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
63 <    $14, $00, $10, $00, $08, $00);
64 <  header_ident1_mac: array[0..$13] of Byte =
65 <    ($61, $30, $C1, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
66 <    $14, $00, $10, $00, $08, $00);
67 <  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);
120 < var
121 <  i: LongWord;
122 <  header_pc, header_mac: Boolean;
123 < begin
124 <  FUnloadWhenUnused := True;
125 <  FDatOpened := False;
126 <  FRawOpened := False;
58 >
59 > constructor TAccess_OniArchive.Create(DatFilename: String; ConnectionID: Integer; var Msg: TStatusMessages);
60 > var
61 >  i: Integer;
62 >  header_pc, header_mac, header_macbeta: Boolean;
63 >  Fdat_header:   THeader;
64 >  Fdat_filesmap: TFilesMap;
65 >  Fdat_namedfilesmap: TNamedFilesMap;
66 > begin
67 >  Msg := SM_UnknownError;
68    if not FileExists(DatFilename) then
69    begin
70 <    ShowMessage('File doesn''t exist!!!');
130 <    Result := False;
70 >    Msg := SM_FileNotFound;
71      Exit;
72    end;
73    FFileName := DatFilename;
74 <  Fdat_file := TFileStream.Create(FFileName, fmOpenRead);
74 >  Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
75    Fdat_file.Read(Fdat_header, SizeOf(Fdat_header));
76    header_pc  := True;
77    header_mac := True;
78 <  for i := 0 to High(Fdat_header.Ident) do
78 >  header_macbeta := True;
79 >  for i := 0 to High(Fdat_header.GlobalIdent) do
80 >    if Fdat_header.GlobalIdent[i] <> HeaderGlobalIdent[i] then
81 >    begin
82 >      Msg := SM_IncompatibleFile;
83 >      Exit;
84 >    end;
85 >
86 >  for i := 0 to High(Fdat_header.OSIdent) do
87    begin
88 <    FLevelInfo.Ident[i] := Fdat_header.Ident[i];
141 <    if Fdat_header.Ident[i] <> header_ident1_pc[i] then
88 >    if Fdat_header.OSIdent[i] <> HeaderOSIdentWin[i] then
89        header_pc := False;
90 <    if Fdat_header.Ident[i] <> header_ident1_mac[i] then
90 >    if Fdat_header.OSIdent[i] <> HeaderOSIdentMac[i] then
91        header_mac := False;
92 +    if Fdat_header.OSIdent[i] <> HeaderOSIdentMacBeta[i] then
93 +      header_macbeta := False;
94    end;
95 <  if not (header_pc xor header_mac) then
95 >  if not (header_pc xor header_mac xor header_macbeta) then
96    begin
97 <    Result := False;
97 >    Msg := SM_IncompatibleFile;
98      Exit;
99    end
100    else
101    begin
102 <    if (header_pc and not header_mac) then
103 <      Fos_mac := False
104 <    else
105 <      Fos_mac := True;
102 >    if (header_pc and not header_mac and not header_macbeta) then
103 >      FDataOS := DOS_WIN
104 >    else if (not header_pc and header_mac and not header_macbeta) then
105 >      FDataOS := DOS_MAC
106 >    else if (not header_pc and not header_mac and header_macbeta) then
107 >      FDataOS := DOS_MACBETA;
108    end;
109    SetLength(Fdat_filesmap, Fdat_header.Files);
110    SetLength(Fdat_files, Fdat_header.Files);
# Line 179 | Line 130 | begin
130      begin
131        Fdat_files[i].Name := '';
132      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;
133    end;
134    Fdat_file.Seek($40 + Fdat_header.Files * $14, soFromBeginning);
135    SetLength(Fdat_namedfilesmap, Fdat_header.NamedFiles);
# Line 195 | Line 142 | begin
142      Fdat_file.Read(Fdat_extensionsmap[i], SizeOf(Fdat_extensionsmap[i]));
143  
144    Fdat_file.Seek(Fdat_files[0].DatAddr + 7, soFromBeginning);
145 <  Fdat_file.Read(FLevelInfo.LevelNumber, 1);
146 <  FLevelInfo.LevelNumber := FLevelInfo.LevelNumber div 2;
145 >  Fdat_file.Read(FLevelNumber, 1);
146 >  FLevelNumber := FLevelNumber div 2;
147 >
148 >  Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
149 >    fmOpenReadWrite);
150 >  if not (FDataOS = DOS_WIN) then
151 >    Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
152 >      fmOpenReadWrite);
153  
154 <  Fdat_file.Free;
154 >  Msg := SM_OK;
155 >  FBackend := DB_ONI;
156 >  FConnectionID := ConnectionID;
157 >  FChangeRights := [CR_EditDat, CR_EditRaw, CR_AppendRaw];
158  
159 <  Result   := True;
204 <  FBackend := ODB_Dat;
159 >  inherited;
160   end;
161  
162  
163  
164  
165 < procedure TOniDataDat.Close;
165 > procedure TAccess_OniArchive.Close;
166   begin
167 <  if not FUnloadWhenUnused and FDatOpened then
167 >  if Assigned(Fdat_file) then
168      Fdat_file.Free;
169 <  if not FUnloadWhenUnused and FRawOpened then
169 >  if Assigned(Fraw_file) then
170      Fraw_file.Free;
171 <  if not FUnloadWhenUnused and FSepOpened then
171 >  if Assigned(Fsep_file) then
172      Fsep_file.Free;
173    Self.Free;
174   end;
# Line 221 | Line 176 | end;
176  
177  
178  
179 < function TOniDataDat.GetFileInfo(fileid: Integer): TFileInfo;
179 > function TAccess_OniArchive.GetFileInfo(fileid: Integer): TFileInfo;
180   begin
181    if fileid = -1 then
182    begin
183      Result := inherited GetFileInfo(fileid);
184      Exit;
185    end;
186 <  if fileid < Self.GetFilesCount then
186 >  if fileid < Self.GetFileCount then
187      Result    := Fdat_files[fileid]
188    else
189      Result.ID := -1;
# Line 237 | Line 192 | end;
192  
193  
194  
195 < function TOniDataDat.GetFilesList(ext: String; pattern: String;
196 <  NoEmptyFiles: Boolean; sort: TSortType): TStringArray;
195 > function TAccess_OniArchive.GetFilesList(ext: String; pattern: String;
196 >  NoEmptyFiles: Boolean; SortType: TSortType): TStrings;
197   var
198 <  i: LongWord;
199 <  list: TStringList;
198 >  i:      Integer;
199 >  list:   TStringList;
200    id, name, extension: String;
201    fields: TStrings;
202  
203    procedure getfields;
204    begin
205 <     fields.CommaText := StringReplace(AnsiQuotedStr(list.Strings[i], '"'), ';', '","', [rfReplaceAll]);
206 <    if sort in [stIDAsc, stIDDesc] then
205 >    fields.CommaText := StringReplace(AnsiQuotedStr(list.Strings[i], '"'), ';', '","', [rfReplaceAll]);
206 >    if SortType in [ST_IDAsc, ST_IDDesc] then
207      begin
208        id := fields.Strings[0];
209        name := fields.Strings[1];
210        extension := fields.Strings[2];
211      end;
212 <    if sort in [stNameAsc, stNameDesc] then
212 >    if SortType in [ST_NameAsc, ST_NameDesc] then
213      begin
214        id := fields.Strings[1];
215        name := fields.Strings[0];
216        extension := fields.Strings[2];
217      end;
218 <    if sort in [stExtAsc, stExtDesc] then
218 >    if SortType in [ST_ExtAsc, ST_ExtDesc] then
219      begin
220        id := fields.Strings[1];
221        name := fields.Strings[2];
222        extension := fields.Strings[0];
223      end;
224 +    if SortType in [ST_ExtNameAsc, ST_ExtNameDesc] then
225 +    begin
226 +      id := fields.Strings[2];
227 +      name := fields.Strings[1];
228 +      extension := fields.Strings[0];
229 +    end;
230    end;
231  
232   begin
233    list := TStringList.Create;
234    list.Sorted := True;
235 <  for i := 0 to Fdat_header.Files - 1 do
235 >  if ext = '*' then
236 >    ext := '';
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];
322 >    if not Assigned(Target) then
323 >      Target := TMemoryStream.Create;
324 >    if GetFileInfo(FileID).Size > 0 then
325 >    begin
326 >      Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
327 >      streampos := Target.Position;
328 >      Target.CopyFrom(Fdat_file, Fdat_files[fileid].Size);
329 >      Target.Seek(streampos, soFromBeginning);
330 >    end;
331    end;
332   end;
333  
334 <
359 <
360 <
361 < function TOniDataDat.LoadDatFile(fileid: LongWord): Tdata;
334 > procedure TAccess_OniArchive.UpdateDatFile(FileID: Integer; Src: TStream);
335   begin
336 <  if fileid < Self.GetFilesCount then
336 >  if fileid < GetFileCount then
337    begin
365    if FUnloadWhenUnused or not FDatOpened then
366      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
338      Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
339 <    SetLength(Result, Fdat_files[fileid].Size);
369 <    Fdat_file.Read(Result[0], Fdat_files[fileid].Size);
370 <    if UnloadWhenUnused then
371 <      Fdat_file.Free
372 <    else
373 <      FDatOpened := True;
339 >    Fdat_file.CopyFrom(Src, Fdat_files[fileid].Size);
340    end;
341   end;
342  
343 <
344 <
345 <
380 < procedure TOniDataDat.UpdateDatFile(fileid: LongWord; Data: Tdata);
343 > procedure TAccess_OniArchive.LoadDatFilePart(FileID, Offset, Size: Integer; var Target: TStream);
344 > var
345 >  streampos: Integer;
346   begin
347 <  if fileid < Self.GetFilesCount then
347 >  if fileid < GetFileCount then
348    begin
349 <    if FUnloadWhenUnused or not FDatOpened then
350 <      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
351 <    Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
352 <    Fdat_file.Write(Data[0], Length(Data));
353 <    if UnloadWhenUnused then
354 <      Fdat_file.Free
390 <    else
391 <      FDatOpened := True;
349 >    if not Assigned(Target) then
350 >      Target := TMemoryStream.Create;
351 >    Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
352 >    streampos := Target.Position;
353 >    Target.CopyFrom(Fdat_file, size);
354 >    Target.Seek(streampos, soFromBeginning);
355    end;
356   end;
357  
358 <
396 <
397 <
398 < procedure TOniDataDat.LoadDatFilePart(fileid, offset, size: LongWord; target: Pointer);
358 > procedure TAccess_OniArchive.UpdateDatFilePart(FileID, Offset, Size: Integer; Src: TStream);
359   begin
360 <  if fileid < Self.GetFilesCount then
360 >  if fileid < GetFileCount then
361    begin
402    if FUnloadWhenUnused or not FDatOpened then
403      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
362      Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
363 <    Fdat_file.Read(target^, size);
406 <    if UnloadWhenUnused then
407 <      Fdat_file.Free
408 <    else
409 <      FDatOpened := True;
363 >    Fdat_file.CopyFrom(Src, Size);
364    end;
365   end;
366  
367  
368  
369 + function TAccess_OniArchive.GetDatLink(FileID, DatOffset: Integer): TDatLink;
370 + var
371 +  link: Integer;
372 + begin
373 +  Result := DatLinksManager.GetDatLink(FConnectionID, FileID, DatOffset);
374 +  LoadDatFilePart(fileid, Result.SrcOffset, 4, @link);
375 +  if link > 0 then
376 +    Result.DestID := link div 256
377 +  else
378 +    Result.DestID := -1;
379 + end;
380 +
381  
382 < procedure TOniDataDat.UpdateDatFilePart(fileid, offset, size: LongWord; target: Pointer);
382 > function TAccess_OniArchive.GetDatLinks(FileID: Integer): TDatLinkList;
383 > var
384 >  i: Integer;
385 >  link: Integer;
386   begin
387 <  if fileid < Self.GetFilesCount then
387 >  Result := DatLinksManager.GetDatLinks(FConnectionID, FileID);
388 >  if Length(Result) > 0 then
389    begin
390 <    if FUnloadWhenUnused or not FDatOpened then
391 <      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
392 <    Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
393 <    Fdat_file.Write(target^, size);
394 <    if UnloadWhenUnused then
395 <      Fdat_file.Free
396 <    else
397 <      FDatOpened := True;
390 >    for i := 0 to High(Result) do
391 >    begin
392 >      LoadDatFilePart(fileid, Result[i].SrcOffset, 4, @link);
393 >      if link > 0 then
394 >        Result[i].DestID := link div 256
395 >      else
396 >        Result[i].DestID := -1;
397 >    end;
398    end;
399   end;
400  
401  
402 + function TAccess_OniArchive.GetRawList(FileID: Integer): TRawDataList;
403 + begin
404 +  Result := RawLists.GetRawList(FConnectionID, FileID);
405 + end;
406  
407  
408 < function TOniDataDat.GetRawList(fileid: LongWord): TRawList;
408 > function TAccess_OniArchive.GetRawsForType(RawType: String): TRawDataList;
409   var
410 <  i: LongWord;
411 < begin
412 <  SetLength(Result, 0);
413 <  for i := 0 to High(RawListHandlers) do
414 <    if UpperCase(RawListHandlers[i].Ext) = UpperCase(Fdat_files[fileid].extension) then
415 <      if RawListHandlers[i].needed then
410 >  i, j: Integer;
411 >  dats: TStrings;
412 >  list: TRawDataList;
413 > begin
414 >  dats := nil;
415 >  dats := GetFilesList(MidStr(RawType, 1, 4), '', True, ST_IDAsc);
416 >  for i := 0 to dats.Count - 1 do
417 >  begin
418 >    list := GetRawList(StrToInt(MidStr(dats.Strings[i], 1, 5)));
419 >    for j := 0 to Length(list) - 1 do
420 >    begin
421 >      if (list[j].RawType = RawType) and (list[j].RawSize > 0) then
422        begin
423 <        Result := RawListHandlers[i].Handler(Self, fileid);
424 <        Break;
425 <      end
426 <      else
427 <        Break;
423 >        SetLength(Result, Length(Result)+1);
424 >        Result[High(Result)] := list[j];
425 >      end;
426 >    end;
427 >  end;
428   end;
429  
430  
431 + function TAccess_OniArchive.GetRawInfo(FileID, DatOffset: Integer): TRawDataInfo;
432 + begin
433 +  Result := RawLists.GetRawInfo(FConnectionID, FileID, DatOffset);
434 + end;
435 +
436  
437  
438 < procedure TOniDataDat.LoadRawOffset(loc_sep: Boolean; raw_addr, size: LongWord;
454 <  target: Pointer);
438 > procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; var target: TStream);
439   begin
440 <  if not loc_sep then
440 >  if not Assigned(Target) then
441 >    Target := TMemoryStream.Create;
442 >  if not LocSep then
443    begin
444 <    if FUnloadWhenUnused or not FRawOpened then
459 <      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
460 <        fmOpenReadWrite);
461 <    if raw_addr <= Fraw_file.Size then
444 >    if RawAddr <= Fraw_file.Size then
445      begin
446 <      Fraw_file.Seek(raw_addr, soFromBeginning);
447 <      Fraw_file.Read(target^, size);
446 >      Fraw_file.Seek(RawAddr, soFromBeginning);
447 >      Target.CopyFrom(Fraw_file, size);
448 >      Target.Seek(0, soFromBeginning);
449      end;
466    if UnloadWhenUnused then
467      Fraw_file.Free
468    else
469      FRawOpened := True;
450    end
451    else
452    begin
453 <    if FUnloadWhenUnused or not FSepOpened then
474 <      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
475 <        fmOpenReadWrite);
476 <    if raw_addr <= Fsep_file.Size then
453 >    if RawAddr <= Fsep_file.Size then
454      begin
455 <      Fsep_file.Seek(raw_addr, soFromBeginning);
456 <      Fsep_file.Read(target^, size);
455 >      Fsep_file.Seek(RawAddr, soFromBeginning);
456 >      Target.CopyFrom(Fsep_file, size);
457 >      Target.Seek(0, soFromBeginning);
458      end;
481    if UnloadWhenUnused then
482      Fsep_file.Free
483    else
484      FSepOpened := True;
459    end;
460   end;
461  
462 + procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; target: Pointer);
463 + var
464 +  data: TStream;
465 + begin
466 +  data := nil;
467 +  LoadRawOffset(LocSep, RawAddr, Size, data);
468 +  data.Read(Target^, Size);
469 +  data.Free;
470 + end;
471  
472 <
490 <
491 < procedure TOniDataDat.LoadRawFile(fileid, dat_offset: LongWord; target: Pointer);
472 > procedure TAccess_OniArchive.LoadRawFile(FileID, DatOffset: Integer; var Target: TStream);
473   var
474 <  raw_info: TRawInfo;
474 >  raw_info: TRawDataInfo;
475 >  streampos: Integer;
476   begin
477 <  if fileid < Self.GetFilesCount then
478 <  begin
479 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
480 <    if not raw_info.loc_sep then
481 <    begin
482 <      if FUnloadWhenUnused or not FRawOpened then
483 <        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
484 <          fmOpenReadWrite);
485 <      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
486 <      Fraw_file.Read(target^, raw_info.raw_size);
487 <      if UnloadWhenUnused then
506 <        Fraw_file.Free
507 <      else
508 <        FRawOpened := True;
477 >  if not Assigned(Target) then
478 >    Target := TMemoryStream.Create;
479 >  if fileid < GetFileCount then
480 >  begin
481 >    raw_info := Self.GetRawInfo(FileID, DatOffset);
482 >    if not raw_info.LocSep then
483 >    begin
484 >      Fraw_file.Seek(raw_info.RawAddr, soFromBeginning);
485 >      streampos := Target.Position;
486 >      Target.CopyFrom(Fraw_file, raw_info.RawSize);
487 >      Target.Seek(streampos, soFromBeginning);
488      end
489      else
490      begin
491 <      if FUnloadWhenUnused or not FSepOpened then
492 <        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
493 <          fmOpenReadWrite);
494 <      Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
516 <      Fsep_file.Read(target^, raw_info.raw_size);
517 <      if UnloadWhenUnused then
518 <        Fsep_file.Free
519 <      else
520 <        FSepOpened := True;
491 >      Fsep_file.Seek(raw_info.RawAddr, soFromBeginning);
492 >      streampos := Target.Position;
493 >      Target.CopyFrom(Fsep_file, raw_info.RawSize);
494 >      Target.Seek(streampos, soFromBeginning);
495      end;
496    end;
497   end;
498  
499 <
526 <
527 <
528 < procedure TOniDataDat.UpdateRawFile(fileid, dat_offset: LongWord;
529 <  size: LongWord; target: Pointer);
499 > procedure TAccess_OniArchive.UpdateRawFile(FileID, DatOffset: Integer; Src: TStream);
500   var
501 <  raw_info: TRawInfo;
501 >  raw_info: TRawDataInfo;
502   begin
503 <  if fileid < Self.GetFilesCount then
503 >  if fileid < GetFileCount then
504    begin
505 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
506 <    if not raw_info.loc_sep then
505 >    raw_info := GetRawInfo(FileID, DatOffset);
506 >    if not raw_info.LocSep then
507      begin
508 <      if FUnloadWhenUnused or not FRawOpened then
509 <        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
540 <          fmOpenReadWrite);
541 <      Fraw_file.Seek(raw_info.raw_addr, soFromBeginning);
542 <      Fraw_file.Write(target^, raw_info.raw_size);
543 <      if UnloadWhenUnused then
544 <        Fraw_file.Free
545 <      else
546 <        FRawOpened := True;
508 >      Fraw_file.Seek(raw_info.RawAddr, soFromBeginning);
509 >      Fraw_file.CopyFrom(Src, Min(raw_info.RawSize, Src.Size));
510      end
511      else
512      begin
513 <      if FUnloadWhenUnused or not FSepOpened then
514 <        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
552 <          fmOpenReadWrite);
553 <      Fsep_file.Seek(raw_info.raw_addr, soFromBeginning);
554 <      Fsep_file.Write(target^, raw_info.raw_size);
555 <      if UnloadWhenUnused then
556 <        Fsep_file.Free
557 <      else
558 <        FSepOpened := True;
513 >      Fsep_file.Seek(raw_info.RawAddr, soFromBeginning);
514 >      Fsep_file.CopyFrom(Src, raw_info.RawSize);
515      end;
516    end;
517   end;
518  
519 <
564 <
565 <
566 < procedure TOniDataDat.LoadRawFilePart(fileid, dat_offset: LongWord;
567 <  offset, size: LongWord; target: Pointer);
519 > procedure TAccess_OniArchive.LoadRawFilePart(FileID, DatOffset, Offset, Size: Integer; var Target: TStream);
520   var
521 <  raw_info: TRawInfo;
522 <  Data:     Tdata;
571 <  mem:      TMemoryStream;
521 >  Data: TStream;
522 >  streampos: Integer;
523   begin
524 <  if fileid < Self.GetFilesCount then
524 >  if not Assigned(Target) then
525 >    Target := TMemoryStream.Create;
526 >  if fileid < Self.GetFileCount then
527    begin
528 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
529 <    SetLength(Data, raw_info.raw_size);
530 <    Self.LoadRawFile(fileid, dat_offset, @Data[0]);
531 <    mem := TMemoryStream.Create;
532 <    mem.Write(Data[offset], size);
533 <    mem.Read(target^, size);
581 <    mem.Free;
528 >    data := nil;
529 >    LoadRawFile(FileID, DatOffset, Data);
530 >    Data.Seek(Offset, soFromBeginning);
531 >    streampos := Target.Position;
532 >    Target.CopyFrom(Data, Size);
533 >    Target.Seek(streampos, soFromBeginning);
534    end;
535   end;
536  
537  
538 <
587 <
588 < procedure TOniDataDat.UpdateRawFilePart(fileid, dat_offset: LongWord;
589 <  offset, size: LongWord; target: Pointer);
538 > procedure TAccess_OniArchive.UpdateRawFilePart(FileID, DatOffset, Offset, Size: Integer; Src: TStream);
539   var
540 <  raw_info: TRawInfo;
540 >  raw_info: TRawDataInfo;
541   begin
542 <  if fileid < Self.GetFilesCount then
542 >  if fileid < GetFileCount then
543    begin
544 <    raw_info := Self.GetRawInfo(fileid, dat_offset);
545 <    if not raw_info.loc_sep then
544 >    raw_info := GetRawInfo(FileID, DatOffset);
545 >    if not raw_info.LocSep then
546      begin
547 <      if FUnloadWhenUnused or not FRawOpened then
548 <        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
600 <          fmOpenReadWrite);
601 <      Fraw_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
602 <      Fraw_file.Write(target^, raw_info.raw_size);
603 <      if UnloadWhenUnused then
604 <        Fraw_file.Free
605 <      else
606 <        FRawOpened := True;
547 >      Fraw_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
548 >      Fraw_file.CopyFrom(Src, Size);
549      end
550      else
551      begin
552 <      if FUnloadWhenUnused or not FSepOpened then
553 <        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
612 <          fmOpenReadWrite);
613 <      Fsep_file.Seek(raw_info.raw_addr + offset, soFromBeginning);
614 <      Fsep_file.Write(target^, raw_info.raw_size);
615 <      if UnloadWhenUnused then
616 <        Fsep_file.Free
617 <      else
618 <        FSepOpened := True;
552 >      Fsep_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
553 >      Fsep_file.CopyFrom(Src, Size);
554      end;
555    end;
556   end;
557  
558 <
559 <
560 <
561 < function TOniDataDat.AppendRawFile(loc_sep: Boolean; size: LongWord;
627 <  target: Pointer): LongWord; //Returns new Address
558 > function TAccess_OniArchive.AppendRawFile(LocSep: Boolean; Src: TStream): Integer;
559 > const
560 >  EmptyBytes: Array[0..31] of Byte = (
561 >      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 );
562   begin
563 <  if not loc_sep then
563 >  if not LocSep then
564    begin
565 <    if FUnloadWhenUnused or not FRawOpened then
566 <      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
633 <        fmOpenReadWrite);
565 >    if (Fraw_file.Size mod 32) > 0 then
566 >      Fraw_file.Write(EmptyBytes[0], 32 - (Fraw_file.Size mod 32));
567      Result := Fraw_file.Size;
568      Fraw_file.Seek(0, soFromEnd);
569 <    Fraw_file.Write(target^, size);
570 <    if UnloadWhenUnused then
571 <      Fraw_file.Free
639 <    else
640 <      FRawOpened := True;
569 >    Fraw_file.CopyFrom(Src, Src.Size);
570 >    if (Fraw_file.Size mod 32) > 0 then
571 >      Fraw_file.Write(EmptyBytes[0], 32 - (Fraw_file.Size mod 32));
572    end
573    else
574    begin
575 <    if FUnloadWhenUnused or not FSepOpened then
576 <      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
646 <        fmOpenReadWrite);
575 >    if (Fsep_file.Size mod 32) > 0 then
576 >      Fsep_file.Write(EmptyBytes[0], 32 - (Fsep_file.Size mod 32));
577      Result := Fsep_file.Size;
578      Fsep_file.Seek(0, soFromEnd);
579 <    Fsep_file.Write(target^, size);
580 <    if UnloadWhenUnused then
581 <      Fsep_file.Free
652 <    else
653 <      FSepOpened := True;
579 >    Fsep_file.CopyFrom(Src, Src.Size);
580 >    if (Fsep_file.Size mod 32) > 0 then
581 >      Fsep_file.Write(EmptyBytes[0], 32 - (Fsep_file.Size mod 32));
582    end;
583   end;
584  
657
658 }
659
660
661
662
585   end.

Diff Legend

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