t2 engine svn checkout

This commit is contained in:
loop 2024-01-07 04:36:33 +00:00
commit ff569bd2ae
988 changed files with 394180 additions and 0 deletions

350
platformLinux/async.c Normal file
View file

@ -0,0 +1,350 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <pthread.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include "async.h"
/*#define ASYNC_DEBUG*/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define MAX_FDS 128
typedef struct {
int fd; /* file descriptor */
AsyncCallback callback; /* callback per endpoint */
int mask; /* event mask for fd */
} assoc_t;
typedef struct {
fd_set read_fds;
fd_set write_fds;
fd_set except_fds;
/* consider changing to map<fd,assoc_t> */
assoc_t endpoints[MAX_FDS];
int num_endpoints;
int high_fd;
} thread_data_t;
static pthread_mutex_t data_mutex;
static pthread_t thread;
static int thread_running;
static thread_data_t thread_data;
static assoc_t *search_endpoint( int fd )
{
int i;
assoc_t* ret = NULL;
pthread_mutex_lock( &data_mutex );
for( i = 0; i < thread_data.num_endpoints; i++ ) {
if( thread_data.endpoints[i].fd == fd ) {
ret = &thread_data.endpoints[i];
break;
}
}
pthread_mutex_unlock( &data_mutex );
return ret;
}
static void do_callback( assoc_t* assoc, int fd, int event, int status )
{
if( assoc->callback ) {
assoc->callback( fd, event, status );
}
}
static void* select_thread( void* data )
{
fd_set read_fds, write_fds, except_fds;
int high, fd;
/* shut up compiler */
data = data;
#ifdef ASYNC_DEBUG
fprintf( stderr, "entering select_thread\n" );
#endif
while( thread_running ) {
struct timeval tv;
int active;
pthread_mutex_lock( &data_mutex );
/* copy? */
read_fds = thread_data.read_fds;
write_fds = thread_data.write_fds;
except_fds = thread_data.except_fds;
high = thread_data.high_fd + 1;
/* unlock here => guarded copy? */
pthread_mutex_unlock( &data_mutex );
/* FIXME: 10 ms timeout? */
tv.tv_sec = 0;
tv.tv_usec = 10000;
active = select( high, &read_fds, &write_fds, &except_fds, &tv );
if( active == -1 ) {
/* Don't bother printing a message here...
perror( "select_thread(): select()" );
*/
continue;
}
if( active == 0 ) {
continue;
}
/* FIXME:
* starting at 0? is this *completely* braindead? why don't
* we just iterate over the values in endpoints[i].fd?
* /me wants the STL map :(
*/
for( fd = 0; fd < high; fd++ ) {
assoc_t* assoc;
assoc = search_endpoint( fd );
if( !assoc ) {
continue;
}
if( FD_ISSET( fd, &read_fds ) ) {
if( assoc->mask & FD_ACCEPT ) {
#ifdef ASYNC_DEBUG
fprintf( stderr, "fd %d is set for accepting\n", fd );
#endif
do_callback( assoc, fd, FD_ACCEPT, 1 );
} else {
if( assoc->mask & FD_CONNECT ) {
#ifdef ASYNC_DEBUG
fprintf( stderr, "fd %d is set for reading, but is waiting\n", fd );
#endif
} else {
int amount;
#ifdef ASYNC_DEBUG
fprintf( stderr, "fd %d is set for reading\n", fd );
#endif
if( ioctl( fd, FIONREAD, &amount ) == -1 ) {
perror( "select_thread(): ioctl()" );
continue;
}
if( !amount ) {
if( assoc->mask & FD_CLOSE ) {
/* Ie, do we want to hear about FD_CLOSE? */
/* ECONNRESET? */
do_callback( assoc, fd, FD_CLOSE, 1 );
}
} else {
do_callback( assoc, fd, FD_READ, 1 );
}
}
}
}
if( FD_ISSET( fd, &write_fds ) ) {
/* data is ready to be written to the socket */
if( assoc->mask & FD_CONNECT ) {
int error = 0;
socklen_t error_size = sizeof( error );
int status = 1;
if( getsockopt( fd, SOL_SOCKET, SO_ERROR, &error, &error_size ) == -1 ) {
perror( "select_thread(): getsockopt()" );
}
if( error ) {
status = 0;
}
#ifdef ASYNC_DEBUG
fprintf( stderr, "fd %d is set for connect with status %d\n", fd, status );
#endif
assoc->mask &= ~(FD_CONNECT);
do_callback( assoc, fd, FD_CONNECT, status );
} else {
#ifdef ASYNC_DEBUG
fprintf( stderr, "fd %d is set for writing\n", fd );
#endif
do_callback( assoc, fd, FD_WRITE, 1 );
/* to prevent checking for it repeatedly */
pthread_mutex_lock( &data_mutex );
FD_CLR( fd, &( thread_data.write_fds ) );
pthread_mutex_unlock( &data_mutex );
}
}
if( FD_ISSET( fd, &except_fds ) ) {
/* exception on the socket, OOB data */
do_callback( assoc, fd, FD_OOB, 1 );
}
} /* for all our fds */
} /* while thread_running */
#ifdef ASYNC_DEBUG
fprintf( stderr, "leaving select_thread\n" );
#endif
return NULL;
}
int AsyncCancel( int fd )
{
int i = 0;
pthread_mutex_lock( &data_mutex );
if( thread_data.num_endpoints <= 0 ) {
pthread_mutex_unlock( &data_mutex );
return -1;
}
FD_CLR( fd, &thread_data.read_fds );
FD_CLR( fd, &thread_data.write_fds );
FD_CLR( fd, &thread_data.except_fds );
for( i = 0; i < thread_data.num_endpoints && thread_data.endpoints[i].fd != fd; i++ ) {
/* spin */
}
if( i == thread_data.num_endpoints ) {
/* we didn't find it */
pthread_mutex_unlock( &data_mutex );
return -1;
}
thread_data.num_endpoints--;
for( ; i < thread_data.num_endpoints; i++ ) {
thread_data.endpoints[i] = thread_data.endpoints[ i + 1 ];
}
assert( thread_data.num_endpoints >= 0 );
pthread_mutex_unlock( &data_mutex );
return 0;
}
int AsyncSelect( int fd, AsyncCallback callback, int mask )
{
int waiting, listening;
pthread_mutex_lock( &data_mutex );
if( thread_data.num_endpoints >= MAX_FDS ) {
pthread_mutex_unlock( &data_mutex );
return -1;
}
waiting = ( mask & FD_CONNECT ) ? 1 : 0;
listening = ( mask & FD_ACCEPT ) ? 1 : 0;
thread_data.endpoints[thread_data.num_endpoints].fd = fd;
thread_data.endpoints[thread_data.num_endpoints].callback = callback;
/* this will copy over FD_CLOSE, etc. */
thread_data.endpoints[thread_data.num_endpoints].mask = mask;
thread_data.num_endpoints++;
#ifdef ASYNC_DEBUG
fprintf( stderr, "added fd %d (%d/%d), %d total\n", fd, waiting,
listening, thread_data.num_endpoints );
#endif
if( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) < 0 ) {
perror( "AsyncSelect(): fcntl()" );
return -1;
}
if( fd > thread_data.high_fd ) {
thread_data.high_fd = fd;
}
if( mask & FD_READ || mask & FD_ACCEPT ) {
FD_SET( fd, &thread_data.read_fds );
}
if( mask & FD_WRITE || mask & FD_CONNECT ) {
FD_SET( fd, &thread_data.write_fds );
}
if( mask & FD_OOB ) {
FD_SET( fd, &thread_data.except_fds );
}
pthread_mutex_unlock( &data_mutex );
return 0;
}
int AsyncShutdown( void )
{
thread_running = FALSE;
pthread_join( thread, 0 );
pthread_mutex_destroy( &data_mutex );
return 0;
}
int AsyncInit( void )
{
pthread_mutex_init( &data_mutex, 0 );
thread_running = TRUE;
FD_ZERO( &thread_data.read_fds );
FD_ZERO( &thread_data.write_fds );
FD_ZERO( &thread_data.except_fds );
thread_data.high_fd = 0;
thread_data.num_endpoints = 0;
if( pthread_create( &thread, 0, select_thread, 0 ) < 0 ) {
perror( "AsyncInit(): pthread_create()" );
return -1;
}
return 0;
}

34
platformLinux/async.h Normal file
View file

@ -0,0 +1,34 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _ASYNC_H_
#define _ASYNC_H_
#ifdef __cplusplus
extern "C" {
#endif
#define FD_READ 0x0001
#define FD_WRITE 0x0002
#define FD_OOB 0x0004
#define FD_ACCEPT 0x0008
#define FD_CONNECT 0x0010
#define FD_CLOSE 0x0020
typedef int (*AsyncCallback)( int fd, int event, int status );
extern int AsyncInit( void );
extern int AsyncShutdown( void );
extern int AsyncCancel( int fd );
extern int AsyncSelect( int fd, AsyncCallback callback, int mask );
#ifdef __cplusplus
}
#endif
#endif

3574
platformLinux/audio.cc Normal file

File diff suppressed because it is too large Load diff

1126
platformLinux/blender.asm Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
#!/usr/bin/perl
#
# This is a script to read a Visual C++ object file and convert the calls
$len = sysread(STDIN, $data, 100000);
$data =~ s/POW/pow/;
$data =~ s/ACOS/acos/;
$data =~ s/\xE8\x00\x00\x00\x00/\xE8\xFC\xFF\xFF\xFF/g;
syswrite(STDOUT, $data, $len);

335
platformLinux/linuxAL.cc Normal file
View file

@ -0,0 +1,335 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformAL.h"
#include "console/console.h"
#include "Core/fileio.h"
#include <stdio.h>
ALuint alBufferSyncData_EXT(ALuint bid,
ALenum format,
ALvoid *data,
ALsizei size,
ALsizei frequency)
{
ALuint r = 0;
// alBufferData doesn't return a value,
// so clear the error setting, execute,
// and check again.
alGetError( );
alBufferData(bid, format, data, size, frequency);
if( alGetError( ) == AL_NO_ERROR ) {
// let AL manage the memory
dFree( data );
r = 1;
}
return r;
}
typedef struct fakeCallbackPair_s {
U32 sid;
void (*proc)(U32, bool);
} fakeCallbackPair_t;
static Vector< fakeCallbackPair_t > fakeCallbackFake(__FILE__, __LINE__);
void alxFakeCallbackUpdate( void )
{
fakeCallbackPair_t pi;
ALuint state;
int i;
i = fakeCallbackFake.size();
while( i-- ) {
pi = fakeCallbackFake.last();
fakeCallbackFake.pop_back();
state = AL_INITIAL;
alGetSourcei( pi.sid, AL_SOURCE_STATE, &state );
if( state == AL_STOPPED )
{
pi.proc( pi.sid, false );
Con::printf( "Calling callback for %d", pi.sid);
} else {
fakeCallbackFake.push_front( pi );
}
}
return;
}
void alSourceCallback_EXT(ALuint sid, void (*dummy)(U32, bool))
{
fakeCallbackPair_t pusher;
if( alIsSource( sid ) == AL_FALSE) {
Con::errorf(ConsoleLogEntry::General,
"alSourceCallback_EXT: %d not a source id", sid );
return;
}
pusher.sid = sid;
pusher.proc = dummy;
Con::printf( "adding Faker sid %d", sid);
fakeCallbackFake.push_back( pusher );
return;
}
ALuint alBufferStreamFile_EXT( ALuint bid, const ALubyte* filename )
{
static ALboolean (*LoadMP3)(ALuint bid, ALvoid *data, ALint size) = NULL;
#define GP(x) alGetProcAddress((const ALubyte *) x)
if(LoadMP3 == NULL) {
LoadMP3 = (ALboolean (*)(ALuint, ALvoid *, ALint)) GP("alutLoadMP3_LOKI");
if(LoadMP3 == NULL) {
Con::warnf( ConsoleLogEntry::General,
"could not get alutLoadMP3_LOKI, no mp3 support" );
}
}
#undef GP
File file;
file.open( (const char*) filename, File::Read );
if( file.getStatus( ) != File::Ok ) {
return AL_FALSE;
}
U32 size = file.getSize( );
char* data = (char*) dMalloc( size );
if( data == NULL ) {
// technically, 'file' will go out of scope and
// close itself, but still...
file.close( );
return AL_FALSE;
}
file.read( size, data );
if( file.getStatus( ) != File::Ok ) {
file.close( );
dFree( data );
return AL_FALSE;
}
U32 ext = dStrlen( filename );
ext -= 3;
ext = ( ext >= 0 ) ? ext : 0;
ALuint err = AL_FALSE;
if( dStrnicmp( &filename[ ext ], "mp3", 3 ) != 0 ) {
alGetError();
alBufferData( bid, AL_FORMAT_WAVE_EXT, data, size, 0 );
err = (alGetError() == AL_NO_ERROR);
} else {
if( LoadMP3 ) {
err = LoadMP3( bid, data, size );
} else {
Con::warnf( ConsoleLogEntry::General,
"cannot load MP3 file, no mp3 support present" );
err = AL_FALSE;
}
}
dFree( data );
file.close( );
if( err == AL_FALSE ) {
Con::warnf( ConsoleLogEntry::General,
"could not buffer and convert MP3 file" );
return AL_FALSE;
}
return AL_TRUE;
}
static void *context_id;
static ALCdevice *dev;
extern void alutInitFake( int *argc, char *argv[] )
{
char devstr_buf[1024];
const char *devstr;
const char *paren;
int refresh, frequency;
ALint attrlist[5];
// Get some basic configuration variables
refresh = Con::getIntVariable( "$pref::Audio::refresh", 15 );
frequency = Con::getIntVariable( "$pref::Audio::frequency", 22050 );
// Open the audio device
devstr = Con::getVariable("$pref::OpenAL::driver");
if ( devstr && ((paren=strrchr(devstr, ')')) != NULL) ) {
// Make sure a sane sampling rate is specified
if ( strstr(devstr, "sampling-rate") == NULL ) {
strcpy(devstr_buf, devstr);
sprintf(&devstr_buf[paren-devstr],
" (sampling-rate %d ))", frequency);
devstr = devstr_buf;
}
} else {
sprintf(devstr_buf, "'( (sampling-rate %d ))", frequency);
devstr = devstr_buf;
}
dev = alcOpenDevice( (const ALubyte *) devstr );
// If there's no audio, use a null device
if( dev == NULL ) {
const char *nulldev = "'( ( devices '( null )))";
dev = alcOpenDevice( (const ALubyte *) nulldev );
}
if( dev == NULL ) {
Con::errorf( ConsoleLogEntry::General, "Audio device open failed, exiting..." );
Platform::forceShutdown( 1 );
return;
}
attrlist[0] = ALC_FREQUENCY;
attrlist[1] = frequency;
attrlist[2] = ALC_REFRESH;
attrlist[3] = refresh;
attrlist[4] = 0;
context_id = alcCreateContext( dev, attrlist );
if( context_id == NULL ) {
Con::errorf( ConsoleLogEntry::General, "Audio context creation failed, exiting..." );
Platform::forceShutdown( 1 );
return;
}
alcMakeContextCurrent( context_id );
// Set the distance attenuation model
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
return;
}
extern void alutExitFake( void )
{
if( context_id == NULL ) {
return;
}
alcDestroyContext( context_id );
alcCloseDevice( dev );
return;
}
void alBufferi_EXT( ALuint bid, ALenum pname, ALint value )
{
// ignore
}
void alContexti_EXT( ALenum pname, ALint value )
{
// ignore.
}
void alGetContexti_EXT( ALenum pname, ALint* value )
{
if( !value ) {
return;
}
switch( pname ) {
case ALC_PROVIDER:
*value = 0;
break;
case ALC_PROVIDER_COUNT:
*value = 1;
break;
case ALC_SPEAKER:
*value = 0;
break;
case ALC_SPEAKER_COUNT:
*value = 1;
break;
case ALC_BUFFER_MEMORY_USAGE:
*value = 0;
break;
case ALC_BUFFER_MEMORY_SIZE:
*value = 1 << 16;
break;
case ALC_BUFFER_MEMORY_COUNT:
*value = 0;
break;
case ALC_BUFFER_COUNT:
*value = 0;
break;
default:
// error
break;
}
}
void alGetContextstr_EXT( ALenum pname, ALuint idx, ALubyte** value )
{
if( !value ) {
return;
}
switch( pname ) {
case ALC_PROVIDER_NAME:
*value = "Loki Software, Inc.";
break;
case ALC_SPEAKER_NAME:
*value = "Stereo, 2-Speaker";
break;
default:
// error
break;
}
}
void alGetEnvironmentiIASIG_EXT( ALuint eid, ALenum param, ALint * value )
{
// Nothing we can do here yet...
}
void alGetEnvironmentfIASIG_EXT( ALuint eid, ALenum param, ALfloat * value )
{
// Nothing we can do here yet...
}
void alSourceResetEnvironment_EXT( ALuint source )
{
// Nothing we can do here yet...
}

View file

@ -0,0 +1,246 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformAL.h"
#include "platformLinux/platformLinux.h"
#include "Platform/platformAudio.h"
static const AudioEnvironment *mCurrentEnvironment; // the last environment set
void* alGetProcAddress( const ALubyte* )
{
return 0;
}
ALenum alGetError( ALvoid )
{
return AL_NO_ERROR;
}
void alGetSourceiv( ALuint sid, ALenum param, ALint* value )
{
// empty
}
ALboolean alIsBuffer( ALuint bid )
{
return AL_FALSE;
}
void alGenBuffers( ALsizei n, ALuint* samples )
{
// empty
}
void alDeleteBuffers( ALsizei n, ALuint* samples )
{
// empty
}
void alListeneriv( int pname, int value )
{
// empty
}
ALboolean alIsSource( ALuint sid )
{
return AL_FALSE;
}
void alBufferData( ALuint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )
{
// emtpy
}
void alDistanceModel( ALenum distanceModel )
{
// empty
}
ALCdevice* alcOpenDevice( const ALubyte* s )
{
return 0;
}
ALvoid* alcCreateContext( ALCdevice* c, ALint* a )
{
return 0;
}
ALCenum alcMakeContextCurrent( ALvoid* c )
{
return AL_FALSE;
}
ALCenum alcDestroyContext( ALvoid* c )
{
return AL_FALSE;
}
void alcCloseDevice( ALCdevice* d )
{
// empty
}
namespace Audio {
void init( void ) {
// empty
}
void destroy( void ) {
// empty
}
}
AUDIOHANDLE alxCreateSource( const Audio::Description* descObject,
const char* filename,
const MatrixF* transform,
EffectDescription* effect,
AudioSampleEnvironment* sampleEnvironment )
{
// empty
return 0;
}
AUDIOHANDLE alxCreateSource( AudioDescription* descObject,
const char* filename,
const MatrixF* transform,
EffectDescription* effect,
AudioSampleEnvironment* sampleEnvironment )
{
// empty
return 0;
}
AUDIOHANDLE alxCreateSource( const AudioProfile* profile, const MatrixF* transform )
{
// empty
return 0;
}
ALuint alxFindSource( AUDIOHANDLE handle )
{
// empty
return 0;
}
bool alxIsPlaying(AUDIOHANDLE handle)
{
// empty
return(false);
}
ALuint alxGetWaveLen( ALuint buffer )
{
// empty
return 0;
}
void alxStop( AUDIOHANDLE handle )
{
// empty
}
AUDIOHANDLE alxPlay( AUDIOHANDLE handle )
{
// empty
return 0;
}
AUDIOHANDLE alxPlay( const AudioProfile* profile, const MatrixF* transform, const Point3F* velocity )
{
// empty
return 0;
}
void alxSourcef( AUDIOHANDLE handle, ALenum pname, ALfloat value )
{
// empty
}
void alxSourcefv( AUDIOHANDLE handle, ALenum pname, ALfloat* values )
{
// empty
}
void alxSource3f( AUDIOHANDLE handle, ALenum pname, ALfloat value1, ALfloat value2, ALfloat value3 )
{
// empty
}
void alxSourcei( AUDIOHANDLE handle, ALenum pname, ALint value )
{
// empty
}
void alxGetSourcefv( AUDIOHANDLE handle, ALenum pname, ALfloat* values )
{
// empty
}
void alxGetSourcei( AUDIOHANDLE handle, ALenum pname, ALint* value )
{
// empty
}
void alxSourceMatrixF( AUDIOHANDLE handle, const MatrixF* transform )
{
// empty
}
void alxListenerMatrixF( const MatrixF* transform )
{
// empty
}
void alxListener3f( ALenum pname, ALfloat x, ALfloat y, ALfloat z )
{
// empty
}
void alxGetListener3f(ALenum pname, ALfloat *value1, ALfloat *value2, ALfloat *value3)
{
// empty
}
void alxEnvironmentf(ALenum pname, ALfloat value)
{
// empty
}
void alxSetEnvironment(const AudioEnvironment * env)
{
mCurrentEnvironment = env;
}
const AudioEnvironment * alxGetEnvironment()
{
return(mCurrentEnvironment);
}
void alxUpdate( )
{
// empty
}
struct SimVoiceStreamEvent;
struct SimVoiceEvent;
void alxReceiveVoiceStream( SimVoiceStreamEvent* event )
{
// empty
}
void alxReceiveVoiceEvent( SimVoiceEvent* event )
{
// empty
}

View file

