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 bool sHasMouseWheel = false;
|
||||||
static int32_t sLastWheelDelta = 0;
|
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).
|
// 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.
|
// 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
|
// 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) {
|
void platformMouseInit(int32_t screenW, int32_t screenH) {
|
||||||
__dpmi_regs r;
|
__dpmi_regs r;
|
||||||
|
|
||||||
|
sMouseRangeW = screenW;
|
||||||
|
sMouseRangeH = screenH;
|
||||||
|
sCurX = screenW / 2;
|
||||||
|
sCurY = screenH / 2;
|
||||||
|
|
||||||
// Function 00h: reset driver, detect mouse hardware
|
// Function 00h: reset driver, detect mouse hardware
|
||||||
memset(&r, 0, sizeof(r));
|
memset(&r, 0, sizeof(r));
|
||||||
r.x.ax = 0x0000;
|
r.x.ax = 0x0000;
|
||||||
__dpmi_int(0x33, &r);
|
__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));
|
memset(&r, 0, sizeof(r));
|
||||||
r.x.ax = 0x0007;
|
r.x.ax = 0x000B;
|
||||||
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;
|
|
||||||
__dpmi_int(0x33, &r);
|
__dpmi_int(0x33, &r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1173,32 +1174,55 @@ void platformMouseSetAccel(int32_t threshold) {
|
||||||
// platformMousePoll
|
// platformMousePoll
|
||||||
// ============================================================
|
// ============================================================
|
||||||
//
|
//
|
||||||
// Reads current mouse state via INT 33h function 03h.
|
// Reads button state via function 03h and raw mickey deltas via
|
||||||
// Returns: CX=X position, DX=Y position, BX=button state
|
// function 0Bh. Position is tracked in software (sCurX/sCurY)
|
||||||
// (bit 0 = left, bit 1 = right, bit 2 = middle).
|
// rather than using the driver's coordinates, because many real-
|
||||||
//
|
// hardware mouse drivers cannot handle VESA mode coordinate ranges.
|
||||||
// Polling is used instead of a callback/event model because the
|
// Function 0Bh returns the accumulated mickey motion since the last
|
||||||
// DVX event loop already runs at frame rate. Installing a real-mode
|
// call and is reliable across all drivers.
|
||||||
// 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.
|
|
||||||
|
|
||||||
void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons) {
|
void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons) {
|
||||||
__dpmi_regs r;
|
__dpmi_regs r;
|
||||||
|
|
||||||
|
// Function 03h: read button state only
|
||||||
memset(&r, 0, sizeof(r));
|
memset(&r, 0, sizeof(r));
|
||||||
r.x.ax = 0x0003;
|
r.x.ax = 0x0003;
|
||||||
__dpmi_int(0x33, &r);
|
__dpmi_int(0x33, &r);
|
||||||
|
|
||||||
*mx = r.x.cx;
|
*buttons = r.x.bx & 0x07;
|
||||||
*my = r.x.dx;
|
|
||||||
*buttons = r.x.bx & 0x07; // BL only: bits 0-2 = left/right/middle
|
|
||||||
|
|
||||||
// BH = signed 8-bit wheel counter (cleared on read by the driver).
|
// BH = signed 8-bit wheel counter (cleared on read by the driver).
|
||||||
// Only meaningful if the wheel API was activated via platformMouseWheelInit.
|
|
||||||
if (sHasMouseWheel) {
|
if (sHasMouseWheel) {
|
||||||
sLastWheelDelta = (int32_t)(int8_t)(r.x.bx >> 8);
|
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.
|
// so the pointer visually sticks to the border.
|
||||||
|
|
||||||
void platformMouseWarp(int32_t x, int32_t y) {
|
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));
|
memset(&r, 0, sizeof(r));
|
||||||
r.x.ax = 0x0004;
|
r.x.ax = 0x000B;
|
||||||
r.x.cx = x;
|
|
||||||
r.x.dx = y;
|
|
||||||
__dpmi_int(0x33, &r);
|
__dpmi_int(0x33, &r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ $(TARGET): $(OBJS) $(LIBDIR)/libdvx.a $(LIBDIR)/libtasks.a | $(BINDIR)
|
||||||
rm -f $(BINDIR)/dvx
|
rm -f $(BINDIR)/dvx
|
||||||
|
|
||||||
$(CONFIGDIR)/dvx.ini: ../dvx.ini | $(CONFIGDIR)
|
$(CONFIGDIR)/dvx.ini: ../dvx.ini | $(CONFIGDIR)
|
||||||
cp $< $@
|
sed 's/$$/\r/' $< > $@
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue