Added Quake III arena unix/win32 folders

This commit is contained in:
L 2023-05-08 22:58:54 +02:00
parent 8451cff91e
commit c7f877c8b4
84 changed files with 46109 additions and 47 deletions

View file

@ -89,19 +89,32 @@ file(GLOB_RECURSE SOURCES_BG "code/game/bg_*.cpp")
### Platform-specific code
if(WIN32)
set(SOURCES_PLATFORM_SPECIFIC
"code/sys/con_win32.c"
"code/sys/sys_win32.c"
"code/sys/win_bounds.cpp"
"code/sys/win_localization.cpp"
"code/sys/win_resource.rc"
WIN32
"code/win32/win_bounds.cpp"
"code/win32/win_input.c"
"code/win32/win_localization.cpp"
"code/win32/win_main.c"
"code/win32/win_net.c"
"code/win32/win_shared.c"
"code/win32/win_syscon.c"
"code/win32/win_wndproc.c"
"code/win32/win_resource.rc"
)
set(SOURCES_CLIENT_PLATFORM_SPECIFIC
"code/win32/win_gamma.c"
"code/win32/win_glimp.c"
"code/win32/win_qgl.c"
"code/win32/win_snd.c"
)
else()
set(SOURCES_PLATFORM_SPECIFIC
"code/sys/con_tty.c"
"code/sys/sys_unix.c"
"code/unix/unix_main.c"
"code/unix/unix_net.c"
"code/unix/unix_shared.c"
# These are still used even they're prefixed 'win'
"code/sys/win_bounds.cpp"
"code/sys/win_localization.cpp"
"code/win32/win_bounds.cpp"
"code/win32/win_localization.cpp"
)
endif()
@ -127,16 +140,11 @@ set(SOURCES_COMMON
"code/qcommon/memory.c"
"code/qcommon/msg.cpp"
"code/qcommon/net_chan.c"
"code/qcommon/net_ip.c"
"code/qcommon/q_math.c"
"code/qcommon/q_shared.c"
"code/qcommon/tiki_main.cpp"
"code/qcommon/tiki_script.cpp"
"code/qcommon/unzip.c"
# Main stuff
"code/sys/sys_main.c"
"code/sys/sys_autoupdater.c"
"code/sys/con_log.c"
# Gamespy
"code/gamespy/sv_gamespy.c"
"code/gamespy/sv_gqueryreporting.c"
@ -172,7 +180,7 @@ include("code/gamespy/gcd.cmake")
file(GLOB_RECURSE SOURCES_SERVER "code/server/*.c" "code/server/*.cpp")
set(SOURCES_SERVER_APP ${SOURCES_APP} ${SOURCES_SERVER})
add_executable(omohaaded ${SOURCES_SERVER_APP} ${SOURCES_PLATFORM_SPECIFIC} "code/null/null_client.c" "code/null/null_input.c" "code/null/null_snddma.c")
add_executable(omohaaded ${SOURCES_PLATFORM_SPECIFIC} ${SOURCES_SERVER_APP} "code/null/null_client.c" "code/null/null_snddma.c")
target_compile_definitions(omohaaded PRIVATE NO_SCRIPTENGINE APP_MODULE DEDICATED TARGET_GAME_TYPE=${TARGET_GAME_TYPE})
target_compile_features(omohaaded PUBLIC cxx_nullptr)
target_compile_features(omohaaded PUBLIC c_variadic_macros)
@ -196,6 +204,7 @@ elseif(UNIX)
endif()
INSTALL(TARGETS omohaaded DESTINATION "./")
INSTALL(FILES $<TARGET_PDB_FILE:omohaaded> DESTINATION "./" OPTIONAL)
if (WITH_CLIENT)
## Client
@ -223,9 +232,10 @@ if (WITH_CLIENT)
# file(GLOB_RECURSE SOURCES_CLIENT "code/client/*.c" "code/client/*.cpp" "code/qcommon/puff.c")
# file(GLOB_RECURSE SOURCES_UILIB "code/uilib/*.c" "code/uilib/*.cpp")
# file(GLOB_RECURSE SOURCES_RENDERER "code/renderer/*.c" "code/renderer/*.cpp")
# #file(GLOB_RECURSE SOURCES_RENDERER "code/sdl/*.c" "code/renderercommon/*.c" "code/renderergl2/*.c" "code/renderergl2/*.cpp")
# set(SOURCES_CLIENT_APP ${SOURCES_APP} ${SOURCES_SERVER} ${SOURCES_CLIENT} ${SOURCES_UILIB} ${SOURCES_LIBS} ${SOURCES_RENDERER})
#
# add_executable(openmohaa ${SOURCES_CLIENT_APP} ${SOURCES_PLATFORM_SPECIFIC})
# add_executable(openmohaa ${SOURCES_PLATFORM_SPECIFIC} ${SOURCES_CLIENT_APP} ${SOURCES_CLIENT_PLATFORM_SPECIFIC})
# target_compile_definitions(openmohaa PRIVATE NO_SCRIPTENGINE APP_MODULE TARGET_GAME_TYPE=${TARGET_GAME_TYPE})
# target_compile_features(openmohaa PUBLIC cxx_nullptr)
# target_compile_features(openmohaa PUBLIC c_variadic_macros)
@ -233,14 +243,29 @@ if (WITH_CLIENT)
# # Gamespy dependency
# add_dependencies(openmohaa gcd)
# target_link_libraries(openmohaa PRIVATE gcd)
# target_include_directories(openmohaa PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server" "code/client" "code/uilib" "code/SDL2/include")
# target_include_directories(openmohaa PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server" "code/client" "code/uilib" "code/SDL2/include" "code/jpeg-8c")
# set_target_properties(openmohaa PROPERTIES OUTPUT_NAME "openmohaa${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}${TARGET_CONFIG_SUFFIX}")
#
# if(WIN32)
# if (MSVC)
# target_link_options(openmohaa PRIVATE "/MANIFEST:NO")
#
# target_link_libraries(openmohaa PRIVATE opengl32)
# add_library(sdl2 SHARED IMPORTED)
# set_target_properties(sdl2 PROPERTIES
# IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/code/libs/win32/SDL2.lib"
# )
#
# add_library(sdl2main SHARED IMPORTED)
# set_target_properties(sdl2main PROPERTIES
# IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/code/libs/win32/SDL2main.lib"
# )
#
# add_library(glew32 SHARED IMPORTED)
# set_target_properties(glew32 PROPERTIES
# IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/code/libs/win32/glew32.lib"
# )
#
# target_link_libraries(openmohaa PRIVATE sdl2 sdl2main glew32 opengl32)
# endif()
#
# target_link_libraries(openmohaa PRIVATE wsock32 ws2_32)

View file

@ -2960,6 +2960,8 @@ it by filling it with 2048 bytes of random data.
*/
static void CL_GenerateQKey(void)
{
// FIXME: unimplemented
/*
int len = 0;
unsigned char buff[ QKEY_SIZE ];
fileHandle_t f;
@ -2989,6 +2991,7 @@ static void CL_GenerateQKey(void)
FS_FCloseFile( f );
Com_Printf( "QKEY generated\n" );
}
*/
}
/*

View file

@ -21,7 +21,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../client/client.h"
/*
static cvar_t in_mouse_real;
cvar_t* in_mouse = NULL;
*/
void IN_Init( void *windowData ) {
/*
memset(&in_mouse_real, 0, sizeof(in_mouse_real));
in_mouse_real.integer = 0;
in_mouse = &in_mouse_real;
*/
}
void IN_Restart( void ) {
@ -39,3 +49,9 @@ void Sys_SendKeyEvents (void) {
void Key_KeynameCompletion( void( *callback )( const char *s ) ) {
}
void IN_Activate(qboolean active) {
}
void IN_MouseEvent(int mstate) {
}

View file

@ -47,6 +47,9 @@ void SNDDMA_Submit(void)
{
}
void SNDDMA_Activate(void) {
}
sfxHandle_t S_RegisterSound( const char *sample, qboolean compressed, qboolean force_load )
{
return 0;

View file

@ -957,7 +957,7 @@ sysEvent_t Com_GetRealEvent( void ) {
}
}
} else {
ev = Com_GetSystemEvent();
ev = Sys_GetEvent();
// write the journal value out if needed
if ( com_journal->integer == 1 ) {
@ -1421,6 +1421,7 @@ void Com_Init( char *commandLine ) {
com_dedicated->modified = qfalse;
#ifndef DEDICATED
if( com_dedicated->integer )
{
Sys_CloseMutex();
@ -1431,6 +1432,10 @@ void Com_Init( char *commandLine ) {
CL_Init();
Sys_ShowConsole( com_viewlog->integer, qfalse );
}
#else
Sys_CloseMutex();
NET_Init();
#endif
// set com_frameTime so that if a map is started on the
// command line it will still be able to count on com_frameTime
@ -1652,6 +1657,8 @@ void Com_Frame( void ) {
{
Cbuf_Execute( 0 );
}
#else
Cbuf_Execute(0);
#endif
lastTime = com_frameTime;
@ -2244,24 +2251,4 @@ void Field_AutoComplete( field_t *field )
Field_CompleteCommand( completionField->buffer, qtrue, qtrue );
}
/*
==================
Com_RandomBytes
fills string array with len radom bytes, peferably from the OS randomizer
==================
*/
void Com_RandomBytes( byte *string, int len )
{
int i;
if( Sys_RandomBytes( string, len ) )
return;
Com_Printf( "Com_RandomBytes: using weak randomization\n" );
srand( time( 0 ) );
for( i = 0; i < len; i++ )
string[i] = (unsigned char)( rand() % 255 );
}
}

View file

@ -1157,8 +1157,6 @@ char *Com_SkipTokens( char *s, int numTokens, const char *sep );
char *Com_SkipCharset( char *s, const char *sep );
void Com_BackslashToSlash( char *str );
void Com_RandomBytes( byte *string, int len );
// mode parm for FS_FOpenFile
typedef enum {
FS_READ,

View file

@ -778,6 +778,26 @@ extern cvar_t *fs_basepath;
/*
==============================================================
MISC
==============================================================
*/
// returnbed by Sys_GetProcessorId
#define CPUID_GENERIC 0 // any unrecognized processor
#define CPUID_AXP 0x10
#define CPUID_INTEL_UNSUPPORTED 0x20 // Intel 386/486
#define CPUID_INTEL_PENTIUM 0x21 // Intel Pentium or PPro
#define CPUID_INTEL_MMX 0x22 // Intel Pentium/MMX or P2/MMX
#define CPUID_INTEL_KATMAI 0x23 // Intel Katmai
#define CPUID_AMD_3DNOW 0x30 // AMD K6 3DNOW!
/*
==============================================================
Edit fields and command line history/completion
==============================================================
@ -871,6 +891,7 @@ extern cvar_t *com_speeds;
extern cvar_t *com_timescale;
extern cvar_t *com_sv_running;
extern cvar_t *com_cl_running;
extern cvar_t *com_viewlog; // 0 = hidden, 1 = visible, 2 = minimized
extern cvar_t *com_shortversion;
extern cvar_t *com_version;
extern cvar_t *autopaused;
@ -1133,6 +1154,8 @@ typedef struct {
void *evPtr; // this must be manually freed if not NULL
} sysEvent_t;
sysEvent_t Sys_GetEvent(void);
void Com_QueueEvent( int time, sysEventType_t type, int value, int value2, size_t ptrLength, void *ptr );
int Com_EventLoop( void );
sysEvent_t Com_GetSystemEvent( void );
@ -1189,7 +1212,7 @@ qboolean Sys_StringToAdr( const char *s, netadr_t *a );
qboolean Sys_IsLANAddress (netadr_t adr);
void Sys_ShowIP(void);
qboolean Sys_Mkdir( const char *path );
void Sys_Mkdir( const char *path );
char *Sys_Cwd( void );
void Sys_SetDefaultInstallPath(const char *path);
char *Sys_DefaultInstallPath( void );

View file

@ -746,11 +746,6 @@ void SV_Frame( int msec ) {
if( !com_sv_running->integer )
{
// Running as a server, but no map loaded
#ifdef DEDICATED
// Block until something interesting happens
Sys_Sleep(-1);
#endif
return;
}

2981
code/unix/ChangeLog Normal file

File diff suppressed because it is too large Load diff

47
code/unix/Cons_gcc.pm Normal file
View file

@ -0,0 +1,47 @@
#
# Some utilities to handle gcc compiler setup
#
package Cons_gcc;
# pass the compiler name
# returns an array, first element is 2 for 2.x 3 for 3.x, then full version, then machine info
sub get_gcc_version
{
my @ret;
my ($CC) = @_;
my $version=`$CC --version | head -1`;
chop($version);
my $machine=`$CC -dumpmachine`;
chop($machine);
if($version =~ '2\.[0-9]*\.[0-9]*')
{
push @ret, '2';
} else {
push @ret, '3';
}
push @ret, $version;
push @ret, $machine;
return @ret;
}
# http://ccache.samba.org/
# check ccache existence and path
# returns an array, first element 0 / 1, then path
sub get_ccache
{
my @ret;
$ccache_path=`which ccache`;
chop($ccache_path);
if(-x $ccache_path)
{
push @ret, '1';
push @ret, $ccache_path;
return @ret;
}
push @ret, '0';
return @ret;
}
# close package
1;

265
code/unix/Conscript-client Normal file
View file

@ -0,0 +1,265 @@
# full client build script
Import qw( BASE_CFLAGS BASE_LDFLAGS INSTALL_DIR BUILD_DIR TARGETNAME CC CXX LINK );
# splines
$env_splines = new cons(
CC => $CC,
CXX => $CXX,
LINK => $LINK,
ENV => { PATH => $ENV{PATH}, HOME => $ENV{HOME} }
);
@SPLINES_FILES = qw(
../splines/math_angles.cpp
../splines/math_matrix.cpp
../splines/math_quaternion.cpp
../splines/math_vector.cpp
../splines/q_parse.cpp
../splines/q_shared.cpp
../splines/splines.cpp
../splines/util_str.cpp
);
$SPLINES_FILESREF = \@SPLINES_FILES;
Library $env_splines 'splines', @$SPLINES_FILESREF;
# botlib
# FIXME TTimo
# we already deal with botlib on dedicated target
# the compilation options are a bit different but we could certainly rely on
# the same Conscript and make things cleaner
$env_botlib = new cons(
CC => $CC,
CXX => $CXX,
LINK => $LINK,
ENV => { PATH => $ENV{PATH}, HOME => $ENV{HOME} },
CFLAGS => $BASE_CFLAGS . '-DBOTLIB '
);
@BOTLIB_FILES = qw(
../botlib/be_aas_bspq3.c
../botlib/be_aas_cluster.c
../botlib/be_aas_debug.c
../botlib/be_aas_entity.c
../botlib/be_aas_file.c
../botlib/be_aas_main.c
../botlib/be_aas_move.c
../botlib/be_aas_optimize.c
../botlib/be_aas_reach.c
../botlib/be_aas_route.c
../botlib/be_aas_routealt.c
../botlib/be_aas_sample.c
../botlib/be_ai_char.c
../botlib/be_ai_chat.c
../botlib/be_ai_gen.c
../botlib/be_ai_goal.c
../botlib/be_ai_move.c
../botlib/be_ai_weap.c
../botlib/be_ai_weight.c
../botlib/be_ea.c
../botlib/be_interface.c
../botlib/l_crc.c
../botlib/l_libvar.c
../botlib/l_log.c
../botlib/l_memory.c
../botlib/l_precomp.c
../botlib/l_script.c
../botlib/l_struct.c
);
$BOTLIB_REF = \@BOTLIB_FILES;
Library $env_botlib 'botlib', @$BOTLIB_REF;
# jpeg
# NOTE TTimo we might need this one on other targets
$env_jpeglib = new cons(
CC => $CC,
CXX => $CXX,
LINK => $LINK,
ENV => { PATH => $ENV{PATH}, HOME => $ENV{HOME} },
CFLAGS => $BASE_CFLAGS
);
@JPEGLIB_FILES = qw(
../jpeg-6/jcapimin.c
../jpeg-6/jchuff.c
../jpeg-6/jcinit.c
../jpeg-6/jccoefct.c
../jpeg-6/jccolor.c
../jpeg-6/jfdctflt.c
../jpeg-6/jcdctmgr.c
../jpeg-6/jcphuff.c
../jpeg-6/jcmainct.c
../jpeg-6/jcmarker.c
../jpeg-6/jcmaster.c
../jpeg-6/jcomapi.c
../jpeg-6/jcparam.c
../jpeg-6/jcprepct.c
../jpeg-6/jcsample.c
../jpeg-6/jdapimin.c
../jpeg-6/jdapistd.c
../jpeg-6/jdatasrc.c
../jpeg-6/jdcoefct.c
../jpeg-6/jdcolor.c
../jpeg-6/jddctmgr.c
../jpeg-6/jdhuff.c
../jpeg-6/jdinput.c
../jpeg-6/jdmainct.c
../jpeg-6/jdmarker.c
../jpeg-6/jdmaster.c
../jpeg-6/jdpostct.c
../jpeg-6/jdsample.c
../jpeg-6/jdtrans.c
../jpeg-6/jerror.c
../jpeg-6/jidctflt.c
../jpeg-6/jmemmgr.c
../jpeg-6/jmemnobs.c
../jpeg-6/jutils.c
);
$JPEGLIB_REF = \@JPEGLIB_FILES;
Library $env_jpeglib 'jpeglib', @$JPEGLIB_REF;
# NOTE TTimo this requires patched cons version to work (see unix/cons)
%nasm_hash = new cons()->copy(
CC => 'nasm',
CCCOM => '%CC -f elf -o %> %<'
);
$nasm_hash{SUFMAP}{'.nasm'} = 'build::command::cc';
$nasm_env = new cons(%nasm_hash);
Library $nasm_env 'asmlib', 'ftol.nasm', 'snapvector.nasm';
# compiling files with inlined assembly
$env_inlined = new cons(
CFLAGS => '-DELF -x assembler-with-cpp'
);
Library $env_inlined 'inlinelib', '../unix/matha.s', '../unix/snd_mixa.s';
# putting it all together
$env = new cons(
CC => $CC,
CXX => $CXX,
LINK => $LINK,
ENV => { PATH => $ENV{PATH}, HOME => $ENV{HOME} },
CFLAGS => $BASE_CFLAGS,
LIBS => ' ' . $BUILD_DIR . '/unix/splines.a '
. $BUILD_DIR . '/unix/botlib.a '
. $BUILD_DIR . '/unix/jpeglib.a '
. $BUILD_DIR . '/unix/asmlib.a '
. $BUILD_DIR . '/unix/inlinelib.a '
. $BASE_LDFLAGS
. '-L/usr/X11R6/lib -lX11 -lXext -lXxf86dga -lXxf86vm -ldl -lm'
);
@RENDERER_FILES = qw(
../renderer/tr_animation.c
../renderer/tr_backend.c
../renderer/tr_bsp.c
../renderer/tr_cmds.c
../renderer/tr_curve.c
../renderer/tr_flares.c
../renderer/tr_font.c
../renderer/tr_image.c
../renderer/tr_init.c
../renderer/tr_light.c
../renderer/tr_main.c
../renderer/tr_marks.c
../renderer/tr_mesh.c
../renderer/tr_model.c
../renderer/tr_noise.c
../renderer/tr_scene.c
../renderer/tr_shade.c
../renderer/tr_shade_calc.c
../renderer/tr_shader.c
../renderer/tr_shadows.c
../renderer/tr_sky.c
../renderer/tr_surface.c
../renderer/tr_world.c
);
$RENDERER_REF = \@RENDERER_FILES;
@CLIENT_FILES = qw(
../client/cl_cgame.c
../client/cl_cin.c
../client/cl_console.c
../client/cl_input.c
../client/cl_keys.c
../client/cl_main.c
../client/cl_net_chan.c
../client/cl_parse.c
../client/cl_scrn.c
../client/cl_ui.c
);
$CLIENT_REF = \@CLIENT_FILES;
@COMMON_FILES = qw(
../qcommon/cm_load.c
../qcommon/cm_patch.c
../qcommon/cm_polylib.c
../qcommon/cm_test.c
../qcommon/cm_trace.c
../qcommon/cmd.c
../qcommon/common.c
../qcommon/cvar.c
../qcommon/files.c
../qcommon/md4.c
../qcommon/msg.c
../qcommon/net_chan.c
../qcommon/huffman.c
../qcommon/unzip.c
);
$COMMON_REF = \@COMMON_FILES;
@SOUND_FILES = qw(
../client/snd_adpcm.c
../client/snd_dma.c
../client/snd_mem.c
../client/snd_mix.c
../client/snd_wavelet.c
);
$SOUND_REF = \@SOUND_FILES;
@UNIX_FILES = qw(
../unix/unix_main.c
../unix/unix_net.c
../unix/unix_shared.c
../unix/linux_common.c
../unix/linux_qgl.c
../unix/linux_glimp.c
../unix/linux_joystick.c
../unix/linux_snd.c
../unix/linux_signals.c
);
$UNIX_REF = \@UNIX_FILES;
@SERVER_FILES = qw(
../server/sv_bot.c
../server/sv_ccmds.c
../server/sv_client.c
../server/sv_game.c
../server/sv_init.c
../server/sv_main.c
../server/sv_net_chan.c
../server/sv_snapshot.c
../server/sv_world.c
);
$SERVER_REF = \@SERVER_FILES;
# FIXME TTimo vm_<cpu>.c
@VM_FILES = qw(
../qcommon/vm.c
../qcommon/vm_x86.c
../qcommon/vm_interpreted.c
);
$VM_REF = \@VM_FILES;
# FIXME: import the CPU string to build the name of the target
Program $env $TARGETNAME, '../game/q_shared.c', '../game/q_math.c',
@$RENDERER_REF, @$CLIENT_REF, @$COMMON_REF, @$SOUND_REF,
@$UNIX_REF, @$SERVER_REF, @$VM_REF;
Install $env $INSTALL_DIR, $TARGETNAME;

View file

@ -0,0 +1,115 @@
# dedicated server build script
Import qw( BASE_CFLAGS BUILD_DIR INSTALL_DIR CC CXX LINK );
$DEDICATED_NAME = 'linuxq3ded';
$env_botlib = new cons(
CC => $CC,
CXX => $CXX,
LINK => $LINK,
ENV => { PATH => $ENV{PATH}, HOME => $ENV{HOME} },
CFLAGS => $BASE_CFLAGS . '-DBOTLIB '
);
@BOTLIB_FILES = qw(
../botlib/be_aas_bspq3.c
../botlib/be_aas_cluster.c
../botlib/be_aas_debug.c
../botlib/be_aas_entity.c
../botlib/be_aas_file.c
../botlib/be_aas_main.c
../botlib/be_aas_move.c
../botlib/be_aas_optimize.c
../botlib/be_aas_reach.c
../botlib/be_aas_route.c
../botlib/be_aas_routealt.c
../botlib/be_aas_sample.c
../botlib/be_ai_char.c
../botlib/be_ai_chat.c
../botlib/be_ai_gen.c
../botlib/be_ai_goal.c
../botlib/be_ai_move.c
../botlib/be_ai_weap.c
../botlib/be_ai_weight.c
../botlib/be_ea.c
../botlib/be_interface.c
../botlib/l_crc.c
../botlib/l_libvar.c
../botlib/l_log.c
../botlib/l_memory.c
../botlib/l_precomp.c
../botlib/l_script.c
../botlib/l_struct.c
);
$BOTLIB_REF = \@BOTLIB_FILES;
Library $env_botlib 'botlib', @$BOTLIB_REF;
# NOTE TTimo this requires patched cons version to work (see unix/cons)
%nasm_hash = new cons()->copy(
CC => 'nasm',
CCCOM => '%CC -f elf -o %> %<'
);
$nasm_hash{SUFMAP}{'.nasm'} = 'build::command::cc';
$nasm_env = new cons(%nasm_hash);
Library $nasm_env 'asmlib', 'ftol.nasm', 'snapvector.nasm';
$env = new cons(
CC => $CC,
CXX => $CXX,
LINK => $LINK,
ENV => { PATH => $ENV{PATH}, HOME => $ENV{HOME} },
# FIXME TTimo I'm not sure about what C_ONLY is for
CFLAGS => $BASE_CFLAGS . '-DC_ONLY',
LDFLAGS => '-ldl -lm',
LIBS => ' '
. $BUILD_DIR . '/unix/botlib.a '
. $BUILD_DIR . '/unix/asmlib.a '
);
# list the files for the dedicated server
@FILES = qw(
../null/null_client.c
../null/null_input.c
../null/null_snddma.c
../server/sv_bot.c
../server/sv_ccmds.c
../server/sv_client.c
../server/sv_game.c
../server/sv_init.c
../server/sv_main.c
../server/sv_net_chan.c
../server/sv_snapshot.c
../server/sv_world.c
../qcommon/cm_load.c
../qcommon/cm_patch.c
../qcommon/cm_polylib.c
../qcommon/cm_test.c
../qcommon/cm_trace.c
../qcommon/cmd.c
../qcommon/common.c
../qcommon/cvar.c
../qcommon/files.c
../qcommon/huffman.c
../qcommon/md4.c
../qcommon/msg.c
../qcommon/net_chan.c
../qcommon/unzip.c
../qcommon/vm.c
../qcommon/vm_interpreted.c
../game/q_math.c
../game/q_shared.c
../unix/linux_common.c
../unix/unix_main.c
../unix/unix_net.c
../unix/unix_shared.c
../unix/linux_signals.c
);
$FILESREF = \@FILES;
# DEDICATED_NAME is imported, holds the name of the target
# wolfded.x86 usually
Program $env $DEDICATED_NAME, '../qcommon/vm_x86.c', @$FILESREF;
Install $env $INSTALL_DIR, $DEDICATED_NAME;

135
code/unix/Conscript-pk3 Normal file
View file

@ -0,0 +1,135 @@
# build pk3 on the fly
Import qw( INSTALL_DIR BUILD_DIR CONFIG_DIR CC CXX LINK );
use Data::Dumper;
$env = new cons(); # the env on which we will be working for all pk3s (NOTE: maybe we need several ctually)
$hcf_do_exec = 1;
sub do_command($)
{
printf("@_[0]\n");
if ($hcf_do_exec)
{
system("@_[0]");
}
}
sub build_pk3 {
sub launch {
#print "In launch\n";
$Data::Dumper::Indent = 2;
#print Dumper(@_);
$tmpdir = "/tmp/pk3-builder$$";
do_command("rm -rf $tmpdir");
($target, $sets) = @_;
$base=`basename $target`; chomp($base);
$dirname=`dirname $target`; chomp($dirname);
foreach (@{$sets})
{
($sourcepath, $destpath, $file) = @{$_};
#print "source: $sourcepath dest: $destpath file: $file\n";
do_command("mkdir -p $tmpdir/$destpath");
if ($sourcepath =~ /#.*/)
{
#print "$sourcepath is absolute\n";
$sourcepath =~ s/#//;
if (ref($file))
{
foreach(@{$file})
{
do_command("cp $sourcepath/$_ $tmpdir/$destpath/$_");
}
}
else
{
do_command("cp $sourcepath/$file $tmpdir/$destpath/$file");
}
}
else
{
#print "$sourcepath in linked dir\n";
if (ref($file))
{
foreach(@{$file})
{
do_command("cp $BUILD_DIR/$sourcepath/$_ $tmpdir/$destpath/$_");
}
}
else
{
do_command("cp $BUILD_DIR/$sourcepath/$file $tmpdir/$destpath/$file");
}
}
}
do_command("cd $tmpdir ; zip -r $base *");
do_command("mkdir -p $BUILD_DIR/$dirname");
do_command("cp $tmpdir/$base $BUILD_DIR/$target");
do_command("rm -rf $tmpdir");
return 1;
}
# extract the parameters
($target, $sets) = @_;
$base=`basename $target`; chomp($base);
$dirname=`dirname $target`; chomp($dirname);
# the build command is stored and called later on by cons
# this makes it impossible to have several build_pk3 working together
# there is probably a cleaner solution than this hack, but this works
$target_uniquename="target_$base";
$target_uniquename=~s/\.//g;
eval("\$$target_uniquename=\$target");
$sets_uniquename="sets_$base";
$sets_uniquename=~s/\.//g;
eval("\$$sets_uniquename=\$sets");
#print "name: $target_uniquename after the hack: $target_pak8pk3";
# don't pass @{@_} .. since this will be called during the process
$command = "[perl] &launch( \$$target_uniquename, [ \@{\$$sets_uniquename} ] )";
#print "$command\n";
foreach(@{$sets})
{
($sourcepath, $destpath, $file) = @{$_};
if (ref($file))
{
foreach(@{$file})
{
Depends $env $target, $sourcepath . '/' . $_;
}
}
else
{
Depends $env $target, $sourcepath . '/' . $file;
}
}
Command $env $target, $command;
Install $env $INSTALL_DIR . "/$dirname", $target;
}
# quick rundown on the syntax:
# <target file>, [ <fileset1>, <fileset2>, ... ]
# where <fileset>: [ <source directory>, <directory in zip>, <file1>, <file2>, .. ]
build_pk3('baseq3/pak8.pk3',
[ [ '#../../../media/Q3Media-1.32/baseq3/menu/art', 'menu/art', 'pblogo.tga' ],
[ '../Q3/q3_ui/q3_ui', 'vm', 'ui.qvm' ],
[ '../Q3/cgame/cgame', 'vm', 'cgame.qvm' ],
[ '../Q3/game/game', 'vm', 'qagame.qvm' ] ]
);
build_pk3('missionpack/pak3.pk3',
[ [ '#../ui', 'ui', [ 'createserver.menu', 'joinserver.menu', 'filter.menu', 'punkbuster.menu', 'menus.txt' ] ],
[ '../TA/ui/ui', 'vm', 'ui.qvm' ],
[ '../TA/cgame/cgame', 'vm', 'cgame.qvm' ],
[ '../TA/game/game', 'vm', 'qagame.qvm' ],
[ '#../../../media/Q3Media-1.32/missionpack/scripts', 'scripts', 'models2.shader' ] ]
);

122
code/unix/Conscript-sdk Normal file
View file

@ -0,0 +1,122 @@
# sdk
Import qw( SDK_NAME Q3_VER CC CXX LINK );
# http://www.devdaily.com/perl/edu/articles/pl010005/pl010005.shtml
#----------------------------( promptUser )-----------------------------#
# #
# FUNCTION: promptUser #
# #
# PURPOSE: Prompt the user for some type of input, and return the #
# input back to the calling program. #
# #
# ARGS: $promptString - what you want to prompt the user with #
# $defaultValue - (optional) a default value for the prompt #
# #
#-------------------------------------------------------------------------#
sub promptUser {
#-------------------------------------------------------------------#
# two possible input arguments - $promptString, and $defaultValue #
# make the input arguments local variables. #
#-------------------------------------------------------------------#
local($promptString,$defaultValue) = @_;
#-------------------------------------------------------------------#
# if there is a default value, use the first print statement; if #
# no default is provided, print the second string. #
#-------------------------------------------------------------------#
if ($defaultValue) {
print $promptString, "[", $defaultValue, "]: ";
} else {
print $promptString, ": ";
}
$| = 1; # force a flush after our print
$_ = <STDIN>; # get the input from STDIN (presumably the keyboard)
#------------------------------------------------------------------#
# remove the newline character from the end of the input the user #
# gave us. #
#------------------------------------------------------------------#
chomp;
#-----------------------------------------------------------------#
# if we had a $default value, and the user gave us input, then #
# return the input; if we had a default, and they gave us no #
# no input, return the $defaultValue. #
# #
# if we did not have a default value, then just return whatever #
# the user gave us. if they just hit the <enter> key, #
# the calling routine will have to deal with that. #
#-----------------------------------------------------------------#
if ("$defaultValue") {
return $_ ? $_ : $defaultValue; # return $_ if it has a value
} else {
return $_;
}
}
sub launch {
print("Building MOD SDK (version $Q3_VER)\n");
print("Before building the mod sdk, your CVS tree must be completely clean!\nIf there are some temporary files and binaries in the tree, they can get included in the distribution and cause problems.\n");
$ok = &promptUser("Ready to build mod sdk [y/n]? ");
if ($ok ne 'y')
{
print("aborting\n");
return 0;
}
# create the dirs:
$RAW_DATA = "mod-sdk-$Q3_VER";
system("rm -rf $RAW_DATA ; mkdir -p $RAW_DATA/code");
# actual code
system("cp -R cgame game q3_ui ui $RAW_DATA/code");
# UI stuff
system("cp -R ../ui $RAW_DATA");
# tools
system("cp -R ../lcc ../q3asm $RAW_DATA");
# build scripts
system("cp Construct $RAW_DATA/code");
system("mkdir $RAW_DATA/code/unix ; cp unix/cons unix/pcons-2.3.1 unix/Conscript-pk3 $RAW_DATA/code/unix");
system("cp unix/mod-sdk-data/Makefile $RAW_DATA/code/");
# cleanup some stuff
system("find $RAW_DATA -name CVS -exec rm -rf {} \\; 2>/dev/null");
# test that the build works just fine
$host=`hostname`; chomp($host);
if ($host ne 'antares')
{
system("rm -rf /tmp/$RAW_DATA ; cp -R $RAW_DATA /tmp");
system("cd /tmp/$RAW_DATA/code ; make");
if ($? ne 0)
{
printf("ERROR: test build failed\n");
return 0;
}
printf("build test successful\n");
}
# make a setup out of this
system("cp -R unix/setup/setup.sh unix/setup/setup.data $RAW_DATA");
# TODO: splash!
system("cp unix/mod-sdk-data/setup.xml unix/mod-sdk-data/config.sh unix/mod-sdk-data/postinstall.sh $RAW_DATA/setup.data");
# mod-sdk-data/Q3A_EULA.txt is a copy of stuff that is usually in $Q3SETUPMEDIA .. can't be arsed
system("cp unix/mod-sdk-data/Q3A_EULA.txt $RAW_DATA");
# I love those dirty hacks
system("cd $RAW_DATA/setup.data/bin ; ln -s Linux FreeBSD ; ln -s Linux OpenBSD ; ln -s Linux NetBSD");
# cleanup some stuff
system("find $RAW_DATA -name CVS -exec rm -rf {} \\; 2>/dev/null");
# weeee
system("unix/mod-sdk-data/makeself/makeself.sh $RAW_DATA $SDK_NAME \"Quake III Arena mod SDK\" ./setup.sh $Q3_VER");
return 1;
}
print("in Conscript-sdk\n");
$env = new cons();
Command $env "$SDK_NAME", "[perl] &launch()";

33
code/unix/Conscript-setup Normal file
View file

@ -0,0 +1,33 @@
# setup
Import qw( INSTALL_BASEDIR );
$env = new cons(
# add this path so setup script finds brandelf
ENV => { PATH => $ENV{PATH} . ":" . $ENV{HOME} . "./usr/bin", },
);
sub launch {
# need to get the correct version (i.e. from SP source)
$version = `cat game/q_shared.h | grep Q3_VERSION`;
chomp $version;
$version =~ s/.*Q3\ (.*)\"/$1/;
print("version: $version\n");
system("cd unix ; ./build_setup.sh $version");
return 1;
}
# no dependency to PB, we get it directly from the tree and not in install/
Depends $env "$INSTALL_BASEDIR/foo",
"$INSTALL_BASEDIR/linuxq3ded",
"$INSTALL_BASEDIR/linuxquake3-smp",
"$INSTALL_BASEDIR/linuxquake3";
# during developement phase, we generate and copy the pk3 on the fly
# then those should move to the media tree
# those have been finalized and moved to the media tree
# "$INSTALL_BASEDIR/baseq3/pak8.pk3",
# "$INSTALL_BASEDIR/missionpack/pak3.pk3";
Command $env "$INSTALL_BASEDIR/foo", "[perl] &launch()";

View file

@ -0,0 +1,150 @@
CHANGES 1.32
11/13/2002 - 1.32b
Update to the Linux client, fixing a number of issues:
- Text mode install broken on glibc 2.3 (Debian Sid)
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=165358
Current Debian Sid's glibc package break backwards compatibility
with binaries compiled on older glibc and statically linked.
This will cause the text mode setup to segfault.
For now you can either:
- find a solution to run the graphical gtk-based setup
- roll back to glibc 2.2
- use an updated setup binary:
run the linux setup once, with the --keep option
(this will exand all the files to setup.tmp/)
get this updated setup file:
http://zerowing.idsoftware.com/linux/165358/setup
replace setup.tmp/setup.data/bin/Linux/x86/setup by the new one
cd to setup.tmp/ and run setup.sh
- Current NVidia drivers don't officially support glibc 2.3 systems
This affects Debian Sid in particular, causing crashes during vid_restart
The issue is related to the SMP build depending upon libpthreads
1.32b has both SMP and non-SMP binary. Use quake3-smp to launch
the SMP version if you want to use it.
- SMP and non-SMP builds:
Default quake3 shortcut will spawn a non-SMP build. Use quake3-smp
for an SMP-enabled run. From the feedback we got after the 1.32 release,
the SMP support as designed in the Quake III Arena technology isn't so
much relevant anymore. It was designed for much lower CPU frequencies
and lower AGP throughputs. Modern systems won't benefit from SMP. Since
it didn't make much sense to remove the SMP binary, we have both now.
- Fixing broken mouse on Suse:
Starting with XFree 4.2, the event timestamps returned by the X server
are no longer matching gettimeofday. And there is currently no API in X
to provide easy synchronisation. 1.32 introduced improved event timing
by correcting event time with X server event timestamp (sub-frame timing).
This worked fine with XFree 4.1, and no longer does. 1.32b adds a safe
check to work again with XFree 4.2, but basically the input timing is
back to 1.31 quality.
Some new cvars related to the mouse control:
in_dgamouse - not new, but be sure to have it set to 1 on any recent system
in_subframe - completely disables sub-frame timing. If XFree 4.2
in_subframe 1 won't hurt, but it won't do anything either.
in_nograb - for mod developers. Set to 1 and run windowed, Q3 won't be
grabbing your mouse pointer (useful for debug breaks)
8/26/2002
General:
- new network protocol, 68
- network code:
improved fragmented messages handling
map change while client loads map no longer causes an 'Invalid .PK3' error
map_restart while client loads map no longer causes a reload
fixing donedl being ignored after autodl if map_restart'ed
- the demo command has a list of compatible protocols, it will loop through 66 67 68
you can do '/demo four' and it will try four.dm_66 four.dm_67 four.dm_68
or you can explicitely give a '/demo demoname.dm_??'
- added mousewheel support in the console:
wheel to scroll, ctrl+wheel to scroll faster, shift+wheel to scroll history
- UI in baseq3/ and missionpack/ for PunkBuster configuration
punkbuster server in server creation dialog (sv_punkbuster)
punkbuster client in server browser (cl_punkbuster)
added PB Yes/No to the browsers
- removed obsolete MPlayer UI stuff
- bumped server browser to handle up to 4096 servers
- IP maintained in userinfo
- cl_guid in userinfo (as part of PB integration)
- printing ports as unsigned ints, no longer printing negative port numbers
- cleaned up the legacy IP banning code
use * for IP pattern matching now instead of 0 (fixes some confusion)
ex: 192.246.12.*
made it safe from overflowing and crashing
NOTE: using PunkBuster's banning system is advised instead though
- rcon: some fixes to the buffering to avoid overflowing and dropping parts of the message
- rcon: now supports quoting /rcon g_motd "foo bar"
- added SVF_CLIENTMASK (0x00000002), works only with <= 32 players
set bitmask of players to which send entity
- pushed cl_maxpackets upper limit to 125
- added [skipnotify] from RTCW, use to display in the console only, but not on client screen
(also fixes pb_msgprefix and pb_sv_msgprefix)
- new cvar sv_lanForceRate (defaults 1):
forces LAN clients to the maximum rate instead of accepting client setting
(1 is the default behaviour, backward compatible)
- new cvar sv_strictAuth (defaults 1):
server side variable to control wether strict CDKEY auth should be performed with the auth server
this is required if you want reliable cl_guid for the server (for users tracking)
- filesystem:
client re-orders it's pk3s according to the order given by server
(fixes some 'Invalid .PK3 files referenced' situations
- fixed invisible entities/players bug (thanks goes to Rick Johnson / Raven for this one!)
- update x86 VM code (better and safer optimisations) (Richk Johnson / Raven too)
- clearing client gentity before GAME_INIT call
- failing vote if there's only one voting client (fixes exploit on 2-player server where one player votes then disconnects, forcing vote to pass)
- added trap_FS_Seek
- renderer fix:
if client game code registers a shader after drawsurfaces are generated but before frame is rendered
had a one-frame visual glitch (shader indexes messed up)
- renderer fix:
r_roundImagesDown 0 + map q3dm1 -> crash (buffer overflow fix)
- renderer fix:
fixed a crash in widescreen displays (q3dm11)
- renderer fix:
MAX_SHADERS up to 2^12
- renderer fix:
moved screenshot from frontend to backend, fixes broken r_smp 1 screenshots
- TA fixes:
MOD_KAMIKAZE MOD_JUICED logging properly to games.log
fixed bot taunt spamming
- fixed typo in scripts/models2.shader (shader error Ursula head)
Win32 specific:
- fixed the DirectInput mouse init procedure
- rcon:
fixed rcon not working on NT/2000/XP workstations that have a long uptime
Linux specific:
- no longer trying to load libMesaVoodooGL.so
obsolete code, was confusing when trying to setup correct OpenGL acceleration
- SMP support in the renderer. Detects CPU count, r_smp 1 default if available. (thanks to Gareth Hughes for contributing this)
- changed default GL driver from libGL.so to libGL.so.1
see LSB 1.2 spec: http://www.linuxbase.org/spec/refspecs/LSB_1.2.0/gLSB/libgl.html
- Handle Ctrl and Space key together correctly (Ctrl was disabling Space)
- sub-frame timing of input events (key/mouse) (input timing quality now equivalent to win32)

View file

@ -0,0 +1,52 @@
Quake III Arena
Quake III: Team Arena
Installation instructions
------
What you need:
- retail CD-ROM of Quake III Arena for Windows or linux
- optionally, retail CD-ROM of Quake III: Team Arena
- a computer running linux (kernel >= 2.2 glibc >= 2.1)
- running the client requires X11 and 3D hardware acceleration with OpenGL
Installation:
If you have the retail CD-ROM of Quake III Arena for linux:
- install Quake III Arena from the CD-ROM
- run the Point Release installer
(to buy Quake III Arena for linux online, try http://www.tuxgames.com/)
If you have the retail CD-ROM of Quake III Arena for Windows:
- run the Point Release installer first
- now you need to copy the main pak files from the CD-ROM
or from your win32 partition. Namely, you need to copy baseq3/pak0.pk3
and for Team Arena, missionpack/pak0.pk3
see below for more instructions on how to copy the files:
WARNING: Those instructions are provided as a reference,
depending on your distribution the CD-ROM might not have the same
mount point. Please refer to your linux documentation for additional
information.
- open a root shell and cd to the default installation path:
cd /usr/local/games/quake3
- mount the Quake III Arena CD-ROM and install the game content
cp /mnt/cdrom/Quake3/baseq3/pak0.pk3 /usr/local/games/quake3/baseq3
- optionally, mount the Quake III: Team Arena CD-ROM
cp /mnt/cdrom/Setup/missionpack/pak0.pk3 /usr/local/games/quake3/missionpack
NOTES:
- If you are running Quake III Arena and Quake III: Team Arena on a
Windows partition, you can save some space by symlinking the game
assets to their windows installation:
ln -s /win/quake3/baseq3/pak0.pk3 /usr/local/games/quake3/baseq3/pak0.pk3
ln -s /win/quake3/missionpack/pak0.pk3 /usr/local/games/quake3/missionpack/pak0.pk3
(Windows partition is mounted as /win and Quake III Arena installation is C:\quake3)
Getting Help:
- consult the FAQ in Help/Q3A_FAQ.html
- head over to the Quake3World forums http://www.quake3world.com/forums
- consult the list of known issues and tips at
http://zerowing.idsoftware.com/linux

View file

@ -0,0 +1,283 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
<title>Linux Quake III Arena Known issues</title></head>
<body text="#000000" bgcolor="#ffffff">
<font size="+2"><b>Linux Quake III Arena Known issues</b></font><br>
<i>Known issues and frequently asked questions - 1.32b</i><br>
<br>
<a href="mailto:ttimo@idsoftware.com">TTimo</a><br>
<i>Changes history</i><br>
2004.2.20 Last update<br>
2001.6.18 Initial version
<hr size="1"><br>
<font size="+1">Current topics</font>
<ul>
<li><a href="#install">Installation instructions</a></li>
<li><a href="#setupfiles">What do I do with a .x86.run file?</a></li>
<li><a href="#glibc">The setup crashes with <i>Segmentation fault "$setup" "$@" 2>/dev/null</i></a></li>
<li><a href="#bsd">Installation on BSD</a></li>
<li><a href="#auth">CLIENT_UNKNOWN_TO_AUTH</a></li>
<li><a href="#pk3">Sys_Error: Couldn't load default.cfg / Sys_Error: FS_FreeFile(
NULL )</a></li>
<li><a href="#setupbug29h">I get <i>./setup.sh {: ==: binary operator expected</i>
when running the setup?</a></li>
<li><a href="#hints">The game doesn't start, I have performance problems,
etc.</a></li>
<li><a href="#aureal">Aureal sound drivers</a></li>
<li><a href="#nosound">The sound doesn't work / sound crashes</a></li>
<li><a href="#discuss">Where can I report bugs and discuss about linux
Quake III Arena?</a></li>
<li><a href="#gameso">The *.so files are not in the setups? (<i>cgamei386.so
qagamei386.so uii386.so</i>)</a></li>
<li><a href="#vm_game">I get <i>Sys_Error: Sys_LoadDll(..) failed dlopen()
completely!</i> when running quake3?</a></li>
<li><a href="#3dnow">I have an AMD CPU and a kernel 2.4.*, Quake III Arena
is slowing down to a complete stop after a while?</a></li>
<li><a href="#gamma">How do I set up the gamma correction?</a></li>
<li><a href="#browser">Servers don't show up in the ingame browser</a></li>
<li><a href="#libsafe">Detected an attempt to write across stack boundary</a></li>
<li><a href="#libmesa">libMesaVoodooGL.so</a></li>
<li><a href="#UDPwide">Running a LAN dedicated server with multiple network
interfaces</a></li>
<li><a href="#64bits">Setup and execution on 64 bits CPUs</a></li>
<li><a href="#links">Links</a></li>
</ul>
<hr size="1"><font size="+1"><a name="install"><b>Installation instructions</b></a></font>
<a name="install"><br>
</a>
<p><a name="install">Linux Quake III Arena is using a graphical installer
(based on Loki software's </a><a href="http://www.icculus.org/loki_setup/">Setup Graphic Installer
</a>). However, since it's a Point Release, you need a retail CD-ROM of Quake
III Arena to perform a complete installation (and optionally your Quake III:
Team Arena CD-ROM). This process is documented in the <a href="http://zerowing.idsoftware.com/linux/q3a/INSTALL">INSTALL</a>file
(this file is also in the setups, it's default location is /usr/local/games/quake3/INSTALL
.. you can run the PR setup and read it to finish the installation afterwards).</p>
<font size="+1"><a name="setupfiles"><b>What do I do with a .x86.run file?</b></a></font>
<a name="setupfiles"><br>
</a>
<p>Those are setup files, meant to be executed. They
come with graphical installation UI or console installation, depending on
what's available on your system. You may need to <i>chmod +x file.x86.run</i>
to make them executable.</p>
<font size="+1"><a name="glibc"><b>The setup crashes with <i>Segmentation fault "$setup" "$@" 2>/dev/null</i></b></a></font>
<p>This is happening on glibc 2.3 systems such as RedHat 9 and Suze. The text mode installer will crash. If you can do a graphical installation, make sure you have Gtk1 installed and avoid the text installer altogether.
If you are doing a remote installation (such as a dedicated server through ssh), you need to use a newer text mode installer. Run the installer with <i>--keep</i> to extract the files
(look for a <i>setup*</i> directory in the current directory for the extracted setup).
Then replace <i>setup.data/bin/Linux/x86/setup</i> by <a href="http://zerowing.idsoftware.com/linux/setup-RH9/setup">this newer version</a>. Run <i>setup.sh</i> at top level and things should work fine.</p>
<p>
<b>Update</b>: Turns out this solution is working for RTCW and ET, but not for Q3 (because the last q3 setup uses an older version of the installer). Will update a specific solution for Q3 'soon'.
</p>
<font size="+1"><a name="bsd"><b>Installation on
BSD</b></a></font><a name="bsd"><br>
</a>
<p><a name="bsd">The linux binaries will run fine on the BSD family (FreeBSD,
NetBSD and OpenBSD) with the linux binary compatibility software. However
if you are getting the error message <i>ELF binary type "0" not known</i>
while installing or trying to run the binaries, that means you need to run
<i>brandelf</i> on the files.</a></p>
<p><a name="bsd">If it's a setup problem, proceed with the following steps:
</a></p>
<pre><a name="bsd">./linuxq3apoint-1.31.x86.run --keep<br>brandelf -t Linux setup.tmp/setup.data/bin/FreeBSD/x86/setup<br>cd setup.tmp<br>sh ./setup.sh<br></a></pre>
<p><a name="bsd">The --keep option will extract the files and leave them
somewhere below your current directory. Depending on the game (Q3 or RTCW)
and the setup version, your mileage may vary (setup.tmp or another directory).</a></p>
<p><a name="bsd">The game binaries might need to be brandelf'ed too, with
a command such as</a></p>
<pre><a name="bsd">brandelf -t Linux /usr/local/games/quake3/quake3.x86<br></a></pre>
<a name="bsd"></a><font size="+1"><a name="auth"><b>CLIENT_UNKNOWN_TO_AUTH</b></a></font>
<a name="auth"><br>
</a>
<p><a name="auth">Graeme Devine recently updated his <i>.plan</i> with very
complete </a><a href="http://www.webdog.org/cgi-bin/finger.plm?id=279&amp;time=20011210020942" target="_new">information about CLIENT_UNKNOWN_TO_AUTH errors</a>.</p>
<p>
See some additional information from the <a href="http://www.gameadmins.com/modules.php?name=Mail_List">gameadmins.com mailing list</a>:
</p>
<pre>If the server you are playing on and the auth server don't see you as the
same IP (for instance you are trying to play on a public internet server
that's on your LAN, and your internet access is using NAT), then it won't
work.
It used to work in 1.31, and it doesn't in 1.32. PunkBuster requires
reliable auth of the players. What you can do:
- run a server with sv_strictauth 0 and you'll be able to join your
server. This will be the same behaviour as 1.31
- connect to a server on the internet before you connect to your local
server (this will trigger your IP into the cache of the auth server for
15mn and let you in to your local server).
- setup two NATs, one for your client one for your server and make sure
your server and Id's auth see the same IP. (this one ain't for network
setup newbies)
</pre>
<font size="+1"><a name="pk3"><b>Sys_Error: Couldn't load default.cfg / Sys_Error:
FS_FreeFile( NULL )</b></a></font><br>
<p>If you get one of these errors after installing Quake III Arena or Return
To Castle Wolfenstein, it means that the engine didn't find all the required
.pk3 files. Either you didn't copy them, or you copied them to the wrong
place. Check the INSTALL instructions for the game for more details, make
sure they are in baseq3/ for quake3 (missionpack/ for TA files) and main/
for Return To Castle Wolfenstein.</p>
<font size="+1"><a name="setupbug29h"><b>I get <i>./setup.sh {: ==: binary
operator expected</i> when running the setup?</b></a></font><a name="setupbug29h"><br>
</a>
<p><a name="setupbug29h">This is a known issue to 1.29h setups and prior.
It happens on systems with bash version &lt; 2.*. There are several solutions:<br>
- Upgrade bash to something more recent and run the setup again - Run the
setup with the --keep option. It will fail but it will leave a <i>setup-full</i>
directory. You can then copy the files manually from that dir. - Once you
used the --keep option above, you can edit setup.sh and replace occurences
of == by =. Then run setup.sh and the installer will execute.</a></p>
<a name="setupbug29h"></a><font size="+1"><a name="hints"><b>The game doesn't
start, I have performance problems, etc.</b></a></font><br>
<p>The first thing to do is to check on the forums and various FAQs (this
one, but there are others. See the <a href="#links">links</a>). The Quake3World
forums have a great search function.</p>
<p>Before reporting the problem to <a href="mailto:ttimo@idsoftware.com">me</a>
make sure it's an issue with the game, and not an issue with your OS/OpenGL/sound
configuration. Common OS issues are listed in this FAQ. You should make sure
you have OpenGL configured correctly (by checking if <i>gears</i>is running
for instance, and how well it runs). And see if non-Id linux games are running
fine too.</p>
<p>When you are going to report a bug, first make sure you are using the
latest version of the game. Include the game version in your report.</p>
<p>Include general information about your OS:<br>
</p>
<ul>
<li>Motherboard brand, CPU type, RAM</li>
<li>distribution name and version</li>
<li>kernel / OS info (from <i>uname -a</i>)</li>
<li>libc version (<i>ls -l /lib/libc.so.*</i>)<br>
 please specify if you can if the libc is your distribution's standard
version, or if you compiled yourself, and what binary target was used (x86,
or AMD, i686 etc.)</li>
</ul>
<p>If it's a problem with the client, send the output of <i>glxinfo</i>.</p>
<p>If you have an nvidia board, send the output of <i>cat /proc/nv/card0</i>
</p>
<p>Send output of the run:<br>
run the game with <i>+set developer 1</i> option, and send the output. You
can do something like <i>quake3 +set developer 1 &amp;&gt;q3run.log</i>.</p>
<p>If it's a crash, you can send a backtrace of the game running through
<i>gdb</i>.</p>
<p>You can also send a log of the game running with <i>strace</i>:</p>
<pre>cd /usr/local/games/quake3<br>strace -o ~/strace.log ./quake3.x86<br></pre>
<p>NOTE: please <b>avoid</b> sending me the <i>strace</i> of <i>/usr/local/games/quake3/quake3</i>,
which is a shell script wrapper and probably no interest to your problem.
</p>
<font size="+1"><a name="aureal"><b>Aureal sound drivers</b></a></font><a name="aureal"><br>
</a>
<p><a name="aureal">It seems that some versions of the Aureal sound drivers
don't work right with Q3. Last I heard, a kernel upgrade to 2.4.17 + Aureal
1.1.3, and/or using the old 1.1.1 drivers from </a><a href="http://aureal.sourceforge.net/" target="_new">Aureal's website</a>fixed
the problem.</p>
<p>If you need to know more about this, have a look at this <a href="http://www.quake3world.com/ubb/Forum15/HTML/001348.html" target="_new">Q3W forum thread</a>.</p>
<font size="+1"><a name="nosound"><b>The sound doesn't work / sound crashes</b></a></font><br>
<p>The first thing to check is that it is actually a sound related. Run
the game with <i>+set s_initsound 0</i> and see what happens. All problems
reported so far about sound turned out to be OS/drivers. Listed below:</p>
<p>On some Mandrake distributions:<br>
Check if you are running the enlightenment sound daemon (esd). With <i>ps
aux | grep esd</i>for instance. It is a multiplexer for /dev/dsp, and might
block use of /dev/dsp by Quake III Arena. You can disable esd with <i>esdctl
stop</i> (as root).</p>
<p><b><a href="http://www.linux-mandrake.com/">Mandrake 8</a></b>'s default
sound drivers seem broken, installing the <a href="http://www.alsa-project.org/" target="_new">Alsa drivers</a> or the
<a href="http://www.opensound.com/">http://www.opensound.com</a> drivers
fixes the problem.</p>
<p>Some beta <a href="http://www.alsa-project.org/" target="_new">Alsa drivers</a>
have been reported to crash with Q3. Non-beta ones are fine.</p>
<p>VIA chipset and AC97 driver:<br>
This combination is known to have various issues. They have been fixed in
recent drivers (thanks to Arne Schmitz for the heads up):<br>
</p>
<pre>http://sourceforge.net/projects/gkernel has got the up to date version of <br>the AC97 kernel driver. The current version can be found here:<br><br>http://prdownloads.sourceforge.net/gkernel/via82cxxx-1.1.15.tar.gz<br><br>It has working mmap sound, so Q3 shouldn't be a problem any more.<br></pre>
(thanks to Arne Schmitz for the heads up)<p></p>
<font size="+1"><a name="discuss"><b>Where can I report bugs and discuss about linux Quake III
Arena?</b></a></font><a name="discuss"><br>
</a>
<p><a name="discuss">Reports bugs to </a><a href="mailto:bugs@idsoftware.com">bugs@idsoftware.com</a>. If you are pretty
sure this is a linux-only issue, you can shorten the loop by emailing <a href="mailto:ttimo@idsoftware.com">ttimo@idsoftware.com</a> directly.</p>
<p>You will find the discussion forums for linux Quake III Arena on <a href="http://www.quake3world.com/cgi-bin/forumdisplay.cgi?action=topics&amp;forum=*nix+Discussion&amp;number=15&amp;DaysPrune=30&amp;LastLogin=">
Quake3World forums</a>. There is for sure a lot of other places to talk about
linux Quake III Arena, but this is the one we read regularly to track bugs
and common issues.</p>
<font size="+1"><a name="gameso"><b>The *.so files are not in the setups?
(<i>cgamei386.so qagamei386.so uii386.so</i>)</b></a></font><a name="gameso"><br>
</a>
<p><a name="gameso">If you still have <i>baseq3/*.so</i> and <i>missionpack/*.so</i>
files, then those come from the earlier 1.27g beta installation and you should
REMOVE them. They were provided in 1.27g to go around a bug in the VM code,
which made win32 VMs incompatible with linux. This problem has been fixed
and the two files are no longer required.</a></p>
<p><a name="gameso">If you are upgrading from 1.27g, it is likely that your
<i>q3config.cfg</i> files are set to use the native libraries (*.so files)
instead of the bytecode. Run quake3 with the following options to set things
right:<br>
<i>quake3 +set vm_game 2 +set vm_cgame 2 +set vm_ui 2</i></a></p>
<a name="gameso"></a><font size="+1"><a name="vm_game"><b>I get <i>Sys_Error:
Sys_LoadDll(..) failed dlopen() completely!</i>when running quake3?</b></a></font><a name="vm_game"><br>
</a>
<p><a name="vm_game">Try running quake3 with the following options:<br>
<i>quake3 +set vm_game 2 +set vm_cgame 2 +set vm_ui 2</i><br>
You should also read the </a><a href="#gameso">above answer</a>.</p>
<font size="+1"><a name="3dnow"><b>I have an AMD CPU and a kernel 2.4.*,
Quake III Arena is slowing down to a complete stop after a while?</b></a></font><br>
<p>It seems the 3DNow! copy routines have issues with the southbridge chip
in the KT133A, this results in performances degrading while playing for a
while. Re-compile your kernel without 3DNow! instructions to avoid the problem,
and wait for newer kernels with better support for 3DNow! / KT133A.</p>
<font size="+1"><a name="gamma"><b>How do I set up the gamma correction?</b></a></font><br>
<p>Starting with 1.29h, you can set the gamma correction with the brightness
slider in the graphical menu (under setup). On some older systems which don't
have the appropriate XFree86 extensions, you might have to set <b>r_gamma</b>
manually from the console, and issue a <b>vid_restart</b> command.</p>
<font size="+1"><a name="browser"><b>Servers don't show up in the ingame
browser</b></a></font>
<p>The reason for this has not been clearly identified yet, seems to be related
to upgrade from older versions. Deleting ~/.q3a/baseq3/q3config.cfg fixes
the problem (you will have to reconfigure your bindings)</p>
<font size="+1"><a name="libsafe"><b>Detected an attempt to write across
stack boundary</b></a></font>
<p>If Quake III Arena exits with the error "Detected an attempt to write
across stack boundary", this probably means that you are running libsafe
on this system. Quake III Arena is compiled with some options that confuse
libsafe, you should disable it before running. See <a href="http://www.mudos.org/?faq" target="_new">this page</a> for more details.
</p>
<font size="+1"><a name="libmesa"><b>libMesaVoodooGL.so</b></a></font>
<p>The GL driver for Voodoo cards (libMesaVoodoGL.so) used to be distributed
in older Q3 setups. <b>This is no longer the case.</b> If you have this .so
in your Quake III Arena directory (<i>/usr/local/games/quake3</i>), you should
remove it. Any recent/decent linux distribution should support your Voodoo
card out of the box, otherwise it is recommended that you setup XFree 4.*
and the correct DRI infrastructure for it.</p>
<font size="+1"><a name="UDPwide"><b>Running a LAN dedicated server with
multiple network interfaces</b></a></font>
<p>A LAN dedicated server will use the <i>net_ip</i> cvar to identify the
NIC it is going to use (default is "localhost"). As it only opens one socket,
it is not possible to have a server broadcast it's packets on all the NICs.
This can be a problem if the server is serving games for a LAN and runs several
NICs to access the various sub networks.<br>
</p>
<p>The following Linux kernel patch (2.4.19) was provided by Rogier Mulhujzen
and John Tobin, it will force broadcasts to be emitted on all interfaces:<br>
<a href="http://zerowing.idsoftware.com/linux/q3a/udp_wide_broadcast.patch">udp_wide_broadcast.patch</a><br>
<a href="http://zerowing.idsoftware.com/linux/q3a/udp_wide_README.txt">udp_wide_README.txt</a><br>
The equivalent <a href="http://www.bsdchicks.com/patches/">patch for FreeBSD</a>
is available too.<br>
</p>
<font size="+1"><a name="64bits"><b>Setup and execution on 64 bits CPUs</b></a></font><br>
<p>If you are running Linux on a 64 bit CPU (such as AMD's Opteron), and if your system is backwards compatible so that it can execute 32 bits x86 binaries, then the regular Quake III Arena binaries should work (your mileage may vary).</p>
<p>It's likely that the installer scripts will get confused though, and will refuse to install giving you an error: "This installation doesn't support glibc-2.1 on Linux / unknown". You will have to extract the game files manually by passing --keep on the command line when running the setup script. Once the files are unpacked, you will need to copy them manually to /usr/local/games. You probably want to have a working installation to refer to while doing this. This also applies to RTCW and ET</p>
<font size="+1"><a name="links"><b>Links</b></a></font><br>
<p>The <a href="http://www.icculus.org/lgfaq" target="_new">Linux Gamer's
faq</a> is a very good resource for general Linux Gaming topics.</p>
<p>Also at <a href="http://www.icculus.org/" target="_new">icculus.org</a>,
the <a href="http://www.icculus.org/lgfaq/loki/q3faq.html" target="_new">old
Q3 FAQ from Loki Software</a>.</p>
<p><a href="http://www.quake3world.com/ubb/Forum15/HTML/000529.html">Quake3World's
linux FAQ</a></p>
<br>
</body></html>

View file

@ -0,0 +1,20 @@
UDP Wide Broadcast Patch for Kernel 2.4.19
Main purpose is to allow Quake 3 servers, and all games powered by the
engine, to be visible in the server browser when the servers are being run on
aliased IP addresses and multiple NICs using the +set net_ip option.
To apply the patch run "patch -p1 < udp_wide_broadcast.patch" from your
source directory and recompile.
Add "echo "1" > /proc/sys/net/ipv4/udp_wide_broadcast" to one of your startup
scripts, i.e./etc/rc.d/rc.local, and run thousands of servers from your
computer.
Patch by:
Rogier Mulhujzen <linux@bsdchicks.com>
John Tobin <ogre@sirinet.net>
A patch with the same functionality for FreeBSD is available from
http://www.bsdchicks.com/patches

View file

@ -0,0 +1,57 @@
--- linux/include/linux/sysctl.h.orig 2002-08-17 19:52:27.000000000 -0500
+++ linux/include/linux/sysctl.h 2002-08-17 19:53:00.000000000 -0500
@@ -291,7 +291,8 @@
NET_IPV4_NONLOCAL_BIND=88,
NET_IPV4_ICMP_RATELIMIT=89,
NET_IPV4_ICMP_RATEMASK=90,
- NET_TCP_TW_REUSE=91
+ NET_TCP_TW_REUSE=91,
+ NET_UDP_WIDE_BROADCAST=92
};
enum {
--- linux-modified/net/ipv4/sysctl_net_ipv4.c.orig 2002-08-17 19:48:19.000000000 -0500
+++ linux-modified/net/ipv4/sysctl_net_ipv4.c 2002-08-17 19:52:03.000000000 -0500
@@ -45,6 +45,9 @@
extern int inet_peer_gc_mintime;
extern int inet_peer_gc_maxtime;
+/* From udp.c */
+extern int sysctl_udp_wide_broadcast;
+
#ifdef CONFIG_SYSCTL
static int tcp_retr1_max = 255;
static int ip_local_port_range_min[] = { 1, 1 };
@@ -221,6 +224,8 @@
&sysctl_icmp_ratemask, sizeof(int), 0644, NULL, &proc_dointvec},
{NET_TCP_TW_REUSE, "tcp_tw_reuse",
&sysctl_tcp_tw_reuse, sizeof(int), 0644, NULL, &proc_dointvec},
+ {NET_UDP_WIDE_BROADCAST, "udp_wide_broadcast",
+ &sysctl_udp_wide_broadcast, sizeof(int), 0644, NULL, &proc_dointvec},
{0}
};
--- linux-modified/net/ipv4/udp.c.orig 2002-08-17 19:40:59.000000000 -0500
+++ linux-modified/net/ipv4/udp.c 2002-08-17 23:37:47.000000000 -0500
@@ -94,6 +94,8 @@
#include <net/inet_common.h>
#include <net/checksum.h>
+int sysctl_udp_wide_broadcast = 0;
+
/*
* Snmp MIB for the UDP layer
*/
@@ -272,9 +274,10 @@
if ((s->num != hnum) ||
(s->daddr && s->daddr!=rmt_addr) ||
(s->dport != rmt_port && s->dport != 0) ||
- (s->rcv_saddr && s->rcv_saddr != loc_addr) ||
- (s->bound_dev_if && s->bound_dev_if != dif))
+ !(sysctl_udp_wide_broadcast || !(s->rcv_saddr && s->rcv_saddr != loc_addr)) ||
+ (s->bound_dev_if && s->bound_dev_if != dif)) {
continue;
+ }
break;
}
return s;

2119
code/unix/Makefile Normal file

File diff suppressed because it is too large Load diff

285
code/unix/Makefile.Game Normal file
View file

@ -0,0 +1,285 @@
#
# Quake3 Unix Game Makefile
#
# GNU Make required
#
###
### These paths are where you probably want to change things
###
#The main Quake3 directory
BDIR=..
#This is the game dir
GAMEDIR=baseq3
#Where the source is, assumed to be same directory as this Makefile
SRCDIR=.
#Location of binaries
BINDIR=../bin
LCC=$(BINDIR)/lcc # -lccdir=$(BINDIR)/
Q3ASM=$(BINDIR)/q3asm
#############################################################################
##
## You shouldn't have to touch anything below here
##
#############################################################################
GDIR=$(SRCDIR)/game
CGDIR=$(SRCDIR)/cgame
UIDIR=$(SRCDIR)/ui
LCCFLAGS=-DQ3_VM -S -Wf-target=bytecode -Wf-g -I..\cgame -I..\game -I..\ui
DO_LCC=$(LCC) $(LCCFLAGS) -o $@ -c $<
TARGETS=\
$(BDIR)/$(GAMEDIR)/vm/cgame.qvm \
$(BDIR)/$(GAMEDIR)/vm/qagame.qvm \
$(BDIR)/$(GAMEDIR)/vm/ui.qvm
default: makedir $(TARGETS)
makedir:
@-mkdir $(GDIR)/vm
@-mkdir $(CGDIR)/vm
@-mkdir $(UIDIR)/vm
#############################################################################
# GAME VM
#############################################################################
##NOTE: g_main must be first. Control passes to first function in the vm
GVMASM = \
$(GDIR)/vm/g_main.asm \
$(GDIR)/vm/bg_misc.asm \
$(GDIR)/vm/bg_lib.asm \
$(GDIR)/vm/bg_pmove.asm \
$(GDIR)/vm/bg_slidemove.asm \
$(GDIR)/vm/q_math.asm \
$(GDIR)/vm/q_shared.asm \
$(GDIR)/vm/ai_dmnet.asm \
$(GDIR)/vm/ai_dmq3.asm \
$(GDIR)/vm/ai_team.asm \
$(GDIR)/vm/ai_main.asm \
$(GDIR)/vm/ai_chat.asm \
$(GDIR)/vm/ai_cmd.asm \
$(GDIR)/vm/g_active.asm \
$(GDIR)/vm/g_arenas.asm \
$(GDIR)/vm/g_bot.asm \
$(GDIR)/vm/g_client.asm \
$(GDIR)/vm/g_cmds.asm \
$(GDIR)/vm/g_combat.asm \
$(GDIR)/vm/g_items.asm \
$(GDIR)/vm/g_mem.asm \
$(GDIR)/vm/g_misc.asm \
$(GDIR)/vm/g_missile.asm \
$(GDIR)/vm/g_mover.asm \
$(GDIR)/vm/g_session.asm \
$(GDIR)/vm/g_spawn.asm \
$(GDIR)/vm/g_svcmds.asm \
$(GDIR)/vm/g_target.asm \
$(GDIR)/vm/g_team.asm \
$(GDIR)/vm/g_trigger.asm \
$(GDIR)/vm/g_utils.asm \
$(GDIR)/vm/g_weapon.asm
$(BDIR)/$(GAMEDIR)/vm/qagame.qvm : $(GVMASM)
$(Q3ASM) -o $@ $(GVMASM) $(SRCDIR)/game/g_syscalls.asm
$(GDIR)/vm/ai_chat.asm : $(GDIR)/ai_chat.c; $(DO_LCC)
$(GDIR)/vm/ai_cmd.asm : $(GDIR)/ai_cmd.c; $(DO_LCC)
$(GDIR)/vm/ai_dmnet.asm : $(GDIR)/ai_dmnet.c; $(DO_LCC)
$(GDIR)/vm/ai_dmq3.asm : $(GDIR)/ai_dmq3.c; $(DO_LCC)
$(GDIR)/vm/ai_main.asm : $(GDIR)/ai_main.c; $(DO_LCC)
$(GDIR)/vm/ai_team.asm : $(GDIR)/ai_team.c; $(DO_LCC)
$(GDIR)/vm/bg_lib.asm : $(GDIR)/bg_lib.c; $(DO_LCC)
$(GDIR)/vm/bg_misc.asm : $(GDIR)/bg_misc.c; $(DO_LCC)
$(GDIR)/vm/bg_pmove.asm : $(GDIR)/bg_pmove.c; $(DO_LCC)
$(GDIR)/vm/bg_slidemove.asm : $(GDIR)/bg_slidemove.c; $(DO_LCC)
$(GDIR)/vm/g_active.asm : $(GDIR)/g_active.c; $(DO_LCC)
$(GDIR)/vm/g_arenas.asm : $(GDIR)/g_arenas.c; $(DO_LCC)
$(GDIR)/vm/g_bot.asm : $(GDIR)/g_bot.c; $(DO_LCC)
$(GDIR)/vm/g_client.asm : $(GDIR)/g_client.c; $(DO_LCC)
$(GDIR)/vm/g_cmds.asm : $(GDIR)/g_cmds.c; $(DO_LCC)
$(GDIR)/vm/g_combat.asm : $(GDIR)/g_combat.c; $(DO_LCC)
$(GDIR)/vm/g_items.asm : $(GDIR)/g_items.c; $(DO_LCC)
$(GDIR)/vm/g_main.asm : $(GDIR)/g_main.c; $(DO_LCC)
$(GDIR)/vm/g_mem.asm : $(GDIR)/g_mem.c; $(DO_LCC)
$(GDIR)/vm/g_misc.asm : $(GDIR)/g_misc.c; $(DO_LCC)
$(GDIR)/vm/g_missile.asm : $(GDIR)/g_missile.c; $(DO_LCC)
$(GDIR)/vm/g_mover.asm : $(GDIR)/g_mover.c; $(DO_LCC)
$(GDIR)/vm/g_session.asm : $(GDIR)/g_session.c; $(DO_LCC)
$(GDIR)/vm/g_spawn.asm : $(GDIR)/g_spawn.c; $(DO_LCC)
$(GDIR)/vm/g_svcmds.asm : $(GDIR)/g_svcmds.c; $(DO_LCC)
$(GDIR)/vm/g_target.asm : $(GDIR)/g_target.c; $(DO_LCC)
$(GDIR)/vm/g_team.asm : $(GDIR)/g_team.c; $(DO_LCC)
$(GDIR)/vm/g_trigger.asm : $(GDIR)/g_trigger.c; $(DO_LCC)
$(GDIR)/vm/g_utils.asm : $(GDIR)/g_utils.c; $(DO_LCC)
$(GDIR)/vm/g_weapon.asm : $(GDIR)/g_weapon.c; $(DO_LCC)
$(GDIR)/vm/q_math.asm : $(GDIR)/q_math.c; $(DO_LCC)
$(GDIR)/vm/q_shared.asm : $(GDIR)/q_shared.c; $(DO_LCC)
$(BDIR)/$(GAMEDIR)/vm/cgame.qvm :
echo cgame.qvm disabled
$(BDIR)/$(GAMEDIR)/vm/ui.qvm :
echo ui.qvm disabled
#############################################################################
# CGAME
#############################################################################
CGOBJ = \
$(SRCDIR)/cgame/bg_lib.o \
$(SRCDIR)/cgame/bg_misc.o \
$(SRCDIR)/cgame/bg_pmove.o \
$(SRCDIR)/cgame/bg_slidemove.o \
$(SRCDIR)/cgame/cg_consolecmds.o \
$(SRCDIR)/cgame/cg_draw.o \
$(SRCDIR)/cgame/cg_drawtools.o \
$(SRCDIR)/cgame/cg_effects.o \
$(SRCDIR)/cgame/cg_ents.o \
$(SRCDIR)/cgame/cg_event.o \
$(SRCDIR)/cgame/cg_info.o \
$(SRCDIR)/cgame/cg_localents.o \
$(SRCDIR)/cgame/cg_main.o \
$(SRCDIR)/cgame/cg_marks.o \
$(SRCDIR)/cgame/cg_players.o \
$(SRCDIR)/cgame/cg_playerstate.o \
$(SRCDIR)/cgame/cg_predict.o \
$(SRCDIR)/cgame/cg_scoreboard.o \
$(SRCDIR)/cgame/cg_servercmds.o \
$(SRCDIR)/cgame/cg_snapshot.o \
$(SRCDIR)/cgame/cg_view.o \
$(SRCDIR)/cgame/cg_weapons.o \
$(SRCDIR)/cgame/q_math.o \
$(SRCDIR)/cgame/q_shared.o
$(SRCDIR)/cgame$(ARCH).$(SHLIBEXT) : $(CGOBJ)
$(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(CGOBJ)
$(SRCDIR)/cgame/bg_lib.o : $(GDIR)/bg_lib.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/bg_misc.o : $(GDIR)/bg_misc.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/bg_pmove.o : $(GDIR)/bg_pmove.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/bg_slidemove.o : $(GDIR)/bg_slidemove.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_consolecmds.o : $(CGDIR)/cg_consolecmds.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_draw.o : $(CGDIR)/cg_draw.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_drawtools.o : $(CGDIR)/cg_drawtools.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_effects.o : $(CGDIR)/cg_effects.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_ents.o : $(CGDIR)/cg_ents.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_event.o : $(CGDIR)/cg_event.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_info.o : $(CGDIR)/cg_info.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_localents.o : $(CGDIR)/cg_localents.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_main.o : $(CGDIR)/cg_main.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_marks.o : $(CGDIR)/cg_marks.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_players.o : $(CGDIR)/cg_players.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_playerstate.o : $(CGDIR)/cg_playerstate.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_predict.o : $(CGDIR)/cg_predict.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_scoreboard.o : $(CGDIR)/cg_scoreboard.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_servercmds.o : $(CGDIR)/cg_servercmds.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_snapshot.o : $(CGDIR)/cg_snapshot.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_view.o : $(CGDIR)/cg_view.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/cg_weapons.o : $(CGDIR)/cg_weapons.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/q_math.o : $(GDIR)/q_math.c; $(DO_SHLIB_CC)
$(SRCDIR)/cgame/q_shared.o : $(GDIR)/q_shared.c; $(DO_SHLIB_CC)
#############################################################################
# UI
#############################################################################
UIOBJ = \
$(SRCDIR)/ui/bg_lib.o \
$(SRCDIR)/ui/bg_misc.o \
$(SRCDIR)/ui/ui_addbots.o \
$(SRCDIR)/ui/ui_atoms.o \
$(SRCDIR)/ui/ui_cinematics.o \
$(SRCDIR)/ui/ui_confirm.o \
$(SRCDIR)/ui/ui_connect.o \
$(SRCDIR)/ui/ui_controls2.o \
$(SRCDIR)/ui/ui_credits.o \
$(SRCDIR)/ui/ui_demo2.o \
$(SRCDIR)/ui/ui_display.o \
$(SRCDIR)/ui/ui_gameinfo.o \
$(SRCDIR)/ui/ui_ingame.o \
$(SRCDIR)/ui/ui_loadconfig.o \
$(SRCDIR)/ui/ui_main.o \
$(SRCDIR)/ui/ui_menu.o \
$(SRCDIR)/ui/ui_mfield.o \
$(SRCDIR)/ui/ui_network.o \
$(SRCDIR)/ui/ui_playermodel.o \
$(SRCDIR)/ui/ui_players.o \
$(SRCDIR)/ui/ui_playersettings.o \
$(SRCDIR)/ui/ui_preferences.o \
$(SRCDIR)/ui/ui_qmenu.o \
$(SRCDIR)/ui/ui_saveconfig.o \
$(SRCDIR)/ui/ui_serverinfo.o \
$(SRCDIR)/ui/ui_servers2.o \
$(SRCDIR)/ui/ui_setup.o \
$(SRCDIR)/ui/ui_sound.o \
$(SRCDIR)/ui/ui_sparena.o \
$(SRCDIR)/ui/ui_specifyserver.o \
$(SRCDIR)/ui/ui_splevel.o \
$(SRCDIR)/ui/ui_sppostgame.o \
$(SRCDIR)/ui/ui_spskill.o \
$(SRCDIR)/ui/ui_startserver.o \
$(SRCDIR)/ui/ui_team.o \
$(SRCDIR)/ui/ui_video.o \
\
$(SRCDIR)/ui/q_math.o \
$(SRCDIR)/ui/q_shared.o
$(SRCDIR)/ui$(ARCH).$(SHLIBEXT) : $(UIOBJ)
$(CC) $(CFLAGS) $(SHLIBLDFLAGS) -o $@ $(UIOBJ)
$(SRCDIR)/ui/bg_lib.o : $(GDIR)/bg_lib.c; $(DO_CC)
$(SRCDIR)/ui/bg_misc.o : $(GDIR)/bg_misc.c; $(DO_CC)
$(SRCDIR)/ui/ui_addbots.o : $(UIDIR)/ui_addbots.c; $(DO_CC)
$(SRCDIR)/ui/ui_atoms.o : $(UIDIR)/ui_atoms.c; $(DO_CC)
$(SRCDIR)/ui/ui_cinematics.o : $(UIDIR)/ui_cinematics.c; $(DO_CC)
$(SRCDIR)/ui/ui_confirm.o : $(UIDIR)/ui_confirm.c; $(DO_CC)
$(SRCDIR)/ui/ui_connect.o : $(UIDIR)/ui_connect.c; $(DO_CC)
$(SRCDIR)/ui/ui_controls2.o : $(UIDIR)/ui_controls2.c; $(DO_CC)
$(SRCDIR)/ui/ui_credits.o : $(UIDIR)/ui_credits.c; $(DO_CC)
$(SRCDIR)/ui/ui_demo2.o : $(UIDIR)/ui_demo2.c; $(DO_CC)
$(SRCDIR)/ui/ui_display.o : $(UIDIR)/ui_display.c; $(DO_CC)
$(SRCDIR)/ui/ui_gameinfo.o : $(UIDIR)/ui_gameinfo.c; $(DO_CC)
$(SRCDIR)/ui/ui_ingame.o : $(UIDIR)/ui_ingame.c; $(DO_CC)
$(SRCDIR)/ui/ui_loadconfig.o : $(UIDIR)/ui_loadconfig.c; $(DO_CC)
$(SRCDIR)/ui/ui_main.o : $(UIDIR)/ui_main.c; $(DO_CC)
$(SRCDIR)/ui/ui_menu.o : $(UIDIR)/ui_menu.c; $(DO_CC)
$(SRCDIR)/ui/ui_mfield.o : $(UIDIR)/ui_mfield.c; $(DO_CC)
$(SRCDIR)/ui/ui_network.o : $(UIDIR)/ui_network.c; $(DO_CC)
$(SRCDIR)/ui/ui_playermodel.o : $(UIDIR)/ui_playermodel.c; $(DO_CC)
$(SRCDIR)/ui/ui_players.o : $(UIDIR)/ui_players.c; $(DO_CC)
$(SRCDIR)/ui/ui_playersettings.o : $(UIDIR)/ui_playersettings.c; $(DO_CC)
$(SRCDIR)/ui/ui_preferences.o : $(UIDIR)/ui_preferences.c; $(DO_CC)
$(SRCDIR)/ui/ui_qmenu.o : $(UIDIR)/ui_qmenu.c; $(DO_CC)
$(SRCDIR)/ui/ui_quit.o : $(UIDIR)/ui_quit.c; $(DO_CC)
$(SRCDIR)/ui/ui_saveconfig.o : $(UIDIR)/ui_saveconfig.c; $(DO_CC)
$(SRCDIR)/ui/ui_serverinfo.o : $(UIDIR)/ui_serverinfo.c; $(DO_CC)
$(SRCDIR)/ui/ui_servers2.o : $(UIDIR)/ui_servers2.c; $(DO_CC)
$(SRCDIR)/ui/ui_setup.o : $(UIDIR)/ui_setup.c; $(DO_CC)
$(SRCDIR)/ui/ui_sound.o : $(UIDIR)/ui_sound.c; $(DO_CC)
$(SRCDIR)/ui/ui_sparena.o : $(UIDIR)/ui_sparena.c; $(DO_CC)
$(SRCDIR)/ui/ui_specifyserver.o : $(UIDIR)/ui_specifyserver.c; $(DO_CC)
$(SRCDIR)/ui/ui_splevel.o : $(UIDIR)/ui_splevel.c; $(DO_CC)
$(SRCDIR)/ui/ui_sppostgame.o : $(UIDIR)/ui_sppostgame.c; $(DO_CC)
$(SRCDIR)/ui/ui_spskill.o : $(UIDIR)/ui_spskill.c; $(DO_CC)
$(SRCDIR)/ui/ui_startserver.o : $(UIDIR)/ui_startserver.c; $(DO_CC)
$(SRCDIR)/ui/ui_team.o : $(UIDIR)/ui_team.c; $(DO_CC)
$(SRCDIR)/ui/ui_video.o : $(UIDIR)/ui_video.c; $(DO_CC)
$(SRCDIR)/ui/q_math.o : $(GDIR)/q_math.c; $(DO_SHLIB_CC)
$(SRCDIR)/ui/q_shared.o : $(GDIR)/q_shared.c; $(DO_SHLIB_CC)
#############################################################################
# MISC
#############################################################################
clean:
rm -f $(GVMASM)

12
code/unix/Quake3.kdelnk Normal file
View file

@ -0,0 +1,12 @@
# KDE Config File
[KDE Desktop Entry]
Name=Quake3
Name[C]=Quake3
MimeType=
Exec=/usr/local/games/quake3/linuxquake3
Comment=Quake3: Arena by id Software
Icon=quake3.xpm
TerminalOptions=
Path=
Type=Application
Terminal=0

184
code/unix/README.EULA Normal file
View file

@ -0,0 +1,184 @@
LIMITED COMPATIBILITY TESTING AND RECREATIONAL
USE SOFTWARE TEST LICENSE AGREEMENT
This Limited Compatibility Testing and Recreational Use Software Test
License Agreement (the "Agreement") is a legal agreement between you, the
end-user, and Id Software, Inc. ("ID"). BY CONTINUING THE INSTALLATION
OF THIS TEST VERSION OF THE GAME PROGRAM ENTITLED QUAKE III: ARENA (THE
"SOFTWARE"), BY LOADING OR RUNNING THE SOFTWARE, OR BY PLACING OR COPYING
THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE, COMPUTER RAM OR OTHER STORAGE,
YOU ARE AGREEING TO BE BOUND BY THE TERMS OF THIS AGREEMENT.
1. Grant of License. Subject to the terms and provisions of this
Agreement, ID grants to you the non-exclusive limited right to use this
Software only in executable or object code form and only for the purpose
of testing the compatibility of your computer system with the Software
and for non-commercial, recreational purposes. The term "Software"
includes all elements of the Software such as data files and screen
displays. You are not receiving any ownership or proprietary right,
title or interest in or to the Software or the copyright, trademarks, or
other rights related thereto. For purposes of this section, "use" means
loading the Software into RAM and/or onto computer hard drive, as well
as installation of the Software on a hard disk or other storage device.
You agree that the Software will not be shipped, transferred or exported
into any country in violation of the U.S. Export Administration Act (or
any other law governing such matters) by you or anyone at your direction
and that you will not utilize and will not authorize anyone to utilize,
in any other manner, the Software in violation of any applicable law.
The Software may not be downloaded or otherwise exported or reexported
into (or to a national or resident of) any country to which the U.S. has
embargoed goods or to anyone or into any country who/which are prohibited,
by applicable law, from receiving such property.
2. Prohibitions. You, either directly or indirectly, shall not do
any of the following acts:
a. rent the Software;
b. sell the Software;
c. lease or lend the Software;
d. offer the Software on a "pay-per-play" basis;
e. distribute the Software (except by electronic means, as permitted
by section 3. hereinbelow) by any means, including, but not limited to
direct mail, retail, mail order or other means;
f. in any other manner and through any medium whatsoever commercially
exploit the Software or use the Software for any commercial purpose;
g. disassemble, reverse engineer, disassemble, decompile, modify
or alter the Software;
h. translate the Software;
i. reproduce or copy the Software (except as permitted by section
3. hereinbelow);
j. publicly display the Software;
k. prepare or develop derivative works based upon the Software;
l. remove or alter any legal notices, such as trademark and copyright
notices, affixed on or within the Software; or
m. create or develop extra or add-on levels for the Software.
3. Permitted Electronic Distribution and Copying. So long as this
Agreement accompanies the Software at all times, ID grants to you the
limited right to distribute, free of charge, and by electronic means
only, the Software. Anyone who receives the Software shall be limited to
all the terms and conditions of this Agreement. You may make only the
following copies of the Software: (i) you may download the Software
from the Internet and onto your computer hard drive; (ii) you may copy
the Software from your computer hard drive into your computer RAM; and
(iii) you may make one (1) "back up" or archival copy of the Software
on one (1) hard disk.
4. Copyright. The Software and all copyrights, trademarks and all
other conceivable intellectual property rights related to the Software
are owned by ID and are protected by United States copyright laws,
international treaty provisions and all applicable law, such as the
Lanham Act. You must treat the Software like any other copyrighted
material, as required by 17 U.S.C., ¤101 et seq. and other applicable law.
You agree to use your best efforts to see that any user of the Software
licensed hereunder complies with this Agreement. You agree that you
are receiving a copy of the Software by license only and not by sale and
that the "first sale" doctrine of 17 U.S.C. ¤109 does not apply to your
receipt or use of the Software.
5. NO WARRANTIES. ID DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE WITH RESPECT TO
THE SOFTWARE. ID DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE
WILL BE UNINTERRUPTED OR ERROR FREE OR THAT THE SOFTWARE WILL MEET YOUR
SPECIFIC REQUIREMENTS. ADDITIONAL STATEMENTS SUCH AS PRESENTATIONS,
WHETHER ORAL OR WRITTEN, DO NOT CONSTITUTE WARRANTIES BY ID AND SHOULD
NOT BE RELIED UPON.
6. Governing Law, Venue and Liability Limitation. This Agreement
shall be construed in accordance with and governed by the applicable laws
of the State of Texas and applicable United States federal law. Copyright
and other proprietary matters will be governed by United States laws and
international treaties. Exclusive venue for all litigation regarding
this Agreement shall be in Dallas County, Texas and you agree to submit to
the jurisdiction of the courts in Dallas, Texas for any such litigation.
IN ANY CASE, NEITHER ID NOR ID'S OFFICERS, EMPLOYEES, DIRECTORS, AGENTS,
LICENSEES, SUBLICENSEES, SUCCESSORS OR ASSIGNS SHALL BE LIABLE FOR LOSS OF
DATA, LOSS OF PROFITS, LOST SAVINGS, SPECIAL, INCIDENTAL, CONSEQUENTIAL,
INDIRECT, PUNITIVE OR OTHER SIMILAR DAMAGES ARISING FROM BREACH OF
WARRANTY, BREACH OF CONTRACT, NEGLIGENCE, STRICT PRODUCT LIABILITY,
OR OTHER LEGAL THEORY EVEN IF ID OR ITS AGENT HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES OR EVEN IF SUCH DAMAGES ARE FORESEEABLE,
OR LIABLE FOR ANY CLAIM BY ANY OTHER PARTY. Some jurisdictions do not
allow the exclusion or limitation of incidental or consequential damages,
so the above limitation or exclusion may not apply to you.
7. U.S. Government Restricted Rights. To the extent applicable,
the United States Government shall only have those rights to use the
Software as expressly stated and expressly limited and restricted in
this Agreement, as provided in 48 C.F.R. ¤¤ 227.7202-1 through 227.7204,
inclusive.
8. General Provisions. A copy of all notices or other correspondence
which you send to ID shall also be sent by you to ID's counsel:
D. Wade Cloud, Jr.
HIERSCHE, MARTENS, HAYWARD, DRAKELEY & URBACH, P.C.
15303 Dallas Parkway, Suite 700
Dallas, TX 75248
(972) 701-7000
Facsimile: (972) 701-8765
Neither this Agreement nor any part or portion hereof shall be assigned
or sublicensed by you. ID may assign its rights under this Agreement
in ID's sole discretion. Should any provision of this Agreement
be held to be void, invalid, unenforceable or illegal by a court,
the validity and enforceability of the other provisions shall not be
affected thereby. If any provision is determined to be unenforceable,
you agree to a modification of such provision to provide for enforcement
of the provision's intent, to the extent permitted by applicable law.
Failure of ID to enforce any provision of this Agreement shall not
constitute or be construed as a waiver of such provision or of the right
to enforce such provision. If you fail to comply with any term of this
Agreement, YOUR LICENSE IS AUTOMATICALLY TERMINATED, WITHOUT NOTICE AND
ID MAY PURSUE ALL RELIEF AND REMEDIES AGAINST YOU WHICH ARE AVAILABLE
UNDER APPLICABLE LAW AND/OR THIS AGREEMENT. You agree that in the event
of litigation relating to this Agreement, the prevailing litigant shall
be entitled to recover the prevailing litigant's attorneys' fees and
expenses and costs of court in addition to all other relief available
under this Agreement and/or applicable law. In the event this Agreement
is terminated, you shall have no right to use the Software, in any manner
and you shall immediately destroy all copies of the Software in your
possession, custody or control. You agree that your unauthorized use
of any ID property, whether in whole or in part, would immediately and
irreparably damage ID such that ID could not be adequately compensated
by an award of monetary damages, and in the event of such threatened
or actual unauthorized use ID shall be entitled to an injunctive order
appropriately restraining and/or prohibiting such unauthorized use
without the necessity of ID posting bond or other security.
YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, YOU UNDERSTAND THIS
AGREEMENT, AND UNDERSTAND THAT BY CONTINUING THE INSTALLATION OF THE
SOFTWARE, BY LOADING OR RUNNING THE SOFTWARE, OR BY PLACING OR COPYING
THE SOFTWARE ONTO YOUR COMPUTER HARD DRIVE OR RAM, YOU AGREE TO BE BOUND
BY THE TERMS AND CONDITIONS OF THIS AGREEMENT. YOU FURTHER AGREE THAT,
EXCEPT FOR WRITTEN SEPARATE AGREEMENTS BETWEEN ID AND YOU, THIS AGREEMENT
IS A COMPLETE AND EXCLUSIVE STATEMENT OF THE RIGHTS AND LIABILITIES OF
THE PARTIES HERETO. THIS AGREEMENT SUPERSEDES ALL PRIOR ORAL AGREEMENTS,
PROPOSALS OR UNDERSTANDINGS, AND ANY OTHER COMMUNICATIONS BETWEEN ID
AND YOU RELATING TO THE SUBJECT MATTER OF THIS AGREEMENT.
April 23, 1999 5:11 p.m.
LIMITED COMPATIBILITY TESTING AND RECREATIONAL USE SOFTWARE
TEST LICENSE AGREEMENT Page 4
3406.0586\C:\DWC\DOC\2082.DOC

352
code/unix/README.Linux Normal file
View file

@ -0,0 +1,352 @@
+----------------------------------------+
| Q3Test |
| The Official Quake 3: Arena TEST |
| Linux version |
| Revision 1.08 |
| Released Aug 3, 1999 |
| Copyright (C) 1999 id Software, inc. |
+----------------------------------------+
| Documentation: Paul Jaquays |
| Dave Kirsch |
+----------------------------------------+
Outline:
1. Introduction
2. Bug Reporting
3. Installing Q3Test
4. Running Q3Test. Operating Instructions
5. Known Issues
==================
== Section 1. ==
== INTRODUCTION ==
==================
This is the Linux version of the test.
Before proceeding onward, please read the README.EULA file. This is
the End User License Agreement. It's the agreement between you and id
regarding this test. Read it. Understand that the acts of loading or
running the software, or placing it on your computer hard drive, RAM,
or other storage, you are agreeing to be bound by the terms of the End
User License Agreement. So it's best to know what you are agreeing to.
The operating instructions for the test are included in the
separate "README.Q3Test" file. For the most part, the game functions
are the same across all platforms. Differences will be noted when necessary.
+----------------+
| THIS IS A TEST |
+----------------+
We want to set the record straight from the outset. This is neither a
demo nor an ALPHA version of the final game and should not be expected
to behave as such. Q3Test is a test of Quake3: Arena's network technology
and graphics compatibility. While many of the game features that you will
see in this test are in a highly polished state, do not confuse this with
being anything other than what it is intended to be: a test. By running
this test openly on the Internet and on a multitude of local networks,
we hope to expose problems that could not otherwise be discovered on the
limited number of in-house systems and computer. That's why we need your
assistance for this test.
Furthermore, it is anticipated that there may be revisions and additions
made to the test that will make it incompatible with earlier versions.
+---------------------+
| SYSTEM REQUIREMENTS |
+---------------------+
There is no software-only version of the game. If your computer is not
hardware accelerated with a game compatible graphics card, you will NOT be
able to run Q3Test. Currently, 3DFX based cards are the only
tested compatible cards. If your computer does not meet the
minimum requirements, you are unlikely to be able to run a satisfactory
game experience.
A glibc compatible Linux installation is required. An easy to determine
if you have glibc support is to type this:
ls -l /lib/libc*
If you get a report of libc6 (you may also have libc5), you have a
glibc based system.
The Linux version requires a supported hardware 3D acceleration card. The
following are currently supported:
o 3Dfx Voodoo Graphics based cards
o 3Dfx Voodoo2 based cards
Other cards of similar make and model may work, but are not supported.
Other X11 OpenGL libraries may work with a supported hardware
accelerator, but have not been extensively tested. Performance on
untested OpenGL configurations may not produce acceptable game
speed.
For 3Dfx based products, Linux Q3Test is distributed with a version of Mesa
3-D specifically compiled for Voodoo support. You must have 3Dfx Linux Glide
drivers installed however. These drivers are available from:
http://glide.xxedgexx.com/3DfxRPMS.html
Make sure that you download and install the glibc versions of the drivers
(found at the bottom of the page).
Mirrors for this site are can be found at:
http://glide.mirrors.sonic.net
http://glide.samiam.org
Please follow the installation instructions presented there for adding the
correct drivers for your 3D-acceleration card. Note that there are two ways
to install the 3DFX drivers-one with support for a /dev/3dfx device that
does not require root permissions in order to use the card. If you choose to
not use the /dev/3dfx method, you will have to run Q3Test as the root user.
NOTE: Linux Q3Test will try to load "libGL.so" before using 3Dfx drivers.
This can cause problems if you have a software or third party OpenGL driver
installed. You can specifically target the included 3Dfx based Mesa driver
by using the following command line:
./linuxquake3 +set r_glDriver libMesaVoodooGL.so.3.1
For 3DFX users, you may disable the vertical sync refresh. This can improve
proformance at the cost of some visual tearing of the image. Entering the
following command into your shell before running Q3Test will turn off
the vertical sync:
export FX_GLIDE_SWAPINTERVAL=0
Then run Linux Q3Test from the same command line normally.
+-----------+
| X11 Setup |
+-----------+
Linux Q3Test requires X11 to run. There is no console-based version as in
previous id products such as GLQuake and Quake2. XFree86 version 3.2 or
later is required.
There are two ways that mouse input is handled under XFree86:
o By default, Q3Test will attempt to use DGA mouse handling. DGA
support features direct reading of the mouse motion and provides
more accurate control while playing the game. By default this
support is enabled, but can be disabled by adding "+set
in_dgamouse 0" to the command line at startup.
o The non-DGA method of mouse input uses pointer grabbing and warps
the pointer to the middle of the window on each mouse update. On
systems with a slow frame rate and a lot of mouse user input, the
motion can get "clipped" to the window boundaries. This method of
input is more compatible however.
Q3Test uses the XFree86 VidModeExtension facilities if available to provide
fullscreen play. This does not apply to 3Dfx passthrough based cards, since
the passthrough cable takes over the video display upon activation anyway.
When configuring your X11 server, make sure that you include lower
resolution modes such as 640x480 and 800x600. Q3Test will auto-switch to
these modes using the VidModeExtension if you select fullscreen from the
graphics options menu. If the lower resolution modes are not listed in the
XFree86 configuration file, Q3Test will be unable to switch to the desired
resolution for fullscreen play.
+-------------------------+
| Sound Support and Setup |
+-------------------------+
Q3Test uses the /dev/dsp sound device for sound support under Linux. This is
the default device provided by the sound drivers included with the Linux
kernel. Please note that at the time of this writing, PCI based sound cards
such as the SoundBlaster Live and Diamond Monster MX series were not
supported. They may be supported in the future. Check
http://www.opensound.com/ for support in the future.
If you do not run Q3Test as root (recommended), you may need to make sure
the permissions for the /dev/dsp device are read and write by the user
running Q3Test. The cheap and easy way to make this happen is to do "chmod
o+rw /dev/dsp" as root. For the more security conscious, a special sound
group could be created and Q3Test could be made setgid to the sound group to
access the device.
Q3Test uses mmap() to map the sound buffers on /dev/dsp directly in order to
provide responsive sound needs. Sound cards must be able to support this
feature in order to work. SoundBlaster 16, AWE32 and AWE64 cards are known
to work.
+----------------------+
| WHAT'S IN THIS TEST? |
+----------------------+
We have included three maps with this test version of Quake3: Arena. They
are q3test1, q3test2, and q3tourney.
q3test1 for 4-8 players on Internet or LAN play Best with 6 players
q3test2 for 3-8 players Primarily for LAN play Best with 3 players
q3tourney is the tournament map
===================
== Section 2. ==
== BUG REPORTING ==
===================
What we would like from our testers are emails with descriptions of
problems that are encountered, particularly those involving video or
network bugs. Do NOT send reports to individual id employees. All bug
reports should go to the following e-mail address:
q3feedback@idsoftware.com
In your subject line, please describe the system the game is being played
on (Mac, Linux, Win32) and the type of problem you are reporting: video,
network, sound or game. Example Subject Line: "Mac/video problem" or
"Linux/network connection problem."
In the body of your letter (no attached files please), briefly list and
describe the problems. Detailed descriptions of problems are good, but
remember that brevity is best. Please do NOT send screen shots unless
they are the ONLY way to show a problem.
While we realize that you may have comments and suggestions regarding
specific game play features, please refrain from submitting such along
with bug reports. Comments on game play can be made on the official
Quake 3: Arena message board at:
http://www.quake3arena.com
========================
== Section 3. ==
== INSTALLING Q3TEST ==
========================
After you have installed the needed hardware drivers for your 3D
acceleration and sound hardware, you need to install the Q3Test package.
Q3Test is available as a Red Hat RPM file or as a tar file. To install the
RPM file, enter the following when logged in as the root user:
rpm -Uvh q3test-1.00-glibc-1.i386.rpm
The rpm installs the game and data files in /usr/local/games/q3test.
[ Note: If you have not installed (or do not wish to install) the Linux
glide drivers, you may get an error message about not having libglide2x.so
installed. This can be ignored and installation can be forced by adding
the --nodeps option to the rpm command line as follows:
rpm --nodeps -Uvh q3test-1.00-glibc-1.i386.rpm ]
If you are going to install the tar version, make a directory for
installation, untar the file as follows:
tar xzvf q3test-1.00-glibc-i386.tar.gz
This will untar the files into a q3test subdirectory under the current
directory.
====================
== Section 4. ==
== RUNNING Q3TEST ==
====================
It is recommended that you do not run Q3Test using the root account or with
root privileges. There are two exceptions to this:
o If you are using a 3Dfx based accelerator card and do not install
the /dev/3dfx configuration option. (You will have to run as root
in order to access the card).
o If you do not have access to the /dev/dsp device and do not wish
to change the mode of the device so that non-root accounts can
access it.
You will have to be running under X11 or have the DISPLAY variable pointed
to a OpenGL glX capable X Server.
By default, Q3Test tries to find the following OpenGL libraries in this
order:
o libGL.so.1
o libMesaVoodooGL.so.3.1
You can override the library name by entering, "+set r_glDriver <libname>"
on the command line. This may be needed if you are using a non-standard set
up and have a different name for the OpenGL shared library.
If everything proceeds successfully, you should have a Q3Test window on your
desktop with a menu displayed (3DFX owners will get a full screen view). If
you want to use full screen, go to the System Configuration, Graphics
Options, Fullscreen, change the value to Yes, and hit enter to apply it.
If you intend to connect to the Internet to play Q3Test, make certain
that your net connection is open and working first.
======================
== Section 5. ==
== KNOWN ISSUES ==
======================
Q. My mouse is erratic. My player is constantly looking up or down and
I can't seem to move him.
A. This happens with two issues. Some versions of XFree86 have a bug in
DGA mouse handling that confuses Q3Test. You can try turning off DGA mouse
support by entering "+set in_dgamouse 0" on the command line when you
start Q3Test. This problem can also occur after a restart of the video
system (such as after a graphic setting change). This is because some
sort of event occurred to jam up the mouse. Restarting the video system
another time and not moving the mouse during the restart should clear it.
Q. When I do a video restart (for example, selecting Apply in the Graphics
Options menu), Q3Test exits with a Sig11.
A. This is a driver related problem.
On 3DFX hardware that is using the /dev/3dfx device and you are NOT running
as root, it seems that the restart doesn't clear some sort of permission.
Running Q3Test as root will fix this problem.
Q. Performance is so slow I can't play! The frame rate looks like one
frame per second!
A. Most of the current drivers for Linux do not support hardware
acceleration at any bit depth other than 15 or 16 bit color. Make sure
that you specify 16 bit color when you run your X11 Server, such as:
startx -- -bpp 16
Q. I have a Voodoo3. When I start the game, I send up at a low resolution
version of my desktop.
A. The current Voodoo3 X11 Servers have problems with DGA Mouse support.
This is a known driver issue and will be fixed in newer revisions of the
Voodoo3 X11 Server. Run the game with the following to disable it:
./linuxquake3 +set in_dgamouse 0
Q. I'm running Gnome with Englightenment and sound doesn't work.
A. If you are using the Enlightenment Sound Daemon (esd), it will not release
the sound hardware for Quake3 Test's usage. You can disable it before running
the test as follows:
esdctl off # turn it off
start q3test the normal way
esdctl on # turn it back on
Q. I try to run Q3Test, but sound doesn't work. The console says "Can't
open /dev/dsp. /dev/dsp: Can't allocate memory."
A. This can happen if the vmware kernel modules are loaded. You can unload
them by typing when logged as root:
/etc/rc.d/init.d/vmware stop
Assuming you are using a RedHat system.
Q. I was playing Q3Test and suddenly it quit and reported a signal error.
A. This is probably a bug. Please report it.

306
code/unix/README.Q3Test Normal file
View file

@ -0,0 +1,306 @@
+----------------------------------------+
| Q3Test |
| The Official Quake 3: Arena TEST |
| Operating Instructions Readme |
| Revision 2.1 |
| Released Friday July 16th, 1999 |
| Copyright (C) 1999 id Software, inc. |
+----------------------------------------+
| Documentation: Paul Jaquays |
+----------------------------------------+
This game is not yet rated by the ESRB. It contains animated
violence and blood. A rating for mature audiences 17+ is
anticipated.
1. Introduction
2. Operating Instructions
3. Status Readouts
4. Player Actions
5. The Arena Environment
6. The Game Console
7. Problem Icons
==================
== Section 1. ==
== INTRODUCTION ==
==================
These instructions for game play should work with the versions of the game that are targeted at different platforms.
Before proceeding onward, click on the EULA_Readme file icon. This is the End User License Agreement. It's the agreement between you and id regarding this test. Read it. Understand that the acts of loading or running the software, or placing it on your computer hard drive, RAM, or other storage, you are agreeing to be bound by the terms of the End User License Agreement. So it's best to know what you are agreeing to.
If you agree to the conditions of the End User License Agreement, install the game on your computer's hard drive.
If you are using the Win32 version, open the readme file included for GLSetup. This application will load the most recent versions of the GL drivers needed to play Quake3: Arena.
The platform-specific instructions for the test are included in a separate Readme file. Refer to the appropriate Readme for your hardware.
+----------------+
| THIS IS A TEST |
+----------------+
We want to set the record straight from the outset. This is neither a demo nor an ALPHA version of the final game and should not be expected to behave as such. Q3Test is a test of Quake3: Arena's network technology and graphics compatibility. While many of the game features that you will see in this test are in a highly polished state, do not confuse this with being anything other than what it is intended to be: a test. By running this test openly on the Internet and on a multitude of local networks, we hope to expose problems that could not otherwise be discovered on the limited number of in-house systems and computers we have available. That's why we need your assistance for this test.
Furthermore, it is anticipated that there may be ongoing revisions and additions made to the test that will make it incompatible with earlier versions.
============================
== Section 2. ==
== OPERATING INSTRUCTIONS ==
============================
When you start Q3Test, the game does not automatically load a map. Instead it displays the Main Menu screen. At this point (or at any time during the game) you may adjust and customize the video and audio settings on your computer, change details regarding your game character, and if desired, change the default controls to ones more to your liking.
At any time during the game, press the Escape key to bring up the Main menu and superimpose it over the game screen. Use the up and down arrow keys to navigate the menu, and press the Enter key to select a function. Press Escape to return to the main level menu (and set any selected choices). Each Main menu function brings up a list of secondary menu items. If you have problems using the secondary menu selections, please refer to the message banner at the bottom of the screen for technical details.
If a menu selection appears in gray, you cannot select or modify it. Choosing some options in the CONTROL CUSTOMIZATION and GRAPHICS OPTIONS menus will disallow other options. This is because they are either unnecessary (as is the case with MOUSE LOOK if you select the FREE LOOK option), or are not supported (as is the case with COLOR DEPTH if you chose the VOODOO OPENGL).
+-----------+
| MAIN MENU |
+-----------+
The first three Main Menu options, SEARCH FOR LAN GAME, CONNECT TO NETWORK GAME and START NETWORK GAME are only available if the player is not currently connected to an ongoing game.
SEARCH FOR LAN GAME:
If your computer is on a Local Area Network (LAN), this will show any currently active Q3Test servers on the network, along with the number of players currently in the game and the maximum number of players that can be in that game.
Example: idserver q3test1 1/8
This indicates that the server on the LAN called "idserver" is currently playing the map "q3test1" and has one player in it out of the possible 8 that can be in the game at one time.
Use the up/down arrow keys to select a server and hit ENTER to command your computer to connect to that game.
CONNECT TO NETWORK GAME:
SERVER: If your computer is connected to the Internet, you can enter the IP address of a server and hit ENTER to attempt to make a connection to that server. For server id's Q3Test server listings, go to http://www.quake3arena.com or check with your favorite 3D gaming web sites for other servers.
RATE: Set the type of network connection you are using. Choices are: "<=28.8K", "33.6K", "56K", "ISDN", and "LAN/cable/xDSL".
START NETWORK GAME:
To start a network game, whether on a LAN or over the Internet, select this option. The secondary menu screen has the following options:
START: Launches the game using the parameters currently set on this menu.
MAP: This gives access to the list of maps located in the Quake3/Baseq3/Maps directory/folder. For the purposes of this test, there are only two maps. Use the left and right arrow keys to toggle between the two maps.
DEDICATED: This is either "no", "dedicated LAN," or "dedicated Internet."
A dedicated server (set to YES) runs the game, but does not display a graphic version of the game on the screen of the computer running the game. The default value for this is no. This means that you are running the server and participating as a player at the same time.
TIME LIMIT: entering a non-zero number here sets a time limit (in minutes) for the game duration. If the game has not ended because a frag limit has been set, then it will end when time runs out.
FRAG LIMIT: Entering a non-zero number here sets the number of "frags" or "kills" needed to win the game. If the game has not ended because a time limit has been set, then it will end when one player in the game reaches this number of frags.
MAX PLAYERS: This is the total number of players that may be in the game at any one time.
HOSTNAME: This is the name of the server. In the LAN example above, the hostname is "idserver."
CUSTOMIZE PLAYER:
Allows the player to change information about his in-game persona.
NAME: This is the player's name as it will appear on-screen during the game. It may be up to 33 characters long.
SKIN: Visor is the only model in the test. Two skins (red and blue) are available for the model. Use the left and right arrow keys to select one.
EFFECTS COLOR: You can choose an identifying color for your rail gun projectile trails. Use the left and right arrow keys to select a color.
HANDICAP: Better players can choose to handicap themselves to balance a match against players of less skill by limiting the maximum amount of health and armor that they can have during the game. Use the left and right arrows to select a value from 25 to 100 points. Certain items and power ups will temporarily raise this value, but will then count down to the preset value. The default is 100.
CUSTOMIZE CONTROLS:
Allows the player to change the assignment of game controls to other keyboard and mouse buttons. When you visit this menu for the first time, the default assignments for all controls are shown. To change an assignment, use the up/down arrow keys to select a game function. Press ENTER to activate the change process. Press the keyboard key or mouse input that you want to use for that function. Up to two keys/buttons may be assigned to each game function in this manner by repeating the process. If you inadvertently use a key assigned to another function, three question marks ("???") appear next to the function that previously used that key.
ALWAYS RUN: setting this to YES causes your player to move faster, but make more noise as he moves. The RUN/WALK key allows the player to switch between fast/noisy and slow/silent movement modes.
FREELOOK: If YES, then you may look freely in all directions as if you were moving only your head by moving the mouse around. If this is Set to NO you must bind a key to mouse look.
INVERT MOUSE: Selecting YES inverts the up and down view movement directions.
MOUSE SPEED: This is set on the menu with a slide control. The faster your mouse speed, the greater the on-screen response to small movements of the mouse. Mouse speed can also be adjusted from the console. Bring the console down and type in "sensitivity". The game will respond by printing "sensitivity" is: "__" (the blank indicating the number value currently assigned to mouse speed) default is "5". Use the up arrow key to display sensitivity on the console again, enter a different number value and hit enter. Higher numbers are more sensitive. Lower numbers are less sensitive.
SYSTEM CONFIGURATION:
EFFECTS VOLUME: Use the slide control to adjust game sound playback volume to your liking.
SOUND QUALITY: Select either Low (16 bit sound running at 11 megahertz) or High (32 bit sound running at 22 megahertz).
BRIGHTNESS: First, try running the game with the brightness set to 1.0 (the default level used by the designer when making the map). If the map is too dark to see in dimly lighted areas or too light in sunny areas, use this slide control to compensate for differences in the way some monitors and video cards draw the game world. Remember that the arenas are supposed to be dark and foreboding places.
GRAPHICS OPTIONS:
This drops you down into another menu layer. The controls here are designed to help you optimize graphics and or/enhance the game's playability on your system. When you are satisfied with your selections, you must move the cursor to the bottom of the screen to the APPLY option to activate them. Pressing Escape to return to the SYSTEM CONFIGURATION MENU does not activate changes in the graphics settings. Changing anything on this menu will cause the game to restart the video.
GRAPHICS MODE: This is a global setting for the display of the game's screen graphics. The settings are HIGH QUALITY, NORMAL, FAST, FASTEST, and CUSTOM. Selecting one of these choices affects most of the other settings on this page. If you make any adjustments to other settings on this page, the graphics mode changes to CUSTOM.
DRIVER: Consult the platform specific readme for the drivers that will work with your platform.
VIDEO MODE: This is the screen resolution size. Smaller resolutions can improve performance speed on slower machines.
COLOR DEPTH: Determines whether you are using 16-bit textures or 32-bit textures. Default means you run with the color depth currently set for your computer's desktop.
FULLSCREEN: A YES selection allows you to choose to run with the test filling the entire screen. A NO selection will run the game in a window. If run in a window, COLOR DEPTH is disabled because you are limited to whatever has been selected for the desktop.
LIGHTING: Allows you to chose either a LIGHTMAP or VERTEX lighting. Using the LIGHTMAP is recommended for best appearance. VERTEX lighting may improve game performance, but at a cost to appearance.
GEOMETRIC DETAIL: Lets you adjust the number subdivisions used to define curves in the arena on both world geometry and items, weapons and characters. HIGH is the normal setting. LOW greatly reduces curve complexity.
SCREEN SIZE: The slide control changes the amount of screen area devoted to display of the game. Reducing screen size can improve performance.
TEXTURE DETAIL: This sliding control allows you to adjust the level of detail displayed. Unless you have an extremely fast computer, the normal setting gives the best balance of detail vs. game speed.
TEXTURE QUALITY: This determines whether you wish to use 32-bit textures, 16-bit textures, or compressed textures. Many of the game's special effects will appear at their best only when defined by 32-bit textures.
OPENGL EXTENSIONS: Allows you to enable or disable OPENGL extensions.
DRIVER INFORMATION: Brings up a display of information regarding the drivers currently operating in your machine. It is not interactive. Hit ESC to return to the previous menu.
PREFERENCES: Hitting ENTER here will drop you into another menu that allows you to adjust other game features.
CROSSHAIR: choose one of four options, none, cross, dot, or angle.
MARKS ON WALLS: Enable or Disable weapons scars and blood smears. Disabling this feature may improve performance.
DYNAMIC LIGHTS: Enable or Disable lights that move through the world (such as light generated by weapon projectile trails). Disabling this feature may improve performance.
LIGHT FLARES: Enable or DISABLE glowing light halos around lights. Disabling this feature may improve performance.
IDENTIFY TARGET: Enable or Disable the ability to see the name of your foe when you put your crosshair on him (does not function if target is in fog).
SKY: Set the sky for either HIGH SPEED or HIGH QUALITY.
RESET DEFAULTS: Restore all game settings and controls to their default value by reloading the default configuration.
APPLY: You must select this and hit ENTER to lock in your choices. Doing so will restart the game video.
SCREENSHOT:
Makes a targa file screen shot of what is currently in view on the screen. Look for it in the Screenshot folder within your Quake 3/Baseq3/screenshots folder.
LEAVE ARENA:
This disconnects you from the arena you are currently playing, but does not quit you out of the game. From here you can connect to other servers or start your own. You can also leave an arena by typing "disconnect" on the command line of the console.
QUIT GAME:
Returns you to the desktop.
======================
== Section 6. ==
== STATUS READOUTS ==
======================
Your player status is shown as numbers and icons floating in your view at the bottom of the screen. There is an indicator for your ammo (far left) including the type of ammo currently in use, current health (left-center), your character portrait (center), armor (center-right), and Frag Count (far right). The digital timer in the upper right shows the amount of time you have been in this arena. When you have a one-use item in your inventory (such as the personal teleporter), its icon will appear on the right side of your display. When you are fragged, the character portrait and name of the foe who killed you appears in the upper right corner of the display. When you change weapons, icons representing the ammo of the weapons in your inventory will appear above your character portrait. If you have a weapon, but no ammunition for it, a negation symbol will be superimposed over the ammo icon.
+----------------------------+
| INTERPRETING THE LAGOMETER |
+----------------------------+
The Lagometer is the graph in the lower right corner of the status display. It is a test function and not a part of regular game play. The upper graph (blue/yellow) slides one pixel for every rendered frame. Blue lines below the baseline mean that the frame is interpolating between two valid snapshots. Yellow lines above the baseline mean the frame is extrapolating beyond the latest valid time. The length of the line is proportional to the time.
The lower graph (green/yellow/red) slides one pixel for every received snapshot. By default, snapshots come 20 times a second, so if you are running >20 fps, the top graph will move faster, and vice versa. A red bar means the snapshot was dropped by the network. Green and yellow bars are properly received snapshots, with the height of the bar proportional to the ping. A yellow bar indicates that the previous snapshot was intentionally suppressed to stay under the rate limit.
The upper graph indicates the consistency of your connection. Ideally, you should always have blue bars of only a pixel or two in height. If you are commonly getting big triangles of yellow on the graph, your connection is inconsistent.
In a heavy firefight, it is normal for modem players to see yellow bars in the bottom graph, which should return to green when the action quiets down. If you are getting several red bars visible, you may want to look for a server that drops less packets.
There are a few tuning variables for people trying to optimize their connection: The most important one is "rate", which is what the connection speed option in the menu sets. We are fairly conservative with the values we set for the given modem speeds: 2500 for 28.8, 3000 for 33, and 3500 for 56k. You may actually be connecting faster than that, and modem compression may be buying you something, so you might get a better play experience by increasing the values slightly. If you connect at 50000 bps, try a rate of 5000, etc. Quake 3 errs on the conservative side, because too low of a rate will only make the movement of other things in the world choppy, while too high of a rate can cause huge amounts of lag.
Note that the optimal rate will be somewhat lower than a rate for QW or Q2, because Quake 3 now includes the UDP packet header length in the bandwidth estimate. You can ask for a different number of snapshots by changing the "snaps" variable, but there isn't a lot of benefit to that. Dedicated servers run at 40hz, so stick to divisors of that: 40, 20 (default), 10. A "snaps" of 40 will usually just cause you to hit your rate limit a lot faster. It may be useful for tuning rate, if nothing else.
You can adjust the local timing point with "cg_timenudge ", which effectively adds local lag to try to make sure you interpolate instead of extrapolate. If you really want to play on a server that is dropping a ton of packets, a timenudge of 100 or so might make the game smoother.
=====================
== Section 7. ==
== PLAYER ACTIONS ==
=====================
The descriptions below are based on the preset default configurations for the game controls. If you have played first person shooting games previously (such as Quake or Quake 2), you may want to reconfigure the controls to match your preferences.
+----------+
| ACTIONS |
+----------+
WALKING: Use the four arrow keys or the mouse to walk around. To walk steadily forward, hold down the "forward" key (the up arrow or center button on a 3-button mouse). Turn left or right with the left or right arrow keys, or by sliding your mouse in the desired direction.
RUNNING: To run, simply hold down the left Shift key to increase your
Speed (unless you have selected "Always Run", in which case it reverts you to a walk. If you prefer to always run during the game, open the Main menu, then the Customize Controls menu, and select Always Run.
SHOOTING: Tap the Ctrl key or the left mouse button to fire. Hold the
fire key down to keep firing.
LOOKING UP AND DOWN: The letters A and Z allow you to look up and down,
respectively. Start walking forward and your line of vision will
automatically readjust to the center position. You may also choose to
select Free Look under the Controls menu which will allow you to move the
mouse around as if it was your head movement.
SWIMMING: While underwater, aim yourself in the direction you wish to go
and press the forward key to go in that direction. Unfortunately, as in
real life, you may lose your bearings while underwater. Use the jump key,
(default is the Space Bar), to kick straight up towards the surface. Once on
the surface, tread water by holding down the jump key. To get out of the
drink, swim toward the shore and you can either jump up onto the land or
walk straight out if it is shallow enough. There is always a way out of
water, but you may have to submerge even deeper in order to find it.
CROUCHING: Press and hold down the C key to duck and move forward to "duck walk." When you release the C key, you will return to an upright position. It is also possible to avoid rockets in this manner.
JUMPING: Tap the space bar to jump. You jump farther if you're moving
forward at the time.
STRAFING: Hold down the ALT key and the left or right arrow key and you will side-step in that particular direction. This is perfect for avoiding incoming weapon attacks.
PICKING UP OBJECTS: To pick up items, weapons, and power-ups, simply walk
over them. The weapon cross-hair will pulse larger briefly to indicate you have acquired a new weapon or supply. If you are unable to pick something up, it means you already have the maximum amount possible for that object.
TALKING: To communicate with other players, press the T key
and type in your message. Press Enter when finished and your words will
appear at the top of the screen. You can also enter communications on the command line of the console.
ATTACKING: Point your weapon at an opponent and press the fire button. Default fire keys are the left mouse and the control key). If a weapon runs out of ammo, it switches to the next available weapon with ammo the next time you fire it. If you have no ammo at all, you fight with the gauntlet.
+--------+
| DYING: |
+--------+
When you die, the weapon you were using (except for the gauntlet and the machine gun), and any active power ups drop where you died. Armor, ammo and one-use items like the teleporter are lost. To respawn into the game, press the fire key. When you re-enter the game you are once again armed with only your starting equipment.
===========================
== Section 8. ==
== THE ARENA ENVIRONMENT ==
===========================
+-----------------------+
| RAPID TRANSIT DEVICES |
+-----------------------+
TELEPORTERS: These devices instantaneously move you to a pre-selected destination.
PORTALS: These are devices that generate holes in space through which you can see your ultimate destination and move to it like walking through a doorway.
JUMP PADS: Jump pads throw you upwards to land on higher portions of the arena. You have some "air" control over your final landing point.
ACCELERATION PADS: Acceleration pads turn you into a human cannon ball, launching you to distant locations in the arena. As with the jump pads, you have some "air" control over your final landing point.
+-----------------------+
| ENVIRONMENTAL HAZARDS |
+-----------------------+
LAVA: Walking on lava is not instantly fatal, but even with good armor protection, it can be a relatively quick (and noisy) doom.
THE VOID: Falling off into the infinite blackness of the void is a near inescapable death.
+--------------+
| TEST ARSENAL |
+--------------+
MACHINE GUN: This is your default weapon. It's an instant hit attack and reasonably accurate even at long range. It uses bullets.
GAUNTLET: This is either your weapon of last resort when you're out of ammo or a cool tool to humiliate other players. When it hits, it does damage and knocks a foe back. It does not require ammunition, but you have to be in direct contact with a foe and activating (firing) it to cause injury and knockback.
SHOTGUN: This uses shells for ammunition. The spread of the shotgun blast makes it deadly in close combat, but not the best choice for long-range attacks.
ROCKET LAUNCHER: The rocket launcher delivers heavy fire power to your target, but travels slower compared to other attacks. Be careful when you use this weapon in close combat.
PLASMA GUN: Powered by Energy cells, this rapid-fire weapon delivers deadly gouts of glowing energy quickly and accurately.
RAIL GUN: The Rail Gun fires depleted uranium slugs at super high velocities. It hits instantly and can pass through the bodies of multiple opponents. But be warned, it recharges slowly and can be a liability in close combat. Take note of the distinctive trail of atmospheric disturbance
caused by the projectile. The color of the rail gun's trail can be changed under the CUSTOMIZE PLAYER menu on the EFFECTS COLOR line.
LIGHTNING GUN: Zap them!
+------------------+
| COMBAT SUPPLIES: |
+------------------+
Pick up these helpful items whenever possible. Some items take effect when
picked up, others you must activate during play.
AMMO: With the exception of the gauntlet, each weapon has a corresponding ammo type. The color of the ammo boxes corresponds with the color of the graphic weapon icons displayed briefly in your heads up display. Each ammo type has a maximum you can carry.
ARMOR: There are three armor types: Green armor shards, yellow combat armor and red body armor. Collecting them increases your armor protection. The red armor and the green armor shards can increase your total armor protection above the maximum for short duration. The points "decay" back to the normal maximum value.
HEALTH: There are three types of standard health kits: small (green), medium (yellow) and large (red) encased in crystalline shells. The green health can increase your total health value above the maximum. Like armor, it "decays" back to your maximum possible health value.
QUAD DAMAGE: The quad temporarily multiplies all your weapon's strengths.
MEGA HEALTH: This blue health power up provides a temporary but significant boost to your health, taking it above your maximum level. Like armor, it "decays" back to your maximum possible health value.
PERSONAL TELEPORTER: Grab this single-use power up and use it to escape from dangerous situations. Activating it immediately teleports you to one of the arena's spawn spots.
=======================
== Section 9. ==
== THE GAME CONSOLE ==
=======================
The game console (or just the console) is a pull down window shade that shows recent game information, including the text of conversations and recently executed game commands. The bottom line of the console is the command line. While playing Q3test, you can enter into console mode by pressing the tilde (~) key and exit by pressing it again. The console is where you enter all the commands to change the game state.
For example, one console command is "map <name>" which will load a map
and start it up. Starting up a map actually starts a local Server and a Client. For the purposes of this test, most of the console commands will be executed to optimize graphics. Pressing the up and down arrows in the console will change to the last command entered. You can backspace over the command and enter new values if you'd like. There is also a command-completion function. Type in the first few letters of a command. By pressing the TAB key, you can have the console automatically finish the name of the command for you.
When you are in console mode (or when you have selected to "talk" by typing in words to appear on the screen), a blue "voice balloon" will appear over your head. Common game courtesy is to NOT shoot players who are in this mode.
=======================
== Section 10. ==
== PROBLEM ICONS ==
=======================
Q3Test has a Problem Icon that you may see on your screen from time to time. When you are disconnected from a Quake Server or the network packet flow is disturbed, you will see a Network Disconnect icon above the spot where your frag count is displayed. Other players will see it displayed over your character's head (similar to the way the talk balloon is displayed). If you are not immediately reconnected to the server, you will need to disconnect (leave arena) and attempt to reconnect with the server by either using the menu commands or by typing "connect" <server IP address> in the console command line.
NOTE: Courteous players will refrain from getting cheap points by fragging lagged out opponents.
=======================
== Section 11. ==
== MESSAGE OF THE DAY ==
=======================
When Quake 3 Arena starts a map up, it sends the GL_RENDERER string to the Message Of The Day server at id. This responds back with a message of the day to the client. If you wish to switch this option off, set CL_MOTD to 0 (+set CL_MOTD 0 from the command line).

125
code/unix/build_setup.sh Normal file
View file

@ -0,0 +1,125 @@
#!/bin/bash
# Build various setups..
# inputs:
# directory with the common media
Q3SETUPMEDIA=/home/timo/Id/Q3SetupMedia/quake3
# directory with binaries tree
Q3BINARIES=../install
# version: $1
VERSION=$1
# temporary directory used to prepare the files
# NOTE: this dir is erased before a new setup is built
TMPDIR=setup.tmp
# location of the setup dir (for graphical installer and makeself)
SETUPDIR=setup
# cp setup phase
# we need to copy the symlinked files, and not the symlinks themselves
# on antares this is forced with a cp -L
# on spoutnik, -L is not recognized, and dereference is the default behaviour
# we need a robust way of checking
TESTFILE=/tmp/foo$$
touch $TESTFILE
# see if option is supported
cp -L $TESTFILE $TESTFILE.cp 2>/dev/null
if [ $? -eq 1 ]
then
# option not supported, should be on by default
echo "cp doesn't have -L option"
unset CPOPT
else
# option supported, use it
echo "cp supports -L option"
CPOPT="-L"
fi
rm $TESTFILE
# graphical installer (based on Loki Software's Setup tool)
build_installer ()
{
TMPDIR=setup.tmp
rm -rf $TMPDIR
mkdir $TMPDIR
# copy base setup files
cp $CPOPT -R $SETUPDIR/setup.sh $SETUPDIR/setup.data $TMPDIR
# copy media files
cp $CPOPT -R $Q3SETUPMEDIA/* $TMPDIR
# remove CVS entries
find $TMPDIR -name CVS | xargs rm -rf
# copy binaries
mkdir -p $TMPDIR/bin/x86
# smp
cp $CPOPT $Q3BINARIES/linuxquake3-smp $TMPDIR/bin/x86/quake3-smp.x86
strip $TMPDIR/bin/x86/quake3-smp.x86
brandelf -t Linux $TMPDIR/bin/x86/quake3-smp.x86
# old school
cp $CPOPT $Q3BINARIES/linuxquake3 $TMPDIR/bin/x86/quake3.x86
strip $TMPDIR/bin/x86/quake3.x86
brandelf -t Linux $TMPDIR/bin/x86/quake3.x86
# ded
cp $CPOPT $Q3BINARIES/linuxq3ded $TMPDIR/bin/x86/q3ded
strip $TMPDIR/bin/x86/q3ded
brandelf -t Linux $TMPDIR/bin/x86/q3ded
# PB files
mkdir -p $TMPDIR/pb/htm
cp $CPOPT ../pb/linux/*.so $TMPDIR/pb
cp $CPOPT ../pb/htm/*.htm $TMPDIR/pb/htm
# Linux FAQ
mkdir -p $TMPDIR/Docs/LinuxFAQ
cp $CPOPT LinuxSupport/* $TMPDIR/Docs/LinuxFAQ
# generated .qvm pk3 files
mkdir -p $TMPDIR/baseq3
mkdir -p $TMPDIR/missionpack
# not needed now
#cp $CPOPT $Q3BINARIES/baseq3/pak8.pk3 $TMPDIR/baseq3/
#cp $CPOPT $Q3BINARIES/missionpack/pak3.pk3 $TMPDIR/missionpack/
# menu shortcut to the game
# FIXME current setup doesn't have a way to set symlinks on arbitrary things
# so we use a dummy quake3 script (which will be overwritten by postinstall.sh)
echo -e "#!/bin/sh\necho \"If you read this, then the setup script failed miserably.\nPlease report to ttimo@idsoftware.com\n\"" > $TMPDIR/bin/x86/quake3
echo -e "#!/bin/sh\necho \"If you read this, then the setup script failed miserably.\nPlease report to ttimo@idsoftware.com\n\"" > $TMPDIR/bin/x86/quake3-smp
# create the auto-extractible archive
# first step: on FreeBSD we would default to Linux binaries .. use a symlink
(
cd $TMPDIR/setup.data/bin
ln -s Linux FreeBSD
ln -s Linux NetBSD
ln -s Linux OpenBSD
)
# NOTE: we used to pass the $VERSION, but it doesn't seem very usefull
./$SETUPDIR/makeself/makeself.sh $TMPDIR linuxq3apoint-$VERSION.x86.run "Quake III Arena Point Release $VERSION " ./setup.sh
chmod a+rx linuxq3apoint-$VERSION.x86.run
#rm -rf $TMPDIR
}
check_brandelf()
{
# make sure brandelf is installed to avoid any problem when building the setups
BRAND=`which brandelf`;
if [ -n "$BRAND" ] && [ -x "$BRAND" ]
then
echo "brandelf is present: $BRAND"
else
echo "brandelf not found"
exit
fi
}
# safe checks
check_brandelf
build_installer

6828
code/unix/cons Normal file

File diff suppressed because it is too large Load diff

9
code/unix/extract_ver.pl Normal file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env perl
# extracting version string from game/q_shared.h
# hacked from Wolf build process
# extract the wolf version from q_shared.h
$line = `cat ../game/q_shared.h | grep Q3_VERSION`;
chomp $line;
$line =~ s/.*Q3\ (.*)\"/$1/;
print "$line\n";

151
code/unix/ftol.nasm Normal file
View file

@ -0,0 +1,151 @@
;===========================================================================
;Copyright (C) 1999-2005 Id Software, Inc.
;
;This file is part of Quake III Arena source code.
;
;Quake III Arena source code 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.
;
;Quake III Arena source code 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 Foobar; if not, write to the Free Software
;Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
;===========================================================================
;
; qftol -- fast floating point to long conversion.
;
segment .data
temp dd 0.0
fpucw dd 0
; Precision Control Field , 2 bits / 0x0300
; PC24 0x0000 Single precision (24 bits).
; PC53 0x0200 Double precision (53 bits).
; PC64 0x0300 Extended precision (64 bits).
; Rounding Control Field, 2 bits / 0x0C00
; RCN 0x0000 Rounding to nearest (even).
; RCD 0x0400 Rounding down (directed, minus).
; RCU 0x0800 Rounding up (directed plus).
; RC0 0x0C00 Rounding towards zero (chop mode).
; rounding towards nearest (even)
cw027F dd 0x027F ; double precision
cw037F dd 0x037F ; extended precision
; rounding towards zero (chop mode)
cw0E7F dd 0x0E7F ; double precision
cw0F7F dd 0x0F7F ; extended precision
segment .text
;
; int qftol( void ) - default control word
;
global qftol
qftol:
fistp dword [temp]
mov eax, [temp]
ret
;
; int qftol027F( void ) - DirectX FPU
;
global qftol027F
qftol027F:
fnstcw [fpucw]
fldcw [cw027F]
fistp dword [temp]
fldcw [fpucw]
mov eax, [temp]
ret
;
; int qftol037F( void ) - Linux FPU
;
global qftol037F
qftol037F:
fnstcw [fpucw]
fldcw [cw037F]
fistp dword [temp]
fldcw [fpucw]
mov eax, [temp]
ret
;
; int qftol0F7F( void ) - ANSI
;
global qftol0F7F
qftol0F7F:
fnstcw [fpucw]
fldcw [cw0F7F]
fistp dword [temp]
fldcw [fpucw]
mov eax, [temp]
ret
;
; int qftol0E7F( void )
;
global qftol0E7F
qftol0E7F:
fnstcw [fpucw]
fldcw [cw0E7F]
fistp dword [temp]
fldcw [fpucw]
mov eax, [temp]
ret
;
; long Q_ftol( float q )
;
global Q_ftol
Q_ftol:
fld dword [esp+4]
fistp dword [temp]
mov eax, [temp]
ret
;
; long qftol0F7F( float q ) - Linux FPU
;
global Q_ftol0F7F
Q_ftol0F7F:
fnstcw [fpucw]
fld dword [esp+4]
fldcw [cw0F7F]
fistp dword [temp]
fldcw [fpucw]
mov eax, [temp]
ret

344
code/unix/linux_common.c Normal file
View file

@ -0,0 +1,344 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/**
* GAS syntax equivalents of the MSVC asm memory calls in common.c
*
* The following changes have been made to the asm:
* 1. Registers are loaded by the inline asm arguments when possible
* 2. Labels have been changed to local label format (0,1,etc.) to allow inlining
*
* HISTORY:
* AH - Created on 08 Dec 2000
*/
#include <unistd.h> // AH - for size_t
#include <string.h>
// bk001207 - we need something under Linux, too. Mac?
#if 1 // defined(C_ONLY) // bk010102 - dedicated?
void Com_Memcpy (void* dest, const void* src, const size_t count) {
memcpy(dest, src, count);
}
void Com_Memset (void* dest, const int val, const size_t count) {
memset(dest, val, count);
}
#else
typedef enum {
PRE_READ, // prefetch assuming that buffer is used for reading only
PRE_WRITE, // prefetch assuming that buffer is used for writing only
PRE_READ_WRITE // prefetch assuming that buffer is used for both reading and writing
} e_prefetch;
void Com_Prefetch (const void *s, const unsigned int bytes, e_prefetch type);
void _copyDWord (unsigned int* dest, const unsigned int constant, const unsigned int count) {
// MMX version not used on standard Pentium MMX
// because the dword version is faster (with
// proper destination prefetching)
__asm__ __volatile__ (" \
//mov eax,constant // eax = val \
//mov edx,dest // dest \
//mov ecx,count \
movd %%eax, %%mm0 \
punpckldq %%mm0, %%mm0 \
\
// ensure that destination is qword aligned \
\
testl $7, %%edx // qword padding?\
jz 0f \
movl %%eax, (%%edx) \
decl %%ecx \
addl $4, %%edx \
\
0: movl %%ecx, %%ebx \
andl $0xfffffff0, %%ecx \
jz 2f \
jmp 1f \
.align 16 \
\
// funny ordering here to avoid commands \
// that cross 32-byte boundaries (the \
// [edx+0] version has a special 3-byte opcode... \
1: movq %%mm0, 8(%%edx) \
movq %%mm0, 16(%%edx) \
movq %%mm0, 24(%%edx) \
movq %%mm0, 32(%%edx) \
movq %%mm0, 40(%%edx) \
movq %%mm0, 48(%%edx) \
movq %%mm0, 56(%%edx) \
movq %%mm0, (%%edx)\
addl $64, %%edx \
subl $16, %%ecx \
jnz 1b \
2: \
movl %%ebx, %%ecx // ebx = cnt \
andl $0xfffffff0, %%ecx // ecx = cnt&~15 \
subl %%ecx, %%ebx \
jz 6f \
cmpl $8, %%ebx \
jl 3f \
\
movq %%mm0, (%%edx) \
movq %%mm0, 8(%%edx) \
movq %%mm0, 16(%%edx) \
movq %%mm0, 24(%%edx) \
addl $32, %%edx \
subl $8, %%ebx \
jz 6f \
\
3: cmpl $4, %%ebx \
jl 4f \
\
movq %%mm0, (%%edx) \
movq %%mm0, 8(%%edx) \
addl $16, %%edx \
subl $4, %%ebx \
\
4: cmpl $2, %%ebx \
jl 5f \
movq %%mm0, (%%edx) \
addl $8, %%edx \
subl $2, %%ebx \
\
5: cmpl $1, %%ebx \
jl 6f \
movl %%eax, (%%edx) \
6: \
emms \
"
: : "a" (constant), "c" (count), "d" (dest)
: "%ebx", "%edi", "%esi", "cc", "memory");
}
// optimized memory copy routine that handles all alignment
// cases and block sizes efficiently
void Com_Memcpy (void* dest, const void* src, const size_t count) {
Com_Prefetch (src, count, PRE_READ);
__asm__ __volatile__ (" \
pushl %%edi \
pushl %%esi \
//mov ecx,count \
cmpl $0, %%ecx // count = 0 check (just to be on the safe side) \
je 6f \
//mov edx,dest \
movl %0, %%ebx \
cmpl $32, %%ecx // padding only? \
jl 1f \
\
movl %%ecx, %%edi \
andl $0xfffffe00, %%edi // edi = count&~31 \
subl $32, %%edi \
\
.align 16 \
0: \
movl (%%ebx, %%edi, 1), %%eax \
movl 4(%%ebx, %%edi, 1), %%esi \
movl %%eax, (%%edx, %%edi, 1) \
movl %%esi, 4(%%edx, %%edi, 1) \
movl 8(%%ebx, %%edi, 1), %%eax \
movl 12(%%ebx, %%edi, 1), %%esi \
movl %%eax, 8(%%edx, %%edi, 1) \
movl %%esi, 12(%%edx, %%edi, 1) \
movl 16(%%ebx, %%edi, 1), %%eax \
movl 20(%%ebx, %%edi, 1), %%esi \
movl %%eax, 16(%%edx, %%edi, 1) \
movl %%esi, 20(%%edx, %%edi, 1) \
movl 24(%%ebx, %%edi, 1), %%eax \
movl 28(%%ebx, %%edi, 1), %%esi \
movl %%eax, 24(%%edx, %%edi, 1) \
movl %%esi, 28(%%edx, %%edi, 1) \
subl $32, %%edi \
jge 0b \
\
movl %%ecx, %%edi \
andl $0xfffffe00, %%edi \
addl %%edi, %%ebx // increase src pointer \
addl %%edi, %%edx // increase dst pointer \
andl $31, %%ecx // new count \
jz 6f // if count = 0, get outta here \
\
1: \
cmpl $16, %%ecx \
jl 2f \
movl (%%ebx), %%eax \
movl %%eax, (%%edx) \
movl 4(%%ebx), %%eax \
movl %%eax, 4(%%edx) \
movl 8(%%ebx), %%eax \
movl %%eax, 8(%%edx) \
movl 12(%%ebx), %%eax \
movl %%eax, 12(%%edx) \
subl $16, %%ecx \
addl $16, %%ebx \
addl $16, %%edx \
2: \
cmpl $8, %%ecx \
jl 3f \
movl (%%ebx), %%eax \
movl %%eax, (%%edx) \
movl 4(%%ebx), %%eax \
subl $8, %%ecx \
movl %%eax, 4(%%edx) \
addl $8, %%ebx \
addl $8, %%edx \
3: \
cmpl $4, %%ecx \
jl 4f \
movl (%%ebx), %%eax // here 4-7 bytes \
addl $4, %%ebx \
subl $4, %%ecx \
movl %%eax, (%%edx) \
addl $4, %%edx \
4: // 0-3 remaining bytes \
cmpl $2, %%ecx \
jl 5f \
movw (%%ebx), %%ax // two bytes \
cmpl $3, %%ecx // less than 3? \
movw %%ax, (%%edx) \
jl 6f \
movb 2(%%ebx), %%al // last byte \
movb %%al, 2(%%edx) \
jmp 6f \
5: \
cmpl $1, %%ecx \
jl 6f \
movb (%%ebx), %%al \
movb %%al, (%%edx) \
6: \
popl %%esi \
popl %%edi \
"
: : "m" (src), "d" (dest), "c" (count)
: "%eax", "%ebx", "%edi", "%esi", "cc", "memory");
}
void Com_Memset (void* dest, const int val, const size_t count)
{
unsigned int fillval;
if (count < 8)
{
__asm__ __volatile__ (" \
//mov edx,dest \
//mov eax, val \
movb %%al, %%ah \
movl %%eax, %%ebx \
andl $0xffff, %%ebx \
shll $16, %%eax \
addl %%ebx, %%eax // eax now contains pattern \
//mov ecx,count \
cmpl $4, %%ecx \
jl 0f \
movl %%eax, (%%edx) // copy first dword \
addl $4, %%edx \
subl $4, %%ecx \
0: cmpl $2, %%ecx \
jl 1f \
movw %%ax, (%%edx) // copy 2 bytes \
addl $2, %%edx \
subl $2, %%ecx \
1: cmpl $0, %%ecx \
je 2f \
movb %%al, (%%edx) // copy single byte \
2: \
"
: : "d" (dest), "a" (val), "c" (count)
: "%ebx", "%edi", "%esi", "cc", "memory");
return;
}
fillval = val;
fillval = fillval|(fillval<<8);
fillval = fillval|(fillval<<16); // fill dword with 8-bit pattern
_copyDWord ((unsigned int*)(dest),fillval, count/4);
__asm__ __volatile__ (" // padding of 0-3 bytes \
//mov ecx,count \
movl %%ecx, %%eax \
andl $3, %%ecx \
jz 1f \
andl $0xffffff00, %%eax \
//mov ebx,dest \
addl %%eax, %%edx \
movl %0, %%eax \
cmpl $2, %%ecx \
jl 0f \
movw %%ax, (%%edx) \
cmpl $2, %%ecx \
je 1f \
movb %%al, 2(%%edx) \
jmp 1f \
0: \
cmpl $0, %%ecx\
je 1f\
movb %%al, (%%edx)\
1: \
"
: : "m" (fillval), "c" (count), "d" (dest)
: "%eax", "%ebx", "%edi", "%esi", "cc", "memory");
}
void Com_Prefetch (const void *s, const unsigned int bytes, e_prefetch type)
{
// write buffer prefetching is performed only if
// the processor benefits from it. Read and read/write
// prefetching is always performed.
switch (type)
{
case PRE_WRITE : break;
case PRE_READ:
case PRE_READ_WRITE:
__asm__ __volatile__ ("\
//mov ebx,s\
//mov ecx,bytes\
cmpl $4096, %%ecx // clamp to 4kB\
jle 0f\
movl $4096, %%ecx\
0:\
addl $0x1f, %%ecx\
shrl $5, %%ecx // number of cache lines\
jz 2f\
jmp 1f\
\
.align 16\
1: testb %%al, (%%edx)\
addl $32, %%edx\
decl %%ecx\
jnz 1b\
2:\
"
: : "d" (s), "c" (bytes)
: "%eax", "%ebx", "%edi", "%esi", "memory", "cc");
break;
}
}
#endif

1780
code/unix/linux_glimp.c Normal file

File diff suppressed because it is too large Load diff

207
code/unix/linux_joystick.c Normal file
View file

@ -0,0 +1,207 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*
** linux_joystick.c
**
** This file contains ALL Linux specific stuff having to do with the
** Joystick input. When a port is being made the following functions
** must be implemented by the port:
**
** Authors: mkv, bk
**
*/
#include <linux/joystick.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h> // bk001204
#include "../client/client.h"
#include "linux_local.h"
/* We translate axes movement into keypresses. */
int joy_keys[16] = {
K_LEFTARROW, K_RIGHTARROW,
K_UPARROW, K_DOWNARROW,
K_JOY16, K_JOY17,
K_JOY18, K_JOY19,
K_JOY20, K_JOY21,
K_JOY22, K_JOY23,
K_JOY24, K_JOY25,
K_JOY26, K_JOY27
};
/* Our file descriptor for the joystick device. */
static int joy_fd = -1;
// bk001130 - from linux_glimp.c
extern cvar_t * in_joystick;
extern cvar_t * in_joystickDebug;
extern cvar_t * joy_threshold;
/**********************************************/
/* Joystick routines. */
/**********************************************/
// bk001130 - from cvs1.17 (mkv), removed from linux_glimp.c
void IN_StartupJoystick( void )
{
int i = 0;
joy_fd = -1;
if( !in_joystick->integer ) {
Com_Printf( "Joystick is not active.\n" );
return;
}
for( i = 0; i < 4; i++ ) {
char filename[PATH_MAX];
snprintf( filename, PATH_MAX, "/dev/js%d", i );
joy_fd = open( filename, O_RDONLY | O_NONBLOCK );
if( joy_fd != -1 ) {
struct js_event event;
char axes = 0;
char buttons = 0;
char name[128];
int n = -1;
Com_Printf( "Joystick %s found\n", filename );
/* Get rid of initialization messages. */
do {
n = read( joy_fd, &event, sizeof( event ) );
if( n == -1 ) {
break;
}
} while( ( event.type & JS_EVENT_INIT ) );
/* Get joystick statistics. */
ioctl( joy_fd, JSIOCGAXES, &axes );
ioctl( joy_fd, JSIOCGBUTTONS, &buttons );
if( ioctl( joy_fd, JSIOCGNAME( sizeof( name ) ), name ) < 0 ) {
strncpy( name, "Unknown", sizeof( name ) );
}
Com_Printf( "Name: %s\n", name );
Com_Printf( "Axes: %d\n", axes );
Com_Printf( "Buttons: %d\n", buttons );
/* Our work here is done. */
return;
}
}
/* No soup for you. */
if( joy_fd == -1 ) {
Com_Printf( "No joystick found.\n" );
return;
}
}
void IN_JoyMove( void )
{
/* Store instantaneous joystick state. Hack to get around
* event model used in Linux joystick driver.
*/
static int axes_state[16];
/* Old bits for Quake-style input compares. */
static unsigned int old_axes = 0;
/* Our current goodies. */
unsigned int axes = 0;
int i = 0;
if( joy_fd == -1 ) {
return;
}
/* Empty the queue, dispatching button presses immediately
* and updating the instantaneous state for the axes.
*/
do {
int n = -1;
struct js_event event;
n = read( joy_fd, &event, sizeof( event ) );
if( n == -1 ) {
/* No error, we're non-blocking. */
break;
}
if( event.type & JS_EVENT_BUTTON ) {
Sys_QueEvent( 0, SE_KEY, K_JOY1 + event.number, event.value, 0, NULL );
} else if( event.type & JS_EVENT_AXIS ) {
if( event.number >= 16 ) {
continue;
}
axes_state[event.number] = event.value;
} else {
Com_Printf( "Unknown joystick event type\n" );
}
} while( 1 );
/* Translate our instantaneous state to bits. */
for( i = 0; i < 16; i++ ) {
float f = ( (float) axes_state[i] ) / 32767.0f;
if( f < -joy_threshold->value ) {
axes |= ( 1 << ( i * 2 ) );
} else if( f > joy_threshold->value ) {
axes |= ( 1 << ( ( i * 2 ) + 1 ) );
}
}
/* Time to update axes state based on old vs. new. */
for( i = 0; i < 16; i++ ) {
if( ( axes & ( 1 << i ) ) && !( old_axes & ( 1 << i ) ) ) {
Sys_QueEvent( 0, SE_KEY, joy_keys[i], qtrue, 0, NULL );
}
if( !( axes & ( 1 << i ) ) && ( old_axes & ( 1 << i ) ) ) {
Sys_QueEvent( 0, SE_KEY, joy_keys[i], qfalse, 0, NULL );
}
}
/* Save for future generations. */
old_axes = axes;
}

49
code/unix/linux_local.h Normal file
View file

@ -0,0 +1,49 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// linux_local.h: Linux-specific Quake3 header file
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message );
void Sys_SendKeyEvents (void);
// Input subsystem
void IN_Init (void);
void IN_Frame (void);
void IN_Shutdown (void);
void IN_JoyMove( void );
void IN_StartupJoystick( void );
// GL subsystem
qboolean QGL_Init( const char *dllname );
void QGL_EnableLogging( qboolean enable );
void QGL_Shutdown( void );
// bk001130 - win32
// void IN_JoystickCommands (void);
char *strlwr (char *s);
// signals.c
void InitSig(void);

4153
code/unix/linux_qgl.c Normal file

File diff suppressed because it is too large Load diff

61
code/unix/linux_signals.c Normal file
View file

@ -0,0 +1,61 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include <signal.h>
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
#ifndef DEDICATED
#include "../renderer/tr_local.h"
#endif
static qboolean signalcaught = qfalse;;
void Sys_Exit(int); // bk010104 - abstraction
static void signal_handler(int sig) // bk010104 - replace this... (NOTE TTimo huh?)
{
if (signalcaught)
{
printf("DOUBLE SIGNAL FAULT: Received signal %d, exiting...\n", sig);
Sys_Exit(1); // bk010104 - abstraction
}
signalcaught = qtrue;
printf("Received signal %d, exiting...\n", sig);
#ifndef DEDICATED
GLimp_Shutdown(); // bk010104 - shouldn't this be CL_Shutdown
#endif
Sys_Exit(0); // bk010104 - abstraction NOTE TTimo send a 0 to avoid DOUBLE SIGNAL FAULT
}
void InitSig(void)
{
signal(SIGHUP, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGILL, signal_handler);
signal(SIGTRAP, signal_handler);
signal(SIGIOT, signal_handler);
signal(SIGBUS, signal_handler);
signal(SIGFPE, signal_handler);
signal(SIGSEGV, signal_handler);
signal(SIGTERM, signal_handler);
}

293
code/unix/linux_snd.c Normal file
View file

@ -0,0 +1,293 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#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>
#ifdef __linux__ // rb0101023 - guard this
#include <linux/soundcard.h>
#endif
#ifdef __FreeBSD__ // rb0101023 - added
#include <sys/soundcard.h>
#endif
#include <stdio.h>
#include "../game/q_shared.h"
#include "../client/snd_local.h"
int audio_fd;
int snd_inited=0;
cvar_t *sndbits;
cvar_t *sndspeed;
cvar_t *sndchannels;
cvar_t *snddevice;
/* Some devices may work only with 48000 */
static int tryrates[] = { 22050, 11025, 44100, 48000, 8000 };
static qboolean use_custom_memset = qfalse;
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
void Snd_Memset (void* dest, const int val, const size_t count)
{
int *pDest;
int i, iterate;
if (!use_custom_memset)
{
Com_Memset(dest,val,count);
return;
}
iterate = count / sizeof(int);
pDest = (int*)dest;
for(i=0; i<iterate; i++)
{
pDest[i] = val;
}
}
qboolean SNDDMA_Init(void)
{
int rc;
int fmt;
int tmp;
int i;
// char *s; // bk001204 - unused
struct audio_buf_info info;
int caps;
extern uid_t saved_euid;
if (snd_inited)
return 1;
if (!snddevice) {
sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
}
// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
if (!audio_fd) {
seteuid(saved_euid);
audio_fd = open(snddevice->string, O_RDWR);
seteuid(getuid());
if (audio_fd < 0) {
perror(snddevice->string);
Com_Printf("Could not open %s\n", snddevice->string);
return 0;
}
}
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1) {
perror(snddevice->string);
Com_Printf("Sound driver too old\n");
close(audio_fd);
return 0;
}
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
Com_Printf("Sorry but your soundcard can't do this\n");
close(audio_fd);
return 0;
}
/* SNDCTL_DSP_GETOSPACE moved to be called later */
// set sample bits & speed
dma.samplebits = (int)sndbits->value;
if (dma.samplebits != 16 && dma.samplebits != 8) {
ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
if (fmt & AFMT_S16_LE)
dma.samplebits = 16;
else if (fmt & AFMT_U8)
dma.samplebits = 8;
}
dma.speed = (int)sndspeed->value;
if (!dma.speed) {
for (i=0 ; i<sizeof(tryrates)/4 ; i++)
if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i]))
break;
dma.speed = tryrates[i];
}
dma.channels = (int)sndchannels->value;
if (dma.channels < 1 || dma.channels > 2)
dma.channels = 2;
/* mmap() call moved forward */
tmp = 0;
if (dma.channels == 2)
tmp = 1;
rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("Could not set %s to stereo=%d", snddevice->string, dma.channels);
close(audio_fd);
return 0;
}
if (tmp)
dma.channels = 2;
else
dma.channels = 1;
rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &dma.speed);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("Could not set %s speed to %d", snddevice->string, dma.speed);
close(audio_fd);
return 0;
}
if (dma.samplebits == 16) {
rc = AFMT_S16_LE;
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("Could not support 16-bit data. Try 8-bit.\n");
close(audio_fd);
return 0;
}
} else if (dma.samplebits == 8) {
rc = AFMT_U8;
rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("Could not support 8-bit data.\n");
close(audio_fd);
return 0;
}
} else {
perror(snddevice->string);
Com_Printf("%d-bit sound not supported.", dma.samplebits);
close(audio_fd);
return 0;
}
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) {
perror("GETOSPACE");
Com_Printf("Um, can't do GETOSPACE?\n");
close(audio_fd);
return 0;
}
dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
dma.submission_chunk = 1;
// memory map the dma buffer
// TTimo 2001/10/08 added PROT_READ to the mmap
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
// checking Alsa bug, doesn't allow dma alloc with PROT_READ?
if (!dma.buffer)
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
* info.fragsize, PROT_WRITE|PROT_READ, MAP_FILE|MAP_SHARED, audio_fd, 0);
if (dma.buffer == MAP_FAILED)
{
Com_Printf("Could not mmap dma buffer PROT_WRITE|PROT_READ\n");
Com_Printf("trying mmap PROT_WRITE (with associated better compatibility / less performance code)\n");
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
* info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
// NOTE TTimo could add a variable to force using regular memset on systems that are known to be safe
use_custom_memset = qtrue;
}
if (dma.buffer == MAP_FAILED) {
perror(snddevice->string);
Com_Printf("Could not mmap %s\n", snddevice->string);
close(audio_fd);
return 0;
}
// toggle the trigger & start her up
tmp = 0;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("Could not toggle.\n");
close(audio_fd);
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0) {
perror(snddevice->string);
Com_Printf("Could not toggle.\n");
close(audio_fd);
return 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(snddevice->string);
Com_Printf("Uh, sound dead.\n");
close(audio_fd);
snd_inited = 0;
return 0;
}
return count.ptr / (dma.samplebits / 8);
}
void SNDDMA_Shutdown(void)
{
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
===============
*/
void SNDDMA_Submit(void)
{
}
void SNDDMA_BeginPainting (void)
{
}

425
code/unix/matha.s Normal file
View file

@ -0,0 +1,425 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// math.s
// x86 assembly-language math routines.
#define GLQUAKE 1 // don't include unneeded defs
#include "qasm.h"
#if id386
.data
.align 4
Ljmptab: .long Lcase0, Lcase1, Lcase2, Lcase3
.long Lcase4, Lcase5, Lcase6, Lcase7
.text
// TODO: rounding needed?
// stack parameter offset
#define val 4
.globl C(Invert24To16)
C(Invert24To16):
movl val(%esp),%ecx
movl $0x100,%edx // 0x10000000000 as dividend
cmpl %edx,%ecx
jle LOutOfRange
subl %eax,%eax
divl %ecx
ret
LOutOfRange:
movl $0xFFFFFFFF,%eax
ret
#if 0
#define in 4
#define out 8
.align 2
.globl C(TransformVector)
C(TransformVector):
movl in(%esp),%eax
movl out(%esp),%edx
flds (%eax) // in[0]
fmuls C(vright) // in[0]*vright[0]
flds (%eax) // in[0] | in[0]*vright[0]
fmuls C(vup) // in[0]*vup[0] | in[0]*vright[0]
flds (%eax) // in[0] | in[0]*vup[0] | in[0]*vright[0]
fmuls C(vpn) // in[0]*vpn[0] | in[0]*vup[0] | in[0]*vright[0]
flds 4(%eax) // in[1] | ...
fmuls C(vright)+4 // in[1]*vright[1] | ...
flds 4(%eax) // in[1] | in[1]*vright[1] | ...
fmuls C(vup)+4 // in[1]*vup[1] | in[1]*vright[1] | ...
flds 4(%eax) // in[1] | in[1]*vup[1] | in[1]*vright[1] | ...
fmuls C(vpn)+4 // in[1]*vpn[1] | in[1]*vup[1] | in[1]*vright[1] | ...
fxch %st(2) // in[1]*vright[1] | in[1]*vup[1] | in[1]*vpn[1] | ...
faddp %st(0),%st(5) // in[1]*vup[1] | in[1]*vpn[1] | ...
faddp %st(0),%st(3) // in[1]*vpn[1] | ...
faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum
flds 8(%eax) // in[2] | ...
fmuls C(vright)+8 // in[2]*vright[2] | ...
flds 8(%eax) // in[2] | in[2]*vright[2] | ...
fmuls C(vup)+8 // in[2]*vup[2] | in[2]*vright[2] | ...
flds 8(%eax) // in[2] | in[2]*vup[2] | in[2]*vright[2] | ...
fmuls C(vpn)+8 // in[2]*vpn[2] | in[2]*vup[2] | in[2]*vright[2] | ...
fxch %st(2) // in[2]*vright[2] | in[2]*vup[2] | in[2]*vpn[2] | ...
faddp %st(0),%st(5) // in[2]*vup[2] | in[2]*vpn[2] | ...
faddp %st(0),%st(3) // in[2]*vpn[2] | ...
faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum
fstps 8(%edx) // out[2]
fstps 4(%edx) // out[1]
fstps (%edx) // out[0]
ret
#endif
#define EMINS 4+4
#define EMAXS 4+8
#define P 4+12
.align 2
.globl C(BoxOnPlaneSide)
C(BoxOnPlaneSide):
pushl %ebx
movl P(%esp),%edx
movl EMINS(%esp),%ecx
xorl %eax,%eax
movl EMAXS(%esp),%ebx
movb pl_signbits(%edx),%al
cmpb $8,%al
jge Lerror
flds pl_normal(%edx) // p->normal[0]
fld %st(0) // p->normal[0] | p->normal[0]
// bk000422 - warning: missing prefix `*' in absolute indirect address, maybe misassembled!
// bk001129 - fix from Andrew Henderson, was: Ljmptab(,%eax,4)
jmp *Ljmptab(,%eax,4)
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
Lcase0:
fmuls (%ebx) // p->normal[0]*emaxs[0] | p->normal[0]
flds pl_normal+4(%edx) // p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]
fxch %st(2) // p->normal[0] | p->normal[0]*emaxs[0] |
// p->normal[1]
fmuls (%ecx) // p->normal[0]*emins[0] |
// p->normal[0]*emaxs[0] | p->normal[1]
fxch %st(2) // p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fld %st(0) // p->normal[1] | p->normal[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 4(%ebx) // p->normal[1]*emaxs[1] | p->normal[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
flds pl_normal+8(%edx) // p->normal[2] | p->normal[1]*emaxs[1] |
// p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(2) // p->normal[1] | p->normal[1]*emaxs[1] |
// p->normal[2] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 4(%ecx) // p->normal[1]*emins[1] |
// p->normal[1]*emaxs[1] |
// p->normal[2] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(2) // p->normal[2] | p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fld %st(0) // p->normal[2] | p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 8(%ebx) // p->normal[2]*emaxs[2] |
// p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(5) // p->normal[0]*emins[0] |
// p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
faddp %st(0),%st(3) //p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
fmuls 8(%ecx) //p->normal[2]*emins[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
fxch %st(1) //p->normal[1]*emaxs[1] |
// p->normal[2]*emins[2] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
faddp %st(0),%st(3) //p->normal[2]*emins[2] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
// p->normal[2]*emaxs[2]
fxch %st(3) //p->normal[2]*emaxs[2] +
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
// p->normal[2]*emins[2]
faddp %st(0),%st(2) //p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// dist1 | p->normal[2]*emins[2]
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
Lcase1:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
Lcase2:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
Lcase3:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
Lcase4:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
Lcase5:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
Lcase6:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
Lcase7:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
LSetSides:
// sides = 0;
// if (dist1 >= p->dist)
// sides = 1;
// if (dist2 < p->dist)
// sides |= 2;
faddp %st(0),%st(2) // dist1 | dist2
fcomps pl_dist(%edx)
xorl %ecx,%ecx
fnstsw %ax
fcomps pl_dist(%edx)
andb $1,%ah
xorb $1,%ah
addb %ah,%cl
fnstsw %ax
andb $1,%ah
addb %ah,%ah
addb %ah,%cl
// return sides;
popl %ebx
movl %ecx,%eax // return status
ret
Lerror:
movl 1, %eax
ret
#endif // id386

7911
code/unix/pcons-2.3.1 Normal file

File diff suppressed because it is too large Load diff

52
code/unix/q3test.spec.sh Normal file
View file

@ -0,0 +1,52 @@
#!/bin/sh
# Generate Quake3 test
# $1 is version
# $2 is release
# $3 is arch
# $4 is install dir (assumed to be in /var/tmp)
cat <<EOF
%define name q3test
%define version ${1}
%define release ${2}
%define arch ${3}
%define builddir \$RPM_BUILD_DIR/%{name}-%{version}
Name: %{name}
Version: %{version}
Release: %{release}
Vendor: id Software
Packager: Dave "Zoid" Kirsch <zoid@idsoftware.com>
URL: http://www.idsoftware.com/
Source: q3test-%{version}.tar.gz
Group: Games
Copyright: Restricted
Icon: quake3.gif
BuildRoot: /var/tmp/%{name}-%{version}
Summary: Q3Test for Linux
%description
%install
%files
%attr(644,root,root) $4/README.EULA
%attr(644,root,root) $4/README.Q3Test
%attr(644,root,root) $4/README.Linux
%attr(644,root,root) $4/Quake3.kdelnk
%attr(644,root,root) $4/quake3.xpm
%attr(755,root,root) $4/linuxquake3
%attr(755,root,root) $4/cgamei386.so
%attr(755,root,root) $4/qagamei386.so
%attr(755,root,root) $4/uii386.so
%attr(755,root,root) $4/libMesaVoodooGL.so.3.1
%attr(644,root,root) $4/demoq3/pak0.pk3
%post
if [ -n "\$KDEDIR" ]; then
ln -sf $4/Quake3.kdelnk \$KDEDIR/share/applnk/Games/Quake3.kdelnk
ln -sf $4/quake3.xpm \$KDEDIR/share/icons/quake3.xpm
fi
EOF

480
code/unix/qasm.h Normal file
View file

@ -0,0 +1,480 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __ASM_I386__
#define __ASM_I386__
#ifdef ELF
#define C(label) label
#else
#define C(label) _##label
#endif
//#define GLQUAKE 1
#if defined(_WIN32) && !defined(WINDED)
#if defined(_M_IX86)
#define __i386__ 1
#endif
#endif
#ifdef __i386__
#define id386 1
#else
#define id386 0
#endif
// !!! must be kept the same as in d_iface.h !!!
#define TRANSPARENT_COLOR 255
#ifndef GLQUAKE
.extern C(d_zistepu)
.extern C(d_pzbuffer)
.extern C(d_zistepv)
.extern C(d_zrowbytes)
.extern C(d_ziorigin)
.extern C(r_turb_s)
.extern C(r_turb_t)
.extern C(r_turb_pdest)
.extern C(r_turb_spancount)
.extern C(r_turb_turb)
.extern C(r_turb_pbase)
.extern C(r_turb_sstep)
.extern C(r_turb_tstep)
.extern C(r_bmodelactive)
.extern C(d_sdivzstepu)
.extern C(d_tdivzstepu)
.extern C(d_sdivzstepv)
.extern C(d_tdivzstepv)
.extern C(d_sdivzorigin)
.extern C(d_tdivzorigin)
.extern C(sadjust)
.extern C(tadjust)
.extern C(bbextents)
.extern C(bbextentt)
.extern C(cacheblock)
.extern C(d_viewbuffer)
.extern C(cachewidth)
.extern C(d_pzbuffer)
.extern C(d_zrowbytes)
.extern C(d_zwidth)
.extern C(d_scantable)
.extern C(r_lightptr)
.extern C(r_numvblocks)
.extern C(prowdestbase)
.extern C(pbasesource)
.extern C(r_lightwidth)
.extern C(lightright)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(lightdelta)
.extern C(lightright)
.extern C(lightdelta)
.extern C(sourcetstep)
.extern C(surfrowbytes)
.extern C(lightrightstep)
.extern C(lightdeltastep)
.extern C(r_sourcemax)
.extern C(r_stepback)
.extern C(colormap)
.extern C(blocksize)
.extern C(sourcesstep)
.extern C(lightleft)
.extern C(blockdivshift)
.extern C(blockdivmask)
.extern C(lightleftstep)
.extern C(r_origin)
.extern C(r_ppn)
.extern C(r_pup)
.extern C(r_pright)
.extern C(ycenter)
.extern C(xcenter)
.extern C(d_vrectbottom_particle)
.extern C(d_vrectright_particle)
.extern C(d_vrecty)
.extern C(d_vrectx)
.extern C(d_pix_shift)
.extern C(d_pix_min)
.extern C(d_pix_max)
.extern C(d_y_aspect_shift)
.extern C(screenwidth)
.extern C(r_leftclipped)
.extern C(r_leftenter)
.extern C(r_rightclipped)
.extern C(r_rightenter)
.extern C(modelorg)
.extern C(xscale)
.extern C(r_refdef)
.extern C(yscale)
.extern C(r_leftexit)
.extern C(r_rightexit)
.extern C(r_lastvertvalid)
.extern C(cacheoffset)
.extern C(newedges)
.extern C(removeedges)
.extern C(r_pedge)
.extern C(r_framecount)
.extern C(r_u1)
.extern C(r_emitted)
.extern C(edge_p)
.extern C(surface_p)
.extern C(surfaces)
.extern C(r_lzi1)
.extern C(r_v1)
.extern C(r_ceilv1)
.extern C(r_nearzi)
.extern C(r_nearzionly)
.extern C(edge_aftertail)
.extern C(edge_tail)
.extern C(current_iv)
.extern C(edge_head_u_shift20)
.extern C(span_p)
.extern C(edge_head)
.extern C(fv)
.extern C(edge_tail_u_shift20)
.extern C(r_apverts)
.extern C(r_anumverts)
.extern C(aliastransform)
.extern C(r_avertexnormals)
.extern C(r_plightvec)
.extern C(r_ambientlight)
.extern C(r_shadelight)
.extern C(aliasxcenter)
.extern C(aliasycenter)
.extern C(a_sstepxfrac)
.extern C(r_affinetridesc)
.extern C(acolormap)
.extern C(d_pcolormap)
.extern C(r_affinetridesc)
.extern C(d_sfrac)
.extern C(d_ptex)
.extern C(d_pedgespanpackage)
.extern C(d_tfrac)
.extern C(d_light)
.extern C(d_zi)
.extern C(d_pdest)
.extern C(d_pz)
.extern C(d_aspancount)
.extern C(erroradjustup)
.extern C(errorterm)
.extern C(d_xdenom)
.extern C(r_p0)
.extern C(r_p1)
.extern C(r_p2)
.extern C(a_tstepxfrac)
.extern C(r_sstepx)
.extern C(r_tstepx)
.extern C(a_ststepxwhole)
.extern C(zspantable)
.extern C(skintable)
.extern C(r_zistepx)
.extern C(erroradjustdown)
.extern C(d_countextrastep)
.extern C(ubasestep)
.extern C(a_ststepxwhole)
.extern C(a_tstepxfrac)
.extern C(r_lstepx)
.extern C(a_spans)
.extern C(erroradjustdown)
.extern C(d_pdestextrastep)
.extern C(d_pzextrastep)
.extern C(d_sfracextrastep)
.extern C(d_ptexextrastep)
.extern C(d_countextrastep)
.extern C(d_tfracextrastep)
.extern C(d_lightextrastep)
.extern C(d_ziextrastep)
.extern C(d_pdestbasestep)
.extern C(d_pzbasestep)
.extern C(d_sfracbasestep)
.extern C(d_ptexbasestep)
.extern C(ubasestep)
.extern C(d_tfracbasestep)
.extern C(d_lightbasestep)
.extern C(d_zibasestep)
.extern C(zspantable)
.extern C(r_lstepy)
.extern C(r_sstepy)
.extern C(r_tstepy)
.extern C(r_zistepy)
.extern C(D_PolysetSetEdgeTable)
.extern C(D_RasterizeAliasPolySmooth)
.extern float_point5
.extern Float2ToThe31nd
.extern izistep
.extern izi
.extern FloatMinus2ToThe31nd
.extern float_1
.extern float_particle_z_clip
.extern float_minus_1
.extern float_0
.extern fp_16
.extern fp_64k
.extern fp_1m
.extern fp_1m_minus_1
.extern fp_8
.extern entryvec_table
.extern advancetable
.extern sstep
.extern tstep
.extern pspantemp
.extern counttemp
.extern jumptemp
.extern reciprocal_table
.extern DP_Count
.extern DP_u
.extern DP_v
.extern DP_32768
.extern DP_Color
.extern DP_Pix
.extern DP_EntryTable
.extern pbase
.extern s
.extern t
.extern sfracf
.extern tfracf
.extern snext
.extern tnext
.extern spancountminus1
.extern zi16stepu
.extern sdivz16stepu
.extern tdivz16stepu
.extern zi8stepu
.extern sdivz8stepu
.extern tdivz8stepu
.extern reciprocal_table_16
.extern entryvec_table_16
.extern ceil_cw
.extern single_cw
.extern fp_64kx64k
.extern pz
.extern spr8entryvec_table
#endif
.extern C(snd_scaletable)
.extern C(paintbuffer)
.extern C(snd_linear_count)
.extern C(snd_p)
.extern C(snd_vol)
.extern C(snd_out)
.extern C(vright)
.extern C(vup)
.extern C(vpn)
.extern C(BOPS_Error)
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// plane_t structure
// !!! if this is changed, it must be changed in model.h too !!!
// !!! if the size of this is changed, the array lookup in SV_HullPointContents
// must be changed too !!!
#define pl_normal 0
#define pl_dist 12
#define pl_type 16
#define pl_signbits 17
#define pl_pad 18
#define pl_size 20
// hull_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define hu_clipnodes 0
#define hu_planes 4
#define hu_firstclipnode 8
#define hu_lastclipnode 12
#define hu_clip_mins 16
#define hu_clip_maxs 28
#define hu_size 40
// dnode_t structure
// !!! if this is changed, it must be changed in bspfile.h too !!!
#define nd_planenum 0
#define nd_children 4
#define nd_mins 8
#define nd_maxs 20
#define nd_firstface 32
#define nd_numfaces 36
#define nd_size 40
// sfxcache_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define sfxc_length 0
#define sfxc_loopstart 4
#define sfxc_speed 8
#define sfxc_width 12
#define sfxc_stereo 16
#define sfxc_data 20
// channel_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define ch_sfx 0
#define ch_leftvol 4
#define ch_rightvol 8
#define ch_end 12
#define ch_pos 16
#define ch_looping 20
#define ch_entnum 24
#define ch_entchannel 28
#define ch_origin 32
#define ch_dist_mult 44
#define ch_master_vol 48
#define ch_size 52
// portable_samplepair_t structure
// !!! if this is changed, it much be changed in sound.h too !!!
#define psp_left 0
#define psp_right 4
#define psp_size 8
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// !!! if this is changed, it must be changed in r_local.h too !!!
#define NEAR_CLIP 0.01
// !!! if this is changed, it must be changed in r_local.h too !!!
#define CYCLE 128
// espan_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define espan_t_u 0
#define espan_t_v 4
#define espan_t_count 8
#define espan_t_pnext 12
#define espan_t_size 16
// sspan_t structure
// !!! if this is changed, it must be changed in d_local.h too !!!
#define sspan_t_u 0
#define sspan_t_v 4
#define sspan_t_count 8
#define sspan_t_size 12
// spanpackage_t structure
// !!! if this is changed, it must be changed in d_polyset.c too !!!
#define spanpackage_t_pdest 0
#define spanpackage_t_pz 4
#define spanpackage_t_count 8
#define spanpackage_t_ptex 12
#define spanpackage_t_sfrac 16
#define spanpackage_t_tfrac 20
#define spanpackage_t_light 24
#define spanpackage_t_zi 28
#define spanpackage_t_size 32
// edge_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define et_u 0
#define et_u_step 4
#define et_prev 8
#define et_next 12
#define et_surfs 16
#define et_nextremove 20
#define et_nearzi 24
#define et_owner 28
#define et_size 32
// surf_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define SURF_T_SHIFT 6
#define st_next 0
#define st_prev 4
#define st_spans 8
#define st_key 12
#define st_last_u 16
#define st_spanstate 20
#define st_flags 24
#define st_data 28
#define st_entity 32
#define st_nearzi 36
#define st_insubmodel 40
#define st_d_ziorigin 44
#define st_d_zistepu 48
#define st_d_zistepv 52
#define st_pad 56
#define st_size 64
// clipplane_t structure
// !!! if this is changed, it must be changed in r_local.h too !!!
#define cp_normal 0
#define cp_dist 12
#define cp_next 16
#define cp_leftedge 20
#define cp_rightedge 21
#define cp_reserved 22
#define cp_size 24
// medge_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define me_v 0
#define me_cachededgeoffset 4
#define me_size 8
// mvertex_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mv_position 0
#define mv_size 12
// refdef_t structure
// !!! if this is changed, it must be changed in render.h too !!!
#define rd_vrect 0
#define rd_aliasvrect 20
#define rd_vrectright 40
#define rd_vrectbottom 44
#define rd_aliasvrectright 48
#define rd_aliasvrectbottom 52
#define rd_vrectrightedge 56
#define rd_fvrectx 60
#define rd_fvrecty 64
#define rd_fvrectx_adj 68
#define rd_fvrecty_adj 72
#define rd_vrect_x_adj_shift20 76
#define rd_vrectright_adj_shift20 80
#define rd_fvrectright_adj 84
#define rd_fvrectbottom_adj 88
#define rd_fvrectright 92
#define rd_fvrectbottom 96
#define rd_horizontalFieldOfView 100
#define rd_xOrigin 104
#define rd_yOrigin 108
#define rd_vieworg 112
#define rd_viewangles 124
#define rd_ambientlight 136
#define rd_size 140
// mtriangle_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mtri_facesfront 0
#define mtri_vertindex 4
#define mtri_size 16 // !!! if this changes, array indexing in !!!
// !!! d_polysa.s must be changed to match !!!
#define mtri_shift 4
#endif

BIN
code/unix/quake3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

161
code/unix/quake3.xpm Normal file
View file

@ -0,0 +1,161 @@
/* XPM */
static char *quake3[] = {
/* width height num_colors chars_per_pixel */
" 32 32 122 2",
/* colors */
".. c #6b1008",
".# c #6b1810",
".a c #6b2118",
".b c #6b2921",
".c c #6b3129",
".d c #731810",
".e c #732118",
".f c #732921",
".g c #733129",
".h c #733931",
".i c #733939",
".j c #734239",
".k c #734a4a",
".l c #7b1810",
".m c #7b2118",
".n c #7b2921",
".o c #7b4239",
".p c #7b4a4a",
".q c #7b524a",
".r c #7b5252",
".s c #7b5a5a",
".t c #7b6363",
".u c #7b6b6b",
".v c #7b7373",
".w c #842110",
".x c #842118",
".y c #842921",
".z c #843129",
".A c #843931",
".B c #844239",
".C c #844a42",
".D c #84524a",
".E c #845252",
".F c #845a5a",
".G c #846b63",
".H c #846b6b",
".I c #847373",
".J c #847b7b",
".K c #848484",
".L c #8c2118",
".M c #8c2921",
".N c #8c4239",
".O c #8c4a42",
".P c #8c5a52",
".Q c #8c635a",
".R c #8c6363",
".S c #8c6b6b",
".T c #8c7b7b",
".U c #8c8484",
".V c #8c848c",
".W c #8c8c8c",
".X c #942921",
".Y c #944a42",
".Z c #946363",
".0 c #946b63",
".1 c #947373",
".2 c #947b7b",
".3 c #948484",
".4 c #949494",
".5 c #9c5a5a",
".6 c #9c6363",
".7 c #9c6b63",
".8 c #9c736b",
".9 c #9c7b73",
"#. c #9c7b7b",
"## c #9c8c8c",
"#a c #9c9494",
"#b c #9c949c",
"#c c #9c9c9c",
"#d c #a55a52",
"#e c #a5736b",
"#f c #a57b73",
"#g c #a57b7b",
"#h c #a58484",
"#i c #a58c8c",
"#j c #a59c9c",
"#k c #a5a5a5",
"#l c #ad8c84",
"#m c #ad8c8c",
"#n c #ad9494",
"#o c #ada5a5",
"#p c #adadad",
"#q c #b59c9c",
"#r c #b5a5a5",
"#s c #b5adad",
"#t c #b5b5b5",
"#u c #bda5a5",
"#v c #bdadad",
"#w c #bdb5b5",
"#x c #bdbdbd",
"#y c #c69c9c",
"#z c #c6a59c",
"#A c #c6adad",
"#B c #c6b5ad",
"#C c #c6b5b5",
"#D c #c6bdbd",
"#E c #c6c6c6",
"#F c #ceb5b5",
"#G c #cec6c6",
"#H c #cecece",
"#I c #d6b5b5",
"#J c #d6bdbd",
"#K c #d6c6bd",
"#L c #d6cece",
"#M c #d6d6d6",
"#N c #decec6",
"#O c #decece",
"#P c #ded6ce",
"#Q c #ded6d6",
"#R c #dedede",
"#S c #e7d6d6",
"#T c #e7dede",
"#U c #e7e7e7",
"#V c #efe7e7",
"#W c #efefe7",
"#X c #efefef",
"#Y c #f7efef",
"#Z c #f7f7ef",
"#0 c #f7f7f7",
"#1 c #fff7f7",
"#2 c #fffff7",
"#3 c #ffffff",
/* pixels */
"#3#2#3#0#3#2#3#2#3#0#3#2#3#2#3#0#3#2#3#2#3#0#3#2#3#2#3#0#3#2#3#2",
"#3#2#3#2#3#0#3#2#3#2#3#0#3#2#Z#A#3#2#3#0#3#2#3#2#3#0#3#2#3#2#3#0",
"#3#2#3#0#3#3#2#3#0#3#3#2#3#3#X#l#U#0#3#2#3#3#0#3#2#3#3#2#3#0#3#3",
"#3#2#3#2#3#0#3#3#2#3#2#3#0#3#Y#e#G#0#3#2#3#2#3#3#0#3#2#3#2#3#0#3",
"#3#2#3#0#3#3#2#3#0#3#3#2#3#2#U.6#D#X#3#2#3#3#0#3#2#3#3#0#3#2#3#2",
"#3#2#3#2#3#0#3#2#3#2#3#3#0#3#Q#d#t#X#3#2#3#2#3#0#3#2#3#3#2#3#0#3",
"#3#2#3#0#3#3#2#3#0#3#2#3#3#2#H.Y#t#X#2#3#1#3#3#2#3#2#3#0#3#3#2#3",
"#3#2#3#2#3#0#3#3#2#3#2#3#0#3#G.N#s#X#3#2#3#2#3#3#0#3#2#3#2#3#3#0",
"#3#2#3#0#3#3#2#3#0#3#3#2#3#2#A.A#o#W#3#0#3#3#2#3#2#3#3#0#3#2#3#2",
"#3#Z#O#s#R#2#3#2#3#2#3#3#0#3#r.z#k#U#2#3#0#3#2#3#2#T#F#L#X#2#3#0",
"#O.2#B#V#X#X#3#2#3#3#0#3#2#3#n.m#a#U#2#3#3#0#3#2#3#3#X#C#.#u#2#3",
".D#Q#M#H#M#Z#3#3#0#3#2#3#2#3#h.x.W#R#3#2#3#2#3#3#0#3#Z#R#D.C#M#0",
".7.D#n#R#1#3#2#3#2#3#0#3#3#1#f.x.W#R#2#3#1#3#2#3#2#0#X#F.5.o#s#U",
"#V.R.b.f.C.7#i#y#F#K#N#O#P#X.8.w.K#D#O#N#J#I#z#h.7.C.f.f.P#v#k#R",
"#3#R#a.s.h.a.#...d.d.m.y.n#A.Z.x.I.D.y.m.e.#...#.a.i.t###a#c#x#Y",
"#3#1#W#E#k.T.H.k.j.j.h.y.m.1.C.L.v.o.l.a.b.h.k.u.v.J.W#c#t#M#0#3",
"#3#2#3#0#Z#R#E#t#b#a.W.H.y.t.p.X.J.o.g.v.J.V.W.4#o#x#M#V#0#3#2#3",
"#3#2#3#2#3#3#1#0#X#U#R#r.n.I.q.M.J.p.g.U#t#M#R#V#0#0#2#3#2#3#2#3",
"#3#2#3#0#3#2#3#2#3#2#3#N.z.J.E.x.K.D.h.4#T#3#2#3#2#3#2#3#0#3#3#2",
"#3#2#3#2#3#3#0#3#2#3#2#O.A.K.Q.m.K.F.o#a#U#3#2#3#0#3#3#2#3#2#3#0",
"#3#2#3#0#3#2#3#3#2#3#0#S.B.U.T.d.4.0.p#c#X#3#2#3#2#3#0#3#3#2#3#2",
"#3#2#3#2#3#3#0#3#2#3#3#S.O.4.3.e.4#g.r#p#X#3#2#3#0#3#3#2#3#0#3#3",
"#3#2#3#0#3#2#3#2#3#0#3#T.C#a.4.b.4#h.G#s#Z#3#3#2#3#0#3#2#3#2#3#2",
"#3#2#3#2#3#3#0#3#2#3#2#U.F#j#o.c.4#m.T#w#0#3#0#3#2#3#3#2#3#0#3#3",
"#3#2#3#0#3#2#3#3#2#3#0#Y.S#o#t.j#j#q###x#0#3#2#3#3#0#3#2#3#3#2#3",
"#3#2#3#2#3#3#0#3#2#3#3#0.9#w#G.p#k#r#o#E#0#3#2#3#2#3#0#3#2#3#2#3",
"#3#2#3#0#3#2#3#2#3#0#3#2#n#E#Q.Q#p#w#x#G#0#3#2#3#3#2#3#0#3#3#2#3",
"#3#2#3#2#3#3#0#3#2#3#3#2#R#H#T.3#t#R#T#R#2#3#2#3#0#3#3#2#3#2#3#0",
"#3#2#3#0#3#2#3#3#2#3#0#3#2#U#U#s#D#0#0#W#3#3#0#3#2#3#2#3#3#0#3#2",
"#3#2#3#2#3#3#0#3#2#3#3#2#3#2#3#X#E#0#3#2#3#0#3#3#2#3#0#3#2#3#3#0",
"#3#2#3#0#3#2#3#2#3#0#3#2#3#3#0#3#W#2#3#0#3#3#2#3#0#3#3#2#3#0#3#2",
"#3#2#3#2#3#3#0#3#2#3#3#2#3#0#3#2#3#3#0#3#2#3#2#3#2#3#0#3#3#2#3#2"
};

12
code/unix/run-target.sh Normal file
View file

@ -0,0 +1,12 @@
#!/bin/sh
# for easy use with Anjuta
cd `dirname $0`/debugi386-glibc
echo "in $PWD"
# now execute whatever you want
#./linuxquake3-smp +set fs_basepath /usr/local/games/quake3 +set developer 1 +set r_smp 1 +set r_showsmp 1 +devmap mythology
#gvd ./linuxquake3-smp --pargs +set logfile 2 +set fs_basepath /usr/local/games/quake3 +set developer 1 +set r_smp 0 +set r_showsmp 1 +devmap mythology
./linuxquake3-smp +set logfile 2 +set fs_basepath /usr/local/games/quake3 +set developer 1 +set r_smp 1 +set r_fullscreen 0 +set r_showsmp 1 +devmap mythology &
gvd ./linuxquake3-smp

95
code/unix/snapvector.nasm Normal file
View file

@ -0,0 +1,95 @@
;===========================================================================
;Copyright (C) 1999-2005 Id Software, Inc.
;
;This file is part of Quake III Arena source code.
;
;Quake III Arena source code 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.
;
;Quake III Arena source code 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 Foobar; if not, write to the Free Software
;Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
;===========================================================================
;
; Sys_SnapVector NASM code (Andrew Henderson)
; See win32/win_shared.c for the Win32 equivalent
; This code is provided to ensure that the
; rounding behavior (and, if necessary, the
; precision) of DLL and QVM code are identical
; e.g. for network-visible operations.
; See ftol.nasm for operations on a single float,
; as used in compiled VM and DLL code that does
; not use this system trap.
;
segment .data
fpucw dd 0
cw037F dd 0x037F ; Rounding to nearest (even).
segment .text
; void Sys_SnapVector( float *v )
global Sys_SnapVector
Sys_SnapVector:
push eax
push ebp
mov ebp, esp
fnstcw [fpucw]
mov eax, dword [ebp + 12]
fldcw [cw037F]
fld dword [eax]
fistp dword [eax]
fild dword [eax]
fstp dword [eax]
fld dword [eax + 4]
fistp dword [eax + 4]
fild dword [eax + 4]
fstp dword [eax + 4]
fld dword [eax + 8]
fistp dword [eax + 8]
fild dword [eax + 8]
fstp dword [eax + 8]
fldcw [fpucw]
pop ebp
pop eax
ret
; void Sys_SnapVectorCW( float *v, unsigned short int cw )
global Sys_SnapVectorCW
Sys_SnapVector_cw:
push eax
push ebp
mov ebp, esp
fnstcw [fpucw]
mov eax, dword [ebp + 12]
fldcw [ebp + 16]
fld dword [eax]
fistp dword [eax]
fild dword [eax]
fstp dword [eax]
fld dword [eax + 4]
fistp dword [eax + 4]
fild dword [eax + 4]
fstp dword [eax + 4]
fld dword [eax + 8]
fistp dword [eax + 8]
fild dword [eax + 8]
fstp dword [eax + 8]
fldcw [fpucw]
pop ebp
pop eax
ret

217
code/unix/snd_mixa.s Normal file
View file

@ -0,0 +1,217 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// snd_mixa.s
// x86 assembly-language sound code
//
#include "qasm.h"
#if id386
.text
#if 0
//----------------------------------------------------------------------
// 8-bit sound-mixing code
//----------------------------------------------------------------------
#define ch 4+16
#define sc 8+16
#define count 12+16
.globl C(S_PaintChannelFrom8)
C(S_PaintChannelFrom8):
pushl %esi // preserve register variables
pushl %edi
pushl %ebx
pushl %ebp
// int data;
// short *lscale, *rscale;
// unsigned char *sfx;
// int i;
movl ch(%esp),%ebx
movl sc(%esp),%esi
// if (ch->leftvol > 255)
// ch->leftvol = 255;
// if (ch->rightvol > 255)
// ch->rightvol = 255;
movl ch_leftvol(%ebx),%eax
movl ch_rightvol(%ebx),%edx
cmpl $255,%eax
jna LLeftSet
movl $255,%eax
LLeftSet:
cmpl $255,%edx
jna LRightSet
movl $255,%edx
LRightSet:
// lscale = snd_scaletable[ch->leftvol >> 3];
// rscale = snd_scaletable[ch->rightvol >> 3];
// sfx = (signed char *)sc->data + ch->pos;
// ch->pos += count;
andl $0xF8,%eax
addl $20,%esi
movl (%esi),%esi
andl $0xF8,%edx
movl ch_pos(%ebx),%edi
movl count(%esp),%ecx
addl %edi,%esi
shll $7,%eax
addl %ecx,%edi
shll $7,%edx
movl %edi,ch_pos(%ebx)
addl $(C(snd_scaletable)),%eax
addl $(C(snd_scaletable)),%edx
subl %ebx,%ebx
movb -1(%esi,%ecx,1),%bl
testl $1,%ecx
jz LMix8Loop
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movb -2(%esi,%ecx,1),%bl
decl %ecx
jz LDone
// for (i=0 ; i<count ; i++)
// {
LMix8Loop:
// data = sfx[i];
// paintbuffer[i].left += lscale[data];
// paintbuffer[i].right += rscale[data];
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
addl C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
movb -2(%esi,%ecx,1),%bl
movl %edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
movl (%eax,%ebx,4),%edi
movl (%edx,%ebx,4),%ebp
movb -3(%esi,%ecx,1),%bl
addl C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
addl C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
movl %edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
movl %ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
// }
subl $2,%ecx
jnz LMix8Loop
LDone:
popl %ebp
popl %ebx
popl %edi
popl %esi
ret
#endif
//----------------------------------------------------------------------
// Transfer of stereo buffer to 16-bit DMA buffer code
//----------------------------------------------------------------------
.globl C(S_WriteLinearBlastStereo16)
C(S_WriteLinearBlastStereo16):
pushl %edi
pushl %ebx
// int i;
// int val;
movl C(snd_linear_count),%ecx
movl C(snd_p),%ebx
movl C(snd_out),%edi
// for (i=0 ; i<snd_linear_count ; i+=2)
// {
LWLBLoopTop:
// val = (snd_p[i]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i] = (short)0x8000;
// else
// snd_out[i] = val;
movl -8(%ebx,%ecx,4),%eax
sarl $8,%eax
cmpl $0x7FFF,%eax
jg LClampHigh
cmpl $0xFFFF8000,%eax
jnl LClampDone
movl $0xFFFF8000,%eax
jmp LClampDone
LClampHigh:
movl $0x7FFF,%eax
LClampDone:
// val = (snd_p[i+1]*snd_vol)>>8;
// if (val > 0x7fff)
// snd_out[i+1] = 0x7fff;
// else if (val < (short)0x8000)
// snd_out[i+1] = (short)0x8000;
// else
// snd_out[i+1] = val;
movl -4(%ebx,%ecx,4),%edx
sarl $8,%edx
cmpl $0x7FFF,%edx
jg LClampHigh2
cmpl $0xFFFF8000,%edx
jnl LClampDone2
movl $0xFFFF8000,%edx
jmp LClampDone2
LClampHigh2:
movl $0x7FFF,%edx
LClampDone2:
shll $16,%edx
andl $0xFFFF,%eax
orl %eax,%edx
movl %edx,-4(%edi,%ecx,2)
// }
subl $2,%ecx
jnz LWLBLoopTop
// snd_p += snd_linear_count;
popl %ebx
popl %edi
ret
#endif // id386

115
code/unix/sys_dosa.s Normal file
View file

@ -0,0 +1,115 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// sys_dosa.s
// x86 assembly-language DOS-dependent routines.
#include "qasm.h"
.data
.align 4
fpenv:
.long 0, 0, 0, 0, 0, 0, 0, 0
.text
.globl C(MaskExceptions)
C(MaskExceptions):
fnstenv fpenv
orl $0x3F,fpenv
fldenv fpenv
ret
#if 0
.globl C(unmaskexceptions)
C(unmaskexceptions):
fnstenv fpenv
andl $0xFFFFFFE0,fpenv
fldenv fpenv
ret
#endif
.data
.align 4
.globl ceil_cw, single_cw, full_cw, cw, pushed_cw
ceil_cw: .long 0
single_cw: .long 0
full_cw: .long 0
cw: .long 0
pushed_cw: .long 0
.text
.globl C(Sys_LowFPPrecision)
C(Sys_LowFPPrecision):
fldcw single_cw
ret
.globl C(Sys_HighFPPrecision)
C(Sys_HighFPPrecision):
fldcw full_cw
ret
.globl C(Sys_PushFPCW_SetHigh)
C(Sys_PushFPCW_SetHigh):
fnstcw pushed_cw
fldcw full_cw
ret
.globl C(Sys_PopFPCW)
C(Sys_PopFPCW):
fldcw pushed_cw
ret
.globl C(Sys_SetFPCW)
C(Sys_SetFPCW):
fnstcw cw
movl cw,%eax
#if id386
andb $0xF0,%ah
orb $0x03,%ah // round mode, 64-bit precision
#endif
movl %eax,full_cw
#if id386
andb $0xF0,%ah
orb $0x0C,%ah // chop mode, single precision
#endif
movl %eax,single_cw
#if id386
andb $0xF0,%ah
orb $0x08,%ah // ceil mode, single precision
#endif
movl %eax,ceil_cw
ret

38
code/unix/unix_glw.h Normal file
View file

@ -0,0 +1,38 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if !( defined __linux__ || defined __FreeBSD__ )
#error You should include this file only on Linux/FreeBSD platforms
#endif
#ifndef __GLW_LINUX_H__
#define __GLW_LINUX_H__
typedef struct
{
void *OpenGLLib; // instance of OpenGL library
FILE *log_fp;
} glwstate_t;
extern glwstate_t glw_state;
#endif

1273
code/unix/unix_main.c Normal file

File diff suppressed because it is too large Load diff

616
code/unix/unix_net.c Normal file
View file

@ -0,0 +1,616 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// unix_net.c
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h> // bk001204
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <errno.h>
#ifdef MACOS_X
#import <sys/sockio.h>
#import <net/if.h>
#import <net/if_types.h>
#import <arpa/inet.h> // for inet_ntoa()
#import <net/if_dl.h> // for 'struct sockaddr_dl'
#endif
static cvar_t *noudp;
netadr_t net_local_adr;
int ip_socket;
int ipx_socket;
#define MAX_IPS 16
static int numIP;
static byte localIP[MAX_IPS][4];
int NET_Socket (char *net_interface, int port);
char *NET_ErrorString (void);
//=============================================================================
void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
{
memset (s, 0, sizeof(*s));
if (a->type == NA_BROADCAST)
{
s->sin_family = AF_INET;
s->sin_port = a->port;
*(int *)&s->sin_addr = -1;
}
else if (a->type == NA_IP)
{
s->sin_family = AF_INET;
*(int *)&s->sin_addr = *(int *)&a->ip;
s->sin_port = a->port;
}
}
void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
{
*(int *)&a->ip = *(int *)&s->sin_addr;
a->port = s->sin_port;
a->type = NA_IP;
}
char *NET_BaseAdrToString (netadr_t a)
{
static char s[64];
Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
return s;
}
/*
=============
Sys_StringToAdr
idnewt
192.246.40.70
=============
*/
qboolean Sys_StringToSockaddr (const char *s, struct sockaddr *sadr)
{
struct hostent *h;
//char *colon; // bk001204 - unused
memset (sadr, 0, sizeof(*sadr));
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
((struct sockaddr_in *)sadr)->sin_port = 0;
if ( s[0] >= '0' && s[0] <= '9')
{
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s);
}
else
{
if (! (h = gethostbyname(s)) )
return qfalse;
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
}
return qtrue;
}
/*
=============
Sys_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
qboolean Sys_StringToAdr (const char *s, netadr_t *a)
{
struct sockaddr_in sadr;
if (!Sys_StringToSockaddr (s, (struct sockaddr *)&sadr))
return qfalse;
SockadrToNetadr (&sadr, a);
return qtrue;
}
//=============================================================================
qboolean Sys_GetPacket (netadr_t *net_from, msg_t *net_message)
{
int ret;
struct sockaddr_in from;
int fromlen;
int net_socket;
int protocol;
int err;
for (protocol = 0 ; protocol < 2 ; protocol++)
{
if (protocol == 0)
net_socket = ip_socket;
else
net_socket = ipx_socket;
if (!net_socket)
continue;
fromlen = sizeof(from);
ret = recvfrom (net_socket, net_message->data, net_message->maxsize
, 0, (struct sockaddr *)&from, &fromlen);
SockadrToNetadr (&from, net_from);
// bk000305: was missing
net_message->readcount = 0;
if (ret == -1)
{
err = errno;
if (err == EWOULDBLOCK || err == ECONNREFUSED)
continue;
Com_Printf ("NET_GetPacket: %s from %s\n", NET_ErrorString(),
NET_AdrToString(*net_from));
continue;
}
if (ret == net_message->maxsize)
{
Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
continue;
}
net_message->cursize = ret;
return qtrue;
}
return qfalse;
}
//=============================================================================
void Sys_SendPacket( int length, const void *data, netadr_t to )
{
int ret;
struct sockaddr_in addr;
int net_socket;
if (to.type == NA_BROADCAST)
{
net_socket = ip_socket;
}
else if (to.type == NA_IP)
{
net_socket = ip_socket;
}
else if (to.type == NA_IPX)
{
net_socket = ipx_socket;
}
else if (to.type == NA_BROADCAST_IPX)
{
net_socket = ipx_socket;
}
else {
Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
return;
}
if (!net_socket)
return;
NetadrToSockadr (&to, &addr);
ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
if (ret == -1)
{
Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(),
NET_AdrToString (to));
}
}
//=============================================================================
/*
==================
Sys_IsLANAddress
LAN clients will have their rate var ignored
==================
*/
qboolean Sys_IsLANAddress (netadr_t adr) {
int i;
if( adr.type == NA_LOOPBACK ) {
return qtrue;
}
if( adr.type == NA_IPX ) {
return qtrue;
}
if( adr.type != NA_IP ) {
return qfalse;
}
// choose which comparison to use based on the class of the address being tested
// any local adresses of a different class than the address being tested will fail based on the first byte
// Class A
if( (adr.ip[0] & 0x80) == 0x00 ) {
for ( i = 0 ; i < numIP ; i++ ) {
if( adr.ip[0] == localIP[i][0] ) {
return qtrue;
}
}
// the RFC1918 class a block will pass the above test
return qfalse;
}
// Class B
if( (adr.ip[0] & 0xc0) == 0x80 ) {
for ( i = 0 ; i < numIP ; i++ ) {
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) {
return qtrue;
}
// also check against the RFC1918 class b blocks
if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) {
return qtrue;
}
}
return qfalse;
}
// Class C
for ( i = 0 ; i < numIP ; i++ ) {
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) {
return qtrue;
}
// also check against the RFC1918 class c blocks
if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 ) {
return qtrue;
}
}
return qfalse;
}
/*
==================
Sys_ShowIP
==================
*/
void Sys_ShowIP(void) {
int i;
for (i = 0; i < numIP; i++) {
Com_Printf( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] );
}
}
/*
=====================
NET_GetLocalAddress
=====================
*/
#ifdef MACOS_X
// Don't do a forward mapping from the hostname of the machine to the IP. The reason is that we might have obtained an IP address from DHCP and there might not be any name registered for the machine. On Mac OS X, the machine name defaults to 'localhost' and NetInfo has 127.0.0.1 listed for this name. Instead, we want to get a list of all the IP network interfaces on the machine.
// This code adapted from OmniNetworking.
#define IFR_NEXT(ifr) \
((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \
MAX(0, (int) (ifr)->ifr_addr.sa_len - (int) sizeof((ifr)->ifr_addr))))
void NET_GetLocalAddress( void ) {
struct ifreq requestBuffer[MAX_IPS], *linkInterface, *inetInterface;
struct ifconf ifc;
struct ifreq ifr;
struct sockaddr_dl *sdl;
int interfaceSocket;
int family;
//Com_Printf("NET_GetLocalAddress: Querying for network interfaces\n");
// Set this early so we can just return if there is an error
numIP = 0;
ifc.ifc_len = sizeof(requestBuffer);
ifc.ifc_buf = (caddr_t)requestBuffer;
// Since we get at this info via an ioctl, we need a temporary little socket. This will only get AF_INET interfaces, but we probably don't care about anything else. If we do end up caring later, we should add a ONAddressFamily and at a -interfaces method to it.
family = AF_INET;
if ((interfaceSocket = socket(family, SOCK_DGRAM, 0)) < 0) {
Com_Printf("NET_GetLocalAddress: Unable to create temporary socket, errno = %d\n", errno);
return;
}
if (ioctl(interfaceSocket, SIOCGIFCONF, &ifc) != 0) {
Com_Printf("NET_GetLocalAddress: Unable to get list of network interfaces, errno = %d\n", errno);
return;
}
linkInterface = (struct ifreq *) ifc.ifc_buf;
while ((char *) linkInterface < &ifc.ifc_buf[ifc.ifc_len]) {
unsigned int nameLength;
// The ioctl returns both the entries having the address (AF_INET) and the link layer entries (AF_LINK). The AF_LINK entry has the link layer address which contains the interface type. This is the only way I can see to get this information. We cannot assume that we will get bot an AF_LINK and AF_INET entry since the interface may not be configured. For example, if you have a 10Mb port on the motherboard and a 100Mb card, you may not configure the motherboard port.
// For each AF_LINK entry...
if (linkInterface->ifr_addr.sa_family == AF_LINK) {
// if there is a matching AF_INET entry
inetInterface = (struct ifreq *) ifc.ifc_buf;
while ((char *) inetInterface < &ifc.ifc_buf[ifc.ifc_len]) {
if (inetInterface->ifr_addr.sa_family == AF_INET &&
!strncmp(inetInterface->ifr_name, linkInterface->ifr_name, sizeof(linkInterface->ifr_name))) {
for (nameLength = 0; nameLength < IFNAMSIZ; nameLength++)
if (!linkInterface->ifr_name[nameLength])
break;
sdl = (struct sockaddr_dl *)&linkInterface->ifr_addr;
// Skip loopback interfaces
if (sdl->sdl_type != IFT_LOOP) {
// Get the local interface address
strncpy(ifr.ifr_name, inetInterface->ifr_name, sizeof(ifr.ifr_name));
if (ioctl(interfaceSocket, OSIOCGIFADDR, (caddr_t)&ifr) < 0) {
Com_Printf("NET_GetLocalAddress: Unable to get local address for interface '%s', errno = %d\n", inetInterface->ifr_name, errno);
} else {
struct sockaddr_in *sin;
int ip;
sin = (struct sockaddr_in *)&ifr.ifr_addr;
ip = ntohl(sin->sin_addr.s_addr);
localIP[ numIP ][0] = (ip >> 24) & 0xff;
localIP[ numIP ][1] = (ip >> 16) & 0xff;
localIP[ numIP ][2] = (ip >> 8) & 0xff;
localIP[ numIP ][3] = (ip >> 0) & 0xff;
Com_Printf( "IP: %i.%i.%i.%i (%s)\n", localIP[ numIP ][0], localIP[ numIP ][1], localIP[ numIP ][2], localIP[ numIP ][3], inetInterface->ifr_name);
numIP++;
}
}
// We will assume that there is only one AF_INET entry per AF_LINK entry.
// What happens when we have an interface that has multiple IP addresses, or
// can that even happen?
// break;
}
inetInterface = IFR_NEXT(inetInterface);
}
}
linkInterface = IFR_NEXT(linkInterface);
}
close(interfaceSocket);
}
#else
void NET_GetLocalAddress( void ) {
char hostname[256];
struct hostent *hostInfo;
// int error; // bk001204 - unused
char *p;
int ip;
int n;
if ( gethostname( hostname, 256 ) == -1 ) {
return;
}
hostInfo = gethostbyname( hostname );
if ( !hostInfo ) {
return;
}
Com_Printf( "Hostname: %s\n", hostInfo->h_name );
n = 0;
while( ( p = hostInfo->h_aliases[n++] ) != NULL ) {
Com_Printf( "Alias: %s\n", p );
}
if ( hostInfo->h_addrtype != AF_INET ) {
return;
}
numIP = 0;
while( ( p = hostInfo->h_addr_list[numIP++] ) != NULL && numIP < MAX_IPS ) {
ip = ntohl( *(int *)p );
localIP[ numIP ][0] = p[0];
localIP[ numIP ][1] = p[1];
localIP[ numIP ][2] = p[2];
localIP[ numIP ][3] = p[3];
Com_Printf( "IP: %i.%i.%i.%i\n", ( ip >> 24 ) & 0xff, ( ip >> 16 ) & 0xff, ( ip >> 8 ) & 0xff, ip & 0xff );
}
}
#endif
/*
====================
NET_OpenIP
====================
*/
// bk001204 - prototype needed
int NET_IPSocket (char *net_interface, int port);
void NET_OpenIP (void)
{
cvar_t *ip;
int port;
int i;
ip = Cvar_Get ("net_ip", "localhost", 0);
port = Cvar_Get("net_port", va("%i", PORT_SERVER), 0)->value;
for ( i = 0 ; i < 10 ; i++ ) {
ip_socket = NET_IPSocket (ip->string, port + i);
if ( ip_socket ) {
Cvar_SetValue( "net_port", port + i );
NET_GetLocalAddress();
return;
}
}
Com_Error (ERR_FATAL, "Couldn't allocate IP port");
}
/*
====================
NET_Init
====================
*/
void NET_Init (void)
{
noudp = Cvar_Get ("net_noudp", "0", 0);
// open sockets
if (! noudp->value) {
NET_OpenIP ();
}
}
/*
====================
NET_IPSocket
====================
*/
int NET_IPSocket (char *net_interface, int port)
{
int newsocket;
struct sockaddr_in address;
qboolean _qtrue = qtrue;
int i = 1;
if ( net_interface ) {
Com_Printf("Opening IP socket: %s:%i\n", net_interface, port );
} else {
Com_Printf("Opening IP socket: localhost:%i\n", port );
}
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
Com_Printf ("ERROR: UDP_OpenSocket: socket: %s", NET_ErrorString());
return 0;
}
// make it non-blocking
if (ioctl (newsocket, FIONBIO, &_qtrue) == -1)
{
Com_Printf ("ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString());
return 0;
}
// make it broadcast capable
if (setsockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
{
Com_Printf ("ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString());
return 0;
}
if (!net_interface || !net_interface[0] || !Q_stricmp(net_interface, "localhost"))
address.sin_addr.s_addr = INADDR_ANY;
else
Sys_StringToSockaddr (net_interface, (struct sockaddr *)&address);
if (port == PORT_ANY)
address.sin_port = 0;
else
address.sin_port = htons((short)port);
address.sin_family = AF_INET;
if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
{
Com_Printf ("ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
close (newsocket);
return 0;
}
return newsocket;
}
/*
====================
NET_Shutdown
====================
*/
void NET_Shutdown (void)
{
if (ip_socket) {
close(ip_socket);
ip_socket = 0;
}
}
/*
====================
NET_ErrorString
====================
*/
char *NET_ErrorString (void)
{
int code;
code = errno;
return strerror (code);
}
// sleeps msec or until net socket is ready
void NET_Sleep(int msec)
{
struct timeval timeout;
fd_set fdset;
extern qboolean stdin_active;
if (!ip_socket || !com_dedicated->integer)
return; // we're not a server, just run full speed
FD_ZERO(&fdset);
if (stdin_active)
FD_SET(0, &fdset); // stdin is processed too
FD_SET(ip_socket, &fdset); // network socket
timeout.tv_sec = msec/1000;
timeout.tv_usec = (msec%1000)*1000;
select(ip_socket+1, &fdset, NULL, NULL, &timeout);
}

435
code/unix/unix_shared.c Normal file
View file

@ -0,0 +1,435 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <pwd.h>
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
//=============================================================================
// Used to determine CD Path
static char cdPath[MAX_OSPATH];
// Used to determine local installation path
static char installPath[MAX_OSPATH];
// Used to determine where to store user-specific files
static char homePath[MAX_OSPATH];
/*
================
Sys_Milliseconds
================
*/
/* base time in seconds, that's our origin
timeval:tv_sec is an int:
assuming this wraps every 0x7fffffff - ~68 years since the Epoch (1970) - we're safe till 2038
using unsigned long data type to work right with Sys_XTimeToSysTime */
unsigned long sys_timeBase = 0;
/* current time in ms, using sys_timeBase as origin
NOTE: sys_timeBase*1000 + curtime -> ms since the Epoch
0x7fffffff ms - ~24 days
although timeval:tv_usec is an int, I'm not sure wether it is actually used as an unsigned int
(which would affect the wrap period) */
int curtime;
int Sys_Milliseconds (void)
{
struct timeval tp;
gettimeofday(&tp, NULL);
if (!sys_timeBase)
{
sys_timeBase = tp.tv_sec;
return tp.tv_usec/1000;
}
curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
return curtime;
}
#if defined(__linux__) && !defined(DEDICATED)
/*
================
Sys_XTimeToSysTime
sub-frame timing of events returned by X
X uses the Time typedef - unsigned long
disable with in_subframe 0
sys_timeBase*1000 is the number of ms since the Epoch of our origin
xtime is in ms and uses the Epoch as origin
Time data type is an unsigned long: 0xffffffff ms - ~49 days period
I didn't find much info in the XWindow documentation about the wrapping
we clamp sys_timeBase*1000 to unsigned long, that gives us the current origin for xtime
the computation will still work if xtime wraps (at ~49 days period since the Epoch) after we set sys_timeBase
================
*/
extern cvar_t *in_subframe;
int Sys_XTimeToSysTime (unsigned long xtime)
{
int ret, time, test;
if (!in_subframe->value)
{
// if you don't want to do any event times corrections
return Sys_Milliseconds();
}
// test the wrap issue
#if 0
// reference values for test: sys_timeBase 0x3dc7b5e9 xtime 0x541ea451 (read these from a test run)
// xtime will wrap in 0xabe15bae ms >~ 0x2c0056 s (33 days from Nov 5 2002 -> 8 Dec)
// NOTE: date -d '1970-01-01 UTC 1039384002 seconds' +%c
// use sys_timeBase 0x3dc7b5e9+0x2c0056 = 0x3df3b63f
// after around 5s, xtime would have wrapped around
// we get 7132, the formula handles the wrap safely
unsigned long xtime_aux,base_aux;
int test;
// Com_Printf("sys_timeBase: %p\n", sys_timeBase);
// Com_Printf("xtime: %p\n", xtime);
xtime_aux = 500; // 500 ms after wrap
base_aux = 0x3df3b63f; // the base a few seconds before wrap
test = xtime_aux - (unsigned long)(base_aux*1000);
Com_Printf("xtime wrap test: %d\n", test);
#endif
// some X servers (like suse 8.1's) report weird event times
// if the game is loading, resolving DNS, etc. we are also getting old events
// so we only deal with subframe corrections that look 'normal'
ret = xtime - (unsigned long)(sys_timeBase*1000);
time = Sys_Milliseconds();
test = time - ret;
//printf("delta: %d\n", test);
if (test < 0 || test > 30) // in normal conditions I've never seen this go above
{
return time;
}
return ret;
}
#endif
//#if 0 // bk001215 - see snapvector.nasm for replacement
#if (defined __APPLE__) // rcg010206 - using this for PPC builds...
long fastftol( float f ) { // bk001213 - from win32/win_shared.c
//static int tmp;
// __asm fld f
//__asm fistp tmp
//__asm mov eax, tmp
return (long)f;
}
void Sys_SnapVector( float *v ) { // bk001213 - see win32/win_shared.c
// bk001213 - old linux
v[0] = rint(v[0]);
v[1] = rint(v[1]);
v[2] = rint(v[2]);
}
#endif
void Sys_Mkdir( const char *path )
{
mkdir (path, 0777);
}
char *strlwr (char *s) {
if ( s==NULL ) { // bk001204 - paranoia
assert(0);
return s;
}
while (*s) {
*s = tolower(*s);
s++;
}
return s; // bk001204 - duh
}
//============================================
#define MAX_FOUND_FILES 0x1000
// bk001129 - new in 1.26
void Sys_ListFilteredFiles( const char *basedir, char *subdirs, char *filter, char **list, int *numfiles ) {
char search[MAX_OSPATH], newsubdirs[MAX_OSPATH];
char filename[MAX_OSPATH];
DIR *fdir;
struct dirent *d;
struct stat st;
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
return;
}
if (strlen(subdirs)) {
Com_sprintf( search, sizeof(search), "%s/%s", basedir, subdirs );
}
else {
Com_sprintf( search, sizeof(search), "%s", basedir );
}
if ((fdir = opendir(search)) == NULL) {
return;
}
while ((d = readdir(fdir)) != NULL) {
Com_sprintf(filename, sizeof(filename), "%s/%s", search, d->d_name);
if (stat(filename, &st) == -1)
continue;
if (st.st_mode & S_IFDIR) {
if (Q_stricmp(d->d_name, ".") && Q_stricmp(d->d_name, "..")) {
if (strlen(subdirs)) {
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s/%s", subdirs, d->d_name);
}
else {
Com_sprintf( newsubdirs, sizeof(newsubdirs), "%s", d->d_name);
}
Sys_ListFilteredFiles( basedir, newsubdirs, filter, list, numfiles );
}
}
if ( *numfiles >= MAX_FOUND_FILES - 1 ) {
break;
}
Com_sprintf( filename, sizeof(filename), "%s/%s", subdirs, d->d_name );
if (!Com_FilterPath( filter, filename, qfalse ))
continue;
list[ *numfiles ] = CopyString( filename );
(*numfiles)++;
}
closedir(fdir);
}
// bk001129 - in 1.17 this used to be
// char **Sys_ListFiles( const char *directory, const char *extension, int *numfiles, qboolean wantsubs )
char **Sys_ListFiles( const char *directory, const char *extension, char *filter, int *numfiles, qboolean wantsubs )
{
struct dirent *d;
// char *p; // bk001204 - unused
DIR *fdir;
qboolean dironly = wantsubs;
char search[MAX_OSPATH];
int nfiles;
char **listCopy;
char *list[MAX_FOUND_FILES];
//int flag; // bk001204 - unused
int i;
struct stat st;
int extLen;
if (filter) {
nfiles = 0;
Sys_ListFilteredFiles( directory, "", filter, list, &nfiles );
list[ nfiles ] = 0;
*numfiles = nfiles;
if (!nfiles)
return NULL;
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
for ( i = 0 ; i < nfiles ; i++ ) {
listCopy[i] = list[i];
}
listCopy[i] = NULL;
return listCopy;
}
if ( !extension)
extension = "";
if ( extension[0] == '/' && extension[1] == 0 ) {
extension = "";
dironly = qtrue;
}
extLen = strlen( extension );
// search
nfiles = 0;
if ((fdir = opendir(directory)) == NULL) {
*numfiles = 0;
return NULL;
}
while ((d = readdir(fdir)) != NULL) {
Com_sprintf(search, sizeof(search), "%s/%s", directory, d->d_name);
if (stat(search, &st) == -1)
continue;
if ((dironly && !(st.st_mode & S_IFDIR)) ||
(!dironly && (st.st_mode & S_IFDIR)))
continue;
if (*extension) {
if ( strlen( d->d_name ) < strlen( extension ) ||
Q_stricmp(
d->d_name + strlen( d->d_name ) - strlen( extension ),
extension ) ) {
continue; // didn't match
}
}
if ( nfiles == MAX_FOUND_FILES - 1 )
break;
list[ nfiles ] = CopyString( d->d_name );
nfiles++;
}
list[ nfiles ] = 0;
closedir(fdir);
// return a copy of the list
*numfiles = nfiles;
if ( !nfiles ) {
return NULL;
}
listCopy = Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ) );
for ( i = 0 ; i < nfiles ; i++ ) {
listCopy[i] = list[i];
}
listCopy[i] = NULL;
return listCopy;
}
void Sys_FreeFileList( char **list ) {
int i;
if ( !list ) {
return;
}
for ( i = 0 ; list[i] ; i++ ) {
Z_Free( list[i] );
}
Z_Free( list );
}
char *Sys_Cwd( void )
{
static char cwd[MAX_OSPATH];
getcwd( cwd, sizeof( cwd ) - 1 );
cwd[MAX_OSPATH-1] = 0;
return cwd;
}
void Sys_SetDefaultCDPath(const char *path)
{
Q_strncpyz(cdPath, path, sizeof(cdPath));
}
char *Sys_DefaultCDPath(void)
{
return cdPath;
}
void Sys_SetDefaultInstallPath(const char *path)
{
Q_strncpyz(installPath, path, sizeof(installPath));
}
char *Sys_DefaultInstallPath(void)
{
if (*installPath)
return installPath;
else
return Sys_Cwd();
}
void Sys_SetDefaultHomePath(const char *path)
{
Q_strncpyz(homePath, path, sizeof(homePath));
}
char *Sys_DefaultHomePath(void)
{
char *p;
if (*homePath)
return homePath;
if ((p = getenv("HOME")) != NULL) {
Q_strncpyz(homePath, p, sizeof(homePath));
#ifdef MACOS_X
Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/Quake3");
#else
Q_strcat(homePath, sizeof(homePath), "/.q3a");
#endif
if (mkdir(homePath, 0777)) {
if (errno != EEXIST)
Sys_Error("Unable to create directory \"%s\", error is %s(%d)\n", homePath, strerror(errno), errno);
}
return homePath;
}
return ""; // assume current dir
}
//============================================
int Sys_GetProcessorId( void )
{
return CPUID_GENERIC;
}
void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
{
}
char *Sys_GetCurrentUser( void )
{
struct passwd *p;
if ( (p = getpwuid( getuid() )) == NULL ) {
return "player";
}
return p->pw_name;
}
#if defined(__linux__)
// TTimo
// sysconf() in libc, POSIX.1 compliant
unsigned int Sys_ProcessorCount()
{
return sysconf(_SC_NPROCESSORS_ONLN);
}
#endif

