home *** CD-ROM | disk | FTP | other *** search
- ;
- ; VGA support routines for raster oriented graphics
- ;
- ; Quincey Koziol June 1988
- ;
- ; National Center for Supercomputing Applications, University of Illinois
- ; 153 Water Resources Building
- ; 605 E. Springfield Ave.
- ; Champaign, Ill 61820
- ; (217)244-0072
- ;
- TITLE VGA GRAPHICS SUPPORT
- INCLUDE DOS.MAC
- SETX
- PSEG
- PUBLIC PUTMAPV,GETMAP,VGALINE1,VGAMODE;,VGAOFF,VGAON,VGAPT
- PUBLIC SHOWPALV,NOPALV,OUTLINEV
- ;
- ; take three arrays of color tables and interleave them into the
- ; VGA registers in the fashion Red, Green, Blue.
- ;
-
- PUTMAPV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
- ;
- MOV AX,[BP+X+2]
- MOV DS,AX ; WHERE TO GET MAPS (SEG)
- MOV SI,[BP+X] ; WHERE TO GET RED
- MOV DI,[BP+X+4] ; WHERE TO GET GREEN
- MOV BP,[BP+X+8] ; WHERE TO GET BLUE
- MOV DX,03C8H ; I/O PORT FOR PEL TABLE
- MOV AL,0 ; VALUE FOR BEGINNING OF TABLE
- OUT DX,AL ; START OUTPUTTING VALUES
- INC DX ; INCREMENT DX TO OUTPUT TABLE
- MOV CX,256 ; LENGTH OF THE TABLE IN BYTE TRIPLES
-
- DORGB:
- MOV AL,DS:[SI] ; GET A RED BYTE
- SHR AL,1
- SHR AL,1 ; GET RID OF TWO HIGHEST BITS
- OUT DX,AL
- INC SI
- ;
- MOV AL,DS:[DI] ; GET A GREEN BYTE
- SHR AL,1
- SHR AL,1 ; GET RID OF TWO HIGHEST BITS
- OUT DX,AL
- INC DI
- ;
- MOV AL,DS:[BP] ; GET A BLUE BYTE
- SHR AL,1
- SHR AL,1 ; GET RID OF TWO HIGHEST BITS
- OUT DX,AL
- INC BP
- ;
- LOOP DORGB ; CONTINUE PRINTING UNTIL ALL 768 BYTES ARE WRITTEN
- ;
- POP ES
- POP DS
- POP BP
- RET
-
- PUTMAPV ENDP
-
- GETMAP PROC FAR
- RET
- GETMAP ENDP
-
- ;
- ; Transfer line to vga screen
- ;
- ; usage : vgaline1(x,y,buf,xoff,linelen)
- ;
- VGALINE1 PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- OKBANK:
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
- MOV SI,[BP+X+4] ; WHERE DATA WILL COME FROM
- MOV AX,[BP+X+8] ; GET THE X OFFSET INTO THE ARRAY
- CMP AX,0 ; CHECK FOR NEGATIVE OFFSET
- JGE OKSIGN ; JUMP AROUND FIXING THE WINDOW
- NEG AX ; TAKE THE OPPOSITE VALUE
- ADD AX,[BP+X] ; AND ADD IT TO THE POSITION ON THE SCREEN
- MOV [BP+X],AX ; AND RE-STORE THE POSITION
- MOV AX,[BP+X+8] ; GET THE NEGATIVE OFFSET AGAIN
- ADD AX,[BP+X+10] ; REDUCE THE NUMBER OF BYTES TO COPY TO THE SCREEN
- MOV [BP+X+10],AX ; AND STORE THE NUMBER OF BYTES AGAIN
- OKSIGN:
- ADD SI,AX ; ADD THE OFFSET TO THE OFFSET OF THE ARRAY
- ;
- MOV AX,[BP+X+6] ; SEGMENT OF DATA
- MOV DS,AX
- ;
- MOV AX,[BP+X+2] ; GET Y VALUE AGAIN
- MOV DX,320 ; GET LENGTH OF A LINE
- MUL DX
- JA DONTFIX ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
- MOV BX,ES ; GET THE ES
- ADD BX,DX ; INCREMENT THE ES
- MOV ES,BX ; AND REPLACE IT
- DONTFIX:
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
- MOV DI,AX ; PREPARE FOR MOVS
- MOV CX,[BP+X+10] ; HOW MANY BYTES?
- BLAST:
- REP MOVSB
-
- POP ES
- POP DS
- POP BP
- RET
- VGALINE1 ENDP
-
- ifdef QAK
- ; point on vga screen
- ;
- ; usage : vgapt(x,y,color)
- ;
- VGAPT PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- ;
- ; READY TO PUT THE POINT
- ;
- POKBANK:
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
-
- MOV AX,[BP+X+2] ; GET Y VALUE AGAIN
- MOV DX,320
- MUL DX
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
-
- MOV DI,AX ; PREPARE FOR MOVS
- MOV AL,[BP+X+4] ; GET COLOR TO PUT THERE
-
- STOSB ; PUT IT
-
- POP ES
- POP DS
- POP BP
- RET
- VGAPT ENDP
- endif
-
- VGAMODE PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,[BP+X] ;GET SCREEN MODE TO SWITCH TO
- MOV AH,00H ;ENTER VIDEO_IO ROUTINE (SET MODE=0)
- INT 10H ;VIDEO INTERUPT
-
- POP ES
- POP DS
- POP BP
- RET
- VGAMODE ENDP
-
- ifdef QAK
- VGAOFF PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING MODE REGISTER
- OUT DX,AL ;SET UP TO READ THE CLOCKING MODE REGISTER
- MOV DX,03C5H ;ADDRESS TO READ FROM
- IN AL,DX ;GET THE CLOCKING MODE REGISTER
- OR AL,20H ;MASK OFF THE SCREEN ENABLE BIT
- MOV BL,AL ;KEEP THAT AROUND
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING REGISTER
- OUT DX,AL ;SET UP TO WRITE BACK THE CLOCKING MODE REGISTER
- INC DX ;SET TO ADDRESS TO WRITE TO
- MOV AL,BL ;GET BACK THE PROPER VALUE
- OUT DX,AL ;TURNS OFF THE VGA SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- VGAOFF ENDP
-
- VGAON PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING MODE REGISTER
- OUT DX,AL ;SET UP TO READ THE CLOCKING MODE REGISTER
- INC DX ;ADDRESS TO READ FROM
- IN AL,DX ;GET THE CLOCKING MODE REGISTER
- AND AL,0DFH ;TURN ON THE SCREEN ENABLE BIT
- MOV BL,AL ;KEEP THAT AROUND
- MOV DX,03C4H ;ADDRESS OF THE SEQ CONTROLLER
- MOV AL,01H ;INDEX OF THE CLOCKING REGISTER
- OUT DX,AL ;SET UP TO WRITE BACK THE CLOCKING MODE REGISTER
- INC DX ;SET TO ADDRESS TO WRITE TO
- MOV AL,BL ;GET BACK THE PROPER VALUE
- OUT DX,AL ;TURNS ON THE VGA SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- VGAON ENDP
- endif
-
- ;
- ; showpalv(&palstore,pal_xoff,pal_yoff);
- ;
- SHOWPALV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
-
- MOV AX,[BP+X] ;GET OFFSET OF ARRAY
- MOV DI,AX
- MOV AX,[BP+X+2] ;GET SEGMENT OF STORAGE ARRAY
- MOV ES,AX
-
- MOV AX,[BP+X+6] ;GET LINE TO START PALETTE ON
- MOV DX,320 ;GET THE LINE LENGTH
- MUL DX ;GET THE OFFSET INTO THE SCREEN
- ADD AX,[BP+X+4] ;ADD IN THE X OFFSET
- JNC NO_ROLLOVER ;ADDITION DIDN'T CARRY
- INC DX ;INCREMENT THE DX REGISTER ON A CARRY
- NO_ROLLOVER:
- MOV SI,AX ;KEEP TRACK OF THE OFFSET
- MOV BX,SI ;IN TWO PLACES
- MOV AX,320 ;GET THE LINE LENGTH
- MOV DX,8 ;GET THE NUMBER OF LINES
- MUL DX ;GET THE NUMBER OF BYTES TO COPY
- MOV CX,AX ;MOVE INTO COUNTER
- MOV AX,0A000H
- MOV DS,AX ;GET THE SEGMENT FOR THE SOURCE
- ZIP:
- REP MOVSB ;COPY THAT SECTION OF SCREEN
-
- MOV CH,0 ;THE NUMBER OF LINES COPIED SO FAR
- MOV CL,00 ;THE NUMBER OF PIXELS
- TOP1:
- MOV SI,BX ;GET THE CORRECT OFFSET TO BE COPIED TO
- MOV AX,0A000H
- MOV ES,AX ;GET THE SEGMENT TO BE COPIED TO
- TOP2:
- MOV ES:[SI],CL ;COPY ACROSS THE SCREEN INCREMENTING VALUES
- INC SI ;MOVE TO NEXT PIXEL
- INC CL ;INCREMENT COUNTER
- JNE TOP2 ;IF COUNTER NOT EQUAL TO ZERO THEN COPY AGAIN
-
- ADD BX,320 ;MOVE DOWN TO NEXT LINE
- INC CH ;INCREMENT THE LINE COUNTER
- CMP CH,8 ;CHECK IF ALL THE LINES ARE DONE
- JNE TOP1 ;IF LINE COUNT <8 THEN COPY ANOTHER LINE
-
- POP ES
- POP DS
- POP BP
- RET
- SHOWPALV ENDP
-
- ;
- ; nopalv(&palstore,pal_xoff,pal_yoff);
- ;
- NOPALV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,[BP+X] ;GET OFFSET OF ARRAY
- MOV SI,AX
- MOV AX,[BP+X+2] ;GET SEGMENT OF STORAGE ARRAY
- MOV DS,AX
-
- MOV AX,[BP+X+6] ;GET LINE TO COPY SCREEN BACK ONTO
- MOV DX,320 ;GET THE LINE LENGTH
- MUL DX ;GET THE OFFSET INTO THE SCREEN
- ADD AX,[BP+X+4] ;ADD IN THE X OFFSET
- JNC NO_ROLL2 ;ADDITION DIDN'T CARRY
- INC DX ;INCREMENT THE DX REGISTER ON A CARRY
- NO_ROLL2:
- MOV DI,AX ;KEEP TRACK OF THE OFFSET
- MOV AX,320 ;GET THE LINE LENGTH
- MOV DX,8 ;GET THE NUMBER OF LINES
- MUL DX ;GET THE NUMBER OF BYTES TO COPY
- MOV CX,AX ;MOVE INTO COUNTER
- MOV AX,0A000H
- MOV ES,AX ;GET THE SEGMENT FOR THE SOURCE
- ZOOM:
- REP MOVSB ;COPY THAT SECTION OF SCREEN
-
- POP ES
- POP DS
- POP BP
- RET
- NOPALV ENDP
-
- ;
- ; Invert A BOX ON THE SCREEN
- ;
- ; usage : outlinev(x1,y1,x2,y2)
- ;
- OUTLINEV PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,[BP+X+2] ; GET FIRST Y VALUE
- CMP AX,[BP+X+6] ; COMPARE WITH THE SECOND Y - VALUE
- JLE CHECKX ; OK ORDER GOTO CHECKING THE X VALUES
- MOV CX,AX ; SWAP THE TWO VALUES
- MOV AX,[BP+X+6] ;
- MOV [BP+X+2],AX ;
- MOV AX,CX ;
- MOV [BP+X+6],AX ;
- CHECKX:
- MOV AX,[BP+X] ; GET FIRST X VALUE
- CMP AX,[BP+X+4] ; COMPARE WITH THE SECOND X - VALUE
- JLE MAKELEN ; OK ORDER GOTO COMPUTING THE LENGTHS
- MOV CX,AX ; SWAP THE TWO VALUES
- MOV AX,[BP+X+4] ;
- MOV [BP+X],AX ;
- MOV AX,CX ;
- MOV [BP+X+4],AX ;
- MAKELEN: ; COMPUTE THE X AND Y WIDTHS FOR THE BOX TO BE INVERTED
- MOV AX,[BP+X+4] ; GET THE LARGER OF THE TWO X VALUES
- SUB AX,[BP+X] ; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
- ADD AX,1 ;
- MOV [BP+X+4],AX ; STORE IT IN THE OLD LOCATION FOR THE 2ND X VALUE
- MOV AX,[BP+X+6] ; GET THE LARGER OF THE TWO Y VALUES
- SUB AX,[BP+X+2] ; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
- SUB AX,1 ; SUBTRACT TWO FOR THE TOP AND BOTTOM EDGES
- CMP AX,0 ; CHECK IF IT IS LESS THAN ZERO
- JG POSITIVE ; JUMP AROUND ZEROING THE ACC.
- MOV AX,0
- POSITIVE:
- MOV [BP+X+6],AX ; STORE IT IN THE OLD LOCATION FOR THE 2ND Y VALUE
- MOV AX,320 ; COMPUTE THE VALUE TO ADD TO THE DI FOR COMPLETE WRAPAROUND
- SUB AX,[BP+X+4] ;
- MOV SI,AX ; KEEP TRACK OF IT
-
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
- ;
- MOV AX,[BP+X+2] ; GET Y VALUE AGAIN
- MOV DX,320 ; GET LENGTH OF A LINE
- MUL DX
- JA DONTFIXA ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
- MOV BX,ES ; GET THE ES
- ADD BX,DX ; INCREMENT THE ES
- MOV ES,BX ; AND REPLACE IT
- DONTFIXA:
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
- MOV DI,AX ; PREPARE FOR MOVS
- MOV CX,[BP+X+4] ; HOW MANY BYTES?
- BLASTA:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT THE VALUE THERE
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; INCREMENT TO NEXT POSITION
- LOOP BLASTA ; LOOP UNTIL ALL HAVE BEEN DONE
-
- ADD DI,SI ; MOVE OVER TO THE BEGINNING OF THE NEXT LINE
- MOV CX,[BP+X+6] ; COUNT VALUE FOR THE NEXT SERIES
- CMP CX,0 ; CHECK FOR NO LINES IN BETWEEN
- JLE BLAST2A ; JUMP AROUND PUTTING THE LINES IN BETWEEN
- BLAST2:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE INVERTED VALUE
- ADD DI,[BP+X+4] ; GO TO THE LAST VALUE TO INVERT ON THAT LINE
- SUB DI,1 ;
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE INVERTED VALUE
- ADD DI,SI ; GET THE VALUE FOR THE BEGINNING OF THE NEXT LINE
- INC DI ;
- LOOP BLAST2 ; DO THE NEXT LINE
-
- BLAST2A:
- MOV CX,[BP+X+4] ; PREPARE FOR LAST LINE
- BLAST3:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT THE VALUE THERE
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; INCREMENT TO NEXT POSITION
- LOOP BLAST3 ; LOOP UNTIL ALL HAVE BEEN DONE
-
- POP ES
- POP DS
- POP BP
- RET
- OUTLINEV ENDP
- ;
- ; Draw a 4x4 ball on the vga screen
- ;
- ; usage : ball(x,y)
- ;
- BALL PROC FAR
- PUSH BP
- MOV BP,SP
- PUSH DS
- PUSH ES
-
- MOV AX,0A000H ; DATA BUFFER
- MOV ES,AX
- ;
- MOV AX,[BP+X+2] ; GET Y VALUE
- MOV DX,320 ; GET LENGTH OF A LINE
- MUL DX
- JA DONTFIXB ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
- MOV BX,ES ; GET THE ES
- ADD BX,DX ; INCREMENT THE ES
- MOV ES,BX ; AND REPLACE IT
- DONTFIXB:
- ADD AX,[BP+X] ; X VALUE OF WHERE ON SCREEN ADDED IN
- MOV DI,AX ; PREPARE FOR MOVS
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; MOVE OVER ONE BYTE
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
-
- ADD DI,318 ; MOVE TO THE NEXT LINE
- MOV CX,4 ; HOW MANY BYTES?
- BLASTB:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT THE VALUE THERE
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; INCREMENT TO NEXT POSITION
- LOOP BLASTB ; LOOP UNTIL ALL HAVE BEEN DONE
-
- MOV CX,4 ; COUNT VALUE FOR THE NEXT SERIES
- ADD DI,316 ; MOVE OVER TO THE BEGINNING OF THE NEXT LINE
- BLASTC:
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE INVERTED VALUE
- INC DI ;
- LOOP BLASTC ; DO THE NEXT LINE
-
- ADD DI,317 ; MOVE ONE BYTE OVER INTO THE NEXT LINE
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
- INC DI ; MOVE OVER ONE BYTE
- MOV AL,ES:[DI] ; GET THE VALUE TO INVERT
- NOT AL ; INVERT IT
- MOV ES:[DI],AL ; REPLACE THE VALUE
-
- POP ES
- POP DS
- POP BP
- RET
- BALL ENDP
-
- ENDPS
- END
-