Expand description
Pure-Rust 32-bit x86 emulator + PE loader + Video for Windows host. Lets oxideav delegate decoding (and eventually encoding) to legitimately-licensed Windows codec DLLs on any platform.
Round 1 — “Load + DllMain + clean exit”. The crate ships:
emulator::mmu— flat 4 GiB virtual address space, sparse 4 KiB pages with R/W/X permission bits.emulator::regs,emulator::decode,emulator::isa_int— i386 register file, instruction decoder, executor for the integer base ISA.pe— PE32-only loader: DOS + PE header parse, section mapping into the MMU, base relocation, IAT resolution against the Win32 stub registry, export-by-name lookup.win32::kernel32— minimum stub set to satisfy a Cinepak-class DLL:GetProcessHeap/HeapAlloc/HeapFree/HeapReAlloc/LocalAlloc/LocalFree/OutputDebugStringA/GetTickCount/InterlockedIncrement/InterlockedDecrement/LoadLibraryA/GetProcAddress.
Round 2 — “Decode one Cinepak frame”. Adds:
Sandbox::call_export— generic stdcall guest-call helper.win32::vfw32—BITMAPINFOHEADERmarshalling,ICDECOMPRESSlayout, and theIC*host surface (ICOpen,ICClose,ICGetInfo,ICDecompressBegin,ICDecompressQuery,ICDecompress,ICDecompressEnd) that drives the codec DLL’sDriverProcend-to-end.Sandbox::install_codec/Sandbox::ic_openetc — the ergonomic Rust-side wrappers the integration test uses.
Round 3 — “Real-codec smoke against IR32_32.DLL”. Adds:
tests/common/mod.rs— fixture-discovery helper:OXIDEAV_VFW_FIXTURE_DIRenv var → Wine prefix → Windows system32 → on-disk cache → HTTPS fetch fromsamples.oxideav.org. CI=true bypasses the cache.- Round-3 m1 test asserted the exact set of 49 Win32 imports (gdi32 / user32 / winmm + 24 extra kernel32) the round-1+2 stub registry did not satisfy — round 4’s concrete dispatch budget. Round 4 closed every gap; the m1 test now asserts zero unresolved imports.
tests/m2_indeo3_driverproc.rsretained the synthetic-codec walkthrough; a forward-compatible Indeo 3DllMain → ICOpen → ICGetInfo → ICClosewalkthrough that activated once round 4 closed the import gaps.
Round 4 — “Close the 49 round-3 import gaps”. Adds the 49 stubs round 3 surfaced:
win32::gdi32— 8 fail-soft stubs forBitBlt/CreateCompatibleDC/DeleteDC/GetDeviceCaps/GetNearestColor/GetObjectA/GetSystemPaletteEntries/SelectObject.win32::kernel32— 24 round-4 stubs covering the CRT init surface (ExitProcess,GetACP/GetOEMCP/GetCPInfo,GetCommandLineA/GetEnvironmentStrings/GetFileType,GetLastError/SetLastError,GetModuleFileNameA/GetModuleHandleA,GetStartupInfoA/GetStdHandle/GetSystemInfo/GetVersion,GlobalAlloc/GlobalFree/GlobalLock/GlobalUnlock,MultiByteToWideChar/WideCharToMultiByte,RtlUnwind,VirtualAlloc/VirtualFree,WriteFile).win32::user32— 16 fail-soft stubs covering the dialog / paint surface;MessageBoxAlogs to stderr +host.message_box_log;wsprintfAis a real cdecl variadic implementation.win32::winmm—DefDriverProc(returns 0 / DRVCNF_OK).emulator::mmu::Mmu::unmap+emulator::mmu::Mmu::find_free_rangefor theVirtualAlloc/VirtualFreefamily.
With round 4 in place, IR32_32.DLL loads cleanly and
DllMain runs until it hits the first ISA opcode our integer
interpreter does not yet decode: ADD AL, imm8 (opcode
0x04) at eip = 0x1000_612A. That was round-4’s hand-off
to round 5.
Round 5 — “DllMain + ICOpen + ICGetInfo + ICClose against Intel IR32_32.DLL”. Adds:
- The 8-bit primary ALU opcodes (
0x00..=0x05ADD,0x08..=0x0DOR,0x10..=0x15ADC, …,0x38..=0x3DCMP) plusr/m8 imm8group-1 (0x80),r/m8group-3 (0xF6),r/m8group-4 (0xFE). - Group-2
r/m8shifts (0xC0/0xD0/0xD2) plus ther/m321/cl variants (0xD1/0xD3). IMUL r32, r/m32, imm32/imm8(0x69/0x6B),XCHG r/m, r(0x86/0x87),SAHF/LAHF(0x9E/0x9F),CMC(0xF5),PUSHAD/POPAD(0x60/0x61),ENTER(0xC8), the fullMOVS/CMPS/STOS/LODS/SCASfamily with REP / REPE / REPNE prefixes.0F 40..4F CMOVcc,0F A3 BT,0F AB BTS,0F A4..A5 SHLD,0F AC..AD SHRD,0F BAgroup-8 (BT/BTS/BTR/BTC imm8),0F B1 CMPXCHG,0F C1 XADD,0F C8..CF BSWAP.- Per-instruction segment-override prefix routing through
emulator::Cpu::set_fs_base/set_gs_base. The runtime maps a 4 KiB TEB at0x7FFD_E000, primesFS:[0](SEH chain end-of-list =-1) andFS:[0x18](TEB self-pointer), and points FS at it. - Corrected
vfw32::ICM_*numeric values (ICM_GETINFO = 0x5002,ICM_DECOMPRESS = 0x400D, etc). win32::vfw32::ic_opennow stages a real 36-byteICOPENso the codec’sDRV_OPENallocates per-instance state (round 4 passed NULL).win32::vfw32::ic_get_infofalls back to an fcc-derivedszNamewhen the codec leaves it NUL (realvfw32!ICGetInfofills it from the registry).- Bug-fix: round-4’s
0xC6(MOV r/m8, imm8) handler fetched the immediate BEFORE resolving the displacement.
Round 6 — “Drive the full IC decode pipeline end-to-end
against Intel IR32_32.DLL”.* No new emulator code needed:
round-5’s ISA + segment-prefix coverage is sufficient for the
ICDecompressQuery → ICDecompressBegin → ICDecompress → ICDecompressEnd sequence to walk cleanly. The
tests/m2_indeo3_driverproc.rs::indeo3_decompress_one_keyframe
integration test exercises the whole sequence against a
synthetic IV31 keyframe (64×48). The codec accepts the input
/ output formats, sets up internal state, rejects the
synthetic NULL-data-size sync frame at the bitstream-header
validation step (returns ICERR_BADIMAGE = -100), and tears
down cleanly. SPECGAP: the IV5PLAY fixture bundle ships
only DLLs, no .avi payloads, so round-6 cannot exercise a
real keyframe end-to-end. Round 7+ swaps the synthetic input
for a real keyframe once one becomes available.
Round 7 — “Real IV31 keyframe decode through cubes.mov,
plus MMX scaffolding”. Twin deliverables:
- Part A — Real keyframe decode. Adds a test-side
QuickTime / ISO BMFF chunk walker
(
tests/common/mov_extractor.rs, ~270 LOC, authored from ISO/IEC 14496-12 alone) that locates sample 0 incubes.mov(160×120 yuv410p, 121 KB) fromsamples.oxideav.org/ffmpeg/V-codecs/IV32/. The newtests/round7_cubes_mov.rs::cubes_mov_first_keyframe_decodes_through_ir32_32_dllfeeds the real 3079-byte IV31 keyframe through the IC* sequence;ICDecompressreturnsICERR_OKand ~30 K of the 57.6 KB RGB24 output is non-zero — the first real pixel decode throughIR32_32.DLL. The bug fix that unblocks this:ICM_DECOMPRESS_BEGINwas atICM_USER + 16 = 0x4010(round-5 typo) — an unmapped slot inIR32_32.DLL’s dispatch table. The canonical vfw.h value isICM_USER + 12 = 0x400C. Without the BEGIN handler running,ICDecompressbailed early at a[state2_ptr] != 0sentinel check. While here,ICM_DECOMPRESS_GET_FORMATcorrected from0x4008→0x400A. - Part B — MMX scaffolding for round 8.
emulator::Cpugrows anmmx: [u64; 8]register file (mm0..mm7, per Intel SDM Vol. 1 §9.2.1). A newemulator::Trap::UnimplementedMmxvariant carries the 2-byte opcode + EIP + an SDM-derived mnemonic hint ("PADDB MMX","PXOR MMX","EMMS", …). The0x0F 0x60..0x6F,0x0F 0x70..0x7F, and0x0F 0xD0..0xFFopcode blocks (per SDM Vol. 2 Appendix A Table A-3) now route throughemulator::isa_int::dispatch_mmxto the structured trap instead of the genericUndefinedOpcode. Round 8 reads the trap log to land MMX semantics opcode-by-opcode.
Round 18 — trace Cargo feature. Resolves the planned
“trace mode” milestone documented in
docs/winmf/winmf-emulator.md §“Trace mode”. A new feature
gate trace (off by default) adds #[cfg]’d probe sites at
the four natural choke points: every dispatch_stub call
(kind=win32_call), every guest memory access overlapping
a registered watchpoint (kind=mem_write / kind=mem_read),
every trap that bubbles out of the run loop (kind=trap),
and — under the trace-exec sub-feature plus
Sandbox::set_exec_trace(true) — every executed
instruction (kind=exec). Output is JSONL on a sink
configured via OXIDEAV_VFW_TRACE_FILE=<path|2> or
Sandbox::set_trace_sink. With the feature off, every
probe compiles away; release builds are bit-identical to
the round-17 baseline. Companion CLI is
oxideav-tracevfw.
Modern codecs (H.264 / HEVC / AV1 / Opus / AAC / …) are decoded natively elsewhere in the workspace; this crate exists for rare/legacy codecs the project would otherwise permanently shelve. Codec DLLs never execute on the host CPU; they run through the bounded-MMU interpreter.
See OxideAV/docs/winmf/winmf-emulator.md (659 lines, 13
sections) for the full design contract.
Re-exports§
pub use context::Context;pub use context::FileAccess;pub use context::FileHandle;pub use context::OpenKey;pub use context::RegistryKey;pub use context::RegistryValue;pub use context::VirtualFs;pub use context::VirtualRegistry;pub use context::HKCR;pub use context::HKCU;pub use context::HKEY_CLASSES_ROOT;pub use context::HKEY_CURRENT_USER;pub use context::HKEY_LOCAL_MACHINE;pub use context::HKEY_USERS;pub use context::HKLM;pub use context::HKU;pub use coverage::CoverageMap;pub use ffi::CallArgs;pub use ffi::Dword;pub use ffi::FromRet;pub use ffi::Guest;pub use com::Guid;pub use com::GuidParseError;pub use com::CLSID_MEMORY_ALLOCATOR;pub use com::IID_IBASEFILTER;pub use com::IID_ICLASSFACTORY;pub use com::IID_IENUMPINS;pub use com::IID_IFILTERGRAPH;pub use com::IID_IMEDIAFILTER;pub use com::IID_IMEDIASAMPLE;pub use com::IID_IMEMALLOCATOR;pub use com::IID_IMEMINPUTPIN;pub use com::IID_IPERSIST;pub use com::IID_IPIN;pub use com::IID_IUNKNOWN;pub use com::MSADDS_AUDIO_DECODER_CLSID;pub use com::MSADDS_AUDIO_PROPERTY_PAGE_CLSID;pub use runtime::Sandbox;pub use runtime::DLL_PROCESS_ATTACH;pub use trace::TraceState;pub use trace::WatchMode;pub use trace::Watchpoint;pub use win32::vfw32::Bih;
Modules§
- com
- COM (Component Object Model) scaffolding — round 25, stage 1.
- context
- Optional emulation-context layer.
- coverage
- Execution coverage tracker.
- emulator
- The 32-bit x86 software interpreter.
- ffi
- FFI-style front end for calling into an emulated guest.
- pe
- PE32 loader — parses Microsoft Portable Executable images,
maps them into the emulator MMU, applies base relocations,
resolves imports against the
crate::win32::Registry, and exposes export-by-name lookup. - runtime
- Top-level
Sandbox— owns the MMU, the CPU, the Win32 stub registry, and the per-emulator host state, and exposes the “load this DLL and call its DllMain” workflow that the integration tests + future codec wrapper layers drive. - sched
- Preemptive scheduler for the Win32 emulator.
- trace
- Reverse-engineering trace surface (gated on the
traceCargo feature). - win32
- Win32 stub registry + per-DLL host implementations of the functions the loaded codec DLLs import.
Enums§
- Error
- Crate-local error type. Each layer (MMU / decoder / executor / PE loader / Win32 stub) has its own variant; sublayers nest their detail enums.
Type Aliases§
- Result
- Crate-local Result alias.