How are the OOS these days? How Do I turn on Error Log

FlyingDragon

Chieftain
Joined
Mar 27, 2016
Messages
8
I haven't attempted a Direct Connect for 5 or 6 months. Last time there was a lot of OOS. Has some of these errors been reduced? It would be nice to play something other than hotseat. Anyways how do I turn on the error log again because I plan to be trying Direct Connect again soon? I love this mod but I would really love to be able to play my wife without having to use the same computer haha :)

Update oh yeah the INI file haha ok have the error logging on lets see how far this goes before my first OOS in direct connect

I guess this probably is the wrong forum mabye. But I thought Id try Direct with my wife tonight. I just found the error or bug forum but not sure if you guys are actually working on OOS errors right now.
 
I haven't worked on OOS errors in a while but was hoping to once other instability issues have calmed down and the tasks I've set for myself for this version have been completed. aka... when my wife and I go to play a game too.

I'm not sure how it would go right now but there are some things you can try if your getting some and some known things to avoid.

1) make sure that all of the globals with the term 'THREAD' in them are set to 0.
2) don't take the Seafaring trait... the free promo somehow skews the estimated move capability of the ships one one machine to another.
3) Move your naval vessels one round at a time, not setting them out to go further than they can reach in one round.
4) Be careful not to set a wonder the other player has already set to build.

Based on the last time we played, this would avoid the majority of them. There were still some rare ones on withdrawal which I still haven't been able to nail down.

I figure once I get to looking at it directly I can probably solve them all but time to mod is a major lacking factor these days.
 
Oh thankyou! I started a thread in the bugs and fixes to log my game. So far gone 206 turns with no issues.. But it was one consecutive session for 4 hours. Today we will try again.

I have the xml already set in both pc's and the city pipeline to 1. I think I have no negative traits set.

Thankyou for the tip on the sea part. I havent got that far yet lol...and I am playing with my wife on the same team so it wont let us set the same world wonder. But does it do it on national wonders as well?. Ill continue to log my game in the bugs forum in a single thread and cross fingers and hope today is good also. But both our computers have logging turned on as well.

I have been excited to get this far in a Direct Connect game in this mod. Civ isnt the same anymore without this mod ... just tired of hotseat on one computer which does works great.

Should I have the withdrawal (retreat) mode shut off?

I noticed in this game so far there are no wonder popups or tech popups... But the voice will kick in. In hotseat I always saw the wonder popups. But I just care about being able to play this at all on direct lol...here we go Day 2...
 
Should I have the withdrawal (retreat) mode shut off?
If you've been able to get this far without an oos and this mode is on then the problem may have been incidentally found and corrected along the way. I tend to keep an eye out for general bad practices that can lead to OOS errors I've seen in the past and correct them if I run across them. It's possible the OOS with that is corrected (but also possible you just haven't encountered it yet too.) Just let me know when you encounter one and what your best guess as to what it might've been caused by. You can often get a clue by looking around and spotting the difference between the games as soon as the OOS alert is given.
 
Yeah game is still going good a week in.

I did set all the xml files and we followed your advice on the ships. There are some game settings we also avoided because heard it was high risk

We are also being careful in how we save. Making sure all the moves complete first before saving and making an exit.

We notice though there is no animations for tech, wonders or combat even though it is enabled. And also noticed we can now work on the same great wonders as a team which was never the case previously. So we now also have to be careful on that issue as well.

I have one thread which I update in bugs and crashes to log this and in case or when we may come across it. But happy so far.
 
Hi guys,

I was wondering how's the OOS situation here. C2C and Rise of Mankind A New Dawn share a big part of the dll and in RAND OOS problems are not too bad until Medieval Era. I'm currently attempting to fix some oos, especially with pitboss. Have you ever tried it with C2C? Anyway something strange is going on, or at least something I can't explain: I've changed the dll in order to always return "1" when SorenRand is called and I've removed all the AsyncRand calls in the dll. But the game is going OOS anyway after a few turns. How is that even possible? Do you have any suggestion? There are a couple of places in the python where Async is called, but I've removed those entries as well, so I have no idea what might cause the OOS problem now. Any suggestion appreciated.
 
I haven't used pitboss myself but AIAndy did some debugging for that.

Randoms aren't the only way that OOS errors can take place. Any call to a variable that has not been defined will cause it as well. That's actually just as or more common. One of the big ones is when you send a variable through a function for a return (&iVariable) without first giving the variable a default value: int iVariable = 0; rather than int iVariable;

