COMMENT % GRAPHIC WORKSHOP VGA SCREEN DRIVER COPYRIGHT (C) 1990 ALCHEMY MINDWORKS INC. VERSION 1.1 This is a skeletal driver for use as the basis for writing custom SVGA loadable drivers for Graphic Workshop. You will require the hardware specific information about your card to customize this driver. As it stands, the driver implements the code for a stock VGA card running in mode 13H for 256 colour images, mode 12H for 16 colour images and mode 11H for monochrome images. To generate a driver from this file, it must be assembled using MASM, linked and converted to a binary file with EXE2BIN. The binary driver file must be less than 64K in size... not a likely problem. Best of cosmic luck... % VERSION EQU 1 ;VERSION NUMBER SUBVERSION EQU 1 ;SUBVERSION NUMBER _AOFF EQU 6 ;STACK OFFSET VGA_WIDE EQU 320 ;WIDTH OF VGA SCREEN IN PIXELS VGA_DEEP EQU 200 ;DEPTH OF VGA SCREEN IN PIXELS VGA_SCREENSEG EQU 0A000H ;SEGMENT OF VGA SCREEN EGA_WIDE EQU 640 ;WIDTH OF EGA SCREEN IN PIXELS EGA_DEEP EQU 480 ;DEPTH OF EGA SCREEN IN PIXELS EGA_BYTES EQU 80 ;WIDTH OF EGA SCREEN IN BYTES EGA_SCREENSEG EQU 0A000H ;SEGMENT OF EGA SCREEN MONO_WIDE EQU 640 ;WIDTH OF MONO SCREEN IN PIXELS MONO_DEEP EQU 480 ;DEPTH OF MONO SCREEN IN PIXELS MONO_BYTES EQU 80 ;WIDTH OF MONO SCREEN IN BYTES MONO_SCREENSEG EQU 0A000H ;SEGMENT OF MONO SCREEN ;THIS MACRO SELECTS AN EGA PLANE EGAPLANE MACRO ARG1 MOV AL,2 MOV DX,03C4H OUT DX,AL INC DX MOV AL,ARG1 OUT DX,AL ENDM CODE SEGMENT PARA PUBLIC 'CODE' ASSUME CS:CODE ORG 0000H ;ORIGIN FOR LOADABLE DRIVER DB 'ALCHDRV2' ;SIGNATURE - DON'T CHANGE THIS ;THE FOLLOWING ARE THE POINTERS TO THE CALLABLE ROUTINES AND THE COMMON ;DATA. THE SEGMENTS ARE FILLED IN BY GRAPHIC WORKSHOP. DON'T CHANGE ANYTHING. DISPATCH PROC FAR DW VGA_ON ;FAR POINTER TO VGA MODE SELECT DW ? DW VGA_LINE ;FAR POINTER TO VGA LINE DISPLAY DW ? DW VGA_OFF ;FAR POINTER TO VGA MODE DESELECT DW ? DW VGA_PALETTE ;FAR POINTER TO VGA PALETTE SET DW ? DW VGA_OVERSCAN ;FAR POINTER TO VGA OVERSCAN SET DW ? DW EGA_ON ;FAR POINTER TO EGA MODE SELECT DW ? DW EGA_LINE ;FAR POINTER TO EGA LINE DISPLAY DW ? DW EGA_OFF ;FAR POINTER TO EGA MODE DESELECT DW ? DW EGA_PALETTE ;FAR POINTER TO EGA PALETTE SET DW ? DW MONO_ON ;FAR POINTER TO MONO MODE SELECT DW ? DW MONO_FRAME ;FAR POINTER TO MONO PAGE DISPLAY DW ? DW MONO_LINE ;FAR POINTER TO MONO LINE DISPLAY DW ? DW MONO_OFF ;FAR POINTER TO MONO MODE DESELECT DW ? DW 0,0 ;NULL ONE DW 0,0 ;NULL TWO DW 0,0 ;NULL THREE DW 0,0 ;NULL FOUR V_VGAWIDE DW VGA_WIDE ;VGA SCREEN WIDTH V_VGADEEP DW VGA_DEEP ;VGA SCREEN DEPTH V_VGASCRNSEG DW VGA_SCREENSEG ;VGA SCREEN SEGMENT V_EGAWIDE DW EGA_WIDE ;EGA SCREEN WIDTH V_EGADEEP DW EGA_DEEP ;EGA SCREEN DEPTH V_EGABYTES DW EGA_BYTES ;EGA SCREEN BYTES V_EGASCRNSEG DW EGA_SCREENSEG ;EGA SCREEN SEGMENT V_MONOWIDE DW MONO_WIDE ;MONO SCREEN WIDTH V_MONODEEP DW MONO_DEEP ;MONO SCREEN DEPTH V_MONOBYTES DW MONO_BYTES ;BYTE WIDTH ON MONOCHROME SCREEN V_MONOSCRNSEG DW MONO_SCREENSEG ;MONOCHROME SCREEN SEGMENT ;THESE VERSION NUMBERS REFLECT THE DRIVER TEMPLATE VERSION AND THE ;VERSION OF THE DRIVER ITSELF. YOU CAN CHANGE THE SUBVERSION VALUE ;TO REFLECT CHANGES IN YOUR DRIVER. THE VERSION VALUE MUST REMAIN ;UNCHANGED OR GRAPHIC WORKSHOP MAY REJECT YOUR DRIVER. DW VERSION DW SUBVERSION ;THE DESCRIPTION APPEARS IN THE F10 "ABOUT" BOX IN GRAPHIC ;WORKSHOP WHEN AN EXTERNAL DRIVER IS BEING USED. IT CAN'T ;EXCEED 24 CHARACTERS AND MUST BE NULL TERMINATED DB 'Standard VGA 320 x 200 ',0 DISPATCH ENDP ;THIS ROUTINE SELECTS THE VGA 256 COLOUR MODE ;THE HEIGHT AND WIDTH OF THE IMAGE ARE ON THE STACK - THESE ;MAY BE USEFUL IF YOU WANT TO PICK ONE OF SEVERAL AVAILABLE ;MODES BASED ON THE AREA OF THE PICTURE TO BE DISPLAYED VGA_ON PROC NEAR PUSH DS MOV AX,CS MOV DS,AX MOV CX,VGA_DEEP ;DEPTH OF SCREEN SUB DX,DX MOV SI,OFFSET SCREENTABLE VGA_ON1: PUSH DX MOV AX,VGA_WIDE ;WIDTH OF SCREEEN MUL DX MOV [SI],AX ADD SI,2 POP DX INC DX LOOP VGA_ON1 MOV AX,0013H INT 10H POP DS RETF VGA_ON ENDP ;THIS ROUTINE DISPLAYS A VGA LINE ;THE FIRST ARGUMENT ON THE STACK (2 WORDS) IS A FAR POINTER TO ;THE LINE. THE SECOND ARGUMENT IS THE LENGTH OF THE LINE IN PIXELS VGA_LINE PROC NEAR PUSH BP MOV BP,SP PUSH DS PUSH ES MOV SI,[BP + _AOFF + 0] ;OFFSET OF SOURCE MOV DS,[BP + _AOFF + 2] ;SEGMENT OF SOURCE MOV BX,[BP + _AOFF + 6] ;GET LINE NUMBER CMP BX,VGA_DEEP JGE SHOWVGAX SHL BX,1 MOV DI,CS:[SCREENTABLE+BX] CLD MOV CX,[BP + _AOFF + 4] ;LENGTH OF MOVE IN BYTES CMP CX,0 JE SHOWVGAX ;CHECK FOR NASTIES CMP CX,VGA_WIDE JL SHOWVGA1 MOV CX,VGA_WIDE SHOWVGA1: MOV AX,VGA_SCREENSEG MOV ES,AX REPNE MOVSB SHOWVGAX: POP ES POP DS POP BP RETF VGA_LINE ENDP ;THIS ROUTINE DESELECTS THE VGA 256 COLOUR MODE VGA_OFF PROC NEAR MOV AX,1200H MOV BX,0031H INT 10H MOV AX,0003H INT 10H RETF VGA_OFF ENDP ;THIS ROUTINE SETS THE VGA PALETTE ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO ;THE PALETTE DATA. THE SECOND ARGUMENT IS THE NUMBER OF COLOURS. VGA_PALETTE PROC NEAR PUSH BP MOV BP,SP PUSH DS PUSH ES MOV AX,CS MOV ES,AX MOV SI,[BP + _AOFF + 0] ;OFFSET OF SOURCE MOV DS,[BP + _AOFF + 2] ;SEGMENT OF SOURCE MOV CX,[BP + _AOFF + 4] ;NUMBER OF COLOURS MOV DI,OFFSET VGAPALETTE CMP CX,0 ;CHECK FOR NASTIES JG GVP0 JMP GVPX ;WE'LL SET THE PALLETTE USING DIRECT REGISTERS RATHER ;THAN A BIOS CALL AS IT LOOKS NIVER GVP0: MOV DX,03C6H MOV AL,0FFH OUT DX,AL MOV BX,0 GVP1: PUSH CX MOV DX,03C8H MOV AL,BL INC BX OUT DX,AL INC DX LODSB SHR AL,1 SHR AL,1 OUT DX,AL LODSB SHR AL,1 SHR AL,1 OUT DX,AL LODSB SHR AL,1 SHR AL,1 OUT DX,AL POP CX LOOP GVP1 COMMENT & GVP0: PUSH CX LODSB SHR AL,1 SHR AL,1 STOSB LODSB SHR AL,1 SHR AL,1 STOSB LODSB SHR AL,1 SHR AL,1 STOSB POP CX LOOP GVP0 MOV AX,1012H ;POINT TO THE PALETTE MOV BX,0000H MOV CX,256 MOV DX,OFFSET VGAPALETTE INT 10H & GVPX: POP ES POP DS POP BP RETF VGA_PALETTE ENDP ;THIS ROUTINE SETS THE VGA OVERSCAN. ;THE FIRST STACK ARGUMENT IS THE COLOUR NUMBER. VGA_OVERSCAN PROC NEAR PUSH BP MOV BP,SP MOV AX,1001H MOV BX,[BP + _AOFF + 0] XCHG BH,BL INT 10H POP BP RETF VGA_OVERSCAN ENDP ;THIS ROUTINE SELECTS THE EGA 16 COLOUR MODE ;THE HEIGHT AND WIDTH OF THE IMAGE ARE ON THE STACK - THESE ;MAY BE USEFUL IF YOU WANT TO PICK ONE OF SEVERAL AVAILABLE ;MODES BASED ON THE AREA OF THE PICTURE TO BE DISPLAYED EGA_ON PROC NEAR PUSH DS MOV AX,CS MOV DS,AX MOV CX,EGA_DEEP ;DEPTH OF SCREEN SUB DX,DX MOV SI,OFFSET SCREENTABLE EGA_ON1: PUSH DX MOV AX,EGA_BYTES ;WIDTH OF SCREEEN MUL DX MOV [SI],AX ADD SI,2 POP DX INC DX LOOP EGA_ON1 MOV AX,0012H INT 10H POP DS RETF EGA_ON ENDP ;THIS ROUTINE DISPLAYS AN EGA LINE ;THE FIRST ARGUMENT ON THE STACK (2 WORDS) IS A FAR POINTER TO ;THE LINE. THE SECOND ARGUMENT IS THE LENGTH OF THE LINE IN BYTES EGA_LINE PROC NEAR PUSH BP MOV BP,SP PUSH DS PUSH ES MOV SI,[BP + _AOFF + 0] ;OFFSET OF SOURCE MOV DS,[BP + _AOFF + 2] ;SEGMENT OF SOURCE MOV BX,[BP + _AOFF + 6] ;GET LINE NUMBER CMP BX,EGA_DEEP JGE SHOWEGAX SHL BX,1 MOV DI,CS:[SCREENTABLE+BX] MOV AX,0A000H MOV ES,AX MOV BX,[BP + _AOFF + 4] ;LENGTH OF MOVE IN BYTES MOV CX,BX EGAPLANE 1 CLD PUSH DI REPNE MOVSB POP DI MOV CX,BX EGAPLANE 2 PUSH DI REPNE MOVSB POP DI MOV CX,BX EGAPLANE 4 PUSH DI REPNE MOVSB POP DI MOV CX,BX EGAPLANE 8 PUSH DI REPNE MOVSB POP DI EGAPLANE 0FH SHOWEGAX: POP ES POP DS POP BP RETF EGA_LINE ENDP ;THIS ROUTINE SETS THE EGA PALETTE ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO ;THE PALETTE DATA. THE SECOND ARGUMENT IS THE NUMBER OF COLOURS. EGA_PALETTE PROC NEAR PUSH BP MOV BP,SP PUSH DS MOV SI,[BP + _AOFF + 0] ;OFFSET OF SOURCE MOV DS,[BP + _AOFF + 2] ;SEGMENT OF SOURCE MOV CX,[BP + _AOFF + 4] ;NUMBER OF COLOURS SUB BX,BX CMP CX,16 JLE EGA_PALETTE1 MOV CX,16 EGA_PALETTE1: MOV BH,[SI] MOV AX,1000H INT 10H INC BL INC SI LOOP EGA_PALETTE1 POP DS POP BP RETF EGA_PALETTE ENDP ;THIS ROUTINE DESELECTS THE EGA 16 COLOUR MODE EGA_OFF PROC NEAR MOV AX,0003H INT 10H RETF EGA_OFF ENDP ;THIS ROUTINE SELECTS THE 2 COLOUR MODE ;THE HEIGHT AND WIDTH OF THE IMAGE ARE ON THE STACK - THESE ;MAY BE USEFUL IF YOU WANT TO PICK ONE OF SEVERAL AVAILABLE ;MODES BASED ON THE AREA OF THE PICTURE TO BE DISPLAYED MONO_ON PROC NEAR PUSH DS PUSH ES MOV AX,CS MOV DS,AX MOV ES,AX MOV AX,0011H INT 10H MOV CX,MONO_DEEP SUB DX,DX MOV SI,OFFSET SCREENTABLE MONO_ON1: PUSH DX MOV AX,MONO_BYTES MUL DX MOV [SI],AX ADD SI,2 POP DX INC DX LOOP MONO_ON1 POP ES POP DS SUB AX,AX RETF MONO_ON ENDP UPDATE_MOVE EQU 2 UPDATE_PAD EQU 4 UPDATE_ADJUST EQU 6 ;THIS ROUTINE DISPLAYS A FULL MONOCHROME PAGE ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO THE PAGE ;THE SECOND ARGUMENT IS THE WIDTH OF THE BITMAP (IN BYTES) ;THE THIRD ARGUMENT IS THE NUMBER OF LINES TO DISPLAY ;NOTE: THE SOURCE BUFFER MAY BE BIGGER THAN 64K. MONO_FRAME PROC NEAR PUSH BP MOV BP,SP SUB SP,UPDATE_ADJUST PUSH DS PUSH ES MOV AX,MONO_SCREENSEG ;POINT TO THE SCREEN MOV ES,AX MOV AX,[BP + _AOFF + 4] ;GET THE WIDTH OF MOVE MOV [BP - UPDATE_MOVE],AX ;SAVE IT LOCALLY MOV WORD PTR [BP - UPDATE_PAD],0 ;SET ADJUSTMENT CMP AX,MONO_BYTES ;IF THE MOVE IS LESS THAN JL UPDATE0 ;SCREEN WIDTH, GO FOR IT SUB AX,MONO_BYTES ;ELSE, SET MOVE WIDTH MOV [BP - UPDATE_PAD],AX ;...AND THE AMOUNT TO MOV AX,MONO_BYTES ;...ADJUST THE POINTER MOV [BP - UPDATE_MOVE],AX ;...AFTER EACH LINE UPDATE0: MOV SI,[BP + _AOFF + 0] ;OFFSET OF BITMAP MOV DS,[BP + _AOFF + 2] ;SEGMENT OF BITMAP MOV CX,[BP + _AOFF + 6] ;NUMBER OF LINES CLD ;CLEAR DIRECTION FLAG SUB BX,BX UPDATE1: PUSH CX ;SAVE COUNT (LINE NUMBER) MOV DI,CS:[SCREENTABLE + BX] ADD BX,2 ;POINT TO NEXT LINE MOV CX,[BP - UPDATE_MOVE] ;GET THE MOVE SIZE REPNE MOVSB ;DO THE MOVE ADD SI,[BP - UPDATE_PAD] ;ADJUST THE POINTER CMP SI,0F800H ;ARE WE WITHIN 2K OF TOP? JL UPDATE2 ;IF NOT, CARRY ON MOV AX,SI ;SEE HOW MANY SEGMENTS ARE MOV CL,4 ;...IN SI (SI DIV 4) SHR AX,CL MOV CX,DS ;ADD THEM TO THE DATA SEGMENT ADD CX,AX ;...(YOU CAN'T JUST ADD DS,AX) MOV DS,CX AND SI,000FH ;ADJUST SI (SI MOD 16) UPDATE2: POP CX ;GET COUNT BACK LOOP UPDATE1 ;DECREMENT AND LOOP POP ES POP DS ADD SP,UPDATE_ADJUST POP BP RETF MONO_FRAME ENDP ;THIS ROUTINE DISPLAYS A SINGLE MONOCHROME LINE ;THE FIRST ARGUMENT ON THE STACK IS A FAR POINTER TO THE LINE ;THE SECOND ARGUMENT IS THE LINE NUMBER ;THE THIRD ARGUMENT IS THE WIDTH OF THE BITMAP (IN BYTES) MONO_LINE PROC NEAR PUSH BP MOV BP,SP PUSH DS PUSH ES MOV AX,MONO_SCREENSEG ;POINT TO THE SCREEN MOV ES,AX MOV CX,[BP + _AOFF + 6] ;GET THE WIDTH OF MOVE CMP CX,0 JE MONO_LINE2 CMP CX,MONO_BYTES JL MONO_LINE1 MOV CX,MONO_BYTES MONO_LINE1: MOV SI,[BP + _AOFF + 0] ;OFFSET OF BITMAP MOV DS,[BP + _AOFF + 2] ;SEGMENT OF BITMAP MOV BX,[BP + _AOFF + 4] ;NUMBER OF LINE SHL BX,1 CLD ;CLEAR DIRECTION FLAG MOV DI,CS:[SCREENTABLE + BX] REPNE MOVSB ;DO THE MOVE MONO_LINE2: POP ES POP DS POP BP RETF MONO_LINE ENDP ;THIS ROUTINE DESELECTS THE 2 COLOUR MODE MONO_OFF PROC NEAR MOV AX,0003H INT 10H SUB AX,AX RETF MONO_OFF ENDP ;THIS IS A LINE START LOOKUP TABLE SCREENTABLE DW MONO_DEEP DUP(?) ;LINE START TABLE ;THIS IS WHERE THE VGA PALETTE IS STORED VGAPALETTE DB 768 DUP(?) ;PALETTE CODE ENDS END