Merge branch 'master' into win

This commit is contained in:
Bill Currie 2016-01-22 01:10:49 +09:00
commit bd52e46adf
258 changed files with 10122 additions and 4405 deletions

1
.gitignore vendored
View file

@ -37,6 +37,7 @@ core
/mkinstalldirs /mkinstalldirs
/quakeforge-config /quakeforge-config
/quakeforge.lsm /quakeforge.lsm
/test-driver
/ylwrap /ylwrap
# /RPM/ # /RPM/

View file

@ -100,7 +100,7 @@ else
fi fi
if test -n "$errors" ; then if test -n "$errors" ; then
echo -e $errors echo "$errors"
exit 1 exit 1
fi fi

View file

@ -380,7 +380,8 @@ QF_DEPS(QFCC_TEST,
) )
QF_DEPS(QFLIGHT, QF_DEPS(QFLIGHT,
[-I$(top_srcdir)/tools/qflight/include], [-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)], [$(WIN32_LIBS)],
) )
QF_DEPS(QFLMP, QF_DEPS(QFLMP,

View file

@ -14,6 +14,27 @@ if test "x$CFLAGS" != "x"; then
fi fi
AC_MSG_RESULT([$leave_cflags_alone]) 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 if test "x$GCC" = xyes; then
set $CC set $CC
shift shift

View file

@ -7,8 +7,6 @@ AC_FUNC_MEMCMP
AC_FUNC_MMAP AC_FUNC_MMAP
AC_TYPE_SIGNAL AC_TYPE_SIGNAL
AC_FUNC_VPRINTF AC_FUNC_VPRINTF
AC_FUNC_VA_COPY
AC_FUNC__VA_COPY
AC_CHECK_FUNCS( AC_CHECK_FUNCS(
access _access connect dlopen execvp fcntl ftime _ftime getaddrinfo \ access _access connect dlopen execvp fcntl ftime _ftime getaddrinfo \
gethostbyname gethostname getnameinfo getpagesize gettimeofday getuid \ gethostbyname gethostname getnameinfo getpagesize gettimeofday getuid \
@ -17,6 +15,17 @@ AC_CHECK_FUNCS(
_vsnprintf wait _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="" DL_LIBS=""
if test "x$ac_cv_func_dlopen" != "xyes"; then if test "x$ac_cv_func_dlopen" != "xyes"; then
AC_CHECK_LIB(dl, dlopen, AC_CHECK_LIB(dl, dlopen,

View file

@ -2,7 +2,7 @@ dnl Checks for SVGALib support
AC_ARG_WITH(svga, AC_ARG_WITH(svga,
[ --with-svga=DIR use SVGALib found in DIR], [ --with-svga=DIR use SVGALib found in DIR],
HAVE_SVGA=$withval, HAVE_SVGA=auto) 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 if test "x$HAVE_SVGA" != xauto; then
SVGA_CFLAGS="$SVGA_CFLAGS -I$withval/include" SVGA_CFLAGS="$SVGA_CFLAGS -I$withval/include"
SVGA_LIBS="$SVGA_LIBS -L$withval/lib" SVGA_LIBS="$SVGA_LIBS -L$withval/lib"

View file

@ -45,7 +45,7 @@ AC_TRY_COMPILE(
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
) )
AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY], 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 #undef HAVE___ATTRIBUTE__VISIBILITY
#ifdef HAVE___ATTRIBUTE__VISIBILITY #ifdef HAVE___ATTRIBUTE__VISIBILITY
# define VISIBLE __attribute__((visibility ("default"))) # define VISIBLE __attribute__((visibility ("default")))
@ -53,6 +53,26 @@ AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY],
# define VISIBLE # define VISIBLE
#endif]) #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_MSG_CHECKING(for __builtin_expect)
AC_TRY_COMPILE( AC_TRY_COMPILE(
[long (*foo) (long, long) = __builtin_expect;], [long (*foo) (long, long) = __builtin_expect;],
@ -68,8 +88,6 @@ AH_VERBATIM([HAVE___BUILTIN_EXPECT],
# define __builtin_expect(x,c) x # define __builtin_expect(x,c) x
#endif]) #endif])
AC_TYPE_VA_LIST
AC_MSG_CHECKING(for type of fpos_t) AC_MSG_CHECKING(for type of fpos_t)
AC_TRY_COMPILE( AC_TRY_COMPILE(
[#include <stdio.h>], [#include <stdio.h>],

View file

@ -1,8 +1,9 @@
endian="" endian=""
FNM_FLAGS=""
case "$host_os" in case "$host_os" in
mingw32*) mingw32*)
mingw=yes mingw=yes
CFLAGS="$CFLAGS -I\$(top_srcdir)/include/win32" FNM_FLAGS="-I\$(top_srcdir)/include/win32"
if test "x$host" != "x$build"; then if test "x$host" != "x$build"; then
case "$build_os" in case "$build_os" in
cygwin*) cygwin*)
@ -24,3 +25,4 @@ case "$host_os" in
fi fi
;; ;;
esac esac
AC_SUBST(FNM_FLAGS)

View file

@ -11,6 +11,7 @@
\li \subpage sound \li \subpage sound
\li \subpage tracklist \li \subpage tracklist
\li \subpage key_binding \li \subpage key_binding
\li \subpage imt
\li \subpage cshift_cvars \li \subpage cshift_cvars
\li \subpage server_timestamps \li \subpage server_timestamps
*/ */

211
doc/config/vkb.cfg Normal file
View 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

View file

@ -276,17 +276,17 @@ img.footer {
/* @group Code Colorization */ /* @group Code Colorization */
span.keyword { span.keyword {
color: #262833; color: white;
font-weight: bold; font-weight: bold;
} }
span.keywordtype { span.keywordtype {
color: #262833; color: #bec3d9;
font-weight: bold; font-weight: bold;
} }
span.keywordflow { span.keywordflow {
color: #000000; color: #bec3d9;
font-weight: bold; font-weight: bold;
} }

28
doc/imt.dox Normal file
View 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.
*/

View file

@ -87,5 +87,5 @@ And yes, these long strings were inspired by Python's long strings.
for doxygen --> for doxygen -->
Binary data is hex-encoded and contained within angle brackets (\c \< \c 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\> \>). 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

View file

@ -30,7 +30,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
# Stuff that is common to both client and server # 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@ SDL_LIBS = @SDL_LIBS@
bin_PROGRAMS= @HW_TARGETS@ bin_PROGRAMS= @HW_TARGETS@

View file

@ -30,6 +30,12 @@
#include "QF/qtypes.h" #include "QF/qtypes.h"
typedef struct shader_s {
int num_strings;
const char **strings;
const char **src;
} shader_t;
typedef struct shaderparam_s { typedef struct shaderparam_s {
const char *name; const char *name;
qboolean uniform; qboolean uniform;
@ -40,9 +46,42 @@ extern int glsl_palette;
extern int glsl_colormap; extern int glsl_colormap;
void GLSL_Init_Common (void); 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_LinkProgram (const char *name, int vert, int frag);
int GLSL_ResolveShaderParam (int program, shaderparam_t *param); int GLSL_ResolveShaderParam (int program, shaderparam_t *param);
void GLSL_DumpAttribArrays (void); 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 #endif // __QF_GLSL_vid_h

View file

@ -7,8 +7,8 @@ nobase_pkginclude_HEADERS = \
link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \ 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 \ 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 \ 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 \ quakeio.h render.h riff.h ruamoko.h screen.h script.h segtext.h set.h \
skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.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 \ 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 \ GL/ati.h GL/defines.h GL/extensions.h GL/funcs.h GL/qf_draw.h \

View file

@ -42,51 +42,52 @@
#ifndef DEBUG_QF_MEMORY #ifndef DEBUG_QF_MEMORY
/** High-tide structure allocator for use in linked lists. /** 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. 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. 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 s The number of structures in the block.
\param t The structure type. \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 \param v The destination of the pointer to the allocated
element. The contents of the allocated element will be element. The contents of the allocated element will be
memset to 0. memset to 0.
\hideinitializer \hideinitializer
*/ */
#define ALLOC(s, t, n, v) \ #define ALLOC(s, t, n, v) \
do { \ do { \
if (!free_##n) { \ if (!n##_freelist) { \
int i; \ int i; \
free_##n = malloc ((s) * sizeof (t)); \ n##_freelist = malloc ((s) * sizeof (t)); \
for (i = 0; i < (s) - 1; i++) \ for (i = 0; i < (s) - 1; i++) \
free_##n[i].next = &free_##n[i + 1];\ n##_freelist[i].next = &n##_freelist[i + 1];\
free_##n[i].next = 0; \ n##_freelist[i].next = 0; \
} \ } \
v = free_##n; \ v = n##_freelist; \
free_##n = free_##n->next; \ n##_freelist = n##_freelist->next; \
memset (v, 0, sizeof (*v)); \ memset (v, 0, sizeof (*v)); \
} while (0) } while (0)
/** Free a block allocated by #ALLOC /** 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. \param p The pointer to the block to be freed.
\hideinitializer \hideinitializer
*/ */
#define FREE(n, p) \ #define FREE(n, p) \
do { \ do { \
p->next = free_##n; \ p->next = n##_freelist; \
free_##n = p->next; \ n##_freelist = p; \
} while (0) } while (0)
#else #else
#define ALLOC(s, t, n, v) \ #define ALLOC(s, t, n, v) \
do { \ do { \
__attribute__((unused)) t **dummy = &free_##n; \ __attribute__((unused)) t **dummy = &n##_freelist; \
v = (t *) calloc (1, sizeof (t)); \ v = (t *) calloc (1, sizeof (t)); \
} while (0) } while (0)
#define FREE(n, p) do { free (p); } while (0) #define FREE(n, p) do { free (p); } while (0)

View file

@ -146,4 +146,9 @@ int Menu_KeyEvent (knum_t key, short unicode, qboolean down);
void Menu_Enter (void); void Menu_Enter (void);
void Menu_Leave (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 #endif // __console_h

View file

@ -29,24 +29,55 @@
#define __QF_joystick_h_ #define __QF_joystick_h_
#include <QF/qtypes.h> #include <QF/qtypes.h>
#include "QF/quakeio.h"
#define JOY_MAX_AXES 8 #define JOY_MAX_AXES 32
#define JOY_MAX_BUTTONS 18 #define JOY_MAX_BUTTONS 64
extern struct cvar_s *joy_device; // Joystick device name extern struct cvar_s *joy_device; // Joystick device name
extern struct cvar_s *joy_enable; // Joystick enabling flag extern struct cvar_s *joy_enable; // Joystick enabling flag
extern qboolean joy_found; // Joystick present? struct joy_axis_button {
extern qboolean joy_active; // Joystick in use? float threshold;
int key;
struct joy_axis { int state;
struct cvar_s *axis;
int current;
}; };
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 { struct joy_button {
int old; int old;
int current; int current;
}; };
extern struct joy_axis joy_axes[JOY_MAX_AXES]; 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. joy_enable->int_val are zero.
*/ */
void JOY_Command (void); void JOY_Command (void);
void joy_clear_axis (int i);
/* /*
JOY_Move (usercmd_t *) // FIXME: Not anymore! JOY_Move (usercmd_t *) // FIXME: Not anymore!
@ -111,4 +143,15 @@ void JOY_Close (void);
*/ */
void JOY_Read (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_ #endif // __QF_joystick_h_

View file

@ -34,8 +34,14 @@
# include "QF/quakeio.h" # include "QF/quakeio.h"
#endif #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 { typedef enum {
/* The keyboard syms have been cleverly chosen to map to ASCII */ /* The keyboard syms have been cleverly chosen to map to ASCII */
QFK_UNKNOWN = 0, QFK_UNKNOWN = 0,
@ -409,19 +415,87 @@ typedef enum {
QFJ_BUTTON30, QFJ_BUTTON30,
QFJ_BUTTON31, QFJ_BUTTON31,
QFJ_BUTTON32, 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 QFK_LAST
} knum_t; } knum_t;
typedef enum { typedef enum {
key_unfocused, // engine has lost input focus key_unfocused, ///< engine has lost input focus
key_game, key_game, ///< Normal in-game key bindings
key_demo, key_demo, ///< Demo playback key bindings
key_console, key_console, ///< Command console key bindings
key_message, key_message, ///< Message input line key bindings
key_menu, key_menu, ///< Menu key bindings.
key_last // enum size key_last ///< enum size
} keydest_t; } keydest_t;
#ifndef __QFCC__ #ifndef __QFCC__
@ -447,34 +521,144 @@ typedef struct imt_s {
int written; ///< avoid duplicate config file writes int written; ///< avoid duplicate config file writes
} imt_t; } imt_t;
/** Chain of input mapping tables ascociated with a keydest sub-system (game,
menu, etc).
*/
typedef struct keytarget_s { typedef struct keytarget_s {
imt_t *imts; imt_t *imts; ///< list of tables attached to this target
imt_t *active; imt_t *active; ///< currently active table in this target
} keytarget_t; } keytarget_t;
extern int keydown[QFK_LAST]; 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); 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, void Key_CreateIMT (keydest_t kd, const char *imt_name,
const char *chain_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); 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_FocusEvent (int gain);
void Key_Init (struct cbuf_s *cb);
void Key_Init_Cvars (void);
void Key_WriteBindings (QFile *f); 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); 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); 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); 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); 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); 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; struct progs_s;
/** Add the Key builtins to the specified progs instance.
*/
void Key_Progs_Init (struct progs_s *pr); void Key_Progs_Init (struct progs_s *pr);
#endif #endif
//@}
#endif // _KEYS_H #endif // _KEYS_H

View file

@ -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); void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross);
vec_t _VectorNormalize (vec3_t v); // returns vector length 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 #ifndef IMPLEMENT_VectorNormalize
extern inline GNU89INLINE inline
#else #else
VISIBLE VISIBLE
#endif #endif