@ -0,0 +1,327 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "terrain/terrData.h"
#include "Math/mMath.h"
#include "dgl/dgl.h"
#include "dgl/gBitmap.h"
#include "terrain/terrRender.h"
void terrMipBlit_asm( U16* dest, U32 destStride, U32 squareSize,
const U8* sourcePtr, U32 sourceStep, U32 sourceRowAdd )
{
#if 0
for( U32 k = 0; k < squareSize; k++ ) {
for( U32 l = 0; l < squareSize; l++ ) {
dest[l] = *( (U16*) sourcePtr );
sourcePtr += sourceStep;
}
dest -= destStride;
sourcePtr += sourceRowAdd;
}
#endif
if( sourceStep == 2 ) {
destStride <<= 1;
sourceRowAdd += squareSize << 1;
__asm__ __volatile__( "pushl %%eax \n\t"
"pushl %%ebx \n\t"
"pushl %%ecx \n\t"
"pushl %%edx \n\t"
"pushl %%edi \n\t"
"pushl %%esi \n\t"
" \n\t"
"movl %0, %%edx \n\t"
"movl %1, %%edi \n\t"
"movl %2, %%esi \n\t"
"shrl $1, %%edx \n\t"
"movl $0, %%ecx \n\t"
"movl $0, %%ebx \n\t"
" \n"
"pixelLoop2: \n\t"
"movl (%%esi,%%ebx,4), %%eax \n\t"
"movl %%eax, (%%edi,%%ebx,4) \n\t"
"incl %%ebx \n\t"
"cmpl %%edx, %%ebx \n\t"
"jnz pixelLoop2 \n\t"
" \n\t"
"movl $0, %%ebx \n\t"
"incl %%ecx \n\t"
"subl %3, %%edi \n\t"
"addl %4, %%esi \n\t"
"cmpl %5, %%ecx \n\t"
"jl pixelLoop2 \n\t"
" \n\t"
"popl %%esi \n\t"
"popl %%edi \n\t"
"popl %%edx \n\t"
"popl %%ecx \n\t"
"popl %%ebx \n\t"
"popl %%eax \n\t"
: /* no outputs */
: "g" (squareSize ), "g" (dest), "g" (sourcePtr),
"g" (destStride), "g" (sourceRowAdd), "g" (squareSize)
: "eax", "ebx", "ecx", "edx", "edi", "esi", "cc", "memory" );
} else if( sourceStep == -2 ) {
destStride <<= 1;
__asm__ __volatile__( "pushl %%eax \n\t"
"pushl %%ebx \n\t"
"pushl %%ecx \n\t"
"pushl %%edx \n\t"
"pushl %%edi \n\t"
"pushl %%esi \n\t"
" \n\t"
"movl %0, %%edx \n\t"
"movl %1, %%edi \n\t"
"movl %2, %%esi \n\t"
"shrl $1, %%edx \n\t"
"movl $0, %%ecx \n\t"
"movl $0, %%ebx \n\t"
" \n"
"pixelLoopNeg2: \n\t"
"movl -2(%%esi), %%eax \n\t"
"subl $4, %%esi \n\t"
"rorl $16, %%eax \n\t"
"movl %%eax, (%%edi,%%ebx,$4) \n\t"
"incl %%ebx \n\t"
"cmpl %%edx, %%ebx \n\t"
"jnz pixelLoopNeg2 \n\t"
" \n\t"
"movl $0, %%ebx \n\t"
"incl %%ecx \n\t"
"subl %3, %%edi \n\t"
"addl %4, %%esi \n\t"
"cmpl %5, %%ecx \n\t"
"jl pixelLoopNeg2 \n\t"
" \n\t"
"popl %%esi \n\t"
"popl %%edi \n\t"
"popl %%edx \n\t"
"popl %%ecx \n\t"
"popl %%ebx \n\t"
"popl %%eax \n\t"
: /* no outputs */
: "g" (squareSize), "g" (dest), "g" (sourcePtr),
"g" (destStride), "g" (sourceRowAdd), "g" (squareSize)
: "eax", "ebx", "ecx", "edx", "esi", "edi", "cc", "memory" );
} else {
destStride = ( destStride + squareSize ) << 1;
__asm__ __volatile__( "pushl %%eax \n\t"
"pushl %%ebx \n\t"
"pushl %%ecx \n\t"
"pushl %%edx \n\t"
"pushl %%edi \n\t"
"pushl %%esi \n\t"
" \n\t"
"movl %0, %%eax \n\t"
"movl %1, %%edi \n\t"
"movl %2, %%esi \n\t"
"leal (%%edi,%%eax,$2), %%edx \n\t"
"movl $0, %%ecx \n\t"
"movl %3, %%ebx \n\t"
" \n"
"pixelLoop: \n\t"
"movw (%%esi,%%ebx), %%ax \n\t"
"shll $16, %%eax \n\t"
"addl $4, %%edi \n\t"
"movw (%%esi), %%ax \n\t"
"leal (%%esi,%%ebx,$2), %%esi \n\t"
"movl %%eax, -4(%%edi) \n\t"
"cmpl %%edx, %%edi \n\t"
"jnz pixelLoop \n\t"
" \n\t"
"incl %%ecx \n\t"
"subl %4, %%edi \n\t"
"movl %0, %%eax \n\t"
"addl %5, %%esi \n\t"
"leal (%%edi,%%eax,$2), %%edx \n\t"
"cmpl %4, %%ecx \n\t"
"jl pixelLoop \n\t"
" \n\t"
"popl %%esi \n\t"
"popl %%edi \n\t"
"popl %%edx \n\t"
"popl %%ecx \n\t"
"popl %%ebx \n\t"
"popl %%eax \n\t"
: /* no outputs */
: "g" (squareSize), "g" (dest), "g" (sourcePtr),
"g" (sourceStep), "g" (destStride), "g" (sourceRowAdd)
: "eax", "ebx", "ecx", "edx", "esi", "edi", "cc", "memory" );
}
}
void bitmapExtrude5551_asm( const void* srcMip, void* mip, U32 height, U32 width )
{
const U16* src = static_cast<const U16*>( srcMip );
U16* dst = static_cast<U16*>( mip );
U32 stride = width << 1;
for( U32 y = 0; y < height; y++ ) {
for( U32 x = 0; x < width; x++ ) {
U32 a = src[0];
U32 b = src[1];
U32 c = src[stride];
U32 d = src[ stride + 1 ];
dst[x] = ( ( ( ( a >> 11 ) + ( b >> 11 ) + ( c >> 11 ) + ( d >> 11 ) ) >> 2 ) << 11 ) |
( ( ( ( ( a >> 6 ) & 0x1f ) + ( ( b >> 6 ) & 0x1f ) + ( ( c >> 6 ) & 0x1f ) +
( ( d >> 6 ) & 0x1F ) ) >> 2 ) << 6 ) |
( ( ( ( ( a >> 1 ) & 0x1F ) + ( ( b >> 1 ) & 0x1F ) + ( ( c >> 1 ) & 0x1f ) +
( ( d >> 1 ) & 0x1f ) ) >> 2 ) << 1 );
src += 2;
}
src += stride;
dst += width;
}
}
void bitmapExtrudeRGB_mmx( const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth )
{
if( srcHeight == 1 || srcWidth == 1 ) {
bitmapExtrudeRGB_c( srcMip, mip, srcHeight, srcWidth );
return;
}
U32 width = srcWidth >> 1;
U32 height = srcHeight >> 1;
if( width <= 1 ) {
bitmapExtrudeRGB_c( srcMip, mip, srcHeight, srcWidth );
return;
}
// now that we've taken care of our pathological cases...
U64 ZERO = 0;
const U8* src = static_cast<const U8*>( srcMip );
U8* dst = static_cast<U8*>( mip );
U32 srcStride = ( width << 1 ) * 3;
U32 dstStride = width * 3;
for( U32 y = 0; y < height; y++ ) {
__asm__ __volatile__( "movl %0, %%eax \n\t"
"movl %%eax, %%ebx \n\t"
"addl %1, %%ebx \n\t"
"movl %2, %%ecx \n\t"
"movl %3, %%edx \n\t"
" \n"
"0: \n\t"
" \n\t"
"punpcklbw (%%eax), %%mm0 \n\t"
"psrlw $8, %%mm0 \n\t"
" \n\t"
"punpcklbw 3(%%eax), %%mm1 \n\t"
"psrlw $8, %%mm1 \n\t"
"paddw %%mm1, %%mm0 \n\t"
" \n\t"
"punpcklbw (%%ebx), %%mm1 \n\t"
"psrlw $8, %%mm1 \n\t"
"paddw %%mm1, %%mm0 \n\t"
" \n\t"
"punpcklbw 3(%%ebx), %%mm1 \n\t"
"psrlw $8, %%mm1 \n\t"
"paddw %%mm1, %%mm0 \n\t"
" \n\t"
"psrlw $2, %%mm0 \n\t"
"packuswb %4, %%mm0 \n\t"
" \n\t"
"movd %%mm0, (%%ecx) \n\t"
"addl $6, %%eax \n\t"
"addl $6, %%ebx \n\t"
"addl $3, %%ecx \n\t"
"decl %%edx \n\t"
"jnz 0b \n\t"
: /* no outputs */
: "g" (src), "g" (srcStride), "g" (dst),
"g" (width), "m" (ZERO)
: "eax", "ebx", "ecx", "edx", "cc", "memory" );
src += srcStride + srcStride;
dst += dstStride;
}
__asm__ __volatile__( "emms \n\t" );
}
void bitmapConvertRGB_to_5551_mmx( U8*src, U32 pixels )
{
U64 MULFACT = 0x0008200000082000;
U64 REDBLUE = 0x00f800f800f800f8;
U64 GREEN = 0x0000f8000000f800;
U64 ALPHA = 0x0000000000010001;
U64 ZERO = 0x0000000000000000;
U32 evenPixels = pixels >> 1;
U32 oddPixels = pixels & 1;
U16* dst = reinterpret_cast<U16*>( src );
if( evenPixels ) {
__asm__ __volatile__( "movl %0, %%eax \n\t"
"movl %1, %%ebx \n\t"
"movl %2, %%edx \n\t"
" \n"
"pixel_loop2: \n\t"
"movd (%%eax), %%mm0 \n\t"
"movd 3(%%eax), %%mm1 \n\t"
"punpckldq %%mm1, %%mm0 \n\t"
"movq %%mm0, %%mm1 \n\t"
"pand %3, %%mm0 \n\t"
"pmaddwd %4, %%mm0 \n\t"
" \n\t"
"pand %5, %%mm1 \n\t"
"por %%mm1, %%mm0 \n\t"
"psrld $6, %%mm0 \n\t"
"packssdw %6, %%mm0 \n\t"
"pslld $1, %%mm0 \n\t"
"por %7, %%mm0 \n\t"
"movd %%mm0, (%%ebx) \n\t"
" \n\t"
"addl $6, %%eax \n\t"
"addl $4, %%ebx \n\t"
"decl %%edx \n\t"
"jnz pixel_loop2 \n\t"
" \n\t"
"movl %%eax, %0 \n\t"
"movl %%ebx, %1 \n\t"
"emms \n\t"
: /* no outputs */
: "g" (src), "g" (dst), "g" (evenPixels),
"m" (REDBLUE), "m" (MULFACT), "m" (GREEN),
"m" (ZERO), "m" (ALPHA)
: "eax", "ebx", "edx", "cc", "memory" );
}
if( oddPixels ) {
U32 r = src[0] >> 3;
U32 g = src[1] >> 3;
U32 b = src[2] >> 3;
*dst = ( b << 1 ) | ( g << 6 ) | ( r << 11 ) | 1;
}
}
void PlatformBlitInit( void )
{
bitmapExtrude5551 = bitmapExtrude5551_asm;
bitmapExtrudeRGB = bitmapExtrudeRGB_c;
if( Platform::SystemInfo.processor.properties & CPU_PROP_MMX ) {
bitmapExtrudeRGB = bitmapExtrudeRGB_mmx;
bitmapConvertRGB_to_5551 = bitmapConvertRGB_to_5551_mmx;
}
// Per 10/04/2000 change to PlatformWin32/linuxAsmBlit.cc
// terrMipBlit = terrMipBlit_asm;
}

View file

@ -0,0 +1,227 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <math.h>
#include "Platform/platform.h"
#include "platformLinux/platformLinux.h"
#include "console/console.h"
#include "Core/stringTable.h"
extern "C" cpu_init_ASM( char* vendor, unsigned int* processor, unsigned int* properties );
Platform::SystemInfo_struct Platform::SystemInfo;
void Processor::init( void )
{
Platform::SystemInfo.processor.type = CPU_X86Compatible;
Platform::SystemInfo.processor.name = StringTable->insert( "Unknown x86 Compatible" );
Platform::SystemInfo.processor.mhz = 0;
Platform::SystemInfo.processor.properties = CPU_PROP_C;
char vendor[13];
U32 properties = 0;
U32 processor = 0;
memset( vendor, 0, 13 );
enum {
BIT_FPU = 1,
BIT_RDTSC = 1 << 4,
BIT_MMX = 1 << 23,
BIT_SSE = 1 << 25,
BIT_3DNOW = 1 << 31
};
// when this code was previously inline, gcc would
// mysteriously optimize away the stores to properties, etc.
cpu_init_ASM( vendor, &processor, &properties );
Platform::SystemInfo.processor.properties |= ( properties & BIT_FPU ) ? CPU_PROP_FPU : 0;
Platform::SystemInfo.processor.properties |= ( properties & BIT_RDTSC ) ? CPU_PROP_RDTSC : 0;
Platform::SystemInfo.processor.properties |= ( properties & BIT_MMX ) ? CPU_PROP_MMX : 0;
if( dStricmp( vendor, "GenuineIntel" ) == 0 ) {
Platform::SystemInfo.processor.properties |= ( properties & BIT_SSE ) ? CPU_PROP_SSE : 0;
switch( processor & 0xf00 ) {
case 0x600:
switch( processor & 0xf0 ) {
case 0x10:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel Pentium Pro" );
break;
case 0x30:
case 0x50:
case 0x60:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel Pentium II" );
break;
case 0x70:
case 0x80:
case 0xa0:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumIII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel Pentium III" );
break;
default:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel (unknown, PPro family)" );
break;
}
break;
case 0x500:
Platform::SystemInfo.processor.type = CPU_Intel_Pentium;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel Pentium" );
break;
default:
Platform::SystemInfo.processor.type = CPU_Intel_Unknown;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel (unknown)" );
break;
}
} else if( dStricmp( vendor, "AuthenticAMD" ) == 0 ) {
Platform::SystemInfo.processor.properties |= ( properties & BIT_3DNOW ) ? CPU_PROP_3DNOW : 0;
switch( processor ) {
case 0x700:
case 0x710:
Platform::SystemInfo.processor.type = CPU_AMD_K7;
Platform::SystemInfo.processor.name = StringTable->insert( "AMD K7" );
break;
case 0x660:
case 0x670:
Platform::SystemInfo.processor.type = CPU_AMD_K6;
Platform::SystemInfo.processor.name = StringTable->insert( "AMD K6" );
break;
case 0x680:
Platform::SystemInfo.processor.type = CPU_AMD_K6_2;
Platform::SystemInfo.processor.name = StringTable->insert( "AMD K6-2" );
break;
case 0x690:
Platform::SystemInfo.processor.type = CPU_AMD_K6_3;
Platform::SystemInfo.processor.name = StringTable->insert( "AMD K6-3" );
break;
case 0x510:
case 0x520:
case 0x530:
Platform::SystemInfo.processor.type = CPU_AMD_K6_3;
Platform::SystemInfo.processor.name = StringTable->insert( "AMD K5" );
break;
default:
Platform::SystemInfo.processor.type = CPU_AMD_Unknown;
Platform::SystemInfo.processor.name = StringTable->insert( "AMD (unknown)" );
break;
}
} else if( dStricmp( vendor, "CyrixInstead" ) == 0 ) {
switch( processor ) {
case 0x520:
Platform::SystemInfo.processor.type = CPU_Cyrix_6x86;
Platform::SystemInfo.processor.name = StringTable->insert( "Cyrix 6x86" );
break;
case 0x440:
Platform::SystemInfo.processor.type = CPU_Cyrix_MediaGX;
Platform::SystemInfo.processor.name = StringTable->insert( "Cyrix Media GX" );
break;
case 0x600:
Platform::SystemInfo.processor.type = CPU_Cyrix_6x86MX;
Platform::SystemInfo.processor.name = StringTable->insert( "Cyrix 6x86mx/MII" );
break;
case 0x540:
Platform::SystemInfo.processor.type = CPU_Cyrix_GXm;
Platform::SystemInfo.processor.name = StringTable->insert( "Cyrix GXm" );
break;
default:
Platform::SystemInfo.processor.type = CPU_Cyrix_Unknown;
Platform::SystemInfo.processor.name = StringTable->insert( "Cyrix (unknown)" );
break;
}
}
if( Platform::SystemInfo.processor.properties & CPU_PROP_RDTSC &&
Platform::SystemInfo.processor.properties & CPU_PROP_FPU ) {
const U32 MS_INTERVAL = 750;
U32 timing[2];
U32 ticks = 0;
__asm__ __volatile__( "pushl %%eax \n\t"
"pushl %%edx \n\t"
"rdtsc \n\t"
"movl %%eax, (%0) \n\t"
"movl %%edx, 4(%0) \n\t"
"popl %%edx \n\t"
"popl %%eax \n\t"
: /* no outputs */
: "r" (timing)
: "eax", "edx", "cc", "memory" );
U32 ms = Platform::getRealMilliseconds( );
while( Platform::getRealMilliseconds ( ) < ms + MS_INTERVAL ) {
// empty
}
ms = Platform::getRealMilliseconds( ) - ms;
__asm__ __volatile__( "pushl %%eax \n\t"
"pushl %%edx \n\t"
"rdtsc \n\t"
"subl 4(%1), %%edx \n\t"
"sbbl (%1), %%eax \n\t"
"movl %%eax, %0 \n\t"
"popl %%edx \n\t"
"popl %%eax \n\t"
: "=g" (ticks)
: "r" (timing)
: "eax", "edx", "cc", "memory" );
U32 mhz = static_cast<F32>( ticks ) / static_cast<F32>( ms ) / 1000.0f;
U32 bucket25 = mhz % 25;
U32 bucket33 = mhz % 33;
U32 bucket50 = mhz % 50;
if( bucket50 < 8 || bucket50 > 42 ) {
Platform::SystemInfo.processor.mhz = static_cast<U32>( ( mhz + ( 50.0f / 2.0f ) ) / 50.0f ) * 50;
} else if( bucket25 < 5 || bucket25 > 20 ) {
Platform::SystemInfo.processor.mhz = static_cast<U32>( ( mhz + ( 25.0f / 2.0f ) ) / 25.0f ) * 25;
} else if( bucket33 < 5 || bucket33 > 28 ) {
Platform::SystemInfo.processor.mhz = static_cast<U32>( ( mhz + ( 33.0f / 2.0f ) ) / 33.0f ) * 33;
} else {
Platform::SystemInfo.processor.mhz = static_cast<U32>( mhz );
}
}
Con::printf( "Processor Init:" );
Con::printf( " %s, %d Mhz",
Platform::SystemInfo.processor.name,
Platform::SystemInfo.processor.mhz );
if( Platform::SystemInfo.processor.properties & CPU_PROP_FPU ) {
Con::printf( " FPU detected" );
}
if( Platform::SystemInfo.processor.properties & CPU_PROP_MMX ) {
Con::printf( " MMX detected" );
}
if( Platform::SystemInfo.processor.properties & CPU_PROP_3DNOW ) {
Con::printf( " 3DNow detected" );
}
if( Platform::SystemInfo.processor.properties & CPU_PROP_SSE ) {
Con::printf( " SSE detected" );
}
PlatformBlitInit( );
}

View file

@ -0,0 +1,64 @@
;
; CPU identification fun.
;
;
; void cpu_init_ASM( char* vendor, int* processor, int* properties )
;
%define in_vendor [ebp+8]
%define in_proc [ebp+12]
%define in_prop [ebp+16]
global cpu_init_ASM
cpu_init_ASM:
push ebp
mov ebp, esp
push ebx
push edx
push ecx
push esi
pushfd
pushfd
pop eax
mov ebx, eax
xor eax, 0x200000
push eax
popfd
pushfd
pop eax
cmp eax, ebx
jz .L1
xor eax, eax
cpuid
mov esi, in_vendor
mov dword [esi], ebx
mov dword [esi+4], edx
mov dword [esi+8], ecx
mov eax, 1
cpuid
and eax, 0x0ff0
mov esi, in_proc
mov [esi], eax
mov esi, in_prop
mov [esi], edx
.L1:
popfd
pop esi
pop ecx
pop edx
pop ebx
pop ebp
ret

View file

@ -0,0 +1,249 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <SDL/SDL.h>
#include "Platform/platform.h"
#include "Platform/event.h"
static KeyCodes SDLCodeMap0_127[] =
{
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_BACKSPACE, // 8
KEY_TAB, // 9
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_RETURN, // 13
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_PAUSE, // 19
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_ESCAPE, // 27
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_SPACE, // 32
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_APOSTROPHE, // 39
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_COMMA, // 44
KEY_MINUS, // 45
KEY_PERIOD,
KEY_SLASH,
KEY_0, // 48
KEY_1, // 49
KEY_2, // 50
KEY_3, // 51
KEY_4, // 52
KEY_5, // 53
KEY_6, // 54
KEY_7, // 55
KEY_8, // 56
KEY_9, // 57
KEY_NULL,
KEY_SEMICOLON, // 59
KEY_NULL,
KEY_EQUALS, // 61
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_LBRACKET, // 91
KEY_BACKSLASH, // 92
KEY_RBRACKET, // 93
KEY_NULL,
KEY_NULL,
KEY_TILDE,
KEY_A, // 97
KEY_B, // 98
KEY_C, // 99
KEY_D, // 100
KEY_E, // 101
KEY_F, // 102
KEY_G, // 103
KEY_H, // 104
KEY_I, // 105
KEY_J, // 106
KEY_K, // 107
KEY_L, // 108
KEY_M, // 109
KEY_N, // 110
KEY_O, // 111
KEY_P, // 112
KEY_Q, // 113
KEY_R, // 114
KEY_S, // 115
KEY_T, // 116
KEY_U, // 117
KEY_V, // 118
KEY_W, // 119
KEY_X, // 120
KEY_Y, // 121
KEY_Z, // 122
KEY_NULL, // 123
KEY_NULL, // 124
KEY_NULL, // 125
KEY_NULL, // 126
KEY_DELETE, // 127
};
static KeyCodes SDLCodeMap256_319[] =
{
KEY_NUMPAD0, // 256
KEY_NUMPAD1, // 257
KEY_NUMPAD2, // 258
KEY_NUMPAD3, // 259
KEY_NUMPAD4, // 260
KEY_NUMPAD5, // 261
KEY_NUMPAD6, // 262
KEY_NUMPAD7, // 263
KEY_NUMPAD8, // 264
KEY_NUMPAD9, // 265
KEY_DECIMAL, // 266
KEY_DIVIDE, // 267
KEY_MULTIPLY, // 268
KEY_SUBTRACT, // 269
KEY_ADD, // 270
KEY_NUMPADENTER, // 271
KEY_EQUALS, // 272
KEY_UP, // 273
KEY_DOWN, // 274
KEY_RIGHT, // 275
KEY_LEFT, // 276
KEY_INSERT,
KEY_HOME,
KEY_END,
KEY_PAGE_UP,
KEY_PAGE_DOWN,
KEY_F1, // 282
KEY_F2, // 283
KEY_F3, // 284
KEY_F4, // 285
KEY_F5, // 286
KEY_F6, // 287
KEY_F7, // 288
KEY_F8, // 289
KEY_F9, // 290
KEY_F10, // 291
KEY_F11, // 292
KEY_F12, // 293
KEY_F13, // 294
KEY_F14, // 295
KEY_F15, // 296
KEY_NULL,
KEY_NULL,
KEY_NULL,
KEY_NUMLOCK, // 300
KEY_CAPSLOCK, // 301
KEY_SCROLLLOCK, // 302
KEY_RSHIFT, // 303
KEY_LSHIFT, // 304
KEY_RCONTROL, // 305
KEY_LCONTROL, // 306
KEY_RALT, // 307
KEY_LALT, // 308
KEY_NULL,
KEY_NULL,
KEY_WIN_LWINDOW, // 311
KEY_WIN_RWINDOW, // 312
KEY_OEM_102, // 313
KEY_NULL,
KEY_HELP, // 315
KEY_PRINT, // 316
KEY_NULL,
KEY_NULL,
KEY_WIN_APPS, // 319
};
SDLKey translateKeyCodeToSDL( KeyCodes code )
{
for( S32 i = 0; i <= 127; i++ ) {
if( SDLCodeMap0_127[i] == code ) {
return (SDLKey) i;
}
}
for( S32 i = 256; i <= 319; i++ ) {
if( SDLCodeMap256_319[ i - 256 ] == code ) {
return (SDLKey) i;
}
}
return SDLK_UNKNOWN;
}
KeyCodes translateSDLToKeyCode( SDLKey sym )
{
S32 i_sym = static_cast<S32>( sym );
if( i_sym >= 0 && i_sym <= 127 ) {
return SDLCodeMap0_127[i_sym];
}
if( i_sym >= 256 && i_sym <= 319 ) {
i_sym -= 256;
return SDLCodeMap256_319[i_sym];
}
return KEY_NULL;
}

View file

@ -0,0 +1,573 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <sys/types.h>
#include <stdio.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include "platformLinux/platformLinux.h"
#include "platformLinux/linuxConsole.h"
#include "Platform/event.h"
#include "Platform/gameInterface.h"
#include "loki_utils.h"
LinuxConsole* linuxConsole = 0;
ConsoleFunction( enableWinConsole, void, 2, 2, "enableWinConsole(bool);" )
{
linuxConsole->enable( dAtob( argv[1] ) );
}
static void handle_sigwinch(int sig)
{
if ( linuxConsole ) {
linuxConsole->check_winsize();
}
}
void LinuxConsole::create( void )
{
linuxConsole = new LinuxConsole( );
signal(SIGWINCH, handle_sigwinch);
}
void LinuxConsole::destroy( void )
{
signal(SIGWINCH, SIG_DFL);
delete linuxConsole;
linuxConsole = 0;
}
static void linuxConsoleConsumer(ConsoleLogEntry::Level level, const char* line)
{
if ( linuxConsole ) {
linuxConsole->processConsoleLine( level, line );
}
}
LinuxConsole::LinuxConsole( void ) : console_enabled( false )
{
init_history();
Con::addConsumer( linuxConsoleConsumer );
}
LinuxConsole::~LinuxConsole( void )
{
enable(false);
free_history();
Con::removeConsumer( linuxConsoleConsumer );
}
// Terminal manipulation routines
void LinuxConsole::set_title(const char *title)
{
printf("\033]0;%s\07", title);
fflush(stdout);
}
void LinuxConsole::move_bol(void)
{
printf("\r");
}
void LinuxConsole::clear_eol(void)
{
printf("\033[K");
}
void LinuxConsole::clear_line(void)
{
move_bol();
clear_eol();
}
void LinuxConsole::move_to(int row, int col)
{
printf("\033[%d;%dH", row, col);
}
void LinuxConsole::move_back()
{
printf("\033[D");
}
void LinuxConsole::set_scroll(int hi, int lo, int col)
{
if ( ! hi && ! lo ) {
printf("\033[r");
} else {
printf("\033[%d;%dr", hi, lo);
move_to(lo, col);
}
}
void LinuxConsole::check_winsize(void)
{
const char *env;
struct /* winsize */ {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
} mywinz;
if ( ioctl(0, TIOCGWINSZ, &mywinz) == 0 ) {
if ( mywinz.ws_row )
rows = mywinz.ws_row;
if ( mywinz.ws_col )
cols = mywinz.ws_col;
}
if ( (env=getenv("LINES")) != NULL )
rows=atoi(env);
if ( (env=getenv("COLUMNS")) != NULL )
cols=atoi(env);
/* Now set defaults if we can't find the window size */
if ( ! rows ) rows=24;
if ( ! cols ) cols=80;
// Display the prompt
display_prompt();
}
void LinuxConsole::enable(bool enabled)
{
static struct termios saved_termios;
if ( enabled == console_enabled ) {
return;
}
console_enabled = enabled;
// Okay, if there's no terminal, we're done
if ( ! isatty(0) || ! isatty(1) ) {
return;
}
if ( enabled ) {
// Save the terminal settings and go raw
const char *title;
const char *env;
struct termios raw_termios;
struct fd_set fdset;
struct timeval timeout;
// Clear the input buffer
delete_line();
// Save the original terminal settings
tcgetattr(0, &saved_termios);
// Set the raw terminal settings
raw_termios = saved_termios;
raw_termios.c_iflag = IGNBRK;
raw_termios.c_oflag &= ~OLCUC;
raw_termios.c_lflag = ISIG;
raw_termios.c_cc[VMIN] = 0;
raw_termios.c_cc[VTIME] = 10;
tcsetattr(0, TCSADRAIN, &raw_termios);
// See if the terminal uses vt100 emulation
split_window = false;
printf("\033[c"); /* Vt100 test: ESC [ c */
fflush(stdout);
FD_ZERO( &fdset );
FD_SET( 0, &fdset );
timeout.tv_sec = 0;
timeout.tv_usec = 500*1000;
while ( select(1, &fdset, NULL, NULL, &timeout) == 1 ) {
char ch;
read(0, &ch, 1);
if ( ch == '\033' ) {
split_window = true;
}
timeout.tv_sec = 0;
timeout.tv_usec = 500*1000;
}
// Set up the split window if we can
rows = 0;
cols = 0;
if ( split_window ) {
check_winsize();
} else {
// No split window, do line-by-line input
tcsetattr(0, TCSADRAIN, &saved_termios);
}
// Try to set the xterm title bar
title = Con::getVariable("Con::WindowTitle");
if ( title && *title ) {
// See if the terminal uses xterm title
if ( ((env=getenv("TERM")) != NULL) &&
(dStrncmp(env, "xterm", 5) == 0) ) {
set_title(title);
}
}
} else {
// Clear the split window, if any
if ( split_window ) {
#ifdef VT100_SCROLL
set_scroll(0, 0, 0);
move_to(rows, 0);
clear_eol();
#else
printf("\n");
#endif
// Restore the terminal settings
tcsetattr(0, TCSADRAIN, &saved_termios);
}
}
}
void LinuxConsole::processConsoleLine( ConsoleLogEntry::Level level, const char* line )
{
char cleaned[256];
if ( isEnabled( ) ) {
// clean string--forums sometimes emit
// control characters which foo the terminal
dStrncpy( cleaned, line, 256 );
cleaned[255] = '\0';
int length = dStrlen( cleaned );
for( int i = 0; i < length; i++ ) {
if( !isprint( cleaned[i] ) ) {
cleaned[i] = ' ';
}
}
if ( split_window ) {
#ifdef VT100_SCROLL
const char *prompt = Con::getVariable("Con::Prompt");
set_scroll(1, rows-1, 0);
printf( "\n%s", cleaned );
set_scroll(rows-1, rows, dStrlen(prompt)+curpos+1);
#else
clear_line();
printf( "%s\n", cleaned );
display_prompt();
#endif
fflush(stdout);
} else {
printf( "%s\n", cleaned );
}
}
}
void LinuxConsole::forward_char(void)
{
if ( curpos < dStrlen(line) ) {
++curpos;
}
}
void LinuxConsole::backward_char(void)
{
if ( curpos > 0 ) {
--curpos;
}
}
void LinuxConsole::forward_eol(void)
{
curpos = dStrlen(line);
}
void LinuxConsole::backward_bol(void)
{
curpos = 0;
}
void LinuxConsole::backspace_char(void)
{
if ( curpos > 0 ) {
--curpos;
memcpy(&line[curpos], &line[curpos+1], sizeof(line)-curpos);
}
}
void LinuxConsole::delete_char(void)
{
memcpy(&line[curpos], &line[curpos+1], sizeof(line)-curpos);
}
void LinuxConsole::delete_eol(void)
{
memset(&line[curpos], 0, sizeof(line)-curpos);
}
void LinuxConsole::delete_line(void)
{
curpos = 0;
memset(line, 0, sizeof(line));
}
void LinuxConsole::insert_char(char ch)
{
if ( line[curpos] != '\0' ) {
memmove(&line[curpos+1],&line[curpos],(sizeof(line)-curpos-1));
}
replace_char(ch);
}
void LinuxConsole::replace_char(char ch)
{
line[curpos++] = ch;
}
void LinuxConsole::replace_line(const char *text)
{
delete_line();
if ( text ) {
strncpy(line, text, sizeof(line)-1);
curpos = dStrlen(line);
}
}
void LinuxConsole::init_history(void)
{
char histfile[PATH_MAX];
FILE *hfp;
memset(history, 0, sizeof(history));
current_history = 0;
// Load the history from our history file
sprintf(histfile, "%s/history.txt", loki_getprefpath());
hfp = fopen(histfile, "r");
if ( hfp ) {
while ( fgets(line, sizeof(line), hfp) ) {
line[dStrlen(line)-1] = '\0';
add_history(line);
incr_history();
}
fclose(hfp);
}
}
void LinuxConsole::add_history(const char *text)
{
if ( history[current_history] ) {
free(history[current_history]);
}
history[current_history] = dStrdup(text);
}
void LinuxConsole::incr_history(void)
{
++current_history;
if ( current_history == NUM_HISTORY ) {
current_history = 0;
}
}
void LinuxConsole::decr_history(void)
{
--current_history;
if ( current_history < 0 ) {
current_history += NUM_HISTORY;
}
}
void LinuxConsole::prev_history(void)
{
add_history(line);
decr_history();
replace_line(history[current_history]);
}
void LinuxConsole::next_history(void)
{
add_history(line);
incr_history();
replace_line(history[current_history]);
}
void LinuxConsole::free_history(void)
{
char histfile[PATH_MAX];
FILE *hfp;
// Save the history to our history file
sprintf(histfile, "%s/history.txt", loki_getprefpath());
hfp = fopen(histfile, "w");
if ( hfp ) {
int history_mark = current_history;
do {
if ( history[current_history] ) {
fprintf(hfp, "%s\n", history[current_history]);
}
incr_history();
} while ( current_history != history_mark );
fclose(hfp);
}
for ( S32 i=0; i<NUM_HISTORY; ++i ) {
if ( history[i] ) {
dFree(history[i]);
history[i] = 0;
}
}
}
void LinuxConsole::tab_complete(void)
{
const char *newtext;
newtext = Con::tabComplete(line, curpos, true);
if ( newtext ) {
int save_pos = curpos;
replace_line(newtext);
curpos = save_pos;
}
}
void LinuxConsole::display_prompt(void)
{
if ( split_window ) {
const char *prompt = Con::getVariable("Con::Prompt");
clear_line();
printf("%s%s", prompt, line);
#ifdef VT100_SCROLL
move_to(rows, dStrlen(prompt)+curpos+1);
#else
U32 maxpos = dStrlen(line);
for ( U32 i=(U32)curpos; i<maxpos; ++i ) {
move_back();
}
#endif
fflush(stdout);
}
}
#define toctrl(X) (X - '@')
void LinuxConsole::process( void )
{
char ch;
struct fd_set fdset;
struct timeval timeout;
static enum {
AT_RESET,
AT_ESCAPE,
AT_BRACKET
} arrow_state = AT_RESET;
FD_ZERO( &fdset );
FD_SET( 0, &fdset );
timeout.tv_sec = 0;
timeout.tv_usec = 0;
while ( isEnabled() && (select(1, &fdset, 0, 0, &timeout ) == 1) ) {
if ( read(0, &ch, 1) <= 0 ) {
break;
}
switch (ch) {
case toctrl('A'):
backward_bol();
break;
case toctrl('E'):
forward_eol();
break;
case toctrl('B'):
backward_char();
break;
case toctrl('F'):
forward_char();
break;
case '\0177':
case toctrl('H'):
backspace_char();
break;
case toctrl('D'):
delete_char();
break;
case toctrl('K'):
delete_eol();
break;
case toctrl('U'):
delete_line();
break;
case toctrl('P'):
prev_history();
break;
case toctrl('N'):
next_history();
break;
case toctrl('I'):
tab_complete();
break;
case '\r':
case '\n':
// Execute command
if ( curpos > 0 ) {
S32 eventSize;
add_history(line);
incr_history();
eventSize = ConsoleEventHeaderSize;
dStrcpy( postEvent.data, line );
postEvent.size = eventSize + dStrlen(line) + 1;
Game->postEvent( postEvent );
delete_line();
}
break;
// Add character to line
default:
{
if ( (ch == '\033') && (arrow_state == AT_RESET) ) {
arrow_state = AT_ESCAPE;
break;
} else
if ( (ch == '[') && (arrow_state == AT_ESCAPE) ) {
arrow_state = AT_BRACKET;
break;
} else if ( arrow_state == AT_BRACKET ) {
switch (ch) {
// Cursor up
case 'A':
prev_history();
break;
// Cursor down
case 'B':
next_history();
break;
// Cursor right
case 'C':
forward_char();
break;
// Cursor left
case 'D':
backward_char();
break;
// Unknown escape code
default:
break;
}
arrow_state = AT_RESET;
break;
}
arrow_state = AT_RESET;
if ( isprint(ch) && (curpos < (sizeof(line)-1)) ) {
insert_char(ch);
}
}
break;
}
display_prompt();
}
}

