/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { #if !defined RTCW_ET char string[1024]; int pos; #endif // RTCW_XX if ( !clc.demorecording ) { return; } #if !defined RTCW_ET pos = FS_FTell( clc.demofile ); sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); #else //bani Cvar_Set( "cl_demooffset", va( "%d", FS_FTell( clc.demofile ) ) ); #endif // RTCW_XX #if defined RTCW_SP SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue ); #elif defined RTCW_MP SCR_DrawStringExt( 5, 470, 8, string, g_color_table[7], qtrue ); #endif // RTCW_XX }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { const float ratio = cls.ratioFix; char string[1024]; int pos; if ( !clc.demorecording ) { return; } if ( clc.spDemoRecording ) { return; } if (cl_drawRecording->integer >= 2 && cls.recordingShader) { vec4_t colour = {1.0f, 0.1f, 0.1f, 1.0f}; const float size = 10.0f; re.SetColor(colour); if ((cl_drawRecording->integer == 3 && (cls.realtime % 1536) < 768) || cl_drawRecording->integer != 3) re.DrawStretchPic(0-size*ratio/1.84f, SCREEN_HEIGHT-size*1.92f, size*3*ratio, size*3, 0, 0, 1, 1, cls.recordingShader); SCR_DrawStringExt2(0+(size+4)*ratio, SCREEN_HEIGHT-size-2, size*ratio, size, "REC", colour, qtrue, qfalse); } else if (cl_drawRecording->integer) { const float size = 8.0f; pos = FS_FTell(clc.demofile); Com_sprintf(string, sizeof(string), "RECORDING %s: %ik", clc.demoName, pos / 1024); SCR_DrawStringExt2(SCREEN_WIDTH/2.0f-strlen(string)*(size/2.0f)*ratio, 20.0f, size*ratio, size, string, g_color_table[7], qtrue, qfalse); } }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording(void) { if (!clc.demorecording) { return; } Cvar_Set("cl_demooffset", va("%d", FS_FTell(clc.demofile))); }
/* ======================================================================================================================================= S_OggOpus_Callback_tell ftell() replacement. ======================================================================================================================================= */ opus_int64 S_OggOpus_Callback_tell(void *datasource) { snd_stream_t *stream; // check if input is valid if (!datasource) { errno = EBADF; return -1; } // snd_stream_t in the generic pointer stream = (snd_stream_t *)datasource; return (opus_int64)FS_FTell(stream->file); }
void SCR_DrawDemoRecording( void ) { char string[1024]; int pos; if ( !clc.demorecording ) { return; } if ( clc.spDemoRecording ) { return; } pos = FS_FTell( clc.demofile ); sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); SCR_DrawStringExt( ((int)SCREEN_WIDTH/2) - (int)strlen( string ) * 4, 20, 8, string, &g_color_table[ColorIndex(COLOR_WHITE)], qtrue, qfalse ); }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { char string[1024]; int pos; if ( !clc.demorecording ) { return; } if ( clc.spDemoRecording ) { return; } pos = FS_FTell( clc.demofile ); sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, ColorForIndex(ColorIndex(COLOR_WHITE)), qtrue, qfalse ); }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { char string[1024]; int pos; if ( !clc.demorecording ) { return; } if ( clc.spDemoRecording ) { return; } pos = FS_FTell( clc.demofile ); sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue ); }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording(void) { char string[1024]; int pos; if(!clc.demorecording) { return; } if(clc.spDemoRecording) { return; } pos = FS_FTell(clc.demofile); sprintf(string, "RECORDING %s: %ik", clc.demoName, pos / 1024); SCR_Text_PaintAligned(320, 45, string, 0.2f, UI_CENTER, g_color_table[7], &cls.consoleFont); }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { const float ratio = cls.ratioFix; char string[1024]; int pos; if ( !clc.demorecording ) { return; } if ( clc.spDemoRecording ) { return; } if (cl_drawRecording->integer >= 2 && cls.recordingShader) { static const float width = 60.0f, height = 15.0f; re.SetColor(NULL); re.DrawStretchPic(0*ratio, SCREEN_HEIGHT-height, width*ratio, height, 0, 0, 1, 1, cls.recordingShader); } else if (cl_drawRecording->integer) { pos = FS_FTell( clc.demofile ); sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - (int)strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue ); } }
///////////////////////////////////////////////////////////////////// // Name : SCR_DrawDemoRecording // Description : Draw the demo recording string ///////////////////////////////////////////////////////////////////// void SCR_DrawDemoRecording(void) { int pos; char string[1024]; if (!clc.demorecording) { return; } if (clc.spDemoRecording) { return; } pos = FS_FTell(clc.demofile); Com_sprintf(string, sizeof(string), "%s[%sRECORDING%s][%s%iKB%s]", S_COLOR_WHITE, (((int)(cls.realtime >> 10) & 1) || (!cl_demoBlink->integer)) ? S_COLOR_RED : S_COLOR_WHITE, S_COLOR_WHITE, S_COLOR_YELLOW, pos / 1024, S_COLOR_WHITE); // draw the demo notification on screen SCR_DrawStringExt(320 - (SCR_GetSmallStringWidth(string) / 2), 4, SMALLCHAR_WIDTH, string, g_color_table[7], qfalse); }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { char string[1024]; int pos; if ( !clc.demorecording ) { return; } if ( clc.spDemoRecording ) { return; } pos = FS_FTell( clc.demofile ); #ifdef URBAN_TERROR sprintf( string, "REC: %.10s...: %iKB", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - strlen( string ) * 4, 1, 8, string, g_color_table[ColorIndex(COLOR_RED)], qtrue, qfalse ); #else sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue, qfalse ); #endif }
int __cdecl Com_SaveBsp_EnforceVersion(FILE* h) { long len = FS_FTell(h); BYTE* buf = new BYTE[len]; FS_FSeek(h, 0, SEEK_SET); FS_FileRead(buf, 1, len, h); D3DBSP* iBSP = new D3DBSP; iBSP->Load(buf); delete[] buf; iBSP->Convert(BSPVERSION_COD_BO); if (!preservedPrimaryLights.isEmpty) { printf("restoring primary ligmmpts\n"); iBSP->RestoreLump(LUMP_PRIMARY_LIGHTS, &preservedPrimaryLights); } if (g_HDR) { delete[] LightGridSampleColors_HDR; Com_SaveLightmaps_HDR(&iBSP->lumps[LUMP_LIGHTBYTES]); Com_SaveLightgrid_HDR(&iBSP->lumps[LUMP_LIGHTGRIDCOLORS]); } len = iBSP->PotentialFileSize(); buf = new BYTE[len]; iBSP->Write(buf); delete iBSP; FS_FSeek(h, 0, SEEK_SET); FS_FileWrite(buf, 1, len, h); return FS_FileClose(h); }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { char string[1024]; int pos; if ( !clc.demorecording ) { return; } if ( clc.spDemoRecording ) { return; } pos = FS_FTell( clc.demofile ); #ifdef OPEN_ARENA // This is what is used in most ioUrT clients to avoid huge names sprintf( string, "REC: %.10s...: %iKB", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - strlen( string ) * 4, 1, 8, string, g_color_table[ColorIndex(COLOR_RED)], qtrue, qfalse ); #else sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 ); SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue, qfalse ); #endif }
/* ================= SCR_DrawDemoRecording ================= */ void SCR_DrawDemoRecording( void ) { char string[1024]; int pos; if (!clc.demorecording || clc.spDemoRecording) return; pos = FS_FTell(clc.demofile); int nameLen = strlen(clc.demoName) + 1; char *demoName = malloc(nameLen); COM_StripExtension(clc.demoName, demoName, nameLen); char *fmt; if (strlen(demoName) > 40) fmt = "^1REC^7: %.40s...: %iKB"; else fmt = "^1REC^7: %s: %iKB"; sprintf(string, fmt, demoName, pos / 1024); SCR_DrawFontText(320 - SCR_FontWidth(string, 0.18) / 2, 10, 0.18, g_color_table[7], string, ITEM_TEXTSTYLE_SHADOWEDLESS); }
size_t Tell(Rocket::Core::FileHandle file) { return (size_t) FS_FTell((fileHandle_t) file); }
/* ================= CL_ReadDemoMessage ================= */ void CL_ReadDemoMessage(void) { int r; msg_t buf; byte bufData[MAX_MSGLEN]; int s; if (!clc.demofile) { CL_DemoCompleted(); return; } #if NEW_DEMOFUNC di.numSnaps++; if (di.snapCount < maxRewindBackups && ((!di.gotFirstSnap && !(cls.state >= CA_CONNECTED && cls.state < CA_PRIMED)) || (di.gotFirstSnap && di.numSnaps % (di.snapsInDemo / maxRewindBackups) == 0))) { rewindBackups_t *rb; if (!di.skipSnap) { // first snap triggers loading screen when rewinding di.skipSnap = qtrue; goto keep_reading; } di.gotFirstSnap = qtrue; rb = &rewindBackups[di.snapCount]; if (!rb->valid) { rb->valid = qtrue; rb->numSnaps = di.numSnaps; rb->seekPoint = FS_FTell(clc.demofile); memcpy(&rb->cl, &cl, sizeof(clientActive_t)); memcpy(&rb->clc, &clc, sizeof(clientConnection_t)); memcpy(&rb->cls, &cls, sizeof(clientStatic_t)); } di.snapCount++; } keep_reading: #endif // get the sequence number r = FS_Read(&s, 4, clc.demofile); if (r != 4) { CL_DemoCompleted(); return; } clc.serverMessageSequence = LittleLong(s); // init the message MSG_Init(&buf, bufData, sizeof(bufData)); // get the length r = FS_Read(&buf.cursize, 4, clc.demofile); if (r != 4) { CL_DemoCompleted(); return; } buf.cursize = LittleLong(buf.cursize); if (buf.cursize == -1) { CL_DemoCompleted(); return; } if (buf.cursize > buf.maxsize) { Com_FuncDrop("demoMsglen > MAX_MSGLEN"); return; } r = FS_Read(buf.data, buf.cursize, clc.demofile); if (r != buf.cursize) { Com_FuncPrinf("Demo file was truncated.\n"); CL_DemoCompleted(); return; } clc.lastPacketTime = cls.realtime; buf.readcount = 0; CL_ParseServerMessage(&buf); }
qboolean CL_PeekSnapshot(int snapshotNumber, snapshot_t *snapshot) { clSnapshot_t *clSnap; clSnapshot_t csn; int i, count; int origPosition; int cmd; //char *s; char buffer[16]; qboolean success = qfalse; int r; msg_t buf; byte bufData[MAX_MSGLEN]; int j; int lastPacketTimeOrig; int parseEntitiesNumOrig; int currentSnapNum; //int serverMessageSequence; clSnap = &csn; if (!clc.demoplaying) { return qfalse; } if (snapshotNumber <= cl.snap.messageNum) { success = CL_GetSnapshot(snapshotNumber, snapshot); if (!success) { Com_FuncPrinf("snapshot number outside of backup buffer\n"); return qfalse; } return qtrue; } if (snapshotNumber > cl.snap.messageNum + 1) { Com_FuncPrinf("FIXME CL_PeekSnapshot %d > cl.snap.messageNum + 1 (%d)\n", snapshotNumber, cl.snap.messageNum); return qfalse; // FIXME: } parseEntitiesNumOrig = cl.parseEntitiesNum; lastPacketTimeOrig = clc.lastPacketTime; // CL_ReadDemoMessage() origPosition = FS_FTell(clc.demofile); if (origPosition < 0) { // FS_FTell prints the warning ... return qfalse; } currentSnapNum = cl.snap.messageNum; for (j = 0; j < snapshotNumber - currentSnapNum; j++) { // get the sequence number memset(buffer, 0, sizeof(buffer)); r = FS_Read(&buffer, 4, clc.demofile); if (r != 4) { Com_FuncPrinf("couldn't read sequence number\n"); FS_Seek(clc.demofile, origPosition, FS_SEEK_SET); clc.lastPacketTime = lastPacketTimeOrig; cl.parseEntitiesNum = parseEntitiesNumOrig; return qfalse; } //serverMessageSequence = LittleLong(*((int *)buffer)); // init the message memset(&buf, 0, sizeof(msg_t)); MSG_Init(&buf, bufData, sizeof(bufData)); // get the length r = FS_Read(&buf.cursize, 4, clc.demofile); if (r != 4) { Com_FuncPrinf("couldn't get length\n"); FS_Seek(clc.demofile, origPosition, FS_SEEK_SET); clc.lastPacketTime = lastPacketTimeOrig; cl.parseEntitiesNum = parseEntitiesNumOrig; return qfalse; } buf.cursize = LittleLong(buf.cursize); if (buf.cursize == -1) { Com_FuncPrinf("buf.cursize == -1\n"); FS_Seek(clc.demofile, origPosition, FS_SEEK_SET); clc.lastPacketTime = lastPacketTimeOrig; cl.parseEntitiesNum = parseEntitiesNumOrig; return qfalse; } if (buf.cursize > buf.maxsize) { Com_FuncDrop("demoMsglen > MAX_MSGLEN"); return qfalse; } r = FS_Read(buf.data, buf.cursize, clc.demofile); if (r != buf.cursize) { Com_FuncPrinf("Demo file was truncated.\n"); FS_Seek(clc.demofile, origPosition, FS_SEEK_SET); clc.lastPacketTime = lastPacketTimeOrig; cl.parseEntitiesNum = parseEntitiesNumOrig; return qfalse; } clc.lastPacketTime = cls.realtime; buf.readcount = 0; MSG_Bitstream(&buf); // get the reliable sequence acknowledge number MSG_ReadLong(&buf); // parse the message while (qtrue) { if (buf.readcount > buf.cursize) { Com_FuncDrop("read past end of server message"); return qfalse; } cmd = MSG_ReadByte(&buf); if (cmd == svc_EOF) { break; } success = qfalse; switch (cmd) { default: Com_FuncDrop("Illegible server message"); return qfalse; case svc_nop: break; case svc_serverCommand: MSG_ReadLong(&buf); // seq //s = MSG_ReadString(&buf); MSG_ReadString(&buf); break; case svc_gamestate: Com_FuncPrinf("FIXME gamestate\n"); goto alldone; break; case svc_snapshot: // TODO: changed this check if it works CL_ParseSnapshot(&buf); if (cl.snap.valid) { success = qtrue; } break; case svc_download: Com_FuncPrinf("FIXME download\n"); goto alldone; break; } } alldone: if (!success) { Com_FuncPrinf("failed\n"); FS_Seek(clc.demofile, origPosition, FS_SEEK_SET); clc.lastPacketTime = lastPacketTimeOrig; cl.parseEntitiesNum = parseEntitiesNumOrig; return success; } // FIXME other ents not supported yet // if the entities in the frame have fallen out of their // circular buffer, we can't return it if (cl.parseEntitiesNum - clSnap->parseEntitiesNum >= MAX_PARSE_ENTITIES) { Com_FuncPrinf("cl.parseEntitiesNum - clSnap->parseEntitiesNum >= MAX_PARSE_ENTITIES"); FS_Seek(clc.demofile, origPosition, FS_SEEK_SET); clc.lastPacketTime = lastPacketTimeOrig; cl.parseEntitiesNum = parseEntitiesNumOrig; return qtrue; // FIXME if you fix other ents } // write the snapshot snapshot->snapFlags = clSnap->snapFlags; snapshot->serverCommandSequence = clSnap->serverCommandNum; snapshot->ping = clSnap->ping; snapshot->serverTime = clSnap->serverTime; Com_Memcpy(snapshot->areamask, clSnap->areamask, sizeof(snapshot->areamask)); snapshot->ps = clSnap->ps; count = clSnap->numEntities; if (count > MAX_ENTITIES_IN_SNAPSHOT) { Com_FuncPrinf("truncated %i entities to %i\n", count, MAX_ENTITIES_IN_SNAPSHOT); count = MAX_ENTITIES_IN_SNAPSHOT; } snapshot->numEntities = count; for (i = 0; i < count; i++) { snapshot->entities[i] = cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)]; } } FS_Seek(clc.demofile, origPosition, FS_SEEK_SET); clc.lastPacketTime = lastPacketTimeOrig; cl.parseEntitiesNum = parseEntitiesNumOrig; // TODO: configstring changes and server commands!!! return qtrue; }
// Do very shallow parse of the demo (could be extended) just to get times and snapshot count static void CL_ParseDemo(void) { int tstart = 0; int demofile = 0; // Reset our demo data memset(&di, 0, sizeof(di)); // Parse start di.gameStartTime = -1; di.gameEndTime = -1; FS_Seek(clc.demofile, 0, FS_SEEK_SET); tstart = Sys_Milliseconds(); while (qtrue) { int r; msg_t buf; msg_t *msg; byte bufData[MAX_MSGLEN]; int s; int cmd; di.demoPos = FS_FTell(clc.demofile); // get the sequence number r = FS_Read(&s, 4, clc.demofile); if (r != 4) { CL_DemoCompleted(); return; } clc.serverMessageSequence = LittleLong(s); // init the message MSG_Init(&buf, bufData, sizeof(bufData)); // get the length r = FS_Read(&buf.cursize, 4, clc.demofile); if (r != 4) { break; } buf.cursize = LittleLong(buf.cursize); if (buf.cursize == -1) { break; } if (buf.cursize > buf.maxsize) { Com_FuncPrinf("demoMsglen > MAX_MSGLEN"); break; } r = FS_Read(buf.data, buf.cursize, clc.demofile); if (r != buf.cursize) { Com_FuncPrinf("Demo file was truncated.\n"); break; } clc.lastPacketTime = cls.realtime; buf.readcount = 0; // parse msg = &buf; MSG_Bitstream(msg); // get the reliable sequence acknowledge number clc.reliableAcknowledge = MSG_ReadLong(msg); if (clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS) { clc.reliableAcknowledge = clc.reliableSequence; } // parse the message while (qtrue) { if (msg->readcount > msg->cursize) { Com_FuncDrop("read past end of server message"); return; } cmd = MSG_ReadByte(msg); if (cmd == svc_EOF) { break; } // other commands switch (cmd) { default: Com_FuncDrop("Illegible server message %d", cmd); return; case svc_nop: break; case svc_serverCommand: MSG_ReadLong(msg); MSG_ReadString(msg); break; case svc_gamestate: clc.serverCommandSequence = MSG_ReadLong(msg); cl.gameState.dataCount = 1; while (qtrue) { int cmd2 = MSG_ReadByte(msg); if (cmd2 == svc_EOF) { break; } if (cmd2 == svc_configstring) { MSG_ReadShort(msg); MSG_ReadBigString(msg); } else if (cmd2 == svc_baseline) { entityState_t s1, s2; memset(&s1, 0, sizeof(s1)); memset(&s2, 0, sizeof(s2)); MSG_ReadBits(msg, GENTITYNUM_BITS); MSG_ReadDeltaEntity(msg, &s1, &s2, 0); } else { Com_FuncDrop("bad command byte"); return; } } MSG_ReadLong(msg); MSG_ReadLong(msg); break; case svc_snapshot: CL_ParseDemoSnapShotSimple(msg); break; case svc_download: MSG_ReadShort(msg); break; } } if (!cl.snap.valid) { Com_FuncPrinf("!cl.snap.valid\n"); continue; } if (cl.snap.serverTime < cl.oldFrameServerTime) { // ignore snapshots that don't have entities if (cl.snap.snapFlags & SNAPFLAG_NOT_ACTIVE) { continue; } cls.state = CA_ACTIVE; // set the timedelta so we are exactly on this first frame cl.serverTimeDelta = cl.snap.serverTime - cls.realtime; cl.oldServerTime = cl.snap.serverTime; clc.timeDemoBaseTime = cl.snap.serverTime; } cl.oldFrameServerTime = cl.snap.serverTime; if (cl.newSnapshots) { CL_AdjustTimeDelta(); } di.lastServerTime = cl.snap.serverTime; if (di.firstServerTime == 0) { di.firstServerTime = cl.snap.serverTime; Com_FuncPrinf("firstServerTime %d\n", di.firstServerTime); } di.snapsInDemo++; } Com_FuncPrinf("Snaps in demo: %i\n", di.snapsInDemo); Com_FuncPrinf("last serverTime %d total %f minutes\n", cl.snap.serverTime, (cl.snap.serverTime - di.firstServerTime) / 1000.0 / 60.0); Com_FuncPrinf("parse time %f seconds\n", (float)(Sys_Milliseconds() - tstart) / 1000.0); FS_Seek(clc.demofile, 0, FS_SEEK_SET); clc.demoplaying = qfalse; demofile = clc.demofile; CL_ClearState(); Com_Memset(&clc, 0, sizeof(clc)); Com_ClearDownload(); clc.demofile = demofile; cls.state = CA_DISCONNECTED; cl_connectedToPureServer = qfalse; dpi.firstTime = di.firstServerTime; dpi.lastTime = di.lastServerTime; }