diff --git a/library/Octane/Data.hs b/library/Octane/Data.hs
--- a/library/Octane/Data.hs
+++ b/library/Octane/Data.hs
@@ -21,6 +21,7 @@
             [ "Archetypes.Ball.Ball_Default"
             , "Archetypes.Ball.Ball_Basketball"
             , "Archetypes.Ball.Ball_Puck"
+            , "Archetypes.Ball.CubeBall"
             ])
         , ( "TAGame.CameraSettingsActor_TA",
             [ "TAGame.CameraSettingsActor_TA:PRI"
@@ -54,7 +55,9 @@
             [ "Archetypes.GameEvent.GameEvent_SoccarPrivate"
             ])
         , ( "TAGame.GameEvent_SoccarSplitscreen_TA",
-            [ "Archetypes.GameEvent.GameEvent_SoccarSplitscreen"
+            [ "Archetypes.GameEvent.GameEvent_BasketballSplitscreen"
+            , "Archetypes.GameEvent.GameEvent_HockeySplitscreen"
+            , "Archetypes.GameEvent.GameEvent_SoccarSplitscreen"
             ])
         , ( "TAGame.GameEvent_Soccar_TA",
             [ "Archetypes.GameEvent.GameEvent_Soccar"
@@ -62,6 +65,7 @@
             ])
         , ( "TAGame.GRI_TA",
             [ "GameInfo_Basketball.GameInfo.GameInfo_Basketball:GameReplicationInfoArchetype"
+            , "Gameinfo_Hockey.GameInfo.Gameinfo_Hockey:GameReplicationInfoArchetype"
             , "GameInfo_Season.GameInfo.GameInfo_Season:GameReplicationInfoArchetype"
             , "GameInfo_Soccar.GameInfo.GameInfo_Soccar:GameReplicationInfoArchetype"
             ])
@@ -140,6 +144,7 @@
     , "eurostadium_p"
     , "eurostadium_rainy_audio"
     , "hoopsstadium_sfx"
+    , "labs_cosmic_p"
     , "labs_doublegoal_p"
     , "labs_underpass_p"
     , "labs_utopia_p"
@@ -195,6 +200,8 @@
     , "ProjectX.GRI_X:bGameStarted"
     , "TAGame.CameraSettingsActor_TA:bUsingBehindView"
     , "TAGame.CameraSettingsActor_TA:bUsingSecondaryCamera"
+    , "TAGame.CarComponent_Boost_TA:bNoBoost"
+    , "TAGame.CarComponent_Boost_TA:bUnlimitedBoost"
     , "TAGame.CarComponent_FlipCar_TA:bFlipRight"
     , "TAGame.GameEvent_Soccar_TA:bBallHasBeenHit"
     , "TAGame.GameEvent_Soccar_TA:bOverTime"
@@ -236,7 +243,7 @@
     , "TAGame.PRI_TA:CameraSettings"
     ] & map Text.pack & Set.fromList
 
--- | A set of properties that are demolition.
+-- | A set of properties that are demolitions.
 demolishProperties :: Set.Set Text.Text
 demolishProperties =
     [ "TAGame.Car_TA:ReplicatedDemolish"
@@ -282,6 +289,9 @@
     , "TAGame.Ball_TA:ReplicatedBallMaxLinearSpeedScale"
     , "TAGame.Ball_TA:ReplicatedBallScale"
     , "TAGame.Ball_TA:ReplicatedWorldBounceScale"
+    , "TAGame.CarComponent_Boost_TA:BoostModifier"
+    , "TAGame.CarComponent_Boost_TA:RechargeDelay"
+    , "TAGame.CarComponent_Boost_TA:RechargeRate"
     , "TAGame.CarComponent_FlipCar_TA:FlipCarTime"
     , "TAGame.CrowdActor_TA:ModifiedNoise"
     ] & map Text.pack & Set.fromList
diff --git a/library/Octane/Json.hs b/library/Octane/Json.hs
new file mode 100644
--- /dev/null
+++ b/library/Octane/Json.hs
@@ -0,0 +1,9 @@
+module Octane.Json where
+
+import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Types as Aeson
+
+toJsonOptions :: String -> Aeson.Options
+toJsonOptions name = Aeson.defaultOptions
+    { Aeson.fieldLabelModifier = Aeson.camelTo2 '_' . drop (length name)
+    }
diff --git a/library/Octane/Parser.hs b/library/Octane/Parser.hs
--- a/library/Octane/Parser.hs
+++ b/library/Octane/Parser.hs
@@ -6,7 +6,6 @@
 
 import qualified Control.DeepSeq as DeepSeq
 import qualified Data.Aeson as Aeson
-import qualified Data.Aeson.Types as Aeson
 import qualified Data.Binary.Bits.Get as Bits
 import qualified Data.Binary.IEEE754 as IEEE754
 import qualified Data.Binary.Get as Binary
@@ -22,6 +21,7 @@
 import qualified Data.Word as Word
 import qualified GHC.Generics as Generics
 import qualified Octane.Data as Data
+import qualified Octane.Json as Json
 import qualified Octane.Parser.ClassPropertyMap as CPM
 import qualified Octane.Type as Type
 import qualified Text.Printf as Printf
@@ -274,12 +274,12 @@
 
 getCamSettingsProperty :: Bits.BitGet PropValue
 getCamSettingsProperty = do
-    fov <- getFloat32
-    height <- getFloat32
-    pitch <- getFloat32
-    dist <- getFloat32
-    stiff <- getFloat32
-    swiv <- getFloat32
+    fov <- getFloat32 -- camera fov
+    height <- getFloat32 -- camera height
+    pitch <- getFloat32 -- camera angle
+    dist <- getFloat32 -- camera distance
+    stiff <- getFloat32 -- camera stiffness
+    swiv <- getFloat32 -- camera swivel speed
     return (PCamSettings fov height pitch dist stiff swiv)
 
 getDemolishProperty :: Bits.BitGet PropValue
@@ -321,9 +321,8 @@
 getGameModeProperty :: Bits.BitGet PropValue
 getGameModeProperty = do
     x <- Bits.getWord8 2
-    if x == 2
-        then return (PGameMode x)
-        else error ("unexpected game mode value " ++ show x)
+    -- 1 is hockey, 2 is hoops
+    return (PGameMode x)
 
 getIntProperty :: Bits.BitGet PropValue
 getIntProperty = do
@@ -521,11 +520,6 @@
     localId <- Bits.getWord8 8
     localId & Just & return
 
-toJsonOptions :: String -> Aeson.Options
-toJsonOptions name = Aeson.defaultOptions
-    { Aeson.fieldLabelModifier = Aeson.camelTo2 '_' . drop (length name)
-    }
-
 type SystemId = Word.Word8
 
 -- This is the number associated with a splitscreen player. So the first player
@@ -551,7 +545,7 @@
 
 instance DeepSeq.NFData Prop
 instance Aeson.ToJSON Prop where
-    toJSON = Aeson.genericToJSON (toJsonOptions "Prop")
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "Prop")
 
 data PropValue
     = PBoolean !Bool
