module Sound.MED.Raw.MMD3 where

import qualified Sound.MED.Raw.MMD2Song as MMD2Song
import Sound.MED.Raw.MMD2Song(MMD2Song)
import qualified Sound.MED.Raw.MMD1Block as MMD1Block
import Sound.MED.Raw.MMD1Block(MMD1Block)
import qualified Sound.MED.Raw.InstrHdr as InstrHdr
import Sound.MED.Raw.InstrHdr(InstrHdr)
import qualified Sound.MED.Raw.MMD0exp as MMD0exp
import Sound.MED.Raw.MMD0exp(MMD0exp)
import Sound.MED.Basic.Amiga

data MMD3 = MMD3
  { id          :: ULONG
  , modlen      :: ULONG
  , song        :: MMD2Song
  , psecnum     :: UWORD
  , pseq        :: UWORD
  , blockarr    :: [ MMD1Block ]
  , mmdflags    :: UBYTE
  , reserved1   :: UBYTE
  , reserved2   :: UBYTE
  , reserved3   :: UBYTE
  , smplarr     :: [ Maybe InstrHdr ]
  , reserved4   :: ULONG
  , expdata     :: Maybe MMD0exp
  , reserved5   :: ULONG
  , pstate      :: UWORD
  , pblock      :: UWORD
  , pline       :: UWORD
  , pseqnum     :: UWORD
  , actplayline :: WORD
  , counter     :: UBYTE
  , extra_songs :: UBYTE
  }
  deriving (Show)

peek :: MEM -> PTR -> IO MMD3
peek m p = do
  id'          <- peekULONG m (p + 0)
  modlen'      <- peekULONG m (p + 4)
  song''       <- peekPTR   m (p + 8)
  song'        <- MMD2Song.peek m song''
  psecnum'     <- peekUWORD m (p + 12)
  pseq'        <- peekUWORD m (p + 14)
  blockarr'''  <- peekPTR   m (p + 16)
  blockarr''   <- mapM (peekPTR m) $ pointerRangeGen blockarr''' 4 (MMD2Song.numblocks song')
  blockarr'    <- mapM (MMD1Block.peek m) blockarr''
  mmdflags'    <- peekUBYTE m (p + 20)
  reserved1'   <- peekUBYTE m (p + 21)
  reserved2'   <- peekUBYTE m (p + 22)
  reserved3'   <- peekUBYTE m (p + 23)
  smplarr'''   <- peekPTR   m (p + 24)
  smplarr''    <- mapM (peekPTR m) $ pointerRangeGenCheck smplarr''' 4 (MMD2Song.numsamples song')
  smplarr'     <- mapM (InstrHdr.peek m $?) smplarr''
  reserved4'   <- peekULONG m (p + 28)
  expdata'''   <- peekPTR   m (p + 32)
  expdata'     <- MMD0exp.peek m $? expdata'''
  reserved5'   <- peekULONG m (p + 36)
  pstate'      <- peekUWORD m (p + 40)
  pblock'      <- peekUWORD m (p + 42)
  pline'       <- peekUWORD m (p + 44)
  pseqnum'     <- peekUWORD m (p + 46)
  actplayline' <- peekWORD  m (p + 48)
  counter'     <- peekUBYTE m (p + 50)
  extra_songs' <- peekUBYTE m (p + 51)
  return $ MMD3
    id' modlen' song' psecnum' pseq' blockarr' mmdflags'
    reserved1' reserved2' reserved3' smplarr' reserved4'
    expdata' reserved5' pstate' pblock' pline' pseqnum'
    actplayline' counter' extra_songs'