Fixed mouse bounding on real hardware. INI is now written with DOS line endings, not UNIX.
This commit is contained in:
parent
a4727754e3
commit
157d79f2d6
2 changed files with 61 additions and 36 deletions
|
|
@ -68,6 +68,17 @@ static void sysInfoAppend(const char *fmt, ...);
|
|||
static bool sHasMouseWheel = false;
|
||||
static int32_t sLastWheelDelta = 0;
|
||||
|
||||
// Software cursor tracking. Many real-hardware mouse drivers fail to
|
||||
// honour INT 33h functions 07h/08h (set coordinate range) in VESA modes
|
||||
// because they don't recognise non-standard video modes. We bypass the
|
||||
// driver's position entirely: platformMousePoll reads raw mickey deltas
|
||||
// via function 0Bh, accumulates them into sCurX/sCurY, and clamps to
|
||||
// the screen bounds. Function 03h is still used for button state.
|
||||
static int32_t sMouseRangeW = 0;
|
||||
static int32_t sMouseRangeH = 0;
|
||||
static int32_t sCurX = 0;
|
||||
static int32_t sCurY = 0;
|
||||
|
||||
// Alt+key scan code to ASCII lookup table (indexed by BIOS scan code).
|
||||
// INT 16h returns these scan codes with ascii=0 for Alt+key combos.
|
||||
// Using a 256-byte lookup table instead of a switch or if-chain because
|
||||
|
|
@ -1122,30 +1133,20 @@ bool platformKeyboardRead(PlatformKeyEventT *evt) {
|
|||
void platformMouseInit(int32_t screenW, int32_t screenH) {
|
||||
__dpmi_regs r;
|
||||
|
||||
sMouseRangeW = screenW;
|
||||
sMouseRangeH = screenH;
|
||||
sCurX = screenW / 2;
|
||||
sCurY = screenH / 2;
|
||||
|
||||
// Function 00h: reset driver, detect mouse hardware
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x0000;
|
||||
__dpmi_int(0x33, &r);
|
||||
|
||||
// Function 07h: set horizontal min/max range
|
||||
// Flush any stale mickey counters so the first poll starts clean.
|
||||
// Function 0Bh returns and resets the accumulated motion counters.
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x0007;
|
||||
r.x.cx = 0;
|
||||
r.x.dx = screenW - 1;
|
||||
__dpmi_int(0x33, &r);
|
||||
|
||||
// Function 08h: set vertical min/max range
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x0008;
|
||||
r.x.cx = 0;
|
||||
r.x.dx = screenH - 1;
|
||||
__dpmi_int(0x33, &r);
|
||||
|
||||
// Function 04h: warp cursor to center of screen
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x0004;
|
||||
r.x.cx = screenW / 2;
|
||||
r.x.dx = screenH / 2;
|
||||
r.x.ax = 0x000B;
|
||||
__dpmi_int(0x33, &r);
|
||||
}
|
||||
|
||||
|
|
@ -1173,32 +1174,55 @@ void platformMouseSetAccel(int32_t threshold) {
|
|||
// platformMousePoll
|
||||
// ============================================================
|
||||
//
|
||||
// Reads current mouse state via INT 33h function 03h.
|
||||
// Returns: CX=X position, DX=Y position, BX=button state
|
||||
// (bit 0 = left, bit 1 = right, bit 2 = middle).
|
||||
//
|
||||
// Polling is used instead of a callback/event model because the
|
||||
// DVX event loop already runs at frame rate. Installing a real-mode
|
||||
// callback for mouse events would add DPMI mode-switch overhead
|
||||
// on every mickeyed movement, which is wasteful when we only sample
|
||||
// once per frame anyway.
|
||||
// Reads button state via function 03h and raw mickey deltas via
|
||||
// function 0Bh. Position is tracked in software (sCurX/sCurY)
|
||||
// rather than using the driver's coordinates, because many real-
|
||||
// hardware mouse drivers cannot handle VESA mode coordinate ranges.
|
||||
// Function 0Bh returns the accumulated mickey motion since the last
|
||||
// call and is reliable across all drivers.
|
||||
|
||||
void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons) {
|
||||
__dpmi_regs r;
|
||||
|
||||
// Function 03h: read button state only
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x0003;
|
||||
__dpmi_int(0x33, &r);
|
||||
|
||||
*mx = r.x.cx;
|
||||
*my = r.x.dx;
|
||||
*buttons = r.x.bx & 0x07; // BL only: bits 0-2 = left/right/middle
|
||||
*buttons = r.x.bx & 0x07;
|
||||
|
||||
// BH = signed 8-bit wheel counter (cleared on read by the driver).
|
||||
// Only meaningful if the wheel API was activated via platformMouseWheelInit.
|
||||
if (sHasMouseWheel) {
|
||||
sLastWheelDelta = (int32_t)(int8_t)(r.x.bx >> 8);
|
||||
}
|
||||
|
||||
// Function 0Bh: read mickey motion counters (signed 16-bit deltas,
|
||||
// cleared on read). Accumulate into software cursor position.
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x000B;
|
||||
__dpmi_int(0x33, &r);
|
||||
|
||||
sCurX += (int16_t)r.x.cx;
|
||||
sCurY += (int16_t)r.x.dx;
|
||||
|
||||
if (sCurX < 0) {
|
||||
sCurX = 0;
|
||||
}
|
||||
|
||||
if (sCurX >= sMouseRangeW) {
|
||||
sCurX = sMouseRangeW - 1;
|
||||
}
|
||||
|
||||
if (sCurY < 0) {
|
||||
sCurY = 0;
|
||||
}
|
||||
|
||||
if (sCurY >= sMouseRangeH) {
|
||||
sCurY = sMouseRangeH - 1;
|
||||
}
|
||||
|
||||
*mx = sCurX;
|
||||
*my = sCurY;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1247,12 +1271,13 @@ int32_t platformMouseWheelPoll(void) {
|
|||
// so the pointer visually sticks to the border.
|
||||
|
||||
void platformMouseWarp(int32_t x, int32_t y) {
|
||||
__dpmi_regs r;
|
||||
sCurX = x;
|
||||
sCurY = y;
|
||||
|
||||
// Flush any pending mickeys so the next poll doesn't undo the warp
|
||||
__dpmi_regs r;
|
||||
memset(&r, 0, sizeof(r));
|
||||
r.x.ax = 0x0004;
|
||||
r.x.cx = x;
|
||||
r.x.dx = y;
|
||||
r.x.ax = 0x000B;
|
||||
__dpmi_int(0x33, &r);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ $(TARGET): $(OBJS) $(LIBDIR)/libdvx.a $(LIBDIR)/libtasks.a | $(BINDIR)
|
|||
rm -f $(BINDIR)/dvx
|
||||
|
||||
$(CONFIGDIR)/dvx.ini: ../dvx.ini | $(CONFIGDIR)
|
||||
cp $< $@
|
||||
sed 's/$$/\r/' $< > $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue