├── .gitignore ├── .hgignore ├── boxv.c ├── boxv.h ├── boxv9x.def ├── boxv9x.inf ├── boxv9x.lnk ├── boxv_io.h ├── boxvint.h ├── dbgprint.c ├── ddk ├── configmg.h ├── dibeng.def ├── dibeng.h ├── dibeng.lbc ├── gdidefs.h ├── minivdd.h └── valmode.h ├── dibcall.c ├── dibthunk.asm ├── enable.c ├── init.c ├── makefile ├── minidrv.h ├── modes.c ├── palette.c ├── readdev.txt ├── readme.txt ├── res ├── colortab.c ├── config.c ├── display.rc ├── display.rcv ├── fonts.c ├── fonts120.c └── fonttmpl.c ├── scrsw.c ├── sswhook.asm ├── vxd ├── .gitignore ├── README.txt ├── boxvmini.asm ├── boxvmini.def └── make.bat └── winhack.h /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | res/*.obj 3 | res/*.bin 4 | *.obj 5 | *.err 6 | *.lib 7 | *.drv 8 | *.map 9 | *.res 10 | *.img -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | # Use glob syntax. 2 | syntax: glob 3 | 4 | *.drv 5 | *.sym 6 | *.res 7 | *.bin 8 | *.obj 9 | *.lib 10 | *.map 11 | *.err 12 | dist 13 | boxv9x.img 14 | -------------------------------------------------------------------------------- /boxv.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2012-2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* Core boxv implementation. */ 26 | 27 | #include "boxv.h" /* Public interface. */ 28 | #include "boxvint.h" /* Implementation internals. */ 29 | #include "boxv_io.h" /* I/O access layer, host specific. */ 30 | 31 | 32 | /* Write a single value to an indexed register at a specified 33 | * index. Suitable for the CRTC or graphics controller. 34 | */ 35 | inline void vid_wridx( void *cx, int idx_reg, int idx, v_byte data ) 36 | { 37 | vid_outw( cx, idx_reg, idx | (data << 8) ); 38 | } 39 | 40 | /* Set an extended non-VGA mode with given parameters. 8bpp and higher only. 41 | * Returns non-zero value on failure. 42 | */ 43 | int BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres, int v_yres ) 44 | { 45 | /* Do basic parameter validation. */ 46 | if( v_xres < xres || v_yres < yres ) 47 | return( -1 ); 48 | 49 | /* Put the hardware into a state where the mode can be safely set. */ 50 | vid_inb( cx, VGA_STAT_ADDR ); /* Reset flip-flop. */ 51 | vid_outb( cx, VGA_ATTR_W, 0 ); /* Disable palette. */ 52 | vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR_RESET ); 53 | 54 | /* Disable the extended display registers. */ 55 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE ); 56 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED ); 57 | 58 | /* Program the extended non-VGA registers. */ 59 | 60 | /* Set X resoultion. */ 61 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES ); 62 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, xres ); 63 | /* Set Y resoultion. */ 64 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES ); 65 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, yres ); 66 | /* Set bits per pixel. */ 67 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP ); 68 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, bpp ); 69 | /* Set the virtual resolution. */ 70 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH ); 71 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, v_xres ); 72 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_HEIGHT ); 73 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, v_yres ); 74 | /* Reset the current bank. */ 75 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BANK ); 76 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 ); 77 | /* Set the X and Y display offset to 0. */ 78 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_X_OFFSET ); 79 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 ); 80 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_Y_OFFSET ); 81 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 ); 82 | /* Enable the extended display registers. */ 83 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE ); 84 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC | VBE_DISPI_LFB_ENABLED ); 85 | 86 | /* Re-enable the sequencer. */ 87 | vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR0_NORESET ); 88 | 89 | /* Reset flip-flop again and re-enable palette. */ 90 | vid_inb( cx, VGA_STAT_ADDR ); 91 | vid_outb( cx, VGA_ATTR_W, 0x20 ); 92 | 93 | return( 0 ); 94 | } 95 | 96 | /* Program the DAC. Each of the 'count' entries is 4 bytes in size, 97 | * red/green/blue/unused. 98 | * Returns non-zero on failure. 99 | */ 100 | int BOXV_dac_set( void *cx, unsigned start, unsigned count, void *pal ) 101 | { 102 | v_byte *prgbu = pal; 103 | 104 | /* Basic argument validation. */ 105 | if( start + count > 256 ) 106 | return( -1 ); 107 | 108 | /* Write the starting index. */ 109 | vid_outb( cx, VGA_DAC_W_INDEX, start ); 110 | /* Load the RGB data. */ 111 | while( count-- ) { 112 | vid_outb( cx, VGA_DAC_DATA, *prgbu++ ); 113 | vid_outb( cx, VGA_DAC_DATA, *prgbu++ ); 114 | vid_outb( cx, VGA_DAC_DATA, *prgbu++ ); 115 | ++prgbu; 116 | } 117 | return( 0 ); 118 | } 119 | 120 | /* Detect the presence of a supported adapter and amount of installed 121 | * video memory. Returns zero if not found. 122 | */ 123 | int BOXV_detect( void *cx, unsigned long *vram_size ) 124 | { 125 | v_word boxv_id; 126 | 127 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID ); 128 | boxv_id = vid_inw( cx, VBE_DISPI_IOPORT_DATA ); 129 | 130 | if( boxv_id < VBE_DISPI_ID0 || boxv_id > VBE_DISPI_ID6 ) 131 | return( 0 ); 132 | 133 | if( vram_size ) { 134 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIDEO_MEMORY_64K ); 135 | *vram_size = (unsigned long)vid_inw( cx, VBE_DISPI_IOPORT_DATA ) << 16; 136 | } 137 | 138 | return( boxv_id ); 139 | } 140 | 141 | /* Disable extended mode and place the hardware into a VGA compatible state. 142 | * Returns non-zero on failure. 143 | */ 144 | int BOXV_ext_disable( void *cx ) 145 | { 146 | /* Disable the extended display registers. */ 147 | vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE ); 148 | vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED ); 149 | return( 0 ); 150 | } 151 | -------------------------------------------------------------------------------- /boxv.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2012-2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* 26 | * Public interface to the boxv library. 27 | */ 28 | 29 | /* PCI vendor and device IDs. */ 30 | #define BOXV_PCI_VEN 0x80EE 31 | #define BOXV_PCI_DEV 0xBEEF 32 | 33 | /* A structure describing mode information. Note: The mode numbers 34 | * usually match VBE, but this should not be relied upon. 35 | */ 36 | typedef struct { 37 | int mode_no; /* Mode number */ 38 | int xres; /* Horizontal resolution */ 39 | int yres; /* Vertical resolution */ 40 | int bpp; /* Color depth */ 41 | } BOXV_mode_t; 42 | 43 | extern void BOXV_mode_enumerate( void *cx, int (cb)( void *cx, BOXV_mode_t *mode ) ); 44 | extern int BOXV_detect( void *cx, unsigned long *vram_size ); 45 | extern int BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres, int v_yres ); 46 | extern int BOXV_mode_set( void *cx, int mode_no ); 47 | extern int BOXV_dac_set( void *cx, unsigned start, unsigned count, void *pal ); 48 | extern int BOXV_ext_disable( void *cx ); 49 | -------------------------------------------------------------------------------- /boxv9x.def: -------------------------------------------------------------------------------- 1 | ; 2 | ; Standard display driver .DEF file 3 | ; 4 | LIBRARY DISPLAY 5 | 6 | ; 7 | ; The magic numbers are: Aspect ratio, Horizontal DPI, Vertical DPI 8 | ; 9 | DESCRIPTION 'DISPLAY : 100, 96, 96 : DIB Engine based Mini display driver.' 10 | EXETYPE WINDOWS 11 | 12 | DATA PRELOAD FIXED SINGLE 13 | 14 | SEGMENTS 15 | _TEXT PRELOAD SHARED 16 | _INIT PRELOAD MOVEABLE 17 | 18 | EXPORTS 19 | BitBlt @1 20 | ColorInfo @2 21 | Control @3 22 | Disable @4 23 | Enable @5 24 | EnumDFonts @6 25 | EnumObj @7 26 | Output @8 27 | Pixel @9 28 | RealizeObject @10 29 | StrBlt @11 30 | ScanLR @12 31 | DeviceMode @13 NODATA 32 | 33 | ExtTextOut @14 34 | GetCharWidth @15 NODATA 35 | DeviceBitmap @16 NODATA 36 | FastBorder @17 37 | SetAttribute @18 NODATA 38 | 39 | DibBlt @19 ; Device Independent Bitmap group 40 | CreateDIBitmap @20 41 | DibToDevice @21 42 | 43 | SetPalette @22 ; Windows 3.0 palette group 44 | GetPalette @23 45 | 46 | SetPaletteTranslate @24 47 | GetPaletteTranslate @25 48 | UpdateColors @26 49 | StretchBlt @27 50 | StretchDIBits @28 51 | 52 | SelectBitmap @29 53 | BitmapBits @30 54 | ReEnable @31 55 | 56 | Inquire @101 ; Mouse cursor function group 57 | SetCursor @102 58 | MoveCursor @103 59 | CheckCursor @104 60 | 61 | GetDriverResourceID @450 ; Undocumented USER callback 62 | UserRepaintDisable @500 ; Undocumented USER callback 63 | 64 | ValidateMode @700 65 | 66 | IMPORTS 67 | GlobalSmartPageLock = KERNEL.230 ; Undocumented function 68 | -------------------------------------------------------------------------------- /boxv9x.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; INF file for QEMU Win9x display driver 3 | ; Copyright 2012-2022, The OS/2 Museum 4 | 5 | [version] 6 | Class=DISPLAY 7 | signature="$CHICAGO$" 8 | Provider=%Mfg% 9 | 10 | [DestinationDirs] 11 | DefaultDestDir = 11 ; LDID_SYS 12 | BoxV.Copy = 11 13 | 14 | [SourceDisksNames] 15 | ; BOXV9X is the driver disk volume label 16 | 1="QEMU Win9x Display Driver Disk",BOXV9X,1 17 | 18 | [SourceDisksFiles] 19 | boxvmini.drv=1 20 | boxvmini.vxd=1 21 | 22 | [Manufacturer] 23 | %Mfg%=Mfg.BoxV 24 | 25 | [Mfg.BoxV] 26 | %PCI\VEN_1234&DEV_1111.DeviceDesc%=BoxV,PCI\VEN_1234&DEV_1111 27 | 28 | [BoxV] 29 | CopyFiles=BoxV.Copy 30 | DelReg=Prev.DelReg 31 | AddReg=BoxV_AddReg 32 | 33 | [BoxV.Copy] 34 | boxvmini.drv 35 | boxvmini.vxd 36 | 37 | [Prev.DelReg] 38 | HKR,,Ver 39 | HKR,,DevLoader 40 | HKR,DEFAULT 41 | HKR,MODES 42 | HKR,CURRENT 43 | 44 | [BoxV_AddReg] 45 | HKR,,Ver,,4.0 46 | HKR,,DevLoader,,*vdd 47 | HKR,DEFAULT,Mode,,"8,640,480" 48 | HKR,DEFAULT,drv,,boxvmini.drv 49 | HKR,DEFAULT,vdd,,"*vdd,*vflatd" 50 | HKR,DEFAULT,minivdd,,boxvmini.vxd 51 | ;HKR,DEFAULT,carddvdd,,cardsamp.vxd 52 | HKR,DEFAULT,RefreshRate,,-1 53 | HKR,DEFAULT,DDC,,1 54 | HKR,DEFAULT,ExtModeSwitch,,0 55 | HKR,"MODES\4\640,480",drv,,vga.drv 56 | HKR,"MODES\4\640,480",vdd,,*vdd 57 | HKR,"MODES\4\800,600",drv,,supervga.drv 58 | HKR,"MODES\4\800,600",vdd,,*vdd 59 | HKR,"MODES\8\640,480" 60 | HKR,"MODES\8\800,600" 61 | HKR,"MODES\8\1024,768" 62 | HKR,"MODES\8\1152,864" 63 | HKR,"MODES\8\1280,720" 64 | HKR,"MODES\8\1280,800" 65 | HKR,"MODES\8\1280,960" 66 | HKR,"MODES\8\1280,1024" 67 | HKR,"MODES\8\1400,1050" 68 | HKR,"MODES\8\1600,1200" 69 | HKR,"MODES\8\1600,900" 70 | HKR,"MODES\8\1680,1050" 71 | HKR,"MODES\8\1920,1080" 72 | HKR,"MODES\8\1920,1200" 73 | HKR,"MODES\16\640,480" 74 | HKR,"MODES\16\800,600" 75 | HKR,"MODES\16\1024,768" 76 | HKR,"MODES\16\1152,864" 77 | HKR,"MODES\16\1280,720" 78 | HKR,"MODES\16\1280,800" 79 | HKR,"MODES\16\1280,960" 80 | HKR,"MODES\16\1280,1024" 81 | HKR,"MODES\16\1400,1050" 82 | HKR,"MODES\16\1600,900" 83 | HKR,"MODES\16\1600,1200" 84 | HKR,"MODES\16\1680,1050" 85 | HKR,"MODES\16\1920,1080" 86 | HKR,"MODES\16\1920,1200" 87 | HKR,"MODES\24\640,480" 88 | HKR,"MODES\24\800,600" 89 | HKR,"MODES\24\1024,768" 90 | HKR,"MODES\24\1152,864" 91 | HKR,"MODES\24\1280,720" 92 | HKR,"MODES\24\1280,800" 93 | HKR,"MODES\24\1280,960" 94 | HKR,"MODES\24\1280,1024" 95 | HKR,"MODES\24\1400,1050" 96 | HKR,"MODES\24\1600,900" 97 | HKR,"MODES\24\1600,1200" 98 | HKR,"MODES\24\1680,1050" 99 | HKR,"MODES\24\1920,1080" 100 | HKR,"MODES\24\1920,1200" 101 | HKR,"MODES\32\640,480" 102 | HKR,"MODES\32\800,600" 103 | HKR,"MODES\32\1024,768" 104 | HKR,"MODES\32\1152,864" 105 | HKR,"MODES\32\1280,720" 106 | HKR,"MODES\32\1280,800" 107 | HKR,"MODES\32\1280,960" 108 | HKR,"MODES\32\1280,1024" 109 | HKR,"MODES\32\1400,1050" 110 | HKR,"MODES\32\1600,900" 111 | HKR,"MODES\32\1600,1200" 112 | HKR,"MODES\32\1680,1050" 113 | HKR,"MODES\32\1920,1080" 114 | HKR,"MODES\32\1920,1200" 115 | 116 | [Strings] 117 | Mfg="QEMU" 118 | PCI\VEN_1234&DEV_1111.DeviceDesc="QEMU SVGA PCI" 119 | -------------------------------------------------------------------------------- /boxv9x.lnk: -------------------------------------------------------------------------------- 1 | # This file produced by MS2WLINK 2 | system windows dll initglobal 3 | file dibthunk.obj 4 | file dibcall.obj 5 | file enable.obj 6 | file init.obj 7 | file palette.obj 8 | file scrsw.obj 9 | file sswhook.obj 10 | file modes.obj 11 | file boxv.obj 12 | name boxvmini.drv 13 | option map=boxvmini.map 14 | library dibeng.lib 15 | library clibs.lib 16 | option modname=DISPLAY 17 | option description 'DISPLAY : 100, 96, 96 : DIB Engine based Mini display driver.' 18 | option oneautodata 19 | segment type data preload fixed 20 | # definition file segments keyword handled differently in WLINK 21 | segment '_TEXT' preload shared 22 | segment '_INIT' preload moveable 23 | export BitBlt.1 24 | export ColorInfo.2 25 | export Control.3 26 | export Disable.4 27 | export Enable.5 28 | export EnumDFonts.6 29 | export EnumObj.7 30 | export Output.8 31 | export Pixel.9 32 | export RealizeObject.10 33 | export StrBlt.11 34 | export ScanLR.12 35 | export DeviceMode.13 36 | export ExtTextOut.14 37 | export GetCharWidth.15 38 | export DeviceBitmap.16 39 | export FastBorder.17 40 | export SetAttribute.18 41 | export DibBlt.19 42 | export CreateDIBitmap.20 43 | export DibToDevice.21 44 | export SetPalette.22 45 | export GetPalette.23 46 | export SetPaletteTranslate.24 47 | export GetPaletteTranslate.25 48 | export UpdateColors.26 49 | export StretchBlt.27 50 | export StretchDIBits.28 51 | export SelectBitmap.29 52 | export BitmapBits.30 53 | export ReEnable.31 54 | export Inquire.101 55 | export SetCursor.102 56 | export MoveCursor.103 57 | export CheckCursor.104 58 | export GetDriverResourceID.450 59 | export UserRepaintDisable.500 60 | export ValidateMode.700 61 | import GlobalSmartPageLock KERNEL.230 62 | -------------------------------------------------------------------------------- /boxv_io.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2012-2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | #include /* For port I/O prototypes. */ 26 | 27 | /* The 16-bit compiler does not do inpd(). We have to do it ourselves. 28 | * NB: It might be OK to trash the high bits of EAX but better be safe. 29 | */ 30 | /* Warning: Destroys high bits of EAX. */ 31 | unsigned long inpd( unsigned port ); 32 | #pragma aux inpd = \ 33 | ".386" \ 34 | "push eax" \ 35 | "in eax, dx" \ 36 | "mov dx, ax" \ 37 | "shr eax, 16" \ 38 | "xchg bx, ax" \ 39 | "pop eax" \ 40 | "xchg bx, ax" \ 41 | "xchg ax, dx" \ 42 | parm [dx] value [dx ax] modify [bx] nomemory; 43 | 44 | static void vid_outb( void *cx, unsigned port, unsigned val ) 45 | { 46 | outp( port, val ); 47 | } 48 | 49 | static void vid_outw( void *cx, unsigned port, unsigned val ) 50 | { 51 | outpw( port, val ); 52 | } 53 | 54 | static unsigned vid_inb( void *cx, unsigned port ) 55 | { 56 | return( inp( port ) ); 57 | } 58 | 59 | static unsigned vid_inw( void *cx, unsigned port ) 60 | { 61 | return( inpw( port ) ); 62 | } 63 | -------------------------------------------------------------------------------- /boxvint.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2012-2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* Internal definitions used by the boxv library. */ 26 | 27 | /*-------------- VGA Specific ----------------*/ 28 | 29 | /* VGA I/O port addresses. */ 30 | #define VGA_CRTC 0x3D4 /* Color only! */ 31 | #define VGA_ATTR_W 0x3C0 32 | #define VGA_ATTR_R 0x3C1 33 | #define VGA_MISC_OUT_W 0x3C2 34 | #define VGA_SEQUENCER 0x3C4 35 | #define VGA_SEQUENCER_DATA 0x3C5 36 | #define VGA_PIXEL_MASK 0x3C6 37 | #define VGA_DAC_W_INDEX 0x3C8 38 | #define VGA_DAC_DATA 0x3C9 39 | #define VGA_MISC_OUT_R 0x3CC 40 | #define VGA_GRAPH_CNTL 0x3CE 41 | #define VGA_GRAPH_CNTL_DATA 0x3CF 42 | #define VGA_STAT_ADDR 0x3DA /* Color only! */ 43 | 44 | /* VGA Attribute Controller register indexes. */ 45 | #define VGA_AR_MODE 0x10 46 | #define VGA_AR_OVERSCAN 0x11 47 | #define VGA_AR_PLANE_EN 0x12 48 | #define VGA_AR_PIX_PAN 0x13 49 | #define VGA_AR_COLOR_SEL 0x14 50 | 51 | /* VGA Graphics Controller register indexes. */ 52 | #define VGA_GR_SET_RESET 0x00 53 | #define VGA_GR_DATA_ROTATE 0x03 54 | #define VGA_GR_READ_MAP_SEL 0x04 55 | #define VGA_GR_MODE 0x05 56 | #define VGA_GR_MISC 0x06 57 | #define VGA_GR_BIT_MASK 0x08 58 | 59 | /* VGA Sequencer register indexes. */ 60 | #define VGA_SR_RESET 0x00 61 | #define VGA_SR_CLK_MODE 0x01 62 | #define VGA_SR_PLANE_MASK 0x02 63 | #define VGA_SR_MEM_MODE 0x04 64 | 65 | /* Sequencer constants. */ 66 | #define VGA_SR0_NORESET 0x03 67 | #define VGA_SR0_RESET 0x00 68 | #define VGA_SR1_BLANK 0x20 69 | 70 | /* VGA CRTC register indexes. */ 71 | #define VGA_CR_HORZ_TOTAL 0x00 72 | #define VGA_CR_CUR_START 0x0A 73 | #define VGA_CR_CUR_END 0x0B 74 | #define VGA_CR_START_HI 0x0C 75 | #define VGA_CR_START_LO 0x0D 76 | #define VGA_CR_CUR_POS_HI 0x0E 77 | #define VGA_CR_CUR_POS_LO 0x0F 78 | #define VGA_CR_VSYNC_START 0x10 79 | #define VGA_CR_VSYNC_END 0x11 80 | 81 | /* VGA Input Status Register 1 constants. */ 82 | #define VGA_STAT_VSYNC 0x08 83 | 84 | /*------------ End VGA Specific --------------*/ 85 | 86 | /*------------- bochs Specific ---------------*/ 87 | 88 | #define VBE_DISPI_BANK_ADDRESS 0xA0000 89 | #define VBE_DISPI_BANK_SIZE_KB 64 90 | 91 | #define VBE_DISPI_MAX_XRES 1024 92 | #define VBE_DISPI_MAX_YRES 768 93 | 94 | #define VBE_DISPI_IOPORT_INDEX 0x01CE 95 | #define VBE_DISPI_IOPORT_DATA 0x01CF 96 | 97 | #define VBE_DISPI_INDEX_ID 0x0 98 | #define VBE_DISPI_INDEX_XRES 0x1 99 | #define VBE_DISPI_INDEX_YRES 0x2 100 | #define VBE_DISPI_INDEX_BPP 0x3 101 | #define VBE_DISPI_INDEX_ENABLE 0x4 102 | #define VBE_DISPI_INDEX_BANK 0x5 103 | #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 104 | #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 105 | #define VBE_DISPI_INDEX_X_OFFSET 0x8 106 | #define VBE_DISPI_INDEX_Y_OFFSET 0x9 107 | #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa 108 | 109 | #define VBE_DISPI_ID0 0xB0C0 110 | #define VBE_DISPI_ID1 0xB0C1 111 | #define VBE_DISPI_ID2 0xB0C2 112 | #define VBE_DISPI_ID3 0xB0C3 113 | #define VBE_DISPI_ID4 0xB0C4 114 | #define VBE_DISPI_ID5 0xB0C5 115 | #define VBE_DISPI_ID6 0xB0C6 116 | 117 | #define VBE_DISPI_DISABLED 0x00 118 | #define VBE_DISPI_ENABLED 0x01 119 | #define VBE_DISPI_GETCAPS 0x02 120 | #define VBE_DISPI_8BIT_DAC 0x20 121 | #define VBE_DISPI_LFB_ENABLED 0x40 122 | #define VBE_DISPI_NOCLEARMEM 0x80 123 | 124 | /*------------ End bochs Specific -------------*/ 125 | 126 | 127 | typedef unsigned char v_byte; 128 | typedef unsigned short v_word; 129 | 130 | /* A structure describing the contents of VGA registers for a mode set. */ 131 | typedef struct { 132 | v_byte misc; /* Miscellaneous register. */ 133 | v_byte seq[5]; /* Sequencer registers. */ 134 | v_byte crtc[25]; /* CRTC registers. */ 135 | v_byte gctl[9]; /* Graphics controller registers. */ 136 | v_byte atr[21]; /* Attribute registers. */ 137 | } v_vgaregs; 138 | 139 | /* A structure fully describing a graphics or text mode. */ 140 | typedef struct { 141 | int mode_no; /* Internal mode number. */ 142 | int xres; /* Horizontal (X) resolution. */ 143 | int yres; /* Vertical (Y) resolution. */ 144 | int bpp; /* Bits per pixel. */ 145 | int ext; /* Non-zero for extended modes. */ 146 | v_vgaregs *vgaregs; /* Contents of VGA registers. */ 147 | } v_mode; 148 | -------------------------------------------------------------------------------- /dbgprint.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* Homegrown printf support. The C runtime printf() is hard to use without 26 | * dragging in much of the library, and much worse, the small model runtime . 27 | * can't operate with SS != DS. So we roll our own very simplified printf() . 28 | * subset, good enough for what we need. . 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | /* Backdoor logging I/O ports. */ 38 | #define INFO_PORT 0xe9 39 | 40 | #pragma code_seg( _INIT ); 41 | 42 | static void prt_ch( char c ) 43 | { 44 | outp( INFO_PORT, c ); 45 | } 46 | 47 | static void prt_u32( uint32_t val, int width ) 48 | { 49 | uint32_t uval; 50 | uint32_t base; 51 | char buf[16]; /* It's 12 digits max. */ 52 | int n = 0; 53 | 54 | uval = val; 55 | 56 | do { 57 | base = uval / 10; 58 | buf[n++] = uval - base * 10 + '0'; 59 | uval = base; 60 | } while( uval ); 61 | 62 | /* Pad with spaces. */ 63 | while( width > n ) { 64 | prt_ch( ' ' ); 65 | --width; 66 | } 67 | 68 | do { 69 | prt_ch( buf[--n] ); 70 | } while( n ); 71 | } 72 | 73 | static void prt_i32( int32_t val, int width ) 74 | { 75 | uint32_t uval; 76 | 77 | if( val < 0 ) { 78 | prt_ch( '-' ); 79 | uval = -val; 80 | if( width > 0 ) 81 | --width; 82 | } else { 83 | uval = val; 84 | } 85 | 86 | prt_u32( uval, width ); 87 | } 88 | 89 | static void prt_hex32( uint32_t val, int width, char hexa ) 90 | { 91 | char buf[8]; /* Enough for a dword. */ 92 | int n = 0; 93 | int nibble; 94 | 95 | do { 96 | nibble = val & 0xF; 97 | val >>= 4; 98 | buf[n++] = nibble + (nibble > 9 ? hexa - 10 : '0'); 99 | } while( val ); 100 | 101 | /* Pad with zeros. */ 102 | while( width > n ) { 103 | prt_ch( '0' ); 104 | --width; 105 | } 106 | 107 | do { 108 | prt_ch( buf[--n] ); 109 | } while( n ); 110 | } 111 | 112 | static void prt_str( const char __far *s ) 113 | { 114 | while( *s ) 115 | prt_ch( *s++ ); 116 | } 117 | 118 | void dbg_printf( const char *s, ... ) 119 | { 120 | char type_len; 121 | char conv; 122 | char hexa; 123 | int width; 124 | uint16_t word; 125 | uint32_t dword; 126 | va_list args; 127 | 128 | va_start( args, s ); 129 | 130 | /* Go until end of format string. */ 131 | while( *s ) { 132 | /* Is it a format specifier? */ 133 | if( *s == '%' ) { 134 | ++s; /* Eat the % sign. */ 135 | conv = 0; 136 | width = 0; 137 | type_len = 0; 138 | 139 | /* Process field width, if any. */ 140 | while( isdigit( *s ) ) { 141 | width *= 10; 142 | width += *s++ - '0'; 143 | } 144 | 145 | /* Process type length specifier, if any. */ 146 | switch( *s ) { 147 | case 'l': /* Long integers. */ 148 | case 'W': /* Far pointers. */ 149 | type_len = *s++; 150 | break; 151 | default: /* Do nothing. */ 152 | break; 153 | } 154 | 155 | /* Now check if a supported conversion is there. */ 156 | switch( *s ) { 157 | case 'c': 158 | case 'd': 159 | case 'u': 160 | case 'p': 161 | case 'P': 162 | case 's': 163 | case 'x': 164 | case 'X': 165 | conv = *s++; 166 | break; 167 | default: /* Do nothing. */ 168 | break; 169 | } 170 | 171 | if( conv ) { 172 | /* Time to start grabbing stuff off the stack. */ 173 | word = va_arg( args, uint16_t ); 174 | /* If argument is double wide, build a doubleword. */ 175 | if( type_len == 'l' || type_len == 'W' ) { 176 | dword = va_arg( args, uint16_t ); 177 | dword <<= 16; 178 | dword |= word; 179 | } 180 | if( conv == 'c' ) { 181 | prt_ch( word ); 182 | } else if( conv == 'd' ) { 183 | if( type_len == 'l' ) 184 | prt_i32( dword, width ); 185 | else 186 | prt_i32( (int16_t)word, width ); 187 | } else if( conv == 'u' ) { 188 | if( type_len == 'l' ) 189 | prt_u32( dword, width ); 190 | else 191 | prt_u32( word, width ); 192 | } else if( conv == 'p' || conv == 'P' ) { 193 | hexa = conv - 'P' + 'A'; 194 | if( type_len == 'W' ) { 195 | prt_hex32( dword >> 16, 4, hexa ); 196 | prt_ch( ':' ); 197 | prt_hex32( word, 4, hexa ); 198 | } else { 199 | prt_hex32( word, 4, hexa ); 200 | } 201 | } else if( conv == 's' ) { 202 | if( type_len == 'W' ) 203 | prt_str( (const char __far *)dword ); 204 | else 205 | prt_str( (const char *)word ); 206 | } else if( conv == 'x' || conv == 'X' ) { 207 | hexa = conv - 'X' + 'A'; 208 | if( type_len == 'l' ) { 209 | if( !width ) 210 | width = 8; 211 | prt_hex32( dword, width, hexa ); 212 | } else { 213 | if( !width ) 214 | width = 4; 215 | prt_hex32( word, width, hexa ); 216 | } 217 | } 218 | } else { 219 | /* Just print whatever is there. */ 220 | prt_ch( *s++ ); 221 | } 222 | } else { 223 | prt_ch( *s++ ); 224 | } 225 | } 226 | va_end( args ); 227 | } 228 | -------------------------------------------------------------------------------- /ddk/configmg.h: -------------------------------------------------------------------------------- 1 | 2 | /* Definitions for the configuration manager. */ 3 | 4 | typedef DWORD CONFIGRET; /* Standardized return value. */ 5 | 6 | typedef DWORD LOG_CONF; /* Logical configuration. */ 7 | typedef LOG_CONF FAR *PLOG_CONF; /* Far pointer to logical configuration. */ 8 | 9 | typedef DWORD RES_DES; /* Resource descriptor. */ 10 | typedef RES_DES FAR *PRES_DES; /* Far pointer to resource descriptor. */ 11 | 12 | typedef DWORD DEVNODE; /* Devnode. */ 13 | 14 | typedef DWORD ULONG; 15 | 16 | typedef void FAR *PFARVOID; 17 | 18 | typedef ULONG RESOURCEID; /* Resource type ID. */ 19 | typedef RESOURCEID FAR *PRESOURCEID; /* Far pointer to resource type ID. */ 20 | 21 | typedef struct { 22 | WORD MD_Count; 23 | WORD MD_Type; 24 | ULONG MD_Alloc_Base; 25 | ULONG MD_Alloc_End; 26 | WORD MD_Flags; 27 | WORD MD_Reserved; 28 | } MEM_DES, *PMEM_DES; 29 | 30 | #define CR_SUCCESS 0 31 | #define ALLOC_LOG_CONF 2 32 | #define ResType_Mem 1 33 | -------------------------------------------------------------------------------- /ddk/dibeng.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | LIBRARY DIBENG 3 | DIB_BitBlt @1 4 | DIB_ColorInfo @2 5 | DIB_Control @3 6 | DIB_Disable @4 7 | DIB_Enable @5 8 | DIB_EnumDFonts @6 9 | DIB_EnumObj @7 10 | DIB_Output @8 11 | DIB_Pixel @9 12 | DIB_RealizeObject @10 13 | DIB_StrBlt @11 14 | DIB_ScanLR @12 15 | DIB_DeviceMode @13 16 | DIB_ExtTextOut @14 17 | DIB_GetCharWidth @15 18 | DIB_DeviceBitmap @16 19 | DIB_FastBorder @17 20 | DIB_SetAttribute @18 21 | DIB_DibBlt @19 22 | DIB_CreateDIBitmap @20 23 | DIB_DibToDevice @21 24 | DIB_SetPalette @22 25 | DIB_GetPalette @23 26 | DIB_SetPaletteTranslate @24 27 | DIB_GetPaletteTranslate @25 28 | DIB_UpdateColors @26 29 | DIB_StretchBlt @27 30 | DIB_StretchDIBits @28 31 | DIB_SelectBitmap @29 32 | DIB_BitmapBits @30 33 | DIB_Inquire @101 34 | DIB_SetCursorExt @102 35 | DIB_MoveCursorExt @103 36 | DIB_CheckCursorExt @104 37 | DIB_BeginAccess @105 38 | DIB_EndAccess @106 39 | CreateDIBPDevice @300 40 | DIB_RealizeObjectExt @400 41 | DIB_DibBltExt @401 42 | DIB_EnumObjExt @402 43 | DIB_ExtTextOutExt @403 44 | DIB_UpdateColorsExt @404 45 | DIB_SetPaletteExt @405 46 | DIB_GetPaletteExt @406 47 | DIB_SetPaletteTranslateExt @407 48 | DIB_GetPaletteTranslateExt @408 49 | 50 | -------------------------------------------------------------------------------- /ddk/dibeng.h: -------------------------------------------------------------------------------- 1 | /* DIB Engine interface. */ 2 | 3 | #define BRUSHSIZE 8 4 | #define VER_DIBENG 0x400 5 | #define TYPE_DIBENG 0x5250 /* 'RP' */ 6 | 7 | #define deCursorExclude deBeginAccess 8 | #define deCursorUnexclude deEndAccess 9 | 10 | /* DIB Engine PDevice structure. The deType field will be 'DI' when GDI 11 | * calls the Engine; deType will be null or a selector if a minidriver is 12 | * calls the DIB Engine. 13 | */ 14 | typedef struct { 15 | WORD deType; /* TYPE_DIBENG or zero. */ 16 | WORD deWidth; /* DIB width in pixels. */ 17 | WORD deHeight; /* DIB height in pixels. */ 18 | WORD deWidthBytes; /* Scanline length in bytes. */ 19 | BYTE dePlanes; /* Number of bit planes. */ 20 | BYTE deBitsPixel; /* Number of bits per pixel. */ 21 | DWORD deReserved1; /* Not used. */ 22 | DWORD deDeltaScan; /* Scanline delta, can be negative.*/ 23 | LPBYTE delpPDevice; /* Associated PDevice pointer. */ 24 | DWORD deBitsOffset; /* 48-bit pointer to */ 25 | WORD deBitsSelector; /* DIB bits storage. */ 26 | WORD deFlags; /* More flags. */ 27 | WORD deVersion; /* Major/minor (0400h = 4.0). */ 28 | LPBITMAPINFO deBitmapInfo; /* Bitmapinfo header pointer. */ 29 | void (WINAPI *deBeginAccess)(); /* Surface access begin callback. */ 30 | void (WINAPI *deEndAccess)(); /* Surface access end callback. */ 31 | DWORD deDriverReserved; /* Reserved for minidrivers. */ 32 | } DIBENGINE, FAR *LPDIBENGINE; 33 | 34 | /* DIBEngine.deFlags */ 35 | #define MINIDRIVER 0x0001 /* Mini display driver. */ 36 | #define PALETTIZED 0x0002 /* Has a palette. */ 37 | #define SELECTEDDIB 0x0004 /* DIB Section. */ 38 | #define OFFSCREEN 0x0008 /* Offscreen surface in VRAM. */ 39 | #define BUSY 0x0010 /* Busy. */ 40 | #define NOT_FRAMEBUFFER 0x0020 /* No FB access (like 8514/A). */ 41 | #define FIVE6FIVE 0x0040 /* 5-6-5 16bpp mode. */ 42 | #define NON64KBANK 0x0080 /* Bank size != 64K. */ 43 | #define VRAM 0x8000 /* Have VRAM access. */ 44 | #define BANKEDVRAM 0x4000 /* VFlatD simulating LFB. */ 45 | #define BANKEDSCAN 0x2000 /* VFlatD with scanlines crossing banks. */ 46 | #define PALETTE_XLAT 0x1000 /* Bkgnd palette translation. */ 47 | #define VGADITHER 0x0800 /* Dither to VGA colors. */ 48 | #define CTCHANGE 0x0400 /* Color table changed/ */ 49 | #define DITHER256 0x0200 /* Dither to 256 colors. */ 50 | 51 | #define BUSY_BIT 4 /* Number of bit to test for busy. */ 52 | 53 | /* DIB_Brush??.dp??BrushFlags */ 54 | #define COLORSOLID 0x01 /* Color part solid. */ 55 | #define MONOSOLID 0x02 /* Mono part solid. */ 56 | #define PATTERNMONO 0x04 /* Brush originated from mono bitmap. */ 57 | #define MONOVALID 0x08 /* Mono part valid. */ 58 | #define MASKVALID 0x10 /* Mask valid. */ 59 | #define PRIVATEDATA 0x20 /* Vendor defined bit. */ 60 | 61 | /* Fake typedefs to avoid conflicts between windows.h and gdidefs.h. */ 62 | typedef LPVOID LPPDEVICE; 63 | typedef LPVOID LPPPEN; 64 | typedef LPVOID LPPBRUSH; 65 | typedef LPVOID LPBRUSH; 66 | typedef LPVOID LPPCOLOR; 67 | typedef LPINT LPSHORT; 68 | 69 | /* DIB Engine functions. */ 70 | /* NB: Based on DDK documentation which may be inaccurate. */ 71 | extern void WINAPI DIB_Control( void ); 72 | extern WORD WINAPI DIB_EnumObjExt( LPPDEVICE lpDestDev, WORD wStyle, FARPROC lpCallbackFunc, 73 | LPVOID lpClientData, LPPDEVICE lpDisplayDev ); 74 | extern VOID WINAPI DIB_CheckCursorExt( LPPDEVICE lpDevice ); 75 | extern WORD WINAPI DIB_Output( LPPDEVICE lpDestDev, WORD wStyle, WORD wCount, 76 | LPPOINT lpPoints, LPPPEN lpPPen, LPPBRUSH lpPBrush, 77 | LPDRAWMODE lpDrawMode, LPRECT lpClipRect); 78 | extern DWORD WINAPI DIB_RealizeObject( LPPDEVICE lpDestDev, WORD wStyle, LPVOID lpInObj, 79 | LPVOID lpOutObj, LPTEXTXFORM lpTextXForm ); 80 | extern WORD WINAPI DIB_RealizeObjectExt( LPPDEVICE lpDestDev, WORD wStyle, LPVOID lpInObj, 81 | LPVOID lpOutObj, LPTEXTXFORM lpTextXForm, 82 | LPPDEVICE lpDisplayDev ); 83 | extern BOOL WINAPI DIB_BitBlt( LPPDEVICE lpDestDev, WORD wDestX, WORD wDestY, LPPDEVICE lpSrcDev, 84 | WORD wSrcX, WORD wSrcY, WORD wXext, WORD wYext, DWORD dwRop3, 85 | LPBRUSH lpPBrush, LPDRAWMODE lpDrawMode ); 86 | extern BOOL WINAPI DIB_BitmapBits( LPPDEVICE lpDevice, DWORD fFlags, DWORD dwCount, LPSTR lpBits ); 87 | extern VOID WINAPI DIB_DibBlt( LPPDEVICE lpBitmap, WORD fGet, WORD iStart, WORD cScans, LPSTR lpDIBits, 88 | LPBITMAPINFO lpBitmapInfo, LPDRAWMODE lpDrawMode, LPINT lpTranslate ); 89 | extern WORD WINAPI DIB_DibToDevice( LPPDEVICE lpDestDev, WORD X, WORD Y, WORD iScan, WORD cScans, 90 | LPRECT lpClipRect, LPDRAWMODE lpDrawMode, LPSTR lpDIBits, 91 | LPBITMAPINFO lpBitmapInfo, LPINT lpTranslate ); 92 | extern DWORD WINAPI DIB_Pixel( LPPDEVICE lpDestDev, WORD X, WORD Y, DWORD dwPhysColor, LPDRAWMODE lpDrawMode ); 93 | extern WORD WINAPI DIB_ScanLR( LPPDEVICE lpDestDev, WORD X, WORD Y, DWORD dwPhysColor, WORD wStyle ); 94 | extern BOOL WINAPI DIB_SelectBitmap(LPPDEVICE lpDevice, LPBITMAP lpPrevBitmap, LPBITMAP lpBitmap, DWORD fFlags ); 95 | extern BOOL WINAPI DIB_StretchBlt( LPPDEVICE lpDestDev, WORD wDestX, WORD wDestY, WORD wDestWidth, 96 | WORD wDestHeight, LPPDEVICE lpSrcDev, WORD wSrcX, WORD wSrcY, 97 | WORD wSrcWidth, WORD wtSrcHeight, DWORD dwRop3, LPBRUSH lpPBrush, 98 | LPDRAWMODE lpDrawMode, LPRECT lpClipRect ); 99 | extern BOOL WINAPI DIB_StretchDIBits( LPPDEVICE lpDestDev, WORD fGet, WORD wDestX, WORD wDestY, WORD wDestWidth, 100 | WORD wDestHeight, WORD wSrcX, WORD wSrcY, WORD wSrcWidth, WORD wSrcHeight, 101 | VOID *lpBits, LPBITMAPINFO lpInfo, LPINT lpTranslate, DWORD dwRop3, 102 | LPBRUSH lpPBrush, LPDRAWMODE lpDrawMode, LPRECT lpClipRect ); 103 | extern DWORD WINAPI DIB_ExtTextOut( LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg, LPRECT lpClipRect, 104 | LPSTR lpString, int wCount, LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, 105 | LPTEXTXFORM lpTextXForm, LPSHORT lpCharWidths, LPRECT lpOpaqueRect, WORD wOptions ); 106 | extern DWORD WINAPI DIB_ExtTextOutExt( LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg, LPRECT lpClipRect, 107 | LPSTR lpString, WORD wCount, LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, 108 | LPTEXTXFORM lpTextXForm, LPSHORT lpCharWidths, LPRECT lpOpaqueRect, 109 | WORD wOptions, LPVOID *lpDrawTextBitmap, LPVOID *lpDrawRect ); 110 | extern WORD WINAPI DIB_GetCharWidth( LPPDEVICE lpDestDev, LPWORD lpBuffer, WORD wFirstChar, WORD wLastChar, 111 | LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, LPTEXTXFORM lpFontTrans ); 112 | 113 | extern DWORD WINAPI DIB_StrBlt( LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg, LPRECT lpClipRect, LPSTR lpString, 114 | WORD wCount, LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, LPTEXTXFORM lpTextXForm ); 115 | extern DWORD WINAPI DIB_ColorInfo( LPPDEVICE lpDestDev, DWORD dwColorin, LPPCOLOR lpPColor ); 116 | extern VOID WINAPI DIB_GetPalette( WORD nStartIndex, WORD nNumEntries, RGBQUAD lpPalette ); 117 | extern VOID WINAPI DIB_GetPaletteExt( WORD nStartIndex, WORD nNumEntries, RGBQUAD lpPalette, LPPDEVICE lpDIBEngine ); 118 | extern VOID WINAPI DIB_GetPaletteTranslate( LPWORD lpIndexes ); 119 | extern VOID WINAPI DIB_GetPaletteTranslateExt( LPWORD lpIndexes, LPPDEVICE lpDIBEngine ); 120 | extern VOID WINAPI DIB_SetPalette( WORD nStartIndex, WORD nNumEntries, LPVOID lpPalette ); 121 | extern VOID WINAPI DIB_SetPaletteExt( WORD nStartIndex, WORD nNumEntries, LPVOID lpPalette, LPPDEVICE lpDIBEngine ); 122 | extern VOID WINAPI DIB_SetPaletteTranslate( LPWORD lpIndexes ); 123 | extern VOID WINAPI DIB_SetPaletteTranslateExt( LPWORD lpIndexes, LPPDEVICE lpDIBEngine ); 124 | extern VOID WINAPI DIB_UpdateColorsExt( WORD wStartX, WORD wStart, WORD wExtX, WORD wExtY, 125 | LPWORD lpTranslate, LPPDEVICE lpDIBEngine ); 126 | extern VOID WINAPI DIB_SetCursorExt( LPPDEVICE lpDevice, LPVOID lpCursorShape ); 127 | extern VOID WINAPI DIB_CheckCursorExt( LPPDEVICE lpDevice ); 128 | extern VOID WINAPI DIB_MoveCursorExt( LPPDEVICE lpDevice, WORD absX, WORD absY ); 129 | extern VOID WINAPI DIB_Inquire( LPVOID lpCursorInfo ); 130 | extern VOID WINAPI DIB_BeginAccess( LPPDEVICE lpDevice, WORD wLeft, WORD wTop, WORD wRight, WORD wBottom, WORD wFlags ); 131 | extern VOID WINAPI DIB_EndAccess( LPPDEVICE lpDevice, WORD wFlags ); 132 | extern WORD WINAPI DIB_CreateDIBitmap( void ); 133 | extern WORD WINAPI DIB_DeviceBitmap( LPPDEVICE lpDestDev, WORD wCommand, LPBITMAP lpBitmap, LPSTR lpBits ); 134 | extern WORD WINAPI DIB_DeviceMode( HWND hWnd, HINSTANCE hInst, LPVOID lpDeviceType, LPVOID lpOutputFile ); 135 | extern UINT WINAPI DIB_Enable( LPPDEVICE lpDevice, WORD wStyle, LPSTR lpDeviceType, LPSTR lpOutputFile, LPVOID lpStuff ); 136 | extern VOID WINAPI DIB_Disable( LPPDEVICE lpDestDev ); 137 | extern WORD WINAPI DIB_EnumDFonts( LPPDEVICE lpDestDev, LPSTR lpFaceName, FARPROC lpCallbackFunc, LPVOID lpClientData ); 138 | extern WORD WINAPI DIB_SetAttribute( LPPDEVICE lpDevice, WORD wStateNum, WORD wIndex, DWORD dwAttribute ); 139 | 140 | 141 | /* WARNING: CreateDIBPDevice returns the result in EAX, not DX:AX! */ 142 | extern DWORD WINAPI CreateDIBPDevice( LPBITMAPINFO lpInfo, LPPDEVICE lpDevice, LPVOID lpBits, WORD wFlags ); 143 | 144 | #define FB_ACCESS 0x0001 145 | #define CURSOREXCLUDE 0x0008 146 | 147 | #define GREY_BIT 0x40 /* Physical color MSB. */ 148 | 149 | /* DIB Engine Color Table entry. A lot like RGBQUAD. */ 150 | typedef struct { 151 | BYTE dceBlue; 152 | BYTE dceGreen; 153 | BYTE dceRed; 154 | BYTE dceFlags; 155 | } DIBColorEntry; 156 | 157 | /* DIBColorEntry.dceFlags */ 158 | #define NONSTATIC 0x80 159 | #define MAPTOWHITE 0x01 160 | 161 | 162 | /* DIB Engine Physical Object Definitions */ 163 | 164 | typedef struct { 165 | WORD dpPenStyle; 166 | BYTE dpPenFlags; 167 | BYTE dpPenBpp; 168 | DWORD dpPenMono; 169 | DWORD dpPenColor; 170 | } DIB_Pen; 171 | 172 | typedef struct { 173 | BYTE dp1BrushFlags; /* Accelerator for solids */ 174 | BYTE dp1BrushBpp; /* Brush Bits per pixel format */ 175 | WORD dp1BrushStyle; /* Style of the brush */ 176 | DWORD dp1FgColor; /* Physical fg color */ 177 | WORD dp1Hatch; /* Hatching style */ 178 | DWORD dp1BgColor; /* Physical bg color */ 179 | BYTE dp1BrushMono[BRUSHSIZE*4]; /* Mono portion */ 180 | BYTE dp1BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ 181 | BYTE dp1BrushBits[BRUSHSIZE*4]; /* 8 rows, 8 columns of 1 bit/pixel */ 182 | } DIB_Brush1; 183 | 184 | typedef struct { 185 | BYTE dp4BrushFlags; /* Accelerator for solids */ 186 | BYTE dp4BrushBpp; /* Brush Bits per pixel format */ 187 | WORD dp4BrushStyle; /* Style of the brush */ 188 | DWORD dp4FgColor; /* Physical fg color */ 189 | WORD dp4Hatch; /* Hatching style */ 190 | DWORD dp4BgColor; /* Physical bg color */ 191 | BYTE dp4BrushMono[BRUSHSIZE*4]; /* Mono portion */ 192 | BYTE dp4BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ 193 | BYTE dp4BrushBits[BRUSHSIZE*4]; /* 8 rows, 8 columns of 4 bit/pixel */ 194 | } DIB_Brush4; 195 | 196 | typedef struct { 197 | BYTE dp8BrushFlags; /* Accelerator for solids */ 198 | BYTE dp8BrushBpp; /* Brush Bits per pixel format */ 199 | WORD dp8BrushStyle; /* Style of the brush */ 200 | DWORD dp8FgColor; /* Physical fg color */ 201 | WORD dp8Hatch; /* Hatching style */ 202 | DWORD dp8BgColor; /* Physical bg color */ 203 | BYTE dp8BrushMono[BRUSHSIZE*4]; /* Mono portion */ 204 | BYTE dp8BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ 205 | BYTE dp8BrushBits[BRUSHSIZE*8]; /* 8 rows,8 columns of 8 bit/pixel */ 206 | } DIB_Brush8; 207 | 208 | typedef struct { 209 | BYTE dp16BrushFlags; /* Accelerator for solids */ 210 | BYTE dp16BrushBpp; /* Brush Bits per pixel format */ 211 | WORD dp16BrushStyle; /* Style of the brush */ 212 | DWORD dp16FgColor; /* Physical fg color */ 213 | WORD dp16Hatch; /* Hatching style */ 214 | DWORD dp16BgColor; /* Physical bg color */ 215 | BYTE dp16BrushMono[BRUSHSIZE*4]; /* Mono portion */ 216 | BYTE dp16BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ 217 | BYTE dp16BrushBits[BRUSHSIZE*16];/* 8 rows,8 columns of 16 bit/pixel */ 218 | } DIB_Brush16; 219 | 220 | typedef struct { 221 | BYTE dp24BrushFlags; /* Accelerator for solids */ 222 | BYTE dp24BrushBpp; /* Brush Bits per pixel format */ 223 | WORD dp24BrushStyle; /* Style of the brush */ 224 | DWORD dp24FgColor; /* Physical fg color */ 225 | WORD dp24Hatch; /* Hatching style */ 226 | DWORD dp24BgColor; /* Physical bg color */ 227 | BYTE dp24BrushMono[BRUSHSIZE*4]; /* Mono portion */ 228 | BYTE dp24BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ 229 | BYTE dp24BrushBits[BRUSHSIZE*24];/* 8 rows,8 columns of 24 bit/pixel */ 230 | } DIB_Brush24; 231 | 232 | typedef struct { 233 | BYTE dp32BrushFlags; /* Accelerator for solids */ 234 | BYTE dp32BrushBpp; /* Brush Bits per pixel format */ 235 | WORD dp32BrushStyle; /* Style of the brush */ 236 | DWORD dp32FgColor; /* Physical fg color */ 237 | WORD dp32Hatch; /* Hatching style */ 238 | DWORD dp32BgColor; /* Physical bg color */ 239 | BYTE dp32BrushMono[BRUSHSIZE*4]; /* Mono portion */ 240 | BYTE dp32BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ 241 | BYTE dp32BrushBits[BRUSHSIZE*32];/* 8 rows,8 columns of 32 bit/pixel */ 242 | } DIB_Brush32; 243 | -------------------------------------------------------------------------------- /ddk/dibeng.lbc: -------------------------------------------------------------------------------- 1 | ++DIB_BitBlt.DIBENG.1 2 | ++DIB_ColorInfo.DIBENG.2 3 | ++DIB_Control.DIBENG.3 4 | ++DIB_Disable.DIBENG.4 5 | ++DIB_Enable.DIBENG.5 6 | ++DIB_EnumDFonts.DIBENG.6 7 | ++DIB_EnumObj.DIBENG.7 8 | ++DIB_Output.DIBENG.8 9 | ++DIB_Pixel.DIBENG.9 10 | ++DIB_RealizeObject.DIBENG.10 11 | ++DIB_StrBlt.DIBENG.11 12 | ++DIB_ScanLR.DIBENG.12 13 | ++DIB_DeviceMode.DIBENG.13 14 | ++DIB_ExtTextOut.DIBENG.14 15 | ++DIB_GetCharWidth.DIBENG.15 16 | ++DIB_DeviceBitmap.DIBENG.16 17 | ++DIB_FastBorder.DIBENG.17 18 | ++DIB_SetAttribute.DIBENG.18 19 | ++DIB_DibBlt.DIBENG.19 20 | ++DIB_CreateDIBitmap.DIBENG.20 21 | ++DIB_DibToDevice.DIBENG.21 22 | ++DIB_SetPalette.DIBENG.22 23 | ++DIB_GetPalette.DIBENG.23 24 | ++DIB_SetPaletteTranslate.DIBENG.24 25 | ++DIB_GetPaletteTranslate.DIBENG.25 26 | ++DIB_UpdateColors.DIBENG.26 27 | ++DIB_StretchBlt.DIBENG.27 28 | ++DIB_StretchDIBits.DIBENG.28 29 | ++DIB_SelectBitmap.DIBENG.29 30 | ++DIB_BitmapBits.DIBENG.30 31 | ++DIB_Inquire.DIBENG.101 32 | ++DIB_SetCursorExt.DIBENG.102 33 | ++DIB_MoveCursorExt.DIBENG.103 34 | ++DIB_CheckCursorExt.DIBENG.104 35 | ++DIB_BeginAccess.DIBENG.105 36 | ++DIB_EndAccess.DIBENG.106 37 | ++CreateDIBPDevice.DIBENG.300 38 | ++DIB_RealizeObjectExt.DIBENG.400 39 | ++DIB_DibBltExt.DIBENG.401 40 | ++DIB_EnumObjExt.DIBENG.402 41 | ++DIB_ExtTextOutExt.DIBENG.403 42 | ++DIB_UpdateColorsExt.DIBENG.404 43 | ++DIB_SetPaletteExt.DIBENG.405 44 | ++DIB_GetPaletteExt.DIBENG.406 45 | ++DIB_SetPaletteTranslateExt.DIBENG.407 46 | ++DIB_GetPaletteTranslateExt.DIBENG.408 47 | -------------------------------------------------------------------------------- /ddk/gdidefs.h: -------------------------------------------------------------------------------- 1 | 2 | /* Definitions for GDI drivers. */ 3 | 4 | /* Physical Bitmap structure. */ 5 | typedef struct { 6 | short int bmType; 7 | unsigned short int bmWidth; 8 | unsigned short int bmHeight; 9 | unsigned short int bmWidthBytes; 10 | BYTE bmPlanes; 11 | BYTE bmBitsPixel; 12 | BYTE FAR *bmBits; 13 | unsigned long int bmWidthPlanes; 14 | BYTE FAR *bmlpPDevice; 15 | unsigned short int bmSegmentIndex; 16 | unsigned short int bmScanSegment; 17 | unsigned short int bmFillBytes; 18 | unsigned short int futureUse4; 19 | unsigned short int futureUse5; 20 | } BITMAP; 21 | 22 | /* DIB structs also defined in windows.h. */ 23 | typedef struct { 24 | DWORD bcSize; 25 | WORD bcWidth; 26 | WORD bcHeight; 27 | WORD bcPlanes; 28 | WORD bcBitCount; 29 | } BITMAPCOREHEADER; 30 | typedef BITMAPCOREHEADER FAR *LPBITMAPCOREHEADER; 31 | typedef BITMAPCOREHEADER *PBITMAPCOREHEADER; 32 | 33 | typedef struct { 34 | DWORD biSize; 35 | DWORD biWidth; 36 | DWORD biHeight; 37 | WORD biPlanes; 38 | WORD biBitCount; 39 | DWORD biCompression; 40 | DWORD biSizeImage; 41 | DWORD biXPelsPerMeter; 42 | DWORD biYPelsPerMeter; 43 | DWORD biClrUsed; 44 | DWORD biClrImportant; 45 | } BITMAPINFOHEADER; 46 | 47 | typedef BITMAPINFOHEADER FAR *LPBITMAPINFOHEADER; 48 | typedef BITMAPINFOHEADER *PBITMAPINFOHEADER; 49 | 50 | typedef struct { 51 | BYTE rgbtBlue; 52 | BYTE rgbtGreen; 53 | BYTE rgbtRed; 54 | } RGBTRIPLE; 55 | 56 | typedef struct { 57 | BYTE rgbBlue; 58 | BYTE rgbGreen; 59 | BYTE rgbRed; 60 | BYTE rgbReserved; 61 | } RGBQUAD; 62 | 63 | /* ICM Color Definitions */ 64 | typedef long FXPT16DOT16, FAR *LPFXPT16DOT16; 65 | typedef long FXPT2DOT30, FAR *LPFXPT2DOT30; 66 | 67 | typedef struct tagCIEXYZ 68 | { 69 | FXPT2DOT30 ciexyzX; 70 | FXPT2DOT30 ciexyzY; 71 | FXPT2DOT30 ciexyzZ; 72 | } CIEXYZ; 73 | typedef CIEXYZ FAR *LPCIEXYZ; 74 | 75 | typedef struct tagICEXYZTRIPLE 76 | { 77 | CIEXYZ ciexyzRed; 78 | CIEXYZ ciexyzGreen; 79 | CIEXYZ ciexyzBlue; 80 | } CIEXYZTRIPLE; 81 | typedef CIEXYZTRIPLE FAR *LPCIEXYZTRIPLE; 82 | 83 | typedef struct { 84 | BITMAPCOREHEADER bmciHeader; 85 | RGBQUAD bmciColors[1]; 86 | } BITMAPCOREINFO; 87 | 88 | typedef BITMAPCOREINFO FAR *LPBITMAPCOREINFO; 89 | typedef BITMAPCOREINFO *PBITMAPCOREINFO; 90 | 91 | typedef struct { 92 | BITMAPINFOHEADER bmiHeader; 93 | RGBQUAD bmiColors[1]; 94 | } BITMAPINFO; 95 | 96 | typedef BITMAPINFO FAR *LPBITMAPINFO; 97 | typedef BITMAPINFO *PBITMAPINFO; 98 | 99 | typedef struct { 100 | DWORD bV4Size; 101 | LONG bV4Width; 102 | LONG bV4Height; 103 | WORD bV4Planes; 104 | WORD bV4BitCount; 105 | DWORD bV4V4Compression; 106 | DWORD bV4SizeImage; 107 | LONG bV4XPelsPerMeter; 108 | LONG bV4YPelsPerMeter; 109 | DWORD bV4ClrUsed; 110 | DWORD bV4ClrImportant; 111 | DWORD bV4RedMask; 112 | DWORD bV4GreenMask; 113 | DWORD bV4BlueMask; 114 | DWORD bV4AlphaMask; 115 | DWORD bV4CSType; 116 | CIEXYZTRIPLE bV4Endpoints; 117 | DWORD bV4GammaRed; 118 | DWORD bV4GammaGreen; 119 | DWORD bV4GammaBlue; 120 | } BITMAPV4HEADER, FAR *LPBITMAPV4HEADER, *PBITMAPV4HEADER; 121 | 122 | typedef struct { 123 | BITMAPV4HEADER bmv4Header; 124 | RGBQUAD bmv4Colors[1]; 125 | } BITMAPV4INFO; 126 | 127 | typedef BITMAPV4INFO FAR *LPBITMAPV4INFO; 128 | typedef BITMAPV4INFO *PBITMAPV4INFO; 129 | 130 | /* currently, if the low byte of biCompression is non zero, 131 | * it must be one of following */ 132 | 133 | #define BI_RGB 0x00 134 | #define BI_RLE8 0x01 135 | #define BI_RLE4 0x02 136 | #define BI_BITFIELDS 0x03 137 | 138 | #define BITMAP_SELECTED 0x01 139 | #define BITMAP_64K 0x01 140 | 141 | #define DIBSIGNATURE 0x4944 142 | 143 | /* Point types are optional. */ 144 | #ifndef NOPTRC 145 | 146 | typedef struct { 147 | short int xcoord; 148 | short int ycoord; 149 | } PTTYPE; 150 | typedef PTTYPE *PPOINT; 151 | typedef PTTYPE FAR *LPPOINT; 152 | 153 | #define POINT PTTYPE 154 | 155 | typedef struct { 156 | short int left; 157 | short int top; 158 | short int right; 159 | short int bottom; 160 | } RECT; 161 | typedef RECT *PRECT; 162 | 163 | #endif 164 | 165 | typedef struct { 166 | PTTYPE min; 167 | PTTYPE ext; 168 | } BOXTYPE; 169 | typedef RECT FAR *LPRECT; 170 | 171 | /* Object definitions used by GDI support routines written in C */ 172 | 173 | #define OBJ_PEN 1 174 | #define OBJ_BRUSH 2 175 | #define OBJ_FONT 3 176 | 177 | typedef struct { 178 | unsigned short int lbStyle; 179 | unsigned long int lbColor; 180 | unsigned short int lbHatch; 181 | unsigned long int lbBkColor; 182 | unsigned long int lbhcmXform; 183 | } LOGBRUSH; 184 | 185 | #define lbPattern lbColor 186 | 187 | /* Brush Style definitions. */ 188 | #define BS_SOLID 0 189 | #define BS_HOLLOW 1 190 | #define BS_HATCHED 2 191 | #define BS_PATTERN 3 192 | 193 | #define MaxBrushStyle 3 194 | 195 | /* Hatch Style definitions. */ 196 | #define HS_HORIZONTAL 0 /* ----- */ 197 | #define HS_VERTICAL 1 /* ||||| */ 198 | #define HS_FDIAGONAL 2 /* ///// */ 199 | #define HS_BDIAGONAL 3 /* \\\\\ */ 200 | #define HS_CROSS 4 /* +++++ */ 201 | #define HS_DIAGCROSS 5 /* xxxxx */ 202 | 203 | #define MaxHatchStyle 5 204 | 205 | 206 | /* Logical Pen Structure. */ 207 | typedef struct { 208 | unsigned short int lopnStyle; 209 | PTTYPE lopnWidth; 210 | unsigned long int lopnColor; 211 | unsigned short int lopnStyle2; 212 | unsigned long int lopnhcmXform; 213 | } LOGPEN; 214 | 215 | /* Line Style definitions. */ 216 | #define LS_SOLID 0 217 | #define LS_DASHED 1 218 | #define LS_DOTTED 2 219 | #define LS_DOTDASHED 3 220 | #define LS_DASHDOTDOT 4 221 | #define LS_NOLINE 5 222 | #define LS_INSIDEFRAME 6 223 | #define MaxLineStyle LS_NOLINE 224 | 225 | #define LS_ENDCAP_FLAT 0x01 226 | #define LS_ENDCAP_ROUND 0x02 227 | #define LS_ENDCAP_SQUARE 0x04 228 | #define LS_JOIN_BEVEL 0x08 229 | #define LS_JOIN_MITER 0x10 230 | #define LS_JOIN_ROUND 0x20 231 | 232 | 233 | /* The size to allocate for the lfFaceName field in the logical font. */ 234 | #ifndef LF_FACESIZE 235 | #define LF_FACESIZE 32 236 | #endif 237 | 238 | /* Various constants for defining a logical font. */ 239 | #define OUT_DEFAULT_PRECIS 0 240 | #define OUT_STRING_PRECIS 1 241 | #define OUT_CHARACTER_PRECIS 2 242 | #define OUT_STROKE_PRECIS 3 243 | #define OUT_TT_PRECIS 4 244 | #define OUT_DEVICE_PRECIS 5 245 | #define OUT_RASTER_PRECIS 6 246 | #define OUT_TT_ONLY_PRECIS 7 247 | 248 | #define CLIP_DEFAULT_PRECIS 0 249 | #define CLIP_CHARACTER_PRECIS 1 250 | #define CLIP_STROKE_PRECIS 2 251 | #define CLIP_MASK 0x0F 252 | #define CLIP_LH_ANGLES 0x10 253 | #define CLIP_TT_ALWAYS 0x20 254 | #define CLIP_EMBEDDED 0x80 255 | 256 | #define DEFAULT_QUALITY 0 257 | #define DRAFT_QUALITY 1 258 | #define PROOF_QUALITY 2 259 | 260 | #define DEFAULT_PITCH 0 261 | #define FIXED_PITCH 1 262 | #define VARIABLE_PITCH 2 263 | 264 | #define ANSI_CHARSET 0 265 | #define DEFAULT_CHARSET 1 266 | #define SYMBOL_CHARSET 2 267 | #define MAC_CHARSET 77 268 | #define SHIFTJIS_CHARSET 128 269 | #define HANGEUL_CHARSET 129 270 | #define CHINESEBIG5_CHARSET 136 271 | #define OEM_CHARSET 255 272 | 273 | 274 | /* GDI font families. */ 275 | #define FF_DONTCARE (0<<4) /* Don't care or don't know. */ 276 | #define FF_ROMAN (1<<4) /* Variable stroke width, serifed. */ 277 | /* Times Roman, Century Schoolbook, etc.*/ 278 | #define FF_SWISS (2<<4) /* Variable stroke width, sans-serifed. */ 279 | /* Helvetica, Swiss, etc. */ 280 | #define FF_MODERN (3<<4) /* Constant stroke width, serifed or sans-serifed. */ 281 | /* Pica, Elite, Courier, etc. */ 282 | #define FF_SCRIPT (4<<4) /* Cursive, etc. */ 283 | #define FF_DECORATIVE (5<<4) /* Old English, etc. */ 284 | 285 | 286 | /* Font weights lightest to heaviest. */ 287 | #define FW_DONTCARE 0 288 | #define FW_THIN 100 289 | #define FW_EXTRALIGHT 200 290 | #define FW_LIGHT 300 291 | #define FW_NORMAL 400 292 | #define FW_MEDIUM 500 293 | #define FW_SEMIBOLD 600 294 | #define FW_BOLD 700 295 | #define FW_EXTRABOLD 800 296 | #define FW_HEAVY 900 297 | 298 | #define FW_ULTRALIGHT FW_EXTRALIGHT 299 | #define FW_REGULAR FW_NORMAL 300 | #define FW_DEMIBOLD FW_SEMIBOLD 301 | #define FW_ULTRABOLD FW_EXTRABOLD 302 | #define FW_BLACK FW_HEAVY 303 | 304 | /* Enumeration font types. */ 305 | #define RASTER_FONTTYPE 1 306 | #define DEVICE_FONTTYPE 2 307 | 308 | 309 | 310 | typedef struct { 311 | short int lfHeight; 312 | short int lfWidth; 313 | short int lfEscapement; 314 | short int lfOrientation; 315 | short int lfWeight; 316 | BYTE lfItalic; 317 | BYTE lfUnderline; 318 | BYTE lfStrikeOut; 319 | BYTE lfCharSet; 320 | BYTE lfOutPrecision; 321 | BYTE lfClipPrecision; 322 | BYTE lfQuality; 323 | BYTE lfPitchAndFamily; 324 | BYTE lfFaceName[LF_FACESIZE]; 325 | } LOGFONT; 326 | 327 | 328 | #define InquireInfo 0x01 /* Inquire Device GDI Info */ 329 | #define EnableDevice 0x00 /* Enable Device */ 330 | #define InfoContext 0x8000 /* Inquire/Enable for info context */ 331 | 332 | /* Device Technology types */ 333 | #define DT_PLOTTER 0 /* Vector plotter */ 334 | #define DT_RASDISPLAY 1 /* Raster display */ 335 | #define DT_RASPRINTER 2 /* Raster printer */ 336 | #define DT_RASCAMERA 3 /* Raster camera */ 337 | #define DT_CHARSTREAM 4 /* Character-stream, PLP */ 338 | #define DT_METAFILE 5 /* Metafile, VDM */ 339 | #define DT_DISPFILE 6 /* Display-file */ 340 | #define DT_JUMBO 11 /* SPAG LJ cool thing */ 341 | 342 | /* Curve Capabilities */ 343 | #define CC_NONE 0x0000 /* Curves not supported */ 344 | #define CC_CIRCLES 0x0001 /* Can do circles */ 345 | #define CC_PIE 0x0002 /* Can do pie wedges */ 346 | #define CC_CHORD 0x0004 /* Can do chord arcs */ 347 | #define CC_ELLIPSES 0x0008 /* Can do ellipese */ 348 | #define CC_WIDE 0x0010 /* Can do wide lines */ 349 | #define CC_STYLED 0x0020 /* Can do styled lines */ 350 | #define CC_WIDESTYLED 0x0040 /* Can do wide styled lines*/ 351 | #define CC_INTERIORS 0x0080 /* Can do interiors */ 352 | #define CC_ROUNDRECT 0x0100 /* Can do round rectangles */ 353 | #define CC_POLYBEZIER 0x0200 /* Can do polybeziers */ 354 | 355 | /* Line Capabilities */ 356 | #define LC_NONE 0x0000 /* Lines not supported */ 357 | #define LC_POLYSCANLINE 0x0001 /* Poly Scanlines supported*/ 358 | #define LC_POLYLINE 0x0002 /* Can do polylines */ 359 | #define LC_MARKER 0x0004 /* Can do markers */ 360 | #define LC_POLYMARKER 0x0008 /* Can do polymarkers */ 361 | #define LC_WIDE 0x0010 /* Can do wide lines */ 362 | #define LC_STYLED 0x0020 /* Can do styled lines */ 363 | #define LC_WIDESTYLED 0x0040 /* Can do wide styled lines*/ 364 | #define LC_INTERIORS 0x0080 /* Can do interiors */ 365 | 366 | /* Polygonal Capabilities */ 367 | #define PC_NONE 0x0000 /* Polygonals not supported*/ 368 | #define PC_ALTPOLYGON 0x0001 /* Can do even odd polygons*/ 369 | #define PC_POLYGON 0x0001 /* old name for ALTPOLYGON */ 370 | #define PC_RECTANGLE 0x0002 /* Can do rectangles */ 371 | #define PC_WINDPOLYGON 0x0004 /* Can do winding polygons */ 372 | #define PC_TRAPEZOID 0x0004 /* old name for WINDPOLYGON*/ 373 | #define PC_SCANLINE 0x0008 /* Can do scanlines */ 374 | #define PC_WIDE 0x0010 /* Can do wide borders */ 375 | #define PC_STYLED 0x0020 /* Can do styled borders */ 376 | #define PC_WIDESTYLED 0x0040 /* Can do wide styled borders*/ 377 | #define PC_INTERIORS 0x0080 /* Can do interiors */ 378 | #define PC_POLYPOLYGON 0x0100 /* Can do PolyPolygons */ 379 | 380 | /* Clipping Capabilities */ 381 | #define CP_NONE 0x0000 /* no clipping of Output */ 382 | #define CP_RECTANGLE 0x0001 /* Output clipped to Rects */ 383 | #define CP_REGION 0x0002 /* not supported */ 384 | #define CP_REGION32 0x0004 /* Output clipped to regions */ 385 | 386 | /* Text Capabilities */ 387 | #define TC_OP_CHARACTER 0x0001 /* Can do OutputPrecision CHARACTER */ 388 | #define TC_OP_STROKE 0x0002 /* Can do OutputPrecision STROKE */ 389 | #define TC_CP_STROKE 0x0004 /* Can do ClipPrecision STROKE */ 390 | #define TC_CR_90 0x0008 /* Can do CharRotAbility 90 */ 391 | #define TC_CR_ANY 0x0010 /* Can do CharRotAbility ANY */ 392 | #define TC_SF_X_YINDEP 0x0020 /* Can do ScaleFreedom X_YINDEPENDENT */ 393 | #define TC_SA_DOUBLE 0x0040 /* Can do ScaleAbility DOUBLE */ 394 | #define TC_SA_INTEGER 0x0080 /* Can do ScaleAbility INTEGER */ 395 | #define TC_SA_CONTIN 0x0100 /* Can do ScaleAbility CONTINUOUS */ 396 | #define TC_EA_DOUBLE 0x0200 /* Can do EmboldenAbility DOUBLE */ 397 | #define TC_IA_ABLE 0x0400 /* Can do ItalisizeAbility ABLE */ 398 | #define TC_UA_ABLE 0x0800 /* Can do UnderlineAbility ABLE */ 399 | #define TC_SO_ABLE 0x1000 /* Can do StrikeOutAbility ABLE */ 400 | #define TC_RA_ABLE 0x2000 /* Can do RasterFontAble ABLE */ 401 | #define TC_VA_ABLE 0x4000 /* Can do VectorFontAble ABLE */ 402 | #define TC_RESERVED 0x8000 /* Reserved. Must be returned zero. */ 403 | 404 | /* Raster Capabilities */ 405 | #define RC_NONE 0x0000 /* No Raster Capabilities */ 406 | #define RC_BITBLT 0x0001 /* Can do bitblt */ 407 | #define RC_BANDING 0x0002 /* Requires banding support */ 408 | #define RC_SCALING 0x0004 /* does scaling while banding */ 409 | #define RC_BITMAP64 0x0008 /* supports >64k bitmaps */ 410 | #define RC_GDI20_OUTPUT 0x0010 /* has 2.0 output calls */ 411 | #define RC_GDI20_STATE 0x0020 /* dc has a state block */ 412 | #define RC_SAVEBITMAP 0x0040 /* can save bitmaps locally */ 413 | #define RC_DI_BITMAP 0x0080 /* can do DIBs */ 414 | #define RC_PALETTE 0x0100 /* can do color pal management */ 415 | #define RC_DIBTODEV 0x0200 /* can do SetDIBitsToDevice */ 416 | #define RC_BIGFONT 0x0400 /* can do BIGFONTs */ 417 | #define RC_STRETCHBLT 0x0800 /* can do StretchBlt */ 418 | #define RC_FLOODFILL 0x1000 /* can do FloodFill */ 419 | #define RC_STRETCHDIB 0x2000 /* can do StretchDIBits */ 420 | #define RC_OP_DX_OUTPUT 0x4000 /* can do smart ExtTextOut w/dx */ 421 | #define RC_DEVBITS 0x8000 /* supports device bitmaps */ 422 | 423 | /* DC Management Flags */ 424 | #define DC_SPDevice 0000001 /* Seperate PDevice required per device/filename */ 425 | #define DC_1PDevice 0000002 /* Only 1 PDevice allowed per device/filename */ 426 | #define DC_IgnoreDFNP 0000004 /* Ignore device/filename pairs when matching */ 427 | 428 | /* dpCaps1 capability bits */ 429 | #define C1_TRANSPARENT 0x0001 /* supports transparency */ 430 | #define TC_TT_ABLE 0x0002 /* can do TT through DDI or brute */ 431 | #define C1_TT_CR_ANY 0x0004 /* can do rotated TT fonts */ 432 | #define C1_EMF_COMPLIANT 0x0008 /* Win95 - supports metafile spooling */ 433 | #define C1_DIBENGINE 0x0010 /* DIB Engine compliant driver */ 434 | #define C1_GAMMA_RAMP 0x0020 /* supports gamma ramp setting */ 435 | #define C1_ICM 0x0040 /* does some form of ICM support */ 436 | #define C1_REINIT_ABLE 0x0080 /* Driver supports ReEnable */ 437 | #define C1_GLYPH_INDEX 0x0100 /* Driver supports glyph index fonts */ 438 | #define C1_BIT_PACKED 0x0200 /* Supports bit-packed glyphs */ 439 | #define C1_BYTE_PACKED 0x0400 /* Supports byte-packed glyphs */ 440 | #define C1_COLORCURSOR 0x0800 /* Driver supports color_cursors and async SetCursor */ 441 | #define C1_CMYK_ABLE 0x1000 /* Driver supports CMYK ColorRefs */ 442 | #define C1_SLOW_CARD 0x2000 /* Little or no acceleration (VGA, etc.)*/ 443 | 444 | /* dpCapsFE capability bits */ 445 | #define FEC_TT_DBCS 0x0020 /* can output DBCS TT fonts correctly */ 446 | #define FEC_WIFE_ABLE 0x0080 /* can handle WIFE font as Engine font */ 447 | 448 | typedef struct { 449 | short int dpVersion; 450 | short int dpTechnology; 451 | short int dpHorzSize; 452 | short int dpVertSize; 453 | short int dpHorzRes; 454 | short int dpVertRes; 455 | short int dpBitsPixel; 456 | short int dpPlanes; 457 | short int dpNumBrushes; 458 | short int dpNumPens; 459 | short int dpCapsFE; 460 | short int dpNumFonts; 461 | short int dpNumColors; 462 | short int dpDEVICEsize; 463 | unsigned short int dpCurves; 464 | unsigned short int dpLines; 465 | unsigned short int dpPolygonals; 466 | unsigned short int dpText; 467 | unsigned short int dpClip; 468 | unsigned short int dpRaster; 469 | short int dpAspectX; 470 | short int dpAspectY; 471 | short int dpAspectXY; 472 | short int dpStyleLen; 473 | PTTYPE dpMLoWin; 474 | PTTYPE dpMLoVpt; 475 | PTTYPE dpMHiWin; 476 | PTTYPE dpMHiVpt; 477 | PTTYPE dpELoWin; 478 | PTTYPE dpELoVpt; 479 | PTTYPE dpEHiWin; 480 | PTTYPE dpEHiVpt; 481 | PTTYPE dpTwpWin; 482 | PTTYPE dpTwpVpt; 483 | short int dpLogPixelsX; 484 | short int dpLogPixelsY; 485 | short int dpDCManage; 486 | unsigned short int dpCaps1; 487 | short int futureuse4; 488 | short int futureuse5; 489 | short int futureuse6; 490 | short int futureuse7; 491 | WORD dpNumPalReg; 492 | WORD dpPalReserved; 493 | WORD dpColorRes; 494 | } GDIINFO; 495 | 496 | /* This bit in the dfType field signals that the dfBitsOffset field is an 497 | absolute memory address and should not be altered. */ 498 | #define PF_BITS_IS_ADDRESS 4 499 | 500 | /* This bit in the dfType field signals that the font is device realized. */ 501 | #define PF_DEVICE_REALIZED 0x80 502 | 503 | /* These bits in the dfType give the fonttype - 504 | raster, vector, other1, other2. */ 505 | #define PF_RASTER_TYPE 0 506 | #define PF_VECTOR_TYPE 1 507 | #define PF_OTHER1_TYPE 2 508 | #define PF_OTHER2_TYPE 3 509 | #define PF_GLYPH_INDEX 0x20 510 | #define PF_WIFE_TYPE 0x08 511 | 512 | /* Glyph types for EngineGetGlyphBmp */ 513 | #define EGB_BITMAP 1 514 | #define EGB_OUTLINE 2 515 | #define EGB_GRAY2_BITMAP 8 516 | #define EGB_GRAY4_BITMAP 9 517 | #define EGB_GRAY8_BITMAP 10 518 | 519 | 520 | /* The size to allocate for the dfMaps field in the physical font. */ 521 | #ifndef DF_MAPSIZE 522 | #define DF_MAPSIZE 1 523 | #endif 524 | 525 | /* Font structure. */ 526 | typedef struct { 527 | short int dfType; 528 | short int dfPoints; 529 | short int dfVertRes; 530 | short int dfHorizRes; 531 | short int dfAscent; 532 | short int dfInternalLeading; 533 | short int dfExternalLeading; 534 | BYTE dfItalic; 535 | BYTE dfUnderline; 536 | BYTE dfStrikeOut; 537 | short int dfWeight; 538 | BYTE dfCharSet; 539 | short int dfPixWidth; 540 | short int dfPixHeight; 541 | BYTE dfPitchAndFamily; 542 | short int dfAvgWidth; 543 | short int dfMaxWidth; 544 | BYTE dfFirstChar; 545 | BYTE dfLastChar; 546 | BYTE dfDefaultChar; 547 | BYTE dfBreakChar; 548 | short int dfWidthBytes; 549 | unsigned long int dfDevice; 550 | unsigned long int dfFace; 551 | unsigned long int dfBitsPointer; 552 | unsigned long int dfBitsOffset; 553 | BYTE dfReservedByte; 554 | unsigned short dfMaps[DF_MAPSIZE]; 555 | } FONTINFO; 556 | 557 | 558 | typedef struct { 559 | short int erType; 560 | short int erPoints; 561 | short int erVertRes; 562 | short int erHorizRes; 563 | short int erAscent; 564 | short int erInternalLeading; 565 | short int erExternalLeading; 566 | BYTE erItalic; 567 | BYTE erUnderline; 568 | BYTE erStrikeOut; 569 | short int erWeight; 570 | BYTE erCharSet; 571 | short int erPixWidth; 572 | short int erPixHeight; 573 | BYTE erPitchAndFamily; 574 | short int erAvgWidth; 575 | short int erMaxWidth; 576 | BYTE erFirstChar; 577 | BYTE erLastChar; 578 | BYTE erDefaultChar; 579 | BYTE erBreakChar; 580 | short int erWidthBytes; 581 | unsigned long int erDevice; 582 | unsigned long int erFace; 583 | unsigned long int erBitsPointer; 584 | unsigned long int erBitsOffset; 585 | BYTE erReservedByte; 586 | short int erUnderlinePos; 587 | short int erUnderlineThick; 588 | short int erStrikeoutPos; 589 | short int erStrikeoutThick; 590 | } SCALABLEFONTINFO; 591 | 592 | 593 | typedef struct { 594 | short int ftHeight; 595 | short int ftWidth; 596 | short int ftEscapement; 597 | short int ftOrientation; 598 | short int ftWeight; 599 | BYTE ftItalic; 600 | BYTE ftUnderline; 601 | BYTE ftStrikeOut; 602 | BYTE ftOutPrecision; 603 | BYTE ftClipPrecision; 604 | unsigned short int ftAccelerator; 605 | short int ftOverhang; 606 | } TEXTXFORM; 607 | 608 | 609 | typedef struct { 610 | short int tmHeight; 611 | short int tmAscent; 612 | short int tmDescent; 613 | short int tmInternalLeading; 614 | short int tmExternalLeading; 615 | short int tmAveCharWidth; 616 | short int tmMaxCharWidth; 617 | short int tmWeight; 618 | BYTE tmItalic; 619 | BYTE tmUnderlined; 620 | BYTE tmStruckOut; 621 | BYTE tmFirstChar; 622 | BYTE tmLastChar; 623 | BYTE tmDefaultChar; 624 | BYTE tmBreakChar; 625 | BYTE tmPitchAndFamily; 626 | BYTE tmCharSet; 627 | short int tmOverhang; 628 | short int tmDigitizedAspectX; 629 | short int tmDigitizedAspectY; 630 | } TEXTMETRIC; 631 | 632 | typedef struct { 633 | short int Rop2; 634 | short int bkMode; 635 | unsigned long int bkColor; 636 | unsigned long int TextColor; 637 | short int TBreakExtra; 638 | short int BreakExtra; 639 | short int BreakErr; 640 | short int BreakRem; 641 | short int BreakCount; 642 | short int CharExtra; 643 | unsigned long int LbkColor; 644 | unsigned long int LTextColor; 645 | DWORD ICMCXform; 646 | short StretchBltMode; 647 | DWORD eMiterLimit; 648 | } DRAWMODE; 649 | 650 | 651 | /* Background Mode definitions. */ 652 | #define TRANSPARENT 1 653 | #define OPAQUE 2 654 | 655 | #define BKMODE_TRANSPARENT 1 656 | #define BKMODE_OPAQUE 2 657 | #define BKMODE_LEVEL1 3 658 | #define BKMODE_LEVEL2 4 659 | #define BKMODE_LEVEL3 5 660 | #define BKMODE_TRANSLATE 6 661 | 662 | /* StretchBlt Mode definitions. */ 663 | #define STRETCH_ANDSCANS 1 664 | #define STRETCH_ORSCANS 2 665 | #define STRETCH_DELETESCANS 3 666 | #define STRETCH_HALFTONE 4 667 | 668 | #define SBM_BLACKONWHITE STRETCH_ANDSCANS 669 | #define SBM_WHITEONBLACK STRETCH_ORSCANS 670 | #define SBM_COLORONCOLOR STRETCH_DELETESCANS 671 | #define SBM_HALFTONE STRETCH_HALFTONE 672 | 673 | typedef struct { 674 | short int scnPntCnt; 675 | short int scnPntTop; 676 | short int scnPntBottom; 677 | short int scnPntX[2]; 678 | short int scnPntCntToo; 679 | } SCAN, FAR* LPSCAN; 680 | 681 | typedef struct { 682 | DWORD cbSize; 683 | LPVOID lpDestDev; 684 | DWORD nEscape; 685 | DWORD cbInput; 686 | LPVOID lpInput; 687 | POINT ptOrigin; 688 | DWORD dwUniq; 689 | RECT rcBBox; 690 | DWORD cScans; 691 | LPSCAN lpScan; 692 | } DRAWESCAPE, FAR* LPDRAWESCAPE; 693 | 694 | typedef struct { 695 | WORD id; 696 | WORD cbSize; 697 | LPRECT lprcClip; 698 | DWORD dwUniq; 699 | RECT rcBBox; 700 | DWORD cScans; 701 | LPSCAN lpScan; 702 | } REGION, FAR* LPREGION; 703 | 704 | 705 | /* Output Style definitions. */ 706 | 707 | #define OS_POLYBEZIER 1 708 | #define OS_ARC 3 709 | #define OS_SCANLINES 4 710 | #define OS_POLYSCANLINE 5 711 | #define OS_RECTANGLE 6 712 | #define OS_ELLIPSE 7 713 | #define OS_MARKER 8 714 | #define OS_POLYLINE 18 715 | #define OS_TRAPEZOID 20 716 | #define OS_WINDPOLYGON OS_TRAPEZOID 717 | #define OS_POLYGON 22 718 | #define OS_ALTPOLYGON OS_POLYGON 719 | #define OS_PIE 23 720 | #define OS_POLYMARKER 24 721 | #define OS_CHORD 39 722 | #define OS_CIRCLE 55 723 | 724 | #define OS_POLYPOLYGON 0x4000 /* ORed with OS_WIND/ALTPOLYGON. */ 725 | 726 | #define OS_BEGINNSCAN 80 727 | #define OS_ENDNSCAN 81 728 | 729 | #define OEM_FAILED 0x80000000L 730 | 731 | #define NEWFRAME 1 732 | #define ABORTDOC 2 733 | #define NEXTBAND 3 734 | #define SETCOLORTABLE 4 735 | #define GETCOLORTABLE 5 736 | #define FLUSHOUTPUT 6 737 | #define DRAFTMODE 7 738 | #define QUERYESCSUPPORT 8 739 | #define SETPRINTERDC 9 /* DDK: between GDI and Driver. */ 740 | #define SETABORTPROC 9 /* SDK: between application and GDI. */ 741 | #define STARTDOC 10 742 | #define ENDDOC 11 743 | #define GETPHYSPAGESIZE 12 744 | #define GETPRINTINGOFFSET 13 745 | #define GETSCALINGFACTOR 14 746 | #define MFCOMMENT 15 747 | #define GETPENWIDTH 16 748 | #define SETCOPYCOUNT 17 749 | #define SELECTPAPERSOURCE 18 750 | #define DEVICEDATA 19 751 | #define PASSTHROUGH 19 752 | #define GETTECHNOLGY 20 753 | #define GETTECHNOLOGY 20 754 | #define SETLINECAP 21 755 | #define SETLINEJOIN 22 756 | #define SETMITERLIMIT 23 757 | #define BANDINFO 24 758 | #define DRAWPATTERNRECT 25 759 | #define GETVECTORPENSIZE 26 760 | #define GETVECTORBRUSHSIZE 27 761 | #define ENABLEDUPLEX 28 762 | #define GETSETPAPERBINS 29 763 | #define GETSETPRINTORIENT 30 764 | #define ENUMPAPERBINS 31 765 | #define SETDIBSCALING 32 766 | #define EPSPRINTING 33 767 | #define ENUMPAPERMETRICS 34 768 | #define GETSETPAPERMETRICS 35 769 | #define GETVERSION 36 770 | #define POSTSCRIPT_DATA 37 771 | #define POSTSCRIPT_IGNORE 38 772 | #define QUERYROPSUPPORT 40 773 | #define GETDEVICEUNITS 42 774 | #define RESETDEVICE 128 775 | #define GETEXTENDEDTEXTMETRICS 256 776 | #define GETEXTENTTABLE 257 777 | #define GETPAIRKERNTABLE 258 778 | #define GETTRACKKERNTABLE 259 779 | #define EXTTEXTOUT 512 780 | #define GETFACENAME 513 781 | #define DOWNLOADFACE 514 782 | #define ENABLERELATIVEWIDTHS 768 783 | #define ENABLEPAIRKERNING 769 784 | #define SETKERNTRACK 770 785 | #define SETALLJUSTVALUES 771 786 | #define SETCHARSET 772 787 | #define STRETCHBLT 2048 788 | #define QUERYDIBSUPPORT 3073 789 | #define QDI_SETDIBITS 0x0001 790 | #define QDI_GETDIBITS 0x0002 791 | #define QDI_DIBTOSCREEN 0x0004 792 | #define QDI_STRETCHDIB 0x0008 793 | #define DCICOMMAND 3075 794 | #define BEGIN_PATH 4096 795 | #define CLIP_TO_PATH 4097 796 | #define END_PATH 4098 797 | #define EXT_DEVICE_CAPS 4099 798 | #define RESTORE_CTM 4100 799 | #define SAVE_CTM 4101 800 | #define SET_ARC_DIRECTION 4102 801 | #define SET_BACKGROUND_COLOR 4103 802 | #define SET_POLY_MODE 4104 803 | #define SET_SCREEN_ANGLE 4105 804 | #define SET_SPREAD 4106 805 | #define TRANSFORM_CTM 4107 806 | #define SET_CLIP_BOX 4108 807 | #define SET_BOUNDS 4109 808 | #define OPENCHANNEL 4110 809 | #define DOWNLOADHEADER 4111 810 | #define CLOSECHANNEL 4112 811 | #define SETGDIXFORM 4113 812 | #define RESETPAGE 4114 813 | #define POSTSCRIPT_PASSTHROUGH 4115 814 | #define ENCAPSULATED_POSTSCRIPT 4116 815 | 816 | 817 | typedef FONTINFO FAR *LPFONTINFO; 818 | typedef DRAWMODE FAR *LPDRAWMODE; 819 | typedef TEXTXFORM FAR *LPTEXTXFORM; 820 | typedef TEXTMETRIC FAR *LPTEXTMETRIC; 821 | typedef LOGFONT FAR *LPLOGFONT; 822 | typedef LOGPEN FAR *LPLOGPEN; 823 | typedef LOGBRUSH FAR *LPLOGBRUSH; 824 | typedef BITMAP FAR *LPBITMAP; 825 | typedef FARPROC FAR *LPFARPROC; 826 | typedef GDIINFO FAR *LPGDIINFO; 827 | typedef SCALABLEFONTINFO FAR * LPSCALABLEFONTINFO; 828 | 829 | -------------------------------------------------------------------------------- /ddk/minivdd.h: -------------------------------------------------------------------------------- 1 | 2 | /* Functions callable via VDD's API entry point, usually called by display 3 | * drivers. 4 | */ 5 | #define MINIVDD_SVC_BASE_OFFSET 0x80 6 | #define VDD_DRIVER_REGISTER (0 + MINIVDD_SVC_BASE_OFFSET) 7 | #define VDD_DRIVER_UNREGISTER (1 + MINIVDD_SVC_BASE_OFFSET) 8 | #define VDD_SAVE_DRIVER_STATE (2 + MINIVDD_SVC_BASE_OFFSET) 9 | #define VDD_REGISTER_DISPLAY_DRIVER_INFO (3 + MINIVDD_SVC_BASE_OFFSET) 10 | #define VDD_REGISTER_SSB_FLAGS (4 + MINIVDD_SVC_BASE_OFFSET) 11 | #define VDD_GET_DISPLAY_CONFIG (5 + MINIVDD_SVC_BASE_OFFSET) 12 | #define VDD_PRE_MODE_CHANGE (6 + MINIVDD_SVC_BASE_OFFSET) 13 | #define VDD_POST_MODE_CHANGE (7 + MINIVDD_SVC_BASE_OFFSET) 14 | #define VDD_SET_USER_FLAGS (8 + MINIVDD_SVC_BASE_OFFSET) 15 | #define VDD_SET_BUSY_FLAG_ADDR (9 + MINIVDD_SVC_BASE_OFFSET) 16 | 17 | /* The DISPLAYINFO structure for querying Registry information. */ 18 | typedef struct { 19 | WORD diHdrSize; 20 | WORD diInfoFlags; 21 | DWORD diDevNodeHandle; 22 | char diDriverName[16]; 23 | WORD diXRes; 24 | WORD diYRes; 25 | WORD diDPI; 26 | BYTE diPlanes; 27 | BYTE diBpp; 28 | WORD diRefreshRateMax; 29 | WORD diRefreshRateMin; 30 | WORD diLowHorz; 31 | WORD diHighHorz; 32 | WORD diLowVert; 33 | WORD diHighVert; 34 | DWORD diMonitorDevNodeHandle; 35 | BYTE diHorzSyncPolarity; 36 | BYTE diVertSyncPolarity; 37 | } DISPLAYINFO; 38 | 39 | /* diInfoFlags */ 40 | #define RETURNED_DATA_IS_STALE 0x001 /* VDD couldn't read Registry, data could be old. */ 41 | #define MINIVDD_FAILED_TO_LOAD 0x002 /* MiniVDD did not load, probably bad config. */ 42 | #define MINIVDD_CHIP_ID_DIDNT_MATCH 0x004 /* ChipID mismatch, probably bad config. */ 43 | #define REGISTRY_BPP_NOT_VALID 0x008 /* BPP could not be read from Registry. */ 44 | #define REGISTRY_RESOLUTION_NOT_VALID 0x010 /* Resolution could not be read from Registry. */ 45 | #define REGISTRY_DPI_NOT_VALID 0x020 /* DPI could not be read from Registry. */ 46 | #define MONITOR_DEVNODE_NOT_ACTIVE 0x040 /* Devnode not there, no refresh rate data. */ 47 | #define MONITOR_INFO_NOT_VALID 0x080 /* Refresh rate data could not be read. */ 48 | #define MONITOR_INFO_DISABLED_BY_USER 0x100 /* Refresh rate data not valid. */ 49 | #define REFRESH_RATE_MAX_ONLY 0x200 /* Only diRefreshRateMax is valid. */ 50 | #define CARD_VDD_LOADED_OK 0x400 /* Second MiniVDD loaded fine. */ 51 | 52 | /* Funcrions callable in a mini-VDD. */ 53 | #define REGISTER_DISPLAY_DRIVER 0 54 | #define GET_VDD_BANK 1 55 | #define SET_VDD_BANK 2 56 | #define RESET_BANK 3 57 | #define PRE_HIRES_TO_VGA 4 58 | #define POST_HIRES_TO_VGA 5 59 | #define PRE_VGA_TO_HIRES 6 60 | #define POST_VGA_TO_HIRES 7 61 | #define SAVE_REGISTERS 8 62 | #define RESTORE_REGISTERS 9 63 | #define MODIFY_REGISTER_STATE 10 64 | #define ACCESS_VGA_MEMORY_MODE 11 65 | #define ACCESS_LINEAR_MEMORY_MODE 12 66 | #define ENABLE_TRAPS 13 67 | #define DISABLE_TRAPS 14 68 | #define MAKE_HARDWARE_NOT_BUSY 15 69 | #define VIRTUALIZE_CRTC_IN 16 70 | #define VIRTUALIZE_CRTC_OUT 17 71 | #define VIRTUALIZE_SEQUENCER_IN 18 72 | #define VIRTUALIZE_SEQUENCER_OUT 19 73 | #define VIRTUALIZE_GCR_IN 20 74 | #define VIRTUALIZE_GCR_OUT 21 75 | #define SET_LATCH_BANK 22 76 | #define RESET_LATCH_BANK 23 77 | #define SAVE_LATCHES 24 78 | #define RESTORE_LATCHES 25 79 | #define DISPLAY_DRIVER_DISABLING 26 80 | #define SELECT_PLANE 27 81 | #define PRE_CRTC_MODE_CHANGE 28 82 | #define POST_CRTC_MODE_CHANGE 29 83 | #define VIRTUALIZE_DAC_OUT 30 84 | #define VIRTUALIZE_DAC_IN 31 85 | #define GET_CURRENT_BANK_WRITE 32 86 | #define GET_CURRENT_BANK_READ 33 87 | #define SET_BANK 34 88 | #define CHECK_HIRES_MODE 35 89 | #define GET_TOTAL_VRAM_SIZE 36 90 | #define GET_BANK_SIZE 37 91 | #define SET_HIRES_MODE 38 92 | #define PRE_HIRES_SAVE_RESTORE 39 93 | #define POST_HIRES_SAVE_RESTORE 40 94 | #define VESA_SUPPORT 41 95 | #define GET_CHIP_ID 42 96 | #define CHECK_SCREEN_SWITCH_OK 43 97 | #define VIRTUALIZE_BLTER_IO 44 98 | #define SAVE_MESSAGE_MODE_STATE 45 99 | #define SAVE_FORCED_PLANAR_STATE 46 100 | #define VESA_CALL_POST_PROCESSING 47 101 | #define PRE_INT_10_MODE_SET 48 102 | 103 | #define NBR_MINI_VDD_FUNCTIONS 49 104 | 105 | /* Port sizes. */ 106 | #define BYTE_LENGTHED 1 107 | #define WORD_LENGTHED 2 108 | 109 | /* Flag bits. */ 110 | #define GOING_TO_WINDOWS_MODE 1 111 | #define GOING_TO_VGA_MODE 2 112 | #define DISPLAY_DRIVER_DISABLED 4 113 | #define IN_WINDOWS_HIRES_MODE 8 114 | 115 | -------------------------------------------------------------------------------- /ddk/valmode.h: -------------------------------------------------------------------------------- 1 | 2 | /* Return values for ValidateMode. */ 3 | #define VALMODE_YES 0 /* Mode is good. */ 4 | #define VALMODE_NO_WRONGDRV 1 /* Hardware not supported by driver. */ 5 | #define VALMODE_NO_NOMEM 2 /* Insufficient video memory. */ 6 | #define VALMODE_NO_NODAC 3 /* DAC cannot handle bit depth. */ 7 | #define VALMODE_NO_UNKNOWN 4 /* Some other problem. */ 8 | 9 | 10 | /* Structure describing a display mode. */ 11 | typedef struct { 12 | UINT dvmSize; /* Size of this struct. */ 13 | UINT dvmBpp; /* Mode color depth. */ 14 | int dvmXRes; /* Mode X resolution. */ 15 | int dvmYRes; /* Mode Y resolution. */ 16 | } DISPVALMODE; 17 | 18 | /* Must be exported by name from driver. Recommended ordinal is 700. */ 19 | extern UINT WINAPI ValidateMode( DISPVALMODE FAR *lpMode ); 20 | 21 | -------------------------------------------------------------------------------- /dibcall.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | 26 | #include "winhack.h" 27 | #include 28 | #include 29 | #include "minidrv.h" 30 | 31 | /* 32 | * What's this all about? Most of the required exported driver functions can 33 | * be passed straight to the DIB Engine. The DIB Engine in some cases requires 34 | * an additional parameter. 35 | * 36 | * See the dibthunk.asm module for functions that can be handled easily. Note 37 | * that although the logic could be implemented in C, it can be done more 38 | * efficiently in assembly. Forwarders turn into simple jumps, and functions 39 | * with an extra parameter can be implemented with very small overhead, saving 40 | * stack space and extra copying. 41 | * 42 | * This module deals with the very few functions that need additional logic but 43 | * are not hardware specific. 44 | */ 45 | 46 | 47 | /* Exported as DISPLAY.104 */ 48 | void WINAPI __loadds CheckCursor( void ) 49 | { 50 | if( wEnabled ) { 51 | DIB_CheckCursorExt( lpDriverPDevice ); 52 | } 53 | } 54 | 55 | /* If there is no hardware screen-to-screen BitBlt, there's no point in 56 | * this and we can just forward BitBlt to the DIB Engine. 57 | */ 58 | #ifdef HWBLT 59 | 60 | extern BOOL WINAPI (* BitBltDevProc)( LPDIBENGINE, WORD, WORD, LPPDEVICE, WORD, WORD, 61 | WORD, WORD, DWORD, LPBRUSH, LPDRAWMODE ); 62 | 63 | /* See if a hardware BitBlt can be done. */ 64 | BOOL WINAPI BitBlt( LPDIBENGINE lpDestDev, WORD wDestX, WORD wDestY, LPPDEVICE lpSrcDev, 65 | WORD wSrcX, WORD wSrcY, WORD wXext, WORD wYext, DWORD dwRop3, 66 | LPBRUSH lpPBrush, LPDRAWMODE lpDrawMode ) 67 | { 68 | WORD dstFlags = lpDestDev->deFlags; 69 | 70 | /* The destination must be video memory and not busy. */ 71 | if( (dstFlags & VRAM) && !(dstFlags & BUSY) ) { 72 | /* If palette translation is needed, only proceed if source 73 | * and destination device are identical. 74 | */ 75 | if( !(dstFlags & PALETTE_XLAT) || (lpDestDev == lpSrcDev) ) { 76 | /* If there is a hardware acceleration callback, use it. */ 77 | if( BitBltDevProc ) { 78 | return( BitBltDevProc( lpDestDev, wDestX, wDestY, lpSrcDev, wSrcX, wSrcY, wXext, wYext, dwRop3, lpPBrush, lpDrawMode ) ); 79 | } 80 | } 81 | } 82 | return( DIB_BitBlt( lpDestDev, wDestX, wDestY, lpSrcDev, wSrcX, wSrcY, wXext, wYext, dwRop3, lpPBrush, lpDrawMode ) ); 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /dibthunk.asm: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ; 3 | ; Copyright (c) 2022 Michal Necasek 4 | ; 5 | ; Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ; of this software and associated documentation files (the "Software"), to deal 7 | ; in the Software without restriction, including without limitation the rights 8 | ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ; copies of the Software, and to permit persons to whom the Software is 10 | ; furnished to do so, subject to the following conditions: 11 | ; 12 | ; The above copyright notice and this permission notice shall be included in 13 | ; all copies or substantial portions of the Software. 14 | ; 15 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | ; THE SOFTWARE. 22 | ; 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 24 | 25 | ; Define a macro which produces a DIB engine thunk, taking care of all 26 | ; externs and publics. 27 | ; The DIB_xxxExt functions take one additional parameter. To minimize 28 | ; stack space copying and usage, the thunk pops off the return address, 29 | ; pushes the additional parameter (always the last parameter of 30 | ; DIB_xxxExt), pushes the return address back, and jumps to DIB_xxxExt. 31 | ; The AX, ECX, and ES registers are modified with no ill effect since 32 | ; they aren't used by the Pascal calling convention to pass arguments. 33 | 34 | ;; Thunk macro with additional parameters. 35 | DIBTHK macro name, param 36 | extrn DIB_&name&Ext : far 37 | public name 38 | name: 39 | mov ax, DGROUP ; Load ES with our data segment. 40 | mov es, ax 41 | assume es:DGROUP 42 | pop ecx ; Save the 16:16 return address in ECX. 43 | push param ; Push the additional parameter. 44 | push ecx ; Put the return address back. 45 | jmp DIB_&name&Ext ; Off to the DIB Engine we go. 46 | endm 47 | 48 | ;; Simple forwarder macro. 49 | DIBFWD macro name 50 | extrn DIB_&name : far 51 | public name 52 | name: 53 | jmp DIB_&name ; Just jump to the DIB Engine. 54 | endm 55 | 56 | ;; Additional variables that need to be pushed are in the data segment. 57 | _DATA segment public 'DATA' 58 | 59 | extrn _lpDriverPDevice : dword 60 | extrn _wPalettized : word 61 | 62 | _DATA ends 63 | 64 | DGROUP group _DATA 65 | 66 | _TEXT segment public 'CODE' 67 | 68 | .386 69 | assume ds:nothing, es:nothing 70 | 71 | ;; Thunks that push an additional parameter. 72 | ;; Sorted by ordinal number. 73 | DIBTHK EnumObj, _lpDriverPDevice 74 | DIBTHK RealizeObject, _lpDriverPDevice 75 | DIBTHK DibBlt, _wPalettized 76 | DIBTHK GetPalette, _lpDriverPDevice 77 | DIBTHK SetPaletteTranslate, _lpDriverPDevice 78 | DIBTHK GetPaletteTranslate, _lpDriverPDevice 79 | DIBTHK UpdateColors, _lpDriverPDevice 80 | DIBTHK SetCursor, _lpDriverPDevice 81 | DIBTHK MoveCursor, _lpDriverPDevice 82 | 83 | ;; Forwarders that simply jump to the DIB Engine. 84 | ;; Sorted by ordinal number. 85 | ifndef HWBLT 86 | DIBFWD BitBlt 87 | endif 88 | DIBFWD ColorInfo 89 | DIBFWD Control 90 | DIBFWD EnumDFonts 91 | DIBFWD Output 92 | DIBFWD Pixel 93 | DIBFWD Strblt 94 | DIBFWD ScanLR 95 | DIBFWD DeviceMode 96 | DIBFWD ExtTextOut 97 | DIBFWD GetCharWidth 98 | DIBFWD DeviceBitmap 99 | DIBFWD FastBorder 100 | DIBFWD SetAttribute 101 | DIBFWD CreateDIBitmap 102 | DIBFWD DibToDevice 103 | DIBFWD StretchBlt 104 | DIBFWD StretchDIBits 105 | DIBFWD SelectBitmap 106 | DIBFWD BitmapBits 107 | DIBFWD Inquire 108 | 109 | _TEXT ends 110 | 111 | end 112 | 113 | -------------------------------------------------------------------------------- /enable.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* GDI Enable (with ReEnable) and Disable implementation. */ 26 | 27 | #include "winhack.h" 28 | #include 29 | #include 30 | #include 31 | #include "minidrv.h" 32 | 33 | #include 34 | 35 | /* Pretend we have a 208 by 156 mm screen. */ 36 | #define DISPLAY_HORZ_MM 208 37 | #define DISPLAY_VERT_MM 156 38 | 39 | /* Size in English units. Looks pretty random. */ 40 | #define DISPLAY_SIZE_EN 325 41 | /* Size in twips. Just as random. */ 42 | #define DISPLAY_SIZE_TWP 2340 43 | 44 | LPDIBENGINE lpDriverPDevice = 0; /* This device's PDEV that's passed to GDI. */ 45 | WORD wEnabled = 0; /* Is this device enabled? */ 46 | RGBQUAD FAR *lpColorTable = 0; /* Current color table. */ 47 | 48 | static BYTE bReEnabling = 0; /* Set when re-enabling PDEV. */ 49 | static WORD wDIBPdevSize = 0; 50 | 51 | 52 | /* 1bpp Color Table (non-palettized). */ 53 | const DIBColorEntry DIB1ColorTable[] = { 54 | /* blue red green flags */ 55 | { 0 , 0 , 0 , 0 }, 56 | { 0xFF, 0xFF, 0xFF, MAPTOWHITE } 57 | }; 58 | 59 | /* 4bpp Color Table (non-palettized). */ 60 | const DIBColorEntry DIB4ColorTable[] = { 61 | /* blue red green flags */ 62 | { 0 , 0 , 0 , 0 }, 63 | { 0 , 0 , 0x80, 0 }, 64 | { 0 , 0x80, 0 , 0 }, 65 | { 0 , 0x80, 0x80, 0 }, 66 | { 0x80, 0 , 0 , 0 }, 67 | { 0x80, 0 , 0x80, 0 }, 68 | { 0x80, 0x80, 0 , 0 }, 69 | { 0xC0, 0xC0, 0xC0, MAPTOWHITE }, 70 | { 0x80, 0x80, 0x80, MAPTOWHITE }, 71 | { 0 , 0 , 0xFF, 0 }, 72 | { 0 , 0xFF, 0 , MAPTOWHITE }, 73 | { 0 , 0xFF, 0xFF, MAPTOWHITE }, 74 | { 0xFF, 0 , 0 , 0 }, 75 | { 0xFF, 0 , 0xFF, 0 }, 76 | { 0xFF, 0xFF, 0 , MAPTOWHITE }, 77 | { 0xFF, 0xFF, 0xFF, MAPTOWHITE } 78 | }; 79 | 80 | /* 8bpp Color Table (palettized), first 10 entries. */ 81 | const DIBColorEntry DIB8ColorTable1[] = { 82 | /* blue red green flags */ 83 | { 0 , 0 , 0 , 0 }, 84 | { 0 , 0 , 0x80, 0 }, 85 | { 0 , 0x80, 0 , 0 }, 86 | { 0 , 0x80, 0x80, 0 }, 87 | { 0x80, 0 , 0 , 0 }, 88 | { 0x80, 0 , 0x80, 0 }, 89 | { 0x80, 0x80, 0 , 0 }, 90 | { 0xC0, 0xC0, 0xC0, MAPTOWHITE }, 91 | { 0xC0, 0xDC, 0xC0, MAPTOWHITE | NONSTATIC }, 92 | { 0xF0, 0xCA, 0xA6, MAPTOWHITE | NONSTATIC } 93 | }; 94 | 95 | /* 8bpp Color Table (palettized), all middle entries (10-245). */ 96 | const DIBColorEntry DIB8ColorTable2[] = { 97 | /* blue red green flags */ 98 | { 0, 0, 0, NONSTATIC } 99 | }; 100 | 101 | /* 8bpp Color Table (palettized), last 10 entries (246-255). */ 102 | const DIBColorEntry DIB8ColorTable3[] = { 103 | /* blue red green flags */ 104 | { 0xF0, 0xFB, 0xFF, MAPTOWHITE | NONSTATIC }, 105 | { 0xA4, 0xA0, 0xA0, MAPTOWHITE | NONSTATIC }, 106 | { 0x80, 0x80, 0x80, MAPTOWHITE }, 107 | { 0 , 0 , 0xFF, 0 }, 108 | { 0 , 0xFF, 0 , MAPTOWHITE }, 109 | { 0 , 0xFF, 0xFF, MAPTOWHITE }, 110 | { 0xFF, 0 , 0 , 0 }, 111 | { 0xFF, 0 , 0xFF, 0 }, 112 | { 0xFF, 0xFF, 0 , MAPTOWHITE }, 113 | { 0xFF, 0xFF, 0xFF, MAPTOWHITE } 114 | }; 115 | 116 | 117 | /* An undocumented function called by USER to check if display driver 118 | * contains a more suitable version of a resource. 119 | * Exported as ordinal 450. 120 | */ 121 | DWORD WINAPI __loadds GetDriverResourceID( WORD wResID, LPSTR lpResType ) 122 | { 123 | if( wResID == OBJ_FONT ) { 124 | if( wDpi != 96 ) { 125 | return( 2003 ); /* If DPI is not 96, return fonts120.bin instead. */ 126 | } 127 | } 128 | return( wResID ); 129 | } 130 | 131 | /* Some genius at Microsoft decided that CreateDIBPDevice returns the result 132 | * in EAX, not DX:AX. This is not at all documented in the Win95 DDK, but it 133 | * is stated clearly in U.S. Patent 6,525,743 (granted in 2003). 134 | * We just create a tiny thunk to produce a sane calling convention. 135 | */ 136 | DWORD PASCAL CreateDIBPDeviceX( LPBITMAPINFO lpInfo, LPPDEVICE lpDevice, LPVOID lpBits, WORD wFlags ); 137 | #pragma aux CreateDIBPDeviceX = \ 138 | "call CreateDIBPDevice" \ 139 | "mov dx, ax" \ 140 | "shr eax, 16" \ 141 | "xchg ax, dx" 142 | 143 | #pragma code_seg( _INIT ) 144 | 145 | /* GDI calls Enable twice at startup, first to query the GDIINFO structure 146 | * and then to initialize the video hardware. 147 | */ 148 | UINT WINAPI __loadds Enable( LPVOID lpDevice, UINT style, LPSTR lpDeviceType, 149 | LPSTR lpOutputFile, LPVOID lpStuff ) 150 | { 151 | WORD rc; 152 | WORD wPalCnt; 153 | 154 | dbg_printf( "Enable: lpDevice=%WP style=%X bReEnabling=%u wPalettized=%u\n", lpDevice, style, bReEnabling, wPalettized ); 155 | if( !(style & 1) ) { /* Only test the low bit! */ 156 | LPDIBENGINE lpEng = lpDevice; 157 | LPBITMAPINFO lpInfo; 158 | WORD wFlags; 159 | DWORD dwRet; 160 | 161 | /* Initialize the PDEVICE. */ 162 | lpDriverPDevice = lpDevice; 163 | rc = PhysicalEnable(); 164 | if( !rc ) { 165 | dbg_printf( "Enable: PhysicalEnable failed!\n" ); 166 | return( 0 ); 167 | } 168 | if( !bReEnabling ) { 169 | int_2Fh( STOP_IO_TRAP ); 170 | } 171 | 172 | /* Pass down to the DIB engine. */ 173 | DIB_Enable( lpDevice, style, lpDeviceType, lpOutputFile, lpStuff ); 174 | 175 | if( wPalettized ) 176 | DIB_SetPaletteTranslateExt( NULL, lpDriverPDevice ); 177 | 178 | dbg_printf( "Enable: wBpp=%u wDpi=%u wScreenX=%u wScreenY=%u wDIBPdevSize=%x\n", 179 | wBpp, wDpi, wScreenX, wScreenY, wDIBPdevSize ); 180 | 181 | /* Fill out the bitmap header. */ 182 | /// @todo Does wDIBPdevSize have to equal sizeof(DIBENGINE)? 183 | lpInfo = (LPVOID)((LPBYTE)lpDevice + wDIBPdevSize); 184 | _fmemset( &lpInfo->bmiHeader, 0, sizeof( lpInfo->bmiHeader ) ); 185 | lpInfo->bmiHeader.biSize = sizeof( lpInfo->bmiHeader ); 186 | lpInfo->bmiHeader.biWidth = wScreenX; 187 | lpInfo->bmiHeader.biHeight = wScreenY; 188 | lpInfo->bmiHeader.biPlanes = 1; 189 | lpInfo->bmiHeader.biBitCount = wBpp; 190 | 191 | /* Set up the color table for non-direct color modes. */ 192 | if( wBpp <= 8 ) { 193 | DIBColorEntry FAR *lpDefaultClr; 194 | 195 | switch( wBpp ) { 196 | case 8: 197 | lpDefaultClr = DIB8ColorTable1; 198 | wPalCnt = sizeof( DIB8ColorTable1 ); 199 | break; 200 | case 4: 201 | lpDefaultClr = DIB4ColorTable; 202 | wPalCnt = sizeof( DIB4ColorTable ); 203 | break; 204 | case 1: 205 | default: 206 | lpDefaultClr = DIB1ColorTable; 207 | wPalCnt = sizeof( DIB1ColorTable ); 208 | break; 209 | } 210 | lpColorTable = &lpInfo->bmiColors; 211 | 212 | if( !bReEnabling ) { 213 | _fmemcpy( lpColorTable, lpDefaultClr, wPalCnt ); 214 | /* For 8bpp, fix up the rest of the palette. */ 215 | if( wBpp == 8 ) { 216 | int i; 217 | 218 | /* The entries at index 10 to 245 are all the same. */ 219 | for( i = 10; i < 246; ++i ) 220 | lpColorTable[i] = DIB8ColorTable2[0]; 221 | 222 | _fmemcpy( &lpColorTable[246], DIB8ColorTable3, sizeof( DIB8ColorTable3 ) ); 223 | } 224 | } 225 | } 226 | 227 | wFlags = wPDeviceFlags; 228 | if( wPalettized ) 229 | wFlags |= PALETTIZED; 230 | 231 | /* Call the DIB Engine to set up the PDevice. */ 232 | dbg_printf( "lpInfo=%WP lpDevice=%WP lpColorTable=%WP wFlags=%X ScreenSelector=%X\n", lpInfo, lpDevice, lpColorTable, wFlags, ScreenSelector ); 233 | dwRet = CreateDIBPDeviceX( lpInfo, lpDevice, ScreenSelector :> 0, wFlags ); 234 | if( !dwRet ) { 235 | dbg_printf( "Enable: CreateDIBPDevice failed!\n" ); 236 | return( 0 ); 237 | } 238 | dbg_printf( "Enable: CreateDIBPDevice returned %lX\n", dwRet ); 239 | 240 | /* Now fill out the begin/end access callbacks. */ 241 | lpEng->deBeginAccess = DIB_BeginAccess; 242 | lpEng->deEndAccess = DIB_EndAccess; 243 | 244 | /* Program the DAC in non-direct color modes. */ 245 | if( wBpp <= 8 ) { 246 | switch( wBpp ) { 247 | case 8: 248 | wPalCnt = 256; 249 | break; 250 | case 4: 251 | wPalCnt = 16; 252 | break; 253 | case 1: 254 | default: 255 | wPalCnt = 2; 256 | break; 257 | } 258 | SetRAMDAC_far( 0, wPalCnt, lpColorTable ); 259 | } 260 | 261 | if( !bReEnabling ) { 262 | HookInt2Fh(); 263 | } 264 | wEnabled = 1; 265 | return( 1 ); 266 | } else { 267 | /* Fill out GDIINFO for GDI. */ 268 | LPGDIINFO lpInfo = lpDevice; 269 | 270 | /* Start with passing down to the DIB engine. It will set dpCurves through dpStyleLen. */ 271 | DIB_Enable( lpDevice, style, lpDeviceType, lpOutputFile, lpStuff ); 272 | 273 | /* Fill out some static data. Note that some fields are set by the DIB Engine 274 | * and we don't touch them (curves, lines, polygons etc.). 275 | */ 276 | lpInfo->dpVersion = DRV_VERSION; 277 | lpInfo->dpTechnology = DT_RASDISPLAY; 278 | lpInfo->dpHorzSize = DISPLAY_HORZ_MM; 279 | lpInfo->dpVertSize = DISPLAY_VERT_MM; 280 | lpInfo->dpPlanes = 1; 281 | lpInfo->dpCapsFE = 0; 282 | lpInfo->dpNumFonts = 0; 283 | 284 | /* Now set the fields that depend on current mode. */ 285 | lpInfo->dpHorzRes = wScrX; 286 | lpInfo->dpVertRes = wScrY; 287 | 288 | lpInfo->dpMLoWin.xcoord = DISPLAY_HORZ_MM * 10; 289 | lpInfo->dpMLoWin.ycoord = DISPLAY_VERT_MM * 10; 290 | lpInfo->dpMLoVpt.xcoord = wScrX; 291 | lpInfo->dpMLoVpt.ycoord = -wScrY; 292 | 293 | lpInfo->dpMHiWin.xcoord = DISPLAY_HORZ_MM * 100; 294 | lpInfo->dpMHiWin.ycoord = DISPLAY_VERT_MM * 100; 295 | lpInfo->dpMHiVpt.xcoord = wScrX; 296 | lpInfo->dpMHiVpt.ycoord = -wScrY; 297 | 298 | /* These calculations are a wild guess and probably don't matter. */ 299 | lpInfo->dpELoWin.xcoord = DISPLAY_SIZE_EN; 300 | lpInfo->dpELoWin.ycoord = DISPLAY_SIZE_EN; 301 | lpInfo->dpELoVpt.xcoord = wScrX / 5; 302 | lpInfo->dpELoVpt.ycoord = -lpInfo->dpELoVpt.xcoord; 303 | 304 | lpInfo->dpELoWin.xcoord = DISPLAY_SIZE_EN * 5; 305 | lpInfo->dpELoWin.ycoord = DISPLAY_SIZE_EN * 5; 306 | lpInfo->dpEHiVpt.xcoord = wScrX / 10; 307 | lpInfo->dpEHiVpt.ycoord = -lpInfo->dpEHiVpt.xcoord; 308 | 309 | lpInfo->dpTwpWin.xcoord = DISPLAY_SIZE_TWP; 310 | lpInfo->dpTwpWin.ycoord = DISPLAY_SIZE_TWP; 311 | lpInfo->dpTwpVpt.xcoord = wScrX / 10; 312 | lpInfo->dpTwpVpt.ycoord = -lpInfo->dpTwpVpt.xcoord; 313 | 314 | /* Update more GDIINFO bits. */ 315 | lpInfo->dpLogPixelsX = wDpi; 316 | lpInfo->dpLogPixelsY = wDpi; 317 | lpInfo->dpBitsPixel = wBpp; 318 | lpInfo->dpDCManage = DC_IgnoreDFNP; 319 | /* In theory we should set the C1_SLOW_CARD flag since this driver is unaccelerated. 320 | * This flag disables certain visual effects like "embossed" disabled text or animations. 321 | * Realistically, software rendering in a VM on a modern system is going to be a lot 322 | * faster than most mid-1990s graphics cards. 323 | */ 324 | lpInfo->dpCaps1 |= C1_BYTE_PACKED | C1_COLORCURSOR | C1_REINIT_ABLE /*| C1_SLOW_CARD*/; 325 | 326 | /* Grab the DIB Engine PDevice size before we add to it. */ 327 | wDIBPdevSize = lpInfo->dpDEVICEsize; 328 | dbg_printf( "Enable: wDIBPdevSize=%X wScrX=%u wScrY=%u wBpp=%u wDpi=%u wScreenX=%u wScreenY=%u\n", 329 | wDIBPdevSize, wScrX, wScrY, wBpp, wDpi, wScreenX, wScreenY ); 330 | 331 | lpInfo->dpNumBrushes = -1; /* Too many to count, always the same.. */ 332 | 333 | if( wBpp == 8 ) { 334 | if( wPalettized ) { 335 | lpInfo->dpNumPens = 16; /* Pens realized by driver. */ 336 | lpInfo->dpNumColors = 20; /* Colors in color table. */ 337 | lpInfo->dpNumPalReg = 256; 338 | lpInfo->dpPalReserved = 20; 339 | lpInfo->dpColorRes = 18; 340 | lpInfo->dpRaster |= RC_DIBTODEV + RC_PALETTE + RC_SAVEBITMAP; 341 | } else { 342 | lpInfo->dpNumPens = 256; /* Pens realized by driver. */ 343 | lpInfo->dpNumColors = 256; /* Colors in color table. */ 344 | lpInfo->dpNumPalReg = 0; 345 | lpInfo->dpPalReserved = 0; 346 | lpInfo->dpColorRes = 0; 347 | lpInfo->dpRaster |= RC_DIBTODEV; 348 | } 349 | lpInfo->dpDEVICEsize += sizeof( BITMAPINFOHEADER ) + 256 * 4; 350 | } else if( wBpp > 8 ) { 351 | lpInfo->dpNumPens = -1; /* Pens realized by driver. */ 352 | lpInfo->dpNumColors = -1; /* Colors in color table. */ 353 | lpInfo->dpNumPalReg = 0; 354 | lpInfo->dpPalReserved = 0; 355 | lpInfo->dpColorRes = 0; 356 | lpInfo->dpRaster |= RC_DIBTODEV; 357 | lpInfo->dpDEVICEsize += sizeof( BITMAPINFOHEADER ); 358 | } else if( wBpp < 8 ) { 359 | WORD wCount; 360 | 361 | wCount = 1 << wBpp; /* 2 or 4 for 2 or 16 bpp. */ 362 | lpInfo->dpNumPens = wCount; /* Pens realized by driver. */ 363 | lpInfo->dpNumColors = wCount; /* Colors in color table. */ 364 | lpInfo->dpNumPalReg = 0; 365 | lpInfo->dpPalReserved = 0; 366 | lpInfo->dpColorRes = 0; 367 | lpInfo->dpRaster |= RC_DIBTODEV; 368 | wCount *= 4; 369 | lpInfo->dpDEVICEsize += sizeof( BITMAPINFOHEADER ) + 8 + wCount; 370 | } 371 | dbg_printf( "sizeof(GDIINFO)=%d (%X), dpDEVICEsize=%X\n", sizeof( GDIINFO ), sizeof( GDIINFO ), lpInfo->dpDEVICEsize ); 372 | return( sizeof( GDIINFO ) ); 373 | } 374 | } 375 | 376 | 377 | /* The ReEnable function is called to dynamically change resolution. 378 | * It must query the new display mode settings and then call Enable. 379 | * NB: Windows 9x will not dynamically change the color depth, only 380 | * resolution. Documented in MS KB Article Q127139. 381 | */ 382 | UINT WINAPI __loadds ReEnable( LPVOID lpDevice, LPGDIINFO lpInfo ) 383 | { 384 | WORD wLastValidBpp = wBpp; 385 | WORD wLastValidX = wScreenX; 386 | WORD wLastValidY = wScreenY; 387 | WORD rc; 388 | 389 | dbg_printf( "ReEnable: lpDevice=%WP lpInfo=%WP wScreenX=%u wScreenY=%u\n", lpDevice, lpInfo, wScreenX, wScreenY ); 390 | 391 | /* Figure out the new mode. */ 392 | ReadDisplayConfig(); 393 | dbg_printf( "ReEnable: wScreenX=%u wScreenY=%u wBpp=%u\n", wScreenX, wScreenY, wBpp ); 394 | 395 | /* Let Enable know it doesn't need to do everything. */ 396 | bReEnabling = 1; 397 | 398 | /* Don't let the cursor mess with things. */ 399 | DIB_BeginAccess( lpDevice, 0, 0, wScreenX - 1, wScreenY - 1, CURSOREXCLUDE ); 400 | 401 | /* Create a new PDevice and set the new mode. Returns zero on failure. */ 402 | rc = Enable( lpDevice, 0, NULL, NULL, NULL ); 403 | 404 | /* Drawing the cursor is safe again. */ 405 | DIB_EndAccess( lpDevice, CURSOREXCLUDE ); 406 | 407 | if( rc ) { 408 | /* Enable succeeded, fill out GDIINFO. */ 409 | Enable( lpInfo, 1, NULL, NULL, NULL ); 410 | rc = 1; 411 | } else { 412 | dbg_printf( "ReEnable: Enable failed!\n" ); 413 | /* Couldn't set new mode. Try to get the old one back. */ 414 | wScreenX = wLastValidX; 415 | wScreenY = wLastValidY; 416 | wBpp = wLastValidBpp; 417 | 418 | Enable( lpDevice, 0, NULL, NULL, NULL ); 419 | 420 | /* And force a repaint. */ 421 | RepaintFunc(); 422 | rc = 0; 423 | } 424 | 425 | bReEnabling = 0; 426 | return( rc ); 427 | } 428 | 429 | void int_10h( unsigned ax ); 430 | #pragma aux int_10h = \ 431 | "int 10h" \ 432 | parm [ax]; 433 | 434 | /* Disable graphics and go back to a text mode. */ 435 | UINT WINAPI __loadds Disable( LPVOID lpDevice ) 436 | { 437 | LPDIBENGINE lpEng = lpDevice; 438 | 439 | dbg_printf( "Disable: lpDevice=%WP\n", lpDevice ); 440 | 441 | /* Start disabling and mark the PDevice busy. */ 442 | wEnabled = 0; 443 | lpEng->deFlags |= BUSY; /// @todo Does this need to be a locked op? 444 | 445 | /* Re-enable I/O trapping before we start setting a standard VGA mode. */ 446 | int_2Fh( START_IO_TRAP ); 447 | 448 | /* Tell VDD we're going away. */ 449 | CallVDD( VDD_DRIVER_UNREGISTER ); 450 | 451 | /* Set standard 80x25 text mode using the BIOS. */ 452 | int_10h( 3 ); 453 | 454 | /* And unhook INT 2F. */ 455 | UnhookInt2Fh(); 456 | 457 | return( 1 ); 458 | } 459 | -------------------------------------------------------------------------------- /init.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* Display driver module initialization. */ 26 | 27 | #include "winhack.h" 28 | #include 29 | #include 30 | #include 31 | #include "minidrv.h" 32 | #include 33 | 34 | /* GlobalSmartPageLock is a semi-undocumented function. Not officially 35 | * documented but described in KB Article Q180586. */ 36 | UINT WINAPI GlobalSmartPageLock( HGLOBAL hglb ); 37 | 38 | WORD wScrX = 640; /* Current X resolution. */ 39 | WORD wScrY = 480; /* Current Y resolution. */ 40 | WORD wDpi = 96; /* Current DPI setting. */ 41 | WORD wBpp = 8; /* Current BPP setting. */ 42 | WORD wPalettized = 0; /* Non-zero if palettized. */ 43 | 44 | WORD OurVMHandle = 0; /* The current VM's ID. */ 45 | DWORD VDDEntryPoint = 0; /* The VDD entry point. */ 46 | DWORD ConfigMGEntryPoint = 0; /* The configuration manager entry point. */ 47 | DWORD LfbBase = 0; /* The physical base address of the linear framebuffer. */ 48 | 49 | /* On Entry: 50 | * EAX = Function code (VDD_GET_DISPLAY_CONFIG) 51 | * EBX = This VM's handle 52 | * ECX = Size of DISPLAYINFO structure 53 | * EDX = Zero to tell VDD to try virtualizing 54 | * ES:EDI = Pointer to DISPLAYINFO structure to be 55 | * filled 56 | * 57 | * On Return: 58 | * EAX = Return code (0 = succeess, -1 = failed) 59 | */ 60 | extern DWORD CallVDDGetDispConf( WORD Function, WORD wDInfSize, LPVOID pDInf ); 61 | #pragma aux CallVDDGetDispConf = \ 62 | ".386" \ 63 | "movzx eax, ax" \ 64 | "movzx ecx, cx" \ 65 | "movzx ebx, OurVMHandle" \ 66 | "movzx edi, di" \ 67 | "call dword ptr VDDEntryPoint"\ 68 | "mov edx, eax" \ 69 | "shr edx, 16" \ 70 | parm [ax] [cx] [es di] modify [bx]; 71 | 72 | 73 | #pragma code_seg( _INIT ) 74 | 75 | /* Get the first logical configuration for a devnode. 76 | */ 77 | CONFIGRET static _near _cdecl CM_Get_First_Log_Conf( 78 | PLOG_CONF plcLogConf, 79 | DEVNODE dnDevNode, 80 | ULONG ulFlags) 81 | { 82 | WORD wRc = 0; 83 | 84 | _asm { mov eax, 01Ah }; /* CM_GET_FIRST_LOG_CONF */ 85 | _asm { call ConfigMGEntryPoint }; 86 | _asm { mov wRc, ax }; 87 | 88 | return( wRc ); 89 | } 90 | 91 | /* Get the next resource descriptor of a given type. 92 | */ 93 | CONFIGRET static _near _cdecl CM_Get_Next_Res_Des( 94 | PRES_DES prdResDes, 95 | RES_DES CurrentResDesOrLogConf, 96 | RESOURCEID ForResource, 97 | PRESOURCEID pResourceID, 98 | ULONG ulFlags) 99 | { 100 | WORD wRc = 0; 101 | 102 | _asm { mov eax, 01Fh }; /* CM_GET_NEXT_RES_DES */ 103 | _asm { call ConfigMGEntryPoint }; 104 | _asm { mov wRc, ax }; 105 | 106 | return( wRc ); 107 | } 108 | 109 | /* Get the data for a resource descriptor. 110 | */ 111 | CONFIGRET static _near _cdecl CM_Get_Res_Des_Data( 112 | RES_DES rdResDes, 113 | PFARVOID Buffer, 114 | ULONG BufferLen, 115 | ULONG ulFlags) 116 | { 117 | WORD wRc = 0; 118 | 119 | _asm { mov eax, 022h }; /* CM_GET_RES_DES_DATA */ 120 | _asm { call ConfigMGEntryPoint }; 121 | _asm { mov wRc, ax }; 122 | 123 | return( wRc ); 124 | } 125 | 126 | /* Read the display settings from SYSTEM.INI or Registry. 127 | */ 128 | DEVNODE ReadDisplayConfig( void ) 129 | { 130 | WORD wX, wY; 131 | UINT bIgnoreRegistry; 132 | MODEDESC mode; 133 | DEVNODE devNode; 134 | DISPLAYINFO DispInfo; 135 | DWORD dwRc; 136 | 137 | /* Get the DPI, default to 96. */ 138 | wDpi = GetPrivateProfileInt( "display", "dpi", 96, "system.ini" ); 139 | 140 | /* Get X and Y resolution. */ 141 | wX = GetPrivateProfileInt( "display", "x_resolution", 0, "system.ini" ); 142 | wY = GetPrivateProfileInt( "display", "y_resolution", 0, "system.ini" ); 143 | 144 | /* Get the bits per pixel. */ 145 | wBpp = GetPrivateProfileInt( "display", "bpp", 0, "system.ini" ); 146 | 147 | dbg_printf( "SYSTEM.INI: %ux%u %ubpp %udpi\n", wX, wY, wBpp, wDpi ); 148 | 149 | bIgnoreRegistry = GetPrivateProfileInt( "display", "IgnoreRegistry", 0, "system.ini" ); 150 | 151 | dwRc = CallVDDGetDispConf( VDD_GET_DISPLAY_CONFIG, sizeof( DispInfo ), &DispInfo ); 152 | if( (dwRc != VDD_GET_DISPLAY_CONFIG) && !dwRc ) { 153 | devNode = (DEVNODE)DispInfo.diDevNodeHandle; 154 | 155 | /* Call succeeded, use the data. */ 156 | if (!bIgnoreRegistry) 157 | { 158 | wScrX = DispInfo.diXRes; 159 | wScrY = DispInfo.diYRes; 160 | wBpp = DispInfo.diBpp; 161 | 162 | dbg_printf( "Registry: %ux%u %ubpp %udpi\n", DispInfo.diXRes, DispInfo.diYRes, DispInfo.diBpp, DispInfo.diDPI ); 163 | 164 | /* DPI might not be set, careful. */ 165 | if( DispInfo.diDPI ) 166 | wDpi = DispInfo.diDPI; 167 | } 168 | } else { 169 | dbg_printf( "VDD_GET_DISPLAY_CONFIG failed, dwRc=%lX\n",dwRc ); 170 | devNode = 0; 171 | } 172 | 173 | mode.xRes = wScrX; 174 | mode.yRes = wScrY; 175 | mode.bpp = wBpp; 176 | 177 | if( !FixModeInfo( &mode ) ) { 178 | /* Values were changed. */ 179 | wScrX = mode.xRes; 180 | wScrY = mode.yRes; 181 | wBpp = mode.bpp; 182 | } 183 | 184 | /* For 8bpp, read the 'palettized' setting. Default to enabled. */ 185 | if( wBpp == 8 ) 186 | wPalettized = GetPrivateProfileInt( "display", "palettized", 1, "system.ini" ); 187 | else 188 | wPalettized = 0; 189 | 190 | return( devNode ); 191 | } 192 | 193 | #define VDD_ID 10 /* Virtual Display Driver ID. */ 194 | #define CONFIGMG_ID 51 /* Configuration Manager Driver ID. */ 195 | 196 | /* Get Device API Entry Point. */ 197 | void __far *int_2F_GetEP( unsigned ax, unsigned bx ); 198 | #pragma aux int_2F_GetEP = \ 199 | "int 2Fh" \ 200 | parm [ax] [bx] value [es di]; 201 | 202 | /* Get "magic number" (current Virtual Machine ID) for VDD calls. */ 203 | WORD int_2F_GetVMID( unsigned ax ); 204 | #pragma aux int_2F_GetVMID = \ 205 | "int 2Fh" \ 206 | parm [ax] value [bx]; 207 | 208 | /* Dummy pointer to get at the _TEXT segment. Is there any easier way? */ 209 | extern char __based( __segname( "_TEXT" ) ) *pText; 210 | 211 | /* This is a standard DLL entry point. Note that DS is already set 212 | * to point to this DLL's data segment on entry. 213 | */ 214 | #pragma aux DriverInit parm [cx] [di] [es si] 215 | UINT FAR DriverInit( UINT cbHeap, UINT hModule, LPSTR lpCmdLine ) 216 | { 217 | DEVNODE devNode; 218 | 219 | /* Lock the code segment. */ 220 | GlobalSmartPageLock( (__segment)pText ); 221 | 222 | /* Query the entry point of the Virtual Display Device. */ 223 | VDDEntryPoint = (DWORD)int_2F_GetEP( 0x1684, VDD_ID ); 224 | 225 | /* Obtain the "magic number" needed for VDD calls. */ 226 | OurVMHandle = int_2F_GetVMID( 0x1683 ); 227 | 228 | dbg_printf( "DriverInit: VDDEntryPoint=%WP, OurVMHandle=%x\n", VDDEntryPoint, OurVMHandle ); 229 | 230 | /* Read the display configuration before doing anything else. */ 231 | LfbBase = 0; 232 | devNode = ReadDisplayConfig(); 233 | 234 | /* Use the Configuration Manager to locate the base address of the linear framebuffer. */ 235 | if( devNode ) { 236 | RES_DES rd; 237 | 238 | ConfigMGEntryPoint = (DWORD)int_2F_GetEP( 0x1684, CONFIGMG_ID ); 239 | 240 | if( CM_Get_First_Log_Conf( &rd, devNode, ALLOC_LOG_CONF ) == CR_SUCCESS ) { 241 | ULONG cbAllocMax = 0; 242 | 243 | /* Take the largest physical memory range in use by this device 244 | * and store it into LfbBase. */ 245 | while( CM_Get_Next_Res_Des( &rd, rd, ResType_Mem, NULL, 0 ) == CR_SUCCESS ) { 246 | 247 | /* Experimentally, no MEM_RES was found to be larger than 0x28 bytes 248 | * with the QEMU VGA adapter, so this buffer is static, but it would 249 | * be better to query the size (with CM_Get_Res_Des_Data_Size) and 250 | * then use alloca here. */ 251 | char memRes[0x28]; 252 | 253 | if( CM_Get_Res_Des_Data( rd, memRes, sizeof(memRes), 0 ) == CR_SUCCESS ) { 254 | PMEM_DES pMemDes = (PMEM_DES)memRes; 255 | ULONG cbAlloc = pMemDes->MD_Alloc_End - pMemDes->MD_Alloc_Base + 1; 256 | 257 | if( cbAlloc > cbAllocMax ) { 258 | cbAllocMax = cbAlloc; 259 | LfbBase = pMemDes->MD_Alloc_Base; 260 | } 261 | } 262 | } 263 | } 264 | } 265 | 266 | dbg_printf("DriverInit: LfbBase is %lX\n", LfbBase); 267 | 268 | /* Return 1 (success) iff we located the physical address of the linear framebuffer. */ 269 | return ( !!LfbBase ); 270 | } 271 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | OBJS = dibthunk.obj dibcall.obj enable.obj init.obj palette.obj & 2 | scrsw.obj sswhook.obj modes.obj boxv.obj 3 | 4 | INCS = -I$(%WATCOM)\h\win -Iddk 5 | 6 | # Define HWBLT if BitBlt can be accelerated. 7 | #FLAGS = -DHWBLT 8 | 9 | # Set DBGPRINT to add debug printf logging. 10 | # DBGPRINT = 1 11 | !ifdef DBGPRINT 12 | FLAGS += -DDBGPRINT 13 | OBJS += dbgprint.obj 14 | # Need this to work with pre-made boxv9x.lnk 15 | DBGFILE = file dbgprint.obj 16 | !else 17 | DBGFILE = 18 | !endif 19 | 20 | boxvmini.drv : $(OBJS) display.res dibeng.lib boxv9x.lnk 21 | wlink op quiet, start=DriverInit_ disable 2055 @boxv9x.lnk $(DBGFILE) 22 | wrc -q display.res $@ 23 | 24 | # Linker script 25 | boxv9x.lnk : boxv9x.def 26 | ms2wlink $(OBJS),boxvmini.drv,boxvmini.map,dibeng.lib clibs.lib,boxv9x.def > boxv9x.lnk 27 | 28 | # Object files 29 | boxv.obj : boxv.c .autodepend 30 | wcc -q -wx -s -zu -zls -3 $(FLAGS) $< 31 | 32 | dbgprint.obj : dbgprint.c .autodepend 33 | wcc -q -wx -s -zu -zls -3 $(FLAGS) $< 34 | 35 | dibcall.obj : dibcall.c .autodepend 36 | wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< 37 | 38 | dibthunk.obj : dibthunk.asm 39 | wasm -q $(FLAGS) $< 40 | 41 | enable.obj : enable.c .autodepend 42 | wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< 43 | 44 | init.obj : init.c .autodepend 45 | wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< 46 | 47 | palette.obj : palette.c .autodepend 48 | wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< 49 | 50 | sswhook.obj : sswhook.asm 51 | wasm -q $(FLAGS) $< 52 | 53 | modes.obj : modes.c .autodepend 54 | wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< 55 | 56 | scrsw.obj : scrsw.c .autodepend 57 | wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< 58 | 59 | # Resources 60 | display.res : res/display.rc res/colortab.bin res/config.bin res/fonts.bin res/fonts120.bin .autodepend 61 | wrc -q -r -ad -bt=windows -fo=$@ -Ires -I$(%WATCOM)/h/win res/display.rc 62 | 63 | res/colortab.bin : res/colortab.c 64 | wcc -q $(INCS) $< 65 | wlink op quiet disable 1014, 1023 name $@ sys dos output raw file colortab.obj 66 | 67 | res/config.bin : res/config.c 68 | wcc -q $(INCS) $< 69 | wlink op quiet disable 1014, 1023 name $@ sys dos output raw file config.obj 70 | 71 | res/fonts.bin : res/fonts.c .autodepend 72 | wcc -q $(INCS) $< 73 | wlink op quiet disable 1014, 1023 name $@ sys dos output raw file fonts.obj 74 | 75 | res/fonts120.bin : res/fonts120.c .autodepend 76 | wcc -q $(INCS) $< 77 | wlink op quiet disable 1014, 1023 name $@ sys dos output raw file fonts120.obj 78 | 79 | # Libraries 80 | dibeng.lib : ddk/dibeng.lbc 81 | wlib -b -q -n -fo -ii @$< $@ 82 | 83 | # Cleanup 84 | clean : .symbolic 85 | rm *.obj 86 | rm *.err 87 | rm *.lib 88 | rm *.drv 89 | rm *.map 90 | rm *.res 91 | rm *.img 92 | rm res/*.obj 93 | rm res/*.bin 94 | 95 | image : .symbolic boxv9x.img 96 | 97 | # Create a 1.44MB distribution floppy image. 98 | # NB: The mkimage tool is not supplied. 99 | boxv9x.img : boxvmini.drv boxv9x.inf readme.txt 100 | if not exist dist mkdir dist 101 | copy boxvmini.drv dist 102 | copy boxv9x.inf dist 103 | copy readme.txt dist 104 | mkimage -l BOXV9X -o boxv9x.img dist 105 | -------------------------------------------------------------------------------- /minidrv.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* First definitions that don't appear to be in any "official" header. */ 26 | 27 | #define DRV_VERSION 0x0400 /* Windows 4.0 aka Windows 95. */ 28 | 29 | /* Int 2Fh subfunctions. */ 30 | #define STOP_IO_TRAP 0x4000 /* Stop trapping video I/O. */ 31 | #define SCREEN_SWITCH_OUT 0x4001 /* DOS session going to background. */ 32 | #define SCREEN_SWITCH_IN 0x4002 /* DOS session going to foreground. */ 33 | #define ENTER_CRIT_REG 0x4003 /* Enter critical section notification. */ 34 | #define EXIT_CRIT_REG 0x4004 /* Leave critical section notification. */ 35 | #define START_IO_TRAP 0x4007 /* Start trapping video I/O. */ 36 | 37 | /* Internal interfaces within minidriver. */ 38 | 39 | /* A simple mode descriptor structure. */ 40 | typedef struct { 41 | WORD xRes; 42 | WORD yRes; 43 | WORD bpp; 44 | } MODEDESC, FAR *LPMODEDESC; 45 | 46 | 47 | extern WORD FixModeInfo( LPMODEDESC lpMode ); 48 | extern int PhysicalEnable( void ); 49 | extern void FAR SetRAMDAC_far( UINT bStart, UINT bCount, RGBQUAD FAR *lpPal ); 50 | extern DWORD ReadDisplayConfig( void ); 51 | extern void FAR RestoreDesktopMode( void ); 52 | extern FARPROC RepaintFunc; 53 | extern void HookInt2Fh( void ); 54 | extern void UnhookInt2Fh( void ); 55 | 56 | #ifdef DBGPRINT 57 | extern void dbg_printf( const char *s, ... ); 58 | #else 59 | /* The "Meaningless use of an expression" warning gets too annoying. */ 60 | #pragma disable_message( 111 ); 61 | #define dbg_printf 1 ? (void)0 : (void) 62 | #endif 63 | 64 | extern LPDIBENGINE lpDriverPDevice; /* DIB Engine PDevice. */ 65 | extern WORD ScreenSelector; /* Selector of video memory. */ 66 | extern WORD wPalettized; /* Non-zero if palettized device. */ 67 | extern WORD wPDeviceFlags; /* Current GDI device flags. */ 68 | extern WORD wDpi; /* Current DPI. */ 69 | extern WORD wBpp; /* Current bits per pixel. */ 70 | extern WORD wScrX; /* Configured X resolution. */ 71 | extern WORD wScrY; /* Configured Y resolution. */ 72 | extern WORD wScreenX; /* Screen width in pixels. */ 73 | extern WORD wScreenY; /* Screen height in pixels. */ 74 | extern WORD wEnabled; /* PDevice enabled flag. */ 75 | extern RGBQUAD FAR *lpColorTable; /* Current color table. */ 76 | 77 | extern DWORD VDDEntryPoint; 78 | extern WORD OurVMHandle; 79 | extern DWORD LfbBase; 80 | 81 | /* Inlines needed in multiple modules. */ 82 | 83 | void int_2Fh( unsigned ax ); 84 | #pragma aux int_2Fh = \ 85 | "int 2Fh" \ 86 | parm [ax]; 87 | 88 | /* NB: It's unclear of EAX/EBX really need preserving. */ 89 | extern void CallVDD( unsigned Function ); 90 | #pragma aux CallVDD = \ 91 | ".386" \ 92 | "push eax" \ 93 | "push ebx" \ 94 | "movzx eax, ax" \ 95 | "movzx ebx, OurVMHandle" \ 96 | "call dword ptr VDDEntryPoint" \ 97 | "pop ebx" \ 98 | "pop eax" \ 99 | parm [ax]; 100 | 101 | -------------------------------------------------------------------------------- /modes.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* Display driver mode management. */ 26 | 27 | #include "winhack.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "minidrv.h" 33 | #include "boxv.h" 34 | 35 | 36 | /* Somewhat arbitrary max resolution. */ 37 | #define RES_MAX_X (5 * 1024) 38 | #define RES_MAX_Y (5 * 768) 39 | 40 | 41 | /* Generic DPMI calls, only used in this module. */ 42 | extern WORD DPMI_AllocLDTDesc( WORD cSelectors ); 43 | #pragma aux DPMI_AllocLDTDesc = \ 44 | "xor ax, ax" \ 45 | "int 31h" \ 46 | "jnc OK" \ 47 | "xor ax, ax" \ 48 | "OK:" \ 49 | parm [cx]; 50 | 51 | extern DWORD DPMI_GetSegBase( WORD Selector ); 52 | #pragma aux DPMI_GetSegBase = \ 53 | "mov ax, 6" \ 54 | "int 31h" \ 55 | "mov ax, cx" \ 56 | "xchg ax, dx" \ 57 | parm [bx] modify [cx]; 58 | 59 | extern void DPMI_SetSegBase( WORD Selector, DWORD Base ); 60 | #pragma aux DPMI_SetSegBase = \ 61 | "mov ax, 7" \ 62 | "int 31h" \ 63 | parm [bx] [cx dx]; 64 | 65 | extern void DPMI_SetSegLimit( WORD Selector, DWORD Limit ); 66 | #pragma aux DPMI_SetSegLimit = \ 67 | "mov ax, 8" \ 68 | "int 31h" \ 69 | parm [bx] [cx dx]; 70 | 71 | /* NB: Compiler insists on CX:BX and DI:SI, DPMI needs it word swapped. */ 72 | extern DWORD DPMI_MapPhys( DWORD Base, DWORD Size ); 73 | #pragma aux DPMI_MapPhys = \ 74 | "xchg cx, bx" \ 75 | "xchg si, di" \ 76 | "mov ax, 800h" \ 77 | "int 31h" \ 78 | "jnc OK" \ 79 | "xor bx, bx" \ 80 | "xor cx, cx" \ 81 | "OK:" \ 82 | "mov dx, bx" \ 83 | "mov ax, cx" \ 84 | parm [cx bx] [di si]; 85 | 86 | 87 | WORD wScreenX = 0; 88 | WORD wScreenY = 0; 89 | WORD BitBltDevProc = 0; 90 | WORD ScreenSelector = 0; 91 | WORD wPDeviceFlags = 0; 92 | 93 | static DWORD dwScreenFlatAddr = 0; /* 32-bit flat address of VRAM. */ 94 | static DWORD dwVideoMemorySize = 0; /* Installed VRAM in bytes. */ 95 | static WORD wScreenPitchBytes = 0; /* Current scanline pitch. */ 96 | static DWORD dwPhysVRAM = 0; /* Physical LFB base address. */ 97 | 98 | /* These are currently calculated not needed in the absence of 99 | * offscreen video memory. 100 | */ 101 | static WORD wMaxWidth = 0; 102 | static WORD wMaxHeight = 0; 103 | 104 | /* On Entry: 105 | * EAX = Function code (VDD_DRIVER_REGISTER) 106 | * EBX = This VM's handle 107 | * ECX = Size of all visible scanlines in bytes 108 | * EDX = Zero to tell VDD to try virtualizing 109 | * ES:DI = Pointer to function called when switching 110 | * back from fullscreen. 111 | * 112 | * On Return: 113 | * EAX = Amount of video memory used by VDD in bytes, 114 | * or function code if VDD call failed. 115 | */ 116 | extern DWORD CallVDDRegister( WORD Function, WORD wPitch, WORD wHeight, void _far *fRHR ); 117 | #pragma aux CallVDDRegister = \ 118 | ".386" \ 119 | "movzx eax, ax" \ 120 | "movzx edx, dx" \ 121 | "mul edx" \ 122 | "mov ecx, eax" \ 123 | "movzx eax, bx" \ 124 | "movzx ebx, OurVMHandle" \ 125 | "xor edx, edx" \ 126 | "call dword ptr VDDEntryPoint"\ 127 | "mov edx, eax" \ 128 | "shr edx, 16" \ 129 | parm [bx] [ax] [dx] [es di]; 130 | 131 | 132 | #pragma code_seg( _INIT ); 133 | 134 | /* Take a mode descriptor and change it to be a valid 135 | * mode if it isn't already. Return zero if mode needed 136 | * fixing (wasn't valid). 137 | */ 138 | WORD FixModeInfo( LPMODEDESC lpMode ) 139 | { 140 | WORD rc = 1; /* Assume valid mode. */ 141 | 142 | /* First validate bits per pixel. */ 143 | switch( lpMode->bpp ) { 144 | case 8: 145 | case 16: 146 | case 24: 147 | case 32: 148 | break; 149 | default: 150 | lpMode->bpp = 8; /* Default to 8 bpp. */ 151 | rc = 0; /* Mode wasn't valid. */ 152 | } 153 | 154 | /* Validate mode. If resolution is under 640x480 in 155 | * either direction, force 640x480. 156 | */ 157 | if( lpMode->xRes < 640 || lpMode->yRes < 480 ) 158 | { 159 | lpMode->xRes = 640; /* Force 640x480. */ 160 | lpMode->yRes = 480; 161 | rc = 0; /* Mode wasn't valid. */ 162 | } 163 | 164 | /* Clip the resolution to something that probably won't make 165 | * Windows have a cow. 166 | */ 167 | if( lpMode->xRes > RES_MAX_X ) { 168 | lpMode->xRes = RES_MAX_X; 169 | rc = 0; 170 | } 171 | if( lpMode->yRes > RES_MAX_Y ) { 172 | lpMode->yRes = RES_MAX_Y; 173 | rc = 0; 174 | } 175 | 176 | return( rc ); 177 | } 178 | 179 | 180 | /* Calculate pitch for a given horizontal resolution and bpp. */ 181 | WORD CalcPitch( WORD x, WORD bpp ) 182 | { 183 | WORD wPitch; 184 | 185 | /* Valid BPP must be a multiple of 8 so it's simple. */ 186 | wPitch = x * (bpp / 8); 187 | 188 | /* Align to 32 bits. */ 189 | wPitch = (wPitch + 3) & ~3; 190 | 191 | return( wPitch ); 192 | } 193 | 194 | 195 | /* Return non-zero if given mode is supported. */ 196 | static int IsModeOK( WORD wXRes, WORD wYRes, WORD wBpp ) 197 | { 198 | MODEDESC mode; 199 | DWORD dwModeMem; 200 | 201 | mode.bpp = wBpp; 202 | mode.xRes = wXRes; 203 | mode.yRes = wYRes; 204 | 205 | /* If mode needed fixing, it's not valid. */ 206 | if( !FixModeInfo( &mode ) ) 207 | return( 0 ); 208 | 209 | /* Make sure there's enough VRAM for it. */ 210 | dwModeMem = (DWORD)CalcPitch( wXRes, wBpp ) * wYRes; 211 | if( dwModeMem > dwVideoMemorySize ) 212 | return( 0 ); 213 | 214 | return( 1 ); 215 | } 216 | 217 | 218 | /* Clear the visible screen by setting it to all black (zeros). 219 | * NB: Assumes there is no off-screen region to the right of 220 | * the visible area. 221 | */ 222 | static void ClearVisibleScreen( void ) 223 | { 224 | LPDWORD lpScr; 225 | WORD wLines = wScreenY; 226 | WORD i; 227 | 228 | lpScr = ScreenSelector :> 0; 229 | 230 | while( wLines-- ) { 231 | for( i = 0; i < wScreenPitchBytes / 4; ++i ) 232 | lpScr[i] = 0; 233 | lpScr += wScreenPitchBytes; /* Scanline pitch. */ 234 | } 235 | } 236 | 237 | 238 | static DWORD AllocLinearSelector( DWORD dwPhysAddr, DWORD dwSize ) 239 | { 240 | WORD wSel; 241 | DWORD dwLinear; 242 | 243 | wSel = DPMI_AllocLDTDesc( 1 ); /* One descriptor, please. */ 244 | if( !wSel ) 245 | return( 0 ); 246 | 247 | /* Map the framebuffer physical memory. */ 248 | dwLinear = DPMI_MapPhys( dwPhysAddr, dwSize ); 249 | 250 | /* Now set the allocated selector to point to VRAM. */ 251 | DPMI_SetSegBase( wSel, dwLinear ); 252 | DPMI_SetSegLimit( wSel, dwSize - 1 ); 253 | 254 | return( wSel ); 255 | } 256 | 257 | 258 | /* Set the currently configured mode (wXRes/wYRes) in hardware. 259 | * If bFullSet is non-zero, then also reinitialize globals. 260 | * When re-establishing a previously set mode (e.g. coming 261 | * back from fullscreen), bFullSet will be zero. 262 | * NB: BPP won't change at runtime. 263 | */ 264 | static int SetDisplayMode( WORD wXRes, WORD wYRes, int bFullSet ) 265 | { 266 | dbg_printf( "SetDisplayMode: wXRes=%u wYRes=%u\n", wXRes, wYRes ); 267 | 268 | /* Inform the VDD that the mode is about to change. */ 269 | CallVDD( VDD_PRE_MODE_CHANGE ); 270 | 271 | BOXV_ext_mode_set( 0, wXRes, wYRes, wBpp, wXRes, wYRes ); 272 | 273 | if( bFullSet ) { 274 | wScreenX = wXRes; 275 | wScreenY = wYRes; 276 | 277 | wScreenPitchBytes = CalcPitch( wXRes, wBpp ); 278 | BitBltDevProc = NULL; /* No acceleration implemented. */ 279 | wPDeviceFlags = MINIDRIVER | VRAM; 280 | if( wBpp == 16 ) { 281 | wPDeviceFlags |= FIVE6FIVE; /* Needed for 16bpp modes. */ 282 | } 283 | 284 | wMaxWidth = wScreenPitchBytes / (wBpp / 8); /* We know bpp is a multiple of 8. */ 285 | wMaxHeight = dwVideoMemorySize / wScreenPitchBytes; 286 | 287 | /* Offscreen regions could be calculated here. We do not use those. */ 288 | } 289 | return( 1 ); 290 | } 291 | 292 | 293 | /* Forward declaration. */ 294 | void __far RestoreDesktopMode( void ); 295 | 296 | int PhysicalEnable( void ) 297 | { 298 | DWORD dwRegRet; 299 | 300 | if( !ScreenSelector ) { 301 | int iChipID; 302 | 303 | /* Extra work if driver hasn't yet been initialized. */ 304 | iChipID = BOXV_detect( 0, &dwVideoMemorySize ); 305 | if( !iChipID ) { 306 | return( 0 ); 307 | } 308 | dwPhysVRAM = LfbBase; 309 | dbg_printf( "PhysicalEnable: Hardware detected, dwVideoMemorySize=%lX dwPhysVRAM=%lX\n", dwVideoMemorySize, dwPhysVRAM ); 310 | } 311 | 312 | if( !IsModeOK( wScrX, wScrY, wBpp ) ) { 313 | /* Can't find mode, oopsie. */ 314 | dbg_printf( "PhysicalEnable: Mode not valid! wScrX=%u wScrY=%u wBpp=%u\n", wScrX, wScrY, wBpp ); 315 | return( 0 ); 316 | } 317 | 318 | if( !SetDisplayMode( wScrX, wScrY, 1 ) ) { 319 | /* This is not good. */ 320 | dbg_printf( "PhysicalEnable: SetDisplayMode failed! wScrX=%u wScrY=%u wBpp=%u\n", wScrX, wScrY, wBpp ); 321 | return( 0 ); 322 | } 323 | 324 | /* Allocate an LDT selector for the screen. */ 325 | if( !ScreenSelector ) { 326 | ScreenSelector = AllocLinearSelector( dwPhysVRAM, dwVideoMemorySize ); 327 | if( !ScreenSelector ) { 328 | dbg_printf( "PhysicalEnable: AllocScreenSelector failed!\n" ); 329 | return( 0 ); 330 | } 331 | } 332 | 333 | /* NB: Currently not used. DirectDraw would need the segment base. */ 334 | dwScreenFlatAddr = DPMI_GetSegBase( ScreenSelector ); /* Not expected to fail. */ 335 | 336 | dbg_printf( "PhysicalEnable: RestoreDesktopMode is at %WP\n", RestoreDesktopMode ); 337 | dwRegRet = CallVDDRegister( VDD_DRIVER_REGISTER, wScreenPitchBytes, wScreenY, RestoreDesktopMode ); 338 | if( dwRegRet != VDD_DRIVER_REGISTER ) { 339 | /* NB: It's not fatal if CallVDDRegister() fails. */ 340 | /// @todo What can we do with the returned value? 341 | } 342 | 343 | /* Let the VDD know that the mode changed. */ 344 | CallVDD( VDD_POST_MODE_CHANGE ); 345 | CallVDD( VDD_SAVE_DRIVER_STATE ); 346 | 347 | ClearVisibleScreen(); 348 | 349 | return( 1 ); /* All good. */ 350 | } 351 | 352 | 353 | /* Check if the requested mode can be set. Return yes, no (with a reason), 354 | * or maybe. . 355 | * Must be exported by name, recommended ordinal 700. 356 | * NB: Can be called when the driver is not the current display driver. 357 | */ 358 | #pragma aux ValidateMode loadds; /* __loadds not operational due to prototype in valmode.h */ 359 | UINT WINAPI __loadds ValidateMode( DISPVALMODE FAR *lpValMode ) 360 | { 361 | UINT rc = VALMODE_YES; 362 | 363 | dbg_printf( "ValidateMode: X=%u Y=%u bpp=%u\n", lpValMode->dvmXRes, lpValMode->dvmYRes, lpValMode->dvmBpp ); 364 | do { 365 | if( !ScreenSelector ) { 366 | int iChipID; 367 | 368 | /* Additional checks if driver isn't running. */ 369 | iChipID = BOXV_detect( 0, &dwVideoMemorySize ); 370 | if( !iChipID ) { 371 | rc = VALMODE_NO_WRONGDRV; 372 | break; 373 | } 374 | dwPhysVRAM = LfbBase; 375 | dbg_printf( "ValidateMode: Hardware detected, dwVideoMemorySize=%lX dwPhysVRAM=%lX\n", dwVideoMemorySize, dwPhysVRAM ); 376 | } 377 | 378 | if( !IsModeOK( lpValMode->dvmXRes, lpValMode->dvmYRes, lpValMode->dvmBpp ) ) { 379 | rc = VALMODE_NO_NOMEM; 380 | } 381 | } while( 0 ); 382 | 383 | dbg_printf( "ValidateMode: rc=%u\n", rc ); 384 | return( rc ); 385 | } 386 | 387 | #pragma code_seg( _TEXT ); 388 | 389 | /* Called by the VDD in order to restore the video state when switching back 390 | * to the system VM. Function is in locked memory (_TEXT segment). 391 | * NB: Must reload DS, but apparently need not save/restore DS. 392 | */ 393 | #pragma aux RestoreDesktopMode loadds; 394 | void __far RestoreDesktopMode( void ) 395 | { 396 | dbg_printf( "RestoreDesktopMode: %ux%u, wBpp=%u\n", wScreenX, wScreenY, wBpp ); 397 | 398 | /* Set the current desktop mode again. */ 399 | SetDisplayMode( wScreenX, wScreenY, 0 ); 400 | 401 | /* Reprogram the DAC if relevant. */ 402 | if( wBpp <= 8 ) { 403 | UINT wPalCnt; 404 | 405 | switch( wBpp ) { 406 | case 8: 407 | wPalCnt = 256; 408 | break; 409 | case 4: 410 | wPalCnt = 16; 411 | break; 412 | default: 413 | wPalCnt = 2; 414 | break; 415 | } 416 | SetRAMDAC_far( 0, wPalCnt, lpColorTable ); 417 | } 418 | 419 | /* Clear the busy flag. Quite important. */ 420 | lpDriverPDevice->deFlags &= ~BUSY; 421 | 422 | /* Poke the VDD now that everything is restored. */ 423 | CallVDD( VDD_SAVE_DRIVER_STATE ); 424 | 425 | ClearVisibleScreen(); 426 | } 427 | 428 | -------------------------------------------------------------------------------- /palette.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* Display driver palette (RAMDAC) functions. */ 26 | 27 | #include "winhack.h" 28 | #include 29 | #include 30 | #include "minidrv.h" 31 | #include /* For port I/O prototypes. */ 32 | #include "boxvint.h" /* For VGA register definitions. */ 33 | 34 | 35 | /* Load the VGA DAC with values from color table. */ 36 | static void SetRAMDAC( UINT bStart, UINT bCount, RGBQUAD FAR *lpPal ) 37 | { 38 | BYTE bIndex = bStart; 39 | 40 | /* The data format is too weird for BOXV_dac_set(). Do it by hand. */ 41 | outp( VGA_DAC_W_INDEX, bIndex ); /* Set starting index. */ 42 | while( bCount-- ) { 43 | outp( VGA_DAC_DATA, lpPal[bIndex].rgbRed ); 44 | outp( VGA_DAC_DATA, lpPal[bIndex].rgbGreen ); 45 | outp( VGA_DAC_DATA, lpPal[bIndex].rgbBlue ); 46 | ++bIndex; 47 | } 48 | } 49 | 50 | /* Allow calls from the _INIT segment. */ 51 | void __far SetRAMDAC_far( UINT bStart, UINT bCount, RGBQUAD FAR *lpPal ) 52 | { 53 | SetRAMDAC( bStart, bCount, lpPal ); 54 | } 55 | 56 | UINT WINAPI __loadds SetPalette( UINT wStartIndex, UINT wNumEntries, LPVOID lpPalette ) 57 | { 58 | /* Let the DIB engine do what it can. */ 59 | DIB_SetPaletteExt( wStartIndex, wNumEntries, lpPalette, lpDriverPDevice ); 60 | 61 | if( !(lpDriverPDevice->deFlags & BUSY) ) 62 | SetRAMDAC( wStartIndex, wNumEntries, lpColorTable ); 63 | 64 | return( 0 ); 65 | } 66 | -------------------------------------------------------------------------------- /readdev.txt: -------------------------------------------------------------------------------- 1 | Development Notes 2 | ================= 3 | 4 | This Windows 9x display minidriver is almost entirely written in C. It is 5 | a 16-bit DLL running with SS != DS. The compiler switches were carefully 6 | chosen. 7 | 8 | The driver is compiled as small model code and although it uses some C 9 | library functions (e.g. _fmemcpy(), _fmemset()), it does not use the C runtime 10 | startup code at all. 11 | 12 | An interrupt 2Fh handler is written in assembler, and so are forwarders and 13 | thunks directing exported functions to the DIB Engine. The latter could be 14 | written in C, but assembly is significantly more efficient and not at all 15 | complex. 16 | 17 | The driver is by necessity similar to Windows 95/98 DDK sample code, except 18 | it's written almost completely in C whereas the DDK sample drivers are written 19 | 100% in assembly, in the tradition of Windows 3.x and 2.x display drivers. 20 | 21 | Although the driver is a 16-bit DLL, it can freely use 386 instructions, 22 | since it requires a 386 or later CPU by virtue of running on Windows 95 or 23 | later. The driver also can and does use 32-bit registers in some situations. 24 | 25 | The ddk subdirectory contains files which are directly derived from the 26 | Win9x DDK. The DDK is not used or required to build this driver, although DDK 27 | documentation is very useful in understanding the code. Note that the Windows 28 | 9x DDK documentation may not cover topics documented in the Windows 3.x DDKs. 29 | 30 | The original DDK drivers are split into two code segments, _TEXT and _INIT. 31 | This driver also uses those segments, but they are combined into a single 32 | physical segment by the linker. This simplifies the code (e.g. no problem with 33 | near calls into the C runtime) and given the small size of the driver, likely 34 | is not at all disadvantageous overall. 35 | 36 | Note that the driver written in C is actually smaller (about 7KB vs. 8KB) 37 | than the assembler-only DDK sample. The C code is smarter and does not waste 38 | space on tables full of zeros and such, enabling it to be overall smaller even 39 | with the overhead of a higher level language. 40 | 41 | 42 | Debug Logging 43 | ------------- 44 | 45 | When built with DBGPRINT (e.g. wmake clean && wmake DBGPRINT=1), the driver 46 | includes debug logging implemented as dbg_printf() function. This is a small 47 | printf() subset with output directed to the QEMU debug port, such that 48 | the output appears on the debug console (supply "-debugcon stdio" to QEMU). 49 | 50 | It would be much nicer to use the C runtime printf(), but that is not at all 51 | possible because the small model library printf() cannot operate with SS != DS 52 | and is thus unusable, even if all other, less showstopping problems were 53 | overcome. 54 | 55 | See driver code for dbg_printf() usage examples. 56 | 57 | 58 | Building with Open Watcom 1.9 59 | ----------------------------- 60 | 61 | The driver source was slightly adapted so that it builds with the released 62 | Open Watcom C/C++ 1.9 compiler. 63 | 64 | The only real issue is that the ms2wlink utility shipped with Open Watcom 65 | version 1.9 cannot correctly process boxv9x.def, and therefore a working 66 | boxv9x.lnk file is supplied. 67 | 68 | The build process was only tested on Windows 10 hosts. It should work, 69 | possibly with minor adaptations, on other platforms as well. That includes 70 | Windows 9x hosts. 71 | 72 | The step of building a floppy image is optional and requires the mkimage 73 | utility (part of the OS/2 Museum's fdimg project) which is not included. 74 | 75 | 76 | Replacing Active Driver 77 | ----------------------- 78 | 79 | Once the boxvmini.drv driver is installed, it cannot be replaced while 80 | Windows 9x is running because the file is locked. It can be replaced in safe 81 | mode or command line boot (F8 key early in Win9x startup). 82 | 83 | It can also be replaced by shutting down Windows 9x (not Windows Me) to 84 | MS-DOS compatibility mode, copying over boxvmini.drv to the WINDOWS\SYSTEM 85 | directory, and exiting back to Windows. 86 | 87 | It is always possible to use the driver update dialog to install a rebuilt 88 | driver, but that requires more clicking and Windows must be restarted 89 | anyway. 90 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | This is a display minidriver for the Windows 9x family of operating systems, 2 | designed to run on the virtual hardware provided by QEMU ("-device VGA"). 3 | 4 | The driver can be installed through the Display Settings dialog or through 5 | the Device Manager. 6 | 7 | Supported color depths are 8/16/24/32 bits per pixel. The driver supports 8 | many common resolutions, limited by the available video memory (VRAM). 9 | 10 | The driver does not have a built in list of modes. It will set more or less 11 | any resolution between 640x480 and 5120x3840. The INF file determines the 12 | set of predefined modes. By editing the INF file or the resolution information 13 | copied into the Registry, users can add or remove available modes. 14 | -------------------------------------------------------------------------------- /res/colortab.c: -------------------------------------------------------------------------------- 1 | #include "winhack.h" 2 | #include 3 | 4 | /* Color table for the Control Panel. */ 5 | 6 | typedef struct { 7 | WORD wCount; 8 | RGBQUAD rgbColors[]; 9 | } COLORTABLE; 10 | 11 | COLORTABLE ColorTbl = { 12 | 48, /* Number of entries in table. */ 13 | 0xFF, 0x80, 0x80, 0, 14 | 0xFF, 0xFF, 0xE8, 0, 15 | 0x80, 0xFF, 0x80, 0, 16 | 0x00, 0xFF, 0x80, 0, 17 | 0x80, 0xFF, 0xFF, 0, 18 | 0x00, 0x80, 0xFF, 0, 19 | 0xFF, 0x80, 0xC0, 0, 20 | 0xFF, 0x80, 0xFF, 0, 21 | 0xFF, 0x00, 0x00, 0, 22 | 0xFF, 0xFF, 0x80, 0, 23 | 0x80, 0xFF, 0x00, 0, 24 | 0x00, 0xFF, 0x40, 0, 25 | 0x00, 0xFF, 0xFF, 0, 26 | 0x00, 0x80, 0xC0, 0, 27 | 0x80, 0x80, 0xC0, 0, 28 | 0xFF, 0x00, 0xFF, 0, 29 | 0x80, 0x40, 0x40, 0, 30 | 0xFF, 0xFF, 0x00, 0, 31 | 0x00, 0xFF, 0x00, 0, 32 | 0x00, 0x80, 0x80, 0, 33 | 0x00, 0x40, 0x80, 0, 34 | 0x80, 0x80, 0xFF, 0, 35 | 0x80, 0x00, 0x40, 0, 36 | 0xFF, 0x00, 0x80, 0, 37 | 0x80, 0x00, 0x00, 0, 38 | 0xFF, 0x80, 0x00, 0, 39 | 0x00, 0x80, 0x00, 0, 40 | 0x00, 0x80, 0x40, 0, 41 | 0x00, 0x00, 0xFF, 0, 42 | 0x00, 0x00, 0xA0, 0, 43 | 0x80, 0x00, 0x80, 0, 44 | 0x80, 0x00, 0xFF, 0, 45 | 0x40, 0x00, 0x00, 0, 46 | 0x80, 0x40, 0x00, 0, 47 | 0x00, 0x40, 0x00, 0, 48 | 0x00, 0x40, 0x40, 0, 49 | 0x00, 0x00, 0x80, 0, 50 | 0x00, 0x00, 0x40, 0, 51 | 0x40, 0x00, 0x40, 0, 52 | 0x40, 0x00, 0x80, 0, 53 | 0x00, 0x00, 0x00, 0, 54 | 0x80, 0x80, 0x00, 0, 55 | 0x80, 0x80, 0x40, 0, 56 | 0x80, 0x80, 0x80, 0, 57 | 0x40, 0x80, 0x80, 0, 58 | 0xC0, 0xC0, 0xC0, 0, 59 | 0x82, 0x82, 0x82, 0, 60 | 0xFF, 0xFF, 0xFF, 0 61 | }; 62 | 63 | -------------------------------------------------------------------------------- /res/config.c: -------------------------------------------------------------------------------- 1 | #include "winhack.h" 2 | #include 3 | 4 | /* Typedef from Windows 3.1 DDK. */ 5 | 6 | typedef struct { 7 | 8 | /* machine-dependent parameters */ 9 | short VertThumHeight; /* vertical thumb height (in pixels) */ 10 | short HorizThumWidth; /* horizontal thumb width (in pixels) */ 11 | short IconXRatio; /* icon width (in pixels) */ 12 | short IconYRatio; /* icon height (in pixels) */ 13 | short CurXRatio; /* cursor width (in pixels) */ 14 | short CurYRatio; /* cursor height (in pixels) */ 15 | short Reserved; /* reserved */ 16 | short XBorder; /* vertical-line width */ 17 | short YBorder; /* horizontal-line width */ 18 | 19 | /* default-system color values */ 20 | RGBQUAD clrScrollbar; 21 | RGBQUAD clrDesktop; 22 | RGBQUAD clrActiveCaption; 23 | RGBQUAD clrInactiveCaption; 24 | RGBQUAD clrMenu; 25 | RGBQUAD clrWindow; 26 | RGBQUAD clrWindowFrame; 27 | RGBQUAD clrMenuText; 28 | RGBQUAD clrWindowText; 29 | RGBQUAD clrCaptionText; 30 | RGBQUAD clrActiveBorder; 31 | RGBQUAD clrInactiveBorder; 32 | RGBQUAD clrAppWorkspace; 33 | RGBQUAD clrHiliteBk; 34 | RGBQUAD clrHiliteText; 35 | RGBQUAD clrBtnFace; 36 | RGBQUAD clrBtnShadow; 37 | RGBQUAD clrGrayText; 38 | RGBQUAD clrBtnText; 39 | RGBQUAD clrInactiveCaptionText; 40 | } CONFIG_BIN; 41 | 42 | 43 | CONFIG_BIN Config = { 44 | 17, 45 | 17, 46 | 2, 47 | 2, 48 | 1, 49 | 1, 50 | 0, 51 | 1, 52 | 1, 53 | 54 | 192, 192, 192, 0, 55 | 192, 192, 192, 0, 56 | 000, 000, 128, 0, 57 | 255, 255, 255, 0, 58 | 255, 255, 255, 0, 59 | 255, 255, 255, 0, 60 | 000, 000, 000, 0, 61 | 000, 000, 000, 0, 62 | 000, 000, 000, 0, 63 | 255, 255, 255, 0, 64 | 192, 192, 192, 0, 65 | 192, 192, 192, 0, 66 | 255, 255, 255, 0, 67 | 000, 000, 128, 0, 68 | 255, 255, 255, 0, 69 | 192, 192, 192, 0, 70 | 128, 128, 128, 0, 71 | 192, 192, 192, 0, 72 | 000, 000, 000, 0, 73 | 000, 000, 000, 0 74 | }; 75 | -------------------------------------------------------------------------------- /res/display.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Windows 9x minidriver resource file. 3 | * Most of the contents is defined by backward compatibility 4 | * requirements. Much of the detail is explained in the Windows 3.x 5 | * and 2.x DDKs. 6 | */ 7 | 8 | #include "windows.h" 9 | #include "display.rcv" 10 | 11 | 1 oembin PRELOAD config.bin 12 | 2 oembin colortab.bin 13 | 3 oembin PRELOAD fonts.bin 14 | fonts oembin fonts.bin 15 | 16 | 2003 oembin PRELOAD fonts120.bin 17 | -------------------------------------------------------------------------------- /res/display.rcv: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Macros for use in the version resource. */ 4 | 5 | #define VER_FILETYPE VFT_DRV 6 | #define VER_FILESUBTYPE VFT2_DRV_DISPLAY 7 | #define VER_FILEDESCRIPTION_STR "Windows 9x Display Minidriver" 8 | #define VER_INTERNALNAME_STR "DISPLAY" 9 | #define VER_LEGALCOPYRIGHT_YEARS "2012-2022" 10 | #define VER_ORIGINALFILENAME_STR "boxvmini.drv" 11 | #define VER_LEGALCOPYRIGHT_STR "Copyright \251 The OS/2 Museum " VER_LEGALCOPYRIGHT_YEARS 12 | #define VER_COMPANYNAME_STR "OS/2 Museum\0" 13 | 14 | #define VER_PRODUCTNAME_STR "Windows 9x Display Driver\0" 15 | #define VER_PRODUCTVERSION 2,00,0,1 16 | #define VER_PRODUCTVERSION_STR "2.00.1\0" 17 | 18 | #define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 19 | 20 | #ifdef DEBUG 21 | #define VER_FILEFLAGS VS_FF_DEBUG 22 | #else 23 | #define VER_FILEFLAGS 0 24 | #endif 25 | 26 | #define VER_FILEOS VOS_DOS_WINDOWS16 27 | 28 | #ifndef VER_FILEVERSION 29 | #define VER_FILEVERSION VER_PRODUCTVERSION 30 | #endif 31 | 32 | #ifndef VER_FILEVERSION_STR 33 | #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR 34 | #endif 35 | 36 | /* Actual version resource structure. */ 37 | 38 | VS_VERSION_INFO VERSIONINFO 39 | FILEVERSION VER_FILEVERSION 40 | PRODUCTVERSION VER_PRODUCTVERSION 41 | FILEFLAGSMASK VER_FILEFLAGSMASK 42 | FILEFLAGS VER_FILEFLAGS 43 | FILEOS VER_FILEOS 44 | FILETYPE VER_FILETYPE 45 | FILESUBTYPE VER_FILESUBTYPE 46 | BEGIN 47 | BLOCK "StringFileInfo" 48 | BEGIN 49 | BLOCK "040904E4" 50 | BEGIN 51 | VALUE "CompanyName" , VER_COMPANYNAME_STR 52 | VALUE "FileDescription" , VER_FILEDESCRIPTION_STR 53 | VALUE "FileVersion" , VER_FILEVERSION_STR 54 | VALUE "InternalName" , VER_INTERNALNAME_STR 55 | VALUE "LegalCopyright" , VER_LEGALCOPYRIGHT_STR 56 | VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR 57 | VALUE "ProductName" , VER_PRODUCTNAME_STR 58 | VALUE "ProductVersion" , VER_PRODUCTVERSION_STR 59 | END 60 | 61 | #ifdef INTL 62 | BLOCK "040904E4" 63 | BEGIN 64 | VALUE "CompanyName" , VER_COMPANYNAME_STR 65 | VALUE "FileDescription" , VER_FILEDESCRIPTION_STR 66 | VALUE "FileVersion" , VER_FILEVERSION_STR 67 | VALUE "InternalName" , VER_INTERNALNAME_STR 68 | VALUE "LegalCopyright" , VER_LEGALCOPYRIGHT_STR 69 | VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR 70 | VALUE "ProductName" , VER_PRODUCTNAME_STR 71 | VALUE "ProductVersion" , VER_PRODUCTVERSION_STR 72 | END 73 | #endif 74 | END 75 | 76 | BLOCK "VarFileInfo" 77 | BEGIN 78 | VALUE "Translation", 0x0409, 0x04E4 /* Needs updating. */ 79 | END 80 | END 81 | 82 | -------------------------------------------------------------------------------- /res/fonts.c: -------------------------------------------------------------------------------- 1 | /* Standard font resource for 96 DPI. */ 2 | 3 | #define OEM_FNT_HEIGHT 12 4 | #define OEM_FNT_WIDTH 8 5 | 6 | #include "fonttmpl.c" 7 | -------------------------------------------------------------------------------- /res/fonts120.c: -------------------------------------------------------------------------------- 1 | /* Font resource for 120 DPI. */ 2 | 3 | #define OEM_FNT_HEIGHT 10 4 | #define OEM_FNT_WIDTH 20 5 | 6 | #include "fonttmpl.c" 7 | -------------------------------------------------------------------------------- /res/fonttmpl.c: -------------------------------------------------------------------------------- 1 | #include "winhack.h" 2 | /* Trick to get a variable-size LOGFONT structure. */ 3 | #define LF_FACESIZE 4 | #include 5 | 6 | LOGFONT OEMFixed = { 7 | OEM_FNT_HEIGHT, 8 | OEM_FNT_WIDTH, 9 | 0, 10 | 0, 11 | 0, 12 | 0, 13 | 0, 14 | 0, 15 | 255, /* Charset. */ 16 | 0, 17 | 2, /* Clip precision. */ 18 | 2, /* Quality. */ 19 | 1, /* Pitch. */ 20 | "Terminal" /* Font face. */ 21 | }; 22 | 23 | LOGFONT ANSIFixed = { 24 | 12, /* Width. */ 25 | 9, /* Height. */ 26 | 0, 27 | 0, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | 0, /* Charset. */ 33 | 0, 34 | 2, /* Clip precision. */ 35 | 2, /* Quality. */ 36 | 1, /* Pitch. */ 37 | "Courier" /* Font face. */ 38 | }; 39 | 40 | LOGFONT ANSIVar = { 41 | 12, /* Width. */ 42 | 9, /* Height. */ 43 | 0, 44 | 0, 45 | 0, 46 | 0, 47 | 0, 48 | 0, 49 | 0, /* Charset. */ 50 | 0, 51 | 2, /* Clip precision. */ 52 | 2, /* Quality. */ 53 | 2, /* Pitch. */ 54 | "Helv" /* Font face. */ 55 | }; 56 | -------------------------------------------------------------------------------- /scrsw.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | 3 | Copyright (c) 2022 Michal Necasek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | *****************************************************************************/ 24 | 25 | /* Screen switching support (C code). */ 26 | 27 | #include "winhack.h" 28 | #include 29 | #include 30 | #include "minidrv.h" 31 | 32 | /* SwitchFlags bits. */ 33 | #define PREVENT_SWITCH 0x80 /* Don't allow screen switching. */ 34 | #define INT_2F_HOOKED 0x01 /* INT 2Fh is hooked. */ 35 | 36 | /* Accessed from sswhook.asm. */ 37 | BYTE SwitchFlags = 0; /* Screen switch flags, see above. */ 38 | 39 | static BOOL bNoRepaint = 0; /* Set when USER disables repaints. */ 40 | static BOOL bPaintPending = 0; /* Set when repaint was postponed.*/ 41 | 42 | FARPROC RepaintFunc = 0; /* Address of repaint callback. */ 43 | 44 | /* Screen switch hook for INT 2Fh. */ 45 | extern void __far SWHook( void ); 46 | 47 | 48 | /* Repaint screen or postpone for later. 49 | * Internal near call. 50 | */ 51 | void RepaintScreen( void ) 52 | { 53 | dbg_printf( "RepaintScreen: RepaintFunc=%WP, bNoRepaint=%u\n", RepaintFunc, bNoRepaint ); 54 | /* Do we have a repaint callback? */ 55 | if( RepaintFunc ) { 56 | /* Either do the work or set the pending flag. */ 57 | if( !bNoRepaint ) 58 | RepaintFunc(); 59 | else 60 | bPaintPending = TRUE; 61 | } 62 | } 63 | 64 | /* This function is exported as DISPLAY.500 and called by USER 65 | * to inform the driver that screen repaint requests should not 66 | * be sent. When we need to repaint while repaints are disabled, 67 | * we set an internal flag and do the redraw as soon as repaints 68 | * are enabled again. 69 | */ 70 | VOID WINAPI __loadds UserRepaintDisable( BOOL bDisable ) 71 | { 72 | bNoRepaint = bDisable; 73 | if( !bDisable && bPaintPending ) { 74 | RepaintScreen(); 75 | bPaintPending = 0; 76 | } 77 | } 78 | 79 | /* Called from INT 2Fh hook when the device is switching to the 80 | * background and needs to disable drawing. 81 | * Internal near call. 82 | */ 83 | void SwitchToBgnd( void ) 84 | { 85 | dbg_printf( "SwitchToBgnd\n" ); 86 | 87 | lpDriverPDevice->deFlags |= BUSY; /// @todo Does this need to be a locked op? 88 | } 89 | 90 | /* Called from INT 2Fh hook when the device is switching to the 91 | * foreground and needs re-enable drawing, repaiting the screen 92 | * and possibly restoring the display mode. 93 | * Internal near call. 94 | */ 95 | void SwitchToFgnd( void ) 96 | { 97 | dbg_printf( "SwitchToFgnd\n" ); 98 | 99 | /* If the PDevice is busy, we need to reset the display mode. */ 100 | if( lpDriverPDevice->deFlags & BUSY ) 101 | RestoreDesktopMode(); /* Will clear the BUSY flag. */ 102 | RepaintScreen(); 103 | } 104 | 105 | /* This minidriver does not currently disable or enable switching. 106 | * Should the functions be needed, they can be enabled. 107 | */ 108 | #if 0 109 | 110 | /* Called to prevent screen switching. 111 | * Internal near call. 112 | */ 113 | void ScrSwDisable( void ) 114 | { 115 | int_2Fh( ENTER_CRIT_REG ); 116 | SwitchFlags |= PREVENT_SWITCH; 117 | } 118 | 119 | /* Called to re-enable screen switching again. 120 | * Internal near call. 121 | */ 122 | void ScrSwEnable( void ) 123 | { 124 | int_2Fh( EXIT_CRIT_REG ); 125 | SwitchFlags &= ~PREVENT_SWITCH; 126 | } 127 | 128 | #endif 129 | 130 | #pragma code_seg( _INIT ) 131 | 132 | /* The pointer is in the code (_TEXT) segment, not data segment. 133 | * Defined in sswhook.asm. 134 | */ 135 | extern void __far * __based( __segname( "_TEXT" ) ) OldInt2Fh; 136 | 137 | 138 | /* Call DOS to get an interrupt vector. */ 139 | void __far *DOSGetIntVec( BYTE bIntNo ); 140 | #pragma aux DOSGetIntVec = \ 141 | "mov ah, 35h" \ 142 | "int 21h" \ 143 | parm [al] value [es bx]; 144 | 145 | /* Call DOS to set an interrupt vector. */ 146 | void DOSSetIntVec( BYTE bIntNo, void __far *NewVector ); 147 | #pragma aux DOSSetIntVec = \ 148 | "mov ah, 25h" \ 149 | "push ds" \ 150 | "push es" \ 151 | "pop ds" \ 152 | "int 21h" \ 153 | "pop ds" \ 154 | parm [al] [es dx]; 155 | 156 | 157 | /* Ordinal of the repaint callback in USER. Of course undocumented. */ 158 | #define REPAINT_ORDINAL 275 159 | 160 | /* Fun times. Undocumented function to create a writable alias of a code 161 | * selector. In MS KB Q67165, Microsoft claimed that the function "is not 162 | * documented and will not be supported in future versions of Windows". 163 | * Clearly they lied, as it happily works on Win9x. 164 | */ 165 | extern UINT WINAPI AllocCStoDSAlias( UINT selCode ); 166 | 167 | /* Internal function to install INT 2Fh hook. */ 168 | void HookInt2Fh( void ) 169 | { 170 | WORD selAlias; 171 | void __far * __far *OldInt2FhAlias; /* This is fun! */ 172 | 173 | /* If not already set, get repaing callback from USER. */ 174 | if( !RepaintFunc ) { 175 | HMODULE hMod; 176 | 177 | hMod = GetModuleHandle( "USER" ); 178 | RepaintFunc = GetProcAddress( hMod, (LPCSTR)REPAINT_ORDINAL ); 179 | } 180 | dbg_printf( "HookInt2Fh: RepaintFunc=%WP\n", RepaintFunc ); 181 | 182 | /* Now hook INT 2Fh. Since the address of the previous INT 2Fh handler 183 | * is in the code segment, we have to create a writable alias. Just 184 | * a little tricky. 185 | */ 186 | selAlias = AllocCStoDSAlias( (__segment)&OldInt2Fh ); 187 | 188 | SwitchFlags |= INT_2F_HOOKED; 189 | /* Build a pointer to OldInt2Fh using the aliased selector. */ 190 | OldInt2FhAlias = selAlias :> (WORD)&OldInt2Fh; 191 | *OldInt2FhAlias = DOSGetIntVec( 0x2F ); 192 | DOSSetIntVec( 0x2F, SWHook ); 193 | 194 | FreeSelector( selAlias ); 195 | } 196 | 197 | /* Internal function to unhook INT 2Fh. */ 198 | void UnhookInt2Fh( void ) 199 | { 200 | if( SwitchFlags & INT_2F_HOOKED ) { 201 | /* We have INT 2Fh hooked, undo that. */ 202 | SwitchFlags &= ~INT_2F_HOOKED; 203 | DOSSetIntVec( 0x2F, OldInt2Fh ); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /sswhook.asm: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ; 3 | ; Copyright (c) 2022 Michal Necasek 4 | ; 5 | ; Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ; of this software and associated documentation files (the "Software"), to deal 7 | ; in the Software without restriction, including without limitation the rights 8 | ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ; copies of the Software, and to permit persons to whom the Software is 10 | ; furnished to do so, subject to the following conditions: 11 | ; 12 | ; The above copyright notice and this permission notice shall be included in 13 | ; all copies or substantial portions of the Software. 14 | ; 15 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | ; THE SOFTWARE. 22 | ; 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 24 | 25 | ; Screen switching hook written in assembler. 26 | 27 | ; See minidrv.h for more. 28 | SCREEN_SWITCH_OUT equ 4001h 29 | SCREEN_SWITCH_IN equ 4002h 30 | 31 | ; Defined by us, must match minidrv.h 32 | PREVENT_SWITCH equ 80h 33 | 34 | ; Carry flag bit on the stack 35 | FLAG_CF equ 0001h 36 | 37 | public _OldInt2Fh 38 | public SWHook_ 39 | 40 | ; Callbacks written in C 41 | extrn SwitchToBgnd_ : far 42 | extrn SwitchToFgnd_ : far 43 | 44 | _DATA segment public 'DATA' 45 | 46 | ; Defined in C code 47 | extrn _SwitchFlags : byte 48 | 49 | ; Dispatch table. Only used locally. 50 | dsp_tbl label word 51 | dw SwitchToBgnd_ ; SCREEN_SWITCH_OUT handler 52 | dw SwitchToFgnd_ ; SCREEN_SWITCH_IN handler 53 | 54 | _DATA ends 55 | 56 | DGROUP group _DATA 57 | 58 | _TEXT segment public 'CODE' 59 | 60 | ; Defined in code segment so that we can chain to the old interrupt 61 | ; handler without needing to mess with DS. 62 | _OldInt2Fh dd 0 63 | 64 | .386 65 | 66 | ; Screen switching hook for INT 2Fh. We need to handle screen switch 67 | ; notifications ourselves and let the previous handler deal with the 68 | ; rest. 69 | SWHook_ proc far 70 | 71 | ; Cannot assume anything 72 | assume ds:nothing, es:nothing 73 | 74 | ; Check if the subfunction is one of those we're 75 | ; interested in and chain to previous handler if not. 76 | cmp ax, SCREEN_SWITCH_OUT 77 | jz handle_fn 78 | cmp ax, SCREEN_SWITCH_IN 79 | jz handle_fn 80 | jmp _OldInt2Fh ; Registers undisturbed (except flags) 81 | 82 | ; We are going to handle this interrupt and not chain. 83 | handle_fn: 84 | push ds ; Save what we can 85 | pushad 86 | 87 | ; Establish data segment addressing 88 | mov bx, _DATA ; We'll overwrite BX later 89 | mov ds, bx 90 | assume ds:DGROUP 91 | 92 | mov bx, ax ; We will need the function later 93 | mov bp, sp ; So we can address stack 94 | 95 | ; See if switching is disabled 96 | mov al, _SwitchFlags 97 | test al, PREVENT_SWITCH 98 | jz dispatch ; If not set, do do the work 99 | 100 | ; It's disabled; set carry flag and return. 101 | 102 | ; To get to the saved flags, we need to skip the 103 | ; return address (4 bytes), saved DS (2 bytes), and 104 | ; saved registers (8 * 4 bytes) 105 | FLG_OFS equ 4 + 2 + 8 * 4 106 | 107 | or word ptr [bp + FLG_OFS], FLAG_CF 108 | jmp exit 109 | 110 | ; Screen switching is not disabled; clear carry flag, 111 | ; process the screen switch notification, and return. 112 | dispatch: 113 | and word ptr [bp + FLG_OFS], NOT FLAG_CF 114 | and bx, 2 ; Bit 1 of the subfunction 115 | call dsp_tbl[bx] ; Call handler in C 116 | 117 | exit: 118 | popad ; Restore and return 119 | pop ds 120 | iret 121 | 122 | SWHook_ endp 123 | 124 | 125 | _TEXT ends 126 | end 127 | -------------------------------------------------------------------------------- /vxd/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.dll 3 | *.inc 4 | *.exp 5 | *.lib 6 | *.map 7 | *.obj 8 | *.vxd 9 | -------------------------------------------------------------------------------- /vxd/README.txt: -------------------------------------------------------------------------------- 1 | To build this VxD, I used the following toolchain, which I can't redistribute: 2 | 3 | * ML.EXE (Microsoft Macro Assembler Version 6.11d) 4 | * LINK.EXE (Microsoft Incremental Linker Version 5.12.8181) 5 | * MSPDB50.DLL (Needed by the linker; version 6.00.7156) 6 | 7 | All three of these binaries came from the Windows 98 DDK, which is available 8 | on archive.org as a RAR file. The binaries are in BINS_DDK.CAB. 9 | 10 | The following header files are also required, also from the Windows 98 DDK: 11 | 12 | * VMM.INC (timestamp August 3rd, 1998) 13 | * MINIVDD.INC (timestamp August 3rd, 1998) 14 | -------------------------------------------------------------------------------- /vxd/boxvmini.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Mini-VDD VxD for the BOXV9X display driver on QEMU 3 | ; 4 | ; Having this mini-VDD present fixes a couple of problems with the BOXV9X 5 | ; driver. First, it virtualizes accesses to the Bochs VGA registers on I/O 6 | ; ports 1CEh and 1CFh (VBE_DISPI_IOPORT_INDEX and VBE_DISPI_IOPORT_DATA). 7 | ; This means that when you start an MS-DOS Prompt, the screen doesn't go 8 | ; wonky when the DOS VM, calling into the VGA ROM BIOS, ends up trying to 9 | ; perform I/O to those ports. 10 | ; 11 | ; Second, it fixes a problem at Windows shutdown (under KVM and WHPX accel) 12 | ; where the machine hangs instead of showing the "Windows is shutting down" 13 | ; graphic momentarily, and then actually shutting down. 14 | ; 15 | .386p 16 | 17 | .xlist 18 | include VMM.INC 19 | include MINIVDD.INC 20 | .list 21 | 22 | Declare_Virtual_Device \ 23 | BOXVMINI, 4, 0, \ 24 | MiniVDD_Control, \ 25 | Undefined_Device_ID, \ 26 | VDD_Init_Order,,,, 27 | 28 | ; Data segment 29 | VxD_DATA_SEG 30 | 31 | WindowsVMHandle dd ? 32 | 33 | VxD_DATA_ENDS 34 | 35 | ; Init segment (discardable) 36 | VxD_ICODE_SEG 37 | 38 | public MiniVDD_Dynamic_Init 39 | BeginProc MiniVDD_Dynamic_Init 40 | ; 41 | mov WindowsVMHandle, ebx 42 | ; 43 | VxDCall VDD_Get_Mini_Dispatch_Table 44 | MiniVDDDispatch PRE_HIRES_TO_VGA, PreHiResToVGA 45 | MiniVDDDispatch POST_HIRES_TO_VGA, PostHiResToVGA 46 | MiniVDDDispatch ENABLE_TRAPS, EnableTraps 47 | MiniVDDDispatch DISPLAY_DRIVER_DISABLING, DisplayDriverDisabling 48 | ; 49 | mov esi, OFFSET32 MiniVDD_Virtual1CE 50 | mov edx, 1ceh 51 | VMMCall Install_IO_Handler 52 | mov edx, 1ceh 53 | VMMCall Disable_Global_Trapping 54 | ; 55 | mov esi, OFFSET32 MiniVDD_Virtual1CE 56 | mov edx, 1cfh 57 | VMMCall Install_IO_Handler 58 | mov edx, 1cfh 59 | VMMCall Disable_Global_Trapping 60 | ; 61 | clc 62 | ret 63 | EndProc MiniVDD_Dynamic_Init 64 | 65 | public MiniVDD_Init_Complete 66 | BeginProc MiniVDD_Init_Complete 67 | ; 68 | ; At Windows shutdown time, the display driver calls VDD_DRIVER_UNREGISTER, 69 | ; which calls our DisplayDriverDisabling callback, and soon thereafter 70 | ; does an INT 10h (AH=0) to mode 3 (and then 13) in V86 mode. However, the 71 | ; memory ranges for display memory are not always mapped! 72 | ; 73 | ; If the VGA ROM BIOS, during execution of such a set video mode call, tries to 74 | ; clear the screen, and the appropriate memory range isn't mapped, then we end 75 | ; up in a page fault handler, which I guess maps the memory and then resumes 76 | ; execution in V86 mode. But strangely, in QEMU, this fault & resume mechanism 77 | ; does not work with KVM or WHPX assist, at least on Intel. The machine hangs 78 | ; instead (I have not root caused why). 79 | ; 80 | ; We can dodge this problem by setting up real mappings up front. 81 | ; 82 | ; At entry, EBX contains a Windows VM handle. 83 | ; 84 | mov edx, 0A0h 85 | VMMCall _PhysIntoV86, 86 | ; 87 | mov edx, 0B8h 88 | VMMCall _PhysIntoV86, 89 | ; 90 | ret 91 | EndProc MiniVDD_Init_Complete 92 | 93 | VxD_ICODE_ENDS 94 | 95 | ; Fixed segment 96 | VxD_LOCKED_CODE_SEG 97 | 98 | Begin_Control_Dispatch MiniVDD 99 | Control_Dispatch Device_Init, MiniVDD_Dynamic_Init 100 | Control_Dispatch Init_Complete, MiniVDD_Init_Complete 101 | Control_Dispatch Sys_Dynamic_Device_Init, MiniVDD_Dynamic_Init 102 | End_Control_Dispatch MiniVDD 103 | 104 | public MiniVDD_Virtual1CE 105 | BeginProc MiniVDD_Virtual1CE 106 | ; AX/AL contains the value to be read or written on the port. 107 | ; EBX contains the handle of the VM accessing the port. 108 | ; ECX contains the direction (in/out) and size (byte/word) of the operation. 109 | ; EDX contains the port number, which for us will either be 1CEh or 1CFh. 110 | VxDCall VDD_Get_VM_Info 111 | cmp edi, WindowsVMHandle ; Is the CRTC controlled by Windows? 112 | jne _Virtual1CEPhysical ; If not, we should allow the I/O 113 | cmp ebx, edi ; Is the calling VM Windows? 114 | jne _Virtual1CEExit ; If not, we should eat the I/O 115 | _Virtual1CEPhysical: 116 | VxDJmp VDD_Do_Physical_IO 117 | _Virtual1CEExit: 118 | ret 119 | EndProc MiniVDD_Virtual1CE 120 | 121 | public MiniVDD_EnableTraps 122 | BeginProc MiniVDD_EnableTraps 123 | mov edx, 1ceh 124 | VMMCall Enable_Global_Trapping 125 | mov edx, 1cfh 126 | VMMCall Enable_Global_Trapping 127 | ret 128 | EndProc MiniVDD_EnableTraps 129 | 130 | public MiniVDD_PreHiResToVGA 131 | BeginProc MiniVDD_PreHiResToVGA 132 | mov edx, 1ceh 133 | VMMCall Disable_Global_Trapping 134 | mov edx, 1cfh 135 | VMMCall Disable_Global_Trapping 136 | ret 137 | EndProc MiniVDD_PreHiResToVGA 138 | 139 | public MiniVDD_PostHiResToVGA 140 | BeginProc MiniVDD_PostHiResToVGA 141 | mov edx, 1ceh 142 | VMMCall Enable_Global_Trapping 143 | mov edx, 1cfh 144 | VMMCall Enable_Global_Trapping 145 | ret 146 | EndProc MiniVDD_PostHiResToVGA 147 | 148 | public MiniVDD_DisplayDriverDisabling 149 | BeginProc MiniVDD_DisplayDriverDisabling 150 | mov edx, 1ceh 151 | VMMCall Disable_Global_Trapping 152 | mov edx, 1cfh 153 | VMMCall Disable_Global_Trapping 154 | ret 155 | EndProc MiniVDD_DisplayDriverDisabling 156 | 157 | VxD_LOCKED_CODE_ENDS 158 | end 159 | -------------------------------------------------------------------------------- /vxd/boxvmini.def: -------------------------------------------------------------------------------- 1 | VXD BOXVMINI DYNAMIC 2 | DESCRIPTION 'DOS386 BOXVMINI Device (Version 4.0)' 3 | 4 | SEGMENTS 5 | _LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE 6 | _LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE 7 | _ITEXT CLASS 'ICODE' DISCARDABLE 8 | 9 | EXPORTS 10 | BOXVMINI_DDB @1 11 | -------------------------------------------------------------------------------- /vxd/make.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM Assemble 4 | ml -coff -DBLD_COFF -W2 -Zd -c -Cx -DMASM6 -Sg -DVGA -DVGA31 -DMINIVDD=1 -Foboxvmini.obj boxvmini.asm 5 | 6 | REM Link 7 | link /VXD /NOD boxvmini.obj /OUT:boxvmini.vxd /MAP:boxvmini.map /DEF:boxvmini.def 8 | -------------------------------------------------------------------------------- /winhack.h: -------------------------------------------------------------------------------- 1 | /* The gdidefs.h header badly conflicts with windows.h. Microsoft's printer 2 | * drivers in the Windows DDK solve that by manually defining a large subset 3 | * of windows.h. We solve that by including the normal windows.h but hiding 4 | * the conflicting definitions. 5 | */ 6 | #define NOGDI 7 | #define PPOINT n_PPOINT 8 | #define LPPOINT n_LPPOINT 9 | #define RECT n_RECT 10 | #define PRECT n_PRECT 11 | #define LPRECT n_LPRECT 12 | #include 13 | #undef PPOINT 14 | #undef LPPOINT 15 | #undef RECT 16 | #undef PRECT 17 | #undef LPRECT 18 | 19 | --------------------------------------------------------------------------------