From: Ketmar Dark Date: Fri, 8 Apr 2016 01:07:26 +0000 (+0300) Subject: sfs: remove common dir from pk3 (this should fix invalid zips) X-Git-Url: http://deadsoftware.ru/gitweb?p=d2df-sdl.git;a=commitdiff_plain;h=20428038ea09152f824e5947da1d550a4774207e sfs: remove common dir from pk3 (this should fix invalid zips) --- diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 0862e74..408191b 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -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; diff --git a/src/game/g_gui.pas b/src/game/g_gui.pas index 7eaed7b..2f9bc08 100644 --- a/src/game/g_gui.pas +++ b/src/game/g_gui.pas @@ -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; diff --git a/src/game/g_options.pas b/src/game/g_options.pas index 3f13430..54ea920 100644 --- a/src/game/g_options.pas +++ b/src/game/g_options.pas @@ -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); diff --git a/src/sfs/sfs.pas b/src/sfs/sfs.pas index f79413a..3776a00 100644 --- a/src/sfs/sfs.pas +++ b/src/sfs/sfs.pas @@ -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 (); diff --git a/src/sfs/sfsZipFS.pas b/src/sfs/sfsZipFS.pas index 5b6dafd..9fb1137 100644 --- a/src/sfs/sfsZipFS.pas +++ b/src/sfs/sfsZipFS.pas @@ -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; diff --git a/src/shared/WADEDITOR.pas b/src/shared/WADEDITOR.pas index 79f14b6..4c3e9ae 100644 --- a/src/shared/WADEDITOR.pas +++ b/src/shared/WADEDITOR.pas @@ -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;