DEADSOFTWARE

sfs: remove common dir from pk3 (this should fix invalid zips)
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 8 Apr 2016 01:07:26 +0000 (04:07 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Fri, 8 Apr 2016 01:13:40 +0000 (04:13 +0300)
src/game/g_game.pas
src/game/g_gui.pas
src/game/g_options.pas
src/sfs/sfs.pas
src/sfs/sfsZipFS.pas
src/shared/WADEDITOR.pas

index 0862e74a18977c7422c08df6058b8a58a4d85f86..408191bb3cd2f2876ca68d0a6cfb3dc1bb59fa81 100644 (file)
@@ -1045,6 +1045,13 @@ begin
     until FindNext(SR) <> 0;
   FindClose(SR);
 
+  if FindFirst(ModelsDir+'*.pk3', faAnyFile, SR) = 0 then
+    repeat
+      if not g_PlayerModel_Load(ModelsDir+SR.Name) then
+        e_WriteLog(Format('Error loading model %s', [SR.Name]), MSG_WARNING);
+    until FindNext(SR) <> 0;
+  FindClose(SR);
+
   gGameOn := False;
   gPause := False;
   gTime := 0;
index 7eaed7ba7128470653e26c6b53d49020b58f09b1..2f9bc08380d79cf1ba7447ce1800a727463e3ec4 100644 (file)
@@ -2872,9 +2872,18 @@ begin
     repeat
       AddItem(SR.Name);
     until FindNext(SR) <> 0;
-
   FindClose(SR);
 
+  //FIXME: HACK!
+  if FFileMask = '*.wad' then
+  begin
+    if FindFirst(path+'*.pk3', faAnyFile, SR) = 0 then
+      repeat
+        AddItem(SR.Name);
+      until FindNext(SR) <> 0;
+    FindClose(SR);
+  end;
+
   for i := 0 to High(FItems) do
     if FItems[i][1] = #1 then
       FItems[i][1] := #29;
index 3f134305da197592e652a1958cda9e74fd2a4b6d..54ea9208357b5bdbab46ccb58a9b0cf3db9b2823 100644 (file)
@@ -94,6 +94,7 @@ var
   gnBotsVS: String            = 'Everybody';
   gsSDLSampleRate: Integer    = 44100;
   gsSDLBufferSize: Integer    = 2048;
+  gSFSDebug: Boolean          = False;
 
 implementation
 
@@ -331,6 +332,7 @@ begin
   gShowMessages := config.ReadBool('Game', 'Messages', True);
   gRevertPlayers := config.ReadBool('Game', 'RevertPlayers', False);
   gChatBubble := Min(Max(config.ReadInt('Game', 'ChatBubble', 4), 0), 4);
+  gSFSDebug := config.ReadBool('Game', 'gSFSDebug', False);
 
 // Ãåéìïëåé â ñâîåé èãðå
   gcMap := config.ReadStr('GameplayCustom', 'Map', '');
@@ -532,6 +534,7 @@ begin
   config.WriteBool('Game', 'Messages', gShowMessages);
   config.WriteBool('Game', 'RevertPlayers', gRevertPlayers);
   config.WriteInt('Game', 'ChatBubble', gChatBubble);
+  config.WriteBool('Game', 'SFSDebug', gSFSDebug);
 
   config.WriteStr ('GameplayCustom', 'Map', gcMap);
   config.WriteStr ('GameplayCustom', 'GameMode', gcGameMode);
index f79413a237e5f2fe3225ca5993bd07b094e980b0..3776a0036d7742c6df3160222d12328f5d35e3b1 100644 (file)
@@ -73,6 +73,8 @@ type
     // íèêàêèõ ïàäåíèé íà íåïðàâèëüíûå èíäåêñû!
     function GetFiles (index: Integer): TSFSFileInfo; virtual;
 
+    procedure removeCommonPath (); virtual;
+
   public
     // pSt íå îáÿçàòåëüíî çàïîìèíàòü, åñëè îí íå íóæåí.
     constructor Create (const pFileName: TSFSString; pSt: TStream); virtual;
@@ -224,6 +226,11 @@ function WildMatch (pattern, text: TSFSString): Boolean;
 function WildListMatch (wildList, text: TSFSString; delimChar: AnsiChar=':'): Integer;
 function HasWildcards (const pattern: TSFSString): Boolean;
 
+// this will compare only last path element from sfspath
+function SFSDFPathEqu (sfspath: string; path: string): Boolean;
+
+function SFSUpCase (ch: Char): Char;
+
 
 var
   // ïðàâäà: ðàçðåøåíî èñêàòü ôàéëî íå òîëüêî â ôàéëàõ äàííûõ, íî è íà äèñêå.
@@ -543,7 +550,7 @@ begin
   end;
 end;
 
-function le2upper (ch: Char): Char;
+function SFSUpCase (ch: Char): Char;
 begin
   if ch < #128 then
   begin
@@ -575,11 +582,32 @@ begin
   if length(s0) <> length(s1) then exit;
   for i := 1 to length(s0) do
   begin
-    if le2upper(s0[i]) <> le2upper(s1[i]) then exit;
+    if SFSUpCase(s0[i]) <> SFSUpCase(s1[i]) then exit;
   end;
   result := true;
 end;
 
+// this will compare only last path element from sfspath
+function SFSDFPathEqu (sfspath: string; path: string): Boolean;
+{var
+  i: Integer;}
+begin
+  result := SFSStrEqu(sfspath, path);
+(*
+  if not result and (length(sfspath) > 1) then
+  begin
+    i := length(sfspath);
+    while i > 1 do
+    begin
+      while (i > 1) and (sfspath[i-1] <> '/') do Dec(i);
+      if i <= 1 then exit;
+      writeln('{', sfspath, '} [', Copy(sfspath, i, length(sfspath)), '] : [', path, ']');
+      result := SFSStrEqu(Copy(sfspath, i, length(sfspath)), path);
+    end;
+  end;
+*)
+end;
+
 function SFSReplacePathDelims (const s: TSFSString; newDelim: TSFSChar): TSFSString;
 var
   f: Integer;
@@ -700,6 +728,10 @@ begin
   fFiles := TObjectList.Create(true);
 end;
 
+procedure TSFSVolume.removeCommonPath ();
+begin
+end;
+
 procedure TSFSVolume.DoDirectoryRead ();
 var
   fl: TStringList; //!!!FIXME! change to list of wide TSFSStrings or so!
@@ -755,6 +787,7 @@ begin
     fl.Free();
     raise;
   end;
+  removeCommonPath();
 end;
 
 destructor TSFSVolume.Destroy ();
index 5b6dafda3ee2e07b5a489e143f9f34798db725d5..9fb1137e0ca70d054282ddc68c6a01a190b67717 100644 (file)
@@ -33,6 +33,7 @@ type
     procedure DFWADReadDirectory ();
 
     procedure ReadDirectory (); override;
+    procedure removeCommonPath (); override;
 
   public
     function OpenFileByIndex (const index: Integer): TStream; override;
@@ -133,6 +134,62 @@ begin
   result := true;
 end;
 
+function maxPrefix (s0: string; s1: string): Integer;
+var
+  f: Integer;
+begin
+  for f := 1 to length(s0) do
+  begin
+    if f > length(s1) then begin result := f; exit; end;
+    if SFSUpCase(s0[f]) <> SFSUpCase(s1[f]) then begin result := f; exit; end;
+  end;
+  result := length(s0);
+end;
+
+procedure TSFSZipVolume.removeCommonPath ();
+var
+  f, pl, maxsc, sc, c: integer;
+  cp, s: string;
+  fi: TSFSZipFileInfo;
+begin
+  if fType <> sfszvZIP then exit;
+  maxsc := 0;
+  if fFiles.Count = 0 then exit;
+  cp := '';
+  for f := 0 to fFiles.Count-1 do
+  begin
+    fi := TSFSZipFileInfo(fFiles[f]);
+    s := fi.fPath;
+    if length(s) > 0 then begin cp := s; break; end;
+  end;
+  if length(cp) = 0 then exit;
+  for f := 0 to fFiles.Count-1 do
+  begin
+    fi := TSFSZipFileInfo(fFiles[f]);
+    s := fi.fPath;
+    if length(s) = 0 then continue;
+    pl := maxPrefix(cp, s);
+    //writeln('s=[', s, ']; cp=[', cp, ']; pl=', pl);
+    if pl = 0 then exit; // no common prefix at all
+    cp := Copy(cp, 1, pl);
+    sc := 0;
+    for c := 1 to length(s) do if s[c] = '/' then Inc(sc);
+    if sc > maxsc then maxsc := sc;
+  end;
+  if maxsc < 2 then exit; // alas
+  while (length(cp) > 0) and (cp[length(cp)] <> '/') do cp := Copy(cp, 1, length(cp)-1);
+  if length(cp) < 2 then exit; // nothing to do
+  for f := 0 to fFiles.Count-1 do
+  begin
+    fi := TSFSZipFileInfo(fFiles[f]);
+    if length(fi.fPath) >= length(cp) then
+    begin
+      s := fi.fPath;
+      fi.fPath := Copy(fi.fPath, length(cp)+1, length(fi.fPath));
+      //writeln('FIXED [', s, '] -> [', fi.fPath, ']');
+    end;
+  end;
+end;
 
 { TSFSZipVolume }
 procedure TSFSZipVolume.ZIPReadDirectory ();
@@ -153,7 +210,9 @@ begin
 
     if sign <> 'PK'#3#4 then break;
 
-    ignoreFile := false; skipped := false;
+    ignoreFile := false;
+    skipped := false;
+
     fi := TSFSZipFileInfo.Create(self);
     fi.fPackSz := 0;
     fi.fMethod := 0;
index 79f14b6364ab88ea17d7049f6feb39caa7ec3fa2..4c3e9aeee201630ac4394980ba2d6f2d86f7cd6c 100644 (file)
@@ -1,6 +1,6 @@
 unit WADEDITOR;
 
-{.$DEFINE SFS_DWFAD_DEBUG}
+{$DEFINE SFS_DWFAD_DEBUG}
 
 interface
 
@@ -53,7 +53,7 @@ procedure g_ProcessResourceStr (ResourceStr: String; FileName, SectionName, Reso
 implementation
 
 uses
-  SysUtils, Classes, BinEditor, e_log;
+  SysUtils, Classes, BinEditor, e_log, g_options;
 
 
 procedure g_ProcessResourceStr (ResourceStr: String; var FileName, SectionName, ResourceName: String);
@@ -147,13 +147,14 @@ var
 begin
   Result := False;
   if not isOpen or (fIter = nil) then Exit;
+  if length(Resource) = 0 then Exit; // just in case
   if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
   for f := 0 to fIter.Count-1 do
   begin
     fi := fIter.Files[f];
     if fi = nil then continue;
     //e_WriteLog(Format('DFWAD: searching for [%s : %s] in [%s]; current is [%s : %s] (%d, %d)', [Section, Resource, fFileName, fi.path, fi.name, SFSStrEqu(fi.path, Section), SFSStrEqu(fi.name, Resource)]), MSG_NOTIFY);
-    if SFSStrEqu(fi.path, Section) and SFSStrEqu(fi.name, Resource) then
+    if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) and SFSStrEqu(fi.name, Resource) then
     begin
       // i found her!
       //fn := fFileName+'::'+fi.path+fi.name;
@@ -174,6 +175,7 @@ begin
       fs.Free;
       result := true;
       {$IFDEF SFS_DWFAD_DEBUG}
+      if gSFSDebug then
         e_WriteLog(Format('DFWAD: file [%s%s] FOUND in [%s]; size is %d bytes', [Section, Resource, fFileName, Len]), MSG_NOTIFY);
       {$ENDIF}
       exit;
@@ -195,7 +197,8 @@ begin
   begin
     fi := fIter.Files[f];
     if fi = nil then continue;
-    if SFSStrEqu(fi.path, Section) then
+    if length(fi.name) = 0 then continue;
+    if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) then
     begin
       SetLength(result, Length(result)+1);
       result[high(result)] := fi.name;