@@ -581,7 +575,7 @@
 
 instance DeepSeq.NFData PropValue
 instance Aeson.ToJSON PropValue where
-    toJSON = Aeson.genericToJSON (toJsonOptions "PropValue")
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "PropValue")
 
 -- | A frame in the net stream. Each frame has the time since the beginning of
 -- the match, the time since the last frame, and a list of replications.
@@ -593,7 +587,7 @@
 
 instance DeepSeq.NFData Frame
 instance Aeson.ToJSON Frame where
-    toJSON = Aeson.genericToJSON (toJsonOptions "Frame")
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "Frame")
 
 data ReplicationState
     = RSOpening
@@ -619,7 +613,7 @@
 
 instance DeepSeq.NFData Replication
 instance Aeson.ToJSON Replication where
-    toJSON = Aeson.genericToJSON (toJsonOptions "Replication")
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "Replication")
 
 data Thing = Thing
     { thingFlag :: !Bool
@@ -657,7 +651,7 @@
 
 instance DeepSeq.NFData ClassInit
 instance Aeson.ToJSON ClassInit where
-    toJSON = Aeson.genericToJSON (toJsonOptions "ClassInit")
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "ClassInit")
 
 -- { class stream id => { property stream id => name } }
 type ClassPropertyMap = IntMap.IntMap (IntMap.IntMap Text.Text)
