Skip to main content

Xash3D FWGS Status Update - December 2024

· 9 min read

This is a detailed overview of the changes that were made during the development of Xash3D FWGS engine in the year 2024. I would also recommend checking out the previous development overviews that were made for 2022 and 2023 years.

Consider Donating

GoldSrc network protocol support

by a1batross

Since this autumn, GoldSrc protocol support is in the mainline engine and available for testing for anybody. This feature is still a work-in-progress, but anyway it is good enough to be called playable. We appreciate any bug reports and contributions according to it.

For connecting to GoldSrc-based servers, you can use the console command: connect <ip> gs. Also, GoldSrc servers can be added to the favorites list - just don't forget to choose the proper protocol when adding it.

There is short footage of playing Counter-Strike 1.6 on some GoldSrc-based server.

But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto. Without this requirement, you will just get "Steam validation rejected" error on connecting. That is because proper authorization with Steam API is not implemented in engine yet. There is a list of things that are still unfinished:

  • Authorization using Steam API (first priority)
  • Voice chat on GoldSrc-based servers
  • Player sprays on GoldSrc-based servers
tip

To avoid misunderstandings: please note that this feature isn't made to circumvent Valve's DRM. It doesn't make it possible to connect to official Steam-based servers without having purchased Half-Life copy on your Steam account. Piracy is highly illegal and Xash3D FWGS developers always encourage everyone to get Half-Life from the Steam store.

Also, we encountered that some GoldSrc-based servers are recognizing Xash3D clients as "fake clients" and banning/kicking them. Maybe this problem will be solved along with better compatibility with GoldSrc behavior, but maybe not - we don't know the logic behind this useless "fake client" check.

Voice chat improvements

by SNMetamorph and a1batross

Fixed an issue when voice chat sound would become completely distorted when multiple players spoke simultaneously. Also, some settings related to voice chat were added to the multiplayer settings menu. Voice chat button was added to touch configuration for Android port.

There is short video with demonstration of working voice chat in multiplayer.

Server browser improvements

by Flying With Gauss

Added tabs with favorites and recent servers, basic server filtering was added (in the bottom).

Also, an entirely new menu for viewing server detailed information was added.

Support for Ogg Vorbis and Ogg Opus audio formats

by SNMetamorph

We've needed some kind of MP3 alternative for a long time. Since being invented back in 1993, nowadays MP3 is far inferior to its modern alternatives in both compression efficiency and audio quality. At the same time, also the best lossy audio compression codec Opus is open-source and free, and we're already using it for voice chat - why don't use it for audio files too? Also, some of the mods using really a lot of sounds, and at some point audio compression efficiency can save several gigabytes of disk space.

What about Vorbis codec? It's still better than MP3, but from practical point of view it can be useful in terms of backward compatibility with existing content (because, obviously, if you have lossy-compressed audio - it's better to not recompress it to another format, because this will lead to "generation loss"). Ogg Vorbis is pretty wide-spread audio format, also other idTech-based game engines supports it.

The sound looping feature, which was already supported in MP3, now also supported in both these formats too.

tip

If you not yet familiar: for Ogg Vorbis sounds file extension .ogg is used. For Ogg Opus sounds used .opus file extension respectively.

Video playback support

by a1batross

This is from that rare kind of feature, that had already been in the engine for a long time, but could not be used for technical reasons. Originally, video playback was dependent on the platform-specific "Video For Windows" framework and the ancient Cinepak codec. For proper working, it should be installed system-wide and also it's available for use only for 32-bit processes and exclusively for Windows. Because of that, users were having a lot of troubles while trying to get things working, and with some circumstances it was not possible at all.

In engine and some of the mods, we support (and use) 64-bit builds for a long time already. Also, we do care about other platforms rather than only Windows. This is why we decided to completely get rid of VFW-related code and instead use ffmpeg for video playback. Also, we decided that video playback support should be an optional feature - ffmpeg libraries are bulky; also, most mods don't use videos anyway. So, anybody who has plans to distribute mods along with the engine, or just want to free up some disk space will be able to just remove those libraries.

Here is a short demonstation of the video playback feature within PrimeXT. The original valve.avi intro video was used for it.

Port for Sega Dreamcast (WIP)

by maximqaxd and megavolt85

This is still in progress, but it already works on actual hardware. Port can load content that was originally made for Dreamcast port, because it supports all of that platform-specific content formats such as PVR with VQ compression and ADPCM WAV sounds. Multiplayer works too.

MacOS port rehabilitated

by sofakng

