Supplemented Linux backend with missing functions. -> [100%] Built target RBDoom3 on Kubuntu 12.10

This commit is contained in:
Robert Beckebans 2012-12-11 23:17:23 +01:00
parent f7279b850c
commit a1730fa430
28 changed files with 5378 additions and 741 deletions

View file

@ -1053,7 +1053,8 @@ else()
list(APPEND RBDOOM3_SOURCES list(APPEND RBDOOM3_SOURCES
${POSIX_INCLUDES} ${POSIX_SOURCES} ${POSIX_INCLUDES} ${POSIX_SOURCES}
${SDL_INCLUDES} ${SDL_SOURCES}) ${SDL_INCLUDES} ${SDL_SOURCES}
sys/linux/linux_main.cpp)
endif() endif()
list(REMOVE_DUPLICATES RBDOOM3_SOURCES) list(REMOVE_DUPLICATES RBDOOM3_SOURCES)

View file

@ -320,8 +320,6 @@ public:
virtual int GetGameFrame() = 0; virtual int GetGameFrame() = 0;
virtual void LaunchExternalTitle( int titleIndex, int device, const lobbyConnectInfo_t* const connectInfo ) = 0;
virtual void InitializeMPMapsModes() = 0; virtual void InitializeMPMapsModes() = 0;
virtual const idStrList& GetModeList() const = 0; virtual const idStrList& GetModeList() const = 0;
virtual const idStrList& GetModeDisplayList() const = 0; virtual const idStrList& GetModeDisplayList() const = 0;

View file

@ -48,60 +48,7 @@ extern idCVar g_demoMode;
// This is for the dirty hack to get a dialog to show up before we capture the screen for autorender. // This is for the dirty hack to get a dialog to show up before we capture the screen for autorender.
const int NumScreenUpdatesToShowDialog = 25; const int NumScreenUpdatesToShowDialog = 25;
/*
================
idCommonLocal::LaunchExternalTitle
Launches an external title ( Doom 1, or 2 ) based on title index.
for PS3, a device number is sent in, for the game to register as a local
user by default, when title initializes.
================
*/
void idCommonLocal::LaunchExternalTitle( int titleIndex, int device, const lobbyConnectInfo_t* const connectInfo )
{
idStr deviceString( device );
// We want to pass in the current executable, so that the launching title knows which title to return to.
// as of right now, this feature is TBD.
const char* currentExecutablePath = "ImNotSureYet";
idStr launchingExecutablePath;
idCmdArgs cmdArgs;
cmdArgs.AppendArg( currentExecutablePath );
if( titleIndex == LAUNCH_TITLE_DOOM )
{
launchingExecutablePath.Format( "%s%s", Sys_DefaultBasePath(), LAUNCH_TITLE_DOOM_EXECUTABLE );
cmdArgs.AppendArg( "d1bfg" );
}
else if( titleIndex == LAUNCH_TITLE_DOOM2 )
{
launchingExecutablePath.Format( "%s%s", Sys_DefaultBasePath(), LAUNCH_TITLE_DOOM2_EXECUTABLE );
cmdArgs.AppendArg( "d2bfg" );
}
else
{
idLib::Warning( "Unhandled Launch Title %d \n", titleIndex );
}
cmdArgs.AppendArg( deviceString.c_str() );
// Add an argument so that the new process knows whether or not to read exitspawn data.
if( connectInfo != NULL )
{
cmdArgs.AppendArg( "exitspawnInvite" );
}
// Add arguments so that the new process will know which command line to invoke to relaunch this process
// if necessary.
const int launchDataSize = ( connectInfo == NULL ) ? 0 : sizeof( *connectInfo );
Sys_Launch( launchingExecutablePath.c_str() , cmdArgs, const_cast< lobbyConnectInfo_t* const >( connectInfo ), launchDataSize );
}
/* /*
================ ================

View file

@ -244,10 +244,6 @@ public:
return gameFrame; return gameFrame;
} }
virtual void LaunchExternalTitle( int titleIndex,
int device,
const lobbyConnectInfo_t* const connectInfo ); // For handling invitations. NULL if no invitation used.
virtual void InitializeMPMapsModes(); virtual void InitializeMPMapsModes();
virtual const idStrList& GetModeList() const virtual const idStrList& GetModeList() const
{ {

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -37,7 +38,7 @@ If you have questions concerning this license or the applicable additional terms
#define GAME_NAME "DOOM 3: BFG Edition" // appears on window titles and errors #define GAME_NAME "DOOM 3: BFG Edition" // appears on window titles and errors
#define SAVE_PATH "\\id Software\\DOOM 3 BFG" #define SAVE_PATH "\\id Software\\DOOM 3 BFG"
#define ENGINE_VERSION "D3BFG 1" // printed in console #define ENGINE_VERSION "RBD3BFG 1" // printed in console
#define BASE_GAMEDIR "base" #define BASE_GAMEDIR "base"
@ -56,3 +57,14 @@ If you have questions concerning this license or the applicable additional terms
#define WIN32_CONSOLE_CLASS "D3BFG_WinConsole" #define WIN32_CONSOLE_CLASS "D3BFG_WinConsole"
#define WIN32_WINDOW_CLASS_NAME "D3BFG" #define WIN32_WINDOW_CLASS_NAME "D3BFG"
#define WIN32_FAKE_WINDOW_CLASS_NAME "D3BFG_WGL_FAKE" #define WIN32_FAKE_WINDOW_CLASS_NAME "D3BFG_WGL_FAKE"
// RB begin
// Linux info
#ifdef ID_DEMO_BUILD
#define LINUX_DEFAULT_PATH "/usr/local/games/rbdoom3-bfg-demo"
#else
#define LINUX_DEFAULT_PATH "/usr/local/games/rbdoom3-bfg"
#endif
// RB end

View file

@ -61,11 +61,13 @@ uintptr_t Sys_CreateThread( xthread_t function, void* parms, xthreadPriority pri
pthread_attr_destroy( &attr ); pthread_attr_destroy( &attr );
// RB: TODO pthread_setname_np is different on Linux, MacOSX and other systems // RB: TODO pthread_setname_np is different on Linux, MacOSX and other systems
#if 0
if( pthread_setname_np( handle, name ) != 0 ) if( pthread_setname_np( handle, name ) != 0 )
{ {
idLib::common->FatalError( "ERROR: pthread_setname_np %s failed\n", name ); idLib::common->FatalError( "ERROR: pthread_setname_np %s failed\n", name );
return ( uintptr_t )0; return ( uintptr_t )0;
} }
#endif
/* /*
TODO RB: support thread priorities? TODO RB: support thread priorities?

View file

@ -1,322 +0,0 @@
/* minigzip.c -- simulate gzip using the zlib compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/*
* minigzip is a minimal implementation of the gzip utility. This is
* only an example of using zlib and isn't meant to replace the
* full-featured gzip. No attempt is made to deal with file systems
* limiting names to 14 or 8+3 characters, etc... Error checking is
* very limited. So use minigzip only for testing; use gzip for the
* real thing. On MSDOS, use only on file names without extension
* or in pipe mode.
*/
/* @(#) $Id$ */
#include <stdio.h>
#include "zlib.h"
#ifdef STDC
# include <string.h>
# include <stdlib.h>
#endif
#ifdef USE_MMAP
# include <sys/types.h>
# include <sys/mman.h>
# include <sys/stat.h>
#endif
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
# include <fcntl.h>
# include <io.h>
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
# define SET_BINARY_MODE(file)
#endif
#ifdef VMS
# define unlink delete
# define GZ_SUFFIX "-gz"
#endif
#ifdef RISCOS
# define unlink remove
# define GZ_SUFFIX "-gz"
# define fileno(file) file->__file
#endif
#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fileno */
#endif
#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
extern int unlink OF((const char *));
#endif
#ifndef GZ_SUFFIX
# define GZ_SUFFIX ".gz"
#endif
#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
#define BUFLEN 16384
#define MAX_NAME_LEN 1024
#ifdef MAXSEG_64K
# define local static
/* Needed for systems with limitation on stack size. */
#else
# define local
#endif
char *prog;
void error OF((const char *msg));
void gz_compress OF((FILE *in, gzFile out));
#ifdef USE_MMAP
int gz_compress_mmap OF((FILE *in, gzFile out));
#endif
void gz_uncompress OF((gzFile in, FILE *out));
void file_compress OF((char *file, char *mode));
void file_uncompress OF((char *file));
int main OF((int argc, char *argv[]));
/* ===========================================================================
* Display error message and exit
*/
void error(msg)
const char *msg;
{
fprintf(stderr, "%s: %s\n", prog, msg);
exit(1);
}
/* ===========================================================================
* Compress input to output then close both files.
*/
void gz_compress(in, out)
FILE *in;
gzFile out;
{
local char buf[BUFLEN];
int len;
int err;
#ifdef USE_MMAP
/* Try first compressing with mmap. If mmap fails (minigzip used in a
* pipe), use the normal fread loop.
*/
if (gz_compress_mmap(in, out) == Z_OK) return;
#endif
for (;;) {
len = (int)fread(buf, 1, sizeof(buf), in);
if (ferror(in)) {
perror("fread");
exit(1);
}
if (len == 0) break;
if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
}
fclose(in);
if (gzclose(out) != Z_OK) error("failed gzclose");
}
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
/* Try compressing the input file at once using mmap. Return Z_OK if
* if success, Z_ERRNO otherwise.
*/
int gz_compress_mmap(in, out)
FILE *in;
gzFile out;
{
int len;
int err;
int ifd = fileno(in);
caddr_t buf; /* mmap'ed buffer for the entire input file */
off_t buf_len; /* length of the input file */
struct stat sb;
/* Determine the size of the file, needed for mmap: */
if (fstat(ifd, &sb) < 0) return Z_ERRNO;
buf_len = sb.st_size;
if (buf_len <= 0) return Z_ERRNO;
/* Now do the actual mmap: */
buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
if (buf == (caddr_t)(-1)) return Z_ERRNO;
/* Compress the whole file at once: */
len = gzwrite(out, (char *)buf, (unsigned)buf_len);
if (len != (int)buf_len) error(gzerror(out, &err));
munmap(buf, buf_len);
fclose(in);
if (gzclose(out) != Z_OK) error("failed gzclose");
return Z_OK;
}
#endif /* USE_MMAP */
/* ===========================================================================
* Uncompress input to output then close both files.
*/
void gz_uncompress(in, out)
gzFile in;
FILE *out;
{
local char buf[BUFLEN];
int len;
int err;
for (;;) {
len = gzread(in, buf, sizeof(buf));
if (len < 0) error (gzerror(in, &err));
if (len == 0) break;
if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
error("failed fwrite");
}
}
if (fclose(out)) error("failed fclose");
if (gzclose(in) != Z_OK) error("failed gzclose");
}
/* ===========================================================================
* Compress the given file: create a corresponding .gz file and remove the
* original.
*/
void file_compress(file, mode)
char *file;
char *mode;
{
local char outfile[MAX_NAME_LEN];
FILE *in;
gzFile out;
strcpy(outfile, file);
strcat(outfile, GZ_SUFFIX);
in = fopen(file, "rb");
if (in == NULL) {
perror(file);
exit(1);
}
out = gzopen(outfile, mode);
if (out == NULL) {
fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
exit(1);
}
gz_compress(in, out);
unlink(file);
}
/* ===========================================================================
* Uncompress the given file and remove the original.
*/
void file_uncompress(file)
char *file;
{
local char buf[MAX_NAME_LEN];
char *infile, *outfile;
FILE *out;
gzFile in;
uInt len = (uInt)strlen(file);
strcpy(buf, file);
if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
infile = file;
outfile = buf;
outfile[len-3] = '\0';
} else {
outfile = file;
infile = buf;
strcat(infile, GZ_SUFFIX);
}
in = gzopen(infile, "rb");
if (in == NULL) {
fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
exit(1);
}
out = fopen(outfile, "wb");
if (out == NULL) {
perror(file);
exit(1);
}
gz_uncompress(in, out);
unlink(infile);
}
/* ===========================================================================
* Usage: minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...]
* -d : decompress
* -f : compress with Z_FILTERED
* -h : compress with Z_HUFFMAN_ONLY
* -r : compress with Z_RLE
* -1 to -9 : compression level
*/
int main(argc, argv)
int argc;
char *argv[];
{
int uncompr = 0;
gzFile file;
char outmode[20];
strcpy(outmode, "wb6 ");
prog = argv[0];
argc--, argv++;
while (argc > 0) {
if (strcmp(*argv, "-d") == 0)
uncompr = 1;
else if (strcmp(*argv, "-f") == 0)
outmode[3] = 'f';
else if (strcmp(*argv, "-h") == 0)
outmode[3] = 'h';
else if (strcmp(*argv, "-r") == 0)
outmode[3] = 'R';
else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
(*argv)[2] == 0)
outmode[2] = (*argv)[1];
else
break;
argc--, argv++;
}
if (outmode[3] == ' ')
outmode[3] = 0;
if (argc == 0) {
SET_BINARY_MODE(stdin);
SET_BINARY_MODE(stdout);
if (uncompr) {
file = gzdopen(fileno(stdin), "rb");
if (file == NULL) error("can't gzdopen stdin");
gz_uncompress(file, stdout);
} else {
file = gzdopen(fileno(stdout), outmode);
if (file == NULL) error("can't gzdopen stdout");
gz_compress(stdin, file);
}
} else {
do {
if (uncompr) {
file_uncompress(*argv);
} else {
file_compress(*argv, outmode);
}
} while (argv++, --argc);
}
return 0;
}

View file

