Exemplo n.º 1
0
static Status load_sys_cursor(const PIVFS& vfs, const VfsPath& pathname, int hx, int hy, sys_cursor* cursor)
{
#if !ALLOW_SYS_CURSOR
	UNUSED2(vfs);
	UNUSED2(pathname);
	UNUSED2(hx);
	UNUSED2(hy);
	UNUSED2(cursor);

	return ERR::FAIL;
#else
	shared_ptr<u8> file; size_t fileSize;
	RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, file, fileSize));

	Tex t;
	RETURN_STATUS_IF_ERR(t.decode(file, fileSize));

	// convert to required BGRA format.
	const size_t flags = (t.m_Flags | TEX_BGR) & ~TEX_DXT;
	RETURN_STATUS_IF_ERR(t.transform_to(flags));
	void* bgra_img = t.get_data();
	if(!bgra_img)
		WARN_RETURN(ERR::FAIL);

	RETURN_STATUS_IF_ERR(sys_cursor_create((int)t.m_Width, (int)t.m_Height, bgra_img, hx, hy, cursor));
	return INFO::OK;
#endif
}
Exemplo n.º 2
0
Status OpenOggNonstream(const PIVFS& vfs, const VfsPath& pathname, OggStreamPtr& stream)
{
	shared_ptr<u8> contents;
	size_t size;
	RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, contents, size));

	shared_ptr<OggStreamImpl<VorbisBufferAdapter> > tmp(new OggStreamImpl<VorbisBufferAdapter>(VorbisBufferAdapter(contents, size)));
	RETURN_STATUS_IF_ERR(tmp->Open());
	stream = tmp;
	return INFO::OK;
}
Exemplo n.º 3
0
void NextNumberedFilename(const PIVFS& fs, const VfsPath& pathnameFormat, size_t& nextNumber, VfsPath& nextPathname)
{
	// (first call only:) scan directory and set nextNumber according to
	// highest matching filename found. this avoids filling "holes" in
	// the number series due to deleted files, which could be confusing.
	// example: add 1st and 2nd; [exit] delete 1st; [restart]
	// add 3rd -> without this measure it would get number 1, not 3. 
	if(nextNumber == 0)
	{
		const VfsPath nameFormat = pathnameFormat.Filename();
		const VfsPath path = pathnameFormat.Parent()/"";

		size_t maxNumber = 0;
		CFileInfos files;
		fs->GetDirectoryEntries(path, &files, 0);
		for(size_t i = 0; i < files.size(); i++)
		{
			int number;
			if(swscanf_s(files[i].Name().string().c_str(), nameFormat.string().c_str(), &number) == 1)
				maxNumber = std::max(size_t(number), maxNumber);
		}

		nextNumber = maxNumber+1;
	}

	// now increment number until that file doesn't yet exist.
	// this is fairly slow, but typically only happens once due
	// to scan loop above. (we still need to provide for looping since
	// someone may have added files in the meantime)
	// we don't bother with binary search - this isn't a bottleneck.
	do
	{
		wchar_t pathnameBuf[PATH_MAX];
		swprintf_s(pathnameBuf, ARRAY_SIZE(pathnameBuf), pathnameFormat.string().c_str(), nextNumber++);
		nextPathname = pathnameBuf;
	}
	while(fs->GetFileInfo(nextPathname, 0) == INFO::OK);
}
Exemplo n.º 4
0
Status ReloadChangedFiles()
{
	std::vector<DirWatchNotification> notifications;
	RETURN_STATUS_IF_ERR(dir_watch_Poll(notifications));
	for(size_t i = 0; i < notifications.size(); i++)
	{
		if(!CanIgnore(notifications[i]))
		{
			VfsPath pathname;
			RETURN_STATUS_IF_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
			RETURN_STATUS_IF_ERR(g_VFS->Invalidate(pathname));

			// Tell each hotloadable system about this file change:

			RETURN_STATUS_IF_ERR(g_GUI->ReloadChangedFiles(pathname));

			for (size_t j = 0; j < g_ReloadFuncs.size(); ++j)
				g_ReloadFuncs[j].first(g_ReloadFuncs[j].second, pathname);

			RETURN_STATUS_IF_ERR(h_reload(g_VFS, pathname));
		}
	}
	return INFO::OK;
}
Exemplo n.º 5
0
Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter, VfsPaths& pathnames)
{
	std::vector<CFileInfo> files;
	RETURN_STATUS_IF_ERR(fs->GetDirectoryEntries(path, &files, 0));

	pathnames.clear();
	pathnames.reserve(files.size());

	for(size_t i = 0; i < files.size(); i++)
	{
		if(match_wildcard(files[i].Name().string().c_str(), filter))
			pathnames.push_back(path / files[i].Name());
	}

	return INFO::OK;
}
Exemplo n.º 6
0
bool XMLWriter_File::StoreVFS(const PIVFS& vfs, const VfsPath& pathname)
{
	if (m_LastElement) debug_warn(L"ERROR: Saving XML while an element is still open");

	const size_t size = m_Data.length();
	shared_ptr<u8> data;
	AllocateAligned(data, size, maxSectorSize);
	memcpy(data.get(), m_Data.data(), size);
	Status ret = vfs->CreateFile(pathname, data, size);
	if (ret < 0)
	{
		LOGERROR(L"Error saving XML data through VFS: %lld '%ls'", (long long)ret, pathname.string().c_str());
		return false;
	}
	return true;
}
Exemplo n.º 7
0
PSRETURN CVFSFile::Load(const PIVFS& vfs, const VfsPath& filename)
{
	// Load should never be called more than once, so complain
	if (m_Buffer)
	{
		DEBUG_WARN_ERR(ERR::LOGIC);
		return PSRETURN_CVFSFile_AlreadyLoaded;
	}

	Status ret = vfs->LoadFile(filename, m_Buffer, m_BufferSize);
	if (ret != INFO::OK)
	{
		LOGERROR(L"CVFSFile: file %ls couldn't be opened (vfs_load: %lld)", filename.string().c_str(), ret);
		return PSRETURN_CVFSFile_LoadFailed;
	}

	return PSRETURN_OK;
}
Exemplo n.º 8
0
// basename is e.g. "console"; the files are "fonts/console.fnt" and "fonts/console.png"
// [10..70ms]
static Status UniFont_reload(UniFont* f, const PIVFS& vfs, const VfsPath& basename, Handle UNUSED(h))
{
	// already loaded
	if(f->ht > 0)
		return INFO::OK;

	f->glyphs = new glyphmap();

	const VfsPath path(L"fonts/");

	// Read font definition file into a stringstream
	shared_ptr<u8> buf; size_t size;
	const VfsPath fntName(basename.ChangeExtension(L".fnt"));
	RETURN_STATUS_IF_ERR(vfs->LoadFile(path / fntName, buf, size));	// [cumulative for 12: 36ms]
	std::istringstream FNTStream(std::string((const char*)buf.get(), size));

	int Version;
	FNTStream >> Version;
	if (Version < 100 || Version > 101) // Make sure this is from a recent version of the font builder
		WARN_RETURN(ERR::FAIL);

	int TextureWidth, TextureHeight;
	FNTStream >> TextureWidth >> TextureHeight;

	GLenum fmt_ovr = GL_ALPHA;
	if (Version >= 101)
	{
		std::string Format;
		FNTStream >> Format;
		if (Format == "rgba")
			fmt_ovr = GL_RGBA;
		else if (Format == "a")
			fmt_ovr = GL_ALPHA;
		else
			debug_warn(L"Invalid .fnt format string");
	}
Exemplo n.º 9
0
Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags)
{
	// (declare here to avoid reallocations)
	CFileInfos files;
	DirectoryNames subdirectoryNames;

	// (a FIFO queue is more efficient than recursion because it uses less
	// stack space and avoids seeks due to breadth-first traversal.)
	std::queue<VfsPath> pendingDirectories;
	pendingDirectories.push(startPath/"");
	while(!pendingDirectories.empty())
	{
		const VfsPath& path = pendingDirectories.front();

		RETURN_STATUS_IF_ERR(fs->GetDirectoryEntries(path, &files, &subdirectoryNames));

		for(size_t i = 0; i < files.size(); i++)
		{
			const CFileInfo fileInfo = files[i];
			if(!match_wildcard(fileInfo.Name().string().c_str(), pattern))
				continue;

			const VfsPath pathname(path / fileInfo.Name());	// (CFileInfo only stores the name)
			RETURN_STATUS_IF_ERR(cb(pathname, fileInfo, cbData));
		}

		if(!(flags & DIR_RECURSIVE))
			break;

		for(size_t i = 0; i < subdirectoryNames.size(); i++)
			pendingDirectories.push(path / subdirectoryNames[i]/"");
		pendingDirectories.pop();
	}

	return INFO::OK;
}
Exemplo n.º 10
0
/**
 * Returns a JS object containing a listing of available mods that
 * have a modname.json file in their modname folder. The returned
 * object looks like { modname1: json1, modname2: json2, ... } where
 * jsonN is the content of the modnameN/modnameN.json file as a JS
 * object.
 *
 * @return JS object with available mods as the keys of the modname.json
 *         properties.
 */