29
code/unix/vm_x86.c Normal file
View file

@ -0,0 +1,29 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/vm_local.h"
void VM_Compile( vm_t *vm, vmHeader_t *header ) {}
int VM_CallCompiled( vm_t *vm, int *args ) {}

462
code/unix/vm_x86a.s Normal file
View file

@ -0,0 +1,462 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// vm_x86a.s
// linux x86 vm support
#include "qasm.h"
.extern C(instructionPointers)
.data
.align 4
programStack .long 0
opStack .long 0
syscallNum .long 0
.text
.globl C(AsmCAll)
C(AsmCall):
movl (%edi),%eax
subl 4,%edi
orl %eax,%eax
jl systemCall
// calling another vm function
shll 2,%eax
addl C(instructionPointers),%eax
call (%eax)
ret
systemCall:
// convert negative num to system call number
// and store right before the first arg
negl %eax
decl %eax
movl %eax,syscallNum
///---- UNFINISHED FROM HERE
mov dword ptr syscallNum, eax // so C code can get at it
mov dword ptr programStack, esi // so C code can get at it
mov dword ptr opStack, edi
push ecx
push esi // we may call recursively, so the
push edi // statics aren't guaranteed to be around
}
// save the stack to allow recursive VM entry
currentVM->programStack = programStack - 4;
*(int *)((byte *)currentVM->dataBase + programStack + 4) = syscallNum;
//VM_LogSyscalls( (int *)((byte *)currentVM->dataBase + programStack + 4) );
*(opStack+1) = currentVM->systemCall( (int *)((byte *)currentVM->dataBase + programStack + 4) );
_asm {
pop edi
pop esi
pop ecx
add edi, 4 // we added the return value
ret
}
}
//--------------------------------------------
movl val(%esp),%ecx
movl $0x100,%edx // 0x10000000000 as dividend
cmpl %edx,%ecx
jle LOutOfRange
subl %eax,%eax
divl %ecx
ret
LOutOfRange:
movl $0xFFFFFFFF,%eax
ret
#if 0
#define in 4
#define out 8
.align 2
.globl C(TransformVector)
C(TransformVector):
movl in(%esp),%eax
movl out(%esp),%edx
flds (%eax) // in[0]
fmuls C(vright) // in[0]*vright[0]
flds (%eax) // in[0] | in[0]*vright[0]
fmuls C(vup) // in[0]*vup[0] | in[0]*vright[0]
flds (%eax) // in[0] | in[0]*vup[0] | in[0]*vright[0]
fmuls C(vpn) // in[0]*vpn[0] | in[0]*vup[0] | in[0]*vright[0]
flds 4(%eax) // in[1] | ...
fmuls C(vright)+4 // in[1]*vright[1] | ...
flds 4(%eax) // in[1] | in[1]*vright[1] | ...
fmuls C(vup)+4 // in[1]*vup[1] | in[1]*vright[1] | ...
flds 4(%eax) // in[1] | in[1]*vup[1] | in[1]*vright[1] | ...
fmuls C(vpn)+4 // in[1]*vpn[1] | in[1]*vup[1] | in[1]*vright[1] | ...
fxch %st(2) // in[1]*vright[1] | in[1]*vup[1] | in[1]*vpn[1] | ...
faddp %st(0),%st(5) // in[1]*vup[1] | in[1]*vpn[1] | ...
faddp %st(0),%st(3) // in[1]*vpn[1] | ...
faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum
flds 8(%eax) // in[2] | ...
fmuls C(vright)+8 // in[2]*vright[2] | ...
flds 8(%eax) // in[2] | in[2]*vright[2] | ...
fmuls C(vup)+8 // in[2]*vup[2] | in[2]*vright[2] | ...
flds 8(%eax) // in[2] | in[2]*vup[2] | in[2]*vright[2] | ...
fmuls C(vpn)+8 // in[2]*vpn[2] | in[2]*vup[2] | in[2]*vright[2] | ...
fxch %st(2) // in[2]*vright[2] | in[2]*vup[2] | in[2]*vpn[2] | ...
faddp %st(0),%st(5) // in[2]*vup[2] | in[2]*vpn[2] | ...
faddp %st(0),%st(3) // in[2]*vpn[2] | ...
faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum
fstps 8(%edx) // out[2]
fstps 4(%edx) // out[1]
fstps (%edx) // out[0]
ret
#endif
#define EMINS 4+4
#define EMAXS 4+8
#define P 4+12
.align 2
.globl C(BoxOnPlaneSide)
C(BoxOnPlaneSide):
pushl %ebx
movl P(%esp),%edx
movl EMINS(%esp),%ecx
xorl %eax,%eax
movl EMAXS(%esp),%ebx
movb pl_signbits(%edx),%al
cmpb $8,%al
jge Lerror
flds pl_normal(%edx) // p->normal[0]
fld %st(0) // p->normal[0] | p->normal[0]
jmp Ljmptab(,%eax,4)
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
Lcase0:
fmuls (%ebx) // p->normal[0]*emaxs[0] | p->normal[0]
flds pl_normal+4(%edx) // p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]
fxch %st(2) // p->normal[0] | p->normal[0]*emaxs[0] |
// p->normal[1]
fmuls (%ecx) // p->normal[0]*emins[0] |
// p->normal[0]*emaxs[0] | p->normal[1]
fxch %st(2) // p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fld %st(0) // p->normal[1] | p->normal[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 4(%ebx) // p->normal[1]*emaxs[1] | p->normal[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
flds pl_normal+8(%edx) // p->normal[2] | p->normal[1]*emaxs[1] |
// p->normal[1] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(2) // p->normal[1] | p->normal[1]*emaxs[1] |
// p->normal[2] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 4(%ecx) // p->normal[1]*emins[1] |
// p->normal[1]*emaxs[1] |
// p->normal[2] | p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(2) // p->normal[2] | p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fld %st(0) // p->normal[2] | p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fmuls 8(%ebx) // p->normal[2]*emaxs[2] |
// p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[0]*emins[0]
fxch %st(5) // p->normal[0]*emins[0] |
// p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1] |
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
faddp %st(0),%st(3) //p->normal[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
fmuls 8(%ecx) //p->normal[2]*emins[2] |
// p->normal[1]*emaxs[1] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
fxch %st(1) //p->normal[1]*emaxs[1] |
// p->normal[2]*emins[2] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0] |
// p->normal[2]*emaxs[2]
faddp %st(0),%st(3) //p->normal[2]*emins[2] |
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
// p->normal[2]*emaxs[2]
fxch %st(3) //p->normal[2]*emaxs[2] +
// p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// p->normal[0]*emaxs[0]+p->normal[1]*emaxs[1]|
// p->normal[2]*emins[2]
faddp %st(0),%st(2) //p->normal[1]*emins[1]+p->normal[0]*emins[0]|
// dist1 | p->normal[2]*emins[2]
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
Lcase1:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
Lcase2:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
Lcase3:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ebx) // emaxs[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ecx) // emins[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
Lcase4:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
Lcase5:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ebx) // emaxs[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ecx) // emins[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
Lcase6:
fmuls (%ebx) // emaxs[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ecx) // emins[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
jmp LSetSides
//dist1= p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
//dist2= p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
Lcase7:
fmuls (%ecx) // emins[0]
flds pl_normal+4(%edx)
fxch %st(2)
fmuls (%ebx) // emaxs[0]
fxch %st(2)
fld %st(0)
fmuls 4(%ecx) // emins[1]
flds pl_normal+8(%edx)
fxch %st(2)
fmuls 4(%ebx) // emaxs[1]
fxch %st(2)
fld %st(0)
fmuls 8(%ecx) // emins[2]
fxch %st(5)
faddp %st(0),%st(3)
fmuls 8(%ebx) // emaxs[2]
fxch %st(1)
faddp %st(0),%st(3)
fxch %st(3)
faddp %st(0),%st(2)
LSetSides:
// sides = 0;
// if (dist1 >= p->dist)
// sides = 1;
// if (dist2 < p->dist)
// sides |= 2;
faddp %st(0),%st(2) // dist1 | dist2
fcomps pl_dist(%edx)
xorl %ecx,%ecx
fnstsw %ax
fcomps pl_dist(%edx)
andb $1,%ah
xorb $1,%ah
addb %ah,%cl
fnstsw %ax
andb $1,%ah
addb %ah,%ah
addb %ah,%cl
// return sides;
popl %ebx
movl %ecx,%eax // return status
ret
Lerror:
movl 1, %eax
ret
#endif // id386

