コード例 #1
0
ファイル: TemplateLoader.cpp プロジェクト: Rektosauros/0ad
std::vector<std::string> CTemplateLoader::FindTemplates(const std::string& path, bool includeSubdirectories, ETemplatesType templatesType)
{
	std::vector<std::string> templates;

	Status ok;
	VfsPath templatePath;

	if (templatesType == SIMULATION_TEMPLATES || templatesType == ALL_TEMPLATES)
	{
		templatePath = VfsPath(TEMPLATE_ROOT) / path;
		if (includeSubdirectories)
			ok = vfs::ForEachFile(g_VFS, templatePath, AddToTemplates, (uintptr_t)&templates, L"*.xml", vfs::DIR_RECURSIVE);
		else
			ok = vfs::ForEachFile(g_VFS, templatePath, AddToTemplates, (uintptr_t)&templates, L"*.xml");
		WARN_IF_ERR(ok);
	}
	if (templatesType == ACTOR_TEMPLATES || templatesType == ALL_TEMPLATES)
	{
		templatePath = VfsPath(ACTOR_ROOT) / path;
		if (includeSubdirectories)
			ok = vfs::ForEachFile(g_VFS, templatePath, AddActorToTemplates, (uintptr_t)&templates, L"*.xml", vfs::DIR_RECURSIVE);
		else
			ok = vfs::ForEachFile(g_VFS, templatePath, AddActorToTemplates, (uintptr_t)&templates, L"*.xml");
		WARN_IF_ERR(ok);
	}

	if (templatesType != SIMULATION_TEMPLATES && templatesType != ACTOR_TEMPLATES && templatesType != ALL_TEMPLATES)
		LOGERROR("Undefined template type (valid: all, simulation, actor)");

	return templates;
}
コード例 #2
0
ファイル: Paths.cpp プロジェクト: Valvador/PyroSpaceFork
/*static*/ OsPath Paths::Root(const OsPath& argv0)
{
#if OS_ANDROID
	return OsPath("/sdcard/0ad"); // TODO: this is kind of bogus
#else

	// get full path to executable
	OsPath pathname = sys_ExecutablePathname();	// safe, but requires OS-specific implementation
	if(pathname.empty())	// failed, use argv[0] instead
	{
		errno = 0;
		pathname = wrealpath(argv0);
		if(pathname.empty())
			WARN_IF_ERR(StatusFromErrno());
	}

	// make sure it's valid
	if(!FileExists(pathname))
	{
		LOGERROR(L"Cannot find executable (expected at '%ls')", pathname.string().c_str());
		WARN_IF_ERR(StatusFromErrno());
	}

	for(size_t i = 0; i < 2; i++)	// remove "system/name.exe"
		pathname = pathname.Parent();
	return pathname;

#endif
}
コード例 #3
0
	void ReadEntry(const VfsPath& pathname, const FileInfo& fileInfo, PIArchiveFile archiveFile)
	{
		if (pathname == L"metadata.json" && m_Metadata)
		{
			std::string buffer;
			buffer.resize(fileInfo.Size());
			WARN_IF_ERR(archiveFile->Load("", DummySharedPtr((u8*)buffer.data()), buffer.size()));
			*m_Metadata = m_ScriptInterface.ParseJSON(buffer);
		}
		else if (pathname == L"simulation.dat" && m_SavedState)
		{
			m_SavedState->resize(fileInfo.Size());
			WARN_IF_ERR(archiveFile->Load("", DummySharedPtr((u8*)m_SavedState->data()), m_SavedState->size()));
		}
	}
