As a way of checking that the stuff I’m posting on GitHub, I’ve been downloading them onto a laptop and testing them.
The laptop is a seven year old Toshiba that was re-purposed from Windows to Ubuntu 18.04 LTS, the same version as I’m running in a Hyper-V session on my main development PC.
Although the laptop is older and only running an i3 chip, it still outperforms the game code running under Hyper-V code on my five year old i7-5930K PC. I think the difference is purely because the GPU code is run in a software layer not on the real GPU. But I might be wrong.
When I tested it with 255 asteroids on screen the laptop still maintained 60 fps but the Hyper-V running version dropped below 60 fps once there were 125 asteroids on screen. I have a suspicion that C code that isn’t calling any SDL routines would run faster under Hyper-V because it’s virtualised.
There are four steps to do this. That’s assuming that you have successfully compiled your C or C++ program and have the source file handy.
Install Disassembly Explorer extension into Visual Studio Code.
Set a configuration setting.
Run a single line command in terminal.
Select a command in the Visual Studio Code command palette.
Install Disassembly Explorer.
In Visual Studio Code just switch to the extension tab and search for Dissassembly Explorer and click the install button.
Next is configuration
View the installed extensions and click the cogwheel for Disassembly Explorer then click Extension Settings at the bottom of the popup menu. A Settings tab will open, click Edit in settings.json.
You should see a few settings but only this one matters: “compilerexplorer.compilationDirectory”: “${workspaceFolder}/.vscode” . That path is where the compile etc. .json files are located.
Now open a terminal
I’ve assumed that you are running on Linux or Mac. If you are on Windows, you can also use Visual Studio Community Edition which includes disassembly features and why I’m not mentioning it here.
In the folder with your source files issue this command in the terminal.
clang -g -o asteroids.S -S asteroids.c
If OTOH you are running gcc then just substitute gcc for clang.
Finally, back in Visual Studio Code select your source file as the open tab then press F1 and in the menu that appears type in enough of Disassembly Explorer: Show until you can select it and a second tab should open with the disassembly. Click on a function in the source tab and it will jump to the correct place in the disassembled code.
In the chapter 42 of both e-books when the first collision detection is introduced, I added a SHOWOVERLAP #define. If this is uncommented, instead of things blowing up, it shows every pixel where two objects pixel’s overlap in bright green.
In the picture above you can see the player ship in the centre and all those green bits where things overlap. You don’t normally see this and it is so intensive that it drops the frame rate from the usual 60 fps to about 3 or 4. But I think it’s quite cool!
How did I fix it? Did I spend hours debugging, poring over every line? No. I woke up in the middle of the night and thought about it and remembered that
I’d had a similar bug in this chapter when working on the original Ebook.
Stupidly I’d put the fix in the sources for the next chapter (44) but hadn’t applied it to the sources in the chapter where it had occurred (42). So I fired up my favourite code comparison tool (Devart Code Compare) and looked for differences between the source files for each chapter.
This was in the function AddObjectToCells and is part of the collision detection. It’s when an asteroid or player ship is partly on screen and calculating the cell coordinates that the object lies over. The fix was just adding these two lines so it doesn’t try and access the cells array with negative indices.
if (cellx < 0) cellx = 0;
if (celly < 0) celly = 0;
Once I reached the masks section in chapter 38, I found my C code that I’d copied from Windows failed because of the type byte. MSVC is a little bit more forgiving over somethings and one of those is the byte type which it accepts. In the Windows code, I had declared the mask arrays like this:
But Clang in its wisdom barfed at that, not recognising the type byte. A simple fix was replace byte with char and all was well.
Looking into it, I loaded one of the Windows asteroids projects, built it and then did a ctrl-click on the byte type. It led me to a file called rpcndr.h in a Windows SDK folder and this line (191) of code.
I’m up to chapter 42 in the Linux e-book. The rest have gone very smoothly though I’m still unable to debug either on my Hyper-V Ubuntu or my Ubuntu running laptop. Both still have the same problem XDG_RUNTIME_DIR not set in the environment.
I’ve been reading up on that and it seems if you switch into root and the value of the environment variable $XAUTHORITY is blank then that is the problem.
My error logging is picking up problems with sound channels not playing. I think the problem is, when I hit the b key to make lots of asteroids explode, it uses up all available sound channels and there’s still explosions happening. Not really a problem.
But to cap it all, there is a segmentation error happening with a core dump. A segfault which kills the program. But it’s not related to the sound problem. I’ve proved that by commenting out the entire PlayASound function. It now looks like this which I call the sound of silence.
So without being able to run the program in a debugger, I’m forced to start putting in lots of logging calls and figure out where the segfault happens that way. It’s an effective way of finding bugs BUT it’s not the fastest! I have also enabled apport to try and get the crash files created in /var/crash so that may be a faster way forward.
Once I have fixed the segmentation fault, I’ll upload the fixed code to Github. It’ll be somewhere in the new code added between chapter 37 and chapter 42, to do with collision detection. Time to put on a deerstalker hat!
I’ve added a page (you can see it in the bar just below the banner) for C Code links. Just because the primary aim of this blog is about Learning C Games (programming), that includes learning C and there’s often no better way than studying or using other people’s source code.
As I come across code, I’ll add it here. I’ve started it off with Awesome-C which is a very comprehensive set of open source links.
I wrote the first book on Windows and used Visual Studio Community Edition 2017 (VS). For Linux I’m using Visual Studio Code (VSC) but if you are working on Windows you have the choice. So which is better suited to you?
Disassembly of OutputDebugString program
Given that my full time job involved Visual Studio Professional, it wasn’t a difficult choice for me, though having used VSC on Linux, I’m now warming to it.
I found the configuration messy but if you stick at it, you get there. It’s a fairly simple product but once you get into all the configuration and extensions, there’s a lot more to it.
VS (now at 2019 version) is an excellent tool and the navigation features and debugging are better than VSC. You can also view disassembly of C code as the screenshot shows.
But if you are also working on Linux or Mac and using VSC, it might be easier or at least more consistent using it for all platforms. Mind you there’s also the question of MSVC vs Clang to sort as well.
VS has extensions but only 3271 currently compared to 16934 for VSC and many of the VS extensions are trial while it appears that all of VSC are free. There’s also nearly ten times as many programming language extensions for VSC (3427) compared to VS (351).
So there’s no outright clear winner here. YMMV as the saying goes. (Your mileage may vary). Here for your delectation is that disassembly including the original C lines. Don’t worry, I won’t publish too many of these!
In the post about rsyslog three days ago, I explained how to log from Linux programs using the rsyslog daemon.
It’s slightly different in Windows. There’s a built in function called OutputDebugString(LPCWSTR str) that you can call from anywhere in your program. It dumps the string str into the Output window if you are debugging it in Visual Studio.
If you are running this outside of a debugger, the output is lost unless you can capture it with a suitable utility. DebugView from SysInternals.com (it redirects to Microsoft) is one such utility. That’s a screenshot of it below.
Just run DebugView and leave it there. It might catch other stuff from Windows, but when you run your program from the command line or double click on it, it will execute quickly and you’ll see any strings captured like this one.
This is the program that I ran. In Release it compiles to a 9 KB exe! Because OutPutDebugString needs a LPCWSTR (Long Pointer to a WideString), I declared the text as wchar_t.
At work I developed a very large program that only worked running on another computer. I used OutputDebugString extensively and without it, debugging would have been much harder.
I originally created Asteroids for Windows using Visual Studio 2017 Community Edition. Since then I’ve started the Clang version on Ubuntu and there haven’t been too many differences but there are just a few so in this post I’ll list what I’ve found so far.
Include Paths
On Windows, I was able to get away with #include <SDL.h> but on Linux, I’ve had to include the path so it’s #include <SDL2/SDL.h>. This was probably because I included the full path in the MSVC configuration.
Link Failures
The asteroids.c code in chapter 29 uses sin and cos for the first time and the linker was unhappy with that. So in tasks.json, I’ve explicitly had to add it into args, along with SDL2 and SDL2_image,