View file

@ -0,0 +1,80 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _LINUXCONSOLE_H_
#define _LINUECONSOLE_H_
#ifndef _CONSOLE_H_
#include "console/console.h"
#endif
#ifndef _EVENT_H_
#include "Platform/event.h"
#endif
#define NUM_HISTORY 32
class LinuxConsole
{
ConsoleEvent postEvent;
bool console_enabled;
bool split_window;
int rows, cols;
int curpos;
char line[1024];
char *history[NUM_HISTORY];
int current_history;
void set_title(const char *title);
void move_bol(void);
void clear_eol(void);
void clear_line(void);
void move_to(int row, int col);
void move_back(void);
void set_scroll(int hi, int lo, int col);
void forward_char(void);
void backward_char(void);
void forward_eol(void);
void backward_bol(void);
void backspace_char(void);
void delete_char(void);
void delete_eol(void);
void delete_line(void);
void insert_char(char ch);
void replace_char(char ch);
void replace_line(const char *text);
void init_history(void);
void add_history(const char *text);
void incr_history(void);
void decr_history(void);
void prev_history(void);
void next_history(void);
void free_history(void);
void tab_complete(void);
void display_prompt(void);
public:
LinuxConsole( void );
~LinuxConsole( void );
void enable( bool enabled );
bool isEnabled( void ) { return console_enabled; };
void process( void );
void processConsoleLine( ConsoleLogEntry::Level level, const char* line );
static void create( );
static void destroy( );
void check_winsize(void);
};
extern LinuxConsole* linuxConsole;
#endif

View file

@ -0,0 +1,853 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <regex.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "loki_utils.h"
#include "engine/platformLinux/platformLinux.h"
#include "engine/core/fileio.h"
#include "engine/core/tVector.h"
#include "engine/core/stringTable.h"
#include "engine/console/console.h"
static void build_canonical_name( const char* path, char* buffer, int size )
{
struct stat sb;
/* default value is identity */
strncpy( buffer, path, size );
buffer[size-1] = '\0';
/* Shortcut, most of the time the file name is fine */
if ( stat(buffer, &sb) != 0 ) {
char* r;
char *pathname;
char *filename;
DIR* dir;
struct dirent* de;
/* find the last slash */
pathname = buffer;
r = strrchr( pathname, '/' );
if( r ) {
*r = '\0';
filename = r+1;
}
/*
* Look for an existing name.
*/
dir = opendir( pathname );
if( dir ) {
while( ( de = readdir( dir ) ) != NULL ) {
if( strcasecmp( de->d_name, filename ) == 0 ) {
strncpy(filename, de->d_name, size-(strlen(pathname)+1));
break;
}
}
closedir( dir );
}
if ( r ) {
*r = '/';
}
}
}
int iopen( const char* path, int flags )
{
char buffer[PATH_MAX];
int fd = -1;
build_canonical_name( path, buffer, PATH_MAX );
fd = open( buffer, flags );
return fd;
}
FILE* ifopen( const char* path, const char* mode )
{
char buffer[PATH_MAX];
FILE* f = NULL;
build_canonical_name( path, buffer, PATH_MAX );
f = fopen( buffer, mode );
return f;
}
static void forwardSlash( char* s )
{
while( *s ) {
if( *s == '\\' ) {
*s = '/';
}
s++;
}
}
static bool copyFile(const char *src, const char *dst)
{
int status;
FILE *i, *o;
int len;
char data[BUFSIZ];
i = fopen(src, "rb");
o = fopen(dst, "wb");
if ( !i || !o ) {
if ( i ) {
fclose(i);
}
if ( o ) {
fclose(i);
}
return(0);
}
status = 0;
while ( (len = fread(data, 1, sizeof(data), i)) > 0 ) {
if ( fwrite(data, 1, len, o) != len ) {
status = -1;
break;
}
}
fclose(i);
if ( fclose(o) != 0 ) {
status = -1;
}
if ( status < 0 ) {
unlink(dst);
}
return(status == 0);
}
//-----------------------------------------------------------------------------
bool dFileDelete(const char * name)
{
bool status;
status = false;
if (name && !dStrstr(name, "../")) {
char canonical[PATH_MAX];
char path[PATH_MAX];
// We can only write and delete files in the prefs directory
dSprintf(canonical, sizeof(canonical), "%s/%s", loki_getprefpath(), name);
build_canonical_name( canonical, path, sizeof(path) );
if ( unlink(path) == 0 ) {
status = true;
}
}
return status;
}
// change the modified time to the current time
bool dFileTouch(const char * name)
{
bool status;
status = false;
if (name && !dStrstr(name, "../")) {
char canonical[PATH_MAX];
char path[PATH_MAX];
// We can only modify files in the prefs directory
dSprintf(canonical, sizeof(canonical), "%s/%s", loki_getprefpath(), name);
build_canonical_name( canonical, path, sizeof(path) );
if ( utime(path, NULL) == 0 ) {
status = true;
}
}
return status;
}
File::File( void ) : currentStatus( Closed ), capability( 0 )
{
handle = NULL;
}
File::~File( void )
{
close( );
handle = NULL;
}
File::Status File::open( const char* filename, const AccessMode mode )
{
char modded[PATH_MAX];
char canonical[PATH_MAX];
assert( filename );
dStrncpy( modded, filename, PATH_MAX );
forwardSlash( modded );
filename = modded;
// if it's not absolute already, put it in the user dir.
if( filename[0] != '/' ) {
dSprintf( canonical, PATH_MAX, "%s/%s", loki_getprefpath( ), filename );
} else {
dStrncpy( canonical, filename, PATH_MAX );
}
if( currentStatus != Closed ) {
close( );
}
switch( mode ) {
case Read:
#if 1
#warning FIXME for performance increase!
// FIXME:
// Cache the contents of the preferences directory
// so we don't have to keep searching for each file
// Can we use the output of dumpPath() in the game?
#endif
handle = ifopen( canonical, "r" );
if( !handle ) {
// if read-only we can try to open in the game dir itself
// because of the "if absolute" check above, it's possible
// that canonical == filename.
handle = ifopen( filename, "r" );
}
break;
case Write:
handle = ifopen( canonical, "w" );
break;
case ReadWrite:
handle = ifopen( canonical, "a+" );
// mimic win32 create on missing by seeking to begin
if( handle ) {
fseek( (FILE*) handle, 0, SEEK_SET );
}
break;
case WriteAppend:
handle = ifopen( canonical, "r" );
if( handle ) {
fclose(handle);
} else {
// We have to copy the original file to append
if ( ! copyFile(filename, canonical) ) {
return setStatus( );
}
}
handle = ifopen( canonical, "a" );
break;
}
if( !handle ) {
#ifdef DEBUG
fprintf(stderr, "Unable to open %s\n", filename);
#endif
return setStatus( );
}
switch( mode ) {
case Read:
capability = static_cast<U32>( FileRead );
break;
case Write:
case WriteAppend:
capability = static_cast<U32>( FileWrite );
break;
case ReadWrite:
capability = static_cast<U32>( FileRead ) |
static_cast<U32>( FileWrite );
break;
}
return ( currentStatus = Ok );
}
U32 File::getPosition( void ) const
{
return ftell( (FILE*) handle );
}
File::Status File::setPosition( S32 position, bool absolute )
{
FILE* file = (FILE*) handle;
if( currentStatus != Ok && currentStatus != EOS ) {
return currentStatus;
}
if( absolute ) {
fseek( file, position, SEEK_SET );
} else {
fseek( file, position, SEEK_CUR );
}
long current = ftell( file );
if( current == -1 ) {
return setStatus( );
} else if( current >= getSize( ) ) {
return ( currentStatus = EOS );
} else {
return ( currentStatus = Ok );
}
}
U32 File::getSize( void ) const
{
if( currentStatus == Ok || currentStatus == EOS ) {
struct stat buf;
int fd = fileno( (FILE*) handle );
if( fstat( fd, &buf ) ) {
return 0;
}
return buf.st_size;
}
return 0;
}
File::Status File::flush( void )
{
if( fflush( (FILE*) handle ) ) {
return setStatus( );
}
return ( currentStatus = Ok );
}
File::Status File::close( void )
{
if( currentStatus == Closed ) {
return currentStatus;
}
if( handle ) {
if( fclose( (FILE*) handle ) ) {
return setStatus( );
}
}
handle = NULL;
return ( currentStatus = Closed );
}
File::Status File::getStatus( void ) const
{
return currentStatus;
}
File::Status File::setStatus( void )
{
switch( errno ) {
case EINVAL:
case EACCES:
case EMFILE:
case ENFILE:
case ENOSPC:
return ( currentStatus = IOError );
default:
return ( currentStatus = UnknownError );
}
}
File::Status File::setStatus( File::Status status )
{
return ( currentStatus = status );
}
File::Status File::read( U32 size, char* dst, U32* bytes )
{
if( currentStatus != Ok || size == 0 ) {
return currentStatus;
}
U32 dummyBytes = 0;
U32* bytesWritten = ( bytes == 0 ) ? &dummyBytes : bytes;
if( ( *bytesWritten = fread( dst, 1, size, (FILE*) handle ) ) != size ) {
if( ferror( (FILE*) handle ) ) {
return setStatus( );
} else {
return ( currentStatus = EOS );
}
}
return ( currentStatus = Ok );
}
File::Status File::write( U32 size, const char* src, U32* bytes )
{
if( ( currentStatus != Ok && currentStatus != EOS ) || 0 == size ) {
return currentStatus;
}
U32 dummyBytes = 0;
U32* bytesWritten = ( bytes == 0 ) ? &dummyBytes : bytes;
if( ( *bytesWritten = fwrite( src, 1, size, (FILE*) handle ) ) != size ) {
if( ferror( (FILE*) handle ) ) {
return setStatus( );
}
}
return ( currentStatus = Ok );
}
bool File::hasCapability( Capability cap ) const
{
return ( ( static_cast<U32>( cap ) & capability ) != 0 );
}
S32 Platform::compareFileTimes( const FileTime& a, const FileTime& b )
{
if( a < b ) {
return -1;
} else if( a > b ) {
return 1;
} else {
return 0;
}
}
typedef void* HANDLE;
typedef unsigned char BOOL;
typedef unsigned int DWORD;
typedef char TCHAR;
typedef const char* LPCTSTR;
#define INVALID_HANDLE_VALUE NULL
#define FILE_ATTRIBUTE_NORMAL 0x0000
#define FILE_ATTRIBUTE_DIRECTORY 0x0040
#define MAX_PATH PATH_MAX
#define TRUE 1
#define FALSE 0
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATA, *LPWIN32_FIND_DATA;
HANDLE FindFirstFile( LPCTSTR, LPWIN32_FIND_DATA );
BOOL FindNextFile( HANDLE, LPWIN32_FIND_DATA );
BOOL FindClose( HANDLE );
/* Opaque handle for Find* functions. */
typedef struct tagFINDSTRUCT {
char dirpath[PATH_MAX];
DIR* dp;
regex_t preg;
} FINDSTRUCT;
ssize_t PreprocessFilename( const char *src, char *dst, ssize_t maxlen )
{
int len;
const char *tmp;
/* Check the size of the destination buffer */
if( dst ) {
if( PreprocessFilename( src, NULL, 0 ) > maxlen ) {
/* Not enough space in destination */
return -1;
}
}
/* "*.*" is a special match anything case */
if( strcmp( src, "*.*") == 0 ) {
const char *match_all = "^.*$";
len = strlen( match_all ) + 1;
if( dst ) {
strcpy( dst, match_all );
}
} else
/* "*." is also a special case -- match anything with no suffix
Warning: "?*." also matches this case, but hope we don't hit it
*/
if( strcmp( src, "*." ) == 0 ) {
const char *match_all_nodot = "^[^\\.]*$";
len = strlen( match_all_nodot ) + 1;
if ( dst ) {
strcpy( dst, match_all_nodot );
}
} else {
len = 1;
for( tmp = src; *tmp; ++tmp ) {
switch( *tmp ) {
case '*':
case '.':
++len;
default:
++len;
}
}
len += 2;
if( dst ) {
*dst++ = '^';
for( tmp = src; *tmp; ++tmp ) {
switch( *tmp ) {
case '*':
*dst++ = '.';
*dst++ = '*';
break;
case '?':
*dst++ = '.';
break;
case '.':
*dst++ = '\\';
*dst++ = '.';
break;
default:
*dst++ = *tmp;
}
}
*dst++ = '$';
*dst++ = '\0';
}
}
return len;
}
HANDLE FindFirstFile( LPCTSTR lpszSearchFile, LPWIN32_FIND_DATA lpffd )
{
FINDSTRUCT * findhandle;
int name_pos;
char SearchFilename[256];
assert( lpffd != NULL );
assert( lpszSearchFile != NULL );
assert( strstr( (char*)lpszSearchFile, ":" ) == NULL );
assert( strstr( (char*)lpszSearchFile, "\\" ) == NULL );
/* Allocate memory for the file handle we return */
findhandle = (FINDSTRUCT*) malloc( sizeof( *findhandle ) );
if( findhandle == NULL ) {
return INVALID_HANDLE_VALUE;
}
memset( findhandle, 0, sizeof( *findhandle ) );
/* Detect and separate a path from a filename in the event there is one */
strncpy( findhandle->dirpath, lpszSearchFile, 256 - 1 );
findhandle->dirpath[256-1] = '\0';
for( name_pos = strlen( findhandle->dirpath ) - 1; name_pos >= 0; name_pos-- ) {
if( findhandle->dirpath[name_pos] == '/' ) {
findhandle->dirpath[name_pos] = '\0';
++name_pos;
break;
}
}
/* Get the filename as a regular expression pattern */
PreprocessFilename( &lpszSearchFile[name_pos], SearchFilename, 256 );
if( regcomp( &(findhandle->preg), SearchFilename, REG_ICASE ) != 0 ) {
free( findhandle );
return INVALID_HANDLE_VALUE;
}
/* Make sure we still have a directory after removing filename */
if ( ! findhandle->dirpath[0] )
strcpy( findhandle->dirpath, "." );
/* Open the directory for reading */
findhandle->dp = opendir( findhandle->dirpath );
if( findhandle->dp == NULL ){
FindClose( findhandle );
return INVALID_HANDLE_VALUE;
}
/* Perform search */
if( ! FindNextFile( findhandle, lpffd ) ) {
FindClose( findhandle );
return INVALID_HANDLE_VALUE;
}
return findhandle;
}
BOOL FindNextFile( HANDLE handle, LPWIN32_FIND_DATA lpffd )
{
FINDSTRUCT* findhandle = (FINDSTRUCT*) handle;
char filepath[256];
struct stat statbuf;
struct dirent *entry;
assert( lpffd != NULL );
assert( findhandle != NULL );
while( ( entry = readdir( ( (FINDSTRUCT*)findhandle )->dp ) ) != NULL ) {
if( (entry->d_name[0] != '.') && regexec( &( ( (FINDSTRUCT*) findhandle )->preg ),
entry->d_name,
0,
0,
0 ) == 0 ) {
sprintf( filepath, "%s/%s", findhandle->dirpath, entry->d_name );
if( stat( filepath, &statbuf ) < 0 ) {
continue;
}
lpffd->ftLastAccessTime.dwLowDateTime = statbuf.st_atime;
lpffd->ftLastWriteTime.dwLowDateTime = statbuf.st_ctime;
//Is path also included?
strncpy( lpffd->cFileName, entry->d_name, 256 - 1 );
lpffd->cFileName[256 - 1] = '\0';
if( S_ISDIR( statbuf.st_mode ) ) {
lpffd->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
} else if( S_ISREG( statbuf.st_mode ) ) {
lpffd->dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
} else {
lpffd->dwFileAttributes = 0;
}
lpffd->nFileSizeLow = statbuf.st_size;
return TRUE;
}
}
return FALSE;
}
BOOL FindClose( HANDLE hFindFile )
{
FINDSTRUCT* findhandle;
findhandle = (FINDSTRUCT*) hFindFile;
if( findhandle == NULL ) {
return FALSE;
}
regfree( &findhandle->preg );
if( findhandle->dp ) {
closedir( findhandle->dp );
}
free( findhandle );
return TRUE;
}
static bool recurseDumpPath( const char* basep,
const char* currentp,
Vector<Platform::FileInfo>& out )
{
char current[PATH_MAX];
char base[PATH_MAX];
char buffer[PATH_MAX];
char scratch[PATH_MAX];
if( currentp ) {
dStrncpy( current, currentp, PATH_MAX );
} else {
current[0] = 0;
}
dStrncpy( base, basep, PATH_MAX );
basep = base;
if( current[0] ) {
dSprintf( buffer, sizeof( buffer ), "%s/%s/*", base, current );
} else {
dSprintf( buffer, sizeof( buffer ), "%s/*", base );
}
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile( buffer, &findData );
if( hFind == INVALID_HANDLE_VALUE ) {
return false;
}
while( hFind != INVALID_HANDLE_VALUE ) {
if( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 ) {
if( findData.cFileName[0] != '.' ) {
scratch[0] = 0;
int length = PATH_MAX;
if( current[0] ) {
dStrncpy( scratch, current, length );
length -= dStrlen( current );
dStrncat( scratch, "/", length );
length--;
}
dStrncat( scratch, findData.cFileName, length );
recurseDumpPath( base, scratch, out );
}
} else {
out.increment( );
Platform::FileInfo& info = out.last( );
if( current[0] ) {
dSprintf( scratch, sizeof( scratch ), "%s/%s", base, current );
info.pFullPath = StringTable->insert( scratch );
info.pVirtPath = StringTable->insert( current );
} else {
info.pFullPath = StringTable->insert( base );
info.pVirtPath = NULL;
}
info.pFileName = StringTable->insert( findData.cFileName );
info.fileSize = findData.nFileSizeLow;
}
if( FindNextFile( hFind, &findData ) == 0 ) {
FindClose( hFind );
hFind = INVALID_HANDLE_VALUE;
}
}
return true;
}
bool Platform::getFileTimes( const char* path, FileTime* create, FileTime* modify )
{
WIN32_FIND_DATA findData;
HANDLE h = FindFirstFile( path, &findData );
if( h == INVALID_HANDLE_VALUE ) {
return false;
}
if( create ) {
// NOTE: always 0 under Linux, but shouldn't be
// an issue with the current usage in the codebase
*create = findData.ftCreationTime.dwLowDateTime;
}
if( modify ) {
*modify = findData.ftLastWriteTime.dwLowDateTime;
}
FindClose( h );
return true;
}
bool Platform::createPath( const char* file )
{
char filename[PATH_MAX];
char pathbuf[PATH_MAX];
const char* dir = 0;
U32 length = 0;
pathbuf[0] = 0;
dSprintf( filename, PATH_MAX, "%s/%s", loki_getprefpath( ), file );
file = filename;
while( ( dir = dStrchr( file, '/' ) ) != 0 ) {
dStrncpy( pathbuf + length, file, dir - file );
pathbuf[ length + dir - file ] = 0;
mkdir( pathbuf, 0700 );
length += dir - file;
pathbuf[ length++ ] = '/';
file = dir + 1;
}
return true;
}
bool Platform::cdFileExists(const char *filePath, const char *volumeName, S32 serialNum)
{
if (!filePath || !filePath[0])
return true;
// FIXME: Add code to scan for CD drives
return true;
return false;
}
bool Platform::dumpPath( const char* spec, Vector<Platform::FileInfo>& out )
{
return recurseDumpPath( spec, 0, out );
}
void Platform::getCurrentDirectory( char* cwd, const U32 size )
{
getcwd( cwd, size );
}
// FIXME: Add to Platform::.
bool platformGetUserPath( const char* base, char* user, U32 size )
{
dSprintf( user, size, "%s/%s", loki_getprefpath( ), base );
return true;
}

209
platformLinux/linuxFont.cc Normal file
View file

@ -0,0 +1,209 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <limits.h>
#include <freetype/freetype.h>
#include "platformLinux/platformLinux.h"
#include "dgl/gFont.h"
#include "Math/mRect.h"
#include "console/console.h"
#include "Core/fileio.h"
#ifdef DEDICATED
void createFontInit( void )
{
// empty
}
void createFontShutdown( void )
{
// emtpy
}
GFont* createFont( const char* name, S32 size )
{
// empty
return 0;
}
#else
static FT_Library library;
void createFontInit( void )
{
FT_Error error = FT_Init_FreeType( &library );
if( error ) {
Con::warnf( ConsoleLogEntry::General, "Freetype initialization failed" );
}
}
void createFontShutdown( void )
{
FT_Error error = FT_Done_FreeType( library );
if( error ) {
Con::warnf( ConsoleLogEntry::General, "Freetype shutdown failed" );
}
}
GFont* createFont( const char* name, S32 size )
{
if( !name ) {
return 0;
}
#ifdef DEBUG
Con::printf( "Creating font %s %d", name, size );
#endif
// open the file and read the contents
char filename[PATH_MAX];
dSprintf( filename, PATH_MAX, "base/fonts/%s.ttf", name );
File file;
file.open( filename, File::Read );
if( file.getStatus( ) != File::Ok ) {
file.close( );
return 0;
}
U32 fileSize = file.getSize( );
U8* buffer = new U8[fileSize];
U32 bytesRead = 0;
if( !buffer ) {
// Don't bother trying to explain OOM :)
file.close( );
return 0;
}
file.read( fileSize, (char*) buffer, &bytesRead );
if( file.getStatus( ) != File::Ok ||
bytesRead != fileSize ) {
Con::warnf( ConsoleLogEntry::General,
"Couldn't read all of %s", filename );
file.close( );
delete[] buffer;
return 0;
}
file.close( );
// tweak point size--non-linear!
F32 points = size;
if( points < 12.0f ) {
points *= 0.80f;
} else {
points *= 0.77f;
}
// to fractional points
points *= 64.0f;
// actual ft API usage
FT_Error error;
FT_Face face;
error = FT_New_Memory_Face( library, buffer, fileSize, 0, &face );
if( error ) {
Con::warnf( ConsoleLogEntry::General, "could not open font %s", filename );
delete[] buffer;
return 0;
}
error = FT_Set_Char_Size( face, 0, points, 0, 0 );
if( error ) {
Con::warnf( ConsoleLogEntry::General, "couldn't set char size" );
delete[] buffer;
return 0;
}
F32 units = face->units_per_EM;
F32 ascent = static_cast<F32>( face->ascender ) / units;
ascent = ceil( ascent * face->size->metrics.y_ppem );
// tweak ascent (?)
ascent *= 1.4f;
F32 descent = static_cast<F32>( face->descender ) / units;
descent *= floor( face->size->metrics.y_ppem );
U32 height = 0;
if( descent > 0 ) {
height = ascent + descent;
} else {
height = ascent - descent;
}
GFont* gfont = new GFont;
for( S32 i = 32; i < 256; i++ ) {
int glyphIndex = FT_Get_Char_Index( face, i );
error = FT_Load_Glyph( face, glyphIndex, FT_LOAD_DEFAULT );
if( error ) {
Con::warnf( ConsoleLogEntry::General, "couldn't load glyph %d", i );
continue;
}
FT_GlyphSlot glyph = face->glyph;
error = FT_Render_Glyph( glyph, ft_render_mode_normal );
if( error ) {
Con::warnf( ConsoleLogEntry::General, "couldn't render glyph %d", i );
continue;
}
FT_Bitmap* bitmap = &glyph->bitmap;
FT_Glyph_Metrics* metrics = &glyph->metrics;
int glyphWidth = ( ( metrics->width + 63 ) & -64 ) / 64;
int glyphHeight = ( ( metrics->height + 63 ) & -64 ) / 64;
int advance = ( ( metrics->horiAdvance + 63 ) & -64 ) / 64;
int hbx = ( ( metrics->horiBearingX + 63 ) & -64 ) / 64;
int hby = ( ( metrics->horiBearingY + 63 ) & -64 ) / 64;
gfont->insertBitmap( i,
bitmap->buffer,
bitmap->pitch,
glyphWidth,
glyphHeight,
hbx,
hby,
advance );
}
gfont->pack( height, ascent );
error = FT_Done_Face( face );
if( error ) {
Con::warnf( ConsoleLogEntry::General, "could not close face" );
}
delete[] buffer;
return gfont;
}
#endif

2409
platformLinux/linuxGL.cc Normal file

File diff suppressed because it is too large Load diff

24
platformLinux/linuxIO.cc Normal file
View file

@ -0,0 +1,24 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int linuxOpen(const char *path, int oflag)
{
return open(path, oflag);
}
int linuxClose(int fd)
{
return close(fd);
}
ssize_t linuxRead(int fd, void *buf, size_t nbytes)
{
return read(fd, buf, nbytes);
}
ssize_t linuxWrite(int fd, const void *buf, size_t nbytes)
{
return write(fd, buf, nbytes);
}

537
platformLinux/linuxInput.cc Normal file
View file

@ -0,0 +1,537 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <SDL/SDL.h>
#include <SDL/SDL_joystick.h>
#include "sdl_utils.h"
#include "engine/platformLinux/platformLinux.h"
#include "engine/platform/platformInput.h"
#include "engine/platform/event.h"
#include "engine/console/console.h"
#include "engine/platform/gameInterface.h"
#define USE_X11_TRANSLATE
#ifdef USE_X11_TRANSLATE
static void fillAsciiTable( void );
#endif
InputManager* Input::smManager = 0;
bool Input::smActive = false;
static SDL_Joystick* joystick = 0;
static int joyNumButtons = 0;
static int joyNumAxes = 0;
static int joyNumBalls = 0;
static int joyNumHats = 0;
static U8* joyHatStates = 0;
static bool cIsJoystickDetected( SimObject* obj, S32 argc, const char** argv )
{
return ( joystick != 0 );
}
static const char* cGetJoystickAxes( SimObject* obj, S32 argc, const char** argv )
{
const char* axisNames[] = { "\tX", "\tY", "\tZ", "\tR", "\tU", "\tV" };
if( joystick == 0 ) {
return "";
}
char buffer[64];
dSprintf( buffer, sizeof( buffer ), "%d", joyNumAxes );
for( U32 i = 0; i < joyNumAxes; i++ ) {
dStrcat( buffer, axisNames[i] );
}
char* returnString = Con::getReturnBuffer( dStrlen( buffer ) + 1 );
dStrcpy( returnString, buffer );
return returnString;
}
// Small helpers.
U8 getHatState( U8 hat )
{
if( joyHatStates == 0 ) {
return 0;
}
if( hat >= joyNumHats ) {
return 0;
}
return joyHatStates[hat];
}
void setHatState( U8 hat, U8 state )
{
if( joyHatStates == 0 ) {
return;
}
if( hat >= joyNumHats ) {
return;
}
joyHatStates[hat] = state;
}
void Input::init( void )
{
Con::printf( "Input init: " );
smActive = false;
Con::addCommand( "isJoystickDetected", cIsJoystickDetected, "isJoystickDetected();", 1, 1 );
Con::addCommand( "getJoystickAxes", cGetJoystickAxes, "getJoystickAxes( device );", 2, 2 );
#ifndef DEDICATED
#ifdef USE_X11_TRANSLATE
fillAsciiTable( );
#endif
sdl_InitClipboard();
Con::printf( " Clipboard initialized" );
Con::printf( " Keyboard initialized" );
Con::printf( " Mouse initialized" );
if( SDL_Init( SDL_INIT_JOYSTICK ) < 0 ) {
Con::printf( " Joystick not initialized" );
return;
}
Con::printf( " Joystick initialized" );
int numJoysticks = SDL_NumJoysticks( );
if( numJoysticks <= 0 ) {
Con::printf( " No joysticks detected" );
return;
}
int i;
for( i = 0; i < numJoysticks; i++ ) {
SDL_Joystick* temp = SDL_JoystickOpen( i );
if( temp ) {
joystick = temp;
break;
}
}
if( !joystick ) {
Con::printf( " No openable joysticks found" );
}
joyNumButtons = SDL_JoystickNumButtons( joystick );
joyNumAxes = SDL_JoystickNumAxes( joystick );
joyNumBalls = SDL_JoystickNumBalls( joystick );
joyNumHats = SDL_JoystickNumHats( joystick );
if( joyNumHats ) {
joyHatStates = new U8[joyNumHats];
dMemset( joyHatStates, 0, joyNumHats );
}
Con::printf( " Found joystick: %s", SDL_JoystickName( i ) );
Con::printf( " Buttons: %d", joyNumButtons );
Con::printf( " Axes: %d", joyNumAxes );
Con::printf( " Balls: %d", joyNumBalls );
Con::printf( " Hats: %d", joyNumHats );
#endif
}
void Input::destroy( void )
{
Con::printf( "Input shutdown" );
smActive = false;
#ifndef DEDICATED
SDL_JoystickClose( joystick );
joystick = 0;
joyNumButtons = 0;
joyNumAxes = 0;
joyNumBalls = 0;
joyNumHats = 0;
if( joyHatStates ) {
delete[] joyHatStates;
}
#endif
}
#ifdef USE_X11_TRANSLATE
typedef struct {
U16 lower;
U16 upper;
U16 goofy;
} asciiTable_t;
#define NUM_KEYS (KEY_OEM_102+1)
#define KEY_FIRST KEY_ESCAPE
static asciiTable_t asciiTable[NUM_KEYS];
// special prototype for non-visible SDL function
extern "C" Uint16 X11_KeyToUnicode( SDLKey keysym, SDLMod modifiers );
static void fillAsciiTable( void )
{
#ifndef DEDICATED
U32 keyCode = 0;
dMemset( &asciiTable, 0, sizeof( asciiTable ) );
for( keyCode = KEY_FIRST; keyCode < NUM_KEYS; keyCode++ ) {
Uint16 key = 0;
SDLKey sym = translateKeyCodeToSDL( keyCode );
SDLMod mod = 0;
// lower case
key = X11_KeyToUnicode( sym, mod );
asciiTable[keyCode].lower = key;
// upper case
mod = KMOD_SHIFT;
key = X11_KeyToUnicode( sym, mod );
asciiTable[keyCode].upper = key;
// goofy (i18n) case
mod = KMOD_MODE;
key = X11_KeyToUnicode( sym, mod );
asciiTable[keyCode].goofy = key;
}
#endif
}
U16 Input::getKeyCode( U16 asciiCode )
{
for( S32 i = KEY_FIRST; i < NUM_KEYS; i++ ) {
if( asciiTable[i].lower == asciiCode ) {
return i;
} else if( asciiTable[i].upper == asciiCode ) {
return i;
} else if( asciiTable[i].goofy == asciiCode ) {
return i;
}
}
return 0;
}
U16 Input::getAscii( U16 keyCode, KEY_STATE keyState )
{
if( keyCode >= NUM_KEYS ) {
return 0;
}
switch( keyState ) {
case STATE_LOWER:
return asciiTable[keyCode].lower;
case STATE_UPPER:
return asciiTable[keyCode].upper;
case STATE_GOOFY:
return asciiTable[keyCode].goofy;
default:
return 0;
}
}
#else
// FIXME: 'goofy' is always '0' because we suck
typedef struct {
U16 code;
U16 lower;
U16 upper;
U16 goofy;
} asciiTable_t;
static asciiTable_t asciiTable[128] =
{
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_BACKSPACE, 8, 8, 0 },
{ KEY_TAB, 9, 9, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_RETURN, 13, 13, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_ESCAPE, 27, 27, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_NULL, 0, 0, 0 },
{ KEY_SPACE, 32, 32, 0 },
{ KEY_1, 49, 33, 0 },
{ KEY_APOSTROPHE, 39, 34, 0 },
{ KEY_3, 51, 35, 0 },
{ KEY_4, 52, 36, 0 },
{ KEY_5, 53, 37, 0 },
{ KEY_7, 55, 38, 0 },
{ KEY_APOSTROPHE, 39, 34, 0 },
{ KEY_9, 58, 40, 0 },
{ KEY_0, 48, 41, 0 },
{ KEY_8, 56, 42, 0 },
{ KEY_EQUALS, 61, 43, 0 }, // 43
{ KEY_COMMA, 44, 60, 0 },
{ KEY_MINUS, 45, 95, 0 },
{ KEY_PERIOD, 46, 62, 0 },
{ KEY_BACKSLASH, 47, 63, 0 },
{ KEY_0, 48, 41, 0 }, // 48
{ KEY_1, 49, 33, 0 },
{ KEY_2, 50, 64, 0 },
{ KEY_3, 51, 35, 0 },
{ KEY_4, 52, 36, 0 },
{ KEY_5, 53, 37, 0 },
{ KEY_6, 54, 94, 0 },
{ KEY_7, 54, 38, 0 },
{ KEY_8, 56, 42, 0 },
{ KEY_9, 57, 28, 0 },
{ KEY_SEMICOLON, 59, 58, 0 }, // 58
{ KEY_SEMICOLON, 59, 58, 0 },
{ KEY_COMMA, 44, 60, 0 },
{ KEY_EQUALS, 61, 43, 0 },
{ KEY_PERIOD, 46, 62, 0 },
{ KEY_BACKSLASH, 47, 63, 0 }, // 63
{ KEY_2, 50, 64, 0 },
{ KEY_A, 97, 65, 0 }, // 65
{ KEY_B, 98, 66, 0 },
{ KEY_C, 99, 67, 0 },
{ KEY_D, 100, 68, 0 },
{ KEY_E, 101, 69, 0 },
{ KEY_F, 102, 70, 0 },
{ KEY_G, 103, 71, 0 },
{ KEY_H, 104, 72, 0 },
{ KEY_I, 105, 73, 0 },
{ KEY_J, 106, 74, 0 },
{ KEY_K, 107, 75, 0 },
{ KEY_L, 108, 76, 0 },
{ KEY_M, 109, 77, 0 },
{ KEY_N, 110, 78, 0 },
{ KEY_O, 111, 79, 0 },
{ KEY_P, 112, 80, 0 },
{ KEY_Q, 113, 81, 0 },
{ KEY_R, 114, 82, 0 },
{ KEY_S, 115, 83, 0 },
{ KEY_T, 116, 84, 0 },
{ KEY_U, 117, 85, 0 },
{ KEY_V, 118, 86, 0 },
{ KEY_W, 119, 87, 0 },
{ KEY_X, 120, 88, 0 },
{ KEY_Y, 121, 89, 0 },
{ KEY_Z, 122, 90, 0 },
{ KEY_LBRACKET, 91, 123, 0 }, // 91
{ KEY_SLASH, 92, 124, 0 },
{ KEY_RBRACKET, 93, 125, 0 },
{ KEY_6, 54, 94, 0 },
{ KEY_MINUS, 45, 95, 0 },
{ KEY_TILDE, 96, 126, 0 },
{ KEY_A, 97, 65, 0 }, // 97
{ KEY_B, 98, 66, 0 },
{ KEY_C, 99, 67, 0 },
{ KEY_D, 100, 68, 0 },
{ KEY_E, 101, 69, 0 },
{ KEY_F, 102, 70, 0 },
{ KEY_G, 103, 71, 0 },
{ KEY_H, 104, 72, 0 },
{ KEY_I, 105, 73, 0 },
{ KEY_J, 106, 74, 0 },
{ KEY_K, 107, 75, 0 },
{ KEY_L, 108, 76, 0 },
{ KEY_M, 109, 77, 0 },
{ KEY_N, 110, 78, 0 },
{ KEY_O, 111, 79, 0 },
{ KEY_P, 112, 80, 0 },
{ KEY_Q, 113, 81, 0 },
{ KEY_R, 114, 82, 0 },
{ KEY_S, 115, 83, 0 },
{ KEY_T, 116, 84, 0 },
{ KEY_U, 117, 85, 0 },
{ KEY_V, 118, 86, 0 },
{ KEY_W, 119, 87, 0 },
{ KEY_X, 120, 88, 0 },
{ KEY_Y, 121, 89, 0 },
{ KEY_Z, 122, 90, 0 },
{ KEY_LBRACKET, 91, 123, 0 }, // 123
{ KEY_SLASH, 92, 124, 0 },
{ KEY_RBRACKET, 93, 125, 0 },
{ KEY_TILDE, 94, 126, 0 },
{ KEY_DELETE, 127, 127, 0 }, // 127
};
U16 Input::getKeyCode( U16 asciiCode )
{
if( asciiCode < sizeof( asciiTable ) ) {
return asciiTable[asciiCode].code;
} else {
return 0;
}
}
U16 Input::getAscii( U16 keyCode, KEY_STATE whichOne )
{
for( S32 i = 0; i < sizeof( asciiTable ); i++ ) {
if( asciiTable[i].code == keyCode ) {
switch( whichOne ) {
case STATE_LOWER:
case STATE_GOOFY:
return asciiTable[i].lower;
case STATE_UPPER:
return asciiTable[i].upper;
}
}
}
return 0;
}
#endif
bool Input::enable( void )
{
return true;
}
void Input::disable( void )
{
}
void Input::activate( void )
{
smActive = true;
}
void Input::deactivate( void )
{
smActive = false;
}
void Input::reactivate( void )
{
// Sorry, needed this indirection for Windows...
Input::activate();
}
bool Input::isEnabled( void )
{
return true;
}
bool Input::isActive( void )
{
return smActive;
}
// bool Input::isKeyboardActive( void )
// {
// return true;
// }
//
// bool Input::isMouseActive( void )
// {
// return true;
// }
//
// bool Input::isJoystickActive( void )
// {
// return ( joystick != 0 );
// }
static JoystickCodes translateAxis( U8 axis )
{
JoystickCodes array[] = { SI_XAXIS, SI_YAXIS, SI_ZAXIS,
SI_RXAXIS, SI_RYAXIS, SI_RZAXIS };
axis = ( axis < 6 ) ? axis : 5;
return array[axis];
}
static void processAxes( void )
{
#ifndef DEDICATED
InputEvent event;
// we need continuous reporting for joystick axes
for( S32 i = 0; i < joyNumAxes; i++ ) {
S16 value = SDL_JoystickGetAxis( joystick, i );
event.deviceInst = 0;
event.deviceType = JoystickDeviceType;
event.objType = translateAxis( i );
event.objInst = 0;
event.action = SI_MOVE;
event.modifier = 0;
event.ascii = 0;
event.fValue = static_cast<float>( value ) / 32767.0f;
Game->postEvent( event );
}
#endif
}
void Input::process( void )
{
// do our immediate processing here
processAxes( );
}
//-----------------------------------------------------------------------------
// Clipboard functions
const char* Platform::getClipboard()
{
#ifdef DEDICATED
return "";
#else
return sdl_GetClipboard();
#endif
}
bool Platform::setClipboard(const char *text)
{
#ifdef DEDICATED
return false;
#else
if (!text)
return false;
sdl_PutClipboard(text);
return true;
#endif
}

459
platformLinux/linuxMath.cc Normal file
View file

@ -0,0 +1,459 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platform.h"
#include "console/console.h"
#include "Math/mMath.h"
#include <stdlib.h>
extern "C" {
void m_quatF_set_matF_ASM( F32 x, F32 y, F32 z, F32 w, F32* m );
F32 m_matF_determinant_ASM( const F32* m );
void m_matF_inverse_ASM( F32* m );
void m_matF_affineInverse_ASM( F32* m );
void m_matF_x_matF_ASM( const F32* a, const F32* b, F32* m );
void m_matF_x_vectorF_ASM( const F32* m, const F32* v, F32* r );
U32 mSolveQuadratic_ASM(F32 A, F32 B, F32 C, F32* x);
U32 mSolveCubic_ASM(F32 A, F32 B, F32 C, F32 D, F32* x);
U32 mSolveQuartic_ASM( F32 A, F32 B, F32 C, F32 D, F32 E, F32* x );
S32 m_mulDivS32_ASM(S32 a, S32 b, S32 c);
U32 m_mulDivU32_ASM(S32 a, S32 b, U32 c);
// Added lots more math functions optimized by Visual C++
void m_point2F_normalize_ASM(F32 *p);
void m_point2F_normalize_f_ASM(F32 *p, F32 val);
void m_point2D_normalize_ASM(F64 *p);
void m_point2D_normalize_f_ASM(F64 *p, F64 val);
void m_point3F_normalize_ASM(F32 *p);
void m_point3F_normalize_f_ASM(F32 *p, F32 val);
void m_point3F_interpolate_ASM(const F32 *from, const F32 *to, F32 factor, F32 *result );
void m_point3D_normalize_ASM(F64 *p);
void m_point3D_interpolate_ASM(const F64 *from, const F64 *to, F64 factor, F64 *result );
void m_point3F_bulk_dot_ASM(const F32* refVector,
const F32* dotPoints,
const U32 numPoints,
const U32 pointStride,
F32* output);
void m_point3F_bulk_dot_indexed_ASM(const F32* refVector,
const F32* dotPoints,
const U32 numPoints,
const U32 pointStride,
const U32* pointIndices,
F32* output);
void m_matF_identity_ASM(F32 *m);
void m_matF_set_euler_ASM(const F32 *e, F32 *result);
void m_matF_set_euler_point_ASM(const F32 *e, const F32 *p, F32 *result);
void m_matF_transpose_ASM(F32 *m);
void m_matF_scale_ASM(F32 *m, const F32 *p);
void m_matF_normalize_ASM(F32 *m);
void m_matF_x_point4F_ASM(const F32 *m, const F32 *p, F32 *presult);
}
extern void mInstallLibrary_C( void );
// drivers
static void m_quatF_set_matF_D( F32 x, F32 y, F32 z, F32 w, F32* m )
{
AssertISV( !isnan( x ), "x == NaN in QuatF::setMatrix" );
AssertISV( !isnan( y ), "y == NaN in QuatF::setMatrix" );
AssertISV( !isnan( z ), "z == NaN in QuatF::setMatrix" );
AssertISV( !isnan( w ), "w == NaN in QuatF::setMatrix" );
m_quatF_set_matF_ASM( x, y, z, w, m );
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in QuatF::setMatrix" );
}
}
static F32 m_matF_determinant_D( const F32* m )
{
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::determinant" );
}
F32 d = m_matF_determinant_ASM( m );
AssertISV( !isnan( d ), "d == NaN in MatrixF::determinant" );
return d;
}
static void m_matF_inverse_D( F32* m )
{
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::inverse" );
}
m_matF_inverse_ASM( m );
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::inverse" );
}
}
static void m_matF_affineInverse_D( F32* m )
{
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::affineInverse" );
}
m_matF_affineInverse_ASM( m );
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::affineInverse" );
}
}
static void m_matF_x_matF_D( const F32* a, const F32* b, F32* m )
{
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( a[i] ), "a[i] == NaN in MatrixF::mul" );
AssertISV( !isnan( b[i] ), "b[i] == NaN in MatrixF::mul" );
}
m_matF_x_matF_ASM( a, b, m );
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::mul" );
}
}
static void m_matF_x_vectorF_D( const F32* m, const F32* v, F32* r )
{
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::mul( VectorF )" );
}
for( int i = 0; i < 3; i++ ) {
AssertISV( !isnan( v[i] ), "v[i] == NaN in MatrixF::mul( VectorF )" );
}
m_matF_x_vectorF_ASM( m, v, r );
for( int i = 0; i < 3; i++ ) {
AssertISV( !isnan( r[i] ), "r[i] == NaN in MatrixF::mul( VectorF )" );
}
}
static U32 mSolveQuartic_D( F32 A, F32 B, F32 C, F32 D, F32 E, F32* x )
{
AssertISV( !isnan( A ), "A == NaN in mSolveQuartic_D" );
AssertISV( !isnan( B ), "B == NaN in mSolveQuartic_D" );
AssertISV( !isnan( C ), "C == NaN in mSolveQuartic_D" );
AssertISV( !isnan( D ), "D == NaN in mSolveQuartic_D" );
AssertISV( !isnan( E ), "E == NaN in mSolveQuartic_D" );
U32 n = mSolveQuartic_ASM( A, B, C, D, E, x );
for( int i = 0; i < n; i++ ) {
AssertISV( !isnan( x[i] ), "x[i] == NaN in mSolveQuartic_D" );
}
return n;
}
static void m_matF_transpose_D(F32 *m)
{
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::transpose()" );
}
m_matF_transpose_ASM( m );
for( int i = 0; i < 16; i++ ) {
AssertISV( !isnan( m[i] ), "m[i] == NaN in MatrixF::transpose()" );
}
}
static void checkASM( void )
{
float i[] = { 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
float aff[] = { 0.1, 0, 0, 0.333,
0, 0.2, 0, 0.666,
0, 0, 0.3, 0.999,
0, 0, 0, 1.0 };
float inv[] = { 1, 3, 1, 1,
2, 5, 2, 2,
1, 3, 8, 9,
1, 3, 2, 2 };
float m[] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16 };
float v[] = { 1, 2 ,3 };
float v2[] = { -1, 2, -0.333 };
float a[16];
float c[16];
int j, k;
for( int j = 0; j < 16; j++ ) {
a[j] = 0.0f;
c[j] = 0.0f;
}
m_matF_x_vectorF_ASM( inv, v, a );
m_matF_x_vectorF( inv, v, c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "m_matF_x_vectorF" );
m_matF_x_vectorF_ASM( inv, v2, a );
m_matF_x_vectorF( inv, v2, c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "m_matF_x_vectorF" );
dMemcpy( a, inv, sizeof( a ) );
dMemcpy( c, inv, sizeof( c ) );
m_matF_inverse_ASM( a );
m_matF_inverse( c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "m_matF_inverse" );
m_quatF_set_matF_ASM( 1, 2, 3, 4, a );
m_quatF_set_matF( 1, 2, 3, 4, c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "m_quatF_set_matF" );
a[0] = m_matF_determinant_ASM( inv );
c[0] = m_matF_determinant_ASM( inv );
AssertISV( a[0] == c[0], "m_matF_determinant" );
dMemcpy( a, aff, sizeof( a ) );
dMemcpy( c, aff, sizeof( c ) );
m_matF_affineInverse_ASM( a );
m_matF_affineInverse( c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "m_matF_affineInverse" );
m_matF_x_matF_ASM( m, m, a );
m_matF_x_matF( m, m, c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "m_matF_x_matF" );
#if 0 // Code generated with Visual C++ gives slighly different results
j = mSolveQuartic_ASM( 1.0, 2.0, 3.0, 4.0, 5.0, a );
k = mSolveQuartic( 1.0, 2.0, 3.0, 4.0, 5.0, c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "mSolveQuartic" );
AssertISV( j == k, "mSolveQuartic" );
j = mSolveQuartic_ASM( 0.0, 1.0, 2.0, 3.0, 4.0, a );
k = mSolveQuartic( 0.0, 1.0, 2.0, 3.0, 4.0, c );
AssertISV( dMemcmp( a, c, sizeof( a ) ) == 0, "mSolveQuartic" );
AssertISV( j == k, "mSolveQuartic" );
#endif
}
void mInstallLibrary_ASM( void )
{
// Experimentally determined by 10,000,000 iteration benchmarks
U32 asm_flags = 0x027FC4F3;
U32 dbg_flags = 0x00000000;
if ( getenv("TRIBES2_ASM_FLAGS") ) {
asm_flags = strtol(getenv("TRIBES2_ASM_FLAGS"), NULL, 0);
if ( ! asm_flags ) {
return;
}
}
if ( getenv("TRIBES2_ASM_DEBUG") ) {
dbg_flags = strtol(getenv("TRIBES2_ASM_DEBUG"), NULL, 0);
if ( dbg_flags ) {
checkASM( );
}
}
if ( asm_flags & (1<<0) ) {
m_mulDivS32 = m_mulDivS32_ASM;
m_mulDivU32 = m_mulDivU32_ASM;
}
if ( asm_flags & (1<<1) ) {
if ( dbg_flags & (1<<1) )
m_quatF_set_matF = m_quatF_set_matF_D;
else
m_quatF_set_matF = m_quatF_set_matF_ASM;
}
if ( asm_flags & (1<<2) ) {
if ( dbg_flags & (1<<2) )
m_matF_determinant = m_matF_determinant_D;
else
m_matF_determinant = m_matF_determinant_ASM;
}
if ( asm_flags & (1<<3) ) {
if ( dbg_flags & (1<<3) )
m_matF_inverse = m_matF_inverse_D;
else
m_matF_inverse = m_matF_inverse_ASM;
}
if ( asm_flags & (1<<4) ) {
if ( dbg_flags & (1<<4) )
m_matF_affineInverse = m_matF_affineInverse_D;
else
m_matF_affineInverse = m_matF_affineInverse_ASM;
}
if ( asm_flags & (1<<5) ) {
if ( dbg_flags & (1<<5) )
m_matF_x_matF = m_matF_x_matF_D;
else
m_matF_x_matF = m_matF_x_matF_ASM;
}
if ( asm_flags & (1<<6) ) {
mSolveQuadratic = mSolveQuadratic_ASM;
mSolveCubic = mSolveCubic_ASM;
}
if ( asm_flags & (1<<7) ) {
if ( dbg_flags & (1<<7) )
mSolveQuartic = mSolveQuartic_D;
else
mSolveQuartic = mSolveQuartic_ASM;
}
// Added lots more math functions optimized by Visual C++
if ( asm_flags & (1<<8) )
m_point2F_normalize = m_point2F_normalize_ASM;
if ( asm_flags & (1<<9) )
m_point2F_normalize_f = m_point2F_normalize_f_ASM;
if ( asm_flags & (1<<10) )
m_point2D_normalize = m_point2D_normalize_ASM;
if ( asm_flags & (1<<11) )
m_point2D_normalize_f = m_point2D_normalize_f_ASM;
if ( asm_flags & (1<<12) )
m_point3F_normalize = m_point3F_normalize_ASM;
if ( asm_flags & (1<<13) )
m_point3F_normalize_f = m_point3F_normalize_f_ASM;
if ( asm_flags & (1<<14) )
m_point3F_interpolate = m_point3F_interpolate_ASM;
if ( asm_flags & (1<<15) )
m_point3D_normalize = m_point3D_normalize_ASM;
if ( asm_flags & (1<<16) )
m_point3D_interpolate = m_point3D_interpolate_ASM;
if ( asm_flags & (1<<17) )
m_point3F_bulk_dot = m_point3F_bulk_dot_ASM;
if ( asm_flags & (1<<18) )
m_point3F_bulk_dot_indexed = m_point3F_bulk_dot_indexed_ASM;
if ( asm_flags & (1<<19) )
m_matF_set_euler = m_matF_set_euler_ASM;
if ( asm_flags & (1<<20) )
m_matF_set_euler_point = m_matF_set_euler_point_ASM;
if ( asm_flags & (1<<21) )
m_matF_identity = m_matF_identity_ASM;
if ( asm_flags & (1<<22) ) {
if ( dbg_flags & (1<<22) )
m_matF_transpose = m_matF_transpose_D;
else
m_matF_transpose = m_matF_transpose_ASM;
}
if ( asm_flags & (1<<23) )
m_matF_scale = m_matF_scale_ASM;
if ( asm_flags & (1<<24) )
m_matF_normalize = m_matF_normalize_ASM;
if ( asm_flags & (1<<25) )
m_matF_x_point4F = m_matF_x_point4F_ASM;
}
static void cMathInit( SimObject* obj, S32 argc, const char** argv )
{
U32 properties = CPU_PROP_C;
if( argc == 1 ) {
Math::init( 0 );
return;
}
for( argc--, argv++; argc; argc--, argv++ ) {
if( dStricmp( *argv, "DETECT" ) == 0 ) {
Math::init( 0 );
return;
}
if( dStricmp( *argv, "C" ) == 0 ) {
properties |= CPU_PROP_C;
continue;
}
if( dStricmp( *argv, "FPU" ) == 0 ) {
properties |= CPU_PROP_FPU;
continue;
}
if( dStricmp( *argv, "MMX" ) == 0 ) {
properties |= CPU_PROP_MMX;
continue;
}
if( dStricmp( *argv, "3DNOW" ) == 0 ) {
properties |= CPU_PROP_3DNOW;
continue;
}
if( dStricmp( *argv, "SSE" ) == 0 ) {
properties |= CPU_PROP_SSE;
continue;
}
Con::printf( "Error: MathInit(): ignoring unknown math extension '%s'", *argv );
}
Math::init( properties );
}
void Math::init( U32 properties )
{
Con::addCommand( "MathInit", cMathInit, "MathInit( detect|C|FPU|MMX|3DNOW|SSE|... )", 1, 10 );
if( !properties ) {
properties = Platform::SystemInfo.processor.properties;
} else {
properties &= Platform::SystemInfo.processor.properties;
}
Con::printf( "Math Init:" );
Con::printf( " Installing Standard C extensions" );
mInstallLibrary_C( );
Con::printf( " Installing Assembly extensions" );
mInstallLibrary_ASM( );
if( properties & CPU_PROP_FPU ) {
Con::printf( " Installing FPU extensions" );
}
if( properties & CPU_PROP_MMX ) {
Con::printf( " Installing MMX extensions" );
}
if( properties & CPU_PROP_3DNOW ) {
Con::printf( " Installing 3DNow! extensions" );
}
if( properties & CPU_PROP_SSE ) {
Con::printf( " Installing SSE extensions" );
}
}