BIN
code/win32/RCa13168 Normal file

Binary file not shown.

BIN
code/win32/background.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

BIN
code/win32/clear.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

51
code/win32/glw_win.h Normal file
View file

@ -0,0 +1,51 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef _WIN32
# error You should not be including this file on this platform
#endif
#ifndef __GLW_WIN_H__
#define __GLW_WIN_H__
typedef struct
{
WNDPROC wndproc;
HDC hDC; // handle to device context
HGLRC hGLRC; // handle to GL rendering context
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
qboolean allowdisplaydepthchange;
qboolean pixelFormatSet;
int desktopBitsPixel;
int desktopWidth, desktopHeight;
qboolean cdsFullscreen;
FILE *log_fp;
} glwstate_t;
extern glwstate_t glw_state;
#endif

BIN
code/win32/icon2.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
code/win32/qe3.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

44
code/win32/resource.h Normal file
View file

@ -0,0 +1,44 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by winquake.rc
//
#define IDS_STRING1 1
#define IDI_ICON1 1
#define IDB_BITMAP1 1
#define IDB_BITMAP2 128
#define IDC_CURSOR1 129
#define IDC_CURSOR2 130
#define IDC_CURSOR3 131
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 132
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1005
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

214
code/win32/win_gamma.c Normal file
View file

