// Register a new command triChar* triCmdRegister( const triChar* name, triCmdFunc func, const triS32 minargs, const triChar* help, const triChar* desc, const triChar* details ) { if (name==0 || func==0) return("Invalid arguments."); if (triCmdFind( name ) || triCVarFind( name ) || triAliasFind( name )) return("Name already used."); triCmd* cmd = triMalloc(sizeof(triCmd)); cmd->name = triMalloc(strlen(name)+1); strcpy( cmd->name, name ); cmd->func = func; cmd->minargs = minargs; cmd->help = 0; if (help!=0) { cmd->help = triMalloc(strlen(help)+1); strcpy( cmd->help, help ); } cmd->description = 0; if (desc!=0) { cmd->description = triMalloc(strlen(desc)+1); strcpy( cmd->description, desc ); } cmd->details = 0; if (details!=0) { cmd->details = triMalloc(strlen(details)+1); strcpy( cmd->details, details ); } cmd->next = triCmds; triCmds = cmd; return(0); }
triChar* triAliasRegister( const triChar* name, const triChar* cmd ) { // Don't allow aliases with same name as commands or cvars if (triCmdFind( name ) || triCVarFind( name )) return("Name already used."); triCmdAlias* alias = triAliasFind( name ); if (alias==0) alias = triMalloc(sizeof(triCmdAlias)); else { triFree(alias->name); triFree(alias->cmd); } if (alias==0) return("Couldn't create alias."); alias->name = triMalloc(strlen(name)+1); strcpy( alias->name, name ); alias->cmd = triMalloc(strlen(cmd)+1); strcpy( alias->cmd, cmd ); alias->next = triAliases; triAliases = alias; return(0); }
void triCVarSet( const triChar* name, const triChar* value ) { triCVar* res = triCVarFind( name ); if (res==0) return; if (res->flags&TRI_CVAR_RDONLY) { triConsolePrintf("CVar is read-only.\n"); return; } res->fvalue = triatof( value ); if (res->flags&TRI_CVAR_ALLOC) if (res->svalue) triFree(res->svalue); if (res->fvalue!=TRI_INVALID_VAL) { res->svalue = triMalloc( 33 ); snprintf( res->svalue, 33, "%f", res->fvalue ); } else { res->svalue = triMalloc( strlen(value)+1 ); strcpy( res->svalue, value ); } res->flags |= TRI_CVAR_ALLOC; }
TRenum binaryAttachEncoder(TRStreamCodec* codec, TRStreamEncoder* encoder, const TRStrDict* options) { BinaryEncoder* enc = triMalloc(triGetState(), sizeof(BinaryEncoder)); TR_UNUSED(codec); TR_UNUSED(options); TR_ASSERT_RETURN(enc, TR_OUT_OF_MEMORY); enc->state = triGetState(); enc->phrasebook = triCreateIntDict(enc->state); enc->stringPool = triCreateStrDict(enc->state); enc->stringPoolId = 1; enc->currentApi = 0; TR_ASSERT_RETURN(enc->phrasebook, TR_OUT_OF_MEMORY); TR_ASSERT_RETURN(enc->stringPool, TR_OUT_OF_MEMORY); /* Initialize state */ encoder->handle = (TRhandle)enc; encoder->ops = &binaryEncoderOps; /* Write version magic */ writeByte(encoder, 'T'); writeByte(encoder, 'C'); writeByte(encoder, 'Y'); writeByte(encoder, '0' + FORMAT_VERSION); return TR_NO_ERROR; }
// Create a new alias or change an existing one triChar* cmd_alias() { triCmdAlias* alias = triAliasFind( triCmdArgv(1) ); if (alias==0) { if (triCmdArgc()<3) return("Alias not found."); return triAliasRegister( triCmdArgv(1), triCmdArgv(2) ); } static triChar triReturnString[256]; // Alias exists? We change it, or print the current commands if (triCmdArgc()<3) { snprintf( triReturnString, 256, "Current commands:\n\"%s\" \"%s\"", alias->name, alias->cmd ); return triReturnString; } else { triFree( alias->cmd ); alias->cmd = triMalloc(strlen(triCmdArgv(2))+1); strcpy( alias->cmd, triCmdArgv(2) ); } return(0); }
void triPlatformInit(TRState* state) { AndroidPlatformData* d = triMalloc(state, sizeof(AndroidPlatformData)); d->seqCounter = 0; d->verbose = getIntegerProperty("tracy.verbose", 1); state->synchronousOperation = getIntegerProperty("tracy.sync", 0); state->platformData = d; /* Schedule a proper termination when the host application shuts down */ atexit(trTerminate); }
void triPlatformInit(TRState* state) { UnixPlatformData* d = triMalloc(state, sizeof(UnixPlatformData)); pthread_mutex_init(&d->lock, 0); d->seqCounter = 0; d->verbose = getenv("TRACY_VERBOSE") ? atoi(getenv("TRACY_VERBOSE")) : 0; state->synchronousOperation = getenv("TRACY_SYNC") ? atoi(getenv("TRACY_SYNC")) : 0; state->platformData = d; /* Schedule a proper termination when the host application shuts down */ atexit(trTerminate); }
triHeap* triHeapCreate( void* base, triU32 size, triU32 block_size ) { triHeap* mem = triMalloc(sizeof(triHeap)); if (mem==0) return(0); mem->_base = base; mem->_size = size; if (block_size==0) block_size = size >> 12; // have 4096 blocks to manage at default if (block_size<16) block_size = 16; // minimum block size of 16 mem->_block_size = block_size; mem->_n_blocks = size/block_size; if (mem->_n_blocks>32768) { mem->_n_blocks = 32768; mem->_block_size = size >> 15; }
void triCVarSetf( const triChar* name, const float value ) { triCVar* res = triCVarFind( name ); if (res==0) return; if (res->flags&TRI_CVAR_RDONLY) { triConsolePrintf("CVar is read-only.\n"); return; } res->fvalue = value; if (res->flags&TRI_CVAR_ALLOC) if (res->svalue) triFree(res->svalue); res->svalue = triMalloc( 33 ); snprintf( res->svalue, 33, "%f", value ); res->flags |= TRI_CVAR_ALLOC; }
triChar* cmd_exec() { triChar* file = triCmdArgv(1); FILE* fp = fopen( file, "r" ); if (fp==0) return("Error opening file."); fseek(fp,0,SEEK_END); triS32 sz = ftell(fp); fseek(fp,0,SEEK_SET); triChar* buffer = triMalloc(sz+1); if (buffer==0) return("Error allocating script buffer."); fread( buffer, 1, sz, fp ); fclose(fp); triCmdExecute( buffer ); triFree(buffer); return(0); }
triBool triAt3Load(const triChar *filename) { triLogPrint("triAt3: Opening file %s\r\n", filename); FILE *pFile = fopen(filename , "rb"); if(pFile == NULL) { triLogError("triAt3: File not found %s\r\n", filename); return(0); } triS32 lSize; fseek(pFile , 0, SEEK_END); lSize = ftell(pFile); rewind(pFile); Tune = (triUChar*) triMalloc(sizeof(triUChar)*lSize); memset(Tune, 0, lSize); if(!Tune) { triLogError("triAt3: Malloc of 'Tune' failed\r\n"); return(0); } fread(Tune, 1, lSize, pFile); fclose(pFile); AT3_Loaded = 1; if(AT3_FileInit(Tune, lSize, &Mixing_CallBack)) return(1); triLogError("triAt3: Error loading file\r\n"); return(0); }
// Execute an alias triS32 triAliasCmd() { triCmdAlias* alias = triAliasFind( triCmdArgv(0) ); if (alias==0) return(0); if (triCmdArgc()<2) { triCmdExecute( alias->cmd ); return (1); } // Allow aliases to to be fed with arguments, making things like 'alias @ echo;@ "aliased echo output"' possible triS32 len = strlen(alias->cmd)+1; triS32 i = 1; for (;i<triCmdArgc();i++) len += strlen(triCmdArgv(i))+1; triChar* buffer = triMalloc(len); if (buffer==0) triCmdExecute( alias->cmd ); else { sprintf( buffer, "%s ", alias->cmd ); len = strlen(alias->cmd)+1; i = 1; for (;i<triCmdArgc();i++) { sprintf( buffer+len, "%s ", triCmdArgv(i) ); len += strlen(triCmdArgv(i))+1; } buffer[len-1] = 0; triCmdExecute( buffer ); triFree( buffer ); } return(1); }
TRenum binaryAttachDecoder(TRStreamCodec* codec, TRStreamDecoder* decoder, const TRStrDict* options) { BinaryDecoder* dec = triMalloc(triGetState(), sizeof(BinaryDecoder)); TR_UNUSED(codec); TR_UNUSED(options); TR_ASSERT_RETURN(dec, TR_OUT_OF_MEMORY); dec->state = triGetState(); dec->phrasebook = triCreateIntDict(dec->state); dec->event = 0; TR_ASSERT_RETURN(dec->phrasebook, TR_OUT_OF_MEMORY); /* Initialize state */ decoder->handle = (TRhandle)dec; decoder->ops = &binaryDecoderOps; /* Read version magic */ if (readByte(decoder) != 'T') return TR_BAD_VALUE; if (readByte(decoder) != 'C') return TR_BAD_VALUE; if (readByte(decoder) != 'Y') return TR_BAD_VALUE; if (readByte(decoder) != '0' + FORMAT_VERSION) return TR_BAD_VALUE; return TR_NO_ERROR; }
triWav *triWavLoad(const triChar *filename) { triLogPrint("triWav: Loading %s\r\n", filename); triUInt filelen; triU32 channels; triU32 samplerate; triU32 blocksize; triU32 bitpersample; triU32 datalength; triU32 samplecount; triChar *wavfile; triWav *theWav; if ((theWav=triRefcountRetain( filename ))!=0) return theWav; FILE *pFile = fopen(filename , "rb"); if(pFile == NULL) { triLogError("triWav: File not found %s\r\n", filename); return NULL; } triS32 lSize; fseek(pFile , 0, SEEK_END); lSize = ftell(pFile); rewind(pFile); theWav = triMalloc(lSize + sizeof(triWav)); triRefcountCreate( filename, theWav ); wavfile = (triChar*)(theWav) + sizeof(triWav); filelen = fread(wavfile, 1, lSize, pFile); fclose(pFile); if (memcmp(wavfile, "RIFF", 4) != 0) { triLogError("triWav: format error not RIFF\r\n"); triFree(theWav); return NULL; } /*if (memcmp(wavfile + 8, "WAVEfmt \x10\x00\x00\x00\x01\x00", 14) != 0) { triLogError("triWav: format error no WAVEfmt string\r\n"); triFree(theWav); return NULL; }*/ channels = *(triS16 *)(wavfile + 0x16); samplerate = *(triS32 *)(wavfile + 0x18); blocksize = *(triS16 *)(wavfile + 0x20); bitpersample = *(triS16 *)(wavfile + 0x22); triSInt i; for(i = 0; memcmp(wavfile + 0x24 + i, "data", 4) != 0; i++) { if (i == 0xFF) { triLogError("triWav: no data chunk found\r\n"); triFree(theWav); return NULL; } } datalength = readU32(wavfile, 0x28+i); //*(triU32 *)(wavfile + 0x28 + i); if (datalength + 0x2c > filelen) { triLogError("triWav: buffer is supposed to be bigger than this\r\n"); triFree(theWav); return NULL; } if (channels != 2 && channels != 1) { triLogError("triWav: not Mono or Stereo sample\r\n"); triFree(theWav); return NULL; } if (samplerate > 100000 || samplerate < 2000) { triLogError("triWav: sample rate is wrong\r\n"); triFree(theWav); return NULL; } /*if (blocksize != channels*2) { triLogError("triWav: BLOCKSIZE MISMATCH\r\n"); triFree(theWav); return NULL; }*/ /*if (bitpersample != 16 || bitpersample != 8) { triLogError("triWav: Bits Per Sample Error\r\n"); triFree(theWav); return NULL; }*/ if (channels == 2) { samplecount = datalength/(bitpersample/4); } else { samplecount = datalength/((bitpersample/4)/2); } if (samplecount <= 0) { triLogError("triWav: no samples\r\n"); triFree(theWav); return NULL; } theWav->channels = channels; theWav->sampleRate = samplerate; theWav->sampleCount = samplecount; theWav->dataLength = datalength; theWav->data = wavfile + 0x2c + i; theWav->rateRatio = (samplerate*0x4000)/11025; theWav->playPtr = 0; theWav->playPtr_frac= 0; theWav->loop = 0; id++; theWav->id = id; theWav->bitPerSample = bitpersample; return theWav; }
if (block_size==0) block_size = size >> 12; // have 4096 blocks to manage at default if (block_size<16) block_size = 16; // minimum block size of 16 mem->_block_size = block_size; mem->_n_blocks = size/block_size; if (mem->_n_blocks>32768) { mem->_n_blocks = 32768; mem->_block_size = size >> 15; } mem->_free = mem->_n_blocks; mem->_largest_block = mem->_n_blocks; mem->_largest_update = 0; mem->_blocks = triMalloc(sizeof(triU32)*mem->_n_blocks); if (mem->_blocks==0) { triFree(mem); return(0); } memset( mem->_blocks,0,sizeof(triU32)*mem->_n_blocks); mem->_blocks[0] = __CBLOCK_MAKE(mem->_n_blocks,0,1,1); return(mem); } void triHeapDestroy( triHeap* mem ) { if (mem==0) return; triFree(mem->_blocks); triFree(mem);
/* Simple thread */ int main(int argc, char **argv) { SetupCallbacks(); triLogInit(); triInit( GU_PSM_8888, 1 ); tri3dInit(); triInputInit(); // FIXME: This is not the right way to do as it will cause the particle manager to try and free pointers from inside the array partSys = triMalloc( sizeof(triParticleSystem)*4 ); partEm = triMalloc( sizeof(triParticleEmitter)*4 ); triS32 PsID0 = triParticleManagerLoadScript( "watersprinkle.txt" ); triParticleSystemConstructor( &partSys[0] ); triParticleSystemConstructor( &partSys[1] ); triParticleSystemConstructor( &partSys[2] ); partSys[0].render = renderParticle; partSys[2].renderMode = GU_TRIANGLES; partSys[2].blendMode = TRI_BLEND_MODE_ALPHA; //triParticleSystemConstructor( &partSys[3] ); //partSys[3].renderMode = GU_TRIANGLES; triParticleEmitterConstructor( &partEm[0], TRI_EMITTER_SPRINKLE ); triParticleEmitterConstructor( &partEm[1], TRI_EMITTER_FIRE ); triParticleEmitterConstructor( &partEm[2], TRI_EMITTER_SMOKE ); //triParticleEmitterConstructor( &partEm[3], TRI_EMITTER_EXPLOSION ); partEm[0].pos.z = -10.0f; partEm[0].pos.x = -5.0f; partEm[0].velRand.w = 1.f; partEm[0].max = 64; partEm[1].pos.z = -10.0f; partEm[1].pos.x = 5.0f; partEm[1].vel.y += 1.5f; partEm[1].binding = 0.0f; // particles are bound to the emitter partEm[1].loosen = 0.85f; // particles loosen from the emitter with age partEm[1].life = 0.8f; partEm[1].growth = -0.7f/partEm[1].life; partEm[1].max = 512; partEm[1].rate = partEm[1].max/(partEm[1].life*1.2); partEm[1].lastpos = partEm[1].pos; partEm[1].vortexRange = 0.6f; partEm[1].vortexDirRand = 2.5f; partEm[2].pos.z -= 3.0; partEm[2].pos.x += 2.0; partEm[2].maxVortex = 16; partEm[2].rateVortex = 2; partEm[2].max = 256; partEm[2].life = 10.f; partEm[2].lifetime = 0; partEm[2].vortexDir = 0.f; partEm[2].vortexDirRand = 1.2f; partEm[2].vortexRange = 0.5f; partEm[2].rate = partEm[2].max/(partEm[2].life); //partEm[3].pos.z -= 5.0; partSys[1].textureID = triTextureLoad( "sprite.tga" ); partSys[2].textureID = triTextureLoad( "smoke32.tga" ); //triParticleManagerAdd( &partSys[0], &partEm[0] ); triParticleManagerAdd( &partSys[1], &partEm[1] ); triParticleManagerAdd( &partSys[2], &partEm[2] ); //triParticleManagerAdd( &partSys[3], &partEm[3] ); cam = triCameraCreate( 0.0f, 0.0f, -10.0f ); // Do additional setup in immediate mode triBegin(); tri3dPerspective( 45.0f ); sceGuFrontFace(GU_CW); triClear( 0x330000 ); triEnable(TRI_VBLANK); triEnd(); //triSync(); triTimer* frametimer = triTimerCreate(); triTimer* demotimer = triTimerCreate(); triS32 vblank = 0; #define SPEED 0.05f while (isrunning) { triBegin(); tri3dClear( 1,0,1 ); triInputUpdate (); if (triInputHeld (PSP_CTRL_UP)) { triCameraRotate( cam, SCE_DEG_TO_RAD(3.2f), &triXAxis ); } if (triInputHeld (PSP_CTRL_DOWN)) { triCameraRotate( cam, SCE_DEG_TO_RAD(-3.2f), &triXAxis ); } if (triInputHeld (PSP_CTRL_LEFT)) { triCameraRotate( cam, SCE_DEG_TO_RAD(3.2f), &triYAxis ); } if (triInputHeld (PSP_CTRL_RIGHT)) { triCameraRotate( cam, SCE_DEG_TO_RAD(-3.2f), &triYAxis ); } if (triInputHeld (PSP_CTRL_LTRIGGER)) { triCameraMove( cam, 0.0f, 0.0f, SPEED ); } if (triInputHeld (PSP_CTRL_RTRIGGER)) { triCameraMove( cam, 0.0f, 0.0f, -SPEED ); } if (triInputPressed (PSP_CTRL_SELECT)) { vblank ^= 1; if (vblank) triEnable(TRI_VBLANK); else triDisable(TRI_VBLANK); } triCameraUpdateMatrix( cam ); sceGumMatrixMode (GU_MODEL); sceGumLoadIdentity (); triTimerUpdate(frametimer); triParticleManagerUpdateRender( cam, triTimerGetDeltaTime(frametimer) ); partEm[1].pos.z = sinf( 30*triTimerPeekDeltaTime(demotimer)*SCE_PI/180.0f )*5.0f - 10.0f; partEm[1].pos.x = cosf( 30*triTimerPeekDeltaTime(demotimer)*SCE_PI/180.0f )*5.0f; triFontActivate(0); triFontPrintf( 0, 0, 0xFFFFFFFF, "CAM: dir <%.3f, %.3f, %.3f> pos <%.3f, %.3f, %.3f>\n", cam->dir.x, cam->dir.y, cam->dir.z, cam->pos.x, cam->pos.y, cam->pos.z); triFontPrintf( 0,10, 0xFFFFFFFF, "FPS: %.2f - CPU: %.0f GPU: %.0f\n", triFps(), triCPULoad(), triGPULoad()); /*if (partEm[3].age>=partEm[3].lifetime && (rand()%100<5)) { triParticleEmitterConstructor( &partEm[3], TRI_EMITTER_EXPLOSION ); partEm[3].pos.x = 3.0f * (rand()%65537 - 32768)/32768.0f; partEm[3].pos.y = 3.0f * (rand()%65537 - 32768)/32768.0f; partEm[3].pos.z = -15.0f + 3.0f * (rand()%65537 - 32768)/32768.0f; }*/ triEnd(); triSwapbuffers(); } triTextureUnload( partSys[1].textureID ); triTextureUnload( partSys[2].textureID ); triParticleManagerDestroy(); triFree( partSys ); triFree( partEm ); triTimerFree(frametimer); triTimerFree(demotimer); triFree( cam ); triInputShutdown(); triClose(); tri3dClose(); triMemoryShutdown(); sceKernelExitGame(); return 0; }
// Tokenize the string line until either a ;, \n or \0 is found and return pointer to that position // ; and spaces may be included in single arguments by encapsulating in quotes "" // spaces may be included in single arguments by encapsulating in round brackets () // This allows things like "cl_backcolor (1.0 0.7 0.1)" triChar* triCmdTokenize( triChar* line ) { // triFree all current command argument buffers if (triCmdCurArgs) { triFree(triCmdCurArgs); triCmdCurArgs = 0; } triS32 i = 0; for (;i<MAXARGS;i++) if (triCmdCurArgv[i]) { triFree(triCmdCurArgv[i]); triCmdCurArgv[i] = 0; } i = 0; // strip whitespaces while (*line && *line<=' ') line++; triCmdCurArgc = 0; triS32 quotes = 0; triS32 brackets = 0; triChar* args = 0; while (1) { if (line[i]=='"') quotes++; if (line[i]=='(') brackets++; if (line[i]==')') if (brackets) brackets--; if ((!(quotes&1) && !brackets && line[i]==' ') || (!(quotes&1) && line[i]==';') || (line[i]=='\n') || (line[i]==0) || (!(quotes&1) && line[i]=='"')) { // Save arguments start if (triCmdCurArgc==0) args = line; // Strip quotes if (line[0]=='"' || line[0]=='\'') { i--; line++; } triCmdCurArgv[triCmdCurArgc] = triMalloc(i+1); if (triCmdCurArgv[triCmdCurArgc]==0) { triLogError("ERROR ALLOCATING ARGV BUFFER!\n"); return(0); } strncpy( triCmdCurArgv[triCmdCurArgc], line, i ); triCmdCurArgv[triCmdCurArgc][i] = 0; if (triCmdCurArgv[triCmdCurArgc][i-1]=='"') triCmdCurArgv[triCmdCurArgc][i-1]=0; triCmdCurArgc++; if (line[i]==0 || line[i]=='\n') break; if (!(quotes&1) && line[i]==';') break; if (line[i]!=0) i++; line += i; i = 0; continue; } i++; } // Create args string if (triCmdCurArgc>1) { triCmdCurArgs = triMalloc(&line[i]-args+1); strncpy( triCmdCurArgs, args, &line[i]-args ); } return &line[i]; }
TRuint defineString(TRStreamEncoder* encoder, const TRbyte* string) { if (!string) { /* Phrase zero is reserved for NULL pointers */ return 0; } else { BinaryEncoder* enc = (BinaryEncoder*)encoder->handle; TRuint id = (TRuint)triStrDictGet(enc->stringPool, string); if (!id) { TRuint length = triStringLength(string) + 1; Phrase* phrase = triMalloc(enc->state, sizeof(Phrase)); if (!phrase) { TRuint i; /* No strings to deallocate? */ if (triDictSize(enc->stringPool) < 4) { TR_ASSERT(phrase); } /* Free a quarter of the allocated strings */ for (i = 0; i < triDictSize(enc->stringPool) / 4; i++) { triDictVisit(enc->stringPool, freeStringPoolEntry, enc); } /* Try the allocation again */ return defineString(encoder, string); } /* Find a free slot in the phrasebook for the new string */ while (triIntDictGet(enc->phrasebook, enc->stringPoolId) || enc->stringPoolId == 0) { enc->stringPoolId++; } /* Add the string to the phrasebook */ id = enc->stringPoolId; phrase->data = triStringDuplicate(enc->state, string); phrase->size = length; triIntDictSet(enc->phrasebook, id, phrase); triStrDictSet(enc->stringPool, string, (void*)id); /* Serialize the string to the stream */ writeByte(encoder, TOK_DEFINE); writeInt(encoder, 2 * sizeof(TRint) + sizeof(TRbyte) + length * sizeof(TRbyte)); writeInt(encoder, id); writeInt(encoder, length); writeByte(encoder, TR_VOID); encoder->stream->ops->write(encoder->stream, string, length); } return id; } }
static TRenum readToken(TRStreamDecoder* decoder, TRint expectedToken, TRVariant* value) { BinaryDecoder* dec = (BinaryDecoder*)decoder->handle; TRubyte token; TRint param; #if defined(TRACER_PLAYER_VERBOSE_LOGGING) /*triLogMessage(dec->state, "[binary] Looking for token 0x%x.", expectedToken);*/ #endif do { if (decoder->stream->ops->read(decoder->stream, (TRbyte*)&token, sizeof(TRubyte)) != 1) { #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] End of stream encountered."); #endif return TR_NOT_FOUND; } #if defined(TRACER_PLAYER_VERBOSE_LOGGING) /*triLogMessage(dec->state, "[binary] Reading token 0x%x.", token);*/ #endif param = readInt(decoder); switch (token) { case TOK_DEFINE: { TRint id = readInt(decoder); TRint size = readInt(decoder); TRbyte type = readByte(decoder); TRuint length = param - (2 * sizeof(TRint) + sizeof(TRbyte)); Phrase* phrase; TRhandle objectNs = 0; const TRClass* objectClass = 0; /* If this is an array of objects, read the class and namespace information */ if (type == TR_OBJECT) { const TRbyte* className = (const TRbyte*)lookupPhrase(decoder, readInt(decoder)); objectNs = readPointer(decoder); objectClass = triGetClassByName(dec->state, className); length -= sizeof(TRint) + sizeof(TRhandle); TR_ASSERT(objectClass); } TR_ASSERT(size >= length); TR_UNUSED(type); #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] DEFINE %p = %d bytes (%d bytes defined)", id, size, length); #endif /* Replace any previous phrase under this id */ phrase = triIntDictGet(dec->phrasebook, id); /* Clear the existing entry if this is a zero-length phrase */ if (phrase && phrase->data && size == 0) { triFree(dec->state, phrase->data); triFree(dec->state, phrase); triIntDictSet(dec->phrasebook, id, 0); /* No need to read the rest of the data since there is none */ continue; } if (!phrase) { /* Allocate the new phrase */ phrase = triMalloc(dec->state, sizeof(Phrase)); TR_ASSERT(phrase); phrase->data = triMalloc(dec->state, size); phrase->size = size; /* Terminate the data with zeros if needed */ triMemSet(&phrase->data[length], 0, size - length); } else { /* Make sure the allocated phrase is big enough */ TR_ASSERT(phrase->size >= size); } if (!phrase->data) { return TR_OUT_OF_MEMORY; } /* Read the phrase contents */ if (decoder->stream->ops->read(decoder->stream, phrase->data, length) != length) { return TR_INVALID_OPERATION; } /* For object arrays, translate the references to live objects */ if (type == TR_OBJECT) { int i; TRhandle* array = (TRhandle*)phrase->data; for (i = 0; i < length / sizeof(TRhandle); i++) { array[i] = triGetObject(dec->state, objectClass->id, objectNs, array[i], array[i]); } } /* Store it in the phrasebook */ triIntDictSet(dec->phrasebook, id, phrase); } break; case TOK_EVENT: { /* TODO: dictionary lookup */ const TRbyte* name = (const TRbyte*)lookupPhrase(decoder, readInt(decoder)); dec->event->function = triLookupFunction(dec->state, dec->event->api, name); dec->event->sequenceNumber = readInt(decoder); dec->event->timestamp = readInt(decoder); #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] EVENT %s (%p), seq = %d, ts = %d", name, dec->event->function, dec->event->sequenceNumber, (TRint)dec->event->timestamp); #endif } break; case TOK_VALUE: { TRint nameId = readInt(decoder); TRbyte type = readByte(decoder); TR_UNUSED(nameId); if (type & TR_PHRASE_BIT) { value->p = lookupPhrase(decoder, readInt(decoder)); } else { switch (type) { case TR_BYTE: value->b = readByte(decoder); break; case TR_SHORT: value->s = readShort(decoder); break; case TR_INTEGER: value->i = readInt(decoder); break; case TR_LONG: value->l = readLong(decoder); break; case TR_FLOAT: value->f = readFloat(decoder); break; case TR_DOUBLE: value->d = readDouble(decoder); break; case TR_OBJECT: { const TRbyte* className = (const TRbyte*)lookupPhrase(decoder, readInt(decoder)); const TRhandle ns = readPointer(decoder); const TRhandle handle = readPointer(decoder); const TRClass* c = triGetClassByName(dec->state, className); if (!c) { #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] Bad class name: %s", className); #endif } else { /* Translate the reference to a live pointer */ value->o.cls = c; value->o.ns = ns; value->o.handle = triGetObject(dec->state, c->id, ns, handle, handle); #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] %s instance at %p mapped to %p", c->name, handle, value->o.handle); #endif } } break; default: TR_ASSERT(!"Corrupted binary stream: Bad value type."); break; } } #if defined(TRACER_PLAYER_VERBOSE_LOGGING) { const TRbyte* name = (const TRbyte*)lookupPhrase(decoder, nameId); triLogMessage(dec->state, "[binary] VALUE %s = %d (%f, %p)", name, value->i, value->f, value->p); } #endif } break; case TOK_API: dec->event->api = param; #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] API %d", dec->event->api); #endif break; case TOK_DURATION: dec->event->callTime = param; #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] DURATION %d", (TRint)dec->event->callTime); #endif break; case TOK_BEGIN_OBJECT: { const TRbyte* className = (const TRbyte*)lookupPhrase(decoder, readInt(decoder)); TRhandle ns = readPointer(decoder); TRhandle handle = readPointer(decoder); const TRClass* objectClass = triGetClassByName(dec->state, className); #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] BEGIN_OBJECT %s", className); #endif if (!objectClass) { #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] Bad class name: %s", className); #endif } else if (handle) { triUnserializeObject(dec->state, objectClass->id, ns, handle); } /* Skip to the end of the object data */ readToken(decoder, TOK_END_OBJECT, value); } break; case TOK_END_OBJECT: #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] END_OBJECT"); #endif break; default: #if defined(TRACER_PLAYER_VERBOSE_LOGGING) triLogMessage(dec->state, "[binary] Bad token: 0x%x", token); #endif /* Skip it */ while (!(token & TOK_TINY_TOKEN_BIT) && param--) { readByte(decoder); } break; } } while (token != expectedToken); #if defined(TRACER_PLAYER_VERBOSE_LOGGING) /*triLogMessage(dec->state, "[binary] Found our token.");*/ #endif return TR_NO_ERROR; }