// ======================= ZoneTool =======================
// zonetool, a fastfile linker for various
// Call of Duty titles. 
//
// Project: https://github.com/ZoneTool/zonetool
// Author: RektInator (https://github.com/RektInator)
// License: GNU GPL v3.0
// ========================================================
#include "stdafx.hpp"

namespace ZoneTool
{
	namespace IW5
	{
		/*legacy zonetool code, refactor me!*/
		GfxWorld* IGfxWorld::parse(const std::string& name, ZoneMemory* mem)
		{
			if (!FileSystem::FileExists(name + ".gfxmap"))
			{
				return nullptr;
			}

			// alloc GfxWorld
			auto asset = mem->Alloc<GfxWorld>();
			memset(asset, 0, sizeof(GfxWorld));

			AssetReader read(mem);
			if (!read.open(name + ".gfxmap"))
			{
				return nullptr;
			}

			ZONETOOL_INFO("Parsing GfxWorld \"%s\"...", name.data());

#ifdef USE_VMPROTECT
			VMProtectBeginUltra("IW5::IGfxWorld::parse");
#endif

			asset->name = read.read_string();
			asset->baseName = read.read_string();

			asset->planeCount = read.read_int();
			asset->nodeCount = read.read_int();
			asset->indexCount = read.read_int();
			asset->skyCount = read.read_int();

			asset->skies = read.read_array<GfxSky>();
			for (unsigned int i = 0; i < asset->skyCount; i++)
			{
				asset->skies[i].skyStartSurfs = read.read_array<std::uint32_t>();
				asset->skies[i].skyImage = read.read_asset<GfxImage>();
			}

			asset->sunPrimaryLightIndex = read.read_int();
			asset->primaryLightCount = read.read_int();
			asset->primaryLightEnvCount = read.read_int();

			char* unknown1 = read.read_array<char>();
			memcpy(asset->unknown1, unknown1, 12);

			// dpvsplanes
			asset->dpvsPlanes.cellCount = read.read_int();
			asset->dpvsPlanes.planes = read.read_array<cplane_s>();
			asset->dpvsPlanes.nodes = read.read_array<unsigned short>();
			asset->dpvsPlanes.sceneEntCellBits = read.read_array<unsigned char>();

			// dpvs
			GfxWorldDpvsStatic* dpvs = read.read_array<GfxWorldDpvsStatic>();
			memcpy(&asset->dpvs, dpvs, sizeof(GfxWorldDpvsStatic));

			asset->dpvs.smodelVisData[0] = read.read_array<char>();
			asset->dpvs.smodelVisData[1] = read.read_array<char>();
			asset->dpvs.smodelVisData[2] = read.read_array<char>();
			asset->dpvs.surfaceVisData[0] = read.read_array<char>();
			asset->dpvs.surfaceVisData[1] = read.read_array<char>();
			asset->dpvs.surfaceVisData[2] = read.read_array<char>();
			asset->dpvs.sortedSurfIndex = read.read_array<unsigned short>();
			asset->dpvs.smodelInsts = read.read_array<GfxStaticModelInst>();
			asset->dpvs.surfaces = read.read_array<GfxSurface>();
			for (int i = 0; i < asset->indexCount; i++)
			{
				asset->dpvs.surfaces[i].material = read.read_asset<Material>();
			}
			asset->dpvs.surfacesBounds = read.read_array<GfxSurfaceBounds>();
			asset->dpvs.smodelDrawInsts = read.read_array<GfxStaticModelDrawInst>();
			for (unsigned int i = 0; i < asset->dpvs.smodelCount; i++)
			{
				asset->dpvs.smodelDrawInsts[i].model = read.read_asset<XModel>();
			}
			asset->dpvs.surfaceMaterials = read.read_array<GfxDrawSurf>();
			asset->dpvs.surfaceCastsSunShadow = read.read_array<unsigned int>();

			// dpvsDyn
			GfxWorldDpvsDynamic* dpvsDyn = read.read_array<GfxWorldDpvsDynamic>();
			memcpy(&asset->dpvsDyn, dpvsDyn, sizeof(GfxWorldDpvsDynamic));

			asset->dpvsDyn.dynEntCellBits[0] = read.read_array<unsigned int>();
			asset->dpvsDyn.dynEntCellBits[1] = read.read_array<unsigned int>();
			asset->dpvsDyn.dynEntVisData[0][0] = read.read_array<char>();
			asset->dpvsDyn.dynEntVisData[1][0] = read.read_array<char>();
			asset->dpvsDyn.dynEntVisData[0][1] = read.read_array<char>();
			asset->dpvsDyn.dynEntVisData[1][1] = read.read_array<char>();
			asset->dpvsDyn.dynEntVisData[0][2] = read.read_array<char>();
			asset->dpvsDyn.dynEntVisData[1][2] = read.read_array<char>();

			// aabbTreeCount
			asset->aabbTreeCounts = read.read_array<GfxCellTreeCount>();

			// GfxCellTree
			asset->aabbTree = read.read_array<GfxCellTree>();
			for (int i = 0; i < asset->dpvsPlanes.cellCount; i++)
			{
				asset->aabbTree[i].aabbtree = read.read_array<GfxAabbTree>();

				for (int j = 0; j < asset->aabbTreeCounts[i].aabbTreeCount; j++)
				{
					asset->aabbTree[i].aabbtree[j].smodelIndexes = read.read_array<unsigned short>();
				}
			}

			// read GFX cells
			asset->cells = read.read_array<GfxCell>();

			for (int i = 0; i < asset->dpvsPlanes.cellCount; i++)
			{
				asset->cells[i].portals = read.read_array<GfxPortal>();
				for (int j = 0; j < asset->cells[i].portalCount; j++)
				{
					asset->cells[i].portals[j].vertices = read.read_array<float[3]>();
				}
				asset->cells[i].reflectionProbes = read.read_array<char>();
				asset->cells[i].reflectionProbeReferences = read.read_array<char>();
			}
			
			auto worldDraw = read.read_array<GfxWorldDraw>();
			memcpy(&asset->worldDraw, worldDraw, sizeof GfxWorldDraw);

			asset->worldDraw.reflectionImages = mem->Alloc<GfxImage*>(asset->worldDraw.reflectionProbeCount);
			// new GfxImage*[asset->draw.reflectionProbeCount];
			memset(asset->worldDraw.reflectionImages, 0, sizeof(GfxImage*) * asset->worldDraw.reflectionProbeCount);

			for (unsigned int i = 0; i < asset->worldDraw.reflectionProbeCount; i++)
			{
				asset->worldDraw.reflectionImages[i] = read.read_asset<GfxImage>();
			}

			asset->worldDraw.reflectionProbes = read.read_array<GfxReflectionProbe>();

			asset->worldDraw.reflectionProbeReferences = read.read_array<char>();
			asset->worldDraw.reflectionProbeReferenceOrigins = read.read_array<GfxReflectionProbeReferenceOrigin>();

			asset->worldDraw.reflectionProbeTextures = read.read_array<GfxTexture>();
			asset->worldDraw.lightmaps = read.read_array<GfxLightmapArray>();
			for (int i = 0; i < asset->worldDraw.lightmapCount; i++)
			{
				asset->worldDraw.lightmaps[i].primary = read.read_asset<GfxImage>();
				asset->worldDraw.lightmaps[i].secondary = read.read_asset<GfxImage>();
			}
			asset->worldDraw.lightmapPrimaryTextures = read.read_array<GfxTexture>();
			asset->worldDraw.lightmapSecondaryTextures = read.read_array<GfxTexture>();
			asset->worldDraw.skyImage = read.read_asset<GfxImage>();
			asset->worldDraw.outdoorImage = read.read_asset<GfxImage>();
			asset->worldDraw.vd.vertices = read.read_array<GfxWorldVertex>();
			asset->worldDraw.vld.data = read.read_array<char>();
			asset->worldDraw.indices = read.read_array<unsigned short>();


			// GfxLightGrid
			GfxLightGrid* lightGrid = read.read_array<GfxLightGrid>();
			memcpy(&asset->lightGrid, lightGrid, sizeof(GfxLightGrid));

			asset->lightGrid.rowDataStart = read.read_array<unsigned short>();
			asset->lightGrid.rawRowData = read.read_array<char>();
			asset->lightGrid.entries = read.read_array<GfxLightGridEntry>();
			asset->lightGrid.colors = read.read_array<GfxLightGridColors>();

			// models
			asset->modelCount = read.read_int();
			asset->models = read.read_array<GfxBrushModel>();

			// mins/maxs
			float* mins = read.read_array<float>();
			memcpy(asset->mins, mins, sizeof(float) * 3);

			float* maxs = read.read_array<float>();
			memcpy(asset->maxs, maxs, sizeof(float) * 3);

			asset->checksum = read.read_int();

			// materialmemory
			asset->materialMemoryCount = read.read_int();
			asset->materialMemory = read.read_array<MaterialMemory>();
			for (int i = 0; i < asset->materialMemoryCount; i++)
			{
				asset->materialMemory[i].material = read.read_asset<Material>();
			}

			// sun data
			sunflare_t* sun = read.read_array<sunflare_t>();
			memcpy(&asset->sun, sun, sizeof(sunflare_t));

			asset->sun.spriteMaterial = read.read_asset<Material>();
			asset->sun.flareMaterial = read.read_asset<Material>();

			// outdoor shit
			auto lookupMatrix = read.read_array<VecInternal<4>>();
			memcpy(&asset->outdoorLookupMatrix, lookupMatrix, sizeof(VecInternal<4>) * 4);

			asset->outdoorImage = read.read_asset<GfxImage>();

			// CellcasterBits
			asset->cellCasterBits[0] = read.read_array<unsigned int>();
			asset->cellCasterBits[1] = read.read_array<unsigned int>();

			// SceneDynModel
			asset->sceneDynModel = read.read_array<GfxSceneDynModel>();

			// SceneDynBrush
			asset->sceneDynBrush = read.read_array<GfxSceneDynBrush>();

			// PrimaryLightEntityShadowVis
			asset->primaryLightEntityShadowVis = read.read_array<unsigned char>();

			// PrimaryLightDynEntShadowVis
			asset->primaryLightDynEntShadowVis[0] = read.read_array<unsigned int>();
			asset->primaryLightDynEntShadowVis[1] = read.read_array<unsigned int>();

			// PrimaryLightForModelDynEnt
			asset->primaryLightForModelDynEnt = read.read_array<char>();

			// GfxShadowGeometry
			asset->shadowGeom = read.read_array<GfxShadowGeometry>();
			for (int i = 0; i < asset->primaryLightCount; i++)
			{
				asset->shadowGeom[i].sortedSurfIndex = read.read_array<unsigned short>();
				asset->shadowGeom[i].smodelIndex = read.read_array<unsigned short>();
			}

			// GfxLightRegion
			asset->lightRegion = read.read_array<GfxLightRegion>();
			for (int i = 0; i < asset->primaryLightCount; i++)
			{
				asset->lightRegion[i].hulls = read.read_array<GfxLightRegionHull>();
				for (unsigned int j = 0; j < asset->lightRegion[i].hullCount; j++)
				{
					asset->lightRegion[i].hulls[j].axis = read.read_array<GfxLightRegionAxis>();
				}
			}

			asset->mapVtxChecksum = read.read_int();

			// heroLights
			asset->heroLightCount = 0;
			asset->heroLights = nullptr;

			asset->fogTypesAllowed = read.read_int();

#ifdef USE_VMPROTECT
			VMProtectEnd();
#endif

			return asset;
		}

