module Nes.APU.Tick (
    -- * Ticking
    -- $semantic
    tick,
    tickOnce,
    IsAPUCycle,

    -- * Internal ticking
    tickFrameCounter,
    runHalfFrameEvent,
    runQuarterFrameEvent,
    setFrameInterruptFlag,
) where

import Control.Monad
import Control.Monad.IO.Class
import Nes.APU.Mixer
import Nes.APU.Monad
import Nes.APU.State
import Nes.APU.State.DMC
import Nes.APU.State.Envelope
import Nes.APU.State.Filter.Thread
import Nes.APU.State.FrameCounter
import qualified Nes.APU.State.FrameCounter as FC
import Nes.APU.State.LengthCounter
import Nes.APU.State.Noise
import Nes.APU.State.Pulse
import Nes.APU.State.Triangle
import Nes.Internal.MonadState
import Nes.Interrupt
import Prelude hiding (cycle)

-- $semantic
--     The APU being a part of the CPU, they both tick at the same time. However, some ticks are updated every other CPU cycles.
--     Here the 'tick' function should be called every CPU tick, and pass as parameter whether the tick is on an even CPU cycle or not.
--     Same goes for 'tickMany'.

type IsAPUCycle = Bool

-- | Calls 'tick' n amount of time
--
-- the first parameter says whether the first tick is an APU cycle or not
tick :: IsAPUCycle -> Int -> APU r ()
tick :: forall r. IsAPUCycle -> Int -> APU r ()
tick IsAPUCycle
_ Int
0 = () -> APU r ()
forall a. a -> APU r a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
tick IsAPUCycle
b Int
n = IsAPUCycle -> APU r ()
forall r. IsAPUCycle -> APU r ()
tickOnce IsAPUCycle
b APU r () -> APU r () -> APU r ()
forall a b. APU r a -> APU r b -> APU r b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IsAPUCycle -> Int -> APU r ()
forall r. IsAPUCycle -> Int -> APU r ()
tick (IsAPUCycle -> IsAPUCycle
not IsAPUCycle
b) (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

{-# INLINE tickOnce #-}
tickOnce :: IsAPUCycle -> APU r ()
tickOnce :: forall r. IsAPUCycle -> APU r ()
tickOnce IsAPUCycle
isAPUCycle = do
    -- Ticks
    APU r ()
forall r. APU r ()
tickDelayedWriteBuffer
    (DMC -> InterruptStatus -> (DMC, InterruptStatus)) -> APU r ()
forall r.
(DMC -> InterruptStatus -> (DMC, InterruptStatus)) -> APU r ()
modifyDMCAndInterrupt DMC -> InterruptStatus -> (DMC, InterruptStatus)
tickDMC
    (Triangle -> Identity Triangle) -> APUState -> Identity APUState
Lens' APUState Triangle
triangle ((Triangle -> Identity Triangle) -> APUState -> Identity APUState)
-> (Triangle -> Triangle) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= Triangle -> Triangle
tickTriangle
    (Noise -> Identity Noise) -> APUState -> Identity APUState
Lens' APUState Noise
noise ((Noise -> Identity Noise) -> APUState -> Identity APUState)
-> (Noise -> Noise) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= Noise -> Noise
tickNoise
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when IsAPUCycle
isAPUCycle (APU r () -> APU r ()) -> APU r () -> APU r ()
forall a b. (a -> b) -> a -> b
$ do
        (Pulse -> Identity Pulse) -> APUState -> Identity APUState
Lens' APUState Pulse
pulse1 ((Pulse -> Identity Pulse) -> APUState -> Identity APUState)
-> (Pulse -> Pulse) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= Pulse -> Pulse
tickPulse
        (Pulse -> Identity Pulse) -> APUState -> Identity APUState
Lens' APUState Pulse
pulse2 ((Pulse -> Identity Pulse) -> APUState -> Identity APUState)
-> (Pulse -> Pulse) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= Pulse -> Pulse
tickPulse
        APU r ()
forall r. APU r ()
tickFrameCounter
    -- Mixing
    Float
sample <- (APUState -> Float) -> APU r Float
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets APUState -> Float
getMixerOutput
    IO () -> APU r ()
forall a. IO a -> APU r a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> APU r ())
-> (FilterThread -> IO ()) -> FilterThread -> APU r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilterThread -> Float -> IO ()
`consumeSample` Float
sample) (FilterThread -> APU r ()) -> APU r FilterThread -> APU r ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Getting FilterThread APUState FilterThread -> APU r FilterThread
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting FilterThread APUState FilterThread
Lens' APUState FilterThread
filterThread
    (Float -> Identity Float) -> APUState -> Identity APUState
