From 8c253f2cc441cc436e9ca59056e38f9859d6c35e Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Tue, 29 Nov 2022 14:07:51 +0100 Subject: [PATCH] improved inlining in VS (I hope this doesn't break the code again) --- src/emucore/tia/Ball.hxx | 150 ++++++++++++++++------------------ src/emucore/tia/Missile.hxx | 128 ++++++++++++++--------------- src/emucore/tia/Player.hxx | 131 +++++++++++++++-------------- src/emucore/tia/Playfield.hxx | 55 ++++++------- src/emucore/tia/TIA.cxx | 4 +- 5 files changed, 222 insertions(+), 246 deletions(-) diff --git a/src/emucore/tia/Ball.hxx b/src/emucore/tia/Ball.hxx index dd6cf8d1f..6750687c8 100644 --- a/src/emucore/tia/Ball.hxx +++ b/src/emucore/tia/Ball.hxx @@ -165,14 +165,80 @@ class Ball : public Serializable bool load(Serializer& in) override; /** - Process a single movement tick. Inline for performance (implementation below). + Process a single movement tick. Inline for performance. */ - FORCE_INLINE void movementTick(uInt32 clock, bool hblank); + FORCE_INLINE void movementTick(uInt32 clock, bool hblank) + { + myLastMovementTick = myCounter; + + // Stop movement once the number of clocks according to HMBL is reached + if (clock == myHmmClocks) + isMoving = false; + + if(isMoving) + { + // Process the tick if we are in hblank. Otherwise, the tick is either masked + // by an ordinary tick or merges two consecutive ticks into a single tick (inverted + // movement clock phase mode). + if (hblank) tick(false); + + // Track a tick outside hblank for later processing + myInvertedPhaseClock = !hblank; + } + } /** - Tick one color clock. Inline for performance (implementation below). + Tick one color clock. Inline for performance. */ - FORCE_INLINE void tick(bool isReceivingRegularClock = true); + FORCE_INLINE void tick(bool isReceivingRegularClock = true) + { + // If we are in inverted movement clock phase mode and a movement tick occurred, it + // will supress the tick. + if(myUseInvertedPhaseClock && myInvertedPhaseClock) + { + myInvertedPhaseClock = false; + return; + } + + // Turn on the signal if the render counter reaches the threshold + mySignalActive = myIsRendering && myRenderCounter >= 0; + + // Consider enabled status and the signal to determine visibility (as represented + // by the collision mask) + collision = (mySignalActive && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled; + + // Regular clock pulse during movement -> starfield mode + const bool starfieldEffect = isMoving && isReceivingRegularClock; + + // Decode value that triggers rendering + if (myCounter == 156) { + myIsRendering = true; + myRenderCounter = renderCounterOffset; + + // What follows is an effective description of ball width in starfield mode. + const uInt8 starfieldDelta = (myCounter + TIAConstants::H_PIXEL - myLastMovementTick) % 4; + if (starfieldEffect && starfieldDelta == 3 && myWidth < 4) ++myRenderCounter; + + switch (starfieldDelta) { + case 3: + myEffectiveWidth = myWidth == 1 ? 2 : myWidth; + break; + + case 2: + myEffectiveWidth = 0; + break; + + default: + myEffectiveWidth = myWidth; + break; + } + + } else if (myIsRendering && ++myRenderCounter >= (starfieldEffect ? myEffectiveWidth : myWidth)) + myIsRendering = false; + + if (++myCounter >= TIAConstants::H_PIXEL) + myCounter = 0; + } public: @@ -336,80 +402,4 @@ class Ball : public Serializable Ball& operator=(Ball&&) = delete; }; -// ############################################################################ -// Implementation -// ############################################################################ - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FORCE_INLINE void Ball::movementTick(uInt32 clock, bool hblank) -{ - myLastMovementTick = myCounter; - - // Stop movement once the number of clocks according to HMBL is reached - if (clock == myHmmClocks) - isMoving = false; - - if(isMoving) - { - // Process the tick if we are in hblank. Otherwise, the tick is either masked - // by an ordinary tick or merges two consecutive ticks into a single tick (inverted - // movement clock phase mode). - if (hblank) tick(false); - - // Track a tick outside hblank for later processing - myInvertedPhaseClock = !hblank; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FORCE_INLINE void Ball::tick(bool isReceivingRegularClock) -{ - // If we are in inverted movement clock phase mode and a movement tick occurred, it - // will supress the tick. - if(myUseInvertedPhaseClock && myInvertedPhaseClock) - { - myInvertedPhaseClock = false; - return; - } - - // Turn on the signal if the render counter reaches the threshold - mySignalActive = myIsRendering && myRenderCounter >= 0; - - // Consider enabled status and the signal to determine visibility (as represented - // by the collision mask) - collision = (mySignalActive && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled; - - // Regular clock pulse during movement -> starfield mode - const bool starfieldEffect = isMoving && isReceivingRegularClock; - - // Decode value that triggers rendering - if (myCounter == 156) { - myIsRendering = true; - myRenderCounter = renderCounterOffset; - - // What follows is an effective description of ball width in starfield mode. - const uInt8 starfieldDelta = (myCounter + TIAConstants::H_PIXEL - myLastMovementTick) % 4; - if (starfieldEffect && starfieldDelta == 3 && myWidth < 4) ++myRenderCounter; - - switch (starfieldDelta) { - case 3: - myEffectiveWidth = myWidth == 1 ? 2 : myWidth; - break; - - case 2: - myEffectiveWidth = 0; - break; - - default: - myEffectiveWidth = myWidth; - break; - } - - } else if (myIsRendering && ++myRenderCounter >= (starfieldEffect ? myEffectiveWidth : myWidth)) - myIsRendering = false; - - if (++myCounter >= TIAConstants::H_PIXEL) - myCounter = 0; -} - #endif // TIA_BALL diff --git a/src/emucore/tia/Missile.hxx b/src/emucore/tia/Missile.hxx index a860bd23b..6638ea937 100644 --- a/src/emucore/tia/Missile.hxx +++ b/src/emucore/tia/Missile.hxx @@ -76,9 +76,69 @@ class Missile : public Serializable bool save(Serializer& out) const override; bool load(Serializer& in) override; - FORCE_INLINE void movementTick(uInt8 clock, uInt8 hclock, bool hblank); + /** + Process a single movement tick. Inline for performance. + */ + FORCE_INLINE void movementTick(uInt8 clock, uInt8 hclock, bool hblank) + { + if(clock == myHmmClocks) isMoving = false; - FORCE_INLINE void tick(uInt8 hclock, bool isReceivingMclock = true); + if (isMoving) + { + if (hblank) tick(hclock, false); + myInvertedPhaseClock = !hblank; + } + } + + /** + Tick one color clock. Inline for performance. + */ + FORCE_INLINE void tick(uInt8 hclock, bool isReceivingMclock = true) + { + if(myUseInvertedPhaseClock && myInvertedPhaseClock) + { + myInvertedPhaseClock = false; + return; + } + + myIsVisible = + myIsRendering && + (myRenderCounter >= 0 || (isMoving && isReceivingMclock && myRenderCounter == -1 && myWidth < 4 && ((hclock + 1) % 4 == 3))); + + collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled; + + if (myDecodes[myCounter] && !myResmp) { + myIsRendering = true; + myRenderCounter = renderCounterOffset; + myCopy = myDecodes[myCounter]; + } else if (myIsRendering) { + + if (myRenderCounter == -1) { + if (isMoving && isReceivingMclock) { + switch ((hclock + 1) % 4) { + case 3: + myEffectiveWidth = myWidth == 1 ? 2 : myWidth; + if (myWidth < 4) ++myRenderCounter; + break; + + case 2: + myEffectiveWidth = 0; + break; + + default: + myEffectiveWidth = myWidth; + break; + } + } else { + myEffectiveWidth = myWidth; + } + } + + if (++myRenderCounter >= (isMoving ? myEffectiveWidth : myWidth)) myIsRendering = false; + } + + if (++myCounter >= TIAConstants::H_PIXEL) myCounter = 0; + } public: @@ -136,68 +196,4 @@ class Missile : public Serializable Missile& operator=(Missile&&) = delete; }; -// ############################################################################ -// Implementation -// ############################################################################ - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FORCE_INLINE void Missile::movementTick(uInt8 clock, uInt8 hclock, bool hblank) -{ - if(clock == myHmmClocks) isMoving = false; - - if (isMoving) - { - if (hblank) tick(hclock, false); - myInvertedPhaseClock = !hblank; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FORCE_INLINE void Missile::tick(uInt8 hclock, bool isReceivingMclock) -{ - if(myUseInvertedPhaseClock && myInvertedPhaseClock) - { - myInvertedPhaseClock = false; - return; - } - - myIsVisible = - myIsRendering && - (myRenderCounter >= 0 || (isMoving && isReceivingMclock && myRenderCounter == -1 && myWidth < 4 && ((hclock + 1) % 4 == 3))); - - collision = (myIsVisible && myIsEnabled) ? myCollisionMaskEnabled : myCollisionMaskDisabled; - - if (myDecodes[myCounter] && !myResmp) { - myIsRendering = true; - myRenderCounter = renderCounterOffset; - myCopy = myDecodes[myCounter]; - } else if (myIsRendering) { - - if (myRenderCounter == -1) { - if (isMoving && isReceivingMclock) { - switch ((hclock + 1) % 4) { - case 3: - myEffectiveWidth = myWidth == 1 ? 2 : myWidth; - if (myWidth < 4) ++myRenderCounter; - break; - - case 2: - myEffectiveWidth = 0; - break; - - default: - myEffectiveWidth = myWidth; - break; - } - } else { - myEffectiveWidth = myWidth; - } - } - - if (++myRenderCounter >= (isMoving ? myEffectiveWidth : myWidth)) myIsRendering = false; - } - - if (++myCounter >= TIAConstants::H_PIXEL) myCounter = 0; -} - #endif // TIA_MISSILE diff --git a/src/emucore/tia/Player.hxx b/src/emucore/tia/Player.hxx index c42fed515..b30b31d58 100644 --- a/src/emucore/tia/Player.hxx +++ b/src/emucore/tia/Player.hxx @@ -87,9 +87,71 @@ class Player : public Serializable bool save(Serializer& out) const override; bool load(Serializer& in) override; - FORCE_INLINE void movementTick(uInt32 clock, bool hblank); + /** + Process a single movement tick. Inline for performance. + */ + FORCE_INLINE void movementTick(uInt32 clock, bool hblank) + { + if (clock == myHmmClocks) + isMoving = false; + + if(isMoving) + { + if (hblank) tick(); + myInvertedPhaseClock = !hblank; + } + } + + /** + Tick one color clock. Inline for performance. + */ + FORCE_INLINE void tick() + { + if(myUseInvertedPhaseClock && myInvertedPhaseClock) + { + myInvertedPhaseClock = false; + return; + } + + if (!myIsRendering || myRenderCounter < myRenderCounterTripPoint) + collision = myCollisionMaskDisabled; + else + collision = (myPattern & (1 << mySampleCounter)) ? myCollisionMaskEnabled : myCollisionMaskDisabled; + + if (myDecodes[myCounter]) { + myIsRendering = true; + mySampleCounter = 0; + myRenderCounter = renderCounterOffset; + myCopy = myDecodes[myCounter]; + } else if (myIsRendering) { + ++myRenderCounter; + + switch (myDivider) { + case 1: + if (myRenderCounter > 0) + ++mySampleCounter; + + if (myRenderCounter >= 0 && myDividerChangeCounter >= 0 && myDividerChangeCounter-- == 0) + setDivider(myDividerPending); + + break; + + default: + if (myRenderCounter > 1 && (((myRenderCounter - 1) % myDivider) == 0)) + ++mySampleCounter; + + if (myRenderCounter > 0 && myDividerChangeCounter >= 0 && myDividerChangeCounter-- == 0) + setDivider(myDividerPending); + + break; + } + + if (mySampleCounter > 7) myIsRendering = false; + } + + if (++myCounter >= TIAConstants::H_PIXEL) myCounter = 0; + } - FORCE_INLINE void tick(); public: @@ -152,69 +214,4 @@ class Player : public Serializable Player& operator=(Player&&) = delete; }; -// ############################################################################ -// Implementation -// ############################################################################ - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FORCE_INLINE void Player::movementTick(uInt32 clock, bool hblank) -{ - if (clock == myHmmClocks) - isMoving = false; - - if(isMoving) - { - if (hblank) tick(); - myInvertedPhaseClock = !hblank; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FORCE_INLINE void Player::tick() -{ - if(myUseInvertedPhaseClock && myInvertedPhaseClock) - { - myInvertedPhaseClock = false; - return; - } - - if (!myIsRendering || myRenderCounter < myRenderCounterTripPoint) - collision = myCollisionMaskDisabled; - else - collision = (myPattern & (1 << mySampleCounter)) ? myCollisionMaskEnabled : myCollisionMaskDisabled; - - if (myDecodes[myCounter]) { - myIsRendering = true; - mySampleCounter = 0; - myRenderCounter = renderCounterOffset; - myCopy = myDecodes[myCounter]; - } else if (myIsRendering) { - ++myRenderCounter; - - switch (myDivider) { - case 1: - if (myRenderCounter > 0) - ++mySampleCounter; - - if (myRenderCounter >= 0 && myDividerChangeCounter >= 0 && myDividerChangeCounter-- == 0) - setDivider(myDividerPending); - - break; - - default: - if (myRenderCounter > 1 && (((myRenderCounter - 1) % myDivider) == 0)) - ++mySampleCounter; - - if (myRenderCounter > 0 && myDividerChangeCounter >= 0 && myDividerChangeCounter-- == 0) - setDivider(myDividerPending); - - break; - } - - if (mySampleCounter > 7) myIsRendering = false; - } - - if (++myCounter >= TIAConstants::H_PIXEL) myCounter = 0; -} - #endif // TIA_PLAYER diff --git a/src/emucore/tia/Playfield.hxx b/src/emucore/tia/Playfield.hxx index 763712fe2..d9e416770 100644 --- a/src/emucore/tia/Playfield.hxx +++ b/src/emucore/tia/Playfield.hxx @@ -132,9 +132,31 @@ class Playfield : public Serializable bool load(Serializer& in) override; /** - Tick one color clock. Inline for performance (implementation below). + Tick one color clock. Inline for performance. */ - FORCE_INLINE void tick(uInt32 x); + FORCE_INLINE void tick(uInt32 x) + { + myX = x; + + // Reflected flag is updated only at x = 0 or x = 79 + if (myX == TIAConstants::H_PIXEL / 2-1 || myX == 0) myRefp = myReflected; + + if (x & 0x03) return; + + uInt32 currentPixel; + + if (myEffectivePattern == 0) { + currentPixel = 0; + } else if (x < TIAConstants::H_PIXEL / 2 - 1) { + currentPixel = myEffectivePattern & (1 << (x >> 2)); + } else if (myRefp) { + currentPixel = myEffectivePattern & (1 << (39 - (x >> 2))); + } else { + currentPixel = myEffectivePattern & (1 << ((x >> 2) - 20)); + } + + collision = currentPixel ? myCollisionMaskEnabled : myCollisionMaskDisabled; + } public: @@ -261,33 +283,4 @@ class Playfield : public Serializable Playfield& operator=(Playfield&&) = delete; }; -// ############################################################################ -// Implementation -// ############################################################################ - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FORCE_INLINE void Playfield::tick(uInt32 x) -{ - myX = x; - - // Reflected flag is updated only at x = 0 or x = 79 - if (myX == TIAConstants::H_PIXEL / 2-1 || myX == 0) myRefp = myReflected; - - if (x & 0x03) return; - - uInt32 currentPixel; - - if (myEffectivePattern == 0) { - currentPixel = 0; - } else if (x < TIAConstants::H_PIXEL / 2 - 1) { - currentPixel = myEffectivePattern & (1 << (x >> 2)); - } else if (myRefp) { - currentPixel = myEffectivePattern & (1 << (39 - (x >> 2))); - } else { - currentPixel = myEffectivePattern & (1 << ((x >> 2) - 20)); - } - - collision = currentPixel ? myCollisionMaskEnabled : myCollisionMaskDisabled; -} - #endif // TIA_PLAYFIELD diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 29a939e0d..bcc1f5281 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -1452,7 +1452,7 @@ void TIA::cycle(uInt32 colorClocks) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::tickMovement() +FORCE_INLINE void TIA::tickMovement() { if (!myMovementInProgress) return; @@ -1538,7 +1538,7 @@ void TIA::applyRsync() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::nextLine() +FORCE_INLINE void TIA::nextLine() { if (myLinesSinceChange >= 2) { cloneLastLine();