JS::Value JSI_Mod::GetAvailableMods(ScriptInterface::CxPrivate* pCxPrivate)
{
	ScriptInterface* scriptInterface = pCxPrivate->pScriptInterface;
	JSContext* cx = scriptInterface->GetContext();
	JSAutoRequest rq(cx);
	JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));

	const Paths paths(g_args);

	// loop over all possible paths
	OsPath modPath = paths.RData()/"mods";
	OsPath modUserPath = paths.UserData()/"mods";

	DirectoryNames modDirs;
	DirectoryNames modDirsUser;

	GetDirectoryEntries(modPath, NULL, &modDirs);
	// Sort modDirs so that we can do a fast lookup below
	std::sort(modDirs.begin(), modDirs.end());

	PIVFS vfs = CreateVfs(1); // No cache needed; TODO but 0 crashes

	for (DirectoryNames::iterator iter = modDirs.begin(); iter != modDirs.end(); ++iter)
	{
		vfs->Clear();
		if (vfs->Mount(L"", modPath / *iter, VFS_MOUNT_MUST_EXIST) < 0)
			continue;

		CVFSFile modinfo;
		if (modinfo.Load(vfs, L"mod.json", false) != PSRETURN_OK)
			continue;

		JS::RootedValue json(cx);
		if (!scriptInterface->ParseJSON(modinfo.GetAsString(), &json))
			continue;

		// Valid mod, add it to our structure
		JS_SetProperty(cx, obj, utf8_from_wstring(iter->string()).c_str(), json);
	}

	GetDirectoryEntries(modUserPath, NULL, &modDirsUser);
	bool dev = InDevelopmentCopy();

	for (DirectoryNames::iterator iter = modDirsUser.begin(); iter != modDirsUser.end(); ++iter)
	{
		// If we are in a dev copy we do not mount mods in the user mod folder that
		// are already present in the mod folder, thus we skip those here.
		if (dev && std::binary_search(modDirs.begin(), modDirs.end(), *iter))
			continue;

		vfs->Clear();
		if (vfs->Mount(L"", modUserPath / *iter, VFS_MOUNT_MUST_EXIST) < 0)
			continue;

		CVFSFile modinfo;
		if (modinfo.Load(vfs, L"mod.json", false) != PSRETURN_OK)
			continue;

		JS::RootedValue json(cx);
		if (!scriptInterface->ParseJSON(modinfo.GetAsString(), &json))
			continue;

		// Valid mod, add it to our structure
		JS_SetProperty(cx, obj, utf8_from_wstring(iter->string()).c_str(), json);
	}

	return JS::ObjectValue(*obj);
}
Exemplo n.º 11
0
bool VfsFileExists(const VfsPath& pathname)
{
	return g_VFS->GetFileInfo(pathname, 0) == INFO::OK;
}