X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fshared%2Fwadreader.pas;h=1419f264faf6876b54adfe1d0b3f4dfa076bf713;hb=03988912c6a1d85d8ba35362e45690c414f13d0b;hp=df0de0fc591a48ffe3d16ce7f68ba412fd781b85;hpb=dd0d8ac4cc2a0aa774f25c8a1a774f7358acfae7;p=d2df-sdl.git diff --git a/src/shared/wadreader.pas b/src/shared/wadreader.pas index df0de0f..1419f26 100644 --- a/src/shared/wadreader.pas +++ b/src/shared/wadreader.pas @@ -1,9 +1,8 @@ -(* Copyright (C) DooM 2D:Forever Developers +(* Copyright (C) Doom 2D: Forever Developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,13 +21,13 @@ unit wadreader; interface uses - sfs, xstreams; + Classes, + {$IFDEF USE_MEMPOOL}mempool,{$ENDIF} + sfs, xstreams, utils; type - SArray = array of ShortString; - - TWADFile = class(TObject) + TWADFile = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF} private fFileName: AnsiString; // empty: not opened fIter: TSFSFileList; @@ -36,33 +35,41 @@ type function getIsOpen (): Boolean; function isMapResource (idx: Integer): Boolean; - function GetResourceEx (name: AnsiString; wantMap: Boolean; var pData: Pointer; var Len: Integer): Boolean; + function GetResourceEx (name: AnsiString; wantMap: Boolean; var pData: Pointer; var Len: Integer; logError: Boolean=true): Boolean; public - constructor Create(); - destructor Destroy(); override; + constructor Create (); + destructor Destroy (); override; - procedure FreeWAD(); + procedure FreeWAD (); function ReadFile (FileName: AnsiString): Boolean; function ReadMemory (Data: Pointer; Len: LongWord): Boolean; - function GetResource (name: AnsiString; var pData: Pointer; var Len: Integer): Boolean; - function GetMapResource (name: AnsiString; var pData: Pointer; var Len: Integer): Boolean; - function GetMapResources (): SArray; + function GetResource (name: AnsiString; var pData: Pointer; var Len: Integer; logError: Boolean=true): Boolean; + function GetMapResource (name: AnsiString; var pData: Pointer; var Len: Integer; logError: Boolean=true): Boolean; + function GetMapResources (): SSArray; + + // returns `nil` if file wasn't found + function openFileStream (name: AnsiString): TStream; property isOpen: Boolean read getIsOpen; end; - +// g_ExtractWadName C:\svr\shit.wad:\MAPS\MAP01 -> C:/svr/shit.wad function g_ExtractWadName (resourceStr: AnsiString): AnsiString; + +// g_ExtractWadNameNoPath C:\svr\shit.wad:\MAPS\MAP01 -> shit.wad function g_ExtractWadNameNoPath (resourceStr: AnsiString): AnsiString; + +// g_ExtractFilePath C:\svr\shit.wad:\MAPS\MAP01 -> :/MAPS function g_ExtractFilePath (resourceStr: AnsiString): AnsiString; + +// g_ExtractFileName C:\svr\shit.wad:\MAPS\MAP01 -> MAP01 function g_ExtractFileName (resourceStr: AnsiString): AnsiString; // without path -function g_ExtractFilePathName (resourceStr: AnsiString): AnsiString; -// return fixed AnsiString or empty AnsiString -function findDiskWad (fname: AnsiString): AnsiString; +// g_ExtractFilePathName C:\svr\shit.wad:\MAPS\MAP01 -> MAPS/MAP01 +function g_ExtractFilePathName (resourceStr: AnsiString): AnsiString; var @@ -73,34 +80,7 @@ var implementation uses - SysUtils, Classes{, BinEditor}, e_log{, g_options}, utils, MAPSTRUCT; - - -function findDiskWad (fname: AnsiString): AnsiString; -begin - result := ''; - if not findFileCI(fname) then - begin - //e_WriteLog(Format('findDiskWad: error looking for [%s]', [fname]), MSG_NOTIFY); - if StrEquCI1251(ExtractFileExt(fname), '.wad') then - begin - fname := ChangeFileExt(fname, '.pk3'); - //e_WriteLog(Format(' looking for [%s]', [fname]), MSG_NOTIFY); - if not findFileCI(fname) then - begin - fname := ChangeFileExt(fname, '.zip'); - //e_WriteLog(Format(' looking for [%s]', [fname]), MSG_NOTIFY); - if not findFileCI(fname) then exit; - end; - end - else - begin - exit; - end; - end; - //e_WriteLog(Format('findDiskWad: FOUND [%s]', [fname]), MSG_NOTIFY); - result := fname; -end; + SysUtils, e_log, MAPDEF, xdynrec; function normSlashes (s: AnsiString): AnsiString; @@ -231,26 +211,58 @@ begin fFileName := ''; end; + +//FIXME: detect text maps properly here function TWADFile.isMapResource (idx: Integer): Boolean; var - sign: packed array [0..2] of Char; - fs: TStream; + //sign: packed array [0..2] of Char; + fs: TStream = nil; begin result := false; if not isOpen or (fIter = nil) then exit; if (idx < 0) or (idx >= fIter.Count) then exit; - fs := nil; try fs := fIter.volume.OpenFileByIndex(idx); + result := TDynMapDef.canBeMap(fs); + (* fs.readBuffer(sign, 3); result := (sign = MAP_SIGNATURE); + if not result then result := (sign[0] = 'm') and (sign[1] = 'a') and (sign[2] = 'p'); + *) except - if fs <> nil then fs.Free(); + fs.Free(); + result := false; // just in case exit; end; fs.Free(); end; + +// returns `nil` if file wasn't found +function TWADFile.openFileStream (name: AnsiString): TStream; +var + f: Integer; + fi: TSFSFileInfo; +begin + result := nil; + // backwards, due to possible similar names and such + for f := fIter.Count-1 downto 0 do + begin + fi := fIter.Files[f]; + if fi = nil then continue; + if StrEquCI1251(fi.name, name) then + begin + try + result := fIter.volume.OpenFileByIndex(f); + except + result := nil; + end; + if (result <> nil) then exit; + end; + end; +end; + + function removeExt (s: AnsiString): AnsiString; var i: Integer; @@ -265,15 +277,19 @@ begin result := s; end; -function TWADFile.GetResourceEx (name: AnsiString; wantMap: Boolean; var pData: Pointer; var Len: Integer): Boolean; + +function TWADFile.GetResourceEx (name: AnsiString; wantMap: Boolean; var pData: Pointer; var Len: Integer; logError: Boolean=true): Boolean; var f, lastSlash: Integer; fi: TSFSFileInfo; fs: TStream; fpp: Pointer; rpath, rname: AnsiString; - sign: array [0..2] of Char; + //sign: packed array [0..2] of Char; goodMap: Boolean; + {$IFNDEF SFS_MAPDETECT_FX} + wst: TSFSMemoryChunkStream; + {$ENDIF} begin Result := False; if not isOpen or (fIter = nil) then Exit; @@ -323,7 +339,7 @@ begin if fs = nil then begin if wantMap then continue; - e_WriteLog(Format('DFWAD: can''t open file [%s] in [%s]', [name, fFileName]), MSG_WARNING); + if logError then e_WriteLog(Format('DFWAD: can''t open file [%s] in [%s]', [name, fFileName]), TMsgType.Warning); break; end; // if we want only maps, check if this is map @@ -331,21 +347,27 @@ begin if wantMap then begin goodMap := false; - //e_WriteLog(Format('DFWAD: checking for good map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]), MSG_NOTIFY); + {$IF DEFINED(D2D_NEW_MAP_READER_DBG)} + e_LogWritefln('DFWAD: checking for good map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]); + {$ENDIF} try - fs.readBuffer(sign, 3); - goodMap := (sign = MAP_SIGNATURE); - { + //fs.readBuffer(sign, 3); + //goodMap := (sign = MAP_SIGNATURE); + //if not goodMap then goodMap := (sign[0] = 'm') and (sign[1] = 'a') and (sign[2] = 'p'); + goodMap := TDynMapDef.canBeMap(fs); + {$IF DEFINED(D2D_NEW_MAP_READER_DBG)} if goodMap then - e_WriteLog(Format(' GOOD map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]), MSG_NOTIFY) + e_LogWritefln(' GOOD map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]) else - e_WriteLog(Format(' BAD map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]), MSG_NOTIFY); - } + e_LogWritefln(' BAD map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]); + {$ENDIF} except end; if not goodMap then begin - //e_WriteLog(Format(' not a map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]), MSG_NOTIFY); + {$IF DEFINED(D2D_NEW_MAP_READER_DBG)} + e_LogWritefln(' not a map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]); + {$ENDIF} fs.Free(); continue; end; @@ -373,8 +395,15 @@ begin goodMap := false; if Len >= 3 then begin - Move(pData^, sign, 3); - goodMap := (sign = MAP_SIGNATURE); + //Move(pData^, sign, 3); + //goodMap := (sign = MAP_SIGNATURE); + wst := TSFSMemoryChunkStream.Create(pData, Len); + try + goodMap := TDynMapDef.canBeMap(wst); + except + goodMap := false; + end; + wst.Free(); end; if not goodMap then begin @@ -389,25 +418,25 @@ begin result := true; {$IFDEF SFS_DFWAD_DEBUG} if wadoptDebug then - e_WriteLog(Format('DFWAD: file [%s] FOUND in [%s]; size is %d bytes', [name, fFileName, Len]), MSG_NOTIFY); + e_WriteLog(Format('DFWAD: file [%s] FOUND in [%s]; size is %d bytes', [name, fFileName, Len]), TMsgType.Notify); {$ENDIF} exit; end; end; - e_WriteLog(Format('DFWAD: file [%s] not found in [%s]', [name, fFileName]), MSG_WARNING); + if logError then e_WriteLog(Format('DFWAD: file [%s] not found in [%s]', [name, fFileName]), TMsgType.Warning); end; -function TWADFile.GetResource (name: AnsiString; var pData: Pointer; var Len: Integer): Boolean; +function TWADFile.GetResource (name: AnsiString; var pData: Pointer; var Len: Integer; logError: Boolean=true): Boolean; begin - result := GetResourceEx(name, false, pData, Len); + result := GetResourceEx(name, false, pData, Len, logError); end; -function TWADFile.GetMapResource (name: AnsiString; var pData: Pointer; var Len: Integer): Boolean; +function TWADFile.GetMapResource (name: AnsiString; var pData: Pointer; var Len: Integer; logError: Boolean=true): Boolean; begin - result := GetResourceEx(name, true, pData, Len); + result := GetResourceEx(name, true, pData, Len, logError); end; -function TWADFile.GetMapResources (): SArray; +function TWADFile.GetMapResources (): SSArray; var f, c: Integer; fi: TSFSFileInfo; @@ -420,7 +449,9 @@ begin fi := fIter.Files[f]; if fi = nil then continue; if length(fi.name) = 0 then continue; - //e_WriteLog(Format('DFWAD: checking for map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]), MSG_NOTIFY); + {$IF DEFINED(D2D_NEW_MAP_READER)} + //e_LogWritefln('DFWAD: checking for map in wad [%s], file [%s] (#%d)', [fFileName, fi.fname, f]); + {$ENDIF} if isMapResource(f) then begin s := removeExt(fi.name); @@ -452,11 +483,11 @@ begin rfn := findDiskWad(FileName); if length(rfn) = 0 then begin - e_WriteLog(Format('TWADFile.ReadFile: error looking for [%s]', [FileName]), MSG_NOTIFY); + e_WriteLog(Format('TWADFile.ReadFile: error looking for [%s]', [FileName]), TMsgType.Notify); exit; end; {$IFDEF SFS_DFWAD_DEBUG} - if wadoptDebug then e_WriteLog(Format('TWADFile.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY); + if wadoptDebug then e_WriteLog(Format('TWADFile.ReadFile: FOUND [%s]', [rfn]), TMsgType.Notify); {$ENDIF} // cache this wad try @@ -475,7 +506,7 @@ begin if fIter = nil then Exit; fFileName := rfn; {$IFDEF SFS_DFWAD_DEBUG} - if wadoptDebug then e_WriteLog(Format('TWADFile.ReadFile: [%s] opened', [fFileName]), MSG_NOTIFY); + if wadoptDebug then e_WriteLog(Format('TWADFile.ReadFile: [%s] opened', [fFileName]), TMsgType.Notify); {$ENDIF} Result := True; end; @@ -495,14 +526,14 @@ begin FreeWAD(); if (Data = nil) or (Len = 0) then begin - e_WriteLog('TWADFile.ReadMemory: EMPTY SUBWAD!', MSG_WARNING); + e_WriteLog('TWADFile.ReadMemory: EMPTY SUBWAD!', TMsgType.Warning); Exit; end; fn := Format(' -- memwad %d -- ', [uniqueCounter]); Inc(uniqueCounter); {$IFDEF SFS_DFWAD_DEBUG} - if wadoptDebug then e_WriteLog(Format('TWADFile.ReadMemory: [%s]', [fn]), MSG_NOTIFY); + if wadoptDebug then e_WriteLog(Format('TWADFile.ReadMemory: [%s]', [fn]), TMsgType.Notify); {$ENDIF} try @@ -522,7 +553,7 @@ begin fFileName := fn; {$IFDEF SFS_DFWAD_DEBUG} - if wadoptDebug then e_WriteLog(Format('TWADFile.ReadMemory: [%s] opened', [fFileName]), MSG_NOTIFY); + if wadoptDebug then e_WriteLog(Format('TWADFile.ReadMemory: [%s] opened', [fFileName]), TMsgType.Notify); {$ENDIF} {