Check if we're in the requested mode after the fullscreen window was
created. If not: Try to switch again in the requested mode by calling
SDL_SetWindowDisplayMode(). If that's successfull set the new window
size with SDL_SetWindowSize(). That shouldn't be necessary, at least to
SDLs crappy doku, but without the subsequent SDL_GetWindowDisplayMode()
call fails with 'Invalid Window'. Use that call to check if we're now
in the requested mode. If yes, process. If not abort and trigger the
fallback magic. It'll set `r_mode 4` and `vid_fullscreen 0`.
Caveat: In the worst case this will switch the display mode 3 times.
To create the window, to work around the bug and to set a refresh rate.
No problem for flat panels, but my unforgotten Trinitron CRT would
have cried in pain.
* Normaly SDL chooses a sane refresh rate for fullscreen windows. Users
may want to override that, so provide a new cvar `vid_rate`. If it's
set to a value greater than 0, we're trying to get a mode close to the
requested resolution and refresh rate and switch to that.
* A bug in SDL may leave us in the wrong mode, detect that condition and
abort. See https://bugzilla.libsdl.org/show_bug.cgi?id=4700 for details.
This is part of issue #302.
Print a list of all available modes as soon as SDLs video backend
initializes and the real display mode after the window was created
or altered.
This hopefully helps debbuging problem with display mode selection, see
issue #302 for an example.
-Add back use of last_position_x and last_position_y
-last_position_x and last_position_y will be set to undefined when the window is shutdown IF the current display used is not the desired display
-last_display will be set to desired display at window shutdown if not the same
-vid_displayindex clamped using ClampDisplayIndexCvar() at startup and window shutdown
-We only need to init the display indices once in GLimp_Init
-We only need to clear the display indices once in GLimp_Shutdown
-Remove extra 'displayindex' variable
-SDL_GetNumVideoDisplays() will always remain the same after the call to SDL_Init(SDL_INIT_VIDEO), so it makes sense to set in GLimp_Init where we do this.
There's an "enable alt joy keys" command now. If a key is bound to that
command, all joystick buttons (incl. hat and triggers) are turned from
K_JOYx into K_JOYx_ALT, which allows two keybindings on the same key,
one with the altselector pressed and one without.
If there's no keybinding for K_JOYx_ALT, it will use the binding for
just K_JOYx as a fallback (if it exists).
This is especially handy to create direct bindings for all the weapons
on the (limited amount of) Joystick buttons.
Seems like AMDs Windows driver doesn't like it when we call
glBufferData() *a lot* (other drivers, incl. Intels, don't seem to
care as much).
Even on an i7-4771 with a Radeon RX 580 I couldn't get stable 60fps
on Windows without this workaround (the open source Linux driver is ok).
This workaround can be enabled/disabled with the gl3_usebigvbo cvar;
by default it's -1 which means "enable if AMD driver is detected".
Enabling it when using a nvidia GPU with their proprietary drivers
reduces the performance to 1/3 of the fps we get without it, so it
indeed needs to be conditional...
use GL3_BufferAndDraw3D() instead of glBufferData() and glDrawArrays()
in each place it's needed.
This by itself doesn't make anything faster, but it will make trying out
different ways to upload data easier.
The developers tested their maps without the fix and decided that it
looked good. Add a new cvar gl_fixsurfsky defaulting to 0 that enables
the fix if someone really want it.
The software renderer already did this, but not the GL renderers. Maybe
the logic was lost somewhere on the long way... Without this change a
fullbright lightmap is generated for SURF_SKY surfaces and without the
SURF_DRAWSKY flags the surfaces aren't skipped in RecursiveLightPoint()
and GL3_LM_CreateSurfaceLightmap(). This isn't a problem under real
skyboxes, but in cases were SURF_SKY is abused fpr interior lightning.
rmine2.bsp in rogue is a good place to see the problem
Reported by @m-x-d, fixes#393.
I guess it makes sense to apply gamma to the color, we do the same
for the standard round particles.
Also, this way the fragment shader for square particles references the
uniCommon UBO (gamma is part of it) - apparently the Intel HD4000
(from Ivy Bridge) GPU driver for Windows has a bug that uniform blocks
that exist in the shader source but aren't actually used can't be found
(with glGetUniformBlockIndex(prog, name)), which we treat as an error
in gl3_shaders.c initShader3D().
fixes#391
Apparently the lightsource for exploding rockets/grenades is very close
to the surface, so the dot-Product between surface-normal and the
vector between the light and the pixel returns 0, basically disabling
the dynamic light for that surface.
As a workaround, move the lightposition (only for that dot product)
a bit above the surface, 32*surfaceNormal looks good.
fixes#386
The real needed size can't be derived from the .bsp file size, because
* many generated structs contain pointers
* there's lots of data generated per face..
* _especially_ for warped faces that are subdivided
introduced FS_GetFilenameForHandle(fileHandle_t) for this
this helps if a map has been started with "wrong" case, which doesn't
immediately fail if it has been loaded from a pack, but will result
in invalid savegame names that (with case-sensitive FSs) will fail to
load (when going back to a formerly played level)
The r1q2 code prioritized pak files over all other files, e.g. as soon
as a pak file was requested no more file were added to the download
queue until it finished downloading. That way one could be sure that
assets included in the pak file weren't downloaded in parallel as single
files.
This is a better, bugfixed and more robust implementation of the same
logic. With this back in place we can switch back to parallel downloads
which gives a nice speedup on Windows. Maybe, just maybe some day
Microsoft will fix Windows crappy I/O...
Working with getter and setters was a good idea as long as we had one or
two quirks. Now we're at three with maybe more to come so it's easier to
use a struct to communicate quirks between the precacher and the HTTP
download code.
The stores it's text in the key_lines array which is NUM_KEY_LINES *
MAXCMDLINE chars long. The code never checked for overflows, it just
assumed that a line will never be longer then 256 chars * 8 = 2048
pixel. With modern displays we can have higher vertical resolutions,
so the array will overflow sooner or later.
Fix it by clamping the maximum line width to MAXCMDLINE - 2 chars (1
for the prompt and 1 for the terminating \0). While at it increase
MAXCMDLINE to 1024 chars * 8 = 8192 pixel, which is more then 8k
resolution and should be enough for the years to come.
This is belived tot fix at least a part of issue #368.
I'm not 100% sure if this is okay for q2pro, but at least in my simple
tests r1q2, q2pro and now yq2 generate the same URL. Nevertheless it's
somewhat inconssistent to search generic files at /moddir/... and the
filelist at /moddir.filelist
This closes issue #370.
Until now the softrenderer calculated the fov relative to a hard coded
aspect of 4/3. That's wrong, because we're supporting arbitrary aspects
and we aren't calculating a fov but just a scaling factor to the global
fov which takes the aspect into the account.
Fix this by not taking any aspect calculations into account. BUT: While
this renders the gun with a correct perspective it's positioned much
nearer to the camera / player then in the GL renderers. The GL renderers
work around that problem by enforcing a minimal Z distance of 4 units,
which can't do because we're just calculating a scaling factor...
The r1q2 URL generator was, like everything in this game, buggy. It took
cl.gamedir into account when generating the URLs, but overlooked that it
is only set when 'gamedir != BASEDIR'. So baseq2 assets ended up with
/maps/foo.bsp and mod assets with /mod/maps/foo.bsp. q2pro fixed that
to always include the gamedir...
Work around this by refactoring the HTTP -> UDP fallback logic to be
more generic: Count the number of iterations and depending on the
iteration set the gamedir to be used by the URL generator or force
UDP downloads.
Cleaning the download queue as soon as a file finished downloading leads
in combination with only one parallel download and multiple precacher
runs to an ugly problem: The generic filelist is requested several time
which can lead to cycles. Hack around this by rembering if we already
requested it and reset set reminder as soon as the precacher finished.
Yes, I'm feeling dirty.
If the server sends us an URL with trailing slash we're generating URIs
like http://example.com//maps/foo.bsp. While double // are perfectly
valid they might me rejected by some servers. So let's play save.
While at it replace the crappy Z_TagMalloc() with the standard malloc().
Z_TagMalloc() ist just a wrapper arround malloc(), there's no functional
change.
This looks easy, but is rather hacky... Downloading is implemented
through the precacher. The server sends an asset list, while loading
the map another one is generated. CL_RequestNextDownload() goes
through this list, in the order models / maps -> sounds -> images,
calls CL_CheckOrDownloadFile() for each file. CL_CheckOrDownloadFile()
checks if the file is already there, return true if it is and false
if not. If the return code is false CL_RequestNextDownload() itself
returns, it's called again by CL_ParseDownload() as soon as the just
queued file finished downloading. This way all missing files are
downloaded one after the other, when CL_RequestNextDownload() finally
reaches it's end (all files are there) it send 'begin' to the server,
thus putting the client into the game.
HTTP downloads are parallel, so CL_RequestNextDownload() cannot track
which files are there and which are missing. The work around for that is
to queue the file but have CL_CheckOrDownloadFile() return true. So
CL_RequestNextDownload() thinks the file is already there, continues
with the next one, until all missing files are queued. After that it
polls CL_PendingHTTPDownloads() and sends the 'begin' as soon as all
HTTP downloads are finished.
If a HTTP download fails we cannot just queue it as UDP download,
because the precacher things that the file is already there. And we
can't tell the precacher that it's not because the precacher tracks
files only by the number of downloaded files per asste type and not
their name. Just decreasing the number of downloaded files isn't
possible since the precacher may have progressed to the next asset
type.
So: On the HTTP side it's tracked if there was an error or not. After
CL_RequestNextDownload() has queued all files and waited for all HTTP
downloads to finish it checks the HTTP error status. If there was an
error the precacher state is reset and CL_RequestNextDownload() recurses
into itself to take another run. All files that couldn't be downloaded
are queued again, this time as UDP downloads.
My solution to this problem is somewhat hacky. A newly added function
OGG_SaveState() can be called to save the state and OGG_RecoverState()
at a later time to restore it. There's only one state and it works
only iff OGG is state playing.
This closes#347.
If we're passing file handles to libcurl to write the data into, the
game may crash under Windows due to incompatible C runtimes between cURL
and quake2. This is even mentioned in the official cURL doku.
Since the moment I took a very first look at the download code I wasn't
a friend of parallel downloads. There're several reasons for that:
- Parallel downloading needs some ugly hacks. For example downloading a
pak file has a high chance to make asset downloads running in parallel
unnecessary.
- Parallel downloads are hard to debug.
- There's just no need for them. I've tested several connection, 1
GBit/s LAN, 50 MBit/s DSL, 6 MBit/s DSL, and there wasn't a
significant difference between 1, 4 or even 16 parallel downloads.
I'm leaving the parallel download code in place. I someone really wants
parallel downloads he can bump the MAX_HTTP_HANDLES define.
Until now download queues entries were created for each file, but only
removed in the unlikely event of changed download server. This leaked
about 4200 byte per file. Fix this by:
- Create a new function CL_RemoveFromQueue() that removes a queue entry
and call it everytime when a download either finished, failed or
aborted.
- Retire the 'download done' state, just the queue entries associated
with a download handle to NULL to communicate that the handle is
unused.
- Cleanup the full queue at shutdown.
Loading libcurl at runtime instead of linking it at compile time makes
things a lot easier and more reliable on Windows. On other platform
libcurl can be installed as optional dependency instead as an hard one.
We're printing only the two relevant informations: A download was queued
and a download finished or failed. That's enough to see what's going on
and not too noisy.
...and fix the bugs, that were worked around with that crap, instead.
This removes some corner cases like cancelation of all HTTP downloads
and fallback to UDP if too many 404 errors were generated. If this is
still a problem in reality - for example HTTP servers blocking the
client after too many 404 or even crashing HTTP server - fix the server
and don't force the clients to work around that.
We aren't in 1997 anymore, todays broadband connections are fast enough
to handle multiple large files. This may download some assets twice if
the server provides both a pak file with all assets and the assets as
plain files.
There's no need to parse the HTTP header on our side of things, CURL can
do that. And the old buffer code was overcomplicated, simplify it. While
at it switch to normal malloc().
While the download speed calculations may be useful their implementation
is crappy and the integration into the console is rather fragile. If we
really want to support the progress bar with HTTP downloads this needs
to be reimplemented.
The URL generation logic was buggy, it took the local fs_gamedir into
account when determining the files path on the server. That could have
worked in r1q2 or q2dos since they assume that the executable dir is
also the config dir. But it breaks in YQ2 were the executable dir and
the config dir differ.
These are:
- CL_ResetPrecacheCheck(): Resets the precacher, forces it to reevaluate
which assets are available and what needs to be downloaded.
- FS_FileInGamedir(): Checks if a file (and only a real file, not
somthing in a pak) is available in fs_gamedir.
- FS_AddPAKFromGamedir(): Adds a pak in fs_gamedir to the search path.
This is a very first cut:
* It compiles
* It doesn't crash
What's missing:
* cmake integration
* CURL should be loaded dynamically
* Integration between download code and filesystem
* Likely UTF-8 stuff
* cl_http.c needs cleanup
* Windows support
We're taking indices and converting them to pointer relative to the
hunks base. Yes, that's dirty. Since the indices are stored as 32 bit
values and hunks are generally small using 32 bit pointers is enough,
even on 64 bit platforms. So the code took the size of void* / 2...
See the problem? Yes, that's not a good idea on 32 bit platforms. Bite
the bullet and just take the size of void*. Shouldn't be a problem,
because the indices are the first thing that's loaded and the hunk is
trimmed right after it anyways. If, and just if, we really need each and
every byte in the early stages of map loading we need two cases. One for
64 bit and one for 32 bit.
This fixes issue #346. Kudos to @ricardosdl for the analysis.
In src/backends/unix/network.c:
* line 181: Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
* line 276: The scope of the variable 'tmp' can be reduced.
* line 665: The scope of the variable 'mcast_addr' can be reduced.
* line 665: The scope of the variable 'mcast_port' can be reduced.
* line 666: The scope of the variable 'error' can be reduced.
* line 775: The scope of the variable 'i' can be reduced.
In src/backends/windows/network.c:
* line 186: Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
* line 287: The scope of the variable 'tmp' can be reduced.
* line 707: The scope of the variable 'mcast_addr' can be reduced.
* line 707: The scope of the variable 'mcast_port' can be reduced.
* line 1049: The scope of the variable 'err' can be reduced.
* line 1163: The scope of the variable 'i' can be reduced.
In src/client/menu/menu.c
arrayIndexOutOfBounds:
* line 1921: Array 'creditsIndex[256]' accessed at index 256, which is out of bounds.
variableScope:
* line 332: The scope of the variable 'item' can be reduced.
* line 533: The scope of the variable 'x' can be reduced.
* line 533: The scope of the variable 'y' can be reduced.
* line 838: The scope of the variable 'b' can be reduced.
* line 864: The scope of the variable 'b' can be reduced.
* line 1910: The scope of the variable 'n' can be reduced.
* line 2199: The scope of the variable 'str' can be reduced.
* line 2812: The scope of the variable 'length' can be reduced.
* line 2813: The scope of the variable 'i' can be reduced.
* line 3838: The scope of the variable 'c' can be reduced.
* line 4112: The scope of the variable 'scratch' can be reduced.
* line 4181: The scope of the variable 'i' can be reduced.
* line 4345: The scope of the variable 's' can be reduced.
In src/game/player/hud.c
arrayIndexOutOfBounds:
* line 132: Array itemlist[43] accessed at index 255 which is out of bounds.
Itemlist assigned only once, and has only 43 items, better ignore unexisted items.
variableScope:
* line 82: The scope of the variable 'n' can be reduced.
* line 217: The scope of the variable 'x' can be reduced.
* line 217: The scope of the variable 'y' can be reduced.
* line 218: The scope of the variable 'cl' can be reduced.
* line 583: The scope of the variable 'cl' can be reduced.
In issue #296 it was pointed out that the menu shows ogg_shuffle
always as disabled, even if it's set to 1. This was an oversight,
the menu code was still checking the ogg_squence cvar removed in
the big OGG/Vorbis refactoring. Update it to match reality.
1) Do not increment the frame rate returned by SDL by 1. Incrementing
is unnessecary, more or less up to date versions on Nvidias, AMDs
and Intels GPU driver on relevant platform return an value that's
either correct or rounded up to next integer. And SDL itself also
rounds up to the next integer. At least in current versions. In fact,
incrementing the value by one is harmfull, it messes our internal
timing up and leads to subtile miss predictions. Working around that
in frame.c would add another bunch of fragile magic... So just do
it correctly. If someone still has broken GPU drivers or SDL versions
that are rounding down the could set vid_displayrefreshrate.
2) The calculation of the 5% security margin to pfps in frame.c was
wrong. It didn't take into account that rfps can be slightly wrong
in the first place, e.g. 60 on an 59.95hz display. Correct it by
comparing against rfps including the margin and not the plain value.
After some pondering I realised that the changes was stupid. It
introduces some new subtile bugs, for example in some cases SDL
still rounds 59.95hz down to 59hz...
In the old world GLimp_GetRefreshRate() was called once at renderer
startup. Now in the new world with SDL 2.0 only it's called every frame
and thus the target framerate git increased by one every frame... That
lead to subtile timin problem in case that the vsync is enabled.
While here remove the hack added for some Windows GPU drivers by AMD.
Older versions returned 59 on 59.95hz displays, leading to small timing
problems. This is fixed in newer version so we don't need to work around
it. Removing the hack gives us somewhat more overall timing precision.
If someone really needs the hack vid_displayrefresh can be set to 60 to
get the old behaviour.
Until now we just called OGG_Stop() as soon as we read the last samples
from a Vorbis files. OGG_Stop() flushed all unplayed samples (about 12
seconds of playback) from the OpenAL playback queue... Instead just set
our internal state of STOPPED, open the next file and be done.
Make sure that the window is destroyed at gl renderer shutdown and
recreated by the soft renderer. Don't deinitialize SDL in the
softrenderer, that's done by vid.c. And make sure that we start the soft
renderer with a clean GL state.
I've chosen the minimal invasive way for this:
* Import miniz and remove -lz linker flags.
* Create a short header minizconf.h roviding everything we need
originally defined by zconf.h and not provided by miniz.
* Replace zlib.h with miniz.h and minizconf.h.
The input system backend was once used in the client and the renderers,
but for some years now it has been an integral part of the client only.
Move it there.
The last commits did some bigger changes to the interaction between the
GL renderers and the client. The code is now SDL 2.0 conformant, window
and context creation are strictly distinct operations. SDL is only
initialized when necessary. Since this broke the client <-> renderer
API, bump it's version.
There a lot of things left to do for dark and cold winter evenings:
* The software renderer implements it's own window handling and
reinitialized SDL whenever vid_restart is called. This is highly
problematic.
* vid_fullscreen is abused to communicate changes to renderer config
throughout the code. That's a very ugly, messy and potential very
problematic hack. But not easy to remove.
* Some funtion calls between the client and the renderer are
unnecessary.
The changes to the client <-> renderer interaction fixed issue #302.
* Sync both files as much as possible.
* Another round of general cleanup.
* Fix stencil tests.
* Simplify gamma handling, hardware gamma is now default.
* Support new client <-> renderer API.
* Another round of general cleanup.
* Introduce gl3_libgl cvar to force a libGL.
* Fix stencil buffer tests.
* Further untangle window <-> context stuff.
The window is now fully at client side, the context at renderer side.
This is another break of the renderer API. And at least GL1 needs to
track this, it's broken for now.
* Even more syntax and code style fixes.
* Rename functions to match their actual purpose.
* Fix comments.
* SDL initialization and shutdown is now client side only. With
SDL 1.2 finally gone there's no need to involve the renderers
in it.
This breaks the client <-> renderer API. I haven't bumped the API
version with this commit because there're likely more changes when
I'm going through the renderer side of things. The VID backend also
needs a lot of love...
It might be a good idea to move this SDL backend files into the client
and rename them. We'll decide that at a later time.
Until now, likely since we first introduced OGG/Vorbis playback 9 years
ago, in about 50% of all cases OGG_PlayTrack() was never called if
cd_shuffle was set 1, resulting in missing background music. Add the
missing call. :)
I wonder why I didn't catch this in sunday. For some reason a "make
clean ; make" cycle was necessary. Maybe a corner case that the header
dependencies didn't catch?
this happens when you just copypaste and adapt r_lefthand
also did some minor changes to R_AliasDrawModel in the soft renderer
to make sure alias[xy]scale is reset properly in the early out cases
At high 'fov' values the weapon looked quite distorted.
Now it's rendered with an independent FOV, which looks better.
Note that the 'fov' cvar sets fov_x, while this is based on fov_y
(which is calculated from fov_x), so it's indeed different values:
r_gunfov seems to correspond to fov 90.
We use r_gunfov 80 as default, because it looks better.
The old code was working only when the client was connected to a local
server. The 'newgame' executed by the menu expands to a 'map', loading
a map ends in SV_InitGame() which calls CL_Drop() on the local client.
That calls CL_Disconnect() and everything is okay.
When the client is already connected to a remote server and no local
server is running the 'map' command spawns a new local server. This
new server thinks "Hey, I'm a new local server and no one is connected
to me. Let's pull the client in!". So it pull the already connected
client onto a new server without disconnecting, smashing it's state.
And everything goes down in flames.
The correct way would be to execute a 'disconnect' right before the
'newgame'. But the 'disconnect' cmd calls CL_Disconnect_f that throws
an ERR_DROP. ERR_DROP is implememted through a longjump(), jumping
around puts the process internal state in ashes... So bite the bullet
and add another hack: Call CL_Disconnect() before executing 'newgame'.
The 'game' command was more or less functional after the last commit.
We just need to reset the initialGame (renamed to userGivenGame) so we
don't revert back to the old game at server disconnect.
When connecting to a multiplayer game that runs a different mod
("game" cvar) than you are, it didn't load the corresponging configs
from the mod, but saved your changes to the config to the mod's config.
Which is doubly useless.
Now when the "game" cvar is changed, the configs are reloaded (from
the right directories for the mod), and when disconnecting the configs
are written, so the changes you did for a mod while playing MP are saved
before game is reset to the game you started with.
The problem was that the cvars were only initialized (with CVar_Get())
if you opened the address book menu.
So if you start (and possibly run) and quit the game /without/ opening
that menu (or at least the "join network server" menu), the game will
not save those cvars to the config when it next writes it.
To prevent this, *always* initialize the cvars in M_Init().
On Unix platforms unicode is implemented through UTF-8 which is
transparent for applications. But on Windows a UTF-16 dialect is
used which needs alteration at application side. This wrapper is
another step to unicode support on Windows, now we can replace
fopen() by a function that converts our internal UTF-8 pathes to
Windows UTF-16 dialect.
This is a noop for Unix platforms. The Windows build is broken,
the compiler errors out in shared.h. This will be fixed in a
later commit.
Caveats:
* fopen() calls in 3rd party code (std_* and unzip) are not replaced.
This may become a problem. We need to check that.
* In the Unix specific code fopen() isn't replaced since it's not
necessayry.
There's no need to exclude directories from search by flags. In fact
the Unix backend has worked nicely for years without it... Sadly we
can't remove the now superfluous 'canhave' and 'musthave' attributes
from Sys_FindFirst() and Sys_FindNext() since they're defined in
shared.h and may be used from custom game DLLs.
Loop 'for ( i = 0; i < 3; i++ )' sets values to vtx[0..2]. So next index must be 3(instead 4) and
loop 'for ( i = 16; i >= 0; i-- )' will set vtx[3..(18*3-1)].
=====
src/client/refresh/gl/r_light.c: In function ‘R_RenderDlight’:
src/client/refresh/gl/r_light.c:76:21: warning: iteration 16 invokes undefined behavior [-Waggressive-loop-optimizations]
vtx[index_vtx++] = light->origin [ j ] + vright [ j ] * cos( a ) * rad
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ vup [ j ] * sin( a ) * rad;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/client/refresh/gl/r_light.c:65:2: note: within this loop
for ( i = 16; i >= 0; i-- )
^~~
=====
This is mostly the same approach as in GL1. I'm not quite sure if the
software rasterizer can work with all aspects and the like but I wasn't
able to crash it by trying several random resultions.
If too many of these sounds are started in one frame (for example if the
player shoots with the super shotgun into the power screen of a Brain)
things get too loud and OpenAL is forced to scale the volume of several
other sounds and the background music down. That leads to a noticable
and annoying drop in the overall volume.
Work around that by limiting the number of sounds started. 16 was
choosen by empirical testing.
This was so broken... Casting the type of an array to silence a
warning... It worked on x86, of course. But gave a SIGBUS on ARM.
Do it right, cast / copy the content of the array into another
array of the correct type. Yeah.
This fixes issue #231.
There're two possible problems with the calculation of the number of
sound buffers for Vorbis if OpenAL is in use:
* We assume that the (more or less) maximum number buffers is allocated
during map load. This is not correct if in a multiplayer game a lot of
custom models with custom sound connect at a later time.
* 64 buffers (about 3 seconds worth of music) may be too low in some
situations.
Work around this by recalculating the number of buffers if necessary.
We're now reserving about 256 (== 12 seconds) buffers.
This may fix issue #252.
We need to take in account that scaling the characters makes them
bigger, thus they need need to be places depending on the scale and not
at a precaclulated position. This should fix issue #247.
Miscframes are coupled to renderframes and are just checking for
renderer changes (very cheap) and advancing CD audio if implemented.
There's no reason not to that at every frame.
This allows us to implement the global timing without an artificial
brake slowing the game unnecessary down. This is only partial working,
more changes and fixes are coming.
The old framecounter had two problems:
* It measured only the time of the current render frame, not the total
time spend between the last and the current render frame. Therefor the
calculated value was too high.
* It was based upon milliseconds and rather inaccurate.
This new frame counter solves both problems. The total time spend
between two render frames is measured and the measurement done in
microseconds.
There're three modes:
* cl_drawfps 1 displayes the average frame rate calculated over the last
60 frames.
* cl_drawfps 2 displays a nice string with minimal framerate, maximum
framerate and average framerate. All three values are calculated over
the last 60 frames.
* cl_drawfps 3 is the same as number 2 but with a second line showing the
raw values.
TODO:
* Discuss if cl_drawfps should be renamed to cl_showfps. All other
status displays are named cl_show*.
While at it remove several unsused drawing functions.
This is the same as the well known Sys_Milliseconds() but like the name
suggests with microsecond precision. To be used in the upcoming new
framecounter.
For some fucking reason, if you set an unsupported
SDL_GL_MULTISAMPLESAMPLES value on Windows (at least Win10 with Intel GPU
drivers, there 16 is unsupported), creating the Window and OpenGL context
will succeed, but you'll get Microsofts stupid GDI OpenGL software
implementation that only supports OpenGL 1.1.
Before these fixes, the GL3 renderer would just crash and the GL1 renderer
would fail to load, which caused the game to run in the background:
No Window, no Input, but sound was playing..
Now this problem should be handled properly and if initialization fails,
the rendering backend will be considered not working, and it will
try the gl1 backend next, and if that also fails it'll give up and exit
the game.
Until now the video menu enforced:
* fov set to 90 and horplus set to 1
* fov set to something other than 90 and horplus to 0
If the user hat configured another configuration through the console the
menu would reset it, even if only unrelated changes are applied. With
this change horplus is ignored by the menu and only fov is altered. The
rationale behind this is that most users want horplus enabled and all
others can disable it through the console.
This is believed to fix issue #225.
While here reimplement the same hack for baseq2/players, lost somewhere
on the way. This is just another searchpath f*ckup. For some reasons
paks have a higher priority than plain directories. We do not want that
for the maps.lst and players/ since id Software decided to put updated
versions of them directly into baseq2/...
This closes issue #217.
SDL_WINDOW_FULLSCREEN changes the display resolution if the requested
resolution is different to the actual resultion. SDL_WINDOW_FULLSCREEN_
DESKTOP doesn't do that, it places a smaller or bigger render area
somewhere inside the fullscreen area. This is somewhat nicer with modern
high resolution flatscreens.
This commit changes vid_fullscreen 1 from SDL_WINDOW_FULLSCREEN to
SDL_WINDOW_FULLSCREEN_DESKTOP. Additional vid_fullscreen 2 is
implemented, it uses SDL_WINDOW_FULLSCREEN to create the fullscreen
area.
TL;DR: Use vid_fullscreen 1 to keep the current resolution or use
vid_fullscreen 2 to switch the resolution.
Implementation details: The whole fullscreen stuff is a horrible mess.
Like generations of hackers before me I'm not desperated enough to clean
it up. GLimp_InitGraphics() is modified to take the fullscreen mode as
an integer and not as a boolean. That's a change to the renderer API.
In GLimp_InitGraphics() the needed SDL fullscreen mode flag is
determined once at the top and just used further down below. That saves
dome SDL1 <-> SDL2 compatibility cruft. IsFullscreen() was modified to
return the actual fullscreen mode and not just if fullscreen is enabled.
if that cvar is set to 1, particles aren't rendered as nice circles, but
as squares, like in the software renderer or in Quake1.
Also documented it in cvarlist.md and fixed some typos there
The model shadows are rendered after all entities are rendered.
This fixes them making entity brushes below them translucent (#194)
The model rendering code used lots of global variables, many of them
totally superfluous (esp. currententity, currentmodel).
I refactored the code to use less global variables (this was at least
partly needed to render the shadows later).
So this looks like lots of changes, but many of them are just using
"entity" instead of "currententity" or "model" instead of "currentmodel"
Like GL1 gl_shadows + gl_stencilshadows: no shadow volumes, but looks
ok apart from standing over edges
The gl_stencilshadows cvar isn't used in GL3, it always uses the stencil
buffer if available (and if gl_shadows != 0)
This still needs performance optimizations: Like the GL1 impl it takes
lots of draw calls per model, it could be done with one per model like
when rendering the actual model.
there have been complaints that those things look too bright, so let
people configure their intensity independently of the general intensity
used for levels, monsters etc.
fixes#189
When applied to y SURF_FLOWING textures are scrolled into the wrong
direction. I guess that in GL1 the offset is also applied to x.
This fixes issue #186.
When the client is paused (either explicit or by entering the menu or
console) the cinematic is paused, too. Therefor no more sound samples
are generated and added to the playback queue, the existing samples are
played over and over again. Until now these samples weren't hearable,
because OpenAL marked them as processed and AL_StreamUpdate() removed
them from OpenALs playback queues. This changed in the previous commit,
now the stay in OpenALs queue and are hearable.
Fix this by calling AL_UnqueueRawSamples() when the menu or console is
entered during cinematic playback.
Newer openal-soft versions changed the way how the processed buffers are
counted when in AL_STOPPED state. Previously only processed buffers were
counted, now all buffers are. Change our unqueue logic to match this new
behavior.
This was debugged and fixed @xorw, I'm just committing the patch. This
closes issue #185.
Resurrect support for render / refresher loadable libraries and use them to implement an experimental OpenGL 3.2 renderer. Please note that the new renderer interface is somewhat different from the original one, old render libraries will NOT work!
The internal order of the items is determined by Menu_AddItem() and
not the y position. Without this change the cursor didn't jump from
item to item, but from the mode list box to the aspect list box,
skipping the brightness slider.
- Bump vid_gamma to 1.2 in both GL1 and GL3. A default value of 1.0 is
too dark.
- Lower gl3_overbrightbits to 1.3, the previous value of 1.5 was too
bright. This can be seen in later units, for example on mine1 some
textures blended into white.
- Lower gl3_particle_size to 40. A value of 60 may be okay, but with
gl3_particle_fade_factor 1.2 the particles take up too much screen
estate in close range combat.
With this changes GL3 looks (at least for me) nearly the same as GL1
rendered through the removed multitexturing path.
Without capping the brightness entity models may fade into pure white
which looks ugly. This can be seen when several flyer fire blaster
bolds onto the player or when multiple barrels are exploding. This
change was suggest by @DanielGibson, I'm just the messenger.
I really don't see why this constraint was ever necessary. It leads to
one line of pixels not rendered either at the bottom or the right edge
of the screen. In GL1 for whatever reasons this line is just black, in
GL3 garbage is drawn.
In SCR_DrawFieldScaled() the HUD scale factor wasn't taken into account
when calculating the screen area affected by the change. Therefor wrong
coordinates were passed to SCR_AddDirtyPoint() and a part of the changed
area wasn't marked dirty, leading to render artifacts.
This bug was present since HUD scaling was first introduced.
the flash should only be drawn in the part of the window where actual
3D rendering happens, not in the borders added if viewsize < 100
(and apparently also for with 1 pixel width if the resolution is odd).
* gl3_particle_size: in GL3 the particles should be a bit bigger because
the particles fade out towards the edge, so I put it in a seperate
CVar
* gl3_intensity: in GL3 the intensity can have any floating point value,
in GL1 only integers, so it gets its own CVar
* gl3_overbrightbits: gl_overbrightbits had to be 1, 2 or 4, in GL3 it
can have any floating point value.
Changed the particle scaling a bit so they look bigger.
One problem was that GL3_Shutdown() called several functions that use
that gl* function pointers - not a good idea if InitContext() failed
and the function pointers are all NULL. So check for that.
Similarly in GL3/R_ShutdownWindow() calling glClear() etc.
Another problem was that R_SetMode() would, if R_SetMode_impl() failed,
try again with a "safe" resolution (640x480 unless we had another
working resolution before) - which is bad if we're already using that
"safe" resolution because then GLimp_InitGraphics() would check mode
and fullscreen and decide it hasn't changed and do nothing and return
true, which would make SetMode() believe everything is fine and
afterwards all hell breaks loose.
This makes the fragment shader faster by skipping lights that haven't
marked this surface in GL3_MarkLights()
This seems to improve performance at least slightly everywhere, but
it really helps *a lot* on integrated intel GPUs like the one on their
Sandy Bridge, Ivy Bride and Haswell CPUs (those are the ones we tested).
adding dot(surfaceNormal, lightToPixelOnSurfaceNormal) to the equation,
should be Phong-y now? Looks good at least.
The Windows AMD legacy driver needed its usual manual padding..
OSX was totally weird.. There were no errors or warnings from OpenGL
at all, but the dynamic lights were just not visible.
After (too long) debugging the shader I figured out that
dynLights[i].lightIntensity was always 1, and thus
'dynLights[i].lightIntensity - distLightToPos - 64' was negative and set
to 0 with max(0, ...).
I still have no idea why that happens, but removing lightIntensity from
the struct, making lightColor a vec4 and using .a for intensity works...
Dynamic lights on normal world brushes work, on brush-based entities
probably not yet properly. For this I need the model matrix in the
shader to transform vertex positions and normals to worldspace
(they already are for world brushes, but not entities that might rotate
and move etc).
Furthermore, while they dynamic lights look nice and smooth they might
need some fine tuning in the shader..
For this to work there are two bigger changes:
* the vertex data for brushes (gl3_3D_vtx_t) now also contains the
vertex normal
- glpoly_t contains array of gl3_3D_vtx_t instead of 7 floats
* 3D shaders now have in vec3 normal, bound to GL3_ATTRIB_NORMAL
* There's a new UBO for light data: uniLights, containing an array of
up to 32 dynamic lights, with data copied from gl3_newrefdef.dlights
..with Radeon 6950 using AMDs legacy driver.
For uploading UBOs it turned out that glBufferData() is faster,
sometimes a lot faster, with several drivers, especially Intel/OSX.
if the lightmap textures are 1024x512 instead of 128x128, all original
Q2 levels will only need one lightmap texture (instead of max 26 or so)
and even maps that needed all 127 (the 128th was the dynamic lightmap)
won't need more than 4.
This should result in less glBindTexture() calls.
(Note: When I wrote "1 lightmap texture" I meant 4, because where the
old renderer dynamically blended the up to 4 lightmaps/surface, I put
them in 4 textures that belong together and are alle passed to and
blended in the fragment shader)
not sure if this is the very best solution..
Every surface can have up to 4 lightmaps.
I now always create 4 lightmaps (in separate textures, so the
corresponding texture coordinates are identical), the "fillers" are
set to 0, so in the shader they won't make a visible difference.
(The shader always adds up lightmaps from 4 textures, but how much
they're actually visible depends on lmScales which also will be set to
0 if "unused")
If all this turns out to be (too) slow, there could be a special case
for surfaces with only one lightmap, I /think/ that's the most common
case by far.
adjusted to new GL3 stuff, of course.
Also, more code for light style/lightmap scale support.
Should probably (maybe) work once we have really have 4 textures
per lightmap id.
(And then of course dynamic lights are still missing)
To be able to test if the game is running portable all checks of the
portable cvar must be done after Cvar_Init(). Instead of redirecting
stdout and stderr as early as possible, delay the redirection right
after Cvar_Init(). After this change the printf() in WinMain() aren't
printed into stdout.txt, but I guess that it isn't a big problem. All
interessting stuff like the search pathes is still there.
Rename fs_portable to portable. It's no longer filesystem specific.
the screenshot command now supports the filetype as optional argument
(just "screenshot" will use tga like before):
"screenshot png" will save the screenshot as PNG, same with jpg, png
and tga.
For jpg, you can even specify the quality, like "screenshot jpg 90"
(the Quality is between 1 and 100, like with libjpeg).
To reduce duplicated code, I addeed Vid_WriteScreenshot() to refimport_t
and implement most of it in the client (vid.c).
The renderer still fetches the raw image data from OpenGL or whatever
and then calls re.VidWriteScreenshot() which will write it to disk in
the format requested by the user.
pass both normal texture and lightmap to shader instead of rendering the
level geometry again with the lightmap and GL_BLEND.
This is not done, some translucent surfaces are buggy now and it's only
static lightmaps. For this to work properly I'll need to add some more
shaders with and without lightmaps and use them accordingly.
For example, translucent surfaces (SURF_TRANS33/66) never have
lightmaps, neither to pertubed ones (SURF_DRAWTURB) like water and lava,
but scrolling surfaces (SURF_FLOWING) like elevators do use lightmaps
(as long as they're not also transulcent or perturbed)...
well, seems to work, but once the lightmaps are rendered with the normal
textured faces, maybe the dynamic part can be done in shader?
(Might even look less blocky, because it's not limited to lightmap
resolution then)
that struct can/should be used with gl3state.vao3D which expects data
as 7 floats (x,y,z, s,t, lms,lmt) - this is used for brushes, sprites,
the sky and more (not for models though).
(For rendering brushes the struct isn't used, the data already is in
that format in float arrays)
beams are now rendered, they are used by the BFG and in some levels for
lasers etc
which just called R_PolyBlend().. no idea what that all was about..
and no idea why it happend in 3D mode, it's much easier after
SetGL2D(), then it can share code with GL3_Draw_FadeScreen() and doesn't
need any additional messing with transformation matrices
* The particles look more fuzzy than in old renderer - I think it looks
better this way ;)
* Not sure I keep the way they're rendered - instead of calculating and
passing the distance in GL3_ShutdownShaders() I could set the player
(camera) origin in a UBO and calculate distance (and based on that
the size) in the vertex shader. I could also pass the basic point size
via UBO, it's the same for all particles..
* Deleting shader programs is a lot shorter now and using a loop and
the fact that consecutive fields of the same type in a struct have
the same memory layout as an array of that type.
Now I can just add a gl3ShaderInfo_t to gl3state, set it up in
GL3_InitShaders() and don't have to add anything to
GL3_ShutdownShaders() (this is good, I forgot that all the time and
didn't notice, as it doesn't cause visible errors)
* Of course the color attribute has 4 floats, not 2..
* I read that updating UBOs with glBufferData() is kinda slow.
I didn't change that (yet), but at least all three GL3_UpdateUBO*()
functions now call updateUBO() which can easily be changed to do
whatever is best without touching the other three functions.
* When using gl_pointparameters, the particles always had the same size
regardless of resolution, i.e. they look bigger (use bigger part of
screen) at lower resolutions. Now I scale gl_particle_size according
to the resolution, assuming the configured size looks good at 800x600
(or generally 600px vertical)
* When not using gl_pointparameters, a textured triangle is rendered.
The texture had a resolution of 8x8 pixels and looked like a cross,
now it's 16x16 and has rounded ages, looking more like a circle.
So particles with "gl_pointparameters 0" should look much better now.
turns out R_MYgluPerspective() was not the same as gluPerspective()
and thus not equivalent to HMM_Perspective() either. Because of this,
the weapon and corresponding arm looked different in GL3 vs GL1.
Created GL3_MYgluPerspective() to fix that.
Also tested optimized code in GL3_RotateForEntity() and
rotAroundAxisZYX(), use this code from now on and cleaned it all up by
removing commented out code.
that was easy..
however, not related to this change or left vs right hand, the gun
seems to be drawn too far back, we should see more of the arm..
I wonder where that went wrong...
introducing vertex color attributes GL3_ATTRIB_COLOR (it's used for
lighting models and to render models flat-colored, I think that's used
for quad damage effect and similar)
kind of messy commit with all the shit from last weekend, finished now
Most importantly the common vertex attribute layout stuff using
glBindAttribLocation()
still no 3D rendering, but in theory it should be able to load models,
bsps etc, just not render them yet.
also moved/copied md2.c and sp2.c to gl/ and gl3/ because they use
renderer-specific types
only for 2D rendering, as we don't have 3D yet; also this might need
a more flexible solution later, as some textures are not supposed to
have intensity applied.
According to the old R_Upload32*() and R_LightScaleTexture() the ones
without mipmaps didn't get intensity. Those were it_pic and it_sky (and
the ones in the "scrap", but those were it_pic too)
when called from R_FindImage() the palette wasn't used anyway.
R_FindImage() now passes NULL.
(LoadPCX() is still called with non-NULL palette from Draw_GetPalette())
the arguments were not used anyway, and returning true/false is clearer
than returning -1 (for error) or sth else (which has no deeper meaning
anyway).
Also:
* PrepareForWindow() can now return -1 if there's an error
* suppress some warnings in Makefile
* fix error for building ref_gl.dylib on OSX
So in all code in the reflib (ref_gl.dll/.so/.dylib) calls to
ri.Con_Printf(print_level, fmt, ...) have been replaced by calls to
R_Printf(print_level, fmt, ...) which uses ri.Com_VPrintf().
somehow all the printf()-like things in Q2 wrap each other and each
one prints into a buffer and then calls the next one with ("%s", buf).
That's not very clever and kinda annoying.
As in the end everyone calls Com_Printf() I created Com_VPrintf()
that can be called instead with the va_list.
I also added printf-format annotation to Com_Printf() and Com_DPrintf()
and fixed places where Com_Printf() was called with the wrong type.
and the changes in the including files for this.
(also removed gl.h includes from local.h, as it's already included in
qgl.h which is included by local.h)
Repeat 10 times:
- strcat() is evil
- strcat() is evil
...
While here fix another small inconsistency: Vorbis playback should
stop when switching 'shuffle' on.
The overflow was reported by @tomgreen66 in pull request #168.
Until now autoexec.cfg was a special case. It was read several
times, whenever the 'game' cvar was altered or when the client was
restarted. But only if it was in the right directory in the right
position of the internal search path... Remove this altogether and
replace it by an ordinary 'exec autoexec.cfg' at startup.
This may break some mods that depend on an autoexec.cfg if the user has
his own version in ~/.yq2/. Such mods should use default.cfg instead.
This closes issue #163.
Multitexturing was never part of any official Quake II release. It was
added in version 3.21, which was released only in source. Over the years
many developers tried to fix multitexturing, including myself. Yamagi
Quake II had it even enabled by default for several releases... But:
* Multitexturing is poorly implemented and **slow**
* Multitexturing leads to render errors, for example in city3
* Multitextring is ortogonal to the normal render path and adds a
lot of special cases to the renderer
Remove it for good. Ciao, it wasn't a nice time. :) The last version
before this commit was at least somewhat fixed, read some of the worst
problems were fixed. If someone's ever going to resurrect it, it would
be a good idea to start at that point.
Otherwise at least one key may be still marked as down causing an
immediate abort of playback. While here be a little bit paranoid
and clean up key states when focus is gained. In theory that's a
no-op.
When the video is scaled through OpenGL we can just throw it on our
vertexes and everything's alright. But when we're softscaling the video
we must consider that the videos size doesn't really match the vertex
size...
especially in the intermission videos, the text looked broken, as parts
of the characters were missing.
This is because Draw_StretchRaw() converts the 320x240 video frame into
a 256x256 texture, without doing proper interpolation (just skipping
some pixels instead).
Now, if the GPU supports non-power-of-two texture sizes, the video
frames are uploaded as textures in their original size.
(Also fixed a harmless typo in common.h)
The original client crashed (or survived by pure luck) when muzzle
flash offsets >210 were send. Our fix was to bail out, but that broke
some buggy mods... So just return and print an optional debug message.
This fixes issue #153.
This step height is used by several evelators, leading to stuttering due
to misspredictions. Additionally half height steps weren't smoothed by
the synchronous client.
Predicting these steps leads to a heavily stuttering elevator in
hangar1. I think that steps between 94 and 98 can't appear on stairs, so
just remove them. If I'm wrong we need a hack to the hack ontop of the
hack... ^^
This fixes#119. As always I've chosen the least invasive way to solve
this problem. Trying to open players/$model/trix.md2 is hack, but solves
the problem without changes to filesystem.c and it's API.
With vsync enabled the render times of consecutive frames can diverge.
The first frame arrives right at the next display frame and is rendered
without waiting time. The next frame has to wait 20ms. The leads to some
problems with the move prediction if the client is asynchronous. Fix
this by capping the desired frame rate at the display refresh rate. Also
make sure that the network framerate is never higher then the renderer
framerate.
With the commit the timing is always correct:
* With no limit as much frames as possible are rendered. In this case
rfps > nfps and everything's good.
* With vsync enabled rfps > nfps or rfps == nfps is given. Also rfps
will never exceed the display refresh rate.
* On slow hardware either rfps > nfps or an implicit rfpc == nfps is
given.
While the bugfix in a6f4a3b made the steping prediction working for
stairs, elevators are still stuttering. r1q2s code solves this problem
and is a little bit faster. Use it instead.
Yesterday I chose setting cl_async to 0 since I saw some movement
changed with the async client enabled. Especially when clipping against
bevels the game started to stutter and there were small rendering
problems. After some debugging I realized that it is caused by slight
inaccuracies in the move prediction. When cl_maxfps is too low, the
movement error between two render frames becomes to big, leading to
misspositions. There're two ways to solve this problem:
* Processing more client frames. Most async clients I've looked on
process 60 or even 90 render frames. I chose to stay at 60 since
I was unable to see differences with higher rates.
* Changed to pmove.c and the pmove_t struct. Some multiplayer focused
clients go that way. But there's a very high of breaking singleplayer
movement and pmove_t is part of the server <-> game API. Additionally
the network code must / should be altered. So this is unsuitable for
YQ2.
Please note that there's still a change in movement. Before 4ae8706 and
when cl_async is set to 0 movement is dependend on the render framerate.
At low framerate bevel clipping isn't working too good, at high
framerates prediction causes physics changes like the famous 125hz bug.
With cl_async set to 1 the network framerate is stable, leading to a
more consistant behahiour.
Most (all?) clients implement the synchronous and the asynchronous
client by seperate code pathes. Instead of doing that we force the
asynchronous path to process one network frame for each render frame.
We're missusing the current frame to pass data from the input subsystem
to the movement prediction without a server frame. While we can use the
current frame for the movements itself, it's not finished and thus
unsuitable for stair step prediction. Also oldframe is determined
wrongly. As a result the player "jumps" over stairs.
This is a slighty revised version of id Software original code. Icculus
code may have some advantages on broken drivers or underpowered GPUs.
Today it's just a performance hook. This is a first step in fixing #147.
This is more than enough for everyone and prevents wasting CPU time.
Without this change as many client frames as possible are rendered,
Quake II uses a complete core.
This is based on work submitted by Scott "pickle" Smith. It's said that
vertex arrays are somewhat faster and more compatible than the old way.
This may remove support of some very, very old GPUs like the Riva128.
This is more less cosmetics since gl_tex_solid_format == GL_RGB and
GL_LIGHTMAP_FORMAT == GL_RGBA. No measurable FPS change on Nvidia and
Intel. Based upon the OpenGL ES patch by Scott "pickle" Smith.
This is based upon the original OpenGL ES patch by Scott "pickle"
Smith. This change gives about the same frame rate on an 750TI but
about 3% more frames on an Ivy Bridge IGP with Mesa3D...
This is largely based upon the cl_async 1 mode from KMQuake2, which in
turn is based upon r1q2. The origins of this code may be even older...
Different to KMQuake2 the asynchonous mode is not optional, the client
is always asynchonous. Since we're mainly integrating this rather
fundamental change to simplify the complex internal timing between
client, server and refresh, there's no point in keeping it optional.
The old cl_maxfps cvar controls the network frames. 30 frames should be
enough, even Q3A hasn't more. The new gl_maxfps cvar controls the render
frames. It's set to 95 fps by default to avoid possible remnant of the
famous 125hz bug.
I'm not quite sure if this really makes a difference. But it's the only
idea I have regarding several "Quake II hangs at shutdown when OpenAL is
run with Pulseaudio backend" bugs.
Hardware gamma is broken, especially in fullscreen, and a Mac user told me
that setting HW/screen gamma on OSX is a bad idea anyway, because it resets
the monitor calibration.
The game /should/ look ok with vid_gamma 1 (if your display is configured
properly), but if you think it's too dark set it a bit higher and do
vid_restart.
Multitexturing was enabled by default in 0f7b422. It gives a small but
on todays hardware neglectable performance boost, but caused several
problems over the years. For example gl_showtris doesn't work with it
and there's at least one render glitch in city3.bsp.
turns out the if the console is opened while no game is currently
running, cls.key_dest is not key_console but still key_game.
Changing it to key_console in those cases blows up in interesting ways.
So in Char_Event() we send events to the console in those cases.
This clamps the UI scale, limiting the relative size of the UI
elements to what they would be at scale 1 in a 320x240 resolution.
Allowing bigger scales is not useful, and would make it possible
for the user to shoot him-/herself in the foot by setting a
"too big" UI scale value in the menu. (Since this would mess up
the menu, it could be hard te recover from for a casual user.)
AL_PlayChannel() is only called by AL_AddLoopSounds() and
S_IssuePlaysound() - but only the latter set a volume there.
Because of that, loopsounds weren't hearable anymore after the last
commit which removed adding s_volume to all volumes in AL_PlayChannel().
This is fixed by setting the volume for looped sounds in
AL_AddLoopSounds() as well.
Looped sounds don't seem to have a customizable volume and are always
played at full volume (the volume is only changed by distance, but
OpenAL does that automatically).
The CD music enable / disable box wasn't used by many users for two
reasons: CD music playback needs a CDROM drive with analog output.
Such drives aren't available for at least 10 years. And CD music is
unsupported with SDL2. A OGG volume slider is much more usefull.
Con_DrawConsole() assumed that the version string was always 21chars
long, we changed it to allow longer strings with other lenghts.
In Unix main() we changed the code for underlining
"Yamagi Quake II $version" with === so the underlining is as long
as the underlined string.
Moving the check under the "do we have the file localy" check prevents
spurious "Refusing to download a path with .." messages with some game
data. The tank commander skin is one example. This change has no
security impact since FS_LoadFile() just opens and closes the file.
While at it tighten the condition to prevent pathes with colons (this
condition is added at the server side, too) and pathes starting with
slashes and dots.
When the keypad was activated key presses were processed twice.
Once as a normal char event and once as a key event (not marked
as special). The key event to console character translation
function turned the key event into a second character...
The savegame list is generated by calling FS_FOpenFile() for each
possible savegame name. When a file handle is returned the savegame
exists, otherwise the savegame slot is empty. But FS_FOpenFile()
searches in every directory known to the VFS. If a savegame file
isn't found in $moddir but in baseq2, the file in baseq2 is opened
and a baseq2 savegame is displayed in the mods / addons savegame menu.
The fix is compromise between a clean solution and invasiveness:
- Refactor FS_FOpenFile() to include FS_FOpenFileRead(). FS_FOpenFile()
was used only to open read only files, limit its's possibilities to
do exactly that.
- Introduce a new flag "gamedir_only" to FS_FOpenFile(). When true
only the gamedir directories are searched and not other directories
like baseq2.
- Change all callers to FS_FOpenFile()s new signature.
- Use the new gamedir_only flag to limit the searchpath for savegames
to the gamedir.
OpenAL sources are reused in Quake2, so if a source has once been used
for a sound coming from the view entity, it'd stay relative, unless
told not to.
So now I set source's AL_SOURCE_RELATIVE to AL_TRUE or AL_FALSE in
AL_PlayChannel(), depending on the source coming from the player or not.
Thanks a lot to Tommi Teistelä for identifying the problem and pushing
me in the right direction!
should hopefully fix#93, which seemed to be caused by ^ and ` being
bound to toggleconsole in default.cfg (as shipped with Q2) *and*
in code, so it'd be called twice and cancel each other out.
It even warns if someone tries to bind those keys and includes an ugly
hack to *not* warn when it's done in default.cfg, to minimize confusion.
OGG_OpenName(): add ogg_ignoretrack0 cvar to set whether we respect
default playback behaviour when track 0 is requested to be played via
standard cd audio playback.
Submitted by: ewe2
As Jack Whitham noticed [0], animated textures freeze at their first
frame if they're on a transparent surface. This can be seen in base3
(Com Centre), for example. At least for the OpenGL renderer this is
caused by the fact that the animation chain is never forwarded if the
texture is bound to a transparent surface. The fix is to do exactly
that...
I can only speculate why the animations on transparent surfaces were
never used / implemented. Maybe performance issues or it was just
forgotten.
0: http://blog.jwhitham.org/2015/04/more-fun-with-floating-point-numbers.html
sounds easy, right?
Except some genius decided to save CVAR_LATCH cvars in buffers of
MAX_OSPATH length into savegames.. so just changing MAX_OSPATH
breaks savegame compatibility.
Fortunately, this assumption only matters in SV_WriteServerFile() and
SV_ReadServerFile() so I worked around it by introducing a
platform-specific LATCH_CVAR_SAVELENGTH (because MAX_OSPATH was 256 on
Windows but 128 on other systems..)
it's saved in $HOME/.yq2/$mod/history.txt
While I was at it, I made the max number of lines in the history
configurable at compiletime by introducing a NUM_KEY_LINES #define
It's apparently not enough to clear key repeats, we'll need to clear
the down states too. Without this Alt stays pressed after toggeling
fullscreen trhough Alt-Enter.
Switching to fullscreen through a SDL2 call is nice, but the renderer
needs to be reinitialized. Without it some things will break, for
example the gamma setting.
No, this is not a rage quit but the result of a long discussion. There
are several reasons for us to drop OS X support:
- OS X support was always more or less hacky. For example is was never
really integrated into the build system and some features like the
OpenAL sound backend never worked well.
- The OS X support never grew into the new world based upon SDL2.
- It was broken since at least Lion which was released 4 years ago.
- None of the developers has a Mac or plans to buy one. Supporting
a software for a platform not used by the developers is more or
less impossible.
- And despite several appeals no one from the OS X community ever
stept up and send patches.
Removed are:
- Makefile support
- The OpenAL quirks
- The Cocoa bindings
- The framworks
Not removed is:
- Savegame support
- Memory management support
- Platform detection
- OpenGL and SDL includes
So, if someone steps up and does a modern, fully integrated port based
upon SDL2 we're happy to merge it back. The requirements are:
- It must be a clean port, without any hacks
- Full build system integration must be provided
- The port must be maintained even after it was merged. At every release
binaries must be build, API / ABI changes with new OS X versions must
be tracked.
Retexturing support is now always on (you can still switch it off with
the gl_retexturing CVAR), as we don't have the additional libjpeg
dependency anymore.
stb_image is used for tga, jpg and the newly supported png, so the
old tga and jpeg loading code has been removed.
I furthermore cleaned up the somehow messy and possibly slightly broken
retexturing selection code in R_FindImage()
Check and use GL_ARB_texture_non_power_of_two and use it if present to allow using all textures unscaled. This makes a huge visual improvement since most skins are not power-of-two textures.
Conflicts:
src/client/refresh/header/local.h
Okay, I tried to solve this issue the gentle way. But apparently it's
not enough to track if a key is down. We must consider if the key is
just down or if it's already repeating... Therefor raise the white flag
and just put the original logic back in place. This may fix issue #57.
When we're building command we must make sure, that all command for
one keystroke will have the timestamp in microseconds. If that's not
the case the command may end up in differend server frames, breaking
things subtile. This may be part of bug #57, but I'm not sure.
This is a less intrusive variant of the old Key_ClearState() function.
When the refresher is restarted or the menu is left, this function is
called to mark all keys as "up". That works around some corner cases
where a key is still marked "down" and thus the first stroke is detected
as a repetition.
- Handling of key combinations like Alt + Return or Shift + Escape
clearly belong into the frontend. Now that the client won't clear
the keystates any more it's save to handle them there.
- The 'force_centerview' command belongs into the client move stuff.
I guess it was part of the backend sinces it messes with mouse
handling. Since the renderer is now part of the client that's not
necessary anymore.
- One can argue that +mlook and -mlook belong into client move stuff,
too. But since we need there calculations in the backend anyway,
leave things like they are.
Until now Quake 2 used keysyms aka key events for everything, including
the console and the chat window. Since key events don't reflect if the
shift key is pressed, Quake 2 needed to convert the lower case chars to
upper case char through a hardcoded table. That lead to the problem that
the keyboard layout was utilised for lower case characters only.
Solve this long standing problem by refactoring both the input backend
and the frontends Key_Event() funktion to use character events for most
input subsystem. Character events are generated by SDL and send the
real character.
An example:
- On german keyboards shift and . is : but Quake 2 generated <.
- Now a character event with : is generated and used.
There are at least 3 disadvantes by this approach:
- The backend needs to tell the frontend if a normal character (ASCII
32 to 126) or a special character is send. Only normal characters can
be treated as character events.
- There may be some differences between the binding of a key seen
through the console and seen by the game. If you have a german
keyboard and bind :, the game may not react to :. This can be worked
around by editing the config file.
- Users may need to rebind some keys.
Please note that Quake 2 can handle ASCII characters only!
In the old times the refresher was a stand alone DLL. For performance
reasons and to avoid laggy input parts of the input system were
implemented in this DLL. Now that the renfresher is part of the main
binary and initialized at client startup we can remove most of the
abstractions between input system, refresher and client. Also the
input system can be treated as a normal subsystem.
Changes:
- Untangle the VID_* stuff and the IN_* stuff. The functions
called by function pointers in in_state are now called directly
and 'struct in_state' was removed.
- Remove input.h and rename the appropriate backend functions.
There's no longer a need for an abstraction layer between the
input backend and the input frontend.
- Move input initialization and shutdown into CL_Init(), like it's
already done for all other subsystems.
- Remove Key_ClearStates(). I'm pretty sure that's a left over from
the old Win 9x backends and unnecessary.
- General cleanup.
Historicaly this functions were used to adjust the cd music volume. In
YQ2 they were converted to enable or disable the cd music. Change their
name to match their current purpose.
This commit has some drawbacks:
- It's rather hacky. The Quake II menu is crap and was never intended
to be scaled. My approach was to add scaling to most of the generic
functions and handle all the special cases in the non generic parts
of the menu. A better solution would require to rewrite at least
parts of the menu. And like it's said in qmenu.c: I won't do that.
- Some menu elements are aligned to the right, others to the left. In
many places magic numbers are used to align elements by hand. This
makes it very hard to impossible to implement a scaling logic which
works in all situations. With this approach most menus look good up
to at least a scaling factor of 3. Especially the "Player Setup"
menu is very problematic at small disalignements are unavoidable.
Please note, that only the menu system itself is scaled. Some elements
like the the "Quit Screen" or the loading plaque are still missing. They
will be done in a later commit.
This change is needed to break a otherwise fatal cycle:
- The renderer calls VID_MenuInit()
- VID_MenuInit() calls SCR_GetMenuScale()
- SCR_GetMenuScale() relies on gl_menuscale which is still
uninitialized at this time.
This fixes a long standing and until now unnoticed bug with negative
colored dynamic lights. Since we never set the OpenGL renderer as out
renderer, remaining softrenderer code was executed and the corresponding
effects never rendered. This manifested itself in missing darkness
around the "gravity well" in rogue.
Newer jpeg versions (I guess starting with 9) define an macro
"VERSION", colliding with ours. While wie could #undef it, take
the less hacky route and rename it.
Without this define newer versions of jpeg define a type "bool" as char,
while the MinGW headers define it as "unsigned short". Automake should
have detected that, but...
The code used build fine on my workstation, since Mesa3D has the
required macros since ever. But on Windows gl.h is still limited
to OpenGL 1 (really?).
MSAA was a long wanted and often requested feature. Just set set the
desired number of samples with gl_msaa_samples and do a vid_restart.
This code is based upon work done in Hecatomb.
Input devices should send key events and nothing more. The ability to
add commands into the input buffer was used by the joystick code
(removed long time ago) and as a dirty hack to work around limitations
of DirectInput.
This function is only used in cl_view.c, so no need for external
declaration. Reimplement it in a sane and on all platform 64 bit
clean way. This allows us to finally remove the horible INT macro.
Without this change the width of the render windows was required to be a
multiple of 8, making it unable to use strange resolutions like 1366x768.
This change is based upon an idea submitted by "tmcp" in pull request
27.
Makefile is adjusted, it compiles and works mostly, but
* For some reason (bug in SDL_GetRelativeMouseState() ?)
mouse input doesn't work properly.. it seems to be bound
to window borders, even if input is grabbed
* some keys can't be used anymore because there's no SDLK_*
for them anymore (gotta find out if this is important)
* Maybe some of the changes need cleanup
Those extensions have become part of ARB about 15 years ago and most if
not all video cards still in use should support the ARB versions. I
believe that at least parts of this code were disfunctional.
This removes the need to define the old qgl function names to the
official OpenGL names. The OpenGL functions are now called directly
without any abstraction.
With this change the "refresh" make target doesn't any longer exists.
It was merged into the "client" target. One will need a "make clean"
before building yQ2 after this change.
This is a manual merge of Hecatomb Q2 ref b8952d5. Manual since git
couldn't do an automerge for some reasons... Notable changes are:
- QGL function pointers are removed, libGL is linked directly
- The OpenGL log framework is removed. It was disfunctional
- The gl_driver cvar is finaly gone
This change is currently untested on Windows and OS. There should
be no problems but a better Makefile integration of libGL is needed.
Normally setting gl_mode cvar would result in VID_LoadRefresh because
of vid_ref being "modified". After removing vid_ref out of the picture
it will "modify" vid_fullscreen to replicate the same behaviour.
Variable "name" (who used to hold refresh dll name) is now left unused
All references to vid_ref cvar has been taken out ...
Revert "change several strcat calls to Q_strlcat calls"
This reverts commit ab879f1bc7.
Revert "change (v)sprintf calls to (v)snprintf calls"
This reverts commit b46e210d76.
Testing showed that after the last round of sound changes FreeBSD is the
only platform with distorted sound when s_volume is set too high. I'm
pretty sure that it's caused by a bug in the OSS backend of openal-soft.
I'll need to analyze this more and maybe write a problem report. Since
FreeBSD users should be experienced enough to lower the volume when
there are problem (there's a FAQ in our README!), use the same default
volume on all platforms.
If the volume is set too high the OpenAL backend preamplification leads
to overdriven sound samples. It's not quite understandable to me why
that only happen on platforms other than Linux (maybe a bug in OpenAL?)
and there's not much we can do against it besides reducing the volume.
As the side note: Simmilar behavior can be seen at least in ioQ3 and
dhewm3...
This cvar is a last resort if all other measures to prevent overdriven
preamplifation fail. Setting it to lower value than 1.0 limits the
overall dynamic range, so sound quality is lost. This is especially
hearable when low volume samples are encountered, like the shotgun
combined with the silencer.
The client uses float values between 0.0 and 1.0 to represent the volume
of sound samples. This is the range required by OpenAL. But the generic
part of the sound system multiplied the raw float value with 374 and
clamped it to a full integer. That worked by luck withth the OpenAL
backend but broke at least the silencer powerup. Solve this problem by
adding a new field "float oal_vol" to the channel_t struct and use it to
pass the raw float value to OpenAL.
This fixes issue #18
Since OpenAL 1.15 AL_GAIN has much more weight than before. That leeds
to overdriven effect samples unless the volume control is set to a very
low level. With this change volume can be set to a high level without
distorting. But there's one problem. A division by 2 is to low to rule
distortion out and by 3 the game is a little bit quieter than before. A
value of 2.5 would be optimal but is not applicable since the volume is
represented by an integer. I've choosen 3 to be aon the save side.
As a side note: This problem was very less worse on Linux than on
Windows and FreeBSD. Maybe Linux guys need to pump there volume up
to compensate this work-around.
For ia64 it's necessary to define int as long long instead of long int. I know
this for a fact because pointers that were encoded as long int in my LLVM and
CLIPS bridge would fail horribly when passed out of clips back into LLVM. long
long fixed it.
If "horplus" is set, the "fov" cvar is interpreted as the horizontal FOV
in a 4:3 screen, and is adapted automatically to the current screen
aspect ratio accordingly. If not set, use the old Vert- approach.
In addition, "horplus" can also be set from the video menu by selecting
the "Auto" option for aspect ratio, which also resets the FOV value to the
standard 90 degrees.
Finally, add a 5:4 aspect ratio (1280x1024) and correct the 16:9 angle
slightly.
These are the code changes and Makefile changes necessary to build and
run Yamagi Quake II on Max OS X. OS X 10.6 or higher is required, older
version may work but we cannot guarantee it. The documentation will be
added in another commit. This patch was contributed by W. Beser, I made
only some small cosmetical changes.