		IGfxWorld::IGfxWorld()
		{
		}

		IGfxWorld::~IGfxWorld()
		{
		}

		void IGfxWorld::init(const std::string& name, ZoneMemory* mem)
		{
			this->name_ = "maps/"s + (currentzone.substr(0, 3) == "mp_" ? "mp/" : "") + currentzone + ".d3dbsp"; // name;
			this->asset_ = this->parse(name, mem);

			if (!this->asset_)
			{
				this->asset_ = DB_FindXAssetHeader(this->type(), name.data(), 1).gfxworld;
			}
		}

		void IGfxWorld::prepare(ZoneBuffer* buf, ZoneMemory* mem)
		{
		}

		void IGfxWorld::load_depending(IZone* zone)
		{
#ifdef USE_VMPROTECT
			VMProtectBeginUltra("IW5::IGfxWorld::load_depending");
#endif

			auto data = this->asset_;

			// Skies
			if (data->skyCount)
			{
				for (unsigned int i = 0; i < data->skyCount; i++)
				{
					if (data->skies[i].skyImage)
					{
						zone->add_asset_of_type(image, data->skies[i].skyImage->name);
					}
				}
			}

			// ReflectionImages
			if (data->worldDraw.reflectionImages)
			{
				for (unsigned int i = 0; i < data->worldDraw.reflectionProbeCount; i++)
				{
					if (data->worldDraw.reflectionImages[i])
					{
						zone->add_asset_of_type(image, data->worldDraw.reflectionImages[i]->name);
					}
				}
			}

			// Lightmaps
			if (data->worldDraw.lightmaps)
			{
				for (int i = 0; i < data->worldDraw.lightmapCount; i++)
				{
					if (data->worldDraw.lightmaps[i].primary)
					{
						zone->add_asset_of_type(image, data->worldDraw.lightmaps[i].primary->name);
					}

					if (data->worldDraw.lightmaps[i].secondary)
					{
						zone->add_asset_of_type(image, data->worldDraw.lightmaps[i].secondary->name);
					}
				}
			}

			// SkyImage (Unused?)
			if (data->worldDraw.skyImage)
			{
				zone->add_asset_of_type(image, data->worldDraw.skyImage->name);
			}

			// OutdoorImage (Unused?)
			if (data->worldDraw.outdoorImage)
			{
				zone->add_asset_of_type(image, data->worldDraw.outdoorImage->name);
			}

			// MaterialMemory

			if (data->materialMemory)
			{
				for (int i = 0; i < data->materialMemoryCount; i++)
				{
					if (data->materialMemory[i].material)
					{
						zone->add_asset_of_type(material, data->materialMemory[i].material->name);
					}
				}
			}

			// Sunflare_t
			if (data->sun.spriteMaterial)
			{
				zone->add_asset_of_type(material, data->sun.spriteMaterial->name);
			}

			if (data->sun.flareMaterial)
			{
				zone->add_asset_of_type(material, data->sun.flareMaterial->name);
			}

			// OutdoorImage
			if (data->outdoorImage)
			{
				zone->add_asset_of_type(image, data->outdoorImage->name);
			}

			// Dpvs.Surfaces
			if (data->dpvs.surfaces)
			{
				for (int i = 0; i < data->indexCount; i++)
				{
					if (data->dpvs.surfaces[i].material)
					{
						zone->add_asset_of_type(material, data->dpvs.surfaces[i].material->name);
					}
				}
			}

			if (data->dpvs.smodelDrawInsts)
			{
				for (unsigned int i = 0; i < data->dpvs.smodelCount; i++)
				{
					if (data->dpvs.smodelDrawInsts[i].model)
					{
						zone->add_asset_of_type(xmodel, data->dpvs.smodelDrawInsts[i].model->name);
					}
				}
			}

#ifdef USE_VMPROTECT
			VMProtectEnd();
#endif
		}

