/*
* comcom64 - 64bit command.com
* Copyright (C) 2023-2024 @stsp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include "asm.h"
#include "mouse.h"
#define CF 1
#ifdef DJ64
static unsigned int mouse_regs;
#else
static __dpmi_regs *mouse_regs;
#endif
static __dpmi_raddr newm;
static __dpmi_raddr oldm;
static unsigned old_mask;
#define MEV_MASK 0xab
static unsigned short popw(__dpmi_regs *r)
{
unsigned lina = (r->x.ss << 4) + r->x.sp;
unsigned short ret = _farpeekw(_dos_ds, lina);
r->x.sp += 2;
return ret;
}
static void do_retf(__dpmi_regs *r)
{
r->x.ip = popw(r);
r->x.cs = popw(r);
}
static void mvxl(int d)
{
__dpmi_regs r = { };
while (d--) {
r.x.ax = 0x500;
r.x.cx = 0x4BE0;
__dpmi_int(0x16, &r);
}
}
static void mvxr(int d)
{
__dpmi_regs r = { };
while (d--) {
r.x.ax = 0x500;
r.x.cx = 0x4DE0;
__dpmi_int(0x16, &r);
}
}
static void mlb(int alt_fn, int x, int y)
{
__dpmi_regs r = { };
short c;
if (alt_fn) {
int cx = wherex();
if (cx == x)
return;
if (x < cx)
mvxl(cx - x);
else
mvxr(x - cx);
return;
}
_conio_gettext(x, y, x, y, &c);
r.x.ax = 0x500;
r.x.cx = c & 0xff;
__dpmi_int(0x16, &r);
}
static void mrb(int alt_fn)
{
__dpmi_regs r = { };
r.x.ax = 0x500;
r.x.cx = alt_fn ? 0x3 : 0x0F09; // ^C or TAB
__dpmi_int(0x16, &r);
}
static void mmb(int alt_fn)
{
__dpmi_regs r = { };
r.x.ax = 0x500;
r.x.cx = alt_fn ? 0x0E08 : 0x1c0d; // BkSp or ENTER
__dpmi_int(0x16, &r);
}
static void mw(int delta)
{
__dpmi_regs r = { };
r.x.ax = 0x500;
if (delta < 0)
r.x.cx = 0x48E0; // UP
else
r.x.cx = 0x50E0; // DOWN
__dpmi_int(0x16, &r);
}
void do_mouse(void)
{
__dpmi_regs *r;
unsigned char rows = wherey();
static unsigned char prev_col, prev_row;
unsigned char col, row;
int dragged;
#ifdef DJ64
r = (__dpmi_regs *) DATA_PTR(mouse_regs);
#else
r = mouse_regs;
#endif
do_retf(r);
col = r->x.cx / 8 + 1;
row = r->x.dx / 8 + 1;
dragged = (r->x.ax & r->x.bx & 1) && (col != prev_col
|| row != prev_row);
if ((r->x.ax & 2) || dragged)
mlb(row == rows, col, row);
if (r->x.ax & 8)
mrb(row == rows);
if (r->x.ax & 0x20)
mmb(row == rows);
if (r->x.ax & 0x80)
mw((char) r->h.bh);
prev_col = r->x.cx / 8 + 1;
prev_row = r->x.dx / 8 + 1;
}
int mouse_init(void)
{
__dpmi_regs r = { };
__dpmi_int(0x33, &r);
if ((r.x.flags & CF) || r.x.ax != 0xffff || r.x.bx != 3) {
puts("mouse not detected");
return 0;
}
/* check the wheel */
r.x.ax = 0x11;
__dpmi_int(0x33, &r);
if ((r.x.flags & CF) || r.x.ax != 0x574d || (r.x.cx & 1) == 0) {
puts("mouse wheel not supported");
// return 0;
}
#ifdef DJ64
mouse_regs = malloc32(sizeof(__dpmi_regs));
#else
mouse_regs = (__dpmi_regs *) malloc(sizeof(__dpmi_regs));
#endif
__dpmi_allocate_real_mode_callback(my_mouse_handler, mouse_regs,
&newm);
r.x.ax = 0x14;
r.x.cx = MEV_MASK;
r.x.es = newm.segment;
r.x.dx = newm.offset16;
__dpmi_int(0x33, &r);
oldm.segment = r.x.es;
oldm.offset16 = r.x.dx;
old_mask = r.x.cx;
mouse_show();
return 1;
}
void mouse_enable(void)
{
__dpmi_regs r = { };
__dpmi_int(0x33, &r); // reset the visibility counter
if ((r.x.flags & CF) || r.x.ax != 0xffff || r.x.bx != 3) {
puts("mouse not detected");
return;
}
r.x.ax = 0x0c;
r.x.cx = MEV_MASK;
r.x.es = newm.segment;
r.x.dx = newm.offset16;
__dpmi_int(0x33, &r);
mouse_show();
}
void mouse_disable(void)
{
__dpmi_regs r = { };
mouse_hide();
r.x.ax = 0x0c;
r.x.cx = old_mask;
r.x.es = oldm.segment;
r.x.dx = oldm.offset16;
__dpmi_int(0x33, &r);
}
void mouse_done(void)
{
mouse_disable();
__dpmi_free_real_mode_callback(&newm);
#ifdef DJ64
free32(mouse_regs);
#else
free(mouse_regs);
#endif
}
void mouse_show(void)
{
__dpmi_regs r = { };
r.x.ax = 1;
__dpmi_int(0x33, &r);
}
void mouse_hide(void)
{
__dpmi_regs r = { };
r.x.ax = 2;
__dpmi_int(0x33, &r);
}