Example #1
0
static void DeinitLevel()
{
	static bool initedLateHook = false;

	if (!initedLateHook)
	{
		// late hook to prevent scenario manager from reinitializing on map load - it messes things up, a lot, and I doubt custom maps use scenarios anyway. :)
		hook::put<uint16_t>(hook::pattern("83 F9 04 0F 85 F9 00 00 00").count(1).get(0).get<void>(3), 0xE990); // shutdown
		hook::put<uint16_t>(hook::pattern("83 F9 02 0F 85 C6 01 00 00").count(1).get(0).get<void>(3), 0xE990); // init

		// don't load mounted ped (personality) metadata anymore (temp dbg-y?)
		hook::nop(hook::pattern("48 8B DA 83 E9 14 74 5B").count(1).get(0).get<void>(0x72 - 12), 5);

		initedLateHook = true;
	}

	// stuff
	g_inLevelFree = true;

	g_deinitLevel();

	shutdownModelInfo(1);
	initModelInfo(1);
	initStreamingInterface();

	// extra content manager shutdown session removes these, and we want these before init session, so we scan them right here, right now.
	extraContentMgr__doScanInt(*g_extraContentMgr);
	extraContentMgr__doScanPost(*g_extraContentMgr, false, false);

	//shutdownPhysics(1);
	//initPhysics(1);

	// unknown value in the bounds streaming module, doesn't get cleared on 'after map loaded' shutdown
	*(uint32_t*)(g_boundsStreamingModule + 5664) = 0;

	// bounds streaming module, 'has preloading bounds completed' value
	*(uint8_t*)(g_boundsStreamingModule + 255) = 0;

	// clear the 'loaded cache hashes' list
	*g_cacheArray = atArray<allocWrap<uint32_t>>(16);

	// free one CScene list of all the bad influences from the last session
	ClearInteriorProxyList(g_sceneLinkedList);

	// also clear the interior proxy pool out, as it might contain garbage references to static bounds, still
	(*g_interiorProxyPool)->Clear();

	// and some global vehicle audio entity also houses... interior proxies.
	*g_vehicleReflEntityArray = atArray<CInteriorProxy*>();

	g_inLevelFree = false;

	if (!g_didLevelFree)
	{
		for (auto& stack : g_stacks)
		{
			FILE* f = fopen(va("D:\\dev\\stacks\\%p.txt", ((stack.first / 256) * 256)), "a");

			if (f)
			{
				fprintf(f, "--- %p ---\n", stack.first);

				for (auto& entry : stack.second)
				{
					fprintf(f, "%p\n", entry);
				}

				fprintf(f, "--- --- ---\n");

				fclose(f);
			}
		}

		g_stackIdx = 0;
		g_stacks.clear();

		g_didLevelFree = true;
	}
}
Example #2
0
static void DeinitLevel()
{
	static bool initedLateHook = false;

	if (!initedLateHook)
	{
		// late hook to prevent scenario manager from reinitializing on map load - it messes things up, a lot, and I doubt custom maps use scenarios anyway. :)
		hook::put<uint16_t>(hook::pattern("83 F9 04 0F 85 F9 00 00 00").count(1).get(0).get<void>(3), 0xE990); // shutdown
		hook::put<uint16_t>(hook::pattern("83 F9 02 0F 85 C6 01 00 00").count(1).get(0).get<void>(3), 0xE990); // init

		// don't load mounted ped (personality) metadata anymore (temp dbg-y?)
		hook::nop(hook::pattern("48 8B DA 83 E9 14 74 5B").count(1).get(0).get<void>(0x72 - 12), 5);

		// recreate interior proxy pool sanely
		//char* poolFn = hook::get_pattern<char>("41 0F B7 C6 4D 89 73 E8 41 8B F6 66 89 44 24 28", -0x23);
		//poolFn += 0xD4;
		//hook::nop(poolFn, 44);
		//hook::jump(poolFn, ClearInteriorProxyPool);

		initedLateHook = true;
	}

	// stuff
	g_inLevelFree = true;

	g_deinitLevel();

	shutdownModelInfo(1);
	initModelInfo(1);
	initStreamingInterface();

	//g_loadClipSets();

	// extra content manager shutdown session removes these, and we want these before init session, so we scan them right here, right now.
	// TEMP REMOVE
	extraContentMgr__doScanInt(*g_extraContentMgr);
	extraContentMgr__doScanPost(*g_extraContentMgr, false, false);

	//shutdownPhysics(1);
	//initPhysics(1);

	// unknown value in the bounds streaming module, doesn't get cleared on 'after map loaded' shutdown
	int colCrashOffset = *hook::get_pattern<int>("0F B7 83 ? ? 00 00 BA FF 1F 00 00 66 33 C1 66", 3);
	int colCrashCountMax = (colCrashOffset - 464) / 4;

	*(uint32_t*)(g_boundsStreamingModule + colCrashOffset) = 0;

	// bounds streaming module, 'has preloading bounds completed' value
	*(uint8_t*)(g_boundsStreamingModule + 255) = 0;

	// clear the 'loaded cache hashes' list
	//*g_cacheArray = atArray<allocWrap<uint32_t>>(16);
	g_cacheArray->ClearCount();

	// free one CScene list of all the bad influences from the last session
	ClearInteriorProxyList(g_sceneLinkedList);

	// also clear the interior proxy pool out, as it might contain garbage references to static bounds, still
	(*g_interiorProxyPool)->Clear();

	// and some global vehicle audio entity also houses... interior proxies.
	*g_vehicleReflEntityArray = atArray<CInteriorProxy*>();

	// clear interior proxies from render phases
	for (auto& pair : g_renderPhases)
	{
		CRenderPhaseScanned* renderPhase = pair.second;

		if (renderPhase->portalScanner)
		{
			trace("clearing %s interior proxy (was %p)\n", pair.first.c_str(), renderPhase->portalScanner->interiorProxy);

			renderPhase->portalScanner->interiorProxy = nullptr;
		}
	}

	g_inLevelFree = false;

	if (!g_didLevelFree)
	{
		for (auto& stack : g_stacks)
		{
			FILE* f = fopen(va("D:\\dev\\stacks\\%p.txt", ((stack.first / 256) * 256)), "a");

			if (f)
			{
				fprintf(f, "--- %p ---\n", stack.first);

				for (auto& entry : stack.second)
				{
					fprintf(f, "%p\n", entry);
				}

				fprintf(f, "--- --- ---\n");

				fclose(f);
			}
		}

		g_stackIdx = 0;
		g_stacks.clear();

		g_didLevelFree = true;
	}
}