Lens' APUState Float
sampleTimer ((Float -> Identity Float) -> APUState -> Identity APUState)
-> Float -> APU r ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
+= (-Float
1)
    Float
sampleTimer' <- Getting Float APUState Float -> APU r Float
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting Float APUState Float
Lens' APUState Float
sampleTimer
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (Float
sampleTimer' Float -> Float -> IsAPUCycle
forall a. Ord a => a -> a -> IsAPUCycle
<= Float
1) (APU r () -> APU r ()) -> APU r () -> APU r ()
forall a b. (a -> b) -> a -> b
$ do
        !Float
filterOut <- IO Float -> APU r Float
forall a. IO a -> APU r a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Float -> APU r Float)
-> (FilterThread -> IO Float) -> FilterThread -> APU r Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilterThread -> IO Float
outputSample (FilterThread -> APU r Float) -> APU r FilterThread -> APU r Float
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Getting FilterThread APUState FilterThread -> APU r FilterThread
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting FilterThread APUState FilterThread
Lens' APUState FilterThread
filterThread
        !Float -> IO ()
callback <- Getting (Float -> IO ()) APUState (Float -> IO ())
-> APU r (Float -> IO ())
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting (Float -> IO ()) APUState (Float -> IO ())
Lens' APUState (Float -> IO ())
pushSampleCallback
        IO () -> APU r ()
forall a. IO a -> APU r a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> APU r ()) -> IO () -> APU r ()
forall a b. (a -> b) -> a -> b
$ Float -> IO ()
callback Float
filterOut
        ((Float -> Identity Float) -> APUState -> Identity APUState
Lens' APUState Float
sampleTimer ((Float -> Identity Float) -> APUState -> Identity APUState)
-> Float -> APU r ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
+=) (Float -> APU r ()) -> APU r Float -> APU r ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Getting Float APUState Float -> APU r Float
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting Float APUState Float
Lens' APUState Float
samplePeriod
    (Int -> Identity Int) -> APUState -> Identity APUState
Lens' APUState Int
cycle ((Int -> Identity Int) -> APUState -> Identity APUState)
-> Int -> APU r ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
+= Int
1

-- | Tells the frame counter to tick channels
--
-- Source: https://www.nesdev.org/wiki/APU_Frame_Counter
tickFrameCounter :: APU r ()
tickFrameCounter :: forall r. APU r ()
tickFrameCounter = do
    IsAPUCycle
reset <- Getting FrameCounter APUState FrameCounter
-> (FrameCounter -> IsAPUCycle) -> APU r IsAPUCycle
forall s (m :: * -> *) a r.
MonadState s m =>
Getting a s a -> (a -> r) -> m r
uses Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter FrameCounter -> IsAPUCycle
shouldResetSequenceStep
    SequenceMode
seqMode <- Getting FrameCounter APUState FrameCounter
-> (FrameCounter -> SequenceMode) -> APU r SequenceMode
forall s (m :: * -> *) a r.
MonadState s m =>
Getting a s a -> (a -> r) -> m r
uses Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter FrameCounter -> SequenceMode
sequenceMode
    if IsAPUCycle
reset
        then APU r ()
forall r. APU r ()
resetFrameCounterSequence
        else do
            FrameCounter
fc <- Getting FrameCounter APUState FrameCounter -> APU r FrameCounter
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter
            IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (FrameCounter -> IsAPUCycle
shouldIncrementSequenceStep FrameCounter
fc) (APU r () -> APU r ()) -> APU r () -> APU r ()
forall a b. (a -> b) -> a -> b
$ do
                case SequenceMode
seqMode of
                    SequenceMode
FourStep -> APU r ()
forall r. APU r ()
tickFrameCounterFourStep
                    SequenceMode
