Skip to main content

· 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.

danger

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:

· 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.

KiTTY Interface KiTTY Shell after logging in

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.

· 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