Beispiel #1
0
bool C4Record::Rec(C4PacketType eCtrlType, C4ControlPacket *pCtrl, int iFrame) {
  if (!fRecording) return false;
  // create copy
  C4IDPacket Pkt = C4IDPacket(eCtrlType, pCtrl, false);
  if (!Pkt.getPkt()) return false;
  C4ControlPacket *pCtrlCpy = static_cast<C4ControlPacket *>(Pkt.getPkt());
  // prepare for recording
  pCtrlCpy->PreRec(this);
  // record it
  return Rec(iFrame, DecompileToBuf<StdCompilerBinWrite>(Pkt), RCT_CtrlPkt);
}
Beispiel #2
0
void C4PacketList::CompileFunc(StdCompiler *pComp)
{
	// unpack packets
	if (pComp->isCompiler())
	{
		// Read until no further sections available
		while (pComp->Name("IDPacket"))
		{
			// Read the packet
			C4IDPacket *pPkt = new C4IDPacket();
			try
			{
				pComp->Value(*pPkt);
				pComp->NameEnd();
			}
			catch (...)
			{
				delete pPkt;
				throw;
			}
			// Terminator?
			if (!pPkt->getPkt()) { delete pPkt; break; }
			// Add to list
			Add(pPkt);
		}
		pComp->NameEnd();
	}
	else
	{
		// Write all packets
		for (C4IDPacket *pPkt = pFirst; pPkt; pPkt = pPkt->pNext)
			pComp->Value(mkNamingAdapt(*pPkt, "IDPacket"));
		// Terminate, if no naming is available
		if (!pComp->hasNaming())
		{
			C4IDPacket Pkt;
			pComp->Value(mkNamingAdapt(Pkt, "IDPacket"));
		}
	}
}
Beispiel #3
0
void C4Playback::Check(C4RecordChunkType eType, const uint8_t *pData,
                       int iSize) {
  // only if enabled
  if (DoNoDebugRec > 0) return;
  if (Game.FrameCounter < DEBUGREC_START_FRAME) return;

  C4PktDebugRec PktInReplay;
  bool fHasPacketFromHead = false;
#ifdef DEBUGREC_EXTFILE
#ifdef DEBUGREC_EXTFILE_WRITE
  // writing of external debugrec file
  DbgRecFile.Write(&eType, sizeof eType);
  int32_t iSize32 = iSize;
  DbgRecFile.Write(&iSize32, sizeof iSize32);
  DbgRecFile.Write(pData, iSize);
  return;
#else
  int32_t iSize32 = 0;
  C4RecordChunkType eTypeRec = RCT_Undefined;
  DbgRecFile.Read(&eTypeRec, sizeof eTypeRec);
  DbgRecFile.Read(&iSize32, sizeof iSize32);
  if (iSize32) {
    StdBuf buf;
    buf.SetSize(iSize32);
    DbgRecFile.Read(buf.getMData(), iSize32);
    PktInReplay = C4PktDebugRec(eTypeRec, buf);
  }
#endif
#else
  // check debug rec in list
  C4IDPacket *pkt;
  if (pkt = DebugRec.firstPkt()) {
    // copy from list
    PktInReplay = *static_cast<C4PktDebugRec *>(pkt->getPkt());
    DebugRec.Delete(pkt);
  } else {
    // special sync check skip...
    while (currChunk != chunks.end() && currChunk->Type == RCT_CtrlPkt) {
      C4IDPacket Packet(*currChunk->pPkt);
      C4ControlPacket *pCtrlPck =
          static_cast<C4ControlPacket *>(Packet.getPkt());
      assert(!pCtrlPck->Sync());
      Game.Control.ExecControlPacket(Packet.getPktType(), pCtrlPck);
      NextChunk();
    }
    // record end?
    if (currChunk == chunks.end() || currChunk->Type == RCT_End || Finished) {
      Log("DebugRec end: All in sync!");
      ++DoNoDebugRec;
      return;
    }
    // unpack directly from head
    if (currChunk->Type != eType) {
      DebugRecError(FormatString("Playback type %x, this type %x",
                                 currChunk->Type, eType).getData());
      return;
    }
    PktInReplay = *currChunk->pDbg;
    fHasPacketFromHead = true;
  }
#endif  // DEBUGREC_EXTFILE
  // record end?
  if (PktInReplay.getType() == RCT_End) {
    Log("DebugRec end: All in sync (2)!");
    ++DoNoDebugRec;
    return;
  }
  // replay packet is unpacked to PktInReplay now; check it
  if (PktInReplay.getType() != eType) {
    DebugRecError(FormatString("Type %s != %s",
                               GetRecordChunkTypeName(PktInReplay.getType()),
                               GetRecordChunkTypeName(eType)).getData());
    return;
  }
  if (PktInReplay.getSize() != iSize) {
    DebugRecError(FormatString("Size %d != %d", (int)PktInReplay.getSize(),
                               (int)iSize).getData());
  }
  // check packet data
  if (memcmp(PktInReplay.getData(), pData, iSize)) {
    StdStrBuf sErr;
    sErr.Format("DbgRecPkt Type %s, size %d", GetRecordChunkTypeName(eType),
                iSize);
    sErr.Append(" Replay: ");
    StdBuf replay(PktInReplay.getData(), PktInReplay.getSize());
    sErr.Append(GetDbgRecPktData(eType, replay));
    sErr.Append(" Here: ");
    StdBuf here(pData, iSize);
    sErr.Append(GetDbgRecPktData(eType, here));
    DebugRecError(sErr.getData());
  }
  // packet is fine, jump over it
  if (fHasPacketFromHead) NextChunk();
}
Beispiel #4
0
void C4Playback::Strip() {
  // Strip what?
  const bool fStripPlayers = false;
  const bool fStripSyncChecks = false;
  const bool fStripDebugRec = true;
  const bool fCheckCheat = false;
  const bool fStripMessages = true;
  // const bool fCheckEMControl = true;
  const int32_t iEndFrame = -1;
  // Iterate over chunk list
  for (chunks_t::iterator i = chunks.begin(); i != chunks.end();) {
    // Strip rest of record?
    if (iEndFrame >= 0 && i->Frame > iEndFrame) {
      // Remove this and all remaining chunks
      while (i != chunks.end()) {
        i->Delete();
        i = chunks.erase(i);
      }
      // Push new End-Chunk
      C4RecordChunk EndChunk;
      EndChunk.Frame = iEndFrame;
      EndChunk.Type = RCT_End;
      chunks.push_back(EndChunk);
      // Done
      break;
    }
    switch (i->Type) {
      case RCT_Ctrl: {
        // Iterate over controls
        C4Control *pCtrl = i->pCtrl;
        for (C4IDPacket *pPkt = pCtrl->firstPkt(), *pNext; pPkt; pPkt = pNext) {
          pNext = pCtrl->nextPkt(pPkt);
          switch (pPkt->getPktType()) {
            // Player join: Strip player file (if possible)
            case CID_JoinPlr:
              if (fStripPlayers) {
                C4ControlJoinPlayer *pJoinPlr =
                    static_cast<C4ControlJoinPlayer *>(pPkt->getPkt());
                pJoinPlr->Strip();
              }
              break;
            // EM commands: May be cheats, so log them
            case CID_Script:
            case CID_EMMoveObj:
            case CID_EMDrawTool:
              if (fCheckCheat)
                Log(DecompileToBuf<StdCompilerINIWrite>(
                        mkNamingAdapt(*pPkt, FormatString("Frame %d", i->Frame)
                                                 .getData())).getData());
              break;
            // Strip sync check
            case CID_SyncCheck:
              if (fStripSyncChecks) {
                i->pCtrl->Remove(pPkt);
              }
              break;
          }
        }
        // Strip empty control lists (always)
        if (!pCtrl->firstPkt()) {
          i->Delete();
          i = chunks.erase(i);
        } else
          i++;
      } break;
      case RCT_CtrlPkt: {
        bool fStripThis = false;
        switch (i->pPkt->getPktType()) {
          // EM commands: May be cheats, so log them
          case CID_Script:
          case CID_EMMoveObj:
          case CID_EMDrawTool:
            if (fCheckCheat)
              Log(DecompileToBuf<StdCompilerINIWrite>(
                      mkNamingAdapt(*i->pPkt, FormatString("Frame %d", i->Frame)
                                                  .getData())).getData());
            break;
          // Strip some stuff
          case CID_SyncCheck:
            if (fStripSyncChecks) fStripThis = true;
            break;
          case CID_Message:
            if (fStripMessages) fStripThis = true;
            break;
        }
        if (fStripThis) {
          i->Delete();
          i = chunks.erase(i);
        } else
          i++;
      } break;
      case RCT_End:
        i++;
        break;
      default:
        // Strip debugrec
        if (fStripDebugRec) {
          i->Delete();
          i = chunks.erase(i);
        } else
          i++;
    }
  }
}