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.

ℹ️
Note on Accuracy
Decompiled code is an approximation of the original. Some behaviors, variable names, and structures are inferred, not proven. Items marked Needs Verification should be verified against the original game behavior before being relied upon.

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

Suspected Artifact
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.