home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_09_08
/
9n08035a
< prev
next >
Wrap
Text File
|
1991-04-23
|
9KB
|
397 lines
/* IBM bios screen control package
Copyright Dave Newman 1991
Permission to use these routines for any reason
is granted as long as this copyright notice is
included.
This should compile on any DOS C compiler
that supports int86() */
/* declarations for these functions */
#include <bios.h>
/* needed for REGS union */
#include <dos.h>
/* these variables are global */
/* these vars hold information about the system.
They are valid after the call to bios_open().
If the information in them is not relevant,
the call to bios_open() is not necessary. */
int cur_mode; /* current display mode */
int cur_page; /* current display page */
int num_cols; /* number of cols on screen */
/* adapter types */
char cga, /* color graphics adapter */
ega, /* Enhanced graphics adapter */
vga, /* video graphics array */
mcga, /* PS/2 mcga display */
mono, /* just black and white */
herc, /* hercules graphics adapter */
none; /* no monitor at all */
char color, /* is using a color monitor */
b_w; /* or black+white? */
/* these vars hold info about the cursor position
and the current color/attribute being used.
(no bios_open call necessary) */
/* display attribute (use to change colors) */
unsigned char cur_attr;
int cur_row; /* current row of cursor */
int cur_col; /* current column of cursor */
/* end global values */
/* bios open function.
Set up the initial values in all of the variables
above. */
void bios_open()
{
union REGS regs;
void vtest(void);
/* determine the current display mode */
regs.x.ax = 0x0f00;
int86(0x10,®s,®s);
cur_mode = regs.h.al;
cur_page = regs.h.bh;
num_cols = regs.h.ah;
/* determine the type of display in the system
and set it's type value to 1
on return the proper video adapter variable
will be set as will the color or b_w value */
none=mono=herc=cga=ega=vga=mcga=color=b_w=0;
vtest();
}
/* and a bios_close function just for the sake of
consistency. Please use this function. It may do
something one day (like restore the screen
to the previous state) */
void bios_close()
{}
/* change value of cursor.
range 0x0000 to 0xFFFF (FFFF == OFF) */
void bios_cursor(int state)
{
union REGS regs;
regs.h.ah = 1;
/* ch == start line. cl == end line */
regs.x.cx = state;
int86(0x10,®s,®s);
}
/* move cursor to row,col */
void bios_move(int row,int col)
{
union REGS regs;
regs.h.dh = row;
regs.h.dl = col;
regs.h.ah = 2;
regs.h.bh = cur_page;
int86(0x10,®s,®s);
cur_row = row;
cur_col = col;
}
/* scroll active page up.
use to clear boxes on screen */
void bios_scroll_up(
int count,int sr,int sc,int er,int ec)
{
union REGS regs;
regs.h.al = count;
regs.h.ch = sr;
regs.h.cl = sc;
regs.h.dh = er;
regs.h.dl = ec;
regs.h.bh = cur_attr;
regs.h.ah = 6;
int86(0x10,®s,®s);
}
/* scroll active page down.
good for clearing entire screen */
void bios_scroll_dn(
int count,int sr,int sc,int er,int ec)
{
union REGS regs;
regs.h.al = count;
regs.h.ch = sr;
regs.h.cl = sc;
regs.h.dh = er;
regs.h.dl = ec;
regs.h.bh = cur_attr;
regs.h.ah = 7;
int86(0x10,®s,®s);
}
/* return current video state */
int bios_mode()
{
union REGS regs;
regs.h.ah = 15;
int86(0x10,®s,®s);
cur_mode = regs.h.al;
return(regs.h.al);
}
/* return current cursor position
into global values */
void bios_rc()
{
union REGS regs;
regs.h.bh = cur_page;
regs.h.ah = 3;
int86(0x10,®s,®s);
cur_row = regs.h.dh;
cur_col = regs.h.dl;
}
/* print char (attribute at r/c unchanged)
at current cursor position */
void bios_putchar(char ch)
{
union REGS regs;
regs.h.bh = cur_page;
regs.x.cx =1;
regs.h.al = ch;
regs.h.ah = 0x0a;
int86(0x10,®s,®s);
}
/* print char & attribute at cusor position */
void bios_pchatt(char ch)
{
union REGS regs;
regs.h.bh = cur_page;
regs.h.bl = cur_attr;
regs.x.cx = 1;
regs.h.al = ch;
regs.h.ah = 0x09;
int86(0x10,®s,®s);
}
/* this function replaces puts()
(but no linefeed on end)
recognises LF,CR,BS and TAB
Use sprintf() with this to simulate printf()
(need large buffer too) */
void bios_puts(char *str)
{
int i;
bios_rc();
while(*str)
{
if(*str == 10) /* do LF */
{
cur_col = 0;
cur_row++;
bios_move(cur_row,cur_col);
str++;
if(!*str)
break;
}
if(*str == 8) /* do BS */
{
if(cur_col == 0)
cur_row--;
else
cur_col--;
bios_move(cur_row,cur_col);
str++;
if(!*str)
break;
}
if(*str == 13) /* do CR */
{
cur_col = 0;
bios_move(cur_row,cur_col);
str++;
if(!*str)
break;
}
if(*str == 9) /* do TAB */
{
i = (1+(cur_col / 8)) *8;
while(cur_col < i)
{
bios_pchatt(' ');
cur_col++;
bios_move(cur_row,cur_col);
}
str++;
if(!*str)
break;
}
bios_pchatt(*str);
str++;
cur_col++;
bios_move(cur_row,cur_col);
}
}
/* returns the char under the cursor */
char bios_rdchar()
{
union REGS regs;
regs.h.bh = cur_page;
regs.h.ah = 8;
int86(0x10,®s,®s);
return((char)regs.h.al);
}
/* returns char AND attribute under cursor */
int bios_rdchatt()
{
union REGS regs;
regs.h.bh = cur_page;
regs.h.ah = 8;
int86(0x10,®s,®s);
/* char is in AL, attribute is in AH */
return((int)regs.x.ax);
}
/* this function was written by Andrew Binstock.
The text of the function
and the supporting artical can be found in
the magazine: C Gazette, Summer 1989 issue.
(v4 #1) p27.
Only minor modifications have been made by me.
*/
/* test to determine type of
video adapter in the system */
void vtest()
{
union REGS regs;
unsigned char hold_a_byte;
int i;
/* identify VGA/MCGA/EGA */
regs.h.ah = 0x1a;
regs.h.al = 0;
int86(0x10,®s,®s);
/* true only for VGA, MCGA */
if(regs.h.al == 0x1a)
{
if(regs.h.bl < 0x0a)
vga =1;
else
mcga =1;
color = 1;
return;
}
/* next test for EGA */
regs.h.ah = 0x12;
regs.h.bl = 0x10;
int86(0x10,®s,®s);
if(regs.h.bl != 0x10) /* it's an EGA */
{
ega = 1;
/* EGA can be color or B+W */
if(regs.h.bh ==0)
color = 1;
else
b_w = 1;
return;
}
/* not any of the above,
so it must be CGA or MONO (or HERC) */
/* test for MONO by looking at the current mode */
bios_mode();
/* go to MONO test. CGA can't use mode 7 */
if(cur_mode != 7)
{
/* test CGA by looking at the CGA registers */
outp(0x3d4,0x0f); /* get value of reg 15 */
hold_a_byte = inp(0x3d5); /* save it */
outp(0x3d5,0x63); /* write an unlikely value */
for(i=0;i< 100;i++) /* wait a bit */
;
if(inp(0x3d5) == 0x63) /* read it back */
{
outp(0x3d5,hold_a_byte); /* restore value */
cga = 1;
color = 1;
return;
}
else
{
outp(0x3d5,hold_a_byte);
none = 1;
color =1;
return;
}
}
/* not CGA, Test for MDA and HERC.
Same test as CGA but to mono ports */
outp(0x3b4,0xf);
hold_a_byte = inp(0x3b5);
outp(0x3b5,0x63);
for(i=0;i<100;i++)
;
if(inp(0x3b5) != 0x63)
{
outp(0x3b5,hold_a_byte);
none = 1;
b_w = 1;
return;
}
outp(0x3b5,hold_a_byte);
/* must be a MONO but is it a HERCULES????? */
hold_a_byte = inp(0x3ba); /* check status port */
hold_a_byte &= 0x80; /* isolate bit 7 */
for(i=0; i< 1000; i++)
{
if(inp(0x3ba) & 0x80 != hold_a_byte)
{
/* if value changes, hercules is present */
herc = 1;
break;
}
}
if(!herc)
{
/* must be just MDA */
mono = 1;
b_w = 1;
return;
}
/* determine if the card is herc mono or color */
hold_a_byte = inp(0x3ba);
switch(hold_a_byte)
{
case 0x50: color = 1;
break;
case 0x00: b_w = 1;
break;
/* case 0x10: graphics plus card found */
}
}