mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2356 lines
67 KiB
2356 lines
67 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/* INSIGNIA (SUB)MODULE SPECIFICATION
|
|
-----------------------------
|
|
|
|
|
|
THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
|
|
CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
|
|
NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT THE EXPRESS
|
|
AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS LTD.
|
|
|
|
DOCUMENT : EGA BIOS
|
|
|
|
RELATED DOCS : IBM EGA Technical reference.
|
|
|
|
DESIGNER : William Gulland
|
|
|
|
REVISION HISTORY :
|
|
First version : 17/8/88 William
|
|
|
|
SUBMODULE NAME : ega_video
|
|
|
|
PURPOSE : Emulate IBM EGA BIOS.
|
|
|
|
|
|
SccsID[]="@(#)ega_video.c 1.70 07/04/95 Copyright Insignia Solutions Ltd.";
|
|
|
|
|
|
[1.INTERMODULE INTERFACE SPECIFICATION]
|
|
|
|
|
|
[1.1 INTERMODULE EXPORTS]
|
|
|
|
PROCEDURES() : give procedure type,name, and argument types
|
|
void ega_video_init()
|
|
void ega_video_io()
|
|
|
|
DATA : give type and name
|
|
|
|
-------------------------------------------------------------------------
|
|
[1.2 DATATYPES FOR [1.1] (if not basic C types)]
|
|
|
|
STRUCTURES/TYPEDEFS/ENUMS:
|
|
|
|
-------------------------------------------------------------------------
|
|
[1.3 INTERMODULE IMPORTS]
|
|
(not o/s objects or standard libs)
|
|
|
|
PROCEDURES() : give name, and source module name
|
|
|
|
DATA : give name, and source module name
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
[1.4 DESCRIPTION OF INTERMODULE INTERFACE]
|
|
|
|
[1.4.1 IMPORTED OBJECTS]
|
|
|
|
DATA OBJECTS : specify in following procedure descriptions
|
|
how these are accessed (read/modified)
|
|
|
|
[1.4.2 EXPORTED OBJECTS]
|
|
=========================================================================
|
|
PROCEDURE : ega_video_init()
|
|
|
|
PURPOSE : Initialize EGA-specific bits of the video BIOS.
|
|
|
|
PARAMETERS None
|
|
|
|
ACCESS : called from video_init if EGA installed.
|
|
|
|
DESCRIPTION : describe what (not how) function does
|
|
|
|
Initializes ega_info & ega_info3.
|
|
|
|
=========================================================================
|
|
|
|
/*=======================================================================
|
|
[3.INTERMODULE INTERFACE DECLARATIONS]
|
|
=========================================================================
|
|
|
|
[3.1 INTERMODULE IMPORTS] */
|
|
|
|
/* [3.1.1 #INCLUDES] */
|
|
|
|
|
|
#ifdef EGG
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
#include FCntlH
|
|
|
|
#include "xt.h"
|
|
#include CpuH
|
|
#include "sas.h"
|
|
#include "ios.h"
|
|
#include "gmi.h"
|
|
#include "gvi.h"
|
|
#include "bios.h"
|
|
#include "error.h"
|
|
#include "config.h"
|
|
#include "equip.h"
|
|
#include "egacpu.h"
|
|
#include "egaports.h"
|
|
#include "gfx_upd.h"
|
|
#include "egagraph.h"
|
|
#include "egaread.h"
|
|
#include "video.h"
|
|
#include "egavideo.h"
|
|
#include "vgaports.h"
|
|
#include "debug.h"
|
|
#include "timer.h"
|
|
#include "host_gfx.h"
|
|
#include "idetect.h"
|
|
#ifndef PROD
|
|
#include "trace.h"
|
|
#endif
|
|
#include "host.h"
|
|
|
|
#ifdef GISP_SVGA
|
|
#include HostHwVgaH
|
|
#include "hwvga.h"
|
|
#endif /* GISP_SVGA */
|
|
|
|
/* [3.1.2 DECLARATIONS] */
|
|
|
|
GLOBAL IU8 Video_mode; /* Shadow copy of BIOS video mode */
|
|
GLOBAL IU8 Currently_emulated_video_mode = 0; /* Holds last video mode
|
|
* set through bios */
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
/* Loads font from PC's BIOS into video memory */
|
|
IMPORT void loadNativeBIOSfont IPT1( int, lines );
|
|
#endif
|
|
|
|
#ifdef NTVDM
|
|
IMPORT int soft_reset;
|
|
IMPORT BOOL VDMForWOW;
|
|
IMPORT BOOL WowModeInitialized;
|
|
#ifndef X86GFX
|
|
IMPORT void mouse_video_mode_changed(int new_video_mode);
|
|
#endif
|
|
#endif /* NTVDM */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
GLOBAL IBOOL forceVideoRmSemantics = FALSE;
|
|
#endif
|
|
|
|
/*
|
|
5.MODULE INTERNALS : (not visible externally, global internally)]
|
|
|
|
[5.1 LOCAL DECLARATIONS] */
|
|
|
|
#ifdef ANSI
|
|
GLOBAL void ega_set_mode(void),ega_char_gen(void);
|
|
static void ega_set_palette(void),ega_alt_sel(void);
|
|
GLOBAL void ega_set_cursor_mode(void);
|
|
static void ega_emul_set_palette(void);
|
|
#else
|
|
GLOBAL void ega_set_mode(),ega_char_gen();
|
|
static void ega_set_palette(),ega_alt_sel();
|
|
GLOBAL void ega_set_cursor_mode();
|
|
static void ega_emul_set_palette();
|
|
#endif /* ANSI */
|
|
static void (*ega_video_func[]) () = {
|
|
ega_set_mode,
|
|
ega_set_cursor_mode,
|
|
vd_set_cursor_position,
|
|
vd_get_cursor_position,
|
|
vd_get_light_pen,
|
|
vd_set_active_page,
|
|
vd_scroll_up,
|
|
vd_scroll_down,
|
|
vd_read_attrib_char,
|
|
vd_write_char_attrib,
|
|
vd_write_char,
|
|
ega_emul_set_palette,
|
|
vd_write_dot,
|
|
vd_read_dot,
|
|
vd_write_teletype,
|
|
vd_get_mode,
|
|
ega_set_palette,
|
|
ega_char_gen,
|
|
ega_alt_sel,
|
|
vd_write_string,
|
|
#ifdef VGG
|
|
not_imp,
|
|
not_imp,
|
|
not_imp,
|
|
not_imp,
|
|
not_imp,
|
|
not_imp,
|
|
vga_disp_comb, /* Function 1A */
|
|
vga_disp_func,
|
|
vga_int_1C, /* Save/Restore Video State */
|
|
#endif
|
|
};
|
|
|
|
static int v7_mode_64_munge[4] ={0, 3, 12, 15};
|
|
IMPORT half_word bg_col_mask;
|
|
|
|
#ifdef VGG
|
|
/*
|
|
* Define arrays for mapping the Video BIOS call start and end
|
|
* cursor scanline to their corresponding VGA/EGA register values.
|
|
* There are seperate arrays for cursor start and end and for
|
|
* 8x8 and 8x16 char cell sizes.
|
|
*/
|
|
|
|
UTINY vga_cursor8_start[17][17] = {
|
|
/*00*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
|
/*01*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
/*02*/ 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
|
/*03*/ 0x00, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
/*04*/ 0x00, 0x01, 0x05, 0x06, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
/*05*/ 0x00, 0x01, 0x02, 0x05, 0x06, 0x07, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
|
/*06*/ 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
|
/*07*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*08*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
/*09*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
|
/*10*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
|
|
/*11*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
/*12*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x0c, 0x0c, 0x0c, 0x0c,
|
|
/*13*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x0d, 0x0d, 0x0d,
|
|
/*14*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x0e, 0x0e,
|
|
/*15*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07, 0x0f,
|
|
/*16*/ 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x06, 0x07,
|
|
};
|
|
|
|
|
|
UTINY vga_cursor16_start[17][17] = {
|
|
/*00*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
|
/*01*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
/*02*/ 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
|
/*03*/ 0x00, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
|
/*04*/ 0x00, 0x01, 0x0c, 0x0d, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
/*05*/ 0x00, 0x01, 0x02, 0x0c, 0x0d, 0x0e, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
|
/*06*/ 0x00, 0x01, 0x02, 0x08, 0x0c, 0x0d, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
|
/*07*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*08*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
|
/*09*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
|
/*10*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
|
|
/*11*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
|
/*12*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c,
|
|
/*13*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x0d, 0x0d, 0x0d,
|
|
/*14*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e, 0x0e, 0x0e,
|
|
/*15*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f,
|
|
/*16*/ 0x00, 0x01, 0x02, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x0d, 0x0e,
|
|
};
|
|
|
|
#ifdef USE_CURSOR_END_TABLES
|
|
|
|
UTINY vga_cursor8_end[17][17] = {
|
|
/*00*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
/*01*/ 0x01, 0x01, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*02*/ 0x02, 0x02, 0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*03*/ 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*04*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*05*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*06*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*07*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*08*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*09*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*10*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*11*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*12*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*13*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*14*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*15*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
/*16*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
};
|
|
|
|
UTINY vga_cursor16_end[17][17] = {
|
|
/*00*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
/*01*/ 0x01, 0x01, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*02*/ 0x02, 0x02, 0x02, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*03*/ 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*04*/ 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*05*/ 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*06*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*07*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*08*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*09*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*10*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*11*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*12*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*13*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f,
|
|
/*14*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f,
|
|
/*15*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
/*16*/ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
|
|
};
|
|
#endif /* USE_CURSOR_END_TABLES */
|
|
#endif /* VGG */
|
|
|
|
/* [5.1.1 #DEFINES] */
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #include specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "VIDEO_BIOS_EGA.seg"
|
|
#endif
|
|
|
|
/* [5.1.2 TYPEDEF, STRUCTURE, ENUM DECLARATIONS] */
|
|
|
|
|
|
/* [5.1.3 PROCEDURE() DECLARATIONS] */
|
|
|
|
/* -----------------------------------------------------------------------
|
|
[5.2 LOCAL DEFINITIONS]
|
|
|
|
[5.2.1 INTERNAL DATA DEFINITIONS */
|
|
|
|
/* [5.2.2 INTERNAL PROCEDURE DEFINITIONS] */
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
FUNCTION : do_outb
|
|
PURPOSE : handy utility to output a value to an EGA chip register.
|
|
INPUT PARAMS : index port, register, value to write
|
|
RETURN PARAMS : None
|
|
==========================================================================
|
|
FUNCTION : follow_ptr
|
|
PURPOSE : handy utility to follow a 'long' intel pointer.
|
|
INPUT PARAMS : Address in M of the pointer
|
|
RETURN PARAMS : Address in M of the pointed-to byte.
|
|
==========================================================================
|
|
FUNCTION : low_set_mode
|
|
PURPOSE : Does low-level mode change.
|
|
EXTERNAL OBJECTS: list any used, and state changes incurred
|
|
RETURN VALUE :
|
|
INPUT PARAMS : mode: screen mode to change to.
|
|
RETURN PARAMS :
|
|
==========================================================================
|
|
FUNCTION : load_font
|
|
PURPOSE : load part of a font into EGA font memory.
|
|
EXTERNAL OBJECTS: list any used, and state changes incurred
|
|
RETURN VALUE :
|
|
INPUT PARAMS : sys_addr table Address in M of the character bitmaps
|
|
int count number of characters to redefine
|
|
int char_off first character to redefine
|
|
int font_no font to change
|
|
int nbytes Number of bytes per character
|
|
RETURN PARAMS :
|
|
==========================================================================
|
|
PROCEDURE : ega_set_mode()
|
|
PURPOSE : Switch screen mode.
|
|
PARAMETERS : AL = mode.
|
|
|
|
GLOBALS : describe what exported data objects are
|
|
accessed and how. Likewise for imported
|
|
data objects.
|
|
|
|
ACCESS : via ega_video_func[] jump table.
|
|
|
|
RETURNED VALUE : None.
|
|
|
|
DESCRIPTION :
|
|
==========================================================================
|
|
PROCEDURE : ega_alt_sel()
|
|
PURPOSE : Get EGA info
|
|
PARAMETERS : BL = function
|
|
GLOBALS :
|
|
ACCESS : via ega_video_func[] jump table.
|
|
RETURNED VALUE : None.
|
|
DESCRIPTION :
|
|
==========================================================================
|
|
FUNCTION : ega_set_palette
|
|
PURPOSE : brief description
|
|
EXTERNAL OBJECTS: list any used, and state changes incurred
|
|
RETURN VALUE :
|
|
INPUT PARAMS :
|
|
RETURN PARAMS :
|
|
==========================================================================
|
|
FUNCTION : ega_emul_set_palette
|
|
PURPOSE : brief description
|
|
EXTERNAL OBJECTS: list any used, and state changes incurred
|
|
RETURN VALUE :
|
|
INPUT PARAMS :
|
|
RETURN PARAMS :
|
|
==========================================================================
|
|
FUNCTION : ega_char_gen
|
|
PURPOSE : brief description
|
|
EXTERNAL OBJECTS: list any used, and state changes incurred
|
|
RETURN VALUE :
|
|
INPUT PARAMS :
|
|
RETURN PARAMS :
|
|
==========================================================================
|
|
FUNCTION : write_ch_set/xor()
|
|
PURPOSE : Output character to screen in EGA graphics modes.
|
|
EXTERNAL OBJECTS: list any used, and state changes incurred
|
|
RETURN VALUE :
|
|
INPUT PARAMS :
|
|
RETURN PARAMS :
|
|
==========================================================================
|
|
FUNCTION : name
|
|
PURPOSE : brief description
|
|
EXTERNAL OBJECTS: list any used, and state changes incurred
|
|
RETURN VALUE :
|
|
INPUT PARAMS :
|
|
RETURN PARAMS :
|
|
==========================================================================
|
|
*/
|
|
#ifdef VGG
|
|
/* Called for not implemented functions */
|
|
void not_imp IFN0()
|
|
{
|
|
setAL(0);
|
|
}
|
|
#endif
|
|
|
|
static void do_outb IFN3(int, index,int, ega_reg, byte, value)
|
|
{
|
|
outb(index,ega_reg);
|
|
outb(index+1,value);
|
|
}
|
|
|
|
sys_addr video_effective_addr IFN2(IU16, seg, IU16, offset)
|
|
{
|
|
#ifdef CPU_40_STYLE
|
|
if (forceVideoRmSemantics)
|
|
{
|
|
/* can't call effective_addr, as the segment is almost
|
|
** certainly bogus in prot mode. This mode of operation
|
|
** should ONLY be used when we are bypassing going to v86
|
|
** mode to do a video bios operation (see WinVDD.c)
|
|
*/
|
|
return((sys_addr)((((IU32)seg)<<4) + offset));
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
return effective_addr(seg, offset);
|
|
}
|
|
}
|
|
|
|
sys_addr follow_ptr IFN1(sys_addr, addr)
|
|
{
|
|
return video_effective_addr(sas_w_at_no_check(addr+2),
|
|
sas_w_at_no_check(addr));
|
|
}
|
|
|
|
void low_set_mode IFN1(int, mode)
|
|
{
|
|
int i;
|
|
sys_addr save_addr,params_addr,palette_addr;
|
|
word temp_word;
|
|
half_word start, end, video_mode;
|
|
|
|
|
|
params_addr = find_mode_table(mode,&save_addr);
|
|
|
|
/* setup Sequencer */
|
|
#ifndef REAL_VGA
|
|
do_outb(EGA_SEQ_INDEX,0,1); /* Synchronous reset - turn off Sequencer */
|
|
#else
|
|
do_outb(EGA_SEQ_INDEX,0,0); /* Reset - turn off Sequencer */
|
|
#endif
|
|
do_outb(EGA_CRTC_INDEX,0x11,0);
|
|
for(i=0;i<EGA_PARMS_SEQ_SIZE;i++)
|
|
{
|
|
do_outb(EGA_SEQ_INDEX,i+1,sas_hw_at_no_check(params_addr+EGA_PARMS_SEQ+i));
|
|
}
|
|
do_outb(EGA_SEQ_INDEX,0,3); /* Turn Sequencer back on */
|
|
/* setup Miscellaneous register */
|
|
outb(EGA_MISC_REG,sas_hw_at_no_check(params_addr+EGA_PARMS_MISC));
|
|
/* setup CRTC */
|
|
for(i=0;i<EGA_PARMS_CRTC_SIZE;i++)
|
|
{
|
|
do_outb(EGA_CRTC_INDEX,i,sas_hw_at_no_check(params_addr+EGA_PARMS_CRTC+i));
|
|
}
|
|
if (video_adapter == EGA) {
|
|
if( (get_EGA_switches() & 1) && mode < 4)
|
|
{
|
|
/* For some reason, the CRTC parameter table for 'enhanced' text has
|
|
* the same cursor start and end as for 'unenhanced' text.
|
|
* So fix the cursor start & end values to sensible things.
|
|
* This is not the case for the VGA BIOS mode table.
|
|
*/
|
|
do_outb(EGA_CRTC_INDEX, R10_CURS_START, 11);
|
|
do_outb(EGA_CRTC_INDEX, R11_CURS_END, 12);
|
|
}
|
|
}
|
|
/* setup attribute chip - NB need to do an inb() to clear the address */
|
|
inb(EGA_IPSTAT1_REG, (half_word *)&temp_word);
|
|
for(i=0;i<EGA_PARMS_ATTR_SIZE;i++)
|
|
{
|
|
outb(EGA_AC_INDEX_DATA,i);
|
|
outb(EGA_AC_INDEX_DATA,sas_hw_at_no_check(params_addr+EGA_PARMS_ATTR+i));
|
|
}
|
|
/* setup graphics chips */
|
|
for(i=0;i<EGA_PARMS_GRAPH_SIZE;i++)
|
|
{
|
|
do_outb(EGA_GC_INDEX,i,sas_hw_at_no_check(params_addr+EGA_PARMS_GRAPH+i));
|
|
}
|
|
|
|
#ifdef V7VGA
|
|
/* setup extensions registers */
|
|
#ifndef GISP_SVGA /* Don't want the V7 stuff for GISP
|
|
builds that still use our
|
|
video ROMS */
|
|
|
|
if (video_adapter == VGA)
|
|
{
|
|
/* turn on extension registers */
|
|
do_outb(EGA_SEQ_INDEX, 6, 0xea);
|
|
|
|
if (mode < 0x46)
|
|
{
|
|
do_outb(EGA_SEQ_INDEX, 0xfd, 0x22);
|
|
do_outb(EGA_SEQ_INDEX, 0xa4, 0x00);
|
|
do_outb(EGA_SEQ_INDEX, 0xfc, 0x08);
|
|
do_outb(EGA_SEQ_INDEX, 0xf6, 0x00);
|
|
do_outb(EGA_SEQ_INDEX, 0xf8, 0x00);
|
|
do_outb(EGA_SEQ_INDEX, 0xff, 0x00);
|
|
}
|
|
else
|
|
{
|
|
if (mode < 0x62)
|
|
do_outb(EGA_SEQ_INDEX, 0xfd, 0x00);
|
|
else if (mode == 0x62)
|
|
do_outb(EGA_SEQ_INDEX, 0xfd, 0x90);
|
|
else
|
|
do_outb(EGA_SEQ_INDEX, 0xfd, 0xa0);
|
|
|
|
if (mode == 0x60)
|
|
do_outb(EGA_SEQ_INDEX, 0xa4, 0x00);
|
|
else
|
|
do_outb(EGA_SEQ_INDEX, 0xa4, 0x10);
|
|
|
|
if (mode < 0x66)
|
|
if ((mode == 0x63) || (mode == 0x64))
|
|
do_outb(EGA_SEQ_INDEX, 0xfc, 0x18);
|
|
else
|
|
do_outb(EGA_SEQ_INDEX, 0xfc, 0x08);
|
|
else
|
|
do_outb(EGA_SEQ_INDEX, 0xfc, 0x6c);
|
|
|
|
if ((mode < 0x65) || (mode == 0x66))
|
|
{
|
|
do_outb(EGA_SEQ_INDEX, 0xf6, 0x00);
|
|
do_outb(EGA_SEQ_INDEX, 0xff, 0x00);
|
|
}
|
|
else
|
|
{
|
|
do_outb(EGA_SEQ_INDEX, 0xf6, 0xc0);
|
|
do_outb(EGA_SEQ_INDEX, 0xff, 0x10);
|
|
}
|
|
|
|
if (mode == 0x62)
|
|
do_outb(EGA_SEQ_INDEX, 0xf8, 0x10);
|
|
else
|
|
do_outb(EGA_SEQ_INDEX, 0xf8, 0x00);
|
|
}
|
|
|
|
/* turn off extension registers */
|
|
do_outb(EGA_SEQ_INDEX, 6, 0xae);
|
|
}
|
|
#endif /* GISP_SVGA */
|
|
|
|
/***
|
|
Update Extended BIOS data stuff ?
|
|
***/
|
|
#endif
|
|
|
|
/*
|
|
* Update BIOS data variables
|
|
*/
|
|
|
|
sas_storew_no_check(VID_COLS,sas_hw_at_no_check(params_addr+EGA_PARMS_COLS)); /* byte in ROM, word in BIOS var! */
|
|
sas_store_no_check(vd_rows_on_screen, sas_hw_at_no_check(params_addr+EGA_PARMS_ROWS));
|
|
sas_store_no_check(ega_char_height, sas_hw_at_no_check(params_addr+EGA_PARMS_HEIGHT));
|
|
sas_storew_no_check(VID_LEN,sas_w_at_no_check(params_addr+EGA_PARMS_LENGTH));
|
|
|
|
/* save cursor mode: BIOS data area has end byte at the low address,
|
|
so the bytes must be swapped over from the CRTC register sense */
|
|
start = sas_hw_at_no_check(params_addr+EGA_PARMS_CURSOR);
|
|
sas_store_no_check(VID_CURMOD+1, start);
|
|
end = sas_hw_at_no_check(params_addr+EGA_PARMS_CURSOR+1);
|
|
sas_store_no_check(VID_CURMOD, end);
|
|
sure_sub_note_trace2(CURSOR_VERBOSE,"changing mode, setting cursor bios vbls to start=%d, end=%d",start,end);
|
|
sure_sub_note_trace2(CURSOR_VERBOSE,"changing mode, mode=%#x, params_addr=%#x",mode,params_addr);
|
|
|
|
/* save Palette registers if necessary */
|
|
palette_addr = follow_ptr(save_addr+PALETTE_OFFSET);
|
|
if(palette_addr)
|
|
{
|
|
for(i=0;i<16;i++)
|
|
sas_store_no_check(palette_addr+i, sas_hw_at_no_check(params_addr+EGA_PARMS_ATTR+i));
|
|
sas_store_no_check(palette_addr+16, sas_hw_at_no_check(params_addr+EGA_PARMS_ATTR+17));
|
|
}
|
|
|
|
/* Get the video_.. variables from the mode table */
|
|
video_mode = sas_hw_at_no_check(vd_video_mode);
|
|
#ifdef V7VGA
|
|
if (video_adapter == VGA)
|
|
{
|
|
if (video_mode > 0x13)
|
|
video_mode += 0x4c;
|
|
else if ((video_mode == 1) && extensions_controller.foreground_latch_1)
|
|
video_mode = extensions_controller.foreground_latch_1;
|
|
}
|
|
|
|
if (video_mode >= 0x60)
|
|
{
|
|
video_pc_low_regen = vd_ext_graph_table[video_mode-0x60].start_addr;
|
|
video_pc_high_regen = vd_ext_graph_table[video_mode-0x60].end_addr;
|
|
}
|
|
else if (video_mode >= 0x40)
|
|
{
|
|
video_pc_low_regen = vd_ext_text_table[video_mode-0x40].start_addr;
|
|
video_pc_high_regen = vd_ext_text_table[video_mode-0x40].end_addr;
|
|
}
|
|
else
|
|
{
|
|
video_pc_low_regen = vd_mode_table[video_mode].start_addr;
|
|
video_pc_high_regen = vd_mode_table[video_mode].end_addr;
|
|
}
|
|
#else
|
|
video_pc_low_regen = vd_mode_table[video_mode].start_addr;
|
|
video_pc_high_regen = vd_mode_table[video_mode].end_addr;
|
|
#endif /* V7VGA */
|
|
|
|
#ifdef VGG
|
|
if (video_adapter == VGA) {
|
|
i = get_scanlines(); /* WARNING - needs the BIOS variables! */
|
|
if(mode == 0x13 || mode > 0x65)
|
|
{
|
|
init_vga_dac(2); /* 256 colour DAC table */
|
|
}
|
|
else if(i == RS200 || mode == 0x63 || mode == 0x64)
|
|
{
|
|
init_vga_dac(1); /* DACs to emulate CGA palette - RGB + Intensity*/
|
|
}
|
|
else
|
|
{
|
|
init_vga_dac(0); /* DACs to emulate EGA palette - RGB + rgb */
|
|
}
|
|
outb(VGA_DAC_MASK,0xff);
|
|
/* Initialize the fancy VGA palette stuff to look like an EGA */
|
|
inb(EGA_IPSTAT1_REG, (half_word *)&temp_word);
|
|
outb(EGA_AC_INDEX_DATA, 20); /* Pixel padding register */
|
|
outb(EGA_AC_INDEX_DATA, 0); /* Use first block of 64 in DACs */
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Load part of a font into EGA font memory. */
|
|
void load_font IFN5
|
|
(
|
|
sys_addr, table, /* Address in M of the character bitmaps */
|
|
int, count, /* number of characters to redefine */
|
|
int, char_off, /* first character to redefine */
|
|
int, font_no, /* font to change */
|
|
int, nbytes /* Number of bytes per character */
|
|
)
|
|
{
|
|
#if !(defined(NTVDM) && defined(X86GFX))
|
|
int i,j;
|
|
sys_addr font_addr;
|
|
sys_addr data_addr;
|
|
#endif /* !(NTVDM && X86GFX) */
|
|
half_word temp_word;
|
|
half_word video_mode;
|
|
static word font_off[] = { 0, 0x4000, 0x8000, 0xc000, 0x2000, 0x6000, 0xa000, 0xe000 };
|
|
|
|
/* First switch to font loading mode */
|
|
low_set_mode(FONT_LOAD_MODE);
|
|
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
loadNativeBIOSfont( 25 );
|
|
|
|
#else
|
|
#ifdef GISP_SVGA
|
|
if( hostIsFullScreen( ) )
|
|
{
|
|
loadFontToVGA( table , count , char_off , font_no , nbytes );
|
|
}
|
|
else
|
|
{
|
|
loadFontToEmulation( table , count , char_off , font_no , nbytes );
|
|
}
|
|
#else /* GISP_SVGA */
|
|
|
|
|
|
/* Work out where to put the font. */
|
|
font_addr = 0xA0000 + font_off[font_no] + FONT_MAX_HEIGHT*char_off;
|
|
data_addr = table;
|
|
|
|
for(i=0;i<count;i++) /* for each character */
|
|
{
|
|
for(j=0;j<nbytes;j++) /* for each byte of character */
|
|
{
|
|
sas_store(font_addr, sas_hw_at_no_check(data_addr));
|
|
font_addr++;
|
|
data_addr++;
|
|
}
|
|
|
|
font_addr += (FONT_MAX_HEIGHT - nbytes);
|
|
}
|
|
#endif /* GISP_SVGA */
|
|
#endif /* NTVDM && X86GFX */
|
|
|
|
/* Finally switch back to the BIOS mode */
|
|
video_mode = sas_hw_at_no_check(vd_video_mode);
|
|
#ifdef V7VGA
|
|
if (video_adapter == VGA)
|
|
if (video_mode > 0x13)
|
|
video_mode += 0x4c;
|
|
else if ((video_mode == 1) && extensions_controller.foreground_latch_1)
|
|
video_mode = extensions_controller.foreground_latch_1;
|
|
#endif /* V7VGA */
|
|
|
|
low_set_mode(video_mode);
|
|
inb(EGA_IPSTAT1_REG,&temp_word);
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
|
|
}
|
|
|
|
void recalc_text IFN1(int, height)
|
|
{
|
|
int scan_lines;
|
|
half_word video_mode;
|
|
word screen_height;
|
|
half_word oflo;
|
|
half_word protect;
|
|
#ifdef NTVDM
|
|
MAX_SCAN_LINE crtc_reg9;
|
|
#endif
|
|
|
|
video_mode = sas_hw_at_no_check(vd_video_mode);
|
|
#ifdef V7VGA
|
|
if (video_adapter == VGA)
|
|
if (video_mode > 0x13)
|
|
video_mode += 0x4c;
|
|
else if ((video_mode == 1) && extensions_controller.foreground_latch_1)
|
|
video_mode = extensions_controller.foreground_latch_1;
|
|
#endif /* V7VGA */
|
|
|
|
if(video_adapter == EGA && !(get_EGA_switches() & 1) && (video_mode < 4))
|
|
scan_lines = 200; /* Low res text mode */
|
|
else
|
|
scan_lines = get_screen_height() + 1;
|
|
|
|
sas_store_no_check(ega_char_height, height);
|
|
sas_store_no_check(vd_rows_on_screen, scan_lines/height - 1);
|
|
if ( video_mode < 4 && scan_lines/height == 25 )
|
|
sas_storew_no_check(VID_LEN, video_mode<2 ? 0x800 : 0x1000);
|
|
else
|
|
sas_storew_no_check(VID_LEN,(sas_hw_at_no_check(vd_rows_on_screen)+1)*sas_w_at_no_check(VID_COLS)*2);
|
|
#ifdef NTVDM
|
|
/* preserve other bits in register 9 for VGA */
|
|
if (video_adapter == VGA) {
|
|
outb(EGA_CRTC_INDEX, 9);
|
|
inb(EGA_CRTC_DATA, (half_word *) &crtc_reg9);
|
|
crtc_reg9.as_bfld.maximum_scan_line = height -1;
|
|
outb(EGA_CRTC_DATA, crtc_reg9.as.abyte);
|
|
}
|
|
else
|
|
do_outb(EGA_CRTC_INDEX,9,height-1); /* Character height */
|
|
#else
|
|
do_outb(EGA_CRTC_INDEX,9,height-1); /* Character height */
|
|
#endif
|
|
do_outb(EGA_CRTC_INDEX,0xA,height-1); /* Cursor start */
|
|
do_outb(EGA_CRTC_INDEX,0xB,0); /* Cursor end */
|
|
|
|
/*
|
|
* VGA adapter height setting occupies Vertical Display End register
|
|
* plus 2 bits in the overflow register. The overflow register may also
|
|
* be write protected.
|
|
*/
|
|
if (video_adapter == VGA)
|
|
{
|
|
#ifdef NTVDM
|
|
/* Some globals that the mouse driver needs to have available */
|
|
/* when an application (such as any CW based apps.) makes a */
|
|
/* call to int 33h AX = 26h. */
|
|
|
|
IMPORT word VirtualX, VirtualY;
|
|
#endif /* NTVDM */
|
|
|
|
screen_height = (sas_hw_at_no_check(vd_rows_on_screen)+1)*height-1;
|
|
|
|
#ifdef NTVDM
|
|
/* Create the virtual screen size maximums for the text modes */
|
|
/* This is needed here for CW applications. */
|
|
|
|
VirtualX = 640; /* This is always this value */
|
|
if(scan_lines == 401)
|
|
VirtualY = 400; /* 50 text row mode - 400 scanlines */
|
|
else if(scan_lines == 351)
|
|
VirtualY = 344; /* 43 text row mode - 350 scanlines */
|
|
else
|
|
VirtualY = 200; /* Failsafe - 25 row mode or rest! */
|
|
|
|
#endif /* NTVDM */
|
|
|
|
outb(EGA_CRTC_INDEX, 7); /* overflow register */
|
|
inb(EGA_CRTC_DATA, &oflo);
|
|
outb(EGA_CRTC_INDEX, 0x11); /* vert sync contains protect bit */
|
|
inb(EGA_CRTC_DATA, &protect);
|
|
|
|
if (screen_height & 0x100)
|
|
oflo |= 2; /* bit 8 of height -> bit 1 of overflow register */
|
|
else
|
|
oflo &= ~2;
|
|
if (screen_height & 0x200)
|
|
oflo |= 0x40; /* bit 9 of height -> bit 6 of overflow register */
|
|
else
|
|
oflo &= ~0x40;
|
|
if ((protect & 0x80) == 0x80) /* overflow reg protected */
|
|
{
|
|
do_outb(EGA_CRTC_INDEX, 0x11, protect & 0x7f); /* enable writes */
|
|
do_outb(EGA_CRTC_INDEX, 7, oflo); /* overflow reg */
|
|
do_outb(EGA_CRTC_INDEX, 0x11, protect); /* put back old value */
|
|
}
|
|
else
|
|
do_outb(EGA_CRTC_INDEX, 7, oflo); /* overflow reg */
|
|
|
|
do_outb(EGA_CRTC_INDEX,0x12, screen_height & 0xff); /* Vertical display end = scan lines */
|
|
}
|
|
else
|
|
if (video_adapter == EGA)
|
|
{
|
|
screen_height = (sas_hw_at_no_check(vd_rows_on_screen)+1)*height-1;
|
|
outb(EGA_CRTC_INDEX, 7); /* overflow register */
|
|
inb(EGA_CRTC_DATA, &oflo);
|
|
if (screen_height & 0x100)
|
|
oflo |= 2; /* bit 8 of height -> bit 1 of overflow reg */
|
|
else
|
|
oflo &= ~2;
|
|
do_outb(EGA_CRTC_INDEX, 7, oflo); /* overflow reg */
|
|
do_outb(EGA_CRTC_INDEX, 0x12, screen_height & 0xff); /* Vertical display end = scan lines */
|
|
}
|
|
else
|
|
{
|
|
assert1(NO, "Bad video adapter (%d) in recalc_text", video_adapter);
|
|
}
|
|
|
|
do_outb(EGA_CRTC_INDEX,0x14,height); /* Underline scan line - ie no underline */
|
|
}
|
|
|
|
static void set_graph_font IFN1(int, height)
|
|
{
|
|
switch (getBL())
|
|
{
|
|
case 0:
|
|
sas_store_no_check(vd_rows_on_screen, getDL()-1);
|
|
break;
|
|
case 1:
|
|
sas_store_no_check(vd_rows_on_screen, 13);
|
|
break;
|
|
case 2:
|
|
sas_store_no_check(vd_rows_on_screen, 24);
|
|
break;
|
|
case 3:
|
|
sas_store_no_check(vd_rows_on_screen, 42);
|
|
break;
|
|
default:
|
|
assert2(FALSE,"Illegal char gen sub-function %#x:%#x",getAL(),getBL());
|
|
}
|
|
sas_store_no_check(ega_char_height, height);
|
|
}
|
|
|
|
LOCAL VOID
|
|
write_ch_set IFN5(sys_addr, char_addr, int, screen_off,
|
|
int, colour, int, nchs, int, scan_length)
|
|
{
|
|
unsigned int i, j, colourmask, data, temp, char_height;
|
|
unsigned int *screen;
|
|
register sys_addr font;
|
|
|
|
#ifndef REAL_VGA
|
|
|
|
/*
|
|
* video mode 11 (VGA 640x480 2 colour mode) is a special case as
|
|
* it does not have a 'no display' attribute.
|
|
*/
|
|
|
|
if( sas_hw_at_no_check(vd_video_mode) == 0x11 )
|
|
colourmask = ~0;
|
|
else
|
|
colourmask = sr_lookup[colour & 0xf];
|
|
|
|
font = char_addr;
|
|
|
|
screen = (unsigned int *) &EGA_planes[screen_off << 2];
|
|
char_height = sas_hw_at_no_check(ega_char_height);
|
|
|
|
if( nchs == 1 )
|
|
{
|
|
for( i = char_height; i > 0; i-- )
|
|
{
|
|
data = sas_hw_at_no_check(font);
|
|
font++;
|
|
temp = data << 8;
|
|
data |= temp;
|
|
temp = data << 16;
|
|
data |= temp;
|
|
|
|
*screen = data & colourmask;
|
|
screen += scan_length;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scan_length -= nchs;
|
|
|
|
for( i = char_height; i > 0; i-- )
|
|
{
|
|
data = sas_hw_at_no_check(font);
|
|
font++;
|
|
temp = data << 8;
|
|
data |= temp;
|
|
temp = data << 16;
|
|
data |= temp;
|
|
|
|
data &= colourmask;
|
|
|
|
for( j = nchs; j > 0; j-- )
|
|
{
|
|
*screen++ = data;
|
|
}
|
|
|
|
screen += scan_length;
|
|
}
|
|
}
|
|
#else
|
|
vga_card_w_ch_set(char_addr, screen_off, colour, nchs, scan_length, char_height);
|
|
#endif
|
|
}
|
|
|
|
void write_ch_xor IFN5(sys_addr, char_addr, int, screen_off,
|
|
int, colour, int, nchs, int, scan_length)
|
|
{
|
|
unsigned int i, j, colourmask, data, temp, char_height;
|
|
unsigned int *screen;
|
|
register sys_addr font;
|
|
|
|
#ifndef REAL_VGA
|
|
/*
|
|
* video mode 11 (VGA 640x480 2 colour mode) is a special case as
|
|
* it does not have a 'no display' attribute.
|
|
*/
|
|
if(sas_hw_at_no_check(vd_video_mode) == 0x11)
|
|
colourmask = ~0;
|
|
else
|
|
colourmask = sr_lookup[colour & 0xf];
|
|
|
|
font = char_addr;
|
|
char_height = sas_hw_at_no_check(ega_char_height);
|
|
|
|
screen = (unsigned int *) &EGA_planes[screen_off << 2];
|
|
|
|
if( nchs == 1 )
|
|
{
|
|
for( i = char_height; i > 0; i-- )
|
|
{
|
|
data = sas_hw_at_no_check(font);
|
|
font++;
|
|
temp = data << 8;
|
|
data |= temp;
|
|
temp = data << 16;
|
|
data |= temp;
|
|
|
|
*screen ^= data & colourmask;
|
|
screen += scan_length;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scan_length -= nchs;
|
|
|
|
for( i = char_height; i > 0; i-- )
|
|
{
|
|
data = sas_hw_at_no_check(font);
|
|
font++;
|
|
temp = data << 8;
|
|
data |= temp;
|
|
temp = data << 16;
|
|
data |= temp;
|
|
|
|
data &= colourmask;
|
|
|
|
for( j = nchs; j > 0; j-- )
|
|
{
|
|
*screen++ ^= data;
|
|
}
|
|
|
|
screen += scan_length;
|
|
}
|
|
}
|
|
#else
|
|
vga_card_w_ch_xor(char_addr, screen_off, colour, nchs, scan_length, char_height);
|
|
#endif
|
|
}
|
|
|
|
GLOBAL void ega_set_mode IFN0()
|
|
{
|
|
int pag;
|
|
sys_addr save_addr,font_addr;
|
|
int font_offset;
|
|
half_word temp_word;
|
|
byte mode_byte;
|
|
byte video_mode;
|
|
#ifdef V7VGA
|
|
byte saveBL;
|
|
#endif /* V7VGA */
|
|
|
|
#ifndef PROD
|
|
trace("setting video mode", DUMP_REG);
|
|
#endif
|
|
|
|
#ifdef GISP_SVGA
|
|
/* Try and catch mode changes early */
|
|
|
|
/* Are we in the ROMS at the BOP 10 ? */
|
|
if( getCS( ) == EgaROMSegment )
|
|
{
|
|
if( videoModeIs( getAL( ) , GRAPH ) )
|
|
{
|
|
/* Seem to have got a video mode int 10 */
|
|
videoInfo.modeType = GRAPH;
|
|
if( !hostEasyMode( ) )
|
|
{
|
|
videoInfo.forcedFullScreen = TRUE;
|
|
|
|
/* point IP at the JMP to host roms */
|
|
setIP( 0x820 );
|
|
|
|
/* and return, to let the host bios do the change */
|
|
return;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/* Not in the vga roms so carry on */
|
|
}
|
|
#endif /* GISP_SVGA */
|
|
|
|
#ifdef V7VGA
|
|
/*
|
|
Real video-7 maps mode 7 and mode f to mode 0.
|
|
*/
|
|
|
|
if (video_adapter==VGA) {
|
|
video_mode=(getAL()&0x7F);
|
|
if (video_mode==7||video_mode==0xF) {
|
|
setAL(getAL()&0x80);
|
|
always_trace1("V7 doesn't support mode %02x, using mode 0\n",video_mode);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (is_bad_vid_mode(getAL()))
|
|
{
|
|
#ifdef V7VGA
|
|
if ((video_adapter == VGA) && is_v7vga_mode(getAL() + 0x4c))
|
|
{
|
|
saveBL = getBL();
|
|
/* Put the mode value where the V7 BIOS expects it */
|
|
setBL(getAL() + 0x4c);
|
|
v7vga_extended_set_mode();
|
|
setBL(saveBL);
|
|
}
|
|
else
|
|
#endif /* V7VGA */
|
|
always_trace1("Bad video mode - %d.\n", getAL());
|
|
return;
|
|
}
|
|
|
|
video_mode=(getAL()&0x7F);
|
|
|
|
#ifdef V7VGA
|
|
/*
|
|
* The real V7 VGA does not change into 40 col mode while
|
|
* in any proprietary text mode. (A bug ?!)
|
|
* Emulate this behaviour !
|
|
*/
|
|
if ( video_adapter == VGA && video_mode == 1
|
|
&& is_v7vga_mode(extensions_controller.foreground_latch_1) ) {
|
|
saveBL = getBL();
|
|
/*
|
|
* This is all backwards - we make the v7vga extended mode setup
|
|
* believe the new mode is the old one. Probably the real card's BIOS
|
|
* is just as confused as this code.
|
|
* Put the mode value where the V7 BIOS expects it.
|
|
*/
|
|
setBL(extensions_controller.foreground_latch_1);
|
|
v7vga_extended_set_mode();
|
|
setBL(saveBL);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Don't confuse the tricky V7 extended mode setting, as
|
|
* implemented in v7_video.c, v7vga_extended_set_mode().
|
|
* low_set_mode() looks at it. Zero it.
|
|
*/
|
|
extensions_controller.foreground_latch_1 = 0;
|
|
#endif /* V7VGA */
|
|
|
|
/*
|
|
* Only update the global video mode if we're in the system virtual machine.
|
|
* The global mode should then be valid for use in timer interrupts.
|
|
*/
|
|
|
|
if (sas_hw_at_no_check(BIOS_VIRTUALISING_BYTE) == 0)
|
|
Video_mode = video_mode;
|
|
|
|
sas_store_no_check(vd_video_mode, getAL() & 0x7F); /* get rid of top bit - indicates clear or not */
|
|
sas_store_no_check(ega_info, (sas_hw_at_no_check(ega_info) & 0x7F ) | (getAL() & 0x80)); /* update screen clear flag in ega_info */
|
|
|
|
#ifdef CPU_40_STYLE
|
|
if (forceVideoRmSemantics && (!get_EGA_no_clear()))
|
|
{
|
|
/* empty the planes... */
|
|
memset(&EGA_planes[0], 0, 64*1024*4);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MSWDVR
|
|
/*
|
|
* If the video mode has actually changed, then call
|
|
* host_mswin_disable().
|
|
*/
|
|
if (Currently_emulated_video_mode != video_mode)
|
|
{
|
|
#ifdef CPU_40_STYLE
|
|
if (!getPE())
|
|
{
|
|
host_mswin_disable();
|
|
}
|
|
#else
|
|
host_mswin_disable();
|
|
#endif /* CPU_40_STYLE */
|
|
}
|
|
#endif /* MSWDVR */
|
|
|
|
Currently_emulated_video_mode = video_mode;
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
/*
|
|
** Tim August 92. MicroSoft.
|
|
** Give host a chance to do a zany non-standard mode change.
|
|
** For Microsoft NT this is a transition to full-screen ie. the
|
|
** real PC's video BIOS and graphics board.
|
|
**
|
|
** Return value of TRUE means host has done the mode change for
|
|
** us, so no need to continue.
|
|
*/
|
|
{
|
|
extern BOOL hostModeChange IPT0();
|
|
|
|
if( hostModeChange() )
|
|
return;
|
|
}
|
|
#endif /* NTVDM & X86GFX */
|
|
|
|
save_addr = follow_ptr(EGA_SAVEPTR);
|
|
if(alpha_num_mode())
|
|
{
|
|
#ifdef VGG
|
|
/* load_font will do the mode change for us */
|
|
if (video_adapter == VGA)
|
|
{
|
|
#ifdef NTVDM
|
|
/* Some globals that the mouse driver needs to have available */
|
|
/* when an application (such as any CW based apps.) makes a */
|
|
/* call to int 33h AX = 26h. */
|
|
|
|
IMPORT word VirtualX, VirtualY;
|
|
#endif /* NTVDM */
|
|
|
|
switch (get_VGA_lines())
|
|
{
|
|
case S350:
|
|
load_font(EGA_CGMN,256,0,0,14);
|
|
#ifdef NTVDM
|
|
VirtualX = 640;
|
|
VirtualY = 344;
|
|
#endif /* NTVDM */
|
|
break;
|
|
case S400:
|
|
load_font(EGA_HIFONT,256,0,0,16);
|
|
#ifdef NTVDM
|
|
/* This one gets hit the most by C.W. applications. */
|
|
/* Actually, the other cases never seem to get hit */
|
|
/* but are there JUST IN CASE! The 43 and 50 row */
|
|
/* modes in recalc_text(). */
|
|
|
|
VirtualX = 640;
|
|
VirtualY = 200;
|
|
#endif /* NTVDM */
|
|
break;
|
|
default:
|
|
load_font(EGA_CGDDOT,256,0,0,8);
|
|
#ifdef NTVDM
|
|
VirtualX = 640;
|
|
VirtualY = 400;
|
|
#endif /* NTVDM */
|
|
}
|
|
}
|
|
else
|
|
#endif /* VGG */
|
|
{
|
|
if(get_EGA_switches() & 1)
|
|
load_font(EGA_CGMN,256,0,0,14);
|
|
else
|
|
load_font(EGA_CGDDOT,256,0,0,8);
|
|
}
|
|
/* Now see if we have a nasty font to load */
|
|
font_addr = follow_ptr(save_addr+ALPHA_FONT_OFFSET);
|
|
if(font_addr != 0)
|
|
{
|
|
/* See if it applies to us */
|
|
font_offset = 11;
|
|
do
|
|
{
|
|
mode_byte = sas_hw_at_no_check(font_addr + font_offset);
|
|
if(mode_byte == video_mode)
|
|
{
|
|
load_font(follow_ptr(font_addr+6),sas_w_at_no_check(font_addr+2),sas_w_at_no_check(font_addr+4), sas_hw_at_no_check(font_addr+1), sas_hw_at_no_check(font_addr));
|
|
recalc_text(sas_hw_at_no_check(font_addr));
|
|
if(sas_hw_at_no_check(font_addr+10) != 0xff)
|
|
sas_store_no_check(vd_rows_on_screen, sas_hw_at_no_check(font_addr+10)-1);
|
|
break;
|
|
}
|
|
font_offset++;
|
|
} while(mode_byte != 0xff);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* graphics mode. No font load, so do mode change ourselves */
|
|
low_set_mode(video_mode);
|
|
/* Set up default graphics font */
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,EGA_SEG);
|
|
if(video_mode == 16)
|
|
sas_storew_no_check(EGA_FONT_INT*4,EGA_CGMN_OFF);
|
|
else
|
|
#ifdef VGG
|
|
if (video_mode == 17 || video_mode == 18)
|
|
sas_storew_no_check(EGA_FONT_INT*4,EGA_HIFONT_OFF);
|
|
else
|
|
#endif
|
|
sas_storew_no_check(EGA_FONT_INT*4,EGA_CGDDOT_OFF);
|
|
/* Now see if we have a nasty font to load */
|
|
font_addr = follow_ptr(save_addr+GRAPH_FONT_OFFSET);
|
|
if(font_addr != 0)
|
|
{
|
|
/* See if it applies to us */
|
|
font_offset = 7;
|
|
do
|
|
{
|
|
mode_byte = sas_hw_at_no_check(font_addr + font_offset);
|
|
if(mode_byte == video_mode)
|
|
{
|
|
sas_store_no_check(vd_rows_on_screen, sas_hw_at_no_check(font_addr)-1);
|
|
sas_store_no_check(ega_char_height, sas_hw_at_no_check(font_addr+1));
|
|
sas_move_bytes_forward(font_addr+3, 4*EGA_FONT_INT, 4);
|
|
break;
|
|
}
|
|
font_offset++;
|
|
} while(mode_byte != 0xff);
|
|
}
|
|
}
|
|
|
|
sas_store_no_check(vd_current_page, 0);
|
|
sas_storew_no_check((sys_addr)VID_ADDR, 0);
|
|
sas_storew_no_check((sys_addr)VID_INDEX, EGA_CRTC_INDEX);
|
|
/*
|
|
* CGA bios fills this entry in 'vd_mode_table' with 'this is a bad mode'
|
|
* value, so make one up for VGA - used in VGA bios disp_func
|
|
*/
|
|
if(video_mode < 8)
|
|
sas_store_no_check(vd_crt_mode, vd_mode_table[video_mode].mode_control_val);
|
|
else if(video_mode < 0x10)
|
|
sas_store_no_check(vd_crt_mode, 0x29);
|
|
else
|
|
sas_store_no_check(vd_crt_mode, 0x1e);
|
|
if(video_mode == 6)
|
|
sas_store_no_check(vd_crt_palette, 0x3f);
|
|
else
|
|
sas_store_no_check(vd_crt_palette, 0x30);
|
|
|
|
for(pag=0; pag<8; pag++)
|
|
sas_storew_no_check(VID_CURPOS + 2*pag, 0);
|
|
|
|
#ifdef V7VGA
|
|
set_host_pix_height(1);
|
|
set_banking( 0, 0 );
|
|
#endif
|
|
|
|
#ifdef NTVDM
|
|
/* Don't want to clear screen on startup if integrated with the console. */
|
|
if (soft_reset)
|
|
#endif /* NTVDM */
|
|
{
|
|
/* Clear screen */
|
|
if(!get_EGA_no_clear())
|
|
{
|
|
#ifdef REAL_VGA
|
|
sas_fillsw_16(video_pc_low_regen, vd_mode_table[video_mode].clear_char,
|
|
(video_pc_high_regen - video_pc_low_regen)/ 2 + 1);
|
|
#else /* REAL_VGA */
|
|
sas_fillsw(video_pc_low_regen, vd_mode_table[video_mode].clear_char,
|
|
(video_pc_high_regen - video_pc_low_regen)/ 2 + 1);
|
|
#ifdef NTVDM
|
|
/*
|
|
* Need to call host clear screen on NT because text windows don't
|
|
* resize and we need to clear portion not being written to.
|
|
*/
|
|
host_clear_screen();
|
|
host_mark_screen_refresh();
|
|
#endif /* NTVDM */
|
|
#endif /* REAL_VGA */
|
|
}
|
|
}
|
|
inb(EGA_IPSTAT1_REG,&temp_word);
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
|
|
#if defined(NTVDM) && !defined(X86GFX)
|
|
/* tell mouse that video mode is changed so it can update its own
|
|
* EGA registers(for EGA.SYS interface). Only do this on RISC machine.
|
|
* On X86 machines, ntio.sys int10 handler redirects set mode call
|
|
* to mouse first which then goes to ega_video_io.
|
|
*/
|
|
mouse_video_mode_changed(video_mode);
|
|
#endif
|
|
#ifndef PROD
|
|
trace("end of video set mode", DUMP_NONE);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Set the cursor start and end positions. A bit strange, in that it assumes
|
|
* the caller thinks the cursor is in an 8*8 character cell ... but this
|
|
* should be a copy of the IBM EGA BIOS routine ... what more can we do?
|
|
*/
|
|
#define CGA_CURSOR_OFF_MASK 0x60
|
|
#define CGA_CURSOR_OFF_VALUE 0x20
|
|
#define EGA_CURSOR_OFF_START 0x1e
|
|
#define EGA_CURSOR_OFF_END 0x00
|
|
|
|
GLOBAL void ega_set_cursor_mode IFN0()
|
|
{
|
|
/*
|
|
* Set cursor mode
|
|
* Parameters:
|
|
* CX - cursor value (CH - start scanline, CL - stop scanline)
|
|
*/
|
|
int start,end,char_height;
|
|
|
|
/* get cursor start and end scan lines */
|
|
start = getCH();
|
|
end = getCL();
|
|
|
|
/* The following check is done to see if the application is trying
|
|
to turn the cursor off using a technique that worked on the CGA.
|
|
If the application wants to turn the cursor off, it is faked
|
|
up using suitable EGA start and end values */
|
|
if ((start & CGA_CURSOR_OFF_MASK) == CGA_CURSOR_OFF_VALUE)
|
|
{
|
|
sure_sub_note_trace0(CURSOR_VERBOSE,"ega curs - application req curs off??");
|
|
start = EGA_CURSOR_OFF_START;
|
|
end = EGA_CURSOR_OFF_END;
|
|
}
|
|
/* If the application has enabled cursor emulation, try to fake
|
|
up the same cursor appearance on the EGA 14 scan line character
|
|
matrix as you would get on the CGA 8 scan line matrix. */
|
|
else if(!get_EGA_cursor_no_emulate())
|
|
{
|
|
sure_sub_note_trace2(CURSOR_VERBOSE,"emulate CGA cursor using EGA cursor, CGA vals; start=%d, end = %d",start,end);
|
|
|
|
char_height = sas_hw_at_no_check(ega_char_height);
|
|
|
|
#ifdef VGG
|
|
if (video_adapter == VGA) {
|
|
UTINY saved_start;
|
|
|
|
if ( start > 0x10 )
|
|
start = 0x10;
|
|
if ( end > 0x10 )
|
|
end = 0x10;
|
|
|
|
/*
|
|
* No more guessing, take the exact values from a real VGA:
|
|
*/
|
|
|
|
saved_start = start;
|
|
|
|
if ( char_height >= 16 ) {
|
|
start = vga_cursor16_start[end][start];
|
|
#ifdef USE_CURSOR_END_TABLES
|
|
end = vga_cursor16_end[end][saved_start]];
|
|
#else
|
|
if ( end && (end > 3 || saved_start > end) )
|
|
if ( end != 0xF && end >= saved_start
|
|
&& end <= saved_start + 2 )
|
|
end = 0xE;
|
|
else
|
|
end = 0xF;
|
|
#endif
|
|
} else {
|
|
start = vga_cursor8_start[end][start];
|
|
#ifdef USE_CURSOR_END_TABLES
|
|
end = vga_cursor8_end[end][saved_start]];
|
|
#else
|
|
if ( end && (end > 3 || saved_start > end)
|
|
&& !(saved_start==6 && end==6) )
|
|
end = 7;
|
|
#endif
|
|
}
|
|
} else {
|
|
#endif /* VGG */
|
|
/* EGA does not allow for character height & does this. */
|
|
if(start > 4)start += 5;
|
|
if(end > 4)end += 5;
|
|
|
|
/* adjust end scan line because the last line is specified by
|
|
the cursor end register MINUS 1 on the EGA ... */
|
|
end++;
|
|
|
|
/* on the EGA, cursors extending to the bottom of the character
|
|
matrix are achieved by setting the end register to 0 ... */
|
|
|
|
if (start != 0 && end >= char_height)
|
|
end = 0;
|
|
|
|
/* this last bit defies any explanation, but it is what the
|
|
IBM BIOS does ... */
|
|
if ((end - start) == 0x10)
|
|
end++;
|
|
#ifdef VGG
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* actually set the EGA registers */
|
|
sure_sub_note_trace2(CURSOR_VERBOSE,"ega_cur mode start %d end %d", start,end);
|
|
do_outb(EGA_CRTC_INDEX, R10_CURS_START, start);
|
|
do_outb(EGA_CRTC_INDEX, R11_CURS_END, end);
|
|
|
|
/*
|
|
* Update BIOS data variables
|
|
*/
|
|
|
|
sas_storew_no_check((sys_addr)VID_CURMOD, getCX());
|
|
setAH(0);
|
|
}
|
|
|
|
/* This routine is an approximate conversion of the corresponding IBM BIOS routine.
|
|
* I don't think the IBM version works either.
|
|
*/
|
|
static void ega_emul_set_palette IFN0()
|
|
{
|
|
sys_addr save_table;
|
|
half_word work_BL;
|
|
byte temp;
|
|
|
|
save_table = follow_ptr( follow_ptr(EGA_SAVEPTR)+PALETTE_OFFSET);
|
|
/* setup attribute chip - NB need to do an inb() to clear the address */
|
|
inb(EGA_IPSTAT1_REG,&temp);
|
|
work_BL = getBL();
|
|
if(getBH() == 0)
|
|
{
|
|
sas_store_no_check(vd_crt_palette, (sas_hw_at_no_check(vd_crt_palette) & 0xe0) | (work_BL & 0x1f));
|
|
work_BL = (work_BL & 7) | ((work_BL<<1) & 0x10);
|
|
if(!alpha_num_mode())
|
|
{
|
|
/* set Palette 0 (the background) */
|
|
outb(EGA_AC_INDEX_DATA,0);
|
|
outb(EGA_AC_INDEX_DATA,work_BL);
|
|
if(save_table)
|
|
sas_store_no_check(save_table, work_BL);
|
|
}
|
|
/* set the overscan register (the border) */
|
|
outb(EGA_AC_INDEX_DATA,17);
|
|
outb(EGA_AC_INDEX_DATA,work_BL);
|
|
if(save_table)
|
|
sas_store_no_check(save_table+16, work_BL);
|
|
|
|
/* Now set BL as if we came in with BH = 1 */
|
|
work_BL = (sas_hw_at_no_check(vd_crt_palette) & 0x20)>>5;
|
|
}
|
|
|
|
/* Now do BH = 1 stuff. */
|
|
if(!alpha_num_mode())
|
|
{
|
|
sas_store_no_check(vd_crt_palette, (sas_hw_at_no_check(vd_crt_palette) & 0xdf) | ((work_BL<<5) & 0x20));
|
|
work_BL = work_BL | (sas_hw_at_no_check(vd_crt_palette) & 0x10) | 2;
|
|
outb(EGA_AC_INDEX_DATA,1);
|
|
outb(EGA_AC_INDEX_DATA,work_BL);
|
|
if(save_table)
|
|
sas_store_no_check(save_table+16, work_BL);
|
|
work_BL += 2;
|
|
outb(EGA_AC_INDEX_DATA,2);
|
|
outb(EGA_AC_INDEX_DATA,work_BL);
|
|
if(save_table)
|
|
sas_store_no_check(save_table+16, work_BL);
|
|
work_BL += 2;
|
|
outb(EGA_AC_INDEX_DATA,3);
|
|
outb(EGA_AC_INDEX_DATA,work_BL);
|
|
if(save_table)
|
|
sas_store_no_check(save_table+16, work_BL);
|
|
}
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
|
|
}
|
|
|
|
static void ega_set_palette IFN0()
|
|
{
|
|
int i;
|
|
byte temp;
|
|
sys_addr save_table, palette_table;
|
|
half_word old_mask;
|
|
|
|
save_table = follow_ptr( follow_ptr(EGA_SAVEPTR)+PALETTE_OFFSET);
|
|
/* setup attribute chip - NB need to do an inb() to clear the address */
|
|
inb(EGA_IPSTAT1_REG,&temp);
|
|
switch (getAL())
|
|
{
|
|
case 0:
|
|
outb(EGA_AC_INDEX_DATA,getBL());
|
|
outb(EGA_AC_INDEX_DATA,getBH());
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
|
|
if(save_table)
|
|
sas_store_no_check(save_table + getBL(), getBH());
|
|
break;
|
|
case 1:
|
|
outb(EGA_AC_INDEX_DATA,17); /* the border colour register */
|
|
outb(EGA_AC_INDEX_DATA,getBH());
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
|
|
if(save_table)
|
|
sas_store_no_check(save_table + 16, getBH());
|
|
break;
|
|
case 2:
|
|
palette_table = video_effective_addr(getES(),
|
|
getDX());
|
|
for(i=0;i<16;i++)
|
|
{
|
|
outb(EGA_AC_INDEX_DATA,i);
|
|
outb(EGA_AC_INDEX_DATA,sas_hw_at_no_check(palette_table+i));
|
|
}
|
|
outb(EGA_AC_INDEX_DATA,17);
|
|
outb(EGA_AC_INDEX_DATA,sas_hw_at_no_check(palette_table+16));
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
|
|
if(save_table)
|
|
for(i=0;i<17;i++)
|
|
sas_store_no_check(save_table + i, sas_hw_at_no_check(palette_table+i));
|
|
break;
|
|
case 3:
|
|
/*<REAL_VGA>*/
|
|
/* Select blinking or intensity - bit3 of AR10 */
|
|
/*inb(EGA_IPSTAT1_REG,&temp);*/
|
|
outb(EGA_AC_INDEX_DATA,16); /* mode control index */
|
|
inb(EGA_AC_SECRET,&temp); /* Old value */
|
|
outb(EGA_AC_INDEX_DATA,
|
|
(temp & 0xf7) | ((getBL() & 1)<<3));
|
|
inb(EGA_IPSTAT1_REG,&temp);
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE);
|
|
/*<REAL_VGA>*/
|
|
old_mask = bg_col_mask;
|
|
if (getBL())
|
|
{
|
|
bg_col_mask = 0x70;
|
|
assert0(FALSE,"Blinking not supported");
|
|
sas_store_no_check(vd_crt_mode, 0x29);
|
|
}
|
|
else
|
|
{
|
|
bg_col_mask = 0xf0; /* Intensity bit set */
|
|
sas_store_no_check(vd_crt_mode, 0x09);
|
|
}
|
|
|
|
if ( bg_col_mask != old_mask )
|
|
screen_refresh_required();
|
|
|
|
break;
|
|
default:
|
|
#ifdef VGG
|
|
if (video_adapter == VGA)
|
|
vga_set_palette(); /* VGA has many more subfuncs */
|
|
else
|
|
{
|
|
assert1(FALSE,"Bad set palette submode %#x",getAL());
|
|
not_imp();
|
|
}
|
|
#else
|
|
assert1(FALSE,"Bad set palette submode %#x",getAL());
|
|
setAL(0);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
GLOBAL void ega_char_gen IFN0()
|
|
{
|
|
switch (getAL())
|
|
{
|
|
case 3:
|
|
do_outb(EGA_SEQ_INDEX,3,getBL());
|
|
break;
|
|
case 0:
|
|
case 0x10:
|
|
load_font(video_effective_addr(getES(),getBP()),getCX(),getDX(),getBL(),getBH());
|
|
if(getAL()==0x10)
|
|
recalc_text(getBH());
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
if( getBH()==0x16 )
|
|
loadNativeBIOSfont( 25 );
|
|
else if( getBH()==0x14 )
|
|
loadNativeBIOSfont( 28 );
|
|
else
|
|
loadNativeBIOSfont( 50 );
|
|
#endif /* NTVDM && X86GFX */
|
|
break;
|
|
case 1:
|
|
case 0x11:
|
|
load_font(EGA_CGMN,256,0,getBL(),14);
|
|
if(getAL()==0x11)
|
|
recalc_text(14);
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
loadNativeBIOSfont( 28 );
|
|
#endif /* NTVDM & X86GFX */
|
|
break;
|
|
case 2:
|
|
case 0x12:
|
|
load_font(EGA_CGDDOT,256,0,getBL(),8);
|
|
if(getAL()==0x12)
|
|
recalc_text(8);
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
loadNativeBIOSfont( 50 );
|
|
#endif /* NTVDM & X86GFX */
|
|
break;
|
|
#ifdef VGG
|
|
case 4:
|
|
case 0x14:
|
|
load_font(EGA_HIFONT,256,0,getBL(),16);
|
|
if(getAL()==0x14)
|
|
recalc_text(16);
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
loadNativeBIOSfont( 25 );
|
|
#endif /* NTVDM & X86GFX */
|
|
break;
|
|
#endif /* VGG */
|
|
case 0x20:
|
|
sas_storew_no_check(BIOS_EXTEND_CHAR*4,getBP());
|
|
sas_storew_no_check(BIOS_EXTEND_CHAR*4+2,getES());
|
|
break;
|
|
case 0x21:
|
|
sas_storew_no_check(EGA_FONT_INT*4,getBP());
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,getES());
|
|
set_graph_font(getCX());
|
|
break;
|
|
case 0x22:
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
sas_storew_no_check(EGA_FONT_INT*4,nativeFontAddresses[F8x14].off);
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,nativeFontAddresses[F8x14].seg);
|
|
#else
|
|
sas_storew_no_check(EGA_FONT_INT*4,EGA_CGMN_OFF);
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,EGA_SEG);
|
|
#endif /* NTVDM & X86GFX */
|
|
set_graph_font(14);
|
|
break;
|
|
case 0x23:
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
sas_storew_no_check(EGA_FONT_INT*4,nativeFontAddresses[F8x8pt1].off);
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,nativeFontAddresses[F8x8pt1].seg);
|
|
#else
|
|
sas_storew_no_check(EGA_FONT_INT*4,EGA_CGDDOT_OFF);
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,EGA_SEG);
|
|
#endif /* NTVDM & X86GFX */
|
|
set_graph_font(8);
|
|
break;
|
|
#ifdef VGG
|
|
case 0x24:
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
sas_storew_no_check(EGA_FONT_INT*4,nativeFontAddresses[F8x16].off);
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,nativeFontAddresses[F8x16].seg);
|
|
#else
|
|
sas_storew_no_check(EGA_FONT_INT*4,EGA_HIFONT_OFF);
|
|
sas_storew_no_check(EGA_FONT_INT*4+2,EGA_SEG);
|
|
#endif /* NTVDM & X86GFX */
|
|
set_graph_font(16);
|
|
break;
|
|
#endif
|
|
case 0x30:
|
|
setCX(sas_hw_at_no_check(ega_char_height));
|
|
setDL(sas_hw_at_no_check(vd_rows_on_screen));
|
|
switch (getBH())
|
|
{
|
|
case 0:
|
|
setBP(sas_w_at_no_check(BIOS_EXTEND_CHAR*4));
|
|
setES(sas_w_at_no_check(BIOS_EXTEND_CHAR*4+2));
|
|
break;
|
|
case 1:
|
|
setBP(sas_w_at_no_check(EGA_FONT_INT*4));
|
|
setES(sas_w_at_no_check(EGA_FONT_INT*4+2));
|
|
break;
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
|
|
/* ntdetect.com gets the font info from real card on NT boot. VDM reads it into
|
|
* array 'nativeFontAddresses'. Return these fonts as Insignia ROM not loaded.
|
|
*/
|
|
case 2:
|
|
setBP(nativeFontAddresses[F8x14].off);
|
|
setES(nativeFontAddresses[F8x14].seg);
|
|
break;
|
|
case 3:
|
|
setBP(nativeFontAddresses[F8x8pt1].off);
|
|
setES(nativeFontAddresses[F8x8pt1].seg);
|
|
break;
|
|
case 4:
|
|
setBP(nativeFontAddresses[F8x8pt2].off);
|
|
setES(nativeFontAddresses[F8x8pt2].seg);
|
|
break;
|
|
case 5:
|
|
setBP(nativeFontAddresses[F9x14].off);
|
|
setES(nativeFontAddresses[F9x14].seg);
|
|
break;
|
|
case 6:
|
|
setBP(nativeFontAddresses[F8x16].off);
|
|
setES(nativeFontAddresses[F8x16].seg);
|
|
break;
|
|
case 7:
|
|
setBP(nativeFontAddresses[F9x16].off);
|
|
setES(nativeFontAddresses[F9x16].seg);
|
|
break;
|
|
|
|
#else /* NTVDM & X86GFX */
|
|
|
|
case 2:
|
|
setBP(EGA_CGMN_OFF);
|
|
setES(EGA_SEG);
|
|
break;
|
|
case 3:
|
|
setBP(EGA_CGDDOT_OFF);
|
|
setES(EGA_SEG);
|
|
break;
|
|
case 4:
|
|
setBP(EGA_INT1F_OFF);
|
|
setES(EGA_SEG);
|
|
break;
|
|
case 5:
|
|
setBP(EGA_CGMN_FDG_OFF);
|
|
setES(EGA_SEG);
|
|
break;
|
|
|
|
#ifdef VGG
|
|
case 6:
|
|
case 7:
|
|
setBP(EGA_HIFONT_OFF);
|
|
setES(EGA_SEG);
|
|
break;
|
|
#endif /* VGG */
|
|
#endif /* NTVDM & X86GFX */
|
|
default:
|
|
assert2(FALSE,"Illegal char_gen subfunction %#x %#x",getAL(),getBH());
|
|
}
|
|
break;
|
|
default:
|
|
assert1(FALSE,"Illegal char_gen %#x",getAL());
|
|
}
|
|
}
|
|
|
|
static void ega_alt_sel IFN0()
|
|
{
|
|
switch (getBL())
|
|
{
|
|
case 0x10:
|
|
setBH( get_EGA_disp() );
|
|
setBL( get_EGA_mem() );
|
|
setCH( get_EGA_feature() );
|
|
setCL( get_EGA_switches() );
|
|
break;
|
|
case 0x20:
|
|
/* Was "enable Print Screen that can do variables lines on screen."
|
|
* This PC/XT bug fix function is redundant on PC/AT's and
|
|
* is removed by BCN3330 -- it has been broken since BCN101.
|
|
*/
|
|
assert1(FALSE,"Illegal alt_sel %#x",getBL());
|
|
setAL(0); /* A function we don't support */
|
|
break;
|
|
default:
|
|
#ifdef VGG
|
|
if (video_adapter == VGA)
|
|
vga_func_12(); /* Try extra VGA stuff */
|
|
else
|
|
#endif
|
|
{
|
|
setAL(0); /* A function we don't support */
|
|
assert1(FALSE,"Illegal alt_sel %#x",getBL());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
7.INTERMODULE INTERFACE IMPLEMENTATION :
|
|
|
|
/*
|
|
[7.1 INTERMODULE DATA DEFINITIONS] */
|
|
/*
|
|
[7.2 INTERMODULE PROCEDURE DEFINITIONS] */
|
|
|
|
void ega_video_init IFN0()
|
|
{
|
|
EQUIPMENT_WORD equip_flag;
|
|
|
|
/*
|
|
* ESTABLISH EQUIPMENT WORD INITIAL VIDEO MODE FIELD.
|
|
*
|
|
* This field will already have been initialised by this stage
|
|
* to 00(binary) from the corresponding field of the CMOS equipment
|
|
* byte; in that context 00(binary) meant 'primary display has its
|
|
* own BIOS'.
|
|
*
|
|
* However, 00(binary) is not meaningful as the initial mode field
|
|
* and must be updated at this point to 10(binary) for 80X25 colour.
|
|
*/
|
|
equip_flag.all = sas_w_at_no_check(EQUIP_FLAG);
|
|
equip_flag.bits.video_mode = VIDEO_MODE_80X25_COLOUR;
|
|
sas_storew_no_check(EQUIP_FLAG, equip_flag.all);
|
|
|
|
#if !defined(NTVDM) || ( defined(NTVDM) && !defined(X86GFX) )
|
|
/* Initialize the INTs */
|
|
sas_storew_no_check(BIOS_EXTEND_CHAR*4, EGA_INT1F_OFF);
|
|
sas_storew_no_check(BIOS_EXTEND_CHAR*4+2, EGA_SEG);
|
|
sas_move_bytes_forward(BIOS_VIDEO_IO*4, 0x42*4, 4); /* save old INT 10 as INT 42 */
|
|
sas_storew_no_check(BIOS_VIDEO_IO*4, EGA_ENTRY_OFF);
|
|
sas_storew_no_check(BIOS_VIDEO_IO*4+2, EGA_SEG);
|
|
|
|
/* Now set up the EGA BIOS variables */
|
|
if (video_adapter == VGA)
|
|
sas_storew_no_check(EGA_SAVEPTR,VGA_PARMS_OFFSET);
|
|
else
|
|
sas_storew_no_check(EGA_SAVEPTR,EGA_PARMS_OFFSET);
|
|
sas_storew_no_check(EGA_SAVEPTR+2,EGA_SEG);
|
|
#endif /* !NTVDM | (NTVDM & !X86GFX) */
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
sas_store_no_check(ega_info,0x60); /* Clear on mode change, 256K, EGA active, emulate cursor */
|
|
#else
|
|
#ifdef V7VGA
|
|
if ( video_adapter == VGA )
|
|
sas_store_no_check(ega_info, 0x70); /* Clear on mode change, 256K, Extensions allowed, EGA active, emulate cursor */
|
|
else
|
|
sas_store_no_check(ega_info, 0x60); /* Clear on mode change, 256K, EGA active, emulate cursor */
|
|
#else /* V7VGA -- Macs don't have V7 */
|
|
sas_store_no_check(ega_info, 0x60); /* Clear on mode change, 256K, EGA active, emulate cursor */
|
|
#endif /* V7VGA */
|
|
|
|
#endif /* NTVDM & X86GFX */
|
|
#if !(defined(NTVDM) && defined(X86GFX))
|
|
/* Some VGA cards eg ET4000, store info here needed for sync.
|
|
* Inherit that info from page 0 copy.
|
|
*/
|
|
sas_store_no_check(ega_info3, 0xf9); /* feature bits = 0xF, EGA installed, use 8*14 font */
|
|
#endif
|
|
|
|
|
|
#ifdef VGG
|
|
set_VGA_flags(S400 | VGA_ACTIVE);
|
|
#endif
|
|
|
|
/* Set the default mode */
|
|
ega_set_mode();
|
|
}
|
|
|
|
void ega_video_io IFN0()
|
|
{
|
|
|
|
|
|
#if defined(NTVDM) && !defined(X86GFX)
|
|
if (stream_io_enabled && getAH()!= 0x0E && getAX() != 0x13FF)
|
|
disable_stream_io();
|
|
#endif
|
|
|
|
|
|
/*
|
|
* The type of operation is coded into the AH register. Some PC code
|
|
* calls AH functions that are for other even more advanced cards - so we
|
|
* ignore these.
|
|
*/
|
|
|
|
#ifdef V7VGA
|
|
#define check_video_func(AH) ((AH >= 0 && AH < EGA_FUNC_SIZE) || (AH == 0x6f && video_adapter == VGA))
|
|
#else
|
|
#define check_video_func(AH) (AH >= 0 && AH < EGA_FUNC_SIZE)
|
|
#endif
|
|
|
|
if (getAH() != 0xff)
|
|
assert1(check_video_func(getAH()),"Illegal EGA VIO:%#x",getAH());
|
|
if (check_video_func(getAH()))
|
|
{
|
|
IDLE_video(); /* add video anti-idle indicator */
|
|
#ifdef V7VGA
|
|
if (getAH() == 0x6f)
|
|
v7vga_func_6f();
|
|
else
|
|
#endif /* V7VGA */
|
|
(*ega_video_func[getAH()])();
|
|
setCF(0);
|
|
}
|
|
else
|
|
setCF(1);
|
|
}
|
|
|
|
/***** Routines to handle the EGA graphics modes,called from video.c **********/
|
|
void ega_graphics_write_char IFN6(int, col, int, row, int, ch,
|
|
int, colour, int, page, int, nchs)
|
|
{
|
|
sys_addr char_addr;
|
|
register int i;
|
|
int screen_off;
|
|
byte char_height;
|
|
register int scan_length = sas_w_at_no_check(VID_COLS);
|
|
|
|
char_height = sas_hw_at_no_check(ega_char_height);
|
|
char_addr = follow_ptr(EGA_FONT_INT*4)+char_height*ch;
|
|
screen_off = page*sas_w_at_no_check(VID_LEN)+row*scan_length*char_height+col;
|
|
#ifdef V7VGA
|
|
if ( video_adapter == VGA )
|
|
if (sas_hw_at_no_check(vd_video_mode) == 0x18)
|
|
colour = v7_mode_64_munge[colour&3];
|
|
#endif /* V7VGA */
|
|
if(colour & 0x80)
|
|
write_ch_xor(char_addr,screen_off,colour,nchs,scan_length);
|
|
else
|
|
write_ch_set(char_addr,screen_off,colour,nchs,scan_length);
|
|
|
|
#ifndef REAL_VGA
|
|
nchs--;
|
|
|
|
if( nchs )
|
|
{
|
|
for(i=char_height;i>0;i--)
|
|
{
|
|
(*update_alg.mark_fill)( screen_off, screen_off + nchs );
|
|
screen_off += scan_length;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i=char_height;i>0;i--)
|
|
{
|
|
(*update_alg.mark_byte)(screen_off);
|
|
screen_off += scan_length;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ega_write_dot IFN4(int, colour, int, page, int, pixcol, int, row)
|
|
{
|
|
register int screen_off,pixmask,setmask,colourmask,temp;
|
|
|
|
screen_off = page*sas_w_at_no_check(VID_LEN)+(row*sas_w_at_no_check(VID_COLS)&0xFFFF)+pixcol/8;
|
|
pixmask = 0x80 >> (pixcol&7);
|
|
|
|
#ifndef REAL_VGA
|
|
|
|
temp = pixmask << 8;
|
|
pixmask |= temp;
|
|
temp = pixmask << 16;
|
|
pixmask |= temp;
|
|
|
|
#ifdef V7VGA
|
|
if ( video_adapter == VGA )
|
|
if (sas_hw_at_no_check(vd_video_mode) == 0x18)
|
|
colour = v7_mode_64_munge[colour&3];
|
|
#endif /* V7VGA */
|
|
|
|
colourmask = sr_lookup[colour & 0xf];
|
|
|
|
setmask = pixmask & colourmask;
|
|
|
|
if( colour & 0x80 )
|
|
{
|
|
/* XOR pixel */
|
|
|
|
temp = *( (unsigned int *) EGA_planes + screen_off );
|
|
*( (unsigned int *) EGA_planes + screen_off ) = temp ^ setmask;
|
|
}
|
|
else
|
|
{
|
|
/* set/clear pixel */
|
|
|
|
temp = *( (unsigned int *) EGA_planes + screen_off );
|
|
temp &= ~pixmask;
|
|
*( (unsigned int *) EGA_planes + screen_off ) = ( temp | setmask );
|
|
}
|
|
|
|
/* Get the screen updated */
|
|
|
|
(*update_alg.mark_byte)(screen_off);
|
|
#else
|
|
vga_card_w_dot(screen_off, pixmask, colour);
|
|
#endif
|
|
}
|
|
|
|
void ega_sensible_graph_scroll_up IFN6(int, row,
|
|
int, col, int, rowsdiff, int, colsdiff, int, lines, int, attr)
|
|
{
|
|
register int col_incr = sas_w_at_no_check(VID_COLS);
|
|
register int i,source,dest;
|
|
byte char_height;
|
|
boolean screen_updated;
|
|
|
|
char_height = sas_hw_at_no_check(ega_char_height);
|
|
dest = sas_w_at_no_check(VID_ADDR)+row*col_incr*char_height+col;
|
|
rowsdiff *= char_height;
|
|
lines *= char_height;
|
|
source = dest+lines*col_incr;
|
|
#ifdef REAL_VGA
|
|
vga_card_scroll_up(source, dest, rowsdiff, colsdiff, lines, attr, col_incr);
|
|
#else
|
|
screen_updated = (col+colsdiff) <= col_incr; /* Check for silly scroll */
|
|
|
|
if(screen_updated)
|
|
screen_updated = (*update_alg.scroll_up)(dest,colsdiff,rowsdiff,attr,lines,0);
|
|
|
|
for(i=0;i<rowsdiff-lines;i++)
|
|
{
|
|
memcpy(&EGA_planes[dest<<2],&EGA_planes[source<<2],colsdiff<<2);
|
|
|
|
if(!screen_updated)
|
|
(*update_alg.mark_string)(dest, dest+colsdiff-1);
|
|
source += col_incr;
|
|
dest += col_incr;
|
|
}
|
|
|
|
attr = sr_lookup[attr & 0xf];
|
|
|
|
while(lines--)
|
|
{
|
|
memset4( attr, (ULONG *)&EGA_planes[dest<<2], colsdiff );
|
|
|
|
if(!screen_updated)
|
|
(*update_alg.mark_fill)(dest, dest+colsdiff-1);
|
|
|
|
dest += col_incr;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ega_sensible_graph_scroll_down IFN6(int, row,
|
|
int, col, int, rowsdiff, int, colsdiff, int, lines, int, attr)
|
|
{
|
|
register int col_incr = sas_w_at_no_check(VID_COLS);
|
|
register int i,source,dest;
|
|
byte char_height;
|
|
boolean screen_updated;
|
|
|
|
char_height = sas_hw_at_no_check(ega_char_height);
|
|
dest = sas_w_at_no_check(VID_ADDR)+row*col_incr*char_height+col;
|
|
rowsdiff *= char_height;
|
|
lines *= char_height;
|
|
#ifdef REAL_VGA
|
|
dest += rowsdiff*col_incr-1; /* Last byte in destination */
|
|
source = dest-lines*col_incr;
|
|
vga_card_scroll_down(source, dest, rowsdiff, colsdiff, lines, attr, col_incr);
|
|
#else
|
|
screen_updated = (col+colsdiff) <= col_incr; /* Check for silly scroll */
|
|
if(screen_updated)
|
|
screen_updated = (*update_alg.scroll_down)(dest,colsdiff,rowsdiff,attr,lines,0);
|
|
dest += (rowsdiff-1)*col_incr; /* First byte in last row of dest */
|
|
source = dest-lines*col_incr;
|
|
|
|
for(i=0;i<rowsdiff-lines;i++)
|
|
{
|
|
memcpy(&EGA_planes[dest<<2],&EGA_planes[source<<2],colsdiff<<2);
|
|
|
|
if(!screen_updated)
|
|
(*update_alg.mark_string)(dest, dest+colsdiff-1);
|
|
source -= col_incr;
|
|
dest -= col_incr;
|
|
}
|
|
|
|
attr = sr_lookup[attr & 0xf];
|
|
|
|
while(lines--)
|
|
{
|
|
memset4( attr, (ULONG *)&EGA_planes[dest<<2], colsdiff );
|
|
|
|
if(!screen_updated)
|
|
(*update_alg.mark_fill)(dest, dest+colsdiff-1);
|
|
|
|
dest -= col_incr;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* This is called from vga_video.c as well. */
|
|
void search_font IFN2(char *, the_char,int, height)
|
|
{
|
|
register int i;
|
|
register host_addr scratch_addr;
|
|
register sys_addr font_addr;
|
|
|
|
font_addr = follow_ptr(4*EGA_FONT_INT);
|
|
scratch_addr = sas_scratch_address(height);
|
|
for(i=0;i<256;i++)
|
|
{
|
|
sas_loads(font_addr, scratch_addr, height);
|
|
if(memcmp(scratch_addr,the_char,height) == 0)
|
|
break;
|
|
font_addr += height;
|
|
}
|
|
if(i<256)
|
|
setAL(i);
|
|
else
|
|
setAL(0); /* Didn't find a character */
|
|
}
|
|
|
|
void ega_read_attrib_char IFN3(int, col, int, row, int, page)
|
|
{
|
|
byte the_char[256], char_height;
|
|
int screen_off;
|
|
int i, data;
|
|
|
|
char_height = sas_hw_at_no_check(ega_char_height);
|
|
screen_off = page*sas_w_at_no_check(VID_LEN)+row*sas_w_at_no_check(VID_COLS)*char_height+col;
|
|
/*
|
|
* Load up the screen character into the_char.
|
|
* We are looking for non-zero pixels, so OR all the planes together
|
|
*/
|
|
#ifndef REAL_VGA
|
|
for(i=0;i<char_height;i++)
|
|
{
|
|
data = *( (unsigned int *) EGA_planes + screen_off );
|
|
data = ( data >> 16 ) | data;
|
|
the_char[i] = ( data >> 8 ) | data;
|
|
screen_off += sas_w_at_no_check(VID_COLS);
|
|
}
|
|
#else
|
|
vga_card_read_ch(screen_off, sas_w_at_no_check(VID_COLS), char_height, the_char);
|
|
#endif
|
|
/* Now search the font */
|
|
search_font((char *)the_char,(int)char_height);
|
|
}
|
|
void ega_read_dot IFN3(int, page, int, col, int, row)
|
|
{
|
|
int screen_off;
|
|
int shift;
|
|
unsigned int data;
|
|
byte val;
|
|
byte mask;
|
|
#ifdef REAL_VGA
|
|
extern half_word vga_card_read_dot();
|
|
#endif
|
|
|
|
|
|
/*
|
|
* The following fixes a bug in print screen from DOS shell.
|
|
* There is a bug in DOS shell that results in -1 and -2 being
|
|
* passed through for the row. Ignoring these values stops
|
|
* SoftPC falling over.
|
|
*/
|
|
|
|
if (row & 0x8000)
|
|
return;
|
|
|
|
screen_off = page*sas_w_at_no_check(VID_LEN)+row*sas_w_at_no_check(VID_COLS)+(col/8);
|
|
/*
|
|
* The value to return is calculated as:
|
|
* val = plane0 | plane1*2**1 | plane2*2**2 | plane3*2**3
|
|
* The masked-out bit from each plane must therefore be
|
|
* shifted right to bit 0 (note it may already be there)
|
|
* and then shifted up again by the appropriate amount for
|
|
* each plane.
|
|
*/
|
|
|
|
mask = 0x80 >> (col & 7);
|
|
shift = 7 - (col & 7);
|
|
|
|
#ifndef REAL_VGA
|
|
|
|
data = *((unsigned int *) EGA_planes + screen_off );
|
|
|
|
val = ((data >> 24) & mask) >> shift;
|
|
val |= (((data >> 16) & mask) >> shift) << 1;
|
|
val |= (((data >> 8) & mask) >> shift) << 2;
|
|
val |= ((data & mask) >> shift) << 3;
|
|
|
|
#else
|
|
val = vga_card_read_dot(screen_off, shift);
|
|
#endif
|
|
setAL(val);
|
|
}
|
|
|
|
/*
|
|
* Routine to grovel around with the fancy EGA mode tables to find the register parameters.
|
|
* This is also called by the mouse driver, because it needs to know where the default
|
|
* EGA register table for the current mode is stored.
|
|
*/
|
|
sys_addr find_mode_table IFN2(int, mode, sys_addr *, save_addr)
|
|
{
|
|
sys_addr params_addr;
|
|
/* get address of the SAVEPTR table, and hence the video params table. */
|
|
*save_addr = follow_ptr(EGA_SAVEPTR);
|
|
params_addr = follow_ptr(*save_addr) + mode*EGA_PARMS_SIZE;
|
|
/* If we are modes F or 10, adjust to pick up the 256K EGA parameters */
|
|
|
|
#ifdef NTVDM
|
|
/* only take real mode number */
|
|
mode &= 0x7F;
|
|
#endif
|
|
if(mode == 0xF || mode == 0x10)
|
|
params_addr += 2*EGA_PARMS_SIZE;
|
|
#ifdef VGG
|
|
if (video_adapter == VGA)
|
|
{
|
|
#ifdef V7VGA
|
|
/* If mode is 0x60+, pick up parameters from 0x1d onwards */
|
|
if (mode >= 0x60)
|
|
params_addr -= 67*EGA_PARMS_SIZE;
|
|
else
|
|
if (mode >= 0x40)
|
|
params_addr -= 25*EGA_PARMS_SIZE;
|
|
else
|
|
#endif /* V7VGA */
|
|
/* If we are modes 0x11 - 0x13, pick up parameters from entry 0x1a onwards */
|
|
if(mode == 0x11 || mode == 0x12 || mode == 0x13)
|
|
params_addr += 9*EGA_PARMS_SIZE;
|
|
else if(mode < 4 || mode == 7) /* Alphanumeric mode */
|
|
{
|
|
switch(get_VGA_lines())
|
|
{
|
|
case S350: /* EGA-type 350 scanlines */
|
|
params_addr += 19*EGA_PARMS_SIZE;
|
|
break;
|
|
case S400: /* Real VGA text mode */
|
|
switch(mode)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
params_addr += (0x17-mode)*EGA_PARMS_SIZE;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
params_addr += (0x18-mode)*EGA_PARMS_SIZE;
|
|
break;
|
|
case 7:
|
|
params_addr += (0x19-mode)*EGA_PARMS_SIZE;
|
|
}
|
|
default: /* 200 scanlines - OK as is. */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif /* VGG */
|
|
{ /* EGA */
|
|
/* If modes 0-3, activate enhancement if switches say so */
|
|
if( (get_EGA_switches() & 1) && mode < 4)
|
|
params_addr += 19*EGA_PARMS_SIZE;
|
|
}
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
/*
|
|
* Tim August 92, Microsoft.
|
|
* Make text modes (0-3) use our mode parameters in KEYBOARD.SYS
|
|
* Three entries in table: 40x25, 80x25 & 80x25 mono
|
|
* Make that 4 - add font load mode B. We have to be defensive in
|
|
* case of dubious values from cards or m/c. (Pro II/EISA, Olivetti MP)
|
|
* Table order: 40x25, 80x25, mono, font
|
|
*/
|
|
{
|
|
extern word babyModeTable;
|
|
extern UTINY tempbabymode[];
|
|
|
|
if(babyModeTable == 0) /* ntio not loaded - use temp table */
|
|
{
|
|
if (!soft_reset) /* be absolutely sure about this */
|
|
{
|
|
/* magic location:good until 16 bit code is running */
|
|
sas_stores(0x41000, tempbabymode, 2 * EGA_PARMS_SIZE);
|
|
if (mode == 0xb)
|
|
params_addr = 0x41000 + EGA_PARMS_SIZE;
|
|
else
|
|
params_addr = 0x41000; /* if not mode 3 tough */
|
|
return params_addr;
|
|
}
|
|
#ifndef PROD
|
|
else
|
|
printf("NTVDM:video window parm table not loaded but system initialised\n");
|
|
#endif
|
|
}
|
|
if(babyModeTable > 0)
|
|
{
|
|
if (get_VGA_lines() == S350 && mode < 4)
|
|
{
|
|
if (mode < 2)
|
|
params_addr = babyModeTable + 4*EGA_PARMS_SIZE;
|
|
else
|
|
params_addr = babyModeTable + 5*EGA_PARMS_SIZE;
|
|
}
|
|
else
|
|
{
|
|
if (mode < 4)
|
|
{
|
|
mode = mode/2;
|
|
params_addr = babyModeTable + mode*EGA_PARMS_SIZE;
|
|
}
|
|
else
|
|
{
|
|
if (mode == 0xb)
|
|
params_addr = babyModeTable + 3 * EGA_PARMS_SIZE;
|
|
else if (mode == 7) /* skip first 2 table entries */
|
|
params_addr = babyModeTable + 2 * EGA_PARMS_SIZE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* NTVDM & X86GFX */
|
|
|
|
return params_addr;
|
|
}
|
|
|
|
/*
|
|
* Calculate how many scanlines are currently displayed, and return a code:
|
|
* RS200: 200 scanlines
|
|
* RS350: 350 scanlines
|
|
* RS400: 400 scanlines
|
|
* RS480: 480 scanlines
|
|
*
|
|
* Different numbers of scanlines are returned as the code corresonding
|
|
* to the nearest kosher scanline number.
|
|
*/
|
|
|
|
int get_scanlines IFN0()
|
|
{
|
|
int scanlines,res;
|
|
|
|
scanlines = sas_hw_at_no_check(ega_char_height) * sas_hw_at_no_check(vd_rows_on_screen);
|
|
|
|
if(scanlines <= 275)
|
|
res = RS200;
|
|
else if(scanlines <=375)
|
|
res = RS350;
|
|
else if(scanlines <= 440)
|
|
res = RS400;
|
|
else
|
|
res = RS480;
|
|
|
|
return (res);
|
|
}
|
|
|
|
#endif /* EGG */
|