The truest trick to finding OOS errors is to trace from the point that you can see a random call being different (which won't help if you've got everything returning '1'.) Or from a suspected point in the code based on the compare between the OOS reports. The way you can track it down is to generate compare data printing to a new temporary report at the beginning of those functions of concern. When you then compare the reports from each computer you can see which function first shows the difference. Don't use a random variable for that or you can sometimes accidentally cause an oos. But if you use local variables being used in the function, you can get an idea where one system deviated in its processing from the other.

In C2C we greatly complexify the issue with some multithreading and this means we need to turn the multithreading off for multiplayer play.

TBH, I haven't worked on trying to search and destroy the existing OOS errors much lately, but I look forward to being able to do so again fairly soon. I'm pretty sure there may be a few situations I still don't know how to find and resolve but I can probably figure it out with the above method which I've used many times to find OOS errors and destroy them. In fact, that method has taught me HOW some OOS errors can take place.

I can try to give you more syntax details on how to set up the tracking methods if you like. Be forewarned, it means you'll be using a dll that is specifically and only used for finding OOS errors and its NOT good for working on OOS errors that are reported by others - it requires you find your own and fix your own really. Which is fine because any given MP play is likely to find the majority or worst of them and what it doesn't find leaves the game within acceptable tolerances for MP players to work through while getting a good game still.
 
Thanks for the info tbrd, I might need some syntax detail but your message ringed a bell when talking about &iVariable. From a quick search, there's plenty of &iVariable that are not initialized in the code of AND. I suppose not all of them might cause out of sync problems, but some probably are. A bit tedious work, but it should be pretty easy to initialize them all before they're used. Anything I should be cautious about these changes?

Edit: for example

Code:
		WRAPPER_READ(wrapper, "CvPlayer", &iNumBuildingTypes);
		while(iNumBuildingTypes-- > 0)
		{
[COLOR="Red"]			int	eBuilding;
			int iCount;[/COLOR]

			WRAPPER_READ(wrapper, "CvPlayer", &eBuilding);
			WRAPPER_READ(wrapper, "CvPlayer", &iCount);

			m_unitConstructionCounts.insert(std::make_pair((BuildingTypes)eBuilding, iCount));
		}

shouldn't I declare

int eBuilding = 0;
int iCount = 0;

?

Or here:

Code:
void CvInfoBase::readOptionalArray(FDataStreamBase* pStream, bool*& pabValues)
{
	[COLOR="Red"]bool	bPresent;
[/COLOR]
	SAFE_DELETE_ARRAY(pabValues);
	pStream->Read(&bPresent);
	if ( bPresent )
	{
		int iSize;

		pStream->Read(&iSize);
		pabValues = new bool[iSize];
		pStream->Read(iSize, pabValues);
	}
}

is it correct or should I declare bool bPresent = false?
 
45°38'N-13°47'E;14396584 said:
Thanks for the info tbrd, I might need some syntax detail but your message ringed a bell when talking about &iVariable. From a quick search, there's plenty of &iVariable that are not initialized in the code of AND. I suppose not all of them might cause out of sync problems, but some probably are. A bit tedious work, but it should be pretty easy to initialize them all before they're used. Anything I should be cautious about these changes?

Edit: for example

Code:
		WRAPPER_READ(wrapper, "CvPlayer", &iNumBuildingTypes);
		while(iNumBuildingTypes-- > 0)
		{
[COLOR="Red"]			int	eBuilding;
			int iCount;[/COLOR]

			WRAPPER_READ(wrapper, "CvPlayer", &eBuilding);
			WRAPPER_READ(wrapper, "CvPlayer", &iCount);

			m_unitConstructionCounts.insert(std::make_pair((BuildingTypes)eBuilding, iCount));
		}

shouldn't I declare

int eBuilding = 0;
int iCount = 0;

?

Or here:

Code:
void CvInfoBase::readOptionalArray(FDataStreamBase* pStream, bool*& pabValues)
{
	[COLOR="Red"]bool	bPresent;
[/COLOR]
	SAFE_DELETE_ARRAY(pabValues);
	pStream->Read(&bPresent);
	if ( bPresent )
	{
		int iSize;

		pStream->Read(&iSize);
		pabValues = new bool[iSize];
		pStream->Read(iSize, pabValues);
	}
}

is it correct or should I declare bool bPresent = false?