View file

@ -174,11 +174,11 @@ void RotatePointAroundVector (vec3_t dst, const vec3_t axis,
} while (0) } while (0)
extern plane_t * const frustum; extern plane_t * const frustum;
extern inline qboolean R_CullBox (const vec3_t mins, const vec3_t maxs); GNU89INLINE 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_CullSphere (const vec3_t origin, const float radius);
#ifndef IMPLEMENT_R_Cull #ifndef IMPLEMENT_R_Cull
extern inline GNU89INLINE inline
#else #else
VISIBLE VISIBLE
#endif #endif
@ -194,7 +194,7 @@ R_CullBox (const vec3_t mins, const vec3_t maxs)
} }
#ifndef IMPLEMENT_R_Cull #ifndef IMPLEMENT_R_Cull
extern inline GNU89INLINE inline
#else #else
VISIBLE VISIBLE
#endif #endif
@ -213,6 +213,11 @@ R_CullSphere (const vec3_t origin, const float radius)
return false; 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 #endif // __mathlib_h

View file

@ -350,6 +350,7 @@ typedef enum {mod_brush, mod_sprite, mod_alias, mod_iqm} modtype_t;
typedef struct model_s { typedef struct model_s {
char name[MAX_QPATH]; 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 qboolean needload; // bmodels and sprites don't cache normally
aliashdr_t *aliashdr; // if not null, alias model is not cached aliashdr_t *aliashdr; // if not null, alias model is not cached
qboolean hasfullbrights; qboolean hasfullbrights;

View file

@ -314,7 +314,7 @@ void PR_Opcode_Init (void);
typedef struct dstatement_s { typedef struct dstatement_s {
pr_opcode_e op:16; pr_opcode_e op:16;
pr_ushort_t a,b,c; pr_ushort_t a,b,c;
} __attribute__((gcc_struct)) dstatement_t; } GCC_STRUCT dstatement_t;
typedef struct ddef_s { typedef struct ddef_s {
pr_ushort_t type; // if DEF_SAVEGLOBGAL bit is set pr_ushort_t type; // if DEF_SAVEGLOBGAL bit is set

View file

@ -247,7 +247,7 @@ struct plitem_s *ED_EntityDict (progs_t *pr, edict_t *ed);
struct plitem_s *ED_GlobalsDict (progs_t *pr); struct plitem_s *ED_GlobalsDict (progs_t *pr);
void ED_InitGlobals (progs_t *pr, struct plitem_s *globals); void ED_InitGlobals (progs_t *pr, struct plitem_s *globals);
void ED_InitEntity (progs_t *pr, struct plitem_s *entity, edict_t *ent); 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); struct plitem_s *ED_Parse (progs_t *pr, const char *data);
void ED_LoadFromFile (progs_t *pr, const char *data); void ED_LoadFromFile (progs_t *pr, const char *data);
void ED_EntityParseFunction (progs_t *pr); void ED_EntityParseFunction (progs_t *pr);

View file

@ -110,4 +110,9 @@ typedef struct plane_s {
byte pad[2]; byte pad[2];
} plane_t; } plane_t;
typedef struct sphere_s {
vec3_t center;
vec_t radius;
} sphere_t;
#endif // __qtypes_h #endif // __qtypes_h

View file

@ -67,6 +67,17 @@ typedef struct gamedir_s {
} dir; } dir;
} gamedir_t; } 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. /** Cached information about the current game directory. \see \ref dirconf.
*/ */
extern gamedir_t *qfs_gamedir; extern gamedir_t *qfs_gamedir;
@ -77,20 +88,20 @@ extern gamedir_t *qfs_gamedir;
typedef void gamedir_callback_t (int phase); typedef void gamedir_callback_t (int phase);
/** Base of the QFS user directory tree. The QFS functions, except for /** 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. this tree. Set via the \c fs_userpath directory.
*/ */
extern const char *qfs_userpath; 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; extern int qfs_filesize;
@ -121,6 +132,34 @@ void QFS_Init (const char *game);
*/ */
void QFS_Gamedir (const char *gamedir); 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. /** Open a file from within the user directory.
If \a path attempts to leave the user directory, this function sets 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); 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. /** Open a file for reading.
The file will be searched for through all the subdirectories given in the 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. substitution.
\param filename The name of the file to open. \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 \param zip If true and the file has been compressed with gzip, the
file will be opened such that it decompresses on the fly. file will be opened such that it decompresses on the fly.
Otherwise, the file will be read as-is. Otherwise, the file will be read as-is.
\return The amount of bytes that can be read from the file handle. \return The file handle or NULL if there is an error.
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.
*/ */
int _QFS_FOpenFile (const char *filename, QFile **gzfile, QFile *_QFS_FOpenFile (const char *filename, int zip);
struct dstring_s *foundname, int zip);
/** Open a file for reading. /** Open a file for reading.
@ -198,39 +235,28 @@ int _QFS_FOpenFile (const char *filename, QFile **gzfile,
_QFS_FOpenFile() for more details. _QFS_FOpenFile() for more details.
\param filename The name of the file to open. \param filename The name of the file to open.
\param gzfile Address of file handle pointer. \return The file handle pointer, or NULL if there is an error.
\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.
*/ */
int QFS_FOpenFile (const char *filename, QFile **gzfile); QFile *QFS_FOpenFile (const char *filename);
/** Load a file into memory. /** Load a file into memory.
This is a convenience wrapper for QFS_FOpenFile(). The file will be loaded The file will be loaded into memory allocated from the location indicated
in memory allocated from the location inicated by usehunk. 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 \param usehunk The location from which to allocate memory for the file's
data. Use 0. data. Use 0.
\return Pointer to the file's data, or NULL on error. \return Pointer to the file's data, or NULL on error.
\todo remove \a usehunk \todo remove \a usehunk
*/ */
byte *QFS_LoadFile (const char *path, int usehunk); byte *QFS_LoadFile (QFile *file, 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);
/** Load a file into memeory. /** Load a file into memeory.
The file is loaded into memory allocated from the hunk. 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. /** Load a file into memeory.
@ -238,7 +264,7 @@ byte *QFS_LoadHunkFile (const char *path);
\deprecated This should go away soon. \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. /** Rename a file.

58
include/QF/segtext.h Normal file
View 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

View file

@ -31,15 +31,32 @@
#ifndef __QF_set_h #ifndef __QF_set_h
#define __QF_set_h #define __QF_set_h
#include "QF/qtypes.h"
/** \defgroup set Set handling /** \defgroup set Set handling
\ingroup utils \ingroup utils
*/ */
//@{ //@{
#define DEFMAP_SIZE ((32 - sizeof (struct set_s *) \ //FIXME other archs
- sizeof (unsigned *) \ #ifdef __x86_64__
- sizeof (int) - sizeof (unsigned))\ typedef uint64_t set_bits_t;
/ sizeof (unsigned)) #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. /** Represent a set using a bitmap.
@ -50,10 +67,10 @@
*/ */
typedef struct set_s { typedef struct set_s {
struct set_s *next; ///< private. for ALLOC 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 int inverted; ///< if true, 0 indicates membership
unsigned size; ///< number of representable members 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; } set_t;
/** Represent the state of a scan through a set. /** Represent the state of a scan through a set.
@ -79,11 +96,19 @@ typedef struct set_iter_s {
unsigned element; unsigned element;
} set_iter_t; } 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. /** Delete a set iterator that is no longer needed.
\param set_iter The set iterator to be deleted. \param set_iter The set iterator to be deleted.
*/ */
void set_del_iter (set_iter_t *set_iter); 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. /** Create a new set.
@ -92,12 +117,28 @@ void set_del_iter (set_iter_t *set_iter);
\return The newly created, empty set. \return The newly created, empty set.
*/ */
set_t *set_new (void); 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. /** Delete a set that is no longer needed.
\param set The set to be deleted. \param set The set to be deleted.
*/ */
void set_delete (set_t *set); void set_delete (set_t *set);
void set_delete_r (set_pool_t *set_pool, set_t *set);
/** Add an element to a set. /** Add an element to a set.
@ -295,6 +336,7 @@ unsigned set_size (const set_t *set);
of everything. of everything.
*/ */
set_iter_t *set_first (const set_t *set); 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. /** Find the next "member" of the set.
@ -312,6 +354,7 @@ set_iter_t *set_first (const set_t *set);
is reached. is reached.
*/ */
set_iter_t *set_next (set_iter_t *set_iter); 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. /** Return a human-readable string representing the set.

View file

@ -58,20 +58,27 @@ typedef struct date_s {
char str[128]; char str[128];
} date_t; } 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); int Sys_mkdir (const char *path);
typedef void (*sys_printf_t) (const char *fmt, va_list args); 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_SetStdPrintf (sys_printf_t func);
void Sys_SetErrPrintf (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_Print (FILE *stream, const char *fmt, va_list args);
void Sys_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); 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_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_Quit (void) __attribute__((noreturn));
void Sys_Shutdown (void); void Sys_Shutdown (void);
void Sys_RegisterShutdown (void (*func) (void)); void Sys_RegisterShutdown (void (*func) (void));
int64_t Sys_LongTime (void);
double Sys_DoubleTime (void); double Sys_DoubleTime (void);
void Sys_TimeOfDay(date_t *date); void Sys_TimeOfDay(date_t *date);

View file

@ -59,8 +59,6 @@ typedef struct {
int conrowbytes; int conrowbytes;
int conwidth; int conwidth;
int conheight; int conheight;
unsigned maxwarpwidth;
unsigned maxwarpheight;
byte *direct; // direct drawing to framebuffer, if not byte *direct; // direct drawing to framebuffer, if not
// NULL // NULL
int (*surf_cache_size)(int width, int height); int (*surf_cache_size)(int width, int height);

View file

@ -30,7 +30,7 @@
#include "gib_tree.h" #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_Brace (const char *str, unsigned int *i);
char GIB_Parse_Match_Backtick (const char *str, unsigned int *i); char GIB_Parse_Match_Backtick (const char *str, unsigned int *i);

View file

@ -20,5 +20,7 @@ void VID_Update (vrect_t *rects);
void VID_LockBuffer (void); void VID_LockBuffer (void);
void VID_UnlockBuffer (void); void VID_UnlockBuffer (void);
void VID_InitBuffers (void); void VID_InitBuffers (void);
void VID_MakeColormaps (void);
#endif//__vid_internal_h #endif//__vid_internal_h

View file

@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
SUBDIRS= targets renderer . test SUBDIRS= targets renderer . test
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
SDL_LIBS= @SDL_LIBS@ SDL_LIBS= @SDL_LIBS@
XMMS_LIBS= @XMMS_LIBS@ XMMS_LIBS= @XMMS_LIBS@
plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)

View file

@ -143,7 +143,7 @@ Load_Tracklist (void)
{ {
QFile *oggfile = NULL; QFile *oggfile = NULL;
char *buffile = NULL; char *buffile = NULL;
int size = -1; int size;
/* kill off the old tracklist, and make sure we're not playing anything */ /* kill off the old tracklist, and make sure we're not playing anything */
I_OGGMus_Shutdown (); I_OGGMus_Shutdown ();
@ -155,8 +155,8 @@ Load_Tracklist (void)
return -1; // bail if we don't have a valid filename return -1; // bail if we don't have a valid filename
} }
size = QFS_FOpenFile (mus_ogglist->string, &oggfile); oggfile = QFS_FOpenFile (mus_ogglist->string);
if (size < 0) { if (!oggfile) {
Sys_Printf ("Mus_OggInit: open of file \"%s\" failed\n", Sys_Printf ("Mus_OggInit: open of file \"%s\" failed\n",
mus_ogglist->string); mus_ogglist->string);
return -1; return -1;

View file

@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ \ AM_CFLAGS= @PREFER_PIC@ \
$(VORBIS_CFLAGS) $(OGG_CFLAGS) $(SAMPLERATE_CFLAGS) $(JACK_CFLAGS) $(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_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)
plugin_libadd= @plugin_libadd@ plugin_libadd= @plugin_libadd@
EXEEXT= EXEEXT=

View file

@ -315,7 +315,7 @@ flac_callback_load (void *object, cache_allocator_t allocator)
sfxblock_t *block = (sfxblock_t *) object; sfxblock_t *block = (sfxblock_t *) object;
QFS_FOpenFile (block->file, &file); file = QFS_FOpenFile (block->file);
if (!file) if (!file)
return; //FIXME Sys_Error? return; //FIXME Sys_Error?
@ -374,7 +374,7 @@ flac_stream_open (sfx_t *sfx)
QFile *file; QFile *file;
void *f; void *f;
QFS_FOpenFile (stream->file, &file); file = QFS_FOpenFile (stream->file);
if (!file) if (!file)
return 0; return 0;

View file

@ -148,7 +148,7 @@ midi_stream_open (sfx_t *sfx)
unsigned long int local_buffer_size; unsigned long int local_buffer_size;
midi_file_t *mf; midi_file_t *mf;
QFS_FOpenFile (stream->file, &file); file = QFS_FOpenFile (stream->file);
local_buffer_size = Qfilesize (file); local_buffer_size = Qfilesize (file);

View file

@ -293,7 +293,6 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
int int
SND_Load (sfx_t *sfx) SND_Load (sfx_t *sfx)
{ {
dstring_t *foundname = dstring_new ();
char *realname; char *realname;
char buf[4]; char buf[4];
QFile *file; QFile *file;
@ -303,16 +302,14 @@ SND_Load (sfx_t *sfx)
sfx->close = snd_noop; sfx->close = snd_noop;
sfx->open = snd_open_fail; sfx->open = snd_open_fail;
_QFS_FOpenFile (sfx->name, &file, foundname, 1); file = QFS_FOpenFile (sfx->name);
if (!file) { if (!file) {
Sys_Printf ("Couldn't load %s\n", sfx->name); Sys_Printf ("Couldn't load %s\n", sfx->name);
dstring_delete (foundname);
return -1; return -1;
} }
sfx->open = snd_open; sfx->open = snd_open;
if (!strequal (foundname->str, sfx->name)) { if (!strequal (qfs_foundfile.realname, sfx->name)) {
realname = foundname->str; realname = strdup (qfs_foundfile.realname);
free (foundname);
} else { } else {
realname = (char *) sfx->name; // won't free if realname == sfx->name realname = (char *) sfx->name; // won't free if realname == sfx->name
} }

View file

@ -196,7 +196,7 @@ vorbis_callback_load (void *object, cache_allocator_t allocator)
sfxblock_t *block = (sfxblock_t *) object; sfxblock_t *block = (sfxblock_t *) object;
QFS_FOpenFile (block->file, &file); file = QFS_FOpenFile (block->file);
if (!file) if (!file)
return; //FIXME Sys_Error? return; //FIXME Sys_Error?
@ -260,7 +260,7 @@ vorbis_stream_open (sfx_t *sfx)
QFile *file; QFile *file;
vorbis_file_t *f; vorbis_file_t *f;
QFS_FOpenFile (stream->file, &file); file = QFS_FOpenFile (stream->file);
if (!file) if (!file)
return 0; return 0;

View file

@ -67,7 +67,7 @@ wav_callback_load (void *object, cache_allocator_t allocator)
sfxbuffer_t *buffer; sfxbuffer_t *buffer;
wavinfo_t *info = &block->wavinfo; wavinfo_t *info = &block->wavinfo;
QFS_FOpenFile (name, &file); file = QFS_FOpenFile (name);
if (!file) if (!file)
return; //FIXME Sys_Error? return; //FIXME Sys_Error?
@ -152,7 +152,7 @@ wav_stream_open (sfx_t *sfx)
QFile *file; QFile *file;
wav_file_t *wf; wav_file_t *wf;
QFS_FOpenFile (stream->file, &file); file = QFS_FOpenFile (stream->file);
if (!file) if (!file)
return 0; return 0;

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
SDL_LIBS = @SDL_LIBS@ SDL_LIBS = @SDL_LIBS@
plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)
plugin_libadd= @plugin_libadd@ plugin_libadd= @plugin_libadd@

View file

@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_PROGRAMS= @AUDIO_TARGETS@ noinst_PROGRAMS= @AUDIO_TARGETS@

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= libQFclient.la noinst_LTLIBRARIES= libQFclient.la

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ 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_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir)
plugin_libadd= @plugin_libadd@ plugin_libadd= @plugin_libadd@
lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \

View file

@ -474,11 +474,15 @@ C_KeyEvent (knum_t key, short unicode, qboolean down)
return; return;
} }
case key_game: case key_game:
case key_demo:
Menu_Enter (); Menu_Enter ();
return; return;
default: case key_unfocused:
Sys_Error ("Bad con_keydest"); return;
case key_last:
break; // should not happen, so hit error
} }
Sys_Error ("Bad con_keydest");
} else if (key == key_toggleconsole) { } else if (key == key_toggleconsole) {
ToggleConsole_f (); ToggleConsole_f ();
return; return;

View file

@ -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 static void
togglemenu_f (void) togglemenu_f (void)
{ {
@ -492,7 +512,7 @@ menu_free_progs_mem (progs_t *pr, void *mem)
static void * static void *
menu_load_file (progs_t *pr, const char *path) 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[] = { static builtin_t builtins[] = {
@ -517,9 +537,38 @@ static builtin_t builtins[] = {
{"Menu_Next", bi_Menu_Next, -1}, {"Menu_Next", bi_Menu_Next, -1},
{"Menu_Prev", bi_Menu_Prev, -1}, {"Menu_Prev", bi_Menu_Prev, -1},
{"Menu_Enter", bi_Menu_Enter, -1}, {"Menu_Enter", bi_Menu_Enter, -1},
{"Menu_Leave", bi_Menu_Leave, -1},
{0}, {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 void
Menu_Init (void) Menu_Init (void)
{ {
@ -549,6 +598,10 @@ Menu_Init (void)
"Toggle the display of the menu"); "Toggle the display of the menu");
Cmd_RemoveCommand ("quit"); Cmd_RemoveCommand ("quit");
Cmd_AddCommand ("quit", quit_f, "Exit the program"); 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 void
@ -562,7 +615,8 @@ Menu_Load (void)
top_menu = 0; top_menu = 0;
menu_pr_state.progs = 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); PR_LoadProgsFile (&menu_pr_state, file, size, 0, 1024 * 1024);
Qclose (file); Qclose (file);

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
lib_ldflags= lib_ldflags=
gc_deps=$(top_builddir)/libs/util/libQFutil.la gc_deps=$(top_builddir)/libs/util/libQFutil.la

View file

@ -328,6 +328,14 @@ signal_hook (int sig, void *data)
return 0; return 0;
} }
static void
error_handler (void *data)
{
progs_t *pr = (progs_t *) data;
PR_DumpState (pr);
fflush (stdout);
}
VISIBLE int VISIBLE int
PR_CallFunction (progs_t *pr, func_t fnum) 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; f = pr->function_table + fnum;
if (f->first_statement < 0) { if (f->first_statement < 0) {
// negative statements are built in functions // 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); f->func (pr);
return 0; return 0;
} else { } else {
@ -366,11 +378,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
startprofile = profile = 0; startprofile = profile = 0;
Sys_PushSignalHook (signal_hook, pr); Sys_PushSignalHook (signal_hook, pr);
Sys_PushErrorHandler (error_handler, pr);
if (!PR_CallFunction (pr, fnum)) { if (!PR_CallFunction (pr, fnum)) {
// called a builtin instead of progs code // called a builtin instead of progs code
Sys_PopSignalHook (); goto exit_program;
return;
} }
st = pr->pr_statements + pr->pr_xstatement; 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)) { && (OPA.uinteger_var >= pr->progs->numstatements)) {
PR_RunError (pr, "Invalid jump destination"); 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; st = pr->pr_statements + pr->pr_xstatement;
break; break;
case OP_JUMPB: case OP_JUMPB:
@ -960,8 +972,8 @@ op_call:
if (pr->pr_depth == exitdepth) { if (pr->pr_depth == exitdepth) {
if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth)
pr->pr_trace = false; pr->pr_trace = false;
Sys_PopSignalHook (); // all done
return; // all done goto exit_program;
} }
break; break;
case OP_STATE: case OP_STATE:
@ -1112,4 +1124,7 @@ op_call:
PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var, PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var,
watch->integer_var); watch->integer_var);
} }
exit_program:
Sys_PopErrorHandler ();
Sys_PopSignalHook ();
} }

