Run original Windows CE ARM applications on modern desktop Windows.
CERF emulates an ARM CPU and thunks WinCE COREDLL calls to native Win32 APIs, allowing unmodified ARM binaries to run on x64 Windows. The full WinCE boot sequence is emulated — device drivers, registry, shell, and explorer — giving each app a complete OS environment.
Successor to wcecl.
cerf.exe # Boot WinCE desktop
cerf.exe --device=wince6 # Boot with WinCE 6.0 profile
cerf.exe --no-init solitare.exe # Launch app directly, skip boot
cerf.exe --gdb-port=1234 # Boot with GDB remote debugging
- ARMv5TE emulation — ARM + Thumb modes, real OS threads per ARM thread
- Full boot sequence — boot screen, device.exe drivers, HKLM\init with dependency ordering
- Multi-process — per-process virtual address space with copy-on-write DLL data isolation
- Win32 API thunking — GDI, windowing, dialogs, registry, filesystem, COM/OLE, sockets
- WinCE theming — system colors, UxTheme stripping, WinCE-style caption bars
- Device profiles — bundled configurations for WinCE 5.0, 6.0, and 7.0
- GDB debugging — remote stub for ARM code debugging
- Only coredll is thunked — all other WinCE DLLs (commctrl, ole32, aygshell, etc.) run as real ARM code
Requires Visual Studio 2022 with C++ desktop development workload.
msbuild cerf.sln /p:Configuration=Release /p:Platform=x64
python e2e_tests/run_all.py
Log-driven tests verify boot + app lifecycle across all device profiles.
See docs/ for architecture, boot sequence, process isolation, SEH, windowing, and thunking details.
CERF does not mock user-mode WinCE libraries — DLLs like commctrl.dll, ole32.dll, aygshell.dll, and ddraw.dll run as real ARM code. The only thunked layer is coredll.dll (the WinCE equivalent of kernel32 + user32 + gdi32), which translates ARM syscall-level APIs to native Win32.
There is no GWES (the WinCE graphics/windowing/event subsystem) and no display driver model. Instead, windowing is built entirely on top of desktop Windows — ARM calls to CreateWindowExW, SetWindowPos, message dispatching, etc. are translated directly to native Win32 window operations. WinCE windows are real desktop windows with layout translation to account for the differences in frame metrics.
Device drivers boot and run as ARM code too. We could mock the internal API sets that drivers register (e.g. the AFD API sets used by ws2.dll), but these are heavily coupled to each driver's internals and likely differ between devices — mocking them would mean maintaining a special implementation per device. Instead, we run the real drivers as ARM code all the way down and only mock at the hardware access boundary. For networking, that means afd.dll runs unmodified and we mock the TCP/IP stack (tcpstk.dll) at the TDI layer, which has a stable API preserved across all WinCE devices. This pattern applies generally: let the full driver stack run and only intercept where it would touch hardware.
The entire codebase was generated by Claude via Claude Code with no human-written code. It's not production-grade — there are likely bugs, shortcuts, and possibly fundamental issues in the emulation layers — but we are trying to take it as seriously as possible, because it is an emulator in the end. This started as a fun project to push what Claude can do and to finally make the old wcecl concept actually work. And it does seem to work.
