mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Merge branch 'master' into win
This commit is contained in:
commit
bd52e46adf
258 changed files with 10122 additions and 4405 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -37,6 +37,7 @@ core
|
|||
/mkinstalldirs
|
||||
/quakeforge-config
|
||||
/quakeforge.lsm
|
||||
/test-driver
|
||||
/ylwrap
|
||||
|
||||
# /RPM/
|
||||
|
|
|
@ -100,7 +100,7 @@ else
|
|||
fi
|
||||
|
||||
if test -n "$errors" ; then
|
||||
echo -e $errors
|
||||
echo "$errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
|
@ -380,7 +380,8 @@ QF_DEPS(QFCC_TEST,
|
|||
)
|
||||
QF_DEPS(QFLIGHT,
|
||||
[-I$(top_srcdir)/tools/qflight/include],
|
||||
[$(top_builddir)/libs/util/libQFutil.la],
|
||||
[$(top_builddir)/libs/gamecode/libQFgamecode.la
|
||||
$(top_builddir)/libs/util/libQFutil.la],
|
||||
[$(WIN32_LIBS)],
|
||||
)
|
||||
QF_DEPS(QFLMP,
|
||||
|
|
|
@ -14,6 +14,27 @@ if test "x$CFLAGS" != "x"; then
|
|||
fi
|
||||
AC_MSG_RESULT([$leave_cflags_alone])
|
||||
|
||||
AC_MSG_CHECKING(for C99 inline)
|
||||
c99_inline=no
|
||||
AC_TRY_LINK(
|
||||
[inline int foo (int x) { return x * x; }
|
||||
int (*bar) (int) = foo;],
|
||||
[],
|
||||
c99_inline=no
|
||||
AC_MSG_RESULT(no),
|
||||
c99_inline=yes
|
||||
AC_DEFINE(HAVE_C99INLINE, extern, [define this if using c99 inline])
|
||||
AC_MSG_RESULT(yes)
|
||||
)
|
||||
AH_VERBATIM([HAVE_C99INLINE],
|
||||
[/* Define this if the GCC __attribute__ keyword is available */
|
||||
#undef HAVE_C99INLINE
|
||||
#ifdef HAVE_C99INLINE
|
||||
# define GNU89INLINE
|
||||
#else
|
||||
# define GNU89INLINE extern
|
||||
#endif])
|
||||
|
||||
if test "x$GCC" = xyes; then
|
||||
set $CC
|
||||
shift
|
||||
|
|
|
@ -7,8 +7,6 @@ AC_FUNC_MEMCMP
|
|||
AC_FUNC_MMAP
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_VPRINTF
|
||||
AC_FUNC_VA_COPY
|
||||
AC_FUNC__VA_COPY
|
||||
AC_CHECK_FUNCS(
|
||||
access _access connect dlopen execvp fcntl ftime _ftime getaddrinfo \
|
||||
gethostbyname gethostname getnameinfo getpagesize gettimeofday getuid \
|
||||
|
@ -17,6 +15,17 @@ AC_CHECK_FUNCS(
|
|||
_vsnprintf wait
|
||||
)
|
||||
|
||||
AC_FUNC_VA_COPY
|
||||
AC_FUNC__VA_COPY
|
||||
AH_VERBATIM([DEFINE_VA_COPY],
|
||||
[#ifndef HAVE_VA_COPY
|
||||
# ifdef HAVE__VA_COPY
|
||||
# define va_copy(d,s) __va_copy ((d), (s))
|
||||
# else
|
||||
# define va_copy(d,s) memcpy (&(d), &(s), sizeof (va_list))
|
||||
# endif
|
||||
#endif])
|
||||
|
||||
DL_LIBS=""
|
||||
if test "x$ac_cv_func_dlopen" != "xyes"; then
|
||||
AC_CHECK_LIB(dl, dlopen,
|
||||
|
|
|
@ -2,7 +2,7 @@ dnl Checks for SVGALib support
|
|||
AC_ARG_WITH(svga,
|
||||
[ --with-svga=DIR use SVGALib found in DIR],
|
||||
HAVE_SVGA=$withval, HAVE_SVGA=auto)
|
||||
if test "x$HAVE_SVGA" != xno; then
|
||||
if test "x$HAVE_SVGA" != xno -a "x$HAVE_SVGA" != xauto; then
|
||||
if test "x$HAVE_SVGA" != xauto; then
|
||||
SVGA_CFLAGS="$SVGA_CFLAGS -I$withval/include"
|
||||
SVGA_LIBS="$SVGA_LIBS -L$withval/lib"
|
||||
|
|
|
@ -45,7 +45,7 @@ AC_TRY_COMPILE(
|
|||
AC_MSG_RESULT(no)
|
||||
)
|
||||
AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY],
|
||||
[/* Define this if the GCC __attribute__ keyword is available */
|
||||
[/* Define this if the GCC visibility __attribute__ is available */
|
||||
#undef HAVE___ATTRIBUTE__VISIBILITY
|
||||
#ifdef HAVE___ATTRIBUTE__VISIBILITY
|
||||
# define VISIBLE __attribute__((visibility ("default")))
|
||||
|
@ -53,6 +53,26 @@ AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY],
|
|||
# define VISIBLE
|
||||
#endif])
|
||||
|
||||
if test "x$SYSTYPE" = "xWIN32"; then
|
||||
AC_MSG_CHECKING(for __attribute__ ((gcc_struct)))
|
||||
AC_TRY_COMPILE(
|
||||
[typedef struct { int foo; }
|
||||
__attribute__ ((gcc_struct)) gcc_struct_test;],
|
||||
[],
|
||||
AC_DEFINE(HAVE___ATTRIBUTE__GCC_STRUCT)
|
||||
AC_MSG_RESULT(yes),
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
fi
|
||||
AH_VERBATIM([HAVE___ATTRIBUTE__GCC_STRUCT],
|
||||
[/* Define this if the GCC gcc_struct __attribute__ is available */
|
||||
#undef HAVE___ATTRIBUTE__GCC_STRUCT
|
||||
#ifdef HAVE___ATTRIBUTE__GCC_STRUCT
|
||||
# define GCC_STRUCT __attribute__((gcc_struct))
|
||||
#else
|
||||
# define GCC_STRUCT
|
||||
#endif])
|
||||
|
||||
AC_MSG_CHECKING(for __builtin_expect)
|
||||
AC_TRY_COMPILE(
|
||||
[long (*foo) (long, long) = __builtin_expect;],
|
||||
|
@ -68,8 +88,6 @@ AH_VERBATIM([HAVE___BUILTIN_EXPECT],
|
|||
# define __builtin_expect(x,c) x
|
||||
#endif])
|
||||
|
||||
AC_TYPE_VA_LIST
|
||||
|
||||
AC_MSG_CHECKING(for type of fpos_t)
|
||||
AC_TRY_COMPILE(
|
||||
[#include <stdio.h>],
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
endian=""
|
||||
FNM_FLAGS=""
|
||||
case "$host_os" in
|
||||
mingw32*)
|
||||
mingw=yes
|
||||
CFLAGS="$CFLAGS -I\$(top_srcdir)/include/win32"
|
||||
FNM_FLAGS="-I\$(top_srcdir)/include/win32"
|
||||
if test "x$host" != "x$build"; then
|
||||
case "$build_os" in
|
||||
cygwin*)
|
||||
|
@ -24,3 +25,4 @@ case "$host_os" in
|
|||
fi
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(FNM_FLAGS)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
\li \subpage sound
|
||||
\li \subpage tracklist
|
||||
\li \subpage key_binding
|
||||
\li \subpage imt
|
||||
\li \subpage cshift_cvars
|
||||
\li \subpage server_timestamps
|
||||
*/
|
||||
|
|
211
doc/config/vkb.cfg
Normal file
211
doc/config/vkb.cfg
Normal file
|
@ -0,0 +1,211 @@
|
|||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
// This is an implementation of a virtual keyboard using the same scheme
|
||||
// as Valve's Big Picture (apparently). This implementation uses only QF's
|
||||
// IMT key binding system and joystick axis controls (to get buttons from
|
||||
// analog inputs) and the standard id parser.
|
||||
//
|
||||
// At this stage, there is no support for backspace or enter. However, that
|
||||
// requires only some modifications to in_type to support things like \h and
|
||||
// \n.
|
||||
//
|
||||
// This probably could be done more elegantly using gib, and certainly using
|
||||
// Ruamoko with just enough config to get the button presses into the VM.
|
||||
|
||||
// The dpad on my gamepad (Elecom jc-u2312fsv) is only pseudo-digital, at
|
||||
// least from Linux's point of view: -32767, 0, 32767. Axis 4 is horizontal
|
||||
// and axis 5 is vertical. This setup makes it so j_axis1 = up/north,
|
||||
// j_axis2 = right/east, j_axis3 = down/south, j_axis4 = left/west
|
||||
in_joy 4 amp 1 pre_amp 1 deadzone 0 offset 0 type button 0
|
||||
in_joy 4 button add J_AXIS2 16384
|
||||
in_joy 4 button add J_AXIS4 -16384
|
||||
in_joy 5 amp 1 pre_amp 1 deadzone 0 offset 0 type button 0
|
||||
in_joy 5 button add J_AXIS1 -16384
|
||||
in_joy 5 button add J_AXIS3 16384
|
||||
|
||||
// create the imts
|
||||
// the vkb imts form a compass rose around imt_vkb. imt_vkb0 is intended to be
|
||||
// at north, imt_vkb2 at east, imt_vkb4 at south, imt_vkb6 at west, and the odd
|
||||
// numbered vkb imts in between the even (eg, imt_vkb1 at NE, imt_vkb7 at NW).
|
||||
imt_create key_console imt_vkb imt_console
|
||||
imt_create key_console imt_vkb0 imt_vkb
|
||||
imt_create key_console imt_vkb1 imt_vkb
|
||||
imt_create key_console imt_vkb2 imt_vkb
|
||||
imt_create key_console imt_vkb3 imt_vkb
|
||||
imt_create key_console imt_vkb4 imt_vkb
|
||||
imt_create key_console imt_vkb5 imt_vkb
|
||||
imt_create key_console imt_vkb6 imt_vkb
|
||||
imt_create key_console imt_vkb7 imt_vkb
|
||||
// in case the imts already existed. clearing the tables isn't strictly
|
||||
// necessary, but it means that we're always starting from a clean slate
|
||||
imt_clear imt_vkb imt_vkb0 imt_vkb1 imt_vkb2 imt_vkb3 imt_vkb4 imt_vkb5 imt_vkb6 imt_vkb7
|
||||
// because key_console already has (or should have) imt_console, creating
|
||||
// imt_vkb won't automatically switch to it.
|
||||
imt_keydest key_console imt_vkb
|
||||
|
||||
// Due to the way the event system works, it's not possible to jump straight
|
||||
// from imt_vkb to any of the odd numbered vkb imts
|
||||
in_bind imt_vkb j_axis1 "+goto_vkb0"
|
||||
in_bind imt_vkb j_axis2 "+goto_vkb2"
|
||||
in_bind imt_vkb j_axis3 "+goto_vkb4"
|
||||
in_bind imt_vkb j_axis4 "+goto_vkb6"
|
||||
|
||||
// when j_axis1 is pressed, we are in vkb0 (N) and thus pressing j_axis2
|
||||
// while holding j_axis1 gives NE thus vkb1 and j_axis4 gives NW thus vkb7
|
||||
in_bind imt_vkb0 j_axis2 "+goto_vkb1"
|
||||
in_bind imt_vkb0 j_axis4 "+goto_vkb7"
|
||||
|
||||
// from vkb2 (E) vkb1 (NE) and vkb3 (SE) can be reached
|
||||
in_bind imt_vkb2 j_axis1 "+goto_vkb1"
|
||||
in_bind imt_vkb2 j_axis3 "+goto_vkb3"
|
||||
|
||||
// from vkb4 (S) vkb3 (SE) and vkb5 (SW) can be reached
|
||||
in_bind imt_vkb4 j_axis2 "+goto_vkb3"
|
||||
in_bind imt_vkb4 j_axis4 "+goto_vkb5"
|
||||
|
||||
// from vkb6 (W) vkb5 (SW) and vkb7 (NW) can be reached
|
||||
in_bind imt_vkb6 j_axis1 "+goto_vkb7"
|
||||
in_bind imt_vkb6 j_axis3 "+goto_vkb5"
|
||||
|
||||
// Releasing j_axis1 while in vkb1 makes only j_axis2 active thus we return
|
||||
// to vkb2. Releasing j_axis2 means only j_axis1 is active thus back to vkb0.
|
||||
// The encoding in the name for goto_vkb1_2 means "we're in vkb1 but will
|
||||
// return to vkb2"
|
||||
in_bind imt_vkb1 j_axis1 "+goto_vkb1_2"
|
||||
in_bind imt_vkb1 j_axis2 "+goto_vkb1_0"
|
||||
|
||||
// from vkb3, can return to either vkb4 or vkb2
|
||||
in_bind imt_vkb3 j_axis2 "+goto_vkb3_4"
|
||||
in_bind imt_vkb3 j_axis3 "+goto_vkb3_2"
|
||||
|
||||
// from vkb5, can return to either vkb6 or vkb4
|
||||
in_bind imt_vkb5 j_axis4 "+goto_vkb5_4"
|
||||
in_bind imt_vkb5 j_axis3 "+goto_vkb5_6"
|
||||
|
||||
// from vkb7, can return to either vkb0 or vkb6
|
||||
in_bind imt_vkb7 j_axis4 "+goto_vkb7_0"
|
||||
in_bind imt_vkb7 j_axis1 "+goto_vkb7_6"
|
||||
|
||||
// the buttons on my gamepad are arranged:
|
||||
// 2 b
|
||||
// 1 4 -> a c
|
||||
// 3 d
|
||||
in_bind imt_vkb0 j_button1 in_type a
|
||||
in_bind imt_vkb0 j_button2 in_type b
|
||||
in_bind imt_vkb0 j_button4 in_type c
|
||||
in_bind imt_vkb0 j_button3 in_type d
|
||||
|
||||
// f
|
||||
// e g
|
||||
// h
|
||||
in_bind imt_vkb1 j_button1 in_type e
|
||||
in_bind imt_vkb1 j_button2 in_type f
|
||||
in_bind imt_vkb1 j_button4 in_type g
|
||||
in_bind imt_vkb1 j_button3 in_type h
|
||||
|
||||
// j
|
||||
// i k
|
||||
// l
|
||||
in_bind imt_vkb2 j_button1 in_type i
|
||||
in_bind imt_vkb2 j_button2 in_type j
|
||||
in_bind imt_vkb2 j_button4 in_type k
|
||||
in_bind imt_vkb2 j_button3 in_type l
|
||||
|
||||
// n
|
||||
// m o
|
||||
// p
|
||||
in_bind imt_vkb3 j_button1 in_type m
|
||||
in_bind imt_vkb3 j_button2 in_type n
|
||||
in_bind imt_vkb3 j_button4 in_type o
|
||||
in_bind imt_vkb3 j_button3 in_type p
|
||||
|
||||
// r
|
||||
// q s
|
||||
// t
|
||||
in_bind imt_vkb4 j_button1 in_type q
|
||||
in_bind imt_vkb4 j_button2 in_type r
|
||||
in_bind imt_vkb4 j_button4 in_type s
|
||||
in_bind imt_vkb4 j_button3 in_type t
|
||||
|
||||
// v
|
||||
// u w
|
||||
// x
|
||||
in_bind imt_vkb5 j_button1 in_type u
|
||||
in_bind imt_vkb5 j_button2 in_type v
|
||||
in_bind imt_vkb5 j_button4 in_type w
|
||||
in_bind imt_vkb5 j_button3 in_type x
|
||||
|
||||
// z
|
||||
// y ,
|
||||
// .
|
||||
in_bind imt_vkb6 j_button1 in_type y
|
||||
in_bind imt_vkb6 j_button2 in_type z
|
||||
in_bind imt_vkb6 j_button4 in_type ,
|
||||
in_bind imt_vkb6 j_button3 in_type .
|
||||
|
||||
// /
|
||||
// : @
|
||||
// _
|
||||
in_bind imt_vkb7 j_button1 in_type :
|
||||
in_bind imt_vkb7 j_button2 in_type /
|
||||
in_bind imt_vkb7 j_button4 in_type @
|
||||
in_bind imt_vkb7 j_button3 in_type _
|
||||
|
||||
// some aliases to clear up the code (and, for now, display which vkb has
|
||||
// been entered)
|
||||
alias enter_vkb "imt_keydest key_console imt_vkb; echo vkb"
|
||||
alias enter_vkb0 "imt_keydest key_console imt_vkb0; echo vkb0"
|
||||
alias enter_vkb1 "imt_keydest key_console imt_vkb1; echo vkb1"
|
||||
alias enter_vkb2 "imt_keydest key_console imt_vkb2; echo vkb2"
|
||||
alias enter_vkb3 "imt_keydest key_console imt_vkb3; echo vkb3"
|
||||
alias enter_vkb4 "imt_keydest key_console imt_vkb4; echo vkb4"
|
||||
alias enter_vkb5 "imt_keydest key_console imt_vkb5; echo vkb5"
|
||||
alias enter_vkb6 "imt_keydest key_console imt_vkb6; echo vkb6"
|
||||
alias enter_vkb7 "imt_keydest key_console imt_vkb7; echo vkb7"
|
||||
|
||||
// The real implementation of the compass rose. the + version of
|
||||
// goto_vkbN_R is not expected to execute (as repeat is not yet supported),
|
||||
// but just in case, make them an effective no-op. Probably don't really need
|
||||
// to define them as everthing seems to work without devinitions for
|
||||
// -goto_vkbN for odd N.
|
||||
alias +goto_vkb0 enter_vkb0
|
||||
alias +goto_vkb1 enter_vkb1
|
||||
alias +goto_vkb1_0 enter_vkb1
|
||||
alias +goto_vkb1_2 enter_vkb1
|
||||
alias +goto_vkb2 enter_vkb2
|
||||
alias +goto_vkb3 enter_vkb3
|
||||
alias +goto_vkb3_2 enter_vkb3
|
||||
alias +goto_vkb3_4 enter_vkb3
|
||||
alias +goto_vkb4 enter_vkb4
|
||||
alias +goto_vkb5 enter_vkb5
|
||||
alias +goto_vkb5_4 enter_vkb5
|
||||
alias +goto_vkb5_6 enter_vkb5
|
||||
alias +goto_vkb6 enter_vkb6
|
||||
alias +goto_vkb7 enter_vkb7
|
||||
alias +goto_vkb7_4 enter_vkb7
|
||||
alias +goto_vkb7_6 enter_vkb7
|
||||
|
||||
alias -goto_vkb0 enter_vkb
|
||||
alias -goto_vkb1_0 enter_vkb0
|
||||
alias -goto_vkb1_2 enter_vkb2
|
||||
alias -goto_vkb2 enter_vkb
|
||||
alias -goto_vkb3_2 enter_vkb2
|
||||
alias -goto_vkb3_4 enter_vkb4
|
||||
alias -goto_vkb4 enter_vkb
|
||||
alias -goto_vkb5_4 enter_vkb4
|
||||
alias -goto_vkb5_6 enter_vkb6
|
||||
alias -goto_vkb6 enter_vkb
|
||||
alias -goto_vkb7_0 enter_vkb0
|
||||
alias -goto_vkb7_6 enter_vkb6
|
|
@ -276,17 +276,17 @@ img.footer {
|
|||
/* @group Code Colorization */
|
||||
|
||||
span.keyword {
|
||||
color: #262833;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.keywordtype {
|
||||
color: #262833;
|
||||
color: #bec3d9;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.keywordflow {
|
||||
color: #000000;
|
||||
color: #bec3d9;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
|
28
doc/imt.dox
Normal file
28
doc/imt.dox
Normal file
|
@ -0,0 +1,28 @@
|
|||
//unfortunately, have to wrap the docs in a C comment for doxygen
|
||||
// vim:tw=74:formatoptions-=l
|
||||
/**
|
||||
\page imt Input Mapping Table
|
||||
|
||||
The user can now create and destroy IMTs at will, though currently
|
||||
destroying IMTs is currently all or nothing (imt_drop_all).
|
||||
|
||||
An IMT is created via imt_create which takes the keydest name (key_game
|
||||
etc), the name of the IMT (must be unique for all IMTs) and optionally the
|
||||
name of the IMT to which the key binding search will fall back if there is
|
||||
no binding in the current IMT, but must be already defined and on the same
|
||||
keydest. This means that IMTs now have user determined fallback paths. The
|
||||
requirements for the fallback IMT prevent loops and other weird behaviour.
|
||||
|
||||
Actual key binding via in_bind is unaffected. This is why the IMT name must
|
||||
be unique across all IMTs.
|
||||
|
||||
The "imt" command works with the key_game keydest, but imt_keydest is
|
||||
provided for specifying the active IMT for a specific keydest.
|
||||
|
||||
At startup, default IMTs are setup to emulate the previous static IMTs so
|
||||
old configs will continue to work (mostly). New config files will be
|
||||
written with commands to drop all of the current IMTs and build new ones,
|
||||
with the bindings and active IMT set as well.
|
||||
|
||||
|
||||
*/
|
|
@ -87,5 +87,5 @@ And yes, these long strings were inspired by Python's long strings.
|
|||
for doxygen -->
|
||||
Binary data is hex-encoded and contained within angle brackets (\c \< \c
|
||||
\>). There must be an even number of hex-digits. That is, while \c \<FF00\>
|
||||
is value, \c \<F00\> is not.
|
||||
is valid, \c \<F00\> is not.
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
# Stuff that is common to both client and server
|
||||
INCLUDES= -I$(top_srcdir)/include -I$(top_srcdir)/hw/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/hw/include
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
|
||||
bin_PROGRAMS= @HW_TARGETS@
|
||||
|
|
|
@ -30,6 +30,12 @@
|
|||
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
typedef struct shader_s {
|
||||
int num_strings;
|
||||
const char **strings;
|
||||
const char **src;
|
||||
} shader_t;
|
||||
|
||||
typedef struct shaderparam_s {
|
||||
const char *name;
|
||||
qboolean uniform;
|
||||
|
@ -40,9 +46,42 @@ extern int glsl_palette;
|
|||
extern int glsl_colormap;
|
||||
|
||||
void GLSL_Init_Common (void);
|
||||
int GLSL_CompileShader (const char *name, const char *shader_src, int type);
|
||||
|
||||
int GLSL_CompileShader (const char *name, const shader_t *shader, int type);
|
||||
int GLSL_LinkProgram (const char *name, int vert, int frag);
|
||||
int GLSL_ResolveShaderParam (int program, shaderparam_t *param);
|
||||
void GLSL_DumpAttribArrays (void);
|
||||
|
||||
/* Register a shader effect "file".
|
||||
|
||||
This is based on The OpenGL Shader Wrangler by the little grasshopper
|
||||
(http://prideout.net/blog/?p=11).
|
||||
|
||||
\param name The name of the effect in the effect key.
|
||||
\param src The string holding the effect file.
|
||||
\return 0 for failure, 1 for success.
|
||||
*/
|
||||
int GLSL_RegisterEffect (const char *name, const char *src);
|
||||
|
||||
/* Build a shader program script from a list of effect keys.
|
||||
|
||||
This is based on The OpenGL Shader Wrangler by the little grasshopper
|
||||
(http://prideout.net/blog/?p=11).
|
||||
|
||||
The returned shader program script is suitable for passing directly to
|
||||
GLSL_CompileShader.
|
||||
|
||||
\param effect_keys Null terminated list of effect keys. The shader will be
|
||||
built from the specified segments in the given order.
|
||||
\return A pointer to the built up shader program script, or null on
|
||||
failure.
|
||||
*/
|
||||
shader_t *GLSL_BuildShader (const char **effect_keys);
|
||||
|
||||
/* Free a shader program script built by GLSL_BuildShader.
|
||||
|
||||
\param shader The shader program script to be freed.
|
||||
*/
|
||||
void GLSL_FreeShader (shader_t *shader);
|
||||
|
||||
#endif // __QF_GLSL_vid_h
|
||||
|
|
|
@ -7,8 +7,8 @@ nobase_pkginclude_HEADERS = \
|
|||
link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \
|
||||
msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \
|
||||
pr_obj.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h quakefs.h \
|
||||
quakeio.h render.h riff.h ruamoko.h set.h screen.h script.h sizebuf.h \
|
||||
skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.h \
|
||||
quakeio.h render.h riff.h ruamoko.h screen.h script.h segtext.h set.h \
|
||||
sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.h \
|
||||
ver_check.h vid.h vrect.h view.h wad.h wadfile.h winding.h zone.h \
|
||||
\
|
||||
GL/ati.h GL/defines.h GL/extensions.h GL/funcs.h GL/qf_draw.h \
|
||||
|
|
|
@ -42,51 +42,52 @@
|
|||
#ifndef DEBUG_QF_MEMORY
|
||||
/** High-tide structure allocator for use in linked lists.
|
||||
|
||||
Using a free-list with the name of \c free_NAME, return a single element.
|
||||
Using a free-list with the name of \c NAME_freelist, return a single
|
||||
element.
|
||||
The type of the element must be a structure with a field named \c next.
|
||||
When the free-list is empty, memory is claimed from the system in blocks.
|
||||
elements may be returned to the pool by linking them into the free-list.
|
||||
Elements may be returned to the pool by linking them into the free-list.
|
||||
|
||||
\param s The number of structures in the block.
|
||||
\param t The structure type.
|
||||
\param n The \c NAME portion of the \c free_NAME free-list.
|
||||
\param n The \c NAME portion of the \c NAME_freelist free-list.
|
||||
\param v The destination of the pointer to the allocated
|
||||
element. The contents of the allocated element will be
|
||||
memset to 0.
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define ALLOC(s, t, n, v) \
|
||||
do { \
|
||||
if (!free_##n) { \
|
||||
int i; \
|
||||
free_##n = malloc ((s) * sizeof (t)); \
|
||||
for (i = 0; i < (s) - 1; i++) \
|
||||
free_##n[i].next = &free_##n[i + 1];\
|
||||
free_##n[i].next = 0; \
|
||||
} \
|
||||
v = free_##n; \
|
||||
free_##n = free_##n->next; \
|
||||
memset (v, 0, sizeof (*v)); \
|
||||
#define ALLOC(s, t, n, v) \
|
||||
do { \
|
||||
if (!n##_freelist) { \
|
||||
int i; \
|
||||
n##_freelist = malloc ((s) * sizeof (t)); \
|
||||
for (i = 0; i < (s) - 1; i++) \
|
||||
n##_freelist[i].next = &n##_freelist[i + 1];\
|
||||
n##_freelist[i].next = 0; \
|
||||
} \
|
||||
v = n##_freelist; \
|
||||
n##_freelist = n##_freelist->next; \
|
||||
memset (v, 0, sizeof (*v)); \
|
||||
} while (0)
|
||||
|
||||
/** Free a block allocated by #ALLOC
|
||||
|
||||
\param n The \c NAME portion of the \c free_NAME free-list.
|
||||
\param n The \c NAME portion of the \c NAME_freelist free-list.
|
||||
\param p The pointer to the block to be freed.
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#define FREE(n, p) \
|
||||
do { \
|
||||
p->next = free_##n; \
|
||||
free_##n = p->next; \
|
||||
#define FREE(n, p) \
|
||||
do { \
|
||||
p->next = n##_freelist; \
|
||||
n##_freelist = p; \
|
||||
} while (0)
|
||||
#else
|
||||
#define ALLOC(s, t, n, v) \
|
||||
do { \
|
||||
__attribute__((unused)) t **dummy = &free_##n; \
|
||||
v = (t *) calloc (1, sizeof (t)); \
|
||||
#define ALLOC(s, t, n, v) \
|
||||
do { \
|
||||
__attribute__((unused)) t **dummy = &n##_freelist; \
|
||||
v = (t *) calloc (1, sizeof (t)); \
|
||||
} while (0)
|
||||
|
||||
#define FREE(n, p) do { free (p); } while (0)
|
||||
|
|
|
@ -146,4 +146,9 @@ int Menu_KeyEvent (knum_t key, short unicode, qboolean down);
|
|||
void Menu_Enter (void);
|
||||
void Menu_Leave (void);
|
||||
|
||||
void Menu_Enter_f (void);
|
||||
void Menu_Leave_f (void);
|
||||
void Menu_Prev_f (void);
|
||||
void Menu_Next_f (void);
|
||||
|
||||
#endif // __console_h
|
||||
|
|
|
@ -29,24 +29,55 @@
|
|||
#define __QF_joystick_h_
|
||||
|
||||
#include <QF/qtypes.h>
|
||||
#include "QF/quakeio.h"
|
||||
|
||||
#define JOY_MAX_AXES 8
|
||||
#define JOY_MAX_BUTTONS 18
|
||||
#define JOY_MAX_AXES 32
|
||||
#define JOY_MAX_BUTTONS 64
|
||||
|
||||
extern struct cvar_s *joy_device; // Joystick device name
|
||||
extern struct cvar_s *joy_enable; // Joystick enabling flag
|
||||
|
||||
extern qboolean joy_found; // Joystick present?
|
||||
extern qboolean joy_active; // Joystick in use?
|
||||
|
||||
struct joy_axis {
|
||||
struct cvar_s *axis;
|
||||
int current;
|
||||
struct joy_axis_button {
|
||||
float threshold;
|
||||
int key;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
js_none, // ignore axis
|
||||
js_position, // linear delta
|
||||
js_angles, // linear delta
|
||||
js_button, // axis button
|
||||
} js_dest_t;
|
||||
|
||||
typedef enum {
|
||||
js_clear,
|
||||
js_amp,
|
||||
js_pre_amp,
|
||||
js_deadzone,
|
||||
js_offset,
|
||||
js_type,
|
||||
js_axis_button,
|
||||
} js_opt_t;
|
||||
|
||||
struct joy_axis {
|
||||
int current;
|
||||
float amp;
|
||||
float pre_amp;
|
||||
int deadzone;
|
||||
float offset;
|
||||
js_dest_t dest;
|
||||
int axis; // if linear delta
|
||||
int num_buttons; // if axis button
|
||||
struct joy_axis_button *axis_buttons; // if axis button
|
||||
};
|
||||
|
||||
extern qboolean joy_found; // Joystick present?
|
||||
extern qboolean joy_active; // Joystick in use?
|
||||
|
||||
struct joy_button {
|
||||
int old;
|
||||
int current;
|
||||
int old;
|
||||
int current;
|
||||
};
|
||||
|
||||
extern struct joy_axis joy_axes[JOY_MAX_AXES];
|
||||
|
@ -64,6 +95,7 @@ extern struct joy_button joy_buttons[JOY_MAX_BUTTONS];
|
|||
joy_enable->int_val are zero.
|
||||
*/
|
||||
void JOY_Command (void);
|
||||
void joy_clear_axis (int i);
|
||||
|
||||
/*
|
||||
JOY_Move (usercmd_t *) // FIXME: Not anymore!
|
||||
|
@ -111,4 +143,15 @@ void JOY_Close (void);
|
|||
*/
|
||||
void JOY_Read (void);
|
||||
|
||||
|
||||
const char *JOY_GetOption_c (int i);
|
||||
int JOY_GetOption_i (const char *c);
|
||||
|
||||
const char *JOY_GetDest_c (int i);
|
||||
int JOY_GetDest_i (const char *c);
|
||||
int JOY_GetAxis_i (int dest, const char *c);
|
||||
|
||||
|
||||
void Joy_WriteBindings (QFile *f);
|
||||
|
||||
#endif // __QF_joystick_h_
|
||||
|
|
|
@ -34,8 +34,14 @@
|
|||
# include "QF/quakeio.h"
|
||||
#endif
|
||||
|
||||
// these are the key numbers that should be passed to Key_Event
|
||||
/** \defgroup input Input Sub-system */
|
||||
|
||||
/** \defgroup input_keybinding Key Binding Sub-system
|
||||
\ingroup input
|
||||
*/
|
||||
//@{
|
||||
|
||||
/// these are the key numbers that should be passed to Key_Event
|
||||
typedef enum {
|
||||
/* The keyboard syms have been cleverly chosen to map to ASCII */
|
||||
QFK_UNKNOWN = 0,
|
||||
|
@ -409,19 +415,87 @@ typedef enum {
|
|||
QFJ_BUTTON30,
|
||||
QFJ_BUTTON31,
|
||||
QFJ_BUTTON32,
|
||||
QFJ_BUTTON33,
|
||||
QFJ_BUTTON34,
|
||||
QFJ_BUTTON35,
|
||||
QFJ_BUTTON36,
|
||||
QFJ_BUTTON37,
|
||||
QFJ_BUTTON38,
|
||||
QFJ_BUTTON39,
|
||||
QFJ_BUTTON40,
|
||||
QFJ_BUTTON41,
|
||||
QFJ_BUTTON42,
|
||||
QFJ_BUTTON43,
|
||||
QFJ_BUTTON44,
|
||||
QFJ_BUTTON45,
|
||||
QFJ_BUTTON46,
|
||||
QFJ_BUTTON47,
|
||||
QFJ_BUTTON48,
|
||||
QFJ_BUTTON49,
|
||||
QFJ_BUTTON50,
|
||||
QFJ_BUTTON51,
|
||||
QFJ_BUTTON52,
|
||||
QFJ_BUTTON53,
|
||||
QFJ_BUTTON54,
|
||||
QFJ_BUTTON55,
|
||||
QFJ_BUTTON56,
|
||||
QFJ_BUTTON57,
|
||||
QFJ_BUTTON58,
|
||||
QFJ_BUTTON59,
|
||||
QFJ_BUTTON60,
|
||||
QFJ_BUTTON61,
|
||||
QFJ_BUTTON62,
|
||||
QFJ_BUTTON63,
|
||||
QFJ_BUTTON64,
|
||||
|
||||
//
|
||||
// joystick axes (for button emulation without consuming buttons)
|
||||
//
|
||||
QFJ_AXIS1,
|
||||
QFJ_AXIS2,
|
||||
QFJ_AXIS3,
|
||||
QFJ_AXIS4,
|
||||
QFJ_AXIS5,
|
||||
QFJ_AXIS6,
|
||||
QFJ_AXIS7,
|
||||
QFJ_AXIS8,
|
||||
QFJ_AXIS9,
|
||||
QFJ_AXIS10,
|
||||
QFJ_AXIS11,
|
||||
QFJ_AXIS12,
|
||||
QFJ_AXIS13,
|
||||
QFJ_AXIS14,
|
||||
QFJ_AXIS15,
|
||||
QFJ_AXIS16,
|
||||
QFJ_AXIS17,
|
||||
QFJ_AXIS18,
|
||||
QFJ_AXIS19,
|
||||
QFJ_AXIS20,
|
||||
QFJ_AXIS21,
|
||||
QFJ_AXIS22,
|
||||
QFJ_AXIS23,
|
||||
QFJ_AXIS24,
|
||||
QFJ_AXIS25,
|
||||
QFJ_AXIS26,
|
||||
QFJ_AXIS27,
|
||||
QFJ_AXIS28,
|
||||
QFJ_AXIS29,
|
||||
QFJ_AXIS30,
|
||||
QFJ_AXIS31,
|
||||
QFJ_AXIS32,
|
||||
|
||||
QFK_LAST
|
||||
} knum_t;
|
||||
|
||||
typedef enum {
|
||||
key_unfocused, // engine has lost input focus
|
||||
key_game,
|
||||
key_demo,
|
||||
key_console,
|
||||
key_message,
|
||||
key_menu,
|
||||
key_unfocused, ///< engine has lost input focus
|
||||
key_game, ///< Normal in-game key bindings
|
||||
key_demo, ///< Demo playback key bindings
|
||||
key_console, ///< Command console key bindings
|
||||
key_message, ///< Message input line key bindings
|
||||
key_menu, ///< Menu key bindings.
|
||||
|
||||
key_last // enum size
|
||||
key_last ///< enum size
|
||||
} keydest_t;
|
||||
|
||||
#ifndef __QFCC__
|
||||
|
@ -447,34 +521,144 @@ typedef struct imt_s {
|
|||
int written; ///< avoid duplicate config file writes
|
||||
} imt_t;
|
||||
|
||||
/** Chain of input mapping tables ascociated with a keydest sub-system (game,
|
||||
menu, etc).
|
||||
*/
|
||||
typedef struct keytarget_s {
|
||||
imt_t *imts;
|
||||
imt_t *active;
|
||||
imt_t *imts; ///< list of tables attached to this target
|
||||
imt_t *active; ///< currently active table in this target
|
||||
} keytarget_t;
|
||||
|
||||
extern int keydown[QFK_LAST];
|
||||
|
||||
struct cbuf_s;
|
||||
|
||||
void Key_Init (struct cbuf_s *cb);
|
||||
void Key_Init_Cvars (void);
|
||||
|
||||
/** Find an Input Mapping Table by name.
|
||||
|
||||
Searches through all keydest targets for the named imt. The search is case
|
||||
insensitive.
|
||||
|
||||
\param imt_name The name of the imt to find. Case insensitive.
|
||||
\return The named imt, or null if not found.
|
||||
*/
|
||||
imt_t *Key_FindIMT (const char *imt_name);
|
||||
|
||||
/** Create a new imt and attach it to the specified keydest target.
|
||||
|
||||
The name of the new imt must be unique (case insensitive) across all
|
||||
keydest targets. This is to simplify the in_bind command.
|
||||
|
||||
If \a chain_imt_name is not null, then it species the fallback imt for when
|
||||
the key is not bound in the new imt. It must be an already existing imt in
|
||||
the specified keydest target. This is to prevent loops and other weird
|
||||
behavior.
|
||||
|
||||
\param kd The keydest target to which the new imt will be attached.
|
||||
\param imt_name The name for the new imt. Must be unique (case
|
||||
insensitive).
|
||||
\param chain_imt_name The name of the fallback imt if not null. Must
|
||||
already exist on the specified keydest target.
|
||||
*/
|
||||
void Key_CreateIMT (keydest_t kd, const char *imt_name,
|
||||
const char *chain_imt_name);
|
||||
|
||||
struct cbuf_s;
|
||||
/** Handle a key press/release event.
|
||||
|
||||
\param key The key that was pressed or released for this event.
|
||||
\param unicode The unicode value of the key.
|
||||
\param down True if a press event, false if a release event.
|
||||
*/
|
||||
void Key_Event (knum_t key, short unicode, qboolean down);
|
||||
|
||||
/** Handle loss or gain of input focus (usually in windowed enviroments).
|
||||
|
||||
Sets the keydest target to key_unfocuses when input focus is lost.
|
||||
|
||||
Triggers keydest callbacks.
|
||||
|
||||
\bug Always sets the target to key_game when focus is gained.
|
||||
|
||||
\param gain True if focus is gained, false if focus is lost.
|
||||
*/
|
||||
void Key_FocusEvent (int gain);
|
||||
void Key_Init (struct cbuf_s *cb);
|
||||
void Key_Init_Cvars (void);
|
||||
|
||||
void Key_WriteBindings (QFile *f);
|
||||
|
||||
/** Force all key states to unpressed.
|
||||
|
||||
Sends a key release event for any keys that are seen as down.
|
||||
*/
|
||||
void Key_ClearStates (void);
|
||||
const char *Key_GetBinding (const char *imt_name, knum_t key);
|
||||
|
||||
/** Return a key binding in the specified input mapping table.
|
||||
|
||||
\param imt The input mapping table from which to get the binding.
|
||||
\param key The key for which to get the binding.
|
||||
\return The command string bound to the key, or null if unbound.
|
||||
*/
|
||||
const char *Key_GetBinding (imt_t *imt, knum_t key);
|
||||
|
||||
/** Bind a command string to a key in the specified input mapping table.
|
||||
|
||||
Only one command string can be bound to a key, but the command string may
|
||||
contain multiple commands.
|
||||
|
||||
\param imt The input mapping table in which the key will be bound.
|
||||
\param keynum The key to which the command string will be bound.
|
||||
\param binding The command string that will be bound.
|
||||
*/
|
||||
void Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding);
|
||||
|
||||
/** Set the current keydest target.
|
||||
|
||||
Triggers keydest callbacks.
|
||||
|
||||
\param kd The keydest target to make current.
|
||||
*/
|
||||
void Key_SetKeyDest(keydest_t kd);
|
||||
typedef void keydest_callback_t (keydest_t);
|
||||
|
||||
/** keydest callback signature.
|
||||
|
||||
\param kd The new current keydest target.
|
||||
*/
|
||||
typedef void keydest_callback_t (keydest_t kd);
|
||||
|
||||
/** Add a callback for when the keydest target changes.
|
||||
|
||||
\param callback The callback to be added.
|
||||
*/
|
||||
void Key_KeydestCallback (keydest_callback_t *callback);
|
||||
|
||||
/** Get the string representation of a key.
|
||||
|
||||
Returns a string (a QFK_* name) for the given keynum.
|
||||
|
||||
\param keynum The key for which to get the string.
|
||||
\return The string representation of the key.
|
||||
*/
|
||||
const char *Key_KeynumToString (knum_t keynum);
|
||||
|
||||
/** Get the keynum for the named key.
|
||||
|
||||
Returns a key number to be used to index keybindings[] by looking at
|
||||
the given string. Single ascii characters return themselves, while
|
||||
the QFK_* names are matched up.
|
||||
|
||||
\param str The name of the key.
|
||||
\return The named key if valid, otherwise -1
|
||||
*/
|
||||
int Key_StringToKeynum (const char *str);
|
||||
|
||||
struct progs_s;
|
||||
|
||||
/** Add the Key builtins to the specified progs instance.
|
||||
*/
|
||||
void Key_Progs_Init (struct progs_s *pr);
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
||||
#endif // _KEYS_H
|
||||
|
|
|
@ -183,10 +183,10 @@ void _VectorSubtract (const vec3_t veca, const vec3_t vecb, vec3_t out);
|
|||
void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross);
|
||||
vec_t _VectorNormalize (vec3_t v); // returns vector length
|
||||
|
||||
extern inline float VectorNormalize (vec3_t v); // returns vector length
|
||||
GNU89INLINE inline float VectorNormalize (vec3_t v); // returns vector length
|
||||
|
||||
#ifndef IMPLEMENT_VectorNormalize
|
||||
extern inline
|
||||
GNU89INLINE inline
|
||||
#else
|
||||
VISIBLE
|
||||
#endif
|
||||
|
|
|
@ -174,11 +174,11 @@ void RotatePointAroundVector (vec3_t dst, const vec3_t axis,
|
|||
} while (0)
|
||||
|
||||
extern plane_t * const frustum;
|
||||
extern inline qboolean R_CullBox (const vec3_t mins, const vec3_t maxs);
|
||||
extern inline qboolean R_CullSphere (const vec3_t origin, const float radius);
|
||||
GNU89INLINE inline qboolean R_CullBox (const vec3_t mins, const vec3_t maxs);
|
||||
GNU89INLINE inline qboolean R_CullSphere (const vec3_t origin, const float radius);
|
||||
|
||||
#ifndef IMPLEMENT_R_Cull
|
||||
extern inline
|
||||
GNU89INLINE inline
|
||||
#else
|
||||
VISIBLE
|
||||
#endif
|
||||
|
@ -194,7 +194,7 @@ R_CullBox (const vec3_t mins, const vec3_t maxs)
|
|||
}
|
||||
|
||||
#ifndef IMPLEMENT_R_Cull
|
||||
extern inline
|
||||
GNU89INLINE inline
|
||||
#else
|
||||
VISIBLE
|
||||
#endif
|
||||
|
@ -213,6 +213,11 @@ R_CullSphere (const vec3_t origin, const float radius)
|
|||
return false;
|
||||
}
|
||||
|
||||
sphere_t SmallestEnclosingBall (const vec3_t points[], int num_points);
|
||||
int CircumSphere (const vec3_t points[], int num_points, sphere_t *sphere);
|
||||
void BarycentricCoords (const vec_t **points, int num_points, const vec3_t p,
|
||||
vec_t *lambda);
|
||||
|
||||
//@}
|
||||
|
||||
#endif // __mathlib_h
|
||||
|
|
|
@ -350,6 +350,7 @@ typedef enum {mod_brush, mod_sprite, mod_alias, mod_iqm} modtype_t;
|
|||
|
||||
typedef struct model_s {
|
||||
char name[MAX_QPATH];
|
||||
const struct vpath_s *vpath;// virtual path where this model was found
|
||||
qboolean needload; // bmodels and sprites don't cache normally
|
||||
aliashdr_t *aliashdr; // if not null, alias model is not cached
|
||||
qboolean hasfullbrights;
|
||||
|
|
|
@ -314,7 +314,7 @@ void PR_Opcode_Init (void);
|
|||
typedef struct dstatement_s {
|
||||
pr_opcode_e op:16;
|
||||
pr_ushort_t a,b,c;
|
||||
} __attribute__((gcc_struct)) dstatement_t;
|
||||
} GCC_STRUCT dstatement_t;
|
||||
|
||||
typedef struct ddef_s {
|
||||
pr_ushort_t type; // if DEF_SAVEGLOBGAL bit is set
|
||||
|
|
|
@ -247,7 +247,7 @@ struct plitem_s *ED_EntityDict (progs_t *pr, edict_t *ed);
|
|||
struct plitem_s *ED_GlobalsDict (progs_t *pr);
|
||||
void ED_InitGlobals (progs_t *pr, struct plitem_s *globals);
|
||||
void ED_InitEntity (progs_t *pr, struct plitem_s *entity, edict_t *ent);
|
||||
struct plitem_s *ED_ConvertToPlist (progs_t *pr, struct script_s *script);
|
||||
struct plitem_s *ED_ConvertToPlist (struct script_s *script, int nohack);
|
||||
struct plitem_s *ED_Parse (progs_t *pr, const char *data);
|
||||
void ED_LoadFromFile (progs_t *pr, const char *data);
|
||||
void ED_EntityParseFunction (progs_t *pr);
|
||||
|
|
|
@ -110,4 +110,9 @@ typedef struct plane_s {
|
|||
byte pad[2];
|
||||
} plane_t;
|
||||
|
||||
typedef struct sphere_s {
|
||||
vec3_t center;
|
||||
vec_t radius;
|
||||
} sphere_t;
|
||||
|
||||
#endif // __qtypes_h
|
||||
|
|
|
@ -67,6 +67,17 @@ typedef struct gamedir_s {
|
|||
} dir;
|
||||
} gamedir_t;
|
||||
|
||||
typedef struct vpath_s vpath_t;
|
||||
|
||||
typedef struct findfile_s {
|
||||
const vpath_t *vpath; ///< vpath in which file was found
|
||||
qboolean in_pak; ///< if true, path refers to a pak file rather
|
||||
///< than a directory
|
||||
const char *realname; ///< the name of the file as found (may have
|
||||
///< .gz appended, or .ogg substituded for
|
||||
///< .wav) does not include the path
|
||||
} findfile_t;
|
||||
|
||||
/** Cached information about the current game directory. \see \ref dirconf.
|
||||
*/
|
||||
extern gamedir_t *qfs_gamedir;
|
||||
|
@ -77,20 +88,20 @@ extern gamedir_t *qfs_gamedir;
|
|||
typedef void gamedir_callback_t (int phase);
|
||||
|
||||
/** Base of the QFS user directory tree. The QFS functions, except for
|
||||
QFS_FOpenFIle() and _QFS_FOpenFile(), will never access a file outside of
|
||||
QFS_FOpenFile() and _QFS_FOpenFile(), will never access a file outside of
|
||||
this tree. Set via the \c fs_userpath directory.
|
||||
*/
|
||||
extern const char *qfs_userpath;
|
||||
|
||||
/** Indicates the found file came from a pak file.
|
||||
/** Gives information about the last file opened by the FOpenFile functions.
|
||||
|
||||
Set by QFS_FOpenFIle() and _QFS_FOpenFile().
|
||||
Set by QFS_FOpenFile() and _QFS_FOpenFile().
|
||||
*/
|
||||
extern int file_from_pak;
|
||||
extern findfile_t qfs_foundfile;
|
||||
|
||||
/** The size of the file found via QFS_FOpenFIle() or _QFS_FOpenFile().
|
||||
/** The size of the file found via QFS_FOpenFile() or _QFS_FOpenFile().
|
||||
|
||||
Set by QFS_FOpenFIle() and _QFS_FOpenFile().
|
||||
Set by QFS_FOpenFile() and _QFS_FOpenFile().
|
||||
*/
|
||||
extern int qfs_filesize;
|
||||
|
||||
|
@ -121,6 +132,34 @@ void QFS_Init (const char *game);
|
|||
*/
|
||||
void QFS_Gamedir (const char *gamedir);
|
||||
|
||||
/** Search for a file in the quake file-system.
|
||||
|
||||
The search will begin in the \a start vpath and end in the \a end vpath.
|
||||
If \a start is null, the search will begin in the vpath specified by
|
||||
qfs_vpaths (ie, the first directory in the \c Path attribute
|
||||
(\ref dirconf)). If \a end is null, the search will continue to the end
|
||||
of the list of vpaths. If \a start and \a end are the same (and non-null),
|
||||
then only the one vpath will be searched.
|
||||
|
||||
\note All search paths in a vpath will be searched. This keeps \QF's
|
||||
directory system transparent.
|
||||
|
||||
\note It is a fatal error for \a end to be non-null but not in the list
|
||||
of vpaths.
|
||||
|
||||
\warning The returned pointer is to a static instance of findfile_t and
|
||||
thus will be overwritten on the next call to any of the search
|
||||
functions (QFS_FindFile, QFS_FOpenFile, _QFS_FOpenFile)
|
||||
|
||||
\param fname The name of the file to be searched for.
|
||||
\param start The first vpath (gamedir) to search.
|
||||
\param end The last vpath (gamedir) to search.
|
||||
\return Pointer to the findfile_t record indicating the location
|
||||
of the file, or null if the file was not found.
|
||||
*/
|
||||
findfile_t *QFS_FindFile (const char *fname, const vpath_t *start,
|
||||
const vpath_t *end);
|
||||
|
||||
/** Open a file from within the user directory.
|
||||
|
||||
If \a path attempts to leave the user directory, this function sets
|
||||
|
@ -163,6 +202,11 @@ QFile *QFS_WOpen (const char *path, int zip);
|
|||
*/
|
||||
void QFS_WriteFile (const char *filename, const void *data, int len);
|
||||
|
||||
QFile *_QFS_VOpenFile (const char *filename, int zip,
|
||||
const vpath_t *start, const vpath_t *end);
|
||||
QFile *QFS_VOpenFile (const char *filename,
|
||||
const vpath_t *start, const vpath_t *end);
|
||||
|
||||
/** Open a file for reading.
|
||||
|
||||
The file will be searched for through all the subdirectories given in the
|
||||
|
@ -177,19 +221,12 @@ void QFS_WriteFile (const char *filename, const void *data, int len);
|
|||
substitution.
|
||||
|
||||
\param filename The name of the file to open.
|
||||
\param gzfile Address of file handle pointer.
|
||||
\param foundname If not NULL, will be set to the real name of the file.
|
||||
\param zip If true and the file has been compressed with gzip, the
|
||||
file will be opened such that it decompresses on the fly.
|
||||
Otherwise, the file will be read as-is.
|
||||
\return The amount of bytes that can be read from the file handle.
|
||||
This will be either the files true size if \a zip is true,
|
||||
or the compressed size of \a zip is false. If an error
|
||||
occurs while opening the file, this will be -1 and
|
||||
\a *gzfile will be set to NULL.
|
||||
\return The file handle or NULL if there is an error.
|
||||
*/
|
||||
int _QFS_FOpenFile (const char *filename, QFile **gzfile,
|
||||
struct dstring_s *foundname, int zip);
|
||||
QFile *_QFS_FOpenFile (const char *filename, int zip);
|
||||
|
||||
/** Open a file for reading.
|
||||
|
||||
|
@ -198,39 +235,28 @@ int _QFS_FOpenFile (const char *filename, QFile **gzfile,
|
|||
_QFS_FOpenFile() for more details.
|
||||
|
||||
\param filename The name of the file to open.
|
||||
\param gzfile Address of file handle pointer.
|
||||
\return The amount of bytes that can be read from the file handle.
|
||||
If an error occurs while opening the file, this will be
|
||||
-1 and \a *gzfile will be set to NULL.
|
||||
\return The file handle pointer, or NULL if there is an error.
|
||||
*/
|
||||
int QFS_FOpenFile (const char *filename, QFile **gzfile);
|
||||
QFile *QFS_FOpenFile (const char *filename);
|
||||
|
||||
/** Load a file into memory.
|
||||
|
||||
This is a convenience wrapper for QFS_FOpenFile(). The file will be loaded
|
||||
in memory allocated from the location inicated by usehunk.
|
||||
The file will be loaded into memory allocated from the location indicated
|
||||
by \a usehunk.
|
||||
|
||||
\param path The name of the file to load.
|
||||
\param file The handle of the file to load.
|
||||
\param usehunk The location from which to allocate memory for the file's
|
||||
data. Use 0.
|
||||
\return Pointer to the file's data, or NULL on error.
|
||||
\todo remove \a usehunk
|
||||
*/
|
||||
byte *QFS_LoadFile (const char *path, int usehunk);
|
||||
|
||||
/** Load a file into memeory.
|
||||
|
||||
This is a wrapper for QFS_LoadFile().
|
||||
|
||||
\deprecated This should go away soon.
|
||||
*/
|
||||
byte *QFS_LoadStackFile (const char *path, void *buffer, int bufsize);
|
||||
byte *QFS_LoadFile (QFile *file, int usehunk);
|
||||
|
||||
/** Load a file into memeory.
|
||||
|
||||
The file is loaded into memory allocated from the hunk.
|
||||
*/
|
||||
byte *QFS_LoadHunkFile (const char *path);
|
||||
byte *QFS_LoadHunkFile (QFile *file);
|
||||
|
||||
/** Load a file into memeory.
|
||||
|
||||
|
@ -238,7 +264,7 @@ byte *QFS_LoadHunkFile (const char *path);
|
|||
|
||||
\deprecated This should go away soon.
|
||||
*/
|
||||
void QFS_LoadCacheFile (const char *path, struct cache_user_s *cu);
|
||||
void QFS_LoadCacheFile (QFile *file, struct cache_user_s *cu);
|
||||
|
||||
/** Rename a file.
|
||||
|
||||
|
|
58
include/QF/segtext.h
Normal file
58
include/QF/segtext.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
segtext.h
|
||||
|
||||
Segmented text file handling
|
||||
|
||||
Copyright (C) 2013 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2013/02/26
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __QF_segtext_h
|
||||
#define __QF_segtext_h
|
||||
|
||||
/** \defgroup segtext Segmented text files.
|
||||
\ingroup utils
|
||||
|
||||
Based on The OpenGL Shader Wrangler: http://prideout.net/blog/?p=11
|
||||
*/
|
||||
|
||||
typedef struct segchunk_s {
|
||||
struct segchunk_s *next;
|
||||
const char *tag;
|
||||
const char *text;
|
||||
int start_line;
|
||||
} segchunk_t;
|
||||
|
||||
typedef struct segtext_s {
|
||||
struct segtext_s *next;
|
||||
segchunk_t *chunk_list;
|
||||
struct hashtab_s *tab;
|
||||
} segtext_t;
|
||||
|
||||
segtext_t *Segtext_new (const char *src);
|
||||
void Segtext_delete (segtext_t *st);
|
||||
const segchunk_t *Segtext_FindChunk (const segtext_t *st, const char *tag);
|
||||
const char *Segtext_Find (const segtext_t *st, const char *tag);
|
||||
|
||||
#endif//__QF_segtext_h
|
|
@ -31,15 +31,32 @@
|
|||
#ifndef __QF_set_h
|
||||
#define __QF_set_h
|
||||
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
/** \defgroup set Set handling
|
||||
\ingroup utils
|
||||
*/
|
||||
//@{
|
||||
|
||||
#define DEFMAP_SIZE ((32 - sizeof (struct set_s *) \
|
||||
- sizeof (unsigned *) \
|
||||
- sizeof (int) - sizeof (unsigned))\
|
||||
/ sizeof (unsigned))
|
||||
//FIXME other archs
|
||||
#ifdef __x86_64__
|
||||
typedef uint64_t set_bits_t;
|
||||
#else
|
||||
typedef uint32_t set_bits_t;
|
||||
#endif
|
||||
|
||||
#define SET_DEFMAP_SIZE ((32 - sizeof (struct set_s *) \
|
||||
- sizeof (set_bits_t *) \
|
||||
- sizeof (int) - sizeof (unsigned))\
|
||||
/ sizeof (set_bits_t))
|
||||
#define SET_BITS (sizeof (set_bits_t) * 8)
|
||||
//NOTE: x is the element number, so size is x + 1
|
||||
#define SET_SIZE(x) (((x) + SET_BITS) & ~(SET_BITS - 1))
|
||||
#define SET_WORDS(s) ((s)->size / SET_BITS)
|
||||
#define SET_ZERO ((set_bits_t) 0)
|
||||
#define SET_ONE ((set_bits_t) 1)
|
||||
#define SET_TEST_MEMBER(s, x) \
|
||||
((s)->map[(x) / SET_BITS] & (SET_ONE << ((x) % SET_BITS)))
|
||||
|
||||
/** Represent a set using a bitmap.
|
||||
|
||||
|
@ -50,10 +67,10 @@
|
|||
*/
|
||||
typedef struct set_s {
|
||||
struct set_s *next; ///< private. for ALLOC
|
||||
unsigned *map; ///< bitmap of set members
|
||||
set_bits_t *map; ///< bitmap of set members
|
||||
int inverted; ///< if true, 0 indicates membership
|
||||
unsigned size; ///< number of representable members
|
||||
unsigned defmap[DEFMAP_SIZE];///< backing store for small sets
|
||||
set_bits_t defmap[SET_DEFMAP_SIZE];///< backing store for small sets
|
||||
} set_t;
|
||||
|
||||
/** Represent the state of a scan through a set.
|
||||
|
@ -79,11 +96,19 @@ typedef struct set_iter_s {
|
|||
unsigned element;
|
||||
} set_iter_t;
|
||||
|
||||
typedef struct set_pool_s {
|
||||
set_t *set_freelist;
|
||||
set_iter_t *set_iter_freelist;
|
||||
} set_pool_t;
|
||||
|
||||
void set_pool_init (set_pool_t *set_pool);
|
||||
|
||||
/** Delete a set iterator that is no longer needed.
|
||||
|
||||
\param set_iter The set iterator to be deleted.
|
||||
*/
|
||||
void set_del_iter (set_iter_t *set_iter);
|
||||
void set_del_iter_r (set_pool_t *set_pool, set_iter_t *set_iter);
|
||||
|
||||
/** Create a new set.
|
||||
|
||||
|
@ -92,12 +117,28 @@ void set_del_iter (set_iter_t *set_iter);
|
|||
\return The newly created, empty set.
|
||||
*/
|
||||
set_t *set_new (void);
|
||||
set_t *set_new_r (set_pool_t *set_pool);
|
||||
|
||||
/** Create a new set with space pre-allocated for the specified set size.
|
||||
|
||||
Although sets automatically grow to accommodate new members as necessary,
|
||||
sometimes the maximum set size is known in advance and it can be more
|
||||
efficient to grow the set in advance.
|
||||
|
||||
The set is initialized to be the empty set.
|
||||
|
||||
\param size The number of elements for which space is to be allocated.
|
||||
\return The newly created, empty set.
|
||||
*/
|
||||
set_t *set_new_size (int size);
|
||||
set_t *set_new_size_r (set_pool_t *set_pool, int size);
|
||||
|
||||
/** Delete a set that is no longer needed.
|
||||
|
||||
\param set The set to be deleted.
|
||||
*/
|
||||
void set_delete (set_t *set);
|
||||
void set_delete_r (set_pool_t *set_pool, set_t *set);
|
||||
|
||||
/** Add an element to a set.
|
||||
|
||||
|
@ -295,6 +336,7 @@ unsigned set_size (const set_t *set);
|
|||
of everything.
|
||||
*/
|
||||
set_iter_t *set_first (const set_t *set);
|
||||
set_iter_t *set_first_r (set_pool_t *set_pool, const set_t *set);
|
||||
|
||||
/** Find the next "member" of the set.
|
||||
|
||||
|
@ -312,6 +354,7 @@ set_iter_t *set_first (const set_t *set);
|
|||
is reached.
|
||||
*/
|
||||
set_iter_t *set_next (set_iter_t *set_iter);
|
||||
set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter);
|
||||
|
||||
/** Return a human-readable string representing the set.
|
||||
|
||||
|
|
|
@ -58,20 +58,27 @@ typedef struct date_s {
|
|||
char str[128];
|
||||
} date_t;
|
||||
|
||||
int Sys_FileTime (const char *path);
|
||||
int Sys_FileExists (const char *path);
|
||||
int Sys_isdir (const char *path);
|
||||
int Sys_mkdir (const char *path);
|
||||
|
||||
typedef void (*sys_printf_t) (const char *fmt, va_list args);
|
||||
typedef void (*sys_error_t) (void *data);
|
||||
|
||||
void Sys_SetStdPrintf (sys_printf_t func);
|
||||
void Sys_SetErrPrintf (sys_printf_t func);
|
||||
|
||||
void Sys_PushErrorHandler (sys_error_t func, void *data);
|
||||
void Sys_PopErrorHandler (void);
|
||||
|
||||
void Sys_Print (FILE *stream, const char *fmt, va_list args);
|
||||
void Sys_Printf (const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn));
|
||||
void Sys_FatalError (const char *error, ...) __attribute__((format(printf,1,2), noreturn));
|
||||
void Sys_Quit (void) __attribute__((noreturn));
|
||||
void Sys_Shutdown (void);
|
||||
void Sys_RegisterShutdown (void (*func) (void));
|
||||
int64_t Sys_LongTime (void);
|
||||
double Sys_DoubleTime (void);
|
||||
void Sys_TimeOfDay(date_t *date);
|
||||
|
||||
|
|
|
@ -59,8 +59,6 @@ typedef struct {
|
|||
int conrowbytes;
|
||||
int conwidth;
|
||||
int conheight;
|
||||
unsigned maxwarpwidth;
|
||||
unsigned maxwarpheight;
|
||||
byte *direct; // direct drawing to framebuffer, if not
|
||||
// NULL
|
||||
int (*surf_cache_size)(int width, int height);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "gib_tree.h"
|
||||
|
||||
inline qboolean GIB_Escaped (const char *str, int i);
|
||||
qboolean GIB_Escaped (const char *str, int i);
|
||||
|
||||
char GIB_Parse_Match_Brace (const char *str, unsigned int *i);
|
||||
char GIB_Parse_Match_Backtick (const char *str, unsigned int *i);
|
||||
|
|
|
@ -20,5 +20,7 @@ void VID_Update (vrect_t *rects);
|
|||
void VID_LockBuffer (void);
|
||||
void VID_UnlockBuffer (void);
|
||||
void VID_InitBuffers (void);
|
||||
void VID_MakeColormaps (void);
|
||||
|
||||
|
||||
#endif//__vid_internal_h
|
||||
|
|
|
@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
|
|||
|
||||
SUBDIRS= targets renderer . test
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
SDL_LIBS= @SDL_LIBS@
|
||||
XMMS_LIBS= @XMMS_LIBS@
|
||||
plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)
|
||||
|
|
|
@ -143,7 +143,7 @@ Load_Tracklist (void)
|
|||
{
|
||||
QFile *oggfile = NULL;
|
||||
char *buffile = NULL;
|
||||
int size = -1;
|
||||
int size;
|
||||
|
||||
/* kill off the old tracklist, and make sure we're not playing anything */
|
||||
I_OGGMus_Shutdown ();
|
||||
|
@ -155,8 +155,8 @@ Load_Tracklist (void)
|
|||
return -1; // bail if we don't have a valid filename
|
||||
}
|
||||
|
||||
size = QFS_FOpenFile (mus_ogglist->string, &oggfile);
|
||||
if (size < 0) {
|
||||
oggfile = QFS_FOpenFile (mus_ogglist->string);
|
||||
if (!oggfile) {
|
||||
Sys_Printf ("Mus_OggInit: open of file \"%s\" failed\n",
|
||||
mus_ogglist->string);
|
||||
return -1;
|
||||
|
|
|
@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
|
|||
|
||||
AM_CFLAGS= @PREFER_PIC@ \
|
||||
$(VORBIS_CFLAGS) $(OGG_CFLAGS) $(SAMPLERATE_CFLAGS) $(JACK_CFLAGS)
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)
|
||||
plugin_libadd= @plugin_libadd@
|
||||
EXEEXT=
|
||||
|
|
|
@ -315,7 +315,7 @@ flac_callback_load (void *object, cache_allocator_t allocator)
|
|||
|
||||
sfxblock_t *block = (sfxblock_t *) object;
|
||||
|
||||
QFS_FOpenFile (block->file, &file);
|
||||
file = QFS_FOpenFile (block->file);
|
||||
if (!file)
|
||||
return; //FIXME Sys_Error?
|
||||
|
||||
|
@ -374,7 +374,7 @@ flac_stream_open (sfx_t *sfx)
|
|||
QFile *file;
|
||||
void *f;
|
||||
|
||||
QFS_FOpenFile (stream->file, &file);
|
||||
file = QFS_FOpenFile (stream->file);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ midi_stream_open (sfx_t *sfx)
|
|||
unsigned long int local_buffer_size;
|
||||
midi_file_t *mf;
|
||||
|
||||
QFS_FOpenFile (stream->file, &file);
|
||||
file = QFS_FOpenFile (stream->file);
|
||||
|
||||
local_buffer_size = Qfilesize (file);
|
||||
|
||||
|
|
|
@ -293,7 +293,6 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
int
|
||||
SND_Load (sfx_t *sfx)
|
||||
{
|
||||
dstring_t *foundname = dstring_new ();
|
||||
char *realname;
|
||||
char buf[4];
|
||||
QFile *file;
|
||||
|
@ -303,16 +302,14 @@ SND_Load (sfx_t *sfx)
|
|||
sfx->close = snd_noop;
|
||||
sfx->open = snd_open_fail;
|
||||
|
||||
_QFS_FOpenFile (sfx->name, &file, foundname, 1);
|
||||
file = QFS_FOpenFile (sfx->name);
|
||||
if (!file) {
|
||||
Sys_Printf ("Couldn't load %s\n", sfx->name);
|
||||
dstring_delete (foundname);
|
||||
return -1;
|
||||
}
|
||||
sfx->open = snd_open;
|
||||
if (!strequal (foundname->str, sfx->name)) {
|
||||
realname = foundname->str;
|
||||
free (foundname);
|
||||
if (!strequal (qfs_foundfile.realname, sfx->name)) {
|
||||
realname = strdup (qfs_foundfile.realname);
|
||||
} else {
|
||||
realname = (char *) sfx->name; // won't free if realname == sfx->name
|
||||
}
|
||||
|
|
|
@ -196,7 +196,7 @@ vorbis_callback_load (void *object, cache_allocator_t allocator)
|
|||
|
||||
sfxblock_t *block = (sfxblock_t *) object;
|
||||
|
||||
QFS_FOpenFile (block->file, &file);
|
||||
file = QFS_FOpenFile (block->file);
|
||||
if (!file)
|
||||
return; //FIXME Sys_Error?
|
||||
|
||||
|
@ -260,7 +260,7 @@ vorbis_stream_open (sfx_t *sfx)
|
|||
QFile *file;
|
||||
vorbis_file_t *f;
|
||||
|
||||
QFS_FOpenFile (stream->file, &file);
|
||||
file = QFS_FOpenFile (stream->file);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ wav_callback_load (void *object, cache_allocator_t allocator)
|
|||
sfxbuffer_t *buffer;
|
||||
wavinfo_t *info = &block->wavinfo;
|
||||
|
||||
QFS_FOpenFile (name, &file);
|
||||
file = QFS_FOpenFile (name);
|
||||
if (!file)
|
||||
return; //FIXME Sys_Error?
|
||||
|
||||
|
@ -152,7 +152,7 @@ wav_stream_open (sfx_t *sfx)
|
|||
QFile *file;
|
||||
wav_file_t *wf;
|
||||
|
||||
QFS_FOpenFile (stream->file, &file);
|
||||
file = QFS_FOpenFile (stream->file);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
SDL_LIBS = @SDL_LIBS@
|
||||
plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)
|
||||
plugin_libadd= @plugin_libadd@
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_PROGRAMS= @AUDIO_TARGETS@
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= libQFclient.la
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS)
|
||||
plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)
|
||||
plugin_libadd= @plugin_libadd@
|
||||
lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \
|
||||
|
|
|
@ -474,11 +474,15 @@ C_KeyEvent (knum_t key, short unicode, qboolean down)
|
|||
return;
|
||||
}
|
||||
case key_game:
|
||||
case key_demo:
|
||||
Menu_Enter ();
|
||||
return;
|
||||
default:
|
||||
Sys_Error ("Bad con_keydest");
|
||||
case key_unfocused:
|
||||
return;
|
||||
case key_last:
|
||||
break; // should not happen, so hit error
|
||||
}
|
||||
Sys_Error ("Bad con_keydest");
|
||||
} else if (key == key_toggleconsole) {
|
||||
ToggleConsole_f ();
|
||||
return;
|
||||
|
|
|
@ -452,6 +452,26 @@ bi_Menu_Enter (progs_t *pr)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Menu_Leave (progs_t *pr)
|
||||
{
|
||||
if (menu) {
|
||||
if (menu->leave_hook) {
|
||||
run_menu_pre ();
|
||||
PR_ExecuteProgram (&menu_pr_state, menu->leave_hook);
|
||||
run_menu_post ();
|
||||
}
|
||||
menu = menu->parent;
|
||||
if (!menu) {
|
||||
if (con_data.force_commandline) {
|
||||
Key_SetKeyDest (key_console);
|
||||
} else {
|
||||
Key_SetKeyDest (key_game);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
togglemenu_f (void)
|
||||
{
|
||||
|
@ -492,7 +512,7 @@ menu_free_progs_mem (progs_t *pr, void *mem)
|
|||
static void *
|
||||
menu_load_file (progs_t *pr, const char *path)
|
||||
{
|
||||
return QFS_LoadFile (path, 0);
|
||||
return QFS_LoadFile (QFS_FOpenFile (path), 0);
|
||||
}
|
||||
|
||||
static builtin_t builtins[] = {
|
||||
|
@ -517,9 +537,38 @@ static builtin_t builtins[] = {
|
|||
{"Menu_Next", bi_Menu_Next, -1},
|
||||
{"Menu_Prev", bi_Menu_Prev, -1},
|
||||
{"Menu_Enter", bi_Menu_Enter, -1},
|
||||
{"Menu_Leave", bi_Menu_Leave, -1},
|
||||
{0},
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
Menu_Enter_f (void)
|
||||
{
|
||||
if (!Menu_KeyEvent(QFK_RETURN, '\0', true))
|
||||
Menu_KeyEvent('y', 'y', true);
|
||||
}
|
||||
|
||||
void
|
||||
Menu_Leave_f (void)
|
||||
{
|
||||
Menu_Leave ();
|
||||
}
|
||||
|
||||
void
|
||||
Menu_Prev_f (void)
|
||||
{
|
||||
Menu_KeyEvent (QFK_UP, '\0', true);
|
||||
}
|
||||
|
||||
void
|
||||
Menu_Next_f (void)
|
||||
{
|
||||
Menu_KeyEvent (QFK_DOWN, '\0', true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Menu_Init (void)
|
||||
{
|
||||
|
@ -549,6 +598,10 @@ Menu_Init (void)
|
|||
"Toggle the display of the menu");
|
||||
Cmd_RemoveCommand ("quit");
|
||||
Cmd_AddCommand ("quit", quit_f, "Exit the program");
|
||||
Cmd_AddCommand ("Menu_Enter", Menu_Enter_f, "Do menu action/move up in the menu tree.");
|
||||
Cmd_AddCommand ("Menu_Leave", Menu_Leave_f, "Move down in the menu tree.");
|
||||
Cmd_AddCommand ("Menu_Prev", Menu_Prev_f, "Move cursor up.");
|
||||
Cmd_AddCommand ("Menu_Next", Menu_Next_f, "Move cursor up.");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -562,7 +615,8 @@ Menu_Load (void)
|
|||
top_menu = 0;
|
||||
|
||||
menu_pr_state.progs = 0;
|
||||
if ((size = QFS_FOpenFile (menu_pr_state.progs_name, &file)) != -1) {
|
||||
if ((file = QFS_FOpenFile (menu_pr_state.progs_name))) {
|
||||
size = Qfilesize (file);
|
||||
PR_LoadProgsFile (&menu_pr_state, file, size, 0, 1024 * 1024);
|
||||
Qclose (file);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
lib_ldflags=
|
||||
|
||||
gc_deps=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
|
|
@ -328,6 +328,14 @@ signal_hook (int sig, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
error_handler (void *data)
|
||||
{
|
||||
progs_t *pr = (progs_t *) data;
|
||||
PR_DumpState (pr);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
VISIBLE int
|
||||
PR_CallFunction (progs_t *pr, func_t fnum)
|
||||
{
|
||||
|
@ -338,6 +346,10 @@ PR_CallFunction (progs_t *pr, func_t fnum)
|
|||
f = pr->function_table + fnum;
|
||||
if (f->first_statement < 0) {
|
||||
// negative statements are built in functions
|
||||
if (pr->pr_trace) {
|
||||
Sys_Printf ("Calling builtin %s @ %p\n",
|
||||
PR_GetString (pr, f->descriptor->s_name), f->func);
|
||||
}
|
||||
f->func (pr);
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -366,11 +378,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
startprofile = profile = 0;
|
||||
|
||||
Sys_PushSignalHook (signal_hook, pr);
|
||||
Sys_PushErrorHandler (error_handler, pr);
|
||||
|
||||
if (!PR_CallFunction (pr, fnum)) {
|
||||
// called a builtin instead of progs code
|
||||
Sys_PopSignalHook ();
|
||||
return;
|
||||
goto exit_program;
|
||||
}
|
||||
st = pr->pr_statements + pr->pr_xstatement;
|
||||
|
||||
|
@ -893,7 +905,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
|||
&& (OPA.uinteger_var >= pr->progs->numstatements)) {
|
||||
PR_RunError (pr, "Invalid jump destination");
|
||||
}
|
||||
pr->pr_xstatement = OPA.uinteger_var;
|
||||
pr->pr_xstatement = OPA.uinteger_var - 1; // offset the st++
|
||||
st = pr->pr_statements + pr->pr_xstatement;
|
||||
break;
|
||||
case OP_JUMPB:
|
||||
|
@ -960,8 +972,8 @@ op_call:
|
|||
if (pr->pr_depth == exitdepth) {
|
||||
if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth)
|
||||
pr->pr_trace = false;
|
||||
Sys_PopSignalHook ();
|
||||
return; // all done
|
||||
// all done
|
||||
goto exit_program;
|
||||
}
|
||||
break;
|
||||
case OP_STATE:
|
||||
|
@ -1112,4 +1124,7 @@ op_call:
|
|||
PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var,
|
||||
watch->integer_var);
|
||||
}
|
||||
exit_program:
|
||||
Sys_PopErrorHandler ();
|
||||
Sys_PopSignalHook ();
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ file_error (progs_t *pr, const char *path)
|
|||
static void *
|
||||
load_file (progs_t *pr, const char *path)
|
||||
{
|
||||
return QFS_LoadHunkFile (path);
|
||||
return QFS_LoadHunkFile (QFS_FOpenFile (path));
|
||||
}
|
||||
|
||||
static void *
|
||||
|
@ -382,7 +382,7 @@ VISIBLE void
|
|||
PR_LoadProgs (progs_t *pr, const char *progsname, int max_edicts, int zone)
|
||||
{
|
||||
QFile *file;
|
||||
QFS_FOpenFile (progsname, &file);
|
||||
file = QFS_FOpenFile (progsname);
|
||||
|
||||
pr->progs_name = progsname;
|
||||
if (file) {
|
||||
|
|
|
@ -299,41 +299,48 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s)
|
|||
*/
|
||||
|
||||
VISIBLE plitem_t *
|
||||
ED_ConvertToPlist (progs_t *pr, script_t *script)
|
||||
ED_ConvertToPlist (script_t *script, int nohack)
|
||||
{
|
||||
plitem_t *plist = PL_NewArray ();
|
||||
plitem_t *ent;
|
||||
plitem_t *key;
|
||||
plitem_t *value;
|
||||
const char *token;
|
||||
char *token;
|
||||
int anglehack;
|
||||
|
||||
while (Script_GetToken (script, 1)) {
|
||||
token = script->token->str;
|
||||
if (!strequal (token, "{"))
|
||||
PR_Error (pr, "ED_ParseEntity: EOF without closing brace");
|
||||
Sys_Error ("ED_ConvertToPlist: EOF without closing brace");
|
||||
ent = PL_NewDictionary ();
|
||||
while (1) {
|
||||
int n;
|
||||
|
||||
if (!Script_GetToken (script, 1))
|
||||
PR_Error (pr, "ED_ParseEntity: EOF without closing brace");
|
||||
Sys_Error ("ED_ConvertToPlist: EOF without closing brace");
|
||||
token = script->token->str;
|
||||
if (strequal (token, "}"))
|
||||
break;
|
||||
// hack to take care of trailing spaces in field names
|
||||
// (looking at you, Rogue)
|
||||
for (n = strlen (token); n && token[n - 1] == ' '; n--) {
|
||||
token[n - 1] = 0;
|
||||
}
|
||||
anglehack = 0;
|
||||
if (strequal (token, "angle")) {
|
||||
if (!nohack && strequal (token, "angle")) {
|
||||
key = PL_NewString ("angles");
|
||||
anglehack = 1;
|
||||
} else if (strequal (token, "light")) {
|
||||
} else if (!nohack && strequal (token, "light")) {
|
||||
key = PL_NewString ("light_lev");
|
||||
} else {
|
||||
key = PL_NewString (token);
|
||||
}
|
||||
if (!Script_TokenAvailable (script, 0))
|
||||
PR_Error (pr, "ED_ParseEntity: EOL without value");
|
||||
Sys_Error ("ED_ConvertToPlist: EOL without value");
|
||||
Script_GetToken (script, 0);
|
||||
token = script->token->str;
|
||||
if (strequal (token, "}"))
|
||||
PR_Error (pr, "ED_ParseEntity: closing brace without data");
|
||||
Sys_Error ("ED_ConvertToPlist: closing brace without data");
|
||||
if (anglehack)
|
||||
value = PL_NewString (va ("0 %s 0", token));
|
||||
else
|
||||
|
@ -501,7 +508,7 @@ ED_Parse (progs_t *pr, const char *data)
|
|||
} else {
|
||||
// oldstyle entity data
|
||||
Script_UngetToken (script);
|
||||
entity_list = ED_ConvertToPlist (pr, script);
|
||||
entity_list = ED_ConvertToPlist (script, 0);
|
||||
}
|
||||
}
|
||||
Script_Delete (script);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS)
|
||||
|
||||
lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \
|
||||
-rpath $(libdir) -no-undefined
|
||||
|
|
|
@ -792,7 +792,7 @@ GIB_File_Read_f (void)
|
|||
if (!(ret = GIB_Return (0)))
|
||||
return;
|
||||
path = GIB_Argv (1);
|
||||
QFS_FOpenFile (path, &file);
|
||||
file = QFS_FOpenFile (path);
|
||||
if (file) {
|
||||
len = Qfilesize (file);
|
||||
ret->size = len + 1;
|
||||
|
|
|
@ -70,7 +70,7 @@ GIB_Exec_Override_f (void)
|
|||
}
|
||||
|
||||
mark = Hunk_LowMark ();
|
||||
f = (char *) QFS_LoadHunkFile (Cmd_Argv (1));
|
||||
f = (char *) QFS_LoadHunkFile (QFS_FOpenFile (Cmd_Argv (1)));
|
||||
if (!f) {
|
||||
Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1));
|
||||
return;
|
||||
|
|
|
@ -62,7 +62,7 @@ LoadImage (const char *imageFile)
|
|||
|
||||
// Check for a .png
|
||||
dstring_replace (tmpFile, tmp, tmpFile->size, ".png", 5);
|
||||
QFS_FOpenFile (tmpFile->str, &fp);
|
||||
fp = QFS_FOpenFile (tmpFile->str);
|
||||
if (fp) {
|
||||
tex = LoadPNG (fp);
|
||||
Qclose (fp);
|
||||
|
@ -72,7 +72,7 @@ LoadImage (const char *imageFile)
|
|||
|
||||
// Check for a .tga
|
||||
dstring_replace (tmpFile, tmp, tmpFile->size, ".tga", 5);
|
||||
QFS_FOpenFile (tmpFile->str, &fp);
|
||||
fp = QFS_FOpenFile (tmpFile->str);
|
||||
if (fp) {
|
||||
tex = LoadTGA (fp);
|
||||
Qclose (fp);
|
||||
|
@ -83,7 +83,7 @@ LoadImage (const char *imageFile)
|
|||
/*
|
||||
// Check for a .jpg
|
||||
dstring_replace (tmpFile, tmp, tmpFile->size, ".jpg", 5);
|
||||
QFS_FOpenFile (tmpFile->str, &fp);
|
||||
fp = QFS_FOpenFile (tmpFile->str);
|
||||
if (fp) {
|
||||
tex = LoadJPG (fp);
|
||||
Qclose (fp);
|
||||
|
@ -94,7 +94,7 @@ LoadImage (const char *imageFile)
|
|||
|
||||
// Check for a .pcx
|
||||
dstring_replace (tmpFile, tmp, tmpFile->size, ".pcx", 5);
|
||||
QFS_FOpenFile (tmpFile->str, &fp);
|
||||
fp = QFS_FOpenFile (tmpFile->str);
|
||||
if (fp) {
|
||||
tex = LoadPCX (fp, 1, NULL); // Convert, some users don't grok paletted
|
||||
Qclose (fp);
|
||||
|
|
|
@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
|
|||
|
||||
SUBDIRS= alias brush iqm sprite . test
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
lib_LTLIBRARIES= libQFmodels.la
|
||||
noinst_LTLIBRARIES= @models_libs@
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= @alias_libs@
|
||||
EXTRA_LTLIBRARIES=libalias_gl.la libalias_glsl.la libalias_sw.la
|
||||
|
|
|
@ -366,7 +366,7 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m,
|
|||
cache->str + strlen ("glquake/"));
|
||||
dstring_appendstr (cache, ".qfms");
|
||||
|
||||
QFS_FOpenFile (cache->str, &f);
|
||||
f = QFS_FOpenFile (cache->str);
|
||||
if (f) {
|
||||
unsigned char d1[MDFOUR_DIGEST_BYTES];
|
||||
unsigned char d2[MDFOUR_DIGEST_BYTES];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= libbrush.la @brush_libs@
|
||||
EXTRA_LTLIBRARIES=libbrush_gl.la libbrush_glsl.la libbrush_sw.la
|
||||
|
|
|
@ -141,6 +141,7 @@ gl_Mod_LoadLighting (bsp_t *bsp)
|
|||
dstring_t *litfilename = dstring_new ();
|
||||
size_t i;
|
||||
int ver;
|
||||
QFile *lit_file;
|
||||
|
||||
dstring_copystr (litfilename, loadmodel->name);
|
||||
loadmodel->lightdata = NULL;
|
||||
|
@ -148,7 +149,8 @@ gl_Mod_LoadLighting (bsp_t *bsp)
|
|||
// LordHavoc: check for a .lit file to load
|
||||
QFS_StripExtension (litfilename->str, litfilename->str);
|
||||
dstring_appendstr (litfilename, ".lit");
|
||||
data = (byte *) QFS_LoadHunkFile (litfilename->str);
|
||||
lit_file = QFS_VOpenFile (litfilename->str, 0, loadmodel->vpath);
|
||||
data = (byte *) QFS_LoadHunkFile (lit_file);
|
||||
if (data) {
|
||||
if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I'
|
||||
&& data[3] == 'T') {
|
||||
|
|
|
@ -186,6 +186,7 @@ build_skin (skin_t *skin, int cmap)
|
|||
s = &player_skin;
|
||||
if (!s->tex) // we haven't loaded the player model yet
|
||||
return;
|
||||
|
||||
texnum = skin_textures + cmap;
|
||||
fb_texnum = 0;
|
||||
if (s->fb)
|
||||
|
@ -197,13 +198,13 @@ build_skin (skin_t *skin, int cmap)
|
|||
if (vid.is8bit) {
|
||||
build_skin_8 (s->tex, texnum, skin_cmap[cmap],
|
||||
scaled_width, scaled_height, false);
|
||||
if (s->fb)
|
||||
if (s->fb && s->fb_tex)
|
||||
build_skin_8 (s->fb_tex, fb_texnum, skin_cmap[cmap],
|
||||
scaled_width, scaled_height, true);
|
||||
} else {
|
||||
build_skin_32 (s->tex, texnum, skin_cmap[cmap],
|
||||
scaled_width, scaled_height, false);
|
||||
if (s->fb)
|
||||
if (s->fb && s->fb_tex)
|
||||
build_skin_32 (s->fb_tex, fb_texnum, skin_cmap[cmap],
|
||||
scaled_width, scaled_height, true);
|
||||
}
|
||||
|
@ -231,19 +232,20 @@ gl_Skin_SetupSkin (skin_t *skin, int cmap)
|
|||
int changed;
|
||||
glskin_t *s;
|
||||
|
||||
skin->texnum = 0;
|
||||
skin->auxtex = 0;
|
||||
if (!cmap) {
|
||||
return;
|
||||
}
|
||||
// simplify cmap usage (texture offset/array index)
|
||||
cmap--;
|
||||
s = skins + cmap;
|
||||
changed = (s->tex != skin->texels);
|
||||
s->tex = skin->texels;
|
||||
if (!changed) {
|
||||
skin->texnum = 0;
|
||||
skin->auxtex = 0;
|
||||
if (cmap >= 0) {
|
||||
skin->texnum = skin_textures + cmap;
|
||||
if (s->fb)
|
||||
skin->auxtex = skin_fb_textures + cmap;
|
||||
}
|
||||
skin->texnum = skin_textures + cmap;
|
||||
if (s->fb)
|
||||
skin->auxtex = skin_fb_textures + cmap;
|
||||
return;
|
||||
}
|
||||
if (s->tex)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= @iqm_libs@
|
||||
EXTRA_LTLIBRARIES=libiqm_gl.la libiqm_glsl.la libiqm_sw.la
|
||||
|
|
|
@ -171,21 +171,20 @@ Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator)
|
|||
uint32_t *buf;
|
||||
|
||||
// load the file
|
||||
buf = (uint32_t *) QFS_LoadFile (mod->name, 0);
|
||||
buf = (uint32_t *) QFS_LoadFile (QFS_FOpenFile (mod->name), 0);
|
||||
if (!buf) {
|
||||
if (crash)
|
||||
Sys_Error ("Mod_LoadModel: %s not found", mod->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// allocate a new model
|
||||
if (loadname)
|
||||
free (loadname);
|
||||
loadname = QFS_FileBase (mod->name);
|
||||
|
||||
loadmodel = mod;
|
||||
|
||||
// fill it in
|
||||
mod->vpath = qfs_foundfile.vpath;
|
||||
mod->fullbright = 0;
|
||||
mod->shadow_alpha = 255;
|
||||
mod->min_light = 0.0;
|
||||
|
|
|
@ -177,7 +177,7 @@ Skin_SetSkin (skin_t *skin, int cmap, const char *skinname)
|
|||
break;
|
||||
}
|
||||
|
||||
QFS_FOpenFile (va ("skins/%s.pcx", name), &file);
|
||||
file = QFS_FOpenFile (va ("skins/%s.pcx", name));
|
||||
if (!file) {
|
||||
Sys_Printf ("Couldn't load skin %s\n", name);
|
||||
free (name);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= @sprite_libs@
|
||||
EXTRA_LTLIBRARIES=libsprite_gl.la libsprite_glsl.la libsprite_sw.la
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
INCLUDES= -I$(srcdir) -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(srcdir) -I$(top_srcdir)/include
|
||||
|
||||
check_PROGRAMS=testclip testcontents testportals
|
||||
EXTRA_DIST= trace-id.c trace-qf-bad.c hulls.h main.c
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "hulls.h"
|
||||
|
||||
// 0,0
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "QF/va.h"
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "QF/va.h"
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "QF/va.h"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
|
|||
|
||||
SUBDIRS= nc nm
|
||||
AM_CFLAGS= @PREFER_NON_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= libnet_chan.la libnet_main.la
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_NON_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= libnc.la
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_NON_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LTLIBRARIES= libnm.la
|
||||
|
||||
|
|
|
@ -97,6 +97,12 @@
|
|||
#include "netmain.h"
|
||||
#include "net_udp.h"
|
||||
|
||||
#ifdef HAVE_IN_PKTINFO
|
||||
# ifndef SOL_IP // BSD-based stacks don't define this.
|
||||
# define SOL_IP IPPROTO_IP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# undef EWOULDBLOCK
|
||||
# define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
noinst_LIBRARIES= libqw.a
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS)
|
||||
|
||||
lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \
|
||||
-rpath $(libdir) -no-undefined
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#include "rua_internal.h"
|
||||
|
||||
#define always_inline inline __attribute__((__always_inline__))
|
||||
|
||||
typedef struct bi_plist_s {
|
||||
struct bi_plist_s *next;
|
||||
struct bi_plist_s **prev;
|
||||
|
@ -140,7 +142,7 @@ plist_free_handle (plist_resources_t *res, bi_plist_t *plist)
|
|||
plist_free (res, plist);
|
||||
}
|
||||
|
||||
static inline bi_plist_t *
|
||||
static always_inline bi_plist_t *
|
||||
get_plist (progs_t *pr, const char *name, int handle)
|
||||
{
|
||||
plist_resources_t *res = PR_Resources_Find (pr, "plist");
|
||||
|
|
|
@ -106,7 +106,7 @@ bi_QFS_LoadFile (progs_t *pr)
|
|||
int size;
|
||||
void *buffer;
|
||||
|
||||
QFS_FOpenFile (filename, &file);
|
||||
file = QFS_FOpenFile (filename);
|
||||
if (!file) {
|
||||
RETURN_POINTER (pr, 0);
|
||||
return;
|
||||
|
@ -129,7 +129,7 @@ bi_QFS_OpenFile (progs_t *pr)
|
|||
QFile *file;
|
||||
const char *filename = P_GSTRING (pr, 0);
|
||||
|
||||
QFS_FOpenFile (filename, &file);
|
||||
file = QFS_FOpenFile (filename);
|
||||
if (!file) {
|
||||
R_INT (pr) = 0;
|
||||
return;
|
||||
|
|
|
@ -4,7 +4,7 @@ SUBDIRS= . test
|
|||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
CCASFLAGS+= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include $(Z_CFLAGS)
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(Z_CFLAGS) $(FNM_FLAGS)
|
||||
|
||||
lib_LTLIBRARIES= libQFutil.la
|
||||
|
||||
|
@ -52,8 +52,8 @@ libQFutil_la_SOURCES= \
|
|||
bspfile.c buildnum.c cbuf.c checksum.c cmd.c crc.c cvar.c dstring.c \
|
||||
fendian.c hash.c idparse.c info.c link.c llist.c \
|
||||
mathlib.c mdfour.c mersenne.c msg.c pakfile.c plugin.c qargs.c qendian.c \
|
||||
qfplist.c quakefs.c quakeio.c riff.c script.c set.c sizebuf.c string.c \
|
||||
sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \
|
||||
qfplist.c quakefs.c quakeio.c riff.c script.c segtext.c set.c sizebuf.c \
|
||||
string.c sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \
|
||||
$(dirent) $(fnmatch) $(getopt)
|
||||
|
||||
EXTRA_DIST= $(fnmatch_src) $(getopt_src)
|
||||
|
|
|
@ -490,7 +490,7 @@ Cmd_Exec_f (void)
|
|||
}
|
||||
|
||||
mark = Hunk_LowMark ();
|
||||
f = (char *) QFS_LoadHunkFile (Cmd_Argv (1));
|
||||
f = (char *) QFS_LoadHunkFile (QFS_FOpenFile (Cmd_Argv (1)));
|
||||
if (!f) {
|
||||
Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1));
|
||||
return;
|
||||
|
@ -638,7 +638,7 @@ Cmd_Exec_File (cbuf_t *cbuf, const char *path, int qfs)
|
|||
if (!path || !*path)
|
||||
return;
|
||||
if (qfs) {
|
||||
QFS_FOpenFile (path, &file);
|
||||
file = QFS_FOpenFile (path);
|
||||
} else {
|
||||
char *newpath = Sys_ExpandSquiggle (path);
|
||||
file = Qopen (newpath, "r");
|
||||
|
|
|
@ -299,23 +299,13 @@ dstring_clearstr (dstring_t *dstr)
|
|||
dstr->str[0] = 0;
|
||||
}
|
||||
|
||||
#if defined (HAVE_VA_COPY)
|
||||
# define VA_COPY(a,b) va_copy (a, b)
|
||||
#elif defined (HAVE__VA_COPY)
|
||||
# define VA_COPY(a,b) __va_copy (a, b)
|
||||
#else
|
||||
# define VA_COPY(a,b) memcpy (a, b, sizeof (a))
|
||||
#endif
|
||||
|
||||
static int
|
||||
_dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args)
|
||||
{
|
||||
int size;
|
||||
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
va_list tmp_args;
|
||||
VA_COPY (tmp_args, args);
|
||||
#endif
|
||||
va_copy (tmp_args, args);
|
||||
|
||||
if (!dstr->truesize)
|
||||
dstring_clearstr (dstr); // Make it a string
|
||||
|
@ -324,17 +314,13 @@ _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args)
|
|||
args)) == -1) {
|
||||
dstr->size = (dstr->truesize & ~1023) + 1024;
|
||||
dstring_adjust (dstr);
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
VA_COPY (args, tmp_args);
|
||||
#endif
|
||||
va_copy (args, tmp_args);
|
||||
}
|
||||
dstr->size = size + offs + 2;
|
||||
// "Proper" implementations return the required size
|
||||
if (dstr->size > dstr->truesize) {
|
||||
dstring_adjust (dstr);
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
VA_COPY (args, tmp_args);
|
||||
#endif
|
||||
va_copy (args, tmp_args);
|
||||
vsnprintf (dstr->str + offs, dstr->truesize - offs - 1, fmt, args);
|
||||
}
|
||||
dstr->size = size + offs + 1;
|
||||
|
|
|
@ -1151,3 +1151,262 @@ Mat4Decompose (const mat4_t mat, quat_t rot, vec3_t shear, vec3_t scale,
|
|||
Mat4toMat3 (mat, m3);
|
||||
return Mat3Decompose (m3, rot, shear, scale);
|
||||
}
|
||||
|
||||
void
|
||||
BarycentricCoords (const vec_t **points, int num_points, const vec3_t p,
|
||||
vec_t *lambda)
|
||||
{
|
||||
vec3_t a, b, c, x, ab, bc, ca, n;
|
||||
vec_t div;
|
||||
if (num_points > 4)
|
||||
Sys_Error ("Don't know how to compute the barycentric coordinates "
|
||||
"for %d points", num_points);
|
||||
switch (num_points) {
|
||||
case 1:
|
||||
lambda[0] = 1;
|
||||
return;
|
||||
case 2:
|
||||
VectorSubtract (p, points[0], x);
|
||||
VectorSubtract (points[1], points[0], a);
|
||||
lambda[1] = DotProduct (x, a) / DotProduct (a, a);
|
||||
lambda[0] = 1 - lambda[1];
|
||||
return;
|
||||
case 3:
|
||||
VectorSubtract (p, points[0], x);
|
||||
VectorSubtract (points[1], points[0], a);
|
||||
VectorSubtract (points[2], points[0], b);
|
||||
CrossProduct (a, b, ab);
|
||||
div = DotProduct (ab, ab);
|
||||
CrossProduct (x, b, n);
|
||||
lambda[1] = DotProduct (n, ab) / div;
|
||||
CrossProduct (a, x, n);
|
||||
lambda[2] = DotProduct (n, ab) / div;
|
||||
lambda[0] = 1 - lambda[1] - lambda[2];
|
||||
return;
|
||||
case 4:
|
||||
VectorSubtract (p, points[0], x);
|
||||
VectorSubtract (points[1], points[0], a);
|
||||
VectorSubtract (points[2], points[0], b);
|
||||
VectorSubtract (points[3], points[0], c);
|
||||
CrossProduct (a, b, ab);
|
||||
CrossProduct (b, c, bc);
|
||||
CrossProduct (c, a, ca);
|
||||
div = DotProduct (a, bc);
|
||||
lambda[1] = DotProduct (x, bc) / div;
|
||||
lambda[2] = DotProduct (x, ca) / div;
|
||||
lambda[3] = DotProduct (x, ab) / div;
|
||||
lambda[0] = 1 - lambda[1] - lambda[2] - lambda[3];
|
||||
return;
|
||||
}
|
||||
Sys_Error ("Not enough points to project or enclose the point");
|
||||
}
|
||||
|
||||
static int
|
||||
circum_circle (const vec_t **points, int num_points, sphere_t *sphere)
|
||||
{
|
||||
vec3_t a, c, b;
|
||||
vec3_t bc, ca, ab;
|
||||
vec_t aa, bb, cc;
|
||||
vec_t div;
|
||||
vec_t alpha, beta, gamma;
|
||||
|
||||
switch (num_points) {
|
||||
case 1:
|
||||
VectorCopy (points[0], sphere->center);
|
||||
return 1;
|
||||
case 2:
|
||||
VectorBlend (points[0], points[1], 0.5, sphere->center);
|
||||
return 1;
|
||||
case 3:
|
||||
VectorSubtract (points[0], points[1], a);
|
||||
VectorSubtract (points[0], points[2], b);
|
||||
VectorSubtract (points[1], points[2], c);
|
||||
aa = DotProduct (a, a);
|
||||
bb = DotProduct (b, b);
|
||||
cc = DotProduct (c, c);
|
||||
div = DotProduct (a, c);
|
||||
div = 2 * (aa * cc - div * div);
|
||||
if (fabs (div) < EQUAL_EPSILON) {
|
||||
// degenerate
|
||||
return 0;
|
||||
}
|
||||
alpha = cc * DotProduct (a, b) / div;
|
||||
beta = -bb * DotProduct (a, c) / div;
|
||||
gamma = aa * DotProduct (b, c) / div;
|
||||
VectorScale (points[0], alpha, sphere->center);
|
||||
VectorMultAdd (sphere->center, beta, points[1], sphere->center);
|
||||
VectorMultAdd (sphere->center, gamma, points[2], sphere->center);
|
||||
return 1;
|
||||
case 4:
|
||||
VectorSubtract (points[1], points[0], a);
|
||||
VectorSubtract (points[2], points[0], b);
|
||||
VectorSubtract (points[3], points[0], c);
|
||||
CrossProduct (b, c, bc);
|
||||
CrossProduct (c, a, ca);
|
||||
CrossProduct (a, b, ab);
|
||||
div = 2 * DotProduct (a, bc);
|
||||
if (fabs (div) < EQUAL_EPSILON) {
|
||||
// degenerate
|
||||
return 0;
|
||||
}
|
||||
aa = DotProduct (a, a) / div;
|
||||
bb = DotProduct (b, b) / div;
|
||||
cc = DotProduct (c, c) / div;
|
||||
VectorScale (bc, aa, sphere->center);
|
||||
VectorMultAdd (sphere->center, bb, ca, sphere->center);
|
||||
VectorMultAdd (sphere->center, cc, ab, sphere->center);
|
||||
VectorAdd (sphere->center, points[0], sphere->center);
|
||||
sphere->radius = VectorDistance (sphere->center, points[0]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
CircumSphere (const vec3_t points[], int num_points, sphere_t *sphere)
|
||||
{
|
||||
const vec_t *p[] = {points[0], points[1], points[2], points[3]};
|
||||
|
||||
if (num_points > 4)
|
||||
return 0;
|
||||
sphere->radius = 0;
|
||||
if (num_points) {
|
||||
if (circum_circle (p, num_points, sphere)) {
|
||||
if (num_points > 1)
|
||||
sphere->radius = VectorDistance (sphere->center, points[0]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
VectorZero (sphere->center);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
closest_point (const vec_t **points, int num_points, const vec3_t x,
|
||||
vec3_t closest)
|
||||
{
|
||||
vec3_t a, b, n, d;
|
||||
vec_t l;
|
||||
|
||||
switch (num_points) {
|
||||
default:
|
||||
case 1:
|
||||
VectorCopy (points[0], closest);
|
||||
break;
|
||||
case 2:
|
||||
VectorSubtract (points[1], points[0], n);
|
||||
VectorSubtract (x, points[0], d);
|
||||
l = DotProduct (d, n) / DotProduct (n, n);
|
||||
VectorMultAdd (points[0], l, n, closest);
|
||||
break;
|
||||
case 3:
|
||||
VectorSubtract (points[1], points[0], a);
|
||||
VectorSubtract (points[2], points[0], b);
|
||||
CrossProduct (a, b, n);
|
||||
VectorSubtract (points[0], x, d);
|
||||
l = DotProduct (d, n) / DotProduct (n, n);
|
||||
VectorMultAdd (x, l, n, closest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sphere_t
|
||||
SmallestEnclosingBall (const vec3_t points[], int num_points)
|
||||
{
|
||||
sphere_t sphere;
|
||||
const vec_t *best;
|
||||
const vec_t *support[4];
|
||||
int num_support;
|
||||
vec_t dist, best_dist;
|
||||
int i;
|
||||
int itters = 0;
|
||||
|
||||
if (num_points < 3) {
|
||||
CircumSphere (points, num_points, &sphere);
|
||||
return sphere;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
support[i] = 0;
|
||||
|
||||
VectorCopy (points[0], sphere.center);
|
||||
best_dist = dist = 0;
|
||||
best = 0;
|
||||
for (i = 1; i < num_points; i++) {
|
||||
dist = VectorDistance_fast (points[i], sphere.center);
|
||||
if (dist > best_dist) {
|
||||
best_dist = dist;
|
||||
best = points[i];
|
||||
}
|
||||
}
|
||||
num_support = 1;
|
||||
support[0] = best;
|
||||
sphere.radius = best_dist; // note: radius squared until the end
|
||||
|
||||
while (1) {
|
||||
vec3_t affine;
|
||||
vec3_t center_to_affine, center_to_point;
|
||||
vec_t affine_dist, point_proj, point_dist, bound;
|
||||
vec_t scale = 1;
|
||||
int i;
|
||||
|
||||
if (itters++ > 10)
|
||||
Sys_Error ("stuck SEB");
|
||||
best = 0;
|
||||
|
||||
if (num_support == 4) {
|
||||
vec_t lambda[4];
|
||||
int dropped = 0;
|
||||
|
||||
BarycentricCoords (support, 4, sphere.center, lambda);
|
||||
for (i = 0; i < 4; i++) {
|
||||
support[i - dropped] = support[i];
|
||||
if (lambda[i] < 0) {
|
||||
dropped++;
|
||||
num_support--;
|
||||
}
|
||||
}
|
||||
if (!dropped)
|
||||
break;
|
||||
for (i = 4 - dropped; i < 4; i++)
|
||||
support[i] = 0;
|
||||
}
|
||||
closest_point (support, num_support, sphere.center, affine);
|
||||
VectorSubtract (affine, sphere.center, center_to_affine);
|
||||
affine_dist = DotProduct (center_to_affine, center_to_affine);
|
||||
if (affine_dist < 1e-2 * sphere.radius)
|
||||
break;
|
||||
for (i = 0; i < num_points; i++) {
|
||||
if (points[i] == support [0] || points[i] == support[1]
|
||||
|| points[i] == support[2])
|
||||
continue;
|
||||
VectorSubtract (points[i], sphere.center, center_to_point);
|
||||
point_proj = DotProduct (center_to_affine, center_to_point);
|
||||
if (affine_dist - point_proj <= 0
|
||||
|| ((affine_dist - point_proj) * (affine_dist - point_proj)
|
||||
< 1e-8 * sphere.radius * affine_dist))
|
||||
continue;
|
||||
point_dist = DotProduct (center_to_point, center_to_point);
|
||||
bound = sphere.radius - point_dist;
|
||||
bound /= 2 * (affine_dist - point_proj);
|
||||
if (bound < scale) {
|
||||
best = points[i];
|
||||
scale = bound;
|
||||
}
|
||||
}
|
||||
VectorMultAdd (sphere.center, scale, center_to_affine, sphere.center);
|
||||
if (!best)
|
||||
break;
|
||||
sphere.radius = VectorDistance_fast (sphere.center, best);
|
||||
support[num_support++] = best;
|
||||
}
|
||||
best_dist = 0;
|
||||
for (i = 0; i < num_points; i++) {
|
||||
dist = VectorDistance_fast (sphere.center, points[i]);
|
||||
if (dist > best_dist)
|
||||
best_dist = dist;
|
||||
}
|
||||
sphere.radius = sqrt (best_dist);
|
||||
return sphere;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
#include <limits.h>
|
||||
|
||||
#include "qfalloca.h"
|
||||
|
||||
#include "QF/alloc.h"
|
||||
#include "QF/cmd.h"
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/dstring.h"
|
||||
|
@ -136,7 +136,34 @@ typedef struct searchpath_s {
|
|||
struct searchpath_s *next;
|
||||
} searchpath_t;
|
||||
|
||||
static searchpath_t *qfs_searchpaths;
|
||||
/** Represent a single game directory.
|
||||
|
||||
A vpath is the union of all locations searched for a single gamedir. This
|
||||
includes all pak files in the gamedir in the user's directory, the
|
||||
filesystem in the user's gamedir, then all pak files in the share
|
||||
game directory, and finally share's gamedir filesystem.
|
||||
|
||||
The purpose is to enable searches to be limited to a single gamedir or to
|
||||
not search past a certain gamedir.
|
||||
*/
|
||||
struct vpath_s { // typedef to vpath_t is in quakefs.h
|
||||
char *name; // usually the gamedir name
|
||||
searchpath_t *user;
|
||||
searchpath_t *share;
|
||||
struct vpath_s *next;
|
||||
};
|
||||
|
||||
typedef struct int_findfile_s {
|
||||
findfile_t ff;
|
||||
struct pack_s *pack;
|
||||
dpackfile_t *packfile;
|
||||
const char *path;
|
||||
int fname_index;
|
||||
} int_findfile_t;
|
||||
|
||||
static searchpath_t *searchpaths_freelist;
|
||||
static vpath_t *vpaths_freelist;
|
||||
static vpath_t *qfs_vpaths;
|
||||
|
||||
//QFS
|
||||
|
||||
|
@ -145,7 +172,7 @@ typedef struct qfs_var_s {
|
|||
char *val;
|
||||
} qfs_var_t;
|
||||
|
||||
static void qfs_add_gamedir (const char *dir);
|
||||
static void qfs_add_gamedir (vpath_t *vpath, const char *dir);
|
||||
|
||||
VISIBLE gamedir_t *qfs_gamedir;
|
||||
static plitem_t *qfs_gd_plist;
|
||||
|
@ -213,6 +240,55 @@ static gamedir_callback_t **gamedir_callbacks;
|
|||
static int num_gamedir_callbacks;
|
||||
static int max_gamedir_callbacks;
|
||||
|
||||
static searchpath_t *
|
||||
new_searchpath (void)
|
||||
{
|
||||
searchpath_t *searchpath;
|
||||
ALLOC (16, searchpath_t, searchpaths, searchpath);
|
||||
return searchpath;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_searchpath (searchpath_t *searchpath)
|
||||
{
|
||||
if (searchpath->pack) {
|
||||
Qclose (searchpath->pack->handle);
|
||||
free (searchpath->pack->files);
|
||||
free (searchpath->pack);
|
||||
}
|
||||
if (searchpath->filename)
|
||||
free (searchpath->filename);
|
||||
FREE (searchpaths, searchpath);
|
||||
}
|
||||
|
||||
static vpath_t *
|
||||
new_vpath (void)
|
||||
{
|
||||
vpath_t *vpath;
|
||||
ALLOC (16, vpath_t, vpaths, vpath);
|
||||
return vpath;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_vpath (vpath_t *vpath)
|
||||
{
|
||||
searchpath_t *next;
|
||||
|
||||
if (vpath->name)
|
||||
free (vpath->name);
|
||||
while (vpath->user) {
|
||||
next = vpath->user->next;
|
||||
delete_searchpath (vpath->user);
|
||||
vpath->user = next;
|
||||
}
|
||||
while (vpath->share) {
|
||||
next = vpath->share->next;
|
||||
delete_searchpath (vpath->share);
|
||||
vpath->share = next;
|
||||
}
|
||||
FREE (vpaths, vpath);
|
||||
}
|
||||
|
||||
static const char *
|
||||
qfs_var_get_key (const void *_v, void *unused)
|
||||
{
|
||||
|
@ -448,18 +524,22 @@ qfs_process_path (const char *path, const char *gamedir)
|
|||
{
|
||||
const char *e = path + strlen (path);
|
||||
const char *s = e;
|
||||
dstring_t *dir = dstring_new ();
|
||||
char *dir;
|
||||
vpath_t *vpath;
|
||||
|
||||
while (s >= path) {
|
||||
while (s != path && s[-1] !=':')
|
||||
s--;
|
||||
if (s != e) {
|
||||
dsprintf (dir, "%.*s", (int) (e - s), s);
|
||||
qfs_add_gamedir (dir->str);
|
||||
dir = nva ("%.*s", (int) (e - s), s);
|
||||
vpath = new_vpath ();
|
||||
vpath->name = dir;
|
||||
qfs_add_gamedir (vpath, dir);
|
||||
vpath->next = qfs_vpaths;
|
||||
qfs_vpaths = vpath;
|
||||
}
|
||||
e = --s;
|
||||
}
|
||||
dstring_delete (dir);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -497,20 +577,10 @@ qfs_build_gamedir (const char **list)
|
|||
free (qfs_gamedir);
|
||||
}
|
||||
|
||||
while (qfs_searchpaths) {
|
||||
searchpath_t *next;
|
||||
|
||||
if (qfs_searchpaths->pack) {
|
||||
Qclose (qfs_searchpaths->pack->handle);
|
||||
free (qfs_searchpaths->pack->files);
|
||||
free (qfs_searchpaths->pack);
|
||||
}
|
||||
if (qfs_searchpaths->filename)
|
||||
free (qfs_searchpaths->filename);
|
||||
|
||||
next = qfs_searchpaths->next;
|
||||
free (qfs_searchpaths);
|
||||
qfs_searchpaths = next;
|
||||
while (qfs_vpaths) {
|
||||
vpath_t *next = qfs_vpaths->next;
|
||||
delete_vpath (qfs_vpaths);
|
||||
qfs_vpaths = next;
|
||||
}
|
||||
|
||||
for (j = 0; list[j]; j++)
|
||||
|
@ -688,19 +758,31 @@ QFS_FileBase (const char *in)
|
|||
return out;
|
||||
}
|
||||
|
||||
static void
|
||||
qfs_path_print (searchpath_t *sp)
|
||||
{
|
||||
if (sp->pack) {
|
||||
Sys_Printf ("%s (%i files)\n", sp->pack->filename, sp->pack->numfiles);
|
||||
} else {
|
||||
Sys_Printf ("%s\n", sp->filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
qfs_path_f (void)
|
||||
{
|
||||
searchpath_t *s;
|
||||
vpath_t *vp;
|
||||
searchpath_t *sp;
|
||||
|
||||
Sys_Printf ("Current search path:\n");
|
||||
for (s = qfs_searchpaths; s; s = s->next) {
|
||||
if (s->pack)
|
||||
Sys_Printf ("%s (%i files)\n", s->pack->filename,
|
||||
s->pack->numfiles);
|
||||
else
|
||||
Sys_Printf ("%s\n", s->filename);
|
||||
for (vp = qfs_vpaths; vp; vp = vp->next) {
|
||||
Sys_Printf ("%s\n", vp->name);
|
||||
for (sp = vp->user; sp; sp = sp->next) {
|
||||
qfs_path_print (sp);
|
||||
}
|
||||
for (sp = vp->share; sp; sp = sp->next) {
|
||||
qfs_path_print (sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,6 +800,128 @@ QFS_WriteFile (const char *filename, const void *data, int len)
|
|||
Qclose (f);
|
||||
}
|
||||
|
||||
static int_findfile_t *
|
||||
qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp,
|
||||
const char **fnames)
|
||||
{
|
||||
static int_findfile_t found;
|
||||
const char **fn;
|
||||
|
||||
found.ff.vpath = 0;
|
||||
found.ff.in_pak = false;
|
||||
found.pack = 0;
|
||||
found.packfile = 0;
|
||||
found.fname_index = 0;
|
||||
if (found.ff.realname) {
|
||||
free ((char *) found.ff.realname);
|
||||
found.ff.realname = 0;
|
||||
}
|
||||
if (found.path) {
|
||||
free ((char *) found.path);
|
||||
found.path = 0;
|
||||
}
|
||||
// is the element a pak file?
|
||||
if (sp->pack) {
|
||||
dpackfile_t *packfile = 0;
|
||||
|
||||
for (fn = fnames; *fn; fn++) {
|
||||
packfile = pack_find_file (sp->pack, *fn);
|
||||
if (packfile) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (packfile) {
|
||||
Sys_MaskPrintf (SYS_FS_F, "PackFile: %s : %s\n",
|
||||
sp->pack->filename, packfile->name);
|
||||
found.ff.vpath = vpath;
|
||||
found.ff.in_pak = true;
|
||||
found.ff.realname = strdup (*fn);
|
||||
found.pack = sp->pack;
|
||||
found.packfile = packfile;
|
||||
found.fname_index = fn - fnames;
|
||||
found.path = strdup (sp->pack->filename);
|
||||
return &found;
|
||||
}
|
||||
} else {
|
||||
// check a file in the directory tree
|
||||
dstring_t *path = dstring_new ();
|
||||
|
||||
for (fn = fnames; *fn; fn++) {
|
||||
if (qfs_expand_path (path, sp->filename, *fn, 1) == 0) {
|
||||
if (Sys_FileExists (path->str) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Sys_MaskPrintf (SYS_FS_F, "FindFile: %s\n", path->str);
|
||||
|
||||
found.ff.vpath = vpath;
|
||||
found.ff.in_pak = false;
|
||||
found.ff.realname = strdup (*fn);
|
||||
found.path = strdup (path->str);
|
||||
found.fname_index = fn - fnames;
|
||||
return &found;
|
||||
}
|
||||
}
|
||||
dstring_delete (path);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int_findfile_t *
|
||||
qfs_findfile (const char **fnames, const vpath_t *start, const vpath_t *end)
|
||||
{
|
||||
const vpath_t *vp;
|
||||
searchpath_t *sp;
|
||||
int_findfile_t *found;
|
||||
|
||||
if (!start) {
|
||||
start = qfs_vpaths;
|
||||
}
|
||||
if (end) {
|
||||
for (vp = start; vp; vp = vp->next) {
|
||||
if (vp == end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!vp) {
|
||||
Sys_Error ("QFS_FindFile: end vpath not in search list");
|
||||
}
|
||||
end = end->next;
|
||||
}
|
||||
for (vp = start; vp && vp != end; vp = vp->next) {
|
||||
for (sp = vp->user; sp; sp = sp->next) {
|
||||
found = qfs_findfile_search (vp, sp, fnames);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
for (sp = vp->share; sp; sp = sp->next) {
|
||||
found = qfs_findfile_search (vp, sp, fnames);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
// file not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
VISIBLE findfile_t *
|
||||
QFS_FindFile (const char *fname, const vpath_t *start, const vpath_t *end)
|
||||
{
|
||||
int_findfile_t *found;
|
||||
const char *fname_list[2];
|
||||
|
||||
fname_list[0] = fname;
|
||||
fname_list[1] = 0;
|
||||
|
||||
found = qfs_findfile (fname_list, start, end);
|
||||
if (found) {
|
||||
return &found->ff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QFile *
|
||||
qfs_openread (const char *path, int offs, int len, int zip)
|
||||
{
|
||||
|
@ -805,7 +1009,7 @@ QFS_CompressPath (const char *pth)
|
|||
return path;
|
||||
}
|
||||
|
||||
VISIBLE int file_from_pak; // global indicating file came from pack file ZOID
|
||||
VISIBLE findfile_t qfs_foundfile;
|
||||
|
||||
/*
|
||||
QFS_FOpenFile
|
||||
|
@ -814,69 +1018,29 @@ VISIBLE int file_from_pak; // global indicating file came from pack file ZOID
|
|||
Sets qfs_filesize and one of handle or file
|
||||
*/
|
||||
|
||||
static int
|
||||
open_file (searchpath_t *search, const char *filename, QFile **gzfile,
|
||||
dstring_t *foundname, int zip)
|
||||
static void
|
||||
open_file (int_findfile_t *found, QFile **gzfile, int zip)
|
||||
{
|
||||
file_from_pak = 0;
|
||||
|
||||
// is the element a pak file?
|
||||
if (search->pack) {
|
||||
dpackfile_t *packfile;
|
||||
|
||||
packfile = pack_find_file (search->pack, filename);
|
||||
if (packfile) {
|
||||
Sys_MaskPrintf (SYS_FS_F, "PackFile: %s : %s\n",
|
||||
search->pack->filename, packfile->name);
|
||||
// open a new file on the pakfile
|
||||
if (foundname) {
|
||||
dstring_clearstr (foundname);
|
||||
dstring_appendstr (foundname, packfile->name);
|
||||
}
|
||||
*gzfile = qfs_openread (search->pack->filename, packfile->filepos,
|
||||
packfile->filelen, zip);
|
||||
file_from_pak = 1;
|
||||
return qfs_filesize;
|
||||
}
|
||||
qfs_foundfile = found->ff;
|
||||
if (found->ff.in_pak) {
|
||||
*gzfile = qfs_openread (found->pack->filename,
|
||||
found->packfile->filepos,
|
||||
found->packfile->filelen, zip);
|
||||
} else {
|
||||
// check a file in the directory tree
|
||||
dstring_t *netpath = dstring_new ();
|
||||
|
||||
if (qfs_expand_path (netpath, search->filename, filename, 1) == 0) {
|
||||
if (foundname) {
|
||||
dstring_clearstr (foundname);
|
||||
dstring_appendstr (foundname, filename);
|
||||
}
|
||||
if (Sys_FileTime (netpath->str) == -1) {
|
||||
dstring_delete (netpath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Sys_MaskPrintf (SYS_FS_F, "FindFile: %s\n", netpath->str);
|
||||
|
||||
*gzfile = qfs_openread (netpath->str, -1, -1, zip);
|
||||
dstring_delete (netpath);
|
||||
return qfs_filesize;
|
||||
}
|
||||
dstring_delete (netpath);
|
||||
return -1;
|
||||
*gzfile = qfs_openread (found->path, -1, -1, zip);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
VISIBLE int
|
||||
_QFS_FOpenFile (const char *filename, QFile **gzfile,
|
||||
dstring_t *foundname, int zip)
|
||||
VISIBLE QFile *
|
||||
_QFS_VOpenFile (const char *filename, int zip,
|
||||
const vpath_t *start, const vpath_t *end)
|
||||
{
|
||||
searchpath_t *search;
|
||||
QFile *gzfile;
|
||||
int_findfile_t *found;
|
||||
char *path;
|
||||
#ifdef HAVE_VORBIS
|
||||
char *oggfilename;
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB
|
||||
char *gzfilename;
|
||||
#endif
|
||||
const char *fnames[4];
|
||||
int zip_flags[3];
|
||||
int ind;
|
||||
|
||||
// make sure they're not trying to do weird stuff with our private files
|
||||
path = QFS_CompressPath (filename);
|
||||
|
@ -887,57 +1051,70 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile,
|
|||
goto error;
|
||||
}
|
||||
|
||||
ind = 0;
|
||||
#ifdef HAVE_VORBIS
|
||||
if (strequal (".wav", QFS_FileExtension (path))) {
|
||||
char *oggfilename;
|
||||
oggfilename = alloca (strlen (path) + 1);
|
||||
QFS_StripExtension (path, oggfilename);
|
||||
strncat (oggfilename, ".ogg",
|
||||
sizeof (oggfilename) - strlen (oggfilename) - 1);
|
||||
} else {
|
||||
oggfilename = 0;
|
||||
fnames[ind] = oggfilename;
|
||||
zip_flags[ind] = 0;
|
||||
ind++;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB
|
||||
gzfilename = alloca (strlen (path) + 3 + 1);
|
||||
sprintf (gzfilename, "%s.gz", path);
|
||||
{
|
||||
char *gzfilename;
|
||||
gzfilename = alloca (strlen (path) + 3 + 1);
|
||||
sprintf (gzfilename, "%s.gz", path);
|
||||
fnames[ind] = gzfilename;
|
||||
zip_flags[ind] = zip;
|
||||
ind++;
|
||||
}
|
||||
#endif
|
||||
|
||||
// search through the path, one element at a time
|
||||
for (search = qfs_searchpaths; search; search = search->next) {
|
||||
#ifdef HAVE_VORBIS
|
||||
//NOTE gzipped oggs not supported
|
||||
if (oggfilename
|
||||
&& open_file (search, oggfilename, gzfile, foundname, false) != -1)
|
||||
goto ok;
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB
|
||||
if (open_file (search, gzfilename, gzfile, foundname, zip) != -1)
|
||||
goto ok;
|
||||
#endif
|
||||
if (open_file (search, path, gzfile, foundname, zip) != -1)
|
||||
goto ok;
|
||||
fnames[ind] = path;
|
||||
zip_flags[ind] = zip;
|
||||
ind++;
|
||||
|
||||
fnames[ind] = 0;
|
||||
|
||||
found = qfs_findfile (fnames, start, end);
|
||||
|
||||
if (found) {
|
||||
open_file (found, &gzfile, zip_flags[found->fname_index]);
|
||||
free(path);
|
||||
return gzfile;
|
||||
}
|
||||
|
||||
Sys_MaskPrintf (SYS_FS_NF, "FindFile: can't find %s\n", filename);
|
||||
error:
|
||||
*gzfile = NULL;
|
||||
qfs_filesize = -1;
|
||||
free (path);
|
||||
return -1;
|
||||
ok:
|
||||
free(path);
|
||||
return qfs_filesize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
VISIBLE int
|
||||
QFS_FOpenFile (const char *filename, QFile **gzfile)
|
||||
VISIBLE QFile *
|
||||
QFS_VOpenFile (const char *filename, const vpath_t *start, const vpath_t *end)
|
||||
{
|
||||
return _QFS_FOpenFile (filename, gzfile, 0, 1);
|
||||
return _QFS_VOpenFile (filename, 1, start, end);
|
||||
}
|
||||
|
||||
cache_user_t *loadcache;
|
||||
byte *loadbuf;
|
||||
int loadsize;
|
||||
VISIBLE QFile *
|
||||
_QFS_FOpenFile (const char *filename, int zip)
|
||||
{
|
||||
return _QFS_VOpenFile (filename, zip, 0, 0);
|
||||
}
|
||||
|
||||
VISIBLE QFile *
|
||||
QFS_FOpenFile (const char *filename)
|
||||
{
|
||||
return _QFS_VOpenFile (filename, 1, 0, 0);
|
||||
}
|
||||
|
||||
static cache_user_t *loadcache;
|
||||
|
||||
/*
|
||||
QFS_LoadFile
|
||||
|
@ -946,20 +1123,22 @@ int loadsize;
|
|||
Always appends a 0 byte to the loaded data.
|
||||
*/
|
||||
VISIBLE byte *
|
||||
QFS_LoadFile (const char *path, int usehunk)
|
||||
QFS_LoadFile (QFile *file, int usehunk)
|
||||
{
|
||||
QFile *h;
|
||||
byte *buf = NULL;
|
||||
char *base;
|
||||
int len;
|
||||
|
||||
// look for it in the filesystem or pack files
|
||||
len = qfs_filesize = QFS_FOpenFile (path, &h);
|
||||
if (!h)
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
base = strdup ("QFS_LoadFile");
|
||||
|
||||
len = qfs_filesize = Qfilesize (file);
|
||||
|
||||
// extract the filename base name for hunk tag
|
||||
base = QFS_FileBase (path);
|
||||
//base = QFS_FileBase (path);
|
||||
|
||||
if (usehunk == 1)
|
||||
buf = Hunk_AllocName (len + 1, base);
|
||||
|
@ -969,20 +1148,16 @@ QFS_LoadFile (const char *path, int usehunk)
|
|||
buf = calloc (1, len + 1);
|
||||
else if (usehunk == 3)
|
||||
buf = Cache_Alloc (loadcache, len + 1, base);
|
||||
else if (usehunk == 4) {
|
||||
if (len + 1 > loadsize)
|
||||
buf = Hunk_TempAlloc (len + 1);
|
||||
else
|
||||
buf = loadbuf;
|
||||
} else
|
||||
else
|
||||
Sys_Error ("QFS_LoadFile: bad usehunk");
|
||||
|
||||
if (!buf)
|
||||
Sys_Error ("QFS_LoadFile: not enough space for %s", path);
|
||||
Sys_Error ("QFS_LoadFile: not enough space");
|
||||
//Sys_Error ("QFS_LoadFile: not enough space for %s", path);
|
||||
|
||||
buf[len] = 0;
|
||||
Qread (h, buf, len);
|
||||
Qclose (h);
|
||||
Qread (file, buf, len);
|
||||
Qclose (file);
|
||||
|
||||
free (base);
|
||||
|
||||
|
@ -990,29 +1165,16 @@ QFS_LoadFile (const char *path, int usehunk)
|
|||
}
|
||||
|
||||
VISIBLE byte *
|
||||
QFS_LoadHunkFile (const char *path)
|
||||
QFS_LoadHunkFile (QFile *file)
|
||||
{
|
||||
return QFS_LoadFile (path, 1);
|
||||
return QFS_LoadFile (file, 1);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
QFS_LoadCacheFile (const char *path, struct cache_user_s *cu)
|
||||
QFS_LoadCacheFile (QFile *file, struct cache_user_s *cu)
|
||||
{
|
||||
loadcache = cu;
|
||||
QFS_LoadFile (path, 3);
|
||||
}
|
||||
|
||||
// uses temp hunk if larger than bufsize
|
||||
VISIBLE byte *
|
||||
QFS_LoadStackFile (const char *path, void *buffer, int bufsize)
|
||||
{
|
||||
byte *buf;
|
||||
|
||||
loadbuf = (byte *) buffer;
|
||||
loadsize = bufsize;
|
||||
buf = QFS_LoadFile (path, 4);
|
||||
|
||||
return buf;
|
||||
QFS_LoadFile (file, 3);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1070,9 +1232,9 @@ qfs_file_sort (char **os1, char **os2)
|
|||
}
|
||||
|
||||
static void
|
||||
qfs_load_gamedir (const char *dir)
|
||||
qfs_load_gamedir (searchpath_t **searchpath, const char *dir)
|
||||
{
|
||||
searchpath_t *search;
|
||||
searchpath_t *sp;
|
||||
pack_t *pak;
|
||||
DIR *dir_ptr;
|
||||
struct dirent *dirent;
|
||||
|
@ -1126,11 +1288,10 @@ qfs_load_gamedir (const char *dir)
|
|||
if (!pak) {
|
||||
Sys_Error ("Bad pakfile %s!!", pakfiles[i]);
|
||||
} else {
|
||||
search = malloc (sizeof (searchpath_t));
|
||||
search->filename = 0;
|
||||
search->pack = pak;
|
||||
search->next = qfs_searchpaths;
|
||||
qfs_searchpaths = search;
|
||||
sp = new_searchpath ();
|
||||
sp->pack = pak;
|
||||
sp->next = *searchpath;
|
||||
*searchpath = sp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1147,23 +1308,22 @@ qfs_load_gamedir (const char *dir)
|
|||
pak1.pak ...
|
||||
*/
|
||||
static void
|
||||
qfs_add_dir (const char *dir)
|
||||
qfs_add_dir (searchpath_t **searchpath, const char *dir)
|
||||
{
|
||||
searchpath_t *search;
|
||||
searchpath_t *sp;
|
||||
|
||||
// add the directory to the search path
|
||||
search = malloc (sizeof (searchpath_t));
|
||||
search->filename = strdup (dir);
|
||||
search->pack = 0;
|
||||
search->next = qfs_searchpaths;
|
||||
qfs_searchpaths = search;
|
||||
sp = new_searchpath ();
|
||||
sp->filename = strdup (dir);
|
||||
sp->next = *searchpath;
|
||||
*searchpath = sp;
|
||||
|
||||
// add any pak files in the format pak0.pak pak1.pak, ...
|
||||
qfs_load_gamedir (dir);
|
||||
qfs_load_gamedir (searchpath, dir);
|
||||
}
|
||||
|
||||
static void
|
||||
qfs_add_gamedir (const char *dir)
|
||||
qfs_add_gamedir (vpath_t *vpath, const char *dir)
|
||||
{
|
||||
const char *e;
|
||||
const char *s;
|
||||
|
@ -1190,7 +1350,7 @@ qfs_add_gamedir (const char *dir)
|
|||
Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n",
|
||||
f_dir->str);
|
||||
|
||||
qfs_add_dir (f_dir->str);
|
||||
qfs_add_dir (&vpath->share, f_dir->str);
|
||||
}
|
||||
}
|
||||
e = --s;
|
||||
|
@ -1198,7 +1358,7 @@ qfs_add_gamedir (const char *dir)
|
|||
|
||||
qfs_expand_userpath (f_dir, dir);
|
||||
Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n", f_dir->str);
|
||||
qfs_add_dir (f_dir->str);
|
||||
qfs_add_dir (&vpath->user, f_dir->str);
|
||||
|
||||
dstring_delete (f_dir);
|
||||
dstring_delete (s_dir);
|
||||
|
@ -1399,7 +1559,7 @@ QFS_NextFilename (dstring_t *filename, const char *prefix, const char *ext)
|
|||
|
||||
if (qfs_expand_userpath (full_path, filename->str) == -1)
|
||||
break;
|
||||
if (Sys_FileTime (full_path->str) == -1) {
|
||||
if (Sys_FileExists (full_path->str) == -1) {
|
||||
// file doesn't exist, so we can use this name
|
||||
ret = 1;
|
||||
break;
|
||||
|
@ -1506,45 +1666,57 @@ QFS_FilelistAdd (filelist_t *filelist, const char *fname, const char *ext)
|
|||
filelist->list[filelist->count++] = str;
|
||||
}
|
||||
|
||||
static void
|
||||
qfs_filelistfill_do (filelist_t *list, const searchpath_t *search, const char *cp, const char *ext, int strip)
|
||||
{
|
||||
const char *separator = "/";
|
||||
|
||||
if (*cp && cp[strlen (cp) - 1] == '/')
|
||||
separator = "";
|
||||
|
||||
if (search->pack) {
|
||||
int i;
|
||||
pack_t *pak = search->pack;
|
||||
|
||||
for (i = 0; i < pak->numfiles; i++) {
|
||||
char *name = pak->files[i].name;
|
||||
if (!fnmatch (va("%s%s*.%s", cp, separator, ext), name,
|
||||
FNM_PATHNAME)
|
||||
|| !fnmatch (va("%s%s*.%s.gz", cp, separator, ext), name,
|
||||
FNM_PATHNAME))
|
||||
QFS_FilelistAdd (list, name, strip ? ext : 0);
|
||||
}
|
||||
} else {
|
||||
DIR *dir_ptr;
|
||||
struct dirent *dirent;
|
||||
|
||||
dir_ptr = opendir (va ("%s/%s", search->filename, cp));
|
||||
if (!dir_ptr)
|
||||
return;
|
||||
while ((dirent = readdir (dir_ptr)))
|
||||
if (!fnmatch (va("*.%s", ext), dirent->d_name, 0)
|
||||
|| !fnmatch (va("*.%s.gz", ext), dirent->d_name, 0))
|
||||
QFS_FilelistAdd (list, dirent->d_name, strip ? ext : 0);
|
||||
closedir (dir_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
QFS_FilelistFill (filelist_t *list, const char *path, const char *ext,
|
||||
int strip)
|
||||
{
|
||||
vpath_t *vpath;
|
||||
searchpath_t *search;
|
||||
DIR *dir_ptr;
|
||||
struct dirent *dirent;
|
||||
char *cpath, *cp;
|
||||
const char *separator = "/";
|
||||
|
||||
if (strchr (ext, '/') || strchr (ext, '\\'))
|
||||
return;
|
||||
|
||||
cp = cpath = QFS_CompressPath (path);
|
||||
if (*cp && cp[strlen (cp) - 1] == '/')
|
||||
separator = "";
|
||||
|
||||
for (search = qfs_searchpaths; search != NULL; search = search->next) {
|
||||
if (search->pack) {
|
||||
int i;
|
||||
pack_t *pak = search->pack;
|
||||
|
||||
for (i = 0; i < pak->numfiles; i++) {
|
||||
char *name = pak->files[i].name;
|
||||
if (!fnmatch (va("%s%s*.%s", cp, separator, ext), name,
|
||||
FNM_PATHNAME)
|
||||
|| !fnmatch (va("%s%s*.%s.gz", cp, separator, ext), name,
|
||||
FNM_PATHNAME))
|
||||
QFS_FilelistAdd (list, name, strip ? ext : 0);
|
||||
}
|
||||
} else {
|
||||
dir_ptr = opendir (va ("%s/%s", search->filename, cp));
|
||||
if (!dir_ptr)
|
||||
continue;
|
||||
while ((dirent = readdir (dir_ptr)))
|
||||
if (!fnmatch (va("*.%s", ext), dirent->d_name, 0)
|
||||
|| !fnmatch (va("*.%s.gz", ext), dirent->d_name, 0))
|
||||
QFS_FilelistAdd (list, dirent->d_name, strip ? ext : 0);
|
||||
closedir (dir_ptr);
|
||||
for (vpath = qfs_vpaths; vpath; vpath = vpath->next) {
|
||||
for (search = vpath->user; search; search = search->next) {
|
||||
qfs_filelistfill_do (list, search, cp, ext, strip);
|
||||
}
|
||||
}
|
||||
free (cpath);
|
||||
|
|
|
@ -383,9 +383,7 @@ Qprintf (QFile *file, const char *fmt, ...)
|
|||
if (!buf)
|
||||
buf = dstring_new ();
|
||||
|
||||
va_start (args, fmt);
|
||||
dvsprintf (buf, fmt, args);
|
||||
va_end (args);
|
||||
ret = strlen (buf->str);
|
||||
if (ret > 0)
|
||||
ret = gzwrite (file->gzfile, buf, (unsigned) ret);
|
||||
|
|
215
libs/util/segtext.c
Normal file
215
libs/util/segtext.c
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
segtext.c
|
||||
|
||||
Segmented text file handling
|
||||
|
||||
Copyright (C) 2013 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2013/02/26
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "QF/alloc.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/qtypes.h"
|
||||
#include "QF/segtext.h"
|
||||
|
||||
static segchunk_t *chunks_freelist;
|
||||
static segtext_t *texts_freelist;
|
||||
|
||||
static segchunk_t *
|
||||
new_chunk (void)
|
||||
{
|
||||
segchunk_t *chunk;
|
||||
ALLOC (64, segchunk_t, chunks, chunk);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_chunk (segchunk_t *chunk)
|
||||
{
|
||||
FREE (chunks, chunk);
|
||||
}
|
||||
|
||||
static segtext_t *
|
||||
new_text (void)
|
||||
{
|
||||
segtext_t *text;
|
||||
ALLOC (64, segtext_t, texts, text);
|
||||
return text;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_text (segtext_t *text)
|
||||
{
|
||||
FREE (texts, text);
|
||||
}
|
||||
|
||||
static const char *
|
||||
segtext_getkey (const void *sc, void *unused)
|
||||
{
|
||||
segchunk_t *chunk = (segchunk_t *) sc;
|
||||
if (!chunk->tag)
|
||||
return "";
|
||||
return chunk->tag;
|
||||
}
|
||||
|
||||
static char *
|
||||
next_line (char *src, int *line)
|
||||
{
|
||||
while (*src && *src != '\n')
|
||||
src++;
|
||||
if (*src == '\n') {
|
||||
*line += 1;
|
||||
src++;
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
static char *
|
||||
next_chunk (char *src, int *line)
|
||||
{
|
||||
while (*src) {
|
||||
// chunks begin on a line that starts with --
|
||||
if (src[0] == '-' && src[1] == '-')
|
||||
return src;
|
||||
src = next_line (src, line);
|
||||
}
|
||||
// no next chunk
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
is_tag_char (char ch)
|
||||
{
|
||||
return isalnum ((byte) ch) || ch == '.' || ch == '_';
|
||||
}
|
||||
|
||||
static char *
|
||||
find_tag (const char *src)
|
||||
{
|
||||
const char *end;
|
||||
char *tag;
|
||||
|
||||
while (*src && *src != '\n' && !is_tag_char (*src))
|
||||
src++;
|
||||
|
||||
for (end = src; is_tag_char (*end); end++)
|
||||
;
|
||||
if (end == src)
|
||||
return 0;
|
||||
|
||||
tag = malloc (end - src + 1);
|
||||
strncpy (tag, src, end - src);
|
||||
tag[end - src] = 0;
|
||||
return tag;
|
||||
}
|
||||
|
||||
VISIBLE segtext_t *
|
||||
Segtext_new (const char *source_string)
|
||||
{
|
||||
segchunk_t **chunk;
|
||||
segtext_t *text;
|
||||
char *src;
|
||||
int line = 1;
|
||||
|
||||
if (!source_string)
|
||||
return 0;
|
||||
text = new_text ();
|
||||
text->tab = Hash_NewTable (61, segtext_getkey, 0, 0);
|
||||
|
||||
src = strdup (source_string);
|
||||
// The first chunk is special in that it holds the pointer to the copied
|
||||
// string data. The chunk itself has no name and may be empty.
|
||||
chunk = &text->chunk_list;
|
||||
*chunk = new_chunk ();
|
||||
(*chunk)->tag = 0;
|
||||
(*chunk)->text = src;
|
||||
(*chunk)->start_line = line;
|
||||
|
||||
chunk = &(*chunk)->next;
|
||||
|
||||
while ((src = next_chunk (src, &line))) {
|
||||
*src++ = 0; // terminate the previous chunk
|
||||
*chunk = new_chunk ();
|
||||
(*chunk)->tag = find_tag (src);
|
||||
src = next_line (src, &line);
|
||||
(*chunk)->text = src;
|
||||
(*chunk)->start_line = line;
|
||||
// If tags are duplicated, the first one takes precedence
|
||||
if ((*chunk)->tag && !Hash_Find (text->tab, (*chunk)->tag))
|
||||
Hash_Add (text->tab, *chunk);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Segtext_delete (segtext_t *st)
|
||||
{
|
||||
segchunk_t *chunk;
|
||||
|
||||
// the first chunk holds the pointer to the block holding all chunk data;
|
||||
free ((char *) st->chunk_list->text);
|
||||
while (st->chunk_list) {
|
||||
chunk = st->chunk_list;
|
||||
st->chunk_list = chunk->next;
|
||||
if (chunk->tag)
|
||||
free ((char *) chunk->tag);
|
||||
delete_chunk (chunk);
|
||||
}
|
||||
Hash_DelTable (st->tab);
|
||||
delete_text (st);
|
||||
}
|
||||
|
||||
const segchunk_t *
|
||||
Segtext_FindChunk (const segtext_t *st, const char *tag)
|
||||
{
|
||||
char *sub;
|
||||
char *dot;
|
||||
segchunk_t *chunk;
|
||||
|
||||
sub = alloca (strlen (tag) + 1);
|
||||
strcpy (sub, tag);
|
||||
do {
|
||||
chunk = Hash_Find (st->tab, sub);
|
||||
if (chunk)
|
||||
return chunk;
|
||||
dot = strrchr (sub, '.');
|
||||
if (dot)
|
||||
*dot = 0;
|
||||
} while (dot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
Segtext_Find (const segtext_t *st, const char *tag)
|
||||
{
|
||||
const segchunk_t *chunk = Segtext_FindChunk (st, tag);
|
||||
if (chunk)
|
||||
return chunk->text;
|
||||
return 0;
|
||||
}
|
181
libs/util/set.c
181
libs/util/set.c
|
@ -45,74 +45,113 @@
|
|||
#include "QF/mathlib.h"
|
||||
#include "QF/set.h"
|
||||
|
||||
#define BITS (sizeof (((set_t *) 0)->map[0]) * 8)
|
||||
|
||||
set_t *free_sets;
|
||||
set_iter_t *free_set_iters;
|
||||
static set_pool_t static_set_pool = {0, 0};
|
||||
|
||||
static set_iter_t *
|
||||
new_setiter (void)
|
||||
new_setiter (set_pool_t *set_pool)
|
||||
{
|
||||
set_iter_t *set_iter;
|
||||
ALLOC (16, set_iter_t, set_iters, set_iter);
|
||||
ALLOC (16, set_iter_t, set_pool->set_iter, set_iter);
|
||||
return set_iter;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_setiter (set_iter_t *set_iter)
|
||||
delete_setiter (set_pool_t *set_pool, set_iter_t *set_iter)
|
||||
{
|
||||
FREE (set_iters, set_iter);
|
||||
FREE (set_pool->set_iter, set_iter);
|
||||
}
|
||||
|
||||
void
|
||||
set_del_iter (set_iter_t *set_iter)
|
||||
{
|
||||
delete_setiter (set_iter);
|
||||
delete_setiter (&static_set_pool, set_iter);
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_new (void)
|
||||
void
|
||||
set_del_iter_r (set_pool_t *set_pool, set_iter_t *set_iter)
|
||||
{
|
||||
delete_setiter (set_pool, set_iter);
|
||||
}
|
||||
|
||||
void
|
||||
set_pool_init (set_pool_t *set_pool)
|
||||
{
|
||||
set_pool->set_freelist = 0;
|
||||
set_pool->set_iter_freelist = 0;
|
||||
}
|
||||
|
||||
inline set_t *
|
||||
set_new_r (set_pool_t *set_pool)
|
||||
{
|
||||
set_t *set;
|
||||
|
||||
ALLOC (16, set_t, sets, set);
|
||||
ALLOC (16, set_t, set_pool->set, set);
|
||||
set->size = sizeof (set->defmap) * 8;
|
||||
set->map = set->defmap;
|
||||
return set;
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_new (void)
|
||||
{
|
||||
return set_new_r (&static_set_pool);
|
||||
}
|
||||
|
||||
void
|
||||
set_delete (set_t *set)
|
||||
set_delete_r (set_pool_t *set_pool, set_t *set)
|
||||
{
|
||||
if (set->map != set->defmap)
|
||||
free (set->map);
|
||||
FREE (sets, set);
|
||||
FREE (set_pool->set, set);
|
||||
}
|
||||
|
||||
void
|
||||
set_delete (set_t *set)
|
||||
{
|
||||
set_delete_r (&static_set_pool, set);
|
||||
}
|
||||
|
||||
static void
|
||||
set_expand (set_t *set, unsigned x)
|
||||
{
|
||||
unsigned *map = set->map;
|
||||
set_bits_t *map = set->map;
|
||||
size_t size;
|
||||
|
||||
if (x <= set->size)
|
||||
return;
|
||||
|
||||
size = (x + BITS) & ~(BITS - 1);
|
||||
size = SET_SIZE (x);
|
||||
set->map = malloc (size / 8);
|
||||
memcpy (set->map, map, set->size / 8);
|
||||
memset (set->map + set->size / BITS, 0, (size - set->size) / 8);
|
||||
memset (set->map + SET_WORDS (set), 0, (size - set->size) / 8);
|
||||
set->size = size;
|
||||
if (map != set->defmap)
|
||||
free (map);
|
||||
}
|
||||
|
||||
inline set_t *
|
||||
set_new_size_r (set_pool_t *set_pool, int size)
|
||||
{
|
||||
set_t *set;
|
||||
|
||||
set = set_new_r (set_pool);
|
||||
set_expand (set, size);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
set_t *
|
||||
set_new_size (int size)
|
||||
{
|
||||
return set_new_size_r (&static_set_pool, size);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_set_add (set_t *set, unsigned x)
|
||||
{
|
||||
if (x >= set->size)
|
||||
set_expand (set, x + 1);
|
||||
set->map[x / BITS] |= 1 << (x % BITS);
|
||||
set->map[x / SET_BITS] |= SET_ONE << (x % SET_BITS);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -120,7 +159,7 @@ _set_remove (set_t *set, unsigned x)
|
|||
{
|
||||
if (x >= set->size)
|
||||
return;
|
||||
set->map[x / BITS] &= ~(1 << (x % BITS));
|
||||
set->map[x / SET_BITS] &= ~(SET_ONE << (x % SET_BITS));
|
||||
}
|
||||
|
||||
set_t *
|
||||
|
@ -158,7 +197,7 @@ _set_union (set_t *dst, const set_t *src)
|
|||
|
||||
size = max (dst->size, src->size);
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (src); i++)
|
||||
dst->map[i] |= src->map[i];
|
||||
return dst;
|
||||
}
|
||||
|
@ -171,9 +210,9 @@ _set_intersection (set_t *dst, const set_t *src)
|
|||
|
||||
size = max (dst->size, src->size);
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (src); i++)
|
||||
dst->map[i] &= src->map[i];
|
||||
for ( ; i < dst->size / BITS; i++)
|
||||
for ( ; i < SET_WORDS (dst); i++)
|
||||
dst->map[i] = 0;
|
||||
return dst;
|
||||
}
|
||||
|
@ -186,7 +225,7 @@ _set_difference (set_t *dst, const set_t *src)
|
|||
|
||||
size = max (dst->size, src->size);
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (src); i++)
|
||||
dst->map[i] &= ~src->map[i];
|
||||
return dst;
|
||||
}
|
||||
|
@ -199,7 +238,7 @@ _set_reverse_difference (set_t *dst, const set_t *src)
|
|||
|
||||
size = max (dst->size, src->size);
|
||||
set_expand (dst, size);
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (src); i++)
|
||||
dst->map[i] = ~dst->map[i] & src->map[i];
|
||||
return dst;
|
||||
}
|
||||
|
@ -275,9 +314,9 @@ set_assign (set_t *dst, const set_t *src)
|
|||
size = max (dst->size, src->size);
|
||||
set_expand (dst, size);
|
||||
dst->inverted = src->inverted;
|
||||
for (i = 0; i < src->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (src); i++)
|
||||
dst->map[i] = src->map[i];
|
||||
for ( ; i < dst->size / BITS; i++)
|
||||
for ( ; i < SET_WORDS (dst); i++)
|
||||
dst->map[i] = 0;
|
||||
return dst;
|
||||
}
|
||||
|
@ -288,7 +327,7 @@ set_empty (set_t *set)
|
|||
unsigned i;
|
||||
|
||||
set->inverted = 0;
|
||||
for (i = 0; i < set->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (set); i++)
|
||||
set->map[i] = 0;
|
||||
return set;
|
||||
}
|
||||
|
@ -299,7 +338,7 @@ set_everything (set_t *set)
|
|||
unsigned i;
|
||||
|
||||
set->inverted = 1;
|
||||
for (i = 0; i < set->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (set); i++)
|
||||
set->map[i] = 0;
|
||||
return set;
|
||||
}
|
||||
|
@ -309,7 +348,7 @@ _set_is_empty (const set_t *set)
|
|||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < set->size / BITS; i++)
|
||||
for (i = 0; i < SET_WORDS (set); i++)
|
||||
if (set->map[i])
|
||||
return 0;
|
||||
return 1;
|
||||
|
@ -335,21 +374,21 @@ static int
|
|||
set_test_n_n (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
unsigned i, end;
|
||||
unsigned intersection = 0;
|
||||
unsigned difference = 0;
|
||||
set_bits_t intersection = 0;
|
||||
set_bits_t difference = 0;
|
||||
|
||||
end = min (s1->size, s2->size) / BITS;
|
||||
end = min (s1->size, s2->size) / SET_BITS;
|
||||
for (i = 0; i < end; i++) {
|
||||
unsigned m1 = s1->map[i];
|
||||
unsigned m2 = s2->map[i];
|
||||
set_bits_t m1 = s1->map[i];
|
||||
set_bits_t m2 = s2->map[i];
|
||||
|
||||
intersection |= m1 & m2;
|
||||
difference |= m1 ^ m2;
|
||||
}
|
||||
for ( ; i < s1->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s1); i++) {
|
||||
difference |= s1->map[i];
|
||||
}
|
||||
for ( ; i < s2->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s2); i++) {
|
||||
difference |= s2->map[i];
|
||||
}
|
||||
return (difference != 0) | ((intersection != 0) << 1);
|
||||
|
@ -359,22 +398,22 @@ static int
|
|||
set_test_n_i (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
unsigned i, end;
|
||||
unsigned intersection = 0;
|
||||
unsigned difference = 0;
|
||||
set_bits_t intersection = 0;
|
||||
set_bits_t difference = 0;
|
||||
|
||||
end = min (s1->size, s2->size) / BITS;
|
||||
end = min (s1->size, s2->size) / SET_BITS;
|
||||
for (i = 0; i < end; i++) {
|
||||
unsigned m1 = s1->map[i];
|
||||
unsigned m2 = ~s2->map[i];
|
||||
set_bits_t m1 = s1->map[i];
|
||||
set_bits_t m2 = ~s2->map[i];
|
||||
|
||||
intersection |= m1 & m2;
|
||||
difference |= m1 ^ m2;
|
||||
}
|
||||
for ( ; i < s1->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s1); i++) {
|
||||
intersection |= s1->map[i];
|
||||
difference |= ~s1->map[i];
|
||||
}
|
||||
for ( ; i < s2->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s2); i++) {
|
||||
difference |= ~s2->map[i];
|
||||
}
|
||||
return (difference != 0) | ((intersection != 0) << 1);
|
||||
|
@ -384,21 +423,21 @@ static int
|
|||
set_test_i_n (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
unsigned i, end;
|
||||
unsigned intersection = 0;
|
||||
unsigned difference = 0;
|
||||
set_bits_t intersection = 0;
|
||||
set_bits_t difference = 0;
|
||||
|
||||
end = min (s1->size, s2->size) / BITS;
|
||||
end = min (s1->size, s2->size) / SET_BITS;
|
||||
for (i = 0; i < end; i++) {
|
||||
unsigned m1 = ~s1->map[i];
|
||||
unsigned m2 = s2->map[i];
|
||||
set_bits_t m1 = ~s1->map[i];
|
||||
set_bits_t m2 = s2->map[i];
|
||||
|
||||
intersection |= m1 & m2;
|
||||
difference |= m1 ^ m2;
|
||||
}
|
||||
for ( ; i < s1->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s1); i++) {
|
||||
difference |= ~s1->map[i];
|
||||
}
|
||||
for ( ; i < s2->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s2); i++) {
|
||||
intersection |= s2->map[i];
|
||||
difference |= ~s2->map[i];
|
||||
}
|
||||
|
@ -409,21 +448,21 @@ static int
|
|||
set_test_i_i (const set_t *s1, const set_t *s2)
|
||||
{
|
||||
unsigned i, end;
|
||||
unsigned intersection = 0;
|
||||
unsigned difference = 0;
|
||||
set_bits_t intersection = 0;
|
||||
set_bits_t difference = 0;
|
||||
|
||||
end = min (s1->size, s2->size) / BITS;
|
||||
end = min (s1->size, s2->size) / SET_BITS;
|
||||
for (i = 0; i < end; i++) {
|
||||
unsigned m1 = ~s1->map[i];
|
||||
unsigned m2 = ~s2->map[i];
|
||||
set_bits_t m1 = ~s1->map[i];
|
||||
set_bits_t m2 = ~s2->map[i];
|
||||
|
||||
intersection |= m1 & m2;
|
||||
difference |= m1 ^ m2;
|
||||
}
|
||||
for ( ; i < s1->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s1); i++) {
|
||||
difference |= ~s1->map[i];
|
||||
}
|
||||
for ( ; i < s2->size / BITS; i++) {
|
||||
for ( ; i < SET_WORDS (s2); i++) {
|
||||
intersection |= s2->map[i];
|
||||
difference |= ~s2->map[i];
|
||||
}
|
||||
|
@ -467,13 +506,13 @@ set_is_subset (const set_t *set, const set_t *sub)
|
|||
{
|
||||
unsigned i, end;
|
||||
|
||||
end = min (set->size, sub->size) / BITS;
|
||||
end = min (set->size, sub->size) / SET_BITS;
|
||||
if (set->inverted && sub->inverted) {
|
||||
for (i = 0; i < end; i++) {
|
||||
if (~sub->map[i] & set->map[i])
|
||||
return 0;
|
||||
}
|
||||
for ( ; i < set->size / BITS; i++)
|
||||
for ( ; i < SET_WORDS (set); i++)
|
||||
if (set->map[i])
|
||||
return 0;
|
||||
} else if (set->inverted) {
|
||||
|
@ -489,7 +528,7 @@ set_is_subset (const set_t *set, const set_t *sub)
|
|||
if (sub->map[i] & ~set->map[i])
|
||||
return 0;
|
||||
}
|
||||
for ( ; i < sub->size / BITS; i++)
|
||||
for ( ; i < SET_WORDS (sub); i++)
|
||||
if (sub->map[i])
|
||||
return 0;
|
||||
}
|
||||
|
@ -501,7 +540,7 @@ _set_is_member (const set_t *set, unsigned x)
|
|||
{
|
||||
if (x >= set->size)
|
||||
return 0;
|
||||
return (set->map[x / BITS] & (1 << (x % BITS))) != 0;
|
||||
return (set->map[x / SET_BITS] & (SET_ONE << (x % SET_BITS))) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -525,14 +564,14 @@ set_size (const set_t *set)
|
|||
}
|
||||
|
||||
set_iter_t *
|
||||
set_first (const set_t *set)
|
||||
set_first_r (set_pool_t *set_pool, const set_t *set)
|
||||
{
|
||||
unsigned x;
|
||||
set_iter_t *set_iter;
|
||||
|
||||
for (x = 0; x < set->size; x++) {
|
||||
if (_set_is_member (set, x)) {
|
||||
set_iter = new_setiter ();
|
||||
set_iter = new_setiter (set_pool);
|
||||
set_iter->set = set;
|
||||
set_iter->element = x;
|
||||
return set_iter;
|
||||
|
@ -542,7 +581,13 @@ set_first (const set_t *set)
|
|||
}
|
||||
|
||||
set_iter_t *
|
||||
set_next (set_iter_t *set_iter)
|
||||
set_first (const set_t *set)
|
||||
{
|
||||
return set_first_r (&static_set_pool, set);
|
||||
}
|
||||
|
||||
set_iter_t *
|
||||
set_next_r (set_pool_t *set_pool, set_iter_t *set_iter)
|
||||
{
|
||||
unsigned x;
|
||||
|
||||
|
@ -552,10 +597,16 @@ set_next (set_iter_t *set_iter)
|
|||
return set_iter;
|
||||
}
|
||||
}
|
||||
delete_setiter (set_iter);
|
||||
delete_setiter (set_pool, set_iter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_iter_t *
|
||||
set_next (set_iter_t *set_iter)
|
||||
{
|
||||
return set_next_r (&static_set_pool, set_iter);
|
||||
}
|
||||
|
||||
const char *
|
||||
set_as_string (const set_t *set)
|
||||
{
|
||||
|
|
130
libs/util/sys.c
130
libs/util/sys.c
|
@ -66,6 +66,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
|
@ -78,6 +79,7 @@
|
|||
|
||||
#include "qfalloca.h"
|
||||
|
||||
#include "QF/alloc.h"
|
||||
#include "QF/cmd.h"
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/dstring.h"
|
||||
|
@ -106,8 +108,17 @@ typedef struct shutdown_list_s {
|
|||
void (*func)(void);
|
||||
} shutdown_list_t;
|
||||
|
||||
typedef struct error_handler_s {
|
||||
struct error_handler_s *next;
|
||||
sys_error_t func;
|
||||
void *data;
|
||||
} error_handler_t;
|
||||
|
||||
static shutdown_list_t *shutdown_list;
|
||||
|
||||
static error_handler_t *error_handler_freelist;
|
||||
static error_handler_t *error_handler;
|
||||
|
||||
#ifndef _WIN32
|
||||
static int do_stdin = 1;
|
||||
qboolean stdin_ready;
|
||||
|
@ -160,6 +171,25 @@ Sys_MaskFPUExceptions (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
Sys_isdir (const char *path)
|
||||
{
|
||||
int res;
|
||||
#ifdef _WIN32
|
||||
struct _stat st;
|
||||
res = _stat (path, &st);
|
||||
#else
|
||||
struct stat st;
|
||||
res = stat (path, &st);
|
||||
#endif
|
||||
if (res < 0) {
|
||||
// assume any error means path does not refer to a directory. certainly
|
||||
// true if errno == ENOENT
|
||||
return 0;
|
||||
}
|
||||
return S_ISDIR (st.st_mode);
|
||||
}
|
||||
|
||||
int
|
||||
Sys_mkdir (const char *path)
|
||||
{
|
||||
|
@ -179,13 +209,11 @@ Sys_mkdir (const char *path)
|
|||
# error do not know how to make directories
|
||||
# endif
|
||||
#endif
|
||||
if (errno != EEXIST)
|
||||
return -1;
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
VISIBLE int
|
||||
Sys_FileTime (const char *path)
|
||||
Sys_FileExists (const char *path)
|
||||
{
|
||||
#ifdef HAVE_ACCESS
|
||||
if (access (path, R_OK) == 0)
|
||||
|
@ -287,8 +315,8 @@ Sys_MaskPrintf (int mask, const char *fmt, ...)
|
|||
va_end (args);
|
||||
}
|
||||
|
||||
VISIBLE double
|
||||
Sys_DoubleTime (void)
|
||||
VISIBLE int64_t
|
||||
Sys_LongTime (void)
|
||||
{
|
||||
static qboolean first = true;
|
||||
#ifdef _WIN32
|
||||
|
@ -314,13 +342,13 @@ Sys_DoubleTime (void)
|
|||
# else
|
||||
// MH's solution combining timeGetTime for stability and
|
||||
// QueryPerformanceCounter for precision.
|
||||
static __int64 qpcfreq = 0;
|
||||
static __int64 currqpccount = 0;
|
||||
static __int64 lastqpccount = 0;
|
||||
static double qpcfudge = 0;
|
||||
DWORD currtime = 0;
|
||||
static DWORD lasttime = 0;
|
||||
static DWORD starttime = 0;
|
||||
static int64_t qpcfreq = 0;
|
||||
static int64_t currqpccount = 0;
|
||||
static int64_t lastqpccount = 0;
|
||||
static int64_t qpcfudge = 0;
|
||||
int64_t currtime = 0;
|
||||
static int64_t lasttime = 0;
|
||||
static int64_t starttime = 0;
|
||||
|
||||
if (first) {
|
||||
timeBeginPeriod (1);
|
||||
|
@ -342,9 +370,8 @@ Sys_DoubleTime (void)
|
|||
|
||||
// store back times and calc a fudge factor as timeGetTime can
|
||||
// overshoot on a sub-millisecond scale
|
||||
qpcfudge = (((double) (currqpccount - lastqpccount)
|
||||
/ (double) qpcfreq))
|
||||
- ((double) (currtime - lasttime) * 0.001);
|
||||
qpcfudge = (( (currqpccount - lastqpccount) * 1000000 / qpcfreq))
|
||||
- ((currtime - lasttime) * 1000);
|
||||
lastqpccount = currqpccount;
|
||||
lasttime = currtime;
|
||||
} else {
|
||||
|
@ -352,19 +379,18 @@ Sys_DoubleTime (void)
|
|||
}
|
||||
|
||||
// the final time is the base from timeGetTime plus an addition from QPC
|
||||
return ((double) (currtime - starttime) * 0.001)
|
||||
+ ((double) (currqpccount - lastqpccount) / (double) qpcfreq)
|
||||
+ qpcfudge;
|
||||
return (((currtime - starttime) * 1000)
|
||||
+ ((currqpccount - lastqpccount) * 1000000 / qpcfreq) + qpcfudge);
|
||||
# endif
|
||||
#else
|
||||
struct timeval tp;
|
||||
struct timezone tzp;
|
||||
double now;
|
||||
static double start_time;
|
||||
int64_t now;
|
||||
static int64_t start_time;
|
||||
|
||||
gettimeofday (&tp, &tzp);
|
||||
|
||||
now = tp.tv_sec + tp.tv_usec / 1e6;
|
||||
now = tp.tv_sec * 1000000 + tp.tv_usec;
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
|
@ -375,6 +401,12 @@ Sys_DoubleTime (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
VISIBLE double
|
||||
Sys_DoubleTime (void)
|
||||
{
|
||||
return (__INT64_C (4294967296000000) + Sys_LongTime ()) / 1e6;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Sys_TimeOfDay (date_t *date)
|
||||
{
|
||||
|
@ -471,21 +503,36 @@ Sys_Quit (void)
|
|||
exit (0);
|
||||
}
|
||||
|
||||
#if defined (HAVE_VA_COPY)
|
||||
# define VA_COPY(a,b) va_copy (a, b)
|
||||
#elif defined (HAVE__VA_COPY)
|
||||
# define VA_COPY(a,b) __va_copy (a, b)
|
||||
#else
|
||||
# define VA_COPY(a,b) memcpy (a, b, sizeof (a))
|
||||
#endif
|
||||
VISIBLE void
|
||||
Sys_PushErrorHandler (sys_error_t func, void *data)
|
||||
{
|
||||
error_handler_t *eh;
|
||||
ALLOC (16, error_handler_t, error_handler, eh);
|
||||
eh->func = func;
|
||||
eh->data = data;
|
||||
eh->next = error_handler;
|
||||
error_handler = eh;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Sys_PopErrorHandler (void)
|
||||
{
|
||||
error_handler_t *eh;
|
||||
|
||||
if (!error_handler) {
|
||||
Sys_Error ("Sys_PopErrorHandler: no handler to pop");
|
||||
}
|
||||
eh = error_handler;
|
||||
error_handler = eh->next;
|
||||
FREE (error_handler, eh);
|
||||
}
|
||||
|
||||
|
||||
VISIBLE void
|
||||
Sys_Error (const char *error, ...)
|
||||
{
|
||||
va_list args;
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
va_list tmp_args;
|
||||
#endif
|
||||
static int in_sys_error = 0;
|
||||
|
||||
if (in_sys_error) {
|
||||
|
@ -499,20 +546,20 @@ Sys_Error (const char *error, ...)
|
|||
in_sys_error = 1;
|
||||
|
||||
va_start (args, error);
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
VA_COPY (tmp_args, args);
|
||||
#endif
|
||||
va_copy (tmp_args, args);
|
||||
sys_err_printf_function (error, args);
|
||||
va_end (args);
|
||||
|
||||
if (error_handler) {
|
||||
error_handler->func (error_handler->data);
|
||||
}
|
||||
|
||||
Sys_Shutdown ();
|
||||
|
||||
if (sys_err_printf_function != Sys_ErrPrintf) {
|
||||
// print the message again using the default error printer to increase
|
||||
// the chances of the error being seen.
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
VA_COPY (args, tmp_args);
|
||||
#endif
|
||||
va_copy (args, tmp_args);
|
||||
Sys_ErrPrintf (error, args);
|
||||
}
|
||||
|
||||
|
@ -849,10 +896,13 @@ Sys_CreatePath (const char *path)
|
|||
|
||||
strcpy (e_path, path);
|
||||
for (ofs = e_path + 1; *ofs; ofs++) {
|
||||
if (*ofs == '/') { // create the directory
|
||||
if (*ofs == '/') {
|
||||
*ofs = 0;
|
||||
if (Sys_mkdir (e_path) == -1)
|
||||
return -1;
|
||||
if (!Sys_isdir (e_path)) {
|
||||
// create the directory
|
||||
if (Sys_mkdir (e_path) == -1)
|
||||
return -1;
|
||||
}
|
||||
*ofs = '/';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
check_PROGRAMS= \
|
||||
test-dq test-half test-mat3 test-mat4 test-plist test-qfs test-quat \
|
||||
test-set test-vrect
|
||||
test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \
|
||||
test-qfs test-quat test-seb test-seg test-set test-vrect
|
||||
|
||||
test_bary_SOURCES=test-bary.c
|
||||
test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||
test_bary_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
||||
test_cs_SOURCES=test-cs.c
|
||||
test_cs_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||
test_cs_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
||||
test_dq_SOURCES=test-dq.c
|
||||
test_dq_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
@ -34,6 +42,14 @@ test_quat_SOURCES=test-quat.c
|
|||
test_quat_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||
test_quat_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
||||
test_seb_SOURCES=test-seb.c
|
||||
test_seb_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||
test_seb_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
||||
test_seg_SOURCES=test-seg.c
|
||||
test_seg_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||
test_seg_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
||||
test_set_SOURCES=test-set.c
|
||||
test_set_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||
test_set_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||
|
|
118
libs/util/test/test-bary.c
Normal file
118
libs/util/test/test-bary.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/mersenne.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
vec3_t points[] = {
|
||||
{-1, -1, 1},
|
||||
{ 1, 1, 1},
|
||||
{-1, 1, -1},
|
||||
{ 1, -1, -1},
|
||||
{-1, -1, -1},
|
||||
{ 1, 1, -1},
|
||||
{-1, 1, 1},
|
||||
{ 1, -1, 1},
|
||||
{ 0, 0, 0},
|
||||
};
|
||||
const vec_t *line[] = {points[0], points[1]};
|
||||
const vec_t *tri[] = {points[0], points[1], points[2]};
|
||||
const vec_t *tetra[] = {points[0], points[1], points[2], points[3]};
|
||||
|
||||
struct {
|
||||
const vec_t **points;
|
||||
int num_points;
|
||||
vec_t *x;
|
||||
vec_t expect[4];
|
||||
} tests[] = {
|
||||
{line, 2, points[0], {1, 0}},
|
||||
{line, 2, points[1], {0, 1}},
|
||||
{line, 2, points[2], {0.5, 0.5}},
|
||||
{line, 2, points[3], {0.5, 0.5}},
|
||||
{line, 2, points[8], {0.5, 0.5}},
|
||||
{tri, 3, points[0], {1, 0, 0}},
|
||||
{tri, 3, points[1], {0, 1, 0}},
|
||||
{tri, 3, points[2], {0, 0, 1}},
|
||||
{tri, 3, points[3], {0.333333284, 0.333333333, 0.333333333}},//rounding :P
|
||||
{tri, 3, points[8], {0.333333284, 0.333333333, 0.333333333}},//rounding :P
|
||||
{tetra, 4, points[0], {1, 0, 0, 0}},
|
||||
{tetra, 4, points[1], {0, 1, 0, 0}},
|
||||
{tetra, 4, points[2], {0, 0, 1, 0}},
|
||||
{tetra, 4, points[3], {0, 0, 0, 1}},
|
||||
{tetra, 4, points[4], { 0.5, -0.5, 0.5, 0.5}},
|
||||
{tetra, 4, points[5], {-0.5, 0.5, 0.5, 0.5}},
|
||||
{tetra, 4, points[6], { 0.5, 0.5, 0.5, -0.5}},
|
||||
{tetra, 4, points[7], { 0.5, 0.5, -0.5, 0.5}},
|
||||
{tetra, 4, points[8], {0.25, 0.25, 0.25, 0.25}},
|
||||
};
|
||||
#define num_tests (sizeof (tests) / sizeof (tests[0]))
|
||||
|
||||
static inline float
|
||||
rnd (mtstate_t *mt)
|
||||
{
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} uf;
|
||||
|
||||
do {
|
||||
uf.u = mtwist_rand (mt) & 0x007fffff;
|
||||
} while (!uf.u);
|
||||
uf.u |= 0x40000000;
|
||||
|
||||
return uf.f - 3.0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, const char **argv)
|
||||
{
|
||||
int res = 0;
|
||||
size_t i;
|
||||
int j;
|
||||
vec_t lambda[4];
|
||||
mtstate_t mt;
|
||||
double start, end;
|
||||
|
||||
for (i = 0; i < num_tests; i ++) {
|
||||
BarycentricCoords (tests[i].points, tests[i].num_points, tests[i].x,
|
||||
lambda);
|
||||
for (j = 0; j < tests[i].num_points; j++) {
|
||||
if (tests[i].expect[j] != lambda[j])
|
||||
break;
|
||||
}
|
||||
if (j != tests[i].num_points) {
|
||||
res = 1;
|
||||
printf ("test %d failed\n", (int) i);
|
||||
printf ("expect:");
|
||||
for (j = 0; j < tests[i].num_points; j++)
|
||||
printf (" %.9g", tests[i].expect[j]);
|
||||
printf ("\ngot :");
|
||||
for (j = 0; j < tests[i].num_points; j++)
|
||||
printf (" %.9g", lambda[j]);
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
mtwist_seed (&mt, 0);
|
||||
start = Sys_DoubleTime ();
|
||||
for (i = 0; i < 1000000; i++) {
|
||||
vec3_t p, x;
|
||||
VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), p);
|
||||
BarycentricCoords (tetra, 4, p, lambda);
|
||||
VectorZero (x);
|
||||
for (j = 0; j < 4; j++)
|
||||
VectorMultAdd (x, lambda[j], tetra[j], x);
|
||||
if (VectorDistance_fast (x, p) > 1e-4) {
|
||||
res = 1;
|
||||
printf ("[%.9g %.9g %.9g] != [%.9g %.9g %.9g]: [%g %g %g %g]\n",
|
||||
VectorExpand (x), VectorExpand (p), QuatExpand (lambda));
|
||||
break;
|
||||
}
|
||||
}
|
||||
end = Sys_DoubleTime ();
|
||||
printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start,
|
||||
i / (end - start));
|
||||
return res;
|
||||
}
|
103
libs/util/test/test-cs.c
Normal file
103
libs/util/test/test-cs.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/mersenne.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
const vec3_t points[] = {
|
||||
{-1, -1, 1},
|
||||
{ 1, 1, 1},
|
||||
{-1, 1, -1},
|
||||
{ 1, -1, -1},
|
||||
{-1, -1, -1},
|
||||
{ 1, 1, -1},
|
||||
{-1, 1, 1},
|
||||
{ 1, -1, 1},
|
||||
{ 0, 0, 0},
|
||||
};
|
||||
|
||||
struct {
|
||||
const vec3_t *points;
|
||||
int num_points;
|
||||
sphere_t expect;
|
||||
} tests[] = {
|
||||
{0, 0, {{ 0, 0, 0}, 0}},
|
||||
{points, 1, {{-1, -1, 1}, 0}},
|
||||
{points, 2, {{ 0, 0, 1}, 1.41421356}},
|
||||
{points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}},
|
||||
{points, 4, {{0, 0, 0}, 1.73205081}},
|
||||
};
|
||||
#define num_tests (sizeof (tests) / sizeof (tests[0]))
|
||||
|
||||
static inline float
|
||||
rnd (mtstate_t *mt)
|
||||
{
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} uf;
|
||||
|
||||
do {
|
||||
uf.u = mtwist_rand (mt) & 0x007fffff;
|
||||
} while (!uf.u);
|
||||
uf.u |= 0x40000000;
|
||||
return uf.f - 3.0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, const char **argv)
|
||||
{
|
||||
int res = 0;
|
||||
size_t i, j;
|
||||
sphere_t sphere;
|
||||
mtstate_t mt;
|
||||
double start, end;
|
||||
|
||||
for (i = 0; i < num_tests; i ++) {
|
||||
CircumSphere (tests[i].points, tests[i].num_points, &sphere);
|
||||
if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 1e-4
|
||||
|| fabs (sphere.radius - tests[i].expect.radius) > 1e-4) {
|
||||
res = 1;
|
||||
printf ("test %d failed\n", (int) i);
|
||||
printf ("expect: [%.9g %.9g %.9g],%.9g\n",
|
||||
VectorExpand (tests[i].expect.center),
|
||||
tests[i].expect.radius);
|
||||
printf ("got : [%.9g %.9g %.9g],%.9g\n",
|
||||
VectorExpand (sphere.center),
|
||||
sphere.radius);
|
||||
}
|
||||
}
|
||||
|
||||
mtwist_seed (&mt, 0);
|
||||
start = Sys_DoubleTime ();
|
||||
for (i = 0; !res && i < 1000000; i++) {
|
||||
vec3_t cloud[4];
|
||||
sphere_t cc;
|
||||
vec_t r2;
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]);
|
||||
}
|
||||
if (!CircumSphere ((const vec_t (*)[3]) cloud, 4, &cc))
|
||||
continue;
|
||||
r2 = cc.radius * cc.radius;
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (fabs (VectorDistance_fast (cloud[j], cc.center) - r2)
|
||||
< 1e-3 * r2)
|
||||
continue;
|
||||
printf ("%d %.9g - %.9g = %.9g\n", (int)j,
|
||||
VectorDistance_fast (cloud[j], cc.center), r2,
|
||||
VectorDistance_fast (cloud[j], cc.center) - r2);
|
||||
printf ("[%.9g %.9g %.9g] - [%.9g %.9g %.9g] = %.9g != %.9g\n",
|
||||
VectorExpand (cloud[j]), VectorExpand (cc.center),
|
||||
VectorDistance_fast (cloud[j], cc.center), r2);
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
end = Sys_DoubleTime ();
|
||||
printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start,
|
||||
i / (end - start));
|
||||
return res;
|
||||
}
|
102
libs/util/test/test-seb.c
Normal file
102
libs/util/test/test-seb.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/mersenne.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
const vec3_t points[] = {
|
||||
{-1, -1, 1},
|
||||
{ 1, 1, 1},
|
||||
{-1, 1, -1},
|
||||
{ 1, -1, -1},
|
||||
{-1, -1, -1},
|
||||
{ 1, 1, -1},
|
||||
{-1, 1, 1},
|
||||
{ 1, -1, 1},
|
||||
{ 0, 0, 0},
|
||||
};
|
||||
|
||||
struct {
|
||||
const vec3_t *points;
|
||||
int num_points;
|
||||
sphere_t expect;
|
||||
} tests[] = {
|
||||
{0, 0, {{ 0, 0, 0}, 0}},
|
||||
{points, 1, {{-1, -1, 1}, 0}},
|
||||
{points, 2, {{ 0, 0, 1}, 1.41421356}},
|
||||
{points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}},
|
||||
{points, 4, {{0, 0, 0}, 1.73205081}},
|
||||
};
|
||||
#define num_tests (sizeof (tests) / sizeof (tests[0]))
|
||||
|
||||
static inline float
|
||||
rnd (mtstate_t *mt)
|
||||
{
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} uf;
|
||||
|
||||
do {
|
||||
uf.u = mtwist_rand (mt) & 0x007fffff;
|
||||
} while (!uf.u);
|
||||
uf.u |= 0x40000000;
|
||||
return uf.f - 1.0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, const char **argv)
|
||||
{
|
||||
int res = 0;
|
||||
size_t i, j;
|
||||
sphere_t sphere;
|
||||
mtstate_t mt;
|
||||
double start, end;
|
||||
|
||||
for (i = 0; i < num_tests; i ++) {
|
||||
sphere = SmallestEnclosingBall (tests[i].points, tests[i].num_points);
|
||||
if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 1e-4
|
||||
|| fabs (sphere.radius - tests[i].expect.radius) > 1e-4) {
|
||||
res = 1;
|
||||
printf ("test %d failed\n", (int) i);
|
||||
printf ("expect: [%.9g %.9g %.9g],%.9g\n",
|
||||
VectorExpand (tests[i].expect.center),
|
||||
tests[i].expect.radius);
|
||||
printf ("got : [%.9g %.9g %.9g],%.9g\n",
|
||||
VectorExpand (sphere.center),
|
||||
sphere.radius);
|
||||
}
|
||||
}
|
||||
|
||||
mtwist_seed (&mt, 0);
|
||||
start = Sys_DoubleTime ();
|
||||
for (i = 0; !res && i < 1000000; i++) {
|
||||
vec3_t cloud[10];
|
||||
sphere_t seb;
|
||||
vec_t r2;
|
||||
|
||||
for (j = 0; j < 5; j++) {
|
||||
VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]);
|
||||
}
|
||||
seb = SmallestEnclosingBall ((const vec_t (*)[3]) cloud, 5);
|
||||
r2 = seb.radius * seb.radius;
|
||||
for (j = 0; j < 5; j++) {
|
||||
if (VectorDistance_fast (cloud[j], seb.center) - r2
|
||||
> 1e-5 * r2) {
|
||||
res = 1;
|
||||
printf ("%d %.9g - %.9g = %.9g\n", (int)j,
|
||||
VectorDistance_fast (cloud[j], seb.center), r2,
|
||||
VectorDistance_fast (cloud[j], seb.center) - r2);
|
||||
printf ("[%.9g %.9g %.9g] - [%.9g %.9g %.9g] = %.9g > %.9g\n",
|
||||
VectorExpand (cloud[j]), VectorExpand (seb.center),
|
||||
VectorDistance_fast (cloud[j], seb.center), r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
end = Sys_DoubleTime ();
|
||||
printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start,
|
||||
i / (end - start));
|
||||
return res;
|
||||
}
|
87
libs/util/test/test-seg.c
Normal file
87
libs/util/test/test-seg.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "QF/segtext.h"
|
||||
|
||||
static const char *test_string =
|
||||
"blah\n"
|
||||
"-- Vertex\n"
|
||||
"FOO\n"
|
||||
"-- Geometry\n"
|
||||
"BAR\n"
|
||||
"-- Fragment.Erosion\n"
|
||||
"BAZ\n"
|
||||
"-- Fragment.Grassfire\n"
|
||||
"QUX\n"
|
||||
"-- TessControl\n"
|
||||
"QUUX\n"
|
||||
"-- TessEvaluation\n"
|
||||
"QUUUX";
|
||||
|
||||
struct {
|
||||
const char *tag;
|
||||
const char *expect;
|
||||
} seg_tests[] = {
|
||||
{"", 0}, // empty tags not findable
|
||||
{"Vertex", "FOO\n"},
|
||||
{"Geometry", "BAR\n"},
|
||||
{"Fragment.Erosion", "BAZ\n"},
|
||||
{"Fragment.Grassfire", "QUX\n"},
|
||||
{"TessControl", "QUUX\n"},
|
||||
{"TessEvaluation", "QUUUX"}, // final chunk doesn't have \n
|
||||
{"Vertex.Erosion", "FOO\n"},
|
||||
{"Geometry.Grasfire", "BAR\n"},
|
||||
};
|
||||
#define num_seg_tests (sizeof (seg_tests) / sizeof (seg_tests[0]))
|
||||
|
||||
struct {
|
||||
const char *tag;
|
||||
int expect;
|
||||
} line_tests[] = {
|
||||
{"Vertex", 3},
|
||||
{"Geometry", 5},
|
||||
{"Fragment.Erosion", 7},
|
||||
{"Fragment.Grassfire", 9},
|
||||
{"TessControl", 11},
|
||||
{"TessEvaluation", 13}, // final chunk doesn't have \n
|
||||
};
|
||||
#define num_line_tests (sizeof (line_tests) / sizeof (line_tests[0]))
|
||||
|
||||
int
|
||||
main (int argc, const char **argv)
|
||||
{
|
||||
size_t i;
|
||||
int res = 0;
|
||||
segtext_t *st;
|
||||
|
||||
st = Segtext_new (test_string);
|
||||
for (i = 0; i < num_seg_tests; i++) {
|
||||
const char *text = Segtext_Find (st, seg_tests[i].tag);
|
||||
if ((!text != !seg_tests[i].expect)
|
||||
&& (!text || !seg_tests[i].expect
|
||||
|| strcmp (text, seg_tests[i].expect))) {
|
||||
fprintf (stderr, "FAIL: (%zd) \"%s\" -> \"%s\", got \"%s\"\n", i,
|
||||
seg_tests[i].tag, seg_tests[i].expect, text);
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < num_line_tests; i++) {
|
||||
const segchunk_t *chunk = Segtext_FindChunk (st, line_tests[i].tag);
|
||||
if (!chunk || chunk->start_line != line_tests[i].expect) {
|
||||
fprintf (stderr, "FAIL: (%zd) \"%s\" -> %d, got %d\n", i,
|
||||
line_tests[i].tag, line_tests[i].expect,
|
||||
chunk->start_line);
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
#include "QF/set.h"
|
||||
|
||||
#define SIZE (DEFMAP_SIZE * sizeof (unsigned) * 8)
|
||||
#define BITS (sizeof (((set_t *) 0)->map[0]) * 8)
|
||||
#define SIZE (SET_DEFMAP_SIZE * sizeof (set_bits_t) * 8)
|
||||
|
||||
typedef set_t *(*setup_func) (void);
|
||||
typedef set_t *(*op_func) (set_t *s1, const set_t *s2);
|
||||
|
@ -121,7 +120,7 @@ struct {
|
|||
{make_everything, 0, 0, check_size, SIZE, "{...}"},
|
||||
{make_empty_invert, 0, 0, check_size, SIZE, "{...}"},
|
||||
{make_everything_invert, 0, 0, check_size, SIZE, "{}"},
|
||||
{make_SIZE, 0, 0, check_size, SIZE + BITS, "{64}"},
|
||||
{make_SIZE, 0, 0, check_size, SIZE + SET_BITS, "{64}"},
|
||||
{make_0_to_SIZEm1, 0, 0, check_size, SIZE,
|
||||
"{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
|
||||
" 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
|
||||
|
|
|
@ -81,7 +81,7 @@ W_LoadWadFile (const char *filename)
|
|||
int i;
|
||||
int infotableofs;
|
||||
|
||||
wad_base = QFS_LoadHunkFile (filename);
|
||||
wad_base = QFS_LoadHunkFile (QFS_FOpenFile (filename));
|
||||
if (!wad_base)
|
||||
Sys_Error ("W_LoadWadFile: unable to load %s", filename);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
|
|||
|
||||
SUBDIRS= @vid_render_dirs@
|
||||
DIST_SUBDIRS= gl glsl sw sw32
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||
|
||||
lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \
|
||||
-rpath $(libdir) -no-undefined
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
AUTOMAKE_OPTIONS= foreign
|
||||
|
||||
AM_CFLAGS= @PREFER_PIC@
|
||||
INCLUDES= -I$(top_srcdir)/include $(GLX_CFLAGS)
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES= libgl.la
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ gl_Draw_CachePic (const char *path, qboolean alpha)
|
|||
|
||||
if (!strcmp (path + strlen (path) - 4, ".lmp")) {
|
||||
// Load the picture..
|
||||
qpic_t *dat = (qpic_t *) QFS_LoadFile (path, 0);
|
||||
qpic_t *dat = (qpic_t *) QFS_LoadFile (QFS_FOpenFile (path), 0);
|
||||
if (!dat)
|
||||
Sys_Error ("Draw_CachePic: failed to load %s", path);
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ gl_R_ReadPointFile_f (void)
|
|||
name = va ("%s.pts", mapname);
|
||||
free (mapname);
|
||||
|
||||
QFS_FOpenFile (name, &f);
|
||||
f = QFS_FOpenFile (name);
|
||||
if (!f) {
|
||||
Sys_Printf ("couldn't open %s\n", name);
|
||||
return;
|
||||
|
@ -1185,8 +1185,12 @@ R_EntityParticles_ID (const entity_t *ent)
|
|||
}
|
||||
|
||||
if (!avelocities[0][0]) {
|
||||
for (i = 0; i < NUMVERTEXNORMALS * 3; i++)
|
||||
avelocities[0][i] = (mtwist_rand (&mt) & 255) * 0.01;
|
||||
for (i = 0; i < NUMVERTEXNORMALS; i++) {
|
||||
int k;
|
||||
for (k = 0; k < 3; k++) {
|
||||
avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
|
|
|
@ -148,7 +148,7 @@ gl_R_Init (void)
|
|||
"Load a pointfile to determine map leaks");
|
||||
Cmd_AddCommand ("loadsky", gl_R_LoadSky_f, "Load a skybox");
|
||||
|
||||
Draw_Init ();
|
||||
gl_Draw_Init ();
|
||||
SCR_Init ();
|
||||
gl_R_InitBubble ();
|
||||
|
||||
|
@ -260,5 +260,5 @@ gl_R_TimeRefresh_f (void)
|
|||
|
||||
stop = Sys_DoubleTime ();
|
||||
time = stop - start;
|
||||
Sys_MaskPrintf (SYS_DEV, "%f seconds (%f fps)\n", time, 128 / time);
|
||||
Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue