mirror of
https://github.com/tribes2/engine.git
synced 2026-03-06 22:10:28 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
350
platformLinux/async.c
Normal file
350
platformLinux/async.c
Normal 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
34
platformLinux/async.h
Normal 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
3574
platformLinux/audio.cc
Normal file
File diff suppressed because it is too large
Load diff
1126
platformLinux/blender.asm
Normal file
1126
platformLinux/blender.asm
Normal file
File diff suppressed because it is too large
Load diff
8
platformLinux/fixcalls.pl
Normal file
8
platformLinux/fixcalls.pl
Normal 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
335
platformLinux/linuxAL.cc
Normal 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...
|
||||
}
|
||||
|
||||
246
platformLinux/linuxALStub.cc
Normal file
246
platformLinux/linuxALStub.cc
Normal 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
|
||||
}
|
||||
327
platformLinux/linuxAsmBlit.cc
Normal file
327
platformLinux/linuxAsmBlit.cc
Normal 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;
|
||||
}
|
||||
227
platformLinux/linuxCPUInfo.cc
Normal file
227
platformLinux/linuxCPUInfo.cc
Normal 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( );
|
||||
}
|
||||
64
platformLinux/linuxCPUInfo_ASM.asm
Normal file
64
platformLinux/linuxCPUInfo_ASM.asm
Normal 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
|
||||
249
platformLinux/linuxCodeMap.cc
Normal file
249
platformLinux/linuxCodeMap.cc
Normal 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;
|
||||
}
|
||||
573
platformLinux/linuxConsole.cc
Normal file
573
platformLinux/linuxConsole.cc
Normal 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();
|
||||
}
|
||||
}
|
||||
80
platformLinux/linuxConsole.h
Normal file
80
platformLinux/linuxConsole.h
Normal 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
|
||||
853
platformLinux/linuxFileio.cc
Normal file
853
platformLinux/linuxFileio.cc
Normal 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
209
platformLinux/linuxFont.cc
Normal 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
2409
platformLinux/linuxGL.cc
Normal file
File diff suppressed because it is too large
Load diff
24
platformLinux/linuxIO.cc
Normal file
24
platformLinux/linuxIO.cc
Normal 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
537
platformLinux/linuxInput.cc
Normal 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
459
platformLinux/linuxMath.cc
Normal 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" );
|
||||
}
|
||||
|
||||
}
|
||||
1014
platformLinux/linuxMath_ASM.asm
Normal file
1014
platformLinux/linuxMath_ASM.asm
Normal file
File diff suppressed because it is too large
Load diff
1145
platformLinux/linuxMath_VC.c
Normal file
1145
platformLinux/linuxMath_VC.c
Normal file
File diff suppressed because it is too large
Load diff
41
platformLinux/linuxMemory.cc
Normal file
41
platformLinux/linuxMemory.cc
Normal 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 );
|
||||
}
|
||||
58
platformLinux/linuxMutex.cc
Normal file
58
platformLinux/linuxMutex.cc
Normal 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
738
platformLinux/linuxNet.cc
Normal 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 ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
612
platformLinux/linuxOGLVideo.cc
Normal file
612
platformLinux/linuxOGLVideo.cc
Normal 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
|
||||
40
platformLinux/linuxOGLVideo.h
Normal file
40
platformLinux/linuxOGLVideo.h
Normal 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
|
||||
241
platformLinux/linuxOpenAL.cc
Normal file
241
platformLinux/linuxOpenAL.cc
Normal 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
|
||||
41
platformLinux/linuxProcessControl.cc
Normal file
41
platformLinux/linuxProcessControl.cc
Normal 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
|
||||
}
|
||||
205
platformLinux/linuxRedBook.cc
Normal file
205
platformLinux/linuxRedBook.cc
Normal 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
|
||||
73
platformLinux/linuxSemaphore.cc
Normal file
73
platformLinux/linuxSemaphore.cc
Normal 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 );
|
||||
}
|
||||
|
||||
}
|
||||
229
platformLinux/linuxStrings.cc
Normal file
229
platformLinux/linuxStrings.cc
Normal 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 );
|
||||
}
|
||||
118
platformLinux/linuxThread.cc
Normal file
118
platformLinux/linuxThread.cc
Normal 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
139
platformLinux/linuxTime.cc
Normal 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 < )
|
||||
{
|
||||
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
1026
platformLinux/linuxWindow.cc
Normal file
File diff suppressed because it is too large
Load diff
866
platformLinux/lokiOpenAL.cc
Normal file
866
platformLinux/lokiOpenAL.cc
Normal 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
|
||||
11
platformLinux/lokiOpenAL.h
Normal file
11
platformLinux/lokiOpenAL.h
Normal 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);
|
||||
387
platformLinux/mSolver_ASM.asm
Normal file
387
platformLinux/mSolver_ASM.asm
Normal 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
136
platformLinux/platformAL.h
Normal 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
3997
platformLinux/platformGL.h
Normal file
File diff suppressed because it is too large
Load diff
67
platformLinux/platformLinux.h
Normal file
67
platformLinux/platformLinux.h
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue