If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
It's set to 0 by default (which is the original behavior), if set to 1,
SDL2 will grab the keyboard, so Alt-Tab or the Windows Key etc will not
be handled by the operating system but by dhewm3 (=> you can bind the
Windows key like any normal key and it won't open the start menu)
If a key is pressed whichs SDL_Keycode isn't known to Doom3 (has no
corresponding K_* constant), its SDL_Scancode is mapped to the
corresponding newly added K_SC_* scancode constant.
I think I have K_SC_* constants for all keys that differ between
keyboard layouts (which is mostly printable characters; F1-F12, Ctrl,
Shift, ... should be the same on all layouts, which means that e.g.
SDL_SCANCODE_F1 always belongs to SDLK_F1 which the old code already
maps to Doom3's K_F1).
What's extra nice (IMO) is that when Doom3 requests a *localized* name
of the key (like for showing in the bindings menu), we actually use the
name of the SDL_Keycode that *currently* belongs to the scancode, and
esp. the "Western High-ASCII characters" (ISO-8859-1) supported by Doom3
like Ä or Ñ are displayed correctly.
(I already implemented a very similar hack in Yamagi Quake II and
reused the list of scancodes)
This should fix most of the problems reported in #323
Added Sys_FreeClipboardData(char*) so I don't have to copy the string
from SDL_GetClipboardText() into a Mem_Alloc() buffer, but can just
do the right thing per platform, which in case of POSIX/SDL2 is
SDL_free().
SDL1.2 doesn't have clipboard support, otherwise I'd have removed all
platform-specific implementations and used SDL_Get/SetClipboardText()
everywhere (IIRC AROS only supports SDL1.2?)
Now the game cycles between QuickSave, QuickSave2, QuickSave3, ...
(up to com_numQuicksaves files, 4 by default, up to 99), always
replacing the oldest.
Quick-loading always loads the newest quicksave, but all quicksaves
can be loaded via the load game menu.
this *shouldn't* matter, but due to some Mesa bug is does:
If the shaders have been loaded already (with R_LoadARBProgram()),
then loading them again (like from the `reloadARBprograms` console cmd
or as it happens if the `r_gammaInShader` has been modified) will
cause glitches with the open source radeonsi driver (maybe also with
others? at least the open source intel driver seems unaffected).
As r_gammaInShader was marked as modified at startup (before the shaders
were even loaded) they were loaded twice: First as expected when OpenGL
is initialized, then again in R_CheckCvars() which is executed each
frame. Marking as at not modified in R_InitOpenGL() prevents this and
thus works around the bug.
However this means that changing r_gammaInShader at runtime will still
trigger this bug (while with non-broken drivers it switches seamlessly
between gamma in shader and gamma in hardware without a vid_restart).
Originally sound updates only happened about every 100ms and
`sampleTime` (or `newSoundTime`) was a multiple of 4096
(`MIXBUFFER_SAMPLES`).
After I changed this to updates every 16ms and made the calculation of
`sampleTime` a lot simpler, it could be any value (as it's current
amount of milliseconds multiplied by 44.1).
It generally seemed to work, but it seems advisable to make it a
multiple of 8 (see also "Fix endless loop when decoding OGGs" commit).
So I round it to the nearest multiple of 8 now. Furthermore I increased
the accuracy when the game has been running for a long time by using
double instead of float, and tried to make sure that `sampleTime` is
always positive (or at least as long as `inTime` is positive).
idStr is used in both the main thread and the async sound thread, so
it should better be thread-safe.. idDynamicBlockAlloc is not.
Use realloc() and free() instead.
For some reason this caused a lot more crashes (due to inconsistencies
in the allocator's heap) with newer Linux distros (like XUbuntu 20.04)
and when using GCC9, while they rarely reproduced with GCC7 or on
XUbuntu 18.04
fixes#391
In idSampleDecoderLocal::DecodeOGG() `totalSamples` was 1 and
`reqSamples` was 0, which caused an endless loop.. this was caused by
idSoundWorldLocal::ReadFromSaveGame() setting
`chan->openalStreamingOffset` to an odd number, I think due to
`currentSoundTime` being an odd number.
To fix that, I round up `chan->openalStreamingOffset` to a (very) even
number, and to be double-sure I also added a check in DecodeOgg() to
make sure it exits the loop if `reqSamples` is 0.
If those functions (e.g. called by common->Printf(), common->Error())
weren't called from the mainthread and win_outputEditString was set to 1,
a deadlock could occur.
Specifically, the async thread (handling sound) was calling
common->Warning() -> Sys_Printf() -> Conbuf_AppendText() which called
SendMessageA() which blocks until the main thread handles the message.
The main thread however was in idSampleDecoderLocal::Decode() trying to
enter CRITICAL_SECTION_ONE, which was held by the async thread
(it's used to synchronize sound handling between main and async thread).
So now if Sys_Printf() (or Sys_Error() which should have the same problem)
is not called by the main thread, the text is buffered and
Conbuf_AppendText() is called for the buffered lines in the next frame
in Win_Frame().
In idSampleDecoderLocal::DecodeOGG() sometimes (esp. in The Lost Mission
mod) it happens that stb_vorbis_get_samples_float() decodes one sample
less than expected so one is left and when trying to decode that,
stb_vorbis_get_samples_float() returns 0, which we interpreted as an error.
This case is now handled more gracefully: No warning is printed (except
if developer 1) and failed is not set (setting it would prevent the sound
from being played again, I think).
only override cmd->viewDef in RB_DrawView() if we're drawing the
primary view (which for several calculations before actual drawing
was set to the saved/locked render view)
Note that r_lockSurfaces is more useful with r_useScissor 0 (otherwise
there's black bars over the screen when moving) and r_shadows 0 (otherwise
areas that weren't visible when locking are black because the lights
there are skipped)
remaining bug: gui surfaces move around the screen when looking around
set(CMAKE_REQUIRED_LIBRARIES backtrace) tells our custom libbacktrace
availability check that it needs to link against libbacktrace.
Seems like it also tells other unrelated compiler-checks like for
-fvisibility=hidden to link against libbacktrace, so if it's not
available they fail as well.
Fixed by unsetting CMAKE_REQUIRED_LIBRARIES after the backtrace check.
While debian-based distros ship libbacktrace as part of libgcc,
apparently in Arch Linux and openSUSE (and possibly others) it's a
separate package, so I mantion it in the README as an (optional)
dependency now and made CMake print a warning if it's not found.
according to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100839
the real compiler flag enabling this bullshit isn't
-fexpensive-optimizations but -ffp-contract=fast which for some(*)
reason is default in optimized builds.
I think it's best to disabled that optimization globally in case it
also breaks other code (I really don't want to spend several days to
hunt such an idiot bug again). I really doubt it makes any measurable
performance difference.
As https://twitter.com/stephentyrone/status/1399424911328874499 says
that clang might also enable this in the future (though to =on instead
of =fast which should be a bit saner but would still break our code),
just set this option for all GCC-ish compilers incl. clang.
(*) the reason of course is that GCC developers don't develop GCC for
their users but to win idiotic SPEC benchmarks
Only happend if `ONATIVE` was enabled (or some other flag was set
that enables the FMA extension), the root cause was that the cross
product didn't return 0 when it should, but a small value < 0.
Caused some faces to be missing in maps compiled with dmap.
https://github.com/RobertBeckebans/RBDOOM-3-BFG/issues/436#issuecomment-851061826
has lots of explanation.
I think this is a compiler bug, this commit works around it.
fixes#147
I'm gonna use it with libbacktrace - I'll need the path of the
executable before I can use idStr (and thus before I could call
Sys_GetPath(PATH_EXE, str)).
The problem was that the editors called ChoosePixelFormat() instead of
wglChoosePixelFormatARB() - and the normal ChoosePixelFormat() has no
attribute for MSAA, so if MSAA is enabled (by SDL2 which calls the wgl
variant), ChoosePixelFormat() will return an incomaptible format and
the editors don't get a working OpenGL context.
So I wrote a wrapper around ChoosePixelFormat() that calls the wgl variant
if available, and all the necessary plumbing around that.
While at it, removed the unused qwgl*PixelFormat function pointers and
supressed the "inconsistent dll linkage" warnings for the gl stubs
Minimum required Windows version is XP again (instead of Win10).
Win_GetWindowScalingFactor() tries to use two dynamically loaded functions
from newer windows versions (8.1+, Win10 1607+) and has a fallback for
older versions that also seems to work (at least if all displays have
the same DPI).
Moved the function to win_main.cpp so the dynamically loaded functions
can be loaded at startup; so edit_gui_common.cpp could be removed again.
- Upped windows version ( needs to go back, and a runtime dpi check comes in place )
- Changed warning settings for msvc to confirm latest compilers
- Fixed up _afxdll
In idDeclManagerLocal::CreateNewDecl() decl->self->DefaultDefinition();
crashed because self was uninitialized.
Now it gets set to NULL in the constructor and initialized to something
sensible in decl->AllocateSelf();
this is part of #378
it wants to store a pointer to itself in an idWinVar - on 32bit idWinInt
was suitable for that, on 64bit it's not, so instead convert the pointer
to a hex-string and stuff it in a idWinStr
also fix a crash when adding a choiceDef in the gui editor
All pointer<->integer conversion truncation warnings I'm aware of are
now enabled for MSVC, to hopefully finally get that tool code 64bit-clean.
I had to adjust the idCVar code for this - it should've been safe enough
(highly unlikely that a valid pointer is exactly 0xFFFFFFFF on 64bit),
but triggered those warnings - now it should behave the same as before
but the warnings (which are now errors) are silenced.
The only thing that still prevents dhewm3 from building with these
warnings-as-errors is rvGEWindowWrapper
rvGEWindowWrapper is still TODO - it's not as straightforward, because
it insists on storing a pointer in an idWinVar (using idWinInt), but there
is no idWinVar type for pointers
the commented out code clamped the loaded filesize of affected .dds
images (crash observed with dds/guis/assets/splash/pdtempa.dds) to
200KB - but then later tries to load it and skip the first mipmap,
resuling in reading invalid memory (> 200KB into the file).
No idea what this was supposed to achieve, but it's disabled now
and the crash (at startup) is gone.
fixes#374
It can be set to a value between 0.0 and 1.0.
1.0 sounds like it did before introducing this cvar; as many people
found the the effect way to strong, I made 0.5 the default value
Otherwise especially looped sounds continue playing while the menu
is open, especially noticeable when opening the menu while firing
the chaingun (the whirring sound continues playing).
The code to decompress OGG files directly on load if they're shorter
than s_decompressionLimit seconds (usually 6) accidentally got broken
when removing the non-OpenAL soundbackends:
`if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_OGG )` slipped into the
`if ( objectInfo.wFormatTag == WAVE_FORMAT_TAG_PCM )` block - obviously
both can't be true at the same time so the OGG case was never executed.
Now it's in its own block again. I put it into a {} scope so it doesn't
have to be re-indented (=> more useful with git blame)
Seems to work; note that idWaveFile is only ever used in idSoundSample::Load()
As stb_vorbis doesn't support custom callbacks for reading, I feed it
the full .ogg files as a buffer. Shouldn't make much of a difference
though - either the whole file is decoded on load anyway (so the buffer
is freed after decoding, or it's streamed, but in that case the old code
also kept the whole ogg file in memory by using idFily_Memory.
I also added warning messages in places where calls to stb_vorbis_*()
can fail, where there were none in the equivalent libvorbis code.