home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource Library: Graphics
/
graphics-16000.iso
/
msdos
/
viewers
/
pcshow
/
vga.asm
< prev
Wrap
Assembly Source File
|
1991-07-01
|
12KB
|
484 lines
;
; 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