Project building issues on MacOS were resolved, and automatic builds for MacOS were added to CI. But this port isn't well-tested anyway, and it is possible to catch some MacOS-specific bugs: in this case, feel free to report it on GitHub. But our capabilities with the MacOS port are limited, since nobody from the developers has any relevant hardware, and because of it we're looking for a proper maintainer.

Compatibility with GoldSrc improved further

by Flying With Gauss

There isn't much to describe here, as it involves plenty of minor changes that are hard to track down retrospectively. In some cases, incompatibility was caused by differences in console variables. Sometimes, it was caused by differences in internal logic between GoldSrc and Xash3D.

  • Implemented PHS/PAS generating; this helped to fix issue #619
  • Added room_off console variable; after this Sven Co-op 4.8 client started working with Xash3D FWGS
  • Added gl_overbright from early GoldSrc versions, also some changes with gamma were made for better matching with GoldSrc looking
  • Added gl_fog console variable for toggling OpenGL's built-in fog implementation. Some of GoldSrc servers anticheats were checking this value
  • Added fps_override console variable for overriding framerate soft limit
  • Reverted ancient GoldSrc shadows, this feature was reintroduced to GoldSrc at the HL25 anniversary update - as of today, we support it too. It could be enabled with r_shadows console variable
  • Fixed broken physics behavior on high FPS: it was caused by rounding error in a physics code

Complete IPv6 support in multiplayer

by Flying With Gauss

As of today, engine and masterserver both support IPv6. And we have some masterservers running on the Internet through IPv6. This means anybody could set up their Xash3D FWGS server on the Internet with IPv6, and it will be presented for other clients who also have IPv6 address. Also, it is well tested, and we didn't discover any issues with it.

If you, for some reason, need to run a dedicated server exclusively on IPv6, you can use the -noip startup parameter, which completely disables IPv4 networking.

Published Docker image of up-to-date XashDS

by SNMetamorph

If you have some VDS or PC with an installed Linux distro, now it's possible to set up a Half-Life dedicated server based on the up-to-date Xash3D FWGS engine build in a couple of actions! Also, this Docker image has pre-installed Metamod, AMX Mod X, and bots using jk_botti Metamod plugin.

For now, a pre-built Docker image is only available for Half-Life, but in the future we hope to build images for other mods too (such as Counter-Strike 1.6).

Here is Docker Compose file example. You can read more information at GitHub repository.

services:
xashds:
image: snmetamorph/xashds-hldm:latest
container_name: xashds-hldm
restart: always
command: +map crossfire
ports:
- '27015:27015/udp'

Hardcoded sounds overriding through sounds.lst

by a1batross

This brand new feature can be used to override some of the hardcoded sounds in temp entities and server physics. You can read a more detailed description in the documentation.

Support for external textures

by a1batross

This feature allows you to create HD texture packs for classic mods without involving any code changes. Initially, this feature was presented in some of the old vanilla Xash3D versions, but was removed by Uncle Mike at some point, and now it's back here again. You can read a more detailed description in the documentation.

Other minor changes

by Flying With Gauss
  • Added SIGTERM signal handling for XashDS, it's needed for the graceful shutdown of the dedicated server inside Docker container
  • Enabled engine binaries signing for the Windows platform, this helped a lot with false-positive antivirus detections
  • Added console variable cl_logomaxdim for setting maximal dimension for player sprays, default is 96 units
  • Added more information to logs: engine build number, VCS branch name & commit hash, platform and architecture name, game startup parameters
  • FastDL improvements: support for chunked transfer encoding and gzip compression
  • Android port improvements: some platform-specific bugs were fixed
  • Reduced connection time to the servers: for now, you can connect to the server in less than 5 seconds (except time spent on content downloading, if it was required)
  • Entities state interpolation fixes: leaded to much more smooth and better multiplayer experience

Breaking down Toshiba 00DN901 customer display

· 5 min read

Introduction

Recently I found such an interesting and kind of vintage piece of hardware at local store - vacuum-fluorescent display (VFD) with 2x20 characters. So I decided to buy two of them for future investigations since they're relatively cheap.

Originally, display distributed with pole and cable. I got rid of pole since I don't need it, anyway you can find how it looks without any problems. About cable: it has familiar DB9 male connector on one side, but on other side there is some strange connector that vaguely looks like 8P8C, but I've never seen it before anywhere.

warning

Note that althrough DB9 connector is used, display is not compatible with common serial port, don't try to plug it in PC, it won't work and can even damage your port.

Proprietary connector on display cable

This is how display without pole looks like:

Dismantling the display

Let's try to detach front panel: that can be done with bare hands, you just need to pull front panel both down and away from the display.

tip