diff --git a/library/Octane/Type/Actor.hs b/library/Octane/Type/Actor.hs
--- a/library/Octane/Type/Actor.hs
+++ b/library/Octane/Type/Actor.hs
@@ -3,10 +3,11 @@
 module Octane.Type.Actor (Actor(..)) where
 
 import qualified Control.DeepSeq as DeepSeq
-import qualified Data.Aeson.Types as Aeson
+import qualified Data.Aeson as Aeson
 import qualified Data.Binary as Binary
 import Data.Function ((&))
 import qualified GHC.Generics as Generics
+import qualified Octane.Json as Json
 import qualified Octane.Type.Primitive.PCString as PCString
 import qualified Octane.Type.Primitive.Word32LE as Word32LE
 
@@ -26,8 +27,4 @@
 instance DeepSeq.NFData Actor
 
 instance Aeson.ToJSON Actor where
-    toJSON =
-        Aeson.genericToJSON
-            Aeson.defaultOptions
-            { Aeson.fieldLabelModifier = drop 5
-            }
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "Actor")
diff --git a/library/Octane/Type/CacheItem.hs b/library/Octane/Type/CacheItem.hs
--- a/library/Octane/Type/CacheItem.hs
+++ b/library/Octane/Type/CacheItem.hs
@@ -3,10 +3,11 @@
 module Octane.Type.CacheItem (CacheItem(..)) where
 
 import qualified Control.DeepSeq as DeepSeq
-import qualified Data.Aeson.Types as Aeson
+import qualified Data.Aeson as Aeson
 import qualified Data.Binary as Binary
 import Data.Function ((&))
 import qualified GHC.Generics as Generics
+import qualified Octane.Json as Json
 import qualified Octane.Type.CacheProperty as CacheProperty
 import qualified Octane.Type.Primitive.List as List
 import qualified Octane.Type.Primitive.Word32LE as Word32LE
@@ -30,8 +31,4 @@
 instance DeepSeq.NFData CacheItem
 
 instance Aeson.ToJSON CacheItem where
-    toJSON =
-        Aeson.genericToJSON
-            Aeson.defaultOptions
-            { Aeson.fieldLabelModifier = drop 9
-            }
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "CacheItem")
diff --git a/library/Octane/Type/CacheProperty.hs b/library/Octane/Type/CacheProperty.hs
--- a/library/Octane/Type/CacheProperty.hs
+++ b/library/Octane/Type/CacheProperty.hs
@@ -3,10 +3,11 @@
 module Octane.Type.CacheProperty (CacheProperty(..)) where
 
 import qualified Control.DeepSeq as DeepSeq
-import qualified Data.Aeson.Types as Aeson
+import qualified Data.Aeson as Aeson
 import qualified Data.Binary as Binary
 import Data.Function ((&))
 import qualified GHC.Generics as Generics
+import qualified Octane.Json as Json
 import qualified Octane.Type.Primitive.Word32LE as Word32LE
 
 -- | A property on an item in the class net cache map.
@@ -24,8 +25,4 @@
 instance DeepSeq.NFData CacheProperty
 
 instance Aeson.ToJSON CacheProperty where
-    toJSON =
-        Aeson.genericToJSON
-            Aeson.defaultOptions
-            { Aeson.fieldLabelModifier = drop 13
-            }
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "CacheProperty")
diff --git a/library/Octane/Type/KeyFrame.hs b/library/Octane/Type/KeyFrame.hs
--- a/library/Octane/Type/KeyFrame.hs
+++ b/library/Octane/Type/KeyFrame.hs
@@ -3,10 +3,11 @@
 module Octane.Type.KeyFrame (KeyFrame(..)) where
 
 import qualified Control.DeepSeq as DeepSeq