View file

@ -83,7 +83,7 @@ file_error (progs_t *pr, const char *path)
static void * static void *
load_file (progs_t *pr, const char *path) load_file (progs_t *pr, const char *path)
{ {
return QFS_LoadHunkFile (path); return QFS_LoadHunkFile (QFS_FOpenFile (path));
} }
static void * static void *
@ -382,7 +382,7 @@ VISIBLE void
PR_LoadProgs (progs_t *pr, const char *progsname, int max_edicts, int zone) PR_LoadProgs (progs_t *pr, const char *progsname, int max_edicts, int zone)
{ {
QFile *file; QFile *file;
QFS_FOpenFile (progsname, &file); file = QFS_FOpenFile (progsname);
pr->progs_name = progsname; pr->progs_name = progsname;
if (file) { if (file) {

View file

@ -299,41 +299,48 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s)
*/ */
VISIBLE plitem_t * 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 *plist = PL_NewArray ();
plitem_t *ent; plitem_t *ent;
plitem_t *key; plitem_t *key;
plitem_t *value; plitem_t *value;
const char *token; char *token;
int anglehack; int anglehack;
while (Script_GetToken (script, 1)) { while (Script_GetToken (script, 1)) {
token = script->token->str; token = script->token->str;
if (!strequal (token, "{")) if (!strequal (token, "{"))
PR_Error (pr, "ED_ParseEntity: EOF without closing brace"); Sys_Error ("ED_ConvertToPlist: EOF without closing brace");
ent = PL_NewDictionary (); ent = PL_NewDictionary ();
while (1) { while (1) {
int n;
if (!Script_GetToken (script, 1)) 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; token = script->token->str;
if (strequal (token, "}")) if (strequal (token, "}"))
break; 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; anglehack = 0;
if (strequal (token, "angle")) { if (!nohack && strequal (token, "angle")) {
key = PL_NewString ("angles"); key = PL_NewString ("angles");
anglehack = 1; anglehack = 1;
} else if (strequal (token, "light")) { } else if (!nohack && strequal (token, "light")) {
key = PL_NewString ("light_lev"); key = PL_NewString ("light_lev");
} else { } else {
key = PL_NewString (token); key = PL_NewString (token);
} }
if (!Script_TokenAvailable (script, 0)) if (!Script_TokenAvailable (script, 0))
PR_Error (pr, "ED_ParseEntity: EOL without value"); Sys_Error ("ED_ConvertToPlist: EOL without value");
Script_GetToken (script, 0); Script_GetToken (script, 0);
token = script->token->str; token = script->token->str;
if (strequal (token, "}")) if (strequal (token, "}"))
PR_Error (pr, "ED_ParseEntity: closing brace without data"); Sys_Error ("ED_ConvertToPlist: closing brace without data");
if (anglehack) if (anglehack)
value = PL_NewString (va ("0 %s 0", token)); value = PL_NewString (va ("0 %s 0", token));
else else
@ -501,7 +508,7 @@ ED_Parse (progs_t *pr, const char *data)
} else { } else {
// oldstyle entity data // oldstyle entity data
Script_UngetToken (script); Script_UngetToken (script);
entity_list = ED_ConvertToPlist (pr, script); entity_list = ED_ConvertToPlist (script, 0);
} }
} }
Script_Delete (script); Script_Delete (script);

View file

@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ 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) \ lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \
-rpath $(libdir) -no-undefined -rpath $(libdir) -no-undefined

View file

@ -792,7 +792,7 @@ GIB_File_Read_f (void)
if (!(ret = GIB_Return (0))) if (!(ret = GIB_Return (0)))
return; return;
path = GIB_Argv (1); path = GIB_Argv (1);
QFS_FOpenFile (path, &file); file = QFS_FOpenFile (path);
if (file) { if (file) {
len = Qfilesize (file); len = Qfilesize (file);
ret->size = len + 1; ret->size = len + 1;

View file

@ -70,7 +70,7 @@ GIB_Exec_Override_f (void)
} }
mark = Hunk_LowMark (); mark = Hunk_LowMark ();
f = (char *) QFS_LoadHunkFile (Cmd_Argv (1)); f = (char *) QFS_LoadHunkFile (QFS_FOpenFile (Cmd_Argv (1)));
if (!f) { if (!f) {
Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1)); Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1));
return; return;