@ -0,0 +1,214 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*
** WIN_GAMMA.C
*/
#include <assert.h>
#include "../renderer/tr_local.h"
#include "../qcommon/qcommon.h"
#include "glw_win.h"
#include "win_local.h"
static unsigned short s_oldHardwareGamma[3][256];
/*
** WG_CheckHardwareGamma
**
** Determines if the underlying hardware supports the Win32 gamma correction API.
*/
void WG_CheckHardwareGamma( void )
{
HDC hDC;
glConfig.deviceSupportsGamma = qfalse;
if ( qwglSetDeviceGammaRamp3DFX )
{
glConfig.deviceSupportsGamma = qtrue;
hDC = GetDC( GetDesktopWindow() );
glConfig.deviceSupportsGamma = qwglGetDeviceGammaRamp3DFX( hDC, s_oldHardwareGamma );
ReleaseDC( GetDesktopWindow(), hDC );
return;
}
// non-3Dfx standalone drivers don't support gamma changes, period
if ( glConfig.driverType == GLDRV_STANDALONE )
{
return;
}
if ( !r_ignorehwgamma->integer )
{
hDC = GetDC( GetDesktopWindow() );
glConfig.deviceSupportsGamma = GetDeviceGammaRamp( hDC, s_oldHardwareGamma );
ReleaseDC( GetDesktopWindow(), hDC );
if ( glConfig.deviceSupportsGamma )
{
//
// do a sanity check on the gamma values
//
if ( ( HIBYTE( s_oldHardwareGamma[0][255] ) <= HIBYTE( s_oldHardwareGamma[0][0] ) ) ||
( HIBYTE( s_oldHardwareGamma[1][255] ) <= HIBYTE( s_oldHardwareGamma[1][0] ) ) ||
( HIBYTE( s_oldHardwareGamma[2][255] ) <= HIBYTE( s_oldHardwareGamma[2][0] ) ) )
{
glConfig.deviceSupportsGamma = qfalse;
ri.Printf( PRINT_WARNING, "WARNING: device has broken gamma support, generated gamma.dat\n" );
}
//
// make sure that we didn't have a prior crash in the game, and if so we need to
// restore the gamma values to at least a linear value
//
if ( ( HIBYTE( s_oldHardwareGamma[0][181] ) == 255 ) )
{
int g;
ri.Printf( PRINT_WARNING, "WARNING: suspicious gamma tables, using linear ramp for restoration\n" );
for ( g = 0; g < 255; g++ )
{
s_oldHardwareGamma[0][g] = g << 8;
s_oldHardwareGamma[1][g] = g << 8;
s_oldHardwareGamma[2][g] = g << 8;
}
}
}
}
}
/*
void mapGammaMax( void ) {
int i, j;
unsigned short table[3][256];
// try to figure out what win2k will let us get away with setting
for ( i = 0 ; i < 256 ; i++ ) {
if ( i >= 128 ) {
table[0][i] = table[1][i] = table[2][i] = 0xffff;
} else {
table[0][i] = table[1][i] = table[2][i] = i<<9;
}
}
for ( i = 0 ; i < 128 ; i++ ) {
for ( j = i*2 ; j < 255 ; j++ ) {
table[0][i] = table[1][i] = table[2][i] = j<<8;
if ( !SetDeviceGammaRamp( glw_state.hDC, table ) ) {
break;
}
}
table[0][i] = table[1][i] = table[2][i] = i<<9;
Com_Printf( "index %i max: %i\n", i, j-1 );
}
}
*/
/*
** GLimp_SetGamma
**
** This routine should only be called if glConfig.deviceSupportsGamma is TRUE
*/
void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned char blue[256] ) {
unsigned short table[3][256];
int i, j;
int ret;
OSVERSIONINFO vinfo;
if ( !glConfig.deviceSupportsGamma || r_ignorehwgamma->integer || !glw_state.hDC ) {
return;
}
//mapGammaMax();
for ( i = 0; i < 256; i++ ) {
table[0][i] = ( ( ( unsigned short ) red[i] ) << 8 ) | red[i];
table[1][i] = ( ( ( unsigned short ) green[i] ) << 8 ) | green[i];
table[2][i] = ( ( ( unsigned short ) blue[i] ) << 8 ) | blue[i];
}
// Win2K puts this odd restriction on gamma ramps...
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
GetVersionEx( &vinfo );
if ( vinfo.dwMajorVersion == 5 && vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
Com_DPrintf( "performing W2K gamma clamp.\n" );
for ( j = 0 ; j < 3 ; j++ ) {
for ( i = 0 ; i < 128 ; i++ ) {
if ( table[j][i] > ( (128+i) << 8 ) ) {
table[j][i] = (128+i) << 8;
}
}
if ( table[j][127] > 254<<8 ) {
table[j][127] = 254<<8;
}
}
} else {
Com_DPrintf( "skipping W2K gamma clamp.\n" );
}
// enforce constantly increasing
for ( j = 0 ; j < 3 ; j++ ) {
for ( i = 1 ; i < 256 ; i++ ) {
if ( table[j][i] < table[j][i-1] ) {
table[j][i] = table[j][i-1];
}
}
}
if ( qwglSetDeviceGammaRamp3DFX )
{
qwglSetDeviceGammaRamp3DFX( glw_state.hDC, table );
}
else
{
ret = SetDeviceGammaRamp( glw_state.hDC, table );
if ( !ret ) {
Com_Printf( "SetDeviceGammaRamp failed.\n" );
}
}
}
/*
** WG_RestoreGamma
*/
void WG_RestoreGamma( void )
{
if ( glConfig.deviceSupportsGamma )
{
if ( qwglSetDeviceGammaRamp3DFX )
{
qwglSetDeviceGammaRamp3DFX( glw_state.hDC, s_oldHardwareGamma );
}
else
{
HDC hDC;
hDC = GetDC( GetDesktopWindow() );
SetDeviceGammaRamp( hDC, s_oldHardwareGamma );
ReleaseDC( GetDesktopWindow(), hDC );
}
}
}