FiveStep -> APU r ()
forall r. APU r ()
tickFrameCounterFiveStep
                (FrameCounter -> Identity FrameCounter)
-> APUState -> Identity APUState
Lens' APUState FrameCounter
frameCounter ((FrameCounter -> Identity FrameCounter)
 -> APUState -> Identity APUState)
-> (FrameCounter -> FrameCounter) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= FrameCounter -> FrameCounter
incrementSequenceStep
            (FrameCounter -> Identity FrameCounter)
-> APUState -> Identity APUState
Lens' APUState FrameCounter
frameCounter ((FrameCounter -> Identity FrameCounter)
 -> APUState -> Identity APUState)
-> (FrameCounter -> FrameCounter) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= \FrameCounter
f -> FrameCounter
f{cycles = 1 + cycles f}

tickDelayedWriteBuffer :: APU r ()
tickDelayedWriteBuffer :: forall r. APU r ()
tickDelayedWriteBuffer = do
    FrameCounter
fc <- Getting FrameCounter APUState FrameCounter -> APU r FrameCounter
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter
    case FrameCounter -> Maybe Int
delayedWriteSideEffectCycle FrameCounter
fc of
        Maybe Int
Nothing -> () -> APU r ()
forall a. a -> APU r a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Just Int
0 ->
            (FrameCounter -> Identity FrameCounter)
-> APUState -> Identity APUState
Lens' APUState FrameCounter
frameCounter
                ((FrameCounter -> Identity FrameCounter)
 -> APUState -> Identity APUState)
-> (FrameCounter -> FrameCounter) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= FrameCounter -> FrameCounter -> FrameCounter
forall a b. a -> b -> a
const FrameCounter
fc{delayedWriteSideEffectCycle = Nothing, FC.sequenceStep = 0, cycles = 0}
        Just Int
n ->
            (FrameCounter -> Identity FrameCounter)
-> APUState -> Identity APUState
Lens' APUState FrameCounter
frameCounter
                ((FrameCounter -> Identity FrameCounter)
 -> APUState -> Identity APUState)
-> (FrameCounter -> FrameCounter) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= FrameCounter -> FrameCounter -> FrameCounter
forall a b. a -> b -> a
const FrameCounter
fc{delayedWriteSideEffectCycle = Just $ n - 1}

resetFrameCounterSequence :: APU r ()
resetFrameCounterSequence :: forall r. APU r ()
resetFrameCounterSequence = do
    (FrameCounter -> Identity FrameCounter)
-> APUState -> Identity APUState
Lens' APUState FrameCounter
frameCounter ((FrameCounter -> Identity FrameCounter)
 -> APUState -> Identity APUState)
-> (FrameCounter -> FrameCounter) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= FrameCounter -> FrameCounter
resetSequence
    SequenceMode
seqMode <- Getting FrameCounter APUState FrameCounter
-> (FrameCounter -> SequenceMode) -> APU r SequenceMode
forall s (m :: * -> *) a r.
MonadState s m =>
Getting a s a -> (a -> r) -> m r
uses Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter FrameCounter -> SequenceMode
sequenceMode
    IsAPUCycle
inhibitFrameInterrupt <- Getting FrameCounter APUState FrameCounter
-> (FrameCounter -> IsAPUCycle) -> APU r IsAPUCycle
forall s (m :: * -> *) a r.
MonadState s m =>
Getting a s a -> (a -> r) -> m r
uses Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter FrameCounter -> IsAPUCycle
inhibitInterrupt
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (SequenceMode
seqMode SequenceMode -> SequenceMode -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
== SequenceMode
FourStep IsAPUCycle -> IsAPUCycle -> IsAPUCycle
&& IsAPUCycle -> IsAPUCycle
not IsAPUCycle
inhibitFrameInterrupt) (APU r () -> APU r ()) -> APU r () -> APU r ()
forall a b. (a -> b) -> a -> b
$ do
        IsAPUCycle -> APU r ()
forall r. IsAPUCycle -> APU r ()
setFrameInterruptFlag IsAPUCycle
True

tickFrameCounterFourStep :: APU r ()
tickFrameCounterFourStep :: forall r. APU r ()
tickFrameCounterFourStep = do
    Int
