VOGONS


First post, by evo

User metadata
Rank Newbie
Rank
Newbie

While experimenting with ultima7 in dosbox, I came accross some annoying bug that forced the mouse to freeze now and then. Even reseting the mouse driver (int 33, ax=0) wouldn't help and I was forced to restart dosbox. Well, as the bug seemed trivial (which in fact was not the case) I couldn't resist to hunt it down, but frequent lock-ups during u7 start prevented me from doing so. I was generating rapid mouse events by moving the mouse because I knew it was triggering the bug.
It turned out after some debugging (which helped me getting somewhat familiar with the code and the debugging capabilities) that both are actually symptoms of the same, obviously mouse-related bug.

What happens is the following:
Ultima7.com controls the basic program flow and launches several subprocesses, such as intro, mainmenu.exe, main game (u7.exe).
mainmenu.exe registers a mouse handler by means of int 33h, ax=14h (swap mouse handler) and it saves the original one into a variable I will simply call "origHandler" and which it restores before mainmenu.exe terminates (again by means of swap handler).

Now, the problem is that mainmenu.exe tests if origHandler is null pointer to decide whether it has already set its mouse handler (origHandler is 0 at program start). But since swap mouse handler returns 0000:0000 just after a mouse reset (i.e. no mouse handler at all), mainmenu.exe thinks it didn't set the handler yet and calls "swap mouse handler" a second time, but this time, it receives a pointer to its own handler which it set before. It is clear that after termination of mainmenu.exe, the handler will point to some piece of code which will be overwritten after another program is lauched (u7.exe in my case). Now, if I generate a mouse event before u7.exe sets again a mouse handler ... well you can imagine what happens 😀
Either the cpu gets stuck somewhere or, if you're lucky, it eventually "returns" from the "random code handler" if accidentally run over a ret or by some other means, but no EOI (end of interrupt) is generated which results in IRQ 12 never being raised again (not even after a mouse reset), thus freezing the mouse.
After checking some docs on the int 33h interface I couln't find any useful information about what int 33h /ax=14h should return. In fact I checked several mouse drivers and they aswell return 0000:0000 if there's no handler yet. This is clearly a bug in mainmenu.exe and it appears also in a real dos environment (I tried within bochs). For some strange reason I cannot remember having those troubles 10 years ago playing it on real hardware...
Fine, to avoid it simply don't move the mouse when loading. But this doesn't satisfy me.
The following changes came to my mind:

- return a pointer to a dummy handler (just a retf) (Q. to the devs: is there any memory region where one could place such a code, like an area reserved for DOS? Could aswell move it into the BIOS). This would allow also programs that don't check for null pointers to chain mouse handlers. I'm not sure whether any programs do this and the int-33h specs I found keep silent about this. But certainly, the u7 devs relied on the mouse driver returning something non-zero.

- to prevent the mouse from permantly freezing one could send the EOI *before* calling the custom mouse handler (that's also how cutemouse does it). Still, a handler should be called only once we returned from the previous handler (thus, there's a tiny chance to miss an event which is certainly worse - but that's how cutemouse does it if I understood the sources correctly...). To me, it is not clear whether handlers should be locked - but I think they should, just to be on the safe side. Also, a mouse reset should make sure that the corresponding IRQ bit in the ISR register is cleared.

What do other devs think?

Also the current implementation of mouse sensitivity is not satisfactory for me. In fullscreen mode, the OSes mouse sensitivity behavior doesn't propagate (via SDL) to dosbox, so mouse is very slow and I have to set the sensitivity to 400. But if i do so, the mouse jumps in 4-pixel steps which is inacceptable for certain games. The solution is trivial: only apply the acceleration if a certain motion threshold is reached. This way you have a quick motion if moving the mouse fast, but retain a pixel accurate selection.

PS (a little off topic):
- It would be of advantage (for new developers at least) if the code was a *little* better documented. I mean, its not easy to find any comments at all (at least the parts I was looking into, especially the dynamic core), and it really slows down understanding the code. Anyways, I realized I wouldn't understand my own code anymore after some years, that's why I spend more time writing comments than code nowadays ... well almost 😉
- There's lots of room for improvement (dynamic core, video memory access, ... haven't looked into more yet). I've made some experimental changes and I got drastic speed increases in certain situations (such that the dynamic core is no longer slower than the normal one 😀 ). Anyways, it's not easy for me to properly do some optimations without the risk of breaking something. I simply lack the overall understanding of the whole code and the rather complex dependencies that have grown. Thus, things will take time so I postpone this into the future.
- forgive me if I wasted your time reading this long post