-import qualified Data.Aeson.Types as Aeson
+import qualified Data.Aeson as Aeson
 import qualified Data.Binary as Binary
 import Data.Function ((&))
 import qualified GHC.Generics as Generics
+import qualified Octane.Json as Json
 import qualified Octane.Type.Primitive.Float32LE as Float32LE
 import qualified Octane.Type.Primitive.Word32LE as Word32LE
 
@@ -29,8 +30,4 @@
 instance DeepSeq.NFData KeyFrame
 
 instance Aeson.ToJSON KeyFrame where
-    toJSON =
-        Aeson.genericToJSON
-            Aeson.defaultOptions
-            { Aeson.fieldLabelModifier = drop 8
-            }
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "KeyFrame")
diff --git a/library/Octane/Type/Mark.hs b/library/Octane/Type/Mark.hs
--- a/library/Octane/Type/Mark.hs
+++ b/library/Octane/Type/Mark.hs
@@ -3,10 +3,11 @@
 module Octane.Type.Mark (Mark(..)) where
 
 import qualified Control.DeepSeq as DeepSeq
-import qualified Data.Aeson.Types as Aeson
+import qualified Data.Aeson as Aeson
 import qualified Data.Binary as Binary
 import Data.Function ((&))
 import qualified GHC.Generics as Generics
+import qualified Octane.Json as Json
 import qualified Octane.Type.Primitive.PCString as PCString
 import qualified Octane.Type.Primitive.Word32LE as Word32LE
 
@@ -25,8 +26,4 @@
 instance DeepSeq.NFData Mark
 
 instance Aeson.ToJSON Mark where
-    toJSON =
-        Aeson.genericToJSON
-            Aeson.defaultOptions
-            { Aeson.fieldLabelModifier = drop 4
-            }
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "Mark")
diff --git a/library/Octane/Type/Message.hs b/library/Octane/Type/Message.hs
--- a/library/Octane/Type/Message.hs
+++ b/library/Octane/Type/Message.hs
@@ -3,10 +3,11 @@
 module Octane.Type.Message (Message(..)) where
 
 import qualified Control.DeepSeq as DeepSeq
-import qualified Data.Aeson.Types as Aeson
+import qualified Data.Aeson as Aeson
 import qualified Data.Binary as Binary
 import Data.Function ((&))
 import qualified GHC.Generics as Generics
+import qualified Octane.Json as Json
 import qualified Octane.Type.Primitive.PCString as PCString
 import qualified Octane.Type.Primitive.Word32LE as Word32LE
 
@@ -27,8 +28,4 @@
 instance DeepSeq.NFData Message
 
 instance Aeson.ToJSON Message where
-    toJSON =
-        Aeson.genericToJSON
-            Aeson.defaultOptions
-            { Aeson.fieldLabelModifier = drop 7
-            }
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "Message")
diff --git a/library/Octane/Type/Primitive/Boolean.hs b/library/Octane/Type/Primitive/Boolean.hs
--- a/library/Octane/Type/Primitive/Boolean.hs
+++ b/library/Octane/Type/Primitive/Boolean.hs
@@ -24,4 +24,5 @@
 
 instance DeepSeq.NFData Boolean
 
-instance Aeson.ToJSON Boolean
+instance Aeson.ToJSON Boolean where
+    toJSON boolean = boolean & unpackBoolean & Aeson.toJSON
diff --git a/library/Octane/Type/Primitive/Float32LE.hs b/library/Octane/Type/Primitive/Float32LE.hs
--- a/library/Octane/Type/Primitive/Float32LE.hs
+++ b/library/Octane/Type/Primitive/Float32LE.hs
@@ -23,4 +23,5 @@
 
 instance DeepSeq.NFData Float32LE
 
-instance Aeson.ToJSON Float32LE
+instance Aeson.ToJSON Float32LE where
+    toJSON float = float & unpackFloat32LE & Aeson.toJSON
diff --git a/library/Octane/Type/Primitive/List.hs b/library/Octane/Type/Primitive/List.hs
--- a/library/Octane/Type/Primitive/List.hs
+++ b/library/Octane/Type/Primitive/List.hs
@@ -27,4 +27,5 @@
 
 instance (DeepSeq.NFData a) => DeepSeq.NFData (List a)
 