File diff suppressed because it is too large Load diff

1145
platformLinux/linuxMath_VC.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platformLinux/platformLinux.h"
#include <memory.h>
#include <stdlib.h>
void* dMemcpy( void* d, const void* s, U32 n )
{
return memcpy( d, s, n );
}
void* dMemmove( void* d, const void* s, U32 n )
{
return memmove( d, s, n );
}
void* dMemset( void* d, S32 c, U32 n )
{
return memset( d, c, n );
}
S32 dMemcmp( const void* p1, const void* p2, U32 n )
{
return memcmp( p1, p2, n );
}
void* dRealMalloc( dsize_t n )
{
return malloc( n );
}
void dRealFree( void* p )
{
free( p );
}

View file

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platformMutex.h"
#include <pthread.h>
void* Mutex::createMutex( void )
{
pthread_mutex_t* mutex = new pthread_mutex_t;
if( mutex == 0 ) {
return 0;
}
pthread_mutexattr_t attr;
pthread_mutexattr_init( &attr );
pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE_NP );
if( pthread_mutex_init( mutex, &attr ) != 0 ) {
delete mutex;
return 0;
}
return mutex;
}
void Mutex::destroyMutex( void* mutex )
{
if( mutex ) {
pthread_mutex_destroy( (pthread_mutex_t*) mutex );
delete mutex;
}
}
void Mutex::lockMutex( void* mutex )
{
if( mutex ) {
pthread_mutex_lock( (pthread_mutex_t*) mutex );
}
}
void Mutex::unlockMutex( void* mutex )
{
if( mutex ) {
pthread_mutex_unlock( (pthread_mutex_t*) mutex );
}
}

738
platformLinux/linuxNet.cc Normal file
View file

@ -0,0 +1,738 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netdb.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
/* The ares library is a C API */
extern "C" {
#define class ares_class
#include <ares.h>
#undef class
}
#include "platformLinux/async.h"
#include "platformLinux/platformLinux.h"
#include "Platform/platform.h"
#include "Platform/event.h"
#include "console/console.h"
#include "Platform/gameInterface.h"
#include "Core/fileStream.h"
//
// Local types
//
typedef struct {
int fd;
U16 port;
} NameLookup;
//
// Sundry module-local variables.
//
static ares_channel channel;
static U16 defaultPort = 28000;
static U16 netPort = 0;
static NetSocket udpSocket = -1;
//
// Our asychronous callbacks.
//
static int selectCallback( int fd, int event, int status )
{
static ConnectedNotifyEvent notifyEvent;
static ConnectedReceiveEvent receiveEvent;
static ConnectedAcceptEvent acceptEvent;
int bytesRead = 0;
Net::Error error = Net::NoError;
switch( event ) {
case FD_READ:
error = Net::recv( fd, receiveEvent.data, MaxPacketDataSize, &bytesRead );
if( error == Net::NoError & bytesRead != 0 ) {
receiveEvent.tag = fd;
receiveEvent.size = ConnectedReceiveEventHeaderSize + bytesRead;
Game->postEvent( receiveEvent );
}
break;
case FD_CONNECT:
notifyEvent.tag = fd;
if( status ) {
notifyEvent.state = ConnectedNotifyEvent::Connected;
} else {
notifyEvent.state = ConnectedNotifyEvent::ConnectFailed;
}
Game->postEvent( notifyEvent );
break;
case FD_CLOSE:
for( ; ; ) {
error = Net::recv( fd, receiveEvent.data, MaxPacketDataSize, &bytesRead );
if( error != Net::NoError || bytesRead == 0 ) {
break;
}
receiveEvent.tag = fd;
receiveEvent.size = ConnectedReceiveEventHeaderSize + bytesRead;
Game->postEvent( receiveEvent );
}
notifyEvent.tag = fd;
notifyEvent.state = ConnectedNotifyEvent::Disconnected;
Game->postEvent( notifyEvent );
break;
case FD_ACCEPT:
acceptEvent.portTag = fd;
acceptEvent.connectionTag = Net::accept( fd, &acceptEvent.address );
if( acceptEvent.connectionTag != InvalidSocket ) {
Net::setBlocking( acceptEvent.connectionTag, false );
AsyncSelect( acceptEvent.connectionTag, selectCallback, FD_READ | FD_CONNECT | FD_CLOSE );
Game->postEvent( acceptEvent );
}
break;
}
}
static void lookupCallback( void* arg, int status, struct hostent* host )
{
static ConnectedNotifyEvent notifyEvent;
char* errorMem = 0;
char** addr = 0;
NameLookup* lookup = static_cast<NameLookup*>( arg );
if( status != ARES_SUCCESS ) {
ares_strerror( status, &errorMem );
Con::printf( "couldn't perform lookup: %s", errorMem );
ares_free_errmem( errorMem );
delete lookup;
return;
}
struct sockaddr_in ipAddr;
dMemcpy( &ipAddr.sin_addr.s_addr, host->h_addr_list[0], sizeof( struct in_addr ) );
ipAddr.sin_port = lookup->port;
ipAddr.sin_family = AF_INET;
notifyEvent.tag = lookup->fd;
int error = ::connect( lookup->fd, (struct sockaddr*) &ipAddr, sizeof( ipAddr ) );
if( error == -1 && errno != EINPROGRESS ) {
notifyEvent.state = ConnectedNotifyEvent::DNSFailed;
::close( lookup->fd );
} else {
AsyncSelect( lookup->fd, selectCallback, FD_READ | FD_CONNECT | FD_CLOSE );
notifyEvent.state = ConnectedNotifyEvent::DNSResolved;
}
Game->postEvent( notifyEvent );
delete lookup;
}
//
// Utilities.
//
static void netToIPSocketAddress( const NetAddress* addr, struct sockaddr_in* ip )
{
memset( ip, 0, sizeof( struct sockaddr_in ) );
ip->sin_family = AF_INET;
ip->sin_port = htons( addr->port );
ip->sin_addr.s_addr = *( (U32*) addr->netNum );
}
static void IPSocketToNetAddress( const sockaddr_in* ip, NetAddress* addr )
{
addr->type = NetAddress::IPAddress;
addr->port = htons( ip->sin_port );
*( (U32*) addr->netNum ) = ip->sin_addr.s_addr;
}
static Net::Error getLastError( void )
{
// God knows what distinguishes Invalid from Wrong...
switch( errno ) {
case 0:
return Net::NoError;
case EBADF:
case ENOTSOCK:
return Net::NotASocket;
case EAGAIN:
return Net::WouldBlock;
case ENOTCONN:
return Net::InvalidPacketProtocol;
case EOPNOTSUPP:
return Net::WrongProtocolType;
default:
return Net::UnknownError;
}
}
//
// Net:: implementation
//
bool Net::init( void )
{
int status;
char* errorMem;
if( AsyncInit( ) == -1 ) {
Con::printf( "AsyncInit failed" );
return false;
}
status = ares_init( &channel );
if( status != ARES_SUCCESS ) {
Con::printf( "ares_init: %s", ares_strerror( status, &errorMem ) );
ares_free_errmem( errorMem );
return false;
}
return true;
}
void Net::shutdown( void )
{
AsyncShutdown( );
ares_destroy( channel );
closePort( );
}
NetSocket Net::openListenPort( U16 port )
{
if( Game->isJournalReading( ) ) {
U32 ret;
Game->journalRead( &ret );
return ret;
}
NetSocket fd = openSocket( );
bind( fd, port );
listen( fd, 4 );
setBlocking( fd, false );
if( AsyncSelect( fd, selectCallback, FD_ACCEPT ) == -1 ) {
Con::printf( "Error: %d", errno );
}
if( Game->isJournalWriting( ) ) {
Game->journalWrite( fd );
}
return fd;
}
NetSocket Net::openConnectTo( const char* addressString )
{
if( !dStrnicmp( addressString, "ip:", 3 ) ) {
addressString += 3;
}
char remoteAddr[256];
dStrncpy( remoteAddr, addressString, 256 );
char* portString = dStrchr( remoteAddr, ':' );
U16 port;
if( portString ) {
*portString++ = 0;
port = htons( dAtoi( portString ) );
} else {
port = htons( defaultPort );
}
if( !dStricmp( remoteAddr, "broadcast" ) ) {
return InvalidSocket;
}
if( Game->isJournalReading( ) ) {
U32 ret;
Game->journalRead( &ret );
return ret;
}
NetSocket fd = openSocket( );
setBlocking( fd, false );
struct sockaddr_in ipAddr;
ipAddr.sin_addr.s_addr = inet_addr( remoteAddr );
if( ipAddr.sin_addr.s_addr != INADDR_NONE ) {
ipAddr.sin_port = port;
ipAddr.sin_family = AF_INET;
int error = ::connect( fd, (struct sockaddr*) &ipAddr, sizeof( ipAddr ) );
if( error == -1 && errno != EINPROGRESS ) {
Con::printf( "Last error: %d", errno );
::close( fd );
fd = InvalidSocket;
}
if( fd != InvalidSocket ) {
AsyncSelect( fd, selectCallback, FD_READ | FD_CONNECT | FD_CLOSE );
}
} else {
NameLookup* lookup = new NameLookup;
lookup->fd = fd;
lookup->port = port;
ares_gethostbyname( channel, remoteAddr, AF_INET, lookupCallback, lookup );
}
if( Game->isJournalWriting( ) ) {
Game->journalWrite( fd );
}
return fd;
}
void Net::closeConnectTo( NetSocket fd )
{
if( Game->isJournalReading( ) ) {
return;
}
AsyncCancel( fd );
::close( fd );
}
Net::Error Net::sendTo( NetSocket fd, const U8* buffer, int size )
{
if( Game->isJournalReading( ) ) {
U32 error;
Game->journalRead( &error );
return static_cast<Net::Error>( error );
}
Net::Error error = send( fd, buffer, size );
if( Game->isJournalWriting( ) ) {
Game->journalWrite( static_cast<U32>( error ) );
}
return error;
}
bool Net::openPort( S32 port )
{
closePort( );
udpSocket = socket( AF_INET, SOCK_DGRAM, 0 );
if( udpSocket != -1 ) {
Net::Error error;
error = bind( udpSocket, port );
if( error == NoError ) {
error = setBufferSize( udpSocket, 32768 );
}
if( error == NoError ) {
error = setBroadcast( udpSocket, true );
}
if( error == NoError ) {
error = setBlocking( udpSocket, false );
}
if( error == NoError ) {
Con::printf( "UDP initialized on port %d", port );
} else {
close( udpSocket );
udpSocket = -1;
Con::printf( "Unable to initialize UDP -- error %d", error );
}
}
netPort = port;
return ( udpSocket != -1 );
}
void Net::closePort( void )
{
if( udpSocket != -1 ) {
close( udpSocket );
}
}
Net::Error Net::sendto( const NetAddress* addr, const U8* buffer, S32 size )
{
if( Game->isJournalReading( ) ) {
return NoError;
}
struct sockaddr_in ip;
netToIPSocketAddress( addr, &ip );
if( ::sendto( udpSocket, buffer, size, 0, (struct sockaddr*) &ip, sizeof( ip ) ) == -1 ) {
return getLastError( );
}
return NoError;
}
void Net::process( void )
{
PacketReceiveEvent event;
for( ; ; ) {
struct sockaddr sa;
socklen_t length = sizeof( sa );
S32 bytes = -1;
if( udpSocket != -1 ) {
bytes = recvfrom( udpSocket, event.data, MaxPacketDataSize, 0, &sa, &length );
}
if( bytes == -1 ) {
break;
}
if( sa.sa_family == AF_INET ) {
IPSocketToNetAddress( (struct sockaddr_in*) &sa, &event.sourceAddress );
} else {
continue;
}
NetAddress& addr = event.sourceAddress;
if( addr.type == NetAddress::IPAddress &&
addr.netNum[0] == 127 && addr.netNum[1] == 0 &&
addr.netNum[1] == 0 && addr.netNum[2] == 1 &&
addr.port == netPort ) {
continue;
}
if( bytes <= 0 ) {
continue;
}
event.size = PacketReceiveEventHeaderSize + bytes;
Game->postEvent( event );
}
// do ares DNS processing
fd_set read_fds, write_fds;
int nfds = 0;
struct timeval* timeout = 0;
struct timeval tv;
struct timezone tz;
FD_ZERO( &read_fds );
FD_ZERO( &write_fds );
nfds = ares_fds( channel, &read_fds, &write_fds );
if( nfds == 0 ) {
return;
}
timeout = ares_timeout( channel, 0, &tv );
select( nfds, &read_fds, &write_fds, 0, timeout );
ares_process( channel, &read_fds, &write_fds );
}
NetSocket Net::openSocket( void )
{
int fd;
if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) {
return InvalidSocket;
}
return fd;
}
Net::Error Net::closeSocket( NetSocket fd )
{
if( fd == InvalidSocket ) {
return NotASocket;
}
if( close( fd ) ) {
return getLastError( );
}
return NoError;
}
Net::Error Net::connect( NetSocket fd, const NetAddress* addr )
{
if( addr->type != NetAddress::IPAddress ) {
return WrongProtocolType;
}
struct sockaddr_in addrIn;
netToIPSocketAddress( addr, &addrIn );
if( ::connect( fd, (struct sockaddr*) &addrIn, sizeof( addrIn ) ) ) {
return getLastError( );
}
return NoError;
}
Net::Error Net::listen( NetSocket fd, S32 backlog )
{
if( ::listen( fd, backlog ) ) {
return getLastError( );
}
return NoError;
}
NetSocket Net::accept( NetSocket fd, NetAddress* addr )
{
struct sockaddr_in ip;
socklen_t length = sizeof( ip );
int ret = ::accept( fd, (struct sockaddr*) &ip, &length );
if( ret != -1 ) {
IPSocketToNetAddress( &ip, addr );
return ret;
}
return InvalidSocket;
}
Net::Error Net::bind( NetSocket fd, U16 port )
{
struct sockaddr_in ip;
dMemset( &ip, 0, sizeof( ip ) );
ip.sin_family = AF_INET;
// It's entirely possible that there are two NIC cards.
// We let the user specify which one the server runs on.
// thanks to [TPG]P1aGu3 for the name
const char* serverIP = Con::getVariable( "Host::BindAddress" );
// serverIP is guaranteed to be non-0.
AssertFatal( serverIP, "serverIP is NULL!" );
if( serverIP[0] != '\0' ) {
// we're not empty
ip.sin_addr.s_addr = inet_addr( serverIP );
if( ip.sin_addr.s_addr != INADDR_NONE ) {
Con::printf( "Binding server port to %s", serverIP );
} else {
Con::warnf( ConsoleLogEntry::General,
"inet_addr() failed for %s while binding!",
serverIP );
ip.sin_addr.s_addr = INADDR_ANY;
}
} else {
Con::printf( "Binding server port to default IP" );
ip.sin_addr.s_addr = INADDR_ANY;
}
ip.sin_port = htons( port );
if( ::bind( fd, (struct sockaddr*) &ip, sizeof( ip ) ) ) {
return getLastError( );
}
return NoError;
}
Net::Error Net::setBufferSize( NetSocket fd, S32 size )
{
if( setsockopt( fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof( size ) ) ) {
return getLastError( );
}
if( setsockopt( fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof( size ) ) ) {
return getLastError( );
}
return NoError;
}
Net::Error Net::setBroadcast( NetSocket fd, bool broadcast )
{
S32 bc = broadcast;
if( setsockopt( fd, SOL_SOCKET, SO_BROADCAST, &bc, sizeof( bc ) ) ) {
return getLastError( );
}
return NoError;
}
Net::Error Net::setBlocking( NetSocket fd, bool blocking )
{
int flags;
// Let's do it the Posix.1g way!
if( ( flags = fcntl( fd, F_GETFL, 0 ) ) < 0 ) {
return getLastError( );
}
if( blocking ) {
flags &= ~O_NONBLOCK;
} else {
flags |= O_NONBLOCK;
}
if( fcntl( fd, F_SETFL, flags ) < 0 ) {
return getLastError( );
}
return NoError;
}
Net::Error Net::send( NetSocket fd, const U8* buffer, S32 size )
{
if( ::send( fd, buffer, size, 0 ) == -1 ) {
return getLastError( );
}
return NoError;
}
Net::Error Net::recv( NetSocket fd, U8* buffer, S32 size, S32* read )
{
if( ( *read = ::recv( fd, buffer, size, 0 ) ) == -1 ) {
return getLastError( );
}
return NoError;
}
bool Net::compareAddresses( const NetAddress* a1, const NetAddress* a2 )
{
// cast our separated ipv4 into a 32-bit word for compare
bool sameType = ( a1->type == a2->type );
bool sameNum = ( *( (U32*) a1->netNum ) == *( (U32*) a2->netNum ) );
bool samePort = ( a1->port == a2->port );
return ( sameType && sameNum && samePort );
}
bool Net::stringToAddress( const char* addressString, NetAddress* address )
{
if( dStrnicmp( addressString, "ip:", 3 ) == 0 ) {
addressString += 3;
}
if( dStrnicmp( addressString, "ipx:", 4 ) == 0 ) {
// foo on IPX.
return false;
}
if( dStrlen( addressString ) > 255 ) {
return false;
}
struct sockaddr_in ipAddr;
char remoteAddr[256];
dStrcpy( remoteAddr, addressString );
char* portString = dStrchr( remoteAddr, ':' );
if( portString ) {
*portString++ = 0;
}
struct hostent* he = 0;
if( dStricmp( remoteAddr, "broadcast" ) == 0 ) {
ipAddr.sin_addr.s_addr = htonl( INADDR_BROADCAST );
} else {
ipAddr.sin_addr.s_addr = inet_addr( remoteAddr );
if( ipAddr.sin_addr.s_addr == INADDR_NONE ) {
if( ( he == gethostbyname( remoteAddr ) ) == NULL ) {
return false;
} else {
memcpy( &ipAddr.sin_addr.s_addr, he->h_addr, sizeof( struct in_addr ) );
}
}
}
if( portString ) {
ipAddr.sin_port = htons( dAtoi( portString ) );
} else {
ipAddr.sin_port = htons( defaultPort );
}
ipAddr.sin_family = AF_INET;
IPSocketToNetAddress( &ipAddr, address );
return true;
}
void Net::addressToString( const NetAddress* address, char addressString[256] )
{
if( address->type == NetAddress::IPAddress ) {
struct sockaddr_in ipAddr;
netToIPSocketAddress( address, &ipAddr );
if( ipAddr.sin_addr.s_addr == htonl( INADDR_BROADCAST ) ) {
dSprintf( addressString, 256, "IP:Broadcast:%d", ntohs( ipAddr.sin_port ) );
} else {
dSprintf( addressString, 256, "IP:%d.%d.%d.%d:%d",
( ipAddr.sin_addr.s_addr ) & 0xff,
( ipAddr.sin_addr.s_addr >> 8 ) & 0xff,
( ipAddr.sin_addr.s_addr >> 16 ) & 0xff,
( ipAddr.sin_addr.s_addr >> 24 ) & 0xff,
ntohs( ipAddr.sin_port ) );
}
}
}

View file

