packages feed

tttool 1.8 → 1.8.1

raw patch · 14 files changed

+222/−141 lines, 14 filesdep −bytestring-builderdep −ghc-primdep −old-localedep ~JuicyPixelsdep ~aesondep ~base

Dependencies removed: bytestring-builder, ghc-prim, old-locale

Dependency ranges changed: JuicyPixels, aeson, base, bytestring, containers, mtl, template-haskell, time, yaml

Files

+ Changelog.md view
@@ -0,0 +1,119 @@+# Changelog for tttool++## 1.8.1 (2019-03-30)++ * The SVG patterns created with `./tttool oid-code` and `./tttool oid-codes`+   now have `id`s that are valid (no spaces).+ * The release tarball now contains a binary for Linux as well.+ * The release tarball now contains a copy of [The tttool book](http://tttool.readthedocs.io/de/latest/)++## 1.8 (2018-02-06)++ * If the script for an oid code contains only one line, one can simply write++        house: P(welcome)++   instead of++        house:+         - P(welcome)+ * `./tttool oid-table` aligns images on pixel boundaries, so that a naive+   rastering of the whole page still yields crisp pixels.+   Thanks to @m7thon for the patch!+ * The PDF output uses PDF patterns for much smaller PDF files.+ * The commands `./tttool oid-code` and `./tttool oid-table` can now also+   produce SVG output with SVG patterns:++   `--image-format SVG` produces SVG with vector squares+   for the pixels, wihle `--image-format SVG+PNG` produces SVG with a small,+   repeated pixel graphics in the pattern+ * Games are now more likely to be properly round-tripped (GH issue #174)++## 1.7 (2017-01-08)++ * `./tttool oid-table` sorts naturally now, so that the sequence is `foo1`+   `foo2` `foo10`, and not `foo1` `foo10` `foo2`.+ * Read and write the language field in the GME header (GH issue #105)++## 1.6.1 (2016-04-17)++ * `./tttool assemble`: Do not fail with too many open files+ * Handle “other” play commands (FFE0, FFE1) even if their argument is not 0,+   with some crude syntax in the YAML format. The meaning of this argument is+   not yet understood, volunteers are welcome!++## 1.6 (2016-01-31)++ * Completely re-done option parsing, so there now proper support for short and+   long options, arbitrary order of options, better error messages and+   per-command `--help` output.++   **Incompatibility:** Some commands are now called differently. In+   particular, to generate PNG files with all codes from a YAML file, use+   `./tttool oid-codes`, not `./tttool oid-code`.+ * The size of the OID codes written by `./tttool oid-code` is configurable.+ * The png files written by `./tttool oid-code` and `./tttool oid-codes` store+   their DPI value, so that importing them into DTP programs is likely to yield+   the desired result.+ * New command `tttool oid-table` that prints all OIDs of a given YAML file as+   a nice and handy table in a PDF file+ * The output of `./tttool games` is more detailed.+ * Games are not exported by `tttool export` and assembled by `tttool+   assemble`. This way, existing Tiptoi products can be modified without losing+   them.+ * The “other” play commands (FFE0, FFE1, FB00) are implemented in the parser,+   printer and serializer, with syntax `P*(..)`, `PA*(..)` and `PA(..)`. These+   are not interesting to you unless you want to understand existing Tiptoi+   products.+ * Support for the “timer” action (FF00) with syntax `T($register,123)`.+ * `./tttool assemble` will print all errors due to missing audio files, not+   just the first.+ * Fix various crashes in corner cases, mostly involving games. Thanks to+   @ToniMahagoni for reporting these!++## 1.5.1 (2015-11-11)++ * Do not assign object IDs >= 15000, as these are not recognized.++## 1.5 (2015-10-28)++ * New commands FB00 (alternative play range command), FFE0 (alternative+   play random sample) and FFE1 (alternative play all samples)+ * New pixel formats -d 1200d and -d 600d,w hich double the size of the+   dots.+ * Assign object IDs dependent on project IDs, to avoid overlap.+ * Fix missing support in tttool play for > and <=++## 1.4 (2015-04-29)++ * The `tttool play` command is greatly enhanced:+   + Audio samples are actually played (On linux, install `sox`).+   + You can use the name of your scripts instead of the OID codes.+   + The prompt supports a persistent history (press ↑).+   + You can tab-complete your input.+ * `tttool` knows its own version.+ * `tttool assemble` warns if the comment field is too long for the GME file.++## 1.3 (2015-03-18)++ * The `tttool play` command now supports jump commands.++## 1.2 (2015-03-08)++ * The `language` fields takes arbitrary strings, which will hopefully be+   understood by the text-to-speak engine.++## 1.1 (2015-02-15)++ * The yaml files support a `language` field, specifying the default language+   for the text-to-speech feature.+ * The `speak` section of the yaml file can have subsections with differing+   languge settings, to allow multi-language files.+ * The text-to-speech feature will use either pico2wave or espeak, depending on+   what is available.+ * The windows release zipfile now comes with espeak and oggenc, so Windows users+   can use text-to-speech out of the box.++## 1.0 (2015-01-29)++ * Last release without a changelog
README.md view
@@ -3,7 +3,6 @@ tip-toi-reveng ============== - The goal of this project is to understand the file and paper format for the Ravensburger TipToi pen. The ultimate goal is that everyone can create their own books, with their own sounds.@@ -15,7 +14,8 @@ The tool can also be used to generate completely new files from scratch; see below for details. -If you want to learn more please have a look into our wiki (https://github.com/entropia/tip-toi-reveng/wiki).+If you want to learn more please have a look into our wiki+(https://github.com/entropia/tip-toi-reveng/wiki).  The tttool tool ---------------@@ -65,46 +65,11 @@ Installation ------------ -This program is written in Haskell and can be installed on Windows, MacOS or Linux.--For Windows users, we create zipfile containing `tttool`, you can find them in-the [releases section](https://github.com/entropia/tip-toi-reveng/releases) of-the github project.--Otherwise, installation from source is not difficult either:-- 1. If you have not done so yet, fetch the source code and change to the-    directory containing the code:--        git clone https://github.com/entropia/tip-toi-reveng.git tttool-        cd tttool-- 2. Install the *Haskell platform*, see http://www.haskell.org/platform/-    for details for your system. Users of Debian or Ubuntu simply run--        apt-get install haskell-platform-- 3. Install the development packages for ncurses, i.e.--        apt-get install libncurses5-dev-- 4. Install the Haskell dependencies. The Haskell platform comes with a tool-    called `cabal`, and you should run the two commands--        cabal update-        cabal install --only-dependencies-- 5. Now you can build the program using--        cabal install --bindir=.-- 6. At this point, `tttool` should be ready to go. If you run--        ./tttool--    you should see the list of commands shown above.+We release `tttool` for Windows and Linux users as a zipfile. You can find them+in the [releases section](https://github.com/entropia/tip-toi-reveng/releases)+of the GitHub project. -If you have any problems, you can [report an issue via GitHub](https://github.com/entropia/tip-toi-reveng/issues).+See `Building.md` for instructions on how to build `tttool` from source.  Building your own gme files ---------------------------@@ -174,7 +139,7 @@ ----------------------------------   * [`oid-decoder.html`](http://htmlpreview.github.io/?https://github.com/entropia/tip-toi-reveng/blob/master/oid-decoder.html) allows you to manually decode an OID image.- * `scripts/update.sh` downloads all gme files from the Ravensburger server (requires perl and the [XML::Simple](http://search.cpan.org/~grantm/XML-Simple/) module).  + * `scripts/update.sh` downloads all gme files from the Ravensburger server (requires perl and the [XML::Simple](http://search.cpan.org/~grantm/XML-Simple/) module).     Instead of downloading all of them, you can conveniently browse them at <http://tiptoi.vakat.de/>, a service provided by Falko Oldenburg <tiptoi@vakat.de>.  * `gameanalyse.c` and `libtiptoi.c` is an alternative tool to investigate gme
src/Commands.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP, RecordWildCards, TupleSections #-}+{-# LANGUAGE LambdaCase #-} module Commands where  import qualified Data.ByteString.Lazy as B@@ -12,7 +13,6 @@ import Data.Bits import Data.List import Data.Either-import Data.Functor import Data.Maybe import Data.Function import Data.Ord@@ -63,7 +63,9 @@             map (1,) ttBinaries1 ++             map (2,) ttBinaries2 ++             map (3,) ttBinaries3 ++-            map (4,) ttBinaries4+            map (4,) ttBinaries4 +++            map (5,) ttBinaries5 +++            map (6,) ttBinaries6      printf "Binary Table entries: %d\n" (length binaries) @@ -115,11 +117,14 @@         (length (filter (isNothing . snd) st)) (length st)     printf "Audio table entries: %d\n" (length ttAudioFiles)     when ttAudioFilesDoubles $ printf "Audio table repeated twice\n"-    printf "Binary tables entries: %d/%d/%d/%d\n"+    printf "Binary tables entries: %d/%d/%d\n"         (length ttBinaries1)         (length ttBinaries2)+        (length ttBinaries6)+    printf "Single binary table entries: %d/%d/%d\n"         (length ttBinaries3)         (length ttBinaries4)+        (length ttBinaries5)     for_ ttSpecialOIDs $ \(oid1, oid2) ->         printf "Special OIDs: %d, %d\n" oid1 oid2     printf "Checksum found 0x%08X, calculated 0x%08X\n" ttChecksum ttChecksumCalc@@ -154,7 +159,7 @@ explain file = do     bytes <- B.readFile file     let (tt,segments) = parseTipToiFile bytes-    forM_ (addHoles segments) $ \e -> case e of+    forM_ (addHoles segments) $ \case         Left (o,l) -> do             printSegment (o,l,["-- unknown --"])             printExtract bytes o l@@ -163,6 +168,7 @@             mapM_ printSegment ss             printExtract bytes o l             putStrLn ""+        Right [] -> error "empty list of errors?"  printExtract :: B.ByteString -> Offset -> Word32 -> IO () printExtract b o 0 = return ()@@ -302,7 +308,8 @@     forM_  codes $ \(s,c) -> do         let filename = printf "oid-%d-%s.%s" (ttProductId tt) s (suffixOf format)         let title = printf "%s (product %d code %d)" s (ttProductId tt) c-        writeImage format conf title c filename+        let url   = printf "%s-%d" s c+        writeImage format conf title url c filename  writeImagesForCodes :: Bool -> Conf -> [Word16] -> IO () writeImagesForCodes False conf codes =@@ -310,40 +317,42 @@         let format = fromMaybe PNG (cImageFormat conf)         let filename = printf "oid-%d.%s" c (suffixOf format)         let title = printf "code %d" c-        writeImage format conf title c filename+        let url   = printf "%d" c+        writeImage format conf title url c filename writeImagesForCodes True conf codes =     forM_ codes $ \r -> do         let format = fromMaybe PNG (cImageFormat conf)         let filename = printf "oid-raw-%d.%s" r (suffixOf format)         let title = printf "raw code %d" r+        let url   = printf "raw-%d" r         printf "Writing %s... (raw code %d)\n" filename r-        writeRawImage format conf title r filename+        writeRawImage format conf title url r filename -writeImage :: ImageFormat -> Conf -> String -> Word16 -> FilePath -> IO ()-writeImage format conf title c filename =+writeImage :: ImageFormat -> Conf -> String -> String -> Word16 -> FilePath -> IO ()+writeImage format conf title url c filename =     case code2RawCode c of         Nothing -> printf "Skipping %s, code %d not known.\n" filename c         Just r -> do             printf "Writing %s.. (Code %d, raw code %d)\n" filename c r-            writeRawImage format conf title r filename+            writeRawImage format conf title url r filename -writeRawImage :: ImageFormat -> Conf -> String -> Word16 -> FilePath -> IO ()-writeRawImage PNG conf title raw_code filename =+writeRawImage :: ImageFormat -> Conf -> String -> String -> Word16 -> FilePath -> IO ()+writeRawImage PNG conf title _url raw_code filename =     writeRawPNG w h conf title raw_code filename   where     (w,h) = cCodeDimPixels conf-writeRawImage (SVG usePNG) conf title raw_code filename =-    writeRawSVG conf usePNG title raw_code filename-writeRawImage _ _ _ _ _ =+writeRawImage (SVG usePNG) conf _title url raw_code filename =+    writeRawSVG conf usePNG url raw_code filename+writeRawImage _ _ _ _ _ _ =     hPutStrLn stderr "this command only supports PNG and SVG" >> exitFailure  cCodeDimPixels :: Conf -> (Int, Int) cCodeDimPixels conf = (w',h')   where     (w,h) = cCodeDim conf-    -- (Roughly) 25mm per inch-    w' = (w * cDPI conf) `div` 25-    h' = (h * cDPI conf) `div` 25+    -- 25.4mm per inch+    w' = round $ fromIntegral (w * cDPI conf) / 25.4+    h' = round $ fromIntegral (h * cDPI conf) / 25.4  readTransscriptFile :: Maybe FilePath -> IO Transscript readTransscriptFile Nothing = return M.empty
src/GMEParser.hs view
@@ -7,17 +7,17 @@ import qualified Data.Binary.Get as G import Text.Printf import Data.List-import Data.Functor import Control.Applicative (Applicative, (<*>)) import Data.Maybe import Control.Monad+import Control.Monad.Fail (MonadFail)+import qualified Control.Monad.Fail  import Control.Monad.Writer.Strict import Control.Monad.State.Strict import Control.Monad.Reader import Control.Monad.RWS.Strict import Control.Exception import Control.Arrow-import Debug.Trace  import Types import Constants@@ -28,15 +28,17 @@ newtype SGet a = SGet (RWS B.ByteString [Segment] Word32  a)     deriving (Functor, Applicative, Monad) +instance MonadFail SGet where fail = error+ liftGet :: G.Get a -> SGet a liftGet act = SGet $ do     offset <- get     bytes <- ask-    when (offset > fromIntegral (B.length bytes)) $ do+    when (offset > fromIntegral (B.length bytes)) $         fail $ printf "Trying to read from offset 0x%08X, which is after the end of the file!" offset     let (a, _, i) = G.runGetState act (B.drop (fromIntegral offset) bytes) 0     put (offset + fromIntegral i)-    return $ a+    return a  jumpTo :: Offset -> SGet () jumpTo offset = SGet (put offset)@@ -416,17 +418,21 @@     ttLang <- getBSNul      jumpTo 0x0071-    ttWelcome <- indirection "initial play lists" $ getPlayListList+    ttWelcome <- indirection "initial play lists" getPlayListList      jumpTo 0x0090     ttBinaries1 <- fromMaybe [] <$> maybeIndirection "Binaries 1" getBinaries     ttSpecialOIDs <- maybeIndirection "special symbols" getSpecials-    ttBinaries2 <- fromMaybe [] <$> maybeIndirection "Binaries 1" getBinaries+    ttBinaries2 <- fromMaybe [] <$> maybeIndirection "Binaries 2" getBinaries      jumpTo 0x00A0     ttBinaries3 <- fromMaybe [] <$> maybeIndirection "Single binary 1" getBinaries     getWord32 --ignored     ttBinaries4 <- fromMaybe [] <$> maybeIndirection "Single binary 2" getBinaries++    jumpTo 0x00C8+    ttBinaries5 <- fromMaybe [] <$> maybeIndirection "Single binary 3" getBinaries+    ttBinaries6 <- fromMaybe [] <$> maybeIndirection "Binaries 3" getBinaries      ttChecksum <- getChecksum     ttChecksumCalc <- calcChecksum
src/GMEWriter.hs view
@@ -10,7 +10,6 @@ import qualified Data.Map as M import Control.Monad.Writer.Lazy import Control.Monad.State.Lazy-import Debug.Trace  import Types import Constants
src/KnownCodes.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE QuasiQuotes #-}- module KnownCodes where  import Data.Word
src/OidCode.hs view
@@ -4,15 +4,12 @@  import Data.Word import Data.Bits-import Data.Functor import qualified Data.ByteString.Lazy as B-import Data.Monoid import Control.Monad import Codec.Picture import Codec.Picture.Types import Codec.Picture.Metadata import Control.Monad.ST-import Control.Applicative import Data.Vector.Storable.ByteString import qualified Data.ByteString.Base64.Lazy import qualified Data.Text as T@@ -99,6 +96,7 @@     value 1 = at (-2,2)  plain     value 2 = at (-2,-2) plain     value 3 = at (2,-2)  plain+    value _ = error "value: unexpected param"     special = at (3,0)   plain      position ((n,m), p) = at (n*12, m*12) p@@ -169,6 +167,7 @@     value 1 = at (-s, s) centeredDot     value 2 = at (-s,-s) centeredDot     value 3 = at ( s,-s) centeredDot+    value _ = error "value: unexpected param"     special = at (ss,0)  centeredDot      position ((n,m), p) = at (n*spacePerPoint, m*spacePerPoint) p
src/OidTableSVG.hs view
@@ -2,7 +2,6 @@  import Data.Word import qualified Data.ByteString.Lazy as LB-import Control.Monad hiding (forM_) import Data.Foldable (forM_) import Text.Printf import Control.Arrow ((***))
src/RangeParser.hs view
@@ -1,7 +1,6 @@ module RangeParser (parseRange) where  import Text.Printf-import Data.Functor import Control.Monad import Text.Parsec hiding (Line, lookAhead, spaces) import Text.Parsec.String
src/TipToiYaml.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE RecordWildCards, DeriveGeneric, CPP, TupleSections, TemplateHaskell #-}+{-# LANGUAGE RecordWildCards, DeriveGeneric, CPP, TupleSections #-}  module TipToiYaml     ( tt2ttYaml, ttYaml2tt@@ -17,14 +17,12 @@ import Text.Printf import Data.Char import Data.Either-import Data.Functor import Data.Maybe import Control.Monad import System.Directory import qualified Data.Map as M import qualified Data.Set as S import qualified Data.Vector as V-import Control.Monad.Writer.Strict #if MIN_VERSION_time(1,5,0) import Data.Time.Format (defaultTimeLocale) #else@@ -33,7 +31,6 @@ import Data.Time (getCurrentTime, formatTime) import Data.Yaml hiding ((.=), Parser) import Data.Aeson.Types hiding ((.=), Parser)-import Data.Aeson.TH import Text.Parsec hiding (Line, lookAhead, spaces) import Text.Parsec.String import qualified Text.Parsec as P@@ -256,6 +253,7 @@         , gyExtraPlayLists           :: [PlayListListYaml]         }     | Game253Yaml+    deriving Generic  data SubGameYaml = SubGameYaml     { sgUnknown :: String@@ -264,10 +262,23 @@     , sgOids3 :: OIDListYaml     , sgPlaylist :: [PlayListListYaml]     }+    deriving Generic  -$(deriveJSON gameYamlOptions ''GameYaml)-$(deriveJSON gameYamlOptions ''SubGameYaml)+instance FromJSON GameYaml where+    parseJSON = genericParseJSON gameYamlOptions+instance ToJSON GameYaml where+    toJSON = genericToJSON gameYamlOptions+#if MIN_VERSION_aeson(0,10,0)+    toEncoding = genericToEncoding gameYamlOptions+#endif+instance FromJSON SubGameYaml where+    parseJSON = genericParseJSON gameYamlOptions+instance ToJSON SubGameYaml where+    toJSON = genericToJSON gameYamlOptions+#if MIN_VERSION_aeson(0,10,0)+    toEncoding = genericToEncoding gameYamlOptions+#endif  tipToiYamlOptions = defaultOptions     { fieldLabelModifier = map fix . map toLower . drop 3@@ -860,6 +871,8 @@         , ttBinaries2 = []         , ttBinaries3 = []         , ttBinaries4 = []+        , ttBinaries5 = []+        , ttBinaries6 = []         , ttSpecialOIDs = Nothing         }, totalMap) 
src/Types.hs view
@@ -83,6 +83,8 @@     , ttBinaries2 :: [(B.ByteString, B.ByteString)]     , ttBinaries3 :: [(B.ByteString, B.ByteString)]     , ttBinaries4 :: [(B.ByteString, B.ByteString)]+    , ttBinaries5 :: [(B.ByteString, B.ByteString)]+    , ttBinaries6 :: [(B.ByteString, B.ByteString)]     , ttSpecialOIDs :: Maybe (Word16, Word16)     , ttChecksum :: Word32     , ttChecksumCalc :: Word32
src/Utils.hs view
@@ -1,6 +1,5 @@ module Utils where -import Control.Applicative import Control.Monad (forM, forM_) import Data.Traversable (for) 
src/tttool.hs view
@@ -4,7 +4,6 @@ import Numeric import Data.List (intercalate) import Options.Applicative.Help.Chunk-import Data.Monoid import Data.Maybe import Data.Foldable (asum) import Data.Char (toLower)
tttool.cabal view
@@ -1,30 +1,23 @@ name:                tttool-version:             1.8+version:             1.8.1 synopsis:            Working with files for the Tiptoi® pen description:         The Ravensburger Tiptoi® pen is programmed via special                      files. Their file format has been reverse engineered; this                      is a tool to analyse and create such files.+                     .+                     For more user-facing documentation, see+                     <http://tttool.entropia.de/> (in German). category:            Reverse Engineering homepage:            https://github.com/entropia/tip-toi-reveng license:             MIT license-file:        LICENSE author:              Joachim Breitner maintainer:          mail@joachim-breitner.de-copyright:           2013-2017 Joachim Breitner+copyright:           2013-2019 Joachim Breitner build-type:          Simple-extra-source-files:  README.md+extra-source-files:  README.md Changelog.md cabal-version:       >=1.10 -flag old-locale- description:-   If false then depend on time >= 1.5.-   .-   If true then depend on time < 1.5 together with old-locale.- default: False--Flag bytestring_has_builder-  default: True- executable tttool   main-is:             tttool.hs   other-modules:@@ -51,53 +44,34 @@     Commands,     Utils -  build-depends:-    base        >= 4.5 && < 4.11,-    binary      >= 0.5 && < 0.9,-    containers  == 0.4.*   ||  == 0.5.*,-    directory   >= 1.2 && < 1.4,-    executable-path == 0.0.*,-    filepath    == 1.3.*   ||  == 1.4.*,-    template-haskell >= 2.7 && < 2.13,--    JuicyPixels >= 3.2.5   &&   < 3.3,-    aeson       >= 0.7     &&   < 1.3,-    hashable    == 1.2.*,-    haskeline   == 0.7.*,-    mtl         == 2.1.*   ||  == 2.2.*,-    parsec      == 3.1.*,-    process     >= 1.1      &&   < 1.7,-    random      >= 1.0      &&   < 1.2,-    vector      >= 0.10     &&   < 0.13,-    yaml        == 0.8.*,-    HPDF        >= 1.4.10   && < 1.5,-    split       == 0.2.*,-    optparse-applicative >= 0.13 && < 0.15,-    spool       == 0.1.*,-    zlib        >= 0.5      && < 0.7,-    natural-sort >= 0.1     && < 0.2,-    blaze-svg   == 0.3.*,-    base64-bytestring == 1.0.*,-    text        == 1.2.*--  if impl(ghc < 7.5)-    build-depends: ghc-prim--  ghc-options: -fcontext-stack=42--  if flag(old-locale)-    build-depends: time == 1.4.*, old-locale-  else-    build-depends: time >= 1.5 && < 1.9--  if flag(bytestring_has_builder)-    build-depends:-      bytestring >= 0.10.4 && < 0.11-  else-    build-depends:-      bytestring >= 0.10 && < 0.10.4,-      bytestring-builder >= 0.10.4.1.1-+  build-depends: aeson >= 0.7 && < 1.5+  build-depends: base >= 4.9 && < 4.13+  build-depends: base64-bytestring == 1.0.*+  build-depends: binary >= 0.5 && < 0.9+  build-depends: blaze-svg == 0.3.*+  build-depends: bytestring >= 0.10.4 && < 0.11+  build-depends: containers >= 0.4 && <0.7+  build-depends: directory >= 1.2 && < 1.4+  build-depends: executable-path == 0.0.*+  build-depends: filepath == 1.3.* || == 1.4.*+  build-depends: hashable == 1.2.*+  build-depends: haskeline == 0.7.*+  build-depends: HPDF >= 1.4.10 && < 1.5+  build-depends: JuicyPixels >= 3.2.5 && < 3.4+  build-depends: mtl == 2.2.*+  build-depends: natural-sort >= 0.1 && < 0.2+  build-depends: optparse-applicative >= 0.13 && < 0.15+  build-depends: parsec == 3.1.*+  build-depends: process >= 1.1 && < 1.7+  build-depends: random >= 1.0 && < 1.2+  build-depends: split == 0.2.*+  build-depends: spool == 0.1.*+  build-depends: template-haskell >= 2.7 && < 2.15+  build-depends: text == 1.2.*+  build-depends: time >= 1.5 && < 1.9+  build-depends: vector >= 0.10 && < 0.13+  build-depends: yaml >= 0.8 && < 0.12+  build-depends: zlib >= 0.5 && < 0.7    hs-source-dirs:      src   default-language:    Haskell2010