module Rattletrap.Decode.Vector
  ( decodeVectorBits
  )
where

import Rattletrap.Decode.Common
import Rattletrap.Decode.CompressedWord
import Rattletrap.Type.CompressedWord
import Rattletrap.Type.Vector

decodeVectorBits :: (Int, Int, Int) -> DecodeBits Vector
decodeVectorBits :: (Int, Int, Int) -> DecodeBits Vector
decodeVectorBits (Int, Int, Int)
version = do
  CompressedWord
size <- Word -> DecodeBits CompressedWord
decodeCompressedWordBits (if (Int, Int, Int)
version (Int, Int, Int) -> (Int, Int, Int) -> Bool
forall a. Ord a => a -> a -> Bool
>= (Int
868, Int
22, Int
7) then Word
21 else Word
19)
  let
    limit :: Word
limit = CompressedWord -> Word
getLimit CompressedWord
size
    bias :: Word
bias = CompressedWord -> Word
getBias CompressedWord
size
  CompressedWord -> Word -> Int -> Int -> Int -> Vector
Vector CompressedWord
size Word
bias
    (Int -> Int -> Int -> Vector)
-> BitGet Int -> BitGet (Int -> Int -> Vector)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (CompressedWord -> Int) -> DecodeBits CompressedWord -> BitGet Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Word -> CompressedWord -> Int
fromDelta Word
bias) (Word -> DecodeBits CompressedWord
decodeCompressedWordBits Word
limit)
    BitGet (Int -> Int -> Vector)
-> BitGet Int -> BitGet (Int -> Vector)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (CompressedWord -> Int) -> DecodeBits CompressedWord -> BitGet Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Word -> CompressedWord -> Int
fromDelta Word
bias) (Word -> DecodeBits CompressedWord
decodeCompressedWordBits Word
limit)
    BitGet (Int -> Vector) -> BitGet Int -> DecodeBits Vector
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (CompressedWord -> Int) -> DecodeBits CompressedWord -> BitGet Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Word -> CompressedWord -> Int
fromDelta Word
bias) (Word -> DecodeBits CompressedWord
decodeCompressedWordBits Word
limit)

getLimit :: CompressedWord -> Word
getLimit :: CompressedWord -> Word
getLimit = (Word
2 Word -> Word -> Word
forall a b. (Num a, Integral b) => a -> b -> a
^) (Word -> Word)
-> (CompressedWord -> Word) -> CompressedWord -> Word
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word -> Word -> Word
forall a. Num a => a -> a -> a
+ Word
2) (Word -> Word)
-> (CompressedWord -> Word) -> CompressedWord -> Word
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CompressedWord -> Word
compressedWordValue

getBias :: CompressedWord -> Word
getBias :: CompressedWord -> Word
getBias = (Word
2 Word -> Word -> Word
forall a b. (Num a, Integral b) => a -> b -> a
^) (Word -> Word)
-> (CompressedWord -> Word) -> CompressedWord -> Word
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word -> Word -> Word
forall a. Num a => a -> a -> a
+ Word
1) (Word -> Word)
-> (CompressedWord -> Word) -> CompressedWord -> Word
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CompressedWord -> Word
compressedWordValue

fromDelta :: Word -> CompressedWord -> Int
fromDelta :: Word -> CompressedWord -> Int
fromDelta Word
bias CompressedWord
x = Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CompressedWord -> Word
compressedWordValue CompressedWord
x) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
bias