summaryrefslogtreecommitdiff
path: root/games/fuhquake
diff options
context:
space:
mode:
authorMax Khon <fjoe@FreeBSD.org>2003-06-02 18:29:57 +0000
committerMax Khon <fjoe@FreeBSD.org>2003-06-02 18:29:57 +0000
commit6d680277e98d6fc123889cce8adbaa445a0fd31a (patch)
tree34aefdf81e1091ffbdd53b7160ad9d880ff01b65 /games/fuhquake
parentMake the metaport depend on ALL KDE modules, (diff)
New port: fuhquake
FuhQuake is an excellent QuakeWorld client. An excellent work by: Alexey Dokuchaev <danfe@regency.nsu.ru>
Notes
Notes: svn path=/head/; revision=82036
Diffstat (limited to 'games/fuhquake')
-rw-r--r--games/fuhquake/Makefile125
-rw-r--r--games/fuhquake/distinfo3
-rw-r--r--games/fuhquake/files/Makefile236
-rw-r--r--games/fuhquake/files/cd_freebsd.c426
-rw-r--r--games/fuhquake/files/fix^m.sh4
-rw-r--r--games/fuhquake/files/nonintel.c62
-rw-r--r--games/fuhquake/files/patch-cl_main.c29
-rw-r--r--games/fuhquake/files/patch-keys.c45
-rw-r--r--games/fuhquake/files/patch-keys.h18
-rw-r--r--games/fuhquake/files/patch-menu.c215
-rw-r--r--games/fuhquake/files/patch-modules.c11
-rw-r--r--games/fuhquake/files/patch-mp3_player.c19
-rw-r--r--games/fuhquake/files/patch-sv_sys_unix.c11
-rw-r--r--games/fuhquake/files/patch-vid_glx.c23
-rw-r--r--games/fuhquake/files/patch-vid_svga.c107
-rw-r--r--games/fuhquake/files/snd_freebsd.c279
-rw-r--r--games/fuhquake/pkg-descr5
-rw-r--r--games/fuhquake/pkg-message6
-rw-r--r--games/fuhquake/pkg-plist21
19 files changed, 1645 insertions, 0 deletions
diff --git a/games/fuhquake/Makefile b/games/fuhquake/Makefile
new file mode 100644
index 000000000000..e081a4925d71
--- /dev/null
+++ b/games/fuhquake/Makefile
@@ -0,0 +1,125 @@
+# New ports collection makefile for: FuhQuake
+# Date created: 01 Jun 2003
+# Whom: Alexey Dokuchaev <danfe@regency.nsu.ru>
+#
+# $FreeBSD$
+#
+
+PORTNAME= fuhquake
+PORTVERSION= 0.28
+CATEGORIES= games
+MASTER_SITES= http://www.fuhquake.net/files/source/:src \
+ http://www.fuhquake.net/files/releases/:dat \
+ http://freebsd.nsu.ru/distfiles/:pak
+DISTNAME= ${PORTNAME}-source-v${PORTVERSION}
+DISTFILES= ${DISTNAME}${EXTRACT_SUFX}:src \
+ ${PORTNAME}-linux-v${PORTVERSION}${EXTRACT_SUFX}:dat \
+ pak0.pak${EXTRACT_SUFX}:pak
+
+MAINTAINER= danfe@regency.nsu.ru
+COMMENT= An excellent QuakeWorld client
+
+.if exists(${LOCALBASE}/lib/libvga.so.1)
+WITH_SVGA= yes
+.endif
+
+.if exists(${X11BASE}/lib/libxmms.so.3)
+WITH_XMMS= yes
+.endif
+
+.if ${MACHINE_ARCH} == "i386" && !defined(WITHOUT_SVGA) && defined(WITH_SVGA)
+LIB_DEPENDS+= vga.1:${PORTSDIR}/graphics/svgalib
+END_TARGETS+= ${PORTNAME}-svga
+PLIST_SUB+= SVGA=""
+.else
+PLIST_SUB+= SVGA="@comment "
+.endif
+
+.if !defined(WITHOUT_X11)
+LIB_DEPENDS+= X11.6:${PORTSDIR}/x11/XFree86-4-libraries \
+ Xext.6:${PORTSDIR}/x11/XFree86-4-libraries
+END_TARGETS+= ${PORTNAME}-x11
+PLIST_SUB+= X11=""
+.else
+PLIST_SUB+= X11="@comment "
+.endif
+
+.if !defined(WITHOUT_GLX)
+LIB_DEPENDS+= GL.1:${PORTSDIR}/x11/XFree86-4-libraries \
+ png.5:${PORTSDIR}/graphics/png \
+ jpeg.9:${PORTSDIR}/graphics/jpeg
+END_TARGETS+= ${PORTNAME}-glx
+PLIST_SUB+= GLX=""
+.else
+PLIST_SUB+= GLX="@comment "
+.endif
+
+.if !defined(WITHOUT_XMMS) && defined(WITH_XMMS) && !(defined(WITHOUT_X11) && defined(WITHOUT_GLX))
+LIB_DEPENDS+= xmms.3:${PORTSDIR}/multimedia/xmms
+MAKE_ARGS+= -DWITH_XMMS
+.endif
+
+pre-everything::
+.if ${MACHINE_ARCH} == "i386" && !defined(WITH_SVGA)
+ @${ECHO_MSG} "Define WITH_SVGA to build SVGA client"
+.endif
+.if !defined(WITH_XMMS)
+ @${ECHO_MSG} "Define WITH_XMMS to enable \`\`MP3 Player'' feature"
+.endif
+.if !defined(WITHOUT_X11)
+ @${ECHO_MSG} "Define WITHOUT_X11 to disable building of X11 client"
+.endif
+.if !defined(WITHOUT_GLX)
+ @${ECHO_MSG} "Define WITHOUT_GLX to disable building of GLX client"
+.endif
+.if !defined(WITH_OPTIMIZED_CFLAGS)
+ @${ECHO_MSG} "Define WITH_OPTIMIZED_CFLAGS to enable extra optimization options"
+.endif
+.if !defined(WITHOUT_X86_ASM)
+ @${ECHO_MSG} "Define WITHOUT_X86_ASM to disable x86 assembly code"
+.endif
+
+MAKEFILE= ${FILESDIR}/Makefile
+USE_ZIP= yes
+EXTRACT_BEFORE_ARGS+= -qo
+WRKSRC= ${WRKDIR}/source
+
+post-extract:
+ @${FIND} -E ${WRKDIR} -type f -iregex ".*\.(c|h|s|txt)" -exec ${FILESDIR}/fix^m.sh '{}' \;
+ @${CP} ${FILESDIR}/*.c ${WRKSRC}
+
+do-build:
+.if !defined(WITHOUT_X11)
+ @(cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} ${MAKE} ${MAKE_FLAGS} ${MAKEFILE} ${MAKE_ARGS} clean x11)
+.endif
+
+.if !defined(WITHOUT_GLX)
+ @(cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} ${MAKE} ${MAKE_FLAGS} ${MAKEFILE} ${MAKE_ARGS} clean glx)
+.endif
+
+.if ${MACHINE_ARCH} == "i386" && defined(WITH_SVGA)
+ @(cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} ${MAKE} ${MAKE_FLAGS} ${MAKEFILE} ${MAKE_ARGS} clean svga)
+.endif
+
+do-install:
+.for tgt in ${END_TARGETS}
+ ${INSTALL_PROGRAM} ${WRKSRC}/${tgt} ${PREFIX}/bin
+.endfor
+ @${MKDIR} ${DATADIR}/qw
+ @${MKDIR} ${DATADIR}/${PORTNAME}
+ ${INSTALL_DATA} ${WRKDIR}/qw/qwprogs.dat ${DATADIR}/qw
+ ${INSTALL_DATA} ${WRKDIR}/qw/spprogs.dat ${DATADIR}/qw
+ ${INSTALL_DATA} ${WRKDIR}/pak0.pak ${DATADIR}/${PORTNAME}
+.if !defined(NOPORTDOCS)
+ @${MKDIR} ${DOCSDIR}
+. for txt in benchmark config_manager crosshairs linux logitech mp3 \
+ particles pointing rulesets track
+ ${INSTALL_DATA} ${WRKDIR}/doc/${txt}.txt ${DOCSDIR}
+. endfor
+ ${INSTALL_DATA} ${WRKDIR}/${PORTNAME}.txt ${DOCSDIR}
+.endif
+
+post-install:
+ @${SED} -e 's#$${PREFIX}#${PREFIX}#g' ${PKGMESSAGE}
+
+.include <bsd.port.mk>
diff --git a/games/fuhquake/distinfo b/games/fuhquake/distinfo
new file mode 100644
index 000000000000..c312d9c5eb48
--- /dev/null
+++ b/games/fuhquake/distinfo
@@ -0,0 +1,3 @@
+MD5 (fuhquake-source-v0.28.zip) = 7e77a97a1e1524b289ffa6978ce5377e
+MD5 (fuhquake-linux-v0.28.zip) = 72e99f8df1baab11e0492b7cee93fdd3
+MD5 (pak0.pak.zip) = eaedb54f2f0fabb1b621afb831185748
diff --git a/games/fuhquake/files/Makefile b/games/fuhquake/files/Makefile
new file mode 100644
index 000000000000..c0af2581d6be
--- /dev/null
+++ b/games/fuhquake/files/Makefile
@@ -0,0 +1,236 @@
+#
+# QuakeWorld/FuhQuake Makefile for FreeBSD
+#
+# - now should build on non-x86
+# - no longer requires gmake(1)
+# - debug targets support axed out
+# - couple of useful knobs added
+#
+# Created on Wednesday, May 21 2003 by Alexey Dokuchaev <danfe@regency.nsu.ru>
+#
+# $FreeBSD$
+#
+
+DO_CFLAGS = ${CFLAGS} -funsigned-char -I${LOCALBASE}/include -I${X11BASE}/include
+
+.if make(svga)
+DO_CFLAGS += -DNO_WINDOWED_MOUSE
+.undef WITHOUT_X86_ASM
+.endif
+
+.if ${MACHINE_ARCH} == "i386" && !defined(WITHOUT_X86_ASM)
+DO_CFLAGS += -Did386
+.endif
+
+.if make(glx)
+DO_CFLAGS += -DWITH_PNG -DWITH_JPEG -DGLQUAKE -DWITH_DGA -DWITH_VMODE
+.endif
+
+.if defined(WITH_OPTIMIZED_CFLAGS)
+DO_CFLAGS += -O9 -pipe -s -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations
+.endif
+
+.if defined(WITH_XMMS) && !make(svga)
+DO_CFLAGS += -D__XMMS__ `xmms-config --cflags`
+XMMS_LIBS = -L${X11BASE}/lib -lxmms
+. if ${OSVERSION} < 500016
+XMMS_LIBS+= -pthread
+. else
+XMMS_LIBS+= -lc_r
+. endif
+.endif
+
+########################################################################
+
+CL_COMMON_OBJS = \
+ host.o \
+ sys_linux.o \
+ nonintel.o \
+\
+ cd_freebsd.o \
+ snd_freebsd.o \
+ snd_dma.o \
+ snd_mem.o \
+ snd_mix.o \
+\
+ cl_input.o \
+ keys.o \
+\
+ net_chan.o \
+ net_udp.o \
+\
+ pr_cmds.o \
+ pr_edict.o \
+ pr_exec.o \
+\
+ pmove.o \
+ pmovetst.o \
+ sv_ccmds.o \
+ sv_ents.o \
+ sv_init.o \
+ sv_main.o \
+ sv_move.o \
+ sv_nchan.o \
+ sv_phys.o \
+ sv_save.o \
+ sv_send.o \
+ sv_user.o \
+ sv_world.o \
+\
+ cl_cam.o \
+ cl_cmd.o \
+ cl_demo.o \
+ cl_ents.o \
+ cl_main.o \
+ cl_parse.o \
+ cl_pred.o \
+ cl_slist.o \
+ cl_tent.o \
+ cl_view.o \
+\
+ cmd.o \
+ common.o \
+ console.o \
+ crc.o \
+ cvar.o \
+ image.o \
+ mathlib.o \
+ mdfour.o \
+ menu.o \
+ sbar.o \
+ skin.o \
+ teamplay.o \
+ version.o \
+ wad.o \
+ zone.o \
+\
+ auth.o \
+ config_manager.o \
+ fchecks.o \
+ fmod.o \
+ ignore.o \
+ logging.o \
+ modules.o \
+ movie.o \
+ mp3_player.o \
+ rulesets.o \
+ utils.o
+
+.if ${MACHINE_ARCH} == "i386" && !defined(WITHOUT_X86_ASM)
+CL_COMMON_AS_OBJS = \
+ cl_math.o \
+ math.o \
+ snd_mixa.o \
+ sys_x86.o
+.endif
+
+CL_SOFT_OBJS = \
+ d_edge.o \
+ d_fill.o \
+ d_init.o \
+ d_modech.o \
+ d_part.o \
+ d_polyse.o \
+ d_scan.o \
+ d_sky.o \
+ d_sprite.o \
+ d_surf.o \
+ d_vars.o \
+ d_zpoint.o \
+\
+ screen.o \
+\
+ r_aclip.o \
+ r_alias.o \
+ r_bsp.o \
+ r_draw.o \
+ r_edge.o \
+ r_efrag.o \
+ r_light.o \
+ r_main.o \
+ r_misc.o \
+ r_model.o \
+ r_part.o \
+ r_rast.o \
+ r_sky.o \
+ r_sprite.o \
+ r_surf.o \
+ r_vars.o
+
+.if ${MACHINE_ARCH} == "i386" && !defined(WITHOUT_X86_ASM)
+CL_SOFT_AS_OBJS = \
+ d_draw.o \
+ d_draw16.o \
+ d_parta.o \
+ d_polysa.o \
+ d_scana.o \
+ d_spr8.o \
+ d_varsa.o \
+ r_aclipa.o \
+ r_aliasa.o \
+ r_drawa.o \
+ r_edgea.o \
+ r_varsa.o \
+ surf16.o \
+ surf8.o
+.endif
+
+CL_X11_OBJS = vid_x11.o
+
+CL_GLX_OBJS = \
+ gl_draw.o \
+ gl_image.o \
+ gl_mesh.o \
+ gl_model.o \
+ gl_ngraph.o \
+ gl_refrag.o \
+ gl_rlight.o \
+ gl_rmain.o \
+ gl_rmisc.o \
+ gl_rpart.o \
+ gl_rsurf.o \
+ gl_screen.o \
+ gl_texture.o \
+ gl_warp.o \
+ r_part.o \
+ vid_common_gl.o \
+ vid_glx.o
+
+CL_SVGA_OBJS = vid_svgalib.o
+
+.if ${MACHINE_ARCH} == "i386" && !defined(WITHOUT_X86_ASM)
+CL_SVGA_AS_OBJS = d_copy.o
+.endif
+
+CL_COMMON_LIBS = -lm
+CL_X11_LIBS = -L${X11BASE}/lib -lX11 -lXext
+CL_SVGA_LIBS = -L${LOCALBASE}/lib -lvga
+CL_GLX_LIBS = -L${LOCALBASE}/lib -lpng -ljpeg -L${X11BASE}/lib -lGL -lXxf86dga -lXxf86vm
+
+.c.o:
+ ${CC} ${DO_CFLAGS} -c $< -o $*.o
+
+.s.o:
+ ${CC} ${DO_CFLAGS} -DELF -x assembler-with-cpp -c $< -o $*.o
+
+x11: ${CL_COMMON_OBJS} ${CL_COMMON_AS_OBJS} \
+ ${CL_SOFT_OBJS} ${CL_SOFT_AS_OBJS} ${CL_X11_OBJS}
+ ${CC} ${CFLAGS} -o fuhquake-x11 \
+ ${CL_COMMON_OBJS} ${CL_COMMON_AS_OBJS} ${CL_SOFT_OBJS} \
+ ${CL_SOFT_AS_OBJS} ${CL_X11_OBJS} \
+ ${CL_COMMON_LIBS} ${CL_X11_LIBS} ${XMMS_LIBS}
+
+glx: ${CL_COMMON_OBJS} ${CL_COMMON_AS_OBJS} ${CL_GLX_OBJS}
+ ${CC} ${CFLAGS} -o fuhquake-glx \
+ ${CL_COMMON_OBJS} ${CL_COMMON_AS_OBJS} ${CL_GLX_OBJS} \
+ ${CL_COMMON_LIBS} ${CL_GLX_LIBS} ${XMMS_LIBS}
+
+svga: ${CL_COMMON_OBJS} ${CL_COMMON_AS_OBJS} \
+ ${CL_SOFT_OBJS} ${CL_SOFT_AS_OBJS} ${CL_SVGA_OBJS} ${CL_SVGA_AS_OBJS}
+ ${CC} ${DO_CFLAGS} -o fuhquake-svga \
+ ${CL_COMMON_OBJS} ${CL_COMMON_AS_OBJS} ${CL_SOFT_OBJS} \
+ ${CL_SOFT_AS_OBJS} ${CL_SVGA_OBJS} ${CL_SVGA_AS_OBJS} \
+ ${CL_COMMON_LIBS} ${CL_SVGA_LIBS} ${XMMS_LIBS}
+
+clean:
+ -rm -f *.o *.core
diff --git a/games/fuhquake/files/cd_freebsd.c b/games/fuhquake/files/cd_freebsd.c
new file mode 100644
index 000000000000..5f911a47d992
--- /dev/null
+++ b/games/fuhquake/files/cd_freebsd.c
@@ -0,0 +1,426 @@
+/*
+Copyright (C) 2003 Alexey Dokuchaev.
+Copyright (C) 1996-1997 Id Software, Inc.
+
+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 included (GNU.txt) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// cd_freebsd.c
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/cdio.h>
+
+#include "quakedef.h"
+#include "cdaudio.h"
+#include "sound.h"
+
+/* Obtained from /usr/include/linux/cdrom.h */
+#define CDROM_DATA_TRACK 4
+
+static qboolean cdValid = false;
+static qboolean playing = false;
+static qboolean wasPlaying = false;
+static qboolean initialized = false;
+static qboolean enabled = true;
+static qboolean playLooping = false;
+static float cdvolume;
+static byte remap[100];
+static byte playTrack;
+static byte maxTrack;
+
+static int cdfile = -1;
+static char cd_dev[64] = "/dev/cdrom";
+
+static void CDAudio_Eject(void)
+{
+ if (cdfile == -1 || !enabled)
+ return; // no cd init'd
+
+ ioctl(cdfile, CDIOCALLOW);
+
+ if ( ioctl(cdfile, CDIOCEJECT) == -1 )
+ Com_DPrintf ("ioctl cdioceject failed\n");
+}
+
+
+static void CDAudio_CloseDoor(void)
+{
+ if (cdfile == -1 || !enabled)
+ return; // no cd init'd
+
+ ioctl(cdfile, CDIOCALLOW);
+
+ if ( ioctl(cdfile, CDIOCCLOSE) == -1 )
+ Com_DPrintf ("ioctl cdiocclose failed\n");
+}
+
+static int CDAudio_GetAudioDiskInfo(void)
+{
+ struct ioc_toc_header tochdr;
+
+ cdValid = false;
+
+ if ( ioctl(cdfile, CDIOREADTOCHEADER, &tochdr) == -1 )
+ {
+ Com_DPrintf ("ioctl cdioreadtocheader failed\n");
+ return -1;
+ }
+
+ if (tochdr.starting_track < 1)
+ {
+ Com_DPrintf ("CDAudio: no music tracks\n");
+ return -1;
+ }
+
+ cdValid = true;
+ maxTrack = tochdr.ending_track;
+
+ return 0;
+}
+
+
+void CDAudio_Play(byte track, qboolean looping)
+{
+ struct ioc_read_toc_single_entry entry;
+ struct ioc_play_track ti;
+
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!cdValid)
+ {
+ CDAudio_GetAudioDiskInfo();
+ if (!cdValid)
+ return;
+ }
+
+ track = remap[track];
+
+ if (track < 1 || track > maxTrack)
+ {
+ Com_DPrintf ("CDAudio: Bad track number %u.\n", track);
+ return;
+ }
+
+ // don't try to play a non-audio track
+ entry.track = track;
+ entry.address_format = CD_MSF_FORMAT;
+ if ( ioctl(cdfile, CDIOREADTOCENTRY, &entry) == -1 )
+ {
+ Com_DPrintf ("ioctl cdioreadtocentry failed\n");
+ return;
+ }
+ if (entry.entry.control == CDROM_DATA_TRACK)
+ {
+ Com_Printf ("CDAudio: track %i is not audio\n", track);
+ return;
+ }
+
+ if (playing)
+ {
+ if (playTrack == track)
+ return;
+ CDAudio_Stop();
+ }
+
+ ti.start_track = track;
+ ti.end_track = track;
+ ti.start_index = 1;
+ ti.start_index = 99;
+
+ if ( ioctl(cdfile, CDIOCPLAYTRACKS, &ti) == -1 )
+ {
+ Com_DPrintf ("ioctl cdiocplaytracks failed\n");
+ return;
+ }
+
+ if ( ioctl(cdfile, CDIOCRESUME) == -1 )
+ Com_DPrintf ("ioctl cdiocresume failed\n");
+
+ playLooping = looping;
+ playTrack = track;
+ playing = true;
+
+ if (cdvolume == 0.0)
+ CDAudio_Pause ();
+}
+
+
+void CDAudio_Stop(void)
+{
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!playing)
+ return;
+
+ if ( ioctl(cdfile, CDIOCSTOP) == -1 )
+ Com_DPrintf ("ioctl cdiocstop failed (%d)\n", errno);
+
+ ioctl(cdfile, CDIOCALLOW);
+
+ wasPlaying = false;
+ playing = false;
+}
+
+void CDAudio_Pause(void)
+{
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!playing)
+ return;
+
+ if ( ioctl(cdfile, CDIOCPAUSE) == -1 )
+ Com_DPrintf ("ioctl cdiocpause failed\n");
+
+ wasPlaying = playing;
+ playing = false;
+}
+
+
+void CDAudio_Resume(void)
+{
+ if (cdfile == -1 || !enabled)
+ return;
+
+ if (!cdValid)
+ return;
+
+ if (!wasPlaying)
+ return;
+
+ if ( ioctl(cdfile, CDIOCRESUME) == -1 )
+ Com_DPrintf ("ioctl cdiocresume failed\n");
+ playing = true;
+}
+
+static void CD_f (void)
+{
+ char *command;
+ int ret;
+ int n;
+
+ if (Cmd_Argc() < 2)
+ return;
+
+ command = Cmd_Argv (1);
+
+ if (Q_strcasecmp(command, "on") == 0)
+ {
+ enabled = true;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "off") == 0)
+ {
+ if (playing)
+ CDAudio_Stop();
+ enabled = false;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "reset") == 0)
+ {
+ enabled = true;
+ if (playing)
+ CDAudio_Stop();
+ for (n = 0; n < 100; n++)
+ remap[n] = n;
+ CDAudio_GetAudioDiskInfo();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "remap") == 0)
+ {
+ ret = Cmd_Argc() - 2;
+ if (ret <= 0)
+ {
+ for (n = 1; n < 100; n++)
+ if (remap[n] != n)
+ Com_Printf (" %u -> %u\n", n, remap[n]);
+ return;
+ }
+ for (n = 1; n <= ret; n++)
+ remap[n] = Q_atoi(Cmd_Argv (n+1));
+ return;
+ }
+
+ if (Q_strcasecmp(command, "close") == 0)
+ {
+ CDAudio_CloseDoor();
+ return;
+ }
+
+ if (!cdValid)
+ {
+ CDAudio_GetAudioDiskInfo();
+ if (!cdValid)
+ {
+ Com_Printf ("No CD in player.\n");
+ return;
+ }
+ }
+
+ if (Q_strcasecmp(command, "play") == 0)
+ {
+ CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
+ return;
+ }
+
+ if (Q_strcasecmp(command, "loop") == 0)
+ {
+ CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
+ return;
+ }
+
+ if (Q_strcasecmp(command, "stop") == 0)
+ {
+ CDAudio_Stop();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "pause") == 0)
+ {
+ CDAudio_Pause();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "resume") == 0)
+ {
+ CDAudio_Resume();
+ return;
+ }
+
+ if (Q_strcasecmp(command, "eject") == 0)
+ {
+ if (playing)
+ CDAudio_Stop();
+ CDAudio_Eject();
+ cdValid = false;
+ return;
+ }
+
+ if (Q_strcasecmp(command, "info") == 0)
+ {
+ Com_Printf ("%u tracks\n", maxTrack);
+ if (playing)
+ Com_Printf ("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+ else if (wasPlaying)
+ Com_Printf ("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
+ Com_Printf ("Volume is %f\n", cdvolume);
+ return;
+ }
+}
+
+void CDAudio_Update(void)
+{
+ struct ioc_read_subchannel subchnl;
+ struct cd_sub_channel_info data;
+ static time_t lastchk;
+
+ if (!enabled)
+ return;
+
+ if (bgmvolume.value != cdvolume)
+ {
+ if (cdvolume)
+ {
+ Cvar_SetValue (&bgmvolume, 0.0);
+ cdvolume = bgmvolume.value;
+ CDAudio_Pause ();
+ }
+ else
+ {
+ Cvar_SetValue (&bgmvolume, 1.0);
+ cdvolume = bgmvolume.value;
+ CDAudio_Resume ();
+ }
+ }
+
+ if (playing && lastchk < time(NULL)) {
+ lastchk = time(NULL) + 2; //two seconds between chks
+ bzero(&subchnl, sizeof(subchnl));
+ subchnl.data = &data;
+ subchnl.data_len = sizeof(data);
+ subchnl.address_format = CD_MSF_FORMAT;
+ subchnl.data_format = CD_CURRENT_POSITION;
+ if (ioctl(cdfile, CDIOCREADSUBCHANNEL, &subchnl) == -1 ) {
+ Com_DPrintf ("ioctl cdiocreadsubchannel failed\n");
+ playing = false;
+ return;
+ }
+ if (subchnl.data->header.audio_status != CD_AS_PLAY_IN_PROGRESS &&
+ subchnl.data->header.audio_status != CD_AS_PLAY_PAUSED) {
+ playing = false;
+ if (playLooping)
+ CDAudio_Play(playTrack, true);
+ }
+ }
+}
+
+int CDAudio_Init(void)
+{
+ int i;
+
+ if (!COM_CheckParm("-cdaudio"))
+ return -1;
+
+ if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1)
+ Q_strncpyz (cd_dev, com_argv[i + 1], sizeof(cd_dev));
+
+ if ((cdfile = open(cd_dev, O_RDONLY)) == -1) {
+ Com_Printf ("CDAudio_Init: open of \"%s\" failed (%i)\n", cd_dev, errno);
+ cdfile = -1;
+ return -1;
+ }
+
+ for (i = 0; i < 100; i++)
+ remap[i] = i;
+ initialized = true;
+ enabled = true;
+
+ if (CDAudio_GetAudioDiskInfo())
+ {
+ Com_Printf ("CDAudio_Init: No CD in player.\n");
+ cdValid = false;
+ }
+
+ Cmd_AddCommand ("cd", CD_f);
+
+ Com_Printf ("CD Audio Initialized\n");
+
+ return 0;
+}
+
+
+void CDAudio_Shutdown(void)
+{
+ if (!initialized)
+ return;
+ CDAudio_Stop();
+ close(cdfile);
+ cdfile = -1;
+}
diff --git a/games/fuhquake/files/fix^m.sh b/games/fuhquake/files/fix^m.sh
new file mode 100644
index 000000000000..897e1062fd17
--- /dev/null
+++ b/games/fuhquake/files/fix^m.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+tr -d '\r' < $1 > $1_
+mv -f $1_ $1
diff --git a/games/fuhquake/files/nonintel.c b/games/fuhquake/files/nonintel.c
new file mode 100644
index 000000000000..254bfaa72a1a
--- /dev/null
+++ b/games/fuhquake/files/nonintel.c
@@ -0,0 +1,62 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//
+// nonintel.c: code for non-Intel processors only
+//
+
+#include "common.h"
+
+#if !id386
+
+/*
+================
+R_Surf8Patch
+================
+*/
+void R_Surf8Patch ()
+{
+ // we only patch code on Intel
+}
+
+
+/*
+================
+R_Surf16Patch
+================
+*/
+void R_Surf16Patch ()
+{
+ // we only patch code on Intel
+}
+
+
+/*
+================
+R_SurfacePatch
+================
+*/
+void R_SurfacePatch (void)
+{
+ // we only patch code on Intel
+}
+
+
+#endif // !id386
+
diff --git a/games/fuhquake/files/patch-cl_main.c b/games/fuhquake/files/patch-cl_main.c
new file mode 100644
index 000000000000..41914c8ed66e
--- /dev/null
+++ b/games/fuhquake/files/patch-cl_main.c
@@ -0,0 +1,29 @@
+--- cl_main.c.orig Wed May 21 17:18:35 2003
++++ cl_main.c Sun May 25 20:30:58 2003
+@@ -43,6 +43,10 @@
+ #include "mp3_player.h"
+
+ #ifndef _WIN32
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
+ #include <netdb.h>
+ #endif
+
+@@ -857,13 +861,13 @@
+ Key_Init ();
+ V_Init ();
+
+-#ifdef __linux__
++#if defined(__linux__) || defined(__FreeBSD__)
+ IN_Init ();
+ #endif
+
+ VID_Init (host_basepal);
+
+-#ifndef __linux__
++#if !(defined(__linux__) || defined(__FreeBSD__))
+ IN_Init ();
+ #endif
+
diff --git a/games/fuhquake/files/patch-keys.c b/games/fuhquake/files/patch-keys.c
new file mode 100644
index 000000000000..fa7d9cce9015
--- /dev/null
+++ b/games/fuhquake/files/patch-keys.c
@@ -0,0 +1,45 @@
+--- keys.c.orig Mon Jun 2 22:41:44 2003
++++ keys.c Mon Jun 2 22:41:52 2003
+@@ -139,6 +139,13 @@
+ {"HOME", K_HOME},
+ {"END", K_END},
+
++ // Windows(tm) keys
++
++ {"K_WINDOW", K_WINDOW},
++ {"K_LWINDOW", K_LWINDOW},
++ {"K_RWINDOW", K_RWINDOW},
++ {"K_POPUPMENU", K_POPUPMENU},
++
+ {"MOUSE1", K_MOUSE1},
+ {"MOUSE2", K_MOUSE2},
+ {"MOUSE3", K_MOUSE3},
+@@ -969,7 +976,7 @@
+ if (b < 0 || b >= sizeof(keybindings))
+ return false;
+
+- return (b == K_CTRL || b == K_ALT || b == K_SHIFT) &&
++ return (b == K_CTRL || b == K_ALT || b == K_SHIFT || b == K_WINDOW) &&
+ (keybindings[b + 1] && keybindings[b + 2] && !strcmp(keybindings[b + 1], keybindings[b + 2]));
+ }
+
+@@ -1082,6 +1089,10 @@
+ consolekeys[K_SHIFT] = true;
+ consolekeys[K_LSHIFT] = true;
+ consolekeys[K_RSHIFT] = true;
++ consolekeys[K_WINDOW] = true;
++ consolekeys[K_LWINDOW] = true;
++ consolekeys[K_RWINDOW] = true;
++ consolekeys[K_POPUPMENU] = true;
+ consolekeys[K_MWHEELUP] = true;
+ consolekeys[K_MWHEELDOWN] = true;
+ consolekeys['`'] = false;
+@@ -1143,6 +1154,8 @@
+ Key_Event (K_CTRL, down);
+ else if (key == K_LSHIFT || key == K_RSHIFT)
+ Key_Event (K_SHIFT, down);
++ else if (key == K_LWINDOW || key == K_RWINDOW)
++ Key_Event (K_WINDOW, down);
+
+ keydown[key] = down;
+
diff --git a/games/fuhquake/files/patch-keys.h b/games/fuhquake/files/patch-keys.h
new file mode 100644
index 000000000000..6a4923b10b90
--- /dev/null
+++ b/games/fuhquake/files/patch-keys.h
@@ -0,0 +1,18 @@
+--- keys.h.orig Wed May 21 17:18:36 2003
++++ keys.h Sat May 24 18:25:24 2003
+@@ -96,6 +96,15 @@
+ KP_ENTER,
+
+ //
++// Windows(tm) keys
++//
++
++ K_WINDOW,
++ K_LWINDOW,
++ K_RWINDOW,
++ K_POPUPMENU,
++
++//
+ // mouse buttons generate virtual keys
+ //
+ K_MOUSE1 = 200,
diff --git a/games/fuhquake/files/patch-menu.c b/games/fuhquake/files/patch-menu.c
new file mode 100644
index 000000000000..0f4336c1a895
--- /dev/null
+++ b/games/fuhquake/files/patch-menu.c
@@ -0,0 +1,215 @@
+--- menu.c.orig Wed May 21 17:18:36 2003
++++ menu.c Tue May 27 23:06:19 2003
+@@ -62,6 +62,7 @@
+ void M_Menu_Fps_f (void);
+ void M_Menu_Video_f (void);
+ void M_Menu_MP3_Control_f (void);
++ void M_Menu_Help_f (void);
+ void M_Menu_Quit_f (void);
+
+ void M_Main_Draw (void);
+@@ -78,6 +79,7 @@
+ void M_Keys_Draw (void);
+ void M_Fps_Draw (void);
+ void M_Video_Draw (void);
++ void M_MP3_Control_Draw (void);
+ void M_Help_Draw (void);
+ void M_Quit_Draw (void);
+
+@@ -95,6 +97,7 @@
+ void M_Keys_Key (int key);
+ void M_Fps_Key (int key);
+ void M_Video_Key (int key);
++ void M_MP3_Control_Key (int key);
+ void M_Help_Key (int key);
+ void M_Quit_Key (int key);
+
+@@ -251,7 +254,11 @@
+ /* MAIN MENU */
+
+ int m_main_cursor;
++#if defined(_WIN32) || defined(__XMMS__)
++#define MAIN_ITEMS 6
++#else
+ #define MAIN_ITEMS 5
++#endif
+
+
+ void M_Menu_Main_f (void) {
+@@ -269,7 +276,13 @@
+ M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp") );
+ p = Draw_CachePic ("gfx/ttl_main.lmp");
+ M_DrawPic ( (320-p->width)/2, 4, p);
+- M_DrawTransPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp") );
++ M_DrawTransPic (72, 32, Draw_CachePic
++#if defined(_WIN32) || defined(__XMMS__)
++ ("gfx/mainmenu_mp3.lmp")
++#else
++ ("gfx/mainmenu.lmp")
++#endif
++ );
+
+ f = (int)(curtime * 10)%6;
+
+@@ -332,7 +345,19 @@
+ break;
+ #endif
+
++ #if defined(_WIN32) || defined(__XMMS__)
+ case 4:
++ #else
++ case 3:
++ #endif
++ M_Menu_Help_f ();
++ break;
++
++ #if defined(_WIN32) || defined(__XMMS__)
++ case 5:
++ #else
++ case 4:
++ #endif
+ M_Menu_Quit_f ();
+ break;
+ }
+@@ -442,9 +467,11 @@
+ Cvar_SetValue (&cl_hudswap, !cl_hudswap.value);
+ break;
+
++#ifndef NO_WINDOWED_MOUSE
+ case 17: // _windowed_mouse
+ Cvar_SetValue (&_windowed_mouse, !_windowed_mouse.value);
+ break;
++#endif
+ }
+ }
+
+@@ -491,25 +518,25 @@
+ r = v_contrast.value - 1.0;
+ M_DrawSlider (220, 72, r);
+
+- M_Print (16, 80, " Mouse Speed");
++ M_Print (16, 80, " Mouse speed");
+ r = (sensitivity.value - 1)/10;
+ M_DrawSlider (220, 80, r);
+
+- M_Print (16, 88, " CD Music Volume");
++ M_Print (16, 88, " CD music volume");
+ r = bgmvolume.value;
+ M_DrawSlider (220, 88, r);
+
+- M_Print (16, 96, " Sound Volume");
++ M_Print (16, 96, " Sound volume");
+ r = s_volume.value;
+ M_DrawSlider (220, 96, r);
+
+- M_Print (16, 104, " Always Run");
++ M_Print (16, 104, " Always run");
+ M_DrawCheckbox (220, 104, cl_forwardspeed.value > 200);
+
+ M_Print (16, 112, " Mouse look");
+ M_DrawCheckbox (220, 112, freelook.value);
+
+- M_Print (16, 120, " Invert Mouse");
++ M_Print (16, 120, " Invert mouse");
+ M_DrawCheckbox (220, 120, m_pitch.value < 0);
+
+ M_Print (16, 128, " Lookstrafe");
+@@ -524,17 +551,19 @@
+ M_Print (16, 152, " FPS settings");
+
+ if (vid_menudrawfn)
+- M_Print (16, 160, " Video Modes");
++ M_Print (16, 160, " Video modes");
+
++#ifndef NO_WINDOWED_MOUSE
+ #ifdef _WIN32
+ if (modestate == MS_WINDOWED)
+ {
+ #endif
+- M_Print (16, 168, " Use Mouse");
++ M_Print (16, 168, " Use mouse");
+ M_DrawCheckbox (220, 168, _windowed_mouse.value);
+ #ifdef _WIN32
+ }
+ #endif
++#endif /* NO_WINDOWED_MOUSE */
+
+ // cursor
+ M_DrawCharacter (200, 32 + options_cursor*8, 12+((int)(curtime*4)&1));
+@@ -611,22 +640,34 @@
+ break;
+ }
+
+- if (options_cursor == 16 && vid_menudrawfn == NULL) {
+- if (k == K_UPARROW || k == K_END || k == K_PGDN)
++ if (k == K_UPARROW || k == K_END || k == K_PGDN)
++ {
++#ifdef NO_WINDOWED_MOUSE
++ if ((options_cursor == 17)
++#ifdef _WIN32
++ && (modestate != MS_WINDOWED)
++#endif
++ )
++ options_cursor = 16;
++#endif /* NO_WINDOWED_MOUSE */
++
++ if (options_cursor == 16 && vid_menudrawfn == NULL)
+ options_cursor = 15;
+- else
+- options_cursor = 0;
+ }
++ else
++ {
++ if (options_cursor == 16 && vid_menudrawfn == NULL)
++ options_cursor = 17;
+
+- if ((options_cursor == 17)
++#ifdef NO_WINDOWED_MOUSE
++ if ((options_cursor == 17)
+ #ifdef _WIN32
+- && (modestate != MS_WINDOWED)
++ && (modestate != MS_WINDOWED)
+ #endif
+- )
+- if (k == K_UPARROW || k == K_END || k == K_PGDN)
+- options_cursor = 16;
+- else
+- options_cursor = 0;
++ )
++ options_cursor = 0;
++#endif /* NO_WINDOWED_MOUSE */
++ }
+ }
+
+
+@@ -894,24 +935,24 @@
+ M_Print (16, 96, " Pickup flashes");
+ M_DrawCheckbox (220, 96, v_bonusflash.value);
+
+- M_Print (16, 104, " Powerup glow");
++ M_Print (16, 104, " Powerup glow");
+ M_Print (220, 104, r_powerupglow.value==2 ? "own off" :
+ r_powerupglow.value ? "on" : "off");
+
+- M_Print (16, 112, " Draw torches");
++ M_Print (16, 112, " Draw torches");
+ M_DrawCheckbox (220, 112, r_drawflame.value);
+
+- M_Print (16, 120, " Fast sky");
++ M_Print (16, 120, " Fast sky");
+ M_DrawCheckbox (220, 120, r_fastsky.value);
+
+ #ifdef GLQUAKE
+- M_Print (16, 128, " Fast lights");
++ M_Print (16, 128, " Fast lights");
+ M_DrawCheckbox (220, 128, gl_flashblend.value);
+ #endif
+
+- M_PrintWhite (16, 136, " Fast mode");
++ M_PrintWhite (16, 136, " Fast mode");
+
+- M_PrintWhite (16, 144, " High quality");
++ M_PrintWhite (16, 144, " High quality");
+
+ // cursor
+ M_DrawCharacter (200, 32 + fps_cursor*8, 12+((int)(curtime*4)&1));
diff --git a/games/fuhquake/files/patch-modules.c b/games/fuhquake/files/patch-modules.c
new file mode 100644
index 000000000000..1f7b9677d38a
--- /dev/null
+++ b/games/fuhquake/files/patch-modules.c
@@ -0,0 +1,11 @@
+--- modules.c.orig Wed May 21 17:18:36 2003
++++ modules.c Wed May 21 17:22:37 2003
+@@ -22,7 +22,7 @@
+ #include "modules.h"
+ #include "version.h"
+
+-#ifdef __linux
++#if defined(__linux__) || defined(__FreeBSD__)
+ #include <dlfcn.h>
+ #endif
+
diff --git a/games/fuhquake/files/patch-mp3_player.c b/games/fuhquake/files/patch-mp3_player.c
new file mode 100644
index 000000000000..986c0a1699f2
--- /dev/null
+++ b/games/fuhquake/files/patch-mp3_player.c
@@ -0,0 +1,19 @@
+--- mp3_player.c.orig Wed May 21 17:18:36 2003
++++ mp3_player.c Wed May 21 17:21:23 2003
+@@ -48,6 +48,7 @@
+
+ #ifdef __XMMS__
+
++#include <sys/signal.h>
+ #include <sys/wait.h>
+
+ cvar_t mp3_dir = {"mp3_xmms_dir", "/usr/local/bin"};
+@@ -769,7 +770,7 @@
+
+ #endif
+
+-#ifdef __linux__
++#if defined(__linux__) || defined(__FreeBSD__)
+
+ #ifdef __XMMS__
+
diff --git a/games/fuhquake/files/patch-sv_sys_unix.c b/games/fuhquake/files/patch-sv_sys_unix.c
new file mode 100644
index 000000000000..5182ac61a7cc
--- /dev/null
+++ b/games/fuhquake/files/patch-sv_sys_unix.c
@@ -0,0 +1,11 @@
+--- sv_sys_unix.c.orig Wed May 21 17:18:37 2003
++++ sv_sys_unix.c Wed May 21 15:09:31 2003
+@@ -24,7 +24,7 @@
+ #include <libc.h>
+ #endif
+
+-#if defined(__linux__) || defined(sun)
++#if defined(__linux__) || defined(__FreeBSD__) || defined(sun)
+ #include <sys/stat.h>
+ #include <unistd.h>
+ #include <sys/time.h>
diff --git a/games/fuhquake/files/patch-vid_glx.c b/games/fuhquake/files/patch-vid_glx.c
new file mode 100644
index 000000000000..6c8185c62e47
--- /dev/null
+++ b/games/fuhquake/files/patch-vid_glx.c
@@ -0,0 +1,23 @@
+--- vid_glx.c.orig Wed May 21 17:18:37 2003
++++ vid_glx.c Mon Jun 2 20:04:34 2003
+@@ -20,7 +20,9 @@
+ #include <termios.h>
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
++#ifdef __linux__
+ #include <sys/vt.h>
++#endif
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <signal.h>
+@@ -601,8 +603,9 @@
+ #ifdef WITH_VMODE
+ // fullscreen
+ if (vidmode_active) {
+- mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask;
++ mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask | CWOverrideRedirect;
+ attr.backing_store = NotUseful;
++ attr.override_redirect = True;
+ attr.save_under = False;
+ }
+ #endif
diff --git a/games/fuhquake/files/patch-vid_svga.c b/games/fuhquake/files/patch-vid_svga.c
new file mode 100644
index 000000000000..de3107eee109
--- /dev/null
+++ b/games/fuhquake/files/patch-vid_svga.c
@@ -0,0 +1,107 @@
+--- vid_svgalib.c.orig Thu May 29 17:56:45 2003
++++ vid_svgalib.c Thu May 29 17:56:28 2003
+@@ -20,12 +20,18 @@
+ #include <termios.h>
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
++#ifdef __linux__
+ #include <sys/vt.h>
++#endif
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <signal.h>
+
++#if defined(__linux__)
+ #include <asm/io.h>
++#elif defined(__FreeBSD__)
++#include <machine/cpufunc.h>
++#endif
+
+ #include "vga.h"
+ #include "vgakeyboard.h"
+@@ -92,7 +98,6 @@
+ float old_mouse_x, old_mouse_y;
+ int mx, my;
+
+-cvar_t _windowed_mouse = {"_windowed_mouse", "1", CVAR_ARCHIVE}; //dummy for menu.c
+ cvar_t m_filter = {"m_filter","0"};
+ cvar_t cl_keypad = {"cl_keypad", "1"};
+
+@@ -330,45 +335,41 @@
+ }
+
+ static byte scantokey_kp[128] = {
+-// 0 1 2 3 4 5 6 7
+-// 8 9 A B C D E F
+- 0 , K_ESCAPE,'1', '2', '3', '4', '5', '6',
+- '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
+- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+- 'o', 'p', '[', ']', K_ENTER,K_LCTRL, 'a', 's', // 1
+- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+- '\'', '`', K_LSHIFT,'\\', 'z', 'x', 'c', 'v', // 2
+- 'b', 'n', 'm', ',', '.', '/', K_RSHIFT,KP_STAR,
+- K_LALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
+- K_F6, K_F7, K_F8, K_F9, K_F10, KP_NUMLOCK,K_SCRLCK,KP_HOME,
+- KP_UPARROW,KP_PGUP,KP_MINUS,KP_LEFTARROW,KP_5,KP_RIGHTARROW,KP_PLUS,KP_END, // 4
+- KP_DOWNARROW,KP_PGDN,KP_INS,KP_DEL, 0, 0, 0, K_F11,
+- K_F12, 0, 0, 0, 0, 0, 0, 0, // 5
+- KP_ENTER,K_RCTRL,KP_SLASH,0, K_RALT, K_PAUSE,K_HOME, K_UPARROW,
+- K_PGUP, K_LEFTARROW,K_RIGHTARROW,K_END, K_DOWNARROW,K_PGDN,K_INS,K_DEL, // 6
+- 0, 0, 0, 0, 0, 0, 0, K_PAUSE,
+- 0, 0, 0, 0, 0, 0, 0, 0 // 7
++ 0, K_ESCAPE, '1', '2', '3', '4', '5', '6',
++ '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9,
++ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
++ 'o', 'p', '[', ']', K_ENTER, K_LCTRL, 'a', 's',
++ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
++ '\'', '`', K_LSHIFT, '\\', 'z', 'x', 'c', 'v',
++ 'b', 'n', 'm', ',', '.', '/', K_RSHIFT, KP_STAR,
++ K_LALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5,
++ K_F6, K_F7, K_F8, K_F9, K_F10, KP_NUMLOCK, K_SCRLCK, KP_HOME,
++ KP_UPARROW, KP_PGUP, KP_MINUS, KP_LEFTARROW, KP_5, KP_RIGHTARROW, KP_PLUS, KP_END,
++ KP_DOWNARROW, KP_PGDN, KP_INS, KP_DEL, 0, 0, 0, K_F11,
++ K_F12, KP_ENTER, K_RCTRL, KP_SLASH, K_PRINTSCR, K_RALT, K_HOME, K_UPARROW,
++ K_PGUP, K_LEFTARROW, K_RIGHTARROW, K_END, K_DOWNARROW, K_PGDN, K_INS, K_DEL,
++ K_PAUSE, K_LWINDOW, K_RWINDOW, K_POPUPMENU, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ static byte scantokey[128] = {
+-// 0 1 2 3 4 5 6 7
+-// 8 9 A B C D E F
+- 0 , K_ESCAPE,'1', '2', '3', '4', '5', '6',
+- '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
+- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+- 'o', 'p', '[', ']', K_ENTER,K_LCTRL, 'a', 's', // 1
+- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+- '\'', '`', K_LSHIFT,'\\', 'z', 'x', 'c', 'v', // 2
+- 'b', 'n', 'm', ',', '.', '/', K_RSHIFT,KP_STAR,
+- K_LALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
+- K_F6, K_F7, K_F8, K_F9, K_F10, KP_NUMLOCK,K_SCRLCK,K_HOME,
+- K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+', K_END, // 4
+- K_DOWNARROW,K_PGDN,K_INS,K_DEL, 0, 0, 0, K_F11,
+- K_F12, 0, 0, 0, 0, 0, 0, 0, // 5
+- K_ENTER,K_RCTRL,'/', 0, K_RALT, K_PAUSE,K_HOME, K_UPARROW,
+- K_PGUP, K_LEFTARROW,K_RIGHTARROW,K_END, K_DOWNARROW,K_PGDN,K_INS,K_DEL, // 6
+- 0, 0, 0, 0, 0, 0, 0, K_PAUSE,
+- 0, 0, 0, 0, 0, 0, 0, 0 // 7
++ 0, K_ESCAPE, '1', '2', '3', '4', '5', '6',
++ '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9,
++ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
++ 'o', 'p', '[', ']', K_ENTER, K_LCTRL, 'a', 's',
++ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
++ '\'', '`', K_LSHIFT, '\\', 'z', 'x', 'c', 'v',
++ 'b', 'n', 'm', ',', '.', '/', K_RSHIFT, KP_STAR,
++ K_LALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5,
++ K_F6, K_F7, K_F8, K_F9, K_F10, KP_NUMLOCK, K_SCRLCK, K_HOME,
++ K_UPARROW, K_PGUP, '-', K_LEFTARROW, '5', K_RIGHTARROW, '+', K_END,
++ K_DOWNARROW, K_PGDN, K_INS, K_DEL, 0, 0, 0, K_F11,
++ K_F12, K_ENTER, K_RCTRL, '/', K_PRINTSCR, K_RALT, K_HOME, K_UPARROW,
++ K_PGUP, K_LEFTARROW, K_RIGHTARROW, K_END, K_DOWNARROW, K_PGDN, K_INS, K_DEL,
++ K_PAUSE, K_LWINDOW, K_RWINDOW, K_POPUPMENU, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ void keyhandler(int scancode, int state) {
diff --git a/games/fuhquake/files/snd_freebsd.c b/games/fuhquake/files/snd_freebsd.c
new file mode 100644
index 000000000000..9cab11f472ee
--- /dev/null
+++ b/games/fuhquake/files/snd_freebsd.c
@@ -0,0 +1,279 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#if defined(__linux__)
+#include <linux/soundcard.h>
+#elif defined(__FreeBSD__)
+#include <sys/soundcard.h>
+#endif
+#include <stdio.h>
+
+#include "quakedef.h"
+#include "sound.h"
+
+int audio_fd;
+int snd_inited;
+const char *snddev = "/dev/dsp";
+
+static int tryrates[] = { 11025, 22051, 44100, 8000 };
+
+qboolean
+SNDDMA_Init(void)
+{
+ int tmp;
+ char *s;
+ struct audio_buf_info info;
+
+ snd_inited = 0;
+
+ if (s = getenv("SNDDEV"))
+ snddev = s;
+ if (tmp = COM_CheckParm("-snddev"))
+ snddev = com_argv[tmp + 1];
+
+ /*
+ * Open audio device, confirm capability to mmap,
+ * and get size of DMA buffer.
+ */
+
+ if ((audio_fd = open(snddev, O_RDWR)) < 0)
+ {
+ perror(snddev);
+ Com_Printf("Could not open %s\n", snddev);
+ return (0);
+ }
+
+ if (ioctl(audio_fd, SNDCTL_DSP_RESET, 0) < 0)
+ {
+ perror(snddev);
+ Com_Printf("Could not reset %s\n", snddev);
+ close(audio_fd);
+ return (0);
+ }
+
+ if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &tmp) == -1)
+ {
+ perror(snddev);
+ Com_Printf("Sound driver too old\n");
+ close(audio_fd);
+ return (0);
+ }
+
+ if (!(tmp & DSP_CAP_TRIGGER) || !(tmp & DSP_CAP_MMAP))
+ {
+ Com_Printf("Sorry, but your soundcard cannot do memory-mapped I/O\n");
+ close(audio_fd);
+ return (0);
+ }
+
+ if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
+ {
+ perror(snddev);
+ Com_Printf("Um, cannot do GETOSPACE?\n");
+ close(audio_fd);
+ return (0);
+ }
+
+ shm = &sn;
+ shm->splitbuffer = 0;
+
+ /* Set sample bits & speed. */
+
+ if (s = getenv("QUAKE_SOUND_SAMPLEBITS"))
+ shm->samplebits = atoi(s);
+ else if (tmp = COM_CheckParm("-sndbits"))
+ shm->samplebits = atoi(com_argv[tmp + 1]);
+
+ if (shm->samplebits != 16 && shm->samplebits != 8)
+ {
+ ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
+ if (tmp & AFMT_S16_LE)
+ shm->samplebits = 16;
+ else if (tmp & AFMT_U8)
+ shm->samplebits = 8;
+ else {
+ Com_Printf("Could not set sample format\n");
+ close(audio_fd);
+ return (0);
+ }
+ }
+
+ if (s = getenv("QUAKE_SOUND_SPEED"))
+ shm->speed = atoi(s);
+ else if (tmp = COM_CheckParm("-sndspeed"))
+ shm->speed = atoi(com_argv[tmp + 1]);
+ else
+ {
+ for (tmp = 0; tmp < sizeof(tryrates) / 4; tmp++)
+ if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[tmp]))
+ break;
+ shm->speed = tryrates[tmp];
+ }
+
+ if (s = getenv("QUAKE_SOUND_CHANNELS"))
+ shm->channels = atoi(s);
+ else if (tmp = COM_CheckParm("-sndmono"))
+ shm->channels = 1;
+ else shm->channels = 2;
+
+ shm->samples = info.fragstotal * info.fragsize / (shm->samplebits / 8);
+ shm->submission_chunk = 1;
+
+ if (shm->channels == 2)
+ tmp = 1;
+ else
+ tmp = 0;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp) < 0)
+ {
+ perror(snddev);
+ Com_Printf("Could not set %s to stereo = %d\n", snddev, shm->channels);
+ close(audio_fd);
+ return (0);
+ }
+
+ Com_Printf("Sound using stereo = %d\n", shm->channels);
+
+ if (tmp)
+ shm->channels = 2;
+ else
+ shm->channels = 1;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &shm->speed) < 0)
+ {
+ perror(snddev);
+ Com_Printf("Could not set %s speed to %d\n", snddev, shm->speed);
+ close(audio_fd);
+ return (0);
+ }
+
+ Com_Printf("Sound on speed = %d\n", shm->speed);
+
+ if (shm->samplebits == 16)
+ {
+ tmp = AFMT_S16_LE;
+ if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp))
+ {
+ perror(snddev);
+ Com_Printf("Could not support 16-bit data, try 8-bit\n");
+ close(audio_fd);
+ return (0);
+ }
+ }
+ else if (shm->samplebits == 8)
+ {
+ tmp = AFMT_U8;
+ if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp))
+ {
+ perror(snddev);
+ Com_Printf("Could not support 8-bit data\n");
+ close(audio_fd);
+ return (0);
+ }
+ }
+ else {
+ perror(snddev);
+ Com_Printf("%d-bit sound not supported\n", shm->samplebits);
+ close(audio_fd);
+ return (0);
+ }
+
+ Com_Printf("%s is set to %d-bit format.\n", snddev, shm->samplebits);
+
+ /* Finally, memory map the DMA buffer. */
+
+ shm->buffer = (unsigned char *)mmap(NULL, info.fragstotal
+ * info.fragsize,
+#ifdef __FreeBSD__
+ PROT_READ | PROT_WRITE,
+#else
+ PROT_WRITE,
+#endif
+ MAP_FILE | MAP_SHARED, audio_fd, 0);
+
+ if (!shm->buffer || shm->buffer == MAP_FAILED)
+ {
+ perror(snddev);
+ Com_Printf("Could not mmap %s\n", snddev);
+ close(audio_fd);
+ return (0);
+ }
+
+ /* Toggle the trigger & start her up. */
+
+ tmp = 0;
+ if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0)
+ {
+ perror(snddev);
+ Com_Printf("Could not toggle\n");
+ munmap(shm->buffer, shm->samples * shm->samplebits / 8);
+ close(audio_fd);
+ return (0);
+ }
+
+ tmp = PCM_ENABLE_OUTPUT;
+ if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0)
+ {
+ perror(snddev);
+ Com_Printf("Could not toggle\n");
+ close(audio_fd);
+ return (0);
+ }
+
+ shm->samplepos = 0;
+ snd_inited = 1;
+
+ return (1);
+}
+
+int
+SNDDMA_GetDMAPos(void)
+{
+ struct count_info count;
+
+ if (!snd_inited)
+ return (0);
+
+ if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1)
+ {
+ perror(snddev);
+ Com_Printf("Uh, sound dead\n");
+ close(audio_fd);
+ snd_inited = 0;
+ return (0);
+ }
+
+ /* shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
+ fprintf(stderr, "%d \r", count.ptr); */
+
+ shm->samplepos = count.ptr / (shm->samplebits / 8);
+
+ return (shm->samplepos);
+}
+
+void
+SNDDMA_Shutdown(void)
+{
+ if (snd_inited)
+ {
+ close(audio_fd);
+ snd_inited = 0;
+ }
+}
+
+/*
+==============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the DMA buffer
+===============
+*/
+void
+SNDDMA_Submit(void)
+{
+}
diff --git a/games/fuhquake/pkg-descr b/games/fuhquake/pkg-descr
new file mode 100644
index 000000000000..07a7b7cc9887
--- /dev/null
+++ b/games/fuhquake/pkg-descr
@@ -0,0 +1,5 @@
+FuhQuake is a QuakeWorld client that aims to not only to have a plethora
+of gameplay and console improvements, but to also incorporate stunning
+visual effects and eyecandy.
+
+WWW: http://www.fuhquake.net/
diff --git a/games/fuhquake/pkg-message b/games/fuhquake/pkg-message
new file mode 100644
index 000000000000..48041f03ad08
--- /dev/null
+++ b/games/fuhquake/pkg-message
@@ -0,0 +1,6 @@
+================================================
+
+ Install models, skins, maps, and mods in
+ ${PREFIX}/share/fuhquake/
+
+================================================
diff --git a/games/fuhquake/pkg-plist b/games/fuhquake/pkg-plist
new file mode 100644
index 000000000000..793477bfff46
--- /dev/null
+++ b/games/fuhquake/pkg-plist
@@ -0,0 +1,21 @@
+%%X11%%bin/fuhquake-x11
+%%GLX%%bin/fuhquake-glx
+%%SVGA%%bin/fuhquake-svga
+%%PORTDOCS%%share/doc/fuhquake/benchmark.txt
+%%PORTDOCS%%share/doc/fuhquake/config_manager.txt
+%%PORTDOCS%%share/doc/fuhquake/crosshairs.txt
+%%PORTDOCS%%share/doc/fuhquake/fuhquake.txt
+%%PORTDOCS%%share/doc/fuhquake/linux.txt
+%%PORTDOCS%%share/doc/fuhquake/logitech.txt
+%%PORTDOCS%%share/doc/fuhquake/mp3.txt
+%%PORTDOCS%%share/doc/fuhquake/particles.txt
+%%PORTDOCS%%share/doc/fuhquake/pointing.txt
+%%PORTDOCS%%share/doc/fuhquake/rulesets.txt
+%%PORTDOCS%%share/doc/fuhquake/track.txt
+%%PORTDOCS%%@dirrm share/doc/fuhquake
+share/fuhquake/fuhquake/pak0.pak
+share/fuhquake/qw/qwprogs.dat
+share/fuhquake/qw/spprogs.dat
+@dirrm share/fuhquake/qw
+@dirrm share/fuhquake/fuhquake
+@dirrm share/fuhquake