Known Issues
Detailed technical issue list maintained in TODO.md.
Items are organized by subsystem. This page documents issues and investigation tasks;
see Roadmap for prioritized next steps.
Build and Dependencies
Build verification
- Clean checkout build needs verification after:
git submodule update --init --recursive cmake -S . -B build -DSPEEDY_BLUPI_BACKEND=FREEDIRECT cmake --build build -j - Confirm default Linux build does not require system-installed SDL packages (
FREE_USE_SYSTEM_SDLdefaultsOFF) - Verify
FREE_USE_SYSTEM_SDL=ONoverride still works - Confirm
free-apiandfree-directlink SDL asPRIVATE - Confirm no game source file directly includes SDL headers
- Scan:
grep -R "#include <SDL" -n src include
CMake cleanup
-
Change
target_include_directoriesforSPEEDY_BLUPI_WINDOWSfromPUBLICtoPRIVATE(executables don't need public include dirs) - Verify whether
/permissive-MSVC flag is appropriate for decompiled C++ -
Keep compiler option changes separate from gameplay/decompilation fixes;
non-MSVC flags (
-fpermissive -fms-extensions -w -Wno-narrowing) are intentional suppressors for decompiled code -
cmake/ThirdPartySDL.cmakefunction name must stayconfigure_vendored_sdl()— do not reintroduce old names
DirectDraw Initialization
CPixmap::Create()is called twice during startup without releasing previous DirectDraw objectsbTrueColorBack/bTrueColorDecorparameters are inconsistent between declaration, definition, and call sitesCacheAll()contains decompilation artifacts:delete this+ member access, suspiciousLOWORD/HIWORDusage, nonsensical rectangle initialization
Double CPixmap::Create() call
Startup currently calls CPixmap::Create() twice: once directly in
DoInit() and then again inside CacheAll(TRUE, ...).
Real DirectDraw 3 may reject the second call with:
DDERR_PRIMARYSURFACEALREADYEXISTS,
DDERR_EXCLUSIVEMODEALREADYSET, or
DDERR_INVALIDPARAMS.
Free Direct currently tolerates this.
- Confirm whether
CPixmap::Create()is really called twice - Add logging at entry/exit of
CPixmap::Create() - Log whether
m_lpDD,m_lpDDSPrimaryalready exist before the second call - Decide: either
DoInit()orCacheAll()should own DirectDraw initialization, not both - If recreation is needed, add a proper cleanup path before re-initialization
Parameter swap: bTrueColorBack / bTrueColorDecor
The CPixmap::Create() declaration in pixmap.hpp and
the definition in pixmap.cpp have the bTrueColor and
bTrueColorDecor parameters in opposite positions, so the wrong value
is used for each:
// Declaration (pixmap.hpp)
BOOL Create(HWND hwnd, POINT dim, BOOL bFullScreen, int mouseType,
BOOL bTrueColor, BOOL bTrueColorDecor);
// Definition (pixmap.cpp) — names are swapped!
BOOL CPixmap::Create(HWND hwnd, POINT dim, BOOL bFullScreen, int mouseType,
BOOL bTrueColorDecor, BOOL bTrueColor)
- Audit all call sites and the intended meaning of each parameter
- Compare with Planet Blupi source for reference
- Do not change behavior until logging proves current behavior is wrong
- Test configurations where background and decor truecolor settings differ
Dangerous delete this in CacheAll(FALSE)
CPixmap::CacheAll(FALSE) contains a delete this followed
immediately by reads of m_hWnd, m_bFullScreen, etc.
This is undefined behavior — reading object members after destroying the object.
- Investigate whether this code path is actually executed at runtime
- Treat as likely decompilation artifact or incorrectly reconstructed logic
- If object recreation is required, save needed values before destruction
- Never access object members after
delete this
Suspicious rectangle initialization in CacheAll(TRUE)
Decompiled code contains a nonsensical rectangle setup, likely a Ghidra artifact:
// Likely wrong — decompiled artifact
char image[12];
*(char*)image = (LXIMAGE) << 64; // nonsensical shift
rect.left = LOWORD(image); // LOWORD on a local array?
rect.right = HIWORD(image);
// Likely intended
SetRect(&rect, 0, 0, LXIMAGE, LYIMAGE);
- Investigate in Ghidra and compare with Planet Blupi source
- Replace only after confirming the intended behavior
Gameplay
- Many movement and physics behaviors in
decblupi.cpp(4,395 lines) need verification against the original game - Network synchronization in
decnet.cppis incomplete - Level editor in
decdesign.cpphas known missing features - Save/load in
decio.cppmay have version compatibility gaps ifDescSavelayout has changed
Audio
With #define _BASS FALSE, the active implementation is the
DirectSound / MCI path. The setup uses preprocessor conditions:
- Verify
_BASS=FALSEis intentional and README audio notes are current - Do not mix audio backend cleanup with DirectDraw fullscreen investigation
- Consider a future CMake option:
FREE_EGGBERT_AUDIO_BACKEND=DSOUND|BASS|STUB
Network
CNetwork::CreateProvider(0) is called at startup but likely fails
silently because m_providers.nb starts at 0 (no provider enumeration
has been called yet). The return value is ignored, so the game continues in
singleplayer mode.
Additionally, CNetwork::Receive() reads into a local buffer but
does not copy the data into the caller's destination buffer before returning
TRUE — this appears to be a reconstruction bug.
- Treat networking / DirectPlay as incomplete
- Audit
CNetwork::EnumProviders(),CreateProvider(), andReceive() - Consider stubbing network cleanly for singleplayer builds
DirectX SDK / dxsdk3 Submodule
dxsdk3is still listed in.gitmoduleseven though the build is focused onFREEDIRECT- Decide whether
dxsdk3is needed for reference, legacy builds, or real DirectX 3 comparison builds - If only historical, document that clearly
Message Loop and Web Support
The native desktop build uses a classic Win32 blocking message loop with a multimedia timer. Emscripten does not work well with this; the web version needs a Free API / launcher-level main-loop adapter.
- Keep the native Win32-style loop intact for desktop builds
- For web builds, design an adapter at the Free API or launcher level
- Do not hack
src/blupi.cppto satisfy Emscripten - Keep web work separate from DirectDraw fullscreen debugging
Recommended Debugging Priority
- Add detailed logging around DirectDraw initialization in
CPixmap::Create() - Verify whether
CPixmap::Create()is really called twice - Capture the exact
HRESULTfrom the secondDirectDrawCreate,SetCooperativeLevel,SetDisplayMode, andCreateSurfacecalls - Decide ownership of
CPixmap::Create()— eitherDoInit()orCacheAll(), not both - Clarify the
bTrueColorBack/bTrueColorDecorparameter order - Keep unrelated systems separate during investigation
- Only after the fullscreen path is understood, continue with web/Android portability