Manage sdlmain's DOS video mode as an <optional>
DOSBox's execution sequence starts by initializing SDL
followed by starting the DOS normal loop, which eventually
sets the DOS video mode.
This commit makes sdlmain's DOS video mode member variable
optional because, with respect to sdlmain, the DOS video mode
doesn't exist (and may not exist) until the DOS side
successfully sets the video mode through the emulated video
card.
In terms of order of operations, Both the SDL and DOS side
can drive mode changes that involve switching the GL Shader
as well as logging the SDL window size or DOS display mode;
this commit lets those play out as-is.
Replace part of the SB 8-on/8-off buffer status with DMA buffer state
The eight on/off logic is split:
1. The off part is kept; we now report available room every 8th call.
2. The on part is replaced with an actual check of the DMA buffer state.
Previously, the SB's write buffer status could report "we're full,
we can't accept data" eight consecutive times, even when when the
DSP and DMA and totally idle. This behaviour causes SimLife and
the Crystal Dream demo to eventually give up on setting up their
DMA transfers.
So this replaces the "we're busy, we're busy, we're busy, ..." with
an actual check of the DMA status.. and if DMA isn't running or
at the minimum (about to run dry), then we say "we're available".
---
More notes from the PR review:
I created this based on logging what these games were doing (just
a bunch of LOGs in SB) combined with reading about the buffer
write check (in the ref'd docs).
86Box and DOSBox-X both calculate the playback rate of the current
DMA transfer and then steadily draining down that time until it
nears completion.
In this implementation, fortunately we've already got the dma.left
and dma.min values to see how close we are to the end of the
transfer.
One of the nuances is that games can change the playback rate as
well as switch from mono to stereo; so the drain down rate can
vary: and indeed, 86Box does this extra bookkeeping.
In our case, these rate changes are already taken care of by the
existing code, and it just happens that this threshold (dma.left
vs dma.min) will happen sooner if the rates are faster.
Scali had a through discussion about Sound Blaster seamless
playback using all the different DMA methods (autoinit, signle
init, and hacked methods)
https://www.vogons.org/viewtopic.php?t=52806. He wrote a nice
seamless playback tool, too (tested this PR with it, and it's
fine).