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

Comparing oup/current/DataAccess/Access_OniArchive.pas (file contents):
Revision 109 by alloc, Wed Feb 21 03:12:33 2007 UTC vs.
Revision 321 by alloc, Wed May 6 13:47:23 2009 UTC

# Line 15 | Line 15 | type
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; ConnectionID: Integer; var Msg: TStatusMessages); override;
24      procedure Close; override;
# Line 33 | Line 34 | type
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; target: Pointer);
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;
# Line 49 | Line 54 | type
54   implementation
55  
56   uses
57 <  SysUtils, StrUtils, Data, Functions, RawList;
57 >  SysUtils, StrUtils, Data, Functions, RawList, DatLinks, Math;
58  
59  
60   (*
# Line 59 | Line 64 | uses
64  
65  
66   constructor TAccess_OniArchive.Create(DatFilename: String; ConnectionID: Integer; var Msg: TStatusMessages);
62 type
63  THeader = packed record
64    Ident:      array[0..$13] of Byte;
65    Files:      Integer;
66    NamedFiles: Integer;
67    Extensions: Integer;
68    DataAddr:   Integer;
69    DataSize:   Integer;
70    NamesAddr:  Integer;
71    NamesSize:  Integer;
72    Ident2:     array[0..$F] of Byte;
73  end;
74  TFilesMap = array of packed record
75    Extension: array[0..$3] of Char;
76    DataAddr:  Integer;
77    NameAddr:  Integer;
78    FileSize:  Integer;
79    FileType:  LongWord;
80  end;
81  TNamedFilesMap = array of packed record
82    FileNumber: Integer;
83    blubb:      Integer;
84  end;
85 const
86  header_ident1_pc: array[0..$13] of Byte =
87    ($1F, $27, $DC, $33, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
88    $14, $00, $10, $00, $08, $00);
89  header_ident1_mac: array[0..$13] of Byte =
90    ($61, $30, $C1, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
91    $14, $00, $10, $00, $08, $00);
92  header_ident1_macbeta: array[0..$13] of Byte =
93    ($81, $11, $8D, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
94    $14, $00, $10, $00, $08, $00);
95  header_ident2: array[0..$F] of Byte =
96    ($99, $CF, $40, $00, $90, $4F, $63, $00, $F4, $55, $5F, $00, $90, $4F, $63, $00);
67   var
68    i: Integer;
69    header_pc, header_mac, header_macbeta: Boolean;
# Line 116 | Line 86 | begin
86    header_pc  := True;
87    header_mac := True;
88    header_macbeta := True;
89 <  for i := 0 to High(Fdat_header.Ident) do
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];
122 <    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.Ident[i] <> header_ident1_macbeta[i] then
102 >    if Fdat_header.OSIdent[i] <> HeaderOSIdentMacBeta[i] then
103        header_macbeta := False;
104    end;
105    if not (header_pc xor header_mac xor header_macbeta) then
# Line 185 | Line 161 | begin
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 TAccess_OniArchive.SetUnloadWhenUnused(doit: Boolean);
172 + begin
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
# Line 249 | Line 274 | var
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 +  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
# Line 262 | 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
266 <          id := IntToHex(Fdat_files[i].ID, 4)
267 <        else
268 <          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  
# Line 273 | Line 303 | begin
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 <  Result := TStringList.Create;
311 >  if not Assigned(Result) then
312 >    Result := TStringList.Create;
313    if list.Count > 0 then
314    begin
315      fields := TStringList.Create;
316 <    if SortType in [ST_IDAsc, ST_NameAsc, ST_ExtAsc] 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;
# Line 313 | Line 345 | function TAccess_OniArchive.GetExtension
345   var
346    i: Integer;
347   begin
348 <  Result := TStringList.Create;
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
# Line 339 | Line 374 | begin
374    begin
375      if not Assigned(Target) then
376        Target := TMemoryStream.Create;
377 <    if not FDatOpened then
343 <      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
344 <    Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
345 <    streampos := Target.Position;
346 <    Target.CopyFrom(Fdat_file, Fdat_files[fileid].Size);
347 <    Target.Seek(streampos, soFromBeginning);
348 <    if UnloadWhenUnused then
377 >    if GetFileInfo(FileID).Size > 0 then
378      begin
379 <      Fdat_file.Free;
380 <      FDatOpened := False;
381 <    end
382 <    else
383 <      FDatOpened := True;
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  
# Line 417 | 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 + function TAccess_OniArchive.GetDatLinks(FileID: Integer): TDatLinkList;
472 + var
473 +  i: Integer;
474 +  link: Integer;
475 + begin
476 +  Result := DatLinksManager.GetDatLinks(FConnectionID, FileID);
477 +  if Length(Result) > 0 then
478 +  begin
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 TAccess_OniArchive.GetRawsForType(RawType: String): TRawDataList;
498 + var
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) and (list[j].RawSize > 0) then
511 +      begin
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);
# Line 430 | Line 524 | end;
524  
525  
526  
527 <
434 < procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; target: Pointer);
527 > procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; var target: TStream);
528   begin
529 +  if not Assigned(Target) then
530 +    Target := TMemoryStream.Create;
531    if not LocSep then
532    begin
533      if not FRawOpened then
# Line 441 | Line 536 | begin
536      if RawAddr <= Fraw_file.Size then
537      begin
538        Fraw_file.Seek(RawAddr, soFromBeginning);
539 <      Fraw_file.Read(target^, size);
539 >      Target.CopyFrom(Fraw_file, size);
540 >      Target.Seek(0, soFromBeginning);
541      end;
542      if UnloadWhenUnused then
543      begin
# Line 459 | Line 555 | begin
555      if RawAddr <= Fsep_file.Size then
556      begin
557        Fsep_file.Seek(RawAddr, soFromBeginning);
558 <      Fsep_file.Read(target^, size);
558 >      Target.CopyFrom(Fsep_file, size);
559 >      Target.Seek(0, soFromBeginning);
560      end;
561      if UnloadWhenUnused then
562      begin
# Line 471 | Line 568 | begin
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   procedure TAccess_OniArchive.LoadRawFile(FileID, DatOffset: Integer; var Target: TStream);
582   var
583    raw_info: TRawDataInfo;
# Line 481 | Line 588 | begin
588    if fileid < GetFileCount then
589    begin
590      raw_info := Self.GetRawInfo(FileID, DatOffset);
591 +    if raw_info.RawSize = 0 then
592 +      exit;
593      if not raw_info.LocSep then
594      begin
595        if not FRawOpened then
# Line 531 | Line 640 | begin
640          Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
641            fmOpenReadWrite);
642        Fraw_file.Seek(raw_info.RawAddr, soFromBeginning);
643 <      Fraw_file.CopyFrom(Src, raw_info.RawSize);
643 >      Fraw_file.CopyFrom(Src, Min(raw_info.RawSize, Src.Size));
644        if UnloadWhenUnused then
645        begin
646          FRawOpened := False;
# Line 576 | Line 685 | begin
685    end;
686   end;
687  
688 +
689   procedure TAccess_OniArchive.UpdateRawFilePart(FileID, DatOffset, Offset, Size: Integer; Src: TStream);
690   var
691    raw_info: TRawDataInfo;
# Line 617 | Line 727 | begin
727   end;
728  
729   function TAccess_OniArchive.AppendRawFile(LocSep: Boolean; Src: TStream): Integer;
730 + const
731 +  EmptyBytes: Array[0..31] of Byte = (
732 +      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 );
733   begin
734    if not LocSep then
735    begin
736      if not FRawOpened then
737        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
738          fmOpenReadWrite);
739 +    if (Fraw_file.Size mod 32) > 0 then
740 +      Fraw_file.Write(EmptyBytes[0], 32 - (Fraw_file.Size mod 32));
741      Result := Fraw_file.Size;
742      Fraw_file.Seek(0, soFromEnd);
743      Fraw_file.CopyFrom(Src, Src.Size);
744 +    if (Fraw_file.Size mod 32) > 0 then
745 +      Fraw_file.Write(EmptyBytes[0], 32 - (Fraw_file.Size mod 32));
746      if UnloadWhenUnused then
747      begin
748        FRawOpened := False;
# Line 639 | Line 756 | begin
756      if not FSepOpened then
757        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
758          fmOpenReadWrite);
759 +    if (Fsep_file.Size mod 32) > 0 then
760 +      Fsep_file.Write(EmptyBytes[0], 32 - (Fsep_file.Size mod 32));
761      Result := Fsep_file.Size;
762      Fsep_file.Seek(0, soFromEnd);
763      Fsep_file.CopyFrom(Src, Src.Size);
764 +    if (Fsep_file.Size mod 32) > 0 then
765 +      Fsep_file.Write(EmptyBytes[0], 32 - (Fsep_file.Size mod 32));
766      if UnloadWhenUnused then
767      begin
768        FSepOpened := False;

Diff Legend

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