diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index 6f3b0971..4662b508 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -511,11 +511,11 @@ CFileLoader::LoadObjectTypes(const char *filename)
 	int pathIndex;
 	char pathTypeStr[20];
 	int id, pathType;
-//	int mlo;
+	int mlo;
 
 	section = NONE;
 	pathIndex = -1;
-//	mlo = 0;
+	mlo = 0;
 	debug("Loading object types from %s...\n", filename);
 
 	fd = CFileMgr::OpenFile(filename, "rb");
@@ -536,12 +536,12 @@ CFileLoader::LoadObjectTypes(const char *filename)
 		}else switch(section){
 		case OBJS:
 			if(strncmp(line, "sta", 3) == 0)
-				assert(0);	// LoadMLO
+				mlo = LoadMLO(line);
 			else
 				LoadObject(line);
 			break;
 		case MLO:
-			assert(0);	// LoadMLOInstance
+			LoadMLOInstance(mlo, line);
 			break;
 		case TOBJ:
 			LoadTimeObject(line);
@@ -644,6 +644,57 @@ CFileLoader::LoadObject(const char *line)
 	MatchModelString(model, id);
 }
 
+int
+CFileLoader::LoadMLO(const char *line)
+{
+	char smth[8];
+	char name[24];
+	int modelIndex;
+	float someFloat;
+
+	sscanf(line, "%s %s %d %f", smth, name, &modelIndex, &someFloat);
+	CMloModelInfo *minfo = CModelInfo::AddMloModel(modelIndex);
+	minfo->SetName(name);
+	minfo->field_34 = someFloat;
+	int instId = CModelInfo::GetMloInstanceStore()->allocPtr;
+	minfo->firstInstance = instId;
+	minfo->lastInstance = instId;
+	minfo->SetTexDictionary("generic");
+	return modelIndex;
+}
+
+void
+CFileLoader::LoadMLOInstance(int id, const char *line)
+{
+	char name[24];
+	RwV3d pos, scale, rot;
+	float angle;
+	int modelIndex;
+
+	CMloModelInfo *minfo = (CMloModelInfo*)CModelInfo::GetModelInfo(id);
+	sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f",
+		&modelIndex,
+		name,
+		&pos.x, &pos.y, &pos.z,
+		&scale.x, &scale.y, &scale.z,
+		&rot.x, &rot.y, &rot.z,
+		&angle);
+	float rad = 2.0f * (PI / 2.0f - atan2(angle, sqrt(1.0f - SQR(angle))));
+	CInstance *inst = CModelInfo::GetMloInstanceStore()->alloc();
+	minfo->lastInstance++;
+
+	RwMatrix *matrix = RwMatrixCreate();
+	RwMatrixScale(matrix, &scale, rwCOMBINEREPLACE);
+	RwMatrixRotate(matrix, &rot, -RADTODEG(rad), rwCOMBINEPOSTCONCAT);
+	RwMatrixTranslate(matrix, &pos, rwCOMBINEPOSTCONCAT);
+
+	inst->GetMatrix() = CMatrix(matrix);
+	inst->GetMatrix().UpdateRW();
+
+	inst->m_modelIndex = modelIndex;
+	RwMatrixDestroy(matrix);
+}
+
 void
 CFileLoader::LoadTimeObject(const char *line)
 {
diff --git a/src/core/FileLoader.h b/src/core/FileLoader.h
index 7ef96da3..1b390279 100644
--- a/src/core/FileLoader.h
+++ b/src/core/FileLoader.h
@@ -23,6 +23,8 @@ public:
 
 	static void LoadObjectTypes(const char *filename);
 	static void LoadObject(const char *line);
+	static int LoadMLO(const char *line);
+	static void LoadMLOInstance(int id, const char *line);
 	static void LoadTimeObject(const char *line);
 	static void LoadClumpObject(const char *line);
 	static void LoadVehicleObject(const char *line);
diff --git a/src/core/Instance.h b/src/core/Instance.h
index bb74ea84..4a7f9aa9 100644
--- a/src/core/Instance.h
+++ b/src/core/Instance.h
@@ -4,8 +4,10 @@
 
 // unused
 
-class CInstance : CPlaceable
+class CInstance : public CPlaceable
 {
+public:
+	int m_modelIndex;
 public:
 	~CInstance() = default;
 };
diff --git a/src/core/config.h b/src/core/config.h
index cbaf4d9a..de96ad1b 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -11,10 +11,13 @@ enum Config {
 	CUTSCENEDIRSIZE = 512,
 
 	SIMPLEMODELSIZE = 5000,
+	MLOMODELSIZE = 1,
+	MLOINSTANCESIZE = 1,
 	TIMEMODELSIZE = 30,
 	CLUMPMODELSIZE = 5,
 	PEDMODELSIZE = 90,
 	VEHICLEMODELSIZE = 120,
+	XTRACOMPSMODELSIZE = 2,
 	TWODFXSIZE = 2000,
 
 	MAXVEHICLESLOADED = 50,	// 70 on mobile
diff --git a/src/entities/Solid.h b/src/entities/Solid.h
new file mode 100644
index 00000000..f4679b3b
--- /dev/null
+++ b/src/entities/Solid.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "Entity.h"
+
+class CSolid : public CEntity
+{
+public:
+	CSolid(void) {
+		bRemoveFromWorld = true;
+		bHasHitWall = false;
+		bImBeingRendered = false;
+		m_flagE2 = true;
+	}
+};
\ No newline at end of file
diff --git a/src/modelinfo/MloModelInfo.cpp b/src/modelinfo/MloModelInfo.cpp
new file mode 100644
index 00000000..693f1fb6
--- /dev/null
+++ b/src/modelinfo/MloModelInfo.cpp
@@ -0,0 +1,39 @@
+#include "common.h"
+#include "patcher.h"
+#include "VisibilityPlugins.h"
+#include "ModelInfo.h"
+
+void
+CMloModelInfo::ConstructClump()
+{
+	m_clump = RpClumpCreate();
+	RwFrame *mainFrame = RwFrameCreate();
+	RwFrameSetIdentity(mainFrame);
+	RpClumpSetFrame(m_clump, mainFrame);
+
+	for (int i = firstInstance; i < lastInstance; i++) {
+		int modelId = CModelInfo::GetMloInstanceStore()->store[i].m_modelIndex;
+		RwMatrix *attMat = CModelInfo::GetMloInstanceStore()->store[i].GetMatrix().m_attachment;
+		CSimpleModelInfo *minfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(modelId);
+
+		if (minfo->m_atomics[0] != nil) {
+			RpAtomic *newAtomic = RpAtomicClone(minfo->m_atomics[0]);
+			RwFrame *newFrame = RwFrameCreate();
+			if (newAtomic != nil && newFrame != nil) {
+				*RwFrameGetMatrix(newFrame) = *attMat;
+				RpAtomicSetFrame(newAtomic, newFrame);
+				RwFrameAddChild(mainFrame, newFrame);
+				RpClumpAddAtomic(m_clump, newAtomic);
+			} else {
+				debug("Failed to allocate memory while creating template MLO.\n");
+			}
+		}
+	}
+
+	if (RpClumpGetNumAtomics(m_clump) != 0) {
+		CVisibilityPlugins::SetClumpModelInfo(m_clump, this);
+	} else {
+		RpClumpDestroy(m_clump);
+		m_clump = nil;
+	}
+}
\ No newline at end of file
diff --git a/src/modelinfo/MloModelInfo.h b/src/modelinfo/MloModelInfo.h
new file mode 100644
index 00000000..19ae63d5
--- /dev/null
+++ b/src/modelinfo/MloModelInfo.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "ClumpModelInfo.h"
+
+class CMloModelInfo : public CClumpModelInfo
+{
+public:
+	float field_34; // draw distance?
+	int firstInstance;
+	int lastInstance;
+public:
+	CMloModelInfo(void) : CClumpModelInfo(MITYPE_MLO) {}
+	void ConstructClump();
+};
\ No newline at end of file
diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp
index c7e18e5f..fdde699b 100644
--- a/src/modelinfo/ModelInfo.cpp
+++ b/src/modelinfo/ModelInfo.cpp
@@ -11,10 +11,13 @@ CBaseModelInfo **CModelInfo::ms_modelInfoPtrs = (CBaseModelInfo**)0x83D408;
 //CStore<CTimeModelInfo, TIMEMODELSIZE> &CModelInfo::ms_timeModelStore = *(CStore<CTimeModelInfo, TIMEMODELSIZE>*)0x94076C;
 //CStore<C2dEffect, TWODFXSIZE> &CModelInfo::ms_2dEffectStore = *(CStore<C2dEffect, TWODFXSIZE>*)0x9434F8;
 CStore<CSimpleModelInfo, SIMPLEMODELSIZE> CModelInfo::ms_simpleModelStore;
+CStore<CMloModelInfo, MLOMODELSIZE> CModelInfo::ms_mloModelStore;
+CStore<CInstance, MLOINSTANCESIZE> CModelInfo::ms_mloInstanceStore;
 CStore<CTimeModelInfo, TIMEMODELSIZE> CModelInfo::ms_timeModelStore;
 CStore<CClumpModelInfo, CLUMPMODELSIZE> CModelInfo::ms_clumpModelStore;
 CStore<CPedModelInfo, PEDMODELSIZE> CModelInfo::ms_pedModelStore;
 CStore<CVehicleModelInfo, VEHICLEMODELSIZE> CModelInfo::ms_vehicleModelStore;
+CStore<CXtraCompsModelInfo, XTRACOMPSMODELSIZE> CModelInfo::ms_xtraCompsModelStore;
 CStore<C2dEffect, TWODFXSIZE> CModelInfo::ms_2dEffectStore;
 
 void
@@ -26,8 +29,11 @@ CModelInfo::Initialise(void)
 	for(i = 0; i < MODELINFOSIZE; i++)
 		ms_modelInfoPtrs[i] = nil;
 	ms_2dEffectStore.clear();
+	ms_mloInstanceStore.clear();
+	ms_xtraCompsModelStore.clear();
 	ms_simpleModelStore.clear();
 	ms_timeModelStore.clear();
+	ms_mloModelStore.clear();
 	ms_clumpModelStore.clear();
 	ms_pedModelStore.clear();
 	ms_vehicleModelStore.clear();
@@ -109,6 +115,18 @@ CModelInfo::AddSimpleModel(int id)
 	return modelinfo;
 }
 
+CMloModelInfo *
+CModelInfo::AddMloModel(int id)
+{
+	CMloModelInfo *modelinfo;
+	modelinfo = CModelInfo::ms_mloModelStore.alloc();
+	CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
+	modelinfo->m_clump = 0;
+	modelinfo->firstInstance = 0;
+	modelinfo->lastInstance = 0;
+	return modelinfo;
+}
+
 CTimeModelInfo*
 CModelInfo::AddTimeModel(int id)
 {
@@ -200,6 +218,13 @@ CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level)
 	}
 }
 
