Beispiel #1
0
void Serialize<Deserializer>(Deserializer& ar, Animation& data, unsigned int version) {
  const ChunkHeader knspHeader = ReadChunkHeader(ar);
  if (knspHeader.id != MakeId('K','N','S','P')) {
    ar.Rewind(chunkHeaderSize);
    return;
  }
  int major;
  ar(major, 1);
  int minor;
  ar(minor, 1);
  data.version = major * 0x100 + minor;
  ar.Skip(knspHeader.size - 2);

  for (;!ar.IsEof();) {
    const ChunkHeader header = ReadChunkHeader(ar);
    switch(header.id) {
    case MakeId('P','I','C','T'):
      data.textureName.resize(header.size);
      ar(&data.textureName[0], header.size); 
      break;
    case MakeId('A','N','I','M'): {
      size_t count;
      ar(count, 4);
      data.sheetList.resize(count);
      for (auto i : data.sheetList) {
        Serialize(ar, i, version);
      }
      break;
    }
    default:
      ar.Skip(header.size);
      break;
    }
  }
}
Beispiel #2
0
// For reading the face-data chunk
static bool ReadFaceData(OpenedFile& OFile, int32 ParentChunkEnd)
{
	uint8 NFBuffer[2];
	uint16 NumFaces;
	if (!OFile.Read(2,NFBuffer))
	{
		logError1("ERROR reading number of faces in %s",Path);
		return false;
	}
	uint8 *S = NFBuffer;
	StreamToValue(S,NumFaces);
	
	int32 DataSize = 4*sizeof(uint16)*int(NumFaces);
	SetChunkBufferSize(DataSize);
	if (!OFile.Read(DataSize,ChunkBufferBase()))
	{
		logError1("ERROR reading face-chunk contents in %s",Path);
		return false;
	}
	
	S = ChunkBufferBase();
	ModelPtr->VertIndices.resize(3*NumFaces);
	for (int k=0; k<NumFaces; k++)
	{
		uint16 *CurrPoly = ModelPtr->VIBase() + 3*k;
		uint16 Flags;
		StreamToList(S,CurrPoly,3);
		StreamToValue(S,Flags);
	}
	
	int32 Location = 0;
	OFile.GetPosition(Location);
	
	while(Location < ParentChunkEnd)
	{
		ChunkHeaderData ChunkHeader;
		if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
		
		switch(ChunkHeader.ID)
		{
		/*
		case OBJECT:
			if (!ReadContainer(OFile,ChunkHeader,ReadObject)) return false;
			break;
		*/
		default:
			if (!SkipChunk(OFile,ChunkHeader)) return false;
		}
		
		// Where are we now?
		OFile.GetPosition(Location);
	}
	
	if (Location > ParentChunkEnd)
	{
		logError3("ERROR: Overran parent chunk: %d > %d in %s",Location,ParentChunkEnd,Path);
		return false;
	}
	return true;
}
Beispiel #3
0
// For reading the editor-data chunk
static bool ReadEditor(OpenedFile& OFile, int32 ParentChunkEnd)
{
	int32 Location = 0;
	OFile.GetPosition(Location);
	
	while(Location < ParentChunkEnd)
	{
		ChunkHeaderData ChunkHeader;
		if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
		
		switch(ChunkHeader.ID)
		{
		case OBJECT:
			if (!ReadContainer(OFile,ChunkHeader,ReadObject)) return false;
			break;
			
		default:
			if (!SkipChunk(OFile,ChunkHeader)) return false;
		}
		
		// Where are we now?
		OFile.GetPosition(Location);
	}
	
	if (Location > ParentChunkEnd)
	{
		logError3("ERROR: Overran parent chunk: %d > %d in %s",Location,ParentChunkEnd,Path);
		return false;
	}
	return true;
}
// For reading the master chunk (ideally, whole file)
static bool ReadMaster(OpenedFile& OFile, int32 ParentChunkEnd)
{
	int32 Location = 0;
	OFile.GetPosition(Location);
	
	while(Location < ParentChunkEnd)
	{
		ChunkHeaderData ChunkHeader;
		if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
		
		switch(ChunkHeader.ID)
		{
		case EDITOR:
			if (!ReadContainer(OFile,ChunkHeader,ReadEditor)) return false;
			break;
				
		default:
			if (!SkipChunk(OFile,ChunkHeader)) return false;
		}
		
		// Where are we now?
		OFile.GetPosition(Location);
	}
	
	if (Location > ParentChunkEnd)
	{
		if (DBOut)
			fprintf(DBOut,"ERROR: Overran parent chunk: %ld > %ld\n",Location,ParentChunkEnd);
		return false;
	}
	return true;
}
bool LoadModel_Studio(FileSpecifier& Spec, Model3D& Model)
{
	ModelPtr = &Model;
	Model.Clear();
	
	if (DBOut)
	{
		// Name buffer
		const int BufferSize = 256;
		char Buffer[BufferSize];
		Spec.GetName(Buffer);
		fprintf(DBOut,"Loading 3D Studio Max model file %s\n",Buffer);
	}
	
	OpenedFile OFile;
	if (!Spec.Open(OFile))
	{	
		if (DBOut) fprintf(DBOut,"ERROR opening the file\n");
		return false;
	}
	
	ChunkHeaderData ChunkHeader;
	if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
	if (ChunkHeader.ID != MASTER)
	{
		if (DBOut) fprintf(DBOut,"ERROR: not a 3DS Max model file\n");
		return false;
	}
	
	if (!ReadContainer(OFile,ChunkHeader,ReadMaster)) return false;
	
	return (!Model.Positions.empty() && !Model.VertIndices.empty());
}
// For reading the object-data chunk
static bool ReadObject(OpenedFile& OFile, int32 ParentChunkEnd)
{
	// Read the name
	if (DBOut) fprintf(DBOut,"Object Name: ");
	while(true)
	{
		char c;
		if (!OFile.Read(1,&c))
		{
			if (DBOut) fprintf(DBOut,"ERROR in reading name");
			return false;
		}
		
		if (c == 0)
		{
			if (DBOut) fprintf(DBOut,"\n");
			break;
		}
		else
		{
			if (DBOut) fprintf(DBOut,"%c",c);
		}
	}
	
	int32 Location = 0;
	OFile.GetPosition(Location);
	
	while(Location < ParentChunkEnd)
	{
		ChunkHeaderData ChunkHeader;
		if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
		
		switch(ChunkHeader.ID)
		{
		case TRIMESH:
			if (!ReadContainer(OFile,ChunkHeader,ReadTrimesh)) return false;
			break;
			
		default:
			if (!SkipChunk(OFile,ChunkHeader)) return false;
		}
		
		// Where are we now?
		OFile.GetPosition(Location);
	}
	
	if (Location > ParentChunkEnd)
	{
		if (DBOut)
			fprintf(DBOut,"ERROR: Overran parent chunk: %ld > %ld\n",Location,ParentChunkEnd);
		return false;
	}
	return true;
}
HRESULT CRiffParser::MoveToNextChunk()
{
    // chunk offset is always bigger than container offset,
    // and both are always non-negative.
    assert(m_llCurrentChunkOffset > m_llContainerOffset);
    assert(m_llCurrentChunkOffset >= 0);
    assert(m_llContainerOffset >= 0);

    HRESULT hr = S_OK;
    LONGLONG maxChunkSize = 0;

    // Update current chunk offset to the start of the next chunk
    m_llCurrentChunkOffset = m_llCurrentChunkOffset + ChunkActualSize();

    // Are we at the end?
    if ((m_llCurrentChunkOffset - m_llContainerOffset) >= m_dwContainerSize)
    {
        return E_FAIL;
    }

    // Current chunk offset + size of current chunk
    if (MAXLONGLONG - m_llCurrentChunkOffset <= ChunkActualSize())
    {
        return E_INVALIDARG;
    }
    
    // Seek to the start of the chunk.
    hr = m_pStream->SetCurrentPosition(m_llCurrentChunkOffset);

    // Read the header. 
    if (SUCCEEDED(hr))
    {
        hr = ReadChunkHeader();
    }
 
    // This chunk cannot be any larger than (container size - (chunk offset - container offset) )
    if (SUCCEEDED(hr))
    {
        maxChunkSize = (LONGLONG)m_dwContainerSize - (m_llCurrentChunkOffset - m_llContainerOffset);

        if (maxChunkSize < ChunkActualSize())
        {
            hr = E_INVALIDARG;
        }
    }

    if (SUCCEEDED(hr))
    {
        m_dwBytesRemaining = m_chunk.DataSize();
    }

    return hr;
}
// For reading the triangle-mesh-data chunk
static bool ReadTrimesh(OpenedFile& OFile, int32 ParentChunkEnd)
{
	int32 Location = 0;
	OFile.GetPosition(Location);
	
	assert(ModelPtr);
	
	while(Location < ParentChunkEnd)
	{
		ChunkHeaderData ChunkHeader;
		if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
		
		switch(ChunkHeader.ID)
		{
		case VERTICES:
			if (!LoadChunk(OFile,ChunkHeader)) return false;
			LoadVertices();
			break;
			
		case TXTR_COORDS:
			if (!LoadChunk(OFile,ChunkHeader)) return false;
			LoadTextureCoordinates();
			break;
			
		case FACE_DATA:
			if (!ReadContainer(OFile,ChunkHeader,ReadFaceData)) return false;
			break;
			
		default:
			if (!SkipChunk(OFile,ChunkHeader)) return false;
		}
		
		// Where are we now?
		OFile.GetPosition(Location);
	}
	
	if (Location > ParentChunkEnd)
	{
		if (DBOut)
			fprintf(DBOut,"ERROR: Overran parent chunk: %ld > %ld\n",Location,ParentChunkEnd);
		return false;
	}
	return true;
}
Beispiel #9
0
// For reading the object-data chunk
static bool ReadObject(OpenedFile& OFile, int32 ParentChunkEnd)
{
	// Read the name
	char c;
	do
	{
		if (!OFile.Read(1,&c))
		{
			logError1("ERROR when reading name in %s",Path);
			return false;
		}
	}
	while(c != 0);
	
	int32 Location = 0;
	OFile.GetPosition(Location);
	
	while(Location < ParentChunkEnd)
	{
		ChunkHeaderData ChunkHeader;
		if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
		
		switch(ChunkHeader.ID)
		{
		case TRIMESH:
			if (!ReadContainer(OFile,ChunkHeader,ReadTrimesh)) return false;
			break;
			
		default:
			if (!SkipChunk(OFile,ChunkHeader)) return false;
		}
		
		// Where are we now?
		OFile.GetPosition(Location);
	}
	
	if (Location > ParentChunkEnd)
	{
		logError3("ERROR: Overran parent chunk: %d > %d in %s",Location,ParentChunkEnd,Path);
		return false;
	}
	return true;
}
Beispiel #10
0
void Serialize<Deserializer>(Deserializer& ar, Sheet& data, unsigned int version) {
  const ChunkHeader chunk = ReadChunkHeader(ar);
  if (chunk.id != MakeId('S','H','E','E')) {
    ar.Rewind(chunkHeaderSize);
    return;
  }
  {
    size_t size;
    ar(size, 4);
    data.chipList.resize(size);
    for (auto i : data.chipList) {
      Serialize(ar, i, version);
    }
  }
  {
    size_t size;
    ar(size, 4);
    data.rectList.resize(size);
    for (auto i : data.rectList) {
      Serialize(ar, i, version);
    }
  }
}
Beispiel #11
0
bool LoadModel_Studio(FileSpecifier& Spec, Model3D& Model)
{
	ModelPtr = &Model;
	Model.Clear();
	
	Path = Spec.GetPath();
	logNote1("Loading 3D Studio Max model file %s",Path);
	
	OpenedFile OFile;
	if (!Spec.Open(OFile))
	{	
		logError1("ERROR opening %s",Path);
		return false;
	}
	
	ChunkHeaderData ChunkHeader;
	if (!ReadChunkHeader(OFile,ChunkHeader)) return false;
	if (ChunkHeader.ID != MASTER)
	{
		logError1("ERROR: not a 3DS Max model file: %s",Path);
		return false;
	}
	
	if (!ReadContainer(OFile,ChunkHeader,ReadMaster)) return false;
	
	if (Model.Positions.empty())
	{
		logError1("ERROR: no vertices found in %s",Path);
		return false;
	}
	if (Model.VertIndices.empty())
	{
		logError1("ERROR: no faces found in %s",Path);
		return false;
	}
	return true;
}
Beispiel #12
0
void CLevel::LoadNewFormat(FILE* aFile)
{
	int version = ReadInt( aFile );

	while ( !feof( aFile ) )
	{
		TChunk blockType;
		int blockLength;

		try
		{
			ReadChunkHeader( blockType, blockLength, aFile);
		}
		catch ( CEOFException& e )
		{
			LOG1("%s\n", e.what() );
			return; // file end reached
		}

		switch ( blockType )
		{
			case KLevelData:
				{
					iWidth = ReadInt( aFile );
					iHeight = ReadInt( aFile );
					iLevelData = new TBlock[iHeight*iWidth];

					for (int a=0;a<iWidth * iHeight;a++)
					{
						iLevelData[a].iType = (TBlockType)(ReadInt( aFile));
						iLevelData[a].iNumber = ReadInt( aFile );
						iLevelData[a].iHeight = ReadInt( aFile );
					}

					break;
				}
			case KPlayerStartPoints:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						int x = ReadInt( aFile );
						int y = ReadInt( aFile );
						iPlStart.push_back( CCoord<int>( x,y ) );
					}
					break;
				}
			case KSpotLights:
				{
					int amount = ReadInt( aFile );
					for (int a=0;a<amount;a++)
					{
						AddSpotLight( aFile );
					}
                    
					break;
				}
			case KSteams:
				{
					int amount = ReadInt( aFile );
					for (int a=0;a<amount;a++)
					{
						AddSteam( aFile );
					}
                    
					break;
				}
			case KGeneralLevelInfo:
				{
					// FIXME: endianness problem
					int ret = fread(&iGeneralLevelInfo,sizeof(iGeneralLevelInfo),1,aFile);
					if ( ret != 1 )
						throw CFailureException("CLevel::LoadNewFormat: KGeneralLevelInfo chunk read failed!");
					break;
				}
			case KRandomWeaponCrateAmountNormal:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						int crateAmount = ReadInt( aFile );
						iRandomCratesNormal.push_back( TRandomCrateInfo(0,a,crateAmount) );
					};
					break;
				}
			case KRandomBulletCrateAmountNormal:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						int crateAmount = ReadInt( aFile );
						iRandomCratesNormal.push_back( TRandomCrateInfo(1,a,crateAmount) );
					};
					break;

				}
			case KRandomOtherCrateAmountNormal:
				{
					int amount = ReadInt( aFile );
					ASSERT( amount == 1 );
					int crateAmount = ReadInt( aFile );
					iRandomCratesNormal.push_back( TRandomCrateInfo(2,0,crateAmount) );
					break;
				}
			case KRandomWeaponCrateAmountDM:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						int crateAmount = ReadInt( aFile );
						iRandomCratesDM.push_back( TRandomCrateInfo(0,a,crateAmount) );
					};
					break;
				}
			case KRandomBulletCrateAmountDM:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						int crateAmount = ReadInt( aFile );
						iRandomCratesDM.push_back( TRandomCrateInfo(1,a,crateAmount) );
					};
					break;
				}
			case KRandomOtherCrateAmountDM:
				{
					int amount = ReadInt( aFile );
					ASSERT( amount == 1 );
					int crateAmount = ReadInt( aFile );
					iRandomCratesDM.push_back( TRandomCrateInfo(2,0,crateAmount) );
					break;
				}
			case KPlacedCratesNormal:
				{
					int amount = ReadInt( aFile );
					
					for (int a=0;a<amount;a++)
					{
						TCrateInfo tmpCrate;
						// FIXME: endianness problem
						if (fread(&tmpCrate, sizeof(TCrateInfo), 1, aFile)!=1) 
							throw CFailureException("CLevel::LoadNewFormat: File loading error 1");

						iPlacedCratesNormal.push_back( tmpCrate );
					}
					break;
				}
			case KPlacedCratesDM:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						TCrateInfo tmpCrate;
						// FIXME: endianness problem
						if (fread(&tmpCrate, sizeof(TCrateInfo), 1, aFile)!=1) 
							throw CFailureException("CLevel::LoadNewFormat: File loading error 2");
						
						iPlacedCratesDM.push_back( tmpCrate );
					}
					break;
				}
			case KOutblockData:
				{
					iOutBlock.iNumber = ReadInt( aFile );
					iOutBlock.iType = (TBlockType)(ReadInt( aFile ));
					break;
				}
			case KPlacedEnemies:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						TEnemyCoords tmpEnemy;
						// FIXME: endianness problem
						if (fread(&tmpEnemy, sizeof(TEnemyCoords), 1, aFile)!=1) 
							throw CFailureException("CLevel::LoadNewFormat: File loading error 3");

						iEnemy.push_back( tmpEnemy );
					}
					break;
				}
			case KOutblockHeight:
				{
					iOutBlock.iHeight = ReadInt( aFile );
					break;
				}

			case KRandomCratesNormal:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						int t1,t2,amo;
						t1  = ReadInt( aFile );
						t2  = ReadInt( aFile );
						amo = ReadInt( aFile );
						iRandomCratesNormal.push_back( TRandomCrateInfo( t1, t2, amo ) );
					}
					break;
				}
			case KRandomCratesDM:
				{
					int amount = ReadInt( aFile );

					for (int a=0;a<amount;a++)
					{
						int t1,t2,amo;
						t1  = ReadInt( aFile );
						t2  = ReadInt( aFile );
						amo = ReadInt( aFile );
						iRandomCratesDM.push_back( TRandomCrateInfo( t1, t2, amo ) );
					}
					break;
				}
			case KUnknown:
				fseek( aFile, blockLength, SEEK_CUR ); // skip unknown blocktype
				break;
			default:
				throw CFailureException("CLevel::LoadNewFormat: Chunk detection failure!");
		};
	}
}
HRESULT CRiffParser::ReadRiffHeader()
{
    // Riff chunks must be WORD aligned
    if ((m_llContainerOffset % 2) != 0)
    {
        return E_INVALIDARG;
    }

    // Offset must be positive.
    if (m_llContainerOffset < 0)
    {
        return E_INVALIDARG;
    }

    // Offset + the size of header must not overflow.
    if (MAXLONGLONG - m_llContainerOffset <= sizeof(RIFFLIST))
    {
        return E_INVALIDARG;
    }

    HRESULT hr = S_OK;
    RIFFLIST header = { 0 };
    ULONG cbRead = 0;

    // Seek to the start of the container.
    hr = m_pStream->SetCurrentPosition(m_llContainerOffset);
    
    // Read the header. 
    if (SUCCEEDED(hr))
    {   
        hr = m_pStream->Read((BYTE*)&header, sizeof(header), &cbRead);
    }

    // Make sure we read the number of bytes we expected.
    if (SUCCEEDED(hr))
    {   
        if (cbRead != sizeof(header))
        {
            hr = E_INVALIDARG;
        }
    }

    // Make sure the header ID matches what the caller expected.
    if (SUCCEEDED(hr))
    {   
        if (header.fcc != m_fccID)
        {
            hr = E_INVALIDARG;
        }
    }

    if (SUCCEEDED(hr))
    {   
        // The size given in the RIFF header does not include the 8-byte header.
        // However, our m_llContainerOffset is the offset from the start of the
        // header. Therefore our container size = listed size + size of header.

        m_dwContainerSize = header.cb + sizeof(RIFFCHUNK); 
        m_fccType = header.fccListType;

        // Start of the first chunk = start of container + size of container header
        m_llCurrentChunkOffset = m_llContainerOffset + sizeof(RIFFLIST);

        hr = ReadChunkHeader();
    }

    return hr;
}
Beispiel #14
0
//-------------------------------------------------------------------------
CIwSoundData* CIwSoundWAV::Create(const CIwStringL& pathname, void* buffer, u_int file_size)
{
    IW_CALLSTACK("CIwSoundWAV::Create")

    CIwSoundData* pData = NULL; // Object to return

    // Open file
    s3eFile* pFile = NULL;
	
	if (buffer != NULL)
		pFile = s3eFileOpenFromMemory(buffer, file_size);
	else
		pFile = IwFileOpenPrefixed(pathname.c_str(), "rb");

    IwAssertMsg(SOUND, pFile, ("Could not load file %s", pathname.c_str()));
    if (!pFile)
        return NULL;

    // Read RIFF header - Gives the file size and checks that this is a WAVE
    // file as expected
    IwRIFFHeader riffHeader;
    if ((s3eFileRead(&riffHeader, sizeof(IwRIFFHeader), 1, pFile) != 1)
        || (strncmp(riffHeader.typeID, "RIFF", 4) != 0)
        || (strncmp(riffHeader.subTypeID, "WAVE", 4) != 0))
    {
        IwAssertMsg(SOUND, false, ("Invalid header in %s (RIFF Header)", pathname.c_str()));
        s3eFileClose(pFile);
        return NULL;
    }

    // Read in RIFF chunks until we reach the end of the file
    // Read the RIFF chunk header. This tells us what type of chunk follows.
    IwRIFFChunkHeader chunkHeader;
    bool readData = false;
    uint32 fileSize = s3eFileGetSize(pFile);

    while (ReadChunkHeader(chunkHeader, *(s3eFile*)pFile))
    {
        uint32 chunkStartPos = s3eFileTell(pFile);

        // Next action depends on chunk type. The order of this is important and we may fail
        // if an unexpected chunk type is found
        if (!strncmp(chunkHeader.typeID, "fmt ", 4))
        {
            // Read WAVE info chunk
            if (!ReadChunkFormat(pathname, chunkHeader, pData, *(s3eFile*)pFile))
            {
                s3eFileClose(pFile);
                return NULL;
            }
        }
        else if (!strncmp(chunkHeader.typeID, "data", 4))
        {
            if (!ReadChunkData(pathname, chunkHeader, pData, *(s3eFile*)pFile))
            {
                s3eFileClose(pFile);
                return NULL;
            }
            readData = true;
        }
        else if (!strncmp(chunkHeader.typeID, "fact", 4))
        {
            if (!ReadChunkFact(pathname, chunkHeader, pData, *(s3eFile*)pFile))
            {
                s3eFileClose(pFile);
                return NULL;
            }
        }
        else
        {
            // Unknown chunk type
            // Make a proper string from the chunk type info
            char typeID[5];
            strncpy(typeID, chunkHeader.typeID, 4);
            typeID[4] = 0;  // Terminate

            const char* g_IgnoreTypes = "LIST" //LIST is just copyright info etc.
                "DISP";  //DISP seems to be info about what package exported it

            IwAssertMsg(SOUND, strstr(g_IgnoreTypes, typeID), ("Unhandled chunk type '%s' in %s. Ignoring this data.", typeID, pathname.c_str()));
        }

        // Exit if at end of file
        if (chunkStartPos + chunkHeader.length >= fileSize)
            break;

        // Move to next chunk
        s3eFileSeek(pFile, chunkStartPos + chunkHeader.length, S3E_FILESEEK_SET);
    }

    // Check that we have read the sample data
    IwAssertMsg(SOUND, readData, ("No data chunk read in %s", pathname.c_str()));
    s3eFileClose(pFile);
    return pData;
}