@ -0,0 +1,612 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef DEDICATED
#include <stdlib.h>
#include <assert.h>
#include <SDL/SDL.h>
#include "PlatformWin32/platformGL.h"
#include "platformLinux/platformLinux.h"
#include "Platform/platformAudio.h"
#include "platformLinux/linuxOGLVideo.h"
#include "console/console.h"
#include "Math/mPoint.h"
#include "Platform/event.h"
#include "Platform/gameInterface.h"
#include "console/consoleInternal.h"
#include "console/ast.h"
#include "Core/fileStream.h"
//------------------------------------------------------------------------------
struct CardProfile
{
const char *vendor; // manufacturer
const char *renderer; // driver name
bool safeMode; // destroy rendering context for resolution change
bool lockArray; // allow compiled vertex arrays
bool subImage; // allow glTexSubImage*
bool fogTexture; // require bound texture for combine extension
bool noEnvColor; // no texture environment color
bool clipHigh; // clip high resolutions
bool deleteContext; // delete rendering context
bool texCompress; // allow texture compression
bool interiorLock; // lock arrays for Interior render
bool skipFirstFog; // skip first two-pass fogging (dumb 3Dfx hack)
bool only16; // inhibit 32-bit resolutions
bool noArraysAlpha; // don't use glDrawArrays with a GL_ALPHA texture
const char *proFile; // explicit profile of graphic settings
};
static Vector<CardProfile> sCardProfiles(__FILE__, __LINE__);
struct ProcessorProfile
{
U16 clock; // clock range max
U16 adjust; // CPU adjust
};
static U8 sNumProcessors = 4;
static ProcessorProfile sProcessorProfiles[] =
{
{ 400, 0 },
{ 600, 5 },
{ 800, 10 },
{ 1000, 15 },
};
struct SettingProfile
{
U16 performance; // metric range max
const char *settings; // default file
};
static U8 sNumSettings = 3;
static SettingProfile sSettingProfiles[] =
{
{ 33, "LowProfile.cs" },
{ 66, "MediumProfile.cs" },
{ 100, "HighProfile.cs" },
};
//------------------------------------------------------------------------------
static void cAddCardProfile(SimObject *, S32, const char **argv)
{
CardProfile profile;
profile.vendor = dStrdup(argv[1]);
profile.renderer = dStrdup(argv[2]);
profile.safeMode = dAtob(argv[3]);
profile.lockArray = dAtob(argv[4]);
profile.subImage = dAtob(argv[5]);
profile.fogTexture = dAtob(argv[6]);
profile.noEnvColor = dAtob(argv[7]);
profile.clipHigh = dAtob(argv[8]);
profile.deleteContext = dAtob(argv[9]);
profile.texCompress = dAtob(argv[10]);
profile.interiorLock = dAtob(argv[11]);
profile.skipFirstFog = dAtob(argv[12]);
profile.only16 = dAtob(argv[13]);
profile.noArraysAlpha = dAtob(argv[14]);
if (strcmp(argv[15],""))
profile.proFile = dStrdup(argv[15]);
else
profile.proFile = NULL;
sCardProfiles.push_back(profile);
}
static void clearCardProfiles()
{
while (sCardProfiles.size())
{
dFree((char *) sCardProfiles.last().vendor);
dFree((char *) sCardProfiles.last().renderer);
dFree((char *) sCardProfiles.last().proFile);
sCardProfiles.decrement();
}
}
static void execScript(const char *scriptFile)
{
// execute the script
FileStream str;
if (!str.open(scriptFile, FileStream::Read))
return;
U32 size = str.getStreamSize();
char *script = new char[size + 1];
str.read(size, script);
str.close();
script[size] = 0;
Con::executef(2, "eval", script);
delete[] script;
}
static void profileSystem(const char *vendor, const char *renderer)
{
Con::addCommand("addCardProfile", cAddCardProfile, "addCardProfile(vendor,renderer,safeMode,lockArray,subImage,fogTexture,noEnvColor,clipHigh,deleteContext,texCompress,interiorLock,skipFirstFog,only16,noArraysAlpha,proFile);", 16, 16);
execScript("CardProfiles.cs");
const char *arch = "";
const char *os = "Linux";
char osProfiles[64];
if ( os != NULL )
{
dSprintf(osProfiles,64,"%s%sCardProfiles.cs",arch,os);
//Con::executef(2, "exec", osProfiles);
execScript(osProfiles);
}
const char *proFile = NULL;
U32 i;
for (i = 0; i < sCardProfiles.size(); ++i)
if (dStrstr(vendor, sCardProfiles[i].vendor) &&
(!dStrcmp(sCardProfiles[i].renderer, "*") ||
dStrstr(renderer, sCardProfiles[i].renderer)))
{
Con::setBoolVariable("$pref::Video::safeModeOn", sCardProfiles[i].safeMode);
Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", !sCardProfiles[i].lockArray);
Con::setBoolVariable("$pref::OpenGL::disableSubImage", !sCardProfiles[i].subImage);
Con::setBoolVariable("$pref::TS::fogTexture", sCardProfiles[i].fogTexture);
Con::setBoolVariable("$pref::OpenGL::noEnvColor", sCardProfiles[i].noEnvColor);
Con::setBoolVariable("$pref::Video::clipHigh", sCardProfiles[i].clipHigh);
Con::setBoolVariable("$pref::Video::deleteContext", true);
Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", !sCardProfiles[i].texCompress);
Con::setBoolVariable("$pref::Interior::lockArrays", sCardProfiles[i].interiorLock);
Con::setBoolVariable("$pref::TS::skipFirstFog", sCardProfiles[i].skipFirstFog);
Con::setBoolVariable("$pref::Video::only16", sCardProfiles[i].only16);
Con::setBoolVariable("$pref::OpenGL::noDrawArraysAlpha", sCardProfiles[i].noArraysAlpha);
proFile = sCardProfiles[i].proFile;
break;
}
// defaults
U16 glProfile;
if (!proFile)
{
// no driver GL profile -- make one via weighting GL extensions
glProfile = 25;
glProfile += gGLState.suppARBMultitexture * 25;
glProfile += gGLState.suppLockedArrays * 15;
glProfile += gGLState.suppVertexArrayRange * 10;
glProfile += gGLState.suppTextureEnvCombine * 5;
glProfile += gGLState.suppPackedPixels * 5;
glProfile += gGLState.suppTextureCompression * 5;
glProfile += gGLState.suppS3TC * 5;
glProfile += gGLState.suppFXT1 * 5;
Con::setBoolVariable("$pref::Video::safeModeOn", true);
Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", false);
Con::setBoolVariable("$pref::OpenGL::disableSubImage", false);
Con::setBoolVariable("$pref::TS::fogTexture", false);
Con::setBoolVariable("$pref::OpenGL::noEnvColor", false);
Con::setBoolVariable("$pref::Video::clipHigh", false);
Con::setBoolVariable("$pref::Video::deleteContext", true);
Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", false);
Con::setBoolVariable("$pref::Interior::lockArrays", true);
Con::setBoolVariable("$pref::TS::skipFirstFog", false);
Con::setBoolVariable("$pref::Video::only16", false);
Con::setBoolVariable("$pref::OpenGL::noDrawArraysAlpha", false);
}
Con::setVariable("$pref::Video::profiledVendor", vendor);
Con::setVariable("$pref::Video::profiledRenderer", renderer);
if (!Con::getBoolVariable("$DisableSystemProfiling") &&
( dStrcmp(vendor, Con::getVariable("$pref::Video::defaultsVendor")) ||
dStrcmp(renderer, Con::getVariable("$pref::Video::defaultsRenderer")) ))
{
if (proFile)
{
char settings[64];
dSprintf(settings,64,"%s.cs",proFile);
//Con::executef(2, "exec", settings);
execScript(settings);
}
else
{
U16 adjust;
// match clock with profile
for (i = 0; i < sNumProcessors; ++i)
{
adjust = sProcessorProfiles[i].adjust;
if (Platform::SystemInfo.processor.mhz < sProcessorProfiles[i].clock) break;
}
const char *settings;
// match performance metric with profile
for (i = 0; i < sNumSettings; ++i)
{
settings = sSettingProfiles[i].settings;
if (glProfile+adjust <= sSettingProfiles[i].performance) break;
}
//Con::executef(2, "exec", settings);
execScript(settings);
}
Con::setVariable("$pref::Video::defaultsVendor", vendor);
Con::setVariable("$pref::Video::defaultsRenderer", renderer);
}
// write out prefs
gEvalState.globalVars.exportVariables("$pref::*", "prefs/ClientPrefs.cs", false);
clearCardProfiles();
}
OpenGLDevice::OpenGLDevice( void )
{
initDevice( );
}
void OpenGLDevice::initDevice( void )
{
mDeviceName = "OpenGL";
mFullScreenOnly = false;
// generate valid resolutions
mResolutionList.clear( );
if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
// Yes, of course this is bad. But we
// need to support it for the dedicated
// codepath in the full client, and we
// do an SDL_Init( SDL_INIT_VIDEO ) in
// the ::activate code, anyway.
return;
}
// make sure we have desktop info
GetDesktopState( );
SDL_Rect** rects = SDL_ListModes( 0, 0 );
if( rects == 0 ) {
// eek
AssertFatal( 0, "No video modes available" );
Con::errorf( ConsoleLogEntry::General,
"No video modes available, exiting..." );
Platform::forceShutdown( 1 );
} else if( rects == (SDL_Rect**) -1 ) {
// okay, we're not fullscreen, so technically any
// dimension is possible, so let's just use some
// nice defaults
int defaults[5][2] = { { 640, 480 },
{ 800, 600 },
{ 1024, 768 },
{ 1280, 1024 },
{ 1600, 1200 } };
for( int i = 0; i < 5; i++ ) {
int w = defaults[i][0];
int h = defaults[i][1];
// but we don't want them too big
if( w <= linuxState.width && h <= linuxState.height ) {
Resolution rez( w, h, linuxState.bpp );
mResolutionList.push_back( rez );
}
}
} else {
for( int i = 0; rects[i] != 0; i++ ) {
Resolution rez( rects[i]->w, rects[i]->h, linuxState.bpp );
mResolutionList.push_back( rez );
}
}
if( getenv( "MESA_GLX_FX" ) == 0 ) {
putenv( "MESA_GLX_FX=f" );
}
if( getenv( "MESA_FX_NO_SIGNALS" ) == 0 ) {
putenv( "MESA_FX_NO_SIGNALS=1" );
}
}
bool OpenGLDevice::activate( U32 width, U32 height, U32 bpp, bool fullScreen )
{
const char* libraryName = Con::getVariable( "$pref::OpenGL::driver" );
assert( libraryName );
if( !dStrcmp( libraryName, "" ) ) {
libraryName = "libGL.so.1";
}
{ static bool loaded_gl = false;
if( ! loaded_gl && !QGL_Init( libraryName, "libGLU.so.1" ) ) {
return false;
}
loaded_gl = true;
}
if( !setScreenMode( width, height, bpp, fullScreen, true, false ) ) {
return false;
}
const char* vendorString = (const char*) glGetString( GL_VENDOR );
const char* rendererString = (const char*) glGetString( GL_RENDERER );
const char* versionString = (const char*) glGetString( GL_VERSION );
Con::printf( "OpenGL driver information:" );
if( vendorString ) {
Con::printf( " Vendor: %s", vendorString );
}
if( rendererString ) {
Con::printf( " Renderer: %s", rendererString );
}
if( versionString ) {
Con::printf( " Version: %s", versionString );
}
QGL_EXT_Init( );
Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
if( Con::getBoolVariable( "$DisableSystemProfiling" ) ) {
return true;
}
// profile on changed display device (including first time)
if( dStrcmp( vendorString, Con::getVariable( "$pref::Video::profiledVendor" ) ) ||
dStrcmp( rendererString, Con::getVariable( "$pref::Video::profiledRenderer" ) ) ) {
bool fullscreen = Con::getBoolVariable( "$pref::Video::fullScreen", true );
profileSystem( vendorString, rendererString );
U32 width, height, bpp;
const char* resolution = Con::getVariable( "$pref::Video::resolution" );
// restart the system now that we've possibly changed
// things from the exec calls in profileSystem().
dSscanf( resolution, "%d %d %d", &width, &height, &bpp );
setScreenMode( width, height, bpp, fullscreen, false, false );
}
return true;
}
void OpenGLDevice::shutdown( void )
{
Con::printf( "Shutting down video subsystem..." );
linuxState.videoInitted = false;
}
bool OpenGLDevice::setScreenMode( U32 width,
U32 height,
U32 bpp,
bool fullScreen,
bool forceIt,
bool repaint )
{
bool needResurrect = false;
// shutdown if we're already up
if( linuxState.videoInitted ) {
Con::printf( "Killing the texture manager..." );
Game->textureKill( );
needResurrect = true;
}
if( bpp != 16 && bpp != 32 ) {
// Occurs because T2 passes 'Default' to atoi()
// which is passed down as the bpp. Is usually
// converted to '0', but we'll play it safe.
bpp = linuxState.bpp;
}
int flags = SDL_OPENGL;
if( fullScreen ) {
flags |= SDL_FULLSCREEN;
}
Con::setBoolVariable( "$pref::Video::fullScreen", fullScreen );
Con::printf( "Setting video mode to %d %d %d (%s)...",
width, height, bpp,
( fullScreen ? "fs" : "w" ) );
// these are the deafults in SDL, actually
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
return false;
}
linuxState.videoInitted = true;
if( needResurrect ) {
Con::printf( "Resurrecting the texture manager..." );
Game->textureResurrect( );
}
// Save the current resolution for fullscreen toggling
if ( SDL_GetVideoSurface()->flags & SDL_FULLSCREEN ) {
smIsFullScreen = true;
} else {
smIsFullScreen = false;
}
smCurrentRes = Resolution( width, height, bpp );
Platform::setWindowSize( smCurrentRes.w, smCurrentRes.h );
char buffer[16];
dSprintf( buffer, sizeof( buffer ), "%d %d %d",
smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
Con::setVariable( "$pref::Video::resolution", buffer );
if( repaint ) {
Con::evaluate( "resetCanvas();" );
}
return true;
}
void OpenGLDevice::swapBuffers( void )
{
SDL_GL_SwapBuffers( );
}
const char* OpenGLDevice::getDriverInfo( void )
{
const char* vendor = (const char*) glGetString( GL_VENDOR );
const char* renderer = (const char*) glGetString( GL_RENDERER );
const char* version = (const char*) glGetString( GL_VERSION );
const char* extensions = (const char*) glGetString( GL_EXTENSIONS );
U32 length = 4;
if( vendor ) {
length += dStrlen( vendor );
}
if( renderer ) {
length += dStrlen( renderer );
}
if( version ) {
length += dStrlen( version );
}
if( extensions ) {
length += dStrlen( extensions );
}
char* info = Con::getReturnBuffer( length );
dSprintf( info, length, "%s\t%s\t%s\t%s",
( vendor ? vendor : "" ),
( renderer ? renderer : "" ),
( version ? version : "" ),
( extensions ? extensions : "" ) );
return info;
}
extern "C" int SDL_GetGamma( float* red, float* green, float* blue );
bool OpenGLDevice::getGammaCorrection( F32& gamma )
{
#ifdef USE_GAMMA_RAMPS
U16 red[256];
U16 green[256];
U16 blue[256];
if( SDL_GetGammaRamp( red, green, blue ) == -1 ) {
return false;
}
F32 sum = 0.0f;
U32 count = 0;
for( U16 i = 1; i < 256; i++ ) {
if( red[i] != 0 && red[i] != 65535 ) {
F64 b = i / 256.0;
F64 a = red[i] / 65535.0;
F32 c = mLog( a ) / mLog( b );
sum += c;
count++;
}
}
gamma = sum / count;
return true;
#else
F32 red = 0;
F32 green = 0;
F32 blue = 0;
int result = SDL_GetGamma( &red, &green, &blue );
gamma = ( red + green + blue ) / 3.0f;
return ( result != -1 );
#endif
}
bool OpenGLDevice::setGammaCorrection( F32 gamma )
{
#ifdef USE_GAMMA_RAMPS
U16 red[256];
U16 green[256];
U16 blue[256];
for( U16 i = 0; i < 256; i++ ) {
red[i] = mPow( static_cast<F32>( i ) / 256.0f, gamma ) * 65535.0f;
}
dMemcpy( green, red, sizeof( green ) );
dMemcpy( blue, red, sizeof( blue ) );
int result = SDL_SetGammaRamp( red, green, blue );
return ( result != -1 );
#else
// no idea why these are foo
gamma = 2.0f - gamma;
return ( SDL_SetGamma( gamma, gamma, gamma ) );
#endif
}
bool OpenGLDevice::setVerticalSync( bool on )
{
// Implement this is you want to...
on;
return( false );
}
DisplayDevice* OpenGLDevice::create( void )
{
// NOTE: We're skipping all that awful hoodoo about checking
// for a fullscreen only implementation.
OpenGLDevice* device = new OpenGLDevice( );
return device;
}
#endif

View file

@ -0,0 +1,40 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _LINUXOGLVIDEO_H_
#define _LINUXOGLVIDEO_H_
#ifndef _PLATFORMVIDEO_H_
#include "Platform/platformVideo.h"
#endif
class OpenGLDevice : public DisplayDevice
{
public:
OpenGLDevice( );
void initDevice( void );
bool activate( U32 width, U32 height, U32 bpp, bool fullScreen );
void shutdown( void );
void destroy( void );
bool setScreenMode( U32 width,
U32 height,
U32 bpp,
bool fullScree,
bool forceIt = false,
bool repaint = true );
void swapBuffers( void );
const char* getDriverInfo( void );
bool getGammaCorrection( F32& gamma );
bool setGammaCorrection( F32 gamma );
bool setVerticalSync( bool on );
static DisplayDevice* create( void );
};
#endif

View file