step <- Getting FrameCounter APUState FrameCounter
-> (FrameCounter -> Int) -> APU r Int
forall s (m :: * -> *) a r.
MonadState s m =>
Getting a s a -> (a -> r) -> m r
uses Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter FrameCounter -> Int
FC.sequenceStep
    IsAPUCycle
inhibitFrameInterrupt <- Getting FrameCounter APUState FrameCounter
-> (FrameCounter -> IsAPUCycle) -> APU r IsAPUCycle
forall s (m :: * -> *) a r.
MonadState s m =>
Getting a s a -> (a -> r) -> m r
uses Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter FrameCounter -> IsAPUCycle
inhibitInterrupt
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (Int
step Int -> Int -> IsAPUCycle
forall a. Ord a => a -> a -> IsAPUCycle
< Int
4) APU r ()
forall r. APU r ()
runQuarterFrameEvent
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (Int
step Int -> Int -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
== Int
1 IsAPUCycle -> IsAPUCycle -> IsAPUCycle
|| Int
step Int -> Int -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
== Int
3) APU r ()
forall r. APU r ()
runHalfFrameEvent
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (Int
step Int -> Int -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
== Int
4) (APU r () -> APU r ()) -> APU r () -> APU r ()
forall a b. (a -> b) -> a -> b
$ -- Flag should be cleared when going from put to get
        IsAPUCycle -> APU r ()
forall r. IsAPUCycle -> APU r ()
setFrameInterruptFlag IsAPUCycle
False
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (Int
step Int -> Int -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
== Int
3 IsAPUCycle -> IsAPUCycle -> IsAPUCycle
&& IsAPUCycle -> IsAPUCycle
not IsAPUCycle
inhibitFrameInterrupt) (APU r () -> APU r ()) -> APU r () -> APU r ()
forall a b. (a -> b) -> a -> b
$
        IsAPUCycle -> APU r ()
forall r. IsAPUCycle -> APU r ()
setFrameInterruptFlag IsAPUCycle
True

tickFrameCounterFiveStep :: APU r ()
tickFrameCounterFiveStep :: forall r. APU r ()
tickFrameCounterFiveStep = do
    Int
step <- Getting FrameCounter APUState FrameCounter
-> (FrameCounter -> Int) -> APU r Int
forall s (m :: * -> *) a r.
MonadState s m =>
Getting a s a -> (a -> r) -> m r
uses Getting FrameCounter APUState FrameCounter
Lens' APUState FrameCounter
frameCounter FrameCounter -> Int
FC.sequenceStep
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (Int
step Int -> Int -> IsAPUCycle
forall a. Ord a => a -> a -> IsAPUCycle
< Int
5 IsAPUCycle -> IsAPUCycle -> IsAPUCycle
&& Int
step Int -> Int -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
/= Int
3) APU r ()
forall r. APU r ()
runQuarterFrameEvent
    IsAPUCycle -> APU r () -> APU r ()
forall (f :: * -> *). Applicative f => IsAPUCycle -> f () -> f ()
when (Int
step Int -> Int -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
== Int
1 IsAPUCycle -> IsAPUCycle -> IsAPUCycle
|| Int
step Int -> Int -> IsAPUCycle
forall a. Eq a => a -> a -> IsAPUCycle
== Int
4) APU r ()
forall r. APU r ()
runHalfFrameEvent

runQuarterFrameEvent :: APU r ()
runQuarterFrameEvent :: forall r. APU r ()
runQuarterFrameEvent = do
    (Pulse -> Identity Pulse) -> APUState -> Identity APUState
Lens' APUState Pulse
pulse1 ((Pulse -> Identity Pulse) -> APUState -> Identity APUState)
-> (Pulse -> Pulse) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= (Envelope -> Envelope) -> Pulse -> Pulse
forall a. HasEnvelope a => (Envelope -> Envelope) -> a -> a
withEnvelope Envelope -> Envelope
tickEnvelope
    (Pulse -> Identity Pulse) -> APUState -> Identity APUState
Lens' APUState Pulse
pulse2 ((Pulse -> Identity Pulse) -> APUState -> Identity APUState)
-> (Pulse -> Pulse) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= (Envelope -> Envelope) -> Pulse -> Pulse
forall a. HasEnvelope a => (Envelope -> Envelope) -> a -> a
withEnvelope Envelope -> Envelope
tickEnvelope
    (Noise -> Identity Noise) -> APUState -> Identity APUState
