AUTOTYPE performs scripted keyboard entry into the running
DOS program.
It can be used to reliably skip intros, answer Q&A style questions
that some games ask on startup, or conduct a simple demo.
It allows for delaying input by any number of fractional seconds,
as well defining the pacing between keystrokes. It uses the
comma character "," to insert additional delays similar to modern
phone numbers.
It uses key_* names as defined by the mapper to avoid using SDL
scancodes[1], which are unstable across platforms. This approach
also allows the triggering of custom key bindings the use has
defined.
[1] https://wiki.libsdl.org/SDL_GetScancodeName
"Warning: The returned name is by design not stable across
platforms, e.g. the name for SDL_SCANCODE_LGUI is "Left GUI" under
Linux but "Left Windows" under Microsoft Windows, and some
scancodes like SDL_SCANCODE_NONUSBACKSLASH don't have any name at
all. There are even scancodes that share names, e.g.
SDL_SCANCODE_RETURN and SDL_SCANCODE_RETURN2 (both called
"Return"). This function is therefore unsuitable for creating a
stable cross-platform two-way mapping between strings and
scancodes."
In the previous code, if the game attempted to seek beyond the track
length, or if a "seek & read" would add up to going beyond the
end-of-the-track, the code would pass those requests to the underlying
codecs to handle (and reject with a corresponding error code).
This PR moves those checks up into the CDROM CD-DA code, and will
short-circuit them. Illegal seeks won't be attempted, however the usual
negative return code will still be passed to the game just like before.
Likewise, reads beyond the end will be pruned so they will get as much
audio as possible, without asking the codec for extra.
In an earlier change, I removed appending newline outside of batch mode
in DOS shell code - that made DOSBox behave less like MS-DOS and more
like modern shells, that do not try to compensate for buggy
applications.
However, we should recognize that DOSBox (unlike e.g. FreeDOS) is designed
to run legacy applications, which might make assumptions about DOS
implementation. Some examples:
- PC Player Benchmark assumes, that help commands are displayed exactly
at 80x25 terminal and formats the output to fill the whole screen
(scrolling past DOS4GW messages).
- Quake and other ID games print shareware information on exit, but do
it via a direct memory dump (not interrupts to print DOS text), and
follow up with setting cursor exactly at line 22 (which is partly
written already), expecting shell to inject newline.
- PCC Compiler prints status message on exit without newline, depending
on MS-DOS shell behaviour.
- TEXTUTIL set of external commands do not print nothing to standard
output, and are designed to clear the screen, therefore writing a
newline after .COM commands would be a mistake.
Therefore we want to inject this newline, but not in every case.
New implementation reuses a static variable used by Program base class
(for purpose of translating UNIX newlines to DOS newlines) for detection
if it's appropriate to inject an additional newline or not.
Injecting the newline happens in function displaying the DOS prompt (so
we don't need to write additonal logic for separately handling batch
mode). When starting a non-COM, non-internal command the static variable
is set to the state indicating that next DOS prompt should inject the
newline.
Fixes: #208
Some games repeatedly query for the first track's position during
playback, perhaps as a dual-purpose "CDROM health/heart-beat"
check.
This excessive console output in DEBUG mode tends to add far more
noise than signal, and prevents the maintainer from seeing the
overall flow of the CDROM calls.
Moves to using a member vector to provide a persistent buffer,
instead of repeatedly allocating and deleting memory on every
invocation (during DAE, this can be called hundreds of times
per second, with requsts of up 24 sectors or ~56KB of memory
per call).
The buffer is only resized upward, which avoids 'zig-zag'
re-allocations when switching between raw (2352-byte) and cooked
(2048-byte) sectors.
Only writes as much data was was successfully read into
the DOS program's buffer, avoiding (potential) garbage-fill.
This commit:
- Adds more sanity checks and comments
- Lets the seek() function to take care of monitoring the track's
post-seek decode position, instead of managing it in read(..).
- Adds in-place conversion from mono-to-stereo
- Adds micro-second-level DEBUG timing around the mono converter
- Makes use of the more intuitive ceil_divide() support function
to avoid excessive casting and floating-point conversion.
This commit:
- Comments why we convert from byte-to-time offset.
- Checks for underlying stream validity before seeking.
- Tracks the new as-seeked decode position.
- Skips seeking if it's unecessary.
- Adds DEBUG messaging and a warning if the seek took
longer than that of an average physical CDROM.
The commit refines several types to their logical use-cases.
For example, a CDROM will at-most contain 400,000 sectors and be
less than 1B bytes in size. Likewise, both are 'physical'
quantities and this should always be zero-or-greater
(therefore, uint32_t is used).
Fortunately, there are almost no cases where these values are
overloaded to mean something else (ie: negative return codes to
indicate failure).
Besides eliminating many implicit cast warnings, differing-signed
comparison warnings, and overflowable type-cast warnings, the
more correct use of types helps logically bound expectations of the
values they contain, which should improve maintainability.
1. Moves the mutex and mixer channel members to unique pointers
2. Moves the trackFile to a weak pointer
3. Move member initialization to the class definition
This class still retains a raw *cd member, however fixing this
ripples up to the array of [26] CD images, and across more
code that generically deals with mount points; so this work
remains to do.
Most MinGW versions work correctly with and without _POSIX_C_SOURCE
or XOPEN macros [1] and don't need any special handling, but some
installations refuse to work correctly.
To be more precise: *some* MinGW installations turn off POSIX support
after turning on -std=c++11 WITHOUT -ansi -Wpedantic, -pedantic-errors
and similar. This behaviour is inconsistent between various Windows
versions and MinGW distributions and manifests itself only when using
GCC (Clang behaves correctly).
[1] https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
Many DOS games open all their files in write-mode regardless if the
game actually intends to write to them or not.
This can result the files' metadata being updated (lossing the
original date-stamp) as well as putting the file at-risk of
corruption if the game crashes with the file open for writing.
Under the existing DOSBox implementation, if a user attempts to
write-protect their data files then DOSBox will quit with an error in
the above scenario.
This commit allows the use of write-protected files (similar to
running a game from CDROM) and indicates which files are being
actively protected against modification.
Typically the only files that need to be left writable are those that
the game actually changes, such as: save-game files, highscore
files, in-game settings, and so on. If these are also protected,
then the game will quit/crash immediately after the protected message
is printed, and thus indicate which file require write-allowance.
This code made silent assumption that first fields in direntry are
exactly 14 bytes - this was fine, except would break as soon as anyone
would touch the struct (or e.g. if a compiler would lack support for
packed structures and inject some padding in there); rewrite the copy
code to follow the same pattern as other fields - now the code will be
fine even if someone will change fields in the direntry struct.
Fixes 2 PVS static analysis issues (buffer underflow on src and dst).
Effect is the same, except packed values are not referenced via pointer
so there's no address-of-packed-member warning, and no need for
unaligned memory access.