		std::string IGfxWorld::name()
		{
			return this->name_;
		}

		std::int32_t IGfxWorld::type()
		{
			return gfx_map;
		}

		void IGfxWorld::write(IZone* zone, ZoneBuffer* buf)
		{
#ifdef USE_VMPROTECT
			VMProtectBeginUltra("IW5::IGfxWorld::write");
#endif

			auto data = this->asset_;
			auto dest = buf->write(data);

			buf->push_stream(3);
			START_LOG_STREAM;

			if (data->name)
			{
				dest->name = buf->write_str(this->name());
			}
			if (data->baseName)
			{
				dest->baseName = buf->write_str(this->name());
			}

			if (data->skies)
			{
				buf->align(3);
				auto skiesArray = buf->write(data->skies, data->skyCount);

				for (std::uint32_t i = 0; i < data->skyCount; i++)
				{
					if (data->skies[i].skyStartSurfs)
					{
						buf->align(3);
						buf->write_p(data->skies[i].skyStartSurfs, data->skies[i].skySurfCount);
						ZoneBuffer::clear_pointer(&skiesArray[i].skyStartSurfs);
					}

					if (data->skies[i].skyImage)
					{
						skiesArray[i].skyImage = reinterpret_cast<GfxImage*>(zone->get_asset_pointer(
							image, data->skies[i].skyImage->name));
					}
				}

				ZoneBuffer::clear_pointer(&dest->skies);
			}

			if (dest->dpvsPlanes.planes)
			{
				dest->dpvsPlanes.planes = buf->write_s(3, data->dpvsPlanes.planes, data->planeCount);
			}

			if (dest->dpvsPlanes.nodes)
			{
				buf->align(1);
				buf->write_p(data->dpvsPlanes.nodes, data->nodeCount);
				ZoneBuffer::clear_pointer(&dest->dpvsPlanes.nodes);
			}

			buf->push_stream(2);
			if (dest->dpvsPlanes.sceneEntCellBits)
			{
				buf->align(3);
				buf->write(data->dpvsPlanes.sceneEntCellBits, data->dpvsPlanes.cellCount << 11);
				ZoneBuffer::clear_pointer(&dest->dpvsPlanes.sceneEntCellBits);
			}
			buf->pop_stream();

			if (data->aabbTreeCounts)
			{
				buf->align(3);
				buf->write_p(data->aabbTreeCounts, data->dpvsPlanes.cellCount);
				ZoneBuffer::clear_pointer(&dest->aabbTreeCounts);
			}

			if (data->aabbTree)
			{
				buf->align(127);
				auto cell_tree = buf->write_p(data->aabbTree, data->dpvsPlanes.cellCount);

				for (std::int32_t i = 0; i < data->dpvsPlanes.cellCount; i++)
				{
					if (data->aabbTree[i].aabbtree)
					{
						buf->align(3);
						auto gfx_aabb_tree = buf->write_p(data->aabbTree[i].aabbtree,
						                                  data->aabbTreeCounts[i].aabbTreeCount);

						for (std::int32_t i2 = 0; i2 < data->aabbTreeCounts[i].aabbTreeCount; i2++)
						{
							if (data->aabbTree[i].aabbtree[i2].smodelIndexes)
							{
								gfx_aabb_tree[i2].smodelIndexes = buf->write_s(
									1, data->aabbTree[i].aabbtree[i2].smodelIndexes,
									data->aabbTree[i].aabbtree[i2].smodelIndexCount);
							}
						}

						ZoneBuffer::clear_pointer(&cell_tree[i].aabbtree);
					}
				}

				ZoneBuffer::clear_pointer(&dest->aabbTree);
			}

			if (data->cells)
			{
				buf->align(3);
				auto gfx_cell = buf->write(data->cells, data->dpvsPlanes.cellCount);

				for (std::int32_t i = 0; i < data->dpvsPlanes.cellCount; i++)
				{
					if (data->cells[i].portals)
					{
						buf->align(3);
						auto gfx_portal = buf->write(data->cells[i].portals, data->cells[i].portalCount);

						for (std::int32_t i2 = 0; i2 < data->cells[i].portalCount; i2++)
						{
							if (data->cells[i].portals[i2].vertices)
							{
								buf->align(3);
								buf->write(data->cells[i].portals[i2].vertices, data->cells[i].portals[i2].vertexCount);
								ZoneBuffer::clear_pointer(&gfx_portal[i2].vertices);
							}
						}

						ZoneBuffer::clear_pointer(&gfx_cell[i].portals);
					}

					if (data->cells[i].reflectionProbes)
					{
						buf->align(0);
						buf->write(data->cells[i].reflectionProbes, data->cells[i].reflectionProbeCount);
						ZoneBuffer::clear_pointer(&gfx_cell[i].reflectionProbes);
					}
					if (data->cells[i].reflectionProbeReferences)
					{
						buf->align(0);
						buf->write(data->cells[i].reflectionProbeReferences,
						           data->cells[i].reflectionProbeReferenceCount);
						ZoneBuffer::clear_pointer(&gfx_cell[i].reflectionProbeReferences);
					}

					ZoneBuffer::clear_pointer(&dest->cells);
				}
			}

			if (data->worldDraw.reflectionImages)
			{
				buf->align(3);
				auto reflectionProbes = buf->write(data->worldDraw.reflectionImages,
				                                   data->worldDraw.reflectionProbeCount);

				for (std::uint64_t i = 0; i < data->worldDraw.reflectionProbeCount; i++)
				{
					if (reflectionProbes[i])
					{
						reflectionProbes[i] = reinterpret_cast<GfxImage*>(zone->get_asset_pointer(
							image, data->worldDraw.reflectionImages[i]->name));
					}
				}

				ZoneBuffer::clear_pointer(&dest->worldDraw.reflectionImages);
			}

			if (data->worldDraw.reflectionProbes)
			{
				buf->align(3);
				buf->write(data->worldDraw.reflectionProbes, data->worldDraw.reflectionProbeCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.reflectionProbes);
			}

			buf->push_stream(2);
			if (data->worldDraw.reflectionProbeTextures)
			{
				buf->align(3);
				buf->write(data->worldDraw.reflectionProbeTextures, data->worldDraw.reflectionProbeCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.reflectionProbeTextures);
			}
			buf->pop_stream();

			if (data->worldDraw.reflectionProbeReferenceOrigins)
			{
				buf->align(3);
				buf->write(data->worldDraw.reflectionProbeReferenceOrigins,
				           data->worldDraw.reflectionProbeReferenceCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.reflectionProbeReferenceOrigins);
			}
			if (data->worldDraw.reflectionProbeReferences)
			{
				buf->align(0);
				buf->write(data->worldDraw.reflectionProbeReferences, data->worldDraw.reflectionProbeReferenceCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.reflectionProbeReferences);
			}

			if (data->worldDraw.lightmaps)
			{
				buf->align(3);
				auto gfx_lightmap_array = buf->write(data->worldDraw.lightmaps, data->worldDraw.lightmapCount);

				for (std::int32_t i = 0; i < data->worldDraw.lightmapCount; i++)
				{
					if (data->worldDraw.lightmaps[i].primary)
					{
						gfx_lightmap_array[i].primary = reinterpret_cast<GfxImage*>(zone->get_asset_pointer(
							image, data->worldDraw.lightmaps[i].primary->name));
					}

					if (data->worldDraw.lightmaps[i].secondary)
					{
						gfx_lightmap_array[i].secondary = reinterpret_cast<GfxImage*>(zone->get_asset_pointer(
							image, data->worldDraw.lightmaps[i].secondary->name));
					}
				}

				ZoneBuffer::clear_pointer(&dest->worldDraw.lightmaps);
			}

			buf->push_stream(2);
			if (data->worldDraw.lightmapPrimaryTextures)
			{
				buf->align(3);
				buf->write_p(data->worldDraw.lightmapPrimaryTextures, data->worldDraw.lightmapCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.lightmapPrimaryTextures);
			}

			if (data->worldDraw.lightmapSecondaryTextures)
			{
				buf->align(3);
				buf->write_p(data->worldDraw.lightmapSecondaryTextures, data->worldDraw.lightmapCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.lightmapSecondaryTextures);
			}
			buf->pop_stream();

			if (data->worldDraw.skyImage)
			{
				dest->worldDraw.skyImage = reinterpret_cast<GfxImage*>(zone->get_asset_pointer(
					image, data->worldDraw.skyImage->name));
			}

			if (data->worldDraw.outdoorImage)
			{
				dest->worldDraw.outdoorImage = reinterpret_cast<GfxImage*>(zone->get_asset_pointer(
					image, data->worldDraw.outdoorImage->name));
			}

			if (data->worldDraw.vd.vertices)
			{
				buf->align(3);
				buf->write_p(data->worldDraw.vd.vertices, data->worldDraw.vertexCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.vd.vertices);
			}

			if (data->worldDraw.vld.data)
			{
				buf->align(0);
				buf->write_p(data->worldDraw.vld.data, data->worldDraw.vertexLayerDataSize);
				ZoneBuffer::clear_pointer(&dest->worldDraw.vld.data);
			}

			if (data->worldDraw.indices)
			{
				buf->align(1);
				buf->write_p(data->worldDraw.indices, data->worldDraw.indexCount);
				ZoneBuffer::clear_pointer(&dest->worldDraw.indices);
			}

			if (data->lightGrid.rowDataStart)
			{
				buf->align(1);
				buf->write_p(data->lightGrid.rowDataStart,
				             data->lightGrid.maxs[data->lightGrid.rowAxis] - data->lightGrid.mins[data
				                                                                                  ->lightGrid.rowAxis] +
				             1);
				ZoneBuffer::clear_pointer(&dest->lightGrid.rowDataStart);
			}

			if (data->lightGrid.rawRowData)
			{
				buf->align(0);
				buf->write_p(data->lightGrid.rawRowData, data->lightGrid.rawRowDataSize);
				ZoneBuffer::clear_pointer(&dest->lightGrid.rawRowData);
			}

			if (data->lightGrid.entries)
			{
				buf->align(3);
				buf->write(data->lightGrid.entries, data->lightGrid.entryCount);
				ZoneBuffer::clear_pointer(&dest->lightGrid.entries);
			}

			if (data->lightGrid.colors)
			{
				buf->align(3);
				buf->write(data->lightGrid.colors, data->lightGrid.colorCount);
				ZoneBuffer::clear_pointer(&dest->lightGrid.colors);
			}

			if (data->models)
			{
				buf->align(3);
				buf->write(data->models, data->modelCount);
				ZoneBuffer::clear_pointer(&dest->models);
			}

			if (data->materialMemory)
			{
				buf->align(3);
				auto memory = buf->write(data->materialMemory, data->materialMemoryCount);

				for (std::int32_t i = 0; i < data->materialMemoryCount; i++)
				{
					memory[i].material = reinterpret_cast<Material*>(zone->get_asset_pointer(
						material, data->materialMemory[i].material->name));
				}

				ZoneBuffer::clear_pointer(&dest->materialMemory);
			}

			if (data->sun.spriteMaterial)
			{
				dest->sun.spriteMaterial = reinterpret_cast<Material*>(zone->get_asset_pointer(
					material, data->sun.spriteMaterial->name));
			}
			if (data->sun.flareMaterial)
			{
				dest->sun.flareMaterial = reinterpret_cast<Material*>(zone->get_asset_pointer(
					material, data->sun.flareMaterial->name));
			}

			if (data->outdoorImage)
			{
				dest->outdoorImage = reinterpret_cast<GfxImage*>(zone->get_asset_pointer(image, data->outdoorImage->name)
				);
			}

			buf->push_stream(2);
			if (data->cellCasterBits[0])
			{
				buf->align(3);
				buf->write(data->cellCasterBits[0],
				           data->dpvsPlanes.cellCount * ((data->dpvsPlanes.cellCount + 31) >> 5));
				ZoneBuffer::clear_pointer(&dest->cellCasterBits[0]);
			}

			if (data->cellCasterBits[1])
			{
				buf->align(3);
				buf->write(data->cellCasterBits[1], (data->dpvsPlanes.cellCount + 31) >> 5);
				ZoneBuffer::clear_pointer(&dest->cellCasterBits[1]);
			}

			if (data->sceneDynModel)
			{
				buf->align(3);
				buf->write(data->sceneDynModel, data->dpvsDyn.dynEntClientCount[0]);
				ZoneBuffer::clear_pointer(&dest->sceneDynModel);
			}

			if (data->sceneDynBrush)
			{
				buf->align(3);
				buf->write(data->sceneDynBrush, data->dpvsDyn.dynEntClientCount[1]);
				ZoneBuffer::clear_pointer(&dest->sceneDynBrush);
			}

			if (data->primaryLightEntityShadowVis)
			{
				buf->align(3);
				buf->write(data->primaryLightEntityShadowVis,
				           (data->primaryLightCount - data->sunPrimaryLightIndex - 1) << 15);
				ZoneBuffer::clear_pointer(&dest->primaryLightEntityShadowVis);
			}

			if (data->primaryLightDynEntShadowVis[0])
			{
				buf->align(3);
				buf->write(data->primaryLightDynEntShadowVis[0],
				           data->dpvsDyn.dynEntClientCount[0] * (data->primaryLightCount - data->sunPrimaryLightIndex -
					           1));
				ZoneBuffer::clear_pointer(&dest->primaryLightDynEntShadowVis[0]);
			}

			if (data->primaryLightDynEntShadowVis[1])
			{
				buf->align(3);
				buf->write(data->primaryLightDynEntShadowVis[1],
				           data->dpvsDyn.dynEntClientCount[1] * (data->primaryLightCount - data->sunPrimaryLightIndex -
					           1));
				ZoneBuffer::clear_pointer(&dest->primaryLightDynEntShadowVis[1]);
			}

			if (data->primaryLightForModelDynEnt)
			{
				buf->align(0);
				buf->write(data->primaryLightForModelDynEnt, data->dpvsDyn.dynEntClientCount[0]);
				ZoneBuffer::clear_pointer(&dest->primaryLightForModelDynEnt);
			}
			buf->pop_stream();

			if (data->shadowGeom)
			{
				buf->align(3);
				auto shadow_geometry = buf->write(data->shadowGeom, data->primaryLightCount);

				for (std::int32_t i = 0; i < data->primaryLightCount; i++)
				{
					if (data->shadowGeom[i].sortedSurfIndex)
					{
						buf->align(1);
						buf->write_p(data->shadowGeom[i].sortedSurfIndex, data->shadowGeom[i].surfaceCount);
						ZoneBuffer::clear_pointer(&shadow_geometry[i].sortedSurfIndex);
					}
					if (data->shadowGeom[i].smodelIndex)
					{
						buf->align(1);
						buf->write_p(data->shadowGeom[i].smodelIndex, data->shadowGeom[i].smodelCount);
						ZoneBuffer::clear_pointer(&shadow_geometry[i].smodelIndex);
					}
				}

				ZoneBuffer::clear_pointer(&dest->shadowGeom);
			}

			if (data->lightRegion)
			{
				buf->align(3);
				auto light_region = buf->write(data->lightRegion, data->primaryLightCount);

				for (std::int32_t i = 0; i < data->primaryLightCount; i++)
				{
					if (data->lightRegion[i].hulls)
					{
						buf->align(3);
						auto light_region_hull = buf->write(data->lightRegion[i].hulls, data->lightRegion[i].hullCount);

						for (std::uint32_t i2 = 0; i2 < data->lightRegion[i].hullCount; i2++)
						{
							if (data->lightRegion[i].hulls[i2].axis)
							{
								buf->align(3);
								buf->write(data->lightRegion[i].hulls[i2].axis,
								           data->lightRegion[i].hulls[i2].axisCount);
								ZoneBuffer::clear_pointer(&light_region_hull[i2].axis);
							}
						}

						ZoneBuffer::clear_pointer(&light_region[i].hulls);
					}
				}

				ZoneBuffer::clear_pointer(&dest->lightRegion);
			}

			buf->push_stream(2);
			if (data->dpvs.smodelVisData[0])
			{
				buf->align(0);
				buf->write(data->dpvs.smodelVisData[0], data->dpvs.smodelCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.smodelVisData[0]);
			}

			if (data->dpvs.smodelVisData[1])
			{
				buf->align(0);
				buf->write(data->dpvs.smodelVisData[1], data->dpvs.smodelCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.smodelVisData[1]);
			}

			if (data->dpvs.smodelVisData[2])
			{
				buf->align(0);
				buf->write(data->dpvs.smodelVisData[2], data->dpvs.smodelCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.smodelVisData[2]);
			}

			if (data->dpvs.surfaceVisData[0])
			{
				buf->align(0);
				buf->write(data->dpvs.surfaceVisData[0], data->dpvs.staticSurfaceCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.surfaceVisData[0]);
			}

			if (data->dpvs.surfaceVisData[1])
			{
				buf->align(0);
				buf->write(data->dpvs.surfaceVisData[1], data->dpvs.staticSurfaceCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.surfaceVisData[1]);
			}

			if (data->dpvs.surfaceVisData[2])
			{
				buf->align(0);
				buf->write(data->dpvs.surfaceVisData[2], data->dpvs.staticSurfaceCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.surfaceVisData[2]);
			}
			buf->pop_stream();

			if (data->dpvs.sortedSurfIndex)
			{
				buf->align(1);
				buf->write_p(data->dpvs.sortedSurfIndex,
				             data->dpvs.staticSurfaceCount + data->dpvs.staticSurfaceCountNoDecal);
				ZoneBuffer::clear_pointer(&dest->dpvs.sortedSurfIndex);
			}

			if (data->dpvs.smodelInsts)
			{
				buf->align(3);
				buf->write(data->dpvs.smodelInsts, data->dpvs.smodelCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.smodelInsts);
			}

			if (data->dpvs.surfaces)
			{
				buf->align(3);
				auto surface = buf->write(data->dpvs.surfaces, data->indexCount);

				for (std::int32_t i = 0; i < data->indexCount; i++)
				{
					if (data->dpvs.surfaces[i].material)
					{
						surface[i].material = reinterpret_cast<Material*>(zone->get_asset_pointer(
							material, data->dpvs.surfaces[i].material->name));
					}

					assert(surface[i].material != nullptr);
				}

				ZoneBuffer::clear_pointer(&dest->dpvs.surfaces);
			}
			assert(data->indexCount > 0);
			assert(data->dpvs.surfaces != nullptr);

			if (data->dpvs.surfacesBounds)
			{
				buf->align(3);
				buf->write(data->dpvs.surfacesBounds, data->indexCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.surfacesBounds);
			}

			if (data->dpvs.smodelDrawInsts)
			{
				buf->align(3);
				auto static_model_draw_inst = buf->write(data->dpvs.smodelDrawInsts, data->dpvs.smodelCount);

				for (std::uint32_t i = 0; i < data->dpvs.smodelCount; i++)
				{
					if (data->dpvs.smodelDrawInsts[i].model)
					{
						static_model_draw_inst[i].model = reinterpret_cast<XModel*>(zone->get_asset_pointer(
							xmodel, data->dpvs.smodelDrawInsts[i].model->name));
					}
				}

				ZoneBuffer::clear_pointer(&dest->dpvs.smodelDrawInsts);
			}

			buf->push_stream(2);
			if (data->dpvs.surfaceMaterials)
			{
				buf->align(7);
				buf->write(data->dpvs.surfaceMaterials, data->indexCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.smodelDrawInsts);
			}

			if (data->dpvs.surfaceCastsSunShadow)
			{
				buf->align(127);
				buf->write(data->dpvs.surfaceCastsSunShadow, data->dpvs.surfaceVisDataCount);
				ZoneBuffer::clear_pointer(&dest->dpvs.surfaceCastsSunShadow);
			}

			if (data->dpvsDyn.dynEntCellBits[0])
			{
				buf->align(3);
				buf->write(data->dpvsDyn.dynEntCellBits[0],
				           data->dpvsDyn.dynEntClientWordCount[0] * data->dpvsPlanes.cellCount);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntCellBits[0]);
			}