+
+CStore<CInstance, MLOINSTANCESIZE>*
+CModelInfo::GetMloInstanceStore()
+{
+	return &CModelInfo::ms_mloInstanceStore;
+}
+
 STARTPATCHES
 	InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP);
 	InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP);
diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h
index ee82276d..1a295264 100644
--- a/src/modelinfo/ModelInfo.h
+++ b/src/modelinfo/ModelInfo.h
@@ -3,26 +3,33 @@
 #include "2dEffect.h"
 #include "BaseModelInfo.h"
 #include "SimpleModelInfo.h"
+#include "MloModelInfo.h"
 #include "TimeModelInfo.h"
 #include "ClumpModelInfo.h"
 #include "PedModelInfo.h"
 #include "VehicleModelInfo.h"
+#include "XtraCompsModelInfo.h"
+#include "Instance.h"
 
 class CModelInfo
 {
 	static CBaseModelInfo **ms_modelInfoPtrs; //[MODELINFOSIZE];
 	static CStore<CSimpleModelInfo, SIMPLEMODELSIZE> ms_simpleModelStore;
+	static CStore<CMloModelInfo, MLOMODELSIZE> ms_mloModelStore;
+	static CStore<CInstance, MLOINSTANCESIZE> ms_mloInstanceStore;
 	static CStore<CTimeModelInfo, TIMEMODELSIZE> ms_timeModelStore;
 	static CStore<CClumpModelInfo, CLUMPMODELSIZE> ms_clumpModelStore;
 	static CStore<CPedModelInfo, PEDMODELSIZE> ms_pedModelStore;
 	static CStore<CVehicleModelInfo, VEHICLEMODELSIZE> ms_vehicleModelStore;
 	static CStore<C2dEffect, TWODFXSIZE> ms_2dEffectStore;
+	static CStore<CXtraCompsModelInfo, XTRACOMPSMODELSIZE> ms_xtraCompsModelStore;
 
 public:
 	static void Initialise(void);
 	static void ShutDown(void);
 
 	static CSimpleModelInfo *AddSimpleModel(int id);
+	static CMloModelInfo *AddMloModel(int id);
 	static CTimeModelInfo *AddTimeModel(int id);
 	static CClumpModelInfo *AddClumpModel(int id);
 	static CPedModelInfo *AddPedModel(int id);
@@ -38,4 +45,5 @@ public:
 	static bool IsBoatModel(int32 id);
 	static bool IsBikeModel(int32 id);
 	static void RemoveColModelsFromOtherLevels(eLevelName level);
+	static CStore<CInstance, MLOINSTANCESIZE>* CModelInfo::GetMloInstanceStore();
 };
