| /* |
| * PC/HW routine collection v1.3 for DOS/DJGPP |
| * |
| * Copyright (C) 2002 - Daniel Borca |
| * Email : dborca@yahoo.com |
| * Web : http://www.geocities.com/dborca |
| */ |
| |
| |
| #include <dpmi.h> |
| #include <sys/exceptn.h> |
| #include <sys/segments.h> |
| |
| #include "pc_hw.h" |
| |
| |
| #define PC_CUTE_WHEEL 1 /* CuteMouse WheelAPI */ |
| |
| #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_wrap (void); |
| extern int mouse_wrap_end[]; |
| |
| static MFUNC mouse_func; |
| static long mouse_callback; |
| static __dpmi_regs mouse_regs; |
| |
| static volatile struct { |
| volatile int x, y, z, b; |
| } pc_mouse; |
| |
| static int minx = 0; |
| static int maxx = 319; |
| static int miny = 0; |
| static int maxy = 199; |
| static int minz = 0; |
| static int maxz = 255; |
| |
| 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; |
| #if PC_CUTE_WHEEL |
| int dz = (signed char)r->h.bh; |
| #endif |
| ox = nx; |
| oy = ny; |
| |
| pc_mouse.b = r->h.bl; |
| pc_mouse.x = MID(minx, pc_mouse.x + dx, maxx); |
| pc_mouse.y = MID(miny, pc_mouse.y + dy, maxy); |
| #if PC_CUTE_WHEEL |
| pc_mouse.z = MID(minz, pc_mouse.z + dz, maxz); |
| #endif |
| |
| 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.z, 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 *)(mouse_wrap_end[0] - 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_callback); |
| LOCKDATA(mouse_regs); |
| LOCKDATA(pc_mouse); |
| LOCKDATA(minx); |
| LOCKDATA(maxx); |
| LOCKDATA(miny); |
| LOCKDATA(maxy); |
| LOCKDATA(minz); |
| LOCKDATA(maxz); |
| LOCKDATA(sx); |
| LOCKDATA(sy); |
| LOCKDATA(emulat3); |
| LOCKDATA(ox); |
| LOCKDATA(oy); |
| LOCKFUNC(mouse); |
| LOCKFUNC(mouse_wrap); |
| |
| mouse_wrap_end[1] = __djgpp_ds_alias; |
| /* grab a locked stack */ |
| if ((mouse_wrap_end[0] = (int)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_wrap), "D"(&mouse_regs) |
| :"%eax", "%ecx", "%edx"); |
| if (!mouse_callback) { |
| free((void *)mouse_wrap_end[0]); |
| return 0; |
| } |
| |
| /* adjust stack */ |
| mouse_wrap_end[0] += MOUSE_STACK_SIZE; |
| |
| /* install the handler */ |
| mouse_regs.x.ax = 0x000c; |
| #if PC_CUTE_WHEEL |
| mouse_regs.x.cx = 0x7f | 0x80; |
| #else |
| mouse_regs.x.cx = 0x7f; |
| #endif |
| 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, int *z) |
| { |
| *x = pc_mouse.x; |
| *y = pc_mouse.y; |
| *z = pc_mouse.z; |
| return pc_mouse.b; |
| } |
| |
| |
| void |
| pc_warp_mouse (int x, int y) |
| { |
| CLEAR_MICKEYS(); |
| |
| pc_mouse.x = MID(minx, x, maxx); |
| pc_mouse.y = MID(miny, y, maxy); |
| |
| if (mouse_func) { |
| mouse_func(pc_mouse.x, pc_mouse.y, pc_mouse.z, pc_mouse.b); |
| } |
| } |
| |
| |
| /* Hack alert: |
| * `mouse_wrap_end' actually holds the |
| * address of stack in a safe data selector. |
| */ |
| __asm("\n\ |
| .text \n\ |
| .p2align 5,,31 \n\ |
| .global _mouse_wrap \n\ |
| _mouse_wrap: \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:_mouse_wrap_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 _mouse \n\ |
| popl %edi \n\ |
| movl %ebx, %ss \n\ |
| movl %esi, %esp \n\ |
| popl %es \n\ |
| iret \n\ |
| .global _mouse_wrap_end \n\ |
| _mouse_wrap_end:.long 0, 0"); |