Project Overview
What free-direct is, why it exists, and how it fits into the open-source preservation of legacy 2D games.
What is free-direct?
free-direct is a C++20 static library that reimplements a focused, game-driven subset of the Microsoft DirectX 3 API — specifically the 2D portions needed to run Speedy Blupi / Speedy Eggbert and Planet Blupi on modern, non-Windows platforms.
It provides the same header-level API shapes as the original DirectDraw, DirectSound, and DirectPlay
interfaces so that legacy C++ game code can include <ddraw.h>,
<dsound.h>, and <dplay.h> and compile without any change.
Internally, the library delegates all rendering to SDL 3, all audio to
SDL3 audio streams, and provides dummy stubs for network calls.
Why does it exist?
The original games were Windows-only and depend on the DirectX 3 runtime, which is a proprietary Microsoft technology. Making them run on Linux, macOS, Android, or the Web requires either:
- Running the Windows binary through a compatibility layer (Wine, etc.), or
- Recompiling the game source against a portable reimplementation of the DirectX APIs.
free-direct takes the second approach. It lets the game source compile as portable C++20 and link against SDL 3 for the actual platform-specific work. The original game logic is untouched.
Relationship to Speedy Blupi / Speedy Eggbert and Planet Blupi
Speedy Blupi (also known as Speedy Eggbert) and Planet Blupi are classic 2D games that use a fixed, well-known subset of DirectDraw for 2D blitting, palette management, and surface operations. They use DirectSound for PCM sound effects, and they reference DirectPlay for (optional) multiplayer networking.
free-direct is explicitly scoped to the call sites present in those games. Methods and flags that the games never invoke are either stubbed or left unimplemented — the goal is a correct, minimal, and maintainable subset rather than a complete DirectX clone.
Compatibility behavior is driven by real call sites in the target game code, not by the DirectX 3 specification. If a feature is not exercised by those games, it is likely missing.
Difference from the original Microsoft DirectX runtime
| Aspect | Original DirectX 3 | free-direct |
|---|---|---|
| Platform | Windows only | Linux, macOS, Windows, Android (partial), Web (planned) |
| Rendering | Hardware-accelerated (HAL / HEL) | SDL3 renderer + CPU pixel buffers (software path) |
| Pixel format | Matches physical device | Fixed internally to 8-bit paletted or 32-bit RGBA |
| Flip chain | Real page-flip with back buffers | Simplified: CPU buffer upload + SDL_RenderPresent |
| COM | Full IUnknown / QueryInterface support | Minimal: AddRef/Release work; QueryInterface returns DDERR_UNSUPPORTED |
| DirectPlay | Real UDP/IPX/modem networking | All stubs; returns success but performs no I/O |
| DirectInput | Keyboard, mouse, joystick | Not implemented; input goes through the free-api WinAPI layer |
| Direct3D | Full 3D pipeline (D3D 5-era) | Not implemented; out of scope |
| License | Proprietary | MIT |
Difference from free-api
The project depends on a companion library called free-api, which is a separate repository. The two libraries have complementary roles:
| Library | What it reimplements | Typical headers |
|---|---|---|
| free-api | WinAPI subset: window creation, message loop, GDI basics, WinMM timers, wide/ANSI string helpers, registry stubs | windows.h, mmsystem.h, winuser.h |
| free-direct | DirectX 3 2D subset: DirectDraw, DirectSound, DirectPlay | ddraw.h, dsound.h, dplay.h |
free-direct is built on top of free-api: its public headers include
<windows.h> from free-api (for HWND, HRESULT,
DWORD, etc.) and link against free-api::free-api. Game code that
uses both DirectX and WinAPI includes both sets of headers.
Design principles
- Minimal by design — only implement what the target games actually call.
- SDL3 as the only backend — SDL 3 is used internally and never exposed in public headers.
- CPU pixel buffers everywhere — all surfaces are backed by
std::vector<uint8_t>for simplicity and portability. - No COM correctness —
QueryInterfaceis stubbed; reference counting works for memory management, not for COM aggregation. - Honest limitations — partial or stub behavior is documented and flagged in code rather than silently misbehaving.
Non-goals
- Full DirectX 3 API coverage.
- Hardware-accurate frame timing or color depth emulation.
- Direct3D (3D pipeline) support.
- DirectInput support (handled by free-api instead).
- Real DirectPlay networking.
- Expanding the implementation beyond what the target games require.