diff --git a/src/modelinfo/XtraCompsModelInfo.h b/src/modelinfo/XtraCompsModelInfo.h
new file mode 100644
index 00000000..bb37ffe3
--- /dev/null
+++ b/src/modelinfo/XtraCompsModelInfo.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "ClumpModelInfo.h"
+
+class CXtraCompsModelInfo : public CClumpModelInfo
+{
+	int field_34;
+public:
+	CXtraCompsModelInfo(void) : CClumpModelInfo(MITYPE_XTRACOMPS) { field_34 = 0; }
+	void SetClump(RpClump*) {};
+	void Shutdown(void) {};
+};
\ No newline at end of file
diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp
index fc68d315..e0db5732 100644
--- a/src/render/Fluff.cpp
+++ b/src/render/Fluff.cpp
@@ -1,6 +1,7 @@
 #include "common.h"
 #include "main.h"
 #include "patcher.h"
+#include "Entity.h"
 #include "Fluff.h"
 #include "Camera.h"
 #include "Sprite.h"
@@ -90,12 +91,19 @@ enum eScrollBarTypes
 CScrollBar    aScrollBars[11];
 CTowerClock   aTowerClocks[2];
 CDigitalClock aDigitalClocks[3];
+
+CMovingThing CMovingThings::StartCloseList;
+CMovingThing CMovingThings::EndCloseList;
+int16 CMovingThings::Num;
+CMovingThing CMovingThings::aMovingThings[NUMMOVINGTHINGS];
  
 void CMovingThings::Init()
 {
-	/*
-	 * Some unused code about CMovingThing was here...
-	 */
+	StartCloseList.m_pNext = &CMovingThings::EndCloseList;
+	StartCloseList.m_pPrev = nil;
+	EndCloseList.m_pNext = nil;
+	EndCloseList.m_pPrev = &CMovingThings::StartCloseList;
+	Num = 0;
 	
 	// Initialize scroll bars
 	 aScrollBars[0].Init(CVector(  228.3f,    -669.0f,     39.0f  ), SCROLL_BUSINESS,       0.0,     0.5,     0.5,   255, 128, 0,   0.3);
@@ -144,11 +152,22 @@ void CMovingThings::Shutdown()
 
 void CMovingThings::Update()
 {
-	/*
-	 * Some unused code about CMovingThing was here...
-	 */
+	const int TIME_SPAN = 64; // frames to process all aMovingThings
+
+	int16 i;
+
+	int block = CTimer::GetFrameCounter() % TIME_SPAN;
+
+	for (i = (block * NUMMOVINGTHINGS) / TIME_SPAN; i < ((block + 1) * NUMMOVINGTHINGS) / TIME_SPAN; i++) {
+		if (aMovingThings[i].field_A == 1)
+			aMovingThings[i].Update();
+	}
+
+	for (i = 0; i < CMovingThings::Num; i++) {
+		if (aMovingThings[i].field_A == 0)
+			aMovingThings[i].Update();
+	}
 
-	int i;
 	for (i = 0; i < 11; ++i)
 	{
 		if (aScrollBars[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0)
@@ -187,9 +206,50 @@ void CMovingThings::Render()
 }
 
 // ---------- CMovingThing ----------
-WRAPPER void CMovingThing::Update()         { EAXJMP(0x4FF290); }
-WRAPPER void CMovingThing::AddToList()      { EAXJMP(0x4FF320); }
-WRAPPER void CMovingThing::RemoveFromList() { EAXJMP(0x4FF340); }
+void CMovingThing::Update()
+{
+	m_pEntity->GetMatrix().UpdateRW();
+	m_pEntity->UpdateRwFrame();
+	
+	if (SQR(m_pEntity->GetPosition().x - TheCamera.GetPosition().x) + SQR(m_pEntity->GetPosition().y - TheCamera.GetPosition().y) < 40000.0f) {
+		if (field_A == 1) {
+			AddToList(&CMovingThings::StartCloseList);
+			field_A = 0;
+		}
+	} else {
+		if (field_A == 0) {
+			RemoveFromList();
+			field_A = 1;
+		}
+	}
+}
+
+void CMovingThing::AddToList(CMovingThing *pThing)
+{
+	m_pNext = pThing->m_pNext;
+	m_pPrev = pThing;
+	pThing->m_pNext = this;
+	m_pNext->m_pPrev = this;
+}
+
+void CMovingThing::RemoveFromList()
+{
+	m_pNext->m_pPrev = m_pPrev;
+	m_pPrev->m_pNext = m_pNext;
+}
+
+int16 CMovingThing::SizeList()
+{
+	CMovingThing *next = m_pNext;
+	int16 count = 0;
+
+	while (next != nil) {
+		next = next->m_pNext;
+		count++;
+	}
+
+	return count;
+}
 
 // ---------- Find message functions ----------
 const char* FindTunnelMessage()
@@ -806,6 +866,10 @@ void CDigitalClock::Render()
 }
 
 STARTPATCHES
+InjectHook(0x4FF290, &CMovingThing::Update, PATCH_JUMP);
+InjectHook(0x4FF320, &CMovingThing::AddToList, PATCH_JUMP);
+InjectHook(0x4FF340, &CMovingThing::RemoveFromList, PATCH_JUMP);
+
 InjectHook(0x4FE7C0, &CMovingThings::Init,     PATCH_JUMP);
 InjectHook(0x4FF020, &CMovingThings::Shutdown, PATCH_JUMP);
 InjectHook(0x4FF0D0, &CMovingThings::Update,   PATCH_JUMP);
diff --git a/src/render/Fluff.h b/src/render/Fluff.h
index b189b9a2..7ab2d81d 100644
--- a/src/render/Fluff.h
+++ b/src/render/Fluff.h
@@ -2,23 +2,38 @@
 #include "common.h"
 #include "Vector.h"
 
+class CMovingThing
+{
+public:
+	CMovingThing *m_pNext;
+	CMovingThing *m_pPrev;
+	int16 m_nType;
+	int16 field_A;
+	CVector m_vecPosn;
+	CEntity* m_pEntity;
+
+	void Update();
+	void AddToList(CMovingThing *pThing);
+	void RemoveFromList();
+	int16 SizeList();
+};
+
+#define NUMMOVINGTHINGS 128
+
 class CMovingThings
 {
 public:
+	static CMovingThing StartCloseList;
+	static CMovingThing EndCloseList;
+	static int16 Num;
+	static CMovingThing aMovingThings[NUMMOVINGTHINGS];
+
 	static void Init();
 	static void Shutdown();
 	static void Update();
 	static void Render();
 };
 
-class CMovingThing
-{
-public:
-	void Update();
-	void AddToList();
-	void RemoveFromList();
-};
-
 class CScrollBar
 {
 private: