Пример #1
0
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
        }
    }
}
Пример #2
0
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;
}
Пример #3
0
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);
}
Пример #4
0
/**@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;
}
Пример #5
0
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
	}
}
Пример #6
0
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;
}
Пример #7
0
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();
		}
	}
}
Пример #8
0
/**@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;
}
Пример #9
0
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);
}
Пример #10
0
// 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());
	}
}
Пример #11
0
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);
}
Пример #12
0
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]);
	}
}
Пример #13
0
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;
    }
}
Пример #14
0
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;
}
Пример #15
0
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);
}
Пример #16
0
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);
		}
	}
}