Image* PVRTCDecoder::Decode(DataStream* ds) { PVRTexHeader header; if (!ds) return 0; if ( ds->Read((Byte*)&header, sizeof(header))!=sizeof(header) ) return 0; if ( header.pvrTag[0] != gPVRTexIdentifier[0] || header.pvrTag[1] != gPVRTexIdentifier[1] || header.pvrTag[2] != gPVRTexIdentifier[2] || header.pvrTag[3] != gPVRTexIdentifier[3] ) return 0; /// @todo swap bytes ordering UInt32 formatFlags = SwapLittleToHost(header.flags) & PVR_TEXTURE_FLAG_TYPE_MASK; if ( formatFlags != kPVRTextureFlagTypePVRTC_2 && formatFlags != kPVRTextureFlagTypePVRTC_4 ) { return 0; } //bool haveAlpha = SwapLittleToHost(header.bitmaskAlpha); UInt32 width = SwapLittleToHost(header.width); UInt32 height = SwapLittleToHost(header.height); UInt32 dataLength = SwapLittleToHost(header.dataLength); UInt32 blockSize = 0; UInt32 widthBlocks = 0; UInt32 heightBlocks = 0; UInt32 bpp = 0; ImageFormat format; if (formatFlags == kPVRTextureFlagTypePVRTC_4) { blockSize = 4 * 4; // Pixel by pixel block size for 4bpp widthBlocks = width / 4; heightBlocks = height / 4; bpp = 4; format = IMAGE_FORMAT_PVRTC_4; } else { blockSize = 8 * 4; // Pixel by pixel block size for 2bpp widthBlocks = width / 8; heightBlocks = height / 4; bpp = 2; format = IMAGE_FORMAT_PVRTC_2; } // Clamp to minimum number of blocks if (widthBlocks < 2) widthBlocks = 2; if (heightBlocks < 2) heightBlocks = 2; UInt32 dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); if ( dataSize < dataLength ) return 0; DataImpl* buffer = new DataImpl( dataSize ); if ( ds->Read(buffer->GetDataPtr(), dataSize )!=dataSize ) { buffer->Release(); return 0; } return new ImageImpl(width,height,format,buffer); }
int32_t VMMemory::getScalar(RXEFile::dstocType type, const void *memoryLocation) const throw(std::invalid_argument) { switch (type) { // Default case RXEFile::TC_UBYTE: return int32_t(SwapLittleToHost(reinterpret_cast<const uint8_t *>(memoryLocation)[0])); case RXEFile::TC_SBYTE: return int32_t(SwapLittleToHost(reinterpret_cast<const int8_t *>(memoryLocation)[0])); case RXEFile::TC_UWORD: return int32_t(SwapLittleToHost(reinterpret_cast<const uint16_t *>(memoryLocation)[0])); case RXEFile::TC_SWORD: return int32_t(SwapLittleToHost(reinterpret_cast<const int16_t *>(memoryLocation)[0])); case RXEFile::TC_ULONG: return int32_t(SwapLittleToHost(reinterpret_cast<const uint32_t *>(memoryLocation)[0])); case RXEFile::TC_SLONG: return int32_t(SwapLittleToHost(reinterpret_cast<const int32_t *>(memoryLocation)[0])); // Special cases // The field for an array contains an uint16_t which is the number of the dope vector. case RXEFile::TC_ARRAY: return int32_t(SwapLittleToHost(reinterpret_cast<const uint16_t *> (memoryLocation)[0])); // A mutex is a 32-bit value. What it contains is not fully clear. case RXEFile::TC_MUTEX: return int32_t(SwapLittleToHost(reinterpret_cast<const uint32_t *> (memoryLocation)[0])); // Extremely sketchy support for floats. case RXEFile::TC_FLOAT: return int32_t(SwapLittleToHost(reinterpret_cast<const float *> (memoryLocation)[0])); // We do NOT like clusters and voids default: throw std::invalid_argument("Invalid DSTOC type used for get"); } }
SoundBuffer::SoundBuffer(const char *filename) throw(std::runtime_error) { std::ifstream file(filename, std::ios::binary); if (!file) throw std::runtime_error("Could not open sound file!"); char actualGroupID[4]; file.read(actualGroupID, 4); if (memcmp(actualGroupID, "RIFF", 4) != 0) throw std::runtime_error("Not a WAV file."); // File length minus eight. Ignored here. uint32_t fileLength; file.read(reinterpret_cast<char *> (&fileLength), 4); fileLength = SwapLittleToHost(fileLength); char actualRiffType[4]; file.read(actualRiffType, 4); if (memcmp(actualRiffType, "WAVE", 4) != 0) throw std::runtime_error("Not a WAV file."); // Information about the file bool haveFmt = false; bool haveData = false; uint32_t dataLength; uint16_t numChannels; uint32_t samplesPerSecond; uint16_t bitsPerSample; char *data = NULL; // Scan chunks while (file.good() && !(haveFmt && haveData)) { char chunkType[4]; file.read(chunkType, 4); if (memcmp(chunkType, "fmt ", 4) == 0) { // Read Format header if (haveFmt) throw std::runtime_error("Format data specified more than once."); haveFmt = true; uint32_t chunkLength; file.read(reinterpret_cast<char *> (&chunkLength), 4); chunkLength = SwapLittleToHost(chunkLength); if (chunkLength != 16) throw std::runtime_error("Sound file format not supported."); uint16_t format; file.read(reinterpret_cast<char *> (&format), 2); format = SwapLittleToHost(format); if (format != 0x0001) throw std::runtime_error("Format is not PCM."); file.read(reinterpret_cast<char *> (&numChannels), 2); numChannels = SwapLittleToHost(numChannels); if (numChannels > 2) throw std::runtime_error("More than two channels."); file.read(reinterpret_cast<char *> (&samplesPerSecond), 4); samplesPerSecond = SwapLittleToHost(samplesPerSecond); // Bytes per second and block align. file.seekg(6, std::ios::cur); file.read(reinterpret_cast<char *> (&bitsPerSample), 2); bitsPerSample = SwapLittleToHost(bitsPerSample); if (bitsPerSample != 8 && bitsPerSample != 16) throw std::runtime_error("Bits per sample has unusual value."); } else if (memcmp(chunkType, "data", 4) == 0) { // Read actual data if (haveData) throw std::runtime_error("Sound data specified more than once."); haveData = true; file.read(reinterpret_cast<char *> (&dataLength), 4); dataLength = SwapLittleToHost(dataLength); data = new char [dataLength]; file.read(data, dataLength); } else { // Skip unknown chunk uint32_t chunkLength; file.read(reinterpret_cast<char *> (&chunkLength), 4); chunkLength += chunkLength % 2; // RIFF-Files are word aligned file.seekg(chunkLength, std::ios::cur); } } if (bitsPerSample == 16) SwapU16LittleToHost(reinterpret_cast<uint16_t *>(data), dataLength/sizeof(uint16_t)); initWithData(data, dataLength, samplesPerSecond, bitsPerSample == 16, numChannels == 2); delete [] data; }