Reply 1 of 10, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Interesting, didn't notice that before. Kicks in only rarely, but is reproducable.
The (maybe only some) ms mousedriver returns a value in ES when calling
int33/ah=14 after a mouse reset. The code at es:dx is zero though, but
this doesn't matter as cx is zero as well so the condition is never met.
That's why it worked for me when booting msdos+msmouse under dosbox.

> It would be of advantage (for new developers at least) if the code was a *little* better documented.

Most code can simply be understood by looking through the according manuals.
Though i'd prefer heavily documented sources as well. Just ask if something
is unclear (and is no bug 😉 ).

> forgive me if I wasted your time reading this long post

Just write shorter ones 😀

Reply 2 of 10, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

comments: yes we could add more to them 😀 But for the mouse you shouldn't be accessing the dynamic core. although for your possbile optimalisation of the dynamic core on selfgenerating code it might be so.

which type of reset does u7 use ? 0 or 21 (hard or software).
int 70 is "high" number those are usually kept/set on zero by the bios.
but I assume you are talking about the USR ?

There are several iret/retfs and such allready stored in the DOSBox memory. There are several parts in which they are kept. (DOS_GetMemory and a few of the bios areas)

sending a eoi before the handling the data is less damaging in DOSBox as it is on a real pc. however as all operations on the pic are instantanously it might give some odd effects. The question is what is correct...Stuff like that is rarely well documented.

The mouse in fullscreen is an SDL problem. We solely rely on that.
We don't have a double speed treshold, but we do have a scaling based on the events you create.

Water flows down the stream
How to ask questions the smart way!

Reply 3 of 10, by evo

User metadata
Rank Newbie
Rank
Newbie
Qbix wrote:

comments: yes we could add more to them 😀 But for the mouse you shouldn't be accessing the dynamic core. although for your possbile optimalisation of the dynamic core on selfgenerating code it might be so.

You are right, though at present my patch is intended to handle what I attributed "weakly self modifying code". But the current implementation is more of a hack than properly designed and more improvement is still possible.

Qbix wrote:

which type of reset does u7 use ? 0 or 21 (hard or software).
int 70 is "high" number those are usually kept/set on zero by the bios.
but I assume you are talking about the USR ?

It uses 0, but that doesn't matter. I was actually talking about the in-service register (ISR). In the code, this seems to be the variable "inservice", but I had to find out it's not really checked when raising IRQs (am I wrong here ??) Is this considered to be auto-EOI? Anyways, I have to recheck where it actually hangs, I never did it because seeing that the CB_IRQ12_RET part was not executed things were evident for me which no longer it is...I can only check once I am at home. Btw, what is the USR? I never heard that.

Qbix wrote:

There are several iret/retfs and such allready stored in the DOSBox memory. There are several parts in which they are kept. (DOS_GetMemory and a few of the bios areas)

sending a eoi before the handling the data is less damaging in DOSBox as it is on a real pc. however as all operations on the pic are instantanously it might give some odd effects. The question is what is correct...Stuff like that is rarely well documented.

It's still a mystery to me how exactly the pic implementation works, so I'm rather not touching it. Anyways it's ages ago that I messed with that stuff so I have to read into it.

Qbix wrote:

The mouse in fullscreen is an SDL problem. We solely rely on that.
We don't have a double speed treshold, but we do have a scaling based on the events you create.

Yes, I'm aware of that, but the current pure scaling approach might be unsatisfactory in cases (you simply loose accuracy on high sensitivity settings), and there's no problem to add another (user defined) variable that controls the threshold. People can set it to 0 if they don't want it.

Reply 4 of 10, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author
evo wrote:
Qbix wrote:

which type of reset does u7 use ? 0 or 21 (hard or software).
int 70 is "high" number those are usually kept/set on zero by the bios.
but I assume you are talking about the USR ?

It uses 0, but that doesn't matter. I was actually talking about the in-service register (ISR). In the code, this seems to be the variable "inservice", but I had to find out it's not really checked when raising IRQs (am I wrong here ??) Is this considered to be auto-EOI? Anyways, I have to recheck where it actually hangs, I never did it because seeing that the CB_IRQ12_RET part was not executed things were evident for me which no longer it is...I can only check once I am at home. Btw, what is the USR? I never heard that.

My mistake. I was refering to installable mouse handler.
UIR (user interrupt routine).

[/quote]Yes, I'm aware of that, but the current pure scaling approach might be unsatisfactory in cases (you simply loose accuracy on high sensitivity settings), and there's no problem to add another (user defined) variable that controls the threshold. People can set it to 0 if they don't want it.[/quote]

I'm not convinced it is a dosbox problem/bug.
However you might want to "experiment" with the scaling between the game resolution and the fullscreenresulotion you set in the configfile. if you change the mousemovements with that amount your "problem" might be fixed. (you probably have to touch src/gui/sdlmain.cpp (there the mouse movents are reported to the mouse driver of DOSBox. there you can easely scale the movements as the resoltution scaling should be calculatable from there as well.

About the bug you might want to read wd's post above mine.
We posted around the same time and I missed it the first time.

The statement that MS mouse returns es!=0 might be the clue for your problem.

Water flows down the stream
How to ask questions the smart way!

Reply 5 of 10, by evo

User metadata
Rank Newbie
Rank
Newbie
Qbix wrote:

I'm not convinced it is a dosbox problem/bug.
However you might want to "experiment" with the scaling between the game resolution and the fullscreenresulotion you set in the configfile. if you change the mousemovements with that amount your "problem" might be fixed. (you probably have to touch src/gui/sdlmain.cpp (there the mouse movents are reported to the mouse driver of DOSBox. there you can easely scale the movements as the resoltution scaling should be calculatable from there as well.

No it's not a bug, it's a missing feature 😀 I will try, but i'm not conviced it works for me (in high-res games e.g.)
Oh and mouse in "non-locking" mode is not working correctly in text mode.
Fix again is simple except for some non-standard text modes (80x50) I still have to figure out how.

Qbix wrote:

About the bug you might want to read wd's post above mine.
We posted around the same time and I missed it the first time.

The statement that MS mouse returns es!=0 might be the clue for your problem.

I know, the bug I was facing is fixed with returning a dummy handler or just something not pointing to anything reasonable. Still, while I'm at it, I try to understand things and look for best possible solutions. Thats why I was still thinking about the handler "problem". It's just that I try to get everything perfect... Anyways, as long as programs behave nicely it shouldn't be a problem and can stay like that.

Reply 6 of 10, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Dosbox returns 0:0 by default because it is assumed that games use it to
check the presence (or absence) of some previous handler. But it seems
to be reasonable to have some useless values there as well (like msmouse)
as long as cx (mask) is zero.
I didn't debug the origin of the value that msmouse returns yet. But it
definitely does NOT point at some valid code.

> No it's not a bug, it's a missing feature

Dunno, but the video interface (SDL/host OS) should be capable of
returning correct mouse positions depending on the video mode.
It works fine on most pcs/OSs btw.

Reply 7 of 10, by evo

User metadata
Rank Newbie
Rank
Newbie
wd wrote:
Dosbox returns 0:0 by default because it is assumed that games use it to check the presence (or absence) of some previous handle […]
Show full quote

Dosbox returns 0:0 by default because it is assumed that games use it to
check the presence (or absence) of some previous handler. But it seems
to be reasonable to have some useless values there as well (like msmouse)
as long as cx (mask) is zero.
I didn't debug the origin of the value that msmouse returns yet. But it
definitely does NOT point at some valid code.

> No it's not a bug, it's a missing feature

Dunno, but the video interface (SDL/host OS) should be capable of
returning correct mouse positions depending on the video mode.
It works fine on most pcs/OSs btw.

I mean, it works perfect, it's just slow I have to move the mouse over the whole table to go from left to right (well, not that much, but you get what I mean 😀 ) It's exactly the same as if I completely disabled mouse acceleration of the window manager. But the point is, that SDL ignores the settings of the WM, not only in full screen mode, but also when the mouse is locked in window mode, so same thing there.

Reply 8 of 10, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

> But the point is, that SDL ignores the settings of the WM

I don't know much about that, but as Qbix said this isn't something that
dosbox can/should control then. As i said, the behaviour you describe
isn't present for me and a very wide range of users, so SDL isn't that
wrong at all 😉
Maybe there's even some SDL switch to control the window manager
mouse acceleration handling.

Reply 9 of 10, by evo

User metadata
Rank Newbie
Rank
Newbie
wd wrote:
> But the point is, that SDL ignores the settings of the WM […]
Show full quote

> But the point is, that SDL ignores the settings of the WM

I don't know much about that, but as Qbix said this isn't something that
dosbox can/should control then. As i said, the behaviour you describe
isn't present for me and a very wide range of users, so SDL isn't that
wrong at all 😉
Maybe there's even some SDL switch to control the window manager
mouse acceleration handling.

No idea, but in either case I agree that this better belong into the SDL at least. But something is buggy there I get a crash if I set it. Maying I'll check that later when I can be bothered.

Reply 10 of 10, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

About the mouse14 swap user handler function: the ms and compatible
(logitech the only one i found) set the segment to a bogus value by
default, all other mouse drivers which return zero crash ultima7 in
the way you described it.