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 248 by alloc, Mon Nov 26 11:02:28 2007 UTC

# Line 11 | Line 11 | type
11      Fsep_file:           TFileStream;
12      Fdat_files:          TFiles;
13      Fdat_extensionsmap:  TExtensionsMap;
14    FUnloadWhenUnused:   Boolean;
15    FDatOpened:          Boolean;
16    FRawOpened:          Boolean;
17    FSepOpened:          Boolean;
14    protected
15    public
20    property UnloadWhenUnused: Boolean Read FUnloadWhenUnused Write FUnloadWhenUnused;
21
16      constructor Create(DatFilename: String; ConnectionID: Integer; var Msg: TStatusMessages); override;
17      procedure Close; override;
18  
# Line 33 | Line 27 | type
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; target: Pointer);
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;
# Line 49 | Line 47 | type
47   implementation
48  
49   uses
50 <  SysUtils, StrUtils, Data, Functions, RawList;
50 >  SysUtils, StrUtils, Data, Functions, RawList, DatLinks, Math;
51  
52  
53   (*
# Line 59 | Line 57 | uses
57  
58  
59   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);
60   var
61    i: Integer;
62    header_pc, header_mac, header_macbeta: Boolean;
# Line 101 | Line 64 | var
64    Fdat_filesmap: TFilesMap;
65    Fdat_namedfilesmap: TNamedFilesMap;
66   begin
104  FUnloadWhenUnused := True;
105  FDatOpened := False;
106  FRawOpened := False;
67    Msg := SM_UnknownError;
68    if not FileExists(DatFilename) then
69    begin
# Line 116 | Line 76 | begin
76    header_pc  := True;
77    header_mac := True;
78    header_macbeta := True;
79 <  for i := 0 to High(Fdat_header.Ident) do
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];
122 <    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.Ident[i] <> header_ident1_macbeta[i] then
92 >    if Fdat_header.OSIdent[i] <> HeaderOSIdentMacBeta[i] then
93        header_macbeta := False;
94    end;
95    if not (header_pc xor header_mac xor header_macbeta) then
# Line 179 | Line 145 | begin
145    Fdat_file.Read(FLevelNumber, 1);
146    FLevelNumber := FLevelNumber div 2;
147  
148 <  Fdat_file.Free;
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    Msg := SM_OK;
155    FBackend := DB_ONI;
156    FConnectionID := ConnectionID;
157    FChangeRights := [CR_EditDat, CR_EditRaw, CR_AppendRaw];
158 +
159 +  inherited;
160   end;
161  
162  
# Line 192 | Line 164 | end;
164  
165   procedure TAccess_OniArchive.Close;
166   begin
167 <  if FDatOpened then
167 >  if Assigned(Fdat_file) then
168      Fdat_file.Free;
169 <  if FRawOpened then
169 >  if Assigned(Fraw_file) then
170      Fraw_file.Free;
171 <  if FSepOpened then
171 >  if Assigned(Fsep_file) then
172      Fsep_file.Free;
173    Self.Free;
174   end;
# Line 249 | Line 221 | var
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 +  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
# Line 262 | 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
266 <          id := IntToHex(Fdat_files[i].ID, 4)
267 <        else
268 <          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  
# Line 273 | Line 250 | begin
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 <  Result := TStringList.Create;
258 >  if not Assigned(Result) then
259 >    Result := TStringList.Create;
260    if list.Count > 0 then
261    begin
262      fields := TStringList.Create;
263 <    if SortType in [ST_IDAsc, ST_NameAsc, ST_ExtAsc] 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;
# Line 313 | Line 292 | function TAccess_OniArchive.GetExtension
292   var
293    i: Integer;
294   begin
295 <  Result := TStringList.Create;
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
# Line 339 | Line 321 | begin
321    begin
322      if not Assigned(Target) then
323        Target := TMemoryStream.Create;
324 <    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
324 >    if GetFileInfo(FileID).Size > 0 then
325      begin
326 <      Fdat_file.Free;
327 <      FDatOpened := False;
328 <    end
329 <    else
330 <      FDatOpened := True;
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  
# Line 359 | Line 335 | procedure TAccess_OniArchive.UpdateDatFi
335   begin
336    if fileid < GetFileCount then
337    begin
362    if not FDatOpened then
363      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
338      Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
339      Fdat_file.CopyFrom(Src, Fdat_files[fileid].Size);
366    if UnloadWhenUnused then
367    begin
368      Fdat_file.Free;
369      FDatOpened := False;
370    end
371    else
372      FDatOpened := True;
340    end;
341   end;
342  
# Line 381 | Line 348 | begin
348    begin
349      if not Assigned(Target) then
350        Target := TMemoryStream.Create;
384    if not FDatOpened then
385      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
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);
390    if UnloadWhenUnused then
391    begin
392      FDatOpened := False;
393      Fdat_file.Free;
394    end
395    else
396      FDatOpened := True;
355    end;
356   end;
357  
# Line 401 | Line 359 | procedure TAccess_OniArchive.UpdateDatFi
359   begin
360    if fileid < GetFileCount then
361    begin
404    if not FDatOpened then
405      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
362      Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
363      Fdat_file.CopyFrom(Src, Size);
408    if UnloadWhenUnused then
409    begin
410      Fdat_file.Free;
411      FDatOpened := False;
412    end
413    else
414      FDatOpened := True;
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 + function TAccess_OniArchive.GetDatLinks(FileID: Integer): TDatLinkList;
383 + var
384 +  i: Integer;
385 +  link: Integer;
386 + begin
387 +  Result := DatLinksManager.GetDatLinks(FConnectionID, FileID);
388 +  if Length(Result) > 0 then
389 +  begin
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 TAccess_OniArchive.GetRawsForType(RawType: String): TRawDataList;
409 + var
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 +        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);
# Line 430 | Line 435 | end;
435  
436  
437  
438 <
434 < procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; target: Pointer);
438 > procedure TAccess_OniArchive.LoadRawOffset(LocSep: Boolean; RawAddr, Size: Integer; var target: TStream);
439   begin
440 +  if not Assigned(Target) then
441 +    Target := TMemoryStream.Create;
442    if not LocSep then
443    begin
438    if not FRawOpened then
439      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
440        fmOpenReadWrite);
444      if RawAddr <= Fraw_file.Size then
445      begin
446        Fraw_file.Seek(RawAddr, soFromBeginning);
447 <      Fraw_file.Read(target^, size);
447 >      Target.CopyFrom(Fraw_file, size);
448 >      Target.Seek(0, soFromBeginning);
449      end;
446    if UnloadWhenUnused then
447    begin
448      FRawOpened := False;
449      Fraw_file.Free;
450    end
451    else
452      FRawOpened := True;
450    end
451    else
452    begin
456    if not FSepOpened then
457      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
458        fmOpenReadWrite);
453      if RawAddr <= Fsep_file.Size then
454      begin
455        Fsep_file.Seek(RawAddr, soFromBeginning);
456 <      Fsep_file.Read(target^, size);
456 >      Target.CopyFrom(Fsep_file, size);
457 >      Target.Seek(0, soFromBeginning);
458      end;
464    if UnloadWhenUnused then
465    begin
466      FSepOpened := False;
467      Fsep_file.Free;
468    end
469    else
470      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   procedure TAccess_OniArchive.LoadRawFile(FileID, DatOffset: Integer; var Target: TStream);
473   var
474    raw_info: TRawDataInfo;
# Line 483 | Line 481 | begin
481      raw_info := Self.GetRawInfo(FileID, DatOffset);
482      if not raw_info.LocSep then
483      begin
486      if not FRawOpened then
487        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
488          fmOpenReadWrite);
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);
493      if UnloadWhenUnused then
494      begin
495        FRawOpened := False;
496        Fraw_file.Free;
497      end
498      else
499        FRawOpened := True;
488      end
489      else
490      begin
503      if FUnloadWhenUnused or not FSepOpened then
504        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
505          fmOpenReadWrite);
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);
510      if UnloadWhenUnused then
511      begin
512        FSepOpened := False;
513        Fsep_file.Free;
514      end
515      else
516        FSepOpened := True;
495      end;
496    end;
497   end;
# Line 527 | Line 505 | begin
505      raw_info := GetRawInfo(FileID, DatOffset);
506      if not raw_info.LocSep then
507      begin
530      if not FRawOpened then
531        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
532          fmOpenReadWrite);
508        Fraw_file.Seek(raw_info.RawAddr, soFromBeginning);
509 <      Fraw_file.CopyFrom(Src, raw_info.RawSize);
535 <      if UnloadWhenUnused then
536 <      begin
537 <        FRawOpened := False;
538 <        Fraw_file.Free;
539 <      end
540 <      else
541 <        FRawOpened := True;
509 >      Fraw_file.CopyFrom(Src, Min(raw_info.RawSize, Src.Size));
510      end
511      else
512      begin
545      if not FSepOpened then
546        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
547          fmOpenReadWrite);
513        Fsep_file.Seek(raw_info.RawAddr, soFromBeginning);
514        Fsep_file.CopyFrom(Src, raw_info.RawSize);
550      if UnloadWhenUnused then
551      begin
552        FSepOpened := False;
553        Fsep_file.Free;
554      end
555      else
556        FSepOpened := True;
515      end;
516    end;
517   end;
# Line 576 | Line 534 | begin
534    end;
535   end;
536  
537 +
538   procedure TAccess_OniArchive.UpdateRawFilePart(FileID, DatOffset, Offset, Size: Integer; Src: TStream);
539   var
540    raw_info: TRawDataInfo;
# Line 585 | Line 544 | begin
544      raw_info := GetRawInfo(FileID, DatOffset);
545      if not raw_info.LocSep then
546      begin
588      if not FRawOpened then
589        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
590          fmOpenReadWrite);
547        Fraw_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
548        Fraw_file.CopyFrom(Src, Size);
593      if UnloadWhenUnused then
594      begin
595        FRawOpened := False;
596        Fraw_file.Free;
597      end
598      else
599        FRawOpened := True;
549      end
550      else
551      begin
603      if not FSepOpened then
604        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
605          fmOpenReadWrite);
552        Fsep_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
553        Fsep_file.CopyFrom(Src, Size);
608      if UnloadWhenUnused then
609      begin
610        FSepOpened := False;
611        Fsep_file.Free;
612      end
613      else
614        FSepOpened := True;
554      end;
555    end;
556   end;
557  
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 LocSep then
564    begin
565 <    if not FRawOpened then
566 <      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
625 <        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.CopyFrom(Src, Src.Size);
570 <    if UnloadWhenUnused then
571 <    begin
631 <      FRawOpened := False;
632 <      Fraw_file.Free;
633 <    end
634 <    else
635 <      FRawOpened := True;
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 not FSepOpened then
576 <      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
641 <        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.CopyFrom(Src, Src.Size);
580 <    if UnloadWhenUnused then
581 <    begin
647 <      FSepOpened := False;
648 <      Fsep_file.Free;
649 <    end
650 <    else
651 <      FSepOpened := True;
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  

Diff Legend

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