diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tier2/riff.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'tier2/riff.cpp')
| -rw-r--r-- | tier2/riff.cpp | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/tier2/riff.cpp b/tier2/riff.cpp new file mode 100644 index 0000000..9e36021 --- /dev/null +++ b/tier2/riff.cpp @@ -0,0 +1,506 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// Avoid these warnings: +#pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated +#pragma warning(disable : 4514) // warning C4514: 'RIFFName' : unreferenced inline function has been removed + +#include "riff.h" +#include <stdio.h> +#include <string.h> +#include "tier0/dbg.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#if 0 +//----------------------------------------------------------------------------- +// Purpose: Test code that implements the interface on stdio +//----------------------------------------------------------------------------- +class StdIOReadBinary : public IFileReadBinary +{ +public: + int open( const char *pFileName ) + { + return (int)fopen( pFileName, "rb" ); + } + + int read( void *pOutput, int size, int file ) + { + FILE *fp = (FILE *)file; + + return fread( pOutput, size, 1, fp ); + } + + void seek( int file, int pos ) + { + fseek( (FILE *)file, pos, SEEK_SET ); + } + + unsigned int tell( int file ) + { + return ftell( (FILE *)file ); + } + + unsigned int size( int file ) + { + FILE *fp = (FILE *)file; + if ( !fp ) + return 0; + + unsigned int pos = ftell( fp ); + fseek( fp, 0, SEEK_END ); + unsigned int size = ftell( fp ); + + fseek( fp, pos, SEEK_SET ); + return size; + } + + void close( int file ) + { + FILE *fp = (FILE *)file; + + fclose( fp ); + } +}; +#endif + + +#define RIFF_ID MAKEID('R','I','F','F') + + +//----------------------------------------------------------------------------- +// Purpose: Opens a RIFF file using the given I/O mechanism +// Input : *pFileName +// &io - I/O interface +//----------------------------------------------------------------------------- +InFileRIFF::InFileRIFF( const char *pFileName, IFileReadBinary &io ) : m_io(io) +{ + m_file = m_io.open( pFileName ); + + int riff = 0; + if ( !m_file ) + { + m_riffSize = 0; + m_riffName = 0; + return; + } + + riff = ReadInt(); + if ( riff != RIFF_ID ) + { + printf( "Not a RIFF File [%s]\n", pFileName ); + m_riffSize = 0; + } + else + { + // we store size as size of all chunks + // subtract off the RIFF form type (e.g. 'WAVE', 4 bytes) + m_riffSize = ReadInt() - 4; + m_riffName = ReadInt(); + + // HACKHACK: LWV files don't obey the RIFF format!!! + // Do this or miss the linguistic chunks at the end. Lame! + // subtract off 12 bytes for (RIFF, size, WAVE) + m_riffSize = m_io.size( m_file ) - 12; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Close the file +//----------------------------------------------------------------------------- +InFileRIFF::~InFileRIFF( void ) +{ + m_io.close( m_file ); +} + + +//----------------------------------------------------------------------------- +// Purpose: read a 4-byte int out of the stream +// Output : int = read value, default is zero +//----------------------------------------------------------------------------- +int InFileRIFF::ReadInt( void ) +{ + int tmp = 0; + m_io.read( &tmp, sizeof(int), m_file ); + tmp = LittleLong( tmp ); + + return tmp; +} + +//----------------------------------------------------------------------------- +// Purpose: Read a block of binary data +// Input : *pOutput - pointer to destination memory +// dataSize - size of block to read +// Output : int - number of bytes read +//----------------------------------------------------------------------------- +int InFileRIFF::ReadData( void *pOutput, int dataSize ) +{ + int count = m_io.read( pOutput, dataSize, m_file ); + + return count; +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the file position +// Output : int (bytes from start of file) +//----------------------------------------------------------------------------- +int InFileRIFF::PositionGet( void ) +{ + return m_io.tell( m_file ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Seek to file position +// Input : position - bytes from start of file +//----------------------------------------------------------------------------- +void InFileRIFF::PositionSet( int position ) +{ + m_io.seek( m_file, position ); +} + +//----------------------------------------------------------------------------- +// Purpose: Used to write a RIFF format file +//----------------------------------------------------------------------------- +OutFileRIFF::OutFileRIFF( const char *pFileName, IFileWriteBinary &io ) : m_io( io ) +{ + m_file = m_io.create( pFileName ); + + if ( !m_file ) + return; + + int riff = RIFF_ID; + m_io.write( &riff, 4, m_file ); + + m_riffSize = 0; + m_nNamePos = m_io.tell( m_file ); + + // Save room for the size and name now + WriteInt( 0 ); + + // Write out the name + WriteInt( RIFF_WAVE ); + + m_bUseIncorrectLISETLength = false; + m_nLISETSize = 0; +} + +OutFileRIFF::~OutFileRIFF( void ) +{ + if ( !IsValid() ) + return; + + unsigned int size = m_io.tell( m_file ) -8; + m_io.seek( m_file, m_nNamePos ); + + if ( m_bUseIncorrectLISETLength ) + { + size = m_nLISETSize - 8; + } + + WriteInt( size ); + m_io.close( m_file ); +} + +void OutFileRIFF::HasLISETData( int position ) +{ + m_bUseIncorrectLISETLength = true; + m_nLISETSize = position; +} + +bool OutFileRIFF::WriteInt( int number ) +{ + if ( !IsValid() ) + return false; + + m_io.write( &number, sizeof( int ), m_file ); + return true; +} + +bool OutFileRIFF::WriteData( void *pOutput, int dataSize ) +{ + if ( !IsValid() ) + return false; + + m_io.write( pOutput, dataSize, m_file ); + return true; +} + +int OutFileRIFF::PositionGet( void ) +{ + if ( !IsValid() ) + return 0; + + return m_io.tell( m_file ); +} + +void OutFileRIFF::PositionSet( int position ) +{ + if ( !IsValid() ) + return; + + m_io.seek( m_file, position ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Create an iterator for the given file +// Input : &riff - riff file +// size - size of file or sub-chunk +//----------------------------------------------------------------------------- +IterateRIFF::IterateRIFF( InFileRIFF &riff, int size ) + : m_riff(riff), m_size(size) +{ + if ( !m_riff.RIFFSize() ) + { + // bad file, just be an empty iterator + ChunkClear(); + return; + } + + // get the position and parse a chunk + m_start = riff.PositionGet(); + ChunkSetup(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Set up a sub-chunk iterator +// Input : &parent - parent iterator +//----------------------------------------------------------------------------- +IterateRIFF::IterateRIFF( IterateRIFF &parent ) + : m_riff(parent.m_riff), m_size(parent.ChunkSize()) +{ + m_start = parent.ChunkFilePosition(); + ChunkSetup(); +} + +//----------------------------------------------------------------------------- +// Purpose: Parse the chunk at the current file position +// This object will iterate over the sub-chunks of this chunk. +// This makes for easy hierarchical parsing +//----------------------------------------------------------------------------- +void IterateRIFF::ChunkSetup( void ) +{ + m_chunkPosition = m_riff.PositionGet(); + + m_chunkName = m_riff.ReadInt(); + m_chunkSize = m_riff.ReadInt(); +} + +//----------------------------------------------------------------------------- +// Purpose: clear chunk setup, ChunkAvailable will return false +//----------------------------------------------------------------------------- +void IterateRIFF::ChunkClear( void ) +{ + m_chunkSize = -1; +} + +//----------------------------------------------------------------------------- +// Purpose: If there are chunks left to read beyond this one, return true +//----------------------------------------------------------------------------- +bool IterateRIFF::ChunkAvailable( void ) +{ + if ( m_chunkSize != -1 && m_chunkSize < 0x10000000 ) + return true; + + return false; +} + + +//----------------------------------------------------------------------------- +// Purpose: Go to the next chunk in the file, return true if there is one. +//----------------------------------------------------------------------------- +bool IterateRIFF::ChunkNext( void ) +{ + if ( !ChunkAvailable() ) + return false; + + int nextPos = m_chunkPosition + 8 + m_chunkSize; + + // chunks are aligned + nextPos += m_chunkSize & 1; + + if ( nextPos >= (m_start + m_size) ) + { + ChunkClear(); + return false; + } + + m_riff.PositionSet( nextPos ); + + ChunkSetup(); + return ChunkAvailable(); + +} + + +//----------------------------------------------------------------------------- +// Purpose: get the chunk FOURCC as an int +// Output : unsigned int +//----------------------------------------------------------------------------- +unsigned int IterateRIFF::ChunkName( void ) +{ + return m_chunkName; +} + + +//----------------------------------------------------------------------------- +// Purpose: get the size of this chunk +// Output : unsigned int +//----------------------------------------------------------------------------- +unsigned int IterateRIFF::ChunkSize( void ) +{ + return m_chunkSize; +} + +//----------------------------------------------------------------------------- +// Purpose: Read the entire chunk into a buffer +// Input : *pOutput - dest buffer +// Output : int bytes read +//----------------------------------------------------------------------------- +int IterateRIFF::ChunkRead( void *pOutput ) +{ + return m_riff.ReadData( pOutput, ChunkSize() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Read a partial chunk (updates file position for subsequent partial reads). +// Input : *pOutput - dest buffer +// dataSize - partial size +// Output : int - bytes read +//----------------------------------------------------------------------------- +int IterateRIFF::ChunkReadPartial( void *pOutput, int dataSize ) +{ + return m_riff.ReadData( pOutput, dataSize ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Read a 4-byte int +// Output : int - read int +//----------------------------------------------------------------------------- +int IterateRIFF::ChunkReadInt( void ) +{ + return m_riff.ReadInt(); +} + +//----------------------------------------------------------------------------- +// Purpose: Used to iterate over an InFileRIFF +//----------------------------------------------------------------------------- +IterateOutputRIFF::IterateOutputRIFF( OutFileRIFF &riff ) +: m_riff( riff ) +{ + if ( !m_riff.IsValid() ) + return; + + m_start = m_riff.PositionGet(); + m_chunkPosition = m_start; + m_chunkStart = -1; +} + +IterateOutputRIFF::IterateOutputRIFF( IterateOutputRIFF &parent ) + : m_riff(parent.m_riff) +{ + m_start = parent.ChunkFilePosition(); + m_chunkPosition = m_start; + m_chunkStart = -1; +} + +void IterateOutputRIFF::ChunkWrite( unsigned int chunkname, void *pOutput, int size ) +{ + m_chunkPosition = m_riff.PositionGet(); + + m_chunkName = chunkname; + m_chunkSize = size; + + m_riff.WriteInt( chunkname ); + m_riff.WriteInt( size ); + m_riff.WriteData( pOutput, size ); + + m_chunkPosition = m_riff.PositionGet(); + + m_chunkPosition += m_chunkPosition & 1; + + m_riff.PositionSet( m_chunkPosition ); + + m_chunkStart = -1; +} + +void IterateOutputRIFF::ChunkWriteInt( int number ) +{ + m_riff.WriteInt( number ); +} + +void IterateOutputRIFF::ChunkWriteData( void *pOutput, int size ) +{ + m_riff.WriteData( pOutput, size ); +} + +void IterateOutputRIFF::ChunkFinish( void ) +{ + Assert( m_chunkStart != -1 ); + + m_chunkPosition = m_riff.PositionGet(); + + int size = m_chunkPosition - m_chunkStart - 8; + + m_chunkPosition += m_chunkPosition & 1; + + m_riff.PositionSet( m_chunkStart + sizeof( int ) ); + + m_riff.WriteInt( size ); + + m_riff.PositionSet( m_chunkPosition ); + + m_chunkStart = -1; +} + +void IterateOutputRIFF::ChunkStart( unsigned int chunkname ) +{ + Assert( m_chunkStart == -1 ); + + m_chunkStart = m_riff.PositionGet(); + + m_riff.WriteInt( chunkname ); + m_riff.WriteInt( 0 ); +} + +void IterateOutputRIFF::ChunkSetPosition( int position ) +{ + m_riff.PositionSet( position ); +} + +unsigned int IterateOutputRIFF::ChunkGetPosition( void ) +{ + return m_riff.PositionGet(); +} + +void IterateOutputRIFF::CopyChunkData( IterateRIFF& input ) +{ + if ( input.ChunkSize() > 0 ) + { + char *buffer = new char[ input.ChunkSize() ]; + Assert( buffer ); + + input.ChunkRead( buffer ); + + // Don't copy/write the name or size, just the data itself + ChunkWriteData( buffer, input.ChunkSize() ); + + delete[] buffer; + } +} + +void IterateOutputRIFF::SetLISETData( int position ) +{ + m_riff.HasLISETData( position ); +}
\ No newline at end of file |