Status: baseline packaged and validated (2026-10-30). A reproducible Wine prefix — VC6 SP5 + Processor Pack + the DirectX 9.0 SDK Update (Summer 2003), with the Wine-gap workarounds baked in — now exists as
toolchain_vc6_prefix.7zand builds the CVS-era trees through thewinecl6-*wrapper scripts. The Beta 2 reversal work runs on this same baseline with per-project externals overlaid. Companion pages: VS2008 under Wine for the conventions this mirrors, and Windows Compatibility Targets for the runtime-side matrix (which OS each era's binaries run on — this page covers the compiler-side ceilings instead).
The original NeL / Ryzom / Snowballs codebase — preserved at github.com/ryzom/nel_cvs — was built with Visual C++ 6.0 (cl 12.00), with Format-6.00 .dsp/.dsw project files (55 projects: nel, nelns, snowballs2, tools). Building that tree with its original compiler under Wine gives the authentic 2000s-era x87 reference, the same role the VS2008/Wine environment plays for the Max-2010-era pipeline.
Survey of the final CVS state (2026-08-06):
nel/include/nel/misc/types_nl.h hard-requires STLport (#error unless __SGI_STL_PORT — any STLport 4.x defines it). VC6's native STL is not an option by the project's own gate.opengl32.lib, odbc32.lib, ...). No freetype in 3d.dsp at this tree state..mak files — building the .dsp projects needs either MSDEV.EXE /MAKE (the VC6 command-line build driver) or an external build harness.Service pack: SP5, not SP6. An earlier revision of this page assumed SP6 (mislabeling cl 12.00.8804, which is SP5). The shipped package is VC6 SP5 + Processor Pack: cl.exe 12.00.8804, C1.DLL 12.00.8867, C1XX.DLL 12.00.8964, and the backend c2.dll 12.00.9044 from the Processor Pack — which installs on SP5 only, never on SP6. This is not just preference: objects compiled by this tree carry @comp.id 12.00.9044, matching the Rich header of the original Ryzom Beta 2 artifacts. A pure-SP5-no-PP variant (RTM c2 12.00.8168) is kept alongside for A/B work.
Package layout (single archive, ~235 MiB, built the same way as the VS2008 toolchain_v90_prefix.7z):
| Path | What | From |
|---|---|---|
drive_c/Program Files/Microsoft Visual Studio |
VC6 SP5+PP (VC98, Common, incl. MSPDB60.DLL in Common/MSDev98/Bin) |
working WinXP install, zipped |
drive_c/DX90SDK |
DirectX 9.0 SDK Update (Summer 2003), trimmed to Include/Lib — ships un-pathed; stage via NL_VC6_DX (below) |
SDK archive |
drive_c/…/VC98/Bin/CL.EXE, LINK.EXE |
injector wrappers, see below | source included |
wine-vc6/winecl6-{env,cc,lib,link,rc} |
build wrapper scripts | source included |
wine-vc6/src/{zmhook.c,cl_wrap.c} |
source of all custom executables | — |
README.md |
full documentation of the above, including a rebuild-from-archives recipe | — |
The prefix is win32 (WINEARCH=win32 at creation). No extern folder structuring is imposed — the Nevrax-convention C:\NEVRAX\EXTERN\* layout (a DX8-named shim over DX90SDK, per-library trees) is a per-project overlay, not baseline; where extern packages live is the consumer project's choice.
Deliberately excluded from the baseline: Platform SDKs (the Feb 2001 and Feb 2003 PSDKs are available separately for experiments — see the trap below for why they must stay off the include path), the 3ds Max SDK, STLport (per-project: era NeL stages its own), and the link-identity probe hooks used during the Ryzom Beta 2 work.
Externals are per-project, not in the baseline: STLport 4.x headers + VC6-built iostreams library (era-authentic 4.5.3 — upstream sourceforge tarball, md5 cd4dd34b623a8704fbc800de79705171, header-identical to the Nevrax-era wpkg package; must be first on INCLUDE — the NL_VC6_STLPORT env var stages it, /dev/null disables), FreeType 2.1.x, libxml2 2.4.x/2.6.x, libjpeg 6b, zlib, GLEXT, EAX 2.x — all built with this same VC6 where needed. The DX row in the dependency survey below stands: at the final CVS tree state the core needs no DX SDK; the Ryzom-era client is where the Summer 2003 SDK enters (see the reversal's pinned setup).
winecl6-env assembles the environment (INCLUDE/LIB/WINEPATH) and every winecl6-* script sources it, then runs the tool through Wine with Unix→Windows path translation (translate_args — same shape as the VS2008 layer, including the glued-/FI case; additionally drops /showIncludes, which cl 12.00 predates). Env knobs: NL_VC6_PREFIX (prefix location), NL_VC6_STLPORT (STLport staging; /dev/null for STLport-free builds such as modern ryzomcore), NL_VC6_DX (DX SDK staging: any Windows path to an SDK root with INCLUDE/LIB, e.g. 'C:\DX90SDK'; unset, the Nevrax C:\NEVRAX\EXTERN\DX8 location is used if it exists — reversal overlay convention —, otherwise no DX at all), WINEDEBUG (default -all).
Default include order in the pristine baseline is VC98 only. Fully staged (era NeL): STLport → DX → VC98 (+MFC/ATL). windows.h resolves to VC98 (the DX SDK has none); the only header collision is VC98 windows.h → winnt.h → DX basetsd.h, which is inert on _MSC_VER 1200 (_W64 is empty, INT_PTR stays 32-bit). LIB: DX libs first, then VC98, then STLport.
Never put a Platform SDK on this path for VC6. PSDK 2003
winbase.hInterlocked*overloads are C2733 on cl 12.00, and a later PSDK in front of VC98 also breaks VC6 C++ via the newerwinnt.h(__w64). The PSDK include order is a VS2008-era concern; for VC6 it is simply wrong.
Validation battery (banner, x87 float bit-exactness — 1.0f/3.0f → 3eaaaaab under /O2 —, C++ /GX /MD smoke, STLport smoke, RC smoke) passes 8/8 on the packaged baseline; a PCH TU and a large client TU compile byte-identical (all content sections; only COFF TimeDateStamp / PDB NB10 build-time fields differ, as they must).
The VS2008 page's trap list mostly does not apply (VC6 has no manifests, no mt.exe, no SxS — plain MSVCRT.DLL, Wine's builtin serves; /Zi works: MSPDB60 is an in-process DLL, there is no mspdbsrv.exe server process until VC7). What bites on VC6 is the compiler's own memory appetite:
C1060 (compiler out of heap space) at stock /Zm800 /YX. /Zm scales the compiler's factoring heap; /Zm800 makes CL.EXE request two anonymous VirtualAlloc(NULL, 400 MB) blocks. Wine's 32-bit preloader parks builtins near 0x7a000000, the first heap lands just below, and the second fails. Two simpler fixes were tried and rejected: WINEPRELOADRESERVE alone (the reserve is not consulted by VirtualAlloc(NULL) — it goes through map_free_area, so reserving just makes C1060 hit earlier), and LARGEADDRESSAWARE on cl/c1xx/c2 (both heaps then fit in 4 GB, but /YX dies with C2437, allocator<char> already initialized).VirtualAlloc hook injected into the real compiler. Wine stubs LoadAppInitDlls, so the AppInit_DLLs registry route is unavailable; instead VC98/Bin/CL.EXE and LINK.EXE are a ~16 KB injector (cl_wrap.c) that launches the real cl_orig.exe/link_orig.exe suspended, injects zmhook.dll via a remote-thread LoadLibraryA, and resumes it. The hook matches Wine's kernel32!VirtualAlloc thunk prologue (8B FF 55 8B EC 5D FF 25 <IAT>), swaps the IAT slot, and pins VirtualAlloc(NULL, ≥128 MB) at 0x20000000, stepping 32 MB — combined with WINEPRELOADRESERVE=0x20000000-0x78000000 this reserves a corridor where the two /Zm800 heaps always land. Every pin is logged to C:\nevrax\extern\zmhook.log.VirtualAlloc thunk prologue ever changes, the hook logs unexpected VirtualAlloc prologue and no-ops (C1060 returns). This is the one Wine-coupling to re-verify on toolchain updates./Fe:name.exe colon form — same as the VS2008 page: use the no-colon /Fename.exe form.RC.EXE lives in Common/MSDev98/Bin in VC6 (not VC98/Bin) — the wrapper points there; /nologo is accepted at this vintage.WINEARCH=win32 at prefix creation. wineboot -i on a 64-bit host without it gives a win64 prefix (Program Files (x86), syswow64). The 32-bit VC6 tools still run under WOW64 there — verified: a win64 prefix produced byte-identical object content against the win32 one — but the win32 convention is smaller, skips the WOW64 layer, and matches the VS2008 flow; verify #arch=win32 in system.reg after init.The wrapper scripts compile/link/lib/rc directly — see the package README.md for the rebuild-from-archives recipe and full usage. Ninja/CMake-driven builds work the same way as the VS2008 flow (command-line only; MSDEV.EXE /MAKE for the .dsp projects remains untried under Wine — the fallback of a small .dsp parser emitting ninja still stands if the IDE route is ever needed).
validate_vc6.sh green/ORDER + first-object IAT ordering; see the reversal notes for the linker-layout methodology).nel/src/misc.dsp → nlmisc.lib (smallest real target, exercises STLport + the header set), then snowballs2.