home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1989 / 02 / porter.asc < prev    next >
Text File  |  1989-01-04  |  15KB  |  425 lines

  1. _Graphics Programming Column_
  2. by Kent Porter
  3.  
  4. [LISTING ONE]
  5.  
  6. ; DRAWPT.ASM: Writes pixel directly to 6845 Video Controller
  7. ; Microsoft MASM 5.1
  8. ; C prototype is 
  9. ;      void far draw_point (int x, int y);
  10. ; To be included in GRAFIX.LIB
  11. ; K. Porter, DDJ Graphics Programming Column, February '89
  12.  
  13. .MODEL  LARGE
  14. .CODE
  15.         PUBLIC  _draw_point
  16.         EXTRN   _color1 : BYTE          ; From GRAFIX.LIB
  17. x       EQU     [bp+6]                  ; Arguments passed from C
  18. y       EQU     [bp+8]
  19.  
  20. _draw_point     PROC FAR
  21.         push    bp                      ; Entry processing
  22.         mov     bp, sp
  23.  
  24. ; Point ES to video memory segment        
  25.         mov     ax, 0A000h
  26.         mov     es, ax
  27.  
  28. ; Row offset = y * 80;
  29.         mov     bx, y                   ; Get y argument
  30.         mov     ax, 80
  31.         mul     bx                      ; Result in AX
  32.         mov     bx, ax                  ; Row offset in BX
  33.  
  34. ; Column offset = x SHR 3
  35.         mov     ax, x                   ; Get x
  36.         mov     cl, 3                   ; Shift operand
  37.         shr     ax, cl                  ; Column offset
  38.  
  39. ; Complete address of pixel byte
  40.         add     bx, ax                  ; ES:BX = address
  41.  
  42. ; Build bit mask for pixel 
  43.         mov     cx, x                   ; Get x again
  44.         and     cx, 7                   ; Isolate low-order bits
  45.         xor     cl, 7                   ; Number of bits to shift
  46.         mov     ah, 1                   ; Start bit mask
  47.         shl     ah, cl                  ; Shift for pixel
  48.         mov     cl, ah                  ; Save it
  49.  
  50. ; Use write mode 2 (single-pixel update)
  51.         mov     dx, 03CEh               ; 6845 command register
  52.         mov     al, 5                   ; Specify mode register
  53.         mov     ah, 2                   ; Write mode 2
  54.         out     dx, ax                  ; Send
  55.  
  56. ; Set 6845 bit mask register
  57.         mov     al, 8                   ; Specify bit mask register
  58.         mov     ah, cl                  ; al = mask
  59.         out     dx, ax                  ; Send bit mask        
  60.  
  61. ; Draw the pixel
  62.         mov     al, es:[bx]             ; Load 6845 latch registers
  63.         xor     al, al                  ; Clear
  64.         mov     byte ptr es:[bx], al    ; Zero the pixel for replace
  65.         mov     al, _color1             ; Get the pixel value
  66.         mov     es:[bx], al             ; Write the pixel
  67.  
  68. ; Restore video controller to default state
  69.         mov     dx, 03CEh
  70.         mov     ax, 0005h               ; write mode 0, read mode 0
  71.         out     dx, ax
  72.         mov     ax, 0FF08h              ; default bit mask
  73.         out     dx, ax
  74.         mov     ax, 0003h               ; default function select
  75.         out     dx, ax
  76.         xor     ax, ax                  ; zero Set/Reset
  77.         out     dx, ax
  78.         mov     ax, 0001h               ; zero Enable Set/Reset
  79.         out     dx, ax
  80.         mov     dx, 03C4h               ; 6845 address reg
  81.         mov     ax, 0F02h               ; Data reg, enable all planes
  82.         out     dx, ax
  83.  
  84. ; Exit
  85.         mov     sp, bp
  86.         pop     bp
  87.         retf
  88. _draw_point     ENDP
  89.                 END
  90.  
  91. [LISTING TWO]
  92.  
  93.    1| /* Library source file GRAFIX.C               */
  94.    2| /* EGA/VGA graphics subsystem                 */
  95.    3| /* Following library routines are external:   */
  96.    4| /*     DRAWPT.ASM       Feb '89               */
  97.    5| /* K. Porter, DDJ Graphics Programming Column */
  98.    6| /* ------------------------------------------ */
  99.    7| 
  100.    8| #include <dos.h>
  101.    9| #include <stdlib.h>
  102.   10| #include <string.h>
  103.   11| #include <stdio.h>
  104.   12| #include "grafix.h"
  105.   13| 
  106.   14| #if !defined TRUE
  107.   15| #define FALSE 0
  108.   16| #define TRUE  !FALSE
  109.   17| #endif
  110.   18| 
  111.   19| /* Variables global to this library */
  112.   20| int  color1,                            /* foreground color */
  113.   21|      oldmode = 0,                      /* pre-graphics mode */
  114.   22|      grafixmode = 0,               /* default graphics mode */
  115.   23|      ega = FALSE,                     /* equipment Booleans */
  116.   24|      vga = FALSE,
  117.   25|      colormonitor = FALSE,
  118.   26|      curpos,                        /* text cursor position */
  119.   27|      textpage;                          /* active text page */
  120.   28| unsigned vidmem;                    /* video buffer segment */
  121.   29| char far *vidsave;                /* video buffer save area */
  122.   30| 
  123.   31| /* -------------------------------------------------------- */
  124.   32| 
  125.   33| int far init_video (int mode)
  126.   34| 
  127.   35| /* Initializes video adapter and defaults for mode          */
  128.   36| /* Sets up pc_textmode() to be called on pgm termination    */
  129.   37| /* Returns TRUE or FALSE indicating success                 */
  130.   38| /* This function will be expanded in a later version        */
  131.   39| {
  132.   40| union REGS r;
  133.   41| int result = FALSE;
  134.   42| 
  135.   43|   /* Determine attached adapter and monitor */
  136.   44|   r.h.ah = 0x1A;                    /* VGA inquiry function */
  137.   45|   r.h.al = 0;
  138.   46|   int86 (0x10, &r, &r);                    /* ROM BIOS call */
  139.   47|   if (r.h.al == 0x1A)
  140.   48|     switch (r.h.bl) {
  141.   49|       case 4 : ega = TRUE;                     /* EGA color */
  142.   50|                colormonitor = TRUE;
  143.   51|                break;
  144.   52|       case 5 : ega = TRUE;                      /* EGA mono */
  145.   53|                break;
  146.   54|       case 7 : ega = TRUE;                      /* VGA mono */
  147.   55|                vga = TRUE;
  148.   56|                break;
  149.   57|       case 8 : ega = TRUE;                     /* VGA color */
  150.   58|                vga = TRUE;
  151.   59|                colormonitor = TRUE;
  152.   60|     }
  153.   61|   else {                        /* No VGA, so check for EGA */
  154.   62|     r.h.ah = 0x12;
  155.   63|     r.x.bx = 0x10;
  156.   64|     int86 (0x10, &r, &r);
  157.   65|     if (r.x.bx != 0x10) {              /* if EGA present... */
  158.   66|       ega = TRUE;                               /* set flag */
  159.   67|       r.h.ah = 0x12;
  160.   68|       r.h.bl = 0x10;              /* find out which monitor */
  161.   69|       int86 (0x10, &r, &r);
  162.   70|       if (r.h.bh == 0)
  163.   71|         colormonitor = TRUE;                   /* EGA color */
  164.   72|     }
  165.   73|   }
  166.   74| 
  167.   75|   /* Proceed only if EGA or VGA present */
  168.   76|   if (ega | vga) {
  169.   77|     set_color1 (15);                 /* default pixel color */
  170.   78| 
  171.   79|     r.h.ah = 0x0F;               /* get current screen mode */
  172.   80|     int86 (0x10, &r, &r);
  173.   81|     oldmode = r.h.al;                           /* store it */
  174.   82|     textpage = r.h.bh;             /* also active text page */
  175.   83| 
  176.   84|     if (colormonitor)              /* point to video memory */
  177.   85|       vidmem = 0xB800;
  178.   86|     else
  179.   87|       vidmem = 0xB000;
  180.   88|     vidsave = malloc (4096);          /* allocate save area */
  181.   89|     movedata                   /* save text screen contents */
  182.   90|         (vidmem, 0, FP_SEG (vidsave), FP_OFF (vidsave), 4096);
  183.   91| 
  184.   92|     r.h.ah = 3;                 /* get text cursor position */
  185.   93|     r.h.bh = textpage;
  186.   94|     int86 (0x10, &r, &r);
  187.   95|     curpos = r.x.dx;                         /* and save it */
  188.   96| 
  189.   97|     if ((mode == EGA) && ega) {
  190.   98|       r.h.ah = 0;
  191.   99|       r.h.al = mode;                        /* set EGA mode */
  192.  100|       int86 (0x10, &r, &r);
  193.  101|       result = TRUE;
  194.  102|     } else
  195.  103|       if ((mode == vga) && vga) {
  196.  104|         r.h.ah = 0;
  197.  105|         r.h.al = mode;
  198.  106|         int86 (0x10, &r, &r);
  199.  107|         result = TRUE;
  200.  108|       }
  201.  109|   }
  202.  110|   if (!result) {            /* unable to switch to graphics */
  203.  111|     oldmode = 0;              /* so cancel text screen save */
  204.  112|     free (vidsave);
  205.  113|     vidsave = 0;
  206.  114|   } else {                             /* successful, so... */
  207.  115|     grafixmode = mode;                         /* save mode */
  208.  116|     atexit (pc_textmode);         /* register exit function */
  209.  117|   }
  210.  118|   return result;
  211.  119| } /* ------------------------------------------------------ */
  212.  120| 
  213.  121| void far pc_textmode (void)
  214.  122| /* SPECIFIC TO MS-DOS */
  215.  123| /* Restore text mode */
  216.  124| /* Automatically called on pgm termination */
  217.  125| {
  218.  126| union REGS r;
  219.  127| 
  220.  128|   if (oldmode) {              /* if not in text mode now... */
  221.  129|     r.h.ah = 0;
  222.  130|     r.h.al = oldmode;                  /* restore text mode */
  223.  131|     int86 (0x10, &r, &r);
  224.  132|     movedata                         /* restore text screen */
  225.  133|         (FP_SEG (vidsave), FP_OFF (vidsave), vidmem, 0, 4096);
  226.  134|     free (vidsave);                /* free allocated memory */
  227.  135|     vidsave = 0;                            /* zero pointer */
  228.  136|     oldmode = 0;                                   /* reset */
  229.  137|     r.h.ah = 2;              /* restore old cursor position */
  230.  138|     r.h.bh = textpage;
  231.  139|     r.x.dx = curpos;
  232.  140|     int86 (0x10, &r, &r);
  233.  141|   }
  234.  142| } /* ------------------------------------------------------ */
  235.  143| 
  236.  144| void far set_color1 (int palette_reg)
  237.  145| /* Select pixel color from palette register */
  238.  146| {
  239.  147|   color1 = palette_reg;
  240.  148| } /* ------------------------------------------------------ */
  241.  
  242.  
  243. [LISTING THREE]
  244.  
  245. /* Library source file GRAFIX.C               */
  246. /* EGA/VGA graphics subsystem                 */
  247. /* Following library routines are external:   */
  248. /*     DRAWPT.ASM       Feb '89               */
  249. /* K. Porter, DDJ Graphics Programming Column */
  250. /* ------------------------------------------ */
  251.  
  252. #include <dos.h>
  253. #include <stdlib.h>
  254. #include <string.h>
  255. #include <stdio.h>
  256. #include "grafix.h"
  257.  
  258. #if !defined TRUE
  259. #define FALSE 0
  260. #define TRUE  !FALSE
  261. #endif
  262.  
  263. /* Variables global to this library */
  264. int  color1,                            /* foreground color */
  265.      oldmode = 0,                      /* pre-graphics mode */
  266.      grafixmode = 0,               /* default graphics mode */
  267.      ega = FALSE,                     /* equipment Booleans */
  268.      vga = FALSE,
  269.      colormonitor = FALSE,
  270.      curpos,                        /* text cursor position */
  271.      textpage;                          /* active text page */
  272. unsigned vidmem;                    /* video buffer segment */
  273. char far *vidsave;                /* video buffer save area */
  274.  
  275. /* -------------------------------------------------------- */
  276.  
  277. int far init_video (int mode)
  278.  
  279. /* Initializes video adapter and defaults for mode          */
  280. /* Sets up pc_textmode() to be called on pgm termination    */
  281. /* Returns TRUE or FALSE indicating success                 */
  282. /* This function will be expanded in a later version        */
  283. {
  284. union REGS r;
  285. int result = FALSE;
  286.  
  287.   /* Determine attached adapter and monitor */
  288.   r.h.ah = 0x1A;                    /* VGA inquiry function */
  289.   r.h.al = 0;
  290.   int86 (0x10, &r, &r);                    /* ROM BIOS call */
  291.   if (r.h.al == 0x1A)
  292.     switch (r.h.bl) {
  293.       case 4 : ega = TRUE;                     /* EGA color */
  294.                colormonitor = TRUE;
  295.                break;
  296.       case 5 : ega = TRUE;                      /* EGA mono */
  297.                break;
  298.       case 7 : ega = TRUE;                      /* VGA mono */
  299.                vga = TRUE;
  300.                break;
  301.       case 8 : ega = TRUE;                     /* VGA color */
  302.                vga = TRUE;
  303.                colormonitor = TRUE;
  304.     }
  305.   else {                        /* No VGA, so check for EGA */
  306.     r.h.ah = 0x12;
  307.     r.x.bx = 0x10;
  308.     int86 (0x10, &r, &r);
  309.     if (r.x.bx != 0x10) {              /* if EGA present... */
  310.       ega = TRUE;                               /* set flag */
  311.       r.h.ah = 0x12;
  312.       r.h.bl = 0x10;              /* find out which monitor */
  313.       int86 (0x10, &r, &r);
  314.       if (r.h.bh == 0)
  315.         colormonitor = TRUE;                   /* EGA color */
  316.     }
  317.   }
  318.  
  319.   /* Proceed only if EGA or VGA present */
  320.   if (ega | vga) {
  321.     set_color1 (15);                 /* default pixel color */
  322.  
  323.     r.h.ah = 0x0F;               /* get current screen mode */
  324.     int86 (0x10, &r, &r);
  325.     oldmode = r.h.al;                           /* store it */
  326.     textpage = r.h.bh;             /* also active text page */
  327.  
  328.     if (colormonitor)              /* point to video memory */
  329.       vidmem = 0xB800;
  330.     else
  331.       vidmem = 0xB000;
  332.     vidsave = malloc (4096);          /* allocate save area */
  333.     movedata                   /* save text screen contents */
  334.         (vidmem, 0, FP_SEG (vidsave), FP_OFF (vidsave), 4096);
  335.  
  336.     r.h.ah = 3;                 /* get text cursor position */
  337.     r.h.bh = textpage;
  338.     int86 (0x10, &r, &r);
  339.     curpos = r.x.dx;                         /* and save it */
  340.  
  341.     if ((mode == EGA) && ega) {
  342.       r.h.ah = 0;
  343.       r.h.al = mode;                        /* set EGA mode */
  344.       int86 (0x10, &r, &r);
  345.       result = TRUE;
  346.     } else
  347.       if ((mode == vga) && vga) {
  348.         r.h.ah = 0;
  349.         r.h.al = mode;
  350.         int86 (0x10, &r, &r);
  351.         result = TRUE;
  352.       }
  353.   }
  354.   if (!result) {            /* unable to switch to graphics */
  355.     oldmode = 0;              /* so cancel text screen save */
  356.     free (vidsave);
  357.     vidsave = 0;
  358.   } else {                             /* successful, so... */
  359.     grafixmode = mode;                         /* save mode */
  360.     atexit (pc_textmode);         /* register exit function */
  361.   }
  362.   return result;
  363. } /* ------------------------------------------------------ */
  364.  
  365. void far pc_textmode (void)
  366. /* SPECIFIC TO MS-DOS */
  367. /* Restore text mode */
  368. /* Automatically called on pgm termination */
  369. {
  370. union REGS r;
  371.  
  372.   if (oldmode) {              /* if not in text mode now... */
  373.     r.h.ah = 0;
  374.     r.h.al = oldmode;                  /* restore text mode */
  375.     int86 (0x10, &r, &r);
  376.     movedata                         /* restore text screen */
  377.         (FP_SEG (vidsave), FP_OFF (vidsave), vidmem, 0, 4096);
  378.     free (vidsave);                /* free allocated memory */
  379.     vidsave = 0;                            /* zero pointer */
  380.     oldmode = 0;                                   /* reset */
  381.     r.h.ah = 2;              /* restore old cursor position */
  382.     r.h.bh = textpage;
  383.     r.x.dx = curpos;
  384.     int86 (0x10, &r, &r);
  385.   }
  386. } /* ------------------------------------------------------ */
  387.  
  388. void far set_color1 (int palette_reg)
  389. /* Select pixel color from palette register */
  390. {
  391.   color1 = palette_reg;
  392. } /* ------------------------------------------------------ */
  393.  
  394.  
  395. [LISTING FOUR]
  396.  
  397. /* STRIPES.C: Demos pixel-writing with GRAFIX library */
  398.  
  399. #include <conio.h>
  400. #include <stdio.h>
  401. #include <stdlib.h>
  402. #include "grafix.h"
  403.  
  404. void main ()
  405. {
  406. int  x, y, color;
  407.  
  408.   if (!init_video (EGA)) {
  409.     puts ("No EGA/VGA present in system: Program ended");
  410.     exit (1);
  411.   } else {
  412.     for (y = 95; y < 255; y++) {
  413.       color = y % 16;                 /* first color this row */
  414.       for (x = 160; x < 480; x++) {
  415.         set_color1 (color);           /* set color this pixel */
  416.         draw_point (x, y);
  417.         if (++color == 16) color = 0;  /* wrap around palette */
  418.       }
  419.     }
  420.     getch();                             /* hold for keypress */
  421.   }
  422. }
  423.  
  424.  
  425.