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 112 by alloc, Thu Feb 22 00:37:39 2007 UTC vs.
Revision 252 by alloc, Sun Dec 16 14:44:16 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 const
63  header_ident1_pc: array[0..$13] of Byte =
64    ($1F, $27, $DC, $33, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
65    $14, $00, $10, $00, $08, $00);
66  header_ident1_mac: array[0..$13] of Byte =
67    ($61, $30, $C1, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
68    $14, $00, $10, $00, $08, $00);
69  header_ident1_macbeta: array[0..$13] of Byte =
70    ($81, $11, $8D, $23, $DF, $BC, $03, $00, $31, $33, $52, $56, $40, $00,
71    $14, $00, $10, $00, $08, $00);
72  header_ident2: array[0..$F] of Byte =
73    ($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 78 | Line 64 | var
64    Fdat_filesmap: TFilesMap;
65    Fdat_namedfilesmap: TNamedFilesMap;
66   begin
81  FUnloadWhenUnused := True;
82  FDatOpened := False;
83  FRawOpened := False;
67    Msg := SM_UnknownError;
68    if not FileExists(DatFilename) then
69    begin
# Line 88 | Line 71 | begin
71      Exit;
72    end;
73    FFileName := DatFilename;
74 <  Fdat_file := TFileStream.Create(FFileName, fmOpenRead);
74 >  Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
75    Fdat_file.Read(Fdat_header, SizeOf(Fdat_header));
76    header_pc  := True;
77    header_mac := True;
78    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];
99 <    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 156 | 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 169 | 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 237 | Line 232 | var
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 258 | Line 255 | begin
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;
# Line 294 | 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 320 | Line 321 | begin
321    begin
322      if not Assigned(Target) then
323        Target := TMemoryStream.Create;
324 <    if not FDatOpened then
324 <      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
325 <    Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
326 <    streampos := Target.Position;
327 <    Target.CopyFrom(Fdat_file, Fdat_files[fileid].Size);
328 <    Target.Seek(streampos, soFromBeginning);
329 <    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 340 | Line 335 | procedure TAccess_OniArchive.UpdateDatFi
335   begin
336    if fileid < GetFileCount then
337    begin
343    if not FDatOpened then
344      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
338      Fdat_file.Seek(Fdat_files[fileid].DatAddr, soFromBeginning);
339      Fdat_file.CopyFrom(Src, Fdat_files[fileid].Size);
347    if UnloadWhenUnused then
348    begin
349      Fdat_file.Free;
350      FDatOpened := False;
351    end
352    else
353      FDatOpened := True;
340    end;
341   end;
342  
# Line 362 | Line 348 | begin
348    begin
349      if not Assigned(Target) then
350        Target := TMemoryStream.Create;
365    if not FDatOpened then
366      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);
371    if UnloadWhenUnused then
372    begin
373      FDatOpened := False;
374      Fdat_file.Free;
375    end
376    else
377      FDatOpened := True;
355    end;
356   end;
357  
# Line 382 | Line 359 | procedure TAccess_OniArchive.UpdateDatFi
359   begin
360    if fileid < GetFileCount then
361    begin
385    if not FDatOpened then
386      Fdat_file := TFileStream.Create(FFileName, fmOpenReadWrite);
362      Fdat_file.Seek(Fdat_files[fileid].DatAddr + offset, soFromBeginning);
363      Fdat_file.CopyFrom(Src, Size);
389    if UnloadWhenUnused then
390    begin
391      Fdat_file.Free;
392      FDatOpened := False;
393    end
394    else
395      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 411 | Line 435 | end;
435  
436  
437  
438 <
415 < 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
419    if not FRawOpened then
420      Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
421        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;
427    if UnloadWhenUnused then
428    begin
429      FRawOpened := False;
430      Fraw_file.Free;
431    end
432    else
433      FRawOpened := True;
450    end
451    else
452    begin
437    if not FSepOpened then
438      Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
439        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;
445    if UnloadWhenUnused then
446    begin
447      FSepOpened := False;
448      Fsep_file.Free;
449    end
450    else
451      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 464 | Line 481 | begin
481      raw_info := Self.GetRawInfo(FileID, DatOffset);
482      if not raw_info.LocSep then
483      begin
467      if not FRawOpened then
468        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
469          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);
474      if UnloadWhenUnused then
475      begin
476        FRawOpened := False;
477        Fraw_file.Free;
478      end
479      else
480        FRawOpened := True;
488      end
489      else
490      begin
484      if FUnloadWhenUnused or not FSepOpened then
485        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
486          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);
491      if UnloadWhenUnused then
492      begin
493        FSepOpened := False;
494        Fsep_file.Free;
495      end
496      else
497        FSepOpened := True;
495      end;
496    end;
497   end;
# Line 508 | Line 505 | begin
505      raw_info := GetRawInfo(FileID, DatOffset);
506      if not raw_info.LocSep then
507      begin
511      if not FRawOpened then
512        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
513          fmOpenReadWrite);
508        Fraw_file.Seek(raw_info.RawAddr, soFromBeginning);
509 <      Fraw_file.CopyFrom(Src, raw_info.RawSize);
516 <      if UnloadWhenUnused then
517 <      begin
518 <        FRawOpened := False;
519 <        Fraw_file.Free;
520 <      end
521 <      else
522 <        FRawOpened := True;
509 >      Fraw_file.CopyFrom(Src, Min(raw_info.RawSize, Src.Size));
510      end
511      else
512      begin
526      if not FSepOpened then
527        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
528          fmOpenReadWrite);
513        Fsep_file.Seek(raw_info.RawAddr, soFromBeginning);
514        Fsep_file.CopyFrom(Src, raw_info.RawSize);
531      if UnloadWhenUnused then
532      begin
533        FSepOpened := False;
534        Fsep_file.Free;
535      end
536      else
537        FSepOpened := True;
515      end;
516    end;
517   end;
# Line 557 | 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 566 | Line 544 | begin
544      raw_info := GetRawInfo(FileID, DatOffset);
545      if not raw_info.LocSep then
546      begin
569      if not FRawOpened then
570        Fraw_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.raw'),
571          fmOpenReadWrite);
547        Fraw_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
548        Fraw_file.CopyFrom(Src, Size);
574      if UnloadWhenUnused then
575      begin
576        FRawOpened := False;
577        Fraw_file.Free;
578      end
579      else
580        FRawOpened := True;
549      end
550      else
551      begin
584      if not FSepOpened then
585        Fsep_file := TFileStream.Create(AnsiReplaceStr(FFileName, '.dat', '.sep'),
586          fmOpenReadWrite);
552        Fsep_file.Seek(raw_info.RawAddr + Offset, soFromBeginning);
553        Fsep_file.CopyFrom(Src, Size);
589      if UnloadWhenUnused then
590      begin
591        FSepOpened := False;
592        Fsep_file.Free;
593      end
594      else
595        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'),
606 <        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
612 <      FRawOpened := False;
613 <      Fraw_file.Free;
614 <    end
615 <    else
616 <      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'),
622 <        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
628 <      FSepOpened := False;
629 <      Fsep_file.Free;
630 <    end
631 <    else
632 <      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)