# HG changeset patch # User Michal Necasek # Date 1655653157 -7200 # Node ID 20b4ed4eebe3a068828ac93400ede51b93602666 Checked in Windows 9x display minidriver for VirtualBox. diff -r 000000000000 -r 20b4ed4eebe3 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,13 @@ +# Use glob syntax. +syntax: glob + +*.drv +*.sym +*.res +*.bin +*.obj +*.lib +*.map +*.err +dist +boxv9x.img diff -r 000000000000 -r 20b4ed4eebe3 boxv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boxv.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,169 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* Core boxv implementation. */ + +#include "boxv.h" /* Public interface. */ +#include "boxvint.h" /* Implementation internals. */ +#include "boxv_io.h" /* I/O access layer, host specific. */ + + +/* Write a single value to an indexed register at a specified + * index. Suitable for the CRTC or graphics controller. + */ +inline void vid_wridx( void *cx, int idx_reg, int idx, v_byte data ) +{ + vid_outw( cx, idx_reg, idx | (data << 8) ); +} + +/* Set an extended non-VGA mode with given parameters. 8bpp and higher only. + * Returns non-zero value on failure. + */ +int BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres, int v_yres ) +{ + /* Do basic parameter validation. */ + if( v_xres < xres || v_yres < yres ) + return( -1 ); + + /* Put the hardware into a state where the mode can be safely set. */ + vid_inb( cx, VGA_STAT_ADDR ); /* Reset flip-flop. */ + vid_outb( cx, VGA_ATTR_W, 0 ); /* Disable palette. */ + vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR_RESET ); + + /* Disable the extended display registers. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED ); + + /* Program the extended non-VGA registers. */ + + /* Set X resoultion. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, xres ); + /* Set Y resoultion. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, yres ); + /* Set bits per pixel. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, bpp ); + /* Set the virtual resolution. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, v_xres ); + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_HEIGHT ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, v_yres ); + /* Reset the current bank. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BANK ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 ); + /* Set the X and Y display offset to 0. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_X_OFFSET ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 ); + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_Y_OFFSET ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 ); + /* Enable the extended display registers. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC ); + + /* Re-enable the sequencer. */ + vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR0_NORESET ); + + /* Reset flip-flop again and re-enable palette. */ + vid_inb( cx, VGA_STAT_ADDR ); + vid_outb( cx, VGA_ATTR_W, 0x20 ); + + return( 0 ); +} + +/* Program the DAC. Each of the 'count' entries is 4 bytes in size, + * red/green/blue/unused. + * Returns non-zero on failure. + */ +int BOXV_dac_set( void *cx, unsigned start, unsigned count, void *pal ) +{ + v_byte *prgbu = pal; + + /* Basic argument validation. */ + if( start + count > 256 ) + return( -1 ); + + /* Write the starting index. */ + vid_outb( cx, VGA_DAC_W_INDEX, start ); + /* Load the RGB data. */ + while( count-- ) { + vid_outb( cx, VGA_DAC_DATA, *prgbu++ ); + vid_outb( cx, VGA_DAC_DATA, *prgbu++ ); + vid_outb( cx, VGA_DAC_DATA, *prgbu++ ); + ++prgbu; + } + return( 0 ); +} + +/* Detect the presence of a supported adapter and amount of installed + * video memory. Returns zero if not found. + */ +int BOXV_detect( void *cx, unsigned long *vram_size ) +{ + v_word boxv_id; + + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID ); + boxv_id = vid_inw( cx, VBE_DISPI_IOPORT_DATA ); + if( vram_size ) { + *vram_size = vid_ind( cx, VBE_DISPI_IOPORT_DATA ); + } + if( boxv_id >= VBE_DISPI_ID0 && boxv_id <= VBE_DISPI_ID4 ) + return( boxv_id ); + else + return( 0 ); +} + +/* Disable extended mode and place the hardware into a VGA compatible state. + * Returns non-zero on failure. + */ +int BOXV_ext_disable( void *cx ) +{ + /* Disable the extended display registers. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED ); + return( 0 ); +} + +/* Return the physical base address of the framebuffer. Needed in environments + * that do not query the base through PCI. + */ +unsigned long BOXV_get_lfb_base( void *cx ) +{ + unsigned long fb_base; + + /* Ask the virtual hardware for the high 16 bits. */ + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_FB_BASE_HI ); + fb_base = vid_inw( cx, VBE_DISPI_IOPORT_DATA ); + + /* Old versions didn't support that, so use the default + * if the value looks like garbage. + */ + if( fb_base != 0 && fb_base != 0xffff ) + fb_base = fb_base << 16; + else + fb_base = VBE_DISPI_LFB_PHYSICAL_ADDRESS; + + return( fb_base ); +} diff -r 000000000000 -r 20b4ed4eebe3 boxv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boxv.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,49 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* + * Public interface to the boxv library. + */ + +/* PCI vendor and device IDs. */ +#define BOXV_PCI_VEN 0x80EE +#define BOXV_PCI_DEV 0xBEEF + +/* A structure describing mode information. Note: The mode numbers + * usually match VBE, but this should not be relied upon. + */ +typedef struct { + int mode_no; /* Mode number */ + int xres; /* Horizontal resolution */ + int yres; /* Vertical resolution */ + int bpp; /* Color depth */ +} BOXV_mode_t; + +extern void BOXV_mode_enumerate( void *cx, int (cb)( void *cx, BOXV_mode_t *mode ) ); +extern int BOXV_detect( void *cx, unsigned long *vram_size ); +extern int BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres, int v_yres ); +extern int BOXV_mode_set( void *cx, int mode_no ); +extern int BOXV_dac_set( void *cx, unsigned start, unsigned count, void *pal ); +extern int BOXV_ext_disable( void *cx ); +extern unsigned long BOXV_get_lfb_base( void *cx ); diff -r 000000000000 -r 20b4ed4eebe3 boxv9x.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boxv9x.def Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,67 @@ +; +; Standard display driver .DEF file +; +LIBRARY DISPLAY + +; +; The magic numbers are: Aspect ratio, Horizontal DPI, Vertical DPI +; +DESCRIPTION 'DISPLAY : 100, 96, 96 : DIB Engine based Mini display driver.' +EXETYPE WINDOWS + +DATA PRELOAD FIXED SINGLE + +SEGMENTS + _TEXT PRELOAD SHARED + _INIT PRELOAD MOVEABLE + +EXPORTS + BitBlt @1 + ColorInfo @2 + Control @3 + Disable @4 + Enable @5 + EnumDFonts @6 + EnumObj @7 + Output @8 + Pixel @9 + RealizeObject @10 + StrBlt @11 + ScanLR @12 + DeviceMode @13 NODATA + + ExtTextOut @14 + GetCharWidth @15 NODATA + DeviceBitmap @16 NODATA + FastBorder @17 + SetAttribute @18 NODATA + + DibBlt @19 ; Device Independent Bitmap group + CreateDIBitmap @20 + DibToDevice @21 + + SetPalette @22 ; Windows 3.0 palette group + GetPalette @23 + + SetPaletteTranslate @24 + GetPaletteTranslate @25 + UpdateColors @26 + StretchBlt @27 + StretchDIBits @28 + + SelectBitmap @29 + BitmapBits @30 + ReEnable @31 + + Inquire @101 ; Mouse cursor function group + SetCursor @102 + MoveCursor @103 + CheckCursor @104 + + GetDriverResourceID @450 ; Undocumented USER callback + UserRepaintDisable @500 ; Undocumented USER callback + + ValidateMode @700 + +IMPORTS + GlobalSmartPageLock = KERNEL.230 ; Undocumented function diff -r 000000000000 -r 20b4ed4eebe3 boxv9x.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boxv9x.inf Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,118 @@ +; +; INF file for VirtualBox Win9x display driver +; Copyright 2012-2022, The OS/2 Museum + +[version] +Class=DISPLAY +signature="$CHICAGO$" +Provider=%Mfg% + +[DestinationDirs] +DefaultDestDir = 11 ; LDID_SYS +BoxV.Copy = 11 + +[SourceDisksNames] +; BOXV9X is the driver disk volume label +1="VirtualBox Win9x Display Driver Disk",BOXV9X,1 + +[SourceDisksFiles] +boxvmini.drv=1 +;boxvmini.vxd=1 + +[Manufacturer] +%Mfg%=Mfg.BoxV + +[Mfg.BoxV] +%PCI\VEN_80EE&DEV_BEEF.DeviceDesc%=BoxV,PCI\VEN_80EE&DEV_BEEF + +[BoxV] +CopyFiles=BoxV.Copy +DelReg=Prev.DelReg +AddReg=BoxV_AddReg + +[BoxV.Copy] +boxvmini.drv +;boxvmini.vxd + +[Prev.DelReg] +HKR,,Ver +HKR,,DevLoader +HKR,DEFAULT +HKR,MODES +HKR,CURRENT + +[BoxV_AddReg] +HKR,,Ver,,4.0 +HKR,,DevLoader,,*vdd +HKR,DEFAULT,Mode,,"8,640,480" +HKR,DEFAULT,drv,,boxvmini.drv +HKR,DEFAULT,vdd,,"*vdd,*vflatd" +;HKR,DEFAULT,minivdd,,boxvmini.vxd +;HKR,DEFAULT,carddvdd,,cardsamp.vxd +HKR,DEFAULT,RefreshRate,,-1 +HKR,DEFAULT,DDC,,1 +HKR,DEFAULT,ExtModeSwitch,,0 +HKR,"MODES\4\640,480",drv,,vga.drv +HKR,"MODES\4\640,480",vdd,,*vdd +HKR,"MODES\4\800,600",drv,,supervga.drv +HKR,"MODES\4\800,600",vdd,,*vdd +HKR,"MODES\8\640,480" +HKR,"MODES\8\800,600" +HKR,"MODES\8\1024,768" +HKR,"MODES\8\1152,864" +HKR,"MODES\8\1280,720" +HKR,"MODES\8\1280,800" +HKR,"MODES\8\1280,960" +HKR,"MODES\8\1280,1024" +HKR,"MODES\8\1400,1050" +HKR,"MODES\8\1600,1200" +HKR,"MODES\8\1600,900" +HKR,"MODES\8\1680,1050" +HKR,"MODES\8\1920,1080" +HKR,"MODES\8\1920,1200" +HKR,"MODES\16\640,480" +HKR,"MODES\16\800,600" +HKR,"MODES\16\1024,768" +HKR,"MODES\16\1152,864" +HKR,"MODES\16\1280,720" +HKR,"MODES\16\1280,800" +HKR,"MODES\16\1280,960" +HKR,"MODES\16\1280,1024" +HKR,"MODES\16\1400,1050" +HKR,"MODES\16\1600,900" +HKR,"MODES\16\1600,1200" +HKR,"MODES\16\1680,1050" +HKR,"MODES\16\1920,1080" +HKR,"MODES\16\1920,1200" +HKR,"MODES\24\640,480" +HKR,"MODES\24\800,600" +HKR,"MODES\24\1024,768" +HKR,"MODES\24\1152,864" +HKR,"MODES\24\1280,720" +HKR,"MODES\24\1280,800" +HKR,"MODES\24\1280,960" +HKR,"MODES\24\1280,1024" +HKR,"MODES\24\1400,1050" +HKR,"MODES\24\1600,900" +HKR,"MODES\24\1600,1200" +HKR,"MODES\24\1680,1050" +HKR,"MODES\24\1920,1080" +HKR,"MODES\24\1920,1200" +HKR,"MODES\32\640,480" +HKR,"MODES\32\800,600" +HKR,"MODES\32\1024,768" +HKR,"MODES\32\1152,864" +HKR,"MODES\32\1280,720" +HKR,"MODES\32\1280,800" +HKR,"MODES\32\1280,960" +HKR,"MODES\32\1280,1024" +HKR,"MODES\32\1400,1050" +HKR,"MODES\32\1600,900" +HKR,"MODES\32\1600,1200" +HKR,"MODES\32\1680,1050" +HKR,"MODES\32\1920,1080" +HKR,"MODES\32\1920,1200" + +[Strings] +Mfg="VirtualBox" +PCI\VEN_80EE&DEV_BEEF.DeviceDesc="VirtualBox SVGA PCI" diff -r 000000000000 -r 20b4ed4eebe3 boxv9x.lnk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boxv9x.lnk Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,61 @@ +# This file produced by MS2WLINK +system windows dll initglobal +file dibthunk.obj +file dibcall.obj +file enable.obj +file init.obj +file palette.obj +file scrsw.obj +file sswhook.obj +file modes.obj +file boxv.obj +name boxvmini.drv +option map=boxvmini.map +library dibeng.lib +library clibs.lib +option modname=DISPLAY +option description 'DISPLAY : 100, 96, 96 : DIB Engine based Mini display driver.' +option oneautodata +segment type data preload fixed +# definition file segments keyword handled differently in WLINK +segment '_TEXT' preload shared +segment '_INIT' preload moveable +export BitBlt.1 +export ColorInfo.2 +export Control.3 +export Disable.4 +export Enable.5 +export EnumDFonts.6 +export EnumObj.7 +export Output.8 +export Pixel.9 +export RealizeObject.10 +export StrBlt.11 +export ScanLR.12 +export DeviceMode.13 +export ExtTextOut.14 +export GetCharWidth.15 +export DeviceBitmap.16 +export FastBorder.17 +export SetAttribute.18 +export DibBlt.19 +export CreateDIBitmap.20 +export DibToDevice.21 +export SetPalette.22 +export GetPalette.23 +export SetPaletteTranslate.24 +export GetPaletteTranslate.25 +export UpdateColors.26 +export StretchBlt.27 +export StretchDIBits.28 +export SelectBitmap.29 +export BitmapBits.30 +export ReEnable.31 +export Inquire.101 +export SetCursor.102 +export MoveCursor.103 +export CheckCursor.104 +export GetDriverResourceID.450 +export UserRepaintDisable.500 +export ValidateMode.700 +import GlobalSmartPageLock KERNEL.230 diff -r 000000000000 -r 20b4ed4eebe3 boxv_io.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boxv_io.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,67 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +#include /* For port I/O prototypes. */ + +/* The 16-bit compiler does not do inpd(). We have to do it ourselves. + * NB: It might be OK to trash the high bits of EAX but better be safe. + */ +/* Warning: Destroys high bits of EAX. */ +unsigned long inpd( unsigned port ); +#pragma aux inpd = \ + ".386" \ + "push eax" \ + "in eax, dx" \ + "mov dx, ax" \ + "shr eax, 16" \ + "xchg bx, ax" \ + "pop eax" \ + "xchg bx, ax" \ + "xchg ax, dx" \ + parm [dx] value [dx ax] modify [bx] nomemory; + +static void vid_outb( void *cx, unsigned port, unsigned val ) +{ + outp( port, val ); +} + +static void vid_outw( void *cx, unsigned port, unsigned val ) +{ + outpw( port, val ); +} + +static unsigned vid_inb( void *cx, unsigned port ) +{ + return( inp( port ) ); +} + +static unsigned vid_inw( void *cx, unsigned port ) +{ + return( inpw( port ) ); +} + +static unsigned long vid_ind( void *cx, unsigned port ) +{ + return( inpd( port ) ); +} diff -r 000000000000 -r 20b4ed4eebe3 boxvint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boxvint.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,149 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* Internal definitions used by the boxv library. */ + +/*-------------- VGA Specific ----------------*/ + +/* VGA I/O port addresses. */ +#define VGA_CRTC 0x3D4 /* Color only! */ +#define VGA_ATTR_W 0x3C0 +#define VGA_ATTR_R 0x3C1 +#define VGA_MISC_OUT_W 0x3C2 +#define VGA_SEQUENCER 0x3C4 +#define VGA_SEQUENCER_DATA 0x3C5 +#define VGA_PIXEL_MASK 0x3C6 +#define VGA_DAC_W_INDEX 0x3C8 +#define VGA_DAC_DATA 0x3C9 +#define VGA_MISC_OUT_R 0x3CC +#define VGA_GRAPH_CNTL 0x3CE +#define VGA_GRAPH_CNTL_DATA 0x3CF +#define VGA_STAT_ADDR 0x3DA /* Color only! */ + +/* VGA Attribute Controller register indexes. */ +#define VGA_AR_MODE 0x10 +#define VGA_AR_OVERSCAN 0x11 +#define VGA_AR_PLANE_EN 0x12 +#define VGA_AR_PIX_PAN 0x13 +#define VGA_AR_COLOR_SEL 0x14 + +/* VGA Graphics Controller register indexes. */ +#define VGA_GR_SET_RESET 0x00 +#define VGA_GR_DATA_ROTATE 0x03 +#define VGA_GR_READ_MAP_SEL 0x04 +#define VGA_GR_MODE 0x05 +#define VGA_GR_MISC 0x06 +#define VGA_GR_BIT_MASK 0x08 + +/* VGA Sequencer register indexes. */ +#define VGA_SR_RESET 0x00 +#define VGA_SR_CLK_MODE 0x01 +#define VGA_SR_PLANE_MASK 0x02 +#define VGA_SR_MEM_MODE 0x04 + +/* Sequencer constants. */ +#define VGA_SR0_NORESET 0x03 +#define VGA_SR0_RESET 0x00 +#define VGA_SR1_BLANK 0x20 + +/* VGA CRTC register indexes. */ +#define VGA_CR_HORZ_TOTAL 0x00 +#define VGA_CR_CUR_START 0x0A +#define VGA_CR_CUR_END 0x0B +#define VGA_CR_START_HI 0x0C +#define VGA_CR_START_LO 0x0D +#define VGA_CR_CUR_POS_HI 0x0E +#define VGA_CR_CUR_POS_LO 0x0F +#define VGA_CR_VSYNC_START 0x10 +#define VGA_CR_VSYNC_END 0x11 + +/* VGA Input Status Register 1 constants. */ +#define VGA_STAT_VSYNC 0x08 + +/*------------ End VGA Specific --------------*/ + +/*------------- bochs Specific ---------------*/ + +#define VBE_DISPI_BANK_ADDRESS 0xA0000 +#define VBE_DISPI_BANK_SIZE_KB 64 + +#define VBE_DISPI_MAX_XRES 1024 +#define VBE_DISPI_MAX_YRES 768 + +#define VBE_DISPI_IOPORT_INDEX 0x01CE +#define VBE_DISPI_IOPORT_DATA 0x01CF + +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_INDEX_VBOX_VIDEO 0xa +#define VBE_DISPI_INDEX_FB_BASE_HI 0xb + +#define VBE_DISPI_ID0 0xB0C0 +#define VBE_DISPI_ID1 0xB0C1 +#define VBE_DISPI_ID2 0xB0C2 +#define VBE_DISPI_ID3 0xB0C3 +#define VBE_DISPI_ID4 0xB0C4 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_GETCAPS 0x02 +#define VBE_DISPI_8BIT_DAC 0x20 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 + +/* Default LFB base. Might be different! */ +#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 + +/*------------ End bochs Specific -------------*/ + + +typedef unsigned char v_byte; +typedef unsigned short v_word; + +/* A structure describing the contents of VGA registers for a mode set. */ +typedef struct { + v_byte misc; /* Miscellaneous register. */ + v_byte seq[5]; /* Sequencer registers. */ + v_byte crtc[25]; /* CRTC registers. */ + v_byte gctl[9]; /* Graphics controller registers. */ + v_byte atr[21]; /* Attribute registers. */ +} v_vgaregs; + +/* A structure fully describing a graphics or text mode. */ +typedef struct { + int mode_no; /* Internal mode number. */ + int xres; /* Horizontal (X) resolution. */ + int yres; /* Vertical (Y) resolution. */ + int bpp; /* Bits per pixel. */ + int ext; /* Non-zero for extended modes. */ + v_vgaregs *vgaregs; /* Contents of VGA registers. */ +} v_mode; diff -r 000000000000 -r 20b4ed4eebe3 dbgprint.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbgprint.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,228 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* Homegrown printf support. The C runtime printf() is hard to use without + * dragging in much of the library, and much worse, the small model runtime . + * can't operate with SS != DS. So we roll our own very simplified printf() . + * subset, good enough for what we need. . + */ + +#include +#include +#include +#include + + +/* Backdoor logging I/O ports. */ +#define INFO_PORT 0x504 +#define DEBUG_PORT 0x403 + +#pragma code_seg( _INIT ); + +static void prt_ch( char c ) +{ + outp( INFO_PORT, c ); +} + +static void prt_u32( uint32_t val, int width ) +{ + uint32_t uval; + uint32_t base; + char buf[16]; /* It's 12 digits max. */ + int n = 0; + + uval = val; + + do { + base = uval / 10; + buf[n++] = uval - base * 10 + '0'; + uval = base; + } while( uval ); + + /* Pad with spaces. */ + while( width > n ) { + prt_ch( ' ' ); + --width; + } + + do { + prt_ch( buf[--n] ); + } while( n ); +} + +static void prt_i32( int32_t val, int width ) +{ + uint32_t uval; + + if( val < 0 ) { + prt_ch( '-' ); + uval = -val; + if( width > 0 ) + --width; + } else { + uval = val; + } + + prt_u32( uval, width ); +} + +static void prt_hex32( uint32_t val, int width, char hexa ) +{ + char buf[8]; /* Enough for a dword. */ + int n = 0; + int nibble; + + do { + nibble = val & 0xF; + val >>= 4; + buf[n++] = nibble + (nibble > 9 ? hexa - 10 : '0'); + } while( val ); + + /* Pad with zeros. */ + while( width > n ) { + prt_ch( '0' ); + --width; + } + + do { + prt_ch( buf[--n] ); + } while( n ); +} + +static void prt_str( const char __far *s ) +{ + while( *s ) + prt_ch( *s++ ); +} + +void dbg_printf( const char *s, ... ) +{ + char type_len; + char conv; + char hexa; + int width; + uint16_t word; + uint32_t dword; + va_list args; + + va_start( args, s ); + + /* Go until end of format string. */ + while( *s ) { + /* Is it a format specifier? */ + if( *s == '%' ) { + ++s; /* Eat the % sign. */ + conv = 0; + width = 0; + type_len = 0; + + /* Process field width, if any. */ + while( isdigit( *s ) ) { + width *= 10; + width += *s++ - '0'; + } + + /* Process type length specifier, if any. */ + switch( *s ) { + case 'l': /* Long integers. */ + case 'W': /* Far pointers. */ + type_len = *s++; + break; + default: /* Do nothing. */ + break; + } + + /* Now check if a supported conversion is there. */ + switch( *s ) { + case 'c': + case 'd': + case 'u': + case 'p': + case 'P': + case 's': + case 'x': + case 'X': + conv = *s++; + break; + default: /* Do nothing. */ + break; + } + + if( conv ) { + /* Time to start grabbing stuff off the stack. */ + word = va_arg( args, uint16_t ); + /* If argument is double wide, build a doubleword. */ + if( type_len == 'l' || type_len == 'W' ) { + dword = va_arg( args, uint16_t ); + dword <<= 16; + dword |= word; + } + if( conv == 'c' ) { + prt_ch( word ); + } else if( conv == 'd' ) { + if( type_len == 'l' ) + prt_i32( dword, width ); + else + prt_i32( (int16_t)word, width ); + } else if( conv == 'u' ) { + if( type_len == 'l' ) + prt_u32( dword, width ); + else + prt_u32( word, width ); + } else if( conv == 'p' || conv == 'P' ) { + hexa = conv - 'P' + 'A'; + if( type_len == 'W' ) { + prt_hex32( dword >> 16, 4, hexa ); + prt_ch( ':' ); + prt_hex32( word, 4, hexa ); + } else { + prt_hex32( word, 4, hexa ); + } + } else if( conv == 's' ) { + if( type_len == 'W' ) + prt_str( (const char __far *)dword ); + else + prt_str( (const char *)word ); + } else if( conv == 'x' || conv == 'X' ) { + hexa = conv - 'X' + 'A'; + if( type_len == 'l' ) { + if( !width ) + width = 8; + prt_hex32( dword, width, hexa ); + } else { + if( !width ) + width = 4; + prt_hex32( word, width, hexa ); + } + } + } else { + /* Just print whatever is there. */ + prt_ch( *s++ ); + } + } else { + prt_ch( *s++ ); + } + } + va_end( args ); +} diff -r 000000000000 -r 20b4ed4eebe3 ddk/dibeng.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddk/dibeng.def Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,49 @@ +EXPORTS +LIBRARY DIBENG + DIB_BitBlt @1 + DIB_ColorInfo @2 + DIB_Control @3 + DIB_Disable @4 + DIB_Enable @5 + DIB_EnumDFonts @6 + DIB_EnumObj @7 + DIB_Output @8 + DIB_Pixel @9 + DIB_RealizeObject @10 + DIB_StrBlt @11 + DIB_ScanLR @12 + DIB_DeviceMode @13 + DIB_ExtTextOut @14 + DIB_GetCharWidth @15 + DIB_DeviceBitmap @16 + DIB_FastBorder @17 + DIB_SetAttribute @18 + DIB_DibBlt @19 + DIB_CreateDIBitmap @20 + DIB_DibToDevice @21 + DIB_SetPalette @22 + DIB_GetPalette @23 + DIB_SetPaletteTranslate @24 + DIB_GetPaletteTranslate @25 + DIB_UpdateColors @26 + DIB_StretchBlt @27 + DIB_StretchDIBits @28 + DIB_SelectBitmap @29 + DIB_BitmapBits @30 + DIB_Inquire @101 + DIB_SetCursorExt @102 + DIB_MoveCursorExt @103 + DIB_CheckCursorExt @104 + DIB_BeginAccess @105 + DIB_EndAccess @106 + CreateDIBPDevice @300 + DIB_RealizeObjectExt @400 + DIB_DibBltExt @401 + DIB_EnumObjExt @402 + DIB_ExtTextOutExt @403 + DIB_UpdateColorsExt @404 + DIB_SetPaletteExt @405 + DIB_GetPaletteExt @406 + DIB_SetPaletteTranslateExt @407 + DIB_GetPaletteTranslateExt @408 + diff -r 000000000000 -r 20b4ed4eebe3 ddk/dibeng.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddk/dibeng.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,242 @@ +/* DIB Engine interface. */ + +#define BRUSHSIZE 8 +#define VER_DIBENG 0x400 +#define TYPE_DIBENG 0x5250 /* 'RP' */ + +#define deCursorExclude deBeginAccess +#define deCursorUnexclude deEndAccess + +/* DIB Engine PDevice structure. The deType field will be 'DI' when GDI + * calls the Engine; deType will be null or a selector if a minidriver is + * calls the DIB Engine. + */ +typedef struct { + WORD deType; /* TYPE_DIBENG or zero. */ + WORD deWidth; /* DIB width in pixels. */ + WORD deHeight; /* DIB height in pixels. */ + WORD deWidthBytes; /* Scanline length in bytes. */ + BYTE dePlanes; /* Number of bit planes. */ + BYTE deBitsPixel; /* Number of bits per pixel. */ + DWORD deReserved1; /* Not used. */ + DWORD deDeltaScan; /* Scanline delta, can be negative.*/ + LPBYTE delpPDevice; /* Associated PDevice pointer. */ + DWORD deBitsOffset; /* 48-bit pointer to */ + WORD deBitsSelector; /* DIB bits storage. */ + WORD deFlags; /* More flags. */ + WORD deVersion; /* Major/minor (0400h = 4.0). */ + LPBITMAPINFO deBitmapInfo; /* Bitmapinfo header pointer. */ + void (WINAPI *deBeginAccess)(); /* Surface access begin callback. */ + void (WINAPI *deEndAccess)(); /* Surface access end callback. */ + DWORD deDriverReserved; /* Reserved for minidrivers. */ +} DIBENGINE, FAR *LPDIBENGINE; + +/* DIBEngine.deFlags */ +#define MINIDRIVER 0x0001 /* Mini display driver. */ +#define PALETTIZED 0x0002 /* Has a palette. */ +#define SELECTEDDIB 0x0004 /* DIB Section. */ +#define OFFSCREEN 0x0008 /* Offscreen surface in VRAM. */ +#define BUSY 0x0010 /* Busy. */ +#define NOT_FRAMEBUFFER 0x0020 /* No FB access (like 8514/A). */ +#define FIVE6FIVE 0x0040 /* 5-6-5 16bpp mode. */ +#define NON64KBANK 0x0080 /* Bank size != 64K. */ +#define VRAM 0x8000 /* Have VRAM access. */ +#define BANKEDVRAM 0x4000 /* VFlatD simulating LFB. */ +#define BANKEDSCAN 0x2000 /* VFlatD with scanlines crossing banks. */ +#define PALETTE_XLAT 0x1000 /* Bkgnd palette translation. */ +#define VGADITHER 0x0800 /* Dither to VGA colors. */ +#define CTCHANGE 0x0400 /* Color table changed/ */ +#define DITHER256 0x0200 /* Dither to 256 colors. */ + +#define BUSY_BIT 4 /* Number of bit to test for busy. */ + +/* DIB_Brush??.dp??BrushFlags */ +#define COLORSOLID 0x01 /* Color part solid. */ +#define MONOSOLID 0x02 /* Mono part solid. */ +#define PATTERNMONO 0x04 /* Brush originated from mono bitmap. */ +#define MONOVALID 0x08 /* Mono part valid. */ +#define MASKVALID 0x10 /* Mask valid. */ +#define PRIVATEDATA 0x20 /* Vendor defined bit. */ + +/* Fake typedefs to avoid conflicts between windows.h and gdidefs.h. */ +typedef LPVOID LPPDEVICE; +typedef LPVOID LPPPEN; +typedef LPVOID LPPBRUSH; +typedef LPVOID LPBRUSH; +typedef LPVOID LPPCOLOR; +typedef LPINT LPSHORT; + +/* DIB Engine functions. */ +/* NB: Based on DDK documentation which may be inaccurate. */ +extern void WINAPI DIB_Control( void ); +extern WORD WINAPI DIB_EnumObjExt( LPPDEVICE lpDestDev, WORD wStyle, FARPROC lpCallbackFunc, + LPVOID lpClientData, LPPDEVICE lpDisplayDev ); +extern VOID WINAPI DIB_CheckCursorExt( LPPDEVICE lpDevice ); +extern WORD WINAPI DIB_Output( LPPDEVICE lpDestDev, WORD wStyle, WORD wCount, + LPPOINT lpPoints, LPPPEN lpPPen, LPPBRUSH lpPBrush, + LPDRAWMODE lpDrawMode, LPRECT lpClipRect); +extern DWORD WINAPI DIB_RealizeObject( LPPDEVICE lpDestDev, WORD wStyle, LPVOID lpInObj, + LPVOID lpOutObj, LPTEXTXFORM lpTextXForm ); +extern WORD WINAPI DIB_RealizeObjectExt( LPPDEVICE lpDestDev, WORD wStyle, LPVOID lpInObj, + LPVOID lpOutObj, LPTEXTXFORM lpTextXForm, + LPPDEVICE lpDisplayDev ); +extern BOOL WINAPI DIB_BitBlt( LPPDEVICE lpDestDev, WORD wDestX, WORD wDestY, LPPDEVICE lpSrcDev, + WORD wSrcX, WORD wSrcY, WORD wXext, WORD wYext, DWORD dwRop3, + LPBRUSH lpPBrush, LPDRAWMODE lpDrawMode ); +extern BOOL WINAPI DIB_BitmapBits( LPPDEVICE lpDevice, DWORD fFlags, DWORD dwCount, LPSTR lpBits ); +extern VOID WINAPI DIB_DibBlt( LPPDEVICE lpBitmap, WORD fGet, WORD iStart, WORD cScans, LPSTR lpDIBits, + LPBITMAPINFO lpBitmapInfo, LPDRAWMODE lpDrawMode, LPINT lpTranslate ); +extern WORD WINAPI DIB_DibToDevice( LPPDEVICE lpDestDev, WORD X, WORD Y, WORD iScan, WORD cScans, + LPRECT lpClipRect, LPDRAWMODE lpDrawMode, LPSTR lpDIBits, + LPBITMAPINFO lpBitmapInfo, LPINT lpTranslate ); +extern DWORD WINAPI DIB_Pixel( LPPDEVICE lpDestDev, WORD X, WORD Y, DWORD dwPhysColor, LPDRAWMODE lpDrawMode ); +extern WORD WINAPI DIB_ScanLR( LPPDEVICE lpDestDev, WORD X, WORD Y, DWORD dwPhysColor, WORD wStyle ); +extern BOOL WINAPI DIB_SelectBitmap(LPPDEVICE lpDevice, LPBITMAP lpPrevBitmap, LPBITMAP lpBitmap, DWORD fFlags ); +extern BOOL WINAPI DIB_StretchBlt( LPPDEVICE lpDestDev, WORD wDestX, WORD wDestY, WORD wDestWidth, + WORD wDestHeight, LPPDEVICE lpSrcDev, WORD wSrcX, WORD wSrcY, + WORD wSrcWidth, WORD wtSrcHeight, DWORD dwRop3, LPBRUSH lpPBrush, + LPDRAWMODE lpDrawMode, LPRECT lpClipRect ); +extern BOOL WINAPI DIB_StretchDIBits( LPPDEVICE lpDestDev, WORD fGet, WORD wDestX, WORD wDestY, WORD wDestWidth, + WORD wDestHeight, WORD wSrcX, WORD wSrcY, WORD wSrcWidth, WORD wSrcHeight, + VOID *lpBits, LPBITMAPINFO lpInfo, LPINT lpTranslate, DWORD dwRop3, + LPBRUSH lpPBrush, LPDRAWMODE lpDrawMode, LPRECT lpClipRect ); +extern DWORD WINAPI DIB_ExtTextOut( LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg, LPRECT lpClipRect, + LPSTR lpString, int wCount, LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, + LPTEXTXFORM lpTextXForm, LPSHORT lpCharWidths, LPRECT lpOpaqueRect, WORD wOptions ); +extern DWORD WINAPI DIB_ExtTextOutExt( LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg, LPRECT lpClipRect, + LPSTR lpString, WORD wCount, LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, + LPTEXTXFORM lpTextXForm, LPSHORT lpCharWidths, LPRECT lpOpaqueRect, + WORD wOptions, LPVOID *lpDrawTextBitmap, LPVOID *lpDrawRect ); +extern WORD WINAPI DIB_GetCharWidth( LPPDEVICE lpDestDev, LPWORD lpBuffer, WORD wFirstChar, WORD wLastChar, + LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, LPTEXTXFORM lpFontTrans ); + +extern DWORD WINAPI DIB_StrBlt( LPPDEVICE lpDestDev, WORD wDestXOrg, WORD wDestYOrg, LPRECT lpClipRect, LPSTR lpString, + WORD wCount, LPFONTINFO lpFontInfo, LPDRAWMODE lpDrawMode, LPTEXTXFORM lpTextXForm ); +extern DWORD WINAPI DIB_ColorInfo( LPPDEVICE lpDestDev, DWORD dwColorin, LPPCOLOR lpPColor ); +extern VOID WINAPI DIB_GetPalette( WORD nStartIndex, WORD nNumEntries, RGBQUAD lpPalette ); +extern VOID WINAPI DIB_GetPaletteExt( WORD nStartIndex, WORD nNumEntries, RGBQUAD lpPalette, LPPDEVICE lpDIBEngine ); +extern VOID WINAPI DIB_GetPaletteTranslate( LPWORD lpIndexes ); +extern VOID WINAPI DIB_GetPaletteTranslateExt( LPWORD lpIndexes, LPPDEVICE lpDIBEngine ); +extern VOID WINAPI DIB_SetPalette( WORD nStartIndex, WORD nNumEntries, LPVOID lpPalette ); +extern VOID WINAPI DIB_SetPaletteExt( WORD nStartIndex, WORD nNumEntries, LPVOID lpPalette, LPPDEVICE lpDIBEngine ); +extern VOID WINAPI DIB_SetPaletteTranslate( LPWORD lpIndexes ); +extern VOID WINAPI DIB_SetPaletteTranslateExt( LPWORD lpIndexes, LPPDEVICE lpDIBEngine ); +extern VOID WINAPI DIB_UpdateColorsExt( WORD wStartX, WORD wStart, WORD wExtX, WORD wExtY, + LPWORD lpTranslate, LPPDEVICE lpDIBEngine ); +extern VOID WINAPI DIB_SetCursorExt( LPPDEVICE lpDevice, LPVOID lpCursorShape ); +extern VOID WINAPI DIB_CheckCursorExt( LPPDEVICE lpDevice ); +extern VOID WINAPI DIB_MoveCursorExt( LPPDEVICE lpDevice, WORD absX, WORD absY ); +extern VOID WINAPI DIB_Inquire( LPVOID lpCursorInfo ); +extern VOID WINAPI DIB_BeginAccess( LPPDEVICE lpDevice, WORD wLeft, WORD wTop, WORD wRight, WORD wBottom, WORD wFlags ); +extern VOID WINAPI DIB_EndAccess( LPPDEVICE lpDevice, WORD wFlags ); +extern WORD WINAPI DIB_CreateDIBitmap( void ); +extern WORD WINAPI DIB_DeviceBitmap( LPPDEVICE lpDestDev, WORD wCommand, LPBITMAP lpBitmap, LPSTR lpBits ); +extern WORD WINAPI DIB_DeviceMode( HWND hWnd, HINSTANCE hInst, LPVOID lpDeviceType, LPVOID lpOutputFile ); +extern UINT WINAPI DIB_Enable( LPPDEVICE lpDevice, WORD wStyle, LPSTR lpDeviceType, LPSTR lpOutputFile, LPVOID lpStuff ); +extern VOID WINAPI DIB_Disable( LPPDEVICE lpDestDev ); +extern WORD WINAPI DIB_EnumDFonts( LPPDEVICE lpDestDev, LPSTR lpFaceName, FARPROC lpCallbackFunc, LPVOID lpClientData ); +extern WORD WINAPI DIB_SetAttribute( LPPDEVICE lpDevice, WORD wStateNum, WORD wIndex, DWORD dwAttribute ); + + +/* WARNING: CreateDIBPDevice returns the result in EAX, not DX:AX! */ +extern DWORD WINAPI CreateDIBPDevice( LPBITMAPINFO lpInfo, LPPDEVICE lpDevice, LPVOID lpBits, WORD wFlags ); + +#define FB_ACCESS 0x0001 +#define CURSOREXCLUDE 0x0008 + +#define GREY_BIT 0x40 /* Physical color MSB. */ + +/* DIB Engine Color Table entry. A lot like RGBQUAD. */ +typedef struct { + BYTE dceBlue; + BYTE dceGreen; + BYTE dceRed; + BYTE dceFlags; +} DIBColorEntry; + +/* DIBColorEntry.dceFlags */ +#define NONSTATIC 0x80 +#define MAPTOWHITE 0x01 + + +/* DIB Engine Physical Object Definitions */ + +typedef struct { + WORD dpPenStyle; + BYTE dpPenFlags; + BYTE dpPenBpp; + DWORD dpPenMono; + DWORD dpPenColor; +} DIB_Pen; + +typedef struct { + BYTE dp1BrushFlags; /* Accelerator for solids */ + BYTE dp1BrushBpp; /* Brush Bits per pixel format */ + WORD dp1BrushStyle; /* Style of the brush */ + DWORD dp1FgColor; /* Physical fg color */ + WORD dp1Hatch; /* Hatching style */ + DWORD dp1BgColor; /* Physical bg color */ + BYTE dp1BrushMono[BRUSHSIZE*4]; /* Mono portion */ + BYTE dp1BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ + BYTE dp1BrushBits[BRUSHSIZE*4]; /* 8 rows, 8 columns of 1 bit/pixel */ +} DIB_Brush1; + +typedef struct { + BYTE dp4BrushFlags; /* Accelerator for solids */ + BYTE dp4BrushBpp; /* Brush Bits per pixel format */ + WORD dp4BrushStyle; /* Style of the brush */ + DWORD dp4FgColor; /* Physical fg color */ + WORD dp4Hatch; /* Hatching style */ + DWORD dp4BgColor; /* Physical bg color */ + BYTE dp4BrushMono[BRUSHSIZE*4]; /* Mono portion */ + BYTE dp4BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ + BYTE dp4BrushBits[BRUSHSIZE*4]; /* 8 rows, 8 columns of 4 bit/pixel */ +} DIB_Brush4; + +typedef struct { + BYTE dp8BrushFlags; /* Accelerator for solids */ + BYTE dp8BrushBpp; /* Brush Bits per pixel format */ + WORD dp8BrushStyle; /* Style of the brush */ + DWORD dp8FgColor; /* Physical fg color */ + WORD dp8Hatch; /* Hatching style */ + DWORD dp8BgColor; /* Physical bg color */ + BYTE dp8BrushMono[BRUSHSIZE*4]; /* Mono portion */ + BYTE dp8BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ + BYTE dp8BrushBits[BRUSHSIZE*8]; /* 8 rows,8 columns of 8 bit/pixel */ +} DIB_Brush8; + +typedef struct { + BYTE dp16BrushFlags; /* Accelerator for solids */ + BYTE dp16BrushBpp; /* Brush Bits per pixel format */ + WORD dp16BrushStyle; /* Style of the brush */ + DWORD dp16FgColor; /* Physical fg color */ + WORD dp16Hatch; /* Hatching style */ + DWORD dp16BgColor; /* Physical bg color */ + BYTE dp16BrushMono[BRUSHSIZE*4]; /* Mono portion */ + BYTE dp16BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ + BYTE dp16BrushBits[BRUSHSIZE*16];/* 8 rows,8 columns of 16 bit/pixel */ +} DIB_Brush16; + +typedef struct { + BYTE dp24BrushFlags; /* Accelerator for solids */ + BYTE dp24BrushBpp; /* Brush Bits per pixel format */ + WORD dp24BrushStyle; /* Style of the brush */ + DWORD dp24FgColor; /* Physical fg color */ + WORD dp24Hatch; /* Hatching style */ + DWORD dp24BgColor; /* Physical bg color */ + BYTE dp24BrushMono[BRUSHSIZE*4]; /* Mono portion */ + BYTE dp24BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ + BYTE dp24BrushBits[BRUSHSIZE*24];/* 8 rows,8 columns of 24 bit/pixel */ +} DIB_Brush24; + +typedef struct { + BYTE dp32BrushFlags; /* Accelerator for solids */ + BYTE dp32BrushBpp; /* Brush Bits per pixel format */ + WORD dp32BrushStyle; /* Style of the brush */ + DWORD dp32FgColor; /* Physical fg color */ + WORD dp32Hatch; /* Hatching style */ + DWORD dp32BgColor; /* Physical bg color */ + BYTE dp32BrushMono[BRUSHSIZE*4]; /* Mono portion */ + BYTE dp32BrushMask[BRUSHSIZE*4]; /* transparency mask (hatch pattern) */ + BYTE dp32BrushBits[BRUSHSIZE*32];/* 8 rows,8 columns of 32 bit/pixel */ +} DIB_Brush32; diff -r 000000000000 -r 20b4ed4eebe3 ddk/dibeng.lbc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddk/dibeng.lbc Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,46 @@ +++DIB_BitBlt.DIBENG.1 +++DIB_ColorInfo.DIBENG.2 +++DIB_Control.DIBENG.3 +++DIB_Disable.DIBENG.4 +++DIB_Enable.DIBENG.5 +++DIB_EnumDFonts.DIBENG.6 +++DIB_EnumObj.DIBENG.7 +++DIB_Output.DIBENG.8 +++DIB_Pixel.DIBENG.9 +++DIB_RealizeObject.DIBENG.10 +++DIB_StrBlt.DIBENG.11 +++DIB_ScanLR.DIBENG.12 +++DIB_DeviceMode.DIBENG.13 +++DIB_ExtTextOut.DIBENG.14 +++DIB_GetCharWidth.DIBENG.15 +++DIB_DeviceBitmap.DIBENG.16 +++DIB_FastBorder.DIBENG.17 +++DIB_SetAttribute.DIBENG.18 +++DIB_DibBlt.DIBENG.19 +++DIB_CreateDIBitmap.DIBENG.20 +++DIB_DibToDevice.DIBENG.21 +++DIB_SetPalette.DIBENG.22 +++DIB_GetPalette.DIBENG.23 +++DIB_SetPaletteTranslate.DIBENG.24 +++DIB_GetPaletteTranslate.DIBENG.25 +++DIB_UpdateColors.DIBENG.26 +++DIB_StretchBlt.DIBENG.27 +++DIB_StretchDIBits.DIBENG.28 +++DIB_SelectBitmap.DIBENG.29 +++DIB_BitmapBits.DIBENG.30 +++DIB_Inquire.DIBENG.101 +++DIB_SetCursorExt.DIBENG.102 +++DIB_MoveCursorExt.DIBENG.103 +++DIB_CheckCursorExt.DIBENG.104 +++DIB_BeginAccess.DIBENG.105 +++DIB_EndAccess.DIBENG.106 +++CreateDIBPDevice.DIBENG.300 +++DIB_RealizeObjectExt.DIBENG.400 +++DIB_DibBltExt.DIBENG.401 +++DIB_EnumObjExt.DIBENG.402 +++DIB_ExtTextOutExt.DIBENG.403 +++DIB_UpdateColorsExt.DIBENG.404 +++DIB_SetPaletteExt.DIBENG.405 +++DIB_GetPaletteExt.DIBENG.406 +++DIB_SetPaletteTranslateExt.DIBENG.407 +++DIB_GetPaletteTranslateExt.DIBENG.408 diff -r 000000000000 -r 20b4ed4eebe3 ddk/gdidefs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddk/gdidefs.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,828 @@ + +/* Definitions for GDI drivers. */ + +/* Physical Bitmap structure. */ +typedef struct { + short int bmType; + unsigned short int bmWidth; + unsigned short int bmHeight; + unsigned short int bmWidthBytes; + BYTE bmPlanes; + BYTE bmBitsPixel; + BYTE FAR *bmBits; + unsigned long int bmWidthPlanes; + BYTE FAR *bmlpPDevice; + unsigned short int bmSegmentIndex; + unsigned short int bmScanSegment; + unsigned short int bmFillBytes; + unsigned short int futureUse4; + unsigned short int futureUse5; +} BITMAP; + +/* DIB structs also defined in windows.h. */ +typedef struct { + DWORD bcSize; + WORD bcWidth; + WORD bcHeight; + WORD bcPlanes; + WORD bcBitCount; +} BITMAPCOREHEADER; +typedef BITMAPCOREHEADER FAR *LPBITMAPCOREHEADER; +typedef BITMAPCOREHEADER *PBITMAPCOREHEADER; + +typedef struct { + DWORD biSize; + DWORD biWidth; + DWORD biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + DWORD biXPelsPerMeter; + DWORD biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER; + +typedef BITMAPINFOHEADER FAR *LPBITMAPINFOHEADER; +typedef BITMAPINFOHEADER *PBITMAPINFOHEADER; + +typedef struct { + BYTE rgbtBlue; + BYTE rgbtGreen; + BYTE rgbtRed; +} RGBTRIPLE; + +typedef struct { + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} RGBQUAD; + +/* ICM Color Definitions */ +typedef long FXPT16DOT16, FAR *LPFXPT16DOT16; +typedef long FXPT2DOT30, FAR *LPFXPT2DOT30; + +typedef struct tagCIEXYZ +{ + FXPT2DOT30 ciexyzX; + FXPT2DOT30 ciexyzY; + FXPT2DOT30 ciexyzZ; +} CIEXYZ; +typedef CIEXYZ FAR *LPCIEXYZ; + +typedef struct tagICEXYZTRIPLE +{ + CIEXYZ ciexyzRed; + CIEXYZ ciexyzGreen; + CIEXYZ ciexyzBlue; +} CIEXYZTRIPLE; +typedef CIEXYZTRIPLE FAR *LPCIEXYZTRIPLE; + +typedef struct { + BITMAPCOREHEADER bmciHeader; + RGBQUAD bmciColors[1]; +} BITMAPCOREINFO; + +typedef BITMAPCOREINFO FAR *LPBITMAPCOREINFO; +typedef BITMAPCOREINFO *PBITMAPCOREINFO; + +typedef struct { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[1]; +} BITMAPINFO; + +typedef BITMAPINFO FAR *LPBITMAPINFO; +typedef BITMAPINFO *PBITMAPINFO; + +typedef struct { + DWORD bV4Size; + LONG bV4Width; + LONG bV4Height; + WORD bV4Planes; + WORD bV4BitCount; + DWORD bV4V4Compression; + DWORD bV4SizeImage; + LONG bV4XPelsPerMeter; + LONG bV4YPelsPerMeter; + DWORD bV4ClrUsed; + DWORD bV4ClrImportant; + DWORD bV4RedMask; + DWORD bV4GreenMask; + DWORD bV4BlueMask; + DWORD bV4AlphaMask; + DWORD bV4CSType; + CIEXYZTRIPLE bV4Endpoints; + DWORD bV4GammaRed; + DWORD bV4GammaGreen; + DWORD bV4GammaBlue; +} BITMAPV4HEADER, FAR *LPBITMAPV4HEADER, *PBITMAPV4HEADER; + +typedef struct { + BITMAPV4HEADER bmv4Header; + RGBQUAD bmv4Colors[1]; +} BITMAPV4INFO; + +typedef BITMAPV4INFO FAR *LPBITMAPV4INFO; +typedef BITMAPV4INFO *PBITMAPV4INFO; + +/* currently, if the low byte of biCompression is non zero, + * it must be one of following */ + +#define BI_RGB 0x00 +#define BI_RLE8 0x01 +#define BI_RLE4 0x02 +#define BI_BITFIELDS 0x03 + +#define BITMAP_SELECTED 0x01 +#define BITMAP_64K 0x01 + +#define DIBSIGNATURE 0x4944 + +/* Point types are optional. */ +#ifndef NOPTRC + +typedef struct { + short int xcoord; + short int ycoord; +} PTTYPE; +typedef PTTYPE *PPOINT; +typedef PTTYPE FAR *LPPOINT; + +#define POINT PTTYPE + +typedef struct { + short int left; + short int top; + short int right; + short int bottom; +} RECT; +typedef RECT *PRECT; + +#endif + +typedef struct { + PTTYPE min; + PTTYPE ext; +} BOXTYPE; +typedef RECT FAR *LPRECT; + +/* Object definitions used by GDI support routines written in C */ + +#define OBJ_PEN 1 +#define OBJ_BRUSH 2 +#define OBJ_FONT 3 + +typedef struct { + unsigned short int lbStyle; + unsigned long int lbColor; + unsigned short int lbHatch; + unsigned long int lbBkColor; + unsigned long int lbhcmXform; +} LOGBRUSH; + +#define lbPattern lbColor + +/* Brush Style definitions. */ +#define BS_SOLID 0 +#define BS_HOLLOW 1 +#define BS_HATCHED 2 +#define BS_PATTERN 3 + +#define MaxBrushStyle 3 + +/* Hatch Style definitions. */ +#define HS_HORIZONTAL 0 /* ----- */ +#define HS_VERTICAL 1 /* ||||| */ +#define HS_FDIAGONAL 2 /* ///// */ +#define HS_BDIAGONAL 3 /* \\\\\ */ +#define HS_CROSS 4 /* +++++ */ +#define HS_DIAGCROSS 5 /* xxxxx */ + +#define MaxHatchStyle 5 + + +/* Logical Pen Structure. */ +typedef struct { + unsigned short int lopnStyle; + PTTYPE lopnWidth; + unsigned long int lopnColor; + unsigned short int lopnStyle2; + unsigned long int lopnhcmXform; +} LOGPEN; + +/* Line Style definitions. */ +#define LS_SOLID 0 +#define LS_DASHED 1 +#define LS_DOTTED 2 +#define LS_DOTDASHED 3 +#define LS_DASHDOTDOT 4 +#define LS_NOLINE 5 +#define LS_INSIDEFRAME 6 +#define MaxLineStyle LS_NOLINE + +#define LS_ENDCAP_FLAT 0x01 +#define LS_ENDCAP_ROUND 0x02 +#define LS_ENDCAP_SQUARE 0x04 +#define LS_JOIN_BEVEL 0x08 +#define LS_JOIN_MITER 0x10 +#define LS_JOIN_ROUND 0x20 + + +/* The size to allocate for the lfFaceName field in the logical font. */ +#ifndef LF_FACESIZE +#define LF_FACESIZE 32 +#endif + +/* Various constants for defining a logical font. */ +#define OUT_DEFAULT_PRECIS 0 +#define OUT_STRING_PRECIS 1 +#define OUT_CHARACTER_PRECIS 2 +#define OUT_STROKE_PRECIS 3 +#define OUT_TT_PRECIS 4 +#define OUT_DEVICE_PRECIS 5 +#define OUT_RASTER_PRECIS 6 +#define OUT_TT_ONLY_PRECIS 7 + +#define CLIP_DEFAULT_PRECIS 0 +#define CLIP_CHARACTER_PRECIS 1 +#define CLIP_STROKE_PRECIS 2 +#define CLIP_MASK 0x0F +#define CLIP_LH_ANGLES 0x10 +#define CLIP_TT_ALWAYS 0x20 +#define CLIP_EMBEDDED 0x80 + +#define DEFAULT_QUALITY 0 +#define DRAFT_QUALITY 1 +#define PROOF_QUALITY 2 + +#define DEFAULT_PITCH 0 +#define FIXED_PITCH 1 +#define VARIABLE_PITCH 2 + +#define ANSI_CHARSET 0 +#define DEFAULT_CHARSET 1 +#define SYMBOL_CHARSET 2 +#define MAC_CHARSET 77 +#define SHIFTJIS_CHARSET 128 +#define HANGEUL_CHARSET 129 +#define CHINESEBIG5_CHARSET 136 +#define OEM_CHARSET 255 + + +/* GDI font families. */ +#define FF_DONTCARE (0<<4) /* Don't care or don't know. */ +#define FF_ROMAN (1<<4) /* Variable stroke width, serifed. */ + /* Times Roman, Century Schoolbook, etc.*/ +#define FF_SWISS (2<<4) /* Variable stroke width, sans-serifed. */ + /* Helvetica, Swiss, etc. */ +#define FF_MODERN (3<<4) /* Constant stroke width, serifed or sans-serifed. */ + /* Pica, Elite, Courier, etc. */ +#define FF_SCRIPT (4<<4) /* Cursive, etc. */ +#define FF_DECORATIVE (5<<4) /* Old English, etc. */ + + +/* Font weights lightest to heaviest. */ +#define FW_DONTCARE 0 +#define FW_THIN 100 +#define FW_EXTRALIGHT 200 +#define FW_LIGHT 300 +#define FW_NORMAL 400 +#define FW_MEDIUM 500 +#define FW_SEMIBOLD 600 +#define FW_BOLD 700 +#define FW_EXTRABOLD 800 +#define FW_HEAVY 900 + +#define FW_ULTRALIGHT FW_EXTRALIGHT +#define FW_REGULAR FW_NORMAL +#define FW_DEMIBOLD FW_SEMIBOLD +#define FW_ULTRABOLD FW_EXTRABOLD +#define FW_BLACK FW_HEAVY + +/* Enumeration font types. */ +#define RASTER_FONTTYPE 1 +#define DEVICE_FONTTYPE 2 + + + +typedef struct { + short int lfHeight; + short int lfWidth; + short int lfEscapement; + short int lfOrientation; + short int lfWeight; + BYTE lfItalic; + BYTE lfUnderline; + BYTE lfStrikeOut; + BYTE lfCharSet; + BYTE lfOutPrecision; + BYTE lfClipPrecision; + BYTE lfQuality; + BYTE lfPitchAndFamily; + BYTE lfFaceName[LF_FACESIZE]; +} LOGFONT; + + +#define InquireInfo 0x01 /* Inquire Device GDI Info */ +#define EnableDevice 0x00 /* Enable Device */ +#define InfoContext 0x8000 /* Inquire/Enable for info context */ + +/* Device Technology types */ +#define DT_PLOTTER 0 /* Vector plotter */ +#define DT_RASDISPLAY 1 /* Raster display */ +#define DT_RASPRINTER 2 /* Raster printer */ +#define DT_RASCAMERA 3 /* Raster camera */ +#define DT_CHARSTREAM 4 /* Character-stream, PLP */ +#define DT_METAFILE 5 /* Metafile, VDM */ +#define DT_DISPFILE 6 /* Display-file */ +#define DT_JUMBO 11 /* SPAG LJ cool thing */ + +/* Curve Capabilities */ +#define CC_NONE 0x0000 /* Curves not supported */ +#define CC_CIRCLES 0x0001 /* Can do circles */ +#define CC_PIE 0x0002 /* Can do pie wedges */ +#define CC_CHORD 0x0004 /* Can do chord arcs */ +#define CC_ELLIPSES 0x0008 /* Can do ellipese */ +#define CC_WIDE 0x0010 /* Can do wide lines */ +#define CC_STYLED 0x0020 /* Can do styled lines */ +#define CC_WIDESTYLED 0x0040 /* Can do wide styled lines*/ +#define CC_INTERIORS 0x0080 /* Can do interiors */ +#define CC_ROUNDRECT 0x0100 /* Can do round rectangles */ +#define CC_POLYBEZIER 0x0200 /* Can do polybeziers */ + +/* Line Capabilities */ +#define LC_NONE 0x0000 /* Lines not supported */ +#define LC_POLYSCANLINE 0x0001 /* Poly Scanlines supported*/ +#define LC_POLYLINE 0x0002 /* Can do polylines */ +#define LC_MARKER 0x0004 /* Can do markers */ +#define LC_POLYMARKER 0x0008 /* Can do polymarkers */ +#define LC_WIDE 0x0010 /* Can do wide lines */ +#define LC_STYLED 0x0020 /* Can do styled lines */ +#define LC_WIDESTYLED 0x0040 /* Can do wide styled lines*/ +#define LC_INTERIORS 0x0080 /* Can do interiors */ + +/* Polygonal Capabilities */ +#define PC_NONE 0x0000 /* Polygonals not supported*/ +#define PC_ALTPOLYGON 0x0001 /* Can do even odd polygons*/ +#define PC_POLYGON 0x0001 /* old name for ALTPOLYGON */ +#define PC_RECTANGLE 0x0002 /* Can do rectangles */ +#define PC_WINDPOLYGON 0x0004 /* Can do winding polygons */ +#define PC_TRAPEZOID 0x0004 /* old name for WINDPOLYGON*/ +#define PC_SCANLINE 0x0008 /* Can do scanlines */ +#define PC_WIDE 0x0010 /* Can do wide borders */ +#define PC_STYLED 0x0020 /* Can do styled borders */ +#define PC_WIDESTYLED 0x0040 /* Can do wide styled borders*/ +#define PC_INTERIORS 0x0080 /* Can do interiors */ +#define PC_POLYPOLYGON 0x0100 /* Can do PolyPolygons */ + +/* Clipping Capabilities */ +#define CP_NONE 0x0000 /* no clipping of Output */ +#define CP_RECTANGLE 0x0001 /* Output clipped to Rects */ +#define CP_REGION 0x0002 /* not supported */ +#define CP_REGION32 0x0004 /* Output clipped to regions */ + +/* Text Capabilities */ +#define TC_OP_CHARACTER 0x0001 /* Can do OutputPrecision CHARACTER */ +#define TC_OP_STROKE 0x0002 /* Can do OutputPrecision STROKE */ +#define TC_CP_STROKE 0x0004 /* Can do ClipPrecision STROKE */ +#define TC_CR_90 0x0008 /* Can do CharRotAbility 90 */ +#define TC_CR_ANY 0x0010 /* Can do CharRotAbility ANY */ +#define TC_SF_X_YINDEP 0x0020 /* Can do ScaleFreedom X_YINDEPENDENT */ +#define TC_SA_DOUBLE 0x0040 /* Can do ScaleAbility DOUBLE */ +#define TC_SA_INTEGER 0x0080 /* Can do ScaleAbility INTEGER */ +#define TC_SA_CONTIN 0x0100 /* Can do ScaleAbility CONTINUOUS */ +#define TC_EA_DOUBLE 0x0200 /* Can do EmboldenAbility DOUBLE */ +#define TC_IA_ABLE 0x0400 /* Can do ItalisizeAbility ABLE */ +#define TC_UA_ABLE 0x0800 /* Can do UnderlineAbility ABLE */ +#define TC_SO_ABLE 0x1000 /* Can do StrikeOutAbility ABLE */ +#define TC_RA_ABLE 0x2000 /* Can do RasterFontAble ABLE */ +#define TC_VA_ABLE 0x4000 /* Can do VectorFontAble ABLE */ +#define TC_RESERVED 0x8000 /* Reserved. Must be returned zero. */ + +/* Raster Capabilities */ +#define RC_NONE 0x0000 /* No Raster Capabilities */ +#define RC_BITBLT 0x0001 /* Can do bitblt */ +#define RC_BANDING 0x0002 /* Requires banding support */ +#define RC_SCALING 0x0004 /* does scaling while banding */ +#define RC_BITMAP64 0x0008 /* supports >64k bitmaps */ +#define RC_GDI20_OUTPUT 0x0010 /* has 2.0 output calls */ +#define RC_GDI20_STATE 0x0020 /* dc has a state block */ +#define RC_SAVEBITMAP 0x0040 /* can save bitmaps locally */ +#define RC_DI_BITMAP 0x0080 /* can do DIBs */ +#define RC_PALETTE 0x0100 /* can do color pal management */ +#define RC_DIBTODEV 0x0200 /* can do SetDIBitsToDevice */ +#define RC_BIGFONT 0x0400 /* can do BIGFONTs */ +#define RC_STRETCHBLT 0x0800 /* can do StretchBlt */ +#define RC_FLOODFILL 0x1000 /* can do FloodFill */ +#define RC_STRETCHDIB 0x2000 /* can do StretchDIBits */ +#define RC_OP_DX_OUTPUT 0x4000 /* can do smart ExtTextOut w/dx */ +#define RC_DEVBITS 0x8000 /* supports device bitmaps */ + +/* DC Management Flags */ +#define DC_SPDevice 0000001 /* Seperate PDevice required per device/filename */ +#define DC_1PDevice 0000002 /* Only 1 PDevice allowed per device/filename */ +#define DC_IgnoreDFNP 0000004 /* Ignore device/filename pairs when matching */ + +/* dpCaps1 capability bits */ +#define C1_TRANSPARENT 0x0001 /* supports transparency */ +#define TC_TT_ABLE 0x0002 /* can do TT through DDI or brute */ +#define C1_TT_CR_ANY 0x0004 /* can do rotated TT fonts */ +#define C1_EMF_COMPLIANT 0x0008 /* Win95 - supports metafile spooling */ +#define C1_DIBENGINE 0x0010 /* DIB Engine compliant driver */ +#define C1_GAMMA_RAMP 0x0020 /* supports gamma ramp setting */ +#define C1_ICM 0x0040 /* does some form of ICM support */ +#define C1_REINIT_ABLE 0x0080 /* Driver supports ReEnable */ +#define C1_GLYPH_INDEX 0x0100 /* Driver supports glyph index fonts */ +#define C1_BIT_PACKED 0x0200 /* Supports bit-packed glyphs */ +#define C1_BYTE_PACKED 0x0400 /* Supports byte-packed glyphs */ +#define C1_COLORCURSOR 0x0800 /* Driver supports color_cursors and async SetCursor */ +#define C1_CMYK_ABLE 0x1000 /* Driver supports CMYK ColorRefs */ +#define C1_SLOW_CARD 0x2000 /* Little or no acceleration (VGA, etc.)*/ + +/* dpCapsFE capability bits */ +#define FEC_TT_DBCS 0x0020 /* can output DBCS TT fonts correctly */ +#define FEC_WIFE_ABLE 0x0080 /* can handle WIFE font as Engine font */ + +typedef struct { + short int dpVersion; + short int dpTechnology; + short int dpHorzSize; + short int dpVertSize; + short int dpHorzRes; + short int dpVertRes; + short int dpBitsPixel; + short int dpPlanes; + short int dpNumBrushes; + short int dpNumPens; + short int dpCapsFE; + short int dpNumFonts; + short int dpNumColors; + short int dpDEVICEsize; + unsigned short int dpCurves; + unsigned short int dpLines; + unsigned short int dpPolygonals; + unsigned short int dpText; + unsigned short int dpClip; + unsigned short int dpRaster; + short int dpAspectX; + short int dpAspectY; + short int dpAspectXY; + short int dpStyleLen; + PTTYPE dpMLoWin; + PTTYPE dpMLoVpt; + PTTYPE dpMHiWin; + PTTYPE dpMHiVpt; + PTTYPE dpELoWin; + PTTYPE dpELoVpt; + PTTYPE dpEHiWin; + PTTYPE dpEHiVpt; + PTTYPE dpTwpWin; + PTTYPE dpTwpVpt; + short int dpLogPixelsX; + short int dpLogPixelsY; + short int dpDCManage; + unsigned short int dpCaps1; + short int futureuse4; + short int futureuse5; + short int futureuse6; + short int futureuse7; + WORD dpNumPalReg; + WORD dpPalReserved; + WORD dpColorRes; +} GDIINFO; + +/* This bit in the dfType field signals that the dfBitsOffset field is an + absolute memory address and should not be altered. */ +#define PF_BITS_IS_ADDRESS 4 + +/* This bit in the dfType field signals that the font is device realized. */ +#define PF_DEVICE_REALIZED 0x80 + +/* These bits in the dfType give the fonttype - + raster, vector, other1, other2. */ +#define PF_RASTER_TYPE 0 +#define PF_VECTOR_TYPE 1 +#define PF_OTHER1_TYPE 2 +#define PF_OTHER2_TYPE 3 +#define PF_GLYPH_INDEX 0x20 +#define PF_WIFE_TYPE 0x08 + +/* Glyph types for EngineGetGlyphBmp */ +#define EGB_BITMAP 1 +#define EGB_OUTLINE 2 +#define EGB_GRAY2_BITMAP 8 +#define EGB_GRAY4_BITMAP 9 +#define EGB_GRAY8_BITMAP 10 + + +/* The size to allocate for the dfMaps field in the physical font. */ +#ifndef DF_MAPSIZE +#define DF_MAPSIZE 1 +#endif + +/* Font structure. */ +typedef struct { + short int dfType; + short int dfPoints; + short int dfVertRes; + short int dfHorizRes; + short int dfAscent; + short int dfInternalLeading; + short int dfExternalLeading; + BYTE dfItalic; + BYTE dfUnderline; + BYTE dfStrikeOut; + short int dfWeight; + BYTE dfCharSet; + short int dfPixWidth; + short int dfPixHeight; + BYTE dfPitchAndFamily; + short int dfAvgWidth; + short int dfMaxWidth; + BYTE dfFirstChar; + BYTE dfLastChar; + BYTE dfDefaultChar; + BYTE dfBreakChar; + short int dfWidthBytes; + unsigned long int dfDevice; + unsigned long int dfFace; + unsigned long int dfBitsPointer; + unsigned long int dfBitsOffset; + BYTE dfReservedByte; + unsigned short dfMaps[DF_MAPSIZE]; +} FONTINFO; + + +typedef struct { + short int erType; + short int erPoints; + short int erVertRes; + short int erHorizRes; + short int erAscent; + short int erInternalLeading; + short int erExternalLeading; + BYTE erItalic; + BYTE erUnderline; + BYTE erStrikeOut; + short int erWeight; + BYTE erCharSet; + short int erPixWidth; + short int erPixHeight; + BYTE erPitchAndFamily; + short int erAvgWidth; + short int erMaxWidth; + BYTE erFirstChar; + BYTE erLastChar; + BYTE erDefaultChar; + BYTE erBreakChar; + short int erWidthBytes; + unsigned long int erDevice; + unsigned long int erFace; + unsigned long int erBitsPointer; + unsigned long int erBitsOffset; + BYTE erReservedByte; + short int erUnderlinePos; + short int erUnderlineThick; + short int erStrikeoutPos; + short int erStrikeoutThick; +} SCALABLEFONTINFO; + + +typedef struct { + short int ftHeight; + short int ftWidth; + short int ftEscapement; + short int ftOrientation; + short int ftWeight; + BYTE ftItalic; + BYTE ftUnderline; + BYTE ftStrikeOut; + BYTE ftOutPrecision; + BYTE ftClipPrecision; + unsigned short int ftAccelerator; + short int ftOverhang; +} TEXTXFORM; + + +typedef struct { + short int tmHeight; + short int tmAscent; + short int tmDescent; + short int tmInternalLeading; + short int tmExternalLeading; + short int tmAveCharWidth; + short int tmMaxCharWidth; + short int tmWeight; + BYTE tmItalic; + BYTE tmUnderlined; + BYTE tmStruckOut; + BYTE tmFirstChar; + BYTE tmLastChar; + BYTE tmDefaultChar; + BYTE tmBreakChar; + BYTE tmPitchAndFamily; + BYTE tmCharSet; + short int tmOverhang; + short int tmDigitizedAspectX; + short int tmDigitizedAspectY; +} TEXTMETRIC; + +typedef struct { + short int Rop2; + short int bkMode; + unsigned long int bkColor; + unsigned long int TextColor; + short int TBreakExtra; + short int BreakExtra; + short int BreakErr; + short int BreakRem; + short int BreakCount; + short int CharExtra; + unsigned long int LbkColor; + unsigned long int LTextColor; + DWORD ICMCXform; + short StretchBltMode; + DWORD eMiterLimit; +} DRAWMODE; + + +/* Background Mode definitions. */ +#define TRANSPARENT 1 +#define OPAQUE 2 + +#define BKMODE_TRANSPARENT 1 +#define BKMODE_OPAQUE 2 +#define BKMODE_LEVEL1 3 +#define BKMODE_LEVEL2 4 +#define BKMODE_LEVEL3 5 +#define BKMODE_TRANSLATE 6 + +/* StretchBlt Mode definitions. */ +#define STRETCH_ANDSCANS 1 +#define STRETCH_ORSCANS 2 +#define STRETCH_DELETESCANS 3 +#define STRETCH_HALFTONE 4 + +#define SBM_BLACKONWHITE STRETCH_ANDSCANS +#define SBM_WHITEONBLACK STRETCH_ORSCANS +#define SBM_COLORONCOLOR STRETCH_DELETESCANS +#define SBM_HALFTONE STRETCH_HALFTONE + +typedef struct { + short int scnPntCnt; + short int scnPntTop; + short int scnPntBottom; + short int scnPntX[2]; + short int scnPntCntToo; +} SCAN, FAR* LPSCAN; + +typedef struct { + DWORD cbSize; + LPVOID lpDestDev; + DWORD nEscape; + DWORD cbInput; + LPVOID lpInput; + POINT ptOrigin; + DWORD dwUniq; + RECT rcBBox; + DWORD cScans; + LPSCAN lpScan; +} DRAWESCAPE, FAR* LPDRAWESCAPE; + +typedef struct { + WORD id; + WORD cbSize; + LPRECT lprcClip; + DWORD dwUniq; + RECT rcBBox; + DWORD cScans; + LPSCAN lpScan; +} REGION, FAR* LPREGION; + + +/* Output Style definitions. */ + +#define OS_POLYBEZIER 1 +#define OS_ARC 3 +#define OS_SCANLINES 4 +#define OS_POLYSCANLINE 5 +#define OS_RECTANGLE 6 +#define OS_ELLIPSE 7 +#define OS_MARKER 8 +#define OS_POLYLINE 18 +#define OS_TRAPEZOID 20 +#define OS_WINDPOLYGON OS_TRAPEZOID +#define OS_POLYGON 22 +#define OS_ALTPOLYGON OS_POLYGON +#define OS_PIE 23 +#define OS_POLYMARKER 24 +#define OS_CHORD 39 +#define OS_CIRCLE 55 + +#define OS_POLYPOLYGON 0x4000 /* ORed with OS_WIND/ALTPOLYGON. */ + +#define OS_BEGINNSCAN 80 +#define OS_ENDNSCAN 81 + +#define OEM_FAILED 0x80000000L + +#define NEWFRAME 1 +#define ABORTDOC 2 +#define NEXTBAND 3 +#define SETCOLORTABLE 4 +#define GETCOLORTABLE 5 +#define FLUSHOUTPUT 6 +#define DRAFTMODE 7 +#define QUERYESCSUPPORT 8 +#define SETPRINTERDC 9 /* DDK: between GDI and Driver. */ +#define SETABORTPROC 9 /* SDK: between application and GDI. */ +#define STARTDOC 10 +#define ENDDOC 11 +#define GETPHYSPAGESIZE 12 +#define GETPRINTINGOFFSET 13 +#define GETSCALINGFACTOR 14 +#define MFCOMMENT 15 +#define GETPENWIDTH 16 +#define SETCOPYCOUNT 17 +#define SELECTPAPERSOURCE 18 +#define DEVICEDATA 19 +#define PASSTHROUGH 19 +#define GETTECHNOLGY 20 +#define GETTECHNOLOGY 20 +#define SETLINECAP 21 +#define SETLINEJOIN 22 +#define SETMITERLIMIT 23 +#define BANDINFO 24 +#define DRAWPATTERNRECT 25 +#define GETVECTORPENSIZE 26 +#define GETVECTORBRUSHSIZE 27 +#define ENABLEDUPLEX 28 +#define GETSETPAPERBINS 29 +#define GETSETPRINTORIENT 30 +#define ENUMPAPERBINS 31 +#define SETDIBSCALING 32 +#define EPSPRINTING 33 +#define ENUMPAPERMETRICS 34 +#define GETSETPAPERMETRICS 35 +#define GETVERSION 36 +#define POSTSCRIPT_DATA 37 +#define POSTSCRIPT_IGNORE 38 +#define QUERYROPSUPPORT 40 +#define GETDEVICEUNITS 42 +#define RESETDEVICE 128 +#define GETEXTENDEDTEXTMETRICS 256 +#define GETEXTENTTABLE 257 +#define GETPAIRKERNTABLE 258 +#define GETTRACKKERNTABLE 259 +#define EXTTEXTOUT 512 +#define GETFACENAME 513 +#define DOWNLOADFACE 514 +#define ENABLERELATIVEWIDTHS 768 +#define ENABLEPAIRKERNING 769 +#define SETKERNTRACK 770 +#define SETALLJUSTVALUES 771 +#define SETCHARSET 772 +#define STRETCHBLT 2048 +#define QUERYDIBSUPPORT 3073 +#define QDI_SETDIBITS 0x0001 +#define QDI_GETDIBITS 0x0002 +#define QDI_DIBTOSCREEN 0x0004 +#define QDI_STRETCHDIB 0x0008 +#define DCICOMMAND 3075 +#define BEGIN_PATH 4096 +#define CLIP_TO_PATH 4097 +#define END_PATH 4098 +#define EXT_DEVICE_CAPS 4099 +#define RESTORE_CTM 4100 +#define SAVE_CTM 4101 +#define SET_ARC_DIRECTION 4102 +#define SET_BACKGROUND_COLOR 4103 +#define SET_POLY_MODE 4104 +#define SET_SCREEN_ANGLE 4105 +#define SET_SPREAD 4106 +#define TRANSFORM_CTM 4107 +#define SET_CLIP_BOX 4108 +#define SET_BOUNDS 4109 +#define OPENCHANNEL 4110 +#define DOWNLOADHEADER 4111 +#define CLOSECHANNEL 4112 +#define SETGDIXFORM 4113 +#define RESETPAGE 4114 +#define POSTSCRIPT_PASSTHROUGH 4115 +#define ENCAPSULATED_POSTSCRIPT 4116 + + +typedef FONTINFO FAR *LPFONTINFO; +typedef DRAWMODE FAR *LPDRAWMODE; +typedef TEXTXFORM FAR *LPTEXTXFORM; +typedef TEXTMETRIC FAR *LPTEXTMETRIC; +typedef LOGFONT FAR *LPLOGFONT; +typedef LOGPEN FAR *LPLOGPEN; +typedef LOGBRUSH FAR *LPLOGBRUSH; +typedef BITMAP FAR *LPBITMAP; +typedef FARPROC FAR *LPFARPROC; +typedef GDIINFO FAR *LPGDIINFO; +typedef SCALABLEFONTINFO FAR * LPSCALABLEFONTINFO; + diff -r 000000000000 -r 20b4ed4eebe3 ddk/minivdd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddk/minivdd.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,114 @@ + +/* Functions callable via VDD's API entry point, usually called by display + * drivers. + */ +#define MINIVDD_SVC_BASE_OFFSET 0x80 +#define VDD_DRIVER_REGISTER (0 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_DRIVER_UNREGISTER (1 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_SAVE_DRIVER_STATE (2 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_REGISTER_DISPLAY_DRIVER_INFO (3 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_REGISTER_SSB_FLAGS (4 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_GET_DISPLAY_CONFIG (5 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_PRE_MODE_CHANGE (6 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_POST_MODE_CHANGE (7 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_SET_USER_FLAGS (8 + MINIVDD_SVC_BASE_OFFSET) +#define VDD_SET_BUSY_FLAG_ADDR (9 + MINIVDD_SVC_BASE_OFFSET) + +/* The DISPLAYINFO structure for querying Registry information. */ +typedef struct { + WORD diHdrSize; + WORD diInfoFlags; + DWORD diDevNodeHandle; + char diDriverName[16]; + WORD diXRes; + WORD diYRes; + WORD diDPI; + BYTE diPlanes; + BYTE diBpp; + WORD diRefreshRateMax; + WORD diRefreshRateMin; + WORD diLowHorz; + WORD diHighHorz; + WORD diLowVert; + WORD diHighVert; + DWORD diMonitorDevNodeHandle; + BYTE diHorzSyncPolarity; + BYTE diVertSyncPolarity; +} DISPLAYINFO; + +/* diInfoFlags */ +#define RETURNED_DATA_IS_STALE 0x001 /* VDD couldn't read Registry, data could be old. */ +#define MINIVDD_FAILED_TO_LOAD 0x002 /* MiniVDD did not load, probably bad config. */ +#define MINIVDD_CHIP_ID_DIDNT_MATCH 0x004 /* ChipID mismatch, probably bad config. */ +#define REGISTRY_BPP_NOT_VALID 0x008 /* BPP could not be read from Registry. */ +#define REGISTRY_RESOLUTION_NOT_VALID 0x010 /* Resolution could not be read from Registry. */ +#define REGISTRY_DPI_NOT_VALID 0x020 /* DPI could not be read from Registry. */ +#define MONITOR_DEVNODE_NOT_ACTIVE 0x040 /* Devnode not there, no refresh rate data. */ +#define MONITOR_INFO_NOT_VALID 0x080 /* Refresh rate data could not be read. */ +#define MONITOR_INFO_DISABLED_BY_USER 0x100 /* Refresh rate data not valid. */ +#define REFRESH_RATE_MAX_ONLY 0x200 /* Only diRefreshRateMax is valid. */ +#define CARD_VDD_LOADED_OK 0x400 /* Second MiniVDD loaded fine. */ + +/* Funcrions callable in a mini-VDD. */ +#define REGISTER_DISPLAY_DRIVER 0 +#define GET_VDD_BANK 1 +#define SET_VDD_BANK 2 +#define RESET_BANK 3 +#define PRE_HIRES_TO_VGA 4 +#define POST_HIRES_TO_VGA 5 +#define PRE_VGA_TO_HIRES 6 +#define POST_VGA_TO_HIRES 7 +#define SAVE_REGISTERS 8 +#define RESTORE_REGISTERS 9 +#define MODIFY_REGISTER_STATE 10 +#define ACCESS_VGA_MEMORY_MODE 11 +#define ACCESS_LINEAR_MEMORY_MODE 12 +#define ENABLE_TRAPS 13 +#define DISABLE_TRAPS 14 +#define MAKE_HARDWARE_NOT_BUSY 15 +#define VIRTUALIZE_CRTC_IN 16 +#define VIRTUALIZE_CRTC_OUT 17 +#define VIRTUALIZE_SEQUENCER_IN 18 +#define VIRTUALIZE_SEQUENCER_OUT 19 +#define VIRTUALIZE_GCR_IN 20 +#define VIRTUALIZE_GCR_OUT 21 +#define SET_LATCH_BANK 22 +#define RESET_LATCH_BANK 23 +#define SAVE_LATCHES 24 +#define RESTORE_LATCHES 25 +#define DISPLAY_DRIVER_DISABLING 26 +#define SELECT_PLANE 27 +#define PRE_CRTC_MODE_CHANGE 28 +#define POST_CRTC_MODE_CHANGE 29 +#define VIRTUALIZE_DAC_OUT 30 +#define VIRTUALIZE_DAC_IN 31 +#define GET_CURRENT_BANK_WRITE 32 +#define GET_CURRENT_BANK_READ 33 +#define SET_BANK 34 +#define CHECK_HIRES_MODE 35 +#define GET_TOTAL_VRAM_SIZE 36 +#define GET_BANK_SIZE 37 +#define SET_HIRES_MODE 38 +#define PRE_HIRES_SAVE_RESTORE 39 +#define POST_HIRES_SAVE_RESTORE 40 +#define VESA_SUPPORT 41 +#define GET_CHIP_ID 42 +#define CHECK_SCREEN_SWITCH_OK 43 +#define VIRTUALIZE_BLTER_IO 44 +#define SAVE_MESSAGE_MODE_STATE 45 +#define SAVE_FORCED_PLANAR_STATE 46 +#define VESA_CALL_POST_PROCESSING 47 +#define PRE_INT_10_MODE_SET 48 + +#define NBR_MINI_VDD_FUNCTIONS 49 + +/* Port sizes. */ +#define BYTE_LENGTHED 1 +#define WORD_LENGTHED 2 + +/* Flag bits. */ +#define GOING_TO_WINDOWS_MODE 1 +#define GOING_TO_VGA_MODE 2 +#define DISPLAY_DRIVER_DISABLED 4 +#define IN_WINDOWS_HIRES_MODE 8 + diff -r 000000000000 -r 20b4ed4eebe3 ddk/valmode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddk/valmode.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,20 @@ + +/* Return values for ValidateMode. */ +#define VALMODE_YES 0 /* Mode is good. */ +#define VALMODE_NO_WRONGDRV 1 /* Hardware not supported by driver. */ +#define VALMODE_NO_NOMEM 2 /* Insufficient video memory. */ +#define VALMODE_NO_NODAC 3 /* DAC cannot handle bit depth. */ +#define VALMODE_NO_UNKNOWN 4 /* Some other problem. */ + + +/* Structure describing a display mode. */ +typedef struct { + UINT dvmSize; /* Size of this struct. */ + UINT dvmBpp; /* Mode color depth. */ + int dvmXRes; /* Mode X resolution. */ + int dvmYRes; /* Mode Y resolution. */ +} DISPVALMODE; + +/* Must be exported by name from driver. Recommended ordinal is 700. */ +extern UINT WINAPI ValidateMode( DISPVALMODE FAR *lpMode ); + diff -r 000000000000 -r 20b4ed4eebe3 dibcall.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dibcall.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,85 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + + +#include "winhack.h" +#include +#include +#include "minidrv.h" + +/* + * What's this all about? Most of the required exported driver functions can + * be passed straight to the DIB Engine. The DIB Engine in some cases requires + * an additional parameter. + * + * See the dibthunk.asm module for functions that can be handled easily. Note + * that although the logic could be implemented in C, it can be done more + * efficiently in assembly. Forwarders turn into simple jumps, and functions + * with an extra parameter can be implemented with very small overhead, saving + * stack space and extra copying. + * + * This module deals with the very few functions that need additional logic but + * are not hardware specific. + */ + + +/* Exported as DISPLAY.104 */ +void WINAPI __loadds CheckCursor( void ) +{ + if( wEnabled ) { + DIB_CheckCursorExt( lpDriverPDevice ); + } +} + +/* If there is no hardware screen-to-screen BitBlt, there's no point in + * this and we can just forward BitBlt to the DIB Engine. + */ +#ifdef HWBLT + +extern BOOL WINAPI (* BitBltDevProc)( LPDIBENGINE, WORD, WORD, LPPDEVICE, WORD, WORD, + WORD, WORD, DWORD, LPBRUSH, LPDRAWMODE ); + +/* See if a hardware BitBlt can be done. */ +BOOL WINAPI BitBlt( LPDIBENGINE lpDestDev, WORD wDestX, WORD wDestY, LPPDEVICE lpSrcDev, + WORD wSrcX, WORD wSrcY, WORD wXext, WORD wYext, DWORD dwRop3, + LPBRUSH lpPBrush, LPDRAWMODE lpDrawMode ) +{ + WORD dstFlags = lpDestDev->deFlags; + + /* The destination must be video memory and not busy. */ + if( (dstFlags & VRAM) && !(dstFlags & BUSY) ) { + /* If palette translation is needed, only proceed if source + * and destination device are identical. + */ + if( !(dstFlags & PALETTE_XLAT) || (lpDestDev == lpSrcDev) ) { + /* If there is a hardware acceleration callback, use it. */ + if( BitBltDevProc ) { + return( BitBltDevProc( lpDestDev, wDestX, wDestY, lpSrcDev, wSrcX, wSrcY, wXext, wYext, dwRop3, lpPBrush, lpDrawMode ) ); + } + } + } + return( DIB_BitBlt( lpDestDev, wDestX, wDestY, lpSrcDev, wSrcX, wSrcY, wXext, wYext, dwRop3, lpPBrush, lpDrawMode ) ); +} + +#endif diff -r 000000000000 -r 20b4ed4eebe3 dibthunk.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dibthunk.asm Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,112 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Copyright (c) 2012-2022 Michal Necasek +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Define a macro which produces a DIB engine thunk, taking care of all +; externs and publics. +; The DIB_xxxExt functions take one additional parameter. To minimize +; stack space copying and usage, the thunk pops off the return address, +; pushes the additional parameter (always the last parameter of +; DIB_xxxExt), pushes the return address back, and jumps to DIB_xxxExt. +; The AX, ECX, and ES registers are modified with no ill effect since +; they aren't used by the Pascal calling convention to pass arguments. + +;; Thunk macro with additional parameters. +DIBTHK macro name, param +extrn DIB_&name&Ext : far +public name +name: + mov ax, DGROUP ; Load ES with our data segment. + mov es, ax + assume es:DGROUP + pop ecx ; Save the 16:16 return address in ECX. + push param ; Push the additional parameter. + push ecx ; Put the return address back. + jmp DIB_&name&Ext ; Off to the DIB Engine we go. + endm + +;; Simple forwarder macro. +DIBFWD macro name +extrn DIB_&name : far +public name +name: + jmp DIB_&name ; Just jump to the DIB Engine. + endm + +;; Additional variables that need to be pushed are in the data segment. +_DATA segment public 'DATA' + +extrn _lpDriverPDevice : dword +extrn _wPalettized : word + +_DATA ends + +DGROUP group _DATA + +_TEXT segment public 'CODE' + +.386 +assume ds:nothing, es:nothing + +;; Thunks that push an additional parameter. +;; Sorted by ordinal number. +DIBTHK EnumObj, _lpDriverPDevice +DIBTHK RealizeObject, _lpDriverPDevice +DIBTHK DibBlt, _wPalettized +DIBTHK GetPalette, _lpDriverPDevice +DIBTHK SetPaletteTranslate, _lpDriverPDevice +DIBTHK GetPaletteTranslate, _lpDriverPDevice +DIBTHK UpdateColors, _lpDriverPDevice +DIBTHK SetCursor, _lpDriverPDevice +DIBTHK MoveCursor, _lpDriverPDevice + +;; Forwarders that simply jump to the DIB Engine. +;; Sorted by ordinal number. +ifndef HWBLT +DIBFWD BitBlt +endif +DIBFWD ColorInfo +DIBFWD Control +DIBFWD EnumDFonts +DIBFWD Output +DIBFWD Pixel +DIBFWD Strblt +DIBFWD ScanLR +DIBFWD DeviceMode +DIBFWD ExtTextOut +DIBFWD GetCharWidth +DIBFWD DeviceBitmap +DIBFWD FastBorder +DIBFWD SetAttribute +DIBFWD CreateDIBitmap +DIBFWD DibToDevice +DIBFWD StretchBlt +DIBFWD StretchDIBits +DIBFWD SelectBitmap +DIBFWD BitmapBits +DIBFWD Inquire + +_TEXT ends + +end + diff -r 000000000000 -r 20b4ed4eebe3 enable.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/enable.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,453 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* GDI Enable (with ReEnable) and Disable implementation. */ + +#include "winhack.h" +#include +#include +#include +#include "minidrv.h" + +#include + +/* Pretend we have a 208 by 156 mm screen. */ +#define DISPLAY_HORZ_MM 208 +#define DISPLAY_VERT_MM 156 + +/* Size in English units. Looks pretty random. */ +#define DISPLAY_SIZE_EN 325 +/* Size in twips. Just as random. */ +#define DISPLAY_SIZE_TWP 2340 + +LPDIBENGINE lpDriverPDevice = 0; /* This device's PDEV that's passed to GDI. */ +WORD wEnabled = 0; /* Is this device enabled? */ +RGBQUAD FAR *lpColorTable = 0; /* Current color table. */ + +static BYTE bReEnabling = 0; /* Set when re-enabling PDEV. */ +static WORD wDIBPdevSize = 0; + + +/* 1bpp Color Table (non-palettized). */ +const DIBColorEntry DIB1ColorTable[] = { + /* blue red green flags */ + { 0 , 0 , 0 , 0 }, + { 0xFF, 0xFF, 0xFF, MAPTOWHITE } +}; + +/* 4bpp Color Table (non-palettized). */ +const DIBColorEntry DIB4ColorTable[] = { + /* blue red green flags */ + { 0 , 0 , 0 , 0 }, + { 0 , 0 , 0x80, 0 }, + { 0 , 0x80, 0 , 0 }, + { 0 , 0x80, 0x80, 0 }, + { 0x80, 0 , 0 , 0 }, + { 0x80, 0 , 0x80, 0 }, + { 0x80, 0x80, 0 , 0 }, + { 0xC0, 0xC0, 0xC0, MAPTOWHITE }, + { 0x80, 0x80, 0x80, MAPTOWHITE }, + { 0 , 0 , 0xFF, 0 }, + { 0 , 0xFF, 0 , MAPTOWHITE }, + { 0 , 0xFF, 0xFF, MAPTOWHITE }, + { 0xFF, 0 , 0 , 0 }, + { 0xFF, 0 , 0xFF, 0 }, + { 0xFF, 0xFF, 0 , MAPTOWHITE }, + { 0xFF, 0xFF, 0xFF, MAPTOWHITE } +}; + +/* 8bpp Color Table (palettized), first 10 entries. */ +const DIBColorEntry DIB8ColorTable1[] = { + /* blue red green flags */ + { 0 , 0 , 0 , 0 }, + { 0 , 0 , 0x80, 0 }, + { 0 , 0x80, 0 , 0 }, + { 0 , 0x80, 0x80, 0 }, + { 0x80, 0 , 0 , 0 }, + { 0x80, 0 , 0x80, 0 }, + { 0x80, 0x80, 0 , 0 }, + { 0xC0, 0xC0, 0xC0, MAPTOWHITE }, + { 0xC0, 0xDC, 0xC0, MAPTOWHITE | NONSTATIC }, + { 0xF0, 0xCA, 0xA6, MAPTOWHITE | NONSTATIC } +}; + +/* 8bpp Color Table (palettized), all middle entries (10-245). */ +const DIBColorEntry DIB8ColorTable2[] = { + /* blue red green flags */ + { 0, 0, 0, NONSTATIC } +}; + +/* 8bpp Color Table (palettized), last 10 entries (246-255). */ +const DIBColorEntry DIB8ColorTable3[] = { + /* blue red green flags */ + { 0xF0, 0xFB, 0xFF, MAPTOWHITE | NONSTATIC }, + { 0xA4, 0xA0, 0xA0, MAPTOWHITE | NONSTATIC }, + { 0x80, 0x80, 0x80, MAPTOWHITE }, + { 0 , 0 , 0xFF, 0 }, + { 0 , 0xFF, 0 , MAPTOWHITE }, + { 0 , 0xFF, 0xFF, MAPTOWHITE }, + { 0xFF, 0 , 0 , 0 }, + { 0xFF, 0 , 0xFF, 0 }, + { 0xFF, 0xFF, 0 , MAPTOWHITE }, + { 0xFF, 0xFF, 0xFF, MAPTOWHITE } +}; + + +/* An undocumented function called by USER to check if display driver + * contains a more suitable version of a resource. + * Exported as ordinal 450. + */ +DWORD WINAPI __loadds GetDriverResourceID( WORD wResID, LPSTR lpResType ) +{ + if( wResID == OBJ_FONT ) { + if( wDpi != 96 ) { + return( 2003 ); /* If DPI is not 96, return fonts120.bin instead. */ + } + } + return( wResID ); +} + +/* Some genius at Microsoft decided that CreateDIBPDevice returns the result + * in EAX, not DX:AX. This is not at all documented in the Win95 DDK, but it + * is stated clearly in U.S. Patent 6,525,743 (granted in 2003). + * We just create a tiny thunk to produce a sane calling convention. + */ +DWORD PASCAL CreateDIBPDeviceX( LPBITMAPINFO lpInfo, LPPDEVICE lpDevice, LPVOID lpBits, WORD wFlags ); +#pragma aux CreateDIBPDeviceX = \ + "call CreateDIBPDevice" \ + "mov dx, ax" \ + "shr eax, 16" \ + "xchg ax, dx" + +#pragma code_seg( _INIT ) + +/* GDI calls Enable twice at startup, first to query the GDIINFO structure + * and then to initialize the video hardware. + */ +UINT WINAPI __loadds Enable( LPVOID lpDevice, UINT style, LPSTR lpDeviceType, + LPSTR lpOutputFile, LPVOID lpStuff ) +{ + WORD rc; + WORD wPalCnt; + + dbg_printf( "Enable: lpDevice=%WP style=%X bReEnabling=%u wPalettized=%u\n", lpDevice, style, bReEnabling, wPalettized ); + if( !(style & 1) ) { /* Only test the low bit! */ + LPDIBENGINE lpEng = lpDevice; + LPBITMAPINFO lpInfo; + WORD wFlags; + DWORD dwRet; + + /* Initialize the PDEVICE. */ + lpDriverPDevice = lpDevice; + rc = PhysicalEnable(); + if( !rc ) { + dbg_printf( "Enable: PhysicalEnable failed!\n" ); + return( 0 ); + } + if( !bReEnabling ) { + int_2Fh( STOP_IO_TRAP ); + } + + /* Pass down to the DIB engine. */ + DIB_Enable( lpDevice, style, lpDeviceType, lpOutputFile, lpStuff ); + + if( wPalettized ) + DIB_SetPaletteTranslateExt( NULL, lpDriverPDevice ); + + dbg_printf( "Enable: wBpp=%u wDpi=%u wScreenX=%u wScreenY=%u wDIBPdevSize=%x\n", + wBpp, wDpi, wScreenX, wScreenY, wDIBPdevSize ); + + /* Fill out the bitmap header. */ + /// @todo Does wDIBPdevSize have to equal sizeof(DIBENGINE)? + lpInfo = (LPVOID)((LPBYTE)lpDevice + wDIBPdevSize); + _fmemset( &lpInfo->bmiHeader, 0, sizeof( lpInfo->bmiHeader ) ); + lpInfo->bmiHeader.biSize = sizeof( lpInfo->bmiHeader ); + lpInfo->bmiHeader.biWidth = wScreenX; + lpInfo->bmiHeader.biHeight = wScreenY; + lpInfo->bmiHeader.biPlanes = 1; + lpInfo->bmiHeader.biBitCount = wBpp; + + /* Set up the color table for non-direct color modes. */ + if( wBpp <= 8 ) { + DIBColorEntry FAR *lpDefaultClr; + + switch( wBpp ) { + case 8: + lpDefaultClr = DIB8ColorTable1; + wPalCnt = sizeof( DIB8ColorTable1 ); + break; + case 4: + lpDefaultClr = DIB4ColorTable; + wPalCnt = sizeof( DIB4ColorTable ); + break; + case 1: + default: + lpDefaultClr = DIB1ColorTable; + wPalCnt = sizeof( DIB1ColorTable ); + break; + } + lpColorTable = &lpInfo->bmiColors; + + if( !bReEnabling ) { + _fmemcpy( lpColorTable, lpDefaultClr, wPalCnt ); + /* For 8bpp, fix up the rest of the palette. */ + if( wBpp == 8 ) { + int i; + + /* The entries at index 10 to 245 are all the same. */ + for( i = 10; i < 246; ++i ) + lpColorTable[i] = DIB8ColorTable2[0]; + + _fmemcpy( &lpColorTable[246], DIB8ColorTable3, sizeof( DIB8ColorTable3 ) ); + } + } + } + + wFlags = wPDeviceFlags; + if( wPalettized ) + wFlags |= PALETTIZED; + + /* Call the DIB Engine to set up the PDevice. */ + dbg_printf( "lpInfo=%WP lpDevice=%WP lpColorTable=%WP wFlags=%X ScreenSelector=%X\n", lpInfo, lpDevice, lpColorTable, wFlags, ScreenSelector ); + dwRet = CreateDIBPDeviceX( lpInfo, lpDevice, ScreenSelector :> 0, wFlags ); + if( !dwRet ) { + dbg_printf( "Enable: CreateDIBPDevice failed!\n" ); + return( 0 ); + } + dbg_printf( "Enable: CreateDIBPDevice returned %lX\n", dwRet ); + + /* Now fill out the begin/end access callbacks. */ + lpEng->deBeginAccess = DIB_BeginAccess; + lpEng->deEndAccess = DIB_EndAccess; + + /* Program the DAC in non-direct color modes. */ + if( wBpp <= 8 ) { + switch( wBpp ) { + case 8: + wPalCnt = 256; + break; + case 4: + wPalCnt = 16; + break; + case 1: + default: + wPalCnt = 2; + break; + } + SetRAMDAC_far( 0, wPalCnt, lpColorTable ); + } + + if( !bReEnabling ) { + HookInt2Fh(); + } + wEnabled = 1; + return( 1 ); + } else { + /* Fill out GDIINFO for GDI. */ + LPGDIINFO lpInfo = lpDevice; + + /* Start with passing down to the DIB engine. It will set dpCurves through dpStyleLen. */ + DIB_Enable( lpDevice, style, lpDeviceType, lpOutputFile, lpStuff ); + + /* Fill out some static data. Note that some fields are set by the DIB Engine + * and we don't touch them (curves, lines, polygons etc.). + */ + lpInfo->dpVersion = DRV_VERSION; + lpInfo->dpTechnology = DT_RASDISPLAY; + lpInfo->dpHorzSize = DISPLAY_HORZ_MM; + lpInfo->dpVertSize = DISPLAY_VERT_MM; + lpInfo->dpPlanes = 1; + lpInfo->dpCapsFE = 0; + lpInfo->dpNumFonts = 0; + + /* Now set the fields that depend on current mode. */ + lpInfo->dpHorzRes = wScrX; + lpInfo->dpVertRes = wScrY; + + lpInfo->dpMLoWin.xcoord = DISPLAY_HORZ_MM * 10; + lpInfo->dpMLoWin.ycoord = DISPLAY_VERT_MM * 10; + lpInfo->dpMLoVpt.xcoord = wScrX; + lpInfo->dpMLoVpt.ycoord = -wScrY; + + lpInfo->dpMHiWin.xcoord = DISPLAY_HORZ_MM * 100; + lpInfo->dpMHiWin.ycoord = DISPLAY_VERT_MM * 100; + lpInfo->dpMHiVpt.xcoord = wScrX; + lpInfo->dpMHiVpt.ycoord = -wScrY; + + /* These calculations are a wild guess and probably don't matter. */ + lpInfo->dpELoWin.xcoord = DISPLAY_SIZE_EN; + lpInfo->dpELoWin.ycoord = DISPLAY_SIZE_EN; + lpInfo->dpELoVpt.xcoord = wScrX / 5; + lpInfo->dpELoVpt.ycoord = -lpInfo->dpELoVpt.xcoord; + + lpInfo->dpELoWin.xcoord = DISPLAY_SIZE_EN * 5; + lpInfo->dpELoWin.ycoord = DISPLAY_SIZE_EN * 5; + lpInfo->dpEHiVpt.xcoord = wScrX / 10; + lpInfo->dpEHiVpt.ycoord = -lpInfo->dpEHiVpt.xcoord; + + lpInfo->dpTwpWin.xcoord = DISPLAY_SIZE_TWP; + lpInfo->dpTwpWin.ycoord = DISPLAY_SIZE_TWP; + lpInfo->dpTwpVpt.xcoord = wScrX / 10; + lpInfo->dpTwpVpt.ycoord = -lpInfo->dpTwpVpt.xcoord; + + /* Update more GDIINFO bits. */ + lpInfo->dpLogPixelsX = wDpi; + lpInfo->dpLogPixelsY = wDpi; + lpInfo->dpBitsPixel = wBpp; + lpInfo->dpDCManage = DC_IgnoreDFNP; + lpInfo->dpCaps1 |= C1_BYTE_PACKED | C1_COLORCURSOR | C1_REINIT_ABLE | C1_SLOW_CARD; + + /* Grab the DIB Engine PDevice size before we add to it. */ + wDIBPdevSize = lpInfo->dpDEVICEsize; + dbg_printf( "Enable: wDIBPdevSize=%X wScrX=%u wScrY=%u wBpp=%u wDpi=%u wScreenX=%u wScreenY=%u\n", + wDIBPdevSize, wScrX, wScrY, wBpp, wDpi, wScreenX, wScreenY ); + + lpInfo->dpNumBrushes = -1; /* Too many to count, always the same.. */ + + if( wBpp == 8 ) { + if( wPalettized ) { + lpInfo->dpNumPens = 16; /* Pens realized by driver. */ + lpInfo->dpNumColors = 20; /* Colors in color table. */ + lpInfo->dpNumPalReg = 256; + lpInfo->dpPalReserved = 20; + lpInfo->dpColorRes = 18; + lpInfo->dpRaster |= RC_DIBTODEV + RC_PALETTE + RC_SAVEBITMAP; + } else { + lpInfo->dpNumPens = 256; /* Pens realized by driver. */ + lpInfo->dpNumColors = 256; /* Colors in color table. */ + lpInfo->dpNumPalReg = 0; + lpInfo->dpPalReserved = 0; + lpInfo->dpColorRes = 0; + lpInfo->dpRaster |= RC_DIBTODEV; + } + lpInfo->dpDEVICEsize += sizeof( BITMAPINFOHEADER ) + 256 * 4; + } else if( wBpp > 8 ) { + lpInfo->dpNumPens = -1; /* Pens realized by driver. */ + lpInfo->dpNumColors = -1; /* Colors in color table. */ + lpInfo->dpNumPalReg = 0; + lpInfo->dpPalReserved = 0; + lpInfo->dpColorRes = 0; + lpInfo->dpRaster |= RC_DIBTODEV; + lpInfo->dpDEVICEsize += sizeof( BITMAPINFOHEADER ); + } else if( wBpp < 8 ) { + WORD wCount; + + wCount = 1 << wBpp; /* 2 or 4 for 2 or 16 bpp. */ + lpInfo->dpNumPens = wCount; /* Pens realized by driver. */ + lpInfo->dpNumColors = wCount; /* Colors in color table. */ + lpInfo->dpNumPalReg = 0; + lpInfo->dpPalReserved = 0; + lpInfo->dpColorRes = 0; + lpInfo->dpRaster |= RC_DIBTODEV; + wCount *= 4; + lpInfo->dpDEVICEsize += sizeof( BITMAPINFOHEADER ) + 8 + wCount; + } + dbg_printf( "sizeof(GDIINFO)=%d (%X), dpDEVICEsize=%X\n", sizeof( GDIINFO ), sizeof( GDIINFO ), lpInfo->dpDEVICEsize ); + return( sizeof( GDIINFO ) ); + } +} + + +/* The ReEnable function is called to dynamically change resolution. + * It must query the new display mode settings and then call Enable. + * NB: Windows 9x will not dynamically change the color depth, only + * resolution. Documented in MS KB Article Q127139. + */ +UINT WINAPI __loadds ReEnable( LPVOID lpDevice, LPGDIINFO lpInfo ) +{ + WORD wLastValidBpp = wBpp; + WORD wLastValidX = wScreenX; + WORD wLastValidY = wScreenY; + WORD rc; + + dbg_printf( "ReEnable: lpDevice=%WP lpInfo=%WP wScreenX=%u wScreenY=%u\n", lpDevice, lpInfo, wScreenX, wScreenY ); + + /* Figure out the new mode. */ + ReadDisplayConfig(); + dbg_printf( "ReEnable: wScreenX=%u wScreenY=%u wBpp=%u\n", wScreenX, wScreenY, wBpp ); + + /* Let Enable know it doesn't need to do everything. */ + bReEnabling = 1; + + /* Don't let the cursor mess with things. */ + DIB_BeginAccess( lpDevice, 0, 0, wScreenX - 1, wScreenY - 1, CURSOREXCLUDE ); + + /* Create a new PDevice and set the new mode. Returns zero on failure. */ + rc = Enable( lpDevice, 0, NULL, NULL, NULL ); + + /* Drawing the cursor is safe again. */ + DIB_EndAccess( lpDevice, CURSOREXCLUDE ); + + if( rc ) { + /* Enable succeeded, fill out GDIINFO. */ + Enable( lpInfo, 1, NULL, NULL, NULL ); + rc = 1; + } else { + dbg_printf( "ReEnable: Enable failed!\n" ); + /* Couldn't set new mode. Try to get the old one back. */ + wScreenX = wLastValidX; + wScreenY = wLastValidY; + wBpp = wLastValidBpp; + + Enable( lpDevice, 0, NULL, NULL, NULL ); + + /* And force a repaint. */ + RepaintFunc(); + rc = 0; + } + + bReEnabling = 0; + return( rc ); +} + +void int_10h( unsigned ax ); +#pragma aux int_10h = \ + "int 10h" \ + parm [ax]; + +/* Disable graphics and go back to a text mode. */ +UINT WINAPI __loadds Disable( LPVOID lpDevice ) +{ + LPDIBENGINE lpEng = lpDevice; + + dbg_printf( "Disable: lpDevice=%WP\n", lpDevice ); + + /* Start disabling and mark the PDevice busy. */ + wEnabled = 0; + lpEng->deFlags |= BUSY; /// @todo Does this need to be a locked op? + + /* Re-enable I/O trapping before we start setting a standard VGA mode. */ + int_2Fh( START_IO_TRAP ); + + /* Tell VDD we're going away. */ + CallVDD( VDD_DRIVER_UNREGISTER ); + + /* Set standard 80x25 text mode using the BIOS. */ + int_10h( 3 ); + + /* And unhook INT 2F. */ + UnhookInt2Fh(); + + return( 1 ); +} diff -r 000000000000 -r 20b4ed4eebe3 init.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/init.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,172 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* Display driver module initialization. */ + +#include "winhack.h" +#include +#include +#include +#include "minidrv.h" + + +/* GlobalSmartPageLock is a semi-undocumented function. Not officially + * documented but described in KB Article Q180586. */ +UINT WINAPI GlobalSmartPageLock( HGLOBAL hglb ); + +WORD wScrX = 640; /* Current X resolution. */ +WORD wScrY = 480; /* Current Y resolution. */ +WORD wDpi = 96; /* Current DPI setting. */ +WORD wBpp = 8; /* Current BPP setting. */ +WORD wPalettized = 0; /* Non-zero if palettized. */ + +WORD OurVMHandle = 0; /* The current VM's ID. */ +DWORD VDDEntryPoint = 0; /* The VDD entry point. */ + +/* On Entry: + * EAX = Function code (VDD_GET_DISPLAY_CONFIG) + * EBX = This VM's handle + * ECX = Size of DISPLAYINFO structure + * EDX = Zero to tell VDD to try virtualizing + * ES:EDI = Pointer to DISPLAYINFO structure to be + * filled + * + * On Return: + * EAX = Return code (0 = succeess, -1 = failed) + */ +extern DWORD CallVDDGetDispConf( WORD Function, WORD wDInfSize, LPVOID pDInf ); +#pragma aux CallVDDGetDispConf = \ + ".386" \ + "movzx eax, ax" \ + "movzx ecx, cx" \ + "movzx ebx, OurVMHandle" \ + "movzx edi, di" \ + "call dword ptr VDDEntryPoint"\ + "mov edx, eax" \ + "shr edx, 16" \ + parm [ax] [cx] [es di]; + + +#pragma code_seg( _INIT ) + +/* Read the display settings from SYSTEM.INI or Registry. + */ +void ReadDisplayConfig( void ) +{ + WORD wX, wY; + UINT bIgnoreRegistry; + MODEDESC mode; + + /* Get the DPI, default to 96. */ + wDpi = GetPrivateProfileInt( "display", "dpi", 96, "system.ini" ); + + /* Get X and Y resolution. */ + wX = GetPrivateProfileInt( "display", "x_resolution", 0, "system.ini" ); + wY = GetPrivateProfileInt( "display", "y_resolution", 0, "system.ini" ); + + /* Get the bits per pixel. */ + wBpp = GetPrivateProfileInt( "display", "bpp", 0, "system.ini" ); + + dbg_printf( "SYSTEM.INI: %ux%u %ubpp %udpi\n", wX, wY, wBpp, wDpi ); + + bIgnoreRegistry = GetPrivateProfileInt( "display", "IgnoreRegistry", 0, "system.ini" ); + + if( !bIgnoreRegistry ) { + DISPLAYINFO DispInfo; + DWORD dwRc; + + dwRc = CallVDDGetDispConf( VDD_GET_DISPLAY_CONFIG, sizeof( DispInfo ), &DispInfo ); + if( (dwRc != VDD_GET_DISPLAY_CONFIG) && !dwRc ) { + /* Call succeeded, use the data. */ + wScrX = DispInfo.diXRes; + wScrY = DispInfo.diYRes; + wBpp = DispInfo.diBpp; + + dbg_printf( "Registry: %ux%u %ubpp %udpi\n", DispInfo.diXRes, DispInfo.diYRes, DispInfo.diBpp, DispInfo.diDPI ); + + /* DPI might not be set, careful. */ + if( DispInfo.diDPI ) + wDpi = DispInfo.diDPI; + } else { + dbg_printf( "VDD_GET_DISPLAY_CONFIG failed, dwRc=%lX\n",dwRc ); + } + } + + mode.xRes = wScrX; + mode.yRes = wScrY; + mode.bpp = wBpp; + + if( !FixModeInfo( &mode ) ) { + /* Values were changed. */ + wScrX = mode.xRes; + wScrY = mode.yRes; + wBpp = mode.bpp; + } + + /* For 8bpp, read the 'palettized' setting. Default to enabled. */ + if( wBpp == 8 ) + wPalettized = GetPrivateProfileInt( "display", "palettized", 1, "system.ini" ); + else + wPalettized = 0; +} + +#define VDD_ID 10 /* Virtual Display Driver ID. */ + +/* Get Device API Entry Point. */ +void __far *int_2F_GetEP( unsigned ax, unsigned bx ); +#pragma aux int_2F_GetEP = \ + "int 2Fh" \ + parm [ax] [bx] value [es di]; + +/* Get "magic number" (current Virtual Machine ID) for VDD calls. */ +WORD int_2F_GetVMID( unsigned ax ); +#pragma aux int_2F_GetVMID = \ + "int 2Fh" \ + parm [ax] value [bx]; + +/* Dummy pointer to get at the _TEXT segment. Is there any easier way? */ +extern char __based( __segname( "_TEXT" ) ) *pText; + +/* This is a standard DLL entry point. Note that DS is already set + * to point to this DLL's data segment on entry. + */ +#pragma aux DriverInit parm [cx] [di] [es si] +UINT FAR DriverInit( UINT cbHeap, UINT hModule, LPSTR lpCmdLine ) +{ + /* Lock the code segment. */ + GlobalSmartPageLock( (__segment)pText ); + + /* Query the entry point of the Virtual Display Device. */ + VDDEntryPoint = (DWORD)int_2F_GetEP( 0x1684, VDD_ID ); + + /* Obtain the "magic number" needed for VDD calls. */ + OurVMHandle = int_2F_GetVMID( 0x1683 ); + + dbg_printf( "DriverInit: VDDEntryPoint=%WP, OurVMHandle=%x\n", VDDEntryPoint, OurVMHandle ); + + /* Read the display configuration before doing anything else. */ + ReadDisplayConfig(); + + return( 1 ); /* Success. */ +} diff -r 000000000000 -r 20b4ed4eebe3 makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/makefile Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,104 @@ +OBJS = dibthunk.obj dibcall.obj enable.obj init.obj palette.obj & + scrsw.obj sswhook.obj modes.obj boxv.obj + +INCS = -I$(%WATCOM)\h\win -Iddk + +# Define HWBLT if BitBlt can be accelerated. +#FLAGS = -DHWBLT + +# Set DBGPRINT to add debug printf logging. +# DBGPRINT = 1 +!ifdef DBGPRINT +FLAGS += -DDBGPRINT +OBJS += dbgprint.obj +# Need this to work with pre-made boxv9x.lnk +DBGFILE = file dbgprint.obj +!else +DBGFILE = +!endif + +boxvmini.drv : $(OBJS) display.res dibeng.lib boxv9x.lnk + wlink op quiet, start=DriverInit_ disable 2055 @boxv9x.lnk $(DBGFILE) + wrc -q display.res $@ + +# Linker script +boxv9x.lnk : boxv9x.def + ms2wlink $(OBJS),boxvmini.drv,boxvmini.map,dibeng.lib clibs.lib,boxv9x.def > boxv9x.lnk + +# Object files +boxv.obj : boxv.c .autodepend + wcc -q -wx -s -zu -zls -3 $(FLAGS) $< + +dbgprint.obj : dbgprint.c .autodepend + wcc -q -wx -s -zu -zls -3 $(FLAGS) $< + +dibcall.obj : dibcall.c .autodepend + wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< + +dibthunk.obj : dibthunk.asm + wasm -q $(FLAGS) $< + +enable.obj : enable.c .autodepend + wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< + +init.obj : init.c .autodepend + wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< + +palette.obj : palette.c .autodepend + wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< + +sswhook.obj : sswhook.asm + wasm -q $(FLAGS) $< + +modes.obj : modes.c .autodepend + wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< + +scrsw.obj : scrsw.c .autodepend + wcc -q -wx -s -zu -zls -3 -zW $(INCS) $(FLAGS) $< + +# Resources +display.res : res/display.rc res/colortab.bin res/config.bin res/fonts.bin res/fonts120.bin .autodepend + wrc -q -r -ad -bt=windows -fo=$@ -Ires -I$(%WATCOM)/h/win res/display.rc + +res/colortab.bin : res/colortab.c + wcc -q $(INCS) $< + wlink op quiet disable 1014, 1023 name $@ sys dos output raw file colortab.obj + +res/config.bin : res/config.c + wcc -q $(INCS) $< + wlink op quiet disable 1014, 1023 name $@ sys dos output raw file config.obj + +res/fonts.bin : res/fonts.c .autodepend + wcc -q $(INCS) $< + wlink op quiet disable 1014, 1023 name $@ sys dos output raw file fonts.obj + +res/fonts120.bin : res/fonts120.c .autodepend + wcc -q $(INCS) $< + wlink op quiet disable 1014, 1023 name $@ sys dos output raw file fonts120.obj + +# Libraries +dibeng.lib : ddk/dibeng.lbc + wlib -b -q -n -fo -ii @$< $@ + +# Cleanup +clean : .symbolic + rm *.obj + rm *.err + rm *.lib + rm *.drv + rm *.map + rm *.res + rm *.img + rm res/*.obj + rm res/*.bin + +image : .symbolic boxv9x.img + +# Create a 1.44MB distribution floppy image. +# NB: The mkimage tool is not supplied. +boxv9x.img : boxvmini.drv boxv9x.inf readme.txt + if not exist dist mkdir dist + copy boxvmini.drv dist + copy boxv9x.inf dist + copy readme.txt dist + mkimage -l BOXV9X -o boxv9x.img dist diff -r 000000000000 -r 20b4ed4eebe3 minidrv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/minidrv.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,99 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* First definitions that don't appear to be in any "official" header. */ + +#define DRV_VERSION 0x0400 /* Windows 4.0 aka Windows 95. */ + +/* Int 2Fh subfunctions. */ +#define STOP_IO_TRAP 0x4000 /* Stop trapping video I/O. */ +#define SCREEN_SWITCH_OUT 0x4001 /* DOS session going to background. */ +#define SCREEN_SWITCH_IN 0x4002 /* DOS session going to foreground. */ +#define ENTER_CRIT_REG 0x4003 /* Enter critical section notification. */ +#define EXIT_CRIT_REG 0x4004 /* Leave critical section notification. */ +#define START_IO_TRAP 0x4007 /* Start trapping video I/O. */ + +/* Internal interfaces within minidriver. */ + +/* A simple mode descriptor structure. */ +typedef struct { + WORD xRes; + WORD yRes; + WORD bpp; +} MODEDESC, FAR *LPMODEDESC; + + +extern WORD FixModeInfo( LPMODEDESC lpMode ); +extern int PhysicalEnable( void ); +extern void FAR SetRAMDAC_far( UINT bStart, UINT bCount, RGBQUAD FAR *lpPal ); +extern void ReadDisplayConfig( void ); +extern void FAR RestoreDesktopMode( void ); +extern FARPROC RepaintFunc; +extern void HookInt2Fh( void ); +extern void UnhookInt2Fh( void ); + +#ifdef DBGPRINT +extern void dbg_printf( const char *s, ... ); +#else +/* The "Meaningless use of an expression" warning gets too annoying. */ +#pragma disable_message( 111 ); +#define dbg_printf 1 ? (void)0 : (void) +#endif + +extern LPDIBENGINE lpDriverPDevice; /* DIB Engine PDevice. */ +extern WORD ScreenSelector; /* Selector of video memory. */ +extern WORD wPalettized; /* Non-zero if palettized device. */ +extern WORD wPDeviceFlags; /* Current GDI device flags. */ +extern WORD wDpi; /* Current DPI. */ +extern WORD wBpp; /* Current bits per pixel. */ +extern WORD wScrX; /* Configured X resolution. */ +extern WORD wScrY; /* Configured Y resolution. */ +extern WORD wScreenX; /* Screen width in pixels. */ +extern WORD wScreenY; /* Screen height in pixels. */ +extern WORD wEnabled; /* PDevice enabled flag. */ +extern RGBQUAD FAR *lpColorTable; /* Current color table. */ + +extern DWORD VDDEntryPoint; +extern WORD OurVMHandle; + +/* Inlines needed in multiple modules. */ + +void int_2Fh( unsigned ax ); +#pragma aux int_2Fh = \ + "int 2Fh" \ + parm [ax]; + +/* NB: It's unclear of EAX/EBX really need preserving. */ +extern void CallVDD( unsigned Function ); +#pragma aux CallVDD = \ + ".386" \ + "push eax" \ + "push ebx" \ + "movzx eax, ax" \ + "movzx ebx, OurVMHandle" \ + "call dword ptr VDDEntryPoint" \ + "pop ebx" \ + "pop eax" \ + parm [ax]; + diff -r 000000000000 -r 20b4ed4eebe3 modes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modes.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,427 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* Display driver mode management. */ + +#include "winhack.h" +#include +#include +#include +#include +#include "minidrv.h" +#include "boxv.h" + + +/* Somewhat arbitrary max resolution. */ +#define RES_MAX_X (5 * 1024) +#define RES_MAX_Y (5 * 768) + + +/* Generic DPMI calls, only used in this module. */ +extern WORD DPMI_AllocLDTDesc( WORD cSelectors ); +#pragma aux DPMI_AllocLDTDesc = \ + "xor ax, ax" \ + "int 31h" \ + "jnc OK" \ + "xor ax, ax" \ + "OK:" \ + parm [cx]; + +extern DWORD DPMI_GetSegBase( WORD Selector ); +#pragma aux DPMI_GetSegBase = \ + "mov ax, 6" \ + "int 31h" \ + "mov ax, cx" \ + "xchg ax, dx" \ + parm [bx] modify [cx]; + +extern void DPMI_SetSegBase( WORD Selector, DWORD Base ); +#pragma aux DPMI_SetSegBase = \ + "mov ax, 7" \ + "int 31h" \ + parm [bx] [cx dx]; + +extern void DPMI_SetSegLimit( WORD Selector, DWORD Limit ); +#pragma aux DPMI_SetSegLimit = \ + "mov ax, 8" \ + "int 31h" \ + parm [bx] [cx dx]; + +/* NB: Compiler insists on CX:BX and DI:SI, DPMI needs it word swapped. */ +extern DWORD DPMI_MapPhys( DWORD Base, DWORD Size ); +#pragma aux DPMI_MapPhys = \ + "xchg cx, bx" \ + "xchg si, di" \ + "mov ax, 800h" \ + "int 31h" \ + "jnc OK" \ + "xor bx, bx" \ + "xor cx, cx" \ + "OK:" \ + "mov dx, bx" \ + "mov ax, cx" \ + parm [cx bx] [di si]; + + +WORD wScreenX = 0; +WORD wScreenY = 0; +WORD BitBltDevProc = 0; +WORD ScreenSelector = 0; +WORD wPDeviceFlags = 0; + +static DWORD dwScreenFlatAddr = 0; /* 32-bit flat address of VRAM. */ +static DWORD dwVideoMemorySize = 0; /* Installed VRAM in bytes. */ +static WORD wScreenPitchBytes = 0; /* Current scanline pitch. */ +static DWORD dwPhysVRAM = 0; /* Physical LFB base address. */ + +/* These are currently calculated not needed in the absence of + * offscreen video memory. + */ +static WORD wMaxWidth = 0; +static WORD wMaxHeight = 0; + +/* On Entry: + * EAX = Function code (VDD_DRIVER_REGISTER) + * EBX = This VM's handle + * ECX = Size of all visible scanlines in bytes + * EDX = Zero to tell VDD to try virtualizing + * ES:DI = Pointer to function called when switching + * back from fullscreen. + * + * On Return: + * EAX = Amount of video memory used by VDD in bytes, + * or function code if VDD call failed. + */ +extern DWORD CallVDDRegister( WORD Function, WORD wPitch, WORD wHeight, void _far *fRHR ); +#pragma aux CallVDDRegister = \ + ".386" \ + "movzx eax, ax" \ + "movzx edx, dx" \ + "mul edx" \ + "mov ecx, eax" \ + "movzx eax, bx" \ + "movzx ebx, OurVMHandle" \ + "xor edx, edx" \ + "call dword ptr VDDEntryPoint"\ + "mov edx, eax" \ + "shr edx, 16" \ + parm [bx] [ax] [dx] [es di]; + + +#pragma code_seg( _INIT ); + +/* Take a mode descriptor and change it to be a valid + * mode if it isn't already. Return zero if mode needed + * fixing (wasn't valid). + */ +WORD FixModeInfo( LPMODEDESC lpMode ) +{ + WORD rc = 1; /* Assume valid mode. */ + + /* First validate bits per pixel. */ + switch( lpMode->bpp ) { + case 8: + case 16: + case 24: + case 32: + break; + default: + lpMode->bpp = 8; /* Default to 8 bpp. */ + rc = 0; /* Mode wasn't valid. */ + } + + /* Validate mode. If resolution is under 640x480 in + * either direction, force 640x480. + */ + if( lpMode->xRes < 640 || lpMode->yRes < 480 ) + { + lpMode->xRes = 640; /* Force 640x480. */ + lpMode->yRes = 480; + rc = 0; /* Mode wasn't valid. */ + } + + /* Clip the resolution to something that probably won't make + * Windows have a cow. + */ + if( lpMode->xRes > RES_MAX_X ) { + lpMode->xRes = RES_MAX_X; + rc = 0; + } + if( lpMode->yRes > RES_MAX_Y ) { + lpMode->yRes = RES_MAX_Y; + rc = 0; + } + + return( rc ); +} + + +/* Calculate pitch for a given horizontal resolution and bpp. */ +WORD CalcPitch( WORD x, WORD bpp ) +{ + WORD wPitch; + + /* Valid BPP must be a multiple of 8 so it's simple. */ + wPitch = x * (bpp / 8); + + /* Align to 32 bits. */ + wPitch = (wPitch + 3) & ~3; + + return( wPitch ); +} + + +/* Return non-zero if given mode is supported. */ +static int IsModeOK( WORD wXRes, WORD wYRes, WORD wBpp ) +{ + MODEDESC mode; + DWORD dwModeMem; + + mode.bpp = wBpp; + mode.xRes = wXRes; + mode.yRes = wYRes; + + /* If mode needed fixing, it's not valid. */ + if( !FixModeInfo( &mode ) ) + return( 0 ); + + /* Make sure there's enough VRAM for it. */ + dwModeMem = (DWORD)CalcPitch( wXRes, wBpp ) * wYRes; + if( dwModeMem > dwVideoMemorySize ) + return( 0 ); + + return( 1 ); +} + + +/* Clear the visible screen by setting it to all black (zeros). + * NB: Assumes there is no off-screen region to the right of + * the visible area. + */ +static void ClearVisibleScreen( void ) +{ + LPDWORD lpScr; + WORD wLines = wScreenY; + WORD i; + + lpScr = ScreenSelector :> 0; + + while( wLines-- ) { + for( i = 0; i < wScreenPitchBytes / 4; ++i ) + lpScr[i] = 0; + lpScr += wScreenPitchBytes; /* Scanline pitch. */ + } +} + + +static DWORD AllocLinearSelector( DWORD dwPhysAddr, DWORD dwSize ) +{ + WORD wSel; + DWORD dwLinear; + + wSel = DPMI_AllocLDTDesc( 1 ); /* One descriptor, please. */ + if( !wSel ) + return( 0 ); + + /* Map the framebuffer physical memory. */ + dwLinear = DPMI_MapPhys( dwPhysAddr, dwSize ); + + /* Now set the allocated selector to point to VRAM. */ + DPMI_SetSegBase( wSel, dwLinear ); + DPMI_SetSegLimit( wSel, dwSize - 1 ); + + return( wSel ); +} + + +/* Set the currently configured mode (wXRes/wYRes) in hardware. + * If bFullSet is non-zero, then also reinitialize globals. + * When re-establishing a previously set mode (e.g. coming + * back from fullscreen), bFullSet will be zero. + * NB: BPP won't change at runtime. + */ +static int SetDisplayMode( WORD wXRes, WORD wYRes, int bFullSet ) +{ + dbg_printf( "SetDisplayMode: wXRes=%u wYRes=%u\n", wXRes, wYRes ); + + /* Inform the VDD that the mode is about to change. */ + CallVDD( VDD_PRE_MODE_CHANGE ); + + BOXV_ext_mode_set( 0, wXRes, wYRes, wBpp, wXRes, wYRes ); + + if( bFullSet ) { + wScreenX = wXRes; + wScreenY = wYRes; + + wScreenPitchBytes = CalcPitch( wXRes, wBpp ); + BitBltDevProc = NULL; /* No acceleration implemented. */ + wPDeviceFlags = MINIDRIVER | VRAM; + if( wBpp == 16 ) { + wPDeviceFlags |= FIVE6FIVE; /* Needed for 16bpp modes. */ + } + + wMaxWidth = wScreenPitchBytes / (wBpp / 8); /* We know bpp is a multiple of 8. */ + wMaxHeight = dwVideoMemorySize / wScreenPitchBytes; + + /* Offscreen regions could be calculated here. We do not use those. */ + } + return( 1 ); +} + + +/* Forward declaration. */ +void __far RestoreDesktopMode( void ); + +int PhysicalEnable( void ) +{ + DWORD dwRegRet; + + if( !ScreenSelector ) { + int iChipID; + + /* Extra work if driver hasn't yet been initialized. */ + iChipID = BOXV_detect( 0, &dwVideoMemorySize ); + if( !iChipID ) { + return( 0 ); + } + dwPhysVRAM = BOXV_get_lfb_base( 0 ); + dbg_printf( "PhysicalEnable: Hardware detected, dwVideoMemorySize=%lX dwPhysVRAM=%lX\n", dwVideoMemorySize, dwPhysVRAM ); + } + + if( !IsModeOK( wScrX, wScrY, wBpp ) ) { + /* Can't find mode, oopsie. */ + dbg_printf( "PhysicalEnable: Mode not valid! wScrX=%u wScrY=%u wBpp=%u\n", wScrX, wScrY, wBpp ); + return( 0 ); + } + + if( !SetDisplayMode( wScrX, wScrY, 1 ) ) { + /* This is not good. */ + dbg_printf( "PhysicalEnable: SetDisplayMode failed! wScrX=%u wScrY=%u wBpp=%u\n", wScrX, wScrY, wBpp ); + return( 0 ); + } + + /* Allocate an LDT selector for the screen. */ + if( !ScreenSelector ) { + ScreenSelector = AllocLinearSelector( dwPhysVRAM, dwVideoMemorySize ); + if( !ScreenSelector ) { + dbg_printf( "PhysicalEnable: AllocScreenSelector failed!\n" ); + return( 0 ); + } + } + + /* NB: Currently not used. DirectDraw would need the segment base. */ + dwScreenFlatAddr = DPMI_GetSegBase( ScreenSelector ); /* Not expected to fail. */ + + dbg_printf( "PhysicalEnable: RestoreDesktopMode is at %WP\n", RestoreDesktopMode ); + dwRegRet = CallVDDRegister( VDD_DRIVER_REGISTER, wScreenPitchBytes, wScreenY, RestoreDesktopMode ); + if( dwRegRet != VDD_DRIVER_REGISTER ) { + /* NB: It's not fatal if CallVDDRegister() fails. */ + /// @todo What can we do with the returned value? + } + + /* Let the VDD know that the mode changed. */ + CallVDD( VDD_POST_MODE_CHANGE ); + CallVDD( VDD_SAVE_DRIVER_STATE ); + + ClearVisibleScreen(); + + return( 1 ); /* All good. */ +} + + +/* Check if the requested mode can be set. Return yes, no (with a reason), + * or maybe. . + * Must be exported by name, recommended ordinal 700. + * NB: Can be called when the driver is not the current display driver. + */ +#pragma aux ValidateMode loadds; /* __loadds not operational due to prototype in valmode.h */ +UINT WINAPI __loadds ValidateMode( DISPVALMODE FAR *lpValMode ) +{ + UINT rc = VALMODE_YES; + + dbg_printf( "ValidateMode: X=%u Y=%u bpp=%u\n", lpValMode->dvmXRes, lpValMode->dvmYRes, lpValMode->dvmBpp ); + do { + if( !ScreenSelector ) { + int iChipID; + + /* Additional checks if driver isn't running. */ + iChipID = BOXV_detect( 0, &dwVideoMemorySize ); + if( !iChipID ) { + rc = VALMODE_NO_WRONGDRV; + break; + } + dwPhysVRAM = BOXV_get_lfb_base( 0 ); + dbg_printf( "ValidateMode: Hardware detected, dwVideoMemorySize=%lX dwPhysVRAM=%lX\n", dwVideoMemorySize, dwPhysVRAM ); + } + + if( !IsModeOK( lpValMode->dvmXRes, lpValMode->dvmYRes, lpValMode->dvmBpp ) ) { + rc = VALMODE_NO_NOMEM; + } + } while( 0 ); + + dbg_printf( "ValidateMode: rc=%u\n", rc ); + return( rc ); +} + +#pragma code_seg( _TEXT ); + +/* Called by the VDD in order to restore the video state when switching back + * to the system VM. Function is in locked memory (_TEXT segment). + * NB: Must reload DS, but apparently need not save/restore DS. + */ +#pragma aux RestoreDesktopMode loadds; +void __far RestoreDesktopMode( void ) +{ + dbg_printf( "RestoreDesktopMode: %ux%u, wBpp=%u\n", wScreenX, wScreenY, wBpp ); + + /* Set the current desktop mode again. */ + SetDisplayMode( wScreenX, wScreenY, 0 ); + + /* Reprogram the DAC if relevant. */ + if( wBpp <= 8 ) { + UINT wPalCnt; + + switch( wBpp ) { + case 8: + wPalCnt = 256; + break; + case 4: + wPalCnt = 16; + break; + default: + wPalCnt = 2; + break; + } + SetRAMDAC_far( 0, wPalCnt, lpColorTable ); + } + + /* Clear the busy flag. Quite important. */ + lpDriverPDevice->deFlags &= ~BUSY; + + /* Poke the VDD now that everything is restored. */ + CallVDD( VDD_SAVE_DRIVER_STATE ); + + ClearVisibleScreen(); +} + diff -r 000000000000 -r 20b4ed4eebe3 palette.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/palette.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,65 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* Display driver palette (RAMDAC) functions. */ + +#include "winhack.h" +#include +#include +#include "minidrv.h" +#include /* For port I/O prototypes. */ +#include "boxvint.h" /* For VGA register definitions. */ + + +/* Load the VGA DAC with values from color table. */ +static void SetRAMDAC( UINT bStart, UINT bCount, RGBQUAD FAR *lpPal ) +{ + BYTE bIndex = bStart; + + /* The data format is too weird for BOXV_dac_set(). Do it by hand. */ + outp( VGA_DAC_W_INDEX, bIndex ); /* Set starting index. */ + while( bCount-- ) { + outp( VGA_DAC_DATA, lpPal[bIndex].rgbRed ); + outp( VGA_DAC_DATA, lpPal[bIndex].rgbGreen ); + outp( VGA_DAC_DATA, lpPal[bIndex].rgbBlue ); + ++bIndex; + } +} + +/* Allow calls from the _INIT segment. */ +void __far SetRAMDAC_far( UINT bStart, UINT bCount, RGBQUAD FAR *lpPal ) +{ + SetRAMDAC( bStart, bCount, lpPal ); +} + +UINT WINAPI __loadds SetPalette( UINT wStartIndex, UINT wNumEntries, LPVOID lpPalette ) +{ + /* Let the DIB engine do what it can. */ + DIB_SetPaletteExt( wStartIndex, wNumEntries, lpPalette, lpDriverPDevice ); + + if( !(lpDriverPDevice->deFlags & BUSY) ) + SetRAMDAC( wStartIndex, wNumEntries, lpColorTable ); + + return( 0 ); +} diff -r 000000000000 -r 20b4ed4eebe3 readdev.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/readdev.txt Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,89 @@ + Development Notes + ================= + + This Windows 9x display minidriver is almost entirely written in C. It is +a 16-bit DLL running with SS != DS. The compiler switches were carefully +chosen. + + The driver is compiled as small model code and although it uses some C +library functions (e.g. _fmemcpy(), _fmemset()), it does not use the C runtime +startup code at all. + + An interrupt 2Fh handler is written in assembler, and so are forwarders and +thunks directing exported functions to the DIB Engine. The latter could be +written in C, but assembly is significantly more efficient and not at all +complex. + + The driver is by necessity similar to Windows 95/98 DDK sample code, except +it's written almost completely in C whereas the DDK sample drivers are written +100% in assembly, in the tradition of Windows 3.x and 2.x display drivers. + + Although the driver is a 16-bit DLL, it can freely use 386 instructions, +since it requires a 386 or later CPU by virtue of running on Windows 95 or +later. The driver also can and does use 32-bit registers in some situations. + + The ddk subdirectory contains files which are directly derived from the +Win9x DDK. The DDK is not used or required to build this driver, although DDK +documentation is very useful in understanding the code. Note that the Windows +9x DDK documentation may not cover topics documented in the Windows 3.x DDKs. + + The original DDK drivers are split into two code segments, _TEXT and _INIT. +This driver also uses those segments, but they are combined into a single +physical segment by the linker. This simplifies the code (e.g. no problem with +near calls into the C runtime) and given the small size of the driver, likely +is not at all disadvantageous overall. + + Note that the driver written in C is actually smaller (about 7KB vs. 8KB) +than the assembler-only DDK sample. The C code is smarter and does not waste +space on tables full of zeros and such, enabling it to be overall smaller even +with the overhead of a higher level language. + + + Debug Logging + ------------- + + When built with DBGPRINT (e.g. wmake clean && wmake DBGPRINT=1), the driver +includes debug logging implemented as dbg_printf() function. This is a small +printf() subset with output directed to the VirtualBox debug port, such that +the output appears in the VBox.log file. + + It would be much nicer to use the C runtime printf(), but that is not at all +possible because the small model library printf() cannot operate with SS != DS +and is thus unusable, even if all other, less showstopping problems were +overcome. + + See driver code for dbg_printf() usage examples. + + + Building with Open Watcom 1.9 + ----------------------------- + + The driver source was slightly adapted so that it builds with the released +Open Watcom C/C++ 1.9 compiler. + + The only real issue is that the ms2wlink utility shipped with Open Watcom +version 1.9 cannot correctly process boxv9x.def, and therefore a working +boxv9x.lnk file is supplied. + + The build process was only tested on Windows 10 hosts. It should work, +possibly with minor adaptations, on other platforms as well. That includes +Windows 9x hosts. + + The step of building a floppy image is optional and requires the mkimage +utility (part of the OS/2 Museum's fdimg project) which is not included. + + + Replacing Active Driver + ----------------------- + + Once the boxvmini.drv driver is installed, it cannot be replaced while +Windows 9x is running because the file is locked. It can be replaced in safe +mode or command line boot (F8 key early in Win9x startup). + + It can also be replaced by shutting down Windows 9x (not Windows Me) to +MS-DOS compatibility mode, copying over boxvmini.drv to the WINDOWS\SYSTEM +directory, and exiting back to Windows. + + It is always possible to use the driver update dialog to install a rebuilt +driver, but that requires more clicking and Windows must be restarted +anyway. diff -r 000000000000 -r 20b4ed4eebe3 readme.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/readme.txt Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,13 @@ +This is a display minidriver for the Windows 9x family of operating systems, +designed to run on the virtual hardware provided by VirtualBox. + +The driver can be installed through the Display Settings dialog or through +the Device Manager. + +Supported color depths are 8/16/24/32 bits per pixel. The driver supports +many common resolutions, limited by the available video memory (VRAM). + +The driver does not have a built in list of modes. It will set more or less +any resolution between 640x480 and 5120x3840. The INF file determines the +set of predefined modes. By editing the INF file or the resolution information +copied into the Registry, users can add or remove available modes. diff -r 000000000000 -r 20b4ed4eebe3 res/colortab.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/colortab.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,62 @@ +#include "winhack.h" +#include + +/* Color table for the Control Panel. */ + +typedef struct { + WORD wCount; + RGBQUAD rgbColors[]; +} COLORTABLE; + +COLORTABLE ColorTbl = { + 48, /* Number of entries in table. */ + 0xFF, 0x80, 0x80, 0, + 0xFF, 0xFF, 0xE8, 0, + 0x80, 0xFF, 0x80, 0, + 0x00, 0xFF, 0x80, 0, + 0x80, 0xFF, 0xFF, 0, + 0x00, 0x80, 0xFF, 0, + 0xFF, 0x80, 0xC0, 0, + 0xFF, 0x80, 0xFF, 0, + 0xFF, 0x00, 0x00, 0, + 0xFF, 0xFF, 0x80, 0, + 0x80, 0xFF, 0x00, 0, + 0x00, 0xFF, 0x40, 0, + 0x00, 0xFF, 0xFF, 0, + 0x00, 0x80, 0xC0, 0, + 0x80, 0x80, 0xC0, 0, + 0xFF, 0x00, 0xFF, 0, + 0x80, 0x40, 0x40, 0, + 0xFF, 0xFF, 0x00, 0, + 0x00, 0xFF, 0x00, 0, + 0x00, 0x80, 0x80, 0, + 0x00, 0x40, 0x80, 0, + 0x80, 0x80, 0xFF, 0, + 0x80, 0x00, 0x40, 0, + 0xFF, 0x00, 0x80, 0, + 0x80, 0x00, 0x00, 0, + 0xFF, 0x80, 0x00, 0, + 0x00, 0x80, 0x00, 0, + 0x00, 0x80, 0x40, 0, + 0x00, 0x00, 0xFF, 0, + 0x00, 0x00, 0xA0, 0, + 0x80, 0x00, 0x80, 0, + 0x80, 0x00, 0xFF, 0, + 0x40, 0x00, 0x00, 0, + 0x80, 0x40, 0x00, 0, + 0x00, 0x40, 0x00, 0, + 0x00, 0x40, 0x40, 0, + 0x00, 0x00, 0x80, 0, + 0x00, 0x00, 0x40, 0, + 0x40, 0x00, 0x40, 0, + 0x40, 0x00, 0x80, 0, + 0x00, 0x00, 0x00, 0, + 0x80, 0x80, 0x00, 0, + 0x80, 0x80, 0x40, 0, + 0x80, 0x80, 0x80, 0, + 0x40, 0x80, 0x80, 0, + 0xC0, 0xC0, 0xC0, 0, + 0x82, 0x82, 0x82, 0, + 0xFF, 0xFF, 0xFF, 0 +}; + diff -r 000000000000 -r 20b4ed4eebe3 res/config.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/config.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,74 @@ +#include "winhack.h" +#include + +/* Typedef from Windows 3.1 DDK. */ + +typedef struct { + + /* machine-dependent parameters */ + short VertThumHeight; /* vertical thumb height (in pixels) */ + short HorizThumWidth; /* horizontal thumb width (in pixels) */ + short IconXRatio; /* icon width (in pixels) */ + short IconYRatio; /* icon height (in pixels) */ + short CurXRatio; /* cursor width (in pixels) */ + short CurYRatio; /* cursor height (in pixels) */ + short Reserved; /* reserved */ + short XBorder; /* vertical-line width */ + short YBorder; /* horizontal-line width */ + + /* default-system color values */ + RGBQUAD clrScrollbar; + RGBQUAD clrDesktop; + RGBQUAD clrActiveCaption; + RGBQUAD clrInactiveCaption; + RGBQUAD clrMenu; + RGBQUAD clrWindow; + RGBQUAD clrWindowFrame; + RGBQUAD clrMenuText; + RGBQUAD clrWindowText; + RGBQUAD clrCaptionText; + RGBQUAD clrActiveBorder; + RGBQUAD clrInactiveBorder; + RGBQUAD clrAppWorkspace; + RGBQUAD clrHiliteBk; + RGBQUAD clrHiliteText; + RGBQUAD clrBtnFace; + RGBQUAD clrBtnShadow; + RGBQUAD clrGrayText; + RGBQUAD clrBtnText; + RGBQUAD clrInactiveCaptionText; +} CONFIG_BIN; + + +CONFIG_BIN Config = { + 17, + 17, + 2, + 2, + 1, + 1, + 0, + 1, + 1, + + 192, 192, 192, 0, + 192, 192, 192, 0, + 000, 000, 128, 0, + 255, 255, 255, 0, + 255, 255, 255, 0, + 255, 255, 255, 0, + 000, 000, 000, 0, + 000, 000, 000, 0, + 000, 000, 000, 0, + 255, 255, 255, 0, + 192, 192, 192, 0, + 192, 192, 192, 0, + 255, 255, 255, 0, + 000, 000, 128, 0, + 255, 255, 255, 0, + 192, 192, 192, 0, + 128, 128, 128, 0, + 192, 192, 192, 0, + 000, 000, 000, 0, + 000, 000, 000, 0 +}; diff -r 000000000000 -r 20b4ed4eebe3 res/display.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/display.rc Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,16 @@ +/* + * Windows 9x minidriver resource file. + * Most of the contents is defined by backward compatibility + * requirements. Much of the detail is explained in the Windows 3.x + * and 2.x DDKs. + */ + +#include "windows.h" +#include "display.rcv" + +1 oembin PRELOAD config.bin +2 oembin colortab.bin +3 oembin PRELOAD fonts.bin +fonts oembin fonts.bin + +2003 oembin PRELOAD fonts120.bin diff -r 000000000000 -r 20b4ed4eebe3 res/display.rcv --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/display.rcv Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,81 @@ +#include + +/* Macros for use in the version resource. */ + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_DISPLAY +#define VER_FILEDESCRIPTION_STR "Windows 9x Display Minidriver" +#define VER_INTERNALNAME_STR "DISPLAY" +#define VER_LEGALCOPYRIGHT_YEARS "2012-2022" +#define VER_ORIGINALFILENAME_STR "boxvmini.drv" +#define VER_LEGALCOPYRIGHT_STR "Copyright \251 The OS/2 Museum " VER_LEGALCOPYRIGHT_YEARS +#define VER_COMPANYNAME_STR "OS/2 Museum\0" + +#define VER_PRODUCTNAME_STR "Windows 9x Display Driver\0" +#define VER_PRODUCTVERSION 2,00,0,1 +#define VER_PRODUCTVERSION_STR "2.00.1\0" + +#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + +#ifdef DEBUG +#define VER_FILEFLAGS VS_FF_DEBUG +#else +#define VER_FILEFLAGS 0 +#endif + +#define VER_FILEOS VOS_DOS_WINDOWS16 + +#ifndef VER_FILEVERSION +#define VER_FILEVERSION VER_PRODUCTVERSION +#endif + +#ifndef VER_FILEVERSION_STR +#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR +#endif + +/* Actual version resource structure. */ + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEFLAGSMASK VER_FILEFLAGSMASK +FILEFLAGS VER_FILEFLAGS +FILEOS VER_FILEOS +FILETYPE VER_FILETYPE +FILESUBTYPE VER_FILESUBTYPE +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName" , VER_COMPANYNAME_STR + VALUE "FileDescription" , VER_FILEDESCRIPTION_STR + VALUE "FileVersion" , VER_FILEVERSION_STR + VALUE "InternalName" , VER_INTERNALNAME_STR + VALUE "LegalCopyright" , VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR + VALUE "ProductName" , VER_PRODUCTNAME_STR + VALUE "ProductVersion" , VER_PRODUCTVERSION_STR + END + +#ifdef INTL + BLOCK "040904E4" + BEGIN + VALUE "CompanyName" , VER_COMPANYNAME_STR + VALUE "FileDescription" , VER_FILEDESCRIPTION_STR + VALUE "FileVersion" , VER_FILEVERSION_STR + VALUE "InternalName" , VER_INTERNALNAME_STR + VALUE "LegalCopyright" , VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR + VALUE "ProductName" , VER_PRODUCTNAME_STR + VALUE "ProductVersion" , VER_PRODUCTVERSION_STR + END +#endif + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 /* Needs updating. */ + END +END + diff -r 000000000000 -r 20b4ed4eebe3 res/fonts.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/fonts.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,6 @@ +/* Standard font resource for 96 DPI. */ + +#define OEM_FNT_HEIGHT 12 +#define OEM_FNT_WIDTH 8 + +#include "fonttmpl.c" diff -r 000000000000 -r 20b4ed4eebe3 res/fonts120.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/fonts120.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,6 @@ +/* Font resource for 120 DPI. */ + +#define OEM_FNT_HEIGHT 10 +#define OEM_FNT_WIDTH 20 + +#include "fonttmpl.c" diff -r 000000000000 -r 20b4ed4eebe3 res/fonttmpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/res/fonttmpl.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,55 @@ +#include "winhack.h" +/* Trick to get a variable-size LOGFONT structure. */ +#define LF_FACESIZE +#include + +LOGFONT OEMFixed = { + OEM_FNT_HEIGHT, + OEM_FNT_WIDTH, + 0, + 0, + 0, + 0, + 0, + 0, + 255, /* Charset. */ + 0, + 2, /* Clip precision. */ + 2, /* Quality. */ + 1, /* Pitch. */ + "Terminal" /* Font face. */ +}; + +LOGFONT ANSIFixed = { + 12, /* Width. */ + 9, /* Height. */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* Charset. */ + 0, + 2, /* Clip precision. */ + 2, /* Quality. */ + 1, /* Pitch. */ + "Courier" /* Font face. */ +}; + +LOGFONT ANSIVar = { + 12, /* Width. */ + 9, /* Height. */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* Charset. */ + 0, + 2, /* Clip precision. */ + 2, /* Quality. */ + 2, /* Pitch. */ + "Helv" /* Font face. */ +}; diff -r 000000000000 -r 20b4ed4eebe3 scrsw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scrsw.c Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,205 @@ +/***************************************************************************** + +Copyright (c) 2012-2022 Michal Necasek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*****************************************************************************/ + +/* Screen switching support (C code). */ + +#include "winhack.h" +#include +#include +#include "minidrv.h" + +/* SwitchFlags bits. */ +#define PREVENT_SWITCH 0x80 /* Don't allow screen switching. */ +#define INT_2F_HOOKED 0x01 /* INT 2Fh is hooked. */ + +/* Accessed from sswhook.asm. */ +BYTE SwitchFlags = 0; /* Screen switch flags, see above. */ + +static BOOL bNoRepaint = 0; /* Set when USER disables repaints. */ +static BOOL bPaintPending = 0; /* Set when repaint was postponed.*/ + +FARPROC RepaintFunc = 0; /* Address of repaint callback. */ + +/* Screen switch hook for INT 2Fh. */ +extern void __far SWHook( void ); + + +/* Repaint screen or postpone for later. + * Internal near call. + */ +void RepaintScreen( void ) +{ + dbg_printf( "RepaintScreen: RepaintFunc=%WP, bNoRepaint=%u\n", RepaintFunc, bNoRepaint ); + /* Do we have a repaint callback? */ + if( RepaintFunc ) { + /* Either do the work or set the pending flag. */ + if( !bNoRepaint ) + RepaintFunc(); + else + bPaintPending = TRUE; + } +} + +/* This function is exported as DISPLAY.500 and called by USER + * to inform the driver that screen repaint requests should not + * be sent. When we need to repaint while repaints are disabled, + * we set an internal flag and do the redraw as soon as repaints + * are enabled again. + */ +VOID WINAPI __loadds UserRepaintDisable( BOOL bDisable ) +{ + bNoRepaint = bDisable; + if( !bDisable && bPaintPending ) { + RepaintScreen(); + bPaintPending = 0; + } +} + +/* Called from INT 2Fh hook when the device is switching to the + * background and needs to disable drawing. + * Internal near call. + */ +void SwitchToBgnd( void ) +{ + dbg_printf( "SwitchToBgnd\n" ); + + lpDriverPDevice->deFlags |= BUSY; /// @todo Does this need to be a locked op? +} + +/* Called from INT 2Fh hook when the device is switching to the + * foreground and needs re-enable drawing, repaiting the screen + * and possibly restoring the display mode. + * Internal near call. + */ +void SwitchToFgnd( void ) +{ + dbg_printf( "SwitchToFgnd\n" ); + + /* If the PDevice is busy, we need to reset the display mode. */ + if( lpDriverPDevice->deFlags & BUSY ) + RestoreDesktopMode(); /* Will clear the BUSY flag. */ + RepaintScreen(); +} + +/* This minidriver does not currently disable or enable switching. + * Should the functions be needed, they can be enabled. + */ +#if 0 + +/* Called to prevent screen switching. + * Internal near call. + */ +void ScrSwDisable( void ) +{ + int_2Fh( ENTER_CRIT_REG ); + SwitchFlags |= PREVENT_SWITCH; +} + +/* Called to re-enable screen switching again. + * Internal near call. + */ +void ScrSwEnable( void ) +{ + int_2Fh( EXIT_CRIT_REG ); + SwitchFlags &= ~PREVENT_SWITCH; +} + +#endif + +#pragma code_seg( _INIT ) + +/* The pointer is in the code (_TEXT) segment, not data segment. + * Defined in sswhook.asm. + */ +extern void __far * __based( __segname( "_TEXT" ) ) OldInt2Fh; + + +/* Call DOS to get an interrupt vector. */ +void __far *DOSGetIntVec( BYTE bIntNo ); +#pragma aux DOSGetIntVec = \ + "mov ah, 35h" \ + "int 21h" \ + parm [al] value [es bx]; + +/* Call DOS to set an interrupt vector. */ +void DOSSetIntVec( BYTE bIntNo, void __far *NewVector ); +#pragma aux DOSSetIntVec = \ + "mov ah, 25h" \ + "push ds" \ + "push es" \ + "pop ds" \ + "int 21h" \ + "pop ds" \ + parm [al] [es dx]; + + +/* Ordinal of the repaint callback in USER. Of course undocumented. */ +#define REPAINT_ORDINAL 275 + +/* Fun times. Undocumented function to create a writable alias of a code + * selector. In MS KB Q67165, Microsoft claimed that the function "is not + * documented and will not be supported in future versions of Windows". + * Clearly they lied, as it happily works on Win9x. + */ +extern UINT WINAPI AllocCStoDSAlias( UINT selCode ); + +/* Internal function to install INT 2Fh hook. */ +void HookInt2Fh( void ) +{ + WORD selAlias; + void __far * __far *OldInt2FhAlias; /* This is fun! */ + + /* If not already set, get repaing callback from USER. */ + if( !RepaintFunc ) { + HMODULE hMod; + + hMod = GetModuleHandle( "USER" ); + RepaintFunc = GetProcAddress( hMod, (LPCSTR)REPAINT_ORDINAL ); + } + dbg_printf( "HookInt2Fh: RepaintFunc=%WP\n", RepaintFunc ); + + /* Now hook INT 2Fh. Since the address of the previous INT 2Fh handler + * is in the code segment, we have to create a writable alias. Just + * a little tricky. + */ + selAlias = AllocCStoDSAlias( (__segment)&OldInt2Fh ); + + SwitchFlags |= INT_2F_HOOKED; + /* Build a pointer to OldInt2Fh using the aliased selector. */ + OldInt2FhAlias = selAlias :> (WORD)&OldInt2Fh; + *OldInt2FhAlias = DOSGetIntVec( 0x2F ); + DOSSetIntVec( 0x2F, SWHook ); + + FreeSelector( selAlias ); +} + +/* Internal function to unhook INT 2Fh. */ +void UnhookInt2Fh( void ) +{ + if( SwitchFlags & INT_2F_HOOKED ) { + /* We have INT 2Fh hooked, undo that. */ + SwitchFlags &= ~INT_2F_HOOKED; + DOSSetIntVec( 0x2F, OldInt2Fh ); + } +} diff -r 000000000000 -r 20b4ed4eebe3 sswhook.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sswhook.asm Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,126 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; Copyright (c) 2012-2022 Michal Necasek +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Screen switching hook written in assembler. + +; See minidrv.h for more. +SCREEN_SWITCH_OUT equ 4001h +SCREEN_SWITCH_IN equ 4002h + +; Defined by us, must match minidrv.h +PREVENT_SWITCH equ 80h + +; Carry flag bit on the stack +FLAG_CF equ 0001h + +public _OldInt2Fh +public SWHook_ + +; Callbacks written in C +extrn SwitchToBgnd_ : far +extrn SwitchToFgnd_ : far + +_DATA segment public 'DATA' + +; Defined in C code +extrn _SwitchFlags : byte + +; Dispatch table. Only used locally. +dsp_tbl label word + dw SwitchToBgnd_ ; SCREEN_SWITCH_OUT handler + dw SwitchToFgnd_ ; SCREEN_SWITCH_IN handler + +_DATA ends + +DGROUP group _DATA + +_TEXT segment public 'CODE' + +; Defined in code segment so that we can chain to the old interrupt +; handler without needing to mess with DS. +_OldInt2Fh dd 0 + + .386 + +; Screen switching hook for INT 2Fh. We need to handle screen switch +; notifications ourselves and let the previous handler deal with the +; rest. +SWHook_ proc far + + ; Cannot assume anything + assume ds:nothing, es:nothing + + ; Check if the subfunction is one of those we're + ; interested in and chain to previous handler if not. + cmp ax, SCREEN_SWITCH_OUT + jz handle_fn + cmp ax, SCREEN_SWITCH_IN + jz handle_fn + jmp _OldInt2Fh ; Registers undisturbed (except flags) + + ; We are going to handle this interrupt and not chain. +handle_fn: + push ds ; Save what we can + pushad + + ; Establish data segment addressing + mov bx, _DATA ; We'll overwrite BX later + mov ds, bx + assume ds:DGROUP + + mov bx, ax ; We will need the function later + mov bp, sp ; So we can address stack + + ; See if switching is disabled + mov al, _SwitchFlags + test al, PREVENT_SWITCH + jz dispatch ; If not set, do do the work + + ; It's disabled; set carry flag and return. + + ; To get to the saved flags, we need to skip the + ; return address (4 bytes), saved DS (2 bytes), and + ; saved registers (8 * 4 bytes) +FLG_OFS equ 4 + 2 + 8 * 4 + + or word ptr [bp + FLG_OFS], FLAG_CF + jmp exit + + ; Screen switching is not disabled; clear carry flag, + ; process the screen switch notification, and return. +dispatch: + and word ptr [bp + FLG_OFS], NOT FLAG_CF + and bx, 2 ; Bit 1 of the subfunction + call dsp_tbl[bx] ; Call handler in C + +exit: + popad ; Restore and return + pop ds + iret + +SWHook_ endp + + +_TEXT ends + end diff -r 000000000000 -r 20b4ed4eebe3 winhack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/winhack.h Sun Jun 19 17:39:17 2022 +0200 @@ -0,0 +1,18 @@ +/* The gdidefs.h header badly conflicts with windows.h. Microsoft's printer + * drivers in the Windows DDK solve that by manually defining a large subset + * of windows.h. We solve that by including the normal windows.h but hiding + * the conflicting definitions. + */ +#define NOGDI +#define PPOINT n_PPOINT +#define LPPOINT n_LPPOINT +#define RECT n_RECT +#define PRECT n_PRECT +#define LPRECT n_LPRECT +#include +#undef PPOINT +#undef LPPOINT +#undef RECT +#undef PRECT +#undef LPRECT +