1658
code/win32/win_glimp.c Normal file

File diff suppressed because it is too large Load diff

1149
code/win32/win_input.c Normal file

File diff suppressed because it is too large Load diff

95
code/win32/win_local.h Normal file
View file

@ -0,0 +1,95 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// win_local.h: Win32-specific Quake3 header file
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning(disable : 4201)
#pragma warning( push )
#endif
#include <windows.h>
#if defined (_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning( pop )
#endif
#define DIRECTSOUND_VERSION 0x0300
#define DIRECTINPUT_VERSION 0x0300
#include <dinput.h>
#include <dsound.h>
#include <winsock.h>
#include <wsipx.h>
void IN_MouseEvent (int mstate);
void Sys_QueEvent( int time, sysEventType_t type, int value, int value2, int ptrLength, void *ptr );
void Sys_CreateConsole( void );
void Sys_DestroyConsole( void );
char *Sys_ConsoleInput (void);
qboolean Sys_GetPacket ( netadr_t *net_from, msg_t *net_message );
// Input subsystem
void IN_Init (void);
void IN_Shutdown (void);
void IN_JoystickCommands (void);
void IN_Move (usercmd_t *cmd);
// add additional non keyboard / non mouse movement on top of the keyboard move cmd
void IN_DeactivateWin32Mouse( void);
void IN_Activate (qboolean active);
void IN_Frame (void);
// window procedure
LONG WINAPI MainWndProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
void Conbuf_AppendText( const char *msg );
void SNDDMA_Activate( void );
int SNDDMA_InitDS ();
typedef struct
{
HINSTANCE reflib_library; // Handle to refresh DLL
qboolean reflib_active;
HWND hWnd;
HINSTANCE hInstance;
qboolean activeApp;
qboolean isMinimized;
OSVERSIONINFO osversion;
// when we get a windows message, we store the time off so keyboard processing
// can know the exact time of an event
unsigned sysMsgTime;
} WinVars_t;
extern WinVars_t g_wv;

