DEF_TEST(StreamPeek, reporter) { // Test a memory stream. const char gAbcs[] = "abcdefghijklmnopqrstuvwxyz"; SkMemoryStream memStream(gAbcs, strlen(gAbcs), false); test_fully_peekable_stream(reporter, &memStream, memStream.getLength()); // Test an arbitrary file stream. file streams do not support peeking. SkFILEStream fileStream(GetResourcePath("baby_tux.webp").c_str()); REPORTER_ASSERT(reporter, fileStream.isValid()); if (!fileStream.isValid()) { return; } SkAutoMalloc storage(fileStream.getLength()); for (size_t i = 1; i < fileStream.getLength(); i++) { REPORTER_ASSERT(reporter, fileStream.peek(storage.get(), i) == 0); } // Now test some FrontBufferedStreams for (size_t i = 1; i < memStream.getLength(); i++) { test_peeking_front_buffered_stream(reporter, memStream, i); } }
void PictureViewer::HandleMimeData(BMessage *e) { int32 numBytes; type_code type; const void *data; const char *m_type; if (e->GetInfo( B_MIME_TYPE, 0, (char**)&m_type, &type, &numBytes) != B_OK) return; e->FindData(m_type,B_MIME_TYPE,&data,&numBytes); BMemoryIO memStream(data, numBytes); BBitmapStream imageStream; if (strcmp(m_type,"image/x-be-bitmap")==0) { uint8 buffer[1024]; int32 size; while ((size=memStream.Read(buffer,1024))>0) imageStream.Write(buffer,size); } else if ( BTranslatorRoster::Default()->Translate(&memStream,NULL,NULL, &imageStream, B_TRANSLATOR_BITMAP, 0, m_type) != B_OK) return; BBitmap *bmp; imageStream.DetachBitmap(&bmp); ((WindowPeek*)Window())->LoadImage(bmp); return; }
void ScriptManager::executeFile(const Common::UString &path) { assert(_luaState && _regNestingLevel == 0); if (isIgnoredFile(path)) { return; } Common::ScopedPtr<Common::SeekableReadStream> stream(ResMan.getResource(path, kFileTypeLUC)); if (!stream) { const Common::UString fileName = TypeMan.setFileType(path, kFileTypeLUC); throw Common::Exception("No such LUC \"%s\"", fileName.c_str()); } Common::ScopedPtr<Common::MemoryReadStream> memStream(stream->readStream(stream->size())); const char *data = reinterpret_cast<const char *>(memStream->getData()); const int dataSize = memStream->size(); const int execResult = lua_dobuffer(_luaState, data, dataSize, path.c_str()); if (execResult != 0) { const Common::UString fileName = TypeMan.setFileType(path, kFileTypeLUC); throw Common::Exception("Failed to execute Lua file: %s", fileName.c_str()); } }
//--------------------------------------------------------------------- Codec::DecodeResult FreeImageCodec::decode(DataStreamPtr& input) const { // Set error handler FreeImage_SetOutputMessage(FreeImageLoadErrorHandler); // Buffer stream into memory (TODO: override IO functions instead?) MemoryDataStream memStream(input, true); FIMEMORY* fiMem = FreeImage_OpenMemory(memStream.getPtr(), static_cast<DWORD>(memStream.size())); FIBITMAP* fiBitmap = FreeImage_LoadFromMemory( (FREE_IMAGE_FORMAT)mFreeImageType, fiMem); if (!fiBitmap) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Error decoding image", "FreeImageCodec::decode"); } ImageData* imgData = OGRE_NEW ImageData(); MemoryDataStreamPtr output; imgData->depth = 1; // only 2D formats handled by this codec imgData->width = FreeImage_GetWidth(fiBitmap); imgData->height = FreeImage_GetHeight(fiBitmap); imgData->num_mipmaps = 0; // no mipmaps in non-DDS imgData->flags = 0; // Must derive format first, this may perform conversions FREE_IMAGE_TYPE imageType = FreeImage_GetImageType(fiBitmap); FREE_IMAGE_COLOR_TYPE colourType = FreeImage_GetColorType(fiBitmap); unsigned bpp = FreeImage_GetBPP(fiBitmap); switch(imageType) { case FIT_UNKNOWN: case FIT_COMPLEX: case FIT_UINT32: case FIT_INT32: case FIT_DOUBLE: default: OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Unknown or unsupported image format", "FreeImageCodec::decode"); break; case FIT_BITMAP: // Standard image type // Perform any colour conversions for greyscale if (colourType == FIC_MINISWHITE || colourType == FIC_MINISBLACK) { FIBITMAP* newBitmap = FreeImage_ConvertToGreyscale(fiBitmap); // free old bitmap and replace FreeImage_Unload(fiBitmap); fiBitmap = newBitmap; // get new formats bpp = FreeImage_GetBPP(fiBitmap); colourType = FreeImage_GetColorType(fiBitmap); } // Perform any colour conversions for RGB else if (bpp < 8 || colourType == FIC_PALETTE || colourType == FIC_CMYK) { FIBITMAP* newBitmap = NULL; if (FreeImage_IsTransparent(fiBitmap)) { // convert to 32 bit to preserve the transparency // (the alpha byte will be 0 if pixel is transparent) newBitmap = FreeImage_ConvertTo32Bits(fiBitmap); } else { // no transparency - only 3 bytes are needed newBitmap = FreeImage_ConvertTo24Bits(fiBitmap); } // free old bitmap and replace FreeImage_Unload(fiBitmap); fiBitmap = newBitmap; // get new formats bpp = FreeImage_GetBPP(fiBitmap); colourType = FreeImage_GetColorType(fiBitmap); } // by this stage, 8-bit is greyscale, 16/24/32 bit are RGB[A] switch(bpp) { case 8: imgData->format = PF_L8; break; case 16: // Determine 555 or 565 from green mask // cannot be 16-bit greyscale since that's FIT_UINT16 if(FreeImage_GetGreenMask(fiBitmap) == FI16_565_GREEN_MASK) { imgData->format = PF_R5G6B5; } else { // FreeImage doesn't support 4444 format so must be 1555 imgData->format = PF_A1R5G5B5; } break; case 24: // FreeImage differs per platform // PF_BYTE_BGR[A] for little endian (== PF_ARGB native) // PF_BYTE_RGB[A] for big endian (== PF_RGBA native) #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB imgData->format = PF_BYTE_RGB; #else imgData->format = PF_BYTE_BGR; #endif break; case 32: #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB imgData->format = PF_BYTE_RGBA; #else imgData->format = PF_BYTE_BGRA; #endif break; }; break; case FIT_UINT16: case FIT_INT16: // 16-bit greyscale imgData->format = PF_L16; break; case FIT_FLOAT: // Single-component floating point data imgData->format = PF_FLOAT32_R; break; case FIT_RGB16: imgData->format = PF_SHORT_RGB; break; case FIT_RGBA16: imgData->format = PF_SHORT_RGBA; break; case FIT_RGBF: imgData->format = PF_FLOAT32_RGB; break; case FIT_RGBAF: imgData->format = PF_FLOAT32_RGBA; break; }; unsigned char* srcData = FreeImage_GetBits(fiBitmap); unsigned srcPitch = FreeImage_GetPitch(fiBitmap); // Final data - invert image and trim pitch at the same time size_t dstPitch = imgData->width * PixelUtil::getNumElemBytes(imgData->format); imgData->size = dstPitch * imgData->height; // Bind output buffer output.bind(OGRE_NEW MemoryDataStream(imgData->size)); uchar* pSrc; uchar* pDst = output->getPtr(); for (size_t y = 0; y < imgData->height; ++y) { pSrc = srcData + (imgData->height - y - 1) * srcPitch; memcpy(pDst, pSrc, dstPitch); pDst += dstPitch; } FreeImage_Unload(fiBitmap); FreeImage_CloseMemory(fiMem); DecodeResult ret; ret.first = output; ret.second = CodecDataPtr(imgData); return ret; }
int _tmain(int argc, _TCHAR* argv[]) { testAlloc(); CommonLib::CBitsVector bitVectors; bool bBit = false; for (size_t i = 0; i < 10000; ++i) { bitVectors.push_back(bBit); bBit = !bBit; } for (size_t i = 0; i < 10000; ++i) { bool bBitt = bitVectors[bBit]; bBit = !bBit; } int nBitCount = 8; int nByte = nBitCount/8; int nBit = nBitCount%8; Int128 a1(2, 0xFFFFFFFFFFFFFFFF); Int128 a2(1, 1); Int128 res = a1 + a2; uint64 dd = 0; uint64 dd1 = 0; uint64 dd2 =100; dd = (dd1 - 1); if(dd > (dd + 1)) { int rr = 0; rr++; } int i = 0; int j = i++; CommonLib::alloc_t *alloc = new CommonLib::simple_alloc_t(); CommonLib::CWriteMemoryStream memStream(alloc); memStream.resize(50); CommonLib::FxBitWriteStream bitWrite; CommonLib::FxBitReadStream bitRead; bitWrite.attach(&memStream, 0, 50); bitRead.attach(&memStream, 0, 50); uint32 nVal1111 = 32; int64 nValue = 0; int len = embDB::BitsUtils::log2(nVal1111); int len2 = embDB::BitsUtils::log2((uint32)1); int len3 = embDB::BitsUtils::log2((uint32)2); bitWrite.writeBits(nVal1111, len + 1); bitRead.readBits(nValue, len); bitWrite.writeBits(nValue, 1); nValue = -1024; bitWrite.writeBits(nValue, 64); int64 nReadValue = 1; bitRead.readBits(nReadValue, 1); bitRead.readBits(nReadValue, 64); bitWrite.writeBits(nValue, 11); /*CommonLib::CWriteFileStream writeFSteam; writeFSteam.open(L"D:\\1.fs", CommonLib::ofmCreateAlways, CommonLib::arWrite, CommonLib::smNoMode); writeFSteam.write((uint64)23); writeFSteam.write((uint32)15); writeFSteam.write((byte)1); writeFSteam.close(); CommonLib::CReadFileStream readFSteam; readFSteam.open(L"D:\\1.fs", CommonLib::ofmOpenExisting, CommonLib::arRead, CommonLib::smNoMode); uint64 retu64 = readFSteam.readIntu64(); uint64 retu32 = readFSteam.readIntu32(); byte retByte = readFSteam.readByte(); readFSteam.close(); memStream.write((uint64)23); memStream.write((uint32)15); memStream.write((byte)1); readStrim.attachBuffer(memStream.buffer(), memStream.size()); uint64 nType; readStrim.read(nType); CommonLib::FxMemoryWriteStream writeStrim(alloc); std::vector<CommonLib::CString> vecFiles; CommonLib::FileSystem::getFiles(CommonLib::CString(L"D:\\2\\") + L"*.shp", vecFiles); CommonLib::CString path(L"C:\\test\\ddf\\1.shp"); CommonLib::CString path1(L"C:\\test\\ddf\\"); CommonLib::CString path2(L"C:\\test\\ddf\\1"); CommonLib::CString path3(L"C:\\test\\ddf\\1."); CommonLib::CString path4(L"2.shp"); CommonLib::CString path5(L"2."); CommonLib::CString path6(L"vdfvdfvfd"); CommonLib::CString sFile = CommonLib::FileSystem::FindFileName(path); CommonLib::CString sFile1 = CommonLib::FileSystem::FindFileName(path1); CommonLib::CString sFile2 = CommonLib::FileSystem::FindFileName(path2); CommonLib::CString sFile3 = CommonLib::FileSystem::FindFileName(path3); CommonLib::CString sOnlyFile = CommonLib::FileSystem::FindOnlyFileName(path); CommonLib::CString sOnlyFile1 = CommonLib::FileSystem::FindOnlyFileName(path1); CommonLib::CString sOnlyFile2 = CommonLib::FileSystem::FindOnlyFileName(path2); CommonLib::CString sOnlyFile3 = CommonLib::FileSystem::FindOnlyFileName(path3); CommonLib::CString sOnlyFile4 = CommonLib::FileSystem::FindOnlyFileName(path4); CommonLib::CString sOnlyFile5 = CommonLib::FileSystem::FindOnlyFileName(path5); CommonLib::CString sOnlyFile6 = CommonLib::FileSystem::FindOnlyFileName(path6); CommonLib::CString sExt = CommonLib::FileSystem::FindFileExtension(path); CommonLib::CString sExt1 = CommonLib::FileSystem::FindFileExtension(path1); CommonLib::CString sExt2 = CommonLib::FileSystem::FindFileExtension(path2); CommonLib::CString sExt3 = CommonLib::FileSystem::FindFileExtension(path3); CommonLib::CString sph = CommonLib::FileSystem::FindFilePath(path); CommonLib::CString sph1 = CommonLib::FileSystem::FindFilePath(path1); CommonLib::CString sph2 = CommonLib::FileSystem::FindFilePath(path2); CommonLib::CString sph3 = CommonLib::FileSystem::FindFilePath(path3); testAlloc(); return 0; CommonLib::FxBitWriteStream writeBitStream(alloc); CommonLib::FxBitReadStream readBitStream(alloc); writeBitStream.create(1000); uint16 nBit16_14 = (1 << 13) + (1 << 12) + (1 << 10) + (1 << 5); uint16 nBit16 = 0xffff; uint32 nBit32_30 = (1 << 29) + (1 << 15) + (1 << 7) + (1 << 3); uint32 nBit32 = 0xffffffff; uint64 nBit64_60 = ((uint64)1 << 59) + ((uint64)1 << 30) + ((uint64)1 << 15) + ((uint64)1 << 3); uint64 nBit64 = 0xffffffffffffffff; uint16 nBit16_14_r; uint16 nBit16_r; uint32 nBit32_30_r; uint32 nBit32_r; uint64 nBit64_60_r; uint64 nBit64_r; //writeBitStream.writeBits(nBit16, 15) writeBitStream.writeBit((byte)1); writeBitStream.writeBit((byte)0); writeBitStream.writeBit((byte)1); writeBitStream.writeBit((byte)0); writeBitStream.writeBit((byte)1); writeBitStream.writeBit((byte)0); writeBitStream.writeBit((byte)1); writeBitStream.writeBit((byte)0); writeBitStream.writeBit((byte)1); writeBitStream.writeBits(nBit16_14, 14); writeBitStream.writeBits(nBit16, 16); writeBitStream.writeBits(nBit32_30, 30); writeBitStream.writeBits(nBit32, 32); writeBitStream.writeBits(nBit64_60, 60); writeBitStream.writeBits(nBit64, 64); byte bBit1, bBit2, bBit3, bBit4, bBit5, bBit6, bBit7, bBit8, bBit9; readBitStream.readBits(nBit16_14_r, 14); readBitStream.readBits(nBit16_r, 16); readBitStream.readBits(nBit32_30_r, 30); readBitStream.readBits(nBit32_r, 32); readBitStream.readBits(nBit64_60_r, 60); readBitStream.readBits(nBit64_r, 64); /*CommonLib::CString str; CommonLib::MemoryStream stream(alloc); str.format("dgf %s", "dd"); str.wstr(); int i1 = 666; float f1 = 237.4556; double d1 = 237.4556; bool b1 = true; stream.write(i1); stream.write(f1); stream.write(d1); stream.write(b1); stream.reset(); int i2; float f2; double d2; bool b2; stream.read(i2); stream.read(f2); stream.read(d2); stream.read(b2);*/ return 0; }
void gkTextManager::parseScripts(const gkString& group) { gkResourceManager::ResourceIterator iter = getResourceIterator(); while (iter.hasMoreElements()) { gkTextFile* tf = static_cast<gkTextFile*>(iter.getNext().second); if (!group.empty() && tf->getGroupName() != group) continue; const gkString& buf = tf->getText(); const int type = tf->getType(); #ifdef OGREKIT_COMPILE_OGRE_SCRIPTS try { if (type == TT_MATERIAL) { Ogre::DataStreamPtr memStream( OGRE_NEW Ogre::MemoryDataStream((void*)buf.c_str(), buf.size())); Ogre::MaterialManager::getSingleton().parseScript(memStream, group); } else if (type == TT_PARTICLE) { Ogre::DataStreamPtr memStream( OGRE_NEW Ogre::MemoryDataStream((void*)buf.c_str(), buf.size())); Ogre::ParticleSystemManager::getSingleton().parseScript(memStream, group); } else if (type == TT_FONT) { // Note: font must be an external file (.ttf anyway (texture fonts are not tested) ) Ogre::DataStreamPtr memStream( OGRE_NEW Ogre::MemoryDataStream((void*)buf.c_str(), buf.size())); Ogre::FontManager::getSingleton().parseScript(memStream, group); } else if (type == TT_COMPOSIT) { Ogre::DataStreamPtr memStream( OGRE_NEW Ogre::MemoryDataStream((void*)buf.c_str(), buf.size())); Ogre::CompositorManager::getSingleton().parseScript(memStream, group); } } catch (Ogre::Exception& e) { gkLogMessage("TextManager: " << e.getDescription()); continue; } if (type == TT_BFONT) { utMemoryStream stream; stream.open(buf.c_str(), buf.size(), utStream::SM_READ); gkFontManager::getSingleton().parseScript(&stream); } #endif #ifdef OGREKIT_USE_LUA if (type == TT_LUA) gkLuaManager::getSingleton().createFromText(gkResourceName(tf->getResourceName().getName(), group), buf); #endif } #ifdef OGREKIT_COMPILE_OGRE_SCRIPTS // Overlays are a dependant script. (.material .font) try { TextArray overlays; getTextFiles(overlays, TT_OVERLAY); TextArray::Iterator it = overlays.iterator(); while (it.hasMoreElements()) { gkTextFile* tf = (gkTextFile*)it.getNext(); const gkString& buf = tf->getText(); const int type = tf->getType(); Ogre::DataStreamPtr memStream( OGRE_NEW Ogre::MemoryDataStream((void*)buf.c_str(), buf.size())); Ogre::OverlayManager::getSingleton().parseScript(memStream, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } } catch (Ogre::Exception& e) { gkLogMessage("TextManager: " << e.getDescription()); } #endif }
void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags) { Audio::RewindableAudioStream *stream = 0; byte *ptr, *spoolPtr; int size = -1; int priority, rate; byte flags = Audio::FLAG_UNSIGNED; Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType; if (soundID > _vm->_numSounds) type = Audio::Mixer::kMusicSoundType; else if (soundID == 1) type = Audio::Mixer::kSpeechSoundType; if (heChannel == -1) heChannel = (_vm->VAR_RESERVED_SOUND_CHANNELS != 0xFF) ? findFreeSoundChannel() : 1; debug(5,"playHESound: soundID %d heOffset %d heChannel %d heFlags %d", soundID, heOffset, heChannel, heFlags); if (soundID >= 10000) { // Special codes, used in pjgames return; } if (soundID > _vm->_numSounds) { int music_offs; Common::File musicFile; Common::String buf(_vm->generateFilename(-4)); if (musicFile.open(buf) == false) { warning("playHESound: Can't open music file %s", buf.c_str()); return; } if (!getHEMusicDetails(soundID, music_offs, size)) { debug(0, "playHESound: musicID %d not found", soundID); return; } musicFile.seek(music_offs, SEEK_SET); _mixer->stopHandle(_heSoundChannels[heChannel]); spoolPtr = _vm->_res->createResource(rtSpoolBuffer, heChannel, size); assert(spoolPtr); musicFile.read(spoolPtr, size); musicFile.close(); if (_vm->_game.heversion == 70) { stream = Audio::makeRawStream(spoolPtr, size, 11025, flags, DisposeAfterUse::NO); _mixer->playStream(type, &_heSoundChannels[heChannel], stream, soundID); return; } } if (soundID > _vm->_numSounds) { ptr = _vm->getResourceAddress(rtSpoolBuffer, heChannel); } else { ptr = _vm->getResourceAddress(rtSound, soundID); } if (!ptr) { return; } // Support for sound in later HE games if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F') || READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) { uint16 compType; int blockAlign; int codeOffs = -1; priority = (soundID > _vm->_numSounds) ? 255 : *(ptr + 18); byte *sbngPtr = findSoundTag(MKTAG('S','B','N','G'), ptr); if (sbngPtr != NULL) { codeOffs = sbngPtr - ptr + 8; } if (_mixer->isSoundHandleActive(_heSoundChannels[heChannel])) { int curSnd = _heChannel[heChannel].sound; if (curSnd == 1 && soundID != 1) return; if (curSnd != 0 && curSnd != 1 && soundID != 1 && _heChannel[heChannel].priority > priority) return; } if (READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) ptr += 8; size = READ_LE_UINT32(ptr + 4); Common::MemoryReadStream memStream(ptr, size); if (!Audio::loadWAVFromStream(memStream, size, rate, flags, &compType, &blockAlign)) { error("playHESound: Not a valid WAV file (%d)", soundID); } assert(heOffset >= 0 && heOffset < size); // FIXME: Disabled sound offsets, due to asserts been triggered heOffset = 0; _vm->setHETimer(heChannel + 4); _heChannel[heChannel].sound = soundID; _heChannel[heChannel].priority = priority; _heChannel[heChannel].rate = rate; _heChannel[heChannel].sbngBlock = (codeOffs != -1) ? 1 : 0; _heChannel[heChannel].codeOffs = codeOffs; memset(_heChannel[heChannel].soundVars, 0, sizeof(_heChannel[heChannel].soundVars)); // TODO: Extra sound flags if (heFlags & 1) { _heChannel[heChannel].timer = 0; } else { _heChannel[heChannel].timer = size * 1000 / rate; } _mixer->stopHandle(_heSoundChannels[heChannel]); if (compType == 17) { Audio::AudioStream *voxStream = Audio::makeADPCMStream(&memStream, DisposeAfterUse::NO, size, Audio::kADPCMMSIma, rate, (flags & Audio::FLAG_STEREO) ? 2 : 1, blockAlign); // FIXME: Get rid of this crude hack to turn a ADPCM stream into a raw stream. // It seems it is only there to allow looping -- if that is true, we certainly // can do without it, using a LoopingAudioStream. byte *sound = (byte *)malloc(size * 4); /* On systems where it matters, malloc will return * even addresses, so the use of (void *) in the * following cast shuts the compiler from warning * unnecessarily. */ size = voxStream->readBuffer((int16*)(void *)sound, size * 2); size *= 2; // 16bits. delete voxStream; _heChannel[heChannel].rate = rate; if (_heChannel[heChannel].timer) _heChannel[heChannel].timer = size * 1000 / rate; // makeADPCMStream returns a stream in native endianness, but RawMemoryStream // defaults to big endian. If we're on a little endian system, set the LE flag. #ifdef SCUMM_LITTLE_ENDIAN flags |= Audio::FLAG_LITTLE_ENDIAN; #endif stream = Audio::makeRawStream(sound + heOffset, size - heOffset, rate, flags); } else { stream = Audio::makeRawStream(ptr + memStream.pos() + heOffset, size - heOffset, rate, flags, DisposeAfterUse::NO); } _mixer->playStream(type, &_heSoundChannels[heChannel], Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID); } // Support for sound in Humongous Entertainment games else if (READ_BE_UINT32(ptr) == MKTAG('D','I','G','I') || READ_BE_UINT32(ptr) == MKTAG('T','A','L','K')) { byte *sndPtr = ptr; int codeOffs = -1; priority = (soundID > _vm->_numSounds) ? 255 : *(ptr + 18); rate = READ_LE_UINT16(ptr + 22); // Skip DIGI/TALK (8) and HSHD (24) blocks ptr += 32; if (_mixer->isSoundHandleActive(_heSoundChannels[heChannel])) { int curSnd = _heChannel[heChannel].sound; if (curSnd == 1 && soundID != 1) return; if (curSnd != 0 && curSnd != 1 && soundID != 1 && _heChannel[heChannel].priority > priority) return; } if (READ_BE_UINT32(ptr) == MKTAG('S','B','N','G')) { codeOffs = ptr - sndPtr + 8; ptr += READ_BE_UINT32(ptr + 4); } assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T')); size = READ_BE_UINT32(ptr + 4) - 8; if (heOffset < 0 || heOffset > size) { // Occurs when making fireworks in puttmoon heOffset = 0; } size -= heOffset; if (_overrideFreq) { // Used by the piano in Fatty Bear's Birthday Surprise rate = _overrideFreq; _overrideFreq = 0; } _vm->setHETimer(heChannel + 4); _heChannel[heChannel].sound = soundID; _heChannel[heChannel].priority = priority; _heChannel[heChannel].rate = rate; _heChannel[heChannel].sbngBlock = (codeOffs != -1) ? 1 : 0; _heChannel[heChannel].codeOffs = codeOffs; memset(_heChannel[heChannel].soundVars, 0, sizeof(_heChannel[heChannel].soundVars)); // TODO: Extra sound flags if (heFlags & 1) { _heChannel[heChannel].timer = 0; } else { _heChannel[heChannel].timer = size * 1000 / rate; } _mixer->stopHandle(_heSoundChannels[heChannel]); stream = Audio::makeRawStream(ptr + heOffset + 8, size, rate, flags, DisposeAfterUse::NO); _mixer->playStream(type, &_heSoundChannels[heChannel], Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID); } // Support for PCM music in 3DO versions of Humongous Entertainment games else if (READ_BE_UINT32(ptr) == MKTAG('M','R','A','W')) { priority = *(ptr + 18); rate = READ_LE_UINT16(ptr + 22); // Skip DIGI (8) and HSHD (24) blocks ptr += 32; assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T')); size = READ_BE_UINT32(ptr + 4) - 8; byte *sound = (byte *)malloc(size); memcpy(sound, ptr + 8, size); _mixer->stopID(_currentMusic); _currentMusic = soundID; stream = Audio::makeRawStream(sound, size, rate, 0); _mixer->playStream(Audio::Mixer::kMusicSoundType, NULL, stream, soundID); } else if (READ_BE_UINT32(ptr) == MKTAG('M','I','D','I')) { if (_vm->_imuse) { // This is used in the DOS version of Fatty Bear's // Birthday Surprise to change the note on the piano // when not using a digitized instrument. _vm->_imuse->stopSound(_currentMusic); _currentMusic = soundID; _vm->_imuse->startSoundWithNoteOffset(soundID, heOffset); } } }