			if (data->dpvsDyn.dynEntCellBits[1])
			{
				buf->align(3);
				buf->write(data->dpvsDyn.dynEntCellBits[1],
				           data->dpvsDyn.dynEntClientWordCount[1] * data->dpvsPlanes.cellCount);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntCellBits[1]);
			}

			if (data->dpvsDyn.dynEntVisData[0][0])
			{
				buf->align(15);
				buf->write(data->dpvsDyn.dynEntVisData[0][0], 32 * data->dpvsDyn.dynEntClientWordCount[0]);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntVisData[0][0]);
			}

			if (data->dpvsDyn.dynEntVisData[1][0])
			{
				buf->align(15);
				buf->write(data->dpvsDyn.dynEntVisData[1][0], 32 * data->dpvsDyn.dynEntClientWordCount[1]);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntVisData[1][0]);
			}

			if (data->dpvsDyn.dynEntVisData[0][1])
			{
				buf->align(15);
				buf->write(data->dpvsDyn.dynEntVisData[0][1], 32 * data->dpvsDyn.dynEntClientWordCount[0]);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntVisData[0][1]);
			}

			if (data->dpvsDyn.dynEntVisData[1][1])
			{
				buf->align(15);
				buf->write(data->dpvsDyn.dynEntVisData[1][1], 32 * data->dpvsDyn.dynEntClientWordCount[1]);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntVisData[1][1]);
			}

			if (data->dpvsDyn.dynEntVisData[0][2])
			{
				buf->align(15);
				buf->write(data->dpvsDyn.dynEntVisData[0][2], 32 * data->dpvsDyn.dynEntClientWordCount[0]);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntVisData[0][2]);
			}

			if (data->dpvsDyn.dynEntVisData[1][2])
			{
				buf->align(15);
				buf->write(data->dpvsDyn.dynEntVisData[1][2], 32 * data->dpvsDyn.dynEntClientWordCount[1]);
				ZoneBuffer::clear_pointer(&dest->dpvsDyn.dynEntVisData[1][2]);
			}
			buf->pop_stream();

			if (data->heroLights)
			{
				buf->align(3);
				buf->write(data->heroLights, data->heroLightCount);
				ZoneBuffer::clear_pointer(&dest->heroLights);
			}

			END_LOG_STREAM;
			buf->pop_stream();

			//encrypt_data(dest, sizeof GfxWorld);
