home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / utils / graphic / viewers / general / msdos / ncsa / src / vga.asm < prev   
Encoding:
Assembly Source File  |  1989-04-22  |  25.9 KB  |  959 lines

  1. ;    
  2. ;    VGA support routines for raster oriented graphics
  3. ;
  4. ;    Quincey Koziol        June 1988
  5. ;
  6. ;    National Center for Supercomputing Applications,    University of Illinois
  7. ;    153    Water Resources Building
  8. ;    605 E. Springfield Ave.
  9. ;    Champaign, Ill    61820
  10. ;    (217)244-0072
  11. ;
  12.     TITLE      VGA GRAPHICS SUPPORT
  13.     INCLUDE DOS.MAC
  14.     SETX
  15.     PSEG
  16.     PUBLIC    PUTMAPV,GETMAP,VGALINE1,VGAPT,VGAMODE,VGAOFF,VGAON,VGASCRN
  17.     PUBLIC    SHOWPALV,NOPALV,SCRLRITE,SCRLLEFT,SCRLUP,SCRLDOWN,OUTLINEV,BALL
  18. ;
  19. ;    take three arrays of color tables and interleave them into the
  20. ;    VGA registers in the fashion Red, Green, Blue.
  21. ;
  22.  
  23. PUTMAPV    PROC    FAR
  24.     PUSH    BP
  25.     MOV        BP,SP
  26.     PUSH    DS
  27.     PUSH    ES
  28. ;
  29.     MOV    AX,[BP+X+2]
  30.     MOV    DS,AX            ; WHERE TO GET MAPS (SEG)
  31.     MOV    SI,[BP+X]        ; WHERE TO GET RED
  32.     MOV DI,[BP+X+4]        ; WHERE TO GET GREEN
  33.     MOV BP,[BP+X+8]        ; WHERE TO GET BLUE
  34.     MOV    DX,03C8H        ; I/O PORT FOR PEL TABLE
  35.     MOV AL,0            ; VALUE FOR BEGINNING OF TABLE
  36.     OUT DX,AL            ; START OUTPUTTING VALUES
  37.     INC DX                ; INCREMENT DX TO OUTPUT TABLE
  38.     MOV CX,256            ; LENGTH OF THE TABLE IN BYTE TRIPLES
  39.  
  40. DORGB:
  41.     MOV AL,DS:[SI]        ; GET A RED BYTE
  42.     SHR AL,1
  43.     SHR AL,1            ; GET RID OF TWO HIGHEST BITS
  44.     OUT DX,AL            
  45.     INC SI
  46. ;
  47.     MOV AL,DS:[DI]        ; GET A GREEN BYTE
  48.     SHR    AL,1
  49.     SHR AL,1            ; GET RID OF TWO HIGHEST BITS
  50.     OUT DX,AL
  51.     INC DI
  52. ;
  53.     MOV    AL,DS:[BP]        ; GET A BLUE BYTE
  54.     SHR AL,1
  55.     SHR AL,1            ; GET RID OF TWO HIGHEST BITS
  56.     OUT DX,AL            
  57.     INC BP
  58. ;
  59.     LOOP DORGB            ; CONTINUE PRINTING UNTIL ALL 768 BYTES ARE WRITTEN
  60. ;
  61.     POP    ES
  62.     POP    DS
  63.     POP    BP
  64.     RET
  65.  
  66. PUTMAPV    ENDP
  67.  
  68. GETMAP    PROC    FAR
  69.     RET
  70. GETMAP    ENDP
  71.  
  72. ;
  73. ;  Transfer line to vga screen
  74. ;
  75. ;   usage : vgaline1(x,y,buf,xoff,linelen)
  76. ;
  77. VGALINE1    PROC    FAR
  78.     PUSH    BP
  79.     MOV        BP,SP
  80.     PUSH    DS
  81.     PUSH    ES
  82.  
  83. OKBANK:
  84.     MOV    AX,0A000H    ; DATA BUFFER
  85.     MOV    ES,AX
  86.     MOV    SI,[BP+X+4]    ; WHERE DATA WILL COME FROM
  87.     MOV    AX,[BP+X+8]    ; GET THE X OFFSET INTO THE ARRAY
  88.     CMP    AX,0        ; CHECK FOR NEGATIVE OFFSET
  89.     JGE    OKSIGN        ; JUMP AROUND FIXING THE WINDOW
  90.     NEG    AX            ; TAKE THE OPPOSITE VALUE
  91.     ADD AX,[BP+X]    ; AND ADD IT TO THE POSITION ON THE SCREEN
  92.     MOV    [BP+X],AX    ; AND RE-STORE THE POSITION
  93.     MOV    AX,[BP+X+8]    ; GET THE NEGATIVE OFFSET AGAIN
  94.     ADD    AX,[BP+X+10]    ; REDUCE THE NUMBER OF BYTES TO COPY TO THE SCREEN
  95.     MOV    [BP+X+10],AX    ; AND STORE THE NUMBER OF BYTES AGAIN
  96. OKSIGN:
  97.     ADD    SI,AX        ; ADD THE OFFSET TO THE OFFSET OF THE ARRAY
  98. ;
  99.     MOV AX,[BP+X+6]    ; SEGMENT OF DATA
  100.     MOV DS,AX
  101. ;
  102.     MOV    AX,[BP+X+2]    ; GET Y VALUE AGAIN
  103.     MOV    DX,320        ; GET LENGTH OF A LINE
  104.     MUL    DX
  105.     JA    DONTFIX        ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
  106.     MOV    BX,ES        ; GET THE ES
  107.     ADD    BX,DX        ; INCREMENT THE ES
  108.     MOV    ES,BX        ; AND REPLACE IT
  109. DONTFIX:
  110.     ADD    AX,[BP+X]    ; X VALUE OF WHERE ON SCREEN ADDED IN
  111.     MOV    DI,AX        ; PREPARE FOR MOVS
  112.     MOV    CX,[BP+X+10]    ; HOW MANY BYTES?
  113. BLAST:
  114.     REP    MOVSB
  115.  
  116.     POP    ES
  117.     POP    DS
  118.     POP    BP
  119.     RET
  120. VGALINE1    ENDP
  121.  
  122. ;  point on vga screen
  123. ;
  124. ;   usage : vgapt(x,y,color)
  125. ;
  126. VGAPT    PROC    FAR
  127.     PUSH    BP
  128.     MOV        BP,SP
  129.     PUSH    DS
  130.     PUSH    ES
  131.  
  132. ;
  133. ;   READY TO PUT THE POINT
  134. ;
  135. POKBANK:
  136.     MOV    AX,0A000H    ; DATA BUFFER
  137.     MOV    ES,AX
  138.  
  139.     MOV    AX,[BP+X+2]    ; GET Y VALUE AGAIN
  140.     MOV    DX,320
  141.     MUL    DX
  142.     ADD    AX,[BP+X]    ; X VALUE OF WHERE ON SCREEN ADDED IN
  143.  
  144.     MOV    DI,AX        ; PREPARE FOR MOVS
  145.     MOV    AL,[BP+X+4]    ; GET COLOR TO PUT THERE
  146.  
  147.     STOSB            ; PUT IT
  148.  
  149.     POP    ES
  150.     POP    DS
  151.     POP    BP
  152.     RET
  153. VGAPT    ENDP
  154.  
  155. VGAMODE        PROC    FAR
  156.     PUSH    BP
  157.     MOV        BP,SP
  158.     PUSH    DS
  159.     PUSH    ES
  160.     
  161.     MOV        AX,[BP+X]        ;GET SCREEN MODE TO SWITCH TO
  162.     MOV        AH,00H            ;ENTER VIDEO_IO ROUTINE (SET MODE=0)
  163.     INT        10H                ;VIDEO INTERUPT
  164.  
  165.     POP    ES
  166.     POP    DS
  167.     POP    BP
  168.     RET
  169. VGAMODE    ENDP
  170.  
  171.  
  172. VGAOFF        PROC    FAR
  173.     PUSH    BP
  174.     MOV        BP,SP
  175.     PUSH    DS
  176.     PUSH    ES
  177.     
  178.     MOV        DX,03C4H        ;ADDRESS OF THE SEQ CONTROLLER
  179.     MOV        AL,01H            ;INDEX OF THE CLOCKING MODE REGISTER
  180.     OUT        DX,AL            ;SET UP TO READ THE CLOCKING MODE REGISTER
  181.     MOV        DX,03C5H        ;ADDRESS TO READ FROM
  182.     IN        AL,DX            ;GET THE CLOCKING MODE REGISTER
  183.     OR        AL,20H            ;MASK OFF THE SCREEN ENABLE BIT    
  184.     MOV        BL,AL            ;KEEP THAT AROUND
  185.     MOV        DX,03C4H        ;ADDRESS OF THE SEQ CONTROLLER
  186.     MOV        AL,01H            ;INDEX OF THE CLOCKING REGISTER
  187.     OUT        DX,AL            ;SET UP TO WRITE BACK THE CLOCKING MODE REGISTER
  188.     INC        DX                ;SET TO ADDRESS TO WRITE TO
  189.     MOV        AL,BL            ;GET BACK THE PROPER VALUE
  190.     OUT        DX,AL            ;TURNS OFF THE VGA SCREEN
  191.  
  192.     POP    ES
  193.     POP    DS
  194.     POP    BP
  195.     RET
  196. VGAOFF    ENDP
  197.  
  198. VGAON        PROC    FAR
  199.     PUSH    BP
  200.     MOV        BP,SP
  201.     PUSH    DS
  202.     PUSH    ES
  203.     
  204.     MOV        DX,03C4H        ;ADDRESS OF THE SEQ CONTROLLER
  205.     MOV        AL,01H            ;INDEX OF THE CLOCKING MODE REGISTER
  206.     OUT        DX,AL            ;SET UP TO READ THE CLOCKING MODE REGISTER
  207.     INC        DX                ;ADDRESS TO READ FROM
  208.     IN        AL,DX            ;GET THE CLOCKING MODE REGISTER
  209.     AND        AL,0DFH            ;TURN ON THE SCREEN ENABLE BIT    
  210.     MOV        BL,AL            ;KEEP THAT AROUND
  211.     MOV        DX,03C4H        ;ADDRESS OF THE SEQ CONTROLLER
  212.     MOV        AL,01H            ;INDEX OF THE CLOCKING REGISTER
  213.     OUT        DX,AL            ;SET UP TO WRITE BACK THE CLOCKING MODE REGISTER
  214.     INC        DX                ;SET TO ADDRESS TO WRITE TO
  215.     MOV        AL,BL            ;GET BACK THE PROPER VALUE
  216.     OUT        DX,AL            ;TURNS ON THE VGA SCREEN
  217.  
  218.     POP    ES
  219.     POP    DS
  220.     POP    BP
  221.     RET
  222. VGAON    ENDP
  223.  
  224. X_COL        DW    0
  225. Y_ROW        DW    0
  226. TEMP1        DB    0
  227. TEMP2        DW    0
  228. TEMP3        DW    0
  229. TEMP4        DW    0
  230. TEMP5        DW  0
  231. NUM_CHARS    DB    0
  232. CRT_ADDR    DW    03D4H
  233. ATTR_ADDR    DW    03C0H
  234. SEQ_ADDR    DW    03C4H
  235. GRAF_ADDR    DW    03CEH
  236. ATTR_TABLE    LABEL    BYTE
  237.             DB    41H        ;BYTE 10H OF THE TABLE!!!
  238.             DB    0        ;BORDER COLOR OF SCREEN BYTE 11H OF TABLE
  239.             DB    0FH        ;BYTE 12H OF ATTR. TABLE
  240.             DB    0        ;AMOUNT TO SHIFT SCREEN TO LEFT BY, BYTE 13H OF TABLE
  241.             DB    0        ;NO COLOR SELECTION NECESSARY, BYTE 14H OF TABLE
  242. SEQ_TABLE    LABEL    BYTE
  243.             DB    3        ;DON'T RESET THE SYSTEM (0'S WOULD RESET)
  244.             DB    1        ;A WHOLE BUNCH OF THINGS, BYTE 01H OF TABLE
  245.             DB    0FH        ;ALLOW WRITES TO ALL MEMORY MAPS
  246.             DB    0        ;DON'T WORRY ABOUT THE CHARACTER MAPS
  247.             DB    0EH        ;SET UP FOR EXTENDED MEMORY
  248. GRAF_TABLE    LABEL    BYTE
  249.             DB    0        ;WRITE A BLANK SCREEN FOR SET/RESETS
  250.             DB    0        ;ENABLE THE SET/RESET FUNCTION
  251.             DB    0        ;COLOR COMPARE VALUE IS ZERO
  252.             DB    0        ;JUST WRITE TO MEMORY, DONT ROTATE, DONT AND or OR
  253.             DB    0        ;SELECT MAP ZERO TO READ FROM
  254.             DB    40H        ;SELECT 256 COLOR MODE AMONG OTHER THINGS
  255.             DB    5        ;SELECT 128K MODE AT A0000H AND GRAPHICS MODE
  256.             DB    0FH        ;DON'T PARTICIPATE IN THE COLOR COMPARE CYCLE
  257.             DB    0FFH    ;ALLOW ALL BITS TO BE WRITTEN TO
  258. TABLE        LABEL    BYTE
  259.             DB    5FH        ;0        ;HORIZONTAL TOTAL=# OF CHARS+# OF CHARS*.25-5
  260.             DB    4FH        ;0        ;HORIZONTAL DISPLAY ENABLE END=# OF CHARS-1
  261.             DB    50H        ;0        ;START HORIZONTAL BLANKING=# OF CHARS
  262.             DB    82H        ;0        ;END HORIZONTAL BLANKING
  263.                     ;    BITS
  264.                     ;    7 = 1
  265.                     ;     6,5 = 0,0
  266.                     ;     4-0 = LOW 5 BITS OF AN EIGHT BIT # = TABLE(00)+3
  267.             DB    54H        ;0        ;START HORIZONTAL RETRACE PULSE=(TABLE(00)+TABLE(02)/2
  268.             DB    80H        ;0        ;END HORIZONTAL RETRACE
  269.                     ;    BITS
  270.                     ;     7 = SIXTH BIT OF TABLE(00)+3
  271.                     ;     6,5 = 0,0
  272.                     ;     4-0 = 0
  273.             DB    0BH        ;0        ;VERTICAL TOTAL=LOW EIGHT BITS OF
  274.                     ; IF Y_ROW<=200 THEN Y_ROW*2.5-2
  275.                     ; IF Y_ROW>200  THEN Y_ROW*1.25-2
  276.             DB    3EH        ;0        ;OVERFLOW
  277.                     ;    BITS
  278.                     ;     7,6 = 0,0
  279.                     ;     5 = BIT 9 OF TABLE(06)
  280.                     ;     4 = 1 - BIT 8 OF TABLE(18)
  281.                     ;     3 = BIT 8 OF TABLE(15)
  282.                     ;     2 = BIT 8 OF TABLE(10)
  283.                     ;     1 = BIT 8 OF TABLE(12)
  284.                     ;     0 = BIT 8 OF TABLE(06)
  285.             DB    0        ;PRESET ROW SCAN=00
  286.             DB    40H        ;0        ;MAXIMUN SCAN LINE
  287.                     ;    BITS
  288.                     ;     7    = 1 IF Y_ROW <=200
  289.                     ;          0 IF Y_ROW >200
  290.                     ;     6 = 1 - BIT 9 OF TABLE(18)
  291.                     ;     5 = BIT 9 OF TABLE(15)
  292.                     ;     4-0 = MAX SCAN LINE = 00
  293.             DB    0        ;CURSOR START=00
  294.             DB    0        ;CURSOR END=00
  295.             DB    0        ;START ADDRESS HIGH=00
  296.             DB    0        ;START ADDR LOW=00
  297.             DB    0        ;CURSOR LOCATION HIGH=00
  298.             DB    0        ;CURSOR LOCATION LOW=00
  299.             DB    0EAH        ;0        ;VERTICAL RETRACE START=
  300.                     ;    IF Y_ROW<=200 THEN Y_ROW*2+12
  301.                     ;    IF Y_ROW>200  THEN Y_ROW+10
  302.             DB    8CH        ;0        ;VERTICAL RETRACE END
  303.                     ;    BITS
  304.                     ;     7 = 1 - PROTECT CRTC TABLE REGS 0-7
  305.                     ;         0 - DON'T PROTECT REGS 0-7
  306.                     ;     6-4 = 0
  307.                     ;     3-0 = LOW FOUR BITS OF TABLE(10)+2
  308.             DB    0DFH        ;0        ;VERTICAL DISPLAY ENABLE END= LOW EIGHT BITS OF
  309.                     ;    IF Y_ROW<=200 THEN Y_ROW*2-1
  310.                     ;    IF Y_ROW >200 THEN Y_ROW-1
  311.             DB    28H        ;0        ;OFFSET=# OF CHARS*.5
  312.             DB    0        ;40H        ;UNDERLINE LOCATION
  313.                     ;    BITS
  314.                     ;     7 = 0
  315.                     ;     6 = 1
  316.                     ;     5-0 = 0
  317.             DB    0E7H        ;0        ;START VERTICAL BLANK= LOW EIGHT BITS OF
  318.                     ;    IF Y_ROW<=200 THEN Y_ROW*2+6
  319.                     ;    IF Y_ROW >200 THEN Y_ROW+6
  320.             DB    04        ;0        ;END VERTICAL BLANK=TABLE(15)+32
  321.             DB    0A3H        ;0A3H        ;CRTC MODE CONTROL
  322.                     ;    BITS
  323.                     ;     7 = 1
  324.                     ;     6 = 0
  325.                     ;     5 = 1
  326.                     ;     4-2 = 0
  327.                     ;     1-0 = 1
  328.             DB    45H        ;LINE COMPARE=0345H
  329.  
  330.             
  331.                 
  332. VGASCRN        PROC    FAR
  333.     PUSH    BP
  334.     MOV        BP,SP
  335.     PUSH    DS
  336.     PUSH    ES
  337.     
  338.     JMP        DO_IT        ;ABORTING LOADING THE CRTC REGISTERS
  339.     
  340.     MOV        AX,[BP+X]        ;GET SCREEN X WIDTH (IN PIXELS)
  341.     MOV        X_COL,AX        ;SAVE SCREEN WIDTH
  342.     MOV        CL,3            
  343.     SHR        AX,CL            ;CONVERT # OF COLUMNS INTO NUMBER OF CHARACTERS
  344.     MOV        NUM_CHARS,AL    ;SAVE # OF CHARS WIDE THE SCREEN IS
  345.     MOV        AX,[BP+X+2]        ;GET SCREEN HEIGHT (IN PIXELS)
  346.     MOV        Y_ROW,AX        ;SAVE SCREEN HEIGHT
  347.     
  348. ;    
  349.     MOV        SI,0            ;INITIAL VALUE FOR OFFSET INTO TABLE
  350.     MOV        AL,TABLE[11H]    ;GET PROTECTION BIT
  351.     AND        AL,07FH            ;MASK OFF TOP BIT
  352.     MOV        TABLE[11H],AL    ;STORE IT BACK TO ALLOW WRITES TO REGS 0-7
  353. ;
  354.     MOV        DL,NUM_CHARS    ;GET NUMBER OF CHARACTERS
  355.     MOV        AL,DL            
  356.     SHR        AL,1
  357.     SHR        AL,1            ;GET THE NUMBER OF CHARS DIVIDED BY 4
  358.     ADD     AL,DL            
  359.     SUB        AL,5            ;FINAL VALUE FOR TABLE(00)
  360.     MOV        TABLE[SI],AL    ;STORE IN FIRST POSION OF TABLE
  361.     INC        SI                ;INCREMENT FOR NEXT VALUE OF TABLE
  362. ;
  363.     MOV        AL,NUM_CHARS    ;GET THE NUMBER OF CHARACTERS
  364.     SUB        AL,1            ;MAKE INTO PROPER VALUE
  365.     MOV        TABLE[SI],AL    ;STORE IN TABLE(01)
  366.     INC        SI                ;INCREMENT TO NEXT VALUE OF TABLE
  367. ;    
  368.     MOV        AL,NUM_CHARS    ;GET THE NUMBER OF CHARACTERS WIDE THE SCREEN IS
  369.     MOV        TABLE[SI],AL    ;STORE TABLE(02)
  370.     INC        SI                ;INCREMENT TO NEXT VALUE OF TABLE
  371. ;    
  372.     MOV        AL,TABLE[00]    ;GET TABLE(00)
  373.     ADD        AL,3            ;AX HAS TABLE(00)+3 IN IT
  374.     MOV        TEMP1,AL        ;KEEP TRACK OF THIS NUMBER FOR LATER
  375.     AND        AL,1FH            ;MASK OFF ALL BUT FIVE LOWEST BITS
  376.     OR        AL,080H            ;TURN ON THE HIGHEST BIT
  377.     MOV        TABLE[SI],AL    ;STORE IN TABLE(03)
  378.     INC        SI                ;GO ON TO NEXT TABLE VALUE
  379. ;
  380.     MOV        AL,TABLE[00]    ;GET TABLE(00)
  381.     ADD        AL,TABLE[2]    ;ADD IN TABLE(02)
  382.     SHR        AL,1            ;DIVIDE BY 2
  383.     MOV        TABLE[SI],AL    ;STORE IN TABLE(04)
  384.     INC        SI                ;GO ON TO NEXT TABLE VALUE
  385. ;
  386.     MOV        AL,TEMP1        ;GET THE TEMPORARY VALUE SAVED
  387.     SHL        AL,1
  388.     SHL        AL,1            ;MOVE THE SIXTH BIT INTO THE EIGHT BIT'S POSITION
  389.     AND        AL,080H            ;CLEAR OUT ALL BUT THE HIGHEST BIT
  390.     MOV        TABLE[SI],AL    ;STORE IN TABLE(05)
  391.     INC        SI                ;INCREMENT TABLE INDEX
  392. ;
  393.     MOV        AX,Y_ROW        ;GET THE NUMBER OF ROWS ON THE SCREEN
  394.     SHL        AX,1            ;MULTIPLY BY 2
  395.     MOV        DX,AX            ;SAVE THIS VALUE
  396.     MOV        AX,Y_ROW        ;GET THE NUMBER OF ROWS AGAIN
  397.     SHR        AX,1            ;DIVIDE BY 2
  398.     ADD        AX,DX            ;GET THE TOTAL
  399.     CMP        Y_ROW,200        ;CHECK FOR MORE THAN 200 ROWS
  400.     JNA        S1                ;IF <=200 ROWS THEN DON'T DIVIDE #
  401.     SHR        AX,1            ;DIVIDE NUMBER BY 2
  402. S1:
  403.     SUB        AX,2            ;SUBTRACT 2 FROM TOTAL
  404.     MOV        TEMP2,AX        ;KEEP AROUND FOR LATER
  405.     MOV        TABLE[SI],AL    ;STORE LOW EIGHT BITS IN TABLE(06)
  406.     INC        SI                ;INCREMENT TABLE INDEX        
  407. ;
  408.     INC        SI                ;COME BACK FOR TABLE(07) LATER AFTER OTHER VALUES ARE CALCULATED
  409. ;
  410.     INC        SI                ;TABLE(08) ALWAYS HAS A ZERO IN IT
  411. ;
  412.     INC        SI                ;COME BACK FOR TABLE(09) ALSO
  413. ;
  414.     ADD        SI,6            ;NEXT TABLE(0A)-TABLE(0F) ALWAYS HAVE ZEROES IN THEM
  415. ;
  416.     MOV        AX,Y_ROW        ;GET THE NUMBER OF ROWS ON THE SCREEN
  417.     CMP        AX,200            ;CHECK IF UNDER 200 ROWS
  418.     JA        S2                ;YES, MORE THAN 200 LINES SO DON'T MULTIPLY
  419.     SHL        AX,1            ;MULTIPLY NUMBER BY 2
  420. S2:    
  421.     ADD        AX,10            ;FINAL 9 BIT VALUE 
  422.     MOV        TEMP3,AX        ;KEEP IT AROUND
  423.     MOV        TABLE[SI],AL    ;STORE THE LOW EIGHT BITS IN TABLE(10)
  424.     INC        SI                ;INCREMENT TO NEXT TABLE VALUE
  425. ;
  426.     MOV        AL,TABLE[10H]    ;GET TABLE(10)
  427.     AND        AL,0FH            ;MASK OFF TOP FOUR BITS
  428.     MOV        TABLE[SI],AL    ;STORE IN TABLE(11)
  429.     INC        SI                ;INCRMENT TABLE INDEX
  430. ;
  431.     MOV        AX,Y_ROW        ;GET THE NUMBER OF ROWS
  432.     CMP        AX,200            ;CHECK FOR UNDER 200 AGAIN
  433.     JA        S3                ;IF OVER 200 THEN DON'T MULTIPLY
  434.     SHL        AX,1            ;MULTIPLY BY 2
  435. S3:
  436.     SUB        AX,1            ;FINAL 10 BIT VALUE
  437.     MOV        TEMP4,AX        ;KEEP THIS AROUND
  438.     MOV        TABLE[SI],AL    ;STORE IN TABLE(12)
  439.     INC        SI                ;INCREMENT TABLE INDEX
  440. ;
  441.     MOV        AL,NUM_CHARS    ;GET THE NUMBER OF CHARACTERS WIDE
  442.     SHR        AL,1            ;DIVIDE IT BY 2
  443.     MOV        TABLE[SI],AL    ;STORE IN TABLE(13)
  444.     INC        SI                ;INCREMENT TABLE INDEX
  445. ;
  446.     INC        SI                ;TABLE(14) IS PRESET
  447. ;
  448.     MOV        AX,Y_ROW        ;GET NUMBER OF ROWS
  449.     CMP        AX,200            ;CHECK IF IT IS OVER 200
  450.     JA        S4                ;IF OVER 200 THEN DON'T MULTIPLY
  451.     SHL        AX,1            ;MULTIPLY BY 2
  452. S4:
  453.     ADD        AX,6            ;FINAL VALUE FOR TEN BIT NUMBER
  454.     MOV        TEMP5,AX        ;KEEP THIS AROUND
  455.     MOV        TABLE[SI],AL    ;STORE IN TABLE(15)
  456.     INC        SI                ;INCREMENT TABLE INDEX
  457. ;
  458.     MOV        AL,TABLE[15H]    ;GET TABLE(15)
  459.     ADD        AL,32            ;FINAL VALUE FOR TABLE(16)
  460.     MOV        TABLE[SI],AL    ;STORE IN TABLE(16)
  461.     INC        SI                ;INCREMENT TABLE INDEX
  462. ;
  463. ;    TABLE(17) AND TABLE(18) ARE PRESET ALSO
  464. ;
  465. ;MAKE TABLE(07)
  466.     MOV        AX,TEMP2        ;GET TEN BIT VERSION OF TABLE(06)
  467.     MOV        CL,4
  468.     SHR        AX,CL            ;SHIFT INTO PROPER BIT POSITION (5)
  469.     AND        AL,20H            ;CLEAR OUT LOWER BITS
  470.     MOV        DL,AL            ;STORE IT SOMEWHERE
  471.     OR        DL,10H            ;MESH THE VALUES TOGETHER
  472.     MOV        AX,TEMP5        ;GET THE TEN BIT VERSION OF TABLE(15)
  473.     MOV        CL,5            
  474.     SHR        AX,CL            ;SHIFT INTO PROPER BIT POSITION (3)
  475.     AND        AL,8            ;KILL OFF OTHER BITS
  476.     OR        DL,AL            ;MESH TOGETHER
  477.     MOV        AX,TEMP3        ;GET THE NINE BIT VERSION OF TABLE(10)
  478.     MOV        CL,6            
  479.     SHR        AX,CL            ;SHIFT INTO PROPER BIT POSITION (2)
  480.     AND        AL,4            ;KILL OTHER BITS
  481.     OR        DL,AL            ;MESH INTO TOTAL
  482.     MOV        AX,TEMP4        ;GET THE TEN BIT VERSION OF TABLE(12)
  483.     MOV        CL,7            
  484.     SHR        AX,CL            ;SHIFT INTO PROPER BIT POSITION (1)
  485.     AND        AL,2            ;KILL OTHER BITS
  486.     OR        DL,AL            ;MESH INTO FINAL VALUE
  487.     MOV        AX,TEMP2        ;GET THE TEN BIT VERSION OF TABLE(06)
  488.     MOV        AL,AH            ;GET INTO PROPER BIT POSITION (0)
  489.     AND        AL,1            ;KILL OFF OTHER BITS
  490.     OR        AL,DL            ;RETRIEVE TOTAL VALUE
  491.     MOV        TABLE[7],AL    ;STORE THIS MISH-MASH INTO TABLE(07)
  492. ;
  493. ;MAKE TABLE(09)
  494.     MOV        AL,40H            ;SET THE VALUE OF TABLE(09) TO BE MODIFIED
  495.     CMP        Y_ROW,200        ;CHECK IF MORE THAN 200 ROWS
  496.     JA        S5                ;IF IT IS LESS THAN 200 THEN SET BIT (7)
  497.     OR        AL,080H            ;SET BIT (7)
  498. S5:
  499.     MOV        DL,AL            ;KEEP TRACK OF THIS
  500.     MOV        AX,TEMP5        ;GET THE TEN BIT VERSION OF TABLE(15)
  501.     MOV        CL,4
  502.     SHR        AX,CL            ;SHIFT BIT 9 INTO BIT 5 POSITION
  503.     AND        AL,20H            ;KILL OFF OTHER BITS
  504.     OR        AL,DL            ;GET OTHER STUFF STORED
  505.     MOV        TABLE[9],AL    ;STORE TABLE(09)
  506. ;
  507.     MOV        AL,TABLE[11H]    ;GET TABLE(11)
  508.     OR        AL,080H            ;SET THE PROTECT BIT AGAIN
  509.     MOV        TABLE[11H],AL    ;PUT TABLE(11) BACK
  510.  
  511. DO_IT:
  512.     MOV        DX,CRT_ADDR        ;GET THE ADDRESS OF THE CRTC CONTROLLER
  513.     MOV        CX,019H            ;GET THE SIZE OF THE TABLE
  514.     MOV        SI,0            ;SET INDEX TO 0
  515.     MOV        AX,0            ;CLEAR OUT ACCUMULATOR
  516. LOOPTOP:
  517.     MOV        AL,AH            ;INIT LOOP
  518.     OUT        DX,AL            ;SET CRTC REGISTER NUMBER
  519.     INC        DX
  520.     INC        AH
  521.     MOV        AL,TABLE[SI]    ;GET OUTPUT VALUE
  522.     OUT        DX,AL            ;OUTPUT VALUE TO CRTC REGISTER
  523.     INC        SI                ;INCREMENT CRTC REGISTER INDEX
  524.     DEC        DX                ;GO BACK TO CONTROLLER ADDRESS
  525.     LOOP    LOOPTOP            ;KEEP DOING THIS FOR ALL VALUES
  526.  
  527.     JMP        NOPE
  528.  
  529.     CMP        X_COL,360        ;CHECK TO SEE IF THE NUMBER OF COLUMNS IS SMALL
  530.     JA        NOPE            ;THE NUMBER OF COLUMNS IS BIG ENOUGH NOT TO SET BIT
  531.     MOV        AL,SEQ_TABLE[1]    ;GET THE BYTE TO SET
  532.     OR        AL,08H            ;TURN ON THE BIT FOR A SMALLISH SCREEN
  533.     MOV        SEQ_TABLE[1],AL    ;REPLACE THE BYTE
  534. NOPE:
  535.     MOV        DX,SEQ_ADDR        ;GET THE ADDRESS OF THE SEQ CONTROLLER
  536.     MOV        CX,5            ;GET THE SIZE OF THE TABLE
  537.     MOV        SI,0            ;SET THE INDEX TO ZERO
  538.     XOR        AX,AX            ;CLEAR THE ACCUMULATOR
  539. SEQ_LOOP:
  540.     MOV        AL,AH            ;INIT LOOP    
  541.     OUT        DX,AL            ;SET SEQ REGISTER NUMBER
  542.     INC        DX
  543.     INC        AH
  544.     MOV        AL,SEQ_TABLE[SI]    ;GET OUTPUT VALUE
  545.     OUT        DX,AL            ;OUTPUT VALUE TO SEQ REGISTER
  546.     INC        SI                ;INCREMENT SEQ REGISTER INDEX
  547.     DEC        DX                ;GO BACK TO CONTROLLER ADDRESS
  548.     LOOP    SEQ_LOOP        ;KEEP DOING THIS FOR ALL VALUES        
  549.  
  550.     MOV        DX,GRAF_ADDR        ;GET THE ADDRESS OF THE GRAF CONTROLLER
  551.     MOV        CX,9            ;GET THE SIZE OF THE TABLE
  552.     MOV        SI,0            ;SET THE INDEX TO ZERO
  553.     XOR        AX,AX            ;CLEAR THE ACCUMULATOR
  554. GRAF_LOOP:
  555.     MOV        AL,AH            ;INIT LOOP    
  556.     OUT        DX,AL            ;SET GRAF REGISTER NUMBER
  557.     INC        DX
  558.     INC        AH
  559.     MOV        AL,GRAF_TABLE[SI]    ;GET OUTPUT VALUE
  560.     OUT        DX,AL            ;OUTPUT VALUE TO GRAF REGISTER
  561.     INC        SI                ;INCREMENT GRAF REGISTER INDEX
  562.     DEC        DX                ;GO BACK TO CONTROLLER ADDRESS
  563.     LOOP    GRAF_LOOP        ;KEEP DOING THIS FOR ALL VALUES        
  564.  
  565.     MOV        DX,ATTR_ADDR    ;GET THE ADDRESS OF THE ATTR CONTROLLER
  566.     MOV        CX,5            ;GET THE SIZE OF THE TABLE
  567.     MOV        SI,0            ;SET THE INDEX TO ZERO
  568.     MOV        AX,3000H        ;SET THE ACCUMULATOR
  569.     MOV        DX,03DAH        ;
  570.     IN        AL,DX            ;SMALL ROUTINE TO SET UP THE ATTR REGISTERS CORRECTLY
  571.     MOV        DX,ATTR_ADDR    ;
  572. ATTR_LOOP:        ;NOTE THE CONTROLLER AND DATA REGISTERS USE THE SAME I/O PORT
  573.     MOV        AL,AH            ;INIT LOOP    
  574.     OUT        DX,AL            ;SET ATTR REGISTER NUMBER
  575.     INC        AH
  576.     MOV        AL,ATTR_TABLE[SI]    ;GET OUTPUT VALUE
  577.     OUT        DX,AL            ;OUTPUT VALUE TO ATTR REGISTER
  578.     INC        SI                ;INCREMENT ATTR REGISTER INDEX
  579.     LOOP    ATTR_LOOP        ;KEEP DOING THIS FOR ALL VALUES        
  580.  
  581.     MOV        DX,03C2H        ;ADDRESS OF THE MISC OUTPUT REGISTER
  582. ;    CMP        Y_ROW,350        ;CHECK IF ROWS = 350
  583. ;    JNE        N1                ;JUMP TO NEXT CHECK
  584. ;    MOV        AL,40H            ;SET THE VERTICAL AND HORIZONTAL SYNC POLARITY
  585. ;    JMP        GO_ON            ;JUMP TO FINISH SETTING THE BITS
  586. ;N1:
  587. ;    CMP        Y_ROW,480        ;CHECK IF ROWS = 480
  588. ;    JNE        N2                ;JUMP TO SET THE DEFAULT BITS
  589. ;    MOV        AL,0C0H            ;SET THE VERTICAL AND HORIZONTAL SYNC POLARITY
  590. ;    JMP        GO_ON            ;JUMP TO FINISH SETTING THE BITS
  591. ;N2:
  592. ;    MOV        AL,080H            ;DEFAULT SETTING FOR VERT AND HORI SYNC BITS
  593. ;GO_ON:
  594. ;    OR        AL,23H            ;SET THE REST OF THE BITS WE NEED
  595.     MOV        AL,63H
  596.     OUT        DX,AL            ;AND WRITE OUT TO THE MISC OUTPUT REGISTER
  597.     
  598.     MOV        DX,03C3H        ;ADDRESS OF THE VGA ENABLE REGISTER
  599.     MOV        AL,1            ;ENABLE THE VIDEO STUFF
  600.     OUT        DX,AL            ;WRITE TO THE VGA ENABLE REGISTER
  601.  
  602.     POP    ES
  603.     POP    DS
  604.     POP    BP
  605.     RET
  606. VGASCRN    ENDP
  607.  
  608. ;
  609. ;    showpalv(&palstore,pal_xoff,pal_yoff);
  610. ;    
  611. SHOWPALV        PROC    FAR
  612.     PUSH    BP
  613.     MOV        BP,SP
  614.     PUSH    DS
  615.     PUSH    ES
  616.  
  617.  
  618.     MOV     AX,[BP+X]        ;GET OFFSET OF ARRAY
  619.     MOV        DI,AX
  620.     MOV        AX,[BP+X+2]        ;GET SEGMENT OF STORAGE ARRAY
  621.     MOV        ES,AX            
  622.  
  623.     MOV        AX,[BP+X+6]        ;GET LINE TO START PALETTE ON
  624.     MOV        DX,320            ;GET THE LINE LENGTH
  625.     MUL        DX                ;GET THE OFFSET INTO THE SCREEN
  626.     ADD        AX,[BP+X+4]        ;ADD IN THE X OFFSET
  627.     JNC        NO_ROLLOVER        ;ADDITION DIDN'T CARRY
  628.     INC        DX                ;INCREMENT THE DX REGISTER ON A CARRY
  629. NO_ROLLOVER:
  630.     MOV        SI,AX            ;KEEP TRACK OF THE OFFSET
  631.     MOV        BX,SI            ;IN TWO PLACES
  632.     MOV        AX,320            ;GET THE LINE LENGTH
  633.     MOV        DX,8            ;GET THE NUMBER OF LINES
  634.     MUL        DX                ;GET THE NUMBER OF BYTES TO COPY
  635.     MOV        CX,AX            ;MOVE INTO COUNTER
  636.     MOV        AX,0A000H
  637.     MOV        DS,AX            ;GET THE SEGMENT FOR THE SOURCE
  638. ZIP:
  639.     REP        MOVSB            ;COPY THAT SECTION OF SCREEN
  640.     
  641.     MOV        CH,0            ;THE NUMBER OF LINES COPIED SO FAR
  642.     MOV        CL,00            ;THE NUMBER OF PIXELS
  643. TOP1:
  644.     MOV        SI,BX            ;GET THE CORRECT OFFSET TO BE COPIED TO
  645.     MOV        AX,0A000H
  646.     MOV        ES,AX            ;GET THE SEGMENT TO BE COPIED TO
  647. TOP2:
  648.     MOV        ES:[SI],CL        ;COPY ACROSS THE SCREEN INCREMENTING VALUES
  649.     INC        SI                ;MOVE TO NEXT PIXEL
  650.     INC        CL                ;INCREMENT COUNTER
  651.     JNE        TOP2            ;IF COUNTER NOT EQUAL TO ZERO THEN COPY AGAIN
  652.     
  653.     ADD        BX,320            ;MOVE DOWN TO NEXT LINE
  654.     INC        CH                ;INCREMENT THE LINE COUNTER
  655.     CMP        CH,8            ;CHECK IF ALL THE LINES ARE DONE
  656.     JNE        TOP1            ;IF LINE COUNT <8 THEN COPY ANOTHER LINE
  657.  
  658.     POP    ES
  659.     POP    DS
  660.     POP    BP
  661.     RET
  662. SHOWPALV    ENDP
  663.  
  664. ;
  665. ;    nopalv(&palstore,pal_xoff,pal_yoff);
  666. ;
  667. NOPALV        PROC    FAR
  668.     PUSH    BP
  669.     MOV        BP,SP
  670.     PUSH    DS
  671.     PUSH    ES
  672.  
  673.     MOV     AX,[BP+X]        ;GET OFFSET OF ARRAY
  674.     MOV        SI,AX
  675.     MOV        AX,[BP+X+2]        ;GET SEGMENT OF STORAGE ARRAY
  676.     MOV        DS,AX            
  677.  
  678.     MOV        AX,[BP+X+6]        ;GET LINE TO COPY SCREEN BACK ONTO
  679.     MOV        DX,320            ;GET THE LINE LENGTH
  680.     MUL        DX                ;GET THE OFFSET INTO THE SCREEN
  681.     ADD        AX,[BP+X+4]        ;ADD IN THE X OFFSET
  682.     JNC        NO_ROLL2        ;ADDITION DIDN'T CARRY
  683.     INC        DX                ;INCREMENT THE DX REGISTER ON A CARRY
  684. NO_ROLL2:
  685.     MOV        DI,AX            ;KEEP TRACK OF THE OFFSET
  686.     MOV        AX,320            ;GET THE LINE LENGTH
  687.     MOV        DX,8            ;GET THE NUMBER OF LINES
  688.     MUL        DX                ;GET THE NUMBER OF BYTES TO COPY
  689.     MOV        CX,AX            ;MOVE INTO COUNTER
  690.     MOV        AX,0A000H
  691.     MOV        ES,AX            ;GET THE SEGMENT FOR THE SOURCE
  692. ZOOM:
  693.     REP        MOVSB            ;COPY THAT SECTION OF SCREEN
  694.  
  695.     POP    ES
  696.     POP    DS
  697.     POP    BP
  698.     RET
  699. NOPALV    ENDP
  700.  
  701. SCRLRITE    PROC    FAR
  702.     PUSH    BP
  703.     MOV        BP,SP
  704.     PUSH    DS
  705.     PUSH    ES
  706.  
  707.     MOV        AX,0A000H        ;GET SEGMENT OF DISPLAY AREA
  708.     MOV        ES,AX            ;USE THAT SEGMENT FOR BOTH DEST
  709.     MOV        DS,AX            ;AND SOURCE
  710.     MOV        SI,63999        ;BEGINNING OF THE SOURCE TO MOVE
  711.     MOV        DI,64000        ;BEGINNING OF THE DEST
  712.     MOV        CX,63999        ;MOV THE ENTIRE SCREEN
  713. RITELOOP:
  714.     MOVSB                    ;MOVE A BYTE
  715.     DEC        SI
  716.     DEC        SI
  717.     DEC        DI
  718.     DEC        DI
  719.     LOOP    RITELOOP        ;GO BACK AND DO IT AGAIN
  720.  
  721.     POP    ES
  722.     POP    DS
  723.     POP    BP
  724.     RET
  725. SCRLRITE    ENDP
  726.  
  727.  
  728. SCRLLEFT    PROC    FAR
  729.     PUSH    BP
  730.     MOV        BP,SP
  731.     PUSH    DS
  732.     PUSH    ES
  733.  
  734.     MOV        AX,0A000H        ;SEGMENT OF DISPLAY AREA
  735.     MOV        ES,AX            ;USE DISPLAY AREA FOR MOVE
  736.     MOV        DS,AX            ;BOTH AS SOURCE AND DESTINATION
  737.     MOV        SI,1            ;START IN THE FIRST POSISTION TO MOVE FROM
  738.     MOV        DI,0            ;MOVE BACK TO THE PREVIOUS POSITION
  739.     MOV        CX,63999        ;MOVE THE WHOLE SCREEN
  740. ZOWIE:
  741.     REP        MOVSB            ;ACTUALLY MOVE THE SCREEN
  742.  
  743.     POP    ES
  744.     POP    DS
  745.     POP    BP
  746.     RET
  747. SCRLLEFT    ENDP
  748.  
  749. SCRLUP        PROC    FAR
  750.     PUSH    BP
  751.     MOV        BP,SP
  752.     PUSH    DS
  753.     PUSH    ES
  754.  
  755.     MOV        AX,0A000H        ;SEGMENT OF DISPLAY AREA
  756.     MOV        ES,AX            ;USE DISPLAY AREA FOR MOVE
  757.     MOV        DS,AX            ;BOTH AS SOURCE AND DESTINATION
  758.     MOV        SI,320            ;START IN THE FIRST POSISTION TO MOVE FROM
  759.     MOV        DI,0            ;MOVE BACK TO THE PREVIOUS POSITION
  760.     MOV        CX,63680        ;MOVE THE WHOLE SCREEN
  761. WHAM:
  762.     REP        MOVSB            ;ACTUALLY MOVE THE SCREEN
  763.  
  764.     POP    ES
  765.     POP    DS
  766.     POP    BP
  767.     RET
  768. SCRLUP        ENDP
  769.  
  770. SCRLDOWN    PROC    FAR
  771.     PUSH    BP
  772.     MOV        BP,SP
  773.     PUSH    DS
  774.     PUSH    ES
  775.  
  776.     MOV        AX,0A000H        ;GET SEGMENT OF DISPLAY AREA
  777.     MOV        ES,AX            ;USE THAT SEGMENT FOR BOTH DEST
  778.     MOV        DS,AX            ;AND SOURCE
  779.     MOV        SI,63680        ;BEGINNING OF THE SOURCE TO MOVE
  780.     MOV        DI,64000        ;BEGINNING OF THE DEST
  781.     MOV        CX,63680        ;MOV THE ENTIRE SCREEN
  782. DOWNLOOP:
  783.     MOVSB                    ;MOVE A BYTE
  784.     DEC        SI
  785.     DEC        SI
  786.     DEC        DI
  787.     DEC        DI
  788.     LOOP    DOWNLOOP        ;GO BACK AND DO IT AGAIN
  789.  
  790.     POP    ES
  791.     POP    DS
  792.     POP    BP
  793.     RET
  794. SCRLDOWN    ENDP
  795. ;
  796. ;  Invert A BOX ON THE SCREEN
  797. ;
  798. ;   usage : outlinev(x1,y1,x2,y2)
  799. ;
  800. OUTLINEV    PROC    FAR
  801.     PUSH    BP
  802.     MOV    BP,SP
  803.     PUSH    DS
  804.     PUSH    ES
  805.  
  806.     MOV    AX,[BP+X+2]    ; GET FIRST Y VALUE
  807.     CMP    AX,[BP+X+6]    ; COMPARE WITH THE SECOND Y - VALUE
  808.     JLE    CHECKX        ; OK ORDER GOTO CHECKING THE X VALUES
  809.     MOV    CX,AX        ; SWAP THE TWO VALUES
  810.     MOV    AX,[BP+X+6]    ;
  811.     MOV    [BP+X+2],AX    ;
  812.     MOV    AX,CX        ;
  813.     MOV    [BP+X+6],AX    ;
  814. CHECKX:
  815.     MOV    AX,[BP+X]    ; GET FIRST X VALUE
  816.     CMP    AX,[BP+X+4]    ; COMPARE WITH THE SECOND X - VALUE
  817.     JLE    MAKELEN        ; OK ORDER GOTO COMPUTING THE LENGTHS
  818.     MOV    CX,AX        ; SWAP THE TWO VALUES
  819.     MOV    AX,[BP+X+4]    ;
  820.     MOV    [BP+X],AX    ;
  821.     MOV    AX,CX        ;
  822.     MOV    [BP+X+4],AX    ;
  823. MAKELEN:            ; COMPUTE THE X AND Y WIDTHS FOR THE BOX TO BE INVERTED
  824.     MOV    AX,[BP+X+4]    ; GET THE LARGER OF THE TWO X VALUES
  825.     SUB    AX,[BP+X]    ; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
  826.     ADD    AX,1        ;
  827.     MOV    [BP+X+4],AX    ; STORE IT IN THE OLD LOCATION FOR THE 2ND X VALUE
  828.     MOV    AX,[BP+X+6]    ; GET THE LARGER OF THE TWO Y VALUES
  829.     SUB    AX,[BP+X+2]    ; SUBTRACT THE SMALLER VALUE TO FIND THE LENGTH
  830.     SUB    AX,1        ; SUBTRACT TWO FOR THE TOP AND BOTTOM EDGES
  831.     CMP    AX,0        ; CHECK IF IT IS LESS THAN ZERO
  832.     JG     POSITIVE    ; JUMP AROUND ZEROING THE ACC.
  833.     MOV    AX,0
  834. POSITIVE:
  835.     MOV    [BP+X+6],AX    ; STORE IT IN THE OLD LOCATION FOR THE 2ND Y VALUE
  836.     MOV    AX,320        ; COMPUTE THE VALUE TO ADD TO THE DI FOR COMPLETE WRAPAROUND
  837.     SUB    AX,[BP+X+4]    ;
  838.     MOV    SI,AX        ; KEEP TRACK OF IT
  839.     
  840.     MOV    AX,0A000H    ; DATA BUFFER
  841.     MOV    ES,AX
  842. ;
  843.     MOV    AX,[BP+X+2]    ; GET Y VALUE AGAIN
  844.     MOV    DX,320        ; GET LENGTH OF A LINE
  845.     MUL    DX
  846.     JA    DONTFIXA    ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
  847.     MOV    BX,ES        ; GET THE ES
  848.     ADD    BX,DX        ; INCREMENT THE ES
  849.     MOV    ES,BX        ; AND REPLACE IT
  850. DONTFIXA:
  851.     ADD    AX,[BP+X]    ; X VALUE OF WHERE ON SCREEN ADDED IN
  852.     MOV    DI,AX        ; PREPARE FOR MOVS
  853.     MOV    CX,[BP+X+4]    ; HOW MANY BYTES?
  854. BLASTA:
  855.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  856.     NOT    AL        ; INVERT THE VALUE THERE
  857.     MOV    ES:[DI],AL    ; REPLACE THE VALUE
  858.     INC    DI        ; INCREMENT TO NEXT POSITION
  859.     LOOP     BLASTA        ; LOOP UNTIL ALL HAVE BEEN DONE
  860.  
  861.     ADD    DI,SI        ; MOVE OVER TO THE BEGINNING OF THE NEXT LINE
  862.     MOV    CX,[BP+X+6]    ; COUNT VALUE FOR THE NEXT SERIES
  863.     CMP    CX,0        ; CHECK FOR NO LINES IN BETWEEN
  864.     JLE    BLAST2A        ; JUMP AROUND PUTTING THE LINES IN BETWEEN
  865. BLAST2:
  866.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  867.     NOT    AL            ; INVERT IT
  868.     MOV    ES:[DI],AL    ; REPLACE THE INVERTED VALUE
  869.     ADD    DI,[BP+X+4]    ; GO TO THE LAST VALUE TO INVERT ON THAT LINE
  870.     SUB    DI,1        ;
  871.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  872.     NOT    AL        ; INVERT IT
  873.     MOV    ES:[DI],AL    ; REPLACE THE INVERTED VALUE
  874.     ADD    DI,SI        ; GET THE VALUE FOR THE BEGINNING OF THE NEXT LINE
  875.     INC    DI        ;
  876.     LOOP    BLAST2        ; DO THE NEXT LINE
  877.  
  878. BLAST2A:
  879.     MOV    CX,[BP+X+4]    ; PREPARE FOR LAST LINE
  880. BLAST3:
  881.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  882.     NOT    AL            ; INVERT THE VALUE THERE
  883.     MOV    ES:[DI],AL    ; REPLACE THE VALUE
  884.     INC    DI            ; INCREMENT TO NEXT POSITION
  885.     LOOP    BLAST3        ; LOOP UNTIL ALL HAVE BEEN DONE
  886.  
  887.     POP    ES
  888.     POP    DS
  889.     POP    BP
  890.     RET
  891. OUTLINEV    ENDP
  892. ;
  893. ;  Draw a 4x4 ball on the vga screen
  894. ;
  895. ;   usage : ball(x,y)
  896. ;
  897. BALL        PROC    FAR
  898.     PUSH    BP
  899.     MOV        BP,SP
  900.     PUSH    DS
  901.     PUSH    ES
  902.  
  903.     MOV    AX,0A000H    ; DATA BUFFER
  904.     MOV    ES,AX
  905. ;
  906.     MOV    AX,[BP+X+2]    ; GET Y VALUE
  907.     MOV    DX,320        ; GET LENGTH OF A LINE
  908.     MUL    DX
  909.     JA    DONTFIXB    ; IF DX IS ZERO THEN DON'T PLAY WITH THE SEGMENT
  910.     MOV    BX,ES        ; GET THE ES
  911.     ADD    BX,DX        ; INCREMENT THE ES
  912.     MOV    ES,BX        ; AND REPLACE IT
  913. DONTFIXB:
  914.     ADD    AX,[BP+X]    ; X VALUE OF WHERE ON SCREEN ADDED IN
  915.     MOV    DI,AX        ; PREPARE FOR MOVS
  916.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  917.     NOT    AL            ; INVERT IT
  918.     MOV    ES:[DI],AL    ; REPLACE THE VALUE
  919.     INC    DI            ; MOVE OVER ONE BYTE
  920.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  921.     NOT    AL            ; INVERT IT
  922.     MOV    ES:[DI],AL    ; REPLACE THE VALUE
  923.  
  924.     ADD    DI,318        ; MOVE TO THE NEXT LINE
  925.     MOV    CX,4        ; HOW MANY BYTES?
  926. BLASTB:
  927.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  928.     NOT    AL            ; INVERT THE VALUE THERE
  929.     MOV    ES:[DI],AL    ; REPLACE THE VALUE
  930.     INC    DI            ; INCREMENT TO NEXT POSITION
  931.     LOOP BLASTB        ; LOOP UNTIL ALL HAVE BEEN DONE
  932.  
  933.     MOV    CX,4        ; COUNT VALUE FOR THE NEXT SERIES
  934.     ADD    DI,316        ; MOVE OVER TO THE BEGINNING OF THE NEXT LINE
  935. BLASTC:
  936.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  937.     NOT    AL            ; INVERT IT
  938.     MOV    ES:[DI],AL    ; REPLACE THE INVERTED VALUE
  939.     INC DI            ;
  940.     LOOP    BLASTC    ; DO THE NEXT LINE
  941.  
  942.     ADD    DI,317        ; MOVE ONE BYTE OVER INTO THE NEXT LINE
  943.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  944.     NOT    AL            ; INVERT IT
  945.     MOV    ES:[DI],AL    ; REPLACE THE VALUE
  946.     INC    DI            ; MOVE OVER ONE BYTE
  947.     MOV    AL,ES:[DI]    ; GET THE VALUE TO INVERT
  948.     NOT    AL            ; INVERT IT
  949.     MOV    ES:[DI],AL    ; REPLACE THE VALUE
  950.  
  951.     POP    ES
  952.     POP    DS
  953.     POP    BP
  954.     RET
  955. BALL    ENDP
  956.  
  957.     ENDPS
  958.     END
  959.