Reverse Engineering Notes
Free Eggbert is based on decompiled and reverse-engineered binary code. This page documents the methodology, sources, and known artifacts of the decompilation process.
Methodology
Three tools were used to reconstruct the source code:
Ghidra
Ghidra (NSA open-source reverse engineering suite) was used for binary analysis, decompilation, and control-flow reconstruction of the Windows executable. Ghidra produces C-like pseudocode from assembly which can be translated back to C++.
IDA
IDA (Interactive Disassembler) was used for additional binary disassembly and analysis, complementing the Ghidra output.
ILSpy and the Windows Phone 2013 Port
The most valuable source of symbol names came from inspecting the 2013 Windows Phone version of Speedy Blupi using ILSpy. This port was compiled in a way that preserved demangled C++ symbol names, providing function names, class names, and member variable names that are not available in the original Windows binary.
Special thanks to Ч.У.Ш from the 4PDA forum for archiving this obscure port.
Planet Blupi Reference
Planet Blupi — the official open-source release of the shared ancestor engine — is used as a behavioral reference. Where the decompiled output is ambiguous, the Planet Blupi implementation often reveals the intended algorithm, since the two codebases share common ancestry and many functions are nearly identical.
Known Decompilation Artifacts
Several areas of the codebase are known to contain decompilation artifacts — code that compiles but does not represent the original accurately.
Double CPixmap::Create() Call
CPixmap::Create() is called twice during startup — once directly
from DoInit(), and again inside CPixmap::CacheAll(TRUE, …).
This likely did not happen in the original code. Real DirectDraw may reject the
second initialization with errors like DDERR_EXCLUSIVEMODEALREADYSET.
bTrueColorBack / bTrueColorDecor Parameter Swap
In include/pixmap.hpp, CPixmap::Create() is declared with
parameters in the order (bTrueColor, bTrueColorDecor). However, in
src/pixmap.cpp, the definition uses the names swapped:
(bTrueColorDecor, bTrueColor). This causes the assignments to be reversed:
m_bTrueColorDecor = bTrueColorDecor; // but receives the "back" value
m_bTrueColorBack = bTrueColor; // but receives the "decor" value
The mismatch may work accidentally when both values are the same (16-bit mode), but can produce wrong behavior if background and decor use different color depths.
Unsafe delete this in CacheAll(FALSE)
The decompiled CPixmap::CacheAll(FALSE) path contains code that
calls delete this and then immediately reads member variables
(m_hWnd, m_bFullScreen, etc.). This is
undefined behavior in C++. It is likely a decompilation
artifact or an incorrectly reconstructed pattern from the original.
Suspicious Rectangle Initialization
In CacheAll(TRUE), there is decompiled code that initializes a
rectangle using nonsensical operations:
char image[12];
*(char*)image = (LXIMAGE) << 64; // nonsensical: left-shift by 64
rect.bottom = LYIMAGE;
rect.left = LOWORD(image); // LOWORD on a local array pointer
rect.top = HIWORD(image);
rect.right = HIWORD(image);
DrawImage(0, 0, rect, 1);
The original code was likely a simple SetRect(&rect, 0, 0, LXIMAGE, LYIMAGE)
that the decompiler failed to reconstruct correctly.
Widespread Uninitialized Variables
The original binary was compiled with optimizations that reused stack space
aggressively. Decompiled code has many variables that appear uninitialized but
were actually initialized by the original compiler's register allocation.
The MSVC flags /wd4700 /wd4703 suppress these warnings.
The _LEGACY Flag
The _LEGACY compile flag controls whether known bugs and quirks
from the original binary are preserved:
_LEGACY=FALSE(default) — enables fixes for confirmed bugs_LEGACY=TRUE— restores intentionally broken behaviors for accuracy
Comparison with Planet Blupi
When behavior in the decompiled output is ambiguous, Planet Blupi is used as a reference. The two codebases share common heritage in:
- Class and function naming conventions
- Data structures (similar grid layout, MoveObject, etc.)
- Many core algorithms (rendering, physics, object movement)
However, Free Eggbert diverges significantly in the player model (single player vs. 100 units), world dimensions (100×100 vs. 200×200 isometric), and many gameplay mechanics. See Free Eggbert vs. Speedy Blupi.