Skip to content

Commit 3fa7f96

Browse files
author
FeralChild64
committed
Add register-level PS/2 mouse access support
1 parent f241e98 commit 3fa7f96

15 files changed

+1047
-1017
lines changed

include/mouse.h

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2022-2022 The DOSBox Staging Team
2+
* Copyright (C) 2022-2023 The DOSBox Staging Team
33
* Copyright (C) 2002-2021 The DOSBox Team
44
*
55
* This program is free software; you can redistribute it and/or modify
@@ -111,18 +111,14 @@ void MOUSE_ToggleUserCapture(const bool pressed);
111111
// BIOS mouse interface for PS/2 mouse
112112
// ***************************************************************************
113113

114-
bool MOUSEBIOS_Enable();
115-
bool MOUSEBIOS_Disable();
116-
void MOUSEBIOS_SetCallback(const uint16_t pseg, const uint16_t pofs);
117-
void MOUSEBIOS_Reset();
118-
bool MOUSEBIOS_SetPacketSize(const uint8_t packet_size);
119-
bool MOUSEBIOS_SetSampleRate(const uint8_t rate_id);
120-
void MOUSEBIOS_SetScaling21(const bool enable);
121-
bool MOUSEBIOS_SetResolution(const uint8_t res_id);
122-
uint8_t MOUSEBIOS_GetProtocol();
123-
uint8_t MOUSEBIOS_GetStatus();
124-
uint8_t MOUSEBIOS_GetResolution();
125-
uint8_t MOUSEBIOS_GetSampleRate();
114+
void MOUSEBIOS_Subfunction_C2();
115+
116+
// ***************************************************************************
117+
// Register-level interface for PS/2 mouse
118+
// ***************************************************************************
119+
120+
void MOUSEPS2_FlushBuffer();
121+
bool MOUSEPS2_SendPacket();
126122

127123
// ***************************************************************************
128124
// DOS mouse driver

src/hardware/input/mouse.cpp

Lines changed: 32 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "mouse_config.h"
2222
#include "mouse_interfaces.h"
2323
#include "mouse_manymouse.h"
24-
#include "mouse_queue.h"
2524

2625
#include <algorithm>
2726
#include <cctype>
@@ -39,7 +38,6 @@ CHECK_NARROWING();
3938

4039
static callback_number_t int74_ret_callback = 0;
4140

42-
static MouseQueue &mouse_queue = MouseQueue::GetInstance();
4341
static ManyMouseGlue &manymouse = ManyMouseGlue::GetInstance();
4442

4543
// ***************************************************************************
@@ -384,65 +382,36 @@ static Bitu int74_exit()
384382