Excellent examples. The ones related to the save/load process are probably safe but just to be sure and to establish good practice, I'd correct them all. Always initiate with a default value if possible. Another place that can cause a lot is when you have a variable failing picking up a default value in CvWhatever::reset();

Note: You also have iSize in that last example not getting any default before being sent to get a value through the function call.
 
HI Thunderbrd and others,
after going through every variable in A New Dawn, I think I've initialized most of them. While I was there and testing anyway, I've found another couple of OOS sources but I'm not sure how to solve them. The code is the almost the same in C2C (here's your code):

Code:
for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			for (iJ = 0; iJ < NUM_MEMORY_TYPES; iJ++)
			{
				[COLOR="Red"]if (AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ)) > 0)[/COLOR]
				{
					if (GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ) > 0)
					{
						/************************************************************************************************/
						/* Afforess	                  Start		 04/26/14                                               */
						/*                                                                                              */
						/* Ruthless AI: Easier for the AI to forget past wrongs                                         */
						/************************************************************************************************/
						//AI attitude is designed to make AI players feel human, but it makes them weak
						//A Perfect AI treats enemies and friends alike, both are obstacles to victory
						int iRand = GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ);
						if (GC.getGameINLINE().isModderGameOption(MODDERGAMEOPTION_REALISTIC_DIPLOMACY))
						{
							iRand /= 3;
							iRand /= AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ));
						}
						if (GC.getGameINLINE().isOption(GAMEOPTION_RUTHLESS_AI))
						{
							iRand /= 2;
						}
						if (GC.getGameINLINE().getSorenRandNum(iRand, "Memory Decay") == 0)
						{
						/************************************************************************************************/
						/* Afforess	                     END                                                            */
						/************************************************************************************************/
							AI_changeMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ), -1);
						}
					}
				}
			}
		}
	}

I think the culprit is the red line. Removing it looks like it's solving the "Memory Decay" OOS. What happens with that line is that one of the human players runs the random roll one time more than the other player, hence causing an OOS. I've tried removing it and changing it with

if ((AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ)) > 0) || GC.getGameINLINE().isNetworkMultiPlayer())

and the OOS is gone. Problem is that removing that line causes all sort of strange values for AI memory of good/bad actions toward AI.
Any hint on how to rework that line so that we can check AI_getMemoryCount without risk? What do you think?
 
45°38'N-13°47'E;14419940 said:
HI Thunderbrd and others,
after going through every variable in A New Dawn, I think I've initialized most of them. While I was there and testing anyway, I've found another couple of OOS sources but I'm not sure how to solve them. The code is the almost the same in C2C (here's your code):

Code:
for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			for (iJ = 0; iJ < NUM_MEMORY_TYPES; iJ++)
			{
				[COLOR="Red"]if (AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ)) > 0)[/COLOR]
				{
					if (GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ) > 0)
					{
						/************************************************************************************************/
						/* Afforess	                  Start		 04/26/14                                               */
						/*                                                                                              */
						/* Ruthless AI: Easier for the AI to forget past wrongs                                         */
						/************************************************************************************************/
						//AI attitude is designed to make AI players feel human, but it makes them weak
						//A Perfect AI treats enemies and friends alike, both are obstacles to victory
						int iRand = GC.getLeaderHeadInfo(getPersonalityType()).getMemoryDecayRand(iJ);
						if (GC.getGameINLINE().isModderGameOption(MODDERGAMEOPTION_REALISTIC_DIPLOMACY))
						{
							iRand /= 3;
							iRand /= AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ));
						}
						if (GC.getGameINLINE().isOption(GAMEOPTION_RUTHLESS_AI))
						{
							iRand /= 2;
						}
						if (GC.getGameINLINE().getSorenRandNum(iRand, "Memory Decay") == 0)
						{
						/************************************************************************************************/
						/* Afforess	                     END                                                            */
						/************************************************************************************************/
							AI_changeMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ), -1);
						}
					}
				}
			}
		}
	}

I think the culprit is the red line. Removing it looks like it's solving the "Memory Decay" OOS. What happens with that line is that one of the human players runs the random roll one time more than the other player, hence causing an OOS. I've tried removing it and changing it with

if ((AI_getMemoryCount(((PlayerTypes)iI), ((MemoryTypes)iJ)) > 0) || GC.getGameINLINE().isNetworkMultiPlayer())

and the OOS is gone. Problem is that removing that line causes all sort of strange values for AI memory of good/bad actions toward AI.
Any hint on how to rework that line so that we can check AI_getMemoryCount without risk? What do you think?
I think the problem would lie somewhere within the AI_getMemoryCount function itself. It sounds like its a caching issue so to resolve it we'll have to look inside that function and see where we can somehow make the check in a more synchronized fashion or bypass where it goes out of sync there.

