diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | src/client/snd_openal.c | 405 | ||||
-rwxr-xr-x | src/libs/macosx/libSDL-1.2.0.dylib | bin | 4474044 -> 4436304 bytes | |||
-rw-r--r-- | src/qcommon/vm_x86_64.c | 254 | ||||
-rw-r--r-- | src/sys/sys_win32.c | 3 |
5 files changed, 283 insertions, 380 deletions
@@ -269,7 +269,6 @@ ifeq ($(PLATFORM),linux) OPTIMIZE = -O3 -fomit-frame-pointer -ffast-math -funroll-loops \ -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ -fstrength-reduce - # experimental x86_64 jit compiler! you need GNU as HAVE_VM_COMPILED = true else ifeq ($(ARCH),x86) diff --git a/src/client/snd_openal.c b/src/client/snd_openal.c index 7ba9c9a3..96068075 100644 --- a/src/client/snd_openal.c +++ b/src/client/snd_openal.c @@ -111,8 +111,10 @@ static void S_AL_ClearError( qboolean quiet ) if( quiet ) return; if(error != AL_NO_ERROR) + { Com_Printf(S_COLOR_YELLOW "WARNING: unhandled AL error: %s\n", S_AL_ErrorMsg(error)); + } } @@ -527,6 +529,7 @@ typedef struct src_s float lastTimePos; // On stopped loops, the last position in the buffer int lastSampleTime; // Time when this was stopped + vec3_t loopSpeakerPos; // Origin of the loop speaker qboolean local; // Is this local (relative to the cam) } src_t; @@ -538,6 +541,7 @@ typedef struct src_s #endif static src_t srcList[MAX_SRC]; static int srcCount = 0; +static int srcActiveCnt = 0; static qboolean alSourcesInitialised = qfalse; static vec3_t lastListenerOrigin = { 0.0f, 0.0f, 0.0f }; @@ -605,8 +609,6 @@ static void S_AL_ScaleGain(src_t *chksrc, vec3_t origin) if(chksrc->scaleGain != scaleFactor); { chksrc->scaleGain = scaleFactor; - // if(scaleFactor > 0.0f) - // Com_Printf("%f\n", scaleFactor); qalSourcef(chksrc->alSource, AL_GAIN, chksrc->scaleGain); } } @@ -662,6 +664,7 @@ qboolean S_AL_SrcInit( void ) // Clear the sources data structure memset(srcList, 0, sizeof(srcList)); srcCount = 0; + srcActiveCnt = 0; // Cap s_alSources to MAX_SRC limit = s_alSources->integer; @@ -695,6 +698,7 @@ static void S_AL_SrcShutdown( void ) { int i; + src_t *curSource; if(!alSourcesInitialised) return; @@ -702,9 +706,14 @@ void S_AL_SrcShutdown( void ) // Destroy all the sources for(i = 0; i < srcCount; i++) { - if(srcList[i].isLocked) + curSource = &srcList[i]; + + if(curSource->isLocked) Com_DPrintf( S_COLOR_YELLOW "WARNING: Source %d is locked\n", i); + if(curSource->entity > 0) + entityList[curSource->entity].srcAllocated = qfalse; + qalSourceStop(srcList[i].alSource); qalDeleteSources(1, &srcList[i].alSource); } @@ -737,7 +746,6 @@ static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t prio curSource->priority = priority; curSource->entity = entity; curSource->channel = channel; - curSource->isActive = qtrue; curSource->isPlaying = qfalse; curSource->isLocked = qfalse; curSource->isLooping = qfalse; @@ -774,6 +782,36 @@ Remove given source as loop master if it is the master and hand off master statu ================= */ +static void S_AL_SaveLoopPos(src_t *dest, ALuint alSource) +{ + int error; + + S_AL_ClearError(qfalse); + + qalGetSourcef(alSource, AL_SEC_OFFSET, &dest->lastTimePos); + if((error = qalGetError()) != AL_NO_ERROR) + { + // Old OpenAL implementations don't support AL_SEC_OFFSET + + if(error != AL_INVALID_ENUM) + { + Com_Printf(S_COLOR_YELLOW "WARNING: Could not get time offset for alSource %d: %s\n", + alSource, S_AL_ErrorMsg(error)); + } + + dest->lastTimePos = -1; + } + else + dest->lastSampleTime = Sys_Milliseconds(); +} + +/* +================= +S_AL_NewLoopMaster +Remove given source as loop master if it is the master and hand off master status to another source in this case. +================= +*/ + static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled) { int index; @@ -789,7 +827,16 @@ static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled) if(curSfx->loopCnt) { - if(rmSource == &srcList[curSfx->masterLoopSrc]) + if(rmSource->priority == SRCPRI_ENTITY) + { + if(!iskilled && rmSource->isPlaying) + { + // only sync ambient loops... + // It makes more sense to have sounds for weapons/projectiles unsynced + S_AL_SaveLoopPos(rmSource, rmSource->alSource); + } + } + else if(rmSource == &srcList[curSfx->masterLoopSrc]) { int firstInactive = -1; @@ -803,7 +850,7 @@ static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled) curSource = &srcList[index]; if(curSource->sfx == rmSource->sfx && curSource != rmSource && - curSource->isActive && curSource->isLooping) + curSource->isActive && curSource->isLooping && curSource->priority == SRCPRI_AMBIENT) { if(curSource->isPlaying) { @@ -819,15 +866,22 @@ static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled) if(!curSfx->loopActiveCnt) { if(firstInactive < 0) - curSource = rmSource; + { + if(iskilled) + { + curSfx->masterLoopSrc = -1; + return; + } + else + curSource = rmSource; + } else curSource = &srcList[firstInactive]; if(rmSource->isPlaying) { // this was the last not stopped source, save last sample position + time - qalGetSourcef(rmSource->alSource, AL_SEC_OFFSET, &curSource->lastTimePos); - curSource->lastSampleTime = Sys_Milliseconds(); + S_AL_SaveLoopPos(curSource, rmSource->alSource); } else { @@ -890,7 +944,11 @@ static void S_AL_SrcKill(srcHandle_t src) curSource->priority = 0; curSource->entity = -1; curSource->channel = -1; - curSource->isActive = qfalse; + if(curSource->isActive) + { + curSource->isActive = qfalse; + srcActiveCnt--; + } curSource->isLocked = qfalse; curSource->isTracking = qfalse; curSource->local = qfalse; @@ -909,24 +967,55 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel ) int weakest = -1; int weakest_time = Sys_Milliseconds(); int weakest_pri = 999; + float weakest_gain = 1000.0; + qboolean weakest_isplaying = qtrue; + int weakest_numloops = 0; + src_t *curSource; for(i = 0; i < srcCount; i++) { + curSource = &srcList[i]; + // If it's locked, we aren't even going to look at it - if(srcList[i].isLocked) + if(curSource->isLocked) continue; // Is it empty or not? - if((!srcList[i].isActive) && (empty == -1)) + if(!curSource->isActive) + { empty = i; - else if(srcList[i].priority < priority) + break; + } + + if(curSource->isPlaying) { - // If it's older or has lower priority, flag it as weak - if((srcList[i].priority < weakest_pri) || - (srcList[i].lastUsedTime < weakest_time)) + if(weakest_isplaying && curSource->priority < priority && + (curSource->priority < weakest_pri || + (!curSource->isLooping && (curSource->scaleGain < weakest_gain || curSource->lastUsedTime < weakest_time)))) { - weakest_pri = srcList[i].priority; - weakest_time = srcList[i].lastUsedTime; + // If it has lower priority, is fainter or older, flag it as weak + // the last two values are only compared if it's not a looping sound, because we want to prevent two + // loops (loops are added EVERY frame) fighting for a slot + weakest_pri = curSource->priority; + weakest_time = curSource->lastUsedTime; + weakest_gain = curSource->scaleGain; + weakest = i; + } + } + else + { + weakest_isplaying = qfalse; + + if(weakest < 0 || + knownSfx[curSource->sfx].loopCnt > weakest_numloops || + curSource->priority < weakest_pri || + curSource->lastUsedTime < weakest_time) + { + // Sources currently not playing of course have lowest priority + // also try to always keep at least one loop master for every loop sound + weakest_pri = curSource->priority; + weakest_time = curSource->lastUsedTime; + weakest_numloops = knownSfx[curSource->sfx].loopCnt; weakest = i; } } @@ -936,7 +1025,7 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel ) // causes incorrect behaviour versus defacto baseq3 #if 0 // Is it an exact match, and not on channel 0? - if((srcList[i].entity == entnum) && (srcList[i].channel == channel) && (channel != 0)) + if((curSource->entity == entnum) && (curSource->channel == channel) && (channel != 0)) { S_AL_SrcKill(i); return i; @@ -944,22 +1033,17 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel ) #endif } - // Do we have an empty one? - if(empty != -1) - { - S_AL_SrcKill( empty ); - return empty; - } - - // No. How about an overridable one? - if(weakest != -1) + if(empty == -1) + empty = weakest; + + if(empty >= 0) { - S_AL_SrcKill(weakest); - return weakest; + S_AL_SrcKill(empty); + srcList[empty].isActive = qtrue; + srcActiveCnt++; } - // Nothing. Return failure (cries...) - return -1; + return empty; } /* @@ -1039,7 +1123,7 @@ Necessary for i.g. Western Quake3 mod which is buggy. static qboolean S_AL_CheckInput(int entityNum, sfxHandle_t sfx) { if (entityNum < 0 || entityNum > MAX_GENTITIES) - Com_Error(ERR_DROP, "S_StartSound: bad entitynum %i", entityNum); + Com_Error(ERR_DROP, "ERROR: S_AL_CheckInput: bad entitynum %i", entityNum); if (sfx < 0 || sfx >= numSfx) { @@ -1086,49 +1170,61 @@ S_AL_StartSound Play a one-shot sound effect ================= */ -static -void S_AL_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx ) +static void S_AL_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx ) { vec3_t sorigin; srcHandle_t src; + src_t *curSource; - if(S_AL_CheckInput(origin ? 0 : entnum, sfx)) + if(origin) + { + if(S_AL_CheckInput(0, sfx)) + return; + + VectorCopy(origin, sorigin); + } + else + { + if(S_AL_CheckInput(entnum, sfx)) + return; + + if(S_AL_HearingThroughEntity(entnum)) + { + S_AL_StartLocalSound(sfx, entchannel); + return; + } + + VectorCopy(entityList[entnum].origin, sorigin); + } + + S_AL_SanitiseVector(sorigin); + + if((srcActiveCnt > 5 * srcCount / 3) && + (DistanceSquared(sorigin, lastListenerOrigin) >= + (s_alMaxDistance->value + s_alGraceDistance->value) * (s_alMaxDistance->value + s_alGraceDistance->value))) + { + // We're getting tight on sources and source is not within hearing distance so don't add it return; + } // Try to grab a source src = S_AL_SrcAlloc(SRCPRI_ONESHOT, entnum, entchannel); if(src == -1) return; - // Set up the effect - if( origin == NULL ) - { - if( S_AL_HearingThroughEntity( entnum ) ) - { - // Where the entity is the local player, play a local sound - S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qtrue ); - VectorClear( sorigin ); - } - else - { - S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse ); - VectorCopy( entityList[ entnum ].origin, sorigin ); - } - srcList[ src ].isTracking = qtrue; - } - else - { - S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse ); - VectorCopy( origin, sorigin ); - } + S_AL_SrcSetup(src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse); + + curSource = &srcList[src]; - S_AL_SanitiseVector( sorigin ); - qalSourcefv( srcList[ src ].alSource, AL_POSITION, sorigin ); - S_AL_ScaleGain(&srcList[src], sorigin); + if(!origin) + curSource->isTracking = qtrue; + + qalSourcefv(curSource->alSource, AL_POSITION, sorigin ); + S_AL_ScaleGain(curSource, sorigin); // Start it playing - srcList[src].isPlaying = qtrue; - qalSourcePlay(srcList[src].alSource); + curSource->isPlaying = qtrue; + qalSourcePlay(curSource->alSource); } /* @@ -1158,6 +1254,10 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx, int src; sentity_t *sent = &entityList[ entityNum ]; src_t *curSource; + vec3_t sorigin, svelocity; + + if(S_AL_CheckInput(entityNum, sfx)) + return; // Do we need to allocate a new source for this entity if( !sent->srcAllocated ) @@ -1171,10 +1271,18 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx, return; } + curSource = &srcList[src]; + sent->startLoopingSound = qtrue; + + curSource->lastTimePos = -1.0; + curSource->lastSampleTime = Sys_Milliseconds(); } else + { src = sent->srcIndex; + curSource = &srcList[src]; + } sent->srcAllocated = qtrue; sent->srcIndex = src; @@ -1185,33 +1293,46 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx, // If this is not set then the looping sound is stopped. sent->loopAddedThisFrame = qtrue; - curSource = &srcList[src]; - // UGH // These lines should be called via S_AL_SrcSetup, but we // can't call that yet as it buffers sfxes that may change // with subsequent calls to S_AL_SrcLoop curSource->entity = entityNum; curSource->isLooping = qtrue; - curSource->isActive = qtrue; if( S_AL_HearingThroughEntity( entityNum ) ) { curSource->local = qtrue; - qalSourcefv( curSource->alSource, AL_POSITION, vec3_origin ); - qalSourcefv( curSource->alSource, AL_VELOCITY, vec3_origin ); + VectorClear(sorigin); + + qalSourcefv(curSource->alSource, AL_POSITION, sorigin); + qalSourcefv(curSource->alSource, AL_VELOCITY, sorigin); } else { curSource->local = qfalse; - qalSourcefv( curSource->alSource, AL_POSITION, (ALfloat *)sent->origin ); - qalSourcefv( curSource->alSource, AL_VELOCITY, (ALfloat *)velocity ); + if(origin) + VectorCopy(origin, sorigin); + else + VectorCopy(sent->origin, sorigin); + + S_AL_SanitiseVector(sorigin); - } + VectorCopy(sorigin, curSource->loopSpeakerPos); + + if(velocity) + { + VectorCopy(velocity, svelocity); + S_AL_SanitiseVector(svelocity); + } + else + VectorClear(svelocity); - S_AL_ScaleGain(curSource, sent->origin); + qalSourcefv( curSource->alSource, AL_POSITION, (ALfloat *)sorigin ); + qalSourcefv( curSource->alSource, AL_VELOCITY, (ALfloat *)velocity ); + } } /* @@ -1219,20 +1340,9 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx, S_AL_AddLoopingSound ================= */ -static -void S_AL_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ) +static void S_AL_AddLoopingSound(int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx) { - vec3_t sanOrigin, sanVelocity; - - if(S_AL_CheckInput(entityNum, sfx)) - return; - - VectorCopy( origin, sanOrigin ); - VectorCopy( velocity, sanVelocity ); - S_AL_SanitiseVector( sanOrigin ); - S_AL_SanitiseVector( sanVelocity ); - - S_AL_SrcLoop(SRCPRI_ENTITY, sfx, sanOrigin, sanVelocity, entityNum); + S_AL_SrcLoop(SRCPRI_ENTITY, sfx, origin, velocity, entityNum); } /* @@ -1240,27 +1350,9 @@ void S_AL_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velo S_AL_AddRealLoopingSound ================= */ -static -void S_AL_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ) +static void S_AL_AddRealLoopingSound(int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx) { - vec3_t sanOrigin, sanVelocity; - - if(S_AL_CheckInput(entityNum, sfx)) - return; - - VectorCopy( origin, sanOrigin ); - VectorCopy( velocity, sanVelocity ); - S_AL_SanitiseVector( sanOrigin ); - S_AL_SanitiseVector( sanVelocity ); - - // There are certain maps (*cough* Q3:TA mpterra*) that have large quantities - // of ET_SPEAKERS in the PVS at any given time. OpenAL can't cope with mixing - // large numbers of sounds, so this culls them by distance - if( DistanceSquared( sanOrigin, lastListenerOrigin ) > (s_alMaxDistance->value + s_alGraceDistance->value) * - (s_alMaxDistance->value + s_alGraceDistance->value) ) - return; - - S_AL_SrcLoop(SRCPRI_AMBIENT, sfx, sanOrigin, sanVelocity, entityNum); + S_AL_SrcLoop(SRCPRI_AMBIENT, sfx, origin, velocity, entityNum); } /* @@ -1288,8 +1380,8 @@ void S_AL_SrcUpdate( void ) int i; int entityNum; ALint state; - src_t *curSource; - + src_t *curSource; + for(i = 0; i < srcCount; i++) { entityNum = srcList[i].entity; @@ -1313,9 +1405,11 @@ void S_AL_SrcUpdate( void ) { sentity_t *sent = &entityList[ entityNum ]; - // If a looping effect hasn't been touched this frame, pause it + // If a looping effect hasn't been touched this frame, pause or kill it if(sent->loopAddedThisFrame) { + alSfx_t *curSfx; + // The sound has changed without an intervening removal if(curSource->isActive && !sent->startLoopingSound && curSource->sfx != sent->loopSfx) @@ -1339,39 +1433,81 @@ void S_AL_SrcUpdate( void ) sent->startLoopingSound = qfalse; } + curSfx = &knownSfx[curSource->sfx]; + + S_AL_ScaleGain(curSource, curSource->loopSpeakerPos); + if(!curSource->scaleGain) + { + if(curSource->isPlaying) + { + // Sound is mute, stop playback until we are in range again + S_AL_NewLoopMaster(curSource, qfalse); + qalSourceStop(curSource->alSource); + curSource->isPlaying = qfalse; + } + else if(!curSfx->loopActiveCnt && curSfx->masterLoopSrc < 0) + curSfx->masterLoopSrc = i; + + continue; + } + if(!curSource->isPlaying) { - alSfx_t *curSfx = &knownSfx[curSource->sfx]; + if(curSource->priority == SRCPRI_AMBIENT) + { + // If there are other ambient looping sources with the same sound, + // make sure the sound of these sources are in sync. - // If there are other looping sources with the same sound, - // make sure the sound of these sources are in sync. + if(curSfx->loopActiveCnt) + { + int offset, error; - if(curSfx->loopActiveCnt) - { - int offset; + // we already have a master loop playing, get buffer position. + S_AL_ClearError(qfalse); + qalGetSourcei(srcList[curSfx->masterLoopSrc].alSource, AL_SAMPLE_OFFSET, &offset); + if((error = qalGetError()) != AL_NO_ERROR) + { + if(error != AL_INVALID_ENUM) + { + Com_Printf(S_COLOR_YELLOW "WARNING: Cannot get sample offset from source %d: " + "%s\n", i, S_AL_ErrorMsg(error)); + } + } + else + qalSourcei(curSource->alSource, AL_SAMPLE_OFFSET, offset); + } + else if(curSfx->loopCnt && curSfx->masterLoopSrc >= 0) + { + float secofs; + + src_t *master = &srcList[curSfx->masterLoopSrc]; + // This loop sound used to be played, but all sources are stopped. Use last sample position/time + // to calculate offset so the player thinks the sources continued playing while they were inaudible. - // we already have a master loop playing, get buffer position. - qalGetSourcei(srcList[curSfx->masterLoopSrc].alSource, AL_SAMPLE_OFFSET, &offset); - qalSourcei(curSource->alSource, AL_SAMPLE_OFFSET, offset); + if(master->lastTimePos >= 0) + { + secofs = master->lastTimePos + (Sys_Milliseconds() - master->lastSampleTime) / 1000.0f; + secofs = fmodf(secofs, (float) curSfx->info.samples / curSfx->info.rate); + + qalSourcef(curSource->alSource, AL_SEC_OFFSET, secofs); + } + + // I be the master now + curSfx->masterLoopSrc = i; + } + else + curSfx->masterLoopSrc = i; } - else if(curSfx->loopCnt && curSfx->masterLoopSrc >= 0) + else if(curSource->lastTimePos >= 0) { float secofs; - src_t *master = &srcList[curSfx->masterLoopSrc]; - // This loop sound used to be played, but all sources are stopped. Use last sample position/time - // to calculate offset so the player thinks the sources continued playing while they were inaudible. - - secofs = master->lastTimePos + (Sys_Milliseconds() - master->lastSampleTime) / 1000.0f; - secofs = fmodf(secofs, curSfx->info.samples / curSfx->info.rate); + // For unsynced loops (SRCPRI_ENTITY) just carry on playing as if the sound was never stopped + secofs = curSource->lastTimePos + (Sys_Milliseconds() - curSource->lastSampleTime) / 1000.0f; + secofs = fmodf(secofs, (float) curSfx->info.samples / curSfx->info.rate); qalSourcef(curSource->alSource, AL_SEC_OFFSET, secofs); - - // I be the master now - curSfx->masterLoopSrc = i; } - else - curSfx->masterLoopSrc = i; curSfx->loopActiveCnt++; @@ -1393,12 +1529,17 @@ void S_AL_SrcUpdate( void ) } } - else if(curSource->isPlaying) + else if(curSource->priority == SRCPRI_AMBIENT) { - S_AL_NewLoopMaster(curSource, qfalse); - qalSourceStop(curSource->alSource); - curSource->isPlaying = qfalse; + if(curSource->isPlaying) + { + S_AL_NewLoopMaster(curSource, qfalse); + qalSourceStop(curSource->alSource); + curSource->isPlaying = qfalse; + } } + else + S_AL_SrcKill(i); continue; } diff --git a/src/libs/macosx/libSDL-1.2.0.dylib b/src/libs/macosx/libSDL-1.2.0.dylib Binary files differindex 2ea0f454..701e596f 100755 --- a/src/libs/macosx/libSDL-1.2.0.dylib +++ b/src/libs/macosx/libSDL-1.2.0.dylib diff --git a/src/qcommon/vm_x86_64.c b/src/qcommon/vm_x86_64.c index b424baf8..02e7bf9c 100644 --- a/src/qcommon/vm_x86_64.c +++ b/src/qcommon/vm_x86_64.c @@ -36,7 +36,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include <unistd.h> #include <stdarg.h> -//#define USE_GAS //#define DEBUG_VM #ifdef DEBUG_VM @@ -48,16 +47,10 @@ static FILE* qdasmout; #define VM_X86_64_MMAP -#ifndef USE_GAS void assembler_set_output(char* buf); size_t assembler_get_code_size(void); void assembler_init(int pass); void assemble_line(const char* input, size_t len); -#ifdef Dfprintf -#undef Dfprintf -#define Dfprintf(args...) -#endif -#endif // USE_GAS static void VM_Destroy_Compiled(vm_t* self); @@ -226,10 +219,6 @@ static unsigned char op_argsize[256] = [OP_BLOCK_COPY] = 4, }; -#ifdef USE_GAS -#define emit(x...) \ - do { fprintf(fh_s, ##x); fputc('\n', fh_s); } while(0) -#else void emit(const char* fmt, ...) { va_list ap; @@ -239,16 +228,10 @@ void emit(const char* fmt, ...) va_end(ap); assemble_line(line, strlen(line)); } -#endif // USE_GAS -#ifdef USE_GAS -#define JMPIARG \ - emit("jmp i_%08x", iarg); -#else #define JMPIARG \ emit("movq $%lu, %%rax", vm->codeBase+vm->instructionPointers[iarg]); \ emit("jmpq *%%rax"); -#endif // integer compare and jump #define IJ(op) \ @@ -336,102 +319,8 @@ void emit(const char* fmt, ...) static void* getentrypoint(vm_t* vm) { -#ifdef USE_GAS - return vm->codeBase+64; // skip ELF header -#else return vm->codeBase; -#endif // USE_GAS -} - -#ifdef USE_GAS -char* mmapfile(const char* fn, size_t* size) -{ - int fd = -1; - char* mem = NULL; - struct stat stb; - - fd = open(fn, O_RDONLY); - if(fd == -1) - goto out; - - if(fstat(fd, &stb) == -1) - goto out; - - *size = stb.st_size; - - mem = mmap(NULL, stb.st_size, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); - if(mem == (void*)-1) - mem = NULL; - -out: - if(fd != -1) - close(fd); - - return mem; -} - -static int doas(char* in, char* out, unsigned char** compiledcode) -{ - unsigned char* mem; - size_t size = -1; - pid_t pid; - - Com_Printf("running assembler < %s > %s\n", in, out); - pid = fork(); - if(pid == -1) - { - Com_Printf(S_COLOR_RED "can't fork\n"); - return -1; - } - - if(!pid) - { - char* const argv[] = { - "as", - "-o", - out, - in, - NULL - }; - - execvp(argv[0], argv); - _exit(-1); - } - else - { - int status; - if(waitpid(pid, &status, 0) == -1) - { - Com_Printf(S_COLOR_RED "can't wait for as: %s\n", strerror(errno)); - return -1; - } - - if(!WIFEXITED(status)) - { - Com_Printf(S_COLOR_RED "as died\n"); - return -1; - } - if(WEXITSTATUS(status)) - { - Com_Printf(S_COLOR_RED "as failed with status %d\n", WEXITSTATUS(status)); - return -1; - } - } - - Com_Printf("done\n"); - - mem = (unsigned char*)mmapfile(out, &size); - if(!mem) - { - Com_Printf(S_COLOR_RED "can't mmap object file %s: %s\n", out, strerror(errno)); - return -1; - } - - *compiledcode = mem; - - return size; } -#endif // USE_GAS static void block_copy_vm(unsigned dest, unsigned src, unsigned count) { @@ -462,68 +351,10 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { unsigned char barg = 0; int neednilabel = 0; struct timeval tvstart = {0, 0}; - -#ifdef USE_GAS - byte* compiledcode; - int compiledsize; - void* entryPoint; - char fn_s[2*MAX_QPATH]; // output file for assembler code - char fn_o[2*MAX_QPATH]; // file written by as #ifdef DEBUG_VM char fn_d[MAX_QPATH]; // disassembled #endif - FILE* fh_s; - int fd_s, fd_o; - - gettimeofday(&tvstart, NULL); - - Com_Printf("compiling %s\n", vm->name); - -#ifdef DEBUG_VM - snprintf(fn_s, sizeof(fn_s), "%.63s.s", vm->name); - snprintf(fn_o, sizeof(fn_o), "%.63s.o", vm->name); - fd_s = open(fn_s, O_CREAT|O_WRONLY|O_TRUNC, 0644); - fd_o = open(fn_o, O_CREAT|O_WRONLY|O_TRUNC, 0644); -#else - snprintf(fn_s, sizeof(fn_s), "/tmp/%.63s.s_XXXXXX", vm->name); - snprintf(fn_o, sizeof(fn_o), "/tmp/%.63s.o_XXXXXX", vm->name); - fd_s = mkstemp(fn_s); - fd_o = mkstemp(fn_o); -#endif - if(fd_s == -1 || fd_o == -1) - { - if(fd_s != -1) close(fd_s); - if(fd_o != -1) close(fd_o); - unlink(fn_s); - unlink(fn_o); - - Com_Printf(S_COLOR_RED "can't create temporary file %s for vm\n", fn_s); - vm->compiled = qfalse; - return; - } - -#ifdef DEBUG_VM - strcpy(fn_d,vm->name); - strcat(fn_d, ".qdasm"); - - qdasmout = fopen(fn_d, "w"); -#endif - fh_s = fdopen(fd_s, "wb"); - if(!fh_s) - { - Com_Printf(S_COLOR_RED "can't write %s\n", fn_s); - vm->compiled = qfalse; - return; - } - - emit("start:"); - emit("or %%r8, %%r8"); // check whether to set up instruction pointers - emit("jnz main"); - emit("jmp setupinstructionpointers"); - - emit("main:"); -#else // USE_GAS int pass; size_t compiledOfs = 0; @@ -544,7 +375,12 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { assembler_init(pass); -#endif // USE_GAS +#ifdef DEBUG_VM + strcpy(fn_d,vm->name); + strcat(fn_d, ".qdasm"); + + qdasmout = fopen(fn_d, "w"); +#endif // translate all instructions pc = 0; @@ -555,12 +391,10 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { op = code[ pc ]; ++pc; -#ifndef USE_GAS vm->instructionPointers[instruction] = assembler_get_code_size(); -#endif /* store current instruction number in r15 for debugging */ -#if 1 +#if DEBUG_VM emit("nop"); emit("movq $%d, %%r15", instruction); emit("nop"); @@ -582,15 +416,11 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { Dfprintf(qdasmout, "%s\n", opnames[op]); } -#ifdef USE_GAS - emit("i_%08x:", instruction); -#else if(neednilabel) { emit("i_%08x:", instruction); neednilabel = 0; } -#endif switch ( op ) { @@ -947,82 +777,20 @@ void VM_Compile( vm_t *vm, vmHeader_t *header ) { } } -#ifdef USE_GAS - emit("setupinstructionpointers:"); - emit("movq $%lu, %%rax", (unsigned long)vm->instructionPointers); - for ( instruction = 0; instruction < header->instructionCount; ++instruction ) - { - emit("movl $i_%08x-start, %d(%%rax)", instruction, instruction*4); - } - emit("ret"); - - emit("debugger:"); - if(1); - { - int i = 6; - while(i--) - { - emit("nop"); - emit("int3"); - } - } - - fflush(fh_s); - fclose(fh_s); + } // pass loop - compiledsize = doas(fn_s, fn_o, &compiledcode); - if(compiledsize == -1) - { - vm->compiled = qfalse; - goto out; - } - - vm->codeBase = compiledcode; // remember to skip ELF header! - vm->codeLength = compiledsize; - -#else // USE_GAS - } assembler_init(0); if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC)) Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed"); -#endif // USE_GAS vm->destroy = VM_Destroy_Compiled; - -#ifdef USE_GAS - entryPoint = getentrypoint(vm); - -// __asm__ __volatile__ ("int3"); - Com_Printf("computing jump table\n"); - - // call code with r8 set to zero to set up instruction pointers - __asm__ __volatile__ ( - " xorq %%r8,%%r8 \r\n" \ - " movq %0,%%r10 \r\n" \ - " callq *%%r10 \r\n" \ - : - : "m" (entryPoint) - : "%r8", "%r10", "%rax" - ); #ifdef DEBUG_VM fflush(qdasmout); fclose(qdasmout); #endif - -out: - close(fd_o); - -#ifndef DEBUG_VM - if(!com_developer->integer) - { - unlink(fn_o); - unlink(fn_s); - } -#endif -#endif // USE_GAS - + if(vm->compiled) { struct timeval tvdone = {0, 0}; @@ -1038,9 +806,7 @@ out: void VM_Destroy_Compiled(vm_t* self) { -#ifdef USE_GAS - munmap(self->codeBase, self->codeLength); -#elif _WIN32 +#ifdef _WIN32 VirtualFree(self->codeBase, 0, MEM_RELEASE); #else munmap(self->codeBase, self->codeLength); diff --git a/src/sys/sys_win32.c b/src/sys/sys_win32.c index bf4b8f75..18efe406 100644 --- a/src/sys/sys_win32.c +++ b/src/sys/sys_win32.c @@ -650,8 +650,5 @@ void Sys_PlatformInit( void ) } else SDL_VIDEODRIVER_externallySet = qfalse; - - // Don't redirect to stdout.txt and stderr.txt - _putenv( "SDL_STDIO_REDIRECT=0" ); #endif } |