#ifdef USE_VMPROTECT
			VMProtectEnd();
#endif
		}

		void IGfxWorld::dump(GfxWorld* asset)
		{
			// dump code
			AssetDumper write;
			if (!write.open(asset->name + ".gfxmap"s))
			{
				return;
			}

			write.dump_string(asset->name);
			write.dump_string(asset->baseName);

			write.dump_int(asset->planeCount);
			write.dump_int(asset->nodeCount);
			write.dump_int(asset->indexCount);
			write.dump_int(asset->skyCount);

			write.dump_array(asset->skies, asset->skyCount);
			for (unsigned int i = 0; i < asset->skyCount; i++)
			{
				write.dump_array(asset->skies[i].skyStartSurfs, asset->skies[i].skySurfCount);
				write.dump_asset(asset->skies[i].skyImage);
			}

			write.dump_int(asset->sunPrimaryLightIndex);
			write.dump_int(asset->primaryLightCount);
			write.dump_int(asset->primaryLightEnvCount);

			write.dump_array(asset->unknown1, 12);

			// dpvsplanes
			write.dump_int(asset->dpvsPlanes.cellCount);
			write.dump_array(asset->dpvsPlanes.planes, asset->planeCount);
			write.dump_array(asset->dpvsPlanes.nodes, asset->nodeCount);
			write.dump_array(asset->dpvsPlanes.sceneEntCellBits, asset->dpvsPlanes.cellCount << 11);

			// dpvs
			write.dump_array(&asset->dpvs, 1);
			write.dump_array(asset->dpvs.smodelVisData[0], asset->dpvs.smodelCount);
			write.dump_array(asset->dpvs.smodelVisData[1], asset->dpvs.smodelCount);
			write.dump_array(asset->dpvs.smodelVisData[2], asset->dpvs.smodelCount);
			write.dump_array(asset->dpvs.surfaceVisData[0], asset->dpvs.staticSurfaceCount);
			write.dump_array(asset->dpvs.surfaceVisData[1], asset->dpvs.staticSurfaceCount);
			write.dump_array(asset->dpvs.surfaceVisData[2], asset->dpvs.staticSurfaceCount);
			write.dump_array(asset->dpvs.sortedSurfIndex,
			            (asset->dpvs.staticSurfaceCount + asset->dpvs.staticSurfaceCountNoDecal));
			write.dump_array(asset->dpvs.smodelInsts, asset->dpvs.smodelCount);
			write.dump_array(asset->dpvs.surfaces, asset->indexCount);

			for (int i = 0; i < asset->indexCount; i++)
			{
				write.dump_asset(asset->dpvs.surfaces[i].material);
			}

			write.dump_array(asset->dpvs.surfacesBounds, asset->indexCount);
			write.dump_array(asset->dpvs.smodelDrawInsts, asset->dpvs.smodelCount);

			for (unsigned int i = 0; i < asset->dpvs.smodelCount; i++)
			{
				write.dump_asset(asset->dpvs.smodelDrawInsts[i].model);
			}
			write.dump_array(asset->dpvs.surfaceMaterials, asset->indexCount);
			write.dump_array(asset->dpvs.surfaceCastsSunShadow, asset->dpvs.surfaceVisDataCount);

			// dpvsDyn
			write.dump_array(&asset->dpvsDyn, 1);
			write.dump_array(asset->dpvsDyn.dynEntCellBits[0],
			            asset->dpvsDyn.dynEntClientWordCount[0] * asset->dpvsPlanes.cellCount);
			write.dump_array(asset->dpvsDyn.dynEntCellBits[1],
			            asset->dpvsDyn.dynEntClientWordCount[1] * asset->dpvsPlanes.cellCount);
			write.dump_array(asset->dpvsDyn.dynEntVisData[0][0], asset->dpvsDyn.dynEntClientWordCount[0] * 32);
			write.dump_array(asset->dpvsDyn.dynEntVisData[1][0], asset->dpvsDyn.dynEntClientWordCount[1] * 32);
			write.dump_array(asset->dpvsDyn.dynEntVisData[0][1], asset->dpvsDyn.dynEntClientWordCount[0] * 32);
			write.dump_array(asset->dpvsDyn.dynEntVisData[1][1], asset->dpvsDyn.dynEntClientWordCount[1] * 32);
			write.dump_array(asset->dpvsDyn.dynEntVisData[0][2], asset->dpvsDyn.dynEntClientWordCount[0] * 32);
			write.dump_array(asset->dpvsDyn.dynEntVisData[1][2], asset->dpvsDyn.dynEntClientWordCount[1] * 32);

			// aabbTreeCount
			write.dump_array(asset->aabbTreeCounts, asset->dpvsPlanes.cellCount);

			// GfxCellTree
			write.dump_array(asset->aabbTree, asset->dpvsPlanes.cellCount);
			for (int i = 0; i < asset->dpvsPlanes.cellCount; i++)
			{
				write.dump_array(asset->aabbTree[i].aabbtree, asset->aabbTreeCounts[i].aabbTreeCount);

				for (int j = 0; j < asset->aabbTreeCounts[i].aabbTreeCount; j++)
				{
					write.dump_array(asset->aabbTree[i].aabbtree[j].smodelIndexes,
					            asset->aabbTree[i].aabbtree[j].smodelIndexCount);
				}
			}

			// read GFX cells
			write.dump_array(asset->cells, asset->dpvsPlanes.cellCount);

			for (int i = 0; i < asset->dpvsPlanes.cellCount; i++)
			{
				write.dump_array(asset->cells[i].portals, asset->cells[i].portalCount);
				for (int j = 0; j < asset->cells[i].portalCount; j++)
				{
					write.dump_array(asset->cells[i].portals[j].vertices, asset->cells[i].portals[j].vertexCount);
				}
				write.dump_array(asset->cells[i].reflectionProbes, asset->cells[i].reflectionProbeCount);
				write.dump_array(asset->cells[i].reflectionProbeReferences, asset->cells[i].reflectionProbeReferenceCount);
			}

			// draw
			write.dump_array(&asset->worldDraw, 1);

			for (unsigned int i = 0; i < asset->worldDraw.reflectionProbeCount; i++)
			{
				write.dump_asset(asset->worldDraw.reflectionImages[i]);
			}

			write.dump_array(asset->worldDraw.reflectionProbes, asset->worldDraw.reflectionProbeCount);

			write.dump_array(asset->worldDraw.reflectionProbeReferences, asset->worldDraw.reflectionProbeReferenceCount);
			write.dump_array(asset->worldDraw.reflectionProbeReferenceOrigins,
			            asset->worldDraw.reflectionProbeReferenceCount);

			write.dump_array(asset->worldDraw.reflectionProbeTextures, asset->worldDraw.reflectionProbeCount);
			write.dump_array(asset->worldDraw.lightmaps, asset->worldDraw.lightmapCount);

			for (int i = 0; i < asset->worldDraw.lightmapCount; i++)
			{
				write.dump_asset(asset->worldDraw.lightmaps[i].primary);
				write.dump_asset(asset->worldDraw.lightmaps[i].secondary);
			}

			write.dump_array(asset->worldDraw.lightmapPrimaryTextures, asset->worldDraw.lightmapCount);
			write.dump_array(asset->worldDraw.lightmapSecondaryTextures, asset->worldDraw.lightmapCount);

			write.dump_asset(asset->worldDraw.skyImage);
			write.dump_asset(asset->worldDraw.outdoorImage);

			write.dump_array(asset->worldDraw.vd.vertices, asset->worldDraw.vertexCount);
			write.dump_array(asset->worldDraw.vld.data, asset->worldDraw.vertexLayerDataSize);
			write.dump_array(asset->worldDraw.indices, asset->worldDraw.indexCount);

			// GfxLightGrid
			write.dump_array(&asset->lightGrid, 1);
			write.dump_array(asset->lightGrid.rowDataStart,
			            (asset->lightGrid.maxs[asset->lightGrid.rowAxis] - asset->lightGrid.mins[asset
			                                                                                     ->lightGrid.rowAxis] +
				            1));
			write.dump_array(asset->lightGrid.rawRowData, asset->lightGrid.rawRowDataSize);
			write.dump_array(asset->lightGrid.entries, asset->lightGrid.entryCount);
			write.dump_array(asset->lightGrid.colors, asset->lightGrid.colorCount);

			// models
			write.dump_int(asset->modelCount);
			write.dump_array(asset->models, asset->modelCount);

			// mins/maxs
			write.dump_array(asset->mins, 3);
			write.dump_array(asset->maxs, 3);

			write.dump_int(asset->checksum);

			// materialmemory
			write.dump_int(asset->materialMemoryCount);
			write.dump_array(asset->materialMemory, asset->materialMemoryCount);
			for (int i = 0; i < asset->materialMemoryCount; i++)
			{
				write.dump_asset(asset->materialMemory[i].material);
			}

			// sun data
			write.dump_array(&asset->sun, 1);
			write.dump_asset(asset->sun.spriteMaterial);
			write.dump_asset(asset->sun.flareMaterial);

			// outdoor shit
			write.dump_array(asset->outdoorLookupMatrix, 4);
			write.dump_asset(asset->outdoorImage);

			// CellcasterBits
			write.dump_array(asset->cellCasterBits[0],
			            asset->dpvsPlanes.cellCount * ((asset->dpvsPlanes.cellCount + 31) >> 5));
			write.dump_array(asset->cellCasterBits[1], (asset->dpvsPlanes.cellCount + 31) >> 5);

			// SceneDynModel
			write.dump_array(asset->sceneDynModel, asset->dpvsDyn.dynEntClientCount[0]);

			// SceneDynBrush
			write.dump_array(asset->sceneDynBrush, asset->dpvsDyn.dynEntClientCount[1]);

			// PrimaryLightEntityShadowVis
			write.dump_array(asset->primaryLightEntityShadowVis,
			            (asset->primaryLightCount - asset->sunPrimaryLightIndex - 1) << 15);

			// PrimaryLightDynEntShadowVis
			write.dump_array(asset->primaryLightDynEntShadowVis[0],
			            asset->dpvsDyn.dynEntClientCount[0] * (asset->primaryLightCount - asset->sunPrimaryLightIndex -
				            1));
			write.dump_array(asset->primaryLightDynEntShadowVis[1],
			            asset->dpvsDyn.dynEntClientCount[1] * (asset->primaryLightCount - asset->sunPrimaryLightIndex -
				            1));

			// PrimaryLightForModelDynEnt
			write.dump_array(asset->primaryLightForModelDynEnt, asset->dpvsDyn.dynEntClientCount[0]);

			// GfxShadowGeometry
			write.dump_array(asset->shadowGeom, asset->primaryLightCount);
			for (int i = 0; i < asset->primaryLightCount; i++)
			{
				write.dump_array(asset->shadowGeom[i].sortedSurfIndex, asset->shadowGeom[i].surfaceCount);
				write.dump_array(asset->shadowGeom[i].smodelIndex, asset->shadowGeom[i].smodelCount);
			}

			// GfxLightRegion
			write.dump_array(asset->lightRegion, asset->primaryLightCount);
			for (int i = 0; i < asset->primaryLightCount; i++)
			{
				write.dump_array(asset->lightRegion[i].hulls, asset->lightRegion[i].hullCount);
				for (unsigned int j = 0; j < asset->lightRegion[i].hullCount; j++)
				{
					write.dump_array(asset->lightRegion[i].hulls[j].axis, asset->lightRegion[i].hulls[j].axisCount);
				}
			}

			write.dump_int(asset->mapVtxChecksum);
			write.dump_int(asset->fogTypesAllowed);

			// save file to disk!
			write.close();
		}
	}
}