コード例 #4
0
ファイル: wpthread.cpp プロジェクト: 2asoft/0ad
static void call_tls_dtors()
{
again:
	bool had_valid_tls = false;

	// for each registered dtor: (call order unspecified by SUSv3)
	for(size_t i = 0; i < MAX_DTORS; i++)
	{
		// is slot #i in use?
		void (*dtor)(void*) = dtors[i].dtor;
		if(!dtor)
			continue;

		// clear slot and call dtor with its previous value.
		const pthread_key_t key = dtors[i].key;
		void* tls = pthread_getspecific(key);
		if(tls)
		{
			WARN_IF_ERR(pthread_setspecific(key, 0));

			dtor(tls);
			had_valid_tls = true;
		}
	}

	// rationale: SUSv3 says we're allowed to loop infinitely. we do so to
	// expose any dtor bugs - this shouldn't normally happen.
	if(had_valid_tls)
		goto again;
}
コード例 #5
0
ファイル: wpthread.cpp プロジェクト: 2asoft/0ad
int pthread_key_create(pthread_key_t* key, void (*dtor)(void*))
{
	DWORD idx = TlsAlloc();
	if(idx == TLS_OUT_OF_INDEXES)
		return -ENOMEM;

	ENSURE(idx < TLS_LIMIT);
	*key = (pthread_key_t)idx;

	// acquire a free dtor slot
	size_t i;
	for(i = 0; i < MAX_DTORS; i++)
	{
		if(cpu_CAS((volatile intptr_t*)&dtors[i].dtor, (intptr_t)0, (intptr_t)dtor))
			goto have_slot;
	}

	// not enough slots; we have a valid key, but its dtor won't be called.
	WARN_IF_ERR(ERR::LIMIT);
	return -1;

have_slot:
	dtors[i].key = *key;
	return 0;
}
コード例 #6
0
ファイル: input.cpp プロジェクト: krichter722/0ad
void in_add_handler(InHandler handler)
{
	ENSURE(handler);

	if(handler_stack_top >= MAX_HANDLERS)
		WARN_IF_ERR(ERR::LIMIT);

	handler_stack[handler_stack_top++] = handler;
}
コード例 #7
0
ファイル: Paths.cpp プロジェクト: Marlinc/0ad
/*static*/ OsPath Paths::Root(const OsPath& argv0)
{
	// get full path to executable
	OsPath pathname = sys_ExecutablePathname();	// safe, but requires OS-specific implementation
	if(pathname.empty())	// failed, use argv[0] instead
	{
		errno = 0;
		pathname = wrealpath(argv0);
		if(pathname.empty())
			WARN_IF_ERR(StatusFromErrno());
	}

	// make sure it's valid
	if(!FileExists(pathname))
		WARN_IF_ERR(StatusFromErrno());

	for(size_t i = 0; i < 2; i++)	// remove "system/name.exe"
		pathname = pathname.Parent();
	return pathname;
}
コード例 #8
0
ファイル: wcursor.cpp プロジェクト: righnatios/0ad
Status sys_cursor_free(sys_cursor cursor)
{
	// bail now to prevent potential confusion below; there's nothing to do.
	if(!cursor)
		return INFO::OK;

	// if the cursor being freed is active, restore the default arrow
	// (just for safety).
	if(cursor_from_HCURSOR(GetCursor()) == cursor)
		WARN_IF_ERR(sys_cursor_set(0));

	if(!DestroyIcon(HICON_from_cursor(cursor)))
		WARN_RETURN(StatusFromWin());
	return INFO::OK;
}
コード例 #9
0
std::vector<CScriptValRooted> SavedGames::GetSavedGames(ScriptInterface& scriptInterface)
{
	TIMER(L"GetSavedGames");

	std::vector<CScriptValRooted> games;

	Status err;

	VfsPaths pathnames;
	err = vfs::GetPathnames(g_VFS, "saves/", L"*.0adsave", pathnames);
	WARN_IF_ERR(err);

	for (size_t i = 0; i < pathnames.size(); ++i)
	{
		OsPath realPath;
		err = g_VFS->GetRealPath(pathnames[i], realPath);
		if (err < 0)
		{
			DEBUG_WARN_ERR(err);
			continue; // skip this file
		}

		PIArchiveReader archiveReader = CreateArchiveReader_Zip(realPath);
		if (!archiveReader)
		{
			// Triggered by e.g. the file being open in another program
			LOGWARNING(L"Failed to read saved game '%ls'", realPath.string().c_str());
			continue; // skip this file
		}

		CScriptValRooted metadata;
		CGameLoader loader(scriptInterface, &metadata, NULL);
		err = archiveReader->ReadEntries(CGameLoader::ReadEntryCallback, (uintptr_t)&loader);
		if (err < 0)
		{
			DEBUG_WARN_ERR(err);
			continue; // skip this file
		}

		CScriptValRooted game;
		scriptInterface.Eval("({})", game);
		scriptInterface.SetProperty(game.get(), "id", pathnames[i].Basename());
		scriptInterface.SetProperty(game.get(), "metadata", metadata);
		games.push_back(game);
	}

	return games;
}
コード例 #10
0
ファイル: tex_jpg.cpp プロジェクト: righnatios/0ad
static Status jpg_encode_impl(Tex* t, jpeg_compress_struct* cinfo, DynArray* da)
{
	dst_prepare(cinfo, da);

	// describe image format
	// required:
	cinfo->image_width = (JDIMENSION)t->m_Width;
	cinfo->image_height = (JDIMENSION)t->m_Height;
	cinfo->input_components = (int)t->m_Bpp / 8;
	cinfo->in_color_space = (t->m_Bpp == 8)? JCS_GRAYSCALE : JCS_RGB;
	// defaults depend on cinfo->in_color_space already having been set!
	jpeg_set_defaults(cinfo);
	// (add optional settings, e.g. quality, here)

	// TRUE ensures that we will write a complete interchange-JPEG file.
	// don't change unless you are very sure of what you're doing.
	jpeg_start_compress(cinfo, TRUE);

	// if BGR, convert to RGB.
	WARN_IF_ERR(t->transform_to(t->m_Flags & ~TEX_BGR));

	const size_t pitch = t->m_Width * t->m_Bpp / 8;
	u8* data = t->get_data();
	std::vector<RowPtr> rows = tex_codec_alloc_rows(data, t->m_Height, pitch, t->m_Flags, TEX_TOP_DOWN);

	// could use cinfo->output_scanline to keep track of progress,
	// but we need to count lines_left anyway (paranoia).
	JSAMPARRAY row = (JSAMPARRAY)&rows[0];
	JDIMENSION lines_left = (JDIMENSION)t->m_Height;
	while(lines_left != 0)
	{
		JDIMENSION lines_read = jpeg_write_scanlines(cinfo, row, lines_left);
		row += lines_read;
		lines_left -= lines_read;

		// we've decoded in-place; no need to further process
	}

	jpeg_finish_compress(cinfo);

	Status ret = INFO::OK;
	if(cinfo->err->num_warnings != 0)
		ret = WARN::TEX_INVALID_DATA;

	return ret;
}
コード例 #11
0
ファイル: Config.cpp プロジェクト: Gallaecio/0ad
// Fill in the globals from the config files.
static void LoadGlobals()
{
    CFG_GET_USER_VAL("vsync", Bool, g_VSync);

    CFG_GET_USER_VAL("nos3tc", Bool, g_NoGLS3TC);
    CFG_GET_USER_VAL("noautomipmap", Bool, g_NoGLAutoMipmap);
    CFG_GET_USER_VAL("novbo", Bool, g_NoGLVBO);
    CFG_GET_USER_VAL("pauseonfocusloss", Bool, g_PauseOnFocusLoss);
    CFG_GET_USER_VAL("shadows", Bool, g_Shadows);
    CFG_GET_USER_VAL("shadowpcf", Bool, g_ShadowPCF);
    CFG_GET_USER_VAL("fancywater", Bool, g_FancyWater);
    CFG_GET_USER_VAL("renderpath", String, g_RenderPath);

    CFG_GET_USER_VAL("lodbias", Float, g_LodBias);

    float gain = -1.0f;
    CFG_GET_USER_VAL("sound.mastergain", Float, gain);
    if(gain >= 0.0f)
        WARN_IF_ERR(snd_set_master_gain(gain));
}
コード例 #12
0
ファイル: wpthread.cpp プロジェクト: 2asoft/0ad
// wait until semaphore is locked or a message arrives. non-portable.
//
// background: on Win32, UI threads must periodically pump messages, or
// else deadlock may result (see WaitForSingleObject docs). that entails
// avoiding any blocking functions. when event waiting is needed,
// one cheap workaround would be to time out periodically and pump messages.
// that would work, but either wastes CPU time waiting, or introduces
// message latency. to avoid this, we provide an API similar to sem_wait and
// sem_timedwait that gives MsgWaitForMultipleObjects functionality.
//
// return value: 0 if the semaphore has been locked (SUS terminology),
// -1 otherwise. errno differentiates what happened: ETIMEDOUT if a
// message arrived (this is to ease switching between message waiting and
// periodic timeout), or an error indication.
int sem_msgwait_np(sem_t* sem)
{
	HANDLE h = HANDLE_from_sem_t(sem);
	DWORD ret = MsgWaitForMultipleObjects(1, &h, FALSE, INFINITE, QS_ALLEVENTS);
	// semaphore is signalled
	if(ret == WAIT_OBJECT_0)
		return 0;

	// something else:
	// .. message came up
	if(ret == WAIT_OBJECT_0+1)
		errno = ETIMEDOUT;
	// .. error
	else
	{
		errno = EINVAL;
		WARN_IF_ERR(ERR::FAIL);
	}
	return -1;
}
コード例 #13
0
ファイル: wpthread.cpp プロジェクト: 2asoft/0ad
// helper function for sem_timedwait - multiple return is convenient.
// converts an absolute timeout deadline into a relative length for use with
// WaitForSingleObject with the following peculiarity: if the semaphore
// could be locked immediately, abs_timeout must be ignored (see SUS).
// to that end, we return a timeout of 0 and pass back <valid> = false if
// abs_timeout is invalid.
static DWORD calc_timeout_length_ms(const struct timespec* abs_timeout,
	bool& timeout_is_valid)
{
	timeout_is_valid = false;

	if(!abs_timeout)
		return 0;

	// SUS requires we fail if not normalized
	if(abs_timeout->tv_nsec >= 1000000000)
		return 0;

	struct timespec cur_time;
	if(clock_gettime(CLOCK_REALTIME, &cur_time) != 0)
		return 0;

	timeout_is_valid = true;

	// convert absolute deadline to relative length, rounding up to [ms].
	// note: use i64 to avoid overflow in multiply.
	const i64  ds = abs_timeout->tv_sec  - cur_time.tv_sec;
	const long dn = abs_timeout->tv_nsec - cur_time.tv_nsec;
	i64 length_ms = ds*1000 + (dn+500000)/1000000;
	// .. deadline already reached; we'll still attempt to lock once
	if(length_ms < 0)
		return 0;
	// .. length > 49 days => result won't fit in 32 bits. most likely bogus.
	//    note: we're careful to avoid returning exactly -1 since
	//          that's the Win32 INFINITE value.
	if(length_ms >= 0xFFFFFFFF)
	{
		WARN_IF_ERR(ERR::LIMIT);
		length_ms = 0xfffffffe;
	}
	return (DWORD)(length_ms & 0xFFFFFFFF);
}
コード例 #14
0
ファイル: wpthread.cpp プロジェクト: 2asoft/0ad
void* pthread_getspecific(pthread_key_t key)
{
	DWORD idx = (DWORD)key;
	ENSURE(idx < TLS_LIMIT);

	// TlsGetValue sets last error to 0 on success (boo).
	// we don't want this to hide previous errors, so it's restored below.
	DWORD last_err = GetLastError();

	void* data = TlsGetValue(idx);

	// no error
	if(GetLastError() == 0)
	{
		// we care about performance here. SetLastError is low overhead,
		// but last error = 0 is expected.
		if(last_err != 0)
			SetLastError(last_err);
	}
	else
		WARN_IF_ERR(ERR::FAIL);

	return data;
}
コード例 #15
0
ファイル: Util.cpp プロジェクト: krichter722/0ad
// Similar to WriteScreenshot, but generates an image of size 640*tiles x 480*tiles.
void WriteBigScreenshot(const VfsPath& extension, int tiles)
{
    // If the game hasn't started yet then use WriteScreenshot to generate the image.
    if(g_Game == NULL) {
        WriteScreenshot(L".bmp");
        return;
    }

    // get next available numbered filename
    // note: %04d -> always 4 digits, so sorting by filename works correctly.
    const VfsPath basenameFormat(L"screenshots/screenshot%04d");
    const VfsPath filenameFormat = basenameFormat.ChangeExtension(extension);
    VfsPath filename;
    vfs::NextNumberedFilename(g_VFS, filenameFormat, s_nextScreenshotNumber, filename);

    // Slightly ugly and inflexible: Always draw 640*480 tiles onto the screen, and
    // hope the screen is actually large enough for that.
    const int tile_w = 640, tile_h = 480;
    ENSURE(g_xres >= tile_w && g_yres >= tile_h);

    const int img_w = tile_w*tiles, img_h = tile_h*tiles;
    const int bpp = 24;
    GLenum fmt = GL_RGB;
    int flags = TEX_BOTTOM_UP;
    // we want writing BMP to be as fast as possible,
    // so read data from OpenGL in BMP format to obviate conversion.
    if(extension == L".bmp")
    {
#if !CONFIG2_GLES // GLES doesn't support BGR
        fmt = GL_BGR;
        flags |= TEX_BGR;
#endif
    }

    const size_t img_size = img_w * img_h * bpp/8;
    const size_t tile_size = tile_w * tile_h * bpp/8;
    const size_t hdr_size = tex_hdr_size(filename);
    void* tile_data = malloc(tile_size);
    if(!tile_data)
    {
        WARN_IF_ERR(ERR::NO_MEM);
        return;
    }
    shared_ptr<u8> img_buf;
    AllocateAligned(img_buf, hdr_size+img_size, maxSectorSize);

    Tex t;
    GLvoid* img = img_buf.get() + hdr_size;
    if(t.wrap(img_w, img_h, bpp, flags, img_buf, hdr_size) < 0)
    {
        free(tile_data);
        return;
    }

    ogl_WarnIfError();

    // Resize various things so that the sizes and aspect ratios are correct
    {
        g_Renderer.Resize(tile_w, tile_h);
        SViewPort vp = { 0, 0, tile_w, tile_h };
        g_Game->GetView()->GetCamera()->SetViewPort(vp);
        g_Game->GetView()->SetCameraProjection();
    }

#if !CONFIG2_GLES
    // Temporarily move everything onto the front buffer, so the user can
    // see the exciting progress as it renders (and can tell when it's finished).
    // (It doesn't just use SwapBuffers, because it doesn't know whether to
    // call the SDL version or the Atlas version.)
    GLint oldReadBuffer, oldDrawBuffer;
    glGetIntegerv(GL_READ_BUFFER, &oldReadBuffer);
    glGetIntegerv(GL_DRAW_BUFFER, &oldDrawBuffer);
    glDrawBuffer(GL_FRONT);
    glReadBuffer(GL_FRONT);
#endif

    // Hide the cursor
    CStrW oldCursor = g_CursorName;
    g_CursorName = L"";

    // Render each tile
    for (int tile_y = 0; tile_y < tiles; ++tile_y)
    {
        for (int tile_x = 0; tile_x < tiles; ++tile_x)
        {
            // Adjust the camera to render the appropriate region
            g_Game->GetView()->GetCamera()->SetProjectionTile(tiles, tile_x, tile_y);

            RenderLogger(false);
            RenderGui(false);
            Render();
            RenderGui(true);
            RenderLogger(true);

            // Copy the tile pixels into the main image
            glReadPixels(0, 0, tile_w, tile_h, fmt, GL_UNSIGNED_BYTE, tile_data);
            for (int y = 0; y < tile_h; ++y)
            {
                void* dest = (char*)img + ((tile_y*tile_h + y) * img_w + (tile_x*tile_w)) * bpp/8;
                void* src = (char*)tile_data + y * tile_w * bpp/8;
                memcpy(dest, src, tile_w * bpp/8);
            }
        }
    }

    // Restore the old cursor
    g_CursorName = oldCursor;

#if !CONFIG2_GLES
    // Restore the buffer settings
    glDrawBuffer(oldDrawBuffer);
    glReadBuffer(oldReadBuffer);
#endif

    // Restore the viewport settings
    {
        g_Renderer.Resize(g_xres, g_yres);
        SViewPort vp = { 0, 0, g_xres, g_yres };
        g_Game->GetView()->GetCamera()->SetViewPort(vp);
        g_Game->GetView()->SetCameraProjection();
        g_Game->GetView()->GetCamera()->SetProjectionTile(1, 0, 0);
    }

    if (tex_write(&t, filename) == INFO::OK)
    {
        OsPath realPath;
        g_VFS->GetRealPath(filename, realPath);

        LOGMESSAGERENDER(g_L10n.Translate("Screenshot written to '%s'"), realPath.string8());

        debug_printf(
            CStr(g_L10n.Translate("Screenshot written to '%s'") + "\n").c_str(),
            realPath.string8().c_str());
    }
    else
        LOGERROR("Error writing screenshot to '%s'", filename.string8());

    free(tile_data);
}
コード例 #16
0
ファイル: TemplateLoader.cpp プロジェクト: Rektosauros/0ad
std::vector<std::string> CTemplateLoader::FindPlaceableTemplates(const std::string& path, bool includeSubdirectories, ETemplatesType templatesType, ScriptInterface& scriptInterface)
{
	JSContext* cx = scriptInterface.GetContext();
	JSAutoRequest rq(cx);
	
	std::vector<std::string> templates;
	Status ok;
	VfsPath templatePath;


	if (templatesType == SIMULATION_TEMPLATES || templatesType == ALL_TEMPLATES)
	{
		JS::RootedValue placeablesFilter(cx);
		scriptInterface.ReadJSONFile("simulation/data/placeablesFilter.json", &placeablesFilter);

		JS::RootedObject folders(cx);
		if (scriptInterface.GetProperty(placeablesFilter, "templates", &folders))
		{
			if (!(JS_IsArrayObject(cx, folders)))
			{
				LOGERROR("FindPlaceableTemplates: Argument must be an array!");
				return templates;
			}

			u32 length;
			if (!JS_GetArrayLength(cx, folders, &length))
			{
				LOGERROR("FindPlaceableTemplates: Failed to get array length!");
				return templates;
			}

			templatePath = VfsPath(TEMPLATE_ROOT) / path;
			//I have every object inside, just run for each
			for (u32 i=0; i<length; ++i)
			{
				JS::RootedValue val(cx);
				if (!JS_GetElement(cx, folders, i, &val))
				{
					LOGERROR("FindPlaceableTemplates: Failed to read array element!");
					return templates;
				}

				std::string directoryPath;
				std::wstring fileFilter;
				scriptInterface.GetProperty(val, "directory", directoryPath);
				scriptInterface.GetProperty(val, "file", fileFilter);
				
				VfsPaths filenames;
				if (vfs::GetPathnames(g_VFS, templatePath / (directoryPath + "/"), fileFilter.c_str(), filenames) != INFO::OK)
					continue;
				
				for (const VfsPath& filename : filenames)
				{
					// Strip the .xml extension
					VfsPath pathstem = filename.ChangeExtension(L"");
					// Strip the root from the path
					std::wstring name = pathstem.string().substr(ARRAY_SIZE(TEMPLATE_ROOT) - 1);

					templates.emplace_back(name.begin(), name.end());
				}
				
			}
			
		}
	}

	if (templatesType == ACTOR_TEMPLATES || templatesType == ALL_TEMPLATES)
	{
		templatePath = VfsPath(ACTOR_ROOT) / path;
		if (includeSubdirectories)
			ok = vfs::ForEachFile(g_VFS, templatePath, AddActorToTemplates, (uintptr_t)&templates, L"*.xml", vfs::DIR_RECURSIVE);
		else
			ok = vfs::ForEachFile(g_VFS, templatePath, AddActorToTemplates, (uintptr_t)&templates, L"*.xml");
		WARN_IF_ERR(ok);
	}

	if (templatesType != SIMULATION_TEMPLATES && templatesType != ACTOR_TEMPLATES && templatesType != ALL_TEMPLATES)
		LOGERROR("Undefined template type (valid: all, simulation, actor)");

	return templates;
}