Anatomy of a Game: Startup and Loading

  • We have updated our Community Code of Conduct. Please read through the new rules for the forum that are an integral part of Paradox Interactive’s User Agreement.
You really do not want to use debug builds while playing the game, or using any software for that matter. Debug builds might have some "additional" feature compared to release builds ( marked in c++ code with something like #ifdef DEBUG) but usually there aren't many of those. That kind of "features" are usually there to overcome some limitation of your environment, when you want some special behavior during debug. But during debug you usually want your application to behave as closer as possible to how it would actually behave.

What debug build is mostly adding additional information so execution of certain part of the code can be recognized and displayed in debugger.

For example somewhere in code you can have something like this:
Code:
auto a = 1;
auto b = a;//and after this a not used anymore in rest of the code
auto c = b;//and after this b not used anymore in rest of the code
auto d = c;//and after this c not used anymore in rest of the code
auto e = d;//and after this d not used anymore in rest of the code
auto f = e;//and after this e not used anymore in rest of the code
// now do something with f
// you will not have this example in real code, I am just showing it as example to explain what can be optimised
In release build, compiler can say, I do not need a, b, c, d, e variables anywhere, so I will replace all of this with auto f = 1; This is much faster and used much less memory. But in debug build that replacement is never done. In debug mode, you want to see when variable a get value of 1, then variable b etc. You want to know when any of those lines are executed.

Of course this is absurd example, you will never write this kind of code. But there are much more subtle optimization, where code is reduced and speed up during building release. This is just extreme example to show the point.

So if you are using software, and you are not trying to figure out why it is not working properly, you always want to use release build, and not debug build.

And about differences between "-debug_mode" and enabeling it ingame via a gui mod, I would say that there are some additional differences. File watchers are for sure attached on load time, so you will not probably have that feature with gui mod. And maybe some logging is turned on as well. I cannot come up with more ideas what "-debug_mode" can have more then gui mod. But all of that, if any additional feature exists, must be related to that flag being present during load time. And all of these are not features related to debug build, but to debug mod in release build.
To add to that, here's an actual hands-on example from CK3.
Here is the info available when I pause the execution of the game during a function that deals with handling all the data for making a frame in a Release build.
1626509590310.png

1626509599560.png

Around half the variables are just completely gone. 4 separate functions in the callstack are gone too (the ones marked "Inline Frame").
Trying to debug this is hell, so we basically only do that if there's a crash on a Release build that we have no way of reproducing on a Debug build.
In a Debug build, none of this would be gone, making my life as a programmer way easier.
 
  • 11
  • 2Like
Reactions:
And about differences between "-debug_mode" and enabeling it ingame via a gui mod, I would say that there are some additional differences. File watchers are for sure attached on load time, so you will not probably have that feature with gui mod. And maybe some logging is turned on as well. I cannot come up with more ideas what "-debug_mode" can have more then gui mod. But all of that, if any additional feature exists, must be related to that flag being present during load time. And all of these are not features related to debug build, but to debug mod in release build.
That's what I figured aswell, hence why i asked to clarify
 
I'm curious how the system you've set up where events, localization, and some other files can be reloaded while in game when modding works.
 
You really do not want to use debug builds while playing the game, or using any software for that matter. Debug builds might have some "additional" feature compared to release builds ( marked in c++ code with something like #ifdef DEBUG) but usually there aren't many of those. That kind of "features" are usually there to overcome some limitation of your environment, when you want some special behavior during debug. But during debug you usually want your application to behave as closer as possible to how it would actually behave.

What debug build is mostly adding additional information so execution of certain part of the code can be recognized and displayed in debugger.

For example somewhere in code you can have something like this:
Code:
auto a = 1;
auto b = a;//and after this a not used anymore in rest of the code
auto c = b;//and after this b not used anymore in rest of the code
auto d = c;//and after this c not used anymore in rest of the code
auto e = d;//and after this d not used anymore in rest of the code
auto f = e;//and after this e not used anymore in rest of the code
// now do something with f
// you will not have this example in real code, I am just showing it as example to explain what can be optimised
In release build, compiler can say, I do not need a, b, c, d, e variables anywhere, so I will replace all of this with auto f = 1; This is much faster and used much less memory. But in debug build that replacement is never done. In debug mode, you want to see when variable a get value of 1, then variable b etc. You want to know when any of those lines are executed.

Of course this is absurd example, you will never write this kind of code. But there are much more subtle optimization, where code is reduced and speed up during building release. This is just extreme example to show the point.

So if you are using software, and you are not trying to figure out why it is not working properly, you always want to use release build, and not debug build.

And about differences between "-debug_mode" and enabeling it ingame via a gui mod, I would say that there are some additional differences. File watchers are for sure attached on load time, so you will not probably have that feature with gui mod. And maybe some logging is turned on as well. I cannot come up with more ideas what "-debug_mode" can have more then gui mod. But all of that, if any additional feature exists, must be related to that flag being present during load time. And all of these are not features related to debug build, but to debug mod in release build.
Very good summary, thanks for your post!

Your guess about the command line vs console command for debug mode is also mostly spot on, it just turns it on sooner so anything needing debug mode to be active during load happens. Such as attaching file watchers and doing extra logging during that time before you’d be in game with the UI setup to turn on debug mode then.
 
  • 4
Reactions:
I'm curious how the system you've set up where events, localization, and some other files can be reloaded while in game when modding works.
We have a system of file watcher set up where we use platform specific functionality wrapped into a unified interface to be notified about changes to a file path.

When it’s changed it notifies the database that then reload its, reloading is just destroying what is already there as then re-reading in the new data. To ensure that we don’t cause issues with our databases leaving dangling pointers around of things using it we destroy and recreate the data in the same memory location.

So code who are storing and using some trait from the databases for example don’t ever know that the trait has changed, just the next time they try to get the modifier a trait applies for instance then they’ll see the new values and use them.
 
  • 5
Reactions:
and recreate the data in the same memory location.
Will I cause a segfault if I hotload a change that replaces a one-liner script value with a 300 line formula that uses every database in the game?
 
Will I cause a segfault if I hotload a change that replaces a one-liner script value with a 300 line formula that uses every database in the game?
Probably not. But also please don't do that.

The bit of memory reused is the statically sized part of the database object, so you using more dynamically sized memory shouldn't really affect anything.
 
  • 2Like
  • 1
Reactions:
I really enjoyed your post. It actually was an easy read and it gave me the basic understanding of what goes behind the game. I appreciate things like this because it is not only interesting to learn new things, but that you took the time.
 
Last edited:
  • 1
Reactions:
Yeah, just wanted to chime in and say this really was fascinating! As someone only beginning to get into programming, the level of knowledge and experience at play to understand and work these systems is a bit daunting, but on the other hand your explanation of the higher level flow really makes it quite digestible.

Without knowing enough to ask a super precise question, I was curious as to how modding functions were translated from the game's base code to paradox script. Is the language at either end comparable, or are things really mutated a lot? And what sort of checks go into the process of adding some new functionality to the language, is security a big concern?
 
  • 1
  • 1Like
Reactions:
Yeah, just wanted to chime in and say this really was fascinating! As someone only beginning to get into programming, the level of knowledge and experience at play to understand and work these systems is a bit daunting, but on the other hand your explanation of the higher level flow really makes it quite digestible.

Without knowing enough to ask a super precise question, I was curious as to how modding functions were translated from the game's base code to paradox script. Is the language at either end comparable, or are things really mutated a lot? And what sort of checks go into the process of adding some new functionality to the language, is security a big concern?
Glad you found it interesting! I definitely get the daunting nature of it, when I started learning programming a few years ago it seemed so huge and that there was so much stuff there. But the upside is that you only need to learn a little bit every day or week before you get to a critical mass of being able to code something fairly decently, and from there you can learn and refine and discover more things as you go!

I'll not answer this question too much for now because the script system as a whole is one of my planned future posts, but the highest level gist of it is that we read in the files and translate them into the objects in code for triggers and effects based on the key and store any other values need, so when it sees gold > 500 it knows to make an instance of the gold trigger and store the value 500. Every trigger and effect then knows what to do with its store data when we evaluate/execute it or build a tooltip for it. At run time we have a context that we pass through that tree to evaluate/execute something for the given character so it knows what value of gold it needs to compare against 500 for instance.
 
  • 4Like
  • 3
Reactions:
Thanks for the article. I love the behind-the-scenes topics :)

Now I understand why my EU4 loads like a blitz when on Linux.
I wish the Microsoft team did something about this loading-many-small-files-takes-forever issue.
 
In case you didn't plan a post on it already, I'm interested to learn more about desync, and what goes into the multiplayer side of things.

Also I'd love to know more about the organisationnal aspect of your work. Like how are things prioritized, how is time allocated, how much of you and your team's time is spent actually coding vs other stuff (meetings, testing and such)? How much of that is for New Things, for bug fixing, for mod support?

As it happens, there's a programing school right where I live and work, and I know quite a few people who attended there. They learn coding skills, but I feel like they don't really learn project management, how to handle an efficient workflow as a team, and so forth.
 
I'm just a Python prototyping guy, but big respect to the actual developers who have the chops for these kinds of complicated engineering problems! This post was extremely informative, thanks! Looking forward to more.
 
  • 1Like
Reactions:
I have no idea what half of this even means, but it is interesting. I say keep these coming.
 
  • 1Like
  • 1
Reactions:
In case you didn't plan a post on it already, I'm interested to learn more about desync, and what goes into the multiplayer side of things.

Also I'd love to know more about the organisationnal aspect of your work. Like how are things prioritized, how is time allocated, how much of you and your team's time is spent actually coding vs other stuff (meetings, testing and such)? How much of that is for New Things, for bug fixing, for mod support?

As it happens, there's a programing school right where I live and work, and I know quite a few people who attended there. They learn coding skills, but I feel like they don't really learn project management, how to handle an efficient workflow as a team, and so forth.
I’ll note that down as an idea for a future one!
 
  • 6Like
  • 1
Reactions:
  • 7
Reactions:
1)The long arrow from CLifeStyleDatabase to NModifier::SDynamicModifiersForTerrainAndGovernmentTypeDependency is frightening.
2)I always have the longest load screens (because I tend not to close the browser in the background) so the main theme is properly heard... for a good ten to twenty minutes, I can make some tea listening to it ;)
3)Is the fact that you now create new game via creating a save game the reason either for the fact you can't switch the year after you chose it once in CK3 (unlike CK2 where you could do that) or for the fact that back in CK2 switching back and forth through the time created some bugs? (Or for both)
 
  • 1Like
Reactions:
1)The long arrow from CLifeStyleDatabase to NModifier::SDynamicModifiersForTerrainAndGovernmentTypeDependency is frightening.
2)I always have the longest load screens (because I tend not to close the browser in the background) so the main theme is properly heard... for a good ten to twenty minutes, I can make some tea listening to it ;)
3)Is the fact that you now create new game via creating a save game the reason either for the fact you can't switch the year after you chose it once in CK3 (unlike CK2 where you could do that) or for the fact that back in CK2 switching back and forth through the time created some bugs? (Or for both)
  1. It isn't toooo bad, the graph makes it look a lot more pain than it is, it all loads quite quickly now
  2. I also would think for that load time you're on a HDD which is a lot lot slower than an SSD
  3. General simplicity really (so a bit of both your points), the switching dates back and forth was always a bit buggy as it meant we need to have a game state we could modify and undo changes to per day and also just a maintenance nightmare of supporting every single date to in theory be playable despite the fact that nobody ever played outside the main start dates really. Makes it so that we can differentiate between has a game state and does not very clear cut and once we've got the game state that is the save we are using and data we have to pick characters or have someone join in an MP game.
 
  • 4
Reactions: