mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-09 03:41:10 +08:00
INT 33h: Games like Lemmings do things with INT 33h that confuse the auto-range detction code. Rather than make the code complicated and convoluted, add dosbox.conf options to manually specify ranges and other INT 33h adjustments.
This commit is contained in:
parent
2ee49ddb57
commit
61e4460f27
@ -1,4 +1,12 @@
|
||||
Next:
|
||||
- INT 33 mouse emulation: Add dosbox.conf options to force a specific
|
||||
coordinate system for the DOS game with respect to host/guest mouse
|
||||
cursor integration (getting the DOS cursor to match the host cursor
|
||||
within the window). Add dosbox.conf option where additional adjustments
|
||||
are available. The maximum x/y and max-adjust options are ideal for
|
||||
Lemmings 2, which uses INT 33h in a way that confuses the automatic
|
||||
range detection code used to synchronize cursor position and therefore
|
||||
needs this option, and the first Lemmings as well. (joncampbell123).
|
||||
- PIT timer: Fix restart_counter(), the delay computation was completely
|
||||
backwards. This is particularly important where it concerns programs
|
||||
that use the PIT to detect the rate at which the Pentium time stamp
|
||||
|
@ -4564,6 +4564,22 @@ void DOSBOX_SetupConfigSections(void) {
|
||||
Pbool->Set_help("Enable INT 33H for mouse support.");
|
||||
Pbool->SetBasic(true);
|
||||
|
||||
Pint = secprop->Add_int("int33 max x", Property::Changeable::WhenIdle, 0);
|
||||
Pint->Set_help("For guest to host cursor integration with DOS games, assume the maximum reported X coordinate has this value, if this is nonzero.\n"
|
||||
"Use this option if the automatic range detection fails to work correctly with the DOS game and the cursor doesn't match the host cursor position.\n"
|
||||
"- Lemmings 2: Use X=640 Y=400");
|
||||
|
||||
Pint = secprop->Add_int("int33 max y", Property::Changeable::WhenIdle, 0);
|
||||
Pint->Set_help("For guest to host cursor integration with DOS games, assume the maximum reported Y coordinate has this value, if this is nonzero.\n"
|
||||
"Use this option if the automatic range detection fails to work correctly with the DOS game and the cursor doesn't match the host cursor position.\n"
|
||||
"- See the max X setting for a list of games");
|
||||
|
||||
Pstring = secprop->Add_string("int33 xy adjust",Property::Changeable::OnlyAtStart,"");
|
||||
Pstring->Set_help("A list of adjustments to INT 33h position adjustments to help align the guest cursor to the host. name=value, comma separated\n"
|
||||
"x=spec, y=spec\n"
|
||||
"spec: <number> position adjust, can be positive or negative\n"
|
||||
" max-excess if game sets maximum larger than int33 max x/y, adjust the position forward by the difference");
|
||||
|
||||
Pint = secprop->Add_int("mouse report rate",Property::Changeable::WhenIdle,0);
|
||||
Pint->Set_help("Mouse reporting rate, or 0 for auto. This affects how often mouse events are reported to the guest through the mouse interrupt.\n"
|
||||
"Some games including CyClone need a lower reporting rate to function correctly. Auto mode allows the guest to change the report rate through the PS/2 mouse emulation.\n"
|
||||
|
@ -47,6 +47,10 @@
|
||||
# pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
|
||||
#endif
|
||||
|
||||
static bool adjust_x_max_excess = false,adjust_y_max_excess = false;
|
||||
static unsigned int assume_max_x = 0,assume_max_y = 0;
|
||||
static int adjust_x = 0,adjust_y = 0;
|
||||
|
||||
#define VMWARE_PORT 0x5658u // communication port
|
||||
#define VMWARE_PORTHB 0x5659u // communication port, high bandwidth
|
||||
static Bitu PortRead(Bitu port, Bitu iolen);
|
||||
@ -895,6 +899,29 @@ void Mouse_CursorMoved(float xrel,float yrel,float x,float y,bool emulate) {
|
||||
mouse.x = x1 * mouse.max_screen_x;
|
||||
mouse.y = y1 * mouse.max_screen_y;
|
||||
|
||||
/* Cursor adjustment to help in-game cursor match host:
|
||||
*
|
||||
* x=[-]adjustment i.e. x=5 or x=-8
|
||||
* y=[-]adjustment i.e. y=8 or y=-10 */
|
||||
mouse.x += adjust_x;
|
||||
mouse.y += adjust_y;
|
||||
/* When used with int33 max x/y:
|
||||
* max-excess can be specified to state that if the game set the maximum
|
||||
* past the dosbox.conf max value, that the x/y coordinates are adjusted
|
||||
* by the difference, for use with games that make use of the min/max
|
||||
* constraint per screen and offset the min/max by some offset (Lemmings 2).
|
||||
*
|
||||
* x=max-excess
|
||||
* y=max-excess */
|
||||
if (adjust_x_max_excess) {
|
||||
if (mouse.max_x > (int)assume_max_x)
|
||||
mouse.x += (mouse.max_x - assume_max_x);
|
||||
}
|
||||
if (adjust_y_max_excess) {
|
||||
if (mouse.max_y > (int)assume_max_y)
|
||||
mouse.y += (mouse.max_y - assume_max_y);
|
||||
}
|
||||
|
||||
if (mouse.x < mouse.min_x)
|
||||
mouse.x = mouse.min_x;
|
||||
if (mouse.y < mouse.min_y)
|
||||
@ -1455,8 +1482,15 @@ void Mouse_AfterNewVideoMode(bool setmode) {
|
||||
mouse.cursorType = 0;
|
||||
mouse.enabled=true;
|
||||
|
||||
mouse.max_screen_x = mouse.max_x;
|
||||
mouse.max_screen_y = mouse.max_y;
|
||||
if (assume_max_x > 0)
|
||||
mouse.max_screen_x = assume_max_x;
|
||||
else
|
||||
mouse.max_screen_x = mouse.max_x;
|
||||
|
||||
if (assume_max_y > 0)
|
||||
mouse.max_screen_y = assume_max_y;
|
||||
else
|
||||
mouse.max_screen_y = mouse.max_y;
|
||||
}
|
||||
|
||||
//Much too empty, Mouse_NewVideoMode contains stuff that should be in here
|
||||
@ -1650,7 +1684,7 @@ static Bitu INT33_Handler(void) {
|
||||
* set after mode set is the only way to make sure mouse pointer integration
|
||||
* tracks the guest pointer properly. */
|
||||
if (mouse.first_range_setx || mouse.buttons == 0) {
|
||||
if (mouse.min_x == 0 && mouse.max_x > 0) {
|
||||
if (mouse.min_x == 0 && mouse.max_x > 0 && assume_max_x == 0) {
|
||||
// most games redefine the range so they can use a saner range matching the screen
|
||||
int16_t nval = mouse.max_x;
|
||||
|
||||
@ -1719,7 +1753,7 @@ static Bitu INT33_Handler(void) {
|
||||
* set after mode set is the only way to make sure mouse pointer integration
|
||||
* tracks the guest pointer properly. */
|
||||
if (mouse.first_range_sety || mouse.buttons == 0) {
|
||||
if (mouse.min_y == 0 && mouse.max_y > 0) {
|
||||
if (mouse.min_y == 0 && mouse.max_y > 0 && assume_max_y == 0) {
|
||||
// most games redefine the range so they can use a saner range matching the screen
|
||||
int16_t nval = mouse.max_y;
|
||||
|
||||
@ -2316,6 +2350,49 @@ void MOUSE_Startup(Section *sec) {
|
||||
user_mouse_report_rate=section->Get_int("mouse report rate");
|
||||
UpdateMouseReportRate();
|
||||
|
||||
assume_max_x=section->Get_int("int33 max x");
|
||||
assume_max_y=section->Get_int("int33 max y");
|
||||
|
||||
{
|
||||
const char *s = section->Get_string("int33 xy adjust");
|
||||
while (*s != 0) {
|
||||
if (*s == ' ') {
|
||||
s++;
|
||||
}
|
||||
else {
|
||||
const char *base = s;
|
||||
while (*s != 0 && *s != ',' && *s != '=') s++;
|
||||
std::string name = std::string(base,(size_t)(s-base)),value;
|
||||
if (*s == '=') {
|
||||
s++;
|
||||
base = s;
|
||||
while (*s != 0 && *s != ',') s++;
|
||||
value = std::string(base,(size_t)(s-base));
|
||||
}
|
||||
if (*s == ',') s++;
|
||||
|
||||
if (name == "x") {
|
||||
const char *v = value.c_str();
|
||||
if (isdigit(*v) || (*v == '-' && isdigit(v[1]))) {
|
||||
adjust_x = atoi(v);
|
||||
}
|
||||
else if (!strcmp(v,"max-excess")) {
|
||||
adjust_x_max_excess = true;
|
||||
}
|
||||
}
|
||||
else if (name == "y") {
|
||||
const char *v = value.c_str();
|
||||
if (isdigit(*v) || (*v == '-' && isdigit(v[1]))) {
|
||||
adjust_y = atoi(v);
|
||||
}
|
||||
else if (!strcmp(v,"max-excess")) {
|
||||
adjust_y_max_excess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
en_int33_hide_if_intsub=section->Get_bool("int33 hide host cursor if interrupt subroutine");
|
||||
|
||||
en_int33_hide_if_polling=section->Get_bool("int33 hide host cursor when polling");
|
||||
|
Loading…
x
Reference in New Issue
Block a user