turns out SDL 2.0.12 added SDL_GameControllerGetType() which tells you
what kind of controller it is (xbox, playstation, nintendo, ..).
Using this to implement an auto-mode for joy_gamepadLayout, when it's
set to -1 (the new default).
This should still build with older versions of SDL2 (but won't have
that autodetection then).
The button names shown in the controls menu now depend on this CVar.
So if you set it to 1 (Nintendo), the "A" button (which, based on its
position, would be "B" on XBox/XInput gamepads) is actually shown as
"Pad A", and if it's set to 2 (Playstation), it's shown as "Pad Cross".
The "real" names, used in the config, remain the same and are based on
position: JOY_BTN_SOUTH, JOY_BTN_EAST, JOY_BTN_WEST, JOY_BTN_NORTH
- make moving the cursor more precise by using an exponential curve
for axis value => cursor speed
- emulate cursor keys with DPad and Enter with left trigger
- also use right trigger for leftclick, as it's usually used for firing
a weapon and thus used for "clicking" ingame UIs
- fix hovering/highlighting menu elements when moving cursor
with gamepad
- treat DPad as 4 regular buttons (was already the case mostly, but now
the code is simpler)
- rename in_invertLook to joy_invertLook and in_useJoystick to
in_useGamepad and remove unused CVars
- make controller Start button generate K_ESCAPE events, so it can
always be used to open/close the menu (similar to D3BFG)
- move mousecursor with sticks, A button (south) for left-click,
B button (east) for right-click (doesn't work in PDA yet)
- removed special handling of K_JOY_BTN_* in idWindow::HandleEvent()
by generating fake mouse button events for gamepad A/B
in idUserInterfaceLocal::HandleEvent()
- renamed gamepad/joystick actions and keys to have some meaning
for buttons (instead of just JOY1, JOY2 etc)
- compiles with SDL1.2 again (there gamepads aren't supported though)
- shorter names for gamepad keys/axis in the key bindings menu
Doom3 and RoE can't be bought alone anymore, only as part of D3 BFG,
so link that instead.
Has the advantage of being cheaper, also giving you the BFG edition,
and (presumably?) making RoE available to German users.
(also added a comment in CMakeLists.txt, for mingw32, copy of the
equivalent comment in MSVC section)
Added the ability to change the screenshot format with a new CVar:
r_screenshotFormat. This has four options: 0 (TGA), 1 (BMP), 2 (PNG),
and 3 (JPG). JPG quality can be selected with a new CVar:
r_screenshotJpgQuality. TGA is the default to preserve original behavior
from DOOM 3.
A new dependency on stb_image_write has been added. It has been
included. No additional configuration with CMake is required.
According to
https://cmake.org/cmake/help/v3.26/variable/CMAKE_LANG_COMPILER_ID.html
there's at least "Clang" (plain LLVM clang), "AppleClang", "ARMClang",
"FujitsuClang", "XLClang" and "IBMClang" (both of which are variations
of the clang/llvm-based IBM XL compiler).
This should detect all of them (I hope they all behave close enough
to normal clang to work..)
There's also "IntelLLVM", but I have no idea if that's based on Clang
or does its own thing based on LLVM.. I also doubt dhewm3 will ever
be built with any other clang-derivate than "Clang" and "AppleClang" :-p
fixes#510
in the "Work around false positive GCC -W(maybe-)uninitialized warnings"
commit I changed that code.. but my change made it nonsensical,
of course we must get oldBounds before calling the callback which
changes the bounds, otherwise comparing the "oldbounds" with the
current bounds just compares them with themselves..
afxv_w32.h (apparently included indirectly viw edit_gui_common.h)
complained that windows.h (included indirectly via DebuggerServer.h
-> platform.h) was included first, apparently that's not allowed..
this was broken by the recent "fix mingw build" commit; now hopefully
both work (MinGW doesn't support building the tools, because they need MFC
which only works with MSVC)
The HD version of the "Birdman" Hellknight model crashed the game,
because on Linux it triggered the 600KB _alloca() assertion and on
Windows (that didn't have such an assertion up to this commit) it
overflowed the stack.
Thde default stacksize on Windows is 1MB, increasing that to 8MB fixes the
problem (in Doom3 1.3.1 it was 4MB).
I also implemented the _alloca() size check assertion for Windows, and
increased the allowed size to 2MB (so it can be safely called multiple
times per function)
Model: https://www.moddb.com/mods/birdman-doom3/downloads/birdman-doom3-v11
<intrin.h>, included by SDL_cpuinfo.h via SDL.h, defines strcmp.
If the idlib/Str.h `#define strcmp idStr::Cmp` hack is visible when
that file is parsed, there's a compiler error (because strcmp in
intrin.h is replaced with idStr::Cmp then).
So I reorderedd includes a bit until it compiled again..
this was so broken, I think if anyone ever tried to use __DATE__ or
__TIME__ it must've crashed, either from free(curtime) (which was the
return value of ctime()) or from things like token[7] = NULL when token
was a pointer (to a single element!).
I think it could work now.
Also fixed potential memory leaks in cases that don't "return" anything
or, in the case of AF.cpp, at least comment on them
I think this fixes most of the remaining "interesting" GCC 12 on Linux
warnings, except for some in idParser::ExpandBuiltinDefine() that I'll
fix in the next commit
For some reason MSVCs integrated CMake doesn't set CMAKE_GENERATOR_PLATFORM
so my CPU arch detection magic in CMakeLists.txt didn't work in that case..
Now (when using MSVC) the CPU architecture (D3_ARCH) is set in
neo/sys/platform.h instead.
-DASAN=ON enables the Address Sanitizer (ASan), if supported
-DUBSAN=ON same for Undefined Behavior Sanitizer (UBSan)
-DFORCE_COLORED_OUTPUT=ON forces GCC or Clang to use colors in their
messages, useful when building with ninja
All three options default to OFF (though when building with make in a
suitable terminal, GCC and clang automatically use colors)
Also modified the cmake_minimum_required() line to shut up deprecation
warnings (though TBH I have no idea if this really still works with
CMake 2.6)
Commit 3c01757d27 introduced scaling down all sounds to prevent too
many loud-ish sounds from making OpenAL scale the overall volume down.
The problem is that before this change, many sounds had a volume > 1.0,
but vastly different: e.g. player_machinegun_fire was 5.039685 (14dB)
and player_chaingun_fire was 1.414214 (3dB).
But in the end, all volumes were clamped to 1.0 before setting AL_GAIN
(because AL_GAIN only supports values between 0 and 1 by default), so
the machinegun and chaingun had the same volume after all.
When scaling those down to 1/3 of the original volume, some sounds that
used to have a volume of >= 1.0 (=> AL_GAIN set to 1.0) had a volume
lower than 1.0, so they suddenly the chaingun sounded quiter than
the machinegun. While theoretically this is more correct than before
(after all, the sound shader of player_chaingun_fire set a much lower
volume than that of player_machinegun_fire), it doesn't sound like it
used to (even with the old software sound backend!).
Clamping to 1.0 *before* scaling to 1/3 should restore the old behavior
(of all sounds with volume > 1.0 before clamping using the same AL_GAIN)
while still avoiding the issue of having OpenAL (Soft) scale down the
overall volume when shooting a metal wall with the shotgun.
Unsurprisingly the same problem (inconsistent weapon volumes due to
incorrect sound shaders setting the volume way to high and thus relying
on being clamped to 1.0) that occurred with my volume *= 0.333 hack
also happens when reducing the global volume.
So apply that global volume scale *after* clamping to 1.0
see https://github.com/bibendovsky/eaxefx/pull/28#issuecomment-1367436162
Some entities wrote the handle from gameRenderWorld->AddLightDef()
into savegames and reused it after restoring it.
That's a bad idea, because at that point the handle most likely belongs
to something else (likely some idLight). The most visible issue this
can create is that the flashlight may not work correctly after loading
a savegame with flashlight on, when it happens to alias a light that's
updated each frame to (mostly) being off..
The correct way to handle this (THAT FOR SOME REASON WAS ALREADY
IMPLEMENTED IN D3XP BUT NOT THE BASE GAME - WHY?!) is to get a fresh
handle with AddLightDef() when restoring a savegame - unless the handle
was -1, which means that the light didn't exist when saving.
fixes#495
Some level scripts in d3xp (erebus4, erebus4, phobos2) use
$entity.startSoundShader( "", SND_CHANNEL_BODY );
(or whatever channel) to stop the sound currently playing there.
With s_playDefaultSound 1 that results in a beep..
Added a special case to that event implementation to call StopSound()
instead when the soundName is "" (or NULL)
the problem was a double-free on files, because USE_COLLADA is not defined.
I'm not even sure why this USE_COLLADA code exists, as we don't have any
real collada support code anywhere..
.. by surrounding it with newlines.
This warning is shown when trying to start a mod without its game dll
(because the user has forgotten to unpack the mod dll archive, or
because it's a mod that doesn't have its own dll).
Surrounding it with empty lines hopefully makes it easier for users
to figure out what went wrong when they look at the log.
When selecting a light in the Radiant (builtin Windows-only level editor)
and pressing `j`, the light editor opened (as expected) but said that
no entity was selected.
That was because com_editorActive was false, most probably because of
e8a1eb8b Fix mouse remaining ungrabbed when running map from Radiant
which sets com_editorActive to false (via com->ActivateTool(false)) if
the Radiant window loses focus, which should be the case when opening
the light editor window.
`com_editors & EDITOR_RADIANT` is != 0 as long as the radiant is
running, no matter which window currently has focus, so it works better.
and add entry to changelog about absolute mouse input etc - this change
was already in RC1 but I forgot to mention it..
and fixed comments for GAME_NAME and ENGINE_VERSION (nowadays dhewm3
uses ENGINE_VERSION for the window title)
It happened a lot more since
504b572a Update sounds at ~60Hz instead of ~10Hz, fixes#141
(because then MixLoop() is more likely to be called in the narrow
timeframe this can happen during level load) but could happen before.
So far I only observed it when starting a new game in Classic Doom 3.
See comment in the change and #461 for more information.
Hoping that Team Future eventually fulfills their promise of releasing
the source of the highly praised Phobos mod, I'm adding it to the list.
Currently this is not very useful, but when (if) the phobos source
becomes available I at least won't have to do a new dhewm3 release to
support it (but only provide tfphobos.dll/.so/.dylib).
by adding special cases for them that set `fs_game_base d3xp`.
Unfortunately there is no more generic way to do this, as mods have
no way to tell the engine if they need fs_game_base.
The assertion that triggered was "assert(iconvDesc == (SDL_iconv_t)-1);"
in Sys_InitInput() - because when loading a mod the window is recreated,
calling Com_ReloadEngine_f() -> idCommonLocal::InitGame()
-> idCommonLocal::InitRenderSystem() -> idCommonLocal::InitOpenGL()
-> R_InitOpenGL() -> Sys_InitInput()
Before that Com_ReloadEngine_f() calls commonLocal.ShutdownGame( true );
which calls the equivalent Shutdown() functions - except so far no one
called Sys_ShutdownInput() (which closes iconvDesc and resets it to -1).
Fixed that by making idRenderSystemLocal::ShutdownOpenGL() call it.
In the savegame from that bugreport, "monster_zsec_shotgun_12" was
lying dead pretty much at its spawn point.
script/map_alphalabs4.script moves those "ride_of_death" platforms
around, and at the end of a cycle teleports "ride_of_death*_parent" back
to its starting position - and the "ride_of_death*" bound to it, which
is a pushing mover, just gets dragged along by the physics code and thus
can collide with that zombie cadaver, which then tries to push it along,
causing that assertion in TestHugeTranslation().
This is a map bug - Doom3 even prints a warning:
WARNING: script/map_alphalabs4.script(722): Thread
'map_alphalabs4::RideOfDeathPath': teleported 'ride_of_death2_parent'
which has the pushing mover 'ride_of_death2' bound to it
So I just disable that assertion for this specific case..
Also moved the assertion behind the corresponding warning, so that gets
printed before the assertion kills the game..
Also a small change to CMakeLists.txt that should make enabling
LINUX_RELEASE_BINS after CMake has already been run without it work
For some reason Wayland thought it would be clever to be the only
windowing system that (non-optionally) uses the alpha chan of the
window's default OpenGL framebuffer for window transparency.
This always caused glitches with dhewm3, as Doom3 uses that alpha-chan
for blending tricks (with GL_DST_ALPHA) - especially visible in the main
menu or when the flashlight is on.
So far the workaround has been r_waylandcompat which requests an OpenGL
context/visual without alpha chan (0 alpha bits), but that also causes
glitches.
There's an EGL extension that's supposed to fix this issue
(EGL_EXT_present_opaque), and newer SDL2 versions use it (when using
the wayland backend) - but unfortunately the Mesa implementation is
broken (seems to provide a visual without alpha channel even if one was
requested), see https://gitlab.freedesktop.org/mesa/mesa/-/issues/5886
and https://github.com/libsdl-org/SDL/pull/4306#issuecomment-1014770600
for the corresponding SDL2 discussion
To work around this issue, dhewm3 now disables the use of that EGL
extension and (optionally) makes sure the alpha channel is opaque at
the end of the frame.
This behavior is controlled with the r_fillWindowAlphaChan CVar:
If it's 1, this always is done (regardless if wayland is used or not),
if it's 0 it's not done (even on wayland),
if it's -1 (the default) it's only done if the SDL "video driver" is
wayland (this could be easily enhanced later in case other windowing
systems have the same issue)
r_waylandcompat has been removed (it never worked properly anyway),
so now the window always has an alpha chan
so if someone configured 16x AA on a system that doesn't support it
(like when using AMDs open source driver), 8x will be tried before
falling back to a 640x480 window with no AA at all.
(and then it'll try 4x and then 2x and then no AA at all, and only then
reducing color depth will start, and even later it'll fall back to
a small 640x480 window)
I don't have such hardware, so I can't test; I also didn't actually build
dhewm3 (would have to build dependencies for ARM first..), but when
configuring ARM or ARM64 targets for Visual C++ in CMake, that's now
correctly detected in CMake.
Also, now D3_ARCH should always be "arm" for 32bit ARM
and "arm64" for 64bit ARM, also when building with GCC or clang.
I was lazy and just renamed SDL_win32_main's stdout.txt - but I still
added the dhewm3log-old.txt backup function.
I also renamed Sys_GetHomeDir() to Win_GetHomeDir() as it's Win32-only
On Windows it's in Documents\My Games\dhewm3\dhewm3log.txt
and refactorings needed for that (I want to create the log right at the
beginning before much else has been initialized, so using things like
idStr or Sys_GetPath() isn't safe)
save_path being $XDG_DATA_HOME/dhewm3/ (usually ~/.local/share/dhewm3/)
on most POSIX systems, $HOME/Library/Application Support/dhewm3/ on Mac
If the log file already exists, it's renamed to dhewm3log-old.txt first,
so there's always the most recent and the last log available.
These are now used by idStr::(v)snPrintf(), and in the future can
be used if a (v)snprintf() that's guaranteed not to call
common->Warning() or similar is needed (e.g. used during early startup)
There were lots of places in the code that called Sys_GrabInput(),
some of them each frame.
Most of this is unified in events.cpp now, in handleMouseGrab() which
is called once per frame by Sys_GenerateEvents() - this makes reasoning
about when the mouse is grabbed and when not a lot easier.
Sys_GrabInput(false) still is called in a few places, before operations
that tend to take long (like loading a map or vid_restart), but
(hopefully) not regularly anymore.
The other big change is that the game now uses SDLs absolute mouse mode
for fullscreen menus (except the PDA which is an ugly hack), so the
ingame cursor is at the same position as the system cursor, which
especially helps when debugging with `in_nograb 1` and should also help
if someone wants to integrate an additional GUI toolkit like Dear ImGui.
glStencilOpSeparateATI() should behave exactly the same as
glStencilOpSeparate() so supporting it is easy enough and might help
some people with hardware or drivers that don't support OpenGL 2.0,
like the Mac OSX versions for PPC.
- Fix build with SDL <=2.0.3
SDL_GetGlobalMouseState was introduced in 2.0.4
(which doesn't support OSX 10.5 or older)
- Don't include execinfo.h on Mac OS X 10.4
This file isn't included in the 10.4 SDK
- Use custom typedef for PFNGLSTENCILOPSEPARATEPROC on OSX 10.4/10.5
because the system OpenGL headers for those versions don't have it
CMAKE_SYSTEM_PROCESSOR used to be broken, CMake "fixed" it by redefining
its meaning (from "Target CPU" to "Host CPU except when crosscompiling").
On Windows it always prints the host CPU, on Linux it at least made trouble
in chroots and when running 64bit kernels with 32bit userlands (this used
to be not totally uncommon on x86 before distros completely switched to
amd64, and apparently Raspbian/Raspberry Pi OS does this on RPi4, see #267)
Thankfully gcc and clang support "-dumpmachine" to print their (default)
target system, so use that instead (MSVC already had a special case).
On the upside, this allows getting rid of the MinGW special case.
I hope this also works with Apple Clang..
The problem was that negative values (from dhewm3tmpres.xyz) were passed
to POW, and POW doesn't have to support negative bases, according to
ARB_fragment_program.txt, and Intels Linux drive apparently doesn't,
see also https://gitlab.freedesktop.org/mesa/mesa/-/issues/5131
Using MUL_SAT instead of MUL to clamp the value that gets passed to POW
afterwards to [0, 1] fixes the problem without any disadvantages.
so far the code assumed that "result.color" is always used directly,
but the ARB shaders allow creating an alias with the aforementioned
syntax. So turn that into an variable-alias for dhewm3tmpres.
as long as it's chars Doom3 supports, i.e. it can be converted
to ISO-8859-1
also renamed kbdNames to _in_kbdNames to reduce likelyhood of clashes
(as it can't be static)
and scale the breakpoint dots accordingly - now they don't looked all
squashed anymore.
I think ResizeImageList() is more correct now, at least this helped with
the breakpoint dots.
The `const char* filename` arg is passed from idProgram::CompileText(),
where it's from idProgram::filename - and that filename can get modified
in idCompiler::NextToken() when it calls gameLocal.program.GetFilenum()
and if the idStr grows and reallocates for that modification,
the filename pointer becomes invalid.
So store `filename` in an idStr and use that when logging the
compile time.
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
but it's still a bit wonky with DPI-scaling
I also made the rect calculations a bit more intuitive
and removed a misleading comment in my breakpoint list code
Double-clicking an entry opens the script at the correct line.
Single-clicking the breakpoint symbol in the list removes the breakpoint,
and so does selecting the breakpoint in the list and pressing the Del key.
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).
the script paths were wrong, on Linux they were like
"pak000.pk4/script/doom_util.script" while on Windows it's only
"script/doom_util.script".
Fixed idFileSystemLocal::OSPathToRelativePath() to skip ...pk4/
also fixed GCC compile error in Common.cpp