@@ -207,6 +210,8 @@ end;
 function TWADEditor_1.ReadFile (FileName: string): Boolean;
 var
   rfn: string;
+  //f: Integer;
+  //fi: TSFSFileInfo;
 begin
   Result := False;
   //e_WriteLog(Format('TWADEditor_1.ReadFile: [%s]', [FileName]), MSG_NOTIFY);
@@ -222,12 +227,14 @@ begin
       else if FileExists(rfn+'.zip') then rfn := rfn+'.zip'
       else rfn := FileName;
       {.$IFDEF SFS_DWFAD_DEBUG}
+      if gSFSDebug then
         if FileExists(rfn) then e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
       {.$ENDIF}
     end;
   end;
   if not FileExists(rfn) then exit;
   {$IFDEF SFS_DWFAD_DEBUG}
+  if gSFSDebug then
     e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
   {$ENDIF}
   // cache this wad
@@ -236,8 +243,17 @@ begin
   if fIter = nil then Exit;
   fFileName := rfn;
   {$IFDEF SFS_DWFAD_DEBUG}
+  if gSFSDebug then
     e_WriteLog(Format('TWADEditor_1.ReadFile: [%s] opened', [fFileName]), MSG_NOTIFY);
   {$ENDIF}
+  {
+    for f := 0 to fIter.Count-1 do
+    begin
+      fi := fIter.Files[f];
+      if fi = nil then continue;
+      e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, fi.size]), MSG_NOTIFY);
+    end;
+  }
   Result := True;
 end;
 
@@ -247,7 +263,6 @@ var
 
 function TWADEditor_1.ReadMemory (Data: Pointer; Len: LongWord): Boolean;
 var
-  Signature: array[0..4] of Char;
   fn: string;
   st: TStream = nil;
   //f: Integer;