diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8f352270..0c90b222 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -341,10 +341,8 @@ add_lego1_static_library(lego1_impl
   LEGO1/lego/legoomni/src/common/legoactors.cpp
   LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp
   LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp
-  LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp
   LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp
   LEGO1/lego/legoomni/src/common/legocharactermanager.cpp
-  LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp
   LEGO1/lego/legoomni/src/common/legogamestate.cpp
   LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp
   LEGO1/lego/legoomni/src/common/legophoneme.cpp
@@ -367,7 +365,6 @@ add_lego1_static_library(lego1_impl
   LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp
   LEGO1/lego/legoomni/src/entity/legoentity.cpp
   LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp
-  LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp
   LEGO1/lego/legoomni/src/entity/legolocations.cpp
   LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp
   LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp
diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h
index 174d74a7..8b31ea73 100644
--- a/LEGO1/lego/legoomni/include/act3.h
+++ b/LEGO1/lego/legoomni/include/act3.h
@@ -92,6 +92,9 @@ public:
 	MxLong Notify(MxParam& p_param) override; // vtable+0x04
 	MxResult Tickle() override;               // vtable+0x08
 
+	// FUNCTION: LEGO1 0x10072500
+	MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c
+
 	// FUNCTION: LEGO1 0x10072510
 	// FUNCTION: BETA10 0x10017550
 	const char* ClassName() const override // vtable+0x0c
@@ -109,7 +112,6 @@ public:
 	MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
 	void Destroy(MxBool p_fromDestructor) override;   // vtable+0x1c
 	void ReadyWorld() override;                       // vtable+0x50
-	MxBool VTable0x5c() override;                     // vtable+0x5c
 	void VTable0x60() override;                       // vtable+0x60
 	MxBool Escape() override;                         // vtable+0x64
 	void Enable(MxBool p_enable) override;            // vtable+0x68
diff --git a/LEGO1/lego/legoomni/include/act3actors.h b/LEGO1/lego/legoomni/include/act3actors.h
index 2a9ceaa5..02b3d22d 100644
--- a/LEGO1/lego/legoomni/include/act3actors.h
+++ b/LEGO1/lego/legoomni/include/act3actors.h
@@ -10,6 +10,44 @@ struct LegoBuildingInfo;
 struct LegoPlantInfo;
 class LegoWorld;
 
+// VTABLE: LEGO1 0x100d7920 LegoPathActor
+// VTABLE: LEGO1 0x100d79f0 LegoAnimActor
+// SIZE 0x1a8
+class Act3Shark : public LegoAnimActor {
+public:
+	Act3Shark();
+
+	void ParseAction(char*) override;    // vtable+0x20
+	void Animate(float p_time) override; // vtable+0x70
+
+	// LegoAnimActor vtable
+	virtual MxResult EatPizza(Act3Ammo* p_ammo); // vtable+0x10
+
+	// FUNCTION: LEGO1 0x100430d0
+	const char* ClassName() const override // vtable+0x0c
+	{
+		// Does not exist in BETA10
+		// STRING: LEGO1 0x100f03a0
+		return "Act3Shark";
+	}
+
+	MxFloat GetUnknown0x2c() { return m_unk0x2c; }
+
+	void SetUnknown0x2c(MxFloat p_unk0x2c) { m_unk0x2c = p_unk0x2c; }
+
+	// SYNTHETIC: LEGO1 0x10043030
+	// Act3Shark::`scalar deleting destructor'
+
+private:
+	list<Act3Ammo*> m_eatPizzas;    // 0x1c
+	Act3Ammo* m_nextPizza;          // 0x28
+	MxFloat m_unk0x2c;              // 0x2c
+	LegoWorld* m_world;             // 0x30
+	LegoAnimActorStruct* m_unk0x34; // 0x34
+	LegoROI* m_unk0x38;             // 0x38
+	Mx3DPointFloat m_unk0x3c;       // 0x3c
+};
+
 // VTABLE: LEGO1 0x100d7668 LegoPathActor
 // VTABLE: LEGO1 0x100d7738 LegoAnimActor
 // VTABLE: BETA10 0x101b8a98 LegoPathActor
@@ -17,19 +55,11 @@ class LegoWorld;
 // SIZE 0x178
 class Act3Actor : public LegoAnimActor {
 public:
-	struct Act3CopDest {
-		// name verified by BETA10 0x10018776
-		const char* m_bName; // 0x00
-
-		// name verified by BETA10 0x100187cb
-		LegoPathBoundary* m_boundary; // 0x04
-
-		MxFloat m_unk0x08[3]; // 0x08
-		MxFloat m_unk0x14[3]; // 0x14
-	};
-
 	Act3Actor();
 
+	MxU32 VTable0x90(float p_time, Matrix4& p_transform) override;     // vtable+0x90
+	MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
+
 	// FUNCTION: LEGO1 0x100431b0
 	// FUNCTION: BETA10 0x1001d320
 	const char* ClassName() const override // vtable+0x0c
@@ -38,9 +68,6 @@ public:
 		return "Act3Actor";
 	}
 
-	MxU32 VTable0x90(float p_time, Matrix4& p_transform) override;     // vtable+0x90
-	MxResult HitActor(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94
-
 	MxFloat GetUnknown0x1c() { return m_unk0x1c; }
 
 	void SetUnknown0x1c(MxFloat p_unk0x1c) { m_unk0x1c = p_unk0x1c; }
@@ -62,6 +89,17 @@ private:
 // SIZE 0x188
 class Act3Cop : public Act3Actor {
 public:
+	struct Act3CopDest {
+		// name verified by BETA10 0x10018776
+		const char* m_bName; // 0x00
+
+		// name verified by BETA10 0x100187cb
+		LegoPathBoundary* m_boundary; // 0x04
+
+		MxFloat m_unk0x08[3]; // 0x08
+		MxFloat m_unk0x14[3]; // 0x14
+	};
+
 	Act3Cop();
 
 	void ParseAction(char* p_extra) override;           // vtable+0x20
@@ -137,44 +175,6 @@ private:
 	MxU8 m_unk0x58;                   // 0x58
 };
 
-// VTABLE: LEGO1 0x100d7920 LegoPathActor
-// VTABLE: LEGO1 0x100d79f0 LegoAnimActor
-// SIZE 0x1a8
-class Act3Shark : public LegoAnimActor {
-public:
-	Act3Shark();
-
-	// FUNCTION: LEGO1 0x100430d0
-	const char* ClassName() const override // vtable+0x0c
-	{
-		// Does not exist in BETA10
-		// STRING: LEGO1 0x100f03a0
-		return "Act3Shark";
-	}
-
-	void ParseAction(char*) override;    // vtable+0x20
-	void Animate(float p_time) override; // vtable+0x70
-
-	// LegoAnimActor vtable
-	virtual MxResult EatPizza(Act3Ammo* p_ammo); // vtable+0x10
-
-	MxFloat GetUnknown0x2c() { return m_unk0x2c; }
-
-	void SetUnknown0x2c(MxFloat p_unk0x2c) { m_unk0x2c = p_unk0x2c; }
-
-	// SYNTHETIC: LEGO1 0x10043030
-	// Act3Shark::`scalar deleting destructor'
-
-private:
-	list<Act3Ammo*> m_eatPizzas;    // 0x1c
-	Act3Ammo* m_nextPizza;          // 0x28
-	MxFloat m_unk0x2c;              // 0x2c
-	LegoWorld* m_world;             // 0x30
-	LegoAnimActorStruct* m_unk0x34; // 0x34
-	LegoROI* m_unk0x38;             // 0x38
-	Mx3DPointFloat m_unk0x3c;       // 0x3c
-};
-
 // FUNCTION: LEGO1 0x1003ff10
 // Act3Actor::`vbase destructor'
 
diff --git a/LEGO1/lego/legoomni/include/act3ammo.h b/LEGO1/lego/legoomni/include/act3ammo.h
index 28de0263..ee4e3dc1 100644
--- a/LEGO1/lego/legoomni/include/act3ammo.h
+++ b/LEGO1/lego/legoomni/include/act3ammo.h
@@ -82,7 +82,7 @@ public:
 
 	MxResult Remove();
 	MxResult Create(Act3* p_world, MxU32 p_isPizza, MxS32 p_index);
-	MxResult FUN_10053b40(Vector3& p_srcLoc, Vector3& p_srcDir, Vector3& p_srcUp);
+	MxResult FUN_10053b40(const Vector3& p_srcLoc, const Vector3& p_srcDir, const Vector3& p_srcUp);
 	MxResult FUN_10053cb0(LegoPathController* p_p, LegoPathBoundary* p_boundary, MxFloat p_unk0x19c);
 	MxResult FUN_10053d30(LegoPathController* p_p, MxFloat p_unk0x19c);
 
diff --git a/LEGO1/lego/legoomni/include/ambulance.h b/LEGO1/lego/legoomni/include/ambulance.h
index 09028188..97e6ba38 100644
--- a/LEGO1/lego/legoomni/include/ambulance.h
+++ b/LEGO1/lego/legoomni/include/ambulance.h
@@ -13,6 +13,40 @@ class AmbulanceMissionState : public LegoState {
 public:
 	AmbulanceMissionState();
 
+	// FUNCTION: LEGO1 0x10037440
+	// FUNCTION: BETA10 0x10024480
+	MxResult Serialize(LegoStorage* p_storage) override
+	{
+		LegoState::Serialize(p_storage);
+
+		if (p_storage->IsReadMode()) {
+			p_storage->ReadS16(m_peScore);
+			p_storage->ReadS16(m_maScore);
+			p_storage->ReadS16(m_paScore);
+			p_storage->ReadS16(m_niScore);
+			p_storage->ReadS16(m_laScore);
+			p_storage->ReadS16(m_peHighScore);
+			p_storage->ReadS16(m_maHighScore);
+			p_storage->ReadS16(m_paHighScore);
+			p_storage->ReadS16(m_niHighScore);
+			p_storage->ReadS16(m_laHighScore);
+		}
+		else if (p_storage->IsWriteMode()) {
+			p_storage->WriteS16(m_peScore);
+			p_storage->WriteS16(m_maScore);
+			p_storage->WriteS16(m_paScore);
+			p_storage->WriteS16(m_niScore);
+			p_storage->WriteS16(m_laScore);
+			p_storage->WriteS16(m_peHighScore);
+			p_storage->WriteS16(m_maHighScore);
+			p_storage->WriteS16(m_paHighScore);
+			p_storage->WriteS16(m_niHighScore);
+			p_storage->WriteS16(m_laHighScore);
+		}
+
+		return SUCCESS;
+	} // vtable+0x1c
+
 	// FUNCTION: LEGO1 0x10037600
 	// FUNCTION: BETA10 0x100246c0
 	const char* ClassName() const override // vtable+0x0c
@@ -27,8 +61,6 @@ public:
 		return !strcmp(p_name, AmbulanceMissionState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
-
 	// FUNCTION: BETA10 0x10088770
 	MxS16 GetHighScore(MxU8 p_actorId)
 	{
@@ -118,6 +150,9 @@ public:
 	MxLong Notify(MxParam& p_param) override; // vtable+0x04
 	MxResult Tickle() override;               // vtable+0x08
 
+	// FUNCTION: LEGO1 0x10035f90
+	void Destroy(MxBool p_fromDestructor) override {} // vtable+0x1c
+
 	// FUNCTION: LEGO1 0x10035fa0
 	// FUNCTION: BETA10 0x100240b0
 	const char* ClassName() const override // vtable+0x0c
@@ -133,7 +168,6 @@ public:
 	}
 
 	MxResult Create(MxDSAction& p_dsAction) override;                              // vtable+0x18
-	void Destroy(MxBool p_fromDestructor) override;                                // vtable+0x1c
 	void Animate(float p_time) override;                                           // vtable+0x70
 	MxLong HandleClick() override;                                                 // vtable+0xcc
 	MxLong HandleControl(LegoControlManagerNotificationParam& p_param) override;   // vtable+0xd4
diff --git a/LEGO1/lego/legoomni/include/gasstation.h b/LEGO1/lego/legoomni/include/gasstation.h
index bb7bb3ad..f8709bc0 100644
--- a/LEGO1/lego/legoomni/include/gasstation.h
+++ b/LEGO1/lego/legoomni/include/gasstation.h
@@ -32,7 +32,7 @@ public:
 		return !strcmp(p_name, GasStationState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	// SYNTHETIC: LEGO1 0x10006290
 	// GasStationState::`scalar deleting destructor'
diff --git a/LEGO1/lego/legoomni/include/hospital.h b/LEGO1/lego/legoomni/include/hospital.h
index e42d1235..0e924bcb 100644
--- a/LEGO1/lego/legoomni/include/hospital.h
+++ b/LEGO1/lego/legoomni/include/hospital.h
@@ -16,11 +16,6 @@ class MxStillPresenter;
 // SIZE 0x18
 class HospitalState : public LegoState {
 public:
-	// SIZE 0x04
-	struct Unknown0x08 {
-		undefined4 m_unk0x00; // 0x00
-	};
-
 	HospitalState();
 	~HospitalState() override {}
 
@@ -38,20 +33,20 @@ public:
 		return !strcmp(p_name, HospitalState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	// SYNTHETIC: LEGO1 0x100764c0
 	// HospitalState::`scalar deleting destructor'
 
 	// TODO: Most likely getters/setters are not used according to BETA.
 
-	Unknown0x08 m_unk0x08; // 0x08
-	MxS16 m_unk0x0c;       // 0x0c
-	MxS16 m_unk0x0e;       // 0x0e
-	MxS16 m_unk0x10;       // 0x10
-	MxS16 m_unk0x12;       // 0x12
-	MxS16 m_unk0x14;       // 0x14
-	MxS16 m_unk0x16;       // 0x16
+	undefined4 m_unk0x08; // 0x08
+	MxS16 m_unk0x0c;      // 0x0c
+	MxS16 m_unk0x0e;      // 0x0e
+	MxS16 m_unk0x10;      // 0x10
+	MxS16 m_unk0x12;      // 0x12
+	MxS16 m_unk0x14;      // 0x14
+	MxS16 m_unk0x16;      // 0x16
 };
 
 // VTABLE: LEGO1 0x100d9730
@@ -65,6 +60,9 @@ public:
 	MxLong Notify(MxParam& p_param) override; // vtable+0x04
 	MxResult Tickle() override;               // vtable+0x08
 
+	// FUNCTION: LEGO1 0x100746a0
+	MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c
+
 	// FUNCTION: LEGO1 0x100746b0
 	// FUNCTION: BETA10 0x1002e1a0
 	const char* ClassName() const override // vtable+0x0c
@@ -81,7 +79,6 @@ public:
 
 	MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
 	void ReadyWorld() override;                       // vtable+0x50
-	MxBool VTable0x5c() override;                     // vtable+0x5c
 	MxBool Escape() override;                         // vtable+0x64
 	void Enable(MxBool p_enable) override;            // vtable+0x68
 
diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h
index f35cc77a..7efe45b4 100644
--- a/LEGO1/lego/legoomni/include/infocenter.h
+++ b/LEGO1/lego/legoomni/include/infocenter.h
@@ -20,6 +20,9 @@ public:
 	InfocenterState();
 	~InfocenterState() override;
 
+	// FUNCTION: LEGO1 0x10071830
+	MxBool IsSerializable() override { return FALSE; } // vtable+0x14
+
 	// FUNCTION: LEGO1 0x10071840
 	// FUNCTION: BETA10 0x10031ee0
 	const char* ClassName() const override // vtable+0x0c
@@ -34,9 +37,6 @@ public:
 		return !strcmp(p_name, InfocenterState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	// FUNCTION: LEGO1 0x10071830
-	MxBool IsSerializable() override { return FALSE; } // vtable+0x14
-
 	MxS16 GetMaxNameLength() { return sizeOfArray(m_letters); }
 	MxStillPresenter* GetNameLetter(MxS32 p_index) { return m_letters[p_index]; }
 	void SetNameLetter(MxS32 p_index, MxStillPresenter* p_letter) { m_letters[p_index] = p_letter; }
@@ -66,8 +66,7 @@ public:
 
 // SIZE 0x18
 struct InfocenterMapEntry {
-	// FUNCTION: LEGO1 0x1006ec80
-	InfocenterMapEntry() {}
+	InfocenterMapEntry();
 
 	MxStillPresenter* m_destCtl; // 0x00
 	undefined4 m_unk0x04;        // 0x04
diff --git a/LEGO1/lego/legoomni/include/infocenterdoor.h b/LEGO1/lego/legoomni/include/infocenterdoor.h
index 10caba7d..c9bb841b 100644
--- a/LEGO1/lego/legoomni/include/infocenterdoor.h
+++ b/LEGO1/lego/legoomni/include/infocenterdoor.h
@@ -16,6 +16,9 @@ public:
 
 	MxLong Notify(MxParam& p_param) override; // vtable+0x04
 
+	// FUNCTION: LEGO1 0x100377a0
+	MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c
+
 	// FUNCTION: LEGO1 0x100377b0
 	// FUNCTION: BETA10 0x10032790
 	const char* ClassName() const override // vtable+0x0c
@@ -32,12 +35,8 @@ public:
 
 	MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
 	void ReadyWorld() override;                       // vtable+0x50
-
-	// FUNCTION: LEGO1 0x100377a0
-	MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c
-
-	MxBool Escape() override;              // vtable+0x64
-	void Enable(MxBool p_enable) override; // vtable+0x68
+	MxBool Escape() override;                         // vtable+0x64
+	void Enable(MxBool p_enable) override;            // vtable+0x68
 
 	// SYNTHETIC: LEGO1 0x100378d0
 	// InfocenterDoor::`scalar deleting destructor'
diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h
index cb845914..2c6c8091 100644
--- a/LEGO1/lego/legoomni/include/isle.h
+++ b/LEGO1/lego/legoomni/include/isle.h
@@ -50,8 +50,8 @@ public:
 		return !strcmp(p_name, Act1State::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxBool Reset() override;                       // vtable+0x18
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxBool Reset() override;                             // vtable+0x18
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	void PlayCptClickDialogue();
 	void StopCptClickDialogue();
diff --git a/LEGO1/lego/legoomni/include/islepathactor.h b/LEGO1/lego/legoomni/include/islepathactor.h
index e3a8bd37..46630e29 100644
--- a/LEGO1/lego/legoomni/include/islepathactor.h
+++ b/LEGO1/lego/legoomni/include/islepathactor.h
@@ -131,12 +131,6 @@ public:
 
 	void FUN_1001b660();
 
-	void Reset()
-	{
-		m_roi->SetVisibility(TRUE);
-		SetActorState(c_initial);
-	}
-
 	void SetWorld(LegoWorld* p_world) { m_world = p_world; }
 
 	static void RegisterSpawnLocations();
diff --git a/LEGO1/lego/legoomni/include/jukebox.h b/LEGO1/lego/legoomni/include/jukebox.h
index 8196f454..e7a36668 100644
--- a/LEGO1/lego/legoomni/include/jukebox.h
+++ b/LEGO1/lego/legoomni/include/jukebox.h
@@ -59,6 +59,9 @@ public:
 	MxLong Notify(MxParam& p_param) override; // vtable+0x04
 	MxResult Tickle() override;               // vtable+0x08
 
+	// FUNCTION: LEGO1 0x1005d6e0
+	MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c
+
 	// FUNCTION: LEGO1 0x1005d6f0
 	// FUNCTION: BETA10 0x100388d0
 	const char* ClassName() const override // vtable+0x0c
@@ -75,7 +78,6 @@ public:
 
 	MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
 	void ReadyWorld() override;                       // vtable+0x50
-	MxBool VTable0x5c() override;                     // vtable+0x5c
 	MxBool Escape() override;                         // vtable+0x64
 	void Enable(MxBool p_enable) override;            // vtable+0x68
 
diff --git a/LEGO1/lego/legoomni/include/legoact2.h b/LEGO1/lego/legoomni/include/legoact2.h
index 62c5f04e..f84e9b0d 100644
--- a/LEGO1/lego/legoomni/include/legoact2.h
+++ b/LEGO1/lego/legoomni/include/legoact2.h
@@ -65,10 +65,13 @@ public:
 	MxResult Tickle() override;                       // vtable+0x08
 	MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
 	void ReadyWorld() override;                       // vtable+0x50
-	MxBool VTable0x5c() override;                     // vtable+0x5c
-	void VTable0x60() override;                       // vtable+0x60
-	MxBool Escape() override;                         // vtable+0x64
-	void Enable(MxBool p_enable) override;            // vtable+0x68
+
+	// FUNCTION: LEGO1 0x1004fe10
+	MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c
+
+	void VTable0x60() override;            // vtable+0x60
+	MxBool Escape() override;              // vtable+0x64
+	void Enable(MxBool p_enable) override; // vtable+0x68
 
 	void SetUnknown0x1138(Act2Actor* p_unk0x1138) { m_unk0x1138 = p_unk0x1138; }
 	void SetDestLocation(LegoGameState::Area p_destLocation) { m_destLocation = p_destLocation; }
diff --git a/LEGO1/lego/legoomni/include/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h
index 1d44371b..3f115e97 100644
--- a/LEGO1/lego/legoomni/include/legoanimactor.h
+++ b/LEGO1/lego/legoomni/include/legoanimactor.h
@@ -42,6 +42,16 @@ public:
 
 	~LegoAnimActor() override;
 
+	void ParseAction(char* p_extra) override;          // vtable+0x20
+	void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
+	void Animate(float p_time) override;               // vtable+0x70
+	void VTable0x74(Matrix4& p_transform) override;    // vtable+0x74
+
+	virtual MxResult FUN_1001c1f0(float& p_und);
+	virtual MxResult FUN_1001c360(float, Matrix4& p_transform);
+	virtual MxResult FUN_1001c450(LegoAnim* p_AnimTreePtr, float p_unk0x00, LegoROI** p_roiMap, MxU32 p_numROIs);
+	virtual void ClearMaps();
+
 	// FUNCTION: LEGO1 0x1000fba0
 	// FUNCTION: BETA10 0x10012400
 	const char* ClassName() const override // vtable+0x0c
@@ -57,16 +67,6 @@ public:
 		return !strcmp(p_name, LegoAnimActor::ClassName()) || LegoPathActor::IsA(p_name);
 	}
 
-	void ParseAction(char* p_extra) override;          // vtable+0x20
-	void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30
-	void Animate(float p_time) override;               // vtable+0x70
-	void VTable0x74(Matrix4& p_transform) override;    // vtable+0x74
-
-	virtual MxResult FUN_1001c1f0(float& p_und);
-	virtual MxResult FUN_1001c360(float, Matrix4& p_transform);
-	virtual MxResult FUN_1001c450(LegoAnim* p_AnimTreePtr, float p_unk0x00, LegoROI** p_roiMap, MxU32 p_numROIs);
-	virtual void ClearMaps();
-
 	// SYNTHETIC: LEGO1 0x1000fb60
 	// LegoAnimActor::`scalar deleting destructor'
 
diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h
index f2d42603..0b5f7f21 100644
--- a/LEGO1/lego/legoomni/include/legoanimationmanager.h
+++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h
@@ -71,8 +71,8 @@ public:
 		return !strcmp(p_name, AnimState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxBool Reset() override;                       // vtable+0x18
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxBool Reset() override;                             // vtable+0x18
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	void CopyToAnims(MxU32, AnimInfo* p_anims, MxU32& p_outExtraCharacterId);
 	void InitFromAnims(MxU32 p_animsLength, AnimInfo* p_anims, MxU32 p_extraCharacterId);
@@ -165,8 +165,8 @@ public:
 	void EnableCamAnims(MxBool p_enableCamAnims);
 	MxResult LoadWorldInfo(LegoOmni::World p_worldId);
 	MxBool FindVehicle(const char* p_name, MxU32& p_index);
-	MxResult ReadAnimInfo(LegoFile* p_file, AnimInfo* p_info);
-	MxResult ReadModelInfo(LegoFile* p_file, ModelInfo* p_info);
+	MxResult ReadAnimInfo(LegoStorage* p_storage, AnimInfo* p_info);
+	MxResult ReadModelInfo(LegoStorage* p_storage, ModelInfo* p_info);
 	void FUN_10060480(const LegoChar* p_characterNames[], MxU32 p_numCharacterNames);
 	void FUN_100604d0(MxBool p_unk0x08);
 	void FUN_100604f0(MxS32 p_objectIds[], MxU32 p_numObjectIds);
diff --git a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h
index a0b05727..d73cd55d 100644
--- a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h
+++ b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h
@@ -1,6 +1,10 @@
 #ifndef LEGOANIMMMPRESENTER_H
 #define LEGOANIMMMPRESENTER_H
 
+// MxDSActionListCursor needs to be included before std::list
+// clang-format off
+#include "mxdsmultiaction.h"
+// clang-format on
 #include "mxcompositepresenter.h"
 
 class LegoAnimPresenter;
diff --git a/LEGO1/lego/legoomni/include/legobackgroundcolor.h b/LEGO1/lego/legoomni/include/legobackgroundcolor.h
deleted file mode 100644
index 3e8b4457..00000000
--- a/LEGO1/lego/legoomni/include/legobackgroundcolor.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef LEGOBACKGROUNDCOLOR_H
-#define LEGOBACKGROUNDCOLOR_H
-
-#include "mxvariable.h"
-
-// VTABLE: LEGO1 0x100d74a8
-// SIZE 0x30
-class LegoBackgroundColor : public MxVariable {
-public:
-	LegoBackgroundColor(const char* p_key, const char* p_value);
-
-	void SetValue(const char* p_colorString) override;
-	void SetLightColor(float p_r, float p_g, float p_b);
-	void SetLightColor();
-	void ToggleDayNight(MxBool);
-	void ToggleSkyColor();
-
-private:
-	float m_h;
-	float m_s;
-	float m_v;
-};
-
-#endif // LEGOBACKGROUNDCOLOR_H
diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h
index 456d7d0e..9d7bc511 100644
--- a/LEGO1/lego/legoomni/include/legocarbuild.h
+++ b/LEGO1/lego/legoomni/include/legocarbuild.h
@@ -44,7 +44,7 @@ public:
 		return !strcmp(p_name, m_className.GetData()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	// SYNTHETIC: LEGO1 0x100260a0
 	// LegoVehicleBuildState::`scalar deleting destructor'
diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h
index deb55c03..821c3a60 100644
--- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h
+++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h
@@ -44,6 +44,9 @@ public:
 		return "LegoCarBuildAnimPresenter";
 	}
 
+	// FUNCTION: LEGO1 0x10078500
+	void RepeatingTickle() override {} // vtable+0x24
+
 	// FUNCTION: LEGO1 0x10078510
 	// FUNCTION: BETA10 0x10073260
 	const char* ClassName() const override // vtable+0x0c
@@ -59,10 +62,11 @@ public:
 
 	void ReadyTickle() override;     // vtable+0x18
 	void StreamingTickle() override; // vtable+0x20
-	void RepeatingTickle() override; // vtable+0x24
 	void EndAction() override;       // vtable+0x40
 	void PutFrame() override;        // vtable+0x6c
 
+	virtual MxResult Serialize(LegoStorage* p_storage);
+
 	void FUN_10079050(MxS16 p_index);
 	void SwapNodesByName(LegoChar* p_param1, LegoChar* p_param2);
 	void FUN_10079160();
diff --git a/LEGO1/lego/legoomni/include/legocharactermanager.h b/LEGO1/lego/legoomni/include/legocharactermanager.h
index 6b4dca71..8e470fdd 100644
--- a/LEGO1/lego/legoomni/include/legocharactermanager.h
+++ b/LEGO1/lego/legoomni/include/legocharactermanager.h
@@ -4,11 +4,11 @@
 #include "decomp.h"
 #include "mxstl/stlcompat.h"
 #include "mxtypes.h"
+#include "mxvariable.h"
 #include "roi/legoroi.h"
 
 #include <SDL3/SDL_stdinc.h>
 
-class CustomizeAnimFileVariable;
 class LegoActor;
 class LegoExtraActor;
 class LegoStorage;
@@ -47,6 +47,15 @@ struct LegoActorInfo;
 
 typedef map<char*, LegoCharacter*, LegoCharacterComparator> LegoCharacterMap;
 
+// VTABLE: LEGO1 0x100da878
+// SIZE 0x24
+class CustomizeAnimFileVariable : public MxVariable {
+public:
+	CustomizeAnimFileVariable(const char* p_key);
+
+	void SetValue(const char* p_value) override; // vtable+0x04
+};
+
 // SIZE 0x08
 class LegoCharacterManager {
 public:
diff --git a/LEGO1/lego/legoomni/include/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h
index 5f930820..05ee8510 100644
--- a/LEGO1/lego/legoomni/include/legoextraactor.h
+++ b/LEGO1/lego/legoomni/include/legoextraactor.h
@@ -2,7 +2,6 @@
 #define LEGOEXTRAACTOR_H
 
 #include "legoanimactor.h"
-#include "legopathboundary.h"
 
 // VTABLE: LEGO1 0x100d6c00 LegoAnimActor
 // VTABLE: LEGO1 0x100d6c10 LegoPathActor
@@ -78,108 +77,6 @@ private:
 	LegoAnimActorStruct* m_disAnim; // 0x64
 };
 
-// FUNCTION: LEGO1 0x1002b980
-inline MxU32 LegoExtraActor::VTable0x6c(
-	LegoPathBoundary* p_boundary,
-	Vector3& p_v1,
-	Vector3& p_v2,
-	float p_f1,
-	float p_f2,
-	Vector3& p_v3
-)
-{
-	LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
-
-	for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
-		if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
-			return 1;
-		}
-	}
-
-	LegoPathActorSet& plpas = p_boundary->GetActors();
-	LegoPathActorSet lpas(plpas);
-
-	for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) {
-		if (plpas.find(*itpa) != plpas.end()) {
-			LegoPathActor* actor = *itpa;
-
-			if (this != actor && !(actor->GetActorState() & LegoPathActor::c_noCollide)) {
-				LegoROI* roi = actor->GetROI();
-
-				if ((roi != NULL && roi->GetVisibility()) || actor->GetCameraFlag()) {
-					if (actor->GetUserNavFlag()) {
-						MxMatrix local2world = roi->GetLocal2World();
-						Vector3 local60(local2world[3]);
-						Mx3DPointFloat local54(p_v1);
-
-						local54 -= local60;
-						float local1c = p_v2.Dot(p_v2, p_v2);
-						float local24 = p_v2.Dot(p_v2, local54) * 2.0f;
-						float local20 = local54.Dot(local54, local54);
-
-						if (m_unk0x15 != 0 && local20 < 10.0f) {
-							return 0;
-						}
-
-						local20 -= 1.0f;
-
-						if (local1c >= 0.001 || local1c <= -0.001) {
-							float local40 = (local24 * local24) + (local20 * local1c * -4.0f);
-
-							if (local40 >= -0.001) {
-								local1c *= 2.0f;
-								local24 = -local24;
-
-								if (local40 < 0.0f) {
-									local40 = 0.0f;
-								}
-
-								local40 = sqrt(local40);
-								float local20X = (local24 + local40) / local1c;
-								float local1cX = (local24 - local40) / local1c;
-
-								if (local1cX < local20X) {
-									local40 = local20X;
-									local20X = local1cX;
-									local1cX = local40;
-								}
-
-								if ((local20X >= 0.0f && local20X <= p_f1) || (local1cX >= 0.0f && local1cX <= p_f1) ||
-									(local20X <= -0.01 && p_f1 + 0.01 <= local1cX)) {
-									p_v3 = p_v1;
-
-									if (HitActor(actor, TRUE) < 0) {
-										return 0;
-									}
-
-									actor->HitActor(this, FALSE);
-									return 2;
-								}
-							}
-						}
-					}
-					else {
-						if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
-							if (HitActor(actor, TRUE) < 0) {
-								return 0;
-							}
-
-							actor->HitActor(this, FALSE);
-							return 2;
-						}
-					}
-				}
-			}
-		}
-	}
-
-	if (m_unk0x15 != 0) {
-		m_unk0x15--;
-	}
-
-	return 0;
-}
-
 // GLOBAL: LEGO1 0x100d6be8
 // LegoExtraActor::`vbtable'{for `LegoAnimActor'}
 
diff --git a/LEGO1/lego/legoomni/include/legofullscreenmovie.h b/LEGO1/lego/legoomni/include/legofullscreenmovie.h
deleted file mode 100644
index 2f2f7614..00000000
--- a/LEGO1/lego/legoomni/include/legofullscreenmovie.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef LEGOFULLSCREENMOVIE_H
-#define LEGOFULLSCREENMOVIE_H
-
-#include "mxvariable.h"
-
-// VTABLE: LEGO1 0x100d74b8
-// SIZE 0x24
-class LegoFullScreenMovie : public MxVariable {
-public:
-	LegoFullScreenMovie(const char* p_key, const char* p_value);
-	void SetValue(const char* p_option) override;
-};
-
-#endif // LEGOFULLSCREENMOVIE_H
diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h
index f4167d2d..4914e0ac 100644
--- a/LEGO1/lego/legoomni/include/legogamestate.h
+++ b/LEGO1/lego/legoomni/include/legogamestate.h
@@ -5,15 +5,13 @@
 #include "decomp.h"
 #include "lego1_export.h"
 #include "mxtypes.h"
+#include "mxvariable.h"
 
 #include <string.h>
 
-class LegoBackgroundColor;
 class LegoFile;
-class LegoFullScreenMovie;
 class LegoState;
 class LegoStorage;
-class MxVariable;
 class MxVariableTable;
 class MxString;
 
@@ -25,6 +23,35 @@ struct ColorStringStruct {
 	const char* m_colorName;  // 0x04
 };
 
+// VTABLE: LEGO1 0x100d74a8
+// SIZE 0x30
+class LegoBackgroundColor : public MxVariable {
+public:
+	LegoBackgroundColor();
+	LegoBackgroundColor(const char* p_key, const char* p_value);
+
+	void SetValue(const char* p_colorString) override; // vtable+0x04
+
+	void SetLightColor(float p_r, float p_g, float p_b);
+	void SetLightColor();
+	void ToggleDayNight(MxBool p_sun);
+	void ToggleSkyColor();
+
+private:
+	float m_h; // 0x24
+	float m_s; // 0x28
+	float m_v; // 0x2c
+};
+
+// VTABLE: LEGO1 0x100d74b8
+// SIZE 0x24
+class LegoFullScreenMovie : public MxVariable {
+public:
+	LegoFullScreenMovie(const char* p_key, const char* p_value);
+
+	void SetValue(const char* p_option) override; // vtable+0x04
+};
+
 // SIZE 0x430
 class LegoGameState {
 public:
@@ -109,10 +136,9 @@ public:
 	// SIZE 0x0e
 	struct Username {
 		Username();
-		Username(Username& p_other) { Set(p_other); }
 		void Set(Username& p_other) { memcpy(m_letters, p_other.m_letters, sizeof(m_letters)); }
 
-		MxResult Serialize(LegoFile* p_file);
+		MxResult Serialize(LegoStorage* p_storage);
 		Username& operator=(const Username& p_other);
 
 		MxS16 m_letters[7]; // 0x00
@@ -120,7 +146,7 @@ public:
 
 	// SIZE 0x2c
 	struct ScoreItem {
-		MxResult Serialize(LegoFile* p_file);
+		MxResult Serialize(LegoStorage* p_storage);
 
 		MxS16 m_totalScore;  // 0x00
 		MxU8 m_scores[5][5]; // 0x02
@@ -132,8 +158,8 @@ public:
 	struct History {
 		History();
 		void WriteScoreHistory();
-		MxResult Serialize(LegoFile* p_file);
-		ScoreItem* FUN_1003cc90(Username* p_player, MxU16 p_unk0x24, MxS32& p_unk0x2c);
+		MxResult Serialize(LegoStorage* p_storage);
+		ScoreItem* FUN_1003cc90(Username* p_player, MxS16 p_unk0x24, MxS32& p_unk0x2c);
 
 		// FUNCTION: BETA10 0x1002c2b0
 		MxS16 GetCount() { return m_count; }
@@ -167,7 +193,7 @@ public:
 	LegoState* GetState(const char* p_stateName);
 	LegoState* CreateState(const char* p_stateName);
 
-	void GetFileSavePath(MxString* p_outPath, MxU8 p_slotn);
+	void GetFileSavePath(MxString* p_outPath, MxS16 p_slotn);
 	void StopArea(Area p_area);
 	void SwitchArea(Area p_area);
 	void Init();
diff --git a/LEGO1/lego/legoomni/include/legohideanimpresenter.h b/LEGO1/lego/legoomni/include/legohideanimpresenter.h
index c04e2fe2..b2bbb7b8 100644
--- a/LEGO1/lego/legoomni/include/legohideanimpresenter.h
+++ b/LEGO1/lego/legoomni/include/legohideanimpresenter.h
@@ -25,6 +25,12 @@ public:
 	LegoHideAnimPresenter();
 	~LegoHideAnimPresenter() override;
 
+	// FUNCTION: LEGO1 0x1006d860
+	void VTable0x8c() override {} // vtable+0x8c
+
+	// FUNCTION: LEGO1 0x1006d870
+	void VTable0x90() override {} // vtable+0x90
+
 	// FUNCTION: BETA10 0x1005d4a0
 	static const char* HandlerClassName()
 	{
@@ -51,8 +57,6 @@ public:
 	void Destroy() override;          // vtable+0x38
 	void EndAction() override;        // vtable+0x40
 	void PutFrame() override;         // vtable+0x6c
-	void VTable0x8c() override;       // vtable+0x8c
-	void VTable0x90() override;       // vtable+0x90
 
 	void FUN_1006db40(LegoTime p_time);
 
diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h
index 53a442e4..46f5e20c 100644
--- a/LEGO1/lego/legoomni/include/legoinputmanager.h
+++ b/LEGO1/lego/legoomni/include/legoinputmanager.h
@@ -92,7 +92,12 @@ public:
 	void Register(MxCore*);
 	void UnRegister(MxCore*);
 
-	MxResult Tickle() override; // vtable+0x08
+	// FUNCTION: LEGO1 0x1005b8b0
+	MxResult Tickle() override
+	{
+		ProcessEvents();
+		return SUCCESS;
+	} // vtable+0x08
 
 	// FUNCTION: LEGO1 0x1005b8c0
 	MxResult PutData() override { return SUCCESS; } // vtable+0x4c
diff --git a/LEGO1/lego/legoomni/include/legojetskiraceactor.h b/LEGO1/lego/legoomni/include/legojetskiraceactor.h
deleted file mode 100644
index c9964e8d..00000000
--- a/LEGO1/lego/legoomni/include/legojetskiraceactor.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef LEGOJETSKIRACEACTOR_H
-#define LEGOJETSKIRACEACTOR_H
-
-#include "legoracespecial.h"
-
-// VTABLE: LEGO1 0x100da208 LegoCarRaceActor
-// VTABLE: LEGO1 0x100da228 LegoRaceActor
-// VTABLE: LEGO1 0x100da230 LegoAnimActor
-// VTABLE: LEGO1 0x100da240 LegoPathActor
-// VTABLE: BETA10 0x101bd348 LegoCarRaceActor
-// VTABLE: BETA10 0x101bd370 LegoRaceActor
-// VTABLE: BETA10 0x101bd378 LegoAnimActor
-// VTABLE: BETA10 0x101bd390 LegoPathActor
-// SIZE 0x1a8
-class LegoJetskiRaceActor : public virtual LegoCarRaceActor {
-public:
-	LegoJetskiRaceActor();
-
-	// FUNCTION: LEGO1 0x10081d90
-	// FUNCTION: BETA10 0x100aa920
-	const char* ClassName() const override // vtable+0x0c
-	{
-		// STRING: LEGO1 0x100f0554
-		return "LegoJetskiRaceActor";
-	}
-
-	// FUNCTION: LEGO1 0x10081db0
-	// FUNCTION: BETA10 0x100aa960
-	MxBool IsA(const char* p_name) const override // vtable+0x10
-	{
-		return !strcmp(p_name, LegoJetskiRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name);
-	}
-
-	MxU32 VTable0x6c(
-		LegoPathBoundary* p_boundary,
-		Vector3& p_v1,
-		Vector3& p_v2,
-		float p_f1,
-		float p_f2,
-		Vector3& p_v3
-	) override;                                                                // vtable+0x6c
-	void Animate(float p_time) override;                                       // vtable+0x70
-	MxS32 VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) override; // vtable+0x1c
-
-	// SYNTHETIC: LEGO1 0x10013a80
-	// LegoJetskiRaceActor::`vbase destructor'
-
-	// SYNTHETIC: LEGO1 0x10081d50
-	// LegoJetskiRaceActor::`scalar deleting destructor'
-
-	// SYNTHETIC: LEGO1 0x10013ba0
-	// LegoJetskiRaceActor::~LegoJetskiRaceActor
-};
-
-// GLOBAL: LEGO1 0x100da1f0
-// LegoJetskiRaceActor::`vbtable'{for `LegoJetskiRaceActor'}
-
-// GLOBAL: LEGO1 0x100da1e8
-// LegoJetskiRaceActor::`vbtable'{for `LegoAnimActor'}
-
-// GLOBAL: LEGO1 0x100da1d8
-// LegoJetskiRaceActor::`vbtable'{for `LegoRaceActor'}
-
-// GLOBAL: LEGO1 0x100da1c8
-// LegoJetskiRaceActor::`vbtable'{for `LegoCarRaceActor'}
-
-#endif // LEGOJETSKIRACEACTOR_H
diff --git a/LEGO1/lego/legoomni/include/legonamedplane.h b/LEGO1/lego/legoomni/include/legonamedplane.h
index df91828a..0e75fe41 100644
--- a/LEGO1/lego/legoomni/include/legonamedplane.h
+++ b/LEGO1/lego/legoomni/include/legonamedplane.h
@@ -6,14 +6,17 @@
 #include "mxstring.h"
 
 // SIZE 0x4c
-class LegoNamedPlane {
-public:
+struct LegoNamedPlane {
 	// FUNCTION: LEGO1 0x10033800
 	LegoNamedPlane() {}
 
 	// FUNCTION: LEGO1 0x10033a70
 	// LegoNamedPlane::~LegoNamedPlane
 
+	// Unclear whether getters/setters were used.
+	// Act1State::Serialize seems to access `m_name` directly (only matches like that)
+	// Act1State::PlaceActors though seems to require extensive use of getters to improve
+
 	const char* GetName() const { return m_name.GetData(); }
 	const Mx3DPointFloat& GetPosition() { return m_position; }
 	const Mx3DPointFloat& GetDirection() { return m_direction; }
@@ -29,25 +32,24 @@ public:
 	void Reset() { m_name = ""; }
 
 	// FUNCTION: LEGO1 0x100344d0
-	MxResult Serialize(LegoFile* p_file)
+	MxResult Serialize(LegoStorage* p_storage)
 	{
-		if (p_file->IsWriteMode()) {
-			p_file->Write(MxString(m_name));
-			p_file->Write(m_position);
-			p_file->Write(m_direction);
-			p_file->Write(m_up);
+		if (p_storage->IsWriteMode()) {
+			p_storage->WriteMxString(m_name);
+			p_storage->WriteVector(m_position);
+			p_storage->WriteVector(m_direction);
+			p_storage->WriteVector(m_up);
 		}
-		else if (p_file->IsReadMode()) {
-			p_file->Read(m_name);
-			p_file->Read(m_position);
-			p_file->Read(m_direction);
-			p_file->Read(m_up);
+		else if (p_storage->IsReadMode()) {
+			p_storage->ReadMxString(m_name);
+			p_storage->ReadVector(m_position);
+			p_storage->ReadVector(m_direction);
+			p_storage->ReadVector(m_up);
 		}
 
 		return SUCCESS;
 	}
 
-	// private:
 	MxString m_name;            // 0x00
 	Mx3DPointFloat m_position;  // 0x10
 	Mx3DPointFloat m_direction; // 0x24
diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h
index 98c41d08..169cdd22 100644
--- a/LEGO1/lego/legoomni/include/legopathactor.h
+++ b/LEGO1/lego/legoomni/include/legopathactor.h
@@ -6,7 +6,7 @@
 #include "mxtypes.h"
 
 struct LegoEdge;
-class LegoNamedPlane;
+struct LegoNamedPlane;
 class LegoPathBoundary;
 class LegoPathController;
 struct LegoPathEdgeContainer;
@@ -37,20 +37,6 @@ public:
 	LegoPathActor();
 	~LegoPathActor() override;
 
-	// FUNCTION: LEGO1 0x1000c430
-	// FUNCTION: BETA10 0x10012790
-	const char* ClassName() const override // vtable+0x0c
-	{
-		// STRING: LEGO1 0x100f0114
-		return "LegoPathActor";
-	}
-
-	// FUNCTION: LEGO1 0x1000c440
-	MxBool IsA(const char* p_name) const override // vtable+0x10
-	{
-		return !strcmp(p_name, LegoPathActor::ClassName()) || LegoActor::IsA(p_name);
-	}
-
 	void ParseAction(char* p_extra) override;                              // vtable+0x20
 	virtual MxS32 VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3); // vtable+0x68
 	virtual MxU32 VTable0x6c(
@@ -137,6 +123,20 @@ public:
 	// FUNCTION: LEGO1 0x10002de0
 	virtual void VTable0xc8(MxU8 p_unk0x148) { m_unk0x148 = p_unk0x148; } // vtable+0xc8
 
+	// FUNCTION: LEGO1 0x1000c430
+	// FUNCTION: BETA10 0x10012790
+	const char* ClassName() const override // vtable+0x0c
+	{
+		// STRING: LEGO1 0x100f0114
+		return "LegoPathActor";
+	}
+
+	// FUNCTION: LEGO1 0x1000c440
+	MxBool IsA(const char* p_name) const override // vtable+0x10
+	{
+		return !strcmp(p_name, LegoPathActor::ClassName()) || LegoActor::IsA(p_name);
+	}
+
 	// FUNCTION: BETA10 0x1001ca40
 	LegoPathBoundary* GetBoundary() { return m_boundary; }
 
diff --git a/LEGO1/lego/legoomni/include/legopathboundary.h b/LEGO1/lego/legoomni/include/legopathboundary.h
index 020bd3c6..3499c24d 100644
--- a/LEGO1/lego/legoomni/include/legopathboundary.h
+++ b/LEGO1/lego/legoomni/include/legopathboundary.h
@@ -125,7 +125,7 @@ private:
 // _Tree<LegoPathActor *,LegoPathActor *,set<LegoPathActor *,LegoPathActorSetCompare,allocator<LegoPathActor *> >::_Kfn,LegoPathActorSetCompare,allocator<LegoPathActor *> >::_Rrotate
 
 // TEMPLATE: LEGO1 0x1004a7a0
-// ?_Construct@@YAXPAPAVMxCore@@ABQAV1@@Z
+// ?_Construct@@YAXPAPAVLegoPathActor@@ABQAV1@@Z
 
 // TEMPLATE: LEGO1 0x10056c20
 // _Tree<LegoAnimPresenter *,LegoAnimPresenter *,set<LegoAnimPresenter *,LegoAnimPresenterSetCompare,allocator<LegoAnimPresenter *> >::_Kfn,LegoAnimPresenterSetCompare,allocator<LegoAnimPresenter *> >::~_Tree<LegoAnimPresenter *,LegoAnimPresenter *,set<LegoA
diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h
index 5e3bd8ae..1a13f961 100644
--- a/LEGO1/lego/legoomni/include/legopathcontroller.h
+++ b/LEGO1/lego/legoomni/include/legopathcontroller.h
@@ -5,11 +5,10 @@
 #include "geom/legounkown100db7f4.h"
 #include "legopathactor.h"
 #include "legopathboundary.h"
-#include "mxcore.h"
+#include "legopathstruct.h"
 #include "mxstl/stlcompat.h"
 
 class LegoAnimPresenter;
-class LegoPathStruct;
 class LegoWorld;
 class MxAtomId;
 class Vector3;
diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h
index cee2e4b6..344136f3 100644
--- a/LEGO1/lego/legoomni/include/legorace.h
+++ b/LEGO1/lego/legoomni/include/legorace.h
@@ -39,17 +39,17 @@ public:
 		MxS16 GetHighScore() { return m_score; }
 
 		// FUNCTION: BETA10 0x100c96f0
-		MxResult Serialize(LegoFile* p_file)
+		MxResult Serialize(LegoStorage* p_storage)
 		{
-			if (p_file->IsReadMode()) {
-				p_file->Read(m_id);
-				p_file->Read(m_unk0x02);
-				p_file->Read(m_score);
+			if (p_storage->IsReadMode()) {
+				p_storage->ReadU8(m_id);
+				p_storage->ReadS16(m_unk0x02);
+				p_storage->ReadS16(m_score);
 			}
-			else if (p_file->IsWriteMode()) {
-				p_file->Write(m_id);
-				p_file->Write(m_unk0x02);
-				p_file->Write(m_score);
+			else if (p_storage->IsWriteMode()) {
+				p_storage->WriteU8(m_id);
+				p_storage->WriteS16(m_unk0x02);
+				p_storage->WriteS16(m_score);
 			}
 			else {
 				return FAILURE;
@@ -82,7 +82,7 @@ public:
 		return !strcmp(p_name, RaceState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	Entry* GetState(MxU8 p_id);
 
diff --git a/LEGO1/lego/legoomni/include/legoracers.h b/LEGO1/lego/legoomni/include/legoracers.h
index 461b3a52..54a29eca 100644
--- a/LEGO1/lego/legoomni/include/legoracers.h
+++ b/LEGO1/lego/legoomni/include/legoracers.h
@@ -1,9 +1,10 @@
 #ifndef LEGORACERS_H
 #define LEGORACERS_H
 
-#include "legojetskiraceactor.h"
-#include "legoracemap.h"
+// clang-format off
 #include "legoracespecial.h"
+// clang-format on
+#include "legoracemap.h"
 
 #define LEGORACECAR_UNKNOWN_0 0
 #define LEGORACECAR_UNKNOWN_1 1
diff --git a/LEGO1/lego/legoomni/include/legoracespecial.h b/LEGO1/lego/legoomni/include/legoracespecial.h
index c65605ff..3382a394 100644
--- a/LEGO1/lego/legoomni/include/legoracespecial.h
+++ b/LEGO1/lego/legoomni/include/legoracespecial.h
@@ -35,7 +35,7 @@ public:
 		return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name);
 	}
 
-	MxU32 VTable0x6c(
+	inline MxU32 VTable0x6c(
 		LegoPathBoundary* p_boundary,
 		Vector3& p_v1,
 		Vector3& p_v2,
@@ -99,6 +99,55 @@ protected:
 	static MxFloat g_unk0x100f7aec;
 };
 
+// VTABLE: LEGO1 0x100da208 LegoCarRaceActor
+// VTABLE: LEGO1 0x100da228 LegoRaceActor
+// VTABLE: LEGO1 0x100da230 LegoAnimActor
+// VTABLE: LEGO1 0x100da240 LegoPathActor
+// VTABLE: BETA10 0x101bd348 LegoCarRaceActor
+// VTABLE: BETA10 0x101bd370 LegoRaceActor
+// VTABLE: BETA10 0x101bd378 LegoAnimActor
+// VTABLE: BETA10 0x101bd390 LegoPathActor
+// SIZE 0x1a8
+class LegoJetskiRaceActor : public virtual LegoCarRaceActor {
+public:
+	LegoJetskiRaceActor();
+
+	// FUNCTION: LEGO1 0x10081d90
+	// FUNCTION: BETA10 0x100aa920
+	const char* ClassName() const override // vtable+0x0c
+	{
+		// STRING: LEGO1 0x100f0554
+		return "LegoJetskiRaceActor";
+	}
+
+	// FUNCTION: LEGO1 0x10081db0
+	// FUNCTION: BETA10 0x100aa960
+	MxBool IsA(const char* p_name) const override // vtable+0x10
+	{
+		return !strcmp(p_name, LegoJetskiRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name);
+	}
+
+	inline MxU32 VTable0x6c(
+		LegoPathBoundary* p_boundary,
+		Vector3& p_v1,
+		Vector3& p_v2,
+		float p_f1,
+		float p_f2,
+		Vector3& p_v3
+	) override;                                                                // vtable+0x6c
+	void Animate(float p_time) override;                                       // vtable+0x70
+	MxS32 VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) override; // vtable+0x1c
+
+	// SYNTHETIC: LEGO1 0x10013a80
+	// LegoJetskiRaceActor::`vbase destructor'
+
+	// SYNTHETIC: LEGO1 0x10081d50
+	// LegoJetskiRaceActor::`scalar deleting destructor'
+
+	// SYNTHETIC: LEGO1 0x10013ba0
+	// LegoJetskiRaceActor::~LegoJetskiRaceActor
+};
+
 // GLOBAL: LEGO1 0x100da0b0
 // LegoCarRaceActor::`vbtable'
 
@@ -108,4 +157,16 @@ protected:
 // GLOBAL: LEGO1 0x100da098
 // LegoCarRaceActor::`vbtable'{for `LegoRaceActor'}
 
+// GLOBAL: LEGO1 0x100da1f0
+// LegoJetskiRaceActor::`vbtable'{for `LegoJetskiRaceActor'}
+
+// GLOBAL: LEGO1 0x100da1e8
+// LegoJetskiRaceActor::`vbtable'{for `LegoAnimActor'}
+
+// GLOBAL: LEGO1 0x100da1d8
+// LegoJetskiRaceActor::`vbtable'{for `LegoRaceActor'}
+
+// GLOBAL: LEGO1 0x100da1c8
+// LegoJetskiRaceActor::`vbtable'{for `LegoCarRaceActor'}
+
 #endif // LEGOCARRACEACTOR_H
diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h
index 940abe72..fa055e0d 100644
--- a/LEGO1/lego/legoomni/include/legostate.h
+++ b/LEGO1/lego/legoomni/include/legostate.h
@@ -76,10 +76,10 @@ public:
 
 	// FUNCTION: LEGO1 0x10005fb0
 	// FUNCTION: BETA10 0x10017af0
-	virtual MxResult Serialize(LegoFile* p_file)
+	virtual MxResult Serialize(LegoStorage* p_storage)
 	{
-		if (p_file->IsWriteMode()) {
-			p_file->Write(MxString(ClassName()));
+		if (p_storage->IsWriteMode()) {
+			p_storage->WriteMxString(ClassName());
 		}
 		return SUCCESS;
 	} // vtable+0x1c
diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h
index 9d95f919..ff78ccc9 100644
--- a/LEGO1/lego/legoomni/include/legoutils.h
+++ b/LEGO1/lego/legoomni/include/legoutils.h
@@ -39,11 +39,11 @@ enum Cursor {
 class BoundingSphere;
 class MxAtomId;
 class LegoEntity;
-class LegoFile;
 class LegoAnimPresenter;
 class LegoNamedTexture;
 class LegoPathActor;
 class LegoROI;
+class LegoStorage;
 class LegoTreeNode;
 
 extern MxAtomId* g_isleScript;
@@ -72,9 +72,9 @@ MxBool FUN_1003ef60();
 MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_worldAtom, MxS32 p_worldEntityId);
 MxS32 UpdateLightPosition(MxS32 p_increase);
 void SetLightPosition(MxS32 p_index);
-LegoNamedTexture* ReadNamedTexture(LegoFile* p_file);
-void WriteDefaultTexture(LegoFile* p_file, const char* p_name);
-void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_namedTexture);
+LegoNamedTexture* ReadNamedTexture(LegoStorage* p_storage);
+void WriteDefaultTexture(LegoStorage* p_storage, const char* p_name);
+void WriteNamedTexture(LegoStorage* p_storage, LegoNamedTexture* p_namedTexture);
 void FUN_1003f930(LegoNamedTexture* p_namedTexture);
 
 // FUNCTION: BETA10 0x100260a0
diff --git a/LEGO1/lego/legoomni/include/legovariables.h b/LEGO1/lego/legoomni/include/legovariables.h
index 1b5cd93b..9447a5f9 100644
--- a/LEGO1/lego/legoomni/include/legovariables.h
+++ b/LEGO1/lego/legoomni/include/legovariables.h
@@ -54,13 +54,4 @@ public:
 	void SetValue(const char* p_value) override; // vtable+0x04
 };
 
-// VTABLE: LEGO1 0x100da878
-// SIZE 0x24
-class CustomizeAnimFileVariable : public MxVariable {
-public:
-	CustomizeAnimFileVariable(const char* p_key);
-
-	void SetValue(const char* p_value) override; // vtable+0x04
-};
-
 #endif // LEGOVARIABLES_H
diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h
index d7dc4671..10ff56ab 100644
--- a/LEGO1/lego/legoomni/include/legoworld.h
+++ b/LEGO1/lego/legoomni/include/legoworld.h
@@ -204,7 +204,7 @@ protected:
 // _Tree<MxCore *,MxCore *,set<MxCore *,CoreSetCompare,allocator<MxCore *> >::_Kfn,CoreSetCompare,allocator<MxCore *> >::find
 
 // TEMPLATE: LEGO1 0x10022360
-// ?_Construct@@YAXPAPAVLegoPathActor@@ABQAV1@@Z
+// ?_Construct@@YAXPAPAVMxCore@@ABQAV1@@Z
 
 // GLOBAL: LEGO1 0x100f11a0
 // _Tree<MxCore *,MxCore *,set<MxCore *,CoreSetCompare,allocator<MxCore *> >::_Kfn,CoreSetCompare,allocator<MxCore *> >::_Nil
diff --git a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h
index 3d42526f..8fcfecc7 100644
--- a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h
+++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h
@@ -15,6 +15,15 @@ public:
 	MxControlPresenter();
 	~MxControlPresenter() override;
 
+	// FUNCTION: LEGO1 0x10043fd0
+	void RepeatingTickle() override {} // vtable+0x24
+
+	// FUNCTION: LEGO1 0x10043fe0
+	MxBool VTable0x64(undefined4 p_undefined) override { return m_unk0x50; } // vtable+0x64
+
+	// FUNCTION: LEGO1 0x10043ff0
+	virtual void VTable0x68(MxBool p_unk0x50) { m_unk0x50 = p_unk0x50; } // vtable+0x68
+
 	// FUNCTION: LEGO1 0x10044000
 	// FUNCTION: BETA10 0x100ebf80
 	const char* ClassName() const override // vtable+0x0c
@@ -30,15 +39,12 @@ public:
 	}
 
 	void ReadyTickle() override;                                     // vtable+0x18
-	void RepeatingTickle() override;                                 // vtable+0x24
 	void ParseExtra() override;                                      // vtable+0x30
 	MxResult AddToManager() override;                                // vtable+0x34
 	MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c
 	void EndAction() override;                                       // vtable+0x40
 	MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48
 	void Enable(MxBool p_enable) override;                           // vtable+0x54
-	MxBool VTable0x64(undefined4 p_undefined) override;              // vtable+0x64
-	virtual void VTable0x68(MxBool p_unk0x50);                       // vtable+0x68
 	virtual void VTable0x6c(MxS16 p_unk0x4e);                        // vtable+0x6c
 
 	MxBool FUN_10044480(LegoControlManagerNotificationParam* p_param, MxPresenter* p_presenter);
diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h
index 84ed7a5e..52a429b8 100644
--- a/LEGO1/lego/legoomni/include/pizza.h
+++ b/LEGO1/lego/legoomni/include/pizza.h
@@ -124,7 +124,7 @@ public:
 		return !strcmp(p_name, PizzaMissionState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	// FUNCTION: BETA10 0x100ef470
 	void SetUnknown0xb0(MxU32 p_unk0xb0) { m_unk0xb0 = p_unk0xb0; }
diff --git a/LEGO1/lego/legoomni/include/pizzeria.h b/LEGO1/lego/legoomni/include/pizzeria.h
index 395dc1ca..a959abb3 100644
--- a/LEGO1/lego/legoomni/include/pizzeria.h
+++ b/LEGO1/lego/legoomni/include/pizzeria.h
@@ -29,7 +29,7 @@ public:
 		return !strcmp(p_name, PizzeriaState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	// SYNTHETIC: LEGO1 0x10017ce0
 	// PizzeriaState::`scalar deleting destructor'
diff --git a/LEGO1/lego/legoomni/include/police.h b/LEGO1/lego/legoomni/include/police.h
index 5f67d546..39294cb1 100644
--- a/LEGO1/lego/legoomni/include/police.h
+++ b/LEGO1/lego/legoomni/include/police.h
@@ -33,7 +33,7 @@ public:
 		return !strcmp(p_name, PoliceState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
+	MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
 
 	// SYNTHETIC: LEGO1 0x1005e920
 	// PoliceState::`scalar deleting destructor'
@@ -59,6 +59,9 @@ public:
 
 	MxLong Notify(MxParam& p_param) override; // vtable+0x04
 
+	// FUNCTION: LEGO1 0x1005e1d0
+	MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c
+
 	// FUNCTION: LEGO1 0x1005e1e0
 	// FUNCTION: BETA10 0x100f0c50
 	const char* ClassName() const override // vtable+0x0c
@@ -75,7 +78,6 @@ public:
 
 	MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18
 	void ReadyWorld() override;                       // vtable+0x50
-	MxBool VTable0x5c() override;                     // vtable+0x5c
 	MxBool Escape() override;                         // vtable+0x64
 	void Enable(MxBool p_enable) override;            // vtable+0x68
 
diff --git a/LEGO1/lego/legoomni/include/raceskel.h b/LEGO1/lego/legoomni/include/raceskel.h
index 48830bea..92859c68 100644
--- a/LEGO1/lego/legoomni/include/raceskel.h
+++ b/LEGO1/lego/legoomni/include/raceskel.h
@@ -17,6 +17,8 @@ public:
 
 	MxResult FUN_1001c360(float p_und, Matrix4& p_transform) override;
 
+	virtual void FUN_10071c80(Vector3& p_vec);
+
 	void GetCurrentAnimData(float* p_outCurAnimPosition, float* p_outCurAnimDuration);
 
 	// SYNTHETIC: LEGO1 0x10071cf0
diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h
index 4bf7d84a..812751bf 100644
--- a/LEGO1/lego/legoomni/include/towtrack.h
+++ b/LEGO1/lego/legoomni/include/towtrack.h
@@ -14,6 +14,40 @@ class TowTrackMissionState : public LegoState {
 public:
 	TowTrackMissionState();
 
+	// FUNCTION: LEGO1 0x1004dde0
+	// FUNCTION: BETA10 0x100f8720
+	MxResult Serialize(LegoStorage* p_storage) override
+	{
+		LegoState::Serialize(p_storage);
+
+		if (p_storage->IsReadMode()) {
+			p_storage->ReadS16(m_peScore);
+			p_storage->ReadS16(m_maScore);
+			p_storage->ReadS16(m_paScore);
+			p_storage->ReadS16(m_niScore);
+			p_storage->ReadS16(m_laScore);
+			p_storage->ReadS16(m_peHighScore);
+			p_storage->ReadS16(m_maHighScore);
+			p_storage->ReadS16(m_paHighScore);
+			p_storage->ReadS16(m_niHighScore);
+			p_storage->ReadS16(m_laHighScore);
+		}
+		else if (p_storage->IsWriteMode()) {
+			p_storage->WriteS16(m_peScore);
+			p_storage->WriteS16(m_maScore);
+			p_storage->WriteS16(m_paScore);
+			p_storage->WriteS16(m_niScore);
+			p_storage->WriteS16(m_laScore);
+			p_storage->WriteS16(m_peHighScore);
+			p_storage->WriteS16(m_maHighScore);
+			p_storage->WriteS16(m_paHighScore);
+			p_storage->WriteS16(m_niHighScore);
+			p_storage->WriteS16(m_laHighScore);
+		}
+
+		return SUCCESS;
+	} // vtable+0x1c
+
 	// FUNCTION: LEGO1 0x1004dfa0
 	// FUNCTION: BETA10 0x100f8920
 	const char* ClassName() const override // vtable+0x0c
@@ -28,8 +62,6 @@ public:
 		return !strcmp(p_name, TowTrackMissionState::ClassName()) || LegoState::IsA(p_name);
 	}
 
-	MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c
-
 	// FUNCTION: BETA10 0x10088890
 	MxS16 GetHighScore(MxU8 p_actorId)
 	{
diff --git a/LEGO1/lego/legoomni/src/actors/act3actors.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp
index 76651bdc..893a52d7 100644
--- a/LEGO1/lego/legoomni/src/actors/act3actors.cpp
+++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp
@@ -30,7 +30,7 @@ DECOMP_SIZE_ASSERT(Act3Shark, 0x1a8)
 // name verified by BETA10 0x10018776
 // GLOBAL: LEGO1 0x100f4120
 // GLOBAL: BETA10 0x101dcdc8
-Act3Actor::Act3CopDest g_copDest[5] = {
+Act3Cop::Act3CopDest g_copDest[5] = {
 	{"INT38", NULL, {3.69, -1.31251, -59.231}, {-0.99601698, 0.0, -0.089166}},
 	{
 		"EDG02_08",
@@ -1013,9 +1013,6 @@ MxResult Act3Brickster::FUN_100417c0()
 // FUNCTION: BETA10 0x1001b017
 MxS32 Act3Brickster::FUN_10042300()
 {
-	// TODO: Has poor inlining, can be fixed by changing the assignment operator in vector.h
-	// See extended comment in vector.h for operator=
-
 	Act3* a3 = (Act3*) m_world;
 
 	assert(a3 && a3->m_cop1 && a3->m_cop2);
diff --git a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp
index 2eaae385..6eb4c70a 100644
--- a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp
+++ b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp
@@ -109,7 +109,7 @@ MxResult Act3Ammo::Create(Act3* p_world, MxU32 p_isPizza, MxS32 p_index)
 
 // FUNCTION: LEGO1 0x10053b40
 // FUNCTION: BETA10 0x1001db2a
-MxResult Act3Ammo::FUN_10053b40(Vector3& p_srcLoc, Vector3& p_srcDir, Vector3& p_srcUp)
+MxResult Act3Ammo::FUN_10053b40(const Vector3& p_srcLoc, const Vector3& p_srcDir, const Vector3& p_srcUp)
 {
 	assert(p_srcDir[1] != 0);
 
diff --git a/LEGO1/lego/legoomni/src/actors/ambulance.cpp b/LEGO1/lego/legoomni/src/actors/ambulance.cpp
index 0d0b2c1b..25002471 100644
--- a/LEGO1/lego/legoomni/src/actors/ambulance.cpp
+++ b/LEGO1/lego/legoomni/src/actors/ambulance.cpp
@@ -49,11 +49,6 @@ Ambulance::Ambulance()
 	m_fuel = 1.0;
 }
 
-// FUNCTION: LEGO1 0x10035f90
-void Ambulance::Destroy(MxBool p_fromDestructor)
-{
-}
-
 // FUNCTION: LEGO1 0x10036150
 // FUNCTION: BETA10 0x100228fe
 Ambulance::~Ambulance()
@@ -647,37 +642,3 @@ AmbulanceMissionState::AmbulanceMissionState()
 	m_niHighScore = 0;
 	m_laHighScore = 0;
 }
-
-// FUNCTION: LEGO1 0x10037440
-// FUNCTION: BETA10 0x10024480
-MxResult AmbulanceMissionState::Serialize(LegoFile* p_file)
-{
-	LegoState::Serialize(p_file);
-
-	if (p_file->IsReadMode()) {
-		p_file->Read(m_peScore);
-		p_file->Read(m_maScore);
-		p_file->Read(m_paScore);
-		p_file->Read(m_niScore);
-		p_file->Read(m_laScore);
-		p_file->Read(m_peHighScore);
-		p_file->Read(m_maHighScore);
-		p_file->Read(m_paHighScore);
-		p_file->Read(m_niHighScore);
-		p_file->Read(m_laHighScore);
-	}
-	else if (p_file->IsWriteMode()) {
-		p_file->Write(m_peScore);
-		p_file->Write(m_maScore);
-		p_file->Write(m_paScore);
-		p_file->Write(m_niScore);
-		p_file->Write(m_laScore);
-		p_file->Write(m_peHighScore);
-		p_file->Write(m_maHighScore);
-		p_file->Write(m_paHighScore);
-		p_file->Write(m_niHighScore);
-		p_file->Write(m_laHighScore);
-	}
-
-	return SUCCESS;
-}
diff --git a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp
index c1b5694a..75e9b03a 100644
--- a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp
+++ b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp
@@ -100,7 +100,8 @@ void IslePathActor::Enter()
 // FUNCTION: BETA10 0x1003669f
 void IslePathActor::Exit()
 {
-	Reset();
+	SetActorState(c_initial);
+	m_roi->SetVisibility(TRUE);
 
 	GetViewManager()->Remove(m_roi);
 	GetViewManager()->Add(m_roi);
diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp
index a3a91218..98d711f2 100644
--- a/LEGO1/lego/legoomni/src/actors/pizza.cpp
+++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp
@@ -606,24 +606,24 @@ PizzaMissionState::PizzaMissionState()
 
 // FUNCTION: LEGO1 0x100393c0
 // FUNCTION: BETA10 0x100eebf2
-MxResult PizzaMissionState::Serialize(LegoFile* p_file)
+MxResult PizzaMissionState::Serialize(LegoStorage* p_storage)
 {
-	LegoState::Serialize(p_file);
+	LegoState::Serialize(p_storage);
 
-	if (p_file->IsReadMode()) {
+	if (p_storage->IsReadMode()) {
 		for (MxS16 i = 0; i < 5; i++) {
-			p_file->Read(m_missions[i].m_unk0x06);
-			p_file->Read(m_missions[i].m_unk0x14);
-			p_file->Read(m_missions[i].m_score);
-			p_file->Read(m_missions[i].m_hiScore);
+			p_storage->ReadS16(m_missions[i].m_unk0x06);
+			p_storage->ReadS16(m_missions[i].m_unk0x14);
+			p_storage->ReadS16(m_missions[i].m_score);
+			p_storage->ReadS16(m_missions[i].m_hiScore);
 		}
 	}
-	else if (p_file->IsWriteMode()) {
+	else if (p_storage->IsWriteMode()) {
 		for (MxS16 i = 0; i < 5; i++) {
-			p_file->Write(m_missions[i].m_unk0x06);
-			p_file->Write(m_missions[i].m_unk0x14);
-			p_file->Write(m_missions[i].m_score);
-			p_file->Write(m_missions[i].m_hiScore);
+			p_storage->WriteS16(m_missions[i].m_unk0x06);
+			p_storage->WriteS16(m_missions[i].m_unk0x14);
+			p_storage->WriteS16(m_missions[i].m_score);
+			p_storage->WriteS16(m_missions[i].m_hiScore);
 		}
 	}
 
diff --git a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp
index 54bf583b..d2d98956 100644
--- a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp
+++ b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp
@@ -118,18 +118,18 @@ MxU32 PizzeriaState::NextAction()
 
 // FUNCTION: LEGO1 0x10017da0
 // FUNCTION: BETA10 0x100efe33
-MxResult PizzeriaState::Serialize(LegoFile* p_file)
+MxResult PizzeriaState::Serialize(LegoStorage* p_storage)
 {
-	MxResult res = LegoState::Serialize(p_file);
+	MxResult res = LegoState::Serialize(p_storage);
 
-	if (p_file->IsReadMode()) {
+	if (p_storage->IsReadMode()) {
 		for (MxS16 i = 0; i < 5; i++) {
-			p_file->Read(m_unk0x08[i].m_nextIndex);
+			p_storage->ReadS16(m_unk0x08[i].m_nextIndex);
 		}
 	}
 	else {
 		for (MxS16 i = 0; i < 5; i++) {
-			p_file->Write(m_unk0x08[i].m_nextIndex);
+			p_storage->WriteS16(m_unk0x08[i].m_nextIndex);
 		}
 	}
 
diff --git a/LEGO1/lego/legoomni/src/actors/towtrack.cpp b/LEGO1/lego/legoomni/src/actors/towtrack.cpp
index aa04a0dd..b3b8d221 100644
--- a/LEGO1/lego/legoomni/src/actors/towtrack.cpp
+++ b/LEGO1/lego/legoomni/src/actors/towtrack.cpp
@@ -609,37 +609,3 @@ TowTrackMissionState::TowTrackMissionState()
 	m_niHighScore = 0;
 	m_laHighScore = 0;
 }
-
-// FUNCTION: LEGO1 0x1004dde0
-// FUNCTION: BETA10 0x100f8720
-MxResult TowTrackMissionState::Serialize(LegoFile* p_file)
-{
-	LegoState::Serialize(p_file);
-
-	if (p_file->IsReadMode()) {
-		p_file->Read(m_peScore);
-		p_file->Read(m_maScore);
-		p_file->Read(m_paScore);
-		p_file->Read(m_niScore);
-		p_file->Read(m_laScore);
-		p_file->Read(m_peHighScore);
-		p_file->Read(m_maHighScore);
-		p_file->Read(m_paHighScore);
-		p_file->Read(m_niHighScore);
-		p_file->Read(m_laHighScore);
-	}
-	else if (p_file->IsWriteMode()) {
-		p_file->Write(m_peScore);
-		p_file->Write(m_maScore);
-		p_file->Write(m_paScore);
-		p_file->Write(m_niScore);
-		p_file->Write(m_laScore);
-		p_file->Write(m_peHighScore);
-		p_file->Write(m_maHighScore);
-		p_file->Write(m_paHighScore);
-		p_file->Write(m_niHighScore);
-		p_file->Write(m_laHighScore);
-	}
-
-	return SUCCESS;
-}
diff --git a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp
index 6338b281..289e4ea3 100644
--- a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp
+++ b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp
@@ -20,9 +20,9 @@ LegoCacheSoundManager::~LegoCacheSoundManager()
 
 	while (!m_list.empty()) {
 		sound = (*m_list.begin()).GetSound();
+		// TODO: LegoCacheSoundEntry::~LegoCacheSoundEntry should not be inlined here
 		m_list.erase(m_list.begin());
 		sound->Stop();
-		// DECOMP: delete should not be inlined here
 		delete sound;
 	}
 }
diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp
index e8cd35ea..3d429841 100644
--- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp
+++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp
@@ -1708,24 +1708,24 @@ LegoVehicleBuildState::LegoVehicleBuildState(const char* p_classType)
 
 // FUNCTION: LEGO1 0x10026120
 // FUNCTION: BETA10 0x1006eef0
-MxResult LegoVehicleBuildState::Serialize(LegoFile* p_file)
+MxResult LegoVehicleBuildState::Serialize(LegoStorage* p_storage)
 {
-	LegoState::Serialize(p_file);
+	LegoState::Serialize(p_storage);
 
-	if (p_file->IsReadMode()) {
-		p_file->Read(m_unk0x4c);
-		p_file->Read(m_unk0x4d);
-		p_file->Read(m_unk0x4e);
+	if (p_storage->IsReadMode()) {
+		p_storage->ReadU8(m_unk0x4c);
+		p_storage->ReadU8(m_unk0x4d);
+		p_storage->ReadU8(m_unk0x4e);
 #ifndef BETA10
-		p_file->Read(m_placedPartCount);
+		p_storage->ReadU8(m_placedPartCount);
 #endif
 	}
 	else {
-		p_file->Write(m_unk0x4c);
-		p_file->Write(m_unk0x4d);
-		p_file->Write(m_unk0x4e);
+		p_storage->WriteU8(m_unk0x4c);
+		p_storage->WriteU8(m_unk0x4d);
+		p_storage->WriteU8(m_unk0x4e);
 #ifndef BETA10
-		p_file->Write(m_placedPartCount);
+		p_storage->WriteU8(m_placedPartCount);
 #endif
 	}
 
diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp
index b3512838..4a162ab6 100644
--- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp
@@ -41,12 +41,6 @@ LegoCarBuildAnimPresenter::LegoCarBuildAnimPresenter()
 	m_mainSourceId = NULL;
 }
 
-// FUNCTION: LEGO1 0x10078500
-void LegoCarBuildAnimPresenter::RepeatingTickle()
-{
-	// empty
-}
-
 // FUNCTION: LEGO1 0x10078680
 // FUNCTION: BETA10 0x1007091e
 LegoCarBuildAnimPresenter::~LegoCarBuildAnimPresenter()
@@ -262,9 +256,9 @@ void LegoCarBuildAnimPresenter::StreamingTickle()
 
 	Mx3DPointFloat dirVec;
 
-	Vector3 cameraPosition(camera->GetWorldPosition());
-	Vector3 upVec(camera->GetWorldUp());
-	Vector3 targetPosition(targetROI->GetWorldPosition());
+	const Vector3 cameraPosition(camera->GetWorldPosition());
+	const Vector3 upVec(camera->GetWorldUp());
+	const Vector3 targetPosition(targetROI->GetWorldPosition());
 
 	MxMatrix localTransform;
 
@@ -296,6 +290,32 @@ void LegoCarBuildAnimPresenter::EndAction()
 	}
 }
 
+// FUNCTION: LEGO1 0x10078e30
+// FUNCTION: BETA10 0x10071387
+MxResult LegoCarBuildAnimPresenter::Serialize(LegoStorage* p_storage)
+{
+	if (p_storage->IsReadMode()) {
+		p_storage->ReadS16(m_placedPartCount);
+		p_storage->ReadFloat(m_unk0x130);
+		for (MxS16 i = 0; i < m_numberOfParts; i++) {
+			p_storage->ReadString(m_parts[i].m_name);
+			p_storage->ReadString(m_parts[i].m_wiredName);
+			p_storage->ReadS16(m_parts[i].m_objectId);
+		}
+	}
+	else if (p_storage->IsWriteMode()) {
+		p_storage->WriteS16(m_placedPartCount);
+		p_storage->WriteFloat(m_unk0x130);
+		for (MxS16 i = 0; i < m_numberOfParts; i++) {
+			p_storage->WriteString(m_parts[i].m_name);
+			p_storage->WriteString(m_parts[i].m_wiredName);
+			p_storage->WriteS16(m_parts[i].m_objectId);
+		}
+	}
+
+	return SUCCESS;
+}
+
 // FUNCTION: LEGO1 0x10079050
 // FUNCTION: BETA10 0x1007151e
 void LegoCarBuildAnimPresenter::FUN_10079050(MxS16 p_index)
diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp
index da23297e..02b08761 100644
--- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp
+++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp
@@ -623,7 +623,7 @@ MxResult LegoAnimationManager::LoadWorldInfo(LegoOmni::World p_worldId)
 
 		DeleteAnimations();
 
-		LegoFile file;
+		LegoFile storage;
 
 		if (p_worldId == LegoOmni::e_undefined) {
 			result = SUCCESS;
@@ -656,12 +656,12 @@ MxResult LegoAnimationManager::LoadWorldInfo(LegoOmni::World p_worldId)
 			}
 		}
 
-		if (file.Open(path, LegoFile::c_read) == FAILURE) {
+		if (storage.Open(path, LegoFile::c_read) == FAILURE) {
 			goto done;
 		}
 
 		MxU32 version;
-		if (file.Read(&version, sizeof(version)) == FAILURE) {
+		if (storage.Read(&version, sizeof(version)) == FAILURE) {
 			goto done;
 		}
 
@@ -670,7 +670,7 @@ MxResult LegoAnimationManager::LoadWorldInfo(LegoOmni::World p_worldId)
 			goto done;
 		}
 
-		if (file.Read(&m_animCount, sizeof(m_animCount)) == FAILURE) {
+		if (storage.Read(&m_animCount, sizeof(m_animCount)) == FAILURE) {
 			goto done;
 		}
 
@@ -678,7 +678,7 @@ MxResult LegoAnimationManager::LoadWorldInfo(LegoOmni::World p_worldId)
 		memset(m_anims, 0, m_animCount * sizeof(*m_anims));
 
 		for (j = 0; j < m_animCount; j++) {
-			if (ReadAnimInfo(&file, &m_anims[j]) == FAILURE) {
+			if (ReadAnimInfo(&storage, &m_anims[j]) == FAILURE) {
 				goto done;
 			}
 
@@ -757,49 +757,49 @@ MxBool LegoAnimationManager::FindVehicle(const char* p_name, MxU32& p_index)
 }
 
 // FUNCTION: LEGO1 0x10060180
-MxResult LegoAnimationManager::ReadAnimInfo(LegoFile* p_file, AnimInfo* p_info)
+MxResult LegoAnimationManager::ReadAnimInfo(LegoStorage* p_storage, AnimInfo* p_info)
 {
 	MxResult result = FAILURE;
 	MxU8 length;
 	MxS32 i, j;
 
-	if (p_file->Read(&length, sizeof(length)) == FAILURE) {
+	if (p_storage->Read(&length, sizeof(length)) == FAILURE) {
 		goto done;
 	}
 
 	p_info->m_name = new char[length + 1];
-	if (p_file->Read(p_info->m_name, length) == FAILURE) {
+	if (p_storage->Read(p_info->m_name, length) == FAILURE) {
 		goto done;
 	}
 
 	p_info->m_name[length] = 0;
-	if (p_file->Read(&p_info->m_objectId, sizeof(p_info->m_objectId)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_objectId, sizeof(p_info->m_objectId)) == FAILURE) {
 		goto done;
 	}
 
-	if (p_file->Read(&p_info->m_location, sizeof(p_info->m_location)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_location, sizeof(p_info->m_location)) == FAILURE) {
 		goto done;
 	}
-	if (p_file->Read(&p_info->m_unk0x0a, sizeof(p_info->m_unk0x0a)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_unk0x0a, sizeof(p_info->m_unk0x0a)) == FAILURE) {
 		goto done;
 	}
-	if (p_file->Read(&p_info->m_unk0x0b, sizeof(p_info->m_unk0x0b)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_unk0x0b, sizeof(p_info->m_unk0x0b)) == FAILURE) {
 		goto done;
 	}
-	if (p_file->Read(&p_info->m_unk0x0c, sizeof(p_info->m_unk0x0c)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_unk0x0c, sizeof(p_info->m_unk0x0c)) == FAILURE) {
 		goto done;
 	}
-	if (p_file->Read(&p_info->m_unk0x0d, sizeof(p_info->m_unk0x0d)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_unk0x0d, sizeof(p_info->m_unk0x0d)) == FAILURE) {
 		goto done;
 	}
 
 	for (i = 0; i < (MxS32) sizeOfArray(p_info->m_unk0x10); i++) {
-		if (p_file->Read(&p_info->m_unk0x10[i], sizeof(*p_info->m_unk0x10)) != SUCCESS) {
+		if (p_storage->Read(&p_info->m_unk0x10[i], sizeof(*p_info->m_unk0x10)) != SUCCESS) {
 			goto done;
 		}
 	}
 
-	if (p_file->Read(&p_info->m_modelCount, sizeof(p_info->m_modelCount)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_modelCount, sizeof(p_info->m_modelCount)) == FAILURE) {
 		goto done;
 	}
 
@@ -807,7 +807,7 @@ MxResult LegoAnimationManager::ReadAnimInfo(LegoFile* p_file, AnimInfo* p_info)
 	memset(p_info->m_models, 0, p_info->m_modelCount * sizeof(*p_info->m_models));
 
 	for (j = 0; j < p_info->m_modelCount; j++) {
-		if (ReadModelInfo(p_file, &p_info->m_models[j]) == FAILURE) {
+		if (ReadModelInfo(p_storage, &p_info->m_models[j]) == FAILURE) {
 			goto done;
 		}
 	}
@@ -819,35 +819,35 @@ done:
 }
 
 // FUNCTION: LEGO1 0x10060310
-MxResult LegoAnimationManager::ReadModelInfo(LegoFile* p_file, ModelInfo* p_info)
+MxResult LegoAnimationManager::ReadModelInfo(LegoStorage* p_storage, ModelInfo* p_info)
 {
 	MxResult result = FAILURE;
 	MxU8 length;
 
-	if (p_file->Read(&length, 1) == FAILURE) {
+	if (p_storage->Read(&length, 1) == FAILURE) {
 		goto done;
 	}
 
 	p_info->m_name = new char[length + 1];
-	if (p_file->Read(p_info->m_name, length) == FAILURE) {
+	if (p_storage->Read(p_info->m_name, length) == FAILURE) {
 		goto done;
 	}
 
 	p_info->m_name[length] = 0;
-	if (p_file->Read(&p_info->m_unk0x04, sizeof(p_info->m_unk0x04)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_unk0x04, sizeof(p_info->m_unk0x04)) == FAILURE) {
 		goto done;
 	}
 
-	if (p_file->Read(p_info->m_location, sizeof(p_info->m_location)) != SUCCESS) {
+	if (p_storage->Read(p_info->m_location, sizeof(p_info->m_location)) != SUCCESS) {
 		goto done;
 	}
-	if (p_file->Read(p_info->m_direction, sizeof(p_info->m_direction)) != SUCCESS) {
+	if (p_storage->Read(p_info->m_direction, sizeof(p_info->m_direction)) != SUCCESS) {
 		goto done;
 	}
-	if (p_file->Read(p_info->m_up, sizeof(p_info->m_up)) != SUCCESS) {
+	if (p_storage->Read(p_info->m_up, sizeof(p_info->m_up)) != SUCCESS) {
 		goto done;
 	}
-	if (p_file->Read(&p_info->m_unk0x2c, sizeof(p_info->m_unk0x2c)) == FAILURE) {
+	if (p_storage->Read(&p_info->m_unk0x2c, sizeof(p_info->m_unk0x2c)) == FAILURE) {
 		goto done;
 	}
 
@@ -2938,21 +2938,21 @@ void AnimState::InitFromAnims(MxU32 p_animsLength, AnimInfo* p_anims, MxU32 p_ex
 
 // FUNCTION: LEGO1 0x100652d0
 // FUNCTION: BETA10 0x10046621
-MxResult AnimState::Serialize(LegoFile* p_file)
+MxResult AnimState::Serialize(LegoStorage* p_storage)
 {
-	MxResult result = LegoState::Serialize(p_file);
+	MxResult result = LegoState::Serialize(p_storage);
 
 	if (result == SUCCESS) {
-		if (p_file->IsReadMode()) {
+		if (p_storage->IsReadMode()) {
 			MxS32 i;
 
-			p_file->Read(m_extraCharacterId);
+			p_storage->ReadU32(m_extraCharacterId);
 
 			if (m_unk0x10) {
 				delete[] m_unk0x10;
 			}
 
-			p_file->Read(m_unk0x0c);
+			p_storage->ReadU32(m_unk0x0c);
 
 #ifndef BETA10
 			if (m_unk0x0c != 0) {
@@ -2966,11 +2966,11 @@ MxResult AnimState::Serialize(LegoFile* p_file)
 #endif
 
 			for (i = 0; i < m_unk0x0c; i++) {
-				p_file->Read(m_unk0x10[i]);
+				p_storage->ReadU16(m_unk0x10[i]);
 			}
 
 			// Note that here we read first and then free memory in contrast to above
-			p_file->Read(m_locationsFlagsLength);
+			p_storage->ReadU32(m_locationsFlagsLength);
 
 #ifndef BETA10
 			if (m_locationsFlags) {
@@ -2988,22 +2988,22 @@ MxResult AnimState::Serialize(LegoFile* p_file)
 #endif
 
 			for (i = 0; i < m_locationsFlagsLength; i++) {
-				p_file->Read(m_locationsFlags[i]);
+				p_storage->ReadU8(m_locationsFlags[i]);
 			}
 		}
-		else if (p_file->IsWriteMode()) {
+		else if (p_storage->IsWriteMode()) {
 			MxS32 i;
 
-			p_file->Write(m_extraCharacterId);
-			p_file->Write(m_unk0x0c);
+			p_storage->WriteU32(m_extraCharacterId);
+			p_storage->WriteU32(m_unk0x0c);
 
 			for (i = 0; i < m_unk0x0c; i++) {
-				p_file->Write(m_unk0x10[i]);
+				p_storage->WriteU16(m_unk0x10[i]);
 			}
 
-			p_file->Write(m_locationsFlagsLength);
+			p_storage->WriteU32(m_locationsFlagsLength);
 			for (i = 0; i < m_locationsFlagsLength; i++) {
-				p_file->Write(m_locationsFlags[i]);
+				p_storage->WriteU8(m_locationsFlags[i]);
 			}
 		}
 	}
diff --git a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp
deleted file mode 100644
index bc31bb2c..00000000
--- a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-#include "legobackgroundcolor.h"
-
-#include "3dmanager/lego3dmanager.h"
-#include "decomp.h"
-#include "legoutils.h"
-#include "legovideomanager.h"
-#include "misc.h"
-
-#include <stdio.h>
-
-DECOMP_SIZE_ASSERT(LegoBackgroundColor, 0x30)
-
-// GLOBAL: LEGO1 0x100f3fb0
-// STRING: LEGO1 0x100f3a18
-const char* g_delimiter = " \t";
-
-// GLOBAL: LEGO1 0x100f3fb4
-// STRING: LEGO1 0x100f3bf0
-const char* g_set = "set";
-
-// GLOBAL: LEGO1 0x100f3fb8
-// STRING: LEGO1 0x100f0cdc
-const char* g_reset = "reset";
-
-// FUNCTION: LEGO1 0x1003bfb0
-LegoBackgroundColor::LegoBackgroundColor(const char* p_key, const char* p_value)
-{
-	m_key = p_key;
-	m_key.ToUpperCase();
-	SetValue(p_value);
-}
-
-// FUNCTION: LEGO1 0x1003c070
-void LegoBackgroundColor::SetValue(const char* p_colorString)
-{
-	m_value = p_colorString;
-	m_value.ToLowerCase();
-
-	LegoVideoManager* videomanager = VideoManager();
-	if (!videomanager || !p_colorString) {
-		return;
-	}
-
-	float convertedR, convertedG, convertedB;
-	char* colorStringCopy = strcpy(new char[strlen(p_colorString) + 1], p_colorString);
-	char* colorStringSplit = strtok(colorStringCopy, g_delimiter);
-
-	if (!strcmp(colorStringSplit, g_set)) {
-		colorStringSplit = strtok(0, g_delimiter);
-		if (colorStringSplit) {
-			m_h = (float) (atoi(colorStringSplit) * 0.01);
-		}
-		colorStringSplit = strtok(0, g_delimiter);
-		if (colorStringSplit) {
-			m_s = (float) (atoi(colorStringSplit) * 0.01);
-		}
-		colorStringSplit = strtok(0, g_delimiter);
-		if (colorStringSplit) {
-			m_v = (float) (atoi(colorStringSplit) * 0.01);
-		}
-
-		ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
-		videomanager->SetSkyColor(convertedR, convertedG, convertedB);
-	}
-	else if (!strcmp(colorStringSplit, g_reset)) {
-		ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
-		videomanager->SetSkyColor(convertedR, convertedG, convertedB);
-	}
-
-	delete[] colorStringCopy;
-}
-
-// FUNCTION: LEGO1 0x1003c230
-void LegoBackgroundColor::ToggleDayNight(MxBool p_sun)
-{
-	char buffer[30];
-
-	if (p_sun) {
-		m_s += 0.1;
-		if (m_s > 0.9) {
-			m_s = 1.0;
-		}
-	}
-	else {
-		m_s -= 0.1;
-		if (m_s < 0.1) {
-			m_s = 0.1;
-		}
-	}
-
-	sprintf(buffer, "set %d %d %d", (MxU32) (m_h * 100.0f), (MxU32) (m_s * 100.0f), (MxU32) (m_v * 100.0f));
-	m_value = buffer;
-
-	float convertedR, convertedG, convertedB;
-	ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
-	VideoManager()->SetSkyColor(convertedR, convertedG, convertedB);
-	SetLightColor(convertedR, convertedG, convertedB);
-}
-
-// FUNCTION: LEGO1 0x1003c330
-void LegoBackgroundColor::ToggleSkyColor()
-{
-	char buffer[30];
-
-	m_h += 0.05;
-	if (m_h > 1.0) {
-		m_h -= 1.0;
-	}
-
-	sprintf(buffer, "set %d %d %d", (MxU32) (m_h * 100.0f), (MxU32) (m_s * 100.0f), (MxU32) (m_v * 100.0f));
-	m_value = buffer;
-
-	float convertedR, convertedG, convertedB;
-	ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
-	VideoManager()->SetSkyColor(convertedR, convertedG, convertedB);
-	SetLightColor(convertedR, convertedG, convertedB);
-}
-
-// FUNCTION: LEGO1 0x1003c400
-void LegoBackgroundColor::SetLightColor(float p_r, float p_g, float p_b)
-{
-	if (!VideoManager()->GetVideoParam().Flags().GetF2bit0()) {
-		// TODO: Computed constants based on what?
-		p_r *= 1. / 0.23;
-		p_g *= 1. / 0.63;
-		p_b *= 1. / 0.85;
-
-		if (p_r > 1.0) {
-			p_r = 1.0;
-		}
-
-		if (p_g > 1.0) {
-			p_g = 1.0;
-		}
-
-		if (p_b > 1.0) {
-			p_b = 1.0;
-		}
-
-		VideoManager()->Get3DManager()->GetLego3DView()->SetLightColor(FALSE, p_r, p_g, p_b);
-		VideoManager()->Get3DManager()->GetLego3DView()->SetLightColor(TRUE, p_r, p_g, p_b);
-	}
-}
-
-// FUNCTION: LEGO1 0x1003c4b0
-void LegoBackgroundColor::SetLightColor()
-{
-	float convertedR, convertedG, convertedB;
-	ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
-	SetLightColor(convertedR, convertedG, convertedB);
-}
diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp
index 61c02d03..23a1a1ea 100644
--- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp
+++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp
@@ -3,9 +3,10 @@
 #include "3dmanager/lego3dmanager.h"
 #include "legoactors.h"
 #include "legoanimactor.h"
+#include "legobuildingmanager.h"
 #include "legoextraactor.h"
 #include "legogamestate.h"
-#include "legovariables.h"
+#include "legoplantmanager.h"
 #include "legovideomanager.h"
 #include "misc.h"
 #include "misc/legocontainer.h"
@@ -23,6 +24,7 @@
 
 DECOMP_SIZE_ASSERT(LegoCharacter, 0x08)
 DECOMP_SIZE_ASSERT(LegoCharacterManager, 0x08)
+DECOMP_SIZE_ASSERT(CustomizeAnimFileVariable, 0x24)
 
 // GLOBAL: LEGO1 0x100fc4d0
 MxU32 LegoCharacterManager::g_maxMove = 4;
@@ -1088,3 +1090,21 @@ LegoROI* LegoCharacterManager::FUN_10085a80(const char* p_name, const char* p_lo
 {
 	return CreateAutoROI(p_name, p_lodName, p_createEntity);
 }
+
+// FUNCTION: LEGO1 0x10085aa0
+CustomizeAnimFileVariable::CustomizeAnimFileVariable(const char* p_key)
+{
+	m_key = p_key;
+	m_key.ToUpperCase();
+}
+
+// FUNCTION: LEGO1 0x10085b50
+void CustomizeAnimFileVariable::SetValue(const char* p_value)
+{
+	// STRING: LEGO1 0x100fc4f4
+	if (strcmp(m_key.GetData(), "CUSTOMIZE_ANIM_FILE") == 0) {
+		CharacterManager()->SetCustomizeAnimFile(p_value);
+		PlantManager()->SetCustomizeAnimFile(p_value);
+		BuildingManager()->SetCustomizeAnimFile(p_value);
+	}
+}
diff --git a/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp b/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp
deleted file mode 100644
index c95cb40e..00000000
--- a/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "legofullscreenmovie.h"
-
-#include "decomp.h"
-#include "legovideomanager.h"
-#include "misc.h"
-#include "mxtypes.h"
-
-DECOMP_SIZE_ASSERT(LegoFullScreenMovie, 0x24)
-
-// GLOBAL: LEGO1 0x100f3fbc
-// STRING: LEGO1 0x100f3be8
-const char* g_strEnable = "enable";
-
-// GLOBAL: LEGO1 0x100f3fc0
-// STRING: LEGO1 0x100f3bf4
-const char* g_strDisable = "disable";
-
-// FUNCTION: LEGO1 0x1003c500
-LegoFullScreenMovie::LegoFullScreenMovie(const char* p_key, const char* p_value)
-{
-	m_key = p_key;
-	m_key.ToUpperCase();
-	SetValue(p_value);
-}
-
-// FUNCTION: LEGO1 0x1003c5c0
-void LegoFullScreenMovie::SetValue(const char* p_option)
-{
-	m_value = p_option;
-	m_value.ToLowerCase();
-
-	LegoVideoManager* videomanager = VideoManager();
-	if (videomanager) {
-		if (!strcmp(m_value.GetData(), g_strEnable)) {
-			videomanager->EnableFullScreenMovie(TRUE);
-			return;
-		}
-
-		if (!strcmp(m_value.GetData(), g_strDisable)) {
-			videomanager->EnableFullScreenMovie(FALSE);
-			return;
-		}
-	}
-}
diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp
index 9587fbc9..14b1fe25 100644
--- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp
+++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp
@@ -31,10 +31,8 @@
 #include "jukebox_actions.h"
 #include "jukeboxw_actions.h"
 #include "legoanimationmanager.h"
-#include "legobackgroundcolor.h"
 #include "legobuildingmanager.h"
 #include "legocharactermanager.h"
-#include "legofullscreenmovie.h"
 #include "legomain.h"
 #include "legonavcontroller.h"
 #include "legoplantmanager.h"
@@ -71,6 +69,8 @@ DECOMP_SIZE_ASSERT(LegoGameState::ScoreItem, 0x2c)
 DECOMP_SIZE_ASSERT(LegoGameState::History, 0x374)
 DECOMP_SIZE_ASSERT(LegoGameState, 0x430)
 DECOMP_SIZE_ASSERT(ColorStringStruct, 0x08)
+DECOMP_SIZE_ASSERT(LegoBackgroundColor, 0x30)
+DECOMP_SIZE_ASSERT(LegoFullScreenMovie, 0x24)
 
 // GLOBAL: LEGO1 0x100f3e40
 // STRING: LEGO1 0x100f3e3c
@@ -89,6 +89,8 @@ const char* g_historyGSI = "History.gsi";
 // TODO: make g_endOfVariables reference the actual end of the variable array.
 // GLOBAL: LEGO1 0x100f3e50
 // STRING: LEGO1 0x100f3e00
+// GLOBAL: BETA10 0x101ed5dc
+// STRING: BETA10 0x101ed768
 const char* g_endOfVariables = "END_OF_VARIABLES";
 
 // GLOBAL: LEGO1 0x100f3e58
@@ -121,6 +123,26 @@ ColorStringStruct g_colorSaveData[43] = {
 // in that table is a special entry, the string "END_OF_VARIABLES"
 extern const char* g_endOfVariables;
 
+// GLOBAL: LEGO1 0x100f3fb0
+// STRING: LEGO1 0x100f3a18
+const char* g_delimiter = " \t";
+
+// GLOBAL: LEGO1 0x100f3fb4
+// STRING: LEGO1 0x100f3bf0
+const char* g_set = "set";
+
+// GLOBAL: LEGO1 0x100f3fb8
+// STRING: LEGO1 0x100f0cdc
+const char* g_reset = "reset";
+
+// GLOBAL: LEGO1 0x100f3fbc
+// STRING: LEGO1 0x100f3be8
+const char* g_strEnable = "enable";
+
+// GLOBAL: LEGO1 0x100f3fc0
+// STRING: LEGO1 0x100f3bf4
+const char* g_strDisable = "disable";
+
 // FUNCTION: LEGO1 0x10039550
 LegoGameState::LegoGameState()
 {
@@ -232,6 +254,7 @@ void LegoGameState::ResetROI()
 }
 
 // FUNCTION: LEGO1 0x10039980
+// FUNCTION: BETA10 0x100840e4
 MxResult LegoGameState::Save(MxULong p_slot)
 {
 	InfocenterState* infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState");
@@ -255,10 +278,10 @@ MxResult LegoGameState::Save(MxULong p_slot)
 		goto done;
 	}
 
-	storage.Write(0x1000c);
-	storage.Write(m_unk0x24);
-	storage.Write((MxU16) m_currentAct);
-	storage.Write(m_actorId);
+	storage.WriteS32(0x1000c);
+	storage.WriteS16(m_unk0x24);
+	storage.WriteU16(m_currentAct);
+	storage.WriteU8(m_actorId);
 
 	for (i = 0; i < sizeOfArray(g_colorSaveData); i++) {
 		if (WriteVariable(&storage, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) {
@@ -284,7 +307,7 @@ MxResult LegoGameState::Save(MxULong p_slot)
 		}
 	}
 
-	storage.Write(count);
+	storage.WriteS16(count);
 
 	for (j = 0; j < m_stateCount; j++) {
 		if (m_stateArray[j]->IsSerializable()) {
@@ -293,7 +316,7 @@ MxResult LegoGameState::Save(MxULong p_slot)
 	}
 
 	area = m_unk0x42c;
-	storage.Write((MxU16) area);
+	storage.WriteU16(area);
 	SerializeScoreHistory(2);
 	m_isDirty = FALSE;
 
@@ -344,18 +367,18 @@ MxResult LegoGameState::Load(MxULong p_slot)
 	MxS16 count, actArea;
 	const char* lightPosition;
 
-	storage.Read(version);
+	storage.ReadS32(version);
 
 	if (version != 0x1000c) {
 		OmniError("Saved game version mismatch", 0);
 		goto done;
 	}
 
-	storage.Read(m_unk0x24);
-	storage.Read(actArea);
+	storage.ReadS16(m_unk0x24);
+	storage.ReadS16(actArea);
 
 	SetCurrentAct((Act) actArea);
-	storage.Read(m_actorId);
+	storage.ReadU8(m_actorId);
 	if (m_actorId) {
 		SetActor(m_actorId);
 	}
@@ -388,11 +411,11 @@ MxResult LegoGameState::Load(MxULong p_slot)
 	}
 
 	char stateName[80];
-	storage.Read(count);
+	storage.ReadS16(count);
 
 	if (count) {
 		for (MxS16 i = 0; i < count; i++) {
-			storage.Read(stateName);
+			storage.ReadString(stateName);
 
 			LegoState* state = GetState(stateName);
 			if (!state) {
@@ -407,7 +430,7 @@ MxResult LegoGameState::Load(MxULong p_slot)
 		}
 	}
 
-	storage.Read(actArea);
+	storage.ReadS16(actArea);
 
 	if (m_currentAct == e_act1) {
 		m_unk0x42c = e_undefined;
@@ -444,6 +467,7 @@ void LegoGameState::SetSavePath(char* p_savePath)
 }
 
 // FUNCTION: LEGO1 0x10039f70
+// FUNCTION: BETA10 0x1008483b
 MxResult LegoGameState::WriteVariable(LegoStorage* p_storage, MxVariableTable* p_from, const char* p_variableName)
 {
 	MxResult result = FAILURE;
@@ -451,20 +475,28 @@ MxResult LegoGameState::WriteVariable(LegoStorage* p_storage, MxVariableTable* p
 
 	if (variableValue) {
 		MxU8 length = strlen(p_variableName);
-		if (p_storage->Write(&length, sizeof(length)) == SUCCESS) {
-			if (p_storage->Write(p_variableName, length) == SUCCESS) {
-				length = strlen(variableValue);
-				if (p_storage->Write(&length, sizeof(length)) == SUCCESS) {
-					result = p_storage->Write(variableValue, length);
-				}
-			}
+		if (p_storage->Write(&length, sizeof(length)) != SUCCESS) {
+			goto done;
 		}
+
+		if (p_storage->Write(p_variableName, length) != SUCCESS) {
+			goto done;
+		}
+
+		length = strlen(variableValue);
+		if (p_storage->Write(&length, sizeof(length)) != SUCCESS) {
+			goto done;
+		}
+
+		result = p_storage->Write(variableValue, length);
 	}
 
+done:
 	return result;
 }
 
 // FUNCTION: LEGO1 0x1003a020
+// FUNCTION: BETA10 0x10084928
 MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_storage)
 {
 	MxU8 len = strlen(g_endOfVariables);
@@ -477,37 +509,52 @@ MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_storage)
 }
 
 // FUNCTION: LEGO1 0x1003a080
+// FUNCTION: BETA10 0x1008498b
 MxS32 LegoGameState::ReadVariable(LegoStorage* p_storage, MxVariableTable* p_to)
 {
 	MxS32 result = 1;
-	MxU8 length;
+	MxU8 len;
 
-	if (p_storage->Read(&length, sizeof(length)) == SUCCESS) {
-		char nameBuffer[256];
-		if (p_storage->Read(nameBuffer, length) == SUCCESS) {
-			nameBuffer[length] = '\0';
-			if (strcmp(nameBuffer, g_endOfVariables) == 0) {
-				// 2 -> "This was the last entry, done reading."
-				result = 2;
-			}
-			else {
-				if (p_storage->Read(&length, sizeof(length)) == SUCCESS) {
-					char valueBuffer[256];
-					if (p_storage->Read(valueBuffer, length) == SUCCESS) {
-						valueBuffer[length] = '\0';
-						p_to->SetVariable(nameBuffer, valueBuffer);
-						result = SUCCESS;
-					}
-				}
-			}
-		}
+	if (p_storage->Read(&len, sizeof(len)) != SUCCESS) {
+		goto done;
 	}
 
+	char varName[256];
+	assert(len < sizeof(varName));
+
+	if (p_storage->Read(varName, len) != SUCCESS) {
+		goto done;
+	}
+
+	varName[len] = '\0';
+	if (strcmp(varName, g_endOfVariables) == 0) {
+		// 2 -> "This was the last entry, done reading."
+		result = 2;
+		goto done;
+	}
+
+	if (p_storage->Read(&len, sizeof(len)) != SUCCESS) {
+		goto done;
+	}
+
+	char value[256];
+	assert(len < sizeof(value));
+
+	if (p_storage->Read(value, len) != SUCCESS) {
+		goto done;
+	}
+
+	value[len] = '\0';
+	p_to->SetVariable(varName, value);
+	result = SUCCESS;
+
+done:
 	return result;
 }
 
 // FUNCTION: LEGO1 0x1003a170
-void LegoGameState::GetFileSavePath(MxString* p_outPath, MxU8 p_slotn)
+// FUNCTION: BETA10 0x10084b45
+void LegoGameState::GetFileSavePath(MxString* p_outPath, MxS16 p_slotn)
 {
 	char baseForSlot[2] = "0";
 	char path[1024] = "";
@@ -530,22 +577,22 @@ void LegoGameState::GetFileSavePath(MxString* p_outPath, MxU8 p_slotn)
 // FUNCTION: LEGO1 0x1003a2e0
 void LegoGameState::SerializePlayersInfo(MxS16 p_flags)
 {
-	LegoFile fileStorage;
+	LegoFile storage;
 	MxString playersGSI = MxString(m_savePath);
 
 	playersGSI += "\\";
 	playersGSI += g_playersGSI;
 
-	if (fileStorage.Open(playersGSI.GetData(), p_flags) == SUCCESS) {
-		if (fileStorage.IsReadMode()) {
-			fileStorage.Read(m_playerCount);
+	if (storage.Open(playersGSI.GetData(), p_flags) == SUCCESS) {
+		if (storage.IsReadMode()) {
+			storage.ReadS16(m_playerCount);
 		}
-		else if (fileStorage.IsWriteMode()) {
-			fileStorage.Write(m_playerCount);
+		else if (storage.IsWriteMode()) {
+			storage.WriteS16(m_playerCount);
 		}
 
 		for (MxS16 i = 0; i < m_playerCount; i++) {
-			m_players[i].Serialize(&fileStorage);
+			m_players[i].Serialize(&storage);
 		}
 	}
 }
@@ -579,6 +626,7 @@ MxResult LegoGameState::AddPlayer(Username& p_player)
 }
 
 // FUNCTION: LEGO1 0x1003a540
+// FUNCTION: BETA10 0x10084fc4
 void LegoGameState::SwitchPlayer(MxS16 p_playerId)
 {
 	if (p_playerId > 0) {
@@ -1066,6 +1114,7 @@ LegoState* LegoGameState::CreateState(const char* p_stateName)
 }
 
 // FUNCTION: LEGO1 0x1003bc30
+// FUNCTION: BETA10 0x1008636e
 void LegoGameState::RegisterState(LegoState* p_state)
 {
 	MxS32 targetIndex;
@@ -1146,6 +1195,174 @@ void LegoGameState::Init()
 	m_unk0x42c = e_undefined;
 }
 
+// FUNCTION: BETA10 0x10086510
+LegoBackgroundColor::LegoBackgroundColor()
+{
+	m_h = 0.0f;
+	m_s = 0.0f;
+	m_v = 0.0f;
+}
+
+// FUNCTION: LEGO1 0x1003bfb0
+// FUNCTION: BETA10 0x1008659d
+LegoBackgroundColor::LegoBackgroundColor(const char* p_key, const char* p_value)
+{
+	m_key = p_key;
+	m_key.ToUpperCase();
+	SetValue(p_value);
+}
+
+// FUNCTION: LEGO1 0x1003c070
+// FUNCTION: BETA10 0x10086634
+void LegoBackgroundColor::SetValue(const char* p_colorString)
+{
+	m_value = p_colorString;
+	m_value.ToLowerCase();
+
+	LegoVideoManager* videomanager = VideoManager();
+	if (!videomanager || !p_colorString) {
+		return;
+	}
+
+	float convertedR, convertedG, convertedB;
+	char* colorStringCopy = strcpy(new char[strlen(p_colorString) + 1], p_colorString);
+	char* colorStringSplit = strtok(colorStringCopy, g_delimiter);
+
+	if (!strcmp(colorStringSplit, g_set)) {
+		colorStringSplit = strtok(0, g_delimiter);
+		if (colorStringSplit) {
+			m_h = (float) (atoi(colorStringSplit) * 0.01);
+		}
+		colorStringSplit = strtok(0, g_delimiter);
+		if (colorStringSplit) {
+			m_s = (float) (atoi(colorStringSplit) * 0.01);
+		}
+		colorStringSplit = strtok(0, g_delimiter);
+		if (colorStringSplit) {
+			m_v = (float) (atoi(colorStringSplit) * 0.01);
+		}
+
+		ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
+		videomanager->SetSkyColor(convertedR, convertedG, convertedB);
+	}
+	else if (!strcmp(colorStringSplit, g_reset)) {
+		ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
+		videomanager->SetSkyColor(convertedR, convertedG, convertedB);
+	}
+
+	delete[] colorStringCopy;
+}
+
+// FUNCTION: LEGO1 0x1003c230
+// FUNCTION: BETA10 0x100867f9
+void LegoBackgroundColor::ToggleDayNight(MxBool p_sun)
+{
+	char buffer[30];
+
+	if (p_sun) {
+		m_s += 0.1;
+		if (m_s > 0.9) {
+			m_s = 1.0;
+		}
+	}
+	else {
+		m_s -= 0.1;
+		if (m_s < 0.1) {
+			m_s = 0.1;
+		}
+	}
+
+	sprintf(buffer, "set %d %d %d", (MxU32) (m_h * 100.0f), (MxU32) (m_s * 100.0f), (MxU32) (m_v * 100.0f));
+	m_value = buffer;
+
+	float convertedR, convertedG, convertedB;
+	ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
+	VideoManager()->SetSkyColor(convertedR, convertedG, convertedB);
+	SetLightColor(convertedR, convertedG, convertedB);
+}
+
+// FUNCTION: LEGO1 0x1003c330
+// FUNCTION: BETA10 0x100868de
+void LegoBackgroundColor::ToggleSkyColor()
+{
+	char buffer[30];
+
+	m_h += 0.05;
+	if (m_h > 1.0) {
+		m_h -= 1.0;
+	}
+
+	sprintf(buffer, "set %d %d %d", (MxU32) (m_h * 100.0f), (MxU32) (m_s * 100.0f), (MxU32) (m_v * 100.0f));
+	m_value = buffer;
+
+	float convertedR, convertedG, convertedB;
+	ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
+	VideoManager()->SetSkyColor(convertedR, convertedG, convertedB);
+	SetLightColor(convertedR, convertedG, convertedB);
+}
+
+// FUNCTION: LEGO1 0x1003c400
+// FUNCTION: BETA10 0x10086984
+void LegoBackgroundColor::SetLightColor(float p_r, float p_g, float p_b)
+{
+	if (!VideoManager()->GetVideoParam().Flags().GetF2bit0()) {
+		// TODO: Computed constants based on what?
+		p_r *= 1. / 0.23;
+		p_g *= 1. / 0.63;
+		p_b *= 1. / 0.85;
+
+		if (p_r > 1.0) {
+			p_r = 1.0;
+		}
+
+		if (p_g > 1.0) {
+			p_g = 1.0;
+		}
+
+		if (p_b > 1.0) {
+			p_b = 1.0;
+		}
+
+		VideoManager()->Get3DManager()->GetLego3DView()->SetLightColor(FALSE, p_r, p_g, p_b);
+		VideoManager()->Get3DManager()->GetLego3DView()->SetLightColor(TRUE, p_r, p_g, p_b);
+	}
+}
+
+// FUNCTION: LEGO1 0x1003c4b0
+void LegoBackgroundColor::SetLightColor()
+{
+	float convertedR, convertedG, convertedB;
+	ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB);
+	SetLightColor(convertedR, convertedG, convertedB);
+}
+
+// FUNCTION: LEGO1 0x1003c500
+// FUNCTION: BETA10 0x10086af6
+LegoFullScreenMovie::LegoFullScreenMovie(const char* p_key, const char* p_value)
+{
+	m_key = p_key;
+	m_key.ToUpperCase();
+	SetValue(p_value);
+}
+
+// FUNCTION: LEGO1 0x1003c5c0
+// FUNCTION: BETA10 0x10086b8d
+void LegoFullScreenMovie::SetValue(const char* p_option)
+{
+	m_value = p_option;
+	m_value.ToLowerCase();
+
+	LegoVideoManager* videomanager = VideoManager();
+	if (videomanager) {
+		if (!strcmp(m_value.GetData(), g_strEnable)) {
+			videomanager->EnableFullScreenMovie(TRUE);
+		}
+		else if (!strcmp(m_value.GetData(), g_strDisable)) {
+			videomanager->EnableFullScreenMovie(FALSE);
+		}
+	}
+}
+
 // FUNCTION: LEGO1 0x1003c670
 LegoGameState::Username::Username()
 {
@@ -1154,16 +1371,16 @@ LegoGameState::Username::Username()
 
 // FUNCTION: LEGO1 0x1003c690
 // FUNCTION: BETA10 0x10086c57
-MxResult LegoGameState::Username::Serialize(LegoFile* p_file)
+MxResult LegoGameState::Username::Serialize(LegoStorage* p_storage)
 {
-	if (p_file->IsReadMode()) {
+	if (p_storage->IsReadMode()) {
 		for (MxS16 i = 0; i < (MxS16) sizeOfArray(m_letters); i++) {
-			p_file->Read(m_letters[i]);
+			p_storage->ReadS16(m_letters[i]);
 		}
 	}
-	else if (p_file->IsWriteMode()) {
+	else if (p_storage->IsWriteMode()) {
 		for (MxS16 i = 0; i < (MxS16) sizeOfArray(m_letters); i++) {
-			p_file->Write(m_letters[i]);
+			p_storage->WriteS16(m_letters[i]);
 		}
 	}
 
@@ -1180,31 +1397,31 @@ LegoGameState::Username& LegoGameState::Username::operator=(const Username& p_ot
 
 // FUNCTION: LEGO1 0x1003c740
 // FUNCTION: BETA10 0x10086d39
-MxResult LegoGameState::ScoreItem::Serialize(LegoFile* p_file)
+MxResult LegoGameState::ScoreItem::Serialize(LegoStorage* p_storage)
 {
-	if (p_file->IsReadMode()) {
-		p_file->Read(m_totalScore);
+	if (p_storage->IsReadMode()) {
+		p_storage->ReadS16(m_totalScore);
 
 		for (MxS32 i = 0; i < 5; i++) {
 			for (MxS32 j = 0; j < 5; j++) {
-				p_file->Read(m_scores[i][j]);
+				p_storage->ReadU8(m_scores[i][j]);
 			}
 		}
 
-		m_name.Serialize(p_file);
-		p_file->Read(m_unk0x2a);
+		m_name.Serialize(p_storage);
+		p_storage->ReadS16(m_unk0x2a);
 	}
-	else if (p_file->IsWriteMode()) {
-		p_file->Write(m_totalScore);
+	else if (p_storage->IsWriteMode()) {
+		p_storage->WriteS16(m_totalScore);
 
 		for (MxS32 i = 0; i < 5; i++) {
 			for (MxS32 j = 0; j < 5; j++) {
-				p_file->Write(m_scores[i][j]);
+				p_storage->WriteU8(m_scores[i][j]);
 			}
 		}
 
-		m_name.Serialize(p_file);
-		p_file->Write(m_unk0x2a);
+		m_name.Serialize(p_storage);
+		p_storage->WriteS16(m_unk0x2a);
 	}
 
 	return SUCCESS;
@@ -1277,7 +1494,7 @@ void LegoGameState::History::WriteScoreHistory()
 
 		MxU8 tmpScores[5][5];
 		Username tmpPlayer;
-		undefined2 tmpUnk0x2a;
+		MxS16 tmpUnk0x2a;
 
 		// TODO: Match bubble sort loops
 		for (MxS32 i = m_count - 1; i > 0; i--) {
@@ -1304,7 +1521,7 @@ void LegoGameState::History::WriteScoreHistory()
 // FUNCTION: BETA10 0x1008732a
 LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
 	LegoGameState::Username* p_player,
-	MxU16 p_unk0x24,
+	MxS16 p_unk0x24,
 	MxS32& p_unk0x2c
 )
 {
@@ -1326,25 +1543,25 @@ LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
 
 // FUNCTION: LEGO1 0x1003ccf0
 // FUNCTION: BETA10 0x100873e7
-MxResult LegoGameState::History::Serialize(LegoFile* p_file)
+MxResult LegoGameState::History::Serialize(LegoStorage* p_storage)
 {
-	if (p_file->IsReadMode()) {
-		p_file->Read(m_unk0x372);
-		p_file->Read(m_count);
+	if (p_storage->IsReadMode()) {
+		p_storage->ReadS16(m_unk0x372);
+		p_storage->ReadS16(m_count);
 
 		for (MxS16 i = 0; i < m_count; i++) {
 			MxS16 j;
-			p_file->Read(j);
-			m_scores[i].Serialize(p_file);
+			p_storage->ReadS16(j);
+			m_scores[i].Serialize(p_storage);
 		}
 	}
-	else if (p_file->IsWriteMode()) {
-		p_file->Write(m_unk0x372);
-		p_file->Write(m_count);
+	else if (p_storage->IsWriteMode()) {
+		p_storage->WriteS16(m_unk0x372);
+		p_storage->WriteS16(m_count);
 
 		for (MxS16 i = 0; i < m_count; i++) {
-			p_file->Write(i);
-			m_scores[i].Serialize(p_file);
+			p_storage->WriteS16(i);
+			m_scores[i].Serialize(p_storage);
 		}
 	}
 
@@ -1354,7 +1571,7 @@ MxResult LegoGameState::History::Serialize(LegoFile* p_file)
 // FUNCTION: LEGO1 0x1003cdd0
 void LegoGameState::SerializeScoreHistory(MxS16 p_flags)
 {
-	LegoFile stream;
+	LegoFile storage;
 	MxString savePath(m_savePath);
 	savePath += "\\";
 	savePath += g_historyGSI;
@@ -1363,8 +1580,8 @@ void LegoGameState::SerializeScoreHistory(MxS16 p_flags)
 		m_history.WriteScoreHistory();
 	}
 
-	if (stream.Open(savePath.GetData(), p_flags) == SUCCESS) {
-		m_history.Serialize(&stream);
+	if (storage.Open(savePath.GetData(), p_flags) == SUCCESS) {
+		m_history.Serialize(&storage);
 	}
 }
 
diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp
index 06bf7746..68a3b35a 100644
--- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp
+++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp
@@ -72,7 +72,6 @@
 #include "legoentitypresenter.h"
 #include "legoflctexturepresenter.h"
 #include "legohideanimpresenter.h"
-#include "legojetskiraceactor.h"
 #include "legoloadcachesoundpresenter.h"
 #include "legolocomotionanimpresenter.h"
 #include "legoloopinganimpresenter.h"
diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp
index ae9484de..874b72d3 100644
--- a/LEGO1/lego/legoomni/src/common/legoutils.cpp
+++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp
@@ -683,17 +683,17 @@ void SetLightPosition(MxS32 p_index)
 }
 
 // FUNCTION: LEGO1 0x1003f3b0
-LegoNamedTexture* ReadNamedTexture(LegoFile* p_file)
+LegoNamedTexture* ReadNamedTexture(LegoStorage* p_storage)
 {
 	LegoTexture* texture = NULL;
 	LegoNamedTexture* namedTexture = NULL;
 	MxString string;
 
-	p_file->Read(string);
+	p_storage->ReadMxString(string);
 
 	texture = new LegoTexture();
 	if (texture != NULL) {
-		if (texture->Read(p_file, 0) != SUCCESS) {
+		if (texture->Read(p_storage, 0) != SUCCESS) {
 			delete texture;
 			return namedTexture;
 		}
@@ -708,7 +708,7 @@ LegoNamedTexture* ReadNamedTexture(LegoFile* p_file)
 }
 
 // FUNCTION: LEGO1 0x1003f540
-void WriteDefaultTexture(LegoFile* p_file, const char* p_name)
+void WriteDefaultTexture(LegoStorage* p_storage, const char* p_name)
 {
 	MxString name(p_name);
 	LegoTextureInfo* textureInfo = TextureContainer()->Get(p_name);
@@ -766,8 +766,8 @@ void WriteDefaultTexture(LegoFile* p_file, const char* p_name)
 					LegoTexture texture;
 					texture.SetImage(image);
 
-					p_file->Write(MxString(name));
-					texture.Write(p_file);
+					p_storage->WriteMxString(name);
+					texture.Write(p_storage);
 				}
 				else {
 					delete image;
@@ -781,10 +781,10 @@ void WriteDefaultTexture(LegoFile* p_file, const char* p_name)
 }
 
 // FUNCTION: LEGO1 0x1003f8a0
-void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_namedTexture)
+void WriteNamedTexture(LegoStorage* p_storage, LegoNamedTexture* p_namedTexture)
 {
-	p_file->Write(MxString(*p_namedTexture->GetName()));
-	p_namedTexture->GetTexture()->Write(p_file);
+	p_storage->WriteMxString(*p_namedTexture->GetName());
+	p_namedTexture->GetTexture()->Write(p_storage);
 }
 
 // FUNCTION: LEGO1 0x1003f930
diff --git a/LEGO1/lego/legoomni/src/common/legovariables.cpp b/LEGO1/lego/legoomni/src/common/legovariables.cpp
index 8c5563e3..28a54907 100644
--- a/LEGO1/lego/legoomni/src/common/legovariables.cpp
+++ b/LEGO1/lego/legoomni/src/common/legovariables.cpp
@@ -1,11 +1,8 @@
 #include "legovariables.h"
 
 #include "3dmanager/lego3dmanager.h"
-#include "legobuildingmanager.h"
-#include "legocharactermanager.h"
 #include "legogamestate.h"
 #include "legonavcontroller.h"
-#include "legoplantmanager.h"
 #include "legovideomanager.h"
 #include "misc.h"
 #include "roi/legoroi.h"
@@ -16,7 +13,6 @@ DECOMP_SIZE_ASSERT(VisibilityVariable, 0x24)
 DECOMP_SIZE_ASSERT(CameraLocationVariable, 0x24)
 DECOMP_SIZE_ASSERT(CursorVariable, 0x24)
 DECOMP_SIZE_ASSERT(WhoAmIVariable, 0x24)
-DECOMP_SIZE_ASSERT(CustomizeAnimFileVariable, 0x24)
 
 // GLOBAL: LEGO1 0x100f7ab0
 // STRING: LEGO1 0x100f09c0
@@ -178,21 +174,3 @@ void WhoAmIVariable::SetValue(const char* p_value)
 		GameState()->SetActorId(5);
 	}
 }
-
-// FUNCTION: LEGO1 0x10085aa0
-CustomizeAnimFileVariable::CustomizeAnimFileVariable(const char* p_key)
-{
-	m_key = p_key;
-	m_key.ToUpperCase();
-}
-
-// FUNCTION: LEGO1 0x10085b50
-void CustomizeAnimFileVariable::SetValue(const char* p_value)
-{
-	// STRING: LEGO1 0x100fc4f4
-	if (strcmp(m_key.GetData(), "CUSTOMIZE_ANIM_FILE") == 0) {
-		CharacterManager()->SetCustomizeAnimFile(p_value);
-		PlantManager()->SetCustomizeAnimFile(p_value);
-		BuildingManager()->SetCustomizeAnimFile(p_value);
-	}
-}
diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
index 57580a67..67c9608f 100644
--- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp
@@ -16,30 +16,12 @@ DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c)
 // FUNCTION: LEGO1 0x10043f50
 MxControlPresenter::MxControlPresenter()
 {
-	this->m_unk0x4c = 0;
-	this->m_unk0x4e = -1;
-	this->m_unk0x50 = FALSE;
-	this->m_unk0x52 = 0;
-	this->m_unk0x58 = 0;
-	this->m_unk0x54 = 0;
-}
-
-// FUNCTION: LEGO1 0x10043fd0
-void MxControlPresenter::RepeatingTickle()
-{
-	// empty
-}
-
-// FUNCTION: LEGO1 0x10043fe0
-MxBool MxControlPresenter::VTable0x64(undefined4 p_undefined)
-{
-	return m_unk0x50;
-}
-
-// FUNCTION: LEGO1 0x10043ff0
-void MxControlPresenter::VTable0x68(MxBool p_unk0x50)
-{
-	m_unk0x50 = p_unk0x50;
+	m_unk0x4c = 0;
+	m_unk0x4e = -1;
+	m_unk0x50 = FALSE;
+	m_unk0x52 = 0;
+	m_unk0x58 = 0;
+	m_unk0x54 = 0;
 }
 
 // FUNCTION: LEGO1 0x10044110
@@ -91,6 +73,7 @@ void MxControlPresenter::EndAction()
 }
 
 // FUNCTION: LEGO1 0x10044270
+// FUNCTION: BETA10 0x100eae68
 MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter)
 {
 	if (m_unk0x4c == 3) {
diff --git a/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp b/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp
deleted file mode 100644
index cda15379..00000000
--- a/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-#include "legojetskiraceactor.h"
-
-#include "legonavcontroller.h"
-#include "legopathcontroller.h"
-#include "misc.h"
-#include "mxmisc.h"
-#include "mxvariabletable.h"
-
-#include <SDL3/SDL_stdinc.h>
-#include <vec.h>
-
-DECOMP_SIZE_ASSERT(LegoJetskiRaceActor, 0x1a8)
-
-// GLOBAL: LEGO1 0x100da044
-// GLOBAL: BETA10 0x101be9fc
-MxFloat g_unk0x100da044 = 8.0f;
-
-// FUNCTION: LEGO1 0x10080ef0
-// FUNCTION: BETA10 0x100a8990
-LegoJetskiRaceActor::LegoJetskiRaceActor()
-{
-	m_unk0x10 = 0.95f;
-	m_unk0x14 = 0.04f;
-	m_unk0x18 = 0.5f;
-	m_unk0x150 = 1.5f;
-}
-
-// FUNCTION: LEGO1 0x10081120
-// FUNCTION: BETA10 0x100ce19f
-MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge)
-{
-	// These are almost certainly not the correct names, but they produce the correct BETA10 stack
-	Mx3DPointFloat a;
-	Mx3DPointFloat bbb;
-	Mx3DPointFloat c;
-
-	// These names are verified by an assertion below
-	Vector3* v1 = NULL;
-	Vector3* v2 = NULL;
-
-	if (m_actorState == c_one) {
-		if (m_destEdge == LegoPathController::GetControlEdgeA(13)) {
-			m_boundary = (LegoPathBoundary*) m_destEdge->OtherFace(LegoPathController::GetControlBoundaryA(13));
-		}
-		else if (m_destEdge == LegoPathController::GetControlEdgeA(15)) {
-			m_boundary = (LegoPathBoundary*) m_destEdge->OtherFace(LegoPathController::GetControlBoundaryA(15));
-		}
-
-		m_actorState = c_initial;
-		m_unk0x7c = 0;
-
-		if (m_userNavFlag) {
-			NavController()->SetLinearVel(m_worldSpeed);
-			return 0;
-		}
-		else {
-			return 1;
-		}
-	}
-	else {
-		if (p_edge == LegoPathController::GetControlEdgeA(12)) {
-			m_actorState = c_one;
-
-			if (m_worldSpeed < g_unk0x100da044) {
-				m_worldSpeed = g_unk0x100da044;
-			}
-
-			m_destEdge = LegoPathController::GetControlEdgeA(13);
-			m_boundary = LegoPathController::GetControlBoundaryA(13);
-		}
-		else if (p_edge == LegoPathController::GetControlEdgeA(14)) {
-			m_actorState = c_one;
-
-			if (m_worldSpeed < g_unk0x100da044) {
-				m_worldSpeed = g_unk0x100da044;
-			}
-
-			m_destEdge = LegoPathController::GetControlEdgeA(15);
-			m_boundary = LegoPathController::GetControlBoundaryA(15);
-		}
-
-		if (m_actorState == c_one) {
-			if (m_userNavFlag) {
-				m_unk0xe4 = 0.5f;
-			}
-
-			v1 = m_destEdge->CCWVertex(*m_boundary);
-			v2 = m_destEdge->CWVertex(*m_boundary);
-			assert(v1 && v2);
-
-			LERP3(a, *v1, *v2, m_unk0xe4);
-
-			m_destEdge->FUN_1002ddc0(*m_boundary, bbb);
-			c.EqualsCross(bbb, *m_boundary->GetUnknown0x14());
-			c.Unitize();
-
-			Mx3DPointFloat worldDirection(m_roi->GetWorldDirection());
-
-			if (!m_userNavFlag) {
-				worldDirection *= -1.0f;
-			}
-
-			if (VTable0x80(m_roi->GetWorldPosition(), worldDirection, a, c)) {
-#ifndef BETA10
-				m_unk0x7c = 0;
-				return 0;
-#else
-				assert(0);
-				return -1;
-#endif
-			}
-
-			m_unk0x7c = 0;
-			return 0;
-		}
-		else {
-			return 1;
-		}
-	}
-}
-
-// FUNCTION: LEGO1 0x10081550
-void LegoJetskiRaceActor::Animate(float p_time)
-{
-	if (m_unk0x0c == 0) {
-		const LegoChar* raceState = VariableTable()->GetVariable(g_raceState);
-		if (!SDL_strcasecmp(raceState, g_racing)) {
-			m_unk0x0c = 1;
-			m_lastTime = p_time - 1.0f;
-			m_unk0x1c = p_time;
-		}
-		else if (!m_userNavFlag) {
-			LegoAnimActor::Animate(m_lastTime + 1.0f);
-		}
-	}
-
-	if (m_unk0x0c == 1) {
-		LegoAnimActor::Animate(p_time);
-	}
-}
-
-// FUNCTION: LEGO1 0x10081fd0
-MxU32 LegoJetskiRaceActor::VTable0x6c(
-	LegoPathBoundary* p_boundary,
-	Vector3& p_v1,
-	Vector3& p_v2,
-	float p_f1,
-	float p_f2,
-	Vector3& p_v3
-)
-{
-	LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
-
-	for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
-		if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
-			return 1;
-		}
-	}
-
-	LegoPathActorSet& plpas = p_boundary->GetActors();
-	LegoPathActorSet lpas(plpas);
-
-	for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) {
-		if (plpas.find(*itpa) != plpas.end()) {
-			LegoPathActor* actor = *itpa;
-
-			if (this != actor) {
-				LegoROI* roi = actor->GetROI();
-
-				if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) {
-					if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
-						HitActor(actor, TRUE);
-
-						if (actor->HitActor(this, FALSE) < 0) {
-							return 0;
-						}
-						else {
-							return 2;
-						}
-					}
-				}
-			}
-		}
-	}
-
-	return 0;
-}
diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp
index d974c439..9c6e3b23 100644
--- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp
+++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp
@@ -324,6 +324,7 @@ float LegoNavController::CalculateNewVel(float p_targetVel, float p_currentVel,
 }
 
 // FUNCTION: LEGO1 0x10055080
+// FUNCTION: BETA10 0x1009b26b
 MxBool LegoNavController::CalculateNewPosDir(
 	const Vector3& p_curPos,
 	const Vector3& p_curDir,
diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp
index cdbd8485..7266293d 100644
--- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp
+++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp
@@ -50,13 +50,6 @@ LegoInputManager::LegoInputManager()
 	m_autoDragTime = 1000;
 }
 
-// FUNCTION: LEGO1 0x1005b8b0
-MxResult LegoInputManager::Tickle()
-{
-	ProcessEvents();
-	return SUCCESS;
-}
-
 // FUNCTION: LEGO1 0x1005b8f0
 LegoInputManager::~LegoInputManager()
 {
diff --git a/LEGO1/lego/legoomni/src/main/legomain.cpp b/LEGO1/lego/legoomni/src/main/legomain.cpp
index 0c4bd702..c21675bc 100644
--- a/LEGO1/lego/legoomni/src/main/legomain.cpp
+++ b/LEGO1/lego/legoomni/src/main/legomain.cpp
@@ -21,7 +21,6 @@
 #include "mxautolock.h"
 #include "mxbackgroundaudiomanager.h"
 #include "mxdisplaysurface.h"
-#include "mxdsfile.h"
 #include "mxmisc.h"
 #include "mxnotificationmanager.h"
 #include "mxomnicreateflags.h"
diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp
index 2c2bd166..3cbbf032 100644
--- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp
+++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp
@@ -420,3 +420,105 @@ MxS32 LegoExtraActor::VTable0x68(Vector3& p_point1, Vector3& p_point2, Vector3&
 {
 	return LegoPathActor::VTable0x68(p_point1, p_point2, p_point3);
 }
+
+// FUNCTION: LEGO1 0x1002b980
+inline MxU32 LegoExtraActor::VTable0x6c(
+	LegoPathBoundary* p_boundary,
+	Vector3& p_v1,
+	Vector3& p_v2,
+	float p_f1,
+	float p_f2,
+	Vector3& p_v3
+)
+{
+	LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
+
+	for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
+		if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
+			return 1;
+		}
+	}
+
+	LegoPathActorSet& plpas = p_boundary->GetActors();
+	LegoPathActorSet lpas(plpas);
+
+	for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) {
+		if (plpas.find(*itpa) != plpas.end()) {
+			LegoPathActor* actor = *itpa;
+
+			if (this != actor && !(actor->GetActorState() & LegoPathActor::c_noCollide)) {
+				LegoROI* roi = actor->GetROI();
+
+				if ((roi != NULL && roi->GetVisibility()) || actor->GetCameraFlag()) {
+					if (actor->GetUserNavFlag()) {
+						MxMatrix local2world = roi->GetLocal2World();
+						Vector3 local60(local2world[3]);
+						Mx3DPointFloat local54(p_v1);
+
+						local54 -= local60;
+						float local1c = p_v2.Dot(p_v2, p_v2);
+						float local24 = p_v2.Dot(p_v2, local54) * 2.0f;
+						float local20 = local54.Dot(local54, local54);
+
+						if (m_unk0x15 != 0 && local20 < 10.0f) {
+							return 0;
+						}
+
+						local20 -= 1.0f;
+
+						if (local1c >= 0.001 || local1c <= -0.001) {
+							float local40 = (local24 * local24) + (local20 * local1c * -4.0f);
+
+							if (local40 >= -0.001) {
+								local1c *= 2.0f;
+								local24 = -local24;
+
+								if (local40 < 0.0f) {
+									local40 = 0.0f;
+								}
+
+								local40 = sqrt(local40);
+								float local20X = (local24 + local40) / local1c;
+								float local1cX = (local24 - local40) / local1c;
+
+								if (local1cX < local20X) {
+									local40 = local20X;
+									local20X = local1cX;
+									local1cX = local40;
+								}
+
+								if ((local20X >= 0.0f && local20X <= p_f1) || (local1cX >= 0.0f && local1cX <= p_f1) ||
+									(local20X <= -0.01 && p_f1 + 0.01 <= local1cX)) {
+									p_v3 = p_v1;
+
+									if (HitActor(actor, TRUE) < 0) {
+										return 0;
+									}
+
+									actor->HitActor(this, FALSE);
+									return 2;
+								}
+							}
+						}
+					}
+					else {
+						if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
+							if (HitActor(actor, TRUE) < 0) {
+								return 0;
+							}
+
+							actor->HitActor(this, FALSE);
+							return 2;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if (m_unk0x15 != 0) {
+		m_unk0x15--;
+	}
+
+	return 0;
+}
diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp
index f42ea5e7..c00963c0 100644
--- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp
+++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp
@@ -1,7 +1,6 @@
 #include "legopathcontroller.h"
 
 #include "legopathedgecontainer.h"
-#include "legopathstruct.h"
 #include "misc/legostorage.h"
 #include "mxmisc.h"
 #include "mxticklemanager.h"
@@ -216,12 +215,21 @@ MxResult LegoPathController::PlaceActor(
 	}
 
 	LegoPathBoundary* pBoundary = GetPathBoundary(p_name);
+
+	assert(pBoundary);
+	assert(p_src < pBoundary->GetNumEdges() && p_dest < pBoundary->GetNumEdges());
+
 	LegoEdge* pSrcE = pBoundary->GetEdges()[p_src];
 	LegoEdge* pDestE = pBoundary->GetEdges()[p_dest];
-	float time = Timer()->GetTime();
 
-	if (p_actor->VTable0x88(pBoundary, time, *pSrcE, p_srcScale, (LegoUnknown100db7f4&) *pDestE, p_destScale) !=
-		SUCCESS) {
+	assert(pSrcE && pDestE);
+
+	float time = Timer()->GetTime();
+	MxResult result =
+		p_actor->VTable0x88(pBoundary, time, *pSrcE, p_srcScale, (LegoUnknown100db7f4&) *pDestE, p_destScale);
+
+	if (result != SUCCESS) {
+		assert(0);
 		return FAILURE;
 	}
 
@@ -681,7 +689,7 @@ MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage)
 
 		if (boundary.m_numTriggers > 0) {
 			boundary.m_unk0x50 = new Mx3DPointFloat;
-			boundary.m_pathTrigger = new LegoWEGEdge::PathWithTrigger[boundary.m_numTriggers];
+			boundary.m_pathTrigger = new PathWithTrigger[boundary.m_numTriggers];
 
 			for (j = 0; j < boundary.m_numTriggers; j++) {
 				if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp
index 58a330b3..ff6aacce 100644
--- a/LEGO1/lego/legoomni/src/race/carrace.cpp
+++ b/LEGO1/lego/legoomni/src/race/carrace.cpp
@@ -5,7 +5,6 @@
 #include "isle.h"
 #include "jukebox_actions.h"
 #include "legoanimationmanager.h"
-#include "legobackgroundcolor.h"
 #include "legocontrolmanager.h"
 #include "legohideanimpresenter.h"
 #include "legomain.h"
diff --git a/LEGO1/lego/legoomni/src/race/legorace.cpp b/LEGO1/lego/legoomni/src/race/legorace.cpp
index de895ad5..a2c0555d 100644
--- a/LEGO1/lego/legoomni/src/race/legorace.cpp
+++ b/LEGO1/lego/legoomni/src/race/legorace.cpp
@@ -135,12 +135,12 @@ RaceState::RaceState()
 
 // FUNCTION: LEGO1 0x10016140
 // FUNCTION: BETA10 0x100c7d9f
-MxResult RaceState::Serialize(LegoFile* p_file)
+MxResult RaceState::Serialize(LegoStorage* p_storage)
 {
-	LegoState::Serialize(p_file);
+	LegoState::Serialize(p_storage);
 
 	for (MxS16 i = 0; i < 5; i++) {
-		m_state[i].Serialize(p_file);
+		m_state[i].Serialize(p_storage);
 	}
 
 	return SUCCESS;
diff --git a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp
index c6294048..f9fe2eb7 100644
--- a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp
+++ b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp
@@ -14,6 +14,7 @@
 // File name verified by BETA10 0x100cedf7
 
 DECOMP_SIZE_ASSERT(LegoCarRaceActor, 0x1a0)
+DECOMP_SIZE_ASSERT(LegoJetskiRaceActor, 0x1a8)
 
 // GLOBAL: LEGO1 0x100f0c68
 // STRING: LEGO1 0x100f0c5c
@@ -34,6 +35,10 @@ const char* g_racing = "RACING";
 // GLOBAL: LEGO1 0x100f7aec
 MxFloat LegoCarRaceActor::g_unk0x100f7aec = 8.0f;
 
+// GLOBAL: LEGO1 0x100da044
+// GLOBAL: BETA10 0x101be9fc
+MxFloat g_unk0x100da044 = 8.0f;
+
 // FUNCTION: LEGO1 0x10080350
 // FUNCTION: BETA10 0x100cd6b0
 LegoCarRaceActor::LegoCarRaceActor()
@@ -285,9 +290,133 @@ MxResult LegoCarRaceActor::VTable0x9c()
 	return SUCCESS;
 }
 
+// FUNCTION: LEGO1 0x10080ef0
+// FUNCTION: BETA10 0x100a8990
+LegoJetskiRaceActor::LegoJetskiRaceActor()
+{
+	m_unk0x10 = 0.95f;
+	m_unk0x14 = 0.04f;
+	m_unk0x18 = 0.5f;
+	m_unk0x150 = 1.5f;
+}
+
+// FUNCTION: LEGO1 0x10081120
+// FUNCTION: BETA10 0x100ce19f
+MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge)
+{
+	// These are almost certainly not the correct names, but they produce the correct BETA10 stack
+	Mx3DPointFloat a;
+	Mx3DPointFloat bbb;
+	Mx3DPointFloat c;
+
+	// These names are verified by an assertion below
+	Vector3* v1 = NULL;
+	Vector3* v2 = NULL;
+
+	if (m_actorState == c_one) {
+		if (m_destEdge == LegoPathController::GetControlEdgeA(13)) {
+			m_boundary = (LegoPathBoundary*) m_destEdge->OtherFace(LegoPathController::GetControlBoundaryA(13));
+		}
+		else if (m_destEdge == LegoPathController::GetControlEdgeA(15)) {
+			m_boundary = (LegoPathBoundary*) m_destEdge->OtherFace(LegoPathController::GetControlBoundaryA(15));
+		}
+
+		m_actorState = c_initial;
+		m_unk0x7c = 0;
+
+		if (m_userNavFlag) {
+			NavController()->SetLinearVel(m_worldSpeed);
+			return 0;
+		}
+		else {
+			return 1;
+		}
+	}
+	else {
+		if (p_edge == LegoPathController::GetControlEdgeA(12)) {
+			m_actorState = c_one;
+
+			if (m_worldSpeed < g_unk0x100da044) {
+				m_worldSpeed = g_unk0x100da044;
+			}
+
+			m_destEdge = LegoPathController::GetControlEdgeA(13);
+			m_boundary = LegoPathController::GetControlBoundaryA(13);
+		}
+		else if (p_edge == LegoPathController::GetControlEdgeA(14)) {
+			m_actorState = c_one;
+
+			if (m_worldSpeed < g_unk0x100da044) {
+				m_worldSpeed = g_unk0x100da044;
+			}
+
+			m_destEdge = LegoPathController::GetControlEdgeA(15);
+			m_boundary = LegoPathController::GetControlBoundaryA(15);
+		}
+
+		if (m_actorState == c_one) {
+			if (m_userNavFlag) {
+				m_unk0xe4 = 0.5f;
+			}
+
+			v1 = m_destEdge->CCWVertex(*m_boundary);
+			v2 = m_destEdge->CWVertex(*m_boundary);
+			assert(v1 && v2);
+
+			LERP3(a, *v1, *v2, m_unk0xe4);
+
+			m_destEdge->FUN_1002ddc0(*m_boundary, bbb);
+			c.EqualsCross(bbb, *m_boundary->GetUnknown0x14());
+			c.Unitize();
+
+			Mx3DPointFloat worldDirection(m_roi->GetWorldDirection());
+
+			if (!m_userNavFlag) {
+				worldDirection *= -1.0f;
+			}
+
+			if (VTable0x80(m_roi->GetWorldPosition(), worldDirection, a, c)) {
+#ifndef BETA10
+				m_unk0x7c = 0;
+				return 0;
+#else
+				assert(0);
+				return -1;
+#endif
+			}
+
+			m_unk0x7c = 0;
+			return 0;
+		}
+		else {
+			return 1;
+		}
+	}
+}
+
+// FUNCTION: LEGO1 0x10081550
+void LegoJetskiRaceActor::Animate(float p_time)
+{
+	if (m_unk0x0c == 0) {
+		const LegoChar* raceState = VariableTable()->GetVariable(g_raceState);
+		if (!SDL_strcasecmp(raceState, g_racing)) {
+			m_unk0x0c = 1;
+			m_lastTime = p_time - 1.0f;
+			m_unk0x1c = p_time;
+		}
+		else if (!m_userNavFlag) {
+			LegoAnimActor::Animate(m_lastTime + 1.0f);
+		}
+	}
+
+	if (m_unk0x0c == 1) {
+		LegoAnimActor::Animate(p_time);
+	}
+}
+
 // FUNCTION: LEGO1 0x10081840
 // FUNCTION: BETA10 0x100cf680
-MxU32 LegoCarRaceActor::VTable0x6c(
+inline MxU32 LegoCarRaceActor::VTable0x6c(
 	LegoPathBoundary* p_boundary,
 	Vector3& p_v1,
 	Vector3& p_v2,
@@ -384,3 +513,50 @@ MxU32 LegoCarRaceActor::VTable0x6c(
 
 	return 0;
 }
+
+// FUNCTION: LEGO1 0x10081fd0
+inline MxU32 LegoJetskiRaceActor::VTable0x6c(
+	LegoPathBoundary* p_boundary,
+	Vector3& p_v1,
+	Vector3& p_v2,
+	float p_f1,
+	float p_f2,
+	Vector3& p_v3
+)
+{
+	LegoAnimPresenterSet& presenters = p_boundary->GetPresenters();
+
+	for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) {
+		if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) {
+			return 1;
+		}
+	}
+
+	LegoPathActorSet& plpas = p_boundary->GetActors();
+	LegoPathActorSet lpas(plpas);
+
+	for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) {
+		if (plpas.find(*itpa) != plpas.end()) {
+			LegoPathActor* actor = *itpa;
+
+			if (this != actor) {
+				LegoROI* roi = actor->GetROI();
+
+				if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) {
+					if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) {
+						HitActor(actor, TRUE);
+
+						if (actor->HitActor(this, FALSE) < 0) {
+							return 0;
+						}
+						else {
+							return 2;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/LEGO1/lego/legoomni/src/race/raceskel.cpp b/LEGO1/lego/legoomni/src/race/raceskel.cpp
index 213e788d..899efe28 100644
--- a/LEGO1/lego/legoomni/src/race/raceskel.cpp
+++ b/LEGO1/lego/legoomni/src/race/raceskel.cpp
@@ -50,6 +50,15 @@ void RaceSkel::ParseAction(char* p_extra)
 	m_roi->SetBoundingSphere(sphere);
 }
 
+// FUNCTION: LEGO1 0x10071c80
+// FUNCTION: BETA10 0x100f1531
+void RaceSkel::FUN_10071c80(Vector3& p_vec)
+{
+	p_vec[0] = -630.0f;
+	p_vec[1] = -4.688f;
+	p_vec[2] = 323.0f;
+}
+
 // FUNCTION: LEGO1 0x10071cb0
 // FUNCTION: BETA10 0x100f158b
 void RaceSkel::GetCurrentAnimData(float* p_outCurAnimPosition, float* p_outCurAnimDuration)
diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp
index 67d49941..0aef42bd 100644
--- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp
@@ -14,16 +14,6 @@ LegoHideAnimPresenter::LegoHideAnimPresenter()
 	Init();
 }
 
-// FUNCTION: LEGO1 0x1006d860
-void LegoHideAnimPresenter::VTable0x8c()
-{
-}
-
-// FUNCTION: LEGO1 0x1006d870
-void LegoHideAnimPresenter::VTable0x90()
-{
-}
-
 // FUNCTION: LEGO1 0x1006d9f0
 LegoHideAnimPresenter::~LegoHideAnimPresenter()
 {
diff --git a/LEGO1/lego/legoomni/src/worlds/act3.cpp b/LEGO1/lego/legoomni/src/worlds/act3.cpp
index 6a74b64f..e8134807 100644
--- a/LEGO1/lego/legoomni/src/worlds/act3.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/act3.cpp
@@ -242,12 +242,6 @@ Act3::Act3()
 	NotificationManager()->Register(this);
 }
 
-// FUNCTION: LEGO1 0x10072500
-MxBool Act3::VTable0x5c()
-{
-	return TRUE;
-}
-
 // FUNCTION: LEGO1 0x100726a0
 // FUNCTION: BETA10 0x100155da
 Act3::~Act3()
diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp
index 56cc4b55..ab0ecf7f 100644
--- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp
@@ -510,23 +510,23 @@ GasStationState::GasStationState()
 
 // FUNCTION: LEGO1 0x10006300
 // FUNCTION: BETA10 0x10029754
-MxResult GasStationState::Serialize(LegoFile* p_file)
+MxResult GasStationState::Serialize(LegoStorage* p_storage)
 {
-	LegoState::Serialize(p_file);
+	LegoState::Serialize(p_storage);
 
-	if (p_file->IsWriteMode()) {
-		p_file->Write(m_pepperAction);
-		p_file->Write(m_mamaAction);
-		p_file->Write(m_papaAction);
-		p_file->Write(m_nickAction);
-		p_file->Write(m_lauraAction);
+	if (p_storage->IsWriteMode()) {
+		p_storage->WriteS16(m_pepperAction);
+		p_storage->WriteS16(m_mamaAction);
+		p_storage->WriteS16(m_papaAction);
+		p_storage->WriteS16(m_nickAction);
+		p_storage->WriteS16(m_lauraAction);
 	}
-	else if (p_file->IsReadMode()) {
-		p_file->Read(m_pepperAction);
-		p_file->Read(m_mamaAction);
-		p_file->Read(m_papaAction);
-		p_file->Read(m_nickAction);
-		p_file->Read(m_lauraAction);
+	else if (p_storage->IsReadMode()) {
+		p_storage->ReadS16(m_pepperAction);
+		p_storage->ReadS16(m_mamaAction);
+		p_storage->ReadS16(m_papaAction);
+		p_storage->ReadS16(m_nickAction);
+		p_storage->ReadS16(m_lauraAction);
 	}
 
 	return SUCCESS;
diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp
index 3cb82fa0..f6122378 100644
--- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp
@@ -52,12 +52,6 @@ Hospital::Hospital()
 	NotificationManager()->Register(this);
 }
 
-// FUNCTION: LEGO1 0x100746a0
-MxBool Hospital::VTable0x5c()
-{
-	return TRUE;
-}
-
 // FUNCTION: LEGO1 0x100747f0
 Hospital::~Hospital()
 {
@@ -69,7 +63,7 @@ Hospital::~Hospital()
 	ControlManager()->Unregister(this);
 	TickleManager()->UnregisterClient(this);
 
-	m_hospitalState->m_unk0x08.m_unk0x00 = 3;
+	m_hospitalState->m_unk0x08 = 3;
 
 	NotificationManager()->Unregister(this);
 	g_unk0x100f7918 = 3;
@@ -89,13 +83,13 @@ MxResult Hospital::Create(MxDSAction& p_dsAction)
 	m_hospitalState = (HospitalState*) GameState()->GetState("HospitalState");
 	if (!m_hospitalState) {
 		m_hospitalState = (HospitalState*) GameState()->CreateState("HospitalState");
-		m_hospitalState->m_unk0x08.m_unk0x00 = 1;
+		m_hospitalState->m_unk0x08 = 1;
 	}
-	else if (m_hospitalState->m_unk0x08.m_unk0x00 == 4) {
-		m_hospitalState->m_unk0x08.m_unk0x00 = 4;
+	else if (m_hospitalState->m_unk0x08 == 4) {
+		m_hospitalState->m_unk0x08 = 4;
 	}
 	else {
-		m_hospitalState->m_unk0x08.m_unk0x00 = 3;
+		m_hospitalState->m_unk0x08 = 3;
 	}
 
 	GameState()->m_currentArea = LegoGameState::e_hospital;
@@ -205,7 +199,7 @@ void Hospital::ReadyWorld()
 			HospitalScript::c_hho007p1_RunAnim
 		};
 
-		m_hospitalState->m_unk0x08.m_unk0x00 = 5;
+		m_hospitalState->m_unk0x08 = 5;
 
 		PlayAction(hospitalScript[m_hospitalState->m_unk0x0c]);
 		m_currentAction = hospitalScript[m_hospitalState->m_unk0x0c];
@@ -214,7 +208,7 @@ void Hospital::ReadyWorld()
 		m_unk0x100 = 1;
 		m_time = Timer()->GetTime();
 
-		m_hospitalState->m_unk0x08.m_unk0x00 = 6;
+		m_hospitalState->m_unk0x08 = 6;
 
 		PlayAction(HospitalScript::c_hho003cl_RunAnim);
 		m_currentAction = HospitalScript::c_hho003cl_RunAnim;
@@ -251,9 +245,9 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 
 	m_unk0x108 = 0;
 
-	switch (m_hospitalState->m_unk0x08.m_unk0x00) {
+	switch (m_hospitalState->m_unk0x08) {
 	case 5:
-		m_hospitalState->m_unk0x08.m_unk0x00 = 7;
+		m_hospitalState->m_unk0x08 = 7;
 		PlayAction(HospitalScript::c_hho006cl_RunAnim);
 
 		m_currentAction = HospitalScript::c_hho006cl_RunAnim;
@@ -267,7 +261,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 		break;
 	case 7:
 	case 10:
-		m_hospitalState->m_unk0x08.m_unk0x00 = 8;
+		m_hospitalState->m_unk0x08 = 8;
 		m_unk0x100 = 1;
 		m_time = Timer()->GetTime();
 		break;
@@ -277,14 +271,14 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 			switch (m_hospitalState->m_unk0x0e) {
 			case 0:
 			case 1:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho017cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho017cl_RunAnim;
 				m_unk0x108 = 1;
 				break;
 			default:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho018cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho018cl_RunAnim;
@@ -296,14 +290,14 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 			switch (m_hospitalState->m_unk0x10) {
 			case 0:
 			case 1:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho019cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho019cl_RunAnim;
 				m_unk0x108 = 1;
 				break;
 			default:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho020cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho020cl_RunAnim;
@@ -315,14 +309,14 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 			switch (m_hospitalState->m_unk0x12) {
 			case 0:
 			case 1:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho023cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho023cl_RunAnim;
 				m_unk0x108 = 1;
 				break;
 			default:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho024cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho024cl_RunAnim;
@@ -334,14 +328,14 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 			switch (m_hospitalState->m_unk0x14) {
 			case 0:
 			case 1:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho021cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho021cl_RunAnim;
 				m_unk0x108 = 1;
 				break;
 			default:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hhoa22cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hhoa22cl_RunAnim;
@@ -353,14 +347,14 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 			switch (m_hospitalState->m_unk0x16) {
 			case 0:
 			case 1:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho025cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho025cl_RunAnim;
 				m_unk0x108 = 1;
 				break;
 			default:
-				m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+				m_hospitalState->m_unk0x08 = 12;
 				PlayAction(HospitalScript::c_hho026cl_RunAnim);
 
 				m_currentAction = HospitalScript::c_hho026cl_RunAnim;
@@ -371,7 +365,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
 		}
 		break;
 	case 12:
-		m_hospitalState->m_unk0x08.m_unk0x00 = 9;
+		m_hospitalState->m_unk0x08 = 9;
 		act1State = (Act1State*) GameState()->GetState("Act1State");
 		act1State->SetUnknown18(9);
 	case 14:
@@ -418,13 +412,13 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
 
 				m_unk0x100 = 3;
 
-				if (m_hospitalState->m_unk0x08.m_unk0x00 == 6) {
+				if (m_hospitalState->m_unk0x08 == 6) {
 					if (m_unk0x128 == 0) {
 						m_unk0x128 = 1;
 
 						TickleManager()->UnregisterClient(this);
 
-						m_hospitalState->m_unk0x08.m_unk0x00 = 9;
+						m_hospitalState->m_unk0x08 = 9;
 						Act1State* act1State = (Act1State*) GameState()->GetState("Act1State");
 						act1State->SetUnknown18(9);
 
@@ -437,9 +431,9 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
 						TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
 					}
 				}
-				else if (m_hospitalState->m_unk0x08.m_unk0x00 == 10 || m_hospitalState->m_unk0x08.m_unk0x00 == 8) {
-					if (m_hospitalState->m_unk0x08.m_unk0x00 == 10) {
-						m_hospitalState->m_unk0x08.m_unk0x00 = 11;
+				else if (m_hospitalState->m_unk0x08 == 10 || m_hospitalState->m_unk0x08 == 8) {
+					if (m_hospitalState->m_unk0x08 == 10) {
+						m_hospitalState->m_unk0x08 = 11;
 
 						BackgroundAudioManager()->RaiseVolume();
 						DeleteObjects(
@@ -454,14 +448,14 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
 							switch (m_hospitalState->m_unk0x0e) {
 							case 0:
 							case 1:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho017cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho017cl_RunAnim;
 								m_unk0x108 = 1;
 								break;
 							default:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho018cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho018cl_RunAnim;
@@ -473,14 +467,14 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
 							switch (m_hospitalState->m_unk0x10) {
 							case 0:
 							case 1:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho019cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho019cl_RunAnim;
 								m_unk0x108 = 1;
 								break;
 							default:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho020cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho020cl_RunAnim;
@@ -492,14 +486,14 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
 							switch (m_hospitalState->m_unk0x12) {
 							case 0:
 							case 1:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho023cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho023cl_RunAnim;
 								m_unk0x108 = 1;
 								break;
 							default:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho024cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho024cl_RunAnim;
@@ -511,14 +505,14 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
 							switch (m_hospitalState->m_unk0x14) {
 							case 0:
 							case 1:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho021cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho021cl_RunAnim;
 								m_unk0x108 = 1;
 								break;
 							default:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hhoa22cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hhoa22cl_RunAnim;
@@ -530,14 +524,14 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
 							switch (m_hospitalState->m_unk0x16) {
 							case 0:
 							case 1:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho025cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho025cl_RunAnim;
 								m_unk0x108 = 1;
 								break;
 							default:
-								m_hospitalState->m_unk0x08.m_unk0x00 = 12;
+								m_hospitalState->m_unk0x08 = 12;
 								PlayAction(HospitalScript::c_hho026cl_RunAnim);
 
 								m_currentAction = HospitalScript::c_hho026cl_RunAnim;
@@ -573,7 +567,7 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
 			DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
 
 			if (m_unk0x100 == 1) {
-				m_hospitalState->m_unk0x08.m_unk0x00 = 14;
+				m_hospitalState->m_unk0x08 = 14;
 
 				PlayAction(HospitalScript::c_hho016cl_RunAnim);
 				m_currentAction = HospitalScript::c_hho016cl_RunAnim;
@@ -581,7 +575,7 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
 			}
 			else if (m_unk0x128 == 0) {
 				m_unk0x128 = 1;
-				m_hospitalState->m_unk0x08.m_unk0x00 = 13;
+				m_hospitalState->m_unk0x08 = 13;
 				m_destLocation = LegoGameState::e_infomain;
 
 				DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
@@ -594,7 +588,7 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
 			DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
 
 			if (m_unk0x100 == 1) {
-				m_hospitalState->m_unk0x08.m_unk0x00 = 15;
+				m_hospitalState->m_unk0x08 = 15;
 
 				PlayAction(HospitalScript::c_hho016cl_RunAnim);
 				m_currentAction = HospitalScript::c_hho016cl_RunAnim;
@@ -602,7 +596,7 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
 			}
 			else if (m_unk0x128 == 0) {
 				m_unk0x128 = 1;
-				m_hospitalState->m_unk0x08.m_unk0x00 = 13;
+				m_hospitalState->m_unk0x08 = 13;
 				m_destLocation = LegoGameState::e_unk31;
 
 				DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
@@ -677,7 +671,7 @@ MxResult Hospital::Tickle()
 MxBool Hospital::Escape()
 {
 	DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, 999);
-	m_hospitalState->m_unk0x08.m_unk0x00 = 0;
+	m_hospitalState->m_unk0x08 = 0;
 
 	m_destLocation = LegoGameState::e_infomain;
 
@@ -697,25 +691,25 @@ HospitalState::HospitalState()
 
 // FUNCTION: LEGO1 0x10076530
 // FUNCTION: BETA10 0x1002db26
-MxResult HospitalState::Serialize(LegoFile* p_file)
+MxResult HospitalState::Serialize(LegoStorage* p_storage)
 {
-	LegoState::Serialize(p_file);
+	LegoState::Serialize(p_storage);
 
-	if (p_file->IsWriteMode()) {
-		p_file->Write(m_unk0x0c);
-		p_file->Write(m_unk0x0e);
-		p_file->Write(m_unk0x10);
-		p_file->Write(m_unk0x12);
-		p_file->Write(m_unk0x14);
-		p_file->Write(m_unk0x16);
+	if (p_storage->IsWriteMode()) {
+		p_storage->WriteS16(m_unk0x0c);
+		p_storage->WriteS16(m_unk0x0e);
+		p_storage->WriteS16(m_unk0x10);
+		p_storage->WriteS16(m_unk0x12);
+		p_storage->WriteS16(m_unk0x14);
+		p_storage->WriteS16(m_unk0x16);
 	}
-	else if (p_file->IsReadMode()) {
-		p_file->Read(m_unk0x0c);
-		p_file->Read(m_unk0x0e);
-		p_file->Read(m_unk0x10);
-		p_file->Read(m_unk0x12);
-		p_file->Read(m_unk0x14);
-		p_file->Read(m_unk0x16);
+	else if (p_storage->IsReadMode()) {
+		p_storage->ReadS16(m_unk0x0c);
+		p_storage->ReadS16(m_unk0x0e);
+		p_storage->ReadS16(m_unk0x10);
+		p_storage->ReadS16(m_unk0x12);
+		p_storage->ReadS16(m_unk0x14);
+		p_storage->ReadS16(m_unk0x16);
 	}
 
 	return SUCCESS;
diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp
index 2c4a4dc5..b56ffadf 100644
--- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp
@@ -149,6 +149,11 @@ Infocenter::Infocenter()
 	m_unk0x1d6 = 0;
 }
 
+// FUNCTION: LEGO1 0x1006ec80
+InfocenterMapEntry::InfocenterMapEntry()
+{
+}
+
 // FUNCTION: LEGO1 0x1006ec90
 Infocenter::~Infocenter()
 {
diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp
index 6c3b0859..aeb9be41 100644
--- a/LEGO1/lego/legoomni/src/worlds/isle.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp
@@ -13,7 +13,6 @@
 #include "jukebox_actions.h"
 #include "jukeboxentity.h"
 #include "legoanimationmanager.h"
-#include "legobackgroundcolor.h"
 #include "legocontrolmanager.h"
 #include "legoinputmanager.h"
 #include "legomain.h"
@@ -1324,150 +1323,140 @@ Act1State::Act1State()
 
 // FUNCTION: LEGO1 0x10033ac0
 // FUNCTION: BETA10 0x1003524f
-MxResult Act1State::Serialize(LegoFile* p_file)
+MxResult Act1State::Serialize(LegoStorage* p_storage)
 {
-	LegoState::Serialize(p_file);
+	LegoState::Serialize(p_storage);
 
-	m_motocyclePlane.Serialize(p_file);
-	m_bikePlane.Serialize(p_file);
-	m_skateboardPlane.Serialize(p_file);
-	m_helicopterPlane.Serialize(p_file);
-	m_jetskiPlane.Serialize(p_file);
-	m_dunebuggyPlane.Serialize(p_file);
-	m_racecarPlane.Serialize(p_file);
+	m_motocyclePlane.Serialize(p_storage);
+	m_bikePlane.Serialize(p_storage);
+	m_skateboardPlane.Serialize(p_storage);
+	m_helicopterPlane.Serialize(p_storage);
+	m_jetskiPlane.Serialize(p_storage);
+	m_dunebuggyPlane.Serialize(p_storage);
+	m_racecarPlane.Serialize(p_storage);
 
-	if (p_file->IsWriteMode()) {
-		// TODO: Seems to match better when using strcmp directly instead of IsPresent
+	if (p_storage->IsWriteMode()) {
 		if (strcmp(m_helicopterPlane.m_name.GetData(), "")) {
 			if (!m_helicopterWindshield) {
-				WriteDefaultTexture(p_file, "chwind.gif");
+				WriteDefaultTexture(p_storage, "chwind.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_helicopterWindshield);
+				WriteNamedTexture(p_storage, m_helicopterWindshield);
 			}
 
 			if (!m_helicopterJetLeft) {
-				WriteDefaultTexture(p_file, "chjetl.gif");
+				WriteDefaultTexture(p_storage, "chjetl.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_helicopterJetLeft);
+				WriteNamedTexture(p_storage, m_helicopterJetLeft);
 			}
 
 			if (!m_helicopterJetRight) {
-				WriteDefaultTexture(p_file, "chjetr.gif");
+				WriteDefaultTexture(p_storage, "chjetr.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_helicopterJetRight);
+				WriteNamedTexture(p_storage, m_helicopterJetRight);
 			}
 		}
 
 		if (strcmp(m_jetskiPlane.m_name.GetData(), "")) {
 			if (!m_jetskiFront) {
-				WriteDefaultTexture(p_file, "jsfrnt.gif");
+				WriteDefaultTexture(p_storage, "jsfrnt.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_jetskiFront);
+				WriteNamedTexture(p_storage, m_jetskiFront);
 			}
 
 			if (!m_jetskiWindshield) {
-				WriteDefaultTexture(p_file, "jswnsh.gif");
+				WriteDefaultTexture(p_storage, "jswnsh.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_jetskiWindshield);
+				WriteNamedTexture(p_storage, m_jetskiWindshield);
 			}
 		}
 
 		if (strcmp(m_dunebuggyPlane.m_name.GetData(), "")) {
 			if (!m_dunebuggyFront) {
-				WriteDefaultTexture(p_file, "dbfrfn.gif");
+				WriteDefaultTexture(p_storage, "dbfrfn.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_dunebuggyFront);
+				WriteNamedTexture(p_storage, m_dunebuggyFront);
 			}
 		}
 
 		if (strcmp(m_racecarPlane.m_name.GetData(), "")) {
 			if (!m_racecarFront) {
-				WriteDefaultTexture(p_file, "rcfrnt.gif");
+				WriteDefaultTexture(p_storage, "rcfrnt.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_racecarFront);
+				WriteNamedTexture(p_storage, m_racecarFront);
 			}
 
 			if (!m_racecarBack) {
-				WriteDefaultTexture(p_file, "rcback.gif");
+				WriteDefaultTexture(p_storage, "rcback.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_racecarBack);
+				WriteNamedTexture(p_storage, m_racecarBack);
 			}
 
 			if (!m_racecarTail) {
-				WriteDefaultTexture(p_file, "rctail.gif");
+				WriteDefaultTexture(p_storage, "rctail.gif");
 			}
 			else {
-				WriteNamedTexture(p_file, m_racecarTail);
+				WriteNamedTexture(p_storage, m_racecarTail);
 			}
 		}
 
-		p_file->Write(m_cptClickDialogue.m_nextIndex);
-		p_file->Write(m_unk0x022);
+		p_storage->WriteS16(m_cptClickDialogue.m_nextIndex);
+		p_storage->WriteU8(m_unk0x022);
 	}
-	else if (p_file->IsReadMode()) {
+	else if (p_storage->IsReadMode()) {
 		if (strcmp(m_helicopterPlane.m_name.GetData(), "")) {
-			m_helicopterWindshield = ReadNamedTexture(p_file);
-			if (m_helicopterWindshield == NULL) {
+			if ((m_helicopterWindshield = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 
-			m_helicopterJetLeft = ReadNamedTexture(p_file);
-			if (m_helicopterJetLeft == NULL) {
+			if ((m_helicopterJetLeft = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 
-			m_helicopterJetRight = ReadNamedTexture(p_file);
-			if (m_helicopterJetRight == NULL) {
+			if ((m_helicopterJetRight = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 		}
 
 		if (strcmp(m_jetskiPlane.m_name.GetData(), "")) {
-			m_jetskiFront = ReadNamedTexture(p_file);
-			if (m_jetskiFront == NULL) {
+			if ((m_jetskiFront = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 
-			m_jetskiWindshield = ReadNamedTexture(p_file);
-			if (m_jetskiWindshield == NULL) {
+			if ((m_jetskiWindshield = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 		}
 
 		if (strcmp(m_dunebuggyPlane.m_name.GetData(), "")) {
-			m_dunebuggyFront = ReadNamedTexture(p_file);
-			if (m_dunebuggyFront == NULL) {
+			if ((m_dunebuggyFront = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 		}
 
 		if (strcmp(m_racecarPlane.m_name.GetData(), "")) {
-			m_racecarFront = ReadNamedTexture(p_file);
-			if (m_racecarFront == NULL) {
+			if ((m_racecarFront = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 
-			m_racecarBack = ReadNamedTexture(p_file);
-			if (m_racecarBack == NULL) {
+			if ((m_racecarBack = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 
-			m_racecarTail = ReadNamedTexture(p_file);
-			if (m_racecarTail == NULL) {
+			if ((m_racecarTail = ReadNamedTexture(p_storage)) == NULL) {
 				return FAILURE;
 			}
 		}
 
-		p_file->Read(m_cptClickDialogue.m_nextIndex);
-		p_file->Read(m_unk0x022);
+		p_storage->ReadS16(m_cptClickDialogue.m_nextIndex);
+		p_storage->ReadU8(m_unk0x022);
 	}
 
 	return SUCCESS;
@@ -1497,12 +1486,12 @@ void Act1State::StopCptClickDialogue()
 // FUNCTION: LEGO1 0x100346d0
 MxBool Act1State::Reset()
 {
-	m_motocyclePlane.Reset();
-	m_bikePlane.Reset();
-	m_skateboardPlane.Reset();
+	m_motocyclePlane.m_name = "";
+	m_bikePlane.m_name = "";
+	m_skateboardPlane.m_name = "";
 	m_unk0x022 = FALSE;
 
-	m_helicopterPlane.Reset();
+	m_helicopterPlane.m_name = "";
 	if (m_helicopterWindshield) {
 		delete m_helicopterWindshield;
 		m_helicopterWindshield = NULL;
@@ -1523,7 +1512,7 @@ MxBool Act1State::Reset()
 		m_helicopter = NULL;
 	}
 
-	m_jetskiPlane.Reset();
+	m_jetskiPlane.m_name = "";
 	if (m_jetskiFront) {
 		delete m_jetskiFront;
 		m_jetskiFront = NULL;
@@ -1539,7 +1528,7 @@ MxBool Act1State::Reset()
 		m_jetski = NULL;
 	}
 
-	m_dunebuggyPlane.Reset();
+	m_dunebuggyPlane.m_name = "";
 	if (m_dunebuggyFront) {
 		delete m_dunebuggyFront;
 		m_dunebuggyFront = NULL;
@@ -1550,7 +1539,7 @@ MxBool Act1State::Reset()
 		m_dunebuggy = NULL;
 	}
 
-	m_racecarPlane.Reset();
+	m_racecarPlane.m_name = "";
 	if (m_racecarFront) {
 		delete m_racecarFront;
 		m_racecarFront = NULL;
diff --git a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp
index e7193307..a92f493d 100644
--- a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp
@@ -26,12 +26,6 @@ JukeBox::JukeBox()
 	NotificationManager()->Register(this);
 }
 
-// FUNCTION: LEGO1 0x1005d6e0
-MxBool JukeBox::VTable0x5c()
-{
-	return TRUE;
-}
-
 // FUNCTION: LEGO1 0x1005d830
 JukeBox::~JukeBox()
 {
diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp
index e9d00302..9f8e7793 100644
--- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp
@@ -92,12 +92,6 @@ LegoAct2::LegoAct2()
 	NotificationManager()->Register(this);
 }
 
-// FUNCTION: LEGO1 0x1004fe10
-MxBool LegoAct2::VTable0x5c()
-{
-	return TRUE;
-}
-
 // FUNCTION: LEGO1 0x1004fe40
 // FUNCTION: BETA10 0x1003a6f0
 LegoAct2::~LegoAct2()
diff --git a/LEGO1/lego/legoomni/src/worlds/police.cpp b/LEGO1/lego/legoomni/src/worlds/police.cpp
index ddfcda95..9daf5b8e 100644
--- a/LEGO1/lego/legoomni/src/worlds/police.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/police.cpp
@@ -26,12 +26,6 @@ Police::Police()
 	NotificationManager()->Register(this);
 }
 
-// FUNCTION: LEGO1 0x1005e1d0
-MxBool Police::VTable0x5c()
-{
-	return TRUE;
-}
-
 // FUNCTION: LEGO1 0x1005e320
 Police::~Police()
 {
@@ -209,15 +203,15 @@ PoliceState::PoliceState()
 
 // FUNCTION: LEGO1 0x1005e990
 // FUNCTION: BETA10 0x100f08b0
-MxResult PoliceState::Serialize(LegoFile* p_file)
+MxResult PoliceState::Serialize(LegoStorage* p_storage)
 {
-	LegoState::Serialize(p_file);
+	LegoState::Serialize(p_storage);
 
-	if (p_file->IsReadMode()) {
-		p_file->Read((MxS32&) m_policeScript);
+	if (p_storage->IsReadMode()) {
+		p_storage->ReadS32((MxS32&) m_policeScript);
 	}
 	else {
-		p_file->Write((MxS32) m_policeScript);
+		p_storage->WriteS32(m_policeScript);
 	}
 
 	return SUCCESS;
diff --git a/LEGO1/lego/sources/geom/legounkown100db7f4.h b/LEGO1/lego/sources/geom/legounkown100db7f4.h
index 1c9c266d..d54e3730 100644
--- a/LEGO1/lego/sources/geom/legounkown100db7f4.h
+++ b/LEGO1/lego/sources/geom/legounkown100db7f4.h
@@ -22,12 +22,12 @@ public:
 
 	// FUNCTION: LEGO1 0x1002ddc0
 	// FUNCTION: BETA10 0x100372a0
-	LegoResult FUN_1002ddc0(LegoWEEdge& p_f, Vector3& p_point)
+	LegoResult FUN_1002ddc0(LegoWEEdge& p_f, Vector3& p_point) const
 	{
 		if (p_f.IsEqual(m_faceA)) {
-			p_point[0] = -m_unk0x28.index_operator(0);
-			p_point[1] = -m_unk0x28.index_operator(1);
-			p_point[2] = -m_unk0x28.index_operator(2);
+			p_point[0] = -m_unk0x28[0];
+			p_point[1] = -m_unk0x28[1];
+			p_point[2] = -m_unk0x28[2];
 		}
 		else {
 			// clang-format off
diff --git a/LEGO1/lego/sources/geom/legowegedge.cpp b/LEGO1/lego/sources/geom/legowegedge.cpp
index 61e2214c..110cd2c6 100644
--- a/LEGO1/lego/sources/geom/legowegedge.cpp
+++ b/LEGO1/lego/sources/geom/legowegedge.cpp
@@ -5,7 +5,7 @@
 #include <assert.h>
 
 DECOMP_SIZE_ASSERT(LegoWEGEdge, 0x54)
-DECOMP_SIZE_ASSERT(LegoWEGEdge::PathWithTrigger, 0x0c)
+DECOMP_SIZE_ASSERT(PathWithTrigger, 0x0c)
 
 // FUNCTION: LEGO1 0x1009a730
 // FUNCTION: BETA10 0x101830ec
diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h
index 350e31b7..af32c3ea 100644
--- a/LEGO1/lego/sources/geom/legowegedge.h
+++ b/LEGO1/lego/sources/geom/legowegedge.h
@@ -1,13 +1,32 @@
 #ifndef __LEGOWEGEDGE_H
 #define __LEGOWEGEDGE_H
 
+class LegoPathStruct;
+
 #include "decomp.h"
 #include "legoweedge.h"
+
+// This struct might have been defined elsewhere (legopathstruct.h?).
+// Must be defined before the inclusion of Mx4DPointFloat for correct order
+// SIZE 0x0c
+struct PathWithTrigger {
+	// FUNCTION: LEGO1 0x10048280
+	// FUNCTION: BETA10 0x100bd450
+	PathWithTrigger()
+	{
+		m_pathStruct = NULL;
+		m_data = 0;
+		m_unk0x08 = 0.0f;
+	}
+
+	LegoPathStruct* m_pathStruct; // 0x00
+	unsigned int m_data;          // 0x04
+	float m_unk0x08;              // 0x08
+};
+
 #include "mxgeometry/mxgeometry3d.h"
 #include "mxgeometry/mxgeometry4d.h"
 
-class LegoPathStruct;
-
 // might be a struct with public members
 // VTABLE: LEGO1 0x100db7f8
 // SIZE 0x54
@@ -20,22 +39,6 @@ public:
 		c_bit5 = 0x10
 	};
 
-	// SIZE 0x0c
-	struct PathWithTrigger {
-		// FUNCTION: LEGO1 0x10048280
-		// FUNCTION: BETA10 0x100bd450
-		PathWithTrigger()
-		{
-			m_pathStruct = NULL;
-			m_data = 0;
-			m_unk0x08 = 0.0f;
-		}
-
-		LegoPathStruct* m_pathStruct; // 0x00
-		unsigned int m_data;          // 0x04
-		float m_unk0x08;              // 0x08
-	};
-
 	LegoWEGEdge();
 	~LegoWEGEdge() override;
 
diff --git a/LEGO1/lego/sources/misc/legocontainer.h b/LEGO1/lego/sources/misc/legocontainer.h
index 72db3332..fd439912 100644
--- a/LEGO1/lego/sources/misc/legocontainer.h
+++ b/LEGO1/lego/sources/misc/legocontainer.h
@@ -27,6 +27,8 @@ class LegoContainerInfo : public map<const char*, T*, LegoContainerInfoComparato
 template <class T>
 class LegoContainer {
 public:
+	LegoContainer() { m_ownership = TRUE; }
+
 	virtual ~LegoContainer()
 	{
 #ifdef COMPAT_MODE
@@ -115,7 +117,6 @@ typedef list<LegoCachedTexture> LegoCachedTextureList;
 // SIZE 0x24
 class LegoTextureContainer : public LegoContainer<LegoTextureInfo> {
 public:
-	LegoTextureContainer() { m_ownership = TRUE; }
 	~LegoTextureContainer() override;
 
 	LegoTextureInfo* GetCached(LegoTextureInfo* p_textureInfo);
diff --git a/LEGO1/lego/sources/misc/legostorage.h b/LEGO1/lego/sources/misc/legostorage.h
index 7f78fbc5..bb2af82a 100644
--- a/LEGO1/lego/sources/misc/legostorage.h
+++ b/LEGO1/lego/sources/misc/legostorage.h
@@ -33,6 +33,154 @@ public:
 	// FUNCTION: LEGO1 0x10045af0
 	virtual LegoBool IsReadMode() { return m_mode == c_read; } // vtable+0x18
 
+	// FUNCTION: BETA10 0x10017c80
+	LegoStorage* WriteString(const char* p_data)
+	{
+		LegoS16 length = strlen(p_data);
+		WriteS16(length);
+		Write(p_data, length);
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x1004b0d0
+	LegoStorage* WriteU8(LegoU8 p_data)
+	{
+		Write(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x10017ce0
+	LegoStorage* WriteS16(LegoS16 p_data)
+	{
+		Write(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x1004b110
+	LegoStorage* WriteU16(LegoU16 p_data)
+	{
+		Write(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// TODO: Type might be different (LegoS32). MxS32 is incompatible with LegoS32.
+	// FUNCTION: BETA10 0x10088540
+	LegoStorage* WriteS32(MxS32 p_data)
+	{
+		Write(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// TODO: Type might be different (LegoU32). MxU32 is incompatible with LegoU32.
+	// FUNCTION: BETA10 0x1004b150
+	LegoStorage* WriteU32(MxU32 p_data)
+	{
+		Write(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x10073610
+	LegoStorage* WriteFloat(LegoFloat p_data)
+	{
+		Write(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: LEGO1 0x100343d0
+	LegoStorage* WriteVector(Mx3DPointFloat p_data)
+	{
+		WriteFloat(p_data[0]);
+		WriteFloat(p_data[1]);
+		WriteFloat(p_data[2]);
+		return this;
+	}
+
+	// FUNCTION: LEGO1 0x10006030
+	// FUNCTION: BETA10 0x10017bb0
+	LegoStorage* WriteMxString(MxString p_data)
+	{
+		WriteString(p_data.GetData());
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x10073690
+	LegoStorage* ReadString(char* p_data)
+	{
+		LegoS16 length;
+		ReadS16(length);
+		Read(p_data, length);
+		p_data[length] = '\0';
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x1004b190
+	LegoStorage* ReadU8(LegoU8& p_data)
+	{
+		Read(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x10024680
+	LegoStorage* ReadS16(LegoS16& p_data)
+	{
+		Read(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x1004b1d0
+	LegoStorage* ReadU16(LegoU16& p_data)
+	{
+		Read(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// TODO: Type might be different (LegoS32). MxS32 is incompatible with LegoS32.
+	// FUNCTION: BETA10 0x10088580
+	LegoStorage* ReadS32(MxS32& p_data)
+	{
+		Read(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// TODO: Type might be different (LegoU32). MxU32 is incompatible with LegoU32.
+	// FUNCTION: BETA10 0x1004b210
+	LegoStorage* ReadU32(MxU32& p_data)
+	{
+		Read(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: BETA10 0x10073650
+	LegoStorage* ReadFloat(LegoFloat& p_data)
+	{
+		Read(&p_data, sizeof(p_data));
+		return this;
+	}
+
+	// FUNCTION: LEGO1 0x10034430
+	LegoStorage* ReadVector(Mx3DPointFloat& p_data)
+	{
+		ReadFloat(p_data[0]);
+		ReadFloat(p_data[1]);
+		ReadFloat(p_data[2]);
+		return this;
+	}
+
+	// FUNCTION: LEGO1 0x10034470
+	LegoStorage* ReadMxString(MxString& p_data)
+	{
+		LegoS16 length;
+		ReadS16(length);
+
+		char* text = new char[length + 1];
+		Read(text, length);
+
+		text[length] = '\0';
+		p_data = text;
+		delete[] text;
+		return this;
+	}
+
 	// SYNTHETIC: LEGO1 0x10045b00
 	// LegoStorage::`scalar deleting destructor'
 
@@ -86,151 +234,6 @@ public:
 	LegoResult SetPosition(LegoU32 p_position) override;             // vtable+0x10
 	LegoResult Open(const char* p_name, LegoU32 p_mode);
 
-	// FUNCTION: LEGO1 0x10006030
-	// FUNCTION: BETA10 0x10017bb0
-	LegoStorage* Write(MxString p_data)
-	{
-		Write(p_data.GetData());
-		return this;
-	}
-
-	// FUNCTION: BETA10 0x10017c80
-	LegoStorage* Write(const char* p_data)
-	{
-		LegoS16 length = strlen(p_data);
-		Write(length);
-		Write(p_data, length);
-		return this;
-	}
-
-	// FUNCTION: BETA10 0x1004b0d0
-	LegoStorage* Write(LegoU8 p_data)
-	{
-		Write(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// FUNCTION: BETA10 0x10017ce0
-	LegoStorage* Write(LegoS16 p_data)
-	{
-		Write(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// FUNCTION: BETA10 0x1004b110
-	LegoStorage* Write(LegoU16 p_data)
-	{
-		Write(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// TODO: Type might be different (LegoS32). MxS32 is incompatible with LegoS32.
-	// FUNCTION: BETA10 0x10088540
-	LegoStorage* Write(MxS32 p_data)
-	{
-		Write(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// TODO: Type might be different (LegoU32). MxU32 is incompatible with LegoU32.
-	// FUNCTION: BETA10 0x1004b150
-	LegoStorage* Write(MxU32 p_data)
-	{
-		Write(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	LegoStorage* Write(LegoFloat p_data)
-	{
-		Write(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// FUNCTION: LEGO1 0x100343d0
-	LegoStorage* Write(Mx3DPointFloat p_vec)
-	{
-		Write(p_vec[0]);
-		Write(p_vec[1]);
-		Write(p_vec[2]);
-		return this;
-	}
-
-	LegoStorage* Read(char* p_data)
-	{
-		LegoS16 length;
-		Read(length);
-		Read(p_data, length);
-		p_data[length] = '\0';
-		return this;
-	}
-
-	// FUNCTION: LEGO1 0x10034470
-	LegoStorage* Read(MxString& p_data)
-	{
-		LegoS16 length;
-		Read(length);
-
-		char* text = new char[length + 1];
-		Read(text, length);
-
-		text[length] = '\0';
-		p_data = text;
-		delete[] text;
-		return this;
-	}
-
-	// FUNCTION: BETA10 0x1004b190
-	LegoStorage* Read(LegoU8& p_data)
-	{
-		Read(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// FUNCTION: BETA10 0x10024680
-	LegoStorage* Read(LegoS16& p_data)
-	{
-		Read(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// FUNCTION: BETA10 0x1004b1d0
-	LegoStorage* Read(LegoU16& p_data)
-	{
-		Read(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// TODO: Type might be different (LegoS32). MxS32 is incompatible with LegoS32.
-	// FUNCTION: BETA10 0x10088580
-	LegoStorage* Read(MxS32& p_data)
-	{
-		Read(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// TODO: Type might be different (LegoU32). MxU32 is incompatible with LegoU32.
-	// FUNCTION: BETA10 0x1004b210
-	LegoStorage* Read(MxU32& p_data)
-	{
-		Read(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	LegoStorage* Read(LegoFloat& p_data)
-	{
-		Read(&p_data, sizeof(p_data));
-		return this;
-	}
-
-	// FUNCTION: LEGO1 0x10034430
-	LegoStorage* Read(Mx3DPointFloat& p_vec)
-	{
-		Read(p_vec[0]);
-		Read(p_vec[1]);
-		Read(p_vec[2]);
-		return this;
-	}
-
 	// SYNTHETIC: LEGO1 0x10099230
 	// LegoFile::`scalar deleting destructor'
 
diff --git a/LEGO1/lego/sources/misc/legounknown.cpp b/LEGO1/lego/sources/misc/legounknown.cpp
index d1af890d..db3f056c 100644
--- a/LEGO1/lego/sources/misc/legounknown.cpp
+++ b/LEGO1/lego/sources/misc/legounknown.cpp
@@ -18,7 +18,13 @@ LegoUnknown::~LegoUnknown()
 }
 
 // FUNCTION: LEGO1 0x1009a140
-void LegoUnknown::FUN_1009a140(const Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, Vector3& p_point4)
+// FUNCTION: BETA10 0x10182c2f
+void LegoUnknown::FUN_1009a140(
+	const Vector3& p_point1,
+	const Vector3& p_point2,
+	const Vector3& p_point3,
+	const Vector3& p_point4
+)
 {
 	m_unk0x00[0] = p_point1;
 	m_unk0x00[1] = p_point2;
diff --git a/LEGO1/lego/sources/misc/legounknown.h b/LEGO1/lego/sources/misc/legounknown.h
index 5659feb7..e129952c 100644
--- a/LEGO1/lego/sources/misc/legounknown.h
+++ b/LEGO1/lego/sources/misc/legounknown.h
@@ -12,7 +12,12 @@ public:
 	LegoUnknown();
 	~LegoUnknown();
 
-	void FUN_1009a140(const Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, Vector3& p_point4);
+	void FUN_1009a140(
+		const Vector3& p_point1,
+		const Vector3& p_point2,
+		const Vector3& p_point3,
+		const Vector3& p_point4
+	);
 	LegoResult FUN_1009a1e0(float p_f1, MxMatrix& p_mat, Vector3& p_v, LegoU32 p_und);
 
 private:
diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h
index d420ffc0..82f3ae87 100644
--- a/LEGO1/library_msvc.h
+++ b/LEGO1/library_msvc.h
@@ -697,7 +697,7 @@
 // strcpy
 
 // LIBRARY: BETA10 0x100f8a88
-// operator new
+// ??2@YAPAXI@Z
 
 // LIBRARY: BETA10 0x100f9420
 // memcpy
diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h
index 578d31b2..0a6ec12e 100644
--- a/LEGO1/mxgeometry/mxgeometry3d.h
+++ b/LEGO1/mxgeometry/mxgeometry3d.h
@@ -38,12 +38,8 @@ public:
 	// FUNCTION: BETA10 0x10013460
 	float& operator[](int idx) { return m_data[idx]; }
 
-	// According to the PDB, BETA10 will not link this one if it is never used
-	// const float& operator[](int idx) const { return m_data[idx]; }
-
-	// only used by LegoUnknown100db7f4::FUN_1002ddc0() for some unknown reason
 	// FUNCTION: BETA10 0x100373c0
-	float& index_operator(int idx) { return m_data[idx]; }
+	const float& operator[](int idx) const { return m_data[idx]; }
 
 	// SYNTHETIC: LEGO1 0x10010c00
 	// ??4Mx3DPointFloat@@QAEAAV0@ABV0@@Z
diff --git a/LEGO1/omni/include/mxbitmap.h b/LEGO1/omni/include/mxbitmap.h
index 8b1205e7..b73c52a5 100644
--- a/LEGO1/omni/include/mxbitmap.h
+++ b/LEGO1/omni/include/mxbitmap.h
@@ -41,15 +41,15 @@ public:
 	MxBitmap();
 	~MxBitmap() override; // vtable+00
 
-	virtual MxResult ImportBitmap(MxBitmap* p_bitmap);                                     // vtable+14
-	virtual MxResult ImportBitmapInfo(MxBITMAPINFO* p_info);                               // vtable+18
-	virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool); // vtable+1c
-	virtual MxResult LoadFile(SDL_IOStream* p_handle);                                     // vtable+20
-	virtual MxLong Read(const char* p_filename);                                           // vtable+24
+	virtual MxResult ImportBitmap(MxBitmap* p_bitmap);                                     // vtable+0x14
+	virtual MxResult ImportBitmapInfo(MxBITMAPINFO* p_info);                               // vtable+0x18
+	virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool); // vtable+0x1c
+	virtual MxResult LoadFile(SDL_IOStream* p_handle);                                     // vtable+0x20
+	virtual MxLong Read(const char* p_filename);                                           // vtable+0x24
 
 	// FUNCTION: LEGO1 0x1004e0d0
 	// FUNCTION: BETA10 0x10060fc0
-	virtual int VTable0x28(int) { return -1; } // vtable+28
+	virtual MxS32 VTable0x28(MxS32) { return -1; } // vtable+0x28
 
 	virtual void BitBlt(
 		MxBitmap* p_src,
@@ -59,7 +59,7 @@ public:
 		MxS32 p_bottom,
 		MxS32 p_width,
 		MxS32 p_height
-	); // vtable+2c
+	); // vtable+0x2c
 	virtual void BitBltTransparent(
 		MxBitmap* p_src,
 		MxS32 p_left,
@@ -68,10 +68,10 @@ public:
 		MxS32 p_bottom,
 		MxS32 p_width,
 		MxS32 p_height
-	);                                                // vtable+30
-	virtual MxPalette* CreatePalette();               // vtable+34
-	virtual void ImportPalette(MxPalette* p_palette); // vtable+38
-	virtual MxResult SetBitDepth(MxBool);             // vtable+3c
+	);                                                // vtable+0x30
+	virtual MxPalette* CreatePalette();               // vtable+0x34
+	virtual void ImportPalette(MxPalette* p_palette); // vtable+0x38
+	virtual MxResult SetBitDepth(MxBool);             // vtable+0x3c
 	virtual MxResult StretchBits(
 		HDC p_hdc,
 		MxS32 p_xSrc,
@@ -80,7 +80,7 @@ public:
 		MxS32 p_yDest,
 		MxS32 p_destWidth,
 		MxS32 p_destHeight
-	); // vtable+40
+	); // vtable+0x40
 
 	// Bit mask trick to round up to the nearest multiple of four.
 	// Pixel data may be stored with padding.
diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h
index b7677e92..32b47b08 100644
--- a/LEGO1/omni/include/mxdsaction.h
+++ b/LEGO1/omni/include/mxdsaction.h
@@ -88,13 +88,13 @@ public:
 	void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; }
 
 	// FUNCTION: BETA10 0x1003db50
-	Vector3& GetLocation() { return m_location; }
+	const Vector3& GetLocation() { return m_location; }
 
 	// FUNCTION: BETA10 0x1003db80
-	Vector3& GetDirection() { return m_direction; }
+	const Vector3& GetDirection() { return m_direction; }
 
 	// FUNCTION: BETA10 0x1003dbb0
-	Vector3& GetUp() { return m_up; }
+	const Vector3& GetUp() { return m_up; }
 
 	// FUNCTION: BETA10 0x100153b0
 	void SetLocation(const Vector3& p_location) { m_location = p_location; }
diff --git a/LEGO1/omni/include/mxstillpresenter.h b/LEGO1/omni/include/mxstillpresenter.h
index c8e5266a..55b2be70 100644
--- a/LEGO1/omni/include/mxstillpresenter.h
+++ b/LEGO1/omni/include/mxstillpresenter.h
@@ -13,6 +13,9 @@ public:
 	// FUNCTION: LEGO1 0x10043550
 	~MxStillPresenter() override { Destroy(TRUE); } // vtable+0x00
 
+	// FUNCTION: LEGO1 0x100435b0
+	void Destroy() override { Destroy(FALSE); } // vtable+0x38
+
 	// FUNCTION: BETA10 0x100980c0
 	static const char* HandlerClassName()
 	{
@@ -33,14 +36,10 @@ public:
 		return !strcmp(p_name, MxStillPresenter::ClassName()) || MxVideoPresenter::IsA(p_name);
 	}
 
-	void StartingTickle() override;  // vtable+0x1c
-	void StreamingTickle() override; // vtable+0x20
-	void RepeatingTickle() override; // vtable+0x24
-	void ParseExtra() override;      // vtable+0x30
-
-	// FUNCTION: LEGO1 0x100435b0
-	void Destroy() override { Destroy(FALSE); } // vtable+0x38
-
+	void StartingTickle() override;                   // vtable+0x1c
+	void StreamingTickle() override;                  // vtable+0x20
+	void RepeatingTickle() override;                  // vtable+0x24
+	void ParseExtra() override;                       // vtable+0x30
 	void Enable(MxBool p_enable) override;            // vtable+0x54
 	void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
 	void CreateBitmap() override;                     // vtable+0x60
diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h
index 307f4ce5..eccc4f04 100644
--- a/LEGO1/realtime/matrix.h
+++ b/LEGO1/realtime/matrix.h
@@ -49,6 +49,8 @@ public:
 	inline void Swap(int p_d1, int p_d2);
 
 	float* operator[](int idx) { return m_data[idx]; }
+
+	// FUNCTION: BETA10 0x10017780
 	const float* operator[](int idx) const { return m_data[idx]; }
 };
 
diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp
index 8f92f6f2..9c6b8434 100644
--- a/LEGO1/viewmanager/viewmanager.cpp
+++ b/LEGO1/viewmanager/viewmanager.cpp
@@ -471,6 +471,7 @@ void ViewManager::SetPOVSource(const OrientableROI* point_of_view)
 }
 
 // FUNCTION: LEGO1 0x100a6dc0
+// FUNCTION: BETA10 0x101739b8
 float ViewManager::ProjectedSize(const BoundingSphere& p_bounding_sphere)
 {
 	// The algorithm projects the radius of bounding sphere onto the perpendicular
diff --git a/LEGO1/viewmanager/viewmanager.h b/LEGO1/viewmanager/viewmanager.h
index cfc819f3..46a6bda9 100644
--- a/LEGO1/viewmanager/viewmanager.h
+++ b/LEGO1/viewmanager/viewmanager.h
@@ -43,6 +43,7 @@ public:
 	// FUNCTION: BETA10 0x100576b0
 	const CompoundObject& GetROIs() { return rois; }
 
+	// FUNCTION: BETA10 0x100e1260
 	void Add(ViewROI* p_roi) { rois.push_back(p_roi); }
 
 	// SYNTHETIC: LEGO1 0x100a6000