Interestingly, it's a bool statement basically, memory exists or doesn't is all its asking, and I suspect that whether it does or doesn't has a lot to do with checking against the current player, which is what would differ on both machines.

Post the code for that function. Let's openly take a look here at the devil in the details. (Not at my modding computer at the moment or I'd go find it and post it myself.)
 
Uh, you might be right! And the problem might not be in AI_getMemoryCount but rather in AI_changeMemoryCount. Look at both functions here:

Code:
int CvPlayerAI::AI_getMemoryCount(PlayerTypes eIndex1, MemoryTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_MEMORY_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_aaiMemoryCount[eIndex1][eIndex2];
}


void CvPlayerAI::AI_changeMemoryCount(PlayerTypes eIndex1, MemoryTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_MEMORY_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	m_aaiMemoryCount[eIndex1][eIndex2] += iChange;
// BUG - Update Attitude Icons - start
[COLOR="Red"]	if (eIndex1 == GC.getGameINLINE().getActivePlayer())
	{
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
	}[/COLOR]
// BUG - Update Attitude Icons - end
	FAssert(AI_getMemoryCount(eIndex1, eIndex2) >= 0);
}

That ActivePlayer call in red looks very suspicious to me. I don't know how to make it synchronous, but being an interface thing we can probably find a way to solve this OOS (which happens pretty often by the way!).

Edit: Oh well, you don't have those lines in the code of C2C:

Code:
int CvPlayerAI::AI_getMemoryCount(PlayerTypes eIndex1, MemoryTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_MEMORY_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_aaiMemoryCount[eIndex1][eIndex2];
}


void CvPlayerAI::AI_changeMemoryCount(PlayerTypes eIndex1, MemoryTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < MAX_PLAYERS, "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_MEMORY_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	m_aaiMemoryCount[eIndex1][eIndex2] += iChange;
	FAssert(AI_getMemoryCount(eIndex1, eIndex2) >= 0);
}

It looks like this is a pure AND OOS and not one we share.
But I've found another one that I'm testing a fix for, so if things turn out good, I'll post it here.

Edit2: No sorry, it's in your DLL too; the code I posted in my edit was from original BTS dll; sorry, too many opened tabs in Notepad++ :p
Maybe I could just remove that if (eIndex1 == GC.getGameINLINE().getActivePlayer())? Even if
gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
is executed for every player even non active ones, it shouldn't cause any problem, just a small slowdown probably. I could make it only for MP games anyway.
 
Maybe I could just remove that if (eIndex1 == GC.getGameINLINE().getActivePlayer())? Even if
gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
is executed for every player even non active ones, it shouldn't cause any problem, just a small slowdown probably. I could make it only for MP games anyway.

if (eIndex1 == GC.getGameINLINE().getActivePlayer() || GC.getGameINLINE().isNetworkMultiPlayer()) would probably do it nicely. The delay is no biggy on MP games but would be an unnecessary bog down on single player or hotseat.

Good catch but I wonder if that's the whole issue. You might want to also check the contexts in which CvPlayerAI::AI_changeMemoryCount is called if you continue to show trouble with that spot. The actual count change is not isolated to if (eIndex1 == GC.getGameINLINE().getActivePlayer()) and its the actual count, as derived from AI_getMemoryCount, that comes up out of sync. So I'm suspicious that the change call is being made asynchronious. Which will require more investigation into where its being called.

The part that is asking for the active player here is, I believe, just going to create a UI display difference and I don't think it would change the actual data in the gamestate for each player.
 
if (eIndex1 == GC.getGameINLINE().getActivePlayer() || GC.getGameINLINE().isNetworkMultiPlayer())would probably do it nicely. The delay is no biggy on MP games but would be an unnecessary bog down on single player or hotseat.

Good catch but I wonder if that's the whole issue. You might want to also check the contexts in which CvPlayerAI::AI_changeMemoryCount is called if you continue to show trouble with that spot. The actual count change is not isolated to if (eIndex1 == GC.getGameINLINE().getActivePlayer()) and its the actual count, as derived from AI_getMemoryCount, that comes up out of sync. So I'm suspicious that the change call is being made asynchronious. Which will require more investigation into where its being called.

The part that is asking for the active player here is, I believe, just going to create a UI display difference and I don't think it would change the actual data in the gamestate for each player.
You might be right, I'll test more with the new code and I'll let you know.
 
