https://gitlab.synchro.net/main/sbbs/-/commit/ddd71e8e444a1e1f4a5f1d45
Modified Files:
src/doors/syncconquer/PROVENANCE.md src/doors/syncconquer/vanilla/tiberiandawn/startup.cpp
Log Message:
syncconquer: syncdawn -- no stray Win32 window, no hang on exit (Windows)
Patch #11 fixed two things for Red Alert on the strength of one observation: the headless door has no Win32 window and no message pump. Neither premise was ever carried over to Tiberian Dawn, and on Windows both bit.
The stray window. TD's main() called Create_Main_Window() under a bare
#if defined(_WIN32) && !defined(SDL_BUILD). RA calls it too, but hands it command_show = 0 -- SW_HIDE -- so RA's window is created and never seen. TD instead derives command_show from GetStartupInfo() (SW_SHOWDEFAULT when the parent set no STARTF_USESHOWWINDOW) and follows it with ShowWindow() + UpdateWindow() + SetFocus() on a WS_EX_TOPMOST | WS_POPUP | WS_MAXIMIZE
window. A door whose video goes to the CALLER's terminal was thus popping a fullscreen, always-on-top "Command & Conquer" window onto the BBS machine's
own desktop and taking focus there. Gate the call on !NEW_VIDEO_BUILD: MainWindow stays NULL, which is what the rest of the door already assumes.
That window's title rendered as CJK glyphs, and the cause is worth recording because it is upstream's, not ours: both winstubs register the class with RegisterClassA and pass an ANSI title to CreateWindowExA, then fall through to the DefWindowProc *macro* -- DefWindowProcW under this UNICODE build. The default WM_NCCREATE handler duly reads "Command & Conquer" as UTF-16. Upstream never sees it: its Windows build defines SDL_BUILD and compiles none of this.
The exit hang. main()'s ReadyToQuit spin-wait -- PostMessage(WM_DESTROY), then do { Keyboard->Check(); } while (ReadyToQuit == 1) -- was likewise ungated. With no pump nothing can run Windows_Procedure()'s WM_DESTROY case to advance ReadyToQuit 1 -> 2, so "Exit Game" spun forever burning CPU: precisely the
hang patch #11 cured for RA. Same guard. Corroborated by the door's own node log -- a Windows syncdawn session ends without the stats[exit] line that every syncalert session prints.
A NULL MainWindow is safe here: what remains are MessageBoxA(NULL, ...) on fatal paths, the harmless PostMessage() above, multiplayer-only netdlg.cpp
(the door is single-player), and common/vqaloader.cpp's VQA_OpenAudio(handle, MainWindow), whose hwnd door/vqaaudio_termgfx.cpp ignores. TD's GameInFocus is already unconditionally true -- RA needed patching to force it, TD does not -- so losing the window's WM_ACTIVATEAPP does not silence TD's audio.
Vendored patch, recorded as PROVENANCE #33. Both binaries still link clean at Win32/Release.
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net