home *** CD-ROM | disk | FTP | other *** search
- /**
- *
- * Name scnewdev -- Select and reset video display device and
- * choose the number of text lines on screen
- *
- * Synopsis new_mode = scnewdev(mode,num_rows);
- *
- * int new_mode Error code returned:
- * -1 if requested mode or font are not
- * supported;
- * actual mode set if no error.
- * int mode New mode value,
- * or -1 to use existing mode and device.
- * int num_rows New maximum number of rows on current
- * display device (25, 30, 43, or 50).
- *
- * Description This function selects and resets a video adapter and
- * selects the 25- or 30-line or (if possible) the 43- or
- * 50-line built-in font. It also selects the proper
- * print-screen routine and sets the global variable
- * b_device (declared in BSCREENS.H).
- *
- * The permitted values for mode are
- *
- * Mode Device Description
- * ---- -------- ------------------------------------------
- * 0 SC_COLOR 40 x 25 Black and White
- * 1 SC_COLOR 40 x 25 Color burst enabled
- * 2 SC_COLOR 80 x 25 Black and White
- * 3 SC_COLOR 80 x 25 Color burst enabled
- * 4 SC_COLOR 320 x 200 Color burst enabled
- * 5 SC_COLOR 320 x 200 Black and White
- * 6 SC_COLOR 640 x 200 Black and White
- * 7 SC_MONO Monochrome Adapter or EGA + Monochrome
- * Display or VGA
- * 8 SC_COLOR 160 x 200 Color (PCjr only)
- * 9 SC_COLOR 320 x 200 Color (PCjr only)
- * 10 SC_COLOR 640 x 200 Color (PCjr only)
- * 13 SC_COLOR 320 x 200 Color (EGA or VGA only)
- * 14 SC_COLOR 640 x 200 Color (EGA or VGA only)
- * 15 SC_MONO 640 x 350 Monochrome (EGA or VGA only)
- * 16 SC_COLOR 640 x 350 Color (EGA or VGA only)
- * 17 SC_COLOR 640 x 480 Color (VGA or MCGA only)
- * 18 SC_COLOR 640 x 480 Color (VGA only)
- * 19 SC_COLOR 320 x 200 Color (VGA or MCGA only)
- *
- * An error occurs if the mode is not supported by the
- * installed hardware or if the requested font is not
- * supported by the requested device. In this case no
- * action occurs and -1 is returned as the value of the
- * function.
- *
- * Method This routine first checks for the presence of the
- * required device and validates the mode and font
- * requested. If the device is present and the mode and
- * font are supportable, SCNEWDEV then sets the BIOS
- * equipment word to select the new device. If the new
- * device is an Enhanced Graphics Adapter, the BIOS cursor
- * compensation bit is set according to the font. Then the
- * new device is reset, clearing the screen. Page 0 is
- * selected as active (currently displayed) and current
- * (selected for output via Blaise C TOOLS screen I/O
- * routines). The standard underline cursor is left at the
- * upper left corner of each page. If 43 or more lines are
- * requested, the proper font is selected.
- *
- * Returns new_mode Error code returned:
- * -1 if requested mode or font are not
- * supported;
- * actual mode set if no error.
- * b_device Adapter used (SC_COLOR or SC_MONO).
- *
- * Version 6.00 (C)Copyright Blaise Computing Inc. 1986-1989
- *
- **/
-
- #include <dos.h>
-
- #include <bscreens.h>
-
- int b_vidcpy(int,int); /* Internal (see below) */
-
- #define FROM_BIOS 0 /* Direction flags for copying */
- #define TO_BIOS 1 /* BIOS video state variables. */
-
- #define VIDEO_FIELD 0x0030 /* The bits to be modified in */
- /* the BIOS equipment word. */
- #define MONO_FLAG 0x0030
- #define COLOR_80 0x0020
- #define COLOR_40 0x0010
-
- int b_vidcpy(int,int); /* Internal (see below) */
-
- #define FROM_BIOS 0 /* Direction flags for copying */
- #define TO_BIOS 1 /* BIOS video state variables. */
-
- /* Address of BIOS equipment word. */
- #define EQUIP_LOC (uttofar(0x0040,0x0010,unsigned int))
-
- /* Address of BIOS INFO byte. */
- #define INFO_LOC (uttofar(0x0040,0x0087,unsigned char))
-
- int scnewdev(mode,num_rows)
- int mode,num_rows;
- {
- int old_dev,old_mode,old_act_page,old_cols;
- int device;
- union REGS inregs,outregs;
-
- int our_word; /* Our copy of equipment word. */
- int old_flag,new_flag; /* Old and new values of video */
- /* device bit field. */
-
- char old_info; /* Our copy of former INFO byte */
- char new_info;
-
- /* Note current state of BIOS. */
-
- old_dev = scmode(&old_mode,&old_cols,&old_act_page);
-
- /* Check validity of mode and font requested */
-
- scequip(); /* Sense hardware settings. */
-
- if (mode == -1)
- mode = old_mode; /* Use existing mode */
- switch (mode)
- { /* Determine requested device. */
-
- /* PCjr color modes: */
- case 8:
- case 9:
- case 10:
- if (b_pcmodel != IBM_JR)
- return -1;
- /* CGA color modes: */
- case 4:
- case 5:
- case 6:
- if (num_rows != 25)
- return -1;
- case 0:
- case 1:
- case 2:
- case 3:
- /* This is a color mode, */
- /* so check for color device. */
- if ( b_cga != SC_COLOR && b_pcmodel != IBM_JR
- && b_ega != SC_COLOR && b_pgc != SC_COLOR
- && b_vga == SC_ABSENT && b_mcga == SC_ABSENT)
- return -1; /* Color/Graphics Adapter */
- /* functions are not available. */
-
- device = SC_COLOR;
- new_flag = COLOR_80;
- break;
-
- /* EGA-only color modes: */
- case 13:
- case 14:
- if (num_rows != 25)
- return -1;
- case 16:
- if ( num_rows > 43
- || (b_ega != SC_COLOR && b_vga == SC_ABSENT))
- return -1;
- device = SC_COLOR;
- new_flag = COLOR_80;
- break;
-
- /* Monochrome modes: */
- case 15:
- if ( num_rows > 43
- || (b_ega != SC_MONO && b_vga == SC_ABSENT))
- return -1;
- case 7:
- /* This is a monochrome mode, */
- /* so check for monochrome device. */
- if (b_mdpa != SC_MONO && b_ega != SC_MONO && b_vga == SC_ABSENT)
- return -1; /* Monochrome Adapter functions */
- /* are not available. */
-
- new_flag = MONO_FLAG; /* Monochrome functions found. */
- device = SC_MONO;
- break;
-
- /* VGA/MCGA modes: */
- case 18:
- if (b_vga == SC_ABSENT)
- return -1;
- case 17:
- if ( (num_rows != 30 && num_rows != 60)
- || (b_vga == SC_ABSENT && b_mcga == SC_ABSENT))
- return -1;
- device = SC_COLOR;
- new_flag = COLOR_80;
- break;
-
- case 19:
- if ( num_rows != 25
- || (b_vga == SC_ABSENT && b_mcga == SC_ABSENT))
- return -1;
- device = SC_COLOR;
- new_flag = COLOR_80;
- break;
-
- default:
- return -1; /* Unknown mode. */
- }
-
- if (device == b_mdpa && mode != 7)
- return -1;
- if ( (device == b_cga || device == b_pgc)
- && mode > 6)
- return -1;
-
- switch (num_rows)
- {
- case 25: /* 25-line mode: */
- break; /* no further checking needed. */
-
- case 30: /* 30-line and 60-line require */
- case 60: /* mode 17 or 18. */
- if (mode != 17 && mode != 18)
- return -1;
- break;
-
- case 43: /* 43-line mode: */
- if ( device == b_mdpa /* can't run on MDPA */
- || device == b_cga /* or on CGA */
- || device == b_pgc /* or on PGC in CGA mode */
- || b_mcga != SC_ABSENT /* or if MCGA present; */
- || ( device == b_ega /* if on EGA */
- && device == SC_COLOR /* in color mode, */
- && b_sw_ega != 0x9 /* must have ECD in */
- && b_sw_ega != 0x3)) /* high-res mode. */
- return -1;
- break;
-
- case 50: /* 50-line mode requires */
- /* VGA or MCGA. */
- if ( device == b_mdpa
- || device == b_cga
- || device == b_ega
- || (b_vga == SC_ABSENT && b_mcga == SC_ABSENT))
- return -1;
- break;
-
- default:
- return -1; /* Unknown number of lines. */
- }
-
- /* Validation complete: now switch devices if necessary */
-
- /* Record current BIOS variables in case we ever need to change */
- /* back to the old device. */
-
- if (b_vidcpy(FROM_BIOS,old_dev))
- return -1;
-
- /* If we are switching VGA from color to monochrome or vice */
- /* versa, note the change in our global variables. */
-
- if ( device != b_mdpa && device != b_cga && device != b_ega
- && device != b_pgc)
- {
- if (b_vga == old_dev)
- b_vga = device;
- }
-
- /* For 43-line text modes on VGA, set scan lines to 350. */
- /* However, this works only if VGA is the former device. */
-
- if ( device == b_vga
- && device == old_dev
- && ((0 <= mode && mode <= 3) || mode == 7))
- {
- inregs.h.ah = 0x12; /* Alternate select. */
- inregs.h.bl = 0x30; /* Scan lines. */
- inregs.h.al = (unsigned char)
- (num_rows == 43 ? 1 /* 350 scan lines. */
- : 2); /* 400 scan lines. */
- int86(SC_BIOS_INT,&inregs,&outregs);
- }
-
- /* The BIOS keeps track of the color vs. monochrome distinction */
- /* by two bits in the equipment word, so we must poke those bits */
- /* to signal the change in device. */
-
- int86(17,&inregs,&outregs); /* Retrieve equipment word. */
- our_word = outregs.x.ax;
-
- old_flag = (our_word & VIDEO_FIELD);
- if (new_flag != old_flag /* There is a change. */
- && (old_flag != COLOR_40 || new_flag != COLOR_80))
- /* (Skip the change if 40-col */
- /* mode is set and we're */
- /* setting color.) */
- {
- /* Install modified equipment */
- /* word. */
- utpokeb(EQUIP_LOC,
- (unsigned char) ((our_word & ~VIDEO_FIELD) | new_flag));
- }
- b_device = device;
-
- /* Handle cursor compensation bit: */
- /* The EGA BIOS adjusts the cursor type based on the lower bit of */
- /* the variable called INFO. When the bit is 0, cursor types are */
- /* automatically adjusted to fit in 14 scan lines; when the bit */
- /* is 1, cursor types are used as requested. The BIOS does not */
- /* maintain this bit. Therefore we set this bit when in 43-line */
- /* mode and clear it for 25-line mode. */
-
- if (b_ega == device || b_vga == device || b_mcga == device)
- {
- /* Fetch INFO byte. */
- old_info = utpeekb(INFO_LOC);
-
- new_info = old_info;
- if (num_rows >= 43)
- new_info |= 1; /* Set compensation bit */
- /* (turn compensation off). */
- else
- new_info &= (~1); /* Clear compensation bit */
- /* (turn compensation on). */
-
- if (new_info != old_info) /* If there is a change, */
- /* install the new INFO byte. */
- utpokeb(INFO_LOC,new_info);
- }
-
- /* Reset new device */
-
- inregs.h.ah = 0;
- inregs.h.al = (unsigned char) mode;
- int86(SC_BIOS_INT,&inregs,&outregs);
-
- /* For 43-line text modes on VGA, set scan lines to 350, unless */
- /* we were able to do so before resetting the mode. Then reset */
- /* the mode again. */
-
- if ( device == b_vga && device != old_dev
- && ((0 <= mode && mode <= 3) || mode == 7)
- && scrows() != num_rows)
- {
- inregs.h.ah = 0x12; /* Alternate select. */
- inregs.h.bl = 0x30; /* Scan lines. */
- inregs.h.al = (unsigned char)
- (num_rows == 43 ? 1 /* 350 scan lines. */
- : 2); /* 400 scan lines. */
- int86(SC_BIOS_INT,&inregs,&outregs);
-
- inregs.h.ah = 0; /* Reset device again. */
- inregs.h.al = (unsigned char) mode;
- int86(SC_BIOS_INT,&inregs,&outregs);
- }
-
- /* Load small font if necessary. */
-
- if (num_rows >= 43)
- {
- if (mode > 3 && mode != 7)
- inregs.x.ax = 0x1123; /* Graphics mode. */
- else
- inregs.x.ax = 0x1112; /* Text mode. */
- inregs.h.bl = 0;
- inregs.h.dl = (unsigned char) num_rows;
- int86(SC_BIOS_INT,&inregs,&outregs);
-
- inregs.h.ah = 0x12; /* Select alternate print screen*/
- inregs.h.bl = 0x20; /* routine. */
- int86(SC_BIOS_INT,&inregs,&outregs);
- }
-
- scpage(0);
-
- /* Record new BIOS variables in case SCCHGDEV ever wants to */
- /* change to the new device. */
-
- b_vidcpy(FROM_BIOS,device);
-
- return mode;
- }
-
- /**
- *
- * Name b_vidcpy -- Copy BIOS video state variables.
- *
- * Synopsis ercode = b_vidcpy(dir,device);
- *
- * int ercode Result code:
- * 1 if dir or device invalid or if
- * table information is unavailable;
- * 0 if ok.
- * int dir Direction:
- * FROM_BIOS means from BIOS to table,
- * TO_BIOS means from table to BIOS.
- * int device SC_MONO or SC_COLOR to denote which
- * entry of the b_adap_state table to use.
- *
- * Description This function copies the four blocks of BIOS video state
- * variables to or from the table called b_adap_state
- * (defined above).
- *
- * If dir is TO_BIOS, the b_adap_state table entry is
- * checked for valid data; if it is marked as invalid, then
- * 1 is returned as an error code.
- *
- * An error is also reported if dir or device is invalid.
- *
- * Returns ercode Result code:
- * 1 if dir or device invalid or if
- * table information is unavailable;
- * 0 if ok.
- *
- **/
-
- /* Internal structure for preserving BIOS video variables */
-
- VIDEO_STATE b_adap_state[2] = {0}; /* One entry for SC_MONO, one */
- /* for SC_COLOR. */
-
- int b_vidcpy(dir,device)
- int dir,device;
- {
- int i;
- int were_on; /* Flag indicating whether interrupts */
- /* were on before we turned them off. */
-
- /* There are four blocks of BIOS variables that describe the */
- /* state of an adapter. Here are tables to help us copy them */
- /* into the b_adap_state array: */
-
- static char *save_area[2][4] = /* Pointers to the sections of */
- { /* the VIDEO_STATE structures */
- /* in the b_adap_state table */
- { b_adap_state[0].pc_area,
- b_adap_state[0].video_area,
- (char *) &b_adap_state[0].save_ptr,
- &b_adap_state[0].prtsc_status},
-
- { b_adap_state[1].pc_area,
- b_adap_state[1].video_area,
- (char *) &b_adap_state[1].save_ptr,
- &b_adap_state[1].prtsc_status}
- };
- static int save_size[4] = /* Sizes of the four sections */
- { /* of a VIDEO_STATE structure */
- sizeof(b_adap_state[0].pc_area),
- sizeof(b_adap_state[0].video_area),
- sizeof(b_adap_state[0].save_ptr),
- sizeof(b_adap_state[0].prtsc_status)
- };
- static char far *bios_ptr[4] = /* Addresses of the four blocks */
- { /* of BIOS variables */
- uttofar(0x0040,0x0049,char),
- uttofar(0x0040,0x0084,char),
- uttofar(0x0040,0x00a8,char),
- uttofar(0x0040,0x0100,char)
- };
-
- if ( (dir != FROM_BIOS && dir != TO_BIOS)
- || (device != SC_COLOR && device != SC_MONO))
- return 1; /* Invalid code. */
-
- if (dir == TO_BIOS && !b_adap_state[device].known)
- return 1; /* Requested table info isn't */
- /* valid. */
-
- were_on = utintoff(); /* Turn interrupts off. */
-
- for (i = 0; i < 4; i++) /* For each of the four blocks, */
- {
- if (dir == FROM_BIOS) /* Copy the block of data */
- utmovmem(bios_ptr[i], /* from BIOS*/
- (char far *) save_area[device][i],
- save_size[i]);
- else
- utmovmem((char far *) save_area[device][i], /* to BIOS */
- bios_ptr[i],
- save_size[i]);
- }
-
- if (were_on)
- utinton(); /* Turn interrupts back on. */
-
- if (dir == FROM_BIOS)
- {
- b_adap_state[device].curpage = b_curpage;
- b_adap_state[device].known = 1;/* Flag table info as valid. */
- }
-
- return 0; /* Success. */
- }