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.
3315 lines
93 KiB
3315 lines
93 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 : name and number
|
|
|
|
RELATED DOCS : include all relevant references
|
|
|
|
DESIGNER :
|
|
|
|
REVISION HISTORY :
|
|
First version : February 1990, S. Frost
|
|
|
|
SUBMODULE NAME : vga
|
|
|
|
SOURCE FILE NAME : vga_ports.c
|
|
|
|
PURPOSE : emulation of VGA registers (ports).
|
|
Calls lower levels of the VGA emulation (or EGA
|
|
emulation) to do the real work.
|
|
|
|
SccsID[]="@(#)vga_ports.c 1.67 07/18/94 Copyright Insignia Solutions Ltd.";
|
|
|
|
|
|
[1.INTERMODULE INTERFACE SPECIFICATION]
|
|
|
|
[1.0 INCLUDE FILE NEEDED TO ACCESS THIS INTERFACE FROM OTHER SUBMODULES]
|
|
|
|
INCLUDE FILE :
|
|
|
|
[1.1 INTERMODULE EXPORTS]
|
|
|
|
PROCEDURES() :
|
|
VOID vga_init()
|
|
VOID vga_term()
|
|
VOID vga_seq_inb()
|
|
VOID vga_crtc_outb()
|
|
VOID vga_crtc_inb()
|
|
VOID vga_gc_outb()
|
|
VOID vga_gc_inb()
|
|
VOID vga_ac_outb()
|
|
VOID vga_ac_inb()
|
|
VOID vga_misc_outb()
|
|
VOID vga_misc_inb()
|
|
VOID vga_feat_outb()
|
|
VOID vga_feat_inb()
|
|
VOID vga_ipstat0_inb()
|
|
VOID vga_dac_outb()
|
|
VOID vga_dac_inb()
|
|
LONG vga_get_line_compare() (* hunter only *)
|
|
LONG vga_get_max_scan_lines() (* hunter only *)
|
|
DATA :
|
|
|
|
-------------------------------------------------------------------------
|
|
[1.2 DATATYPES FOR [1.1] (if not basic C types)]
|
|
-------------------------------------------------------------------------
|
|
[1.3 INTERMODULE IMPORTS]
|
|
(not o/s objects or standard libs)
|
|
|
|
PROCEDURES() :
|
|
io_define_inb
|
|
io_define_outb
|
|
io_redefine_inb
|
|
io_redefine_outb
|
|
io_connect_port
|
|
io_disconnect_port
|
|
flag_mode_change_required()
|
|
set_index_state()
|
|
in_index_state()
|
|
|
|
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)
|
|
|
|
FILES ACCESSED : NONE
|
|
|
|
DEVICES ACCESSED : NONE
|
|
|
|
SIGNALS CAUGHT : NONE
|
|
|
|
SIGNALS ISSUED : NONE
|
|
|
|
|
|
[1.4.2 EXPORTED OBJECTS]
|
|
=========================================================================
|
|
PROCEDURE : vga_init
|
|
|
|
PURPOSE : initialize VGA.
|
|
|
|
PARAMETERS : none
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION : establish vga ports.
|
|
initialize vga code to sensible state.
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_term
|
|
|
|
PURPOSE : terminate VGA.
|
|
|
|
PARAMETERS : none
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION : remove vga ports.
|
|
free up allocated memory etc.
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_seq_inb((io_addr) port, (half_word) *value)
|
|
|
|
PURPOSE : deal with an attempt to read a byte from one of the
|
|
sequencers's register ports, and gets info from
|
|
appropriate vga sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : pointer to memory byte where value read from port should go.
|
|
|
|
GLOBALS : none
|
|
DESCRIPTION :
|
|
ERROR INDICATIONS : none.
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_crtc_outb((io_addr) port, (half_word) value)
|
|
|
|
PURPOSE : deal with bytes written to the sequencer chip's ports, and pass
|
|
appropriate info to vga sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : the byte written to the port.
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION :
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_crtc_inb((io_addr) port, (half_word) *value)
|
|
|
|
PURPOSE : deal with an attempt to read a byte from one of the crtc's register ports,
|
|
and gets info from appropriate vga sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : pointer to memory byte where value read from port should go.
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION :
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_gc_outb((io_addr) port, (half_word) value)
|
|
|
|
PURPOSE : deal with bytes written to the graphics controller chip's ports,
|
|
and pass appropriate info to ega sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : the byte written to the port.
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION :
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_gc_inb((io_addr) port, (half_word) *value)
|
|
|
|
PURPOSE : deal with an attempt to read a byte from one of the
|
|
graphics controller's register ports, and gets info from
|
|
appropriate vga sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : pointer to memory byte where value read from port should go.
|
|
|
|
GLOBALS : none
|
|
DESCRIPTION :
|
|
ERROR INDICATIONS : none.
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_ac_outb((io_addr) port, (half_word) value)
|
|
|
|
PURPOSE : deal with bytes written to the attribute controller chip's ports, and pass
|
|
appropriate info to vga sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : the byte written to the port.
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION :
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_ac_inb((io_addr) port, (half_word) *value)
|
|
|
|
PURPOSE : deal with an attempt to read a byte from one of the
|
|
attribute controller's register ports, and gets info
|
|
from appropriate vga sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : pointer to memory byte where value read from port should go.
|
|
|
|
GLOBALS : none
|
|
DESCRIPTION :
|
|
ERROR INDICATIONS : none.
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
=========================================================================
|
|
PROCEDURE : vga_misc_outb((io_addr) port, (half_word) value)
|
|
|
|
PURPOSE : deal with bytes written to the miscellaneous register's port, and pass
|
|
appropriate info to ega sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : the byte written to the port.
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION :
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_ipstat0_inb((io_addr) port, (half_word) *value)
|
|
|
|
PURPOSE : deal with an attempt to read a byte from the input status register 0 port,
|
|
and gets info from appropriate ega sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : pointer to memory byte where value read from port should go.
|
|
|
|
GLOBALS : none
|
|
|
|
DESCRIPTION :
|
|
|
|
ERROR INDICATIONS : none.
|
|
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
=========================================================================
|
|
PROCEDURE : vga_dac_inb((io_addr) port, (half_word) *value)
|
|
|
|
PURPOSE : deal with an attempt to read a byte from one of the
|
|
DAC's register ports, and gets info from appropriate
|
|
vga sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : pointer to memory byte where value read from port should go.
|
|
|
|
GLOBALS : none
|
|
DESCRIPTION :
|
|
ERROR INDICATIONS : none.
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
=========================================================================
|
|
PROCEDURE : vga_dac_outb((io_addr) port, (half_word) value)
|
|
|
|
PURPOSE : deal with bytes written to one of the DAC register
|
|
ports, and pass appropriate info to ega sub-modules.
|
|
|
|
PARAMETERS
|
|
port : port address written to.
|
|
value : the byte written to the port.
|
|
|
|
GLOBALS : none
|
|
DESCRIPTION :
|
|
ERROR INDICATIONS : none.
|
|
ERROR RECOVERY : none.
|
|
=========================================================================
|
|
|
|
|
|
/*=======================================================================
|
|
[3.INTERMODULE INTERFACE DECLARATIONS]
|
|
=========================================================================
|
|
|
|
[3.1 INTERMODULE IMPORTS] */
|
|
|
|
/* [3.1.1 #INCLUDES] */
|
|
|
|
#ifndef REAL_VGA /* ega port handling moved to host for REAL_VGA */
|
|
#ifdef VGG
|
|
|
|
#include "xt.h"
|
|
#include CpuH
|
|
#include "debug.h"
|
|
#include "timer.h"
|
|
/* both timer.h & gvi.h define HIGH & LOW - ensure we get gvi definitions */
|
|
#undef HIGH
|
|
#undef LOW
|
|
#include "sas.h"
|
|
#include "gmi.h"
|
|
#include "gvi.h"
|
|
#include "ios.h"
|
|
#include "ica.h"
|
|
#include "gfx_upd.h"
|
|
#include "egacpu.h"
|
|
#include "egagraph.h"
|
|
#include "video.h"
|
|
#include "egaread.h"
|
|
#include "egamode.h"
|
|
#include "vgaports.h"
|
|
#include "error.h"
|
|
#include "config.h"
|
|
|
|
#include "host_gfx.h"
|
|
|
|
/* [3.1.2 DECLARATIONS] */
|
|
|
|
/* [3.2 INTERMODULE EXPORTS] */
|
|
|
|
#include "egaports.h"
|
|
|
|
#ifdef GISP_SVGA
|
|
#include "hwvgaio.h"
|
|
#endif /* GISP_SVGA */
|
|
|
|
/*
|
|
5.MODULE INTERNALS : (not visible externally, global internally)]
|
|
|
|
[5.1 LOCAL DECLARATIONS] */
|
|
|
|
VOID vote_vga_mode IPT0();
|
|
|
|
/* [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 "SOFTPC_VGA.seg"
|
|
#endif
|
|
|
|
|
|
/* [5.1.2 TYPEDEF, STRUCTURE, ENUM DECLARATIONS] */
|
|
#ifdef V7VGA
|
|
GLOBAL struct extensions_controller extensions_controller;
|
|
#endif /* V7VGA */
|
|
GLOBAL struct crt_controller crt_controller;
|
|
GLOBAL struct sequencer sequencer;
|
|
GLOBAL struct attribute_controller attribute_controller;
|
|
GLOBAL struct graphics_controller graphics_controller;
|
|
|
|
/* Registers not contained in an LSI device */
|
|
|
|
GLOBAL MISC_OUTPUT_REG miscellaneous_output_register;
|
|
|
|
GLOBAL FEAT_CONT_REG feature_control_register;
|
|
|
|
GLOBAL INPUT_STAT_REG0 input_status_register_zero;
|
|
|
|
GLOBAL INPUT_STAT_REG1 input_status_register_one;
|
|
|
|
typedef enum { DAC_RED, DAC_GREEN, DAC_BLUE } RGB;
|
|
LOCAL RGB DAC_rgb_state = DAC_RED;
|
|
LOCAL byte DAC_wr_addr;
|
|
LOCAL byte DAC_rd_addr;
|
|
LOCAL byte DAC_state;
|
|
|
|
/* 31.3.92 MG For windows 3.1 we must emulate the DAC correctly, storing
|
|
6 or 8 bit data depending on the value in the video-7 C1 extension
|
|
register. */
|
|
|
|
GLOBAL byte DAC_data_mask=0x3f;
|
|
#ifdef V7VGA
|
|
GLOBAL int DAC_data_bits=6;
|
|
#endif
|
|
|
|
byte crtc_0_7_protect = FALSE;
|
|
#ifdef V7VGA
|
|
byte crtc_0_8_protect = FALSE;
|
|
byte crtc_9_b_protect = FALSE;
|
|
byte crtc_c_protect = FALSE;
|
|
#endif /* V7VGA */
|
|
|
|
IMPORT half_word bg_col_mask; /* Used to work out the background colour */
|
|
|
|
VOID vga_ipstat1_inb IPT2(io_addr,port,half_word *,value);
|
|
|
|
/* Declarations for new sequencer code */
|
|
VOID vga_seq_outb_index IPT2(io_addr,port,half_word,value);
|
|
VOID vga_seq_clock IPT2(io_addr,port,half_word,value);
|
|
VOID vga_seq_char_map IPT2(io_addr,port,half_word,value);
|
|
VOID vga_seq_mem_mode IPT2(io_addr,port,half_word,value);
|
|
#ifdef V7VGA
|
|
IMPORT VOID vga_seq_extn_control IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID vga_extn_outb IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID vga_extn_inb IPT2(io_addr,port,half_word *,value);
|
|
#endif /* V7VGA */
|
|
VOID vga_seq_inb IPT2(io_addr,port,half_word *,value);
|
|
/* Same as EGA */
|
|
VOID vga_seq_map_mask IPT2(io_addr,port,half_word,value);
|
|
|
|
IMPORT VOID (*ega_seq_regs[]) IPT2(io_addr, port, half_word, value);
|
|
IMPORT VOID ega_seq_reset IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_seq_clock IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_seq_map_mask IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_seq_char_map IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_seq_mem_mode IPT2(io_addr,port,half_word,value);
|
|
|
|
/* Declarations for VGA graphics controller code */
|
|
/* VGA differing versions */
|
|
VOID vga_gc_mode IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_inb IPT2(io_addr,port,half_word *,value);
|
|
VOID vga_gc_outb IPT2(io_addr,port,half_word,value);
|
|
/* Same as EGA but needed as static struct has changed - shame */
|
|
VOID vga_gc_outb_index IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_outw IPT2(io_addr,port,word,value);
|
|
VOID vga_gc_set_reset IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_enable_set IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_compare IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_rotate IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_read_map IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_misc IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_dont_care IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_mask IPT2(io_addr,port,half_word,value);
|
|
VOID vga_gc_mask_ff IPT2(io_addr,port,half_word,value);
|
|
|
|
|
|
/* extern decls to put redirection array back */
|
|
IMPORT VOID (*ega_gc_regs[]) IPT2(io_addr,port,half_word,value);
|
|
#ifndef A2CPU
|
|
IMPORT VOID (*ega_gc_regs_cpu[]) IPT2(io_addr,port,half_word,value);
|
|
#endif
|
|
IMPORT VOID ega_gc_set_reset IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_enable_set IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_compare IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_rotate IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_read_map IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_mode IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_misc IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_set_reset IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_dont_care IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID ega_gc_mask_ff IPT2(io_addr,port,half_word,value);
|
|
|
|
IMPORT VOID _vga_gc_outb_index IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID _ega_gc_outb_mask IPT2(io_addr,port,half_word,value);
|
|
IMPORT VOID _ega_gc_outb_mask_ff IPT2(io_addr,port,half_word,value);
|
|
|
|
/* Declarations for VGA DAC code */
|
|
VOID vga_dac_inb IPT2(io_addr,port,half_word *,value);
|
|
VOID vga_dac_outb IPT2(io_addr,port,half_word,value);
|
|
VOID vga_dac_data_outb IPT2(io_addr,port,half_word,value);
|
|
VOID vga_dac_data_inb IPT2(io_addr,port,half_word *,value);
|
|
|
|
VOID vga_ac_inb IPT2(io_addr,port,half_word *,value);
|
|
VOID vga_ac_outb IPT2(io_addr,port,half_word,value);
|
|
VOID vga_crtc_inb IPT2(io_addr,port,half_word *,value);
|
|
VOID vga_crtc_outb IPT2(io_addr,port,half_word,value);
|
|
VOID vga_misc_outb IPT2(io_addr,port,half_word,value);
|
|
VOID vga_misc_inb IPT2(io_addr,port,half_word *,value);
|
|
VOID vga_feat_outb IPT2(io_addr,port,half_word,value);
|
|
VOID vga_feat_inb IPT2(io_addr,port,half_word *,value);
|
|
VOID vga_ipstat0_inb IPT2(io_addr,port,half_word *,value);
|
|
/* [5.2.2 INTERNAL PROCEDURE DEFINITIONS] */
|
|
|
|
/* copy of ega routines needed to access correct copy of structs */
|
|
LOCAL VOID do_chain_majority_decision IFN0()
|
|
{
|
|
SAVED SHORT current_votes=0;
|
|
SHORT new_votes;
|
|
|
|
new_votes = sequencer.memory_mode.as_bfld.not_odd_or_even ? 0 : 1 ; /* 0 - chained */
|
|
new_votes += graphics_controller.mode.as_bfld.odd_or_even ; /* 1 - chained */
|
|
new_votes += graphics_controller.miscellaneous.as_bfld.odd_or_even ; /* 1 - chained */
|
|
|
|
if(( new_votes == 1 ) && ( current_votes > 1 ) && ( EGA_CPU.chain != CHAIN4 ))
|
|
{
|
|
/*
|
|
* Transition from chained to unchained
|
|
*/
|
|
|
|
EGA_CPU.chain = UNCHAINED;
|
|
setVideochain(EGA_CPU.chain);
|
|
ega_read_routines_update();
|
|
ega_write_routines_update(CHAINED);
|
|
set_memory_chained(NO);
|
|
flag_mode_change_required();
|
|
}
|
|
else
|
|
{
|
|
if(( new_votes > 1 ) && ( current_votes == 1 ))
|
|
{
|
|
/*
|
|
* Transition from unchained to chained
|
|
*/
|
|
|
|
EGA_CPU.chain = CHAIN2;
|
|
setVideochain(EGA_CPU.chain);
|
|
ega_read_routines_update();
|
|
ega_write_routines_update(CHAINED);
|
|
set_memory_chained(YES);
|
|
flag_mode_change_required();
|
|
}
|
|
}
|
|
|
|
current_votes = new_votes;
|
|
}
|
|
|
|
#ifdef NTVDM
|
|
/*
|
|
* NTVDM uses do_new_cursor() to sync the emulation.
|
|
*/
|
|
GLOBAL VOID do_new_cursor IFN0()
|
|
#else
|
|
LOCAL VOID do_new_cursor IFN0()
|
|
#endif
|
|
{
|
|
|
|
note_entrance0("do_new_cursor()");
|
|
|
|
if (crt_controller.cursor_start.as_bfld.cursor_start >= get_char_height() ) {
|
|
note_entrance0("No cursor");
|
|
set_cursor_visible(FALSE);
|
|
host_cursor_size_changed(crt_controller.cursor_start.as_bfld.cursor_start | 0x20,
|
|
crt_controller.cursor_end.as_bfld.cursor_end);
|
|
}
|
|
else if (crt_controller.cursor_end.as_bfld.cursor_end == 0) {
|
|
note_entrance0("cursor from start to bum");
|
|
set_cursor_start1(0);
|
|
set_cursor_height1(0);
|
|
set_cursor_start(crt_controller.cursor_start.as_bfld.cursor_start);
|
|
set_cursor_height(get_char_height() - get_cursor_start());
|
|
set_cursor_visible(TRUE);
|
|
host_cursor_size_changed(crt_controller.cursor_start.as_bfld.cursor_start,
|
|
crt_controller.cursor_end.as_bfld.cursor_end);
|
|
}
|
|
else if (crt_controller.cursor_end.as_bfld.cursor_end < crt_controller.cursor_start.as_bfld.cursor_start) {
|
|
note_entrance0("2 cursors");
|
|
set_cursor_start1(0);
|
|
set_cursor_height1(crt_controller.cursor_end.as_bfld.cursor_end);
|
|
set_cursor_start(crt_controller.cursor_start.as_bfld.cursor_start);
|
|
set_cursor_height(get_char_height() - get_cursor_start());
|
|
set_cursor_visible(TRUE);
|
|
host_cursor_size_changed(crt_controller.cursor_start.as_bfld.cursor_start,
|
|
crt_controller.cursor_end.as_bfld.cursor_end);
|
|
}
|
|
else if (crt_controller.cursor_end.as_bfld.cursor_end == crt_controller.cursor_start.as_bfld.cursor_start) {
|
|
note_entrance0("One line cursor");
|
|
set_cursor_start(crt_controller.cursor_start.as_bfld.cursor_start);
|
|
set_cursor_height(1);
|
|
set_cursor_start1(0);
|
|
set_cursor_height1(0);
|
|
set_cursor_visible(TRUE);
|
|
host_cursor_size_changed(crt_controller.cursor_start.as_bfld.cursor_start,
|
|
crt_controller.cursor_end.as_bfld.cursor_end);
|
|
}
|
|
else if (crt_controller.cursor_end.as_bfld.cursor_end - 1 >= get_char_height()) {
|
|
note_entrance0("block cursor");
|
|
set_cursor_start(0);
|
|
set_cursor_height(get_char_height());
|
|
set_cursor_start1(0);
|
|
set_cursor_height1(0);
|
|
set_cursor_visible(TRUE);
|
|
host_cursor_size_changed(crt_controller.cursor_start.as_bfld.cursor_start,
|
|
crt_controller.cursor_end.as_bfld.cursor_end);
|
|
}
|
|
else {
|
|
assert2(((crt_controller.cursor_end.as_bfld.cursor_end - 1) >= crt_controller.cursor_start.as_bfld.cursor_start),
|
|
"cursor values do not match default set Start %d, End %d",
|
|
crt_controller.cursor_end.as_bfld.cursor_end,
|
|
crt_controller.cursor_start.as_bfld.cursor_start);
|
|
note_entrance0("normal cursor");
|
|
set_cursor_start(crt_controller.cursor_start.as_bfld.cursor_start);
|
|
set_cursor_height(crt_controller.cursor_end.as_bfld.cursor_end - crt_controller.cursor_start.as_bfld.cursor_start);
|
|
set_cursor_start1(0);
|
|
set_cursor_height1(0);
|
|
set_cursor_visible(TRUE);
|
|
host_cursor_size_changed(crt_controller.cursor_start.as_bfld.cursor_start,
|
|
crt_controller.cursor_end.as_bfld.cursor_end);
|
|
}
|
|
|
|
if(( get_cur_y() < 0 ) ||
|
|
((( get_cur_y() + 1 ) * get_char_height()) > get_screen_height() ))
|
|
{
|
|
set_cursor_visible( FALSE );
|
|
}
|
|
|
|
base_cursor_shape_changed();
|
|
}
|
|
/*
|
|
7.INTERMODULE INTERFACE IMPLEMENTATION :
|
|
|
|
/*
|
|
[7.1 INTERMODULE DATA DEFINITIONS] */
|
|
|
|
PC_palette *DAC;
|
|
|
|
/*
|
|
[7.2 INTERMODULE PROCEDURE DEFINITIONS] */
|
|
|
|
GLOBAL UTINY *vga_gc_outb_index_addr;
|
|
|
|
GLOBAL VOID vga_init IFN0()
|
|
{
|
|
note_entrance0("vga_init");
|
|
/*
|
|
* Define sequencer's ports
|
|
*/
|
|
|
|
ega_seq_regs[1] = FAST_FUNC_ADDR(vga_seq_clock);
|
|
ega_seq_regs[2] = FAST_FUNC_ADDR(vga_seq_map_mask);
|
|
ega_seq_regs[3] = FAST_FUNC_ADDR(vga_seq_char_map);
|
|
ega_seq_regs[4] = FAST_FUNC_ADDR(vga_seq_mem_mode);
|
|
#ifdef V7VGA
|
|
ega_seq_regs[6] = vga_seq_extn_control;
|
|
#endif /* V7VGA */
|
|
|
|
io_define_outb(EGA_SEQ_ADAP_INDEX,vga_seq_outb_index);
|
|
io_define_outb(EGA_SEQ_ADAP_DATA,ega_seq_reset);
|
|
io_define_inb(EGA_SEQ_ADAP_INDEX,vga_seq_inb);
|
|
io_define_inb(EGA_SEQ_ADAP_DATA,vga_seq_inb);
|
|
io_connect_port(EGA_SEQ_INDEX,EGA_SEQ_ADAP_INDEX,IO_READ_WRITE);
|
|
io_connect_port(EGA_SEQ_DATA,EGA_SEQ_ADAP_DATA,IO_READ_WRITE);
|
|
|
|
/*
|
|
* Define CRTC's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_CRTC_ADAPTOR,vga_crtc_outb);
|
|
io_define_inb(EGA_CRTC_ADAPTOR,vga_crtc_inb);
|
|
io_connect_port(EGA_CRTC_INDEX,EGA_CRTC_ADAPTOR,IO_READ_WRITE);
|
|
io_connect_port(EGA_CRTC_DATA,EGA_CRTC_ADAPTOR,IO_READ_WRITE);
|
|
|
|
/*
|
|
* Define Graphics Controller's ports
|
|
*/
|
|
|
|
ega_gc_regs[0] = FAST_FUNC_ADDR(vga_gc_set_reset);
|
|
ega_gc_regs[1] = FAST_FUNC_ADDR(vga_gc_enable_set);
|
|
ega_gc_regs[2] = FAST_FUNC_ADDR(vga_gc_compare);
|
|
ega_gc_regs[3] = FAST_FUNC_ADDR(vga_gc_rotate);
|
|
ega_gc_regs[4] = FAST_FUNC_ADDR(vga_gc_read_map);
|
|
ega_gc_regs[5] = FAST_FUNC_ADDR(vga_gc_mode);
|
|
ega_gc_regs[6] = FAST_FUNC_ADDR(vga_gc_misc);
|
|
ega_gc_regs[7] = FAST_FUNC_ADDR(vga_gc_dont_care);
|
|
ega_gc_regs[8] = FAST_FUNC_ADDR(vga_gc_mask_ff);
|
|
|
|
vga_gc_outb_index_addr = (UTINY *) &graphics_controller.address;
|
|
|
|
io_define_out_routines(EGA_GC_ADAP_INDEX, vga_gc_outb_index, vga_gc_outw, NULL, NULL);
|
|
|
|
#ifndef CPU_40_STYLE /* TEMPORARY */
|
|
Cpu_define_outb(EGA_GC_ADAP_INDEX,_vga_gc_outb_index);
|
|
#endif
|
|
|
|
io_define_outb(EGA_GC_ADAP_DATA,ega_gc_set_reset);
|
|
Cpu_define_outb(EGA_GC_ADAP_DATA,NULL);
|
|
#ifndef A2CPU
|
|
ega_gc_regs_cpu[8] = NULL;
|
|
#endif
|
|
|
|
io_define_inb(EGA_GC_ADAP_INDEX,vga_gc_inb);
|
|
io_define_inb(EGA_GC_ADAP_DATA,vga_gc_inb);
|
|
|
|
io_connect_port(EGA_GC_INDEX,EGA_GC_ADAP_INDEX,IO_READ_WRITE);
|
|
io_connect_port(EGA_GC_DATA,EGA_GC_ADAP_DATA,IO_READ_WRITE);
|
|
|
|
/*
|
|
* Define Attribute controller's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_AC_ADAPTOR,vga_ac_outb);
|
|
io_define_inb(EGA_AC_ADAPTOR,vga_ac_inb);
|
|
io_connect_port(EGA_AC_INDEX_DATA,EGA_AC_ADAPTOR,IO_READ_WRITE);
|
|
io_connect_port(EGA_AC_SECRET,EGA_AC_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Miscellaneous register's port
|
|
*/
|
|
|
|
io_define_outb(EGA_MISC_ADAPTOR,vga_misc_outb);
|
|
io_define_inb(EGA_MISC_ADAPTOR,vga_misc_inb);
|
|
io_connect_port(EGA_MISC_REG,EGA_MISC_ADAPTOR,IO_WRITE);
|
|
io_connect_port(VGA_MISC_READ_REG,EGA_MISC_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Feature controller's port
|
|
*/
|
|
|
|
io_define_outb(EGA_FEAT_ADAPTOR,vga_feat_outb);
|
|
io_define_inb(EGA_FEAT_ADAPTOR,vga_feat_inb);
|
|
io_connect_port(EGA_FEAT_REG,EGA_FEAT_ADAPTOR,IO_WRITE);
|
|
io_connect_port(VGA_FEAT_READ_REG,EGA_FEAT_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Input Status Register 0 port
|
|
*/
|
|
|
|
io_define_inb(EGA_IPSTAT0_ADAPTOR,vga_ipstat0_inb);
|
|
io_connect_port(EGA_IPSTAT0_REG,EGA_IPSTAT0_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Input Status Register 1 port
|
|
*/
|
|
|
|
io_define_inb(EGA_IPSTAT1_ADAPTOR,vga_ipstat1_inb);
|
|
io_connect_port(EGA_IPSTAT1_REG,EGA_IPSTAT1_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define VGA DAC register port
|
|
*/
|
|
io_define_inb(VGA_DAC_INDEX_PORT,vga_dac_inb);
|
|
io_define_outb(VGA_DAC_INDEX_PORT,vga_dac_outb);
|
|
io_connect_port(VGA_DAC_MASK,VGA_DAC_INDEX_PORT,IO_READ_WRITE);
|
|
io_connect_port(VGA_DAC_RADDR,VGA_DAC_INDEX_PORT,IO_READ_WRITE);
|
|
io_connect_port(VGA_DAC_WADDR,VGA_DAC_INDEX_PORT,IO_READ_WRITE);
|
|
io_define_inb(VGA_DAC_DATA_PORT,vga_dac_data_inb);
|
|
io_define_outb(VGA_DAC_DATA_PORT,vga_dac_data_outb);
|
|
io_connect_port(VGA_DAC_DATA,VGA_DAC_DATA_PORT,IO_READ_WRITE);
|
|
|
|
/*
|
|
* Initialise internals of VGA
|
|
* +++++++++++++++++++++++++++
|
|
*/
|
|
|
|
choose_display_mode = choose_vga_display_mode;
|
|
|
|
miscellaneous_output_register.as.abyte = 0;
|
|
|
|
set_pc_pix_height(1); /* set by bit 7 of the crtc max scanline reg */
|
|
set_host_pix_height(1);
|
|
|
|
/* Initialize address map */
|
|
|
|
graphics_controller.miscellaneous.as.abyte = 0;
|
|
graphics_controller.read_map_select.as_bfld.map_select = 0;
|
|
|
|
/* Looking for bright white */
|
|
|
|
graphics_controller.color_compare.as_bfld.color_compare = 0xf;
|
|
|
|
/* All planes significant */
|
|
|
|
graphics_controller.color_dont_care.as_bfld.color_dont_care = 0xf;
|
|
|
|
/* Initialise palette source */
|
|
|
|
attribute_controller.address.as_bfld.palette_address_source = 1;
|
|
|
|
/* Initialise crtc screen height fields and set screen height to be consistent */
|
|
|
|
crt_controller.vertical_display_enable_end = 0;
|
|
crt_controller.crtc_overflow.as_bfld.vertical_display_enab_end_bit_8 = 0;
|
|
crt_controller.crtc_overflow.as_bfld.vertical_display_enab_end_bit_9 = 0;
|
|
/* JOKER: Avoid video BIOS dividing by zero.. */
|
|
crt_controller.horizontal_display_end = 400;
|
|
set_screen_height(0);
|
|
|
|
init_vga_globals();
|
|
EGA_CPU.fun_or_protection = 1; /* assume complicated until we know it's easy */
|
|
|
|
setVideobit_prot_mask(0xffffffff);
|
|
|
|
#ifdef V7VGA
|
|
/* Initialise V7VGA Extensions Registers */
|
|
extensions_controller.pointer_pattern = 0xff;
|
|
extensions_controller.clock_select.as.abyte = 0;
|
|
extensions_controller.cursor_attrs.as.abyte = 0;
|
|
extensions_controller.emulation_control.as.abyte = 0;
|
|
extensions_controller.masked_write_control.as_bfld.masked_write_enable = 0;
|
|
extensions_controller.ram_bank_select.as.abyte = 0;
|
|
extensions_controller.clock_control.as.abyte &= 0xe4;
|
|
extensions_controller.page_select.as.abyte = 0;
|
|
extensions_controller.compatibility_control.as.abyte &= 0x2;
|
|
extensions_controller.timing_select.as.abyte = 0;
|
|
extensions_controller.fg_bg_control.as.abyte &= 0xf3;
|
|
extensions_controller.interface_control.as.abyte &= 0xe0;
|
|
extensions_controller.foreground_latch_1 = 0;
|
|
|
|
/* 31.3.92 MG Default to six-bit palette */
|
|
|
|
extensions_controller.dac_control.as.abyte=0;
|
|
DAC_data_bits=6;
|
|
#endif /* V7VGA */
|
|
DAC_data_mask=0x3f;
|
|
|
|
ega_write_init();
|
|
ega_read_init();
|
|
ega_mode_init();
|
|
|
|
/*
|
|
* Some parts of input status register always return 1, so set fields accordingly
|
|
*/
|
|
input_status_register_zero.as.abyte = 0x70 ;
|
|
|
|
/*
|
|
* set up some variables to get us going (They may have to be changed in the fullness of time)
|
|
*/
|
|
|
|
gvi_pc_low_regen = CGA_REGEN_START;
|
|
gvi_pc_high_regen = CGA_REGEN_END;
|
|
|
|
set_pix_width(1);
|
|
set_pix_char_width(8);
|
|
set_display_disabled(FALSE);
|
|
|
|
set_char_height(8);
|
|
#ifdef V7VGA
|
|
set_screen_limit(0x20000);
|
|
#else
|
|
set_screen_limit(0x8000);
|
|
#endif /* V7VGA */
|
|
set_screen_start(0);
|
|
set_word_addressing(YES);
|
|
set_actual_offset_per_line(80);
|
|
set_offset_per_line(160); /* chained */
|
|
set_horiz_total(80); /* calc screen params from this and prev 3 */
|
|
#ifdef NTVDM
|
|
set_screen_split(0x3FF); /* 10 bits for VGA line compare register */
|
|
#else
|
|
set_screen_split(511); /* make sure there is no split screen to start with ! */
|
|
#endif
|
|
|
|
set_prim_font_index(0);
|
|
set_sec_font_index(0);
|
|
|
|
set_regen_ptr(0,EGA_planes);
|
|
|
|
/* prevent copyright message mysteriously disappearing */
|
|
timer_video_enabled = TRUE;
|
|
|
|
}
|
|
|
|
GLOBAL VOID vga_term IFN0()
|
|
{
|
|
SHORT index;
|
|
|
|
note_entrance0("vga_term");
|
|
|
|
/*
|
|
* Disconnect sequencer's ports
|
|
*/
|
|
|
|
ega_seq_regs[1] = FAST_FUNC_ADDR(ega_seq_clock);
|
|
ega_seq_regs[2] = FAST_FUNC_ADDR(ega_seq_map_mask);
|
|
ega_seq_regs[3] = FAST_FUNC_ADDR(ega_seq_char_map);
|
|
ega_seq_regs[4] = FAST_FUNC_ADDR(ega_seq_mem_mode);
|
|
io_disconnect_port(EGA_SEQ_INDEX,EGA_SEQ_ADAP_INDEX);
|
|
io_disconnect_port(EGA_SEQ_DATA,EGA_SEQ_ADAP_DATA);
|
|
|
|
/*
|
|
* Disconnect CRTC's ports
|
|
*/
|
|
|
|
io_disconnect_port(EGA_CRTC_INDEX,EGA_CRTC_ADAPTOR);
|
|
io_disconnect_port(EGA_CRTC_DATA,EGA_CRTC_ADAPTOR);
|
|
|
|
/*
|
|
* Disconnect Graphics Controller's ports
|
|
*/
|
|
|
|
ega_gc_regs[0] = FAST_FUNC_ADDR(ega_gc_set_reset);
|
|
ega_gc_regs[1] = FAST_FUNC_ADDR(ega_gc_enable_set);
|
|
ega_gc_regs[2] = FAST_FUNC_ADDR(ega_gc_compare);
|
|
ega_gc_regs[3] = FAST_FUNC_ADDR(ega_gc_rotate);
|
|
ega_gc_regs[4] = FAST_FUNC_ADDR(ega_gc_read_map);
|
|
ega_gc_regs[5] = FAST_FUNC_ADDR(ega_gc_mode);
|
|
ega_gc_regs[6] = FAST_FUNC_ADDR(ega_gc_misc);
|
|
ega_gc_regs[7] = FAST_FUNC_ADDR(ega_gc_dont_care);
|
|
ega_gc_regs[8] = FAST_FUNC_ADDR(ega_gc_mask_ff);
|
|
io_disconnect_port(EGA_GC_INDEX,EGA_GC_ADAP_INDEX);
|
|
io_disconnect_port(EGA_GC_DATA,EGA_GC_ADAP_DATA);
|
|
|
|
/*
|
|
* Disconnect Attribute controller's ports
|
|
*/
|
|
|
|
io_disconnect_port(EGA_AC_INDEX_DATA,EGA_AC_ADAPTOR);
|
|
io_disconnect_port(EGA_AC_SECRET,EGA_AC_ADAPTOR);
|
|
|
|
/*
|
|
* Disconnect Miscellaneous register's port
|
|
*/
|
|
|
|
io_disconnect_port(EGA_MISC_REG,EGA_MISC_ADAPTOR);
|
|
io_disconnect_port(VGA_MISC_READ_REG,EGA_MISC_ADAPTOR);
|
|
|
|
/*
|
|
* Disconnect Feature controller port
|
|
*/
|
|
|
|
io_disconnect_port(EGA_FEAT_REG,EGA_MISC_ADAPTOR);
|
|
io_disconnect_port(VGA_FEAT_READ_REG,EGA_MISC_ADAPTOR);
|
|
|
|
/*
|
|
* Disconnect Input Status Register 0 port
|
|
*/
|
|
|
|
io_disconnect_port(EGA_IPSTAT0_REG,EGA_IPSTAT0_ADAPTOR);
|
|
|
|
/*
|
|
* Disconnect Input Status Register 1 port
|
|
*/
|
|
|
|
io_disconnect_port(EGA_IPSTAT1_REG,EGA_IPSTAT1_ADAPTOR);
|
|
|
|
/*
|
|
* Disconnect DAC ports
|
|
*/
|
|
|
|
io_disconnect_port(VGA_DAC_MASK,VGA_DAC_INDEX_PORT);
|
|
io_disconnect_port(VGA_DAC_RADDR,VGA_DAC_INDEX_PORT);
|
|
io_disconnect_port(VGA_DAC_WADDR,VGA_DAC_INDEX_PORT);
|
|
io_disconnect_port(VGA_DAC_DATA,VGA_DAC_DATA_PORT);
|
|
|
|
/*
|
|
* Free internals of VGA
|
|
*/
|
|
|
|
/* free the font files */
|
|
for (index = 0; index < MAX_NUM_FONTS; index++)
|
|
host_free_font(index);
|
|
|
|
EGA_CPU.chain = UNCHAINED;
|
|
setVideochain(EGA_CPU.chain);
|
|
set_chain4_mode(NO);
|
|
EGA_CPU.doubleword = FALSE;
|
|
set_doubleword_mode(NO);
|
|
set_graph_shift_reg(NO);
|
|
set_256_colour_mode(NO);
|
|
|
|
/* Disable CPU read processing */
|
|
ega_read_term();
|
|
ega_write_term();
|
|
}
|
|
|
|
GLOBAL VOID vga_seq_dummy_outb IFN2(io_addr,port,half_word,value)
|
|
{
|
|
UNUSED(port);
|
|
#ifdef PROD
|
|
UNUSED(value);
|
|
#endif
|
|
|
|
assert2(NO,"Output to bad seq reg %#x with data %#x\n",sequencer.address.as.abyte,value);
|
|
}
|
|
|
|
GLOBAL VOID vga_seq_outb_index IFN2(io_addr,port,half_word,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
note_entrance2("vga_seq_outb_index(%x,%x)", port, value);
|
|
#ifdef V7VGA
|
|
if (sequencer.extensions_control.as_bfld.extension_enable && (value & 0x80))
|
|
{
|
|
sequencer.address.as.abyte = value;
|
|
io_redefine_inb(EGA_SEQ_ADAP_DATA, vga_extn_inb);
|
|
io_redefine_outb(EGA_SEQ_ADAP_DATA, vga_extn_outb);
|
|
return;
|
|
}
|
|
io_redefine_inb(EGA_SEQ_ADAP_DATA, vga_seq_inb);
|
|
#endif /* V7VGA */
|
|
|
|
sequencer.address.as.abyte = ( value & 0x07 );
|
|
|
|
#ifndef V7VGA
|
|
if (value > 4)
|
|
{
|
|
/* a bad port index value, so ignore any data sent to it */
|
|
io_redefine_outb(EGA_SEQ_ADAP_DATA,vga_seq_dummy_outb);
|
|
return;
|
|
}
|
|
#endif /* !V7VGA */
|
|
io_redefine_outb(EGA_SEQ_ADAP_DATA,ega_seq_regs[value & 0x07]);
|
|
}
|
|
|
|
|
|
GLOBAL VOID vga_seq_clock IFN2(io_addr,port,half_word,value)
|
|
{
|
|
FAST TINY dot_clock;
|
|
TINY screen_off;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"seq(1,%x)\n",value);)
|
|
note_entrance2("vga_seq_clock(%x,%x)", port, value);
|
|
/* clock mode register */
|
|
dot_clock = sequencer.clocking_mode.as_bfld.dot_clock;
|
|
screen_off = sequencer.clocking_mode.as_bfld.screen_off;
|
|
sequencer.clocking_mode.as.abyte = value;
|
|
if (sequencer.clocking_mode.as_bfld.dot_clock != dot_clock) {
|
|
/*
|
|
** Switch to/from double width pixels
|
|
*/
|
|
if (sequencer.clocking_mode.as_bfld.dot_clock==1) {
|
|
set_pix_width(2);
|
|
set_double_pix_wid(YES);
|
|
set_pix_char_width(16);
|
|
} else {
|
|
set_pix_width(1);
|
|
set_double_pix_wid(NO);
|
|
set_pix_char_width(8);
|
|
}
|
|
flag_mode_change_required();
|
|
}
|
|
if (sequencer.clocking_mode.as_bfld.screen_off != screen_off) {
|
|
if (sequencer.clocking_mode.as_bfld.screen_off) {
|
|
set_display_disabled(TRUE);
|
|
timer_video_enabled = 0;
|
|
disable_gfx_update_routines();
|
|
}
|
|
else {
|
|
set_display_disabled(FALSE);
|
|
timer_video_enabled = 1;
|
|
enable_gfx_update_routines();
|
|
screen_refresh_required();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* the vga supports 4 fonts maps to the ega's 4 */
|
|
GLOBAL VOID vga_seq_char_map IFN2(io_addr,port,half_word,value)
|
|
{
|
|
FAST TINY map_selects, select_a, select_b;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"seq(3,%#x)\n",value);)
|
|
note_entrance2("vga_seq_char_map(%x,%x)", port, value);
|
|
/* char map select reg */
|
|
map_selects = sequencer.character_map_select.character.map_selects;
|
|
sequencer.character_map_select.as.abyte = value;
|
|
if (sequencer.character_map_select.character.map_selects != map_selects)
|
|
{
|
|
/*
|
|
** character mapping attributes have changed.
|
|
**
|
|
** If fonts selected are different bit 3 of attribute byte in alpha mode
|
|
** selects which of the two fonts to use (giving 512 chars).
|
|
*/
|
|
|
|
|
|
select_a = sequencer.character_map_select.as_bfld.character_map_select_a | (sequencer.character_map_select.as_bfld.ch_map_select_a_hi << 2);
|
|
select_b = sequencer.character_map_select.as_bfld.character_map_select_b | (sequencer.character_map_select.as_bfld.ch_map_select_b_hi << 2);
|
|
EGA_GRAPH.attrib_font_select = (select_a != select_b);
|
|
set_prim_font_index(select_a);
|
|
set_sec_font_index(select_b);
|
|
|
|
host_select_fonts(get_prim_font_index(), get_sec_font_index());
|
|
flag_mode_change_required();
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_seq_mem_mode IFN2(io_addr,port,half_word,value)
|
|
{
|
|
TINY now_chain4;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"seq(4,%#x)\n",value);)
|
|
note_entrance2("vga_seq_mem_mode(%x,%x)", port, value);
|
|
|
|
now_chain4 = sequencer.memory_mode.as_bfld.chain4;
|
|
/* mem mode register */
|
|
sequencer.memory_mode.as.abyte = value ;
|
|
|
|
if( now_chain4 != sequencer.memory_mode.as_bfld.chain4 )
|
|
{
|
|
if( sequencer.memory_mode.as_bfld.chain4 == 0 )
|
|
{
|
|
EGA_CPU.chain = UNCHAINED;
|
|
setVideochain(EGA_CPU.chain);
|
|
set_chain4_mode(NO);
|
|
do_chain_majority_decision();
|
|
if (EGA_CPU.chain != CHAIN2)
|
|
{
|
|
ega_read_routines_update();
|
|
ega_write_routines_update(CHAINED);
|
|
flag_mode_change_required();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
EGA_CPU.chain = CHAIN4;
|
|
setVideochain(EGA_CPU.chain);
|
|
set_chain4_mode(YES);
|
|
set_memory_chained(NO);
|
|
ega_read_routines_update();
|
|
ega_write_routines_update(CHAINED);
|
|
flag_mode_change_required();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
do_chain_majority_decision();
|
|
}
|
|
|
|
assert1(sequencer.memory_mode.as_bfld.extended_memory == 1,
|
|
"Someone is trying to set extended memory to 0 (reg=%x)",value);
|
|
}
|
|
|
|
GLOBAL VOID vga_seq_inb IFN2(io_addr,port,half_word *,value)
|
|
{
|
|
note_entrance1("vga_seq_inb(%x)", port);
|
|
if (port == EGA_SEQ_INDEX) {
|
|
*value = sequencer.address.as.abyte;
|
|
note_entrance1("returning %x",*value);
|
|
return;
|
|
}
|
|
if (port == EGA_SEQ_DATA) {
|
|
switch(sequencer.address.as.abyte) {
|
|
|
|
case 0:
|
|
*value = 3;
|
|
break;
|
|
case 1:
|
|
*value = sequencer.clocking_mode.as.abyte;
|
|
break;
|
|
case 2:
|
|
*value = getVideoplane_enable();
|
|
break;
|
|
case 3:
|
|
*value = sequencer.character_map_select.as.abyte;
|
|
break;
|
|
case 4:
|
|
*value = sequencer.memory_mode.as.abyte;
|
|
break;
|
|
#ifdef V7VGA
|
|
case 6:
|
|
*value = sequencer.extensions_control.as.abyte;
|
|
break;
|
|
#endif /* V7VGA */
|
|
default:
|
|
assert1(NO,"Bad sequencer index %d\n",sequencer.address.as.abyte);
|
|
*value = IO_EMPTY_PORT_BYTE_VALUE;
|
|
}
|
|
note_entrance1("returning %x",*value);
|
|
}
|
|
else {
|
|
assert1(NO,"Bad seq port %d",port);
|
|
*value = IO_EMPTY_PORT_BYTE_VALUE;
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_crtc_outb IFN2(io_addr,port,half_word,value)
|
|
{
|
|
SHORT offset;
|
|
struct
|
|
{ /* aVOID alignment problems with casts */
|
|
unsigned value : 8;
|
|
} new;
|
|
|
|
|
|
note_entrance2("vga_crtc_outb(%x,%x)", port, value);
|
|
switch (port) {
|
|
case 0x3d4:
|
|
note_entrance1("New crtc index %d",value);
|
|
crt_controller.address.as.abyte = value;
|
|
break;
|
|
case 0x3d5:
|
|
note_entrance1( "Index %d", crt_controller.address.as_bfld.index );
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE) if (crt_controller.address.as_bfld.index != 0xe && crt_controller.address.as_bfld.index != 0xf)fprintf(trace_file,"crtc(%#x,%#x)\n",crt_controller.address.as_bfld.index,value);)
|
|
/*
|
|
* We have to save all values in the VGA, even if we
|
|
* dont support the reg, as all values are read/write.
|
|
*/
|
|
switch (crt_controller.address.as_bfld.index) {
|
|
case 0:
|
|
note_entrance0("horiz total");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE && crtc_0_7_protect == FALSE)
|
|
#else
|
|
if (crtc_0_7_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
crt_controller.horizontal_total = value;
|
|
break;
|
|
case 1:
|
|
note_entrance0("horiz display end");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE && crtc_0_7_protect == FALSE)
|
|
#else
|
|
if (crtc_0_7_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
{
|
|
crt_controller.horizontal_display_end = value+1;
|
|
if (get_256_colour_mode())
|
|
{
|
|
set_horiz_total(crt_controller.horizontal_display_end>>1);
|
|
}
|
|
else
|
|
{
|
|
set_horiz_total(crt_controller.horizontal_display_end);
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
note_entrance0("start horiz blank");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE && crtc_0_7_protect == FALSE)
|
|
#else
|
|
if (crtc_0_7_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
crt_controller.start_horizontal_blanking = value;
|
|
break;
|
|
case 3:
|
|
note_entrance0("end horiz blank");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE && crtc_0_7_protect == FALSE)
|
|
#else
|
|
if (crtc_0_7_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
crt_controller.end_horizontal_blanking.as.abyte = value;
|
|
break;
|
|
case 4:
|
|
note_entrance0("start horiz retrace");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE && crtc_0_7_protect == FALSE)
|
|
#else
|
|
if (crtc_0_7_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
crt_controller.start_horizontal_retrace = value;
|
|
break;
|
|
case 5:
|
|
note_entrance0("end horiz retrace");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE && crtc_0_7_protect == FALSE)
|
|
#else
|
|
if (crtc_0_7_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
crt_controller.end_horizontal_retrace.as.abyte = value;
|
|
break;
|
|
case 6:
|
|
note_entrance0("vert tot");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE && crtc_0_7_protect == FALSE)
|
|
#else
|
|
if (crtc_0_7_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
crt_controller.vertical_total = value;
|
|
break;
|
|
case 7:
|
|
note_entrance0("overflow");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE)
|
|
{
|
|
#endif /* V7VGA */
|
|
new.value = value;
|
|
if (crtc_0_7_protect) {
|
|
byte temp_line_cmp;
|
|
temp_line_cmp = ((CRTC_OVERFLOW*)&new)->as_bfld.line_compare_bit_8;
|
|
((CRTC_OVERFLOW*)&new)->as.abyte = crt_controller.crtc_overflow.as.abyte;
|
|
((CRTC_OVERFLOW*)&new)->as_bfld.line_compare_bit_8 = temp_line_cmp;
|
|
}
|
|
if (crt_controller.crtc_overflow.as_bfld.vertical_display_enab_end_bit_8 !=
|
|
((CRTC_OVERFLOW*)&new)->as_bfld.vertical_display_enab_end_bit_8)
|
|
{
|
|
/*
|
|
* Screen height changed
|
|
*/
|
|
|
|
set_screen_height_med_recal(
|
|
((CRTC_OVERFLOW*)&new)->as_bfld.vertical_display_enab_end_bit_8 );
|
|
|
|
flag_mode_change_required();
|
|
}
|
|
if (crt_controller.crtc_overflow.as_bfld.line_compare_bit_8 !=
|
|
((CRTC_OVERFLOW*)&new)->as_bfld.line_compare_bit_8)
|
|
{
|
|
/*
|
|
* split screen height changed
|
|
*/
|
|
|
|
EGA_GRAPH.screen_split.as_bfld.med_bit =
|
|
((CRTC_OVERFLOW*)&new)->as_bfld.line_compare_bit_8;
|
|
|
|
if( !get_split_screen_used() )
|
|
flag_mode_change_required();
|
|
|
|
screen_refresh_required();
|
|
}
|
|
if (crt_controller.crtc_overflow.as_bfld.vertical_display_enab_end_bit_9 !=
|
|
((CRTC_OVERFLOW*)&new)->as_bfld.vertical_display_enab_end_bit_9)
|
|
{
|
|
/*
|
|
* split screen height changed
|
|
*/
|
|
set_screen_height_hi_recal(((CRTC_OVERFLOW*)&new)->as_bfld.vertical_display_enab_end_bit_9);
|
|
flag_mode_change_required();
|
|
}
|
|
#ifdef NTVDM
|
|
crt_controller.crtc_overflow.as.abyte = new.value;
|
|
#else
|
|
crt_controller.crtc_overflow.as.abyte = value;
|
|
#endif
|
|
#ifdef V7VGA
|
|
}
|
|
#endif /* V7VGA */
|
|
break;
|
|
case 8:
|
|
note_entrance0("preset row scan");
|
|
#ifdef V7VGA
|
|
if (crtc_0_8_protect == FALSE)
|
|
#endif /* V7VGA */
|
|
crt_controller.preset_row_scan.as.abyte = value;
|
|
break;
|
|
case 9:
|
|
note_entrance0("max scan line");
|
|
#ifdef V7VGA
|
|
if (crtc_9_b_protect == FALSE)
|
|
{
|
|
#endif /* V7VGA */
|
|
new.value = value;
|
|
if (crt_controller.maximum_scan_line.as_bfld.maximum_scan_line
|
|
!= ((MAX_SCAN_LINE*)&new)->as_bfld.maximum_scan_line)
|
|
{
|
|
set_char_height_recal(
|
|
(((MAX_SCAN_LINE*)&new)->as_bfld.maximum_scan_line)+1);
|
|
do_new_cursor();
|
|
flag_mode_change_required();
|
|
}
|
|
|
|
if( crt_controller.maximum_scan_line.as_bfld.double_scanning
|
|
!= ((MAX_SCAN_LINE*)&new)->as_bfld.double_scanning)
|
|
{
|
|
set_pc_pix_height(1 <<
|
|
((MAX_SCAN_LINE*)&new)->as_bfld.double_scanning);
|
|
|
|
flag_mode_change_required();
|
|
}
|
|
|
|
if (crt_controller.maximum_scan_line.as_bfld.line_compare_bit_9
|
|
!= ((MAX_SCAN_LINE*)&new)->as_bfld.line_compare_bit_9)
|
|
{
|
|
/*
|
|
* split screen height changed
|
|
*/
|
|
|
|
EGA_GRAPH.screen_split.as_bfld.top_bit =
|
|
((MAX_SCAN_LINE*)&new)->as_bfld.line_compare_bit_9;
|
|
|
|
if( !get_split_screen_used() )
|
|
flag_mode_change_required();
|
|
|
|
screen_refresh_required();
|
|
}
|
|
crt_controller.maximum_scan_line.as.abyte = value;
|
|
#ifdef V7VGA
|
|
}
|
|
#endif /* V7VGA */
|
|
break;
|
|
case 0xa:
|
|
note_entrance0("cursor start");
|
|
#ifdef V7VGA
|
|
if (crtc_9_b_protect == FALSE)
|
|
{
|
|
#endif /* V7VGA */
|
|
new.value = value;
|
|
if (crt_controller.cursor_start.as_bfld.cursor_off)
|
|
set_cursor_visible(FALSE);
|
|
else
|
|
set_cursor_visible(TRUE);
|
|
|
|
if (crt_controller.cursor_start.as_bfld.cursor_start !=
|
|
((CURSOR_START*)&new)->as_bfld.cursor_start)
|
|
{
|
|
crt_controller.cursor_start.as.abyte = value;
|
|
}
|
|
|
|
do_new_cursor();
|
|
#ifdef V7VGA
|
|
}
|
|
#endif /* V7VGA */
|
|
break;
|
|
case 0xb:
|
|
note_entrance0("cursor end");
|
|
#ifdef V7VGA
|
|
if (crtc_9_b_protect == FALSE)
|
|
{
|
|
#endif /* V7VGA */
|
|
new.value = value;
|
|
if (crt_controller.cursor_end.as_bfld.cursor_end !=
|
|
((CURSOR_END*)&new)->as_bfld.cursor_end)
|
|
{
|
|
crt_controller.cursor_end.as.abyte = value;
|
|
assert0(crt_controller.cursor_end.as_bfld.cursor_skew_control == 0,
|
|
"Someone is trying to use cursor skew");
|
|
do_new_cursor();
|
|
}
|
|
#ifdef V7VGA
|
|
}
|
|
#endif /* V7VGA */
|
|
break;
|
|
case 0xc:
|
|
note_entrance0("start address high");
|
|
#ifdef V7VGA
|
|
if (crtc_c_protect == FALSE)
|
|
{
|
|
#endif /* V7VGA */
|
|
if (crt_controller.start_address_high != value)
|
|
{
|
|
set_screen_start((value << 8) + crt_controller.start_address_low);
|
|
host_screen_address_changed(value, crt_controller.start_address_low);
|
|
/* check if it wraps now */
|
|
#ifdef V7VGA
|
|
if( !( get_seq_chain4_mode() || get_seq_chain_mode() ))
|
|
#endif /* V7VGA */
|
|
if (get_chain4_mode() )
|
|
{
|
|
if( (get_screen_start()<<2)
|
|
+ get_screen_length() > 4*EGA_PLANE_DISP_SIZE )
|
|
choose_vga_display_mode();
|
|
}
|
|
else
|
|
if ( get_memory_chained() )
|
|
{
|
|
if( (get_screen_start()<<1)
|
|
+ get_screen_length() > 2*EGA_PLANE_DISP_SIZE )
|
|
choose_vga_display_mode();
|
|
}
|
|
else
|
|
{
|
|
if( get_screen_start()
|
|
+ get_screen_length() > EGA_PLANE_DISP_SIZE )
|
|
choose_vga_display_mode();
|
|
}
|
|
screen_refresh_required();
|
|
}
|
|
crt_controller.start_address_high = value;
|
|
#ifdef V7VGA
|
|
}
|
|
#endif /* V7VGA */
|
|
break;
|
|
case 0xd:
|
|
note_entrance0("start address low");
|
|
if (crt_controller.start_address_low != value)
|
|
{
|
|
set_screen_start((crt_controller.start_address_high << 8) + value);
|
|
host_screen_address_changed(crt_controller.start_address_high, value);
|
|
/* check if it wraps now */
|
|
#ifdef V7VGA
|
|
if( !( get_seq_chain4_mode() || get_seq_chain_mode() ))
|
|
#endif /* V7VGA */
|
|
if (get_chain4_mode() )
|
|
{
|
|
if( (get_screen_start()<<2)
|
|
+ get_screen_length() > 4*EGA_PLANE_DISP_SIZE )
|
|
choose_vga_display_mode();
|
|
}
|
|
else
|
|
if ( get_memory_chained() )
|
|
{
|
|
if( (get_screen_start()<<1)
|
|
+ get_screen_length() > 2*EGA_PLANE_DISP_SIZE )
|
|
choose_vga_display_mode();
|
|
}
|
|
else
|
|
{
|
|
if( get_screen_start()
|
|
+ get_screen_length() > EGA_PLANE_DISP_SIZE )
|
|
choose_vga_display_mode();
|
|
}
|
|
screen_refresh_required();
|
|
}
|
|
crt_controller.start_address_low = value;
|
|
break;
|
|
case 0xe:
|
|
note_entrance0("cursor loc high");
|
|
if (crt_controller.cursor_location_high != value)
|
|
{
|
|
crt_controller.cursor_location_high = value;
|
|
|
|
offset = (value<<8) | crt_controller.cursor_location_low;
|
|
offset -= get_screen_start();
|
|
|
|
set_cur_x(offset % crt_controller.horizontal_display_end);
|
|
set_cur_y(offset / crt_controller.horizontal_display_end);
|
|
|
|
do_new_cursor();
|
|
|
|
if(!get_mode_change_required() && is_it_text())
|
|
cursor_changed(get_cur_x(), get_cur_y());
|
|
}
|
|
break;
|
|
case 0xf:
|
|
note_entrance0("cursor loc lo");
|
|
if (crt_controller.cursor_location_low != value)
|
|
{
|
|
crt_controller.cursor_location_low = value;
|
|
|
|
offset = value | (crt_controller.cursor_location_high<<8);
|
|
offset -= get_screen_start();
|
|
|
|
set_cur_x(offset % crt_controller.horizontal_display_end);
|
|
set_cur_y(offset / crt_controller.horizontal_display_end);
|
|
|
|
do_new_cursor();
|
|
|
|
if(!get_mode_change_required() && is_it_text())
|
|
cursor_changed(get_cur_x(), get_cur_y());
|
|
}
|
|
break;
|
|
case 0x10:
|
|
note_entrance0("vert retrace start");
|
|
crt_controller.vertical_retrace_start = value;
|
|
break;
|
|
case 0x11:
|
|
note_entrance0("vert retrace end");
|
|
crt_controller.vertical_retrace_end.as.abyte = value;
|
|
if ((value & 32) == 32)
|
|
ega_int_enable = 0;
|
|
else
|
|
{
|
|
ega_int_enable = 1;
|
|
input_status_register_zero.as_bfld.crt_interrupt = 1; /* = !VS */
|
|
}
|
|
if ((value & 16) != 16)
|
|
{
|
|
ica_clear_int(AT_EGA_VTRACE_ADAPTER,AT_EGA_VTRACE_INT);
|
|
/*
|
|
* clear status latch
|
|
*/
|
|
input_status_register_zero.as_bfld.crt_interrupt = 0; /* = !VS */
|
|
}
|
|
/* ??? */
|
|
if (crt_controller.vertical_retrace_end.as_bfld.crtc_protect)
|
|
crtc_0_7_protect = TRUE;
|
|
else
|
|
crtc_0_7_protect = FALSE;
|
|
break;
|
|
case 0x12:
|
|
note_entrance0("vert disp enable end");
|
|
if (crt_controller.vertical_display_enable_end != value)
|
|
{
|
|
crt_controller.vertical_display_enable_end = value;
|
|
set_screen_height_lo_recal(value);
|
|
flag_mode_change_required();
|
|
}
|
|
break;
|
|
case 0x13:
|
|
note_entrance0("offset");
|
|
if (crt_controller.offset != value)
|
|
{
|
|
crt_controller.offset = value;
|
|
set_actual_offset_per_line(value<<1); /* actual offset into plane in bytes */
|
|
flag_mode_change_required();
|
|
}
|
|
break;
|
|
case 0x14:
|
|
note_entrance0("underline loc");
|
|
crt_controller.underline_location.as.abyte = value;
|
|
set_underline_start(crt_controller.underline_location.as_bfld.underline_location);
|
|
if (crt_controller.underline_location.as_bfld.doubleword_mode) {
|
|
assert0(crt_controller.underline_location.as_bfld.count_by_4 == 1,"count by 4 not set in doubleword mode");
|
|
EGA_CPU.doubleword = TRUE;
|
|
set_doubleword_mode(YES);
|
|
}
|
|
else {
|
|
assert0(crt_controller.underline_location.as_bfld.count_by_4 == 0,"count by 4 set when doubleword clear");
|
|
EGA_CPU.doubleword = FALSE;
|
|
set_doubleword_mode(NO);
|
|
}
|
|
break;
|
|
case 0x15:
|
|
note_entrance0("start vert blank");
|
|
crt_controller.start_vertical_blanking = value;
|
|
break;
|
|
case 0x16:
|
|
note_entrance0("end vert blank");
|
|
crt_controller.end_vertical_blanking = value;
|
|
break;
|
|
case 0x17:
|
|
note_entrance0("mode control");
|
|
new.value = value;
|
|
if (crt_controller.mode_control.as_bfld.compatibility_mode_support !=
|
|
((MODE_CONTROL*)&new)->as_bfld.compatibility_mode_support)
|
|
{
|
|
if ( (((MODE_CONTROL*)&new)->as_bfld.compatibility_mode_support) == 0)
|
|
set_cga_mem_bank(YES);
|
|
else set_cga_mem_bank(NO);
|
|
flag_mode_change_required();
|
|
}
|
|
if (crt_controller.mode_control.as_bfld.word_or_byte_mode !=
|
|
((MODE_CONTROL*)&new)->as_bfld.word_or_byte_mode)
|
|
{
|
|
set_word_addressing_recal(
|
|
(((MODE_CONTROL*)&new)->as_bfld.word_or_byte_mode) == 0 );
|
|
}
|
|
#ifdef V7VGA
|
|
if (crt_controller.mode_control.as_bfld.horizontal_retrace_select !=
|
|
((MODE_CONTROL*)&new)->as_bfld.horizontal_retrace_select)
|
|
{
|
|
EGA_GRAPH.multiply_vert_by_two = ((MODE_CONTROL*)&new)->as_bfld.horizontal_retrace_select;
|
|
flag_mode_change_required();
|
|
screen_refresh_required();
|
|
|
|
}
|
|
#endif
|
|
crt_controller.mode_control.as.abyte = value;
|
|
assert0(crt_controller.mode_control.as_bfld.select_row_scan_counter == 1,"Row scan 0");
|
|
assert0(crt_controller.mode_control.as_bfld.horizontal_retrace_select == 0,
|
|
"retrace select 1");
|
|
assert0(crt_controller.mode_control.as_bfld.hardware_reset == 1,"hardware reset cleared");
|
|
break;
|
|
case 0x18:
|
|
note_entrance0("line compare reg");
|
|
if (crt_controller.line_compare != value)
|
|
{
|
|
crt_controller.line_compare = value;
|
|
EGA_GRAPH.screen_split.as_bfld.low_byte = value;
|
|
|
|
if( !get_split_screen_used() )
|
|
flag_mode_change_required();
|
|
|
|
screen_refresh_required();
|
|
}
|
|
break;
|
|
default:
|
|
assert1(NO,"Bad crtc index %d",crt_controller.address.as_bfld.index);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
assert1(NO,"Bad port passed %x", port );
|
|
break;
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_crtc_inb IFN2(io_addr,port,half_word *,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
note_entrance3("ega_crtc_inb(%x,%x) index %d", port, value, crt_controller.address.as_bfld.index);
|
|
switch(crt_controller.address.as_bfld.index) {
|
|
case 0:
|
|
*value = crt_controller.horizontal_total;
|
|
break;
|
|
case 1:
|
|
*value = crt_controller.horizontal_display_end - 1;
|
|
break;
|
|
case 2:
|
|
*value = crt_controller.start_horizontal_blanking;
|
|
break;
|
|
case 3:
|
|
*value =crt_controller.end_horizontal_blanking.as.abyte;
|
|
break;
|
|
case 4:
|
|
*value = crt_controller.start_horizontal_retrace;
|
|
break;
|
|
case 5:
|
|
*value = crt_controller.end_horizontal_retrace.as.abyte;
|
|
break;
|
|
case 6:
|
|
*value = crt_controller.vertical_total;
|
|
break;
|
|
case 7:
|
|
*value = crt_controller.crtc_overflow.as.abyte;
|
|
break;
|
|
case 8:
|
|
*value = crt_controller.preset_row_scan.as.abyte;
|
|
break;
|
|
case 9:
|
|
*value = crt_controller.maximum_scan_line.as.abyte;
|
|
break;
|
|
case 0xa:
|
|
*value = crt_controller.cursor_start.as.abyte ;
|
|
note_entrance1("cursor start %d",*value);
|
|
break;
|
|
case 0xb:
|
|
*value = crt_controller.cursor_end.as.abyte ;
|
|
note_entrance1("cursor end %d",*value);
|
|
break;
|
|
case 0xc:
|
|
*value = crt_controller.start_address_high ;
|
|
note_entrance1("start address high %x",*value);
|
|
break;
|
|
case 0xd:
|
|
*value = crt_controller.start_address_low ;
|
|
note_entrance1("start address low %x",*value);
|
|
break;
|
|
case 0xe:
|
|
*value = crt_controller.cursor_location_high ;
|
|
note_entrance1("cursor location high %x",*value);
|
|
break;
|
|
case 0xf:
|
|
*value = crt_controller.cursor_location_low ;
|
|
note_entrance1("cursor location low %x",*value);
|
|
break;
|
|
case 0x10:
|
|
*value = crt_controller.vertical_retrace_start;
|
|
break;
|
|
case 0x11:
|
|
*value = crt_controller.vertical_retrace_end.as.abyte & ~0x20;
|
|
break;
|
|
case 0x12:
|
|
*value = crt_controller.vertical_display_enable_end;
|
|
break;
|
|
case 0x13:
|
|
*value = crt_controller.offset;
|
|
break;
|
|
case 0x14:
|
|
*value = crt_controller.underline_location.as.abyte;
|
|
break;
|
|
case 0x15:
|
|
*value = crt_controller.start_vertical_blanking;
|
|
break;
|
|
case 0x16:
|
|
*value = crt_controller.end_vertical_blanking;
|
|
break;
|
|
case 0x17:
|
|
*value = crt_controller.mode_control.as.abyte;
|
|
break;
|
|
case 0x18:
|
|
*value = crt_controller.line_compare;
|
|
break;
|
|
#ifdef V7VGA
|
|
case 0x1f:
|
|
*value = crt_controller.start_address_high ^ 0xea;
|
|
break;
|
|
case 0x22:
|
|
switch(graphics_controller.read_map_select.as_bfld.map_select)
|
|
{
|
|
case 0:
|
|
*value = get_latch0;
|
|
break;
|
|
case 1:
|
|
*value = get_latch1;
|
|
break;
|
|
case 2:
|
|
*value = get_latch2;
|
|
break;
|
|
case 3:
|
|
*value = get_latch3;
|
|
break;
|
|
}
|
|
break;
|
|
case 0x24:
|
|
*value = attribute_controller.address.as.abyte;
|
|
break;
|
|
#endif /* V7VGA */
|
|
default:
|
|
assert1(crt_controller.address.as_bfld.index>24,"inb from bad crtc index %d",crt_controller.address.as_bfld.index);
|
|
*value = IO_EMPTY_PORT_BYTE_VALUE;
|
|
break;
|
|
}
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"RD crtc %#x = %#x\n",crt_controller.address.as_bfld.index,*value);)
|
|
}
|
|
|
|
|
|
GLOBAL VOID vga_gc_mode IFN2(io_addr,port,half_word,value)
|
|
{
|
|
MODE new_mode;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(5,%#x)\n",value);)
|
|
note_entrance2("vga_gc_mode(%x,%x)", port, value);
|
|
new_mode.as.abyte = value;
|
|
if (graphics_controller.mode.as_bfld.write_mode != new_mode.as_bfld.write_mode)
|
|
{
|
|
/*
|
|
* write mode change
|
|
*/
|
|
|
|
EGA_CPU.write_mode = new_mode.as_bfld.write_mode;
|
|
setVideowrmode(EGA_CPU.write_mode);
|
|
ega_write_routines_update(WRITE_MODE);
|
|
}
|
|
|
|
if (graphics_controller.mode.as_bfld.read_mode != new_mode.as_bfld.read_mode)
|
|
{
|
|
/*
|
|
* read mode change
|
|
*/
|
|
read_state.mode = new_mode.as_bfld.read_mode;
|
|
ega_read_routines_update();
|
|
}
|
|
|
|
if (graphics_controller.mode.as_bfld.shift_register_mode != new_mode.as_bfld.shift_register_mode)
|
|
{
|
|
|
|
switch(new_mode.as_bfld.shift_register_mode) {
|
|
|
|
case 0: /* EGA mode */
|
|
set_graph_shift_reg(NO);
|
|
set_256_colour_mode(NO);
|
|
set_horiz_total(crt_controller.horizontal_display_end);
|
|
break;
|
|
case 1: /* CGA med res mode */
|
|
set_graph_shift_reg(YES);
|
|
set_256_colour_mode(NO);
|
|
set_horiz_total(crt_controller.horizontal_display_end);
|
|
break;
|
|
case 2: /* VGA 256 colour mode */
|
|
case 3: /* Bottom bit ignored, if top bit set */
|
|
set_graph_shift_reg(NO);
|
|
set_256_colour_mode(YES);
|
|
/* Need to halve horiz display end for 256 cols */
|
|
set_horiz_total(crt_controller.horizontal_display_end>>1);
|
|
flag_palette_change_required();
|
|
break;
|
|
}
|
|
flag_mode_change_required();
|
|
}
|
|
|
|
graphics_controller.mode.as.abyte = new_mode.as.abyte;
|
|
|
|
/*
|
|
* Check for any change to chained mode rule by having an election
|
|
* (Note: EGA registers must be updated before calling election)
|
|
*/
|
|
|
|
do_chain_majority_decision();
|
|
}
|
|
|
|
/*
|
|
* note: identical to ega routines, but needed in this module to ensure
|
|
* correct struct set
|
|
*/
|
|
|
|
GLOBAL VOID vga_gc_outb_index IFN2(io_addr,port,half_word,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
note_entrance2("vga_gc_outb_index(%x,%x)", port, value);
|
|
value &= 0xf;
|
|
graphics_controller.address.as.abyte = value;
|
|
assert2(value<9,"Bad gc index %#x port %#x",value,port);
|
|
|
|
io_redefine_outb(EGA_GC_ADAP_DATA,ega_gc_regs[value]);
|
|
Cpu_define_outb(EGA_GC_ADAP_DATA,ega_gc_regs_cpu[value]);
|
|
}
|
|
|
|
|
|
/*( vga_gc_outw
|
|
** Most PC programs do an "OUT DX, AX" which sets up the GC index
|
|
** register with the AL and the GC data register with AH.
|
|
** Avoid going through generic_outw() by doing it all here!
|
|
** See also: ega_gc_outw() in "ega_ports.c"
|
|
)*/
|
|
GLOBAL VOID vga_gc_outw IFN2(io_addr, port, word, outval)
|
|
{
|
|
reg temp;
|
|
INT value;
|
|
|
|
temp.X = outval;
|
|
|
|
value = temp.byte.low & 0xf;
|
|
graphics_controller.address.as.abyte = value;
|
|
|
|
assert2(value<9,"Bad gc index %#x port %#x",value,port);
|
|
|
|
io_redefine_outb(EGA_GC_ADAP_DATA,ega_gc_regs[value]);
|
|
|
|
Cpu_define_outb(EGA_GC_ADAP_DATA,ega_gc_regs_cpu[value]);
|
|
|
|
(*(ega_gc_regs[value]))(port+1, temp.byte.high);
|
|
}
|
|
|
|
|
|
GLOBAL VOID vga_gc_set_reset IFN2(io_addr,port,half_word,value)
|
|
{
|
|
FAST TINY set_reset;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(0,%x)\n",value);)
|
|
note_entrance2("vga_gc_set_reset(%x,%x)", port, value);
|
|
set_reset = graphics_controller.set_or_reset.as_bfld.set_or_reset;
|
|
graphics_controller.set_or_reset.as.abyte = value;
|
|
if (graphics_controller.set_or_reset.as_bfld.set_or_reset != set_reset)
|
|
{
|
|
EGA_CPU.set_reset = graphics_controller.set_or_reset.as_bfld.set_or_reset;
|
|
ega_write_routines_update(SET_RESET);
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_gc_enable_set IFN2(io_addr,port,half_word,value)
|
|
{
|
|
FAST TINY en_set_reset;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(1,%x)\n",value);)
|
|
note_entrance2("vga_gc_enable_set(%x,%x)", port, value);
|
|
en_set_reset = graphics_controller.enable_set_or_reset.as_bfld.enable_set_or_reset;
|
|
graphics_controller.enable_set_or_reset.as.abyte = value;
|
|
if (graphics_controller.enable_set_or_reset.as_bfld.enable_set_or_reset != en_set_reset)
|
|
{
|
|
EGA_CPU.sr_enable = graphics_controller.enable_set_or_reset.as_bfld.enable_set_or_reset;
|
|
write_state.sr = graphics_controller.enable_set_or_reset.as_bfld.enable_set_or_reset==0?0:1;
|
|
setVideowrstate(EGA_CPU.ega_state.mode_0.lookup);
|
|
ega_write_routines_update(ENABLE_SET_RESET);
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_gc_compare IFN2(io_addr,port,half_word,value)
|
|
{
|
|
FAST TINY colour_compare;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(2,%x)\n",value);)
|
|
note_entrance2("vga_gc_compare(%x,%x)", port, value);
|
|
colour_compare = graphics_controller.color_compare.as_bfld.color_compare;
|
|
graphics_controller.color_compare.as.abyte = value;
|
|
if (graphics_controller.color_compare.as_bfld.color_compare != colour_compare)
|
|
{
|
|
read_state.colour_compare = graphics_controller.color_compare.as_bfld.color_compare;
|
|
if (read_state.mode == 1) ega_read_routines_update();
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_gc_rotate IFN2(io_addr,port,half_word,value)
|
|
{
|
|
struct {
|
|
unsigned value : 8;
|
|
} new;
|
|
|
|
UNUSED(port);
|
|
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(3,%x)\n",value);)
|
|
new.value = value;
|
|
if (graphics_controller.data_rotate.as_bfld.rotate_count != ((DATA_ROTATE*)&new)->as_bfld.rotate_count )
|
|
{
|
|
setVideorotate(((DATA_ROTATE*)&new)->as_bfld.rotate_count);
|
|
ega_write_routines_update(ROTATION);
|
|
}
|
|
if (graphics_controller.data_rotate.as_bfld.function_select != ((DATA_ROTATE*)&new)->as_bfld.function_select)
|
|
{
|
|
write_state.func = ((DATA_ROTATE*)&new)->as_bfld.function_select;
|
|
setVideowrstate(EGA_CPU.ega_state.mode_0.lookup);
|
|
ega_write_routines_update(FUNCTION);
|
|
}
|
|
EGA_CPU.fun_or_protection = (value != 0) || write_state.bp;
|
|
graphics_controller.data_rotate.as.abyte = value;
|
|
}
|
|
|
|
GLOBAL VOID vga_gc_read_map IFN2(io_addr,port,half_word,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(4,%x)\n",value);)
|
|
|
|
note_entrance2("vga_gc_read_map(%x,%x)", port, value);
|
|
|
|
setVideoread_mapped_plane(value & 3);
|
|
|
|
update_shift_count();
|
|
}
|
|
|
|
GLOBAL VOID vga_gc_misc IFN2(io_addr,port,half_word,value)
|
|
{
|
|
FAST TINY memory_map;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(6,%x)\n",value);)
|
|
note_entrance2("vga_gc_misc(%x,%x)", port, value);
|
|
memory_map = graphics_controller.miscellaneous.as_bfld.memory_map;
|
|
graphics_controller.miscellaneous.as.abyte = value;
|
|
if (graphics_controller.miscellaneous.as_bfld.memory_map != memory_map)
|
|
{
|
|
/*
|
|
* Where EGA appears in PC memory space changed.
|
|
*/
|
|
|
|
#ifndef GISP_SVGA
|
|
if (miscellaneous_output_register.as_bfld.enable_ram)
|
|
sas_disconnect_memory(gvi_pc_low_regen,gvi_pc_high_regen);
|
|
#endif /* GISP_SVGA */
|
|
|
|
switch (graphics_controller.miscellaneous.as_bfld.memory_map)
|
|
{
|
|
case 0:
|
|
gvi_pc_low_regen = 0xA0000;
|
|
gvi_pc_high_regen = 0xBFFFF;
|
|
break;
|
|
case 1:
|
|
gvi_pc_low_regen = 0xA0000;
|
|
gvi_pc_high_regen = 0xAFFFF;
|
|
break;
|
|
case 2:
|
|
gvi_pc_low_regen = 0xB0000;
|
|
gvi_pc_high_regen = 0xB7FFF;
|
|
break;
|
|
case 3:
|
|
gvi_pc_low_regen = 0xB8000;
|
|
gvi_pc_high_regen = 0xBFFFF;
|
|
break;
|
|
}
|
|
|
|
if (miscellaneous_output_register.as_bfld.enable_ram)
|
|
sas_connect_memory(gvi_pc_low_regen,gvi_pc_high_regen,(half_word)SAS_VIDEO);
|
|
|
|
/*
|
|
* Tell cpu associated modules that regen area has moved
|
|
*/
|
|
|
|
ega_read_routines_update();
|
|
ega_write_routines_update(RAM_MOVED);
|
|
}
|
|
|
|
/* Decide alpha/graphics mode by voting. */
|
|
vote_vga_mode();
|
|
|
|
/*
|
|
* Check for any change to chained mode rule by having an election
|
|
* (Note: EGA registers must be updated before calling election)
|
|
*/
|
|
|
|
do_chain_majority_decision();
|
|
}
|
|
|
|
GLOBAL VOID vga_gc_dont_care IFN2(io_addr,port,half_word,value)
|
|
{
|
|
FAST TINY colour_dont_care;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(7,%x)\n",value);)
|
|
note_entrance2("vga_gc_dont_care(%x,%x)", port, value);
|
|
colour_dont_care = graphics_controller.color_dont_care.as_bfld.color_dont_care;
|
|
graphics_controller.color_dont_care.as.abyte = value;
|
|
if (graphics_controller.color_dont_care.as_bfld.color_dont_care != colour_dont_care)
|
|
{
|
|
read_state.colour_dont_care = graphics_controller.color_dont_care.as_bfld.color_dont_care;
|
|
if (read_state.mode == 1) ega_read_routines_update();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* The EGA mask register is written to more times than all other ports added together!
|
|
* To help make this register fast, we have two different routines to handle it:
|
|
* ega_gc_mask for when the register's current value is not 0xFF, ie. masking is active
|
|
* ega_gc_mask_ff for when the mask register = 0xFF, so masking is disabled.
|
|
*/
|
|
|
|
|
|
/*(
|
|
** vga_mask_register_changed
|
|
** This gets called whenever the mask register gets changed, and
|
|
** updates the internals appropriately. Since the mask registers
|
|
** are hit more than any other registers, this should do the job!
|
|
**
|
|
** Rather than calling the monster ega_write_routines_update() (in "ega_write.c"),
|
|
** we do as little as we possibly can here!
|
|
** In particular, all we do is set the video write pointer handlers
|
|
** to the appropriate one and update the internal EGA_CPU state...
|
|
**
|
|
** We DON'T do anything about altering the marking funcs, etc.
|
|
**
|
|
** See also "ega_mask_register_changed" in "ega_ports.c".
|
|
**
|
|
** NB: GLOBAL for JOKER.
|
|
)*/
|
|
#include "cpu_vid.h"
|
|
|
|
GLOBAL VOID vga_mask_register_changed IFN1(BOOL, gotBitProtection)
|
|
{
|
|
ULONG state;
|
|
SAVED IU8 masks[] = {0x1f, 0x01, 0x0f, 0x0f};
|
|
IMPORT WRT_POINTERS *mode_chain_handler_table[];
|
|
#ifdef V7VGA
|
|
IMPORT UTINY Last_v7_fg_bg, fg_bg_control;
|
|
#endif
|
|
|
|
|
|
write_state.bp = gotBitProtection;
|
|
setVideowrstate(EGA_CPU.ega_state.mode_0.lookup);
|
|
EGA_CPU.fun_or_protection = (gotBitProtection || (graphics_controller.data_rotate.as.abyte != 0));
|
|
|
|
/* Check that we're not trying to handle any pathological cases here...
|
|
** This means we chicken out for Chain2 and V7VGA dithering.
|
|
*/
|
|
|
|
if ((EGA_CPU.chain == CHAIN2)
|
|
#ifdef V7VGA
|
|
|| ( Last_v7_fg_bg != fg_bg_control)
|
|
#endif /* V7VGA */
|
|
)
|
|
{
|
|
ega_write_routines_update(BIT_PROT);
|
|
|
|
return;
|
|
}
|
|
|
|
/* the "mode_0" union variant has the largest "lookup" field (5 bits.) */
|
|
|
|
state = EGA_CPU.ega_state.mode_0.lookup & masks[EGA_CPU.write_mode];
|
|
|
|
#ifdef A3CPU
|
|
#ifdef C_VID
|
|
Glue_set_vid_wrt_ptrs(&mode_chain_handler_table[EGA_CPU.saved_mode_chain][state]);
|
|
#else
|
|
Cpu_set_vid_wrt_ptrs(&mode_chain_handler_table[EGA_CPU.saved_mode_chain][state]);
|
|
#endif /* C_VID */
|
|
#else
|
|
#if !(defined(NTVDM) && defined(X86GFX))
|
|
Glue_set_vid_wrt_ptrs(&mode_chain_handler_table[EGA_CPU.saved_mode_chain][state]);
|
|
#endif /* !(NTVDM && X86GFX) */
|
|
#endif /* A3CPU */
|
|
|
|
EGA_CPU.saved_state = state;
|
|
}
|
|
|
|
|
|
/* this is the one that is usually called */
|
|
GLOBAL VOID vga_gc_mask IFN2(USHORT,port,FAST UTINY,value)
|
|
{
|
|
FAST ULONG mask;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(8,%x)\n",value);)
|
|
note_entrance2("vga_gc_mask(%x,%x)", port, value);
|
|
|
|
/*
|
|
* Update video routine according to new bit protection
|
|
*/
|
|
|
|
mask = value | (value << 8);
|
|
mask |= (mask << 16); /* replicate the mask into 4 bytes */
|
|
setVideobit_prot_mask(mask);
|
|
setVideodata_xor_mask(~(EGA_CPU.calc_data_xor & mask));
|
|
setVideolatch_xor_mask(EGA_CPU.calc_latch_xor & mask);
|
|
|
|
if(value == 0xff)
|
|
{
|
|
#ifndef USE_OLD_MASK_CODE
|
|
vga_mask_register_changed(/*bit protection :=*/0);
|
|
#else
|
|
write_state.bp = 0;
|
|
setVideowrstate(EGA_CPU.ega_state.mode_0.lookup);
|
|
EGA_CPU.fun_or_protection = (graphics_controller.data_rotate.as.abyte != 0);
|
|
ega_write_routines_update(BIT_PROT);
|
|
#endif /* USE_OLD_MASK_CODE */
|
|
|
|
/* Alter the function table used by ega_gc_index */
|
|
ega_gc_regs[8] = FAST_FUNC_ADDR(vga_gc_mask_ff);
|
|
|
|
#ifndef CPU_40_STYLE /* TEMPORARY */
|
|
#ifndef A2CPU
|
|
/* Alter the function table used by assembler ega_gc_index */
|
|
ega_gc_regs_cpu[8] = FAST_FUNC_ADDR(_ega_gc_outb_mask_ff);
|
|
#endif
|
|
#endif
|
|
|
|
io_redefine_outb(EGA_GC_ADAP_DATA,vga_gc_mask_ff);
|
|
|
|
#ifndef CPU_40_STYLE /* TEMPORARY */
|
|
Cpu_define_outb(EGA_GC_ADAP_DATA,_ega_gc_outb_mask_ff);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* This version isn't called so often */
|
|
GLOBAL VOID vga_gc_mask_ff IFN2(USHORT,port,FAST UTINY,value)
|
|
{
|
|
FAST ULONG mask;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"gc(8,%x)\n",value);)
|
|
note_entrance2("vga_gc_mask(%x,%x)", port, value);
|
|
|
|
/*
|
|
* Update video routine according to new bit protection
|
|
*/
|
|
|
|
if(value != 0xff)
|
|
{
|
|
mask = value | (value << 8);
|
|
mask |= (mask << 16); /* replicate the mask into 4 bytes */
|
|
setVideobit_prot_mask(mask);
|
|
setVideodata_xor_mask(~(EGA_CPU.calc_data_xor & mask));
|
|
setVideolatch_xor_mask(EGA_CPU.calc_latch_xor & mask);
|
|
|
|
#ifndef USE_OLD_MASK_CODE
|
|
vga_mask_register_changed(/*bit protection :=*/1);
|
|
#else
|
|
write_state.bp = 1;
|
|
setVideowrstate(EGA_CPU.ega_state.mode_0.lookup);
|
|
EGA_CPU.fun_or_protection = TRUE;
|
|
ega_write_routines_update(BIT_PROT);
|
|
#endif /* USE_OLD_MASK_CODE*/
|
|
|
|
/* Alter the function table used by ega_gc_index */
|
|
ega_gc_regs[8] = FAST_FUNC_ADDR(vga_gc_mask);
|
|
|
|
#ifndef CPU_40_STYLE /* TEMPORARY */
|
|
#ifndef A2CPU
|
|
/* Alter the function table used by assembler ega_gc_index */
|
|
ega_gc_regs_cpu[8] = FAST_FUNC_ADDR(_ega_gc_outb_mask);
|
|
#endif
|
|
#endif
|
|
|
|
io_redefine_outb(EGA_GC_ADAP_DATA,vga_gc_mask);
|
|
|
|
#ifndef CPU_40_STYLE /* TEMPORARY */
|
|
Cpu_define_outb(EGA_GC_ADAP_DATA,_ega_gc_outb_mask);
|
|
#endif
|
|
}
|
|
}
|
|
/* end of 'same as EGA' gc routines */
|
|
|
|
/*
|
|
* copy of ega routine to place in correct module to update static struct.
|
|
*/
|
|
GLOBAL VOID vga_seq_map_mask IFN2(io_addr,port,half_word,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"seq(2,%x)\n",value);)
|
|
note_entrance2("vga_seq_map_mask(%x,%x)", port, value);
|
|
|
|
/* map mask register */
|
|
/*
|
|
* Different display plane(s) have been enabled. Update the video
|
|
* routines to deal with this
|
|
*/
|
|
|
|
value &= 0xf; /* 4 planes ==> lower 4 bits valid */
|
|
|
|
setVideoplane_enable(value);
|
|
setVideoplane_enable_mask(sr_lookup[value]);
|
|
write_state.pe = (value == 0xf); /* 1 or 0 */
|
|
setVideowrstate(EGA_CPU.ega_state.mode_0.lookup);
|
|
ega_write_routines_update(PLANES_ENABLED);
|
|
}
|
|
/* end of 'same as EGA' seq routines */
|
|
|
|
/*
|
|
* copy of ega routine to place in correct module to update static struct.
|
|
*/
|
|
|
|
SAVED TINY vga_ip0_state = 0; /* current ega status state */
|
|
SAVED TINY vga_ip0_state_count = 1; /* position in that state */
|
|
|
|
GLOBAL VOID v_ret_intr_status IFN0()
|
|
{
|
|
vga_ip0_state = 3;
|
|
vga_ip0_state_count = 6;
|
|
}
|
|
|
|
|
|
/*
|
|
The following routine should not return a value with top bit set
|
|
until we emulate a Rev4 Video7 card.
|
|
*/
|
|
|
|
/*
|
|
* Some programs synchronise with the display by waiting for the
|
|
* next vertical retrace.
|
|
*
|
|
* We attempt to follow the following waveform:
|
|
* _____ _____
|
|
* VS _____| |_____________________________________________| |___
|
|
* ____________ _ _ _ _ _____________
|
|
* DE __| |___| |___| |_ ....... _| |___| |___| |_
|
|
*
|
|
* State | 3 | 0 | 1 | 2 |
|
|
*
|
|
*/
|
|
|
|
#if defined(NTVDM) || defined(host_get_time_ms) || defined(host_get_count_ms)
|
|
|
|
/*
|
|
* end of periods for each state
|
|
* Units are 100 usec (0.1 ms) to match GetPerfCounter() resolution
|
|
* Total period is based on 70 Hz for NTVDM and 50Hz otherwise
|
|
*/
|
|
#ifdef NTVDM
|
|
#define IPSTAT1_STATE_0 (25)
|
|
#define IPSTAT1_STATE_1 (IPSTAT1_STATE_0 + 75)
|
|
#define IPSTAT1_STATE_2 (IPSTAT1_STATE_1 + 25)
|
|
#define IPSTAT1_STATE_3 (IPSTAT1_STATE_2 + 10)
|
|
#define IPSTAT1_CYCLE_TIME IPSTAT1_STATE_3
|
|
#else /* NTVDM */
|
|
#define IPSTAT1_STATE_0 (4) /* End of state 0, ms */
|
|
#define IPSTAT1_STATE_1 (IPSTAT1_STATE_0 + 9) /* End of state 1, ms */
|
|
#define IPSTAT1_STATE_2 (IPSTAT1_STATE_1 + 4) /* End of state 2, ms */
|
|
#define IPSTAT1_STATE_3 (IPSTAT1_STATE_2 + 3) /* End of state 3, ms */
|
|
#define IPSTAT1_CYCLE_TIME IPSTAT1_STATE_3 /* Cycle time, ms */
|
|
#endif /* NTVDM */
|
|
|
|
GLOBAL VOID vga_ipstat1_inb IFN2(io_addr,port,half_word *,value)
|
|
{
|
|
IMPORT ULONG GetPerfCounter(void);
|
|
SAVED ULONG RefreshStartTime=0;
|
|
ULONG cycles;
|
|
ULONG CurrTime;
|
|
|
|
|
|
#if defined(X86GFX)
|
|
/* Silly programs (especially editors) that are concerned that they might
|
|
* be running on CGA's will read this port like crazy before each screen
|
|
* access. This frig catches the common case:
|
|
* in
|
|
* test al,80
|
|
* j{e,ne} back to the in
|
|
* and moves IP to beyond the test. So far this hasn't broken anything(!!)
|
|
* but has made good speedups in a variety of apps.
|
|
*/
|
|
sys_addr off;
|
|
word cs, ip;
|
|
ULONG dwat;
|
|
IMPORT word getCS(), getIP();
|
|
#endif
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
|
|
#ifdef X86GFX
|
|
cs = getCS();
|
|
ip = getIP();
|
|
off = (cs << 4) + ip;
|
|
dwat = sas_dw_at(off);
|
|
if (dwat == 0xfb7401a8 || dwat == 0xfb7501a8)
|
|
{
|
|
ip += 4;
|
|
setIP(ip);
|
|
*value = 5; /* anything really */
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
note_entrance2("vga_ipstat1_inb(%x,%x)", port, value);
|
|
|
|
#ifdef V7VGA
|
|
attribute_controller.address.as_bfld.index_state = 0;
|
|
#else
|
|
set_index_state(); /* Initialize the Attribute register flip-flop (EGA tech ref, p 56) */
|
|
#endif /* V7VGA */
|
|
|
|
#if defined(NTVDM) || defined(host_get_count_ms)
|
|
|
|
#ifdef NTVDM
|
|
CurrTime = GetPerfCounter();
|
|
#else
|
|
CurrTime = host_get_count_ms();
|
|
#endif
|
|
|
|
cycles = CurrTime >= RefreshStartTime
|
|
? CurrTime - RefreshStartTime
|
|
: 0xFFFFFFFF - RefreshStartTime + CurrTime;
|
|
|
|
/* If app hasn't checked the status for a long time (for at least
|
|
* one Display Refresh Cycle). start the app at end of state 0.
|
|
*/
|
|
if (cycles > IPSTAT1_CYCLE_TIME) {
|
|
RefreshStartTime = CurrTime;
|
|
cycles = 0;
|
|
}
|
|
|
|
#else /* host_get_time_ms */
|
|
|
|
cycles = host_get_time_ms() % IPSTAT1_CYCLE_TIME;
|
|
|
|
#endif /* host_get_time_ms */
|
|
|
|
if (cycles < IPSTAT1_STATE_0)
|
|
{
|
|
*value = 0x05;
|
|
input_status_register_zero.as_bfld.crt_interrupt = 0; /* = !VS */
|
|
}
|
|
else if (cycles < IPSTAT1_STATE_1)
|
|
{
|
|
*value = 0x04;
|
|
if (((cycles - IPSTAT1_STATE_0) % 3) == 0)
|
|
*value |= 0x01;
|
|
input_status_register_zero.as_bfld.crt_interrupt = 0; /* = !VS */
|
|
}
|
|
else if (cycles < IPSTAT1_STATE_2)
|
|
{
|
|
*value = 0x05;
|
|
input_status_register_zero.as_bfld.crt_interrupt = 0; /* = !VS */
|
|
}
|
|
else /* IPSTAT1_STATE_3 */
|
|
{
|
|
*value = 0x0d;
|
|
input_status_register_zero.as_bfld.crt_interrupt = 1; /* = VS */
|
|
}
|
|
}
|
|
|
|
#else /* !(NTVDM || host_get_time_ms || host_get_count_ms) */
|
|
|
|
GLOBAL VOID vga_ipstat1_inb IFN2(io_addr,port,half_word *,value)
|
|
{
|
|
|
|
/*
|
|
* The whole of this routine has been nicked from the cga without modification
|
|
* The s_lengths array should probably be altered for the ega timings, and somewhere
|
|
* an interrupt should be fired off.
|
|
*/
|
|
|
|
SAVED TINY sub_state = 0; /* sub state for ega state 2 */
|
|
|
|
SAVED ULONG gmfudge = 17; /* Random number seed for pseudo-random
|
|
bitstream generator to give the state
|
|
lengths below that 'genuine' feel to
|
|
progs that require it! */
|
|
FAST ULONG h;
|
|
|
|
/*
|
|
* relative 'lengths' of each state. State 2 is *3 as it has 3 sub states
|
|
*/
|
|
|
|
SAVED TINY s_lengths[] = { 8, 18, 8, 6 };
|
|
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
note_entrance2("vga_ipstat1_inb(%x,%x)", port, value);
|
|
|
|
#ifdef V7VGA
|
|
attribute_controller.address.as_bfld.index_state = 0;
|
|
#else
|
|
set_index_state(); /* Initialize the Attribute register flip-flop (EGA tech ref, p 56) */
|
|
#endif /* V7VGA */
|
|
|
|
vga_ip0_state_count --; /* attempt relative 'timings' */
|
|
switch (vga_ip0_state) {
|
|
|
|
case 0:
|
|
if (vga_ip0_state_count == 0) { /* change to next state ? */
|
|
h = gmfudge << 1;
|
|
gmfudge = (h&0x80000000) ^ (gmfudge & 0x80000000)? h|1 : h;
|
|
vga_ip0_state_count = s_lengths[1] + (gmfudge & 3);
|
|
vga_ip0_state = 1;
|
|
}
|
|
input_status_register_zero.as_bfld.crt_interrupt = 0; /* = !VS */
|
|
*value = 0x05;
|
|
break;
|
|
|
|
case 1:
|
|
if (vga_ip0_state_count == 0) { /* change to next state ? */
|
|
h = gmfudge << 1;
|
|
gmfudge = (h&0x80000000) ^ (gmfudge & 0x80000000)? h|1 : h;
|
|
vga_ip0_state_count = s_lengths[2] + (gmfudge & 3);
|
|
vga_ip0_state = 2;
|
|
sub_state = 2;
|
|
}
|
|
switch (sub_state) { /* cycle through 0,0,1 sequence */
|
|
case 0: /* to represent DE toggling */
|
|
*value = 0x04;
|
|
sub_state = 1;
|
|
break;
|
|
case 1:
|
|
*value = 0x04;
|
|
sub_state = 2;
|
|
break;
|
|
case 2:
|
|
*value = 0x05;
|
|
sub_state = 0;
|
|
break;
|
|
}
|
|
input_status_register_zero.as_bfld.crt_interrupt = 0; /* = !VS */
|
|
break;
|
|
|
|
case 2:
|
|
if (vga_ip0_state_count == 0) { /* change to next state ? */
|
|
h = gmfudge << 1;
|
|
gmfudge = (h&0x80000000) ^ (gmfudge & 0x80000000)? h|1 : h;
|
|
vga_ip0_state_count = s_lengths[3] + (gmfudge & 3);
|
|
vga_ip0_state = 3;
|
|
}
|
|
*value = 0x05;
|
|
input_status_register_zero.as_bfld.crt_interrupt = 0; /* = !VS */
|
|
break;
|
|
|
|
case 3:
|
|
if (vga_ip0_state_count == 0) { /* wrap back to first state */
|
|
h = gmfudge << 1;
|
|
gmfudge = (h&0x80000000) ^ (gmfudge & 0x80000000)? h|1 : h;
|
|
vga_ip0_state_count = s_lengths[0] + (gmfudge & 3);
|
|
vga_ip0_state = 0;
|
|
}
|
|
input_status_register_zero.as_bfld.crt_interrupt = 1; /* = !VS */
|
|
*value = 0x0d;
|
|
break;
|
|
}
|
|
note_entrance1("returning %x",*value);
|
|
}
|
|
|
|
#endif /* !(NTVDM || host_get_time_ms || host_get_count_ms) */
|
|
|
|
GLOBAL VOID vga_gc_inb IFN2(io_addr,port,half_word *, value)
|
|
{
|
|
note_entrance1("vga_gc_inb(%x)", port);
|
|
if (port == EGA_GC_INDEX) {
|
|
*value = graphics_controller.address.as.abyte;
|
|
note_entrance1("returning %x",*value);
|
|
return;
|
|
}
|
|
if (port == EGA_GC_DATA) {
|
|
switch(graphics_controller.address.as.abyte) {
|
|
|
|
case 0:
|
|
*value = graphics_controller.set_or_reset.as.abyte;
|
|
break;
|
|
case 1:
|
|
*value = graphics_controller.enable_set_or_reset.as.abyte;
|
|
break;
|
|
case 2:
|
|
*value = graphics_controller.color_compare.as.abyte;
|
|
break;
|
|
case 3:
|
|
*value = graphics_controller.data_rotate.as.abyte;
|
|
break;
|
|
case 4:
|
|
*value = getVideoread_mapped_plane();
|
|
break;
|
|
case 5:
|
|
*value = graphics_controller.mode.as.abyte;
|
|
break;
|
|
case 6:
|
|
*value = graphics_controller.miscellaneous.as.abyte;
|
|
break;
|
|
case 7:
|
|
*value = graphics_controller.color_dont_care.as.abyte;
|
|
break;
|
|
case 8:
|
|
*value = getVideobit_prot_mask() & 0xff;
|
|
break;
|
|
default:
|
|
assert1(NO,"Bad gc index %d",graphics_controller.address.as.abyte);
|
|
*value = IO_EMPTY_PORT_BYTE_VALUE;
|
|
}
|
|
note_entrance1("returning %x",*value);
|
|
}
|
|
else {
|
|
assert1(NO,"Bad gc port %d",port);
|
|
*value = IO_EMPTY_PORT_BYTE_VALUE;
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_ac_outb IFN2(io_addr,port,half_word,value)
|
|
{
|
|
struct {
|
|
unsigned value : 8;
|
|
} new;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
|
|
note_entrance2("vga_ac_outb(%x,%x)", port, value);
|
|
assert1( port == EGA_AC_INDEX_DATA, "Bad port %x", port);
|
|
new.value = value;
|
|
#ifdef V7VGA
|
|
attribute_controller.address.as_bfld.index_state = !attribute_controller.address.as_bfld.index_state;
|
|
if (attribute_controller.address.as_bfld.index_state) {
|
|
#else
|
|
if ( in_index_state() ) {
|
|
#endif /* V7VGA */
|
|
note_entrance1("Setting index to %d", value);
|
|
if (((value & 0x20) >> 5) != attribute_controller.address.as_bfld.palette_address_source)
|
|
{
|
|
if (value & 0x20)
|
|
{
|
|
set_display_disabled(FALSE);
|
|
timer_video_enabled = 1;
|
|
enable_gfx_update_routines();
|
|
screen_refresh_required();
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* not strictly accurate, since we are meant to fill the screen with
|
|
* the current overscan colour. However that is normally black so this
|
|
* will do.
|
|
*/
|
|
set_display_disabled(TRUE);
|
|
timer_video_enabled = 0;
|
|
disable_gfx_update_routines();
|
|
}
|
|
}
|
|
#ifdef V7VGA
|
|
attribute_controller.address.as.abyte = (attribute_controller.address.as_bfld.index_state << 7) | (value & 0x3f);
|
|
#else
|
|
attribute_controller.address.as.abyte = value;
|
|
#endif /* V7VGA */
|
|
} else {
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"attr(%#x,%#x)\n",attribute_controller.address.as_bfld.index,value);)
|
|
switch (attribute_controller.address.as_bfld.index) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 0xa:
|
|
case 0xb:
|
|
case 0xc:
|
|
case 0xd:
|
|
case 0xe:
|
|
case 0xf:
|
|
note_entrance1("Change palette %d",attribute_controller.address.as_bfld.index);
|
|
attribute_controller.palette[attribute_controller.address.as_bfld.index].as.abyte = value;
|
|
set_palette_val(attribute_controller.address.as_bfld.index, value);
|
|
|
|
flag_palette_change_required();
|
|
break;
|
|
case 0x10:
|
|
note_entrance0("mode control reg");
|
|
if (attribute_controller.mode_control.as_bfld.background_intensity_or_blink !=
|
|
((AC_MODE_CONTROL*)&new)->as_bfld.background_intensity_or_blink)
|
|
{
|
|
set_intensity( ((AC_MODE_CONTROL*)&new)->as_bfld.background_intensity_or_blink );
|
|
}
|
|
if (attribute_controller.mode_control.as_bfld.select_video_bits !=
|
|
((AC_MODE_CONTROL*)&new)->as_bfld.select_video_bits)
|
|
{
|
|
set_colour_select(((AC_MODE_CONTROL*)&new)->as_bfld.select_video_bits);
|
|
flag_palette_change_required();
|
|
}
|
|
attribute_controller.mode_control.as.abyte = value;
|
|
|
|
if (attribute_controller.mode_control.as_bfld.background_intensity_or_blink)
|
|
/* blinking - not supported */
|
|
bg_col_mask = 0x70;
|
|
else
|
|
/* using blink bit to provide 16 background colours */
|
|
bg_col_mask = 0xf0;
|
|
|
|
/* Vote on alpha/graphics mode */
|
|
vote_vga_mode();
|
|
assert0(attribute_controller.mode_control.as_bfld.display_type == 0, "Mono display selected");
|
|
assert0(attribute_controller.mode_control.as_bfld.enable_line_graphics_char_codes == 0,
|
|
"line graphics enabled");
|
|
break;
|
|
case 0x11:
|
|
note_entrance0("set border");
|
|
attribute_controller.overscan_color.as.abyte = value;
|
|
EGA_GRAPH.border[RED] = get_border_color(red_border,secondary_red_border);
|
|
EGA_GRAPH.border[GREEN] = get_border_color(green_border,secondary_green_border);
|
|
EGA_GRAPH.border[BLUE] = get_border_color(blue_border,secondary_blue_border);
|
|
host_set_border_colour(value);
|
|
break;
|
|
case 0x12:
|
|
note_entrance1("color plane enable %x",value);
|
|
if ( attribute_controller.color_plane_enable.as_bfld.color_plane_enable !=
|
|
((COLOR_PLANE_ENABLE*)&new)->as_bfld.color_plane_enable ) {
|
|
set_plane_mask(((COLOR_PLANE_ENABLE*)&new)->as_bfld.color_plane_enable);
|
|
host_change_plane_mask(get_plane_mask()); /* Update Host palette */
|
|
}
|
|
attribute_controller.color_plane_enable.as.abyte = value;
|
|
break;
|
|
case 0x13:
|
|
note_entrance0("horiz pel panning");
|
|
attribute_controller.horizontal_pel_panning.as.abyte = value;
|
|
break;
|
|
case 0x14:
|
|
note_entrance0("pixel padding register");
|
|
if (attribute_controller.pixel_padding.as_bfld.color_top_bits !=
|
|
((PIXEL_PAD*)&new)->as_bfld.color_top_bits)
|
|
{
|
|
set_top_pixel_pad(((PIXEL_PAD*)&new)->as_bfld.color_top_bits);
|
|
flag_palette_change_required();
|
|
}
|
|
if (attribute_controller.pixel_padding.as_bfld.color_mid_bits !=
|
|
((PIXEL_PAD*)&new)->as_bfld.color_mid_bits)
|
|
{
|
|
set_mid_pixel_pad(((PIXEL_PAD*)&new)->as_bfld.color_mid_bits);
|
|
flag_palette_change_required();
|
|
}
|
|
attribute_controller.pixel_padding.as.abyte = value;
|
|
break;
|
|
default:
|
|
assert1(NO,"Bad ac index %d", attribute_controller.address.as_bfld.index);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_ac_inb IFN2(io_addr,port,half_word *, value)
|
|
{
|
|
note_entrance1("vga_ac_inb(%x)", port);
|
|
if (port == EGA_AC_INDEX_DATA) { /* 3c0 */
|
|
*value = attribute_controller.address.as.abyte;
|
|
note_entrance1("returning %x",*value);
|
|
return;
|
|
}
|
|
if (port == EGA_AC_SECRET) { /* 3c1 */
|
|
switch (attribute_controller.address.as_bfld.index) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 0xa:
|
|
case 0xb:
|
|
case 0xc:
|
|
case 0xd:
|
|
case 0xe:
|
|
case 0xf:
|
|
*value = attribute_controller.palette[attribute_controller.address.as_bfld.index].as.abyte;
|
|
break;
|
|
case 0x10:
|
|
*value = attribute_controller.mode_control.as.abyte;
|
|
break;
|
|
case 0x11:
|
|
*value = attribute_controller.overscan_color.as.abyte;
|
|
break;
|
|
case 0x12:
|
|
*value = attribute_controller.color_plane_enable.as.abyte;
|
|
break;
|
|
case 0x13:
|
|
*value = attribute_controller.horizontal_pel_panning.as.abyte;
|
|
break;
|
|
case 0x14:
|
|
*value = attribute_controller.pixel_padding.as.abyte;
|
|
break;
|
|
}
|
|
note_entrance1("returning %x",*value);
|
|
}
|
|
else {
|
|
assert1(NO,"Bad ac port %d",port);
|
|
*value = IO_EMPTY_PORT_BYTE_VALUE;
|
|
}
|
|
}
|
|
|
|
GLOBAL VOID vga_misc_outb IFN2(io_addr,port,half_word,value)
|
|
{
|
|
MISC_OUTPUT_REG new;
|
|
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
|
|
NON_PROD(if(io_verbose & EGA_PORTS_VERBOSE)fprintf(trace_file,"misc %#x\n",value);)
|
|
|
|
note_entrance2("vga_misc_outb(%x,%x)", port, value);
|
|
|
|
assert1(port==EGA_MISC_REG,"Bad port %x",port);
|
|
new.as.abyte = value;
|
|
|
|
if (miscellaneous_output_register.as_bfld.enable_ram != new.as_bfld.enable_ram)
|
|
{
|
|
/*
|
|
* writes to plane memory en/disabled
|
|
*/
|
|
|
|
note_entrance0("Ram enabled");
|
|
|
|
#ifndef GISP_SVGA
|
|
if(new.as_bfld.enable_ram)
|
|
sas_connect_memory(gvi_pc_low_regen,gvi_pc_high_regen,(half_word)SAS_VIDEO);
|
|
else
|
|
sas_disconnect_memory(gvi_pc_low_regen,gvi_pc_high_regen);
|
|
#endif /* GISP_SVGA */
|
|
EGA_CPU.ram_enabled = new.as_bfld.enable_ram;
|
|
ega_read_routines_update();
|
|
ega_write_routines_update(RAM_ENABLED);
|
|
}
|
|
|
|
miscellaneous_output_register.as.abyte = new.as.abyte;
|
|
|
|
update_banking();
|
|
}
|
|
|
|
GLOBAL VOID vga_misc_inb IFN2(io_addr,port,half_word *, value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
assert1(port==VGA_MISC_READ_REG,"Bad port %x",port);
|
|
*value = miscellaneous_output_register.as.abyte;
|
|
}
|
|
|
|
GLOBAL VOID vga_ipstat0_inb IFN2(io_addr,port,half_word *, value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
note_entrance1("vga_ipstat0_inb(%x)", port);
|
|
*value = input_status_register_zero.as.abyte;
|
|
note_entrance1("returning %x",*value);
|
|
}
|
|
|
|
GLOBAL VOID vga_feat_outb IFN2(io_addr,port,half_word,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
note_entrance2("ega_feat_outb(%x,%x)", port, value);
|
|
feature_control_register.as.abyte = value;
|
|
}
|
|
|
|
GLOBAL VOID vga_feat_inb IFN2(io_addr,port,half_word *, value)
|
|
{
|
|
UNUSED(port);
|
|
*value = feature_control_register.as.abyte;
|
|
}
|
|
|
|
GLOBAL VOID vga_dac_outb IFN2(io_addr,port,half_word,value)
|
|
{
|
|
note_entrance1("vga_dac_outb %#x",port);
|
|
switch(port) {
|
|
|
|
case VGA_DAC_MASK:
|
|
if (get_DAC_mask() != value) {
|
|
set_DAC_mask(value);
|
|
flag_palette_change_required();
|
|
}
|
|
break;
|
|
|
|
case VGA_DAC_RADDR:
|
|
DAC_rd_addr = value;
|
|
DAC_state = 3; /* show 3c7 status read in read mode */
|
|
assert0(DAC_rgb_state == DAC_RED, "DAC rd addr change when state not RED");
|
|
DAC_rgb_state = DAC_RED;
|
|
break;
|
|
|
|
case VGA_DAC_WADDR:
|
|
DAC_wr_addr = value;
|
|
DAC_state = 0; /* show 3c7 status read in write mode */
|
|
assert0(DAC_rgb_state == DAC_RED, "DAC wr addr change when state not RED");
|
|
DAC_rgb_state = DAC_RED;
|
|
break;
|
|
|
|
default:
|
|
assert1(NO,"Bad DAC port %d",port);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* as this poor little port is hammered, we split it off from it's DAC siblings
|
|
* for (hoped) efficiency.
|
|
*/
|
|
GLOBAL VOID vga_dac_data_outb IFN2(io_addr,port,half_word,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
|
|
note_entrance1("vga_dac_data_outb %#x",port);
|
|
switch(DAC_rgb_state) {
|
|
|
|
case DAC_RED:
|
|
DAC[DAC_wr_addr].red = value & DAC_data_mask;
|
|
DAC_rgb_state = DAC_GREEN;
|
|
break;
|
|
|
|
case DAC_GREEN:
|
|
DAC[DAC_wr_addr].green = value & DAC_data_mask;
|
|
DAC_rgb_state = DAC_BLUE;
|
|
break;
|
|
|
|
case DAC_BLUE:
|
|
DAC[DAC_wr_addr].blue = value & DAC_data_mask;
|
|
DAC_rgb_state = DAC_RED;
|
|
/*
|
|
* very important side affect - many progs dont touch the DAC
|
|
* index reg after setting it to the start of a group.
|
|
*/
|
|
DAC_wr_addr++;
|
|
break;
|
|
|
|
default:
|
|
assert1(NO,"unknown DAC state %d",DAC_rgb_state);
|
|
}
|
|
|
|
flag_palette_change_required();
|
|
}
|
|
|
|
GLOBAL VOID vga_dac_inb IFN2(io_addr,port,half_word *,value)
|
|
{
|
|
note_entrance1("vga_dac_inb %#x",port);
|
|
switch(port) {
|
|
|
|
case VGA_DAC_MASK:
|
|
*value = get_DAC_mask();
|
|
break;
|
|
|
|
case VGA_DAC_RADDR:
|
|
*value= DAC_state; /* either 0 - write mode or 3 - read mode */
|
|
break;
|
|
|
|
case VGA_DAC_WADDR:
|
|
*value = DAC_wr_addr;
|
|
break;
|
|
|
|
default:
|
|
assert1(NO,"Bad DAC port read %d",port);
|
|
}
|
|
note_entrance1("returning %#x",*value);
|
|
}
|
|
|
|
GLOBAL VOID vga_dac_data_inb IFN2(io_addr,port,half_word *,value)
|
|
{
|
|
#ifdef PROD
|
|
UNUSED(port);
|
|
#endif
|
|
note_entrance1("vga_dac_data_inb %#x",port);
|
|
switch(DAC_rgb_state) {
|
|
|
|
case DAC_RED:
|
|
*value = DAC[DAC_rd_addr].red;
|
|
DAC_rgb_state = DAC_GREEN;
|
|
break;
|
|
|
|
case DAC_GREEN:
|
|
*value = DAC[DAC_rd_addr].green;
|
|
DAC_rgb_state = DAC_BLUE;
|
|
break;
|
|
|
|
case DAC_BLUE:
|
|
*value = DAC[DAC_rd_addr].blue;
|
|
DAC_rgb_state = DAC_RED;
|
|
/* NB important side affect of 3rd read */
|
|
DAC_rd_addr++;
|
|
break;
|
|
|
|
default:
|
|
assert1(NO,"bad DAC state %d",DAC_rgb_state);
|
|
}
|
|
note_entrance1("returning %#x",*value);
|
|
}
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
/*
|
|
* There is no way of obtaining the DAC read address via a port access
|
|
* (that we know of). Thus save/restore stuff etc needs this interface.
|
|
*/
|
|
half_word get_vga_DAC_rd_addr()
|
|
{
|
|
return DAC_rd_addr;
|
|
}
|
|
#endif /* NTVDM & X86GFX */
|
|
|
|
VOID vote_vga_mode IFN0()
|
|
{
|
|
int votes;
|
|
|
|
votes = graphics_controller.miscellaneous.as_bfld.graphics_mode;
|
|
votes += attribute_controller.mode_control.as_bfld.graphics_mode;
|
|
switch(votes) {
|
|
case 0:
|
|
if (!is_it_text())
|
|
{
|
|
/* switch to text mode */
|
|
set_text_mode(YES);
|
|
flag_mode_change_required();
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (is_it_text())
|
|
{
|
|
/* switch to graphics mode */
|
|
set_text_mode(NO);
|
|
flag_mode_change_required();
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
if (graphics_controller.miscellaneous.as_bfld.graphics_mode)
|
|
{
|
|
if (is_it_text())
|
|
{
|
|
assert0(NO,"Forcing mode to be graphics cos graphics controller sez so");
|
|
set_text_mode(NO);
|
|
flag_mode_change_required();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!is_it_text())
|
|
{
|
|
assert0(NO,"Forcing mode to be alpha cos graphics controller sez so");
|
|
set_text_mode(YES);
|
|
flag_mode_change_required();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert1(NO,"Wierd vote result %d in vote_vga_mode",votes);
|
|
}
|
|
} /* vote_vga_mode */
|
|
|
|
#ifdef GISP_SVGA
|
|
/*(
|
|
* function : mapRealIOPorts( )
|
|
*
|
|
* purpose : mapping of real io functions for HW
|
|
* vga on ccpu
|
|
*
|
|
* inputs : none
|
|
* outputs : none
|
|
* returns : void
|
|
* globals : none
|
|
*
|
|
*
|
|
)*/
|
|
|
|
void
|
|
mapRealIOPorts IFN0( )
|
|
{
|
|
always_trace0("mapping vga ports to _real_ IN/OUT");
|
|
/*
|
|
* Define sequencer's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_SEQ_ADAP_INDEX, hostRealOUTB );
|
|
io_define_outb(EGA_SEQ_ADAP_DATA, hostRealOUTB );
|
|
io_define_inb(EGA_SEQ_ADAP_INDEX, hostRealINB );
|
|
io_define_inb(EGA_SEQ_ADAP_DATA, hostRealINB );
|
|
|
|
/*
|
|
* Define CRTC's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_CRTC_ADAPTOR, hostRealOUTB );
|
|
io_define_inb(EGA_CRTC_ADAPTOR, hostRealINB );
|
|
|
|
/*
|
|
* Define Graphics Controller's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_GC_ADAP_INDEX, hostRealOUTB );
|
|
Cpu_define_outb(EGA_GC_ADAP_INDEX, NULL );
|
|
|
|
io_define_outb(EGA_GC_ADAP_DATA, hostRealOUTB );
|
|
Cpu_define_outb(EGA_GC_ADAP_DATA,NULL);
|
|
|
|
io_define_inb(EGA_GC_ADAP_INDEX, hostRealINB );
|
|
io_define_inb(EGA_GC_ADAP_DATA, hostRealINB );
|
|
|
|
/*
|
|
* Define Attribute controller's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_AC_ADAPTOR, hostRealOUTB );
|
|
io_define_inb(EGA_AC_ADAPTOR, hostRealINB );
|
|
|
|
/*
|
|
* Define Miscellaneous register's port
|
|
*/
|
|
|
|
io_define_outb(EGA_MISC_ADAPTOR, hostRealOUTB );
|
|
io_define_inb(EGA_MISC_ADAPTOR, hostRealINB );
|
|
|
|
/*
|
|
* Define Feature controller's port
|
|
*/
|
|
|
|
io_define_outb(EGA_FEAT_ADAPTOR, hostRealOUTB );
|
|
io_define_inb(EGA_FEAT_ADAPTOR, hostRealINB );
|
|
|
|
/*
|
|
* Define Input Status Register 0 port
|
|
*/
|
|
|
|
io_define_inb(EGA_IPSTAT0_ADAPTOR, hostRealINB );
|
|
|
|
/*
|
|
* Define Input Status Register 1 port
|
|
*/
|
|
|
|
io_define_inb(EGA_IPSTAT1_ADAPTOR, hostRealINB );
|
|
|
|
/*
|
|
* Define VGA DAC register port
|
|
*/
|
|
io_define_inb(VGA_DAC_INDEX_PORT, hostRealINB );
|
|
io_define_outb(VGA_DAC_INDEX_PORT, hostRealOUTB );
|
|
io_define_inb(VGA_DAC_DATA_PORT, hostRealINB );
|
|
io_define_outb(VGA_DAC_DATA_PORT, hostRealOUTB );
|
|
|
|
}
|
|
|
|
|
|
/*(
|
|
* function : mapEmulatedIOPorts( )
|
|
*
|
|
* purpose : mapping of emulated io functions for HW
|
|
* vga on ccpu
|
|
*
|
|
* inputs : none
|
|
* outputs : none
|
|
* returns : void
|
|
* globals : none
|
|
*
|
|
*
|
|
)*/
|
|
|
|
void
|
|
mapEmulatedIOPorts IFN0( )
|
|
{
|
|
always_trace0( "Mapping vga ports to Emulation" );
|
|
|
|
/*
|
|
* Define sequencer's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_SEQ_ADAP_INDEX,vga_seq_outb_index);
|
|
io_define_outb(EGA_SEQ_ADAP_DATA,ega_seq_reset);
|
|
io_define_inb(EGA_SEQ_ADAP_INDEX,vga_seq_inb);
|
|
io_define_inb(EGA_SEQ_ADAP_DATA,vga_seq_inb);
|
|
io_connect_port(EGA_SEQ_INDEX,EGA_SEQ_ADAP_INDEX,IO_READ_WRITE);
|
|
io_connect_port(EGA_SEQ_DATA,EGA_SEQ_ADAP_DATA,IO_READ_WRITE);
|
|
|
|
/*
|
|
* Define CRTC's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_CRTC_ADAPTOR,vga_crtc_outb);
|
|
io_define_inb(EGA_CRTC_ADAPTOR,vga_crtc_inb);
|
|
io_connect_port(EGA_CRTC_INDEX,EGA_CRTC_ADAPTOR,IO_READ_WRITE);
|
|
io_connect_port(EGA_CRTC_DATA,EGA_CRTC_ADAPTOR,IO_READ_WRITE);
|
|
|
|
/*
|
|
* Define Graphics Controller's ports
|
|
*/
|
|
|
|
vga_gc_outb_index_addr = (UTINY *) &graphics_controller.address;
|
|
|
|
io_define_outb(EGA_GC_ADAP_INDEX,vga_gc_outb_index);
|
|
Cpu_define_outb(EGA_GC_ADAP_INDEX,_vga_gc_outb_index);
|
|
|
|
io_define_outb(EGA_GC_ADAP_DATA,ega_gc_set_reset);
|
|
Cpu_define_outb(EGA_GC_ADAP_DATA,NULL);
|
|
|
|
io_define_inb(EGA_GC_ADAP_INDEX,vga_gc_inb);
|
|
io_define_inb(EGA_GC_ADAP_DATA,vga_gc_inb);
|
|
|
|
io_connect_port(EGA_GC_INDEX,EGA_GC_ADAP_INDEX,IO_READ_WRITE);
|
|
io_connect_port(EGA_GC_DATA,EGA_GC_ADAP_DATA,IO_READ_WRITE);
|
|
|
|
/*
|
|
* Define Attribute controller's ports
|
|
*/
|
|
|
|
io_define_outb(EGA_AC_ADAPTOR,vga_ac_outb);
|
|
io_define_inb(EGA_AC_ADAPTOR,vga_ac_inb);
|
|
io_connect_port(EGA_AC_INDEX_DATA,EGA_AC_ADAPTOR,IO_READ_WRITE);
|
|
io_connect_port(EGA_AC_SECRET,EGA_AC_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Miscellaneous register's port
|
|
*/
|
|
|
|
io_define_outb(EGA_MISC_ADAPTOR,vga_misc_outb);
|
|
io_define_inb(EGA_MISC_ADAPTOR,vga_misc_inb);
|
|
io_connect_port(EGA_MISC_REG,EGA_MISC_ADAPTOR,IO_WRITE);
|
|
io_connect_port(VGA_MISC_READ_REG,EGA_MISC_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Feature controller's port
|
|
*/
|
|
|
|
io_define_outb(EGA_FEAT_ADAPTOR,vga_feat_outb);
|
|
io_define_inb(EGA_FEAT_ADAPTOR,vga_feat_inb);
|
|
io_connect_port(EGA_FEAT_REG,EGA_FEAT_ADAPTOR,IO_WRITE);
|
|
io_connect_port(VGA_FEAT_READ_REG,EGA_FEAT_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Input Status Register 0 port
|
|
*/
|
|
|
|
io_define_inb(EGA_IPSTAT0_ADAPTOR,vga_ipstat0_inb);
|
|
io_connect_port(EGA_IPSTAT0_REG,EGA_IPSTAT0_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define Input Status Register 1 port
|
|
*/
|
|
|
|
io_define_inb(EGA_IPSTAT1_ADAPTOR,vga_ipstat1_inb);
|
|
io_connect_port(EGA_IPSTAT1_REG,EGA_IPSTAT1_ADAPTOR,IO_READ);
|
|
|
|
/*
|
|
* Define VGA DAC register port
|
|
*/
|
|
io_define_inb(VGA_DAC_INDEX_PORT,vga_dac_inb);
|
|
io_define_outb(VGA_DAC_INDEX_PORT,vga_dac_outb);
|
|
io_connect_port(VGA_DAC_MASK,VGA_DAC_INDEX_PORT,IO_READ_WRITE);
|
|
io_connect_port(VGA_DAC_RADDR,VGA_DAC_INDEX_PORT,IO_READ_WRITE);
|
|
io_connect_port(VGA_DAC_WADDR,VGA_DAC_INDEX_PORT,IO_READ_WRITE);
|
|
io_define_inb(VGA_DAC_DATA_PORT,vga_dac_data_inb);
|
|
io_define_outb(VGA_DAC_DATA_PORT,vga_dac_data_outb);
|
|
io_connect_port(VGA_DAC_DATA,VGA_DAC_DATA_PORT,IO_READ_WRITE);
|
|
|
|
}
|
|
|
|
#endif /* GISP_SVGA */
|
|
|
|
|
|
#ifdef HUNTER
|
|
|
|
/* Get line compare value */
|
|
|
|
LONG vga_get_line_compare IFN0()
|
|
|
|
{
|
|
LONG return_value;
|
|
|
|
return_value = crt_controller.line_compare;
|
|
if (crt_controller.crtc_overflow.as_bfld.line_compare_bit_8 != 0)
|
|
return_value += 0x100;
|
|
return (return_value);
|
|
} /* ega_get_line_compare */
|
|
|
|
/* Get maximum scan lines value */
|
|
|
|
LONG vga_get_max_scan_lines IFN0()
|
|
|
|
{
|
|
return (crt_controller.maximum_scan_line.as_bfld.maximum_scan_line);
|
|
} /* ega_get_max_scan_lines */
|
|
|
|
/* Set line compare value */
|
|
|
|
VOID vga_set_line_compare IFN1(LONG,lcomp_val)
|
|
|
|
/* lcomp_val ----> new value for line compare */
|
|
|
|
{
|
|
CRTC_OVERFLOW new_overflow;
|
|
|
|
new_overflow.as.abyte = crt_controller.crtc_overflow.as.abyte;
|
|
if (lcomp_val >= 0x100)
|
|
new_overflow.as_bfld.line_compare_bit_8 = 1;
|
|
else
|
|
new_overflow.as_bfld.line_compare_bit_8 = 0;
|
|
|
|
outb(EGA_CRTC_INDEX, 7);
|
|
outb(EGA_CRTC_DATA, new_overflow.as.abyte);
|
|
outb(EGA_CRTC_INDEX, 24);
|
|
outb(EGA_CRTC_DATA, lcomp_val & 0xff);
|
|
}
|
|
|
|
#endif /* HUNTER */
|
|
#endif /* VGG */
|
|
#endif /* REAL_VGA */
|