Front panel has dimming filter in it, and it is not glued or welded and can be easily pulled away, in case if you want to polish or clean this filter.

This is how front panel looks like on the back side:

Next, you need to remove three screws on both sides:

Display case without PCB, it has a lot of free space, even when PCB attached
PCB extracted from display case

First thing we see, is that display based on Futaba M202MD10C board. From this information I found out that display more likely uses UART with 9600-8N1 configuration (but also with inverted logic levels). So I'll test it in future steps. Also it's worth to notice that if you'll try to gather information about this board, you'll find much more than it was when I was doing all this research (reason will be described in the end of this post).

Determining pinout

But let's assume that we're at time point when all of needed information is not available yet. Next step we should do is determine display pinout. Probably, since display has only four pins, it shouldn't be that hard. I easily found GND pin and two VCC pins (that is so strange that we have 2 pins for VCC, but only 1 for ground). Therefore, last remaining pin is used for transfer data from microcontroller to display. As a result, we got this table:

Pin numberDescription
1GND
2DATA
3VCC
4VCC

We got pinout scheme and obviously next step will be applying voltage to display. But what exact voltage we should use? I guess that 5 Volts will not enough. Then I'll try 9 and 12 Volts. As it turned out later, 9 Volts also not enough. But with 12 Volts it worked - display showed underscore at first row.

Connecting display to MCU

And it's time to bring other hardware to this journey - I'll use Arduino Uno and try to send some information to display and check what will happen. For this we need pretty simple code snippet:

#include <Arduino.h>
#include <SoftwareSerial.h>

// display DATA should be connected to pin #3, pin #2 will be unused
// "true" as third argument means that logic levels will be inverted
SoftwareSerial softSerial(2, 3, true);

void setup() {
// sets proper baudrate according to information obtained earlier
softSerial.begin(9600);

// send some ASCII text to check is it even works
softSerial.print("Wake up, Neo...");
}

void loop() {
}

And it worked without any problems!

Conclusion

This post in theory can be much longer, I didn't covered determining other functions of display protocol, such as controlling cursor position, dimming, etc. But there is nothing interesting it in, really. It's just sending random bytes to serial stream and see what happened. For narrow down the number of possible bytes combinations I checked datasheets for similar displays from Futaba corporation. Also, some russian guy with nickname abomin helps me with code pages and custom character defining feature a lot. And one by one, I determined all things that this display can do.

And result of all this investigations was library for working with Futaba M202MD10C board on Arduino framework. This library exposes in it's API all possible functionality of displays based on this board. Library is well documented and contains bunch of code examples that covers different library functions. Therefore, there is no problems at all to create your own library that works with this display, in case if you want to use display with STM microcontrollers or just don't want to depends on any kind of frameworks.

After some time I got an idea to make thing like meteostation, but based on this display. It shows current air temperature, relative humidity, atmospheric pressure and carbon dioxide concentration on display, and also sends all of that information to Home Assistant through MQTT. That thing based on ESP8266 microcontroller, and sensors BME280 and MH-Z14A used too. Energy consumption of this device is around 6 Watts, a most of this bugdet used by display. This is how this device looks:

Compiling Half-Life 1 maps on Android TV-box

· 8 min read

I have been modding the legendary Half-Life 1 for these years, and somehow quite spontaneously I thought: how cool it would be to be able to compile maps on some platform other than the usual x86 and amd64... Then I remembered that I have an Android TV box at home that, in theory, could be used for this purpose. So, why not? This is how all this things was started.

What's we have?

In stock, I had a budget GoldMaster I-905 TV set-top box, which was completely unremarkable. It has 16 gigabytes of internal memory, 2 gigabytes of RAM. Based on the Allwinner H313 processor. From interfaces: has two USB 2.0 ports, composite video output, HDMI port. Network access can be provided both via Wi-Fi and via an Ethernet port (I used a wired connection).

Main information about TV-box system, shown by neofetch

Also, we need map compiler sources. For almost 30 years of the existence of the game, quite a few of their variations have appeared: the original compilers from Valve, ZHLT, VHLT, P2ST, etc. I will use the map compilers from my PrimeXT project: they are the most up-to-date at the moment, they will be the easiest to assemble and run under some exotic platform, unlike all other variations. The game itself, as well as all related utilities, including map compilers, are written in C/C++. PrimeXT uses the CMake build system.

Preparing

After a short search for information, I found out that in order to build C++ projects straight on Android, I need Termux. It needs to be downloaded from the F-Droid repository as the version published on Google Play has been deprecated and is no longer supported.

After installing Termux, just in case, update the installed packages:

