Blame |
Last modification |
View Log
| RSS feed
/*
* PC/HW routine collection v1.2 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include <dpmi.h>
#include "pc_hw.h"
#define MOUSE_STACK_SIZE 16384
#define CLEAR_MICKEYS() \
do { \
__asm __volatile ("movw $0xb, %%ax; int $0x33":::"%eax", "%ecx", "%edx"); \
ox = oy = 0; \
} while (0)
extern void mouse_wrapper
(void);
extern void mouse_wrapper_end
(void);
static MFUNC mouse_func
;
static void *mouse_stack
;
static long mouse_callback
;
static __dpmi_regs mouse_regs
;
static volatile int pc_mouse_x
, pc_mouse_y
, pc_mouse_b
;
static int minx
= 0;
static int maxx
= 319;
static int miny
= 0;
static int maxy
= 199;
static int sx
= 2;
static int sy
= 2;
static int emulat3
= FALSE
;
static int ox
, oy
;
static void mouse
(__dpmi_regs
*r
)
{
int nx
= (signed short)r
->x.
si / sx
;
int ny
= (signed short)r
->x.
di / sy
;
int dx
= nx
- ox
;
int dy
= ny
- oy
;
ox
= nx
;
oy
= ny
;
pc_mouse_b
= r
->x.
bx;
pc_mouse_x
= MID
(minx
, pc_mouse_x
+ dx
, maxx
);
pc_mouse_y
= MID
(miny
, pc_mouse_y
+ dy
, maxy
);
if (emulat3
) {
if ((pc_mouse_b
&3)==3) {
pc_mouse_b
= 4;
}
}
if (mouse_func
) {
mouse_func
(pc_mouse_x
, pc_mouse_y
, pc_mouse_b
);
}
} ENDOFUNC
(mouse
)
void pc_remove_mouse
(void)
{
if (mouse_callback
) {
pc_clexit
(pc_remove_mouse
);
__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"(mouse_callback
):"%eax", "%ecx");
mouse_callback
= 0;
free((void *)((unsigned long)mouse_stack
-MOUSE_STACK_SIZE
));
}
}
int pc_install_mouse
(void)
{
int buttons
;
/* fail if already call-backed */
if (mouse_callback
) {
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 wrapper */
LOCKDATA
(mouse_func
);
LOCKDATA
(mouse_stack
);
LOCKDATA
(mouse_callback
);
LOCKDATA
(mouse_regs
);
LOCKDATA
(pc_mouse_x
);
LOCKDATA
(pc_mouse_y
);
LOCKDATA
(pc_mouse_b
);
LOCKDATA
(minx
);
LOCKDATA
(maxx
);
LOCKDATA
(miny
);
LOCKDATA
(maxy
);
LOCKDATA
(sx
);
LOCKDATA
(sy
);
LOCKDATA
(emulat3
);
LOCKDATA
(ox
);
LOCKDATA
(oy
);
LOCKFUNC
(mouse
);
LOCKFUNC
(mouse_wrapper
);
/* grab a locked stack */
if ((mouse_stack
=pc_malloc
(MOUSE_STACK_SIZE
))==NULL
) {
return 0;
}
/* 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"(mouse_callback
)
:"S" (mouse_wrapper
), "D"(&mouse_regs
)
:"%eax", "%ecx", "%edx");
if (!mouse_callback
) {
free(mouse_stack
);
return 0;
}
/* adjust stack */
mouse_stack
= (void *)((unsigned long)mouse_stack
+ MOUSE_STACK_SIZE
);
/* install the handler */
mouse_regs.
x.
ax = 0x000c;
mouse_regs.
x.
cx = 0x007f;
mouse_regs.
x.
dx = mouse_callback
&0xffff;
mouse_regs.
x.
es = mouse_callback
>>16;
__dpmi_int
(0x33, &mouse_regs
);
CLEAR_MICKEYS
();
emulat3
= buttons
<3;
pc_atexit
(pc_remove_mouse
);
return buttons
;
}
MFUNC pc_install_mouse_handler
(MFUNC handler
)
{
MFUNC old
;
if (!mouse_callback
&& !pc_install_mouse
()) {
return NULL
;
}
old
= mouse_func
;
mouse_func
= handler
;
return old
;
}
void pc_mouse_area
(int x1
, int y1
, int x2
, int y2
)
{
minx
= x1
;
maxx
= x2
;
miny
= y1
;
maxy
= y2
;
}
void pc_mouse_speed
(int xspeed
, int yspeed
)
{
DISABLE
();
sx
= MAX
(1, xspeed
);
sy
= MAX
(1, yspeed
);
ENABLE
();
}
int pc_query_mouse
(int *x
, int *y
)
{
*x
= pc_mouse_x
;
*y
= pc_mouse_y
;
return pc_mouse_b
;
}
void pc_show_mouse
(void)
{
/* not implemented */
}
void pc_scare_mouse
(void)
{
/* not implemented */
}
void pc_unscare_mouse
(void)
{
/* not implemented */
}
__asm
("\n\
.text \n\
.balign 4 \n\
.global _mouse_wrapper \n\
_mouse_wrapper: \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\
movl %cs:___djgpp_ds_alias, %ss \n\
movl %cs:_mouse_stack, %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 _mouse \n\
popl %edi \n\
movl %ebx, %ss \n\
movl %esi, %esp \n\
popl %es \n\
iret \n\
.balign 4 \n\
.global _mouse_wrapper_end \n\
_mouse_wrapper_end:");