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

Diff Legend

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