1593
code/win32/win_main.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- No id for Windows XP -->
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>

1031
code/win32/win_net.c Normal file

File diff suppressed because it is too large Load diff

4374
code/win32/win_qgl.c Normal file

File diff suppressed because it is too large Load diff

44
code/win32/win_resource.h Normal file
View file

@ -0,0 +1,44 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by winquake.rc
//
#define IDS_STRING1 1
#define IDI_ICON1 1
#define IDB_BITMAP1 1
#define IDB_BITMAP2 128
#define IDC_CURSOR1 129
#define IDC_CURSOR2 130
#define IDC_CURSOR3 131
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 132
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1005
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -0,0 +1,82 @@
//Microsoft Developer Studio generated resource script.
//
#include "win_resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include <winresrc.h>
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
#ifndef __MINGW32__
IDI_ICON1 ICON DISCARDABLE "../../misc/openmohaa.ico"
#else
IDI_ICON1 ICON DISCARDABLE "misc/openmohaa.ico"
#endif
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_STRING1 "OpenMoHAA"
END
/////////////////////////////////////////////////////////////////////////////
//
// Application Manifest
//
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "win_manifest.xml"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////

306
code/win32/win_shared.c Normal file
View file

@ -0,0 +1,306 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "win_local.h"
#include <lmerr.h>
#include <lmcons.h>
#include <lmwksta.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
/*
================
Sys_Milliseconds
================
*/
int sys_timeBase;
int Sys_Milliseconds (void)
{
int sys_curtime;
static qboolean initialized = qfalse;
if (!initialized) {
sys_timeBase = timeGetTime();
initialized = qtrue;
}
sys_curtime = timeGetTime() - sys_timeBase;
return sys_curtime;
}
/*
================
Sys_SnapVector
================
*/
long fastftol( float f ) {
static int tmp;
__asm fld f
__asm fistp tmp
__asm mov eax, tmp
}
void Sys_SnapVector( float *v )
{
int i;
float f;
f = *v;
__asm fld f;
__asm fistp i;
*v = i;
v++;
f = *v;
__asm fld f;
__asm fistp i;
*v = i;
v++;
f = *v;
__asm fld f;
__asm fistp i;
*v = i;
/*
*v = fastftol(*v);
v++;
*v = fastftol(*v);
v++;
*v = fastftol(*v);
*/
}
/*
**
** Disable all optimizations temporarily so this code works correctly!
**
*/
#pragma optimize( "", off )
/*
** --------------------------------------------------------------------------------
**
** PROCESSOR STUFF
**
** --------------------------------------------------------------------------------
*/
static void CPUID( int func, unsigned regs[4] )
{
unsigned regEAX, regEBX, regECX, regEDX;
#ifndef __VECTORC
__asm mov eax, func
__asm __emit 00fh
__asm __emit 0a2h
__asm mov regEAX, eax
__asm mov regEBX, ebx
__asm mov regECX, ecx
__asm mov regEDX, edx
regs[0] = regEAX;
regs[1] = regEBX;
regs[2] = regECX;
regs[3] = regEDX;
#else
regs[0] = 0;
regs[1] = 0;
regs[2] = 0;
regs[3] = 0;
#endif
}
static int IsPentium( void )
{
__asm
{
pushfd // save eflags
pop eax
test eax, 0x00200000 // check ID bit
jz set21 // bit 21 is not set, so jump to set_21
and eax, 0xffdfffff // clear bit 21
push eax // save new value in register
popfd // store new value in flags
pushfd
pop eax
test eax, 0x00200000 // check ID bit
jz good
jmp err // cpuid not supported
set21:
or eax, 0x00200000 // set ID bit
push eax // store new value
popfd // store new value in EFLAGS
pushfd
pop eax
test eax, 0x00200000 // if bit 21 is on
jnz good
jmp err
}
err:
return qfalse;
good:
return qtrue;
}
static int Is3DNOW( void )
{
unsigned regs[4];
char pstring[16];
char processorString[13];
// get name of processor
CPUID( 0, ( unsigned int * ) pstring );
processorString[0] = pstring[4];
processorString[1] = pstring[5];
processorString[2] = pstring[6];
processorString[3] = pstring[7];
processorString[4] = pstring[12];
processorString[5] = pstring[13];
processorString[6] = pstring[14];
processorString[7] = pstring[15];
processorString[8] = pstring[8];
processorString[9] = pstring[9];
processorString[10] = pstring[10];
processorString[11] = pstring[11];
processorString[12] = 0;
// REMOVED because you can have 3DNow! on non-AMD systems
// if ( strcmp( processorString, "AuthenticAMD" ) )
// return qfalse;
// check AMD-specific functions
CPUID( 0x80000000, regs );
if ( regs[0] < 0x80000000 )
return qfalse;
// bit 31 of EDX denotes 3DNOW! support
CPUID( 0x80000001, regs );
if ( regs[3] & ( 1 << 31 ) )
return qtrue;
return qfalse;
}
static int IsKNI( void )
{
unsigned regs[4];
// get CPU feature bits
CPUID( 1, regs );
// bit 25 of EDX denotes KNI existence
if ( regs[3] & ( 1 << 25 ) )
return qtrue;
return qfalse;
}
static int IsMMX( void )
{
unsigned regs[4];
// get CPU feature bits
CPUID( 1, regs );
// bit 23 of EDX denotes MMX existence
if ( regs[3] & ( 1 << 23 ) )
return qtrue;
return qfalse;
}
int Sys_GetProcessorId( void )
{
#if defined _M_ALPHA
return CPUID_AXP;
#elif !defined _M_IX86
return CPUID_GENERIC;
#else
// verify we're at least a Pentium or 486 w/ CPUID support
if ( !IsPentium() )
return CPUID_INTEL_UNSUPPORTED;
// check for MMX
if ( !IsMMX() )
{
// Pentium or PPro
return CPUID_INTEL_PENTIUM;
}
// see if we're an AMD 3DNOW! processor
if ( Is3DNOW() )
{
return CPUID_AMD_3DNOW;
}
// see if we're an Intel Katmai
if ( IsKNI() )
{
return CPUID_INTEL_KATMAI;
}
// by default we're functionally a vanilla Pentium/MMX or P2/MMX
return CPUID_INTEL_MMX;
#endif
}
/*
**
** Re-enable optimizations back to what they were
**
*/
#pragma optimize( "", on )
//============================================
char *Sys_GetCurrentUser( void )
{
static char s_userName[1024];
unsigned long size = sizeof( s_userName );
if ( !GetUserName( s_userName, &size ) )
strcpy( s_userName, "player" );
if ( !s_userName[0] )
{
strcpy( s_userName, "player" );
}
return s_userName;
}
char *Sys_DefaultHomePath(void) {
return NULL;
}
char *Sys_DefaultInstallPath(void)
{
return Sys_Cwd();
}