385383
static Bitu int74_handler()
386384
{
387-
MouseEvent ev;
388-
mouse_queue.FetchEvent(ev);
389-
390-
// Handle DOS events
391-
if (ev.request_dos) {
392-
uint8_t mask = 0;
393-
if (ev.dos_moved) {
394-
mask = MOUSEDOS_UpdateMoved();
395-
396-
// Taken from DOSBox X: HERE within the IRQ 12 handler
397-
// is the appropriate place to redraw the cursor. OSes
398-
// like Windows 3.1 expect real-mode code to do it in
399-
// response to IRQ 12, not "out of the blue" from the
400-
// SDL event handler like the original DOSBox code did
401-
// it. Doing this allows the INT 33h emulation to draw
402-
// the cursor while not causing Windows 3.1 to crash or
403-
// behave erratically.
404-
if (mask) {
405-
MOUSEDOS_DrawCursor();
406-
}
407-
}
408-
if (ev.dos_button) {
409-
const auto new_mask = mask | MOUSEDOS_UpdateButtons(ev.dos_buttons);
410-
mask = static_cast<uint8_t>(new_mask);
411-
}
412-
if (ev.dos_wheel) {
413-
const auto new_mask = mask | MOUSEDOS_UpdateWheel();
414-
mask = static_cast<uint8_t>(new_mask);
415-
}
416-
417-
// If DOS driver's client is not interested in this particular
418-
// type of event - skip it
419-
if (!MOUSEDOS_HasCallback(mask)) {
420-
return int74_exit();
421-
}
422-
423-
const auto real_pt = CALLBACK_RealPointer(int74_ret_callback);
424-
CPU_Push16(RealSeg(real_pt));
425-
CPU_Push16(RealOff(static_cast<RealPt>(real_pt) + 7));
426-
427-
return MOUSEDOS_DoCallback(mask, ev.dos_buttons);
428-
}
429-
430-
// Handle PS/2 and BIOS mouse events
431-
if (ev.request_ps2 && mouse_shared.active_bios) {
385+
// Try BIOS events (from Intel 8042 controller)
386+
if (MOUSEBIOS_CheckCallback()) {
432387
CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
433388
CPU_Push16(RealOff(CALLBACK_RealPointer(int74_ret_callback)));
389+
MOUSEBIOS_DoCallback();
390+
// TODO: Handle both BIOS and DOS callback within
391+
// in a single interrupt
392+
return CBRET_NONE;
393+
}
394+
395+
// Try DOS driver events
396+
if (!mouse_shared.dos_cb_running) {
397+
const auto mask = MOUSEDOS_DoInterrupt();
398+
if (mask) {
399+
const auto real_pt = CALLBACK_RealPointer(int74_ret_callback);
400+
CPU_Push16(RealSeg(real_pt));
401+
CPU_Push16(RealOff(static_cast<RealPt>(real_pt) + 7));
434402

435-
MOUSEPS2_UpdatePacket();
436-
return MOUSEBIOS_DoCallback();
403+
MOUSEDOS_DoCallback(mask);
404+
return CBRET_NONE;
405+
}
437406
}
438407

439-
// No mouse emulation module is interested in event
408+
// No mouse emulation module is interested in the event
440409
return int74_exit();
441410
}
442411

443412
Bitu int74_ret_handler()
444413
{
445-
mouse_queue.StartTimerIfNeeded();
414+
MOUSEDOS_FinalizeInterrupt();
446415
return CBRET_NONE;
447416
}
448417

@@ -507,29 +476,13 @@ void MOUSE_NotifyWindowActive(const bool is_active)
507476
MOUSE_UpdateGFX();
508477
}
509478

510-
void MOUSE_NotifyResetDOS()
511-
{
512-
mouse_queue.ClearEventsDOS();
513-
}
514-
515479
void MOUSE_NotifyDisconnect(const MouseInterfaceId interface_id)
516480
{
517481
auto interface = MouseInterface::Get(interface_id);
518482
if (interface)
519483
interface->NotifyDisconnect();
520484
}
521485

522-
void MOUSE_NotifyFakePS2()
523-
{
524-
const auto interface = MouseInterface::GetPS2();
525-
526-
if (interface && interface->IsUsingEvents()) {
527-
MouseEvent ev;
528-
ev.request_ps2 = true;
529-
mouse_queue.AddEvent(ev);
530-
}
531-
}
532-
533486
void MOUSE_NotifyBooting()
534487
{
535488
for (auto &interface : mouse_interfaces)
@@ -567,14 +520,11 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel,
567520
// so it needs data in both formats.
568521

569522
// Notify mouse interfaces
570-
571-
MouseEvent ev;
572523
for (auto &interface : mouse_interfaces)
573524
if (interface->IsUsingHostPointer())
574-
interface->NotifyMoved(ev, x_rel, y_rel,
525+
interface->NotifyMoved(x_rel, y_rel,
575526
state.cursor_x_abs,
576527
state.cursor_y_abs);
577-
mouse_queue.AddEvent(ev);
578528
}
579529

580530
void MOUSE_EventMoved(const float x_rel, const float y_rel,
@@ -587,11 +537,10 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel,
587537
return;
588538
}
589539

540+
// Notify mouse interface
590541
auto interface = MouseInterface::Get(interface_id);
591542
if (interface && interface->IsUsingEvents()) {
592-
MouseEvent ev;
593-
interface->NotifyMoved(ev, x_rel, y_rel, 0, 0);
594-
mouse_queue.AddEvent(ev);
543+
interface->NotifyMoved(x_rel, y_rel, 0, 0);
595544
}
596545
}
597546

@@ -629,11 +578,10 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed)
629578
}
630579
}
631580