Well, after hundreds of turns of testing (very quickly, without taking any decisive action), it looks like "Memory Decay" OOS doesn't show up anymore. Either it was very rare and it didn't show up yet, or the fix I've proposed above is working, although I'm not 100% convinced.
In the meantime I've also fixed a very frequent OOS caused by diplomacy. Basically there are some calls of

Code:
AI_getContactTimer(((PlayerTypes)iI), [BLA BLA BLA, for example CONTACT_PERMANENT_ALLIANCE) == 0

which are throwing the game OOS. I've not been able to fix AI_getContactTimer or AI_changeContactTimer functions, I've found nothing wrong there, but I've found a way to avoid OOS. I've placed an if condition so that if the game is not NetworkMultiplayer, the code runs as always. But if we're playing a MP game, I've copied-pasted most of the code in void CvPlayerAI::AI_doDiplo() after an else condition but removing every AI_changeContactTimer and changing

Code:
AI_getContactTimer(((PlayerTypes)iI), [BLA BLA BLA, for example CONTACT_PERMANENT_ALLIANCE) == 0

with
Code:
GC.getGameINLINE().getSorenRandNum(RandomContactTurnTotal, "Trade Permanent Alliance MP") < RandomContactTurnPercent

which basically has a 20% chance to be true, which is good enough for the purpose of allowing some AI trade more or less with the same frequency given by the counter I've removed (I've introduced and scaled RandomContactTurnTotal and RandomContactTurnPercent for this purpose). It looks like it's working good enough until now.
I'll push it in the next RAND revision probably tomorrow if you want to have a look at the whole code. :)
I can't guarantee it will work the same for C2C as I haven't checked all the diplo code of your mod but to me it looks similiar enough to our code. So I hope it can help you too.
 
I'd like to throw my support to the work 45° is doing with T-Brd's help. It really means a lot to me this work to kill OOSs. I can't wait to play a 2-player MP as I used to do back when I played the LoR Mod but with a great mod like C2C or RAND.

Keep up the good work :thumbsup:
 
45°38'N-13°47'E;14426144 said:
Well, after hundreds of turns of testing (very quickly, without taking any decisive action), it looks like "Memory Decay" OOS doesn't show up anymore. Either it was very rare and it didn't show up yet, or the fix I've proposed above is working, although I'm not 100% convinced.
In the meantime I've also fixed a very frequent OOS caused by diplomacy. Basically there are some calls of

Code:
AI_getContactTimer(((PlayerTypes)iI), [BLA BLA BLA, for example CONTACT_PERMANENT_ALLIANCE) == 0

which are throwing the game OOS. I've not been able to fix AI_getContactTimer or AI_changeContactTimer functions, I've found nothing wrong there, but I've found a way to avoid OOS. I've placed an if condition so that if the game is not NetworkMultiplayer, the code runs as always. But if we're playing a MP game, I've copied-pasted most of the code in void CvPlayerAI::AI_doDiplo() after an else condition but removing every AI_changeContactTimer and changing

Code:
AI_getContactTimer(((PlayerTypes)iI), [BLA BLA BLA, for example CONTACT_PERMANENT_ALLIANCE) == 0

with
Code:
GC.getGameINLINE().getSorenRandNum(RandomContactTurnTotal, "Trade Permanent Alliance MP") < RandomContactTurnPercent

which basically has a 20% chance to be true, which is good enough for the purpose of allowing some AI trade more or less with the same frequency given by the counter I've removed (I've introduced and scaled RandomContactTurnTotal and RandomContactTurnPercent for this purpose). It looks like it's working good enough until now.
I'll push it in the next RAND revision probably tomorrow if you want to have a look at the whole code. :)
I can't guarantee it will work the same for C2C as I haven't checked all the diplo code of your mod but to me it looks similiar enough to our code. So I hope it can help you too.

I'll take a look soon. Thanks for pointing these out! I must have missed you posting that last one for some reason. Sorry for that.
 
I'll take a look soon. Thanks for pointing these out! I must have missed you posting that last one for some reason. Sorry for that.
Hey, no problem, I'm testing a MP game and it looks like it's working good enough, OOS have decreased from one every 10-20 turns to 1 every 60 turns, blitz speed which is 600 turns in AND. Halfway through Renaissance and only 4 OOS. I'll keep you informed but if you look at revision 1034-1035 of AND you can see the latest changes.
 
Top Bottom