Exemple #1
0
// return indication of whether archive is currently being built; this is
// used to prevent reloading during that time (see call site).
static bool ProgressiveBuildArchive()
{
ONCE(g_GUI->SendEventToAll("archivebuildercomplete"));
return false;
#if 0
	int ret = vfs_opt_auto_build("../logs/trace.txt", "mods/official/official%02d.zip", "mods/official/mini%02d.zip");
	if(ret == INFO::ALL_COMPLETE)
	{
		// nothing to do; will return false below
	}
	else if(ret < 0)
		DEBUG_DISPLAY_ERROR(L"Archive build failed");
	else if(ret == INFO::OK)
		g_GUI.SendEventToAll("archivebuildercomplete");
	// in progress
	else
	{
		int percent = (int)ret;
		g_ScriptingHost.SetGlobal("g_ArchiveBuilderProgress", INT_TO_JSVAL(percent));
		g_GUI.SendEventToAll("archivebuilderprogress");
		return true;
	}

	return false;
#endif
}
Exemple #2
0
// called when an exception is detected (see below); provides detailed
// debugging information and exits.
//
// note: keep memory allocs and locking to an absolute minimum, because
// they may deadlock the process!
long __stdcall wseh_ExceptionFilter(struct _EXCEPTION_POINTERS* ep)
{
	// OutputDebugString raises an exception, which OUGHT to be swallowed
	// by WaitForDebugEvent but sometimes isn't. if we see it, ignore it.
	if(ep->ExceptionRecord->ExceptionCode == 0x40010006)	// DBG_PRINTEXCEPTION_C
		return EXCEPTION_CONTINUE_EXECUTION;

	// if run in a debugger, let it handle exceptions (tends to be more
	// convenient since it can bring up the crash location)
	if(IsDebuggerPresent())
		return EXCEPTION_CONTINUE_SEARCH;

	// make sure we don't recurse infinitely if this function raises an
	// SEH exception. (we may only have the guard page's 4 KB worth of
	// stack space if the exception is EXCEPTION_STACK_OVERFLOW)
	static intptr_t nestingLevel = 0;
	cpu_AtomicAdd(&nestingLevel, 1);
	if(nestingLevel >= 3)
		return EXCEPTION_CONTINUE_SEARCH;

	// someone is already holding the dbghelp lock - this is bad.
	// we'll report this problem first and then try to display the
	// exception info regardless (maybe dbghelp won't blow up).
	if(wutil_IsLocked(WDBG_SYM_CS) == 1)
		DEBUG_DISPLAY_ERROR(L"Exception raised while critical section is held - may deadlock..");

	// a dump file is essential for debugging, so write it before
	// anything else goes wrong (especially before showing the error
	// dialog because the user could choose to exit immediately)
	wdbg_sym_WriteMinidump(ep);

	// extract details from ExceptionRecord.
	wchar_t descriptionBuf[150];
	const wchar_t* description = GetExceptionDescription(ep, descriptionBuf, ARRAY_SIZE(descriptionBuf));
	wchar_t file[DEBUG_FILE_CHARS] = {0};
	int line = 0;
	wchar_t func[DEBUG_SYMBOL_CHARS] = {0};
	GetExceptionLocus(ep, file, &line, func);

	wchar_t message[500];
	const wchar_t* messageFormat =
		L"Much to our regret we must report the program has encountered an error.\r\n"
		L"\r\n"
		L"Please let us know at http://trac.wildfiregames.com/ and attach the crashlog.txt and crashlog.dmp files.\r\n"
		L"\r\n"
		L"Details: unhandled exception (%ls)\r\n";
	swprintf_s(message, ARRAY_SIZE(message), messageFormat, description);

	size_t flags = 0;
	if(ep->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
		flags = DE_NO_CONTINUE;
	const wchar_t* const lastFuncToSkip = WIDEN(STRINGIZE(DECORATED_NAME(wseh_ExceptionFilter)));
	ErrorReaction er = debug_DisplayError(message, flags, ep->ContextRecord, lastFuncToSkip, file,line,utf8_from_wstring(func).c_str(), 0);
	ENSURE(er == ER_CONTINUE);	// nothing else possible

	// invoke the Win32 default handler - it calls ExitProcess for
	// most exception types.
	return EXCEPTION_CONTINUE_SEARCH;
}
Exemple #3
0
// starts the Atlas UI.
static void ATLAS_Run(const CmdLineArgs& args, int flags = 0)
{
	// first check if we can run at all
	if(!atlas_dll.LoadDLL())
	{
		if(flags & ATLAS_NO_GUI)
			DEBUG_DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");
		else
			DEBUG_DISPLAY_ERROR(L"The Atlas UI was not successfully loaded and therefore cannot be started as requested.");// TODO: implement GUI error message
		return;
	}

	// TODO (make nicer)
	extern bool BeginAtlas(const CmdLineArgs& args, const DllLoader& dll);
	if (!BeginAtlas(args, atlas_dll))
	{
		debug_warn(L"Atlas loading failed");
		return;
	}
}
Exemple #4
0
// choose an internal format for <fmt> based on the given q_flags.
static GLint choose_int_fmt(GLenum fmt, int q_flags)
{
	// true => 4 bits per component; otherwise, 8
	const bool half_bpp = (q_flags & OGL_TEX_HALF_BPP) != 0;

	// early-out for S3TC textures: they don't need an internal format
	// (because upload is via glCompressedTexImage2DARB), but we must avoid
	// triggering the default case below. we might as well return a
	// meaningful value (i.e. int_fmt = fmt).
	if(fmt_is_s3tc(fmt))
		return fmt;

	switch(fmt)
	{
	// 8bpp
	case GL_LUMINANCE:
		return half_bpp? GL_LUMINANCE4 : GL_LUMINANCE8;
	case GL_INTENSITY:
		return half_bpp? GL_INTENSITY4 : GL_INTENSITY8;
	case GL_ALPHA:
		return half_bpp? GL_ALPHA4 : GL_ALPHA8;

	// 16bpp
	case GL_LUMINANCE_ALPHA:
		return half_bpp? GL_LUMINANCE4_ALPHA4 : GL_LUMINANCE8_ALPHA8;

	// 24bpp
	case GL_RGB:
	case GL_BGR:	// note: BGR can't be used as internal format
		return half_bpp? GL_RGB4 : GL_RGB8;

	// 32bpp
	case GL_RGBA:
	case GL_BGRA:	// note: BGRA can't be used as internal format
		return half_bpp? GL_RGBA4 : GL_RGBA8;

	default:
		{
		wchar_t buf[100];
		swprintf_s(buf, ARRAY_SIZE(buf), L"choose_int_fmt: fmt 0x%x isn't covered! please add it", fmt);
		DEBUG_DISPLAY_ERROR(buf);
		DEBUG_WARN_ERR(ERR::LOGIC);	// given fmt isn't covered! please add it.
		// fall back to a reasonable default
		return half_bpp? GL_RGB4 : GL_RGB8;
		}
	}

	UNREACHABLE;
}
Exemple #5
0
Status debug_WriteCrashlog(const wchar_t* text)
{
	// (avoid infinite recursion and/or reentering this function if it
	// fails/reports an error)
	enum State
	{
		IDLE,
		BUSY,
		FAILED
	};
	// note: the initial state is IDLE. we rely on zero-init because
	// initializing local static objects from constants may happen when
	// this is first called, which isn't thread-safe. (see C++ 6.7.4)
	cassert(IDLE == 0);
	static volatile intptr_t state;

	if(!cpu_CAS(&state, IDLE, BUSY))
		return ERR::REENTERED;	// NOWARN

	OsPath pathname = ah_get_log_dir()/"crashlog.txt";
	FILE* f = sys_OpenFile(pathname, "w");
	if(!f)
	{
		state = FAILED;	// must come before DEBUG_DISPLAY_ERROR
		DEBUG_DISPLAY_ERROR(L"Unable to open crashlog.txt for writing (please ensure the log directory is writable)");
		return ERR::FAIL;	// NOWARN (the above text is more helpful than a generic error code)
	}

	fputwc(0xFEFF, f);	// BOM
	fwprintf(f, L"%ls\n", text);
	fwprintf(f, L"\n\n====================================\n\n");

	// allow user to bundle whatever information they want
	ah_bundle_logs(f);

	fclose(f);
	state = IDLE;
	return INFO::OK;
}
Exemple #6
0
void InitGraphics(const CmdLineArgs& args, int flags)
{
	const bool setup_vmode = (flags & INIT_HAVE_VMODE) == 0;

	if(setup_vmode)
	{
		InitSDL();

		if (!g_VideoMode.InitSDL())
			throw PSERROR_System_VmodeFailed(); // abort startup

#if !SDL_VERSION_ATLEAST(2, 0, 0)
		SDL_WM_SetCaption("0 A.D.", "0 A.D.");
#endif
	}

	RunHardwareDetection();

	const int quality = SANE_TEX_QUALITY_DEFAULT;	// TODO: set value from config file
	SetTextureQuality(quality);

	ogl_WarnIfError();

	// Optionally start profiler GPU timings automatically
	// (By default it's only enabled by a hotkey, for performance/compatibility)
	bool profilerGPUEnable = false;
	CFG_GET_VAL("profiler2.autoenable", profilerGPUEnable);
	if (profilerGPUEnable)
		g_Profiler2.EnableGPU();

	if(!g_Quickstart)
	{
		WriteSystemInfo();
		// note: no longer vfs_display here. it's dog-slow due to unbuffered
		// file output and very rarely needed.
	}

	if(g_DisableAudio)
		ISoundManager::SetEnabled(false);

	g_GUI = new CGUIManager();

	// (must come after SetVideoMode, since it calls ogl_Init)
	if (ogl_HaveExtensions(0, "GL_ARB_vertex_program", "GL_ARB_fragment_program", NULL) != 0 // ARB
		&& ogl_HaveExtensions(0, "GL_ARB_vertex_shader", "GL_ARB_fragment_shader", NULL) != 0) // GLSL
	{
		DEBUG_DISPLAY_ERROR(
			L"Your graphics card doesn't appear to be fully compatible with OpenGL shaders."
			L" In the future, the game will not support pre-shader graphics cards."
			L" You are advised to try installing newer drivers and/or upgrade your graphics card."
			L" For more information, please see http://www.wildfiregames.com/forum/index.php?showtopic=16734"
		);
		// TODO: actually quit once fixed function support is dropped
	}

	const char* missing = ogl_HaveExtensions(0,
		"GL_ARB_multitexture",
		"GL_EXT_draw_range_elements",
		"GL_ARB_texture_env_combine",
		"GL_ARB_texture_env_dot3",
		NULL);
	if(missing)
	{
		wchar_t buf[500];
		swprintf_s(buf, ARRAY_SIZE(buf),
			L"The %hs extension doesn't appear to be available on your computer."
			L" The game may still work, though - you are welcome to try at your own risk."
			L" If not or it doesn't look right, upgrade your graphics card.",
			missing
		);
		DEBUG_DISPLAY_ERROR(buf);
		// TODO: i18n
	}

	if (!ogl_HaveExtension("GL_ARB_texture_env_crossbar"))
	{
		DEBUG_DISPLAY_ERROR(
			L"The GL_ARB_texture_env_crossbar extension doesn't appear to be available on your computer."
			L" Shadows are not available and overall graphics quality might suffer."
			L" You are advised to try installing newer drivers and/or upgrade your graphics card.");
		g_Shadows = false;
	}

	ogl_WarnIfError();
	InitRenderer();

	InitInput();

	ogl_WarnIfError();

	try
	{
		if (!Autostart(args))
		{
			const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
			// We only want to display the splash screen at startup
			shared_ptr<ScriptInterface> scriptInterface = g_GUI->GetScriptInterface();
			JSContext* cx = scriptInterface->GetContext();
			JSAutoRequest rq(cx);
			JS::RootedValue data(cx);
			if (g_GUI)
			{
				scriptInterface->Eval("({})", &data);
				scriptInterface->SetProperty(data, "isStartup", true);
			}
			InitPs(setup_gui, L"page_pregame.xml", g_GUI->GetScriptInterface().get(), data);
		}
	}
	catch (PSERROR_Game_World_MapLoadFailed& e)
	{
		// Map Loading failed

		// Start the engine so we have a GUI
		InitPs(true, L"page_pregame.xml", NULL, JS::UndefinedHandleValue);

		// Call script function to do the actual work
		//	(delete game data, switch GUI page, show error, etc.)
		CancelLoad(CStr(e.what()).FromUTF8());
	}
}
Exemple #7
0
void InitGraphics(const CmdLineArgs& args, int flags)
{
	const bool setup_vmode = (flags & INIT_HAVE_VMODE) == 0;

	if(setup_vmode)
	{
		InitSDL();

		if (!g_VideoMode.InitSDL())
			throw PSERROR_System_VmodeFailed(); // abort startup

#if !SDL_VERSION_ATLEAST(2, 0, 0)
		SDL_WM_SetCaption("0 A.D.", "0 A.D.");
#endif
	}

	RunHardwareDetection();

	tex_codec_register_all();

	const int quality = SANE_TEX_QUALITY_DEFAULT;	// TODO: set value from config file
	SetTextureQuality(quality);

	ogl_WarnIfError();

	// Optionally start profiler GPU timings automatically
	// (By default it's only enabled by a hotkey, for performance/compatibility)
	bool profilerGPUEnable = false;
	CFG_GET_VAL("profiler2.gpu.autoenable", Bool, profilerGPUEnable);
	if (profilerGPUEnable)
		g_Profiler2.EnableGPU();

	if(!g_Quickstart)
	{
		WriteSystemInfo();
		// note: no longer vfs_display here. it's dog-slow due to unbuffered
		// file output and very rarely needed.
	}

	if(g_DisableAudio)
	{
		// speed up startup by disabling all sound
		// (OpenAL init will be skipped).
		// must be called before first snd_open.
#if CONFIG2_AUDIO
		CSoundManager::SetEnabled(false);
#endif
	}

	g_GUI = new CGUIManager(g_ScriptingHost.GetScriptInterface());

	// (must come after SetVideoMode, since it calls ogl_Init)
	const char* missing = ogl_HaveExtensions(0,
		"GL_ARB_multitexture",
		"GL_EXT_draw_range_elements",
		"GL_ARB_texture_env_combine",
		"GL_ARB_texture_env_dot3",
		NULL);
	if(missing)
	{
		wchar_t buf[500];
		swprintf_s(buf, ARRAY_SIZE(buf),
			L"The %hs extension doesn't appear to be available on your computer."
			L" The game may still work, though - you are welcome to try at your own risk."
			L" If not or it doesn't look right, upgrade your graphics card.",
			missing
		);
		DEBUG_DISPLAY_ERROR(buf);
		// TODO: i18n
	}

	if (!ogl_HaveExtension("GL_ARB_texture_env_crossbar"))
	{
		DEBUG_DISPLAY_ERROR(
			L"The GL_ARB_texture_env_crossbar extension doesn't appear to be available on your computer."
			L" Shadows are not available and overall graphics quality might suffer."
			L" You are advised to try installing newer drivers and/or upgrade your graphics card.");
		g_Shadows = false;
	}

	ogl_WarnIfError();
	InitRenderer();

	InitInput();

	ogl_WarnIfError();

	try
	{
		if (!Autostart(args))
		{
			const bool setup_gui = ((flags & INIT_NO_GUI) == 0);
			// We only want to display the splash screen at startup
			CScriptValRooted data;
			if (g_GUI)
			{
				ScriptInterface& scriptInterface = g_GUI->GetScriptInterface();
				scriptInterface.Eval("({})", data);
				scriptInterface.SetProperty(data.get(), "isStartup", true);
			}
			InitPs(setup_gui, L"page_pregame.xml", data.get());
		}
	}
	catch (PSERROR_Game_World_MapLoadFailed e)
	{
		// Map Loading failed

		// Start the engine so we have a GUI
		InitPs(true, L"page_pregame.xml", JSVAL_VOID);

		// Call script function to do the actual work
		//	(delete game data, switch GUI page, show error, etc.)
		CancelLoad(CStr(e.what()).FromUTF8());
	}
}