pkg upgrade

Now let's install the packages that we actually need.

pkg install cmake git openssh pkg-config ninja

For more convenient work, I decided to run an SSH server on the TV-box and connect to it from my computer. To do this, I used a bunch of software KiTTY + WinSCP. Of course, you can use any other software instead. And you can do without an SSH server at all - just write all the necessary commands into Termux manually on the device. I will use WinSCP for convenient work with files on a remote device.

Now you need to start the SSH server: the procedure is quite trivial.
First, we need to set a password to connect to the server, and then start the corresponding service.

passwd
sshd

After that, you can try to connect from the computer to the server. Please note that Termux uses port 8022 for the SSH server, not the usual 22. You can enter any username, but you need to enter the password specified earlier. If the connection is successful, a shell will be displayed.

Building map compilers

After completing all the preparatory procedures, you can go directly to the build procedure: the first step is to clone the sources into your home directory.

cd ~
git clone --recursive https://github.com/SNMetamorph/PrimeXT.git
cd PrimeXT

Next, you need to bootstrap vcpkg package manager. You can be warned about missing packages, so you'll need to install they too.

export VCPKG_FORCE_SYSTEM_BINARIES=1
external/vcpkg/bootstrap-vcpkg.sh

Then, you need to create and prepare the directory in which the assembly will take place.

cmake -E make_directory ./build
cd build

And now it's time to generate the CMake cache and run the build. Since I'm only interested in map compilers, I disabled building game libraries, the launcher, and other utilities. Also, to make the compilation of the project faster, I will set the build to 4 threads.

cmake .. --preset utils-termux-debug
cmake --build . --parallel 4
CMake cache was successfully generated

After executing the two commands described above, the build process will start.

If the build succeeds, it will look like this. If any errors occur, it is better to restart the assembly in one thread, so it will be easier to find out exactly where the compilation error occurred. By the way, on this set-top box, the assembly into 4 streams took about four minutes, taking into account the fact that an IPTV player was running in the background.

Map compilers build successfully finished

Compiling map

For the final step, you need to prepare a working directory that will contain WAD files with textures, a .rad file, and a map source. In my case, this directory will be called gameres.

mkdir ~/gameres
cd ~/gameres

Then, inside this directory, you need to create a gameinfo.txt file with the following content:

basedir ""
gamedir "gameres"

Important tip: in this file, the value of the gamedir parameter must match the name of the working directory. Next, you need to put the WAD files used in the working directory, create a subdirectory called maps inside it, and put the .rad file and the map source in the form of a .map file into the subdirectory. All the necessary files that I used are available at this link.

Now you can try to compile the map, and all that remains is to wait.

cd ~/PrimeXT/build/Release/primext/devkit
./pxcsg ~/gameres/maps/crossfire_double1_v2.map
./pxbsp ~/gameres/maps/crossfire_double1_v2.bsp
./pxvis ~/gameres/maps/crossfire_double1_v2.bsp
./pxrad ~/gameres/maps/crossfire_double1_v2.bsp

The map compilation process consists of four steps. At the end of each stage, the time spent on it will be displayed. If there are any problems during the compilation of the map, you can look at the log file in the maps subdirectory. Also, you can add the -dev 5 startup option to compilers to display the process in more detail.

Last map compiling stage was finished

Checking the results

After the map successfully compiled on the TV-box, I decided to rebuild the same map on my computer and then compare these two maps. Ideally, there should be no visible differences. I will test this whole thing in the PrimeXT mod, which is based on the Xash3D FWGS engine.

Maps build on different architecture and platform

The engine has a mapstats console command that allows you to display various internal information about the map. For our situation, this is exactly what we need.

Stats of map compiled on TV-box

Object names  Objects/Maxobjs  Memory / Maxmem  Fullness
------------ --------------- --------------- --------
entities [variable] 64780/1048576 ( 6.2%)
planes 2179/65536 43580/1310720 ( 3.3%)
textures [variable] 4976/33554432 ( 0.0%)
vertexes 11219/65535 134628/786420 (17.1%)
visibility [variable] 199238/16777216 ( 1.2%)
nodes 5031/32767 120744/786408 (15.4%)
texinfo 1383/65535 55320/2621400 ( 2.1%)
faces 8467/65535 169340/1310700 (12.9%)
lightmaps [variable] 1745778/33554432 ( 5.2%)
clipnodes 12686/32767 101488/262136 (38.7%)
leafs 3260/32767 91280/917476 ( 9.9%)
markfaces 11552/65535 23104/131070 (17.6%)
edges 20150/1048576 80600/4194304 ( 1.9%)
surfedges 40037/2097152 160148/8388608 ( 1.9%)
models 142/1024 9088/65536 (13.9%)
deluxmaps [variable] 1745778/33554432 ( 5.2%)
=== Total BSP file data space used: 4.53 Mb ===
World size ( 5120 5824 3920 ) units
Supports transparency world water: No
Lighting: colored
World total leafs: 2318
original name: maps/crossfire_double1_v2_arm.bsp
internal name: desert
map compiler: PrimeXT Tools v.0.90 (Dec 15 2022 / 1397a04 / armv7l / android)
map editor: J.A.C.K. 1.1.2800 (vpHalfLife)

