DocumentationClient from source▾

Client from source

Besides the classic DLL client, the server is now compatible with the client rebuilt from source: a C++ port of the 0.97k main.exe, reverse-engineered from the original binary.

Unlike the DLL client — a closed executable with a library injected into it — here you have the code. You build it, modify it and debug it like any other C++ project.

Where it stands. It starts, connects, logs in, enters the world and is playable: terrain, characters, inventory, equipment, chat, party, guild, shop, vault, combat and effects all work. It is not a finished client — it is a reconstruction in progress, and differences keep surfacing as new code paths get exercised. For production, the DLL client is still the stable option.

Which one to use

DLL client Client from source
How the IP is configured ClientInfo.bmd (InfoEncoder) server.cfg, plain text
How you get it ready-to-ship folder you build it yourself
Status stable, proven in production reconstruction in progress
Can be modified no, it is a binary yes, it is source code
Native Linux no not yet — see below

If you just want to run a server and have people play, use the DLL client. This guide is for anyone who wants to build it, study it or modify it.

Building

You need Visual Studio 2022 with the C++ desktop toolset.

  1. Open mu97k.sln
  2. Select the Debug configuration and Win32 platform
  3. Build

The executable lands in bin/Client/main.exe. The project links straight into that folder, which is where the assets and the configuration live, so there is no intermediate copy and no risk of running a stale binary.

The platform has to be Win32 (x86). The whole port assumes 32-bit pointers: the original binary’s addresses, the struct layouts and the memory pools. It does not compile on x64, and if it did it would not work.

The libraries it links are all from the Windows SDK (opengl32, glu32, winmm, ws2_32), except libjpeg which is bundled in the repository. Nothing else to install.

Configuring: server.cfg

This is the main difference from the classic client. There is no ClientInfo.bmd and no InfoEncoder: the configuration is a plain text file called server.cfg, next to the executable.

127.0.0.1 44405        <- ConnectServer (server list)
127.0.0.1 55901        <- GameServer (fallback)

CustomerName=MuLinux
ServerSerial=TbYehR2hFUPBKgZj
ClientVersion=0.97.11

The addresses

With two lines the full ConnectServer flow is used: the client asks for the real server list, the server replies with names and occupancy, and picking one redirects you to the GameServer. With a single line it connects straight to the GameServer, which is the classic behavior.

Replace 127.0.0.1 with your VPS public IP on both lines.

The server identity

The three values below have to match your server’s, in MuServer/GameServer/DATA/GameServerInfo - StartUp.dat. If any one of them does not match, the client connects but never gets in, with no useful message:

Key Where it comes from What happens if it does not match
CustomerName CustomerName= in the .dat Connects, decrypts garbage and hangs on “connecting to GameServer” forever
ServerSerial ServerSerial= in the .dat Same as above, plus the login returns “wrong version”
ClientVersion ServerVersion= in the same .dat Login rejected with “wrong version”

CustomerName and ServerSerial feed the encryption key, which the GameServer derives from the two combined. That is why changing the client’s name breaks the connection even when everything else is right.

If they are omitted, the project defaults are used (the ones in the example above). ClientVersion accepts both 0.97.11 and 09711.

Client options

The original 0.97k reads these options from the Windows registry, which is where the official launcher leaves them. Since there is no launcher here, they are also accepted in server.cfg and, when present, they win over the registry — so you can ship the client already configured.

Key Default What it does
MusicOnOff 0 Background music. It is off in the original binary; the example ships it as 1. The client does not decode the mp3, it launches MuPlayer.exe.
SoundOnOff 1 Sound effects.
Resolution 0 Index 0..4 or WIDTHxHEIGHT, but only the binary’s five: 640×480, 800×600, 1024×768, 1280×1024 and 1600×1200. Anything else is ignored and it starts at 640×480.
WindowMode 1 1 = windowed, 0 = fullscreen.
Borderless 0 No title bar and no border. Only applies in windowed mode.

They are accepted as 0/1 or as on/off.

Windowed mode is an addition: the original 0.97k only runs fullscreen and looks for a 16-bit color video mode that no longer exists on Windows 10/11, so the mode switch fails silently and the window ends up borderless in a corner.

Diagnostics

The client writes bin/Client/debug.log on every start. The first useful line is the derived encryption key:

MuEmu: InitKeys CustomerName='MuLinux' Serial='TbYehR2hFUPBKgZj' -> EncDecKey1=0xC2 EncDecKey2=0x01
server.cfg: ClientVersion='09711'

If the client hangs while connecting, that line is the first thing to look at: compare the CustomerName against your server’s.

Linux: not yet

The client does not build on Linux for now, and that is what is coming next.

The port is written against the original Windows binary: it assumes 32-bit pointers, uses the Win32 API for the window and input, and OpenGL through wgl. Taking it to Linux is a project stage of its own — platform abstraction and a CMake build — that starts after the 1:1 reconstruction is closed.

In the meantime the client runs on Windows against a Linux server without any problem: the server has been Linux-native from the start and they talk over the network.

The repository

The code lives at EmanuelCatania/Mu-97k-Client-Source.

It is active development: the 1:1 reconstruction against the original binary is not closed yet, and progress is merged through pull requests. The repository README documents the status per subsystem, how to build it and the known pitfalls of the port.