SchannelCertificate::SchannelCertificate(const ByteArray& der) { if (!der.empty()) { // Convert the DER encoded certificate to a PCERT_CONTEXT CERT_BLOB certBlob = {0}; certBlob.cbData = der.size(); certBlob.pbData = (BYTE*)&der[0]; if (!CryptQueryObject( CERT_QUERY_OBJECT_BLOB, &certBlob, CERT_QUERY_CONTENT_FLAG_CERT, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, NULL, NULL, NULL, (const void**)m_cert.Reset())) { // TODO: Because Swiften isn't exception safe, we have no way to indicate failure } } }
ByteArray HKDF::expand(const ByteArray &prk, const ByteArray &info, int outputSize) const { int iterations = std::ceil((float)outputSize / HKDF::HASH_OUTPUT_SIZE); ByteArray mixin; ByteArray results; int remainingBytes = outputSize; for (int i = iterationStartOffset; i < (iterations + iterationStartOffset); i++) { ByteArray message(mixin); if (!info.empty()) { message += info; } message += ByteArray(1, (char)(i % 256)); unsigned char out[32]; HMAC_SHA256((unsigned char*)message.c_str(), message.size(), (unsigned char*)prk.c_str(), prk.size(), out); ByteArray stepResult((const char*)out, 32); int stepSize = std::min((int)remainingBytes, (int)stepResult.size()); results += stepResult.substr(0, stepSize); mixin = stepResult; remainingBytes -= stepSize; } return results; }
ByteArray HKDF::deriveSecrets(const ByteArray &inputKeyMaterial, const ByteArray &info, int outputLength, const ByteArray &saltFirst) const { ByteArray salt = saltFirst; if (salt.empty()) { salt = ByteArray(HKDF::HASH_OUTPUT_SIZE, '\0'); } ByteArray prk = extract(salt, inputKeyMaterial); return expand(prk, info, outputLength); }
/**@brief Constructs String as string representation of byte sequence in hex form. * e.g 234F11A1...*/ String String::fromByteArray(const ByteArray& bytes) { if(bytes.empty()) return String(); String result; for(ByteArray::const_iterator i = bytes.begin(); i != bytes.end(); ++i) { result += hex2char(((*i)/0x10)%0x10); result += hex2char((*i)%0x10); } return result; }
SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(NULL), _voiceContext(NULL), _voiceSerial(-1) { // Load sound module resource file contexts _sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE); if (_sfxContext == NULL) { error("SndRes::SndRes resource context not found"); } setVoiceBank(0); if (_vm->getGameId() == GID_ITE) { _fxTable.resize(ITE_SFXCOUNT); for (uint i = 0; i < _fxTable.size(); i++) { _fxTable[i].res = ITE_SfxTable[i].res; _fxTable[i].vol = ITE_SfxTable[i].vol; } #ifdef ENABLE_IHNM } else if (_vm->getGameId() == GID_IHNM) { ResourceContext *resourceContext; resourceContext = _vm->_resource->getContext(GAME_SOUNDFILE); if (resourceContext == NULL) { error("Resource::loadGlobalResources() resource context not found"); } ByteArray resourceData; if (_vm->isIHNMDemo()) { _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_SFX_LUT, resourceData); } else { _vm->_resource->loadResource(resourceContext, RID_IHNM_SFX_LUT, resourceData); } if (resourceData.empty()) { error("Sndres::SndRes can't read SfxIDs table"); } _fxTableIDs.resize(resourceData.size() / 2); ByteArrayReadStreamEndian metaS(resourceData); for (uint i = 0; i < _fxTableIDs.size(); i++) { _fxTableIDs[i] = metaS.readSint16LE(); } #endif #ifdef ENABLE_SAGA2 } else if (_vm->getGameId() == GID_DINO) { // TODO } else if (_vm->getGameId() == GID_FTA2) { // TODO #endif } }
DIGESTMD5Properties DIGESTMD5Properties::parse(const ByteArray& data) { DIGESTMD5Properties result; bool inKey = true; ByteArray currentKey; ByteArray currentValue; for (size_t i = 0; i < data.size(); ++i) { char c = static_cast<char>(data[i]); if (inKey) { if (c == '=') { inKey = false; } else { currentKey.push_back(static_cast<unsigned char>(c)); } } else { if (c == ',' && !insideQuotes(currentValue)) { std::string key = byteArrayToString(currentKey); if (isQuoted(key)) { result.setValue(key, byteArrayToString(stripQuotes(currentValue))); } else { result.setValue(key, byteArrayToString(currentValue)); } inKey = true; currentKey = ByteArray(); currentValue = ByteArray(); } else { currentValue.push_back(static_cast<unsigned char>(c)); } } } if (!currentKey.empty()) { std::string key = byteArrayToString(currentKey); if (isQuoted(key)) { result.setValue(key, byteArrayToString(stripQuotes(currentValue))); } else { result.setValue(key, byteArrayToString(currentValue)); } } return result; }
void PalAnim::loadPalAnim(const ByteArray &resourceData) { clear(); if (resourceData.empty()) { return; } ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); if (_vm->getGameId() == GID_IHNM) { return; } _entries.resize(readS.readUint16()); debug(3, "PalAnim::loadPalAnim(): Loading %d PALANIM entries.", _entries.size()); for (Common::Array<PalanimEntry>::iterator i = _entries.begin(); i != _entries.end(); ++i) { i->cycle = 0; i->colors.resize(readS.readUint16()); debug(2, "PalAnim::loadPalAnim(): Loading %d SAGA_COLOR structures.", i->colors.size()); i->palIndex.resize(readS.readUint16()); debug(2, "PalAnim::loadPalAnim(): Loading %d palette indices.\n", i->palIndex.size()); for (uint j = 0; j < i->palIndex.size(); j++) { i->palIndex[j] = readS.readByte(); } for (Common::Array<Color>::iterator j = i->colors.begin(); j != i->colors.end(); ++j) { j->red = readS.readByte(); j->green = readS.readByte(); j->blue = readS.readByte(); } } }
/**@brief Constructs String from byte sequence, using the locale codecvt * facet.*/ String String::fromByteArray(const ByteArray& bytes, std::locale loc) { if(bytes.empty()) return String(); // converting, using codecvt facets size_t bsize = bytes.size(); mbstate_t tmp; const char * cnext; wchar_t * wnext; wchar_t *wstr = new wchar_t[bsize + 1]; std::uninitialized_fill(wstr, wstr + bsize + 1, 0); typedef std::codecvt<wchar_t, char, mbstate_t> cvt; std::vector<char> charr = barr2charr(bytes); cvt::result res = std::use_facet<cvt>(loc).in(tmp, &charr[0], &charr[0] + bsize, cnext, wstr, wstr + bsize, wnext); assert(res == cvt::ok); String result(wstr); delete [] wstr; return result; }
void Scene::IHNMLoadCutaways() { ResourceContext *resourceContext; //ResourceContext *soundContext; ByteArray resourceData; resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (resourceContext == NULL) { error("Scene::IHNMStartProc() resource context not found"); } if (!_vm->isIHNMDemo()) _vm->_resource->loadResource(resourceContext, RID_IHNM_INTRO_CUTAWAYS, resourceData); else _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_INTRO_CUTAWAYS, resourceData); if (resourceData.empty()) { error("Scene::IHNMStartProc() Can't load cutaway list"); } // Load the cutaways for the title screens _vm->_anim->loadCutawayList(resourceData); }
// Loads an object map resource ( objects ( clickareas ( points ) ) ) void ObjectMap::load(const ByteArray &resourceData) { if (!_hitZoneList.empty()) { error("ObjectMap::load _hitZoneList not empty"); } if (resourceData.empty()) { return; } if (resourceData.size() < 4) { error("ObjectMap::load wrong resourceLength"); } ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); _hitZoneList.resize(readS.readUint16()); int idx = 0; for (HitZoneArray::iterator i = _hitZoneList.begin(); i != _hitZoneList.end(); ++i) { i->load(_vm, &readS, idx++, _vm->_scene->currentSceneNumber()); } }
Scene::Scene(SagaEngine *vm) : _vm(vm) { ByteArray sceneLUTData; uint32 resourceId; uint i; // Do nothing for SAGA2 games for now if (_vm->isSaga2()) { _inGame = false; _sceneLoaded = false; return; } // Load scene module resource context _sceneContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (_sceneContext == NULL) { error("Scene::Scene() scene context not found"); } // Load scene lookup table resourceId = _vm->_resource->convertResourceId(_vm->getResourceDescription()->sceneLUTResourceId); debug(3, "Loading scene LUT from resource %i", resourceId); _vm->_resource->loadResource(_sceneContext, resourceId, sceneLUTData); if (sceneLUTData.empty()) { error("Scene::Scene() sceneLUT is empty"); } _sceneLUT.resize(sceneLUTData.size() / 2); ByteArrayReadStreamEndian readS(sceneLUTData, _sceneContext->isBigEndian()); for (i = 0; i < _sceneLUT.size(); i++) { _sceneLUT[i] = readS.readUint16(); debug(8, "sceneNumber %i has resourceId %i", i, _sceneLUT[i]); } #ifdef SAGA_DEBUG #define DUMP_SCENES_LEVEL 10 if (DUMP_SCENES_LEVEL <= gDebugLevel) { int backUpDebugLevel = gDebugLevel; SAGAResourceTypes *types; int typesCount; SAGAResourceTypes resType; SceneResourceDataArray resourceList; getResourceTypes(types, typesCount); for (i = 0; i < _sceneLUT.size(); i++) { gDebugLevel = -1; loadSceneDescriptor(_sceneLUT[i]); loadSceneResourceList(_sceneDescription.resourceListResourceId, resourceList); gDebugLevel = backUpDebugLevel; debug(DUMP_SCENES_LEVEL, "Dump Scene: number %i, descriptor resourceId %i, resourceList resourceId %i", i, _sceneLUT[i], _sceneDescription.resourceListResourceId); debug(DUMP_SCENES_LEVEL, "\tresourceListCount %i", (int)resourceList.size()); for (SceneResourceDataArray::iterator j = resourceList.begin(); j != resourceList.end(); ++j) { if (j->resourceType >= typesCount) { error("wrong resource type %i", j->resourceType); } resType = types[j->resourceType]; debug(DUMP_SCENES_LEVEL, "\t%s resourceId %i", SAGAResourceTypesString[resType], j->resourceId); } } } #endif debug(3, "LUT has %d entries.", _sceneLUT.size()); _sceneLoaded = false; _sceneNumber = 0; _chapterNumber = 0; _sceneResourceId = 0; _inGame = false; _sceneDescription.reset(); _sceneProc = NULL; _objectMap = new ObjectMap(_vm); _actionMap = new ObjectMap(_vm); }
void SagaEngine::loadStrings(StringsTable &stringsTable, const ByteArray &stringsData) { uint16 stringsCount; size_t offset; size_t prevOffset = 0; Common::Array<size_t> tempOffsets; uint ui; if (stringsData.empty()) { error("SagaEngine::loadStrings() Error loading strings list resource"); } ByteArrayReadStreamEndian scriptS(stringsData, isBigEndian()); //TODO: get endianess from context offset = scriptS.readUint16(); stringsCount = offset / 2; ui = 0; scriptS.seek(0); tempOffsets.resize(stringsCount); while (ui < stringsCount) { offset = scriptS.readUint16(); // In some rooms in IHNM, string offsets can be greater than the maximum value than a 16-bit integer can hold // We detect this by checking the previous offset, and if it was bigger than the current one, an overflow // occurred (since the string offsets are sequential), so we're adding the missing part of the number // Fixes bug #1895205 - "IHNM: end game text/caption error" if (prevOffset > offset) offset += 65536; prevOffset = offset; if (offset == stringsData.size()) { stringsCount = ui; tempOffsets.resize(stringsCount); break; } if (offset > stringsData.size()) { // This case should never occur, but apparently it does in the Italian fan // translation of IHNM warning("SagaEngine::loadStrings wrong strings table"); stringsCount = ui; tempOffsets.resize(stringsCount); break; } tempOffsets[ui] = offset; ui++; } prevOffset = scriptS.pos(); int32 left = scriptS.size() - prevOffset; if (left < 0) { error("SagaEngine::loadStrings() Error loading strings buffer"); } stringsTable.buffer.resize(left); if (left > 0) { scriptS.read(&stringsTable.buffer.front(), left); } stringsTable.strings.resize(tempOffsets.size()); for (ui = 0; ui < tempOffsets.size(); ui++) { offset = tempOffsets[ui] - prevOffset; if (offset >= stringsTable.buffer.size()) { error("SagaEngine::loadStrings() Wrong offset"); } stringsTable.strings[ui] = &stringsTable.buffer[offset]; debug(9, "string[%i]=%s", ui, stringsTable.strings[ui]); } }
void BaseClient::onPackageReceived(const NetPackageHeader& header, const unsigned char* contentP, const size_t& contentLen, boost::shared_ptr<NetConnection> connection) { if (contentLen <= 0 || NULL == connection) { return ; } ByteArray tmpData; if (header.m_flag.compress == COMPRESS_ZLIB || header.m_flag.compress == COMPRESS_DOUBLE_ZLIB) { if (header.m_flag.compress == COMPRESS_DOUBLE_ZLIB && connection->m_compressType != COMPRESS_DOUBLE_ZLIB) { connection->m_compressType = COMPRESS_DOUBLE_ZLIB; } bool bOK = zlibDecompress(const_cast<unsigned char*>(contentP), contentLen, tmpData, 0); if (tmpData.empty()) { return; } if (bOK) { if (tmpData.size() <= 0) { return; } } } else if (header.m_flag.compress == COMPRESS_LZMA || header.m_flag.compress == COMPRESS_DOUBLE_LZMA) { if (header.m_flag.compress == COMPRESS_DOUBLE_LZMA && connection->m_compressType != COMPRESS_DOUBLE_LZMA) { connection->m_compressType = COMPRESS_DOUBLE_LZMA; } bool bOK = LzmaDecomp(const_cast<unsigned char*>(contentP), contentLen, tmpData, 0); if (tmpData.empty()) { return; } if (bOK) { if (tmpData.size() <= 0) { return; } } } switch (header.m_cmd) { case NET_CMD_RPC: { string status; if (jsonHelper::getInstance()->getField(status, "status",tmpData)) { r_int64 seq = header.m_seq; CBTable::iterator ret = m_CBs.find(seq); if (ret != m_CBs.end()) { ByteArray param; string error; jsonHelper::getInstance()->getField(error, "error",tmpData); if (jsonHelper::getInstance()->getSubJson(param, "param", tmpData)) { ret->second(param, error); { boost::mutex::scoped_lock lock(m_mutex); m_CBs.erase(seq); } } } } } break; case NET_CMD_KEEPALIVE: { NetPackageHeader header(NET_CMD_KEEPALIVE_RESPONSE, 0, 0, 0); header.m_length = sizeof(r_int32) + NET_PACKAGE_HEADER_LENGTH; ByteArray bytes; bytes.resize(sizeof(r_int32) + NET_PACKAGE_HEADER_LENGTH); r_int32 pos = header.encode(bytes); connection->sendData(bytes, bytes.size()); } break; case NET_CMD_KEEPALIVE_RESPONSE: //接收到心跳包反馈 break; default: break; } }
bool tryLock(const Zstring& lockfilepath) //throw FileError { #ifdef ZEN_WIN #ifdef TODO_MinFFS_ActivatePriviledge try { activatePrivilege(SE_BACKUP_NAME); } catch (const FileError&) {} try { activatePrivilege(SE_RESTORE_NAME); } catch (const FileError&) {} #endif//TODO_MinFFS_ActivatePriviledge const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilepath).c_str(), //_In_ LPCTSTR lpFileName, //use both when writing over network, see comment in file_io.cpp GENERIC_READ | GENERIC_WRITE, //_In_ DWORD dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //_In_ DWORD dwShareMode, nullptr, //_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, CREATE_NEW, //_In_ DWORD dwCreationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, //_In_ DWORD dwFlagsAndAttributes, nullptr); //_In_opt_ HANDLE hTemplateFile if (fileHandle == INVALID_HANDLE_VALUE) { const DWORD ec = ::GetLastError(); //copy before directly/indirectly making other system calls! if (ec == ERROR_FILE_EXISTS || //confirmed to be used ec == ERROR_ALREADY_EXISTS) //comment on msdn claims, this one is used on Windows Mobile 6 return false; throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(lockfilepath)), formatSystemError(L"CreateFile", ec)); } ScopeGuard guardLockFile = zen::makeGuard([&] { removeFile(lockfilepath); }); FileOutput fileOut(fileHandle, lockfilepath); //pass handle ownership //be careful to avoid CreateFile() + CREATE_ALWAYS on a hidden file -> see file_io.cpp //=> we don't need it that badly //::SetFileAttributes(applyLongPathPrefix(lockfilepath).c_str(), FILE_ATTRIBUTE_HIDDEN); //(try to) hide it #elif defined ZEN_LINUX || defined ZEN_MAC const mode_t oldMask = ::umask(0); //important: we want the lock file to have exactly the permissions specified ZEN_ON_SCOPE_EXIT(::umask(oldMask)); //O_EXCL contains a race condition on NFS file systems: http://linux.die.net/man/2/open const int fileHandle = ::open(lockfilepath.c_str(), O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (fileHandle == -1) { if (errno == EEXIST) return false; else THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(lockfilepath)), L"open"); } ScopeGuard guardLockFile = zen::makeGuard([&] { removeFile(lockfilepath); }); FileOutput fileOut(fileHandle, lockfilepath); //pass handle ownership #endif //write housekeeping info: user, process info, lock GUID ByteArray binStream = [&] { MemStreamOut streamOut; LockInformation(FromCurrentProcess()).toStream(streamOut); return streamOut.ref(); }(); if (!binStream.empty()) fileOut.write(&*binStream.begin(), binStream.size()); //throw FileError guardLockFile.dismiss(); //lockfile created successfully return true; }
void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) { if (chapter < 0) chapter = !_vm->isIHNMDemo() ? 8 : 7; _vm->_script->_globalVoiceLUT.clear(); ResourceContext *resourceContext; ResourceContext *soundContext; uint i; resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (resourceContext == NULL) { error("Resource::loadGlobalResources() resource context not found"); } soundContext = _vm->_resource->getContext(GAME_SOUNDFILE); if (soundContext == NULL) { error("Resource::loadGlobalResources() sound context not found"); } ByteArray resourceData; if (!_vm->isIHNMDemo()) { _vm->_resource->loadResource(resourceContext, metaResourceTable[chapter], resourceData); } else { _vm->_resource->loadResource(resourceContext, metaResourceTableDemo[chapter], resourceData); } if (resourceData.empty()) { error("Resource::loadGlobalResources wrong metaResource"); } { ByteArrayReadStreamEndian metaS(resourceData); _metaResource.sceneIndex = metaS.readSint16LE(); _metaResource.objectCount = metaS.readSint16LE(); _metaResource.objectsStringsResourceID = metaS.readSint32LE(); _metaResource.inventorySpritesID = metaS.readSint32LE(); _metaResource.mainSpritesID = metaS.readSint32LE(); _metaResource.objectsResourceID = metaS.readSint32LE(); _metaResource.actorCount = metaS.readSint16LE(); _metaResource.actorsStringsResourceID = metaS.readSint32LE(); _metaResource.actorsResourceID = metaS.readSint32LE(); _metaResource.protagFaceSpritesID = metaS.readSint32LE(); _metaResource.field_22 = metaS.readSint32LE(); _metaResource.field_26 = metaS.readSint16LE(); _metaResource.protagStatesCount = metaS.readSint16LE(); _metaResource.protagStatesResourceID = metaS.readSint32LE(); _metaResource.cutawayListResourceID = metaS.readSint32LE(); _metaResource.songTableID = metaS.readSint32LE(); } _vm->_actor->loadActorList(actorsEntrance, _metaResource.actorCount, _metaResource.actorsResourceID, _metaResource.protagStatesCount, _metaResource.protagStatesResourceID); _vm->_actor->_protagonist->_sceneNumber = _metaResource.sceneIndex; _vm->_actor->_objectsStrings.clear(); _vm->_resource->loadResource(resourceContext, _metaResource.objectsStringsResourceID, resourceData); _vm->loadStrings(_vm->_actor->_objectsStrings, resourceData); if (uint(chapter) >= _vm->_sndRes->_fxTableIDs.size()) { error("Chapter ID exceeds fxTableIDs length"); } debug(0, "Going to read %d of %d", chapter, _vm->_sndRes->_fxTableIDs[chapter]); _vm->_resource->loadResource(soundContext, _vm->_sndRes->_fxTableIDs[chapter], resourceData); if (resourceData.empty()) { error("Resource::loadGlobalResources Can't load sound effects for current track"); } _vm->_sndRes->_fxTable.resize(resourceData.size() / 4); { ByteArrayReadStreamEndian fxS(resourceData); for (i = 0; i < _vm->_sndRes->_fxTable.size(); i++) { _vm->_sndRes->_fxTable[i].res = fxS.readSint16LE(); _vm->_sndRes->_fxTable[i].vol = fxS.readSint16LE(); } } _vm->_interface->_defPortraits.clear(); _vm->_sprite->loadList(_metaResource.protagFaceSpritesID, _vm->_interface->_defPortraits); _vm->_actor->_actorsStrings.clear(); _vm->_resource->loadResource(resourceContext, _metaResource.actorsStringsResourceID, resourceData); _vm->loadStrings(_vm->_actor->_actorsStrings, resourceData); _vm->_sprite->_inventorySprites.clear(); _vm->_sprite->loadList(_metaResource.inventorySpritesID, _vm->_sprite->_inventorySprites); _vm->_sprite->_mainSprites.clear(); _vm->_sprite->loadList(_metaResource.mainSpritesID, _vm->_sprite->_mainSprites); _vm->_actor->loadObjList(_metaResource.objectCount, _metaResource.objectsResourceID); _vm->_resource->loadResource(resourceContext, _metaResource.cutawayListResourceID, resourceData); if (resourceData.empty()) { error("Resource::loadGlobalResources Can't load cutaway list"); } _vm->_anim->loadCutawayList(resourceData); if (_metaResource.songTableID > 0) { _vm->_resource->loadResource(resourceContext, _metaResource.songTableID, resourceData); if (chapter == 6) { if (resourceData.size() < (uint(actorsEntrance) * 4 + 4)) { error("Resource::loadGlobalResources chapter 6 has wrong resource"); } int32 id = READ_LE_UINT32(&resourceData[actorsEntrance * 4]); _vm->_resource->loadResource(resourceContext, id, resourceData); } if (resourceData.empty()) { error("Resource::loadGlobalResources Can't load songs list for current track"); } _vm->_music->_songTable.resize(resourceData.size() / 4); ByteArrayReadStreamEndian songS(resourceData); for (i = 0; i < _vm->_music->_songTable.size(); i++) _vm->_music->_songTable[i] = songS.readSint32LE(); } else { // The IHNM demo has a fixed music track and doesn't load a song table _vm->_music->setVolume(_vm->_musicVolume, 1); _vm->_music->play(3, MUSIC_LOOP); } int voiceLUTResourceID = 0; if (chapter != 7) { int voiceBank = (chapter == 8) ? 0 : chapter; _vm->_sndRes->setVoiceBank(voiceBank); voiceLUTResourceID = 22 + voiceBank; } else { // IHNM demo _vm->_sndRes->setVoiceBank(0); voiceLUTResourceID = 17; } if (voiceLUTResourceID) { _vm->_resource->loadResource(resourceContext, voiceLUTResourceID, resourceData); _vm->_script->loadVoiceLUT(_vm->_script->_globalVoiceLUT, resourceData); } _vm->_spiritualBarometer = 0; _vm->_scene->setChapterNumber(chapter); }
void Sprite::loadList(int resourceId, SpriteList &spriteList) { SpriteInfo *spriteInfo; ByteArray spriteListData; uint16 oldSpriteCount; uint16 newSpriteCount; uint16 spriteCount; uint i; int outputLength, inputLength; uint32 offset; const byte *spritePointer; const byte *spriteDataPointer; _vm->_resource->loadResource(_spriteContext, resourceId, spriteListData); if (spriteListData.empty()) { return; } ByteArrayReadStreamEndian readS(spriteListData, _spriteContext->isBigEndian()); spriteCount = readS.readUint16(); debug(9, "Sprites: %d", spriteCount); oldSpriteCount = spriteList.size(); newSpriteCount = oldSpriteCount + spriteCount; spriteList.resize(newSpriteCount); bool bigHeader = _vm->getGameId() == GID_IHNM || _vm->isMacResources(); for (i = oldSpriteCount; i < spriteList.size(); i++) { spriteInfo = &spriteList[i]; if (bigHeader) offset = readS.readUint32(); else offset = readS.readUint16(); if (offset >= spriteListData.size()) { // ITE Mac demos throw this warning warning("Sprite::loadList offset exceeded"); spriteList.resize(i); return; } spritePointer = spriteListData.getBuffer(); spritePointer += offset; if (bigHeader) { Common::MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian()); spriteInfo->xAlign = readS2.readSint16(); spriteInfo->yAlign = readS2.readSint16(); spriteInfo->width = readS2.readUint16(); spriteInfo->height = readS2.readUint16(); spriteDataPointer = spritePointer + readS2.pos(); } else { Common::MemoryReadStreamEndian readS2(spritePointer, 4, false); spriteInfo->xAlign = readS2.readSByte(); spriteInfo->yAlign = readS2.readSByte(); spriteInfo->width = readS2.readByte(); spriteInfo->height = readS2.readByte(); spriteDataPointer = spritePointer + readS2.pos(); } outputLength = spriteInfo->width * spriteInfo->height; inputLength = spriteListData.size() - (spriteDataPointer - spriteListData.getBuffer()); spriteInfo->decodedBuffer.resize(outputLength); if (outputLength > 0) { decodeRLEBuffer(spriteDataPointer, inputLength, outputLength); byte *dst = &spriteInfo->decodedBuffer.front(); #ifdef ENABLE_IHNM // IHNM sprites are upside-down, for reasons which i can only // assume are perverse. To simplify things, flip them now. Not // at drawing time. if (_vm->getGameId() == GID_IHNM) { byte *src = &_decodeBuf[spriteInfo->width * (spriteInfo->height - 1)]; for (int j = 0; j < spriteInfo->height; j++) { memcpy(dst, src, spriteInfo->width); src -= spriteInfo->width; dst += spriteInfo->width; } } else #endif memcpy(dst, &_decodeBuf.front(), outputLength); } } }