home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / intel / hwsamp.txt < prev    next >
Encoding:
Text File  |  2013-11-08  |  639.1 KB  |  19,837 lines

  1.  \SAMPCODE
  2.  \SAMPCODE\MOUSE
  3.  \SAMPCODE\MOUSE\LIB
  4.  \SAMPCODE\MOUSE\LIB\EGA
  5.  \SAMPCODE\MOUSE\LIB\EGA\DEMO
  6.  \SAMPCODE\MOUSE\LIB\EGA\DEMO\LMCEGA.C
  7.  
  8.  /*----------------------------------------------------------------------*/
  9.  /* REFERENCE -- Test of cegal()                         IN lmcega.c     */
  10.  /*                                                                      */
  11.  /* This program tests the function cegal(), which is an interface       */
  12.  /* between large model MSC 3.0 (or higher) 'C' programs, and the EGA    */
  13.  /* Register Interface.                                                  */
  14.  /*                                                                      */
  15.  /* To create lmcega.exe:                                                */
  16.  /*                              MSC  /AL /Ze /w0 LMCEGA;                */
  17.  /*                              LINK LMCEGA,,,..\EGA;                   */
  18.  /*                     or:                                              */
  19.  /*                              MAKE LMCEGA.MAK                         */
  20.  /*----------------------------------------------------------------------*/
  21.  #include <stdio.h>
  22.  #include <dos.h>
  23.  
  24.  #define ega(a,b,c,d,e)  cegal(a,b,c,d,e)
  25.  #define FALSE   0
  26.  #define NOT     !
  27.  #define TRUE    NOT FALSE
  28.  
  29.  
  30.  main()
  31.  {
  32.      int ah, bx, cx, dx, es;
  33.      char buf[2];
  34.      char far *ver_fptr;
  35.  
  36.      ah = 0xfa;
  37.      bx = 0;
  38.  
  39.      ega(&ah, &bx, &cx, &dx, &es);
  40.  
  41.      if (!bx)
  42.      {
  43.          printf("\nEGA Driver not found");
  44.          return;
  45.      }
  46.      printf("\nEGA Driver found, version ");
  47.      ver_fptr = (((long) es) << 16) + bx;
  48.      printf("%1d.%2d", *ver_fptr, ver_fptr[1]);
  49.  
  50.      printf("\nRead/Write Range functions (F2, F3) ");
  51.      if (test_range())   printf("PASSED");
  52.      else                printf("FAILED");
  53.      printf("\n\n\n");
  54.  }
  55.  
  56.  
  57.  test_range()
  58.  {
  59.      int ah, bx, cx, dx, es;
  60.      int *bxp;
  61.      static char org_buf[2] = {0xAA, 0xAA};
  62.      static char wr_buf[2] = {0xBB, 0xBB};
  63.      static char rd_buf[2] = {0xCC, 0xCC};
  64.      int old_map_mask;
  65.      int old_misc_reg;
  66.  
  67.      /* read the cursor location high and low registers */
  68.  
  69.      ah  = 0xF2;         /* read range   */
  70.      cx  = 0x0e00;       /* start at reg 14      */
  71.      cx |= 0x0002;       /* 2 reg to read        */
  72.      dx  = 0x0000;       /* crt controller       */
  73.      es  = getds();      /* current data segment */
  74.  
  75.      ega(&ah, org_buf, &cx, &dx, &es);
  76.  
  77.      wr_buf[0] = 0xee;
  78.      wr_buf[1] = 0xff;
  79.  
  80.      ah = 0xF3;          /* write range          */
  81.      cx = 0x0e02;        /* start at e, write 2  */
  82.      dx = 0;             /* crt controller       */
  83.      es = getds();
  84.  
  85.      ega(&ah, wr_buf, &cx, &dx, &es);
  86.  
  87.      ah = 0xF2;          /* read range   */
  88.      cx = 0x0e02;        /* start at e , read 2  */
  89.      dx = 0;
  90.      es = getds();
  91.  
  92.      ega(&ah, rd_buf, &cx, &dx, &es);
  93.  
  94.      /* restore original values */
  95.  
  96.      ah = 0xF3;          /* write range          */
  97.      cx = 0x0e02;        /* start at e, write 2  */
  98.      dx = 0;             /* crt controller       */
  99.      es = getds();
  100.      ega(&ah, org_buf, &cx, &dx, &es);
  101.  
  102.      if (rd_buf[0] != wr_buf[0])
  103.          return FALSE;
  104.      if (rd_buf[1] != wr_buf[1])
  105.          return FALSE;
  106.  
  107.      return TRUE;
  108.  }
  109.  
  110.  
  111.  getds()
  112.  /*----------------------------------------------------------------------*/
  113.  /* METHOD  -- Returns the current data segment.                         */
  114.  /*----------------------------------------------------------------------*/
  115.  /* RETURNS -- Current code segment.                                     */
  116.  /*----------------------------------------------------------------------*/
  117.  /* GLOBAL EFFECTS -- none.                                              */
  118.  /*----------------------------------------------------------------------*/
  119.  /* REVISION  1.00 is:  Original version.                                */
  120.  /*----------------------------------------------------------------------*/
  121.  {
  122.      struct SREGS segregs;
  123.  
  124.      segread(&segregs);
  125.      return segregs.ds;
  126.  }
  127.  
  128.  \SAMPCODE\MOUSE\LIB\EGA\DEMO\MMCEGA.C
  129.  
  130.  /*----------------------------------------------------------------------*/
  131.  /* REFERENCE -- Test of cegam()                         IN mmcega.c     */
  132.  /*                                                                      */
  133.  /* This program tests the function cegam(), which is an interface       */
  134.  /* between medium model MSC 3.0 (or higher) 'C' programs, and the EGA   */
  135.  /* Register Interface.                                                  */
  136.  /*                                                                      */
  137.  /* To create mmcega.exe:                                                */
  138.  /*                              MSC  /AM MMCEGA;                        */
  139.  /*                              LINK MMCEGA,,,..\EGA                    */
  140.  /*                      or:                                             */
  141.  /*                              MAKE MMCEGA.MAK                         */
  142.  /*----------------------------------------------------------------------*/
  143.  #include <stdio.h>
  144.  #include <dos.h>
  145.  
  146.  #define ega(a,b,c,d,e)  cegam(a,b,c,d,e)
  147.  #define FALSE   0
  148.  #define NOT     !
  149.  #define TRUE    NOT FALSE
  150.  
  151.  
  152.  main()
  153.  {
  154.      int ah, bx, cx, dx, es;
  155.      char buf[2];
  156.  
  157.      ah = 0xfa;
  158.      bx = 0;
  159.  
  160.      ega(&ah, &bx, &cx, &dx, &es);
  161.  
  162.      if (!bx)
  163.      {
  164.          printf("\nEGA Driver not found");
  165.          return;
  166.      }
  167.      printf("\nEGA Driver found, version ");
  168.      movedata(es, bx, getds(), buf, 2);
  169.  
  170.      printf("%1d.%2d", buf[0], buf[1]);
  171.  
  172.      printf("\nRead/Write Range functions (F2, F3) ");
  173.      if (test_range())   printf("PASSED");
  174.      else                printf("FAILED");
  175.      printf("\n\n\n");
  176.  }
  177.  
  178.  
  179.  test_range()
  180.  {
  181.      int ah, bx, cx, dx, es;
  182.      int *bxp;
  183.      static char org_buf[2] = {0xAA, 0xAA};
  184.      static char wr_buf[2] = {0xBB, 0xBB};
  185.      static char rd_buf[2] = {0xCC, 0xCC};
  186.      int old_map_mask;
  187.      int old_misc_reg;
  188.  
  189.      /* read the cursor location high and low registers */
  190.  
  191.      ah  = 0xF2;         /* read range   */
  192.      cx  = 0x0e00;       /* start at reg 14      */
  193.      cx |= 0x0002;       /* 2 reg to read        */
  194.      dx  = 0x0000;       /* crt controller       */
  195.      es  = getds();      /* current data segment */
  196.  
  197.      ega(&ah, org_buf, &cx, &dx, &es);
  198.  
  199.      wr_buf[0] = 0xee;
  200.      wr_buf[1] = 0xff;
  201.  
  202.      ah = 0xF3;          /* write range          */
  203.      cx = 0x0e02;        /* start at e, write 2  */
  204.      dx = 0;             /* crt controller       */
  205.      es = getds();
  206.  
  207.      ega(&ah, wr_buf, &cx, &dx, &es);
  208.  
  209.      ah = 0xF2;          /* read range   */
  210.      cx = 0x0e02;        /* start at e , read 2  */
  211.      dx = 0;
  212.      es = getds();
  213.  
  214.      ega(&ah, rd_buf, &cx, &dx, &es);
  215.  
  216.      /* restore original values */
  217.  
  218.      ah = 0xF3;          /* write range          */
  219.      cx = 0x0e02;        /* start at e, write 2  */
  220.      dx = 0;             /* crt controller       */
  221.      es = getds();
  222.      ega(&ah, org_buf, &cx, &dx, &es);
  223.  
  224.      if (rd_buf[0] != wr_buf[0])
  225.          return FALSE;
  226.      if (rd_buf[1] != wr_buf[1])
  227.          return FALSE;
  228.  
  229.      return TRUE;
  230.  }
  231.  
  232.  
  233.  getds()
  234.  /*----------------------------------------------------------------------*/
  235.  /* METHOD  -- Returns the current data segment.                         */
  236.  /*----------------------------------------------------------------------*/
  237.  /* RETURNS -- Current code segment.                                     */
  238.  /*----------------------------------------------------------------------*/
  239.  /* GLOBAL EFFECTS -- none.                                              */
  240.  /*----------------------------------------------------------------------*/
  241.  /* REVISION  1.00 is:  Original version.                                */
  242.  /*----------------------------------------------------------------------*/
  243.  {
  244.      struct SREGS segregs;
  245.  
  246.      segread(&segregs);
  247.      return segregs.ds;
  248.  }
  249.  
  250.  \SAMPCODE\MOUSE\LIB\EGA\DEMO\SMCEGA.C
  251.  
  252.  /*----------------------------------------------------------------------*/
  253.  /* REFERENCE -- Test of cegas()                         IN smcega.c     */
  254.  /*                                                                      */
  255.  /* This program tests the function cegas(), which is an interface       */
  256.  /* between small model MSC 3.0 (or higher) 'C' programs, and the EGA    */
  257.  /* Register Interface.                                                  */
  258.  /*                                                                      */
  259.  /* To create smcega.exe:                                                */
  260.  /*                              MSC  SMCEGA;                            */
  261.  /*                              LINK SMCEGA,,,..\EGA;                   */
  262.  /*                     or:                                              */
  263.  /*                              MAKE SMCEGA.MAK                         */
  264.  /*----------------------------------------------------------------------*/
  265.  #include <stdio.h>
  266.  #include <dos.h>
  267.  
  268.  #define ega(a,b,c,d,e)  cegas(a,b,c,d,e)
  269.  #define FALSE   0
  270.  #define NOT     !
  271.  #define TRUE    NOT FALSE
  272.  
  273.  
  274.  main()
  275.  {
  276.      int ah, bx, cx, dx, es;
  277.      char buf[2];
  278.  
  279.      ah = 0xfa;
  280.      bx = 0;
  281.  
  282.      ega(&ah, &bx, &cx, &dx, &es);
  283.  
  284.      if (!bx)
  285.      {
  286.          printf("\nEGA Driver not found");
  287.          return;
  288.      }
  289.      printf("\nEGA Driver found, version ");
  290.      movedata(es, bx, getds(), buf, 2);
  291.  
  292.      printf("%1d.%2d", buf[0], buf[1]);
  293.  
  294.      printf("\nRead/Write Range functions (F2, F3) ");
  295.      if (test_range())   printf("PASSED");
  296.      else                printf("FAILED");
  297.      printf("\n\n\n");
  298.  }
  299.  
  300.  
  301.  test_range()
  302.  {
  303.      int ah, bx, cx, dx, es;
  304.      int *bxp;
  305.      static char org_buf[2] = {0xAA, 0xAA};
  306.      static char wr_buf[2] = {0xBB, 0xBB};
  307.      static char rd_buf[2] = {0xCC, 0xCC};
  308.      int old_map_mask;
  309.      int old_misc_reg;
  310.  
  311.      /* read the cursor location high and low registers */
  312.  
  313.      ah  = 0xF2;         /* read range   */
  314.      cx  = 0x0e00;       /* start at reg 14      */
  315.      cx |= 0x0002;       /* 2 reg to read        */
  316.      dx  = 0x0000;       /* crt controller       */
  317.      es  = getds();      /* current data segment */
  318.  
  319.      ega(&ah, org_buf, &cx, &dx, &es);
  320.  
  321.      wr_buf[0] = 0xee;
  322.      wr_buf[1] = 0xff;
  323.  
  324.      ah = 0xF3;          /* write range          */
  325.      cx = 0x0e02;        /* start at e, write 2  */
  326.      dx = 0;             /* crt controller       */
  327.      es = getds();
  328.  
  329.      ega(&ah, wr_buf, &cx, &dx, &es);
  330.  
  331.      ah = 0xF2;          /* read range   */
  332.      cx = 0x0e02;        /* start at e , read 2  */
  333.      dx = 0;
  334.      es = getds();
  335.  
  336.      ega(&ah, rd_buf, &cx, &dx, &es);
  337.  
  338.      /* restore original values */
  339.  
  340.      ah = 0xF3;          /* write range          */
  341.      cx = 0x0e02;        /* start at e, write 2  */
  342.      dx = 0;             /* crt controller       */
  343.      es = getds();
  344.      ega(&ah, org_buf, &cx, &dx, &es);
  345.  
  346.      if (rd_buf[0] != wr_buf[0])
  347.          return FALSE;
  348.      if (rd_buf[1] != wr_buf[1])
  349.          return FALSE;
  350.  
  351.      return TRUE;
  352.  }
  353.  
  354.  
  355.  getds()
  356.  /*----------------------------------------------------------------------*/
  357.  /* METHOD  -- Returns the current data segment.                         */
  358.  /*----------------------------------------------------------------------*/
  359.  /* RETURNS -- Current code segment.                                     */
  360.  /*----------------------------------------------------------------------*/
  361.  /* GLOBAL EFFECTS -- none.                                              */
  362.  /*----------------------------------------------------------------------*/
  363.  /* REVISION  1.00 is:  Original version.                                */
  364.  /*----------------------------------------------------------------------*/
  365.  {
  366.      struct SREGS segregs;
  367.  
  368.      segread(&segregs);
  369.      return segregs.ds;
  370.  }
  371.  
  372.  \SAMPCODE\MOUSE\LIB\EGA\DEMO\QBEGA.BAS
  373.  
  374.  '
  375.  ' Test of function ega() and egas() in ega.lib.  Tests all of the parameters
  376.  ' passed to these two functions.
  377.  '
  378.  ' To make qbega.exe:            QB QBEGA;
  379.  '                               LINK QBEGA,,,EGA;
  380.  '
  381.  '
  382.  
  383.  ' Interrogate the driver, get the version number.
  384.  '
  385.  '
  386.      e1% = &h00fa
  387.      e2% = 0
  388.      e3% = 0
  389.      e4% = 0
  390.      e5% = 0
  391.  
  392.      call ega(e1%, e2%, e3%, e4%, e5%)
  393.  
  394.      if (e2% <> 0) then 100
  395.      print "Mouse Driver not found"
  396.      end
  397.  100 print "Mouse Driver found, version ";
  398.      def seg = e5%
  399.      majver = peek(e2%)
  400.      minver = peek(e2%+1)
  401.      def seg
  402.      print " = ";
  403.      print using "#";majver;
  404.      print ".";
  405.      print using "##";minver
  406.      print
  407.      def seg
  408.  
  409.  
  410.  ' Test the read and write register range functions F2 and F3.  Save old value
  411.  ' write new value, read value, restore original value, if value read was not
  412.  ' the value written, then something is wrong.
  413.  '
  414.  
  415.      print "Read/Write Range functions (F2, F3) ";
  416.  
  417.      nvals = 2
  418.      nints = int (nvals/2) + 1
  419.      start = &h0e
  420.  
  421.      dim orbuf%(1)
  422.      dim rdbuf%(1)
  423.      dim wrbuf%(1)
  424.  
  425.      orbuf%(0) = &haaaa
  426.      rdbuf%(0) = &hbbbb
  427.      wrbuf%(0) = &hcccc
  428.  '
  429.      e1%  = &hF2                                 ' read range
  430.      e3%  = start * 256 + nvals                  ' start reg & num regs
  431.      e4%  = 0                                    ' crt controller
  432.      e5%  = 0                                    ' dummy arg
  433.  
  434.      call ega(e1%, orbuf%(0), e3%, e4%, e5%)
  435.  
  436.      wrbuf%(0) = &heeff
  437.      e1% = &hF3                                  ' write range
  438.      call ega(e1%, wrbuf%(0), e3%, e4%, e5%)
  439.  
  440.  
  441.      e1% = &hF2                                  ' read range
  442.      call ega(e1%, rdbuf%(0), e3%, e4%, e5%)
  443.  
  444.      e1% = &hF3                                  ' write range
  445.      call ega(e1%, orbuf%(0), e3%, e4%, e5%)
  446.  
  447.      if (rdbuf%(0) <> wrbuf%(0))  then print "FAILED" else print "PASSED"
  448.  
  449.  
  450.  '
  451.  ' Now test segment:offset calls
  452.  '
  453.      print
  454.      print
  455.      print "Testing calls with segment:offset, using CALLS and EGAS"
  456.      print
  457.  
  458.      e1% = &h00fa
  459.      e2% = 0
  460.      e3% = 0
  461.      e4% = 0
  462.      e5% = 0
  463.  
  464.      calls egas(e1%, e2%, e3%, e4%, e5%)
  465.  
  466.      if (e2% <> 0) then 200
  467.      print "Mouse Driver not found"
  468.      end
  469.  200 print "Mouse Driver found, version ";
  470.      def seg = e5%
  471.      majver = peek(e2%)
  472.      minver = peek(e2%+1)
  473.      def seg
  474.      print " = ";
  475.      print using "#";majver;
  476.      print ".";
  477.      print using "##";minver
  478.      print
  479.      def seg
  480.  
  481.      print "Read/Write Range functions (F2, F3) ";
  482.      ' read the cursor location high and low registers
  483.  
  484.  
  485.      nvals = 2
  486.      nints = int (nvals/2) + 1
  487.      start = &h0e
  488.  
  489.      orbuf%(0) = &haaaa
  490.      rdbuf%(0) = &hbbbb
  491.      wrbuf%(0) = &hcccc
  492.  '
  493.      e1%  = &hF2                                 ' read range
  494.      e3%  = start * 256 + nvals                  ' start reg & num regs
  495.      e4%  = 0                                    ' crt controller
  496.      e5%  = 0                                    ' dummy arg
  497.  
  498.      calls egas(e1%, orbuf%(0), e3%, e4%, e5%)
  499.  
  500.      wrbuf%(0) = &heeff
  501.      e1% = &hF3                                  ' write range
  502.      calls egas(e1%, wrbuf%(0), e3%, e4%, e5%)
  503.  
  504.  
  505.      e1% = &hF2                                  ' read range
  506.      calls egas(e1%, rdbuf%(0), e3%, e4%, e5%)
  507.  
  508.      e1% = &hF3                                  ' write range
  509.      calls egas(e1%, orbuf%(0), e3%, e4%, e5%)
  510.  
  511.      if (rdbuf%(0) <> wrbuf%(0))  then print "FAILED" else print "PASSED"
  512.      print
  513.  
  514.  ' Thats all
  515.  
  516.      end
  517.  
  518.  \SAMPCODE\MOUSE\LIB\EGA\DEMO\LMCEGA.MAK
  519.  
  520.  lmcega.obj:     lmcega.c
  521.          msc /AL /Ze lmcega;
  522.  
  523.  lmcega.exe:     lmcega.obj
  524.          link lmcega,,,..\ega;
  525.  
  526.  \SAMPCODE\MOUSE\LIB\EGA\DEMO\QBEGA.MAK
  527.  
  528.  QBEGA.OBJ:      QBEGA.BAS
  529.          QB QBEGA /O;
  530.  
  531.  QBEGA.EXE:      QBEGA.OBJ
  532.          LINK QBEGA,,,BCOM20+..\EGA;
  533.  
  534.  \SAMPCODE\MOUSE\LIB\EGA\DEMO\SMCEGA.MAK
  535.  
  536.  smcega.obj:     smcega.c
  537.          msc smcega;
  538.  
  539.  smcega.exe:     smcega.obj
  540.          link smcega,,,..\ega;
  541.  
  542.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES
  543.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F0EXAMP.ASM
  544.  
  545.  ; The following example saves the contents of the Sequencer Map Mask register
  546.  ; in "myvalue".
  547.  
  548.  myvalue db      ?
  549.  
  550.          mov     ah, 0f0h        ; f0 = read one register
  551.          mov     bx, 0002h       ; bh = 0
  552.                                  ; bl = map mask index
  553.          mov     dx, 0008h       ; dx = sequencer
  554.          int     10h             ; get it!
  555.          mov     myvalue, bl     ; save it!
  556.  
  557.  
  558.  ;---------------------------------------------------------------------
  559.  
  560.  
  561.  ; The following example saves the contents of the Miscellaneous Output
  562.  ; register in "myvalue".
  563.  
  564.  myvalue db      ?
  565.  
  566.          mov     ah, 0f0h        ; f0 = read one register
  567.          mov     dx, 0020h       ; dx = miscellaneous output register
  568.          int     10h             ; get it!
  569.          mov     myvalue, bl     ; save it!
  570.  
  571.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F1EXAMP.ASM
  572.  
  573.  ; The following example writes the contents of "myvalue" into the CRT
  574.  ; Controller Cursor Start register.
  575.  
  576.  myvalue db      3h
  577.  
  578.          mov     ah, 0f1h        ; f1 = write one register
  579.          mov     bh, myvalue     ; bh = data from myvalue
  580.          mov     bl, 000ah       ; bl = cursor start index
  581.          mov     dx, 0000h       ; dx = crt controller
  582.          int     10h             ; write it!
  583.  
  584.  
  585.  ;---------------------------------------------------------------------
  586.  
  587.  
  588.  ; The following example writes the contents of "myvalue" into the Feature
  589.  ; Control register.
  590.  
  591.  myvalue db      2h
  592.  
  593.          mov     ah, 0f1h        ; f1 = write one register
  594.          mov     bl, myvalue     ; bl = data from myvalue
  595.          mov     dx, 0028h       ; dx = feature control register
  596.          int     10h             ; write it!
  597.  
  598.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F2EXAMP.ASM
  599.  
  600.  ; The following example saves the contents of the Attribute Controller
  601.  ; Palette registers in "paltable".
  602.  
  603.  paltable db     16 dup (?)
  604.  
  605.          mov     ax, ds                  ; assume paltable in data segment
  606.          mov     es, ax                  ; es = data segment
  607.          mov     bx, offset paltable     ; es:bx = paltable address
  608.          mov     ah, 0f2h                ; f2 = read register range
  609.          mov     cx, 0010h               ; ch = start index of 0
  610.                                          ; cl = 16 registers to read
  611.          mov     dx, 0018h               ; dx = attribute controller
  612.          int     10h                     ; read them!
  613.  
  614.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F3EXAMP.ASM
  615.  
  616.  ; The following example writes the contents of "cursloc" into the CRT
  617.  ; Controller Cursor Location High and Cursor Location Low registers.
  618.  
  619.  cursloc db      01h, 00h
  620.  
  621.          mov     ax, ds                  ; assume cursloc in data segment
  622.          mov     es, ax                  ; es = data segment
  623.          mov     bx, offset cursloc      ; es:bx = cursloc address
  624.          mov     ah, 0f3h                ; f2 = write register range
  625.          mov     cx, 0e02h               ; ch = start index of 14
  626.                                          ; cl = 2 registers to write
  627.          mov     dx, 0000h               ; dx = crt controller
  628.          int     10h                     ; write them!
  629.  
  630.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F4EXAMP.ASM
  631.  
  632.  ; The following example saves the contents of the Miscellaneous Output
  633.  ; register, Sequencer Memory Mode register, and CRT Controller Mode Control
  634.  ; register in "results".
  635.  
  636.  outvals dw      0020h           ; miscellaneous output register
  637.          db      0               ; 0 for single registers
  638.          db      ?               ; returned value
  639.  
  640.          dw      0008h           ; sequencer
  641.          db      04h             ; memory mode register index
  642.          db      ?               ; returned value
  643.  
  644.          dw      0000h           ; crt controller
  645.          db      17h             ; mode control register index
  646.          db      ?               ; returned value
  647.  
  648.  results db      3 dup (?)
  649.  
  650.          mov     ax, ds                  ; assume outvals in data segment
  651.          mov     es, ax                  ; es = data segment
  652.          mov     bx, offset outvals      ; es:bx = outvals address
  653.          mov     ah, 0f4h                ; f4 = read register set
  654.          mov     cx, 3                   ; number of entries in outvals
  655.          int     10h                     ; get values into outvals!
  656.          mov     si, 3                   ; move the returned values from
  657.          add     si, offset outvals      ;  outvals
  658.          mov     di, offset results      ;  to results
  659.          mov     cx, 3                   ; 3 values to move
  660.  
  661.  movloop:
  662.          mov     ax, [si]                ; move one value from outvals
  663.          mov     [di], ax                ;  to results
  664.          add     si, 4                   ; skip to next source byte
  665.          inc     di                      ; point to next destination byte
  666.          loop    movloop
  667.  
  668.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F5EXAMP.ASM
  669.  
  670.  ; The following example writes the contents of "outvals" to the Miscellaneous
  671.  ; Output register, Sequencer Memory Mode register, and CRT Controller Mode
  672.  ; Control register.
  673.  
  674.  outvals dw      0020h           ; miscellaneous output register
  675.          db      0               ; 0 for single registers
  676.          db      0a7h            ; output value
  677.  
  678.          dw      0008h           ; sequencer
  679.          db      04h             ; memory mode register index
  680.          db      03h             ; output value
  681.  
  682.          dw      0000h           ; crt controller
  683.          db      17h             ; mode control register index
  684.          db      0a3h            ; output value
  685.  
  686.          mov     ax, ds                  ; assume outvals in data segment
  687.          mov     es, ax                  ; es = data segment
  688.          mov     bx, offset outvals      ; es:bx = outvals address
  689.          mov     ah, 0f5h                ; f5 = write register set
  690.          mov     cx, 3                   ; number of entries in outvals
  691.          int     10h                     ; write the registers!
  692.  
  693.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F6EXAMP.ASM
  694.  
  695.  ; The following example restores the default settings of the EGA registers.
  696.  
  697.          mov     ah, 0f6h        ; f6 = revert to default registers
  698.          int     10h             ; do it now!
  699.  
  700.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\F7EXAMP.ASM
  701.  
  702.  ; The following example defnes default values for the Attribute Controller.
  703.  
  704.  attrdflt db     00h, 01h, 02h, 03h, 04h, 05h, 06h, 07h
  705.           db     10h, 11h, 12h, 13h, 14h, 15h, 16h, 17h
  706.           db     08h, 00h, 0fh, 00h
  707.  
  708.          mov     ax, ds                  ; assume attrdflt in data segment
  709.          mov     es, ax                  ; es = data segment
  710.          mov     bx, offset attrdflt     ; es:bx = attrdflt address
  711.          mov     ah, 0f7h                ; f7 = define default register table
  712.          mov     dx, 0018h               ; dx = attribute controller
  713.          int     10h                     ; do it!
  714.  
  715.  
  716.  ;---------------------------------------------------------------------------
  717.  
  718.  
  719.  ; The following example defines a default value for the Feature Control
  720.  ; register.
  721.  
  722.  featdflt db     00h
  723.  
  724.          mov     ax, ds                  ; assume featdflt in data segment
  725.          mov     es, ax                  ; es = data segment
  726.          mov     bx, offset attrdflt     ; es:bx = featdflt address
  727.          mov     ah, 0f7h                ; f7 = define default register table
  728.          mov     dx, 0028h               ; dx = feature control register
  729.          int     10h                     ; do it!
  730.  
  731.  \SAMPCODE\MOUSE\LIB\EGA\EXAMPLES\FAEXAMP.ASM
  732.  
  733.  ; The following example interrogates the mouse driver and displays the
  734.  ; results.
  735.  
  736.  gotmsg  db      "mouse driver found", 0dh, 0ah, 24h
  737.  nopmsg  db      "mouse drive not found", 0dh, 0ah, 24h
  738.  revmsg  db      "revision $"
  739.  crlf    db      0dh, 0ah, 24h
  740.  
  741.  ten     db      10
  742.  
  743.          mov     bx, 0                   ; must be 0 for this call
  744.          mov     ah, 0fah                ; fa = interrogate driver
  745.          int     10h                     ; interrogate!
  746.          or      bx, bx                  ; bx = 0 ?
  747.          jnz     found                   ; branch if driver present
  748.          mov     dx, offset nopmsg       ; assume nopmsg in data segment
  749.          mov     ah, 09h                 ; 9 = print string
  750.          int     21h                     ; output not found message
  751.          jmp     continue                ; that's all for now
  752.  
  753.  found:  mov     dx, offset gotmsg       ; assume gotmsg in data segment
  754.          mov     ah, 09h                 ; 9 = print string
  755.          int     21h                     ; output found message
  756.          mov     dx, offset revmsg       ; assume revmsg in data segment
  757.          mov     ah, 09h                 ; 9 = print string
  758.          int     21h                     ; output "revision"
  759.          mov     dl, es:[bx]             ; dl = major release number
  760.          add     dl, "0"                 ; convert to ascii
  761.          mov     ah, 2                   ; 2 = display character
  762.          int     21h                     ; output major release number
  763.          mov     dl, "."                 ; dl = "."
  764.          mov     ah, 2                   ; 2 = display character
  765.          int     21h                     ; output a period
  766.          mov     al, es:[bx+1]           ; al = minor release number
  767.          xor     ah, ah                  ; ah = 0
  768.          idiv    ten                     ; al = 10ths, ah = 100ths
  769.          mov     bx, ax                  ; save ax in bx
  770.          mov     dl, al                  ; dl = 10ths
  771.          add     dl, "0"                 ; convert to ascii
  772.          mov     ah, 2                   ; 2 = display character
  773.          int     21h                     ; output minor release 10ths
  774.          mov     dl, bh                  ; dl = 100ths
  775.          add     dl, "0"                 ; convert to ascii
  776.          mov     ah, 2                   ; 2 = display character
  777.          int     21h                     ; output minor release 100ths
  778.          mov     dx, offset crlf         ; assume crlf in data segment
  779.          mov     ah, 09h                 ; 9 = print string
  780.          int     21h                     ; output end of line
  781.  
  782.  continue:                               ; the end
  783.  
  784.  \SAMPCODE\MOUSE\LIB\MOUSE
  785.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO
  786.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\CMCMOUSE.C
  787.  
  788.  /*----------------------------------------------------------------------*/
  789.  /* REFERENCE -- Compact model mouse drive interface test  IN cmcmouse.c */
  790.  /*                                                                      */
  791.  /* To create cmcmouse.exe:                                              */
  792.  /*                              MSC CMCMOUSE;                           */
  793.  /*                              LINK CMCMOUSE+SUBS,,,..\MOUSE           */
  794.  /*                      or:                                             */
  795.  /*                              MAKE CMCMOUSE.MAK                       */
  796.  /*                                                                      */
  797.  /*----------------------------------------------------------------------*/
  798.  #include <stdio.h>
  799.  #include <dos.h>
  800.  
  801.  #define mouse(a, b, c, d)       cmousec(a, b, c, d)
  802.  
  803.  #define M_RESET         0
  804.  #define M_SHOW_CURS     1
  805.  #define M_HIDE_CURS     2
  806.  #define M_GET_STATUS    3
  807.  #define M_SET_CURS      4
  808.  #define M_GET_PRESS     5
  809.  #define M_GET_REL       6
  810.  #define M_SET_MAX_POS   7
  811.  #define M_SET_MIN_POS   8
  812.  #define M_SET_G_CURS    9
  813.  #define M_SET_T_CURS    10
  814.  #define M_READ_COUNT    11
  815.  #define M_USER_SUB      12
  816.  #define M_LPEN_ON       13
  817.  #define M_LPEN_OFF      14
  818.  #define M_MICK_2_PIX    15
  819.  #define M_COND_OFF      16
  820.  #define M_D_SPEED       19
  821.  
  822.  #define XMAX            640
  823.  #define YMAX            200
  824.  
  825.  
  826.  main()
  827.  {
  828.      int m1, m2, m3, m4, m5;
  829.      int t, b, l, r;
  830.      int bounds[4];
  831.      int *bptr=bounds;
  832.  
  833.      cls();
  834.      chkdrv();
  835.  
  836.      m1 = M_RESET;
  837.      mouse(&m1, &m2, &m3, &m4);
  838.      if (m1)
  839.      {
  840.          printf("\nMouse driver installed, %d button mouse", m2);
  841.      }
  842.      else
  843.      {
  844.          printf("\nMouse driver not installed, exiting.");
  845.          return;
  846.      }
  847.  
  848.      test_graphics_cursor();
  849.  
  850.      m1 = M_SET_CURS;
  851.      m3 = XMAX;
  852.      m4 = YMAX/2;
  853.      mouse(&m1, &m2, &m3, &m4);
  854.  
  855.      m1 = M_SHOW_CURS;
  856.      mouse(&m1, &m2, &m3, &m4);
  857.  
  858.      printf("\nCursor should appear at end of middle line (press a key)...");
  859.      getch();
  860.  
  861.      t = 0;    b = YMAX;    l = 0;    r = XMAX;
  862.      do
  863.      {
  864.          circle(t, b, l, r);
  865.          t += 8;
  866.          b -= 8;
  867.          l += 8;
  868.          r -= 8;
  869.      }
  870.      while (t <= b);
  871.  
  872.      m1 = M_HIDE_CURS;
  873.      mouse(&m1, &m2, &m3, &m4);
  874.      cls();
  875.      m1 = M_SHOW_CURS;
  876.      mouse(&m1, &m2, &m3, &m4);
  877.  
  878.      printf("+----------------------------------------------------+\n");
  879.      printf("|  Test of conditional off function call.  Move the  |\n");
  880.      printf("|  cursor around, and verify that it disappears in   |\n");
  881.      printf("|  the area bounded by the dashed line.              |\n");
  882.      printf("|                                                    |\n");
  883.      printf("|  Press any key to redisplay the cursor.            |\n");
  884.      printf("|                                                    |\n");
  885.      printf("|  Press ESCape when verified.                       |\n");
  886.      printf("+----------------------------------------------------+\n");
  887.  
  888.      do
  889.      {
  890.          m1 = M_SET_CURS;
  891.          m3 = XMAX;
  892.          m4 = YMAX/2;
  893.          mouse(&m1, &m2, &m3, &m4);
  894.  
  895.          m1 = M_SHOW_CURS;
  896.          mouse(&m1, &m2, &m3, &m4);
  897.  
  898.          m1 = M_COND_OFF;
  899.          bounds[0] = 0;
  900.          bounds[1] = 0;
  901.          bounds[2] = 424;
  902.          bounds[3] = 64;
  903.          mouse(&m1, &m2, &m3, &bptr);
  904.      } while (getch() != 0x1B);
  905.  
  906.      m1 = M_SHOW_CURS;
  907.      mouse(&m1, &m2, &m3, &m4);
  908.  
  909.      read_pos();
  910.  
  911.      printf("\n\n\nPress a key to terminate this program");
  912.      getch();
  913.      m1 = M_RESET;
  914.      mouse(&m1, &m2, &m3, &m4);
  915.  }
  916.  
  917.  
  918.  chkdrv()
  919.  {
  920.      union REGS inregs, outregs;
  921.      struct SREGS segregs;
  922.      long address;
  923.      unsigned char first_byte;
  924.  
  925.      inregs.x.ax = 0x3533;
  926.      intdosx ( &inregs, &outregs, &segregs );
  927.  
  928.      address = (((long) segregs.es) << 16) + (long) outregs.x.bx;
  929.      first_byte = * (long far *) address;
  930.  
  931.      if ((address == 0) || (first_byte == 0xcf)) {
  932.          printf("Mouse driver NOT installed");
  933.          exit();
  934.          }
  935.  }
  936.  
  937.  
  938.  cls()
  939.  {
  940.      union REGS inregs, outregs;
  941.  
  942.      inregs.x.ax = 0x0600;
  943.      inregs.h.bh = 7;
  944.      inregs.x.cx = 0;
  945.      inregs.x.dx = 0x184f;
  946.      int86(0x10, &inregs, &outregs);
  947.      inregs.x.ax = 0x0200;
  948.      inregs.h.bh = 0;
  949.      inregs.x.dx = 0;
  950.      int86(0x10, &inregs, &outregs);
  951.  }
  952.  
  953.  
  954.  #define VWAIT 100
  955.  #define HWAIT 50
  956.  
  957.  circle (t, b, l, r)
  958.  int t, b, l, r;
  959.  {
  960.      int m1, m2, m3, m4, i;
  961.  
  962.      m1 = M_SET_CURS;
  963.      m4 = t;
  964.  
  965.      for (m3 = l; m3 < r; m3++)
  966.      {
  967.          for (i=0; i < HWAIT; i++);
  968.          mouse(&m1, &m2, &m3, &m4);
  969.      }
  970.  
  971.      for (m4 = t; m4 < b; m4++)
  972.      {
  973.          for (i=0; i < VWAIT; i++);
  974.          mouse(&m1, &m2, &m3, &m4);
  975.      }
  976.  
  977.      for (; m3 >= l; m3--)
  978.      {
  979.          for (i=0; i < HWAIT; i++);
  980.          mouse(&m1, &m2, &m3, &m4);
  981.      }
  982.  
  983.      for (; m4 >= t; m4--)
  984.      {
  985.          for (i=0; i < VWAIT; i++);
  986.          mouse(&m1, &m2, &m3, &m4);
  987.      }
  988.  }
  989.  
  990.  
  991.  read_pos()
  992.  {
  993.      int m1, m2, m3, m4;
  994.  
  995.      m1 = M_HIDE_CURS;
  996.      mouse(&m1, &m2, &m3, &m4);
  997.      cls();
  998.      m1 = M_SHOW_CURS;
  999.      mouse(&m1, &m2, &m3, &m4);
  1000.  
  1001.      printf("\nMove mouse to the UPPER LEFT corner, RELEASE both buttons");
  1002.      printf("\nand then press Enter: ");
  1003.      while(getch() != 0x0d)
  1004.          ;
  1005.      m1 = M_GET_STATUS;
  1006.      mouse(&m1, &m2, &m3, &m4);
  1007.      if (m2 != 0)        printf("\nBUTTON INFO WRONG.");
  1008.      if (m3 != 0)        printf("\nX VALUE WRONG, EXPECT 0, READ %d", m3);
  1009.      if (m4 != 0)        printf("\nY VALUE WRONG, EXPECT 0, READ %d", m4);
  1010.  
  1011.      printf("\nMove mouse to the BOTTOM RIGHT corner, PRESS both buttons");
  1012.      printf("\nand then press Enter: ");
  1013.      while(getch() != 0x0d)
  1014.          ;
  1015.      m1 = M_GET_STATUS;
  1016.      mouse(&m1, &m2, &m3, &m4);
  1017.      if (m2 != 3)        printf("\nBUTTON INFO WRONG.");
  1018.      if (m3 != 632)      printf("\nX VALUE WRONG, EXPECT 632, READ %d", m3);
  1019.      if (m4 != 192)      printf("\nY VALUE WRONG, EXPECT 192, READ %d", m4);
  1020.  }
  1021.  
  1022.  
  1023.  test_graphics_cursor()
  1024.  {
  1025.      static int cursor[32] =
  1026.      {
  1027.          /* SCREEN MASK FOR POINTING HAND */
  1028.  
  1029.          0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0, 0, 0,
  1030.          0, 0, 0, 0, 0, 0, 0, 0,
  1031.  
  1032.          /* CURSOR MASK FOR POINTING HAND */
  1033.  
  1034.          0x1E00, 0x1200, 0x1200, 0x1200, 0x1200, 0x13FF, 0x1249, 0x1249,
  1035.          0xF249, 0x9001, 0x9001, 0x9001, 0x8001, 0x8001, 0x8001, 0xFFFF
  1036.      };
  1037.  
  1038.      int *cptr=cursor;
  1039.  
  1040.      int m1, m2, m3, m4;
  1041.  
  1042.      video_mode(6);                      /* 640 X 200 B&W                */
  1043.  
  1044.      m1 = 9;
  1045.      m2 = 0;
  1046.      m3 = 0;
  1047.      mouse(&m1, &m2, &m3, &cptr);
  1048.      m1 = 1;
  1049.      mouse(&m1, &m2, &m3, &m4);
  1050.  
  1051.      printf("\ncursor should now be a pointing hand.");
  1052.      printf("\nMove around, press Enter when done...");
  1053.      getch();
  1054.      video_mode(3);
  1055.  }
  1056.  
  1057.  
  1058.  video_mode(mode)
  1059.  int mode;
  1060.  {
  1061.      union REGS inregs, outregs;
  1062.  
  1063.      inregs.h.ah = 0;
  1064.      inregs.h.al = mode;
  1065.      int86(0x10, &inregs, &outregs);
  1066.  }
  1067.  
  1068.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\LMCMOUSE.C
  1069.  
  1070.  /*----------------------------------------------------------------------*/
  1071.  /* REFERENCE -- Large model mouse drive interface test   IN  lmcmouse.c */
  1072.  /*                                                                      */
  1073.  /* To create lmcmouse.exe:                                              */
  1074.  /*                              MSC LMCMOUSE;                           */
  1075.  /*                              LINK LMCMOUSE+SUBS,,,..\MOUSE           */
  1076.  /*                      or:                                             */
  1077.  /*                              MAKE LMCMOUSE.MAK                       */
  1078.  /*                                                                      */
  1079.  /*----------------------------------------------------------------------*/
  1080.  #include <stdio.h>
  1081.  #include <dos.h>
  1082.  
  1083.  #define mouse(a, b, c, d)       cmousel(a, b, c, d)
  1084.  
  1085.  #define M_RESET         0
  1086.  #define M_SHOW_CURS     1
  1087.  #define M_HIDE_CURS     2
  1088.  #define M_GET_STATUS    3
  1089.  #define M_SET_CURS      4
  1090.  #define M_GET_PRESS     5
  1091.  #define M_GET_REL       6
  1092.  #define M_SET_MAX_POS   7
  1093.  #define M_SET_MIN_POS   8
  1094.  #define M_SET_G_CURS    9
  1095.  #define M_SET_T_CURS    10
  1096.  #define M_READ_COUNT    11
  1097.  #define M_USER_SUB      12
  1098.  #define M_LPEN_ON       13
  1099.  #define M_LPEN_OFF      14
  1100.  #define M_MICK_2_PIX    15
  1101.  #define M_COND_OFF      16
  1102.  #define M_D_SPEED       19
  1103.  
  1104.  #define XMAX            640
  1105.  #define YMAX            200
  1106.  
  1107.  
  1108.  main()
  1109.  {
  1110.      int m1, m2, m3, m4, m5;
  1111.      int t, b, l, r;
  1112.      int bounds[4];
  1113.      int *bptr=bounds;
  1114.  
  1115.      cls();
  1116.      chkdrv();
  1117.  
  1118.      m1 = M_RESET;
  1119.      mouse(&m1, &m2, &m3, &m4);
  1120.      if (m1)
  1121.      {
  1122.          printf("\nMouse driver installed, %d button mouse", m2);
  1123.      }
  1124.      else
  1125.      {
  1126.          printf("\nMouse driver not installed, exiting.");
  1127.          return;
  1128.      }
  1129.  
  1130.      test_graphics_cursor();
  1131.  
  1132.      m1 = M_SET_CURS;
  1133.      m3 = XMAX;
  1134.      m4 = YMAX/2;
  1135.      mouse(&m1, &m2, &m3, &m4);
  1136.  
  1137.      m1 = M_SHOW_CURS;
  1138.      mouse(&m1, &m2, &m3, &m4);
  1139.  
  1140.      printf("\nCursor should appear at end of middle line (press a key)...");
  1141.      getch();
  1142.  
  1143.      t = 0;    b = YMAX;    l = 0;    r = XMAX;
  1144.      do
  1145.      {
  1146.          circle(t, b, l, r);
  1147.          t += 8;
  1148.          b -= 8;
  1149.          l += 8;
  1150.          r -= 8;
  1151.      }
  1152.      while (t <= b);
  1153.  
  1154.      m1 = M_HIDE_CURS;
  1155.      mouse(&m1, &m2, &m3, &m4);
  1156.      cls();
  1157.      m1 = M_SHOW_CURS;
  1158.      mouse(&m1, &m2, &m3, &m4);
  1159.  
  1160.      printf("+----------------------------------------------------+\n");
  1161.      printf("|  Test of conditional off function call.  Move the  |\n");
  1162.      printf("|  cursor around, and verify that it disappears in   |\n");
  1163.      printf("|  the area bounded by the dashed line.              |\n");
  1164.      printf("|                                                    |\n");
  1165.      printf("|  Press any key to redisplay the cursor.            |\n");
  1166.      printf("|                                                    |\n");
  1167.      printf("|  Press ESCape when verified.                       |\n");
  1168.      printf("+----------------------------------------------------+\n");
  1169.  
  1170.      do
  1171.      {
  1172.          m1 = M_SET_CURS;
  1173.          m3 = XMAX;
  1174.          m4 = YMAX/2;
  1175.          mouse(&m1, &m2, &m3, &m4);
  1176.  
  1177.          m1 = M_SHOW_CURS;
  1178.          mouse(&m1, &m2, &m3, &m4);
  1179.  
  1180.          m1 = M_COND_OFF;
  1181.          bounds[0] = 0;
  1182.          bounds[1] = 0;
  1183.          bounds[2] = 424;
  1184.          bounds[3] = 64;
  1185.          mouse(&m1, &m2, &m3, &bptr);
  1186.      } while (getch() != 0x1B);
  1187.  
  1188.      m1 = M_SHOW_CURS;
  1189.      mouse(&m1, &m2, &m3, &m4);
  1190.  
  1191.      read_pos();
  1192.  
  1193.      printf("\n\n\nPress a key to terminate this program");
  1194.      getch();
  1195.      m1 = M_RESET;
  1196.      mouse(&m1, &m2, &m3, &m4);
  1197.  }
  1198.  
  1199.  
  1200.  chkdrv()
  1201.  {
  1202.      union REGS inregs, outregs;
  1203.      struct SREGS segregs;
  1204.      long address;
  1205.      unsigned char first_byte;
  1206.  
  1207.      inregs.x.ax = 0x3533;
  1208.      intdosx ( &inregs, &outregs, &segregs );
  1209.  
  1210.      address = (((long) segregs.es) << 16) + (long) outregs.x.bx;
  1211.      first_byte = * (long far *) address;
  1212.  
  1213.      if ((address == 0) || (first_byte == 0xcf)) {
  1214.          printf("Mouse driver NOT installed");
  1215.          exit();
  1216.          }
  1217.  }
  1218.  
  1219.  
  1220.  cls()
  1221.  {
  1222.      union REGS inregs, outregs;
  1223.  
  1224.      inregs.x.ax = 0x0600;
  1225.      inregs.h.bh = 7;
  1226.      inregs.x.cx = 0;
  1227.      inregs.x.dx = 0x184f;
  1228.      int86(0x10, &inregs, &outregs);
  1229.      inregs.x.ax = 0x0200;
  1230.      inregs.h.bh = 0;
  1231.      inregs.x.dx = 0;
  1232.      int86(0x10, &inregs, &outregs);
  1233.  }
  1234.  
  1235.  
  1236.  #define VWAIT 100
  1237.  #define HWAIT 50
  1238.  
  1239.  circle (t, b, l, r)
  1240.  int t, b, l, r;
  1241.  {
  1242.      int m1, m2, m3, m4, i;
  1243.  
  1244.      m1 = M_SET_CURS;
  1245.      m4 = t;
  1246.  
  1247.      for (m3 = l; m3 < r; m3++)
  1248.      {
  1249.          for (i=0; i < HWAIT; i++);
  1250.          mouse(&m1, &m2, &m3, &m4);
  1251.      }
  1252.  
  1253.      for (m4 = t; m4 < b; m4++)
  1254.      {
  1255.          for (i=0; i < VWAIT; i++);
  1256.          mouse(&m1, &m2, &m3, &m4);
  1257.      }
  1258.  
  1259.      for (; m3 >= l; m3--)
  1260.      {
  1261.          for (i=0; i < HWAIT; i++);
  1262.          mouse(&m1, &m2, &m3, &m4);
  1263.      }
  1264.  
  1265.      for (; m4 >= t; m4--)
  1266.      {
  1267.          for (i=0; i < VWAIT; i++);
  1268.          mouse(&m1, &m2, &m3, &m4);
  1269.      }
  1270.  }
  1271.  
  1272.  
  1273.  read_pos()
  1274.  {
  1275.      int m1, m2, m3, m4;
  1276.  
  1277.      m1 = M_HIDE_CURS;
  1278.      mouse(&m1, &m2, &m3, &m4);
  1279.      cls();
  1280.      m1 = M_SHOW_CURS;
  1281.      mouse(&m1, &m2, &m3, &m4);
  1282.  
  1283.      printf("\nMove mouse to the UPPER LEFT corner, RELEASE both buttons");
  1284.      printf("\nand then press Enter: ");
  1285.      while(getch() != 0x0d)
  1286.          ;
  1287.      m1 = M_GET_STATUS;
  1288.      mouse(&m1, &m2, &m3, &m4);
  1289.      if (m2 != 0)        printf("\nBUTTON INFO WRONG.");
  1290.      if (m3 != 0)        printf("\nX VALUE WRONG, EXPECT 0, READ %d", m3);
  1291.      if (m4 != 0)        printf("\nY VALUE WRONG, EXPECT 0, READ %d", m4);
  1292.  
  1293.      printf("\nMove mouse to the BOTTOM RIGHT corner, PRESS both buttons");
  1294.      printf("\nand then press Enter: ");
  1295.      while(getch() != 0x0d)
  1296.          ;
  1297.      m1 = M_GET_STATUS;
  1298.      mouse(&m1, &m2, &m3, &m4);
  1299.      if (m2 != 3)        printf("\nBUTTON INFO WRONG.");
  1300.      if (m3 != 632)      printf("\nX VALUE WRONG, EXPECT 632, READ %d", m3);
  1301.      if (m4 != 192)      printf("\nY VALUE WRONG, EXPECT 192, READ %d", m4);
  1302.  }
  1303.  
  1304.  
  1305.  test_graphics_cursor()
  1306.  {
  1307.      static int cursor[32] =
  1308.      {
  1309.          /* SCREEN MASK FOR POINTING HAND */
  1310.  
  1311.          0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0, 0, 0,
  1312.          0, 0, 0, 0, 0, 0, 0, 0,
  1313.  
  1314.          /* CURSOR MASK FOR POINTING HAND */
  1315.  
  1316.          0x1E00, 0x1200, 0x1200, 0x1200, 0x1200, 0x13FF, 0x1249, 0x1249,
  1317.          0xF249, 0x9001, 0x9001, 0x9001, 0x8001, 0x8001, 0x8001, 0xFFFF
  1318.      };
  1319.  
  1320.      int *cptr=cursor;
  1321.  
  1322.      int m1, m2, m3, m4;
  1323.  
  1324.      video_mode(6);                      /* 640 X 200 B&W                */
  1325.  
  1326.      m1 = 9;
  1327.      m2 = 0;
  1328.      m3 = 0;
  1329.      mouse(&m1, &m2, &m3, &cptr);
  1330.      m1 = 1;
  1331.      mouse(&m1, &m2, &m3, &m4);
  1332.  
  1333.      printf("\ncursor should now be a pointing hand.");
  1334.      printf("\nMove around, press Enter when done...");
  1335.      getch();
  1336.      video_mode(3);
  1337.  }
  1338.  
  1339.  
  1340.  video_mode(mode)
  1341.  int mode;
  1342.  {
  1343.      union REGS inregs, outregs;
  1344.  
  1345.      inregs.h.ah = 0;
  1346.      inregs.h.al = mode;
  1347.      int86(0x10, &inregs, &outregs);
  1348.  }
  1349.  
  1350.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\MMCMOUSE.C
  1351.  
  1352.  /*----------------------------------------------------------------------*/
  1353.  /* REFERENCE -- Medium model mouse drive interface test   IN mmcmouse.c */
  1354.  /*                                                                      */
  1355.  /* To create mmcmouse.exe:                                              */
  1356.  /*                              MSC MMCMOUSE;                           */
  1357.  /*                              LINK MMCMOUSE+SUBS,,,..\MOUSE           */
  1358.  /*                      or:                                             */
  1359.  /*                              MAKE MMCMOUSE.MAK                       */
  1360.  /*                                                                      */
  1361.  /*----------------------------------------------------------------------*/
  1362.  #include <stdio.h>
  1363.  #include <dos.h>
  1364.  
  1365.  #define mouse(a, b, c, d)       cmousem(a, b, c, d)
  1366.  
  1367.  #define M_RESET         0
  1368.  #define M_SHOW_CURS     1
  1369.  #define M_HIDE_CURS     2
  1370.  #define M_GET_STATUS    3
  1371.  #define M_SET_CURS      4
  1372.  #define M_GET_PRESS     5
  1373.  #define M_GET_REL       6
  1374.  #define M_SET_MAX_POS   7
  1375.  #define M_SET_MIN_POS   8
  1376.  #define M_SET_G_CURS    9
  1377.  #define M_SET_T_CURS    10
  1378.  #define M_READ_COUNT    11
  1379.  #define M_USER_SUB      12
  1380.  #define M_LPEN_ON       13
  1381.  #define M_LPEN_OFF      14
  1382.  #define M_MICK_2_PIX    15
  1383.  #define M_COND_OFF      16
  1384.  #define M_D_SPEED       19
  1385.  
  1386.  #define XMAX            640
  1387.  #define YMAX            200
  1388.  
  1389.  
  1390.  main()
  1391.  {
  1392.      int m1, m2, m3, m4, m5;
  1393.      int t, b, l, r;
  1394.      int bounds[4];
  1395.      int *bptr=bounds;
  1396.  
  1397.      cls();
  1398.      chkdrv();
  1399.  
  1400.      m1 = M_RESET;
  1401.      mouse(&m1, &m2, &m3, &m4);
  1402.      if (m1)
  1403.      {
  1404.          printf("\nMouse driver installed, %d button mouse", m2);
  1405.      }
  1406.      else
  1407.      {
  1408.          printf("\nMouse driver not installed, exiting.");
  1409.          return;
  1410.      }
  1411.  
  1412.      test_graphics_cursor();
  1413.  
  1414.      m1 = M_SET_CURS;
  1415.      m3 = XMAX;
  1416.      m4 = YMAX/2;
  1417.      mouse(&m1, &m2, &m3, &m4);
  1418.  
  1419.      m1 = M_SHOW_CURS;
  1420.      mouse(&m1, &m2, &m3, &m4);
  1421.  
  1422.      printf("\nCursor should appear at end of middle line (press a key)...");
  1423.      getch();
  1424.  
  1425.      t = 0;    b = YMAX;    l = 0;    r = XMAX;
  1426.      do
  1427.      {
  1428.          circle(t, b, l, r);
  1429.          t += 8;
  1430.          b -= 8;
  1431.          l += 8;
  1432.          r -= 8;
  1433.      }
  1434.      while (t <= b);
  1435.  
  1436.      m1 = M_HIDE_CURS;
  1437.      mouse(&m1, &m2, &m3, &m4);
  1438.      cls();
  1439.      m1 = M_SHOW_CURS;
  1440.      mouse(&m1, &m2, &m3, &m4);
  1441.  
  1442.      printf("+----------------------------------------------------+\n");
  1443.      printf("|  Test of conditional off function call.  Move the  |\n");
  1444.      printf("|  cursor around, and verify that it disappears in   |\n");
  1445.      printf("|  the area bounded by the dashed line.              |\n");
  1446.      printf("|                                                    |\n");
  1447.      printf("|  Press any key to redisplay the cursor.            |\n");
  1448.      printf("|                                                    |\n");
  1449.      printf("|  Press ESCape when verified.                       |\n");
  1450.      printf("+----------------------------------------------------+\n");
  1451.  
  1452.      do
  1453.      {
  1454.          m1 = M_SET_CURS;
  1455.          m3 = XMAX;
  1456.          m4 = YMAX/2;
  1457.          mouse(&m1, &m2, &m3, &m4);
  1458.  
  1459.          m1 = M_SHOW_CURS;
  1460.          mouse(&m1, &m2, &m3, &m4);
  1461.  
  1462.          m1 = M_COND_OFF;
  1463.          bounds[0] = 0;
  1464.          bounds[1] = 0;
  1465.          bounds[2] = 424;
  1466.          bounds[3] = 64;
  1467.          mouse(&m1, &m2, &m3, &bptr);
  1468.      } while (getch() != 0x1B);
  1469.  
  1470.      m1 = M_SHOW_CURS;
  1471.      mouse(&m1, &m2, &m3, &m4);
  1472.  
  1473.      read_pos();
  1474.  
  1475.      printf("\n\n\nPress a key to terminate this program");
  1476.      getch();
  1477.      m1 = M_RESET;
  1478.      mouse(&m1, &m2, &m3, &m4);
  1479.  }
  1480.  
  1481.  
  1482.  chkdrv()
  1483.  {
  1484.      union REGS inregs, outregs;
  1485.      struct SREGS segregs;
  1486.      long address;
  1487.      unsigned char first_byte;
  1488.  
  1489.      inregs.x.ax = 0x3533;
  1490.      intdosx ( &inregs, &outregs, &segregs );
  1491.  
  1492.      address = (((long) segregs.es) << 16) + (long) outregs.x.bx;
  1493.      first_byte = * (long far *) address;
  1494.  
  1495.      if ((address == 0) || (first_byte == 0xcf)) {
  1496.          printf("Mouse driver NOT installed");
  1497.          exit();
  1498.          }
  1499.  }
  1500.  
  1501.  
  1502.  cls()
  1503.  {
  1504.      union REGS inregs, outregs;
  1505.  
  1506.      inregs.x.ax = 0x0600;
  1507.      inregs.h.bh = 7;
  1508.      inregs.x.cx = 0;
  1509.      inregs.x.dx = 0x184f;
  1510.      int86(0x10, &inregs, &outregs);
  1511.      inregs.x.ax = 0x0200;
  1512.      inregs.h.bh = 0;
  1513.      inregs.x.dx = 0;
  1514.      int86(0x10, &inregs, &outregs);
  1515.  }
  1516.  
  1517.  
  1518.  #define VWAIT 100
  1519.  #define HWAIT 50
  1520.  
  1521.  circle (t, b, l, r)
  1522.  int t, b, l, r;
  1523.  {
  1524.      int m1, m2, m3, m4, i;
  1525.  
  1526.      m1 = M_SET_CURS;
  1527.      m4 = t;
  1528.  
  1529.      for (m3 = l; m3 < r; m3++)
  1530.      {
  1531.          for (i=0; i < HWAIT; i++);
  1532.          mouse(&m1, &m2, &m3, &m4);
  1533.      }
  1534.  
  1535.      for (m4 = t; m4 < b; m4++)
  1536.      {
  1537.          for (i=0; i < VWAIT; i++);
  1538.          mouse(&m1, &m2, &m3, &m4);
  1539.      }
  1540.  
  1541.      for (; m3 >= l; m3--)
  1542.      {
  1543.          for (i=0; i < HWAIT; i++);
  1544.          mouse(&m1, &m2, &m3, &m4);
  1545.      }
  1546.  
  1547.      for (; m4 >= t; m4--)
  1548.      {
  1549.          for (i=0; i < VWAIT; i++);
  1550.          mouse(&m1, &m2, &m3, &m4);
  1551.      }
  1552.  }
  1553.  
  1554.  
  1555.  read_pos()
  1556.  {
  1557.      int m1, m2, m3, m4;
  1558.  
  1559.      m1 = M_HIDE_CURS;
  1560.      mouse(&m1, &m2, &m3, &m4);
  1561.      cls();
  1562.      m1 = M_SHOW_CURS;
  1563.      mouse(&m1, &m2, &m3, &m4);
  1564.  
  1565.      printf("\nMove mouse to the UPPER LEFT corner, RELEASE both buttons");
  1566.      printf("\nand then press Enter: ");
  1567.      while(getch() != 0x0d)
  1568.          ;
  1569.      m1 = M_GET_STATUS;
  1570.      mouse(&m1, &m2, &m3, &m4);
  1571.      if (m2 != 0)        printf("\nBUTTON INFO WRONG.");
  1572.      if (m3 != 0)        printf("\nX VALUE WRONG, EXPECT 0, READ %d", m3);
  1573.      if (m4 != 0)        printf("\nY VALUE WRONG, EXPECT 0, READ %d", m4);
  1574.  
  1575.      printf("\nMove mouse to the BOTTOM RIGHT corner, PRESS both buttons");
  1576.      printf("\nand then press Enter: ");
  1577.      while(getch() != 0x0d)
  1578.          ;
  1579.      m1 = M_GET_STATUS;
  1580.      mouse(&m1, &m2, &m3, &m4);
  1581.      if (m2 != 3)        printf("\nBUTTON INFO WRONG.");
  1582.      if (m3 != 632)      printf("\nX VALUE WRONG, EXPECT 632, READ %d", m3);
  1583.      if (m4 != 192)      printf("\nY VALUE WRONG, EXPECT 192, READ %d", m4);
  1584.  }
  1585.  
  1586.  
  1587.  test_graphics_cursor()
  1588.  {
  1589.      static int cursor[32] =
  1590.      {
  1591.          /* SCREEN MASK FOR POINTING HAND */
  1592.  
  1593.          0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0, 0, 0,
  1594.          0, 0, 0, 0, 0, 0, 0, 0,
  1595.  
  1596.          /* CURSOR MASK FOR POINTING HAND */
  1597.  
  1598.          0x1E00, 0x1200, 0x1200, 0x1200, 0x1200, 0x13FF, 0x1249, 0x1249,
  1599.          0xF249, 0x9001, 0x9001, 0x9001, 0x8001, 0x8001, 0x8001, 0xFFFF
  1600.      };
  1601.  
  1602.      int *cptr=cursor;
  1603.  
  1604.      int m1, m2, m3, m4;
  1605.  
  1606.      video_mode(6);                      /* 640 X 200 B&W                */
  1607.  
  1608.      m1 = 9;
  1609.      m2 = 0;
  1610.      m3 = 0;
  1611.      mouse(&m1, &m2, &m3, &cptr);
  1612.      m1 = 1;
  1613.      mouse(&m1, &m2, &m3, &m4);
  1614.  
  1615.      printf("\ncursor should now be a pointing hand.");
  1616.      printf("\nMove around, press Enter when done...");
  1617.      getch();
  1618.      video_mode(3);
  1619.  }
  1620.  
  1621.  
  1622.  video_mode(mode)
  1623.  int mode;
  1624.  {
  1625.      union REGS inregs, outregs;
  1626.  
  1627.      inregs.h.ah = 0;
  1628.      inregs.h.al = mode;
  1629.      int86(0x10, &inregs, &outregs);
  1630.  }
  1631.  
  1632.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\SMCMOUSE.C
  1633.  
  1634.  /*----------------------------------------------------------------------*/
  1635.  /* REFERENCE -- Small model mouse drive interface test   IN  smcmouse.c */
  1636.  /*                                                                      */
  1637.  /* To create smcmouse.exe:                                              */
  1638.  /*                              MSC SMCMOUSE;                           */
  1639.  /*                              LINK SMCMOUSE+SUBS,,,..\MOUSE           */
  1640.  /*                      or:                                             */
  1641.  /*                              MAKE SMCMOUSE.MAK                       */
  1642.  /*                                                                      */
  1643.  /*----------------------------------------------------------------------*/
  1644.  #include <stdio.h>
  1645.  #include <dos.h>
  1646.  
  1647.  #define mouse(a, b, c, d)       cmouses(a, b, c, d)
  1648.  
  1649.  #define M_RESET         0
  1650.  #define M_SHOW_CURS     1
  1651.  #define M_HIDE_CURS     2
  1652.  #define M_GET_STATUS    3
  1653.  #define M_SET_CURS      4
  1654.  #define M_GET_PRESS     5
  1655.  #define M_GET_REL       6
  1656.  #define M_SET_MAX_POS   7
  1657.  #define M_SET_MIN_POS   8
  1658.  #define M_SET_G_CURS    9
  1659.  #define M_SET_T_CURS    10
  1660.  #define M_READ_COUNT    11
  1661.  #define M_USER_SUB      12
  1662.  #define M_LPEN_ON       13
  1663.  #define M_LPEN_OFF      14
  1664.  #define M_MICK_2_PIX    15
  1665.  #define M_COND_OFF      16
  1666.  #define M_D_SPEED       19
  1667.  
  1668.  #define XMAX            640
  1669.  #define YMAX            200
  1670.  
  1671.  
  1672.  main()
  1673.  {
  1674.      int m1, m2, m3, m4, m5;
  1675.      int t, b, l, r;
  1676.      int bounds[4];
  1677.      int *bptr=bounds;
  1678.  
  1679.      cls();
  1680.      chkdrv();
  1681.  
  1682.      m1 = M_RESET;
  1683.      mouse(&m1, &m2, &m3, &m4);
  1684.      if (m1)
  1685.      {
  1686.          printf("\nMouse driver installed, %d button mouse", m2);
  1687.      }
  1688.      else
  1689.      {
  1690.          printf("\nMouse driver not installed, exiting.");
  1691.          return;
  1692.      }
  1693.  
  1694.      test_graphics_cursor();
  1695.  
  1696.      m1 = M_SET_CURS;
  1697.      m3 = XMAX;
  1698.      m4 = YMAX/2;
  1699.      mouse(&m1, &m2, &m3, &m4);
  1700.  
  1701.      m1 = M_SHOW_CURS;
  1702.      mouse(&m1, &m2, &m3, &m4);
  1703.  
  1704.      printf("\nCursor should appear at end of middle line (press a key)...");
  1705.      getch();
  1706.  
  1707.      t = 0;    b = YMAX;    l = 0;    r = XMAX;
  1708.      do
  1709.      {
  1710.          circle(t, b, l, r);
  1711.          t += 8;
  1712.          b -= 8;
  1713.          l += 8;
  1714.          r -= 8;
  1715.      }
  1716.      while (t <= b);
  1717.  
  1718.      m1 = M_HIDE_CURS;
  1719.      mouse(&m1, &m2, &m3, &m4);
  1720.      cls();
  1721.      m1 = M_SHOW_CURS;
  1722.      mouse(&m1, &m2, &m3, &m4);
  1723.  
  1724.      printf("+----------------------------------------------------+\n");
  1725.      printf("|  Test of conditional off function call.  Move the  |\n");
  1726.      printf("|  cursor around, and verify that it disappears in   |\n");
  1727.      printf("|  the area bounded by the dashed line.              |\n");
  1728.      printf("|                                                    |\n");
  1729.      printf("|  Press any key to redisplay the cursor.            |\n");
  1730.      printf("|                                                    |\n");
  1731.      printf("|  Press ESCape when verified.                       |\n");
  1732.      printf("+----------------------------------------------------+\n");
  1733.  
  1734.      do
  1735.      {
  1736.          m1 = M_SET_CURS;
  1737.          m3 = XMAX;
  1738.          m4 = YMAX/2;
  1739.          mouse(&m1, &m2, &m3, &m4);
  1740.  
  1741.          m1 = M_SHOW_CURS;
  1742.          mouse(&m1, &m2, &m3, &m4);
  1743.  
  1744.          m1 = M_COND_OFF;
  1745.          bounds[0] = 0;
  1746.          bounds[1] = 0;
  1747.          bounds[2] = 424;
  1748.          bounds[3] = 64;
  1749.          mouse(&m1, &m2, &m3, &bptr);
  1750.      } while (getch() != 0x1B);
  1751.  
  1752.      m1 = M_SHOW_CURS;
  1753.      mouse(&m1, &m2, &m3, &m4);
  1754.  
  1755.      read_pos();
  1756.  
  1757.      printf("\n\n\nPress a key to terminate this program");
  1758.      getch();
  1759.      m1 = M_RESET;
  1760.      mouse(&m1, &m2, &m3, &m4);
  1761.  }
  1762.  
  1763.  
  1764.  chkdrv()
  1765.  {
  1766.      union REGS inregs, outregs;
  1767.      struct SREGS segregs;
  1768.      long address;
  1769.      unsigned char first_byte;
  1770.  
  1771.      inregs.x.ax = 0x3533;
  1772.      intdosx ( &inregs, &outregs, &segregs );
  1773.  
  1774.      address = (((long) segregs.es) << 16) + (long) outregs.x.bx;
  1775.      first_byte = * (long far *) address;
  1776.  
  1777.      if ((address == 0) || (first_byte == 0xcf)) {
  1778.          printf("Mouse driver NOT installed");
  1779.          exit();
  1780.          }
  1781.  }
  1782.  
  1783.  
  1784.  cls()
  1785.  {
  1786.      union REGS inregs, outregs;
  1787.  
  1788.      inregs.x.ax = 0x0600;
  1789.      inregs.h.bh = 7;
  1790.      inregs.x.cx = 0;
  1791.      inregs.x.dx = 0x184f;
  1792.      int86(0x10, &inregs, &outregs);
  1793.      inregs.x.ax = 0x0200;
  1794.      inregs.h.bh = 0;
  1795.      inregs.x.dx = 0;
  1796.      int86(0x10, &inregs, &outregs);
  1797.  }
  1798.  
  1799.  
  1800.  #define VWAIT 100
  1801.  #define HWAIT 50
  1802.  
  1803.  circle (t, b, l, r)
  1804.  int t, b, l, r;
  1805.  {
  1806.      int m1, m2, m3, m4, i;
  1807.  
  1808.      m1 = M_SET_CURS;
  1809.      m4 = t;
  1810.  
  1811.      for (m3 = l; m3 < r; m3++)
  1812.      {
  1813.          for (i=0; i < HWAIT; i++);
  1814.          mouse(&m1, &m2, &m3, &m4);
  1815.      }
  1816.  
  1817.      for (m4 = t; m4 < b; m4++)
  1818.      {
  1819.          for (i=0; i < VWAIT; i++);
  1820.          mouse(&m1, &m2, &m3, &m4);
  1821.      }
  1822.  
  1823.      for (; m3 >= l; m3--)
  1824.      {
  1825.          for (i=0; i < HWAIT; i++);
  1826.          mouse(&m1, &m2, &m3, &m4);
  1827.      }
  1828.  
  1829.      for (; m4 >= t; m4--)
  1830.      {
  1831.          for (i=0; i < VWAIT; i++);
  1832.          mouse(&m1, &m2, &m3, &m4);
  1833.      }
  1834.  }
  1835.  
  1836.  
  1837.  read_pos()
  1838.  {
  1839.      int m1, m2, m3, m4;
  1840.  
  1841.      m1 = M_HIDE_CURS;
  1842.      mouse(&m1, &m2, &m3, &m4);
  1843.      cls();
  1844.      m1 = M_SHOW_CURS;
  1845.      mouse(&m1, &m2, &m3, &m4);
  1846.  
  1847.      printf("\nMove mouse to the UPPER LEFT corner, RELEASE both buttons");
  1848.      printf("\nand then press Enter: ");
  1849.      while(getch() != 0x0d)
  1850.          ;
  1851.      m1 = M_GET_STATUS;
  1852.      mouse(&m1, &m2, &m3, &m4);
  1853.      if (m2 != 0)        printf("\nBUTTON INFO WRONG.");
  1854.      if (m3 != 0)        printf("\nX VALUE WRONG, EXPECT 0, READ %d", m3);
  1855.      if (m4 != 0)        printf("\nY VALUE WRONG, EXPECT 0, READ %d", m4);
  1856.  
  1857.      printf("\nMove mouse to the BOTTOM RIGHT corner, PRESS both buttons");
  1858.      printf("\nand then press Enter: ");
  1859.      while(getch() != 0x0d)
  1860.          ;
  1861.      m1 = M_GET_STATUS;
  1862.      mouse(&m1, &m2, &m3, &m4);
  1863.      if (m2 != 3)        printf("\nBUTTON INFO WRONG.");
  1864.      if (m3 != 632)      printf("\nX VALUE WRONG, EXPECT 632, READ %d", m3);
  1865.      if (m4 != 192)      printf("\nY VALUE WRONG, EXPECT 192, READ %d", m4);
  1866.  }
  1867.  
  1868.  
  1869.  test_graphics_cursor()
  1870.  {
  1871.      static int cursor[32] =
  1872.      {
  1873.          /* SCREEN MASK FOR POINTING HAND */
  1874.  
  1875.          0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0xE1FF, 0, 0, 0,
  1876.          0, 0, 0, 0, 0, 0, 0, 0,
  1877.  
  1878.          /* CURSOR MASK FOR POINTING HAND */
  1879.  
  1880.          0x1E00, 0x1200, 0x1200, 0x1200, 0x1200, 0x13FF, 0x1249, 0x1249,
  1881.          0xF249, 0x9001, 0x9001, 0x9001, 0x8001, 0x8001, 0x8001, 0xFFFF
  1882.      };
  1883.  
  1884.      int *cptr=cursor;
  1885.  
  1886.      int m1, m2, m3, m4;
  1887.  
  1888.      video_mode(6);                      /* 640 X 200 B&W                */
  1889.  
  1890.      m1 = 9;
  1891.      m2 = 0;
  1892.      m3 = 0;
  1893.      mouse(&m1, &m2, &m3, &cptr);
  1894.      m1 = 1;
  1895.      mouse(&m1, &m2, &m3, &m4);
  1896.  
  1897.      printf("\ncursor should now be a pointing hand.");
  1898.      printf("\nMove around, press Enter when done...");
  1899.      getch();
  1900.      video_mode(3);
  1901.  }
  1902.  
  1903.  
  1904.  video_mode(mode)
  1905.  int mode;
  1906.  {
  1907.      union REGS inregs, outregs;
  1908.  
  1909.      inregs.h.ah = 0;
  1910.      inregs.h.al = mode;
  1911.      int86(0x10, &inregs, &outregs);
  1912.  }
  1913.  
  1914.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\SUBS.ASM
  1915.  
  1916.  ;
  1917.  ;
  1918.  ; This is the subroutine for mouse.lib test in FORTRAN
  1919.  ; and Pascal examples.  Procedure graf sets the screen
  1920.  ; video mode into hi-res graphics.
  1921.  ;
  1922.  ;
  1923.  ;
  1924.  mdata           segment byte public 'data'
  1925.  
  1926.                  msg     db   "Mouse Driver NOT installed","$"
  1927.  
  1928.  mdata           ends
  1929.  
  1930.  
  1931.  
  1932.  
  1933.  mcode           segment para public 'CODE'
  1934.                  assume  cs:mcode
  1935.  ;
  1936.                  public  graf
  1937.  ;
  1938.  graf            proc    far
  1939.                  push    bp
  1940.                  mov     ax, 06h                 ;change to graphics
  1941.                  int     10h                     ;mode by calling
  1942.                  pop     bp                      ;int 10 service
  1943.                  ret
  1944.  graf            endp
  1945.  ;
  1946.  ;
  1947.  ;
  1948.                  public  chkdrv
  1949.  ;
  1950.  chkdrv          proc    far
  1951.                  push    bp
  1952.                  push    es
  1953.  
  1954.                  mov     ax, 03533h              ;get int 33h
  1955.                  int     21h                     ;by calling int 21
  1956.                  mov     ax, es                  ;check segment and
  1957.                  or      ax, bx                  ;offset of int 33
  1958.                  jnz     back                    ;vector if 0 or IRET
  1959.                  mov     bl, es:[bx]             ;mouse driver not installed
  1960.                  cmp     bl, 0cfh
  1961.                  jne     back                    ;exit
  1962.  
  1963.                  mov     ax,seg mdata            ;set up DS to
  1964.                  mov     ds,ax                   ;point to data seg
  1965.                  mov     dx, offset msg          ;get message
  1966.                  mov     ah, 09h                 ;out to screen
  1967.                  int     21h
  1968.                  pop     es
  1969.                  pop     bp
  1970.                  mov     ax,04c00h               ;function code for
  1971.                  int     21h                     ;end process
  1972.  
  1973.          back:
  1974.                  pop     es
  1975.                  pop     bp
  1976.                  ret
  1977.  chkdrv          endp
  1978.  ;
  1979.  mcode           ends
  1980.                  end
  1981.  
  1982.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\PDEMO.PAS
  1983.  
  1984.  program mtest(output);
  1985.  
  1986.  procedure mouses(vars m1,m2,m3,m4:word);extern;
  1987.  procedure chkdrv;extern;
  1988.  procedure graf;extern;
  1989.  
  1990.  var
  1991.    m1,m2,m3,m4:word;
  1992.    Cursor : array [0..31]of word;
  1993.    bound  : array [0..3] of word;
  1994.    ptradd : array [1..2] of word;
  1995.    i, j : integer;
  1996.  
  1997.  begin
  1998.  
  1999.    for i := 0 to 15  do cursor[i] := 16#ffff;
  2000.    Cursor[16] := 16#8000;
  2001.    Cursor[17] := 16#E000;
  2002.    Cursor[18] := 16#F800;
  2003.    Cursor[19] := 16#FE00;  {initialize curosr array}
  2004.    Cursor[20] := 16#D800;
  2005.    Cursor[21] := 16#0C00;
  2006.    Cursor[22] := 16#0600;
  2007.    Cursor[23] := 16#0300;
  2008.    for j := 24 to 31 do Cursor[j] := 16#0000;
  2009.  
  2010.    chkdrv;                           {Check for mouse     }
  2011.                                      { driver installation}
  2012.    m1:=0;                            {Function call 0     }
  2013.    mouses(m1,m2,m3,m4);              {initialize mouse    }
  2014.    if ( m1 = 0 ) then                {No, output message  }
  2015.       writeln('Microsoft mouse NOT found')
  2016.    else
  2017.       begin                          {Yes, demo function 9}
  2018.                                      { and funciton 16    }
  2019.         graf;                        {set to graphics mode}
  2020.  
  2021.         m1:=9;                       {Function call 9     }
  2022.         m2:=1;                       { set graphics cursor}
  2023.         m3:=1;
  2024.         ptradd[1] := (ads Cursor).r; {offset  of the array}
  2025.         ptradd[2] := (ads Cursor).s; {segment of the array}
  2026.         mouses(m1,m2,m3,ptradd[1]);
  2027.  
  2028.         writeln('Mouse cursor will disappear within this area.');
  2029.         writeln('Press the right mouse button to EXIT.........');
  2030.  
  2031.         m1:=1;                       {Function call 1     }
  2032.         mouses(m1,m2,m3,m4);         { show mouse cursor  }
  2033.  
  2034.         m1 := 16;                    {Function call 16    }
  2035.         bound[0] := 0;               {left  x coordinate  }
  2036.         bound[1] := 0;               {upper y coordinate  }
  2037.         bound[2] := 390;             {right x coordinate  }
  2038.         bound[3] := 25;              {lower y coordinate  }
  2039.         ptradd[1] := (ads bound).r;  {offset  of the array}
  2040.         ptradd[2] := (ads bound).s;  {segment of the array}
  2041.         mouses(m1,m2,m3,ptradd[1]);
  2042.  
  2043.         m2 := 999;                   {dummy value for loop}
  2044.         repeat                       {until .             }
  2045.           m1 := 3;                   {Function call 3, get}
  2046.           mouses( m1, m2, m3, m4 );  {current mouse status}
  2047.         until m2 = 2;                {left button pressed }
  2048.  
  2049.       end
  2050.  end.
  2051.  
  2052.  
  2053.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\BDEMO.BAS
  2054.  
  2055.  ' Mouse library call test in Quick Basic V2.0
  2056.  
  2057.    DIM cursor% (32), cond% (4)
  2058.  
  2059.    cursor%(1) =&hf87f   ' initilize data for function call #9
  2060.    cursor%(2) =&h0741
  2061.    cursor%(3) =&hcf9f
  2062.    cursor%(4) =&h9fc7
  2063.    cursor%(5) =&h0f81
  2064.    cursor%(6) =&h77be
  2065.    cursor%(7) =&h0fce
  2066.    cursor%(8) =&h8fdf
  2067.    cursor%(9) =&hbfe3
  2068.    cursor%(10)=&h9ff9
  2069.    cursor%(11)=&hc3f9
  2070.    cursor%(12)=&hfc01
  2071.    cursor%(13)=&hf7fe
  2072.    cursor%(14)=&h0ffe
  2073.    cursor%(15)=&hf87e
  2074.    cursor%(16)=&hff83
  2075.    cursor%(17)=&h0780
  2076.    cursor%(18)=&hf8be
  2077.    cursor%(19)=&h3060
  2078.    cursor%(20)=&h6038
  2079.    cursor%(21)=&hf07e
  2080.    cursor%(22)=&h8841
  2081.    cursor%(23)=&hf031
  2082.    cursor%(24)=&h7020
  2083.    cursor%(25)=&h401c
  2084.    cursor%(26)=&h6006
  2085.    cursor%(27)=&h3c06
  2086.    cursor%(28)=&h03fe
  2087.    cursor%(29)=&h0001
  2088.    cursor%(30)=&hf001
  2089.    cursor%(31)=&h0781
  2090.    cursor%(32)=&h007c
  2091.  
  2092.  
  2093.    call chkdrv                 ' Check for driver install
  2094.  
  2095.    m1%=0                       ' Function 0
  2096.    call mouse(m1%,m2%,m3%,m4%) ' initialize mouse
  2097.    if ( M1% = 0 ) then
  2098.       print "Microsoft Mouse not found"
  2099.       end
  2100.    end if
  2101.  
  2102.    screen 2                     ' Grahpics screen mode
  2103.  
  2104.    m1%=9                        ' Function call 9
  2105.    m2%=1
  2106.    m3%=1
  2107.    m4%=VARPTR(cursor%(1))       ' Pointer to currsor array
  2108.    call mouse(m1%, m2%, m3%, m4%)
  2109.  
  2110.    print "Mouse cursor will disappear within this area."
  2111.    print "Press right button to EXIT..................."
  2112.  
  2113.    m1% = 1
  2114.    call mouse(m1%,m2%,m3%,m4%)
  2115.  
  2116.    m1%=16
  2117.    cond%(1) = 0
  2118.    cond%(2) = 0
  2119.    cond%(3) = 390
  2120.    cond%(4) = 25
  2121.    m4%=VARPTR(cond%(1))
  2122.    call mouse(m1%,m2%,m3%,m4%)
  2123.  
  2124.    m2% = 99
  2125.    while ( m2% <> 2 )
  2126.      m1% = 3
  2127.      call mouse(m1%,m2%,m3%,m4%)
  2128.    wend
  2129.  
  2130.    screen 0
  2131.  
  2132.    end
  2133.  
  2134.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\IBMOUSE.BAS
  2135.  
  2136.  1000  ' REFERENCE test of mouse/interpretive BASIC interface    IN ibmouse.ba
  2137.  1010  '
  2138.  1020  ' This program is intended to test the parameter passing from interpret
  2139.  1030  ' BASIC to the mouse driver.
  2140.  1040  '
  2141.  1050  ' Note:  This program is written for interpretive BASIC.  Do not attemp
  2142.  1060  ' attempt to run it using compiled BASIC.
  2143.  1070  '
  2144.  1080 DEF SEG = 0
  2145.  1090 MSEG = 256*PEEK(51*4+3)+PEEK(51*4+2)
  2146.  1100 MOUSE = 256*PEEK(51*4+1)+PEEK(51*4)+2
  2147.  1110 IF MSEG OR (MOUSE-2) THEN 1130
  2148.  1120 PRINT "Mouse Driver not found" : END
  2149.  1130 DEF SEG=MSEG
  2150.  1140 IF PEEK (MOUSE-2) = 207, THEN 1120                 '207 is iret
  2151.  1150 '
  2152.  1160 CLS
  2153.  1170 '
  2154.  1180 M1% = 0                                            ' Reset the mouse
  2155.  1190 CALL MOUSE(M1%, M2%, M3%, M4%)
  2156.  1200 IF NOT (M1%) THEN PRINT "Mouse not installed." : END
  2157.  1210 '
  2158.  1220 M1% = 1                                            ' Show the mouse curs
  2159.  1230 CALL MOUSE(M1%, M2%, M3%, M4%)
  2160.  1240 PRINT "Mouse cursor should now be visible..."
  2161.  1250 '
  2162.  1260 M1% = 4
  2163.  1270 FOR M4% = 0 TO 200 STEP 8
  2164.  1280     FOR M3% = 0 TO 640 STEP 2
  2165.  1290         CALL MOUSE(M1%, M2%, M3%, M4%)
  2166.  1300     NEXT
  2167.  1310 NEXT
  2168.  1320 '
  2169.  1330 M1%=4                                              ' Move the mouse
  2170.  1340 M3%=320                                            '  cursor to the
  2171.  1350 M4%=100                                            '  center of the
  2172.  1360 CALL MOUSE (M1%, M2%, M3%, M4%)                    '  screen
  2173.  1370 '
  2174.  1380 M1% = 0                                            ' Reset the mouse
  2175.  1390 CALL MOUSE(M1%, M2%, M3%, M4%)
  2176.  1400 END
  2177.  
  2178.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\QBDEMO.BAS
  2179.  
  2180.  ' Mouse library call test in Quick Basic V2.0
  2181.  
  2182.    call chkdrv
  2183.  
  2184.    screen 0
  2185.  
  2186.    m1%=0                                         ' Function 0
  2187.    call mouse(m1%,m2%,m3%,m4%)
  2188.    if ( M1% = 0 ) then
  2189.       print "Microsoft Mouse NOT found"
  2190.       end
  2191.    end if
  2192.  
  2193.    m1%=4                                         ' Function 4
  2194.    m3%=200
  2195.    m4%=100
  2196.    call mouse(m1%,m2%,m3%,m4%)
  2197.  
  2198.    m1%=7                                         ' Function 7
  2199.    m3%=150
  2200.    m4%=450
  2201.    call mouse(m1%,m2%,m3%,m4%)
  2202.  
  2203.    m1%=8                                         ' Function 8
  2204.    m3%=50
  2205.    m4%=150
  2206.    call mouse(m1%,m2%,m3%,m4%)
  2207.  
  2208.    screen 2
  2209.  
  2210.    print "graphics cursor, bounded in center screen"
  2211.    print "Press left button to EXIT."
  2212.  
  2213.    m1% = 1
  2214.    call mouse(m1%,m2%,m3%,m4%)
  2215.  
  2216.    m2% = 99
  2217.    while ( m2% <> 1 )
  2218.      m1% = 3
  2219.      call mouse(m1%,m2%,m3%,m4%)
  2220.    wend
  2221.  
  2222.    screen 0
  2223.  
  2224.    end
  2225.  
  2226.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\QBMOUSE.BAS
  2227.  
  2228.          ' REFERENCE test of mouse() in mouse.lib        IN qbmouse.bas
  2229.          '
  2230.          ' This program is intended to test the parameter passing from
  2231.          ' QucikBASIC through the mouse library function mouse(), to
  2232.          ' the mouse driver.
  2233.          '
  2234.          ' To create qbmouse.exe:
  2235.          '
  2236.          '               QB QBMOUSE;
  2237.          '               LINK QBMOUSE+SUBS,,,BCOM20+MOUSE.LIB
  2238.          '
  2239.          ' Note:  This program is written in QuickBASIC (compiled).  Do not
  2240.          ' attempt to run it under interepted BASIC, since the mouse() functio
  2241.          ' is not available.
  2242.          '
  2243.  
  2244.          DIM BOUNDS%(4)
  2245.  
  2246.          CALL CHKDRV                             ' Make sure mouse driver exis
  2247.          SCREEN 2                                ' 640x200 display (CGA mode 6
  2248.          CLS                                     ' Clear the screen
  2249.  
  2250.          M1% = 0                                 ' Reset the mouse
  2251.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2252.  
  2253.          M1% = 1                                 ' Show the mouse cursor
  2254.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2255.  
  2256.          PRINT "Mouse cursor should now be sweeping the screen."
  2257.          M1% = 4
  2258.          FOR M3% = 0 TO 640 STEP 8
  2259.              FOR M4% = 0 TO 200 STEP 4
  2260.                  CALL MOUSE(M1%, M2%, M3%, M4%)  ' Set mouse cursor position
  2261.              NEXT
  2262.          NEXT
  2263.  
  2264.          M1% = 2                                 ' Hide the mouse cursor
  2265.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2266.          CLS
  2267.  
  2268.          PRINT "╔════════════════════════════════════════════════╗"
  2269.          PRINT "║  Function 16 test.  Cursor should disappear    ║"
  2270.          PRINT "║  when moved over double line.                  ║"
  2271.          PRINT "║                                                ║"
  2272.          PRINT "║  Type any key to make cursor reappear.         ║"
  2273.          PRINT "║                                                ║"
  2274.          PRINT "║  Type ESCape to exit.                          ║"
  2275.          PRINT "╚════════════════════════════════════════════════╝"
  2276.  
  2277.  100     M1%= 4                                  ' Position mouse cursor
  2278.          M3% = 320                               '  in center of screen
  2279.          M4% = 100
  2280.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2281.  
  2282.          M1% = 1                                 ' Show mouse cursor
  2283.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2284.  '
  2285.          M1% = 16
  2286.          BOUNDS%(0) = 0                          ' Exclude mouse cursor from
  2287.          BOUNDS%(1) = 0                          '  the rectangle with corners
  2288.          BOUNDS%(2) = 392                        '  at (0,0), (0,56), (392,0),
  2289.          BOUNDS%(3) = 56                         '  and (392,56)
  2290.          M4% = VARPTR(BOUNDS%(0))                ' M4% = array address
  2291.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2292.  
  2293.  200     A$ = INKEY$
  2294.          IF A$ = "" THEN 200
  2295.          IF A$ <> "" THEN 100
  2296.  
  2297.          M1% = 2                                 ' Make sure the mouse cursor
  2298.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is hidden
  2299.          CLS
  2300.  
  2301.          PRINT "Move the mouse cursor to the UPPER LEFT corner of the screen."
  2302.          PRINT "RELEASE both mouse buttons, and then press ESCape."
  2303.          M1% = 1                                 ' Make sure the mouse cursor
  2304.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is displayed
  2305.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2306.  300     A$ = INKEY$
  2307.          IF A$ <> "" THEN 300
  2308.          M1% = 3                                 ' Get mouse position and
  2309.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  button status
  2310.          M1% = 2                                 ' Make sure the mouse cursor
  2311.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is hidden
  2312.          IF (M2% <> 0) THEN PRINT "Mouse button information error"
  2313.          IF (M3% <> 0) THEN PRINT "Mouse x coordinate position error ";M3%
  2314.          IF (M4% <> 0) THEN PRINT "Mouse y coordinate position error ";M4%
  2315.          M1% = 1                                 ' Make sure the mouse cursor
  2316.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is displayed
  2317.  
  2318.          M1% = 2                                 ' Make sure the mouse cursor
  2319.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is hidden
  2320.          PRINT "Move the mouse cursor to the LOWER RIGHT corner of the screen.
  2321.          PRINT "HOLD DOWN both mouse buttons, and then press ESCape."
  2322.          M1% = 1                                 ' Make sure the mouse cursor
  2323.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is displayed
  2324.  400     A$ = INKEY$
  2325.          IF A$ <> "" THEN 400
  2326.          M1% = 3                                 ' Get mouse position and
  2327.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  button status
  2328.          M1% = 2                                 ' Make sure the mouse cursor
  2329.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is hidden
  2330.          IF (M2% <> 3) THEN PRINT "Mouse button information error"
  2331.          IF (M3% <> 639) THEN PRINT "Mouse x coordinate position error ";M3%
  2332.          IF (M4% <> 199) THEN PRINT "Mouse y coordinate position error ";M4%
  2333.          M1% = 1                                 ' Make sure the mouse cursor
  2334.          CALL MOUSE(M1%, M2%, M3%, M4%)          '  is displayed
  2335.  
  2336.          PRINT
  2337.          PRINT "Press any key to terminate."
  2338.  500     A$ = INKEY$
  2339.          IF A$ ="" THEN 500
  2340.          M1% = 0                                 ' Reset the mouse
  2341.          CALL MOUSE(M1%, M2%, M3%, M4%)
  2342.  
  2343.          END
  2344.  
  2345.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\FDEMO.FOR
  2346.  
  2347.         PROGRAM MTEST
  2348.  
  2349.  C
  2350.  C      -- Mouse Library function calls demo in MS FORTRAN V3.31
  2351.  C
  2352.  
  2353.  C      -- mouse parameters --
  2354.         INTEGER*2   M1, M2, M3, M4, M5
  2355.         INTEGER*2   MCURSOR(32), BOUND(4)
  2356.         INTEGER*2   ARRLOC(2)
  2357.         INTEGER*4   ARRADDS
  2358.         EXTERNAL    CHKDRV, GRAF
  2359.         EQUIVALENCE (ARRLOC(1),ARRADDS)
  2360.  
  2361.  C      -- initialize data for function call 9 --
  2362.  C         Mouse call #9 needs 2 byte integer input, in V3.31
  2363.  C         use INT2 function.
  2364.  
  2365.         DO 50 I = 1, 16
  2366.    50   MCURSOR (I) = INT2(#ffff)
  2367.  
  2368.         MCURSOR(17) = INT2(#0780)
  2369.         MCURSOR(18) = INT2(#b8b8)
  2370.         MCURSOR(19) = INT2(#3060)
  2371.         MCURSOR(20) = INT2(#6038)
  2372.         MCURSOR(21) = INT2(#f07e)
  2373.         MCURSOR(22) = INT2(#8841)
  2374.         MCURSOR(23) = INT2(#f031)
  2375.         MCURSOR(24) = INT2(#7020)
  2376.         MCURSOR(25) = INT2(#401c)
  2377.         MCURSOR(26) = INT2(#6006)
  2378.         MCURSOR(27) = INT2(#3c06)
  2379.         MCURSOR(28) = INT2(#03fe)
  2380.         MCURSOR(29) = INT2(#0001)
  2381.         MCURSOR(30) = INT2(#f001)
  2382.         MCURSOR(31) = INT2(#0301)
  2383.         MCURSOR(32) = INT2(#007c)
  2384.  
  2385.  C      -- Chech for mouse and driver installation  --
  2386.         CALL CHKDRV
  2387.  
  2388.         M1 = 0
  2389.         CALL MOUSES(M1, M2, M3, M4)
  2390.  
  2391.         IF ( M1 .EQ. 0 ) THEN
  2392.            WRITE(*,*)' Microsoft mouse NOT found'
  2393.            STOP
  2394.         ENDIF
  2395.  
  2396.  
  2397.         WRITE(*,*) ' Enter "c" to continue'
  2398.    100  READ (*,200) CH
  2399.    200  FORMAT(A)
  2400.         IF ( CH .NE. 'c' ) GOTO 100
  2401.  
  2402.  C      -- Change to graphics mode --
  2403.         CALL GRAF
  2404.  
  2405.  C      -- Function 9 Graphics Cursor --
  2406.         M1 = 9
  2407.         M2 = 1
  2408.         M3 = 1
  2409.         ARRADDS = LOCFAR(MCURSOR)
  2410.         CALL MOUSES(M1, M2, M3, ARRLOC(1))
  2411.  
  2412.         M1 = 1
  2413.         CALL MOUSES(M1, M2, M3, M4)
  2414.  
  2415.  C      -- Function 16 Conditional Off --
  2416.         M1 = 16
  2417.         BOUND(1) = 0
  2418.         BOUND(2) = 0
  2419.         BOUND(3) = 50
  2420.         BOUND(4) = 300
  2421.         ARRADDS = LOCFAR(BOUND)
  2422.         CALL MOUSES(M1, M2, M3, ARRLOC(1))
  2423.  
  2424.  
  2425.         WRITE(*,*) ' ENTER "q" TO CONTINUE'
  2426.    300  READ (*,200) CH
  2427.         IF ( CH .NE. 'q' ) GOTO 300
  2428.  
  2429.         STOP
  2430.         END
  2431.  
  2432.  
  2433.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\FORMOUSE.FOR
  2434.  
  2435.  C----------------------------------------------------------------------
  2436.  C
  2437.  C This program tests the 4 parameter mouse driver interface function
  2438.  C
  2439.  C              To Run :
  2440.  C                       FOR1 FORMOUSE;
  2441.  C                       PAS1;
  2442.  C                       LINK FORMOUSE+SUBS,,,MOUSE
  2443.  C                             OR
  2444.  C                       MAKE FORMOUSE.MAK
  2445.  C
  2446.  C----------------------------------------------------------------------
  2447.          INTEGER*2     M1, M2, M3, M4
  2448.          INTEGER*2     PTRADD(2), BOUND(4)
  2449.          INTEGER*4     PTR
  2450.          EXTERNAL      CHKDRV, GRAF
  2451.          EQUIVALENCE   (PTRADD(1), PTR)
  2452.  
  2453.          CALL CHKDRV
  2454.  
  2455.          M1 = 0
  2456.          CALL MOUSES(M1, M2, M3, M4)
  2457.          IF (M1 .NE. 0) GOTO 100
  2458.          WRITE (*, 800) ' Mouse Driver not installed'
  2459.          GOTO 99999
  2460.  
  2461.   100    CALL GRAF
  2462.  
  2463.          M1 = 1
  2464.          CALL MOUSES(M1, M2, M3, M4)
  2465.  
  2466.          WRITE (*, 800) ' mouse cursor should be sweeping the screen'
  2467.  
  2468.          M1 = 4
  2469.          DO 210 M3 = 0, 640, 16
  2470.          DO 200 M4 = 0, 200, 2
  2471.          CALL MOUSES(M1, M2, M3, M4)
  2472.   200    CONTINUE
  2473.   210    CONTINUE
  2474.  
  2475.          CALL GRAF
  2476.  
  2477.          WRITE(*,800)'++-----------------------------------------------+'
  2478.          WRITE(*,800)' | Function 16 test.  Cursor should disappear    |'
  2479.          WRITE(*,800)' | when moved over DOTTED line.                  |'
  2480.          WRITE(*,800)' | Cursor should appear in center of screen      |'
  2481.          WRITE(*,800)' |                                               |'
  2482.          WRITE(*,800)' | Type ENTER to make cursor reappear.           |'
  2483.          WRITE(*,800)' | Type C (Upper Case) and ENTER to continue.    |'
  2484.          WRITE(*,800)' +-----------------------------------------------+'
  2485.  
  2486.   300    M1 = 4
  2487.          M3 = 320
  2488.          M4 = 100
  2489.          CALL MOUSES(M1, M2, M3, M4)
  2490.  
  2491.          M1 = 1
  2492.          CALL MOUSES(M1, M2, M3, M4)
  2493.  
  2494.          M1 = 16
  2495.          BOUND(1) = 0
  2496.          BOUND(2) = 0
  2497.          BOUND(3) = 384
  2498.          BOUND(4) = 56
  2499.          PTR = LOCFAR(BOUND)
  2500.          CALL MOUSES(M1, M2, M3, PTRADD(1))
  2501.  
  2502.   400    READ (*,800) CH
  2503.          IF (CH .NE. 'C') GOTO 300
  2504.  
  2505.  C       Test buttons and mouse position
  2506.  
  2507.          CALL GRAF
  2508.  
  2509.          WRITE (*,800) ' Move mouse to UPPER LEFT corner.'
  2510.          WRITE (*,800) ' PRESS both buttons, press C and ENTER'
  2511.          M1 = 1
  2512.          CALL MOUSES(M1, M2, M3, M4)
  2513.   500    READ (*,800) CH
  2514.          IF (CH .NE. 'C') GOTO 500
  2515.          M1 = 3
  2516.          M2 = 9999
  2517.          M3 = 9999
  2518.          M4 = 9999
  2519.          CALL MOUSES(M1, M2, M3, M4)
  2520.          M1 = 2
  2521.          CALL MOUSES(M1, M2, M3, M4)
  2522.          IF (M2 .NE. 3) WRITE(*, 700) ' BUTTON INFO ERROR : ',M2
  2523.          IF (M3 .NE. 0) WRITE(*, 700) ' X COORD ERROR : ',M3
  2524.          IF (M4 .NE. 0) WRITE(*, 700) ' Y COORD ERROR : ',M4
  2525.          M1 = 1
  2526.          CALL MOUSES(M1, M2, M3, M4)
  2527.  
  2528.  
  2529.          M1 = 2
  2530.          CALL MOUSE(M1, M2, M3, M4)
  2531.          WRITE (*,800) ' Move mouse to LOWER RIGHT corner.'
  2532.          WRITE (*,800) ' RELEASE both buttons, then press C then ENTER'
  2533.          M1 = 1
  2534.          CALL MOUSES(M1, M2, M3, M4)
  2535.   600    READ (*,800) CH
  2536.          IF (CH .NE. 'C') GOTO 600
  2537.          M1 = 3
  2538.          M3 = 9999
  2539.          M4 = 9999
  2540.          CALL MOUSES(M1, M2, M3, M4)
  2541.          M1 = 2
  2542.          CALL MOUSES(M1, M2, M3, M4)
  2543.          IF (M2 .NE. 0) WRITE(*, 700) ' BUTTON INFO ERROR : ',M2
  2544.          IF (M3 .NE. 639) WRITE(*, 700) ' X COORD ERROR : ',M3
  2545.          IF (M4 .NE. 199) WRITE(*, 700) ' Y COORD ERROR : ',M4
  2546.          M1 = 1
  2547.          CALL MOUSES(M1, M2, M3, M4)
  2548.  
  2549.  
  2550.   700    FORMAT (A, I4)
  2551.  
  2552.   800    FORMAT(A)
  2553.  
  2554.          STOP
  2555.  99999   END
  2556.  
  2557.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\BDEMO.MAK
  2558.  
  2559.  bdemo.obj:   bdemo.bas
  2560.         qb bdemo;
  2561.  
  2562.  bdemo.exe:   bdemo.obj subs.obj
  2563.         link bdemo subs,,,..\mouse;
  2564.  
  2565.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\CMCMOUSE.MAK
  2566.  
  2567.  cmcmouse.obj:   cmcmouse.c
  2568.          msc /AC cmcmouse;
  2569.  
  2570.  cmcmouse.exe:   cmcmouse.obj
  2571.          link cmcmouse+subs,,,..\mouse
  2572.  
  2573.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\FDEMO.MAK
  2574.  
  2575.  fdemo.obj:   fdemo.for
  2576.         for1 fdemo;
  2577.         pas2
  2578.  
  2579.  fdemo.exe:   fdemo.obj subs.obj
  2580.         link fdemo subs,,,..\mouse;
  2581.  
  2582.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\FORMOUSE.MAK
  2583.  
  2584.  formouse.obj:   formouse.for
  2585.         for1 formouse;
  2586.         pas2
  2587.  
  2588.  formouse.exe:   formouse.obj
  2589.         link formouse subs,,,..\mouse;
  2590.  
  2591.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\LMCMOUSE.MAK
  2592.  
  2593.  lmcmouse.obj:   lmcmouse.c
  2594.          msc /AL lmcmouse;
  2595.  
  2596.  lmcmouse.exe:   lmcmouse.obj
  2597.          link lmcmouse+subs,,,..\mouse
  2598.  
  2599.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\MMCMOUSE.MAK
  2600.  
  2601.  mmcmouse.obj:   mmcmouse.c
  2602.          msc /AM mmcmouse;
  2603.  
  2604.  mmcmouse.exe:   mmcmouse.obj
  2605.          link mmcmouse+subs,,,..\mouse
  2606.  
  2607.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\PDEMO.MAK
  2608.  
  2609.  pdemo.obj:   pdemo.pas
  2610.         pas1 pdemo;
  2611.         pas2
  2612.  
  2613.  pdemo.exe:   pdemo.obj subs.obj
  2614.         link pdemo subs,,,..\mouse;
  2615.  
  2616.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\QBDEMO.MAK
  2617.  
  2618.  QBMOUSE.OBJ:    QBDEMO.BAS
  2619.          QB QBDEMO /O;
  2620.  
  2621.  QBDEMO.EXE:     QBDEMO.OBJ
  2622.          LINK QBDEMO+SUBS,,,BCOM20+..\MOUSE
  2623.  
  2624.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\QBMOUSE.MAK
  2625.  
  2626.  QBMOUSE.OBJ:    QBMOUSE.BAS
  2627.          QB QBMOUSE /O;
  2628.  
  2629.  QBMOUSE.EXE:    QBMOUSE.OBJ
  2630.          LINK QBMOUSE+SUBS,,,BCOM20+..\MOUSE
  2631.  
  2632.  \SAMPCODE\MOUSE\LIB\MOUSE\DEMO\SMCMOUSE.MAK
  2633.  
  2634.  smcmouse.obj:   smcmouse.c
  2635.          msc smcmouse;
  2636.  
  2637.  smcmouse.exe:   smcmouse.obj
  2638.          link smcmouse+subs,,,..\mouse
  2639.  
  2640.  \SAMPCODE\MOUSE\LIB\MOUSE\EXAMPLES
  2641.  \SAMPCODE\MOUSE\LIB\MOUSE\EXAMPLES\MSCEXAMP.C
  2642.  
  2643.  /*          Mouse Function Calls and Microsoft C
  2644.  
  2645.              To Run :    MSC MSCEXAMP;
  2646.                          LINK MSCEXAMP,,,MOUSE;
  2647.                              or
  2648.                          MAKE MSCEXAMP.MAK
  2649.  
  2650.  */
  2651.  
  2652.  #include <stdio.h>
  2653.  #include <dos.h>
  2654.  
  2655.  void chkdrv();
  2656.  void graf();
  2657.  
  2658.  main()
  2659.  {
  2660.          int m1, m2, m3, m4;
  2661.  
  2662.          chkdrv();               /* check for mouse driver   */
  2663.  
  2664.          m1 = 0;                 /* initialize mouse         */
  2665.          cmouses( &m1, &m2, &m3, &m4);
  2666.  
  2667.          if ( m1 = 0 ) {
  2668.              printf("Microsoft Mouse NOT found");
  2669.              exit (-1);          /* exit, if mouse not found */
  2670.              }
  2671.  
  2672.          m1 = 4;                 /* function call 4          */
  2673.          m3 = 200;               /* set mouse pisition at    */
  2674.          m4 = 100;               /* center of the screen     */
  2675.          cmouses( &m1, &m2, &m3, &m4);
  2676.  
  2677.          m1 = 7;                 /* function call 7          */
  2678.          m3 = 150;               /* minimum horizontal value */
  2679.          m4 = 450;               /* maximum horizontal value */
  2680.          cmouses( &m1, &m2, &m3, &m4);
  2681.  
  2682.          m1 = 8;                 /* function call 8          */
  2683.          m3 = 50;                /* minimum vertical value   */
  2684.          m4 = 150;               /* maximum vertical value   */
  2685.          cmouses( &m1, &m2, &m3, &m4);
  2686.  
  2687.          graf();
  2688.  
  2689.          printf("Graphics cursor limited to center of the screen.\n");
  2690.          printf("Press the left button to EXIT.");
  2691.  
  2692.          m1 = 1;                 /* function 1, show cursor  */
  2693.          cmouses( &m1, &m2, &m3, &m4);
  2694.  
  2695.          m2 = 0;                 /* loop until left mouse    */
  2696.          while ( m2 != 1 ) {     /* button is pressed        */
  2697.              m1 = 3;
  2698.              cmouses( &m1, &m2, &m3, &m4 );
  2699.              }
  2700.  
  2701.          m1 = 2;                 /* function 2, show cursor  */
  2702.          cmouses( &m1, &m2, &m3, &m4);
  2703.  
  2704.  }
  2705.  
  2706.  
  2707.  void chkdrv()
  2708.  {
  2709.          union REGS inregs, outregs;
  2710.          struct SREGS segregs;
  2711.          long address;
  2712.          unsigned char first_byte;
  2713.  
  2714.          inregs.x.ax = 0x3533;
  2715.          intdosx ( &inregs, &outregs, &segregs );
  2716.  
  2717.          address = (((long) segregs.es) << 16) + (long) outregs.x.bx;
  2718.          first_byte = * (long far *) address;
  2719.  
  2720.          if ((address == 0) || (first_byte == 0xcf)) {
  2721.              printf("Mouse driver NOT installed");
  2722.              exit();
  2723.              }
  2724.  
  2725.  }
  2726.  
  2727.  
  2728.  void graf()
  2729.  {
  2730.          union REGS cpuregs;
  2731.  
  2732.          cpuregs.x.ax = 0x0006;
  2733.          int86 ( 0x10, &cpuregs, &cpuregs );
  2734.  }
  2735.  
  2736.  \SAMPCODE\MOUSE\LIB\MOUSE\EXAMPLES\ASMEXAMP.ASM
  2737.  
  2738.  ;           Mouse Function Calls and Microsoft Assembler
  2739.  ;
  2740.  ;           To Run :    MASM ASMEXAMP;
  2741.  ;                       LINK ASMEXAMP;
  2742.  ;
  2743.  ;                       MAKE ASMEXAMP.MAK
  2744.  ;
  2745.  ;
  2746.  
  2747.  
  2748.  stack  segment stack   'stack'
  2749.                  db      256 dup(?)
  2750.  stack   ends
  2751.  ;
  2752.  data            segment public  'data'
  2753.                  msg1    db   "Microsoft Mouse NOT found","$"
  2754.                  msg2    db   "Graphics cursor limit at center of the screen",
  2755.                          db   "Press the left mouse button to EXIT","$"
  2756.  data            ends
  2757.  ;
  2758.  code            segment public  'code'
  2759.                  assume cs:code, ds:data, es:data; ss:stack
  2760.  start:
  2761.                  push    bp
  2762.                  mov     bp,sp
  2763.                  mov     ax,seg data             ;Set DS to the
  2764.                  mov     ds,ax                   ; data segment
  2765.  
  2766.                  push    es                      ;Save PSP segment address
  2767.                  mov     ax, 03533h              ;Get int 33h vector
  2768.                  int     21h                     ; by calling int 21
  2769.                  mov     ax, es                  ;Check segment and
  2770.                  or      ax, bx                  ;offset of int 33
  2771.                  jnz     begin                   ;vector.  If 0 or pointing to
  2772.                  mov     bl, es:[bx]             ;an IRET driver not install
  2773.                  cmp     bl, 0cfh
  2774.                  jne     begin                   ;Exit
  2775.  
  2776.                  mov     dx, offset msg1         ;Get not found message offset
  2777.                  mov     ah, 09h                 ;Output message to screen
  2778.                  int     21h
  2779.                  pop     es
  2780.                  jmp     short exit              ;Exit
  2781.  
  2782.  begin:
  2783.                  mov     ax,0                    ;Initialize mouse
  2784.                  int     33h
  2785.                  cmp     ax,0                    ;Is mouse installed?
  2786.                  jz      exit                    ;No, exit
  2787.                  mov     ax,0006h                ;Set up for 640x200 resolutio
  2788.                  int     10h                     ;graphics mode (CGA-mode 6)
  2789.                  mov     ax, 4                   ;Function 4 (set cursor posit
  2790.                  mov     cx, 200                 ;M3 = 200
  2791.                  mov     dx, 100                 ;M4 = 100
  2792.                  int     33h
  2793.                  mov     ax, 7                   ;Function 7
  2794.                  mov     cx, 150                 ;M3 = 150
  2795.                  mov     dx, 450                 ;M4 = 450
  2796.                  int     33h
  2797.                  mov     ax, 8                   ;Function 8
  2798.                  mov     cx, 50                  ;M3 = 50
  2799.                  mov     dx, 150                 ;M4 = 150
  2800.                  int     33h
  2801.                  mov     ax,1                    ;Shoe the mouse cursor
  2802.                  int     33h
  2803.  
  2804.                  mov     dx, offset msg2         ;Get exit message
  2805.                  mov     ah, 09h                 ;Output message to screen
  2806.                  int     21h
  2807.                  xor     ax, ax
  2808.  
  2809.  around:
  2810.                  mov     ax,3                    ;Get mouse status
  2811.                  int     33h
  2812.                  cmp     bx,0001h                ;Left button pressed ?
  2813.                  jne     around                  ;Branch if left button NOT pr
  2814.  
  2815.                  mov     ax,0
  2816.                  int     33h                     ;Reset mouse
  2817.                  mov     ax,0003h                ;Set up 80x25 character text
  2818.                  int     10h
  2819.  exit:
  2820.                  mov     sp,bp
  2821.                  pop     bp
  2822.                  mov     ax,04c00h               ;Terminate
  2823.                  int     21h
  2824.  ;
  2825.  code            ends
  2826.  end             start
  2827.  
  2828.  \SAMPCODE\MOUSE\LIB\MOUSE\EXAMPLES\SUBS.ASM
  2829.  
  2830.  ;
  2831.  ;
  2832.  ; This is the subroutine for mouse.lib test in FORTRAN
  2833.  ; and Pascal examples.  Procedure graf sets the screen
  2834.  ; video mode into hi-res graphics.
  2835.  ;
  2836.  ;
  2837.  ;
  2838.  mdata           segment byte public 'data'
  2839.  
  2840.                  msg     db   "Mouse Driver NOT installed","$"
  2841.  
  2842.  mdata           ends
  2843.  
  2844.  
  2845.  
  2846.  
  2847.  mcode           segment para public 'CODE'
  2848.                  assume  cs:mcode
  2849.  ;
  2850.                  public  graf
  2851.  ;
  2852.  graf            proc    far
  2853.                  push    bp
  2854.                  mov     ax, 06h                 ;change to graphics
  2855.                  int     10h                     ;mode by calling
  2856.                  pop     bp                      ;int 10 service
  2857.                  ret
  2858.  graf            endp
  2859.  ;
  2860.  ;
  2861.  ;
  2862.                  public  chkdrv
  2863.  ;
  2864.  chkdrv          proc    far
  2865.                  push    bp
  2866.                  push    es
  2867.  
  2868.                  mov     ax, 03533h              ;get int 33h
  2869.                  int     21h                     ;by calling int 21
  2870.                  mov     ax, es                  ;check segment and
  2871.                  or      ax, bx                  ;offset of int 33
  2872.                  jnz     back                    ;vector if 0 or IRET
  2873.                  mov     bl, es:[bx]             ;mouse driver not installed
  2874.                  cmp     bl, 0cfh
  2875.                  jne     back                    ;exit
  2876.  
  2877.                  mov     ax,seg mdata            ;set up DS to
  2878.                  mov     ds,ax                   ;point to data seg
  2879.                  mov     dx, offset msg          ;get message
  2880.                  mov     ah, 09h                 ;out to screen
  2881.                  int     21h
  2882.                  pop     es
  2883.                  pop     bp
  2884.                  mov     ax,04c00h               ;function code for
  2885.                  int     21h                     ;end process
  2886.  
  2887.          back:
  2888.                  pop     es
  2889.                  pop     bp
  2890.                  ret
  2891.  chkdrv          endp
  2892.  ;
  2893.  mcode           ends
  2894.                  end
  2895.  
  2896.  \SAMPCODE\MOUSE\LIB\MOUSE\EXAMPLES\PASEXAMP.PAS
  2897.  
  2898.  {           Mouse Function Calls and Microsoft Pascal       }
  2899.  {                                                           }
  2900.  {           To Run :    PAS1 PASEXAMP;                      }
  2901.  {                       PAS2                                }
  2902.  {                       LINK PASEXAMP+SUBS,,,MOUSE;         }
  2903.  {                            or                             }
  2904.  {                       MAKE PASEXAMP.MAK                   }
  2905.  {                                                           }
  2906.  
  2907.  program mtest (output);
  2908.  
  2909.  procedure mouses(vars m1, m2, m3, m4:word);extern;
  2910.  procedure chkdrv;extern;
  2911.  procedure graf;extern;
  2912.  
  2913.  var
  2914.    m1, m2, m3, m4: word;
  2915.  
  2916.  begin {demo}
  2917.  
  2918.    chkdrv;                       {check mouse driver, if not }
  2919.                                  {installed, Exit.           }
  2920.    m1:=0;                        {installed, initialize mouse}
  2921.    mouses( m1, m2, m3, m4);
  2922.    if ( m1 = 0 ) then
  2923.       writeln('Microsoft Mouse NOT found')
  2924.    else
  2925.       begin
  2926.  
  2927.         m1 := 4;                 {function call 4, set mouse }
  2928.         m3 := 200;               {horizontal position        }
  2929.         m4 := 100;               {vertical position          }
  2930.         mouses( m1, m2, m3, m4 );
  2931.  
  2932.  
  2933.         m1 := 7;                 {function call 4, set mouse }
  2934.         m3 := 150;               {minimum horizontal position}
  2935.         m4 := 450;               {maximum horizontal position}
  2936.         mouses( m1, m2, m3, m4 );
  2937.  
  2938.  
  2939.         m1 := 8;                 {function call 4, set mouse }
  2940.         m3 := 50;                {minimum vertical position  }
  2941.         m4 := 150;               {maximum vertical position  }
  2942.         mouses( m1, m2, m3, m4 );
  2943.  
  2944.         graf;                    {change into graphics mode  }
  2945.  
  2946.         writeln('Graphics cursor limited to center of the screen.');
  2947.         writeln('Press the left mouse button to EXIT.');
  2948.  
  2949.         m1:=1;                   {function call 1            }
  2950.         mouses( m1, m2, m3, m4 );{show mouse cursor          }
  2951.  
  2952.         m2 := 999;               {dummy value for loop       }
  2953.         repeat                   {until ....                 }
  2954.           m1 := 3;                  {function call 3         }
  2955.           mouses( m1, m2, m3, m4 ); {get current mouse status}
  2956.         until m2 = 1;            {left mouse button pressed  }
  2957.  
  2958.       end
  2959.  
  2960.  end. {demo}
  2961.  
  2962.  \SAMPCODE\MOUSE\LIB\MOUSE\EXAMPLES\QBEXAMP.BAS
  2963.  
  2964.  '           Mouse Function Calls and Microsoft QuickBASIC
  2965.  '
  2966.  '           To Run :    QB QBEXAMP;
  2967.  '                       LINK QBEXAMP+SUBS,,,MOUSE;
  2968.  '                            or
  2969.  '                       MAKE QBEXAMP.MAK
  2970.  '
  2971.  '
  2972.  ' Mouse library call test in Quick Basic V2.0
  2973.  
  2974.    call chkdrv
  2975.  
  2976.    screen 0
  2977.  
  2978.    m1%=0                                         ' Function 0
  2979.    call mouse(m1%,m2%,m3%,m4%)
  2980.    if ( M1% = 0 ) then
  2981.       print "Microsoft Mouse NOT found"
  2982.       end
  2983.    end if
  2984.  
  2985.    m1%=4                                         ' Function 4
  2986.    m3%=200
  2987.    m4%=100
  2988.    call mouse(m1%,m2%,m3%,m4%)
  2989.  
  2990.    m1%=7                                         ' Function 7
  2991.    m3%=150
  2992.    m4%=450
  2993.    call mouse(m1%,m2%,m3%,m4%)
  2994.  
  2995.    m1%=8                                         ' Function 8
  2996.    m3%=50
  2997.    m4%=150
  2998.    call mouse(m1%,m2%,m3%,m4%)
  2999.  
  3000.    screen 2
  3001.  
  3002.    print "graphics cursor, bounded in center screen"
  3003.    print "Press left button to EXIT."
  3004.  
  3005.    m1% = 1
  3006.    call mouse(m1%,m2%,m3%,m4%)
  3007.  
  3008.    m2% = 99
  3009.    while ( m2% <> 1 )
  3010.      m1% = 3
  3011.      call mouse(m1%,m2%,m3%,m4%)
  3012.    wend
  3013.  
  3014.    screen 0
  3015.  
  3016.    end
  3017.  
  3018.  \SAMPCODE\MOUSE\LIB\MOUSE\EXAMPLES\FOREXAMP.FOR
  3019.  
  3020.  C           Mouse Function Calls and Microsoft FORTRAN
  3021.  C
  3022.  C           To Run :    FOR1 FOREXAMP;
  3023.  C                       PAS2
  3024.  C                       LINK FOREXAMP+SUBS,,,MOUSE;
  3025.  C                            or
  3026.  C                       MAKE FOREXAMP.MAK
  3027.  C
  3028.  
  3029.         PROGRAM MTEST
  3030.  
  3031.  C
  3032.  C      -- Mouse Library calls test in MS FORTRAN V3.31 --
  3033.  C
  3034.  
  3035.         INTEGER*2   M1, M2, M3, M4
  3036.         EXTERNAL    GRAF, CHKDRV
  3037.  
  3038.  
  3039.  C      --  Call driver checking routine  --
  3040.         CALL CHKDRV()
  3041.  
  3042.  C      -- Mouse init call --
  3043.         M1 = 0
  3044.         CALL MOUSES(M1, M2, M3, M4)
  3045.         IF ( M1 .EQ. 0 ) THEN
  3046.               WRITE(*,*)' Microsoft Mouse NOT found'
  3047.               STOP
  3048.         ENDIF
  3049.  
  3050.  C      -- Place Cursor in the center of the screen --
  3051.         M1 = 4
  3052.         M3 = 200
  3053.         M4 = 100
  3054.         CALL MOUSES(M1, M2, M3, M4)
  3055.  
  3056.  C      -- Set minimum and maximum horizontal position --
  3057.         M1 = 7
  3058.         M3 = 150
  3059.         M4 = 450
  3060.         CALL MOUSES(M1, M2, M3, M4)
  3061.  
  3062.  C      -- Set minimum and maximum vertical position --
  3063.         M1 = 8
  3064.         M3 = 50
  3065.         M4 = 150
  3066.         CALL MOUSES(M1, M2, M3, M4)
  3067.  
  3068.         CALL GRAF()
  3069.  
  3070.         WRITE(*,*) ' Graphics cursor limited to the screen center.'
  3071.         WRITE(*,*) ' Press the left mouse button to EXIT.'
  3072.  
  3073.         M1 = 1
  3074.         CALL MOUSES(M1, M2, M3, M4)
  3075.  
  3076.  
  3077.  C      -- Loop for left moue button pressed  --
  3078.         M2 = 9999
  3079.   100      M1 = 3
  3080.            CALL MOUSES(M1, M2, M3, M4)
  3081.         IF ( M2 .NE. 1 ) GOTO 100
  3082.  
  3083.         STOP
  3084.         END
  3085.  
  3086.  \SAMPCODE\MOUSE\SOURCES
  3087.  \SAMPCODE\MOUSE\SOURCES\COLOR.DEF
  3088.  
  3089.  ;       SAMPLE Microsoft Mouse COLOR MENU
  3090.  ;
  3091.  ; This menu displays the color options available for the
  3092.  ; Microsoft Mouse Menus.
  3093.  ;
  3094.  ;
  3095.  BEGIN lb
  3096.  ;
  3097.  lb:     execute popmen
  3098.  nul:    nothing
  3099.  ;
  3100.  popmen:   POPUP 2,1,NORMAL
  3101.  text "╔QUIT════════════════════════════════════════════════════════════╗"
  3102.  text "║ 000 016 032 048 064 080 096 112 128 144 160 176 192 208 224 240║"
  3103.  text "║ 001 017 033 049 065 081 097 113 129 145 161 177 193 209 225 241║"
  3104.  text "║ 002 018 034 050 066 082 098 114 130 146 162 178 194 210 226 242║"
  3105.  text "║ 003 019 035 051 067 083 099 115 131 147 163 179 195 211 227 243║"
  3106.  text "║ 004 020 036 052 068 084 100 116 132 148 164 180 196 212 228 244║"
  3107.  text "║ 005 021 037 053 069 085 101 117 133 149 165 181 197 213 229 245║"
  3108.  text "║ 006 022 038 054 070 086 102 118 134 150 166 182 198 214 230 246║"
  3109.  text "║ 007 023 039 055 071 087 103 119 135 151 167 183 199 215 231 247║"
  3110.  text "║ 008 024 040 056 072 088 104 120 136 152 168 184 200 216 232 248║"
  3111.  text "║ 009 025 041 057 073 089 105 121 137 153 169 185 201 217 233 249║"
  3112.  text "║ 010 026 042 058 074 090 106 122 138 154 170 186 202 218 234 250║"
  3113.  text "║ 011 027 043 059 075 091 107 123 139 155 171 187 203 219 235 251║"
  3114.  text "║ 012 028 044 060 076 092 108 124 140 156 172 188 204 220 236 252║"
  3115.  text "║ 013 029 045 061 077 093 109 125 141 157 173 189 205 221 237 253║"
  3116.  text "║ 014 030 046 062 078 094 110 126 142 158 174 190 206 222 238 254║"
  3117.  text "║ 015 031 047 063 079 095 111 127 143 159 175 191 207 223 239 255║"
  3118.  text "╚════════════════════════════════════════════════════════════════╝"
  3119.  ;
  3120.     SELECT 1,2,4,nul
  3121.     SELECT 1,6,4,lb
  3122.     SELECT 1,10,4,lb
  3123.     SELECT 1,14,4,lb
  3124.     SELECT 1,18,4,lb
  3125.     SELECT 1,22,4,lb
  3126.     SELECT 1,26,4,lb
  3127.     SELECT 1,30,4,lb
  3128.     SELECT 1,34,4,lb
  3129.     SELECT 1,38,4,lb
  3130.     SELECT 1,42,4,lb
  3131.     SELECT 1,46,4,lb
  3132.     SELECT 1,50,4,lb
  3133.     SELECT 1,54,4,lb
  3134.     SELECT 1,58,4,lb
  3135.     SELECT 1,62,4,lb
  3136.     SELECT 2,2,4,lb
  3137.     SELECT 3,2,4,m001
  3138.     SELECT 4,2,4,m002
  3139.     SELECT 5,2,4,m003
  3140.     SELECT 6,2,4,m004
  3141.     SELECT 7,2,4,m005
  3142.     SELECT 8,2,4,m006
  3143.     SELECT 9,2,4,m007
  3144.     SELECT 10,2,4,m008
  3145.     SELECT 11,2,4,m009
  3146.     SELECT 12,2,4,m010
  3147.     SELECT 13,2,4,m011
  3148.     SELECT 14,2,4,m012
  3149.     SELECT 15,2,4,m013
  3150.     SELECT 16,2,4,m014
  3151.     SELECT 17,2,4,m015
  3152.     SELECT 2,6,4,m016
  3153.     SELECT 3,6,4,m017
  3154.     SELECT 4,6,4,m018
  3155.     SELECT 5,6,4,m019
  3156.     SELECT 6,6,4,m020
  3157.     SELECT 7,6,4,m021
  3158.     SELECT 8,6,4,m022
  3159.     SELECT 9,6,4,m023
  3160.     SELECT 10,6,4,m024
  3161.     SELECT 11,6,4,m025
  3162.     SELECT 12,6,4,m026
  3163.     SELECT 13,6,4,m027
  3164.     SELECT 14,6,4,m028
  3165.     SELECT 15,6,4,m029
  3166.     SELECT 16,6,4,m030
  3167.     SELECT 17,6,4,m031
  3168.     SELECT 2,10,4,m032
  3169.     SELECT 3,10,4,m033
  3170.     SELECT 4,10,4,m034
  3171.     SELECT 5,10,4,m035
  3172.     SELECT 6,10,4,m036
  3173.     SELECT 7,10,4,m037
  3174.     SELECT 8,10,4,m038
  3175.     SELECT 9,10,4,m039
  3176.     SELECT 10,10,4,m040
  3177.     SELECT 11,10,4,m041
  3178.     SELECT 12,10,4,m042
  3179.     SELECT 13,10,4,m043
  3180.     SELECT 14,10,4,m044
  3181.     SELECT 15,10,4,m045
  3182.     SELECT 16,10,4,m046
  3183.     SELECT 17,10,4,m047
  3184.     SELECT 2,14,4,m048
  3185.     SELECT 3,14,4,m049
  3186.     SELECT 4,14,4,m050
  3187.     SELECT 5,14,4,m051
  3188.     SELECT 6,14,4,m052
  3189.     SELECT 7,14,4,m053
  3190.     SELECT 8,14,4,m054
  3191.     SELECT 9,14,4,m055
  3192.     SELECT 10,14,4,m056
  3193.     SELECT 11,14,4,m057
  3194.     SELECT 12,14,4,m058
  3195.     SELECT 13,14,4,m059
  3196.     SELECT 14,14,4,m060
  3197.     SELECT 15,14,4,m061
  3198.     SELECT 16,14,4,m062
  3199.     SELECT 17,14,4,m063
  3200.     SELECT 2,18,4,m064
  3201.     SELECT 3,18,4,m065
  3202.     SELECT 4,18,4,m066
  3203.     SELECT 5,18,4,m067
  3204.     SELECT 6,18,4,m068
  3205.     SELECT 7,18,4,m069
  3206.     SELECT 8,18,4,m070
  3207.     SELECT 9,18,4,m071
  3208.     SELECT 10,18,4,m072
  3209.     SELECT 11,18,4,m073
  3210.     SELECT 12,18,4,m074
  3211.     SELECT 13,18,4,m075
  3212.     SELECT 14,18,4,m076
  3213.     SELECT 15,18,4,m077
  3214.     SELECT 16,18,4,m078
  3215.     SELECT 17,18,4,m079
  3216.     SELECT 2,22,4,m080
  3217.     SELECT 3,22,4,m081
  3218.     SELECT 4,22,4,m082
  3219.     SELECT 5,22,4,m083
  3220.     SELECT 6,22,4,m084
  3221.     SELECT 7,22,4,m085
  3222.     SELECT 8,22,4,m086
  3223.     SELECT 9,22,4,m087
  3224.     SELECT 10,22,4,m088
  3225.     SELECT 11,22,4,m089
  3226.     SELECT 12,22,4,m090
  3227.     SELECT 13,22,4,m091
  3228.     SELECT 14,22,4,m092
  3229.     SELECT 15,22,4,m093
  3230.     SELECT 16,22,4,m094
  3231.     SELECT 17,22,4,m095
  3232.     SELECT 2,26,4,m096
  3233.     SELECT 3,26,4,m097
  3234.     SELECT 4,26,4,m098
  3235.     SELECT 5,26,4,m099
  3236.     SELECT 6,26,4,m100
  3237.     SELECT 7,26,4,m101
  3238.     SELECT 8,26,4,m102
  3239.     SELECT 9,26,4,m103
  3240.     SELECT 10,26,4,m104
  3241.     SELECT 11,26,4,m105
  3242.     SELECT 12,26,4,m106
  3243.     SELECT 13,26,4,m107
  3244.     SELECT 14,26,4,m108
  3245.     SELECT 15,26,4,m109
  3246.     SELECT 16,26,4,m110
  3247.     SELECT 17,26,4,m111
  3248.     SELECT 2,30,4,m112
  3249.     SELECT 3,30,4,m113
  3250.     SELECT 4,30,4,m114
  3251.     SELECT 5,30,4,m115
  3252.     SELECT 6,30,4,m116
  3253.     SELECT 7,30,4,m117
  3254.     SELECT 8,30,4,m118
  3255.     SELECT 9,30,4,m119
  3256.     SELECT 10,30,4,m120
  3257.     SELECT 11,30,4,m121
  3258.     SELECT 12,30,4,m122
  3259.     SELECT 13,30,4,m123
  3260.     SELECT 14,30,4,m124
  3261.     SELECT 15,30,4,m125
  3262.     SELECT 16,30,4,m126
  3263.     SELECT 17,30,4,m127
  3264.     SELECT 2,34,4,m128
  3265.     SELECT 3,34,4,m129
  3266.     SELECT 4,34,4,m130
  3267.     SELECT 5,34,4,m131
  3268.     SELECT 6,34,4,m132
  3269.     SELECT 7,34,4,m133
  3270.     SELECT 8,34,4,m134
  3271.     SELECT 9,34,4,m135
  3272.     SELECT 10,34,4,m136
  3273.     SELECT 11,34,4,m137
  3274.     SELECT 12,34,4,m138
  3275.     SELECT 13,34,4,m139
  3276.     SELECT 14,34,4,m140
  3277.     SELECT 15,34,4,m141
  3278.     SELECT 16,34,4,m142
  3279.     SELECT 17,34,4,m143
  3280.     SELECT 2,38,4,m144
  3281.     SELECT 3,38,4,m145
  3282.     SELECT 4,38,4,m146
  3283.     SELECT 5,38,4,m147
  3284.     SELECT 6,38,4,m148
  3285.     SELECT 7,38,4,m149
  3286.     SELECT 8,38,4,m150
  3287.     SELECT 9,38,4,m151
  3288.     SELECT 10,38,4,m152
  3289.     SELECT 11,38,4,m153
  3290.     SELECT 12,38,4,m154
  3291.     SELECT 13,38,4,m155
  3292.     SELECT 14,38,4,m156
  3293.     SELECT 15,38,4,m157
  3294.     SELECT 16,38,4,m158
  3295.     SELECT 17,38,4,m159
  3296.     SELECT 2,42,4,m160
  3297.     SELECT 3,42,4,m161
  3298.     SELECT 4,42,4,m162
  3299.     SELECT 5,42,4,m163
  3300.     SELECT 6,42,4,m164
  3301.     SELECT 7,42,4,m165
  3302.     SELECT 8,42,4,m166
  3303.     SELECT 9,42,4,m167
  3304.     SELECT 10,42,4,m168
  3305.     SELECT 11,42,4,m169
  3306.     SELECT 12,42,4,m170
  3307.     SELECT 13,42,4,m171
  3308.     SELECT 14,42,4,m172
  3309.     SELECT 15,42,4,m173
  3310.     SELECT 16,42,4,m174
  3311.     SELECT 17,42,4,m175
  3312.     SELECT 2,46,4,m176
  3313.     SELECT 3,46,4,m177
  3314.     SELECT 4,46,4,m178
  3315.     SELECT 5,46,4,m179
  3316.     SELECT 6,46,4,m180
  3317.     SELECT 7,46,4,m181
  3318.     SELECT 8,46,4,m182
  3319.     SELECT 9,46,4,m183
  3320.     SELECT 10,46,4,m184
  3321.     SELECT 11,46,4,m185
  3322.     SELECT 12,46,4,m186
  3323.     SELECT 13,46,4,m187
  3324.     SELECT 14,46,4,m188
  3325.     SELECT 15,46,4,m189
  3326.     SELECT 16,46,4,m190
  3327.     SELECT 17,46,4,m191
  3328.     SELECT 2,50,4,m192
  3329.     SELECT 3,50,4,m193
  3330.     SELECT 4,50,4,m194
  3331.     SELECT 5,50,4,m195
  3332.     SELECT 6,50,4,m196
  3333.     SELECT 7,50,4,m197
  3334.     SELECT 8,50,4,m198
  3335.     SELECT 9,50,4,m199
  3336.     SELECT 10,50,4,m200
  3337.     SELECT 11,50,4,m201
  3338.     SELECT 12,50,4,m202
  3339.     SELECT 13,50,4,m203
  3340.     SELECT 14,50,4,m204
  3341.     SELECT 15,50,4,m205
  3342.     SELECT 16,50,4,m206
  3343.     SELECT 17,50,4,m207
  3344.     SELECT 2,54,4,m208
  3345.     SELECT 3,54,4,m209
  3346.     SELECT 4,54,4,m210
  3347.     SELECT 5,54,4,m211
  3348.     SELECT 6,54,4,m212
  3349.     SELECT 7,54,4,m213
  3350.     SELECT 8,54,4,m214
  3351.     SELECT 9,54,4,m215
  3352.     SELECT 10,54,4,m216
  3353.     SELECT 11,54,4,m217
  3354.     SELECT 12,54,4,m218
  3355.     SELECT 13,54,4,m219
  3356.     SELECT 14,54,4,m220
  3357.     SELECT 15,54,4,m221
  3358.     SELECT 16,54,4,m222
  3359.     SELECT 17,54,4,m223
  3360.     SELECT 2,58,4,m224
  3361.     SELECT 3,58,4,m225
  3362.     SELECT 4,58,4,m226
  3363.     SELECT 5,58,4,m227
  3364.     SELECT 6,58,4,m228
  3365.     SELECT 7,58,4,m229
  3366.     SELECT 8,58,4,m230
  3367.     SELECT 9,58,4,m231
  3368.     SELECT 10,58,4,m232
  3369.     SELECT 11,58,4,m233
  3370.     SELECT 12,58,4,m234
  3371.     SELECT 13,58,4,m235
  3372.     SELECT 14,58,4,m236
  3373.     SELECT 15,58,4,m237
  3374.     SELECT 16,58,4,m238
  3375.     SELECT 17,58,4,m239
  3376.     SELECT 2,62,4,m240
  3377.     SELECT 3,62,4,m241
  3378.     SELECT 4,62,4,m242
  3379.     SELECT 5,62,4,m243
  3380.     SELECT 6,62,4,m244
  3381.     SELECT 7,62,4,m245
  3382.     SELECT 8,62,4,m246
  3383.     SELECT 9,62,4,m247
  3384.     SELECT 10,62,4,m248
  3385.     SELECT 11,62,4,m249
  3386.     SELECT 12,62,4,m250
  3387.     SELECT 13,62,4,m251
  3388.     SELECT 14,62,4,m252
  3389.     SELECT 15,62,4,m253
  3390.     SELECT 16,62,4,m254
  3391.     SELECT 17,62,4,m255
  3392.     PEND
  3393.  ;
  3394.  m001: MENU   "001",10,35,001
  3395.        option "Blue\Black",lb
  3396.        MEND
  3397.  ;
  3398.  m002: MENU   "002",10,35,002
  3399.        option "Green\Black",lb
  3400.        MEND
  3401.  ;
  3402.  m003: MENU   "003",10,35,003
  3403.        option "Cyan\Black",lb
  3404.        MEND
  3405.  ;
  3406.  m004: MENU   "004",10,35,004
  3407.        option "Red\Black",lb
  3408.        MEND
  3409.  ;
  3410.  m005: MENU   "005",10,35,005
  3411.        option "Magenta\Black",lb
  3412.        MEND
  3413.  ;
  3414.  m006: MENU   "006",10,35,006
  3415.        option "Brown \Black",lb
  3416.        MEND
  3417.  ;
  3418.  m007: MENU   "007",10,35,007
  3419.        option "White\Black",lb
  3420.        MEND
  3421.  ;
  3422.  m008: MENU   "008",10,35,008
  3423.        option "Gray\Black",lb
  3424.        MEND
  3425.  ;
  3426.  m009: MENU   "009",10,35,009
  3427.        option "Lt. Blue\Black",lb
  3428.        MEND
  3429.  ;
  3430.  m010: MENU   "010",10,35,010
  3431.        option "Lt. Green\Black",lb
  3432.        MEND
  3433.  ;
  3434.  m011: MENU   "011",10,35,011
  3435.        option "Lt. Cyan\Black",lb
  3436.        MEND
  3437.  ;
  3438.  m012: MENU   "012",10,35,012
  3439.        option "Lt. Red\Black",lb
  3440.        MEND
  3441.  ;
  3442.  m013: MENU   "013",10,35,013
  3443.        option "Lt. Magenta\Black",lb
  3444.        MEND
  3445.  ;
  3446.  m014: MENU   "014",10,35,014
  3447.        option "Yellow\Black",lb
  3448.        MEND
  3449.  ;
  3450.  m015: MENU   "015",10,35,015
  3451.        option "Hi-int. White\Black",lb
  3452.        MEND
  3453.  ;
  3454.  m016: MENU   "016",10,35,016
  3455.        option "Black\Blue",lb
  3456.        MEND
  3457.  ;
  3458.  m017: MENU   "017",10,35,017
  3459.        option "Blue\Blue",lb
  3460.        MEND
  3461.  ;
  3462.  m018: MENU   "018",10,35,018
  3463.        option "Green\Blue",lb
  3464.        MEND
  3465.  ;
  3466.  m019: MENU   "019",10,35,019
  3467.        option "Cyan\Blue",lb
  3468.        MEND
  3469.  ;
  3470.  m020: MENU   "020",10,35,020
  3471.        option "Red\Blue",lb
  3472.        MEND
  3473.  ;
  3474.  m021: MENU   "021",10,35,021
  3475.        option "Magenta\Blue",lb
  3476.        MEND
  3477.  ;
  3478.  m022: MENU   "022",10,35,022
  3479.        option "Brown\Blue",lb
  3480.        MEND
  3481.  ;
  3482.  m023: MENU   "023",10,35,023
  3483.        option "White\Blue",lb
  3484.        MEND
  3485.  ;
  3486.  m024: MENU   "024",10,35,024
  3487.        option "Gray\Blue",lb
  3488.        MEND
  3489.  ;
  3490.  m025: MENU    "025",10,35,025
  3491.        option "Lt. Blue\Blue",lb
  3492.        MEND
  3493.  ;
  3494.  m026: MENU   "026",10,35,026
  3495.        option "Lt. Green\Blue",lb
  3496.        MEND
  3497.  ;
  3498.  m027: MENU   "027",10,35,027
  3499.        option "Lt. Cyan\Blue",lb
  3500.        MEND
  3501.  ;
  3502.  m028: MENU   "028",10,35,028
  3503.        option "Lt. Red\Blue",lb
  3504.        MEND
  3505.  ;
  3506.  m029: MENU   "029",10,35,029
  3507.        option "Lt. Magenta\Blue",lb
  3508.        MEND
  3509.  ;
  3510.  m030: MENU   "030",10,35,030
  3511.        option "Yellow\Blue",lb
  3512.        MEND
  3513.  ;
  3514.  m031: MENU   "031",10,35,031
  3515.        option "Hi-int. White\Blue",lb
  3516.        MEND
  3517.  ;
  3518.  m032: MENU   "032",10,35,032
  3519.        option "Black\Green",lb
  3520.        MEND
  3521.  ;
  3522.  m033: MENU   "033",10,35,033
  3523.        option "Blue\Green",lb
  3524.        MEND
  3525.  ;
  3526.  m034: MENU   "034",10,35,034
  3527.        option "Green\Green",lb
  3528.        MEND
  3529.  ;
  3530.  m035: MENU   "035",10,35,035
  3531.        option "Cyan\Green",lb
  3532.        MEND
  3533.  ;
  3534.  m036: MENU   "036",10,35,036
  3535.        option "Red\Green",lb
  3536.        MEND
  3537.  ;
  3538.  m037: MENU   "037",10,35,037
  3539.        option "Magenta\Green",lb
  3540.        MEND
  3541.  ;
  3542.  m038: MENU   "038",10,35,038
  3543.        option "Brown\Green",lb
  3544.        MEND
  3545.  ;
  3546.  m039: MENU   "039",10,35,039
  3547.        option "White\Green",lb
  3548.        MEND
  3549.  ;
  3550.  m040: MENU   "040",10,35,040
  3551.        option "Gray\Green",lb
  3552.        MEND
  3553.  ;
  3554.  m041: MENU   "041",10,35,041
  3555.        option "Lt. Blue\Green",lb
  3556.        MEND
  3557.  ;
  3558.  m042: MENU   "042",10,35,042
  3559.        option "Lt. Green\Green",lb
  3560.        MEND
  3561.  ;
  3562.  m043: MENU   "043",10,35,043
  3563.        option "Lt. Cyan\Green",lb
  3564.        MEND
  3565.  ;
  3566.  m044: MENU   "044",10,35,044
  3567.        option "Lt. Red\Green",lb
  3568.        MEND
  3569.  ;
  3570.  m045: MENU   "045",10,35,045
  3571.        option "Lt. Magenta\Green",lb
  3572.        MEND
  3573.  ;
  3574.  m046: MENU   "046",10,35,046
  3575.        option "Yellow\Green",lb
  3576.        MEND
  3577.  ;
  3578.  m047: MENU   "047",10,35,047
  3579.        option "Hi-int. White\Green",lb
  3580.        MEND
  3581.  ;
  3582.  m048: MENU   "048",10,35,048
  3583.        option "Black\Cyan",lb
  3584.        MEND
  3585.  ;
  3586.  m049: MENU   "049",10,35,049
  3587.        option "Blue\Cyan",lb
  3588.        MEND
  3589.  ;
  3590.  m050: MENU   "050",10,35,050
  3591.        option "Green\Cyan",lb
  3592.        MEND
  3593.  ;
  3594.  m051: MENU   "051",10,35,051
  3595.        option "Cyan\Cyan",lb
  3596.        MEND
  3597.  ;
  3598.  m052: MENU   "052",10,35,052
  3599.        option "Red\Cyan",lb
  3600.        MEND
  3601.  ;
  3602.  m053: MENU   "053",10,35,053
  3603.        option "Magenta\Cyan",lb
  3604.        MEND
  3605.  ;
  3606.  m054: MENU   "054",10,35,054
  3607.        option "Brown\Cyan",lb
  3608.        MEND
  3609.  ;
  3610.  m055: MENU   "055",10,35,055
  3611.        option "White\Cyan",lb
  3612.        MEND
  3613.  ;
  3614.  m056: MENU   "056",10,35,056
  3615.        option "Gray\Cyan",lb
  3616.        MEND
  3617.  ;
  3618.  m057: MENU   "057",10,35,057
  3619.        option "Lt. Blue\Cyan",lb
  3620.        MEND
  3621.  ;
  3622.  m058: MENU   "058",10,35,058
  3623.        option "Lt. Green\Cyan",lb
  3624.        MEND
  3625.  ;
  3626.  m059: MENU   "059",10,35,059
  3627.        option "Lt. Cyan\Cyan",lb
  3628.        MEND
  3629.  ;
  3630.  m060: MENU   "060",10,35,060
  3631.        option "Lt. Red\Cyan",lb
  3632.        MEND
  3633.  ;
  3634.  m061: MENU   "061",10,35,061
  3635.        option "Lt. Magenta\Cyan",lb
  3636.        MEND
  3637.  ;
  3638.  m062: MENU   "062",10,35,062
  3639.        option "Yellow\Cyan",lb
  3640.        MEND
  3641.  ;
  3642.  m063: MENU   "063",10,35,063
  3643.        option "Hi-int. White\Cyan",lb
  3644.        MEND
  3645.  ;
  3646.  m064: MENU   "064",10,35,064
  3647.        option "Black\Red",lb
  3648.        MEND
  3649.  ;
  3650.  m065: MENU   "065",10,35,065
  3651.        option "Blue\Red",lb
  3652.        MEND
  3653.  ;
  3654.  m066: MENU   "066",10,35,066
  3655.        option "Green\Red",lb
  3656.        MEND
  3657.  ;
  3658.  m067: MENU   "067",10,35,067
  3659.        option "Cyan\Red",lb
  3660.        MEND
  3661.  ;
  3662.  m068: MENU   "068",10,35,068
  3663.        option "Red\Red",lb
  3664.        MEND
  3665.  ;
  3666.  m069: MENU   "069",10,35,069
  3667.        option "Magenta\Red",lb
  3668.        MEND
  3669.  ;
  3670.  m070: MENU   "070",10,35,070
  3671.        option "Brown\Red",lb
  3672.        MEND
  3673.  ;
  3674.  m071: MENU   "071",10,35,071
  3675.        option "White\Red",lb
  3676.        MEND
  3677.  ;
  3678.  m072: MENU   "072",10,35,072
  3679.        option "Gray\Red",lb
  3680.        MEND
  3681.  ;
  3682.  m073: MENU   "073",10,35,073
  3683.        option "Lt. Blue\Red",lb
  3684.        MEND
  3685.  ;
  3686.  m074: MENU   "074",10,35,074
  3687.        option "Lt. Green\Red",lb
  3688.        MEND
  3689.  ;
  3690.  m075: MENU   "075",10,35,075
  3691.        option "Lt. Cyan\Red",lb
  3692.        MEND
  3693.  ;
  3694.  m076: MENU   "076",10,35,076
  3695.        option "Lt. Red\Red",lb
  3696.        MEND
  3697.  ;
  3698.  m077: MENU   "077",10,35,077
  3699.        option "Lt. Magenta\Red",lb
  3700.        MEND
  3701.  ;
  3702.  m078: MENU   "078",10,35,078
  3703.        option "Yellow\Red",lb
  3704.        MEND
  3705.  ;
  3706.  m079: MENU   "079",10,35,079
  3707.        option "Hi-int. White\Red",lb
  3708.        MEND
  3709.  ;
  3710.  m080: MENU   "080",10,35,080
  3711.        option "Black\Magenta",lb
  3712.        MEND
  3713.  ;
  3714.  m081: MENU   "081",10,35,081
  3715.        option "Blue\Magenta",lb
  3716.        MEND
  3717.  ;
  3718.  m082: MENU   "082",10,35,082
  3719.        option "Green\Magenta",lb
  3720.        MEND
  3721.  ;
  3722.  m083: MENU   "083",10,35,083
  3723.        option "Cyan\Magenta",lb
  3724.        MEND
  3725.  ;
  3726.  m084: MENU   "084",10,35,084
  3727.        option "Red\Magenta",lb
  3728.        MEND
  3729.  ;
  3730.  m085: MENU   "085",10,35,085
  3731.        option "Magenta\Magenta",lb
  3732.        MEND
  3733.  ;
  3734.  m086: MENU   "086",10,35,086
  3735.        option "Brown\Magenta",lb
  3736.        MEND
  3737.  ;
  3738.  m087: MENU   "087",10,35,087
  3739.        option "White\Magenta",lb
  3740.        MEND
  3741.  ;
  3742.  m088: MENU   "088",10,35,088
  3743.        option "Gray\Magenta",lb
  3744.        MEND
  3745.  ;
  3746.  m089: MENU   "089",10,35,089
  3747.        option "Lt. Blue\Magenta",lb
  3748.        MEND
  3749.  ;
  3750.  m090: MENU   "090",10,35,090
  3751.        option "Lt. Green\Magenta",lb
  3752.        MEND
  3753.  ;
  3754.  m091: MENU   "091",10,35,091
  3755.        option "Lt. Cyan\Magenta",lb
  3756.        MEND
  3757.  ;
  3758.  m092: MENU   "092",10,35,092
  3759.        option "Lt. Red\Magenta",lb
  3760.        MEND
  3761.  ;
  3762.  m093: MENU   "093",10,35,093
  3763.        option "Lt. Magenta\Magenta",lb
  3764.        MEND
  3765.  ;
  3766.  m094: MENU   "094",10,35,094
  3767.        option "Yellow\Magenta",lb
  3768.        MEND
  3769.  ;
  3770.  m095: MENU   "095",10,35,095
  3771.        option "Hi-int. White\Magenta",lb
  3772.        MEND
  3773.  ;
  3774.  m096: MENU   "096",10,35,096
  3775.        option "Black\Brown",lb
  3776.        MEND
  3777.  ;
  3778.  m097: MENU   "097",10,35,097
  3779.        option "Blue\Brown",lb
  3780.        MEND
  3781.  ;
  3782.  m098: MENU   "098",10,35,098
  3783.        option "Green\Brown",lb
  3784.        MEND
  3785.  ;
  3786.  m099: MENU   "099",10,35,099
  3787.        option "Cyan\Brown",lb
  3788.        MEND
  3789.  ;
  3790.  m100: MENU   "100",10,35,100
  3791.        option "Red\Brown",lb
  3792.        MEND
  3793.  ;
  3794.  m101: MENU   "101",10,35,101
  3795.        option "Magenta\Brown",lb
  3796.        MEND
  3797.  ;
  3798.  m102: MENU   "102",10,35,102
  3799.        option "Brown\Brown",lb
  3800.        MEND
  3801.  ;
  3802.  m103: MENU   "103",10,35,103
  3803.        option "White\Brown",lb
  3804.        MEND
  3805.  ;
  3806.  m104: MENU   "104",10,35,104
  3807.        option "Gray\Brown",lb
  3808.        MEND
  3809.  ;
  3810.  m105: MENU   "105",10,35,105
  3811.        option "Lt. Blue\Brown",lb
  3812.        MEND
  3813.  ;
  3814.  m106: MENU   "106",10,35,106
  3815.        option "Lt. Green\Brown",lb
  3816.        MEND
  3817.  ;
  3818.  m107: MENU   "107",10,35,107
  3819.        option "Lt. Cyan\Brown",lb
  3820.        MEND
  3821.  ;
  3822.  m108: MENU   "108",10,35,108
  3823.        option "Lt. Red\Brown",lb
  3824.        MEND
  3825.  ;
  3826.  m109: MENU   "109",10,35,109
  3827.        option "Lt. Magenta\Brown",lb
  3828.        MEND
  3829.  ;
  3830.  m110: MENU   "110",10,35,110
  3831.        option "Yellow\Brown",lb
  3832.        MEND
  3833.  ;
  3834.  m111: MENU   "111",10,35,111
  3835.        option "Hi-int. White\Brown",lb
  3836.        MEND
  3837.  ;
  3838.  m112: MENU   "112",10,35,112
  3839.        option "Black\White",lb
  3840.        MEND
  3841.  ;
  3842.  m113: MENU   "113",10,35,113
  3843.        option "Blue\White",lb
  3844.        MEND
  3845.  ;
  3846.  m114: MENU   "114",10,35,114
  3847.        option "Green\White",lb
  3848.        MEND
  3849.  ;
  3850.  m115: MENU   "115",10,35,115
  3851.        option "Cyan\White",lb
  3852.        MEND
  3853.  ;
  3854.  m116: MENU   "116",10,35,116
  3855.        option "Red\White",lb
  3856.        MEND
  3857.  ;
  3858.  m117: MENU   "117",10,35,117
  3859.        option "Magenta\White",lb
  3860.        MEND
  3861.  ;
  3862.  m118: MENU   "118",10,35,118
  3863.        option "Brown\White",lb
  3864.        MEND
  3865.  ;
  3866.  m119: MENU   "119",10,35,119
  3867.        option "White\White",lb
  3868.        MEND
  3869.  ;
  3870.  m120: MENU   "120",10,35,120
  3871.        option "Gray\White",lb
  3872.        MEND
  3873.  ;
  3874.  m121: MENU   "121",10,35,121
  3875.        option "Lt. Blue\White",lb
  3876.        MEND
  3877.  ;
  3878.  m122: MENU   "122",10,35,122
  3879.        option "Lt. Green\White",lb
  3880.        MEND
  3881.  ;
  3882.  m123: MENU   "123",10,35,123
  3883.        option "Lt. Cyan\White",lb
  3884.        MEND
  3885.  ;
  3886.  m124: MENU   "124",10,35,124
  3887.        option "Lt. Red\White",lb
  3888.        MEND
  3889.  ;
  3890.  m125: MENU   "125",10,35,125
  3891.        option "Lt. Magenta\White",lb
  3892.        MEND
  3893.  ;
  3894.  m126: MENU   "126",10,35,126
  3895.        option "Yellow\White",lb
  3896.        MEND
  3897.  ;
  3898.  m127: MENU   "127",10,35,127
  3899.        option "Hi-int White\White",lb
  3900.        MEND
  3901.  ;
  3902.  m128: MENU   "128",10,35,128
  3903.        option "Black\Gray",lb
  3904.        MEND
  3905.  ;
  3906.  m129: MENU   "129",10,35,129
  3907.        option "Blue\Gray",lb
  3908.        MEND
  3909.  ;
  3910.  m130: MENU   "130",10,35,130
  3911.        option "Green\Gray",lb
  3912.        MEND
  3913.  ;
  3914.  m131: MENU   "131",10,35,131
  3915.        option "Cyan\Gray",lb
  3916.        MEND
  3917.  ;
  3918.  m132: MENU   "132",10,35,132
  3919.        option "Red\Gray",lb
  3920.        MEND
  3921.  ;
  3922.  m133: MENU   "133",10,35,133
  3923.        option "Magenta\Gray",lb
  3924.        MEND
  3925.  ;
  3926.  m134: MENU   "134",10,35,134
  3927.        option "Brown\Gray",lb
  3928.        MEND
  3929.  ;
  3930.  m135: MENU   "135",10,35,135
  3931.        option "White\Gray",lb
  3932.        MEND
  3933.  ;
  3934.  m136: MENU   "136",10,35,136
  3935.        option "Gray\Gray",lb
  3936.        MEND
  3937.  ;
  3938.  m137: MENU   "137",10,35,137
  3939.        option "Lt. Blue\Gray",lb
  3940.        MEND
  3941.  ;
  3942.  m138: MENU   "138",10,35,138
  3943.        option "Lt. Green\Gray",lb
  3944.        MEND
  3945.  ;
  3946.  m139: MENU   "139",10,35,139
  3947.        option "Lt. Cyan\Gray",lb
  3948.        MEND
  3949.  ;
  3950.  m140: MENU   "140",10,35,140
  3951.        option "Lt. Red\Gray",lb
  3952.        MEND
  3953.  ;
  3954.  m141: MENU   "141",10,35,141
  3955.        option "Lt. Magenta\Gray",lb
  3956.        MEND
  3957.  ;
  3958.  m142: MENU   "142",10,35,142
  3959.        option "Yellow\Gray",lb
  3960.        MEND
  3961.  ;
  3962.  m143: MENU   "143",10,35,143
  3963.        option "Hi-int. White\Gray",lb
  3964.        MEND
  3965.  ;
  3966.  m144: MENU   "144",10,35,144
  3967.        option "Black\Lt. Blue",lb
  3968.        MEND
  3969.  ;
  3970.  m145: MENU   "145",10,35,145
  3971.        option "Blue\Lt. Blue",lb
  3972.        MEND
  3973.  ;
  3974.  m146: MENU   "146",10,35,146
  3975.        option "Green\Lt. Blue",lb
  3976.        MEND
  3977.  ;
  3978.  m147: MENU   "147",10,35,147
  3979.        option "Cyan\Lt. Blue",lb
  3980.        MEND
  3981.  ;
  3982.  m148: MENU   "148",10,35,148
  3983.        option "Red\Lt. Blue",lb
  3984.        MEND
  3985.  ;
  3986.  m149: MENU   "149",10,35,149
  3987.        option "Magenta\Lt. Blue",lb
  3988.        MEND
  3989.  ;
  3990.  m150: MENU   "150",10,35,150
  3991.        option "Brown\Lt. Blue",lb
  3992.        MEND
  3993.  ;
  3994.  m151: MENU   "151",10,35,151
  3995.        option "White\Lt. Blue",lb
  3996.        MEND
  3997.  ;
  3998.  m152: MENU   "152",10,35,152
  3999.        option "Gray\Lt. Blue",lb
  4000.        MEND
  4001.  ;
  4002.  m153: MENU   "153",10,35,153
  4003.        option "Lt. Blue\Lt. Blue",lb
  4004.        MEND
  4005.  ;
  4006.  m154: MENU   "154",10,35,154
  4007.        option "Lt. Green\Lt. Blue",lb
  4008.        MEND
  4009.  ;
  4010.  m155: MENU   "155",10,35,155
  4011.        option "Lt. Cyan\Lt. Blue",lb
  4012.        MEND
  4013.  ;
  4014.  m156: MENU   "156",10,35,156
  4015.        option "Lt. Red\Lt. Blue",lb
  4016.        MEND
  4017.  ;
  4018.  m157: MENU   "157",10,35,157
  4019.        option "Lt. Magenta\Lt. Blue",lb
  4020.        MEND
  4021.  ;
  4022.  m158: MENU   "158",10,35,158
  4023.        option "Yellow\Lt. Blue",lb
  4024.        MEND
  4025.  ;
  4026.  m159: MENU   "159",10,35,159
  4027.        option "Hi-int. White\Lt. Blue",lb
  4028.        MEND
  4029.  ;
  4030.  m160: MENU   "160",10,35,160
  4031.        option "Black\Lt. Green",lb
  4032.        MEND
  4033.  ;
  4034.  m161: MENU   "161",10,35,161
  4035.        option "Blue\Lt. Green",lb
  4036.        MEND
  4037.  ;
  4038.  m162: MENU   "162",10,35,162
  4039.        option "Green\Lt. Green",lb
  4040.        MEND
  4041.  ;
  4042.  m163: MENU   "163",10,35,163
  4043.        option "Cyan\Lt. Green",lb
  4044.        MEND
  4045.  ;
  4046.  m164: MENU   "164",10,35,164
  4047.        option "Red\Lt. Green",lb
  4048.        MEND
  4049.  ;
  4050.  m165: MENU   "165",10,35,165
  4051.        option "Magenta\Lt. Green",lb
  4052.        MEND
  4053.  ;
  4054.  m166: MENU   "166",10,35,166
  4055.        option "Brown\Lt. Green",lb
  4056.        MEND
  4057.  ;
  4058.  m167: MENU   "167",10,35,167
  4059.        option "White\Lt. Green",lb
  4060.        MEND
  4061.  ;
  4062.  m168: MENU   "168",10,35,168
  4063.        option "Gray\Lt. Green",lb
  4064.        MEND
  4065.  ;
  4066.  m169: MENU   "169",10,35,169
  4067.        option "Lt. Blue\Lt. Green",lb
  4068.        MEND
  4069.  ;
  4070.  m170: MENU   "170",10,35,170
  4071.        option "Lt. Green\Lt. Green",lb
  4072.        MEND
  4073.  ;
  4074.  m171: MENU   "171",10,35,171
  4075.        option "Lt. Cyan\Lt. Green",lb
  4076.        MEND
  4077.  ;
  4078.  m172: MENU   "172",10,35,172
  4079.        option "Lt. Red\Lt. Green",lb
  4080.        MEND
  4081.  ;
  4082.  m173: MENU   "173",10,35,173
  4083.        option "Lt. Magenta\Lt. Green",lb
  4084.        MEND
  4085.  ;
  4086.  m174: MENU   "174",10,35,174
  4087.        option "Yellow\Lt. Green",lb
  4088.        MEND
  4089.  ;
  4090.  m175: MENU   "175",10,35,175
  4091.        option "Hi-int. White\Lt. Green",lb
  4092.        MEND
  4093.  ;
  4094.  m176: MENU   "176",10,35,176
  4095.        option "Black\Lt. Cyan",lb
  4096.        MEND
  4097.  ;
  4098.  m177: MENU   "177",10,35,177
  4099.        option "Blue\Lt. Cyan",lb
  4100.        MEND
  4101.  ;
  4102.  m178: MENU   "178",10,35,178
  4103.        option "Green\Lt. Cyan",lb
  4104.        MEND
  4105.  ;
  4106.  m179: MENU   "179",10,35,179
  4107.        option "Cyan\Lt. Cyan",lb
  4108.        MEND
  4109.  ;
  4110.  m180: MENU   "180",10,35,180
  4111.        option "Red\Lt. Cyan",lb
  4112.        MEND
  4113.  ;
  4114.  m181: MENU   "181",10,35,181
  4115.        option "Magenta\Lt. Cyan",lb
  4116.        MEND
  4117.  ;
  4118.  m182: MENU   "182",10,35,182
  4119.        option "Brown\Lt. Cyan",lb
  4120.        MEND
  4121.  ;
  4122.  m183: MENU   "183",10,35,183
  4123.        option "White\Lt. Cyan",lb
  4124.        MEND
  4125.  ;
  4126.  m184: MENU   "184",10,35,184
  4127.        option "Gray\Lt. Cyan",lb
  4128.        MEND
  4129.  ;
  4130.  m185: MENU   "185",10,35,185
  4131.        option "Lt. Blue\Lt. Cyan",lb
  4132.        MEND
  4133.  ;
  4134.  m186: MENU   "186",10,35,186
  4135.        option "Lt. Green\Lt. Cyan",lb
  4136.        MEND
  4137.  ;
  4138.  m187: MENU   "187",10,35,187
  4139.        option "Lt. Cyan\Lt. Cyan",lb
  4140.        MEND
  4141.  ;
  4142.  m188: MENU   "188",10,35,188
  4143.        option "Lt. Red\Lt. Cyan",lb
  4144.        MEND
  4145.  ;
  4146.  m189: MENU   "189",10,35,189
  4147.        option "Lt. Magenta\Lt. Cyan",lb
  4148.        MEND
  4149.  ;
  4150.  m190: MENU   "190",10,35,190
  4151.        option "Yellow\Lt. Cyan",lb
  4152.        MEND
  4153.  ;
  4154.  m191: MENU   "191",10,35,191
  4155.        option "Hi-int. White\Lt. Cyan",lb
  4156.        MEND
  4157.  ;
  4158.  m192: MENU   "192",10,35,192
  4159.        option "Black\Lt. Red",lb
  4160.        MEND
  4161.  ;
  4162.  m193: MENU   "193",10,35,193
  4163.        option "Blue\Lt. Red",lb
  4164.        MEND
  4165.  ;
  4166.  m194: MENU   "194",10,35,194
  4167.        option "Green\Lt. Red",lb
  4168.        MEND
  4169.  ;
  4170.  m195: MENU   "195",10,35,195
  4171.        option "Cyan\Lt. Red",lb
  4172.        MEND
  4173.  ;
  4174.  m196: MENU   "196",10,35,196
  4175.        option "Red\Lt. Red",lb
  4176.        MEND
  4177.  ;
  4178.  m197: MENU   "197",10,35,197
  4179.        option "Magenta\Lt. Red",lb
  4180.        MEND
  4181.  ;
  4182.  m198: MENU   "198",10,35,198
  4183.        option "Brown\Lt. Red",lb
  4184.        MEND
  4185.  ;
  4186.  m199: MENU   "199",10,35,199
  4187.        option "White\Lt. Red",lb
  4188.        MEND
  4189.  ;
  4190.  m200: MENU   "200",10,35,200
  4191.        option "Gray\Lt. Red",lb
  4192.        MEND
  4193.  ;
  4194.  m201: MENU   "201",10,35,201
  4195.        option "Lt. Blue\Lt. Red",lb
  4196.        MEND
  4197.  ;
  4198.  m202: MENU   "202",10,35,202
  4199.        option "Lt. Green\Lt. Red",lb
  4200.        MEND
  4201.  ;
  4202.  m203: MENU   "203",10,35,203
  4203.        option "Lt. Cyan\Lt. Red",lb
  4204.        MEND
  4205.  ;
  4206.  m204: MENU   "204",10,35,204
  4207.        option "Lt. Red\Lt. Red",lb
  4208.        MEND
  4209.  ;
  4210.  m205: MENU   "205",10,35,205
  4211.        option "Lt. Magenta\Lt. Red",lb
  4212.        MEND
  4213.  ;
  4214.  m206: MENU   "206",10,35,206
  4215.        option "Yellow\Lt. Red",lb
  4216.        MEND
  4217.  ;
  4218.  m207: MENU   "207",10,35,207
  4219.        option "Hi-int. White\Lt. Red",lb
  4220.        MEND
  4221.  ;
  4222.  m208: MENU   "208",10,35,208
  4223.        option "Black\Lt. Magenta",lb
  4224.        MEND
  4225.  ;
  4226.  m209: MENU   "209",10,35,209
  4227.        option "Blue\Lt. Magenta",lb
  4228.        MEND
  4229.  ;
  4230.  m210: MENU   "210",10,35,210
  4231.        option "Green\Lt. Magenta",lb
  4232.        MEND
  4233.  ;
  4234.  m211: MENU   "211",10,35,211
  4235.        option "Cyan\Lt. Magenta",lb
  4236.        MEND
  4237.  ;
  4238.  m212: MENU   "212",10,35,212
  4239.        option "Red\Lt. Magenta",lb
  4240.        MEND
  4241.  ;
  4242.  m213: MENU   "213",10,35,213
  4243.        option "Magenta\Lt. Magenta",lb
  4244.        MEND
  4245.  ;
  4246.  m214: MENU   "214",10,35,214
  4247.        option "Brown\Lt. Magenta",lb
  4248.        MEND
  4249.  ;
  4250.  m215: MENU   "215",10,35,215
  4251.        option "White\Lt. Magenta",lb
  4252.        MEND
  4253.  ;
  4254.  m216: MENU   "216",10,35,216
  4255.        option "Gray\Lt. Magenta",lb
  4256.        MEND
  4257.  ;
  4258.  m217: MENU   "217",10,35,217
  4259.        option "Lt. Blue\Lt. Magenta",lb
  4260.        MEND
  4261.  ;
  4262.  m218: MENU   "218",10,35,218
  4263.        option "Lt. Green\Lt. Magenta",lb
  4264.        MEND
  4265.  ;
  4266.  m219: MENU   "219",10,35,219
  4267.        option "Lt. Cyan\Lt. Magenta",lb
  4268.        MEND
  4269.  ;
  4270.  m220: MENU   "220",10,35,220
  4271.        option "Lt. Red\Lt. Magenta",lb
  4272.        MEND
  4273.  ;
  4274.  m221: MENU   "221",10,35,221
  4275.        option "Lt. Magenta\Lt. Magenta",lb
  4276.        MEND
  4277.  ;
  4278.  m222: MENU   "222",10,35,222
  4279.        option "Yellow\Lt. Magenta",lb
  4280.        MEND
  4281.  ;
  4282.  m223: MENU   "223",10,35,223
  4283.        option "Hi-int. White\Lt. Magenta",lb
  4284.        MEND
  4285.  ;
  4286.  m224: MENU   "224",10,35,224
  4287.        option "Black\Yellow",lb
  4288.        MEND
  4289.  ;
  4290.  m225: MENU   "225",10,35,225
  4291.        option "Blue\Yellow",lb
  4292.        MEND
  4293.  ;
  4294.  m226: MENU   "226",10,35,226
  4295.        option "Green\Yellow",lb
  4296.        MEND
  4297.  ;
  4298.  m227: MENU   "227",10,35,227
  4299.        option "Cyan\Yellow",lb
  4300.        MEND
  4301.  ;
  4302.  m228: MENU   "228",10,35,228
  4303.        option "Red\Yellow",lb
  4304.        MEND
  4305.  ;
  4306.  m229: MENU   "229",10,35,229
  4307.        option "Magenta\Yellow",lb
  4308.        MEND
  4309.  ;
  4310.  m230: MENU   "230",10,35,230
  4311.        option "Brown\Yellow",lb
  4312.        MEND
  4313.  ;
  4314.  m231: MENU   "231",10,35,231
  4315.        option "White\Yellow",lb
  4316.        MEND
  4317.  ;
  4318.  m232: MENU   "232",10,35,232
  4319.        option "Gray\Yellow",lb
  4320.        MEND
  4321.  ;
  4322.  m233: MENU   "233",10,35,233
  4323.        option "Lt. Blue\Yellow",lb
  4324.        MEND
  4325.  ;
  4326.  m234: MENU   "234",10,35,234
  4327.        option "Lt. Green\Yellow",lb
  4328.        MEND
  4329.  ;
  4330.  m235: MENU   "235",10,35,235
  4331.        option "Lt. Cyan\Yellow",lb
  4332.        MEND
  4333.  ;
  4334.  m236: MENU   "236",10,35,236
  4335.        option "Lt. Red\Yellow",lb
  4336.        MEND
  4337.  ;
  4338.  m237: MENU   "237",10,35,237
  4339.        option "Lt. Magenta\Yellow",lb
  4340.        MEND
  4341.  ;
  4342.  m238: MENU   "238",10,35,238
  4343.        option "Yellow\Yellow",lb
  4344.        MEND
  4345.  ;
  4346.  m239: MENU   "239",10,35,239
  4347.        option "Hi-int. White\Yellow",lb
  4348.        MEND
  4349.  ;
  4350.  m240: MENU   "240",10,35,240
  4351.        option "Black\Hi-int. White",lb
  4352.        MEND
  4353.  ;
  4354.  m241: MENU   "241",10,35,241
  4355.        option "Blue\Hi-int. White",lb
  4356.        MEND
  4357.  ;
  4358.  m242: MENU   "242",10,35,242
  4359.        option "Green\Hi-int. White",lb
  4360.        MEND
  4361.  ;
  4362.  m243: MENU   "243",10,35,243
  4363.        option "Cyan\Hi-int. White",lb
  4364.        MEND
  4365.  ;
  4366.  m244: MENU   "244",10,35,244
  4367.        option "Red\Hi-int. White",lb
  4368.        MEND
  4369.  ;
  4370.  m245: MENU   "245",10,35,245
  4371.        option "Magenta\Hi-int. White",lb
  4372.        MEND
  4373.  ;
  4374.  m246: MENU   "246",10,35,246
  4375.        option "Brown\Hi-int. White",lb
  4376.        MEND
  4377.  ;
  4378.  m247: MENU   "247",10,35,247
  4379.        option "White\Hi-int. White",lb
  4380.        MEND
  4381.  ;
  4382.  m248: MENU   "248",10,35,248
  4383.        option "Gray\Hi-int. White",lb
  4384.        MEND
  4385.  ;
  4386.  m249: MENU   "249",10,35,249
  4387.        option "Lt. Blue\Hi-int. White",lb
  4388.        MEND
  4389.  ;
  4390.  m250: MENU   "250",10,35,250
  4391.        option "Lt. Green\Hi-int. White",lb
  4392.        MEND
  4393.  ;
  4394.  m251: MENU   "251",10,35,251
  4395.        option "Lt. Cyan\Hi-int. White",lb
  4396.        MEND
  4397.  ;
  4398.  m252: MENU   "252",10,35,252
  4399.        option "Lt. Red\Hi-int. White",lb
  4400.        MEND
  4401.  ;
  4402.  m253: MENU   "253",10,35,253
  4403.        option "Lt. Magenta\Hi-int. White",lb
  4404.        MEND
  4405.  ;
  4406.  m254: MENU   "254",10,35,254
  4407.        option "Yellow\Hi-int. White",lb
  4408.        MEND
  4409.  ;
  4410.  m255: MENU   "255",10,35,255
  4411.        option "Hi-int. White\Hi-int. White",lb
  4412.        MEND
  4413.  ;
  4414.  
  4415.  \SAMPCODE\MOUSE\SOURCES\DROP.DEF
  4416.  
  4417.  ;       SAMPLE Microsoft Mouse 'DROP' MENU
  4418.  ;
  4419.  ; Note: Please review the comments below before you compile
  4420.  ;       and use this source file as a mouse menu.
  4421.  
  4422.  ; The DROP mouse menu demonstrates how to create 'drop-
  4423.  ; down' menus.
  4424.  ;
  4425.  ; Clicking a mouse button when the cursor is on the main
  4426.  ; menu (drop1) will display a drop-down menu (except in the
  4427.  ; case of the 'CLR SCRN' field, which will cause a screen-
  4428.  ; clear command to be executed).
  4429.  ;
  4430.  ; Clicking a mouse button when the cursor is on the top
  4431.  ; entry of a drop-down menu will redisplay the main menu.
  4432.  ;
  4433.  ; Since the entire area underneath the main menu will be
  4434.  ; written over by each drop-down menu, you should use a
  4435.  ; BLACK background for this type of mouse menu.
  4436.  ;
  4437.  ; When you choose a drop-down menu, the initial position of
  4438.  ; the cursor is always the upper-left corner of the area
  4439.  ; defined by the set of SELECT statements associated with
  4440.  ; the menu.
  4441.  ;
  4442.  ;
  4443.  BEGIN lb
  4444.  ;
  4445.  lb:     execute drop1
  4446.  rb:     execute drop2
  4447.  bb:     execute drop3
  4448.  nul:    nothing
  4449.  ;
  4450.  drop1:  POPUP 1,40,NORMAL
  4451.          text "╔══════════╤══════════╤══════════╗"
  4452.          text "║ CLR SCRN │ LIST DIR │ CH DRIVE ║"
  4453.          text "╚══════════╧══════════╧══════════╝"
  4454.          select 2,2,10,cls
  4455.          select 2,13,10,rb
  4456.          select 2,24,10,bb
  4457.          PEND
  4458.  ;
  4459.  cls:    type "cls",enter
  4460.  ;
  4461.  drop2:  POPUP 1,40,NORMAL
  4462.          text "╔══════════╦══════════╦══════════╗"
  4463.          text "║ CLR SCRN ║ LIST DIR ║ CH DRIVE ║"
  4464.          text "╚══════════╬══════════╬══════════╝"
  4465.          text "           ║   dir    ║"
  4466.          text "           ║  *.bat   ║"
  4467.          text "           ║  *.com   ║"
  4468.          text "           ║  *.doc   ║"
  4469.          text "           ║  *.exe   ║"
  4470.          text "           ║  *.sys   ║"
  4471.          text "           ║  CANCEL  ║"
  4472.          text "           ╚══════════╝"
  4473.        select 2,13,10,lb
  4474.        select 3,13,10,rb
  4475.        select 4,13,10,dir
  4476.        select 5,13,10,dirb
  4477.        select 6,13,10,dirc
  4478.        select 7,13,10,dird
  4479.        select 8,13,10,dire
  4480.        select 9,13,10,dirs
  4481.        select 10,13,10,nul
  4482.        PEND
  4483.  ;
  4484.  dir:        type "dir",enter
  4485.  dirb:       type "dir *.bat",enter
  4486.  dirc:       type "dir *.com",enter
  4487.  dird:       type "dir *.doc",enter
  4488.  dire:       type "dir *.exe",enter
  4489.  dirs:       type "dir *.sys",enter
  4490.  ;
  4491.  drop3:  POPUP 1,40,NORMAL
  4492.          text "╔══════════╤══════════╦══════════╗"
  4493.          text "║ CLR SCRN │ LIST DIR ║ CH DRIVE ║"
  4494.          text "╚══════════╧══════════╬══════════╣"
  4495.          text "                      ║    A:    ║"
  4496.          text "                      ║    B:    ║"
  4497.          text "                      ║    C:    ║"
  4498.          text "                      ║  CANCEL  ║"
  4499.          text "                      ╚══════════╝"
  4500.          select 2,24,10,lb
  4501.          select 3,24,10,bb
  4502.          select 4,24,10,a
  4503.          select 5,24,10,b
  4504.          select 6,24,10,c
  4505.          select 7,24,10,nul
  4506.          PEND
  4507.  ;
  4508.  a:      type "A:",enter,"cls",enter,enter
  4509.  b:      type "B:",enter,"cls",enter,enter
  4510.  c:      type "C:",enter,"cls",enter,enter
  4511.  ;
  4512.  
  4513.  \SAMPCODE\MOUSE\SOURCES\EXECUTE1.DEF
  4514.  
  4515.  ;       SAMPLE Microsoft Mouse `EXECUTE1' MENU
  4516.  ;
  4517.  ; NOTE: Please review the comments below before you compile
  4518.  ;       and use this source file as a mouse menu.
  4519.  ;
  4520.  ; The EXECUTE1 menu provides an example of the functional
  4521.  ; limitations of the Microsoft Mouse EXECUTE statement.
  4522.  ;
  4523.  ; This example calls a label from a menu (menu1), where the
  4524.  ; label (run:) specifies that two commands be executed (cls
  4525.  ; & menu2).  The label 'cls:' causes a 'cls<return>'
  4526.  ; sequence to be sent to the keyboard buffer, after which
  4527.  ; 'menu2:'is run.
  4528.  ;
  4529.  ; Running the menu appears to yield the opposite order of
  4530.  ; operations.  That is, the 'cls<enter>' command is executed
  4531.  ; AFTER 'menu2:' terminates.  The keystrokes 'cls<enter>'
  4532.  ; are sent to the keyboard buffer BEFORE 'menu2:' is
  4533.  ; executed, but since the menu has not relinquished control
  4534.  ; to DOS, they are not immediately acted upon.
  4535.  ;
  4536.  ; Note: See the file EXECUTE2.DEF for a related example.
  4537.  ;
  4538.  ;
  4539.  BEGIN lb
  4540.  
  4541.  lb:     execute menu1
  4542.  
  4543.  menu1: MENU   " sample 'execute' function menu (1)",1,40,NORMAL
  4544.         option "  clear the screen, and run menu2  ",run
  4545.         MEND
  4546.  ;
  4547.  run:   execute cls,menu2
  4548.  ;
  4549.  menu2: MENU   " sample 'execute' function menu (2)",1,40,NORMAL
  4550.         option "             do nothing            ",nul
  4551.         MEND
  4552.  ;
  4553.  cls:   type "cls",enter
  4554.  nul:   nothing
  4555.  ;
  4556.  
  4557.  \SAMPCODE\MOUSE\SOURCES\EXECUTE2.DEF
  4558.  
  4559.  ;       SAMPLE Microsoft Mouse `EXECUTE2' MENU
  4560.  ;
  4561.  ; NOTE: Review the comments below before you compile
  4562.  ;       and use this source file as a mouse menu.
  4563.  ;
  4564.  ; The EXECUTE2 menu provides an example of 'semi-automatic'
  4565.  ; mouse menu activation.  It demonstrates how you can
  4566.  ; achieve subtle interaction between certain types of mouse
  4567.  ; menu 'event trapping' (especially with mouse motion/MATCH
  4568.  ; statement trapping).  This menu runs at the DOS level.
  4569.  ; The comments included in the source code explain the
  4570.  ; necessary complexity of the menu.
  4571.  
  4572.  ; EXECUTE2 has two levels of menus.  The first menu is
  4573.  ; activated by clicking a mouse button, and sets up the
  4574.  ; conditions for entry into the second menu (horizontal
  4575.  ; mouse motion combined with particular screen display
  4576.  ; conditions).  Exiting the second menu ensures that the
  4577.  ; proper conditions are set up for the first menu.
  4578.  ;
  4579.  ; The major reason for this menu's complexity is the speed
  4580.  ; at which mouse motion trapping occurs.  If the entry and
  4581.  ; exit conditions around the second menu are cut down, the
  4582.  ; second menu may become active before the DOS 'cls'
  4583.  ; statement is COMPLETELY processed.  In addition, mouse
  4584.  ; motion in conjunction with a mouse button click within the
  4585.  ; second menu could cause the second menu to be redisplayed
  4586.  ; (this would occur if the 'cln:' "ASSIGN" statement was
  4587.  ; EXECUTED upon exiting menu2).
  4588.  ;
  4589.  ; When working with menus with this style of user
  4590.  ; interaction, ALL input and output conditions must be
  4591.  ; thoroughly analyzed and accommodated.  Otherwise, the
  4592.  ; intended entry conditions may be violated.
  4593.  ;
  4594.  ;
  4595.  BEGIN lb,nul,nul,nul,nul,nul,nul,32,16  ;left button is the only
  4596.                                          ;entry into the initial menu
  4597.  ;
  4598.  lb:     execute menu1
  4599.  ;
  4600.  menu1: MENU   " sample 'match' function menu (1)",1,40,NORMAL
  4601.         option " clear the screen, and run menu2 ",set
  4602.         MEND
  4603.  ;
  4604.  set:   execute cls,asn,nul             ;'cls:' clears the screen
  4605.                                         ;'asn:' reassigns the menu
  4606.                                         ; entry to allow horizontal
  4607.                                         ; mouse motion to trigger the
  4608.                                         ; second menu.
  4609.                                         ;'nul:' is a "do nothing"
  4610.  ;
  4611.  cls:   type "cls",enter
  4612.  asn:   ASSIGN lb,nul,nul,chk,chk,nul,nul,32,16
  4613.  nul:   nothing
  4614.  ;
  4615.  chk:   MATCH 2,0,NORMAL,32,res,nul     ;When horizontal mouse motion
  4616.                                         ; is detected, this statement
  4617.                                         ; looks for a SPACE character
  4618.                                         ; at the left margin of the
  4619.                                         ; second line of the display,
  4620.                                         ; indicating that the DOS 'cls'
  4621.                                         ; command is complete...
  4622.  ;
  4623.  res:   EXECUTE clr,menu2               ;When 'chk:' is satisfied, this
  4624.                                         ; will cause the horizontal
  4625.                                         ; motion sensitivity to be
  4626.                                         ; low, and reassigns all motion
  4627.                                         ; trapping to a 'do nothing'
  4628.                                         ; state, disallowing REENTRY
  4629.                                         ; into the second menu (menu2).
  4630.  ;
  4631.  clr:   ASSIGN lb,nul,nul,nul,nul,nul,nul,5000,16
  4632.  menu2: MENU   " sample 'execute' function menu (2)",1,40,NORMAL
  4633.         option "             do nothing            ",org
  4634.         option "             do nothing            ",org
  4635.         MEND
  4636.  ;
  4637.  org:   execute cln,zip                 ;This will reset the menu
  4638.                                         ; parameters to the original
  4639.                                         ; state at menu load-time,
  4640.                                         ; and makes sure that there
  4641.                                         ; is something other than
  4642.                                         ; a SPACE at the left margin
  4643.                                         ; of line 2 of the display
  4644.                                         ; (depending on the DOS
  4645.                                         ; PROMPT configuration)
  4646.                                         ; - this will disallow early
  4647.                                         ; entry into 'menu2' after
  4648.                                         ; subsequent entry into
  4649.                                         ; menu1.
  4650.  ;
  4651.  cln:   ASSIGN lb,nul,nul,nul,nul,nul,nul,32,16
  4652.  zip:   type enter
  4653.  ;
  4654.  
  4655.  \SAMPCODE\MOUSE\SOURCES\KBD.DEF
  4656.  
  4657.  ;    SAMPLE Microsoft Mouse `KEYBOARD EMULATION' MENU
  4658.  ;
  4659.  ; NOTE: Please review the comments below before you compile
  4660.  ;       and use this source file as a mouse menu.
  4661.  ;
  4662.  ; This menu is designed to provide a partial keyboard
  4663.  ; emulation.  Not all usable keystrokes are emulated.
  4664.  ; The <ALT> and <SHIFT> function keys are not implemented.
  4665.  ; <CTRL> plus PrtSc, Home, the left or right cursor key,
  4666.  ; End, and PgDn are not implemented.  <ALT> plus 1 through
  4667.  ; 9, -, =, and uppercase ASCII are also not implemented.
  4668.  ;
  4669.  ; Most of the SELECT statements (except in the
  4670.  ; case of the function keys) work from single screen
  4671.  ; locations.  You can modify the third SELECT parameter to
  4672.  ; specify wider selection fields.  However, make sure each
  4673.  ; screen position does not have more than one SELECT
  4674.  ; statement defining it.
  4675.  
  4676.  ; This menu is displayed when you click a mouse button.
  4677.  ; Double clicking a menu item puts the selected character
  4678.  ; into the keyboard buffer, then reactivates the menu.
  4679.  
  4680.  ; Please note that the 'control character' menu shown below
  4681.  ; will send ANY ASCII control code to the console.  Use of
  4682.  ; some codes under certain programs may cause operational
  4683.  ; difficulties.  In particular, use the 'SUB' code
  4684.  ; carefully.  SUB is the normal 'end-of-file' marker, or
  4685.  ; 'control-Z.'  Sending this code to the console (display)
  4686.  ; within an application that is performing stream I/O to the
  4687.  ; standard output device (CON or 'stdout') may terminate
  4688.  ; communications.
  4689.  ;
  4690.  ; This menu has been provided for illustrative purposes,
  4691.  ; and is not intended as a replacement for the keyboard.
  4692.  ; It is not efficient for typing anything but the simplest
  4693.  ; character sequences.
  4694.  ;
  4695.  ;
  4696.  BEGIN nulx,ctrl,nula
  4697.  
  4698.  nulx:      execute kpop          ;run the 'keyboard' menu if the
  4699.                                   ;left button was clicked
  4700.  ctrl:      execute cpop          ;run the 'control keys' menu if
  4701.                                   ;the right button was clicked
  4702.  nula:      execute gpop          ;run the 'graphics' character menu
  4703.                                   ;if both buttons were clicked.
  4704.  
  4705.  kpop: POPUP 2,40,NORMAL          ;this is the 'keyboard' menu
  4706.        text "╔════╦════╤════╦═══════╦═══╦════╗"
  4707.        text "║quit║Ctrl│Symb║ Enter ║Ins║Del ║"
  4708.        text "╠═╤═╤╩╤═╤═╪═╤═╤╩╤═╤═╤═╤╩╤═╤╩╤═╤═╣"
  4709.        text "║@│A│B│C│D│E│F│G│H│I│J│K│L│M│N│O║"
  4710.        text "║P│Q│R│S│T│U│V│W│X│Y│Z│[│\│^│]│^║"
  4711.        text "║`│a│b│c│d│e│f│g│h│i│j│k│l│m│n│o║"
  4712.        text "║p│q│r│s│t│u│v│w│x│y│z│{│|│}│~│·║"
  4713.        text "║─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴╔╧═╧═╣"
  4714.        text "║         spacebar         ║ BS ║"
  4715.        text "║─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬╚╤═╤═╣"
  4716.        text "║ │!│ │#│$│%│&│'│(│)│*│+│,│-│.│/║"
  4717.        text "║0│1│2│3│4│5│6│7│8│9│:│;│<│=│>│?║"
  4718.        text "║═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╣"
  4719.        text "║ h  p │ f1  f2  f3  f4  f5    ║"
  4720.        text "║  ·  │ f6  f8  f8  f9  f10   ║"
  4721.        text "║ e  d ╔═══════════════════════╝"
  4722.        text "╚═══════╝"
  4723.                                   ;here are the SELECT statements
  4724.                                   ;for the 'keyboard' menu.
  4725.        select 2,2,1,quit
  4726.        select 2,3,1,quit
  4727.        select 2,4,1,quit
  4728.        select 2,5,1,quit
  4729.        select 2,6,1,nulx
  4730.        select 2,7,1,ctrl
  4731.        select 2,8,1,ctrl
  4732.        select 2,9,1,ctrl
  4733.        select 2,10,1,ctrl
  4734.        select 2,11,1,nulx
  4735.        select 2,12,1,nula
  4736.        select 2,13,1,nula
  4737.        select 2,14,1,nula
  4738.        select 2,15,1,nula
  4739.        select 2,16,1,nulx
  4740.        select 2,17,1,x13
  4741.        select 2,18,1,x13
  4742.        select 2,19,1,x13
  4743.        select 2,20,1,x13
  4744.        select 2,21,1,x13
  4745.        select 2,22,1,x13
  4746.        select 2,23,1,x13
  4747.        select 2,24,1,nulx
  4748.        select 2,25,1,ins
  4749.        select 2,26,1,ins
  4750.        select 2,27,1,ins
  4751.        select 2,28,1,nulx
  4752.        select 2,29,1,del
  4753.        select 2,30,1,del
  4754.        select 2,31,1,del
  4755.        select 2,32,1,nulx
  4756.        select 3,2,1,nulx
  4757.        select 3,3,1,nulx
  4758.        select 3,4,1,nulx
  4759.        select 3,5,1,nulx
  4760.        select 3,6,1,nulx
  4761.        select 3,7,1,nulx
  4762.        select 3,8,1,nulx
  4763.        select 3,9,1,nulx
  4764.        select 3,10,1,nulx
  4765.        select 3,11,1,nulx
  4766.        select 3,12,1,nulx
  4767.        select 3,13,1,nulx
  4768.        select 3,14,1,nulx
  4769.        select 3,15,1,nulx
  4770.        select 3,16,1,nulx
  4771.        select 3,17,1,nulx
  4772.        select 3,18,1,nulx
  4773.        select 3,19,1,nulx
  4774.        select 3,20,1,nulx
  4775.        select 3,21,1,nulx
  4776.        select 3,22,1,nulx
  4777.        select 3,23,1,nulx
  4778.        select 3,24,1,nulx
  4779.        select 3,25,1,nulx
  4780.        select 3,26,1,nulx
  4781.        select 3,27,1,nulx
  4782.        select 3,28,1,nulx
  4783.        select 3,29,1,nulx
  4784.        select 3,30,1,nulx
  4785.        select 3,31,1,nulx
  4786.        select 3,32,1,nulx
  4787.        select 4,2,1,x64
  4788.        select 4,3,1,nulx
  4789.        select 4,4,1,x65
  4790.        select 4,5,1,nulx
  4791.        select 4,6,1,x66
  4792.        select 4,7,1,nulx
  4793.        select 4,8,1,x67
  4794.        select 4,9,1,nulx
  4795.        select 4,10,1,x68
  4796.        select 4,11,1,nulx
  4797.        select 4,12,1,x69
  4798.        select 4,13,1,nulx
  4799.        select 4,14,1,x70
  4800.        select 4,15,1,nulx
  4801.        select 4,16,1,x71
  4802.        select 4,17,1,nulx
  4803.        select 4,18,1,x72
  4804.        select 4,19,1,nulx
  4805.        select 4,20,1,x73
  4806.        select 4,21,1,nulx
  4807.        select 4,22,1,x74
  4808.        select 4,23,1,nulx
  4809.        select 4,24,1,x75
  4810.        select 4,25,1,nulx
  4811.        select 4,26,1,x76
  4812.        select 4,27,1,nulx
  4813.        select 4,28,1,x77
  4814.        select 4,29,1,nulx
  4815.        select 4,30,1,x78
  4816.        select 4,31,1,nulx
  4817.        select 4,32,1,x79
  4818.        select 5,2,1,x80
  4819.        select 5,3,1,nulx
  4820.        select 5,4,1,x81
  4821.        select 5,5,1,nulx
  4822.        select 5,6,1,x82
  4823.        select 5,7,1,nulx
  4824.        select 5,8,1,x83
  4825.        select 5,9,1,nulx
  4826.        select 5,10,1,x84
  4827.        select 5,11,1,nulx
  4828.        select 5,12,1,x85
  4829.        select 5,13,1,nulx
  4830.        select 5,14,1,x86
  4831.        select 5,15,1,nulx
  4832.        select 5,16,1,x87
  4833.        select 5,17,1,nulx
  4834.        select 5,18,1,x88
  4835.        select 5,19,1,nulx
  4836.        select 5,20,1,x89
  4837.        select 5,21,1,nulx
  4838.        select 5,22,1,x90
  4839.        select 5,23,1,nulx
  4840.        select 5,24,1,x91
  4841.        select 5,25,1,nulx
  4842.        select 5,26,1,x92
  4843.        select 5,27,1,nulx
  4844.        select 5,28,1,x93
  4845.        select 5,29,1,nulx
  4846.        select 5,30,1,x94
  4847.        select 5,31,1,nulx
  4848.        select 5,32,1,x95
  4849.        select 6,2,1,x96
  4850.        select 6,3,1,nulx
  4851.        select 6,4,1,x97
  4852.        select 6,5,1,nulx
  4853.        select 6,6,1,x98
  4854.        select 6,7,1,nulx
  4855.        select 6,8,1,x99
  4856.        select 6,9,1,nulx
  4857.        select 6,10,1,x100
  4858.        select 6,11,1,nulx
  4859.        select 6,12,1,x101
  4860.        select 6,13,1,nulx
  4861.        select 6,14,1,x102
  4862.        select 6,15,1,nulx
  4863.        select 6,16,1,x103
  4864.        select 6,17,1,nulx
  4865.        select 6,18,1,x104
  4866.        select 6,19,1,nulx
  4867.        select 6,20,1,x105
  4868.        select 6,21,1,nulx
  4869.        select 6,22,1,x106
  4870.        select 6,23,1,nulx
  4871.        select 6,24,1,x107
  4872.        select 6,25,1,nulx
  4873.        select 6,26,1,x108
  4874.        select 6,27,1,nulx
  4875.        select 6,28,1,x109
  4876.        select 6,29,1,nulx
  4877.        select 6,30,1,x110
  4878.        select 6,31,1,nulx
  4879.        select 6,32,1,x111
  4880.        select 7,2,1,x112
  4881.        select 7,3,1,nulx
  4882.        select 7,4,1,x113
  4883.        select 7,5,1,nulx
  4884.        select 7,6,1,x114
  4885.        select 7,7,1,nulx
  4886.        select 7,8,1,x115
  4887.        select 7,9,1,nulx
  4888.        select 7,10,1,x116
  4889.        select 7,11,1,nulx
  4890.        select 7,12,1,x117
  4891.        select 7,13,1,nulx
  4892.        select 7,14,1,x118
  4893.        select 7,15,1,nulx
  4894.        select 7,16,1,x119
  4895.        select 7,17,1,nulx
  4896.        select 7,18,1,x120
  4897.        select 7,19,1,nulx
  4898.        select 7,20,1,x121
  4899.        select 7,21,1,nulx
  4900.        select 7,22,1,x122
  4901.        select 7,23,1,nulx
  4902.        select 7,24,1,x123
  4903.        select 7,25,1,nulx
  4904.        select 7,26,1,x124
  4905.        select 7,27,1,nulx
  4906.        select 7,28,1,x125
  4907.        select 7,29,1,nulx
  4908.        select 7,30,1,x126
  4909.        select 7,31,1,nulx
  4910.        select 7,32,1,x127
  4911.        select 8,2,1,nulx
  4912.        select 8,3,1,nulx
  4913.        select 8,4,1,nulx
  4914.        select 8,5,1,nulx
  4915.        select 8,6,1,nulx
  4916.        select 8,7,1,nulx
  4917.        select 8,8,1,nulx
  4918.        select 8,9,1,nulx
  4919.        select 8,10,1,nulx
  4920.        select 8,11,1,nulx
  4921.        select 8,12,1,nulx
  4922.        select 8,13,1,nulx
  4923.        select 8,14,1,nulx
  4924.        select 8,15,1,nulx
  4925.        select 8,16,1,nulx
  4926.        select 8,17,1,nulx
  4927.        select 8,18,1,nulx
  4928.        select 8,19,1,nulx
  4929.        select 8,20,1,nulx
  4930.        select 8,21,1,nulx
  4931.        select 8,22,1,nulx
  4932.        select 8,23,1,nulx
  4933.        select 8,24,1,nulx
  4934.        select 8,25,1,nulx
  4935.        select 8,26,1,nulx
  4936.        select 8,27,1,nulx
  4937.        select 8,28,1,nulx
  4938.        select 8,29,1,nulx
  4939.        select 8,30,1,nulx
  4940.        select 8,31,1,nulx
  4941.        select 8,32,1,nulx
  4942.        select 9,2,1,x32
  4943.        select 9,3,1,x32
  4944.        select 9,4,1,x32
  4945.        select 9,5,1,x32
  4946.        select 9,6,1,x32
  4947.        select 9,7,1,x32
  4948.        select 9,8,1,x32
  4949.        select 9,9,1,x32
  4950.        select 9,10,1x32
  4951.        select 9,11,1,x32
  4952.        select 9,12,1,x32
  4953.        select 9,13,1,x32
  4954.        select 9,14,1,x32
  4955.        select 9,15,1,x32
  4956.        select 9,16,1,x32
  4957.        select 9,17,1,x32
  4958.        select 9,18,1,x32
  4959.        select 9,19,1,x32
  4960.        select 9,20,1,x32
  4961.        select 9,21,1,x32
  4962.        select 9,22,1,x32
  4963.        select 9,23,1,x32
  4964.        select 9,24,1,x32
  4965.        select 9,25,1,x32
  4966.        select 9,26,1,x32
  4967.        select 9,27,1,x32
  4968.        select 9,28,1,nulx
  4969.        select 9,29,1,x8
  4970.        select 9,30,1,x8
  4971.        select 9,31,1,x8
  4972.        select 9,32,1,x8
  4973.        select 10,2,1,nulx
  4974.        select 10,3,1,nulx
  4975.        select 10,4,1,nulx
  4976.        select 10,5,1,nulx
  4977.        select 10,6,1,nulx
  4978.        select 10,7,1,nulx
  4979.        select 10,8,1,nulx
  4980.        select 10,9,1,nulx
  4981.        select 10,10,1,nulx
  4982.        select 10,11,1,nulx
  4983.        select 10,12,1,nulx
  4984.        select 10,13,1,nulx
  4985.        select 10,14,1,nulx
  4986.        select 10,15,1,nulx
  4987.        select 10,16,1,nulx
  4988.        select 10,17,1,nulx
  4989.        select 10,18,1,nulx
  4990.        select 10,19,1,nulx
  4991.        select 10,20,1,nulx
  4992.        select 10,21,1,nulx
  4993.        select 10,22,1,nulx
  4994.        select 10,23,1,nulx
  4995.        select 10,24,1,nulx
  4996.        select 10,25,1,nulx
  4997.        select 10,26,1,nulx
  4998.        select 10,27,1,nulx
  4999.        select 10,28,1,nulx
  5000.        select 10,29,1,nulx
  5001.        select 10,30,1,nulx
  5002.        select 10,31,1,nulx
  5003.        select 10,32,1,nulx
  5004.        select 11,2,1,x32
  5005.        select 11,3,1,nulx
  5006.        select 11,4,1,x33
  5007.        select 11,5,1,nulx
  5008.        select 11,6,1,x34
  5009.        select 11,7,1,nulx
  5010.        select 11,8,1,x35
  5011.        select 11,9,1,nulx
  5012.        select 11,10,1,x36
  5013.        select 11,11,1,nulx
  5014.        select 11,12,1,x37
  5015.        select 11,13,1,nulx
  5016.        select 11,14,1,x38
  5017.        select 11,15,1,nulx
  5018.        select 11,16,1,x39
  5019.        select 11,17,1,nulx
  5020.        select 11,18,1,x40
  5021.        select 11,19,1,nulx
  5022.        select 11,20,1,x41
  5023.        select 11,21,1,nulx
  5024.        select 11,22,1,x42
  5025.        select 11,23,1,nulx
  5026.        select 11,24,1,x43
  5027.        select 11,25,1,nulx
  5028.        select 11,26,1,x44
  5029.        select 11,27,1,nulx
  5030.        select 11,28,1,x45
  5031.        select 11,29,1,nulx
  5032.        select 11,30,1,x46
  5033.        select 11,31,1,nulx
  5034.        select 11,32,1,x47
  5035.        select 12,2,1,x48
  5036.        select 12,3,1,nulx
  5037.        select 12,4,1,x49
  5038.        select 12,5,1,nulx
  5039.        select 12,6,1,x50
  5040.        select 12,7,1,nulx
  5041.        select 12,8,1,x51
  5042.        select 12,9,1,nulx
  5043.        select 12,10,1,x52
  5044.        select 12,11,1,nulx
  5045.        select 12,12,1,x53
  5046.        select 12,13,1,nulx
  5047.        select 12,14,1,x54
  5048.        select 12,15,1,nulx
  5049.        select 12,16,1,x55
  5050.        select 12,17,1,nulx
  5051.        select 12,18,1,x56
  5052.        select 12,19,1,nulx
  5053.        select 12,20,1,x57
  5054.        select 12,21,1,nulx
  5055.        select 12,22,1,x58
  5056.        select 12,23,1,nulx
  5057.        select 12,24,1,x59
  5058.        select 12,25,1,nulx
  5059.        select 12,26,1,x60
  5060.        select 12,27,1,nulx
  5061.        select 12,28,1,x61
  5062.        select 12,29,1,nulx
  5063.        select 12,30,1,x62
  5064.        select 12,31,1,nulx
  5065.        select 12,32,1,x63
  5066.        select 13,2,1,nulx
  5067.        select 13,3,1,nulx
  5068.        select 13,4,1,nulx
  5069.        select 13,5,1,nulx
  5070.        select 13,6,1,nulx
  5071.        select 13,7,1,nulx
  5072.        select 13,8,1,nulx
  5073.        select 13,9,1,nulx
  5074.        select 13,10,1,nulx
  5075.        select 13,11,1,nulx
  5076.        select 13,12,1,nulx
  5077.        select 13,13,1,nulx
  5078.        select 13,14,1,nulx
  5079.        select 13,15,1,nulx
  5080.        select 13,16,1,nulx
  5081.        select 13,17,1,nulx
  5082.        select 13,18,1,nulx
  5083.        select 13,19,1,nulx
  5084.        select 13,20,1,nulx
  5085.        select 13,21,1,nulx
  5086.        select 13,22,1,nulx
  5087.        select 13,23,1,nulx
  5088.        select 13,24,1,nulx
  5089.        select 13,25,1,nulx
  5090.        select 13,26,1,nulx
  5091.        select 13,27,1,nulx
  5092.        select 13,28,1,nulx
  5093.        select 13,29,1,nulx
  5094.        select 13,30,1,nulx
  5095.        select 13,31,1,nulx
  5096.        select 13,32,1,nulx
  5097.        select 14,2,1,nulx
  5098.        select 14,3,1,home
  5099.        select 14,4,1,nulx
  5100.        select 14,5,1,upcur
  5101.        select 14,6,1,nulx
  5102.        select 14,7,1,pgup
  5103.        select 14,8,1,nulx
  5104.        select 14,9,1,nulx
  5105.        select 14,10,1,nulx
  5106.        select 14,11,3,f1
  5107.        select 14,14,1,nulx,
  5108.        select 14,15,3,f2
  5109.        select 14,18,1,nulx
  5110.        select 14,19,3,f3
  5111.        select 14,22,1,nulx
  5112.        select 14,23,3,f4
  5113.        select 14,26,1,nulx
  5114.        select 14,27,3,f5
  5115.        select 14,30,1,nulx
  5116.        select 14,31,1,nulx
  5117.        select 14,32,1,nulx
  5118.        select 15,2,1,nulx
  5119.        select 15,3,1,lcurs
  5120.        select 15,4,1,nulx
  5121.        select 15,5,1,ncurs
  5122.        select 15,6,1,nulx
  5123.        select 15,7,1,rcurs
  5124.        select 15,8,1,nulx
  5125.        select 15,9,1,nulx
  5126.        select 15,10,1,nulx
  5127.        select 15,11,3,f6
  5128.        select 15,14,1,nulx,
  5129.        select 15,15,3,f7
  5130.        select 15,18,1,nulx
  5131.        select 15,19,3,f8
  5132.        select 15,22,1,nulx
  5133.        select 15,23,3,f9
  5134.        select 15,26,1,nulx
  5135.        select 15,27,3,f10
  5136.        select 15,30,1,nulx
  5137.        select 15,31,1,nulx
  5138.        select 15,32,1,nulx
  5139.        select 16,2,1,nulx
  5140.        select 16,3,1,endx
  5141.        select 16,4,1,nulx
  5142.        select 16,5,1,dcurs
  5143.        select 16,6,1,nulx
  5144.        select 16,7,1,pgdn
  5145.        select 16,8,1,nulx
  5146.        PEND
  5147.  
  5148.  cpop: POPUP 2,40,NORMAL          ;this is the 'control keys' menu
  5149.        text "   ╔════╦════╦════╗"
  5150.        text "   ║quit║Kybd║Symb║"
  5151.        text "╔══╬════╩════╬═══╦╝"
  5152.        text "║ 0║ NUL DLE ║ 10║"
  5153.        text "║ 1║ SOH DC1 ║ 11║"
  5154.        text "║ 2║ STX DC2 ║ 12║"
  5155.        text "║ 3║ ETX DC3 ║ 13║"
  5156.        text "║ 4║ EOT DC4 ║ 14║"
  5157.        text "║ 5║ ENQ NAK ║ 15║"
  5158.        text "║ 6║ ACK SYN ║ 16║"
  5159.        text "║ 7║ BEL ETB ║ 17║"
  5160.        text "║ 8║  BS CAN ║ 18║"
  5161.        text "║ 9║  HT  EM ║ 19║"
  5162.        text "║ A║  LF SUB ║ 1A║"
  5163.        text "║ B║  VT ESC ║ 1B║"
  5164.        text "║ C║  FF  FS ║ 1C║"
  5165.        text "║ D║  CR  GS ║ 1D║"
  5166.        text "║ E║  SO  RS ║ 1E║"
  5167.        text "║ F║  SI  US ║ 1F║"
  5168.        text "╚══╩═════════╩═══╝"
  5169.                                   ;here are the SELECT statements
  5170.                                   ;for the 'control keys' menu.
  5171.        select 2,5,4,quit
  5172.        select 2,9,1,ctrl
  5173.        select 2,10,4,nulx
  5174.        select 2,14,1,ctrl
  5175.        select 2,15,4,nula
  5176.        select 3,5,4,ctrl
  5177.        select 3,9,1,ctrl
  5178.        select 3,10,4,ctrl
  5179.        select 4,5,4,x0
  5180.        select 4,9,1,ctrl
  5181.        select 4,10,4,x16
  5182.        select 5,5,4,x1
  5183.        select 5,9,1,ctrl
  5184.        select 5,10,4,x17
  5185.        select 6,5,4,x2
  5186.        select 6,9,1,ctrl
  5187.        select 6,10,4,x18
  5188.        select 7,5,4,x3
  5189.        select 7,9,1,ctrl
  5190.        select 7,10,4,x19
  5191.        select 8,5,4,x4
  5192.        select 8,9,1,ctrl
  5193.        select 8,10,4,x20
  5194.        select 9,5,4,x5
  5195.        select 9,9,1,ctrl
  5196.        select 9,10,4,x21
  5197.        select 10,5,4,x6
  5198.        select 10,9,1,ctrl
  5199.        select 10,10,4,x22
  5200.        select 11,5,4,x7
  5201.        select 11,9,1,ctrl
  5202.        select 11,10,4,x23
  5203.        select 11,19,3,f8
  5204.        select 12,5,4,x8
  5205.        select 12,9,1,ctrl
  5206.        select 12,10,4,x24
  5207.        select 13,5,4,x9
  5208.        select 13,9,1,ctrl
  5209.        select 13,10,4,x25
  5210.        select 14,5,4,x10
  5211.        select 14,9,1,ctrl
  5212.        select 14,10,4,x26
  5213.        select 15,5,4,x11
  5214.        select 15,9,1,ctrl
  5215.        select 15,10,4,x27
  5216.        select 16,5,4,x12
  5217.        select 16,9,1,ctrl
  5218.        select 16,10,4,x28
  5219.        select 17,5,4,x13
  5220.        select 17,9,1,ctrl
  5221.        select 17,10,4,x29
  5222.        select 18,5,4,x14
  5223.        select 18,9,1,ctrl
  5224.        select 18,10,4,x30
  5225.        select 19,5,4,x15
  5226.        select 19,9,1,ctrl
  5227.        select 19,10,4,x31
  5228.        PEND
  5229.  
  5230.  gpop: POPUP 2,40,NORMAL          ;here is the 'graphics character' menu
  5231.        text "╔════╦══════════╤═════════╤═════╗"
  5232.        text "║quit║ Keyboard │ Control │Enter║"
  5233.        text "╠═╤═╤╩╤═╤═╤═╤═╤═╪═╤═╤═╤═╤═╪═╤═╤═╣"
  5234.        text "║Ç│ü│é│â│ä│à│å│ç│ê│ë│è│ï│î│ì│Ä│Å║"
  5235.        text "║É│æ│Æ│ô│ö│ò│û│ù│ÿ│Ö│Ü│¢│£│¥│₧│ƒ║"
  5236.        text "║á│í│ó│ú│ñ│Ñ│ª│º│¿│⌐│¬│½│¼│¡│«│»║"
  5237.        text "║α│ß│Γ│π│Σ│σ│µ│τ│Φ│Θ│Ω│δ│∞│φ│ε│∩║"
  5238.        text "║≡│±│≥│≤│⌠│⌡│÷│≈│°│∙│·│√│ⁿ│²│■│ ║"
  5239.        text "╚═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╧═╝"
  5240.                                   ;here are the SELECT statements
  5241.                                   ;for the 'graphics character' menu.
  5242.        select 2,2,1,quit
  5243.        select 2,3,1,quit
  5244.        select 2,4,1,quit
  5245.        select 2,5,1,quit
  5246.        select 2,6,1,nula
  5247.        select 2,7,1,nulx
  5248.        select 2,8,1,nulx
  5249.        select 2,9,1,nulx
  5250.        select 2,10,1,nulx
  5251.        select 2,11,1,nulx
  5252.        select 2,12,1,nulx
  5253.        select 2,13,1,nulx
  5254.        select 2,14,1,nulx
  5255.        select 2,15,1,nulx
  5256.        select 2,16,1,nulx
  5257.        select 2,17,1,nula
  5258.        select 2,18,1,ctrl
  5259.        select 2,19,1,ctrl
  5260.        select 2,20,1,ctrl
  5261.        select 2,21,1,ctrl
  5262.        select 2,22,1,ctrl
  5263.        select 2,23,1,ctrl
  5264.        select 2,24,1,ctrl
  5265.        select 2,25,1,ctrl
  5266.        select 2,26,1,ctrl
  5267.        select 2,27,1,nula
  5268.        select 2,28,1,x13
  5269.        select 2,29,1,x13
  5270.        select 2,30,1,x13
  5271.        select 2,31,1,x13
  5272.        select 2,32,1,x13
  5273.        select 3,2,1,nula
  5274.        select 3,3,1,nula
  5275.        select 3,4,1,nula
  5276.        select 3,5,1,nula
  5277.        select 3,6,1,nula
  5278.        select 3,7,1,nula
  5279.        select 3,8,1,nula
  5280.        select 3,9,1,nula
  5281.        select 3,10,1,nula
  5282.        select 3,11,1,nula
  5283.        select 3,12,1,nula
  5284.        select 3,13,1,nula
  5285.        select 3,14,1,nula
  5286.        select 3,15,1,nula
  5287.        select 3,16,1,nula
  5288.        select 3,17,1,nula
  5289.        select 3,18,1,nula
  5290.        select 3,19,1,nula
  5291.        select 3,20,1,nula
  5292.        select 3,21,1,nula
  5293.        select 3,22,1,nula
  5294.        select 3,23,1,nula
  5295.        select 3,24,1,nula
  5296.        select 3,25,1,nula
  5297.        select 3,26,1,nula
  5298.        select 3,27,1,nula
  5299.        select 3,28,1,nula
  5300.        select 3,29,1,nula
  5301.        select 3,30,1,nula
  5302.        select 3,31,1,nula
  5303.        select 3,32,1,nula
  5304.        select 4,2,1,x128
  5305.        select 4,3,1,nula
  5306.        select 4,4,1,x129
  5307.        select 4,5,1,nula
  5308.        select 4,6,1,x130
  5309.        select 4,7,1,nula
  5310.        select 4,8,1,x131
  5311.        select 4,9,1,nula
  5312.        select 4,10,1,x132
  5313.        select 4,11,1,nula
  5314.        select 4,12,1,x133
  5315.        select 4,13,1,nula
  5316.        select 4,14,1,x134
  5317.        select 4,15,1,nula
  5318.        select 4,16,1,x135
  5319.        select 4,17,1,nula
  5320.        select 4,18,1,x136
  5321.        select 4,19,1,nula
  5322.        select 4,20,1,x137
  5323.        select 4,21,1,nula
  5324.        select 4,22,1,x138
  5325.        select 4,23,1,nula
  5326.        select 4,24,1,x139
  5327.        select 4,25,1,nula
  5328.        select 4,26,1,x140
  5329.        select 4,27,1,nula
  5330.        select 4,28,1,x141
  5331.        select 4,29,1,nula
  5332.        select 4,30,1,x142
  5333.        select 4,31,1,nula
  5334.        select 4,32,1,x143
  5335.        select 5,2,1,x144
  5336.        select 5,3,1,nula
  5337.        select 5,4,1,x145
  5338.        select 5,5,1,nula
  5339.        select 5,6,1,x146
  5340.        select 5,7,1,nula
  5341.        select 5,8,1,x147
  5342.        select 5,9,1,nula
  5343.        select 5,10,1,x148
  5344.        select 5,11,1,nula
  5345.        select 5,12,1,x149
  5346.        select 5,13,1,nula
  5347.        select 5,14,1,x150
  5348.        select 5,15,1,nula
  5349.        select 5,16,1,x151
  5350.        select 5,17,1,nula
  5351.        select 5,18,1,x152
  5352.        select 5,19,1,nula
  5353.        select 5,20,1,x153
  5354.        select 5,21,1,nula
  5355.        select 5,22,1,x154
  5356.        select 5,23,1,nula
  5357.        select 5,24,1,x155
  5358.        select 5,25,1,nula
  5359.        select 5,26,1,x156
  5360.        select 5,27,1,nula
  5361.        select 5,28,1,x157
  5362.        select 5,29,1,nula
  5363.        select 5,30,1,x158
  5364.        select 5,31,1,nula
  5365.        select 5,32,1,x159
  5366.        select 6,2,1,x160
  5367.        select 6,3,1,nula
  5368.        select 6,4,1,x161
  5369.        select 6,5,1,nula
  5370.        select 6,6,1,x162
  5371.        select 6,7,1,nula
  5372.        select 6,8,1,x163
  5373.        select 6,9,1,nula
  5374.        select 6,10,1,x164
  5375.        select 6,11,1,nula
  5376.        select 6,12,1,x165
  5377.        select 6,13,1,nula
  5378.        select 6,14,1,x166
  5379.        select 6,15,1,nula
  5380.        select 6,16,1,x167
  5381.        select 6,17,1,nula
  5382.        select 6,18,1,x168
  5383.        select 6,19,1,nula
  5384.        select 6,20,1,x169
  5385.        select 6,21,1,nula
  5386.        select 6,22,1,x170
  5387.        select 6,23,1,nula
  5388.        select 6,24,1,x171
  5389.        select 6,25,1,nula
  5390.        select 6,26,1,x172
  5391.        select 6,27,1,nula
  5392.        select 6,28,1,x173
  5393.        select 6,29,1,nula
  5394.        select 6,30,1,x174
  5395.        select 6,31,1,nula
  5396.        select 6,32,1,x175
  5397.        select 7,2,1,x224
  5398.        select 7,3,1,nula
  5399.        select 7,4,1,x225
  5400.        select 7,5,1,nula
  5401.        select 7,6,1,x226
  5402.        select 7,7,1,nula
  5403.        select 7,8,1,x227
  5404.        select 7,9,1,nula
  5405.        select 7,10,1,x228
  5406.        select 7,11,1,nula
  5407.        select 7,12,1,x229
  5408.        select 7,13,1,nula
  5409.        select 7,14,1,x230
  5410.        select 7,15,1,nula
  5411.        select 7,16,1,x231
  5412.        select 7,17,1,nula
  5413.        select 7,18,1,x232
  5414.        select 7,19,1,nula
  5415.        select 7,20,1,x233
  5416.        select 7,21,1,nula
  5417.        select 7,22,1,x234
  5418.        select 7,23,1,nula
  5419.        select 7,24,1,x235
  5420.        select 7,25,1,nula
  5421.        select 7,26,1,x236
  5422.        select 7,27,1,nula
  5423.        select 7,28,1,x237
  5424.        select 7,29,1,nula
  5425.        select 7,30,1,x238
  5426.        select 7,31,1,nula
  5427.        select 7,32,1,x239
  5428.        select 8,2,1,x240
  5429.        select 8,3,1,nula
  5430.        select 8,4,1,x241
  5431.        select 8,5,1,nula
  5432.        select 8,6,1,x242
  5433.        select 8,7,1,nula
  5434.        select 8,8,1,x243
  5435.        select 8,9,1,nula
  5436.        select 8,10,1,x244
  5437.        select 8,11,1,nula
  5438.        select 8,12,1,x245
  5439.        select 8,13,1,nula
  5440.        select 8,14,1,x246
  5441.        select 8,15,1,nula
  5442.        select 8,16,1,x247
  5443.        select 8,17,1,nula
  5444.        select 8,18,1,x248
  5445.        select 8,19,1,nula
  5446.        select 8,20,1,x249
  5447.        select 8,21,1,nula
  5448.        select 8,22,1,x250
  5449.        select 8,23,1,nula
  5450.        select 8,24,1,x251
  5451.        select 8,25,1,nula
  5452.        select 8,26,1,x252
  5453.        select 8,27,1,nula
  5454.        select 8,28,1,x253
  5455.        select 8,29,1,nula
  5456.        select 8,30,1,x254
  5457.        select 8,31,1,nula
  5458.        select 8,32,1,x255
  5459.        PEND
  5460.  
  5461.                             ;the following labels define all of
  5462.                             ;the keystrokes available within this
  5463.                             ;menu.  Note that the cursor and function
  5464.                             ;key TYPE statements are defining
  5465.                             ;extended key codes.  Definitions for these
  5466.                             ;extended key codes may be found in the
  5467.                             ;various MS-DOS computer 'Hardware
  5468.                             ;Technical Reference Manuals'.
  5469.  quit:    nothing
  5470.  upcur:   TYPE 0,72
  5471.  dcurs:   TYPE 0,79
  5472.  lcurs:   TYPE 0,75
  5473.  rcurs:   TYPE 0,77
  5474.  home:    TYPE 0,71
  5475.  endx:    TYPE 0,79
  5476.  pgup:    TYPE 0,73
  5477.  pgdn:    TYPE 0,81
  5478.  ncurs:   TYPE 0,76
  5479.  ins:     TYPE 0,82
  5480.  del:     TYPE 0,83
  5481.  f1:      TYPE 0,59
  5482.  f2:      TYPE 0,60
  5483.  f3:      TYPE 0,61
  5484.  f4:      TYPE 0,62
  5485.  f5:      TYPE 0,63
  5486.  f6:      TYPE 0,64
  5487.  f7:      TYPE 0,65
  5488.  f8:      TYPE 0,66
  5489.  f9:      TYPE 0,67
  5490.  f10:     TYPE 0,68
  5491.  x0:      TYPE 0,3
  5492.  x1:      TYPE 1
  5493.  x2:      TYPE 2
  5494.  x3:      TYPE 3
  5495.  x4:      TYPE 4
  5496.  x5:      TYPE 5
  5497.  x6:      TYPE 6
  5498.  x7:      TYPE 7
  5499.  x8:      TYPE 8
  5500.  x9:      TYPE 9
  5501.  x10:     TYPE 10
  5502.  x11:     TYPE 11
  5503.  x12:     TYPE 12
  5504.  x13:     TYPE 13
  5505.  x14:     TYPE 14
  5506.  x15:     TYPE 15
  5507.  x16:     TYPE 16
  5508.  x17:     TYPE 17
  5509.  x18:     TYPE 18
  5510.  x19:     TYPE 19
  5511.  x20:     TYPE 20
  5512.  x21:     TYPE 21
  5513.  x22:     TYPE 22
  5514.  x23:     TYPE 23
  5515.  x24:     TYPE 24
  5516.  x25:     TYPE 25
  5517.  x26:     TYPE 26
  5518.  x27:     TYPE 27
  5519.  x28:     TYPE 28
  5520.  x29:     TYPE 29
  5521.  x30:     TYPE 30
  5522.  x31:     TYPE 31
  5523.  x32:     TYPE 32
  5524.  x33:     TYPE 33
  5525.  x34:     TYPE 34
  5526.  x35:     TYPE 35
  5527.  x36:     TYPE 36
  5528.  x37:     TYPE 37
  5529.  x38:     TYPE 38
  5530.  x39:     TYPE 39
  5531.  x40:     TYPE 40
  5532.  x41:     TYPE 41
  5533.  x42:     TYPE 42
  5534.  x43:     TYPE 43
  5535.  x44:     TYPE 44
  5536.  x45:     TYPE 45
  5537.  x46:     TYPE 46
  5538.  x47:     TYPE 47
  5539.  x48:     TYPE 48
  5540.  x49:     TYPE 49
  5541.  x50:     TYPE 50
  5542.  x51:     TYPE 51
  5543.  x52:     TYPE 52
  5544.  x53:     TYPE 53
  5545.  x54:     TYPE 54
  5546.  x55:     TYPE 55
  5547.  x56:     TYPE 56
  5548.  x57:     TYPE 57
  5549.  x58:     TYPE 58
  5550.  x59:     TYPE 59
  5551.  x60:     TYPE 60
  5552.  x61:     TYPE 61
  5553.  x62:     TYPE 62
  5554.  x63:     TYPE 63
  5555.  x64:     TYPE 64
  5556.  x65:     TYPE 65
  5557.  x66:     TYPE 66
  5558.  x67:     TYPE 67
  5559.  x68:     TYPE 68
  5560.  x69:     TYPE 69
  5561.  x70:     TYPE 70
  5562.  x71:     TYPE 71
  5563.  x72:     TYPE 72
  5564.  x73:     TYPE 73
  5565.  x74:     TYPE 74
  5566.  x75:     TYPE 75
  5567.  x76:     TYPE 76
  5568.  x77:     TYPE 77
  5569.  x78:     TYPE 78
  5570.  x79:     TYPE 79
  5571.  x80:     TYPE 80
  5572.  x81:     TYPE 81
  5573.  x82:     TYPE 82
  5574.  x83:     TYPE 83
  5575.  x84:     TYPE 84
  5576.  x85:     TYPE 85
  5577.  x86:     TYPE 86
  5578.  x87:     TYPE 87
  5579.  x88:     TYPE 88
  5580.  x89:     TYPE 89
  5581.  x90:     TYPE 90
  5582.  x91:     TYPE 91
  5583.  x92:     TYPE 92
  5584.  x93:     TYPE 93
  5585.  x94:     TYPE 94
  5586.  x95:     TYPE 95
  5587.  x96:     TYPE 96
  5588.  x97:     TYPE 97
  5589.  x98:     TYPE 98
  5590.  x99:     TYPE 99
  5591.  x100:    TYPE 100
  5592.  x101:    TYPE 101
  5593.  x102:    TYPE 102
  5594.  x103:    TYPE 103
  5595.  x104:    TYPE 104
  5596.  x105:    TYPE 105
  5597.  x106:    TYPE 106
  5598.  x107:    TYPE 107
  5599.  x108:    TYPE 108
  5600.  x109:    TYPE 109
  5601.  x110:    TYPE 110
  5602.  x111:    TYPE 111
  5603.  x112:    TYPE 112
  5604.  x113:    TYPE 113
  5605.  x114:    TYPE 114
  5606.  x115:    TYPE 115
  5607.  x116:    TYPE 116
  5608.  x117:    TYPE 117
  5609.  x118:    TYPE 118
  5610.  x119:    TYPE 119
  5611.  x120:    TYPE 120
  5612.  x121:    TYPE 121
  5613.  x122:    TYPE 122
  5614.  x123:    TYPE 123
  5615.  x124:    TYPE 124
  5616.  x125:    TYPE 125
  5617.  x126:    TYPE 126
  5618.  x127:    TYPE 127
  5619.  x128:    TYPE 128
  5620.  x129:    TYPE 129
  5621.  x130:    TYPE 130
  5622.  x131:    TYPE 131
  5623.  x132:    TYPE 132
  5624.  x133:    TYPE 133
  5625.  x134:    TYPE 134
  5626.  x135:    TYPE 135
  5627.  x136:    TYPE 136
  5628.  x137:    TYPE 137
  5629.  x138:    TYPE 138
  5630.  x139:    TYPE 139
  5631.  x140:    TYPE 140
  5632.  x141:    TYPE 141
  5633.  x142:    TYPE 142
  5634.  x143:    TYPE 143
  5635.  x144:    TYPE 144
  5636.  x145:    TYPE 145
  5637.  x146:    TYPE 146
  5638.  x147:    TYPE 147
  5639.  x148:    TYPE 148
  5640.  x149:    TYPE 149
  5641.  x150:    TYPE 150
  5642.  x151:    TYPE 151
  5643.  x152:    TYPE 152
  5644.  x153:    TYPE 153
  5645.  x154:    TYPE 154
  5646.  x155:    TYPE 155
  5647.  x156:    TYPE 156
  5648.  x157:    TYPE 157
  5649.  x158:    TYPE 158
  5650.  x159:    TYPE 159
  5651.  x160:    TYPE 160
  5652.  x161:    TYPE 161
  5653.  x162:    TYPE 162
  5654.  x163:    TYPE 163
  5655.  x164:    TYPE 164
  5656.  x165:    TYPE 165
  5657.  x166:    TYPE 166
  5658.  x167:    TYPE 167
  5659.  x168:    TYPE 168
  5660.  x169:    TYPE 169
  5661.  x170:    TYPE 170
  5662.  x171:    TYPE 171
  5663.  x172:    TYPE 172
  5664.  x173:    TYPE 173
  5665.  x174:    TYPE 174
  5666.  x175:    TYPE 175
  5667.  x224:    TYPE 224
  5668.  x225:    TYPE 225
  5669.  x226:    TYPE 226
  5670.  x227:    TYPE 227
  5671.  x228:    TYPE 228
  5672.  x229:    TYPE 229
  5673.  x230:    TYPE 230
  5674.  x231:    TYPE 231
  5675.  x232:    TYPE 232
  5676.  x233:    TYPE 233
  5677.  x234:    TYPE 234
  5678.  x235:    TYPE 235
  5679.  x236:    TYPE 236
  5680.  x237:    TYPE 237
  5681.  x238:    TYPE 238
  5682.  x239:    TYPE 239
  5683.  x240:    TYPE 240
  5684.  x241:    TYPE 241
  5685.  x242:    TYPE 242
  5686.  x243:    TYPE 243
  5687.  x244:    TYPE 244
  5688.  x245:    TYPE 245
  5689.  x246:    TYPE 246
  5690.  x247:    TYPE 247
  5691.  x248:    TYPE 248
  5692.  x249:    TYPE 249
  5693.  x250:    TYPE 250
  5694.  x251:    TYPE 251
  5695.  x252:    TYPE 252
  5696.  x253:    TYPE 253
  5697.  x254:    TYPE 254
  5698.  x255:    TYPE 255
  5699.  
  5700.  \SAMPCODE\MOUSE\SOURCES\MPIBM.DEF
  5701.  
  5702.  BEGIN lb,rb,bb,lma,rma,uma,dma,32,16
  5703.  
  5704.  ;------------------------------BOTH BUTTONS----------------------------------
  5705.  
  5706.  bb:     EXECUTE ESCAPE
  5707.  
  5708.  ;------------------------------LEFT BUTTON-----------------------------------
  5709.  
  5710.  lb:     MATCH 24,7,NORMAL,"Y",YES,lb1             ;"Enter Y"
  5711.  lb1:    MATCH 24,5,NORMAL,"w",YES,lb2             ;"Overwrite"
  5712.  lb2:    MATCH 24,15,NORMAL,":",YES,lb3            ;"Confirm change:"
  5713.  lb3:    MATCH 22,1,NORMAL,"H",NUL,MAIN            ;"HELP:"
  5714.  
  5715.  ;------------------------------RIGHT BUTTON----------------------------------
  5716.  
  5717.  rb:     MATCH 22,7,NORMAL,"D:",RETURN,rb1         ;"COMMAND:"
  5718.  rb1:    MATCH 22,4,NORMAL,"Y:",RETURN,rb2         ;"COPY:"
  5719.  rb2:    MATCH 22,6,NORMAL,"E:",RETURN,rb3         ;"DELETE:"
  5720.  rb3:    MATCH 22,7,NORMAL,"T:",RETURN,rb4         ;"FORMAT:"
  5721.  rb4:    MATCH 22,14,NORMAL,"T:",RETURN,rb5        ;"FORMAT DEFAULT:"
  5722.  rb5:    MATCH 22,4,NORMAL,"O:",RETURN,rb6         ;"GOTO:"
  5723.  rb6:    MATCH 22,6,NORMAL,"T:",RETURN,rb7         ;"INSERT:"
  5724.  rb7:    MATCH 22,4,NORMAL,"K:",RETURN,rb8         ;"LOCK:"
  5725.  rb8:    MATCH 22,4,NORMAL,"E:",RETURN,rb9         ;"MOVE:"
  5726.  rb9:    MATCH 22,5,NORMAL,"T:",RETURN,rb10        ;"PRINT:"
  5727.  rb10:   MATCH 22,8,NORMAL,"R:",RETURN,rb11        ;"TRANSFER:"
  5728.  rb11:   MATCH 22,6,NORMAL,"W:",RETURN,rb12        ;"WINDOW:"
  5729.  rb12:   MATCH 22,12,NORMAL,"T:",RETURN,rb13       ;"WINDOW SPLIT:"
  5730.  rb13:   MATCH 22,8,NORMAL,"L:",RETURN,rb14        ;"EXTERNAL:"
  5731.  rb14:   MATCH 22,1,NORMAL,"H",RETURN,rb15         ;"HELP:"
  5732.  rb15:   MATCH 24,7,NORMAL,"Y",YES,rb16            ;"Enter Y"
  5733.  rb16:   MATCH 24,5,NORMAL,"w",YES,rb17            ;"Overwrite"
  5734.  rb17:   MATCH 24,15,NORMAL,":",YES,TB             ;"Confirm change:"
  5735.  
  5736.  ;------------------------------LEFT MOTION-----------------------------------
  5737.  
  5738.  lma:    MATCH 22,1,NORMAL,"H",BKSP,lma1           ;"HELP:"
  5739.  lma1:   MATCH 24,18,NORMAL,"ty",LEFT,lma2         ;"Select option or type ...
  5740.  lma2:   MATCH 24,1,NORMAL,"M",LEFT,lm1            ;"Multiplan ..."
  5741.  
  5742.  lmb:    MATCH 24,18,NORMAL,"ty",BKSP,lmb1         ;"Select option or type ...
  5743.  lmb1:   MATCH 24,1,NORMAL,"M",BKSP,lm1            ;"Multiplan ..."
  5744.  
  5745.  lm1:    MATCH 24,1,NORMAL,"Se",BKSP,lm2           ;"Select option"
  5746.  lm2:    MATCH 24,9,NORMAL,"op",SPBKSP,lm3         ;"Invalid option ..."
  5747.  lm3:    MATCH 24,23,NORMAL,"w",NUL,lm4            ;"Press any key to redraw .
  5748.  lm4:    MATCH 24,15,NORMAL,":",NUL,lm5            ;"Confirm change:"
  5749.  lm5:    MATCH 24,7,NORMAL,"Y",NUL,lm6             ;"Enter Y"
  5750.  lm6:    MATCH 24,5,NORMAL,"w",NUL,LEFT            ;"Overwrite"
  5751.  
  5752.  ;------------------------------RIGHT MOTION----------------------------------
  5753.  
  5754.  rma:    MATCH 22,1,NORMAL,"H",SP,rma1             ;"HELP:"
  5755.  rma1:   MATCH 24,18,NORMAL,"ty",RIGHT,rma2        ;"Select option or type ...
  5756.  rma2:   MATCH 24,1,NORMAL,"M",RIGHT,rm1           ;"Multiplan ..."
  5757.  
  5758.  rmb:    MATCH 24,18,NORMAL,"ty",SP,rmb1           ;"Select option or type ...
  5759.  rmb1:   MATCH 24,1,NORMAL,"M",SP,rm1              ;"Multiplan ..."
  5760.  
  5761.  rm1:    MATCH 24,1,NORMAL,"Se",SP,rm2             ;"Select option"
  5762.  rm2:    MATCH 24,9,NORMAL,"op",SPBKSP,rm3         ;"Invalid option ..."
  5763.  rm3:    MATCH 24,23,NORMAL,"w",NUL,rm4            ;"Press any key to redraw .
  5764.  rm4:    MATCH 24,15,NORMAL,":",NUL,rm5            ;"Confirm change:"
  5765.  rm5:    MATCH 24,7,NORMAL,"Y",NUL,rm6             ;"Enter Y"
  5766.  rm6:    MATCH 24,5,NORMAL,"w",NUL,RIGHT           ;"Overwrite"
  5767.  
  5768.  ;------------------------------UP MOTION-------------------------------------
  5769.  
  5770.  uma:    MATCH 22,1,NORMAL,"H",NUL,uma1            ;"HELP:"
  5771.  uma1:   MATCH 24,18,NORMAL,"ty",UP,uma2           ;"Select option or type ...
  5772.  uma2:   MATCH 24,1,NORMAL,"M",UP,um1              ;"Multiplan ..."
  5773.  
  5774.  umb:    MATCH 24,18,NORMAL,"ty",NUL,umb1          ;"Select option or type ...
  5775.  umb1:   MATCH 24,1,NORMAL,"M",NUL,um1             ;"Multiplan ..."
  5776.  
  5777.  um1:    MATCH 24,1,NORMAL,"Se",NUL,um2            ;"Select option"
  5778.  um2:    MATCH 24,9,NORMAL,"op",SPBKSP,um3         ;"Invalid option ..."
  5779.  um3:    MATCH 24,23,NORMAL,"w",NUL,um4            ;"Press any key to redraw .
  5780.  um4:    MATCH 24,15,NORMAL,":",NUL,um5            ;"Confirm change:"
  5781.  um5:    MATCH 24,7,NORMAL,"Y",NUL,um6             ;"Enter Y"
  5782.  um6:    MATCH 24,5,NORMAL,"w",NUL,UP              ;"Overwrite"
  5783.  
  5784.  ;------------------------------DOWN MOTION-----------------------------------
  5785.  
  5786.  dma:    MATCH 22,1,NORMAL,"H",NUL,dma1            ;"HELP:"
  5787.  dma1:   MATCH 24,18,NORMAL,"ty",DOWN,dma2         ;"Select option or type ...
  5788.  dma2:   MATCH 24,1,NORMAL,"M",DOWN,dm1            ;"Multiplan ..."
  5789.  
  5790.  dmb:    MATCH 24,18,NORMAL,"ty",NUL,dmb1          ;"Select option or type ...
  5791.  dmb1:   MATCH 24,1,NORMAL,"M",NUL,dm1             ;"Multiplan ..."
  5792.  dm1:    MATCH 24,1,NORMAL,"Se",NUL,dm2            ;"Select option"
  5793.  dm2:    MATCH 24,9,NORMAL,"op",SPBKSP,dm3         ;"Invalid option ..."
  5794.  dm3:    MATCH 24,23,NORMAL,"w",NUL,dm4            ;"Press any key to redraw .
  5795.  dm4:    MATCH 24,15,NORMAL,":",NUL,dm5            ;"Confirm change:"
  5796.  dm5:    MATCH 24,7,NORMAL,"Y",NUL,dm6             ;"Enter Y"
  5797.  dm6:    MATCH 24,5,NORMAL,"w",NUL,DOWN            ;"Overwrite"
  5798.  
  5799.  ;------------------------------MENUS-----------------------------------------
  5800.  
  5801.  MAIN:   popup 19,1,NORMAL
  5802.  text "───────────────────────────────────────────────────────────────────────
  5803.  text "MAIN: Enter Cancel Cell Command Reference Recalc  :   ,  Help CURSOR
  5804.  text "───────────────────────────────────────────────────────────────────────
  5805.  select 2,7,5,RETURN
  5806.  select 2,13,6,ESCAPE
  5807.  select 2,20,4,CELL
  5808.  select 2,25,7,COMMAND
  5809.  select 2,33,9,REFERENCE
  5810.  select 2,43,6,RECALC
  5811.  select 2,50,3,COLON
  5812.  select 2,54,3,COMMA
  5813.  select 2,58,4,HELP
  5814.  select 2,63,6,CURSOR
  5815.  pend
  5816.  
  5817.  COMMAND:  ASSIGN ,,,lmb,rmb,umb,dmb,,
  5818.  CELL:     ASSIGN ,,,lma,rma,uma,dma,,
  5819.  
  5820.  CURSOR: popup 19,1,NORMAL
  5821.  text "───────────────────────────────────────────────────────────────────────
  5822.  text "CURSOR: MAIN Home End NxtWindow NxtCell PageUp PageDown PageLeft PageRi
  5823.  text "───────────────────────────────────────────────────────────────────────
  5824.  select 2,9,4,MAIN
  5825.  select 2,14,4,HOME
  5826.  select 2,19,3,END
  5827.  select 2,23,9,NXTWINDOW
  5828.  select 2,33,7,NXTCELL
  5829.  select 2,41,6,PGUP
  5830.  select 2,48,8,PGDOWN
  5831.  select 2,57,8,PGLEFT
  5832.  select 2,66,9,PGRIGHT
  5833.  pend
  5834.  
  5835.  ;------------------------------KEYS------------------------------------------
  5836.  
  5837.  NUL:           NOTHING
  5838.  BKSP:          TYPE 8                             ;Backspace
  5839.  TB:            TYPE 9                             ;Tab
  5840.  RETURN:        TYPE 13                            ;Enter
  5841.  ESCAPE:        TYPE 27                            ;Esc
  5842.  HELP:          TYPE 0,35                          ;Alt-H
  5843.  SP:            TYPE " "
  5844.  YES:           TYPE "Y"
  5845.  SPBKSP:        TYPE " ",8                         ;Space,Backspace
  5846.  NXTWINDOW:     TYPE 0,59                          ;F1
  5847.  NXTCELL:       TYPE 0,60                          ;F2
  5848.  REFERENCE:     TYPE 0,61                          ;F3
  5849.  RECALC:        TYPE 0,62                          ;F4
  5850.  COLON:         TYPE ":"
  5851.  COMMA:         TYPE ","
  5852.  HOME:          TYPE 0,132                         ;Ctrl-PgUp
  5853.  END:           TYPE 0,79                          ;End
  5854.  PGUP:          TYPE 0,73                          ;PgUp
  5855.  PGDOWN:        TYPE 0,81                          ;PgDn
  5856.  PGLEFT:        TYPE 0,115                         ;Ctrl-Left
  5857.  PGRIGHT:       TYPE 0,116                         ;Ctrl-Right
  5858.  LEFT:          TYPE 0,75                          ;Left
  5859.  RIGHT:         TYPE 0,77                          ;Right
  5860.  UP:            TYPE 0,72                          ;Up
  5861.  DOWN:          TYPE 0,80                          ;Down
  5862.  
  5863.  
  5864.  \SAMPCODE\MOUSE\SOURCES\MPMS.DEF
  5865.  
  5866.  BEGIN lb,rb,bb,lma,rma,uma,dma,32,16
  5867.  
  5868.  ;------------------------------BOTH BUTTONS----------------------------------
  5869.  
  5870.  bb:     EXECUTE ESCAPE
  5871.  
  5872.  ;------------------------------LEFT BUTTON-----------------------------------
  5873.  
  5874.  lb:     MATCH 24,7,NORMAL,"Y",YES,lb1             ;"Enter Y"
  5875.  lb1:    MATCH 24,5,NORMAL,"w",YES,lb2             ;"Overwrite"
  5876.  lb2:    MATCH 24,15,NORMAL,":",YES,lb3            ;"Confirm change:"
  5877.  lb3:    MATCH 22,1,NORMAL,"H",NUL,MAIN            ;"HELP:"
  5878.  
  5879.  ;------------------------------RIGHT BUTTON----------------------------------
  5880.  
  5881.  rb:     MATCH 22,7,NORMAL,"D:",RETURN,rb1         ;"COMMAND:"
  5882.  rb1:    MATCH 22,4,NORMAL,"Y:",RETURN,rb2         ;"COPY:"
  5883.  rb2:    MATCH 22,6,NORMAL,"E:",RETURN,rb3         ;"DELETE:"
  5884.  rb3:    MATCH 22,7,NORMAL,"T:",RETURN,rb4         ;"FORMAT:"
  5885.  rb4:    MATCH 22,14,NORMAL,"T:",RETURN,rb5        ;"FORMAT DEFAULT:"
  5886.  rb5:    MATCH 22,4,NORMAL,"O:",RETURN,rb6         ;"GOTO:"
  5887.  rb6:    MATCH 22,6,NORMAL,"T:",RETURN,rb7         ;"INSERT:"
  5888.  rb7:    MATCH 22,4,NORMAL,"K:",RETURN,rb8         ;"LOCK:"
  5889.  rb8:    MATCH 22,4,NORMAL,"E:",RETURN,rb9         ;"MOVE:"
  5890.  rb9:    MATCH 22,5,NORMAL,"T:",RETURN,rb10        ;"PRINT:"
  5891.  rb10:   MATCH 22,8,NORMAL,"R:",RETURN,rb11        ;"TRANSFER:"
  5892.  rb11:   MATCH 22,6,NORMAL,"W:",RETURN,rb12        ;"WINDOW:"
  5893.  rb12:   MATCH 22,12,NORMAL,"T:",RETURN,rb13       ;"WINDOW SPLIT:"
  5894.  rb13:   MATCH 22,8,NORMAL,"L:",RETURN,rb14        ;"EXTERNAL:"
  5895.  rb14:   MATCH 22,1,NORMAL,"H",RETURN,rb15         ;"HELP:"
  5896.  rb15:   MATCH 24,7,NORMAL,"Y",YES,rb16            ;"Enter Y"
  5897.  rb16:   MATCH 24,5,NORMAL,"w",YES,rb17            ;"Overwrite"
  5898.  rb17:   MATCH 24,15,NORMAL,":",YES,TB             ;"Confirm change:"
  5899.  
  5900.  ;------------------------------LEFT MOTION-----------------------------------
  5901.  
  5902.  lma:    MATCH 22,1,NORMAL,"H",BKSP,lma1           ;"HELP:"
  5903.  lma1:   MATCH 24,18,NORMAL,"ty",LEFT,lma2         ;"Select option or type ...
  5904.  lma2:   MATCH 24,1,NORMAL,"M",LEFT,lm1            ;"Multiplan ..."
  5905.  
  5906.  lmb:    MATCH 24,18,NORMAL,"ty",BKSP,lmb1         ;"Select option or type ...
  5907.  lmb1:   MATCH 24,1,NORMAL,"M",BKSP,lm1            ;"Multiplan ..."
  5908.  
  5909.  lm1:    MATCH 24,1,NORMAL,"Se",BKSP,lm2           ;"Select option"
  5910.  lm2:    MATCH 24,9,NORMAL,"op",SPBKSP,lm3         ;"Invalid option ..."
  5911.  lm3:    MATCH 24,23,NORMAL,"w",NUL,lm4            ;"Press any key to redraw .
  5912.  lm4:    MATCH 24,15,NORMAL,":",NUL,lm5            ;"Confirm change:"
  5913.  lm5:    MATCH 24,7,NORMAL,"Y",NUL,lm6             ;"Enter Y"
  5914.  lm6:    MATCH 24,5,NORMAL,"w",NUL,LEFT            ;"Overwrite"
  5915.  
  5916.  ;------------------------------RIGHT MOTION----------------------------------
  5917.  
  5918.  rma:    MATCH 22,1,NORMAL,"H",SP,rma1             ;"HELP:"
  5919.  rma1:   MATCH 24,18,NORMAL,"ty",RIGHT,rma2        ;"Select option or type ...
  5920.  rma2:   MATCH 24,1,NORMAL,"M",RIGHT,rm1           ;"Multiplan ..."
  5921.  
  5922.  rmb:    MATCH 24,18,NORMAL,"ty",SP,rmb1           ;"Select option or type ...
  5923.  rmb1:   MATCH 24,1,NORMAL,"M",SP,rm1              ;"Multiplan ..."
  5924.  
  5925.  rm1:    MATCH 24,1,NORMAL,"Se",SP,rm2             ;"Select option"
  5926.  rm2:    MATCH 24,9,NORMAL,"op",SPBKSP,rm3         ;"Invalid option ..."
  5927.  rm3:    MATCH 24,23,NORMAL,"w",NUL,rm4            ;"Press any key to redraw .
  5928.  rm4:    MATCH 24,15,NORMAL,":",NUL,rm5            ;"Confirm change:"
  5929.  rm5:    MATCH 24,7,NORMAL,"Y",NUL,rm6             ;"Enter Y"
  5930.  rm6:    MATCH 24,5,NORMAL,"w",NUL,RIGHT           ;"Overwrite"
  5931.  
  5932.  ;------------------------------UP MOTION-------------------------------------
  5933.  
  5934.  uma:    MATCH 22,1,NORMAL,"H",NUL,uma1            ;"HELP:"
  5935.  uma1:   MATCH 24,18,NORMAL,"ty",UP,uma2           ;"Select option or type ...
  5936.  uma2:   MATCH 24,1,NORMAL,"M",UP,um1              ;"Multiplan ..."
  5937.  
  5938.  umb:    MATCH 24,18,NORMAL,"ty",NUL,umb1          ;"Select option or type ...
  5939.  umb1:   MATCH 24,1,NORMAL,"M",NUL,um1             ;"Multiplan ..."
  5940.  
  5941.  um1:    MATCH 24,1,NORMAL,"Se",NUL,um2            ;"Select option"
  5942.  um2:    MATCH 24,9,NORMAL,"op",SPBKSP,um3         ;"Invalid option ..."
  5943.  um3:    MATCH 24,23,NORMAL,"w",NUL,um4            ;"Press any key to redraw .
  5944.  um4:    MATCH 24,15,NORMAL,":",NUL,um5            ;"Confirm change:"
  5945.  um5:    MATCH 24,7,NORMAL,"Y",NUL,um6             ;"Enter Y"
  5946.  um6:    MATCH 24,5,NORMAL,"w",NUL,UP              ;"Overwrite"
  5947.  
  5948.  ;------------------------------DOWN MOTION-----------------------------------
  5949.  
  5950.  dma:    MATCH 22,1,NORMAL,"H",NUL,dma1            ;"HELP:"
  5951.  dma1:   MATCH 24,18,NORMAL,"ty",DOWN,dma2         ;"Select option or type ...
  5952.  dma2:   MATCH 24,1,NORMAL,"M",DOWN,dm1            ;"Multiplan ..."
  5953.  
  5954.  dmb:    MATCH 24,18,NORMAL,"ty",NUL,dmb1          ;"Select option or type ...
  5955.  dmb1:   MATCH 24,1,NORMAL,"M",NUL,dm1             ;"Multiplan ..."
  5956.  dm1:    MATCH 24,1,NORMAL,"Se",NUL,dm2            ;"Select option"
  5957.  dm2:    MATCH 24,9,NORMAL,"op",SPBKSP,dm3         ;"Invalid option ..."
  5958.  dm3:    MATCH 24,23,NORMAL,"w",NUL,dm4            ;"Press any key to redraw .
  5959.  dm4:    MATCH 24,15,NORMAL,":",NUL,dm5            ;"Confirm change:"
  5960.  dm5:    MATCH 24,7,NORMAL,"Y",NUL,dm6             ;"Enter Y"
  5961.  dm6:    MATCH 24,5,NORMAL,"w",NUL,DOWN            ;"Overwrite"
  5962.  
  5963.  ;------------------------------MENUS-----------------------------------------
  5964.  
  5965.  MAIN:   popup 19,1,NORMAL
  5966.  text "───────────────────────────────────────────────────────────────────────
  5967.  text "MAIN: Enter Cancel Cell Command Reference Recalc  :   ,  Help CURSOR
  5968.  text "───────────────────────────────────────────────────────────────────────
  5969.  select 2,7,5,RETURN
  5970.  select 2,13,6,ESCAPE
  5971.  select 2,20,4,CELL
  5972.  select 2,25,7,COMMAND
  5973.  select 2,33,9,REFERENCE
  5974.  select 2,43,6,RECALC
  5975.  select 2,50,3,COLON
  5976.  select 2,54,3,COMMA
  5977.  select 2,58,4,HELP
  5978.  select 2,63,6,CURSOR
  5979.  pend
  5980.  
  5981.  COMMAND:  ASSIGN ,,,lmb,rmb,umb,dmb,,
  5982.  CELL:     ASSIGN ,,,lma,rma,uma,dma,,
  5983.  
  5984.  CURSOR: popup 19,1,NORMAL
  5985.  text "───────────────────────────────────────────────────────────────────────
  5986.  text "CURSOR: MAIN Home End NxtWindow NxtCell PageUp PageDown PageLeft PageRi
  5987.  text "───────────────────────────────────────────────────────────────────────
  5988.  select 2,9,4,MAIN
  5989.  select 2,14,4,HOME
  5990.  select 2,19,3,END
  5991.  select 2,23,9,NXTWINDOW
  5992.  select 2,33,7,NXTCELL
  5993.  select 2,41,6,PGUP
  5994.  select 2,48,8,PGDOWN
  5995.  select 2,57,8,PGLEFT
  5996.  select 2,66,9,PGRIGHT
  5997.  pend
  5998.  
  5999.  ;------------------------------KEYS------------------------------------------
  6000.  
  6001.  NUL:           NOTHING
  6002.  BKSP:          TYPE 8                             ;Backspace
  6003.  TB:            TYPE 9                             ;Tab
  6004.  RETURN:        TYPE 13                            ;Enter
  6005.  ESCAPE:        TYPE 27                            ;Esc
  6006.  HELP:          TYPE 0,68                          ;F10
  6007.  SP:            TYPE " "
  6008.  YES:           TYPE "Y"
  6009.  SPBKSP:        TYPE " ",8                         ;Space,Backspace
  6010.  NXTWINDOW:     TYPE 0,64                          ;F6
  6011.  NXTCELL:       TYPE 0,63                          ;F5
  6012.  REFERENCE:     TYPE 0,65                          ;F7
  6013.  RECALC:        TYPE 0,66                          ;F8
  6014.  COLON:         TYPE ":"
  6015.  COMMA:         TYPE ","
  6016.  HOME:          TYPE 0,71                          ;Home
  6017.  END:           TYPE 0,79                          ;End
  6018.  PGUP:          TYPE 0,73                          ;PgUp
  6019.  PGDOWN:        TYPE 0,81                          ;PgDn
  6020.  PGLEFT:        TYPE 0,115                         ;Ctrl-Left
  6021.  PGRIGHT:       TYPE 0,116                         ;Ctrl-Right
  6022.  LEFT:          TYPE 0,75                          ;Left
  6023.  RIGHT:         TYPE 0,77                          ;Right
  6024.  UP:            TYPE 0,72                          ;Up
  6025.  DOWN:          TYPE 0,80                          ;Down
  6026.  
  6027.  
  6028.  \SAMPCODE\MOUSE\SOURCES\SYM.DEF
  6029.  
  6030.  BEGIN lb,rb,bb,lm,rm,um,dm,32,16
  6031.  
  6032.  ;********************************************************************
  6033.  ;*          Microsoft Mouse definition file for Symphony            *
  6034.  ;*          Revised 6/25/86                                         *
  6035.  ;********************************************************************
  6036.  
  6037.  ;------------------------------BOTH BUTTONS--------------------------
  6038.  bb:   EXECUTE ESCAPE
  6039.  ;------------------------------LEFT BUTTON---------------------------
  6040.  lb:   MATCH 10,2,," ",MAIN,lb1
  6041.  lb1:  MATCH 10,3,," ",MAIN,lb2
  6042.  lb2:  MATCH 10,4,," ",MAIN,lb3
  6043.  lb3:  MATCH 10,5,," ",MAIN,lb4
  6044.  lb4:  MATCH 10,6,," ",MAIN,lb5
  6045.  lb5:  MATCH 23,76,," ",MAIN,lb6
  6046.  lb6:  MATCH 23,77,," ",MAIN,lb7
  6047.  lb7:  MATCH 23,78,," ",MAIN,lb8
  6048.  lb8:  MATCH 23,79,," ",MAIN,lb9
  6049.  lb9:  MATCH 24,76,," ",MAIN,lb10
  6050.  lb10: MATCH 24,77,," ",MAIN,lb11
  6051.  lb11: MATCH 24,78,," ",MAIN,lb12
  6052.  lb12: MATCH 24,79,," ",MAIN,SLASH  ;In Graphics mode, pop sym menu
  6053.  
  6054.  ;------------------------------RIGHT BUTTON--------------------------
  6055.  rb:   MATCH 1,76,,"SHEET",SLASH,RETURN
  6056.  ;------------------------------LEFT MOTION---------------------------
  6057.  lm:   MATCH 1,76,,"ERROR",NUL,lm1
  6058.  lm1:  MATCH 23,3,,"[ESCAPE]",NUL,lm2        ;Install
  6059.  lm2:  MATCH 2,35,,"Help Screen",NUL,lm3     ;Install Help
  6060.  lm3:  MATCH 6,24,,"translate",NUL,LEFT      ;Translate
  6061.  
  6062.  ;------------------------------RIGHT MOTION--------------------------
  6063.  rm:   MATCH 1,76,,"ERROR",NUL,rm1
  6064.  rm1:  MATCH 23,3,,"[ESCAPE]",NUL,rm2        ;Install
  6065.  rm2:  MATCH 2,35,,"Help Screen",NUL,rm3     ;Install Help
  6066.  rm3:  MATCH 6,24,,"translate",NUL,RIGHT     ;Translate
  6067.  
  6068.  ;------------------------------UP MOTION-----------------------------
  6069.  um:   MATCH 1,76,,"ERROR",NUL,um1
  6070.  um1:  MATCH 1,76,,"MENU",NUL,um2
  6071.  um2:  MATCH 1,77,,"MENU",NUL,um4
  6072.  um4:  MATCH 3,3,,"Symphony",NUL,um5         ;Access title menu
  6073.  um5:  MATCH 2,35,,"Help Screen",NUL,UP      ;Install Help
  6074.  
  6075.  ;------------------------------DOWN MOTION---------------------------
  6076.  dm:  MATCH 1,76,,"ERROR",NUL,dm1
  6077.  dm1: MATCH 1,76,,"MENU",NUL,dm2
  6078.  dm2: MATCH 1,77,,"MENU",NUL,dm4
  6079.  dm4: MATCH 3,3,,"Symphony",NUL,dm5         ;Access title menu
  6080.  dm5: MATCH 2,35,,"Help Screen",NUL,DOWN    ;Install Help
  6081.  
  6082.  ;------------------------------MENUS---------------------------------
  6083.  
  6084.  MAIN: popup 23,1,NORMAL
  6085.  text "───────────────────────────────────────────────────────────────────────
  6086.  text "MAIN: Cancel Help Menu Service Anchor NxtWin Zoom Change Switch Update
  6087.  text "───────────────────────────────────────────────────────────────────────
  6088.  select 2,7,6,CANCEL
  6089.  select 2,14,4,F1
  6090.  select 2,19,4,F10
  6091.  select 2,24,7,F9
  6092.  select 2,32,6,PERIOD
  6093.  select 2,39,6,F6
  6094.  select 2,46,4,ALTF6
  6095.  select 2,51,6,ALTF10
  6096.  select 2,58,6,ALTF9
  6097.  select 2,65,6,ALTF8
  6098.  select 2,72,5,SHEET
  6099.  select 2,78,3,DOC
  6100.  pend
  6101.  
  6102.  SHEET: popup 23,1,NORMAL
  6103.  text "───────────────────────────────────────────────────────────────────────
  6104.  text "SHEET: MAIN Menu Services Anchor @Sum( ) ( + - * / Abs Edit Recalc Name
  6105.  text "───────────────────────────────────────────────────────────────────────
  6106.  select 2,8,4,MAIN
  6107.  select 2,13,4,F10
  6108.  select 2,18,8,F9
  6109.  select 2,27,6,PERIOD
  6110.  select 2,34,5,SUM
  6111.  select 2,40,1,RGTPRAN
  6112.  select 2,42,1,LFTPRAN
  6113.  select 2,44,1,ADD
  6114.  select 2,46,1,SUB
  6115.  select 2,48,1,MUL
  6116.  select 2,50,1,DIV
  6117.  select 2,52,3,F3
  6118.  select 2,56,4,F2
  6119.  select 2,61,6,F8
  6120.  select 2,68,4,RENAME
  6121.  select 2,73,4,HOME
  6122.  select 2,78,3,END
  6123.  pend
  6124.  
  6125.  DOC: popup 23,1,NORMAL
  6126.  text "───────────────────────────────────────────────────────────────────────
  6127.  text "DOC: MAIN Menu Services I? Align Split Center Indent Erase Compose GoTo
  6128.  text "───────────────────────────────────────────────────────────────────────
  6129.  select 2,6,4,MAIN
  6130.  select 2,11,4,F10
  6131.  select 2,16,8,F9
  6132.  select 2,25,2,ALTF2
  6133.  select 2,28,5,F2
  6134.  select 2,34,5,ALTF3
  6135.  select 2,40,6,ALTF4
  6136.  select 2,47,6,F3
  6137.  select 2,54,5,F4
  6138.  select 2,60,7,ALTF1
  6139.  select 2,68,4,F5
  6140.  select 2,73,3,END
  6141.  select 2,77,4,MOVE
  6142.  pend
  6143.  
  6144.  MOVE: popup 23,1,NORMAL
  6145.  text "───────────────────────────────────────────────────────────────────────
  6146.  text "MOVE: Left Right Ln_Start Ln_End Par_Start Par_End PgUp PgDn Doc_Start
  6147.  text "───────────────────────────────────────────────────────────────────────
  6148.  select 2,7,4,CTLLEFT
  6149.  select 2,12,5,CTLRGHT
  6150.  select 2,18,8,ENDLEFT
  6151.  select 2,27,6,ENDRGHT
  6152.  select 2,34,9,ENDUP
  6153.  select 2,44,7,ENDDOWN
  6154.  select 2,52,4,PGUP
  6155.  select 2,57,4,PGDN
  6156.  select 2,62,9,HOME
  6157.  select 2,72,7,ENDHOME
  6158.  pend
  6159.  
  6160.  ;------------------------------KEYS----------------------------------
  6161.  NUL:       NOTHING
  6162.  RETURN:    TYPE 13
  6163.  RENAME:    TYPE "/","R","N"
  6164.  ESCAPE:    TYPE 27
  6165.  SLASH:     TYPE "/"
  6166.  CANCEL:    TYPE 27,27,27,27,27,27,27,27
  6167.  PERIOD:    TYPE "."
  6168.  COMMA:     TYPE ","
  6169.  F1:        TYPE 0,59
  6170.  F2:        TYPE 0,60
  6171.  F3:        TYPE 0,61
  6172.  F4:        TYPE 0,62
  6173.  F5:        TYPE 0,63
  6174.  F6:        TYPE 0,64
  6175.  F7:        TYPE 0,65
  6176.  F8:        TYPE 0,66
  6177.  F9:        TYPE 0,67
  6178.  F10:       TYPE 0,68
  6179.  ALTF1:     TYPE 0,104
  6180.  ALTF2:     TYPE 0,105
  6181.  ALTF3:     TYPE 0,106
  6182.  ALTF4:     TYPE 0,107
  6183.  ALTF5:     TYPE 0,108
  6184.  ALTF6:     TYPE 0,109
  6185.  ALTF7:     TYPE 0,110
  6186.  ALTF8:     TYPE 0,111
  6187.  ALTF9:     TYPE 0,112
  6188.  ALTF10:    TYPE 0,113
  6189.  HOME:      TYPE 0,71
  6190.  END:       TYPE 0,79
  6191.  ENDUP:     TYPE 0,79,0,72
  6192.  ENDDOWN:   TYPE 0,79,0,80
  6193.  ENDLEFT:   TYPE 0,79,0,75
  6194.  ENDRGHT:   TYPE 0,79,0,77
  6195.  ENDHOME:   TYPE 0,79,0,71
  6196.  CTLLEFT:   TYPE 0,115
  6197.  CTLRGHT:   TYPE 0,116
  6198.  BKTB:      TYPE 0,15         ;BACK TAB
  6199.  TB:        TYPE 9
  6200.  PGUP:      TYPE 0,73
  6201.  PGDN:      TYPE 0,81
  6202.  LEFT:      TYPE 0,75
  6203.  RIGHT:     TYPE 0,77
  6204.  UP:        TYPE 0,72
  6205.  DOWN:      TYPE 0,80
  6206.  SPACE:     TYPE 32
  6207.  LFTPRAN:   TYPE "("
  6208.  RGTPRAN:   TYPE ")"
  6209.  MUL:       TYPE "*"
  6210.  ADD:       TYPE "+"
  6211.  SUB:       TYPE "-"
  6212.  DIV:       TYPE "/"
  6213.  SUM:       TYPE "@Sum("
  6214.  
  6215.  \SAMPCODE\MOUSE\SOURCES\VC.DEF
  6216.  
  6217.  
  6218.  BEGIN   lb,rb,bb,lm,rm,um,dm,32,16
  6219.  
  6220.  ;------------------------------BOTH BUTTONS----------------------------------
  6221.  
  6222.  bb:     MATCH 2,1,INVERSE,"[",CTRLC,bb1         ;"[Edit]:"
  6223.  bb1:    MATCH 2,1,INVERSE,"V",CTRLC,bb2         ;"Value"
  6224.  bb2:    MATCH 2,5,INVERSE,"l ",CTRLC,ESCAPE             ;"Label" not "Label:"
  6225.  
  6226.  ;------------------------------LEFT BUTTON-----------------------------------
  6227.  
  6228.  lb:     MATCH 2,1,INVERSE," ",MAIN,lb1          ;Not in command mode
  6229.  lb1:    MATCH 2,1,INVERSE,"(C)",MAIN,lb2        ;"(C)"
  6230.  lb2:    MATCH 2,1,INVERSE,"V",VALUE,lb3         ;"Value"
  6231.  lb3:    MATCH 2,5,INVERSE,"l ",LABEL,lb4                ;"Label" not "Label:"
  6232.  lb4:    MATCH 2,12,INVERSE,"N=",NO,lb5          ;"Replicate: N=No Change ..."
  6233.  lb5:    MATCH 2,13,INVERSE,"Y",YES,lb6          ;"Clear: Type Y ..."
  6234.  lb6:    MATCH 2,12,INVERSE,"Y",YES,lb7          ;"Quit: Type Y ..."
  6235.  lb7:    MATCH 2,25,INVERSE,"Y",YES,lb8          ;"... File already ..."
  6236.  lb8:    MATCH 2,19,INVERSE,"Y",YES,RETURN               ;"Delete File: Type Y
  6237.  
  6238.  ;------------------------------RIGHT BUTTON----------------------------------
  6239.  
  6240.  rb:     MATCH 2,1,INVERSE," ",MAIN,rb1          ;Not in command mode
  6241.  rb1:    MATCH 2,1,INVERSE,"(C)",MAIN,rb2        ;"(C)"
  6242.  rb2:    MATCH 2,1,INVERSE,"V",VALUE,rb3         ;"Value"
  6243.  rb3:    MATCH 2,5,INVERSE,"l ",LABEL,rb4                ;"Label" not "Label:"
  6244.  rb4:    MATCH 2,12,INVERSE,"N=",REL,lb5         ;"Replicate: N=No Change ..."
  6245.  rb5:    MATCH 2,13,INVERSE,"Y",YES,rb6          ;"Clear: Type Y ..."
  6246.  rb6:    MATCH 2,12,INVERSE,"Y",YES,rb7          ;"Quit: Type Y ..."
  6247.  rb7:    MATCH 2,25,INVERSE,"Y",YES,rb8          ;"... File already ..."
  6248.  rb8:    MATCH 2,19,INVERSE,"Y",YES,RETURN               ;"Delete File: Type Y
  6249.  
  6250.  ;------------------------------LEFT MOTION-----------------------------------
  6251.  
  6252.  lm:     MATCH 2,1,INVERSE," ",LEFT,lm1          ;Not in command mode
  6253.  lm1:    MATCH 2,1,INVERSE,"(C)",LEFT,lm2                ;"(C)"
  6254.  lm2:    MATCH 2,1,INVERSE,"V",LEFT,lm3          ;"Value"
  6255.  lm3:    MATCH 2,1,INVERSE,"M",LEFT,lm4          ;"Move:"
  6256.  lm4:    MATCH 2,1,INVERSE,"[",LEFT,lm5          ;"[Edit]:"
  6257.  lm5:    MATCH 2,1,INVERSE,"Rep",LEFT,lm6        ;"Replicate:"
  6258.  lm6:    MATCH 2,6,INVERSE,": L",LEFT,lm7        ;"Print: Lower right ..."
  6259.  lm7:    MATCH 2,10,INVERSE,": L",LEFT,NUL       ;"Data save: Lower right ..."
  6260.  
  6261.  ;------------------------------RIGHT MOTION----------------------------------
  6262.  
  6263.  rm:     MATCH 2,1,INVERSE," ",RIGHT,rm1         ;Not in command mode
  6264.  rm1:    MATCH 2,1,INVERSE,"(C)",RIGHT,rm2       ;"(C)"
  6265.  rm2:    MATCH 2,1,INVERSE,"V",RIGHT,rm3         ;"Value"
  6266.  rm3:    MATCH 2,1,INVERSE,"M",RIGHT,rm4         ;"Move:"
  6267.  rm4:    MATCH 2,1,INVERSE,"[",RIGHT,rm5         ;"[Edit]:"
  6268.  rm5:    MATCH 2,1,INVERSE,"Rep",RIGHT,rm6       ;"Replicate:"
  6269.  rm6:    MATCH 2,6,INVERSE,": L",RIGHT,rm7       ;"Print: Lower right ..."
  6270.  rm7:    MATCH 2,10,INVERSE,": L",RIGHT,NUL      ;"Data save: Lower right ..."
  6271.  
  6272.  ;------------------------------UP MOTION-------------------------------------
  6273.  
  6274.  um:     MATCH 2,1,INVERSE," ",UP,um1            ;Not in command mode
  6275.  um1:    MATCH 2,1,INVERSE,"(C)",UP,um2          ;"(C)"
  6276.  um2:    MATCH 2,1,INVERSE,"V",UP,um3            ;"Value"
  6277.  um3:    MATCH 2,1,INVERSE,"M",UP,um4            ;"Move:"
  6278.  um4:    MATCH 2,1,INVERSE,"Rep",UP,um5          ;"Replicate:"
  6279.  um5:    MATCH 2,6,INVERSE,": L",UP,um6  ;"Print: Lower right ..."
  6280.  um6:    MATCH 2,10,INVERSE,": L",UP,NUL ;"Data save: Lower right ..."
  6281.  
  6282.  ;------------------------------DOWN MOTION-----------------------------------
  6283.  
  6284.  dm:     MATCH 2,1,INVERSE," ",DOWN,dm1          ;Not in command mode
  6285.  dm1:    MATCH 2,1,INVERSE,"(C)",DOWN,dm2        ;"(C)"
  6286.  dm2:    MATCH 2,1,INVERSE,"V",DOWN,dm3          ;"Value"
  6287.  dm3:    MATCH 2,1,INVERSE,"M",DOWN,dm4          ;"Move:"
  6288.  dm4:    MATCH 2,1,INVERSE,"Rep",DOWN,dm5        ;"Replicate:"
  6289.  dm5:    MATCH 2,6,INVERSE,": L",DOWN,dm6        ;"Print: Lower right ..."
  6290.  dm6:    MATCH 2,10,INVERSE,": L",DOWN,NUL       ;"Data save: Lower right ..."
  6291.  
  6292.  ;------------------------------MENUS-----------------------------------------
  6293.  
  6294.  MAIN:   popup   2,1,INVERSE
  6295.          text "Main: Command Label Value Goto Home Window Recalc Absolute "
  6296.          select  1,7,7,COMMAND
  6297.          select  1,15,5,QUOTE
  6298.          select  1,21,5,PLUSBKSP
  6299.          select  1,27,4,GREAT
  6300.          select  1,32,4,HOME
  6301.          select  1,37,6,SEMICOLON
  6302.          select  1,44,6,BANG
  6303.          select  1,51,8,POUND
  6304.          pend
  6305.  
  6306.  COMMAND:        popup   2,1,INVERSE
  6307.          text "Command: Blank Clear Delete Edit Format Global Insert Move "
  6308.          text "         Print Replicate Storage Titles Version Window Repeat(-
  6309.          select  1,10,5,B
  6310.          select  1,16,5,C
  6311.          select  1,22,6,DELETE
  6312.          select  1,29,4,E
  6313.          select  1,34,6,FORMAT
  6314.          select  1,41,6,GLOBAL
  6315.          select  1,48,6,INSERT
  6316.          select  1,55,4,M
  6317.          select  2,10,5,PRINT
  6318.          select  2,16,9,R
  6319.          select  2,26,7,STORAGE
  6320.          select  2,34,6,TITLE
  6321.          select  2,41,7,V
  6322.          select  2,49,6,WINDOW
  6323.          select  2,56,9,REPEAT
  6324.          pend
  6325.  B:      TYPE "/b"
  6326.  C:      TYPE "/c"
  6327.  E:      TYPE "/e"
  6328.  M:      TYPE "/m"
  6329.  R:      TYPE "/r"
  6330.  V:      TYPE "/v"
  6331.  REPEAT:   TYPE "/-"
  6332.  
  6333.  DELETE: popup   2,1,INVERSE
  6334.          text "Delete: Row Column                                "
  6335.          select  1,9,3,DR
  6336.          select  1,13,6,DC
  6337.          pend
  6338.  DR:     TYPE "/dr"
  6339.  DC:     TYPE "/dc"
  6340.  
  6341.  FORMAT: popup   2,1,INVERSE
  6342.          text "Format: Default General Integer Left Right Dollar($) Graph(*) "
  6343.          select  1,9,7,FD
  6344.          select  1,17,7,FG
  6345.          select  1,25,7,FI
  6346.          select  1,33,4,FL
  6347.          select  1,38,5,FR
  6348.          select  1,44,9,FDOLLAR
  6349.          select  1,54,8,FGRAPH
  6350.          pend
  6351.  FD:     TYPE "/fd"
  6352.  FG:     TYPE "/fg"
  6353.  FI:     TYPE "/fi"
  6354.  FL:     TYPE "/fl"
  6355.  FR:     TYPE "/fr"
  6356.  FDOLLAR:        TYPE "/f$"
  6357.  FGRAPH: TYPE "/f*"
  6358.  
  6359.  GLOBAL: popup   2,1,INVERSE
  6360.          text "Global: Column Order Recalc Format                "
  6361.          select  1,9,6,GC
  6362.          select  1,16,5,ORDER
  6363.          select  1,22,6,RECALC
  6364.          select  1,29,6,FORMAT2
  6365.          pend
  6366.  GC:     TYPE "/gc"
  6367.  
  6368.  ORDER:  popup   2,1,INVERSE
  6369.          text "Reeval Order: Row Column                          "
  6370.          select  1,15,3,GOR
  6371.          select  1,19,6,GOC
  6372.          pend
  6373.  GOR:    TYPE "/gor"
  6374.  GOC:    TYPE "/goc"
  6375.  
  6376.  RECALC: popup   2,1,INVERSE
  6377.          text "Recalc: Auto Manual                               "
  6378.          select  1,9,4,GRA
  6379.          select  1,14,6,GRM
  6380.          pend
  6381.  GRA:    TYPE "/gra"
  6382.  GRM:    TYPE "/grm"
  6383.  
  6384.  FORMAT2:        popup   2,1,INVERSE
  6385.          text "Format: Default General Integer Left Right Dollar($) Graph(*) "
  6386.          select  1,9,7,GFD
  6387.          select  1,17,7,GFG
  6388.          select  1,25,7,GFI
  6389.          select  1,33,4,GFL
  6390.          select  1,38,5,GFR
  6391.          select  1,44,9,GFDOLLAR
  6392.          select  1,54,8,GFGRAPH
  6393.          pend
  6394.  GFD:    TYPE "/gfd"
  6395.  GFG:    TYPE "/gfg"
  6396.  GFI:    TYPE "/gfi"
  6397.  GFL:    TYPE "/gfl"
  6398.  GFR:    TYPE "/gfr"
  6399.  GFDOLLAR:       TYPE "/gf$"
  6400.  GFGRAPH:        TYPE "/gf*"
  6401.  
  6402.  INSERT: popup   2,1,INVERSE
  6403.          text "Insert: Row Column                                "
  6404.          select  1,9,3,IR
  6405.          select  1,13,6,IC
  6406.          pend
  6407.  IR:     TYPE "/ir"
  6408.  IC:     TYPE "/ic"
  6409.  
  6410.  PRINT:  popup   2,1,INVERSE
  6411.          text "Print: Printer File                               "
  6412.          select  1,8,7,PP
  6413.          select  1,16,4,PF
  6414.          pend
  6415.  PP:     TYPE "/pp"
  6416.  PF:     TYPE "/pf"
  6417.  
  6418.  STORAGE:        popup   2,1,INVERSE
  6419.          text "Storage: Load Save Delete Quit Data(#)            "
  6420.          select  1,10,4,SL
  6421.          select  1,15,4,SS
  6422.          select  1,20,6,SD
  6423.          select  1,27,4,SQ
  6424.          select  1,32,7,DATA
  6425.          pend
  6426.  SL:     TYPE "/sl"
  6427.  SS:     TYPE "/ss"
  6428.  SD:     TYPE "/sd"
  6429.  SQ:     TYPE "/sq"
  6430.  
  6431.  DATA:   popup   2,1,INVERSE
  6432.          text "Data: Save Load                                   "
  6433.          select  1,7,4,SPOUNDS
  6434.          select  1,12,4,SPOUNDL
  6435.          pend
  6436.  SPOUNDS:        TYPE "/s#s"
  6437.  SPOUNDL:        TYPE "/s#l"
  6438.  
  6439.  TITLE:  popup   2,1,INVERSE
  6440.          text "Titles: Horizontal Vertical Both None             "
  6441.          select  1,9,10,TH
  6442.          select  1,20,8,TV
  6443.          select  1,29,4,TB
  6444.          select  1,34,4,TN
  6445.          pend
  6446.  TH:     TYPE "/th"
  6447.  TV:     TYPE "/tv"
  6448.  TB:     TYPE "/tb"
  6449.  TN:     TYPE "/tn"
  6450.  
  6451.  WINDOW: popup   2,1,INVERSE
  6452.          text "Window: Horizontal Vertical 1Window Synch Unsynch "
  6453.          select  1,9,10,WH
  6454.          select  1,20,8,WV
  6455.          select  1,29,7,W1
  6456.          select  1,37,5,WS
  6457.          select  1,43,7,WU
  6458.          pend
  6459.  WH:     TYPE "/wh"
  6460.  WV:     TYPE "/wv"
  6461.  W1:     TYPE "/w1"
  6462.  WS:     TYPE "/ws"
  6463.  WU:     TYPE "/wu"
  6464.  
  6465.  LABEL:  popup   2,1,INVERSE
  6466.          text "Label: Execute Edit "
  6467.          select  1,8,7,RETURN
  6468.          select  1,16,4,CTRLE
  6469.          pend
  6470.  
  6471.  VALUE:  popup   2,1,INVERSE
  6472.          text "Value: Enter Period Edit Recalc Absolute "
  6473.          select  1,8,5,RETURN
  6474.          select  1,14,6,PERIOD
  6475.          select  1,21,4,CTRLE
  6476.          select  1,26,6,BANG
  6477.          select  1,33,8,POUND
  6478.          pend
  6479.  
  6480.  
  6481.  ;------------------------------KEYS------------------------------------------
  6482.  
  6483.  NUL:    NOTHING
  6484.  CTRLC:  TYPE 3
  6485.  CTRLE:  TYPE 5
  6486.  BKSP:           TYPE 8
  6487.  RETURN:         TYPE 13
  6488.  ESCAPE:         TYPE 27
  6489.  BANG:   TYPE "!"
  6490.  QUOTE:  TYPE 34
  6491.  POUND:  TYPE "#"
  6492.  PLUSBKSP:       TYPE "+",8
  6493.  PERIOD:         TYPE "."
  6494.  SEMICOLON:      TYPE ";"
  6495.  GREAT:  TYPE ">"
  6496.  NO:     TYPE "n"
  6497.  REL:    TYPE "r"
  6498.  YES:    TYPE "y"
  6499.  HOME:           TYPE 0,71
  6500.  UP:             TYPE 0,72
  6501.  LEFT:           TYPE 0,75
  6502.  RIGHT:          TYPE 0,77
  6503.  DOWN:           TYPE 0,80
  6504.  
  6505.  
  6506.  \SAMPCODE\MOUSE\SOURCES\WS.DEF
  6507.  
  6508.  ;
  6509.  ;       Wordstar pop-up mouse menus
  6510.  ;
  6511.  
  6512.  ;       Set up initial labels for mouse commands
  6513.  
  6514.          begin leftb,rightb,bothb,mousel,mouser,mouseu,moused,16,40
  6515.  
  6516.  ;       -------------------- Left Button ---------------------------
  6517.  
  6518.  ;       Display edit/block menu if in edit mode else display no-file menu
  6519.  
  6520.  leftb:  match 1,12,,"e",imen,chk33  ;Check for e in editing no file
  6521.  chk33:  match 1,12,,"n",imen,chkl   ;Check for n in not editing (V 3.3)
  6522.  
  6523.  chkl:   match 1,11,,":",emen,nothing ;Check for : after drive letter
  6524.  
  6525.  
  6526.  ;       -------------------- Right button ------------------------
  6527.  
  6528.  ;       If in edit mode execute cursor movement menu else nothing
  6529.  
  6530.  rightb: match 1,11,,":",movmen,nothing    ;Check state of WS
  6531.  
  6532.  ;       --------------------- Both buttons ------------------------
  6533.  
  6534.  ;       If in edit mode execute edit/file menu, if not in edit
  6535.  ;       mode then type escape.
  6536.  
  6537.  bothb:  match 1,11,,":",emen2,keyesc    ;Both buttons - Check state
  6538.  
  6539.  ;       -------------------- Mouse left -----------------------
  6540.  
  6541.  mousel: match 1,11,,":",lchkctrl,nothing          ;Edit mode?
  6542.  lchkctrl: match 1,1,,"^",nothing,keyctrls               ;Yes - Move left
  6543.  
  6544.  ;       ------------------- Mouse right -----------------------
  6545.  
  6546.  mouser: match 1,11,,":",rchkctrl,nothing          ;Edit mode?
  6547.  rchkctrl: match 1,1,,"^",nothing,keyctrld               ;Yes - Move right
  6548.  
  6549.  ;       --------------------- Mouse up -----------------------
  6550.  
  6551.  mouseu: match 1,11,,":",uchkctrl,nothing          ;Edit mode?
  6552.  uchkctrl: match 1,1,,"^",nothing,keyctrle         ;Yes - Move up
  6553.  
  6554.  ;       ------------------- Mouse down -----------------------
  6555.  
  6556.  moused: match 1,11,,":",dchkctrl,nothing          ;Edit mode?
  6557.  dchkctrl: match 1,1,,"^",nothing,keyctrlx               ;Yes - Move down
  6558.  
  6559.  ;       Initial menu displayed when left button pressed
  6560.  
  6561.  imen:   popup 2,1
  6562.          text "╔══════════════════ < < <  N O - F I L E   M E N U  > > > ═════
  6563.          text "║ Cancel menu    Change drive   Print a file   Rename a file  R
  6564.          text "║ Open document  Toggle file dir               Delete a file  R
  6565.          text "║ Open non-doc   Set help level Exit to DOS    Copy a file    R
  6566.          text "╚══════════════════════════════════════════════════════════════
  6567.          select 2,3,15
  6568.          select 3,3,15,keyd
  6569.          select 4,3,15,keyn
  6570.          select 2,18,15,keyl
  6571.          select 3,18,15,keyf
  6572.          select 4,18,15,hlpmen
  6573.          select 2,33,15,keyp
  6574.  ;
  6575.          select 4,33,15,keyx
  6576.          select 2,48,15,keye
  6577.          select 3,48,15,keyy
  6578.          select 4,48,15,keyo
  6579.          select 2,63,14,keyr
  6580.          select 3,63,14,keys
  6581.          select 4,63,14,keym
  6582.          pend
  6583.  
  6584.  ;       Set help level
  6585.  
  6586.  hlpmen: popup 2,1
  6587.          text "╔═════ SET HELP LEVEL ════╗"
  6588.          text "║       Cancel menu       ║"
  6589.          text "║   All menus displayed   ║"
  6590.          text "║  Main menu suppressed   ║"
  6591.          text "║ Prefix menus suppressed ║"
  6592.          text "║  All menus suppressed   ║"
  6593.          text "╚═════════════════════════╝"
  6594.          select 2,3,23
  6595.          select 3,3,23,keyh3
  6596.          select 4,3,23,keyh2
  6597.          select 5,3,23,keyh1
  6598.          select 6,3,23,keyh0
  6599.          pend
  6600.  
  6601.  ; Edit/Block menu - selected by pressing left button in edit mode
  6602.  
  6603.  emen:   popup 2,1
  6604.          text "╔══════ EDIT / BLOCK MENU ══════╗"
  6605.          text "║ Cancel Menu      Begin block  ║"
  6606.          text "║ Reform           End block    ║"
  6607.          text "║ Center text      Copy block   ║"
  6608.          text "║ Toggle insert    Move block   ║"
  6609.          text "║ Find text        Delete block ║"
  6610.          text "║ Find/Replace     Write block  ║"
  6611.          text "║ Find/Replace agn Column block ║"
  6612.          text "╚═══════════════════════════════╝"
  6613.          select 2,3,17
  6614.          select 3,3,17,keyctrlb
  6615.          select 4,3,17,keyctrloc
  6616.          select 5,3,17,keyctrlv
  6617.          select 6,3,17,keyctrlqf
  6618.          select 7,3,17,keyctrlqa
  6619.          select 8,3,17,keyctrll
  6620.          select 2,20,12,keyctrlkb
  6621.          select 3,20,12,keyctrlkk
  6622.          select 4,20,12,keyctrlkc
  6623.          select 5,20,12,keyctrlkv
  6624.          select 6,20,12,keyctrlky
  6625.          select 7,20,12,keyctrlkw
  6626.          select 8,20,12,keyctrlkn
  6627.          pend
  6628.  
  6629.  ; Edit / File menu displayed when both buttons pressed in edit mode
  6630.  
  6631.  emen2:  popup 2,1
  6632.          text "╔════════ EDIT / FILE MENU ════════╗"
  6633.          text "║ Cancel menu    Print/Format menu ║"
  6634.          text "║ Save & Resume  Margins/Tabs menu ║"
  6635.          text "║ Save & Done    Toggles menu      ║"
  6636.          text "║ Save & Exit    File command menu ║"
  6637.          text "║ Abandon file   Help menu         ║"
  6638.          text "╚══════════════════════════════════╝"
  6639.          select 2,3,15
  6640.          select 3,3,15,keyctrlks
  6641.          select 4,3,15,keyctrlkd
  6642.          select 5,3,15,keyctrlkx
  6643.          select 6,3,15,keyctrlkq
  6644.          select 2,18,17,frmtmen
  6645.          select 3,18,17,mtmen
  6646.          select 4,18,17,togmen
  6647.          select 5,18,17,filmen
  6648.          select 6,18,17,hlpmen2
  6649.          pend
  6650.  
  6651.  ; Print/Format menu selected from Edit menu
  6652.  
  6653.  frmtmen: popup 2,1
  6654.          text "╔═════════════ PRINT FORMAT MENU ═══════════════╗"
  6655.          text "║ Cancel menu    Subscript      Print pause     ║"
  6656.          text "║ Bold           Superscript    Overprint line  ║"
  6657.          text "║ Double strike  Strikeout      Nonbreak space  ║"
  6658.          text "║ Underscore     Phantom space  Standard pitch  ║"
  6659.          text "║ Overprint char Phantom Rubout Alternate pitch ║"
  6660.          text "╚═══════════════════════════════════════════════╝"
  6661.          select 2,3,15
  6662.          select 3,3,15,keyctrlpb
  6663.          select 4,3,15,keyctrlpd
  6664.          select 5,3,15,keyctrlps
  6665.          select 6,3,15,keyctrlph
  6666.          select 2,18,15,keyctrlpv
  6667.          select 3,18,15,keyctrlpt
  6668.          select 4,18,15,keyctrlpx
  6669.          select 5,18,15,keyctrlpf
  6670.          select 6,18,15,keyctrlpg
  6671.          select 2,33,15,keyctrlpc
  6672.          select 3,33,15,keyctrlprk
  6673.          select 4,33,15,keyctrlpo
  6674.          select 5,33,15,keyctrlpn
  6675.          select 6,33,15,keyctrlpa
  6676.          pend
  6677.  
  6678.  ;       Margins/Tabs menu selected from main edit menu
  6679.  
  6680.  mtmen:  popup 2,1
  6681.          text "╔══════════ MARGINS / TABS MENU ════════════╗"
  6682.          text "║ Cancel menu        Set a tab stop         ║"
  6683.          text "║ Set left margin    Set tab stop at cursor ║"
  6684.          text "║ Set right margin   Set a paragraph tab    ║"
  6685.          text "║ Release margins    Clear a tab stop       ║"
  6686.          text "╚═══════════════════════════════════════════╝"
  6687.          select 2,3,19
  6688.          select 3,3,19,keyctrlol
  6689.          select 4,3,19,keyctrlor
  6690.          select 5,3,19,keyctrlox
  6691.          select 2,22,22,keyctrloi
  6692.          select 3,22,22,keyctrloie
  6693.          select 4,22,22,keyctrlog
  6694.          select 5,22,22,keyctrlon
  6695.          pend
  6696.  
  6697.  ; Help menu selected from Edit/File menu
  6698.  
  6699.  hlpmen2: popup 2,1
  6700.          text "╔═════════════ HELP MENU ══════════════╗"
  6701.          text "║ Cancel menu           Mouse help     ║"
  6702.          text "║ Set help level        Status line    ║"
  6703.          text "║ Paragraph reform      Ruler line     ║"
  6704.          text "║ Flags in right column Margins & tabs ║"
  6705.          text "║ Dot commands          Place markers  ║"
  6706.          text "║ Index of commands     Moving text    ║"
  6707.          text "╚══════════════════════════════════════╝"
  6708.          select 2,3,22
  6709.          select 3,3,22,chlpmen
  6710.          select 4,3,22,keyctrljb
  6711.          select 5,3,22,keyctrljf
  6712.          select 6,3,22,keyctrljd
  6713.          select 7,3,22,keyctrlji
  6714.          select 2,25,14,mousehlp
  6715.          select 3,25,14,keyctrljs
  6716.          select 4,25,14,keyctrljr
  6717.          select 5,25,14,keyctrljm
  6718.          select 6,25,14,keyctrljp
  6719.          select 7,25,14,keyctrljv
  6720.          pend
  6721.  
  6722.  ; Set help level from edit mode - ctrlj then h0,h1,h2,h3
  6723.  
  6724.  chlpmen: execute keyctrlj,hlpmen
  6725.  
  6726.  ;       Mouse help
  6727.  
  6728.  mousehlp: popup 2,1
  6729.          text "╔════════════════ MOUSE  HELP ══════════════════╗"
  6730.          text "║                                               ║"
  6731.          text "║ Left button  - Displays Edit/Block menu       ║"
  6732.          text "║ Right button - Displays Cursor movement menu  ║"
  6733.          text "║ Both buttons - Displays Edit/File menu        ║"
  6734.          text "║                                               ║"
  6735.          text "║ Moving the mouse up,down,left, or right will  ║"
  6736.          text "║ cause the cursor to move in that direction.   ║"
  6737.          text "║                                               ║"
  6738.          text "╚═══════════════════════════════════════════════╝"
  6739.          select 1,19,11
  6740.          pend
  6741.  
  6742.  ; File command menu selected from main edit menu
  6743.  
  6744.  filmen: popup 2,1
  6745.          text "╔ FILE COMMANDS ╗"
  6746.          text "║  Cancel menu  ║"
  6747.          text "║  Read a file  ║"
  6748.          text "║  Copy a file  ║"
  6749.          text "║ Delete a file ║"
  6750.          text "║ Rename a file ║"
  6751.          text "║  Print a file ║"
  6752.          text "╚═══════════════╝"
  6753.          select 2,3,13
  6754.          select 3,3,13,keyctrlkr
  6755.          select 4,3,13,keyctrlko
  6756.          select 5,3,13,keyctrlkj
  6757.          select 6,3,13,keyctrlke
  6758.          select 7,3,13,keyctrlkp
  6759.          pend
  6760.  
  6761.  ; Toggle menu selected from main edit menu
  6762.  
  6763.  togmen: popup 2,1
  6764.          text "╔════════════ TOGGLES MENU ══════════════╗"
  6765.          text "║ Cancel menu       Toggle soft hyphen   ║"
  6766.          text "║ Toggle ruler line Toggle vari-Tabs     ║"
  6767.          text "║ Toggle word wrap  Toggle print display ║"
  6768.          text "║ Toggle justify    Toggle auto page brk ║"
  6769.          text "╚════════════════════════════════════════╝"
  6770.          select 2,3,18
  6771.          select 3,3,18,keyctrlot
  6772.          select 4,3,18,keyctrlow
  6773.          select 5,3,18,keyctrloj
  6774.          select 2,21,20,keyctrloe
  6775.          select 3,21,20,keyctrlov
  6776.          select 4,21,20,keyctrlod
  6777.          select 5,21,20,keyctrlop
  6778.          pend
  6779.  
  6780.  ; Cursor movement menu displayed when right button pressed in edit mode
  6781.  
  6782.  movmen: popup 2,1
  6783.          text "╔═══════ CURSOR MOVEMENT ═══════╗"
  6784.          text "║ Cancel menu    Top of screen  ║"
  6785.          text "║ Screen up      Bottom of scrn ║"
  6786.          text "║ Screen down    Start of file  ║"
  6787.          text "║ Previous place End of file    ║"
  6788.          text "╚═══════════════════════════════╝"
  6789.          select 2,3,15
  6790.          select 3,3,15,keyctrlr
  6791.          select 4,3,15,keyctrlc
  6792.          select 5,3,15,keyctrlqp
  6793.          select 2,18,15,keyctrlqe
  6794.          select 3,18,15,keyctrlqx
  6795.          select 4,18,15,keyctrlqr
  6796.          select 5,18,15,keyctrlqc
  6797.          pend
  6798.  
  6799.  ;               --- Key Commands ---
  6800.  
  6801.  keyctrls: type 19                       ;Ctrl S - Left char
  6802.  keyctrld: type 4                        ;Ctrl D - Right char
  6803.  keyctrle: type 5                        ;Ctrl E - Up char
  6804.  keyctrlx: type 24                       ;Ctrl X - Down char
  6805.  keyctrlr: type 18                       ;Ctrl R - Screen down
  6806.  keyctrlj: type 10
  6807.  keyctrlk: type 11
  6808.  keyctrlkb: type 11,"B"
  6809.  keyctrlkc: type 11,"C"
  6810.  keyctrlkd: type 11,"D"
  6811.  keyctrlkk: type 11,"K"
  6812.  keyctrlkn: type 11,"N"
  6813.  keyctrlkp: type 11,"P"
  6814.  keyctrlkx: type 11,"X"
  6815.  keyctrlks: type 11,"S"
  6816.  keyctrlkq: type 11,"Q"
  6817.  keyctrlkv: type 11,"V"
  6818.  keyctrlkw: type 11,"W"
  6819.  keyctrlky: type 11,"Y"
  6820.  keyctrlkr: type 11,"R"
  6821.  keyctrlko: type 11,"O"
  6822.  keyctrlkj: type 11,"J"
  6823.  keyctrlke: type 11,"E"
  6824.  keyctrll:  type 12
  6825.  keyctrlb: type 2
  6826.  keyctrlc: type 3
  6827.  keyctrlg: type 7
  6828.  keyctrlp: type 16
  6829.  keyctrlq: type 17
  6830.  keyctrlo: type 15
  6831.  keyctrlv: type 22
  6832.  keyctrljb: type 10,"B"
  6833.  keyctrljf: type 10,"F"
  6834.  keyctrljd: type 10,"D"
  6835.  keyctrlji: type 10,"I"
  6836.  keyctrljs: type 10,"S"
  6837.  keyctrljr: type 10,"R"
  6838.  keyctrljp: type 10,"P"
  6839.  keyctrljm: type 10,"M"
  6840.  keyctrljv: type 10,"V"
  6841.  keyctrloc: type 15,"C"
  6842.  keyctrlox: type 15,"X"
  6843.  keyctrlol: type 15,"L"
  6844.  keyctrlor: type 15,"R"
  6845.  keyctrloi: type 15,"I"
  6846.  keyctrloie: type 15,"I",27
  6847.  keyctrlog: type 15,"G"
  6848.  keyctrlon: type 15,"N"
  6849.  keyctrlot: type 15,"T"
  6850.  keyctrlow: type 15,"W"
  6851.  keyctrloj: type 15,"J"
  6852.  keyctrloe: type 15,"E"
  6853.  keyctrlov: type 15,"V"
  6854.  keyctrlod: type 15,"D"
  6855.  keyctrlop: type 15,"P"
  6856.  keyctrlprk: type 16,13                          ;Ctrl K then return key
  6857.  keyctrlpa: type 16,"A"
  6858.  keyctrlpb: type 16,"B"
  6859.  keyctrlpc: type 16,"C"
  6860.  keyctrlpd: type 16,"D"
  6861.  keyctrlpf: type 16,"F"
  6862.  keyctrlpg: type 16,"G"
  6863.  keyctrlph: type 16,"H"
  6864.  keyctrlpn: type 16,"N"
  6865.  keyctrlpo: type 16,"O"
  6866.  keyctrlps: type 16,"S"
  6867.  keyctrlpt: type 16,"T"
  6868.  keyctrlpv: type 16,"V"
  6869.  keyctrlpx: type 16,"X"
  6870.  keyctrlqa: type 17,"A"
  6871.  keyctrlqe: type 17,"E"
  6872.  keyctrlqf: type 17,"F"
  6873.  keyctrlqr: type 17,"R"
  6874.  keyctrlqc: type 17,"C"
  6875.  keyctrlqk: type 17,"K"
  6876.  keyctrlqp: type 17,"P"
  6877.  keyctrlqq: type 17,"Q"
  6878.  keyctrlqx: type 17,"X"
  6879.  keyctrlqy: type 17,"Y"
  6880.  keyd:   type "D"                ;D - Open Document
  6881.  keye:   type "E"                ;E - Rename
  6882.  keyf:   type "F"                ;F - Toggle directory
  6883.  keyh:   type "H"                ;H - Help menu
  6884.  keyh0:  type "H0"               ;H - Set help level 0
  6885.  keyh1:  type "H1"               ;H - Set help level 1
  6886.  keyh2:  type "H2"               ;H - Set help level 2
  6887.  keyh3:  type "H3"               ;H - Set help level 3
  6888.  keyl:   type "L"                ;L - Change drive
  6889.  keym:   type "M"                ;M - Run mailmerge
  6890.  keyn:   type "N"                ;N - Open Non document
  6891.  keyo:   type "O"                ;O - Copy
  6892.  keyp:   type "P"                ;P - Print
  6893.  keyr:   type "R"                ;R - Run program
  6894.  keys:   type "S"                ;S - Run spellstar
  6895.  keyx:   type "X"                ;X - Exit
  6896.  keyy:   type "Y"                ;Y - Delete
  6897.  keyesc: type 27                 ;Escape
  6898.  
  6899.  NOTHING:        NOTHING
  6900.  
  6901.  ; The end
  6902.  
  6903.  \SAMPCODE\VIDEO
  6904.  \SAMPCODE\VIDEO\1
  6905.  \SAMPCODE\VIDEO\1\1_3.C
  6906.  
  6907.  /* Listing 1-3 */
  6908.  
  6909.  main( argc, argv )
  6910.  int     argc;
  6911.  char    **argv;
  6912.  {
  6913.          int     ModeNumber;
  6914.          void    SetVmode();
  6915.  
  6916.  
  6917.          if (argc != 2)                  /* verify command line syntax */
  6918.          {
  6919.            printf( "\nSyntax:  SETVMODE n\n" );
  6920.            exit( 1 );
  6921.          }
  6922.  
  6923.          sscanf( argv[1], "%x", &ModeNumber );   /* get desired mode number */
  6924.  
  6925.          SetVmode( ModeNumber );                 /* call ROM BIOS via INT 10h
  6926.  }
  6927.  
  6928.  \SAMPCODE\VIDEO\1\1_4.C
  6929.  
  6930.  /* Listing 1-4 */
  6931.  
  6932.  main()
  6933.  {
  6934.          int     GetVmode();
  6935.  
  6936.          return( GetVmode() );
  6937.  }
  6938.  
  6939.  \SAMPCODE\VIDEO\1\1_5.C
  6940.  
  6941.  /* Listing 1-5 */
  6942.  
  6943.  #include        "dos.h"
  6944.  
  6945.  main()
  6946.  {
  6947.          struct  BYTEREGS regs;          /* BYTEREGS defined in dos.h */
  6948.  
  6949.  
  6950.          regs.ah = 0x0F;                 /* AH=0x0F (ROM BIOS function number)
  6951.  
  6952.          int86( 0x10, ®s, ®s );    /* perform interrupt 10h */
  6953.  
  6954.          return( (int)regs.al );
  6955.  }
  6956.  
  6957.  \SAMPCODE\VIDEO\1\1_1.ASM
  6958.  
  6959.                  TITLE   'Listing 1-1'
  6960.                  NAME    SetVmode
  6961.                  PAGE    55,132
  6962.  
  6963.  ;
  6964.  ; Name:         SetVmode
  6965.  ;
  6966.  ; Function:     Call IBM PC ROM BIOS to set a video display mode.
  6967.  ;
  6968.  ; Caller:       Microsoft C:
  6969.  ;
  6970.  ;                       void SetVmode(n);
  6971.  ;
  6972.  ;                       int n;                  /* video mode */
  6973.  ;
  6974.  
  6975.  ARGn            EQU     byte ptr [bp+4] ; stack frame addressing
  6976.  
  6977.  EQUIP_FLAG      EQU     byte ptr ds:[10h] ; (in Video Display Data Area)
  6978.  
  6979.  CGAbits         EQU     00100000b       ; bits for EQUIP_FLAG
  6980.  MDAbits         EQU     00110000b
  6981.  
  6982.  _TEXT           SEGMENT byte public 'CODE'
  6983.                  ASSUME  cs:_TEXT
  6984.  
  6985.                  PUBLIC  _SetVmode
  6986.  _SetVmode       PROC    near
  6987.  
  6988.                  push    bp              ; preserve caller registers
  6989.                  mov     bp,sp
  6990.                  push    ds
  6991.  
  6992.                  mov     ax,40h
  6993.                  mov     ds,ax           ; DS -> Video Display Data Area
  6994.  
  6995.                  mov     bl,CGAbits      ; BL := bits indicating presence of C
  6996.  
  6997.                  mov     al,ARGn         ; AL := desired video mode number
  6998.  
  6999.                  mov     ah,al           ; test if desired mode is monochrome
  7000.                  and     ah,7
  7001.                  cmp     ah,7
  7002.                  jne     L01             ; jump if desired mode not 7 or 0Fh
  7003.  
  7004.                  mov     bl,MDAbits      ; BL := bits indicating presence of M
  7005.  
  7006.  L01:            and     EQUIP_FLAG,11001111b
  7007.                  or      EQUIP_FLAG,bl   ; set bits in EQUIP_FLAG
  7008.  
  7009.                  xor     ah,ah           ; AH := 0 (INT 10h function number)
  7010.  
  7011.                  push    bp
  7012.                  int     10h             ; call ROM BIOS to set the video mode
  7013.                  pop     bp
  7014.  
  7015.                  pop     ds              ; restore caller registers and return
  7016.                  mov     sp,bp
  7017.                  pop     bp
  7018.                  ret
  7019.  
  7020.  _SetVmode       ENDP
  7021.  
  7022.  _TEXT           ENDS
  7023.  
  7024.                  END
  7025.  
  7026.  \SAMPCODE\VIDEO\1\1_2.ASM
  7027.  
  7028.                  TITLE   'Listing 1-2'
  7029.                  NAME    GetVmode
  7030.                  PAGE    55,132
  7031.  
  7032.  ;
  7033.  ; Name:         GetVmode
  7034.  ;
  7035.  ; Function:     Call IBM PC ROM BIOS to set a video display mode.
  7036.  ;
  7037.  ; Caller:       Microsoft C:
  7038.  ;
  7039.  ;                       int     GetVmode();
  7040.  ;
  7041.  
  7042.  _TEXT           SEGMENT byte public 'CODE'
  7043.                  ASSUME  cs:_TEXT
  7044.  
  7045.                  PUBLIC  _GetVmode
  7046.  _GetVmode       PROC    near
  7047.  
  7048.                  push    bp              ; preserve caller registers
  7049.                  mov     bp,sp
  7050.  
  7051.                  mov     ah,0Fh          ; AH := 0Fh (INT 10h function number)
  7052.  
  7053.                  push    bp
  7054.                  int     10h             ; call ROM BIOS to get video mode num
  7055.                  pop     bp
  7056.  
  7057.                  xor     ah,ah           ; AX := video mode number
  7058.  
  7059.                  mov     sp,bp
  7060.                  pop     bp
  7061.                  ret
  7062.  
  7063.  _GetVmode       ENDP
  7064.  
  7065.  _TEXT           ENDS
  7066.  
  7067.                  END
  7068.  
  7069.  \SAMPCODE\VIDEO\10
  7070.  \SAMPCODE\VIDEO\10\10_15.C
  7071.  
  7072.  /* Listing 10-15 */
  7073.  
  7074.  #define Points          14      /* displayed scan lines per character */
  7075.  #define StartCharCode   0x80    /* first character code in "window" */
  7076.  #define CGenDefSize     32      /* (use 16 for Hercules) */
  7077.  
  7078.  char far *CRT_MODE = 0x00400049;        /* BIOS video mode number */
  7079.  int  far *CRT_COLS = 0x0040004A;        /* characters per row */
  7080.  
  7081.  char far *VideoBuffer;                  /* pointer to video buffer */
  7082.  char far *CharDefTable = 0xA0000000;    /* pointer to char def RAM */
  7083.                                          /* (use 0xB0004000 for Hercules) */
  7084.  main()
  7085.  {
  7086.          int     i;
  7087.          int     CharCode;
  7088.          int     CharOffset;
  7089.          int     CharScanLine;
  7090.          int     CharDefOffset;
  7091.          int     Row,Column;
  7092.  
  7093.  
  7094.          /* establish alphanumeric mode */
  7095.  
  7096.          if (*CRT_MODE == 7)             /* set video buffer pointer */
  7097.            VideoBuffer = 0xB0000000;
  7098.          else
  7099.            VideoBuffer = 0xB8000000;
  7100.  
  7101.          AlphaModeSet( 8, Points, 8 );
  7102.  
  7103.  
  7104.          /* establish a tiled graphics window in the upper left corner */
  7105.  
  7106.          CharCode = StartCharCode;
  7107.  
  7108.          for ( Row=0; Row<4; Row++ )
  7109.            for ( Column=0; Column< 32; Column++ )
  7110.            {
  7111.              CharOffset = (Row*(*CRT_COLS) + Column) * 2;
  7112.              VideoBuffer[CharOffset] = CharCode++;
  7113.            }
  7114.  
  7115.  
  7116.          /* clear the window */
  7117.  
  7118.          CGenModeSet();          /* make character generator RAM addressable *
  7119.  
  7120.          for (CharCode=StartCharCode; CharCode<256; CharCode++ )
  7121.            for ( CharScanLine=0; CharScanLine<Points; CharScanLine++ )
  7122.            {
  7123.              CharDefOffset = CharCode*CGenDefSize + CharScanLine;
  7124.              CharDefTable[CharDefOffset] = 0;
  7125.            }
  7126.  
  7127.  
  7128.          /* draw a few lines */
  7129.  
  7130.          for ( i=0; i<256; i++ )         /* horizontal lines */
  7131.          {
  7132.            SetPixel( i, 0 );
  7133.            SetPixel( i, 4*Points-1 );
  7134.          }
  7135.  
  7136.          for ( i=0; i<4*Points-1; i++ )  /* vertical lines */
  7137.          {
  7138.            SetPixel( 0, i );
  7139.            SetPixel( 255, i );
  7140.          }
  7141.  
  7142.          for( i=0; i<Points*4; i++ )     /* diagonal lines */
  7143.          {
  7144.            SetPixel( i, i );
  7145.            SetPixel( 255-i, i );
  7146.          }
  7147.  
  7148.          CGenModeClear();                /* restore alphanumeric mode */
  7149.  
  7150.  }
  7151.  
  7152.  SetPixel( x, y )
  7153.  int     x,y;            /* pixel coordinates */
  7154.  {
  7155.          int     CharCode;
  7156.          int     CharScanLine;
  7157.          int     BitMask;
  7158.          int     CharDefOffset;
  7159.  
  7160.  
  7161.          CharCode = StartCharCode + (y/Points)*32 + x/8;
  7162.          CharScanLine = y % Points;              /* y MOD Points */
  7163.          BitMask = 0x80 >> (x % 8);              /* 10000000b SHR (x MOD 8) */
  7164.  
  7165.          CharDefOffset = CharCode*CGenDefSize + CharScanLine;
  7166.          CharDefTable[CharDefOffset] |= BitMask; /* OR the pixel */
  7167.  }
  7168.  
  7169.  \SAMPCODE\VIDEO\10\10_16.C
  7170.  
  7171.  SetPixel( x, y )
  7172.  int     x,y;            /* pixel coordinates */
  7173.  {
  7174.          int     CharCode;
  7175.          int     CharScanLine;
  7176.          int     BitMask;
  7177.          int     CharDefOffset;
  7178.  
  7179.  
  7180.          /* the window is 32 characters across */
  7181.          CharCode = StartCharCode + (y/Points)*32 + x/8;
  7182.          CharScanLine = y % Points;              /* y MOD Points */
  7183.          BitMask = 0x80 >> (x % 8);              /* 10000000b SHR (x MOD 8) */
  7184.  
  7185.          CharDefOffset = CharCode*2 + CharScanLine*512 + 1;
  7186.          CharDefTable[CharDefOffset] |= BitMask; /* OR the pixel */
  7187.  }
  7188.  
  7189.  \SAMPCODE\VIDEO\10\10_12.ASM
  7190.  
  7191.                  TITLE   'Listing 10-12'
  7192.                  NAME    AlphaModeSet
  7193.                  PAGE    55,132
  7194.  
  7195.  ;
  7196.  ; Name:         AlphaModeSet
  7197.  ;
  7198.  ;               Program the CRTC in 80-column EGA alphanumeric modes
  7199.  ;
  7200.  ; Caller:       Microsoft C:
  7201.  ;
  7202.  ;                       void AlphaModeSet(w,h,c);
  7203.  ;
  7204.  ;                       int     w;      /* width of character matrix */
  7205.  ;                       int     h;      /* height of character matrix */
  7206.  ;                       int     c;      /* character code size */
  7207.  ;
  7208.  
  7209.  ARGw            EQU     byte ptr [bp+4]         ; must be 8 or 9 pixels wide
  7210.  ARGh            EQU     byte ptr [bp+6]         ; must be 2-32 pixels high
  7211.  ARGc            EQU     byte ptr [bp+8]         ; must be 8 or 9 bits
  7212.  
  7213.  CRT_MODE        EQU     49h             ; addresses in video BIOS data area
  7214.  CRT_COLS        EQU     4Ah
  7215.  ADDR_6845       EQU     63h
  7216.  
  7217.  DGROUP          GROUP   _DATA
  7218.  
  7219.  _TEXT           SEGMENT byte public 'CODE'
  7220.                  ASSUME  cs:_TEXT,ds:DGROUP
  7221.  
  7222.                  PUBLIC  _AlphaModeSet
  7223.  _AlphaModeSet   PROC    near
  7224.  
  7225.                  push    bp              ; preserve caller registers
  7226.                  mov     bp,sp
  7227.                  push    si
  7228.  
  7229.  ; Program the CRTC
  7230.  
  7231.                  mov     bx,40h
  7232.                  mov     es,bx           ; ES := video BIOS data segment
  7233.  
  7234.                  mov     bl,ARGw         ; BL := character width
  7235.                  mov     bh,ARGh         ; BH := character height
  7236.                  call    SetCRTC
  7237.  
  7238.  ; Program the Sequencer and Attribute Controller for 8 or 9 dots per characte
  7239.  
  7240.                  mov     dx,3C4h
  7241.                  mov     ax,0100h        ; AH bit 1 := 0 (synchronous reset)
  7242.                                          ; AL := 0 (Reset register number)
  7243.                  cli                     ; disable interrupts
  7244.                  out     dx,ax           ; Sequencer synchronous reset
  7245.  
  7246.                  mov     bx,1            ; BH,BL := values for 8-wide chars:
  7247.                                          ;  BH := 0 (value for Horiz Pel Pan)
  7248.                                          ;  BL := 1 (value for Clocking Mode)
  7249.                  cmp     ARGw,8
  7250.                  je      L01             ; jump if 8-wide characters
  7251.  
  7252.                  mov     bx,0800h        ; BH,BL := values for 9-wide characte
  7253.  
  7254.  L01:            mov     ah,bl           ; AH := value for Clocking Mode reg
  7255.                  mov     al,1            ; AL := Clocking Mode reg number
  7256.                  out     dx,ax           ; program the Sequencer
  7257.  
  7258.                  mov     ax,0300h        ; AH := 3 (disable reset)
  7259.                                          ; AL := 0 (Sequencer register number)
  7260.                  out     dx,ax           ; disable Sequencer reset
  7261.                  sti                     ; enable interrupts
  7262.  
  7263.                  mov     bl,13h          ; BL := Horizontal Pel Pan reg number
  7264.                  mov     ax,1000h        ; AH := 10H (INT 10H function number)
  7265.                                          ; AL := 0 (set specified register)
  7266.                  int     10h             ; program Attribute Controller
  7267.  
  7268.  ; Program the Attribute Controller for 8- or 9-bit character codes
  7269.  
  7270.                  mov     ax,1000h        ; AH := 10H (INT 10H function number)
  7271.                                          ; AL := 0 (set specified register)
  7272.                  mov     bx,0F12h        ; BH := 0FH (Color Plane Enable value
  7273.                                          ; BL := 12H (Color Plane Enable reg #
  7274.                  cmp     ARGc,8
  7275.                  je      L02             ; jump if 8-bit character codes
  7276.  
  7277.                  mov     bh,7            ; BH bit 3 := 0 (ignore bit 3 of all
  7278.                                          ;  attributes)
  7279.  L02:            int     10h             ; update Color Plane Enable register
  7280.  
  7281.  ; update video BIOS data area
  7282.  
  7283.                  cmp     byte ptr es:[CRT_MODE],7
  7284.                  jne     L03             ; jump if not monochrome mode
  7285.  
  7286.                  mov     ax,720          ; AX := displayed pixels per row
  7287.                  div     ARGw            ; AL := displayed character columns
  7288.                  mov     es:[CRT_COLS],al
  7289.  
  7290.  L03:            pop     si
  7291.                  pop     bp
  7292.                  ret
  7293.  
  7294.  _AlphaModeSet   ENDP
  7295.  
  7296.  
  7297.  SetCRTC         PROC    near            ; Caller:       BH = character height
  7298.                                          ;               BL = character width
  7299.  
  7300.                  push    dx
  7301.                  mov     dx,es:[ADDR_6845]  ; CRTC I/O port
  7302.  
  7303.  ; establish CRTC vertical timing and cursor position in character matrix
  7304.  
  7305.                  push    bx              ; preserve height and width
  7306.                  mov     ax,1110h        ; AH := 11H (INT 10H function number)
  7307.                                          ; AL := 0 (user alpha load)
  7308.                  xor     cx,cx           ; CX := 0 (store no characters)
  7309.                  int     10h             ; call BIOS to program CRTC for
  7310.                                          ;  vertical size of characters
  7311.  
  7312.                  pop     ax              ; AH := character height
  7313.                  push    ax              ; preserve height and width
  7314.                  sub     ah,2            ; AH := starting scan line for cursor
  7315.                  mov     al,0Ah          ; AL := 0AH (Cursor Start reg number)
  7316.                  out     dx,ax           ; update CRTC Cursor Start register
  7317.  
  7318.                  mov     ax,000Bh        ; AH := 0 (Cursor End value)
  7319.                                          ; AL := 0BH (Cursor End reg number)
  7320.                  out     dx,ax           ; update CRTC Cursor End register
  7321.  
  7322.  ; establish CRTC horizontal timing
  7323.  
  7324.                  pop     bx              ; BX := character height and width
  7325.                  cmp     byte ptr es:[CRT_MODE],7
  7326.                  jne     L10             ; exit if not monochrome mode
  7327.  
  7328.                  xor     bh,bh           ; BX := character width
  7329.                  sub     bl,8            ; BX := 0 or 1
  7330.                  neg     bx              ; BX := 0 or 0FFFFH
  7331.                  and     bx,14           ; BX := 0 or 14 (offset into table)
  7332.                  mov     si,bx           ; SI := offset into table
  7333.  
  7334.                  add     si,offset DGROUP:HorizParms     ; DS:SI -> parameters
  7335.                  call    UpdateCRTC
  7336.  
  7337.  L10:            pop     dx
  7338.                  ret
  7339.  
  7340.  SetCRTC         ENDP
  7341.  
  7342.  
  7343.  UpdateCRTC      PROC    near            ; Caller:       DX = CRTC address por
  7344.                                          ;               DS:SI -> parameters
  7345.                                          ; Destroys:     AX,CX
  7346.  
  7347.                  mov     cx,7            ; CX := number of registers to update
  7348.  
  7349.  L20:            lodsw                   ; AH := data for CRTC register in AL
  7350.                  out     dx,ax           ; update the register
  7351.                  loop    L20
  7352.  
  7353.                  ret
  7354.  
  7355.  UpdateCRTC      ENDP
  7356.  
  7357.  _TEXT           ENDS
  7358.  
  7359.  
  7360.  _DATA           SEGMENT word public 'DATA'
  7361.  
  7362.  HorizParms      DW      6C00h,5901h,6002h,2403h,5B04h,6A05h,2D13h  ; 8-wide
  7363.                  DW      6000h,4F01h,5602h,3A03h,5104h,6005h,2813h  ; 9-wide
  7364.  
  7365.  _DATA           ENDS
  7366.  
  7367.                  END
  7368.  
  7369.  \SAMPCODE\VIDEO\10\10_13.ASM
  7370.  
  7371.                  TITLE   'Listing 10-13'
  7372.                  NAME    AlphaModeSet
  7373.                  PAGE    55,132
  7374.  
  7375.  ;
  7376.  ; Name:         AlphaModeSet
  7377.  ;
  7378.  ;               Program the CRTC in 80-column VGA alphanumeric modes
  7379.  ;
  7380.  ; Caller:       Microsoft C:
  7381.  ;
  7382.  ;                       void AlphaModeSet(w,h,c);
  7383.  ;
  7384.  ;                       int     w;      /* width of character matrix */
  7385.  ;                       int     h;      /* height of character matrix */
  7386.  ;                       int     c;      /* character code size */
  7387.  ;
  7388.  
  7389.  ARGw            EQU     byte ptr [bp+4]         ; must be 8 or 9 pixels wide
  7390.  ARGh            EQU     byte ptr [bp+6]         ; must be 2-32 pixels high
  7391.  ARGc            EQU     byte ptr [bp+8]         ; must be 8 or 9 bits
  7392.  
  7393.  CRT_COLS        EQU     4Ah             ; addresses in video BIOS data area
  7394.  ADDR_6845       EQU     63h
  7395.  
  7396.  DGROUP          GROUP   _DATA
  7397.  
  7398.  _TEXT           SEGMENT byte public 'CODE'
  7399.                  ASSUME  cs:_TEXT,ds:DGROUP
  7400.  
  7401.                  PUBLIC  _AlphaModeSet
  7402.  _AlphaModeSet   PROC    near
  7403.  
  7404.                  push    bp              ; preserve caller registers
  7405.                  mov     bp,sp
  7406.                  push    si
  7407.  
  7408.  ; Program the CRTC
  7409.  
  7410.                  mov     bx,40h
  7411.                  mov     es,bx           ; ES := video BIOS data segment
  7412.  
  7413.                  mov     bl,ARGw         ; BL := character width
  7414.                  mov     bh,ARGh         ; BH := character height
  7415.                  call    SetCRTC
  7416.  
  7417.  ; Program the Sequencer and Attribute Controller for 8 or 9 dots per characte
  7418.  
  7419.                  mov     dx,3C4h
  7420.                  mov     ax,0100h        ; AH bit 1 := 0 (synchronous reset)
  7421.                                          ; AL := 0 (Reset register number)
  7422.                  cli                     ; disable interrupts
  7423.                  out     dx,ax           ; Sequencer synchronous reset
  7424.  
  7425.                  mov     bx,1            ; BH,BL := values for 8-wide chars:
  7426.                                          ;  BH := 0 (value for Horiz Pel Pan)
  7427.                                          ;  BL := 1 (value for Clocking Mode)
  7428.                  cmp     ARGw,8
  7429.                  je      L01             ; jump if 8-wide characters
  7430.  
  7431.                  mov     bx,0800h        ; BH,BL := values for 9-wide characte
  7432.  
  7433.  L01:            mov     ah,bl           ; AH := value for Clocking Mode reg
  7434.                  mov     al,1            ; AL := Clocking Mode reg number
  7435.                  out     dx,ax           ; program the Sequencer
  7436.  
  7437.                  mov     ax,0300h        ; AH := 3 (disable reset)
  7438.                                          ; AL := 0 (Sequencer register number)
  7439.                  out     dx,ax           ; disable Sequencer reset
  7440.                  sti                     ; enable interrupts
  7441.  
  7442.                  mov     bl,13h          ; BL := Horizontal Pel Pan reg number
  7443.                  mov     ax,1000h        ; AH := 10H (INT 10H function number)
  7444.                                          ; AL := 0 (set specified register)
  7445.                  int     10h             ; program Attribute Controller
  7446.  
  7447.  ; Program the Attribute Controller for 8- or 9-bit character codes
  7448.  
  7449.                  mov     ax,1000h        ; AH := 10H (INT 10H function number)
  7450.                                          ; AL := 0 (set specified register)
  7451.                  mov     bx,0F12h        ; BH := 0FH (Color Plane Enable value
  7452.                                          ; BL := 12H (Color Plane Enable reg #
  7453.                  cmp     ARGc,8
  7454.                  je      L02             ; jump if 8-bit character codes
  7455.  
  7456.                  mov     bh,7            ; BH bit 3 := 0 (ignore bit 3 of all
  7457.                                          ;  attributes)
  7458.  L02:            int     10h             ; update Color Plane Enable register
  7459.  
  7460.  ; update video BIOS data area
  7461.  
  7462.                  mov     ax,720          ; AX := displayed pixels per row
  7463.                  div     ARGw            ; AL := displayed character columns
  7464.                  mov     es:[CRT_COLS],al
  7465.  
  7466.                  pop     si
  7467.                  pop     bp
  7468.                  ret
  7469.  
  7470.  _AlphaModeSet   ENDP
  7471.  
  7472.  
  7473.  SetCRTC         PROC    near            ; Caller:       BH = character height
  7474.                                          ;               BL = character width
  7475.  
  7476.                  push    dx
  7477.                  mov     dx,es:[ADDR_6845]  ; CRTC I/O port
  7478.  
  7479.  ; establish CRTC vertical timing and cursor position in character matrix
  7480.  
  7481.                  push    bx              ; preserve char height and width
  7482.                  mov     ax,1110h        ; AH := 11H (INT 10H function number)
  7483.                                          ; AL := 0 (user alpha load)
  7484.                  xor     cx,cx           ; CX := 0 (store no characters)
  7485.                  int     10h             ; call BIOS to program CRTC
  7486.                  pop     bx
  7487.  
  7488.  ; enable I/O writes to CRTC registers
  7489.  
  7490.                  mov     al,11h          ; AL := Vertical Retrace End reg numb
  7491.                  out     dx,al
  7492.                  inc     dx
  7493.                  in      al,dx           ; AL := current value of this registe
  7494.                  dec     dx
  7495.  
  7496.                  mov     ah,al           ; AH := current value
  7497.                  mov     al,11h          ; AL := register number
  7498.                  push    ax              ; save on stack
  7499.  
  7500.                  and     ah,01111111b    ; zero bit 7
  7501.                  out     dx,ax           ; update this register
  7502.  
  7503.  ; establish CRTC horizontal timing
  7504.  
  7505.                  xor     bh,bh           ; BX := character width
  7506.                  sub     bl,8            ; BX := 0 or 1
  7507.                  neg     bx              ; BX := 0 or 0FFFFH
  7508.                  and     bx,14           ; BX := 0 or 14 (offset into table)
  7509.                  mov     si,bx           ; SI := offset into table
  7510.  
  7511.                  add     si,offset DGROUP:HorizParms     ; DS:SI -> parameters
  7512.                  call    UpdateCRTC
  7513.  
  7514.  ; write-protect CRTC registers
  7515.  
  7516.                  pop     ax              ; AX := previous VR End register data
  7517.                  out     dx,ax           ; restore this register
  7518.  
  7519.                  pop     dx
  7520.                  ret
  7521.  
  7522.  SetCRTC         ENDP
  7523.  
  7524.  
  7525.  UpdateCRTC      PROC    near            ; Caller:       DX = CRTC address por
  7526.                                          ;               DS:SI -> parameters
  7527.                                          ; Destroys:     AX,CX
  7528.  
  7529.                  mov     cx,7            ; CX := number of registers to update
  7530.  
  7531.  L10:            lodsw                   ; AH := data for CRTC register in AL
  7532.                  out     dx,ax           ; update the register
  7533.                  loop    L10
  7534.  
  7535.                  ret
  7536.  
  7537.  UpdateCRTC      ENDP
  7538.  
  7539.  _TEXT           ENDS
  7540.  
  7541.  
  7542.  _DATA           SEGMENT word public 'DATA'
  7543.  
  7544.  HorizParms      DW      6A00h,5901h,5A02h,8D03h,6304h,8805h,2D13h  ; 8-wide
  7545.                  DW      5F00h,4F01h,5002h,8203h,5504h,8105h,2813h  ; 9-wide
  7546.  
  7547.  _DATA           ENDS
  7548.  
  7549.                  END
  7550.  
  7551.  \SAMPCODE\VIDEO\10\10_14.ASM
  7552.  
  7553.                  TITLE   'Listing 10-14'
  7554.                  NAME    AlphaModeSet
  7555.                  PAGE    55,132
  7556.  
  7557.  ;
  7558.  ; Name:         AlphaModeSet
  7559.  ;
  7560.  ; Function:     Program the CRTC in alphanumeric modes on HGC+ or InColor car
  7561.  ;
  7562.  ; Caller:       Microsoft C:
  7563.  ;
  7564.  ;                       void AlphaModeSet(w,h,c);
  7565.  ;
  7566.  ;                       int     w;      /* width of character matrix */
  7567.  ;                       int     h;      /* height of character matrix */
  7568.  ;                       int     c;      /* character code size */
  7569.  ;
  7570.  
  7571.  ARGw            EQU     byte ptr [bp+4]         ; must be 8 or 9 pixels wide
  7572.  ARGh            EQU     byte ptr [bp+6]         ; must be 4-16 pixels high
  7573.  ARGc            EQU     byte ptr [bp+8]         ; must be 8 or 12 bits
  7574.  
  7575.  CRT_COLS        EQU     4Ah
  7576.  CRT_LEN         EQU     4Ch
  7577.  CRT_MODE_SET    EQU     65h
  7578.  ROWS            EQU     84h
  7579.  
  7580.  DGROUP          GROUP   _DATA
  7581.  
  7582.  _TEXT           SEGMENT byte public 'CODE'
  7583.                  ASSUME  cs:_TEXT,ds:DGROUP
  7584.  
  7585.                  PUBLIC  _AlphaModeSet
  7586.  _AlphaModeSet   PROC    near
  7587.  
  7588.                  push    bp              ; preserve caller registers
  7589.                  mov     bp,sp
  7590.                  push    ds
  7591.                  push    si
  7592.  
  7593.  ; Set Configuration Switch to bring RAM starting at B000:4000 into memory map
  7594.  
  7595.                  mov     dx,3BFh         ; DX := Configuration Switch port
  7596.                  mov     al,1            ; AL bit 1 := 0 (exclude 2nd 32K of
  7597.                                          ;                 video buffer)
  7598.                                          ; AL bit 0 := 1 (make RAM at B000:400
  7599.                  out     dx,ax           ;                 addressable)
  7600.  
  7601.  ; Blank the screen to avoid interference during CRTC programming
  7602.  
  7603.                  mov     dx,3B8h         ; DX := CRTC Mode Control Register po
  7604.                  xor     al,al           ; AL bit 3 := 0 (disable video signal
  7605.                  out     dx,al           ; blank the screen
  7606.  
  7607.  ; Program the CRTC
  7608.  
  7609.                  mov     bh,ARGw         ; BH := character width
  7610.                  mov     bl,ARGh         ; BL := character height
  7611.                  call    SetHercCRTC
  7612.  
  7613.  ; Set the xModeReg
  7614.  
  7615.                  mov     dx,3B4h         ; DX := CRTC address port
  7616.                  mov     ax,114h         ; AH bit 0 := 1 (enable RAM-based
  7617.                                          ;  character generator)
  7618.                                          ; AL := 14h (xModeReg number)
  7619.                  cmp     ARGw,9
  7620.                  je      L01             ; jump if 9-wide characters
  7621.  
  7622.                  or      ah,2            ; AH bit 1 := 1 (8-wide characters)
  7623.  
  7624.  L01:            cmp     ARGc,8
  7625.                  je      L02             ; jump if 8-bit character codes
  7626.  
  7627.                  or      ah,4            ; AH bit 2 := 1 (12-bit character cod
  7628.  
  7629.  L02:            out     dx,ax           ; update the register
  7630.  
  7631.  ; update video BIOS data area
  7632.  
  7633.                  mov     ax,40h
  7634.                  mov     ds,ax           ; DS := video BIOS data segment
  7635.  
  7636.                  mov     ax,720          ; AX := displayed pixels per row
  7637.                  div     ARGw            ; AL := displayed character columns
  7638.                  mov     ds:[CRT_COLS],al
  7639.  
  7640.                  mov     ax,350          ; AX := number of displayed scan line
  7641.                  div     ARGh            ; AL := displayed character rows
  7642.                  dec     al              ; AL := (character rows) - 1
  7643.                  mov     ds:[ROWS],al
  7644.  
  7645.                  inc     al
  7646.                  mul     byte ptr ds:[CRT_COLS]
  7647.                  shl     ax,1            ; AX := rows * columns * 2
  7648.                  mov     ds:[CRT_LEN],ax
  7649.  
  7650.  ; re-enable display and exit
  7651.  
  7652.                  mov     dx,3B8h         ; DX := CRT Mode Control port
  7653.                  mov     al,ds:[CRT_MODE_SET]    ; restore previous value
  7654.                  out     dx,al
  7655.  
  7656.                  pop     si
  7657.                  pop     ds
  7658.                  pop     bp
  7659.                  ret
  7660.  
  7661.  _AlphaModeSet   ENDP
  7662.  
  7663.  
  7664.  SetHercCRTC     PROC    near            ; Caller:       BH = character width
  7665.                                          ;               BL = character height
  7666.  
  7667.                  push    dx
  7668.                  mov     dx,3B4h         ; DX := CRTC Address Reg port 3B4h
  7669.  
  7670.  ; establish cursor position in character matrix
  7671.  
  7672.                  mov     ah,bl
  7673.                  dec     ah              ; AH := value for Max Scan Line reg
  7674.                  mov     al,9            ; AL := Max Scan Line register number
  7675.                  out     dx,ax
  7676.  
  7677.                  mov     al,0Bh          ; AL := Cursor End reg number
  7678.                  out     dx,ax           ; set cursor to end on last line of
  7679.                                          ;   character matrix
  7680.  
  7681.                  sub     ax,101h         ; AH := second-to-last line
  7682.                                          ; AL := 0AH (Cursor Start reg number)
  7683.                  out     dx,ax           ; set cursor to start on second-to-
  7684.                                          ;  last line
  7685.  
  7686.  ; compute offsets into parameter tables
  7687.  
  7688.                  sub     bx,0804h        ; BH := 0 or 1
  7689.                                          ; BL := 0 through 12
  7690.                  add     bx,bx
  7691.                  add     bx,bx           ; BH := 0 or 4
  7692.                                          ; BL := 0 through 48
  7693.  ; establish CRTC horizontal timing
  7694.  
  7695.                  push    bx              ; preserve BX
  7696.                  mov     bl,bh
  7697.                  xor     bh,bh           ; BX := 0 or 4
  7698.                  add     bx,offset DGROUP:HorizParms     ; DS:BX -> parameters
  7699.  
  7700.                  mov     al,0            ; AL := first CRTC reg to update
  7701.                  call    UpdateCRTC
  7702.  
  7703.  ; establish vertical timing
  7704.  
  7705.                  pop     bx
  7706.                  xor     bh,bh           ; BX := 0 through 48
  7707.                  add     bx,offset DGROUP:VertParms      ; DS:BX -> parameters
  7708.  
  7709.                  mov     al,4            ; AL := first CRTC reg to update
  7710.                  call    UpdateCRTC
  7711.  
  7712.                  pop     dx              ; restore DX
  7713.                  ret
  7714.  
  7715.  SetHercCRTC     ENDP
  7716.  
  7717.  
  7718.  UpdateCRTC      PROC    near            ; Caller:       AL = first reg number
  7719.                                          ;               DX = CRTC address por
  7720.                                          ;               DS:BX -> parameters
  7721.                                          ; Destroys:     AX,CX
  7722.  
  7723.                  mov     cx,4            ; CX := number of registers to update
  7724.  
  7725.  L10:            mov     ah,[bx]         ; AH := data for CRTC register in AL
  7726.                  out     dx,ax           ; update the register
  7727.                  inc     ax              ; AL := next register number
  7728.                  inc     bx              ; DS:BX -> next value in table
  7729.                  loop    L10
  7730.  
  7731.                  ret
  7732.  
  7733.  UpdateCRTC      ENDP
  7734.  
  7735.  _TEXT           ENDS
  7736.  
  7737.  
  7738.  _DATA           SEGMENT word public 'DATA'
  7739.  
  7740.  HorizParms      DB      6Dh,5Ah,5Ch,0Fh         ; 8 pixels wide
  7741.                  DB      61h,50h,52h,0Fh         ; 9 pixels wide
  7742.  
  7743.  
  7744.  VertParms       DB      5Ch,02h,58h,59h         ; 4 scan lines high
  7745.                  DB      4Ah,00h,46h,46h         ; 5
  7746.                  DB      3Dh,04h,3Ah,3Bh         ; 6
  7747.                  DB      34h,06h,32h,33h         ; 7
  7748.                  DB      2Dh,02h,2Bh,2Ch         ; 8
  7749.                  DB      28h,01h,26h,27h         ; 9
  7750.                  DB      24h,00h,23h,23h         ; 10
  7751.                  DB      20h,07h,1Fh,20h         ; 11
  7752.                  DB      1Dh,0Ah,1Dh,1Dh         ; 12
  7753.                  DB      1Bh,06h,1Ah,1Bh         ; 13
  7754.                  DB      19h,06h,19h,19h         ; 14
  7755.                  DB      17h,0Ah,17h,17h         ; 15
  7756.                  DB      16h,02h,15h,16h
  7757.  
  7758.  _DATA           ENDS
  7759.  
  7760.                  END
  7761.  
  7762.  \SAMPCODE\VIDEO\10\10_1A.ASM
  7763.  
  7764.                  TITLE   'Listing 10-1a'
  7765.                  NAME    CGenModeSet
  7766.                  PAGE    55,132
  7767.  
  7768.  ;
  7769.  ; Name:         CGenModeSet
  7770.  ;
  7771.  ;               Direct access to EGA and VGA alphanumeric character generator
  7772.  ;
  7773.  ; Caller:       Microsoft C:
  7774.  ;
  7775.  ;                       void CGenModeSet();
  7776.  ;
  7777.  
  7778.  DGROUP          GROUP   _DATA
  7779.  
  7780.  _TEXT           SEGMENT byte public 'CODE'
  7781.                  ASSUME  cs:_TEXT,ds:DGROUP
  7782.  
  7783.                  PUBLIC  _CGenModeSet
  7784.  _CGenModeSet    PROC    near
  7785.  
  7786.                  push    bp              ; preserve caller registers
  7787.                  mov     bp,sp
  7788.                  push    si
  7789.  
  7790.  ; Program the Sequencer
  7791.  
  7792.                  cli                     ; disable interrupts
  7793.                  mov     dx,3C4h         ; Sequencer port address
  7794.                  mov     si,offset DGROUP:SeqParms
  7795.                  mov     cx,4
  7796.  
  7797.  L01:            lodsw                   ; AH := value for Sequencer register
  7798.                                          ; AL := register number
  7799.                  out     dx,ax           ; program the register
  7800.                  loop    L01
  7801.                  sti                     ; enable interrupts
  7802.  
  7803.  ; Program the Graphics Controller
  7804.  
  7805.                  mov     dl,0CEh         ; DX := 3CEH (Graphics Controller por
  7806.                                          ;               address)
  7807.                  mov     si,offset DGROUP:GCParms
  7808.                  mov     cx,3
  7809.  
  7810.  L02:            lodsw                   ; program the Graphics Controller
  7811.                  out     dx,ax
  7812.                  loop    L02
  7813.  
  7814.                  pop     si
  7815.                  pop     bp
  7816.                  ret
  7817.  
  7818.  _CGenModeSet    ENDP
  7819.  
  7820.  _TEXT           ENDS
  7821.  
  7822.  
  7823.  _DATA           SEGMENT word public 'DATA'
  7824.  
  7825.  ; Format of the parameters is:  Lo-order byte:  Register number
  7826.  ;                               Hi-order byte:  Value for reg
  7827.  
  7828.  SeqParms        DW      0100h           ; synchronous reset
  7829.                  DW      0402h           ; CPU writes only to map 2
  7830.                  DW      0704h           ; sequential addressing
  7831.                  DW      0300h           ; clear synchronous reset
  7832.  
  7833.  GCParms         DW      0204h           ; select map 2 for CPU reads
  7834.                  DW      0005h           ; disable odd-even addressing
  7835.                  DW      0006h           ; map starts at A000:0000
  7836.  
  7837.  _DATA           ENDS
  7838.  
  7839.                  END
  7840.  
  7841.  \SAMPCODE\VIDEO\10\10_1B.ASM
  7842.  
  7843.                  TITLE   'Listing 10-1b'
  7844.                  NAME    CGenModeClear
  7845.                  PAGE    55,132
  7846.  
  7847.  ;
  7848.  ; Name:         CGenModeClear
  7849.  ;
  7850.  ;               Restore EGA or VGA alphanumeric mode after accessing
  7851.  ;                character generator RAM
  7852.  ;
  7853.  ; Caller:       Microsoft C:
  7854.  ;
  7855.  ;                       void CGenModeClear();
  7856.  ;
  7857.  
  7858.  
  7859.  DGROUP          GROUP   _DATA
  7860.  
  7861.  _TEXT           SEGMENT byte public 'CODE'
  7862.                  ASSUME  cs:_TEXT,ds:DGROUP
  7863.  
  7864.                  PUBLIC  _CGenModeClear
  7865.  _CGenModeClear  PROC    near
  7866.  
  7867.                  push    bp              ; preserve caller registers
  7868.                  mov     bp,sp
  7869.                  push    si
  7870.  
  7871.  ; Program the Sequencer
  7872.  
  7873.                  cli                     ; disable interrupts
  7874.                  mov     dx,3C4h         ; Sequencer port address
  7875.                  mov     si,offset DGROUP:SeqParms
  7876.                  mov     cx,4
  7877.  
  7878.  L01:            lodsw                   ; AH := value for Sequencer register
  7879.                                          ; AL := register number
  7880.                  out     dx,ax           ; program the register
  7881.                  loop    L01
  7882.                  sti                     ; enable interrupts
  7883.  
  7884.  ; Program the Graphics Controller
  7885.  
  7886.                  mov     dl,0CEh         ; DX := 3CEH (Graphics Controller por
  7887.                                          ;               address)
  7888.                  mov     si,offset DGROUP:GCParms
  7889.                  mov     cx,3
  7890.  
  7891.  L02:            lodsw                   ; program the Graphics Controller
  7892.                  out     dx,ax
  7893.                  loop    L02
  7894.  
  7895.                  mov     ah,0Fh          ; AH := INT 10H function number
  7896.                  int     10h             ; get video mode
  7897.  
  7898.                  cmp     al,7
  7899.                  jne     L03             ; jump if not monochrome mode
  7900.  
  7901.                  mov     ax,0806h        ; program Graphics Controller
  7902.                  out     dx,ax           ;  to start map at B000:0000
  7903.  
  7904.  L03:            pop     si
  7905.                  pop     bp
  7906.                  ret
  7907.  
  7908.  _CGenModeClear  ENDP
  7909.  
  7910.  _TEXT           ENDS
  7911.  
  7912.  
  7913.  _DATA           SEGMENT word public 'DATA'
  7914.  
  7915.  ; Format of the parameters is:  Lo-order byte:  Register number
  7916.  ;                               Hi-order byte:  Value for reg
  7917.  
  7918.  SeqParms        DW      0100h           ; synchronous reset
  7919.                  DW      0302h           ; CPU writes to maps 0 and 1
  7920.                  DW      0304h           ; odd-even addressing
  7921.                  DW      0300h           ; clear synchronous reset
  7922.  
  7923.  GCParms         DW      0004h           ; select map 0 for CPU reads
  7924.                  DW      1005h           ; enable odd-even addressing
  7925.                  DW      0E06h           ; map starts at B800:0000
  7926.  
  7927.  _DATA           ENDS
  7928.  
  7929.                  END
  7930.  
  7931.  \SAMPCODE\VIDEO\10\10_5.ASM
  7932.  
  7933.                  TITLE   'Listing 10-5'
  7934.                  NAME    SetFontPages
  7935.                  PAGE    55,132
  7936.  
  7937.  ;
  7938.  ; Name:         SetFontPages
  7939.  ;
  7940.  ;               Update MCGA Font Pages
  7941.  ;
  7942.  ; Caller:       Microsoft C:
  7943.  ;
  7944.  ;                       void SetFontPages(n0,n1);
  7945.  ;
  7946.  ;                       int     n0,n1;  /* font page values */
  7947.  ;
  7948.  
  7949.  ARGn0           EQU     [bp+4]
  7950.  ARGn1           EQU     [bp+6]
  7951.  
  7952.  _TEXT           SEGMENT byte public 'CODE'
  7953.                  ASSUME  cs:_TEXT
  7954.  
  7955.                  PUBLIC  _SetFontPages
  7956.  _SetFontPages   PROC    near
  7957.  
  7958.                  push    bp              ; preserve caller registers
  7959.                  mov     bp,sp
  7960.  
  7961.                  mov     ax,1103h        ; AH := INT 10H function number
  7962.                                          ; AL := 3 (Set Block Specifier)
  7963.                  mov     bl,ARGn1        ; BL := value for bits 2-3
  7964.                  shl     bl,1
  7965.                  shl     bl,1            ; BL bits 2-3 := n1
  7966.                  or      bl,ARGn0        ; BL bits 0-1 := n0
  7967.                  int     10h             ; load font pages
  7968.  
  7969.                  pop     bp
  7970.                  ret
  7971.  
  7972.  _SetFontPages   ENDP
  7973.  
  7974.  _TEXT           ENDS
  7975.  
  7976.                  END
  7977.  
  7978.  \SAMPCODE\VIDEO\11
  7979.  \SAMPCODE\VIDEO\11\11_5.C
  7980.  
  7981.  /* Listing 11-5 */
  7982.  
  7983.  main()
  7984.  {
  7985.          int     xc      = 400;          /* center of circle */
  7986.          int     yc      = 125;
  7987.          int     a,b;                    /* semimajor and semiminor axes */
  7988.          int     n = 12;                 /* pixel value */
  7989.          int     i;
  7990.          float   ScaleFactor = 1.37;     /* for 640x350 16-color mode */
  7991.  
  7992.  
  7993.          for( i=0; i<10; i++ )
  7994.            for( a=0; a<100; a++ )
  7995.            {
  7996.              b = (float) a / ScaleFactor;        /* scale semiminor axis */
  7997.              Ellipse10( xc, yc, a, b, n );       /* draw a circle */
  7998.              Ellipse10( xc, yc, a, b, n );       /* draw it again */
  7999.            }
  8000.  }
  8001.  
  8002.  \SAMPCODE\VIDEO\11\11_6.C
  8003.  
  8004.  /* Listing 11-6 */
  8005.  
  8006.  #define Xmax    640
  8007.  
  8008.  #define TRUE    1
  8009.  #define FALSE   0
  8010.  
  8011.  main()
  8012.  {
  8013.          int     x0      = 0;            /* corners of box at 0,0 and 150,100
  8014.          int     y0      = 0;
  8015.          int     x1      = 150;
  8016.          int     y1      = 100;
  8017.          int     n = 12;                 /* pixel value */
  8018.  
  8019.  
  8020.          while( x1 < Xmax )                      /* slide box right */
  8021.            XORBox( x0++, y0, x1++, y1, n );
  8022.  
  8023.          while( x0 > 0 )                         /* slide box left */
  8024.            XORBox( --x0, y0, --x1, y1, n );
  8025.  }
  8026.  
  8027.  
  8028.  XORBox ( x0, y0, x1, y1, n )
  8029.  int     x0,y0,x1,y1;            /* pixel coordinates of opposite corners */
  8030.  int     n;                      /* pixel value */
  8031.  {
  8032.          Rectangle( x0, y0, x1, y1, n );                      /* draw the box
  8033.          Rectangle( x0, y0, x1, y1, n );                     /* erase the box
  8034.  }
  8035.  
  8036.  
  8037.  Rectangle( x0, y0, x1, y1, n )
  8038.  int     x0,y0,x1,y1;
  8039.  int     n;
  8040.  {
  8041.          Line10( x0, y0, x0, y1, n );
  8042.          Line10( x0, y0, x1, y0, n );
  8043.          Line10( x1, y1, x0, y1, n );
  8044.          Line10( x1, y1, x1, y0, n );
  8045.  }
  8046.  
  8047.  \SAMPCODE\VIDEO\11\11_7.C
  8048.  
  8049.  /* Listing 11-7 */
  8050.  
  8051.  #define Xmax    640                     /* screen dimensions in 640x350 mode
  8052.  #define Ymax    350
  8053.  
  8054.  main()
  8055.  {
  8056.          int     x0      = 150;          /* fixed endpoint at 150,100 */
  8057.          int     y0      = 100;
  8058.          int     x       = 0;            /* moving endpoint at 0,0 */
  8059.          int     y       = 0;
  8060.          int     n       = 12;           /* pixel value */
  8061.  
  8062.  
  8063.          for( ; x<Xmax; x++ )                    /* move right */
  8064.            XORLine( x0, y0, x, y, n );
  8065.  
  8066.          for( --x; y<Ymax; y++ )                 /* move down */
  8067.            XORLine( x0, y0, x, y, n );
  8068.  
  8069.          for( --y; x>=0; --x )                   /* move left */
  8070.            XORLine( x0, y0, x, y, n );
  8071.  
  8072.          for( x++; y>=0; --y )                   /* move up */
  8073.            XORLine( x0, y0, x, y, n );
  8074.  }
  8075.  
  8076.  
  8077.  XORLine ( x0, y0, x1, y1, n )
  8078.  int     x0,y0,x1,y1;            /* endpoints */
  8079.  int     n;                      /* pixel value */
  8080.  {
  8081.          Line10( x0, y0, x1, y1, n );                 /* the line is onscreen
  8082.          Line10( x0, y0, x1, y1, n );                   /* the line is erased
  8083.  }
  8084.  
  8085.  \SAMPCODE\VIDEO\11\11_1.ASM
  8086.  
  8087.                  TITLE   'Listing 11-1'
  8088.                  NAME    GetBitBlock06
  8089.                  PAGE    55,132
  8090.  
  8091.  ;
  8092.  ; Name:         GetBitBlock06
  8093.  ;
  8094.  ; Function:     Copy bit block from video buffer to system RAM
  8095.  ;                in 640x200 2-color mode
  8096.  ;
  8097.  ; Caller:       Microsoft C:
  8098.  ;
  8099.  ;                       int GetBitBlock06(x0,y0,x1,y1,buf);
  8100.  ;
  8101.  ;                            int x0,y0;    /* upper left corner of bit block
  8102.  ;                            int x1,y1;       /* lower right corner */
  8103.  ;                            char far *buf;   /* buffer */
  8104.  ;
  8105.  ; Notes:        Returns size of bit block in system RAM.
  8106.  ;
  8107.  
  8108.  
  8109.  ARGx0           EQU     word ptr [bp+4]
  8110.  ARGy0           EQU     word ptr [bp+6]
  8111.  ARGx1           EQU     word ptr [bp+8]
  8112.  ARGy1           EQU     word ptr [bp+10]
  8113.  ADDRbuf         EQU              [bp+12]
  8114.  
  8115.  VARPixelRows    EQU     word ptr [bp-2]
  8116.  VARPixelRowLen  EQU     word ptr [bp-4]
  8117.  VARincr         EQU     word ptr [bp-6]
  8118.  
  8119.  ByteOffsetShift EQU     3               ; reflects number of pixels per byte
  8120.  
  8121.  
  8122.  _TEXT           SEGMENT byte public 'CODE'
  8123.                  ASSUME  cs:_TEXT
  8124.  
  8125.                  EXTRN   PixelAddr06:near
  8126.  
  8127.                  PUBLIC  _GetBitBlock06
  8128.  _GetBitBlock06  PROC    near
  8129.  
  8130.                  push    bp              ; preserve caller registers
  8131.                  mov     bp,sp
  8132.                  sub     sp,6            ; establish stack frame
  8133.                  push    ds
  8134.                  push    si
  8135.                  push    di
  8136.  
  8137.  ; compute dimensions of bit block
  8138.  
  8139.                  mov     ax,ARGx1
  8140.                  sub     ax,ARGx0
  8141.                  mov     cx,0FF07h       ; CH := unshifted bit mask
  8142.                                          ; CL := AND mask for AL
  8143.                  and     cl,al           ; CL := number of pixels in last
  8144.                                          ;  byte of row
  8145.                  xor     cl,7            ; CL := number of bits to shift
  8146.                  shl     ch,cl           ; CH := bit mask for last byte of row
  8147.                  mov     cl,ch
  8148.                  push    cx              ; save on stack
  8149.  
  8150.                  mov     cl,ByteOffsetShift
  8151.                  shr     ax,cl
  8152.                  inc     ax              ; AX := number of bytes per row
  8153.                  push    ax              ; save on stack
  8154.  
  8155.                  mov     ax,ARGy1
  8156.                  sub     ax,ARGy0
  8157.                  inc     ax              ; AX := number of pixel rows
  8158.                  push    ax              ; save on stack
  8159.  
  8160.  ; establish addressing
  8161.  
  8162.                  mov     ax,ARGy0
  8163.                  mov     bx,ARGx0
  8164.                  call    PixelAddr06     ; ES:BX -> x0,y0 in video buffer
  8165.                  xor     cl,7            ; CL := number of bits to shift left
  8166.                  push    es
  8167.                  pop     ds
  8168.                  mov     si,bx           ; DS:SI -> video buffer
  8169.  
  8170.                  mov     bx,2000h        ; BX := increment from 1st to 2nd
  8171.                                          ;  interleave in CGA video buffer
  8172.                  test    si,2000h
  8173.                  jz      L01             ; jump if x0,y0 is in 1st interleave
  8174.  
  8175.                  mov     bx,80-2000h     ; increment from 2nd to 1st interleav
  8176.  
  8177.  L01:            mov     VARincr,bx      ; initialize this variable
  8178.  
  8179.                  les     di,ADDRbuf      ; ES:DI -> buffer in system RAM
  8180.  
  8181.  ; build 5-byte bit block header
  8182.  
  8183.                  pop     ax
  8184.                  mov     VARPixelRows,ax
  8185.                  stosw                   ; byte 0-1 := number of pixel rows
  8186.                  pop     ax
  8187.                  mov     VARPixelRowLen,ax
  8188.                  stosw                   ; byte 2-3 := bytes per pixel row
  8189.                  pop     ax
  8190.                  mov     ch,al           ; CH := bit mask for last byte
  8191.                  stosb                   ; byte 4 := bit mask for last byte
  8192.  
  8193.  ; copy from video buffer to system RAM
  8194.  
  8195.  L02:            mov     bx,VARPixelRowLen
  8196.                  push    si              ; preserve SI at start of pixel row
  8197.  
  8198.  L03:            lodsw                   ; AL := next byte in video buffer
  8199.                                          ; AH := (next byte) + 1
  8200.                  dec     si              ; DS:SI -> (next byte) + 1
  8201.                  rol     ax,cl           ; AL := next 4 pixels in row
  8202.                  stosb                   ; copy to system RAM
  8203.                  dec     bx              ; loop across row
  8204.                  jnz     L03
  8205.  
  8206.                  and     es:[di-1],ch    ; mask last byte of row
  8207.                  pop     si              ; DS:SI -> start of row
  8208.                  add     si,VARincr      ; DS:SI -> start of next row
  8209.                  xor     VARincr,2000h XOR (80-2000H)  ; update increment
  8210.  
  8211.                  dec     VARPixelRows
  8212.                  jnz     L02             ; loop down rows
  8213.  
  8214.                  mov     ax,di
  8215.                  sub     ax,ADDRbuf      ; AX := return value (size of bit blo
  8216.                                          ;  in system RAM)
  8217.  
  8218.                  pop     di              ; restore registers and exit
  8219.                  pop     si
  8220.                  pop     ds
  8221.                  mov     sp,bp
  8222.                  pop     bp
  8223.                  ret
  8224.  
  8225.  _GetBitBlock06  ENDP
  8226.  
  8227.  _TEXT           ENDS
  8228.  
  8229.                  END
  8230.  
  8231.  \SAMPCODE\VIDEO\11\11_2.ASM
  8232.  
  8233.                  TITLE   'Listing 11-2'
  8234.                  NAME    StoreBitBlock06
  8235.                  PAGE    55,132
  8236.  
  8237.  ;
  8238.  ; Name:         StoreBitBlock06
  8239.  ;
  8240.  ; Function:     Copy bit block from video buffer to system RAM
  8241.  ;                in 640x200 2-color mode
  8242.  ;
  8243.  ; Caller:       Microsoft C:
  8244.  ;
  8245.  ;                       void StoreBitBlock06(buf,x,y);
  8246.  ;
  8247.  ;                            char far *buf;   /* buffer */
  8248.  ;                            int x,y;    /* upper left corner of bit block */
  8249.  ;
  8250.  
  8251.  
  8252.  ADDRbuf         EQU     dword ptr [bp+4]
  8253.  ARGx            EQU     word ptr [bp+8]
  8254.  ARGy            EQU     word ptr [bp+10]
  8255.  
  8256.  VARPixelRows    EQU     word ptr [bp-2]
  8257.  VARPixelRowLen  EQU     word ptr [bp-4]
  8258.  VARincr         EQU     word ptr [bp-6]
  8259.  
  8260.  
  8261.  DGROUP          GROUP   _DATA
  8262.  
  8263.  _TEXT           SEGMENT byte public 'CODE'
  8264.                  ASSUME  cs:_TEXT,ds:DGROUP
  8265.  
  8266.                  EXTRN   PixelAddr06:near
  8267.  
  8268.                  PUBLIC  _StoreBitBlock06
  8269.  _StoreBitBlock06 PROC   near
  8270.  
  8271.                  push    bp              ; preserve caller registers
  8272.                  mov     bp,sp
  8273.                  sub     sp,6            ; establish stack frame
  8274.                  push    ds
  8275.                  push    si
  8276.                  push    di
  8277.  
  8278.  ; establish addressing
  8279.  
  8280.                  mov     ax,ARGy
  8281.                  mov     bx,ARGx
  8282.                  call    PixelAddr06     ; ES:BX -> byte offset of x,y
  8283.                  xor     cl,7            ; CL := number of bits to shift right
  8284.  
  8285.                  mov     di,bx           ; ES:DI -> x,y in video buffer
  8286.  
  8287.                  mov     bx,2000h        ; BX := increment from 1st to 2nd
  8288.                                          ;  interleave in CGA video buffer
  8289.                  test    di,2000h
  8290.                  jz      L01             ; jump if x,y is in 1st interleave
  8291.  
  8292.                  mov     bx,80-2000h     ; increment from 2nd to 1st interleav
  8293.  
  8294.  L01:            mov     VARincr,bx      ; initialize this variable
  8295.  
  8296.                  mov     bx,StoreBitBlockOp  ; BX := subroutine address
  8297.  
  8298.                  lds     si,ADDRbuf      ; ES:DI -> buffer in system RAM
  8299.  
  8300.  ; obtain dimensions of bit block from header
  8301.  
  8302.                  lodsw                   ; AX := number of pixel rows
  8303.                  mov     VARPixelRows,ax
  8304.                  lodsw                   ; AX := bytes per pixel row
  8305.                  mov     VARPixelRowLen,ax
  8306.                  lodsb                   ; AL := bit mask for last byte in row
  8307.                  mov     ch,al
  8308.  
  8309.                  jmp     bx              ; jump to subroutine
  8310.  
  8311.  
  8312.  ReplaceBitBlock:
  8313.                  cmp     cx,0FF00h       ; if mask <> 0FFH or bits to shift <>
  8314.                  jne     L15             ;  jump if not byte-aligned
  8315.  
  8316.  ; routine for byte-aligned bit blocks
  8317.  
  8318.                  mov     cx,VARPixelRowLen
  8319.  
  8320.  L10:            push    di              ; preserve DI and CX
  8321.                  push    cx
  8322.                  rep     movsb           ; copy one pixel row into video buffe
  8323.                  pop     cx              ; restore DI and CX
  8324.                  pop     di
  8325.                  add     di,VARincr      ; ES:DI -> next pixel row in buffer
  8326.                  xor     VARincr,2000h XOR (80-2000h) ; update increment
  8327.                  dec     VARPixelRows
  8328.                  jnz     L10             ; loop down pixel rows
  8329.  
  8330.                  jmp     Lexit
  8331.  
  8332.  ; routine for all other bit blocks
  8333.  
  8334.  L15:            not     ch              ; CH := mask for end of row
  8335.                  mov     dx,0FF00h
  8336.                  ror     dx,cl           ; DX := rotated mask for each byte
  8337.  
  8338.                  mov     bx,VARPixelRowLen
  8339.                  dec     bx              ; BX := bytes per row - 1
  8340.  
  8341.  L16:            push    di
  8342.                  test    bx,bx
  8343.                  jz      L18             ; jump if only one byte per row
  8344.  
  8345.                  push    bx
  8346.  
  8347.  L17:            and     es:[di],dx      ; mask next 8 pixels in video buffer
  8348.                  lodsb                   ; AL := pixels in bit block
  8349.                  xor     ah,ah
  8350.                  ror     ax,cl           ; AX := pixels rotated into position
  8351.                  or      es:[di],ax      ; set pixels in video buffer
  8352.                  inc     di              ; ES:DI -> next byte in bit block
  8353.                  dec     bx
  8354.                  jnz     L17
  8355.  
  8356.                  pop     bx
  8357.  
  8358.  L18:            mov     al,ch
  8359.                  mov     ah,0FFh         ; AX := mask for last pixels in row
  8360.                  ror     ax,cl           ; AX := mask rotated into position
  8361.                  and     es:[di],ax      ; mask last pixels in video buffer
  8362.                  lodsb                   ; AL := last byte in row
  8363.                  xor     ah,ah
  8364.                  ror     ax,cl           ; AX := pixels rotated into position
  8365.                  or      es:[di],ax      ; set pixels in video buffer
  8366.  
  8367.                  pop     di
  8368.                  add     di,VARincr      ; ES:DI -> next pixel row in buffer
  8369.                  xor     VARincr,2000h XOR (80-2000h)
  8370.                  dec     VARPixelRows
  8371.                  jnz     L16             ; loop down pixel rows
  8372.  
  8373.                  jmp     Lexit
  8374.  
  8375.  
  8376.  XORBitBlock:
  8377.                  mov     bx,VARPixelRowLen
  8378.  
  8379.  L20:            push    di
  8380.                  push    bx
  8381.  
  8382.  L21:            lodsb                   ; AL := pixels in bit block
  8383.                  xor     ah,ah
  8384.                  ror     ax,cl           ; AX := pixels rotated into position
  8385.                  xor     es:[di],ax      ; XOR pixels into video buffer
  8386.                  inc     di              ; ES:DI -> next byte in bit block
  8387.                  dec     bx
  8388.                  jnz     L21
  8389.  
  8390.                  pop     bx
  8391.                  pop     di
  8392.                  add     di,VARincr      ; ES:DI -> next pixel row in buffer
  8393.                  xor     VARincr,2000h XOR (80-2000h)
  8394.                  dec     VARPixelRows
  8395.                  jnz     L20             ; loop down pixel rows
  8396.  
  8397.                  jmp     Lexit
  8398.  
  8399.  ANDBitBlock:
  8400.                  not     ch              ; CH := mask for end of row
  8401.  
  8402.                  mov     bx,VARPixelRowLen
  8403.                  dec     bx              ; BX := bytes per row - 1
  8404.  
  8405.  L30:            push    di
  8406.                  test    bx,bx
  8407.                  jz      L32             ; jump if only one byte per row
  8408.  
  8409.                  push    bx
  8410.  
  8411.  L31:            lodsb                   ; AL := pixels in bit block
  8412.                  mov     ah,0FFh
  8413.                  ror     ax,cl           ; AX := pixels rotated into position
  8414.                  and     es:[di],ax      ; AND pixels into video buffer
  8415.                  inc     di              ; ES:DI -> next byte in bit block
  8416.                  dec     bx
  8417.                  jnz     L31
  8418.  
  8419.                  pop     bx
  8420.  
  8421.  L32:            lodsb                   ; AL := last byte in row
  8422.                  or      al,ch           ; mask last pixels in row
  8423.                  mov     ah,0FFh
  8424.                  ror     ax,cl           ; AX := pixels rotated into position
  8425.                  and     es:[di],ax      ; AND pixels into video buffer
  8426.  
  8427.                  pop     di
  8428.                  add     di,VARincr      ; ES:DI -> next pixel row in buffer
  8429.                  xor     VARincr,2000h XOR (80-2000h)
  8430.                  dec     VARPixelRows
  8431.                  jnz     L30             ; loop down pixel rows
  8432.  
  8433.                  jmp     Lexit
  8434.  
  8435.  
  8436.  ORBitBlock:
  8437.                  mov     bx,VARPixelRowLen
  8438.  
  8439.  L40:            push    di
  8440.                  push    bx
  8441.  
  8442.  L41:            lodsb                   ; AL := pixels in bit block
  8443.                  xor     ah,ah
  8444.                  ror     ax,cl           ; AX := pixels rotated into position
  8445.                  or      es:[di],ax      ; OR pixels into video buffer
  8446.                  inc     di              ; ES:DI -> next byte in bit block
  8447.                  dec     bx
  8448.                  jnz     L41
  8449.  
  8450.                  pop     bx
  8451.                  pop     di
  8452.                  add     di,VARincr      ; ES:DI -> next pixel row in buffer
  8453.                  xor     VARincr,2000h XOR (80-2000h)
  8454.                  dec     VARPixelRows
  8455.                  jnz     L40             ; loop down pixel rows
  8456.  
  8457.  
  8458.  Lexit:          pop     di              ; restore registers and exit
  8459.                  pop     si
  8460.                  pop     ds
  8461.                  mov     sp,bp
  8462.                  pop     bp
  8463.                  ret
  8464.  
  8465.  _StoreBitBlock06 ENDP
  8466.  
  8467.  _TEXT           ENDS
  8468.  
  8469.  
  8470.  _DATA           SEGMENT word public 'DATA'
  8471.  
  8472.  StoreBitBlockOp DW      ReplaceBitBlock ; address of selected subroutine
  8473.                                          ;  (Replace, XOR, AND, OR)
  8474.  
  8475.  _DATA           ENDS
  8476.  
  8477.                  END
  8478.  
  8479.  \SAMPCODE\VIDEO\11\11_3.ASM
  8480.  
  8481.                  TITLE   'Listing 11-3'
  8482.                  NAME    GetBitBlock10
  8483.                  PAGE    55,132
  8484.  
  8485.  ;
  8486.  ; Name:         GetBitBlock10
  8487.  ;
  8488.  ; Function:     Copy bit block from video buffer to system RAM
  8489.  ;                in native EGA and VGA graphics modes
  8490.  ;
  8491.  ; Caller:       Microsoft C:
  8492.  ;
  8493.  ;                       int GetBitBlock10(x0,y0,x1,y1,buf);
  8494.  ;
  8495.  ;                            int x0,y0;    /* upper left corner of bit block
  8496.  ;                            int x1,y1;       /* lower right corner */
  8497.  ;                            char far *buf;   /* buffer */
  8498.  ;
  8499.  ; Notes:        Returns size of bit block in system RAM.
  8500.  ;
  8501.  
  8502.  
  8503.  ARGx0           EQU     word ptr [bp+4]
  8504.  ARGy0           EQU     word ptr [bp+6]
  8505.  ARGx1           EQU     word ptr [bp+8]
  8506.  ARGy1           EQU     word ptr [bp+10]
  8507.  ADDRbuf         EQU              [bp+12]
  8508.  
  8509.  VARPixelRows    EQU     word ptr [bp-2]
  8510.  VARPixelRowLen  EQU     word ptr [bp-4]
  8511.  
  8512.  BytesPerRow     EQU     80
  8513.  ByteOffsetShift EQU     3               ; reflects number of pixels per byte
  8514.  
  8515.  
  8516.  _TEXT           SEGMENT byte public 'CODE'
  8517.                  ASSUME  cs:_TEXT
  8518.  
  8519.                  EXTRN   PixelAddr10:near
  8520.  
  8521.                  PUBLIC  _GetBitBlock10
  8522.  _GetBitBlock10  PROC    near
  8523.  
  8524.                  push    bp              ; preserve caller registers
  8525.                  mov     bp,sp
  8526.                  sub     sp,4            ; establish stack frame
  8527.                  push    ds
  8528.                  push    si
  8529.                  push    di
  8530.  
  8531.  ; compute dimensions of bit block
  8532.  
  8533.                  mov     ax,ARGx1
  8534.                  sub     ax,ARGx0
  8535.                  mov     cx,0FF07h       ; CH := unshifted bit mask
  8536.                                          ; CL := AND mask for AL
  8537.                  and     cl,al           ; CL := number of pixels in last
  8538.                                          ;  byte of row
  8539.                  xor     cl,7            ; CL := number of bits to shift
  8540.                  shl     ch,cl           ; CH := bit mask for last byte of row
  8541.                  mov     cl,ch
  8542.                  push    cx              ; save on stack
  8543.  
  8544.                  mov     cl,ByteOffsetShift
  8545.                  shr     ax,cl
  8546.                  inc     ax              ; AX := number of bytes per row
  8547.                  push    ax              ; save on stack
  8548.  
  8549.                  mov     ax,ARGy1
  8550.                  sub     ax,ARGy0
  8551.                  inc     ax              ; AX := number of pixel rows
  8552.                  push    ax              ; save on stack
  8553.  
  8554.  ; establish addressing
  8555.  
  8556.                  mov     ax,ARGy0
  8557.                  mov     bx,ARGx0
  8558.                  call    PixelAddr10     ; ES:BX -> x0,y0 in video buffer
  8559.                  xor     cl,7            ; CL := number of bits to shift left
  8560.                  push    es
  8561.                  pop     ds
  8562.                  mov     si,bx           ; DS:SI -> video buffer
  8563.  
  8564.                  les     di,ADDRbuf      ; ES:DI -> buffer in system RAM
  8565.  
  8566.  ; build 5-byte bit block header
  8567.  
  8568.                  pop     ax
  8569.                  mov     VARPixelRows,ax
  8570.                  stosw                   ; byte 0-1 := number of pixel rows
  8571.                  pop     ax
  8572.                  mov     VARPixelRowLen,ax
  8573.                  stosw                   ; byte 2-3 := bytes per pixel row
  8574.                  pop     ax
  8575.                  mov     ch,al           ; CH := bit mask for last byte in row
  8576.                  stosb                   ; byte 4 := bit mask for last byte
  8577.  
  8578.  ; set up Graphics Controller
  8579.  
  8580.                  mov     dx,3CEh         ; DX := Graphics Controller address p
  8581.  
  8582.                  mov     ax,0005         ; AH := 0 (read mode 0, write mode 0)
  8583.                                          ; AL := 5 (Mode register number)
  8584.                  out     dx,ax           ; set up read mode 0
  8585.  
  8586.                  mov     ax,0304h        ; AH := 3 (first bit plane to read)
  8587.                                          ; AL := 4 (Read Map Select reg number
  8588.  
  8589.  ; copy from video buffer to system RAM
  8590.  
  8591.  L01:            out     dx,ax           ; select next memory map to read
  8592.                  push    ax              ; preserve memory map number
  8593.                  push    VARPixelRows    ; preserve number of pixel rows
  8594.                  push    si              ; preserve offset of x0,y0
  8595.  
  8596.  L02:            mov     bx,VARPixelRowLen
  8597.                  push    si              ; preserve SI at start of pixel row
  8598.  
  8599.  L03:            lodsw                   ; AL := next byte in video buffer
  8600.                                          ; AH := (next byte) + 1
  8601.                  dec     si              ; DS:SI -> (next byte) + 1
  8602.                  rol     ax,cl           ; AL := next 4 pixels in row
  8603.                  stosb                   ; copy to system RAM
  8604.                  dec     bx              ; loop across row
  8605.                  jnz     L03
  8606.  
  8607.                  and     es:[di-1],ch    ; mask last byte in row
  8608.                  pop     si              ; DS:SI -> start of row
  8609.                  add     si,BytesPerRow  ; DS:SI -> start of next row
  8610.  
  8611.                  dec     VARPixelRows
  8612.                  jnz     L02             ; loop down rows
  8613.  
  8614.                  pop     si              ; DS:SI -> start of bit block
  8615.                  pop     VARPixelRows    ; restore number of pixel rows
  8616.                  pop     ax              ; AH := last map read
  8617.                                          ; AL := Read Map Select reg number
  8618.                  dec     ah
  8619.                  jns     L01             ; loop across bit planes
  8620.  
  8621.                  mov     ax,di
  8622.                  sub     ax,ADDRbuf      ; AX := return value (size of bit blo
  8623.                                          ;  in system RAM)
  8624.  
  8625.                  pop     di              ; restore registers and exit
  8626.                  pop     si
  8627.                  pop     ds
  8628.                  mov     sp,bp
  8629.                  pop     bp
  8630.                  ret
  8631.  
  8632.  _GetBitBlock10  ENDP
  8633.  
  8634.  _TEXT           ENDS
  8635.  
  8636.                  END
  8637.  
  8638.  \SAMPCODE\VIDEO\11\11_4.ASM
  8639.  
  8640.                  TITLE   'Listing 11-4'
  8641.                  NAME    StoreBitBlock10
  8642.                  PAGE    55,132
  8643.  
  8644.  ;
  8645.  ; Name:         StoreBitBlock10
  8646.  ;
  8647.  ; Function:     Copy bit block from video buffer to system RAM
  8648.  ;                in native EGA and VGA graphics modes
  8649.  ;
  8650.  ; Caller:       Microsoft C:
  8651.  ;
  8652.  ;                       void StoreBitBlock10(buf,x,y);
  8653.  ;
  8654.  ;                            char far *buf;   /* buffer */
  8655.  ;                            int x,y;    /* upper left corner of bit block */
  8656.  ;
  8657.  
  8658.  
  8659.  ADDRbuf         EQU     dword ptr [bp+4]
  8660.  ARGx            EQU     word ptr [bp+8]
  8661.  ARGy            EQU     word ptr [bp+10]
  8662.  
  8663.  VARPixelRows    EQU     word ptr [bp-2]
  8664.  VARPixelRowLen  EQU     word ptr [bp-4]
  8665.  VARRowCounter   EQU     word ptr [bp-6]
  8666.  VARStartMask    EQU     word ptr [bp-8]
  8667.  VAREndMaskL     EQU     word ptr [bp-10]
  8668.  VAREndMaskR     EQU     word ptr [bp-12]
  8669.  
  8670.  BytesPerRow     EQU     80              ; logical width of video buffer
  8671.  ByteOffsetShift EQU     3               ; reflects number of pixels per byte
  8672.  RMWbits         EQU     18h             ; selects replace, XOR, AND, or OR
  8673.  
  8674.  _TEXT           SEGMENT byte public 'CODE'
  8675.                  ASSUME  cs:_TEXT
  8676.  
  8677.                  EXTRN   PixelAddr10:near
  8678.  
  8679.                  PUBLIC  _StoreBitBlock10
  8680.  _StoreBitBlock10        PROC    near
  8681.  
  8682.                  push    bp              ; preserve caller registers
  8683.                  mov     bp,sp
  8684.                  sub     sp,12           ; establish stack frame
  8685.                  push    ds
  8686.                  push    si
  8687.                  push    di
  8688.  
  8689.  ; establish addressing
  8690.  
  8691.                  mov     ax,ARGy
  8692.                  mov     bx,ARGx
  8693.                  call    PixelAddr10     ; ES:BX -> byte offset of x,y
  8694.                  inc     cl
  8695.                  and     cl,7            ; CL := number of bits to shift left
  8696.  
  8697.                  mov     di,bx           ; ES:DI -> x,y in video buffer
  8698.  
  8699.                  lds     si,ADDRbuf      ; ES:DI -> buffer in system RAM
  8700.  
  8701.  ; obtain dimensions of bit block from header
  8702.  
  8703.                  lodsw                   ; AX := number of pixel rows
  8704.                  mov     VARPixelRows,ax
  8705.                  lodsw                   ; AX := bytes per pixel row
  8706.                  mov     VARPixelRowLen,ax
  8707.                  lodsb                   ; AL := bit mask for last byte in row
  8708.                  mov     ch,al
  8709.  
  8710.  ; set up Graphics Controller
  8711.  
  8712.                  mov     dx,3CEh         ; DX := Graphics Controller I/O port
  8713.  
  8714.                  mov     ah,RMWbits      ; AH := value for Data Rotate/Functio
  8715.                  mov     al,3            ;  Select register
  8716.                  out     dx,ax           ; update this register
  8717.  
  8718.                  mov     ax,0805h        ; AH := 8 (read mode 1, write mode 0)
  8719.                                          ; AL := 5 (Mode register number)
  8720.                  out     dx,ax           ; set up read mode 0
  8721.  
  8722.                  mov     ax,0007         ; AH := 0 (don't care for all maps;
  8723.                                          ;  CPU reads always return 0FFH)
  8724.                                          ; AL := 7 (Color Don't Care reg numbe
  8725.                  out     dx,ax           ; set up Color Don't Care reg
  8726.  
  8727.                  mov     ax,0FF08h       ; AH := 0FFH (value for Bit Mask reg)
  8728.                  out     dx,ax           ; set up Bit Mask reg
  8729.  
  8730.                  mov     dl,0C4h         ; DX := 3C4H (Sequencer I/O port)
  8731.                  mov     ax,0802h        ; AH := 1000B (value for Map Mask reg
  8732.                                          ; AL := 2 (Map Mask register number)
  8733.  
  8734.                  cmp     cx,0FF00h       ; if mask <> 0FFH or bits to shift <>
  8735.                  jne     L15             ;  jump if not byte-aligned
  8736.  
  8737.  ; routine for byte-aligned bit blocks
  8738.  
  8739.                  mov     cx,VARPixelRowLen
  8740.  
  8741.  L10:            out     dx,ax           ; enable one bit plane for writes
  8742.                  push    ax              ; preserve Map Mask value
  8743.                  push    di              ; preserve video buffer offset of x,y
  8744.                  mov     bx,VARPixelRows
  8745.  
  8746.  L11:            push    di              ; preserve DI and CX
  8747.                  push    cx
  8748.  
  8749.  L12:            lodsb                   ; AL := next byte of pixels
  8750.                  and     es:[di],al      ; update bit plane
  8751.                  inc     di
  8752.                  loop    L12
  8753.  
  8754.                  pop     cx              ; restore DI and CX
  8755.                  pop     di
  8756.                  add     di,BytesPerRow  ; ES:DI -> next pixel row in buffer
  8757.                  dec     bx
  8758.                  jnz     L11             ; loop down pixel rows
  8759.  
  8760.                  pop     di              ; ES:DI -> video buffer offset of x,y
  8761.                  pop     ax              ; AH := current Map Mask reg value
  8762.                  shr     ah,1            ; AH := new Map Mask value
  8763.                  jnz     L10             ; loop across all bit planes
  8764.  
  8765.                  jmp     Lexit
  8766.  
  8767.  ; routine for non-aligned bit blocks
  8768.  
  8769.  L15:            push    ax              ; preserve Map Mask reg values
  8770.  
  8771.                  mov     bx,0FFh         ; BH := 0 (mask for first byte in row
  8772.                                          ; BL := 0FFh
  8773.                  mov     al,ch           ; AL := mask for last byte in pixel r
  8774.                  cbw                     ; AH := 0FFh (mask for last-1 byte)
  8775.  
  8776.                  cmp     VARPixelRowLen,1
  8777.                  jne     L16             ; jump if more than one byte per row
  8778.  
  8779.                  mov     bl,ch
  8780.                  mov     ah,ch           ; AH := mask for last-1 byte
  8781.                  xor     al,al           ; AL := 0 (mask for last byte)
  8782.  
  8783.  L16:            shl     ax,cl           ; shift masks into position
  8784.                  shl     bx,cl
  8785.  
  8786.                  mov     bl,al           ; save masks along with ..
  8787.                  mov     al,8            ; .. Bit Mask register number
  8788.                  mov     VAREndMaskL,ax
  8789.                  mov     ah,bl
  8790.                  mov     VAREndMaskR,ax
  8791.                  mov     ah,bh
  8792.                  mov     VARStartMask,ax
  8793.  
  8794.                  mov     bx,VARPixelRowLen
  8795.                  pop     ax              ; restore Map Mask reg values
  8796.  
  8797.  ; set pixels row by row in the bit planes
  8798.  
  8799.  L17:            out     dx,ax           ; enable one bit plane for writes
  8800.                  push    ax              ; preserve Map Mask value
  8801.                  push    di              ; preserve video buffer offset of x,y
  8802.                  mov     dl,0CEh         ; DX := 3CEH (Graphics Controller por
  8803.  
  8804.                  mov     ax,VARPixelRows
  8805.                  mov     VARRowCounter,ax  ; initialize loop counter
  8806.  
  8807.  ; set pixels at start of row in currently enabled bit plane
  8808.  
  8809.  L18:            push    di              ; preserve offset of start of pixel r
  8810.                  push    si              ; preserve offset of row in bit block
  8811.                  push    bx              ; preserve bytes per pixel row
  8812.  
  8813.                  mov     ax,VARStartMask
  8814.                  out     dx,ax           ; set Bit Mask reg for first byte of
  8815.  
  8816.                  lodsw                   ; AH := 2nd byte of pixels
  8817.                                          ; AL := 1st byte of pixels
  8818.                  dec     si              ; DS:SI -> 2nd byte of pixels
  8819.                  test    cl,cl
  8820.                  jnz     L19             ; jump if not left-aligned
  8821.  
  8822.                  dec     bx              ; BX := bytes per row - 1
  8823.                  jnz     L20             ; jump if at least 2 bytes per row
  8824.                  jmp     short L22       ; jump if only one byte per row
  8825.  
  8826.  L19:            rol     ax,cl           ; AH := left part of 1st byte,
  8827.                                          ;        right part of 2nd byte
  8828.                                          ; AL := right part of 1st byte,
  8829.                                          ;        left part of 2nd byte
  8830.                  and     es:[di],ah      ; set pixels for left part of first b
  8831.                  inc     di
  8832.                  dec     bx              ; BX := bytes per row - 2
  8833.  
  8834.  L20:            push    ax              ; preserve pixels
  8835.                  mov     ax,0FF08h
  8836.                  out     dx,ax           ; set Bit Mask reg for succeeding byt
  8837.                  pop     ax
  8838.  
  8839.                  dec     bx
  8840.                  jng     L22             ; jump if only 1 or 2 bytes in pixel
  8841.  
  8842.  ; set pixels in middle of row
  8843.  
  8844.  L21:            and     es:[di],al      ; set pixels in right part of current
  8845.                  inc     di              ;  byte and left part of next byte
  8846.  
  8847.                  lodsw                   ; AH := next+1 byte of pixels
  8848.                  dec     si              ; AL := next byte of pixels
  8849.                  rol     ax,cl           ; AH := left part of next byte, right
  8850.                                          ;        part of next+1 byte
  8851.                                          ; AL := right part of next byte, left
  8852.                                          ;        part of next+1 byte
  8853.                  dec     bx
  8854.                  jnz     L21             ; loop across pixel row
  8855.  
  8856.  ; set pixels at end of row
  8857.  
  8858.  L22:            mov     bx,ax           ; BH := right part of last byte, left
  8859.                                          ;        part of last-1 byte
  8860.                                          ; BL := left part of last byte, right
  8861.                                          ;        part of last-1 byte
  8862.                  mov     ax,VAREndMaskL  ; AH := mask for last-1 byte
  8863.                                          ; AL := Bit Mask reg number
  8864.                  out     dx,ax           ; set Bit Mask register
  8865.                  and     es:[di],bl      ; set pixels for last-1 byte
  8866.  
  8867.                  mov     ax,VAREndMaskR  ; mask for last byte in pixel row
  8868.                  out     dx,ax           ; .. last byte in pixel row
  8869.                  and     es:[di+1],bh    ; set pixels for last byte
  8870.  
  8871.                  pop     bx              ; BX := bytes per pixel row
  8872.                  pop     si
  8873.                  add     si,bx           ; DS:SI -> next row in bit block
  8874.                  pop     di
  8875.                  add     di,BytesPerRow  ; ES:DI -> next pixel row in buffer
  8876.                  dec     VARRowCounter
  8877.                  jnz     L18             ; loop down pixel rows
  8878.  
  8879.                  pop     di              ; ES:DI -> video buffer offset of x,y
  8880.                  pop     ax              ; AX := current Map Mask value
  8881.                  mov     dl,0C4h         ; DX := 3C4H
  8882.                  shr     ah,1            ; AH := next Map Mask value
  8883.                  jnz     L17             ; loop across bit planes
  8884.  
  8885.  ; restore Graphics Controller and Sequencer to their default states
  8886.  
  8887.  Lexit:          mov     ax,0F02h        ; default Map Mask value
  8888.                  out     dx,ax
  8889.  
  8890.                  mov     dl,0CEh         ; DX := 3CEh
  8891.                  mov     ax,0003         ; default Data Rotate/Function Select
  8892.                  out     dx,ax
  8893.  
  8894.                  mov     ax,0005         ; default Mode value
  8895.                  out     dx,ax
  8896.  
  8897.                  mov     ax,0F07h        ; default Color Compare value
  8898.                  out     dx,ax
  8899.  
  8900.                  mov     ax,0FF08h       ; default Bit Mask value
  8901.                  out     dx,ax
  8902.  
  8903.                  pop     di              ; restore registers and exit
  8904.                  pop     si
  8905.                  pop     ds
  8906.                  mov     sp,bp
  8907.                  pop     bp
  8908.                  ret
  8909.  
  8910.  _StoreBitBlock10 ENDP
  8911.  
  8912.  _TEXT           ENDS
  8913.  
  8914.                  END
  8915.  
  8916.  \SAMPCODE\VIDEO\12
  8917.  \SAMPCODE\VIDEO\12\12_2.C
  8918.  
  8919.  /* Listing 12-2 */
  8920.  
  8921.  int     VRcount = 0;                    /* vertical interrupt counter */
  8922.  
  8923.  main()
  8924.  {
  8925.          if ( EnableISR0A() )
  8926.          {
  8927.            printf( "\nCan't enable vertical interrupt handler\n" );
  8928.            exit( 1 );
  8929.          }
  8930.  
  8931.          while (VRcount < 600)
  8932.            printf( "\015Number of vertical interrupts:  %d", VRcount );
  8933.  
  8934.          DisableISR0A();
  8935.  }
  8936.  
  8937.  \SAMPCODE\VIDEO\12\12_1.ASM
  8938.  
  8939.                  TITLE   'Listing 12-1'
  8940.                  NAME    VREGA
  8941.                  PAGE    55,132
  8942.  
  8943.  ;
  8944.  ; Name:         VREGA
  8945.  ;
  8946.  ; Function:     Vertical Interrupt Service routine for EGA and VGA
  8947.  ;
  8948.  ; Caller:       Microsoft C:
  8949.  ;
  8950.  ;                       int EnableISR0A();      /* returns 0 if installed ok
  8951.  ;
  8952.  ;                       void DisableISR0A();
  8953.  ;
  8954.  
  8955.  CRT_MODE        EQU     49h             ; addresses in video BIOS data area
  8956.  ADDR_6845       EQU     63h
  8957.  
  8958.  DGROUP          GROUP   _DATA
  8959.  
  8960.  _TEXT           SEGMENT byte public 'CODE'
  8961.                  ASSUME  cs:_TEXT,ds:DGROUP
  8962.  
  8963.  ISR0A           PROC    far             ; Interrupt handler for INT 0Ah
  8964.  
  8965.                  push    ax              ; preserve registers
  8966.                  push    dx
  8967.                  push    ds
  8968.  
  8969.                  mov     ax,seg DGROUP
  8970.                  mov     ds,ax           ; DS -> DGROUP
  8971.  
  8972.  ; determine whether a vertical interrupt has occurred
  8973.  
  8974.                  mov     dx,3C2h         ; DX := I/O port for
  8975.                                          ;  Input Status Register Zero
  8976.                  in      al,dx
  8977.                  test    al,80h          ; test bit 7 of the Status Reg value
  8978.                  jnz     L10             ; jump if vertical interrupt
  8979.  
  8980.  ; not a vertical interrupt so chain to previous interrupt handler
  8981.  
  8982.                  pushf                   ; simulate an INT
  8983.                  call    ds:PrevISR0A    ;  to the previous INT 0Ah handler
  8984.                  jmp     short Lexit
  8985.  
  8986.  ; handle a vertical interrupt
  8987.  
  8988.  L10:            mov     dx,Port3x4      ; DX := 3B4h or 3D4h
  8989.  
  8990.                  in      al,dx           ; AL := value of CRTC address reg
  8991.                  push    ax              ; preserve this value
  8992.  
  8993.                  mov     ax,DefaultVREnd ; AH := default value for VR End Reg
  8994.                                          ; AL := 11h (register number)
  8995.                  and     ah,11101111b    ; AH bit 4 := 0 (clear interrupt latc
  8996.                  out     dx,ax           ; update VR End Register
  8997.                  jmp     $+2             ; wait for CRTC to respond
  8998.  
  8999.  ; send End of Interrupt to Intel 8259A Programmable Interrupt Controller
  9000.  ;  to allow subsequent IRQ2 interrupts to occur
  9001.  
  9002.                  mov     al,20h          ; 8259A I/O port
  9003.                  out     20h,al          ; send nonspecific EOI to 8259A
  9004.                  jmp     $+2             ; wait for PIC to respond
  9005.                  sti                     ; enable interrupts
  9006.  
  9007.  ; do something useful ...
  9008.  
  9009.                  inc     word ptr _VRcount       ; increment a counter
  9010.  
  9011.  ; enable CRTC to generate another interrupt
  9012.  
  9013.                  cli                     ; disable interrupts
  9014.                  mov     ax,DefaultVREnd ; AH := default value for VR End Reg
  9015.                                          ; AL := 11h (register number)
  9016.                  and     ah,11011111b    ; AH bit 5 := 0 (enable vertical int)
  9017.                  or      ah,00010000b    ; AH bit 4 := 1 (enable int latch)
  9018.                  out     dx,ax
  9019.                  jmp     $+2
  9020.  
  9021.                  pop     ax
  9022.                  out     dx,al           ; restore previous Address reg value
  9023.  
  9024.  Lexit:          pop     ds              ; restore registers and exit
  9025.                  pop     dx
  9026.                  pop     ax
  9027.                  iret
  9028.  
  9029.  ISR0A           ENDP
  9030.  
  9031.  ;
  9032.  ; EnableISR0A -- enable Vertical Interrupt Handler
  9033.  ;
  9034.                  PUBLIC  _EnableISR0A
  9035.  _EnableISR0A    PROC    near
  9036.  
  9037.                  push    bp              ; preserve caller registers
  9038.                  mov     bp,sp
  9039.                  push    si
  9040.                  push    di
  9041.  
  9042.                  mov     ax,40h
  9043.                  mov     es,ax           ; ES -> video BIOS data area
  9044.  
  9045.  ; save default CRTC register values
  9046.  
  9047.                  mov     dx,es:[ADDR_6845]  ; DX := CRTC Address port
  9048.                  mov     Port3x4,dx      ; save port address
  9049.  
  9050.                  mov     ax,1A00h        ; AH := 1AH (INT 10H function number)
  9051.                                          ; AL := 0 (read Display Combination)
  9052.                  int     10h             ; AL := 1AH if function 1AH supported
  9053.                                          ; BL := active video subsystem
  9054.                  cmp     al,1Ah
  9055.                  jne     L20             ; jump if not a VGA
  9056.  
  9057.                  cmp     bl,7
  9058.                  je      L21             ; jump if VGA
  9059.  
  9060.                  cmp     bl,8
  9061.                  je      L21             ; jump if VGA
  9062.  
  9063.                  mov     ax,0FFFFh       ; return 0FFFFh if neither EGA nor VG
  9064.                  jmp     short L23
  9065.  
  9066.  ; get default value for EGA Vertical Retrace End register
  9067.  
  9068.  L20:            mov     al,es:[CRT_MODE]  ; AL := video BIOS mode number
  9069.                  mov     bx,offset DGROUP:EGADefaultVals
  9070.                  xlat                    ; AL := default value for VR End reg
  9071.                  jmp     short L22
  9072.                                          ;
  9073.  ; get default value for VGA Vertical Retrace End register
  9074.  
  9075.  L21:            mov     al,VREndReg     ; AL := VR End register number
  9076.                  out     dx,al
  9077.                  inc     dx              ; DX := 3B5H or 3D5H
  9078.                  in      al,dx           ; AL := current value for register
  9079.  
  9080.  L22:            mov     VREndValue,al   ; save this value
  9081.  
  9082.  ; save old interrupt 0Ah vector
  9083.  
  9084.                  mov     ax,350Ah        ; AH := 35H (INT 21h function number)
  9085.                                          ; AL := 0AH (interrupt number)
  9086.                  int     21h             ; ES:BX := previous INT 0AH vector
  9087.  
  9088.                  mov     word ptr PrevISR0A,bx
  9089.                  mov     word ptr PrevISR0A+2,es ; save previous vector
  9090.  
  9091.  ; update interrupt 0AH vector with address of this handler
  9092.  
  9093.                  push    ds              ; preserve DS
  9094.                  mov     dx,offset ISR0A
  9095.                  push    cs
  9096.                  pop     ds              ; DS:DX -> ISR0A
  9097.                  mov     ax,250Ah        ; AH := 25H (INT 21H function number)
  9098.                                          ; AL := 0AH (interrupt number)
  9099.                  int     21h             ; update INT 0AH vector
  9100.                  pop     ds              ; restore DS
  9101.  
  9102.  ; enable IRQ2 by zeroing bit 2 of the 8259A's mask register
  9103.  
  9104.                  cli                     ; clear interrupts
  9105.                  mov     dx,21h          ; DX := 8259A mask register
  9106.                  in      al,dx           ; AL := mask register value
  9107.                  and     al,11111011b    ; reset bit 2
  9108.                  out     dx,al
  9109.  
  9110.  ; enable vertical interrupts
  9111.  
  9112.                  mov     dx,Port3x4      ; DX := 3B4H or 3D4H
  9113.                  mov     ax,DefaultVREnd
  9114.  
  9115.                  and     ah,11001111b
  9116.                  out     dx,ax           ; clear bits 4 and 5 of VR End reg
  9117.                  jmp     $+2             ; wait for CRTC to respond
  9118.                  or      ah,00010000b
  9119.                  out     dx,ax           ; set bit 4
  9120.                  jmp     $+2
  9121.                  sti                     ; enable interrupts
  9122.  
  9123.                  xor     ax,ax           ; AX := 0 (return value)
  9124.  
  9125.  L23:            pop     di              ; restore registers and exit
  9126.                  pop     si
  9127.                  mov     sp,bp
  9128.                  pop     bp
  9129.                  ret
  9130.  
  9131.  _EnableISR0A    ENDP
  9132.  
  9133.  ;
  9134.  ; DisableISR0A -- disable Vertical Interrupt Handler
  9135.  ;
  9136.                  PUBLIC  _DisableISR0A
  9137.  _DisableISR0A   PROC    near
  9138.  
  9139.                  push    bp
  9140.                  mov     bp,sp
  9141.                  push    si
  9142.                  push    di
  9143.                  push    ds
  9144.  
  9145.  ; disable vertical interrupts
  9146.  
  9147.                  cli                     ; disable interrupts
  9148.                  mov     dx,Port3x4
  9149.                  mov     ax,DefaultVREnd
  9150.                  out     dx,ax           ; restore Vertical Retrace End reg
  9151.                  jmp     $+2
  9152.                  sti                     ; enable interrupts
  9153.  
  9154.  ; restore previous interrupt 0Ah handler
  9155.  
  9156.                  lds     dx,PrevISR0A    ; DS:DX := previous INT 0AH vector
  9157.                  mov     ax,250Ah        ; AH := 25H (INT 21H function number)
  9158.                                          ; AL := 0AH (interrupt number)
  9159.                  int     21h
  9160.  
  9161.                  pop     ds              ; restore registers and exit
  9162.                  pop     di
  9163.                  pop     si
  9164.                  mov     sp,bp
  9165.                  pop     bp
  9166.                  ret
  9167.  
  9168.  _DisableISR0A   ENDP
  9169.  
  9170.  _TEXT           ENDS
  9171.  
  9172.  _DATA           SEGMENT word public 'DATA'
  9173.  
  9174.                  EXTRN   _VRcount:word   ; declared in C caller
  9175.  
  9176.  PrevISR0A       DD      ?               ; save area for old int 0Ah vector
  9177.  Port3x4         DW      ?               ; 3B4h or 3D4h
  9178.  
  9179.  DefaultVREnd    LABEL   word
  9180.  VREndReg        DB      11h             ; Vertical Retrace End register numbe
  9181.  VREndValue      DB      ?               ; default value for VR End register
  9182.  
  9183.  EGADefaultVals  DB      2Bh,2Bh,2Bh,2Bh,24h,24h,23h,2Eh ; default values for
  9184.                  DB      00h,00h,00h,00h,00h,24h,23h,2Eh ;  EGA VR End reg
  9185.                  DB      2Bh
  9186.  
  9187.  _DATA           ENDS
  9188.  
  9189.                  END
  9190.  
  9191.  \SAMPCODE\VIDEO\12\12_10.ASM
  9192.  
  9193.                  TITLE   'Listing 12-10'
  9194.                  NAME    GetHercMode
  9195.                  PAGE    55,132
  9196.  
  9197.  ;
  9198.  ; Name:         GetHercMode
  9199.  ;
  9200.  ; Function:     Determine video mode on Hercules adapters by estimating the s
  9201.  ;               of the displayed portion of the video buffer.
  9202.  ;
  9203.  ; Caller:       Microsoft C:
  9204.  ;
  9205.  ;                       int GetHercMode(n);     /* returns approximate size *
  9206.  ;                                               /*  of displayed portion of *
  9207.  ;                                               /*  video buffer in words   *
  9208.  ;
  9209.  
  9210.  _TEXT           SEGMENT byte public 'CODE'
  9211.                  ASSUME  cs:_TEXT
  9212.  
  9213.                  PUBLIC  _GetHercMode
  9214.  _GetHercMode    PROC    near
  9215.  
  9216.                  push    bp              ; preserve BP
  9217.                  mov     bp,sp
  9218.  
  9219.  ; reset CRTC light pen latch
  9220.  
  9221.                  mov     dx,3BBh         ; DX := light pen reset port
  9222.                  out     dx,al           ; OUT to this port clears the latch
  9223.                                          ;  (the value in AL doesn't matter)
  9224.  
  9225.  ; wait for start of next vertical retrace
  9226.  
  9227.                  dec     dx              ; DX := 3BAH (CRT status port)
  9228.  L01:            in      al,dx           ; wait for start of vertical retrace
  9229.                  test    al,80h
  9230.                  jnz     L01
  9231.  
  9232.  L02:            in      al,dx           ; wait for end of vertical retrace
  9233.                  test    al,80h
  9234.                  jz      L02
  9235.  
  9236.                  cli                     ; disable interrupts
  9237.  L03:            in      al,dx           ; wait for start of vertical retrace
  9238.                  test    al,80h
  9239.                  jnz     L03
  9240.  
  9241.  ; latch the current CRTC address counter in the Light Pen registers
  9242.  
  9243.                  dec     dx              ; DX := 3B9H
  9244.                  out     dx,al           ; OUT to this port loads the latch
  9245.                  sti                     ; re-enable interrupts
  9246.  
  9247.  ; return the value in the Light Pen registers
  9248.  
  9249.                  mov     dl,0B4h         ; DX := 3B4H (CRTC address port)
  9250.                  mov     al,10h          ; AL := Light Pen High register numbe
  9251.                  out     dx,al
  9252.                  inc     dx
  9253.                  in      al,dx           ; read this register
  9254.                  dec     dx
  9255.                  mov     ah,al           ; AH := current Light Pen High value
  9256.  
  9257.                  mov     al,11h          ; AL := Light Pen Low register number
  9258.                  out     dx,al
  9259.                  inc     dx
  9260.                  in      al,dx           ; AX := current light pen latch value
  9261.                                          ;  (i.e., value of CRTC address count
  9262.                                          ;   at start of vertical retrace)
  9263.                  pop     bp
  9264.                  ret
  9265.  
  9266.  _GetHercMode    ENDP
  9267.  
  9268.  _TEXT           ENDS
  9269.  
  9270.                  END
  9271.  
  9272.  \SAMPCODE\VIDEO\12\12_3.ASM
  9273.  
  9274.                  TITLE   'Listing 12-3'
  9275.                  NAME    VRMCGA
  9276.                  PAGE    55,132
  9277.  
  9278.  ;
  9279.  ; Name:         VRMCGA
  9280.  ;
  9281.  ; Function:     Vertical Interrupt Service routine for MCGA
  9282.  ;
  9283.  ; Caller:       Microsoft C:
  9284.  ;
  9285.  ;                       int EnableISR0A();      /* returns 0 if installed ok
  9286.  ;
  9287.  ;                       void DisableISR0A();
  9288.  ;
  9289.  
  9290.  ADDR_6845       EQU     63h
  9291.  
  9292.  DGROUP          GROUP   _DATA
  9293.  
  9294.  _TEXT           SEGMENT byte public 'CODE'
  9295.                  ASSUME  cs:_TEXT,ds:DGROUP
  9296.  
  9297.  ISR0A           PROC    far             ; Interrupt handler for INT 0Ah
  9298.  
  9299.                  push    ax              ; preserve registers
  9300.                  push    dx
  9301.                  push    ds
  9302.  
  9303.                  mov     ax,seg DGROUP
  9304.                  mov     ds,ax           ; DS -> DGROUP
  9305.  
  9306.                  mov     dx,Port3x4      ; DX := CRTC Address reg number
  9307.                  in      al,dx
  9308.                  push    ax              ; preserve CRTC Address reg value
  9309.  
  9310.  ; determine whether a vertical interrupt has occurred
  9311.  
  9312.                  mov     al,IContReg     ; AL := register number
  9313.                  out     dx,al
  9314.                  jmp     $+2             ; wait for MCGA to respond
  9315.                  inc     dx              ; DX := 3D5H
  9316.                  in      al,dx           ; AL := current Interrupt Control
  9317.                                          ;  register value
  9318.                  dec     dx
  9319.                  test    al,40h          ; test bit 6
  9320.                  jnz     L10             ; jump if vertical interrupt
  9321.  
  9322.  ; not a vertical interrupt so chain to previous interrupt handler
  9323.  
  9324.                  pushf                   ; simulate an INT to the
  9325.                  call    ds:PrevISR0A    ;  previous INT 0Ah handler
  9326.                  jmp     short Lexit
  9327.  
  9328.  ; handle a vertical interrupt
  9329.  
  9330.  L10:            mov     ax,DefaultICont ; AH := default value for
  9331.                                          ;  Interrupt Control register
  9332.                                          ; AL := 11h (register number)
  9333.                  and     ah,11101111b    ; AH bit 4 := 0 (clear interrupt latc
  9334.                  out     dx,ax           ; update Interrupt Control reg
  9335.                  jmp     $+2             ; wait for MCGA to respond
  9336.  
  9337.  ; send End of Interrupt to Programmable Interrupt Controller
  9338.  ;  to allow subsequent IRQ2 interrupts to occur
  9339.  
  9340.                  mov     al,20h          ; PIC I/O port
  9341.                  out     20h,al          ; send nonspecific EOI to PIC
  9342.                  jmp     $+2             ; wait for PIC to respond
  9343.                  sti                     ; enable interrupts
  9344.  
  9345.  ; do something useful ...
  9346.  
  9347.                  inc     word ptr _VRcount       ; increment a counter
  9348.  
  9349.  ; enable CRTC to generate another interrupt
  9350.  
  9351.                  cli                     ; disable interrupts
  9352.                  mov     ax,DefaultICont ; AH := default value for
  9353.                                          ;  Interrupt Control register
  9354.                                          ; AL := 11h (register number)
  9355.                  and     ah,11011111b    ; AH bit 5 := 0 (enable vert int)
  9356.                  or      ah,00010000b    ; AH bit 4 := 1 (enable int latch)
  9357.                  out     dx,ax
  9358.                  jmp     $+2
  9359.  
  9360.  Lexit:          pop     ax
  9361.                  out     dx,al           ; restore previous 3D4H value
  9362.  
  9363.                  pop     ds              ; restore registers and exit
  9364.                  pop     dx
  9365.                  pop     ax
  9366.                  iret
  9367.  
  9368.  ISR0A           ENDP
  9369.  
  9370.  ;
  9371.  ; EnableISR0A -- enable Vertical Interrupt Handler
  9372.  ;
  9373.                  PUBLIC  _EnableISR0A
  9374.  _EnableISR0A    PROC    near
  9375.  
  9376.                  push    bp              ; preserve caller registers
  9377.                  mov     bp,sp
  9378.                  push    si
  9379.                  push    di
  9380.  
  9381.                  mov     ax,40h
  9382.                  mov     es,ax           ; ES -> video BIOS data area
  9383.  
  9384.  ; save default CRTC register values
  9385.  
  9386.                  mov     dx,es:[ADDR_6845]  ; DX := CRTC Address port
  9387.                  mov     Port3x4,dx      ; save port address
  9388.  
  9389.                  mov     ax,1A00h        ; AH := 1AH (INT 10H function number)
  9390.                                          ; AL := 0 (read Display Combination)
  9391.                  int     10h             ; AL := 1AH if function 1AH supported
  9392.                                          ; BL := active video subsystem
  9393.                  cmp     al,1Ah
  9394.                  jne     L20             ; jump if not an MCGA
  9395.  
  9396.                  cmp     bl,0Bh
  9397.                  je      L21             ; jump if MCGA
  9398.  
  9399.                  cmp     bl,0Ch
  9400.                  je      L21             ; jump if MCGA
  9401.  
  9402.  L20:            mov     ax,0FFFFh       ; return 0FFFFh if not an MCGA
  9403.                  jmp     short L23
  9404.  
  9405.  ; get default value for MCGA Interrupt Control register
  9406.  
  9407.  L21:            mov     al,IContReg     ; AL := Interrupt Control reg number
  9408.                  cli
  9409.                  out     dx,al
  9410.                  jmp     $+2
  9411.                  inc     dx              ; DX := 3D5H
  9412.                  in      al,dx           ; AL := current value for register
  9413.                  sti
  9414.  
  9415.                  mov     IContValue,al   ; save this value
  9416.  
  9417.  ; save old interrupt 0Ah vector
  9418.  
  9419.                  mov     ax,350Ah        ; AH := 35H (INT 21h function number)
  9420.                                          ; AL := 0AH (interrupt number)
  9421.                  int     21h             ; ES:BX := previous INT 0AH vector
  9422.  
  9423.                  mov     word ptr PrevISR0A,bx
  9424.                  mov     word ptr PrevISR0A+2,es ; save previous vector
  9425.  
  9426.  ; update interrupt 0AH vector with address of this handler
  9427.  
  9428.                  push    ds              ; preserve DS
  9429.                  mov     dx,offset ISR0A
  9430.                  push    cs
  9431.                  pop     ds              ; DS:DX -> ISR0A
  9432.                  mov     ax,250Ah        ; AH := 25H (INT 21H function number)
  9433.                                          ; AL := 0AH (interrupt number)
  9434.                  int     21h             ; update INT 0AH vector
  9435.                  pop     ds              ; restore DS
  9436.  
  9437.  ; enable IRQ2 by zeroing bit 2 of the PIC's mask register
  9438.  
  9439.                  cli                     ; clear interrupts
  9440.                  mov     dx,21h          ; DX := PIC mask register
  9441.                  in      al,dx           ; AL := mask register value
  9442.                  and     al,11111011b    ; reset bit 2
  9443.                  out     dx,al
  9444.  
  9445.  ; enable vertical interrupts
  9446.  
  9447.                  mov     dx,Port3x4      ; DX := CRTC Address port
  9448.                  mov     ax,DefaultICont
  9449.  
  9450.                  and     ah,11001111b
  9451.                  out     dx,ax           ; clear bits 4 and 5 of Int Control r
  9452.                  jmp     $+2             ; wait for MCGA to respond
  9453.                  or      ah,00010000b
  9454.                  out     dx,ax           ; set bit 4
  9455.                  jmp     $+2
  9456.                  sti                     ; enable interrupts
  9457.  
  9458.                  xor     ax,ax           ; AX := 0 (return value)
  9459.  
  9460.  L23:            pop     di              ; restore registers and exit
  9461.                  pop     si
  9462.                  mov     sp,bp
  9463.                  pop     bp
  9464.                  ret
  9465.  
  9466.  _EnableISR0A    ENDP
  9467.  
  9468.  ;
  9469.  ; DisableISR0A -- disable Vertical Interrupt Handler
  9470.  ;
  9471.                  PUBLIC  _DisableISR0A
  9472.  _DisableISR0A   PROC    near
  9473.  
  9474.                  push    bp
  9475.                  mov     bp,sp
  9476.                  push    si
  9477.                  push    di
  9478.                  push    ds
  9479.  
  9480.  ; disable vertical interrupts
  9481.  
  9482.                  cli                     ; disable interrupts
  9483.                  mov     dx,Port3x4
  9484.                  mov     ax,DefaultICont
  9485.                  out     dx,ax           ; restore Interrupt Control register
  9486.                  jmp     $+2
  9487.                  sti                     ; enable interrupts
  9488.  
  9489.  ; restore previous interrupt 0Ah handler
  9490.  
  9491.                  lds     dx,PrevISR0A    ; DS:DX := previous INT 0AH vector
  9492.                  mov     ax,250Ah        ; AH := 25H (INT 21H function number)
  9493.                                          ; AL := 0AH (interrupt number)
  9494.                  int     21h
  9495.  
  9496.                  pop     ds              ; restore registers and exit
  9497.                  pop     di
  9498.                  pop     si
  9499.                  mov     sp,bp
  9500.                  pop     bp
  9501.                  ret
  9502.  
  9503.  _DisableISR0A   ENDP
  9504.  
  9505.  _TEXT           ENDS
  9506.  
  9507.  _DATA           SEGMENT word public 'DATA'
  9508.  
  9509.                  EXTRN   _VRcount:word   ; declared in C caller
  9510.  
  9511.  PrevISR0A       DD      ?               ; save area for old int 0Ah vector
  9512.  Port3x4         DW      ?               ; 3B4h or 3D4h
  9513.  
  9514.  DefaultICont    LABEL   word
  9515.  IContReg        DB      11h             ; Interrupt Control register number
  9516.  IContValue      DB      ?               ; default value for Int Control reg
  9517.  
  9518.  _DATA           ENDS
  9519.  
  9520.                  END
  9521.  
  9522.  \SAMPCODE\VIDEO\12\12_4.ASM
  9523.  
  9524.                  TITLE   'Listing 12-4'
  9525.                  NAME    ScreenOrigin
  9526.                  PAGE    55,132
  9527.  
  9528.  ;
  9529.  ; Name:         ScreenOrigin
  9530.  ;
  9531.  ; Function:     Set screen origin on EGA and VGA
  9532.  ;
  9533.  ; Caller:       Microsoft C:
  9534.  ;
  9535.  ;                       void ScreenOrigin(x,y);
  9536.  ;
  9537.  ;                               int     x,y;    /* pixel x,y coordinates */
  9538.  ;
  9539.  
  9540.  ARGx            EQU     [bp+4]
  9541.  ARGy            EQU     [bp+6]
  9542.  
  9543.  
  9544.  CRT_MODE        EQU     49h             ; addresses in video BIOS data area
  9545.  ADDR_6845       EQU     63h
  9546.  POINTS          EQU     85h
  9547.  BIOS_FLAGS      EQU     89h
  9548.  
  9549.  DGROUP          GROUP   _DATA
  9550.  
  9551.  _TEXT           SEGMENT byte public 'CODE'
  9552.                  ASSUME  cs:_TEXT,ds:DGROUP
  9553.  
  9554.                  PUBLIC  _ScreenOrigin
  9555.  _ScreenOrigin   PROC    near
  9556.  
  9557.                  push    bp              ; preserve caller registers
  9558.                  mov     bp,sp
  9559.                  push    si
  9560.                  push    di
  9561.  
  9562.                  mov     ax,40h
  9563.                  mov     es,ax           ; ES -> video BIOS data area
  9564.                  mov     cl,es:[CRT_MODE]
  9565.  
  9566.                  mov     ax,ARGx         ; AX := pixel x-coordinate
  9567.                  mov     bx,ARGy         ; BX := pixel y-coordinate
  9568.  
  9569.                  cmp     cl,7
  9570.                  ja      L01             ; jump if graphics mode
  9571.  
  9572.                  je      L02             ; jump if monochrome alpha
  9573.  
  9574.                  test    byte ptr es:[BIOS_FLAGS],1
  9575.                  jnz     L02             ; jump if VGA
  9576.  
  9577.                  jmp     short L03
  9578.  
  9579.  ; setup for graphics modes (8 pixels per byte)
  9580.  
  9581.  L01:            mov     cx,8            ; CL := 8 (displayed pixels per byte)
  9582.                                          ; CH := 0 (value for Preset Row Scan)
  9583.                  div     cl              ; AH := bit offset in byte
  9584.                                          ; AL := byte offset in pixel row
  9585.                  mov     cl,ah           ; CL := bit offset (for Horiz Pel Pan
  9586.                  xor     ah,ah
  9587.                  xchg    ax,bx           ; AX := y
  9588.                                          ; BX := byte offset in pixel row
  9589.  
  9590.                  mul     word ptr _BytesPerRow
  9591.                                          ; AX := byte offset of start of row
  9592.                  jmp     short L05
  9593.  
  9594.  ; setup for VGA alphanumeric modes and EGA monochrome alphanumeric mode
  9595.  ;  (9 pixels per byte)
  9596.  
  9597.  L02:                                    ; routine for alpha modes
  9598.                  mov     cx,9            ; CL := 9 (displayed pixels per byte)
  9599.                                          ; CH := 0
  9600.                  div     cl              ; AH := bit offset in byte
  9601.                                          ; AL := byte offset in pixel row
  9602.                  dec     ah              ; AH := -1, 0-7
  9603.                  jns     L04             ; jump if bit offset 0-7
  9604.                  mov     ah,8            ; AH := 8
  9605.                  jmp     short L04
  9606.  
  9607.  ; setup for EGA color alphanumeric modes (8 pixels per byte)
  9608.  
  9609.  L03:            mov     cx,8            ; CL := 8 (displayed pixels per byte)
  9610.                                          ; CH := 0
  9611.                  div     cl              ; AH := bit offset in byte
  9612.                                          ; AL := byte offset in pixel row
  9613.  
  9614.  L04:            mov     cl,ah           ; CL := value for Horiz Pel Pan reg
  9615.                  xor     ah,ah
  9616.                  xchg    ax,bx           ; AX := y
  9617.                                          ; BX := byte offset in row
  9618.                  div     byte ptr es:[POINTS]  ; AL := character row
  9619.                                                ; AH := scan line in char matri
  9620.                  xchg    ah,ch           ; AX := character row
  9621.                                          ; CH := scan line (value for Preset
  9622.                                          ;               Row Scan register)
  9623.                  mul     word ptr _BytesPerRow   ; AX := byte offset of char r
  9624.                  shr     ax,1            ; AX := word offset of character row
  9625.  
  9626.  L05:            call    SetOrigin
  9627.  
  9628.                  pop     di              ; restore registers and exit
  9629.                  pop     si
  9630.                  mov     sp,bp
  9631.                  pop     bp
  9632.                  ret
  9633.  
  9634.  _ScreenOrigin   ENDP
  9635.  
  9636.  
  9637.  SetOrigin       PROC    near            ; Caller:  AX = offset of character r
  9638.                                          ;          BX = byte offset within ro
  9639.                                          ;          CH = Preset Row Scan value
  9640.                                          ;          CL = Horizontal Pel Pan va
  9641.  
  9642.                  add     bx,ax           ; BX := buffer offset
  9643.  
  9644.                  mov     dx,es:[ADDR_6845]  ; CRTC I/O port (3B4H or 3D4H)
  9645.                  add     dl,6            ; video status port (3BAH or 3DAH)
  9646.  
  9647.  ; update Start Address High and Low registers
  9648.  
  9649.  L20:            in      al,dx           ; wait for start of vertical retrace
  9650.                  test    al,8
  9651.                  jz      L20
  9652.  
  9653.  L21:            in      al,dx           ; wait for end of vertical retrace
  9654.                  test    al,8
  9655.                  jnz     L21
  9656.  
  9657.                  cli                     ; disable interrupts
  9658.                  sub     dl,6            ; DX := 3B4H or 3D4H
  9659.  
  9660.                  mov     ah,bh           ; AH := value for Start Address High
  9661.                  mov     al,0Ch          ; AL := Start Address High reg number
  9662.                  out     dx,ax           ; update this register
  9663.  
  9664.                  mov     ah,bl           ; AH := value for Start Address Low
  9665.                  inc     al              ; AL := Start Address Low reg number
  9666.                  out     dx,ax           ; update this register
  9667.                  sti                     ; enable interrupts
  9668.  
  9669.                  add     dl,6            ; DX := video status port
  9670.  
  9671.  L22:            in      al,dx           ; wait for start of vertical retrace
  9672.                  test    al,8
  9673.                  jz      L22
  9674.  
  9675.                  cli                     ; disable interrupts
  9676.  
  9677.                  sub     dl,6            ; DX := 3B4H or 3D4H
  9678.                  mov     ah,ch           ; AH := value for Preset Row Scan reg
  9679.                  mov     al,8            ; AL := Preset Row Scan reg number
  9680.                  out     dx,ax           ; update this register
  9681.  
  9682.                  mov     dl,0C0h         ; DX := 3C0h (Attribute Controller po
  9683.                  mov     al,13h OR 20h   ; AL bit 0-4 := Horiz Pel Pan reg num
  9684.                                          ; AL bit 5 := 1
  9685.                  out     dx,al           ; write Attribute Controller Address
  9686.                                          ;  (Attribute Controller address
  9687.                                          ;    flip-flop has been reset by
  9688.                                          ;    the IN at L22.)
  9689.                  mov     al,cl           ; AL := value for Horiz Pel Pan reg
  9690.                  out     dx,al           ; update this register
  9691.  
  9692.                  sti                     ; re-enable interrupts
  9693.                  ret
  9694.  
  9695.  SetOrigin       ENDP
  9696.  
  9697.  _TEXT           ENDS
  9698.  
  9699.  
  9700.  _DATA           SEGMENT word public 'DATA'
  9701.  
  9702.                  EXTRN   _BytesPerRow:word       ; bytes per pixel row
  9703.  
  9704.  _DATA           ENDS
  9705.  
  9706.                  END
  9707.  
  9708.  \SAMPCODE\VIDEO\13
  9709.  \SAMPCODE\VIDEO\13\13_1B.C
  9710.  
  9711.  /* Listing 13-1b */
  9712.  
  9713.  /* draws an n-leaved rose of the form  rho = a * cos(n*theta) */
  9714.  
  9715.  #define Leaves          (double)11      /* n must be an odd number */
  9716.  
  9717.  #define Xmax            640
  9718.  #define Ymax            350
  9719.  #define PixelValue      14
  9720.  #define ScaleFactor     (double) 1.37
  9721.  
  9722.  main()
  9723.  {
  9724.          int     x,y;                    /* pixel coordinates */
  9725.          double  a;                      /* length of the semi-axis */
  9726.          double  rho,theta;              /* polar coordinates */
  9727.  
  9728.          double  pi = 3.14159265358979;
  9729.          double  sin(),cos();
  9730.  
  9731.          void SetPixel();
  9732.  
  9733.  
  9734.          a = (Ymax / 2) - 1;             /* a reasonable choice for a */
  9735.  
  9736.          for (theta=0.0; theta < pi; theta+=0.001)
  9737.          {
  9738.            rho = a * cos( Leaves*theta );        /* apply the formula */
  9739.  
  9740.            x = rho * cos( theta );       /* convert to rectangular coords */
  9741.            y = rho * sin( theta ) / ScaleFactor;
  9742.  
  9743.            SetPixel( x+Xmax/2, y+Ymax/2, PixelValue );   /* plot the point */
  9744.          }
  9745.  }
  9746.  
  9747.  \SAMPCODE\VIDEO\13\13_6.C
  9748.  
  9749.  /* Listing 13-6 */
  9750.  
  9751.  FilledRectangle( x1, y1, x2, y2, n )
  9752.  int     x1,y1;                  /* upper left corner */
  9753.  int     x2,y2;                  /* lower right corner */
  9754.  int     n;                      /* pixel value */
  9755.  {
  9756.          int     y;
  9757.  
  9758.          for (y=y1; y<=y2; y++)          /* draw rectangle as a set of */
  9759.            Line( x1, y, x2, y, n );      /*  adjacent horizontal lines */
  9760.  }
  9761.  
  9762.  \SAMPCODE\VIDEO\13\13_8.C
  9763.  
  9764.  /* Listing 13-8 */
  9765.  
  9766.  
  9767.      HWND hWnd;                      /* window handle */
  9768.      HDC  hDC;                       /* device context handle */
  9769.  
  9770.      struct
  9771.      {
  9772.        HDC hdc;                      /* device context handle */
  9773.        BOOL fErase;
  9774.        RECT rcPaint;
  9775.        BOOL fRestore;
  9776.        BOOL fIncUpdate;
  9777.        BYTE rgbReserved[16];
  9778.      }                         ps;   /* "paint structure" */
  9779.  
  9780.  
  9781.      /* create a window */
  9782.  
  9783.      hWnd = CreateWindow( ... );
  9784.      .
  9785.      .
  9786.      .
  9787.  
  9788.      /* initialize device context for window */
  9789.  
  9790.      BeginPaint( hWnd, &ps );
  9791.      hDC = ps.hdc;
  9792.      .
  9793.      .
  9794.      .
  9795.  
  9796.      /* associate attributes with device context */
  9797.  
  9798.      hpen = CreatePen( PS_SOLID, 0, GetSysColor(COLOR_WINDOWTEXT) );
  9799.      SelectObject( hDC, (HANDLE)hpen );
  9800.  
  9801.      hbr = CreateSolidBrush( GetNearestColor(hDC,RectFillColor) );
  9802.      SelectObject( hDC, (HANDLE)hbr );
  9803.      .
  9804.      .
  9805.      .
  9806.  
  9807.      /* draw a filled rectangle */
  9808.  
  9809.      Rectangle( hDC, 0, 0, 100, 100 );
  9810.  
  9811.  \SAMPCODE\VIDEO\13\13_1A.ASM
  9812.  
  9813.                  TITLE   'Listing 13-1a'
  9814.                  NAME    SetPixel
  9815.                  PAGE    55,132
  9816.  
  9817.  ;
  9818.  ; Name:         SetPixel
  9819.  ;
  9820.  ; Function:     Set the value of a pixel in native EGA graphics modes.
  9821.  ;
  9822.  ; Caller:       Microsoft C (small memory model):
  9823.  ;
  9824.  ;                       void SetPixel(x,y,n);
  9825.  ;
  9826.  ;                       int x,y;                /* pixel coordinates */
  9827.  ;
  9828.  ;                       int n;                  /* pixel value */
  9829.  ;
  9830.  ; Notes:        This is the same routine as in Chapter 5.
  9831.  ;
  9832.  
  9833.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  9834.  ARGy            EQU     word ptr [bp+6]
  9835.  ARGn            EQU     byte ptr [bp+8]
  9836.  
  9837.  RMWbits         EQU     0               ; read-modify-write bits
  9838.  
  9839.  
  9840.  _TEXT           SEGMENT byte public 'CODE'
  9841.                  ASSUME  cs:_TEXT
  9842.  
  9843.                  EXTRN   PixelAddr:near
  9844.  
  9845.                  PUBLIC  _SetPixel
  9846.  _SetPixel       PROC    near
  9847.  
  9848.                  push    bp              ; preserve caller registers
  9849.                  mov     bp,sp
  9850.  
  9851.                  mov     ax,ARGy         ; AX := y
  9852.                  mov     bx,ARGx         ; BX := x
  9853.                  call    PixelAddr       ; AH := bit mask
  9854.                                          ; ES:BX -> buffer
  9855.                                          ; CL := # bits to shift left
  9856.  
  9857.  ; set Graphics Controller Bit Mask register
  9858.  
  9859.                  shl     ah,cl           ; AH := bit mask in proper position
  9860.                  mov     dx,3CEh         ; GC address register port
  9861.                  mov     al,8            ; AL := Bit Mask register number
  9862.                  out     dx,ax
  9863.  
  9864.  ; set Graphics Controller Mode register
  9865.  
  9866.                  mov     ax,0005h        ; AL :=  Mode register number
  9867.                                          ; AH :=  Write Mode 0 (bits 0,1)
  9868.                                          ;        Read Mode 0 (bit 3)
  9869.                  out     dx,ax
  9870.  
  9871.  ; set Data Rotate/Function Select register
  9872.  
  9873.                  mov     ah,RMWbits      ; AH := Read-Modify-Write bits
  9874.                  mov     al,3            ; AL := Data Rotate/Function Select r
  9875.                  out     dx,ax
  9876.  
  9877.  ; set Set/Reset and Enable Set/Reset registers
  9878.  
  9879.                  mov     ah,ARGn         ; AH := pixel value
  9880.                  mov     al,0            ; AL := Set/Reset reg number
  9881.                  out     dx,ax
  9882.  
  9883.                  mov     ax,0F01h        ; AH := value for Enable Set/Reset (a
  9884.                                          ;  bit planes enabled)
  9885.                                          ; AL := Enable Set/Reset reg number
  9886.                  out     dx,ax
  9887.  
  9888.  ; set the pixel value
  9889.  
  9890.                  or      es:[bx],al      ; load latches during CPU read
  9891.                                          ; update latches and bit planes durin
  9892.                                          ;  CPU write
  9893.  
  9894.  ; restore default Graphics Controller registers
  9895.  
  9896.                  mov     ax,0FF08h       ; default Bit Mask
  9897.                  out     dx,ax
  9898.  
  9899.                  mov     ax,0005         ; default Mode register
  9900.                  out     dx,ax
  9901.  
  9902.                  mov     ax,0003         ; default Function Select
  9903.                  out     dx,ax
  9904.  
  9905.                  mov     ax,0001         ; default Enable Set/Reset
  9906.                  out     dx,ax
  9907.  
  9908.                  mov     sp,bp           ; restore caller registers and return
  9909.                  pop     bp
  9910.                  ret
  9911.  
  9912.  _SetPixel       ENDP
  9913.  
  9914.  _TEXT           ENDS
  9915.  
  9916.                  END
  9917.  
  9918.  \SAMPCODE\VIDEO\13\13_5.ASM
  9919.  
  9920.                  TITLE   'Listing 13-5'
  9921.                  NAME    SetPixel
  9922.                  PAGE    55,132
  9923.  
  9924.  ;
  9925.  ; Name:         SetPixel
  9926.  ;
  9927.  ; Function:     Set the value of a pixel in native EGA graphics modes.
  9928.  ;
  9929.  ; Caller:       Memory-resident routine invoked via interrupt 60H:
  9930.  ;
  9931.  ;                       mov ax,PixelX      ; pixel x-coordinate
  9932.  ;                       mov bx,PixelY      ; pixel y-coordinate
  9933.  ;                       mov cx,PixelValue  ; pixel value
  9934.  ;
  9935.  ; Notes:        - Assemble and link to create SETPIXEL.EXE.
  9936.  ;               - Execute once to make SetPixel resident in memory and to poi
  9937.  ;                  the INT 60H vector to the RAM-resident code.
  9938.  ;               - Requires MS-DOS version 2.0 or later.
  9939.  ;
  9940.  
  9941.  RMWbits         EQU     0
  9942.  
  9943.  _TEXT           SEGMENT byte public 'CODE'
  9944.                  ASSUME  cs:_TEXT
  9945.  
  9946.                  EXTRN   PixelAddr:near
  9947.  
  9948.                  PUBLIC  SetPixel
  9949.  SetPixel        PROC    near            ; RAM-resident interrupt 60H handler
  9950.  
  9951.                  sti                     ; enable interrupts
  9952.                  push    ax              ; preserve caller registers on
  9953.                  push    bx              ;  caller's stack
  9954.                  push    cx
  9955.                  push    dx
  9956.  
  9957.                  push    cx              ; preserve pixel value on stack
  9958.  
  9959.                  call    PixelAddr       ; compute pixel address
  9960.                  shl     ah,cl
  9961.  
  9962.                  mov     dx,3CEh         ; program the Graphics Controller
  9963.                  mov     al,8            ; AL := Bit Mask register number
  9964.                  out     dx,ax
  9965.  
  9966.                  mov     ax,0005h
  9967.                  out     dx,ax
  9968.  
  9969.                  mov     ah,RMWbits      ; AH := Read-Modify-Write bits
  9970.                  mov     al,3            ; AL := Data Rotate/Function Select r
  9971.                  out     dx,ax
  9972.  
  9973.                  pop     ax
  9974.                  mov     ah,al           ; AH := pixel value
  9975.                  mov     al,0
  9976.                  out     dx,ax
  9977.  
  9978.                  mov     ax,0F01h
  9979.                  out     dx,ax
  9980.  
  9981.                  or      es:[bx],al      ; set the pixel value
  9982.  
  9983.                  mov     ax,0FF08h       ; restore default Graphics Controller
  9984.                  out     dx,ax           ;  values
  9985.  
  9986.                  mov     ax,0005
  9987.                  out     dx,ax
  9988.  
  9989.                  mov     ax,0003
  9990.                  out     dx,ax
  9991.  
  9992.                  mov     ax,0001
  9993.                  out     dx,ax
  9994.  
  9995.                  pop     dx              ; restore caller registers and return
  9996.                  pop     cx
  9997.                  pop     bx
  9998.                  pop     ax
  9999.                  iret
  10000.  
  10001.  SetPixel        ENDP
  10002.  
  10003.  _TEXT           ENDS
  10004.  
  10005.  
  10006.  TRANSIENT_TEXT  SEGMENT para
  10007.                  ASSUME  cs:TRANSIENT_TEXT,ss:STACK
  10008.  
  10009.  Install         PROC    near
  10010.  
  10011.                  mov     ax,2560h        ; AH := 25H (INT 21H function number)
  10012.                                          ; AL := 60H (interrupt number)
  10013.                  mov     dx,seg _TEXT
  10014.                  mov     ds,dx
  10015.                  mov     dx,offset _TEXT:SetPixel   ; DS:DX -> interrupt handl
  10016.  
  10017.                  int     21h             ; point INT 60H vector to
  10018.                                          ;  SetPixel routine
  10019.  
  10020.                  mov     dx,cs           ; DX := segment of start of transient
  10021.                                          ;  (discardable) portion of program
  10022.                  mov     ax,es           ; ES := Program Segment Prefix
  10023.                  sub     dx,ax           ; DX := size of RAM-resident portion
  10024.                  mov     ax,3100h        ; AH := 31H (INT 21H function number)
  10025.                                          ; AL := 0 (return code)
  10026.                  int     21h             ; Terminate but Stay Resident
  10027.  
  10028.  Install         ENDP
  10029.  
  10030.  TRANSIENT_TEXT  ENDS
  10031.  
  10032.  STACK           SEGMENT para stack 'STACK'
  10033.  
  10034.                  DB      80h dup(?)      ; stack space for transient portion
  10035.                                          ;  of program
  10036.  STACK           ENDS
  10037.  
  10038.                  END     Install
  10039.  
  10040.  \SAMPCODE\VIDEO\13\13_7.ASM
  10041.  
  10042.                  TITLE   'Listing 13-7'
  10043.                  NAME    dgisrect
  10044.                  PAGE    55,132
  10045.  
  10046.  ;
  10047.  ; Name:         dgisrect
  10048.  ;
  10049.  ; Function:     draw a filled rectangle using DGIS
  10050.  ;
  10051.  ; Notes:        assemble and link to create DGISRECT.EXE
  10052.  ;
  10053.  
  10054.  CR              EQU     0Dh
  10055.  LF              EQU     0Ah
  10056.  
  10057.  _TEXT           SEGMENT byte public 'CODE'
  10058.                  ASSUME  cs:_TEXT,ds:_DATA,ss:STACK
  10059.  
  10060.  EntryPoint      PROC    far
  10061.  
  10062.                  mov     ax,seg _DATA
  10063.                  mov     ds,ax                   ; DS -> _DATA
  10064.                  push    ss
  10065.                  pop     es                      ; ES -> stack segment
  10066.  
  10067.  ; look for installed DGIS devices
  10068.  
  10069.                  xor     dx,dx                   ; DX = 0 (buffer length)
  10070.                  xor     cx,cx                   ; CX = 0
  10071.                  xor     bx,bx                   ; BX = 0
  10072.                  mov     ax,6A00h                ; AX = DGIS opcode (Inquire
  10073.                                                  ;       Available Devices)
  10074.                  int     10h
  10075.                  or      cx,cx
  10076.                  jnz     L01                     ; jump if device(s) installed
  10077.  
  10078.                  mov     dx,offset _DATA:Msg0
  10079.                  jmp     ErrorExit
  10080.  
  10081.  ; find a graphics output device in the list of installed DGIS devices
  10082.  
  10083.  L01:            inc     cx                      ; CX = (# of bytes in list) +
  10084.                  and     cx,0FFFEh               ; CX = even number of bytes
  10085.                  mov     bp,sp
  10086.                  sub     sp,cx                   ; establish stack frame
  10087.                                                  ;  (SS:BP -> end of frame)
  10088.                  mov     di,sp                   ; ES:DI -> start of stack fra
  10089.  
  10090.                  push    di                      ; save for later
  10091.                  mov     dx,cx                   ; DX = size of buffer
  10092.                  xor     cx,cx
  10093.                  xor     bx,bx
  10094.                  mov     ax,6A00h                ; AX = DGIS opcode (Inquire
  10095.                                                  ;       Available Devices)
  10096.                  int     10h                     ; get device list at ES:DI
  10097.                  pop     di                      ; ES:DI -> device list
  10098.  
  10099.  L02:            cmp     word ptr es:[di+2],0    ; is this a graphics device?
  10100.                  je      L04                     ; jump if so
  10101.  
  10102.                  sub     bx,es:[di]              ; BX = bytes remaining in lis
  10103.                  jnz     L03                     ; jump if more devices in lis
  10104.  
  10105.                  mov     dx,offset _DATA:Msg1
  10106.                  jmp     ErrorExit
  10107.  
  10108.  L03:            add     di,es:[di]              ; ES:DI -> next device in lis
  10109.                  jmp     L02
  10110.  
  10111.  ; establish a logical connection to the graphics device
  10112.  ;  using the first available configuration on the device
  10113.  
  10114.  L04:            les     di,es:[di+6]            ; ES:DI -> device entry point
  10115.                  mov     word ptr GrDevEntry,di
  10116.                  mov     word ptr GrDevEntry+2,es  ; save entry point
  10117.  
  10118.                  mov     cx,0                    ; CX = first configuration in
  10119.                  mov     ax,0027h                ; AX = DGIS opcode (Connect)
  10120.                  call    dword ptr GrDevEntry    ; connect to graphics device
  10121.                  cmp     bx,-1                   ; test returned handle
  10122.                  jne     L05                     ; jump if connected
  10123.  
  10124.                  mov     dx,offset _DATA:Msg2
  10125.                  jmp     ErrorExit
  10126.  
  10127.  L05:            mov     ChannelHandle,bx        ; save the handle for later
  10128.                  mov     ax,001Bh                ; AX = DGIS opcode (Init DGI)
  10129.                  call    dword ptr GrDevEntry    ; initialize the device with
  10130.                                                  ;  default attributes
  10131.  
  10132.  ; draw a filled rectangle using default attributes
  10133.  
  10134.                  mov     di,100                  ; DI = lower right corner y
  10135.                  mov     si,100                  ; SI = lower right corner x
  10136.                  mov     dx,0                    ; DX = upper left corner y
  10137.                  mov     cx,0                    ; CX = upper left corner x
  10138.                  mov     bx,ChannelHandle        ; BX = handle
  10139.                  mov     ax,003Fh                ; AX = DGIS opcode (Output
  10140.                                                  ;       Filled Rectangle)
  10141.                  call    dword ptr GrDevEntry
  10142.  
  10143.  ; disconnect and exit
  10144.  
  10145.                  mov     bx,ChannelHandle        ; BX = handle
  10146.                  mov     ax,002Bh                ; AX = DGIS opcode (Disconnec
  10147.                  call    dword ptr GrDevEntry
  10148.  
  10149.  Lexit:          mov     ax,4C00h
  10150.                  int     21h                     ; return to DOS
  10151.  
  10152.  ErrorExit:      mov     ah,9
  10153.                  int     21h                     ; display error message
  10154.                  mov     ax,4C01h
  10155.                  int     21h                     ; return to DOS
  10156.  
  10157.  EntryPoint      ENDP
  10158.  
  10159.  _TEXT           ENDS
  10160.  
  10161.  
  10162.  _DATA           SEGMENT para public 'DATA'
  10163.  
  10164.  GrDevEntry      DD      ?                       ; graphics device entry point
  10165.  ChannelHandle   DW      ?                       ; handle to connected device
  10166.                                                  ;  configuration
  10167.  
  10168.  Msg0            DB      CR,LF,'No DGIS devices installed',CR,LF,'$'
  10169.  Msg1            DB      CR,LF,'No graphics devices installed',CR,LF,'$'
  10170.  Msg2            DB      CR,LF,'Can''t connect to graphics device',CR,LF,'$'
  10171.  
  10172.  _DATA           ENDS
  10173.  
  10174.  
  10175.  STACK           SEGMENT stack 'STACK'
  10176.  
  10177.                  DB      400h dup(?)
  10178.  
  10179.  STACK           ENDS
  10180.  
  10181.                  END     EntryPoint
  10182.  
  10183.  \SAMPCODE\VIDEO\2
  10184.  \SAMPCODE\VIDEO\2\2_2.ASM
  10185.  
  10186.                  TITLE   'Listing 2-2'
  10187.                  NAME    HRTimeout
  10188.                  PAGE    55,132
  10189.  
  10190.  ;
  10191.  ; Name:         HRTimeout
  10192.  ;
  10193.  ; Function:     Determine a timeout value for the horizontal blanking interva
  10194.  ;
  10195.  ; Caller:       Microsoft C:
  10196.  ;
  10197.  ;                       int HRTimeout();
  10198.  ;
  10199.  
  10200.  _TEXT           SEGMENT byte public 'CODE'
  10201.                  ASSUME  cs:_TEXT
  10202.  
  10203.                  PUBLIC  _HRTimeout
  10204.  _HRTimeout      PROC    near
  10205.  
  10206.                  push    bp              ; usual C prologue to establish
  10207.                  mov     bp,sp           ;  stack frame
  10208.  
  10209.                  mov     ax,40h
  10210.                  mov     es,ax           ; ES := video BIOS data segment
  10211.  
  10212.                  mov     dx,es:[63h]     ; DX := port for CRTC Address registe
  10213.                  add     dl,6            ; DX := port for CRTC Status register
  10214.  
  10215.  ; synchronize with start of refresh cycle
  10216.  
  10217.  L01:            in      al,dx           ; AL := CRTC status
  10218.                  test    al,8            ; test bit 3
  10219.                  jz      L01             ; loop while NOT in vertical retrace
  10220.  
  10221.  L02:            in      al,dx
  10222.                  test    al,8
  10223.                  jnz     L02             ; loop during vertical retrace
  10224.  
  10225.  ; synchronize with a horizontal scan and time the horizontal blanking interva
  10226.  
  10227.                  mov     cx,0FFFFh       ; CX := loop counter
  10228.  
  10229.                  cli                     ; disable interrupts
  10230.  
  10231.  L03:            in      al,dx
  10232.                  test    al,1
  10233.                  jnz     L03             ; loop while Display Enable is inacti
  10234.  
  10235.  L04:            in      al,dx
  10236.                  test    al,1
  10237.                  jz      L04             ; loop while Display Enable is active
  10238.  
  10239.  L05:            in      al,dx
  10240.                  test    al,1
  10241.                  loopnz  L05             ; decrement CX and loop while Display
  10242.                                          ;  Enable is inactive
  10243.  
  10244.                  sti                     ; enable interrupts again
  10245.  
  10246.                  mov     ax,cx           ; AX := loop counter
  10247.                  neg     ax
  10248.                  shl     ax,1            ; AX := timeout value
  10249.  
  10250.                  mov     sp,bp           ; discard stack frame and return to C
  10251.                  pop     bp
  10252.                  ret
  10253.  
  10254.  _HRTimeout      ENDP
  10255.  
  10256.  _TEXT           ENDS
  10257.  
  10258.                  END
  10259.  
  10260.  \SAMPCODE\VIDEO\2\2_4.ASM
  10261.  
  10262.                  TITLE   'Listing 2-4'
  10263.                  NAME    HercGraphMode
  10264.                  PAGE    55,132
  10265.  
  10266.  ;
  10267.  ; Name:         HercGraphMode
  10268.  ;
  10269.  ; Function:     Establish Hercules 720x348 graphics mode on HGC, HGC+, InColo
  10270.  ;
  10271.  ; Caller:       Microsoft C:
  10272.  ;
  10273.  ;                               void HercGraphMode();
  10274.  ;
  10275.  
  10276.  DGROUP          GROUP   _DATA
  10277.  
  10278.  _TEXT           SEGMENT byte public 'CODE'
  10279.                  ASSUME  cs:_TEXT,ds:DGROUP
  10280.  
  10281.                  PUBLIC  _HercGraphMode
  10282.  _HercGraphMode  PROC    near
  10283.  
  10284.                  push    bp              ; preserve caller registers
  10285.                  mov     bp,sp
  10286.                  push    si
  10287.                  push    di
  10288.  
  10289.  ; Update Video BIOS Data Area with reasonable values
  10290.  
  10291.                  mov     ax,40h
  10292.                  mov     es,ax
  10293.                  mov     di,49h          ; ES:DI := 0040:0049 (BIOS data area)
  10294.  
  10295.                  mov     si,offset DGROUP:BIOSData
  10296.                  mov     cx,BIOSDataLen
  10297.                  rep     movsb           ; update BIOS data area
  10298.  
  10299.  ; Set Configuration Switch
  10300.  
  10301.                  mov     dx,3BFh         ; DX := Configuration Switch port
  10302.                  mov     al,1            ; AL bit 1 := 0 (exclude 2nd 32K of
  10303.                                          ;                 video buffer)
  10304.                                          ; AL bit 0 := 1 (allow graphics mode
  10305.                  out     dx,al           ;                setting via 3B8h)
  10306.  
  10307.  ; Blank the screen to avoid interference during CRTC programming
  10308.  
  10309.                  mov     dx,3B8h         ; DX := CRTC Mode Control Register po
  10310.                  xor     al,al           ; AL bit 3 := 0 (disable video signal
  10311.                  out     dx,al           ; blank the screen
  10312.  
  10313.  ; Program the CRTC
  10314.  
  10315.                  sub     dl,4            ; DX := CRTC Address Reg port 3B4h
  10316.  
  10317.                  mov     si,offset DGROUP:CRTCParms
  10318.                  mov     cx,CRTCParmsLen
  10319.  
  10320.  L01:            lodsw                   ; AL := CRTC register number
  10321.                                          ; AH := data for this register
  10322.                  out     dx,ax
  10323.                  loop    L01
  10324.  
  10325.  ; Set graphics mode
  10326.  
  10327.                  add     dl,4            ; DX := 3B8h (CRTC Mode Control Reg)
  10328.                  mov     al,CRTMode      ; AL bit 1 = 1 (enable graphics mode)
  10329.                                          ;    bit 3 = 1 (enable video)
  10330.                  out     dx,al
  10331.  
  10332.                  pop     di              ; restore registers and exit
  10333.                  pop     si
  10334.                  mov     sp,bp
  10335.                  pop     bp
  10336.                  ret
  10337.  
  10338.  _HercGraphMode  ENDP
  10339.  
  10340.  _TEXT           ENDS
  10341.  
  10342.  
  10343.  _DATA           SEGMENT word public 'DATA'
  10344.  
  10345.                                  ; These are the parameters recommended by Her
  10346.                                  ; They are based on 16 pixels/character and
  10347.                                  ; 4 scan lines per character.
  10348.  
  10349.  CRTCParms       DB      00h,35h ; Horizontal Total:  54 characters
  10350.                  DB      01h,2Dh ; Horizontal Displayed:  45 characters
  10351.                  DB      02h,2Eh ; Horizontal Sync Position:  at 46th characte
  10352.                  DB      03h,07h ; Horizontal Sync Width:  7 character clocks
  10353.  
  10354.                  DB      04h,5Bh ; Vertical Total:  92 characters (368 lines)
  10355.                  DB      05h,02h ; Vertical Adjust:  2 scan lines
  10356.                  DB      06h,57h ; Vertical Displayed:  87 character rows (348
  10357.                  DB      07h,57h ; Vertical Sync Position:  after 87th char ro
  10358.  
  10359.                  DB      09h,03h ; Max Scan Line:  4 scan lines per char
  10360.  
  10361.  CRTCParmsLen    EQU     ($-CRTCParms)/2
  10362.  
  10363.  BIOSData        DB      7       ; CRT_MODE
  10364.                  DW      80      ; CRT_COLS
  10365.                  DW      8000h   ; CRT_LEN
  10366.                  DW      0       ; CRT_START
  10367.                  DW      8 dup(0) ; CURSOR_POSN
  10368.                  DW      0       ; CURSOR_MODE
  10369.                  DB      0       ; ACTIVE_PAGE
  10370.  CRTCAddr        DW      3B4h    ; ADDR_6845
  10371.  CRTMode         DB      0Ah     ; CRT_MODE_SET (value for port 3B8h)
  10372.                  DB      0       ; CRT_PALETTE (unused)
  10373.  
  10374.  BIOSDataLen     EQU     $-BIOSData
  10375.  
  10376.  _DATA           ENDS
  10377.  
  10378.                  END
  10379.  
  10380.  \SAMPCODE\VIDEO\3
  10381.  \SAMPCODE\VIDEO\3\3_10.ASM
  10382.  
  10383.                  TITLE   'Listing 3-10'
  10384.                  NAME    DisplayText
  10385.                  PAGE    55,132
  10386.  
  10387.  ;
  10388.  ; Name:         DisplayText
  10389.  ;
  10390.  ; Function:     Display an alphanumeric string without interference on the CG
  10391.  ;
  10392.  ; Caller:       Microsoft C:
  10393.  ;
  10394.  ;                       int DisplayText(buf,n,offset);
  10395.  ;
  10396.  ;                       char *buf;              /* buffer containing text in
  10397.  ;                                                  CGA alphanumeric format
  10398.  ;                                                  (alternating character cod
  10399.  ;                                                  and attribute bytes)
  10400.  ;                                               */
  10401.  ;
  10402.  ;                       int n;                  /* buffer length in bytes */
  10403.  ;
  10404.  ;                       unsigned int offset;    /* offset into video buffer *
  10405.  ;
  10406.  
  10407.  ARGbuf          EQU     word ptr [bp+4]
  10408.  ARGn            EQU     word ptr [bp+6]
  10409.  ARGoffset       EQU     word ptr [bp+8]
  10410.  TIMEOUT         EQU     6               ; horizontal timeout loop limit
  10411.  VBcount         EQU     250             ; number of words to write during
  10412.                                          ;  vertical blanking interval
  10413.  
  10414.  _TEXT           SEGMENT byte public 'CODE'
  10415.                  ASSUME  cs:_TEXT
  10416.  
  10417.                  PUBLIC  _DisplayText
  10418.  _DisplayText    PROC    near
  10419.  
  10420.                  push    bp              ; usual C prologue to establish
  10421.                  mov     bp,sp           ;  stack frame and preserve registers
  10422.                  push    si
  10423.                  push    di
  10424.  
  10425.                  mov     ax,0B800h
  10426.                  mov     es,ax
  10427.                  mov     di,ARGoffset    ; ES:DI -> destination in video buffe
  10428.                  mov     si,ARGbuf       ; DS:SI -> source buffer
  10429.                  mov     cx,ARGn
  10430.                  shr     cx,1            ; CX := buffer length in words
  10431.  
  10432.                  mov     dx,3DAh         ; DX := CGA Status Port
  10433.  
  10434.  ; write during remaining vertical blanking interval
  10435.  
  10436.  L01:            mov     bx,cx           ; preserve buffer length in BX
  10437.                  mov     cx,TIMEOUT      ; CX := horizontal timeout
  10438.                  cli                     ; disable interrupts during loop
  10439.  
  10440.  L02:            in      al,dx           ; AL := video status
  10441.                  test    al,1
  10442.                  loopnz  L02             ; loop while Display Enable inactive
  10443.                  jz      L03             ; jump if loop did not time out
  10444.  
  10445.                  movsw                   ; copy one word
  10446.                  sti
  10447.                  mov     cx,bx           ; CX := buffer length
  10448.                  loop    L01
  10449.  
  10450.                  jmp     short L10       ; exit (entire string copied)
  10451.  
  10452.  ; write during horizontal blanking intervals
  10453.  
  10454.  L03:            sti
  10455.                  mov     cx,bx           ; restore CX
  10456.  
  10457.  L04:            lodsw                   ; AL := character code
  10458.                                          ; AH := attribute
  10459.                  mov     bx,ax           ; BX := character and attribute
  10460.                  push    cx              ; preserve word loop counter
  10461.                  mov     cx,TIMEOUT      ; CX := timeout loop limit
  10462.  
  10463.                  cli                     ; clear interrupts during one scan li
  10464.  L05:            in      al,dx
  10465.                  test    al,1
  10466.                  loopnz  L05             ; loop during horizontal blanking
  10467.                                          ;  until timeout occurs
  10468.                  jnz     L07             ; jump if timed out (vertical
  10469.                                          ;  blanking has started)
  10470.  L06:            in      al,dx
  10471.                  test    al,1
  10472.                  jz      L06             ; loop while Display Enable is active
  10473.  
  10474.                  xchg    ax,bx           ; AX := character & attribute
  10475.                  stosw                   ; copy 2 bytes to display buffer
  10476.  
  10477.                  sti                     ; restore interrupts
  10478.                  pop     cx              ; CX := word loop counter
  10479.                  loop    L04
  10480.  
  10481.                  jmp     short L10       ; exit (entire string copied)
  10482.  
  10483.  ; write during entire vertical blanking interval
  10484.  
  10485.  L07:            pop     bx              ; BX := word loop counter
  10486.                  dec     si
  10487.                  dec     si              ; DS:SI -> word to copy from buffer
  10488.  
  10489.                  mov     cx,VBcount      ; CX := # of words to copy
  10490.                  cmp     bx,cx
  10491.                  jnb     L08             ; jump if more than VBcount words rem
  10492.                                          ;  in buffer
  10493.                  mov     cx,bx           ; CX := # of remaining words in buffe
  10494.                  xor     bx,bx           ; BX := 0
  10495.                  jmp     short L09
  10496.  
  10497.  L08:            sub     bx,cx           ; BX := (# of remaining words) - VBco
  10498.  
  10499.  L09:            rep     movsw           ; copy to video buffer
  10500.  
  10501.                  mov     cx,bx           ; CX := # of remaining words
  10502.                  test    cx,cx
  10503.                  jnz     L01             ; loop until buffer is displayed
  10504.  
  10505.  L10:            pop     di              ; usual C epilogue to restore registe
  10506.                  pop     si              ;  and discard stack frame
  10507.                  mov     sp,bp
  10508.                  pop     bp
  10509.                  ret
  10510.  
  10511.  _DisplayText    ENDP
  10512.  
  10513.  _TEXT           ENDS
  10514.  
  10515.                  END
  10516.  
  10517.  \SAMPCODE\VIDEO\3\3_9.ASM
  10518.  
  10519.                  TITLE   'Listing 3-9'
  10520.                  NAME    DisplayText
  10521.                  PAGE    55,132
  10522.  
  10523.  ;
  10524.  ; Name:         DisplayText
  10525.  ;
  10526.  ; Function:     Display an alphanumeric string without interference on the CG
  10527.  ;
  10528.  ; Caller:       Microsoft C:
  10529.  ;
  10530.  ;                       int DisplayText1(buf,n,offset);
  10531.  ;
  10532.  ;                       char *buf;              /* buffer containing text in
  10533.  ;                                                  CGA alphanumeric format
  10534.  ;                                                  (alternating character cod
  10535.  ;                                                  and attribute bytes
  10536.  ;                                               */
  10537.  ;
  10538.  ;                       int n;                  /* buffer length in bytes */
  10539.  ;
  10540.  ;                       unsigned int offset;    /* offset into video buffer *
  10541.  ;
  10542.  
  10543.  Set80X25        EQU     (1 SHL 0)       ; bit masks for Mode Control Register
  10544.  Set320X200      EQU     (1 SHL 1)
  10545.  BlackAndWhite   EQU     (1 SHL 2)
  10546.  EnableVideo     EQU     (1 SHL 3)
  10547.  Set640X200      EQU     (1 SHL 4)
  10548.  EnableBlink     EQU     (1 SHL 5)
  10549.  
  10550.  ARGbuf          EQU     word ptr [bp+4] ; stack frame addressing
  10551.  ARGn            EQU     word ptr [bp+6]
  10552.  ARGoffset       EQU     word ptr [bp+8]
  10553.  TIMEOUT         EQU     5               ; Horizontal Retrace timeout loop lim
  10554.  
  10555.  
  10556.  _TEXT           SEGMENT byte public 'CODE'
  10557.                  ASSUME  cs:_TEXT
  10558.  
  10559.                  PUBLIC  _DisplayText
  10560.  _DisplayText    PROC    near
  10561.  
  10562.                  push    bp              ; usual C prologue to establish
  10563.                  mov     bp,sp           ;  stack frame and preserve registers
  10564.                  push    si
  10565.                  push    di
  10566.  
  10567.                  mov     ax,0B800h
  10568.                  mov     es,ax
  10569.                  mov     di,ARGoffset    ; ES:DI -> destination in video buffe
  10570.                  mov     si,ARGbuf       ; DS:SI -> source buffer
  10571.                  mov     bx,ARGn
  10572.                  shr     bx,1            ; BX := buffer length in words
  10573.  
  10574.                  mov     dx,3DAh         ; DX := CGA Status Port
  10575.  
  10576.  ; wait for start of vertical blanking period
  10577.  
  10578.  L01:            mov     cx,TIMEOUT      ; CX := loop counter (timeout value)
  10579.  
  10580.  L02:            in      al,dx           ; AL := video status
  10581.                  test    al,8
  10582.                  jnz     L02             ; loop if in vertical retrace
  10583.                  test    al,1
  10584.                  jz      L02             ; loop if not in horizontal retrace
  10585.  
  10586.                  cli                     ; disable interrupts during horiz ret
  10587.  
  10588.  L03:            in      al,dx
  10589.                  test    al,1
  10590.                  loopnz  L03             ; loop until end of retrace or timeou
  10591.  
  10592.                  sti                     ; re-enable interrupts
  10593.  
  10594.                  jz      L01             ; loop if no timeout
  10595.  
  10596.  ; blank the display
  10597.  
  10598.                  mov     dl,0D8h         ; DX := 3D8h (Mode Control register)
  10599.                  mov     al,(Set80X25 OR EnableBlink)
  10600.                  out     dx,al           ; turn video off
  10601.  
  10602.  ; copy the data to the video buffer
  10603.  
  10604.                  mov     cx,bx           ; CX := buffer length in words
  10605.                  rep     movsw
  10606.  
  10607.  ; re-enable the display
  10608.  
  10609.                  or      al,EnableVideo
  10610.                  out     dx,al
  10611.  
  10612.                  pop     di              ; usual C epilogue to restore registe
  10613.                  pop     si              ;  and discard stack frame
  10614.                  mov     sp,bp
  10615.                  pop     bp
  10616.                  ret
  10617.  
  10618.  _DisplayText    ENDP
  10619.  
  10620.  _TEXT           ENDS
  10621.  
  10622.                  END
  10623.  
  10624.  \SAMPCODE\VIDEO\4
  10625.  \SAMPCODE\VIDEO\4\4_1.ASM
  10626.  
  10627.                  TITLE   'Listing 4-1'
  10628.                  NAME    PixelAddr04
  10629.                  PAGE    55,132
  10630.  
  10631.  ;
  10632.  ; Name:         PixelAddr04
  10633.  ;
  10634.  ; Function:     Determine buffer address of pixel in 320x200 4-color mode
  10635.  ;
  10636.  ; Caller:       AX = y-coordinate (0-199)
  10637.  ;               BX = x-coordinate (0-319)
  10638.  ;
  10639.  ; Returns:      AH = bit mask
  10640.  ;               BX = byte offset in buffer
  10641.  ;               CL = number of bits to shift left
  10642.  ;               ES = video buffer segment
  10643.  ;
  10644.  
  10645.  
  10646.  OriginOffset    EQU     0               ; byte offset of (0,0)
  10647.  VideoBufferSeg  EQU     0B800h
  10648.  
  10649.  _TEXT           SEGMENT byte public 'CODE'
  10650.                  ASSUME  cs:_TEXT
  10651.  
  10652.                  PUBLIC  PixelAddr04
  10653.  PixelAddr04     PROC    near
  10654.  
  10655.                  mov     cl,bl           ; CL := low-order byte of x
  10656.  
  10657.                  xchg    ah,al           ; AX := 100h * y
  10658.                  shr     ax,1            ; AL := 80h * (y&1)
  10659.                  add     bh,al           ; BX := x + 8000h*(y&1)
  10660.                  xor     al,al           ; AX := 100h*(y/2)
  10661.                  add     bx,ax           ; BX := x + 8000h*(y&1) + 100h*(y/2)
  10662.                  shr     ax,1
  10663.                  shr     ax,1            ; AX := 40h*(y/2)
  10664.                  add     bx,ax           ; BX := x + 8000h*(y&1) + 140h*(y/2)
  10665.                  shr     bx,1
  10666.                  shr     bx,1            ; BX := x/4 + 2000h*(y&1) + 50h*(y/2)
  10667.                  add     bx,OriginOffset ; BX := byte offset in video buffer
  10668.  
  10669.                  mov     ax,VideoBufferSeg
  10670.                  mov     es,ax           ; ES:BX := byte address of pixel
  10671.  
  10672.                  mov     ah,3            ; AH := unshifted bit mask
  10673.                  and     cl,ah           ; CL := x & 3
  10674.                  xor     cl,ah           ; CL := 3 - (x & 3)
  10675.                  shl     cl,1            ; CL := # bits to shift left
  10676.  
  10677.                  ret
  10678.  
  10679.  PixelAddr04     ENDP
  10680.  
  10681.  _TEXT           ENDS
  10682.  
  10683.                  END
  10684.  
  10685.  \SAMPCODE\VIDEO\4\4_2.ASM
  10686.  
  10687.                  TITLE   'Listing 4-2'
  10688.                  NAME    PixelAddr06
  10689.                  PAGE    55,132
  10690.  
  10691.  ;
  10692.  ; Name:         PixelAddr06
  10693.  ;
  10694.  ; Function:     Determine buffer address of pixel in 640x200 2-color mode
  10695.  ;
  10696.  ; Caller:       AX = y-coordinate (0-199)
  10697.  ;               BX = x-coordinate (0-639)
  10698.  ;
  10699.  ; Returns:      AH = bit mask
  10700.  ;               BX = byte offset in buffer
  10701.  ;               CL = number of bits to shift left
  10702.  ;               ES = video buffer segment
  10703.  ;
  10704.  
  10705.  
  10706.  OriginOffset    EQU     0               ; byte offset of (0,0)
  10707.  VideoBufferSeg  EQU     0B800h
  10708.  
  10709.  _TEXT           SEGMENT byte public 'CODE'
  10710.                  ASSUME  cs:_TEXT
  10711.  
  10712.                  PUBLIC  PixelAddr06
  10713.  PixelAddr06     PROC    near
  10714.  
  10715.                  mov     cl,bl           ; CL := low-order byte of x
  10716.  
  10717.                  xchg    ah,al           ; AX := 100h * y
  10718.                  shr     bx,1            ; BX := x/2
  10719.                  shr     ax,1            ; AL := 80h*(y&1)
  10720.                  add     bh,al           ; BX := x/2 + 8000h*(y&1)
  10721.                  xor     al,al           ; AX := 100h*(y/2)
  10722.                  add     bx,ax           ; BX := x/2 + 8000h*(y&1) + 100h*(y/2
  10723.                  shr     ax,1
  10724.                  shr     ax,1            ; AX := 40h*(y/2)
  10725.                  add     bx,ax           ; BX := x/2 + 8000h*(y&1) + 140h*(y/2
  10726.                  shr     bx,1
  10727.                  shr     bx,1            ; BX := x/8 + 2000h*(y&1) + 50h*(y/2)
  10728.                  add     bx,OriginOffset ; BX := byte offset in video buffer
  10729.  
  10730.                  mov     ax,VideoBufferSeg
  10731.                  mov     es,ax           ; ES:BX := byte address of pixel
  10732.  
  10733.                  and     cl,7            ; CL := x & 7
  10734.                  xor     cl,7            ; CL := number of bits to shift left
  10735.                  mov     ah,1            ; AH := unshifted bit mask
  10736.  
  10737.                  ret
  10738.  
  10739.  PixelAddr06     ENDP
  10740.  
  10741.  _TEXT           ENDS
  10742.  
  10743.                  END
  10744.  
  10745.  \SAMPCODE\VIDEO\4\4_3.ASM
  10746.  
  10747.                  TITLE   'Listing 4-3'
  10748.                  NAME    PixelAddrHGC
  10749.                  PAGE    55,132
  10750.  
  10751.  ;
  10752.  ; Name:         PixelAddrHGC
  10753.  ;
  10754.  ; Function:     Determine buffer address of pixel in 720x348 Hercules graphic
  10755.  ;
  10756.  ; Caller:       AX = y-coordinate (0-347)
  10757.  ;               BX = x-coordinate (0-719)
  10758.  ;
  10759.  ; Returns:      AH = bit mask
  10760.  ;               BX = byte offset in buffer
  10761.  ;               CL = number of bits to shift left
  10762.  ;               ES = video buffer segment
  10763.  ;
  10764.  
  10765.  BytesPerLine    EQU     90
  10766.  OriginOffset    EQU     0               ; byte offset of (0,0)
  10767.  VideoBufferSeg  EQU     0B000h
  10768.  
  10769.  _TEXT           SEGMENT byte public 'CODE'
  10770.                  ASSUME  cs:_TEXT
  10771.  
  10772.                  PUBLIC  PixelAddrHGC
  10773.  PixelAddrHGC    PROC    near
  10774.  
  10775.                  mov     cl,bl           ; CL := low-order byte of x
  10776.  
  10777.                  shr     ax,1            ; AX := y/2
  10778.                  rcr     bx,1            ; BX := 8000h*(y&1) + x/2
  10779.                  shr     ax,1            ; AX := y/4
  10780.                  rcr     bx,1            ; BX := 4000h*(y&3) + x/4
  10781.                  shr     bx,1            ; BX := 2000h*(y&3) + x/8
  10782.                  mov     ah,BytesPerLine
  10783.                  mul     ah              ; AX := BytesPerLine*(y/4)
  10784.                  add     bx,ax           ; BX := 2000h*(y&3) + x/8 + BytesPerL
  10785.                  add     bx,OriginOffset ; BX := byte offset in video buffer
  10786.  
  10787.                  mov     ax,VideoBufferSeg
  10788.                  mov     es,ax           ; ES:BX := byte address of pixel
  10789.  
  10790.                  and     cl,7            ; CL := x & 7
  10791.                  xor     cl,7            ; CL := number of bits to shift left
  10792.                  mov     ah,1            ; AH := unshifted bit mask
  10793.  
  10794.                  ret
  10795.  
  10796.  PixelAddrHGC    ENDP
  10797.  
  10798.  _TEXT           ENDS
  10799.  
  10800.                  END
  10801.  
  10802.  \SAMPCODE\VIDEO\4\4_4.ASM
  10803.  
  10804.                  TITLE   'Listing 4-4'
  10805.                  NAME    PixelAddr10
  10806.                  PAGE    55,132
  10807.  
  10808.  ;
  10809.  ; Name:         PixelAddr10
  10810.  ;
  10811.  ; Function:     Determine buffer address of pixel in native EGA and VGA modes
  10812.  ;                       320x200 16-color
  10813.  ;                       640x200 16-color
  10814.  ;                       640x350 16-color
  10815.  ;                       640x350 monochrome (4-color)
  10816.  ;                       640x480 2-color
  10817.  ;                       640x480 16-color
  10818.  ;
  10819.  ; Caller:       AX = y-coordinate
  10820.  ;               BX = x-coordinate
  10821.  ;
  10822.  ; Returns:      AH = bit mask
  10823.  ;               BX = byte offset in buffer
  10824.  ;               CL = number of bits to shift left
  10825.  ;               ES = video buffer segment
  10826.  ;
  10827.  
  10828.  
  10829.  BytesPerLine    EQU     80              ; bytes in one horizontal line
  10830.  OriginOffset    EQU     0               ; byte offset of (0,0)
  10831.  VideoBufferSeg  EQU     0A000h
  10832.  
  10833.  _TEXT           SEGMENT byte public 'CODE'
  10834.                  ASSUME  cs:_TEXT
  10835.  
  10836.                  PUBLIC  PixelAddr10
  10837.  PixelAddr10     PROC    near
  10838.  
  10839.                  mov     cl,bl           ; CL := low-order byte of x
  10840.  
  10841.                  push    dx              ; preserve DX
  10842.  
  10843.                  mov     dx,BytesPerLine ; AX := y * BytesPerLine
  10844.                  mul     dx
  10845.  
  10846.                  pop     dx
  10847.                  shr     bx,1
  10848.                  shr     bx,1
  10849.                  shr     bx,1            ; BX := x/8
  10850.                  add     bx,ax           ; BX := y*BytesPerLine + x/8
  10851.                  add     bx,OriginOffset ; BX := byte offset in video buffer
  10852.  
  10853.                  mov     ax,VideoBufferSeg
  10854.                  mov     es,ax           ; ES:BX := byte address of pixel
  10855.  
  10856.                  and     cl,7            ; CL := x & 7
  10857.                  xor     cl,7            ; CL := number of bits to shift left
  10858.                  mov     ah,1            ; AH := unshifted bit mask
  10859.                  ret
  10860.  
  10861.  PixelAddr10     ENDP
  10862.  
  10863.  _TEXT           ENDS
  10864.  
  10865.                  END
  10866.  
  10867.  \SAMPCODE\VIDEO\4\4_5.ASM
  10868.  
  10869.                  TITLE   'Listing 4-5'
  10870.                  NAME    PixelAddr13
  10871.                  PAGE    55,132
  10872.  
  10873.  ;
  10874.  ; Name:         PixelAddr13
  10875.  ;
  10876.  ; Function:     Determine buffer address of pixel in 320x200 256-color mode
  10877.  ;
  10878.  ; Caller:       AX = y-coordinate (0-199)
  10879.  ;               BX = x-coordinate (0-319)
  10880.  ;
  10881.  ; Returns:      BX = byte offset in buffer
  10882.  ;               ES = video buffer segment
  10883.  ;
  10884.  
  10885.  
  10886.  OriginOffset    EQU     0               ; byte offset of (0,0)
  10887.  VideoBufferSeg  EQU     0A000h
  10888.  
  10889.  _TEXT           SEGMENT byte public 'CODE'
  10890.                  ASSUME  cs:_TEXT
  10891.  
  10892.                  PUBLIC  PixelAddr13
  10893.  PixelAddr13     PROC    near
  10894.  
  10895.                  xchg    ah,al           ; AX := 256*y
  10896.                  add     bx,ax           ; BX := 256*y + x
  10897.                  shr     ax,1
  10898.                  shr     ax,1            ; AX := 64*y
  10899.                  add     bx,ax           ; BX := 320*y + x
  10900.  
  10901.                  add     bx,OriginOffset ; BX := byte offset in video buffer
  10902.  
  10903.                  mov     ax,VideoBufferSeg
  10904.                  mov     es,ax           ; ES:BX := byte address of pixel
  10905.                  ret
  10906.  
  10907.  PixelAddr13     ENDP
  10908.  
  10909.  _TEXT           ENDS
  10910.  
  10911.                  END
  10912.  
  10913.  \SAMPCODE\VIDEO\5
  10914.  \SAMPCODE\VIDEO\5\5_10.ASM
  10915.  
  10916.                  TITLE   'Listing 5-10'
  10917.                  NAME    SetPixel06
  10918.                  PAGE    55,132
  10919.  
  10920.  ;
  10921.  ; Name:         SetPixel06
  10922.  ;
  10923.  ; Function:     Set the value of a pixel in 640x200 2-color mode
  10924.  ;
  10925.  ; Caller:       Microsoft C:
  10926.  ;
  10927.  ;                       void SetPixel(x,y,n);
  10928.  ;
  10929.  ;                       int x,y;                /* pixel coordinates */
  10930.  ;
  10931.  ;                       int n;                  /* pixel value */
  10932.  ;
  10933.  
  10934.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  10935.  ARGy            EQU     word ptr [bp+6]
  10936.  ARGn            EQU     byte ptr [bp+8]
  10937.  
  10938.  
  10939.  DGROUP          GROUP   _DATA
  10940.  
  10941.  _TEXT           SEGMENT byte public 'CODE'
  10942.                  ASSUME  cs:_TEXT,ds:DGROUP
  10943.  
  10944.                  EXTRN   PixelAddr06:near
  10945.  
  10946.                  PUBLIC  _SetPixel06
  10947.  _SetPixel06     PROC    near
  10948.  
  10949.                  push    bp              ; preserve caller registers
  10950.                  mov     bp,sp
  10951.  
  10952.                  mov     ax,ARGy         ; AX := y
  10953.                  mov     bx,ARGx         ; BX := x
  10954.                  call    PixelAddr06     ; AH := bit mask
  10955.                                          ; ES:BX -> buffer
  10956.                                          ; CL := # bits to shift left
  10957.  
  10958.                  mov     al,ARGn         ; AL := unshifted pixel value
  10959.                  shl     ax,cl           ; AH := bit mask in proper position
  10960.                                          ; AL := pixel value in proper positio
  10961.  
  10962.                  jmp     word ptr SetPixelOp06   ; jump to Replace, AND,
  10963.                                                  ;  OR or XOR routine
  10964.  
  10965.  
  10966.                                          ; routine to Replace pixel value
  10967.  
  10968.  ReplacePixel06: not     ah              ; AH := inverse bit mask
  10969.                  and     es:[bx],ah      ; zero the pixel value
  10970.                  or      es:[bx],al      ; set the pixel value
  10971.                  jmp     short L02
  10972.  
  10973.  
  10974.                                          ; routine to AND pixel value
  10975.  ANDPixel06:     test    al,al
  10976.                  jnz     L02             ; do nothing if pixel value = 1
  10977.  
  10978.  L01:            not     ah              ; AH := inverse of bit mask
  10979.                  and     es:[bx],ah      ; set bit in video buffer to 0
  10980.                  jmp     short L02
  10981.  
  10982.  
  10983.                                          ; routine to OR pixel value
  10984.  ORPixel06:      test    al,al
  10985.                  jz      L02             ; do nothing if pixel value = 0
  10986.  
  10987.                  or      es:[bx],al      ; set bit in video buffer
  10988.                  jmp     short L02
  10989.  
  10990.  
  10991.                                          ; routine to XOR pixel value
  10992.  XORPixel06:     test    al,al
  10993.                  jz      L02             ; do nothing if pixel value = 0
  10994.  
  10995.                  xor     es:[bx],al      ; XOR bit in video buffer
  10996.  
  10997.  
  10998.  L02:            mov     sp,bp           ; restore caller registers and return
  10999.                  pop     bp
  11000.                  ret
  11001.  
  11002.  _SetPixel06     ENDP
  11003.  
  11004.  _TEXT           ENDS
  11005.  
  11006.  
  11007.  _DATA           SEGMENT word public 'DATA'
  11008.  
  11009.  SetPixelOp06    dw      ReplacePixel06  ; contains addr of pixel operation
  11010.  
  11011.  _DATA           ENDS
  11012.  
  11013.                  END
  11014.  
  11015.  \SAMPCODE\VIDEO\5\5_11.ASM
  11016.  
  11017.                  TITLE   'Listing 5-11'
  11018.                  NAME    SetPixel04
  11019.                  PAGE    55,132
  11020.  
  11021.  ;
  11022.  ; Name:         SetPixel04
  11023.  ;
  11024.  ; Function:     Set the value of a pixel in 320x200 4-color mode
  11025.  ;
  11026.  ; Caller:       Microsoft C:
  11027.  ;
  11028.  ;                       void SetPixel(x,y,n);
  11029.  ;
  11030.  ;                       int x,y;                /* pixel coordinates */
  11031.  ;
  11032.  ;                       int n;                  /* pixel value */
  11033.  ;
  11034.  
  11035.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11036.  ARGy            EQU     word ptr [bp+6]
  11037.  ARGn            EQU     byte ptr [bp+8]
  11038.  
  11039.  
  11040.  DGROUP          GROUP   _DATA
  11041.  
  11042.  _TEXT           SEGMENT byte public 'CODE'
  11043.                  ASSUME  cs:_TEXT,ds:DGROUP
  11044.  
  11045.                  EXTRN   PixelAddr04:near
  11046.  
  11047.                  PUBLIC  _SetPixel04
  11048.  _SetPixel04     PROC    near
  11049.  
  11050.                  push    bp              ; preserve caller registers
  11051.                  mov     bp,sp
  11052.  
  11053.                  mov     ax,ARGy         ; AX := y
  11054.                  mov     bx,ARGx         ; BX := x
  11055.                  call    PixelAddr04     ; AH := bit mask
  11056.                                          ; ES:BX -> buffer
  11057.                                          ; CL := #bits to shift left
  11058.  
  11059.                  mov     al,ARGn
  11060.                  shl     ax,cl           ; AH := bit mask in proper position
  11061.                                          ; AL := pixel value in proper positio
  11062.  
  11063.                  jmp     word ptr SetPixelOp04   ; jump to Replace, AND,
  11064.                                                  ;  OR or XOR routine
  11065.  
  11066.  
  11067.                                          ; routine to Replace pixel value
  11068.  
  11069.  ReplacePixel04: not     ah              ; AH := inverse bit mask
  11070.                  and     es:[bx],ah      ; zero the pixel value
  11071.                  or      es:[bx],al      ; set the pixel value
  11072.                  jmp     short L02
  11073.  
  11074.                                          ; routine to AND pixel value
  11075.  
  11076.  ANDPixel04:     not     ah              ; AH := inverse bit mask
  11077.                  or      al,ah           ; AL := all 1's except pixel value
  11078.                  and     es:[bx],al
  11079.                  jmp     short L02
  11080.  
  11081.  
  11082.  ORPixel04:      or      es:[bx],al      ; routine to OR pixel value
  11083.                  jmp     short L02
  11084.  
  11085.  
  11086.  XORPixel04:     xor     es:[bx],al      ; routine to XOR pixel value
  11087.  
  11088.  
  11089.  L02:            mov     sp,bp           ; restore caller registers and return
  11090.                  pop     bp
  11091.                  ret
  11092.  
  11093.  _SetPixel04     ENDP
  11094.  
  11095.  _TEXT           ENDS
  11096.  
  11097.  
  11098.  _DATA           SEGMENT word public 'DATA'
  11099.  
  11100.  SetPixelOp04    DW      ReplacePixel04  ; contains addr of pixel operation
  11101.  
  11102.  _DATA           ENDS
  11103.  
  11104.                  END
  11105.  
  11106.  \SAMPCODE\VIDEO\5\5_12.ASM
  11107.  
  11108.                  TITLE   'Listing 5-12'
  11109.                  NAME    SetPixel10
  11110.                  PAGE    55,132
  11111.  
  11112.  ;
  11113.  ; Name:         SetPixel10
  11114.  ;
  11115.  ; Function:     Set the value of a pixel in native EGA graphics modes.
  11116.  ;
  11117.  ;               *** Write Mode 0, Set/Reset ***
  11118.  ;
  11119.  ; Caller:       Microsoft C:
  11120.  ;
  11121.  ;                       void SetPixel(x,y,n);
  11122.  ;
  11123.  ;                       int x,y;                /* pixel coordinates */
  11124.  ;
  11125.  ;                       int n;                  /* pixel value */
  11126.  ;
  11127.  
  11128.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11129.  ARGy            EQU     word ptr [bp+6]
  11130.  ARGn            EQU     byte ptr [bp+8]
  11131.  
  11132.  RMWbits         EQU     18h             ; read-modify-write bits
  11133.  
  11134.  
  11135.  _TEXT           SEGMENT byte public 'CODE'
  11136.                  ASSUME  cs:_TEXT
  11137.  
  11138.                  EXTRN   PixelAddr10:near
  11139.  
  11140.                  PUBLIC  _SetPixel10
  11141.  _SetPixel10     PROC    near
  11142.  
  11143.                  push    bp              ; preserve caller registers
  11144.                  mov     bp,sp
  11145.  
  11146.                  mov     ax,ARGy         ; AX := y
  11147.                  mov     bx,ARGx         ; BX := x
  11148.                  call    PixelAddr10     ; AH := bit mask
  11149.                                          ; ES:BX -> buffer
  11150.                                          ; CL := # bits to shift left
  11151.  
  11152.  ; set Graphics Controller Bit Mask register
  11153.  
  11154.                  shl     ah,cl           ; AH := bit mask in proper position
  11155.                  mov     dx,3CEh         ; GC address register port
  11156.                  mov     al,8            ; AL := Bit Mask register number
  11157.                  out     dx,ax
  11158.  
  11159.  ; set Graphics Controller Mode register
  11160.  
  11161.                  mov     ax,0005h        ; AL :=  Mode register number
  11162.                                          ; AH :=  Write Mode 0 (bits 0,1)
  11163.                                          ;        Read Mode 0 (bit 3)
  11164.                  out     dx,ax
  11165.  
  11166.  ; set Data Rotate/Function Select register
  11167.  
  11168.                  mov     ah,RMWbits      ; AH := Read-Modify-Write bits
  11169.                  mov     al,3            ; AL := Data Rotate/Function Select r
  11170.                  out     dx,ax
  11171.  
  11172.  ; set Set/Reset and Enable Set/Reset registers
  11173.  
  11174.                  mov     ah,ARGn         ; AH := pixel value
  11175.                  mov     al,0            ; AL := Set/Reset reg number
  11176.                  out     dx,ax
  11177.  
  11178.                  mov     ax,0F01h        ; AH := value for Enable Set/Reset (a
  11179.                                          ;  bit planes enabled)
  11180.                                          ; AL := Enable Set/Reset reg number
  11181.                  out     dx,ax
  11182.  
  11183.  ; set the pixel value
  11184.  
  11185.                  or      es:[bx],al      ; load latches during CPU read
  11186.                                          ; update latches and bit planes durin
  11187.                                          ;  CPU write
  11188.  
  11189.  ; restore default Graphics Controller registers
  11190.  
  11191.                  mov     ax,0FF08h       ; default Bit Mask
  11192.                  out     dx,ax
  11193.  
  11194.                  mov     ax,0005         ; default Mode register
  11195.                  out     dx,ax
  11196.  
  11197.                  mov     ax,0003         ; default Function Select
  11198.                  out     dx,ax
  11199.  
  11200.                  mov     ax,0001         ; default Enable Set/Reset
  11201.                  out     dx,ax
  11202.  
  11203.                  mov     sp,bp           ; restore caller registers and return
  11204.                  pop     bp
  11205.                  ret
  11206.  
  11207.  _SetPixel10     ENDP
  11208.  
  11209.  _TEXT           ENDS
  11210.  
  11211.                  END
  11212.  
  11213.  \SAMPCODE\VIDEO\5\5_13.ASM
  11214.  
  11215.                  TITLE   'Listing 5-13'
  11216.                  NAME    SetPixel10
  11217.                  PAGE    55,132
  11218.  
  11219.  ;
  11220.  ; Name:         SetPixel10
  11221.  ;
  11222.  ; Function:     Set the value of a pixel in native EGA graphics modes.
  11223.  ;
  11224.  ;               *** Write Mode 0, Sequencer Map Mask ***
  11225.  ;
  11226.  ; Caller:       Microsoft C:
  11227.  ;
  11228.  ;                       void SetPixel(x,y,n);
  11229.  ;
  11230.  ;                       int x,y;                /* pixel coordinates */
  11231.  ;
  11232.  ;                       int n;                  /* pixel value */
  11233.  ;
  11234.  
  11235.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11236.  ARGy            EQU     word ptr [bp+6]
  11237.  ARGn            EQU     byte ptr [bp+8]
  11238.  
  11239.  
  11240.  _TEXT           SEGMENT byte public 'CODE'
  11241.                  ASSUME  cs:_TEXT
  11242.  
  11243.                  EXTRN   PixelAddr10:near
  11244.  
  11245.                  PUBLIC  _SetPixel10
  11246.  _SetPixel10     PROC    near
  11247.  
  11248.                  push    bp              ; preserve caller registers
  11249.                  mov     bp,sp
  11250.  
  11251.                  mov     ax,ARGy         ; AX := y
  11252.                  mov     bx,ARGx         ; BX := x
  11253.                  call    PixelAddr10     ; AH := bit mask
  11254.                                          ; ES:BX -> buffer
  11255.                                          ; CL := # bits to shift left
  11256.  
  11257.  ; set Graphics Controller Bit Mask register
  11258.  
  11259.                  shl     ah,cl           ; AH := bit mask in proper position
  11260.                  mov     dx,3CEh         ; Graphics Controller address reg por
  11261.                  mov     al,8            ; AL := Bit Mask register number
  11262.                  out     dx,ax
  11263.  
  11264.  ; zero the pixel value
  11265.  
  11266.                  mov     al,es:[bx]      ; latch one byte from each bit plane
  11267.                  mov     byte ptr es:[bx],0  ; zero masked bits in all planes
  11268.  
  11269.  ; set Sequencer Map Mask register
  11270.  
  11271.                  mov     dl,0C4h         ; DX := 3C4h (Sequencer addr reg port
  11272.                  mov     ah,ARGn         ; AH := value for Map Mask register
  11273.                                          ;  (nonzero bits in pixel value selec
  11274.                                          ;    enabled bit planes for Sequencer
  11275.                  mov     al,2            ; AL := Map Mask register number
  11276.                  out     dx,ax
  11277.  
  11278.  ; set the nonzero bits in the pixel value
  11279.  
  11280.                  mov     byte ptr es:[bx],0FFh ; set bits in enabled bit plane
  11281.  
  11282.  ; restore default Sequencer registers
  11283.  
  11284.                  mov     ah,0Fh          ; AH := value for Map Mask reg (all b
  11285.                                          ;  planes enabled)
  11286.                  out     dx,ax
  11287.  
  11288.  ; restore default Graphics Controller registers
  11289.  
  11290.                  mov     dl,0CEh         ; DX := 3CEh (Graphics Controller por
  11291.                  mov     ax,0FF08h       ; default Bit Mask
  11292.                  out     dx,ax
  11293.  
  11294.                  mov     sp,bp           ; restore caller registers and return
  11295.                  pop     bp
  11296.                  ret
  11297.  
  11298.  _SetPixel10     ENDP
  11299.  
  11300.  _TEXT           ENDS
  11301.  
  11302.                  END
  11303.  
  11304.  \SAMPCODE\VIDEO\5\5_14.ASM
  11305.  
  11306.                  TITLE   'Listing 5-14'
  11307.                  NAME    SetPixel10
  11308.                  PAGE    55,132
  11309.  
  11310.  ;
  11311.  ; Name:         SetPixel10
  11312.  ;
  11313.  ; Function:     Set the value of a pixel in native EGA graphics modes.
  11314.  ;
  11315.  ;               *** Write Mode 2 ***
  11316.  ;
  11317.  ; Caller:       Microsoft C:
  11318.  ;
  11319.  ;                       void SetPixel(x,y,n);
  11320.  ;
  11321.  ;                       int x,y;                /* pixel coordinates */
  11322.  ;
  11323.  ;                       int n;                  /* pixel value */
  11324.  ;
  11325.  
  11326.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11327.  ARGy            EQU     word ptr [bp+6]
  11328.  ARGn            EQU     byte ptr [bp+8]
  11329.  
  11330.  RMWbits         EQU     18h             ; read-modify-write bits
  11331.  
  11332.  
  11333.  _TEXT           SEGMENT byte public 'CODE'
  11334.                  ASSUME  cs:_TEXT
  11335.  
  11336.                  EXTRN   PixelAddr10:near
  11337.  
  11338.                  PUBLIC  _SetPixel10
  11339.  _SetPixel10     PROC    near
  11340.  
  11341.                  push    bp              ; preserve stack frame
  11342.                  mov     bp,sp
  11343.  
  11344.                  mov     ax,ARGy         ; AX := y
  11345.                  mov     bx,ARGx         ; BX := x
  11346.                  call    PixelAddr10     ; AH := bit mask
  11347.                                          ; ES:BX -> buffer
  11348.                                          ; CL := # bits to shift left
  11349.  
  11350.  ; set Graphics Controller Bit Mask register
  11351.  
  11352.                  shl     ah,cl           ; AH := bit mask in proper position
  11353.                  mov     dx,3CEh         ; GC address register port
  11354.                  mov     al,8            ; AL := Bit Mask register number
  11355.                  out     dx,ax
  11356.  
  11357.  ; set Graphics Controller Mode register
  11358.  
  11359.                  mov     ax,205h         ; AL :=  Mode register number
  11360.                                          ; AH :=  Write Mode 2 (bits 0,1)
  11361.                                          ;        Read Mode 0 (bit 3)
  11362.                  out     dx,ax
  11363.  
  11364.  ; set Data Rotate/Function Select register
  11365.  
  11366.                  mov     ah,RMWbits      ; AH := Read-Modify-Write bits
  11367.                  mov     al,3            ; AL := Data Rotate/Function Select r
  11368.                  out     dx,ax
  11369.  
  11370.  ; set the pixel value
  11371.  
  11372.                  mov     al,es:[bx]      ; latch one byte from each bit plane
  11373.                  mov     al,ARGn         ; AL := pixel value
  11374.                  mov     es:[bx],al      ; update all bit planes
  11375.  
  11376.  ; restore default Graphics Controller registers
  11377.  
  11378.                  mov     ax,0FF08h       ; default Bit Mask
  11379.                  out     dx,ax
  11380.  
  11381.                  mov     ax,0005         ; default Mode register
  11382.                  out     dx,ax
  11383.  
  11384.                  mov     ax,0003         ; default Function Select
  11385.                  out     dx,ax
  11386.  
  11387.                  mov     sp,bp           ; restore stack frame and return
  11388.                  pop     bp
  11389.                  ret
  11390.  
  11391.  _SetPixel10     ENDP
  11392.  
  11393.  _TEXT           ENDS
  11394.  
  11395.                  END
  11396.  
  11397.  \SAMPCODE\VIDEO\5\5_15.ASM
  11398.  
  11399.                  TITLE   'Listing 5-15'
  11400.                  NAME    SetPixelInC
  11401.                  PAGE    55,132
  11402.  
  11403.  ;
  11404.  ; Name:         SetPixelInC
  11405.  ;
  11406.  ; Function:     Set the value of a pixel in 720x348 16-color mode
  11407.  ;
  11408.  ; Caller:       Microsoft C:
  11409.  ;
  11410.  ;                       void SetPixel(x,y,n);
  11411.  ;
  11412.  ;                       int x,y;                /* pixel coordinates */
  11413.  ;
  11414.  ;                       int n;                  /* pixel value */
  11415.  ;
  11416.  
  11417.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11418.  ARGy            EQU     word ptr [bp+6]
  11419.  ARGn            EQU     byte ptr [bp+8]
  11420.  
  11421.  DefaultRWColor  EQU     0Fh             ; default value for R/W Color Registe
  11422.  
  11423.  
  11424.  DGROUP          GROUP   _DATA
  11425.  
  11426.  _TEXT           SEGMENT byte public 'CODE'
  11427.                  ASSUME  cs:_TEXT,ds:DGROUP
  11428.  
  11429.                  EXTRN   PixelAddrHGC:near
  11430.  
  11431.                  PUBLIC  _SetPixelInC
  11432.  _SetPixelInC    PROC    near
  11433.  
  11434.                  push    bp              ; preserve caller registers
  11435.                  mov     bp,sp
  11436.  
  11437.                  mov     ax,ARGy         ; AX := y
  11438.                  mov     bx,ARGx         ; BX := x
  11439.                  call    PixelAddrHGC    ; AH := bit mask
  11440.                                          ; ES:BX -> buffer
  11441.                                          ; CL := # bits to shift left
  11442.  
  11443.                  shl     ah,cl           ; AH := bit mask in proper position
  11444.  
  11445.                  mov     dx,3B4h         ; DX := CRTC port
  11446.  
  11447.                  jmp     word ptr SetPixelOpInC  ; jump to Replace, AND,
  11448.                                                  ;  OR or XOR routine
  11449.  
  11450.  
  11451.  ReplacePixelInC:                        ; routine to Replace pixel value
  11452.  
  11453.                  mov     ch,ah           ; CH := bit mask for pixel
  11454.                  mov     ax,1F19h        ; AH bit 6 := 0 (Mask Polarity)
  11455.                                          ; AH bits 5-4 := 1 (Write Mode)
  11456.                                          ; AH bits 3-0 := "don't care" bits
  11457.                                          ; AL := R/W Control Register number
  11458.                  out     dx,ax           ; set R/W Control Register
  11459.  
  11460.                  inc     ax              ; AL := 1Ah (R/W Color Reg number)
  11461.                  mov     ah,ARGn         ; AH := foreground value
  11462.                  out     dx,ax           ; set R/W color register
  11463.  
  11464.                  and     es:[bx],ch      ; update bit planes
  11465.                  jmp     short L01
  11466.  
  11467.  ANDPixelInC:                            ; routine to AND pixel value
  11468.  
  11469.                  mov     ch,ah           ; CH := bit mask for pixel
  11470.                  mov     ax,1F19h        ; AH bit 6 := 0 (Mask Polarity)
  11471.                                          ; AH bits 5-4 := 1 (Write Mode)
  11472.                                          ; AH bits 3-0 := "don't care" bits
  11473.                                          ; AL := R/W Control Register number
  11474.                  out     dx,ax           ; set R/W Control Register
  11475.  
  11476.                  dec     ax              ; AL := 18h (Plane Mask Register numb
  11477.                  mov     ah,ARGn         ; AH := pixel value
  11478.                  mov     cl,4
  11479.                  shl     ah,cl           ; AH bits 7-4 := writeable plane mask
  11480.                  or      ah,0Fh          ; AH bits 3-0 := visible plane mask
  11481.                  out     dx,ax           ; set Plane Mask Register
  11482.  
  11483.                  mov     ax,001Ah        ; AH := 0 (foreground value)
  11484.                                          ; AL := 1Ah (R/W Color reg)
  11485.                  out     dx,ax           ; set R/W Color Register
  11486.  
  11487.                  and     es:[bx],ch      ; update bit planes
  11488.                  jmp     short L01
  11489.  
  11490.                                          ; routine to OR pixel value
  11491.  ORPixelInC:
  11492.                  mov     ch,ah           ; CH := bit mask for pixel
  11493.                  mov     ax,1F19h        ; AH bit 6 := 0 (Mask Polarity)
  11494.                                          ; AH bits 5-4 := 1 (Write Mode)
  11495.                                          ; AH bits 3-0 := "don't care" bits
  11496.                                          ; AL := R/W Control Register number
  11497.                  out     dx,ax           ; set R/W Control Register
  11498.  
  11499.                  dec     ax              ; AL := 18h (Plane Mask Register numb
  11500.                  mov     ah,ARGn         ; AH := pixel value
  11501.                  not     ah              ; AH := complement of pixel value
  11502.                  mov     cl,4
  11503.                  shl     ah,cl           ; AH bits 7-4 := writeable plane mask
  11504.                  or      ah,0Fh          ; AH bits 3-0 := visible plane mask
  11505.                  out     dx,ax           ; set Plane Mask Register
  11506.  
  11507.                  mov     ax,0F1Ah        ; AH := 0 (foreground value)
  11508.                                          ; AL := 1Ah (R/W Color reg)
  11509.                  out     dx,ax           ; set R/W Color Register
  11510.  
  11511.                  and     es:[bx],ch      ; update bit planes
  11512.                  jmp     short L01
  11513.  
  11514.  XORPixelInC:                            ; routine to XOR pixel value
  11515.                  mov     ch,ah           ; CH := bit mask for pixel
  11516.                  mov     ax,3F19h        ; AH bit 6 := 0 (Mask Polarity)
  11517.                                          ; AH bits 5-4 := 3 (Write Mode)
  11518.                                          ; AH bits 3-0 := "don't care" bits
  11519.                                          ; AL := R/W Control Register number
  11520.                  out     dx,ax           ; set R/W Control Register
  11521.  
  11522.                  dec     ax              ; AL := 18h (Plane Mask Register numb
  11523.                  mov     ah,ARGn         ; AH := pixel value
  11524.                  not     ah              ; AH := complement of pixel value
  11525.                  mov     cl,4
  11526.                  shl     ah,cl           ; AH bits 7-4 := writeable plane mask
  11527.                  or      ah,0Fh          ; AH bits 3-0 := visible plane mask
  11528.                  out     dx,ax           ; set Plane Mask Register
  11529.  
  11530.                  xor     es:[bx],ch      ; update bit planes
  11531.  
  11532.  L01:            mov     ax,0F18h
  11533.                  out     dx,ax           ; restore default Plane Mask value
  11534.  
  11535.                  mov     ax,4019h        ; restore default R/W Control value
  11536.                  out     dx,ax
  11537.  
  11538.                  inc     ax              ; restore default R/W Color value
  11539.                  mov     ah,DefaultRWColor
  11540.                  out     dx,ax
  11541.  
  11542.                  mov     sp,bp           ; restore caller registers and return
  11543.                  pop     bp
  11544.                  ret
  11545.  
  11546.  _SetPixelInC    ENDP
  11547.  
  11548.  _TEXT           ENDS
  11549.  
  11550.  
  11551.  _DATA           SEGMENT word public 'DATA'
  11552.  
  11553.  SetPixelOpInC   DW      ReplacePixelInc ; contains addr of pixel operation
  11554.  
  11555.  _DATA           ENDS
  11556.  
  11557.                  END
  11558.  
  11559.  \SAMPCODE\VIDEO\5\5_16.ASM
  11560.  
  11561.                  TITLE   'Listing 5-16'
  11562.                  NAME    SetPixel11
  11563.                  PAGE    55,132
  11564.  
  11565.  ;
  11566.  ; Name:         SetPixel11
  11567.  ;
  11568.  ; Function:     Set the value of a pixel in 640x480 2-color mode (MCGA or VGA
  11569.  ;
  11570.  ; Caller:       Microsoft C:
  11571.  ;
  11572.  ;                       void SetPixel(x,y,n);
  11573.  ;
  11574.  ;                       int x,y;                /* pixel coordinates */
  11575.  ;
  11576.  ;                       int n;                  /* pixel value */
  11577.  ;
  11578.  
  11579.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11580.  ARGy            EQU     word ptr [bp+6]
  11581.  ARGn            EQU     byte ptr [bp+8]
  11582.  
  11583.  
  11584.  DGROUP          GROUP   _DATA
  11585.  
  11586.  _TEXT           SEGMENT byte public 'CODE'
  11587.                  ASSUME  cs:_TEXT,ds:DGROUP
  11588.  
  11589.                  EXTRN   PixelAddr10:near
  11590.  
  11591.                  PUBLIC  _SetPixel11
  11592.  _SetPixel11     PROC    near
  11593.  
  11594.                  push    bp              ; preserve caller registers
  11595.                  mov     bp,sp
  11596.  
  11597.                  mov     ax,ARGy         ; AX := y
  11598.                  mov     bx,ARGx         ; BX := x
  11599.                  call    PixelAddr10     ; AH := bit mask
  11600.                                          ; ES:BX -> buffer
  11601.                                          ; CL := # bits to shift left
  11602.  
  11603.                  mov     al,ARGn         ; AL := unshifted pixel value
  11604.                  shl     ax,cl           ; AH := bit mask in proper position
  11605.                                          ; AL := pixel value in proper positio
  11606.  
  11607.                  jmp     word ptr SetPixelOp11   ; jump to Replace, AND,
  11608.                                                  ;  OR or XOR routine
  11609.  
  11610.  
  11611.                                          ; routine to Replace pixel value
  11612.  
  11613.  ReplacePixel11: not     ah              ; AH := inverse bit mask
  11614.                  and     es:[bx],ah      ; zero the pixel value
  11615.                  or      es:[bx],al      ; set the pixel value
  11616.                  jmp     short L02
  11617.  
  11618.  
  11619.                                          ; routine to AND pixel value
  11620.  ANDPixel11:     test    al,al
  11621.                  jnz     L02             ; do nothing if pixel value = 1
  11622.  
  11623.  L01:            not     ah              ; AH := inverse of bit mask
  11624.                  and     es:[bx],ah      ; set bit in video buffer to 0
  11625.                  jmp     short L02
  11626.  
  11627.  
  11628.                                          ; routine to OR pixel value
  11629.  ORPixel11:      test    al,al
  11630.                  jz      L02             ; do nothing if pixel value = 0
  11631.  
  11632.                  or      es:[bx],al      ; set bit in video buffer
  11633.                  jmp     short L02
  11634.  
  11635.  
  11636.                                          ; routine to XOR pixel value
  11637.  XORPixel11:     test    al,al
  11638.                  jz      L02             ; do nothing if pixel value = 0
  11639.  
  11640.                  xor     es:[bx],al      ; XOR bit in video buffer
  11641.  
  11642.  
  11643.  L02:            mov     sp,bp           ; restore caller registers and return
  11644.                  pop     bp
  11645.                  ret
  11646.  
  11647.  _SetPixel11     ENDP
  11648.  
  11649.  _TEXT           ENDS
  11650.  
  11651.  
  11652.  _DATA           SEGMENT word public 'DATA'
  11653.  
  11654.  SetPixelOp11    DW      ReplacePixel11  ; contains addr of pixel operation
  11655.  
  11656.  _DATA           ENDS
  11657.  
  11658.                  END
  11659.  
  11660.  \SAMPCODE\VIDEO\5\5_17.ASM
  11661.  
  11662.                  TITLE   'Listing 5-17'
  11663.                  NAME    SetPixel13
  11664.                  PAGE    55,132
  11665.  
  11666.  ;
  11667.  ; Name:         SetPixel13
  11668.  ;
  11669.  ; Function:     Set the value of a pixel in VGA 320x200 256-color mode
  11670.  ;
  11671.  ; Caller:       Microsoft C:
  11672.  ;
  11673.  ;                       void SetPixel(x,y,n);
  11674.  ;
  11675.  ;                       int x,y;                /* pixel coordinates */
  11676.  ;
  11677.  ;                       int n;                  /* pixel value */
  11678.  ;
  11679.  
  11680.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11681.  ARGy            EQU     word ptr [bp+6]
  11682.  ARGn            EQU     byte ptr [bp+8]
  11683.  
  11684.  DGROUP          GROUP   _DATA
  11685.  
  11686.  _TEXT           SEGMENT byte public 'CODE'
  11687.                  ASSUME  cs:_TEXT,ds:DGROUP
  11688.  
  11689.                  EXTRN   PixelAddr13:near
  11690.  
  11691.                  PUBLIC  _SetPixel13
  11692.  _SetPixel13     PROC    near
  11693.  
  11694.                  push    bp              ; preserve caller registers
  11695.                  mov     bp,sp
  11696.  
  11697.                  mov     ax,ARGy         ; AX := y
  11698.                  mov     bx,ARGx         ; BX := x
  11699.                  call    PixelAddr13     ; ES:BX -> buffer
  11700.  
  11701.                  mov     al,ARGn         ; AL := pixel value
  11702.  
  11703.                  jmp     word ptr SetPixelOp13   ; jump to Replace, AND,
  11704.                                                  ;  OR or XOR routine
  11705.  
  11706.  
  11707.  ReplacePixel13: mov     es:[bx],al
  11708.                  jmp     short L01
  11709.  
  11710.  ANDPixel13:     and     es:[bx],al
  11711.                  jmp     short L01
  11712.  
  11713.  ORPixel13:      or      es:[bx],al
  11714.                  jmp     short L01
  11715.  
  11716.  XORPixel13:     xor     es:[bx],al
  11717.  
  11718.  
  11719.  L01:            mov     sp,bp           ; restore caller registers and return
  11720.                  pop     bp
  11721.                  ret
  11722.  
  11723.  _SetPixel13     ENDP
  11724.  
  11725.  _TEXT           ENDS
  11726.  
  11727.  
  11728.  _DATA           SEGMENT word public 'DATA'
  11729.  
  11730.  SetPixelOp13    DW      ReplacePixel13
  11731.  
  11732.  _DATA           ENDS
  11733.  
  11734.                  END
  11735.  
  11736.  \SAMPCODE\VIDEO\5\5_2.ASM
  11737.  
  11738.                  TITLE   'Listing 5-2'
  11739.                  NAME    ReadPixel06
  11740.                  PAGE    55,132
  11741.  
  11742.  ;
  11743.  ; Name:         ReadPixel06
  11744.  ;
  11745.  ; Function:     Read the value of a pixel in 640x200 2-color mode
  11746.  ;
  11747.  ; Caller:       Microsoft C:
  11748.  ;
  11749.  ;                       int ReadPixel06(x,y);
  11750.  ;
  11751.  ;                       int x,y;                /* pixel coordinates */
  11752.  ;
  11753.  
  11754.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11755.  ARGy            EQU     word ptr [bp+6]
  11756.  
  11757.  
  11758.  _TEXT           SEGMENT byte public 'CODE'
  11759.                  ASSUME  cs:_TEXT
  11760.  
  11761.                  EXTRN   PixelAddr06:near
  11762.  
  11763.                  PUBLIC  _ReadPixel06
  11764.  _ReadPixel06    PROC    near
  11765.  
  11766.                  push    bp              ; preserve caller registers
  11767.                  mov     bp,sp
  11768.  
  11769.                  mov     ax,ARGy         ; AX := y
  11770.                  mov     bx,ARGx         ; BX := x
  11771.                  call    PixelAddr06     ; AH := bit mask
  11772.                                          ; ES:BX -> buffer
  11773.                                          ; CL := #bits to shift
  11774.  
  11775.                  mov     al,es:[bx]      ; AL := byte containing pixel
  11776.                  shr     al,cl           ; shift pixel value to low-order bits
  11777.                  and     al,ah           ; AL := pixel value
  11778.                  xor     ah,ah           ; AX := pixel value
  11779.  
  11780.                  mov     sp,bp           ; restore caller registers and return
  11781.                  pop     bp
  11782.                  ret
  11783.  
  11784.  _ReadPixel06    ENDP
  11785.  
  11786.  _TEXT           ENDS
  11787.  
  11788.                  END
  11789.  
  11790.  \SAMPCODE\VIDEO\5\5_3.ASM
  11791.  
  11792.                  TITLE   'Listing 5-3'
  11793.                  NAME    ReadPixel04
  11794.                  PAGE    55,132
  11795.  
  11796.  ;
  11797.  ; Name:         ReadPixel04
  11798.  ;
  11799.  ; Function:     Read the value of a pixel in 320x200 4-color mode
  11800.  ;
  11801.  ; Caller:       Microsoft C:
  11802.  ;
  11803.  ;                       int ReadPixel04(x,y);
  11804.  ;
  11805.  ;                       int x,y;                /* pixel coordinates */
  11806.  ;
  11807.  
  11808.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11809.  ARGy            EQU     word ptr [bp+6]
  11810.  
  11811.  
  11812.  _TEXT           SEGMENT byte public 'CODE'
  11813.                  ASSUME  cs:_TEXT
  11814.  
  11815.                  EXTRN   PixelAddr04:near
  11816.  
  11817.                  PUBLIC  _ReadPixel04
  11818.  _ReadPixel04    PROC    near
  11819.  
  11820.                  push    bp              ; preserve caller registers
  11821.                  mov     bp,sp
  11822.  
  11823.                  mov     ax,ARGy         ; AX := y
  11824.                  mov     bx,ARGx         ; BX := x
  11825.                  call    PixelAddr04     ; AH := bit mask
  11826.                                          ; ES:BX -> buffer
  11827.                                          ; CL := #bits to shift
  11828.  
  11829.                  mov     al,es:[bx]      ; AL := byte containing pixel
  11830.                  shr     al,cl           ; shift pixel value to low-order bits
  11831.                  and     al,ah           ; AL := pixel value
  11832.                  xor     ah,ah           ; AX := pixel value
  11833.  
  11834.                  mov     sp,bp           ; restore caller registers and return
  11835.                  pop     bp
  11836.                  ret
  11837.  
  11838.  _ReadPixel04    ENDP
  11839.  
  11840.  _TEXT           ENDS
  11841.  
  11842.                  END
  11843.  
  11844.  \SAMPCODE\VIDEO\5\5_4.ASM
  11845.  
  11846.                  TITLE   'Listing 5-4'
  11847.                  NAME    ReadPixel10
  11848.                  PAGE    55,132
  11849.  
  11850.  ;
  11851.  ; Name:         ReadPixel10
  11852.  ;
  11853.  ; Function:     Read the value of a pixel in EGA native graphics modes
  11854.  ;
  11855.  ; Caller:       Microsoft C:
  11856.  ;
  11857.  ;                       int ReadPixel10(x,y);
  11858.  ;
  11859.  ;                       int x,y;                /* pixel coordinates */
  11860.  ;
  11861.  
  11862.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11863.  ARGy            EQU     word ptr [bp+6]
  11864.  
  11865.  
  11866.  _TEXT           SEGMENT byte public 'CODE'
  11867.                  ASSUME  cs:_TEXT
  11868.  
  11869.                  EXTRN   PixelAddr10:near
  11870.  
  11871.                  PUBLIC  _ReadPixel10
  11872.  _ReadPixel10    PROC    near
  11873.  
  11874.                  push    bp              ; preserve caller registers
  11875.                  mov     bp,sp
  11876.                  push    si
  11877.  
  11878.                  mov     ax,ARGy         ; AX := y
  11879.                  mov     bx,ARGx         ; BX := x
  11880.                  call    PixelAddr10     ; AH := bit mask
  11881.                                          ; ES:BX -> buffer
  11882.                                          ; CL := #bits to shift
  11883.  
  11884.                  mov     ch,ah
  11885.                  shl     ch,cl           ; CH := bit mask in proper position
  11886.  
  11887.                  mov     si,bx           ; ES:SI -> regen buffer byte
  11888.                  xor     bl,bl           ; BL is used to accumulate the pixel
  11889.  
  11890.                  mov     dx,3CEh         ; DX := Graphics Controller port
  11891.                  mov     ax,304h         ; AH := initial bit plane number
  11892.                                          ; AL := Read Map Select register numb
  11893.  
  11894.  L01:            out     dx,ax           ; select bit plane
  11895.                  mov     bh,es:[si]      ; BH := byte from current bit plane
  11896.                  and     bh,ch           ; mask one bit
  11897.                  neg     bh              ; bit 7 of BH := 1 (if masked bit = 1
  11898.                                          ; bit 7 of BH := 0 (if masked bit = 0
  11899.                  rol     bx,1            ; bit 0 of BL := next bit from pixel
  11900.                  dec     ah              ; AH := next bit plane number
  11901.                  jge     L01
  11902.  
  11903.                  mov     al,bl           ; AL := pixel value
  11904.                  xor     ah,ah           ; AX := pixel value
  11905.  
  11906.                  pop     si              ; restore caller registers and return
  11907.                  mov     sp,bp
  11908.                  pop     bp
  11909.                  ret
  11910.  
  11911.  _ReadPixel10    ENDP
  11912.  
  11913.  _TEXT           ENDS
  11914.  
  11915.                  END
  11916.  
  11917.  \SAMPCODE\VIDEO\5\5_5.ASM
  11918.  
  11919.                  TITLE   'Listing 5-5'
  11920.                  NAME    ReadPixel0F
  11921.                  PAGE    55,132
  11922.  
  11923.  ;
  11924.  ; Name:         ReadPixel0F
  11925.  ;
  11926.  ; Function:     Read the value of a pixel in 640x350 monochrome mode
  11927.  ;
  11928.  ; Caller:       Microsoft C:
  11929.  ;
  11930.  ;                       int     ReadPixel0F(x,y);
  11931.  ;
  11932.  ;                       int x,y;                /* pixel coordinates */
  11933.  ;
  11934.  
  11935.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  11936.  ARGy            EQU     word ptr [bp+6]
  11937.  
  11938.  
  11939.  _TEXT           SEGMENT byte public 'CODE'
  11940.                  ASSUME  cs:_TEXT
  11941.  
  11942.                  EXTRN   PixelAddr10:near
  11943.  
  11944.                  PUBLIC  _ReadPixel0F
  11945.  _ReadPixel0F    PROC    near
  11946.  
  11947.                  push    bp              ; preserve caller registers
  11948.                  mov     bp,sp
  11949.                  push    si
  11950.  
  11951.                  mov     ax,ARGy         ; AX := y
  11952.                  mov     bx,ARGx         ; BX := x
  11953.                  call    PixelAddr10     ; AH := bit mask
  11954.                                          ; ES:BX -> buffer
  11955.                                          ; CL := #bits to shift
  11956.  
  11957.  ; concatenate bits from bit planes 2 and 0
  11958.  
  11959.                  mov     ch,ah
  11960.                  shl     ch,cl           ; CH := bit mask in proper position
  11961.                  mov     si,bx           ; ES:SI -> regen buffer byte
  11962.  
  11963.                  mov     dx,3CEh         ; DX := Graphics Controller port
  11964.                  mov     ax,204h         ; AH := initial bit plane number
  11965.                                          ; AL := Read Map Select register numb
  11966.  
  11967.                  xor     bl,bl           ; BL is used to accumulate the pixel
  11968.  
  11969.  L01:            out     dx,ax           ; (same as before)
  11970.                  mov     bh,es:[si]
  11971.                  and     bh,ch
  11972.                  neg     bh
  11973.  
  11974.                  rol     bx,1
  11975.                  sub     ah,2
  11976.                  jge     L01
  11977.  
  11978.                  mov     al,bl
  11979.                  xor     ah,ah
  11980.  
  11981.                  pop     si
  11982.                  mov     sp,bp
  11983.                  pop     bp
  11984.                  ret
  11985.  
  11986.  _ReadPixel0F    ENDP
  11987.  
  11988.  _TEXT           ENDS
  11989.  
  11990.                  END
  11991.  
  11992.  \SAMPCODE\VIDEO\5\5_6.ASM
  11993.  
  11994.                  TITLE   'Listing 5-6'
  11995.                  NAME    ReadPixel10
  11996.                  PAGE    55,132
  11997.  
  11998.  ;
  11999.  ; Name:         ReadPixel10
  12000.  ;
  12001.  ; Function:     Read the value of a pixel in 640x350 modes on 64K EGA
  12002.  ;
  12003.  ; Caller:       Microsoft C:
  12004.  ;
  12005.  ;                       int     ReadPixel10(x,y);
  12006.  ;
  12007.  ;                       int x,y;                /* pixel coordinates */
  12008.  ;
  12009.  
  12010.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  12011.  ARGy            EQU     word ptr [bp+6]
  12012.  
  12013.  
  12014.  _TEXT           SEGMENT byte public 'CODE'
  12015.                  ASSUME  cs:_TEXT
  12016.  
  12017.                  EXTRN   PixelAddr10:near
  12018.  
  12019.                  PUBLIC  _ReadPixel10
  12020.  _ReadPixel10    PROC    near
  12021.  
  12022.                  push    bp              ; preserve caller registers
  12023.                  mov     bp,sp
  12024.                  push    si
  12025.  
  12026.                  mov     ax,ARGy         ; AX := y
  12027.                  mov     bx,ARGx         ; BX := x
  12028.                  call    PixelAddr10     ; AH := bit mask
  12029.                                          ; ES:BX -> buffer
  12030.                                          ; CL := #bits to shift
  12031.  
  12032.  ; concatenate bits from bit planes 2 and 0 (even byte address)
  12033.  ;  or 3 and 1 (odd byte address)
  12034.  
  12035.                  mov     ch,ah
  12036.                  shl     ch,cl           ; CH := bit mask in proper position
  12037.  
  12038.                  mov     si,bx           ; ES:SI -> regen buffer byte
  12039.  
  12040.                  mov     ah,bl           ; AH := low-order byte of address
  12041.                  and     ax,100h         ; AH := low-order bit of address
  12042.                                          ; AL := 0
  12043.                  add     ax,204h         ; AH := initial bit plane number (2 o
  12044.                                          ; AL := Read Map Select register numb
  12045.  
  12046.                  mov     dx,3CEh         ; DX := Graphics Controller port
  12047.                  xor     bl,bl           ; BL is used to accumulate the pixel
  12048.  
  12049.  L01:            out     dx,ax           ; (same as before)
  12050.                  mov     bh,es:[si]
  12051.                  and     bh,ch
  12052.                  neg     bh
  12053.  
  12054.                  rol     bx,1
  12055.                  sub     ah,2
  12056.                  jge     L01
  12057.  
  12058.                  mov     al,bl
  12059.                  xor     ah,ah
  12060.  
  12061.                  pop     si
  12062.                  mov     sp,bp
  12063.                  pop     bp
  12064.                  ret
  12065.  
  12066.  _ReadPixel10    ENDP
  12067.  
  12068.  _TEXT           ENDS
  12069.  
  12070.                  END
  12071.  
  12072.  \SAMPCODE\VIDEO\5\5_7.ASM
  12073.  
  12074.                  TITLE   'Listing 5-7'
  12075.                  NAME    ReadPixelInC
  12076.                  PAGE    55,132
  12077.  
  12078.  ;
  12079.  ; Name:         ReadPixelInC
  12080.  ;
  12081.  ; Function:     Read the value of a pixel in InColor 720x348 16-color mode
  12082.  ;
  12083.  ; Caller:       Microsoft C:
  12084.  ;
  12085.  ;                       int     ReadPixelInC(x,y);
  12086.  ;
  12087.  ;                       int x,y;
  12088.  ;
  12089.  
  12090.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  12091.  ARGy            EQU     word ptr [bp+6]
  12092.  
  12093.  DefaultRWColor  EQU     0Fh             ; default value for R/W Color Registe
  12094.  
  12095.  
  12096.  _TEXT           SEGMENT byte public 'CODE'
  12097.                  ASSUME  cs:_TEXT
  12098.  
  12099.                  EXTRN   PixelAddrHGC:near
  12100.  
  12101.                  PUBLIC  _ReadPixelInC
  12102.  _ReadPixelInC   PROC    near
  12103.  
  12104.                  push    bp              ; preserve caller registers
  12105.                  mov     bp,sp
  12106.                  push    si
  12107.  
  12108.                  mov     ax,ARGy         ; AX := y
  12109.                  mov     bx,ARGx         ; BX := x
  12110.                  call    PixelAddrHGC    ; AH := bit mask
  12111.                                          ; ES:BX -> buffer
  12112.                                          ; CL := #bits to shift
  12113.  
  12114.  ; set up to examine each bit plane separately
  12115.  
  12116.                  mov     si,bx           ; ES:SI -> buffer
  12117.  
  12118.                  shl     ah,cl
  12119.                  mov     cl,ah           ; CL := bit mask in proper position
  12120.  
  12121.                  mov     dx,3B4h         ; DX := graphics control port
  12122.  
  12123.                  mov     ax,0F01Ah       ; AH bits 4-7 := 1111b (background va
  12124.                                          ; AL := 1Ah (R/W Color Register)
  12125.                  out     dx,ax           ; set background value
  12126.  
  12127.                  mov     bx,800h         ; BH := 1000b (initial "don't care" b
  12128.                                          ; BL := 0 (initial value for result)
  12129.  
  12130.                  dec     ax              ; AL := 19h (R/W Control Register num
  12131.  
  12132.  ; loop across bit planes by updating "don't care" bits
  12133.  
  12134.  L01:            mov     ah,bh           ; AH bits 0-3 := next "don't care" bi
  12135.                                          ; AH bit 6 := 0 (Mask Polarity bit)
  12136.                  xor     ah,1111b        ; invert "don't care" bits
  12137.                  out     dx,ax           ; set R/W Control Register
  12138.  
  12139.                  mov     ch,cl           ; CH := bit mask
  12140.                  and     ch,es:[si]      ; latch bit planes
  12141.                                          ; CH <> 0 if bit in latch is set
  12142.  
  12143.                  neg     ch              ; cf set if CH <> 0
  12144.                  rcl     bl,1            ; accumulate result in BL
  12145.  
  12146.                  shr     bh,1            ; BH := shifted "don't care" bits
  12147.                  jnz     L01             ; loop until shifted out of BH,
  12148.                                          ;  at which point BX = pixel value
  12149.  ; restore default state
  12150.  
  12151.                  mov     ah,40h          ; AH := default R/W Control Register
  12152.                  out     dx,ax
  12153.  
  12154.                  inc     ax              ; AL := 1Ah (R/W Color Register numbe
  12155.                  mov     ah,DefaultRWColor
  12156.                  out     dx,ax
  12157.  
  12158.                  mov     ax,bx           ; AX := pixel value
  12159.  
  12160.                  pop     si              ; restore caller registers and return
  12161.                  mov     sp,bp
  12162.                  pop     bp
  12163.                  ret
  12164.  
  12165.  _ReadPixelInC   ENDP
  12166.  
  12167.  _TEXT           ENDS
  12168.  
  12169.                  END
  12170.  
  12171.  \SAMPCODE\VIDEO\5\5_8.ASM
  12172.  
  12173.                  TITLE   'Listing 5-8'
  12174.                  NAME    ReadPixel11
  12175.                  PAGE    55,132
  12176.  
  12177.  ;
  12178.  ; Name:         ReadPixel11
  12179.  ;
  12180.  ; Function:     Read the value of a pixel in 640x480 2-color mode (MCGA or VG
  12181.  ;
  12182.  ; Caller:       Microsoft C:
  12183.  ;
  12184.  ;                       int ReadPixel11(x,y);
  12185.  ;
  12186.  ;                       int x,y;                /* pixel coordinates */
  12187.  ;
  12188.  
  12189.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  12190.  ARGy            EQU     word ptr [bp+6]
  12191.  
  12192.  
  12193.  _TEXT           SEGMENT byte public 'CODE'
  12194.                  ASSUME  cs:_TEXT
  12195.  
  12196.                  EXTRN   PixelAddr10:near
  12197.  
  12198.                  PUBLIC  _ReadPixel11
  12199.  _ReadPixel11    PROC    near
  12200.  
  12201.                  push    bp              ; preserve caller registers
  12202.                  mov     bp,sp
  12203.  
  12204.                  mov     ax,ARGy         ; AX := y
  12205.                  mov     bx,ARGx         ; BX := x
  12206.                  call    PixelAddr10     ; AH := bit mask
  12207.                                          ; ES:BX -> buffer
  12208.                                          ; CL := #bits to shift
  12209.  
  12210.                  mov     al,es:[bx]      ; AL := byte containing pixel
  12211.                  shr     al,cl           ; shift pixel value to low-order bits
  12212.                  and     al,ah           ; AL := pixel value
  12213.                  xor     ah,ah           ; AX := pixel value
  12214.  
  12215.                  mov     sp,bp           ; restore caller registers and return
  12216.                  pop     bp
  12217.                  ret
  12218.  
  12219.  _ReadPixel11    ENDP
  12220.  
  12221.  _TEXT           ENDS
  12222.  
  12223.                  END
  12224.  
  12225.  \SAMPCODE\VIDEO\5\5_9.ASM
  12226.  
  12227.                  TITLE   'Listing 5-9'
  12228.                  NAME    ReadPixel13
  12229.                  PAGE    55,132
  12230.  
  12231.  ;
  12232.  ; Name:         ReadPixel13
  12233.  ;
  12234.  ; Function:     Read the value of a pixel in 320x200 256-color mode (MCGA and
  12235.  ;
  12236.  ; Caller:       Microsoft C:
  12237.  ;
  12238.  ;                       int ReadPixel13(x,y);
  12239.  ;
  12240.  ;                       int x,y;                /* pixel coordinates */
  12241.  ;
  12242.  
  12243.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  12244.  ARGy            EQU     word ptr [bp+6]
  12245.  
  12246.  
  12247.  _TEXT           SEGMENT byte public 'CODE'
  12248.                  ASSUME  cs:_TEXT
  12249.  
  12250.                  EXTRN   PixelAddr13:near
  12251.  
  12252.                  PUBLIC  _ReadPixel13
  12253.  _ReadPixel13    PROC    near
  12254.  
  12255.                  push    bp              ; preserve caller registers
  12256.                  mov     bp,sp
  12257.  
  12258.                  mov     ax,ARGy         ; AX := y
  12259.                  mov     bx,ARGx         ; BX := x
  12260.                  call    PixelAddr13     ; ES:BX -> buffer
  12261.  
  12262.                  mov     al,es:[bx]      ; AL := pixel value
  12263.                  xor     ah,ah           ; AX := pixel value
  12264.  
  12265.                  mov     sp,bp
  12266.                  pop     bp
  12267.                  ret
  12268.  
  12269.  _ReadPixel13    ENDP
  12270.  
  12271.  _TEXT           ENDS
  12272.  
  12273.                  END
  12274.  
  12275.  \SAMPCODE\VIDEO\6
  12276.  \SAMPCODE\VIDEO\6\6_1.C
  12277.  
  12278.  /* Listing 6-1 */
  12279.  
  12280.  Line( x1, y1, x2, y2, n )
  12281.  int     x1,y1;                  /* endpoint */
  12282.  int     x2,y2;                  /* endpoint */
  12283.  int     n;                      /* pixel value */
  12284.  {
  12285.          int     x,y;
  12286.          float   m;              /* slope */
  12287.          float   b;              /* y-intercept */
  12288.  
  12289.  
  12290.          if (x2 == x1)                           /* vertical line */
  12291.          {
  12292.            if (y1 > y2)
  12293.             Swap( &y1, &y2 );                    /* force y1 < y2 */
  12294.  
  12295.            for (y=y1; y<=y2; y++)                /* draw from y1 to y2 */
  12296.             SetPixel( x1, y, n );
  12297.  
  12298.            return;
  12299.          }
  12300.  
  12301.          if (x1 > x2)                            /* force x1 < x2 */
  12302.          {
  12303.            Swap( &x1, &x2 );
  12304.            Swap( &y1, &y2 );
  12305.          }
  12306.  
  12307.  
  12308.          m = (float)(y2-y1) / (float)(x2-x1);    /* compute m and b */
  12309.          b = y1 - (m*x1);
  12310.  
  12311.          for (x=x1; x<=x2; x++)                  /* draw from x1 to x2 */
  12312.          {
  12313.            y = m*x + b;
  12314.            SetPixel( x, y, n );
  12315.          }
  12316.  }
  12317.  
  12318.  Swap( a, b )                    /* exchange values of a and b */
  12319.  int     *a,*b;
  12320.  {
  12321.          int     t;
  12322.  
  12323.          t = *a;
  12324.          *a = *b;
  12325.          *b = t;
  12326.  }
  12327.  
  12328.  \SAMPCODE\VIDEO\6\6_11.C
  12329.  
  12330.  /* Listing 6-11 */
  12331.  
  12332.  struct  EndpointStruct          /* endpoints for clipped line */
  12333.  {
  12334.    int   x1,y1;
  12335.    int   x2,y2;
  12336.  };
  12337.  
  12338.  struct  RegionStruct            /* rectangular clipping region */
  12339.  {
  12340.    int   Xul;
  12341.    int   Yul;
  12342.    int   Xlr;
  12343.    int   Ylr;
  12344.  };
  12345.  
  12346.  
  12347.  union OutcodeUnion      /* outcodes are represented as bit fields */
  12348.  {
  12349.    struct
  12350.    {
  12351.      unsigned code0 : 1;         /* x < Xul */
  12352.      unsigned code1 : 1;         /* y < Yul */
  12353.      unsigned code2 : 1;         /* x > Xlr */
  12354.      unsigned code3 : 1;         /* y > Ylr */
  12355.    }
  12356.          ocs;
  12357.  
  12358.    int   outcodes;
  12359.  };
  12360.  
  12361.  
  12362.  #define X1      ep->x1
  12363.  #define Y1      ep->y1
  12364.  #define X2      ep->x2
  12365.  #define Y2      ep->y2
  12366.  #define XUL     r->Xul
  12367.  #define YUL     r->Yul
  12368.  #define XLR     r->Xlr
  12369.  #define YLR     r->Ylr
  12370.  
  12371.  
  12372.  Clip(ep,r)
  12373.  struct  EndpointStruct  *ep;
  12374.  struct  RegionStruct    *r;
  12375.  {
  12376.          union OutcodeUnion      ocu1,ocu2;
  12377.          int     Inside;
  12378.          int     Outside;
  12379.  
  12380.  
  12381.          /* initialize 4-bit codes */
  12382.  
  12383.          SetOutcodes( &ocu1, r, X1, Y1 );        /* initial 4-bit codes */
  12384.          SetOutcodes( &ocu2, r, X2, Y2 );
  12385.  
  12386.          Inside  = ((ocu1.outcodes | ocu2.outcodes) == 0);
  12387.          Outside = ((ocu1.outcodes & ocu2.outcodes) != 0);
  12388.  
  12389.          while (!Outside && !Inside)
  12390.          {
  12391.            if (ocu1.outcodes==0)         /* swap endpoints if necessary so */
  12392.            {                             /*  that (x1,y1) needs to be clipped
  12393.              Swap( &X1, &X2 );
  12394.              Swap( &Y1, &Y2 );
  12395.              Swap( &ocu1, &ocu2 );
  12396.            }
  12397.  
  12398.  
  12399.            if (ocu1.ocs.code0)                   /* clip left */
  12400.            {
  12401.              Y1 += (long)(Y2-Y1)*(XUL-X1)/(X2-X1);
  12402.              X1 = XUL;
  12403.            }
  12404.  
  12405.            else if (ocu1.ocs.code1)              /* clip above */
  12406.            {
  12407.              X1 += (long)(X2-X1)*(YUL-Y1)/(Y2-Y1);
  12408.              Y1 = YUL;
  12409.            }
  12410.  
  12411.            else if (ocu1.ocs.code2)              /* clip right */
  12412.            {
  12413.              Y1 += (long)(Y2-Y1)*(XLR-X1)/(X2-X1);
  12414.              X1 = XLR;
  12415.            }
  12416.  
  12417.            else if (ocu1.ocs.code3)              /* clip below */
  12418.            {
  12419.              X1 += (long)(X2-X1)*(YLR-Y1)/(Y2-Y1);
  12420.              Y1 = YLR;
  12421.            }
  12422.  
  12423.            SetOutcodes( &ocu1, r, X1, Y1 );            /* update for (x1,y1) *
  12424.  
  12425.            Inside  = ((ocu1.outcodes | ocu2.outcodes) == 0); /* update       *
  12426.            Outside = ((ocu1.outcodes & ocu2.outcodes) != 0); /*  4-bit codes *
  12427.          }
  12428.  
  12429.          return( Inside );
  12430.  }
  12431.  
  12432.  
  12433.  SetOutcodes( u, r, x, y )
  12434.  union OutcodeUnion      *u;
  12435.  struct RegionStruct     *r;
  12436.  int     x,y;
  12437.  {
  12438.          u->outcodes = 0;
  12439.          u->ocs.code0 = (x < XUL);
  12440.          u->ocs.code1 = (y < YUL);
  12441.          u->ocs.code2 = (x > XLR);
  12442.          u->ocs.code3 = (y > YLR);
  12443.  }
  12444.  
  12445.  
  12446.  Swap( pa, pb )
  12447.  int     *pa,*pb;
  12448.  {
  12449.          int     t;
  12450.  
  12451.          t = *pa;
  12452.          *pa = *pb;
  12453.          *pb = t;
  12454.  }
  12455.  
  12456.  \SAMPCODE\VIDEO\6\6_2.C
  12457.  
  12458.  /* Listing 6-2 */
  12459.  
  12460.  Line( x1, y1, x2, y2, n )       /* for lines with slope between -1 and 1 */
  12461.  int     x1,y1;
  12462.  int     x2,y2;                  /* endpoints */
  12463.  int     n;                      /* pixel value */
  12464.  {
  12465.          int     d,dx,dy;
  12466.          int     Aincr,Bincr,yincr;
  12467.          int     x,y;
  12468.  
  12469.  
  12470.          if (x1 > x2)                            /* force x1 < x2 */
  12471.          {
  12472.            Swap( &x1, &x2 );
  12473.            Swap( &y1, &y2 );
  12474.          }
  12475.  
  12476.          if (y2 > y1)                            /* determine increment for y
  12477.            yincr = 1;
  12478.          else
  12479.            yincr = -1;
  12480.  
  12481.          dx = x2 - x1;                           /* initialize constants */
  12482.          dy = abs( y2-y1 );
  12483.          d = 2 * dy - dx;
  12484.  
  12485.          Aincr = 2 * (dy - dx);
  12486.          Bincr = 2 * dy;
  12487.  
  12488.          x = x1;                                 /* initial x and y */
  12489.          y = y1;
  12490.  
  12491.          SetPixel( x, y, n );                    /* set pixel at (x1,y1) */
  12492.  
  12493.          for (x=x1+1; x<=x2; x++)                /* do from x1+1 to x2 */
  12494.          {
  12495.            if (d >= 0)
  12496.            {
  12497.              y += yincr;                         /* set pixel A */
  12498.              d += Aincr;
  12499.            }
  12500.            else                                  /* set pixel B */
  12501.              d += Bincr;
  12502.  
  12503.            SetPixel( x, y, n );
  12504.          }
  12505.  }
  12506.  
  12507.  
  12508.  Swap( pa, pb )
  12509.  int     *pa,*pb;
  12510.  {
  12511.          int     t;
  12512.  
  12513.          t = *pa;
  12514.          *pa = *pb;
  12515.          *pb = t;
  12516.  }
  12517.  
  12518.  \SAMPCODE\VIDEO\6\6_3.C
  12519.  
  12520.  /* Listing 6-3 */
  12521.  
  12522.  FilledRectangle( x1, y1, x2, y2, n )
  12523.  int     x1,y1;                  /* upper left corner */
  12524.  int     x2,y2;                  /* lower right corner */
  12525.  int     n;                      /* pixel value */
  12526.  {
  12527.          int     y;
  12528.  
  12529.          for (y=y1; y<=y2; y++)          /* draw rectangle as a set of */
  12530.            Line( x1, y, x2, y, n );      /*  adjacent horizontal lines */
  12531.  }
  12532.  
  12533.  \SAMPCODE\VIDEO\6\6_10.ASM
  12534.  
  12535.                  TITLE   'Listing 6-10'
  12536.                  NAME    LineInC
  12537.                  PAGE    55,132
  12538.  
  12539.  ;
  12540.  ; Name:         LineInC
  12541.  ;
  12542.  ; Function:     Draw a line in Hercules InColor 720x348 16-color mode
  12543.  ;
  12544.  ; Caller:       Microsoft C:
  12545.  ;
  12546.  ;                       void LineInC(x1,y1,x2,y2,n);
  12547.  ;
  12548.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  12549.  ;
  12550.  ;                       int n;                  /* pixel value */
  12551.  ;
  12552.  
  12553.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  12554.  ARGy1           EQU     word ptr [bp+6]
  12555.  ARGx2           EQU     word ptr [bp+8]
  12556.  ARGy2           EQU     word ptr [bp+10]
  12557.  ARGn            EQU     byte ptr [bp+12]
  12558.  VARleafincr     EQU     word ptr [bp-2]
  12559.  VARincr1        EQU     word ptr [bp-4]
  12560.  VARincr2        EQU     word ptr [bp-6]
  12561.  VARroutine      EQU     word ptr [bp-8]
  12562.  
  12563.  ByteOffsetShift EQU     3               ; used to convert pixels to byte offs
  12564.  DefaultRWColor  EQU     0Fh             ; default value for R/W Color registe
  12565.  
  12566.  
  12567.  _TEXT           SEGMENT byte public 'CODE'
  12568.                  ASSUME  cs:_TEXT
  12569.  
  12570.                  EXTRN   PixelAddrHGC:near
  12571.  
  12572.                  PUBLIC  _LineInC
  12573.  _LineInC        PROC    near
  12574.  
  12575.                  push    bp              ; preserve caller registers
  12576.                  mov     bp,sp
  12577.                  sub     sp,8            ; stack space for local variables
  12578.                  push    si
  12579.                  push    di
  12580.  
  12581.                  mov     si,2000h        ; increment for video buffer interlea
  12582.                  mov     di,90-8000h     ; increment from last to first interl
  12583.  
  12584.  ; set up InColor CRTC registers
  12585.  
  12586.                  mov     dx,3B4h         ; DX := CRTC I/O port
  12587.                  mov     ax,5F19h        ; AH bit 6 := 1 (Mask Polarity)
  12588.                                          ; AH bits 5-4 := 1 (Write Mode)
  12589.                                          ; AH bits 3-0 := "don't care" bits
  12590.                                          ; AL := R/W Control Register number
  12591.                  out     dx,ax           ; set R/W Control Register
  12592.  
  12593.                  inc     ax              ; AL := 1Ah (R/W Color Reg number)
  12594.                  mov     ah,ARGn         ; AH := foreground value
  12595.                  out     dx,ax           ; set R/W color register
  12596.  
  12597.  
  12598.                  mov     cx,ARGx2
  12599.                  sub     cx,ARGx1        ; CX := x2 - x1
  12600.                  jz      VertLineInC     ; jump if vertical line
  12601.  
  12602.  ; force x1 < x2
  12603.  
  12604.                  jns     L01             ; jump if x2 > x1
  12605.  
  12606.                  neg     cx              ; CX := x1 - x2
  12607.  
  12608.                  mov     bx,ARGx2        ; exchange x1 and x2
  12609.                  xchg    bx,ARGx1
  12610.                  mov     ARGx2,bx
  12611.  
  12612.                  mov     bx,ARGy2        ; exchange y1 and y2
  12613.                  xchg    bx,ARGy1
  12614.                  mov     ARGy2,bx
  12615.  
  12616.  ; calculate dy = ABS(y2-y1)
  12617.  
  12618.  L01:            mov     bx,ARGy2
  12619.                  sub     bx,ARGy1        ; BX := y2 - y1
  12620.                  jz      HorizLineInC    ; jump if horizontal line
  12621.  
  12622.                  jns     L03
  12623.  
  12624.                  neg     bx              ; BX := y1 - y2
  12625.                  neg     si              ; negate increments for buffer interl
  12626.                  neg     di
  12627.  
  12628.  ; select appropriate routine for slope of line
  12629.  
  12630.  L03:            mov     VARleafincr,di  ; save increment for buffer interleav
  12631.  
  12632.                  mov     VARroutine,offset LoSlopeLineInC
  12633.                  cmp     bx,cx
  12634.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  12635.                  mov     VARroutine,offset HiSlopeLineInC
  12636.                  xchg    bx,cx           ; exchange dy and dx
  12637.  
  12638.  ; calculate initial decision variable and increments
  12639.  
  12640.  L04:            shl     bx,1            ; BX := 2 * dy
  12641.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  12642.                  sub     bx,cx
  12643.                  mov     di,bx           ; DI := d = 2 * dy - dx
  12644.                  sub     bx,cx
  12645.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  12646.  
  12647.  ; calculate first pixel address
  12648.  
  12649.                  push    cx              ; preserve this register
  12650.                  mov     ax,ARGy1        ; AX := y
  12651.                  mov     bx,ARGx1        ; BX := x
  12652.                  call    PixelAddrHGC    ; AH := bit mask
  12653.                                          ; ES:BX -> buffer
  12654.                                          ; CL := # bits to shift left
  12655.  
  12656.                  shl     ah,cl
  12657.                  mov     dh,ah           ; DH := bit mask in proper position
  12658.  
  12659.                  pop     cx              ; restore this register
  12660.                  inc     cx              ; CX := # of pixels to draw
  12661.  
  12662.                  jmp     VARroutine      ; jump to appropriate routine for slo
  12663.  
  12664.  
  12665.  ; routine for vertical lines
  12666.  
  12667.  VertLineInC:    mov     ax,ARGy1        ; AX := y1
  12668.                  mov     bx,ARGy2        ; BX := y2
  12669.                  mov     cx,bx
  12670.                  sub     cx,ax           ; CX := dy
  12671.                  jge     L31             ; jump if dy >= 0
  12672.  
  12673.                  neg     cx              ; force dy >= 0
  12674.                  mov     ax,bx           ; AX := y2
  12675.  
  12676.  L31:            inc     cx              ; CX := # of pixels to draw
  12677.                  mov     bx,ARGx1        ; BX := x
  12678.                  push    cx              ; preserve this register
  12679.                  call    PixelAddrHGC    ; AH := bit mask
  12680.                                          ; ES:BX -> video buffer
  12681.                                          ; CL := # bits to shift left
  12682.                  shl     ah,cl           ; AH := bit mask in proper position
  12683.                  pop     cx              ; restore this register
  12684.  
  12685.  L32:            or      es:[bx],ah      ; update pixel in buffer
  12686.  
  12687.                  add     bx,si           ; increment to next portion of interl
  12688.                  jns     L33
  12689.  
  12690.                  add     bx,di           ; increment to first portion of inter
  12691.  
  12692.  L33:            loop    L32
  12693.  
  12694.                  jmp     Lexit
  12695.  
  12696.  
  12697.  
  12698.  ; routine for horizontal lines (slope = 0)
  12699.  
  12700.  HorizLineInC:   mov     ax,ARGy1
  12701.                  mov     bx,ARGx1
  12702.                  call    PixelAddrHGC    ; AH := bit mask
  12703.                                          ; ES:BX -> video buffer
  12704.                                          ; CL := # bits to shift left
  12705.                  mov     di,bx           ; ES:DI -> buffer
  12706.  
  12707.                  mov     dh,ah
  12708.                  not     dh              ; DH := unshifted bit mask for leftmo
  12709.                                          ;        byte
  12710.                  mov     dl,0FFh         ; DL := unshifted bit mask for
  12711.                                          ;        rightmost byte
  12712.  
  12713.                  shl     dh,cl           ; DH := reverse bit mask for first by
  12714.                  not     dh              ; DH := bit mask for first byte
  12715.  
  12716.                  mov     cx,ARGx2
  12717.                  and     cl,7
  12718.                  xor     cl,7            ; CL := number of bits to shift left
  12719.                  shl     dl,cl           ; DL := bit mask for last byte
  12720.  
  12721.  ; determine byte offset of first and last pixel in the line
  12722.  
  12723.                  mov     ax,ARGx2        ; AX := x2
  12724.                  mov     bx,ARGx1        ; BX := x1
  12725.  
  12726.                  mov     cl,ByteOffsetShift      ; number of bits to shift to
  12727.                                                  ;  convert pixels to bytes
  12728.  
  12729.                  shr     ax,cl           ; AX := byte offset of x2
  12730.                  shr     bx,cl           ; BX := byte offset of x1
  12731.                  mov     cx,ax
  12732.                  sub     cx,bx           ; CX := (# bytes in line) - 1
  12733.  
  12734.  ; set pixels in leftmost byte of the line
  12735.  
  12736.                  or      dh,dh
  12737.                  js      L43             ; jump if byte-aligned (x1 is leftmos
  12738.                                          ;  pixel in byte)
  12739.                  or      cx,cx
  12740.                  jnz     L42             ; jump if more than one byte in the l
  12741.  
  12742.                  and     dl,dh           ; bit mask for the line
  12743.                  jmp     short L44
  12744.  
  12745.  L42:            or      es:[di],dh      ; update masked pixels in buffer
  12746.                  inc     di
  12747.                  dec     cx
  12748.  
  12749.  ; use a fast 8086 machine instruction to draw the remainder of the line
  12750.  
  12751.  L43:            mov     al,0FFh         ; 8-pixel bit mask
  12752.                  rep     stosb           ; update all pixels in the line
  12753.  
  12754.  ; set pixels in the rightmost byte of the line
  12755.  
  12756.  L44:            or      es:[di],dl      ; update masked pixels in buffer
  12757.                  jmp     Lexit
  12758.  
  12759.  
  12760.  ; routine for dy <= dx (slope <= 1)     ; ES:BX -> video buffer
  12761.                                          ; CX = # pixels to draw
  12762.                                          ; DH = bit mask
  12763.                                          ; SI = buffer interleave increment
  12764.                                          ; DI = decision variable
  12765.  LoSlopeLineInC:
  12766.  
  12767.  L10:            mov     ah,es:[bx]      ; latch bit planes
  12768.                                          ; AH := 0 because all planes
  12769.                                          ;  are "don't care"
  12770.  
  12771.  L11:            or      ah,dh           ; set pixel value in byte
  12772.  
  12773.                  ror     dh,1            ; rotate bit mask
  12774.                  jc      L14             ; jump if bit mask rotated to
  12775.                                          ;  leftmost pixel position
  12776.  
  12777.  ; bit mask not shifted out
  12778.  
  12779.                  or      di,di           ; test sign of d
  12780.                  jns     L12             ; jump if d >= 0
  12781.  
  12782.                  add     di,VARincr1     ; d := d + incr1
  12783.                  loop    L11
  12784.  
  12785.                  mov     es:[bx],ah      ; store remaining pixels in buffer
  12786.                  jmp     short Lexit
  12787.  
  12788.  L12:            add     di,VARincr2     ; d := d + incr2
  12789.                  mov     es:[bx],ah      ; update buffer
  12790.  
  12791.                  add     bx,si           ; increment y
  12792.                  jns     L13             ; jump if not in last interleave
  12793.  
  12794.                  add     bx,VARleafincr  ; increment into next interleave
  12795.  
  12796.  L13:            loop    L10
  12797.                  jmp     short Lexit
  12798.  
  12799.  ; bit mask shifted out
  12800.  
  12801.  L14:            mov     es:[bx],ah      ; update buffer
  12802.                  inc     bx              ; BX := offset of next byte
  12803.  
  12804.                  or      di,di           ; test sign of d
  12805.                  jns     L15             ; jump if non-negative
  12806.  
  12807.                  add     di,VARincr1     ; d := d + incr1
  12808.                  loop    L10
  12809.                  jmp     short Lexit
  12810.  
  12811.  L15:            add     di,VARincr2     ; d := d + incr2
  12812.  
  12813.                  add     bx,si           ; increment y
  12814.                  jns     L16             ; jump if not in last interleave
  12815.  
  12816.                  add     bx,VARleafincr  ; increment into next interleave
  12817.  
  12818.  L16:            loop    L10             ; loop until all pixels are set
  12819.                  jmp     short Lexit
  12820.  
  12821.  
  12822.  ; routine for dy > dx (slope > 1)       ; ES:BX -> video buffer
  12823.                                          ; CX = # pixels to draw
  12824.                                          ; DH = bit mask
  12825.                                          ; SI = buffer interleave increment
  12826.                                          ; DI = decision variable
  12827.  HiSlopeLineInC:
  12828.  
  12829.  L21:            or      es:[bx],dh      ; set pixel value in video buffer
  12830.  
  12831.                  add     bx,si           ; increment y
  12832.                  jns     L22             ; jump if not in last interleave
  12833.  
  12834.                  add     bx,VARleafincr  ; increment into next interleave
  12835.  
  12836.  L22:            or      di,di
  12837.                  jns     L23             ; jump if d >= 0
  12838.  
  12839.                  add     di,VARincr1     ; d := d + incr1
  12840.                  loop    L21
  12841.                  jmp     short Lexit
  12842.  
  12843.  
  12844.  L23:            add     di,VARincr2     ; d := d + incr2
  12845.  
  12846.                  ror     dh,1            ; rotate bit mask
  12847.                  adc     bx,0            ; BX := offset of next byte (incremen
  12848.                                          ;  if bit mask rotated to
  12849.                                          ;  leftmost pixel position
  12850.  
  12851.                  loop    L21
  12852.  
  12853.  
  12854.  Lexit:          mov     dx,3B4h         ; DX := CRTC I/O port
  12855.                  mov     ax,0F18h
  12856.                  out     dx,ax           ; restore default Plane Mask value
  12857.  
  12858.                  mov     ax,4019h        ; restore default R/W Control value
  12859.                  out     dx,ax
  12860.  
  12861.                  inc     ax              ; restore default R/W Color value
  12862.                  mov     ah,DefaultRWColor
  12863.                  out     dx,ax
  12864.  
  12865.                  pop     di              ; restore registers and return
  12866.                  pop     si
  12867.                  mov     sp,bp
  12868.                  pop     bp
  12869.                  ret
  12870.  
  12871.  _LineInC        ENDP
  12872.  
  12873.  _TEXT           ENDS
  12874.  
  12875.                  END
  12876.  
  12877.  \SAMPCODE\VIDEO\6\6_4.ASM
  12878.  
  12879.                  TITLE   'Listing 6-4'
  12880.                  NAME    Line06
  12881.                  PAGE    55,132
  12882.  
  12883.  ;
  12884.  ; Name:         Line06
  12885.  ;
  12886.  ; Function:     Draw a line in 640x200 2-color mode
  12887.  ;
  12888.  ; Caller:       Microsoft C:
  12889.  ;
  12890.  ;                       void Line06(x1,y1,x2,y2,n);
  12891.  ;
  12892.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  12893.  ;
  12894.  ;                       int n;                  /* pixel value */
  12895.  ;
  12896.  
  12897.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  12898.  ARGy1           EQU     word ptr [bp+6]
  12899.  ARGx2           EQU     word ptr [bp+8]
  12900.  ARGy2           EQU     word ptr [bp+10]
  12901.  ARGn            EQU     byte ptr [bp+12]
  12902.  VARleafincr     EQU     word ptr [bp-2]
  12903.  VARincr1        EQU     word ptr [bp-4]
  12904.  VARincr2        EQU     word ptr [bp-6]
  12905.  VARroutine      EQU     word ptr [bp-8]
  12906.  
  12907.  ByteOffsetShift EQU     3               ; used to convert pixels to byte offs
  12908.  
  12909.  DGROUP          GROUP   _DATA
  12910.  
  12911.  _TEXT           SEGMENT byte public 'CODE'
  12912.                  ASSUME  cs:_TEXT,ds:DGROUP
  12913.  
  12914.                  EXTRN   PixelAddr06:near
  12915.  
  12916.                  PUBLIC  _Line06
  12917.  _Line06         PROC    near
  12918.  
  12919.                  push    bp              ; preserve caller registers
  12920.                  mov     bp,sp
  12921.                  sub     sp,8            ; stack space for local variables
  12922.                  push    si
  12923.                  push    di
  12924.  
  12925.  
  12926.                  mov     si,2000h        ; increment for video buffer interlea
  12927.                  mov     di,80-2000h     ; increment from last to first interl
  12928.  
  12929.                  mov     cx,ARGx2
  12930.                  sub     cx,ARGx1        ; CX := x2 - x1
  12931.                  jz      VertLine06      ; jump if vertical line
  12932.  
  12933.  ; force x1 < x2
  12934.  
  12935.                  jns     L01             ; jump if x2 > x1
  12936.  
  12937.                  neg     cx              ; CX := x1 - x2
  12938.  
  12939.                  mov     bx,ARGx2        ; exchange x1 and x2
  12940.                  xchg    bx,ARGx1
  12941.                  mov     ARGx2,bx
  12942.  
  12943.                  mov     bx,ARGy2        ; exchange y1 and y2
  12944.                  xchg    bx,ARGy1
  12945.                  mov     ARGy2,bx
  12946.  
  12947.  ; calculate dy = ABS(y2-y1)
  12948.  
  12949.  L01:            mov     bx,ARGy2
  12950.                  sub     bx,ARGy1        ; BX := y2 - y1
  12951.                  jnz     L02
  12952.  
  12953.                  jmp     HorizLine06     ; jump if horizontal line
  12954.  
  12955.  L02:            jns     L03
  12956.  
  12957.                  neg     bx              ; BX := y1 - y2
  12958.                  neg     si              ; negate increments for buffer interl
  12959.                  neg     di
  12960.                  xchg    si,di           ; exchange increments
  12961.  
  12962.  ; select appropriate routine for slope of line
  12963.  
  12964.  L03:            mov     VARleafincr,di  ; save increment for buffer interleav
  12965.  
  12966.                  mov     VARroutine,offset LoSlopeLine06
  12967.                  cmp     bx,cx
  12968.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  12969.                  mov     VARroutine,offset HiSlopeLine06
  12970.                  xchg    bx,cx           ; exchange dy and dx
  12971.  
  12972.  ; calculate initial decision variable and increments
  12973.  
  12974.  L04:            shl     bx,1            ; BX := 2 * dy
  12975.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  12976.                  sub     bx,cx
  12977.                  mov     di,bx           ; DI := d = 2 * dy - dx
  12978.                  sub     bx,cx
  12979.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  12980.  
  12981.  ; calculate first pixel address
  12982.  
  12983.                  push    cx              ; preserve this register
  12984.                  mov     ax,ARGy1        ; AX := y
  12985.                  mov     bx,ARGx1        ; BX := x
  12986.                  call    PixelAddr06     ; AH := bit mask
  12987.                                          ; ES:BX -> buffer
  12988.                                          ; CL := # bits to shift left
  12989.  
  12990.                  mov     al,ARGn         ; AL := unshifted pixel value
  12991.                  shl     ax,cl           ; AH := bit mask in proper position
  12992.                                          ; AL := pixel value in proper positio
  12993.  
  12994.                  mov     dx,ax           ; DH := bit mask
  12995.                                          ; DL := pixel value
  12996.                  not     dh              ; DH := inverse bit mask
  12997.  
  12998.                  pop     cx              ; restore this register
  12999.                  inc     cx              ; CX := # of pixels to draw
  13000.  
  13001.                  test    bx,2000h        ; set zero flag if BX in 1st interlea
  13002.                  jz      L05
  13003.  
  13004.                  xchg    si,VARleafincr  ; exchange increment values if 1st pi
  13005.                                          ;  lies in 1st interleave
  13006.  
  13007.  L05:            jmp     VARroutine      ; jump to appropriate routine for slo
  13008.  
  13009.  
  13010.  ; routine for vertical lines
  13011.  
  13012.  VertLine06:     mov     ax,ARGy1        ; AX := y1
  13013.                  mov     bx,ARGy2        ; BX := y2
  13014.                  mov     cx,bx
  13015.                  sub     cx,ax           ; CX := dy
  13016.                  jge     L31             ; jump if dy >= 0
  13017.  
  13018.                  neg     cx              ; force dy >= 0
  13019.                  mov     ax,bx           ; AX := y2
  13020.  
  13021.  L31:            inc     cx              ; CX := # of pixels to draw
  13022.                  mov     bx,ARGx1        ; BX := x
  13023.                  push    cx              ; preserve this register
  13024.                  call    PixelAddr06     ; AH := bit mask
  13025.                                          ; ES:BX -> video buffer
  13026.                                          ; CL := # bits to shift left
  13027.                  mov     al,ARGn         ; AL := pixel value
  13028.                  shl     ax,cl           ; AH := bit mask in proper position
  13029.                                          ; AL := pixel value in proper positio
  13030.                  not     ah              ; AH := inverse bit mask
  13031.                  pop     cx              ; restore this register
  13032.  
  13033.                  test    bx,si           ; set zero flag if BX in 1st interlea
  13034.                  jz      L32
  13035.  
  13036.                  xchg    si,di           ; exchange increment values if 1st pi
  13037.                                          ;  lies in 1st interleave
  13038.  
  13039.  L32:            test    al,al
  13040.                  jz      L34             ; jump if pixel value = 0
  13041.  
  13042.  L33:            or      es:[bx],al      ; set pixel values in buffer
  13043.                  add     bx,si           ; increment to next portion of interl
  13044.                  xchg    si,di           ; toggle between increment values
  13045.                  loop    L33             ; loop down the line
  13046.                  jmp     short L35
  13047.  
  13048.  L34:            and     es:[bx],ah      ; reset pixel values in buffer
  13049.                  add     bx,si           ; increment to next portion of interl
  13050.                  xchg    si,di           ; toggle between increment values
  13051.                  loop    L34
  13052.  
  13053.  L35:            jmp     Lexit
  13054.  
  13055.  
  13056.  ; routine for horizontal lines (slope = 0)
  13057.  
  13058.  HorizLine06:    mov     ax,ARGy1
  13059.                  mov     bx,ARGx1
  13060.                  call    PixelAddr06     ; AH := bit mask
  13061.                                          ; ES:BX -> video buffer
  13062.                                          ; CL := # bits to shift left
  13063.                  mov     di,bx           ; ES:DI -> buffer
  13064.  
  13065.                  mov     dh,ah
  13066.                  not     dh              ; DH := unshifted bit mask for leftmo
  13067.                                          ;        byte
  13068.                  mov     dl,0FFh         ; DL := unshifted bit mask for
  13069.                                          ;        rightmost byte
  13070.  
  13071.                  shl     dh,cl           ; DH := reverse bit mask for first by
  13072.                  not     dh              ; DH := bit mask for first byte
  13073.  
  13074.                  mov     cx,ARGx2
  13075.                  and     cl,7
  13076.                  xor     cl,7            ; CL := number of bits to shift left
  13077.                  shl     dl,cl           ; DL := bit mask for last byte
  13078.  
  13079.  ; determine byte offset of first and last pixel in the line
  13080.  
  13081.                  mov     ax,ARGx2        ; AX := x2
  13082.                  mov     bx,ARGx1        ; BX := x1
  13083.  
  13084.                  mov     cl,ByteOffsetShift      ; number of bits to shift to
  13085.                                                  ;  convert pixels to bytes
  13086.  
  13087.                  shr     ax,cl           ; AX := byte offset of x2
  13088.                  shr     bx,cl           ; BX := byte offset of x1
  13089.                  mov     cx,ax
  13090.                  sub     cx,bx           ; CX := (# bytes in line) - 1
  13091.  
  13092.  ; propagate pixel value throughout one byte
  13093.  
  13094.                  mov     bx,offset DGROUP:PropagatedPixel
  13095.                  mov     al,ARGn         ; AL := pixel value
  13096.                  xlat
  13097.  
  13098.  ; set pixels in leftmost byte of the line
  13099.  
  13100.                  or      dh,dh
  13101.                  js      L43             ; jump if byte-aligned (x1 is leftmos
  13102.                                          ;  pixel in byte)
  13103.                  or      cx,cx
  13104.                  jnz     L42             ; jump if more than one byte in the l
  13105.  
  13106.                  and     dl,dh           ; bit mask for the line
  13107.                  jmp     short L44
  13108.  
  13109.  L42:            mov     ah,al
  13110.                  and     ah,dh           ; AH := masked pixel bits
  13111.                  not     dh              ; DH := reverse bit mask for 1st byte
  13112.                  and     es:[di],dh      ; zero masked pixels in buffer
  13113.                  or      es:[di],ah      ; update masked pixels in buffer
  13114.                  inc     di
  13115.                  dec     cx
  13116.  
  13117.  ; use a fast 8086 machine instruction to draw the remainder of the line
  13118.  
  13119.  L43:            rep     stosb           ; update all pixels in the line
  13120.  
  13121.  ; set pixels in the rightmost byte of the line
  13122.  
  13123.  L44:            and     al,dl           ; AL := masked pixels for last byte
  13124.                  not     dl
  13125.                  and     es:[di],dl      ; zero masked pixels in buffer
  13126.                  or      es:[di],al      ; update masked pixels in buffer
  13127.  
  13128.                  jmp     Lexit
  13129.  
  13130.  
  13131.  ; routine for dy <= dx (slope <= 1)     ; ES:BX -> video buffer
  13132.                                          ; CX = # pixels to draw
  13133.                                          ; DH = inverse bit mask
  13134.                                          ; DL = pixel value in proper position
  13135.                                          ; SI = buffer interleave increment
  13136.                                          ; DI = decision variable
  13137.  LoSlopeLine06:
  13138.  
  13139.  L10:            mov     ah,es:[bx]      ; AH := byte from video buffer
  13140.  
  13141.  L11:            and     ah,dh           ; zero pixel value at current bit off
  13142.                  or      ah,dl           ; set pixel value in byte
  13143.  
  13144.                  ror     dl,1            ; rotate pixel value
  13145.                  ror     dh,1            ; rotate bit mask
  13146.                  jnc     L14             ; jump if bit mask rotated to
  13147.                                          ;  leftmost pixel position
  13148.  
  13149.  ; bit mask not shifted out
  13150.  
  13151.                  or      di,di           ; test sign of d
  13152.                  jns     L12             ; jump if d >= 0
  13153.  
  13154.                  add     di,VARincr1     ; d := d + incr1
  13155.                  loop    L11
  13156.  
  13157.                  mov     es:[bx],ah      ; store remaining pixels in buffer
  13158.                  jmp     short Lexit
  13159.  
  13160.  L12:            add     di,VARincr2     ; d := d + incr2
  13161.                  mov     es:[bx],ah      ; update buffer
  13162.  
  13163.                  add     bx,si           ; increment y
  13164.                  xchg    si,VARleafincr  ; exchange interleave increment value
  13165.                  loop    L10
  13166.                  jmp     short Lexit
  13167.  
  13168.  ; bit mask shifted out
  13169.  
  13170.  L14:            mov     es:[bx],ah      ; update buffer
  13171.                  inc     bx              ; BX := offset of next byte
  13172.  
  13173.                  or      di,di           ; test sign of d
  13174.                  jns     L15             ; jump if non-negative
  13175.  
  13176.                  add     di,VARincr1     ; d := d + incr1
  13177.                  loop    L10
  13178.                  jmp     short Lexit
  13179.  
  13180.  L15:            add     di,VARincr2     ; d := d + incr2
  13181.  
  13182.                  add     bx,si           ; increment y
  13183.                  xchg    si,VARleafincr
  13184.  
  13185.                  loop    L10
  13186.                  jmp     short Lexit
  13187.  
  13188.  
  13189.  ; routine for dy > dx (slope > 1)       ; ES:BX -> video buffer
  13190.                                          ; CX = # pixels to draw
  13191.                                          ; DH = inverse bit mask
  13192.                                          ; DL = pixel value in proper position
  13193.                                          ; SI = buffer interleave increment
  13194.                                          ; DI = decision variable
  13195.  HiSlopeLine06:
  13196.  
  13197.  L21:            and     es:[bx],dh      ; zero pixel value in video buffer
  13198.                  or      es:[bx],dl      ; set pixel value in byte
  13199.  
  13200.                  add     bx,si           ; increment y
  13201.                  xchg    si,VARleafincr  ; exchange interleave increment value
  13202.  
  13203.  L22:            or      di,di           ; test sign of d
  13204.                  jns     L23             ; jump if d >= 0
  13205.  
  13206.                  add     di,VARincr1     ; d := d + incr1
  13207.                  loop    L21
  13208.  
  13209.                  jmp     short Lexit
  13210.  
  13211.  
  13212.  L23:            add     di,VARincr2     ; d := d + incr2
  13213.  
  13214.                  ror     dl,1            ; rotate pixel value
  13215.                  ror     dh,1            ; rotate bit mask
  13216.                  cmc                     ; cf set if bit mask not rotated to
  13217.                                          ;  leftmost pixel position
  13218.  
  13219.                  adc     bx,0            ; BX := offset of next byte
  13220.  
  13221.                  loop    L21
  13222.  
  13223.  
  13224.  Lexit:          pop     di              ; restore registers and return
  13225.                  pop     si
  13226.                  mov     sp,bp
  13227.                  pop     bp
  13228.                  ret
  13229.  
  13230.  _Line06         ENDP
  13231.  
  13232.  _TEXT           ENDS
  13233.  
  13234.  
  13235.  _DATA           SEGMENT word public 'DATA'
  13236.  
  13237.  PropagatedPixel DB      00000000b       ; 0
  13238.                  DB      11111111b       ; 1
  13239.  
  13240.  _DATA           ENDS
  13241.  
  13242.                  END
  13243.  
  13244.  \SAMPCODE\VIDEO\6\6_5.ASM
  13245.  
  13246.                  TITLE   'Listing 6-5'
  13247.                  NAME    Line04
  13248.                  PAGE    55,132
  13249.  
  13250.  ;
  13251.  ; Name:         Line04
  13252.  ;
  13253.  ; Function:     Draw a line in 320x200 4-color mode
  13254.  ;
  13255.  ; Caller:       Microsoft C:
  13256.  ;
  13257.  ;                       void Line04(x1,y1,x2,y2,n);
  13258.  ;
  13259.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  13260.  ;
  13261.  ;                       int n;                  /* pixel value */
  13262.  ;
  13263.  
  13264.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  13265.  ARGy1           EQU     word ptr [bp+6]
  13266.  ARGx2           EQU     word ptr [bp+8]
  13267.  ARGy2           EQU     word ptr [bp+10]
  13268.  ARGn            EQU     byte ptr [bp+12]
  13269.  VARleafincr     EQU     word ptr [bp-2]
  13270.  VARincr1        EQU     word ptr [bp-4]
  13271.  VARincr2        EQU     word ptr [bp-6]
  13272.  VARroutine      EQU     word ptr [bp-8]
  13273.  
  13274.  ByteOffsetShift EQU     2               ; used to convert pixels to byte offs
  13275.  
  13276.  DGROUP          GROUP   _DATA
  13277.  
  13278.  _TEXT           SEGMENT byte public 'CODE'
  13279.                  ASSUME  cs:_TEXT,ds:DGROUP
  13280.  
  13281.                  EXTRN   PixelAddr04:near
  13282.  
  13283.                  PUBLIC  _Line04
  13284.  _Line04         PROC    near
  13285.  
  13286.                  push    bp              ; preserve caller registers
  13287.                  mov     bp,sp
  13288.                  sub     sp,8            ; stack space for local variables
  13289.                  push    si
  13290.                  push    di
  13291.  
  13292.  
  13293.                  mov     si,2000h        ; increment for video buffer interlea
  13294.                  mov     di,80-2000h     ; increment from last to first interl
  13295.  
  13296.                  mov     cx,ARGx2
  13297.                  sub     cx,ARGx1        ; CX := x2 - x1
  13298.                  jz      VertLine04      ; jump if vertical line
  13299.  
  13300.  ; force x1 < x2
  13301.  
  13302.                  jns     L01             ; jump if x2 > x1
  13303.  
  13304.                  neg     cx              ; CX := x1 - x2
  13305.  
  13306.                  mov     bx,ARGx2        ; exchange x1 and x2
  13307.                  xchg    bx,ARGx1
  13308.                  mov     ARGx2,bx
  13309.  
  13310.                  mov     bx,ARGy2        ; exchange y1 and y2
  13311.                  xchg    bx,ARGy1
  13312.                  mov     ARGy2,bx
  13313.  
  13314.  ; calculate dy = ABS(y2-y1)
  13315.  
  13316.  L01:            mov     bx,ARGy2
  13317.                  sub     bx,ARGy1        ; BX := y2 - y1
  13318.                  jnz     L02
  13319.  
  13320.                  jmp     HorizLine04     ; jump if horizontal line
  13321.  
  13322.  L02:            jns     L03
  13323.  
  13324.                  neg     bx              ; BX := y1 - y2
  13325.                  neg     si              ; negate increments for buffer interl
  13326.                  neg     di
  13327.                  xchg    si,di           ; exchange increments
  13328.  
  13329.  ; select appropriate routine for slope of line
  13330.  
  13331.  L03:            mov     VARleafincr,di  ; save increment for buffer interleav
  13332.  
  13333.                  mov     VARroutine,offset LoSlopeLine04
  13334.                  cmp     bx,cx
  13335.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  13336.                  mov     VARroutine,offset HiSlopeLine04
  13337.                  xchg    bx,cx           ; exchange dy and dx
  13338.  
  13339.  ; calculate initial decision variable and increments
  13340.  
  13341.  L04:            shl     bx,1            ; BX := 2 * dy
  13342.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  13343.                  sub     bx,cx
  13344.                  mov     di,bx           ; DI := d = 2 * dy - dx
  13345.                  sub     bx,cx
  13346.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  13347.  
  13348.  ; calculate first pixel address
  13349.  
  13350.                  push    cx              ; preserve this register
  13351.                  mov     ax,ARGy1        ; AX := y
  13352.                  mov     bx,ARGx1        ; BX := x
  13353.                  call    PixelAddr04     ; AH := bit mask
  13354.                                          ; ES:BX -> buffer
  13355.                                          ; CL := # bits to shift left
  13356.  
  13357.                  mov     al,ARGn         ; AL := unshifted pixel value
  13358.                  shl     ax,cl           ; AH := bit mask in proper position
  13359.                                          ; AL := pixel value in proper positio
  13360.  
  13361.                  mov     dx,ax           ; DH := bit mask
  13362.                                          ; DL := pixel value
  13363.                  not     dh              ; DH := inverse bit mask
  13364.  
  13365.                  pop     cx              ; restore this register
  13366.                  inc     cx              ; CX := # of pixels to draw
  13367.  
  13368.                  test    bx,2000h        ; set zero flag if BX in 1st interlea
  13369.                  jz      L05
  13370.  
  13371.                  xchg    si,VARleafincr  ; exchange increment values if 1st pi
  13372.                                          ;  lies in 1st interleave
  13373.  
  13374.  L05:            jmp     VARroutine      ; jump to appropriate routine for slo
  13375.  
  13376.  
  13377.  ; routine for vertical lines
  13378.  
  13379.  VertLine04:     mov     ax,ARGy1        ; AX := y1
  13380.                  mov     bx,ARGy2        ; BX := y2
  13381.                  mov     cx,bx
  13382.                  sub     cx,ax           ; CX := dy
  13383.                  jge     L31             ; jump if dy >= 0
  13384.  
  13385.                  neg     cx              ; force dy >= 0
  13386.                  mov     ax,bx           ; AX := y2
  13387.  
  13388.  L31:            inc     cx              ; CX := # of pixels to draw
  13389.                  mov     bx,ARGx1        ; BX := x
  13390.                  push    cx              ; preserve this register
  13391.                  call    PixelAddr04     ; AH := bit mask
  13392.                                          ; ES:BX -> video buffer
  13393.                                          ; CL := # bits to shift left
  13394.                  mov     al,ARGn         ; AL := pixel value
  13395.                  shl     ax,cl           ; AH := bit mask in proper position
  13396.                                          ; AL := pixel value in proper positio
  13397.                  not     ah              ; AH := inverse bit mask
  13398.                  pop     cx              ; restore this register
  13399.  
  13400.                  test    bx,si           ; set zero flag if BX in 1st interlea
  13401.                  jz      L32
  13402.  
  13403.                  xchg    si,di           ; exchange increment values if 1st pi
  13404.                                          ;  lies in 1st interleave
  13405.  
  13406.  L32:            and     es:[bx],ah      ; zero pixel in buffer
  13407.                  or      es:[bx],al      ; set pixel value in buffer
  13408.  
  13409.                  add     bx,si           ; increment to next portion of interl
  13410.                  xchg    si,di           ; toggle between increment values
  13411.  
  13412.                  loop    L32
  13413.  
  13414.                  jmp     Lexit
  13415.  
  13416.  
  13417.  
  13418.  ; routine for horizontal lines (slope = 0)
  13419.  
  13420.  HorizLine04:    mov     ax,ARGy1
  13421.                  mov     bx,ARGx1
  13422.                  call    PixelAddr04     ; AH := bit mask
  13423.                                          ; ES:BX -> video buffer
  13424.                                          ; CL := # bits to shift left
  13425.                  mov     di,bx           ; ES:DI -> buffer
  13426.  
  13427.                  mov     dh,ah
  13428.                  not     dh              ; DH := unshifted bit mask for leftmo
  13429.                                          ;        byte
  13430.                  mov     dl,0FFh         ; DL := unshifted bit mask for
  13431.                                          ;        rightmost byte
  13432.  
  13433.                  shl     dh,cl           ; DH := reverse bit mask for first by
  13434.                  not     dh              ; DH := bit mask for first byte
  13435.  
  13436.                  mov     cx,ARGx2
  13437.                  and     cl,3
  13438.                  xor     cl,3
  13439.                  shl     cl,1            ; CL := number of bits to shift left
  13440.                  shl     dl,cl           ; DL := bit mask for last byte
  13441.  
  13442.  ; determine byte offset of first and last pixel in the line
  13443.  
  13444.                  mov     ax,ARGx2        ; AX := x2
  13445.                  mov     bx,ARGx1        ; BX := x1
  13446.  
  13447.                  mov     cl,ByteOffsetShift      ; number of bits to shift to
  13448.                                                  ;  convert pixels to bytes
  13449.  
  13450.                  shr     ax,cl           ; AX := byte offset of x2
  13451.                  shr     bx,cl           ; BX := byte offset of x1
  13452.                  mov     cx,ax
  13453.                  sub     cx,bx           ; CX := (# bytes in line) - 1
  13454.  
  13455.  ; propagate pixel value throughout one byte
  13456.  
  13457.                  mov     bx,offset DGROUP:PropagatedPixel
  13458.                  mov     al,ARGn         ; AL := pixel value
  13459.                  xlat                    ; AL := propagated pixel value
  13460.  
  13461.  ; set pixels in leftmost byte of the line
  13462.  
  13463.                  or      dh,dh
  13464.                  js      L43             ; jump if byte-aligned (x1 is leftmos
  13465.                                          ;  pixel in byte)
  13466.                  or      cx,cx
  13467.                  jnz     L42             ; jump if more than one byte in the l
  13468.  
  13469.                  and     dl,dh           ; bit mask for the line
  13470.                  jmp     short L44
  13471.  
  13472.  L42:            mov     ah,al
  13473.                  and     ah,dh           ; AH := masked pixel bits
  13474.                  not     dh              ; DH := reverse bit mask for 1st byte
  13475.                  and     es:[di],dh      ; zero masked pixels in buffer
  13476.                  or      es:[di],ah      ; update masked pixels in buffer
  13477.                  inc     di
  13478.                  dec     cx
  13479.  
  13480.  ; use a fast 8086 machine instruction to draw the remainder of the line
  13481.  
  13482.  L43:            rep     stosb           ; update all pixels in the line
  13483.  
  13484.  ; set pixels in the rightmost byte of the line
  13485.  
  13486.  L44:            and     al,dl           ; AL := masked pixels for last byte
  13487.                  not     dl
  13488.                  and     es:[di],dl      ; zero masked pixels in buffer
  13489.                  or      es:[di],al      ; update masked pixels in buffer
  13490.  
  13491.                  jmp     Lexit
  13492.  
  13493.  
  13494.  ; routine for dy <= dx (slope <= 1)     ; ES:BX -> video buffer
  13495.                                          ; CX = # pixels to draw
  13496.                                          ; DH = inverse bit mask
  13497.                                          ; DL = pixel value in proper position
  13498.                                          ; SI = buffer interleave increment
  13499.                                          ; DI = decision variable
  13500.  LoSlopeLine04:
  13501.  
  13502.  L10:            mov     ah,es:[bx]      ; AH := byte from video buffer
  13503.  
  13504.  L11:            and     ah,dh           ; zero pixel value at current bit off
  13505.                  or      ah,dl           ; set pixel value in byte
  13506.  
  13507.                  ror     dl,1            ; rotate pixel value
  13508.                  ror     dl,1
  13509.                  ror     dh,1            ; rotate bit mask
  13510.                  ror     dh,1
  13511.                  jnc     L14             ; jump if bit mask rotated to
  13512.                                          ;  leftmost pixel position
  13513.  
  13514.  ; bit mask not shifted out
  13515.  
  13516.                  or      di,di           ; test sign of d
  13517.                  jns     L12             ; jump if d >= 0
  13518.  
  13519.                  add     di,VARincr1     ; d := d + incr1
  13520.                  loop    L11
  13521.  
  13522.                  mov     es:[bx],ah      ; store remaining pixels in buffer
  13523.                  jmp     short Lexit
  13524.  
  13525.  L12:            add     di,VARincr2     ; d := d + incr2
  13526.                  mov     es:[bx],ah      ; update buffer
  13527.  
  13528.                  add     bx,si           ; increment y
  13529.                  xchg    si,VARleafincr  ; exchange interleave increment value
  13530.  
  13531.                  loop    L10
  13532.                  jmp     short Lexit
  13533.  
  13534.  ; bit mask shifted out
  13535.  
  13536.  L14:            mov     es:[bx],ah      ; update buffer
  13537.                  inc     bx              ; BX := offset of next byte
  13538.  
  13539.                  or      di,di           ; test sign of d
  13540.                  jns     L15             ; jump if non-negative
  13541.  
  13542.                  add     di,VARincr1     ; d := d + incr1
  13543.                  loop    L10
  13544.                  jmp     short Lexit
  13545.  
  13546.  
  13547.  L15:            add     di,VARincr2     ; d := d + incr2
  13548.  
  13549.                  add     bx,si           ; increment y
  13550.                  xchg    si,VARleafincr
  13551.  
  13552.                  loop    L10
  13553.                  jmp     short Lexit
  13554.  
  13555.  
  13556.  ; routine for dy > dx (slope > 1)       ; ES:BX -> video buffer
  13557.                                          ; CX = # pixels to draw
  13558.                                          ; DH = inverse bit mask
  13559.                                          ; DL = pixel value in proper position
  13560.                                          ; SI = buffer interleave increment
  13561.                                          ; DI = decision variable
  13562.  HiSlopeLine04:
  13563.  
  13564.  L21:            and     es:[bx],dh      ; zero pixel value in video buffer
  13565.                  or      es:[bx],dl      ; set pixel value in byte
  13566.  
  13567.                  add     bx,si           ; increment y
  13568.                  xchg    si,VARleafincr  ; exchange interleave increment value
  13569.  
  13570.  L22:            or      di,di           ; test sign of d
  13571.                  jns     L23             ; jump if d >= 0
  13572.  
  13573.                  add     di,VARincr1     ; d := d + incr1
  13574.                  loop    L21
  13575.  
  13576.                  jmp     short Lexit
  13577.  
  13578.  
  13579.  L23:            add     di,VARincr2     ; d := d + incr2
  13580.  
  13581.                  ror     dl,1            ; rotate pixel value
  13582.                  ror     dl,1
  13583.                  ror     dh,1            ; rotate bit mask
  13584.                  ror     dh,1
  13585.                  cmc                     ; cf set if bit mask not rotated to
  13586.                                          ;  leftmost pixel position
  13587.  
  13588.                  adc     bx,0            ; BX := offset of next byte
  13589.  
  13590.                  loop    L21
  13591.  
  13592.  
  13593.  Lexit:          pop     di              ; restore registers and return
  13594.                  pop     si
  13595.                  mov     sp,bp
  13596.                  pop     bp
  13597.                  ret
  13598.  
  13599.  _Line04         ENDP
  13600.  
  13601.  _TEXT           ENDS
  13602.  
  13603.  
  13604.  _DATA           SEGMENT word public 'DATA'
  13605.  
  13606.  PropagatedPixel DB      00000000b       ; 0
  13607.                  DB      01010101b       ; 1
  13608.                  DB      10101010b       ; 2
  13609.                  DB      11111111b       ; 3
  13610.  
  13611.  _DATA           ENDS
  13612.  
  13613.                  END
  13614.  
  13615.  \SAMPCODE\VIDEO\6\6_6.ASM
  13616.  
  13617.                  TITLE   'Listing 6-6'
  13618.                  NAME    LineHGC
  13619.                  PAGE    55,132
  13620.  
  13621.  ;
  13622.  ; Name:         LineHGC
  13623.  ;
  13624.  ; Function:     Draw a line in HGC or HGC+ 720x348 graphics
  13625.  ;
  13626.  ; Caller:       Microsoft C:
  13627.  ;
  13628.  ;                       void LineHGC(x1,y1,x2,y2,n);
  13629.  ;
  13630.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  13631.  ;
  13632.  ;                       int n;                  /* pixel value */
  13633.  ;
  13634.  
  13635.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  13636.  ARGy1           EQU     word ptr [bp+6]
  13637.  ARGx2           EQU     word ptr [bp+8]
  13638.  ARGy2           EQU     word ptr [bp+10]
  13639.  ARGn            EQU     byte ptr [bp+12]
  13640.  VARleafincr     EQU     word ptr [bp-2]
  13641.  VARincr1        EQU     word ptr [bp-4]
  13642.  VARincr2        EQU     word ptr [bp-6]
  13643.  VARroutine      EQU     word ptr [bp-8]
  13644.  
  13645.  ByteOffsetShift EQU     3               ; used to convert pixels to byte offs
  13646.  
  13647.  DGROUP          GROUP   _DATA
  13648.  
  13649.  _TEXT           SEGMENT byte public 'CODE'
  13650.                  ASSUME  cs:_TEXT,ds:DGROUP
  13651.  
  13652.                  EXTRN   PixelAddrHGC:near
  13653.  
  13654.                  PUBLIC  _LineHGC
  13655.  _LineHGC        PROC    near
  13656.  
  13657.                  push    bp              ; preserve caller registers
  13658.                  mov     bp,sp
  13659.                  sub     sp,8            ; stack space for local variables
  13660.                  push    si
  13661.                  push    di
  13662.  
  13663.                  mov     si,2000h        ; increment for video buffer interlea
  13664.                  mov     di,90-8000h     ; increment from last to first interl
  13665.  
  13666.                  mov     cx,ARGx2
  13667.                  sub     cx,ARGx1        ; CX := x2 - x1
  13668.                  jz      VertLineHGC     ; jump if vertical line
  13669.  
  13670.  ; force x1 < x2
  13671.  
  13672.                  jns     L01             ; jump if x2 > x1
  13673.  
  13674.                  neg     cx              ; CX := x1 - x2
  13675.  
  13676.                  mov     bx,ARGx2        ; exchange x1 and x2
  13677.                  xchg    bx,ARGx1
  13678.                  mov     ARGx2,bx
  13679.  
  13680.                  mov     bx,ARGy2        ; exchange y1 and y2
  13681.                  xchg    bx,ARGy1
  13682.                  mov     ARGy2,bx
  13683.  
  13684.  ; calculate dy = ABS(y2-y1)
  13685.  
  13686.  L01:            mov     bx,ARGy2
  13687.                  sub     bx,ARGy1        ; BX := y2 - y1
  13688.                  jnz     L02
  13689.  
  13690.                  jmp     HorizLineHGC    ; jump if horizontal line
  13691.  
  13692.  L02:            jns     L03
  13693.  
  13694.                  neg     bx              ; BX := y1 - y2
  13695.                  neg     si              ; negate increments for buffer interl
  13696.                  neg     di
  13697.  
  13698.  ; select appropriate routine for slope of line
  13699.  
  13700.  L03:            mov     VARleafincr,di  ; save increment for buffer interleav
  13701.  
  13702.                  mov     VARroutine,offset LoSlopeLineHGC
  13703.                  cmp     bx,cx
  13704.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  13705.                  mov     VARroutine,offset HiSlopeLineHGC
  13706.                  xchg    bx,cx           ; exchange dy and dx
  13707.  
  13708.  ; calculate initial decision variable and increments
  13709.  
  13710.  L04:            shl     bx,1            ; BX := 2 * dy
  13711.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  13712.                  sub     bx,cx
  13713.                  mov     di,bx           ; DI := d = 2 * dy - dx
  13714.                  sub     bx,cx
  13715.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  13716.  
  13717.  ; calculate first pixel address
  13718.  
  13719.                  push    cx              ; preserve this register
  13720.                  mov     ax,ARGy1        ; AX := y
  13721.                  mov     bx,ARGx1        ; BX := x
  13722.                  call    PixelAddrHGC    ; AH := bit mask
  13723.                                          ; ES:BX -> buffer
  13724.                                          ; CL := # bits to shift left
  13725.  
  13726.                  mov     al,ARGn         ; AL := unshifted pixel value
  13727.                  shl     ax,cl           ; AH := bit mask in proper position
  13728.                                          ; AL := pixel value in proper positio
  13729.  
  13730.                  mov     dx,ax           ; DH := bit mask
  13731.                                          ; DL := pixel value
  13732.                  not     dh              ; DH := inverse bit mask
  13733.  
  13734.                  pop     cx              ; restore this register
  13735.                  inc     cx              ; CX := # of pixels to draw
  13736.  
  13737.                  jmp     VARroutine      ; jump to appropriate routine for slo
  13738.  
  13739.  
  13740.  ; routine for vertical lines
  13741.  
  13742.  VertLineHGC:    mov     ax,ARGy1        ; AX := y1
  13743.                  mov     bx,ARGy2        ; BX := y2
  13744.                  mov     cx,bx
  13745.                  sub     cx,ax           ; CX := dy
  13746.                  jge     L31             ; jump if dy >= 0
  13747.  
  13748.                  neg     cx              ; force dy >= 0
  13749.                  mov     ax,bx           ; AX := y2
  13750.  
  13751.  L31:            inc     cx              ; CX := # of pixels to draw
  13752.                  mov     bx,ARGx1        ; BX := x
  13753.                  push    cx              ; preserve this register
  13754.                  call    PixelAddrHGC    ; AH := bit mask
  13755.                                          ; ES:BX -> video buffer
  13756.                                          ; CL := # bits to shift left
  13757.                  mov     al,ARGn         ; AL := pixel value
  13758.                  shl     ax,cl           ; AH := bit mask in proper position
  13759.                                          ; AL := pixel value in proper positio
  13760.                  not     ah              ; AH := inverse bit mask
  13761.                  pop     cx              ; restore this register
  13762.  
  13763.  ; draw the line
  13764.                  test    al,al
  13765.                  jz      L34             ; jump if pixel value is zero
  13766.  
  13767.  L32:            or      es:[bx],al      ; set pixel values in buffer
  13768.  
  13769.                  add     bx,si           ; increment to next portion of interl
  13770.                  jns     L33
  13771.                  add     bx,di           ; increment to first portion of inter
  13772.  L33:            loop    L32
  13773.                  jmp     short L36
  13774.  
  13775.  L34:            and     es:[bx],ah      ; reset pixel values in buffer
  13776.  
  13777.                  add     bx,si           ; increment to next portion of interl
  13778.                  jns     L35
  13779.                  add     bx,di           ; increment to first portion of inter
  13780.  L35:            loop    L34
  13781.  
  13782.  L36:            jmp     Lexit
  13783.  
  13784.  
  13785.  ; routine for horizontal lines (slope = 0)
  13786.  
  13787.  HorizLineHGC:   mov     ax,ARGy1
  13788.                  mov     bx,ARGx1
  13789.                  call    PixelAddrHGC    ; AH := bit mask
  13790.                                          ; ES:BX -> video buffer
  13791.                                          ; CL := # bits to shift left
  13792.                  mov     di,bx           ; ES:DI -> buffer
  13793.  
  13794.                  mov     dh,ah
  13795.                  not     dh              ; DH := unshifted bit mask for leftmo
  13796.                                          ;        byte
  13797.                  mov     dl,0FFh         ; DL := unshifted bit mask for
  13798.                                          ;        rightmost byte
  13799.  
  13800.                  shl     dh,cl           ; DH := reverse bit mask for first by
  13801.                  not     dh              ; DH := bit mask for first byte
  13802.  
  13803.                  mov     cx,ARGx2
  13804.                  and     cl,7
  13805.                  xor     cl,7            ; CL := number of bits to shift left
  13806.                  shl     dl,cl           ; DL := bit mask for last byte
  13807.  
  13808.  ; determine byte offset of first and last pixel in the line
  13809.  
  13810.                  mov     ax,ARGx2        ; AX := x2
  13811.                  mov     bx,ARGx1        ; BX := x1
  13812.  
  13813.                  mov     cl,ByteOffsetShift      ; number of bits to shift to
  13814.                                                  ;  convert pixels to bytes
  13815.  
  13816.                  shr     ax,cl           ; AX := byte offset of x2
  13817.                  shr     bx,cl           ; BX := byte offset of x1
  13818.                  mov     cx,ax
  13819.                  sub     cx,bx           ; CX := (# bytes in line) - 1
  13820.  
  13821.  ; propagate pixel value throughout one byte
  13822.  
  13823.                  mov     bx,offset DGROUP:PropagatedPixel
  13824.                  mov     al,ARGn         ; AL := pixel value
  13825.                  xlat                    ; AL := propagated pixel value
  13826.  
  13827.  ; set pixels in leftmost byte of the line
  13828.  
  13829.                  or      dh,dh
  13830.                  js      L43             ; jump if byte-aligned (x1 is leftmos
  13831.                                          ;  pixel in byte)
  13832.                  or      cx,cx
  13833.                  jnz     L42             ; jump if more than one byte in the l
  13834.  
  13835.                  and     dl,dh           ; bit mask for the line
  13836.                  jmp     short L44
  13837.  
  13838.  L42:            mov     ah,al
  13839.                  and     ah,dh           ; AH := masked pixel bits
  13840.                  not     dh              ; DH := reverse bit mask for 1st byte
  13841.                  and     es:[di],dh      ; zero masked pixels in buffer
  13842.                  or      es:[di],ah      ; update masked pixels in buffer
  13843.                  inc     di
  13844.                  dec     cx
  13845.  
  13846.  ; use a fast 8086 machine instruction to draw the remainder of the line
  13847.  
  13848.  L43:            rep     stosb           ; update all pixels in the line
  13849.  
  13850.  ; set pixels in the rightmost byte of the line
  13851.  
  13852.  L44:            and     al,dl           ; AL := masked pixels for last byte
  13853.                  not     dl
  13854.                  and     es:[di],dl      ; zero masked pixels in buffer
  13855.                  or      es:[di],al      ; update masked pixels in buffer
  13856.  
  13857.                  jmp     Lexit
  13858.  
  13859.  
  13860.  ; routine for dy <= dx (slope <= 1)     ; ES:BX -> video buffer
  13861.                                          ; CX = #pixels to draw
  13862.                                          ; DH = inverse bit mask
  13863.                                          ; DL = pixel value in proper position
  13864.                                          ; SI = buffer interleave increment
  13865.                                          ; DI = decision variable
  13866.  LoSlopeLineHGC:
  13867.  
  13868.  L10:            mov     ah,es:[bx]      ; AH := byte from video buffer
  13869.  
  13870.  L11:            and     ah,dh           ; zero pixel value at current bit off
  13871.                  or      ah,dl           ; set pixel value in byte
  13872.  
  13873.                  ror     dl,1            ; rotate pixel value
  13874.                  ror     dh,1            ; rotate bit mask
  13875.                  jnc     L14             ; jump if bit mask rotated to
  13876.                                          ;  leftmost pixel position
  13877.  
  13878.  ; bit mask not shifted out
  13879.  
  13880.                  or      di,di           ; test sign of d
  13881.                  jns     L12             ; jump if d >= 0
  13882.  
  13883.                  add     di,VARincr1     ; d := d + incr1
  13884.                  loop    L11
  13885.  
  13886.                  mov     es:[bx],ah      ; store remaining pixels in buffer
  13887.                  jmp     short Lexit
  13888.  
  13889.  L12:            add     di,VARincr2     ; d := d + incr2
  13890.                  mov     es:[bx],ah      ; update buffer
  13891.  
  13892.                  add     bx,si           ; increment y
  13893.                  jns     L13             ; jump if not in last interleave
  13894.  
  13895.                  add     bx,VARleafincr  ; increment into next interleave
  13896.  
  13897.  L13:            loop    L10
  13898.                  jmp     short Lexit
  13899.  
  13900.  ; bit mask shifted out
  13901.  
  13902.  L14:            mov     es:[bx],ah      ; update buffer
  13903.                  inc     bx              ; BX := offset of next byte
  13904.  
  13905.                  or      di,di           ; test sign of d
  13906.                  jns     L15             ; jump if non-negative
  13907.  
  13908.                  add     di,VARincr1     ; d := d + incr1
  13909.                  loop    L10
  13910.                  jmp     short Lexit
  13911.  
  13912.  L15:            add     di,VARincr2     ; d := d + incr2
  13913.  
  13914.                  add     bx,si           ; increment y
  13915.                  jns     L16             ; jump if not in last interleave
  13916.  
  13917.                  add     bx,VARleafincr  ; increment into next interleave
  13918.  
  13919.  L16:            loop    L10             ; loop until all pixels are set
  13920.                  jmp     short Lexit
  13921.  
  13922.  
  13923.  ; routine for dy > dx (slope > 1)       ; ES:BX -> video buffer
  13924.                                          ; CX = #pixels to draw
  13925.                                          ; DH = inverse bit mask
  13926.                                          ; DL = pixel value in proper position
  13927.                                          ; SI = buffer interleave increment
  13928.                                          ; DI = decision variable
  13929.  HiSlopeLineHGC:
  13930.  
  13931.  L21:            and     es:[bx],dh      ; zero pixel value in video buffer
  13932.                  or      es:[bx],dl      ; set pixel value in byte
  13933.  
  13934.                  add     bx,si           ; increment y
  13935.                  jns     L22             ; jump if not in last interleave
  13936.  
  13937.                  add     bx,VARleafincr  ; increment into next interleave
  13938.  
  13939.  L22:            or      di,di
  13940.                  jns     L23             ; jump if d >= 0
  13941.  
  13942.                  add     di,VARincr1     ; d := d + incr1
  13943.                  loop    L21
  13944.                  jmp     short Lexit
  13945.  
  13946.  
  13947.  L23:            add     di,VARincr2     ; d := d + incr2
  13948.  
  13949.                  ror     dl,1            ; rotate pixel value
  13950.                  ror     dh,1            ; rotate bit mask
  13951.                  cmc                     ; cf set if bit mask not rotated to
  13952.                                          ;  leftmost pixel position
  13953.                  adc     bx,0            ; BX := offset of next byte
  13954.  
  13955.                  loop    L21
  13956.  
  13957.  
  13958.  Lexit:          pop     di
  13959.                  pop     si
  13960.                  mov     sp,bp
  13961.                  pop     bp
  13962.                  ret
  13963.  
  13964.  _LineHGC        ENDP
  13965.  
  13966.  _TEXT           ENDS
  13967.  
  13968.  _DATA           SEGMENT word public 'DATA'
  13969.  
  13970.  PropagatedPixel DB      00000000b       ; 0
  13971.                  DB      11111111b       ; 1
  13972.  
  13973.  _DATA           ENDS
  13974.  
  13975.                  END
  13976.  
  13977.  \SAMPCODE\VIDEO\6\6_7.ASM
  13978.  
  13979.                  TITLE   'Listing 6-7'
  13980.                  NAME    Line10
  13981.                  PAGE    55,132
  13982.  
  13983.  ;
  13984.  ; Name:         Line10
  13985.  ;
  13986.  ; Function:     Draw a line in the following EGA and VGA graphics modes:
  13987.  ;                       200-line 16-color modes
  13988.  ;                       350-line modes
  13989.  ;                       640x480 16-color
  13990.  ;
  13991.  ; Caller:       Microsoft C:
  13992.  ;
  13993.  ;                       void Line10(x1,y1,x2,y2,n);
  13994.  ;
  13995.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  13996.  ;
  13997.  ;                       int n;                  /* pixel value */
  13998.  ;
  13999.  
  14000.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  14001.  ARGy1           EQU     word ptr [bp+6]
  14002.  ARGx2           EQU     word ptr [bp+8]
  14003.  ARGy2           EQU     word ptr [bp+10]
  14004.  ARGn            EQU     byte ptr [bp+12]
  14005.  VARvertincr     EQU     word ptr [bp-2]
  14006.  VARincr1        EQU     word ptr [bp-4]
  14007.  VARincr2        EQU     word ptr [bp-6]
  14008.  VARroutine      EQU     word ptr [bp-8]
  14009.  
  14010.  ByteOffsetShift EQU     3               ; used to convert pixels to byte offs
  14011.  BytesPerLine    EQU     80
  14012.  RMWbits         EQU     0               ; value for Data Rotate/Func Select r
  14013.  
  14014.  
  14015.  _TEXT           SEGMENT byte public 'CODE'
  14016.                  ASSUME  cs:_TEXT
  14017.  
  14018.                  EXTRN   PixelAddr10:near
  14019.  
  14020.                  PUBLIC  _Line10
  14021.  _Line10         PROC    near
  14022.  
  14023.                  push    bp              ; preserve caller registers
  14024.                  mov     bp,sp
  14025.                  sub     sp,8            ; stack space for local variables
  14026.                  push    si
  14027.                  push    di
  14028.  
  14029.  ; configure the Graphics Controller
  14030.  
  14031.                  mov     dx,3CEh         ; DX := Graphics Controller port addr
  14032.  
  14033.                  mov     ah,ARGn         ; AH := pixel value
  14034.                  xor     al,al           ; AL := Set/Reset Register number
  14035.                  out     dx,ax
  14036.  
  14037.                  mov     ax,0F01h        ; AH := 1111b (bit plane mask for
  14038.                                          ;  Enable Set/Reset
  14039.                  out     dx,ax           ; AL := Enable Set/Reset Register #
  14040.  
  14041.                  mov     ah,RMWbits      ; bits 3 and 4 of AH := function
  14042.                  mov     al,3            ; AL := Data Rotate/Func Select reg #
  14043.                  out     dx,ax
  14044.  
  14045.  ; check for vertical line
  14046.  
  14047.                  mov     si,BytesPerLine ; increment for video buffer
  14048.  
  14049.                  mov     cx,ARGx2
  14050.                  sub     cx,ARGx1        ; CX := x2 - x1
  14051.                  jz      VertLine10      ; jump if vertical line
  14052.  
  14053.  ; force x1 < x2
  14054.  
  14055.                  jns     L01             ; jump if x2 > x1
  14056.  
  14057.                  neg     cx              ; CX := x1 - x2
  14058.  
  14059.                  mov     bx,ARGx2        ; exchange x1 and x2
  14060.                  xchg    bx,ARGx1
  14061.                  mov     ARGx2,bx
  14062.  
  14063.                  mov     bx,ARGy2        ; exchange y1 and y2
  14064.                  xchg    bx,ARGy1
  14065.                  mov     ARGy2,bx
  14066.  
  14067.  ; calculate dy = ABS(y2-y1)
  14068.  
  14069.  L01:            mov     bx,ARGy2
  14070.                  sub     bx,ARGy1        ; BX := y2 - y1
  14071.                  jz      HorizLine10     ; jump if horizontal line
  14072.  
  14073.                  jns     L03             ; jump if slope is positive
  14074.  
  14075.                  neg     bx              ; BX := y1 - y2
  14076.                  neg     si              ; negate increment for buffer interle
  14077.  
  14078.  ; select appropriate routine for slope of line
  14079.  
  14080.  L03:            mov     VARvertincr,si  ; save vertical increment
  14081.  
  14082.                  mov     VARroutine,offset LoSlopeLine10
  14083.                  cmp     bx,cx
  14084.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  14085.                  mov     VARroutine,offset HiSlopeLine10
  14086.                  xchg    bx,cx           ; exchange dy and dx
  14087.  
  14088.  ; calculate initial decision variable and increments
  14089.  
  14090.  L04:            shl     bx,1            ; BX := 2 * dy
  14091.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  14092.                  sub     bx,cx
  14093.                  mov     si,bx           ; SI := d = 2 * dy - dx
  14094.                  sub     bx,cx
  14095.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  14096.  
  14097.  ; calculate first pixel address
  14098.  
  14099.                  push    cx              ; preserve this register
  14100.                  mov     ax,ARGy1        ; AX := y
  14101.                  mov     bx,ARGx1        ; BX := x
  14102.                  call    PixelAddr10     ; AH := bit mask
  14103.                                          ; ES:BX -> buffer
  14104.                                          ; CL := # bits to shift left
  14105.  
  14106.                  mov     di,bx           ; ES:DI -> buffer
  14107.                  shl     ah,cl           ; AH := bit mask in proper position
  14108.                  mov     bl,ah           ; AH,BL := bit mask
  14109.                  mov     al,8            ; AL := Bit Mask Register number
  14110.  
  14111.                  pop     cx              ; restore this register
  14112.                  inc     cx              ; CX := # of pixels to draw
  14113.  
  14114.                  jmp     VARroutine      ; jump to appropriate routine for slo
  14115.  
  14116.  
  14117.  ; routine for vertical lines
  14118.  
  14119.  VertLine10:     mov     ax,ARGy1        ; AX := y1
  14120.                  mov     bx,ARGy2        ; BX := y2
  14121.                  mov     cx,bx
  14122.                  sub     cx,ax           ; CX := dy
  14123.                  jge     L31             ; jump if dy >= 0
  14124.  
  14125.                  neg     cx              ; force dy >= 0
  14126.                  mov     ax,bx           ; AX := y2
  14127.  
  14128.  L31:            inc     cx              ; CX := # of pixels to draw
  14129.                  mov     bx,ARGx1        ; BX := x
  14130.                  push    cx              ; preserve this register
  14131.                  call    PixelAddr10     ; AH := bit mask
  14132.                                          ; ES:BX -> video buffer
  14133.                                          ; CL := # bits to shift left
  14134.  ; set up Graphics Controller
  14135.  
  14136.                  shl     ah,cl           ; AH := bit mask in proper position
  14137.                  mov     al,8            ; AL := Bit Mask reg number
  14138.                  out     dx,ax
  14139.  
  14140.                  pop     cx              ; restore this register
  14141.  
  14142.  ; draw the line
  14143.  
  14144.  L32:            or      es:[bx],al      ; set pixel
  14145.                  add     bx,si           ; increment to next line
  14146.                  loop    L32
  14147.  
  14148.                  jmp     Lexit
  14149.  
  14150.  
  14151.  
  14152.  ; routine for horizontal lines (slope = 0)
  14153.  
  14154.  HorizLine10:
  14155.                  push    ds              ; preserve DS
  14156.  
  14157.                  mov     ax,ARGy1
  14158.                  mov     bx,ARGx1
  14159.                  call    PixelAddr10     ; AH := bit mask
  14160.                                          ; ES:BX -> video buffer
  14161.                                          ; CL := # bits to shift left
  14162.                  mov     di,bx           ; ES:DI -> buffer
  14163.  
  14164.                  mov     dh,ah           ; DH := unshifted bit mask for leftmo
  14165.                                          ;        byte
  14166.                  not     dh
  14167.                  shl     dh,cl           ; DH := reverse bit mask for first by
  14168.                  not     dh              ; DH := bit mask for first byte
  14169.  
  14170.                  mov     cx,ARGx2
  14171.                  and     cl,7
  14172.                  xor     cl,7            ; CL := number of bits to shift left
  14173.                  mov     dl,0FFh         ; DL := unshifted bit mask for
  14174.                                          ;        rightmost byte
  14175.                  shl     dl,cl           ; DL := bit mask for last byte
  14176.  
  14177.  ; determine byte offset of first and last pixel in the line
  14178.  
  14179.                  mov     ax,ARGx2        ; AX := x2
  14180.                  mov     bx,ARGx1        ; BX := x1
  14181.  
  14182.                  mov     cl,ByteOffsetShift      ; number of bits to shift to
  14183.                                                  ;  convert pixels to bytes
  14184.  
  14185.                  shr     ax,cl           ; AX := byte offset of x2
  14186.                  shr     bx,cl           ; BX := byte offset of x1
  14187.                  mov     cx,ax
  14188.                  sub     cx,bx           ; CX := (# bytes in line) - 1
  14189.  
  14190.  ; get Graphics Controller port address into DX
  14191.  
  14192.                  mov     bx,dx           ; BH := bit mask for first byte
  14193.                                          ; BL := bit mask for last byte
  14194.                  mov     dx,3CEh         ; DX := Graphics Controller port
  14195.                  mov     al,8            ; AL := Bit Mask Register number
  14196.  
  14197.  ; make video buffer addressible through DS:SI
  14198.  
  14199.                  push    es
  14200.                  pop     ds
  14201.                  mov     si,di           ; DS:SI -> video buffer
  14202.  
  14203.  ; set pixels in leftmost byte of the line
  14204.  
  14205.                  or      bh,bh
  14206.                  js      L43             ; jump if byte-aligned (x1 is leftmos
  14207.                                          ;  pixel in byte)
  14208.                  or      cx,cx
  14209.                  jnz     L42             ; jump if more than one byte in the l
  14210.  
  14211.                  and     bl,bh           ; BL := bit mask for the line
  14212.                  jmp     short L44
  14213.  
  14214.  L42:            mov     ah,bh           ; AH := bit mask for 1st byte
  14215.                  out     dx,ax           ; update Graphics Controller
  14216.  
  14217.                  movsb                   ; update bit planes
  14218.                  dec     cx
  14219.  
  14220.  ; use a fast 8086 machine instruction to draw the remainder of the line
  14221.  
  14222.  L43:            mov     ah,11111111b    ; AH := bit mask
  14223.                  out     dx,ax           ; update Bit Mask Register
  14224.  
  14225.                  rep     movsb           ; update all pixels in the line
  14226.  
  14227.  ; set pixels in the rightmost byte of the line
  14228.  
  14229.  L44:            mov     ah,bl           ; AH := bit mask for last byte
  14230.                  out     dx,ax           ; update Graphics Controller
  14231.  
  14232.                  movsb                   ; update bit planes
  14233.  
  14234.                  pop     ds              ; restore DS
  14235.                  jmp     short Lexit
  14236.  
  14237.  
  14238.  ; routine for dy <= dx (slope <= 1)     ; ES:DI -> video buffer
  14239.                                          ; AL = Bit Mask Register number
  14240.                                          ; BL = bit mask for 1st pixel
  14241.                                          ; CX = #pixels to draw
  14242.                                          ; DX = Graphics Controller port addr
  14243.                                          ; SI = decision variable
  14244.  LoSlopeLine10:
  14245.  
  14246.  L10:            mov     ah,bl           ; AH := bit mask for next pixel
  14247.  
  14248.  L11:            or      ah,bl           ; mask current pixel position
  14249.                  ror     bl,1            ; rotate pixel value
  14250.                  jc      L14             ; jump if bit mask rotated to
  14251.                                          ;  leftmost pixel position
  14252.  
  14253.  ; bit mask not shifted out
  14254.  
  14255.                  or      si,si           ; test sign of d
  14256.                  jns     L12             ; jump if d >= 0
  14257.  
  14258.                  add     si,VARincr1     ; d := d + incr1
  14259.                  loop    L11
  14260.  
  14261.                  out     dx,ax           ; update Bit Mask Register
  14262.                  or      es:[di],al      ; set remaining pixel(s)
  14263.                  jmp     short Lexit
  14264.  
  14265.  L12:            add     si,VARincr2     ; d := d + incr2
  14266.                  out     dx,ax           ; update Bit Mask Register
  14267.  
  14268.                  or      es:[di],al      ; update bit planes
  14269.  
  14270.                  add     di,VARvertincr  ; increment y
  14271.                  loop    L10
  14272.                  jmp     short Lexit
  14273.  
  14274.  ; bit mask shifted out
  14275.  
  14276.  L14:            out     dx,ax           ; update Bit Mask Register ...
  14277.  
  14278.                  or      es:[di],al      ; update bit planes
  14279.                  inc     di              ; increment x
  14280.  
  14281.                  or      si,si           ; test sign of d
  14282.                  jns     L15             ; jump if non-negative
  14283.  
  14284.                  add     si,VARincr1     ; d := d + incr1
  14285.                  loop    L10
  14286.                  jmp     short Lexit
  14287.  
  14288.  L15:            add     si,VARincr2     ; d := d + incr2
  14289.                  add     di,VARvertincr  ; vertical increment
  14290.                  loop    L10
  14291.                  jmp     short Lexit
  14292.  
  14293.  
  14294.  ; routine for dy > dx (slope > 1)       ; ES:DI -> video buffer
  14295.                                          ; AH = bit mask for 1st pixel
  14296.                                          ; AL = Bit Mask Register number
  14297.                                          ; CX = #pixels to draw
  14298.                                          ; DX = Graphics Controller port addr
  14299.                                          ; SI = decision variable
  14300.  HiSlopeLine10:
  14301.                  mov     bx,VARvertincr  ; BX := y-increment
  14302.  
  14303.  L21:            out     dx,ax           ; update Bit Mask Register
  14304.                  or      es:[di],al      ; update bit planes
  14305.  
  14306.                  add     di,bx           ; increment y
  14307.  
  14308.  L22:            or      si,si           ; test sign of d
  14309.                  jns     L23             ; jump if d >= 0
  14310.  
  14311.                  add     si,VARincr1     ; d := d + incr1
  14312.                  loop    L21
  14313.                  jmp     short Lexit
  14314.  
  14315.  
  14316.  L23:            add     si,VARincr2     ; d := d + incr2
  14317.  
  14318.                  ror     ah,1            ; rotate bit mask
  14319.                  adc     di,0            ; increment DI if when mask rotated t
  14320.                                          ;  leftmost pixel position
  14321.  
  14322.                  loop    L21
  14323.  
  14324.  
  14325.  ; restore default Graphics Controller state and return to caller
  14326.  
  14327.  Lexit:          xor     ax,ax           ; AH := 0, AL := 0
  14328.                  out     dx,ax           ; restore Set/Reset Register
  14329.  
  14330.                  inc     ax              ; AH := 0, AL := 1
  14331.                  out     dx,ax           ; restore Enable Set/Reset Register
  14332.  
  14333.                  mov     al,3            ; AH := 0, AL := 3
  14334.                  out     dx,ax           ; AL := Data Rotate/Func Select reg #
  14335.  
  14336.                  mov     ax,0FF08h       ; AH := 1111111b, AL := 8
  14337.                  out     dx,ax           ; restore Bit Mask Register
  14338.  
  14339.                  pop     di              ; restore registers and return
  14340.                  pop     si
  14341.                  mov     sp,bp
  14342.                  pop     bp
  14343.                  ret
  14344.  
  14345.  _Line10         ENDP
  14346.  
  14347.  _TEXT           ENDS
  14348.  
  14349.                  END
  14350.  
  14351.  \SAMPCODE\VIDEO\6\6_8.ASM
  14352.  
  14353.                  TITLE   'Listing 6-8'
  14354.                  NAME    Line11
  14355.                  PAGE    55,132
  14356.  
  14357.  ;
  14358.  ; Name:         Line11
  14359.  ;
  14360.  ; Function:     Draw a line in 640x480 2-color mode (MCGA, VGA)
  14361.  ;
  14362.  ; Caller:       Microsoft C:
  14363.  ;
  14364.  ;                       void Line11(x1,y1,x2,y2,n);
  14365.  ;
  14366.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  14367.  ;
  14368.  ;                       int n;                  /* pixel value */
  14369.  ;
  14370.  
  14371.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  14372.  ARGy1           EQU     word ptr [bp+6]
  14373.  ARGx2           EQU     word ptr [bp+8]
  14374.  ARGy2           EQU     word ptr [bp+10]
  14375.  ARGn            EQU     byte ptr [bp+12]
  14376.  VARincr1        EQU     word ptr [bp-2]
  14377.  VARincr2        EQU     word ptr [bp-4]
  14378.  VARroutine      EQU     word ptr [bp-6]
  14379.  
  14380.  BytesPerLine    EQU     80              ; bytes in one row of pixels
  14381.  ByteOffsetShift EQU     3               ; used to convert pixels to byte offs
  14382.  
  14383.  DGROUP          GROUP   _DATA
  14384.  
  14385.  _TEXT           SEGMENT byte public 'CODE'
  14386.                  ASSUME  cs:_TEXT,ds:DGROUP
  14387.  
  14388.                  EXTRN   PixelAddr10:near
  14389.  
  14390.                  PUBLIC  _Line11
  14391.  _Line11         PROC    near
  14392.  
  14393.                  push    bp              ; preserve caller registers
  14394.                  mov     bp,sp
  14395.                  sub     sp,6            ; stack space for local variables
  14396.                  push    si
  14397.                  push    di
  14398.  
  14399.  ; check for vertical line
  14400.  
  14401.                  mov     si,BytesPerLine ; SI := initial y-increment
  14402.  
  14403.                  mov     cx,ARGx2
  14404.                  sub     cx,ARGx1        ; CX := x2 - x1
  14405.                  jz      VertLine11      ; jump if vertical line
  14406.  
  14407.  ; force x1 < x2
  14408.  
  14409.                  jns     L01             ; jump if x2 > x1
  14410.  
  14411.                  neg     cx              ; CX := x1 - x2
  14412.  
  14413.                  mov     bx,ARGx2        ; exchange x1 and x2
  14414.                  xchg    bx,ARGx1
  14415.                  mov     ARGx2,bx
  14416.  
  14417.                  mov     bx,ARGy2        ; exchange y1 and y2
  14418.                  xchg    bx,ARGy1
  14419.                  mov     ARGy2,bx
  14420.  
  14421.  ; calculate dy = ABS(y2-y1)
  14422.  
  14423.  L01:            mov     bx,ARGy2
  14424.                  sub     bx,ARGy1        ; BX := y2 - y1
  14425.                  jnz     L02
  14426.  
  14427.                  jmp     HorizLine11     ; jump if horizontal line
  14428.  
  14429.  L02:            jns     L03
  14430.  
  14431.                  neg     bx              ; BX := y1 - y2
  14432.                  neg     si              ; negate y-increment
  14433.  
  14434.  ; select appropriate routine for slope of line
  14435.  
  14436.  L03:            mov     VARroutine,offset LoSlopeLine11
  14437.                  cmp     bx,cx
  14438.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  14439.                  mov     VARroutine,offset HiSlopeLine11
  14440.                  xchg    bx,cx           ; exchange dy and dx
  14441.  
  14442.  ; calculate initial decision variable and increments
  14443.  
  14444.  L04:            shl     bx,1            ; BX := 2 * dy
  14445.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  14446.                  sub     bx,cx
  14447.                  mov     di,bx           ; DI := d = 2 * dy - dx
  14448.                  sub     bx,cx
  14449.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  14450.  
  14451.  ; calculate first pixel address
  14452.  
  14453.                  push    cx              ; preserve this register
  14454.                  mov     ax,ARGy1        ; AX := y
  14455.                  mov     bx,ARGx1        ; BX := x
  14456.                  call    PixelAddr10     ; AH := bit mask
  14457.                                          ; ES:BX -> buffer
  14458.                                          ; CL := # bits to shift left
  14459.  
  14460.                  mov     al,ARGn         ; AL := unshifted pixel value
  14461.                  shl     ax,cl           ; AH := bit mask in proper position
  14462.                                          ; AL := pixel value in proper positio
  14463.  
  14464.                  mov     dx,ax           ; DH := bit mask
  14465.                                          ; DL := pixel value
  14466.                  not     dh              ; DH := inverse bit mask
  14467.  
  14468.                  pop     cx              ; restore this register
  14469.                  inc     cx              ; CX := # of pixels to draw
  14470.  
  14471.                  jmp     VARroutine      ; jump to appropriate routine for slo
  14472.  
  14473.  
  14474.  ; routine for vertical lines
  14475.  
  14476.  VertLine11:     mov     ax,ARGy1        ; AX := y1
  14477.                  mov     bx,ARGy2        ; BX := y2
  14478.                  mov     cx,bx
  14479.                  sub     cx,ax           ; CX := dy
  14480.                  jge     L31             ; jump if dy >= 0
  14481.  
  14482.                  neg     cx              ; force dy >= 0
  14483.                  mov     ax,bx           ; AX := y2
  14484.  
  14485.  L31:            inc     cx              ; CX := # of pixels to draw
  14486.                  mov     bx,ARGx1        ; BX := x
  14487.                  push    cx              ; preserve this register
  14488.                  call    PixelAddr10     ; AH := bit mask
  14489.                                          ; ES:BX -> video buffer
  14490.                                          ; CL := # bits to shift left
  14491.                  mov     al,ARGn         ; AL := pixel value
  14492.                  shl     ax,cl           ; AH := bit mask in proper position
  14493.                                          ; AL := pixel value in proper positio
  14494.                  not     ah              ; AH := inverse bit mask
  14495.                  pop     cx              ; restore this register
  14496.  
  14497.  ; draw the line
  14498.  
  14499.                  test    al,al
  14500.                  jz      L33             ; jump if pixel value = 0
  14501.  
  14502.  L32:            or      es:[bx],al      ; set pixel values in buffer
  14503.                  add     bx,si
  14504.                  loop    L32
  14505.                  jmp     short L34
  14506.  
  14507.  L33:            and     es:[bx],ah      ; reset pixel values in buffer
  14508.                  add     bx,si
  14509.                  loop    L33
  14510.  
  14511.  L34:            jmp     Lexit
  14512.  
  14513.  
  14514.  ; routine for horizontal lines (slope = 0)
  14515.  
  14516.  HorizLine11:    mov     ax,ARGy1
  14517.                  mov     bx,ARGx1
  14518.                  call    PixelAddr10     ; AH := bit mask
  14519.                                          ; ES:BX -> video buffer
  14520.                                          ; CL := # bits to shift left
  14521.                  mov     di,bx           ; ES:DI -> buffer
  14522.  
  14523.                  mov     dh,ah
  14524.                  not     dh              ; DH := unshifted bit mask for leftmo
  14525.                                          ;        byte
  14526.                  mov     dl,0FFh         ; DL := unshifted bit mask for
  14527.                                          ;        rightmost byte
  14528.  
  14529.                  shl     dh,cl           ; DH := reverse bit mask for first by
  14530.                  not     dh              ; DH := bit mask for first byte
  14531.  
  14532.                  mov     cx,ARGx2
  14533.                  and     cl,7
  14534.                  xor     cl,7            ; CL := number of bits to shift left
  14535.                  shl     dl,cl           ; DL := bit mask for last byte
  14536.  
  14537.  ; determine byte offset of first and last pixel in the line
  14538.  
  14539.                  mov     ax,ARGx2        ; AX := x2
  14540.                  mov     bx,ARGx1        ; BX := x1
  14541.  
  14542.                  mov     cl,ByteOffsetShift      ; number of bits to shift to
  14543.                                                  ;  convert pixels to bytes
  14544.  
  14545.                  shr     ax,cl           ; AX := byte offset of x2
  14546.                  shr     bx,cl           ; BX := byte offset of x1
  14547.                  mov     cx,ax
  14548.                  sub     cx,bx           ; CX := (# bytes in line) - 1
  14549.  
  14550.  ; propagate pixel value throughout one byte
  14551.  
  14552.                  mov     bx,offset DGROUP:PropagatedPixel
  14553.                  mov     al,ARGn         ; AL := pixel value
  14554.                  xlat
  14555.  
  14556.  ; set pixels in leftmost byte of the line
  14557.  
  14558.                  or      dh,dh
  14559.                  js      L43             ; jump if byte-aligned (x1 is leftmos
  14560.                                          ;  pixel in byte)
  14561.                  or      cx,cx
  14562.                  jnz     L42             ; jump if more than one byte in the l
  14563.  
  14564.                  and     dl,dh           ; bit mask for the line
  14565.                  jmp     short L44
  14566.  
  14567.  L42:            mov     ah,al
  14568.                  and     ah,dh           ; AH := masked pixel bits
  14569.                  not     dh              ; DH := reverse bit mask for 1st byte
  14570.                  and     es:[di],dh      ; zero masked pixels in buffer
  14571.                  or      es:[di],ah      ; update masked pixels in buffer
  14572.                  inc     di
  14573.                  dec     cx
  14574.  
  14575.  ; use a fast 8086 machine instruction to draw the remainder of the line
  14576.  
  14577.  L43:            rep     stosb           ; update all pixels in the line
  14578.  
  14579.  ; set pixels in the rightmost byte of the line
  14580.  
  14581.  L44:            and     al,dl           ; AL := masked pixels for last byte
  14582.                  not     dl
  14583.                  and     es:[di],dl      ; zero masked pixels in buffer
  14584.                  or      es:[di],al      ; update masked pixels in buffer
  14585.  
  14586.                  jmp     Lexit
  14587.  
  14588.  
  14589.  ; routine for dy <= dx (slope <= 1)     ; ES:BX -> video buffer
  14590.                                          ; CX = #pixels to draw
  14591.                                          ; DH = inverse bit mask
  14592.                                          ; DL = pixel value in proper position
  14593.                                          ; SI = bytes per pixel row
  14594.                                          ; DI = decision variable
  14595.  LoSlopeLine11:
  14596.  
  14597.  L10:            mov     ah,es:[bx]      ; AH := byte from video buffer
  14598.  
  14599.  L11:            and     ah,dh           ; zero pixel value at current bit off
  14600.                  or      ah,dl           ; set pixel value in byte
  14601.  
  14602.                  ror     dl,1            ; rotate pixel value
  14603.                  ror     dh,1            ; rotate bit mask
  14604.                  jnc     L14             ; jump if bit mask rotated to
  14605.                                          ;  leftmost pixel position
  14606.  
  14607.  ; bit mask not shifted out
  14608.  
  14609.                  or      di,di           ; test sign of d
  14610.                  jns     L12             ; jump if d >= 0
  14611.  
  14612.                  add     di,VARincr1     ; d := d + incr1
  14613.                  loop    L11
  14614.  
  14615.                  mov     es:[bx],ah      ; store remaining pixels in buffer
  14616.                  jmp     short Lexit
  14617.  
  14618.  L12:            add     di,VARincr2     ; d := d + incr2
  14619.                  mov     es:[bx],ah      ; update buffer
  14620.  
  14621.                  add     bx,si           ; increment y
  14622.                  loop    L10
  14623.                  jmp     short Lexit
  14624.  
  14625.  ; bit mask shifted out
  14626.  
  14627.  L14:            mov     es:[bx],ah      ; update buffer
  14628.                  inc     bx              ; BX := offset of next byte
  14629.  
  14630.                  or      di,di           ; test sign of d
  14631.                  jns     L15             ; jump if non-negative
  14632.  
  14633.                  add     di,VARincr1     ; d := d + incr1
  14634.                  loop    L10
  14635.                  jmp     short Lexit
  14636.  
  14637.  L15:            add     di,VARincr2     ; d := d + incr2
  14638.  
  14639.                  add     bx,si           ; increment y
  14640.                  loop    L10
  14641.                  jmp     short Lexit
  14642.  
  14643.  
  14644.  ; routine for dy > dx (slope > 1)       ; ES:BX -> video buffer
  14645.                                          ; CX = #pixels to draw
  14646.                                          ; DH = inverse bit mask
  14647.                                          ; DL = pixel value in proper position
  14648.                                          ; SI = bytes per pixel row
  14649.                                          ; DI = decision variable
  14650.  HiSlopeLine11:
  14651.  
  14652.  L21:            and     es:[bx],dh      ; zero pixel value in video buffer
  14653.                  or      es:[bx],dl      ; set pixel value in byte
  14654.  
  14655.                  add     bx,si           ; increment y
  14656.  
  14657.  L22:            or      di,di           ; test sign of d
  14658.                  jns     L23             ; jump if d >= 0
  14659.  
  14660.                  add     di,VARincr1     ; d := d + incr1
  14661.                  loop    L21
  14662.  
  14663.                  jmp     short Lexit
  14664.  
  14665.  
  14666.  L23:            add     di,VARincr2     ; d := d + incr2
  14667.  
  14668.                  ror     dl,1            ; rotate pixel value
  14669.                  ror     dh,1            ; rotate bit mask
  14670.                  cmc                     ; cf set if bit mask not rotated to
  14671.                                          ;  leftmost pixel position
  14672.  
  14673.                  adc     bx,0            ; BX := offset of next byte
  14674.  
  14675.                  loop    L21
  14676.  
  14677.  
  14678.  Lexit:          pop     di
  14679.                  pop     si
  14680.                  mov     sp,bp
  14681.                  pop     bp
  14682.                  ret
  14683.  
  14684.  _Line11         ENDP
  14685.  
  14686.  _TEXT           ENDS
  14687.  
  14688.  
  14689.  _DATA           SEGMENT word public 'DATA'
  14690.  
  14691.  PropagatedPixel DB      00000000b       ; 0
  14692.                  DB      11111111b       ; 1
  14693.  
  14694.  _DATA           ENDS
  14695.  
  14696.                  END
  14697.  
  14698.  \SAMPCODE\VIDEO\6\6_9.ASM
  14699.  
  14700.                  TITLE   'Listing 6-9'
  14701.                  NAME    Line13
  14702.                  PAGE    55,132
  14703.  
  14704.  ;
  14705.  ; Name:         Line13
  14706.  ;
  14707.  ; Function:     Draw a line in MCGA/VGA 320x200 256-color mode
  14708.  ;
  14709.  ; Caller:       Microsoft C:
  14710.  ;
  14711.  ;                       void Line13(x1,y1,x2,y2,n);
  14712.  ;
  14713.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  14714.  ;
  14715.  ;                       int n;                  /* pixel value */
  14716.  ;
  14717.  
  14718.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  14719.  ARGy1           EQU     word ptr [bp+6]
  14720.  ARGx2           EQU     word ptr [bp+8]
  14721.  ARGy2           EQU     word ptr [bp+10]
  14722.  ARGn            EQU     byte ptr [bp+12]
  14723.  VARincr1        EQU     word ptr [bp-2]
  14724.  VARincr2        EQU     word ptr [bp-4]
  14725.  VARroutine      EQU     word ptr [bp-6]
  14726.  
  14727.  BytesPerLine    EQU     320
  14728.  
  14729.  
  14730.  _TEXT           SEGMENT byte public 'CODE'
  14731.                  ASSUME  cs:_TEXT
  14732.  
  14733.                  EXTRN   PixelAddr13:near
  14734.  
  14735.                  PUBLIC  _Line13
  14736.  _Line13         PROC    near
  14737.  
  14738.                  push    bp              ; preserve caller registers
  14739.                  mov     bp,sp
  14740.                  sub     sp,6            ; stack space for local variables
  14741.                  push    si
  14742.                  push    di
  14743.  
  14744.  ; check for vertical line
  14745.  
  14746.                  mov     si,BytesPerLine ; initial y-increment
  14747.  
  14748.                  mov     cx,ARGx2
  14749.                  sub     cx,ARGx1        ; CX := x2 - x1
  14750.                  jz      VertLine13      ; jump if vertical line
  14751.  
  14752.  ; force x1 < x2
  14753.  
  14754.                  jns     L01             ; jump if x2 > x1
  14755.  
  14756.                  neg     cx              ; CX := x1 - x2
  14757.  
  14758.                  mov     bx,ARGx2        ; exchange x1 and x2
  14759.                  xchg    bx,ARGx1
  14760.                  mov     ARGx2,bx
  14761.  
  14762.                  mov     bx,ARGy2        ; exchange y1 and y2
  14763.                  xchg    bx,ARGy1
  14764.                  mov     ARGy2,bx
  14765.  
  14766.  ; calculate dy = ABS(y2-y1)
  14767.  
  14768.  L01:            mov     bx,ARGy2
  14769.                  sub     bx,ARGy1        ; BX := y2 - y1
  14770.                  jz      HorizLine13     ; jump if horizontal line
  14771.  
  14772.                  jns     L03             ; jump if slope is positive
  14773.  
  14774.                  neg     bx              ; BX := y1 - y2
  14775.                  neg     si              ; negate y-increment
  14776.  
  14777.  ; select appropriate routine for slope of line
  14778.  
  14779.  L03:            push    si              ; preserve y-increment
  14780.  
  14781.                  mov     VARroutine,offset LoSlopeLine13
  14782.                  cmp     bx,cx
  14783.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  14784.                  mov     VARroutine,offset HiSlopeLine13
  14785.                  xchg    bx,cx           ; exchange dy and dx
  14786.  
  14787.  ; calculate initial decision variable and increments
  14788.  
  14789.  L04:            shl     bx,1            ; BX := 2 * dy
  14790.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  14791.                  sub     bx,cx
  14792.                  mov     si,bx           ; SI := d = 2 * dy - dx
  14793.                  sub     bx,cx
  14794.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  14795.  
  14796.  ; calculate first pixel address
  14797.  
  14798.                  push    cx              ; preserve this register
  14799.                  mov     ax,ARGy1        ; AX := y
  14800.                  mov     bx,ARGx1        ; BX := x
  14801.                  call    PixelAddr13     ; ES:BX -> buffer
  14802.  
  14803.                  mov     di,bx           ; ES:DI -> buffer
  14804.  
  14805.                  pop     cx              ; restore this register
  14806.                  inc     cx              ; CX := # of pixels to draw
  14807.  
  14808.                  pop     bx              ; BX := y-increment
  14809.                  jmp     VARroutine      ; jump to appropriate routine for slo
  14810.  
  14811.  
  14812.  ; routine for vertical lines
  14813.  
  14814.  VertLine13:     mov     ax,ARGy1        ; AX := y1
  14815.                  mov     bx,ARGy2        ; BX := y2
  14816.                  mov     cx,bx
  14817.                  sub     cx,ax           ; CX := dy
  14818.                  jge     L31             ; jump if dy >= 0
  14819.  
  14820.                  neg     cx              ; force dy >= 0
  14821.                  mov     ax,bx           ; AX := y2
  14822.  
  14823.  L31:            inc     cx              ; CX := # of pixels to draw
  14824.                  mov     bx,ARGx1        ; BX := x
  14825.                  push    cx              ; preserve this register
  14826.                  call    PixelAddr13     ; ES:BX -> video buffer
  14827.                  pop     cx
  14828.  
  14829.                  mov     di,bx           ; ES:DI -> video buffer
  14830.                  dec     si              ; SI := bytes/line - 1
  14831.  
  14832.                  mov     al,ARGn         ; AL := pixel value
  14833.  
  14834.  L32:            stosb                   ; set pixel value in buffer
  14835.                  add     di,si           ; increment to next line
  14836.                  loop    L32
  14837.  
  14838.                  jmp     Lexit
  14839.  
  14840.  
  14841.  
  14842.  ; routine for horizontal lines (slope = 0)
  14843.  
  14844.  HorizLine13:
  14845.                  push    cx              ; preserve CX
  14846.                  mov     ax,ARGy1
  14847.                  mov     bx,ARGx1
  14848.                  call    PixelAddr13     ; ES:BX -> video buffer
  14849.                  mov     di,bx           ; ES:DI -> buffer
  14850.  
  14851.                  pop     cx
  14852.                  inc     cx              ; CX := number of pixels to draw
  14853.  
  14854.                  mov     al,ARGn         ; AL := pixel value
  14855.  
  14856.                  rep     stosb           ; update the video buffer
  14857.  
  14858.                  jmp     short Lexit
  14859.  
  14860.  
  14861.  ; routine for dy <= dx (slope <= 1)     ; ES:DI -> video buffer
  14862.                                          ; BX = y-increment
  14863.                                          ; CX = #pixels to draw
  14864.                                          ; SI = decision variable
  14865.  LoSlopeLine13:
  14866.  
  14867.                  mov     al,ARGn         ; AL := pixel value
  14868.  
  14869.  L11:            stosb                   ; store pixel, increment x
  14870.  
  14871.                  or      si,si           ; test sign of d
  14872.                  jns     L12             ; jump if d >= 0
  14873.  
  14874.                  add     si,VARincr1     ; d := d + incr1
  14875.                  loop    L11
  14876.                  jmp     short Lexit
  14877.  
  14878.  L12:            add     si,VARincr2     ; d := d + incr2
  14879.                  add     di,bx           ; increment y
  14880.                  loop    L11
  14881.                  jmp     short Lexit
  14882.  
  14883.  
  14884.  ; routine for dy > dx (slope > 1)       ; ES:DI -> video buffer
  14885.                                          ; BX = y-increment
  14886.                                          ; CX = #pixels to draw
  14887.                                          ; SI = decision variable
  14888.  HiSlopeLine13:
  14889.                  mov     al,ARGn         ; AL := pixel value
  14890.  
  14891.  L21:            stosb                   ; update next pixel, increment x
  14892.  
  14893.                  add     di,bx           ; increment y
  14894.  
  14895.  L22:            or      si,si           ; test sign of d
  14896.                  jns     L23             ; jump if d >= 0
  14897.  
  14898.                  add     si,VARincr1     ; d := d + incr1
  14899.                  dec     di              ; decrement x (already incremented
  14900.                                          ;  by stosb)
  14901.                  loop    L21
  14902.                  jmp     short Lexit
  14903.  
  14904.  
  14905.  L23:            add     si,VARincr2     ; d := d + incr2
  14906.                  loop    L21
  14907.  
  14908.  
  14909.  Lexit:          pop     di              ; restore registers and return
  14910.                  pop     si
  14911.                  mov     sp,bp
  14912.                  pop     bp
  14913.                  ret
  14914.  
  14915.  _Line13         ENDP
  14916.  
  14917.  _TEXT           ENDS
  14918.  
  14919.                  END
  14920.  
  14921.  \SAMPCODE\VIDEO\7
  14922.  \SAMPCODE\VIDEO\7\7_1.C
  14923.  
  14924.  /* Listing 7-1 */
  14925.  
  14926.  Ellipse( xc, yc, a0, b0 )               /* using equation of ellipse */
  14927.  int     xc,yc;                  /* center of ellipse */
  14928.  int     a0,b0;                  /* major and minor axes */
  14929.  {
  14930.  
  14931.          double  x = 0;
  14932.          double  y = b0;
  14933.          double  Bsquared = (double)b0 * (double)b0;
  14934.          double  Asquared = (double)a0 * (double)a0;
  14935.          double  sqrt();
  14936.  
  14937.  
  14938.          do                              /* do while dy/dx >= -1 */
  14939.          {
  14940.            y = sqrt( Bsquared - ((Bsquared/Asquared) * x*x) );
  14941.            Set4Pixels( (int)x, (int)y, xc, yc, PixelValue );
  14942.            ++x;
  14943.          }
  14944.          while ( (x <= a0) && (Bsquared*x < Asquared*y) );
  14945.  
  14946.  
  14947.          while (y >= 0)                  /* do while dy/dx < -1 */
  14948.          {
  14949.            x = sqrt( Asquared - ((Asquared/Bsquared) * y*y) );
  14950.            Set4Pixels( (int)x, (int)y, xc, yc, PixelValue );
  14951.            --y;
  14952.          }
  14953.  }
  14954.  
  14955.  
  14956.  Set4Pixels( x, y, xc, yc, n )   /* set pixels in 4 quadrants by symmetry */
  14957.  int     x,y;
  14958.  int     xc,yc;
  14959.  int     n;
  14960.  {
  14961.          SPFunc(xc+x,yc+y,n);
  14962.          SPFunc(xc-x,yc+y,n);
  14963.          SPFunc(xc+x,yc-y,n);
  14964.          SPFunc(xc-x,yc-y,n);
  14965.  }
  14966.  
  14967.  \SAMPCODE\VIDEO\7\7_2.C
  14968.  
  14969.  /* Listing 7-2 */
  14970.  
  14971.  Ellipse( xc, yc, a0, b0 )
  14972.  int     xc,yc;                  /* center of ellipse */
  14973.  int     a0,b0;                  /* semiaxes */
  14974.  {
  14975.          int     x = 0;
  14976.          int     y = b0;
  14977.  
  14978.          long    a = a0;                         /* use 32-bit precision */
  14979.          long    b = b0;
  14980.  
  14981.          long    Asquared = a * a;               /* initialize values outside
  14982.          long    TwoAsquared = 2 * Asquared;     /*  of loops */
  14983.          long    Bsquared = b * b;
  14984.          long    TwoBsquared = 2 * Bsquared;
  14985.  
  14986.          long    d;
  14987.          long    dx,dy;
  14988.  
  14989.  
  14990.          d = Bsquared - Asquared*b + Asquared/4L;
  14991.          dx = 0;
  14992.          dy = TwoAsquared * b;
  14993.  
  14994.          while (dx<dy)
  14995.          {
  14996.            Set4Pixels( x, y, xc, yc, PixelValue );
  14997.  
  14998.            if (d > 0L)
  14999.            {
  15000.              --y;
  15001.              dy -= TwoAsquared;
  15002.              d -= dy;
  15003.            }
  15004.  
  15005.            ++x;
  15006.            dx += TwoBsquared;
  15007.            d += Bsquared + dx;
  15008.          }
  15009.  
  15010.  
  15011.          d += (3L*(Asquared-Bsquared)/2L - (dx+dy)) / 2L;
  15012.  
  15013.          while (y>=0)
  15014.          {
  15015.            Set4Pixels( x, y, xc, yc, PixelValue );
  15016.  
  15017.            if (d < 0L)
  15018.            {
  15019.              ++x;
  15020.              dx += TwoBsquared;
  15021.              d += dx;
  15022.            }
  15023.  
  15024.            --y;
  15025.            dy -= TwoAsquared;
  15026.            d += Asquared - dy;
  15027.          }
  15028.  }
  15029.  
  15030.  
  15031.  Set4Pixels( x, y, xc, yc, n )       /* set pixels by symmetry in 4 quadrants
  15032.  int     x,y;
  15033.  int     xc,yc;
  15034.  int     n;
  15035.  {
  15036.          SetPixel( xc+x, yc+y, n );
  15037.          SetPixel( xc-x, yc+y, n );
  15038.          SetPixel( xc+x, yc-y, n );
  15039.          SetPixel( xc-x, yc-y, n );
  15040.  }
  15041.  
  15042.  \SAMPCODE\VIDEO\7\7_3.C
  15043.  
  15044.  /* Listing 7-3 */
  15045.  
  15046.  Set4Pixels( x, y, xc, yc, n )   /* avoids setting the same pixel twice */
  15047.  int     x,y;
  15048.  int     xc,yc;
  15049.  int     n;
  15050.  {
  15051.          if (x!=0)
  15052.          {
  15053.            SetPixel( xc+x, yc+y, n );
  15054.            SetPixel( xc-x, yc+y, n );
  15055.            if (y!=0)
  15056.            {
  15057.              SetPixel( xc+x, yc-y, n );
  15058.              SetPixel( xc-x, yc-y, n );
  15059.            }
  15060.          }
  15061.          else
  15062.          {
  15063.            SetPixel( xc, yc+y, n );
  15064.            if (y!=0)
  15065.              SetPixel( xc, yc-y, n );
  15066.          }
  15067.  }
  15068.  
  15069.  \SAMPCODE\VIDEO\7\7_5.C
  15070.  
  15071.  /* Listing 7-5 */
  15072.  
  15073.  Circle10( xc, yc, xr, yr, n)            /* circles in 640x350 16-color mode *
  15074.  int     xc,yc;          /* center of circle */
  15075.  int     xr,yr;          /* point on circumference */
  15076.  int     n;              /* pixel value */
  15077.  {
  15078.          double  x,y;
  15079.          double  sqrt();
  15080.          double  Scale10 = 1.37;         /* pixel scaling factor */
  15081.          int     a,b;
  15082.  
  15083.          x = xr - xc;                    /* translate center of ellipse */
  15084.          y = (yr - yc) * Scale10;        /*  to origin */
  15085.  
  15086.  
  15087.          a = sqrt( x*x + y*y );          /* compute major and minor axes */
  15088.          b = a / Scale10;
  15089.  
  15090.          Ellipse10( xc, yc, a, b, n);    /* draw it */
  15091.  }
  15092.  
  15093.  \SAMPCODE\VIDEO\7\7_4.ASM
  15094.  
  15095.                  TITLE   'Listing 7-4'
  15096.                  NAME    Ellipse10
  15097.                  PAGE    55,132
  15098.  
  15099.  ;
  15100.  ; Name:         Ellipse10
  15101.  ;
  15102.  ; Function:     Draw an ellipse in native EGA/VGA graphics modes.
  15103.  ;
  15104.  ; Caller:       Microsoft C:
  15105.  ;
  15106.  ;                       void Ellipse10(xc,yc,a,b,n);
  15107.  ;
  15108.  ;                       int xc,yc;              /* center of ellipse */
  15109.  ;
  15110.  ;                       int a,b;                /* major and minor axes */
  15111.  ;
  15112.  ;                       int n;                  /* pixel value */
  15113.  ;
  15114.  
  15115.  ARGxc           EQU     word ptr [bp+4] ; stack frame addressing
  15116.  ARGyc           EQU     word ptr [bp+6]
  15117.  ARGa            EQU     word ptr [bp+8]
  15118.  ARGb            EQU     word ptr [bp+10]
  15119.  ARGn            EQU     byte ptr [bp+12]
  15120.  
  15121.  ULAddr          EQU     word ptr [bp-2]
  15122.  URAddr          EQU     word ptr [bp-4]
  15123.  LLAddr          EQU     word ptr [bp-6]
  15124.  LRAddr          EQU     word ptr [bp-8]
  15125.  LMask           EQU     byte ptr [bp-10]
  15126.  RMask           EQU     byte ptr [bp-12]
  15127.  
  15128.  VARd            EQU     word ptr [bp-16]
  15129.  VARdx           EQU     word ptr [bp-20]
  15130.  VARdy           EQU     word ptr [bp-24]
  15131.  Asquared        EQU     word ptr [bp-28]
  15132.  Bsquared        EQU     word ptr [bp-32]
  15133.  TwoAsquared     EQU     word ptr [bp-36]
  15134.  TwoBsquared     EQU     word ptr [bp-40]
  15135.  
  15136.  RMWbits         EQU     0               ; read-modify-write bits
  15137.  BytesPerLine    EQU     80
  15138.  
  15139.  
  15140.  _TEXT           SEGMENT byte public 'CODE'
  15141.                  ASSUME  cs:_TEXT
  15142.  
  15143.                  EXTRN   PixelAddr10:near
  15144.  
  15145.                  PUBLIC  _Ellipse10
  15146.  _Ellipse10      PROC    near
  15147.  
  15148.                  push    bp              ; preserve caller registers
  15149.                  mov     bp,sp
  15150.                  sub     sp,40           ; establish stack frame
  15151.                  push    si
  15152.                  push    di
  15153.  
  15154.  ; set Graphics Controller Mode register
  15155.  
  15156.                  mov     dx,3CEh         ; DX := Graphics Controller I/O port
  15157.                  mov     ax,0005h        ; AL := Mode register number
  15158.                                          ; AH := Write Mode 0 (bits 0,1)
  15159.                  out     dx,ax           ;       Read Mode 0 (bit 4)
  15160.  
  15161.  ; set Data Rotate/Function Select register
  15162.  
  15163.                  mov     ah,RMWbits      ; AH := Read-Modify-Write bits
  15164.                  mov     al,3            ; AL := Data Rotate/Function Select r
  15165.                  out     dx,ax
  15166.  
  15167.  ; set Set/Reset and Enable Set/Reset registers
  15168.  
  15169.                  mov     ah,ARGn         ; AH := pixel value
  15170.                  mov     al,0            ; AL := Set/Reset reg number
  15171.                  out     dx,ax
  15172.  
  15173.                  mov     ax,0F01h        ; AH := value for Enable Set/Reset (a
  15174.                                          ;  bit planes enabled)
  15175.                  out     dx,ax           ; AL := Enable Set/Reset reg number
  15176.  
  15177.  ; initial constants
  15178.  
  15179.                  mov     ax,ARGa
  15180.                  mul     ax
  15181.                  mov     Asquared,ax
  15182.                  mov     Asquared+2,dx   ; a^2
  15183.                  shl     ax,1
  15184.                  rcl     dx,1
  15185.                  mov     TwoAsquared,ax
  15186.                  mov     TwoAsquared+2,dx ; 2*a^2
  15187.  
  15188.                  mov     ax,ARGb
  15189.                  mul     ax
  15190.                  mov     Bsquared,ax
  15191.                  mov     Bsquared+2,dx   ; b^2
  15192.                  shl     ax,1
  15193.                  rcl     dx,1
  15194.                  mov     TwoBsquared,ax
  15195.                  mov     TwoBsquared+2,dx ; 2*b^2
  15196.  ;
  15197.  ; plot pixels from (0,b) until dy/dx = -1
  15198.  ;
  15199.  
  15200.  ; initial buffer address and bit mask
  15201.  
  15202.                  mov     ax,BytesPerLine ; AX := video buffer line length
  15203.                  mul     ARGb            ; AX := relative byte offset of b
  15204.                  mov     si,ax
  15205.                  mov     di,ax
  15206.  
  15207.                  mov     ax,ARGyc        ; AX := yc
  15208.                  mov     bx,ARGxc        ; BX := xc
  15209.                  call    PixelAddr10     ; AH := bit mask
  15210.                                          ; ES:BX -> buffer
  15211.                                          ; CL := # bits to shift left
  15212.                  mov     ah,1
  15213.                  shl     ah,cl           ; AH := bit mask for first pixel
  15214.                  mov     LMask,ah
  15215.                  mov     RMask,ah
  15216.  
  15217.                  add     si,bx           ; SI := offset of (0,b)
  15218.                  mov     ULAddr,si
  15219.                  mov     URAddr,si
  15220.                  sub     bx,di           ; AX := offset of (0,-b)
  15221.                  mov     LLAddr,bx
  15222.                  mov     LRAddr,bx
  15223.  
  15224.  ; initial decision variables
  15225.  
  15226.                  xor     ax,ax
  15227.                  mov     VARdx,ax
  15228.                  mov     VARdx+2,ax      ; dx = 0
  15229.  
  15230.                  mov     ax,TwoAsquared
  15231.                  mov     dx,TwoAsquared+2
  15232.                  mov     cx,ARGb
  15233.                  call    LongMultiply    ; perform 32-bit by 16-bit mulitply
  15234.                  mov     VARdy,ax
  15235.                  mov     VARdy+2,dx      ; dy = TwoAsquared * b
  15236.  
  15237.                  mov     ax,Asquared
  15238.                  mov     dx,Asquared+2   ; DX:AX = Asquared
  15239.                  sar     dx,1
  15240.                  rcr     ax,1
  15241.                  sar     dx,1
  15242.                  rcr     ax,1            ; DX:AX = Asquared/4
  15243.  
  15244.                  add     ax,Bsquared
  15245.                  adc     dx,Bsquared+2   ; DX:AX = Bsquared + Asquared/4
  15246.                  mov     VARd,ax
  15247.                  mov     VARd+2,dx
  15248.  
  15249.                  mov     ax,Asquared
  15250.                  mov     dx,Asquared+2
  15251.                  mov     cx,ARGb
  15252.                  call    LongMultiply    ; DX:AX = Asquared*b
  15253.                  sub     VARd,ax
  15254.                  sbb     VARd+2,dx       ; d = Bsquared - Asquared*b + Asquare
  15255.  
  15256.  ; loop until dy/dx >= -1
  15257.  
  15258.                  mov     bx,ARGb         ; BX := initial y-coordinate
  15259.  
  15260.                  xor     cx,cx           ; CH := 0 (initial y-increment)
  15261.                                          ; CL := 0 (initial x-increment)
  15262.  L10:            mov     ax,VARdx
  15263.                  mov     dx,VARdx+2
  15264.                  sub     ax,VARdy
  15265.                  sbb     dx,VARdy+2
  15266.                  jns     L20             ; jump if dx>=dy
  15267.  
  15268.                  call    Set4Pixels
  15269.  
  15270.                  mov     cx,1            ; CH := 0 (y-increment)
  15271.                                          ; CL := 1 (x-increment)
  15272.                  cmp     VARd+2,0
  15273.                  js      L11             ; jump if d < 0
  15274.  
  15275.                  mov     ch,1            ; increment in y direction
  15276.                  dec     bx              ; decrement current y-coordinate
  15277.  
  15278.                  mov     ax,VARdy
  15279.                  mov     dx,VARdy+2
  15280.                  sub     ax,TwoAsquared
  15281.                  sbb     dx,TwoAsquared+2 ; DX:AX := dy - TwoAsquared
  15282.                  mov     VARdy,ax
  15283.                  mov     VARdy+2,dx      ; dy -= TwoAsquared
  15284.  
  15285.                  sub     VARd,ax
  15286.                  sbb     VARd+2,dx       ; d -= dy
  15287.  
  15288.  L11:            mov     ax,VARdx
  15289.                  mov     dx,VARdx+2
  15290.                  add     ax,TwoBsquared
  15291.                  adc     dx,TwoBsquared+2 ; DX:AX := dx + TwoBsquared
  15292.                  mov     VARdx,ax
  15293.                  mov     VARdx+2,dx      ; dx += TwoBsquared
  15294.  
  15295.                  add     ax,Bsquared
  15296.                  adc     dx,Bsquared+2   ; DX:AX := dx + Bsquared
  15297.                  add     VARd,ax
  15298.                  adc     VARd+2,dx       ; d += dx + Bsquared
  15299.  
  15300.                  jmp     L10
  15301.  ;
  15302.  ; plot pixels from current (x,y) until y < 0
  15303.  ;
  15304.  
  15305.  ; initial buffer address and bit mask
  15306.  
  15307.  L20:            push    bx              ; preserve current y-coordinate
  15308.                  push    cx              ; preserve x- and y-increments
  15309.  
  15310.                  mov     ax,Asquared
  15311.                  mov     dx,Asquared+2
  15312.                  sub     ax,Bsquared
  15313.                  sbb     dx,Bsquared+2   ; DX:AX := Asquared-Bsquared
  15314.  
  15315.                  mov     bx,ax
  15316.                  mov     cx,dx           ; CX:BX := (Asquared-Bsquared)
  15317.  
  15318.                  sar     dx,1
  15319.                  rcr     ax,1            ; DX:AX := (Asquared-Bsquared)/2
  15320.                  add     ax,bx
  15321.                  adc     dx,cx           ; DX:AX := 3*(Asquared-Bsquared)/2
  15322.  
  15323.                  sub     ax,VARdx
  15324.                  sbb     dx,VARdx+2
  15325.                  sub     ax,VARdy
  15326.                  sbb     dx,VARdy+2      ; DX:AX := 3*(Asquared-Bsquared)/2 -
  15327.  
  15328.                  sar     dx,1
  15329.                  rcr     ax,1            ; DX:AX :=
  15330.                                          ;  ( 3*(Asquared-Bsquared)/2 - (dx+dy
  15331.                  add     VARd,ax
  15332.                  adc     VARd+2,dx       ; update d
  15333.  
  15334.  ; loop until y < 0
  15335.  
  15336.                  pop     cx              ; CH,CL := y- and x-increments
  15337.                  pop     bx              ; BX := y
  15338.  
  15339.  L21:            call    Set4Pixels
  15340.  
  15341.                  mov     cx,100h         ; CH := 1 (y-increment)
  15342.                                          ; CL := 0 (x-increment)
  15343.  
  15344.                  cmp     VARd+2,0
  15345.                  jns     L22             ; jump if d >= 0
  15346.  
  15347.                  mov     cl,1            ; increment in x direction
  15348.  
  15349.                  mov     ax,VARdx
  15350.                  mov     dx,VARdx+2
  15351.                  add     ax,TwoBsquared
  15352.                  adc     dx,TwoBsquared+2 ; DX:AX := dx + TwoBsquared
  15353.                  mov     VARdx,ax
  15354.                  mov     VARdx+2,dx      ; dx += TwoBsquared
  15355.  
  15356.                  add     VARd,ax
  15357.                  adc     VARd+2,dx       ; d += dx
  15358.  
  15359.  L22:            mov     ax,VARdy
  15360.                  mov     dx,VARdy+2
  15361.                  sub     ax,TwoAsquared
  15362.                  sbb     dx,TwoAsquared+2 ; DX:AX := dy - TwoAsquared
  15363.                  mov     VARdy,ax
  15364.                  mov     VARdy+2,dx      ; dy -= TwoAsquared
  15365.  
  15366.                  sub     ax,Asquared
  15367.                  sbb     dx,Asquared+2   ; DX:AX := dy - Asquared
  15368.                  sub     VARd,ax
  15369.                  sbb     VARd+2,dx       ; d += Asquared - dy
  15370.  
  15371.                  dec     bx              ; decrement y
  15372.                  jns     L21             ; loop if y >= 0
  15373.  
  15374.  
  15375.  ; restore default Graphics Controller registers
  15376.  
  15377.  Lexit:          mov     ax,0FF08h       ; default Bit Mask
  15378.                  mov     dx,3CEh
  15379.                  out     dx,ax
  15380.  
  15381.                  mov     ax,0003         ; default Function Select
  15382.                  out     dx,ax
  15383.  
  15384.                  mov     ax,0001         ; default Enable Set/Reset
  15385.                  out     dx,ax
  15386.  
  15387.                  pop     di              ; restore registers and return
  15388.                  pop     si
  15389.                  mov     sp,bp
  15390.                  pop     bp
  15391.                  ret
  15392.  
  15393.  _Ellipse10      ENDP
  15394.  
  15395.  
  15396.  Set4Pixels      PROC    near            ; Call with:  CH := y-increment (0, -
  15397.                                          ;             CL := x-increment (0, 1
  15398.  
  15399.                  push    ax              ; preserve these regs
  15400.                  push    bx
  15401.                  push    dx
  15402.  
  15403.                  mov     dx,3CEh         ; DX := Graphics Controller port
  15404.  
  15405.                  xor     bx,bx           ; BX := 0
  15406.                  test    ch,ch
  15407.                  jz      L30             ; jump if y-increment = 0
  15408.  
  15409.                  mov     bx,BytesPerLine ; BX := positive increment
  15410.                  neg     bx              ; BX := negative increment
  15411.  
  15412.  L30:            mov     al,8            ; AL := Bit Mask reg number
  15413.  
  15414.  ; pixels at (xc-x,yc+y) and (xc-x,yc-y)
  15415.  
  15416.                  xor     si,si           ; SI := 0
  15417.                  mov     ah,LMask
  15418.  
  15419.                  rol     ah,cl           ; AH := bit mask rotated horizontally
  15420.                  rcl     si,1            ; SI := 1 if bit mask rotated around
  15421.                  neg     si              ; SI := 0 or -1
  15422.  
  15423.                  mov     di,si           ; SI,DI := left horizontal increment
  15424.  
  15425.                  add     si,ULAddr       ; SI := upper left addr + horiz incr
  15426.                  add     si,bx           ; SI := new upper left addr
  15427.                  add     di,LLAddr
  15428.                  sub     di,bx           ; DI := new lower left addr
  15429.  
  15430.                  mov     LMask,ah        ; update these variables
  15431.                  mov     ULAddr,si
  15432.                  mov     LLAddr,di
  15433.  
  15434.                  out     dx,ax           ; update Bit Mask register
  15435.  
  15436.                  mov     ch,es:[si]      ; update upper left pixel
  15437.                  mov     es:[si],ch
  15438.                  mov     ch,es:[di]      ; update lower left pixel
  15439.                  mov     es:[di],ch
  15440.  
  15441.  
  15442.  ; pixels at (xc+x,yc+y) and (xc+x,yc-y)
  15443.  
  15444.                  xor     si,si           ; SI := 0
  15445.                  mov     ah,RMask
  15446.  
  15447.                  ror     ah,cl           ; AH := bit mask rotated horizontally
  15448.                  rcl     si,1            ; SI := 1 if bit mask rotated around
  15449.  
  15450.                  mov     di,si           ; SI,DI := right horizontal increment
  15451.  
  15452.                  add     si,URAddr       ; SI := upper right addr + horiz incr
  15453.                  add     si,bx           ; SI := new upper right addr
  15454.                  add     di,LRAddr
  15455.                  sub     di,bx           ; DI := new lower right addr
  15456.  
  15457.                  mov     RMask,ah        ; update these variables
  15458.                  mov     URAddr,si
  15459.                  mov     LRAddr,di
  15460.  
  15461.                  out     dx,ax           ; update Bit Mask register
  15462.  
  15463.                  mov     ch,es:[si]      ; update upper right pixel
  15464.                  mov     es:[si],ch
  15465.                  mov     ch,es:[di]      ; update lower right pixel
  15466.                  mov     es:[di],ch
  15467.  
  15468.                  pop     dx              ; restore these regs
  15469.                  pop     bx
  15470.                  pop     ax
  15471.                  ret
  15472.  
  15473.  Set4Pixels      ENDP
  15474.  
  15475.  
  15476.  LongMultiply    PROC    near            ; Caller:       DX = u1 (hi-order wor
  15477.                                          ;                of 32-bit number)
  15478.                                          ;               AX = u2 (lo-order wor
  15479.                                          ;               CX = v1 (16-bit numbe
  15480.                                          ; Returns:      DX:AX = 32-bit result
  15481.  
  15482.                  push    ax              ; preserve u2
  15483.                  mov     ax,dx           ; AX :=
  15484.                  mul     cx              ; AX := high-order word of result
  15485.                  xchg    ax,cx           ; AX := v1, CX := high-order word
  15486.                  pop     dx              ; DX := u2
  15487.                  mul     dx              ; AX := low-order word of result
  15488.                                          ; DX := carry
  15489.                  add     dx,cx           ; CX := high-order word of result
  15490.                  ret
  15491.  
  15492.  LongMultiply    ENDP
  15493.  
  15494.  _TEXT           ENDS
  15495.  
  15496.                  END
  15497.  
  15498.  \SAMPCODE\VIDEO\8
  15499.  \SAMPCODE\VIDEO\8\8_1.C
  15500.  
  15501.  /* Listing 6-3 */
  15502.  
  15503.  FilledRectangle( x1, y1, x2, y2, n )
  15504.  int     x1,y1;                  /* upper left corner */
  15505.  int     x2,y2;                  /* lower right corner */
  15506.  int     n;                      /* pixel value */
  15507.  {
  15508.          int     y;
  15509.  
  15510.          for (y=y1; y<=y2; y++)          /* draw rectangle as a set of */
  15511.            Line( x1, y, x2, y, n );      /*  adjacent horizontal lines */
  15512.  }
  15513.  
  15514.  \SAMPCODE\VIDEO\8\8_2.C
  15515.  
  15516.  /* Listing 8-2 */
  15517.  
  15518.  int     FillValue;                       /* value of pixels in filled region
  15519.  int     BorderValue;                     /* value of pixels in border */
  15520.  
  15521.  PixelFill( x, y )
  15522.  in⌠     x,y;
  15523.  {
  15524.          int     v;
  15525.  
  15526.          v = ReadPixel( x, y );
  15527.  
  15528.          if ( (v!=FillValue) && (v!=BorderValue) )
  15529.          {
  15530.            SetPixel( x, y, FillValue );
  15531.  
  15532.            PixelFill( x-1, y );
  15533.            PixelFill( x+1, y );
  15534.            PixelFill( x, y-1 );
  15535.            PixelFill( x, y+1 );
  15536.          }
  15537.  }
  15538.  
  15539.  \SAMPCODE\VIDEO\8\8_3.C
  15540.  
  15541.  /* Listing 8-3 */
  15542.  
  15543.  #define UP              -1
  15544.  #define DOWN            1
  15545.  
  15546.  
  15547.  LineAdjFill( SeedX, SeedY, D, PrevXL, PrevXR )
  15548.  int     SeedX,SeedY;            /* seed for current row of pixels */
  15549.  int     D;                      /* direction searched to find current row */
  15550.  int     PrevXL,PrevXR;          /* endpoints of previous row of pixels */
  15551.  {
  15552.          int     x,y;
  15553.          int     xl,xr;
  15554.          int     v;
  15555.  
  15556.          y = SeedY;              /* initialize to seed coordinates */
  15557.          xl = SeedX;
  15558.          xr = SeedX;
  15559.  
  15560.          ScanLeft( &xl, &y );    /* determine endpoints of seed line segment *
  15561.          ScanRight( &xr, &y );
  15562.  
  15563.          Line( xl, y, xr, y, FillValue );        /* fill line with FillValue *
  15564.  
  15565.  
  15566.  /* find and fill adjacent line segments in same direction */
  15567.  
  15568.          for (x=xl; x<=xr; x++)          /* inspect adjacent rows of pixels */
  15569.          {
  15570.            v = ReadPixel( x, y+D );
  15571.            if ( (v!=BorderValue) && (v!=FillValue) )
  15572.              x = LineAdjFill( x, y+D, D, xl, xr );
  15573.          }
  15574.  
  15575.  /* find and fill adjacent line segments in opposite direction */
  15576.  
  15577.          for (x=xl; x<PrevXL; x++)
  15578.          {
  15579.            v = ReadPixel( x, y-D );
  15580.            if ( (v!=BorderValue) && (v!=FillValue) )
  15581.              x = LineAdjFill( x, y-D, -D, xl, xr );
  15582.          }
  15583.  
  15584.          for (x=PrevXR; x<xr; x++)
  15585.          {
  15586.            v = ReadPixel( x, y-D );
  15587.            if ( (v!=BorderValue) && (v!=FillValue) )
  15588.              x = LineAdjFill( x, y-D, -D, xl, xr );
  15589.          }
  15590.  
  15591.          return( xr );
  15592.  }
  15593.  
  15594.  
  15595.  ScanLeft( x, y )
  15596.  int     *x,*y;
  15597.  {
  15598.          int     v;
  15599.  
  15600.  
  15601.          do
  15602.          {
  15603.            --(*x);                       /* move left one pixel */
  15604.            v = ReadPixel( *x, *y );      /* determine its value */
  15605.          }
  15606.          while ( (v!=BorderValue) && (v!=FillValue) );
  15607.  
  15608.          ++(*x);         /* x-coordinate of leftmost pixel in row */
  15609.  }
  15610.  
  15611.  
  15612.  ScanRight( x, y )
  15613.  int     *x,*y;
  15614.  {
  15615.          int     v;
  15616.  
  15617.  
  15618.          do
  15619.          {
  15620.            ++(*x);                       /* move right one pixel */
  15621.            v = ReadPixel( *x, *y );      /* determine its value */
  15622.          }
  15623.          while ( (v!=BorderValue) && (v!=FillValue) );
  15624.  
  15625.          --(*x);         /* x-coordinate of rightmost pixel in row */
  15626.  }
  15627.  
  15628.  \SAMPCODE\VIDEO\8\8_4.C
  15629.  
  15630.  /* Listing 8-3 */
  15631.  
  15632.  #define BLOCKED         1
  15633.  #define UNBLOCKED       2
  15634.  #define TRUE            1
  15635.  #define FALSE           0
  15636.  
  15637.  struct  BPstruct                        /* table of border pixels */
  15638.  {
  15639.          int     x,y;
  15640.          int     flag;
  15641.  }
  15642.          BP[3000];                       /* (increase if necessary) */
  15643.  
  15644.  int     BPstart;                        /* start of table */
  15645.  int     BPend = 0;                      /* first empty cell in table */
  15646.  int     FillValue;                      /* value of pixels in filled region *
  15647.  int     BorderValue;                    /* value of pixels in border */
  15648.  
  15649.  
  15650.  BorderFill( x, y )
  15651.  int     x,y;
  15652.  {
  15653.          do                              /* do until entire table has been sca
  15654.          {
  15655.            TraceBorder( x, y );          /* trace border starting at x,y */
  15656.            SortBP( BP );                 /* sort the border pixel table */
  15657.            ScanRegion( &x, &y );         /* look for holes in the interior */
  15658.          }
  15659.          while (BPstart < BPend);
  15660.  
  15661.          FillRegion();                   /* use the table to fill the interior
  15662.  }
  15663.  
  15664.  
  15665.  ScanRegion( x, y )
  15666.  int     *x,*y;
  15667.  {
  15668.          int     i = BPstart;
  15669.          int     xr;
  15670.  
  15671.          while (i<BPend)
  15672.          {
  15673.            if (BP[i].flag == BLOCKED)            /* skip pixel if blocked */
  15674.              ++i;
  15675.  
  15676.            else
  15677.            if (BP[i].y != BP[i+1].y)             /* skip pixel if last in line
  15678.              ++i;
  15679.  
  15680.            else
  15681.            {                                     /* if at least one pixel to f
  15682.              if (BP[i].x < BP[i+1].x-1)          /* .. scan the line */
  15683.              {
  15684.                xr = ScanRight( BP[i].x+1, BP[i].y );
  15685.  
  15686.                if (xr<BP[i+1].x)                 /* if a border pixel is found
  15687.                {
  15688.                  *x = xr;                        /* .. return its x,y coordina
  15689.                  *y = BP[i].y;
  15690.                  break;
  15691.                }
  15692.              }
  15693.  
  15694.              i += 2;                             /* advance past this pair of
  15695.            }
  15696.          }
  15697.  
  15698.          BPstart = i;
  15699.  }
  15700.  
  15701.  
  15702.  SortBP()                        /* uses Microsoft C library quicksort routine
  15703.  {
  15704.          int     CompareBP();
  15705.  
  15706.          qsort( BP+BPstart, BPend-BPstart, sizeof(struct BPstruct), CompareBP
  15707.  }
  15708.  
  15709.  
  15710.  CompareBP( arg1, arg2 )         /* returns -1 if arg1 < arg2 */
  15711.  struct  BPstruct  *arg1,*arg2;
  15712.  {
  15713.          int     i;
  15714.  
  15715.          i = arg1->y - arg2->y;          /* sort by y-coordinate */
  15716.          if (i!=0)
  15717.            return( (i<0) ? -1 : 1 );     /* (return -1 if i<0, 1 if i>0) */
  15718.  
  15719.          i = arg1->x - arg2->x;          /* sort by x-coordinate */
  15720.          if (i!=0)
  15721.            return( (i<0) ? -1 : 1 );
  15722.  
  15723.          i = arg1->flag - arg2->flag;    /* sort by flag */
  15724.            return( (i<0) ? -1 : 1 );
  15725.  }
  15726.  
  15727.  
  15728.  FillRegion()
  15729.  {
  15730.          int     i;
  15731.  
  15732.  
  15733.          for(i=0; i<BPend;)
  15734.          {
  15735.            if (BP[i].flag == BLOCKED)            /* skip pixel if blocked */
  15736.              ++i;
  15737.  
  15738.            else
  15739.            if (BP[i].y != BP[i+1].y)             /* skip pixel if last in line
  15740.              ++i;
  15741.  
  15742.            else
  15743.            {                                     /* if at least one pixel to f
  15744.              if (BP[i].x < BP[i+1].x-1)          /* .. draw a line */
  15745.                Line( BP[i].x+1, BP[i].y, BP[i+1].x-1, BP[i+1].y, FillValue );
  15746.  
  15747.              i += 2;
  15748.            }
  15749.          }
  15750.  }
  15751.  
  15752.  
  15753.  /* border tracing routine */
  15754.  
  15755.  struct  BPstruct CurrentPixel;
  15756.  int     D;                              /* current search direction */
  15757.  int     PrevD;                          /* previous search direction */
  15758.  int     PrevV;                          /* previous vertical direction */
  15759.  
  15760.  
  15761.  TraceBorder( StartX, StartY )
  15762.  int     StartX,StartY;
  15763.  {
  15764.          int     NextFound;              /* flags */
  15765.          int     Done;
  15766.  
  15767.  /* initialize */
  15768.  
  15769.          CurrentPixel.x = StartX;
  15770.          CurrentPixel.y = StartY;
  15771.  
  15772.          D = 6;                          /* current search direction */
  15773.          PrevD = 8;                      /* previous search direction */
  15774.          PrevV = 2;                      /* most recent vertical direction */
  15775.  
  15776.  /* loop around the border until returned to the starting pixel */
  15777.  
  15778.          do
  15779.          {
  15780.            NextFound = FindNextPixel();
  15781.            Done =
  15782.             (CurrentPixel.x == StartX) && (CurrentPixel.y == StartY);
  15783.          }
  15784.          while (NextFound && !Done);
  15785.  
  15786.  /* if only one pixel in border, add it twice to the table */
  15787.  
  15788.          if (!NextFound)                         /* pixel has no neighbors */
  15789.          {
  15790.            AppendBPList( StartX, StartY, UNBLOCKED );
  15791.            AppendBPList( StartX, StartY, UNBLOCKED );
  15792.          }
  15793.  
  15794.  /* if last search direction was upward, add the starting pixel to the table *
  15795.  
  15796.          else
  15797.          if ( (PrevD <= 3) && (PrevD >= 1) )
  15798.            AppendBPList( StartX, StartY, UNBLOCKED );
  15799.  }
  15800.  
  15801.  
  15802.  FindNextPixel( )
  15803.  {
  15804.          int     i;
  15805.          int     flag;
  15806.  
  15807.  
  15808.          for (i=-1; i<=5; i++)
  15809.          {
  15810.            flag = FindBP( (D+i) & 7 );           /* search for next border pix
  15811.            if (flag)                             /* flag is TRUE if found */
  15812.            {
  15813.              D = (D+i) & 6;                      /* (D+i) MOD 2 */
  15814.              break;                              /* exit from loop */
  15815.            }
  15816.          }
  15817.  
  15818.          return(flag);
  15819.  }
  15820.  
  15821.  
  15822.  FindBP( d )
  15823.  int     d;                      /* direction to search for next border pixel
  15824.  {
  15825.          int     x,y;
  15826.  
  15827.          x = CurrentPixel.x;
  15828.          y = CurrentPixel.y;
  15829.  
  15830.  
  15831.          NextXY( &x, &y, d );            /* get x,y of pixel in direction d */
  15832.  
  15833.          if ( BorderValue == ReadPixel( x, y ) )
  15834.          {
  15835.            AddBPList( d );               /* add pixel at x,y to table */
  15836.            CurrentPixel.x = x;           /* pixel at x,y becomes current pixel
  15837.            CurrentPixel.y = y;
  15838.            return( TRUE );
  15839.          }
  15840.  
  15841.          else
  15842.            return( FALSE );
  15843.  }
  15844.  
  15845.  
  15846.  NextXY( x, y, Direction )
  15847.  int     *x,*y;
  15848.  int     Direction;
  15849.  {
  15850.          switch( Direction )             /*   3 2 1   */
  15851.          {                               /*   4   0   */
  15852.            case 1:                       /*   5 6 7   */
  15853.            case 2:
  15854.            case 3:
  15855.  
  15856.                  *y -= 1;                /* up */
  15857.                  break;
  15858.            case 5:
  15859.            case 6:
  15860.            case 7:
  15861.                  *y += 1;                /* down */
  15862.                  break;
  15863.          }
  15864.  
  15865.          switch(Direction)
  15866.          {
  15867.            case 3:
  15868.            case 4:
  15869.            case 5:
  15870.                  *x -= 1;                /* left */
  15871.                  break;
  15872.            case 1:
  15873.            case 0:
  15874.            case 7:
  15875.                  *x += 1;                /* right */
  15876.                  break;
  15877.          }
  15878.  }
  15879.  
  15880.  
  15881.  AddBPList( d )
  15882.  int     d;
  15883.  {
  15884.          if (d == PrevD)
  15885.            SameDirection();
  15886.  
  15887.          else
  15888.          {
  15889.            DifferentDirection( d );
  15890.            PrevV = PrevD;                        /* new previous vertical dire
  15891.          }
  15892.  
  15893.          PrevD = d;                              /* new previous search direct
  15894.  }
  15895.  
  15896.  SameDirection()
  15897.  {
  15898.          if (PrevD == 0)                         /* moving right ... */
  15899.            BP[BPend-1].flag = BLOCKED;           /* .. block previous pixel */
  15900.  
  15901.          else
  15902.          if (PrevD != 4)                         /* if not moving horizontally
  15903.            AppendBPList( CurrentPixel.x, CurrentPixel.y, UNBLOCKED );
  15904.  }
  15905.  
  15906.  
  15907.  DifferentDirection( d )
  15908.  int     d;
  15909.  {
  15910.  
  15911.  /* previously moving left */
  15912.  
  15913.          if (PrevD == 4)
  15914.          {
  15915.            if (PrevV == 5)                       /* if from above .. */
  15916.              BP[BPend-1].flag = BLOCKED;         /* .. block rightmost in line
  15917.  
  15918.            AppendBPList( CurrentPixel.x, CurrentPixel.y, BLOCKED );
  15919.          }
  15920.  
  15921.  /* previously moving right */
  15922.  
  15923.          else
  15924.          if (PrevD == 0)                         /* previously moving right ..
  15925.          {
  15926.            BP[BPend-1].flag = BLOCKED;           /* .. block rightmost in line
  15927.  
  15928.            if (d == 7)                           /* if line started from above
  15929.              AppendBPList( CurrentPixel.x, CurrentPixel.y, BLOCKED );
  15930.            else
  15931.              AppendBPList( CurrentPixel.x, CurrentPixel.y, UNBLOCKED );
  15932.          }
  15933.  
  15934.  /* previously moving in some vertical direction */
  15935.  
  15936.          else
  15937.          {
  15938.            AppendBPList( CurrentPixel.x, CurrentPixel.y, UNBLOCKED );
  15939.  
  15940.  /* add pixel twice if local vertical maximum or minimum */
  15941.  
  15942.            if ( ( (d>=1) && (d<=3) ) && ( (PrevD >= 5) && (PrevD <= 7) ) ||
  15943.                 ( (d>=5) && (d<=7) ) && ( (PrevD >= 1) && (PrevD <= 3) ) )
  15944.              AppendBPList( CurrentPixel.x, CurrentPixel.y, UNBLOCKED );
  15945.          }
  15946.  }
  15947.  
  15948.  
  15949.  AppendBPList( p, q, f )
  15950.  int     p,q;                    /* pixel x,y coordinates */
  15951.  int     f;                      /* flag */
  15952.  {
  15953.          BP[BPend].x = p;
  15954.          BP[BPend].y = q;
  15955.          BP[BPend].flag = f;
  15956.  
  15957.          ++BPend;                /* increment past last entry in table */
  15958.  }
  15959.  
  15960.  
  15961.  /* routine to scan a line for a border pixel */
  15962.  
  15963.  int     Xmax;                   /* largest valid pixel x-coordinate */
  15964.  
  15965.  ScanRight( x, y )
  15966.  int     x,y;
  15967.  {
  15968.          while ( ReadPixel( x, y ) != BorderValue )
  15969.          {
  15970.            ++x;                          /* increment x */
  15971.            if (x==Xmax)                  /* if end of line in buffer .. */
  15972.              break;                      /* .. exit from the loop */
  15973.          }
  15974.  
  15975.          return( x );
  15976.  }
  15977.  
  15978.  \SAMPCODE\VIDEO\8\8_5.ASM
  15979.  
  15980.                  TITLE   'Listing 8-4'
  15981.                  NAME    ScanRight10
  15982.                  PAGE    55,132
  15983.  
  15984.  ;
  15985.  ; Name:         ScanRight10
  15986.  ;
  15987.  ; Function:     Scan for a pixel of a given value in 16-color EGA/VGA graphic
  15988.  ;
  15989.  ; Caller:       Microsoft C:
  15990.  ;
  15991.  ;                       int ScanRight10(x,y);
  15992.  ;
  15993.  ;                       int x,y;                        /* starting pixel */
  15994.  ;
  15995.  ;                       extern  int BorderValue;        /* value of border pi
  15996.  ;
  15997.  ;               Returns the x-coordinate of the rightmost border pixel.
  15998.  ;
  15999.  
  16000.  ARGx            EQU     word ptr [bp+4] ; stack frame addressing
  16001.  ARGy            EQU     word ptr [bp+6]
  16002.  
  16003.  ByteOffsetShift EQU     3               ; used to convert pixels to byte offs
  16004.  BytesPerLine    EQU     80              ; 80 for most 16-color graphics modes
  16005.                                          ;  (40 for 320x200 16-color)
  16006.  
  16007.  
  16008.  DGROUP          GROUP   _DATA
  16009.  
  16010.  _TEXT           SEGMENT byte public 'CODE'
  16011.                  ASSUME  cs:_TEXT,ds:DGROUP
  16012.  
  16013.                  EXTRN   PixelAddr10:near
  16014.  
  16015.                  PUBLIC  _ScanRight10
  16016.  _ScanRight10    PROC    near
  16017.  
  16018.                  push    bp              ; preserve caller registers
  16019.                  mov     bp,sp
  16020.                  push    si
  16021.                  push    di
  16022.  
  16023.  ; calculate pixel address of (0,y)
  16024.  
  16025.                  mov     ax,ARGy         ; AX := y
  16026.                  xor     bx,bx           ; BX := 0
  16027.                  call    PixelAddr10     ; ES:BX -> buffer
  16028.                  mov     di,bx           ; ES:DI -> buffer
  16029.  
  16030.  ; calculate offset of x in row
  16031.  
  16032.                  mov     ax,ARGx
  16033.                  mov     si,ax           ; SI,AX := x
  16034.                  mov     cl,ByteOffsetShift
  16035.                  shr     si,cl           ; SI := offset of x in row y
  16036.                  add     di,si           ; DI := offset of x in buffer
  16037.  
  16038.  ; calculate a bit mask for the first byte to scan
  16039.  
  16040.                  mov     cl,al
  16041.                  and     cl,7            ; CL := x & 7
  16042.                  mov     ch,0FFh
  16043.                  shr     ch,cl           ; CH := bit mask for first scanned by
  16044.  
  16045.  ; configure the Graphics Controller
  16046.  
  16047.                  mov     dx,3CEh         ; DX := Graphics Controller port addr
  16048.  
  16049.                  mov     ah,_BorderValue ; AH := pixel value for Color Compare
  16050.                  mov     al,2            ; AL := Color Compare Reg number
  16051.                  out     dx,ax
  16052.  
  16053.                  mov     ax,805h         ; AH := 00001000b (Read Mode 1)
  16054.                  out     dx,ax           ; AL := Mode reg number
  16055.  
  16056.                  mov     ax,0F07h        ; AH := 00001111b (Color Compare reg
  16057.                  out     dx,ax           ; AL := Color Compare reg number
  16058.  
  16059.  ; inspect the first byte for border pixels
  16060.  
  16061.                  mov     al,es:[di]      ; AL := nonzero bits corresponding to
  16062.                                          ;  border pixels
  16063.                  inc     di              ; ES:DI -> next byte to scan
  16064.                  and     al,ch           ; apply bit mask
  16065.                  jnz     L01             ; jump if border pixel(s) found
  16066.  
  16067.  ; scan remainder of line for border pixels
  16068.  
  16069.                  mov     cx,BytesPerLine
  16070.                  sub     cx,si           ; CX := BytesPerLine - (byte offset o
  16071.                                          ;  starting pixel)
  16072.                  dec     cx              ; CX := # of bytes to scan
  16073.  
  16074.                  repe    scasb           ; scan until nonzero byte read; i.e.,
  16075.                                          ;  border pixel(s) found
  16076.  
  16077.  ; compute x value of border pixel
  16078.  
  16079.                  mov     al,es:[di-1]    ; AL := last byte compared
  16080.  
  16081.  L01:            sub     di,bx           ; DI := offset of byte past the one w
  16082.                                          ;  contains a border pixel
  16083.                  mov     cl,ByteOffsetShift
  16084.                  shl     di,cl           ; DI := x-coordinate of 1st pixel in
  16085.  
  16086.                  mov     cx,8            ; CX := loop limit
  16087.  
  16088.  L02:            shl     al,1            ; isolate first border pixel
  16089.                  jc      L03
  16090.  
  16091.                  loop    L02
  16092.  
  16093.  L03:            sub     di,cx           ; DI := x-coordinate of border pixel
  16094.  
  16095.  ; restore default Graphics Controller state and return to caller
  16096.  
  16097.                  mov     ax,2            ; AH := 0 (default Color Compare valu
  16098.                  out     dx,ax           ; restore Color Compare reg
  16099.  
  16100.                  mov     al,5            ; AH := 0, AL := 5
  16101.                  out     dx,ax           ; restore Mode reg
  16102.  
  16103.                  mov     ax,di           ; AX := return value
  16104.  
  16105.                  pop     di              ; restore caller registers and return
  16106.                  pop     si
  16107.                  mov     sp,bp
  16108.                  pop     bp
  16109.                  ret
  16110.  
  16111.  _ScanRight10    ENDP
  16112.  
  16113.  _TEXT           ENDS
  16114.  
  16115.  
  16116.  _DATA           SEGMENT word public 'DATA'
  16117.  
  16118.                  EXTRN   _BorderValue:byte
  16119.  
  16120.  _DATA           ENDS
  16121.  
  16122.                  END
  16123.  
  16124.  \SAMPCODE\VIDEO\9
  16125.  \SAMPCODE\VIDEO\9\9_2.ASM
  16126.  
  16127.                  TITLE   'Listing 9-3'
  16128.                  NAME    DisplayChar06
  16129.                  PAGE    55,132
  16130.  
  16131.  ;
  16132.  ; Name:         DisplayChar06
  16133.  ;
  16134.  ; Function:     Display a character in 640x200 2-color mode
  16135.  ;
  16136.  ; Caller:       Microsoft C:
  16137.  ;
  16138.  ;                       void DisplayChar06(c,x,y,fgd,bkgd);
  16139.  ;
  16140.  ;                       int c;                  /* character code */
  16141.  ;
  16142.  ;                       int x,y;                /* upper left pixel */
  16143.  ;
  16144.  ;                       int fgd,bkgd;           /* foreground and background
  16145.  ;                                                   pixel values */
  16146.  ;
  16147.  
  16148.  ARGc            EQU     word ptr [bp+4] ; stack frame addressing
  16149.  ARGx            EQU     word ptr [bp+6]
  16150.  ARGy            EQU     word ptr [bp+8]
  16151.  ARGfgd          EQU     byte ptr [bp+10]
  16152.  ARGbkgd         EQU     byte ptr [bp+12]
  16153.  
  16154.  VARmask         EQU     [bp-2]
  16155.  VARtoggle       EQU     [bp-4]
  16156.  
  16157.  
  16158.  _TEXT           SEGMENT byte public 'CODE'
  16159.                  ASSUME  cs:_TEXT
  16160.  
  16161.                  EXTRN   PixelAddr06:near
  16162.  
  16163.                  PUBLIC  _DisplayChar06
  16164.  _DisplayChar06  PROC    near
  16165.  
  16166.                  push    bp              ; preserve caller registers
  16167.                  mov     bp,sp
  16168.                  sub     sp,4            ; stack space for local variables
  16169.                  push    si
  16170.                  push    di
  16171.                  push    ds
  16172.  
  16173.  ; set up foreground pixel toggle mask
  16174.  
  16175.                  mov     ah,ARGfgd       ; AH := 0 or 1 (foreground pixel valu
  16176.                  ror     ah,1            ; high-order bit of AH := 0 or 1
  16177.                  cwd                     ; propagate high-order bit through DX
  16178.                  not     dx              ; DX :=     0 if foreground = 1
  16179.                                          ;    or FFFFh if foreground = 0
  16180.                  mov     VARtoggle,dx
  16181.  
  16182.  ; calculate first pixel address
  16183.  
  16184.                  mov     ax,ARGy         ; AX := y
  16185.                  mov     bx,ARGx         ; BX := x
  16186.                  call    PixelAddr06     ; ES:BX -> buffer
  16187.                                          ; CL := # bits to shift left
  16188.  
  16189.                  xor     cl,7            ; CL := # bits to rotate right
  16190.  
  16191.                  mov     ax,0FF00h
  16192.                  ror     ax,cl           ; AX := bit mask in proper position
  16193.                  mov     VARmask,ax
  16194.  
  16195.  ; set up video buffer addressing
  16196.  
  16197.                  mov     dx,2000h        ; increment for video buffer interlea
  16198.                  mov     di,80-2000h     ; increment from last to first interl
  16199.  
  16200.                  test    bx,2000h        ; set zero flag if BX in 1st interlea
  16201.                  jz      L01
  16202.  
  16203.                  xchg    di,dx           ; exchange increment values if 1st pi
  16204.                                          ;  lies in 1st interleave
  16205.  
  16206.  ; set up character definition table addressing
  16207.  
  16208.  L01:            push    bx              ; preserve buffer address
  16209.  
  16210.                  mov     ax,40h
  16211.                  mov     ds,ax           ; DS := segment of BIOS Video
  16212.                                          ;  Display Data area
  16213.                  mov     ch,ds:[85h]     ; CH := POINTS (pixel rows in charact
  16214.  
  16215.                  xor     ax,ax
  16216.                  mov     ds,ax           ; DS := absolute zero
  16217.  
  16218.                  mov     ax,ARGc         ; AL := character code
  16219.                  cmp     al,80h
  16220.                  jae     L02
  16221.  
  16222.                  mov     bx,43h*4        ; DS:BX -> int 43h vector if char < 8
  16223.                  jmp     short L03
  16224.  
  16225.  L02:            mov     bx,1Fh*4        ; DS:BX -> int 1Fh vector if char >=
  16226.                  sub     al,80h          ; put character code in range of tabl
  16227.  
  16228.  L03:            lds     si,ds:[bx]      ; DS:SI -> start of character table
  16229.                  mul     ch              ; AX := offset into char def table
  16230.                                          ;  (POINTS * char code)
  16231.                  add     si,ax           ; SI := addr of char def
  16232.  
  16233.                  pop     bx              ; restore buffer address
  16234.  
  16235.                  test    cl,cl           ; test # bits to rotate
  16236.                  jnz     L20             ; jump if character is not byte-align
  16237.  
  16238.  
  16239.  ; routine for byte-aligned characters
  16240.  
  16241.                  mov     ah,VARtoggle    ; AH := foreground toggle mask
  16242.                  xchg    ch,cl           ; CX := POINTS
  16243.  
  16244.  L10:            lodsb                   ; AL := bit pattern for next pixel ro
  16245.                  xor     al,ah           ; toggle pixels if foreground = 0
  16246.                  mov     es:[bx],al      ; store pixels in buffer
  16247.  
  16248.                  add     bx,dx           ; BX := next row in buffer
  16249.                  xchg    di,dx           ; swap buffer increments
  16250.                  loop    L10
  16251.                  jmp     short Lexit
  16252.  
  16253.  
  16254.  ; routine for non-byte-aligned characters
  16255.  
  16256.  L20:            mov     ax,VARmask
  16257.                  and     es:[bx],ax      ; mask character pixels in buffer
  16258.  
  16259.                  xor     ah,ah
  16260.                  lodsb                   ; AX := bit pattern for next pixel ro
  16261.                  xor     al,VARtoggle    ; toggle pixels if foreground = 0
  16262.  
  16263.                  ror     ax,cl           ; rotate pixels into position
  16264.                  or      es:[bx],ax      ; store pixels in buffer
  16265.  
  16266.                  add     bx,dx           ; BX := next row in buffer
  16267.                  xchg    di,dx           ; swap buffer increments
  16268.                  dec     ch
  16269.                  jnz     L20
  16270.  
  16271.  
  16272.  Lexit:          pop     ds              ; restore registers and return
  16273.                  pop     di
  16274.                  pop     si
  16275.                  mov     sp,bp
  16276.                  pop     bp
  16277.                  ret
  16278.  
  16279.  _DisplayChar06  ENDP
  16280.  
  16281.  _TEXT           ENDS
  16282.  
  16283.                  END
  16284.  
  16285.  \SAMPCODE\VIDEO\9\9_3.ASM
  16286.  
  16287.                  TITLE   'Listing 9-3'
  16288.                  NAME    DisplayChar04
  16289.                  PAGE    55,132
  16290.  
  16291.  ;
  16292.  ; Name:         DisplayChar04
  16293.  ;
  16294.  ; Function:     Display a character in 320x200 4-color graphics mode
  16295.  ;
  16296.  ; Caller:       Microsoft C:
  16297.  ;
  16298.  ;                       void DisplayChar04(c,x,y,fgd,bkgd);
  16299.  ;
  16300.  ;                       int c;                  /* character code */
  16301.  ;
  16302.  ;                       int x,y;                /* upper left pixel */
  16303.  ;
  16304.  ;                       int fgd,bkgd;           /* foreground and background
  16305.  ;                                                   pixel values */
  16306.  ;
  16307.  
  16308.  ARGc            EQU     word ptr [bp+4] ; stack frame addressing
  16309.  ARGx            EQU     word ptr [bp+6]
  16310.  ARGy            EQU     word ptr [bp+8]
  16311.  ARGfgd          EQU              [bp+10]
  16312.  ARGbkgd         EQU              [bp+12]
  16313.  
  16314.  VARshift        EQU     word ptr [bp-2]
  16315.  VARincr         EQU     word ptr [bp-4]
  16316.  
  16317.  
  16318.  DGROUP          GROUP   _DATA
  16319.  
  16320.  _TEXT           SEGMENT byte public 'CODE'
  16321.                  ASSUME  cs:_TEXT,ds:DGROUP
  16322.  
  16323.                  EXTRN   PixelAddr04:near
  16324.  
  16325.                  PUBLIC  _DisplayChar04
  16326.  _DisplayChar04  PROC    near
  16327.  
  16328.                  push    bp              ; preserve caller registers
  16329.                  mov     bp,sp
  16330.                  sub     sp,4            ; stack space for local variables
  16331.                  push    si
  16332.                  push    di
  16333.                  push    ds
  16334.  
  16335.  ; propagate pixel values
  16336.  
  16337.                  mov     bx,offset DGROUP:PropagatedPixel
  16338.                  mov     al,ARGfgd
  16339.                  xlat                    ; propagate foreground pixel value
  16340.                  mov     ah,al
  16341.                  mov     ARGfgd,ax
  16342.  
  16343.                  mov     al,ARGbkgd
  16344.                  xlat                    ; propagate background pixel value
  16345.                  mov     ah,al
  16346.                  mov     ARGbkgd,ax
  16347.  
  16348.  ; calculate first pixel address
  16349.  
  16350.                  mov     ax,ARGy         ; AX := y
  16351.                  mov     bx,ARGx         ; BX := x
  16352.                  call    PixelAddr04     ; ES:BX -> buffer
  16353.                                          ; CL := # bits to shift left
  16354.                                          ;  to mask pixel
  16355.                  mov     ch,0FCh
  16356.                  shl     ch,cl           ; CH := bit mask for right side of ch
  16357.  
  16358.                  xor     cl,6            ; CL := 6 - CL (# bits to rotate char
  16359.                                          ;  into position)
  16360.                  mov     VARshift,cx
  16361.  
  16362.  ; set up video buffer addressing
  16363.  
  16364.                  mov     di,2000h        ; increment for video buffer interlea
  16365.                  mov     VARincr,80-2000h ; increment from last to first inter
  16366.  
  16367.                  test    bx,2000h        ; set zero flag if BX in 1st interlea
  16368.                  jz      L01
  16369.  
  16370.                  xchg    VARincr,di      ; exchange increment values if 1st pi
  16371.                                          ;  lies in 1st interleave
  16372.  
  16373.  ; set up character definition table addressing
  16374.  
  16375.  L01:            push    bx              ; preserve buffer address
  16376.  
  16377.                  mov     ax,40h
  16378.                  mov     ds,ax           ; DS := segment of BIOS Video
  16379.                                          ;  Display Data area
  16380.                  mov     ch,ds:[85h]     ; CH := POINTS (pixel rows in charact
  16381.  
  16382.                  xor     ax,ax
  16383.                  mov     ds,ax           ; DS := absolute zero
  16384.  
  16385.                  mov     ax,ARGc         ; AL := character code
  16386.                  cmp     al,80h
  16387.                  jae     L02
  16388.  
  16389.                  mov     bx,43h*4        ; DS:BX -> int 43h vector if char < 8
  16390.                  jmp     short L03
  16391.  
  16392.  L02:            mov     bx,1Fh*4        ; DS:BX -> int 1Fh vector if char >=
  16393.                  sub     al,80h          ; put character code in range of tabl
  16394.  
  16395.  L03:            lds     si,ds:[bx]      ; DS:SI -> start of character table
  16396.                  mul     ch              ; AX := offset into char def table
  16397.                                          ;  (POINTS * char code)
  16398.                  add     si,ax           ; SI := addr of char def
  16399.  
  16400.                  pop     bx              ; restore buffer address
  16401.  
  16402.                  xchg    ch,cl           ; CH := # bits to rotate
  16403.                                          ; CL := POINTS
  16404.  
  16405.                  test    ch,ch           ; test # bits to rotate
  16406.                  jnz     L20             ; jump if character is not byte-align
  16407.  
  16408.  
  16409.  ; routine for byte-aligned characters
  16410.  
  16411.  L10:            lodsb                   ; AL := bit pattern for next pixel ro
  16412.                  xor     dx,dx           ; DX := initial value for doubled bit
  16413.                  mov     ah,8            ; AH := # of bits in pattern
  16414.  
  16415.  L11:            shr     al,1            ; cf := lo-order bit of AL
  16416.                  rcr     dx,1            ; hi-order bit of CX := cf
  16417.                  sar     dx,1            ; double hi-order bit of DX
  16418.                  dec     ah              ; loop 8 times
  16419.                  jnz     L11
  16420.  
  16421.                  mov     ax,dx           ; AX,DX := doubled bit pattern
  16422.                  and     ax,ARGfgd       ; AX := foreground pixels
  16423.                  not     dx
  16424.                  and     dx,ARGbkgd      ; DX := background pixels
  16425.  
  16426.                  or      ax,dx           ; AX := eight pixels
  16427.                  xchg    ah,al           ; put bytes in proper order
  16428.                  mov     es:[bx],ax      ; update video buffer
  16429.  
  16430.                  add     bx,di           ; BX := next row in buffer
  16431.                  xchg    di,VARincr      ; swap buffer increments
  16432.  
  16433.                  loop    L10
  16434.                  jmp     short Lexit
  16435.  
  16436.  
  16437.  ; routine for non-byte-aligned characters
  16438.  
  16439.  L20:            xor     ch,ch           ; CX := POINTS
  16440.  
  16441.  L21:            push    cx              ; preserve CX
  16442.  
  16443.                  mov     cx,VARshift     ; CH := mask for right side of char
  16444.                                          ; CL := # bits to rotate
  16445.  
  16446.                  lodsb                   ; AL := bit pattern for next pixel ro
  16447.                  xor     dx,dx           ; DX := initial value for doubled bit
  16448.                  mov     ah,8            ; AH := # of bits in pattern
  16449.  
  16450.  L22:            shr     al,1            ; DX := double bits in AL
  16451.                  rcr     dx,1            ;  (same as above)
  16452.                  sar     dx,1
  16453.                  dec     ah
  16454.                  jnz     L22
  16455.  
  16456.                  xchg    dh,dl           ; DH := bits for right half of char
  16457.                                          ; DL := bits for left half of char
  16458.                  mov     ax,dx
  16459.                  and     ax,ARGfgd       ; AX := foreground pixels
  16460.                  not     dx
  16461.                  and     dx,ARGbkgd      ; DX := background pixels
  16462.  
  16463.                  or      dx,ax           ; DX := eight pixels
  16464.                  ror     dx,cl           ; DH := left and right side pixels
  16465.                                          ; DL := middle pixels
  16466.                  mov     al,ch
  16467.                  xor     ah,ah           ; AX := mask for left and middle
  16468.                                          ;  bytes of char
  16469.                  and     es:[bx],ax      ; zero pixels in video buffer
  16470.  
  16471.                  not     ax
  16472.                  and     ax,dx
  16473.                  or      es:[bx],ax      ; update pixels in left and middle by
  16474.  
  16475.                  mov     al,ch           ; AL := mask for right-hand byte
  16476.                  not     al
  16477.                  and     es:[bx+2],al    ; mask pixels in right-hand byte in b
  16478.                  and     ch,dl
  16479.                  or      es:[bx+2],ch    ; update pixels in right-hand byte
  16480.  
  16481.                  add     bx,di           ; BX := next row in buffer
  16482.                  xchg    di,VARincr      ; swap buffer increments
  16483.  
  16484.                  pop     cx              ; restore CX
  16485.                  loop    L21
  16486.  
  16487.  
  16488.  Lexit:          pop     ds              ; restore registers and return
  16489.                  pop     di
  16490.                  pop     si
  16491.                  mov     sp,bp
  16492.                  pop     bp
  16493.                  ret
  16494.  
  16495.  _DisplayChar04  ENDP
  16496.  
  16497.  _TEXT           ENDS
  16498.  
  16499.  
  16500.  _DATA           SEGMENT word public 'DATA'
  16501.  
  16502.  PropagatedPixel DB      00000000b       ; 0
  16503.                  DB      01010101b       ; 1
  16504.                  DB      10101010b       ; 2
  16505.                  DB      11111111b       ; 3
  16506.  
  16507.  _DATA           ENDS
  16508.  
  16509.                  END
  16510.  
  16511.  \SAMPCODE\VIDEO\9\9_4.ASM
  16512.  
  16513.                  TITLE   'Listing 9-4'
  16514.                  NAME    DisplayCharHGC
  16515.                  PAGE    55,132
  16516.  
  16517.  ;
  16518.  ; Name:         DisplayCharHGC
  16519.  ;
  16520.  ; Function:     Display a character in Hercules 720x348 monochrome graphics m
  16521.  ;
  16522.  ; Caller:       Microsoft C:
  16523.  ;
  16524.  ;                       void DisplayCharHGC(c,x,y,fgd,bkgd);
  16525.  ;
  16526.  ;                       int c;                  /* character code */
  16527.  ;
  16528.  ;                       int x,y;                /* upper left pixel */
  16529.  ;
  16530.  ;                       int fgd,bkgd;           /* foreground and background
  16531.  ;                                                   pixel values */
  16532.  ;
  16533.  
  16534.  ARGc            EQU     word ptr [bp+4] ; stack frame addressing
  16535.  ARGx            EQU     word ptr [bp+6]
  16536.  ARGy            EQU     word ptr [bp+8]
  16537.  ARGfgd          EQU     byte ptr [bp+10]
  16538.  ARGbkgd         EQU     byte ptr [bp+12]
  16539.  
  16540.  VARmask         EQU              [bp-2]
  16541.  VARtoggle       EQU              [bp-4]
  16542.  VAR9bits        EQU     byte ptr [bp-6]
  16543.  
  16544.  
  16545.  _TEXT           SEGMENT byte public 'CODE'
  16546.                  ASSUME  cs:_TEXT
  16547.  
  16548.                  EXTRN   PixelAddrHGC:near
  16549.  
  16550.                  PUBLIC  _DisplayCharHGC
  16551.  _DisplayCharHGC PROC    near
  16552.  
  16553.                  push    bp              ; preserve caller registers
  16554.                  mov     bp,sp
  16555.                  sub     sp,6            ; stack space for local variables
  16556.                  push    si
  16557.                  push    di
  16558.                  push    ds
  16559.  
  16560.  ; calculate first pixel address
  16561.  
  16562.                  mov     ax,ARGy         ; AX := y
  16563.                  mov     bx,ARGx         ; BX := x
  16564.                  call    PixelAddrHGC    ; ES:BX -> buffer
  16565.                                          ; CL := # bits to shift left
  16566.  
  16567.                  xor     cl,7            ; CL := # bits to rotate right
  16568.  
  16569.  ; set up 8- or 9-bit mask
  16570.  
  16571.                  mov     ax,40h
  16572.                  mov     ds,ax           ; DS := segment of BIOS Video
  16573.                                          ;  Display Data area
  16574.  
  16575.                  mov     ax,0FF00h       ; AX := 8-bit mask
  16576.                  mov     VAR9bits,0      ; zero this flag
  16577.  
  16578.                  cmp     byte ptr ds:[4Ah],90    ; does CRT_COLS = 90?
  16579.                  je      L01             ; jump if characters are 8 pixels wid
  16580.  
  16581.                  mov     ah,7Fh          ; AX := 9-bit mask
  16582.                  cmp     ARGc,0C0h
  16583.                  jb      L01             ; jump if character code ...
  16584.  
  16585.                  cmp     ARGc,0DFh
  16586.                  ja      L01             ; ... outside of range 0C0-0DFh
  16587.  
  16588.                  inc     VAR9bits        ; set flag to extend to 9 bits
  16589.  
  16590.  L01:            ror     ax,cl           ; AX := bit mask in proper position
  16591.                  mov     VARmask,ax
  16592.  
  16593.  ; set up foreground pixel toggle mask
  16594.  
  16595.                  mov     ah,ARGfgd       ; AH := 0 or 1 (foreground pixel valu
  16596.                  ror     ah,1            ; high-order bit of AH := 0 or 1
  16597.                  cwd                     ; propagate high-order bit through DX
  16598.                  not     dx              ; DX :=     0 if foreground = 1
  16599.                                          ;    or FFFFh if foreground = 0
  16600.                  mov     ax,VARmask
  16601.                  not     ax
  16602.                  and     dx,ax           ; zero unused bits of toggle mask in
  16603.                  mov     VARtoggle,dx
  16604.  
  16605.  ; set up character definition table addressing
  16606.  
  16607.                  push    bx              ; preserve buffer address
  16608.  
  16609.                  mov     ch,ds:[85h]     ; CH := POINTS (pixel rows in charact
  16610.  
  16611.                  xor     ax,ax
  16612.                  mov     ds,ax           ; DS := absolute zero
  16613.  
  16614.                  mov     ax,ARGc         ; AL := character code
  16615.                  cmp     al,80h
  16616.                  jae     L02
  16617.  
  16618.                  mov     bx,43h*4        ; DS:BX -> int 43h vector if char < 8
  16619.                  jmp     short L03
  16620.  
  16621.  L02:            mov     bx,1Fh*4        ; DS:BX -> int 1Fh vector if char >=
  16622.                  sub     al,80h          ; put character code in range of tabl
  16623.  
  16624.  L03:            lds     si,ds:[bx]      ; DS:SI -> start of character table
  16625.                  mul     ch              ; AX := offset into char def table
  16626.                                          ;  (POINTS * char code)
  16627.                  add     si,ax           ; SI := addr of char def
  16628.  
  16629.                  pop     bx              ; restore buffer address
  16630.  
  16631.  ; mask and set pixels in the video buffer
  16632.  
  16633.  L20:            mov     ax,VARmask
  16634.                  and     es:[bx],ax      ; mask character pixels in buffer
  16635.  
  16636.                  xor     ah,ah
  16637.                  lodsb                   ; AX := bit pattern for next pixel ro
  16638.                  cmp     VAR9bits,0
  16639.                  je      L21             ; jump if character is 8 pixels wide
  16640.  
  16641.                  ror     ax,1            ; copy lo-order bit of AX into ...
  16642.                  rcl     al,1            ;  hi-order bit
  16643.  
  16644.  L21:            ror     ax,cl           ; rotate pixels into position
  16645.                  xor     ax,VARtoggle    ; toggle pixels if foreground = 0
  16646.                  or      es:[bx],ax      ; store pixels in buffer
  16647.  
  16648.                  add     bx,2000h        ; increment to next portion of interl
  16649.                  jns     L22
  16650.  
  16651.                  add     bx,90-8000h     ; increment to first portion of inter
  16652.  
  16653.  L22:            dec     ch
  16654.                  jnz     L20
  16655.  
  16656.  
  16657.  Lexit:          pop     ds              ; restore registers and return
  16658.                  pop     di
  16659.                  pop     si
  16660.                  mov     sp,bp
  16661.                  pop     bp
  16662.                  ret
  16663.  
  16664.  _DisplayCharHGC ENDP
  16665.  
  16666.  _TEXT           ENDS
  16667.  
  16668.                  END
  16669.  
  16670.  \SAMPCODE\VIDEO\9\9_5.ASM
  16671.  
  16672.                  TITLE   'Listing 9-5'
  16673.                  NAME    DisplayChar13
  16674.                  PAGE    55,132
  16675.  
  16676.  ;
  16677.  ; Name:         DisplayChar13
  16678.  ;
  16679.  ; Function:     Display a character in MCGA/VGA 320x200 256-color mode
  16680.  ;
  16681.  ; Caller:       Microsoft C:
  16682.  ;
  16683.  ;                       void DisplayChar13(c,x,y,fgd,bkgd);
  16684.  ;
  16685.  ;                       int c;                  /* character code */
  16686.  ;
  16687.  ;                       int x,y;                /* upper left pixel */
  16688.  ;
  16689.  ;                       int fgd,bkgd;           /* foreground and background
  16690.  ;                                                   pixel values */
  16691.  ;
  16692.  
  16693.  ARGc            EQU     word ptr [bp+4] ; stack frame addressing
  16694.  ARGx            EQU     word ptr [bp+6]
  16695.  ARGy            EQU     word ptr [bp+8]
  16696.  ARGfgd          EQU     byte ptr [bp+10]
  16697.  ARGbkgd         EQU     byte ptr [bp+12]
  16698.  
  16699.  BytesPerLine    EQU     320
  16700.  
  16701.  _TEXT           SEGMENT byte public 'CODE'
  16702.                  ASSUME  cs:_TEXT
  16703.  
  16704.                  EXTRN   PixelAddr13:near
  16705.  
  16706.                  PUBLIC  _DisplayChar13
  16707.  _DisplayChar13  PROC    near
  16708.  
  16709.                  push    bp              ; preserve caller registers
  16710.                  mov     bp,sp
  16711.                  push    si
  16712.                  push    di
  16713.                  push    ds
  16714.  
  16715.  ; calculate first pixel address
  16716.  
  16717.                  mov     ax,ARGy         ; AX := y
  16718.                  mov     bx,ARGx         ; BX := x
  16719.                  call    PixelAddr13     ; ES:BX -> buffer
  16720.                  mov     di,bx           ; ES:DI -> buffer
  16721.  
  16722.  ; set up character definition table addressing
  16723.  
  16724.                  mov     ax,40h
  16725.                  mov     ds,ax           ; DS := segment of BIOS Video
  16726.                                          ;  Display Data area
  16727.                  mov     cx,ds:[85h]     ; CX := POINTS (pixel rows in charact
  16728.  
  16729.                  xor     ax,ax
  16730.                  mov     ds,ax           ; DS := absolute zero
  16731.  
  16732.                  mov     ax,ARGc         ; AL := character code
  16733.                  mov     bx,43h*4        ; DS:BX -> int 43h vector if char < 8
  16734.                  lds     si,ds:[bx]      ; DS:SI -> start of character table
  16735.                  mul     cl              ; AX := offset into char def table
  16736.                                          ;  (POINTS * char code)
  16737.                  add     si,ax           ; SI := addr of char def
  16738.  
  16739.  ; store the character in the video buffer
  16740.  
  16741.                  mov     bl,ARGfgd       ; BL := foreground pixel value
  16742.                  mov     bh,ARGbkgd      ; BH := background pixel value
  16743.  
  16744.  L10:            push    cx              ; preserve CX across loop
  16745.                  mov     cx,8            ; CX := character width in pixels
  16746.                  lodsb
  16747.                  mov     ah,al           ; AH := bit pattern for next pixel ro
  16748.  
  16749.  L11:            mov     al,bl           ; AL := foreground pixel value
  16750.                  shl     ah,1            ; carry flag := high-order bit
  16751.                  jc      L12             ; jump if bit pattern specifies a
  16752.                                          ;  foreground pixel (bit = 1)
  16753.                  mov     al,bh           ; AL := background pixel value
  16754.  
  16755.  L12:            stosb                   ; update one pixel in the buffer
  16756.                  loop    L11
  16757.  
  16758.                  add     di,BytesPerLine-8 ; increment buffer address to next
  16759.                                            ;  row of pixels
  16760.                  pop     cx
  16761.                  loop    L10             ; loop down character
  16762.  
  16763.                  pop     ds              ; restore registers and return
  16764.                  pop     di
  16765.                  pop     si
  16766.                  mov     sp,bp
  16767.                  pop     bp
  16768.                  ret
  16769.  
  16770.  _DisplayChar13  ENDP
  16771.  
  16772.  _TEXT           ENDS
  16773.  
  16774.                  END
  16775.  
  16776.  \SAMPCODE\VIDEO\9\9_6.ASM
  16777.  
  16778.                  TITLE   'Listing 9-6'
  16779.                  NAME    DisplayChar10
  16780.                  PAGE    55,132
  16781.  
  16782.  ;
  16783.  ; Name:         DisplayChar10
  16784.  ;
  16785.  ; Function:     Display a character in native EGA and VGA graphics modes
  16786.  ;
  16787.  ; Caller:       Microsoft C:
  16788.  ;
  16789.  ;                       void DisplayChar10(c,x,y,fgd,bkgd);
  16790.  ;
  16791.  ;                       int c;                  /* character code */
  16792.  ;
  16793.  ;                       int x,y;                /* upper left pixel */
  16794.  ;
  16795.  ;                       int fgd,bkgd;           /* foreground and background
  16796.  ;                                                   pixel values */
  16797.  ;
  16798.  
  16799.  ARGc            EQU     word ptr [bp+4] ; stack frame addressing
  16800.  ARGx            EQU     word ptr [bp+6]
  16801.  ARGy            EQU     word ptr [bp+8]
  16802.  ARGfgd          EQU     byte ptr [bp+10]
  16803.  ARGbkgd         EQU     byte ptr [bp+12]
  16804.  
  16805.  VARshift        EQU              [bp-2]
  16806.  
  16807.  BytesPerLine    =       80              ; (must 40 in 320x200 16-color mode)
  16808.  RMWbits         =       18h             ; Read-Modify-Write bits
  16809.  
  16810.  _TEXT           SEGMENT byte public 'CODE'
  16811.                  ASSUME  cs:_TEXT
  16812.  
  16813.                  EXTRN   PixelAddr10:near
  16814.  
  16815.                  PUBLIC  _DisplayChar10
  16816.  _DisplayChar10  PROC    near
  16817.  
  16818.                  push    bp              ; preserve caller registers
  16819.                  mov     bp,sp
  16820.                  sub     sp,2            ; stack space for local variable
  16821.                  push    si
  16822.                  push    di
  16823.                  push    ds
  16824.  
  16825.  ; calculate first pixel address
  16826.  
  16827.                  mov     ax,ARGy         ; AX := y
  16828.                  mov     bx,ARGx         ; BX := x
  16829.                  call    PixelAddr10     ; ES:BX -> buffer
  16830.                                          ; CL := # bits to shift left to mask
  16831.                                          ;  pixel
  16832.                  inc     cx
  16833.                  and     cl,7            ; CL := # bits to shift to mask char
  16834.  
  16835.                  mov     ch,0FFh
  16836.                  shl     ch,cl           ; CH := bit mask for right side of ch
  16837.                  mov     VARshift,cx
  16838.  
  16839.                  push    es              ; preserve video buffer segment
  16840.                  mov     si,bx           ; SI := video buffer offset
  16841.  
  16842.  ; set up character definition table addressing
  16843.  
  16844.                  mov     ax,40h
  16845.                  mov     ds,ax           ; DS := segment of BIOS Video
  16846.                                          ;  Display Data area
  16847.                  mov     cx,ds:[85h]     ; CX := POINTS (pixel rows in charact
  16848.  
  16849.                  xor     ax,ax
  16850.                  mov     ds,ax           ; DS := absolute zero
  16851.  
  16852.                  mov     ax,ARGc         ; AL := character code
  16853.                  mov     bx,43h*4        ; DS:BX -> int 43h vector
  16854.                  les     di,ds:[bx]      ; ES:DI -> start of character table
  16855.                  mul     cl              ; AX := offset into char def table
  16856.                                          ;  (POINTS * char code)
  16857.                  add     di,ax           ; DI := addr of char def
  16858.  
  16859.                  pop     ds              ; DS:SI -> video buffer
  16860.  
  16861.  ; set up Graphics Controller registers
  16862.  
  16863.                  mov     dx,3CEh         ; Graphics Controller address reg por
  16864.  
  16865.                  mov     ax,0A05h        ; AL :=  Mode register number
  16866.                                          ; AH :=  Write Mode 2 (bits 0-1)
  16867.                                          ;        Read Mode 1 (bit 4)
  16868.                  out     dx,ax
  16869.  
  16870.                  mov     ah,RMWbits      ; AH := Read-Modify-Write bits
  16871.                  mov     al,3            ; AL := Data Rotate/Function Select r
  16872.                  out     dx,ax
  16873.  
  16874.                  mov     ax,0007         ; AH := Color Don't Care bits
  16875.                                          ; AL := Color Don't Care reg number
  16876.                  out     dx,ax           ; "don't care" for all bit planes
  16877.  
  16878.  ; select output routine depending on whether character is byte-aligned
  16879.  
  16880.                  mov     bl,ARGfgd       ; BL := foreground pixel value
  16881.                  mov     bh,ARGbkgd      ; BH := background pixel value
  16882.  
  16883.                  cmp     byte ptr VARshift,0   ; test # bits to shift
  16884.                  jne     L20             ; jump if character is not byte-align
  16885.  
  16886.  
  16887.  ; routine for byte-aligned characters
  16888.  
  16889.                  mov     al,8            ; AL := Bit Mask register number
  16890.  
  16891.  L10:            mov     ah,es:[di]      ; AH := pattern for next row of pixel
  16892.                  out     dx,ax           ; update Bit Mask register
  16893.                  and     [si],bl         ; update foreground pixels
  16894.  
  16895.                  not     ah
  16896.                  out     dx,ax
  16897.                  and     [si],bh         ; update background pixels
  16898.  
  16899.                  inc     di              ; ES:DI -> next byte in char def tabl
  16900.                  add     si,BytesPerLine ; increment to next line in video buf
  16901.                  loop    L10
  16902.                  jmp     short Lexit
  16903.  
  16904.  
  16905.  ; routine for non-byte-aligned characters
  16906.  
  16907.  L20:            push    cx              ; preserve loop counter
  16908.                  mov     cx,VARshift     ; CH := mask for left side of charact
  16909.                                          ; CL := # bits to shift left
  16910.  ; left side of character
  16911.  
  16912.                  mov     al,es:[di]      ; AL := bits for next row of pixels
  16913.                  xor     ah,ah
  16914.                  shl     ax,cl           ; AH := bits for left side of char
  16915.                                          ; AL := bits for right side of char
  16916.                  push    ax              ; save bits for right side on stack
  16917.                  mov     al,8            ; AL := Bit Mask Register number
  16918.                  out     dx,ax           ; set bit mask for foreground pixels
  16919.  
  16920.                  and     [si],bl         ; update foreground pixels
  16921.  
  16922.                  not     ch              ; CH := mask for left side of char
  16923.                  xor     ah,ch           ; AH := bits for background pixels
  16924.                  out     dx,ax           ; set bit mask
  16925.  
  16926.                  and     [si],bh         ; update background pixels
  16927.  
  16928.  ; right side of character
  16929.  
  16930.                  pop     ax
  16931.                  mov     ah,al           ; AH := bits for right side of char
  16932.                  mov     al,8
  16933.                  out     dx,ax           ; set bit mask
  16934.  
  16935.                  inc     si              ; DS:SI -> right side of char in buff
  16936.  
  16937.                  and     [si],bl         ; update foreground pixels
  16938.  
  16939.                  not     ch              ; CH := mask for right side of char
  16940.                  xor     ah,ch           ; AH := bits for background pixels
  16941.                  out     dx,ax           ; set bit mask
  16942.  
  16943.                  and     [si],bh         ; update background pixels
  16944.  
  16945.  ; increment to next row of pixels in character
  16946.  
  16947.                  inc     di              ; ES:DI -> next byte in char def tabl
  16948.                  dec     si
  16949.                  add     si,BytesPerLine ; DS:SI -> next line in video buffer
  16950.  
  16951.                  pop     cx
  16952.                  loop    L20
  16953.  
  16954.  
  16955.  ; restore default Graphics Controller registers
  16956.  
  16957.  Lexit:          mov     ax,0FF08h       ; default Bit Mask
  16958.                  out     dx,ax
  16959.  
  16960.                  mov     ax,0005         ; default Mode register
  16961.                  out     dx,ax
  16962.  
  16963.                  mov     ax,0003         ; default Data Rotate/Function Select
  16964.                  out     dx,ax
  16965.  
  16966.                  mov     ax,0F07h        ; default Color Don't Care
  16967.                  out     dx,ax
  16968.  
  16969.                  pop     ds              ; restore caller registers and return
  16970.                  pop     di
  16971.                  pop     si
  16972.                  mov     sp,bp
  16973.                  pop     bp
  16974.                  ret
  16975.  
  16976.  _DisplayChar10  ENDP
  16977.  
  16978.  _TEXT           ENDS
  16979.  
  16980.                  END
  16981.  
  16982.  \SAMPCODE\VIDEO\9\9_7.ASM
  16983.  
  16984.                  TITLE   'Listing 9-7'
  16985.                  NAME    DisplayCharInC
  16986.                  PAGE    55,132
  16987.  
  16988.  ;
  16989.  ; Name:         DisplayCharInC
  16990.  ;
  16991.  ; Function:     Display a character in InColor 720x348 16-color mode
  16992.  ;
  16993.  ; Caller:       Microsoft C:
  16994.  ;
  16995.  ;                       void DisplayCharInC(c,x,y,fgd,bkgd);
  16996.  ;
  16997.  ;                       int c;                  /* character code */
  16998.  ;
  16999.  ;                       int x,y;                /* upper left pixel */
  17000.  ;
  17001.  ;                       int fgd,bkgd;           /* foreground and background
  17002.  ;                                                   pixel values */
  17003.  ;
  17004.  
  17005.  ARGc            EQU     word ptr [bp+4] ; stack frame addressing
  17006.  ARGx            EQU     word ptr [bp+6]
  17007.  ARGy            EQU     word ptr [bp+8]
  17008.  ARGfgd          EQU     byte ptr [bp+10]
  17009.  ARGbkgd         EQU     byte ptr [bp+12]
  17010.  
  17011.  VARmask         EQU     word ptr [bp-2]
  17012.  VAR9bits        EQU     byte ptr [bp-4]
  17013.  
  17014.  _TEXT           SEGMENT byte public 'CODE'
  17015.                  ASSUME  cs:_TEXT
  17016.  
  17017.                  EXTRN   PixelAddrHGC:near
  17018.  
  17019.                  PUBLIC  _DisplayCharInC
  17020.  _DisplayCharInC PROC    near
  17021.  
  17022.                  push    bp              ; preserve caller registers
  17023.                  mov     bp,sp
  17024.                  sub     sp,4            ; stack space for local variables
  17025.                  push    si
  17026.                  push    di
  17027.                  push    ds
  17028.  
  17029.  ; calculate first pixel address
  17030.  
  17031.                  mov     ax,ARGy         ; AX := y
  17032.                  mov     bx,ARGx         ; BX := x
  17033.                  call    PixelAddrHGC    ; ES:BX -> buffer
  17034.                                          ; CL := # bits to shift left to mask
  17035.                                          ;  pixel
  17036.                  xor     cl,7            ; CL := # bits to rotate right
  17037.  
  17038.                  push    es              ; preserve video buffer segment
  17039.                  mov     si,bx           ; DI := video buffer offset
  17040.  
  17041.  ; set up flag for 8- or 9-bit characters
  17042.  
  17043.                  mov     ax,40h
  17044.                  mov     ds,ax           ; DS := segment of BIOS Video
  17045.                                          ;  Display Data area
  17046.  
  17047.                  mov     ax,0FF00h       ; AX := 8-bit mask
  17048.                  mov     VAR9bits,0      ; zero this flag
  17049.  
  17050.                  cmp     byte ptr ds:[4Ah],90    ; does CRT_COLS = 90?
  17051.                  je      L01             ; jump if characters are 8 pixels wid
  17052.  
  17053.                  mov     ah,7Fh          ; AX := 9-bit mask
  17054.                  cmp     ARGc,0C0h
  17055.                  jb      L01             ; jump if character code ...
  17056.  
  17057.                  cmp     ARGc,0DFh
  17058.                  ja      L01             ; ... outside of range 0C0-0DFh
  17059.  
  17060.                  inc     VAR9bits        ; set flag to extend to 9 bits
  17061.  
  17062.  L01:            ror     ax,cl           ; AX := bit mask in proper position
  17063.                  mov     VARmask,ax
  17064.  
  17065.  ; set up character definition table addressing
  17066.  
  17067.                  mov     ax,40h
  17068.                  mov     ds,ax           ; DS := segment of BIOS Video
  17069.                                          ;  Display Data area
  17070.                  mov     ch,ds:[85h]     ; CH := POINTS (pixel rows in charact
  17071.  
  17072.                  xor     ax,ax
  17073.                  mov     ds,ax           ; DS := absolute zero
  17074.  
  17075.                  mov     ax,ARGc         ; AL := character code
  17076.                  cmp     al,80h
  17077.                  jae     L02
  17078.  
  17079.                  mov     bx,43h*4        ; DS:BX -> int 43h vector if char < 8
  17080.                  jmp     short L03
  17081.  
  17082.  L02:            mov     bx,1Fh*4        ; DS:BX -> int 1Fh vector if char >=
  17083.                  sub     al,80h          ; put character code in range of tabl
  17084.  
  17085.  L03:            les     di,ds:[bx]      ; ES:DI -> start of character table
  17086.                  mul     ch              ; AX := offset into char def table
  17087.                                          ;  (POINTS * char code)
  17088.                  add     di,ax           ; DI := addr of char def
  17089.  
  17090.                  pop     ds              ; DS:SI -> video buffer
  17091.  
  17092.  ; set up control registers
  17093.  
  17094.                  mov     dx,3B4h         ; control register I/O port
  17095.  
  17096.                  push    cx              ; preserve CX
  17097.                  mov     ah,ARGbkgd      ; AH := background pixel value
  17098.                  mov     cl,4
  17099.                  shl     ah,cl           ; AH bits 4-7 := background pixel val
  17100.                  or      ah,ARGfgd       ; AH bits 0-3 := foreground pixel val
  17101.                  pop     cx              ; restore CX
  17102.  
  17103.                  mov     al,1Ah          ; AL := Read/Write Color reg number
  17104.                  out     dx,ax           ; set Read/Write Color value
  17105.  
  17106.  ; mask and set pixels in the video buffer
  17107.  
  17108.  L20:            xor     bh,bh
  17109.                  mov     bl,es:[di]      ; BX := bit pattern for next pixel ro
  17110.                  inc     di              ; increment pointer to char def table
  17111.                  cmp     VAR9bits,0
  17112.  
  17113.                  je      L21             ; jump if character is 8 pixels wide
  17114.  
  17115.                  ror     bx,1            ; copy lo-order bit of BX into ...
  17116.                  rcl     bl,1            ;  hi-order bit
  17117.  
  17118.  L21:            ror     bx,cl           ; rotate pixels into position
  17119.  
  17120.                  mov     ax,5F19h        ; AH bit 6 := 1 (mask polarity)
  17121.                                          ; AH bits 4-5 := 01b (write mode 1)
  17122.                                          ; AH bits 0-3 := 1111b (don't care bi
  17123.                                          ; AL := 19h (Read/Write Control reg)
  17124.                  out     dx,ax           ; set up Read/Write control reg
  17125.  
  17126.                  or      [si],bl         ; update foreground pixels
  17127.                  or      [si+1],bh
  17128.  
  17129.                  mov     ah,6Fh          ; set up write mode 2
  17130.                  out     dx,ax
  17131.  
  17132.                  or      bx,VARmask      ; BX := background pixel bit pattern
  17133.                  or      [si],bl         ; update background pixels
  17134.                  or      [si+1],bh
  17135.  
  17136.                  add     si,2000h        ; increment to next portion of interl
  17137.                  jns     L22
  17138.  
  17139.                  add     si,90-8000h     ; increment to first portion of inter
  17140.  
  17141.  L22:            dec     ch
  17142.                  jnz     L20
  17143.  
  17144.  ; restore default InColor register values
  17145.  
  17146.                  mov     ax,4019h        ; default Read/Write Control reg
  17147.                  out     dx,ax
  17148.  
  17149.                  mov     ax,071Ah        ; default Read/Write Color reg
  17150.                  out     dx,ax
  17151.  
  17152.                  pop     ds              ; restore registers and return
  17153.                  pop     di
  17154.                  pop     si
  17155.                  mov     sp,bp
  17156.                  pop     bp
  17157.                  ret
  17158.  
  17159.  _DisplayCharInC ENDP
  17160.  
  17161.  _TEXT           ENDS
  17162.  
  17163.                  END
  17164.  
  17165.  \SAMPCODE\VIDEO\A
  17166.  \SAMPCODE\VIDEO\A\A_1.ASM
  17167.  
  17168.                  TITLE   'Listing A-1'
  17169.                  NAME    EstablishPSA
  17170.                  PAGE    55,132
  17171.  
  17172.  ;
  17173.  ; Name:         EstablishPSA
  17174.  ;
  17175.  ; Function:     Establish a Parameter Save Area for the EGA or VGA video BIOS
  17176.  ;               This save area will reflect the current values of the Attribu
  17177.  ;               Controller's Palette and Overscan registers.
  17178.  ;
  17179.  ; Caller:       Microsoft C:
  17180.  ;
  17181.  ;                       void EstablishPSA();
  17182.  ;
  17183.  
  17184.  SAVE_PTR        EQU     0A8h
  17185.  
  17186.  DGROUP          GROUP   _DATA
  17187.  
  17188.  _TEXT           SEGMENT byte public 'CODE'
  17189.                  ASSUME  cs:_TEXT,ds:DGROUP,es:DGROUP
  17190.  
  17191.                  PUBLIC  _EstablishPSA
  17192.  _EstablishPSA   PROC    near
  17193.  
  17194.                  push    bp
  17195.                  mov     bp,sp
  17196.                  push    si
  17197.                  push    di
  17198.  
  17199.  ; preserve previous SAVE_PTR
  17200.  
  17201.                  push    ds
  17202.                  pop     es              ; ES -> DGROUP
  17203.                  mov     di,offset DGROUP:Old_SAVE_PTR
  17204.  
  17205.                  mov     ax,40h
  17206.                  mov     ds,ax           ; DS -> video BIOS data area
  17207.                  mov     si,SAVE_PTR     ; DS:SI -> SAVE_PTR
  17208.  
  17209.                  mov     cx,4
  17210.                  rep     movsb
  17211.  
  17212.  ; copy SAVE POINTER table to RAM
  17213.  
  17214.                  lds     si,es:Old_SAVE_PTR      ; DS:SI -> SAVE POINTER table
  17215.                  mov     di,offset DGROUP:SP_TABLE1
  17216.                  mov     cx,7*4          ; number of bytes to move
  17217.                  rep     movsb
  17218.  
  17219.  ; update SAVE_PTR with the address of the new SAVE POINTER table
  17220.  
  17221.                  mov     ds,ax           ; DS -> video BIOS data area
  17222.                  mov     si,SAVE_PTR
  17223.                  mov     word ptr [si],offset DGROUP:SP_TABLE1
  17224.                  mov     [si+2],es
  17225.  
  17226.  ; update SAVE POINTER table with address of Parameter Save Area
  17227.  
  17228.                  push    es
  17229.                  pop     ds      ; DS -> DGROUP
  17230.  
  17231.                  mov     word ptr SP_TABLE1[4],offset DGROUP:PSA
  17232.                  mov     word ptr SP_TABLE1[6],ds
  17233.  
  17234.  ; restore registers and exit
  17235.  
  17236.                  pop     di
  17237.                  pop     si
  17238.                  mov     sp,bp
  17239.                  pop     bp
  17240.                  ret
  17241.  
  17242.  _EstablishPSA   ENDP
  17243.  
  17244.  _TEXT           ENDS
  17245.  
  17246.  
  17247.  _DATA           SEGMENT word public 'DATA'
  17248.  
  17249.  Old_SAVE_PTR    DD      ?               ; previous value of SAVE_PTR
  17250.  
  17251.  SP_TABLE1       DD      7 dup(?)        ; RAM copy of SAVE POINTER table
  17252.  
  17253.  PSA             DB      256 dup(0)      ; Parameter Save Area
  17254.  
  17255.  _DATA           ENDS
  17256.  
  17257.                  END
  17258.  
  17259.  \SAMPCODE\VIDEO\A\A_2.ASM
  17260.  
  17261.                  TITLE   'Listing A-2'
  17262.                  NAME    EstablishUPP
  17263.                  PAGE    55,132
  17264.  
  17265.  ;
  17266.  ; Name:         EstablishUPP
  17267.  ;
  17268.  ; Function:     Establish a User Palette Profile Save Area for the VGA video
  17269.  ;               This save area overrides the usual default palette values for
  17270.  ;               specified list of video modes.
  17271.  ;
  17272.  ; Caller:       Microsoft C:
  17273.  ;
  17274.  ;                       void EstablishUPP();
  17275.  ;
  17276.  
  17277.  SAVE_PTR        EQU     0A8h
  17278.  
  17279.  DGROUP          GROUP   _DATA
  17280.  
  17281.  _TEXT           SEGMENT byte public 'CODE'
  17282.                  ASSUME  cs:_TEXT,ds:DGROUP,es:DGROUP
  17283.  
  17284.                  PUBLIC  _EstablishUPP
  17285.  _EstablishUPP   PROC    near
  17286.  
  17287.                  push    bp
  17288.                  mov     bp,sp
  17289.                  push    si
  17290.                  push    di
  17291.  
  17292.  ; preserve previous SAVE_PTR
  17293.  
  17294.                  push    ds
  17295.                  pop     es              ; ES -> DGROUP
  17296.                  mov     di,offset DGROUP:Old_SAVE_PTR
  17297.  
  17298.                  mov     ax,40h
  17299.                  mov     ds,ax           ; DS -> video BIOS data area
  17300.                  mov     si,SAVE_PTR     ; DS:SI -> SAVE_PTR
  17301.  
  17302.                  mov     cx,4
  17303.                  rep     movsb
  17304.  
  17305.  ; copy SAVE POINTER table to RAM
  17306.  
  17307.                  lds     si,es:Old_SAVE_PTR      ; DS:SI -> SAVE POINTER table
  17308.                  mov     di,offset DGROUP:SP_TABLE1
  17309.                  mov     cx,7*4          ; number of bytes to move
  17310.                  rep     movsb
  17311.  
  17312.  ; update SAVE_PTR with the address of the new SAVE POINTER table
  17313.  
  17314.                  mov     ds,ax           ; DS -> video BIOS data area
  17315.                  mov     si,SAVE_PTR
  17316.                  mov     word ptr [si],offset DGROUP:SP_TABLE1
  17317.                  mov     [si+2],es
  17318.  
  17319.  ; copy SECONDARY SAVE POINTER table to RAM
  17320.  
  17321.                  lds     si,es:SP_TABLE1[16]     ; DS:SI -> SEC SAVE POINTER t
  17322.                  mov     di,offset DGROUP:SP_TABLE2
  17323.                  mov     cx,[si]
  17324.                  rep     movsb
  17325.  
  17326.  ; update new SAVE POINTER table with address of new SECONDARY SAVE POINTER ta
  17327.  
  17328.                  push    es
  17329.                  pop     ds      ; DS -> DGROUP
  17330.  
  17331.                  mov     word ptr SP_TABLE1[16],offset DGROUP:SP_TABLE2
  17332.                  mov     word ptr SP_TABLE1[18],ds
  17333.  
  17334.  ; update SECONDARY SAVE POINTER with address of User Palette Profile
  17335.  
  17336.                  mov     word ptr SP_TABLE2[10],offset DGROUP:UPP
  17337.                  mov     word ptr SP_TABLE2[12],ds
  17338.  
  17339.  ; restore registers and exit
  17340.  
  17341.                  pop     di
  17342.                  pop     si
  17343.                  mov     sp,bp
  17344.                  pop     bp
  17345.                  ret
  17346.  
  17347.  _EstablishUPP   ENDP
  17348.  
  17349.  _TEXT           ENDS
  17350.  
  17351.  
  17352.  _DATA           SEGMENT word public 'DATA'
  17353.  
  17354.  Old_SAVE_PTR    DD      ?               ; previous value of SAVE_PTR
  17355.  
  17356.  SP_TABLE1       DD      7 dup(?)        ; copy of SAVE POINTER table
  17357.  
  17358.  SP_TABLE2       DW      ?               ; copy of SECONDARY SAVE POINTER tabl
  17359.                  DD      6 dup(?)
  17360.  
  17361.  UPP             DB      0               ; underlining flag
  17362.                  DB      0               ; (reserved)
  17363.                  DW      0               ; (reserved)
  17364.                  DW      17              ; # of palette & overscan registers
  17365.                  DW      0               ; first register specified in table
  17366.                  DW      DGROUP:PalTable ; pointer to palette table
  17367.                  DW      seg DGROUP
  17368.                  DW      0               ; number of video DAC color regs
  17369.                  DW      0               ; first video DAC register
  17370.                  DD      0               ; pointer to video DAC color table
  17371.                  DB      3,0FFh          ; list of applicable video modes
  17372.  
  17373.  PalTable        DB      30h,31h,32h,33h,34h,35h,36h,37h ; a custom palette
  17374.                  DB      00h,01h,02h,03h,04h,05h,14h,07h
  17375.                  DB      01h                             ; overscan reg
  17376.  
  17377.  _DATA           ENDS
  17378.  
  17379.                  END
  17380.  
  17381.  \SAMPCODE\VIDEO\B
  17382.  \SAMPCODE\VIDEO\B\B_1.ASM
  17383.  
  17384.                  TITLE   'Listing B-1'
  17385.                  NAME    ScreenDumpCGA
  17386.                  PAGE    55,132
  17387.  
  17388.  ;
  17389.  ; Name:         ScreenDumpCGA
  17390.  ;
  17391.  ; Function:     Screen Dump for CGA 640x200 2-color and 320x200 4-color modes
  17392.  ;
  17393.  ; Caller:       (undefined)
  17394.  ;
  17395.  ; Notes:        The main procedure of this program, ScreenDumpCGA, may be
  17396.  ;               called from an application program or as part of a TSR
  17397.  ;               (Terminate-but-Stay Resident) handler for interrupt 5.
  17398.  ;
  17399.  
  17400.  STDPRN          =       4               ; MS-DOS standard printer handle
  17401.  
  17402.  
  17403.  DGROUP          GROUP   _DATA
  17404.  
  17405.  _TEXT           SEGMENT byte public 'CODE'
  17406.                  ASSUME  cs:_TEXT,ds:DGROUP
  17407.  
  17408.  ;
  17409.  ; PrintLine
  17410.  ;
  17411.  ;       Writes one line of characters to the standard printer device.  Ignore
  17412.  ;       errors.
  17413.  ;
  17414.  
  17415.  PrintLine       PROC    near            ; Caller:       DS:DX -> data
  17416.                                          ;               CX = # of bytes
  17417.                  mov     bx,STDPRN
  17418.                  mov     ah,40h          ; INT 21h function 40h:  Write
  17419.                  int     21h
  17420.                  ret
  17421.  
  17422.  PrintLine       ENDP
  17423.  
  17424.  ;
  17425.  ; PrinterGraphics
  17426.  ;
  17427.  ;       Puts the printer in its "graphics mode."  This routine must be
  17428.  ;       customized for different printers.
  17429.  ;
  17430.  
  17431.  PrinterGraphics PROC    near            ; Configures Epson MX-80 printer
  17432.                                          ;  for 480 dots/line
  17433.  
  17434.                  mov     dx,offset DGROUP:EpsonGraphics
  17435.                  mov     cx,3
  17436.                  call    PrintLine
  17437.                  ret
  17438.  
  17439.  PrinterGraphics ENDP
  17440.  
  17441.  ;
  17442.  ; PrinterDefault
  17443.  ;
  17444.  ;       Puts the printer in its default (non-graphics) mode.  Again, this
  17445.  ;       routine must be customized for different printers.
  17446.  ;
  17447.  
  17448.  PrinterDefault  PROC    near            ; Configures Epson MX-80 for default
  17449.                                          ;  alphanumeric output
  17450.  
  17451.                  mov     dx,offset DGROUP:EpsonReset
  17452.                  mov     cx,2
  17453.                  call    PrintLine
  17454.                  ret
  17455.  
  17456.  PrinterDefault  ENDP
  17457.  
  17458.  ;
  17459.  ; ChopZeroes
  17460.  ;
  17461.  ;       Chops trailing zeros from the printer output buffer.
  17462.  ;
  17463.  
  17464.  ChopZeroes      PROC    near            ; Caller:       ES:DI -> buffer
  17465.                                          ;               CX = buffer length
  17466.                                          ; Returns:      CX = adjusted length
  17467.  
  17468.                  jcxz    L01             ; exit if buffer is empty
  17469.  
  17470.                  add     di,cx
  17471.                  dec     di              ; ES:DI -> last byte in buffer
  17472.  
  17473.                  xor     al,al           ; AL := 0 (byte to scan for)
  17474.  
  17475.                  std                     ; scan backwards
  17476.                  repe    scasb
  17477.                  cld                     ; restore direction flag
  17478.                  je      L01             ; jump if buffer filled with zeroes
  17479.  
  17480.                  inc     cx              ; adjust length past last nonzero byt
  17481.  
  17482.  L01:            ret
  17483.  
  17484.  ChopZeroes      ENDP
  17485.  
  17486.  ;
  17487.  ; PrintPixels
  17488.  ;
  17489.  ;       Prints one row of pixels on an Epson MX-80.
  17490.  ;
  17491.  
  17492.  PrintPixels     PROC    near            ; Caller:       DI = offset of buffer
  17493.                                          ;               CX = buffer length
  17494.  
  17495.                  push    ds
  17496.                  pop     es              ; ES := DS
  17497.  
  17498.                  push    di              ; preserve buffer offset
  17499.                  call    ChopZeroes
  17500.                  push    cx              ; preserve length
  17501.  
  17502.                  mov     word ptr DataHeader+2,cx  ; store buffer length
  17503.                                                    ;  in output data header
  17504.                  mov     dx,offset DGROUP:DataHeader
  17505.                  mov     cx,4
  17506.                  call    PrintLine       ; print data header
  17507.  
  17508.                  pop     cx              ; CX := buffer length
  17509.                  pop     dx              ; DX := buffer offset
  17510.                  call    PrintLine       ; print the pixels
  17511.  
  17512.                  mov     dx,offset DGROUP:CRLF
  17513.                  mov     cx,2
  17514.                  call    PrintLine
  17515.  
  17516.                  ret
  17517.  
  17518.  PrintPixels     ENDP
  17519.  
  17520.  ;
  17521.  ; TranslatePixels
  17522.  ;
  17523.  ;       Copies one printable row of pixels from the video buffer to the
  17524.  ;       print buffer.  This routine can be modified at will to change the
  17525.  ;       scaling or orientation of the printed image, to interpolate gray-
  17526.  ;       scale values for color pixels, etc.
  17527.  ;
  17528.  ;       This routine formats the printer buffer for output to an Epson
  17529.  ;       MX-80.  The page is printed sideways, with two horizontal printed pix
  17530.  ;       for each vertical pixel in the video buffer.  Since the CGA screen
  17531.  ;       is 200 pixels high, the printed output is 400 pixels wide.
  17532.  ;
  17533.  
  17534.  TranslatePixels PROC    near            ; Caller:       SI = video buffer off
  17535.                                          ;               ES:DI -> print buffer
  17536.  
  17537.                  push    ds              ; preserve DS
  17538.                  mov     ds,VideoBufSeg  ; DS:SI -> video buffer
  17539.  
  17540.                  add     di,398          ; ES:DI -> 2 bytes before end of buff
  17541.  
  17542.                  mov     cx,200          ; CX := # of vertical pixels
  17543.                  mov     bx,2000h+1      ; BX := 1st video buffer increment
  17544.                  mov     dx,81-2000h     ; DX := 2nd video buffer increment
  17545.  
  17546.                  std                     ; fill the print buffer backwards
  17547.  
  17548.  L11:            lodsb                   ; AL := 8 pixels from video buffer
  17549.                  mov     ah,al           ; AX := 8 doubled pixels
  17550.                  stosw                   ; write them to print buffer
  17551.  
  17552.                  add     si,bx           ; increment to next interleave of
  17553.                  xchg    bx,dx           ;  video buffer
  17554.  
  17555.                  loop    L11
  17556.  
  17557.                  cld                     ; clear direction flag
  17558.                  pop     ds              ; restore DS
  17559.                  ret
  17560.  
  17561.  TranslatePixels ENDP
  17562.  
  17563.  ;
  17564.  ; ScreenDumpCGA
  17565.  ;
  17566.  
  17567.  ScreenDumpCGA   PROC    near            ; Caller:       DS = DGROUP
  17568.  
  17569.                  call    PrinterGraphics ; configure the printer for graphics
  17570.  
  17571.                  push    ds
  17572.                  pop     es              ; DS,ES := DGROUP
  17573.  
  17574.                  xor     si,si           ; SI := offset of start of video buff
  17575.  
  17576.  L21:            push    si
  17577.                  mov     di,offset DGROUP:PrintBuf
  17578.                  call    TranslatePixels ; copy one printable row of pixels
  17579.  
  17580.                  mov     cx,400
  17581.                  mov     di,offset DGROUP:PrintBuf
  17582.                  call    PrintPixels     ; print them
  17583.  
  17584.                  pop     si
  17585.                  inc     si
  17586.                  cmp     si,80           ; loop across all 80 columns in
  17587.                  jb      L21             ;  the video buffer
  17588.  
  17589.                  call    PrinterDefault  ; restore the printer to its default
  17590.                                          ;  state
  17591.                  ret
  17592.  
  17593.  ScreenDumpCGA   ENDP
  17594.  
  17595.  _TEXT           ENDS
  17596.  
  17597.  
  17598.  _DATA           SEGMENT word public 'DATA'
  17599.  
  17600.  PrintBuf        DB      400 dup(?)      ; print output buffer
  17601.  
  17602.  VideoBufSeg     DW      0B800h
  17603.  
  17604.  EpsonGraphics   DB      1Bh,33h,18h
  17605.  EpsonReset      DB      1Bh,40h
  17606.  DataHeader      DB      1Bh,4Bh,00h,00h
  17607.  CRLF            DB      0Dh,0Ah
  17608.  
  17609.  _DATA           ENDS
  17610.  
  17611.                  END
  17612.  
  17613.  \SAMPCODE\VIDEO\B\B_2.ASM
  17614.  
  17615.                  TITLE   'Listing B-2'
  17616.                  NAME    ScreenDumpEGA
  17617.                  PAGE    55,132
  17618.  
  17619.  ;
  17620.  ; Name:         ScreenDumpEGA
  17621.  ;
  17622.  ; Function:     Screen Dump for EGA 640x350 16-color mode
  17623.  ;
  17624.  ; Caller:       (undefined)
  17625.  ;
  17626.  ; Notes:        The main procedure of this program, ScreenDumpEGA, may be
  17627.  ;               called from an application program or as part of a TSR
  17628.  ;               (Terminate-but-Stay Resident) handler for interrupt 5.
  17629.  ;
  17630.  
  17631.  STDPRN          =       4               ; MS-DOS standard printer handle
  17632.  
  17633.  
  17634.  DGROUP          GROUP   _DATA
  17635.  
  17636.  _TEXT           SEGMENT byte public 'CODE'
  17637.                  ASSUME  cs:_TEXT,ds:DGROUP
  17638.  
  17639.  ;
  17640.  ; PrintLine
  17641.  ;
  17642.  ;       Writes one line of characters to the standard printer device.  Ignore
  17643.  ;       errors.
  17644.  ;
  17645.  
  17646.  PrintLine       PROC    near            ; Caller:       DS:DX -> data
  17647.                                          ;               CX = # of bytes
  17648.                  mov     bx,STDPRN
  17649.                  mov     ah,40h          ; INT 21h function 40h:  Write
  17650.                  int     21h
  17651.                  ret
  17652.  
  17653.  PrintLine       ENDP
  17654.  
  17655.  ;
  17656.  ; PrinterGraphics
  17657.  ;
  17658.  ;       Puts the printer in its "graphics mode."  This routine must be
  17659.  ;       customized for different printers.
  17660.  ;
  17661.  
  17662.  PrinterGraphics PROC    near            ; Configures Epson MX-80 printer
  17663.                                          ;  for 480 dots/line
  17664.  
  17665.                  mov     dx,offset DGROUP:EpsonGraphics
  17666.                  mov     cx,3
  17667.                  call    PrintLine
  17668.                  ret
  17669.  
  17670.  PrinterGraphics ENDP
  17671.  
  17672.  ;
  17673.  ; PrinterDefault
  17674.  ;
  17675.  ;       Puts the printer in its default (non-graphics) mode.  Again, this
  17676.  ;       routine must be customized for different printers.
  17677.  ;
  17678.  
  17679.  PrinterDefault  PROC    near            ; Configures Epson MX-80 for default
  17680.                                          ;  alphanumeric output
  17681.  
  17682.                  mov     dx,offset DGROUP:EpsonReset
  17683.                  mov     cx,2
  17684.                  call    PrintLine
  17685.                  ret
  17686.  
  17687.  PrinterDefault  ENDP
  17688.  
  17689.  ;
  17690.  ; ChopZeroes
  17691.  ;
  17692.  ;       Chops trailing zeros from the printer output buffer.
  17693.  ;
  17694.  
  17695.  ChopZeroes      PROC    near            ; Caller:       ES:DI -> buffer
  17696.                                          ;               CX = buffer length
  17697.                                          ; Returns:      CX = adjusted length
  17698.  
  17699.                  jcxz    L01             ; exit if buffer is empty
  17700.  
  17701.                  add     di,cx
  17702.                  dec     di              ; ES:DI -> last byte in buffer
  17703.  
  17704.                  xor     al,al           ; AL := 0 (byte to scan for)
  17705.  
  17706.                  std                     ; scan backwards
  17707.                  repe    scasb
  17708.                  cld                     ; restore direction flag
  17709.                  je      L01             ; jump if buffer filled with zeroes
  17710.  
  17711.                  inc     cx              ; adjust length past last nonzero byt
  17712.  
  17713.  L01:            ret
  17714.  
  17715.  ChopZeroes      ENDP
  17716.  
  17717.  ;
  17718.  ; PrintPixels
  17719.  ;
  17720.  ;       Prints one row of pixels on an Epson MX-80.
  17721.  ;
  17722.  
  17723.  PrintPixels     PROC    near            ; Caller:       DI = offset of buffer
  17724.                                          ;               CX = buffer length
  17725.  
  17726.                  push    ds
  17727.                  pop     es              ; ES := DS
  17728.  
  17729.                  push    di              ; preserve buffer offset
  17730.                  call    ChopZeroes
  17731.                  push    cx              ; preserve length
  17732.  
  17733.                  mov     word ptr DataHeader+2,cx  ; store buffer length
  17734.                                                    ;  in output data header
  17735.                  mov     dx,offset DGROUP:DataHeader
  17736.                  mov     cx,4
  17737.                  call    PrintLine       ; print data header
  17738.  
  17739.                  pop     cx              ; CX := buffer length
  17740.                  pop     dx              ; DX := buffer offset
  17741.                  call    PrintLine       ; print the pixels
  17742.  
  17743.                  mov     dx,offset DGROUP:CRLF
  17744.                  mov     cx,2
  17745.                  call    PrintLine
  17746.  
  17747.                  ret
  17748.  
  17749.  PrintPixels     ENDP
  17750.  
  17751.  ;
  17752.  ; TranslatePixels
  17753.  ;
  17754.  ;       Copies one printable row of pixels from the video buffer to the
  17755.  ;       print buffer.  This routine can be modified at will to change the
  17756.  ;       scaling or orientation of the printed image, to interpolate gray-
  17757.  ;       scale values for color pixels, etc.
  17758.  ;
  17759.  ;       This routine formats the printer buffer for output to an Epson
  17760.  ;       MX-80.  The page is printed sideways, so the printed output is
  17761.  ;       350 pixels wide.
  17762.  ;
  17763.  
  17764.  TranslatePixels PROC    near            ; Caller:       SI = video buffer off
  17765.                                          ;               ES:DI -> print buffer
  17766.  
  17767.                  push    ds              ; preserve DS
  17768.                  mov     ds,VideoBufSeg  ; DS:SI -> video buffer
  17769.  
  17770.                  add     di,349          ; ES:DI -> last byte in print buffer
  17771.  
  17772.                  mov     cx,350          ; CX := # of vertical pixels
  17773.  
  17774.  ; set up the Graphics Controller for read mode 1
  17775.  
  17776.                  mov     dx,3CEh         ; Graphics Controller I/O port
  17777.                  mov     ax,805h         ; AH := 00001000b (read mode 1)
  17778.                                          ; AL := Mode register number
  17779.                  out     dx,ax
  17780.  
  17781.                  mov     ax,002          ; AH := 0 (color compare value)
  17782.                  out     dx,ax           ; AL := Color Compare register number
  17783.  
  17784.                  mov     ax,0F07h        ; AH := 00001111b (color don't care m
  17785.                  out     dx,ax           ; AL := Color Don't Care register num
  17786.  
  17787.  ; fill the print buffer; all nonzero pixels in the video buffer are printed
  17788.  
  17789.                  std                     ; fill the print buffer backwards
  17790.  
  17791.  L11:            lodsb                   ; AL := 8-pixel color compare value
  17792.                                          ;  (bits = 0 if pixel <> 0)
  17793.                  not     al              ; AL := 8 printable pixels
  17794.                  stosb                   ; store in print buffer
  17795.  
  17796.                  add     si,81           ; increment to next row in video buff
  17797.                  loop    L11
  17798.  
  17799.                  cld                     ; clear direction flag
  17800.  
  17801.  ; restore Graphics Controller default state
  17802.  
  17803.                  mov     ax,5            ; AH := read mode 0, write mode 0
  17804.                  out     dx,ax           ; AL := Mode register number
  17805.  
  17806.                  mov     ax,7            ; AH := 0 (color don't care mask)
  17807.                  out     dx,ax           ; AL := Color Don't Care register num
  17808.  
  17809.                  pop     ds              ; restore DS
  17810.                  ret
  17811.  
  17812.  TranslatePixels ENDP
  17813.  
  17814.  ;
  17815.  ; ScreenDumpEGA
  17816.  ;
  17817.  
  17818.  ScreenDumpEGA   PROC    near            ; Caller:       DS = DGROUP
  17819.  
  17820.                  call    PrinterGraphics ; configure the printer for graphics
  17821.  
  17822.                  push    ds
  17823.                  pop     es              ; DS,ES := DGROUP
  17824.  
  17825.                  xor     si,si           ; SI := offset of start of video buff
  17826.  
  17827.  L21:            push    si
  17828.                  mov     di,offset DGROUP:PrintBuf
  17829.                  call    TranslatePixels ; copy one printable row of pixels
  17830.  
  17831.                  mov     cx,350
  17832.                  mov     di,offset DGROUP:PrintBuf
  17833.                  call    PrintPixels     ; print them
  17834.  
  17835.                  pop     si
  17836.                  inc     si
  17837.                  cmp     si,80           ; loop across all 80 columns in
  17838.                  jb      L21             ;  the video buffer
  17839.  
  17840.                  call    PrinterDefault  ; restore the printer to its default
  17841.                                          ;  state
  17842.                  ret
  17843.  
  17844.  ScreenDumpEGA   ENDP
  17845.  
  17846.  _TEXT           ENDS
  17847.  
  17848.  
  17849.  _DATA           SEGMENT word public 'DATA'
  17850.  
  17851.  PrintBuf        DB      350 dup(?)      ; print output buffer
  17852.  
  17853.  VideoBufSeg     DW      0A000h
  17854.  
  17855.  EpsonGraphics   DB      1Bh,33h,18h
  17856.  EpsonReset      DB      1Bh,40h
  17857.  DataHeader      DB      1Bh,4Bh,00h,00h
  17858.  CRLF            DB      0Dh,0Ah
  17859.  
  17860.  _DATA           ENDS
  17861.  
  17862.                  END
  17863.  
  17864.  \SAMPCODE\VIDEO\B\B_3.ASM
  17865.  
  17866.                  TITLE   'Listing B-3'
  17867.                  NAME    ScreenDumpAlpha
  17868.                  PAGE    55,132
  17869.  
  17870.  ;
  17871.  ; Name:         ScreenDumpAlpha
  17872.  ;
  17873.  ; Function:     Screen Dump for EGA alphanumeric modes with 350-line resoluti
  17874.  ;
  17875.  ; Caller:       (undefined)
  17876.  ;
  17877.  ; Notes:        The main procedure of this program, ScreenDumpAlpha, may be
  17878.  ;               called from an application program or as part of a TSR
  17879.  ;               (Terminate-but-Stay Resident) handler for interrupt 5.
  17880.  ;
  17881.  
  17882.  STDPRN          =       4               ; MS-DOS standard printer handle
  17883.  
  17884.  
  17885.  DGROUP          GROUP   _DATA
  17886.  
  17887.  _TEXT           SEGMENT byte public 'CODE'
  17888.                  ASSUME  cs:_TEXT,ds:DGROUP,es:DGROUP
  17889.  
  17890.  ;
  17891.  ; PrintLine
  17892.  ;
  17893.  ;       Writes one line of characters to the standard printer device.  Ignore
  17894.  ;       errors.
  17895.  ;
  17896.  
  17897.  PrintLine       PROC    near            ; Caller:       DS:DX -> data
  17898.                                          ;               CX = # of bytes
  17899.                  mov     bx,STDPRN
  17900.                  mov     ah,40h          ; INT 21h function 40h:  Write
  17901.                  int     21h
  17902.                  ret
  17903.  
  17904.  PrintLine       ENDP
  17905.  
  17906.  ;
  17907.  ; PrinterGraphics
  17908.  ;
  17909.  ;       Puts the printer in its "graphics mode."  This routine must be
  17910.  ;       customized for different printers.
  17911.  ;
  17912.  
  17913.  PrinterGraphics PROC    near            ; Configures Epson MX-80 printer
  17914.                                          ;  for 480 dots/line
  17915.  
  17916.                  mov     dx,offset DGROUP:EpsonGraphics
  17917.                  mov     cx,3
  17918.                  call    PrintLine
  17919.                  ret
  17920.  
  17921.  PrinterGraphics ENDP
  17922.  
  17923.  ;
  17924.  ; PrinterDefault
  17925.  ;
  17926.  ;       Puts the printer in its default (non-graphics) mode.  Again, this
  17927.  ;       routine must be customized for different printers.
  17928.  ;
  17929.  
  17930.  PrinterDefault  PROC    near            ; Configures Epson MX-80 for default
  17931.                                          ;  alphanumeric output
  17932.  
  17933.                  mov     dx,offset DGROUP:EpsonReset
  17934.                  mov     cx,2
  17935.                  call    PrintLine
  17936.                  ret
  17937.  
  17938.  PrinterDefault  ENDP
  17939.  
  17940.  ;
  17941.  ; ChopZeroes
  17942.  ;
  17943.  ;       Chops trailing zeros from the printer output buffer.
  17944.  ;
  17945.  
  17946.  ChopZeroes      PROC    near            ; Caller:       ES:DI -> buffer
  17947.                                          ;               CX = buffer length
  17948.                                          ; Returns:      CX = adjusted length
  17949.  
  17950.                  jcxz    L01             ; exit if buffer is empty
  17951.  
  17952.                  add     di,cx
  17953.                  dec     di              ; ES:DI -> last byte in buffer
  17954.  
  17955.                  xor     al,al           ; AL := 0 (byte to scan for)
  17956.  
  17957.                  std                     ; scan backwards
  17958.                  repe    scasb
  17959.                  cld                     ; restore direction flag
  17960.                  je      L01             ; jump if buffer filled with zeroes
  17961.  
  17962.                  inc     cx              ; adjust length past last nonzero byt
  17963.  
  17964.  L01:            ret
  17965.  
  17966.  ChopZeroes      ENDP
  17967.  
  17968.  ;
  17969.  ; PrintPixels
  17970.  ;
  17971.  ;       Prints one row of pixels on an Epson MX-80.
  17972.  ;
  17973.  
  17974.  PrintPixels     PROC    near            ; Caller:       DI = offset of buffer
  17975.                                          ;               CX = buffer length
  17976.  
  17977.                  push    ds
  17978.                  pop     es              ; ES := DS
  17979.  
  17980.                  push    di              ; preserve buffer offset
  17981.                  call    ChopZeroes
  17982.                  push    cx              ; preserve length
  17983.  
  17984.                  mov     word ptr DataHeader+2,cx  ; store buffer length
  17985.                                                    ;  in output data header
  17986.                  mov     dx,offset DGROUP:DataHeader
  17987.                  mov     cx,4
  17988.                  call    PrintLine       ; print data header
  17989.  
  17990.                  pop     cx              ; CX := buffer length
  17991.                  pop     dx              ; DX := buffer offset
  17992.                  call    PrintLine       ; print the pixels
  17993.  
  17994.                  mov     dx,offset DGROUP:CRLF
  17995.                  mov     cx,2
  17996.                  call    PrintLine
  17997.  
  17998.                  ret
  17999.  
  18000.  PrintPixels     ENDP
  18001.  
  18002.  ;
  18003.  ; TranslatePixels
  18004.  ;
  18005.  ;       Copies one printable row of pixels from the first character definitio
  18006.  ;       table in map 2 to the print buffer.
  18007.  ;
  18008.  ;       This routine formats the printer buffer for output to an Epson
  18009.  ;       MX-80.  The page is printed sideways, so the printed output is
  18010.  ;       350 pixels wide.
  18011.  ;
  18012.  
  18013.  TranslatePixels PROC    near            ; Caller:       SI = video buffer off
  18014.                                          ;               ES:DI -> print buffer
  18015.  
  18016.                  push    ds              ; preserve DS
  18017.                  mov     ds,VideoBufSeg  ; DS:SI -> video buffer
  18018.  
  18019.                  add     di,es:PrintBufSize
  18020.                  dec     di              ; ES:DI -> last byte in print buffer
  18021.  
  18022.                  mov     dx,3CEh         ; Graphics Controller I/O port
  18023.  
  18024.  ; fill the print buffer
  18025.  
  18026.                  mov     cx,es:Rows      ; CX := number of character rows
  18027.  
  18028.  L11:            push    cx              ; preserve CX and SI
  18029.                  push    si
  18030.  
  18031.                  mov     ax,0004h        ; AH := value for Read Map Select reg
  18032.                                          ; AL := Read Map Select reg number
  18033.                  out     dx,ax           ; select map 0 (character codes)
  18034.  
  18035.                  lodsb                   ; AX := next char code in video buffe
  18036.                  mov     cl,5
  18037.                  shl     ax,cl           ; AX := AX * 32
  18038.                  mov     si,ax           ; SI := offset of character definitio
  18039.                                          ;  in map 2
  18040.                  mov     ax,0204h
  18041.                  out     dx,ax           ; select map 2 (bit patterns)
  18042.  
  18043.                  mov     cx,es:Points    ; CX := size of character definition
  18044.  
  18045.  L12:            cld
  18046.                  lodsb                   ; AL := 8-bit pattern from character
  18047.                                          ;  definition table
  18048.                                          ; SI := SI + 1
  18049.                  std
  18050.                  stosb                   ; store bit pattern in print buffer
  18051.                                          ; DI := DI - 1
  18052.                  loop    L12             ; loop down character definition
  18053.  
  18054.                  pop     si              ; restore SI and CX
  18055.                  pop     cx
  18056.  
  18057.                  add     si,es:Columns   ; DS:SI -> next row of characters
  18058.                  loop    L11             ; loop down character rows
  18059.  
  18060.                  cld                     ; clear direction flag
  18061.  
  18062.                  pop     ds              ; restore DS
  18063.                  ret
  18064.  
  18065.  TranslatePixels ENDP
  18066.  
  18067.  ;
  18068.  ; ScreenDumpAlpha
  18069.  ;
  18070.  
  18071.  ScreenDumpAlpha PROC    near            ; Caller:       DS = DGROUP
  18072.  
  18073.                  call    PrinterGraphics ; configure the printer for graphics
  18074.  
  18075.                  call    CGenModeSet     ; address EGA memory maps in parallel
  18076.                                          ;  map 0 contains character codes
  18077.                                          ;  map 2 contains character definitio
  18078.  
  18079.  ; copy screen dimensions from Video Display Data Area
  18080.  
  18081.                  mov     ax,40h
  18082.                  mov     es,ax           ; ES -> video BIOS data area
  18083.  
  18084.                  mov     al,es:[84h]     ; AX := ROWS
  18085.                  inc     ax
  18086.                  mov     Rows,ax
  18087.                  mov     ax,es:[4Ah]     ; AX := CRT_COLS
  18088.                  add     ax,ax           ; * 2 for proper buffer addressing
  18089.                  mov     Columns,ax
  18090.                  mov     ax,es:[85h]     ; AX := POINTS
  18091.                  mov     Points,ax
  18092.                  mul     Rows            ; AX := ROWS * POINTS
  18093.                  mov     PrintBufSize,ax
  18094.  
  18095.  ; print the screen
  18096.  
  18097.                  push    ds
  18098.                  pop     es              ; DS,ES := DGROUP
  18099.  
  18100.                  xor     si,si           ; SI := offset of start of video buff
  18101.  
  18102.  L21:            push    si
  18103.                  mov     di,offset DGROUP:PrintBuf
  18104.                  call    TranslatePixels ; copy one printable row of pixels
  18105.  
  18106.                  mov     cx,PrintBufSize
  18107.                  mov     di,offset DGROUP:PrintBuf
  18108.                  call    PrintPixels     ; print them
  18109.  
  18110.                  pop     si
  18111.                  add     si,2            ; increment to next character column
  18112.                  cmp     si,Columns      ; loop across all character columns
  18113.                  jb      L21
  18114.  
  18115.                  call    CGenModeClear   ; restore previous alphanumeric mode
  18116.  
  18117.                  call    PrinterDefault  ; restore the printer to its default
  18118.                                          ;  state
  18119.                  ret
  18120.  
  18121.  ScreenDumpAlpha ENDP
  18122.  
  18123.  ;
  18124.  ; CGenModeSet (from Chapter 10)
  18125.  ;
  18126.  
  18127.  CGenModeSet     PROC    near
  18128.  
  18129.                  push    si              ; preserve these registers
  18130.                  push    cx
  18131.  
  18132.                  cli                     ; disable interrupts
  18133.                  mov     dx,3C4h         ; Sequencer port address
  18134.                  mov     si,offset DGROUP:SetSeqParms
  18135.                  mov     cx,4
  18136.  
  18137.  L31:            lodsw                   ; AH := value for Sequencer register
  18138.                                          ; AL := register number
  18139.                  out     dx,ax           ; program the register
  18140.                  loop    L31
  18141.                  sti                     ; enable interrupts
  18142.  
  18143.                  mov     dl,0CEh         ; DX := 3CEH (Graphics Controller por
  18144.                                          ;               address)
  18145.                  mov     si,offset DGROUP:SetGCParms
  18146.                  mov     cx,3
  18147.  
  18148.  L32:            lodsw                   ; program the Graphics Controller
  18149.                  out     dx,ax
  18150.                  loop    L32
  18151.  
  18152.                  pop     cx              ; restore registers and return
  18153.                  pop     si
  18154.                  ret
  18155.  
  18156.  CGenModeSet     ENDP
  18157.  
  18158.  
  18159.  ;
  18160.  ; CGenModeClear (from Chapter 10)
  18161.  ;
  18162.  
  18163.  CGenModeClear   PROC    near
  18164.  
  18165.                  push    si              ; preserve these registers
  18166.                  push    cx
  18167.  
  18168.                  cli                     ; disable interrupts
  18169.                  mov     dx,3C4h         ; Sequencer port address
  18170.                  mov     si,offset DGROUP:ClearSeqParms
  18171.                  mov     cx,4
  18172.  
  18173.  L41:            lodsw                   ; AH := value for Sequencer register
  18174.                                          ; AL := register number
  18175.                  out     dx,ax           ; program the register
  18176.                  loop    L41
  18177.                  sti                     ; enable interrupts
  18178.  
  18179.                  mov     dl,0CEh         ; DX := 3CEH (Graphics Controller por
  18180.                                          ;               address)
  18181.                  mov     si,offset DGROUP:ClearGCParms
  18182.                  mov     cx,3
  18183.  
  18184.  L42:            lodsw                   ; program the Graphics Controller
  18185.                  out     dx,ax
  18186.                  loop    L42
  18187.  
  18188.                  mov     ah,0Fh          ; AH := INT 10H function number
  18189.                  int     10h             ; get video mode
  18190.  
  18191.                  cmp     al,7
  18192.                  jne     L43             ; jump if not monochrome mode
  18193.  
  18194.                  mov     ax,0806h        ; program Graphics Controller
  18195.                  out     dx,ax           ;  to start map at B000:0000
  18196.  
  18197.  L43:            pop     cx              ; restore registers and return
  18198.                  pop     si
  18199.                  ret
  18200.  
  18201.  CGenModeClear   ENDP
  18202.  
  18203.  _TEXT           ENDS
  18204.  
  18205.  
  18206.  _DATA           SEGMENT word public 'DATA'
  18207.  
  18208.  PrintBuf        DB      400 dup(?)      ; print output buffer
  18209.  
  18210.  VideoBufSeg     DW      0A000h
  18211.  
  18212.  EpsonGraphics   DB      1Bh,33h,18h
  18213.  EpsonReset      DB      1Bh,40h
  18214.  DataHeader      DB      1Bh,4Bh,00h,00h
  18215.  CRLF            DB      0Dh,0Ah
  18216.  
  18217.  Columns         DW      ?               ; number of displayed character colum
  18218.  Rows            DW      ?               ; number of displayed character rows
  18219.  Points          DW      ?               ; vertical size of character matrix
  18220.  PrintBufSize    DW      ?               ; Rows * Points
  18221.  
  18222.  SetSeqParms     DW      0100h           ; parameters for CGenModeSet
  18223.                  DW      0402h
  18224.                  DW      0704h
  18225.                  DW      0300h
  18226.  
  18227.  SetGCParms      DW      0204h
  18228.                  DW      0005h
  18229.                  DW      0006h
  18230.  
  18231.  ClearSeqParms   DW      0100h           ; parameters for CGenModeClear
  18232.                  DW      0302h
  18233.                  DW      0304h
  18234.                  DW      0300h
  18235.  
  18236.  ClearGCParms    DW      0004h
  18237.                  DW      1005h
  18238.                  DW      0E06h
  18239.  
  18240.  _DATA           ENDS
  18241.  
  18242.                  END
  18243.  
  18244.  \SAMPCODE\VIDEO\C
  18245.  \SAMPCODE\VIDEO\C\C_2.C
  18246.  
  18247.  /* Listing C-2 */
  18248.  
  18249.  main()
  18250.  {
  18251.          char    *SubsystemName();
  18252.          char    *DisplayName();
  18253.  
  18254.          static struct
  18255.          {
  18256.            char  Subsystem;
  18257.            char  Display;
  18258.          }
  18259.                          VIDstruct[2];
  18260.  
  18261.  
  18262.          /* detect video subsystems */
  18263.  
  18264.          VideoID( VIDstruct );
  18265.  
  18266.  
  18267.          /* show results */
  18268.  
  18269.          printf( "Video subsystems in this computer:" );
  18270.  
  18271.          printf( "\n  %s (%s)", SubsystemName(VIDstruct[0].Subsystem),
  18272.            DisplayName(VIDstruct[0].Display) );
  18273.  
  18274.          if ( VIDstruct[1].Subsystem )
  18275.            printf( "\n  %s (%s)", SubsystemName(VIDstruct[1].Subsystem),
  18276.              DisplayName(VIDstruct[1].Display) );
  18277.  }
  18278.  
  18279.  
  18280.  char *SubsystemName( a )
  18281.  char    a;
  18282.  {
  18283.          static char *IBMname[] =
  18284.          {
  18285.            "(none)",
  18286.            "MDA",
  18287.            "CGA",
  18288.            "EGA",
  18289.            "MCGA",
  18290.            "VGA"
  18291.          };
  18292.  
  18293.          static char *Hercname[] =
  18294.          {
  18295.            "HGC",
  18296.            "HGC+",
  18297.            "InColor"
  18298.          };
  18299.  
  18300.          if ( a & 0x80 )
  18301.            return ( Hercname[a & 0x7F] );
  18302.          else
  18303.            return( IBMname[a] );
  18304.  }
  18305.  
  18306.  
  18307.  char *DisplayName( d )
  18308.  char    d;
  18309.  {
  18310.          static char *name[] =
  18311.          {
  18312.            "(none)",
  18313.            "MDA-compatible monochrome display",
  18314.            "CGA-compatible color display",
  18315.            "EGA-compatible color display",
  18316.            "PS/2-compatible monochrome display",
  18317.            "PS/2-compatible color display"
  18318.          };
  18319.  
  18320.          return( name[d] );
  18321.  }
  18322.  
  18323.  \SAMPCODE\VIDEO\C\C_1.ASM
  18324.  
  18325.                  TITLE   'Listing C-1'
  18326.                  NAME    VideoID
  18327.                  PAGE    55,132
  18328.  
  18329.  ;
  18330.  ; Name:         VideoID
  18331.  ;
  18332.  ; Function:     Detects the presence of various video subsystems and associat
  18333.  ;               monitors.
  18334.  ;
  18335.  ; Caller:       Microsoft C:
  18336.  ;
  18337.  ;                       void VideoID(VIDstruct);
  18338.  ;
  18339.  ;                       struct
  18340.  ;                       {
  18341.  ;                         char VideoSubsystem;
  18342.  ;                         char Display;
  18343.  ;                       }
  18344.  ;                               *VIDstruct[2];
  18345.  ;
  18346.  ;               Subsystem ID values:
  18347.  ;                                0  = (none)
  18348.  ;                                1  = MDA
  18349.  ;                                2  = CGA
  18350.  ;                                3  = EGA
  18351.  ;                                4  = MCGA
  18352.  ;                                5  = VGA
  18353.  ;                               80h = HGC
  18354.  ;                               81h = HGC+
  18355.  ;                               82h = Hercules InColor
  18356.  ;
  18357.  ;               Display types:   0  = (none)
  18358.  ;                                1  = MDA-compatible monochrome
  18359.  ;                                2  = CGA-compatible color
  18360.  ;                                3  = EGA-compatible color
  18361.  ;                                4  = PS/2-compatible monochrome
  18362.  ;                                5  = PS/2-compatible color
  18363.  ;
  18364.  ;
  18365.  ;       The values returned in VIDstruct[0].VideoSubsystem and
  18366.  ;       VIDstruct[0].Display indicate the currently active subsystem.
  18367.  ;
  18368.  
  18369.  ARGpVID         EQU     word ptr [bp+4] ; stack frame addressing
  18370.  
  18371.  
  18372.  VIDstruct       STRUC                   ; corresponds to C data structure
  18373.  
  18374.  Video0Type      DB      ?               ; first subsystem type
  18375.  Display0Type    DB      ?               ; display attached to first subsystem
  18376.  
  18377.  Video1Type      DB      ?               ; second subsystem type
  18378.  Display1Type    DB      ?               ; display attached to second subsyste
  18379.  
  18380.  VIDstruct       ENDS
  18381.  
  18382.  
  18383.  Device0         EQU     word ptr Video0Type[di]
  18384.  Device1         EQU     word ptr Video1Type[di]
  18385.  
  18386.  
  18387.  MDA             EQU     1               ; subsystem types
  18388.  CGA             EQU     2
  18389.  EGA             EQU     3
  18390.  MCGA            EQU     4
  18391.  VGA             EQU     5
  18392.  HGC             EQU     80h
  18393.  HGCPlus         EQU     81h
  18394.  InColor         EQU     82h
  18395.  
  18396.  MDADisplay      EQU     1               ; display types
  18397.  CGADisplay      EQU     2
  18398.  EGAColorDisplay EQU     3
  18399.  PS2MonoDisplay  EQU     4
  18400.  PS2ColorDisplay EQU     5
  18401.  
  18402.  TRUE            EQU     1
  18403.  FALSE           EQU     0
  18404.  
  18405.  
  18406.  DGROUP          GROUP   _DATA
  18407.  
  18408.  _TEXT           SEGMENT byte public 'CODE'
  18409.                  ASSUME  cs:_TEXT,ds:DGROUP
  18410.  
  18411.                  PUBLIC  _VideoID
  18412.  _VideoID        PROC    near
  18413.  
  18414.                  push    bp              ; preserve caller registers
  18415.                  mov     bp,sp
  18416.                  push    si
  18417.                  push    di
  18418.  
  18419.  ; initialize the data structure that will contain the results
  18420.  
  18421.                  mov     di,ARGpVID      ; DS:DI -> start of data structure
  18422.  
  18423.                  mov     Device0,0       ; zero these variables
  18424.                  mov     Device1,0
  18425.  
  18426.  ; look for the various subsystems using the subroutines whose addresses are
  18427.  ;  tabulated in TestSequence; each subroutine sets flags in TestSequence
  18428.  ;  to indicate whether subsequent subroutines need to be called
  18429.  
  18430.                  mov     byte ptr CGAflag,TRUE
  18431.                  mov     byte ptr EGAflag,TRUE
  18432.                  mov     byte ptr Monoflag,TRUE
  18433.  
  18434.                  mov     cx,NumberOfTests
  18435.                  mov     si,offset DGROUP:TestSequence
  18436.  
  18437.  L01:            lodsb                   ; AL := flag
  18438.                  test    al,al
  18439.                  lodsw                   ; AX := subroutine address
  18440.                  jz      L02             ; skip subroutine if flag is false
  18441.  
  18442.                  push    si
  18443.                  push    cx
  18444.                  call    ax              ; call subroutine to detect subsystem
  18445.                  pop     cx
  18446.                  pop     si
  18447.  
  18448.  L02:            loop    L01
  18449.  
  18450.  ; determine which subsystem is active
  18451.  
  18452.                  call    FindActive
  18453.  
  18454.                  pop     di              ; restore caller registers and return
  18455.                  pop     si
  18456.                  mov     sp,bp
  18457.                  pop     bp
  18458.                  ret
  18459.  
  18460.  _VideoID        ENDP
  18461.  
  18462.  
  18463.  ;
  18464.  ; FindPS2
  18465.  ;
  18466.  ;       This subroutine uses INT 10H function 1Ah to determine the video BIOS
  18467.  ;        Display Combination Code (DCC) for each video subsystem present.
  18468.  ;
  18469.  
  18470.  FindPS2         PROC    near
  18471.  
  18472.                  mov     ax,1A00h
  18473.                  int     10h             ; call video BIOS for info
  18474.  
  18475.                  cmp     al,1Ah
  18476.                  jne     L13             ; exit if function not supported (i.e
  18477.                                          ;  no MCGA or VGA in system)
  18478.  
  18479.  ; convert BIOS DCCs into specific subsystems & displays
  18480.  
  18481.                  mov     cx,bx
  18482.                  xor     bh,bh           ; BX := DCC for active subsystem
  18483.  
  18484.                  or      ch,ch
  18485.                  jz      L11             ; jump if only one subsystem present
  18486.  
  18487.                  mov     bl,ch           ; BX := inactive DCC
  18488.                  add     bx,bx
  18489.                  mov     ax,[bx+offset DGROUP:DCCtable]
  18490.  
  18491.                  mov     Device1,ax
  18492.  
  18493.                  mov     bl,cl
  18494.                  xor     bh,bh           ; BX := active DCC
  18495.  
  18496.  L11:            add     bx,bx
  18497.                  mov     ax,[bx+offset DGROUP:DCCtable]
  18498.  
  18499.                  mov     Device0,ax
  18500.  
  18501.  ; reset flags for subsystems that have been ruled out
  18502.  
  18503.                  mov     byte ptr CGAflag,FALSE
  18504.                  mov     byte ptr EGAflag,FALSE
  18505.                  mov     byte ptr Monoflag,FALSE
  18506.  
  18507.                  lea     bx,Video0Type[di]  ; if the BIOS reported an MDA ...
  18508.                  cmp     byte ptr [bx],MDA
  18509.                  je      L12
  18510.  
  18511.                  lea     bx,Video1Type[di]
  18512.                  cmp     byte ptr [bx],MDA
  18513.                  jne     L13
  18514.  
  18515.  L12:            mov     word ptr [bx],0    ; ... Hercules can't be ruled out
  18516.                  mov     byte ptr Monoflag,TRUE
  18517.  
  18518.  L13:            ret
  18519.  
  18520.  FindPS2         ENDP
  18521.  
  18522.  
  18523.  ;
  18524.  ; FindEGA
  18525.  ;
  18526.  ; Look for an EGA.  This is done by making a call to an EGA BIOS function
  18527.  ;  which doesn't exist in the default (MDA, CGA) BIOS.
  18528.  
  18529.  FindEGA         PROC    near            ; Caller:       AH = flags
  18530.                                          ; Returns:      AH = flags
  18531.                                          ;               Video0Type and
  18532.                                          ;                Display0Type updated
  18533.  
  18534.                  mov     bl,10h          ; BL := 10h (return EGA info)
  18535.                  mov     ah,12h          ; AH := INT 10H function number
  18536.                  int     10h             ; call EGA BIOS for info
  18537.                                          ; if EGA BIOS is present,
  18538.                                          ;  BL <> 10H
  18539.                                          ;  CL = switch setting
  18540.                  cmp     bl,10h
  18541.                  je      L22             ; jump if EGA BIOS not present
  18542.  
  18543.                  mov     al,cl
  18544.                  shr     al,1            ; AL := switches/2
  18545.                  mov     bx,offset DGROUP:EGADisplays
  18546.                  xlat                    ; determine display type from switche
  18547.                  mov     ah,al           ; AH := display type
  18548.                  mov     al,EGA          ; AL := subystem type
  18549.                  call    FoundDevice
  18550.  
  18551.                  cmp     ah,MDADisplay
  18552.                  je      L21             ; jump if EGA has a monochrome displa
  18553.  
  18554.                  mov     CGAflag,FALSE   ; no CGA if EGA has color display
  18555.                  jmp     short L22
  18556.  
  18557.  L21:            mov     Monoflag,FALSE  ; EGA has a mono display, so MDA and
  18558.                                          ;  Hercules are ruled out
  18559.  L22:            ret
  18560.  
  18561.  FindEGA         ENDP
  18562.  
  18563.  
  18564.  ;
  18565.  ; FindCGA
  18566.  ;
  18567.  ;       This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H.
  18568.  ;
  18569.  
  18570.  FindCGA         PROC    near            ; Returns:      VIDstruct updated
  18571.  
  18572.                  mov     dx,3D4h         ; DX := CRTC address port
  18573.                  call    Find6845
  18574.                  jc      L31             ; jump if not present
  18575.  
  18576.                  mov     al,CGA
  18577.                  mov     ah,CGADisplay
  18578.                  call    FoundDevice
  18579.  
  18580.  L31:            ret
  18581.  
  18582.  FindCGA         ENDP
  18583.  
  18584.  
  18585.  ;
  18586.  ; FindMono
  18587.  ;
  18588.  ;       This is done by looking for the MDA's 6845 CRTC at I/O port 3B4H.  If
  18589.  ;       a 6845 is found, the subroutine distinguishes between an MDA
  18590.  ;       and a Hercules adapter by monitoring bit 7 of the CRT Status byte.
  18591.  ;       This bit changes on Hercules adapters but does not change on an MDA.
  18592.  ;
  18593.  ;       The various Hercules adapters are identified by bits 4 through 6 of
  18594.  ;       the CRT Status value:
  18595.  ;
  18596.  ;               000b = HGC
  18597.  ;               001b = HGC+
  18598.  ;               101b = InColor card
  18599.  ;
  18600.  
  18601.  FindMono        PROC    near            ; Returns:      VIDstruct updated
  18602.  
  18603.                  mov     dx,3B4h         ; DX := CRTC address port
  18604.                  call    Find6845
  18605.                  jc      L44             ; jump if not present
  18606.  
  18607.                  mov     dl,0BAh         ; DX := 3BAh (status port)
  18608.                  in      al,dx
  18609.                  and     al,80h
  18610.                  mov     ah,al           ; AH := bit 7 (vertical sync on HGC)
  18611.  
  18612.                  mov     cx,8000h        ; do this 32768 times
  18613.  L41:            in      al,dx
  18614.                  and     al,80h          ; isolate bit 7
  18615.                  cmp     ah,al
  18616.                  loope   L41             ; wait for bit 7 to change
  18617.  
  18618.                  jne     L42             ; if bit 7 changed, it's a Hercules
  18619.  
  18620.                  mov     al,MDA          ; if bit 7 didn't change, it's an MDA
  18621.                  mov     ah,MDADisplay
  18622.                  call    FoundDevice
  18623.                  jmp     short L44
  18624.  
  18625.  L42:            in      al,dx
  18626.                  mov     dl,al           ; DL := value from status port
  18627.  
  18628.                  mov     ah,MDADisplay   ; assume it's a monochrome display
  18629.  
  18630.                  mov     al,HGC          ; look for an HGC
  18631.                  and     dl,01110000b    ; mask off bits 4 thru 6
  18632.                  jz      L43
  18633.  
  18634.                  mov     al,HGCPlus      ; look for an HGC+
  18635.                  cmp     dl,00010000b
  18636.                  je      L43             ; jump if it's an HGC+
  18637.  
  18638.                  mov     al,InColor      ; it's an InColor card
  18639.                  mov     ah,EGAColorDisplay
  18640.  
  18641.  L43:            call    FoundDevice
  18642.  
  18643.  L44:            ret
  18644.  
  18645.  FindMono        ENDP
  18646.  
  18647.  
  18648.  ;
  18649.  ; Find6845
  18650.  ;
  18651.  ;       This routine detects the presence of the CRTC on a MDA, CGA or HGC.
  18652.  ;       The technique is to write and read register 0Fh of the chip (cursor
  18653.  ;       low).  If the same value is read as written, assume the chip is
  18654.  ;       present at the specified port addr.
  18655.  ;
  18656.  
  18657.  Find6845        PROC    near            ; Caller:       DX = port addr
  18658.                                          ; Returns:      cf set if not present
  18659.                  mov     al,0Fh
  18660.                  out     dx,al           ; select 6845 reg 0Fh (Cursor Low)
  18661.                  inc     dx
  18662.                  in      al,dx           ; AL := current Cursor Low value
  18663.                  mov     ah,al           ; preserve in AH
  18664.                  mov     al,66h          ; AL := arbitrary value
  18665.                  out     dx,al           ; try to write to 6845
  18666.  
  18667.                  mov     cx,100h
  18668.  L51:            loop    L51             ; wait for 6845 to respond
  18669.  
  18670.                  in      al,dx
  18671.                  xchg    ah,al           ; AH := returned value
  18672.                                          ; AL := original value
  18673.                  out     dx,al           ; restore original value
  18674.  
  18675.                  cmp     ah,66h          ; test whether 6845 responded
  18676.                  je      L52             ; jump if it did (cf is reset)
  18677.  
  18678.                  stc                     ; set carry flag if no 6845 present
  18679.  
  18680.  L52:            ret
  18681.  
  18682.  Find6845        ENDP
  18683.  
  18684.  
  18685.  ;
  18686.  ; FindActive
  18687.  ;
  18688.  ;       This subroutine stores the currently active device as Device0.  The
  18689.  ;       current video mode determines which subsystem is active.
  18690.  ;
  18691.  
  18692.  FindActive      PROC    near
  18693.  
  18694.                  cmp     word ptr Device1,0
  18695.                  je      L63                     ; exit if only one subsystem
  18696.  
  18697.                  cmp     Video0Type[di],4        ; exit if MCGA or VGA present
  18698.                  jge     L63                     ;  (INT 10H function 1AH
  18699.                  cmp     Video1Type[di],4        ;  already did the work)
  18700.                  jge     L63
  18701.  
  18702.                  mov     ah,0Fh
  18703.                  int     10h                     ; AL := current BIOS video mo
  18704.  
  18705.                  and     al,7
  18706.                  cmp     al,7                    ; jump if monochrome
  18707.                  je      L61                     ;  (mode 7 or 0Fh)
  18708.  
  18709.                  cmp     Display0Type[di],MDADisplay
  18710.                  jne     L63                     ; exit if Display0 is color
  18711.                  jmp     short L62
  18712.  
  18713.  L61:            cmp     Display0Type[di],MDADisplay
  18714.                  je      L63                     ; exit if Display0 is monochr
  18715.  
  18716.  L62:            mov     ax,Device0              ; make Device0 currently acti
  18717.                  xchg    ax,Device1
  18718.                  mov     Device0,ax
  18719.  
  18720.  L63:            ret
  18721.  
  18722.  FindActive      ENDP
  18723.  
  18724.  
  18725.  ;
  18726.  ; FoundDevice
  18727.  ;
  18728.  ;       This routine updates the list of subsystems.
  18729.  ;
  18730.  
  18731.  FoundDevice     PROC    near                    ; Caller:    AH = display #
  18732.                                                  ;            AL = subsystem #
  18733.                                                  ; Destroys:  BX
  18734.                  lea     bx,Video0Type[di]
  18735.                  cmp     byte ptr [bx],0
  18736.                  je      L71                     ; jump if 1st subsystem
  18737.  
  18738.                  lea     bx,Video1Type[di]       ; must be 2nd subsystem
  18739.  
  18740.  L71:            mov     [bx],ax                 ; update list entry
  18741.                  ret
  18742.  
  18743.  FoundDevice     ENDP
  18744.  
  18745.  _TEXT           ENDS
  18746.  
  18747.  
  18748.  _DATA           SEGMENT word public 'DATA'
  18749.  
  18750.  EGADisplays     DB      CGADisplay      ; 0000b, 0001b  (EGA switch values)
  18751.                  DB      EGAColorDisplay ; 0010b, 0011b
  18752.                  DB      MDADisplay      ; 0100b, 0101b
  18753.                  DB      CGADisplay      ; 0110b, 0111b
  18754.                  DB      EGAColorDisplay ; 1000b, 1001b
  18755.                  DB      MDADisplay      ; 1010b, 1011b
  18756.  
  18757.  DCCtable        DB      0,0             ; translate table for INT 10h func 1A
  18758.                  DB      MDA,MDADisplay
  18759.                  DB      CGA,CGADisplay
  18760.                  DB      0,0
  18761.                  DB      EGA,EGAColorDisplay
  18762.                  DB      EGA,MDADisplay
  18763.                  DB      0,0
  18764.                  DB      VGA,PS2MonoDisplay
  18765.                  DB      VGA,PS2ColorDisplay
  18766.                  DB      0,0
  18767.                  DB      MCGA,EGAColorDisplay
  18768.                  DB      MCGA,PS2MonoDisplay
  18769.                  DB      MCGA,PS2ColorDisplay
  18770.  
  18771.  TestSequence    DB      TRUE            ; this list of flags and addresses
  18772.                  DW      FindPS2         ;  determines the order in which this
  18773.                                          ;  program looks for the various
  18774.  EGAflag         DB      ?               ;  subsystems
  18775.                  DW      FindEGA
  18776.  
  18777.  CGAflag         DB      ?
  18778.                  DW      FindCGA
  18779.  
  18780.  Monoflag        DB      ?
  18781.                  DW      FindMono
  18782.  
  18783.  NumberOfTests   EQU     ($-TestSequence)/3
  18784.  
  18785.  _DATA           ENDS
  18786.  
  18787.                  END
  18788.  
  18789.  \SAMPCODE\VIDEO\DEMO
  18790.  \SAMPCODE\VIDEO\DEMO\DEMO.C
  18791.  
  18792.  /****************************************************************************
  18793.  *
  18794.  * Name:  demo.c
  18795.  *
  18796.  * Description:  This program shows how assembly language video graphics
  18797.  *                can be built into a high-level program.
  18798.  *
  18799.  *
  18800.  * Notes:        Use  MAKE DEMO  to build this program.  You need the
  18801.  *                following tools:
  18802.  *
  18803.  *                    - Microsoft C
  18804.  *                    - Microsoft Macro Assembler
  18805.  *                    - LINK
  18806.  *
  18807.  *
  18808.  *               Use an IBM CGA, EGA, or VGA, or compatible hardware.
  18809.  *
  18810.  *****************************************************************************
  18811.  
  18812.  #define TRUE            1
  18813.  #define FALSE           0
  18814.  
  18815.  #define CGA             2
  18816.  #define EGA             3
  18817.  #define MCGA            4
  18818.  #define VGA             5
  18819.  
  18820.  #define Xmax            319
  18821.  #define Ymax            199
  18822.  
  18823.  #define FivePI          (double)(5*3.1415926535)
  18824.  
  18825.  main()
  18826.  {
  18827.          static struct                   /* for video ID */
  18828.          {
  18829.            char  Subsystem;
  18830.            char  Display;
  18831.          }               VIDstruct[2];
  18832.  
  18833.          int     VIDok = FALSE;
  18834.  
  18835.          int     x,y,Fgd;
  18836.          int     i;
  18837.          double  sin();
  18838.  
  18839.  
  18840.  /* verify presence of CGA-compatible hardware */
  18841.  
  18842.          VideoID( VIDstruct );
  18843.  
  18844.          for( i=0; (i<=1) && !VIDok; i++ )
  18845.            VIDok = ( VIDstruct[i].Subsystem == CGA ) ||
  18846.                    ( VIDstruct[i].Subsystem == EGA ) ||
  18847.                    ( VIDstruct[i].Subsystem == MCGA ) ||
  18848.                    ( VIDstruct[i].Subsystem == VGA );
  18849.  
  18850.          if( !VIDok )
  18851.          {
  18852.            printf( "\nCan't find compatible video hardware\n");
  18853.            exit( 1 );
  18854.          }
  18855.  
  18856.  /* draw something in 320x200 4-color mode */
  18857.  
  18858.          SetVmode( 4 );                  /* BIOS mode 4 is 320x200 4-color */
  18859.  
  18860.          Line04( 0, Ymax/2, Xmax, Ymax/2, 3 );
  18861.  
  18862.          for( x=0; x<=Xmax; x++ )
  18863.          {
  18864.            y = sin( FivePI * (double)x/(double)Xmax ) * (double)(Ymax/2);
  18865.            y += Ymax/2;
  18866.  
  18867.            Fgd = ( x%10 ? 2 : 3 );       /* select foreground pixel value */
  18868.  
  18869.            Line04( x, y, x, Ymax/2, Fgd );       /* draw a line or two */
  18870.            Line04( x, Ymax-y, x, Ymax/2, 5-Fgd );
  18871.          }
  18872.  }
  18873.  
  18874.  \SAMPCODE\VIDEO\DEMO\1_1.ASM
  18875.  
  18876.                  TITLE   'Listing 1-1'
  18877.                  NAME    SetVmode
  18878.                  PAGE    55,132
  18879.  
  18880.  ;
  18881.  ; Name:         SetVmode
  18882.  ;
  18883.  ; Function:     Call IBM PC ROM BIOS to set a video display mode.
  18884.  ;
  18885.  ; Caller:       Microsoft C:
  18886.  ;
  18887.  ;                       void SetVmode(n);
  18888.  ;
  18889.  ;                       int n;                  /* video mode */
  18890.  ;
  18891.  
  18892.  ARGn            EQU     byte ptr [bp+4] ; stack frame addressing
  18893.  
  18894.  EQUIP_FLAG      EQU     byte ptr ds:[10h] ; (in Video Display Data Area)
  18895.  
  18896.  CGAbits         EQU     00100000b       ; bits for EQUIP_FLAG
  18897.  MDAbits         EQU     00110000b
  18898.  
  18899.  _TEXT           SEGMENT byte public 'CODE'
  18900.                  ASSUME  cs:_TEXT
  18901.  
  18902.                  PUBLIC  _SetVmode
  18903.  _SetVmode       PROC    near
  18904.  
  18905.                  push    bp              ; preserve caller registers
  18906.                  mov     bp,sp
  18907.                  push    ds
  18908.  
  18909.                  mov     ax,40h
  18910.                  mov     ds,ax           ; DS -> Video Display Data Area
  18911.  
  18912.                  mov     bl,CGAbits      ; BL := bits indicating presence of C
  18913.  
  18914.                  mov     al,ARGn         ; AL := desired video mode number
  18915.  
  18916.                  mov     ah,al           ; test if desired mode is monochrome
  18917.                  and     ah,7
  18918.                  cmp     ah,7
  18919.                  jne     L01             ; jump if desired mode not 7 or 0Fh
  18920.  
  18921.                  mov     bl,MDAbits      ; BL := bits indicating presence of M
  18922.  
  18923.  L01:            and     EQUIP_FLAG,11001111b
  18924.                  or      EQUIP_FLAG,bl   ; set bits in EQUIP_FLAG
  18925.  
  18926.                  xor     ah,ah           ; AH := 0 (INT 10h function number)
  18927.  
  18928.                  push    bp
  18929.                  int     10h             ; call ROM BIOS to set the video mode
  18930.                  pop     bp
  18931.  
  18932.                  pop     ds              ; restore caller registers and return
  18933.                  mov     sp,bp
  18934.                  pop     bp
  18935.                  ret
  18936.  
  18937.  _SetVmode       ENDP
  18938.  
  18939.  _TEXT           ENDS
  18940.  
  18941.                  END
  18942.  
  18943.  \SAMPCODE\VIDEO\DEMO\4_1.ASM
  18944.  
  18945.                  TITLE   ''Listing 4-1'
  18946.                  NAME    PixelAddr04
  18947.                  PAGE    55,132
  18948.  
  18949.  ;
  18950.  ; Name:         PixelAddr04
  18951.  ;
  18952.  ; Function:     Determine buffer address of pixel in 320x200 4-color mode
  18953.  ;
  18954.  ; Caller:       AX = y-coordinate (0-199)
  18955.  ;               BX = x-coordinate (0-319)
  18956.  ;
  18957.  ; Returns:      AH = bit mask
  18958.  ;               BX = byte offset in buffer
  18959.  ;               CL = number of bits to shift left
  18960.  ;               ES = video buffer segment
  18961.  ;
  18962.  
  18963.  
  18964.  OriginOffset    EQU     0               ; byte offset of (0,0)
  18965.  VideoBufferSeg  EQU     0B800h
  18966.  
  18967.  _TEXT           SEGMENT byte public 'CODE'
  18968.                  ASSUME  cs:_TEXT
  18969.  
  18970.                  PUBLIC  PixelAddr04
  18971.  PixelAddr04     PROC    near
  18972.  
  18973.                  mov     cl,bl           ; CL := low-order byte of x
  18974.  
  18975.                  xchg    ah,al           ; AX := 100h * y
  18976.                  shr     ax,1            ; AL := 80h * (y&1)
  18977.                  add     bh,al           ; BX := x + 8000h*(y&1)
  18978.                  xor     al,al           ; AX := 100h*(y/2)
  18979.                  add     bx,ax           ; BX := x + 8000h*(y&1) + 100h*(y/2)
  18980.                  shr     ax,1
  18981.                  shr     ax,1            ; AX := 40h*(y/2)
  18982.                  add     bx,ax           ; BX := x + 8000h*(y&1) + 140h*(y/2)
  18983.                  shr     bx,1
  18984.                  shr     bx,1            ; BX := x/4 + 2000h*(y&1) + 50h*(y/2)
  18985.                  add     bx,OriginOffset ; BX := byte offset in video buffer
  18986.  
  18987.                  mov     ax,VideoBufferSeg
  18988.                  mov     es,ax           ; ES:BX := byte address of pixel
  18989.  
  18990.                  mov     ah,3            ; AH := unshifted bit mask
  18991.                  and     cl,ah           ; CL := x & 3
  18992.                  xor     cl,ah           ; CL := 3 - (x & 3)
  18993.                  shl     cl,1            ; CL := # bits to shift left
  18994.  
  18995.                  ret
  18996.  
  18997.  PixelAddr04     ENDP
  18998.  
  18999.  _TEXT           ENDS
  19000.  
  19001.                  END
  19002.  
  19003.  \SAMPCODE\VIDEO\DEMO\6_5.ASM
  19004.  
  19005.                  TITLE   'Listing 6-5'
  19006.                  NAME    Line04
  19007.                  PAGE    55,132
  19008.  
  19009.  ;
  19010.  ; Name:         Line04
  19011.  ;
  19012.  ; Function:     Draw a line in 320x200 4-color mode
  19013.  ;
  19014.  ; Caller:       Microsoft C:
  19015.  ;
  19016.  ;                       void Line04(x1,y1,x2,y2,n);
  19017.  ;
  19018.  ;                       int x1,y1,x2,y2;        /* pixel coordinates */
  19019.  ;
  19020.  ;                       int n;                  /* pixel value */
  19021.  ;
  19022.  
  19023.  ARGx1           EQU     word ptr [bp+4] ; stack frame addressing
  19024.  ARGy1           EQU     word ptr [bp+6]
  19025.  ARGx2           EQU     word ptr [bp+8]
  19026.  ARGy2           EQU     word ptr [bp+10]
  19027.  ARGn            EQU     byte ptr [bp+12]
  19028.  VARleafincr     EQU     word ptr [bp-2]
  19029.  VARincr1        EQU     word ptr [bp-4]
  19030.  VARincr2        EQU     word ptr [bp-6]
  19031.  VARroutine      EQU     word ptr [bp-8]
  19032.  
  19033.  ByteOffsetShift EQU     2               ; used to convert pixels to byte offs
  19034.  
  19035.  DGROUP          GROUP   _DATA
  19036.  
  19037.  _TEXT           SEGMENT byte public 'CODE'
  19038.                  ASSUME  cs:_TEXT,ds:DGROUP
  19039.  
  19040.                  EXTRN   PixelAddr04:near
  19041.  
  19042.                  PUBLIC  _Line04
  19043.  _Line04         PROC    near
  19044.  
  19045.                  push    bp              ; preserve caller registers
  19046.                  mov     bp,sp
  19047.                  sub     sp,8            ; stack space for local variables
  19048.                  push    si
  19049.                  push    di
  19050.  
  19051.  
  19052.                  mov     si,2000h        ; increment for video buffer interlea
  19053.                  mov     di,80-2000h     ; increment from last to first interl
  19054.  
  19055.                  mov     cx,ARGx2
  19056.                  sub     cx,ARGx1        ; CX := x2 - x1
  19057.                  jz      VertLine04      ; jump if vertical line
  19058.  
  19059.  ; force x1 < x2
  19060.  
  19061.                  jns     L01             ; jump if x2 > x1
  19062.  
  19063.                  neg     cx              ; CX := x1 - x2
  19064.  
  19065.                  mov     bx,ARGx2        ; exchange x1 and x2
  19066.                  xchg    bx,ARGx1
  19067.                  mov     ARGx2,bx
  19068.  
  19069.                  mov     bx,ARGy2        ; exchange y1 and y2
  19070.                  xchg    bx,ARGy1
  19071.                  mov     ARGy2,bx
  19072.  
  19073.  ; calculate dy = ABS(y2-y1)
  19074.  
  19075.  L01:            mov     bx,ARGy2
  19076.                  sub     bx,ARGy1        ; BX := y2 - y1
  19077.                  jnz     L02
  19078.  
  19079.                  jmp     HorizLine04     ; jump if horizontal line
  19080.  
  19081.  L02:            jns     L03
  19082.  
  19083.                  neg     bx              ; BX := y1 - y2
  19084.                  neg     si              ; negate increments for buffer interl
  19085.                  neg     di
  19086.                  xchg    si,di           ; exchange increments
  19087.  
  19088.  ; select appropriate routine for slope of line
  19089.  
  19090.  L03:            mov     VARleafincr,di  ; save increment for buffer interleav
  19091.  
  19092.                  mov     VARroutine,offset LoSlopeLine04
  19093.                  cmp     bx,cx
  19094.                  jle     L04             ; jump if dy <= dx (slope <= 1)
  19095.                  mov     VARroutine,offset HiSlopeLine04
  19096.                  xchg    bx,cx           ; exchange dy and dx
  19097.  
  19098.  ; calculate initial decision variable and increments
  19099.  
  19100.  L04:            shl     bx,1            ; BX := 2 * dy
  19101.                  mov     VARincr1,bx     ; incr1 := 2 * dy
  19102.                  sub     bx,cx
  19103.                  mov     di,bx           ; DI := d = 2 * dy - dx
  19104.                  sub     bx,cx
  19105.                  mov     VARincr2,bx     ; incr2 := 2 * (dy - dx)
  19106.  
  19107.  ; calculate first pixel address
  19108.  
  19109.                  push    cx              ; preserve this register
  19110.                  mov     ax,ARGy1        ; AX := y
  19111.                  mov     bx,ARGx1        ; BX := x
  19112.                  call    PixelAddr04     ; AH := bit mask
  19113.                                          ; ES:BX -> buffer
  19114.                                          ; CL := # bits to shift left
  19115.  
  19116.                  mov     al,ARGn         ; AL := unshifted pixel value
  19117.                  shl     ax,cl           ; AH := bit mask in proper position
  19118.                                          ; AL := pixel value in proper positio
  19119.  
  19120.                  mov     dx,ax           ; DH := bit mask
  19121.                                          ; DL := pixel value
  19122.                  not     dh              ; DH := inverse bit mask
  19123.  
  19124.                  pop     cx              ; restore this register
  19125.                  inc     cx              ; CX := # of pixels to draw
  19126.  
  19127.                  test    bx,2000h        ; set zero flag if BX in 1st interlea
  19128.                  jz      L05
  19129.  
  19130.                  xchg    si,VARleafincr  ; exchange increment values if 1st pi
  19131.                                          ;  lies in 1st interleave
  19132.  
  19133.  L05:            jmp     VARroutine      ; jump to appropriate routine for slo
  19134.  
  19135.  
  19136.  ; routine for vertical lines
  19137.  
  19138.  VertLine04:     mov     ax,ARGy1        ; AX := y1
  19139.                  mov     bx,ARGy2        ; BX := y2
  19140.                  mov     cx,bx
  19141.                  sub     cx,ax           ; CX := dy
  19142.                  jge     L31             ; jump if dy >= 0
  19143.  
  19144.                  neg     cx              ; force dy >= 0
  19145.                  mov     ax,bx           ; AX := y2
  19146.  
  19147.  L31:            inc     cx              ; CX := # of pixels to draw
  19148.                  mov     bx,ARGx1        ; BX := x
  19149.                  push    cx              ; preserve this register
  19150.                  call    PixelAddr04     ; AH := bit mask
  19151.                                          ; ES:BX -> video buffer
  19152.                                          ; CL := # bits to shift left
  19153.                  mov     al,ARGn         ; AL := pixel value
  19154.                  shl     ax,cl           ; AH := bit mask in proper position
  19155.                                          ; AL := pixel value in proper positio
  19156.                  not     ah              ; AH := inverse bit mask
  19157.                  pop     cx              ; restore this register
  19158.  
  19159.                  test    bx,si           ; set zero flag if BX in 1st interlea
  19160.                  jz      L32
  19161.  
  19162.                  xchg    si,di           ; exchange increment values if 1st pi
  19163.                                          ;  lies in 1st interleave
  19164.  
  19165.  L32:            and     es:[bx],ah      ; zero pixel in buffer
  19166.                  or      es:[bx],al      ; set pixel value in buffer
  19167.  
  19168.                  add     bx,si           ; increment to next portion of interl
  19169.                  xchg    si,di           ; toggle between increment values
  19170.  
  19171.                  loop    L32
  19172.  
  19173.                  jmp     Lexit
  19174.  
  19175.  
  19176.  
  19177.  ; routine for horizontal lines (slope = 0)
  19178.  
  19179.  HorizLine04:    mov     ax,ARGy1
  19180.                  mov     bx,ARGx1
  19181.                  call    PixelAddr04     ; AH := bit mask
  19182.                                          ; ES:BX -> video buffer
  19183.                                          ; CL := # bits to shift left
  19184.                  mov     di,bx           ; ES:DI -> buffer
  19185.  
  19186.                  mov     dh,ah
  19187.                  not     dh              ; DH := unshifted bit mask for leftmo
  19188.                                          ;        byte
  19189.                  mov     dl,0FFh         ; DL := unshifted bit mask for
  19190.                                          ;        rightmost byte
  19191.  
  19192.                  shl     dh,cl           ; DH := reverse bit mask for first by
  19193.                  not     dh              ; DH := bit mask for first byte
  19194.  
  19195.                  mov     cx,ARGx2
  19196.                  and     cl,3
  19197.                  xor     cl,3
  19198.                  shl     cl,1            ; CL := number of bits to shift left
  19199.                  shl     dl,cl           ; DL := bit mask for last byte
  19200.  
  19201.  ; determine byte offset of first and last pixel in the line
  19202.  
  19203.                  mov     ax,ARGx2        ; AX := x2
  19204.                  mov     bx,ARGx1        ; BX := x1
  19205.  
  19206.                  mov     cl,ByteOffsetShift      ; number of bits to shift to
  19207.                                                  ;  convert pixels to bytes
  19208.  
  19209.                  shr     ax,cl           ; AX := byte offset of x2
  19210.                  shr     bx,cl           ; BX := byte offset of x1
  19211.                  mov     cx,ax
  19212.                  sub     cx,bx           ; CX := (# bytes in line) - 1
  19213.  
  19214.  ; propagate pixel value throughout one byte
  19215.  
  19216.                  mov     bx,offset DGROUP:PropagatedPixel
  19217.                  mov     al,ARGn         ; AL := pixel value
  19218.                  xlat                    ; AL := propagated pixel value
  19219.  
  19220.  ; set pixels in leftmost byte of the line
  19221.  
  19222.                  or      dh,dh
  19223.                  js      L43             ; jump if byte-aligned (x1 is leftmos
  19224.                                          ;  pixel in byte)
  19225.                  or      cx,cx
  19226.                  jnz     L42             ; jump if more than one byte in the l
  19227.  
  19228.                  and     dl,dh           ; bit mask for the line
  19229.                  jmp     short L44
  19230.  
  19231.  L42:            mov     ah,al
  19232.                  and     ah,dh           ; AH := masked pixel bits
  19233.                  not     dh              ; DH := reverse bit mask for 1st byte
  19234.                  and     es:[di],dh      ; zero masked pixels in buffer
  19235.                  or      es:[di],ah      ; update masked pixels in buffer
  19236.                  inc     di
  19237.                  dec     cx
  19238.  
  19239.  ; use a fast 8086 machine instruction to draw the remainder of the line
  19240.  
  19241.  L43:            rep     stosb           ; update all pixels in the line
  19242.  
  19243.  ; set pixels in the rightmost byte of the line
  19244.  
  19245.  L44:            and     al,dl           ; AL := masked pixels for last byte
  19246.                  not     dl
  19247.                  and     es:[di],dl      ; zero masked pixels in buffer
  19248.                  or      es:[di],al      ; update masked pixels in buffer
  19249.  
  19250.                  jmp     Lexit
  19251.  
  19252.  
  19253.  ; routine for dy <= dx (slope <= 1)     ; ES:BX -> video buffer
  19254.                                          ; CX = #pixels to draw
  19255.                                          ; DH = inverse bit mask
  19256.                                          ; DL = pixel value in proper position
  19257.                                          ; SI = buffer interleave increment
  19258.                                          ; DI = decision variable
  19259.  LoSlopeLine04:
  19260.  
  19261.  L10:            mov     ah,es:[bx]      ; AH := byte from video buffer
  19262.  
  19263.  L11:            and     ah,dh           ; zero pixel value at current bit off
  19264.                  or      ah,dl           ; set pixel value in byte
  19265.  
  19266.                  ror     dl,1            ; rotate pixel value
  19267.                  ror     dl,1
  19268.                  ror     dh,1            ; rotate bit mask
  19269.                  ror     dh,1
  19270.                  jnc     L14             ; jump if bit mask rotated to
  19271.                                          ;  leftmost pixel position
  19272.  
  19273.  ; bit mask not shifted out
  19274.  
  19275.                  or      di,di           ; test sign of d
  19276.                  jns     L12             ; jump if d >= 0
  19277.  
  19278.                  add     di,VARincr1     ; d := d + incr1
  19279.                  loop    L11
  19280.  
  19281.                  mov     es:[bx],ah      ; store remaining pixels in buffer
  19282.                  jmp     short Lexit
  19283.  
  19284.  L12:            add     di,VARincr2     ; d := d + incr2
  19285.                  mov     es:[bx],ah      ; update buffer
  19286.  
  19287.                  add     bx,si           ; increment y
  19288.                  xchg    si,VARleafincr  ; exchange interleave increment value
  19289.  
  19290.                  loop    L10
  19291.                  jmp     short Lexit
  19292.  
  19293.  ; bit mask shifted out
  19294.  
  19295.  L14:            mov     es:[bx],ah      ; update buffer
  19296.                  inc     bx              ; BX := offset of next byte
  19297.  
  19298.                  or      di,di           ; test sign of d
  19299.                  jns     L15             ; jump if non-negative
  19300.  
  19301.                  add     di,VARincr1     ; d := d + incr1
  19302.                  loop    L10
  19303.                  jmp     short Lexit
  19304.  
  19305.  
  19306.  L15:            add     di,VARincr2     ; d := d + incr2
  19307.  
  19308.                  add     bx,si           ; increment y
  19309.                  xchg    si,VARleafincr
  19310.  
  19311.                  loop    L10
  19312.                  jmp     short Lexit
  19313.  
  19314.  
  19315.  ; routine for dy > dx (slope > 1)       ; ES:BX -> video buffer
  19316.                                          ; CX = #pixels to draw
  19317.                                          ; DH = inverse bit mask
  19318.                                          ; DL = pixel value in proper position
  19319.                                          ; SI = buffer interleave increment
  19320.                                          ; DI = decision variable
  19321.  HiSlopeLine04:
  19322.  
  19323.  L21:            and     es:[bx],dh      ; zero pixel value in video buffer
  19324.                  or      es:[bx],dl      ; set pixel value in byte
  19325.  
  19326.                  add     bx,si           ; increment y
  19327.                  xchg    si,VARleafincr  ; exchange interleave increment value
  19328.  
  19329.  L22:            or      di,di           ; test sign of d
  19330.                  jns     L23             ; jump if d >= 0
  19331.  
  19332.                  add     di,VARincr1     ; d := d + incr1
  19333.                  loop    L21
  19334.  
  19335.                  jmp     short Lexit
  19336.  
  19337.  
  19338.  L23:            add     di,VARincr2     ; d := d + incr2
  19339.  
  19340.                  ror     dl,1            ; rotate pixel value
  19341.                  ror     dl,1
  19342.                  ror     dh,1            ; rotate bit mask
  19343.                  ror     dh,1
  19344.                  cmc                     ; cf set if bit mask not rotated to
  19345.                                          ;  leftmost pixel position
  19346.  
  19347.                  adc     bx,0            ; BX := offset of next byte
  19348.  
  19349.                  loop    L21
  19350.  
  19351.  
  19352.  Lexit:          pop     di              ; restore registers and return
  19353.                  pop     si
  19354.                  mov     sp,bp
  19355.                  pop     bp
  19356.                  ret
  19357.  
  19358.  _Line04         ENDP
  19359.  
  19360.  _TEXT           ENDS
  19361.  
  19362.  
  19363.  _DATA           SEGMENT word public 'DATA'
  19364.  
  19365.  PropagatedPixel db      00000000b       ; 0
  19366.                  db      01010101b       ; 1
  19367.                  db      10101010b       ; 2
  19368.                  db      11111111b       ; 3
  19369.  
  19370.  _DATA           ENDS
  19371.  
  19372.                  END
  19373.  
  19374.  \SAMPCODE\VIDEO\DEMO\C_1.ASM
  19375.  
  19376.                  TITLE   'Listing C-1'
  19377.                  NAME    VideoID
  19378.                  PAGE    55,132
  19379.  
  19380.  ;
  19381.  ; Name:         VideoID
  19382.  ;
  19383.  ; Function:     Detects the presence of various video subsystems and associat
  19384.  ;               monitors.
  19385.  ;
  19386.  ; Caller:       Microsoft C:
  19387.  ;
  19388.  ;                       void VideoID(VIDstruct);
  19389.  ;
  19390.  ;                       struct
  19391.  ;                       {
  19392.  ;                         char VideoSubsystem;
  19393.  ;                         char Display;
  19394.  ;                       }
  19395.  ;                               *VIDstruct[2];
  19396.  ;
  19397.  ;               Subsystem ID values:
  19398.  ;                                0  = (none)
  19399.  ;                                1  = MDA
  19400.  ;                                2  = CGA
  19401.  ;                                3  = EGA
  19402.  ;                                4  = MCGA
  19403.  ;                                5  = VGA
  19404.  ;                               80h = HGC
  19405.  ;                               81h = HGC+
  19406.  ;                               82h = Hercules InColor
  19407.  ;
  19408.  ;               Display types:   0  = (none)
  19409.  ;                                1  = MDA-compatible monochrome
  19410.  ;                                2  = CGA-compatible color
  19411.  ;                                3  = EGA-compatible color
  19412.  ;                                4  = PS/2-compatible monochrome
  19413.  ;                                5  = PS/2-compatible color
  19414.  ;
  19415.  ;
  19416.  ;       The values returned in VIDstruct[0].VideoSubsystem and
  19417.  ;       VIDstruct[0].Display indicate the currently active subsystem.
  19418.  ;
  19419.  
  19420.  ARGpVID         EQU     word ptr [bp+4] ; stack frame addressing
  19421.  
  19422.  
  19423.  VIDstruct       STRUC                   ; corresponds to C data structure
  19424.  
  19425.  Video0Type      DB      ?               ; first subsystem type
  19426.  Display0Type    DB      ?               ; display attached to first subsystem
  19427.  
  19428.  Video1Type      DB      ?               ; second subsystem type
  19429.  Display1Type    DB      ?               ; display attached to second subsyste
  19430.  
  19431.  VIDstruct       ENDS
  19432.  
  19433.  
  19434.  Device0         EQU     word ptr Video0Type[di]
  19435.  Device1         EQU     word ptr Video1Type[di]
  19436.  
  19437.  
  19438.  MDA             EQU     1               ; subsystem types
  19439.  CGA             EQU     2
  19440.  EGA             EQU     3
  19441.  MCGA            EQU     4
  19442.  VGA             EQU     5
  19443.  HGC             EQU     80h
  19444.  HGCPlus         EQU     81h
  19445.  InColor         EQU     82h
  19446.  
  19447.  MDADisplay      EQU     1               ; display types
  19448.  CGADisplay      EQU     2
  19449.  EGAColorDisplay EQU     3
  19450.  PS2MonoDisplay  EQU     4
  19451.  PS2ColorDisplay EQU     5
  19452.  
  19453.  TRUE            EQU     1
  19454.  FALSE           EQU     0
  19455.  
  19456.  
  19457.  DGROUP          GROUP   _DATA
  19458.  
  19459.  _TEXT           SEGMENT byte public 'CODE'
  19460.                  ASSUME  cs:_TEXT,ds:DGROUP
  19461.  
  19462.                  PUBLIC  _VideoID
  19463.  _VideoID        PROC    near
  19464.  
  19465.                  push    bp              ; preserve caller registers
  19466.                  mov     bp,sp
  19467.                  push    si
  19468.                  push    di
  19469.  
  19470.  ; initialize the data structure that will contain the results
  19471.  
  19472.                  mov     di,ARGpVID      ; DS:DI -> start of data structure
  19473.  
  19474.                  mov     Device0,0       ; zero these variables
  19475.                  mov     Device1,0
  19476.  
  19477.  ; look for the various subsystems using the subroutines whose addresses are
  19478.  ;  tabulated in TestSequence; each subroutine sets flags in TestSequence
  19479.  ;  to indicate whether subsequent subroutines need to be called
  19480.  
  19481.                  mov     cx,NumberOfTests
  19482.                  mov     si,offset DGROUP:TestSequence
  19483.  
  19484.  L01:            lodsb                   ; AL := flag
  19485.                  test    al,al
  19486.                  lodsw                   ; AX := subroutine address
  19487.                  jz      L02             ; skip subroutine if flag is false
  19488.  
  19489.                  push    si
  19490.                  push    cx
  19491.                  call    ax              ; call subroutine to detect subsystem
  19492.                  pop     cx
  19493.                  pop     si
  19494.  
  19495.  L02:            loop    L01
  19496.  
  19497.  ; determine which subsystem is active
  19498.  
  19499.                  call    FindActive
  19500.  
  19501.                  pop     di              ; restore caller registers and return
  19502.                  pop     si
  19503.                  mov     sp,bp
  19504.                  pop     bp
  19505.                  ret
  19506.  
  19507.  _VideoID        ENDP
  19508.  
  19509.  
  19510.  ;
  19511.  ; FindPS2
  19512.  ;
  19513.  ;       This subroutine uses INT 10H function 1Ah to determine the video BIOS
  19514.  ;        Display Combination Code (DCC) for each video subsystem present.
  19515.  ;
  19516.  
  19517.  FindPS2         PROC    near
  19518.  
  19519.                  mov     ax,1A00h
  19520.                  int     10h             ; call video BIOS for info
  19521.  
  19522.                  cmp     al,1Ah
  19523.                  jne     L13             ; exit if function not supported (i.e
  19524.                                          ;  no MCGA or VGA in system)
  19525.  
  19526.  ; convert BIOS DCCs into specific subsystems & displays
  19527.  
  19528.                  mov     cx,bx
  19529.                  xor     bh,bh           ; BX := DCC for active subsystem
  19530.  
  19531.                  or      ch,ch
  19532.                  jz      L11             ; jump if only one subsystem present
  19533.  
  19534.                  mov     bl,ch           ; BX := inactive DCC
  19535.                  add     bx,bx
  19536.                  mov     ax,[bx+offset DGROUP:DCCtable]
  19537.  
  19538.                  mov     Device1,ax
  19539.  
  19540.                  mov     bl,cl
  19541.                  xor     bh,bh           ; BX := active DCC
  19542.  
  19543.  L11:            add     bx,bx
  19544.                  mov     ax,[bx+offset DGROUP:DCCtable]
  19545.  
  19546.                  mov     Device0,ax
  19547.  
  19548.  ; reset flags for subsystems that have been ruled out
  19549.  
  19550.                  mov     byte ptr CGAflag,FALSE
  19551.                  mov     byte ptr EGAflag,FALSE
  19552.                  mov     byte ptr Monoflag,FALSE
  19553.  
  19554.                  lea     bx,Video0Type[di]  ; if the BIOS reported an MDA ...
  19555.                  cmp     byte ptr [bx],MDA
  19556.                  je      L12
  19557.  
  19558.                  lea     bx,Video1Type[di]
  19559.                  cmp     byte ptr [bx],MDA
  19560.                  jne     L13
  19561.  
  19562.  L12:            mov     word ptr [bx],0    ; ... Hercules can't be ruled out
  19563.                  mov     byte ptr Monoflag,TRUE
  19564.  
  19565.  L13:            ret
  19566.  
  19567.  FindPS2         ENDP
  19568.  
  19569.  
  19570.  ;
  19571.  ; FindEGA
  19572.  ;
  19573.  ; Look for an EGA.  This is done by making a call to an EGA BIOS function
  19574.  ;  which doesn't exist in the default (MDA, CGA) BIOS.
  19575.  
  19576.  FindEGA         PROC    near            ; Caller:       AH = flags
  19577.                                          ; Returns:      AH = flags
  19578.                                          ;               Video0Type and
  19579.                                          ;                Display0Type updated
  19580.  
  19581.                  mov     bl,10h          ; BL := 10h (return EGA info)
  19582.                  mov     ah,12h          ; AH := INT 10H function number
  19583.                  int     10h             ; call EGA BIOS for info
  19584.                                          ; if EGA BIOS is present,
  19585.                                          ;  BL <> 10H
  19586.                                          ;  CL = switch setting
  19587.                  cmp     bl,10h
  19588.                  je      L22             ; jump if EGA BIOS not present
  19589.  
  19590.                  mov     al,cl
  19591.                  shr     al,1            ; AL := switches/2
  19592.                  mov     bx,offset DGROUP:EGADisplays
  19593.                  xlat                    ; determine display type from switche
  19594.                  mov     ah,al           ; AH := display type
  19595.                  mov     al,EGA          ; AL := subystem type
  19596.                  call    FoundDevice
  19597.  
  19598.                  cmp     ah,MDADisplay
  19599.                  je      L21             ; jump if EGA has a monochrome displa
  19600.  
  19601.                  mov     CGAflag,FALSE   ; no CGA if EGA has color display
  19602.                  jmp     short L22
  19603.  
  19604.  L21:            mov     Monoflag,FALSE  ; EGA has a mono display, so MDA and
  19605.                                          ;  Hercules are ruled out
  19606.  L22:            ret
  19607.  
  19608.  FindEGA         ENDP
  19609.  
  19610.  
  19611.  ;
  19612.  ; FindCGA
  19613.  ;
  19614.  ;       This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H.
  19615.  ;
  19616.  
  19617.  FindCGA         PROC    near            ; Returns:      VIDstruct updated
  19618.  
  19619.                  mov     dx,3D4h         ; DX := CRTC address port
  19620.                  call    Find6845
  19621.                  jc      L31             ; jump if not present
  19622.  
  19623.                  mov     al,CGA
  19624.                  mov     ah,CGADisplay
  19625.                  call    FoundDevice
  19626.  
  19627.  L31:            ret
  19628.  
  19629.  FindCGA         ENDP
  19630.  
  19631.  
  19632.  ;
  19633.  ; FindMono
  19634.  ;
  19635.  ;       This is done by looking for the MDA's 6845 CRTC at I/O port 3B4H.  If
  19636.  ;       a 6845 is found, the subroutine distinguishes between an MDA
  19637.  ;       and a Hercules adapter by monitoring bit 7 of the CRT Status byte.
  19638.  ;       This bit changes on Hercules adapters but does not change on an MDA.
  19639.  ;
  19640.  ;       The various Hercules adapters are identified by bits 4 through 6 of
  19641.  ;       the CRT Status value:
  19642.  ;
  19643.  ;               000b = HGC
  19644.  ;               001b = HGC+
  19645.  ;               101b = InColor card
  19646.  ;
  19647.  
  19648.  FindMono        PROC    near            ; Returns:      VIDstruct updated
  19649.  
  19650.                  mov     dx,3B4h         ; DX := CRTC address port
  19651.                  call    Find6845
  19652.                  jc      L44             ; jump if not present
  19653.  
  19654.                  mov     dl,0BAh         ; DX := 3BAh (status port)
  19655.                  in      al,dx
  19656.                  and     al,80h
  19657.                  mov     ah,al           ; AH := bit 7 (vertical sync on HGC)
  19658.  
  19659.                  mov     cx,8000h        ; do this 32768 times
  19660.  L41:            in      al,dx
  19661.                  and     al,80h          ; isolate bit 7
  19662.                  cmp     ah,al
  19663.                  loope   L41             ; wait for bit 7 to change
  19664.  
  19665.                  jne     L42             ; if bit 7 changed, it's a Hercules
  19666.  
  19667.                  mov     al,MDA          ; if bit 7 didn't change, it's an MDA
  19668.                  mov     ah,MDADisplay
  19669.                  call    FoundDevice
  19670.                  jmp     short L44
  19671.  
  19672.  L42:            in      al,dx
  19673.                  mov     dl,al           ; DL := value from status port
  19674.  
  19675.                  mov     ah,MDADisplay   ; assume it's a monochrome display
  19676.  
  19677.                  mov     al,HGC          ; look for an HGC
  19678.                  and     dl,01110000b    ; mask off bits 4 thru 6
  19679.                  jz      L43
  19680.  
  19681.                  mov     al,HGCPlus      ; look for an HGC+
  19682.                  cmp     dl,00010000b
  19683.                  je      L43             ; jump if it's an HGC+
  19684.  
  19685.                  mov     al,InColor      ; it's an InColor card
  19686.                  mov     ah,EGAColorDisplay
  19687.  
  19688.  L43:            call    FoundDevice
  19689.  
  19690.  L44:            ret
  19691.  
  19692.  FindMono        ENDP
  19693.  
  19694.  
  19695.  ;
  19696.  ; Find6845
  19697.  ;
  19698.  ;       This routine detects the presence of the CRTC on a MDA, CGA or HGC.
  19699.  ;       The technique is to write and read register 0Fh of the chip (cursor
  19700.  ;       low).  If the same value is read as written, assume the chip is
  19701.  ;       present at the specified port addr.
  19702.  ;
  19703.  
  19704.  Find6845        PROC    near            ; Caller:       DX = port addr
  19705.                                          ; Returns:      cf set if not present
  19706.                  mov     al,0Fh
  19707.                  out     dx,al           ; select 6845 reg 0Fh (Cursor Low)
  19708.                  inc     dx
  19709.                  in      al,dx           ; AL := current Cursor Low value
  19710.                  mov     ah,al           ; preserve in AH
  19711.                  mov     al,66h          ; AL := arbitrary value
  19712.                  out     dx,al           ; try to write to 6845
  19713.  
  19714.                  mov     cx,100h
  19715.  L51:            loop    L51             ; wait for 6845 to respond
  19716.  
  19717.                  in      al,dx
  19718.                  xchg    ah,al           ; AH := returned value
  19719.                                          ; AL := original value
  19720.                  out     dx,al           ; restore original value
  19721.  
  19722.                  cmp     ah,66h          ; test whether 6845 responded
  19723.                  je      L52             ; jump if it did (cf is reset)
  19724.  
  19725.                  stc                     ; set carry flag if no 6845 present
  19726.  
  19727.  L52:            ret
  19728.  
  19729.  Find6845        ENDP
  19730.  
  19731.  
  19732.  ;
  19733.  ; FindActive
  19734.  ;
  19735.  ;       This subroutine stores the currently active device as Device0.  The
  19736.  ;       current video mode determines which subsystem is active.
  19737.  ;
  19738.  
  19739.  FindActive      PROC    near
  19740.  
  19741.                  cmp     word ptr Device1,0
  19742.                  je      L63                     ; exit if only one subsystem
  19743.  
  19744.                  cmp     Video0Type[di],4        ; exit if MCGA or VGA present
  19745.                  jge     L63                     ;  (INT 10H function 1AH
  19746.                  cmp     Video1Type[di],4        ;  already did the work)
  19747.                  jge     L63
  19748.  
  19749.                  mov     ah,0Fh
  19750.                  int     10h                     ; AL := current BIOS video mo
  19751.  
  19752.                  and     al,7
  19753.                  cmp     al,7                    ; jump if monochrome
  19754.                  je      L61                     ;  (mode 7 or 0Fh)
  19755.  
  19756.                  cmp     Display0Type[di],MDADisplay
  19757.                  jne     L63                     ; exit if Display0 is color
  19758.                  jmp     short L62
  19759.  
  19760.  L61:            cmp     Display0Type[di],MDADisplay
  19761.                  je      L63                     ; exit if Display0 is monochr
  19762.  
  19763.  L62:            mov     ax,Device0              ; make Device0 currently acti
  19764.                  xchg    ax,Device1
  19765.                  mov     Device0,ax
  19766.  
  19767.  L63:            ret
  19768.  
  19769.  FindActive      ENDP
  19770.  
  19771.  
  19772.  ;
  19773.  ; FoundDevice
  19774.  ;
  19775.  ;       This routine updates the list of subsystems.
  19776.  ;
  19777.  
  19778.  FoundDevice     PROC    near                    ; Caller:    AH = display #
  19779.                                                  ;            AL = subsystem #
  19780.                                                  ; Destroys:  BX
  19781.                  lea     bx,Video0Type[di]
  19782.                  cmp     byte ptr [bx],0
  19783.                  je      L71                     ; jump if 1st subsystem
  19784.  
  19785.                  lea     bx,Video1Type[di]       ; must be 2nd subsystem
  19786.  
  19787.  L71:            mov     [bx],ax                 ; update list entry
  19788.                  ret
  19789.  
  19790.  FoundDevice     ENDP
  19791.  
  19792.  _TEXT           ENDS
  19793.  
  19794.  
  19795.  _DATA           SEGMENT word public 'DATA'
  19796.  
  19797.  EGADisplays     DB      CGADisplay      ; 0000b, 0001b  (EGA switch values)
  19798.                  DB      EGAColorDisplay ; 0010b, 0011b
  19799.                  DB      MDADisplay      ; 0100b, 0101b
  19800.                  DB      CGADisplay      ; 0110b, 0111b
  19801.                  DB      EGAColorDisplay ; 1000b, 1001b
  19802.                  DB      MDADisplay      ; 1010b, 1011b
  19803.  
  19804.  DCCtable        DB      0,0             ; translate table for INT 10h func 1A
  19805.                  DB      MDA,MDADisplay
  19806.                  DB      CGA,CGADisplay
  19807.                  DB      0,0
  19808.                  DB      EGA,EGAColorDisplay
  19809.                  DB      EGA,MDADisplay
  19810.                  DB      0,0
  19811.                  DB      VGA,PS2MonoDisplay
  19812.                  DB      VGA,PS2ColorDisplay
  19813.                  DB      0,0
  19814.                  DB      MCGA,EGAColorDisplay
  19815.                  DB      MCGA,PS2MonoDisplay
  19816.                  DB      MCGA,PS2ColorDisplay
  19817.  
  19818.  TestSequence    DB      TRUE            ; this list of flags and addresses
  19819.                  DW      FindPS2         ;  determines the order in which this
  19820.                                          ;  program looks for the various
  19821.  EGAflag         DB      TRUE            ;  subsystems
  19822.                  DW      FindEGA
  19823.  
  19824.  CGAflag         DB      TRUE
  19825.                  DW      FindCGA
  19826.  
  19827.  Monoflag        DB      TRUE
  19828.                  DW      FindMono
  19829.  
  19830.  NumberOfTests   EQU     ($-TestSequence)/3
  19831.  
  19832.  _DATA           ENDS
  19833.  
  19834.                  END
  19835.  
  19836.  
  19837.