632-
MouseEvent ev;
581+
// Notify mouse interfaces
633582
for (auto &interface : mouse_interfaces)
634583
if (interface->IsUsingHostPointer())
635-
interface->NotifyButton(ev, idx, pressed);
636-
mouse_queue.AddEvent(ev);
584+
interface->NotifyButton(idx, pressed);
637585
}
638586

639587
void MOUSE_EventButton(const uint8_t idx, const bool pressed,
@@ -648,11 +596,10 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed,
648596
return;
649597
}
650598

599+
// Notify mouse interface
651600
auto interface = MouseInterface::Get(interface_id);
652601
if (interface && interface->IsUsingEvents()) {
653-
MouseEvent ev;
654-
interface->NotifyButton(ev, idx, pressed);
655-
mouse_queue.AddEvent(ev);
602+
interface->NotifyButton(idx, pressed);
656603
}
657604
}
658605

@@ -665,11 +612,10 @@ void MOUSE_EventWheel(const int16_t w_rel)
665612
return;
666613
}
667614

668-
MouseEvent ev;
615+
// Notify mouse interfaces
669616
for (auto &interface : mouse_interfaces)
670617
if (interface->IsUsingHostPointer())
671-
interface->NotifyWheel(ev, w_rel);
672-
mouse_queue.AddEvent(ev);
618+
interface->NotifyWheel(w_rel);
673619
}
674620

675621
void MOUSE_EventWheel(const int16_t w_rel, const MouseInterfaceId interface_id)
@@ -681,11 +627,10 @@ void MOUSE_EventWheel(const int16_t w_rel, const MouseInterfaceId interface_id)
681627
return;
682628
}
683629

630+
// Notify mouse interface
684631
auto interface = MouseInterface::Get(interface_id);
685632
if (interface && interface->IsUsingEvents()) {
686-
MouseEvent ev;
687-
interface->NotifyWheel(ev, w_rel);
688-
mouse_queue.AddEvent(ev);
633+
interface->NotifyWheel(w_rel);
689634
}
690635
}
691636

@@ -1041,7 +986,7 @@ void MOUSE_StartupIfReady()
1041986
: "be sent to the game/program (clicks not used to capture/release)");
1042987
}
1043988

1044-
// Callback for ps2 irq
989+
// Callback for PS/2 BIOS or DOS driver IRQ
1045990
auto call_int74 = CALLBACK_Allocate();
1046991
CALLBACK_Setup(call_int74, &int74_handler, CB_IRQ12, "int 74");
1047992
// pseudocode for CB_IRQ12:

src/hardware/input/mouse_common.h

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2022-2022 The DOSBox Staging Team
2+
* Copyright (C) 2022-2023 The DOSBox Staging Team
33
*
44
* This program is free software; you can redistribute it and/or modify
55
* it under the terms of the GNU General Public License as published by
@@ -155,19 +155,4 @@ union MouseButtons12S {
155155
MouseButtons12S &operator=(const MouseButtons12S &other);
156156
};
157157

158-
// ***************************************************************************
159-
// Internal mouse event types
160-
// ***************************************************************************
161-
162-
struct MouseEvent {
163-
bool request_dos = false; // if DOS mouse driver needs an event
164-
bool request_ps2 = false; // if PS/2 mouse emulation needs an event
165-
166-
bool dos_moved = false;
167-
bool dos_button = false;
168-
bool dos_wheel = false;
169-
170-
MouseButtons12S dos_buttons = 0;
171-
};
172-
173158
#endif // DOSBOX_MOUSE_COMMON_H

src/hardware/input/mouse_config.cpp

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@
3131

3232
CHECK_NARROWING();
3333

34-
// TODO - IntelliMouse Explorer emulation is currently deactivated - there is
35-
// probably no way to test it. The IntelliMouse 3.0 software can use it, but
36-
// it seems to require physical PS/2 mouse registers to work correctly,
37-
// and these are not emulated yet.
38-
39-
// #define ENABLE_EXPLORER_MOUSE
40-
4134
MouseConfig mouse_config;
4235
MousePredefined mouse_predefined;
4336

@@ -48,9 +41,8 @@ constexpr auto capture_type_nomouse_str = "nomouse";
4841