388
code/win32/win_snd.c Normal file
View file

@ -0,0 +1,388 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include <float.h>
#include "../client/snd_local.h"
#include "win_local.h"
HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
#define SECONDARY_BUFFER_SIZE 0x10000
static qboolean dsound_init;
static int sample16;
static DWORD gSndBufSize;
static DWORD locksize;
static LPDIRECTSOUND pDS;
static LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
static HINSTANCE hInstDS;
static const char *DSoundError( int error ) {
switch ( error ) {
case DSERR_BUFFERLOST:
return "DSERR_BUFFERLOST";
case DSERR_INVALIDCALL:
return "DSERR_INVALIDCALLS";
case DSERR_INVALIDPARAM:
return "DSERR_INVALIDPARAM";
case DSERR_PRIOLEVELNEEDED:
return "DSERR_PRIOLEVELNEEDED";
}
return "unknown";
}
/*
==================
SNDDMA_Shutdown
==================
*/
void SNDDMA_Shutdown( void ) {
Com_DPrintf( "Shutting down sound system\n" );
if ( pDS ) {
Com_DPrintf( "Destroying DS buffers\n" );
if ( pDS )
{
Com_DPrintf( "...setting NORMAL coop level\n" );
pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY );
}
if ( pDSBuf )
{
Com_DPrintf( "...stopping and releasing sound buffer\n" );
pDSBuf->lpVtbl->Stop( pDSBuf );
pDSBuf->lpVtbl->Release( pDSBuf );
}
// only release primary buffer if it's not also the mixing buffer we just released
if ( pDSPBuf && ( pDSBuf != pDSPBuf ) )
{
Com_DPrintf( "...releasing primary buffer\n" );
pDSPBuf->lpVtbl->Release( pDSPBuf );
}
pDSBuf = NULL;
pDSPBuf = NULL;
dma.buffer = NULL;
Com_DPrintf( "...releasing DS object\n" );
pDS->lpVtbl->Release( pDS );
}
if ( hInstDS ) {
Com_DPrintf( "...freeing DSOUND.DLL\n" );
FreeLibrary( hInstDS );
hInstDS = NULL;
}
pDS = NULL;
pDSBuf = NULL;
pDSPBuf = NULL;
dsound_init = qfalse;
memset ((void *)&dma, 0, sizeof (dma));
CoUninitialize( );
}
/*
==================
SNDDMA_Init
Initialize direct sound
Returns false if failed
==================
*/
qboolean SNDDMA_Init(void) {
memset ((void *)&dma, 0, sizeof (dma));
dsound_init = 0;
CoInitialize(NULL);
if ( !SNDDMA_InitDS () ) {
return qfalse;
}
dsound_init = qtrue;
Com_DPrintf("Completed successfully\n" );
return qtrue;
}
#undef DEFINE_GUID
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
// DirectSound Component GUID {47D4D946-62E8-11CF-93BC-444553540000}
DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
// DirectSound 8.0 Component GUID {3901CC3F-84B5-4FA4-BA35-AA8172B8A09B}
DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b);
DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93, 0xF395, 0x4834, 0x9E, 0xF6, 0x7F, 0xA9, 0x9D, 0xE5, 0x09, 0x66);
DEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);
int SNDDMA_InitDS ()
{
HRESULT hresult;
DSBUFFERDESC dsbuf;
DSBCAPS dsbcaps;
WAVEFORMATEX format;
int use8;
Com_Printf( "Initializing DirectSound\n");
use8 = 1;
// Create IDirectSound using the primary sound device
if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound8, (void **)&pDS))) {
use8 = 0;
if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&pDS))) {
Com_Printf ("failed\n");
SNDDMA_Shutdown ();
return qfalse;
}
}
hresult = pDS->lpVtbl->Initialize( pDS, NULL);
Com_DPrintf( "ok\n" );
Com_DPrintf("...setting DSSCL_PRIORITY coop level: " );
if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY ) ) {
Com_Printf ("failed\n");
SNDDMA_Shutdown ();
return qfalse;
}
Com_DPrintf("ok\n" );
// create the secondary buffer we'll actually work with
dma.channels = 2;
dma.samplebits = 16;
// if (s_khz->integer == 44)
// dma.speed = 44100;
// else if (s_khz->integer == 22)
// dma.speed = 22050;
// else
// dma.speed = 11025;
dma.speed = 22050;
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = dma.channels;
format.wBitsPerSample = dma.samplebits;
format.nSamplesPerSec = dma.speed;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
// Micah: take advantage of 2D hardware.if available.
dsbuf.dwFlags = DSBCAPS_LOCHARDWARE;
if (use8) {
dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2;
}
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
dsbuf.lpwfxFormat = &format;
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
Com_DPrintf( "...creating secondary buffer: " );
if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) {
Com_Printf( "locked hardware. ok\n" );
}
else {
// Couldn't get hardware, fallback to software.
dsbuf.dwFlags = DSBCAPS_LOCSOFTWARE;
if (use8) {
dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2;
}
if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) {
Com_Printf( "failed\n" );
SNDDMA_Shutdown ();
return qfalse;
}
Com_DPrintf( "forced to software. ok\n" );
}
// Make sure mixer is active
if ( DS_OK != pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING) ) {
Com_Printf ("*** Looped sound play failed ***\n");
SNDDMA_Shutdown ();
return qfalse;
}
// get the returned buffer size
if ( DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps) ) {
Com_Printf ("*** GetCaps failed ***\n");
SNDDMA_Shutdown ();
return qfalse;
}
gSndBufSize = dsbcaps.dwBufferBytes;
dma.channels = format.nChannels;
dma.samplebits = format.wBitsPerSample;
dma.speed = format.nSamplesPerSec;
dma.samples = gSndBufSize/(dma.samplebits/8);
dma.submission_chunk = 1;
dma.buffer = NULL; // must be locked first
sample16 = (dma.samplebits/8) - 1;
SNDDMA_BeginPainting ();
if (dma.buffer)
memset(dma.buffer, 0, dma.samples * dma.samplebits/8);
SNDDMA_Submit ();
return 1;
}
/*
==============
SNDDMA_GetDMAPos
return the current sample position (in mono samples read)
inside the recirculating dma buffer, so the mixing code will know
how many sample are required to fill it up.
===============
*/
int SNDDMA_GetDMAPos( void ) {
MMTIME mmtime;
int s;
DWORD dwWrite;
if ( !dsound_init ) {
return 0;
}
mmtime.wType = TIME_SAMPLES;
pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite);
s = mmtime.u.sample;
s >>= sample16;
s &= (dma.samples-1);
return s;
}
/*
==============
SNDDMA_BeginPainting
Makes sure dma.buffer is valid
===============
*/
void SNDDMA_BeginPainting( void ) {
int reps;
DWORD dwSize2;
DWORD *pbuf, *pbuf2;
HRESULT hresult;
DWORD dwStatus;
if ( !pDSBuf ) {
return;
}
// if the buffer was lost or stopped, restore it and/or restart it
if ( pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK ) {
Com_Printf ("Couldn't get sound buffer status\n");
}
if (dwStatus & DSBSTATUS_BUFFERLOST)
pDSBuf->lpVtbl->Restore (pDSBuf);
if (!(dwStatus & DSBSTATUS_PLAYING))
pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
// lock the dsound buffer
reps = 0;
dma.buffer = NULL;
while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &locksize,
&pbuf2, &dwSize2, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
Com_Printf( "SNDDMA_BeginPainting: Lock failed with error '%s'\n", DSoundError( hresult ) );
S_Shutdown ();
return;
}
else
{
pDSBuf->lpVtbl->Restore( pDSBuf );
}
if (++reps > 2)
return;
}
dma.buffer = (unsigned char *)pbuf;
}
/*
==============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
Also unlocks the dsound buffer
===============
*/
void SNDDMA_Submit( void ) {
// unlock the dsound buffer
if ( pDSBuf ) {
pDSBuf->lpVtbl->Unlock(pDSBuf, dma.buffer, locksize, NULL, 0);
}
}
/*
=================
SNDDMA_Activate
When we change windows we need to do this
=================
*/
void SNDDMA_Activate( void ) {
if ( !pDS ) {
return;
}
if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY ) ) {
Com_Printf ("sound SetCooperativeLevel failed\n");
SNDDMA_Shutdown ();
}
}

