diff --git a/openrct2.vcxproj b/openrct2.vcxproj
index df88b9b32d..d8f417eea1 100644
--- a/openrct2.vcxproj
+++ b/openrct2.vcxproj
@@ -127,6 +127,7 @@
+
@@ -444,6 +445,7 @@
+
diff --git a/src/object.h b/src/object.h
index 157348e49f..d5a2dea50a 100644
--- a/src/object.h
+++ b/src/object.h
@@ -114,7 +114,7 @@ int object_load_packed(SDL_RWops* rw);
bool object_saved_packed(SDL_RWops* rw, const rct_object_entry * entry);
void object_unload_all();
-int check_object_entry(rct_object_entry *entry);
+int check_object_entry(const rct_object_entry *entry);
bool object_load_chunk(int groupIndex, const rct_object_entry * entry, int * outGroupIndex);
bool object_entry_compare(const rct_object_entry *a, const rct_object_entry *b);
int object_calculate_checksum(const rct_object_entry * entry, const void * data, size_t dataLength);
diff --git a/src/object/ObjectManager.cpp b/src/object/ObjectManager.cpp
new file mode 100644
index 0000000000..3a0a09ac31
--- /dev/null
+++ b/src/object/ObjectManager.cpp
@@ -0,0 +1,299 @@
+#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
+/*****************************************************************************
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * OpenRCT2 is the work of many authors, a full list can be found in contributors.md
+ * For more information, visit https://github.com/OpenRCT2/OpenRCT2
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * A full copy of the GNU General Public License can be found in licence.txt
+ *****************************************************************************/
+#pragma endregion
+
+#include
+#include
+#include "../core/Console.hpp"
+#include "../core/Memory.hpp"
+#include "Object.h"
+#include "ObjectManager.h"
+#include "ObjectRepository.h"
+
+extern "C"
+{
+ #include "../object_list.h"
+}
+
+class ObjectManager : public IObjectManager
+{
+private:
+ IObjectRepository * _objectRepository;
+ Object * * _loadedObjects = nullptr;
+
+public:
+ ObjectManager(IObjectRepository * objectRepository)
+ {
+ _objectRepository = objectRepository;
+ }
+
+ ~ObjectManager() override
+ {
+ SetNewLoadedObjectList(nullptr);
+ }
+
+ Object * GetLoadedObject(size_t index) override
+ {
+ if (_loadedObjects == nullptr)
+ {
+ return nullptr;
+ }
+ return _loadedObjects[index];
+ }
+
+ bool LoadObjects(const rct_object_entry * entries, size_t count) override
+ {
+ IObjectRepository * objectRepository = GetObjectRepository();
+
+ // Find all the required objects
+ size_t numRequiredObjects;
+ auto requiredObjects = new const ObjectRepositoryItem *[OBJECT_ENTRY_COUNT];
+ if (!GetRequiredObjects(entries, requiredObjects, &numRequiredObjects))
+ {
+ return false;
+ }
+
+ // Create a new list of loaded objects
+ size_t numNewLoadedObjects;
+ Object * * loadedObjects = LoadObjects(requiredObjects, &numNewLoadedObjects);
+
+ delete requiredObjects;
+
+ if (loadedObjects == nullptr)
+ {
+ UnloadAll();
+ return false;
+ }
+ else
+ {
+ SetNewLoadedObjectList(loadedObjects);
+ UpdateLegacyLoadedObjectList();
+ reset_type_to_ride_entry_index_map();
+ Console::WriteLine("%u / %u new objects loaded", numNewLoadedObjects, numRequiredObjects);
+ return true;
+ }
+ }
+
+ void UnloadAll() override
+ {
+ if (_loadedObjects != nullptr)
+ {
+ for (int i = 0; i < OBJECT_ENTRY_COUNT; i++)
+ {
+ UnloadObject(_loadedObjects[i]);
+ _loadedObjects[i] = nullptr;
+ }
+ }
+ UpdateLegacyLoadedObjectList();
+ reset_type_to_ride_entry_index_map();
+ }
+
+private:
+ void SetNewLoadedObjectList(Object * * newLoadedObjects)
+ {
+ if (newLoadedObjects == nullptr)
+ {
+ UnloadAll();
+ }
+ else
+ {
+ UnloadObjectsExcept(newLoadedObjects);
+ }
+ Memory::Free(_loadedObjects);
+ _loadedObjects = newLoadedObjects;
+ }
+
+ void UnloadObject(Object * object)
+ {
+ if (object != nullptr)
+ {
+ // TODO try to prevent doing a repository search
+ const ObjectRepositoryItem * ori = _objectRepository->FindObject(object->GetObjectEntry());
+ if (ori != nullptr)
+ {
+ _objectRepository->UnregisterLoadedObject(ori, object);
+ }
+
+ object->Unload();
+ delete object;
+ }
+ }
+
+ void UnloadObjectsExcept(Object * * newLoadedObjects)
+ {
+ if (_loadedObjects == nullptr)
+ {
+ return;
+ }
+
+ // Build a hash set for quick checking
+ auto exceptSet = std::unordered_set