Lens' APUState Noise
noise ((Noise -> Identity Noise) -> APUState -> Identity APUState)
-> (Noise -> Noise) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= (Envelope -> Envelope) -> Noise -> Noise
forall a. HasEnvelope a => (Envelope -> Envelope) -> a -> a
withEnvelope Envelope -> Envelope
tickEnvelope
    (Triangle -> Identity Triangle) -> APUState -> Identity APUState
Lens' APUState Triangle
triangle ((Triangle -> Identity Triangle) -> APUState -> Identity APUState)
-> (Triangle -> Triangle) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= Triangle -> Triangle
tickTriangleLinearCounter

runHalfFrameEvent :: APU r ()
runHalfFrameEvent :: forall r. APU r ()
runHalfFrameEvent = do
    (Pulse -> Identity Pulse) -> APUState -> Identity APUState
Lens' APUState Pulse
pulse1 ((Pulse -> Identity Pulse) -> APUState -> Identity APUState)
-> (Pulse -> Pulse) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= ((LengthCounter -> LengthCounter) -> Pulse -> Pulse
forall a.
HasLengthCounter a =>
(LengthCounter -> LengthCounter) -> a -> a
withLengthCounter LengthCounter -> LengthCounter
tickLengthCounter (Pulse -> Pulse) -> (Pulse -> Pulse) -> Pulse -> Pulse
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pulse -> Pulse
tickSweepUnit)
    (Pulse -> Identity Pulse) -> APUState -> Identity APUState
Lens' APUState Pulse
pulse2 ((Pulse -> Identity Pulse) -> APUState -> Identity APUState)
-> (Pulse -> Pulse) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= ((LengthCounter -> LengthCounter) -> Pulse -> Pulse
forall a.
HasLengthCounter a =>
(LengthCounter -> LengthCounter) -> a -> a
withLengthCounter LengthCounter -> LengthCounter
tickLengthCounter (Pulse -> Pulse) -> (Pulse -> Pulse) -> Pulse -> Pulse
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pulse -> Pulse
tickSweepUnit)
    (Noise -> Identity Noise) -> APUState -> Identity APUState
Lens' APUState Noise
noise ((Noise -> Identity Noise) -> APUState -> Identity APUState)
-> (Noise -> Noise) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= (LengthCounter -> LengthCounter) -> Noise -> Noise
forall a.
HasLengthCounter a =>
(LengthCounter -> LengthCounter) -> a -> a
withLengthCounter LengthCounter -> LengthCounter
tickLengthCounter
    (Triangle -> Identity Triangle) -> APUState -> Identity APUState
Lens' APUState Triangle
triangle ((Triangle -> Identity Triangle) -> APUState -> Identity APUState)
-> (Triangle -> Triangle) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= (LengthCounter -> LengthCounter) -> Triangle -> Triangle
forall a.
HasLengthCounter a =>
(LengthCounter -> LengthCounter) -> a -> a
withLengthCounter LengthCounter -> LengthCounter
tickLengthCounter

-- | Set the Frame Counter's Frame flag
{-# INLINE setFrameInterruptFlag #-}
setFrameInterruptFlag :: Bool -> APU r ()
setFrameInterruptFlag :: forall r. IsAPUCycle -> APU r ()
setFrameInterruptFlag IsAPUCycle
b = do
    (InterruptStatus -> InterruptStatus) -> APU r ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((InterruptStatus -> InterruptStatus) -> APU r ())
-> (InterruptStatus -> InterruptStatus) -> APU r ()
forall a b. (a -> b) -> a -> b
$ \InterruptStatus
s -> InterruptStatus
s{irq = Just FrameCounter}
    (FrameCounter -> Identity FrameCounter)
-> APUState -> Identity APUState
Lens' APUState FrameCounter
frameCounter ((FrameCounter -> Identity FrameCounter)
 -> APUState -> Identity APUState)
-> (FrameCounter -> FrameCounter) -> APU r ()
forall s (m :: * -> *) a.
MonadState s m =>
ASetter' s a -> (a -> a) -> m ()
%= \FrameCounter
fc -> FrameCounter
fc{frameInterruptFlag = b}