Initial commit.
This commit is contained in:
131
codemp/unix/ftol.nasm
Normal file
131
codemp/unix/ftol.nasm
Normal file
@@ -0,0 +1,131 @@
|
||||
;
|
||||
; 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
|
||||
|
||||
323
codemp/unix/linux_common.c
Normal file
323
codemp/unix/linux_common.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* 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
|
||||
1543
codemp/unix/linux_glimp.c
Normal file
1543
codemp/unix/linux_glimp.c
Normal file
File diff suppressed because it is too large
Load Diff
186
codemp/unix/linux_joystick.c
Normal file
186
codemp/unix/linux_joystick.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
** 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;
|
||||
}
|
||||
|
||||
|
||||
29
codemp/unix/linux_local.h
Normal file
29
codemp/unix/linux_local.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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);
|
||||
4132
codemp/unix/linux_qgl.c
Normal file
4132
codemp/unix/linux_qgl.c
Normal file
File diff suppressed because it is too large
Load Diff
237
codemp/unix/linux_snd.c
Normal file
237
codemp/unix/linux_snd.c
Normal file
@@ -0,0 +1,237 @@
|
||||
#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 "../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 };
|
||||
|
||||
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
|
||||
|
||||
if (!dma.buffer)
|
||||
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
|
||||
* info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
|
||||
|
||||
if (!dma.buffer) {
|
||||
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)
|
||||
{
|
||||
}
|
||||
75
codemp/unix/snapvector.nasm
Normal file
75
codemp/unix/snapvector.nasm
Normal file
@@ -0,0 +1,75 @@
|
||||
;
|
||||
; 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
|
||||
1164
codemp/unix/unix_main.c
Normal file
1164
codemp/unix/unix_main.c
Normal file
File diff suppressed because it is too large
Load Diff
599
codemp/unix/unix_net.c
Normal file
599
codemp/unix/unix_net.c
Normal file
@@ -0,0 +1,599 @@
|
||||
// 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,(socklen_t*) &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;
|
||||
}
|
||||
*/
|
||||
//we only look at class C since ISPs and Universities are using class A but we don't want to consider them on the same LAN.
|
||||
// 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;
|
||||
|
||||
// Set this early so we can just return if there is an error
|
||||
numIP = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 );
|
||||
numIP++;
|
||||
}
|
||||
}
|
||||
#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, (sockaddr *)&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);
|
||||
}
|
||||
|
||||
350
codemp/unix/unix_shared.c
Normal file
350
codemp/unix/unix_shared.c
Normal file
@@ -0,0 +1,350 @@
|
||||
#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"
|
||||
|
||||
typedef unsigned short DWORD;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// 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];
|
||||
|
||||
//DWORD timeGetTime(void)
|
||||
//{
|
||||
// return Sys_Milliseconds();
|
||||
//}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_Milliseconds
|
||||
================
|
||||
*/
|
||||
int curtime;
|
||||
int sys_timeBase;
|
||||
int Sys_Milliseconds (bool baseTime)
|
||||
{
|
||||
struct timeval tp;
|
||||
struct timezone tzp;
|
||||
|
||||
gettimeofday(&tp, &tzp);
|
||||
|
||||
if (!sys_timeBase)
|
||||
{
|
||||
sys_timeBase = tp.tv_sec;
|
||||
return tp.tv_usec/1000;
|
||||
}
|
||||
|
||||
curtime = (tp.tv_sec - sys_timeBase)*1000 + tp.tv_usec/1000;
|
||||
|
||||
static int sys_timeBase = curtime;
|
||||
if (!baseTime)
|
||||
{
|
||||
curtime -= sys_timeBase;
|
||||
}
|
||||
|
||||
return curtime;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//#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_SnapVector3( 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 = (char **)Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ),TAG_FILESYS,qfalse );
|
||||
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 = (char **)Z_Malloc( ( nfiles + 1 ) * sizeof( *listCopy ),TAG_FILESYS,qfalse );
|
||||
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), "/.jkii");
|
||||
#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;
|
||||
}
|
||||
8
codemp/unix/vm_x86.c
Normal file
8
codemp/unix/vm_x86.c
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
#include "../qcommon/vm_local.h"
|
||||
|
||||
void VM_Compile( vm_t *vm, vmHeader_t *header ) {}
|
||||
int VM_CallCompiled( vm_t *vm, int *args ) {}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user