Strip out watchpoint system (thunkSetWatch, WATCH-PRE/POST), INT 10h entry counters, segment verification dumps, and inline extern declarations. Add neSetDebug to neload.h, correct -fno-gcse comment, and add project CLAUDE.md for git-tracked notes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.1 KiB
6.1 KiB
Win31drv Project Memory
Build Environment
- DJGPP cross-compiler:
~/djgpp/djgpp/bin/i586-pc-msdosdjgpp-gcc(GCC 12.2.0) - DJGPP binutils need
libfl.so.2: stored intools/lib/(Makefiles set LD_LIBRARY_PATH) - CWSDPMI zip stored in
tools/cwsdpmi.zip(extracted to bin/ during build) - DOSBox-X:
flatpak run com.dosbox_x.DOSBox-X(installed as user flatpak) - CWSDPMI.EXE in
bin/directory for DPMI support under DOSBox-X - Config:
dosbox-x.confwith S3 Trio64 machine type, 64MB RAM
Project Structure
windriver/
├── Makefile # Top-level: builds demo, calls win31drv/Makefile
├── demo.c # Demo program
├── dosbox-x.conf # DOSBox-X config (S3 SVGA)
├── obj/ # Demo object files
├── bin/ # Executables + CWSDPMI.EXE
└── win31drv/ # Library
├── Makefile # Builds libwindrv.a
├── obj/ # Library objects
├── neload.c/h # NE format loader
├── neformat.h # NE structures
├── thunk.c/h # 32→16 bit thunking
├── windrv.c/h # Main API
├── winstub.c/h # Windows API stubs
├── winddi.h # DDI structures
└── wintypes.h # Win16 types
DJGPP Portability Notes
uint32_tisunsigned long(notunsigned int) in DJGPP — usePRIu32/PRIX32from<inttypes.h>- Always include
<stdarg.h>explicitly forva_list/va_start/va_end - Headers must be self-contained (include their own dependencies)
Thunking Architecture Notes
- SS == DS == DGROUP: Win3.x drivers assume SS == DS == DGROUP. VBESVGA's BBLT.ASM does
PrestoChangeoSelector(SS, WorkSelector)to create a code alias for compiled blit code. thunkCall16 uses dgroupSel as SS (SP=0xFFF0) when available. Without this, the code alias has the wrong base and the CPU executes garbage. - Register corruption with -O2 inlining: When demo.c's demoDrawing is inlined into main,
DJGPP GCC 12.2.0 mishandles callee-saved registers across thunk calls in long functions.
Fix:
__attribute__((noinline))on demoDrawing. Symptom: handle pointer corrupted to a ColorInfo return value (e.g. 0xFF0001F6) between Demo 2 and Demo 3.
DOSBox-X Driver Notes
waitForEngine(): GP_STAT port 0x9AE8 bit 9 polling — S3 only (gIsS3 guard)- S3 detection: Probe CR30 chip ID register. S3 chips: 0x81-0xE1. ET4000: 0x00. Only apply S3-specific setup (cursor disable, dispYOffset, setDisplayStart) when isS3=true AND driver is not VGA-class (1bpp/4planes).
- Pattern scratch artifact: S3 driver writes 8x8 dithered brush pattern to VRAM at fixed
position (~(144,1)-(151,8)) during accelerated pattern fills. Fixed by shifting CRTC display
start down 10 scanlines (
dispYOffset) so the scratch area is off-screen. -fno-gcserequired for windrv.c: With -O2 GCSE, stack layout causes issues during 16-bit driver calls. Only windrv.c needs this. SeeWINDRV_CFLAGSin win31drv/Makefile.- Output DDI (polylines/rectangles) requires a physical pen from RealizeObject, not a raw LogPen16T. The pen must be in DGROUP (same as brush, drawMode, PDEVICE).
wdrvUnloadDriverdoes NOT auto-call Disable — caller must handle text mode restoresleep()hangs under DOSBox-X because BIOS timer ticks don't advance without I/O- Debug output:
-dflag enables verbose logging in neload, winstub, thunk, and windrv - Known issue: mode mismatch HW=800x600 vs GDIINFO=640x480
DGROUP Stack Management
- VGA.DRV ships with DGROUP[0x0A]=0xFFFF (stack bottom = top of segment → no stack). Its BitBlt prolog calls a stack check function at 0x18CA that compares available stack against [SS:0x0A]. With 0xFFFF, ALL functions fail immediately (return 0).
- Fix: patch [0x0A] to objBase after extending DGROUP. Only done when original = 0xFFFF.
- S3TRIO.DRV and VBESVGA.DRV have [0x0A]=0x0000 — no patching needed.
- Do NOT unconditionally overwrite DGROUP offsets 0x00-0x0F — VBESVGA.DRV stores driver-specific data there (0x030A at offset 0, 0x01 at offset 4).
BitBlt Source Device Rules
- For pattern-only ROPs (PATCOPY=0xF0, BLACKNESS=0x00, WHITENESS=0xFF, etc.), lpSrcDev must be NULL (0:0) per DDI spec. VGA.DRV rejects non-NULL source for pattern-only ROPs. S3TRIO.DRV tolerates it but correct behavior is NULL.
- Source dependency check:
ropNeedsSrc = (((rop8 >> 2) ^ rop8) & 0x33) != 0
INT 10h ES Translation
- Different INT 10h function families use different ES:offset registers: VBE 4Fxx → ES:DI, AH=10h (palette) → ES:DX, AH=11h (fonts) → ES:BP, AH=1Bh → ES:DI
- Only specific AL subfunctions use ES as a buffer pointer; most don't
- Copy sizes must be exact (17 bytes for palette, CX*3 for DAC blocks, etc.)
- Copy direction matters: "Set" = copy-in only, "Read/Get" = copy-out only
WINFLAGS Handling
- WF_80x87 NOT used: We don't save/restore FPU state across thunk boundaries
- VGA-class drivers need WF_STANDARD: VGA.DRV's physical_enable hangs in Enhanced mode (polls VDD that doesn't exist). Auto-detected after Enable(style=1) returns 1bpp/4planes GDIINFO → repatch __WINFLAGS in all segments (0x0025→0x0015).
- SVGA drivers (S3TRIO, VBESVGA) use WF_ENHANCED normally
ET4000 Driver Notes
- ET4000.DRV from Win 3.x distribution is SZDD-compressed; decompress with
msexpand(rename to .DR_ first, output is .DR without the V — rename to .DRV) - DOSBox-X machine type:
svga_et4000for ET4000 hardware emulation - ET4000 is 640x480 8bpp, software-rendered (no accelerator engine in DOSBox-X)
- CR30=0x00 on ET4000 → isS3=false → no S3 engine wait, no display start shift
Current Demo Status
- S3TRIO.DRV, VBESVGA.DRV, VGA.DRV, ET4000.DRV all work: Load → Enable → Draw → Disable → Unload
- Demo 1: Fill rectangles (BitBlt) — works
- Demo 2: Pixel patterns (Pixel) — works
- Demo 3: Lines/starburst (Output/Polyline) — works
- Demo 4: Screen-to-screen blit (BitBlt SRCCOPY) — works
- VGA.DRV: 640x480 4-plane 16-color mode; limited color palette but functional
- ET4000.DRV: 640x480 8bpp on svga_et4000; software-only, no hw acceleration
- Drivers stored in
drivers/directory, copied tobin/during build