2009-04-19 18:07:22 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.IO ;
using CodeImp.DoomBuilder.IO ;
using CodeImp.DoomBuilder.ZDoom ;
2012-06-01 10:17:47 +00:00
using CodeImp.DoomBuilder.GZBuilder.Data ;
2014-01-08 09:46:57 +00:00
using System.Text.RegularExpressions ;
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.Data
{
internal sealed class WADReader : DataReader
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Structures
private struct LumpRange
{
public int start ;
public int end ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Source
private WAD file ;
private bool is_iwad ;
private bool strictpatches ;
// Lump ranges
private List < LumpRange > flatranges ;
2013-12-02 15:02:01 +00:00
private List < LumpRange > invertedflatranges ; //mxd
2009-04-19 18:07:22 +00:00
private List < LumpRange > patchranges ;
private List < LumpRange > spriteranges ;
private List < LumpRange > textureranges ;
2009-05-12 09:50:08 +00:00
private List < LumpRange > colormapranges ;
2014-01-08 09:46:57 +00:00
private List < LumpRange > voxelranges ; //mxd
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public bool IsIWAD { get { return is_iwad ; } }
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
public WADReader ( DataLocation dl ) : base ( dl )
{
General . WriteLogLine ( "Opening WAD resource '" + location . location + "'" ) ;
2010-10-03 16:54:38 +00:00
if ( ! File . Exists ( location . location ) )
throw new FileNotFoundException ( "Could not find the file \"" + location . location + "\"" , location . location ) ;
2009-04-19 18:07:22 +00:00
// Initialize
file = new WAD ( location . location , true ) ;
is_iwad = ( file . Type = = WAD . TYPE_IWAD ) ;
strictpatches = dl . option1 ;
patchranges = new List < LumpRange > ( ) ;
spriteranges = new List < LumpRange > ( ) ;
flatranges = new List < LumpRange > ( ) ;
textureranges = new List < LumpRange > ( ) ;
2009-05-12 09:50:08 +00:00
colormapranges = new List < LumpRange > ( ) ;
2014-01-08 09:46:57 +00:00
voxelranges = new List < LumpRange > ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Find ranges
FindRanges ( patchranges , General . Map . Config . PatchRanges , "patches" ) ;
FindRanges ( spriteranges , General . Map . Config . SpriteRanges , "sprites" ) ;
FindRanges ( flatranges , General . Map . Config . FlatRanges , "flats" ) ;
FindRanges ( textureranges , General . Map . Config . TextureRanges , "textures" ) ;
2009-05-12 09:50:08 +00:00
FindRanges ( colormapranges , General . Map . Config . ColormapRanges , "colormaps" ) ;
2014-01-08 09:46:57 +00:00
FindRanges ( voxelranges , General . Map . Config . VoxelRanges , "voxels" ) ;
2009-04-19 18:07:22 +00:00
2013-12-02 15:02:01 +00:00
//mxd
invertedflatranges = new List < LumpRange > ( ) ;
2014-12-03 23:15:26 +00:00
if ( flatranges . Count > 0 )
{
2014-04-09 10:16:33 +00:00
//add range before the first flatrange
2014-12-03 23:15:26 +00:00
if ( flatranges [ 0 ] . start > 0 )
{
2014-04-03 12:57:02 +00:00
LumpRange range = new LumpRange { start = 0 , end = flatranges [ 0 ] . start - 1 } ;
invertedflatranges . Add ( range ) ;
}
2013-12-02 15:02:01 +00:00
2014-04-08 11:09:05 +00:00
//add ranges between flatranges
2014-12-03 23:15:26 +00:00
for ( int i = 1 ; i < flatranges . Count ; i + + )
{
2014-04-08 11:09:05 +00:00
LumpRange range = new LumpRange { start = flatranges [ i - 1 ] . end + 1 , end = flatranges [ i ] . start - 1 } ;
invertedflatranges . Add ( range ) ;
}
2014-04-09 10:16:33 +00:00
//add range after the last flatrange
2014-12-03 23:15:26 +00:00
if ( flatranges [ flatranges . Count - 1 ] . end < file . Lumps . Count - 1 )
{
2014-04-08 11:09:05 +00:00
LumpRange range = new LumpRange { start = flatranges [ flatranges . Count - 1 ] . end + 1 , end = file . Lumps . Count - 1 } ;
2013-12-02 15:02:01 +00:00
invertedflatranges . Add ( range ) ;
}
2014-12-03 23:15:26 +00:00
}
else // No flat ranges? Make one giant range then...
{
2014-04-08 11:09:05 +00:00
LumpRange range = new LumpRange { start = 0 , end = file . Lumps . Count - 1 } ;
invertedflatranges . Add ( range ) ;
2013-12-02 15:02:01 +00:00
}
2009-04-19 18:07:22 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Disposer
public override void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
General . WriteLogLine ( "Closing WAD resource '" + location . location + "'" ) ;
// Clean up
file . Dispose ( ) ;
// Done
base . Dispose ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Management
// Return a short name for this data location
public override string GetTitle ( )
{
return Path . GetFileName ( location . location ) ;
}
// This suspends use of this resource
public override void Suspend ( )
{
file . Dispose ( ) ;
base . Suspend ( ) ;
}
// This resumes use of this resource
public override void Resume ( )
{
file = new WAD ( location . location , true ) ;
is_iwad = ( file . Type = = WAD . TYPE_IWAD ) ;
base . Resume ( ) ;
}
// This fills a ranges list
private void FindRanges ( List < LumpRange > ranges , IDictionary rangeinfos , string rangename )
{
2014-10-31 13:53:43 +00:00
Dictionary < LumpRange , KeyValuePair < string , string > > failedranges = new Dictionary < LumpRange , KeyValuePair < string , string > > ( ) ; //mxd
Dictionary < int , bool > successfulrangestarts = new Dictionary < int , bool > ( ) ; //mxd
Dictionary < int , bool > failedrangestarts = new Dictionary < int , bool > ( ) ; //mxd
2009-04-19 18:07:22 +00:00
foreach ( DictionaryEntry r in rangeinfos )
{
// Read start and end
string rangestart = General . Map . Config . ReadSetting ( rangename + "." + r . Key + ".start" , "" ) ;
string rangeend = General . Map . Config . ReadSetting ( rangename + "." + r . Key + ".end" , "" ) ;
if ( ( rangestart . Length > 0 ) & & ( rangeend . Length > 0 ) )
{
// Find ranges
int startindex = file . FindLumpIndex ( rangestart ) ;
while ( startindex > - 1 )
{
LumpRange range = new LumpRange ( ) ;
range . start = startindex ;
range . end = file . FindLumpIndex ( rangeend , startindex ) ;
if ( range . end > - 1 )
{
2014-10-31 13:53:43 +00:00
if ( ! successfulrangestarts . ContainsKey ( startindex ) ) successfulrangestarts . Add ( startindex , false ) ; //mxd
2009-04-19 18:07:22 +00:00
ranges . Add ( range ) ;
startindex = file . FindLumpIndex ( rangestart , range . end ) ;
}
else
{
2014-10-31 13:53:43 +00:00
//mxd
if ( ! failedrangestarts . ContainsKey ( startindex ) )
{
failedranges . Add ( range , new KeyValuePair < string , string > ( rangestart , rangeend ) ) ; //mxd
failedrangestarts . Add ( startindex , false ) ;
}
2009-04-19 18:07:22 +00:00
startindex = - 1 ;
}
}
}
}
2014-10-31 13:53:43 +00:00
//mxd. Display warnings for unclosed ranges
foreach ( KeyValuePair < LumpRange , KeyValuePair < string , string > > group in failedranges )
{
if ( successfulrangestarts . ContainsKey ( group . Key . start ) ) continue ;
General . ErrorLogger . Add ( ErrorType . Warning , "'" + group . Value . Key + "' range at index " + group . Key . start + " is not closed in '" + location . location + "' ('" + group . Value . Value + "' marker is missing)!" ) ;
}
2009-04-19 18:07:22 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = Palette
// This loads the PLAYPAL palette
public override Playpal LoadPalette ( )
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
// Look for a lump named PLAYPAL
2013-12-04 13:27:34 +00:00
Lump lump = file . FindLump ( "PLAYPAL" ) ;
if ( lump ! = null ) return new Playpal ( lump . Stream ) ; // Read the PLAYPAL from stream
return null ; // No palette
2009-04-19 18:07:22 +00:00
}
#endregion
2009-05-12 09:50:08 +00:00
#region = = = = = = = = = = = = = = = = = = Colormaps
// This loads the textures
public override ICollection < ImageData > LoadColormaps ( )
{
List < ImageData > images = new List < ImageData > ( ) ;
string rangestart , rangeend ;
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
// Read ranges from configuration
foreach ( DictionaryEntry r in General . Map . Config . ColormapRanges )
{
// Read start and end
rangestart = General . Map . Config . ReadSetting ( "colormaps." + r . Key + ".start" , "" ) ;
rangeend = General . Map . Config . ReadSetting ( "colormaps." + r . Key + ".end" , "" ) ;
if ( ( rangestart . Length > 0 ) & & ( rangeend . Length > 0 ) )
{
// Load texture range
LoadColormapsRange ( rangestart , rangeend , ref images ) ;
}
}
// Add images to the container-specific texture set
foreach ( ImageData img in images )
textureset . AddFlat ( img ) ;
// Return result
return images ;
}
// This loads a range of colormaps
private void LoadColormapsRange ( string startlump , string endlump , ref List < ImageData > images )
{
int startindex , endindex ;
ColormapImage image ;
// Continue until no more start can be found
startindex = file . FindLumpIndex ( startlump ) ;
while ( startindex > - 1 )
{
// Find end index
endindex = file . FindLumpIndex ( endlump , startindex + 1 ) ;
if ( endindex > - 1 )
{
// Go for all lumps between start and end exclusive
for ( int i = startindex + 1 ; i < endindex ; i + + )
{
// Lump not zero-length?
if ( file . Lumps [ i ] . Length > 0 )
{
// Make the image object
image = new ColormapImage ( file . Lumps [ i ] . Name ) ;
// Add image to collection
images . Add ( image ) ;
}
}
}
// Find the next start
startindex = file . FindLumpIndex ( startlump , startindex + 1 ) ;
}
}
// This finds and returns a colormap stream
public override Stream GetColormapData ( string pname )
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2014-01-08 09:46:57 +00:00
Lump lump ;
2009-05-13 20:54:45 +00:00
// Strictly read patches only between C_START and C_END?
if ( strictpatches )
2009-05-12 09:50:08 +00:00
{
2009-05-13 20:54:45 +00:00
// Find the lump in ranges
foreach ( LumpRange range in colormapranges )
{
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
}
}
else
{
// Find the lump anywhere
lump = file . FindLump ( pname ) ;
2009-05-12 09:50:08 +00:00
if ( lump ! = null ) return lump . Stream ;
}
return null ;
}
#endregion
2009-04-19 18:07:22 +00:00
#region = = = = = = = = = = = = = = = = = = Textures
// This loads the textures
public override ICollection < ImageData > LoadTextures ( PatchNames pnames )
{
2014-01-08 09:46:57 +00:00
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2009-04-19 18:07:22 +00:00
List < ImageData > images = new List < ImageData > ( ) ;
2014-01-08 09:46:57 +00:00
float defaultscale = General . Map . Config . DefaultTextureScale ; //mxd
2009-04-19 18:07:22 +00:00
// Load two sets of textures, if available
2015-01-15 20:48:57 +00:00
Lump lump = file . FindLump ( "TEXTURE1" ) ;
if ( lump ! = null )
{
LoadTextureSet ( "TEXTURE1" , lump . Stream , ref images , pnames ) ;
if ( images . Count > 0 ) images . RemoveAt ( 0 ) ; //mxd. The first TEXTURE1 texture cannot be used. Let's remove it here
}
2009-04-19 18:07:22 +00:00
lump = file . FindLump ( "TEXTURE2" ) ;
if ( lump ! = null ) LoadTextureSet ( "TEXTURE2" , lump . Stream , ref images , pnames ) ;
// Read ranges from configuration
foreach ( LumpRange range in textureranges )
{
2014-01-08 09:46:57 +00:00
// Go for all lumps between start and end exclusive
2014-12-03 23:15:26 +00:00
for ( int i = range . start + 1 ; i < range . end ; i + + )
{
2014-01-08 09:46:57 +00:00
// Lump not zero length?
2014-12-03 23:15:26 +00:00
if ( file . Lumps [ i ] . Length > 0 )
{
2014-01-08 09:46:57 +00:00
// Make the image
SimpleTextureImage image = new SimpleTextureImage ( file . Lumps [ i ] . Name , file . Lumps [ i ] . Name , defaultscale , defaultscale ) ;
// Add image to collection
images . Add ( image ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2014-01-08 09:46:57 +00:00
// Can't load image without size
General . ErrorLogger . Add ( ErrorType . Error , "Can't load texture '" + file . Lumps [ i ] . Name + "' because it doesn't contain any data." ) ;
}
}
2009-04-19 18:07:22 +00:00
}
2010-08-13 15:19:51 +00:00
2009-04-19 18:07:22 +00:00
// Load TEXTURES lump file
2015-01-15 20:48:57 +00:00
int lumpindex = file . FindLumpIndex ( "TEXTURES" ) ;
2010-08-13 15:19:51 +00:00
while ( lumpindex > - 1 )
2009-04-19 18:07:22 +00:00
{
2010-08-13 15:19:51 +00:00
MemoryStream filedata = new MemoryStream ( file . Lumps [ lumpindex ] . Stream . ReadAllBytes ( ) ) ;
2009-04-19 18:07:22 +00:00
WADReader . LoadHighresTextures ( filedata , "TEXTURES" , ref images , null , null ) ;
filedata . Dispose ( ) ;
2010-08-13 15:19:51 +00:00
// Find next
lumpindex = file . FindLumpIndex ( "TEXTURES" , lumpindex + 1 ) ;
2009-04-19 18:07:22 +00:00
}
2010-08-13 15:19:51 +00:00
2009-04-19 18:07:22 +00:00
// Add images to the container-specific texture set
2015-01-15 20:48:57 +00:00
foreach ( ImageData img in images ) textureset . AddTexture ( img ) ;
2009-04-19 18:07:22 +00:00
// Return result
return images ;
}
// This loads the texture definitions from a TEXTURES lump
public static void LoadHighresTextures ( Stream stream , string filename , ref List < ImageData > images , Dictionary < long , ImageData > textures , Dictionary < long , ImageData > flats )
{
// Parse the data
TexturesParser parser = new TexturesParser ( ) ;
parser . Parse ( stream , filename ) ;
// Make the textures
foreach ( TextureStructure t in parser . Textures )
{
if ( t . Name . Length > 0 )
{
// Add the texture
2014-02-26 14:11:06 +00:00
ImageData img = t . MakeImage ( ) ;
2009-04-19 18:07:22 +00:00
images . Add ( img ) ;
}
else
{
// Can't load image without name
2009-05-10 16:02:08 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Can't load an unnamed texture from \"" + filename + "\". Please consider giving names to your resources." ) ;
2009-04-19 18:07:22 +00:00
}
}
}
// This loads a set of textures
public static void LoadTextureSet ( string sourcename , Stream texturedata , ref List < ImageData > images , PatchNames pnames )
{
BinaryReader reader = new BinaryReader ( texturedata ) ;
int flags , width , height , patches , px , py , pi ;
uint numtextures ;
byte scalebytex , scalebytey ;
float scalex , scaley , defaultscale ;
byte [ ] namebytes ;
TextureImage image = null ;
bool strifedata ;
2013-12-03 10:50:33 +00:00
if ( texturedata . Length = = 0 ) return ;
2010-08-14 15:44:47 +00:00
2009-04-19 18:07:22 +00:00
// Determine default scale
defaultscale = General . Map . Config . DefaultTextureScale ;
// Get number of textures
texturedata . Seek ( 0 , SeekOrigin . Begin ) ;
numtextures = reader . ReadUInt32 ( ) ;
// Skip offset bytes (we will read all textures sequentially)
texturedata . Seek ( 4 * numtextures , SeekOrigin . Current ) ;
// Go for all textures defined in this lump
for ( uint i = 0 ; i < numtextures ; i + + )
{
// Read texture properties
namebytes = reader . ReadBytes ( 8 ) ;
flags = reader . ReadUInt16 ( ) ;
scalebytex = reader . ReadByte ( ) ;
scalebytey = reader . ReadByte ( ) ;
width = reader . ReadInt16 ( ) ;
height = reader . ReadInt16 ( ) ;
patches = reader . ReadInt16 ( ) ;
// Check for doom or strife data format
if ( patches = = 0 )
{
// Ignore 2 bytes and then read number of patches
texturedata . Seek ( 2 , SeekOrigin . Current ) ;
patches = reader . ReadInt16 ( ) ;
strifedata = false ;
}
else
{
// Texture data is in strife format
strifedata = true ;
}
// Determine actual scales
2013-12-02 15:02:01 +00:00
if ( scalebytex = = 0 ) scalex = defaultscale ; else scalex = 1f / ( scalebytex / 8f ) ;
if ( scalebytey = = 0 ) scaley = defaultscale ; else scaley = 1f / ( scalebytey / 8f ) ;
2009-04-19 18:07:22 +00:00
// Validate data
if ( ( width > 0 ) & & ( height > 0 ) & & ( patches > 0 ) & &
( scalex ! = 0 ) | | ( scaley ! = 0 ) )
{
string texname = Lump . MakeNormalName ( namebytes , WAD . ENCODING ) ;
if ( texname . Length > 0 )
{
// Make the image object
image = new TextureImage ( Lump . MakeNormalName ( namebytes , WAD . ENCODING ) ,
width , height , scalex , scaley ) ;
}
else
{
// Can't load image without name
2009-05-10 16:02:08 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Can't load an unnamed texture from \"" + sourcename + "\". Please consider giving names to your resources." ) ;
2009-04-19 18:07:22 +00:00
}
// Go for all patches in texture
for ( int p = 0 ; p < patches ; p + + )
{
// Read patch properties
px = reader . ReadInt16 ( ) ;
py = reader . ReadInt16 ( ) ;
pi = reader . ReadUInt16 ( ) ;
if ( ! strifedata ) texturedata . Seek ( 4 , SeekOrigin . Current ) ;
// Validate data
if ( ( pi > = 0 ) & & ( pi < pnames . Length ) )
{
if ( pnames [ pi ] . Length > 0 )
{
// Create patch on image
if ( image ! = null ) image . AddPatch ( new TexturePatch ( pnames [ pi ] , px , py ) ) ;
}
else
{
// Can't load image without name
2009-05-10 16:02:08 +00:00
General . ErrorLogger . Add ( ErrorType . Error , "Can't use an unnamed patch referenced in \"" + sourcename + "\". Please consider giving names to your resources." ) ;
2009-04-19 18:07:22 +00:00
}
}
}
// Add image to collection
images . Add ( image ) ;
}
else
{
// Skip patches data
texturedata . Seek ( 6 * patches , SeekOrigin . Current ) ;
if ( ! strifedata ) texturedata . Seek ( 4 * patches , SeekOrigin . Current ) ;
}
}
}
// This returns the patch names from the PNAMES lump
public override PatchNames LoadPatchNames ( )
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
// Look for a lump named PNAMES
2013-12-04 13:27:34 +00:00
Lump lump = file . FindLump ( "PNAMES" ) ;
if ( lump ! = null ) return new PatchNames ( lump . Stream ) ; // Read the PNAMES from stream
return null ; // No patch names found
2009-04-19 18:07:22 +00:00
}
// This finds and returns a patch stream
2014-11-25 11:52:01 +00:00
public override Stream GetPatchData ( string pname , bool longname )
2009-04-19 18:07:22 +00:00
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2014-11-25 11:52:01 +00:00
if ( longname ) return null ; //mxd
Lump lump ;
2009-04-19 18:07:22 +00:00
2013-12-02 15:02:01 +00:00
// mxd. First strictly read patches between P_START and P_END
2014-11-25 11:52:01 +00:00
foreach ( LumpRange range in patchranges )
{
2013-12-02 15:02:01 +00:00
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
}
2014-11-25 11:52:01 +00:00
if ( ! strictpatches )
{
2013-12-02 15:02:01 +00:00
//mxd. Find the lump anywhere EXCEPT flat ranges (the way it's done in ZDoom)
2014-11-25 11:52:01 +00:00
foreach ( LumpRange range in invertedflatranges )
{
2009-04-19 18:07:22 +00:00
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
}
2013-12-02 15:02:01 +00:00
// Find the lump anywhere IN flat ranges
2014-11-25 11:52:01 +00:00
foreach ( LumpRange range in flatranges )
{
2013-12-02 15:02:01 +00:00
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
2013-09-11 09:47:53 +00:00
}
2009-04-19 18:07:22 +00:00
}
return null ;
}
// This finds and returns a texture stream
2014-11-25 11:52:01 +00:00
public override Stream GetTextureData ( string pname , bool longname )
2009-04-19 18:07:22 +00:00
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2014-11-25 11:52:01 +00:00
if ( longname ) return null ; //mxd
Lump lump ;
2009-04-19 18:07:22 +00:00
// Find the lump in ranges
foreach ( LumpRange range in textureranges )
{
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
}
return null ;
}
2009-05-12 09:50:08 +00:00
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Flats
2014-01-08 09:46:57 +00:00
//mxd. This loads the flats
2014-11-25 11:52:01 +00:00
public override ICollection < ImageData > LoadFlats ( )
{
2009-04-19 18:07:22 +00:00
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2014-01-08 09:46:57 +00:00
List < ImageData > images = new List < ImageData > ( ) ;
FlatImage image ;
2014-11-25 11:52:01 +00:00
foreach ( LumpRange range in flatranges )
{
2014-01-08 09:46:57 +00:00
if ( range . end < range . start + 2 ) continue ;
2014-11-25 11:52:01 +00:00
for ( int i = range . start + 1 ; i < range . end ; i + + )
{
2014-01-08 09:46:57 +00:00
// Lump not zero-length?
2014-11-25 11:52:01 +00:00
if ( file . Lumps [ i ] . Length > 0 )
{
2014-01-08 09:46:57 +00:00
// Make the image object
image = new FlatImage ( file . Lumps [ i ] . Name ) ;
// Add image to collection
images . Add ( image ) ;
}
2009-04-19 18:07:22 +00:00
}
}
2010-08-18 05:49:15 +00:00
// Load TEXTURES lump file
2014-01-08 09:46:57 +00:00
int lumpindex = file . FindLumpIndex ( "TEXTURES" ) ;
2014-11-25 11:52:01 +00:00
while ( lumpindex > - 1 )
{
2010-08-18 05:49:15 +00:00
MemoryStream filedata = new MemoryStream ( file . Lumps [ lumpindex ] . Stream . ReadAllBytes ( ) ) ;
WADReader . LoadHighresFlats ( filedata , "TEXTURES" , ref images , null , null ) ;
filedata . Dispose ( ) ;
// Find next
lumpindex = file . FindLumpIndex ( "TEXTURES" , lumpindex + 1 ) ;
}
2014-01-08 09:46:57 +00:00
2009-04-19 18:07:22 +00:00
// Add images to the container-specific texture set
2014-01-08 09:46:57 +00:00
foreach ( ImageData img in images ) textureset . AddFlat ( img ) ;
2009-04-19 18:07:22 +00:00
// Return result
return images ;
}
2010-08-18 05:49:15 +00:00
// This loads the flat definitions from a TEXTURES lump
public static void LoadHighresFlats ( Stream stream , string filename , ref List < ImageData > images , Dictionary < long , ImageData > textures , Dictionary < long , ImageData > flats )
{
// Parse the data
TexturesParser parser = new TexturesParser ( ) ;
parser . Parse ( stream , filename ) ;
// Make the textures
foreach ( TextureStructure t in parser . Flats )
{
if ( t . Name . Length > 0 )
{
// Add the texture
2014-02-26 14:11:06 +00:00
ImageData img = t . MakeImage ( ) ;
2010-08-18 05:49:15 +00:00
images . Add ( img ) ;
}
else
{
// Can't load image without name
General . ErrorLogger . Add ( ErrorType . Error , "Can't load an unnamed flat from \"" + filename + "\". Please consider giving names to your resources." ) ;
}
}
}
2009-04-19 18:07:22 +00:00
// This finds and returns a patch stream
2014-11-25 11:52:01 +00:00
public override Stream GetFlatData ( string pname , bool longname )
2009-04-19 18:07:22 +00:00
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2014-11-25 11:52:01 +00:00
if ( longname ) return null ; //mxd
2014-01-08 09:46:57 +00:00
Lump lump ;
2009-04-19 18:07:22 +00:00
// Find the lump in ranges
foreach ( LumpRange range in flatranges )
{
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
}
return null ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Sprite
2010-08-18 09:07:54 +00:00
// This loads the textures
public override ICollection < ImageData > LoadSprites ( )
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2014-01-08 09:46:57 +00:00
List < ImageData > images = new List < ImageData > ( ) ;
2010-08-18 09:07:54 +00:00
// Load TEXTURES lump file
2014-01-08 09:46:57 +00:00
int lumpindex = file . FindLumpIndex ( "TEXTURES" ) ;
2010-08-18 09:07:54 +00:00
while ( lumpindex > - 1 )
{
MemoryStream filedata = new MemoryStream ( file . Lumps [ lumpindex ] . Stream . ReadAllBytes ( ) ) ;
WADReader . LoadHighresSprites ( filedata , "TEXTURES" , ref images , null , null ) ;
filedata . Dispose ( ) ;
// Find next
lumpindex = file . FindLumpIndex ( "TEXTURES" , lumpindex + 1 ) ;
}
// Return result
return images ;
}
// This loads the sprites definitions from a TEXTURES lump
public static void LoadHighresSprites ( Stream stream , string filename , ref List < ImageData > images , Dictionary < long , ImageData > textures , Dictionary < long , ImageData > flats )
{
// Parse the data
TexturesParser parser = new TexturesParser ( ) ;
parser . Parse ( stream , filename ) ;
// Make the textures
foreach ( TextureStructure t in parser . Sprites )
{
if ( t . Name . Length > 0 )
{
// Add the sprite
2014-02-26 14:11:06 +00:00
ImageData img = t . MakeImage ( ) ;
2010-08-18 09:07:54 +00:00
images . Add ( img ) ;
}
else
{
// Can't load image without name
General . ErrorLogger . Add ( ErrorType . Error , "Can't load an unnamed sprite from \"" + filename + "\". Please consider giving names to your resources." ) ;
}
}
}
2009-04-19 18:07:22 +00:00
// This finds and returns a sprite stream
public override Stream GetSpriteData ( string pname )
{
Lump lump ;
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
// Find the lump in ranges
foreach ( LumpRange range in spriteranges )
{
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
}
return null ;
}
// This checks if the given sprite exists
public override bool GetSpriteExists ( string pname )
{
Lump lump ;
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
// Find the lump in ranges
foreach ( LumpRange range in spriteranges )
{
lump = file . FindLump ( pname , range . start , range . end ) ;
if ( lump ! = null ) return true ;
}
return false ;
}
#endregion
2014-01-08 09:46:57 +00:00
#region = = = = = = = = = = = = = = = = = = Voxels ( mxd )
//mxd. This returns the list of voxels, which can be used without VOXELDEF definition
2014-12-03 23:15:26 +00:00
public override string [ ] GetVoxelNames ( )
{
2014-01-08 09:46:57 +00:00
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
List < string > voxels = new List < string > ( ) ;
Regex spriteName = new Regex ( SPRITE_NAME_PATTERN ) ;
2014-12-03 23:15:26 +00:00
foreach ( LumpRange range in voxelranges )
{
2014-01-08 09:46:57 +00:00
if ( range . start = = range . end ) continue ;
2014-12-03 23:15:26 +00:00
for ( int i = range . start + 1 ; i < range . end ; i + + )
{
2014-01-08 09:46:57 +00:00
if ( spriteName . IsMatch ( file . Lumps [ i ] . Name ) ) voxels . Add ( file . Lumps [ i ] . Name ) ;
}
}
return voxels . ToArray ( ) ;
}
//mxd
2014-12-03 23:15:26 +00:00
public override KeyValuePair < string , Stream > GetVoxeldefData ( )
{
2014-01-08 09:46:57 +00:00
Lump lump = file . FindLump ( "VOXELDEF" ) ;
if ( lump ! = null ) return new KeyValuePair < string , Stream > ( "VOXELDEF" , lump . Stream ) ;
return new KeyValuePair < string , Stream > ( ) ;
}
//mxd. This finds and returns a voxel stream or null if no voxel was found
2014-12-03 23:15:26 +00:00
public override Stream GetVoxelData ( string name )
{
2014-01-08 09:46:57 +00:00
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
Lump lump ;
2014-12-03 23:15:26 +00:00
foreach ( LumpRange range in voxelranges )
{
2014-01-08 09:46:57 +00:00
if ( range . start = = range . end ) continue ;
lump = file . FindLump ( name , range . start , range . end ) ;
if ( lump ! = null ) return lump . Stream ;
}
return null ;
}
#endregion
2012-07-23 21:28:23 +00:00
#region = = = = = = = = = = = = = = = = = = Decorate , Gldefs , Mapinfo , etc . . .
2009-04-19 18:07:22 +00:00
// This finds and returns a sprite stream
2014-10-23 12:48:31 +00:00
public override Dictionary < string , Stream > GetDecorateData ( string pname )
2009-04-19 18:07:22 +00:00
{
// Error when suspended
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2014-02-26 14:11:06 +00:00
2014-10-23 12:48:31 +00:00
Dictionary < string , Stream > result = new Dictionary < string , Stream > ( ) ;
2014-02-26 14:11:06 +00:00
2010-08-12 10:03:29 +00:00
// Find all lumps named 'DECORATE'
2014-02-26 14:11:06 +00:00
int lumpindex = file . FindLumpIndex ( pname ) ;
2010-08-12 10:03:29 +00:00
while ( lumpindex > - 1 )
{
2014-10-26 20:11:07 +00:00
//mxd. Since we are using Dictionary, all names should be unique
result . Add ( Path . Combine ( file . Filename , pname + "#" + lumpindex ) , file . Lumps [ lumpindex ] . Stream ) ;
2010-08-12 10:03:29 +00:00
// Find next
lumpindex = file . FindLumpIndex ( pname , lumpindex + 1 ) ;
}
2014-10-23 12:48:31 +00:00
return result ;
2009-04-19 18:07:22 +00:00
}
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2014-12-03 23:15:26 +00:00
public override Dictionary < string , Stream > GetMapinfoData ( )
{
2013-09-11 09:47:53 +00:00
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2012-06-01 10:17:47 +00:00
2014-02-26 14:11:06 +00:00
Dictionary < string , Stream > streams = new Dictionary < string , Stream > ( StringComparer . Ordinal ) ;
2013-09-11 09:47:53 +00:00
string src = "ZMAPINFO" ;
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//should be only one entry per wad
//first look for ZMAPINFO
2014-02-26 14:11:06 +00:00
int lumpindex = file . FindLumpIndex ( src ) ;
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//then for MAPINFO
2014-12-03 23:15:26 +00:00
if ( lumpindex = = - 1 )
{
2013-09-11 09:47:53 +00:00
src = "MAPINFO" ;
lumpindex = file . FindLumpIndex ( src ) ;
}
2012-06-01 10:17:47 +00:00
2014-12-03 23:15:26 +00:00
if ( lumpindex ! = - 1 ) streams . Add ( src , file . Lumps [ lumpindex ] . Stream ) ;
2013-09-11 09:47:53 +00:00
return streams ;
}
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2014-12-03 23:15:26 +00:00
public override Dictionary < string , Stream > GetGldefsData ( GameType gameType )
{
2013-09-11 09:47:53 +00:00
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2012-06-01 10:17:47 +00:00
2014-02-26 14:11:06 +00:00
Dictionary < string , Stream > streams = new Dictionary < string , Stream > ( StringComparer . Ordinal ) ;
2013-09-11 09:47:53 +00:00
int lumpindex ;
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//try to load game specific GLDEFS first
2014-12-03 23:15:26 +00:00
if ( gameType ! = GameType . UNKNOWN )
{
2013-09-11 09:47:53 +00:00
string lumpName = Gldefs . GLDEFS_LUMPS_PER_GAME [ ( int ) gameType ] ;
lumpindex = file . FindLumpIndex ( lumpName ) ;
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
if ( lumpindex ! = - 1 )
streams . Add ( lumpName , file . Lumps [ lumpindex ] . Stream ) ;
}
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//should be only one entry per wad
lumpindex = file . FindLumpIndex ( "GLDEFS" ) ;
2014-12-03 23:15:26 +00:00
if ( lumpindex ! = - 1 ) streams . Add ( "GLDEFS" , file . Lumps [ lumpindex ] . Stream ) ;
2013-09-11 09:47:53 +00:00
return streams ;
}
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2014-12-03 23:15:26 +00:00
public override Dictionary < string , Stream > GetGldefsData ( string location )
{
2013-09-11 09:47:53 +00:00
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
2012-06-01 10:17:47 +00:00
2014-02-26 14:11:06 +00:00
Dictionary < string , Stream > streams = new Dictionary < string , Stream > ( StringComparer . Ordinal ) ;
int lumpindex = file . FindLumpIndex ( location ) ;
2013-09-11 09:47:53 +00:00
2014-12-03 23:15:26 +00:00
if ( lumpindex ! = - 1 ) streams . Add ( location , file . Lumps [ lumpindex ] . Stream ) ;
2013-09-11 09:47:53 +00:00
return streams ;
}
2012-06-01 10:17:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2014-12-03 23:15:26 +00:00
public override Dictionary < string , Stream > GetModeldefData ( )
{
2013-09-11 09:47:53 +00:00
return GetGldefsData ( "MODELDEF" ) ;
}
2013-03-18 13:52:27 +00:00
2015-01-25 23:22:42 +00:00
//mxd
public override Dictionary < string , Stream > GetReverbsData ( )
{
if ( issuspended ) throw new Exception ( "Data reader is suspended" ) ;
Dictionary < string , Stream > result = new Dictionary < string , Stream > ( ) ;
Lump lump = file . FindLump ( "REVERBS" ) ;
if ( lump ! = null ) result . Add ( Path . Combine ( location . location , "REVERBS" ) , lump . Stream ) ;
return result ;
}
2013-09-11 09:47:53 +00:00
//mxd
2014-12-03 23:15:26 +00:00
internal override MemoryStream LoadFile ( string name )
{
2013-09-11 09:47:53 +00:00
Lump l = file . FindLump ( name ) ;
2013-03-18 13:52:27 +00:00
2014-12-03 23:15:26 +00:00
if ( l ! = null )
{
2013-09-11 09:47:53 +00:00
l . Stream . Seek ( 0 , SeekOrigin . Begin ) ;
return new MemoryStream ( l . Stream . ReadAllBytes ( ) ) ;
}
2013-03-18 13:52:27 +00:00
2013-09-11 09:47:53 +00:00
return null ;
}
2012-07-23 21:28:23 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2014-12-03 23:15:26 +00:00
internal override bool FileExists ( string name )
{
2013-08-05 13:03:08 +00:00
return file . FindLumpIndex ( name ) ! = - 1 ;
2013-09-11 09:47:53 +00:00
}
2012-07-23 21:28:23 +00:00
2009-04-19 18:07:22 +00:00
#endregion
}
}