I’m a simple man. I see #RSS I subscribe. 😄
This is the journey of getting head tracking for X4 Foundations on Linux. Browsing the in-game options I found key bindings to enable and reset a head tracker so I got my hopes high for head tracking for X4 on Linux and started reading.
tl;dr: The native build of X4 does not support this at all. It even lacks the symbols in the executable. There is hope with Wine though.
While seeking through the patch notes two things catched my eye (harhar). The notes suggest support for Tobi Eyetracker and somewhat earlier TrackIR. The Tobi one was marked as “Windows only” so I hoped for TrackIR and tried to understand what is involved into getting this particular head tracking to work.
Please do keep in mind that I never touched any head tracking before so I had to grasp the theory behind all this first.
So apparently there are not many possibilities to configure anything in-game. There is the additional start parameter
-forcehmd that may have some effect here but that’s about it. So everything related must come from the outside, right?
Funny enough a Kerbal Space Program extension on GitHub provided me with the idea how TrackIR is supposed to function: https://github.com/pizzaoverhead/KerbTrack/blob/master/KerbTrack/TrackIRClient.cs#L45 so let’s clear that one up: The code looks for the registry entry “
Software\\NaturalPoint\\NATURALPOINT\\NPClient Location” that points to the
NPClient64.dll) which in turn in loaded by the executable if found and accessed. And sure enough I found the same pattern by using the good old hexeditor on
X4.exe as well:
You may suspect this already but none of that can be found in the X4 binary for Linux and this is the end of the story.
Appendix: It might be possible that a joystick look-around thingy may be abused for this but since I do not own such a joystick (yet) I wouldn’t know how to fake such signals.
A new hope
During my research on head tracking on Linux I stumbled over the website https://tkoletivrijedi.in.rs/node/219?language=en that mentioned the OpenTrack project https://github.com/opentrack/opentrack to play Windows games with Wine on Linux. How cool is that? A quick check suggests that OpenTrack features (also) the output protocol “freetrack” for Windows and a “Wine freetrack glue protocol” for Linux and OSX.
Freetrack seems to be a implementation of what TrackIR does up to version 4. Looks like the company didn’t like that or was afraid that some tinkerers use self built head tracking devices and not buy their ~200$ hardware any more so they added encryption to their devices with version 5 leaving freetrack dead in the water. Or whatever. So if a game would only support protocol 5… it’ll probably no longer work. Anyway, let’s jump into OpenTrack and give it a try. Once all required developer packages are installed, that includes the wine-devel packages for i686 (and libevdev if you want virtual joystick support), this can be compiled:
git clone https://github.com/opentrack/opentrack cd opentrack mkdir build cd build ccmake ../ make -j4 make install ./install/bin/opentrack
The important part is to tick the
SDK_WINE option or we don’t get the precious Wine Glue. Here, have a video:
And sure enough we find the following already familiar files in
So what OpenTrack does is once it’s started and configured to use “Wine — Windows layer for Unix” as Output: It “injects” the key
[Software\NaturalPoint\NATURALPOINT\NPClient Location] to the
user.reg of the configured Wine/Proton prefix on start while the also started
opentrack-wrapper-wine.exe.so is used for the shared memory mapping – means from my understanding from the OpenTrack binary to some Wine process.
TrackIR.exe is just a dummy that may also be run with Wine but does nothing. It’s apparently for games that check for a process with that name before they initialize head tracking features. Neat, huh?
For this to work you have to click on the little hammer symbol next to Output so make sure that your Wine Prefix is properly configured or OpenTrack may insert the registry key to the wrong Wine prefix. Sure enough it seems to come Steam and Proton ready as well but I did not try this because I made the mistake of buying X4 on GOG (I know this is getting old).
So what’s next? Oh yes, a Head Tracking device. Well bite me, I don’t even have any. Why did I go through all this trouble at all?
The head tracking device
Well why should I purchase such a device without knowing if I can even use it? Do you know what kind of device has a gyroscope built in however? Yes, every average smart phone has one and some are even really good (I hear.) So here comes the fun part: I strapped my mobile phone to my headphones while an app sends the tracking information via wifi and the UDP protocol to OpenTrack as input source.
So I will not bore you with the details how I configured and mapped this in Opentrack. It will be of no use for you anyway since this depends totally on your device and system but I can tell you that this is a lot of fiddling with the settings. Also know that a 3-point device can indeed be built for ~10$ with some LED and a webcam – there are various people demonstrating this on the net and you will find plenty on the usual video platforms.
I don’t like to have to install the game twice now, once native and once with Wine, but… it’s for science! Or so.
Yes, it’s a little clunky. This is probably because:
- my phone sucks
- my phone really sucks (seriously)
- it’s UDP – order of packages is not guaranteed
- it’s wireless and the access point is two walls away
- …and I probably also messed up with the mapping and filter options 🙂
- I even read that it’s not any better on Windows xD
So that’s it. Head tracking on Linux for X4 Foundations. Jumped the hoops 🙂
Meh… that’s exactly the HDMI capture I got months ago. I needed it mostly to debug some Raspberry boot trouble that would show way too short to be parsed by a human before the device would reboot again so it’s okay. I did wonder though why the framerate was so jacked up but blamed the undervolted HDMI splitter (It came without a fitting PS so I’m happy that it does _something_).
Lesson learnt. I suspect similar for a dead cheap SD-card writer at work.
I’m having way too much fun with this. Did some plumbing today and this is the result 😀
The flight instruments are from https://github.com/uw-ray/Skyhawk-Flight-Instruments and are not for #x4foundations obviously.
I patched the http server to send Access-Control-Allow-Origin so the browser wouldn’t refuse to load. Could set up a proxy but I wanted results fast xD
- Speed is also mapped to ALT as Fast Travel speed
- It reads just the camera position and not really the ship position (and since there is no up and down in space it settles fast on the new artificial horizon – may need some more tuning)
- Plumbed the speed to the pressure so it starts creeping up from 27.1 inHg to 33 inHg (max on the instrument) when speed goes over 200. Just for fun.
- Turn Coordinator is just Camera yaw + left or right based on mouse/pointer X.
- Some target data as proof of concept
This worked out better than expected and the best thing is: Doesn’t need to run on the same computer – it just has to be on the net so a tiny Raspberry and some external display would be enough for some fun cockpit building 8)
I found https://github.com/Alia5/X4-rest-server/ today and it makes me way to excited. Tricky to set up and “just” a proof of concept (that proofs very well) but look at this: #x4foundations with a REST server that lets you read (and partially set) additional gamedata more or less live. Awesome! Could plumb all sorts of stuff on that!
Getting into #x4foundations modding is a painful experience for a newcomer especially when on a clock (as in: Ain’t no time for this) so here is what I understood so far.
EgoSoft is one of the few companies that still hold on to a forum. They may be on social media but that’s just as news outlet. This is somehow also where the modding community resides, when it usually would find a place on it’s own “elsewhere”. Clever move and I applaud – at least I don’t have to join some private group on Facebook.
Sadly the forum has no search function to speak of especially not for a technical search or, gasp, a code search. So most mod developers usually host their stuff elsewhere – like scattered on GitHub, and only talk about their mods here and there. Connecting the dots (and users) is up to the initiate. In fact it helps slightly to utilize an external search engine that does a better job compared to the forum search itself. Go figure.
Eventually I stumbled by accident or luck over a Confluence installation that seems to act as some sort of Wiki and has indeed some pointers on modding for various X titles at https://www.egosoft.com:8444/confluence/ – and I am still uncertain if this is intended to be public or not. Sadly the X4 modding articles in there are short and of course available in English only. That wouldn’t be an issue if Confluence wouldn’t stubbornly insist in trying to render a page in my native language first, informing me helpful every time that no such entry exists and makes me switch the language every single time back to English. Well, I guess it is a community driven documentation system so I could scratch my own itch and translate stuff. Thing is I should understand what I’d be talking about in the first place, no?
Turns out that most know-how for X4 modding can in fact be learnt from X3 and X Rebirth in particular. Both are precursors and partially sandboxes for X4, from my understanding, so a lot of the information does also apply to X4. Sometimes with slight differences.
The most helpful place however is an unofficial Discord channel where many of the mod developers hang out and they do seem to be really friendly to newcomers asking the same old questions over and over again. I won’t bother with the invite link as this one is subject to change all the time but it can indeed be found with the dreaded forum search.
The extension file formats (and formatting)
Anyway, let’s dive into some details. Mods, or as it should be called nowadays “extensions”, consist usually of so called MD Scripts, that’s short for Mission Director (and not Markdown) written in well formed XML Syntax, and LUA scripts (that seems to be the gaming industry standard – at least I keep hearing that). LUA itself is explained in great detail in the online documentation of LUA while game specifics are listed in varying detail on the Confluence mentioned above but that’s subject for another article. Also various assets may be floating around in the extension folders.
Now in theory XML and LUA are completely system independent so modding with different systems in mind should be a no brainer, right? Right?
Well, of course nothing is ever that easy. Thankfully the user CulunTse took the burden and wrote an article on all the caveats encountered so far: https://forum.egosoft.com/viewtopic.php?t=380912 (Steps to make your mod work on Linux+Mac) – it’s for X-Rebirth but the gist applies for X4 as well. So when writing mods make sure to use lower case only and don’t use special characters at all. Best not even use a white-space just to be sure.
So now we learnt that an extension consists mostly of XML and LUA files, so how comes that mods downloaded from Steam, e.g. to learn from, are riddled with various TXT files instead rendering your linter of choice useless because it won’t automatically parse a text file? Well that seems to be a Steam Workshop limitation not allowing certain file… extensions. So developers started to rename their files when uploaded to Steam. Yay, more confusion for man and machine (as in mankind – c’mon, it’s a lame allusion!).
Why I mentioned Steam now? Well, learning from existing extensions is the way to go. Also since some simply don’t work for Not-Windows users it’s up to myself to debug. The places to get extensions is usually from NexusMods (no thanks, still angry that they lost my user data years ago – still used by scammers) and Steam. Avid readers of my ramblings may know my especially sour spot of having purchased X4 on GOG (https://beko.famkos.net/2021/03/17/x4-cradle-of-humanity-for-linux-and-gog/) so downloading from the Steam Workshop is not as straight forward as it is for others. There are various so called “steam workshop downloader” that easy the pain somewhat.
But wait. The Steam Workshop file comes as DAT file. What is that again when I just talked about TXT files? Well, this is from my understanding a format by EgoSoft designed for Steam Workshop files for X Rebirth – also called a XRWS file. At least from https://github.com/Lighting/XRWSunpack – a tiny little project that helps unpacking the DAT files but has to be compiled before use. That’s usually a matter of issuing the
make command after checking out the repository (or download the release file if you’re feeling lucky). Fair warning: It is somewhat rigid in the way the DAT file has to be named so you may have to adjust that by renaming. Ymmv.
Armed with that knowledge I was able to download and extract the awesome
extensions_fireandsmoke_v107.dat extension that really spices up space fights with the effects we know and love from X Rebirth (or not). This one I could also drop in my user space folder under
~/.config/EgoSoft/X4/extensions/x4_fireandsmoke/ (again: case sensitive, important). The folder name matters because it is also hardcoded into the extension files itself and will fail to load various assets if changed. Interesting design choice.
Why this is noteworthy? Well apparently this does not work for all kinds of extensions. Some seem to work only when put in the game path
/path/to/X4_Foundations/game/extensions/ where the game also stores official DLCs. Better keep that in mind. The gist seems to be that user space extensions are limited in functionality to prevent nefarious mods. Or so I hear. Maybe EgoSoft simply never got it working properly. There is more (conflicting) info hidden deep in that Confluence mentioned above.
One extension to rule them all (and a pipe)
So why go through all that trouble when an extension can simply be downloaded from e.g. GitHub? Well, I learnt the hard way: Also not as simple. For example many mods rely on one very important extension that can be found in the repository https://github.com/bvbohnen/x4-projects – a wild mix of various extensions and even a Pipe Server (more on that later). It’s the indeed impressive extension
sn_mod_support_apis featuring a clever way to work around some UI modding limitations in X4, allowing lazy loading of further LUA scripts and even introduces a Pipe Server to interact with the game from the outer world – mostly used for more complex hot keys. A dream coming true and used by many other extensions as well.
Sadly it didn’t really work out of the box when checked out from GitHub and put in place at
/path/to/X4_Foundations/game/extensions/sn_mod_support_apis/. There were various reasons for this. First of all: Case sensitive again. The XML files in the
md/ folder must be lower case or X4 will simply ignore the files. Easily fixed though.
The next problem wasn’t that easy to identify and the reason for this is hidden in plain sight in this titbit of information from the synopsis:
A workaround is to load in custom lua files alongside the egosoft lua. This is done by editing one of a handful of ui.xml files in the ui/addons folders, adding the path to the custom lua file. These ui.xml files cannot be diff patched. The lua file must be given an xpl extension, and this xpl and the ui.xml must be packed in a “subst” cat/dat.bvbohnen/x4-projects
Where this arcane know-how was acquired from in the first place I do not know. The gist is that some XML files are happily read by X4 (and can even be hot reloaded) while some can not. The
ui.xml falls into the not so much category and since I have no idea how to create a cat/dat file (yet) I had to scrape the “subst” files from a release (Steam Workshop, NexusMod, GitHub release, you name it). Without it’s simply not read and ignored and this is also why no single debug line will ever be logged to give the (weary) initiate a hint what may be wrong.
After that mods relying on
sn_mod_support_apis started working (or throwing traces at least). Awesome! Onwards to Pipes! Or Not! Because this part is Windows only. Why? Well, the Pipe Server uses a LUA feature to load a library from disk providing that pipe feature. And that project is written in C, compiled as a separate DLL and relying on Windows, of course. That makes even sense and I really can not blame the author for scratching the own itch only here. See https://github.com/bvbohnen/x4-projects/blob/master/extensions/sn_mod_support_apis/lua/c_library/winpipe.lua for details and to be fair the extension is written in a way that other features do still work so it’s not a total roadblock and in theory I can go back to be a happy gamer at this point.
Alas I want that Pipe feature, of course, so I have to come up with my own library at this point. It’s not a complex file but my C days are long past. So to spice this up I needed a crash course on how LUA is supposed to work. Script wise and all and I don’t think I was prepared for all this.
Diving into the unknown (What is LUA/JIT anyway?)
LUA is basically… ah frell, go and look it up yourself. In the end LUA scripts are interpreted by a VM. That would be LuaJIT (JIT – Just In Time) on Linux and this is why X4 is shipped with a file named
libluajit-5.1.so.2. Sadly this is not the particular version of LuaJIT. It stands for an ABI compatibility version. In theory at least. My first goal to get the idea was to grab the source and compile my own libluajit. Should be a no brainer, right? Little did I know when I checked out the project from https://github.com/LuaJIT/LuaJIT.
I run a hexedit on the distributed library to get an idea what version is used and came up with 2_1_0_beta3. The commit 8271c643c21d1b2f344e339f559f2de6f3663191 of the LuaJIT project is tagged with that version so I went with that first.
Compile went smooth, beside some warnings, but X4 would stop dead throwing a Fatal Error at me that I’ve never seen before. Well, let’s fast forward to HEAD and try again and this time the game started but became stuck in main menu with unresponsive entries and missing labels (some said “Processing…”). So obviously X4 is not running vanilla LuaJIT and since this is under MIT licence I don’t think they even have to provide modifications. What now?
Thankfully some fellow gamer on Telegram, who doesn’t want to be named, pointed me in the right directions due to experience with LUA. An article over at https://developer.x-plane.com/article/luajit/ explains some major caveats with this and sure enough once I knew what I was looking for I found evidence here and here and here. (Yes, they have Jira as well – who would have guessed).
Lua engine was upgraded to LuaJIT 2.1 which comes with performance improvements as well as new language features (incl. some added Lua 5.2-specific features as well as some Lua 5.3 ones.
Just looking at the number of forks of LuaJIT on GitHub makes me dizzy so I went with the first recommendation https://github.com/openresty/luajit2 that also addresses the memory issue and also edited the file
src/Makefile enabling some LUA 5.2 features by commenting in the line: XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT
And guess what, X4 launched with this and also started an older save game of mine just fine. I guess this works so I’ll keep that in mind in case I need some monkey patching to try stuff.
Next on that list? Find out how to write a loadable C library for LUA and adapt that Pipe Server.
At least gaming itself is easy as pie on Linux in 2021. Modding? Now so much.
Not a big fan of reveal parties n stuff so here goes what some close friends know already:
If I had just one wish
Only one demand
I hope he’s not like me
I hope he understands Creed, With Arms Wide Open
(I’m bad with words)
The little one (7) saved for a new toy camera. After doodling around with the camera she mentioned wanting to make “movies” so I gave her a little tripod and suggested to go for a Stop Motion one. She listened to the overall idea and vanished in her room. A day later I was presented with a SD card full with over 300 pictures of one scene each carefully adjusted over the course of three hours.
I’ve to say I am really impressed with what she achieved here on her own just by listening to some ramblings of mine and fiddling with that toy camera, that sadly is not even able to write legit JPG images so they couldn’t be used as input for
ffmpeg to make a movie out of the sequence. ImageMagick had my back though converting the faulty images to PNG and with two lines of console commands we managed to produce a movie she can proudly show her friends now:
mogrify -format png *.jpg ffmpeg -framerate 5 -pattern_type glob -i 'PICT0*.png' output.mp4
Of course she asked for an audio / voice-over next. Should have seen that one coming xD
Are you interested in writing a modern, RESTful, scalable solution to common problems?
Learn from existing projects – like FOAAS (Fuck Off As A Service): https://github.com/tomdionysus/foaas.
This post was written in a hurry in response to some misinformation about Google’s newest Web antifeature, Federated Learning of Cohorts (FLoC). Google’s FLoC is an attempt to track users even when their browsers (rightly) block third-party cookies. The initial blog posts about this issue were q...
Who would have guessed: That empty policy header against FLoC is probably worthless in the first place because people that are concerned about this are probably not affected by a prior opt-in at all: https://seirdy.one/2021/04/16/permissions-policy-floc-misinfo.html
Really curious what else will show up on this topic over the next weeks.