@ -97,7 +97,9 @@ idCVar r_skipDynamicTextures( "r_skipDynamicTextures", "0", CVAR_RENDERER | CVAR
idCVar r_skipCopyTexture( "r_skipCopyTexture", "0", CVAR_RENDERER | CVAR_BOOL, "do all rendering, but don't actually copyTexSubImage2D" ); idCVar r_skipCopyTexture( "r_skipCopyTexture", "0", CVAR_RENDERER | CVAR_BOOL, "do all rendering, but don't actually copyTexSubImage2D" );
idCVar r_skipBackEnd( "r_skipBackEnd", "0", CVAR_RENDERER | CVAR_BOOL, "don't draw anything" ); idCVar r_skipBackEnd( "r_skipBackEnd", "0", CVAR_RENDERER | CVAR_BOOL, "don't draw anything" );
idCVar r_skipRender( "r_skipRender", "0", CVAR_RENDERER | CVAR_BOOL, "skip 3D rendering, but pass 2D" ); idCVar r_skipRender( "r_skipRender", "0", CVAR_RENDERER | CVAR_BOOL, "skip 3D rendering, but pass 2D" );
idCVar r_skipRenderContext( "r_skipRenderContext", "0", CVAR_RENDERER | CVAR_BOOL, "NULL the rendering context during backend 3D rendering" ); // RB begin
idCVar r_skipRenderContext( "r_skipRenderContext", "0", CVAR_RENDERER | CVAR_BOOL, "DISABLED: NULL the rendering context during backend 3D rendering" );
// RB end
idCVar r_skipTranslucent( "r_skipTranslucent", "0", CVAR_RENDERER | CVAR_BOOL, "skip the translucent interaction rendering" ); idCVar r_skipTranslucent( "r_skipTranslucent", "0", CVAR_RENDERER | CVAR_BOOL, "skip the translucent interaction rendering" );
idCVar r_skipAmbient( "r_skipAmbient", "0", CVAR_RENDERER | CVAR_BOOL, "bypasses all non-interaction drawing" ); idCVar r_skipAmbient( "r_skipAmbient", "0", CVAR_RENDERER | CVAR_BOOL, "bypasses all non-interaction drawing" );
idCVar r_skipNewAmbient( "r_skipNewAmbient", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "bypasses all vertex/fragment program ambient drawing" ); idCVar r_skipNewAmbient( "r_skipNewAmbient", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "bypasses all vertex/fragment program ambient drawing" );

View file

@ -3150,10 +3150,13 @@ void RB_DrawView( const void* data, const int stereoEye )
// skip render context sets the wgl context to NULL, // skip render context sets the wgl context to NULL,
// which should factor out the API cost, under the assumption // which should factor out the API cost, under the assumption
// that all gl calls just return if the context isn't valid // that all gl calls just return if the context isn't valid
if( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys )
{ // RB: not really needed
GLimp_DeactivateContext(); //if( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys )
} //{
// GLimp_DeactivateContext();
//}
// RB end
backEnd.pc.c_surfaces += backEnd.viewDef->numDrawSurfs; backEnd.pc.c_surfaces += backEnd.viewDef->numDrawSurfs;
@ -3165,11 +3168,13 @@ void RB_DrawView( const void* data, const int stereoEye )
RB_MotionBlur(); RB_MotionBlur();
// restore the context for 2D drawing if we were stubbing it out // restore the context for 2D drawing if we were stubbing it out
if( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys ) // RB: not really needed
{ //if( r_skipRenderContext.GetBool() && backEnd.viewDef->viewEntitys )
GLimp_ActivateContext(); //{
GL_SetDefaultState(); // GLimp_ActivateContext();
} // GL_SetDefaultState();
//}
// RB end
// optionally draw a box colored based on the eye number // optionally draw a box colored based on the eye number
if( r_drawEyeColor.GetBool() ) if( r_drawEyeColor.GetBool() )

View file

@ -0,0 +1,688 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#include "../posix/posix_public.h"
#include "../sys_local.h"
//#include "local.h"
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef ID_MCHECK
#include <mcheck.h>
#endif
static idStr basepath;
static idStr savepath;
/*
==============
Sys_DefaultSavePath
==============
*/
const char* Sys_DefaultSavePath()
{
#if defined( ID_DEMO_BUILD )
sprintf( savepath, "%s/.rbdoom3-demo", getenv( "HOME" ) );
#else
sprintf( savepath, "%s/.rbdoom3", getenv( "HOME" ) );
#endif
return savepath.c_str();
}
/*
==============
Sys_EXEPath
==============
*/
const char* Sys_EXEPath()
{
static char buf[ 1024 ];
idStr linkpath;
int len;
buf[ 0 ] = '\0';
sprintf( linkpath, "/proc/%d/exe", getpid() );
len = readlink( linkpath.c_str(), buf, sizeof( buf ) );
if( len == -1 )
{
Sys_Printf( "couldn't stat exe path link %s\n", linkpath.c_str() );
// RB: fixed array subscript is below array bounds
buf[ 0 ] = '\0';
// RB end
}
return buf;
}
/*
================
Sys_DefaultBasePath
Get the default base path
- binary image path
- current directory
- hardcoded
Try to be intelligent: if there is no BASE_GAMEDIR, try the next path
================
*/
const char* Sys_DefaultBasePath()
{
struct stat st;
idStr testbase;
basepath = Sys_EXEPath();
if( basepath.Length() )
{
basepath.StripFilename();
testbase = basepath;
testbase += "/";
testbase += BASE_GAMEDIR;
if( stat( testbase.c_str(), &st ) != -1 && S_ISDIR( st.st_mode ) )
{
return basepath.c_str();
}
else
{
common->Printf( "no '%s' directory in exe path %s, skipping\n", BASE_GAMEDIR, basepath.c_str() );
}
}
if( basepath != Posix_Cwd() )
{
basepath = Posix_Cwd();
testbase = basepath;
testbase += "/";
testbase += BASE_GAMEDIR;
if( stat( testbase.c_str(), &st ) != -1 && S_ISDIR( st.st_mode ) )
{
return basepath.c_str();
}
else
{
common->Printf( "no '%s' directory in cwd path %s, skipping\n", BASE_GAMEDIR, basepath.c_str() );
}
}
common->Printf( "WARNING: using hardcoded default base path\n" );
return LINUX_DEFAULT_PATH;
}
/*
===============
Sys_Shutdown
===============
*/
void Sys_Shutdown()
{
basepath.Clear();
savepath.Clear();
Posix_Shutdown();
}
/*
===============
Sys_GetProcessorId
===============
*/
cpuid_t Sys_GetProcessorId()
{
return CPUID_GENERIC;
}
/*
===============
Sys_GetProcessorString
===============
*/
const char* Sys_GetProcessorString()
{
return "generic";
}
/*
===============
Sys_FPU_EnableExceptions
===============
*/
//void Sys_FPU_EnableExceptions( int exceptions )
//{
//}
/*
===============
Sys_FPE_handler
===============
*/
void Sys_FPE_handler( int signum, siginfo_t* info, void* context )
{
assert( signum == SIGFPE );
Sys_Printf( "FPE\n" );
}
/*
===============
Sys_GetClockticks
===============
*/
double Sys_GetClockTicks()
{
#if defined( __i386__ )
unsigned long lo, hi;
__asm__ __volatile__(
"push %%ebx\n" \
"xor %%eax,%%eax\n" \
"cpuid\n" \
"rdtsc\n" \
"mov %%eax,%0\n" \
"mov %%edx,%1\n" \
"pop %%ebx\n"
: "=r"( lo ), "=r"( hi ) );
return ( double ) lo + ( double ) 0xFFFFFFFF * hi;
#else
//#error unsupported CPU
// RB begin
struct timespec now;
clock_gettime( CLOCK_MONOTONIC, &now );
return now.tv_sec * 1000000000LL + now.tv_nsec;
// RB end
#endif
}
/*
===============
MeasureClockTicks
===============
*/
double MeasureClockTicks()
{
double t0, t1;
t0 = Sys_GetClockTicks( );
Sys_Sleep( 1000 );
t1 = Sys_GetClockTicks( );
return t1 - t0;
}
/*
===============
Sys_ClockTicksPerSecond
===============
*/
double Sys_ClockTicksPerSecond()
{
static bool init = false;
static double ret;
int fd, len, pos, end;
char buf[ 4096 ];
if( init )
{
return ret;
}
fd = open( "/proc/cpuinfo", O_RDONLY );
if( fd == -1 )
{
common->Printf( "couldn't read /proc/cpuinfo\n" );
ret = MeasureClockTicks();
init = true;
common->Printf( "measured CPU frequency: %g MHz\n", ret / 1000000.0 );
return ret;
}
len = read( fd, buf, 4096 );
close( fd );
pos = 0;
while( pos < len )
{
if( !idStr::Cmpn( buf + pos, "cpu MHz", 7 ) )
{
pos = strchr( buf + pos, ':' ) - buf + 2;
end = strchr( buf + pos, '\n' ) - buf;
if( pos < len && end < len )
{
buf[end] = '\0';
ret = atof( buf + pos );
}
else
{
common->Printf( "failed parsing /proc/cpuinfo\n" );
ret = MeasureClockTicks();
init = true;
common->Printf( "measured CPU frequency: %g MHz\n", ret / 1000000.0 );
return ret;
}
common->Printf( "/proc/cpuinfo CPU frequency: %g MHz\n", ret );
ret *= 1000000;
init = true;
return ret;
}
pos = strchr( buf + pos, '\n' ) - buf + 1;
}
common->Printf( "failed parsing /proc/cpuinfo\n" );
ret = MeasureClockTicks();
init = true;
common->Printf( "measured CPU frequency: %g MHz\n", ret / 1000000.0 );
return ret;
}
/*
========================
Sys_CPUCount
numLogicalCPUCores - the number of logical CPU per core
numPhysicalCPUCores - the total number of cores per package
numCPUPackages - the total number of packages (physical processors)
========================
*/
// RB begin
void Sys_CPUCount( int& numLogicalCPUCores, int& numPhysicalCPUCores, int& numCPUPackages )
{
static bool init = false;
static double ret;
static int s_numLogicalCPUCores;
static int s_numPhysicalCPUCores;
static int s_numCPUPackages;
int fd, len, pos, end;
char buf[ 4096 ];
if( init )
{
numPhysicalCPUCores = s_numPhysicalCPUCores;
numLogicalCPUCores = s_numLogicalCPUCores;
numCPUPackages = s_numCPUPackages;
}
s_numPhysicalCPUCores = 1;
s_numLogicalCPUCores = 1;
s_numCPUPackages = 1;
fd = open( "/proc/cpuinfo", O_RDONLY );
if( fd != -1 )
{
len = read( fd, buf, 4096 );
close( fd );
pos = 0;
while( pos < len )
{
if( !idStr::Cmpn( buf + pos, "processor", 9 ) )
{
pos = strchr( buf + pos, ':' ) - buf + 2;
end = strchr( buf + pos, '\n' ) - buf;
if( pos < len && end < len )
{
buf[end] = '\0';
int processor = atoi( buf + pos );
if( ( processor + 1 ) > s_numPhysicalCPUCores )
{
s_numPhysicalCPUCores = processor + 1;
}
}
else
{
common->Printf( "failed parsing /proc/cpuinfo\n" );
break;
}
}
if( !idStr::Cmpn( buf + pos, "core id", 7 ) )
{
pos = strchr( buf + pos, ':' ) - buf + 2;
end = strchr( buf + pos, '\n' ) - buf;
if( pos < len && end < len )
{
buf[end] = '\0';
int coreId = atoi( buf + pos );
if( ( coreId + 1 ) > s_numLogicalCPUCores )
{
s_numLogicalCPUCores = coreId + 1;
}
}
else
{
common->Printf( "failed parsing /proc/cpuinfo\n" );
break;
}
}
pos = strchr( buf + pos, '\n' ) - buf + 1;
}
}
common->Printf( "/proc/cpuinfo CPU processors: %d\n", s_numPhysicalCPUCores );
common->Printf( "/proc/cpuinfo CPU logical cores: %d\n", s_numLogicalCPUCores );
numPhysicalCPUCores = s_numPhysicalCPUCores;
numLogicalCPUCores = s_numLogicalCPUCores;
numCPUPackages = s_numCPUPackages;
}
// RB end
/*
================
Sys_GetSystemRam
returns in megabytes
================
*/
int Sys_GetSystemRam()
{
long count, page_size;
int mb;
count = sysconf( _SC_PHYS_PAGES );
if( count == -1 )
{
common->Printf( "GetSystemRam: sysconf _SC_PHYS_PAGES failed\n" );
return 512;
}
page_size = sysconf( _SC_PAGE_SIZE );
if( page_size == -1 )
{
common->Printf( "GetSystemRam: sysconf _SC_PAGE_SIZE failed\n" );
return 512;
}
mb = ( int )( ( double )count * ( double )page_size / ( 1024 * 1024 ) );
// round to the nearest 16Mb
mb = ( mb + 8 ) & ~15;
return mb;
}
/*
==================
Sys_DoStartProcess
if we don't fork, this function never returns
the no-fork lets you keep the terminal when you're about to spawn an installer
if the command contains spaces, system() is used. Otherwise the more straightforward execl ( system() blows though )
==================
*/
void Sys_DoStartProcess( const char* exeName, bool dofork )
{
bool use_system = false;
if( strchr( exeName, ' ' ) )
{
use_system = true;
}
else
{
// set exec rights when it's about a single file to execute
struct stat buf;
if( stat( exeName, &buf ) == -1 )
{
printf( "stat %s failed: %s\n", exeName, strerror( errno ) );
}
else
{
if( chmod( exeName, buf.st_mode | S_IXUSR ) == -1 )
{
printf( "cmod +x %s failed: %s\n", exeName, strerror( errno ) );
}
}
}
if( dofork )
{
switch( fork() )
{
case -1:
// main thread
break;
case 0:
if( use_system )
{
printf( "system %s\n", exeName );
system( exeName );
_exit( 0 );
}
else
{
printf( "execl %s\n", exeName );
execl( exeName, exeName, NULL );
printf( "execl failed: %s\n", strerror( errno ) );
_exit( -1 );
}
break;
}
}
else
{
if( use_system )
{
printf( "system %s\n", exeName );
system( exeName );
sleep( 1 ); // on some systems I've seen that starting the new process and exiting this one should not be too close
}
else
{
printf( "execl %s\n", exeName );
execl( exeName, exeName, NULL );
printf( "execl failed: %s\n", strerror( errno ) );
}
// terminate
_exit( 0 );
}
}
/*
=================
Sys_OpenURL
=================
*/
void idSysLocal::OpenURL( const char* url, bool quit )
{
const char* script_path;
idFile* script_file;
char cmdline[ 1024 ];
static bool quit_spamguard = false;
if( quit_spamguard )
{
common->DPrintf( "Sys_OpenURL: already in a doexit sequence, ignoring %s\n", url );
return;
}
common->Printf( "Open URL: %s\n", url );
// opening an URL on *nix can mean a lot of things ..
// just spawn a script instead of deciding for the user :-)
// look in the savepath first, then in the basepath
script_path = fileSystem->BuildOSPath( cvarSystem->GetCVarString( "fs_savepath" ), "", "openurl.sh" );
script_file = fileSystem->OpenExplicitFileRead( script_path );
if( !script_file )
{
script_path = fileSystem->BuildOSPath( cvarSystem->GetCVarString( "fs_basepath" ), "", "openurl.sh" );
script_file = fileSystem->OpenExplicitFileRead( script_path );
}
if( !script_file )
{
common->Printf( "Can't find URL script 'openurl.sh' in either savepath or basepath\n" );
common->Printf( "OpenURL '%s' failed\n", url );
return;
}
fileSystem->CloseFile( script_file );
// if we are going to quit, only accept a single URL before quitting and spawning the script
if( quit )
{
quit_spamguard = true;
}
common->Printf( "URL script: %s\n", script_path );
// StartProcess is going to execute a system() call with that - hence the &
idStr::snPrintf( cmdline, 1024, "%s '%s' &", script_path, url );
sys->StartProcess( cmdline, quit );
}
/*
==================
Sys_DoPreferences
==================
*/
void Sys_DoPreferences() { }
#if 0
/*
================
Sys_FPU_SetDAZ
================
*/
void Sys_FPU_SetDAZ( bool enable )
{
/*
DWORD dwData;
_asm {
movzx ecx, byte ptr enable
and ecx, 1
shl ecx, 6
STMXCSR dword ptr dwData
mov eax, dwData
and eax, ~(1<<6) // clear DAX bit
or eax, ecx // set the DAZ bit
mov dwData, eax
LDMXCSR dword ptr dwData
}
*/
}
/*
================
Sys_FPU_SetFTZ
================
*/
void Sys_FPU_SetFTZ( bool enable )
{
/*
DWORD dwData;
_asm {
movzx ecx, byte ptr enable
and ecx, 1
shl ecx, 15
STMXCSR dword ptr dwData
mov eax, dwData
and eax, ~(1<<15) // clear FTZ bit
or eax, ecx // set the FTZ bit
mov dwData, eax
LDMXCSR dword ptr dwData
}
*/
}
#endif
/*
===============
mem consistency stuff
===============
*/
#ifdef ID_MCHECK
const char* mcheckstrings[] =
{
"MCHECK_DISABLED",
"MCHECK_OK",
"MCHECK_FREE", // block freed twice
"MCHECK_HEAD", // memory before the block was clobbered
"MCHECK_TAIL" // memory after the block was clobbered
};
void abrt_func( mcheck_status status )
{
Sys_Printf( "memory consistency failure: %s\n", mcheckstrings[ status + 1 ] );
Posix_SetExit( EXIT_FAILURE );
common->Quit();
}
#endif
/*
========================
Sys_GetCmdLine
========================
*/
const char* Sys_GetCmdLine()
{
return "TODO Sys_GetCmdLine";
}
/*
========================
Sys_ReLaunch
========================
*/
void Sys_ReLaunch( void* data, const unsigned int dataSize )
{
idLib::Error( "Could not start process: TODO Sys_ReLaunch() " );
}
/*
===============
main
===============
*/
int main( int argc, const char** argv )
{
#ifdef ID_MCHECK
// must have -lmcheck linkage
mcheck( abrt_func );
Sys_Printf( "memory consistency checking enabled\n" );
#endif
Posix_EarlyInit( );
if( argc > 1 )
{
common->Init( argc - 1, &argv[1], NULL );
}
else
{
common->Init( 0, NULL, NULL );
}
Posix_LateInit( );
while( 1 )
{
common->Frame();
}
}

View file

@ -0,0 +1,111 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../../idlib/precompiled.h"
#include "posix_achievements.h"
#include "../sys_session_local.h"
extern idCVar achievements_Verbose;
#define STEAM_ACHIEVEMENT_PREFIX "ach_"
/*
========================
idAchievementSystemWin::idAchievementSystemWin
========================
*/
idAchievementSystemWin::idAchievementSystemWin()
{
}
/*
========================
idAchievementSystemWin::IsInitialized
========================
*/
bool idAchievementSystemWin::IsInitialized()
{
return false;
}
/*
================================
idAchievementSystemWin::AchievementUnlock
================================
*/
void idAchievementSystemWin::AchievementUnlock( idLocalUser* user, int achievementID )
{
}
/*
========================
idAchievementSystemWin::AchievementLock
========================
*/
void idAchievementSystemWin::AchievementLock( idLocalUser* user, const int achievementID )
{
}
/*
========================
idAchievementSystemWin::AchievementLockAll
========================
*/
void idAchievementSystemWin::AchievementLockAll( idLocalUser* user, const int maxId )
{
}
/*
========================
idAchievementSystemWin::GetAchievementDescription
========================
*/
bool idAchievementSystemWin::GetAchievementDescription( idLocalUser* user, const int achievementID, achievementDescription_t& data ) const
{
return false;
}
/*
========================
idAchievementSystemWin::GetAchievementState
========================
*/
bool idAchievementSystemWin::GetAchievementState( idLocalUser* user, idArray< bool, idAchievementSystem::MAX_ACHIEVEMENTS >& achievements ) const
{
return false;
}
/*
================================
idAchievementSystemWin::Pump
================================
*/
void idAchievementSystemWin::Pump()
{
}

View file

@ -0,0 +1,50 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __POSIX_ACHIEVEMENTS_H__
#define __POSIX_ACHIEVEMENTS_H__
/*
================================================
idAchievementSystemWin
================================================
*/
class idAchievementSystemWin : public idAchievementSystem
{
public:
idAchievementSystemWin();
bool IsInitialized();
void AchievementUnlock( idLocalUser* user, const int achievementID );
void AchievementLock( idLocalUser* user, const int achievementID );
void AchievementLockAll( idLocalUser* user, const int maxId );
void Pump();
bool GetAchievementDescription( idLocalUser* user, const int id, achievementDescription_t& data ) const;
bool GetAchievementState( idLocalUser* user, idArray< bool, idAchievementSystem::MAX_ACHIEVEMENTS >& achievements ) const;
};
#endif // __POSIX_ACHIEVEMENTS_H__

View file

@ -0,0 +1,131 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../../idlib/precompiled.h"
#include "posix_localuser.h"
extern idCVar win_userPersistent;
extern idCVar win_userOnline;
extern idCVar win_isInParty;
extern idCVar win_partyCount;
/*
========================
idLocalUserWin::Init
========================
*/
void idLocalUserWin::Init( int inputDevice_, const char* gamertag_, int numLocalUsers )
{
if( numLocalUsers == 1 ) // Check for 1, since this is now incremented before we get in here
{
// This is the master user
gamertag = gamertag_;
}
else
{
// On steam, we need to generate a name based off the master user for split-screen users.
// We use the number of users on the system to generate the name rather than the device
// number so that it is always consistently "username (2)" for the second player.
gamertag.Format( "%s (%i)", gamertag_, numLocalUsers );
}
inputDevice = inputDevice_;
}
/*
========================
idLocalUserWin::IsProfileReady
========================
*/
bool idLocalUserWin::IsProfileReady() const
{
#ifdef _DEBUG
return win_userPersistent.GetBool();
#else
return true;
#endif
}
/*
========================
idLocalUserWin::IsOnline
========================
*/
bool idLocalUserWin::IsOnline() const
{
#ifdef _DEBUG
return win_userOnline.GetBool();
#else
return true;
#endif
}
/*
========================
idLocalUserWin::IsInParty
========================
*/
bool idLocalUserWin::IsInParty() const
{
#ifdef _DEBUG
return win_isInParty.GetBool();
#else
return false;
#endif
}
/*
========================
idLocalUserWin::GetPartyCount
========================
*/
int idLocalUserWin::GetPartyCount() const
{
// TODO: Implement
#ifdef _DEBUG
return win_partyCount.GetInteger();
#else
return 0;
#endif
}
/*
========================
idLocalUserWin::VerifyUserState
========================
*/
bool idLocalUserWin::VerifyUserState( winUserState_t& state )
{
if( state.inputDevice != inputDevice )
{
return false;
}
return true;
}

View file

@ -0,0 +1,96 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __POSIX_LOCALUSER_H__
#define __POSIX_LOCALUSER_H__
// This is to quickly get/set the data needed for disc-swapping
typedef struct
{
int inputDevice;
} winUserState_t;
/*
================================================
idLocalUserWin
================================================
*/
class idLocalUserWin : public idLocalUser
{
public:
static const int MAX_GAMERTAG = 64; // max number of bytes for a gamertag
static const int MAX_GAMERTAG_CHARS = 16; // max number of UTF-8 characters to show
idLocalUserWin() : inputDevice( 0 ) {}
//==========================================================================================
// idLocalUser interface
//==========================================================================================
virtual bool IsProfileReady() const;
virtual bool IsOnline() const;
virtual bool IsInParty() const;
virtual int GetPartyCount() const;
virtual uint32 GetOnlineCaps() const
{
return ( IsPersistent() && IsOnline() ) ? ( CAP_IS_ONLINE | CAP_CAN_PLAY_ONLINE ) : 0;
}
virtual int GetInputDevice() const
{
return inputDevice;
}
virtual const char* GetGamerTag() const
{
return gamertag.c_str();
}
virtual void PumpPlatform() {}
//==========================================================================================
// idLocalUserWin interface
//==========================================================================================
void SetInputDevice( int inputDevice_ )
{
inputDevice = inputDevice_;
}
void SetGamerTag( const char* gamerTag_ )
{
gamertag = gamerTag_;
}
winUserState_t GetUserState()
{
winUserState_t a = { inputDevice };
return a;
}
bool VerifyUserState( winUserState_t& state );
void Init( int inputDevice_, const char* gamertag_, int numLocalUsers );
private:
idStrStatic< MAX_GAMERTAG > gamertag;
int inputDevice;
};
#endif // __POSIX_LOCALUSER_H__

View file

@ -3,6 +3,7 @@
Doom 3 GPL Source Code Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?). This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
@ -46,6 +47,8 @@ If you have questions concerning this license or the applicable additional terms
#if defined(__ANDROID__) #if defined(__ANDROID__)
#include <android/log.h> #include <android/log.h>
#endif #endif
#include <sys/statvfs.h>
// RB end // RB end
#include "posix_public.h" #include "posix_public.h"
@ -95,10 +98,12 @@ void Posix_Exit( int ret )
} }
// at this point, too late to catch signals // at this point, too late to catch signals
Posix_ClearSigs(); Posix_ClearSigs();
if( asyncThread.threadHandle )
{ //if( asyncThread.threadHandle )
Sys_DestroyThread( asyncThread ); //{
} // Sys_DestroyThread( asyncThread );
//}
// process spawning. it's best when it happens after everything has shut down // process spawning. it's best when it happens after everything has shut down
if( exit_spawn[0] ) if( exit_spawn[0] )
{ {
@ -233,6 +238,26 @@ int Sys_Milliseconds()
#endif #endif
} }
// RB: added for BFG
/*
================
Sys_Microseconds
================
*/
uint64 Sys_Microseconds()
{
static uint64 ticksPerMicrosecondTimes1024 = 0;
if( ticksPerMicrosecondTimes1024 == 0 )
{
ticksPerMicrosecondTimes1024 = ( ( uint64 )Sys_ClockTicksPerSecond() << 10 ) / 1000000;
assert( ticksPerMicrosecondTimes1024 > 0 );
}
return ( ( uint64 )( ( int64 )Sys_GetClockTicks() << 10 ) ) / ticksPerMicrosecondTimes1024;
}
/* /*
================ ================
Sys_Mkdir Sys_Mkdir
@ -243,6 +268,51 @@ void Sys_Mkdir( const char* path )
mkdir( path, 0777 ); mkdir( path, 0777 );
} }
/*
================
Sys_Rmdir
================
*/
bool Sys_Rmdir( const char* path )
{
return ( rmdir( path ) == 0 );
}
/*
========================
Sys_IsFileWritable
========================
*/
bool Sys_IsFileWritable( const char* path )
{
struct stat st;
if( stat( path, &st ) == -1 )
{
return true;
}
return ( st.st_mode & S_IWRITE ) != 0;
}
/*
========================
Sys_IsFolder
========================
*/
sysFolder_t Sys_IsFolder( const char* path )
{
struct stat buffer;
if( stat( path, &buffer ) < 0 )
{
return FOLDER_ERROR;
}
return ( buffer.st_mode & S_IFDIR ) != 0 ? FOLDER_YES : FOLDER_NO;
}
// RB end
/* /*
================ ================
Sys_ListFiles Sys_ListFiles
@ -319,12 +389,13 @@ int Sys_ListFiles( const char* directory, const char* extension, idStrList& list
EVENT LOOP EVENT LOOP
============================================================================ ============================================================================
*/ */
/*
#define MAX_QUED_EVENTS 256 #define MAX_QUED_EVENTS 256
#define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 ) #define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 )
static sysEvent_t eventQue[MAX_QUED_EVENTS]; static sysEvent_t eventQue[MAX_QUED_EVENTS];
static int eventHead, eventTail; static int eventHead, eventTail;
*/
/* /*
================ ================
@ -333,11 +404,12 @@ Posix_QueEvent
ptr should either be null, or point to a block of data that can be freed later ptr should either be null, or point to a block of data that can be freed later
================ ================
*/ */
/*
void Posix_QueEvent( sysEventType_t type, int value, int value2, void Posix_QueEvent( sysEventType_t type, int value, int value2,
int ptrLength, void* ptr ) int ptrLength, void* ptr )
{ {
sysEvent_t* ev; sysEvent_t* ev;
ev = &eventQue[eventHead & MASK_QUED_EVENTS]; ev = &eventQue[eventHead & MASK_QUED_EVENTS];
if( eventHead - eventTail >= MAX_QUED_EVENTS ) if( eventHead - eventTail >= MAX_QUED_EVENTS )
{ {
@ -351,29 +423,31 @@ void Posix_QueEvent( sysEventType_t type, int value, int value2,
} }
eventTail++; eventTail++;
} }
eventHead++; eventHead++;
ev->evType = type; ev->evType = type;
ev->evValue = value; ev->evValue = value;
ev->evValue2 = value2; ev->evValue2 = value2;
ev->evPtrLength = ptrLength; ev->evPtrLength = ptrLength;
ev->evPtr = ptr; ev->evPtr = ptr;
#if 0 #if 0
common->Printf( "Event %d: %d %d\n", ev->evType, ev->evValue, ev->evValue2 ); common->Printf( "Event %d: %d %d\n", ev->evType, ev->evValue, ev->evValue2 );
#endif #endif
} }
*/
/* /*
================ ================
Sys_GetEvent Sys_GetEvent
================ ================
*/ */
/*
sysEvent_t Sys_GetEvent() sysEvent_t Sys_GetEvent()
{ {
static sysEvent_t ev; static sysEvent_t ev;
// return if we have data // return if we have data
if( eventHead > eventTail ) if( eventHead > eventTail )
{ {
@ -382,19 +456,22 @@ sysEvent_t Sys_GetEvent()
} }
// return the empty event with the current time // return the empty event with the current time
memset( &ev, 0, sizeof( ev ) ); memset( &ev, 0, sizeof( ev ) );
return ev; return ev;
} }
*/
/* /*
================ ================
Sys_ClearEvents Sys_ClearEvents
================ ================
*/ */
/*
void Sys_ClearEvents() void Sys_ClearEvents()
{ {
eventHead = eventTail = 0; eventHead = eventTail = 0;
} }
*/
/* /*
================ ================
@ -516,7 +593,7 @@ const char* Sys_DefaultCDPath()
return ""; return "";
} }
long Sys_FileTimeStamp( FILE* fp ) ID_TIME_T Sys_FileTimeStamp( idFileHandle fp )
{ {
struct stat st; struct stat st;
fstat( fileno( fp ), &st ); fstat( fileno( fp ), &st );
@ -567,6 +644,7 @@ void Sys_FlushCacheMemory( void* base, int bytes )
// Sys_Printf("Sys_FlushCacheMemory stub\n"); // Sys_Printf("Sys_FlushCacheMemory stub\n");
} }
/*
bool Sys_FPU_StackIsEmpty() bool Sys_FPU_StackIsEmpty()
{ {
return true; return true;
@ -584,6 +662,7 @@ const char* Sys_FPU_GetState()
void Sys_FPU_SetPrecision( int precision ) void Sys_FPU_SetPrecision( int precision )
{ {
} }
*/
/* /*
================ ================
@ -615,18 +694,59 @@ void Sys_SetPhysicalWorkMemory( int minBytes, int maxBytes )
common->DPrintf( "TODO: Sys_SetPhysicalWorkMemory\n" ); common->DPrintf( "TODO: Sys_SetPhysicalWorkMemory\n" );
} }
// RB begin
/* /*
=========== ================
Sys_GetDriveFreeSpace Sys_GetDriveFreeSpace
return in MegaBytes returns in megabytes
=========== ================
*/ */
int Sys_GetDriveFreeSpace( const char* path ) int Sys_GetDriveFreeSpace( const char* path )
{ {
common->DPrintf( "TODO: Sys_GetDriveFreeSpace\n" ); int ret = 26;
return 1000 * 1024;
struct statvfs st;
if( statvfs( path, &st ) == 0 )
{
unsigned long blocksize = st.f_bsize;
unsigned long freeblocks = st.f_bfree;
unsigned long free = blocksize * freeblocks;
ret = ( double )( free ) / ( 1024.0 * 1024.0 );
}
return ret;
} }
/*
========================
Sys_GetDriveFreeSpaceInBytes
========================
*/
int64 Sys_GetDriveFreeSpaceInBytes( const char* path )
{
int64 ret = 1;
struct statvfs st;
if( statvfs( path, &st ) == 0 )
{
unsigned long blocksize = st.f_bsize;
unsigned long freeblocks = st.f_bfree;
unsigned long free = blocksize * freeblocks;
ret = free;
}
return ret;
}
// RB end
/* /*
================ ================
Sys_AlreadyRunning Sys_AlreadyRunning
@ -645,12 +765,15 @@ Posix_EarlyInit
*/ */
void Posix_EarlyInit() void Posix_EarlyInit()
{ {
memset( &asyncThread, 0, sizeof( asyncThread ) ); //memset( &asyncThread, 0, sizeof( asyncThread ) );
exit_spawn[0] = '\0'; exit_spawn[0] = '\0';
Posix_InitSigs(); Posix_InitSigs();
// set the base time // set the base time
Sys_Milliseconds(); Sys_Milliseconds();
Posix_InitPThreads();
//Posix_InitPThreads();
} }
/* /*
@ -664,10 +787,12 @@ void Posix_LateInit()
com_pid.SetInteger( getpid() ); com_pid.SetInteger( getpid() );
common->Printf( "pid: %d\n", com_pid.GetInteger() ); common->Printf( "pid: %d\n", com_pid.GetInteger() );
common->Printf( "%d MB System Memory\n", Sys_GetSystemRam() ); common->Printf( "%d MB System Memory\n", Sys_GetSystemRam() );
#ifndef ID_DEDICATED
common->Printf( "%d MB Video Memory\n", Sys_GetVideoRam() ); //#ifndef ID_DEDICATED
#endif //common->Printf( "%d MB Video Memory\n", Sys_GetVideoRam() );
Posix_StartAsyncThread( ); //#endif
//Posix_StartAsyncThread( );
} }
/* /*
@ -826,7 +951,7 @@ void tty_Show()
// RB begin // RB begin
#if defined(__ANDROID__) #if defined(__ANDROID__)
//__android_log_print(ANDROID_LOG_DEBUG, "Techyon_DEBUG", "%s", buf); //__android_log_print(ANDROID_LOG_DEBUG, "RBDoom3_DEBUG", "%s", buf);
#endif #endif
// RB end // RB end
@ -1164,6 +1289,7 @@ called during frame loops, pacifier updates etc.
this is only for console input polling and misc mouse grab tasks this is only for console input polling and misc mouse grab tasks
the actual mouse and keyboard input is in the Sys_Poll logic the actual mouse and keyboard input is in the Sys_Poll logic
*/ */
/*
void Sys_GenerateEvents() void Sys_GenerateEvents()
{ {
char* s; char* s;
@ -1171,13 +1297,14 @@ void Sys_GenerateEvents()
{ {
char* b; char* b;
int len; int len;
len = strlen( s ) + 1; len = strlen( s ) + 1;
b = ( char* )Mem_Alloc( len ); b = ( char* )Mem_Alloc( len );
strcpy( b, s ); strcpy( b, s );
Posix_QueEvent( SE_CONSOLE, 0, 0, len, b ); Posix_QueEvent( SE_CONSOLE, 0, 0, len, b );
} }
} }
*/
/* /*
=============== ===============
@ -1196,7 +1323,7 @@ void Sys_DebugPrintf( const char* fmt, ... )
va_end( argptr ); va_end( argptr );
msg[sizeof( msg ) - 1] = '\0'; msg[sizeof( msg ) - 1] = '\0';
__android_log_print( ANDROID_LOG_DEBUG, "Techyon_Debug", msg ); __android_log_print( ANDROID_LOG_DEBUG, "RBDoom3_Debug", msg );
#else #else
va_list argptr; va_list argptr;
@ -1211,7 +1338,7 @@ void Sys_DebugPrintf( const char* fmt, ... )
void Sys_DebugVPrintf( const char* fmt, va_list arg ) void Sys_DebugVPrintf( const char* fmt, va_list arg )
{ {
#if defined(__ANDROID__) #if defined(__ANDROID__)
__android_log_vprint( ANDROID_LOG_DEBUG, "Techyon_Debug", fmt, arg ); __android_log_vprint( ANDROID_LOG_DEBUG, "RBDoom3_Debug", fmt, arg );
#else #else
tty_Hide(); tty_Hide();
vprintf( fmt, arg ); vprintf( fmt, arg );
@ -1230,7 +1357,7 @@ void Sys_Printf( const char* fmt, ... )
va_end( argptr ); va_end( argptr );
msg[sizeof( msg ) - 1] = '\0'; msg[sizeof( msg ) - 1] = '\0';
__android_log_print( ANDROID_LOG_DEBUG, "Techyon", msg ); __android_log_print( ANDROID_LOG_DEBUG, "RBDoom3", msg );
#else #else
va_list argptr; va_list argptr;
@ -1245,7 +1372,7 @@ void Sys_Printf( const char* fmt, ... )
void Sys_VPrintf( const char* fmt, va_list arg ) void Sys_VPrintf( const char* fmt, va_list arg )
{ {
#if defined(__ANDROID__) #if defined(__ANDROID__)
__android_log_vprint( ANDROID_LOG_DEBUG, "Techyon", fmt, arg ); __android_log_vprint( ANDROID_LOG_DEBUG, "RBDoom3", fmt, arg );
#else #else
tty_Hide(); tty_Hide();
vprintf( fmt, arg ); vprintf( fmt, arg );
@ -1272,8 +1399,12 @@ void Sys_Error( const char* error, ... )
} }
/* /*
=============== ================
Sys_FreeOpenAL Sys_SetLanguageFromSystem
=============== ================
*/ */
void Sys_FreeOpenAL() { } extern idCVar sys_lang;
void Sys_SetLanguageFromSystem()
{
sys_lang.SetString( Sys_DefaultLanguage() );
}

