Unlike the Steam and GOG support I'm not doing a registry search as I don't see anything in the registry that would show us the path. If we find more official ways to search for it later we can address that, in the meantime the path is just hardcoded to where it's installed by default.
The ppc arch is the 2.0.1 that was there originaly.
The i386 arch is 2.0.16, now compiled with an SDK later than 10.9 so the Notarization process is cool with it.
So now all post-ppc SDL libraries are 2.0.16.
Also works on Apple Silicon. Specific signing values are in a non-committed file, and the ub2 script only notarizes if a "notarize" flag is passed in on the command line.
NOTE: the SDL dylib currently only has x86_64 and arm64, will need extra work to graft those back in and keep the Notary service happy.
- Reorganized Xcode project
- Added missionpack support to Xcode project
- Incorporated changes from MaddTheSane for Apple Silicon support https://github.com/maddthesane/ioq3
- Built SDL 2.0.14 for Apple Siicon, added to existing SDL dylib
- Built SDLMain for Apple Silicon, added to existing libSDL2main.a
qvmcall64 has its own custom calling convention due to pushing all non-volatile registers to the stack. The game uses set/longjmp which on Windows uses "RtlUnwindEx" to unwind the callstack. qvmcall64 cannot be unwound by default due to the custom calling convention. To allow unwinding, we need to add custom SEH unwind data to the function.
Not all non-volatile registers were actually saved and restored, leading to a few registers being trashed after calling the vm instructions.
All non-volatile registers have been added.
The affect of my 2017 commit c3e64d3806
"Make bots only use q3tourney6 crusher to kill their enemy"
made it easier to beat the last map of the Quake 3 single player
campaign. It was mainly intended for CTF and Team Arena gametypes
variants of the map. (Team deathmatch is usually treated as deathmatch
with teams rather than an actual team based gametype.)
Restore original difficulty for non-CTF/Team Arena gametypes; bot will
crush player even if bot hasn't seen the player since either they or
player respawned. [This is not good in CTF where all five bots on the
team suddenly flip around and shoot at the crusher trigger.]
Team deathmatch still uses my added behavior of not triggering crusher
if there is a teammate under the crusher.
Pulseaudio audio capture didn't stop when paused on Debian 8 but works
on Debian 9 when using the same manual SDL build. So it seems to have
been an issue in pulseaudio, not SDL.
- New msvc142 directory (keeping with naming after version of C compiler)
- Added SDL2.lib/SDL2main.lib back in (compiled from SDL 2.0.8 source from libsdl.org)
- Post build step to copy SDL2.dll to debug directory
There is no need for a tentative definition in this case. By providing
an explicit initializer, the resulting definition has the same effect
as before, but is no longer tentative. This avoids easy errors
resulting from multiple tentative definitions in different translation
units. (Previous compilers permitted those common errors, but GCC 10
rejects them by default.)
My 2017 commit f7c3276 ("Fix g_teamAutoJoin and g_teamForceBalance")
caused BroadcastTeamChange() to be run an extra time when bots connect.
This caused a duplicate center print message to be sent to all clients.
g_teamAutoJoin 1 sent an extra center print when any player or bot
connects. Though that is the original behavior from Team Arena.
Team set during connection no longer sends broadcast as it will be
sent later in ClientConnect().
Reported by Pascal Brochart (pbrochart) as causing clients to be
kicked due to server command overflow if many bots join at the
same time.
If bots join before the local client (dedicated server) the bots would
not be listed in the Q3A team orders menu and so they could not be given
orders using the menu.
The Q3A team orders menu got local client's team while looping through
all clients. Ignoring any bots with clientnum lower than the local
client. Get local client's team before the loop so all bots are
listed.
The lightning trail is fired from the real non-predicted entity for
the local client so it can show the server location. The real client
entity was always used to check if a player entity is firing the
lighting gun. This potentially causes corpses and players on single
player podiums with lightning gun to render the lightning trail if
the real (living) client is firing the lightning gun.
I'm not aware of this causing any issues without modifying the game
logic. Corpses have no weapon and it's not possible to fire during
single player intermission.
GL_CLAMP (clamp to border) was changed to GL_CLAMP_TO_EDGE in 2008
(f2baf359). In 2018 (ce1d5406) I made OpenGL 1.2 be required since
GL_CLAMP_TO_EDGE is used.
Restore support for GL_CLAMP in order to support OpenGL 1.1 like vanilla
Quake 3 does. This should allow using the default Microsoft Windows
GDI Generic OpenGL 1.1 driver (untested but it won't fail the version
check at least).
From gpuinfo.org, it looks like drivers stopped advertising support for
GL_SGIS_texture_edge_clamp so use a version check in addition to the
extension check.
r_allowExtensions 0 disables using GL_CLAMP_TO_EDGE in the opengl1
renderer. GL_CLAMP support wasn't added to the opengl2 renderer.
For lerped frames (refEntity_t frame not equal oldframe) IQM joint
matrices may have incorrect axis scale. This can cause significant model
distortion. The matrix lerp is linear causing each vector to move in a
straight line between frames instead of arcing like a circle. Each joint
frame can have a different scale so can't just normalize the joint
matrix.
Store joints as quaternions and spherical lerp between them and then
convert to a matrix. For my test model, setting up the skeleton is four
times slower now but it still seems to be fast enough to be usable.
r_cubeMapping requires textureCubeLod() which is only in OpenGL 3.0
(GLSL 1.30) and later. It's not in OpenGL ES 3.0 / GLSL ES 3.00.
This needs to be checked before R_InitImages() so can't just check in
GLSL_InitGPUShaders().
Override the video mode list in the Team Arena data files with detected
modes from SDL like in ioquake3's Q3 UI. Add the aspect ratio to the
end of the video resolution (i.e., "640x480 (4:3)"). Add the current
(custom) video mode to the list.
Before when using a custom resolution in the menu you could not change
the video mode using the mouse because the resolution text was blank.
Now custom video resolution is displayed and can be clicked.
Team Arena HUD's team member info box can be cycled through using
nextTeamMember and prevTeamMember commands. nextTeamMember command loops
around when end of list is reached but prevTeamMember command got stuck
at last entry in list (team overview).
My commit last month "Fix SDL audio playback with surround sound" broke
16-bit stereo sound. S_TransferStereo16() still assumed that dma.samples
was a power of two. I also cleaned up code related to the previously
mentioned commit.
If user has surround sound enabled, ioq3 would not play any sound.
Fix painting sound buffer for 4/5.1 audio channels. Extra channels
currently play no audio.
BotSetEntityNumForGoal() was checking all entities that are not
team_redobelisk (which is the obelisk visual entity) to find the
untitled obelisk collision entity. This may fail in rare cases where
there is an another entity within 10 units of the obelisk origin.
Failing to find the correct entity may cause bots to not attack the
obelisk.
Instead add BotSetEntityNumForGoalWithActivator() for looking for the
obelisk collision entity by activator classname (team_redobelisk) which
should be less likely to find the wrong entity.
This doesn't affect official Team Arena maps (unknown if it affects any
others).
Reversed strcmp check was reported by Thomas Köppe.
Bounds are optional for animated IQM models but are not possible to
include with unanimated models (seems intended for use with separate
model containing animations and bounds). Calculating bounds for
unanimated IQM models fixes culling and head model on HUD which
calculates position from model bounds.
The axis returned for IQM tag was the animation's joint rotation without
the base frame joint rotation. It only worked correct for models that
did not rotate the base frame joints.
Using GPU vertex skinning is significantly faster than CPU vertex
skinning. Especially since OpenGL2 has to run R_VaoPackNormal() and
R_VaoPackTangent() each vertex each frame which causes CPU vertex
skinning to be significantly slower than OpenGL1 renderer.
Only calculate vertex blend matrix for each unique bone indexes/weights
combination once per-surface instead of recalculating for each vertex.
For best performance the model surfaces needs to use few vertex bone
indexes and weights combinations.
Unroll loops so GCC better optimizes them.
In my tests drawing animated IQM may take 50% as long in opengl1 and
70% as long in opengl2. It will vary by model though and might not
help much at all.
Made unanimated IQM models skip matrix math altogether.
- Only allocate memory for vertex arrays that are present in the IQM
file and are actually used (may not have colors or blend index/weights,
don't load tangents in opengl1). (Colors is fixed to next commit.)
- Explicitly handle loading IQM files without meshes (bones only).
- Better IQM validation. Header data offset 0 mean data is not present
in file. Check if required vertex arrays are present.
This involved a lot of white space changes and moving code around.
Fix two constants in GLSL shaders. Remove f suffix from float and fix
int to float assignment. They were causing shader compile errors in
OpenGL ES 2 context.
Remove disabling clip plane. Clip plane is unused and never enabled in
the opengl2 renderer. Remove disabling it to avoid causing a GL error
when using OpenGL 3.2 core profile or OpenGL ES.
Make VAO cache vertex stride be size of srfVert_t since that is what
is uploaded to the GPU. No behavior change. There is a disabled debug
id in srfVert_t though which if enabled changes srfVert_t size.
OpenGL ES is only required to support unsigned short for element buffer
values.
R_DrawElements() firstIndex argument was glIndex_t which caused element
indexes to wrap around to 0 when glIndex_t is an unsigned short.
(glIndex_t is an index into the vertexes buffer, not element buffer.)
Change it to 'int' like tess.firstIndex which is passed to
R_DrawElements().
World VAO cache buffer size allowed storing more vertexes than unsigned
short glIndex_t could reference. This resulted in the vertex indexes in
the element buffer wrapping around to 0.
Load functions procs supported by OpenGL ES 2.0, though there is not a
compatible renderer yet. Change argument for GLimp_Init from coreContext
to fixedFunction.
Also declare the GL functions in tr_local.h so there is compile error
for non-core GL functions instead of SEGFAULT from dereferencing a NULL
pointer.
Disable the non-functional stencil shadow code that hasn't been updated
to use OpenGL 3.2 core compatible drawing.
If renderer is compiled into client (USE_RENDERER_DLOPEN=0) and after
start up set r_allowExtension to 0 and run vid_restart, some extension
were still used.
Connecting to a server running a different fs_game and using a
autoexec.cfg containing in_restart would hit a fatal error in IN_Init().
IN_Init called before SDL_Init( SDL_INIT_VIDEO )
Reported by smokey2k on the ioquake3 forum.
In 2013 ioquake3 stopped referencing the pk3 file that qagame.qvm was
loaded from. This had the unintended side affect of causing
non-dedicated pure servers to no longer reference a pk3 that only
contains the three QVM files.
Non-dedicated pure servers did not reference the pk3 containing the
latest cgame.qvm so if client did not have the pk3 file they were kicked
as unpure instead of the client trying to download the pk3 file.
Also make server touch ui.qvm since it's required to pass pure check and
may be separate from cgame.qvm.
Moved all the code using Altivec intrinsics to separate files. This
means we can optionally use GCC's -maltivec on just these files, which
are chosen at runtime if the CPU supports Altivec, and compile the rest
without it, making a single binary that has Altivec optimizations but
can still work on G3.
Unlike SSE and similar extensions on x86, there does not seem to be
a way to enable conditional, targeted use of Altivec based on runtime
detection (which is what ioquake3 wants to do) without also giving the
compiler permission to use Altivec in code generation; so to not crash
on CPUs that do not implement Altivec, we'll have to turn it off
altogether, except in translation units that are only entered when
runtime Altivec detection is successful.
This has been tested on Linux PPC (on an Altivec-enabled CPU),
but we may need further work after testing trickles out to other
PowerPC devices and ancient Mac OS X builds.
I did a little work on this patch, but the majority of the effort belongs
to Simon McVittie (thanks!).
When you start recording using SDL pulseaudio driver the client sends
all audio captured while not recording. 240 milliseconds of audio is
sent each frame until the capture buffer is empty. This is a problem for
privacy and causes confusing to debug VoIP playback issues on other
clients connected to server and when playing back demos.
Fix specularScale <metallic> <smoothness> with r_pbr 1 which has been
broken since r_pbr was implemented in 2016.
Fix specularScale <r> <g> <b> <gloss> setting b to gloss and leaving
gloss as 0 since it was implemented in 2014.
The key handler allowed going 2 beyond the end of the bot list and the
display function clamped to 0 causing the first bot to be shown 3 times.
Attempting to add the bot in gametypes < GT_TEAM would fallback to
Sarge in UI_GetBotNameByNumber() (who isn't the first bot) and gametypes
>= GT_TEAM would access characterList past known values (typically NULL
but if teaminfo.txt contained 63 characters it would access out of
bounds memory).
Switching to dedicated camera follower with no possible players to
follow would spawn at the intermission point and display "connection
interrupted" HUD message. Pmove() was not run for the client so
ps.commandTime was too far behind. I made it so that dedicated camera
followers and scoreboard run Pmove() but cannot move (PM_FREEZE).
When all players possible to follow leave, the dedicated camera follower
would continue to display the old player state of the player they were
following (along with "connection interrupted" HUD message). Unlike the
regular case of a spectator following a specific player, dedicated
camera followers did not reset their player state to the intermission
point after the followed player was no longer valid.
Now a client can be set as 'team follow1' to automatically switch
between displaying the intermission point and following a player when
possible.