module DarkPlaces.Demo ( getDemoMessage, getDemoMessages, iterDemoMessages, demoFileMessages, demoFilePackets ) where import Control.Applicative import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString as B import Data.Binary.Get import DarkPlaces.Types import DarkPlaces.Binary import DarkPlaces.PacketParser getDemoMessage :: Get (QVector, BL.ByteString) getDemoMessage = do size <- fromIntegral <$> getWord32le angls <- getQVector msg <- getLazyByteString size return (angls, msg) getDemoMessages :: Get [(QVector, BL.ByteString)] getDemoMessages = do empty <- isEmpty if empty then return [] else (:) <$> getDemoMessage <*> getDemoMessages iterDemoMessages :: BL.ByteString -> [Either ErrorInfo (QVector, BL.ByteString)] iterDemoMessages demo_data = go decoder $ BL.toChunks demo_data where decoder = runGetIncremental getDemoMessage go (Fail _ offset msg) _ = [Left (offset, msg)] go (Partial k) [] = go (k Nothing) [] go (Partial k) (x:xs) = go (k $ Just x) xs go (Done left _ res) xs = Right res : if empty then [] else go decoder xs' where empty = B.null left && null xs xs' = left:xs demoFileMessages :: BL.ByteString -> [Either ErrorInfo (QVector, BL.ByteString)] demoFileMessages file_data = either (\l -> [Left l]) iterDemoMessages either_demo where either_demo = skipTrack file_data demoFilePackets :: BL.ByteString -> [Either ErrorInfo PacketOrError] demoFilePackets file_data = parse (demoFileMessages file_data) defaultDemoState where parse (x:xs) s = case x of Left l -> [Left l] Right (_, ps) -> case listPackets ps s of Left l -> [Left l] Right (pls, s') -> (Right <$> pls) ++ parse xs s' parse [] _ = []