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

  1. /*
  2.     pcmode.c
  3.  
  4.     % pc_ mode routines
  5.  
  6.     7/9/88  by Ted.
  7.  
  8.     OWL-PC 1.2
  9.     Copyright (c) 1988, by Oakland Group, Inc.
  10.     ALL RIGHTS RESERVED.
  11.  
  12.     Revision History:
  13.     -----------------
  14.      1/31/89 ted    Changed pc_ModeSupport so it supports mode 7 even when an
  15.                     EGA/VGA is installed.
  16.      6/29/89 ted    Converted pcinfo.asm to C; moved it here from pcinfo.asm.
  17.      7/12/89 ted    Added OSTATIC's and '_func' macros.
  18.      7/17/89 ted    Fixed newbios_modesupport: modebyte = 40 +, not 0x40 +.
  19.      8/01/89 ted    Moved pc_init/restoremode to pcdisp.c.
  20.  
  21.      9/29/89 jsm    Fixed CGA mode 0 and 1 bug - as detailed by TED   
  22.      3/28/90 jmd    ansi-fied
  23.      6/07/90 ted    Added comments in ram_testword and cursport_test.
  24.      6/22/90 ted    added "void"s to no-parameter functions per ansii.
  25.     10/17/90 ted    added cursport_test & EGA mono test to pc_IsHerc().
  26.     12/07/90 jsm/ted changed newbios_modesupport to return a 0 or 1 (not a bit mask).
  27. */
  28.  
  29. #include "pcpriv.h"
  30.  
  31. OSTATIC void     DIGPRIV pc_sethflag(byte vf);
  32. OSTATIC boolean DIGPRIV ega_ismono(byte inbh);
  33. OSTATIC boolean DIGPRIV ega_modesupport(int mode);
  34. OSTATIC boolean DIGPRIV newbios(void);
  35. OSTATIC boolean DIGPRIV newbios_modesupport(int mode);
  36. OSTATIC boolean DIGPRIV vga_getinfo(byte *buf);
  37. OSTATIC boolean DIGPRIV ram_testword(unsigned seg, unsigned offs);
  38. OSTATIC boolean DIGPRIV cursport_test(int port);
  39.  
  40. /* -------------------------------------------------------------------------- */
  41.  
  42. void pc_SetMode(int mode)
  43. /*
  44.     Sets the current video mode of the display adapter to the given mode. 
  45.     Clears the screen in the new mode.
  46. */
  47. {
  48.     OREGS regs;
  49.     
  50.     switch (mode) {
  51.     default:
  52.         if (mode == 0x07 || mode == 0x0F) {
  53.             pc_sethflag(PCHFLAG_MONO);
  54.             if (pc_IsHerc()) {    /* Restore herc card to text mode */
  55.                 herc_settmode();
  56.             }
  57.         }
  58.         else {
  59.             pc_sethflag(PCHFLAG_COLO);
  60.         }
  61.         if (mode == PCMODE_CPQ40) {
  62.             mode = 0x40;
  63.         }
  64.         regs.h.al = (byte)mode;
  65.         regs.h.ah = VIDINT_SETVM;
  66.         regs.h.bh = TEXT_RPAGE;
  67.         oakint86(BIOS_VIDINT, ®s);
  68.         break;
  69.     case PCMODE_EGA43:
  70.     case PCMODE_VGA50:
  71.         pc_sethflag(PCHFLAG_COLO);
  72.  
  73.         /* In case this is a VGA, set the proper number of scanlines */
  74.         /* (EGA will not respond to this call and stay at 350) */
  75.         regs.h.ah = VIDINT_ALTSEL;        /* alternate select */
  76.         regs.h.bl = ALTSEL_SETLINES;        /* set # of scanlines */
  77.         if (mode == PCMODE_EGA43) {
  78.             regs.h.al = SETLINES_350;
  79.         }
  80.         else {
  81.             regs.h.al = SETLINES_400;
  82.         }
  83.         oakint86(BIOS_VIDINT, ®s);
  84.  
  85.         regs.h.al = 0x03;            /* These modes are based on mode 3 */
  86.         regs.h.bh = TEXT_RPAGE;
  87.         regs.h.ah = VIDINT_SETVM;            /* reset video mode (see ega docs) */
  88.         oakint86(BIOS_VIDINT, ®s);
  89.  
  90.         regs.h.ah = VIDINT_CHARGEN;        /* character generator command */
  91.         regs.h.al = CHARGEN_ROM8X8;        /* choose 8x8 cell */
  92.         regs.h.bl = 0;
  93.         oakint86(BIOS_VIDINT, ®s); /* setup 43/50 line */
  94.         
  95.         regs.h.ah = VIDINT_ALTSEL;        /* alternate select */
  96.         regs.h.bl = ALTSEL_NEWPRTSCR;        /* new print screen routine */
  97.         oakint86(BIOS_VIDINT, ®s);    /* setup new prt scrn */
  98.  
  99.         break;
  100.     case PCMODE_HERC0:
  101.     case PCMODE_HERC1:
  102.         herc_setgmode(mode != PCMODE_HERC0);
  103.         break;
  104.     }
  105. }
  106. /* -------------------------------------------------------------------------- */
  107.  
  108. int pc_GetMode(void)
  109. /*
  110.     Returns the current video mode of the display adapter.
  111. */
  112. {
  113.     OREGS regs;
  114.     int mode;
  115.     byte rows;
  116.  
  117.     regs.h.ah = VIDINT_GETVM;
  118.     oakint86(BIOS_VIDINT, ®s);
  119.     mode = (int)(regs.h.al & 0x7F);    /* knock out hi noclear bit */
  120.  
  121. /* Check for 43 or 50 line mode */
  122.     if (mode == 0x03) {
  123.         if (pc_IsEGA()) {
  124.             ram_segtomem(0x40, 0x84, &rows, 1);    /* Get Rows from BIOS data area */
  125.             if (rows == 43-1) mode = PCMODE_EGA43;
  126.             if (rows == 50-1) mode = PCMODE_VGA50;
  127.         }
  128.     }
  129. /* Check for herc graphics mode */
  130.     if (mode == 0x05 || mode == 0x06 || mode == 0x07) {
  131.         if (pc_IsHerc()) {
  132.             if (herc_getlines() > 0xF00) {
  133.                 ram_segtomem(0x40, 0x49, &rows, 1);    /* Get vidmode from BIOS */
  134.                 if (rows != 5) {
  135.                     mode = PCMODE_HERC0;
  136.                 }
  137.                 else mode = PCMODE_HERC1;
  138.             }
  139.         }
  140.     }
  141. /* Check for Compaq mode 40 */
  142.     if (mode == 0x40) {
  143.         mode = PCMODE_CPQ40;
  144.     }
  145.     return(mode);
  146. }
  147. /* -------------------------------------------------------------------------- */
  148.  
  149. boolean pc_ModeSupport(int mode)
  150. /* Return TRUE if mode is supported on current hardware */
  151. {
  152.     if (mode == PCMODE_HERC0) {
  153.         return(pc_IsHerc());
  154.     }
  155.     if (mode == PCMODE_HERC1) {
  156.         return(pc_IsHerc() && !pc_IsCGA());
  157.     }
  158.     if (mode == PCMODE_CPQ40) {
  159.         return(pc_IsCompaqPlasma() && !pc_IsEGA() && !pc_IsMDA());
  160.     }
  161.     if (newbios()) {    /* vga/mcga bios gives supported modes */
  162.         if (newbios_modesupport(mode)) {
  163.             return(TRUE);
  164.         }
  165.     }
  166.     if (pc_IsEGA()) {
  167.         if (ega_modesupport(mode)) {
  168.             return(TRUE);
  169.         }
  170.     }
  171.     switch(mode) {
  172.     case 0x00:
  173.     case 0x01:
  174.     case 0x02:
  175.     case 0x03:
  176.     case 0x04:
  177.     case 0x05:
  178.     case 0x06:
  179.         return(pc_IsCGA());
  180.     case 0x07:
  181.         return(pc_IsMDA());
  182.     default:
  183.         return(FALSE);
  184.     }
  185. }
  186. /* -------------------------------------------------------------------------- */
  187.  
  188. boolean pc_IsHerc(void)
  189. {
  190.     return(cursport_test(VID_MDAPORT) && herc_present() &&
  191.             !(pc_IsEGA() && ega_ismono(0)));
  192. }
  193. /* -------------------------------------------------------------------------- */
  194.  
  195. boolean pc_IsMDA(void)
  196. {
  197.     return(ram_testword(VID_MONOADDR, 4000) && cursport_test(VID_MDAPORT));
  198. }
  199. /* -------------------------------------------------------------------------- */
  200.  
  201. boolean pc_IsCGA(void)
  202. {
  203.     return(ram_testword(VID_CGAADDR, 16000) && cursport_test(VID_CGAPORT));
  204. }
  205. /* -------------------------------------------------------------------------- */
  206.  
  207. boolean pc_IsEGA(void)
  208. {
  209.     if (!ega_ismono(1)) {
  210.         return(TRUE);                    /* ega is present, not mono */
  211.     }
  212.     else {
  213.         if (ega_ismono(0)) {
  214.             return(TRUE);                /* ega is present */
  215.         }
  216.     }
  217.     return(FALSE);                        /* ega not present */
  218. }
  219. /* -------------------------------------------------------------------------- */
  220.  
  221. boolean pc_IsMCGA(void)
  222. {
  223.     return(newbios_modesupport(0x13));
  224. }
  225. /* -------------------------------------------------------------------------- */
  226.  
  227. boolean pc_IsVGA(void)
  228. {
  229.     return(newbios_modesupport(0x12));
  230. }
  231. /* -------------------------------------------------------------------------- */
  232.  
  233. boolean pc_IsCompaqPlasma(void)
  234. {
  235.     OREGS regs;
  236.  
  237.     if (!pc_IsCompaq()) {
  238.         return(FALSE);
  239.     }
  240.     regs.h.ah = VIDINT_CPQINFO;            /* alternate select function */
  241.     regs.h.al = 3;
  242.     regs.x.cx = 0;
  243.     oakint86(BIOS_VIDINT, ®s);
  244.  
  245.     return((regs.h.cl & CPQINFO_PLASMABIT) != 0);
  246. }
  247. /* -------------------------------------------------------------------------- */
  248. /* -------------------------------------------------------------------------- */
  249.  
  250. static void DIGPRIV pc_sethflag(byte vf)
  251. {
  252.     byte hf;
  253.  
  254. /* Put Hardware Equip Flag Video bits to BIOS data area */
  255.     ram_segtomem(0x40, 0x10, &hf, 1);
  256.     hf &= ~0x30;
  257.     hf |= vf & 0x30;
  258.     ram_memtoseg(0x40, 0x10, &hf, 1);
  259. }
  260. /* -------------------------------------------------------------------------- */
  261.  
  262. static boolean DIGPRIV ega_ismono(byte inbh)
  263. {
  264.     OREGS regs;
  265.  
  266.     regs.h.ah = VIDINT_ALTSEL;            /* alternate select function */
  267.     regs.h.bl = ALTSEL_GETINFO;            /* return ega info */
  268.     regs.h.bh = inbh;
  269.     oakint86(BIOS_VIDINT, ®s);
  270.  
  271.     return(regs.h.bh == 1);
  272. }
  273. /* -------------------------------------------------------------------------- */
  274.  
  275. static boolean DIGPRIV ega_modesupport(int mode)
  276. {
  277.     switch(mode) {
  278.     case 0x02:
  279.     case 0x03:
  280.     case 0x04:
  281.     case 0x05:
  282.     case 0x06:
  283.     case 0x0D:
  284.     case 0x0E:
  285.     case 0x10:
  286.     case PCMODE_EGA43:
  287.         return(!ega_ismono(0));
  288.     case 0x07:
  289.     case 0x0F:
  290.         return(ega_ismono(0));
  291.     default:
  292.         return(FALSE);
  293.     }
  294. }
  295. /* -------------------------------------------------------------------------- */
  296.  
  297. static boolean DIGPRIV newbios(void)
  298. {
  299.     byte info[0x50];
  300.  
  301.     return(vga_getinfo(info));
  302. }
  303. /* -------------------------------------------------------------------------- */
  304.  
  305. static boolean DIGPRIV newbios_modesupport(int mode)
  306. {
  307.     byte info[0x50];
  308.     unsigned modebit;
  309.     int modebyte;
  310.  
  311.     if (vga_getinfo(info)) {
  312.         if (mode == PCMODE_EGA43 || mode == PCMODE_VGA50) mode = 0x03;
  313.         if (mode <= 0x13) {
  314.             modebyte = 0x40 + mode/8;
  315.             modebit = 1 << (mode % 8);
  316.             return((boolean)((info[modebyte] & modebit) != 0));
  317.         }
  318.     }
  319.     return(FALSE);
  320. }
  321. /* -------------------------------------------------------------------------- */
  322.  
  323. static boolean DIGPRIV vga_getinfo(byte *buf)
  324. /*
  325.     Load up a 50-byte buffer with vga mode info.
  326. */
  327. {
  328.     OREGS regs;
  329.     unsigned seg, offs;
  330.     
  331.     /* Call BIOS get-mode-info function to read info into buf */
  332.     regs.a.esdx = buf;
  333.     regs.x.di = regs.x.dx;
  334.     regs.h.ah = VIDINT_MODEINFO;        
  335.     regs.h.al = 0;        
  336.     regs.x.bx = 0;
  337.     oakint86es(BIOS_VIDINT, ®s, 0x40);
  338.  
  339.     if (regs.h.al == VIDINT_MODEINFO && regs.x.bx == 0) {
  340.         /* Move extra info into end of buf using pointer from start of buf */
  341.         offs = ((unsigned short *) buf)[0];
  342.         seg  = ((unsigned short *) buf)[1];
  343.         ram_segtomem(seg, offs, &buf[0x40], 0x10);
  344.         return(TRUE);
  345.     }
  346.     else return(FALSE);
  347. }
  348. /* -------------------------------------------------------------------------- */
  349. #define TESTVAL        0x56D4
  350.  
  351. static boolean DIGPRIV ram_testword(unsigned seg, unsigned offs)
  352. /*
  353.     Tests to see whether any graphics memory is present by writing a
  354.     dummy value and then reading it again to see if it stayed written.
  355. */
  356. {
  357.     unsigned oldval, tdummy, dummy;
  358.  
  359.     ram_segtomem(seg, offs, (byte *)&oldval, 2);        /* read current val */
  360.  
  361.     dummy = TESTVAL;
  362.     if (oldval == dummy) dummy++;    /* If it's already dummy, change dummy */
  363.  
  364.     ram_memtoseg(seg, offs, (byte *)&dummy, 2);        /* write dummy */
  365.     tdummy = 0;        /* kill time, settle bus */
  366.     ram_segtomem(seg, offs, (byte *)&tdummy, 2);    /* read back dummy */
  367.  
  368.     if (tdummy == dummy) {            /* If dummy stayed written */
  369.         ram_memtoseg(seg, offs, (byte *)&oldval, 2);    /* restore old val */
  370.         return(TRUE);
  371.     }
  372.     else return(FALSE);
  373. }
  374. /* -------------------------------------------------------------------------- */
  375. #define TESTPOS    4
  376.  
  377. static boolean DIGPRIV cursport_test(int port)
  378. /*
  379.     Tests to see whether a 6845 graphics controller is present by writing a
  380.     dummy value to its cursor port and then reading it again to see if it stayed
  381.     written.
  382. */
  383. {
  384.     int oldval, tdummy, dummy;
  385.  
  386.     outp(port, 0x0F);                /* Select the cursor port */
  387.     oldval = inp(port+1);            /* Read the current value */
  388.  
  389.     dummy = TESTPOS;
  390.     if (oldval == dummy) dummy++;    /* If it's already dummy, change dummy */
  391.  
  392.     outp(port, 0x0F);                /* Select the cursor port */
  393.     outp(port+1, dummy);            /* Set dummy value */
  394.  
  395.     tdummy = 0;                        /* delay statement to avoid back-to back i/o */
  396.     outp(port, 0x0F);                /* Select the cursor port */
  397.     tdummy = inp(port+1);            /* Read the dummy value back */
  398.  
  399.     if (tdummy == dummy) {            /* If we read back the same as what we wrote */
  400.         outp(port, 0x0F);                /* Select the cursor port */
  401.         outp(port+1, oldval);            /* Restore the starting value */
  402.         return(TRUE);
  403.     }
  404.     else return(FALSE);
  405. }
  406. /* -------------------------------------------------------------------------- */
  407.  
  408.