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 or 43).
- *
- * Description This function selects and resets a video adapter and
- * selects the 25-line or (if possible) the 43-line
- * built-in font. It also selects the proper print-screen
- * routine.
- *
- * The permitted values for mode are
- *
- * Mode Device Description
- * ---- ------ ------------------------------------------
- * 0 COLOR 40 x 25 Black and White (Power on default)
- * 1 COLOR 40 x 25 Color burst enabled
- * 2 COLOR 80 x 25 Black and White
- * 3 COLOR 80 x 25 Color burst enabled
- * 4 COLOR 320 x 200 Color burst enabled (Medium res)
- * 5 COLOR 320 x 200 Black and White (Medium res)
- * 6 COLOR 640 x 200 Black and White (High res)
- * 7 MONO Monochrome Adapter or EGA + Mono Display
- * 8 COLOR 160 x 200 Color (PCjr only) (Low res)
- * 9 COLOR 320 x 200 Color (PCjr only) (Medium res)
- * 10 COLOR 640 x 200 Color (PCjr only) (High res)
- * 13 COLOR 320 x 200 Color (EGA only) (Medium res)
- * 14 COLOR 640 x 200 Color (EGA only) (High res)
- * 15 MONO 640 x 350 Mono (EGA only) (High res)
- * 16 COLOR 640 x 350 Color (EGA + Enhanced Color
- * Display 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.
- *
- * Use SCCHGDEV to switch video devices without clearing
- * screens or resetting adapters.
- *
- * 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 saves the state of
- * the BIOS video state internal variables for the former
- * device and 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 C TOOLS PLUS screen I/O routines). The standard
- * underline cursor is left at the upper left corner of
- * each page. If 43 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.
- *
- * Version 3.0 (C)Copyright Blaise Computing Inc. 1986
- *
- * Version 3.02 March 23, 1987
- * Corrected handling of mode -1.
- *
- **/
-
- #include <bquery.h>
- #include <bscreen.h>
-
- int b_device = DONT_KNOW; /* Current adapter: DONT_KNOW, */
- /* MONO, or COLOR */
-
- 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 scnewdev(mode,num_rows)
- int mode,num_rows;
- {
- int old_dev,old_mode,old_cols,old_act_page;
- int device;
- int ax,bx,cx,dx,flags;
- int row,col,high,low;
-
- /* Address of BIOS equipment */
- static ADS equip_word_ads = {0x0010,0x0040}; /* word. */
-
- #define our_word ax /* Our copy of equipment word. */
- ADS our_ads; /* Address of our_word. */
- int old_flag,new_flag; /* Old and new values of video */
- /* device bit field. */
-
- /* Address of BIOS INFO byte */
- static ADS INFO_ads = {0x0087,0x0040};
-
- char old_info; /* Our copy of former INFO byte */
- ADS old_ads; /* Address of old_info */
- char new_info;
-
- if (num_rows != 25 && num_rows != 43)
- return -1; /* Unknown font. */
-
- /* 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. */
-
- /* Non-EGA color modes: */
- case 8:
- case 9:
- case 10:
- if (b_pcmodel != IBM_JR)
- return -1;
- 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 != COLOR && b_pcmodel != IBM_JR
- && b_ega != COLOR && b_pgc != COLOR)
- return -1; /* Color/Graphics Adapter */
- /* functions are not available, */
-
- device = COLOR; /* Color device is present. */
- new_flag = COLOR_80;
- break;
-
- /* EGA-only color modes: */
- case 13:
- case 14:
- if (num_rows != 25)
- return -1;
- case 16:
- if (b_ega != COLOR)
- return -1;
- device = COLOR; /* Color device is present. */
- new_flag = COLOR_80;
- break;
-
- /* Monochrome modes: */
- case 15:
- if (b_ega != MONO)
- return -1;
- case 7:
- /* This is a monochrome mode, */
- /* so check for mono device. */
- if (b_mdpa != MONO && b_ega != MONO)
- return -1; /* Monochrome Adapter functions */
- /* are not available, */
-
- new_flag = MONO_FLAG; /* Monochrome functions found. */
- device = MONO;
- break;
-
- default:
- return -1; /* Unknown mode. */
- }
-
- if (num_rows == 43) /* If requesting 43 lines */
- if ( device != b_ega /* but not on EGA */
- || ( device == COLOR /* or if color */
- && b_sw_ega != 0x9 /* and not on ECD in high-res */
- && b_sw_ega != 0x3)) /* mode */
- return -1; /* then quit. */
-
- /* 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;
-
- /* 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. */
-
- bios(17,&ax,&bx,&cx,&dx,&flags); /* Retrieve equipment word. */
-
- 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.) */
- {
- our_word = (our_word & ~VIDEO_FIELD) | new_flag;
-
- /* Install modified equipment */
- /* word. */
- utabsptr((char *) &our_word,&our_ads);
- utslmove(&our_ads,&equip_word_ads,1); /* Lower byte only */
- }
- 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)
- {
- utabsptr(&old_info,&old_ads);
- utslmove(&INFO_ads,&old_ads,1); /* Fetch INFO byte. */
-
- 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, */
- {
- old_info = new_info; /* install the new INFO byte. */
- utslmove(&old_ads,&INFO_ads,1);
- }
- }
-
- /* Reset new device */
-
- ax = utbyword(0,mode);
- bios(16,&ax,&bx,&cx,&dx,&flags);
-
- if (num_rows == 43)
- {
- if (mode > 3 && mode != 7)
- { /* Graphics mode */
- ax = 0x1123; /* Install 43-line font */
- bx = 0x0003;
- bios(16,&ax,&bx,&cx,&dx,&flags);
- }
- else
- { /* Text mode */
- ax = 0x1112; /* Install 43-line font */
- bx = 0;
- bios(16,&ax,&bx,&cx,&dx,&flags);
- }
-
- ax = 0x1200; /* Select 43-line print screen */
- bx = 0x0020; /* routine. */
- bios(16,&ax,&bx,&cx,&dx,&flags);
- }
-
- scpage(0);
-
- b_curknown[device] = 0; /* Forget former cursor types. */
- sccurst(&row,&col,&high,&low); /* Retrieve & record cursor type*/
- /* for all pages. */
-
- /* 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 MONO or COLOR to denote which entry of
- * the b_adap_state table to use.
- *
- * Description This function copies the five 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 MONO, one for */
- /* 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 five 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: */
-
- ADS save_ads;
- static char *save_area[2][5] = /* Pointers to the sections of */
- { /* the VIDEO_STATE structures */
- /* in the b_adap_state table */
- { b_adap_state[0].pc_area,
- (char *) &b_adap_state[0].reset_flag,
- b_adap_state[0].ega_area,
- (char *) &b_adap_state[0].save_ptr,
- &b_adap_state[0].ega_status},
-
- { b_adap_state[1].pc_area,
- (char *) &b_adap_state[1].reset_flag,
- b_adap_state[1].ega_area,
- (char *) &b_adap_state[1].save_ptr,
- &b_adap_state[1].ega_status}
- };
- static int save_size[5] = /* Sizes of the five sections */
- { /* of a VIDEO_STATE structure */
- sizeof(b_adap_state[0].pc_area),
- sizeof(b_adap_state[0].reset_flag),
- sizeof(b_adap_state[0].ega_area),
- sizeof(b_adap_state[0].save_ptr),
- sizeof(b_adap_state[0].ega_status)
- };
- static ADS bios_ads[5] = /* Addresses of the five blocks */
- { /* of BIOS variables */
- {0x0049,0x0040},
- {0x0072,0x0040},
- {0x0084,0x0040},
- {0x00a8,0x0040},
- {0x0100,0x0040}
- };
-
- if ( (dir != FROM_BIOS && dir != TO_BIOS)
- || (device != COLOR && device != 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 < 5; i++) /* For each of the five blocks, */
- {
- /* Compute address of the area */
- /* where it is to be saved. */
- utabsptr((char *) save_area[device][i],&save_ads);
-
- if (dir == FROM_BIOS) /* Copy the block of data */
- utslmove(&bios_ads[i],&save_ads,save_size[i]);/* from BIOS*/
- else
- utslmove(&save_ads,&bios_ads[i],save_size[i]); /* to BIOS */
- }
-
- 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. */
- }