338 lines
11 KiB
C
338 lines
11 KiB
C
//========================================================================
|
|
// GLFW - An OpenGL framework
|
|
// File: dos_mouse.c
|
|
// Platform: DOS
|
|
// API version: 2.6
|
|
// WWW: http://glfw.sourceforge.net
|
|
//------------------------------------------------------------------------
|
|
// Copyright (c) 2002-2006 Camilla Berglund
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would
|
|
// be appreciated but is not required.
|
|
//
|
|
// 2. Altered source versions must be plainly marked as such, and must not
|
|
// be misrepresented as being the original software.
|
|
//
|
|
// 3. This notice may not be removed or altered from any source
|
|
// distribution.
|
|
//
|
|
//========================================================================
|
|
|
|
#include "internal.h"
|
|
|
|
//========================================================================
|
|
// Most of the code in this source file is based on the mouse driver in
|
|
// Daniel Borca's GLUT implementation for DOS/MESA.
|
|
//========================================================================
|
|
|
|
//========================================================================
|
|
// Definitions
|
|
//========================================================================
|
|
|
|
#define _GLFW_MOUSE_STACK_SIZE 16384
|
|
|
|
|
|
// Assembler function prototypes
|
|
extern void _glfwMouseWrap( void );
|
|
extern int _glfwMouseWrap_end[];
|
|
|
|
|
|
//========================================================================
|
|
// Global variables
|
|
//========================================================================
|
|
|
|
static int _glfwMouseInstalled = 0;
|
|
|
|
static struct {
|
|
long Callback;
|
|
int Emulate3;
|
|
int OldX, OldY, OldB;
|
|
__dpmi_regs Regs;
|
|
} _glfwMouseDrv;
|
|
|
|
|
|
|
|
//************************************************************************
|
|
//**** Mouse Interrupt ***************************************************
|
|
//************************************************************************
|
|
|
|
//========================================================================
|
|
// _glfwMouseInt() - Mouse interrupt handler
|
|
//========================================================================
|
|
|
|
static void _glfwMouseInt( __dpmi_regs *r )
|
|
{
|
|
int newx, newy, dx, dy, dz, buttons;
|
|
_GLFWdosevent event;
|
|
struct mousemove_event *mousemove = &event.MouseMove;
|
|
struct mousewheel_event *mousewheel = &event.MouseWheel;
|
|
struct mousebutton_event *mousebutton = &event.MouseButton;
|
|
|
|
// Calculate mouse deltas
|
|
newx = (signed short)r->x.si;
|
|
newy = (signed short)r->x.di;
|
|
dx = newx - _glfwMouseDrv.OldX;
|
|
dy = newy - _glfwMouseDrv.OldY;
|
|
dz = (signed char)r->h.bh;
|
|
|
|
// Get mouse buttons status
|
|
buttons = r->h.bl;
|
|
|
|
// Emulate 3rd mouse button?
|
|
if( _glfwMouseDrv.Emulate3 )
|
|
{
|
|
if( (buttons & 3) == 3 )
|
|
{
|
|
buttons = 4;
|
|
}
|
|
}
|
|
|
|
// Mouse moved?
|
|
if( dx || dy )
|
|
{
|
|
mousemove->Type = _GLFW_DOS_MOUSE_MOVE_EVENT;
|
|
mousemove->DeltaX = dx;
|
|
mousemove->DeltaY = dy;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
|
|
// Mouse wheel moved?
|
|
if( dz )
|
|
{
|
|
mousewheel->Type = _GLFW_DOS_MOUSE_WHEEL_EVENT;
|
|
mousewheel->WheelDelta = dz;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
|
|
// Button state changed?
|
|
if( buttons != _glfwMouseDrv.OldB )
|
|
{
|
|
mousebutton->Type = _GLFW_DOS_MOUSE_BUTTON_EVENT;
|
|
|
|
// Left mouse button changed?
|
|
if( (_glfwMouseDrv.OldB & 1) && !(buttons & 1) )
|
|
{
|
|
mousebutton->Button = GLFW_MOUSE_BUTTON_LEFT;
|
|
mousebutton->Action = GLFW_RELEASE;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
else if( !(_glfwMouseDrv.OldB & 1) && (buttons & 1) )
|
|
{
|
|
mousebutton->Button = GLFW_MOUSE_BUTTON_LEFT;
|
|
mousebutton->Action = GLFW_PRESS;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
|
|
// Right mouse button changed?
|
|
if( (_glfwMouseDrv.OldB & 2) && !(buttons & 2) )
|
|
{
|
|
mousebutton->Button = GLFW_MOUSE_BUTTON_RIGHT;
|
|
mousebutton->Action = GLFW_RELEASE;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
else if( !(_glfwMouseDrv.OldB & 2) && (buttons & 2) )
|
|
{
|
|
mousebutton->Button = GLFW_MOUSE_BUTTON_RIGHT;
|
|
mousebutton->Action = GLFW_PRESS;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
|
|
// Middle mouse button changed?
|
|
if( (_glfwMouseDrv.OldB & 4) && !(buttons & 4) )
|
|
{
|
|
mousebutton->Button = GLFW_MOUSE_BUTTON_MIDDLE;
|
|
mousebutton->Action = GLFW_RELEASE;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
else if( !(_glfwMouseDrv.OldB & 4) && (buttons & 4) )
|
|
{
|
|
mousebutton->Button = GLFW_MOUSE_BUTTON_MIDDLE;
|
|
mousebutton->Action = GLFW_PRESS;
|
|
_glfwPostDOSEvent( &event );
|
|
}
|
|
|
|
}
|
|
|
|
// Remember old mouse state
|
|
_glfwMouseDrv.OldX = newx;
|
|
_glfwMouseDrv.OldY = newy;
|
|
_glfwMouseDrv.OldB = buttons;
|
|
} ENDOFUNC(_glfwMouseInt)
|
|
|
|
|
|
|
|
//************************************************************************
|
|
//**** GLFW internal functions ****
|
|
//************************************************************************
|
|
|
|
//========================================================================
|
|
// _glfwInitMouse() - Initialize mouse driver
|
|
//========================================================================
|
|
|
|
int _glfwInitMouse( void )
|
|
{
|
|
int buttons;
|
|
|
|
// Already installed?
|
|
if( _glfwMouseInstalled )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Reset mouse and get status
|
|
__asm("\n\
|
|
xorl %%eax, %%eax \n\
|
|
int $0x33 \n\
|
|
andl %%ebx, %%eax \n\
|
|
movl %%eax, %0 \n\
|
|
":"=g" (buttons)::"%eax", "%ebx");
|
|
if( !buttons )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Lock data and functions
|
|
LOCKDATA( _glfwMouseDrv );
|
|
LOCKBUFF( _glfwMouseWrap_end, 8 );
|
|
LOCKFUNC( _glfwMouseInt );
|
|
LOCKFUNC( _glfwMouseWrap );
|
|
|
|
_glfwMouseWrap_end[1] = __djgpp_ds_alias;
|
|
|
|
// Grab a locked stack
|
|
_glfwMouseWrap_end[0] = (int)malloc( _GLFW_MOUSE_STACK_SIZE );
|
|
if( _glfwMouseWrap_end[0] == NULL )
|
|
{
|
|
return 0;
|
|
}
|
|
LOCKBUFF( _glfwMouseWrap_end[0], _GLFW_MOUSE_STACK_SIZE );
|
|
|
|
// Try to hook a call-back
|
|
__asm("\n\
|
|
pushl %%ds \n\
|
|
pushl %%es \n\
|
|
movw $0x0303, %%ax \n\
|
|
pushl %%ds \n\
|
|
pushl %%cs \n\
|
|
popl %%ds \n\
|
|
popl %%es \n\
|
|
int $0x31 \n\
|
|
popl %%es \n\
|
|
popl %%ds \n\
|
|
jc 0f \n\
|
|
shll $16, %%ecx \n\
|
|
movw %%dx, %%cx \n\
|
|
movl %%ecx, %0 \n\
|
|
0: \n\
|
|
":"=g"(_glfwMouseDrv.Callback)
|
|
:"S" (_glfwMouseWrap), "D"(&_glfwMouseDrv.Regs)
|
|
:"%eax", "%ecx", "%edx");
|
|
if( !_glfwMouseDrv.Callback )
|
|
{
|
|
free( (void *)_glfwMouseWrap_end[0] );
|
|
return 0;
|
|
}
|
|
|
|
// Adjust stack
|
|
_glfwMouseWrap_end[0] += _GLFW_MOUSE_STACK_SIZE;
|
|
|
|
// Install the handler
|
|
_glfwMouseDrv.Regs.x.ax = 0x000c;
|
|
_glfwMouseDrv.Regs.x.cx = 0x7f | 0x80;
|
|
_glfwMouseDrv.Regs.x.dx = _glfwMouseDrv.Callback & 0xffff;
|
|
_glfwMouseDrv.Regs.x.es = _glfwMouseDrv.Callback >> 16;
|
|
__dpmi_int( 0x33, &_glfwMouseDrv.Regs );
|
|
|
|
// Clear mickeys
|
|
__asm __volatile ("\n\
|
|
movw $0xb, %%ax; \n\
|
|
int $0x33 \n\
|
|
":::"%eax", "%ecx", "%edx");
|
|
|
|
_glfwMouseDrv.OldX = 0;
|
|
_glfwMouseDrv.OldY = 0;
|
|
_glfwMouseDrv.OldB = 0;
|
|
|
|
// Emulate third mouse button?
|
|
_glfwMouseDrv.Emulate3 = buttons < 3;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
// _glfwTerminateMouse() - Terminate mouse driver
|
|
//========================================================================
|
|
|
|
void _glfwTerminateMouse( void )
|
|
{
|
|
if( !_glfwMouseInstalled )
|
|
{
|
|
return;
|
|
}
|
|
|
|
__asm("\n\
|
|
movl %%edx, %%ecx \n\
|
|
shrl $16, %%ecx \n\
|
|
movw $0x0304, %%ax \n\
|
|
int $0x31 \n\
|
|
movw $0x000c, %%ax \n\
|
|
xorl %%ecx, %%ecx \n\
|
|
int $0x33 \n\
|
|
"::"d"(_glfwMouseDrv.Callback):"%eax", "%ecx");
|
|
_glfwMouseDrv.Callback = 0;
|
|
|
|
free( (void *)(_glfwMouseWrap_end[0] - _GLFW_MOUSE_STACK_SIZE) );
|
|
|
|
_glfwMouseInstalled = 0;
|
|
}
|
|
|
|
|
|
|
|
//========================================================================
|
|
// _glfwMouseWrap()
|
|
//========================================================================
|
|
|
|
// Hack alert: `_glfwMouseWrap_end' actually holds the address of stack in
|
|
// a safe data selector.
|
|
|
|
__asm("\n\
|
|
.text \n\
|
|
.p2align 5,,31 \n\
|
|
.global __glfwMouseWrap \n\
|
|
__glfwMouseWrap: \n\
|
|
cld \n\
|
|
lodsl \n\
|
|
movl %eax, %es:42(%edi) \n\
|
|
addw $4, %es:46(%edi) \n\
|
|
pushl %es \n\
|
|
movl %ss, %ebx \n\
|
|
movl %esp, %esi \n\
|
|
lss %cs:__glfwMouseWrap_end, %esp\n\
|
|
pushl %ss \n\
|
|
pushl %ss \n\
|
|
popl %es \n\
|
|
popl %ds \n\
|
|
movl ___djgpp_dos_sel, %fs \n\
|
|
pushl %fs \n\
|
|
popl %gs \n\
|
|
pushl %edi \n\
|
|
call __glfwMouseInt \n\
|
|
popl %edi \n\
|
|
movl %ebx, %ss \n\
|
|
movl %esi, %esp \n\
|
|
popl %es \n\
|
|
iret \n\
|
|
.global __glfwMouseWrap_end \n\
|
|
__glfwMouseWrap_end:.long 0, 0");
|