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

Diff Legend

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