Stats of map compiled on my PC

Object names  Objects/Maxobjs  Memory / Maxmem  Fullness
------------ --------------- --------------- --------
entities [variable] 64777/1048576 ( 6.2%)
planes 2179/65536 43580/1310720 ( 3.3%)
textures [variable] 4976/33554432 ( 0.0%)
vertexes 11210/65535 134520/786420 (17.1%)
visibility [variable] 198643/16777216 ( 1.2%)
nodes 5031/32767 120744/786408 (15.4%)
texinfo 1383/65535 55320/2621400 ( 2.1%)
faces 8465/65535 169300/1310700 (12.9%)
lightmaps [variable] 1744599/33554432 ( 5.2%)
clipnodes 12747/32767 101976/262136 (38.9%)
leafs 3258/32767 91224/917476 ( 9.9%)
markfaces 11512/65535 23024/131070 (17.6%)
edges 20138/1048576 80552/4194304 ( 1.9%)
surfedges 40013/2097152 160052/8388608 ( 1.9%)
models 142/1024 9088/65536 (13.9%)
deluxmaps [variable] 1744599/33554432 ( 5.2%)
=== Total BSP file data space used: 4.53 Mb ===
World size ( 5120 5824 3920 ) units
Supports transparency world water: No
Lighting: colored
World total leafs: 2316
original name: maps/crossfire_double1_v2.bsp
internal name: desert
map compiler: PrimeXT Tools v.0.90 (Dec 16 2022 / 1397a04 / amd64 / win32)
map editor: J.A.C.K. 1.1.2800 (vpHalfLife)

As you can see, there are still minimal differences in stats. It is difficult to say what exactly is the reason for these differences, but most likely they are completely uncritical. Next, it makes sense to compare if there are any visual differences on the map itself.

Screenshots of map compiled on my PC

Screenshots of map compiled on TV-box

Personally, I didn’t notice any visual differences in lighting or geometry at all, which of course is good. The experiment can be considered successful.

Resume

Using the procedures described above, it is quite possible to compile maps for Half-Life 1 on almost any device that is based on the Android or Linux OS. Unless, on too large and detailed maps, the device may not have enough RAM for compilation. Can all this be useful to someone? Of course. For example, if for some reason you don’t want to load the main PC, or there are no devices other than a smartphone at all, but the map needs to be compiled somehow.

Windows typical exception codes cheatsheet

· 2 min read

For somehow strange reason, there is no handy list of common Windows application exception codes list on the entire Internet. At least, I can't find it in Google. So I decided to make this one here. Also I think in future this list can be extended with more info.

Exception codeNameCause of exception
0xC0000005STATUS_ACCESS_VIOLATIONReading or writing to an inaccessible memory location
0x80000003STATUS_BREAKPOINTEncountering a hardware-defined breakpoint; used only by debuggers
0x80000002STATUS_DATATYPE_MISALIGNMENTReading or writing to data at an address that is not properly aligned; for example, 16-bit entities must be aligned on 2-byte boundaries (Not applicable to Intel 80x86 processors)
0xC000008ESTATUS_FLOAT_DIVIDE_BY_ZERODividing floating-point type by 0.0
0xC0000091STATUS_FLOAT_OVERFLOWExceeding maximum positive exponent of floating-point type
0xC0000093STATUS_FLOAT_UNDERFLOWExceeding magnitude of lowest negative exponent of floating-point type
0xC000001DSTATUS_ILLEGAL_INSTRUCTIONAttempting to execute an instruction code not defined by the processor
0xC0000096STATUS_PRIVILEGED_INSTRUCTIONExecuting an instruction not allowed in current machine mode
0xC0000094STATUS_INTEGER_DIVIDE_BY_ZERODividing an integer type by 0
0xC0000095STATUS_INTEGER_OVERFLOWAttempting an operation that exceeds the range of the integer
0x80000004STATUS_SINGLE_STEPExecuting one instruction in single-step mode; used only by debuggers