Game Design, Programming and running a one-man games business…

Fun with 64 bit programming

So my recent adventures in the land of code have taken me to port Production Line to 64 bit. The current 32bit build only allows me to access 2 GB of RAM and although even super large factories can fit in 800MB now, when you really pack things in and put the hours in, it *is* possible to hit 2 GB. With modding & any possible post-release expansion possibilities, there is arguable a need to remove that limit and so here we are.

I’ve basically done 2 days(ish) work on it, and have a release build and debug build 64 bit version of the game that seems to run just fine. It was relatively painless. The 3rd party stuff I use is mostly, Steam, some sound middle ware, Directx and an intel profiler, and all of this has 64 bit support, so the majority of the work has been going through the config for the game and changing include folders and paths to point to 64 bit DLLs and Lib files.

This has been complicated a bit by the mess that the Visual Studio (2013) software makes out of configurations. I can have a debug64 project config that then has the platform set to 32bit, and then god-knows where the exe gets put or which files get compiled and oh-my-god how messy. I think I have finally got close to getting it straight in my head, although I have ended up hard coding exe names and paths and may have to even rename my engines lib file to engine_64.lib to make ABSOLUTELY sure that it is not using the wrong lib file and thus mix-and matching.

I can totally see why people do not want to support both 32 bit and 64 bit versions of the same game, especially given the fact that, unbeknown to me, the mere *existence* of a 32 bit dll in the exe folder will seemingly stop my 64bit .exe launching. I guess you end up with separate folders? What a pain.

In terms of code, it was almost entirely painless. As I suspected, my one pain point was my GUI code for buttons. I have a base button type that takes a function pointer called BUTTONFUNC to execute when clicked. I cannot remember far enough back to work out why, but generally I end up passing an objects ‘this’ pointer as an (int) to the constructor for a button, if I want the button function to access it as data. So I end up writing code like this:

PCheckFree = new GUI_CheckButton(TRANSLATE(“CHOOSE_MISSION_FREEPLAY”), Freeplay, (int)this);

And then in the code that receives it I’d do this:

void GUI_Scenario::Freeplay(int data)
{
GUI_Scenario* pwin = (GUI_Scenario*)data;
pwin->SetType(SIM_Scenario::FREEPLAY);
}

Which is perfectly fine and lovely, assuming pointers are 32 bit and an int is 32bit. However, it turns out that porting to 64 bit is as simple as just replacing both users of (int) with (size_t) which varies based on platform, and voila! problem sorted. I expected this to be the first step in a whole world of nightmares,, but although I have not done serious testing yet, it appears to launch, run and allow me to load in massive save games, so I reckon I’m 95% of the way there. All I need to do know is investigate how all the various stores (Humble, Kartridge, Steam, Gog) handle multiple versions (64 bit versus 32 bit), to ensure I’m not leaving the tiny 32bit minority behind. I guess eventually that will not be an issue.

I’m definitely happy that this seems to have gone smoothly, as it amounts to days of coding and admin and investigation which are essential, but doesn’t make the game noticeably better for players, which is always a worry when the game is still in Early Access. Fun fun fun…

 

 

 


5 thoughts on Fun with 64 bit programming

  1. Just FYI: size_t is not meant to be used the way you use it now. size_t is defined as the value returned by the sizeof() operator. There are no other guarantees. Heck there are probably systems out there that are 64 bit but size_t is only 16 bit in size because the biggest *single* chunk that can be allocated is 64 KiB.

    What you want is intptr_t, which is by definition the type used in such circumstances.

    However, I wonder: why not just use ‘void *’ and call it a day?

    1. oooh interesting. I have in that case read a misleading article. But yeah… I have no idea historically why I started doing this…

      1. There is no shame in making missteps when porting to 64 bit. Reading your post I am actually jealous that it only took you days (all together).

        And I guess the article(s) you read where not misleading but plainly wrong.
        You are in a great position, since articles and information are plentiful nowadays.
        You are in a sorry position, since a great number of those articles are just wrong. ;)

        Back when I started porting my code to 64 bit 10+ years ago for Windows, Mac OS, Linux and FreeBSD, as well as PowerPC for Mac OS (32 bit), there was either no information at all or mostly reliable one. Mostly no information, however. So it was a lot of reading docs/specs and trial and error to get it not just to work, but getting it right. However using 3 different compilers, different ‘bitness’ and even different architectures/endianess led to a huge increase in quality of my codebase.
        But I start to ramble. The gist of it is: I would have been glad if all of it could have been counted in weeks, never mind days.
        If there is anything related you want to know or run by me, feel free to drop me a line.

Comments are currently closed.