View file

@ -62,7 +62,7 @@ LoadImage (const char *imageFile)
// Check for a .png // Check for a .png
dstring_replace (tmpFile, tmp, tmpFile->size, ".png", 5); dstring_replace (tmpFile, tmp, tmpFile->size, ".png", 5);
QFS_FOpenFile (tmpFile->str, &fp); fp = QFS_FOpenFile (tmpFile->str);
if (fp) { if (fp) {
tex = LoadPNG (fp); tex = LoadPNG (fp);
Qclose (fp); Qclose (fp);
@ -72,7 +72,7 @@ LoadImage (const char *imageFile)
// Check for a .tga // Check for a .tga
dstring_replace (tmpFile, tmp, tmpFile->size, ".tga", 5); dstring_replace (tmpFile, tmp, tmpFile->size, ".tga", 5);
QFS_FOpenFile (tmpFile->str, &fp); fp = QFS_FOpenFile (tmpFile->str);
if (fp) { if (fp) {
tex = LoadTGA (fp); tex = LoadTGA (fp);
Qclose (fp); Qclose (fp);
@ -83,7 +83,7 @@ LoadImage (const char *imageFile)
/* /*
// Check for a .jpg // Check for a .jpg
dstring_replace (tmpFile, tmp, tmpFile->size, ".jpg", 5); dstring_replace (tmpFile, tmp, tmpFile->size, ".jpg", 5);
QFS_FOpenFile (tmpFile->str, &fp); fp = QFS_FOpenFile (tmpFile->str);
if (fp) { if (fp) {
tex = LoadJPG (fp); tex = LoadJPG (fp);
Qclose (fp); Qclose (fp);
@ -94,7 +94,7 @@ LoadImage (const char *imageFile)
// Check for a .pcx // Check for a .pcx
dstring_replace (tmpFile, tmp, tmpFile->size, ".pcx", 5); dstring_replace (tmpFile, tmp, tmpFile->size, ".pcx", 5);
QFS_FOpenFile (tmpFile->str, &fp); fp = QFS_FOpenFile (tmpFile->str);
if (fp) { if (fp) {
tex = LoadPCX (fp, 1, NULL); // Convert, some users don't grok paletted tex = LoadPCX (fp, 1, NULL); // Convert, some users don't grok paletted
Qclose (fp); Qclose (fp);

View file

@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
SUBDIRS= alias brush iqm sprite . test SUBDIRS= alias brush iqm sprite . test
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
lib_LTLIBRARIES= libQFmodels.la lib_LTLIBRARIES= libQFmodels.la
noinst_LTLIBRARIES= @models_libs@ noinst_LTLIBRARIES= @models_libs@

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= @alias_libs@ noinst_LTLIBRARIES= @alias_libs@
EXTRA_LTLIBRARIES=libalias_gl.la libalias_glsl.la libalias_sw.la EXTRA_LTLIBRARIES=libalias_gl.la libalias_glsl.la libalias_sw.la

View file

@ -366,7 +366,7 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m,
cache->str + strlen ("glquake/")); cache->str + strlen ("glquake/"));
dstring_appendstr (cache, ".qfms"); dstring_appendstr (cache, ".qfms");
QFS_FOpenFile (cache->str, &f); f = QFS_FOpenFile (cache->str);
if (f) { if (f) {
unsigned char d1[MDFOUR_DIGEST_BYTES]; unsigned char d1[MDFOUR_DIGEST_BYTES];
unsigned char d2[MDFOUR_DIGEST_BYTES]; unsigned char d2[MDFOUR_DIGEST_BYTES];

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= libbrush.la @brush_libs@ noinst_LTLIBRARIES= libbrush.la @brush_libs@
EXTRA_LTLIBRARIES=libbrush_gl.la libbrush_glsl.la libbrush_sw.la EXTRA_LTLIBRARIES=libbrush_gl.la libbrush_glsl.la libbrush_sw.la

View file

@ -141,6 +141,7 @@ gl_Mod_LoadLighting (bsp_t *bsp)
dstring_t *litfilename = dstring_new (); dstring_t *litfilename = dstring_new ();
size_t i; size_t i;
int ver; int ver;
QFile *lit_file;
dstring_copystr (litfilename, loadmodel->name); dstring_copystr (litfilename, loadmodel->name);
loadmodel->lightdata = NULL; loadmodel->lightdata = NULL;
@ -148,7 +149,8 @@ gl_Mod_LoadLighting (bsp_t *bsp)
// LordHavoc: check for a .lit file to load // LordHavoc: check for a .lit file to load
QFS_StripExtension (litfilename->str, litfilename->str); QFS_StripExtension (litfilename->str, litfilename->str);
dstring_appendstr (litfilename, ".lit"); 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) {
if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I'
&& data[3] == 'T') { && data[3] == 'T') {

View file

@ -186,6 +186,7 @@ build_skin (skin_t *skin, int cmap)
s = &player_skin; s = &player_skin;
if (!s->tex) // we haven't loaded the player model yet if (!s->tex) // we haven't loaded the player model yet
return; return;
texnum = skin_textures + cmap; texnum = skin_textures + cmap;
fb_texnum = 0; fb_texnum = 0;
if (s->fb) if (s->fb)
@ -197,13 +198,13 @@ build_skin (skin_t *skin, int cmap)
if (vid.is8bit) { if (vid.is8bit) {
build_skin_8 (s->tex, texnum, skin_cmap[cmap], build_skin_8 (s->tex, texnum, skin_cmap[cmap],
scaled_width, scaled_height, false); 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], build_skin_8 (s->fb_tex, fb_texnum, skin_cmap[cmap],
scaled_width, scaled_height, true); scaled_width, scaled_height, true);
} else { } else {
build_skin_32 (s->tex, texnum, skin_cmap[cmap], build_skin_32 (s->tex, texnum, skin_cmap[cmap],
scaled_width, scaled_height, false); 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], build_skin_32 (s->fb_tex, fb_texnum, skin_cmap[cmap],
scaled_width, scaled_height, true); scaled_width, scaled_height, true);
} }
@ -231,19 +232,20 @@ gl_Skin_SetupSkin (skin_t *skin, int cmap)
int changed; int changed;
glskin_t *s; glskin_t *s;
skin->texnum = 0;
skin->auxtex = 0;
if (!cmap) {
return;
}
// simplify cmap usage (texture offset/array index) // simplify cmap usage (texture offset/array index)
cmap--; cmap--;
s = skins + cmap; s = skins + cmap;
changed = (s->tex != skin->texels); changed = (s->tex != skin->texels);
s->tex = skin->texels; s->tex = skin->texels;
if (!changed) { if (!changed) {
skin->texnum = 0; skin->texnum = skin_textures + cmap;
skin->auxtex = 0; if (s->fb)
if (cmap >= 0) { skin->auxtex = skin_fb_textures + cmap;
skin->texnum = skin_textures + cmap;
if (s->fb)
skin->auxtex = skin_fb_textures + cmap;
}
return; return;
} }
if (s->tex) if (s->tex)

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= @iqm_libs@ noinst_LTLIBRARIES= @iqm_libs@
EXTRA_LTLIBRARIES=libiqm_gl.la libiqm_glsl.la libiqm_sw.la EXTRA_LTLIBRARIES=libiqm_gl.la libiqm_glsl.la libiqm_sw.la

View file

@ -171,21 +171,20 @@ Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator)
uint32_t *buf; uint32_t *buf;
// load the file // load the file
buf = (uint32_t *) QFS_LoadFile (mod->name, 0); buf = (uint32_t *) QFS_LoadFile (QFS_FOpenFile (mod->name), 0);
if (!buf) { if (!buf) {
if (crash) if (crash)
Sys_Error ("Mod_LoadModel: %s not found", mod->name); Sys_Error ("Mod_LoadModel: %s not found", mod->name);
return NULL; return NULL;
} }
// allocate a new model
if (loadname) if (loadname)
free (loadname); free (loadname);
loadname = QFS_FileBase (mod->name); loadname = QFS_FileBase (mod->name);
loadmodel = mod; loadmodel = mod;
// fill it in // fill it in
mod->vpath = qfs_foundfile.vpath;
mod->fullbright = 0; mod->fullbright = 0;
mod->shadow_alpha = 255; mod->shadow_alpha = 255;
mod->min_light = 0.0; mod->min_light = 0.0;

View file

@ -177,7 +177,7 @@ Skin_SetSkin (skin_t *skin, int cmap, const char *skinname)
break; break;
} }
QFS_FOpenFile (va ("skins/%s.pcx", name), &file); file = QFS_FOpenFile (va ("skins/%s.pcx", name));
if (!file) { if (!file) {
Sys_Printf ("Couldn't load skin %s\n", name); Sys_Printf ("Couldn't load skin %s\n", name);
free (name); free (name);

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= @sprite_libs@ noinst_LTLIBRARIES= @sprite_libs@
EXTRA_LTLIBRARIES=libsprite_gl.la libsprite_glsl.la libsprite_sw.la EXTRA_LTLIBRARIES=libsprite_gl.la libsprite_glsl.la libsprite_sw.la

View file

@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
INCLUDES= -I$(srcdir) -I$(top_srcdir)/include AM_CPPFLAGS= -I$(srcdir) -I$(top_srcdir)/include
check_PROGRAMS=testclip testcontents testportals check_PROGRAMS=testclip testcontents testportals
EXTRA_DIST= trace-id.c trace-qf-bad.c hulls.h main.c EXTRA_DIST= trace-id.c trace-qf-bad.c hulls.h main.c

View file

@ -1,3 +1,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "hulls.h" #include "hulls.h"
// 0,0 // 0,0

View file

@ -1,3 +1,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include "QF/va.h" #include "QF/va.h"

View file

@ -1,3 +1,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include "QF/va.h" #include "QF/va.h"

View file

@ -1,3 +1,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include "QF/va.h" #include "QF/va.h"

View file

@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
SUBDIRS= nc nm SUBDIRS= nc nm
AM_CFLAGS= @PREFER_NON_PIC@ AM_CFLAGS= @PREFER_NON_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= libnet_chan.la libnet_main.la noinst_LTLIBRARIES= libnet_chan.la libnet_main.la

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_NON_PIC@ AM_CFLAGS= @PREFER_NON_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= libnc.la noinst_LTLIBRARIES= libnc.la

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_NON_PIC@ AM_CFLAGS= @PREFER_NON_PIC@
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LTLIBRARIES= libnm.la noinst_LTLIBRARIES= libnm.la

View file

@ -97,6 +97,12 @@
#include "netmain.h" #include "netmain.h"
#include "net_udp.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 #ifdef _WIN32
# undef EWOULDBLOCK # undef EWOULDBLOCK
# define EWOULDBLOCK WSAEWOULDBLOCK # define EWOULDBLOCK WSAEWOULDBLOCK

View file

@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
noinst_LIBRARIES= libqw.a noinst_LIBRARIES= libqw.a

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ 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) \ lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \
-rpath $(libdir) -no-undefined -rpath $(libdir) -no-undefined

View file

@ -45,6 +45,8 @@
#include "rua_internal.h" #include "rua_internal.h"
#define always_inline inline __attribute__((__always_inline__))
typedef struct bi_plist_s { typedef struct bi_plist_s {
struct bi_plist_s *next; struct bi_plist_s *next;
struct bi_plist_s **prev; struct bi_plist_s **prev;
@ -140,7 +142,7 @@ plist_free_handle (plist_resources_t *res, bi_plist_t *plist)
plist_free (res, 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) get_plist (progs_t *pr, const char *name, int handle)
{ {
plist_resources_t *res = PR_Resources_Find (pr, "plist"); plist_resources_t *res = PR_Resources_Find (pr, "plist");

View file

@ -106,7 +106,7 @@ bi_QFS_LoadFile (progs_t *pr)
int size; int size;
void *buffer; void *buffer;
QFS_FOpenFile (filename, &file); file = QFS_FOpenFile (filename);
if (!file) { if (!file) {
RETURN_POINTER (pr, 0); RETURN_POINTER (pr, 0);
return; return;
@ -129,7 +129,7 @@ bi_QFS_OpenFile (progs_t *pr)
QFile *file; QFile *file;
const char *filename = P_GSTRING (pr, 0); const char *filename = P_GSTRING (pr, 0);
QFS_FOpenFile (filename, &file); file = QFS_FOpenFile (filename);
if (!file) { if (!file) {
R_INT (pr) = 0; R_INT (pr) = 0;
return; return;

View file

@ -4,7 +4,7 @@ SUBDIRS= . test
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
CCASFLAGS+= @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 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 \ 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 \ 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 \ 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 \ qfplist.c quakefs.c quakeio.c riff.c script.c segtext.c set.c sizebuf.c \
sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \ string.c sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \
$(dirent) $(fnmatch) $(getopt) $(dirent) $(fnmatch) $(getopt)
EXTRA_DIST= $(fnmatch_src) $(getopt_src) EXTRA_DIST= $(fnmatch_src) $(getopt_src)

View file

@ -490,7 +490,7 @@ Cmd_Exec_f (void)
} }
mark = Hunk_LowMark (); mark = Hunk_LowMark ();
f = (char *) QFS_LoadHunkFile (Cmd_Argv (1)); f = (char *) QFS_LoadHunkFile (QFS_FOpenFile (Cmd_Argv (1)));
if (!f) { if (!f) {
Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1)); Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1));
return; return;
@ -638,7 +638,7 @@ Cmd_Exec_File (cbuf_t *cbuf, const char *path, int qfs)
if (!path || !*path) if (!path || !*path)
return; return;
if (qfs) { if (qfs) {
QFS_FOpenFile (path, &file); file = QFS_FOpenFile (path);
} else { } else {
char *newpath = Sys_ExpandSquiggle (path); char *newpath = Sys_ExpandSquiggle (path);
file = Qopen (newpath, "r"); file = Qopen (newpath, "r");

View file

@ -299,23 +299,13 @@ dstring_clearstr (dstring_t *dstr)
dstr->str[0] = 0; 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 static int
_dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args) _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args)
{ {
int size; int size;
#ifdef VA_LIST_IS_ARRAY
va_list tmp_args; va_list tmp_args;
VA_COPY (tmp_args, args); va_copy (tmp_args, args);
#endif
if (!dstr->truesize) if (!dstr->truesize)
dstring_clearstr (dstr); // Make it a string 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) { args)) == -1) {
dstr->size = (dstr->truesize & ~1023) + 1024; dstr->size = (dstr->truesize & ~1023) + 1024;
dstring_adjust (dstr); dstring_adjust (dstr);
#ifdef VA_LIST_IS_ARRAY va_copy (args, tmp_args);
VA_COPY (args, tmp_args);
#endif
} }
dstr->size = size + offs + 2; dstr->size = size + offs + 2;
// "Proper" implementations return the required size // "Proper" implementations return the required size
if (dstr->size > dstr->truesize) { if (dstr->size > dstr->truesize) {
dstring_adjust (dstr); dstring_adjust (dstr);
#ifdef VA_LIST_IS_ARRAY va_copy (args, tmp_args);
VA_COPY (args, tmp_args);
#endif
vsnprintf (dstr->str + offs, dstr->truesize - offs - 1, fmt, args); vsnprintf (dstr->str + offs, dstr->truesize - offs - 1, fmt, args);
} }
dstr->size = size + offs + 1; dstr->size = size + offs + 1;

View file

@ -1151,3 +1151,262 @@ Mat4Decompose (const mat4_t mat, quat_t rot, vec3_t shear, vec3_t scale,
Mat4toMat3 (mat, m3); Mat4toMat3 (mat, m3);
return Mat3Decompose (m3, rot, shear, scale); 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;
}

View file

@ -74,7 +74,7 @@
#include <limits.h> #include <limits.h>
#include "qfalloca.h" #include "qfalloca.h"
#include "QF/alloc.h"
#include "QF/cmd.h" #include "QF/cmd.h"
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/dstring.h" #include "QF/dstring.h"
@ -136,7 +136,34 @@ typedef struct searchpath_s {
struct searchpath_s *next; struct searchpath_s *next;
} searchpath_t; } 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 //QFS
@ -145,7 +172,7 @@ typedef struct qfs_var_s {
char *val; char *val;
} qfs_var_t; } 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; VISIBLE gamedir_t *qfs_gamedir;
static plitem_t *qfs_gd_plist; static plitem_t *qfs_gd_plist;
@ -213,6 +240,55 @@ static gamedir_callback_t **gamedir_callbacks;
static int num_gamedir_callbacks; static int num_gamedir_callbacks;
static int max_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 * static const char *
qfs_var_get_key (const void *_v, void *unused) 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 *e = path + strlen (path);
const char *s = e; const char *s = e;
dstring_t *dir = dstring_new (); char *dir;
vpath_t *vpath;
while (s >= path) { while (s >= path) {
while (s != path && s[-1] !=':') while (s != path && s[-1] !=':')
s--; s--;
if (s != e) { if (s != e) {
dsprintf (dir, "%.*s", (int) (e - s), s); dir = nva ("%.*s", (int) (e - s), s);
qfs_add_gamedir (dir->str); vpath = new_vpath ();
vpath->name = dir;
qfs_add_gamedir (vpath, dir);
vpath->next = qfs_vpaths;
qfs_vpaths = vpath;
} }
e = --s; e = --s;
} }
dstring_delete (dir);
} }
static void static void
@ -497,20 +577,10 @@ qfs_build_gamedir (const char **list)
free (qfs_gamedir); free (qfs_gamedir);
} }
while (qfs_searchpaths) { while (qfs_vpaths) {
searchpath_t *next; vpath_t *next = qfs_vpaths->next;
delete_vpath (qfs_vpaths);
if (qfs_searchpaths->pack) { qfs_vpaths = next;
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;
} }
for (j = 0; list[j]; j++) for (j = 0; list[j]; j++)
@ -688,19 +758,31 @@ QFS_FileBase (const char *in)
return out; 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 static void
qfs_path_f (void) qfs_path_f (void)
{ {
searchpath_t *s; vpath_t *vp;
searchpath_t *sp;
Sys_Printf ("Current search path:\n"); Sys_Printf ("Current search path:\n");
for (s = qfs_searchpaths; s; s = s->next) { for (vp = qfs_vpaths; vp; vp = vp->next) {
if (s->pack) Sys_Printf ("%s\n", vp->name);
Sys_Printf ("%s (%i files)\n", s->pack->filename, for (sp = vp->user; sp; sp = sp->next) {
s->pack->numfiles); qfs_path_print (sp);
else }
Sys_Printf ("%s\n", s->filename); 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); 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 * static QFile *
qfs_openread (const char *path, int offs, int len, int zip) qfs_openread (const char *path, int offs, int len, int zip)
{ {
@ -805,7 +1009,7 @@ QFS_CompressPath (const char *pth)
return path; return path;
} }
VISIBLE int file_from_pak; // global indicating file came from pack file ZOID VISIBLE findfile_t qfs_foundfile;
/* /*
QFS_FOpenFile 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 Sets qfs_filesize and one of handle or file
*/ */
static int static void
open_file (searchpath_t *search, const char *filename, QFile **gzfile, open_file (int_findfile_t *found, QFile **gzfile, int zip)
dstring_t *foundname, int zip)
{ {
file_from_pak = 0; qfs_foundfile = found->ff;
if (found->ff.in_pak) {
// is the element a pak file? *gzfile = qfs_openread (found->pack->filename,
if (search->pack) { found->packfile->filepos,
dpackfile_t *packfile; found->packfile->filelen, zip);
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;
}
} else { } else {
// check a file in the directory tree *gzfile = qfs_openread (found->path, -1, -1, zip);
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;
} }
return -1;
} }
VISIBLE int VISIBLE QFile *
_QFS_FOpenFile (const char *filename, QFile **gzfile, _QFS_VOpenFile (const char *filename, int zip,
dstring_t *foundname, int zip) const vpath_t *start, const vpath_t *end)
{ {
searchpath_t *search; QFile *gzfile;
int_findfile_t *found;
char *path; char *path;
#ifdef HAVE_VORBIS const char *fnames[4];
char *oggfilename; int zip_flags[3];
#endif int ind;
#ifdef HAVE_ZLIB
char *gzfilename;
#endif
// make sure they're not trying to do weird stuff with our private files // make sure they're not trying to do weird stuff with our private files
path = QFS_CompressPath (filename); path = QFS_CompressPath (filename);
@ -887,57 +1051,70 @@ _QFS_FOpenFile (const char *filename, QFile **gzfile,
goto error; goto error;
} }
ind = 0;
#ifdef HAVE_VORBIS #ifdef HAVE_VORBIS
if (strequal (".wav", QFS_FileExtension (path))) { if (strequal (".wav", QFS_FileExtension (path))) {
char *oggfilename;
oggfilename = alloca (strlen (path) + 1); oggfilename = alloca (strlen (path) + 1);
QFS_StripExtension (path, oggfilename); QFS_StripExtension (path, oggfilename);
strncat (oggfilename, ".ogg", strncat (oggfilename, ".ogg",
sizeof (oggfilename) - strlen (oggfilename) - 1); sizeof (oggfilename) - strlen (oggfilename) - 1);
} else { fnames[ind] = oggfilename;
oggfilename = 0; zip_flags[ind] = 0;
ind++;
} }
#endif #endif
#ifdef HAVE_ZLIB #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 #endif
// search through the path, one element at a time fnames[ind] = path;
for (search = qfs_searchpaths; search; search = search->next) { zip_flags[ind] = zip;
#ifdef HAVE_VORBIS ind++;
//NOTE gzipped oggs not supported
if (oggfilename fnames[ind] = 0;
&& open_file (search, oggfilename, gzfile, foundname, false) != -1)
goto ok; found = qfs_findfile (fnames, start, end);
#endif
#ifdef HAVE_ZLIB if (found) {
if (open_file (search, gzfilename, gzfile, foundname, zip) != -1) open_file (found, &gzfile, zip_flags[found->fname_index]);
goto ok; free(path);
#endif return gzfile;
if (open_file (search, path, gzfile, foundname, zip) != -1)
goto ok;
} }
Sys_MaskPrintf (SYS_FS_NF, "FindFile: can't find %s\n", filename); Sys_MaskPrintf (SYS_FS_NF, "FindFile: can't find %s\n", filename);
error: error:
*gzfile = NULL;
qfs_filesize = -1; qfs_filesize = -1;
free (path); free (path);
return -1; return 0;
ok:
free(path);
return qfs_filesize;
} }
VISIBLE int VISIBLE QFile *
QFS_FOpenFile (const char *filename, QFile **gzfile) 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; VISIBLE QFile *
byte *loadbuf; _QFS_FOpenFile (const char *filename, int zip)
int loadsize; {
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 QFS_LoadFile
@ -946,20 +1123,22 @@ int loadsize;
Always appends a 0 byte to the loaded data. Always appends a 0 byte to the loaded data.
*/ */
VISIBLE byte * VISIBLE byte *
QFS_LoadFile (const char *path, int usehunk) QFS_LoadFile (QFile *file, int usehunk)
{ {
QFile *h;
byte *buf = NULL; byte *buf = NULL;
char *base; char *base;
int len; int len;
// look for it in the filesystem or pack files // look for it in the filesystem or pack files
len = qfs_filesize = QFS_FOpenFile (path, &h); if (!file)
if (!h)
return NULL; return NULL;
base = strdup ("QFS_LoadFile");
len = qfs_filesize = Qfilesize (file);
// extract the filename base name for hunk tag // extract the filename base name for hunk tag
base = QFS_FileBase (path); //base = QFS_FileBase (path);
if (usehunk == 1) if (usehunk == 1)
buf = Hunk_AllocName (len + 1, base); buf = Hunk_AllocName (len + 1, base);
@ -969,20 +1148,16 @@ QFS_LoadFile (const char *path, int usehunk)
buf = calloc (1, len + 1); buf = calloc (1, len + 1);
else if (usehunk == 3) else if (usehunk == 3)
buf = Cache_Alloc (loadcache, len + 1, base); buf = Cache_Alloc (loadcache, len + 1, base);
else if (usehunk == 4) { else
if (len + 1 > loadsize)
buf = Hunk_TempAlloc (len + 1);
else
buf = loadbuf;
} else
Sys_Error ("QFS_LoadFile: bad usehunk"); Sys_Error ("QFS_LoadFile: bad usehunk");
if (!buf) 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; buf[len] = 0;
Qread (h, buf, len); Qread (file, buf, len);
Qclose (h); Qclose (file);
free (base); free (base);
@ -990,29 +1165,16 @@ QFS_LoadFile (const char *path, int usehunk)
} }
VISIBLE byte * VISIBLE byte *
QFS_LoadHunkFile (const char *path) QFS_LoadHunkFile (QFile *file)
{ {
return QFS_LoadFile (path, 1); return QFS_LoadFile (file, 1);
} }
VISIBLE void VISIBLE void
QFS_LoadCacheFile (const char *path, struct cache_user_s *cu) QFS_LoadCacheFile (QFile *file, struct cache_user_s *cu)
{ {
loadcache = cu; loadcache = cu;
QFS_LoadFile (path, 3); QFS_LoadFile (file, 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;
} }
/* /*
@ -1070,9 +1232,9 @@ qfs_file_sort (char **os1, char **os2)
} }
static void 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; pack_t *pak;
DIR *dir_ptr; DIR *dir_ptr;
struct dirent *dirent; struct dirent *dirent;
@ -1126,11 +1288,10 @@ qfs_load_gamedir (const char *dir)
if (!pak) { if (!pak) {
Sys_Error ("Bad pakfile %s!!", pakfiles[i]); Sys_Error ("Bad pakfile %s!!", pakfiles[i]);
} else { } else {
search = malloc (sizeof (searchpath_t)); sp = new_searchpath ();
search->filename = 0; sp->pack = pak;
search->pack = pak; sp->next = *searchpath;
search->next = qfs_searchpaths; *searchpath = sp;
qfs_searchpaths = search;
} }
} }
@ -1147,23 +1308,22 @@ qfs_load_gamedir (const char *dir)
pak1.pak ... pak1.pak ...
*/ */
static void 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 // add the directory to the search path
search = malloc (sizeof (searchpath_t)); sp = new_searchpath ();
search->filename = strdup (dir); sp->filename = strdup (dir);
search->pack = 0; sp->next = *searchpath;
search->next = qfs_searchpaths; *searchpath = sp;
qfs_searchpaths = search;
// add any pak files in the format pak0.pak pak1.pak, ... // add any pak files in the format pak0.pak pak1.pak, ...
qfs_load_gamedir (dir); qfs_load_gamedir (searchpath, dir);
} }
static void static void
qfs_add_gamedir (const char *dir) qfs_add_gamedir (vpath_t *vpath, const char *dir)
{ {
const char *e; const char *e;
const char *s; const char *s;
@ -1190,7 +1350,7 @@ qfs_add_gamedir (const char *dir)
Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n", Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n",
f_dir->str); f_dir->str);
qfs_add_dir (f_dir->str); qfs_add_dir (&vpath->share, f_dir->str);
} }
} }
e = --s; e = --s;
@ -1198,7 +1358,7 @@ qfs_add_gamedir (const char *dir)
qfs_expand_userpath (f_dir, dir); qfs_expand_userpath (f_dir, dir);
Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n", f_dir->str); 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 (f_dir);
dstring_delete (s_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) if (qfs_expand_userpath (full_path, filename->str) == -1)
break; 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 // file doesn't exist, so we can use this name
ret = 1; ret = 1;
break; break;
@ -1506,45 +1666,57 @@ QFS_FilelistAdd (filelist_t *filelist, const char *fname, const char *ext)
filelist->list[filelist->count++] = str; 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 VISIBLE void
QFS_FilelistFill (filelist_t *list, const char *path, const char *ext, QFS_FilelistFill (filelist_t *list, const char *path, const char *ext,
int strip) int strip)
{ {
vpath_t *vpath;
searchpath_t *search; searchpath_t *search;
DIR *dir_ptr;
struct dirent *dirent;
char *cpath, *cp; char *cpath, *cp;
const char *separator = "/";
if (strchr (ext, '/') || strchr (ext, '\\')) if (strchr (ext, '/') || strchr (ext, '\\'))
return; return;
cp = cpath = QFS_CompressPath (path); cp = cpath = QFS_CompressPath (path);
if (*cp && cp[strlen (cp) - 1] == '/')
separator = "";
for (search = qfs_searchpaths; search != NULL; search = search->next) { for (vpath = qfs_vpaths; vpath; vpath = vpath->next) {
if (search->pack) { for (search = vpath->user; search; search = search->next) {
int i; qfs_filelistfill_do (list, search, cp, ext, strip);
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);
} }
} }
free (cpath); free (cpath);

View file

@ -383,9 +383,7 @@ Qprintf (QFile *file, const char *fmt, ...)
if (!buf) if (!buf)
buf = dstring_new (); buf = dstring_new ();
va_start (args, fmt);
dvsprintf (buf, fmt, args); dvsprintf (buf, fmt, args);
va_end (args);
ret = strlen (buf->str); ret = strlen (buf->str);
if (ret > 0) if (ret > 0)
ret = gzwrite (file->gzfile, buf, (unsigned) ret); ret = gzwrite (file->gzfile, buf, (unsigned) ret);

215
libs/util/segtext.c Normal file
View 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;
}

