home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1989 / 05 / vuport.asc < prev   
Text File  |  1989-05-12  |  38KB  |  1,023 lines

  1. _Graphics Programming_
  2. by Kent Porter
  3.  
  4.  
  5.  
  6.  
  7. [LISTING ONE]
  8.  
  9.    1| ; DRAWPT.ASM: Writes pixel directly to 6845 Video Controller
  10.    2| ; Microsoft MASM 5.1
  11.    3| ; C prototype is 
  12.    4| ;      void far draw_point (int x, int y);
  13.    5| ; To be included in GRAFIX.LIB
  14.    6| ; K. Porter, «MDUL»DDJ«MDNM» Graphics Programming Column, February '89
  15.    7| 
  16.    8| .MODEL  LARGE
  17.    9| .CODE
  18.   10|         PUBLIC  _draw_point
  19.   11| 
  20.   12| ; Externals in GRAFIX.LIB
  21.   13|         EXTRN   _color1 : BYTE          ; Pixel color reg value
  22.   14|         EXTRN   _vuport : WORD          ; far ptr to vuport structure
  23.   15| 
  24.   16| ; Arguments passed from C
  25.   17| x       EQU     [bp+6]                  ; Arguments passed from C
  26.   18| y       EQU     [bp+8]
  27.   19| 
  28.   20| _draw_point     PROC FAR
  29.   21|         push    bp                      ; Entry processing
  30.   22|         mov     bp, sp
  31.   23| 
  32.   24| ; Point ES:[BX] to vuport structure
  33.   25|         mov     ax, _vuport+2           ; get pointer segment
  34.   26|         mov     es, ax
  35.   27|         mov     bx, _vuport             ; get offset
  36.   28| 
  37.   29| ; Clip if coordinates outside viewport
  38.   30|         mov     cx, y                   ; get y
  39.   31|         cmp     cx, es:[bx+6]           ; is y within viewport?
  40.   32|         jl      checkx                  ; ok if so
  41.   33|         jmp     exit                    ; else quit
  42.   34| checkx: mov     ax, x                   ; get x
  43.   35|         cmp     ax, es:[bx+4]           ; is x within viewport?
  44.   36|         jl      remap                   ; ok if so
  45.   37|         jmp     exit                    ; else quit
  46.   38| 
  47.   39| ; Map pixel coordinates to current viewport
  48.   40| remap:  add     ax, es:[bx]             ; offset x by vuport.left
  49.   41|         mov     x, ax                   ; save remapped X
  50.   42|         add     cx, es:[bx+2]           ; offset y by vuport.top
  51.   43|         mov     y, cx                   ; save remapped Y
  52.   44| 
  53.   45| ; Point ES to video memory segment        
  54.   46| vmem:   mov     ax, 0A000h
  55.   47|         mov     es, ax
  56.   48| 
  57.   49| ; Row offset = y * 80;
  58.   50|         mov     bx, y                   ; Get y argument
  59.   51|         mov     ax, 80
  60.   52|         mul     bx                      ; Result in AX
  61.   53|         mov     bx, ax                  ; Row offset in BX
  62.   54| 
  63.   55| ; Column offset = x SHR 3
  64.   56|         mov     ax, x                   ; Get x
  65.   57|         mov     cl, 3                   ; Shift operand
  66.   58|         shr     ax, cl                  ; Column offset
  67.   59| 
  68.   60| ; Complete address of pixel byte
  69.   61|         add     bx, ax                  ; ES:BX = address
  70.   62| 
  71.   63| ; Build bit mask for pixel 
  72.   64|         mov     cx, x                   ; Get x again
  73.   65|         and     cx, 7                   ; Isolate low-order bits
  74.   66|         xor     cl, 7                   ; Number of bits to shift
  75.   67|         mov     ah, 1                   ; Start bit mask
  76.   68|         shl     ah, cl                  ; Shift for pixel
  77.   69|         mov     cl, ah                  ; Save it
  78.   70| 
  79.   71| ; Use write mode 2 (single-pixel update)
  80.   72|         mov     dx, 03CEh               ; 6845 command register
  81.   73|         mov     al, 5                   ; Specify mode register
  82.   74|         mov     ah, 2                   ; Read mode 0, write mode 2
  83.   75|         out     dx, ax                  ; Send
  84.   76|         ; Following added May '89
  85.   77|         mov     al, 3                   ; Specify function select reg
  86.   78|         xor     ah, ah                  ; Replace-pixel mode
  87.   79|         out     dx, ax                  ; Send
  88.   80| 
  89.   81| ; Set 6845 bit mask register
  90.   82|         mov     al, 8                   ; Specify bit mask register
  91.   83|         mov     ah, cl                  ; al = mask
  92.   84|         out     dx, ax                  ; Send bit mask        
  93.   85| 
  94.   86| ; Draw the pixel
  95.   87|         mov     al, es:[bx]             ; Load 6845 latch registers
  96.   88|         xor     al, al                  ; Clear
  97.   89|         mov     byte ptr es:[bx], al    ; Zero the pixel for replace
  98.   90|         mov     al, _color1             ; Get the pixel value
  99.   91|         mov     es:[bx], al             ; Write the pixel
  100.   92| 
  101.   93| ; Restore video controller to default state
  102.   94|         mov     dx, 03CEh
  103.   95|         mov     ax, 0005h               ; write mode 0, read mode 0
  104.   96|         out     dx, ax
  105.   97|         mov     ax, 0FF08h              ; default bit mask
  106.   98|         out     dx, ax
  107.   99|         mov     ax, 0003h               ; default function select
  108.  100|         out     dx, ax
  109.  101|         xor     ax, ax                  ; zero Set/Reset
  110.  102|         out     dx, ax
  111.  103|         mov     ax, 0001h               ; zero Enable Set/Reset
  112.  104|         out     dx, ax
  113.  105|         mov     dx, 03C4h               ; 6845 address reg
  114.  106|         mov     ax, 0F02h               ; Data reg, enable all planes
  115.  107|         out     dx, ax
  116.  108| 
  117.  109| exit:
  118.  110|         mov     sp, bp
  119.  111|         pop     bp
  120.  112|         retf
  121.  113| _draw_point     ENDP
  122.  114|                 END
  123.  
  124.  
  125.  
  126.  
  127. [LISTING TWO]
  128.  
  129.    1| ; HLINE.ASM: Fast horizontal line drawing routine
  130.    2| ; Uses 6845 Write Mode 0 to update 8 pixels at a time on EGA/VGA
  131.    3| ; C prototype is
  132.    4| ;     void far hline (int x, int y, int length_in_pixels);
  133.    5| ; Writes in current color1 from GRAFIX.LIB
  134.    6| ; Microsoft MASM 5.1
  135.    7| ; K. Porter, «MDUL»DDJ«MDNM» Graphics Programming Column, March 89
  136.    8| 
  137.    9| .MODEL  LARGE
  138.   10| .CODE
  139.   11|         PUBLIC  _hline
  140.   12|         EXTRN   _color1 : BYTE          ; Current palette reg for pixel
  141.   13|         EXTRN   _draw_point : PROC      ; Pixel writing routine
  142.   14|         EXTRN   _vuport : WORD          ; far ptr to vuport structure
  143.   15| 
  144.   16| ; Declare arguments passed by caller
  145.   17|         x       EQU     [bp+6]
  146.   18|         y       EQU     [bp+8]
  147.   19|         len     EQU     [bp+10]
  148.   20| 
  149.   21| ; Declare auto variables
  150.   22|         last    EQU     [bp- 2]         ; Last byte to write
  151.   23|         solbits EQU     [bp- 4]         ; Mask for start of line
  152.   24|         oddsol  EQU     [bp- 6]         ; # odd bits at start of line
  153.   25|         eolbits EQU     [bp- 8]         ; Mask for end of line
  154.   26|         oddeol  EQU     [bp-10]         ; # odd bits at end of line
  155.   27| ; ----------------------------
  156.   28| 
  157.   29| _hline          PROC FAR                ; ENTRY POINT TO PROC
  158.   30|         push    bp                      ; entry processing
  159.   31|         mov     bp, sp
  160.   32|         sub     sp, 10                  ; make room for auto variables
  161.   33|         xor     ax, ax                  ; initialize auto variables
  162.   34|         mov     last, ax
  163.   35|         mov     solbits, ax
  164.   36|         mov     oddsol, ax
  165.   37|         mov     eolbits, ax
  166.   38|         mov     oddeol, ax
  167.   39| 
  168.   40| ; Do nothing if line length is zero
  169.   41|         mov     bx, len                 ; get line length
  170.   42|         cmp     bx, 0                   ; length = 0?
  171.   43|         jnz     chlen                   ; if not, go on
  172.   44|         jmp     quit                    ; else nothing to draw
  173.   45| 
  174.   46| ; Call draw_point() with a loop if line length < 8
  175.   47| chlen:  cmp     bx, 8
  176.   48|         jnb     getvp                   ; go if len >= 8
  177.   49|         mov     ax, y                   ; get args
  178.   50|         mov     cx, x
  179.   51| drpt:   push    bx                      ; push remaining length
  180.   52|         push    ax                      ; push args to draw_point()
  181.   53|         push    cx
  182.   54|         call    _draw_point             ; draw next pixel
  183.   55|         pop     cx                      ; clear args from stack
  184.   56|         pop     ax
  185.   57|         pop     bx                      ; fetch remaining length
  186.   58|         inc     cx                      ; next x
  187.   59|         dec     bx                      ; count pixel drawn
  188.   60|         jnz     drpt                    ; loop until thru
  189.   61|         jmp     quit                    ; then exit
  190.   62| 
  191.   63| ; Point ES:[BX] to vuport structure
  192.   64| getvp:  mov     ax, _vuport+2           ; get pointer segment
  193.   65|         mov     es, ax
  194.   66|         mov     bx, _vuport             ; get offset
  195.   67| 
  196.   68| ; Clip if starting coordinates outside viewport
  197.   69|         mov     cx, y                   ; get y
  198.   70|         cmp     cx, es:[bx+6]           ; is y within viewport?
  199.   71|         jl      checkx                  ; ok if so
  200.   72|         jmp     quit                    ; else quit
  201.   73| checkx: mov     ax, x                   ; get x
  202.   74|         cmp     ax, es:[bx+4]           ; is x within viewport?
  203.   75|         jl      remap                   ; ok if so
  204.   76|         jmp     quit                    ; else quit
  205.   77| 
  206.   78| ; Map starting coordinates to current viewport
  207.   79| remap:  add     ax, es:[bx]             ; offset x by vuport.left
  208.   80|         mov     x, ax                   ; save remapped X
  209.   81|         add     cx, es:[bx+2]           ; offset y by vuport.top
  210.   82|         mov     y, cx                   ; save remapped Y
  211.   83| 
  212.   84| ; Clip line length to viewport width
  213.   85|         mov     ax, es:[bx+4]           ; get vuport.width
  214.   86|         sub     ax, x                   ; maxlength = width - starting x
  215.   87|         add     ax, es:[bx]             ;     + vuport.left
  216.   88|         cmp     ax, len                 ; if maxlength > length
  217.   89|         jg      wm0                     ;   length is ok
  218.   90|         mov     len, ax                 ;   else length = maxlength
  219.   91| 
  220.   92| ; Set 6845 for write mode 0, all planes enabled, color selected
  221.   93| wm0:    mov     dx, 03CEh
  222.   94|         mov     ax, 0005h               ; Set write mode
  223.   95|         out     dx, ax
  224.   96|         mov     ax, 0FF00h              ; Set/Reset reg, enable all planes
  225.   97|         out     dx, ax
  226.   98|         mov     ax, 0FF01h              ; Enable set/reset reg, all planes
  227.   99|         out     dx, ax
  228.  100|         mov     dx, 03C4h               ; 6845 address reg
  229.  101|         mov     al, 2                   ; Data reg
  230.  102|         mov     ah, _color1             ; Palette reg planes enabled
  231.  103|         out     dx, ax                  ; Set color code
  232.  104|         ; Following added May '89
  233.  105|         mov     ah, 3                   ; Function select reg
  234.  106|         xor     al, al                  ; Pixel-replace mode
  235.  107|         out     dx, ax
  236.  108| 
  237.  109| ; Compute x coord for last byte to be written
  238.  110|         mov     bx, x                   ; get start of line
  239.  111|         add     bx, len                 ; end = start + length
  240.  112|         mov     cx, bx
  241.  113|         and     cx, 0FFF8h              ; x coordinate where odd bits
  242.  114|         mov     last, cx                ;   at end of line begin
  243.  115| 
  244.  116| ; Compute number of odd pixels at end of line
  245.  117|         sub     bx, cx
  246.  118|         mov     oddeol, bx              ; save it
  247.  119| 
  248.  120| ; Construct pixel mask for last byte of line
  249.  121|         cmp     bx, 0   
  250.  122|         jz      bsol                    ; go if no odd pixels
  251.  123|         xor     ax, ax
  252.  124| eolb:   shr     ax, 1                   ; shift right and 
  253.  125|         or      ax, 80h                 ;   set H/O bit
  254.  126|         dec     bl                      ;   until mask is built
  255.  127|         jnz     eolb
  256.  128|         mov     eolbits, ax             ; then save mask
  257.  129| 
  258.  130| ; Compute number of odd pixels at start of line
  259.  131| bsol:   mov     cx, x                   ; get starting X again
  260.  132|         and     cx, 7                   ; # of pixels from start of byte
  261.  133|         jz      saddr                   ; go if none
  262.  134|         mov     bx, 8
  263.  135|         sub     bx, cx                  ; # of pixels to write
  264.  136|         mov     oddsol, bx              ; save
  265.  137| 
  266.  138| ; Construct pixel mask for first byte of line
  267.  139|         xor     ax, ax
  268.  140| solb:   shl     ax, 1                   ; shift left and
  269.  141|         or      ax, 1                   ;   set L/O bit 
  270.  142|         dec     bl                      ;   until mask is built
  271.  143|         jnz     solb
  272.  144|         mov     solbits, ax             ; then save mask
  273.  145| 
  274.  146| ; Translate last byte X into an address
  275.  147| saddr:  mov     ax, 0A000h              
  276.  148|         mov     es, ax                  ; ES ==> video buffer
  277.  149|         mov     bx, y                   ; get row
  278.  150|         mov     ax, 80
  279.  151|         mul     bx
  280.  152|         mov     bx, ax                  ; BX = row offset = row * 80
  281.  153|         push    bx                      ; save row offset
  282.  154|         mov     ax, last                ; get last byte X
  283.  155|         mov     cl, 3
  284.  156|         shr     ax, cl                  ; shift for col offset
  285.  157|         add     bx, ax                  ; last offs = row offs + col offs
  286.  158|         mov     last, bx
  287.  159| 
  288.  160| ; Compute address of first byte (ES:[BX])
  289.  161|         pop     bx                      ; fetch row offset
  290.  162|         mov     ax, x                   ; get col offset
  291.  163|         mov     cl, 3
  292.  164|         shr     ax, cl                  ; shift right 3 for col offset
  293.  165|         add     bx, ax                  ; offset = row offs + col offs
  294.  166|         cmp     bx, last                ; is first byte also last?
  295.  167|         jz      weol                    ; skip to end mask if so
  296.  168| 
  297.  169| ; Write start of line
  298.  170|         mov     dx, 03CEh               ; 6845 port
  299.  171|         mov     ah, solbits             ; start-of-line mask
  300.  172|         cmp     ah, 0
  301.  173|         jz      w8                      ; go if empty mask
  302.  174|         mov     al, 8                   ; set bit mask reg
  303.  175|         out     dx, ax
  304.  176|         mov     cl, es:[bx]             ; load 6845 latches
  305.  177|         mov     ax, solbits
  306.  178|         neg     al                      ; complement
  307.  179|         dec     al                      ;   for reversed bit mask
  308.  180|         and     al, cl                  ; filter previously unset pixels
  309.  181|         mov     es:[bx], al             ; clear affected bits
  310.  182|         mov     al, _color1
  311.  183|         mov     es:[bx], al             ; set affected bits
  312.  184|         inc     bx                      ; next byte
  313.  185|         cmp     bx, last                ; ready for end of line yet?
  314.  186|         jae     weol                    ; go if so
  315.  187| 
  316.  188| ; Write 8 pixels at a time until last byte in line
  317.  189| w8:     mov     ax, 0FF08h              ; update all pixels in byte
  318.  190|         out     dx, ax                  ; set bit mask reg
  319.  191|         mov     al, es:[bx]             ; load 6845 latches
  320.  192|         xor     al, al
  321.  193|         mov     es:[bx], al             ; clear all pixels
  322.  194|         mov     al, _color1
  323.  195|         mov     es:[bx], al             ; set all bits
  324.  196|         inc     bx                      ; next byte
  325.  197|         cmp     bx, last                ; thru?
  326.  198|         jnz     w8                      ; loop if not           
  327.  199| 
  328.  200| ; Write end of line
  329.  201| weol:   mov     dx, 03CEh               ; 6845 port
  330.  202|         mov     ah, eolbits             ; end-of-line mask
  331.  203|         cmp     ah, 0
  332.  204|         jz      rvc                     ; go if empty mask
  333.  205|         mov     al, 8                   ; set bit mask reg
  334.  206|         out     dx, ax
  335.  207|         mov     cl, es:[bx]             ; load 6845 latches
  336.  208|         mov     ax, eolbits
  337.  209|         neg     al                      ; complement
  338.  210|         dec     al                      ;   for reversed bit mask
  339.  211|         and     al, cl                  ; filter previously unset pixels
  340.  212|         mov     es:[bx], al             ; clear affected bits
  341.  213|         mov     al, _color1
  342.  214|         mov     es:[bx], al             ; set affected bits
  343.  215| 
  344.  216| ; Restore video controller to default state
  345.  217| rvc:    mov     dx, 03CEh
  346.  218|         mov     ax, 0005h               ; write mode 0, read mode 0
  347.  219|         out     dx, ax
  348.  220|         mov     ax, 0FF08h              ; default bit mask
  349.  221|         out     dx, ax
  350.  222|         mov     ax, 0003h               ; default function select
  351.  223|         out     dx, ax
  352.  224|         xor     ax, ax                  ; zero Set/Reset
  353.  225|         out     dx, ax
  354.  226|         mov     ax, 0001h               ; zero Enable Set/Reset
  355.  227|         out     dx, ax
  356.  228|         mov     dx, 03C4h               ; 6845 address reg
  357.  229|         mov     ax, 0F02h               ; Data reg, enable all planes
  358.  230|         out     dx, ax
  359.  231| 
  360.  232| ; End of routine
  361.  233| quit:   mov     sp, bp
  362.  234|         pop     bp
  363.  235|         retf
  364.  236| _hline  ENDP
  365.  237|         END
  366.  238|         
  367.  239| 
  368.  
  369.  
  370.  
  371.  
  372. [LISTING THREE]
  373.  
  374.  
  375. /* From May, '89 */
  376. /* ------------- */
  377. typedef int VP_HAN;                         /* viewport handle type */
  378.  
  379. void far default_viewport (int height);    /* init default viewport */
  380.  
  381. VP_HAN far vp_open (int x, int y, int width, int height);
  382.                                    /* open viewport, make it active */
  383.  
  384. int far vp_use (VP_HAN vp);                       /* make vp active */
  385.  
  386. void far vp_close (VP_HAN vp);                    /* close viewport */
  387.  
  388. void far vp_outline (VP_HAN vp);                      /* outline vp */
  389.  
  390. VP_HAN far vp_active (void);             /* get handle of active vp */
  391.  
  392. int far vp_width (void)                      /* get active vp width */
  393.  
  394. int far vp_height (void)                    /* get active vp height */
  395.  
  396.  
  397.  
  398.  
  399.  
  400. [LISTING FOUR]
  401.  
  402.  
  403. /* VUPORT.C: Library source for viewport support       */
  404. /* This is part of the GRAFIX library                  */
  405. /* K. Porter, «MDUL»DDJ«MDNM» Graphics Programming Column, May '89 */
  406.  
  407. #include <stdio.h>
  408. #include <stdlib.h>
  409. #include "grafix.h"
  410.  
  411. typedef struct vpnode {         /* viewport descriptor node */
  412.   int            left, top, width, height,
  413.                  handle;
  414.   struct vpnode  far *next, far *prev;
  415. } VPNODE;
  416.  
  417. #if !defined TRUE
  418. #define FALSE 0
  419. #define TRUE  !FALSE
  420. #endif
  421.  
  422. VPNODE far *vplist = NULL;    /* pointer to list of vpnodes */
  423. VPNODE def_vp = {0, 0, 640, 350, 0};    /* default viewport */
  424. VPNODE far *vuport = &def_vp;    /* ptr to current viewport */
  425. /* -------------------------- */
  426.  
  427. void far default_viewport (int height)
  428. {                            /* initialize default viewport */
  429.   vuport->height = height;
  430. } /* ------------------------ */
  431.  
  432. VP_HAN far vp_open (int x, int y, int width, int height)
  433. {                                        /* open a viewport */
  434. VPNODE far *newvp, far *listnode;
  435.  
  436.   newvp = malloc (sizeof *newvp);             /* make space */
  437.   newvp->next = newvp->prev = NULL;       /* init list ptrs */
  438.   newvp->left   = x;                      /* set descriptor */
  439.   newvp->top    = y;
  440.   newvp->width  = width;
  441.   newvp->height = height;
  442.   newvp->handle   = 1;
  443.   if (vplist == NULL)
  444.     vplist = newvp;                   /* set first viewport */
  445.   else {
  446.     listnode = vplist;              /* add viewport to list */
  447.     while (listnode->next != NULL)
  448.       listnode = listnode->next;               /* find tail */
  449.     listnode->next = newvp;              /* update pointers */
  450.     newvp->prev    = listnode;
  451.     newvp->handle  = listnode->handle + 1;    /* and handle */
  452.   }
  453.   vuport = newvp;               /* make new viewport active */
  454.   return newvp->handle;
  455. } /* ------------------------------------------------------ */
  456.  
  457. int far vp_use (VP_HAN vp)                /* make vp active */
  458. {
  459. VPNODE far *port;
  460. int success = FALSE;
  461.  
  462.   if (vp == 0) {              /* switch to default viewport */
  463.     vuport = &def_vp;
  464.     success = TRUE;
  465.   } else {                         /* find desired viewport */
  466.     port = vplist;
  467.     do {
  468.       if (port->handle == vp) {
  469.         success = TRUE;
  470.         break;               /* jump out of loop when found */
  471.       }
  472.       port = port->next;
  473.     } while (port != NULL);
  474.     if (success)
  475.       vuport = port;                         /* make active */
  476.   }
  477.   return success;
  478. } /* ------------------------------------------------------ */
  479.  
  480. void far vp_close (VP_HAN vp)           /* close a viewport */
  481. {
  482. VPNODE far *port;
  483.  
  484.   if (vp == 0) return;            /* can't close default vp */
  485.   port = vplist;
  486.   while (port->next != NULL) {     /* find desired viewport */
  487.     if (port->handle == vp)
  488.       break;
  489.     port = port->next;
  490.   }
  491.   if (port != NULL) {                 /* viewport was found */
  492.     if (port->next != NULL)          /* so remove from list */
  493.       port->next->prev = port->prev;
  494.     if (port->prev != NULL)
  495.       port->prev->next = port->next;
  496.     if (port == vplist)                 /* if removing head */
  497.       vplist = port->next;
  498.     if (port == vuport)            /* if removing active vp */
  499.       vuport = &def_vp;
  500.     free (port);
  501.   }
  502. } /* ------------------------------------------------------ */
  503.  
  504. void far vp_outline (VP_HAN vp)               /* outline vp */
  505.             /* outline is immediately outside viewport area */
  506. {
  507. VP_HAN  active;
  508. int     x, y, w, h;
  509.  
  510.   active = vp_active();            /* save current viewport */
  511.   if (vp_use (vp)) {
  512.     x = vuport->left-1;
  513.     y = vuport->top-1;
  514.     w = vuport->width+1;
  515.     h = vuport->height+1;
  516.  
  517.     /* draw outline */
  518.     vp_use (0);                              /* full screen */
  519.     draw_rect (x, y, w, h);
  520.     vp_use (active);             /* restore active viewport */
  521.   }
  522. } /* ------------------------------------------------------ */
  523.  
  524. VP_HAN far vp_active (void)      /* get handle of active vp */
  525. {
  526.   return vuport->handle;
  527. } /* ------------------------------------------------------ */
  528.  
  529. int far vp_width (void)              /* get active vp width */
  530. {
  531.   return vuport->width;
  532. } /* ------------------------------------------------------ */
  533.  
  534. int far vp_height (void)            /* get active vp height */
  535. {
  536.   return vuport->height;
  537. } /* ------------------------------------------------------ */
  538.  
  539.  
  540.  
  541.  
  542. [LISTING FIVE]
  543.  
  544.  
  545. /* VP.C: Draws several viewports */
  546. /* Hex star inside each */
  547. /* K. Porter, «MDUL»DDJ«MDNM» Graphics Programming Col, 5/89 */
  548.  
  549. #include "grafix.h"
  550. #include <conio.h>
  551.  
  552. int hex1[] = {25,55, 110,20, 110,90,  25,55};
  553. int hex2[] = {55,20, 135,55,  55,90,  55,20};
  554.  
  555. void main()
  556. {
  557. VP_HAN  vp1, vp2, vp3;
  558.  
  559.   if (init_video (EGA)) {
  560.  
  561.     /* Draw star in default viewport */
  562.     set_color1 (5);       /* magenta */
  563.     polyline (3, hex1);
  564.     polyline (3, hex2);
  565.     set_color1 (9);
  566.  
  567.     /* Draw star in unbordered viewport */
  568.     set_color1 (1);             /* blue */
  569.     vp1 = vp_open (60, 250, 200, 95);
  570.     polyline (3, hex1);
  571.     polyline (3, hex2);
  572.  
  573.     /* Draw star in small bordered viewport */
  574.     vp2 = vp_open (200, 150, 100, 75);
  575.     vp_outline (vp2);
  576.     set_color1 (15);               /* white */
  577.     polyline (3, hex1);
  578.     polyline (3, hex2);
  579.  
  580.     /* Draw star in filled bordered viewport */
  581.     vp3 = vp_open (400, 60, 140, 100);
  582.     vp_outline (vp3);
  583.     set_color1 (2);                 /* green */
  584.     fill_rect (0, 0, vp_width(), vp_height());
  585.     set_color1 (4);                   /* red */
  586.     polyline (3, hex1);
  587.     polyline (3, hex2);
  588.  
  589.     /* Wait for keypress, then close vp's and quit */
  590.     getch();
  591.     vp_close (vp1);
  592.     vp_close (vp2);
  593.     vp_close (vp3);
  594.   }
  595. }
  596.  
  597.  
  598.  
  599. [LISTING SIX]
  600.  
  601. /* LINEGRAF.C: Self-scaling viewports showing a line graph */
  602. /* K. Porter, «MDUL»DDJ«MDNM» Graphics Programming Column, May '89     */
  603.  
  604. #include "grafix.h"
  605. #include <conio.h>
  606.  
  607. int data [] = {30, 70, 10, 40, 30, 80, 60, 90, 40, 50, 40};
  608.  
  609. void main ()
  610. {
  611. void graph (void);
  612. VP_HAN vp1, vp2, vp3;
  613.  
  614.   if (init_video (EGA)) {
  615.  
  616.     /* Open three viewports */
  617.     vp1 = vp_open (  1,   1, 360, 150);
  618.     vp2 = vp_open (  1, 170, 638, 170);
  619.     vp3 = vp_open (500,  50,  80,  50);
  620.  
  621.     /* First version upper left quadrant */
  622.     vp_use (vp1);
  623.     set_color1 (14);  /* yellow */
  624.     vp_outline (vp1);
  625.     graph();
  626.     getch();          /* wait for keypress */
  627.     vp_close (vp1);
  628.  
  629.     /* Second across bottom */
  630.     vp_use (vp2);
  631.     set_color1 (2);   /* green */
  632.     vp_outline (vp2);
  633.     graph();
  634.     getch();          /* wait for keypress */
  635.     vp_close (vp2);
  636.  
  637.     /* Third at upper right */
  638.     vp_use (vp3);
  639.     set_color1 (3);   /* cyan */
  640.     vp_outline (vp3);
  641.     graph();
  642.     getch();          /* wait for keypress */
  643.     vp_close (vp3);
  644.   }
  645. } /* ------------------------ */
  646.  
  647. void graph (void)   /* draw self-scaling line graph */
  648. {
  649. int    npts, p, prevx, prevy, curx, cury;
  650. double vint, hint;
  651.  
  652.   npts = sizeof (data) / sizeof (int);  /* # data points */
  653.  
  654.   /* Scaling factors for data points */
  655.   hint = (double) vp_width() / (npts - 1); /* horizontal */
  656.   vint = (double) vp_height() / 100.0;       /* vertical */
  657.  
  658.   /* Draw the graph */
  659.   prevx = 0; prevy = vp_height() - (int)(data[0] * vint);
  660.   for (p = 1; p < npts; p++) {
  661.     curx = (int)(p * hint);
  662.     cury = vp_height() - (int)(data[p] * vint);
  663.     draw_line (prevx, prevy, curx, cury);
  664.     prevx = curx; prevy = cury;
  665.   }
  666. }
  667.  
  668.  
  669. [GRAFIX.C, NOT A NUMBER LISTING IN DDJ 5/89]
  670.  
  671. /* Library source file GRAFIX.C               */
  672. /* EGA/VGA graphics subsystem                 */
  673. /* Following library routines are external:   */
  674. /*     DRAWPT.ASM       Feb '89               */
  675. /*     HLINE.ASM        Mar '89               */
  676. /*     EGAPALET.C       Apr '89               */
  677. /*     PIXEL.ASM        May '89               */
  678. /*     VUPORT.C         May '89               */
  679. /* K. Porter, DDJ Graphics Programming Column */
  680. /* ------------------------------------------ */
  681.  
  682. #include <dos.h>
  683. #include <stdlib.h>
  684. #include <string.h>
  685. #include <stdio.h>
  686. #include "grafix.h"
  687.  
  688. #if !defined TRUE
  689. #define FALSE 0
  690. #define TRUE  !FALSE
  691. #endif
  692.  
  693. /* Variables global to this library */
  694. int  color1,                            /* foreground color */
  695.      oldmode = 0,                      /* pre-graphics mode */
  696.      grafixmode = 0,               /* default graphics mode */
  697.      ega = FALSE,                     /* equipment Booleans */
  698.      vga = FALSE,
  699.      colormonitor = FALSE,
  700.      curpos,                        /* text cursor position */
  701.      textpage;                          /* active text page */
  702. unsigned vidmem;                    /* video buffer segment */
  703. char far *vidsave;                /* video buffer save area */
  704. /* -------------------------------------------------------- */
  705.  
  706. int far init_video (int mode)
  707.  
  708. /* Initializes video adapter and defaults for mode          */
  709. /* Sets up pc_textmode() to be called on pgm termination    */
  710. /* Returns TRUE or FALSE indicating success                 */
  711. /* This function will be expanded in a later version        */
  712. {
  713. union REGS r;
  714. int result = FALSE;
  715.  
  716.   /* Determine attached adapter and monitor */
  717.   r.h.ah = 0x1A;                    /* VGA inquiry function */
  718.   r.h.al = 0;
  719.   int86 (0x10, &r, &r);                    /* ROM BIOS call */
  720.   if (r.h.al == 0x1A)
  721.     switch (r.h.bl) {
  722.       case 4 : ega = TRUE;                     /* EGA color */
  723.                colormonitor = TRUE;
  724.                break;
  725.       case 5 : ega = TRUE;                      /* EGA mono */
  726.                break;
  727.       case 7 : ega = TRUE;                      /* VGA mono */
  728.                vga = TRUE;
  729.                break;
  730.       case 8 : ega = TRUE;                     /* VGA color */
  731.                vga = TRUE;
  732.                colormonitor = TRUE;
  733.     }
  734.   else {                        /* No VGA, so check for EGA */
  735.     r.h.ah = 0x12;
  736.     r.x.bx = 0x10;
  737.     int86 (0x10, &r, &r);
  738.     if (r.x.bx != 0x10) {              /* if EGA present... */
  739.       ega = TRUE;                               /* set flag */
  740.       r.h.ah = 0x12;
  741.       r.h.bl = 0x10;              /* find out which monitor */
  742.       int86 (0x10, &r, &r);
  743.       if (r.h.bl != 0)
  744.         colormonitor = TRUE;                   /* EGA color */
  745.     }
  746.   }
  747.  
  748.   /* Proceed only if EGA or VGA present */
  749.   if (ega | vga) {
  750.     set_color1 (15);                 /* default pixel color */
  751.     r.h.ah = 0x0F;               /* get current screen mode */
  752.     int86 (0x10, &r, &r);
  753.     oldmode = r.h.al;                           /* store it */
  754.     textpage = r.h.bh;             /* also active text page */
  755.  
  756.     if (colormonitor)              /* point to video memory */
  757.       vidmem = 0xB800;
  758.     else
  759.       vidmem = 0xB000;
  760.     vidsave = malloc (4096);          /* allocate save area */
  761.     movedata                   /* save text screen contents */
  762.         (vidmem, 0, FP_SEG (vidsave), FP_OFF (vidsave), 4096);
  763.  
  764.     r.h.ah = 3;                 /* get text cursor position */
  765.     r.h.bh = textpage;
  766.     int86 (0x10, &r, &r);
  767.     curpos = r.x.dx;                         /* and save it */
  768.  
  769.     if ((mode == EGA) && ega) {
  770.       r.h.ah = 0;
  771.       r.h.al = mode;                        /* set EGA mode */
  772.       int86 (0x10, &r, &r);
  773.       grafixmode = mode;                       /* save mode */
  774.       atexit (pc_textmode);       /* register exit function */
  775.       result = TRUE;
  776.     } else
  777.       if ((mode == VGA16) && vga) {      /* typo fixed 5/89 */
  778.         r.h.ah = 0;
  779.         r.h.al = mode;
  780.         int86 (0x10, &r, &r);
  781.         grafixmode = mode;
  782.         atexit (pc_textmode);
  783.         result = TRUE;
  784.       }
  785.   }
  786.   if (!result) {            /* unable to switch to graphics */
  787.     oldmode = 0;              /* so cancel text screen save */
  788.     free (vidsave);
  789.     vidsave = 0;
  790.   }
  791.   if (mode == VGA16 && vga)  /* viewport init added May '89 */
  792.     default_viewport (480);
  793.   return result;
  794. } /* ------------------------------------------------------ */
  795.  
  796. void far pc_textmode (void)
  797. /* SPECIFIC TO MS-DOS */
  798. /* Restore text mode */
  799. /* Automatically called on pgm termination */
  800. {
  801. union REGS r;
  802.  
  803.   if (oldmode) {              /* if not in text mode now... */
  804.     r.h.ah = 0;
  805.     r.h.al = oldmode;                  /* restore text mode */
  806.     int86 (0x10, &r, &r);
  807.     movedata                         /* restore text screen */
  808.         (FP_SEG (vidsave), FP_OFF (vidsave), vidmem, 0, 4096);
  809.     free (vidsave);                /* free allocated memory */
  810.     vidsave = 0;                            /* zero pointer */
  811.     oldmode = 0;                                   /* reset */
  812.     r.h.ah = 2;              /* restore old cursor position */
  813.     r.h.bh = textpage;
  814.     r.x.dx = curpos;
  815.     int86 (0x10, &r, &r);
  816.   }
  817. } /* ------------------------------------------------------ */
  818.  
  819. void far set_color1 (int palette_reg)
  820. /* Select pixel color from palette register */
  821. {
  822.   color1 = palette_reg;
  823. } /* ------------------------------------------------------ */
  824.  
  825. void far draw_line (int x1, int y1, int x2, int y2)
  826.                         /* Bresenham line drawing algorithm */
  827.                         /* x1, y1 and x2, y2 are end points */
  828. {
  829. int  w, h, d, dxd, dyd, dxn, dyn, dinc, ndinc, p;
  830. register x, y;
  831.  
  832.   /* Set up */
  833.   x = x1; y = y1;                          /* start of line */
  834.   w = x2 - x1;                      /* width domain of line */
  835.   h = y2 - y1;                     /* height domain of line */
  836.  
  837.   /* Determine drawing direction */
  838.   if (w < 0) {                     /* drawing right to left */
  839.     w = -w;                               /* absolute width */
  840.     dxd = -1;                    /* x increment is negative */
  841.   } else                           /* drawing left to right */
  842.     dxd = 1;                       /* so x incr is positive */
  843.   if (h < 0) {                     /* drawing bottom to top */
  844.     h = -h;                       /* so get absolute height */
  845.     dyd = -1;                         /* y incr is negative */
  846.   } else                           /* drawing top to bottom */
  847.     dyd = 1;                       /* so y incr is positive */
  848.  
  849.   /* Determine major axis of motion */
  850.   if (w < h) {                           /* major axis is Y */
  851.     p = h, h = w, w = p;       /* exchange height and width */
  852.     dxn = 0;
  853.     dyn = dyd;
  854.   } else {                               /* major axis is X */
  855.     dxn = dxd;
  856.     dyn = 0;
  857.   }
  858.  
  859.   /* Set control variables */
  860.   ndinc = h * 2;                  /* Non-diagonal increment */
  861.   d = ndinc - w;                /* pixel selection variable */
  862.   dinc = d - w;                       /* Diagonal increment */
  863.   
  864.   /* Loop to draw the line */
  865.   for (p = 0; p <= w; p++) {
  866.     draw_point (x, y);
  867.     if (d < 0) {                     /* step non-diagonally */
  868.       x += dxn;
  869.       y += dyn;
  870.       d += ndinc;
  871.     } else {                             /* step diagonally */
  872.       x += dxd;
  873.       y += dyd;
  874.       d += dinc;
  875.     }
  876.   }
  877. } /* ------------------------------------------------------ */
  878.  
  879. void far draw_rect (int xleft, int ytop, int w, int h)
  880. /* Draw outline rectangle in color1 from top left corner */
  881. /* w and h are width and height */
  882. /* xleft and ytop are top left corner */
  883. {
  884.   draw_line (xleft, ytop, xleft+w, ytop);            /* top */
  885.   draw_line (xleft+w, ytop, xleft+w, ytop+h);      /* right */
  886.   draw_line (xleft+w, ytop+h, xleft, ytop+h);     /* bottom */
  887.   draw_line (xleft, ytop+h, xleft, ytop);           /* left */
  888. } /* ------------------------------------------------------ */
  889.  
  890. void far polyline (int edges, int vertex[])  
  891. /* Draw multipoint line of n edges from n+1 vertices where: */
  892. /*        vertex [0] = x0    vertex [1] = y0                */
  893. /*        vertex [2] = x1    vertex [3] = y1                */
  894. /*          etc.                                            */
  895. {
  896. int x1, y1, x2, y2, v;
  897.  
  898.   x1 = vertex[0];
  899.   y1 = vertex[1];
  900.   for (v = 2; v < (edges+1)*2; v+= 2) {
  901.     x2 = vertex[v];
  902.     y2 = vertex[v+1];
  903.     draw_line (x1, y1, x2, y2);
  904.     x1 = x2;
  905.     y1 = y2;
  906.   }
  907. } /* ------------------------------------------------------ */
  908.  
  909. void far fill_rect (int xleft, int ytop, int w, int h)
  910. /* Draw solid rectangle in color1 from top left corner */
  911. {
  912. register y;
  913.  
  914.   for (y = ytop; y < ytop+h; y++)
  915.     hline (xleft, y, w);
  916. } /* ------------------------------------------------------ */
  917.  
  918.  
  919. [GRAPHIX.H, NOT A NUMBERED LISTING IN DDJ, 5/89]
  920.  
  921.  
  922. /* Include file for GRAFIX.LIB                */
  923. /* EGA/VGA graphics subsystem                 */
  924. /* K. Porter, DDJ Graphics Programming Column */
  925. /* ------------------------------------------ */
  926.  
  927. /* Color constants from April, 89 */
  928. #define Black     0        /* standard colors */
  929. #define Blue      1
  930. #define Green     2
  931. #define Cyan      3
  932. #define Red       4
  933. #define Magenta   5
  934. #define Brown     0x14
  935. #define LtGray    7
  936. #define DkGray    0x38
  937. #define LtBlue    0x39
  938. #define LtGreen   0x3A
  939. #define LtCyan    0x3B
  940. #define LtRed     0x3C
  941. #define LtMagenta 0x3D
  942. #define Yellow    0x3E
  943. #define White     0x3F
  944.  
  945. #define RED0      0x00  /* basic hues for mixing */
  946. #define RED1      0x20
  947. #define RED2      0x04
  948. #define RED3      0x24
  949. #define GRN0      0x00
  950. #define GRN1      0x10
  951. #define GRN2      0x02
  952. #define GRN3      0x12
  953. #define BLU0      0x00
  954. #define BLU1      0x08
  955. #define BLU2      0x01
  956. #define BLU3      0x09
  957.  
  958. #if !defined byte
  959. #define byte unsigned char
  960. #endif
  961.  
  962. /* Supported video modes */
  963. #define  EGA       0x10              /* EGA 640 x 350, 16/64 colors */
  964. #define  VGA16     0x11              /* VGA 640 x 480, 16/64 colors */
  965.  
  966. /* Function prototypes */
  967. /* From February, '89 */
  968. /* ------------------ */
  969. int far init_video (int mode);        /* init display in video mode */
  970.  
  971. void far pc_textmode (void);                        /* PC text mode */
  972.  
  973. void far draw_point (int x, int y);        /* write pixel in color1 */
  974.  
  975. void far set_color1 (int palette_reg);      /* set foreground color */
  976.  
  977. /* From March, '89 */
  978. /* --------------- */
  979. void far draw_line (int x1, int y1, int x2, int y2);
  980.                                 /* Bresenham line drawing algorithm */
  981.  
  982. void far draw_rect (int left, int top, int width, int height);
  983.                              /* draw rectangle from top left corner */
  984.  
  985. void far polyline (int edges, int vertices[]);     /* draw polyline */
  986.  
  987. void far hline (int x, int y, int len);          /* horizontal line */
  988.  
  989. void far fill_rect (int left, int top, int width, int height);
  990.       /* draw solid rectangle in color1 starting at top left corner */
  991.  
  992. /* From April, '89 */
  993. /* --------------- */
  994. byte far ega_palreg (int preg);         /* color in EGA palette reg */
  995.  
  996. void far set_ega_palreg (int reg, int color);    /* set palette reg */
  997.  
  998. byte far colorblend (byte r, byte g, byte b);         /* blend hues */
  999.  
  1000. void far get_ega_colormix (int preg, int *r, int *g, int *b);
  1001.         /* get mix of red, green, and blue in EGA pal register preg */
  1002.  
  1003. /* From May, '89 */
  1004. /* ------------- */
  1005. typedef int VP_HAN;                         /* viewport handle type */
  1006.  
  1007. void far default_viewport (int height);    /* init default viewport */
  1008.  
  1009. VP_HAN far vp_open (int x, int y, int width, int height);
  1010.                                    /* open viewport, make it active */
  1011.  
  1012. int far vp_use (VP_HAN vp);                       /* make vp active */
  1013.  
  1014. void far vp_close (VP_HAN vp);                    /* close viewport */
  1015.  
  1016. VP_HAN far vp_active (void);             /* get handle of active vp */
  1017.  
  1018. void far vp_outline (VP_HAN vp);                      /* outline vp */
  1019.  
  1020. int far vp_width (void);               /* get active viewport width */
  1021.  
  1022. int far vp_height (void);                             /* and height */
  1023.