A Windows executable emulator for running classic Windows games and applications on modern systems. Supports both 32-bit PE (Win32) and 16-bit NE (Win16) executables.
- Cross-Platform: Runs on Windows, Linux, and macOS (both x86 and ARM)
- Win32 & Win16 Support: Runs both 32-bit PE and 16-bit NE executables (Win16 support is experimental)
- Hardware-Accelerated: Uses .NET intrinsics for CPU instruction acceleration
- Modern CPU Support: Automatically detects and uses SSE, AVX, and NEON instructions
- Accurate Emulation: Full x86 CPU and Windows API emulation
- JIT Caching: Persistent JIT cache to disk for faster subsequent executions with precompilation support
- Disc Image Support: CHD (Compressed Hunks of Data) detection and validation for CD-ROM games
Cross-platform desktop GUI for managing your game library and emulator settings. Built with Avalonia UI.
Note: This is now the primary executable for Win32Emu. The standalone CLI has been integrated into this application.
Features:
- Game library with thumbnail views
- File picker for adding games
- Emulator configuration (rendering backend, resolution scaling, memory, Windows version)
- One-click game launching
- CLI mode with
--noguiflag for headless operation
GUI Usage:
# Launch the GUI application
Win32Emu.GuiCLI Usage (with --nogui flag):
# Run in command-line mode without GUI
Win32Emu.Gui --nogui <path-to-pe> [options]CLI Options:
--debug: Enable enhanced debugging mode with automatic error detection--interactive-debug: Enable interactive step-through debugger (GDB-like)--gdb-server [port]: Start GDB server for remote debugging with Ghidra/IDA (default port: 1234)- Supports remote file I/O when VFS is initialized (access game files from debugger)
--backend <SDL|GLFW|Vulkan|Metal|Software>: Select rendering backend (default: SDL)--log-file [path]: Enable logging to file (auto-generates MD5-based filename if path not provided)- Filename format:
<executable>_<md5hash>_<timestamp>.log - Useful for capturing logs when reporting issues
- Filename format:
--telemetry-console: Enable OpenTelemetry with console exporter for logging and metrics--telemetry-otlp [endpoint]: Enable OpenTelemetry with OTLP exporter (default: http://localhost:4317)
Environment Variables:
WIN32EMU_BACKEND: Set rendering backend (SDL, GLFW, Vulkan, Metal, or Software)OTEL_EXPORTER_OTLP_ENDPOINT: OpenTelemetry OTLP endpoint (e.g.,http://localhost:4317)- Automatically enables OpenTelemetry when set
- Useful for IDE integrations like JetBrains Rider
CLI Examples:
# Run normally (uses SDL backend)
Win32Emu.Gui --nogui game.exe
# Run with GLFW backend (alternative if SDL has issues)
Win32Emu.Gui --nogui game.exe --backend GLFW
# Run with Vulkan backend (uses MoltenVK on macOS)
Win32Emu.Gui --nogui game.exe --backend Vulkan
# Run with Metal backend (macOS only, hardware-accelerated)
Win32Emu.Gui --nogui game.exe --backend Metal
# Run with Software backend (CPU-based, no GPU required)
Win32Emu.Gui --nogui game.exe --backend Software
# Run in headless mode (no display, CI/CD environments)
# Use the provided launcher script that sets SDL_VIDEODRIVER=dummy
./run-headless.sh --nogui game.exe --backend Software
# Or set the environment variable manually
SDL_VIDEODRIVER=dummy Win32Emu.Gui --nogui game.exe --backend Software
# Run with enhanced debugging
Win32Emu.Gui --nogui game.exe --debug
# Run with interactive debugger for step-through debugging
Win32Emu.Gui --nogui game.exe --interactive-debug
# Run with GDB server for debugging in Ghidra or IDA
Win32Emu.Gui --nogui game.exe --gdb-server
# Run with GDB server on custom port
Win32Emu.Gui --nogui game.exe --gdb-server 5678
# Enable file logging (auto-generates filename with MD5 hash)
Win32Emu.Gui --nogui game.exe --log-file
# Enable file logging with custom path
Win32Emu.Gui --nogui game.exe --log-file my_debug.log
# Run with OpenTelemetry console exporter for observability
Win32Emu.Gui --nogui game.exe --telemetry-console
# Run with OpenTelemetry OTLP exporter (for Jaeger, Prometheus, etc.)
Win32Emu.Gui --nogui game.exe --telemetry-otlp http://localhost:4317Important Note for macOS Users:
Running with --nogui ensures that rendering backends run on the main thread, which is required for proper operation of Metal, SDL, and other graphics APIs on macOS.
Running in Headless Environments (CI/CD, Docker, SSH): For environments without a display (e.g., GitHub Actions, Docker, SSH sessions), use the Software backend with SDL's dummy video driver:
# Option 1: Use the provided launcher script (recommended)
./run-headless.sh --nogui game.exe --backend Software
# Option 2: Set environment variable manually
SDL_VIDEODRIVER=dummy Win32Emu.Gui --nogui game.exe --backend Software
# Option 3: Export for the entire session
export SDL_VIDEODRIVER=dummy
Win32Emu.Gui --nogui game.exe --backend SoftwareNote: The SDL_VIDEODRIVER environment variable must be set before starting the Win32Emu process. Setting it from within the application is too late because SDL reads it during native library initialization.
See Win32Emu.Gui/README.md for more details about the GUI features.
See Also:
- HEADLESS_MODE.md - Comprehensive guide for running in headless environments
- docs/implementation/SILK_NET_MIGRATION.md - Backend system and configuration
- docs/guides/GHIDRA_DEBUGGING_FAQ.md - Troubleshooting "no debugging symbols" and debugging tips
- docs/guides/DEBUGGING_GUIDE.md - Enhanced debugging mode
- docs/guides/INTERACTIVE_DEBUGGER_GUIDE.md - Interactive debugger
- docs/guides/GDB_SERVER_GUIDE.md - GDB server for Ghidra/IDA integration
- docs/guides/VFS_DOCUMENTATION.md - Virtual File System for game file isolation
- docs/guides/OPENTELEMETRY_USAGE.md - OpenTelemetry for logging, metrics, and profiling
- docs/examples/TELEMETRY_EXAMPLE.md - Practical examples of using OpenTelemetry
- docs/guides/RIDER_OPENTELEMETRY_SETUP.md - JetBrains Rider integration guide
- docs/implementation/JIT_CACHE_IMPLEMENTATION.md - JIT caching to disk for faster emulation
- docs/examples/JIT_CACHE_EXAMPLES.md - JIT cache usage examples and best practices
- docs/features/CHD_DISC_IMAGE_SUPPORT.md - CHD disc image format support
- docs/implementation/NE_LOADER_IMPLEMENTATION.md - Win16 NE format support (experimental)
Interactive web-based frontend for Win32Emu, built with Blazor WebAssembly.
Live Demo: https://archanox.github.io/Win32Emu/emulator/
Features:
- Browser-Based: Run the emulator interface directly in your web browser
- HTML5 Canvas Display: Dedicated canvas area for DirectDraw output rendering
- Dual Output Panels: Separate panels for standard output and debug messages
- Status Monitoring: Real-time display of instructions executed, FPS, and audio status
- File Upload: Upload Windows PE executables directly from your device
- Mobile-Friendly: Test and interact with emulated applications on mobile devices
Current Status: This is a proof-of-concept implementation. The Win32Emu core library currently has native dependencies (SDL3, Silk.NET, UnicornEngine) that don't support WebAssembly. To enable full web-based emulation, the following work is needed:
- Create a WASM-compatible rendering backend using HTML5 Canvas and JavaScript interop
- Implement Web Audio API integration for DirectSound emulation
- Adapt CPU emulation to work without native intrinsics or provide fallbacks
- Handle file I/O through browser APIs (IndexedDB, FileSystem API)
Use Cases:
- Test emulator compatibility on mobile devices
- Share emulated applications via URL
- Automated testing with Playwright browser automation
- Quick PE file compatibility checks without installing the native application
See Win32Emu.Wasm/README.md for more details.
The core emulation library that powers Win32Emu.Gui. This library provides the Emulator class and EmulatorLauncher API for embedding Win32 emulation into .NET applications.
Win32Emu now includes experimental support for Win16 NE (New Executable) format applications. This enables running 16-bit Windows installers and games common for Windows 9x through a thunking layer that translates Win16 API calls to Win32 equivalents.
Status: 🚧 Experimental - Format loading and Win16→Win32 thunking implemented, full API compatibility in progress
Supported:
- ✓ NE format detection and validation
- ✓ Segment table parsing and loading
- ✓ Entry point resolution
- ✓ Resident/non-resident name table parsing
- ✓ Import module identification and relocation
- ✓ Win16 to Win32 module name mapping (KERNEL→KERNEL32, USER→USER32, GDI→GDI32, etc.)
- ✓ Win16 thunking layer with 6 modules (KERNEL, USER, GDI, KEYBOARD, SYSTEM, SOUND)
- ✓ Handle size conversion (16-bit to 32-bit)
- ✓ Parameter forwarding for compatible functions
Implemented Win16 Modules:
- KERNEL → KERNEL32.DLL (memory, file I/O, strings, module loading)
- USER → USER32.DLL (windows, messages, dialogs, menus, input)
- GDI → GDI32.DLL (device contexts, drawing, text, bitmaps, fonts)
- KEYBOARD → USER32.DLL (keyboard state and configuration)
- SYSTEM → KERNEL32.DLL (timers and system time)
- SOUND → WINMM.DLL (multimedia and sound playback)
Known Limitations:
⚠️ Simplified thunking (complex parameter translation may be needed for some functions)⚠️ PASCAL calling convention handled by underlying Win32 implementations⚠️ Far pointer (segment:offset) translation not fully implemented⚠️ Complex Win16-specific structures may need additional marshalling⚠️ NE resource loading is basic
Example Usage:
# Win32Emu automatically detects the format
Win32Emu.Gui --nogui installer16.exe
# The emulator will log:
# [Loader] Detected format: NE
# [Loader] Win16 NE format support is experimental
# [Loader] Registering Win16 thunking modules for NE format executable
# [Win16 Thunk] GLOBALALLOC - forwarding to KERNEL32For More Information:
Win32Emu uses pluggable backends for cross-platform multimedia support:
- SDL (default): SDL3-CS - Native Metal on macOS, Vulkan on Linux, DirectX 12 on Windows. Best compatibility, hardware-accelerated
- GLFW: Silk.NET.GLFW + OpenGL - Alternative for systems where SDL has issues
- Vulkan: Silk.NET.Vulkan - Modern GPU API with cross-platform support (uses MoltenVK on macOS)
- Metal: SharpMetal - Native Metal backend for macOS (hardware-accelerated)
- Software: SDL3 software renderer - True CPU-only rendering with windowing and event support. No GPU acceleration required, ideal for macOS, debugging, or systems without GPU support
- SDL Audio: SDL3-CS audio when using SDL backend - Native audio support
- OpenAL: Silk.NET.OpenAL - Cross-platform audio support for GLFW/Vulkan backends
- SDL Input: SDL3-CS input when using SDL backend - Keyboard, mouse, and joystick support
- Silk.NET.Input: Unified keyboard, mouse, and gamepad support for GLFW/Vulkan backends
Configuration:
- Command-line:
--backend SDL,--backend GLFW,--backend Vulkan,--backend Metal, or--backend Software - Environment variable:
WIN32EMU_BACKEND=SDL,WIN32EMU_BACKEND=GLFW,WIN32EMU_BACKEND=Vulkan,WIN32EMU_BACKEND=Metal, orWIN32EMU_BACKEND=Software - Programmatic:
BackendFactory.CurrentBackendType = BackendType.SDL;
See docs/implementation/SILK_NET_MIGRATION.md for detailed documentation.
Win32Emu leverages hardware-accelerated SIMD instructions for better performance:
- x86 hosts: Uses SSE, SSE2, SSE3, SSE4, AVX, AVX2 instructions
- ARM hosts: Uses NEON (AdvSimd) instructions
- Automatic detection: CPUID reports accurate host CPU capabilities
- Fallback support: Software implementations when intrinsics aren't available
See docs/implementation/INTRINSICS.md for detailed documentation.
Win32Emu includes a DispatchR-inspired message handling system for type-safe, zero-allocation Win32 message dispatching:
- Type-Safe Handlers: Strongly-typed message classes with compile-time checking
- Zero Allocation: Lambda-based handlers avoid heap allocations
- Extensible: Easy to register custom message handlers
- Testable: Handlers can be tested independently from API implementations
Example:
// Register a message handler
env.MessageDispatcher.RegisterHandler(WM.COMMAND, msg =>
{
var cmdMsg = (CommandMessage)msg;
Console.WriteLine($"Button {cmdMsg.ControlId} clicked!");
return 0;
});
// Dispatch a message
var message = new CommandMessage(hwnd, wParam, lParam);
env.MessageDispatcher.Dispatch(message);See docs/implementation/MESSAGE_DISPATCHER_IMPLEMENTATION.md for detailed documentation and examples.
dotnet build Win32Emu.slndotnet test Win32Emu.slnWin32Emu includes comprehensive CPU conformance tests based on the SingleStepTests/80386 test suite - hardware-generated tests that validate CPU implementation against real 386 behavior.
📊 View live test results: CPU Test Results Dashboard
The dashboard shows:
- Pass/fail status for 941 test files
- Success rate per instruction type
- Detailed failure analysis
- Weekly updates via GitHub Actions
For more information about the test reporter tool, see Win32Emu.Tools.TestReporter/README.md.
Win32Emu provides comprehensive Win32 API emulation with transparency about implementation status:
📊 View API Status: API Implementation Dashboard
The dashboard shows:
- All 31 Win32 DLL modules (Kernel32, User32, GDI32, DirectDraw, etc.)
- 1,090 total functions with implementation status
- 84.2% implementation rate (918 implemented, 172 stubs)
- Search and filter by module or function
- Detailed function metadata (ordinal, version, export name)
🔍 View Missing Functions: Missing Functions Report
Compare native Windows ME DLL exports with Win32Emu implementations:
- 27 native DLLs analyzed (KERNEL32, USER32, GDI32, etc.)
- 4,962 total native exports
- 764 implemented (15.4%), 129 stubs (2.6%), 4,069 missing (82.0%)
- Interactive search and filtering
- Detailed per-DLL coverage statistics
Generate report locally:
# Quick generation script
./generate-missing-functions-report.sh
# Or manually
dotnet run --project Win32Emu.Tools.ApiStatusGenerator docs/pages/api-status.json
dotnet run --project Win32Emu.Tools.NativeDllAnalyzer DLLs/WinME docs/pages/api-status.json docs/pages/missing-functions.jsonSee docs/NATIVE_DLL_ANALYSIS.md for detailed documentation.
Use the PeAnalyzer tool to check if your executable is compatible with Win32Emu:
# Analyze a PE executable
dotnet run --project Win32Emu.Tools.PeAnalyzer \
your-game.exe \
docs/pages/api-status.jsonOutput:
{
"verdict": "PARTIALLY COMPATIBLE - 2 missing function(s)",
"implementationPercentage": 86.67,
"dependencies": [
{
"dllName": "USER32.DLL",
"implementedCount": 12,
"stubCount": 0,
"missingCount": 0
}
]
}Features:
- Uses PeNet to parse PE import tables
- Cross-references with Win32Emu implementation status
- Shows per-DLL and per-function compatibility
- Identifies missing, stubbed, and implemented functions
- Calculates overall compatibility percentage
For more information, see Win32Emu.Tools.PeAnalyzer/README.md.