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.
6664 lines
170 KiB
6664 lines
170 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*
|
|
* SoftPC Revision 3.0
|
|
*
|
|
* Title : Mouse Driver Emulation
|
|
*
|
|
* Emulated Version : 8.00
|
|
*
|
|
*
|
|
* Description : This module provides an emulation of the Microsoft
|
|
* Mouse Driver: the module is accessed using the following
|
|
* BOP calls from the BIOS:
|
|
*
|
|
* mouse_install1() | Mouse Driver install
|
|
* mouse_install2() | routines
|
|
*
|
|
* mouse_int1() | Mouse Driver hardware interrupt
|
|
* mouse_int2() | handling routines
|
|
*
|
|
* mouse_io_interrupt() | Mouse Driver io function assembler
|
|
* mouse_io_language() | and high-level language interfaces
|
|
*
|
|
* mouse_video_io() | Intercepts video io function
|
|
*
|
|
* Since a mouse driver can only be installed AFTER the
|
|
* operating system has booted, a small Intel program must
|
|
* run to enable the Insignia Mouse Driver. This program
|
|
* calls BOP mouse_install2 if an existing mouse driver
|
|
* is detected; otherwise BOP mouse_install1 is called to
|
|
* start the Insignia Mouse Driver.
|
|
*
|
|
* When the Insignia Mouse Driver is enabled, interrupts
|
|
* are processed as follows
|
|
*
|
|
* INT 0A (Mouse hardware interrupt) BOP mouse_int1-2
|
|
* INT 10 (Video IO interrupt) BOP mouse_video_io
|
|
* INT 33 (Mouse IO interrupt) BOP mouse_io_interrupt
|
|
*
|
|
* High-level languages can call a mouse io entry point 2 bytes
|
|
* above the interrupt entry point: this call is handled
|
|
* using a BOP mouse_io_language.
|
|
*
|
|
* Author : Ross Beresford
|
|
*
|
|
* Notes : The functionality of the Mouse Driver was established
|
|
* from the following sources:
|
|
* Microsoft Mouse User's Guide
|
|
* IBM PC-XT Technical Reference Manuals
|
|
* Microsoft InPort Technical Note
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* static char SccsID[]="07/04/95 @(#)mouse_io.c 1.72 Copyright Insignia Solutions Ltd.";
|
|
*/
|
|
|
|
|
|
#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_MOUSE.seg"
|
|
#endif
|
|
|
|
|
|
/*
|
|
* O/S include files.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
#include StringH
|
|
|
|
/*
|
|
* SoftPC include files
|
|
*/
|
|
#include "xt.h"
|
|
#include "ios.h"
|
|
#include "bios.h"
|
|
#include "sas.h"
|
|
#include CpuH
|
|
#include "trace.h"
|
|
#include "debug.h"
|
|
#include "gvi.h"
|
|
#include "cga.h"
|
|
#ifdef EGG
|
|
#include "egacpu.h"
|
|
#include "egaports.h"
|
|
#include "egavideo.h"
|
|
#endif
|
|
#include "error.h"
|
|
#include "config.h"
|
|
#include "mouse_io.h"
|
|
#include "ica.h"
|
|
#include "video.h"
|
|
#include "gmi.h"
|
|
#include "gfx_upd.h"
|
|
#include "egagraph.h"
|
|
#include "vgaports.h"
|
|
#include "keyboard.h"
|
|
#include "virtual.h"
|
|
|
|
#ifdef NTVDM
|
|
#include "nt_event.h"
|
|
#include "nt_mouse.h"
|
|
|
|
#ifdef MONITOR
|
|
/*
|
|
* We're running with real ROMs on the monitor and so all the hard coded ROM
|
|
* addresses defined below don't work. Pick up the real addresses of this stuff
|
|
* which is now resident in the driver and put it into the MOUSE_ tokens which
|
|
* have been magically changed into variables.
|
|
*/
|
|
#undef MOUSE_INT1_SEGMENT
|
|
#undef MOUSE_INT1_OFFSET
|
|
#undef MOUSE_INT2_SEGMENT
|
|
#undef MOUSE_INT2_OFFSET
|
|
#undef MOUSE_IO_INTERRUPT_OFFSET
|
|
#undef MOUSE_IO_INTERRUPT_SEGMENT
|
|
#undef MOUSE_VIDEO_IO_OFFSET
|
|
#undef MOUSE_VIDEO_IO_SEGMENT
|
|
#undef MOUSE_COPYRIGHT_SEGMENT
|
|
#undef MOUSE_COPYRIGHT_OFFSET
|
|
#undef MOUSE_VERSION_SEGMENT
|
|
#undef MOUSE_VERSION_OFFSET
|
|
#undef VIDEO_IO_SEGMENT
|
|
#undef VIDEO_IO_RE_ENTRY
|
|
|
|
LOCAL word MOUSE_INT1_SEGMENT, MOUSE_INT1_OFFSET,
|
|
MOUSE_IO_INTERRUPT_OFFSET, MOUSE_IO_INTERRUPT_SEGMENT,
|
|
MOUSE_VIDEO_IO_SEGMENT, MOUSE_VIDEO_IO_OFFSET,
|
|
MOUSE_COPYRIGHT_SEGMENT, MOUSE_COPYRIGHT_OFFSET,
|
|
MOUSE_VERSION_SEGMENT, MOUSE_VERSION_OFFSET,
|
|
MOUSE_INT2_SEGMENT, MOUSE_INT2_OFFSET,
|
|
VIDEO_IO_SEGMENT, VIDEO_IO_RE_ENTRY;
|
|
|
|
/* @ACW */
|
|
word DRAW_FS_POINTER_OFFSET; /* holds segment:offset for the Intel code which */
|
|
word DRAW_FS_POINTER_SEGMENT;/* draws the fullscreen mouse cursor */
|
|
word POINTER_ON_OFFSET;
|
|
word POINTER_ON_SEGMENT;
|
|
word POINTER_OFF_OFFSET;
|
|
word POINTER_OFF_SEGMENT;
|
|
WORD F0_OFFSET,F0_SEGMENT;
|
|
word F9_OFFSET,F9_SEGMENT;
|
|
word CP_X_O,CP_Y_O;
|
|
word CP_X_S,CP_Y_S;
|
|
word savedtextsegment,savedtextoffset;
|
|
word button_off,button_seg;
|
|
|
|
static word mouseINBsegment, mouseINBoffset;
|
|
static word mouseOUTBsegment, mouseOUTBoffset;
|
|
static word mouseOUTWsegment, mouseOUTWoffset;
|
|
sys_addr mouseCFsysaddr;
|
|
sys_addr conditional_off_sysaddr;
|
|
|
|
#endif /* MONITOR */
|
|
|
|
IMPORT void host_m2p_ratio(word *,word *,word *,word *);
|
|
IMPORT void host_x_range(word *,word *,word *,word *);
|
|
IMPORT void host_y_range(word *,word *,word *,word *);
|
|
void host_show_pointer(void);
|
|
void host_hide_pointer(void);
|
|
|
|
LOCAL word saved_int71_segment;
|
|
LOCAL word saved_int71_offset;
|
|
|
|
#endif /* NTVDM */
|
|
|
|
#include "host_gfx.h"
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
#include HostHwVgaH
|
|
#include "hwvga.h"
|
|
#include "mouse16b.h"
|
|
#endif /* MOUSE_16_BIT */
|
|
|
|
/*
|
|
* Tidy define to optimise port accesses, motivated by discovering
|
|
* how bad it is to run out of register windows on the SPARC.
|
|
*/
|
|
|
|
#ifdef CPU_40_STYLE
|
|
|
|
/* IO virtualisation is essential - no optimisation allowed. */
|
|
#define OUTB(port, val) outb(port, val)
|
|
|
|
#else
|
|
|
|
IMPORT VOID (**get_outb_ptr())();
|
|
#define OUTB(port, val) (**get_outb_ptr(port))(port, val)
|
|
|
|
#endif /* CPU_40_STYLE */
|
|
|
|
/*
|
|
Offsets to data buffers held in MOUSE.COM (built from
|
|
base/intel/mouse/uf.mouse.asm).
|
|
*/
|
|
#define OFF_HOOK_POSN 0x103
|
|
#define OFF_ACCL_BUFFER 0x105
|
|
#define OFF_MOUSE_INI_BUFFER 0x249
|
|
|
|
/*
|
|
Data values for mouse functions.
|
|
*/
|
|
#define MOUSE_M1 (0xffff)
|
|
#define MOUSE_M2 (0xfffe)
|
|
|
|
#define MAX_NR_VIDEO_MODES 0x7F
|
|
|
|
#ifdef EGG
|
|
LOCAL BOOL jap_mouse=FALSE; /* flag if need to fake text cursor */
|
|
IMPORT IU8 Currently_emulated_video_mode; /* as set in ega_set_mode() */
|
|
#endif /* EGG */
|
|
|
|
/*
|
|
* MOUSE DRIVER LOCAL STATE DATA
|
|
* =============================
|
|
*/
|
|
|
|
/*
|
|
* Function Declarations
|
|
*/
|
|
LOCAL void mouse_reset IPT4(word *,installed_ptr,word *,nbuttons_ptr,word *,junk3,word *,junk4);
|
|
|
|
LOCAL void mouse_show_cursor IPT4(word *,junk1,word *,junk2,word *,junk3,word *,junk4);
|
|
|
|
LOCAL void mouse_hide_cursor IPT4(word *,junk1,word *,junk2,word *,junk3,word *,junk4);
|
|
|
|
LOCAL void mouse_get_position IPT4(word *,junk1,MOUSE_STATE *,button_status_ptr,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr);
|
|
|
|
LOCAL void mouse_set_position IPT4(word *,junk1,word *,junk2,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr);
|
|
|
|
LOCAL void mouse_get_press IPT4(MOUSE_STATE *,button_status_ptr,MOUSE_COUNT *,button_ptr,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr);
|
|
|
|
LOCAL void mouse_get_release IPT4(MOUSE_STATE *,button_status_ptr,MOUSE_COUNT *,button_ptr,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr);
|
|
|
|
LOCAL void mouse_set_range_x IPT4(word *,junk1,word *,junk2,MOUSE_SCALAR *,minimum_x_ptr,MOUSE_SCALAR *,maximum_x_ptr);
|
|
|
|
LOCAL void mouse_set_range_y IPT4(word *,junk1,word *,junk2,MOUSE_SCALAR *,minimum_y_ptr,MOUSE_SCALAR *,maximum_y_ptr);
|
|
|
|
LOCAL void mouse_set_graphics IPT4(word *,junk1,MOUSE_SCALAR *,hot_spot_x_ptr,MOUSE_SCALAR *,hot_spot_y_ptr,word *,bitmap_address);
|
|
|
|
LOCAL void mouse_set_text IPT4(word *,junk1,MOUSE_STATE *,text_cursor_type_ptr,MOUSE_SCREEN_DATA *,parameter1_ptr,MOUSE_SCREEN_DATA *,parameter2_ptr);
|
|
|
|
LOCAL void mouse_read_motion IPT4(word *,junk1,word *,junk2,MOUSE_COUNT *,motion_count_x_ptr,MOUSE_COUNT *,motion_count_y_ptr);
|
|
|
|
LOCAL void mouse_set_subroutine IPT4(word *,junk1,word *,junk2,word *,call_mask,word *,subroutine_address);
|
|
|
|
LOCAL void mouse_light_pen_on IPT4(word *,junk1,word *,junk2,word *,junk3,word *,junk4);
|
|
|
|
LOCAL void mouse_light_pen_off IPT4(word *,junk1,word *,junk2,word *,junk3,word *,junk4);
|
|
|
|
LOCAL void mouse_set_ratio IPT4(word *,junk1,word *,junk2,MOUSE_SCALAR *,ratio_x_ptr,MOUSE_SCALAR *,ratio_y_ptr);
|
|
|
|
LOCAL void mouse_conditional_off IPT4(word *,junk1,word *,junk2,MOUSE_SCALAR *,upper_x_ptr,MOUSE_SCALAR *,upper_y_ptr);
|
|
|
|
LOCAL void mouse_unrecognised IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_set_double_speed IPT4(word *,junk1,word *,junk2,word *,junk3,word *,threshold_speed);
|
|
|
|
LOCAL void mouse_get_and_set_subroutine IPT4(word *,junk1,word *,junk2,word *,call_mask,word *,subroutine_address);
|
|
|
|
LOCAL void mouse_get_state_size IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_save_state IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_restore_state IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_set_alt_subroutine IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_alt_subroutine IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_set_sensitivity IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_sensitivity IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_set_int_rate IPT4(word *,m1,word *,int_rate_ptr,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_set_pointer_page IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_pointer_page IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_driver_disable IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_driver_enable IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_set_language IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_language IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_info IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_driver_info IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_max_coords IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void mouse_get_masks_and_mickeys IPT4
|
|
(
|
|
MOUSE_SCREEN_DATA *, screen_mask_ptr, /* aka start line */
|
|
MOUSE_SCREEN_DATA *, cursor_mask_ptr, /* aka stop line */
|
|
MOUSE_SCALAR *, raw_horiz_count,
|
|
MOUSE_SCALAR *, raw_vert_count
|
|
); /* FUNC 39 */
|
|
|
|
LOCAL void mouse_set_video_mode IPT4
|
|
(
|
|
word *, m1,
|
|
word *, m2,
|
|
word *, video_mode_ptr,
|
|
word *, font_size_ptr
|
|
); /* FUNC 40 */
|
|
|
|
LOCAL void mouse_enumerate_video_modes IPT4
|
|
(
|
|
word *, m1,
|
|
word *, m2,
|
|
word *, video_nr_ptr,
|
|
word *, offset_ptr
|
|
); /* FUNC 41 */
|
|
|
|
LOCAL void mouse_get_cursor_hot_spot IPT4
|
|
(
|
|
word *, fCursor_ptr,
|
|
MOUSE_SCALAR *, hot_spot_x_ptr,
|
|
MOUSE_SCALAR *, hot_spot_y_ptr,
|
|
word *, mouse_type_ptr
|
|
); /* FUNC 42 */
|
|
|
|
LOCAL void mouse_load_acceleration_curves IPT4
|
|
(
|
|
word *, success_ptr,
|
|
word *, curve_ptr,
|
|
word *, m3,
|
|
word *, m4
|
|
); /* FUNC 43 */
|
|
|
|
LOCAL void mouse_read_acceleration_curves IPT4
|
|
(
|
|
word *, success_ptr,
|
|
word *, curve_ptr,
|
|
word *, m3,
|
|
word *, m4
|
|
); /* FUNC 44 */
|
|
|
|
LOCAL void mouse_set_get_active_acceleration_curve IPT4
|
|
(
|
|
word *, success_ptr,
|
|
word *, curve_ptr,
|
|
word *, m3,
|
|
word *, m4
|
|
); /* FUNC 45 */
|
|
|
|
LOCAL void mouse_microsoft_internal IPT4
|
|
(
|
|
word *, m1,
|
|
word *, m2,
|
|
word *, m3,
|
|
word *, m4
|
|
); /* FUNC 46 */
|
|
|
|
LOCAL void mouse_hardware_reset IPT4
|
|
(
|
|
word *, status_ptr,
|
|
word *, m2,
|
|
word *, m3,
|
|
word *, m4
|
|
); /* FUNC 47 */
|
|
|
|
LOCAL void mouse_set_get_ballpoint_info IPT4
|
|
(
|
|
word *, status_ptr,
|
|
word *, rotation_angle_ptr,
|
|
word *, button_mask_ptr,
|
|
word *, m4
|
|
); /* FUNC 48 */
|
|
|
|
LOCAL void mouse_get_min_max_virtual_coords IPT4
|
|
(
|
|
MOUSE_SCALAR *, min_x_ptr,
|
|
MOUSE_SCALAR *, min_y_ptr,
|
|
MOUSE_SCALAR *, max_x_ptr,
|
|
MOUSE_SCALAR *, max_y_ptr
|
|
); /* FUNC 49 */
|
|
|
|
LOCAL void mouse_get_active_advanced_functions IPT4
|
|
(
|
|
word *, active_flag1_ptr,
|
|
word *, active_flag2_ptr,
|
|
word *, active_flag3_ptr,
|
|
word *, active_flag4_ptr
|
|
); /* FUNC 50 */
|
|
|
|
LOCAL void mouse_get_switch_settings IPT4
|
|
(
|
|
word *, status_ptr,
|
|
word *, m2,
|
|
word *, buffer_length_ptr,
|
|
word *, offset_ptr
|
|
); /* FUNC 51 */
|
|
|
|
LOCAL void mouse_get_mouse_ini IPT4
|
|
(
|
|
word *, status_ptr,
|
|
word *, m2,
|
|
word *, m3,
|
|
word *, offset_ptr
|
|
); /* FUNC 52 */
|
|
|
|
LOCAL void do_mouse_function IPT4(word *,m1,word *,m2,word *,m3,word *,m4);
|
|
|
|
LOCAL void load_acceleration_curve IPT3
|
|
(
|
|
word, seg,
|
|
word, off,
|
|
ACCELERATION_CURVE_DATA *, hcurve
|
|
);
|
|
|
|
LOCAL void store_acceleration_curve IPT3
|
|
(
|
|
word, seg,
|
|
word, off,
|
|
ACCELERATION_CURVE_DATA *, hcurve
|
|
);
|
|
|
|
LOCAL void mouse_EM_move IPT0();
|
|
|
|
LOCAL void mouse_update IPT1(MOUSE_CALL_MASK, event_mask);
|
|
|
|
LOCAL void cursor_undisplay IPT0();
|
|
|
|
LOCAL void cursor_mode_change IPT1(int,new_mode);
|
|
|
|
LOCAL void inport_get_event IPT1(MOUSE_INPORT_DATA *,event);
|
|
|
|
LOCAL void cursor_update IPT0();
|
|
|
|
LOCAL void jump_to_user_subroutine IPT3(MOUSE_CALL_MASK,condition_mask,word,segment,word,offset);
|
|
|
|
LOCAL void cursor_display IPT0();
|
|
|
|
LOCAL void inport_reset IPT0();
|
|
|
|
GLOBAL void software_text_cursor_display IPT0();
|
|
|
|
GLOBAL void software_text_cursor_undisplay IPT0();
|
|
|
|
GLOBAL void hardware_text_cursor_display IPT0();
|
|
|
|
GLOBAL void hardware_text_cursor_undisplay IPT0();
|
|
|
|
LOCAL void graphics_cursor_display IPT0();
|
|
|
|
LOCAL void graphics_cursor_undisplay IPT0();
|
|
|
|
LOCAL void get_screen_size IPT0();
|
|
|
|
LOCAL void clean_all_regs IPT0();
|
|
|
|
LOCAL void dirty_all_regs IPT0();
|
|
|
|
LOCAL void copy_default_graphics_cursor IPT0();
|
|
|
|
#ifdef EGG
|
|
LOCAL VOID VGA_graphics_cursor_display IPT0();
|
|
LOCAL VOID VGA_graphics_cursor_undisplay IPT0();
|
|
LOCAL EGA_graphics_cursor_undisplay IPT0();
|
|
LOCAL EGA_graphics_cursor_display IPT0();
|
|
#endif
|
|
|
|
#ifdef HERC
|
|
LOCAL void HERC_graphics_cursor_display IPT0();
|
|
LOCAL void HERC_graphics_cursor_undisplay IPT0();
|
|
#endif /* HERC */
|
|
|
|
void (*mouse_int1_action) IPT0();
|
|
void (*mouse_int2_action) IPT0();
|
|
|
|
|
|
/* jump table */
|
|
SAVED void (*mouse_function[MOUSE_FUNCTION_MAXIMUM])() =
|
|
{
|
|
/* 0 */ mouse_reset,
|
|
/* 1 */ mouse_show_cursor,
|
|
/* 2 */ mouse_hide_cursor,
|
|
/* 3 */ mouse_get_position,
|
|
/* 4 */ mouse_set_position,
|
|
/* 5 */ mouse_get_press,
|
|
/* 6 */ mouse_get_release,
|
|
/* 7 */ mouse_set_range_x,
|
|
/* 8 */ mouse_set_range_y,
|
|
/* 9 */ mouse_set_graphics,
|
|
/* 10 */ mouse_set_text,
|
|
/* 11 */ mouse_read_motion,
|
|
/* 12 */ mouse_set_subroutine,
|
|
/* 13 */ mouse_light_pen_on,
|
|
/* 14 */ mouse_light_pen_off,
|
|
/* 15 */ mouse_set_ratio,
|
|
/* 16 */ mouse_conditional_off,
|
|
/* 17 */ mouse_unrecognised,
|
|
/* 18 */ mouse_unrecognised,
|
|
/* 19 */ mouse_set_double_speed,
|
|
/* 20 */ mouse_get_and_set_subroutine,
|
|
/* 21 */ mouse_get_state_size,
|
|
/* 22 */ mouse_save_state,
|
|
/* 23 */ mouse_restore_state,
|
|
/* 24 */ mouse_set_alt_subroutine,
|
|
/* 25 */ mouse_get_alt_subroutine,
|
|
/* 26 */ mouse_set_sensitivity,
|
|
/* 27 */ mouse_get_sensitivity,
|
|
/* 28 */ mouse_set_int_rate,
|
|
/* 29 */ mouse_set_pointer_page,
|
|
/* 30 */ mouse_get_pointer_page,
|
|
/* 31 */ mouse_driver_disable,
|
|
/* 32 */ mouse_driver_enable,
|
|
/* 33 */ mouse_reset,
|
|
/* 34 */ mouse_set_language,
|
|
/* 35 */ mouse_get_language,
|
|
/* 36 */ mouse_get_info,
|
|
/* 37 */ mouse_get_driver_info,
|
|
/* 38 */ mouse_get_max_coords,
|
|
/* 39 */ mouse_get_masks_and_mickeys,
|
|
/* 40 */ mouse_set_video_mode,
|
|
/* 41 */ mouse_enumerate_video_modes,
|
|
/* 42 */ mouse_get_cursor_hot_spot,
|
|
/* 43 */ mouse_load_acceleration_curves,
|
|
/* 44 */ mouse_read_acceleration_curves,
|
|
/* 45 */ mouse_set_get_active_acceleration_curve,
|
|
/* 46 */ mouse_microsoft_internal,
|
|
/* 47 */ mouse_hardware_reset,
|
|
/* 48 */ mouse_set_get_ballpoint_info,
|
|
/* 49 */ mouse_get_min_max_virtual_coords,
|
|
/* 50 */ mouse_get_active_advanced_functions,
|
|
/* 51 */ mouse_get_switch_settings,
|
|
/* 52 */ mouse_get_mouse_ini,
|
|
};
|
|
|
|
|
|
/*
|
|
* Mickey to Pixel Ratio Declarations
|
|
*/
|
|
|
|
/* NB all mouse gears are scaled by MOUSE_RATIO_SCALE_FACTOR */
|
|
LOCAL MOUSE_VECTOR mouse_gear_default =
|
|
{
|
|
MOUSE_RATIO_X_DEFAULT,
|
|
MOUSE_RATIO_Y_DEFAULT
|
|
};
|
|
|
|
/*
|
|
* Sensitivity declarations
|
|
*/
|
|
|
|
#define mouse_sens_calc_val(sens) \
|
|
/* This macro converts a sensitivity request (1-100) to a multiplier value */ \
|
|
( \
|
|
(sens < MOUSE_SENS_DEF) ? \
|
|
((IS32)MOUSE_SENS_MIN_VAL + ( ((IS32)sens - (IS32)MOUSE_SENS_MIN)*(IS32)MOUSE_SENS_MULT * \
|
|
((IS32)MOUSE_SENS_DEF_VAL - (IS32)MOUSE_SENS_MIN_VAL) / \
|
|
((IS32)MOUSE_SENS_DEF - (IS32)MOUSE_SENS_MIN) ) ) \
|
|
: \
|
|
((IS32)MOUSE_SENS_DEF_VAL + ( ((IS32)sens - (IS32)MOUSE_SENS_DEF)*(IS32)MOUSE_SENS_MULT * \
|
|
((IS32)MOUSE_SENS_MAX_VAL - (IS32)MOUSE_SENS_DEF_VAL) / \
|
|
((IS32)MOUSE_SENS_MAX - (IS32)MOUSE_SENS_DEF) ) ) \
|
|
)
|
|
|
|
/*
|
|
* Text Cursor Declarations
|
|
*/
|
|
|
|
LOCAL MOUSE_SOFTWARE_TEXT_CURSOR software_text_cursor_default =
|
|
{
|
|
MOUSE_TEXT_SCREEN_MASK_DEFAULT,
|
|
MOUSE_TEXT_CURSOR_MASK_DEFAULT
|
|
};
|
|
|
|
/*
|
|
* Graphics Cursor Declarations
|
|
*/
|
|
LOCAL MOUSE_GRAPHICS_CURSOR graphics_cursor_default =
|
|
{
|
|
{
|
|
MOUSE_GRAPHICS_HOT_SPOT_X_DEFAULT,
|
|
MOUSE_GRAPHICS_HOT_SPOT_Y_DEFAULT
|
|
},
|
|
{
|
|
MOUSE_GRAPHICS_CURSOR_WIDTH,
|
|
MOUSE_GRAPHICS_CURSOR_DEPTH
|
|
},
|
|
MOUSE_GRAPHICS_SCREEN_MASK_DEFAULT,
|
|
MOUSE_GRAPHICS_CURSOR_MASK_DEFAULT
|
|
};
|
|
|
|
/* grid the cursor must lie on */
|
|
LOCAL MOUSE_VECTOR cursor_grids[MOUSE_VIDEO_MODE_MAXIMUM] =
|
|
{
|
|
{ 16, 8 }, /* mode 0 */
|
|
{ 16, 8 }, /* mode 1 */
|
|
{ 8, 8 }, /* mode 2 */
|
|
{ 8, 8 }, /* mode 3 */
|
|
{ 2, 1 }, /* mode 4 */
|
|
{ 2, 1 }, /* mode 5 */
|
|
{ 1, 1 }, /* mode 6 */
|
|
{ 8, 8 }, /* mode 7 */
|
|
#ifdef EGG
|
|
{ 0, 0 }, /* mode 8, not on EGA */
|
|
{ 0, 0 }, /* mode 9, not on EGA */
|
|
{ 0, 0 }, /* mode A, not on EGA */
|
|
{ 0, 0 }, /* mode B, not on EGA */
|
|
{ 0, 0 }, /* mode C, not on EGA */
|
|
{ 2, 1 }, /* mode D */
|
|
{ 1, 1 }, /* mode E */
|
|
{ 1, 1 }, /* mode F */
|
|
{ 1, 1 }, /* mode 10 */
|
|
#endif
|
|
#ifdef VGG
|
|
{ 1, 1 }, /* mode 11 */
|
|
{ 1, 1 }, /* mode 12 */
|
|
{ 2, 1 }, /* mode 13 */
|
|
#endif
|
|
};
|
|
#ifdef V7VGA
|
|
LOCAL MOUSE_VECTOR v7text_cursor_grids[6] =
|
|
{
|
|
{ 8, 8 }, /* mode 40 */
|
|
{ 8, 14 }, /* mode 41 */
|
|
{ 8, 8 }, /* mode 42 */
|
|
{ 8, 8 }, /* mode 43 */
|
|
{ 8, 8 }, /* mode 44 */
|
|
{ 8, 14 }, /* mode 45 */
|
|
};
|
|
LOCAL MOUSE_VECTOR v7graph_cursor_grids[10] =
|
|
{
|
|
{ 1, 1 }, /* mode 60 */
|
|
{ 1, 1 }, /* mode 61 */
|
|
{ 1, 1 }, /* mode 62 */
|
|
{ 1, 1 }, /* mode 63 */
|
|
{ 1, 1 }, /* mode 64 */
|
|
{ 1, 1 }, /* mode 65 */
|
|
{ 1, 1 }, /* mode 66 */
|
|
{ 1, 1 }, /* mode 67 */
|
|
{ 1, 1 }, /* mode 68 */
|
|
{ 1, 1 }, /* mode 69 */
|
|
};
|
|
#endif /* V7VGA */
|
|
|
|
/* grid for light pen response */
|
|
LOCAL MOUSE_VECTOR text_grids[MOUSE_VIDEO_MODE_MAXIMUM] =
|
|
{
|
|
{ 16, 8 }, /* mode 0 */
|
|
{ 16, 8 }, /* mode 1 */
|
|
{ 8, 8 }, /* mode 2 */
|
|
{ 8, 8 }, /* mode 3 */
|
|
{ 16, 8 }, /* mode 4 */
|
|
{ 16, 8 }, /* mode 5 */
|
|
{ 8, 8 }, /* mode 6 */
|
|
{ 8, 8 }, /* mode 7 */
|
|
#ifdef EGG
|
|
{ 0, 0 }, /* mode 8, not on EGA */
|
|
{ 0, 0 }, /* mode 9, not on EGA */
|
|
{ 0, 0 }, /* mode A, not on EGA */
|
|
{ 0, 0 }, /* mode B, not on EGA */
|
|
{ 0, 0 }, /* mode C, not on EGA */
|
|
{ 8, 8 }, /* mode D */
|
|
{ 8, 8 }, /* mode E */
|
|
{ 8, 14 }, /* mode F */
|
|
{ 8, 14 }, /* mode 10 */
|
|
#endif
|
|
#ifdef VGG
|
|
{ 8, 8 }, /* mode 11 */
|
|
{ 8, 8 }, /* mode 12 */
|
|
{ 8, 16 }, /* mode 13 */
|
|
#endif
|
|
};
|
|
#ifdef V7VGA
|
|
LOCAL MOUSE_VECTOR v7text_text_grids[6] =
|
|
{
|
|
{ 8, 8 }, /* mode 40 */
|
|
{ 8, 14 }, /* mode 41 */
|
|
{ 8, 8 }, /* mode 42 */
|
|
{ 8, 8 }, /* mode 43 */
|
|
{ 8, 8 }, /* mode 44 */
|
|
{ 8, 14 }, /* mode 45 */
|
|
};
|
|
LOCAL MOUSE_VECTOR v7graph_text_grids[10] =
|
|
{
|
|
{ 8, 8 }, /* mode 60 */
|
|
{ 8, 8 }, /* mode 61 */
|
|
{ 8, 8 }, /* mode 62 */
|
|
{ 8, 8 }, /* mode 63 */
|
|
{ 8, 8 }, /* mode 64 */
|
|
{ 8, 8 }, /* mode 65 */
|
|
{ 8, 16 }, /* mode 66 */
|
|
{ 8, 16 }, /* mode 67 */
|
|
{ 8, 8 }, /* mode 68 */
|
|
{ 8, 8 }, /* mode 69 */
|
|
};
|
|
#endif /* V7VGA */
|
|
|
|
/* Default acceleration curve */
|
|
LOCAL ACCELERATION_CURVE_DATA default_acceleration_curve =
|
|
{
|
|
/* length */
|
|
{ 1, 8, 12, 16 },
|
|
/* mickey counts */
|
|
{{ 1, 127, 127, 127, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127},
|
|
{ 1, 5, 9, 13, 17, 21, 25, 29,
|
|
127, 127, 127, 127, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127},
|
|
{ 1, 4, 7, 10, 13, 16, 19, 22,
|
|
25, 28, 31, 34, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127},
|
|
{ 1, 3, 5, 7, 9, 11, 13, 15,
|
|
17, 19, 21, 23, 25, 27, 29, 31,
|
|
127, 127, 127, 127, 127, 127, 127, 127,
|
|
127, 127, 127, 127, 127, 127, 127, 127}},
|
|
/* scale factors */
|
|
{{ 16, 16, 16, 16, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16},
|
|
{ 16, 20, 24, 28, 32, 36, 40, 44,
|
|
16, 16, 16, 16, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16},
|
|
{ 16, 20, 24, 28, 32, 36, 40, 44,
|
|
48, 52, 56, 60, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16},
|
|
{ 16, 20, 24, 28, 32, 36, 40, 44,
|
|
48, 52, 56, 60, 64, 68, 72, 76,
|
|
16, 16, 16, 16, 16, 16, 16, 16,
|
|
16, 16, 16, 16, 16, 16, 16, 16}},
|
|
/* names */
|
|
{{'V', 'a', 'n', 'i', 'l', 'l', 'a', 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0},
|
|
{'S', 'l', 'o', 'w', 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0},
|
|
{'N', 'o', 'r', 'm', 'a', 'l', 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0},
|
|
{'F', 'a', 's', 't', 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0}},
|
|
};
|
|
|
|
/* used to get current video page size */
|
|
#define video_page_size() (sas_w_at(VID_LEN))
|
|
|
|
/* check if page requested is valid */
|
|
#define is_valid_page_number(pg) ((pg) < vd_mode_table[sas_hw_at(vd_video_mode)].npages)
|
|
|
|
/*
|
|
* Mouse Driver Version
|
|
*/
|
|
|
|
LOCAL half_word mouse_emulated_release = 0x08;
|
|
LOCAL half_word mouse_emulated_version = 0x00;
|
|
LOCAL half_word mouse_io_rev; /* Filled in from SCCS ID */
|
|
LOCAL half_word mouse_com_rev; /* Passed in from MOUSE.COM */
|
|
|
|
LOCAL char *mouse_id = "%s Mouse %d.01 installed\015\012";
|
|
LOCAL char *mouse_installed = "%s Mouse %d.01 already installed\015\012";
|
|
|
|
/*
|
|
* Context save stuff
|
|
*/
|
|
/* magic cookie for saved context */
|
|
LOCAL char mouse_context_magic[] = "ISMMC"; /* Insignia Solutions Mouse Magic Cookie */
|
|
#define MOUSE_CONTEXT_MAGIC_SIZE 5
|
|
#define MOUSE_CONTEXT_CHECKSUM_SIZE 1
|
|
|
|
/* size of our context (in bytes) */
|
|
#define mouse_context_size (MOUSE_CONTEXT_MAGIC_SIZE + sizeof(MOUSE_CONTEXT) + \
|
|
MOUSE_CONTEXT_CHECKSUM_SIZE)
|
|
|
|
|
|
LOCAL half_word mouse_interrupt_rate;
|
|
|
|
|
|
/*
|
|
Handle to data instanced for each Virtual Machine.
|
|
*/
|
|
MM_INSTANCE_DATA_HANDLE mm_handle;
|
|
|
|
static initial_mouse_screen_mask[MOUSE_GRAPHICS_CURSOR_DEPTH] =
|
|
MOUSE_GRAPHICS_SCREEN_MASK_DEFAULT;
|
|
|
|
static initial_mouse_cursor_mask[MOUSE_GRAPHICS_CURSOR_DEPTH] =
|
|
MOUSE_GRAPHICS_CURSOR_MASK_DEFAULT;
|
|
|
|
/* Initialisation and Termination Procedures */
|
|
GLOBAL void mouse_driver_initialisation IFN0()
|
|
{
|
|
int i;
|
|
|
|
/* Set up instance memory */
|
|
mm_handle = (MM_INSTANCE_DATA_HANDLE)NIDDB_Allocate_Instance_Data(
|
|
sizeof(MM_INSTANCE_DATA),
|
|
(NIDDB_CR_CALLBACK)0,
|
|
(NIDDB_TM_CALLBACK)0);
|
|
|
|
if ( mm_handle == (MM_INSTANCE_DATA_HANDLE)0 )
|
|
{
|
|
host_error(EG_OWNUP, ERR_QUIT,
|
|
"mouse_io: NIDDB_Allocate_Instance_Data() failed.");
|
|
}
|
|
|
|
/* TMM: belt and braces fix, some variables don't get set to zero when perhaps they should */
|
|
host_memset ((*mm_handle), sizeof(MM_INSTANCE_DATA), 0);
|
|
|
|
/* Initialise Variables */
|
|
for ( i = 0; i < MOUSE_BUTTON_MAXIMUM; i++)
|
|
{
|
|
button_transitions[i].press_position.x = 0;
|
|
button_transitions[i].press_position.y = 0;
|
|
button_transitions[i].release_position.x = 0;
|
|
button_transitions[i].release_position.y = 0;
|
|
button_transitions[i].press_count = 0;
|
|
button_transitions[i].release_count = 0;
|
|
}
|
|
|
|
mouse_gear.x = MOUSE_RATIO_X_DEFAULT;
|
|
mouse_gear.y = MOUSE_RATIO_Y_DEFAULT;
|
|
|
|
mouse_sens.x = MOUSE_SENS_DEF;
|
|
mouse_sens.y = MOUSE_SENS_DEF;
|
|
|
|
mouse_sens_val.x = MOUSE_SENS_DEF_VAL;
|
|
mouse_sens_val.y = MOUSE_SENS_DEF_VAL;
|
|
|
|
mouse_double_thresh = MOUSE_DOUBLE_DEF;
|
|
text_cursor_type = MOUSE_TEXT_CURSOR_TYPE_SOFTWARE;
|
|
|
|
software_text_cursor.screen = MOUSE_TEXT_SCREEN_MASK_DEFAULT;
|
|
software_text_cursor.cursor = MOUSE_TEXT_CURSOR_MASK_DEFAULT;
|
|
|
|
graphics_cursor.hot_spot.x = MOUSE_GRAPHICS_HOT_SPOT_X_DEFAULT;
|
|
graphics_cursor.hot_spot.y = MOUSE_GRAPHICS_HOT_SPOT_Y_DEFAULT;
|
|
graphics_cursor.size.x = MOUSE_GRAPHICS_CURSOR_WIDTH;
|
|
graphics_cursor.size.y = MOUSE_GRAPHICS_CURSOR_DEPTH;
|
|
|
|
for (i = 0; i < MOUSE_GRAPHICS_CURSOR_DEPTH; i++)
|
|
{
|
|
graphics_cursor.screen[i] = initial_mouse_screen_mask[i];
|
|
graphics_cursor.cursor[i] = initial_mouse_cursor_mask[i];
|
|
}
|
|
|
|
user_subroutine_segment = 0;
|
|
user_subroutine_offset = 0;
|
|
user_subroutine_call_mask = 0;
|
|
|
|
/* TMM: Flag the alternative user subroutines as not initialised */
|
|
alt_user_subroutines_active = FALSE;
|
|
for (i = 0; i < NUMBER_ALT_SUBROUTINES; i++)
|
|
{
|
|
alt_user_subroutine_segment [i] = 0;
|
|
alt_user_subroutine_offset [i]= 0;
|
|
alt_user_subroutine_call_mask [i] = 0;
|
|
}
|
|
|
|
black_hole.top_left.x = -MOUSE_VIRTUAL_SCREEN_WIDTH;
|
|
black_hole.top_left.y = -MOUSE_VIRTUAL_SCREEN_DEPTH;
|
|
black_hole.bottom_right.x = -MOUSE_VIRTUAL_SCREEN_WIDTH;
|
|
black_hole.bottom_right.y = -MOUSE_VIRTUAL_SCREEN_DEPTH;
|
|
|
|
double_speed_threshold = MOUSE_DOUBLE_SPEED_THRESHOLD_DEFAULT;
|
|
cursor_flag = MOUSE_CURSOR_DEFAULT;
|
|
|
|
cursor_status.position.x = MOUSE_VIRTUAL_SCREEN_WIDTH / 2;
|
|
cursor_status.position.y = MOUSE_VIRTUAL_SCREEN_DEPTH / 2;
|
|
cursor_status.button_status = 0;
|
|
|
|
cursor_window.top_left.x = cursor_window.top_left.y = 0;
|
|
cursor_window.bottom_right.x = cursor_window.bottom_right.y = 0;
|
|
|
|
light_pen_mode = TRUE;
|
|
|
|
mouse_motion.x = 0;
|
|
mouse_motion.y = 0;
|
|
mouse_raw_motion.x = 0;
|
|
mouse_raw_motion.y = 0;
|
|
|
|
/* Reset to default curve */
|
|
active_acceleration_curve = 3; /* Back to Normal */
|
|
|
|
memcpy(&acceleration_curve_data, &default_acceleration_curve,
|
|
sizeof(ACCELERATION_CURVE_DATA));
|
|
|
|
next_video_mode = 0; /* reset video mode enumeration */
|
|
|
|
point_set(&cursor_position_default, MOUSE_VIRTUAL_SCREEN_WIDTH / 2,
|
|
MOUSE_VIRTUAL_SCREEN_DEPTH / 2);
|
|
|
|
point_set(&cursor_position, MOUSE_VIRTUAL_SCREEN_WIDTH / 2,
|
|
MOUSE_VIRTUAL_SCREEN_DEPTH / 2);
|
|
|
|
point_set(&cursor_fractional_position, 0, 0);
|
|
cursor_page = 0;
|
|
|
|
mouse_driver_disabled = FALSE;
|
|
text_cursor_background = 0;
|
|
|
|
for ( i = 0; i < MOUSE_GRAPHICS_CURSOR_DEPTH; i++)
|
|
graphics_cursor_background[i] = 0;
|
|
|
|
save_area_in_use = FALSE;
|
|
point_set(&save_position, 0, 0);
|
|
|
|
save_area.top_left.x = save_area.top_left.y = 0;
|
|
save_area.bottom_right.x = save_area.bottom_right.y = 0;
|
|
|
|
user_subroutine_critical = FALSE;
|
|
last_condition_mask = 0;
|
|
|
|
virtual_screen.top_left.x = MOUSE_VIRTUAL_SCREEN_ORIGIN_X;
|
|
virtual_screen.top_left.y = MOUSE_VIRTUAL_SCREEN_ORIGIN_Y;
|
|
virtual_screen.bottom_right.x = MOUSE_VIRTUAL_SCREEN_WIDTH;
|
|
virtual_screen.bottom_right.y = MOUSE_VIRTUAL_SCREEN_DEPTH;
|
|
|
|
cursor_grid.x = 8;
|
|
cursor_grid.y = 8;
|
|
|
|
text_grid.x = 8;
|
|
text_grid.y = 8;
|
|
|
|
black_hole_default.top_left.x = -MOUSE_VIRTUAL_SCREEN_WIDTH;
|
|
black_hole_default.top_left.y = -MOUSE_VIRTUAL_SCREEN_DEPTH;
|
|
black_hole_default.bottom_right.x = -MOUSE_VIRTUAL_SCREEN_WIDTH;
|
|
black_hole_default.bottom_right.y = -MOUSE_VIRTUAL_SCREEN_DEPTH;
|
|
|
|
#ifdef HERC
|
|
HERC_graphics_virtual_screen.top_left.x = 0;
|
|
HERC_graphics_virtual_screen.top_left.y = 0;
|
|
HERC_graphics_virtual_screen.bottom_right.x = 720;
|
|
HERC_graphics_virtual_screen.bottom_right.y = 350;
|
|
#endif /* HERC */
|
|
|
|
cursor_EM_disabled = FALSE;
|
|
}
|
|
|
|
GLOBAL void mouse_driver_termination IFN0()
|
|
{
|
|
/* Just free up instance memory */
|
|
NIDDB_Deallocate_Instance_Data((IHP *)mm_handle);
|
|
}
|
|
|
|
/*
|
|
* MOUSE DRIVER EXTERNAL FUNCTIONS
|
|
* ===============================
|
|
*/
|
|
|
|
/*
|
|
* Macro to produce an interrupt table location from an interrupt number
|
|
*/
|
|
|
|
#define int_addr(int_no) (int_no * 4)
|
|
|
|
void mouse_install1()
|
|
{
|
|
|
|
/*
|
|
* This function is called from the Mouse Driver program to
|
|
* install the Insignia Mouse Driver. The interrupt vector
|
|
* table is patched to divert all the mouse driver interrupts
|
|
*/
|
|
word junk1, junk2, junk3, junk4;
|
|
word hook_offset;
|
|
half_word interrupt_mask_register;
|
|
char temp[128];
|
|
#ifdef NTVDM
|
|
word o,s;
|
|
sys_addr block_offset;
|
|
#endif
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_install1:");
|
|
|
|
#ifdef MONITOR
|
|
/*
|
|
* Get addresses of stuff usually in ROM from driver
|
|
* To minimise changes, MOUSE... tokens are now variables and
|
|
* not defines.
|
|
*/
|
|
|
|
block_offset = effective_addr(getCS(), getBX());
|
|
|
|
sas_loadw(block_offset, &MOUSE_IO_INTERRUPT_OFFSET);
|
|
sas_loadw(block_offset+2, &MOUSE_IO_INTERRUPT_SEGMENT);
|
|
sas_loadw(block_offset+4, &MOUSE_VIDEO_IO_OFFSET);
|
|
sas_loadw(block_offset+6, &MOUSE_VIDEO_IO_SEGMENT);
|
|
sas_loadw(block_offset+8, &MOUSE_INT1_OFFSET);
|
|
sas_loadw(block_offset+10, &MOUSE_INT1_SEGMENT);
|
|
sas_loadw(block_offset+12, &MOUSE_VERSION_OFFSET);
|
|
sas_loadw(block_offset+14, &MOUSE_VERSION_SEGMENT);
|
|
sas_loadw(block_offset+16, &MOUSE_COPYRIGHT_OFFSET);
|
|
sas_loadw(block_offset+18, &MOUSE_COPYRIGHT_SEGMENT);
|
|
sas_loadw(block_offset+20, &VIDEO_IO_RE_ENTRY);
|
|
sas_loadw(block_offset+22, &VIDEO_IO_SEGMENT);
|
|
sas_loadw(block_offset+24, &MOUSE_INT2_OFFSET);
|
|
sas_loadw(block_offset+26, &MOUSE_INT2_SEGMENT);
|
|
sas_loadw(block_offset+28, &DRAW_FS_POINTER_OFFSET);
|
|
sas_loadw(block_offset+30, &DRAW_FS_POINTER_SEGMENT);
|
|
sas_loadw(block_offset+32, &F0_OFFSET);
|
|
sas_loadw(block_offset+34, &F0_SEGMENT);
|
|
sas_loadw(block_offset+36, &POINTER_ON_OFFSET);
|
|
sas_loadw(block_offset+38, &POINTER_ON_SEGMENT);
|
|
sas_loadw(block_offset+40, &POINTER_OFF_OFFSET);
|
|
sas_loadw(block_offset+42, &POINTER_OFF_SEGMENT);
|
|
sas_loadw(block_offset+44, &F9_OFFSET);
|
|
sas_loadw(block_offset+46, &F9_SEGMENT);
|
|
sas_loadw(block_offset+48, &CP_X_O);
|
|
sas_loadw(block_offset+50, &CP_X_S);
|
|
sas_loadw(block_offset+52, &CP_Y_O);
|
|
sas_loadw(block_offset+54, &CP_Y_S);
|
|
sas_loadw(block_offset+56, &mouseINBoffset);
|
|
sas_loadw(block_offset+58, &mouseINBsegment);
|
|
sas_loadw(block_offset+60, &mouseOUTBoffset);
|
|
sas_loadw(block_offset+62, &mouseOUTBsegment);
|
|
sas_loadw(block_offset+64, &mouseOUTWoffset);
|
|
sas_loadw(block_offset+66, &mouseOUTWsegment);
|
|
sas_loadw(block_offset+68, &savedtextoffset);
|
|
sas_loadw(block_offset+70, &savedtextsegment);
|
|
sas_loadw(block_offset+72, &o);
|
|
sas_loadw(block_offset+74, &s);
|
|
sas_loadw(block_offset+76, &button_off);
|
|
sas_loadw(block_offset+78, &button_seg);
|
|
|
|
mouseCFsysaddr = effective_addr(s,o);
|
|
sas_loadw(block_offset+80, &o);
|
|
sas_loadw(block_offset+82, &s);
|
|
conditional_off_sysaddr = effective_addr(s, o);
|
|
|
|
#endif /* MONITOR */
|
|
/*
|
|
* Make sure that old save area does not get re-painted!
|
|
*/
|
|
save_area_in_use = FALSE;
|
|
|
|
/*
|
|
* Get rev of MOUSE.COM
|
|
*/
|
|
mouse_com_rev = getAL();
|
|
|
|
/*
|
|
* Bus mouse hardware interrupt
|
|
*/
|
|
#ifdef NTVDM
|
|
sas_loadw (int_addr(0x71) + 0, &saved_int71_offset);
|
|
sas_loadw (int_addr(0x71) + 2, &saved_int71_segment);
|
|
sas_storew(int_addr(0x71), MOUSE_INT1_OFFSET);
|
|
sas_storew(int_addr(0x71) + 2, MOUSE_INT1_SEGMENT);
|
|
#else
|
|
sas_loadw (int_addr(MOUSE_VEC) + 0, &saved_int0A_offset);
|
|
sas_loadw (int_addr(MOUSE_VEC) + 2, &saved_int0A_segment);
|
|
sas_storew(int_addr(MOUSE_VEC), MOUSE_INT1_OFFSET);
|
|
sas_storew(int_addr(MOUSE_VEC) + 2, MOUSE_INT1_SEGMENT);
|
|
|
|
#endif NTVDM
|
|
|
|
/*
|
|
* Enable mouse hardware interrupts in the ica
|
|
*/
|
|
inb(ICA1_PORT_1, &interrupt_mask_register);
|
|
interrupt_mask_register &= ~(1 << AT_CPU_MOUSE_INT);
|
|
outb(ICA1_PORT_1, interrupt_mask_register);
|
|
inb(ICA0_PORT_1, &interrupt_mask_register);
|
|
interrupt_mask_register &= ~(1 << CPU_MOUSE_INT);
|
|
outb(ICA0_PORT_1, interrupt_mask_register);
|
|
|
|
/*
|
|
* Mouse io user interrupt
|
|
*/
|
|
|
|
sas_loadw (int_addr(0x33) + 0, &saved_int33_offset);
|
|
sas_loadw (int_addr(0x33) + 2, &saved_int33_segment);
|
|
|
|
#ifdef NTVDM
|
|
sas_storew(int_addr(0x33), MOUSE_IO_INTERRUPT_OFFSET);
|
|
sas_storew(int_addr(0x33) + 2, MOUSE_IO_INTERRUPT_SEGMENT);
|
|
#else
|
|
/* Read offset of INT 33 procedure from MOUSE.COM */
|
|
sas_loadw(effective_addr(getCS(), OFF_HOOK_POSN), &hook_offset);
|
|
|
|
sas_storew(int_addr(0x33), hook_offset);
|
|
sas_storew(int_addr(0x33) + 2, getCS());
|
|
#endif /* NTVDM */
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
/*
|
|
* Call 16-bit mouse driver initialisation routine
|
|
*/
|
|
mouse16bInstall( );
|
|
#endif
|
|
|
|
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX))
|
|
/*
|
|
* Mouse video io user interrupt
|
|
*/
|
|
sas_loadw (int_addr(0x10) + 0, &saved_int10_offset);
|
|
sas_loadw (int_addr(0x10) + 2, &saved_int10_segment);
|
|
/*
|
|
Determine if the current int10h vector points to
|
|
our roms. If it points elsewhere then the vector has
|
|
been hooked and we must call the current int10h handler
|
|
at the end of mouse_video_io().
|
|
*/
|
|
int10_chained = TRUE;
|
|
#ifdef EGG
|
|
if(video_adapter == EGA || video_adapter == VGA)
|
|
{
|
|
if ((saved_int10_segment == EGA_SEG) &&
|
|
(saved_int10_offset == EGA_ENTRY_OFF))
|
|
int10_chained = FALSE;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if ((saved_int10_segment == VIDEO_IO_SEGMENT) &&
|
|
(saved_int10_offset == VIDEO_IO_OFFSET))
|
|
int10_chained = FALSE;
|
|
}
|
|
#ifndef MOUSE_16_BIT
|
|
sas_storew(int_addr(0x10), MOUSE_VIDEO_IO_OFFSET);
|
|
sas_storew(int_addr(0x10) + 2, MOUSE_VIDEO_IO_SEGMENT);
|
|
#else /* MOUSE_16_BIT */
|
|
sas_storedw(int_addr(0x10), mouseIOData.mouse_video_io );
|
|
#endif /* MOUSE_16_BIT */
|
|
|
|
#else
|
|
int10_chained = FALSE; // make it initialized
|
|
#endif /* if NTVDM && !X86GFX */
|
|
|
|
/*
|
|
* Reset mouse hardware and software
|
|
*/
|
|
junk1 = MOUSE_RESET;
|
|
mouse_reset(&junk1, &junk2, &junk3, &junk4);
|
|
|
|
/*
|
|
* Display mouse driver identification string
|
|
*/
|
|
#ifdef NTVDM
|
|
clear_string();
|
|
#endif
|
|
sprintf (temp, mouse_id, SPC_Product_Name, mouse_com_rev);
|
|
#ifdef NTVDM
|
|
display_string(temp);
|
|
#endif
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_install1:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
void mouse_install2()
|
|
{
|
|
/*
|
|
* This function is called from the Mouse Driver program to
|
|
* print a message saying that an existing mouse driver
|
|
* program is already installed
|
|
*/
|
|
char temp[128];
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_install2:");
|
|
|
|
/*
|
|
* Make sure that old save area does not get re-painted!
|
|
*/
|
|
save_area_in_use = FALSE;
|
|
|
|
/*
|
|
* Display mouse driver identification string
|
|
*/
|
|
#ifdef NTVDM
|
|
clear_string();
|
|
#endif
|
|
sprintf (temp, mouse_installed, SPC_Product_Name, mouse_com_rev);
|
|
#ifdef NTVDM
|
|
display_string(temp);
|
|
#endif
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_install2:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
void mouse_io_interrupt()
|
|
{
|
|
/*
|
|
* This is the entry point for mouse access via the INT 33H
|
|
* interface. I/O tracing is provided in each mouse function
|
|
*/
|
|
word local_AX, local_BX, local_CX, local_DX;
|
|
|
|
#ifdef NTVDM
|
|
if(stream_io_enabled) {
|
|
disable_stream_io();
|
|
}
|
|
#endif /* NTVDM */
|
|
|
|
/*
|
|
* Get the parameters
|
|
*/
|
|
local_AX = getAX();
|
|
local_BX = getBX();
|
|
local_CX = getCX();
|
|
local_DX = getDX();
|
|
|
|
#ifdef EGG
|
|
jap_mouse = ((sas_hw_at(vd_video_mode) != Currently_emulated_video_mode) && alpha_num_mode());
|
|
if (jap_mouse)
|
|
note_trace0(MOUSE_VERBOSE, "In Japanese mode - will emulate textmouse");
|
|
#endif /* EGG */
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse function %d, position is %d,%d, button state is %d",
|
|
local_AX, cursor_status.position.x,
|
|
cursor_status.position.y, cursor_status.button_status);
|
|
|
|
/*
|
|
* Do what you have to do
|
|
*/
|
|
do_mouse_function(&local_AX, &local_BX, &local_CX, &local_DX);
|
|
|
|
/*
|
|
* Set the parameters
|
|
*/
|
|
setAX(local_AX);
|
|
setBX(local_BX);
|
|
setCX(local_CX);
|
|
setDX(local_DX);
|
|
}
|
|
|
|
|
|
|
|
|
|
void mouse_io_language()
|
|
{
|
|
/*
|
|
* This is the entry point for mouse access via a language.
|
|
* I/O tracing is provided in each mouse function
|
|
*/
|
|
word local_SI = getSI(), local_DI = getDI();
|
|
word m1, m2, m3, m4;
|
|
word offset, data;
|
|
sys_addr stack_addr = effective_addr(getSS(), getSP());
|
|
|
|
/*
|
|
* Retrieve parameters from the caller's stack
|
|
*/
|
|
sas_loadw(stack_addr+10, &offset);
|
|
sas_loadw(effective_addr(getDS(), offset), &m1);
|
|
|
|
sas_loadw(stack_addr+8, &offset);
|
|
sas_loadw(effective_addr(getDS(), offset), &m2);
|
|
|
|
sas_loadw(stack_addr+6, &offset);
|
|
sas_loadw(effective_addr(getDS(), offset), &m3);
|
|
|
|
switch(m1)
|
|
{
|
|
case MOUSE_SET_GRAPHICS:
|
|
case MOUSE_SET_SUBROUTINE:
|
|
/*
|
|
* The fourth parameter is used directly as the offset
|
|
*/
|
|
sas_loadw(stack_addr+4, &m4);
|
|
break;
|
|
case MOUSE_CONDITIONAL_OFF:
|
|
/*
|
|
* The fourth parameter addresses a parameter block
|
|
* that contains the data
|
|
*/
|
|
sas_loadw(stack_addr+4, &offset);
|
|
sas_loadw(effective_addr(getDS(), offset), &m3);
|
|
sas_loadw(effective_addr(getDS(), offset+2), &m4);
|
|
sas_loadw(effective_addr(getDS(), offset+4), &data);
|
|
setSI(data);
|
|
sas_loadw(effective_addr(getDS(), offset+6), &data);
|
|
setDI(data);
|
|
break;
|
|
default:
|
|
/*
|
|
* The fourth parameter addresses the data to be used
|
|
*/
|
|
sas_loadw(stack_addr+4, &offset);
|
|
sas_loadw(effective_addr(getDS(), offset), &m4);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Do what you have to do
|
|
*/
|
|
do_mouse_function(&m1, &m2, &m3, &m4);
|
|
|
|
/*
|
|
* Store results back on the stack
|
|
*/
|
|
sas_loadw(stack_addr+10, &offset);
|
|
sas_storew(effective_addr(getDS(), offset), m1);
|
|
|
|
sas_loadw(stack_addr+8, &offset);
|
|
sas_storew(effective_addr(getDS(), offset), m2);
|
|
|
|
sas_loadw(stack_addr+6, &offset);
|
|
sas_storew(effective_addr(getDS(), offset), m3);
|
|
|
|
sas_loadw(stack_addr+4, &offset);
|
|
sas_storew(effective_addr(getDS(), offset), m4);
|
|
|
|
/*
|
|
* Restore potentially corrupted registers
|
|
*/
|
|
setSI(local_SI);
|
|
setDI(local_DI);
|
|
}
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
/*
|
|
* function : mouse16bCheckConditionalOff
|
|
*
|
|
* purpose : Make the 16 bit driver check the conditional
|
|
* off area and either draw or hide the pointer
|
|
* appropriately. This function is only called
|
|
* when the cursor flag is set to
|
|
* MOUSE_CURSOR_DISPLAYED.
|
|
*
|
|
* inputs : none
|
|
* outputs : none
|
|
* returns : void
|
|
* globals : cursor_flag is decremented if the pointer has
|
|
* to be hidden
|
|
*
|
|
*
|
|
*/
|
|
LOCAL void mouse16bCheckConditionalOff IFN0()
|
|
{
|
|
/* If the mouse has moved into the conditional
|
|
** off area (the black hole) then the mouse
|
|
** must be hidden and the cursor flag
|
|
** decremented, otherwise the mouse is drawn
|
|
** in its new position.
|
|
*/
|
|
if ((cursor_position.x >=
|
|
black_hole.top_left.x) &&
|
|
(cursor_position.x <=
|
|
black_hole.bottom_right.x) &&
|
|
(cursor_position.y >=
|
|
black_hole.top_left.y) &&
|
|
(cursor_position.y <=
|
|
black_hole.bottom_right.y))
|
|
{
|
|
cursor_flag--;
|
|
mouse16bHidePointer();
|
|
}
|
|
else
|
|
mouse16bDrawPointer( &cursor_status );
|
|
}
|
|
#endif /* MOUSE_16_BIT */
|
|
|
|
LOCAL void get_screen_size IFN0()
|
|
{
|
|
#ifdef HERC
|
|
if (video_adapter == HERCULES){
|
|
if (get_cga_mode() == GRAPHICS){
|
|
virtual_screen.bottom_right.x = 720;
|
|
virtual_screen.bottom_right.y = 348;
|
|
}else{
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 348;
|
|
}
|
|
return;
|
|
}
|
|
#endif /* HERC */
|
|
switch(current_video_mode)
|
|
{
|
|
/*==================================================================
|
|
ACW 17/3/93 Some code added to return a different virtual
|
|
coordinate size for the screen if text mode is used NOT in 25 line
|
|
mode. This really emulates the Microsoft Mouse Driver.
|
|
Note: There are 8 x 8 virtual pixels in any character cell.
|
|
==================================================================*/
|
|
case 0x2:
|
|
case 0x3:
|
|
case 0x7:
|
|
{
|
|
half_word no_of_lines;
|
|
|
|
sas_load(0x484, &no_of_lines); /* do a look up in BIOS */
|
|
no_of_lines &= 0xff; /* clean up */
|
|
switch(no_of_lines)
|
|
{
|
|
case 24:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 200;
|
|
break;
|
|
case 42:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 344;
|
|
break;
|
|
case 49:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 400;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
/*==================================================================
|
|
End of ACW code
|
|
==================================================================*/
|
|
case 0xf:
|
|
case 0x10:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 350;
|
|
break;
|
|
case 0x40:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 344;
|
|
break;
|
|
case 0x41:
|
|
virtual_screen.bottom_right.x = 1056;
|
|
virtual_screen.bottom_right.y = 350;
|
|
break;
|
|
case 0x42:
|
|
virtual_screen.bottom_right.x = 1056;
|
|
virtual_screen.bottom_right.y = 344;
|
|
break;
|
|
case 0x45:
|
|
virtual_screen.bottom_right.x = 1056;
|
|
virtual_screen.bottom_right.y = 392;
|
|
break;
|
|
case 0x66:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 400;
|
|
break;
|
|
case 0x11:
|
|
case 0x12:
|
|
case 0x43:
|
|
case 0x67:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 480;
|
|
break;
|
|
case 0x44:
|
|
virtual_screen.bottom_right.x = 800;
|
|
virtual_screen.bottom_right.y = 480;
|
|
break;
|
|
case 0x60:
|
|
virtual_screen.bottom_right.x = 752;
|
|
virtual_screen.bottom_right.y = 410;
|
|
break;
|
|
case 0x61:
|
|
case 0x68:
|
|
virtual_screen.bottom_right.x = 720;
|
|
virtual_screen.bottom_right.y = 540;
|
|
break;
|
|
case 0x62:
|
|
case 0x69:
|
|
virtual_screen.bottom_right.x = 800;
|
|
virtual_screen.bottom_right.y = 600;
|
|
break;
|
|
case 0x63:
|
|
case 0x64:
|
|
case 0x65:
|
|
virtual_screen.bottom_right.x = 1024;
|
|
virtual_screen.bottom_right.y = 768;
|
|
break;
|
|
default:
|
|
virtual_screen.bottom_right.x = 640;
|
|
virtual_screen.bottom_right.y = 200;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#ifdef EGG
|
|
|
|
/*
|
|
* Utility routine to restore EGA defaults to the saved values.
|
|
* If to_hw == TRUE, the restored values are also sent to the EGA.
|
|
*/
|
|
|
|
|
|
LOCAL boolean dirty_crtc[EGA_PARMS_CRTC_SIZE], dirty_seq[EGA_PARMS_SEQ_SIZE],
|
|
dirty_graph[EGA_PARMS_GRAPH_SIZE], dirty_attr[EGA_PARMS_ATTR_SIZE];
|
|
|
|
LOCAL void clean_all_regs()
|
|
{
|
|
int i;
|
|
|
|
for(i=0;i<EGA_PARMS_CRTC_SIZE;i++)
|
|
dirty_crtc[i] = 0;
|
|
for(i=0;i<EGA_PARMS_SEQ_SIZE;i++)
|
|
dirty_seq[i] = 0;
|
|
for(i=0;i<EGA_PARMS_GRAPH_SIZE;i++)
|
|
dirty_graph[i] = 0;
|
|
for(i=0;i<EGA_PARMS_ATTR_SIZE;i++)
|
|
dirty_attr[i] = 0;
|
|
}
|
|
|
|
LOCAL void dirty_all_regs()
|
|
{
|
|
int i;
|
|
|
|
for(i=0;i<EGA_PARMS_CRTC_SIZE;i++)
|
|
dirty_crtc[i] = 1;
|
|
for(i=0;i<EGA_PARMS_SEQ_SIZE;i++)
|
|
dirty_seq[i] = 1;
|
|
for(i=0;i<EGA_PARMS_GRAPH_SIZE;i++)
|
|
dirty_graph[i] = 1;
|
|
for(i=0;i<EGA_PARMS_ATTR_SIZE;i++)
|
|
dirty_attr[i] = 1;
|
|
}
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
|
|
#define inb(a,b) doINB(a,b)
|
|
#undef OUTB
|
|
#define OUTB(a,b) doOUTB(a,b)
|
|
#define outw(a,b) doOUTW(a,b)
|
|
|
|
static void doINB IFN2(word, port, byte, *value)
|
|
{
|
|
word savedIP=getIP(), savedCS=getCS();
|
|
word savedAX=getAX(), savedDX=getDX();
|
|
|
|
setDX(port);
|
|
setCS(mouseINBsegment);
|
|
setIP(mouseINBoffset);
|
|
host_simulate();
|
|
setCS(savedCS);
|
|
setIP(savedIP);
|
|
*value=getAL();
|
|
setAX(savedAX);
|
|
setDX(savedDX);
|
|
}
|
|
|
|
static void doOUTB IFN2(word, port, byte, value)
|
|
{
|
|
word savedIP=getIP(), savedCS=getCS();
|
|
word savedAX=getAX(), savedDX=getDX();
|
|
|
|
setDX(port);
|
|
setAL(value);
|
|
setCS(mouseOUTBsegment);
|
|
setIP(mouseOUTBoffset);
|
|
host_simulate();
|
|
setCS(savedCS);
|
|
setIP(savedIP);
|
|
setAX(savedAX);
|
|
setDX(savedDX);
|
|
}
|
|
|
|
static void doOUTW IFN2(word, port, word, value)
|
|
{
|
|
word savedIP=getIP(), savedCS=getCS();
|
|
word savedAX=getAX(), savedDX=getDX();
|
|
|
|
setDX(port);
|
|
setAX(value);
|
|
setCS(mouseOUTWsegment);
|
|
setIP(mouseOUTWoffset);
|
|
host_simulate();
|
|
setCS(savedCS);
|
|
setIP(savedIP);
|
|
setAX(savedAX);
|
|
setDX(savedDX);
|
|
}
|
|
|
|
#endif /* NTVDM && MONITOR */
|
|
|
|
LOCAL void restore_ega_defaults(to_hw)
|
|
boolean to_hw;
|
|
{
|
|
int i;
|
|
half_word temp_word;
|
|
|
|
sas_loads(ega_default_crtc,ega_current_crtc,EGA_PARMS_CRTC_SIZE);
|
|
sas_loads(ega_default_seq,ega_current_seq,EGA_PARMS_SEQ_SIZE);
|
|
sas_loads(ega_default_graph,ega_current_graph,EGA_PARMS_GRAPH_SIZE);
|
|
sas_loads(ega_default_attr,ega_current_attr,EGA_PARMS_ATTR_SIZE);
|
|
|
|
ega_current_misc = sas_hw_at_no_check(ega_default_misc);
|
|
|
|
if(to_hw)
|
|
{
|
|
/* setup Sequencer */
|
|
|
|
OUTB( EGA_SEQ_INDEX, 0x0 );
|
|
OUTB( EGA_SEQ_INDEX + 1, 0x1 );
|
|
|
|
for(i=0;i<EGA_PARMS_SEQ_SIZE;i++)
|
|
{
|
|
if (dirty_seq[i])
|
|
{
|
|
OUTB( EGA_SEQ_INDEX,(half_word)i+1);
|
|
OUTB( EGA_SEQ_INDEX + 1, sas_hw_at_no_check( ega_default_seq + i ));
|
|
}
|
|
}
|
|
|
|
OUTB( EGA_SEQ_INDEX, 0x0 );
|
|
OUTB( EGA_SEQ_INDEX + 1, 0x3 );
|
|
|
|
/* setup Miscellaneous register */
|
|
|
|
OUTB( EGA_MISC_REG, sas_hw_at_no_check( ega_default_misc ));
|
|
|
|
/* setup CRTC */
|
|
|
|
for(i=0;i<EGA_PARMS_CRTC_SIZE;i++)
|
|
{
|
|
if (dirty_crtc[i])
|
|
{
|
|
OUTB(EGA_CRTC_INDEX,(half_word)i);
|
|
OUTB( EGA_CRTC_INDEX + 1, sas_hw_at_no_check( ega_default_crtc + i ));
|
|
}
|
|
}
|
|
|
|
/* setup attribute chip - NB need to do an inb() to clear the address */
|
|
|
|
inb(EGA_IPSTAT1_REG,&temp_word);
|
|
|
|
for(i=0;i<EGA_PARMS_ATTR_SIZE;i++)
|
|
{
|
|
if (dirty_attr[i])
|
|
{
|
|
OUTB( EGA_AC_INDEX_DATA, i );
|
|
OUTB( EGA_AC_INDEX_DATA, sas_hw_at_no_check( ega_default_attr + i ));
|
|
}
|
|
}
|
|
|
|
/* setup graphics chips */
|
|
|
|
for(i=0;i<EGA_PARMS_GRAPH_SIZE;i++)
|
|
{
|
|
if (dirty_graph[i])
|
|
{
|
|
OUTB( EGA_GC_INDEX, i );
|
|
OUTB( EGA_GC_INDEX + 1, sas_hw_at_no_check( ega_default_graph + i ));
|
|
}
|
|
}
|
|
|
|
OUTB( EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE ); /* re-enable video */
|
|
clean_all_regs();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LOCAL mouse_adjust_screen_size()
|
|
{
|
|
/* Alter mouse variables which depend on mode */
|
|
IS32 old_depth = virtual_screen.bottom_right.y;
|
|
IS32 old_width = virtual_screen.bottom_right.x;
|
|
|
|
/*
|
|
Height & width of screen in pixels is variable with EGA/(V7)VGA.
|
|
|
|
Theoretically, punters can invent their own modes which would
|
|
confuse the issue. However most of SoftPC seems to rely on people
|
|
using standard BIOS modes only, with standard screen heights &
|
|
widths.
|
|
*/
|
|
|
|
get_screen_size();
|
|
|
|
/* Reinitialise things that depend on screen height & width. */
|
|
|
|
cursor_position_default.x = virtual_screen.bottom_right.x / 2;
|
|
cursor_position_default.y = virtual_screen.bottom_right.y / 2;
|
|
|
|
cursor_position.x = (MOUSE_SCALAR)(((IS32)cursor_position.x *
|
|
(IS32)virtual_screen.bottom_right.x) / old_width);
|
|
cursor_position.y = (MOUSE_SCALAR)(((IS32)cursor_position.y *
|
|
(IS32)virtual_screen.bottom_right.y) / old_depth);
|
|
|
|
black_hole.top_left.x = -virtual_screen.bottom_right.x;
|
|
black_hole.top_left.y = -virtual_screen.bottom_right.y;
|
|
|
|
black_hole_default.top_left.x = -virtual_screen.bottom_right.x;
|
|
black_hole_default.top_left.y = -virtual_screen.bottom_right.y;
|
|
|
|
black_hole.bottom_right.x = -virtual_screen.bottom_right.x;
|
|
black_hole.bottom_right.y = -virtual_screen.bottom_right.y;
|
|
|
|
black_hole_default.bottom_right.x = -virtual_screen.bottom_right.x;
|
|
black_hole_default.bottom_right.y = -virtual_screen.bottom_right.y;
|
|
}
|
|
|
|
#if defined(NTVDM) && !defined(X86GFX)
|
|
GLOBAL void mouse_video_mode_changed(int new_mode)
|
|
{
|
|
IMPORT word VirtualX, VirtualY;
|
|
|
|
current_video_mode = new_mode & 0x7F;
|
|
mouse_ega_mode(current_video_mode);
|
|
VirtualX = virtual_screen.bottom_right.x;
|
|
VirtualY = virtual_screen.bottom_right.y;
|
|
}
|
|
#endif
|
|
|
|
GLOBAL mouse_ega_mode(curr_video_mode)
|
|
int curr_video_mode;
|
|
{
|
|
sys_addr parms_addr; /* Address of EGA register table for video mode */
|
|
sys_addr temp_word; /* Bit of storage to pass to inb() */
|
|
|
|
UNUSED(curr_video_mode);
|
|
|
|
mouse_adjust_screen_size();
|
|
|
|
if(video_adapter == EGA || video_adapter == VGA)
|
|
{
|
|
#ifdef NTVDM
|
|
parms_addr = find_mode_table(current_video_mode,&temp_word);
|
|
#else
|
|
#ifdef V7VGA /* suret */
|
|
if( (getAH()) == 0x6F )
|
|
parms_addr = find_mode_table(getBL(),&temp_word);
|
|
else
|
|
parms_addr = find_mode_table(getAL(),&temp_word);
|
|
#else
|
|
parms_addr = find_mode_table(getAL(),&temp_word);
|
|
#endif
|
|
#endif /* NTVDM */
|
|
ega_default_crtc = parms_addr + EGA_PARMS_CRTC;
|
|
ega_default_seq = parms_addr + EGA_PARMS_SEQ;
|
|
ega_default_graph = parms_addr + EGA_PARMS_GRAPH;
|
|
ega_default_attr = parms_addr + EGA_PARMS_ATTR;
|
|
ega_default_misc = parms_addr + EGA_PARMS_MISC;
|
|
restore_ega_defaults(FALSE); /* Load up current tables, but don't write to EGA!! */
|
|
}
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
sas_store(conditional_off_sysaddr, 0);
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
void mouse_video_io()
|
|
{
|
|
/*
|
|
* This is the entry point for video accesses via the INT 10H
|
|
* interface
|
|
*/
|
|
#ifdef EGG
|
|
half_word temp_word; /* Bit of storage to pass to inb() */
|
|
#endif /* EGG */
|
|
IS32 mouse_video_function = getAH();
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
extern void host_call_bios_mode_change();
|
|
#endif
|
|
|
|
#ifdef V7VGA
|
|
if (mouse_video_function == MOUSE_VIDEO_SET_MODE || getAX() == MOUSE_V7_VIDEO_SET_MODE)
|
|
#else
|
|
if (mouse_video_function == MOUSE_VIDEO_SET_MODE)
|
|
#endif /* V7VGA */
|
|
{
|
|
note_trace1(MOUSE_VERBOSE, "mouse_video_io:set_mode(%d)",
|
|
getAL());
|
|
|
|
|
|
current_video_mode = getAL() & 0x7f;
|
|
#ifdef V7VGA
|
|
if (mouse_video_function == 0x6f)
|
|
current_video_mode = getBL() & 0x7f;
|
|
else if (current_video_mode > 0x13)
|
|
current_video_mode += 0x4c;
|
|
|
|
if (is_bad_vid_mode(current_video_mode) && !is_v7vga_mode(current_video_mode))
|
|
#else
|
|
if (is_bad_vid_mode(current_video_mode))
|
|
#endif /* V7VGA */
|
|
{
|
|
always_trace1("Bad video mode - %d.\n", current_video_mode);
|
|
#ifdef V7VGA
|
|
if (mouse_video_function == 0x6f)
|
|
setAH( 0x02 ); /* suret */
|
|
#endif /* V7VGA */
|
|
return;
|
|
}
|
|
|
|
#ifdef EGG
|
|
mouse_ega_mode(current_video_mode);
|
|
dirty_all_regs();
|
|
#endif
|
|
/*
|
|
* Remove the old cursor from the screen, and hide
|
|
* the cursor
|
|
*/
|
|
cursor_undisplay();
|
|
|
|
cursor_flag = MOUSE_CURSOR_DEFAULT;
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
sas_store(mouseCFsysaddr,(half_word)MOUSE_CURSOR_DEFAULT);
|
|
#endif
|
|
/*
|
|
* Deal with the mode change
|
|
*/
|
|
cursor_mode_change(current_video_mode);
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
host_call_bios_mode_change();
|
|
#endif
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
/* Remember whether in text or graphics mode for
|
|
** later use.
|
|
*/
|
|
is_graphics_mode = ((current_video_mode > 3) &&
|
|
(current_video_mode != 7));
|
|
#endif /* MOUSE_16_BIT */
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_video_io:return()");
|
|
}
|
|
else if ( (mouse_video_function == MOUSE_VIDEO_READ_LIGHT_PEN)
|
|
&& light_pen_mode)
|
|
{
|
|
note_trace0(MOUSE_VERBOSE, "mouse_video_io:read_light_pen()");
|
|
|
|
/*
|
|
* Set text row and column of "light pen" position
|
|
*/
|
|
setDL(cursor_status.position.x/text_grid.x);
|
|
setDH(cursor_status.position.y/text_grid.y);
|
|
|
|
/*
|
|
* Set pixel column and raster line of "light pen"
|
|
* position
|
|
*/
|
|
setBX(cursor_status.position.x/cursor_grid.x);
|
|
if (sas_hw_at(vd_video_mode)>= 0x04 && sas_hw_at(vd_video_mode)<=0x06){
|
|
setCH(cursor_status.position.y);
|
|
}else if (sas_hw_at(vd_video_mode)>= 0x0D && sas_hw_at(vd_video_mode)<=0x13){
|
|
setCX(cursor_status.position.y);
|
|
}
|
|
|
|
/*
|
|
* Set the button status
|
|
*/
|
|
setAH(cursor_status.button_status);
|
|
|
|
note_trace5(MOUSE_VERBOSE,
|
|
"mouse_video_io:return(st=%d,ca=[%d,%d],pa=[%d,%d])",
|
|
getAH(), getDL(), getDH(), getBX(), cursor_status.position.y);
|
|
return;
|
|
}
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
else if (mouse_video_function == MOUSE_VIDEO_LOAD_FONT)
|
|
{
|
|
note_trace0(MOUSE_VERBOSE, "mouse_video_io:load_font()");
|
|
|
|
/*
|
|
* Call the host to tell it to adjust the mouse buffer selected
|
|
* if the number of lines on the screen have changed.
|
|
*/
|
|
host_check_mouse_buffer();
|
|
}
|
|
#endif /* NTVDM && MONITOR */
|
|
|
|
/*
|
|
* Now do the standard video io processing
|
|
*/
|
|
switch (mouse_video_function)
|
|
{
|
|
#ifdef EGG
|
|
/* Fancy stuff to access EGA registers */
|
|
case 0xf0: /* Read a register */
|
|
switch (getDX())
|
|
{
|
|
case 0:
|
|
setBL(ega_current_crtc[getBL()]);
|
|
break;
|
|
case 8:
|
|
setBL(ega_current_seq[getBL()-1]);
|
|
break;
|
|
case 0x10:
|
|
setBL(ega_current_graph[getBL()]);
|
|
break;
|
|
case 0x18:
|
|
setBL(ega_current_attr[getBL()]);
|
|
break;
|
|
case 0x20:
|
|
setBL(ega_current_misc);
|
|
break;
|
|
case 0x28:
|
|
break;
|
|
/* Graphics Position registers not supported. */
|
|
case 0x30:
|
|
case 0x38:
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 0xf1: /* Write a register */
|
|
switch (getDX())
|
|
{
|
|
case 0:
|
|
outw( EGA_CRTC_INDEX, getBX() );
|
|
ega_current_crtc[getBL()] = getBH();
|
|
dirty_crtc[getBL()] = 1;
|
|
break;
|
|
case 8:
|
|
outw( EGA_SEQ_INDEX, getBX() );
|
|
if(getBL()>0)
|
|
{
|
|
ega_current_seq[getBL()-1] = getBH();
|
|
dirty_seq[getBL()-1] = 1;
|
|
}
|
|
break;
|
|
case 0x10:
|
|
outw( EGA_GC_INDEX, getBX() );
|
|
ega_current_graph[getBL()] = getBH();
|
|
dirty_graph[getBL()] = 1;
|
|
break;
|
|
case 0x18:
|
|
inb(EGA_IPSTAT1_REG,&temp_word); /* Clear attrib. index */
|
|
|
|
/* outw( EGA_AC_INDEX_DATA, getBX() ); this is not correct (andyw BCN 1692) */
|
|
|
|
/*=============================================================================
|
|
The attribute controller index register and data register associated
|
|
with that index are accessed through the same I/O port = 03C0h.
|
|
The correct procedure is to map the index register to 03C0h by doing
|
|
the INB as above. Then OUTB the index of the A.C. register required.
|
|
The VGA hardware then maps in the correct data register to which
|
|
the application OUTBs the necessary data.
|
|
=============================================================================*/
|
|
OUTB( EGA_AC_INDEX_DATA, getBL() ); /* BL contains the index value */
|
|
OUTB( EGA_AC_INDEX_DATA, getBH() ); /* BH contains the data */
|
|
|
|
/*=== End of BCN 1692 ===*/
|
|
OUTB( EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE ); /* re-enable video */
|
|
ega_current_attr[getBL()] = getBH();
|
|
dirty_attr[getBL()] = 1;
|
|
break;
|
|
case 0x20:
|
|
OUTB( EGA_MISC_REG, getBL() );
|
|
ega_current_misc = getBL();
|
|
break;
|
|
case 0x28:
|
|
OUTB( EGA_FEAT_REG, getBL() );
|
|
break;
|
|
/* Graphics Position registers not supported. */
|
|
case 0x30:
|
|
case 0x38:
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 0xf2: /* read range */
|
|
switch (getDX())
|
|
{
|
|
case 0:
|
|
sas_stores(effective_addr(getES(),getBX()),&ega_current_crtc[getCH()],getCL());
|
|
break;
|
|
case 8:
|
|
sas_stores(effective_addr(getES(),getBX()),&ega_current_seq[getCH()-1],getCL());
|
|
break;
|
|
case 0x10:
|
|
sas_stores(effective_addr(getES(),getBX()),&ega_current_graph[getCH()],getCL());
|
|
break;
|
|
case 0x18:
|
|
sas_stores(effective_addr(getES(),getBX()),&ega_current_attr[getCH()],getCL());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case 0xf3: /* write range */
|
|
{
|
|
int first = getCH(), last = getCH()+getCL();
|
|
sys_addr sauce = effective_addr(getES(),getBX());
|
|
switch (getDX())
|
|
{
|
|
case 0:
|
|
sas_loads(sauce,&ega_current_crtc[getCH()],getCL());
|
|
for(;first<last;first++)
|
|
{
|
|
dirty_crtc[first] = 1;
|
|
outw(EGA_CRTC_INDEX,first+(sas_hw_at(sauce++) << 8));
|
|
}
|
|
break;
|
|
case 8:
|
|
sas_loads(sauce,&ega_current_seq[getCH()-1],getCL());
|
|
for(;first<last;first++)
|
|
{
|
|
dirty_seq[first+1] = 1;
|
|
outw(EGA_SEQ_INDEX,first+1+(sas_hw_at(sauce++) << 8));
|
|
}
|
|
break;
|
|
case 0x10:
|
|
sas_loads(sauce,&ega_current_graph[getCH()],getCL());
|
|
for(;first<last;first++)
|
|
{
|
|
dirty_graph[first] = 1;
|
|
outw(EGA_GC_INDEX,first+(sas_hw_at(sauce++) << 8));
|
|
}
|
|
break;
|
|
case 0x18:
|
|
sas_loads(sauce,&ega_current_attr[getCH()],getCL());
|
|
inb(EGA_IPSTAT1_REG,&temp_word); /* Clear attrib. index */
|
|
for(;first<last;first++)
|
|
{
|
|
dirty_attr[first] = 1;
|
|
|
|
/* Using 'secret' that attrib. chip responds to it's port+1 */
|
|
#ifndef NTVDM
|
|
outw(EGA_AC_INDEX_DATA,first+(sas_hw_at(sauce++) << 8));
|
|
#else
|
|
OUTB(EGA_AC_INDEX_DATA,first);
|
|
OUTB(EGA_AC_INDEX_DATA,sas_hw_at(sauce++));
|
|
#endif /* !NTVDM */
|
|
}
|
|
#ifndef NTVDM
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
|
|
#else
|
|
OUTB(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
|
|
#endif /* NTVDM */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 0xf4: /* read set */
|
|
{
|
|
int i = getCX();
|
|
sys_addr set_def = effective_addr(getES(),getBX());
|
|
while(i--)
|
|
{
|
|
switch (sas_hw_at(set_def))
|
|
{
|
|
case 0:
|
|
sas_store((set_def+3), ega_current_crtc[sas_hw_at(set_def+2)]);
|
|
break;
|
|
case 8:
|
|
sas_store((set_def+3), ega_current_seq[sas_hw_at(set_def+2)-1]);
|
|
break;
|
|
case 0x10:
|
|
sas_store((set_def+3), ega_current_graph[sas_hw_at(set_def+2)]);
|
|
break;
|
|
case 0x18:
|
|
sas_store((set_def+3), ega_current_attr[sas_hw_at(set_def+2)]);
|
|
break;
|
|
case 0x20:
|
|
sas_store((set_def+3), ega_current_misc);
|
|
setBL(ega_current_misc);
|
|
break;
|
|
case 0x28:
|
|
/* Graphics Position registers not supported. */
|
|
case 0x30:
|
|
case 0x38:
|
|
default:
|
|
break;
|
|
}
|
|
set_def += 4;
|
|
}
|
|
}
|
|
break;
|
|
case 0xf5: /* write set */
|
|
{
|
|
int i = getCX();
|
|
sys_addr set_def = effective_addr(getES(),getBX());
|
|
while(i--)
|
|
{
|
|
switch (sas_hw_at(set_def))
|
|
{
|
|
case 0:
|
|
outw(EGA_CRTC_INDEX,sas_hw_at(set_def+2)+(sas_hw_at(set_def+3)<<8));
|
|
ega_current_crtc[sas_hw_at(set_def+2)] = sas_hw_at(set_def+3);
|
|
dirty_crtc[sas_hw_at(set_def+2)] = 1;
|
|
break;
|
|
case 8:
|
|
outw(EGA_SEQ_INDEX,sas_hw_at(set_def+2)+(sas_hw_at(set_def+3)<<8));
|
|
if(sas_hw_at(set_def+2))
|
|
ega_current_seq[sas_hw_at(set_def+2)-1] = sas_hw_at(set_def+3);
|
|
dirty_seq[sas_hw_at(set_def+2)-1] = 1;
|
|
break;
|
|
case 0x10:
|
|
outw(EGA_GC_INDEX,sas_hw_at(set_def+2)+(sas_hw_at(set_def+3)<<8));
|
|
ega_current_graph[sas_hw_at(set_def+2)] = sas_hw_at(set_def+3);
|
|
dirty_graph[sas_hw_at(set_def+2)] = 1;
|
|
break;
|
|
case 0x18:
|
|
inb(EGA_IPSTAT1_REG,&temp_word); /* Clear attrib. index */
|
|
#ifndef NTVDM
|
|
outw(EGA_AC_INDEX_DATA,sas_hw_at(set_def+2)+(sas_hw_at(set_def+3)<<8)); /* Using 'secret' that attrib. chip responds to it's port+1 */
|
|
outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
|
|
#else
|
|
|
|
OUTB( EGA_AC_INDEX_DATA,sas_hw_at(set_def+2));
|
|
OUTB( EGA_AC_INDEX_DATA,sas_hw_at(set_def+3));
|
|
OUTB( EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE ); /* re-enable video */
|
|
#endif /* !NTVDM */
|
|
ega_current_attr[sas_hw_at(set_def+2)] = sas_hw_at(set_def+3);
|
|
dirty_attr[sas_hw_at(set_def+2)] = 1;
|
|
break;
|
|
case 0x20:
|
|
outb(EGA_MISC_REG,sas_hw_at(set_def+2));
|
|
ega_current_misc = sas_hw_at(set_def+2);
|
|
break;
|
|
case 0x28:
|
|
outb(EGA_FEAT_REG,sas_hw_at(set_def+2));
|
|
break;
|
|
/* Graphics Position registers not supported. */
|
|
case 0x30:
|
|
case 0x38:
|
|
default:
|
|
break;
|
|
}
|
|
set_def += 4;
|
|
}
|
|
}
|
|
break;
|
|
case 0xf6:
|
|
restore_ega_defaults(TRUE);
|
|
break;
|
|
case 0xf7:
|
|
dirty_all_regs();
|
|
switch (getDX())
|
|
{
|
|
case 0:
|
|
ega_default_crtc = effective_addr(getES(),getBX());
|
|
break;
|
|
case 8:
|
|
ega_default_seq = effective_addr(getES(),getBX());
|
|
break;
|
|
case 0x10:
|
|
ega_default_graph = effective_addr(getES(),getBX());
|
|
break;
|
|
case 0x18:
|
|
ega_default_attr = effective_addr(getES(),getBX());
|
|
break;
|
|
case 0x20:
|
|
ega_default_misc = effective_addr(getES(),getBX());
|
|
break;
|
|
case 0x28: /* Feature Reg not reallt supported */
|
|
break;
|
|
/* Graphics Position registers not supported. */
|
|
case 0x30:
|
|
case 0x38:
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
#endif
|
|
case 0xfa:
|
|
/*
|
|
* MS word on an EGA uses this call and needs BX != 0 to make its cursor work. Real MS mouse driver returns a pointer in ES:BX
|
|
* aimed at several bytes of unknown significance followed by a "This is Copyright 1984 Microsoft" message, which we don't have.
|
|
* This seems to work with MS word and MS Windows, presumably non MS applications wouldn't use it as it's not documented.
|
|
*
|
|
* We now have a wonderful document - "The Microsoft Mouse Driver", which tells us that ES:BX should
|
|
* point to the EGA Register Interface version number (2 bytes).
|
|
* If BX=0 this means "no mouse driver". So returning 1 seems OK for now. WJG.
|
|
*/
|
|
setBX(1);
|
|
break;
|
|
case 0x11:
|
|
/*
|
|
* If we are issuing a TEXT MODE CHARACTER GENERATOR then this will
|
|
* cause a mode set. Therefore we need to recalc the screen
|
|
* parameters subsequently as the screen size may differ!!
|
|
* this occurred in DOSSHELL.
|
|
*/
|
|
#if !defined(NTVDM) || !defined(MONITOR)
|
|
#ifdef EGG
|
|
if (video_adapter == EGA || video_adapter == VGA)
|
|
{
|
|
#ifdef GISP_SVGA
|
|
if( hostIsFullScreen( ) )
|
|
#endif /* GISP_SVGA */
|
|
ega_video_io();
|
|
if (!(getAL() & 0x20))
|
|
mouse_ega_mode(current_video_mode); /* only for text */
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef GISP_SVGA
|
|
if( hostIsFullScreen( ) )
|
|
#endif /* GISP_SVGA */
|
|
video_io();
|
|
#endif /* !NTVDM && !MONITOR */
|
|
break;
|
|
|
|
default:
|
|
#ifndef X86GFX
|
|
/* Does the previous int10h vector point to our roms ? */
|
|
if (int10_chained == FALSE)
|
|
{
|
|
/* Yes - call our video handler */
|
|
#ifndef GISP_SVGA
|
|
#ifdef EGG
|
|
if (video_adapter == EGA || video_adapter == VGA)
|
|
#ifdef GISP_SVGA
|
|
if( hostIsFullScreen( ) )
|
|
#endif /* GISP_SVGA */
|
|
ega_video_io();
|
|
else
|
|
#endif
|
|
#ifdef GISP_SVGA
|
|
if( hostIsFullScreen( ) )
|
|
#endif /* GISP_SVGA */
|
|
video_io();
|
|
#else /* GISP_SVGA */
|
|
/* Video bios chain done from 16 bit */
|
|
/* NULL */;
|
|
#endif /* GISP_SVGA */
|
|
}
|
|
else
|
|
{
|
|
/* No - chain the previous int10h handler */
|
|
setCS(saved_int10_segment);
|
|
setIP(saved_int10_offset);
|
|
}
|
|
#else
|
|
break;
|
|
#endif /* !X86GFX */
|
|
}
|
|
#ifdef GISP_SVGA
|
|
setCF( 1 );
|
|
#endif /* GISP_SVGA */
|
|
|
|
}
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
#undef inb
|
|
#undef OUTB
|
|
#undef outw
|
|
#endif /* NTVDM && MONITOR */
|
|
|
|
void mouse_EM_callback()
|
|
{
|
|
note_trace1(MOUSE_VERBOSE,
|
|
"Enhanced Mode Mouse-Support Callback Function(%x).", getAX());
|
|
|
|
/* Windows Enhanced Mode Mouse-Support Callback */
|
|
switch ( getAX() )
|
|
{
|
|
case 0x1: /* Mouse move/Button click */
|
|
mouse_EM_move();
|
|
break;
|
|
|
|
case 0x2: /* Disable Mouse Cursor Drawing */
|
|
if ( cursor_flag == MOUSE_CURSOR_DISPLAYED )
|
|
cursor_undisplay();
|
|
cursor_EM_disabled = TRUE;
|
|
break;
|
|
|
|
case 0x3: /* Enable Mouse Cursor Drawing */
|
|
cursor_EM_disabled = FALSE;
|
|
if ( cursor_flag == MOUSE_CURSOR_DISPLAYED )
|
|
cursor_display();
|
|
break;
|
|
|
|
default: /* Unknown == Unsupported */
|
|
break;
|
|
}
|
|
}
|
|
|
|
LOCAL void mouse_EM_move()
|
|
{
|
|
MOUSE_CALL_MASK event_mask;
|
|
MOUSE_STATE button_state;
|
|
MOUSE_SCALAR x_pixel;
|
|
MOUSE_SCALAR y_pixel;
|
|
MOUSE_VECTOR mouse_movement;
|
|
|
|
/* Pick up parameters. */
|
|
event_mask = getSI();
|
|
button_state = getDX();
|
|
x_pixel = getBX();
|
|
y_pixel = getCX();
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"Extended Interface: event mask(%x) button_state(%x) posn(%d,%d).",
|
|
event_mask, button_state, x_pixel, y_pixel);
|
|
|
|
/* Process mouse events. */
|
|
if ( event_mask & MOUSE_CALL_MASK_LEFT_RELEASE_BIT )
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_LEFT_BUTTON].release_position);
|
|
button_transitions[MOUSE_LEFT_BUTTON].release_count++;
|
|
}
|
|
|
|
if ( event_mask & MOUSE_CALL_MASK_LEFT_PRESS_BIT )
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_LEFT_BUTTON].press_position);
|
|
button_transitions[MOUSE_LEFT_BUTTON].press_count++;
|
|
}
|
|
|
|
if ( event_mask & MOUSE_CALL_MASK_RIGHT_RELEASE_BIT )
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_RIGHT_BUTTON].release_position);
|
|
button_transitions[MOUSE_RIGHT_BUTTON].release_count++;
|
|
}
|
|
|
|
if ( event_mask & MOUSE_CALL_MASK_RIGHT_PRESS_BIT )
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_RIGHT_BUTTON].press_position);
|
|
button_transitions[MOUSE_RIGHT_BUTTON].press_count++;
|
|
}
|
|
|
|
cursor_status.button_status = button_state;
|
|
|
|
/* Process any mouse movement. */
|
|
if ( event_mask & MOUSE_CALL_MASK_POSITION_BIT )
|
|
{
|
|
/* Calculate mickeys moved. */
|
|
point_set(&mouse_movement, x_pixel, y_pixel);
|
|
vector_multiply_by_vector(&mouse_movement, &mouse_gear);
|
|
|
|
/* Update micky count. */
|
|
point_translate(&mouse_motion, &mouse_movement);
|
|
|
|
/* Set up point in pixels, again. */
|
|
point_set(&mouse_movement, x_pixel, y_pixel);
|
|
|
|
/* Update raw pixel position, and go grid it. */
|
|
cursor_position.x = x_pixel;
|
|
cursor_position.y = y_pixel;
|
|
cursor_update();
|
|
}
|
|
|
|
/* Now handle user subroutine and/or display update. */
|
|
mouse_update(event_mask);
|
|
}
|
|
|
|
void mouse_int1()
|
|
{
|
|
/*
|
|
* The bus mouse hardware interrupt handler
|
|
*/
|
|
#ifndef NTVDM
|
|
MOUSE_VECTOR mouse_movement;
|
|
MOUSE_INPORT_DATA inport_event;
|
|
#else
|
|
MOUSE_VECTOR mouse_counter = { 0, 0 };
|
|
#endif
|
|
MOUSE_CALL_MASK condition_mask;
|
|
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_int1:");
|
|
|
|
#ifdef NTVDM
|
|
|
|
|
|
//
|
|
// Okay, lets forget that the InPort adapter ever existed!
|
|
//
|
|
|
|
cursor_status.button_status = 0;
|
|
condition_mask = 0;
|
|
|
|
//
|
|
// Get the mouse motion counters back from the host side of things.
|
|
// Note: The real mouse driver returns the mouse motion counter values
|
|
// to the application in two possible ways. First, if the app uses
|
|
// int 33h function 11, a counter displacement is returned since the
|
|
// last call to this function.
|
|
// If a user subroutine is installed, the motion counters are given
|
|
// to this callback in SI and DI.
|
|
//
|
|
|
|
host_os_mouse_pointer(&cursor_status,&condition_mask,&mouse_counter);
|
|
|
|
//
|
|
// If movement during the last mouse hardware interrupt has been recorded,
|
|
// update the mouse motion counters.
|
|
//
|
|
|
|
mouse_motion.x += mouse_counter.x;
|
|
mouse_motion.y += mouse_counter.y;
|
|
|
|
//
|
|
// Update the statistics for an int 33h function 5, if one
|
|
// should occur.
|
|
// Note: The cases can't be mixed, since only one can occur
|
|
// per hardware interrupt - after all each press or release
|
|
// causes a hw int.
|
|
//
|
|
|
|
switch(condition_mask & 0x1e) // look at bits 1,2,3 and 4.
|
|
{
|
|
case 0x2: //left button pressed
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_LEFT_BUTTON].press_position);
|
|
button_transitions[MOUSE_LEFT_BUTTON].press_count++;
|
|
}
|
|
break;
|
|
case 0x4: //left button released
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_LEFT_BUTTON].release_position);
|
|
button_transitions[MOUSE_LEFT_BUTTON].release_count++;
|
|
}
|
|
break;
|
|
case 0x8: //right button pressed
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_RIGHT_BUTTON].press_position);
|
|
button_transitions[MOUSE_RIGHT_BUTTON].press_count++;
|
|
}
|
|
break;
|
|
case 0x10: //right button released
|
|
{
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_RIGHT_BUTTON].release_position);
|
|
button_transitions[MOUSE_RIGHT_BUTTON].release_count++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/*==================================================================
|
|
|
|
The old fashioned stuff
|
|
|
|
==================================================================*/
|
|
|
|
#else /* use the SoftPC emulation */
|
|
/*
|
|
* Terminate the mouse hardware interrupt
|
|
*/
|
|
outb(ICA0_PORT_0, END_INTERRUPT);
|
|
|
|
/*
|
|
* Get the mouse InPort input event frame
|
|
*/
|
|
inport_get_event(&inport_event);
|
|
|
|
note_trace3(MOUSE_VERBOSE,
|
|
"mouse_int1:InPort status=0x%x,data1=%d,data2=%d",
|
|
inport_event.status,
|
|
inport_event.data_x, inport_event.data_y);
|
|
|
|
/*
|
|
* Update button status and transition information and fill in
|
|
* button bits in the event mask
|
|
*/
|
|
cursor_status.button_status = 0;
|
|
condition_mask = 0;
|
|
|
|
switch(inport_event.status & MOUSE_INPORT_STATUS_B1_TRANSITION_MASK)
|
|
{
|
|
case MOUSE_INPORT_STATUS_B1_RELEASED:
|
|
condition_mask |= MOUSE_CALL_MASK_LEFT_RELEASE_BIT;
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_LEFT_BUTTON].release_position);
|
|
button_transitions[MOUSE_LEFT_BUTTON].release_count++;
|
|
case MOUSE_INPORT_STATUS_B1_UP:
|
|
break;
|
|
|
|
case MOUSE_INPORT_STATUS_B1_PRESSED:
|
|
condition_mask |= MOUSE_CALL_MASK_LEFT_PRESS_BIT;
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_LEFT_BUTTON].press_position);
|
|
button_transitions[MOUSE_LEFT_BUTTON].press_count++;
|
|
case MOUSE_INPORT_STATUS_B1_DOWN:
|
|
cursor_status.button_status |= MOUSE_LEFT_BUTTON_DOWN_BIT;
|
|
break;
|
|
}
|
|
|
|
switch(inport_event.status & MOUSE_INPORT_STATUS_B3_TRANSITION_MASK)
|
|
{
|
|
case MOUSE_INPORT_STATUS_B3_RELEASED:
|
|
condition_mask |= MOUSE_CALL_MASK_RIGHT_RELEASE_BIT;
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_RIGHT_BUTTON].release_position);
|
|
button_transitions[MOUSE_RIGHT_BUTTON].release_count++;
|
|
case MOUSE_INPORT_STATUS_B3_UP:
|
|
break;
|
|
|
|
case MOUSE_INPORT_STATUS_B3_PRESSED:
|
|
condition_mask |= MOUSE_CALL_MASK_RIGHT_PRESS_BIT;
|
|
point_copy(&cursor_status.position,
|
|
&button_transitions[MOUSE_RIGHT_BUTTON].press_position);
|
|
button_transitions[MOUSE_RIGHT_BUTTON].press_count++;
|
|
case MOUSE_INPORT_STATUS_B3_DOWN:
|
|
cursor_status.button_status |= MOUSE_RIGHT_BUTTON_DOWN_BIT;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Update position information and fill in position bit in the
|
|
* event mask
|
|
*/
|
|
if (inport_event.data_x != 0 || inport_event.data_y != 0)
|
|
{
|
|
condition_mask |= MOUSE_CALL_MASK_POSITION_BIT;
|
|
|
|
point_set(&mouse_movement,
|
|
inport_event.data_x, inport_event.data_y);
|
|
|
|
point_translate(&mouse_raw_motion, &mouse_movement);
|
|
|
|
/*
|
|
* Adjust for sensitivity
|
|
*/
|
|
mouse_movement.x = (MOUSE_SCALAR)(((IS32)mouse_movement.x * (IS32)mouse_sens_val.x) / MOUSE_SENS_MULT);
|
|
mouse_movement.y = (MOUSE_SCALAR)(((IS32)mouse_movement.y * (IS32)mouse_sens_val.y) / MOUSE_SENS_MULT);
|
|
|
|
/*
|
|
* NB. !!!
|
|
* We ought to apply the acceleration curve here
|
|
* and not the double speed set up. However mouse
|
|
* interrupts and mouse display are probably not
|
|
* fast enough anyway to make it worth while adding
|
|
* the acceleration fine tuning.
|
|
*/
|
|
|
|
/*
|
|
* Do speed doubling
|
|
*/
|
|
if ( (scalar_absolute(mouse_movement.x) > double_speed_threshold)
|
|
|| (scalar_absolute(mouse_movement.y) > double_speed_threshold))
|
|
vector_scale(&mouse_movement, MOUSE_DOUBLE_SPEED_SCALE);
|
|
|
|
/*
|
|
* Update the user mouse motion counters
|
|
*/
|
|
point_translate(&mouse_motion, &mouse_movement);
|
|
|
|
/*
|
|
* Convert the movement from a mouse Mickey count vector
|
|
* to a virtual screen coordinate vector, using the
|
|
* previous remainder and saving the new remainder
|
|
*/
|
|
vector_scale(&mouse_movement, MOUSE_RATIO_SCALE_FACTOR);
|
|
point_translate(&mouse_movement, &cursor_fractional_position);
|
|
point_copy(&mouse_movement, &cursor_fractional_position);
|
|
vector_divide_by_vector(&mouse_movement, &mouse_gear);
|
|
vector_mod_by_vector(&cursor_fractional_position, &mouse_gear);
|
|
|
|
/*
|
|
* Update the absolute cursor position and the windowed
|
|
* and gridded screen cursor position
|
|
*/
|
|
point_translate(&cursor_position, &mouse_movement);
|
|
cursor_update();
|
|
}
|
|
|
|
#endif /* NTVDM*/
|
|
|
|
/* OK mouse variables updated - go handle consequences */
|
|
mouse_update(condition_mask);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_int1:return()");
|
|
}
|
|
|
|
LOCAL void mouse_update IFN1(MOUSE_CALL_MASK, condition_mask)
|
|
{
|
|
MOUSE_CALL_MASK key_mask;
|
|
boolean alt_found = FALSE;
|
|
int i;
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse_update():cursor status = (%d,%d), LEFT %s, RIGHT %s",
|
|
cursor_status.position.x, cursor_status.position.y,
|
|
mouse_button_description(cursor_status.button_status & MOUSE_LEFT_BUTTON_DOWN_BIT),
|
|
mouse_button_description(cursor_status.button_status & MOUSE_RIGHT_BUTTON_DOWN_BIT));
|
|
|
|
if (alt_user_subroutines_active){
|
|
/* Get current key states in correct form */
|
|
key_mask = ((sas_hw_at(kb_flag) & LR_SHIFT) ? MOUSE_CALL_MASK_SHIFT_KEY_BIT : 0) |
|
|
((sas_hw_at(kb_flag) & CTL_SHIFT) ? MOUSE_CALL_MASK_CTRL_KEY_BIT : 0) |
|
|
((sas_hw_at(kb_flag) & ALT_SHIFT) ? MOUSE_CALL_MASK_ALT_KEY_BIT : 0);
|
|
for (i=0; !alt_found && i<NUMBER_ALT_SUBROUTINES; i++){
|
|
alt_found = (alt_user_subroutine_call_mask[i] & MOUSE_CALL_MASK_KEY_BITS) == key_mask;
|
|
}
|
|
}
|
|
|
|
#ifndef NTVDM
|
|
|
|
if (alt_found){
|
|
i--; /* Adjust for extra inc */
|
|
if (condition_mask & alt_user_subroutine_call_mask[i]){
|
|
if (!user_subroutine_critical){
|
|
user_subroutine_critical = TRUE;
|
|
jump_to_user_subroutine(condition_mask, alt_user_subroutine_segment[i], alt_user_subroutine_offset[i]);
|
|
}
|
|
return;
|
|
}
|
|
}else{
|
|
if (condition_mask & user_subroutine_call_mask){
|
|
if (!user_subroutine_critical){
|
|
user_subroutine_critical = TRUE;
|
|
jump_to_user_subroutine(condition_mask, user_subroutine_segment, user_subroutine_offset);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
#else /* NTVDM */
|
|
|
|
|
|
if (alt_found)
|
|
{
|
|
i--; /* Adjust for extra inc */
|
|
if ((condition_mask & alt_user_subroutine_call_mask[i]))
|
|
{
|
|
SuspendMouseInterrupts();
|
|
jump_to_user_subroutine(condition_mask, alt_user_subroutine_segment[i], alt_user_subroutine_offset[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((condition_mask & user_subroutine_call_mask))
|
|
{
|
|
SuspendMouseInterrupts();
|
|
jump_to_user_subroutine(condition_mask, user_subroutine_segment, user_subroutine_offset);
|
|
}
|
|
}
|
|
|
|
outb(ICA1_PORT_0, 0x20 );
|
|
outb(ICA0_PORT_0, END_INTERRUPT);
|
|
#endif
|
|
|
|
/*
|
|
* if the OS pointer is NOT being used to supply input,
|
|
* then get SoftPC to draw its own cursor
|
|
*/
|
|
/*@ACW*/
|
|
|
|
#ifndef NTVDM
|
|
/*
|
|
* If the cursor is currently displayed, move it to the new
|
|
* position
|
|
*/
|
|
if (condition_mask & MOUSE_CALL_MASK_POSITION_BIT)
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
#ifdef MOUSE_16_BIT
|
|
if (is_graphics_mode)
|
|
mouse16bCheckConditionalOff();
|
|
else
|
|
#endif /* MOUSE_16_BIT */
|
|
{
|
|
cursor_display();
|
|
}
|
|
#endif /*NTVDM*/
|
|
}
|
|
|
|
|
|
void mouse_int2()
|
|
{
|
|
/*
|
|
* Part 2 of the mouse hardware interrupt service routine. Control
|
|
* is passed to this routine when the "user subroutine" that may
|
|
* be called as part of the interrupt service routine completes
|
|
*/
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_int2:");
|
|
|
|
#ifndef NTVDM
|
|
user_subroutine_critical = FALSE;
|
|
#endif
|
|
|
|
setAX(saved_AX);
|
|
setBX(saved_BX);
|
|
setCX(saved_CX);
|
|
setDX(saved_DX);
|
|
setSI(saved_SI);
|
|
setDI(saved_DI);
|
|
setES(saved_ES);
|
|
setBP(saved_BP);
|
|
setDS(saved_DS);
|
|
|
|
/*
|
|
* If the cursor is currently displayed, move it to the new
|
|
* position
|
|
*/
|
|
if (last_condition_mask & MOUSE_CALL_MASK_POSITION_BIT)
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
{
|
|
#ifdef MOUSE_16_BIT
|
|
if (is_graphics_mode)
|
|
mouse16bCheckConditionalOff();
|
|
else
|
|
#endif /* MOUSE_16_BIT */
|
|
{
|
|
cursor_display();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Ensure any changes to the screen image are updated immediately
|
|
* on the real screen, giving a "smooth" mouse response; the flush
|
|
* must be done here for applications such as GEM which disable
|
|
* the mouse driver's graphics capabilities in favour of doing
|
|
* their own graphics in the user subroutine.
|
|
*/
|
|
host_flush_screen();
|
|
|
|
#ifdef NTVDM
|
|
ResumeMouseInterrupts();
|
|
#endif
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_int2:return()");
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* MOUSE DRIVER LOCAL FUNCTIONS
|
|
* ============================
|
|
*/
|
|
|
|
LOCAL void do_mouse_function IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This is the mouse function dispatcher
|
|
*/
|
|
int function = *m1;
|
|
|
|
switch(function)
|
|
{
|
|
/*
|
|
* Deal with special undocumented functions
|
|
*/
|
|
case MOUSE_SPECIAL_COPYRIGHT:
|
|
setES(MOUSE_COPYRIGHT_SEGMENT);
|
|
setDI(MOUSE_COPYRIGHT_OFFSET);
|
|
break;
|
|
case MOUSE_SPECIAL_VERSION:
|
|
setES(MOUSE_VERSION_SEGMENT);
|
|
setDI(MOUSE_VERSION_OFFSET);
|
|
break;
|
|
|
|
/*
|
|
* Deal with special undocumented functions
|
|
*/
|
|
default:
|
|
if (!mouse_function_in_range(function))
|
|
{
|
|
/*
|
|
* Use the unrecognised function
|
|
*/
|
|
function = MOUSE_UNRECOGNISED;
|
|
}
|
|
|
|
(*mouse_function[function])(m1, m2, m3, m4);
|
|
break;
|
|
}
|
|
}
|
|
|
|
LOCAL void mouse_reset IFN4(word *,installed_ptr,word *,nbuttons_ptr,word *,junk3,word *,junk4)
|
|
/*
|
|
* *installed_ptr Holds function number on input...
|
|
* Returns installation state.
|
|
*/
|
|
{
|
|
/*
|
|
* This function resets the mouse driver, and returns
|
|
* the installation status of the mouse hardware and software
|
|
*/
|
|
boolean soft_reset_only = (*installed_ptr == MOUSE_SOFT_RESET);
|
|
half_word crt_mode;
|
|
int button;
|
|
|
|
UNUSED(junk3);
|
|
UNUSED(junk4);
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io:reset(%s)",
|
|
soft_reset_only ? "SOFT" : "HARD");
|
|
|
|
/*
|
|
* Remove the old cursor from the screen
|
|
*/
|
|
cursor_undisplay();
|
|
|
|
/*
|
|
* Set cursor position to the default position, and the button
|
|
* status to all buttons up
|
|
*/
|
|
point_copy(&cursor_position_default, &cursor_position);
|
|
point_set(&cursor_fractional_position, 0, 0);
|
|
cursor_status.button_status = 0;
|
|
|
|
if (host_mouse_installed())
|
|
host_mouse_reset();
|
|
|
|
/*
|
|
* Set cursor window to be the whole screen
|
|
*/
|
|
area_copy(&virtual_screen, &cursor_window);
|
|
|
|
/*
|
|
* Set cursor flag to default
|
|
*/
|
|
cursor_flag = MOUSE_CURSOR_DEFAULT;
|
|
|
|
#if defined(MONITOR) && defined(NTVDM)
|
|
sas_store(mouseCFsysaddr, MOUSE_CURSOR_DEFAULT);
|
|
#endif
|
|
|
|
/*
|
|
* Get current video mode, and update parameters that are
|
|
* dependent on it
|
|
*/
|
|
sas_load(MOUSE_VIDEO_CRT_MODE, &crt_mode);
|
|
#if !defined(NTVDM) || (defined(NTVDM) && defined(V7VGA))
|
|
if ((crt_mode == 1) && extensions_controller.foreground_latch_1)
|
|
crt_mode = extensions_controller.foreground_latch_1;
|
|
else if (crt_mode > 0x13)
|
|
crt_mode += 0x4c;
|
|
#endif
|
|
|
|
cursor_mode_change((int)crt_mode);
|
|
|
|
/*
|
|
* Update dependent cursor status
|
|
*/
|
|
cursor_update();
|
|
|
|
/*
|
|
* Set default text cursor type and masks
|
|
*/
|
|
text_cursor_type = MOUSE_TEXT_CURSOR_TYPE_DEFAULT;
|
|
software_text_cursor_copy(&software_text_cursor_default,
|
|
&software_text_cursor);
|
|
|
|
/*
|
|
* Set default graphics cursor
|
|
*/
|
|
graphics_cursor_copy(&graphics_cursor_default, &graphics_cursor);
|
|
copy_default_graphics_cursor();
|
|
|
|
/*
|
|
* Set cursor page to zero
|
|
*/
|
|
cursor_page = 0;
|
|
|
|
/*
|
|
* Set light pen emulation mode on
|
|
*/
|
|
light_pen_mode = TRUE;
|
|
|
|
/*
|
|
* Set default Mickey to pixel ratios
|
|
*/
|
|
point_copy(&mouse_gear_default, &mouse_gear);
|
|
|
|
/*
|
|
* Clear mouse motion counters
|
|
*/
|
|
point_set(&mouse_motion, 0, 0);
|
|
point_set(&mouse_raw_motion, 0, 0);
|
|
|
|
/* Reset to default acceleration curve */
|
|
active_acceleration_curve = 3; /* Back to Normal */
|
|
|
|
memcpy(&acceleration_curve_data, &default_acceleration_curve,
|
|
sizeof(ACCELERATION_CURVE_DATA));
|
|
|
|
next_video_mode = 0; /* reset video mode enumeration */
|
|
|
|
/*
|
|
* Clear mouse button transition data
|
|
*/
|
|
for (button = 0; button < MOUSE_BUTTON_MAXIMUM; button++)
|
|
{
|
|
button_transitions[button].press_position.x = 0;
|
|
button_transitions[button].press_position.y = 0;
|
|
button_transitions[button].release_position.x = 0;
|
|
button_transitions[button].release_position.y = 0;
|
|
button_transitions[button].press_count = 0;
|
|
button_transitions[button].release_count = 0;
|
|
}
|
|
|
|
/*
|
|
* Disable conditional off area
|
|
*/
|
|
area_copy(&black_hole_default, &black_hole);
|
|
|
|
#if defined(MONITOR) && defined(NTVDM)
|
|
sas_store(conditional_off_sysaddr, 0);
|
|
#endif
|
|
|
|
/*
|
|
* Set default sensitivity
|
|
*/
|
|
vector_set (&mouse_sens, MOUSE_SENS_DEF, MOUSE_SENS_DEF);
|
|
vector_set (&mouse_sens_val, MOUSE_SENS_DEF_VAL, MOUSE_SENS_DEF_VAL);
|
|
mouse_double_thresh = MOUSE_DOUBLE_DEF;
|
|
|
|
/*
|
|
* Set double speed threshold to the default
|
|
*/
|
|
double_speed_threshold = MOUSE_DOUBLE_SPEED_THRESHOLD_DEFAULT;
|
|
|
|
/*
|
|
* Clear subroutine call mask
|
|
*/
|
|
user_subroutine_call_mask = 0;
|
|
|
|
/*
|
|
* Reset the bus mouse hardware
|
|
*/
|
|
if (!soft_reset_only){
|
|
inport_reset();
|
|
}
|
|
|
|
/*
|
|
* Set return values
|
|
*/
|
|
*installed_ptr = MOUSE_INSTALLED;
|
|
*nbuttons_ptr = 2;
|
|
|
|
note_trace2(MOUSE_VERBOSE, "mouse_io:return(ms=%d,nb=%d)",
|
|
*installed_ptr, *nbuttons_ptr);
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_show_cursor IFN4(word *,junk1,word *,junk2,word *,junk3,word *,junk4)
|
|
{
|
|
/*
|
|
* This function is used to display the cursor, based on the
|
|
* state of the internal cursor flag. If the cursor flag is
|
|
* already MOUSE_CURSOR_DISPLAYED, then this function does
|
|
* nothing. If the internal cursor flag becomes
|
|
* MOUSE_CURSOR_DISPLAYED when incremented by 1, the cursor
|
|
* is revealed
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
UNUSED(junk3);
|
|
UNUSED(junk4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:show_cursor()");
|
|
|
|
#ifndef NTVDM
|
|
/*
|
|
* Disable conditional off area
|
|
*/
|
|
area_copy(&black_hole_default, &black_hole);
|
|
|
|
/*
|
|
* Display the cursor
|
|
*/
|
|
if (cursor_flag != MOUSE_CURSOR_DISPLAYED)
|
|
if (++cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
#ifdef MOUSE_16_BIT
|
|
if (is_graphics_mode)
|
|
mouse16bShowPointer(&cursor_status);
|
|
else
|
|
#endif /* MOUSE_16_BIT */
|
|
{
|
|
cursor_display();
|
|
}
|
|
#endif /* NTVDM */
|
|
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
host_show_pointer();
|
|
#endif
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_hide_cursor IFN4(word *,junk1,word *,junk2,word *,junk3,word *,junk4)
|
|
{
|
|
/*
|
|
* This function is used to undisplay the cursor, based on
|
|
* the state of the internal cursor flag. If the cursor flag
|
|
* is already not MOUSE_CURSOR_DISPLAYED, then this function
|
|
* does nothing, otherwise it removes the cursor from the display
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
UNUSED(junk3);
|
|
UNUSED(junk4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:hide_cursor()");
|
|
#ifndef NTVDM
|
|
if (cursor_flag-- == MOUSE_CURSOR_DISPLAYED)
|
|
#ifdef MOUSE_16_BIT
|
|
if (is_graphics_mode)
|
|
mouse16bHidePointer();
|
|
else
|
|
#endif /* MOUSE_16_BIT */
|
|
{
|
|
cursor_undisplay();
|
|
}
|
|
#endif
|
|
#if defined(NTVDM) && defined(X86GFX)
|
|
host_hide_pointer();
|
|
#endif
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_get_position IFN4(word *,junk1,MOUSE_STATE *,button_status_ptr,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr)
|
|
{
|
|
/*
|
|
* This function returns the state of the left and right mouse
|
|
* buttons and the gridded position of the cursor on the screen
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:get_position()");
|
|
|
|
*button_status_ptr = cursor_status.button_status;
|
|
*cursor_x_ptr = cursor_status.position.x;
|
|
*cursor_y_ptr = cursor_status.position.y;
|
|
|
|
note_trace3(MOUSE_VERBOSE, "mouse_io:return(bs=%d,x=%d,y=%d)",
|
|
*button_status_ptr, *cursor_x_ptr, *cursor_y_ptr);
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_set_position IFN4(word *,junk1,word *,junk2,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr)
|
|
{
|
|
/*
|
|
* This function sets the cursor to a new position
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
|
|
note_trace2(MOUSE_VERBOSE, "mouse_io:set_position(x=%d,y=%d)",
|
|
*cursor_x_ptr, *cursor_y_ptr);
|
|
|
|
|
|
#if defined(NTVDM)
|
|
|
|
#ifndef X86GFX
|
|
/*
|
|
* update the cursor position. cc:Mail installtion does
|
|
* do {
|
|
* SetMouseCursorPosition(x,y)
|
|
* GetMouseCursorPosition(&NewX, &NewY);
|
|
* } while(NewX != x || NewY != y)
|
|
* If we don't retrun correct cursor position, this application
|
|
* looks hung
|
|
*
|
|
*/
|
|
point_set(&cursor_status.position, *cursor_x_ptr, *cursor_y_ptr);
|
|
|
|
#endif
|
|
/*
|
|
* For NT, the system pointer is used directly to provide
|
|
* input except for fullscreen graphics where the host code
|
|
* has the dubious pleasure of drawing the pointer through
|
|
* a 16 bit device driver.
|
|
*/
|
|
|
|
host_mouse_set_position((USHORT)*cursor_x_ptr,(USHORT)*cursor_y_ptr);
|
|
return; /* let's get out of this mess - FAST! */
|
|
|
|
#endif /* NTVDM */
|
|
|
|
/*
|
|
* Update the current cursor position, and reflect the change
|
|
* in the cursor position on the screen
|
|
*/
|
|
point_set(&cursor_position, *cursor_x_ptr, *cursor_y_ptr);
|
|
cursor_update();
|
|
|
|
/*
|
|
* If the cursor is currently displayed, move it to the new
|
|
* position
|
|
*/
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
cursor_display();
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_get_press IFN4(MOUSE_STATE *,button_status_ptr,MOUSE_COUNT *,button_ptr,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr)
|
|
{
|
|
/*
|
|
* This function returns the status of a button, the number of
|
|
* presses since the last call to this function, and the
|
|
* coordinates of the cursor at the last button press
|
|
*/
|
|
int button = *button_ptr;
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io:get_press(button=%d)", button);
|
|
|
|
/* Now and with 1. This is a fix for Norton Editor, but may cause
|
|
problems for programs which use both mouse buttons pressed
|
|
simultaneously, in which case need both bottom bits of button
|
|
preserved, which may break Norton Editor again. sigh. */
|
|
button &= 1;
|
|
|
|
if (mouse_button_in_range(button))
|
|
{
|
|
*button_status_ptr = cursor_status.button_status;
|
|
*button_ptr = button_transitions[button].press_count;
|
|
button_transitions[button].press_count = 0;
|
|
*cursor_x_ptr = button_transitions[button].press_position.x;
|
|
*cursor_y_ptr = button_transitions[button].press_position.y;
|
|
}
|
|
|
|
note_trace4(MOUSE_VERBOSE, "mouse_io:return(bs=%d,ct=%d,x=%d,y=%d)",
|
|
*button_status_ptr, *button_ptr,
|
|
*cursor_x_ptr, *cursor_y_ptr);
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_get_release IFN4(MOUSE_STATE *,button_status_ptr,MOUSE_COUNT *,button_ptr,MOUSE_SCALAR *,cursor_x_ptr,MOUSE_SCALAR *,cursor_y_ptr)
|
|
{
|
|
/*
|
|
* This function returns the status of a button, the number of
|
|
* releases since the last call to this function, and the
|
|
* coordinates of the cursor at the last button release
|
|
*/
|
|
int button = *button_ptr;
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io:get_release(button=%d)",
|
|
*button_ptr);
|
|
|
|
/* fix for norton editor, see previous comment */
|
|
button &= 1;
|
|
|
|
if (mouse_button_in_range(button))
|
|
{
|
|
*button_status_ptr = cursor_status.button_status;
|
|
*button_ptr = button_transitions[button].release_count;
|
|
button_transitions[button].release_count = 0;
|
|
*cursor_x_ptr = button_transitions[button].release_position.x;
|
|
*cursor_y_ptr = button_transitions[button].release_position.y;
|
|
}
|
|
|
|
note_trace4(MOUSE_VERBOSE, "mouse_io:return(bs=%d,ct=%d,x=%d,y=%d)",
|
|
*button_status_ptr, *button_ptr,
|
|
*cursor_x_ptr, *cursor_y_ptr);
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_set_range_x IFN4(word *,junk1,word *,junk2,MOUSE_SCALAR *,minimum_x_ptr,MOUSE_SCALAR *,maximum_x_ptr)
|
|
{
|
|
/*
|
|
* This function sets the horizontal range within which
|
|
* movement of the cursor is to be restricted
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
|
|
note_trace2(MOUSE_VERBOSE, "mouse_io:set_range_x(min=%d,max=%d)",
|
|
*minimum_x_ptr, *maximum_x_ptr);
|
|
|
|
/*
|
|
* Update the current cursor window, normalise it and validate
|
|
* it
|
|
*/
|
|
cursor_window.top_left.x = *minimum_x_ptr;
|
|
cursor_window.bottom_right.x = *maximum_x_ptr;
|
|
area_normalise(&cursor_window);
|
|
#ifdef NTVDM
|
|
/* make host aware of the new range setting because it is the one doing
|
|
* clipping based on video mode setting.
|
|
* Flight Simulator runs on 320x400 256 color mode and set the
|
|
* cursor range to (0-13f, 0-18f). Without notifying the host,
|
|
* the mouse cursor is always contrained to standard video mode
|
|
* resolution which is not what the application wanted.
|
|
*/
|
|
host_x_range(NULL, NULL, &cursor_window.top_left.x, &cursor_window.bottom_right.x);
|
|
#endif
|
|
|
|
/*
|
|
* Reflect the change in the cursor position on the screen
|
|
*/
|
|
cursor_update();
|
|
|
|
/*
|
|
* If the cursor is currently displayed, move it to the new
|
|
* position
|
|
*/
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
cursor_display();
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_set_range_y IFN4(word *,junk1,word *,junk2,MOUSE_SCALAR *,minimum_y_ptr,MOUSE_SCALAR *,maximum_y_ptr)
|
|
{
|
|
/*
|
|
* This function sets the vertical range within which
|
|
* movement of the cursor is to be restricted
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
|
|
note_trace2(MOUSE_VERBOSE, "mouse_io:set_range_y(min=%d,max=%d)",
|
|
*minimum_y_ptr, *maximum_y_ptr);
|
|
|
|
/*
|
|
* Update the current cursor window, normalise it and validate
|
|
* it
|
|
*/
|
|
cursor_window.top_left.y = *minimum_y_ptr;
|
|
cursor_window.bottom_right.y = *maximum_y_ptr;
|
|
area_normalise(&cursor_window);
|
|
#ifdef NTVDM
|
|
/* make host aware of the new range setting because it is the one doing
|
|
* clipping based on video mode setting.
|
|
* Flight Simulator runs on 320x400 256 color mode and set the
|
|
* cursor range to (0-13f, 0-18f). Without notifying the host,
|
|
* the mouse cursor is always contrained to standard video mode
|
|
* resolution which is not what the application wanted.
|
|
*/
|
|
host_y_range(NULL, NULL, &cursor_window.top_left.y, &cursor_window.bottom_right.y);
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Reflect the change in the cursor position on the screen
|
|
*/
|
|
cursor_update();
|
|
|
|
/*
|
|
* If the cursor is currently displayed, move it to the new
|
|
* position
|
|
*/
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
cursor_display();
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
LOCAL void copy_default_graphics_cursor IFN0()
|
|
{
|
|
|
|
int line;
|
|
UTINY temp;
|
|
IU32 temp2;
|
|
|
|
for (line = 0; line < MOUSE_GRAPHICS_CURSOR_DEPTH; line++)
|
|
{
|
|
temp = (UTINY)((graphics_cursor.screen[line] & 0xff00) >> 8);
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.screen_lo[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
temp = (UTINY)(graphics_cursor.screen[line] & 0xff);
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.screen_hi[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
}
|
|
|
|
for (line = 0; line < MOUSE_GRAPHICS_CURSOR_DEPTH; line++)
|
|
{
|
|
temp = (UTINY)((graphics_cursor.cursor[line] & 0xff00) >> 8);
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.cursor_lo[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
temp = (UTINY)(graphics_cursor.cursor[line] & 0xff);
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.cursor_hi[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
LOCAL void mouse_set_graphics IFN4(word *,junk1,MOUSE_SCALAR *,hot_spot_x_ptr,MOUSE_SCALAR *,hot_spot_y_ptr,word *,bitmap_address)
|
|
{
|
|
/*
|
|
* This function defines the shape, colour and hot spot of the
|
|
* graphics cursor
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
|
|
#ifndef NTVDM
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
mouse16bSetBitmap( hot_spot_x_ptr , hot_spot_y_ptr , bitmap_address );
|
|
#else /* MOUSE_16_BIT */
|
|
|
|
if (host_mouse_installed())
|
|
{
|
|
host_mouse_set_graphics(hot_spot_x_ptr, hot_spot_y_ptr, bitmap_address);
|
|
}
|
|
else
|
|
{
|
|
MOUSE_SCREEN_DATA *mask_address;
|
|
int line;
|
|
UTINY temp;
|
|
IU32 temp2;
|
|
|
|
/*
|
|
* Set graphics cursor hot spot
|
|
*/
|
|
point_set(&graphics_cursor.hot_spot, *hot_spot_x_ptr, *hot_spot_y_ptr);
|
|
|
|
/*
|
|
* Set graphics cursor screen and cursor masks
|
|
*/
|
|
mask_address = (MOUSE_SCREEN_DATA *)effective_addr(getES(), *bitmap_address);
|
|
|
|
for (line = 0; line < MOUSE_GRAPHICS_CURSOR_DEPTH; line++, mask_address++)
|
|
{
|
|
sas_load((sys_addr)mask_address + 1, &temp );
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.screen_lo[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
sas_load((sys_addr)mask_address , &temp );
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.screen_hi[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
graphics_cursor.screen[line] = ( graphics_cursor.screen_hi[line] & 0xff )
|
|
| ( graphics_cursor.screen_lo[line] << 8 );
|
|
}
|
|
|
|
for (line = 0; line < MOUSE_GRAPHICS_CURSOR_DEPTH; line++, mask_address++)
|
|
{
|
|
sas_load((sys_addr)mask_address + 1, &temp );
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.cursor_lo[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
sas_load((sys_addr)mask_address , &temp );
|
|
|
|
temp2 = ( (IU32) temp << 8 ) | (IU32) temp;
|
|
graphics_cursor.cursor_hi[line] = ( temp2 << 16 ) | temp2;
|
|
|
|
graphics_cursor.cursor[line] = ( graphics_cursor.cursor_hi[line] & 0xff )
|
|
| ( graphics_cursor.cursor_lo[line] << 8 );
|
|
}
|
|
|
|
}
|
|
#endif /* MOUSE_16_BIT */
|
|
#endif /* NTVDM */
|
|
/*
|
|
* Redisplay cursor if necessary
|
|
*/
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
cursor_display();
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_set_text IFN4(word *,junk1,MOUSE_STATE *,text_cursor_type_ptr,MOUSE_SCREEN_DATA *,parameter1_ptr,MOUSE_SCREEN_DATA *,parameter2_ptr)
|
|
{
|
|
/*
|
|
* This function selects the software or hardware text cursor
|
|
*/
|
|
UNUSED(junk1);
|
|
|
|
#ifndef PROD
|
|
if (io_verbose & MOUSE_VERBOSE)
|
|
{
|
|
fprintf(trace_file, "mouse_io:set_text(type=%d,",
|
|
*text_cursor_type_ptr);
|
|
if (*text_cursor_type_ptr == MOUSE_TEXT_CURSOR_TYPE_SOFTWARE)
|
|
fprintf(trace_file, "screen=0x%x,cursor=0x%x)\n",
|
|
*parameter1_ptr, *parameter2_ptr);
|
|
else
|
|
fprintf(trace_file, "start=%d,stop=%d)\n",
|
|
*parameter1_ptr, *parameter2_ptr);
|
|
}
|
|
#endif
|
|
|
|
if (mouse_text_cursor_type_in_range(*text_cursor_type_ptr))
|
|
{
|
|
/*
|
|
* Remove existing text cursor
|
|
*/
|
|
cursor_undisplay();
|
|
|
|
text_cursor_type = *text_cursor_type_ptr;
|
|
#ifdef EGG
|
|
if (jap_mouse) {
|
|
/* we need to emulate the text cursor in the
|
|
* current graphics mode. Just do a block at present
|
|
*/
|
|
int line;
|
|
for (line = 0; line < MOUSE_GRAPHICS_CURSOR_DEPTH; line++)
|
|
{
|
|
graphics_cursor.cursor[line]=0xff00;
|
|
graphics_cursor.screen[line]=0xffff;
|
|
}
|
|
point_set(&(graphics_cursor.hot_spot),0,0);
|
|
point_set(&(graphics_cursor.size),MOUSE_GRAPHICS_CURSOR_WIDTH,MOUSE_GRAPHICS_CURSOR_WIDTH);
|
|
copy_default_graphics_cursor();
|
|
} else
|
|
#endif /* EGG */
|
|
if (text_cursor_type == MOUSE_TEXT_CURSOR_TYPE_SOFTWARE)
|
|
{
|
|
/*
|
|
* Parameters are the data for the screen
|
|
* and cursor masks
|
|
*/
|
|
software_text_cursor.screen = *parameter1_ptr;
|
|
software_text_cursor.cursor = *parameter2_ptr;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Parameters are the scan line start and
|
|
* stop values
|
|
*/
|
|
word savedIP = getIP(), savedCS = getCS();
|
|
|
|
setCH(*parameter1_ptr);
|
|
setCL(*parameter2_ptr);
|
|
setAH(MOUSE_VIDEO_SET_CURSOR);
|
|
|
|
setCS(VIDEO_IO_SEGMENT);
|
|
setIP(VIDEO_IO_RE_ENTRY);
|
|
host_simulate();
|
|
setCS(savedCS);
|
|
setIP(savedIP);
|
|
}
|
|
|
|
/*
|
|
* Put new text cursor on screen
|
|
*/
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
cursor_display();
|
|
}
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_read_motion IFN4(word *,junk1,word *,junk2,MOUSE_COUNT *,motion_count_x_ptr,MOUSE_COUNT *,motion_count_y_ptr)
|
|
{
|
|
/*
|
|
* This function returns the horizontal and vertical mouse
|
|
* motion counts since the last call; the motion counters
|
|
* are cleared
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:read_motion()");
|
|
|
|
*motion_count_x_ptr = mouse_motion.x;
|
|
mouse_motion.x = 0;
|
|
*motion_count_y_ptr = mouse_motion.y;
|
|
mouse_motion.y = 0;
|
|
|
|
|
|
note_trace2(MOUSE_VERBOSE, "mouse_io:return(x=%d,y=%d)",
|
|
*motion_count_x_ptr, *motion_count_y_ptr);
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_set_subroutine IFN4(word *,junk1,word *,junk2,word *,call_mask,word *,subroutine_address)
|
|
{
|
|
/*
|
|
* This function sets the call mask and subroutine address
|
|
* for a user function to be called when a mouse interrupt
|
|
* occurs
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
|
|
note_trace3(MOUSE_VERBOSE,
|
|
"mouse_io:set_subroutine(CS:IP=%x:%x,mask=0x%02x)",
|
|
getES(), *subroutine_address, *call_mask);
|
|
|
|
user_subroutine_segment = getES();
|
|
user_subroutine_offset = *subroutine_address;
|
|
user_subroutine_call_mask = (*call_mask) & MOUSE_CALL_MASK_SIGNIFICANT_BITS;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
/* unpublished service 20, used by Microsoft Windows */
|
|
LOCAL void mouse_get_and_set_subroutine IFN4(word *,junk1,word *,junk2,word *,call_mask,word *,subroutine_address)
|
|
{
|
|
/*
|
|
same as set_subroutine (function 12) but also returns previous call mask in cx (m3)
|
|
and user subroutine address in es:dx (es:m4)
|
|
*/
|
|
word local_segment, local_offset, local_call_mask;
|
|
|
|
note_trace3(MOUSE_VERBOSE,
|
|
"mouse_io:get_and_set_subroutine(CS:IP=%x:%x,mask=0x%02x)",
|
|
getES(), *subroutine_address, *call_mask);
|
|
|
|
local_offset = user_subroutine_offset;
|
|
local_segment = user_subroutine_segment;
|
|
local_call_mask = user_subroutine_call_mask;
|
|
/* save previous subroutine data so it can be returned */
|
|
|
|
mouse_set_subroutine(junk1,junk2,call_mask,subroutine_address);
|
|
/* set the subroutine stuff with the normal function 12 */
|
|
*call_mask = local_call_mask;
|
|
*subroutine_address = local_offset;
|
|
setES(local_segment);
|
|
}
|
|
|
|
|
|
|
|
LOCAL void mouse_light_pen_on IFN4(word *,junk1,word *,junk2,word *,junk3,word *,junk4)
|
|
{
|
|
/*
|
|
* This function enables light pen emulation
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
UNUSED(junk3);
|
|
UNUSED(junk4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:light_pen_on()");
|
|
|
|
light_pen_mode = TRUE;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_light_pen_off IFN4(word *,junk1,word *,junk2,word *,junk3,word *,junk4)
|
|
{
|
|
/*
|
|
* This function disables light pen emulation
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
UNUSED(junk3);
|
|
UNUSED(junk4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:light_pen_off()");
|
|
|
|
light_pen_mode = FALSE;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_set_ratio IFN4(word *,junk1,word *,junk2,MOUSE_SCALAR *,ratio_x_ptr,MOUSE_SCALAR *,ratio_y_ptr)
|
|
{
|
|
/*
|
|
* This function sets the Mickey to Pixel ratio in the
|
|
* horizontal and vertical directions
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
|
|
note_trace2(MOUSE_VERBOSE, "mouse_io:set_ratio(x=%d,y=%d)",
|
|
*ratio_x_ptr, *ratio_y_ptr);
|
|
|
|
/*
|
|
* Update the Mickey to pixel ratio in force
|
|
*/
|
|
if (mouse_ratio_in_range(*ratio_x_ptr))
|
|
mouse_gear.x = *ratio_x_ptr;
|
|
if (mouse_ratio_in_range(*ratio_y_ptr))
|
|
mouse_gear.y = *ratio_y_ptr;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void mouse_conditional_off IFN4(word *,junk1,word *,junk2,MOUSE_SCALAR *,upper_x_ptr,MOUSE_SCALAR *,upper_y_ptr)
|
|
{
|
|
/*
|
|
* This function defines an area of the virtual screen where
|
|
* the mouse is automatically hidden
|
|
*/
|
|
MOUSE_SCALAR lower_x = getSI(), lower_y = getDI();
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse_io:conditional_off(ux=%d,uy=%d,lx=%d,ly=%d)",
|
|
*upper_x_ptr, *upper_y_ptr, lower_x, lower_y);
|
|
|
|
/*
|
|
* Update the conditional off area and normalise it: the Microsoft
|
|
* driver adds a considerable "margin for error" to the left and
|
|
* above the conditional off area requested - we must do the same
|
|
* to behave compatibly
|
|
*/
|
|
black_hole.top_left.x = (*upper_x_ptr) - MOUSE_CONDITIONAL_OFF_MARGIN_X;
|
|
black_hole.top_left.y = (*upper_y_ptr) - MOUSE_CONDITIONAL_OFF_MARGIN_Y;
|
|
black_hole.bottom_right.x = lower_x + 1;
|
|
black_hole.bottom_right.y = lower_y + 1;
|
|
area_normalise(&black_hole);
|
|
|
|
/*
|
|
* If the cursor is currently displayed, redisplay taking the
|
|
* conditional off area into account
|
|
*/
|
|
#ifdef MOUSE_16_BIT
|
|
if (is_graphics_mode)
|
|
{
|
|
if ((cursor_position.x >= black_hole.top_left.x) &&
|
|
(cursor_position.x <= black_hole.bottom_right.x) &&
|
|
(cursor_position.y >= black_hole.top_left.y) &&
|
|
(cursor_position.y <= black_hole.bottom_right.y))
|
|
if (cursor_flag-- == MOUSE_CURSOR_DISPLAYED)
|
|
mouse16bHidePointer();
|
|
}
|
|
else
|
|
#endif /* MOUSE_16_BIT */
|
|
{
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED)
|
|
cursor_display();
|
|
}
|
|
#if defined (NTVDM) && defined(MONITOR)
|
|
|
|
sas_store(conditional_off_sysaddr, 1);
|
|
host_mouse_conditional_off_enabled();
|
|
#endif
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_state_size IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function returns the size of buffer the caller needs to
|
|
* supply to mouse function 22 (save state)
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_get_state_size()");
|
|
|
|
*m2 = (word)mouse_context_size;
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io: ...size is %d(decimal) bytes.",
|
|
*m2);
|
|
}
|
|
|
|
|
|
LOCAL void mouse_save_state IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function saves the state of the driver in the user-supplied
|
|
* buffer ready for subsequent passing to mouse function 23 (restore
|
|
* state)
|
|
*
|
|
* Note that a magic cookie and checksum are placed in the saved state so that the
|
|
* restore routine can ignore invalid calls.
|
|
*/
|
|
sys_addr dest;
|
|
IS32 cs = 0;
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
|
|
/* real CF resides in 16 bit code */
|
|
int saved_cursor_flag = cursor_flag;
|
|
IS8 copyCF;
|
|
|
|
#endif
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
sas_load(mouseCFsysaddr, ©CF);
|
|
cursor_flag = (int)copyCF;
|
|
#endif
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_save_state()");
|
|
|
|
dest = effective_addr (getES(), *m4);
|
|
|
|
/* Save Cookie */
|
|
sas_stores(dest, (IU8 *)mouse_context_magic, MOUSE_CONTEXT_MAGIC_SIZE);
|
|
dest += MOUSE_CONTEXT_MAGIC_SIZE;
|
|
|
|
/* Save Context Variables */
|
|
sas_stores(dest, (IU8 *)&mouse_context, sizeof(MOUSE_CONTEXT));
|
|
dest += sizeof(MOUSE_CONTEXT);
|
|
|
|
/* Save Checksum */
|
|
sas_store (dest, (byte)(cs & 0xFF));
|
|
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
cursor_flag = saved_cursor_flag;
|
|
#endif
|
|
}
|
|
|
|
|
|
LOCAL void mouse_restore_state IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function restores the state of the driver from the user-supplied
|
|
* buffer which was set up by a call to mouse function 22.
|
|
*
|
|
* Note that a magic cookie and checksum were placed in the saved state so this routine
|
|
* checks for its presence and ignores the call if it is not found.
|
|
*/
|
|
sys_addr src;
|
|
IS32 i;
|
|
IS32 cs = 0;
|
|
half_word b;
|
|
boolean valid=TRUE;
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_restore_state()");
|
|
|
|
src = effective_addr (getES(), *m4);
|
|
|
|
/* Check Cookie */
|
|
for (i=0; valid && i<MOUSE_CONTEXT_MAGIC_SIZE; i++){
|
|
sas_load (src, &b);
|
|
valid = (b == mouse_context_magic[i]);
|
|
src++;
|
|
}
|
|
|
|
if (valid){
|
|
/* Cookie was present... check checksum */
|
|
src = effective_addr (getES(), *m4);
|
|
for (i=0; i<MOUSE_CONTEXT_MAGIC_SIZE; i++){
|
|
sas_load (src, &b);
|
|
cs += b;
|
|
src++;
|
|
}
|
|
for (i = 0; i < sizeof(MOUSE_CONTEXT); i++){
|
|
sas_load (src, &b);
|
|
cs += b;
|
|
src++;
|
|
}
|
|
sas_load (src, &b); /* Pick up saved checksum */
|
|
valid = (b == (half_word)(cs & 0xFF));
|
|
}
|
|
if (valid){
|
|
/* Checksum OK, too.... load up our variables */
|
|
cursor_undisplay();
|
|
src = effective_addr (getES(), *m4) + MOUSE_CONTEXT_MAGIC_SIZE;
|
|
sas_loads(src, (IU8 *)&mouse_context, sizeof(MOUSE_CONTEXT));
|
|
#ifdef EGG
|
|
mouse_ega_mode (sas_hw_at(vd_video_mode));
|
|
#endif
|
|
#if defined(NTVDM) && defined(MONITOR)
|
|
/* real CF resides in 16 Bit code: */
|
|
sas_store(mouseCFsysaddr, (half_word)cursor_flag);
|
|
if (cursor_flag )
|
|
cursor_flag = MOUSE_CURSOR_DEFAULT;
|
|
#endif
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED){
|
|
cursor_display();
|
|
}
|
|
}else{
|
|
/* Something failed.... ignore the call */
|
|
#ifndef PROD
|
|
printf ("mouse_io.c: invalid call to restore context.\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void mouse_set_alt_subroutine IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function sets up to 3 alternate event handlers for mouse
|
|
* events which occur while various combinations of the Ctrl, Shift
|
|
* and Alt keys are down.
|
|
*/
|
|
boolean found_one=FALSE;
|
|
int i;
|
|
|
|
UNUSED(m2);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_set_alt_subroutine()");
|
|
|
|
if (*m3 & MOUSE_CALL_MASK_KEY_BITS){
|
|
/* Search for entry with same key combination */
|
|
for (i=0; !found_one && i<NUMBER_ALT_SUBROUTINES; i++){
|
|
found_one = (*m3 & MOUSE_CALL_MASK_KEY_BITS)==(alt_user_subroutine_call_mask[i] & MOUSE_CALL_MASK_KEY_BITS);
|
|
}
|
|
|
|
if (!found_one){
|
|
/* Does not match existing entry... try to find free slot */
|
|
for (i=0; !found_one && i<NUMBER_ALT_SUBROUTINES; i++){
|
|
found_one = (alt_user_subroutine_call_mask[i] & MOUSE_CALL_MASK_KEY_BITS) == 0;
|
|
}
|
|
}
|
|
|
|
if (found_one){
|
|
i--; /* Adjust for final increment */
|
|
alt_user_subroutine_call_mask[i] = *m3;
|
|
if (*m3 & MOUSE_CALL_MASK_SIGNIFICANT_BITS){
|
|
/* New value active */
|
|
alt_user_subroutines_active = TRUE;
|
|
alt_user_subroutine_offset[i] = *m4;
|
|
alt_user_subroutine_segment[i] = getES();
|
|
}else{
|
|
/* New value is not active - check if we've disabled the last one */
|
|
alt_user_subroutines_active = FALSE;
|
|
for (i=0; !alt_user_subroutines_active && i<NUMBER_ALT_SUBROUTINES; i++){
|
|
alt_user_subroutines_active =
|
|
(alt_user_subroutine_call_mask[i] & MOUSE_CALL_MASK_SIGNIFICANT_BITS) != 0;
|
|
}
|
|
}
|
|
/* Return success */
|
|
*m1 = 0;
|
|
}else{
|
|
/* Request failed - no free slot */
|
|
*m1 = 0xFFFF;
|
|
}
|
|
}else{
|
|
/* Error - no key bits set in request */
|
|
*m1 = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_alt_subroutine IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function obtains the address of a specific alternate
|
|
* user event handling subroutine as set up by a previous call
|
|
* to mouse function 24.
|
|
*/
|
|
boolean found_one=FALSE;
|
|
int i;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_get_alt_subroutine()");
|
|
|
|
if (*m3 & MOUSE_CALL_MASK_KEY_BITS){
|
|
/* Search for entry with same key combination */
|
|
for (i=0; !found_one && i<NUMBER_ALT_SUBROUTINES; i++){
|
|
found_one = (*m3 & MOUSE_CALL_MASK_KEY_BITS)==(alt_user_subroutine_call_mask[i] & MOUSE_CALL_MASK_KEY_BITS);
|
|
}
|
|
|
|
if (found_one){
|
|
i--; /* Adjust for final increment */
|
|
*m3 = alt_user_subroutine_call_mask[i];
|
|
*m2 = alt_user_subroutine_segment[i];
|
|
*m4 = alt_user_subroutine_offset[i];
|
|
/* Return success */
|
|
*m1 = 0;
|
|
}else{
|
|
/* Request failed - not found */
|
|
*m1 = 0xFFFF;
|
|
*m2 = *m3 = *m4 = 0;
|
|
}
|
|
}else{
|
|
/* Error - no key bits set in request */
|
|
*m1 = 0xFFFF;
|
|
*m2 = *m3 = *m4 = 0;
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void mouse_set_sensitivity IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function sets a new value for the mouse sensitivity and
|
|
* double speed threshold.
|
|
* The sensitivity value is used before the mickeys per pixel
|
|
* ratio is applied.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_set_sensitivity()");
|
|
|
|
if (mouse_sens_in_range(*m2))
|
|
{
|
|
mouse_sens_val.x = mouse_sens_calc_val(*m2);
|
|
mouse_sens.x = *m2;
|
|
}
|
|
else
|
|
{
|
|
mouse_sens_val.x = MOUSE_SENS_DEF_VAL;
|
|
mouse_sens.x = MOUSE_SENS_DEF;
|
|
}
|
|
if (mouse_sens_in_range(*m3))
|
|
{
|
|
mouse_sens_val.y = mouse_sens_calc_val(*m3);
|
|
mouse_sens.y = *m3;
|
|
}
|
|
else
|
|
{
|
|
mouse_sens_val.y = MOUSE_SENS_DEF_VAL;
|
|
mouse_sens.y = MOUSE_SENS_DEF;
|
|
}
|
|
/*
|
|
* m4 has speed double threshold value... still needs to be implemented.
|
|
*/
|
|
if (mouse_sens_in_range(*m4))
|
|
mouse_double_thresh = *m4;
|
|
else
|
|
mouse_double_thresh = MOUSE_DOUBLE_DEF;
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_sensitivity IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function returns the current value of the mouse sensitivity.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_get_sensitivity()");
|
|
|
|
*m2 = mouse_sens.x;
|
|
*m3 = mouse_sens.y;
|
|
*m4 = mouse_double_thresh;
|
|
}
|
|
|
|
|
|
LOCAL void mouse_set_int_rate IFN4
|
|
(
|
|
word *, m1,
|
|
word *, int_rate_ptr,
|
|
word *, m3,
|
|
word *, m4
|
|
)
|
|
{
|
|
/*
|
|
Func 28: Set Mouse Interrupt Rate.
|
|
0 = No interrupts
|
|
1 = 30 interrupte/sec
|
|
2 = 50 interrupte/sec
|
|
3 = 100 interrupte/sec
|
|
4 = 200 interrupte/sec
|
|
>4 = undefined
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io: set_int_rate(rate=%d)", *int_rate_ptr);
|
|
|
|
/* Just remember rate, for later return (Func 51). We don't actually
|
|
action it. */
|
|
mouse_interrupt_rate = *int_rate_ptr;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: return()");
|
|
}
|
|
|
|
|
|
LOCAL void mouse_set_pointer_page IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function sets the current mouse pointer video page.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_set_pointer_page()");
|
|
|
|
if (is_valid_page_number(*m2)){
|
|
cursor_undisplay();
|
|
cursor_page = *m2;
|
|
if (cursor_flag == MOUSE_CURSOR_DISPLAYED){
|
|
cursor_display();
|
|
}
|
|
}else{
|
|
#ifndef PROD
|
|
fprintf(trace_file, "mouse_io: Bad page requested\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_pointer_page IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function gets the value of the current mouse pointer
|
|
* video page.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_get_pointer_page()");
|
|
*m2 = cursor_page;
|
|
}
|
|
|
|
|
|
LOCAL void mouse_driver_disable IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function disables the mouse driver and de-installs the
|
|
* interrupt vectors (bar INT 33h, whose previous value is
|
|
* returned to the caller to allow them to use DOS function
|
|
* 25h to completely remove the mouse driver).
|
|
*/
|
|
boolean failed = FALSE;
|
|
#ifdef NTVDM
|
|
word current_int71_offset, current_int71_segment;
|
|
#else
|
|
word current_int0A_offset, current_int0A_segment;
|
|
word current_int10_offset, current_int10_segment;
|
|
#endif
|
|
half_word interrupt_mask_register;
|
|
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_disable()");
|
|
mouse_driver_disabled = TRUE;
|
|
|
|
if (!failed){
|
|
#ifdef NTVDM
|
|
sas_loadw (int_addr(0x71) + 0, ¤t_int71_offset);
|
|
sas_loadw (int_addr(0x71) + 2, ¤t_int71_segment);
|
|
failed = current_int71_offset != MOUSE_INT1_OFFSET ||
|
|
current_int71_segment != MOUSE_INT1_SEGMENT;
|
|
#else
|
|
sas_loadw (int_addr(MOUSE_VEC) + 0, ¤t_int0A_offset);
|
|
sas_loadw (int_addr(MOUSE_VEC) + 2, ¤t_int0A_segment);
|
|
sas_loadw (int_addr(0x10) + 0, ¤t_int10_offset);
|
|
sas_loadw (int_addr(0x10) + 2, ¤t_int10_segment);
|
|
failed = current_int0A_offset != MOUSE_INT1_OFFSET ||
|
|
current_int0A_segment != MOUSE_INT1_SEGMENT ||
|
|
current_int10_offset != MOUSE_VIDEO_IO_OFFSET ||
|
|
current_int10_segment != MOUSE_VIDEO_IO_SEGMENT;
|
|
#endif
|
|
}
|
|
if (!failed){
|
|
/*
|
|
* Disable mouse H/W interrupts
|
|
*/
|
|
inb(ICA1_PORT_1, &interrupt_mask_register);
|
|
interrupt_mask_register |= (1 << AT_CPU_MOUSE_INT);
|
|
outb(ICA1_PORT_1, interrupt_mask_register);
|
|
inb(ICA0_PORT_1, &interrupt_mask_register);
|
|
interrupt_mask_register |= (1 << CPU_MOUSE_INT);
|
|
outb(ICA0_PORT_1, interrupt_mask_register);
|
|
/*
|
|
* Restore interrupt vectors
|
|
*/
|
|
|
|
#ifdef NTVDM
|
|
sas_storew (int_addr(0x71) + 0, saved_int71_offset);
|
|
sas_storew (int_addr(0x71) + 2, saved_int71_segment);
|
|
#else
|
|
sas_storew (int_addr(MOUSE_VEC) + 0, saved_int0A_offset);
|
|
sas_storew (int_addr(MOUSE_VEC) + 2, saved_int0A_segment);
|
|
sas_storew (int_addr(0x10) + 0, saved_int10_offset);
|
|
sas_storew (int_addr(0x10) + 2, saved_int10_segment);
|
|
#endif
|
|
/*
|
|
* Return success status and old INT33h vector
|
|
*/
|
|
*m1 = 0x1F;
|
|
*m2 = saved_int33_offset;
|
|
*m3 = saved_int33_segment;
|
|
}else{
|
|
/*
|
|
* Return failure
|
|
*/
|
|
*m1 = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL void mouse_driver_enable IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function re-enables the mouse driver after a call to
|
|
* function 31 (disable mouse driver).
|
|
*/
|
|
word hook_offset;
|
|
half_word interrupt_mask_register;
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_driver_enable()");
|
|
|
|
/*
|
|
* This prevents an endless loop of calls to mouse_video_io() if an
|
|
* application does a Mouse Driver Enable without first having done
|
|
* a Mouse Driver Disable
|
|
*/
|
|
if (!mouse_driver_disabled)
|
|
return;
|
|
|
|
mouse_driver_disabled = FALSE;
|
|
|
|
/*
|
|
* Reload bus mouse hardware interrupt
|
|
*/
|
|
|
|
#ifdef NTVDM
|
|
sas_loadw (int_addr(0x71) + 0, &saved_int71_offset);
|
|
sas_loadw (int_addr(0x71) + 2, &saved_int71_segment);
|
|
sas_storew(int_addr(0x71), MOUSE_INT1_OFFSET);
|
|
sas_storew(int_addr(0x71) + 2, MOUSE_INT1_SEGMENT);
|
|
#else
|
|
sas_loadw (int_addr(MOUSE_VEC) + 0, &saved_int0A_offset);
|
|
sas_loadw (int_addr(MOUSE_VEC) + 2, &saved_int0A_segment);
|
|
sas_storew(int_addr(MOUSE_VEC), MOUSE_INT1_OFFSET);
|
|
sas_storew(int_addr(MOUSE_VEC) + 2, MOUSE_INT1_SEGMENT);
|
|
#endif
|
|
|
|
/*
|
|
* Enable mouse hardware interrupts in the ica
|
|
*/
|
|
inb(ICA1_PORT_1, &interrupt_mask_register);
|
|
interrupt_mask_register &= ~(1 << AT_CPU_MOUSE_INT);
|
|
outb(ICA1_PORT_1, interrupt_mask_register);
|
|
inb(ICA0_PORT_1, &interrupt_mask_register);
|
|
interrupt_mask_register &= ~(1 << CPU_MOUSE_INT);
|
|
outb(ICA0_PORT_1, interrupt_mask_register);
|
|
|
|
/*
|
|
* Mouse io user interrupt
|
|
*/
|
|
|
|
#ifndef NTVDM
|
|
/* Read offset of INT 33 procedure from MOUSE.COM */
|
|
sas_loadw(effective_addr(getCS(), OFF_HOOK_POSN), &hook_offset);
|
|
|
|
sas_storew(int_addr(0x33), hook_offset);
|
|
sas_storew(int_addr(0x33) + 2, getCS());
|
|
|
|
/*
|
|
* Mouse video io user interrupt
|
|
*/
|
|
sas_loadw (int_addr(0x10) + 0, &saved_int10_offset);
|
|
sas_loadw (int_addr(0x10) + 2, &saved_int10_segment);
|
|
sas_storew(int_addr(0x10), MOUSE_VIDEO_IO_OFFSET);
|
|
sas_storew(int_addr(0x10) + 2, MOUSE_VIDEO_IO_SEGMENT);
|
|
#endif /* NTVDM */
|
|
}
|
|
|
|
|
|
LOCAL void mouse_set_language IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function is only applicable to an international version
|
|
* of a mouse driver... which this is not! Acts as a NOP.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_set_language()");
|
|
/* NOP */
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_language IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function is only meaningful on an international version
|
|
* of a mouse driver... which this is not! Always returns 0
|
|
* (English).
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_get_language()");
|
|
|
|
*m2 = 0;
|
|
|
|
note_trace1(MOUSE_VERBOSE,
|
|
"mouse_io: mouse_get_language returning m2=0x%04x.", *m2);
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_info IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function obtains certain information about the mouse
|
|
* driver and hardware.
|
|
*/
|
|
UNUSED(m1);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: mouse_get_info()");
|
|
|
|
*m2 = ((word)mouse_emulated_release << 8) | (word)mouse_emulated_version;
|
|
*m3 = ((word)MOUSE_TYPE_INPORT << 8) | (word)CPU_MOUSE_INT;
|
|
|
|
note_trace2(MOUSE_VERBOSE,
|
|
"mouse_io: mouse_get_info returning m2=0x%04x, m3=0x%04x.",
|
|
*m2, *m3);
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_driver_info IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
*m1 = (current_video_mode > 3 ? 0x2000 : 0) | 0x100;
|
|
/* bit 15 = 0 for COM v SYS
|
|
bit 14 = 0 for original non-integrated type
|
|
bit 13 is 1 for graphics cursor or 0 for text
|
|
bit 12 = 0 for software cursor
|
|
bits 8-11 are encoded interrupt rate, 1 means 30 Hz
|
|
bits 0-7 used only by integrated driver
|
|
*/
|
|
*m2 = 0; /* fCursorLock, used by driver under OS/2 */
|
|
*m3 = 0; /* fInMouseCode, flag for current execution path
|
|
being inside mouse driver under OS/2. Since the
|
|
driver is in a bop it can't be interrupted */
|
|
*m4 = 0; /* fMouseBusy, similar to *m3 */
|
|
}
|
|
|
|
|
|
LOCAL void mouse_get_max_coords IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
#ifdef NTVDM
|
|
IMPORT word VirtualX, VirtualY;
|
|
#endif
|
|
|
|
UNUSED(m1);
|
|
|
|
#ifdef NTVDM
|
|
*m3 = VirtualX;
|
|
*m4 = VirtualY;
|
|
#endif
|
|
|
|
*m2 = mouse_driver_disabled;
|
|
|
|
#ifndef NTVDM
|
|
get_screen_size();
|
|
*m3 = virtual_screen.bottom_right.x - 1;
|
|
*m4 = virtual_screen.bottom_right.y - 1;
|
|
#endif
|
|
}
|
|
|
|
LOCAL void mouse_get_masks_and_mickeys IFN4
|
|
(
|
|
MOUSE_SCREEN_DATA *, screen_mask_ptr,
|
|
MOUSE_SCREEN_DATA *, cursor_mask_ptr,
|
|
MOUSE_SCALAR *, raw_horiz_count_ptr,
|
|
MOUSE_SCALAR *, raw_vert_count_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 39: Get Screen/Cursor Masks and Mickey Counts.
|
|
*/
|
|
word cursor_mode;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: get_masks_and_mickeys");
|
|
|
|
/* read and reset counts */
|
|
*raw_horiz_count_ptr = mouse_raw_motion.x;
|
|
*raw_vert_count_ptr = mouse_raw_motion.y;
|
|
mouse_raw_motion.x = mouse_raw_motion.y = 0;
|
|
|
|
if ( text_cursor_type == MOUSE_TEXT_CURSOR_TYPE_SOFTWARE )
|
|
{
|
|
*screen_mask_ptr = software_text_cursor.screen;
|
|
*cursor_mask_ptr = software_text_cursor.cursor;
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse_io: return(screen=0x%x, mask=0x%x, raw mickeys=(%d,%d))",
|
|
*screen_mask_ptr,
|
|
*cursor_mask_ptr,
|
|
*raw_horiz_count_ptr,
|
|
*raw_vert_count_ptr);
|
|
}
|
|
else
|
|
{
|
|
/* Read BIOS data variable */
|
|
sas_loadw((sys_addr)VID_CURMOD, &cursor_mode);
|
|
|
|
/* Then extract start and stop from it */
|
|
*screen_mask_ptr = cursor_mode >> 8; /* start */
|
|
*cursor_mask_ptr = cursor_mode & 0xff; /* stop */
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse_io: return(start=%d, stop=%d, raw mickeys=(%d,%d))",
|
|
*screen_mask_ptr,
|
|
*cursor_mask_ptr,
|
|
*raw_horiz_count_ptr,
|
|
*raw_vert_count_ptr);
|
|
}
|
|
}
|
|
|
|
LOCAL void mouse_set_video_mode IFN4
|
|
(
|
|
word *, m1,
|
|
word *, m2,
|
|
word *, video_mode_ptr,
|
|
word *, font_size_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 40 Set Video Mode. NB. This only sets the mouse state to
|
|
match the video mode. Actual changes to the video mode are still
|
|
made by the application calling the BIOS.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
|
|
note_trace2(MOUSE_VERBOSE,
|
|
"mouse_io: set_video_mode(mode=0x%x, font size=0x%x)",
|
|
*video_mode_ptr, *font_size_ptr);
|
|
|
|
/* Check validity of mode */
|
|
if ( is_bad_vid_mode(*video_mode_ptr) && !is_v7vga_mode(*video_mode_ptr) )
|
|
{
|
|
/* Bad mode do nothing */
|
|
;
|
|
}
|
|
else
|
|
{
|
|
/* Update our parameters, as per the given mode */
|
|
current_video_mode = *video_mode_ptr;
|
|
|
|
mouse_adjust_screen_size();
|
|
|
|
cursor_undisplay();
|
|
cursor_flag = MOUSE_CURSOR_DEFAULT;
|
|
cursor_mode_change(current_video_mode);
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
/* Remember whether in text or graphics mode for later use. */
|
|
is_graphics_mode = ((current_video_mode > 3) &&
|
|
(current_video_mode != 7));
|
|
#endif /* MOUSE_16_BIT */
|
|
|
|
*video_mode_ptr = 0; /* Indicate success */
|
|
}
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io: return(mode=0x%x)",
|
|
*video_mode_ptr);
|
|
}
|
|
|
|
LOCAL void mouse_enumerate_video_modes IFN4
|
|
(
|
|
word *, m1,
|
|
word *, m2,
|
|
word *, video_nr_ptr,
|
|
word *, offset_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 41 Enumerate Video Modes.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io: enumerate_video_modes(mode=0x%x)", *video_nr_ptr);
|
|
|
|
/* Do they want to reset to first entry */
|
|
if ( *video_nr_ptr == 0 )
|
|
{
|
|
next_video_mode = 1; /* Yes */
|
|
}
|
|
|
|
/* Blindly try all possible mode settings */
|
|
while ( next_video_mode <= MAX_NR_VIDEO_MODES )
|
|
{
|
|
if ( is_bad_vid_mode(next_video_mode) && !is_v7vga_mode(next_video_mode) )
|
|
{
|
|
next_video_mode++; /* keep searching */
|
|
}
|
|
else
|
|
{
|
|
break; /* stop searching as valid mode has been found */
|
|
}
|
|
}
|
|
|
|
/* Action setting found, or end of list */
|
|
if ( next_video_mode > MAX_NR_VIDEO_MODES )
|
|
{
|
|
*video_nr_ptr = 0;
|
|
}
|
|
else
|
|
{
|
|
*video_nr_ptr = next_video_mode;
|
|
next_video_mode++; /* update for next call */
|
|
}
|
|
|
|
/* We don't provide string descriptions */
|
|
setES(0);
|
|
*offset_ptr = 0;
|
|
|
|
note_trace3(MOUSE_VERBOSE, "mouse_io: return(mode=0x%x, seg=0x%x, off=0x%x)",
|
|
*video_nr_ptr, getES(), *offset_ptr);
|
|
}
|
|
|
|
LOCAL void mouse_get_cursor_hot_spot IFN4
|
|
(
|
|
word *, fCursor_ptr,
|
|
MOUSE_SCALAR *, hot_spot_x_ptr,
|
|
MOUSE_SCALAR *, hot_spot_y_ptr,
|
|
word *, mouse_type_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 42: Return cursor hot spot location, the type of mouse in
|
|
use, and the internal counter that controls cursor visibility.
|
|
*/
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: get_cursor_hot_spot");
|
|
|
|
*fCursor_ptr = (word)cursor_flag;
|
|
|
|
*hot_spot_x_ptr = graphics_cursor.hot_spot.x;
|
|
*hot_spot_y_ptr = graphics_cursor.hot_spot.y;
|
|
|
|
*mouse_type_ptr = MOUSE_TYPE_INPORT;
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse_io: return(cursor flag = %d, hotspot = (%d,%d), type = %d)",
|
|
*fCursor_ptr,
|
|
*hot_spot_x_ptr, *hot_spot_y_ptr,
|
|
*mouse_type_ptr);
|
|
}
|
|
|
|
/* Load acceleration curve from Intel memory to Host memory */
|
|
LOCAL void load_acceleration_curve IFN3
|
|
(
|
|
word, seg, /* Pointer to Intel Memory */
|
|
word, off,
|
|
ACCELERATION_CURVE_DATA *, hcurve /* Pointer to Host Memory */
|
|
)
|
|
{
|
|
int i, j;
|
|
|
|
/* Read lengths */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
hcurve->ac_length[i] = sas_hw_at(effective_addr(seg, off));
|
|
off++;
|
|
}
|
|
|
|
/* Read mickey counts */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
for (j = 0; j < NR_ACCL_MICKEY_COUNTS; j++)
|
|
{
|
|
hcurve->ac_count[i][j] = sas_hw_at(effective_addr(seg, off));
|
|
off++;
|
|
}
|
|
}
|
|
|
|
/* Read scale factors */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
for (j = 0; j < NR_ACCL_SCALE_FACTORS; j++)
|
|
{
|
|
hcurve->ac_scale[i][j] = sas_hw_at(effective_addr(seg, off));
|
|
off++;
|
|
}
|
|
}
|
|
|
|
/* Read names */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
for (j = 0; j < NR_ACCL_NAME_CHARS; j++)
|
|
{
|
|
hcurve->ac_name[i][j] = sas_hw_at(effective_addr(seg, off));
|
|
off++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Store acceleration curve from Host memory to Intel memory */
|
|
LOCAL void store_acceleration_curve IFN3
|
|
(
|
|
word, seg, /* Pointer to Intel Memory */
|
|
word, off,
|
|
ACCELERATION_CURVE_DATA *, hcurve /* Pointer to Host Memory */
|
|
)
|
|
{
|
|
int i, j;
|
|
|
|
/* Write lengths */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
sas_store(effective_addr(seg, off), hcurve->ac_length[i]);
|
|
off++;
|
|
}
|
|
|
|
/* Write mickey counts */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
for (j = 0; j < NR_ACCL_MICKEY_COUNTS; j++)
|
|
{
|
|
sas_store(effective_addr(seg, off), hcurve->ac_count[i][j]);
|
|
off++;
|
|
}
|
|
}
|
|
|
|
/* Write scale factors */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
for (j = 0; j < NR_ACCL_SCALE_FACTORS; j++)
|
|
{
|
|
sas_store(effective_addr(seg, off), hcurve->ac_scale[i][j]);
|
|
off++;
|
|
}
|
|
}
|
|
|
|
/* Write names */
|
|
for (i = 0; i < NR_ACCL_CURVES; i++)
|
|
{
|
|
for (j = 0; j < NR_ACCL_NAME_CHARS; j++)
|
|
{
|
|
sas_store(effective_addr(seg, off), hcurve->ac_name[i][j]);
|
|
off++;
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCAL void mouse_load_acceleration_curves IFN4
|
|
(
|
|
word *, success_ptr,
|
|
word *, curve_ptr,
|
|
word *, m3,
|
|
word *, m4
|
|
)
|
|
{
|
|
/*
|
|
Func 43: Load Acceleration Curves.
|
|
*/
|
|
|
|
word c_seg;
|
|
word c_off;
|
|
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace1(MOUSE_VERBOSE,
|
|
"mouse_io: load_acceleration_curve(curve=%d)", *curve_ptr);
|
|
|
|
/* Check reason for call */
|
|
if ( *curve_ptr == MOUSE_M1 )
|
|
{
|
|
/* Reset to default acceleration curve */
|
|
active_acceleration_curve = 3; /* Back to Normal */
|
|
|
|
memcpy(&acceleration_curve_data, &default_acceleration_curve,
|
|
sizeof(ACCELERATION_CURVE_DATA));
|
|
|
|
*success_ptr = 0; /* Completed OK */
|
|
}
|
|
else
|
|
{
|
|
/* Load new curve */
|
|
if ( *curve_ptr >= 1 && *curve_ptr <= 4 )
|
|
{
|
|
/* Valid curve number - load it. */
|
|
active_acceleration_curve = *curve_ptr;
|
|
|
|
c_seg = getES(); /* Pick up pointer to Intel Data */
|
|
c_off = getSI();
|
|
|
|
/* INTEL => HOST */
|
|
load_acceleration_curve(c_seg, c_off, &acceleration_curve_data);
|
|
|
|
*success_ptr = 0; /* Completed OK */
|
|
}
|
|
else
|
|
{
|
|
/* Curve number out of range */
|
|
*success_ptr = MOUSE_M1;
|
|
}
|
|
}
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io: return(success=0x%x)", *success_ptr);
|
|
}
|
|
|
|
LOCAL void mouse_read_acceleration_curves IFN4
|
|
(
|
|
word *, success_ptr,
|
|
word *, curve_ptr,
|
|
word *, m3,
|
|
word *, m4
|
|
)
|
|
{
|
|
/*
|
|
Func 44: Read Acceleration Curves.
|
|
*/
|
|
|
|
word c_seg;
|
|
word c_off;
|
|
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: read_acceleration_curves");
|
|
|
|
*success_ptr = 0; /* Completed OK */
|
|
|
|
*curve_ptr = active_acceleration_curve;
|
|
|
|
c_seg = getCS(); /* Set up pointer to Intel Buffer */
|
|
c_off = OFF_ACCL_BUFFER;
|
|
|
|
/* INTEL <= HOST */
|
|
store_acceleration_curve(c_seg, c_off, &acceleration_curve_data);
|
|
|
|
setES(c_seg);
|
|
setSI(c_off);
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse_io: return(success=0x%x, curve=%d, seg=0x%x, off=0x%x)",
|
|
*success_ptr, *curve_ptr, getES(), getSI());
|
|
}
|
|
|
|
LOCAL void mouse_set_get_active_acceleration_curve IFN4
|
|
(
|
|
word *, success_ptr,
|
|
word *, curve_ptr,
|
|
word *, m3,
|
|
word *, m4
|
|
)
|
|
{
|
|
/*
|
|
Func 45: Set/Get Active Acceleration Curve.
|
|
*/
|
|
|
|
word c_seg;
|
|
word c_off;
|
|
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace1(MOUSE_VERBOSE,
|
|
"mouse_io: set_get_active_acceleration_curve(curve=%d)", *curve_ptr);
|
|
|
|
/* Check reason for call */
|
|
if ( *curve_ptr == MOUSE_M1 )
|
|
{
|
|
/* Return currently active curve */
|
|
*curve_ptr = active_acceleration_curve;
|
|
*success_ptr = 0; /* Completed OK */
|
|
}
|
|
else
|
|
{
|
|
/* Set new active curve */
|
|
if ( *curve_ptr >= 1 && *curve_ptr <= 4 )
|
|
{
|
|
/* Valid curve number - make active */
|
|
active_acceleration_curve = *curve_ptr;
|
|
*success_ptr = 0; /* Completed OK */
|
|
}
|
|
else
|
|
{
|
|
*curve_ptr = active_acceleration_curve;
|
|
*success_ptr = MOUSE_M2; /* Failed */
|
|
}
|
|
}
|
|
|
|
/* Return name to caller */
|
|
c_seg = getCS(); /* Set up pointer to Intel Buffer */
|
|
c_off = OFF_ACCL_BUFFER;
|
|
|
|
/* INTEL <= HOST */
|
|
store_acceleration_curve(c_seg, c_off, &acceleration_curve_data);
|
|
|
|
/* adjust pointer to select correct name */
|
|
c_off = c_off + 4 + (4*32) + (4*32); /* length,count,scale */
|
|
c_off = c_off + ((active_acceleration_curve-1) * 16);
|
|
|
|
setES(c_seg);
|
|
setSI(c_off);
|
|
|
|
note_trace4(MOUSE_VERBOSE,
|
|
"mouse_io: return(success=0x%x, curve=%d, seg=0x%x, off=0x%x)",
|
|
*success_ptr, *curve_ptr, getES(), getSI());
|
|
}
|
|
|
|
LOCAL void mouse_microsoft_internal IFN4
|
|
(
|
|
word *, m1,
|
|
word *, m2,
|
|
word *, m3,
|
|
word *, m4
|
|
)
|
|
{
|
|
/*
|
|
Func 46: Microsoft Internal. We don't support it.
|
|
*/
|
|
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: microsoft_internal NOT SUPPORTED!");
|
|
}
|
|
|
|
LOCAL void mouse_hardware_reset IFN4
|
|
(
|
|
word *, status_ptr,
|
|
word *, m2,
|
|
word *, m3,
|
|
word *, m4
|
|
)
|
|
{
|
|
/*
|
|
Func 47: Reset the mouse hardware and display variables.
|
|
This is not a full software reset as per Func 0 or Func 33.
|
|
*/
|
|
|
|
half_word crt_mode;
|
|
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: hardware_reset");
|
|
|
|
inport_reset(); /* reset hardware */
|
|
|
|
/* Update variables which depend on display hardware */
|
|
sas_load(MOUSE_VIDEO_CRT_MODE, &crt_mode);
|
|
cursor_mode_change((int)crt_mode);
|
|
cursor_update();
|
|
|
|
if ( cursor_flag == MOUSE_CURSOR_DISPLAYED )
|
|
cursor_display();
|
|
|
|
*status_ptr = MOUSE_M1; /* ie success */
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: return()");
|
|
}
|
|
|
|
LOCAL void mouse_set_get_ballpoint_info IFN4
|
|
(
|
|
word *, status_ptr,
|
|
word *, rotation_angle_ptr,
|
|
word *, button_mask_ptr,
|
|
word *, m4
|
|
)
|
|
{
|
|
/*
|
|
Func 48: Get/Set Ballpoint Information.
|
|
Note: We do not support a ballpoint device.
|
|
*/
|
|
|
|
UNUSED(m4);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: set_get_ballpoint_info");
|
|
|
|
if ( *button_mask_ptr == 0 ) /* Check command request */
|
|
{
|
|
/* Get Status (Angle and Mask) Command */
|
|
;
|
|
}
|
|
else
|
|
{
|
|
/* Set Status (Angle and Mask) Command */
|
|
note_trace2(MOUSE_VERBOSE,
|
|
"mouse_io: Rotation Angle = %d, Button Mask = %d",
|
|
*rotation_angle_ptr,
|
|
*button_mask_ptr);
|
|
}
|
|
|
|
*status_ptr = MOUSE_M1; /* ie not supported */
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: return(NOT_SUPPORTED)");
|
|
}
|
|
|
|
LOCAL void mouse_get_min_max_virtual_coords IFN4
|
|
(
|
|
MOUSE_SCALAR *, min_x_ptr,
|
|
MOUSE_SCALAR *, min_y_ptr,
|
|
MOUSE_SCALAR *, max_x_ptr,
|
|
MOUSE_SCALAR *, max_y_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 49: Return minimum and maximum virtual coordinates for
|
|
current screen mode. The values are those set by Funcs 7 and 8.
|
|
*/
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: get_min_max_virtual_coords");
|
|
|
|
*min_x_ptr = cursor_window.top_left.x;
|
|
*min_y_ptr = cursor_window.top_left.y;
|
|
*max_x_ptr = cursor_window.bottom_right.x;
|
|
*max_y_ptr = cursor_window.bottom_right.y;
|
|
|
|
note_trace4(MOUSE_VERBOSE, "mouse_io: return(min=(%d,%d), max=(%d,%d))",
|
|
*min_x_ptr, *min_y_ptr,
|
|
*max_x_ptr, *max_y_ptr);
|
|
}
|
|
|
|
LOCAL void mouse_get_active_advanced_functions IFN4
|
|
(
|
|
word *, active_flag1_ptr,
|
|
word *, active_flag2_ptr,
|
|
word *, active_flag3_ptr,
|
|
word *, active_flag4_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 50: Get Active Advanced Functions, ie define which functions
|
|
above or equal to 37 are supported.
|
|
*/
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: get_active_advanced_functions");
|
|
|
|
*active_flag1_ptr = 0x8000 | /* Func 37 supported */
|
|
0x4000 | /* Func 38 supported */
|
|
0x2000 | /* Func 39 supported */
|
|
0x1000 | /* Func 40 supported */
|
|
0x0800 | /* Func 41 supported */
|
|
0x0400 | /* Func 42 supported */
|
|
0x0200 | /* Func 43 supported */
|
|
0x0100 | /* Func 44 supported */
|
|
0x0080 | /* Func 45 supported */
|
|
0x0000 | /* Func 46 NOT supported */
|
|
0x0020 | /* Func 47 supported */
|
|
0x0010 | /* Func 48 supported */
|
|
0x0008 | /* Func 49 supported */
|
|
0x0004 | /* Func 50 supported */
|
|
0x0002 | /* Func 51 supported */
|
|
0x0001; /* Func 52 supported */
|
|
|
|
/* No other (ie newer) functions are supported */
|
|
*active_flag2_ptr = *active_flag3_ptr = *active_flag4_ptr = 0;
|
|
|
|
note_trace4(MOUSE_VERBOSE, "mouse_io: return(active=%04x,%04x,%04x,%04x)",
|
|
*active_flag1_ptr,
|
|
*active_flag2_ptr,
|
|
*active_flag3_ptr,
|
|
*active_flag4_ptr);
|
|
}
|
|
|
|
LOCAL void mouse_get_switch_settings IFN4
|
|
(
|
|
word *, status_ptr,
|
|
word *, m2,
|
|
word *, buffer_length_ptr,
|
|
word *, offset_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 51: Get switch settings. Returns output buffer (340 bytes)
|
|
with:-
|
|
|
|
0 Mouse Type (low nibble) 0-5
|
|
Mouse Port (high nibble) 0-4
|
|
1 Language 0-8
|
|
2 Horizontal Sensitivity 0-100
|
|
3 Vertical Sensitivity 0-100
|
|
4 Double Threshold 0-100
|
|
5 Ballistic Curve 1-4
|
|
6 Interrupt Rate 1-4
|
|
7 Cursor Override Mask 0-255
|
|
8 Laptop Adjustment 0-255
|
|
9 Memory Type 0-2
|
|
10 Super VGA Support 0-1
|
|
11 Rotation Angle 0-359
|
|
13 Primary Button 1-4
|
|
14 Secondary Button 1-4
|
|
15 Click Lock Enabled 0-1
|
|
16 Acceleration Curve Data
|
|
*/
|
|
|
|
word obuf_seg;
|
|
word obuf_off;
|
|
half_word mem_int_type;
|
|
|
|
UNUSED(m2);
|
|
|
|
note_trace3(MOUSE_VERBOSE,
|
|
"mouse_io: get_switch_settings(seg=0x%04x,off=0x%04x,len=0x%x)",
|
|
getES(), *offset_ptr, *buffer_length_ptr);
|
|
|
|
if ( *buffer_length_ptr == 0 )
|
|
{
|
|
/* Undocumented method of just finding buffer size */
|
|
*buffer_length_ptr = 340;
|
|
}
|
|
else
|
|
{
|
|
*buffer_length_ptr = 340;
|
|
|
|
obuf_seg = getES(); /* Pick up pointer to output buffer */
|
|
obuf_off = *offset_ptr;
|
|
|
|
/* Store MouseType and MousePort(=0) */
|
|
sas_store(effective_addr(obuf_seg, obuf_off),
|
|
(half_word)MOUSE_TYPE_INPORT);
|
|
|
|
/* Store Language (always 0) */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 1)),
|
|
(half_word)0);
|
|
|
|
/* Store Horizontal and Vertical Sensitivity */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 2)),
|
|
(half_word)mouse_sens.x);
|
|
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 3)),
|
|
(half_word)mouse_sens.y);
|
|
|
|
/* Store Double Threshold */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 4)),
|
|
(half_word)mouse_double_thresh);
|
|
|
|
/* Store Ballistic Curve */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 5)),
|
|
(half_word)active_acceleration_curve);
|
|
|
|
/* Store Interrupt Rate */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 6)),
|
|
(half_word)mouse_interrupt_rate);
|
|
|
|
/* Store Cursor Override Mask */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 7)),
|
|
(half_word)0); /* Microsoft Specific Feature? */
|
|
|
|
/* Store Laptop Adjustment */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 8)),
|
|
(half_word)0); /* What is it? */
|
|
|
|
/* Store Memory Type */
|
|
/* NB 0 = Low, 1 = High, 2 = Extended */
|
|
mem_int_type = 0;
|
|
|
|
if ( getCS() >= 0xA000 )
|
|
mem_int_type++;
|
|
|
|
if ( getCS() == 0xFFFF )
|
|
mem_int_type++;
|
|
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 9)),
|
|
mem_int_type);
|
|
|
|
/* Store Super VGA Support. - We don't support fancy hardware cursor */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 10)),
|
|
(half_word)0);
|
|
|
|
/* Store Rotation Angle */
|
|
sas_storew(effective_addr(obuf_seg, (obuf_off + 11)),
|
|
(half_word)0);
|
|
|
|
/* Store Primary Button */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 13)),
|
|
(half_word)1);
|
|
|
|
/* Store Secondary Button */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 14)),
|
|
(half_word)3);
|
|
|
|
/* Store Click Lock Enabled */
|
|
sas_store(effective_addr(obuf_seg, (obuf_off + 15)),
|
|
(half_word)0); /* What is it? */
|
|
|
|
/* Store Acceleration Curve Data */
|
|
store_acceleration_curve(obuf_seg, (obuf_off + 16),
|
|
&acceleration_curve_data);
|
|
}
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io: return(bytes_returned=0x%x)",
|
|
*buffer_length_ptr);
|
|
}
|
|
|
|
LOCAL void mouse_get_mouse_ini IFN4
|
|
(
|
|
word *, status_ptr,
|
|
word *, m2,
|
|
word *, m3,
|
|
word *, offset_ptr
|
|
)
|
|
{
|
|
/*
|
|
Func 52: Return Segment:Offset pointer to full pathname of
|
|
MOUSE.INI.
|
|
NB. As we do not support MOUSE.INI a pointer to a null string is
|
|
returned.
|
|
*/
|
|
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io: get_mouse_ini");
|
|
|
|
*status_ptr = 0;
|
|
|
|
*offset_ptr = OFF_MOUSE_INI_BUFFER;
|
|
setES(getCS());
|
|
|
|
note_trace2(MOUSE_VERBOSE, "mouse_io: return(seg=%04x,off=%04x)",
|
|
getES(), *offset_ptr);
|
|
}
|
|
|
|
LOCAL void mouse_unrecognised IFN4(word *,m1,word *,m2,word *,m3,word *,m4)
|
|
{
|
|
/*
|
|
* This function is called when an invalid mouse function
|
|
* number is found
|
|
*/
|
|
#ifndef PROD
|
|
int function = *m1;
|
|
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
|
|
fprintf(trace_file,
|
|
"mouse_io:unrecognised function(fn=%d)\n", function);
|
|
#else
|
|
UNUSED(m1);
|
|
UNUSED(m2);
|
|
UNUSED(m3);
|
|
UNUSED(m4);
|
|
#endif
|
|
}
|
|
|
|
|
|
LOCAL void mouse_set_double_speed IFN4(word *,junk1,word *,junk2,word *,junk3,word *,threshold_speed)
|
|
{
|
|
/*
|
|
* This function sets the threshold speed at which the cursor's
|
|
* motion on the screen doubles
|
|
*/
|
|
|
|
UNUSED(junk1);
|
|
UNUSED(junk2);
|
|
UNUSED(junk3);
|
|
|
|
note_trace1(MOUSE_VERBOSE, "mouse_io:set_double_speed(speed=%d)",
|
|
*threshold_speed);
|
|
|
|
/*
|
|
* Save the double speed threshold value, converting from
|
|
* Mickeys per second to a rounded Mickeys per timer interval
|
|
* value
|
|
*/
|
|
double_speed_threshold =
|
|
(*threshold_speed + MOUSE_TIMER_INTERRUPTS_PER_SECOND/2) /
|
|
MOUSE_TIMER_INTERRUPTS_PER_SECOND;
|
|
|
|
note_trace0(MOUSE_VERBOSE, "mouse_io:return()");
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* MOUSE DRIVER VIDEO ADAPTER ACCESS FUNCTIONS
|
|
* ===========================================
|
|
*/
|
|
|
|
LOCAL MOUSE_BYTE_ADDRESS point_as_text_cell_address IFN1(MOUSE_POINT *,point_ptr)
|
|
{
|
|
/*
|
|
* Return the byte offset of the character in the text mode regen
|
|
* buffer corresponding to the virtual screen position
|
|
* "*point_ptr"
|
|
*/
|
|
MOUSE_BYTE_ADDRESS byte_address;
|
|
word crt_start;
|
|
|
|
/*
|
|
* Get pc address for the start of video memory
|
|
*/
|
|
sas_loadw(MOUSE_VIDEO_CRT_START, &crt_start);
|
|
byte_address = (MOUSE_BYTE_ADDRESS)crt_start;
|
|
|
|
/*
|
|
* Adjust for current video page
|
|
*/
|
|
byte_address += cursor_page * video_page_size();
|
|
|
|
/*
|
|
* Add offset contributions for the cursor's row and column
|
|
*/
|
|
byte_address += (2*get_chars_per_line() * (point_ptr->y / cursor_grid.y));
|
|
byte_address += (point_ptr->x / cursor_grid.x) * 2;
|
|
|
|
return(byte_address);
|
|
}
|
|
|
|
LOCAL MOUSE_BIT_ADDRESS point_as_graphics_cell_address IFN1(MOUSE_POINT *,point_ptr)
|
|
{
|
|
/*
|
|
* Return the bit offset of the pixel in the graphics mode regen
|
|
* buffer (odd or even) bank corresponding to the virtual screen
|
|
* position "*point_ptr"
|
|
*/
|
|
IS32 bit_address;
|
|
|
|
/*
|
|
* Get offset contributions for the cursor's row and column
|
|
*/
|
|
bit_address = ((IS32)MOUSE_GRAPHICS_MODE_PITCH * (point_ptr->y / 2)) + point_ptr->x;
|
|
|
|
/*
|
|
* Adjust for current video page
|
|
*/
|
|
bit_address += (IS32)cursor_page * (IS32)video_page_size() * 8L;
|
|
|
|
return(bit_address);
|
|
}
|
|
|
|
#ifdef HERC
|
|
LOCAL MOUSE_BIT_ADDRESS point_as_HERC_graphics_cell_address IFN1(MOUSE_POINT *,point_ptr)
|
|
{
|
|
IMPORT half_word herc_page;
|
|
|
|
/*
|
|
* Return the bit offset of the pixel in the graphics mode regen
|
|
* buffer (0, 1, 2, 3) bank corresponding to the virtual screen
|
|
* position "*point_ptr"
|
|
*/
|
|
IS32 bit_address;
|
|
|
|
/*
|
|
* Get offset contributions for the cursor's row and column
|
|
*/
|
|
bit_address = ((IS32)720 * (point_ptr->y / 4)) + point_ptr->x;
|
|
|
|
/*
|
|
* Adjust for current video page - note that for 100% correct emulation,
|
|
* we should read location 40:49 (the BIOS video mode)... hercules
|
|
* applications put a 6 here to indicate page 0 and a 5 for page 1.
|
|
* To avoid a performance penalty the global herc_page is used instead;
|
|
* this will have the side effect of making application which try to
|
|
* set the mouse pointer to the non-displayed page not succeed in doing so.
|
|
*/
|
|
if (herc_page != 0){
|
|
bit_address += 0x8000L * 8L;
|
|
}
|
|
|
|
return(bit_address);
|
|
}
|
|
#endif /* HERC */
|
|
|
|
LOCAL MOUSE_BIT_ADDRESS ega_point_as_graphics_cell_address IFN1(MOUSE_POINT *,point_ptr)
|
|
{
|
|
/*
|
|
* Return the bit offset of the pixel in the graphics mode regen
|
|
* buffer corresponding to the virtual screen position "*point_ptr"
|
|
*/
|
|
MOUSE_BIT_ADDRESS bit_address;
|
|
UTINY video_mode = sas_hw_at(vd_video_mode);
|
|
|
|
/*
|
|
* Get offset contributions for the cursor's row and column
|
|
*/
|
|
#ifdef V7VGA
|
|
if (video_mode >= 0x40)
|
|
bit_address = (get_bytes_per_line() * 8 * point_ptr->y) + point_ptr->x;
|
|
else
|
|
#endif /* V7VGA */
|
|
switch(video_mode)
|
|
{
|
|
case 0xd :
|
|
bit_address = (get_actual_offset_per_line() * 8 * point_ptr->y) + point_ptr->x / 2;
|
|
break;
|
|
case 0x13 :
|
|
bit_address = (get_bytes_per_line() * 1 * point_ptr->y) + point_ptr->x / 2;
|
|
break;
|
|
default:
|
|
bit_address = (get_actual_offset_per_line() * 8 * point_ptr->y) + point_ptr->x;
|
|
}
|
|
|
|
/*
|
|
* Adjust for current video page
|
|
*/
|
|
bit_address += cursor_page * video_page_size() * 8;
|
|
|
|
return(bit_address);
|
|
}
|
|
|
|
|
|
LOCAL void cursor_update IFN0()
|
|
{
|
|
#ifndef NTVDM
|
|
/*
|
|
* This function is used to update the displayed cursor
|
|
* position on the screen following a change to the
|
|
* absolute position of the cursor
|
|
*/
|
|
|
|
point_coerce_to_area(&cursor_position, &cursor_window);
|
|
point_copy(&cursor_position, &cursor_status.position);
|
|
point_coerce_to_grid(&cursor_status.position, &cursor_grid);
|
|
|
|
if (host_mouse_in_use())
|
|
host_mouse_set_position(cursor_status.position.x * mouse_gear.x * mouse_sens.x / 800,
|
|
cursor_status.position.y * mouse_gear.y * mouse_sens.y / 800);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void cursor_display IFN0()
|
|
{
|
|
#ifndef NTVDM
|
|
UTINY v_mode;
|
|
|
|
/* Check if Enhanced Mode wants to "see" cursor */
|
|
if ( cursor_EM_disabled )
|
|
return;
|
|
|
|
/*
|
|
* Display a representation of the current mouse status on
|
|
* the screen
|
|
*/
|
|
|
|
v_mode = sas_hw_at(vd_video_mode);
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
if (is_graphics_mode)
|
|
return;
|
|
#endif /* MOUSE_16_BIT */
|
|
|
|
/*
|
|
* Remove the old representation of the
|
|
* cursor from the display
|
|
*/
|
|
cursor_undisplay();
|
|
|
|
#ifdef EGG
|
|
if (jap_mouse) {
|
|
/* So far DOS has had its way, but now we have to map the current
|
|
* cursor position in terms of mode 3 onto a mode 0x12 display.
|
|
* Go direct 'cos the selection process gets confused below...
|
|
*/
|
|
EGA_graphics_cursor_display();
|
|
} else
|
|
#endif /* EGG */
|
|
|
|
if (in_text_mode())
|
|
{
|
|
if (text_cursor_type == MOUSE_TEXT_CURSOR_TYPE_SOFTWARE)
|
|
{
|
|
software_text_cursor_display();
|
|
}
|
|
else
|
|
{
|
|
hardware_text_cursor_display();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef MOUSE_16_BIT
|
|
mouse16bShowPointer( );
|
|
#else /* MOUSE_16_BIT */
|
|
if (host_mouse_installed())
|
|
{
|
|
if ( cursor_position.x >= black_hole.top_left.x &&
|
|
cursor_position.x <= black_hole.bottom_right.x &&
|
|
cursor_position.y >= black_hole.top_left.y &&
|
|
cursor_position.y <= black_hole.bottom_right.y )
|
|
host_mouse_cursor_undisplay();
|
|
else
|
|
host_mouse_cursor_display();
|
|
}
|
|
else
|
|
{
|
|
#ifdef EGG
|
|
if ((video_adapter == EGA || video_adapter == VGA) && (v_mode > 6))
|
|
{
|
|
#ifdef VGG
|
|
if (v_mode != 0x13)
|
|
EGA_graphics_cursor_display();
|
|
else
|
|
VGA_graphics_cursor_display();
|
|
#else
|
|
EGA_graphics_cursor_display();
|
|
#endif /* VGG */
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef HERC
|
|
if (video_adapter == HERCULES)
|
|
HERC_graphics_cursor_display();
|
|
else
|
|
#endif /* HERC */
|
|
graphics_cursor_display();
|
|
}
|
|
#endif /* MOUSE_16_BIT */
|
|
}
|
|
|
|
/*
|
|
* Ensure the cursor is updated immediately on the real screen:
|
|
* this gives a "smooth" response to the mouse even on ports that
|
|
* don't automatically update the screen regularly
|
|
*/
|
|
host_flush_screen();
|
|
#endif /* !NTVDM */
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void cursor_undisplay IFN0()
|
|
{
|
|
#ifndef NTVDM
|
|
UTINY v_mode;
|
|
|
|
/* Check if Enhanced Mode wants to "see" cursor */
|
|
if ( cursor_EM_disabled )
|
|
return;
|
|
|
|
v_mode = sas_hw_at(vd_video_mode);
|
|
|
|
#ifdef MOUSE_16_BIT
|
|
if (is_graphics_mode)
|
|
return;
|
|
#endif /* MOUSE_16_BIT */
|
|
|
|
/*
|
|
* Undisplay the representation of the current mouse status on
|
|
* the screen. This routine tolerates being called when the
|
|
* cursor isn't actually being displayed
|
|
*/
|
|
if (host_mouse_in_use())
|
|
{
|
|
host_mouse_cursor_undisplay();
|
|
}
|
|
else
|
|
{
|
|
if (save_area_in_use)
|
|
{
|
|
save_area_in_use = FALSE;
|
|
|
|
#ifdef EGG
|
|
if (jap_mouse) {
|
|
/* If we forced an EGA cursor, we must undisplay the same.
|
|
* Go direct 'cos the selection process gets confused below...
|
|
*/
|
|
EGA_graphics_cursor_undisplay();
|
|
} else
|
|
#endif /* EGG */
|
|
|
|
if (in_text_mode())
|
|
{
|
|
if (text_cursor_type == MOUSE_TEXT_CURSOR_TYPE_SOFTWARE)
|
|
{
|
|
software_text_cursor_undisplay();
|
|
}
|
|
else
|
|
{
|
|
hardware_text_cursor_undisplay();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef MOUSE_16_BIT
|
|
mouse16bHidePointer( );
|
|
#else /* MOUSE_16_BIT */
|
|
#ifdef EGG
|
|
if ((video_adapter == EGA || video_adapter == VGA) && (v_mode > 6))
|
|
{
|
|
#ifdef VGG
|
|
if (v_mode != 0x13)
|
|
EGA_graphics_cursor_undisplay();
|
|
else
|
|
VGA_graphics_cursor_undisplay();
|
|
#else
|
|
EGA_graphics_cursor_undisplay();
|
|
#endif
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef HERC
|
|
if (video_adapter == HERCULES)
|
|
HERC_graphics_cursor_undisplay();
|
|
else
|
|
#endif /* HERC */
|
|
graphics_cursor_undisplay();
|
|
#endif /* MOUSE_16_BIT */
|
|
}
|
|
}
|
|
}
|
|
#endif /* !NTVDM */
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void cursor_mode_change IFN1(int,new_mode)
|
|
{
|
|
/*
|
|
* Update parameters that are dependent on the screen mode
|
|
* in force
|
|
*/
|
|
#ifdef V7VGA
|
|
if (new_mode >= 0x40)
|
|
if (new_mode >= 0x60)
|
|
{
|
|
point_copy(&v7graph_cursor_grids[new_mode-0x60], &cursor_grid);
|
|
point_copy(&v7graph_text_grids[new_mode-0x60], &text_grid);
|
|
}
|
|
else
|
|
{
|
|
point_copy(&v7text_cursor_grids[new_mode-0x40], &cursor_grid);
|
|
point_copy(&v7text_text_grids[new_mode-0x40], &text_grid);
|
|
}
|
|
else
|
|
#endif /* V7VGA */
|
|
{
|
|
point_copy(&cursor_grids[new_mode], &cursor_grid);
|
|
point_copy(&text_grids[new_mode], &text_grid);
|
|
}
|
|
/*
|
|
* Always set page to zero
|
|
*/
|
|
cursor_page = 0;
|
|
|
|
if (host_mouse_in_use())
|
|
host_mouse_cursor_mode_change();
|
|
}
|
|
|
|
|
|
|
|
|
|
GLOBAL void software_text_cursor_display IFN0()
|
|
{
|
|
/*
|
|
* Get the area the cursor will occupy on the
|
|
* screen, and display the cursor if its area
|
|
* overlaps the virtual screen and lies completely
|
|
* outside the conditional off area
|
|
*/
|
|
MOUSE_AREA cursor_area;
|
|
MOUSE_BYTE_ADDRESS text_address;
|
|
|
|
/*
|
|
* Get area cursor will cover on screen
|
|
*/
|
|
point_copy(&cursor_status.position, &cursor_area.top_left);
|
|
point_copy(&cursor_status.position, &cursor_area.bottom_right);
|
|
point_translate(&cursor_area.bottom_right, &cursor_grid);
|
|
|
|
if ( area_is_intersected_by_area(&virtual_screen, &cursor_area)
|
|
&& !area_is_intersected_by_area(&black_hole, &cursor_area))
|
|
{
|
|
/*
|
|
* Get new address for text cursor
|
|
* Should we look at video mode? Or is 0xb8000 OK?
|
|
*/
|
|
text_address = 0xb8000 + sas_w_at(VID_ADDR) +
|
|
point_as_text_cell_address(&cursor_area.top_left);
|
|
|
|
/*
|
|
* Save area text cursor will cover
|
|
*/
|
|
sas_loadw(text_address, &text_cursor_background);
|
|
save_area_in_use = TRUE;
|
|
point_copy(&cursor_area.top_left, &save_position);
|
|
|
|
/*
|
|
* Stuff masked screen data
|
|
*/
|
|
sas_storew(text_address,
|
|
(text_cursor_background & software_text_cursor.screen) ^
|
|
software_text_cursor.cursor);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
GLOBAL void software_text_cursor_undisplay IFN0()
|
|
{
|
|
/*
|
|
* Remove old text cursor
|
|
* Should we look at video mode? Or is 0xb8000 OK?
|
|
*/
|
|
MOUSE_BYTE_ADDRESS text_address;
|
|
|
|
text_address = 0xb8000 + sas_w_at(VID_ADDR) +
|
|
point_as_text_cell_address(&save_position);
|
|
|
|
/*
|
|
* Stuff restored data and alert gvi
|
|
*/
|
|
sas_storew(text_address, text_cursor_background);
|
|
}
|
|
|
|
|
|
|
|
|
|
GLOBAL void hardware_text_cursor_display IFN0()
|
|
{
|
|
/*
|
|
* Display a representation of the current mouse status on
|
|
* the screen using the hardware text cursor, provided the
|
|
* cursor overlaps the virtual screen. Since the hardware
|
|
* cursor display does not corrupt the Intel memory, it
|
|
* doesn't matter if the hardware cursor lies inside the
|
|
* conditional off area
|
|
*/
|
|
MOUSE_AREA cursor_area;
|
|
MOUSE_BYTE_ADDRESS text_address;
|
|
word card_address;
|
|
|
|
/*
|
|
* Get area cursor will cover on screen
|
|
*/
|
|
point_copy(&cursor_status.position, &cursor_area.top_left);
|
|
point_copy(&cursor_status.position, &cursor_area.bottom_right);
|
|
point_translate(&cursor_area.bottom_right, &cursor_grid);
|
|
|
|
if (area_is_intersected_by_area(&virtual_screen, &cursor_area))
|
|
{
|
|
/*
|
|
* Get address of the base register on the active display
|
|
* adaptor card
|
|
*/
|
|
sas_loadw(MOUSE_VIDEO_CARD_BASE, &card_address);
|
|
|
|
/*
|
|
* Get word offset of cursor position in the text mode
|
|
* regen buffer
|
|
*/
|
|
text_address =
|
|
point_as_text_cell_address(&cursor_status.position) / 2;
|
|
|
|
/*
|
|
* Output the cursor address high byte
|
|
*/
|
|
outb(card_address++, MOUSE_CURSOR_HIGH_BYTE);
|
|
outb(card_address--, text_address >> 8);
|
|
|
|
/*
|
|
* Output the cursor address low byte
|
|
*/
|
|
outb(card_address++, MOUSE_CURSOR_LOW_BYTE);
|
|
outb(card_address--, text_address);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
GLOBAL void hardware_text_cursor_undisplay IFN0()
|
|
{
|
|
/*
|
|
* Nothing to do
|
|
*/
|
|
}
|
|
|
|
|
|
#ifdef EGG
|
|
LOCAL EGA_graphics_cursor_display IFN0()
|
|
|
|
{
|
|
#ifdef REAL_VGA
|
|
#ifndef PROD
|
|
if (io_verbose & MOUSE_VERBOSE)
|
|
fprintf(trace_file, "oops - EGA graphics display cursor\n");
|
|
#endif /* PROD */
|
|
#else
|
|
/*
|
|
* Display a representation of the current mouse status on
|
|
* the screen using the graphics cursor, provided the
|
|
* cursor overlaps the virtual screen and lies completely
|
|
* outside the conditional off area
|
|
*/
|
|
MOUSE_BIT_ADDRESS bit_shift;
|
|
MOUSE_BYTE_ADDRESS byte_offset;
|
|
int line, line_max;
|
|
int byte_min, byte_max;
|
|
IU32 strip_lo, strip_mid, strip_hi;
|
|
IU32 mask_lo, mask_hi;
|
|
|
|
MOUSE_SCALAR saved_cursor_pos;
|
|
MOUSE_SCALAR saved_bottom_right;
|
|
|
|
if (jap_mouse) {
|
|
/* fake up the mode 0x12 cursor position, saving original */
|
|
saved_cursor_pos=cursor_status.position.y;
|
|
saved_bottom_right=virtual_screen.bottom_right.y;
|
|
|
|
cursor_status.position.y = saved_cursor_pos * 19 / 8;
|
|
virtual_screen.bottom_right.y = virtual_screen.bottom_right.y * 19 / 8;
|
|
}
|
|
|
|
/*
|
|
* Get area cursor will cover on screen
|
|
*/
|
|
point_copy(&cursor_status.position, &save_area.top_left);
|
|
point_copy(&cursor_status.position, &save_area.bottom_right);
|
|
point_translate(&save_area.bottom_right, &graphics_cursor.size);
|
|
point_translate_back(&save_area.top_left, &graphics_cursor.hot_spot);
|
|
point_translate_back(&save_area.bottom_right, &graphics_cursor.hot_spot);
|
|
|
|
if ( area_is_intersected_by_area(&virtual_screen, &save_area)
|
|
&& !area_is_intersected_by_area(&black_hole, &save_area))
|
|
{
|
|
/*
|
|
* Record save position and screen area
|
|
*/
|
|
save_area_in_use = TRUE;
|
|
area_coerce_to_area(&save_area, &virtual_screen);
|
|
point_copy(&save_area.top_left, &save_position);
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the
|
|
* regen buffer, and bit shift to apply
|
|
*/
|
|
byte_offset = ega_point_as_graphics_cell_address(&save_position);
|
|
bit_shift = byte_offset & 7;
|
|
byte_offset /= 8;
|
|
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
/*
|
|
* Get range of bytes that need to be displayed
|
|
*/
|
|
byte_min = 0;
|
|
byte_max = 2;
|
|
if (save_position.x < 0)
|
|
byte_min += (7 - save_position.x) / 8;
|
|
else
|
|
if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
byte_max -=
|
|
(8 + MOUSE_GRAPHICS_CURSOR_WIDTH - area_width(&save_area)) / 8;
|
|
|
|
if( bit_shift )
|
|
{
|
|
mask_lo = 0xff >> bit_shift;
|
|
mask_lo = ( mask_lo << 8 ) | mask_lo;
|
|
mask_lo = ~(( mask_lo << 16 ) | mask_lo);
|
|
|
|
mask_hi = 0xff >> bit_shift;
|
|
mask_hi = ( mask_hi << 8 ) | mask_hi;
|
|
mask_hi = ( mask_hi << 16 ) | mask_hi;
|
|
}
|
|
|
|
while (line < line_max)
|
|
{
|
|
if (bit_shift)
|
|
{
|
|
/*
|
|
* Get save area
|
|
*/
|
|
|
|
ega_backgrnd_lo[line] = *( (IU32 *) EGA_planes + byte_offset );
|
|
ega_backgrnd_mid[line] = *( (IU32 *) EGA_planes + byte_offset + 1 );
|
|
ega_backgrnd_hi[line] = *( (IU32 *) EGA_planes + byte_offset + 2 );
|
|
|
|
/*
|
|
* Overlay cursor line
|
|
*/
|
|
|
|
|
|
strip_lo = ega_backgrnd_lo[line] & mask_lo;
|
|
|
|
strip_lo |= ~mask_lo & (( ega_backgrnd_lo[line]
|
|
& ( graphics_cursor.screen_lo[line] >> bit_shift ))
|
|
^ ( graphics_cursor.cursor_lo[line] >> bit_shift ));
|
|
|
|
strip_mid = ~mask_hi & (( ega_backgrnd_mid[line]
|
|
& ( graphics_cursor.screen_lo[line] << (8 - bit_shift) ))
|
|
^ ( graphics_cursor.cursor_lo[line] << (8 - bit_shift) ));
|
|
|
|
strip_mid |= ~mask_lo & (( ega_backgrnd_mid[line]
|
|
& ( graphics_cursor.screen_hi[line] >> bit_shift ))
|
|
^ ( graphics_cursor.cursor_hi[line] >> bit_shift ));
|
|
|
|
strip_hi = ega_backgrnd_hi[line] & mask_hi;
|
|
|
|
strip_hi |= ~mask_hi & (( ega_backgrnd_hi[line]
|
|
& ( graphics_cursor.screen_hi[line] << (8 - bit_shift) ))
|
|
^ ( graphics_cursor.cursor_hi[line] << (8 - bit_shift) ));
|
|
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
*((IU32 *) EGA_planes + byte_offset) = strip_lo;
|
|
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
*((IU32 *) EGA_planes + byte_offset + 1) = strip_mid;
|
|
|
|
if (byte_min <= 2 && byte_max >= 2)
|
|
*((IU32 *) EGA_planes + byte_offset + 2) = strip_hi;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Get save area
|
|
*/
|
|
|
|
ega_backgrnd_lo[line] = *( (IU32 *) EGA_planes + byte_offset );
|
|
ega_backgrnd_hi[line] = *( (IU32 *) EGA_planes + byte_offset + 1 );
|
|
|
|
/*
|
|
* Create overlaid cursor line
|
|
*/
|
|
|
|
strip_lo = (ega_backgrnd_lo[line] &
|
|
graphics_cursor.screen_lo[line]) ^
|
|
graphics_cursor.cursor_lo[line];
|
|
|
|
strip_hi = (ega_backgrnd_hi[line] &
|
|
graphics_cursor.screen_hi[line]) ^
|
|
graphics_cursor.cursor_hi[line];
|
|
|
|
/*
|
|
* Draw cursor line
|
|
*/
|
|
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
*((IU32 *) EGA_planes + byte_offset) = strip_lo;
|
|
}
|
|
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
*((IU32 *) EGA_planes + byte_offset + 1) = strip_hi;
|
|
}
|
|
|
|
}
|
|
|
|
update_alg.mark_string(byte_offset, byte_offset + 2);
|
|
#ifdef V7VGA
|
|
if (sas_hw_at(vd_video_mode) >= 0x40)
|
|
byte_offset += get_bytes_per_line();
|
|
else
|
|
#endif /* V7VGA */
|
|
byte_offset += get_actual_offset_per_line();
|
|
line++;
|
|
}
|
|
if (jap_mouse) {
|
|
/* put things back how they should be */
|
|
cursor_status.position.y = saved_cursor_pos;
|
|
virtual_screen.bottom_right.y = saved_bottom_right;
|
|
}
|
|
}
|
|
#endif /* REAL_VGA */
|
|
}
|
|
|
|
|
|
LOCAL EGA_graphics_cursor_undisplay IFN0()
|
|
|
|
{
|
|
#ifdef REAL_VGA
|
|
#ifndef PROD
|
|
if (io_verbose & MOUSE_VERBOSE)
|
|
fprintf(trace_file, "oops - EGA graphics undisplay cursor\n");
|
|
#endif /* PROD */
|
|
#else
|
|
/*
|
|
* Remove the graphics cursor representation of the mouse
|
|
* status
|
|
*/
|
|
MOUSE_BIT_ADDRESS bit_shift;
|
|
MOUSE_BYTE_ADDRESS byte_offset;
|
|
int line, line_max;
|
|
int byte_min, byte_max;
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the
|
|
* even or odd bank, and bit shift to apply
|
|
*/
|
|
byte_offset = ega_point_as_graphics_cell_address(&save_position);
|
|
bit_shift = byte_offset & 7;
|
|
byte_offset /= 8;
|
|
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
|
|
/*
|
|
* Get range of bytes that need to be displayed
|
|
*/
|
|
byte_min = 0;
|
|
byte_max = 2;
|
|
if (save_position.x < 0)
|
|
byte_min += (7 - save_position.x) / 8;
|
|
else if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
byte_max -= (8 + MOUSE_GRAPHICS_CURSOR_WIDTH - area_width(&save_area)) / 8;
|
|
|
|
while(line < line_max)
|
|
{
|
|
/*
|
|
* Draw saved area
|
|
*/
|
|
|
|
if (bit_shift)
|
|
{
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
*((IU32 *) EGA_planes + byte_offset) = ega_backgrnd_lo[line];
|
|
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
*((IU32 *) EGA_planes + byte_offset + 1) = ega_backgrnd_mid[line];
|
|
|
|
if (byte_min <= 2 && byte_max >= 2)
|
|
*((IU32 *) EGA_planes + byte_offset + 2) = ega_backgrnd_hi[line];
|
|
}
|
|
else
|
|
{
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
*((IU32 *) EGA_planes + byte_offset) = ega_backgrnd_lo[line];
|
|
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
*((IU32 *) EGA_planes + byte_offset + 1) = ega_backgrnd_hi[line];
|
|
}
|
|
|
|
update_alg.mark_string(byte_offset, byte_offset + 2);
|
|
#ifdef V7VGA
|
|
if (sas_hw_at(vd_video_mode) >= 0x40)
|
|
byte_offset += get_bytes_per_line();
|
|
else
|
|
#endif /* V7VGA */
|
|
byte_offset += get_actual_offset_per_line();
|
|
line++;
|
|
}
|
|
#endif /* REAL_VGA */
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#ifdef VGG
|
|
LOCAL VOID VGA_graphics_cursor_display IFN0()
|
|
{
|
|
#ifdef REAL_VGA
|
|
#ifndef PROD
|
|
if (io_verbose & MOUSE_VERBOSE)
|
|
fprintf(trace_file, "oops - VGA graphics display cursor\n");
|
|
#endif /* PROD */
|
|
#else /* REAL_VGA */
|
|
|
|
MOUSE_BYTE_ADDRESS byte_offset;
|
|
SHORT line, line_max, index;
|
|
SHORT index_max = MOUSE_GRAPHICS_CURSOR_WIDTH;
|
|
USHORT scr_strip, cur_strip;
|
|
UTINY scr_byte, cur_byte;
|
|
USHORT mask;
|
|
|
|
|
|
/*
|
|
* Get area cursor will cover on screen
|
|
*/
|
|
point_copy(&cursor_status.position, &save_area.top_left);
|
|
point_copy(&cursor_status.position, &save_area.bottom_right);
|
|
point_translate(&save_area.bottom_right, &graphics_cursor.size);
|
|
point_translate_back(&save_area.top_left, &graphics_cursor.hot_spot);
|
|
point_translate_back(&save_area.bottom_right, &graphics_cursor.hot_spot);
|
|
|
|
if ( area_is_intersected_by_area(&virtual_screen, &save_area)
|
|
&& !area_is_intersected_by_area(&black_hole, &save_area))
|
|
{
|
|
/*
|
|
* Record save position and screen area
|
|
*/
|
|
save_area_in_use = TRUE;
|
|
area_coerce_to_area(&save_area, &virtual_screen);
|
|
point_copy(&save_area.top_left, &save_position);
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the
|
|
* regen buffer, and bit shift to apply
|
|
*/
|
|
byte_offset = ega_point_as_graphics_cell_address(&save_position);
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
|
|
if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
index_max = (area_width(&save_area));
|
|
|
|
while (line < line_max)
|
|
{
|
|
mask = 0x8000;
|
|
|
|
for(index=0;index<index_max;index++)
|
|
{
|
|
vga_background[line][index] = *(EGA_planes + byte_offset + index);
|
|
scr_strip = graphics_cursor.screen[line] & mask;
|
|
cur_strip = graphics_cursor.cursor[line] & mask;
|
|
if (scr_strip)
|
|
scr_byte = 0xff;
|
|
else
|
|
scr_byte = 0x0;
|
|
|
|
if (cur_strip)
|
|
cur_byte = 0x0f;
|
|
else
|
|
cur_byte = 0x0;
|
|
|
|
/*
|
|
* Draw cursor byte
|
|
*/
|
|
*(EGA_planes + byte_offset + index) =
|
|
( vga_background[line][index] & scr_byte) ^ cur_byte;
|
|
|
|
mask >>= 1;
|
|
}
|
|
|
|
update_alg.mark_string(byte_offset, byte_offset+index);
|
|
line++;
|
|
byte_offset += get_bytes_per_line();
|
|
|
|
}
|
|
}
|
|
#endif /* REAL_VGA */
|
|
}
|
|
|
|
LOCAL VOID VGA_graphics_cursor_undisplay IFN0()
|
|
{
|
|
#ifdef REAL_VGA
|
|
#ifndef PROD
|
|
if (io_verbose & MOUSE_VERBOSE)
|
|
fprintf(trace_file, "oops - VGA graphics undisplay cursor\n");
|
|
#endif /* PROD */
|
|
#else /* REAL_VGA */
|
|
|
|
/*
|
|
* Remove the graphics cursor representation of the mouse
|
|
* status
|
|
*/
|
|
MOUSE_BYTE_ADDRESS byte_offset;
|
|
SHORT index;
|
|
SHORT index_max = MOUSE_GRAPHICS_CURSOR_WIDTH;
|
|
int line, line_max;
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the EGA memory
|
|
*/
|
|
|
|
byte_offset = ega_point_as_graphics_cell_address(&save_position);
|
|
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
|
|
if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
index_max = (area_width(&save_area));
|
|
|
|
/*
|
|
* Get range of bytes that need to be displayed
|
|
*/
|
|
while (line < line_max)
|
|
{
|
|
for (index=0;index<index_max;index++)
|
|
*(EGA_planes + byte_offset + index) = vga_background[line][index];
|
|
|
|
|
|
update_alg.mark_string(byte_offset, byte_offset+index);
|
|
line++;
|
|
byte_offset += get_bytes_per_line();
|
|
}
|
|
|
|
#endif /* REAL_VGA */
|
|
}
|
|
|
|
#endif /* VGG */
|
|
|
|
|
|
LOCAL void graphics_cursor_display IFN0()
|
|
{
|
|
/*
|
|
* Display a representation of the current mouse status on
|
|
* the screen using the graphics cursor, provided the
|
|
* cursor overlaps the virtual screen and lies completely
|
|
* outside the conditional off area
|
|
*/
|
|
boolean even_scan_line;
|
|
MOUSE_BIT_ADDRESS bit_shift;
|
|
IS32 byte_offset;
|
|
sys_addr byte_address;
|
|
IU32 strip;
|
|
int line, line_max;
|
|
int byte_min, byte_max;
|
|
|
|
/*
|
|
* Get area cursor will cover on screen
|
|
*/
|
|
point_copy(&cursor_status.position, &save_area.top_left);
|
|
point_copy(&cursor_status.position, &save_area.bottom_right);
|
|
point_translate(&save_area.bottom_right, &graphics_cursor.size);
|
|
point_translate_back(&save_area.top_left, &graphics_cursor.hot_spot);
|
|
point_translate_back(&save_area.bottom_right, &graphics_cursor.hot_spot);
|
|
|
|
if ( area_is_intersected_by_area(&virtual_screen, &save_area)
|
|
&& !area_is_intersected_by_area(&black_hole, &save_area))
|
|
{
|
|
/*
|
|
* Record save position and screen area
|
|
*/
|
|
save_area_in_use = TRUE;
|
|
point_copy(&save_area.top_left, &save_position);
|
|
area_coerce_to_area(&save_area, &virtual_screen);
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the
|
|
* even or odd bank, and bit shift to apply
|
|
*/
|
|
even_scan_line = ((save_area.top_left.y % 2) == 0);
|
|
byte_offset = point_as_graphics_cell_address(&save_position);
|
|
bit_shift = byte_offset & 7;
|
|
byte_offset >>= 3;
|
|
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
|
|
/*
|
|
* Get range of bytes that need to be displayed
|
|
*/
|
|
byte_min = 0;
|
|
byte_max = 2;
|
|
if (save_position.x < 0)
|
|
byte_min += (7 - save_position.x) / 8;
|
|
else if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
byte_max -= (8 + MOUSE_GRAPHICS_CURSOR_WIDTH - area_width(&save_area)) / 8;
|
|
|
|
while (line < line_max)
|
|
{
|
|
if (even_scan_line)
|
|
{
|
|
even_scan_line = FALSE;
|
|
byte_address = EVEN_START + byte_offset;
|
|
}
|
|
else
|
|
{
|
|
even_scan_line = TRUE;
|
|
byte_address = ODD_START + byte_offset;
|
|
byte_offset += MOUSE_GRAPHICS_MODE_PITCH / 8;
|
|
}
|
|
|
|
if (bit_shift)
|
|
{
|
|
/*
|
|
* Get save area
|
|
*/
|
|
strip = (IU32)sas_hw_at(byte_address) << 16;
|
|
strip |= (unsigned short)sas_hw_at(byte_address+1) << 8;
|
|
strip |= sas_hw_at(byte_address+2);
|
|
graphics_cursor_background[line] =
|
|
strip >> (8 - bit_shift);
|
|
|
|
/*
|
|
* Overlay cursor line
|
|
*/
|
|
strip &= (SHIFT_VAL >> bit_shift);
|
|
strip |= (IU32)((graphics_cursor_background[line] &
|
|
graphics_cursor.screen[line]) ^
|
|
graphics_cursor.cursor[line])
|
|
<< (8 - bit_shift);
|
|
|
|
/*
|
|
* Stash cursor line
|
|
*/
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 16);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip >> 8);
|
|
}
|
|
if (byte_min <= 2 && byte_max >= 2)
|
|
{
|
|
sas_store(byte_address+2, strip);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Get save area
|
|
*/
|
|
graphics_cursor_background[line] = (sas_hw_at(byte_address) << 8) + sas_hw_at(byte_address+1);
|
|
|
|
/*
|
|
* Get overlaid cursor line
|
|
*/
|
|
strip = (graphics_cursor_background[line] &
|
|
graphics_cursor.screen[line]) ^
|
|
graphics_cursor.cursor[line];
|
|
|
|
/*
|
|
* Stash cursor line and alert gvi
|
|
*/
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 8);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip);
|
|
}
|
|
}
|
|
line++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef HERC
|
|
LOCAL void HERC_graphics_cursor_display IFN0()
|
|
{
|
|
/*
|
|
* Display a representation of the current mouse status on
|
|
* the screen using the graphics cursor, provided the
|
|
* cursor overlaps the virtual screen and lies completely
|
|
* outside the conditional off area
|
|
*/
|
|
int scan_line_mod;
|
|
MOUSE_BIT_ADDRESS bit_shift;
|
|
IS32 byte_offset;
|
|
sys_addr byte_address;
|
|
IU32 strip;
|
|
int line, line_max;
|
|
int byte_min, byte_max;
|
|
|
|
/*
|
|
* Get area cursor will cover on screen
|
|
*/
|
|
point_copy(&cursor_status.position, &save_area.top_left);
|
|
point_copy(&cursor_status.position, &save_area.bottom_right);
|
|
point_translate(&save_area.bottom_right, &graphics_cursor.size);
|
|
point_translate_back(&save_area.top_left, &graphics_cursor.hot_spot);
|
|
point_translate_back(&save_area.bottom_right, &graphics_cursor.hot_spot);
|
|
|
|
if ( area_is_intersected_by_area(&HERC_graphics_virtual_screen, &save_area)
|
|
&& !area_is_intersected_by_area(&black_hole, &save_area))
|
|
{
|
|
/*
|
|
* Record save position and screen area
|
|
*/
|
|
save_area_in_use = TRUE;
|
|
point_copy(&save_area.top_left, &save_position);
|
|
area_coerce_to_area(&save_area, &HERC_graphics_virtual_screen);
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the
|
|
* even or odd bank, and bit shift to apply
|
|
*/
|
|
scan_line_mod = save_area.top_left.y % 4;
|
|
byte_offset = point_as_HERC_graphics_cell_address(&save_position);
|
|
bit_shift = byte_offset & 7;
|
|
byte_offset >>= 3;
|
|
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
|
|
/*
|
|
* Get range of bytes that need to be displayed
|
|
*/
|
|
byte_min = 0;
|
|
byte_max = 2;
|
|
if (save_position.x < 0)
|
|
byte_min += (7 - save_position.x) / 8;
|
|
else if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
byte_max -= (8 + MOUSE_GRAPHICS_CURSOR_WIDTH - area_width(&save_area)) / 8;
|
|
|
|
while (line < line_max)
|
|
{
|
|
switch (scan_line_mod){
|
|
case 0:
|
|
scan_line_mod++;
|
|
byte_address = gvi_pc_low_regen + 0x0000 + byte_offset;
|
|
break;
|
|
case 1:
|
|
scan_line_mod++;
|
|
byte_address = gvi_pc_low_regen + 0x2000 + byte_offset;
|
|
break;
|
|
case 2:
|
|
scan_line_mod++;
|
|
byte_address = gvi_pc_low_regen + 0x4000 + byte_offset;
|
|
break;
|
|
case 3:
|
|
scan_line_mod=0;
|
|
byte_address = gvi_pc_low_regen + 0x6000 + byte_offset;
|
|
byte_offset += 720 / 8;
|
|
break;
|
|
}
|
|
|
|
if (bit_shift)
|
|
{
|
|
/*
|
|
* Get save area
|
|
*/
|
|
strip = (IU32)sas_hw_at(byte_address) << 16;
|
|
strip |= (unsigned short)sas_hw_at(byte_address+1) << 8;
|
|
strip |= sas_hw_at(byte_address+2);
|
|
graphics_cursor_background[line] =
|
|
strip >> (8 - bit_shift);
|
|
|
|
/*
|
|
* Overlay cursor line
|
|
*/
|
|
strip &= (SHIFT_VAL >> bit_shift);
|
|
strip |= (IU32)((graphics_cursor_background[line] &
|
|
graphics_cursor.screen[line]) ^
|
|
graphics_cursor.cursor[line])
|
|
<< (8 - bit_shift);
|
|
|
|
/*
|
|
* Stash cursor line and alert gvi
|
|
*/
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 16);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip >> 8);
|
|
}
|
|
if (byte_min <= 2 && byte_max >= 2)
|
|
{
|
|
sas_store(byte_address+2, strip);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Get save area
|
|
*/
|
|
graphics_cursor_background[line] = (sas_hw_at(byte_address) << 8) +
|
|
sas_hw_at(byte_address+1);
|
|
|
|
/*
|
|
* Get overlaid cursor line
|
|
*/
|
|
strip = (graphics_cursor_background[line] &
|
|
graphics_cursor.screen[line]) ^
|
|
graphics_cursor.cursor[line];
|
|
|
|
/*
|
|
* Stash cursor line and alert gvi
|
|
*/
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 8);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip);
|
|
}
|
|
}
|
|
line++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* HERC */
|
|
|
|
|
|
LOCAL void graphics_cursor_undisplay IFN0()
|
|
{
|
|
/*
|
|
* Remove the graphics cursor representation of the mouse
|
|
* status
|
|
*/
|
|
boolean even_scan_line;
|
|
MOUSE_BIT_ADDRESS bit_shift;
|
|
IS32 byte_offset;
|
|
sys_addr byte_address;
|
|
IU32 strip;
|
|
int line, line_max;
|
|
int byte_min, byte_max;
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the
|
|
* even or odd bank, and bit shift to apply
|
|
*/
|
|
even_scan_line = ((save_area.top_left.y % 2) == 0);
|
|
byte_offset = point_as_graphics_cell_address(&save_position);
|
|
bit_shift = byte_offset & 7;
|
|
byte_offset >>= 3;
|
|
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
|
|
/*
|
|
* Get range of bytes that need to be displayed
|
|
*/
|
|
byte_min = 0;
|
|
byte_max = 2;
|
|
if (save_position.x < 0)
|
|
byte_min += (7 - save_position.x) / 8;
|
|
else if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
byte_max -= (8 + MOUSE_GRAPHICS_CURSOR_WIDTH - area_width(&save_area)) / 8;
|
|
|
|
while(line < line_max)
|
|
{
|
|
if (even_scan_line)
|
|
{
|
|
even_scan_line = FALSE;
|
|
byte_address = EVEN_START + byte_offset;
|
|
}
|
|
else
|
|
{
|
|
even_scan_line = TRUE;
|
|
byte_address = ODD_START + byte_offset;
|
|
byte_offset += MOUSE_GRAPHICS_MODE_PITCH / 8;
|
|
}
|
|
|
|
if (bit_shift)
|
|
{
|
|
/*
|
|
* Get cursor line
|
|
*/
|
|
strip = (IU32)sas_hw_at(byte_address) << 16;
|
|
strip |= (unsigned short)sas_hw_at(byte_address+1) << 8;
|
|
strip |= sas_hw_at(byte_address+2);
|
|
|
|
/*
|
|
* Overlay save area
|
|
*/
|
|
strip &= (SHIFT_VAL >> bit_shift);
|
|
strip |= (IU32)graphics_cursor_background[line]
|
|
<< (8 - bit_shift);
|
|
|
|
/*
|
|
* Stash cursor line and alert gvi
|
|
*/
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 16);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip >> 8);
|
|
}
|
|
if (byte_min <= 2 && byte_max >= 2)
|
|
{
|
|
sas_store(byte_address+2, strip);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Stash save area and alert gvi
|
|
*/
|
|
strip = graphics_cursor_background[line];
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 8);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip);
|
|
}
|
|
}
|
|
line++;
|
|
}
|
|
}
|
|
|
|
#ifdef HERC
|
|
|
|
LOCAL void HERC_graphics_cursor_undisplay IFN0()
|
|
{
|
|
/*
|
|
* Remove the graphics cursor representation of the mouse
|
|
* status
|
|
*/
|
|
int scan_line_mod;
|
|
MOUSE_BIT_ADDRESS bit_shift;
|
|
IS32 byte_offset;
|
|
sys_addr byte_address;
|
|
IU32 strip;
|
|
int line, line_max;
|
|
int byte_min, byte_max;
|
|
|
|
/*
|
|
* Get cursor byte offset relative to the start of the
|
|
* even or odd bank, and bit shift to apply
|
|
*/
|
|
scan_line_mod = save_area.top_left.y % 4;
|
|
byte_offset = point_as_HERC_graphics_cell_address(&save_position);
|
|
bit_shift = byte_offset & 7;
|
|
byte_offset >>= 3;
|
|
|
|
/*
|
|
* Get range of cursor lines that need to be displayed
|
|
*/
|
|
line = save_area.top_left.y - save_position.y;
|
|
line_max = area_depth(&save_area);
|
|
|
|
/*
|
|
* Get range of bytes that need to be displayed
|
|
*/
|
|
byte_min = 0;
|
|
byte_max = 2;
|
|
if (save_position.x < 0)
|
|
byte_min += (7 - save_position.x) / 8;
|
|
else if (area_width(&save_area) < MOUSE_GRAPHICS_CURSOR_WIDTH)
|
|
byte_max -= (8 + MOUSE_GRAPHICS_CURSOR_WIDTH - area_width(&save_area)) / 8;
|
|
|
|
while(line < line_max)
|
|
{
|
|
switch (scan_line_mod){
|
|
case 0:
|
|
scan_line_mod++;
|
|
byte_address = gvi_pc_low_regen + 0x0000 + byte_offset;
|
|
break;
|
|
case 1:
|
|
scan_line_mod++;
|
|
byte_address = gvi_pc_low_regen + 0x2000 + byte_offset;
|
|
break;
|
|
case 2:
|
|
scan_line_mod++;
|
|
byte_address = gvi_pc_low_regen + 0x4000 + byte_offset;
|
|
break;
|
|
case 3:
|
|
scan_line_mod=0;
|
|
byte_address = gvi_pc_low_regen + 0x6000 + byte_offset;
|
|
byte_offset += 720 / 8;
|
|
break;
|
|
}
|
|
|
|
if (bit_shift)
|
|
{
|
|
/*
|
|
* Get cursor line
|
|
*/
|
|
strip = (IU32)sas_hw_at(byte_address) << 16;
|
|
strip |= (unsigned short)sas_hw_at(byte_address+1) << 8;
|
|
strip |= sas_hw_at(byte_address+2);
|
|
|
|
/*
|
|
* Overlay save area
|
|
*/
|
|
strip &= (SHIFT_VAL >> bit_shift);
|
|
strip |= (IU32)graphics_cursor_background[line]
|
|
<< (8 - bit_shift);
|
|
|
|
/*
|
|
* Stash cursor line and alert gvi
|
|
*/
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 16);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip >> 8);
|
|
}
|
|
if (byte_min <= 2 && byte_max >= 2)
|
|
{
|
|
sas_store(byte_address+2, strip);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Stash save area
|
|
*/
|
|
strip = graphics_cursor_background[line];
|
|
if (byte_min <= 0 && byte_max >= 0)
|
|
{
|
|
sas_store(byte_address, strip >> 8);
|
|
}
|
|
if (byte_min <= 1 && byte_max >= 1)
|
|
{
|
|
sas_store(byte_address+1, strip);
|
|
}
|
|
}
|
|
line++;
|
|
}
|
|
}
|
|
#endif /* HERC */
|
|
|
|
|
|
/*
|
|
* MOUSE DRIVER INPORT ACCESS FUNCTIONS
|
|
* ====================================
|
|
*/
|
|
|
|
LOCAL void inport_get_event IFN1(MOUSE_INPORT_DATA *,event)
|
|
{
|
|
/*
|
|
* Get InPort event data from the Bus Mouse hardware following
|
|
* an interrupt
|
|
*/
|
|
half_word inport_mode;
|
|
|
|
/*
|
|
* Set hold bit in InPort mode register to transfer the mouse
|
|
* event data into the status and data registers
|
|
*/
|
|
outb(MOUSE_INPORT_ADDRESS_REG, MOUSE_INPORT_ADDRESS_MODE);
|
|
inb(MOUSE_INPORT_DATA_REG, &inport_mode);
|
|
outb(MOUSE_INPORT_DATA_REG, inport_mode | MOUSE_INPORT_MODE_HOLD_BIT);
|
|
|
|
/*
|
|
* Retreive the InPort mouse status, data1 and data2 registers
|
|
*/
|
|
outb(MOUSE_INPORT_ADDRESS_REG, MOUSE_INPORT_ADDRESS_STATUS);
|
|
inb(MOUSE_INPORT_DATA_REG, &event->status);
|
|
outb(MOUSE_INPORT_ADDRESS_REG, MOUSE_INPORT_ADDRESS_DATA1);
|
|
inb(MOUSE_INPORT_DATA_REG, (half_word *)&event->data_x);
|
|
outb(MOUSE_INPORT_ADDRESS_REG, MOUSE_INPORT_ADDRESS_DATA2);
|
|
inb(MOUSE_INPORT_DATA_REG, (half_word *)&event->data_y);
|
|
|
|
/*
|
|
* Clear hold bit in mode register
|
|
*/
|
|
outb(MOUSE_INPORT_ADDRESS_REG, MOUSE_INPORT_ADDRESS_MODE);
|
|
inb(MOUSE_INPORT_DATA_REG, &inport_mode);
|
|
outb(MOUSE_INPORT_DATA_REG, inport_mode & ~MOUSE_INPORT_MODE_HOLD_BIT);
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void inport_reset IFN0()
|
|
{
|
|
/*
|
|
* Reset the InPort bus mouse hardware
|
|
*/
|
|
|
|
/*
|
|
* Set the reset bit in the address register
|
|
*/
|
|
outb(MOUSE_INPORT_ADDRESS_REG, MOUSE_INPORT_ADDRESS_RESET_BIT);
|
|
|
|
/*
|
|
* Select the mode register, and set it to the correct value
|
|
*/
|
|
outb(MOUSE_INPORT_ADDRESS_REG, MOUSE_INPORT_ADDRESS_MODE);
|
|
outb(MOUSE_INPORT_DATA_REG, MOUSE_INPORT_MODE_VALUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* USER SUBROUTINE CALL ACCESS FUNCTIONS
|
|
* =====================================
|
|
*/
|
|
|
|
LOCAL void jump_to_user_subroutine IFN3(MOUSE_CALL_MASK,condition_mask,word,segment,word,offset)
|
|
{
|
|
/*
|
|
* This routine sets up the CPU registers so that when the CPU
|
|
* restarts, control will pass to the user subroutine, and when
|
|
* the user subroutine returns, control will pass to the second
|
|
* part of the mouse hardware interrupt service routine
|
|
*/
|
|
|
|
/*
|
|
* Push address of second part of mouse hardware interrupt service
|
|
* routine
|
|
*/
|
|
|
|
setSP(getSP() - 2);
|
|
sas_storew(effective_addr(getSS(), getSP()), MOUSE_INT2_SEGMENT);
|
|
setSP(getSP() - 2);
|
|
sas_storew(effective_addr(getSS(), getSP()), MOUSE_INT2_OFFSET);
|
|
|
|
/*
|
|
* Set CS:IP to point to the user subroutine. Adjust the IP by
|
|
* HOST_BOP_IP_FUDGE, since the CPU emulator will increment IP by
|
|
* HOST_BOP_IP_FUDGE for the BOP instruction before proceeding
|
|
*/
|
|
setCS(segment);
|
|
#ifdef CPU_30_STYLE
|
|
setIP(offset);
|
|
#else /* !CPU_30_STYLE */
|
|
setIP(offset + HOST_BOP_IP_FUDGE);
|
|
#endif /* !CPU_30_STYLE */
|
|
|
|
/*
|
|
* Put parameters into the registers, saving the previous contents
|
|
* to be restored in the second part of the mouse hardware
|
|
* interrupt service routine
|
|
*/
|
|
saved_AX = getAX();
|
|
setAX(condition_mask);
|
|
saved_BX = getBX();
|
|
setBX(cursor_status.button_status);
|
|
saved_CX = getCX();
|
|
setCX(cursor_status.position.x);
|
|
saved_DX = getDX();
|
|
setDX(cursor_status.position.y);
|
|
saved_SI = getSI();
|
|
setSI(mouse_motion.x);
|
|
saved_DI = getDI();
|
|
setDI(mouse_motion.y);
|
|
saved_ES = getES();
|
|
saved_BP = getBP();
|
|
saved_DS = getDS();
|
|
|
|
/*
|
|
* Save the condition mask so that the second part of the mouse
|
|
* hardware interrupt service routine can determine whether the
|
|
* cursor has changed position
|
|
*/
|
|
|
|
last_condition_mask = condition_mask;
|
|
|
|
/*
|
|
* Enable interrupts
|
|
*/
|
|
setIF(1);
|
|
}
|