Platform Support
Free Eggbert supports multiple platforms through the FreeDirect/SDL3 abstraction layer.
Summary
| Platform | Backend | Status | Build Method |
|---|---|---|---|
| Windows (native DirectX) | DirectDraw / DirectSound | Partial | Visual Studio 2022 |
| Windows (FreeDirect) | SDL3 | Partial | CMake |
| Linux | SDL3 (FreeDirect) | Partial | CMake |
| macOS | SDL3 (FreeDirect) | Needs Verification | CMake |
| WebAssembly | Emscripten + SDL3 | Partial | emcmake |
| Android | SDL3 (NDK) | Partial | Gradle + CMake |
Windows
Native DirectX (Visual Studio)
The original build target uses the real DirectX 3 SDK (dxsdk3 submodule)
with Visual Studio 2022. This path uses DirectDraw and DirectSound directly.
CPixmap::Create() call and fullscreen initialization problems.
CMake + FreeDirect
Building with CMake on Windows uses the FreeDirect backend instead of real DirectX.
This requires the third_party/ SDL submodules.
git submodule update --init --recursive
cmake -S . -B build -G "Visual Studio 17 2022" -DSPEEDY_BLUPI_BACKEND=FREEDIRECT
cmake --build build --config Debug
Linux / macOS
Build using CMake with the FreeDirect backend. No system SDL packages required by default.
git submodule update --init --recursive
cmake -S . -B build -DSPEEDY_BLUPI_BACKEND=FREEDIRECT
cmake --build build -j
On Linux the default compiler is GCC or Clang. The permissive compiler flags
(-fpermissive, -fms-extensions, etc.) handle
decompiled code constructs that strict C++ would reject.
WebAssembly (Emscripten)
Build
source /path/to/emsdk/emsdk_env.sh
emcmake cmake -S . -B cmake-build-web -DCMAKE_BUILD_TYPE=Debug
cmake --build cmake-build-web -j
emrun cmake-build-web/bin/SPEEDY_BLUPI_WINDOWS.html
Assets
Game assets are preloaded into the Emscripten virtual filesystem at build time
from gamefiles/DATA, gamefiles/IMAGE08,
gamefiles/IMAGE16, and gamefiles/SOUND.
Persistent Saves
Save data is stored in the browser's IndexedDB via Emscripten IDBFS,
mounted at /save. This persists across page reloads.
Clearing browser site data resets the saves.
// Export save data
Module.ccall('FreeEggbert_ExportPersistentData', null, [], []);
// Import save data
Module.ccall('FreeEggbert_ImportPersistentData', null, [], []);
Web Rendering
On widescreen displays, the game image is automatically letterboxed using SDL3's logical presentation mode. Touch and mouse coordinates are mapped from physical screen coordinates into game logical coordinates — touches on black bars do not register as in-game clicks.
Message Loop Consideration
The native build uses a classic Win32 message loop with a multimedia timer. Emscripten does not work well with a blocking infinite loop, so the web version needs a Free API / launcher-level main-loop adapter. This is an active area of work and is handled at the FreeDirect layer, not in game code.
Android
Prerequisites
| Tool | Recommended Version |
|---|---|
| Android Studio | Ladybug (2024.2) or newer |
| Android SDK | API level 35 |
| Android NDK | 30.0.14904198 |
| CMake (NDK bundle) | 3.21+ via SDK Manager |
| Java (JDK) | 17 (bundled with Android Studio) |
Setup
- Open Android Studio → Settings → SDK Manager → SDK Tools
- Check NDK (Side by side) version 30.0.14904198
- Check CMake version 3.21+
- Click Apply and let Android Studio download and install
- Create
android/local.properties:cp android/local.properties.template android/local.properties # Edit and set sdk.dir to your Android SDK path
Game Assets on Android
Game assets are linked via symbolic links in android/app/src/main/assets/:
If symbolic links don't work, copy the directories instead:
cd android/app/src/main/assets
cp -r ../../../../../gamefiles/DATA data
cp -r ../../../../../gamefiles/IMAGE08 image08
cp -r ../../../../../gamefiles/IMAGE16 image16
cp -r ../../../../../gamefiles/SOUND sound
Build
cd android
./gradlew assembleDebug
Output: android/app/build/outputs/apk/debug/app-debug.apk
Install and Run
# Clear previous install (resets extracted assets and save data)
adb shell pm clear org.openeggbert.freeeggbert
# Install
adb install -r android/app/build/outputs/apk/debug/app-debug.apk
# Launch
adb shell am start -n org.openeggbert.freeeggbert/.FreeEggbertActivity
Logcat Diagnostics
adb logcat | grep -E "SDL|FREEAPI|FREE_DIRECT|Eggbert|free-eggbert"
| Log Tag / Message | Meaning |
|---|---|
free-api: SDL_main starting | SDL_main entry point reached |
free-api: FreeApiAndroidSetup begin | Android asset setup started |
FREEAPI_ANDROID: smoke-test data/config.def EXISTS | Required config file found |
free-api: asset extraction complete | All assets extracted successfully |
FREE_DIRECT_PRESENT: source=… | Render loop is running |
FREE_DIRECT_INPUT: raw=… | Input events being processed |
Release APK
# Create a keystore
keytool -genkey -v -keystore android/free-eggbert-release.keystore \
-alias free-eggbert -keyalg RSA -keysize 2048 -validity 10000
# Create android/key.properties with keystore credentials
# Build the signed release APK
cd android
./gradlew assembleRelease
Android Troubleshooting
| Problem | Solution |
|---|---|
INSTALL_FAILED_UPDATE_INCOMPATIBLE |
Uninstall first: adb uninstall org.openeggbert.freeeggbert |
| App exits immediately | Asset extraction failed. Check logcat for free-api: entries. Verify symlinks in android/app/src/main/assets/ |
| No audio | Verify sound files are present in the APK. Check SDL_mixer WAV support. |
| Crash on launch | Check logcat for native crash. Common: missing libmain.so or incomplete git submodule update |
Rendering Across Platforms
Free Eggbert uses a fixed 640×480 logical resolution. On all platforms via FreeDirect, the game renders to this size and SDL3 handles scaling to the actual display:
- Desktop: Windowed at 640×480, resizable with letterboxing
- Web: Letterboxed to fit the browser window
- Android: Letterboxed to the device screen, black bars on sides or top/bottom