View file

@ -45,74 +45,113 @@
#include "QF/mathlib.h" #include "QF/mathlib.h"
#include "QF/set.h" #include "QF/set.h"
#define BITS (sizeof (((set_t *) 0)->map[0]) * 8) static set_pool_t static_set_pool = {0, 0};
set_t *free_sets;
set_iter_t *free_set_iters;
static set_iter_t * static set_iter_t *
new_setiter (void) new_setiter (set_pool_t *set_pool)
{ {
set_iter_t *set_iter; 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; return set_iter;
} }
static void 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 void
set_del_iter (set_iter_t *set_iter) set_del_iter (set_iter_t *set_iter)
{ {
delete_setiter (set_iter); delete_setiter (&static_set_pool, set_iter);
} }
set_t * void
set_new (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; set_t *set;
ALLOC (16, set_t, sets, set); ALLOC (16, set_t, set_pool->set, set);
set->size = sizeof (set->defmap) * 8; set->size = sizeof (set->defmap) * 8;
set->map = set->defmap; set->map = set->defmap;
return set; return set;
} }
set_t *
set_new (void)
{
return set_new_r (&static_set_pool);
}
void void
set_delete (set_t *set) set_delete_r (set_pool_t *set_pool, set_t *set)
{ {
if (set->map != set->defmap) if (set->map != set->defmap)
free (set->map); 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 static void
set_expand (set_t *set, unsigned x) set_expand (set_t *set, unsigned x)
{ {
unsigned *map = set->map; set_bits_t *map = set->map;
size_t size; size_t size;
if (x <= set->size) if (x <= set->size)
return; return;
size = (x + BITS) & ~(BITS - 1); size = SET_SIZE (x);
set->map = malloc (size / 8); set->map = malloc (size / 8);
memcpy (set->map, map, set->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; set->size = size;
if (map != set->defmap) if (map != set->defmap)
free (map); 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 static inline void
_set_add (set_t *set, unsigned x) _set_add (set_t *set, unsigned x)
{ {
if (x >= set->size) if (x >= set->size)
set_expand (set, x + 1); 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 static inline void
@ -120,7 +159,7 @@ _set_remove (set_t *set, unsigned x)
{ {
if (x >= set->size) if (x >= set->size)
return; return;
set->map[x / BITS] &= ~(1 << (x % BITS)); set->map[x / SET_BITS] &= ~(SET_ONE << (x % SET_BITS));
} }
set_t * set_t *
@ -158,7 +197,7 @@ _set_union (set_t *dst, const set_t *src)
size = max (dst->size, src->size); size = max (dst->size, src->size);
set_expand (dst, 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]; dst->map[i] |= src->map[i];
return dst; return dst;
} }
@ -171,9 +210,9 @@ _set_intersection (set_t *dst, const set_t *src)
size = max (dst->size, src->size); size = max (dst->size, src->size);
set_expand (dst, 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]; dst->map[i] &= src->map[i];
for ( ; i < dst->size / BITS; i++) for ( ; i < SET_WORDS (dst); i++)
dst->map[i] = 0; dst->map[i] = 0;
return dst; return dst;
} }
@ -186,7 +225,7 @@ _set_difference (set_t *dst, const set_t *src)
size = max (dst->size, src->size); size = max (dst->size, src->size);
set_expand (dst, 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]; dst->map[i] &= ~src->map[i];
return dst; return dst;
} }
@ -199,7 +238,7 @@ _set_reverse_difference (set_t *dst, const set_t *src)
size = max (dst->size, src->size); size = max (dst->size, src->size);
set_expand (dst, 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]; dst->map[i] = ~dst->map[i] & src->map[i];
return dst; return dst;
} }
@ -275,9 +314,9 @@ set_assign (set_t *dst, const set_t *src)
size = max (dst->size, src->size); size = max (dst->size, src->size);
set_expand (dst, size); set_expand (dst, size);
dst->inverted = src->inverted; 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]; dst->map[i] = src->map[i];
for ( ; i < dst->size / BITS; i++) for ( ; i < SET_WORDS (dst); i++)
dst->map[i] = 0; dst->map[i] = 0;
return dst; return dst;
} }
@ -288,7 +327,7 @@ set_empty (set_t *set)
unsigned i; unsigned i;
set->inverted = 0; set->inverted = 0;
for (i = 0; i < set->size / BITS; i++) for (i = 0; i < SET_WORDS (set); i++)
set->map[i] = 0; set->map[i] = 0;
return set; return set;
} }
@ -299,7 +338,7 @@ set_everything (set_t *set)
unsigned i; unsigned i;
set->inverted = 1; set->inverted = 1;
for (i = 0; i < set->size / BITS; i++) for (i = 0; i < SET_WORDS (set); i++)
set->map[i] = 0; set->map[i] = 0;
return set; return set;
} }
@ -309,7 +348,7 @@ _set_is_empty (const set_t *set)
{ {
unsigned i; unsigned i;
for (i = 0; i < set->size / BITS; i++) for (i = 0; i < SET_WORDS (set); i++)
if (set->map[i]) if (set->map[i])
return 0; return 0;
return 1; return 1;
@ -335,21 +374,21 @@ static int
set_test_n_n (const set_t *s1, const set_t *s2) set_test_n_n (const set_t *s1, const set_t *s2)
{ {
unsigned i, end; unsigned i, end;
unsigned intersection = 0; set_bits_t intersection = 0;
unsigned difference = 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++) { for (i = 0; i < end; i++) {
unsigned m1 = s1->map[i]; set_bits_t m1 = s1->map[i];
unsigned m2 = s2->map[i]; set_bits_t m2 = s2->map[i];
intersection |= m1 & m2; intersection |= m1 & m2;
difference |= m1 ^ m2; difference |= m1 ^ m2;
} }
for ( ; i < s1->size / BITS; i++) { for ( ; i < SET_WORDS (s1); i++) {
difference |= s1->map[i]; difference |= s1->map[i];
} }
for ( ; i < s2->size / BITS; i++) { for ( ; i < SET_WORDS (s2); i++) {
difference |= s2->map[i]; difference |= s2->map[i];
} }
return (difference != 0) | ((intersection != 0) << 1); return (difference != 0) | ((intersection != 0) << 1);
@ -359,22 +398,22 @@ static int
set_test_n_i (const set_t *s1, const set_t *s2) set_test_n_i (const set_t *s1, const set_t *s2)
{ {
unsigned i, end; unsigned i, end;
unsigned intersection = 0; set_bits_t intersection = 0;
unsigned difference = 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++) { for (i = 0; i < end; i++) {
unsigned m1 = s1->map[i]; set_bits_t m1 = s1->map[i];
unsigned m2 = ~s2->map[i]; set_bits_t m2 = ~s2->map[i];
intersection |= m1 & m2; intersection |= m1 & m2;
difference |= m1 ^ m2; difference |= m1 ^ m2;
} }
for ( ; i < s1->size / BITS; i++) { for ( ; i < SET_WORDS (s1); i++) {
intersection |= s1->map[i]; intersection |= s1->map[i];
difference |= ~s1->map[i]; difference |= ~s1->map[i];
} }
for ( ; i < s2->size / BITS; i++) { for ( ; i < SET_WORDS (s2); i++) {
difference |= ~s2->map[i]; difference |= ~s2->map[i];
} }
return (difference != 0) | ((intersection != 0) << 1); return (difference != 0) | ((intersection != 0) << 1);
@ -384,21 +423,21 @@ static int
set_test_i_n (const set_t *s1, const set_t *s2) set_test_i_n (const set_t *s1, const set_t *s2)
{ {
unsigned i, end; unsigned i, end;
unsigned intersection = 0; set_bits_t intersection = 0;
unsigned difference = 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++) { for (i = 0; i < end; i++) {
unsigned m1 = ~s1->map[i]; set_bits_t m1 = ~s1->map[i];
unsigned m2 = s2->map[i]; set_bits_t m2 = s2->map[i];
intersection |= m1 & m2; intersection |= m1 & m2;
difference |= m1 ^ m2; difference |= m1 ^ m2;
} }
for ( ; i < s1->size / BITS; i++) { for ( ; i < SET_WORDS (s1); i++) {
difference |= ~s1->map[i]; difference |= ~s1->map[i];
} }
for ( ; i < s2->size / BITS; i++) { for ( ; i < SET_WORDS (s2); i++) {
intersection |= s2->map[i]; intersection |= s2->map[i];
difference |= ~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) set_test_i_i (const set_t *s1, const set_t *s2)
{ {
unsigned i, end; unsigned i, end;
unsigned intersection = 0; set_bits_t intersection = 0;
unsigned difference = 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++) { for (i = 0; i < end; i++) {
unsigned m1 = ~s1->map[i]; set_bits_t m1 = ~s1->map[i];
unsigned m2 = ~s2->map[i]; set_bits_t m2 = ~s2->map[i];
intersection |= m1 & m2; intersection |= m1 & m2;
difference |= m1 ^ m2; difference |= m1 ^ m2;
} }
for ( ; i < s1->size / BITS; i++) { for ( ; i < SET_WORDS (s1); i++) {
difference |= ~s1->map[i]; difference |= ~s1->map[i];
} }
for ( ; i < s2->size / BITS; i++) { for ( ; i < SET_WORDS (s2); i++) {
intersection |= s2->map[i]; intersection |= s2->map[i];
difference |= ~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; unsigned i, end;
end = min (set->size, sub->size) / BITS; end = min (set->size, sub->size) / SET_BITS;
if (set->inverted && sub->inverted) { if (set->inverted && sub->inverted) {
for (i = 0; i < end; i++) { for (i = 0; i < end; i++) {
if (~sub->map[i] & set->map[i]) if (~sub->map[i] & set->map[i])
return 0; return 0;
} }
for ( ; i < set->size / BITS; i++) for ( ; i < SET_WORDS (set); i++)
if (set->map[i]) if (set->map[i])
return 0; return 0;
} else if (set->inverted) { } 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]) if (sub->map[i] & ~set->map[i])
return 0; return 0;
} }
for ( ; i < sub->size / BITS; i++) for ( ; i < SET_WORDS (sub); i++)
if (sub->map[i]) if (sub->map[i])
return 0; return 0;
} }
@ -501,7 +540,7 @@ _set_is_member (const set_t *set, unsigned x)
{ {
if (x >= set->size) if (x >= set->size)
return 0; return 0;
return (set->map[x / BITS] & (1 << (x % BITS))) != 0; return (set->map[x / SET_BITS] & (SET_ONE << (x % SET_BITS))) != 0;
} }
int int
@ -525,14 +564,14 @@ set_size (const set_t *set)
} }
set_iter_t * set_iter_t *
set_first (const set_t *set) set_first_r (set_pool_t *set_pool, const set_t *set)
{ {
unsigned x; unsigned x;
set_iter_t *set_iter; set_iter_t *set_iter;
for (x = 0; x < set->size; x++) { for (x = 0; x < set->size; x++) {
if (_set_is_member (set, x)) { if (_set_is_member (set, x)) {
set_iter = new_setiter (); set_iter = new_setiter (set_pool);
set_iter->set = set; set_iter->set = set;
set_iter->element = x; set_iter->element = x;
return set_iter; return set_iter;
@ -542,7 +581,13 @@ set_first (const set_t *set)
} }
set_iter_t * 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; unsigned x;
@ -552,10 +597,16 @@ set_next (set_iter_t *set_iter)
return set_iter; return set_iter;
} }
} }
delete_setiter (set_iter); delete_setiter (set_pool, set_iter);
return 0; return 0;
} }
set_iter_t *
set_next (set_iter_t *set_iter)
{
return set_next_r (&static_set_pool, set_iter);
}
const char * const char *
set_as_string (const set_t *set) set_as_string (const set_t *set)
{ {

View file

@ -66,6 +66,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <time.h> #include <time.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
#include <sys/time.h> #include <sys/time.h>
@ -78,6 +79,7 @@
#include "qfalloca.h" #include "qfalloca.h"
#include "QF/alloc.h"
#include "QF/cmd.h" #include "QF/cmd.h"
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/dstring.h" #include "QF/dstring.h"
@ -106,8 +108,17 @@ typedef struct shutdown_list_s {
void (*func)(void); void (*func)(void);
} shutdown_list_t; } 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 shutdown_list_t *shutdown_list;
static error_handler_t *error_handler_freelist;
static error_handler_t *error_handler;
#ifndef _WIN32 #ifndef _WIN32
static int do_stdin = 1; static int do_stdin = 1;
qboolean stdin_ready; qboolean stdin_ready;
@ -160,6 +171,25 @@ Sys_MaskFPUExceptions (void)
} }
#endif #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 int
Sys_mkdir (const char *path) Sys_mkdir (const char *path)
{ {
@ -179,13 +209,11 @@ Sys_mkdir (const char *path)
# error do not know how to make directories # error do not know how to make directories
# endif # endif
#endif #endif
if (errno != EEXIST) return -1;
return -1;
return 0;
} }
VISIBLE int VISIBLE int
Sys_FileTime (const char *path) Sys_FileExists (const char *path)
{ {
#ifdef HAVE_ACCESS #ifdef HAVE_ACCESS
if (access (path, R_OK) == 0) if (access (path, R_OK) == 0)
@ -287,8 +315,8 @@ Sys_MaskPrintf (int mask, const char *fmt, ...)
va_end (args); va_end (args);
} }
VISIBLE double VISIBLE int64_t
Sys_DoubleTime (void) Sys_LongTime (void)
{ {
static qboolean first = true; static qboolean first = true;
#ifdef _WIN32 #ifdef _WIN32
@ -314,13 +342,13 @@ Sys_DoubleTime (void)
# else # else
// MH's solution combining timeGetTime for stability and // MH's solution combining timeGetTime for stability and
// QueryPerformanceCounter for precision. // QueryPerformanceCounter for precision.
static __int64 qpcfreq = 0; static int64_t qpcfreq = 0;
static __int64 currqpccount = 0; static int64_t currqpccount = 0;
static __int64 lastqpccount = 0; static int64_t lastqpccount = 0;
static double qpcfudge = 0; static int64_t qpcfudge = 0;
DWORD currtime = 0; int64_t currtime = 0;
static DWORD lasttime = 0; static int64_t lasttime = 0;
static DWORD starttime = 0; static int64_t starttime = 0;
if (first) { if (first) {
timeBeginPeriod (1); timeBeginPeriod (1);
@ -342,9 +370,8 @@ Sys_DoubleTime (void)
// store back times and calc a fudge factor as timeGetTime can // store back times and calc a fudge factor as timeGetTime can
// overshoot on a sub-millisecond scale // overshoot on a sub-millisecond scale
qpcfudge = (((double) (currqpccount - lastqpccount) qpcfudge = (( (currqpccount - lastqpccount) * 1000000 / qpcfreq))
/ (double) qpcfreq)) - ((currtime - lasttime) * 1000);
- ((double) (currtime - lasttime) * 0.001);
lastqpccount = currqpccount; lastqpccount = currqpccount;
lasttime = currtime; lasttime = currtime;
} else { } else {
@ -352,19 +379,18 @@ Sys_DoubleTime (void)
} }
// the final time is the base from timeGetTime plus an addition from QPC // the final time is the base from timeGetTime plus an addition from QPC
return ((double) (currtime - starttime) * 0.001) return (((currtime - starttime) * 1000)
+ ((double) (currqpccount - lastqpccount) / (double) qpcfreq) + ((currqpccount - lastqpccount) * 1000000 / qpcfreq) + qpcfudge);
+ qpcfudge;
# endif # endif
#else #else
struct timeval tp; struct timeval tp;
struct timezone tzp; struct timezone tzp;
double now; int64_t now;
static double start_time; static int64_t start_time;
gettimeofday (&tp, &tzp); gettimeofday (&tp, &tzp);
now = tp.tv_sec + tp.tv_usec / 1e6; now = tp.tv_sec * 1000000 + tp.tv_usec;
if (first) { if (first) {
first = false; first = false;
@ -375,6 +401,12 @@ Sys_DoubleTime (void)
#endif #endif
} }
VISIBLE double
Sys_DoubleTime (void)
{
return (__INT64_C (4294967296000000) + Sys_LongTime ()) / 1e6;
}
VISIBLE void VISIBLE void
Sys_TimeOfDay (date_t *date) Sys_TimeOfDay (date_t *date)
{ {
@ -471,21 +503,36 @@ Sys_Quit (void)
exit (0); exit (0);
} }
#if defined (HAVE_VA_COPY) VISIBLE void
# define VA_COPY(a,b) va_copy (a, b) Sys_PushErrorHandler (sys_error_t func, void *data)
#elif defined (HAVE__VA_COPY) {
# define VA_COPY(a,b) __va_copy (a, b) error_handler_t *eh;
#else ALLOC (16, error_handler_t, error_handler, eh);
# define VA_COPY(a,b) memcpy (a, b, sizeof (a)) eh->func = func;
#endif 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 VISIBLE void
Sys_Error (const char *error, ...) Sys_Error (const char *error, ...)
{ {
va_list args; va_list args;
#ifdef VA_LIST_IS_ARRAY
va_list tmp_args; va_list tmp_args;
#endif
static int in_sys_error = 0; static int in_sys_error = 0;
if (in_sys_error) { if (in_sys_error) {
@ -499,20 +546,20 @@ Sys_Error (const char *error, ...)
in_sys_error = 1; in_sys_error = 1;
va_start (args, error); va_start (args, error);
#ifdef VA_LIST_IS_ARRAY va_copy (tmp_args, args);
VA_COPY (tmp_args, args);
#endif
sys_err_printf_function (error, args); sys_err_printf_function (error, args);
va_end (args); va_end (args);
if (error_handler) {
error_handler->func (error_handler->data);
}
Sys_Shutdown (); Sys_Shutdown ();
if (sys_err_printf_function != Sys_ErrPrintf) { if (sys_err_printf_function != Sys_ErrPrintf) {
// print the message again using the default error printer to increase // print the message again using the default error printer to increase
// the chances of the error being seen. // the chances of the error being seen.
#ifdef VA_LIST_IS_ARRAY va_copy (args, tmp_args);
VA_COPY (args, tmp_args);
#endif
Sys_ErrPrintf (error, args); Sys_ErrPrintf (error, args);
} }
@ -849,10 +896,13 @@ Sys_CreatePath (const char *path)
strcpy (e_path, path); strcpy (e_path, path);
for (ofs = e_path + 1; *ofs; ofs++) { for (ofs = e_path + 1; *ofs; ofs++) {
if (*ofs == '/') { // create the directory if (*ofs == '/') {
*ofs = 0; *ofs = 0;
if (Sys_mkdir (e_path) == -1) if (!Sys_isdir (e_path)) {
return -1; // create the directory
if (Sys_mkdir (e_path) == -1)
return -1;
}
*ofs = '/'; *ofs = '/';
} }
} }

View file

@ -1,10 +1,18 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
INCLUDES= -I$(top_srcdir)/include AM_CPPFLAGS= -I$(top_srcdir)/include
check_PROGRAMS= \ check_PROGRAMS= \
test-dq test-half test-mat3 test-mat4 test-plist test-qfs test-quat \ test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \
test-set test-vrect 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_SOURCES=test-dq.c
test_dq_LDADD=$(top_builddir)/libs/util/libQFutil.la 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_LDADD=$(top_builddir)/libs/util/libQFutil.la
test_quat_DEPENDENCIES=$(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_SOURCES=test-set.c
test_set_LDADD=$(top_builddir)/libs/util/libQFutil.la test_set_LDADD=$(top_builddir)/libs/util/libQFutil.la
test_set_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la test_set_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la

118
libs/util/test/test-bary.c Normal file
View 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
View 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
View 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
View 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;
}

View file

@ -6,8 +6,7 @@
#include "QF/set.h" #include "QF/set.h"
#define SIZE (DEFMAP_SIZE * sizeof (unsigned) * 8) #define SIZE (SET_DEFMAP_SIZE * sizeof (set_bits_t) * 8)
#define BITS (sizeof (((set_t *) 0)->map[0]) * 8)
typedef set_t *(*setup_func) (void); typedef set_t *(*setup_func) (void);
typedef set_t *(*op_func) (set_t *s1, const set_t *s2); 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_everything, 0, 0, check_size, SIZE, "{...}"},
{make_empty_invert, 0, 0, check_size, SIZE, "{...}"}, {make_empty_invert, 0, 0, check_size, SIZE, "{...}"},
{make_everything_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, {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" "{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" " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"

View file

@ -81,7 +81,7 @@ W_LoadWadFile (const char *filename)
int i; int i;
int infotableofs; int infotableofs;
wad_base = QFS_LoadHunkFile (filename); wad_base = QFS_LoadHunkFile (QFS_FOpenFile (filename));
if (!wad_base) if (!wad_base)
Sys_Error ("W_LoadWadFile: unable to load %s", filename); Sys_Error ("W_LoadWadFile: unable to load %s", filename);

View file

@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign
SUBDIRS= @vid_render_dirs@ SUBDIRS= @vid_render_dirs@
DIST_SUBDIRS= gl glsl sw sw32 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) \ lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \
-rpath $(libdir) -no-undefined -rpath $(libdir) -no-undefined

View file

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS= foreign AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
INCLUDES= -I$(top_srcdir)/include $(GLX_CFLAGS) AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS)
noinst_LTLIBRARIES= libgl.la noinst_LTLIBRARIES= libgl.la

View file

@ -229,7 +229,7 @@ gl_Draw_CachePic (const char *path, qboolean alpha)
if (!strcmp (path + strlen (path) - 4, ".lmp")) { if (!strcmp (path + strlen (path) - 4, ".lmp")) {
// Load the picture.. // 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) if (!dat)
Sys_Error ("Draw_CachePic: failed to load %s", path); Sys_Error ("Draw_CachePic: failed to load %s", path);

View file

@ -213,7 +213,7 @@ gl_R_ReadPointFile_f (void)
name = va ("%s.pts", mapname); name = va ("%s.pts", mapname);
free (mapname); free (mapname);
QFS_FOpenFile (name, &f); f = QFS_FOpenFile (name);
if (!f) { if (!f) {
Sys_Printf ("couldn't open %s\n", name); Sys_Printf ("couldn't open %s\n", name);
return; return;
@ -1185,8 +1185,12 @@ R_EntityParticles_ID (const entity_t *ent)
} }
if (!avelocities[0][0]) { if (!avelocities[0][0]) {
for (i = 0; i < NUMVERTEXNORMALS * 3; i++) for (i = 0; i < NUMVERTEXNORMALS; i++) {
avelocities[0][i] = (mtwist_rand (&mt) & 255) * 0.01; int k;
for (k = 0; k < 3; k++) {
avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01;
}
}
} }
for (i = 0; i < j; i++) { for (i = 0; i < j; i++) {

View file

@ -148,7 +148,7 @@ gl_R_Init (void)
"Load a pointfile to determine map leaks"); "Load a pointfile to determine map leaks");
Cmd_AddCommand ("loadsky", gl_R_LoadSky_f, "Load a skybox"); Cmd_AddCommand ("loadsky", gl_R_LoadSky_f, "Load a skybox");
Draw_Init (); gl_Draw_Init ();
SCR_Init (); SCR_Init ();
gl_R_InitBubble (); gl_R_InitBubble ();
@ -260,5 +260,5 @@ gl_R_TimeRefresh_f (void)
stop = Sys_DoubleTime (); stop = Sys_DoubleTime ();
time = stop - start; 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