Rules are defined for all C/C++ code, except src/libs.
These rules are designed to emulate kernel coding convention with some
adaptations for C++11. Configuration file uses options available in
clang-format 8.0 (the newest version in 10.0) to provide compatibility
with older environments and operating systems. Some options are
commented out and marked with TODOs - those need to be investigated and
enabled/disabled during upgrade to clang-format 9.0.
DOSBox codebase is a mix of various styles with only few consistent
rules seen throughout the codebase, these clang-format rules preserve
some of existing conventions and conciously break with others.
Some unwritten upstream rules, that are now encoded in clang-format:
- Using tab for indentation.
- K&R-like indentation for control statements.
- Indentation rules for structs, classes, and non-anonymous enums.
- Case labels in switch statements are aligned the same way goto
statements would be (also K&R rule).
Some formatting aspects that were not followed consistently throughout
old DOSBox code, but are now encoded in clang-format:
- Space placing in control statements and function calls (makes the code
much more readable).
- Control statements (if-else, while) must be broken into multiple lines
(makes the code more readable, helps with debugging, reading compiler
logs and static analysis reports).
Some unwritten upstream rules, that are now changed by these rules:
- Placing opening function bracket in the same line as function
declaration (not in line with K&R). This rule makes it hard to make
constructor formatting consistent - old code dealt with it by not
formatting initializer lists at all. Unformatted initializer list can
result in lines hundreds of lines long and make it hard to add/remove
class fields while assuring correct initialization order.
In new clang-format rules K&R indentation is followed, allowing
initalizer lists to be formatted one initializer per line (which makes
it much easier to read and edit.
This fixes mouse visibility issues on the Raspberry Pi,
which uses an older customized version of SDL2. SDL2 on
the Pi fires different windows events in a different
order, making dealing with states challenging.
To handle this generically, we additionally assess the
mouse capture state after the Window has gained focus.
We also add a "has_focus" state tracking boolean to the
SDL object, which protects against general SDL mouse
trigger events from changing the mouse state before the
Window has "risen" and delivered us an EXPOSED or FOCUS
event. In the prior code rapidly clicking the mouse while
DOSBox was starting could freeze the mouse cursor in
place on the Pi.
We still also assess the mouse state on EXPOSE events,
which is fired after full - windowed modes are toggled.
The EXPOSE even occurs reliably on OSX, X11, Wayland, and
Windows after the window has settled (but is never fired
on the Pi).
Upstream replaced C++11 code with C++ "almost-equivalents", when merging
code from MAME project.
Reverting this fixes few warnings (comparison of signed and unsigned
integer in this case) and makes it slightly easier for the compiler
to unroll the nested loops.
vsync is an option introduced by SDL2 patch, but the testing indicates,
that it very rarely (if ever) works. We still want to support it, but
this might require serious implementation effort, so for the time being
we're removing broken option to prevent confusing the users.
This allows us to show a warning to the user if the .conf file includes
a property that is no longer supported, or a property that is completely
unknown. Actual handling of the property can still be implemented
(e.g. to use as a fallback for modern replacement), but doesn't need
to be.
It's the easiest way to prevent problems when user wants to play the
game using fullscreen while explicitly setting tiny resolution
for a specific game (e.g. 320x200).
All rendering backends except output=surface assume input buffer row
with the same length as output buffer row. Surface is "special" and in
fullscreen uses pitch equal to *screen* width instead. Padding the
output rows with black pixels is necessary for splash screen to show up
correctly.
SCREEN_SURFACE is no longer the default option, and it's usable only for
debugging purposes. Move it to the last position in switches, to make
texture and opengl a little bit faster.
Usually, when window is being created without SDL_WINDOW_OPENGL flag,
SDL2 internally re-creates it to support OpenGL during
SDL_CreateRenderer if needed.
This leads to crash in AMD OpenGL drivers (Windows only), which happens
for drivers: "opengl", "opengles", "opengles2".
When the window is created with correct flag from the get-go, the crash
does not happen.
On Linux, the code does not crash either way (at least not when using
Mesa and AMDGPU open source driver), so there's no point in propagating
the hack.
Also, remove a comment that is no longer relevant to the code below.
Lock/UnlockTexture is stable and works very well on Linux and with
OpenGL texture driver and on Linux and Windows, but it's usage caused
problems with content of updated texture when used with drivers:
'direct3d11' on Windows and 'metal' on macOS.
Also, Lock/Unlock turned out to be the root cause of deadlocks for
'opengl' driver on AmigaOS.
According to SDL2 documentation, using Lock/UnlockTexture is supposed to
be faster, but in DOSBox usecase we couldn't confirm significant
performance change - there are some community reports indicating, that
UpdateTexture might be actually faster (but we couldn't confirm it
either).
Discussion on this topic can be found on SDL forum:
https://forums.libsdl.org/viewtopic.php?t=9728
In our case, switch to UpdateTexture has no serious negative impact, but
makes the behaviour more robust across the board.
Make the user settings affect splash screen as well as emulator; this
way, when user wants to start in fullscreen, the splash screen will be
displayed in fullscreen - making the startup process more streamlined.
This fixes long-standing problem on SteamOS (or Steam in Big Picture
mode), when starting dosbox moves the user out of fullscreen to window
(to show tiny splash screen), and then back to fullscreen.
Simplify the code displaying the splash screen and extract it to a new
function. Using GFX_* functions avoids the problem of re-creating
the window from scratch after splash is shown, which solves a lot of
problems:
- application window is always visible on screen, it does not disappear
for a moment between closing splash and starting emulator.
- seriously reduces resolution trashing on start
- user will not experience loss of window focus due to splash screen
disappearing (this was happening e.g. on AmigaOS)
Usage of this function depends on the state of global sdl struct; and
it's very easy to make a mistake - documentation should lower this risk.
Change the type of output parameter 'pitch' and assure type safety with
internal SDL types via static asserts.
This used to have meaning for Windows 9x support via SDL 1.2; the issue
described in README was never mentioned in the context of SDL2.
Add missing include to video header while we're at it.
This will trigger CI jobs automatically when pull-request is
created/updated. Until now we used only push event, as it was enough to
handle all automatic jobs from repository maintainers, but this does not
work for pull requests triggered by external collaborators.
We can't simply turn on new event, as it results in duplicate jobs when
PR is created by maintainer, so additional "if" filter is needed to
prevent duplicates from running. GitHub still shows "empty jobs" in some
parts of UI, but at least they don't run and fight for resources.
Unfortunately, GitHub Actions "if" functionality is fairly limited at
the moment:
- it does not work on workflows, only specific jobs
- it does not support array literals (that's why maintainer list is
passed as a string)
- it can't access workflow env variables (that's why maintainer list is
duplicated)
- it does not support regular expressions
- seems to have problem with using unary "!" operator and nested boolean
expressions…
- … and official documentation is pretty misleading by suggesting it
can do many of those things :(
that's why this "if" line looks like it does and is duplicated in every
workflow.