596
code/win32/win_syscon.c Normal file
View file

@ -0,0 +1,596 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// win_syscon.h
#include "../client/client.h"
#include "win_local.h"
#include "resource.h"
#include <errno.h>
#include <float.h>
#include <fcntl.h>
#include <stdio.h>
#include <direct.h>
#include <io.h>
#include <conio.h>
#define COPY_ID 1
#define QUIT_ID 2
#define CLEAR_ID 3
#define ERRORBOX_ID 10
#define ERRORTEXT_ID 11
#define EDIT_ID 100
#define INPUT_ID 101
typedef struct
{
HWND hWnd;
HWND hwndBuffer;
HWND hwndButtonClear;
HWND hwndButtonCopy;
HWND hwndButtonQuit;
HWND hwndErrorBox;
HWND hwndErrorText;
HBITMAP hbmLogo;
HBITMAP hbmClearBitmap;
HBRUSH hbrEditBackground;
HBRUSH hbrErrorBackground;
HFONT hfBufferFont;
HFONT hfButtonFont;
HWND hwndInputLine;
char errorString[80];
char consoleText[512], returnedText[512];
int visLevel;
qboolean quitOnClose;
int windowWidth, windowHeight;
WNDPROC SysInputLineWndProc;
} WinConData;
static WinConData s_wcd;
static LONG WINAPI ConWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char *cmdString;
static qboolean s_timePolarity;
switch (uMsg)
{
case WM_ACTIVATE:
if ( LOWORD( wParam ) != WA_INACTIVE )
{
SetFocus( s_wcd.hwndInputLine );
}
if ( com_viewlog && ( com_dedicated && !com_dedicated->integer ) )
{
// if the viewlog is open, check to see if it's being minimized
if ( com_viewlog->integer == 1 )
{
if ( HIWORD( wParam ) ) // minimized flag
{
Cvar_Set( "viewlog", "2" );
}
}
else if ( com_viewlog->integer == 2 )
{
if ( !HIWORD( wParam ) ) // minimized flag
{
Cvar_Set( "viewlog", "1" );
}
}
}
break;
case WM_CLOSE:
if ( ( com_dedicated && com_dedicated->integer ) )
{
cmdString = CopyString( "quit" );
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
}
else if ( s_wcd.quitOnClose )
{
PostQuitMessage( 0 );
}
else
{
Sys_ShowConsole( 0, qfalse );
Cvar_Set( "viewlog", "0" );
}
return 0;
case WM_CTLCOLORSTATIC:
if ( ( HWND ) lParam == s_wcd.hwndBuffer )
{
SetBkColor( ( HDC ) wParam, RGB( 0x00, 0x00, 0xB0 ) );
SetTextColor( ( HDC ) wParam, RGB( 0xff, 0xff, 0x00 ) );
#if 0 // this draws a background in the edit box, but there are issues with this
if ( ( hdcScaled = CreateCompatibleDC( ( HDC ) wParam ) ) != 0 )
{
if ( SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo ) )
{
StretchBlt( ( HDC ) wParam, 0, 0, 512, 384,
hdcScaled, 0, 0, 512, 384,
SRCCOPY );
}
DeleteDC( hdcScaled );
}
#endif
return ( long ) s_wcd.hbrEditBackground;
}
else if ( ( HWND ) lParam == s_wcd.hwndErrorBox )
{
if ( s_timePolarity & 1 )
{
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
SetTextColor( ( HDC ) wParam, RGB( 0xff, 0x0, 0x00 ) );
}
else
{
SetBkColor( ( HDC ) wParam, RGB( 0x80, 0x80, 0x80 ) );
SetTextColor( ( HDC ) wParam, RGB( 0x00, 0x0, 0x00 ) );
}
return ( long ) s_wcd.hbrErrorBackground;
}
break;
case WM_COMMAND:
if ( wParam == COPY_ID )
{
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
SendMessage( s_wcd.hwndBuffer, WM_COPY, 0, 0 );
}
else if ( wParam == QUIT_ID )
{
if ( s_wcd.quitOnClose )
{
PostQuitMessage( 0 );
}
else
{
cmdString = CopyString( "quit" );
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, strlen( cmdString ) + 1, cmdString );
}
}
else if ( wParam == CLEAR_ID )
{
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, FALSE, ( LPARAM ) "" );
UpdateWindow( s_wcd.hwndBuffer );
}
break;
case WM_CREATE:
// s_wcd.hbmLogo = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP1 ) );
// s_wcd.hbmClearBitmap = LoadBitmap( g_wv.hInstance, MAKEINTRESOURCE( IDB_BITMAP2 ) );
s_wcd.hbrEditBackground = CreateSolidBrush( RGB( 0x00, 0x00, 0xB0 ) );
s_wcd.hbrErrorBackground = CreateSolidBrush( RGB( 0x80, 0x80, 0x80 ) );
SetTimer( hWnd, 1, 1000, NULL );
break;
case WM_ERASEBKGND:
#if 0
HDC hdcScaled;
HGDIOBJ oldObject;
#if 1 // a single, large image
hdcScaled = CreateCompatibleDC( ( HDC ) wParam );
assert( hdcScaled != 0 );
if ( hdcScaled )
{
oldObject = SelectObject( ( HDC ) hdcScaled, s_wcd.hbmLogo );
assert( oldObject != 0 );
if ( oldObject )
{
StretchBlt( ( HDC ) wParam, 0, 0, s_wcd.windowWidth, s_wcd.windowHeight,
hdcScaled, 0, 0, 512, 384,
SRCCOPY );
}
DeleteDC( hdcScaled );
hdcScaled = 0;
}
#else // a repeating brush
{
HBRUSH hbrClearBrush;
RECT r;
GetWindowRect( hWnd, &r );
r.bottom = r.bottom - r.top + 1;
r.right = r.right - r.left + 1;
r.top = 0;
r.left = 0;
hbrClearBrush = CreatePatternBrush( s_wcd.hbmClearBitmap );
assert( hbrClearBrush != 0 );
if ( hbrClearBrush )
{
FillRect( ( HDC ) wParam, &r, hbrClearBrush );
DeleteObject( hbrClearBrush );
}
}
#endif
return 1;
#endif
return DefWindowProc( hWnd, uMsg, wParam, lParam );
case WM_TIMER:
if ( wParam == 1 )
{
s_timePolarity = !s_timePolarity;
if ( s_wcd.hwndErrorBox )
{
InvalidateRect( s_wcd.hwndErrorBox, NULL, FALSE );
}
}
break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char inputBuffer[1024];
switch ( uMsg )
{
case WM_KILLFOCUS:
if ( ( HWND ) wParam == s_wcd.hWnd ||
( HWND ) wParam == s_wcd.hwndErrorBox )
{
SetFocus( hWnd );
return 0;
}
break;
case WM_CHAR:
if ( wParam == 13 )
{
GetWindowText( s_wcd.hwndInputLine, inputBuffer, sizeof( inputBuffer ) );
strncat( s_wcd.consoleText, inputBuffer, sizeof( s_wcd.consoleText ) - strlen( s_wcd.consoleText ) - 5 );
strcat( s_wcd.consoleText, "\n" );
SetWindowText( s_wcd.hwndInputLine, "" );
Sys_Print( va( "]%s\n", inputBuffer ) );
return 0;
}
}
return CallWindowProc( s_wcd.SysInputLineWndProc, hWnd, uMsg, wParam, lParam );
}
/*
** Sys_CreateConsole
*/
void Sys_CreateConsole( void )
{
HDC hDC;
WNDCLASS wc;
RECT rect;
const char *DEDCLASS = "Q3 WinConsole";
int nHeight;
int swidth, sheight;
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
memset( &wc, 0, sizeof( wc ) );
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) ConWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_wv.hInstance;
wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = (void *)COLOR_WINDOW;
wc.lpszMenuName = 0;
wc.lpszClassName = DEDCLASS;
if ( !RegisterClass (&wc) )
return;
rect.left = 0;
rect.right = 540;
rect.top = 0;
rect.bottom = 450;
AdjustWindowRect( &rect, DEDSTYLE, FALSE );
hDC = GetDC( GetDesktopWindow() );
swidth = GetDeviceCaps( hDC, HORZRES );
sheight = GetDeviceCaps( hDC, VERTRES );
ReleaseDC( GetDesktopWindow(), hDC );
s_wcd.windowWidth = rect.right - rect.left + 1;
s_wcd.windowHeight = rect.bottom - rect.top + 1;
s_wcd.hWnd = CreateWindowEx( 0,
DEDCLASS,
"OpenMoHAA Console",
DEDSTYLE,
( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
NULL,
NULL,
g_wv.hInstance,
NULL );
if ( s_wcd.hWnd == NULL )
{
return;
}
//
// create fonts
//
hDC = GetDC( s_wcd.hWnd );
nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY), 72);
s_wcd.hfBufferFont = CreateFont( nHeight,
0,
0,
0,
FW_LIGHT,
0,
0,
0,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
FF_MODERN | FIXED_PITCH,
"Courier New" );
ReleaseDC( s_wcd.hWnd, hDC );
//
// create the input line
//
s_wcd.hwndInputLine = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
ES_LEFT | ES_AUTOHSCROLL,
6, 400, 528, 20,
s_wcd.hWnd,
( HMENU ) INPUT_ID, // child window ID
g_wv.hInstance, NULL );
//
// create the buttons
//
s_wcd.hwndButtonCopy = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
5, 425, 72, 24,
s_wcd.hWnd,
( HMENU ) COPY_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndButtonCopy, WM_SETTEXT, 0, ( LPARAM ) "copy" );
s_wcd.hwndButtonClear = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
82, 425, 72, 24,
s_wcd.hWnd,
( HMENU ) CLEAR_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndButtonClear, WM_SETTEXT, 0, ( LPARAM ) "clear" );
s_wcd.hwndButtonQuit = CreateWindow( "button", NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
462, 425, 72, 24,
s_wcd.hWnd,
( HMENU ) QUIT_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndButtonQuit, WM_SETTEXT, 0, ( LPARAM ) "quit" );
//
// create the scrollbuffer
//
s_wcd.hwndBuffer = CreateWindow( "edit", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY,
6, 40, 526, 354,
s_wcd.hWnd,
( HMENU ) EDIT_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndBuffer, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
s_wcd.SysInputLineWndProc = ( WNDPROC ) SetWindowLong( s_wcd.hwndInputLine, GWL_WNDPROC, ( long ) InputLineWndProc );
SendMessage( s_wcd.hwndInputLine, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
ShowWindow( s_wcd.hWnd, SW_SHOWDEFAULT);
UpdateWindow( s_wcd.hWnd );
SetForegroundWindow( s_wcd.hWnd );
SetFocus( s_wcd.hwndInputLine );
s_wcd.visLevel = 1;
}
/*
** Sys_DestroyConsole
*/
void Sys_DestroyConsole( void ) {
if ( s_wcd.hWnd ) {
ShowWindow( s_wcd.hWnd, SW_HIDE );
CloseWindow( s_wcd.hWnd );
DestroyWindow( s_wcd.hWnd );
s_wcd.hWnd = 0;
}
}
/*
** Sys_ShowConsole
*/
void Sys_ShowConsole( int visLevel, qboolean quitOnClose )
{
s_wcd.quitOnClose = quitOnClose;
if ( visLevel == s_wcd.visLevel )
{
return;
}
s_wcd.visLevel = visLevel;
if ( !s_wcd.hWnd )
return;
switch ( visLevel )
{
case 0:
ShowWindow( s_wcd.hWnd, SW_HIDE );
break;
case 1:
ShowWindow( s_wcd.hWnd, SW_SHOWNORMAL );
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
break;
case 2:
ShowWindow( s_wcd.hWnd, SW_MINIMIZE );
break;
default:
Sys_Error( "Invalid visLevel %d sent to Sys_ShowConsole\n", visLevel );
break;
}
}
/*
** Sys_ConsoleInput
*/
char *Sys_ConsoleInput( void )
{
if ( s_wcd.consoleText[0] == 0 )
{
return NULL;
}
strcpy( s_wcd.returnedText, s_wcd.consoleText );
s_wcd.consoleText[0] = 0;
return s_wcd.returnedText;
}
/*
** Conbuf_AppendText
*/
void Conbuf_AppendText( const char *pMsg )
{
#define CONSOLE_BUFFER_SIZE 16384
char buffer[CONSOLE_BUFFER_SIZE*2];
char *b = buffer;
const char *msg;
int bufLen;
int i = 0;
static unsigned long s_totalChars;
//
// if the message is REALLY long, use just the last portion of it
//
if ( strlen( pMsg ) > CONSOLE_BUFFER_SIZE - 1 )
{
msg = pMsg + strlen( pMsg ) - CONSOLE_BUFFER_SIZE + 1;
}
else
{
msg = pMsg;
}
//
// copy into an intermediate buffer
//
while ( msg[i] && ( ( b - buffer ) < sizeof( buffer ) - 1 ) )
{
if ( msg[i] == '\n' && msg[i+1] == '\r' )
{
b[0] = '\r';
b[1] = '\n';
b += 2;
i++;
}
else if ( msg[i] == '\r' )
{
b[0] = '\r';
b[1] = '\n';
b += 2;
}
else if ( msg[i] == '\n' )
{
b[0] = '\r';
b[1] = '\n';
b += 2;
}
else if ( Q_IsColorString( &msg[i] ) )
{
i++;
}
else
{
*b= msg[i];
b++;
}
i++;
}
*b = 0;
bufLen = b - buffer;
s_totalChars += bufLen;
//
// replace selection instead of appending if we're overflowing
//
if ( s_totalChars > 0x7fff )
{
SendMessage( s_wcd.hwndBuffer, EM_SETSEL, 0, -1 );
s_totalChars = bufLen;
}
//
// put this text into the windows console
//
SendMessage( s_wcd.hwndBuffer, EM_LINESCROLL, 0, 0xffff );
SendMessage( s_wcd.hwndBuffer, EM_SCROLLCARET, 0, 0 );
SendMessage( s_wcd.hwndBuffer, EM_REPLACESEL, 0, (LPARAM) buffer );
}
/*
** Sys_SetErrorText
*/
void Sys_SetErrorText( const char *buf )
{
Q_strncpyz( s_wcd.errorString, buf, sizeof( s_wcd.errorString ) );
if ( !s_wcd.hwndErrorBox )
{
s_wcd.hwndErrorBox = CreateWindow( "static", NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN,
6, 5, 526, 30,
s_wcd.hWnd,
( HMENU ) ERRORBOX_ID, // child window ID
g_wv.hInstance, NULL );
SendMessage( s_wcd.hwndErrorBox, WM_SETFONT, ( WPARAM ) s_wcd.hfBufferFont, 0 );
SetWindowText( s_wcd.hwndErrorBox, s_wcd.errorString );
DestroyWindow( s_wcd.hwndInputLine );
s_wcd.hwndInputLine = NULL;
}
}

440
code/win32/win_wndproc.c Normal file
View file

@ -0,0 +1,440 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code 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.
Quake III Arena source code 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 Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../client/client.h"
#include "win_local.h"
WinVars_t g_wv;
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL (WM_MOUSELAST+1) // message that will be supported by the OS
#endif
static UINT MSH_MOUSEWHEEL;
// Console variables that we need to access from this module
cvar_t *vid_xpos; // X coordinate of window position
cvar_t *vid_ypos; // Y coordinate of window position
cvar_t *r_fullscreen;
#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) )
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
static qboolean s_alttab_disabled;
static void WIN_DisableAltTab( void )
{
if ( s_alttab_disabled )
return;
if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
{
RegisterHotKey( 0, 0, MOD_ALT, VK_TAB );
}
else
{
BOOL old;
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 1, &old, 0 );
}
s_alttab_disabled = qtrue;
}
static void WIN_EnableAltTab( void )
{
if ( s_alttab_disabled )
{
if ( !Q_stricmp( Cvar_VariableString( "arch" ), "winnt" ) )
{
UnregisterHotKey( 0, 0 );
}
else
{
BOOL old;
SystemParametersInfo( SPI_SCREENSAVERRUNNING, 0, &old, 0 );
}
s_alttab_disabled = qfalse;
}
}
/*
==================
VID_AppActivate
==================
*/
static void VID_AppActivate(BOOL fActive, BOOL minimize)
{
g_wv.isMinimized = minimize;
Com_DPrintf("VID_AppActivate: %i\n", fActive );
//Key_ClearStates(); // FIXME!!!
// we don't want to act like we're active if we're minimized
if (fActive && !g_wv.isMinimized )
{
g_wv.activeApp = qtrue;
}
else
{
g_wv.activeApp = qfalse;
}
// minimize/restore mouse-capture on demand
if (!g_wv.activeApp )
{
IN_Activate (qfalse);
}
else
{
IN_Activate (qtrue);
}
}
//==========================================================================
static byte s_scantokey[128] =
{
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2
'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*',
K_ALT,' ', K_CAPSLOCK , K_F1, K_F2, K_F3, K_F4, K_F5, // 3
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME,
K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,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
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7
};
/*
=======
MapKey
Map from windows to quake keynums
=======
*/
static int MapKey (int key)
{
int result;
int modified;
qboolean is_extended;
// Com_Printf( "0x%x\n", key);
modified = ( key >> 16 ) & 255;
if ( modified > 127 )
return 0;
if ( key & ( 1 << 24 ) )
{
is_extended = qtrue;
}
else
{
is_extended = qfalse;
}
result = s_scantokey[modified];
if ( !is_extended )
{
switch ( result )
{
case K_HOME:
return K_KP_HOME;
case K_UPARROW:
return K_KP_UPARROW;
case K_PGUP:
return K_KP_PGUP;
case K_LEFTARROW:
return K_KP_LEFTARROW;
case K_RIGHTARROW:
return K_KP_RIGHTARROW;
case K_END:
return K_KP_END;
case K_DOWNARROW:
return K_KP_DOWNARROW;
case K_PGDN:
return K_KP_PGDN;
case K_INS:
return K_KP_INS;
case K_DEL:
return K_KP_DEL;
default:
return result;
}
}
else
{
switch ( result )
{
case K_PAUSE:
return K_KP_NUMLOCK;
case 0x0D:
return K_KP_ENTER;
case 0x2F:
return K_KP_SLASH;
case 0xAF:
return K_KP_PLUS;
}
return result;
}
}
/*
====================
MainWndProc
main window procedure
====================
*/
extern cvar_t *in_mouse;
LONG WINAPI MainWndProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
static qboolean flip = qtrue;
int zDelta, i;
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp
// Windows 95, Windows NT 3.51 - uses MSH_MOUSEWHEEL
// only relevant for non-DI input
//
// NOTE: not sure how reliable this is anymore, might trigger double wheel events
if (in_mouse->integer != 1)
{
if ( uMsg == MSH_MOUSEWHEEL )
{
if ( ( ( int ) wParam ) > 0 )
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qfalse, 0, NULL );
}
else
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL );
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
}
switch (uMsg)
{
case WM_MOUSEWHEEL:
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp
// Windows 98/Me, Windows NT 4.0 and later - uses WM_MOUSEWHEEL
// only relevant for non-DI input and when console is toggled in window mode
// if console is toggled in window mode (KEYCATCH_CONSOLE) then mouse is released and DI doesn't see any mouse wheel
if (in_mouse->integer != 1 || (!r_fullscreen->integer && (cls.keyCatchers & KEYCATCH_CONSOLE)))
{
// 120 increments, might be 240 and multiples if wheel goes too fast
// NOTE Logitech: logitech drivers are screwed and send the message twice?
// could add a cvar to interpret the message as successive press/release events
zDelta = ( short ) HIWORD( wParam ) / 120;
if ( zDelta > 0 )
{
for(i=0; i<zDelta; i++)
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELUP, qfalse, 0, NULL );
}
}
else
{
for(i=0; i<-zDelta; i++)
{
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL );
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL );
}
}
// when an application processes the WM_MOUSEWHEEL message, it must return zero
return 0;
}
break;
case WM_CREATE:
g_wv.hWnd = hWnd;
vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE);
vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE);
r_fullscreen = Cvar_Get ("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
if ( r_fullscreen->integer )
{
WIN_DisableAltTab();
}
else
{
WIN_EnableAltTab();
}
break;
#if 0
case WM_DISPLAYCHANGE:
Com_DPrintf( "WM_DISPLAYCHANGE\n" );
// we need to force a vid_restart if the user has changed
// their desktop resolution while the game is running,
// but don't do anything if the message is a result of
// our own calling of ChangeDisplaySettings
if ( com_insideVidInit ) {
break; // we did this on purpose
}
// something else forced a mode change, so restart all our gl stuff
Cbuf_AddText( "vid_restart\n" );
break;
#endif
case WM_DESTROY:
// let sound and input know about this?
g_wv.hWnd = NULL;
if ( r_fullscreen->integer )
{
WIN_EnableAltTab();
}
break;
case WM_CLOSE:
Cbuf_ExecuteText( EXEC_APPEND, "quit" );
break;
case WM_ACTIVATE:
{
int fActive, fMinimized;
fActive = LOWORD(wParam);
fMinimized = (BOOL) HIWORD(wParam);
VID_AppActivate( fActive != WA_INACTIVE, fMinimized);
SNDDMA_Activate();
}
break;
case WM_MOVE:
{
int xPos, yPos;
RECT r;
int style;
if (!r_fullscreen->integer )
{
xPos = (short) LOWORD(lParam); // horizontal position
yPos = (short) HIWORD(lParam); // vertical position
r.left = 0;
r.top = 0;
r.right = 1;
r.bottom = 1;
style = GetWindowLong( hWnd, GWL_STYLE );
AdjustWindowRect( &r, style, FALSE );
Cvar_SetValue( "vid_xpos", xPos + r.left);
Cvar_SetValue( "vid_ypos", yPos + r.top);
vid_xpos->modified = qfalse;
vid_ypos->modified = qfalse;
if ( g_wv.activeApp )
{
IN_Activate (qtrue);
}
}
}
break;
// this is complicated because Win32 seems to pack multiple mouse events into
// one update sometimes, so we always check all states and look for events
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
{
int temp;
temp = 0;
if (wParam & MK_LBUTTON)
temp |= 1;
if (wParam & MK_RBUTTON)
temp |= 2;
if (wParam & MK_MBUTTON)
temp |= 4;
IN_MouseEvent (temp);
}
break;
case WM_SYSCOMMAND:
if ( wParam == SC_SCREENSAVE )
return 0;
break;
case WM_SYSKEYDOWN:
if ( wParam == 13 )
{
if ( r_fullscreen )
{
Cvar_SetValue( "r_fullscreen", !r_fullscreen->integer );
Cbuf_AddText( "vid_restart\n" );
}
return 0;
}
// fall through
case WM_KEYDOWN:
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qtrue, 0, NULL );
break;
case WM_SYSKEYUP:
case WM_KEYUP:
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qfalse, 0, NULL );
break;
case WM_CHAR:
Sys_QueEvent( g_wv.sysMsgTime, SE_CHAR, wParam, 0, 0, NULL );
break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

71
code/win32/winquake.rc Normal file
View file

@ -0,0 +1,71 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "qe3.ico"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE DISCARDABLE
BEGIN
IDS_STRING1 "Quake3"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////