View file

@ -46,10 +46,9 @@ If you have questions concerning this license or the applicable additional terms
#include "../../idlib/precompiled.h" #include "../../idlib/precompiled.h"
idPort clientPort, serverPort; idUDP clientPort, serverPort;
idCVar net_ip( "net_ip", "localhost", CVAR_SYSTEM, "local IP address" ); idCVar net_ip( "net_ip", "localhost", CVAR_SYSTEM, "local IP address" );
idCVar net_port( "net_port", "", CVAR_SYSTEM | CVAR_INTEGER, "local IP port number" );
typedef struct typedef struct
{ {
@ -540,12 +539,47 @@ static int IPSocket( const char* net_interface, int port, netadr_t* bound_to = N
return newsocket; return newsocket;
} }
/*
========================
Sys_GetLocalIPCount
========================
*/
int Sys_GetLocalIPCount()
{
return num_interfaces;
}
/*
========================
Sys_GetLocalIP
========================
*/
const char* Sys_GetLocalIP( int i )
{
if( ( i < 0 ) || ( i >= num_interfaces ) )
{
return NULL;
}
static char s[64];
unsigned char bytes[4];
bytes[0] = netint[i].ip & 0xFF;
bytes[1] = ( netint[i].ip >> 8 ) & 0xFF;
bytes[2] = ( netint[i].ip >> 16 ) & 0xFF;
bytes[3] = ( netint[i].ip >> 24 ) & 0xFF;
idStr::snPrintf( s, sizeof( s ), "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] );
return s;
}
/* /*
================== ==================
idPort::idPort idUDP::idUDP
================== ==================
*/ */
idPort::idPort() idUDP::idUDP()
{ {
netSocket = 0; netSocket = 0;
memset( &bound_to, 0, sizeof( bound_to ) ); memset( &bound_to, 0, sizeof( bound_to ) );
@ -553,20 +587,20 @@ idPort::idPort()
/* /*
================== ==================
idPort::~idPort idUDP::~idUDP
================== ==================
*/ */
idPort::~idPort() idUDP::~idUDP()
{ {
Close(); Close();
} }
/* /*
================== ==================
idPort::Close idUDP::Close
================== ==================
*/ */
void idPort::Close() void idUDP::Close()
{ {
if( netSocket ) if( netSocket )
{ {
@ -578,10 +612,10 @@ void idPort::Close()
/* /*
================== ==================
idPort::GetPacket idUDP::GetPacket
================== ==================
*/ */
bool idPort::GetPacket( netadr_t& net_from, void* data, int& size, int maxSize ) bool idUDP::GetPacket( netadr_t& net_from, void* data, int& size, int maxSize )
{ {
int ret; int ret;
struct sockaddr_in from; struct sockaddr_in from;
@ -602,7 +636,7 @@ bool idPort::GetPacket( netadr_t& net_from, void* data, int& size, int maxSize )
// those commonly happen, don't verbose // those commonly happen, don't verbose
return false; return false;
} }
common->DPrintf( "idPort::GetPacket recvfrom(): %s\n", strerror( errno ) ); common->DPrintf( "idUDP::GetPacket recvfrom(): %s\n", strerror( errno ) );
return false; return false;
} }
@ -615,10 +649,10 @@ bool idPort::GetPacket( netadr_t& net_from, void* data, int& size, int maxSize )
/* /*
================== ==================
idPort::GetPacketBlocking idUDP::GetPacketBlocking
================== ==================
*/ */
bool idPort::GetPacketBlocking( netadr_t& net_from, void* data, int& size, int maxSize, int timeout ) bool idUDP::GetPacketBlocking( netadr_t& net_from, void* data, int& size, int maxSize, int timeout )
{ {
fd_set set; fd_set set;
struct timeval tv; struct timeval tv;
@ -644,12 +678,12 @@ bool idPort::GetPacketBlocking( netadr_t& net_from, void* data, int& size, int m
{ {
if( errno == EINTR ) if( errno == EINTR )
{ {
common->DPrintf( "idPort::GetPacketBlocking: select EINTR\n" ); common->DPrintf( "idUDP::GetPacketBlocking: select EINTR\n" );
return false; return false;
} }
else else
{ {
common->Error( "idPort::GetPacketBlocking: select failed: %s\n", strerror( errno ) ); common->Error( "idUDP::GetPacketBlocking: select failed: %s\n", strerror( errno ) );
} }
} }
@ -665,7 +699,7 @@ bool idPort::GetPacketBlocking( netadr_t& net_from, void* data, int& size, int m
if( ret == -1 ) if( ret == -1 )
{ {
// there should be no blocking errors once select declares things are good // there should be no blocking errors once select declares things are good
common->DPrintf( "idPort::GetPacketBlocking: %s\n", strerror( errno ) ); common->DPrintf( "idUDP::GetPacketBlocking: %s\n", strerror( errno ) );
return false; return false;
} }
assert( ret < maxSize ); assert( ret < maxSize );
@ -676,17 +710,17 @@ bool idPort::GetPacketBlocking( netadr_t& net_from, void* data, int& size, int m
/* /*
================== ==================
idPort::SendPacket idUDP::SendPacket
================== ==================
*/ */
void idPort::SendPacket( const netadr_t to, const void* data, int size ) void idUDP::SendPacket( const netadr_t to, const void* data, int size )
{ {
int ret; int ret;
struct sockaddr_in addr; struct sockaddr_in addr;
if( to.type == NA_BAD ) if( to.type == NA_BAD )
{ {
common->Warning( "idPort::SendPacket: bad address type NA_BAD - ignored" ); common->Warning( "idUDP::SendPacket: bad address type NA_BAD - ignored" );
return; return;
} }
@ -700,16 +734,16 @@ void idPort::SendPacket( const netadr_t to, const void* data, int size )
ret = sendto( netSocket, data, size, 0, ( struct sockaddr* ) &addr, sizeof( addr ) ); ret = sendto( netSocket, data, size, 0, ( struct sockaddr* ) &addr, sizeof( addr ) );
if( ret == -1 ) if( ret == -1 )
{ {
common->Printf( "idPort::SendPacket ERROR: to %s: %s\n", Sys_NetAdrToString( to ), strerror( errno ) ); common->Printf( "idUDP::SendPacket ERROR: to %s: %s\n", Sys_NetAdrToString( to ), strerror( errno ) );
} }
} }
/* /*
================== ==================
idPort::InitForPort idUDP::InitForPort
================== ==================
*/ */
bool idPort::InitForPort( int portNumber ) bool idUDP::InitForPort( int portNumber )
{ {
netSocket = IPSocket( net_ip.GetString(), portNumber, &bound_to ); netSocket = IPSocket( net_ip.GetString(), portNumber, &bound_to );
if( netSocket <= 0 ) if( netSocket <= 0 )
@ -721,209 +755,4 @@ bool idPort::InitForPort( int portNumber )
return true; return true;
} }
//=============================================================================
/*
==================
idTCP::idTCP
==================
*/
idTCP::idTCP()
{
fd = 0;
memset( &address, 0, sizeof( address ) );
}
/*
==================
idTCP::~idTCP
==================
*/
idTCP::~idTCP()
{
Close();
}
/*
==================
idTCP::Init
==================
*/
bool idTCP::Init( const char* host, short port )
{
struct sockaddr_in sadr;
if( !Sys_StringToNetAdr( host, &address, true ) )
{
common->Printf( "Couldn't resolve server name \"%s\"\n", host );
return false;
}
address.type = NA_IP;
if( !address.port )
{
address.port = port;
}
common->Printf( "\"%s\" resolved to %i.%i.%i.%i:%i\n", host,
address.ip[0], address.ip[1], address.ip[2], address.ip[3], address.port );
NetadrToSockadr( &address, &sadr );
if( fd )
{
common->Warning( "idTCP::Init: already initialized?\n" );
}
if( ( fd = socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
fd = 0;
common->Printf( "ERROR: idTCP::Init: socket: %s\n", strerror( errno ) );
return false;
}
if( connect( fd, ( const sockaddr* )&sadr, sizeof( sadr ) ) == -1 )
{
common->Printf( "ERROR: idTCP::Init: connect: %s\n", strerror( errno ) );
close( fd );
fd = 0;
return false;
}
int status;
if( ( status = fcntl( fd, F_GETFL, 0 ) ) != -1 )
{
status |= O_NONBLOCK; /* POSIX */
status = fcntl( fd, F_SETFL, status );
}
if( status == -1 )
{
common->Printf( "ERROR: idTCP::Init: fcntl / O_NONBLOCK: %s\n", strerror( errno ) );
close( fd );
fd = 0;
return false;
}
common->DPrintf( "Opened TCP connection\n" );
return true;
}
/*
==================
idTCP::Close
==================
*/
void idTCP::Close()
{
if( fd )
{
close( fd );
}
fd = 0;
}
/*
==================
idTCP::Read
==================
*/
int idTCP::Read( void* data, int size )
{
int nbytes;
if( !fd )
{
common->Printf( "idTCP::Read: not initialized\n" );
return -1;
}
#if defined(_GNU_SOURCE)
// handle EINTR interrupted system call with TEMP_FAILURE_RETRY - this is probably GNU libc specific
if( ( nbytes = TEMP_FAILURE_RETRY( read( fd, data, size ) ) ) == -1 )
{
#else
do
{
nbytes = read( fd, data, size );
}
while( nbytes == -1 && errno == EINTR );
if( nbytes == -1 )
{
#endif
if( errno == EAGAIN )
{
return 0;
}
common->Printf( "ERROR: idTCP::Read: %s\n", strerror( errno ) );
Close();
return -1;
}
// a successful read of 0 bytes indicates remote has closed the connection
if( nbytes == 0 )
{
common->DPrintf( "idTCP::Read: read 0 bytes - assume connection closed\n" );
return -1;
}
return nbytes;
}
/*
==================
idTCP::Write
==================
*/
static void got_SIGPIPE( int signum )
{
common->Printf( "idTCP: SIGPIPE\n" );
}
int idTCP::Write( void* data, int size )
{
int nbytes;
if( !fd )
{
common->Printf( "idTCP::Write: not initialized\n" );
return -1;
}
struct sigaction bak_action;
struct sigaction action;
action.sa_handler = got_SIGPIPE;
sigemptyset( &action.sa_mask );
action.sa_flags = 0;
if( sigaction( SIGPIPE, &action, &bak_action ) != 0 )
{
common->Printf( "ERROR: idTCP::Write: failed to set temporary SIGPIPE handler\n" );
Close();
return -1;
}
#if defined(_GNU_SOURCE)
// handle EINTR interrupted system call with TEMP_FAILURE_RETRY - this is probably GNU libc specific
if( ( nbytes = TEMP_FAILURE_RETRY( write( fd, data, size ) ) ) == -1 )
{
#else
do
{
nbytes = write( fd, data, size );
}
while( nbytes == -1 && errno == EINTR );
if( nbytes == -1 )
{
#endif
common->Printf( "ERROR: idTCP::Write: %s\n", strerror( errno ) );
Close();
return -1;
}
if( sigaction( SIGPIPE, &bak_action, NULL ) != 0 )
{
common->Printf( "ERROR: idTCP::Write: failed to reset SIGPIPE handler\n" );
Close();
return -1;
}
return nbytes;
}

View file

@ -57,5 +57,7 @@ void Posix_Shutdown();
void Sys_FPE_handler( int signum, siginfo_t* info, void* context ); void Sys_FPE_handler( int signum, siginfo_t* info, void* context );
void Sys_DoStartProcess( const char* exeName, bool dofork = true ); // if not forking, current process gets replaced void Sys_DoStartProcess( const char* exeName, bool dofork = true ); // if not forking, current process gets replaced
char* Posix_ConsoleInput();
#endif #endif

View file

@ -0,0 +1,848 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../../idlib/precompiled.h"
#include "../sys_session_local.h"
#include "../sys_savegame.h"
idCVar savegame_winInduceDelay( "savegame_winInduceDelay", "0", CVAR_INTEGER, "on windows, this is a delay induced before any file operation occurs" );
extern idCVar fs_savepath;
extern idCVar saveGame_checksum;
extern idCVar savegame_error;
#define SAVEGAME_SENTINAL 0x12358932
// RB begin
#define ERROR_SUCCESS 0
// RB end
/*
========================
void Sys_ExecuteSavegameCommandAsync
========================
*/
void Sys_ExecuteSavegameCommandAsyncImpl( idSaveLoadParms* savegameParms )
{
assert( savegameParms != NULL );
session->GetSaveGameManager().GetSaveGameThread().data.saveLoadParms = savegameParms;
if( session->GetSaveGameManager().GetSaveGameThread().GetThreadHandle() == 0 )
{
session->GetSaveGameManager().GetSaveGameThread().StartWorkerThread( "Savegame", CORE_ANY );
}
session->GetSaveGameManager().GetSaveGameThread().SignalWork();
}
/*
========================
idLocalUser * GetLocalUserFromUserId
========================
*/
idLocalUserWin* GetLocalUserFromSaveParms( const saveGameThreadArgs_t& data )
{
if( ( data.saveLoadParms != NULL ) && ( data.saveLoadParms->inputDeviceId >= 0 ) )
{
idLocalUser* user = session->GetSignInManager().GetLocalUserByInputDevice( data.saveLoadParms->inputDeviceId );
if( user != NULL )
{
idLocalUserWin* userWin = static_cast< idLocalUserWin* >( user );
if( userWin != NULL && data.saveLoadParms->userId == idStr::Hash( userWin->GetGamerTag() ) )
{
return userWin;
}
}
}
return NULL;
}
/*
========================
idSaveGameThread::SaveGame
========================
*/
int idSaveGameThread::Save()
{
idLocalUserWin* user = GetLocalUserFromSaveParms( data );
if( user == NULL )
{
data.saveLoadParms->errorCode = SAVEGAME_E_INVALID_USER;
return -1;
}
idSaveLoadParms* callback = data.saveLoadParms;
idStr saveFolder = "savegame";
saveFolder.AppendPath( callback->directory );
// Check for the required storage space.
int64 requiredSizeBytes = 0;
{
for( int i = 0; i < callback->files.Num(); i++ )
{
idFile_SaveGame* file = callback->files[i];
requiredSizeBytes += ( file->Length() + sizeof( unsigned int ) ); // uint for checksum
if( file->type == SAVEGAMEFILE_PIPELINED )
{
requiredSizeBytes += MIN_SAVEGAME_SIZE_BYTES;
}
}
}
int ret = ERROR_SUCCESS;
// Check size of previous files if needed
// ALL THE FILES RIGHT NOW---- could use pattern later...
idStrList filesToDelete;
if( ( callback->mode & SAVEGAME_MBF_DELETE_FILES ) && !callback->cancelled )
{
if( fileSystem->IsFolder( saveFolder.c_str(), "fs_savePath" ) == FOLDER_YES )
{
idFileList* files = fileSystem->ListFilesTree( saveFolder.c_str(), "*.*" );
for( int i = 0; i < files->GetNumFiles(); i++ )
{
requiredSizeBytes -= fileSystem->GetFileLength( files->GetFile( i ) );
filesToDelete.Append( files->GetFile( i ) );
}
fileSystem->FreeFileList( files );
}
}
// Inform user about size required if necessary
if( requiredSizeBytes > 0 && !callback->cancelled )
{
user->StorageSizeAvailable( requiredSizeBytes, callback->requiredSpaceInBytes );
if( callback->requiredSpaceInBytes > 0 )
{
// check to make sure savepath actually exists before erroring
idStr directory = fs_savepath.GetString();
directory += "\\"; // so it doesn't think the last part is a file and ignores in the directory creation
fileSystem->CreateOSPath( directory ); // we can't actually check FileExists in production builds, so just try to create it
user->StorageSizeAvailable( requiredSizeBytes, callback->requiredSpaceInBytes );
if( callback->requiredSpaceInBytes > 0 )
{
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
// safe to return, haven't written any files yet
return -1;
}
}
}
// Delete all previous files if needed
// ALL THE FILES RIGHT NOW---- could use pattern later...
for( int i = 0; i < filesToDelete.Num() && !callback->cancelled; i++ )
{
fileSystem->RemoveFile( filesToDelete[i].c_str() );
}
// Save the raw files.
for( int i = 0; i < callback->files.Num() && ret == ERROR_SUCCESS && !callback->cancelled; i++ )
{
idFile_SaveGame* file = callback->files[i];
idStr fileName = saveFolder;
fileName.AppendPath( file->GetName() );
idStr tempFileName = va( "%s.temp", fileName.c_str() );
idFile* outputFile = fileSystem->OpenFileWrite( tempFileName, "fs_savePath" );
if( outputFile == NULL )
{
idLib::Warning( "[%s]: Couldn't open file for writing, %s", __FUNCTION__, tempFileName.c_str() );
file->error = true;
callback->errorCode = SAVEGAME_E_UNKNOWN;
ret = -1;
continue;
}
if( ( file->type & SAVEGAMEFILE_PIPELINED ) != 0 )
{
idFile_SaveGamePipelined* inputFile = dynamic_cast< idFile_SaveGamePipelined* >( file );
assert( inputFile != NULL );
blockForIO_t block;
while( inputFile->NextWriteBlock( & block ) )
{
if( ( size_t )outputFile->Write( block.data, block.bytes ) != block.bytes )
{
idLib::Warning( "[%s]: Write failed.", __FUNCTION__ );
file->error = true;
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
ret = -1;
break;
}
}
}
else
{
if( ( file->type & SAVEGAMEFILE_BINARY ) || ( file->type & SAVEGAMEFILE_COMPRESSED ) )
{
if( saveGame_checksum.GetBool() )
{
unsigned int checksum = MD5_BlockChecksum( file->GetDataPtr(), file->Length() );
size_t size = outputFile->WriteBig( checksum );
if( size != sizeof( checksum ) )
{
idLib::Warning( "[%s]: Write failed.", __FUNCTION__ );
file->error = true;
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
ret = -1;
}
}
}
size_t size = outputFile->Write( file->GetDataPtr(), file->Length() );
if( size != ( size_t )file->Length() )
{
idLib::Warning( "[%s]: Write failed.", __FUNCTION__ );
file->error = true;
callback->errorCode = SAVEGAME_E_INSUFFICIENT_ROOM;
ret = -1;
}
else
{
idLib::PrintfIf( saveGame_verbose.GetBool(), "Saved %s (%s)\n", fileName.c_str(), outputFile->GetFullPath() );
}
}
delete outputFile;
if( ret == ERROR_SUCCESS )
{
// Remove the old file
if( !fileSystem->RenameFile( tempFileName, fileName, "fs_savePath" ) )
{
idLib::Warning( "Could not start to rename temporary file %s to %s.", tempFileName.c_str(), fileName.c_str() );
}
}
else
{
fileSystem->RemoveFile( tempFileName );
idLib::Warning( "Invalid write to temporary file %s.", tempFileName.c_str() );
}
}
if( data.saveLoadParms->cancelled )
{
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
}
// Removed because it seemed a bit drastic
#if 0
// If there is an error, delete the partially saved folder
if( callback->errorCode != SAVEGAME_E_NONE )
{
if( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES )
{
idFileList* files = fileSystem->ListFilesTree( saveFolder, "/|*" );
for( int i = 0; i < files->GetNumFiles(); i++ )
{
fileSystem->RemoveFile( files->GetFile( i ) );
}
fileSystem->FreeFileList( files );
fileSystem->RemoveDir( saveFolder );
}
}
#endif
return ret;
}
/*
========================
idSessionLocal::LoadGame
========================
*/
int idSaveGameThread::Load()
{
idSaveLoadParms* callback = data.saveLoadParms;
idStr saveFolder = "savegame";
saveFolder.AppendPath( callback->directory );
if( fileSystem->IsFolder( saveFolder, "fs_savePath" ) != FOLDER_YES )
{
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
return -1;
}
int ret = ERROR_SUCCESS;
for( int i = 0; i < callback->files.Num() && ret == ERROR_SUCCESS && !callback->cancelled; i++ )
{
idFile_SaveGame* file = callback->files[i];
idStr filename = saveFolder;
filename.AppendPath( file->GetName() );
idFile* inputFile = fileSystem->OpenFileRead( filename.c_str() );
if( inputFile == NULL )
{
file->error = true;
if( !( file->type & SAVEGAMEFILE_OPTIONAL ) )
{
callback->errorCode = SAVEGAME_E_CORRUPTED;
ret = -1;
}
continue;
}
if( ( file->type & SAVEGAMEFILE_PIPELINED ) != 0 )
{
idFile_SaveGamePipelined* outputFile = dynamic_cast< idFile_SaveGamePipelined* >( file );
assert( outputFile != NULL );
size_t lastReadBytes = 0;
blockForIO_t block;
while( outputFile->NextReadBlock( &block, lastReadBytes ) && !callback->cancelled )
{
lastReadBytes = inputFile->Read( block.data, block.bytes );
if( lastReadBytes != block.bytes )
{
// Notify end-of-file to the save game file which will cause all reads on the
// other end of the pipeline to return zero bytes after the pipeline is drained.
outputFile->NextReadBlock( NULL, lastReadBytes );
break;
}
}
}
else
{
size_t size = inputFile->Length();
unsigned int originalChecksum = 0;
if( ( file->type & SAVEGAMEFILE_BINARY ) != 0 || ( file->type & SAVEGAMEFILE_COMPRESSED ) != 0 )
{
if( saveGame_checksum.GetBool() )
{
if( size >= sizeof( originalChecksum ) )
{
inputFile->ReadBig( originalChecksum );
size -= sizeof( originalChecksum );
}
}
}
file->SetLength( size );
size_t sizeRead = inputFile->Read( ( void* )file->GetDataPtr(), size );
if( sizeRead != size )
{
file->error = true;
callback->errorCode = SAVEGAME_E_CORRUPTED;
ret = -1;
}
if( ( file->type & SAVEGAMEFILE_BINARY ) != 0 || ( file->type & SAVEGAMEFILE_COMPRESSED ) != 0 )
{
if( saveGame_checksum.GetBool() )
{
unsigned int checksum = MD5_BlockChecksum( file->GetDataPtr(), file->Length() );
if( checksum != originalChecksum )
{
file->error = true;
callback->errorCode = SAVEGAME_E_CORRUPTED;
ret = -1;
}
}
}
}
delete inputFile;
}
if( data.saveLoadParms->cancelled )
{
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
}
return ret;
}
/*
========================
idSaveGameThread::Delete
This deletes a complete savegame directory
========================
*/
int idSaveGameThread::Delete()
{
idSaveLoadParms* callback = data.saveLoadParms;
idStr saveFolder = "savegame";
saveFolder.AppendPath( callback->directory );
int ret = ERROR_SUCCESS;
if( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES )
{
idFileList* files = fileSystem->ListFilesTree( saveFolder, "/|*" );
for( int i = 0; i < files->GetNumFiles() && !callback->cancelled; i++ )
{
fileSystem->RemoveFile( files->GetFile( i ) );
}
fileSystem->FreeFileList( files );
fileSystem->RemoveDir( saveFolder );
}
else
{
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
ret = -1;
}
if( data.saveLoadParms->cancelled )
{
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
}
return ret;
}
/*
========================
idSaveGameThread::Enumerate
========================
*/
int idSaveGameThread::Enumerate()
{
idSaveLoadParms* callback = data.saveLoadParms;
idStr saveFolder = "savegame";
callback->detailList.Clear();
int ret = ERROR_SUCCESS;
if( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES )
{
idFileList* files = fileSystem->ListFilesTree( saveFolder, SAVEGAME_DETAILS_FILENAME );
const idStrList& fileList = files->GetList();
for( int i = 0; i < fileList.Num() && !callback->cancelled; i++ )
{
idSaveGameDetails* details = callback->detailList.Alloc();
// We have more folders on disk than we have room in our save detail list, stop trying to read them in and continue with what we have
if( details == NULL )
{
break;
}
idStr directory = fileList[i];
idFile* file = fileSystem->OpenFileRead( directory.c_str() );
if( file != NULL )
{
// Read the DETAIL file for the enumerated data
if( callback->mode & SAVEGAME_MBF_READ_DETAILS )
{
if( !SavegameReadDetailsFromFile( file, *details ) )
{
details->damaged = true;
ret = -1;
}
}
// RB: FIXME ?
// use current time
time_t aclock;
time( &aclock );
/*
// Use the date from the directory
WIN32_FILE_ATTRIBUTE_DATA attrData;
BOOL attrRet = GetFileAttributesEx( file->GetFullPath(), GetFileExInfoStandard, &attrData );
delete file;
if( attrRet == TRUE )
{
FILETIME lastWriteTime = attrData.ftLastWriteTime;
const ULONGLONG second = 10000000L; // One second = 10,000,000 * 100 nsec
SYSTEMTIME base_st = { 1970, 1, 0, 1, 0, 0, 0, 0 };
ULARGE_INTEGER itime;
FILETIME base_ft;
BOOL success = SystemTimeToFileTime( &base_st, &base_ft );
itime.QuadPart = ( ( ULARGE_INTEGER* )&lastWriteTime )->QuadPart;
if( success )
{
itime.QuadPart -= ( ( ULARGE_INTEGER* )&base_ft )->QuadPart;
}
else
{
// Hard coded number of 100-nanosecond units from 1/1/1601 to 1/1/1970
itime.QuadPart -= 116444736000000000LL;
}
itime.QuadPart /= second;
details->date = itime.QuadPart;
}
*/
// RB end
}
else
{
details->damaged = true;
}
// populate the game details struct
directory = directory.StripFilename();
details->slotName = directory.c_str() + saveFolder.Length() + 1; // Strip off the prefix too
// JDC: I hit this all the time assert( fileSystem->IsFolder( directory.c_str(), "fs_savePath" ) == FOLDER_YES );
}
fileSystem->FreeFileList( files );
}
else
{
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
ret = -3;
}
if( data.saveLoadParms->cancelled )
{
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
}
return ret;
}
/*
========================
idSaveGameThread::EnumerateFiles
========================
*/
int idSaveGameThread::EnumerateFiles()
{
idSaveLoadParms* callback = data.saveLoadParms;
idStr folder = "savegame";
folder.AppendPath( callback->directory );
callback->files.Clear();
int ret = ERROR_SUCCESS;
if( fileSystem->IsFolder( folder, "fs_savePath" ) == FOLDER_YES )
{
// get listing of all the files, but filter out below
idFileList* files = fileSystem->ListFilesTree( folder, "*.*" );
// look for the instance pattern
for( int i = 0; i < files->GetNumFiles() && ret == 0 && !callback->cancelled; i++ )
{
idStr fullFilename = files->GetFile( i );
idStr filename = fullFilename;
filename.StripPath();
if( filename.IcmpPrefix( callback->pattern ) != 0 )
{
continue;
}
if( !callback->postPattern.IsEmpty() && filename.Right( callback->postPattern.Length() ).IcmpPrefix( callback->postPattern ) != 0 )
{
continue;
}
// Read the DETAIL file for the enumerated data
if( callback->mode & SAVEGAME_MBF_READ_DETAILS )
{
idSaveGameDetails& details = callback->description;
idFile* uncompressed = fileSystem->OpenFileRead( fullFilename.c_str() );
if( uncompressed == NULL )
{
details.damaged = true;
}
else
{
if( !SavegameReadDetailsFromFile( uncompressed, details ) )
{
ret = -1;
}
delete uncompressed;
}
// populate the game details struct
details.slotName = callback->directory;
assert( fileSystem->IsFolder( details.slotName, "fs_savePath" ) == FOLDER_YES );
}
idFile_SaveGame* file = new( TAG_SAVEGAMES ) idFile_SaveGame( filename, SAVEGAMEFILE_AUTO_DELETE );
callback->files.Append( file );
}
fileSystem->FreeFileList( files );
}
else
{
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
ret = -3;
}
if( data.saveLoadParms->cancelled )
{
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
}
return ret;
}
/*
========================
idSaveGameThread::DeleteFiles
========================
*/
int idSaveGameThread::DeleteFiles()
{
idSaveLoadParms* callback = data.saveLoadParms;
idStr folder = "savegame";
folder.AppendPath( callback->directory );
// delete the explicitly requested files first
for( int j = 0; j < callback->files.Num() && !callback->cancelled; ++j )
{
idFile_SaveGame* file = callback->files[j];
idStr fullpath = folder;
fullpath.AppendPath( file->GetName() );
fileSystem->RemoveFile( fullpath );
}
int ret = ERROR_SUCCESS;
if( fileSystem->IsFolder( folder, "fs_savePath" ) == FOLDER_YES )
{
// get listing of all the files, but filter out below
idFileList* files = fileSystem->ListFilesTree( folder, "*.*" );
// look for the instance pattern
for( int i = 0; i < files->GetNumFiles() && !callback->cancelled; i++ )
{
idStr filename = files->GetFile( i );
filename.StripPath();
// If there are post/pre patterns to match, make sure we adhere to the patterns
if( callback->pattern.IsEmpty() || ( filename.IcmpPrefix( callback->pattern ) != 0 ) )
{
continue;
}
if( callback->postPattern.IsEmpty() || ( filename.Right( callback->postPattern.Length() ).IcmpPrefix( callback->postPattern ) != 0 ) )
{
continue;
}
fileSystem->RemoveFile( files->GetFile( i ) );
}
fileSystem->FreeFileList( files );
}
else
{
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
ret = -3;
}
if( data.saveLoadParms->cancelled )
{
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
}
return ret;
}
/*
========================
idSaveGameThread::DeleteAll
This deletes all savegame directories
========================
*/
int idSaveGameThread::DeleteAll()
{
idSaveLoadParms* callback = data.saveLoadParms;
idStr saveFolder = "savegame";
int ret = ERROR_SUCCESS;
if( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES )
{
idFileList* files = fileSystem->ListFilesTree( saveFolder, "/|*" );
// remove directories after files
for( int i = 0; i < files->GetNumFiles() && !callback->cancelled; i++ )
{
// contained files should always be first
if( fileSystem->IsFolder( files->GetFile( i ), "fs_savePath" ) == FOLDER_YES )
{
fileSystem->RemoveDir( files->GetFile( i ) );
}
else
{
fileSystem->RemoveFile( files->GetFile( i ) );
}
}
fileSystem->FreeFileList( files );
}
else
{
callback->errorCode = SAVEGAME_E_FOLDER_NOT_FOUND;
ret = -3;
}
if( data.saveLoadParms->cancelled )
{
data.saveLoadParms->errorCode = SAVEGAME_E_CANCELLED;
}
return ret;
}
/*
========================
idSaveGameThread::Run
========================
*/
int idSaveGameThread::Run()
{
int ret = ERROR_SUCCESS;
try
{
idLocalUserWin* user = GetLocalUserFromSaveParms( data );
if( user != NULL && !user->IsStorageDeviceAvailable() )
{
data.saveLoadParms->errorCode = SAVEGAME_E_UNABLE_TO_SELECT_STORAGE_DEVICE;
}
if( savegame_winInduceDelay.GetInteger() > 0 )
{
Sys_Sleep( savegame_winInduceDelay.GetInteger() );
}
if( data.saveLoadParms->mode & SAVEGAME_MBF_SAVE )
{
ret = Save();
}
else if( data.saveLoadParms->mode & SAVEGAME_MBF_LOAD )
{
ret = Load();
}
else if( data.saveLoadParms->mode & SAVEGAME_MBF_ENUMERATE )
{
ret = Enumerate();
}
else if( data.saveLoadParms->mode & SAVEGAME_MBF_DELETE_FOLDER )
{
ret = Delete();
}
else if( data.saveLoadParms->mode & SAVEGAME_MBF_DELETE_ALL_FOLDERS )
{
ret = DeleteAll();
}
else if( data.saveLoadParms->mode & SAVEGAME_MBF_DELETE_FILES )
{
ret = DeleteFiles();
}
else if( data.saveLoadParms->mode & SAVEGAME_MBF_ENUMERATE_FILES )
{
ret = EnumerateFiles();
}
// if something failed and no one set an error code, do it now.
if( ret != 0 && data.saveLoadParms->errorCode == SAVEGAME_E_NONE )
{
data.saveLoadParms->errorCode = SAVEGAME_E_UNKNOWN;
}
}
catch( ... )
{
// if anything horrible happens, leave it up to the savegame processors to handle in PostProcess().
data.saveLoadParms->errorCode = SAVEGAME_E_UNKNOWN;
}
// Make sure to cancel any save game file pipelines.
if( data.saveLoadParms->errorCode != SAVEGAME_E_NONE )
{
data.saveLoadParms->CancelSaveGameFilePipelines();
}
// Override error if cvar set
if( savegame_error.GetInteger() != 0 )
{
data.saveLoadParms->errorCode = ( saveGameError_t )savegame_error.GetInteger();
}
// Tell the waiting caller that we are done
data.saveLoadParms->callbackSignal.Raise();
return ret;
}
/*
========================
Sys_SaveGameCheck
========================
*/
void Sys_SaveGameCheck( bool& exists, bool& autosaveExists )
{
exists = false;
autosaveExists = false;
const idStr autosaveFolderStr = AddSaveFolderPrefix( SAVEGAME_AUTOSAVE_FOLDER, idSaveGameManager::PACKAGE_GAME );
const char* autosaveFolder = autosaveFolderStr.c_str();
const char* saveFolder = "savegame";
if( fileSystem->IsFolder( saveFolder, "fs_savePath" ) == FOLDER_YES )
{
idFileList* files = fileSystem->ListFiles( saveFolder, "/" );
const idStrList& fileList = files->GetList();
idLib::PrintfIf( saveGame_verbose.GetBool(), "found %d savegames\n", fileList.Num() );
for( int i = 0; i < fileList.Num(); i++ )
{
const char* directory = va( "%s/%s", saveFolder, fileList[i].c_str() );
if( fileSystem->IsFolder( directory, "fs_savePath" ) == FOLDER_YES )
{
exists = true;
idLib::PrintfIf( saveGame_verbose.GetBool(), "found savegame: %s\n", fileList[i].c_str() );
if( idStr::Icmp( fileList[i].c_str(), autosaveFolder ) == 0 )
{
autosaveExists = true;
break;
}
}
}
fileSystem->FreeFileList( files );
}
}

View file

@ -0,0 +1,751 @@
/*
================================================================================================
CONFIDENTIAL AND PROPRIETARY INFORMATION/NOT FOR DISCLOSURE WITHOUT WRITTEN PERMISSION
Copyright 2010 id Software LLC, a ZeniMax Media company. All Rights Reserved.
================================================================================================
*/
/*
================================================================================================
Contains the windows implementation of the network session
================================================================================================
*/
#pragma hdrstop
#include "../../idlib/precompiled.h"
#include "../../framework/Common_local.h"
#include "../sys_session_local.h"
#include "../sys_stats.h"
#include "../sys_savegame.h"
#include "../sys_lobby_backend_direct.h"
#include "../sys_voicechat.h"
#include "posix_achievements.h"
//#include "_local.h"
/*
========================
Global variables
========================
*/
extern idCVar net_port;
class idLobbyToSessionCBLocal;
/*
========================
idSessionLocalWin::idSessionLocalWin
========================
*/
class idSessionLocalWin : public idSessionLocal
{
friend class idLobbyToSessionCBLocal;
public:
idSessionLocalWin();
virtual ~idSessionLocalWin();
// idSessionLocal interface
virtual void Initialize();
virtual void Shutdown();
virtual void InitializeSoundRelatedSystems();
virtual void ShutdownSoundRelatedSystems();
virtual void PlatformPump();
virtual void InviteFriends();
virtual void InviteParty();
virtual void ShowPartySessions();
virtual void ShowSystemMarketplaceUI() const;
virtual void ListServers( const idCallback& callback );
virtual void CancelListServers();
virtual int NumServers() const;
virtual const serverInfo_t* ServerInfo( int i ) const;
virtual void ConnectToServer( int i );
virtual void ShowServerGamerCardUI( int i );
virtual void ShowLobbyUserGamerCardUI( lobbyUserID_t lobbyUserID );
virtual void ShowOnlineSignin() {}
virtual void UpdateRichPresence() {}
virtual void CheckVoicePrivileges() {}
virtual bool ProcessInputEvent( const sysEvent_t* ev );
// System UI
virtual bool IsSystemUIShowing() const;
virtual void SetSystemUIShowing( bool show );
// Invites
virtual void HandleBootableInvite( int64 lobbyId = 0 );
virtual void ClearBootableInvite();
virtual void ClearPendingInvite();
virtual bool HasPendingBootableInvite();
virtual void SetDiscSwapMPInvite( void* parm );
virtual void* GetDiscSwapMPInviteParms();
virtual void EnumerateDownloadableContent();
virtual void HandleServerQueryRequest( lobbyAddress_t& remoteAddr, idBitMsg& msg, int msgType );
virtual void HandleServerQueryAck( lobbyAddress_t& remoteAddr, idBitMsg& msg );
// Leaderboards
virtual void LeaderboardUpload( lobbyUserID_t lobbyUserID, const leaderboardDefinition_t* leaderboard, const column_t* stats, const idFile_Memory* attachment = NULL );
virtual void LeaderboardDownload( int sessionUserIndex, const leaderboardDefinition_t* leaderboard, int startingRank, int numRows, const idLeaderboardCallback& callback );
virtual void LeaderboardDownloadAttachment( int sessionUserIndex, const leaderboardDefinition_t* leaderboard, int64 attachmentID );
// Scoring (currently just for TrueSkill)
virtual void SetLobbyUserRelativeScore( lobbyUserID_t lobbyUserID, int relativeScore, int team ) {}
virtual void LeaderboardFlush();
virtual idNetSessionPort& GetPort( bool dedicated = false );
virtual idLobbyBackend* CreateLobbyBackend( const idMatchParameters& p, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType );
virtual idLobbyBackend* FindLobbyBackend( const idMatchParameters& p, int numPartyUsers, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType );
virtual idLobbyBackend* JoinFromConnectInfo( const lobbyConnectInfo_t& connectInfo , idLobbyBackend::lobbyBackendType_t lobbyType );
virtual void DestroyLobbyBackend( idLobbyBackend* lobbyBackend );
virtual void PumpLobbies();
virtual void JoinAfterSwap( void* joinID );
virtual bool GetLobbyAddressFromNetAddress( const netadr_t& netAddr, lobbyAddress_t& outAddr ) const;
virtual bool GetNetAddressFromLobbyAddress( const lobbyAddress_t& lobbyAddress, netadr_t& outNetAddr ) const;
public:
void Connect_f( const idCmdArgs& args );
private:
void EnsurePort();
idLobbyBackend* CreateLobbyInternal( idLobbyBackend::lobbyBackendType_t lobbyType );
idArray< idLobbyBackend*, 3 > lobbyBackends;
idNetSessionPort port;
bool canJoinLocalHost;
idLobbyToSessionCBLocal* lobbyToSessionCB;
};
idSessionLocalWin sessionLocalWin;
idSession* session = &sessionLocalWin;
/*
========================
idLobbyToSessionCBLocal
========================
*/
class idLobbyToSessionCBLocal : public idLobbyToSessionCB
{
public:
idLobbyToSessionCBLocal( idSessionLocalWin* sessionLocalWin_ ) : sessionLocalWin( sessionLocalWin_ ) { }
virtual bool CanJoinLocalHost() const
{
sessionLocalWin->EnsurePort();
return sessionLocalWin->canJoinLocalHost;
}
virtual class idLobbyBackend* GetLobbyBackend( idLobbyBackend::lobbyBackendType_t type ) const
{
return sessionLocalWin->lobbyBackends[ type ];
}
private:
idSessionLocalWin* sessionLocalWin;
};
idLobbyToSessionCBLocal lobbyToSessionCBLocal( &sessionLocalWin );
idLobbyToSessionCB* lobbyToSessionCB = &lobbyToSessionCBLocal;
class idVoiceChatMgrWin : public idVoiceChatMgr
{
public:
virtual bool GetLocalChatDataInternal( int talkerIndex, byte* data, int& dataSize )
{
return false;
}
virtual void SubmitIncomingChatDataInternal( int talkerIndex, const byte* data, int dataSize ) { }
virtual bool TalkerHasData( int talkerIndex )
{
return false;
}
virtual bool RegisterTalkerInternal( int index )
{
return true;
}
virtual void UnregisterTalkerInternal( int index ) { }
};
/*
========================
idSessionLocalWin::idSessionLocalWin
========================
*/
idSessionLocalWin::idSessionLocalWin()
{
signInManager = new( TAG_SYSTEM ) idSignInManagerWin;
saveGameManager = new( TAG_SAVEGAMES ) idSaveGameManager();
voiceChat = new( TAG_SYSTEM ) idVoiceChatMgrWin();
lobbyToSessionCB = new( TAG_SYSTEM ) idLobbyToSessionCBLocal( this );
canJoinLocalHost = false;
lobbyBackends.Zero();
}
/*
========================
idSessionLocalWin::idSessionLocalWin
========================
*/
idSessionLocalWin::~idSessionLocalWin()
{
delete voiceChat;
delete lobbyToSessionCB;
}
/*
========================
idSessionLocalWin::Initialize
========================
*/
void idSessionLocalWin::Initialize()
{
idSessionLocal::Initialize();
// The shipping path doesn't load title storage
// Instead, we inject values through code which is protected through steam DRM
titleStorageVars.Set( "MAX_PLAYERS_ALLOWED", "8" );
titleStorageLoaded = true;
// First-time check for downloadable content once game is launched
EnumerateDownloadableContent();
GetPartyLobby().Initialize( idLobby::TYPE_PARTY, sessionCallbacks );
GetGameLobby().Initialize( idLobby::TYPE_GAME, sessionCallbacks );
GetGameStateLobby().Initialize( idLobby::TYPE_GAME_STATE, sessionCallbacks );
achievementSystem = new( TAG_SYSTEM ) idAchievementSystemWin();
achievementSystem->Init();
}
/*
========================
idSessionLocalWin::Shutdown
========================
*/
void idSessionLocalWin::Shutdown()
{
NET_VERBOSE_PRINT( "NET: Shutdown\n" );
idSessionLocal::Shutdown();
MoveToMainMenu();
// Wait until we fully shutdown
while( localState != STATE_IDLE && localState != STATE_PRESS_START )
{
Pump();
}
if( achievementSystem != NULL )
{
achievementSystem->Shutdown();
delete achievementSystem;
achievementSystem = NULL;
}
}
/*
========================
idSessionLocalWin::InitializeSoundRelatedSystems
========================
*/
void idSessionLocalWin::InitializeSoundRelatedSystems()
{
if( voiceChat != NULL )
{
voiceChat->Init( NULL );
}
}
/*
========================
idSessionLocalWin::ShutdownSoundRelatedSystems
========================
*/
void idSessionLocalWin::ShutdownSoundRelatedSystems()
{
if( voiceChat != NULL )
{
voiceChat->Shutdown();
}
}
/*
========================
idSessionLocalWin::PlatformPump
========================
*/
void idSessionLocalWin::PlatformPump()
{
}
/*
========================
idSessionLocalWin::InviteFriends
========================
*/
void idSessionLocalWin::InviteFriends()
{
}
/*
========================
idSessionLocalWin::InviteParty
========================
*/
void idSessionLocalWin::InviteParty()
{
}
/*
========================
idSessionLocalWin::ShowPartySessions
========================
*/
void idSessionLocalWin::ShowPartySessions()
{
}
/*
========================
idSessionLocalWin::ShowSystemMarketplaceUI
========================
*/
void idSessionLocalWin::ShowSystemMarketplaceUI() const
{
}
/*
========================
idSessionLocalWin::ListServers
========================
*/
void idSessionLocalWin::ListServers( const idCallback& callback )
{
ListServersCommon();
}
/*
========================
idSessionLocalWin::CancelListServers
========================
*/
void idSessionLocalWin::CancelListServers()
{
}
/*
========================
idSessionLocalWin::NumServers
========================
*/
int idSessionLocalWin::NumServers() const
{
return 0;
}
/*
========================
idSessionLocalWin::ServerInfo
========================
*/
const serverInfo_t* idSessionLocalWin::ServerInfo( int i ) const
{
return NULL;
}
/*
========================
idSessionLocalWin::ConnectToServer
========================
*/
void idSessionLocalWin::ConnectToServer( int i )
{
}
/*
========================
idSessionLocalWin::Connect_f
========================
*/
void idSessionLocalWin::Connect_f( const idCmdArgs& args )
{
if( args.Argc() < 2 )
{
idLib::Printf( "Usage: Connect to IP. Use with net_port. \n" );
return;
}
Cancel();
if( signInManager->GetMasterLocalUser() == NULL )
{
signInManager->RegisterLocalUser( 0 );
}
lobbyConnectInfo_t connectInfo;
Sys_StringToNetAdr( args.Argv( 1 ), &connectInfo.netAddr, true );
connectInfo.netAddr.port = net_port.GetInteger();
ConnectAndMoveToLobby( GetPartyLobby(), connectInfo, false );
}
/*
========================
void Connect_f
========================
*/
CONSOLE_COMMAND( connect, "Connect to the specified IP", NULL )
{
sessionLocalWin.Connect_f( args );
}
/*
========================
idSessionLocalWin::ShowServerGamerCardUI
========================
*/
void idSessionLocalWin::ShowServerGamerCardUI( int i )
{
}
/*
========================
idSessionLocalWin::ShowLobbyUserGamerCardUI(
========================
*/
void idSessionLocalWin::ShowLobbyUserGamerCardUI( lobbyUserID_t lobbyUserID )
{
}
/*
========================
idSessionLocalWin::ProcessInputEvent
========================
*/
bool idSessionLocalWin::ProcessInputEvent( const sysEvent_t* ev )
{
if( GetSignInManager().ProcessInputEvent( ev ) )
{
return true;
}
return false;
}
/*
========================
idSessionLocalWin::IsSystemUIShowing
========================
*/
bool idSessionLocalWin::IsSystemUIShowing() const
{
// RB: TODO track SDL_ACTIVEENT
return isSysUIShowing;
//return !win32.activeApp || isSysUIShowing; // If the user alt+tabs away, treat it the same as bringing up the steam overlay
}
/*
========================
idSessionLocalWin::SetSystemUIShowing
========================
*/
void idSessionLocalWin::SetSystemUIShowing( bool show )
{
isSysUIShowing = show;
}
/*
========================
idSessionLocalWin::HandleServerQueryRequest
========================
*/
void idSessionLocalWin::HandleServerQueryRequest( lobbyAddress_t& remoteAddr, idBitMsg& msg, int msgType )
{
NET_VERBOSE_PRINT( "HandleServerQueryRequest from %s\n", remoteAddr.ToString() );
}
/*
========================
idSessionLocalWin::HandleServerQueryAck
========================
*/
void idSessionLocalWin::HandleServerQueryAck( lobbyAddress_t& remoteAddr, idBitMsg& msg )
{
NET_VERBOSE_PRINT( "HandleServerQueryAck from %s\n", remoteAddr.ToString() );
}
/*
========================
idSessionLocalWin::ClearBootableInvite
========================
*/
void idSessionLocalWin::ClearBootableInvite()
{
}
/*
========================
idSessionLocalWin::ClearPendingInvite
========================
*/
void idSessionLocalWin::ClearPendingInvite()
{
}
/*
========================
idSessionLocalWin::HandleBootableInvite
========================
*/
void idSessionLocalWin::HandleBootableInvite( int64 lobbyId )
{
}
/*
========================
idSessionLocalWin::HasPendingBootableInvite
========================
*/
bool idSessionLocalWin::HasPendingBootableInvite()
{
return false;
}
/*
========================
idSessionLocal::SetDiscSwapMPInvite
========================
*/
void idSessionLocalWin::SetDiscSwapMPInvite( void* parm )
{
}
/*
========================
idSessionLocal::GetDiscSwapMPInviteParms
========================
*/
void* idSessionLocalWin::GetDiscSwapMPInviteParms()
{
return NULL;
}
/*
========================
idSessionLocalWin::EnumerateDownloadableContent
========================
*/
void idSessionLocalWin::EnumerateDownloadableContent()
{
}
/*
========================
idSessionLocalWin::LeaderboardUpload
========================
*/
void idSessionLocalWin::LeaderboardUpload( lobbyUserID_t lobbyUserID, const leaderboardDefinition_t* leaderboard, const column_t* stats, const idFile_Memory* attachment )
{
}
/*
========================
idSessionLocalWin::LeaderboardFlush
========================
*/
void idSessionLocalWin::LeaderboardFlush()
{
}
/*
========================
idSessionLocalWin::LeaderboardDownload
========================
*/
void idSessionLocalWin::LeaderboardDownload( int sessionUserIndex, const leaderboardDefinition_t* leaderboard, int startingRank, int numRows, const idLeaderboardCallback& callback )
{
}
/*
========================
idSessionLocalWin::LeaderboardDownloadAttachment
========================
*/
void idSessionLocalWin::LeaderboardDownloadAttachment( int sessionUserIndex, const leaderboardDefinition_t* leaderboard, int64 attachmentID )
{
}
/*
========================
idSessionLocalWin::EnsurePort
========================
*/
void idSessionLocalWin::EnsurePort()
{
// Init the port using reqular windows sockets
if( port.IsOpen() )
{
return; // Already initialized
}
if( port.InitPort( net_port.GetInteger(), false ) )
{
canJoinLocalHost = false;
}
else
{
// Assume this is another instantiation on the same machine, and just init using any available port
port.InitPort( PORT_ANY, false );
canJoinLocalHost = true;
}
}
/*
========================
idSessionLocalWin::GetPort
========================
*/
idNetSessionPort& idSessionLocalWin::GetPort( bool dedicated )
{
EnsurePort();
return port;
}
/*
========================
idSessionLocalWin::CreateLobbyBackend
========================
*/
idLobbyBackend* idSessionLocalWin::CreateLobbyBackend( const idMatchParameters& p, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType )
{
idLobbyBackend* lobbyBackend = CreateLobbyInternal( lobbyType );
lobbyBackend->StartHosting( p, skillLevel, lobbyType );
return lobbyBackend;
}
/*
========================
idSessionLocalWin::FindLobbyBackend
========================
*/
idLobbyBackend* idSessionLocalWin::FindLobbyBackend( const idMatchParameters& p, int numPartyUsers, float skillLevel, idLobbyBackend::lobbyBackendType_t lobbyType )
{
idLobbyBackend* lobbyBackend = CreateLobbyInternal( lobbyType );
lobbyBackend->StartFinding( p, numPartyUsers, skillLevel );
return lobbyBackend;
}
/*
========================
idSessionLocalWin::JoinFromConnectInfo
========================
*/
idLobbyBackend* idSessionLocalWin::JoinFromConnectInfo( const lobbyConnectInfo_t& connectInfo, idLobbyBackend::lobbyBackendType_t lobbyType )
{
idLobbyBackend* lobbyBackend = CreateLobbyInternal( lobbyType );
lobbyBackend->JoinFromConnectInfo( connectInfo );
return lobbyBackend;
}
/*
========================
idSessionLocalWin::DestroyLobbyBackend
========================
*/
void idSessionLocalWin::DestroyLobbyBackend( idLobbyBackend* lobbyBackend )
{
assert( lobbyBackend != NULL );
assert( lobbyBackends[lobbyBackend->GetLobbyType()] == lobbyBackend );
lobbyBackends[lobbyBackend->GetLobbyType()] = NULL;
lobbyBackend->Shutdown();
delete lobbyBackend;
}
/*
========================
idSessionLocalWin::PumpLobbies
========================
*/
void idSessionLocalWin::PumpLobbies()
{
assert( lobbyBackends[idLobbyBackend::TYPE_PARTY] == NULL || lobbyBackends[idLobbyBackend::TYPE_PARTY]->GetLobbyType() == idLobbyBackend::TYPE_PARTY );
assert( lobbyBackends[idLobbyBackend::TYPE_GAME] == NULL || lobbyBackends[idLobbyBackend::TYPE_GAME]->GetLobbyType() == idLobbyBackend::TYPE_GAME );
assert( lobbyBackends[idLobbyBackend::TYPE_GAME_STATE] == NULL || lobbyBackends[idLobbyBackend::TYPE_GAME_STATE]->GetLobbyType() == idLobbyBackend::TYPE_GAME_STATE );
// Pump lobbyBackends
for( int i = 0; i < lobbyBackends.Num(); i++ )
{
if( lobbyBackends[i] != NULL )
{
lobbyBackends[i]->Pump();
}
}
}
/*
========================
idSessionLocalWin::CreateLobbyInternal
========================
*/
idLobbyBackend* idSessionLocalWin::CreateLobbyInternal( idLobbyBackend::lobbyBackendType_t lobbyType )
{
EnsurePort();
idLobbyBackend* lobbyBackend = new( TAG_NETWORKING ) idLobbyBackendDirect();
lobbyBackend->SetLobbyType( lobbyType );
assert( lobbyBackends[lobbyType] == NULL );
lobbyBackends[lobbyType] = lobbyBackend;
return lobbyBackend;
}
/*
========================
idSessionLocalWin::JoinAfterSwap
========================
*/
void idSessionLocalWin::JoinAfterSwap( void* joinID )
{
}
/*
========================
idSessionLocalWin::GetLobbyAddressFromNetAddress
========================
*/
bool idSessionLocalWin::GetLobbyAddressFromNetAddress( const netadr_t& netAddr, lobbyAddress_t& outAddr ) const
{
return false;
}
/*
========================
idSessionLocalWin::GetNetAddressFromLobbyAddress
========================
*/
bool idSessionLocalWin::GetNetAddressFromLobbyAddress( const lobbyAddress_t& lobbyAddress, netadr_t& outNetAddr ) const
{
return false;
}

View file

@ -112,10 +112,6 @@ static void sig_handler( int signum, siginfo_t* info, void* context )
// NOTE: see sigaction man page, could verbose the whole siginfo_t and print human readable si_code // NOTE: see sigaction man page, could verbose the whole siginfo_t and print human readable si_code
Sys_Printf( "signal caught: %s\nsi_code %d\n", strsignal( signum ), info->si_code ); Sys_Printf( "signal caught: %s\nsi_code %d\n", strsignal( signum ), info->si_code );
#ifndef ID_BT_STUB
Sys_Printf( "callstack:\n%s", Sys_GetCallStackCurStr( 30 ) );
#endif
if( fatalError[ 0 ] ) if( fatalError[ 0 ] )
{ {
Sys_Printf( "Was in fatal error shutdown: %s\n", fatalError ); Sys_Printf( "Was in fatal error shutdown: %s\n", fatalError );

View file

@ -0,0 +1,161 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma hdrstop
#include "../../idlib/precompiled.h"
#include "../../framework/PlayerProfile.h"
#include "../sys_session_local.h"
#include "posix_signin.h"
#include <unistd.h>
#ifdef _DEBUG
idCVar win_userPersistent( "win_userPersistent", "1", CVAR_BOOL, "debugging cvar for profile persistence status" );
idCVar win_userOnline( "win_userOnline", "1", CVAR_BOOL, "debugging cvar for profile online status" );
idCVar win_isInParty( "win_isInParty", "0", CVAR_BOOL, "debugging cvar for platform party status" );
idCVar win_partyCount( "win_partyCount", "0", CVAR_INTEGER, "debugginc var for platform party count" );
#endif
/*
========================
idSignInManagerWin::Shutdown
========================
*/
void idSignInManagerWin::Shutdown()
{
}
/*
========================
idSignInManagerWin::Pump
========================
*/
void idSignInManagerWin::Pump()
{
// If we have more users than we need, then set to the lower amount
// (don't remove the master user though)
if( localUsers.Num() > 1 && localUsers.Num() > maxDesiredLocalUsers )
{
localUsers.SetNum( maxDesiredLocalUsers );
}
#ifndef ID_RETAIL
// If we don't have enough, then make sure we do
// NOTE - We always want at least one user on windows for now,
// and this master user will always use controller 0
while( localUsers.Num() < minDesiredLocalUsers )
{
RegisterLocalUser( localUsers.Num() );
}
#endif
// See if we need to save settings on any of the profiles
for( int i = 0; i < localUsers.Num(); i++ )
{
localUsers[i].Pump();
}
}
/*
========================
idSignInManagerWin::RemoveLocalUserByIndex
========================
*/
void idSignInManagerWin::RemoveLocalUserByIndex( int index )
{
session->OnLocalUserSignout( &localUsers[index] );
localUsers.RemoveIndex( index );
}
/*
========================
idSignInManagerWin::RegisterLocalUser
========================
*/
void idSignInManagerWin::RegisterLocalUser( int inputDevice )
{
if( GetLocalUserByInputDevice( inputDevice ) != NULL )
{
return;
}
static char machineName[128];
gethostname( machineName, sizeof( machineName ) );
const char* nameSource = machineName;
idStr name( nameSource );
int nameLength = name.Length();
if( idStr::IsValidUTF8( nameSource, nameLength ) )
{
int nameIndex = 0;
int numChars = 0;
name.Empty();
while( nameIndex < nameLength && numChars++ < idLocalUserWin::MAX_GAMERTAG_CHARS )
{
uint32 c = idStr::UTF8Char( nameSource, nameIndex );
name.AppendUTF8Char( c );
}
}
idLocalUserWin& localUser = *localUsers.Alloc();
localUser.Init( inputDevice, name.c_str(), localUsers.Num() );
localUser.SetLocalUserHandle( GetUniqueLocalUserHandle( localUser.GetGamerTag() ) );
session->OnLocalUserSignin( &localUser );
}
/*
========================
idSignInManagerWin::CreateNewUser
========================
*/
bool idSignInManagerWin::CreateNewUser( winUserState_t& state )
{
//idScopedGlobalHeap everythingHereGoesInTheGlobalHeap; // users obviously persist across maps
RemoveAllLocalUsers();
RegisterLocalUser( state.inputDevice );
if( localUsers.Num() > 0 )
{
if( !localUsers[0].VerifyUserState( state ) )
{
RemoveAllLocalUsers();
}
}
return true;
}
CONSOLE_COMMAND( testRemoveAllLocalUsers, "Forces removal of local users - mainly for PC testing", NULL )
{
session->GetSignInManager().RemoveAllLocalUsers();
}

View file

@ -0,0 +1,72 @@
/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __POSIX_SIGNIN_H__
#define __POSIX_SIGNIN_H__
#include "posix_localuser.h"
/*
================================================
idSignInManagerWin
================================================
*/
class idSignInManagerWin : public idSignInManagerBase
{
public:
idSignInManagerWin() : dlcVersionChecked( false ) {}
virtual ~idSignInManagerWin() {}
//==========================================================================================
// idSignInManagerBase interface
//==========================================================================================
virtual void Pump();
virtual void Shutdown();
virtual int GetNumLocalUsers() const
{
return localUsers.Num();
}
virtual idLocalUser* GetLocalUserByIndex( int index )
{
return &localUsers[index];
}
virtual const idLocalUser* GetLocalUserByIndex( int index ) const
{
return &localUsers[index];
}
virtual void RemoveLocalUserByIndex( int index );
virtual void RegisterLocalUser( int inputDevice ); // Register a local user to the passed in controller
bool CreateNewUser( winUserState_t& state );
private:
idStaticList< idLocalUserWin, MAX_INPUT_DEVICES > localUsers;
bool dlcVersionChecked;
};
#endif

View file

@ -49,6 +49,7 @@ If you have questions concerning this license or the applicable additional terms
Sys_GetClockTicks Sys_GetClockTicks
================ ================
*/ */
#if defined(_WIN32)
double Sys_GetClockTicks() double Sys_GetClockTicks()
{ {
// RB begin // RB begin
@ -85,12 +86,14 @@ double Sys_GetClockTicks()
#endif #endif
// RB end // RB end
} }
#endif
/* /*
================ ================
Sys_ClockTicksPerSecond Sys_ClockTicksPerSecond
================ ================
*/ */
#if defined(_WIN32)
double Sys_ClockTicksPerSecond() double Sys_ClockTicksPerSecond()
{ {
static double ticks = 0; static double ticks = 0;
@ -136,6 +139,7 @@ double Sys_ClockTicksPerSecond()
#endif #endif
return ticks; return ticks;
} }
#endif
/* /*
@ -157,12 +161,14 @@ numPhysicalCPUCores - the total number of cores per package
numCPUPackages - the total number of packages (physical processors) numCPUPackages - the total number of packages (physical processors)
======================== ========================
*/ */
#if defined(_WIN32)
void Sys_CPUCount( int& numLogicalCPUCores, int& numPhysicalCPUCores, int& numCPUPackages ) void Sys_CPUCount( int& numLogicalCPUCores, int& numPhysicalCPUCores, int& numCPUPackages )
{ {
numPhysicalCPUCores = 1; numPhysicalCPUCores = 1;
numLogicalCPUCores = SDL_GetCPUCount(); numLogicalCPUCores = SDL_GetCPUCount();
numCPUPackages = 1; numCPUPackages = 1;
} }
#endif
/* /*
================ ================
@ -201,10 +207,12 @@ cpuid_t Sys_GetCPUId()
} }
// check for Streaming SIMD Extensions 3 aka Prescott's New Instructions // check for Streaming SIMD Extensions 3 aka Prescott's New Instructions
#if 0 //SDL_VERSION_ATLEAST(2,0,0)
if( SDL_HasSSE3() ) if( SDL_HasSSE3() )
{ {
flags |= CPUID_SSE3; flags |= CPUID_SSE3;
} }
#endif
/* /*
// check for Hyper-Threading Technology // check for Hyper-Threading Technology

View file

@ -3,6 +3,8 @@
Doom 3 GPL Source Code Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 dhewg (dhewm3)
Copyright (C) 2012 Robert Beckebans
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
@ -28,15 +30,10 @@ If you have questions concerning this license or the applicable additional terms
#include <SDL.h> #include <SDL.h>
#include "sys/platform.h" #include "../../idlib/precompiled.h"
#include "idlib/containers/List.h"
#include "idlib/Heap.h"
#include "framework/Common.h"
#include "framework/KeyInput.h"
#include "renderer/RenderSystem.h"
#include "renderer/tr_local.h" #include "renderer/tr_local.h"
#include "sdl_local.h"
#include "sys/sys_public.h" #include "../posix/posix_public.h"
#if !SDL_VERSION_ATLEAST(2, 0, 0) #if !SDL_VERSION_ATLEAST(2, 0, 0)
#define SDL_Keycode SDLKey #define SDL_Keycode SDLKey
@ -115,8 +112,8 @@ static byte mapkey( SDL_Keycode key )
switch( key ) switch( key )
{ {
case SDLK_APPLICATION: //case SDLK_APPLICATION:
return K_COMMAND; // return K_COMMAND;
case SDLK_CAPSLOCK: case SDLK_CAPSLOCK:
return K_CAPSLOCK; return K_CAPSLOCK;
case SDLK_SCROLLLOCK: case SDLK_SCROLLLOCK:
@ -137,18 +134,21 @@ static byte mapkey( SDL_Keycode key )
return K_LWIN; return K_LWIN;
case SDLK_RGUI: case SDLK_RGUI:
return K_RWIN; return K_RWIN;
case SDLK_MENU: //case SDLK_MENU:
return K_MENU; // return K_MENU;
case SDLK_LALT: case SDLK_LALT:
return K_LALT;
case SDLK_RALT: case SDLK_RALT:
return K_ALT; return K_RALT;
case SDLK_RCTRL: case SDLK_RCTRL:
return K_RCTRL;
case SDLK_LCTRL: case SDLK_LCTRL:
return K_CTRL; return K_LCTRL;
case SDLK_RSHIFT: case SDLK_RSHIFT:
return K_RSHIFT;
case SDLK_LSHIFT: case SDLK_LSHIFT:
return K_SHIFT; return K_LSHIFT;
case SDLK_INSERT: case SDLK_INSERT:
return K_INS; return K_INS;
case SDLK_DELETE: case SDLK_DELETE:
@ -195,29 +195,29 @@ static byte mapkey( SDL_Keycode key )
return K_F15; return K_F15;
case SDLK_KP_7: case SDLK_KP_7:
return K_KP_HOME; return K_KP_7;
case SDLK_KP_8: case SDLK_KP_8:
return K_KP_UPARROW; return K_KP_8;
case SDLK_KP_9: case SDLK_KP_9:
return K_KP_PGUP; return K_KP_9;
case SDLK_KP_4: case SDLK_KP_4:
return K_KP_LEFTARROW; return K_KP_4;
case SDLK_KP_5: case SDLK_KP_5:
return K_KP_5; return K_KP_5;
case SDLK_KP_6: case SDLK_KP_6:
return K_KP_RIGHTARROW; return K_KP_6;
case SDLK_KP_1: case SDLK_KP_1:
return K_KP_END; return K_KP_1;
case SDLK_KP_2: case SDLK_KP_2:
return K_KP_DOWNARROW; return K_KP_2;
case SDLK_KP_3: case SDLK_KP_3:
return K_KP_PGDN; return K_KP_3;
case SDLK_KP_ENTER: case SDLK_KP_ENTER:
return K_KP_ENTER; return K_KP_ENTER;
case SDLK_KP_0: case SDLK_KP_0:
return K_KP_INS; return K_KP_0;
case SDLK_KP_PERIOD: case SDLK_KP_PERIOD:
return K_KP_DEL; return K_KP_DOT;
case SDLK_KP_DIVIDE: case SDLK_KP_DIVIDE:
return K_KP_SLASH; return K_KP_SLASH;
// K_SUPERSCRIPT_TWO; // K_SUPERSCRIPT_TWO;
@ -227,7 +227,7 @@ static byte mapkey( SDL_Keycode key )
case SDLK_KP_PLUS: case SDLK_KP_PLUS:
return K_KP_PLUS; return K_KP_PLUS;
case SDLK_NUMLOCKCLEAR: case SDLK_NUMLOCKCLEAR:
return K_KP_NUMLOCK; return K_NUMLOCK;
case SDLK_KP_MULTIPLY: case SDLK_KP_MULTIPLY:
return K_KP_STAR; return K_KP_STAR;
case SDLK_KP_EQUALS: case SDLK_KP_EQUALS:
@ -259,9 +259,9 @@ static byte mapkey( SDL_Keycode key )
// K_AUX16; // K_AUX16;
case SDLK_PRINTSCREEN: case SDLK_PRINTSCREEN:
return K_PRINT_SCR; return K_PRINTSCREEN;
case SDLK_MODE: case SDLK_MODE:
return K_RIGHT_ALT; return K_RALT;
} }
return 0; return 0;
@ -273,7 +273,7 @@ static void PushConsoleEvent( const char* s )
size_t len; size_t len;
len = strlen( s ) + 1; len = strlen( s ) + 1;
b = ( char* )Mem_Alloc( len ); b = ( char* )Mem_Alloc( len, TAG_EVENTS );
strcpy( b, s ); strcpy( b, s );
SDL_Event event; SDL_Event event;
@ -673,8 +673,8 @@ void Sys_ClearEvents()
while( SDL_PollEvent( &ev ) ) while( SDL_PollEvent( &ev ) )
; ;
kbd_polls.SetNum( 0, false ); kbd_polls.SetNum( 0 );
mouse_polls.SetNum( 0, false ); mouse_polls.SetNum( 0 );
} }
/* /*
@ -684,7 +684,7 @@ Sys_GenerateEvents
*/ */
void Sys_GenerateEvents() void Sys_GenerateEvents()
{ {
char* s = Sys_ConsoleInput(); char* s = Posix_ConsoleInput();
if( s ) if( s )
PushConsoleEvent( s ); PushConsoleEvent( s );
@ -724,7 +724,7 @@ Sys_EndKeyboardInputEvents
*/ */
void Sys_EndKeyboardInputEvents() void Sys_EndKeyboardInputEvents()
{ {
kbd_polls.SetNum( 0, false ); kbd_polls.SetNum( 0 );
} }
/* /*
@ -732,32 +732,55 @@ void Sys_EndKeyboardInputEvents()
Sys_PollMouseInputEvents Sys_PollMouseInputEvents
================ ================
*/ */
int Sys_PollMouseInputEvents() int Sys_PollMouseInputEvents( int mouseEvents[MAX_MOUSE_EVENTS][2] )
{ {
return mouse_polls.Num(); int numEvents = mouse_polls.Num();
}
if( numEvents > MAX_MOUSE_EVENTS )
/* {
================ numEvents = MAX_MOUSE_EVENTS;
Sys_ReturnMouseInputEvent }
================
*/ for( int i = 0; i < numEvents; i++ )
int Sys_ReturnMouseInputEvent( const int n, int& action, int& value ) {
{ const mouse_poll_t& mp = mouse_polls[i];
if( n >= mouse_polls.Num() )
return 0;
action = mouse_polls[n].action; mouseEvents[i][0] = mp.action;
value = mouse_polls[n].value; mouseEvents[i][1] = mp.value;
return 1; }
mouse_polls.SetNum( 0 );
return numEvents;
} }
/*
================ //=====================================================================================
Sys_EndMouseInputEvents // Joystick Input Handling
================ //=====================================================================================
*/
void Sys_EndMouseInputEvents() void Sys_SetRumble( int device, int low, int hi )
{ {
mouse_polls.SetNum( 0, false ); // TODO;
} }
int Sys_PollJoystickInputEvents( int deviceNum )
{
// TODO;
return 0;
}
int Sys_ReturnJoystickInputEvent( const int n, int& action, int& value )
{
// TODO;
return 0;
}
void Sys_EndJoystickInputEvents()
{
}

View file

@ -3,6 +3,8 @@
Doom 3 GPL Source Code Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 dhewg (dhewm3)
Copyright (C) 2012 Robert Beckebans
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
@ -29,10 +31,10 @@ If you have questions concerning this license or the applicable additional terms
#include <SDL.h> #include <SDL.h>
#include <SDL_syswm.h> #include <SDL_syswm.h>
#include "sys/platform.h" #include "../../idlib/precompiled.h"
#include "framework/Licensee.h"
#include "renderer/tr_local.h" #include "renderer/tr_local.h"
#include "sdl_local.h"
idCVar in_nograb( "in_nograb", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "prevents input grabbing" ); idCVar in_nograb( "in_nograb", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "prevents input grabbing" );
idCVar r_waylandcompat( "r_waylandcompat", "0", CVAR_SYSTEM | CVAR_NOCHEAT | CVAR_ARCHIVE, "wayland compatible framebuffer" ); idCVar r_waylandcompat( "r_waylandcompat", "0", CVAR_SYSTEM | CVAR_NOCHEAT | CVAR_ARCHIVE, "wayland compatible framebuffer" );
@ -165,7 +167,9 @@ bool GLimp_Init( glimpParms_t parms )
if( SDL_GL_SetSwapInterval( r_swapInterval.GetInteger() ) < 0 ) if( SDL_GL_SetSwapInterval( r_swapInterval.GetInteger() ) < 0 )
common->Warning( "SDL_GL_SWAP_CONTROL not supported" ); common->Warning( "SDL_GL_SWAP_CONTROL not supported" );
SDL_GetWindowSize( window, &glConfig.vidWidth, &glConfig.vidHeight ); // RB begin
SDL_GetWindowSize( window, &glConfig.nativeScreenWidth, &glConfig.nativeScreenHeight );
// RB end
glConfig.isFullscreen = ( SDL_GetWindowFlags( window ) & SDL_WINDOW_FULLSCREEN ) == SDL_WINDOW_FULLSCREEN; glConfig.isFullscreen = ( SDL_GetWindowFlags( window ) & SDL_WINDOW_FULLSCREEN ) == SDL_WINDOW_FULLSCREEN;
#else #else
@ -182,8 +186,8 @@ bool GLimp_Init( glimpParms_t parms )
continue; continue;
} }
glConfig.vidWidth = window->w; glConfig.nativeScreenWidth = window->w;
glConfig.vidHeight = window->h; glConfig.nativeScreenHeight = window->h;
glConfig.isFullscreen = ( window->flags & SDL_FULLSCREEN ) == SDL_FULLSCREEN; glConfig.isFullscreen = ( window->flags & SDL_FULLSCREEN ) == SDL_FULLSCREEN;
#endif #endif
@ -197,6 +201,11 @@ bool GLimp_Init( glimpParms_t parms )
glConfig.displayFrequency = 0; glConfig.displayFrequency = 0;
// RB begin
glConfig.isStereoPixelFormat = parms.stereo;
glConfig.multisamples = parms.multiSamples;
// RB end
break; break;
} }
@ -279,26 +288,6 @@ void GLimp_SetGamma( unsigned short red[256], unsigned short green[256], unsigne
common->Warning( "Couldn't set gamma ramp: %s", SDL_GetError() ); common->Warning( "Couldn't set gamma ramp: %s", SDL_GetError() );
} }
/*
=================
GLimp_ActivateContext
=================
*/
void GLimp_ActivateContext()
{
common->DPrintf( "TODO: GLimp_ActivateContext\n" );
}
/*
=================
GLimp_DeactivateContext
=================
*/
void GLimp_DeactivateContext()
{
common->DPrintf( "TODO: GLimp_DeactivateContext\n" );
}
/* /*
=================== ===================
GLimp_ExtensionPointer GLimp_ExtensionPointer
@ -339,3 +328,77 @@ void GLimp_GrabInput( int flags )
SDL_WM_GrabInput( grab ? SDL_GRAB_ON : SDL_GRAB_OFF ); SDL_WM_GrabInput( grab ? SDL_GRAB_ON : SDL_GRAB_OFF );
#endif #endif
} }
/*
====================
DumpAllDisplayDevices
====================
*/
void DumpAllDisplayDevices()
{
common->DPrintf( "TODO: DumpAllDisplayDevices\n" );
}
class idSort_VidMode : public idSort_Quick< vidMode_t, idSort_VidMode >
{
public:
int Compare( const vidMode_t& a, const vidMode_t& b ) const
{
int wd = a.width - b.width;
int hd = a.height - b.height;
int fd = a.displayHz - b.displayHz;
return ( hd != 0 ) ? hd : ( wd != 0 ) ? wd : fd;
}
};
/*
====================
R_GetModeListForDisplay
====================
*/
bool R_GetModeListForDisplay( const int requestedDisplayNum, idList<vidMode_t>& modeList )
{
modeList.Clear();
bool verbose = false;
const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo();
SDL_Rect** modes = SDL_ListModes( videoInfo->vfmt, SDL_OPENGL | SDL_FULLSCREEN );
if( !modes )
{
common->Warning( "Can't get list of available modes\n" );
return false;
}
if( modes == ( SDL_Rect** ) - 1 )
{
common->Printf( "Display supports any resolution\n" );
return false; // can set any resolution
}
int numModes;
for( numModes = 0; modes[numModes]; numModes++ );
if( numModes > 1 )
{
for( int i = 0; i < numModes; i++ )
{
vidMode_t mode;
mode.width = modes[i]->w;
mode.height = modes[i]->h;
mode.displayHz = 60; // FIXME;
modeList.AddUnique( mode );
}
// sort with lowest resolution first
modeList.SortWithTemplate( idSort_VidMode() );
return true;
}
return false;
}

2025
neo/sys/sdl/sdl_qgl.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -519,9 +520,12 @@ bool Sys_UnlockMemory( void* ptr, int bytes );
void Sys_SetPhysicalWorkMemory( int minBytes, int maxBytes ); void Sys_SetPhysicalWorkMemory( int minBytes, int maxBytes );
// DLL loading, the path should be a fully qualified OS path to the DLL file to be loaded // DLL loading, the path should be a fully qualified OS path to the DLL file to be loaded
int Sys_DLL_Load( const char* dllName );
void* Sys_DLL_GetProcAddress( int dllHandle, const char* procName ); // RB: 64 bit fixes, changed int to intptr_t
void Sys_DLL_Unload( int dllHandle ); intptr_t Sys_DLL_Load( const char* dllName );
void* Sys_DLL_GetProcAddress( intptr_t dllHandle, const char* procName );
void Sys_DLL_Unload( intptr_t dllHandle );
// RB end
// event generation // event generation
void Sys_GenerateEvents(); void Sys_GenerateEvents();

View file

@ -30,8 +30,15 @@ If you have questions concerning this license or the applicable additional terms
#undef private #undef private
#undef protected #undef protected
// RB begin
#if defined(_WIN32)
#include "win32/win_achievements.h" #include "win32/win_achievements.h"
#include "win32/win_signin.h" #include "win32/win_signin.h"
#else
#include "posix/posix_achievements.h"
#include "posix/posix_signin.h"
#endif
// RB end
#include "sys_lobby_backend.h" #include "sys_lobby_backend.h"
#include "sys_lobby.h" #include "sys_lobby.h"