home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / OWLSCR / PCEVGA.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-11  |  12.8 KB  |  462 lines

  1. /*
  2.     pcevga.c
  3.  
  4.     % EGA and VGA support
  5.  
  6.     7/27/88  by Ted.
  7.  
  8.     OWL-PC 1.2
  9.     Copyright (c) 1988, 1989 by Oakland Group, Inc.
  10.     ALL RIGHTS RESERVED.
  11.  
  12.     Revision History:
  13.     -----------------
  14.      8/31/88 Ted    Added actual ega graphics code.
  15.      4/14/89 ted    Added palette poking function.
  16.      4/20/89 ted    Fixed setcolmap loop counts from 16 to cmap->nentries.
  17.      5/06/89 ted    Added colormap initialization.
  18.      6/15/89 Ted    Added PlotText func.
  19.      6/28/89 ted    removed dispid and changed mmwidth/height to x/ypixperm.
  20.      7/10/89 ted    installed new text-plotting approach.
  21.      7/12/89 ted    Added OSTATIC's and '_func' macros.
  22.      8/22/89 ted    Added fontdesc_struct elements to def_font initialization.
  23.      9/06/89 ted    Added pragma to turn off MS -Oi optimization.
  24.  
  25.     11/05/89 ted    Added pc_roundbyte calls for scrbox x byte alignment.
  26.     12/04/89 jmd    now uses window cursor color
  27.      3/28/90 jmd    ansi-fied
  28.      4/12/90 ted    Changed logic to evade MC5 compiler bug; removed pragma.
  29.      6/06/90 ted    Added planemask arg to ram_copy stuff for EVGA plane drawing.
  30. */
  31.  
  32. #include "pcpriv.h"
  33.  
  34. #define XORBIT        0x80
  35.  
  36. OSTATIC void DIGPRIV evga_setfuncs(dig_struct *digp);
  37.  
  38. OSTATIC pc_setinfo_func            (evga_setinfo);
  39. OSTATIC dig_dControl_func        (evga_dControl);
  40. OSTATIC dig_pDrawCursor_func    (evga_DrawCursor);
  41. OSTATIC dig_pClear_func            (evga_Clear);
  42. OSTATIC dig_pDrawPixmap_func    (evga_DrawPixmap);
  43. OSTATIC dig_pReadPixmap_func    (evga_ReadPixmap);
  44. OSTATIC dig_pScrollBoxVt_func    (evga_ScrollBoxVt);
  45. OSTATIC dig_pScrollBoxHz_func    (evga_ScrollBoxHz);
  46. OSTATIC ramplanecopy_func         (evga_segtomem);
  47. OSTATIC ramplanecopy_func         (evga_memtoseg);
  48.  
  49. OSTATIC void DIGPRIV ega_setcolmap(ocolmap_type cmap);
  50. OSTATIC void DIGPRIV vga_setcolmap(ocolmap_type cmap);
  51. /* -------------------------------------------------------------------------- */
  52.  
  53. boolean pc_ModeD(dig_struct *digp)
  54. {
  55.     return(pc_OpenEVGA(digp, 0x0D));
  56. }
  57.  
  58. boolean pc_ModeE(dig_struct *digp)
  59. {
  60.     return(pc_OpenEVGA(digp, 0x0E));
  61. }
  62.  
  63. boolean pc_ModeF(dig_struct *digp)
  64. {
  65.     return(pc_OpenEVGA(digp, 0x0F));
  66. }
  67.  
  68. boolean pc_Mode10(dig_struct *digp)
  69. {
  70.     return(pc_OpenEVGA(digp, 0x10));
  71. }
  72.  
  73. boolean pc_Mode11(dig_struct *digp)
  74. {
  75.     return(pc_OpenEVGA(digp, 0x11));
  76. }
  77.  
  78. boolean pc_Mode12(dig_struct *digp)
  79. {
  80.     return(pc_OpenEVGA(digp, 0x12));
  81. }
  82. /* -------------------------------------------------------------------------- */
  83.  
  84. boolean DIGPRIV pc_OpenEVGA(dig_struct *digp, int mode)
  85. {
  86.     if (!pc_OpenDIG(digp, mode, evga_setinfo)) {
  87.         return(FALSE);
  88.     }
  89.     evga_setfuncs(digp);
  90.     return(TRUE);
  91. }
  92. /* -------------------------------------------------------------------------- */
  93.  
  94. static void DIGPRIV evga_setfuncs(dig_struct *digp)
  95. {
  96.     pc_setgfuncs(digp);        /* Set the standard ptrs & vars for pc graphics */
  97.  
  98.     digp->dControl      = evga_dControl;
  99.  
  100.     digp->pDrawCursor    = evga_DrawCursor;
  101.     digp->pClear        = evga_Clear;
  102.     digp->pScrollBoxVt    = evga_ScrollBoxVt;
  103.     digp->pScrollBoxHz    = evga_ScrollBoxHz;
  104.  
  105.     digp->pDrawPixmap    = evga_DrawPixmap;
  106.     digp->pReadPixmap    = evga_ReadPixmap;
  107. }
  108. /* -------------------------------------------------------------------------- */
  109.  
  110. static dispinfo_struct evgainfo = {
  111.     {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0},    /* devname */
  112.     0x0E,            /* mode */
  113.     0, 0,            /* xpixperm, ypixperm */
  114.     &pcdatastruc.dmspace, /* dispmap */
  115.     VID_EVGAADDR,    /* dispaddr */
  116.     80,                /* bytewidth */
  117.     0,                /* ileave */
  118.     0,                /* ilsize */
  119.     4,                /* nplanes */
  120.     1,                /* pixbits */
  121.  
  122.     16L,            /* ncolors */
  123.     DTYPE_MAPCOLOR,    /* color type */
  124.     (ocolmap_type)&pcdefcmap,     /* defcolmap */
  125.  
  126.     FALSE,            /* hardcursor */
  127.     BO_LSBYTFIRST,    /* byteorder */
  128.     {                /* def_font */
  129.         0,                /* fontid */
  130.         { 8, 8, 0, 0,0,0, 0 },        /* real: width, height, style, etc. */
  131.         { 8, 8, 0, 0,0,0, 0 }        /* req:  width, height, style, etc. */
  132.     }
  133. };
  134. /* -------------------------------------------------------------------------- */
  135.  
  136. static boolean DIGPRIV evga_setinfo(int mode)
  137. {
  138. /* Set up the device info structure */
  139.     memmove(&pcdata->info, &evgainfo, sizeof(dispinfo_struct));
  140.     pc_initdispmap(640, 200);
  141.  
  142.     pcdata->info.mode = mode;
  143.  
  144. /* Pre-set default values */
  145.     pchdata->xmouscale = 1;
  146.  
  147.     /* Set up stuff for font plotter */
  148.     pcdata->attrcols = pc_attrcols;
  149.     pcdata->plotchar = pc_evgaplotchar;
  150.  
  151.     switch(mode) {
  152.     case 0x0D:
  153.         pchdata->xmouscale = 2;
  154.         pcdata->info.dispmap->width = 320;
  155.         pcdata->info.bytewidth = 40;
  156.         strncpy(pcdata->info.devname, "IBM PC EGA LORES", DEVNAMELEN-1);
  157.         break;
  158.     case 0x0E:
  159.         strncpy(pcdata->info.devname, "IBM PC EGA MEDRES", DEVNAMELEN-1);
  160.         break;
  161.     case 0x0F:
  162.         pcdata->info.dispmap->height = 350;
  163.         pcdata->info.nplanes = 2;
  164.         pcdata->info.ncolors = 4L;
  165.         strncpy(pcdata->info.devname, "IBM PC EGA MONO", DEVNAMELEN-1);
  166.         pcdata->info.defcolmap = (ocolmap_type)&pcdefmcmap;
  167.         pcdata->info.def_font.real.height = 14;
  168.         break;
  169.     case 0x10:
  170.         pcdata->info.dispmap->height = 350;
  171.         strncpy(pcdata->info.devname, "IBM PC EGA HIRES", DEVNAMELEN-1);
  172.         pcdata->info.def_font.real.height = 14;
  173.         break;
  174.     case 0x11:
  175.         pcdata->info.dispmap->height = 480;
  176.         pcdata->info.nplanes = 1;
  177.         pcdata->info.ncolors = 2L;
  178.         strncpy(pcdata->info.devname, "IBM PC VGA MONO", DEVNAMELEN-1);
  179.         pcdata->info.def_font.real.height = 16;
  180.         pcdata->info.defcolmap = (ocolmap_type)&pcdefmcmap;
  181.         pcdata->plotchar = pc_1bitplotchar;
  182.         break;
  183.     case 0x12:
  184.         pcdata->info.dispmap->height = 480;
  185.         strncpy(pcdata->info.devname, "IBM PC VGA HIRES", DEVNAMELEN-1);
  186.         pcdata->info.def_font.real.height = 16;
  187.         break;
  188.     }
  189.     pcdata->info.devname[DEVNAMELEN-1] = '\0';
  190.  
  191.     pchdata->ymouscale = 1;
  192.  
  193.     return(TRUE);
  194. }
  195. /* -------------------------------------------------------------------------- */
  196.  
  197. static int evga_dControl(dig_dcmsg msg, VOID *indata, VOID *outdata)
  198. {
  199.     switch (msg) {
  200.     case DC_SETCOLMAP:
  201.         if (pcdata->info.dispmap->height <= 350) {
  202.             ega_setcolmap((ocolmap_type) indata);
  203.         }
  204.         else vga_setcolmap((ocolmap_type) indata);
  205.         break;
  206.     case DC_GETCOLMAP:
  207.         ocolmap_set((ocolmap_type) outdata, pcdata->colmap);
  208.         break;
  209.     default:
  210.         return(pc_dControl(msg, indata, outdata));
  211.     }
  212.     return(TRUE);
  213. }
  214. /* -------------------------------------------------------------------------- */
  215.  
  216. static void evga_DrawCursor(ptd_struct *ptd, cursortype ctype)
  217. {
  218.     win_type win;
  219.     opbox cursbox;
  220.     opbox *opboxp;
  221.  
  222.     if (ctype != CURSOR_NONE) {
  223.         win = ptd->win;
  224.         dig_getcursbox(win, ctype, &cursbox);
  225.         cursbox.xmax += 1;
  226.         if (opbox_clipbox(ptd->relboxp, &cursbox)) {
  227.             opboxp = ptd->relboxp;
  228.             ptd->relboxp = &cursbox;
  229.             evga_Clear(ptd, win_curscolor(win));
  230.             ptd->relboxp = opboxp;
  231.         }
  232.     }
  233. }
  234. /* -------------------------------------------------------------------------- */
  235. /* EGA/VGA register control functions */
  236. /* -------------------------------------------------------------------------- */
  237. #define GCADDR        0x3CE
  238. #define GSADDR        0x3C4
  239. #define MODEREG        0x00
  240.  
  241. /* Disable Set/Reset / Disable Data Rotate / Unmask Writes */
  242. #define setup()                    \
  243.         (outp(GCADDR, 1), outp(GCADDR+1, 0x00),    \
  244.          outp(GCADDR, 3), outp(GCADDR+1, 0x00),    \
  245.          outp(GCADDR, 8), outp(GCADDR+1, 0xFF))
  246. #define planewrite()        (setup(), writemode(0))
  247. #define planeread()            writemode(1)
  248.  
  249. #define wplaneselect(plane)    (outp(GSADDR, 2), outp(GSADDR+1, 0x01 << (plane)))
  250. #define wallplanes()        (outp(GSADDR, 2), outp(GSADDR+1, 0x0F))
  251. #define rplaneselect(plane)    (outp(GCADDR, 4), outp(GCADDR+1, (byte)(plane)))
  252. #define writemode(mode)        (outp(GCADDR, 5), outp(GCADDR+1, MODEREG | (mode)))
  253. /* -------------------------------------------------------------------------- */
  254.  
  255. static void evga_Clear(ptd_struct *ptd, opixval color)
  256. {
  257.     writemode(2);
  258.     ram_Clear(ptd, color);
  259.     writemode(0);
  260. }
  261. /* -------------------------------------------------------------------------- */
  262.  
  263. static void evga_ScrollBoxVt(ptd_struct *ptd, opcoord nrows)
  264. {
  265.     writemode(1);
  266.     ram_ScrollBoxVt(ptd, nrows);
  267.     writemode(0);
  268. }
  269. /* -------------------------------------------------------------------------- */
  270.  
  271. static void evga_ScrollBoxHz(ptd_struct *ptd, opcoord ncols)
  272. {
  273.     writemode(1);
  274.     ram_ScrollBoxHz(ptd, ncols);
  275.     writemode(0);
  276. }
  277. /* -------------------------------------------------------------------------- */
  278.  
  279. static void evga_DrawPixmap(ptd_struct *ptd, pmap_type pmap, opbox *pmboxp)
  280. /*
  281.     Copy from the portion of pmap that is inside 'pmboxp' to the
  282.     display inside of 'ptd->relboxp'.
  283. */
  284. {
  285.     opbox scrbox;
  286.     opcoord pmx, pmy;
  287.     unsigned planemask;
  288.  
  289.     if (copypm_clip(ptd, pmap, pmboxp, &scrbox, &pmx, &pmy)) {
  290.         if (pc_roundbytex(&scrbox, &pmx)) {
  291.  
  292.             planewrite();
  293.  
  294.             if (pc_nplanes() == 1) {
  295.                 ram_copypm(&scrbox, pmap, pmx, pmy, ram_memtoseg, 1);
  296.             }
  297.             else {
  298.                 if (ptd->emsgdata != NULL) {
  299.                      planemask = (unsigned) (*((opixval *) ptd->emsgdata));
  300.                 }
  301.                 else planemask = (unsigned) -1;
  302.  
  303.                 ram_copypm(&scrbox, pmap, pmx, pmy,
  304.                             (ramcopy_fptr) evga_memtoseg, planemask);
  305.                 wallplanes();
  306.             }
  307.         }
  308.     }
  309. }
  310. /* -------------------------------------------------------------------------- */
  311.  
  312. static void DIGPRIV evga_memtoseg(
  313.     unsigned segm, unsigned segoffs,
  314.     byte *membuf, unsigned bwidth, unsigned memoffs,
  315.     unsigned planemask)
  316. {
  317.     int iplane;
  318.     unsigned ipmask;
  319.  
  320.     for (iplane = 0, ipmask = 1; iplane < pc_nplanes(); iplane++,ipmask <<= 1) {
  321.         if (pc_nplanes() == 2) {
  322.             wplaneselect(iplane << 1);    /* Mode F: planes 0,2 */
  323.         }
  324.         else wplaneselect(iplane);
  325.  
  326.         if (ipmask & planemask) {
  327.             ram_memtoseg(segm, segoffs,
  328.                         ((byte **) membuf)[iplane] + memoffs,
  329.                         bwidth);
  330.         }
  331.         else {
  332.             ram_segwordset(segm, segoffs, bwidth, 0);
  333.         }
  334.     }
  335.     writemode(0);
  336. }
  337. /* -------------------------------------------------------------------------- */
  338.  
  339. static void evga_ReadPixmap(ptd_struct *ptd, pmap_type pmap, opbox *pmboxp)
  340. /*
  341.     Copy into the portion of pmap that is inside 'pmboxp' from the
  342.     display inside of 'ptd->relboxp'.
  343. */
  344. {
  345.     opbox scrbox;
  346.     opcoord pmx, pmy;
  347.  
  348.     if (copypm_clip(ptd, pmap, pmboxp, &scrbox, &pmx, &pmy)) {
  349.         if (pc_roundbytex(&scrbox, &pmx)) {
  350.  
  351.             planeread();
  352.  
  353.             if (pc_nplanes() == 1) {
  354.                 rplaneselect(0);
  355.                 ram_copypm(&scrbox, pmap, pmx, pmy, ram_segtomem, 1);
  356.             }
  357.             else {
  358.                 ram_copypm(&scrbox, pmap, pmx, pmy, (ramcopy_fptr) evga_segtomem, (unsigned) -1);
  359.                 wallplanes();
  360.             }
  361.             writemode(0);
  362.         }
  363.     }
  364. }
  365. /* -------------------------------------------------------------------------- */
  366.  
  367. static void DIGPRIV evga_segtomem(
  368.     unsigned segm, unsigned segoffs,
  369.     byte *membuf, unsigned bwidth, unsigned memoffs,
  370.     unsigned planemask)
  371. {
  372.     int iplane;
  373.  
  374.     oak_notused(planemask);        /* It's only used for drawing pixmaps */
  375.  
  376.     for (iplane = 0; iplane < pc_nplanes(); iplane++) {
  377.         if (pc_nplanes() == 2) {
  378.             rplaneselect(iplane << 1);    /* Mode F: planes 0,2 */
  379.         }
  380.         else rplaneselect(iplane);
  381.  
  382.         ram_segtomem(segm, segoffs, ((byte **)membuf)[iplane] + memoffs, bwidth);
  383.     }
  384. }
  385. /* -------------------------------------------------------------------------- */
  386.  
  387. static void DIGPRIV ega_setcolmap(ocolmap_type cmap)
  388. {
  389.     OREGS regs;
  390.     byte r, g, b, palval;
  391.     int i, ipix;
  392.  
  393.     if (cmap == NULL) {
  394.         return;
  395.     }
  396.     /* From cmap, set the rgb vals for the appropriate regs */
  397.     /* as nearly as possible */
  398.     for (i = 0; i < cmap->nentries; i++) {
  399.         ipix = cmap->firstpix + i;
  400.         if (ipix > 16) break;
  401.  
  402.         /* construct the color (use only hi 2 bits of each rgb level) */
  403.         r = ocolmap_pixred(cmap, ipix) >> 1;
  404.         g = ocolmap_pixgreen(cmap, ipix) >> 2;
  405.         b = ocolmap_pixblue(cmap, ipix) >> 3;
  406.         palval = ((b >> 4) & 1) | ((g >> 4) & 2) | ((r >> 4) & 4) |
  407.                   (b & 8)        |  (g & 16)         |  (r & 32);
  408.  
  409.         /* set the palette entry */
  410.         regs.x.ax = 0x1000;
  411.  
  412.         regs.h.bl = (byte)i;
  413.         regs.h.bh = palval;
  414.  
  415.         oakint86(BIOS_VIDINT, ®s);
  416.  
  417.     /* Copy the info into our colmap copy */
  418.         ocolmap_setpixrgb(pcdata->colmap, ipix,
  419.                 (r << 1)& 0xC0 +63, (g << 2)& 0xC0 +63, (b << 3)& 0xC0 +63);
  420.     }
  421. }
  422. /* -------------------------------------------------------------------------- */
  423.  
  424. static void DIGPRIV vga_setcolmap(ocolmap_type cmap)
  425. {
  426.     OREGS regs;
  427.     byte palregs[17];
  428.     int i, ipix;
  429.  
  430.     if (cmap == NULL) {
  431.         return;
  432.     }
  433.     /* set the register block selector mode and value to 0,0 */
  434.     /* assume mode 0, block 0 */
  435.  
  436.     /* read pal regs */
  437.     regs.x.ax = 0x1009;            /* int 10h, funtion 10.09: get palette regs */
  438.     regs.a.esdx = palregs;
  439.     oakint86es(BIOS_VIDINT, ®s, 17);
  440.  
  441.     /* from cmap, set the rgb vals for the appropriate regs */
  442.     for (i = 0; i < cmap->nentries; i++) {
  443.         ipix = cmap->firstpix + i;
  444.         if (ipix > 16) break;
  445.  
  446.         /* set the palette entry's rgb val */
  447.         regs.x.ax = 0x1010;
  448.         regs.x.bx = palregs[ipix];
  449.         regs.h.dh = ocolmap_pixred(cmap, ipix) >> 2;
  450.         regs.h.ch = ocolmap_pixgreen(cmap, ipix) >> 2;
  451.         regs.h.cl = ocolmap_pixblue(cmap, ipix) >> 2;
  452.  
  453.     /* Copy the info into our colmap copy */
  454.         ocolmap_setpixrgb(pcdata->colmap, ipix,
  455.                 (regs.h.dh << 2)+3, (regs.h.ch << 2)+3, (regs.h.cl << 2)+3);
  456.  
  457.         oakint86(BIOS_VIDINT, ®s);
  458.     }
  459. }
  460. /* -------------------------------------------------------------------------- */
  461.  
  462.