home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
VIDEO.ZIP
/
VIDEOID.C
next >
Wrap
C/C++ Source or Header
|
1992-06-29
|
15KB
|
468 lines
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* . *
* Video *
* *
* (c) Copyright 1988 Michael K. Heney *
* *
* File: VideoID.C *
* Purpose: Identify the video subsystem(s) present. *
* *
* Routines: VideoID FindPS2 FindEGA FindCGA FindMono *
* Find6845 FindActive *
* *
* Written: 15 Jul 88 - 16 Jul 88 MKH *
* *
* Notes: Adapted from the VideoID program written in assembler in *
* "Programmer's Guide to PC & PS/2 Video Systems" by *
* Richard Wilton (Microsoft Press). Listing C-1, pp. 513-521. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <dos.h>
#include "videoid.h"
union REGS regs ;
enum videocard device0, device1 ;
enum display display0, display1 ;
int EGAFlag, CGAFlag, MonoFlag ;
static const int DCCTable[][2] =
{
None, NoDisplay,
MDA, MDADisplay,
CGA, CGADisplay,
None, NoDisplay,
EGA, EGAColorDisplay,
EGA, MDADisplay,
None, NoDisplay,
VGA, PS2MonoDisplay,
VGA, PS2ColorDisplay,
None, NoDisplay,
MCGA, EGAColorDisplay,
MCGA, PS2MonoDisplay,
MCGA, PS2ColorDisplay
} ;
static const int EGADisplays[] =
{
CGADisplay,
EGAColorDisplay,
MDADisplay,
CGADisplay,
EGAColorDisplay,
MDADisplay
} ;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VideoID checks for up to 2 video systems present, looking for PS/2, *
* EGA, CGA, and Monochrome. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
long VideoID()
{
long rc ;
/* ---- initilize - no video subsystems found yet ---- */
device0 = None ;
display0 = NoDisplay ;
device1 = None ;
display1 = NoDisplay ;
/* ---- flags - nothing ruled out yet ---- */
EGAFlag = 1 ;
CGAFlag = 1 ;
MonoFlag = 1 ;
/* ---- check each video subsytem type as appropriate ---- */
FindPS2() ;
if (EGAFlag) FindEGA() ;
if (CGAFlag) FindCGA() ;
if (MonoFlag) FindMono() ;
/* ---- determine which video subsystem is active, if 2 present ---- */
FindActive() ;
rc = ( ( ( ( ( ( (long) device0 << 8) | (long) display0) << 8)
| (long) device1) << 8) | (long) display1) ;
return (rc) ;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* FindPS2 looks for PS/2 compatable video systems (VGA or MCGA) *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int FindPS2()
{
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* use video service 1A (video display combination) of INT 10h *
* (video services) to see if (1) this is a PS/2 system, and *
* (2) what the displays are. *
* *
* Register assignments for service 1A are: *
* *
* Call: *
* AH = 0x1A video service 1A *
* AL = 0x00 subservice 0 - PS/2 return video *
* display combinations *
* *
* Return: *
* AL = 0x1A if service available! *
* BL = active display *
* BH = inactive display *
* *
* Display type codes: *
* 00 No display *
* 01 MDA with monochrome display *
* 02 CGA with color display *
* 03 (reserved) *
* 04 EGA with color display *
* 05 EGA with monochrome display *
* 06 Professional Graphics Controller *
* 07 VGA with analog monochrome display *
* 08 VGA with analog color display *
* 09 (reserved) *
* 0A MCGA with digital color display *
* 0B MCGA with analog mono display *
* 0C MCGA with analog color display *
* FF Unrecognized video subsystem *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
regs.x.ax = 0x1a00 ;
int86(0x10, ®s, ®s) ;
/* ---- if not PS/2, leave ---- */
if (regs.h.al != 0x1a)
return ;
/* ---- if inactive display (BH) exists, classify it ---- */
if (regs.h.bh)
{
device1 = DCCTable[1][regs.h.bh] ;
display1 = DCCTable[2][regs.h.bh] ;
}
/* ---- now for the active display ---- */
device0 = DCCTable[1][regs.h.bl] ;
display0 = DCCTable[2][regs.h.bl] ;
/* ---- we have both systems ... ---- */
EGAFlag = 0 ;
CGAFlag = 0 ;
MonoFlag = 0 ;
/* ---- if either device was MDA, we'll need to check for HERCULES ---- */
if (device0 == MDA)
{
MonoFlag = 1 ;
device0 = None ;
display0 = NoDisplay ;
}
else if (device1 == MDA)
{
MonoFlag = 1 ;
device1 = None ;
display1 = NoDisplay ;
}
return ;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* FindEGA looks for an EGA system *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int FindEGA()
{
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* use video service 12h (video subsystem configuraton of *
* INT 10h (video services) to see if there is an EGA card *
* and what kind of monitor is attached. * *
* *
* Register assignments for service 12h are: *
* *
* Call: *
* AH = 0x12 video service 12h *
* BL = 0x10 subservice 10h - EGA return video *
* configuration information *
* *
* Return: *
* BH = default BIOS video mode *
* 0 Color *
* 1 Monochrome *
* BL = amount of EGA vide RAM *
* 0 64 KB *
* 1 128 KB *
* 2 192 KB *
* 3 256 KB *
* 10h subservice not available - no EGA present *
* CH = feature bits *
* CL = configuration switch setting *
* *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
regs.h.ah = 0x12 ;
regs.h.bl = 0x10 ;
int86(0x10, ®s, ®s) ;
/* ---- if not EGA (no change in bl) leave ---- */
if (regs.h.bl == 0x10)
return ;
/* ---- cl described the display type. Since we get ---- */
/* ---- here iff not PS2, this must be the first found. ---- */
device0 = EGA ;
display0 = EGADisplays[regs.h.cl > 1] ; /* trust me, it works */
/* ---- figure out what we can't have for a 2nd monitor ---- */
if (display0 == MDA)
MonoFlag = 0 ;
else
CGAFlag = 0 ;
return ;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* FindCGA looks for a CGA system *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int FindCGA()
{
/* Call Find6845 to see if a video controller is at port 0x03d4 ---- */
if ( Find6845(0x03d4) )
{
/* ---- assign to 1st or 2nd device found as appropriate ---- */
if (device0)
{
device1 = CGA ;
display1 = CGADisplay ;
}
else
{
device0 = CGA ;
display0 = CGADisplay ;
}
}
return ;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* FindMono looks for a Mono system. This gets to be fun, as we need to *
* determine if the monitor is HERCULES graphics if mono. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int FindMono()
{
register char bit7, hold7 ;
int i ;
/* Call Find6845 to see if a video controller is at port 0x03b4 ---- */
if ( Find6845(0x03b4) == 0)
return ;
/* ---- assign to 1st or 2nd device found as appropriate ---- */
if (device0)
{
device1 = MDA ;
display1 = MDADisplay ;
}
else
{
device0 = MDA ;
display0 = MDADisplay ;
}
/* ---- now check for HERCULES. Hercs use bit 7 of port 0x03ba ---- */
/* ---- to signal horizontal resynch, non-graphics cards don't. ---- */
/* ---- So, if this bit changes, it's a HERC! ---- */
hold7 = inp(0x03ba) & 0x80 ;
for (i = 0; i < 32767; i++)
{
bit7 = inp(0x03ba) & 0x80 ;
if (hold7 != bit7)
break ;
}
/* ---- if it never changed, we're done! ---- */
if (hold7 == bit7)
return ;
/* ---- check the status port One More Time to get the Herc Type ---- */
/* ---- bits 4-6 (as 76543210) denote the type. ---- */
/* ---- x000xxxx is HGC ---- */
/* ---- x001xxxx is HGC Plus ---- */
/* ---- x101xxxx is Hercules Incolor ---- */
/* ---- Anything else will be assumed to be a plain HGC card. ---- */
hold7 = inp(0x03ba) & 0x0070 ;
/* ---- HGC+ has only bit 4 on ---- */
if (hold7 == 0x0010)
{
if (device0 == MDA)
device0 = HGCPlus ;
else
device1 = HGCPlus ;
return ;
}
/* ---- HGC InColor has bits 4 and 6 on ---- */
if (hold7 == 0x0050)
{
if (device0 == MDA)
{
device0 = InColor ;
display0 = EGAColorDisplay ;
}
else
{
device1 = InColor ;
display1 = EGAColorDisplay ;
}
return ;
}
/* ---- anything else is just an HGC (to be safe) ---- */
if (device0 == MDA)
device0 = HGC ;
else
device1 = HGC ;
return ;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Find6845 tries to write to a specified video port, reporting its success *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int Find6845(int port)
{
int oldval, newval ;
int i, port1 ;
port1 = port+1 ;
/* ---- We try to read/write register 0x0f (Cursor Low) on the ---- */
/* ---- 6845 CRT controller. For EGA/CGA, use ports 3d4/3d5; ---- */
/* ---- for mono use 3b4/3b5 as the register select port and ---- */
/* ---- the data port, repectively. If the write changes the ---- */
/* ---- value, we are there is a contoller on those ports. ---- */
/* ---- save current value ---- */
outp(port,0x000f) ;
oldval = inp(port1) ;
/* ---- try to put a value out - invert oldval ---- */
outp(port, 0x000f) ;
outp(port1, ~oldval & 0x00ff) ;
/* ---- short wait ---- */
for (i = 0; i < 256; i++)
;
/* ----read the port, and see if our value got written ---- */
outp(port,0x000f) ;
newval = inp(port1) ;
outp(port,0x000f) ;
outp (port1,oldval) ;
return (newval == (~oldval & 0x00ff) ) ;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* FindaActive makes sure the active display subsystem is device0/display0 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int FindActive()
{
enum videocard devicex ;
enum display displayx ;
/* ---- if VGA or MCGA is present, or there is only 1 monitor, ---- */
/* ---- things are quite easy. ---- */
if ( (device1 == None) || (device0 == VGA) || (device0 == MCGA)
|| (device1 == VGA) || (device1 == MCGA) )
return ;
/* ---- use the BIOS to get the video mode ---- */
regs.h.ah = 0x0F ;
int86(0x10, ®s, ®s) ;
/* ---- if mode is 7 (mono), we're OK if display0 is mono. ---- */
if (regs.h.al == 7)
{
if (display0 == MDADisplay)
return ;
}
/* ---- problems in EGAMono if CGA also present ... ---- */
else
{
if (display0 != MDADisplay)
return ;
}
/* ---- swap the displays and devices ---- */
devicex = device0 ;
device0 = device1 ;
device1 = devicex ;
displayx = display0 ;
display0 = display1 ;
display1 = displayx ;
return ;
}