@ -0,0 +1,241 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifdef DYNAMIC_LINKING
#include <dlfcn.h>
#endif
#include "engine/console/console.h"
#include "engine/platformLinux/lokiOpenAL.h"
#include <AL/altypes.h>
#include <AL/alctypes.h>
#include <AL/alexttypes.h>
static void *hinstOpenAL = NULL;
// Stub functions: ---------------------------------------------------------
// AL:
ALvoid stub_alEnable( ALenum ) {}
ALvoid stub_alDisable( ALenum ) {}
ALboolean stub_alIsEnabled( ALenum ) {return(AL_FALSE);}
ALvoid stub_alHint( ALenum , ALenum ) {}
ALboolean stub_alGetBoolean( ALenum ) {return(AL_FALSE);}
ALint stub_alGetInteger( ALenum ) {return(0);}
ALfloat stub_alGetFloat( ALenum ) {return(0.f);}
ALdouble stub_alGetDouble( ALenum ) {return(0.f);}
ALvoid stub_alGetBooleanv( ALenum, ALboolean* ) {}
ALvoid stub_alGetIntegerv( ALenum, ALint* ) {}
ALvoid stub_alGetFloatv( ALenum, ALfloat* ) {}
ALvoid stub_alGetDoublev( ALenum, ALdouble* ) {}
const ALubyte* stub_alGetString( ALenum pname )
{
switch(pname)
{
case AL_VENDOR: return (ALubyte*)"None";
case AL_VERSION: return (ALubyte*)"OpenAL 0.1";
case AL_RENDERER: return (ALubyte*)"None";
case AL_EXTENSIONS: return (ALubyte*)"";
}
return(0);
}
ALenum stub_alGetError( ALvoid ) {return(0);}
ALboolean stub_alIsExtensionPresent( const ALubyte* ) {return(AL_FALSE);}
ALvoid* stub_alGetProcAddress( const ALubyte* ) {return(0);}
ALenum stub_alGetEnumValue( const ALubyte* ) {return(0);}
ALvoid stub_alListenerf( ALenum, ALfloat ) {}
ALvoid stub_alListener3f( ALenum, ALfloat, ALfloat, ALfloat ) {}
ALvoid stub_alListenerfv( ALenum, ALfloat* ) {}
ALvoid stub_alGetListeneri( ALenum, ALint* ) {}
ALvoid stub_alGetListenerf( ALenum, ALfloat* ) {}
ALvoid stub_alGetListenerfv( ALenum, ALfloat* ) {}
ALvoid stub_alGenSources( ALsizei, ALuint* ) {}
ALvoid stub_alDeleteSources( ALsizei, ALuint* ) {}
ALboolean stub_alIsSource( ALuint ) {return(AL_FALSE);}
ALvoid stub_alSourcei( ALuint, ALenum, ALint ) {}
ALvoid stub_alSourcef( ALuint, ALenum, ALfloat ) {}
ALvoid stub_alSource3f( ALuint, ALenum, ALfloat, ALfloat, ALfloat ) {}
ALvoid stub_alSourcefv( ALuint, ALenum, ALfloat* ) {}
ALvoid stub_alGetSourcei( ALuint, ALenum, ALint* ) {}
ALvoid stub_alGetSourcef( ALuint, ALenum, ALfloat* ) {}
ALvoid stub_alGetSourcefv( ALuint, ALenum, ALfloat* ) {}
ALvoid stub_alSourcePlayv( ALuint, ALuint* ) {}
ALvoid stub_alSourceStopv( ALuint, ALuint* ) {}
ALvoid stub_alSourcePlay( ALuint ) {}
ALvoid stub_alSourcePause( ALuint ) {}
ALvoid stub_alSourceStop( ALuint ) {}
ALvoid stub_alGenBuffers( ALsizei, ALuint* ) {}
ALvoid stub_alDeleteBuffers( ALsizei, ALuint* ) {}
ALboolean stub_alIsBuffer( ALuint ) {return(AL_FALSE);}
ALvoid stub_alBufferData( ALuint, ALenum, ALvoid*, ALsizei, ALsizei ) {}
ALsizei stub_alBufferAppendData( ALuint, ALenum, ALvoid*, ALsizei, ALsizei ) {return(0);}
ALvoid stub_alGetBufferi( ALuint, ALenum, ALint* ) {}
ALvoid stub_alGetBufferf( ALuint, ALenum, ALfloat* ) {}
// ALC:
ALvoid* stub_alcCreateContext( ALint *) {return(0);}
ALCenum stub_alcMakeContextCurrent( ALvoid *) {return(ALC_INVALID);}
ALvoid* stub_alcUpdateContext( ALvoid * ) {return(0);}
ALCenum stub_alcDestroyContext( ALvoid * ) {return(ALC_INVALID);}
ALCenum stub_alcGetError( ALvoid ) {return(ALC_INVALID);}
const ALubyte* stub_alcGetErrorString( ALvoid ) {return(0);}
ALvoid* stub_alcGetCurrentContext( ALvoid ) {return(0);}
// ALUT:
void stub_alutInit( int *, char ** ) {}
void stub_alutExit( ALvoid ) {}
ALboolean stub_alutLoadWAV( const char *, ALvoid **, ALsizei *, ALsizei *, ALsizei *, ALsizei *) {return(AL_FALSE);}
// Extension: IASIG
ALvoid stub_alGenEnvironmentIASIG( ALsizei, ALuint* ) {}
ALvoid stub_alDeleteEnvironmentIASIG( ALsizei, ALuint*) {}
ALboolean stub_alIsEnvironmentIASIG( ALuint ) {return(AL_FALSE);}
ALvoid stub_alEnvironmentiIASIG( ALuint, ALenum, ALint ) {}
ALvoid stub_alEnvironmentfIASIG( ALuint, ALenum, ALfloat ) {}
ALvoid stub_alGetEnvironmentiIASIG_EXT( ALuint, ALenum, ALint * ) {}
ALvoid stub_alGetEnvironmentfIASIG_EXT( ALuint, ALenum, ALfloat * ) {}
// Extension: Dynamix
ALboolean stub_alBufferi_EXT( ALuint, ALenum, ALint ) { return(AL_FALSE); }
ALboolean stub_alBufferSyncData_EXT( ALuint, ALenum, ALvoid *, ALsizei, ALsizei ) {return(AL_FALSE); }
ALboolean stub_alBufferStreamFile_EXT( ALuint, const ALubyte * ) { return(AL_FALSE); }
ALboolean stub_alSourceCallback_EXT( ALuint, ALvoid * ) { return(AL_FALSE); }
ALvoid stub_alSourceResetEnvironment_EXT( ALuint ) {}
ALboolean stub_alContexti_EXT( ALenum, ALint) { return(AL_FALSE); }
ALboolean stub_alGetContexti_EXT( ALenum, ALint * ) { return(AL_FALSE); }
ALboolean stub_alGetContextstr_EXT( ALenum, ALuint, ALubyte ** ) { return(AL_FALSE); }
ALboolean stub_alCaptureInit_EXT( ALenum, ALuint, ALsizei ) { return(AL_FALSE); }
ALboolean stub_alCaptureDestroy_EXT( ALvoid ) { return(AL_FALSE); }
ALboolean stub_alCaptureStart_EXT( ALvoid ) { return(AL_FALSE); }
ALboolean stub_alCaptureStop_EXT( ALvoid ) { return(AL_FALSE); }
ALsizei stub_alCaptureGetData_EXT( ALvoid *, ALsizei, ALenum, ALuint ) { return(AL_FALSE); }
// declare OpenAL functions
#define AL_EXTENSION(ext_name) bool gDoesSupport_##ext_name = false;
#define AL_FUNCTION(fn_return,fn_name,fn_args) fn_return (*fn_name)fn_args = stub_##fn_name;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) fn_return (*fn_name)fn_args = stub_##fn_name;
#include "lib/openal/win32/openALFn.h"
// DLL's: ------------------------------------------------------------------
static bool findExtension( const char* name )
{
bool result = false;
if (alGetString != NULL)
{
result = dStrstr( (const char*)alGetString(AL_EXTENSIONS), name) != NULL;
}
return result;
}
static bool bindFunction( void *&fnAddress, const char *name )
{
#ifdef DYNAMIC_LINKING
fnAddress = dlsym( hinstOpenAL, name );
if( !fnAddress )
Con::errorf(ConsoleLogEntry::General, " Missing OpenAL function '%s'", name);
return (fnAddress != NULL);
#endif // DYNAMIC_LINKING
}
static void bindExtension( void *&fnAddress, const char *name, bool &supported )
{
if (supported)
{
bindFunction(fnAddress, name);
if (fnAddress == NULL)
supported = NULL;
}
else
fnAddress = NULL;
}
static bool bindDLLFunctions()
{
bool result = true;
#define AL_FUNCTION(fn_return,fn_name,fn_args) result &= bindFunction( *(void**)&fn_name, #fn_name);
#include "lib/openal/win32/openALFn.h"
return result;
}
// Stub: -------------------------------------------------------------------
static void bindStubFunctions()
{
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = false;
#define AL_FUNCTION(fn_return,fn_name,fn_parms) fn_name = stub_##fn_name;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) fn_name = stub_##fn_name;
#include "lib/openal/win32/openALFn.h"
}
namespace Audio
{
static bool sStaticLibrary;
void libraryShutdown()
{
#ifdef DYNAMIC_LINKING
if (hinstOpenAL)
dlclose(hinstOpenAL);
hinstOpenAL = NULL;
#endif // DYNAMIC_LINKING
// static drivers...
unbindOpenALFunctions();
bindStubFunctions();
sStaticLibrary = true;
}
bool libraryInit(const char *library)
{
libraryShutdown();
if(!library || !library[0])
return(false);
// static drivers...
if(!dStricmp(library, "OpenAL"))
{
if ( bindOpenALFunctions() ) {
return(true);
}
libraryShutdown();
}
#ifdef DYNAMIC_LINKING
hinstOpenAL = dlopen( avar("./%s.so", library), RTLD_NOW );
if(hinstOpenAL != NULL)
{
if(bindDLLFunctions())
{
sStaticLibrary = false;
return(true);
}
libraryShutdown();
}
#endif // DYNAMIC_LINKING
return(false);
}
void libraryInitExtensions()
{
// static library extensions are bound on libraryInit (need to be defined anyways...)
if(sStaticLibrary)
{
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = findExtension( #ext_name );
#include "lib/openal/win32/openALFn.h"
}
else
{
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = findExtension( #ext_name );
#define AL_EXT_FUNCTION(ext_name, fn_return,fn_name,fn_args) bindExtension( *(void**)&fn_name, #fn_name, gDoesSupport_##ext_name );
#include "lib/openal/win32/openALFn.h"
}
}
} // end namespace Audio

View file

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <SDL/SDL.h>
#include <stdlib.h>
#include <unistd.h>
#include "platformLinux/platformLinux.h"
#include "console/console.h"
void Platform::postQuitMessage( const U32 value )
{
#ifdef DEDICATED
linuxPostQuitMessage( );
#else
SDL_Event event;
event.type = SDL_QUIT;
SDL_PushEvent( &event );
#endif
}
void Platform::debugBreak( void )
{
__asm__( "int $03" );
}
void Platform::forceShutdown( S32 value )
{
// We have to use _exit() because of really bad
// global constructor/destructor mojo they have.
#ifdef DEDICATED
_exit( value );
#else
SDL_Quit( );
_exit( value );
#endif
}

View file

@ -0,0 +1,205 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef DEDICATED
#include <SDL/SDL.h>
#include "platformLinux/platformLinux.h"
#include "Platform/platformRedBook.h"
#include "PlatformWin32/platformAL.h"
class LinuxRedBookDevice : public RedBookDevice
{
private:
int mDeviceId;
SDL_CD* cdrom;
void setLastError( const char* );
public:
LinuxRedBookDevice( int id = -1 );
~LinuxRedBookDevice( void );
U32 getDeviceId( void );
bool open( void );
bool close( void );
bool play( U32 );
bool stop( void );
bool getTrackCount( U32* );
bool getVolume( F32* );
bool setVolume( F32 );
};
static ALfloat (*alcGetAudioChannel)( ALuint channel ) = 0;
static void (*alcSetAudioChannel)( ALuint channel, ALfloat value ) = 0;
void installRedBookDevices( void )
{
if( SDL_Init( SDL_INIT_CDROM ) < 0 ) {
return;
}
int numCDs = SDL_CDNumDrives( );
if( numCDs <= 0 ) {
return;
}
for( int i = 0; i < numCDs; i++ ) {
SDL_CD* temp = SDL_CDOpen( i );
if( temp ) {
LinuxRedBookDevice* device = new LinuxRedBookDevice( i );
const char* name = SDL_CDName( i );
device->mDeviceName = new char[ dStrlen( name ) + 1 ];
dStrcpy( device->mDeviceName, name );
RedBook::installDevice( device );
SDL_CDClose( temp );
}
}
}
LinuxRedBookDevice::LinuxRedBookDevice( int id )
: mDeviceId( id ), cdrom( 0 )
{
// empty
}
LinuxRedBookDevice::~LinuxRedBookDevice( void )
{
close( );
}
U32 LinuxRedBookDevice::getDeviceId( void )
{
return static_cast<U32>( mDeviceId );
}
bool LinuxRedBookDevice::open( void )
{
if( mAcquired ) {
setLastError( "already open" );
return false;
}
cdrom = SDL_CDOpen( mDeviceId );
if( !cdrom ) {
setLastError( "open failed" );
return false;
}
mAcquired = true;
return true;
}
bool LinuxRedBookDevice::close( void )
{
if( !mAcquired ) {
setLastError( "not acquired" );
return false;
}
stop( );
if( cdrom ) {
SDL_CDClose( cdrom );
cdrom = 0;
}
mAcquired = false;
return true;
}
bool LinuxRedBookDevice::play( U32 track )
{
if( !mAcquired ) {
setLastError( "not acquired" );
return false;
}
if( track >= cdrom->numtracks ) {
setLastError( "track out of range" );
return false;
}
if( CD_INDRIVE( SDL_CDStatus( cdrom ) ) ) {
if( SDL_CDPlayTracks( cdrom, track, 0, 0, cdrom->track[track].length ) ) {
setLastError( SDL_GetError( ) );
return false;
}
}
return true;
}
bool LinuxRedBookDevice::stop( void )
{
if( !mAcquired ) {
setLastError( "not acquired" );
return false;
}
if( SDL_CDStop( cdrom ) ) {
setLastError( SDL_GetError( ) );
return false;
}
return true;
}
bool LinuxRedBookDevice::getTrackCount( U32* numTracks )
{
if( !mAcquired ) {
setLastError( "not acquried" );
return false;
}
return cdrom->numtracks;
}
bool LinuxRedBookDevice::getVolume( F32* volume )
{
if( volume && alcGetAudioChannel ) {
*volume = alcGetAudioChannel( ALC_CHAN_CD_LOKI );
return true;
}
return false;
}
bool LinuxRedBookDevice::setVolume( F32 volume )
{
if( alcSetAudioChannel ) {
alcSetAudioChannel( ALC_CHAN_CD_LOKI, volume );
return true;
}
return false;
}
void LinuxRedBookDevice::setLastError( const char* error )
{
RedBook::setLastError( error );
}
#endif

View file

@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platformSemaphore.h"
#include <semaphore.h>
void* Semaphore::createSemaphore( U32 initialCount )
{
sem_t* sem = new sem_t;
if( sem ) {
if( sem_init( sem, 0, initialCount ) ) {
delete sem;
return 0;
}
}
return sem;
}
void Semaphore::destroySemaphore( void* semaphore )
{
if( semaphore ) {
sem_t* sem = (sem_t*) semaphore;
sem_destroy( sem );
delete sem;
}
}
bool Semaphore::acquireSemaphore( void* semaphore, bool block )
{
bool r = false;
if( !semaphore ) {
return false;
}
sem_t* sem = (sem_t*) semaphore;
if( block ) {
sem_wait( sem );
r = true;
} else {
if( sem_trywait( sem ) == 0 ) {
r = true;
} else {
r = false;
}
}
return r;
}
void Semaphore::releaseSemaphore( void* semaphore )
{
if( semaphore ) {
sem_post( (sem_t*) semaphore );
}
}

View file

@ -0,0 +1,229 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdlib.h>
#include "platformLinux/platformLinux.h"
// dMalloc heap.
char* dStrdup_r( const char* s, const char *fileName, U32 lineNumber )
{
char* sp = (char*) dMalloc_r( dStrlen( s ) + 1, fileName, lineNumber );
dStrcpy( sp, s );
return sp;
}
char* dStrcat( char* d, const char* s )
{
return strcat( d, s );
}
char* dStrncat( char* d, const char* s, size_t n )
{
return strncat( d, s, n );
}
S32 dStrcmp( const char* s1, const char* s2 )
{
return strcmp( s1, s2 );
}
S32 dStricmp( const char* s1, const char* s2 )
{
return strcasecmp( s1, s2 );
}
S32 dStrncmp( const char* s1, const char* s2, U32 n )
{
return strncmp( s1, s2, n );
}
S32 dStrnicmp( const char* s1, const char* s2, U32 n )
{
return strncasecmp( s1, s2, n );
}
char* dStrcpy( char* d, const char* s )
{
return strcpy( d, s );
}
char* dStrncpy( char* d, const char* s, U32 n )
{
return strncpy( d, s, n );
}
U32 dStrlen( const char* s )
{
return strlen( s );
}
char* dStrupr( char* s )
{
U32 l = dStrlen( s );
for( int i = 0; i < l; i++ ) {
s[i] = toupper( s[i] );
}
return s;
}
char* dStrlwr( char* s )
{
U32 l = dStrlen( s );
for( int i = 0; i < l; i++ ) {
s[i] = tolower( s[i] );
}
return s;
}
char* dStrchr( char* s, S32 c )
{
return strchr( s, c );
}
const char* dStrchr( const char* s, S32 c )
{
return strchr( s, c );
}
char* dStrrchr( char* s, S32 c )
{
return strrchr( s, c );
}
const char* dStrrchr( const char* s, S32 c )
{
return strrchr( s, c );
}
U32 dStrspn( const char* s, const char* t )
{
return strspn( s, t );
}
U32 dStrcspn( const char* s, const char* t )
{
return strcspn( s, t );
}
char* dStrstr( char* s1, char* s2 )
{
return strstr( s1, s2 );
}
const char* dStrstr( const char* s1, const char* s2 )
{
return strstr( s1, s2 );
}
char* dStrtok( char* s, const char* t )
{
return strtok( s, t );
}
S32 dAtoi( const char* s )
{
return static_cast<S32>( atoi( s ) );
}
F32 dAtof( const char* s )
{
double f = atof( s );
if( isinf( f ) ) {
return 0.0f;
}
return static_cast<F32>( f );
}
bool dAtob( const char* s )
{
return !dStricmp( s, "true" ) || dAtof( s );
}
bool dIsalnum( const char c )
{
return isalnum( c );
}
bool dIsalpha( const char c )
{
return isalpha( c );
}
bool dIsspace( const char c )
{
return isspace( c );
}
bool dIsdigit( const char c )
{
return isdigit( c );
}
void dPrintf( const char* f, ... )
{
va_list a;
va_start( a, f );
vprintf( f, a );
va_end( a );
}
S32 dVprintf( const char* f, void* a )
{
S32 l = vprintf( f, (va_list) a );
// supposedly we're going to do something neat here.
return l;
}
S32 dSprintf( char* b, U32 n, const char* f, ... )
{
va_list a;
va_start( a, f );
S32 l = vsnprintf( b, n, f, a );
va_end( a );
return l;
}
S32 dVsprintf( char* b, U32 n, const char* f, void* a )
{
S32 l = vsnprintf( b, n, f, (va_list) a );
return l;
}
S32 dSscanf( const char* b, const char* f, ... )
{
va_list a;
va_start( a, f );
S32 l = vsscanf( b, f, a );
va_end( a );
return l;
}
S32 dFflushStdout( void )
{
return fflush( stdout );
}
S32 dFflushStderr( void )
{
return fflush( stderr );
}
void dQsort( void* b, U32 n, U32 w, S32 (QSORT_CALLBACK* f)( const void*, const void* ) )
{
qsort( b, n, w, f );
}

View file

@ -0,0 +1,118 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platformThread.h"
#include "Platform/platformSemaphore.h"
#include <pthread.h>
typedef struct {
ThreadRunFunction mRunFunc;
S32 mRunArg;
Thread* mThread;
void* mSemaphore;
LinuxThreadData( void ) {
mRunFunc = 0;
mRunArg = 0;
mThread = 0;
mSemaphore = 0;
}
} LinuxThreadData;
Thread::Thread( ThreadRunFunction func, S32 arg, bool start_thread )
{
LinuxThreadData* threadData = new LinuxThreadData( );
threadData->mRunFunc = func;
threadData->mRunArg = arg;
threadData->mThread = this;
threadData->mSemaphore = Semaphore::createSemaphore( );
mData = threadData;
if ( start_thread ) {
start( );
}
}
Thread::~Thread( void )
{
join( );
LinuxThreadData* threadData = reinterpret_cast<LinuxThreadData*>( mData );
Semaphore::destroySemaphore( threadData->mSemaphore );
delete threadData;
}
static int threadRunHandler( void* arg )
{
LinuxThreadData* threadData = reinterpret_cast<LinuxThreadData*>( arg );
threadData->mThread->run( threadData->mRunArg );
Semaphore::releaseSemaphore( threadData->mSemaphore );
return 0;
}
typedef void* (*pthread_func)( void* );
void Thread::start( void )
{
if( isAlive( ) ) {
return;
}
LinuxThreadData* threadData = reinterpret_cast<LinuxThreadData*>( mData );
Semaphore::acquireSemaphore( threadData->mSemaphore );
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
pthread_create( &thread, &attr, (pthread_func) threadRunHandler, threadData );
}
bool Thread::join( void )
{
if( !isAlive( ) ) {
return false;
}
LinuxThreadData* threadData = reinterpret_cast<LinuxThreadData*>( mData );
bool result = Semaphore::acquireSemaphore( threadData->mSemaphore );
return result;
}
void Thread::run( S32 arg )
{
LinuxThreadData* threadData = reinterpret_cast<LinuxThreadData*>( mData );
if( threadData->mRunFunc ) {
threadData->mRunFunc( arg );
}
}
bool Thread::isAlive( void )
{
LinuxThreadData* threadData = reinterpret_cast<LinuxThreadData*>( mData );
bool signal = Semaphore::acquireSemaphore( threadData->mSemaphore, false );
if( signal ) {
Semaphore::releaseSemaphore( threadData->mSemaphore );
}
return !signal;
}

139
platformLinux/linuxTime.cc Normal file
View file

@ -0,0 +1,139 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include "platformLinux/platformLinux.h"
static U32 virtualTime = 0;
#if !defined(__i386__)
#define USE_GETTIMEOFDAY
#endif
#ifdef USE_GETTIMEOFDAY
/* gettimeofday() based time implementation */
static struct timeval start;
void linuxInitTicks( void )
{
gettimeofday( &start, 0 );
}
static inline U32 linuxGetTicks( void )
{
struct timeval now;
U32 ticks;
gettimeofday( &now, 0 );
ticks = ( now.tv_sec - start.tv_sec ) * 1000 + ( now.tv_usec - start.tv_usec ) / 1000;
return ticks;
}
#else
/* rdtsc based time implementation */
static unsigned long long int start;
static unsigned long long int freq;
static unsigned int cpu_KHz(void)
{
struct timeval t1, t2;
unsigned long long int r1, r2;
unsigned int z1, z2;
unsigned int ms;
int delta;
const int max_delta = 1;
int tries;
const int max_tries = 20;
tries = 0;
z2 = 0;
do {
z1 = z2;
gettimeofday(&t1, NULL);
__asm__ __volatile__ ("rdtsc" : "=A" (r1));
do {
gettimeofday(&t2, NULL);
ms = (t2.tv_sec-t1.tv_sec)*1000 +
(t2.tv_usec-t1.tv_usec)/1000;
} while ( ms < 100 );
__asm__ __volatile__ ("rdtsc" : "=A" (r2));
z2 = (r2-r1)/ms;
if ( z2 > z1 ) {
delta = (int)(z2 - z1);
} else {
delta = (int)(z1 - z2);
}
} while ( (delta > max_delta) && (tries++ < max_tries) );
return(z2);
}
void linuxInitTicks( void )
{
__asm__ ("rdtsc" : "=A" (start));
freq = cpu_KHz();
}
static inline U32 linuxGetTicks( void )
{
unsigned long long int ticks;
__asm__ ("rdtsc" : "=A" (ticks));
return (U32)((ticks-start)/freq);
}
#endif /* USE_GETTIMEOFDAY */
void Platform::getLocalTime( LocalTime &lt )
{
struct tm *systime;
time_t long_time;
time( &long_time );
systime = localtime( &long_time );
lt.sec = systime->tm_sec;
lt.min = systime->tm_min;
lt.hour = systime->tm_hour;
lt.month = systime->tm_mon;
lt.monthday = systime->tm_mday;
lt.weekday = systime->tm_wday;
lt.year = systime->tm_year;
lt.yearday = systime->tm_yday;
lt.isdst = systime->tm_isdst;
}
U32 Platform::getTime( void )
{
time_t when;
time( &when );
return static_cast<U32>( when );
}
U32 Platform::getRealMilliseconds( void )
{
return linuxGetTicks( );
}
U32 Platform::getVirtualMilliseconds( void )
{
return virtualTime;
}
void Platform::advanceTime( U32 delta )
{
virtualTime += delta;
}

1026
platformLinux/linuxWindow.cc Normal file

File diff suppressed because it is too large Load diff

866
platformLinux/lokiOpenAL.cc Normal file
View file

@ -0,0 +1,866 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifdef DEDICATED
// Stubs for the dedicated server
bool bindOpenALFunctions(void)
{
return false;
}
void unbindOpenALFunctions(void)
{
return;
}
#else
// Code for the Linux client
#include <dlfcn.h>
#include "engine/console/console.h"
#include "engine/core/fileio.h"
#include "engine/core/tVector.h"
#include "engine/platformWIN32/platformAL.h"
// For the MP3 playback support
#include "SDL.h"
#include "smpeg.h"
static void *hinstOpenAL = NULL;
// declare DLL loaded OpenAL functions
#define AL_FUNCTION(fn_return,fn_name,fn_args) fn_return (*OpenAL_##fn_name)fn_args = NULL;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) fn_return (*OpenAL_##fn_name)fn_args = NULL;
// An API change in OpenAL 1.0 - the context creation takes a device handle
AL_FUNCTION(ALCdevice *, alcOpenDevice, ( const ALubyte *tokstr ));
AL_FUNCTION(ALvoid, alcCloseDevice, ( ALCdevice *dev ));
AL_FUNCTION(ALvoid, alDistanceModel, ( ALenum distanceModel ));
ALvoid* (*OpenAL10_alcCreateContext)( struct _AL_device *dev, ALint* attrlist ) = NULL;
#include "lib/openal/win32/openALFn.h"
// Loki functions: ---------------------------------------------------------
// Used by alutInit() and alutExit() for device context handling
static void *context_id;
static ALCdevice *dev;
typedef struct fakeCallbackPair_s {
U32 sid;
void (*proc)(U32, bool);
} fakeCallbackPair_t;
static Vector< fakeCallbackPair_t > fakeCallbackFake(__FILE__, __LINE__);
void alxFakeCallbackUpdate( void )
{
fakeCallbackPair_t pi;
ALuint state;
int i;
i = fakeCallbackFake.size();
while( i-- ) {
pi = fakeCallbackFake.last();
fakeCallbackFake.pop_back();
state = AL_INITIAL;
alGetSourcei( pi.sid, AL_SOURCE_STATE, &state );
if( state == AL_STOPPED )
{
Con::printf( "Calling callback for %d", pi.sid);
pi.proc( pi.sid, false );
} else {
fakeCallbackFake.push_front( pi );
}
}
}
// Code for MP3 playback support
static SMPEG *mpeg = NULL;
#define MAX_MPEG_READ 512
static ALint MP3_Callback(ALuint sid,
ALuint bid,
ALshort *outdata,
ALenum format,
ALint freq,
ALint samples)
{
int bytesRequested = samples * sizeof( ALshort );
int bytesPlayed;
int i;
if(samples > MAX_MPEG_READ) {
int first, second;
first = MP3_Callback(sid, bid, outdata, format, freq, MAX_MPEG_READ);
second = MP3_Callback(sid, bid, outdata + MAX_MPEG_READ, format, freq, samples - MAX_MPEG_READ);
return first + second;
}
if( SMPEG_status(mpeg) != SMPEG_PLAYING ) {
SMPEG_play( mpeg );
}
memset( outdata, 0, bytesRequested );
bytesPlayed = SMPEG_playAudio( mpeg, (ALubyte *) outdata, bytesRequested );
bytesPlayed /= sizeof( ALshort );
if(bytesPlayed < samples) {
SMPEG_stop( mpeg );
SMPEG_rewind( mpeg );
return bytesPlayed;
}
return samples;
}
ALboolean alutLoadMP3_LOKI(ALuint bid, ALvoid *data, ALint size)
{
void (*alBufferDataWithCallback)(ALuint bid,
int (*Callback)(ALuint, ALuint, ALshort *, ALenum, ALint, ALint));
SDL_AudioSpec spec;
alBufferDataWithCallback = (void (*)(ALuint bid,
int (*Callback)(ALuint, ALuint, ALshort *, ALenum, ALint, ALint)))
alGetProcAddress((ALubyte *) "alBufferDataWithCallback_LOKI");
if(alBufferDataWithCallback == NULL) {
Con::errorf(ConsoleLogEntry::General, "Need alBufferDataWithCallback()");
return AL_FALSE;
}
if ( mpeg != NULL ) {
SMPEG_stop(mpeg);
SMPEG_delete(mpeg);
}
mpeg = SMPEG_new_data( data, size, NULL, 0 );
if ( mpeg == NULL ) {
Con::errorf( ConsoleLogEntry::General, "Unable to allocate MP3 data");
return AL_FALSE;
}
SMPEG_wantedSpec( mpeg, &spec );
spec.freq = Con::getIntVariable( "$pref::Audio::frequency", 22050 );
spec.format = AUDIO_S16;
/* implicitly multichannel */
alBufferi_EXT( bid, AL_CHANNELS, spec.channels );
SMPEG_actualSpec( mpeg, &spec );
SMPEG_enableaudio( mpeg, 1 );
SMPEG_enablevideo( mpeg, 0 ); /* sanity check */
alBufferDataWithCallback(bid, MP3_Callback);
return AL_TRUE;
}
// AL functions
ALvoid loki_alEnable( ALenum capability )
{
OpenAL_alEnable( capability );
}
ALvoid loki_alDisable( ALenum capability )
{
OpenAL_alDisable( capability );
}
ALboolean loki_alIsEnabled( ALenum capability )
{
return OpenAL_alIsEnabled( capability );
}
ALvoid loki_alHint( ALenum target, ALenum mode )
{
OpenAL_alHint( target, mode );
}
ALboolean loki_alGetBoolean( ALenum param )
{
return OpenAL_alGetBoolean( param );
}
ALint loki_alGetInteger( ALenum param )
{
return OpenAL_alGetInteger( param );
}
ALfloat loki_alGetFloat( ALenum param )
{
return OpenAL_alGetFloat( param );
}
ALdouble loki_alGetDouble( ALenum param )
{
return OpenAL_alGetDouble( param );
}
ALvoid loki_alGetBooleanv( ALenum param, ALboolean* data )
{
OpenAL_alGetBooleanv( param, data );
}
ALvoid loki_alGetIntegerv( ALenum param, ALint* data )
{
OpenAL_alGetIntegerv( param, data );
}
ALvoid loki_alGetFloatv( ALenum param, ALfloat* data )
{
OpenAL_alGetFloatv( param, data );
}
ALvoid loki_alGetDoublev( ALenum param, ALdouble* data )
{
OpenAL_alGetDoublev( param, data );
}
const ALubyte* loki_alGetString( ALenum param )
{
const ALubyte* string;
switch (param) {
case AL_EXTENSIONS:
string = "AL_EXT_DYNAMIX";
break;
default:
string = OpenAL_alGetString( param );
break;
}
return string;
}
ALenum loki_alGetError( ALvoid )
{
ALenum error;
error = AL_NO_ERROR;
error += OpenAL_alGetError( );
error += OpenAL_alcGetError( );
return error;
}
ALboolean loki_alIsExtensionPresent( const ALubyte* fname )
{
ALboolean value;
if ( dStrcmp(fname, "AL_EXT_DYNAMIX") == 0 ) {
value = true;
} else {
value = OpenAL_alIsExtensionPresent( fname );
}
return value;
}
ALvoid* loki_alGetProcAddress( const ALubyte* fname )
{
return OpenAL_alGetProcAddress( fname );
}
ALenum loki_alGetEnumValue( const ALubyte* ename )
{
return OpenAL_alGetEnumValue( ename );
}
ALvoid loki_alListenerf( ALenum pname, ALfloat param )
{
OpenAL_alListenerf( pname, param );
}
ALvoid loki_alListener3f( ALenum pname, ALfloat param1, ALfloat param2, ALfloat param3 )
{
OpenAL_alListener3f( pname, param1, param2, param3 );
}
ALvoid loki_alListenerfv( ALenum pname, ALfloat* param )
{
OpenAL_alListenerfv( pname, param );
}
ALvoid loki_alGetListeneri( ALenum pname, ALint* value )
{
OpenAL_alGetListeneri( pname, value );
}
ALvoid loki_alGetListenerf( ALenum pname, ALfloat* values )
{
OpenAL_alGetListenerf( pname, values );
}
ALvoid loki_alGetListenerfv( ALenum pname, ALfloat* values )
{
OpenAL_alGetListenerfv( pname, values );
}
ALvoid loki_alGenSources( ALsizei n, ALuint* sources )
{
OpenAL_alGenSources( n, sources );
}
ALvoid loki_alDeleteSources( ALsizei n, ALuint* sources )
{
OpenAL_alDeleteSources( n, sources );
}
ALboolean loki_alIsSource( ALuint sid )
{
return OpenAL_alIsSource( sid );
}
ALvoid loki_alSourcei( ALuint sid, ALenum param, ALint value )
{
switch (param) {
case AL_STREAMING:
case AL_ENV_SAMPLE_DIRECT_EXT:
case AL_ENV_SAMPLE_DIRECT_HF_EXT:
case AL_ENV_SAMPLE_ROOM_EXT:
case AL_ENV_SAMPLE_ROOM_HF_EXT:
case AL_ENV_SAMPLE_OUTSIDE_VOLUME_HF_EXT:
case AL_ENV_SAMPLE_FLAGS_EXT:
// Not yet supported
break;
case AL_SOURCE_AMBIENT:
// Special case, emulated by positioning relative sources
if ( value ) {
alSourcei(sid, AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(sid, AL_POSITION, 0.0, 0.0, 0.0);
} else {
alSourcei(sid, AL_SOURCE_RELATIVE, AL_FALSE);
}
break;
default:
// Pass through to OpenAL 1.0
OpenAL_alSourcei( sid, param, value );
break;
}
}
ALvoid loki_alSourcef( ALuint sid, ALenum param, ALfloat value )
{
switch (param) {
case AL_PAN:
case AL_ENV_SAMPLE_REVERB_MIX_EXT:
case AL_ENV_SAMPLE_OBSTRUCTION_EXT:
case AL_ENV_SAMPLE_OBSTRUCTION_LF_RATIO_EXT:
case AL_ENV_SAMPLE_OCCLUSION_EXT:
case AL_ENV_SAMPLE_OCCLUSION_ROOM_RATIO_EXT:
case AL_ENV_SAMPLE_ROOM_ROLLOFF_EXT:
case AL_ENV_SAMPLE_AIR_ABSORPTION_EXT:
// Not yet supported
break;
default:
// Pass through to OpenAL 1.0
OpenAL_alSourcef( sid, param, value );
break;
}
}
ALvoid loki_alSource3f( ALuint sid, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 )
{
OpenAL_alSource3f( sid, param, v1, v2, v3 );
}
ALvoid loki_alSourcefv( ALuint sid, ALenum param, ALfloat* values )
{
OpenAL_alSourcefv( sid, param, values );
}
ALvoid loki_alGetSourcei( ALuint sid, ALenum pname, ALint* value )
{
switch (pname) {
case AL_SOURCE_AMBIENT:
// Special case, emulated by positioning relative sources
alGetSourcei(sid, AL_SOURCE_RELATIVE, value);
break;
default:
// Pass through to OpenAL 1.0
OpenAL_alGetSourcei( sid, pname, value );
break;
}
}
ALvoid loki_alGetSourcef( ALuint sid, ALenum pname, ALfloat* value )
{
OpenAL_alGetSourcef( sid, pname, value );
}
ALvoid loki_alGetSourcefv( ALuint sid, ALenum pname, ALfloat* values )
{
OpenAL_alGetSourcefv( sid, pname, values );
}
ALvoid loki_alSourcePlayv( ALuint ns, ALuint* ids )
{
OpenAL_alSourcePlayv( ns, ids );
}
ALvoid loki_alSourceStopv( ALuint ns, ALuint* ids )
{
OpenAL_alSourceStopv( ns, ids );
}
ALvoid loki_alSourcePlay( ALuint sid )
{
OpenAL_alSourcePlay( sid );
}
ALvoid loki_alSourcePause( ALuint sid )
{
OpenAL_alSourcePause( sid );
}
ALvoid loki_alSourceStop( ALuint sid )
{
OpenAL_alSourceStop( sid );
}
ALvoid loki_alGenBuffers( ALsizei n, ALuint* samples )
{
OpenAL_alGenBuffers( n, samples );
}
ALvoid loki_alDeleteBuffers( ALsizei n, ALuint* samples )
{
OpenAL_alDeleteBuffers( n, samples );
}
ALboolean loki_alIsBuffer( ALuint buffer )
{
return OpenAL_alIsBuffer( buffer );
}
ALvoid loki_alBufferData( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )
{
OpenAL_alBufferData( buffer, format, data, size, freq );
}
ALsizei loki_alBufferAppendData( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )
{
return OpenAL_alBufferAppendData( buffer, format, data, size, freq );
}
ALvoid loki_alGetBufferi( ALuint buffer, ALenum param, ALint* value )
{
OpenAL_alGetBufferi( buffer, param, value );
}
ALvoid loki_alGetBufferf( ALuint buffer, ALenum param, ALfloat* value )
{
OpenAL_alGetBufferf( buffer, param, value );
}
// ALC functions
ALvoid* loki_alcCreateContext( ALint* attrlist )
{
return OpenAL10_alcCreateContext( dev, attrlist );
}
ALCenum loki_alcMakeContextCurrent( ALvoid* context )
{
return OpenAL_alcMakeContextCurrent( context );
}
ALvoid* loki_alcUpdateContext( ALvoid* context )
{
return OpenAL_alcUpdateContext( context );
}
ALCenum loki_alcDestroyContext( ALvoid* context )
{
return OpenAL_alcDestroyContext( context );
}
ALCenum loki_alcGetError( ALvoid )
{
return OpenAL_alcGetError( );
}
const ALubyte * loki_alcGetErrorString( ALvoid )
{
return OpenAL_alcGetErrorString( );
}
ALvoid* loki_alcGetCurrentContext( ALvoid )
{
return OpenAL_alcGetCurrentContext( );
}
// ALUT functions
void loki_alutInit( int* argc, char** argv )
{
char devstr_buf[1024];
const char *devstr;
const char *paren;
int refresh, frequency;
ALint attrlist[5];
// Get some basic configuration variables
refresh = Con::getIntVariable( "$pref::Audio::refresh", 15 );
frequency = Con::getIntVariable( "$pref::Audio::frequency", 22050 );
// Open the audio device
devstr = Con::getVariable("$pref::OpenAL::driver");
if ( devstr && ((paren=strrchr(devstr, ')')) != NULL) ) {
// Make sure a sane sampling rate is specified
if ( strstr(devstr, "sampling-rate") == NULL ) {
strcpy(devstr_buf, devstr);
sprintf(&devstr_buf[paren-devstr],
" (sampling-rate %d ))", frequency);
devstr = devstr_buf;
}
} else {
sprintf(devstr_buf, "'( (sampling-rate %d ))", frequency);
devstr = devstr_buf;
}
dev = OpenAL_alcOpenDevice( (const ALubyte *) devstr );
if( dev == NULL ) {
Con::errorf( ConsoleLogEntry::General, "Audio device open failed..." );
return;
}
attrlist[0] = ALC_FREQUENCY;
attrlist[1] = frequency;
attrlist[2] = ALC_REFRESH;
attrlist[3] = refresh;
attrlist[4] = 0;
context_id = alcCreateContext( attrlist );
if( context_id == NULL ) {
Con::errorf( ConsoleLogEntry::General, "Audio context creation failed, exiting..." );
Platform::forceShutdown( 1 );
return;
}
alcMakeContextCurrent( context_id );
// Set the distance attenuation model
OpenAL_alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
}
void loki_alutExit( ALvoid )
{
if( context_id != NULL ) {
alcDestroyContext( context_id );
OpenAL_alcCloseDevice( dev );
context_id = NULL;
}
}
ALboolean loki_alutLoadWAV( const char* fname, ALvoid** data, ALsizei* format, ALsizei* size, ALsizei* bits, ALsizei* freq )
{
return OpenAL_alutLoadWAV( fname, data, format, size, bits, freq );
}
// Extensions
ALvoid loki_alGenEnvironmentIASIG( ALsizei n, ALuint* environs )
{
OpenAL_alGenEnvironmentIASIG( n, environs );
}
ALvoid loki_alDeleteEnvironmentIASIG( ALsizei n, ALuint* environs )
{
OpenAL_alDeleteEnvironmentIASIG( n, environs );
}
ALboolean loki_alIsEnvironmentIASIG( ALuint environment )
{
return OpenAL_alIsEnvironmentIASIG( environment );
}
ALvoid loki_alEnvironmentiIASIG( ALuint eid, ALenum param, ALint value )
{
OpenAL_alEnvironmentiIASIG( eid, param, value );
}
ALboolean loki_alBufferi_EXT( ALuint buffer, ALenum pname, ALint value )
{
ALboolean status;
alGetError();
switch (pname) {
case AL_BUFFER_KEEP_RESIDENT:
status = false;
break;
default:
OpenAL_alBufferi_EXT( buffer, pname, value );
status = (alGetError() == AL_NO_ERROR);
break;
}
return status;
}
ALboolean loki_alBufferSyncData_EXT( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )
{
ALboolean status;
// alBufferData doesn't return a value,
// so clear the error setting, execute,
// and check again.
alGetError( );
alBufferData(buffer, format, data, size, freq);
if( alGetError( ) == AL_NO_ERROR ) {
// let AL manage the memory
dFree( data );
status = true;
} else {
status = false;
}
return status;
}
ALboolean loki_alBufferStreamFile_EXT( ALuint buffer, const ALubyte* filename )
{
File file;
file.open( (const char*) filename, File::Read );
if( file.getStatus( ) != File::Ok ) {
return AL_FALSE;
}
U32 size = file.getSize( );
char* data = (char*) dMalloc( size );
if( data == NULL ) {
// technically, 'file' will go out of scope and
// close itself, but still...
file.close( );
return AL_FALSE;
}
file.read( size, data );
if( file.getStatus( ) != File::Ok ) {
file.close( );
dFree( data );
return AL_FALSE;
}
U32 ext = dStrlen( filename );
ext -= 3;
ext = ( ext >= 0 ) ? ext : 0;
ALuint ok = AL_FALSE;
if( dStrnicmp( &filename[ ext ], "mp3", 3 ) != 0 ) {
alGetError();
alBufferData( buffer, AL_FORMAT_WAVE_EXT, data, size, 0 );
ok = (alGetError() == AL_NO_ERROR);
} else {
ok = alutLoadMP3_LOKI( buffer, data, size );
}
dFree( data );
file.close( );
if( ok == AL_FALSE ) {
Con::warnf( ConsoleLogEntry::General,
"could not buffer and convert %s", filename );
return AL_FALSE;
}
return AL_TRUE;
}
ALboolean loki_alSourceCallback_EXT( ALuint source, ALvoid* callback )
{
fakeCallbackPair_t pusher;
if( alIsSource( source ) == AL_FALSE) {
Con::errorf(ConsoleLogEntry::General,
"alSourceCallback_EXT: %d not a source id", source );
return;
}
pusher.sid = source;
pusher.proc = callback;
fakeCallbackFake.push_back( pusher );
}
ALvoid loki_alSourceResetEnvironment_EXT( ALuint source )
{
return; // Nothing we can do here yet...
}
ALboolean loki_alContexti_EXT( ALenum pname, ALint value )
{
return false;
}
ALboolean loki_alGetContexti_EXT( ALenum pname, ALint* value )
{
ALboolean status;
status = false;
if( value ) {
switch( pname ) {
case ALC_PROVIDER:
*value = 0;
status = true;
break;
case ALC_PROVIDER_COUNT:
*value = 1;
status = true;
break;
case ALC_SPEAKER:
*value = 0;
status = true;
break;
case ALC_SPEAKER_COUNT:
*value = 1;
status = true;
break;
case ALC_BUFFER_MEMORY_USAGE:
*value = 0;
status = true;
break;
case ALC_BUFFER_MEMORY_SIZE:
*value = 1 << 16;
status = true;
break;
case ALC_BUFFER_MEMORY_COUNT:
*value = 0;
status = true;
break;
case ALC_BUFFER_COUNT:
*value = 0;
status = true;
break;
default:
// error
break;
}
}
return status;
}
ALboolean loki_alGetContextstr_EXT( ALenum pname, ALuint idx, ALubyte** value )
{
ALboolean status;
status = false;
if( value ) {
switch( pname ) {
case ALC_PROVIDER_NAME:
*value = "Loki Software, Inc.";
status = true;
break;
case ALC_SPEAKER_NAME:
*value = "Stereo, 2-Speaker";
status = true;
break;
default:
// error
break;
}
}
return status;
}
ALboolean loki_alCaptureInit_EXT( ALenum format, ALuint rate, ALsizei bufferSize )
{
return OpenAL_alCaptureInit_EXT( format, rate, bufferSize );
}
ALboolean loki_alCaptureDestroy_EXT( ALvoid )
{
return OpenAL_alCaptureDestroy_EXT( );
}
ALboolean loki_alCaptureStart_EXT( ALvoid )
{
return OpenAL_alCaptureStart_EXT( );
}
ALboolean loki_alCaptureStop_EXT( ALvoid )
{
return OpenAL_alCaptureStop_EXT( );
}
ALsizei loki_alCaptureGetData_EXT( ALvoid* data, ALsizei n, ALenum format, ALuint rate )
{
return OpenAL_alCaptureGetData_EXT( data, n, format, rate );
}
ALvoid loki_alEnvironmentfIASIG( ALuint eid, ALenum param, ALfloat value )
{
return; // Nothing we can do here yet...
}
ALvoid loki_alGetEnvironmentiIASIG_EXT( ALuint eid, ALenum param, ALint * value )
{
return; // Nothing we can do here yet...
}
ALvoid loki_alGetEnvironmentfIASIG_EXT( ALuint eid, ALenum param, ALfloat * value )
{
return; // Nothing we can do here yet...
}
// DLL's: ------------------------------------------------------------------
static bool findExtension( const char* name )
{
bool result = false;
if (alGetString != NULL)
{
result = dStrstr( (const char*)alGetString(AL_EXTENSIONS), name) != NULL;
}
return result;
}
static bool bindFunction( void *&fnAddress, const char *name )
{
fnAddress = dlsym( hinstOpenAL, name );
#ifdef DEBUG_OPENAL
if( !fnAddress ) {
Con::errorf(ConsoleLogEntry::General, " Missing OpenAL function '%s'", name);
}
#endif
return (fnAddress != NULL);
}
static void bindExtension( void *&fnAddress, const char *name, bool &supported )
{
if (supported)
{
bindFunction(fnAddress, name);
#if 0
if (fnAddress == NULL)
supported = false;
#endif
}
else
fnAddress = NULL;
}
static bool bindDLLFunctions()
{
bool result = true;
/* It's okay if the following functions are not found:
alGetBoolean()
alGetInteger()
alGetFloat()
alGetDouble()
alcUpdateContext()
alcGetErrorString()
*/
#define AL_EXTENSION(ext_name) \
gDoesSupport_##ext_name = findExtension(#ext_name);
#define AL_FUNCTION(fn_return,fn_name,fn_args) \
{ const char *name = #fn_name; \
/* Do some renaming of functions to match OpenAL 1.0 API */ \
if ( dStrcmp(name, "alGetListeneri") == 0 ) \
name = "alGetListeneriv"; \
else \
if ( dStrcmp(name, "alGetListenerf") == 0 ) \
name = "alGetListenerfv"; \
else \
if ( dStrcmp(name, "alGetSourcei") == 0 ) \
name = "alGetSourceiv"; \
else \
if ( dStrcmp(name, "alGetSourcef") == 0 ) \
name = "alGetSourcefv"; \
else \
if ( dStrcmp(name, "alBufferi_EXT") == 0 ) \
name = "alBufferi_LOKI"; \
result &= bindFunction( *(void**)&OpenAL_##fn_name, name); \
}
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) \
{ const char *name = #fn_name; \
/* Do some renaming of functions to match OpenAL 1.0 API */ \
if ( dStrcmp(name, "alBufferi_EXT") == 0 ) \
name = "alBufferi_LOKI"; \
bindExtension( *(void**)&OpenAL_##fn_name, name, gDoesSupport_##ext_name); \
}
AL_FUNCTION(ALCdevice *, alcOpenDevice, ( const ALubyte *tokstr ));
AL_FUNCTION(ALvoid, alcCloseDevice, ( ALCdevice *dev ));
AL_FUNCTION(ALvoid, alDistanceModel, ( ALenum distanceModel ));
result &= bindFunction( *(void**)&OpenAL10_alcCreateContext, "alcCreateContext");
#include "lib/openal/win32/openALFn.h"
return result;
}
bool bindOpenALFunctions(void)
{
hinstOpenAL = dlopen( "./libopenal.so.0", RTLD_NOW );
if(hinstOpenAL == NULL)
{
return false;
}
// Set the Loki OpenAL function pointers (needed for extension loading)
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = false;
#define AL_FUNCTION(fn_return,fn_name,fn_parms) fn_name = loki_##fn_name;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) fn_name = loki_##fn_name;
#include "lib/openal/win32/openALFn.h"
// Load the real OpenAL functions from the shared library
bindDLLFunctions();
// Yay, we're done!
return true;
}
void unbindOpenALFunctions(void)
{
if (hinstOpenAL)
dlclose(hinstOpenAL);
hinstOpenAL = NULL;
}
#endif // DEDICATED

View file

@ -0,0 +1,11 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
extern int bindOpenALFunctions(void);
// Unload the Loki OpenAL functions
extern void unbindOpenALFunctions(void);

View file

@ -0,0 +1,387 @@
;
; ASM implementations of mSolver code
;
; externs
extern mSolveCubic_c__FffffPf
; data
segment .data
; float constants
f_quarter dd 0.25
f_half dd 0.5
f_n_half dd -0.5
f_two dd 2.0
f_n_three dd -3.0
f_four dd 4.0
f_n_four dd -4.0
f_n_six dd -6.0
f_eight dd 8.0
; integer constants
i_n_one dd 1
; variables
i dd 0
nreal dd 0
w dd 0
b0 dd 0
b1 dd 0
b2 dd 0
d0 dd 0
d1 dd 0
h dd 0
t dd 0
z dd 0
px dd 0
cubeA dd 0
cubeB dd 0
cubeC dd 0
cubeD dd 0
p dd 0
q dd 0
dis dd 0
phi dd 0
segment .text
; functions
;
; U32 mSolveQuartic_ASM(F32 A, F32 B, F32 C, F32 D, F32 E, F32* x)
;
%define A [ebp+8]
%define B [ebp+12]
%define C [ebp+16]
%define D [ebp+20]
%define E [ebp+24]
%define x [ebp+28]
global mSolveQuartic_ASM
mSolveQuartic_ASM:
push ebp
mov ebp, esp
; if (A==0.0)
; return mSolveCubic(B, C, D, E, x);
fld dword A
fldz
fcompp
fnstsw ax
and ah, 68
xor ah, 64
jne .L1
push dword x
push dword E
push dword D
push dword C
push dword B
call mSolveCubic_c__FffffPf
add esp, byte 20
jmp .L2
.L1:
; w = B/(4*A); /* offset */
fld dword A
fmul dword [f_four]
fld dword B
fxch
fdivp st1, st0
fstp dword [w]
; b2 = -6*square(w) + C/A; /* coeffs. of shifted polynomial */
fld dword [w]
fmul st0, st0
fld dword [f_n_six]
fmulp st1, st0
fld dword C
fld dword A
fdivp st1, st0
faddp st1, st0
fstp dword [b2]
; b1 = (8*square(w) - 2*C/A)*w + D/A;
fld dword [w]
fmul st0, st0
fmul dword [f_eight]
fld dword C
fld dword A
fdivp st1, st0
fmul dword [f_two]
fsubp st1, st0
fmul dword [w]
fld dword D
fld dword A
fdivp st1, st0
faddp st1, st0
fstp dword [b1]
; b0 = ((-3*square(w) + C/A)*w - D/A)*w + E/A;
fld dword [w]
fmul st0, st0
fmul dword [f_n_three]
fld dword C
fld dword A
fdivp st1, st0
faddp st1, st0
fmul dword [w]
fld dword D
fld dword A
fdivp st1, st0
fsubp st1, st0
fmul dword [w]
fld dword E
fld dword A
fdivp st1, st0
faddp st1, st0
fstp dword [b0]
; // cubic resolvent
; F32 cubeA = 1.0;
; F32 cubeB = b2;
; F32 cubeC = -4 * b0;
; F32 cubeD = square(b1) - 4 * b0 * b2;
fld1
fstp dword [cubeA]
fld dword [b2]
fstp dword [cubeB]
fld dword [b0]
fmul dword [f_n_four]
fstp dword [cubeC]
fld dword [b1]
fmul st0, st0
fld dword [f_four]
fmul dword [b0]
fmul dword [b2]
fsubp st1, st0
fstp dword [cubeD]
; mSolveCubic(cubeA, cubeB, cubeC, cubeD, x);
push dword x
push dword [cubeD]
push dword [cubeC]
push dword [cubeB]
push dword [cubeA]
call mSolveCubic_c__FffffPf
add esp, byte 20
mov eax, dword x
; z = x[0];
fld dword [eax+0]
fstp dword [z]
; nreal = 0;
xor dword [nreal], 0
; px = x;
mov dword [px], eax
; t = mSqrt(0.25 * square(z) - b0);
fld dword [z]
fmul st0, st0
fmul dword [f_quarter]
fsub dword [b0]
fsqrt
fstp dword [t]
; for (i=-1; i<=1; i+=2) {
mov ecx, dword [i_n_one]
.L3
; d0 = -0.5*z + i*t; /* coeffs. of quadratic factor */
fld dword [f_n_half]
fmul dword [z]
fld dword [i]
fmul dword [t]
faddp st1, st0
fstp dword [d0]
; d1 = (t!=0.0)? -i*0.5*b1/t : i*mSqrt(-z - b2);
fild dword [i]
fld dword [t]
fldz
fcompp
fnstsw ax
;; if t == 0.0 jump to .L4
;; if C3 is set, jump to .L4
;; if ah & C3 is not-zero, jump to .L4
and ah, 64
jnz .L4
fchs
fmul dword [f_half]
fmul dword [b1]
fdiv dword [t]
jmp .L5
.L4:
fld dword [z]
fchs
fsub dword [b2]
fsqrt
fmulp st1, st0
.L5:
fstp dword [d1]
; h = 0.25 * square(d1) - d0;
fld dword [d1]
fmul st0, st0
fmul dword [f_quarter]
fsub dword [d0]
fst dword [h]
; if (h>=0.0) {
; h = mSqrt(h);
; nreal += 2;
; *px = -0.5*d1 - h - w;
; px++;
; *px = -0.5*d1 + h - w;
; px++;
; }
fldz
fcomp st1
; if h < 0.0, jump to .L6
; if C0 is 0, jump to .L6
; if ( ah & 0x1 ) == 0.0, jump to .L6
fnstsw ax
and ah, 0x1
jz .L6
fsqrt
fstp dword [h]
add dword [nreal], 2
fld dword [d1]
fmul dword [f_n_half]
fsub dword [h]
fsub dword [w]
fstp dword [px]
mov eax, dword [px]
add eax, 4
mov dword [px], eax
fld dword [d1]
fmul dword [f_n_half]
fadd dword [h]
fsub dword [w]
fstp dword [px]
mov eax, dword [px]
add eax, 4
mov dword [px], eax
; }
.L6:
add ecx, 2
cmp ecx, 1
jle near .L3
; // sort results in ascending order
; if (nreal == 4)
; {
mov ecx, dword [nreal]
cmp ecx, 4
jnz near .L7
mov ecx, x
; if (x[2] < x[0])
fld dword [ecx]
fld dword [ecx+8]
fcom st1
fnstsw ax
and ah, 0x1
jz .L8
; swap(x[0], x[2]);
fstp dword [ecx]
fstp dword [ecx+8]
jmp .L9
.L8:
fstp st0
fstp st0
.L9:
; if (x[3] < x[1])
fld dword [ecx+4]
fld dword [ecx+12]
fcom st1
fnstsw ax
and ah, 0x1
jz .L10
; swap(x[1], x[3]);
fstp dword [ecx+4]
fstp dword [ecx+12]
jmp .L11
.L10:
fstp st0
fstp st0
.L11:
; if (x[1] < x[0])
fld dword [ecx]
fld dword [ecx+4]
fcom st1
fnstsw ax
and ah, 0x1
jz .L12
; swap(x[0], x[1]);
fstp dword [ecx]
fstp dword [ecx+4]
jmp .L13
.L12:
fstp st0
fstp st0
.L13:
; if (x[3] < x[2])
fld dword [ecx+12]
fld dword [ecx+8]
fcom st1
fnstsw ax
and ah, 0x1
jz .L14
; swap(x[2], x[3]);
fstp dword [ecx+12]
fstp dword [ecx+8]
jmp .L15
.L14:
fstp st0
fstp st0
.L15:
; if (x[2] < x[1])
fld dword [ecx+4]
fld dword [ecx+8]
fcom st1
fnstsw ax
and ah, 0x1
jz .L16
; swap(x[1], x[2]);
fstp dword [ecx+4]
fstp dword [ecx+8]
jmp .L17
.L16:
fstp st0
fstp st0
.L17
; }
;
.L7
; return(nreal);
mov eax, dword [nreal]
.L2:
pop ebp
ret

136
platformLinux/platformAL.h Normal file
View file

@ -0,0 +1,136 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _PLATFORMAL_H_
#define _PLATFORMAL_H_
#ifndef _PLATFORM_H_
#include "engine/platform/platform.h"
#endif
#include <AL/altypes.h>
#include <AL/alctypes.h>
#include <AL/alexttypes.h>
// rename
#define AL_GAIN_LINEAR AL_GAIN_LINEAR_LOKI
#define AL_SOURCE_LOOPING AL_LOOPING
#define AL_MIN_DISTANCE AL_REFERENCE_DISTANCE
// fictional tokens
#define AL_PAN 0xFFFFFFFE
#define AL_SOURCE_AMBIENT 0xFFFFFFFD
#define AL_BUFFER_KEEP_RESIDENT 0xFFFFFFFC
#define ALC_PROVIDER 0x1FFFFFFE
#define ALC_PROVIDER_COUNT 0x1FFFFFFD
#define ALC_PROVIDER_NAME 0x1FFFFFFC
#define ALC_SPEAKER 0x1FFFFFFB
#define ALC_SPEAKER_COUNT 0x1FFFFFFA
#define ALC_SPEAKER_NAME 0x1FFFFFF9
#define ALC_BUFFER_MEMORY_USAGE 0x1FFFFFF8
#define ALC_BUFFER_MEMORY_SIZE 0x1FFFFFF7
#define ALC_BUFFER_MEMORY_COUNT 0x1FFFFFF6
#define ALC_BUFFER_COUNT 0x1FFFFFF5
#define ALC_BUFFER_DYNAMIC_MEMORY_USAGE 0x1FFFFFF4
#define ALC_BUFFER_DYNAMIC_MEMORY_SIZE 0x1FFFFFF3
#define ALC_BUFFER_DYNAMIC_MEMORY_COUNT 0x1FFFFFF2
#define ALC_BUFFER_DYNAMIC_COUNT 0x1FFFFFF1
#define ALC_BUFFER_LATENCY 0x1FFFFFF0
#define ALC_RESOLUTION 0x1FFFFFEF
#define ALC_CHANNELS 0x1FFFFFEE
#define AL_ENV_FLAGS_EXT 0x2FFFFFFE
#define AL_ENV_ROOM_VOLUME_EXT 0x2FFFFFFD
#define AL_ENV_EFFECT_VOLUME_EXT 0x2FFFFFFC
#define AL_ENV_DAMPING_EXT 0x2FFFFFFB
#define AL_ENV_ENVIRONMENT_SIZE_EXT 0x2FFFFFFA
#define AL_ENV_SAMPLE_REVERB_MIX_EXT 0x2FFFFFF9
#define AL_ENV_SAMPLE_DIRECT_EXT 0x2FFFFFF8
#define AL_ENV_SAMPLE_DIRECT_HF_EXT 0x2FFFFFF7
#define AL_ENV_SAMPLE_ROOM_EXT 0x2FFFFFF6
#define AL_ENV_SAMPLE_ROOM_HF_EXT 0x2FFFFFF5
#define AL_ENV_SAMPLE_OUTSIDE_VOLUME_HF_EXT 0x2FFFFFF4
#define AL_ENV_SAMPLE_FLAGS_EXT 0x2FFFFFF3
#define AL_ENV_SAMPLE_OBSTRUCTION_EXT 0x2FFFFFF2
#define AL_ENV_SAMPLE_OBSTRUCTION_LF_RATIO_EXT 0x2FFFFFF1
#define AL_ENV_SAMPLE_OCCLUSION_EXT 0x2FFFFFF0
#define AL_ENV_SAMPLE_OCCLUSION_LF_RATIO_EXT 0x2FFFFFEF
#define AL_ENV_SAMPLE_OCCLUSION_ROOM_RATIO_EXT 0x2FFFFFEE
#define AL_ENV_SAMPLE_ROOM_ROLLOFF_EXT 0x2FFFFFED
#define AL_ENV_SAMPLE_AIR_ABSORPTION_EXT 0x2FFFFFEC
// room types: same as miles/eax
enum {
AL_ENVIRONMENT_GENERIC = 0,
AL_ENVIRONMENT_PADDEDCELL,
AL_ENVIRONMENT_ROOM,
AL_ENVIRONMENT_BATHROOM,
AL_ENVIRONMENT_LIVINGROOM,
AL_ENVIRONMENT_STONEROOM,
AL_ENVIRONMENT_AUDITORIUM,
AL_ENVIRONMENT_CONCERTHALL,
AL_ENVIRONMENT_CAVE,
AL_ENVIRONMENT_ARENA,
AL_ENVIRONMENT_HANGAR,
AL_ENVIRONMENT_CARPETEDHALLWAY,
AL_ENVIRONMENT_HALLWAY,
AL_ENVIRONMENT_STONECORRIDOR,
AL_ENVIRONMENT_ALLEY,
AL_ENVIRONMENT_FOREST,
AL_ENVIRONMENT_CITY,
AL_ENVIRONMENT_MOUNTAINS,
AL_ENVIRONMENT_QUARRY,
AL_ENVIRONMENT_PLAIN,
AL_ENVIRONMENT_PARKINGLOT,
AL_ENVIRONMENT_SEWERPIPE,
AL_ENVIRONMENT_UNDERWATER,
AL_ENVIRONMENT_DRUGGED,
AL_ENVIRONMENT_DIZZY,
AL_ENVIRONMENT_PSYCHOTIC,
AL_ENVIRONMENT_COUNT
};
// declare OpenAL functions
#define AL_EXTENSION(ext_name) extern bool gDoesSupport_##ext_name;
#define AL_FUNCTION(fn_return,fn_name,fn_args) extern fn_return (FN_CDECL *fn_name)fn_args;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) extern fn_return (FN_CDECL *fn_name)fn_args;
#ifndef _OPENALFN_H_
#include "lib/openal/win32/openALFn.h"
#endif
namespace Audio
{
bool libraryInit(const char *library);
void libraryInitExtensions();
void libraryShutdown();
inline bool doesSupportIASIG()
{
return gDoesSupport_AL_EXT_IASIG;
}
inline bool doesSupportDynamix()
{
return gDoesSupport_AL_EXT_DYNAMIX;
}
// helpers
F32 DBToLinear(F32 value);
F32 linearToDB(F32 value);
} // end namespace Audio
// Used by the Linux client audio
extern void alxFakeCallbackUpdate( void );
#endif

3997
platformLinux/platformGL.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _PLATFORMLINUX_H_
#define _PLATFORMLINUX_H_
#include <stdio.h>
#include <string.h>
#include <SDL/SDL.h>
#ifndef _PLATFORM_H_
#include "Platform/platform.h"
#endif
#ifndef _EVENT_H_
#include "Platform/event.h"
#endif
class LinuxPlatformState
{
public:
S32 width;
S32 height;
S32 bpp;
bool videoInitted;
LinuxPlatformState( ) {
width = 0;
height = 0;
bpp = 0;
videoInitted = false;
}
};
extern LinuxPlatformState linuxState;
extern bool QGL_Init( const char* glName, const char* gluName );
extern bool QGL_EXT_Init( void );
extern void QGL_Shutdown( void );
extern void GetDesktopState( void );
extern char* dStrncat( char* d, const char* s, size_t n );
extern void linuxInitTicks( void );
#ifdef DEDICATED
extern void linuxPostQuitMessage( void );
#endif
extern void createFontInit( void );
extern void createFontShutdown( void );
extern void installRedBookDevices( void );
extern void PlatformBlitInit( void );
extern U8 getHatState( U8 hat );
extern void setHatState( U8 hat, U8 state );
extern SDLKey translateKeyCodeToSDL( KeyCodes code );
extern KeyCodes translateSDLToKeyCode( SDLKey sym );
#endif