-instance (Aeson.ToJSON a) => Aeson.ToJSON (List a)
+instance (Aeson.ToJSON a) => Aeson.ToJSON (List a) where
+    toJSON list = list & unpackList & Aeson.toJSON
diff --git a/library/Octane/Type/Primitive/PCString.hs b/library/Octane/Type/Primitive/PCString.hs
--- a/library/Octane/Type/Primitive/PCString.hs
+++ b/library/Octane/Type/Primitive/PCString.hs
@@ -73,7 +73,8 @@
 
 instance DeepSeq.NFData PCString
 
-instance Aeson.ToJSON PCString
+instance Aeson.ToJSON PCString where
+    toJSON string = string & unpackPCString & Aeson.toJSON
 
 encodeLatin1 :: Text.Text -> BS.ByteString
 encodeLatin1 text = text & Text.unpack & BS8.pack
diff --git a/library/Octane/Type/Primitive/Word32LE.hs b/library/Octane/Type/Primitive/Word32LE.hs
--- a/library/Octane/Type/Primitive/Word32LE.hs
+++ b/library/Octane/Type/Primitive/Word32LE.hs
@@ -25,4 +25,5 @@
 
 instance DeepSeq.NFData Word32LE
 
-instance Aeson.ToJSON Word32LE
+instance Aeson.ToJSON Word32LE where
+    toJSON word = word & unpackWord32LE & Aeson.toJSON
diff --git a/library/Octane/Type/Primitive/Word64LE.hs b/library/Octane/Type/Primitive/Word64LE.hs
--- a/library/Octane/Type/Primitive/Word64LE.hs
+++ b/library/Octane/Type/Primitive/Word64LE.hs
@@ -25,4 +25,5 @@
 
 instance DeepSeq.NFData Word64LE
 
-instance Aeson.ToJSON Word64LE
+instance Aeson.ToJSON Word64LE where
+    toJSON word = word & unpackWord64LE & Aeson.toJSON
diff --git a/library/Octane/Type/Replay.hs b/library/Octane/Type/Replay.hs
--- a/library/Octane/Type/Replay.hs
+++ b/library/Octane/Type/Replay.hs
@@ -3,10 +3,11 @@
 module Octane.Type.Replay (Replay(..)) where
 
 import qualified Control.DeepSeq as DeepSeq
-import qualified Data.Aeson.Types as Aeson
+import qualified Data.Aeson as Aeson
 import qualified Data.Binary as Binary
 import Data.Function ((&))
 import qualified GHC.Generics as Generics
+import qualified Octane.Json as Json
 import qualified Octane.Type.Actor as Actor
 import qualified Octane.Type.CacheItem as CacheItem
 import qualified Octane.Type.KeyFrame as KeyFrame
@@ -111,8 +112,4 @@
 instance DeepSeq.NFData Replay
 
 instance Aeson.ToJSON Replay where
-    toJSON =
-        Aeson.genericToJSON
-            Aeson.defaultOptions
-            { Aeson.fieldLabelModifier = drop 6
-            }
+    toJSON = Aeson.genericToJSON (Json.toJsonOptions "Replay")
diff --git a/octane.cabal b/octane.cabal
--- a/octane.cabal
+++ b/octane.cabal
@@ -3,7 +3,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           octane
-version:        0.5.9
+version:        0.6.0
 synopsis:       Parse Rocket League replays.
 description:    Octane parses Rocket League replays.
 category:       Game
@@ -43,6 +43,7 @@
   exposed-modules:
       Octane
       Octane.Data
+      Octane.Json
       Octane.Main
       Octane.Parser
       Octane.Parser.ClassPropertyMap
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -68,4 +68,4 @@
     - -with-rtsopts=-N
     main: TestSuite.hs
     source-dirs: test-suite
-version: '0.5.9'
+version: '0.6.0'
