2016-03-12 01:20:51 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation
|
|
|
|
|
|
|
|
|
|
|
|
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "EMsgBuffer.h"
|
|
|
|
|
|
|
|
#include <Engine/Math/Functions.h>
|
|
|
|
#include <Engine/Base/Memory.h>
|
|
|
|
#include <Engine/Math/Quaternion.h>
|
|
|
|
|
|
|
|
|
|
|
|
void AngleToUL(ANGLE3D &Angle,ULONG &ulResult)
|
|
|
|
{
|
|
|
|
Quaternion<float> qQuat;
|
|
|
|
FLOAT3D Axis;
|
|
|
|
float fRotAngle;
|
|
|
|
ANGLE3D AxisAngles;
|
|
|
|
UBYTE ubDir;
|
|
|
|
UWORD swAngle;
|
|
|
|
|
|
|
|
qQuat.FromEuler(Angle);
|
|
|
|
qQuat.ToAxisAngle(Axis,fRotAngle);
|
|
|
|
Axis.Normalize();
|
|
|
|
DirectionVectorToAngles(Axis,AxisAngles);
|
|
|
|
|
|
|
|
|
|
|
|
ubDir = (UBYTE) (AxisAngles(1)/360*255);
|
|
|
|
ulResult = ubDir;
|
|
|
|
ubDir = (UBYTE) (AxisAngles(2)/90*127);
|
|
|
|
ulResult = ulResult << 8;
|
|
|
|
ulResult |= ubDir;
|
2016-04-06 22:43:08 +02:00
|
|
|
swAngle = (UWORD) (SWORD) (fRotAngle * 180); // after rounding, angle is precise up to 1/180 degrees (65536/360 ~ 180)
|
2016-03-11 14:57:17 +01:00
|
|
|
ulResult = (ulResult << 16) | swAngle;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void ULToAngle(ULONG &ulResult,ANGLE3D &Angle)
|
|
|
|
{
|
|
|
|
Quaternion<float> qQuat;
|
|
|
|
FLOAT3D Axis;
|
|
|
|
float fRotAngle;
|
|
|
|
ANGLE3D AxisAngles;
|
|
|
|
UBYTE ubDir;
|
|
|
|
UWORD swAngle;
|
|
|
|
Matrix<float,3,3> mRotMatrix;
|
|
|
|
|
|
|
|
swAngle = ulResult & 0x0000FFFF;
|
|
|
|
fRotAngle = swAngle / 180.0f;
|
|
|
|
ulResult = ulResult >> 16;
|
|
|
|
ubDir = ulResult & 0x000000FF;
|
|
|
|
AxisAngles(2) = ((FLOAT) ubDir)*90/127;
|
|
|
|
ulResult = ulResult >> 8;
|
|
|
|
ubDir = ulResult & 0x000000FF;
|
|
|
|
AxisAngles(1) = ((FLOAT) ubDir)*360/255;
|
|
|
|
AxisAngles(3) = 0;
|
|
|
|
|
|
|
|
AnglesToDirectionVector(AxisAngles,Axis);
|
|
|
|
qQuat.FromAxisAngle(Axis,fRotAngle);
|
|
|
|
qQuat.ToMatrix(mRotMatrix);
|
|
|
|
|
|
|
|
DecomposeRotationMatrixNoSnap(Angle,mRotMatrix);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::WritePlacement(ULONG &ulEntityID,CPlacement3D &plPlacement)
|
|
|
|
{
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
ULONG ulShrunkAngle;
|
|
|
|
SWORD swH,swP,swB;
|
|
|
|
|
|
|
|
|
|
|
|
em_ulType = EMT_SETPLACEMENT;
|
|
|
|
em_ubSize = sizeof(FLOAT3D) + sizeof(ULONG);
|
|
|
|
em_ulEntityID = ulEntityID;
|
|
|
|
|
|
|
|
swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5);
|
|
|
|
swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5);
|
|
|
|
swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5);
|
|
|
|
|
|
|
|
ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21);
|
|
|
|
ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11);
|
|
|
|
ulShrunkAngle |= (((ULONG) swB) & 0x000007FF);
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D));
|
|
|
|
pubMarker += sizeof(FLOAT3D);
|
|
|
|
memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG));
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::ReadPlacement(ULONG &ulEntityID,CPlacement3D &plPlacement)
|
|
|
|
{
|
|
|
|
ASSERT (em_ulType == EMT_SETPLACEMENT);
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
ULONG ulShrunkAngle;
|
|
|
|
SWORD swH,swP,swB;
|
|
|
|
|
|
|
|
|
|
|
|
ulEntityID = em_ulEntityID;
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D));
|
|
|
|
pubMarker += sizeof(FLOAT3D);
|
|
|
|
memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG));
|
|
|
|
|
|
|
|
swB = (SWORD) ulShrunkAngle & 0x000007FF;
|
|
|
|
swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF;
|
|
|
|
swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF;
|
|
|
|
|
|
|
|
plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180;
|
|
|
|
plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90;
|
|
|
|
plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::WriteEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
|
|
|
|
{
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
|
|
|
|
em_ulType = EMT_EVENT;
|
|
|
|
em_ubSize = sizeof(UWORD) + uwDataSize;
|
|
|
|
em_ulEntityID = ulEntityID;
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(pubMarker,&uwEventCode,sizeof(SLONG));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
memcpy(pubMarker,pvEventData,uwDataSize);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::ReadEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
|
|
|
|
{
|
|
|
|
ASSERT (em_ulType == EMT_EVENT);
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(&uwEventCode,pubMarker,sizeof(SLONG));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
uwDataSize = em_ubSize - sizeof(ULONG) - sizeof(UWORD);
|
|
|
|
memcpy(pvEventData,pubMarker,uwDataSize);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::WriteEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
|
|
|
|
{
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
ULONG ulShrunkAngle;
|
|
|
|
SWORD swH,swP,swB;
|
|
|
|
|
|
|
|
em_ulType = EMT_CREATE;
|
|
|
|
em_ubSize = sizeof(FLOAT3D) + sizeof(ULONG) + sizeof(UWORD) + sizeof(UWORD) + uwDataSize;
|
|
|
|
em_ulEntityID = ulEntityID;
|
|
|
|
|
|
|
|
swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5);
|
|
|
|
swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5);
|
|
|
|
swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5);
|
|
|
|
|
|
|
|
ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21);
|
|
|
|
ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11);
|
|
|
|
ulShrunkAngle |= (((ULONG) swB) & 0x000007FF);
|
|
|
|
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D));
|
|
|
|
pubMarker += sizeof(FLOAT3D);
|
|
|
|
memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG));
|
|
|
|
pubMarker += sizeof(ULONG);
|
|
|
|
memcpy(pubMarker,&uwEntityClassID,sizeof(UWORD));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
memcpy(pubMarker,&uwEventCode,sizeof(UWORD));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
memcpy(pubMarker,pvEventData,uwDataSize);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void CEntityMessage::ReadEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
|
|
|
|
{
|
|
|
|
ASSERT (em_ulType == EMT_CREATE);
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
ULONG ulShrunkAngle;
|
|
|
|
SWORD swH,swP,swB;
|
|
|
|
|
|
|
|
ulEntityID = em_ulEntityID;
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D));
|
|
|
|
pubMarker += sizeof(FLOAT3D);
|
|
|
|
memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG));
|
|
|
|
|
|
|
|
swB = (SWORD) ulShrunkAngle & 0x000007FF;
|
|
|
|
swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF;
|
|
|
|
swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF;
|
|
|
|
|
|
|
|
plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180;
|
|
|
|
plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90;
|
|
|
|
plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180;
|
|
|
|
|
|
|
|
pubMarker += sizeof(ULONG);
|
|
|
|
memcpy(&uwEntityClassID,pubMarker,sizeof(UWORD));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
memcpy(&uwEventCode,pubMarker,sizeof(UWORD));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
uwDataSize = em_ubSize - sizeof(FLOAT3D) - sizeof(ULONG) - sizeof(UWORD) - sizeof(UWORD);
|
|
|
|
memcpy(pubMarker,pvEventData,uwDataSize);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::WriteEntityDestroy(ULONG &ulEntityID)
|
|
|
|
{
|
|
|
|
|
|
|
|
em_ulType = EMT_DESTROY;
|
|
|
|
em_ubSize = 0;
|
|
|
|
em_ulEntityID = ulEntityID;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::ReadEntityDestroy(ULONG &ulEntityID)
|
|
|
|
{
|
|
|
|
ASSERT (em_ulType == EMT_DESTROY);
|
|
|
|
|
|
|
|
ulEntityID = em_ulEntityID;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CEntityMessage::WriteEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
|
|
|
|
{
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
ULONG ulShrunkAngle;
|
|
|
|
SWORD swH,swP,swB;
|
|
|
|
|
|
|
|
em_ulType = EMT_COPY;
|
|
|
|
em_ubSize = sizeof(ULONG) + sizeof(FLOAT3D) + sizeof(ULONG) + sizeof(UWORD) + uwDataSize;
|
|
|
|
em_ulEntityID = ulSourceEntityID;
|
|
|
|
|
|
|
|
swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5);
|
|
|
|
swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5);
|
|
|
|
swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5);
|
|
|
|
|
|
|
|
ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21);
|
|
|
|
ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11);
|
|
|
|
ulShrunkAngle |= (((ULONG) swB) & 0x000007FF);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(pubMarker,&ulTargetEntityID,sizeof(ULONG));
|
|
|
|
pubMarker += sizeof(ULONG);
|
|
|
|
memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D));
|
|
|
|
pubMarker += sizeof(FLOAT3D);
|
|
|
|
memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG));
|
|
|
|
pubMarker += sizeof(ULONG);
|
|
|
|
memcpy(pubMarker,&uwEventCode,sizeof(SLONG));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
memcpy(pubMarker,pvEventData,uwDataSize);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void CEntityMessage::ReadEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
|
|
|
|
{
|
|
|
|
ASSERT (em_ulType == EMT_COPY);
|
|
|
|
UBYTE *pubMarker;
|
|
|
|
ULONG ulShrunkAngle;
|
|
|
|
SWORD swH,swP,swB;
|
|
|
|
|
|
|
|
ulSourceEntityID = em_ulEntityID;
|
|
|
|
|
|
|
|
pubMarker = em_aubMessage;
|
|
|
|
memcpy(&ulTargetEntityID,pubMarker,sizeof(ULONG));
|
|
|
|
pubMarker += sizeof(ULONG);
|
|
|
|
memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D));
|
|
|
|
pubMarker += sizeof(FLOAT3D);
|
|
|
|
memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG));
|
|
|
|
|
|
|
|
swB = (SWORD) ulShrunkAngle & 0x000007FF;
|
|
|
|
swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF;
|
|
|
|
swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF;
|
|
|
|
|
|
|
|
plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180;
|
|
|
|
plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90;
|
|
|
|
plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180;
|
|
|
|
|
|
|
|
pubMarker += sizeof(ULONG);
|
|
|
|
memcpy(&uwEventCode,pubMarker,sizeof(SLONG));
|
|
|
|
pubMarker += sizeof(UWORD);
|
|
|
|
uwDataSize = em_ubSize - sizeof(ULONG) - sizeof(FLOAT3D) - sizeof(ULONG) - sizeof(UWORD);
|
|
|
|
memcpy(pubMarker,pvEventData,uwDataSize);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CEMsgBuffer::CEMsgBuffer()
|
|
|
|
{
|
|
|
|
emb_uwNumTickMarkers = 0;
|
|
|
|
emb_iFirstTickMarker = 0;
|
|
|
|
emb_iCurrentTickMarker = 0;
|
|
|
|
emb_fCurrentTickTime = -1;
|
|
|
|
|
|
|
|
for (int i=0;i<MAX_TICKS_KEPT;i++) {
|
|
|
|
emb_atmTickMarkers[i].tm_slTickOffset = -1;
|
|
|
|
emb_atmTickMarkers[i].tm_fTickTime = -1;
|
|
|
|
emb_atmTickMarkers[i].tm_ubAcknowledgesExpected = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CEMsgBuffer::~CEMsgBuffer ()
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEMsgBuffer::Clear(void)
|
|
|
|
{
|
|
|
|
emb_uwNumTickMarkers = 0;
|
|
|
|
emb_iFirstTickMarker = 0;
|
|
|
|
emb_iCurrentTickMarker = 0;
|
|
|
|
emb_fCurrentTickTime = -1;
|
|
|
|
|
|
|
|
for (int i=0;i<MAX_TICKS_KEPT;i++) {
|
|
|
|
emb_atmTickMarkers[i].tm_slTickOffset = -1;
|
|
|
|
emb_atmTickMarkers[i].tm_fTickTime = -1;
|
|
|
|
emb_atmTickMarkers[i].tm_ubAcknowledgesExpected = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bu_slWriteOffset = 0;
|
|
|
|
bu_slReadOffset = 0;
|
|
|
|
|
|
|
|
bu_slFree = bu_slSize;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEMsgBuffer::WriteMessage(CEntityMessage &emEntityMessage)
|
|
|
|
{
|
|
|
|
// a tick must have started before any messages are generated
|
|
|
|
ASSERT (emb_uwNumTickMarkers > 0);
|
|
|
|
ULONG ulTemp;
|
|
|
|
int iTickMarker;
|
|
|
|
|
|
|
|
ulTemp = emEntityMessage.em_ulEntityID | (emEntityMessage.em_ulType << 24);
|
|
|
|
WriteBytes(&(ulTemp),sizeof(ULONG));
|
|
|
|
WriteBytes(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize));
|
|
|
|
if (emEntityMessage.em_ubSize > 0) {
|
|
|
|
WriteBytes(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
iTickMarker = emb_iCurrentTickMarker-1;
|
|
|
|
if (iTickMarker < 0) iTickMarker += MAX_TICKS_KEPT;
|
|
|
|
emb_atmTickMarkers[iTickMarker].tm_uwNumMessages++;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::ReadMessage(CEntityMessage &emEntityMessage)
|
|
|
|
{
|
|
|
|
ULONG ulTemp;
|
|
|
|
|
|
|
|
if (bu_slReadOffset == bu_slWriteOffset) {
|
|
|
|
return EMB_ERR_BUFFER_EMPTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReadBytes(&(ulTemp),sizeof(ULONG));
|
|
|
|
emEntityMessage.em_ulType = ulTemp >> 24;
|
|
|
|
emEntityMessage.em_ulEntityID = ulTemp & 0x007FFFFF;
|
|
|
|
ReadBytes(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize));
|
|
|
|
if (emEntityMessage.em_ubSize > 0) {
|
|
|
|
ReadBytes(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::PeekMessageAtOffset(CEntityMessage &emEntityMessage,SLONG &slTickOffset)
|
|
|
|
{
|
|
|
|
ASSERT(slTickOffset >= 0 && slTickOffset <= bu_slSize);
|
|
|
|
ULONG ulTemp;
|
|
|
|
|
|
|
|
PeekBytesAtOffset(&(ulTemp),sizeof(ULONG),slTickOffset);
|
|
|
|
emEntityMessage.em_ulType = ulTemp >> 24;
|
|
|
|
emEntityMessage.em_ulEntityID = ulTemp & 0x007FFFFF;
|
|
|
|
PeekBytesAtOffset(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize),slTickOffset);
|
|
|
|
if (emEntityMessage.em_ubSize > 0) {
|
|
|
|
PeekBytesAtOffset(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize,slTickOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::StartNewTick(float fTickTime)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (emb_uwNumTickMarkers >= MAX_TICKS_KEPT) {
|
|
|
|
return EMB_ERR_MAX_TICKS;
|
|
|
|
}
|
|
|
|
|
|
|
|
emb_atmTickMarkers[emb_iCurrentTickMarker].tm_fTickTime = fTickTime;
|
|
|
|
emb_atmTickMarkers[emb_iCurrentTickMarker].tm_slTickOffset = bu_slWriteOffset;
|
|
|
|
emb_atmTickMarkers[emb_iCurrentTickMarker].tm_ubAcknowledgesExpected = 0;
|
|
|
|
emb_atmTickMarkers[emb_iCurrentTickMarker].tm_uwNumMessages = 0;
|
|
|
|
|
|
|
|
emb_uwNumTickMarkers++;
|
|
|
|
emb_iCurrentTickMarker++;
|
|
|
|
emb_iCurrentTickMarker %= MAX_TICKS_KEPT;
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::SetCurrentTick(float fTickTime)
|
|
|
|
{
|
|
|
|
int iErr;
|
|
|
|
INDEX iTickIndex;
|
|
|
|
|
|
|
|
iErr = GetTickIndex(fTickTime,iTickIndex);
|
|
|
|
if (iErr != EMB_SUCCESS_OK) {
|
|
|
|
return iErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
emb_iCurrentTickMarker = iTickIndex;
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::GetTickIndex(float fTickTime,INDEX &iTickIndex)
|
|
|
|
{
|
|
|
|
INDEX iTickMarker;
|
|
|
|
|
|
|
|
// 0.025 should be _pTimer->TickQuantum/2
|
|
|
|
for (int i=0;i<emb_uwNumTickMarkers;i++) {
|
|
|
|
iTickMarker = (i + emb_iFirstTickMarker) % MAX_TICKS_KEPT;
|
|
|
|
if (fabs(emb_atmTickMarkers[iTickMarker].tm_fTickTime - fTickTime) < 0.025) {
|
|
|
|
iTickIndex = iTickMarker;
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
iTickIndex = -1;
|
|
|
|
|
|
|
|
return EMB_ERR_NOT_IN_BUFFER;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::GetTickOffset(float fTickTime,SLONG &slTickOffset)
|
|
|
|
{
|
|
|
|
INDEX iTickMarker;
|
|
|
|
// 0.025 should be _pTimer->TickQuantum/2
|
|
|
|
for (int i=0;i<emb_uwNumTickMarkers;i++) {
|
|
|
|
iTickMarker = (i + emb_iFirstTickMarker) % MAX_TICKS_KEPT;
|
|
|
|
if (fabs(emb_atmTickMarkers[iTickMarker].tm_fTickTime - fTickTime) < 0.025) {
|
|
|
|
slTickOffset = emb_atmTickMarkers[iTickMarker].tm_slTickOffset;
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
slTickOffset = -1.0f;
|
|
|
|
|
|
|
|
return EMB_ERR_NOT_IN_BUFFER;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::GetNextTickTime(float fTickTime,float &fNextTickTime)
|
|
|
|
{
|
|
|
|
INDEX iTickIndex;
|
|
|
|
int iErr;
|
|
|
|
|
|
|
|
if (fTickTime < 0) {
|
|
|
|
if (emb_uwNumTickMarkers > 0) {
|
|
|
|
fNextTickTime = emb_atmTickMarkers[0].tm_fTickTime;
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
} else {
|
|
|
|
return EMB_ERR_NOT_IN_BUFFER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fTickTime < emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime) {
|
|
|
|
fNextTickTime = emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime;
|
|
|
|
return SUCCESS_OK;
|
|
|
|
};
|
|
|
|
|
|
|
|
iErr = GetTickIndex(fTickTime,iTickIndex);
|
|
|
|
if (iErr != EMB_SUCCESS_OK) {
|
|
|
|
return iErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
iTickIndex = (iTickIndex + 1) % MAX_TICKS_KEPT;
|
|
|
|
|
|
|
|
fNextTickTime = emb_atmTickMarkers[iTickIndex].tm_fTickTime;
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::RequestTickAcknowledge(float fTickTime,UBYTE ubNumAcknowledges)
|
|
|
|
{
|
|
|
|
ASSERT (fTickTime >= 0);
|
|
|
|
INDEX iTickIndex;
|
|
|
|
int iErr;
|
|
|
|
|
|
|
|
iErr = GetTickIndex(fTickTime,iTickIndex);
|
|
|
|
if (iErr == EMB_SUCCESS_OK) {
|
|
|
|
emb_atmTickMarkers[iTickIndex].tm_ubAcknowledgesExpected += ubNumAcknowledges;
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
}
|
|
|
|
return iErr;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::ReceiveTickAcknowledge(float fTickTime)
|
|
|
|
{
|
|
|
|
ASSERT (fTickTime >= 0);
|
|
|
|
INDEX iTickIndex;
|
|
|
|
INDEX iFirst;
|
|
|
|
int iErr;
|
|
|
|
int iNumMark = emb_uwNumTickMarkers;
|
|
|
|
|
|
|
|
iErr = GetTickIndex(fTickTime,iTickIndex);
|
|
|
|
if (iErr == EMB_SUCCESS_OK) {
|
|
|
|
iFirst = emb_iFirstTickMarker;
|
|
|
|
emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected--;
|
|
|
|
while (iFirst!=iTickIndex) {
|
|
|
|
iFirst++;
|
|
|
|
iFirst%=MAX_TICKS_KEPT;
|
|
|
|
emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
iFirst = emb_iFirstTickMarker;
|
|
|
|
if (emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected == 0 && iNumMark != 0) {
|
|
|
|
while (emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected == 0 && iNumMark != 0) {
|
|
|
|
if (iNumMark > 0) {
|
|
|
|
iNumMark--;
|
|
|
|
iFirst++;
|
|
|
|
iFirst %= MAX_TICKS_KEPT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MoveToStartOfTick(emb_atmTickMarkers[iFirst].tm_fTickTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
}
|
|
|
|
return iErr;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// does not advance the read offset - access is random, not sequential
|
|
|
|
int CEMsgBuffer::ReadTick(float fTickTime,const void *pv, SLONG &slSize)
|
|
|
|
{
|
|
|
|
ASSERT (slSize>0);
|
|
|
|
ASSERT (pv != NULL);
|
|
|
|
ASSERT (fTickTime >= 0);
|
|
|
|
int iErr;
|
|
|
|
INDEX iTickIndex,iNextTickIndex;
|
|
|
|
|
|
|
|
|
|
|
|
iErr = GetTickIndex(fTickTime,iTickIndex);
|
|
|
|
|
|
|
|
if (iErr != EMB_SUCCESS_OK) {
|
|
|
|
return iErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iTickIndex >= (emb_iFirstTickMarker + emb_uwNumTickMarkers - 1)) {
|
|
|
|
return EMB_ERR_TICK_NOT_COMPLETE;
|
|
|
|
}
|
|
|
|
|
|
|
|
iNextTickIndex = (iTickIndex + 1) % MAX_TICKS_KEPT;
|
|
|
|
SLONG slTickSize = emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset - emb_atmTickMarkers[iTickIndex].tm_slTickOffset;
|
|
|
|
// if not wrapping
|
|
|
|
if ( slTickSize > 0) {
|
|
|
|
if (slSize < slTickSize) {
|
|
|
|
return EMB_ERR_BUFFER_TOO_SMALL;
|
|
|
|
}
|
|
|
|
slSize = slTickSize;
|
|
|
|
memcpy((UBYTE*)pv,bu_pubBuffer+emb_atmTickMarkers[iTickIndex].tm_slTickOffset,slTickSize);
|
|
|
|
} else {
|
|
|
|
if (slSize < (bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset) + emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset-1) {
|
|
|
|
return EMB_ERR_BUFFER_TOO_SMALL;
|
|
|
|
}
|
|
|
|
slSize = (bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset) + emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset;
|
|
|
|
// copy data from the start of this ick to the end of the bufer
|
|
|
|
memcpy((UBYTE*)pv,bu_pubBuffer+emb_atmTickMarkers[iTickIndex].tm_slTickOffset,bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset);
|
|
|
|
// copy datafrom the start of the buffer to the start of next tick
|
|
|
|
memcpy(((UBYTE*)pv)+bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset,bu_pubBuffer,emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void CEMsgBuffer::WriteTick(float tm_fTickTime,const void *pv, SLONG slSize)
|
|
|
|
{
|
|
|
|
ASSERT(slSize>=0 && pv!=NULL);
|
|
|
|
|
|
|
|
StartNewTick(tm_fTickTime);
|
|
|
|
WriteBytes(pv,slSize);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int CEMsgBuffer::MoveToStartOfTick(float fTickTime)
|
|
|
|
{
|
|
|
|
int iErr;
|
|
|
|
INDEX iTickIndex;
|
|
|
|
|
|
|
|
ASSERT(fTickTime >= emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime);
|
|
|
|
|
|
|
|
iErr = GetTickIndex(fTickTime,iTickIndex);
|
|
|
|
if (iErr != EMB_SUCCESS_OK) {
|
|
|
|
return iErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if not wrapping
|
|
|
|
if (iTickIndex >= emb_iFirstTickMarker) {
|
|
|
|
emb_uwNumTickMarkers -= iTickIndex - emb_iFirstTickMarker;
|
|
|
|
} else {
|
|
|
|
emb_uwNumTickMarkers -= iTickIndex + (MAX_TICKS_KEPT - emb_iFirstTickMarker);
|
|
|
|
}
|
|
|
|
|
|
|
|
emb_iFirstTickMarker = iTickIndex;
|
|
|
|
|
|
|
|
if (bu_slReadOffset <= emb_atmTickMarkers[iTickIndex].tm_slTickOffset) {
|
|
|
|
bu_slFree += emb_atmTickMarkers[iTickIndex].tm_slTickOffset - bu_slReadOffset;
|
|
|
|
} else {
|
|
|
|
bu_slFree += (bu_slSize - bu_slReadOffset) + emb_atmTickMarkers[iTickIndex].tm_slTickOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
bu_slReadOffset = emb_atmTickMarkers[iTickIndex].tm_slTickOffset;
|
|
|
|
|
|
|
|
|
|
|
|
return EMB_SUCCESS_OK;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// expand buffer to be given number of bytes in size
|
|
|
|
void CEMsgBuffer::Expand(SLONG slNewSize)
|
|
|
|
{
|
|
|
|
ASSERT(slNewSize>0);
|
|
|
|
ASSERT(bu_slSize>=0);
|
|
|
|
// if not already allocated
|
|
|
|
if (bu_slSize==0) {
|
|
|
|
// allocate a new empty buffer
|
|
|
|
ASSERT(bu_pubBuffer==NULL);
|
|
|
|
bu_pubBuffer = (UBYTE*)AllocMemory(slNewSize);
|
|
|
|
bu_slWriteOffset = 0;
|
|
|
|
bu_slReadOffset = 0;
|
|
|
|
bu_slFree = slNewSize;
|
|
|
|
bu_slSize = slNewSize;
|
|
|
|
|
|
|
|
// if already allocated
|
|
|
|
} else {
|
|
|
|
ASSERT(slNewSize>bu_slSize);
|
|
|
|
SLONG slSizeDiff = slNewSize-bu_slSize;
|
|
|
|
ASSERT(bu_pubBuffer!=NULL);
|
|
|
|
// grow buffer
|
|
|
|
GrowMemory((void**)&bu_pubBuffer, slNewSize);
|
|
|
|
|
|
|
|
cout << "EXPAND!\n";
|
|
|
|
// if buffer is currently wrapping
|
|
|
|
if (bu_slReadOffset>bu_slWriteOffset||bu_slFree==0) {
|
|
|
|
cout << "WRAP!\n";
|
|
|
|
// move part at the end of buffer to the end
|
|
|
|
memmove(bu_pubBuffer+bu_slReadOffset+slSizeDiff, bu_pubBuffer+bu_slReadOffset,bu_slSize-bu_slReadOffset);
|
|
|
|
for (int i=0;i<MAX_TICKS_KEPT;i++) {
|
|
|
|
if (emb_atmTickMarkers[i].tm_slTickOffset >= bu_slReadOffset) {
|
|
|
|
emb_atmTickMarkers[i].tm_slTickOffset += slSizeDiff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bu_slReadOffset+=slSizeDiff;
|
|
|
|
}
|
|
|
|
bu_slFree += slNewSize-bu_slSize;
|
|
|
|
bu_slSize = slNewSize;
|
|
|
|
|
|
|
|
ASSERT(bu_slReadOffset>=0 && bu_slReadOffset<bu_slSize);
|
|
|
|
ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// write bytes to buffer
|
|
|
|
void CEMsgBuffer::WriteBytes(const void *pv, SLONG slSize)
|
|
|
|
{
|
|
|
|
BOOL bWraping = FALSE;
|
|
|
|
SLONG slOldReadOffset = bu_slReadOffset;
|
|
|
|
|
|
|
|
// if buffer is currently wrapping
|
|
|
|
|
|
|
|
ASSERT(slSize>=0 && pv!=NULL);
|
|
|
|
// if there is nothing to write
|
|
|
|
|
|
|
|
if (slSize==0) {
|
|
|
|
// do nothing
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// check for errors
|
|
|
|
if (slSize<0) {
|
|
|
|
cout << "WARNING: WriteBytes(): slSize<0\n!";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if there is not enough free space
|
|
|
|
if (bu_slFree<slSize) {
|
|
|
|
SLONG slSizeDiff;
|
|
|
|
SLONG slNewSize;
|
|
|
|
slNewSize = bu_slSize + ((slSize-bu_slFree + bu_slAllocationStep - 1) / bu_slAllocationStep) * bu_slAllocationStep;
|
|
|
|
slSizeDiff = slNewSize - bu_slSize;
|
|
|
|
|
|
|
|
// if buffer is currently wrapping
|
|
|
|
// if (bu_slReadOffset>bu_slWriteOffset||bu_slFree==0) {
|
|
|
|
// bWraping = TRUE;
|
|
|
|
// }
|
|
|
|
// expand the buffer
|
|
|
|
Expand(slNewSize);
|
|
|
|
|
|
|
|
|
|
|
|
ASSERT(bu_slFree>=slSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
UBYTE *pub = (UBYTE*)pv;
|
|
|
|
|
|
|
|
// write part of block at the end of buffer
|
|
|
|
SLONG slSizeEnd = __min(bu_slSize-bu_slWriteOffset, slSize);
|
|
|
|
memcpy(bu_pubBuffer+bu_slWriteOffset, pub, slSizeEnd);
|
|
|
|
pub+=slSizeEnd;
|
|
|
|
memcpy(bu_pubBuffer, pub, slSize-slSizeEnd);
|
|
|
|
// move write pointer
|
|
|
|
bu_slWriteOffset+=slSize;
|
|
|
|
bu_slWriteOffset%=bu_slSize;
|
|
|
|
bu_slFree-=slSize;
|
|
|
|
|
|
|
|
ASSERT(bu_slWriteOffset>=0 && bu_slWriteOffset<bu_slSize);
|
|
|
|
ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SLONG CEMsgBuffer::PeekBytes(const void *pv, SLONG slSize)
|
|
|
|
{
|
|
|
|
ASSERT(slSize>0 && pv!=NULL);
|
|
|
|
UBYTE *pub = (UBYTE*)pv;
|
|
|
|
|
|
|
|
// clamp size to amount of bytes actually in the buffer
|
|
|
|
SLONG slUsed = bu_slSize-bu_slFree;
|
|
|
|
if (slUsed<slSize) {
|
|
|
|
slSize = slUsed;
|
|
|
|
}
|
|
|
|
// if there is nothing to read
|
|
|
|
if (slSize==0) {
|
|
|
|
// do nothing
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read part of block after read pointer to the end of buffer
|
|
|
|
SLONG slSizeEnd = __min(bu_slSize-bu_slReadOffset, slSize);
|
|
|
|
memcpy(pub, bu_pubBuffer+bu_slReadOffset, slSizeEnd);
|
|
|
|
pub+=slSizeEnd;
|
|
|
|
// if that is not all
|
|
|
|
if (slSizeEnd<slSize) {
|
|
|
|
// read rest from start of buffer
|
|
|
|
memcpy(pub, bu_pubBuffer, slSize-slSizeEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(bu_slReadOffset>=0 && bu_slReadOffset<bu_slSize);
|
|
|
|
ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
|
|
|
|
|
|
|
|
return slSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SLONG CEMsgBuffer::PeekBytesAtOffset(const void *pv, SLONG slSize,SLONG &slTickOffset)
|
|
|
|
{
|
|
|
|
ASSERT(slSize>0 && pv!=NULL);
|
|
|
|
UBYTE *pub = (UBYTE*)pv;
|
|
|
|
|
|
|
|
// clamp size to amount of bytes actually in the buffer
|
|
|
|
SLONG slUsed = bu_slSize-bu_slFree;
|
|
|
|
if (slUsed<slSize) {
|
|
|
|
slSize = slUsed;
|
|
|
|
}
|
|
|
|
// if there is nothing to read
|
|
|
|
if (slSize==0) {
|
|
|
|
// do nothing
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read part of block after read pointer to the end of buffer
|
|
|
|
SLONG slSizeEnd = __min(bu_slSize-slTickOffset, slSize);
|
|
|
|
memcpy(pub, bu_pubBuffer+slTickOffset, slSizeEnd);
|
|
|
|
pub+=slSizeEnd;
|
|
|
|
slTickOffset += slSizeEnd;
|
|
|
|
// if that is not all
|
|
|
|
if (slSizeEnd<slSize) {
|
|
|
|
// read rest from start of buffer
|
|
|
|
memcpy(pub, bu_pubBuffer, slSize-slSizeEnd);
|
|
|
|
slTickOffset = slSize - slSizeEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
slTickOffset %= bu_slSize;
|
|
|
|
ASSERT(slTickOffset>=0 && slTickOffset<bu_slSize);
|
|
|
|
ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
|
|
|
|
|
|
|
|
return slSize;
|
|
|
|
}
|