DEADSOFTWARE

simple allocation counter for classes
[d2df-sdl.git] / src / shared / wadreader.pas
index df0de0fc591a48ffe3d16ce7f68ba412fd781b85..3f13946bcb1dea1532c6805ad57af2ae4854449a 100644 (file)
@@ -22,13 +22,13 @@ unit wadreader;
 interface
 
 uses
-  sfs, xstreams;
+  mempool, sfs, xstreams, Classes;
 
 
 type
   SArray = array of ShortString;
 
-  TWADFile = class(TObject)
+  TWADFile = class(TPoolObject)
   private
     fFileName: AnsiString; // empty: not opened
     fIter: TSFSFileList;
@@ -36,21 +36,24 @@ 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 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 (): SArray;
 
+    // returns `nil` if file wasn't found
+    function openFileStream (name: AnsiString): TStream;
+
     property isOpen: Boolean read getIsOpen;
   end;
 
@@ -73,7 +76,7 @@ var
 implementation
 
 uses
-  SysUtils, Classes{, BinEditor}, e_log{, g_options}, utils, MAPSTRUCT;
+  SysUtils, e_log, utils, MAPDEF, xdynrec;
 
 
 function findDiskWad (fname: AnsiString): AnsiString;
@@ -231,26 +234,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 +300,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 +362,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]), MSG_WARNING);
         break;
       end;
       // if we want only maps, check if this is map
@@ -331,21 +370,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 +418,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
@@ -394,17 +446,17 @@ begin
       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]), MSG_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;
@@ -420,7 +472,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);