4942
constexpr auto model_ps2_standard_str = "standard";
5043
constexpr auto model_ps2_intellimouse_str = "intellimouse";
51-
#ifdef ENABLE_EXPLORER_MOUSE
52-
constexpr auto model_ps2_explorer_str = "explorer";
53-
#endif
44+
constexpr auto model_ps2_explorer_str = "explorer";
45+
constexpr auto model_ps2_nomouse_str = "none";
5446

5547
constexpr auto model_com_2button_str = "2button";
5648
constexpr auto model_com_3button_str = "3button";
@@ -68,13 +60,12 @@ static const char *list_capture_types[] = {
6860
nullptr
6961
};
7062

71-
static const char *list_models_ps2[] = {
63+
static const char* list_models_ps2[] = {
7264
model_ps2_standard_str,
73-
model_ps2_intellimouse_str,
74-
#ifdef ENABLE_EXPLORER_MOUSE
75-
model_ps2_explorer_str,
76-
#endif
77-
nullptr
65+
model_ps2_intellimouse_str,
66+
model_ps2_explorer_str,
67+
model_ps2_nomouse_str,
68+
nullptr
7869
};
7970

8071
static const char *list_models_com[] = {
@@ -166,16 +157,17 @@ bool MouseConfig::ParseCOMModel(const std::string &model_str,
166157

167158
bool MouseConfig::ParsePS2Model(const std::string &model_str, MouseModelPS2 &model)
168159
{
169-
if (model_str == model_ps2_standard_str)
160+
if (model_str == model_ps2_standard_str) {
170161
model = MouseModelPS2::Standard;
171-
else if (model_str == model_ps2_intellimouse_str)
162+
} else if (model_str == model_ps2_intellimouse_str) {
172163
model = MouseModelPS2::IntelliMouse;
173-
#ifdef ENABLE_EXPLORER_MOUSE
174-
else if (model_str == model_ps2_explorer_str)
164+
} else if (model_str == model_ps2_explorer_str) {
175165
model = MouseModelPS2::Explorer;
176-
#endif
177-
else
166+
} else if (model_str == model_ps2_nomouse_str) {
167+
model = MouseModelPS2::NoMouse;
168+
} else {
178169
return false;
170+
}
179171
return true;
180172
}
181173

@@ -324,19 +316,19 @@ static void config_init(Section_prop &secprop)
324316

325317
// Physical mice configuration
326318

327-
prop_str = secprop.Add_string("ps2_mouse_model", only_at_start,
328-
model_ps2_intellimouse_str);
319+
// TODO: PS/2 mouse might be hot-pluggable
320+
prop_str = secprop.Add_string("ps2_mouse_model",
321+
only_at_start,
322+
model_ps2_explorer_str);
329323
assert(prop_str);
330324
prop_str->Set_values(list_models_ps2);
331325
prop_str->Set_help(
332326
"PS/2 AUX port mouse model:\n"
333-
// TODO - Add option "none"
334327
" standard: 3 buttons, standard PS/2 mouse.\n"
335-
" intellimouse: 3 buttons + wheel, Microsoft IntelliMouse (default)."
336-
#ifdef ENABLE_EXPLORER_MOUSE
337-
"\n explorer: 5 buttons + wheel, Microsoft IntelliMouse Explorer."
338-
#endif
339-
);
328+
" intellimouse: 3 buttons + wheel, Microsoft IntelliMouse.\n"
329+
" explorer: 5 buttons + wheel, Microsoft IntelliMouse Explorer.\n"
330+
" none: no PS/2 mouse emulated.\n"
331+
"Default: explorer");
340332

341333
prop_str = secprop.Add_string("com_mouse_model",
342334
only_at_start,

src/hardware/input/mouse_config.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ extern MousePredefined mouse_predefined;
5959
enum class MouseCapture : uint8_t { Seamless, OnClick, OnStart, NoMouse };
6060

6161
enum class MouseModelPS2 : uint8_t {
62-
// Values must match PS/2 protocol IDs
62+
NoMouse = 0xff,
63+
// Values below must match PS/2 protocol IDs
6364
Standard = 0x00,
6465
IntelliMouse = 0x03,
6566
Explorer = 0x04,

0 commit comments

Comments
 (0)