EMsgBuffer.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdafx.h"
  13. #include "EMsgBuffer.h"
  14. #include <Engine/Math/Functions.h>
  15. #include <Engine/Base/Memory.h>
  16. #include <Engine/Math/Quaternion.h>
  17. void AngleToUL(ANGLE3D &Angle,ULONG &ulResult)
  18. {
  19. Quaternion<float> qQuat;
  20. FLOAT3D Axis;
  21. float fRotAngle;
  22. ANGLE3D AxisAngles;
  23. UBYTE ubDir;
  24. UWORD swAngle;
  25. qQuat.FromEuler(Angle);
  26. qQuat.ToAxisAngle(Axis,fRotAngle);
  27. Axis.Normalize();
  28. DirectionVectorToAngles(Axis,AxisAngles);
  29. ubDir = (UBYTE) (AxisAngles(1)/360*255);
  30. ulResult = ubDir;
  31. ubDir = (UBYTE) (AxisAngles(2)/90*127);
  32. ulResult = ulResult << 8;
  33. ulResult |= ubDir;
  34. swAngle = (UWORD) (fRotAngle * 180); // after rounding, angle is precise up to 1/180 degrees (65536/360 ~ 180)
  35. ulResult = (ulResult << 16) | swAngle;
  36. };
  37. void ULToAngle(ULONG &ulResult,ANGLE3D &Angle)
  38. {
  39. Quaternion<float> qQuat;
  40. FLOAT3D Axis;
  41. float fRotAngle;
  42. ANGLE3D AxisAngles;
  43. UBYTE ubDir;
  44. UWORD swAngle;
  45. Matrix<float,3,3> mRotMatrix;
  46. swAngle = ulResult & 0x0000FFFF;
  47. fRotAngle = swAngle / 180.0f;
  48. ulResult = ulResult >> 16;
  49. ubDir = ulResult & 0x000000FF;
  50. AxisAngles(2) = ((FLOAT) ubDir)*90/127;
  51. ulResult = ulResult >> 8;
  52. ubDir = ulResult & 0x000000FF;
  53. AxisAngles(1) = ((FLOAT) ubDir)*360/255;
  54. AxisAngles(3) = 0;
  55. AnglesToDirectionVector(AxisAngles,Axis);
  56. qQuat.FromAxisAngle(Axis,fRotAngle);
  57. qQuat.ToMatrix(mRotMatrix);
  58. DecomposeRotationMatrixNoSnap(Angle,mRotMatrix);
  59. };
  60. void CEntityMessage::WritePlacement(ULONG &ulEntityID,CPlacement3D &plPlacement)
  61. {
  62. UBYTE *pubMarker;
  63. ULONG ulShrunkAngle;
  64. SWORD swH,swP,swB;
  65. em_ulType = EMT_SETPLACEMENT;
  66. em_ubSize = sizeof(FLOAT3D) + sizeof(ULONG);
  67. em_ulEntityID = ulEntityID;
  68. swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5);
  69. swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5);
  70. swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5);
  71. ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21);
  72. ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11);
  73. ulShrunkAngle |= (((ULONG) swB) & 0x000007FF);
  74. pubMarker = em_aubMessage;
  75. memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D));
  76. pubMarker += sizeof(FLOAT3D);
  77. memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG));
  78. };
  79. void CEntityMessage::ReadPlacement(ULONG &ulEntityID,CPlacement3D &plPlacement)
  80. {
  81. ASSERT (em_ulType == EMT_SETPLACEMENT);
  82. UBYTE *pubMarker;
  83. ULONG ulShrunkAngle;
  84. SWORD swH,swP,swB;
  85. ulEntityID = em_ulEntityID;
  86. pubMarker = em_aubMessage;
  87. memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D));
  88. pubMarker += sizeof(FLOAT3D);
  89. memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG));
  90. swB = (SWORD) ulShrunkAngle & 0x000007FF;
  91. swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF;
  92. swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF;
  93. plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180;
  94. plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90;
  95. plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180;
  96. };
  97. void CEntityMessage::WriteEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
  98. {
  99. UBYTE *pubMarker;
  100. em_ulType = EMT_EVENT;
  101. em_ubSize = sizeof(UWORD) + uwDataSize;
  102. em_ulEntityID = ulEntityID;
  103. pubMarker = em_aubMessage;
  104. memcpy(pubMarker,&uwEventCode,sizeof(SLONG));
  105. pubMarker += sizeof(UWORD);
  106. memcpy(pubMarker,pvEventData,uwDataSize);
  107. };
  108. void CEntityMessage::ReadEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
  109. {
  110. ASSERT (em_ulType == EMT_EVENT);
  111. UBYTE *pubMarker;
  112. pubMarker = em_aubMessage;
  113. memcpy(&uwEventCode,pubMarker,sizeof(SLONG));
  114. pubMarker += sizeof(UWORD);
  115. uwDataSize = em_ubSize - sizeof(ULONG) - sizeof(UWORD);
  116. memcpy(pvEventData,pubMarker,uwDataSize);
  117. };
  118. void CEntityMessage::WriteEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
  119. {
  120. UBYTE *pubMarker;
  121. ULONG ulShrunkAngle;
  122. SWORD swH,swP,swB;
  123. em_ulType = EMT_CREATE;
  124. em_ubSize = sizeof(FLOAT3D) + sizeof(ULONG) + sizeof(UWORD) + sizeof(UWORD) + uwDataSize;
  125. em_ulEntityID = ulEntityID;
  126. swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5);
  127. swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5);
  128. swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5);
  129. ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21);
  130. ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11);
  131. ulShrunkAngle |= (((ULONG) swB) & 0x000007FF);
  132. pubMarker = em_aubMessage;
  133. memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D));
  134. pubMarker += sizeof(FLOAT3D);
  135. memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG));
  136. pubMarker += sizeof(ULONG);
  137. memcpy(pubMarker,&uwEntityClassID,sizeof(UWORD));
  138. pubMarker += sizeof(UWORD);
  139. memcpy(pubMarker,&uwEventCode,sizeof(UWORD));
  140. pubMarker += sizeof(UWORD);
  141. memcpy(pubMarker,pvEventData,uwDataSize);
  142. };
  143. void CEntityMessage::ReadEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
  144. {
  145. ASSERT (em_ulType == EMT_CREATE);
  146. UBYTE *pubMarker;
  147. ULONG ulShrunkAngle;
  148. SWORD swH,swP,swB;
  149. ulEntityID = em_ulEntityID;
  150. pubMarker = em_aubMessage;
  151. memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D));
  152. pubMarker += sizeof(FLOAT3D);
  153. memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG));
  154. swB = (SWORD) ulShrunkAngle & 0x000007FF;
  155. swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF;
  156. swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF;
  157. plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180;
  158. plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90;
  159. plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180;
  160. pubMarker += sizeof(ULONG);
  161. memcpy(&uwEntityClassID,pubMarker,sizeof(UWORD));
  162. pubMarker += sizeof(UWORD);
  163. memcpy(&uwEventCode,pubMarker,sizeof(UWORD));
  164. pubMarker += sizeof(UWORD);
  165. uwDataSize = em_ubSize - sizeof(FLOAT3D) - sizeof(ULONG) - sizeof(UWORD) - sizeof(UWORD);
  166. memcpy(pubMarker,pvEventData,uwDataSize);
  167. };
  168. void CEntityMessage::WriteEntityDestroy(ULONG &ulEntityID)
  169. {
  170. em_ulType = EMT_DESTROY;
  171. em_ubSize = 0;
  172. em_ulEntityID = ulEntityID;
  173. };
  174. void CEntityMessage::ReadEntityDestroy(ULONG &ulEntityID)
  175. {
  176. ASSERT (em_ulType == EMT_DESTROY);
  177. ulEntityID = em_ulEntityID;
  178. };
  179. void CEntityMessage::WriteEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
  180. {
  181. UBYTE *pubMarker;
  182. ULONG ulShrunkAngle;
  183. SWORD swH,swP,swB;
  184. em_ulType = EMT_COPY;
  185. em_ubSize = sizeof(ULONG) + sizeof(FLOAT3D) + sizeof(ULONG) + sizeof(UWORD) + uwDataSize;
  186. em_ulEntityID = ulSourceEntityID;
  187. swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5);
  188. swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5);
  189. swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5);
  190. ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21);
  191. ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11);
  192. ulShrunkAngle |= (((ULONG) swB) & 0x000007FF);
  193. pubMarker = em_aubMessage;
  194. memcpy(pubMarker,&ulTargetEntityID,sizeof(ULONG));
  195. pubMarker += sizeof(ULONG);
  196. memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D));
  197. pubMarker += sizeof(FLOAT3D);
  198. memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG));
  199. pubMarker += sizeof(ULONG);
  200. memcpy(pubMarker,&uwEventCode,sizeof(SLONG));
  201. pubMarker += sizeof(UWORD);
  202. memcpy(pubMarker,pvEventData,uwDataSize);
  203. };
  204. void CEntityMessage::ReadEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize)
  205. {
  206. ASSERT (em_ulType == EMT_COPY);
  207. UBYTE *pubMarker;
  208. ULONG ulShrunkAngle;
  209. SWORD swH,swP,swB;
  210. ulSourceEntityID = em_ulEntityID;
  211. pubMarker = em_aubMessage;
  212. memcpy(&ulTargetEntityID,pubMarker,sizeof(ULONG));
  213. pubMarker += sizeof(ULONG);
  214. memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D));
  215. pubMarker += sizeof(FLOAT3D);
  216. memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG));
  217. swB = (SWORD) ulShrunkAngle & 0x000007FF;
  218. swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF;
  219. swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF;
  220. plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180;
  221. plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90;
  222. plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180;
  223. pubMarker += sizeof(ULONG);
  224. memcpy(&uwEventCode,pubMarker,sizeof(SLONG));
  225. pubMarker += sizeof(UWORD);
  226. uwDataSize = em_ubSize - sizeof(ULONG) - sizeof(FLOAT3D) - sizeof(ULONG) - sizeof(UWORD);
  227. memcpy(pubMarker,pvEventData,uwDataSize);
  228. };
  229. CEMsgBuffer::CEMsgBuffer()
  230. {
  231. emb_uwNumTickMarkers = 0;
  232. emb_iFirstTickMarker = 0;
  233. emb_iCurrentTickMarker = 0;
  234. emb_fCurrentTickTime = -1;
  235. for (int i=0;i<MAX_TICKS_KEPT;i++) {
  236. emb_atmTickMarkers[i].tm_slTickOffset = -1;
  237. emb_atmTickMarkers[i].tm_fTickTime = -1;
  238. emb_atmTickMarkers[i].tm_ubAcknowledgesExpected = 0;
  239. }
  240. };
  241. CEMsgBuffer::~CEMsgBuffer ()
  242. {
  243. };
  244. void CEMsgBuffer::Clear(void)
  245. {
  246. emb_uwNumTickMarkers = 0;
  247. emb_iFirstTickMarker = 0;
  248. emb_iCurrentTickMarker = 0;
  249. emb_fCurrentTickTime = -1;
  250. for (int i=0;i<MAX_TICKS_KEPT;i++) {
  251. emb_atmTickMarkers[i].tm_slTickOffset = -1;
  252. emb_atmTickMarkers[i].tm_fTickTime = -1;
  253. emb_atmTickMarkers[i].tm_ubAcknowledgesExpected = 0;
  254. }
  255. bu_slWriteOffset = 0;
  256. bu_slReadOffset = 0;
  257. bu_slFree = bu_slSize;
  258. };
  259. void CEMsgBuffer::WriteMessage(CEntityMessage &emEntityMessage)
  260. {
  261. // a tick must have started before any messages are generated
  262. ASSERT (emb_uwNumTickMarkers > 0);
  263. ULONG ulTemp;
  264. int iTickMarker;
  265. ulTemp = emEntityMessage.em_ulEntityID | (emEntityMessage.em_ulType << 24);
  266. WriteBytes(&(ulTemp),sizeof(ULONG));
  267. WriteBytes(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize));
  268. if (emEntityMessage.em_ubSize > 0) {
  269. WriteBytes(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize);
  270. }
  271. iTickMarker = emb_iCurrentTickMarker-1;
  272. if (iTickMarker < 0) iTickMarker += MAX_TICKS_KEPT;
  273. emb_atmTickMarkers[iTickMarker].tm_uwNumMessages++;
  274. };
  275. int CEMsgBuffer::ReadMessage(CEntityMessage &emEntityMessage)
  276. {
  277. ULONG ulTemp;
  278. if (bu_slReadOffset == bu_slWriteOffset) {
  279. return EMB_ERR_BUFFER_EMPTY;
  280. }
  281. ReadBytes(&(ulTemp),sizeof(ULONG));
  282. emEntityMessage.em_ulType = ulTemp >> 24;
  283. emEntityMessage.em_ulEntityID = ulTemp & 0x007FFFFF;
  284. ReadBytes(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize));
  285. if (emEntityMessage.em_ubSize > 0) {
  286. ReadBytes(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize);
  287. }
  288. return EMB_SUCCESS_OK;
  289. };
  290. int CEMsgBuffer::PeekMessageAtOffset(CEntityMessage &emEntityMessage,SLONG &slTickOffset)
  291. {
  292. ASSERT(slTickOffset >= 0 && slTickOffset <= bu_slSize);
  293. ULONG ulTemp;
  294. PeekBytesAtOffset(&(ulTemp),sizeof(ULONG),slTickOffset);
  295. emEntityMessage.em_ulType = ulTemp >> 24;
  296. emEntityMessage.em_ulEntityID = ulTemp & 0x007FFFFF;
  297. PeekBytesAtOffset(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize),slTickOffset);
  298. if (emEntityMessage.em_ubSize > 0) {
  299. PeekBytesAtOffset(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize,slTickOffset);
  300. }
  301. return EMB_SUCCESS_OK;
  302. };
  303. int CEMsgBuffer::StartNewTick(float fTickTime)
  304. {
  305. if (emb_uwNumTickMarkers >= MAX_TICKS_KEPT) {
  306. return EMB_ERR_MAX_TICKS;
  307. }
  308. emb_atmTickMarkers[emb_iCurrentTickMarker].tm_fTickTime = fTickTime;
  309. emb_atmTickMarkers[emb_iCurrentTickMarker].tm_slTickOffset = bu_slWriteOffset;
  310. emb_atmTickMarkers[emb_iCurrentTickMarker].tm_ubAcknowledgesExpected = 0;
  311. emb_atmTickMarkers[emb_iCurrentTickMarker].tm_uwNumMessages = 0;
  312. emb_uwNumTickMarkers++;
  313. emb_iCurrentTickMarker++;
  314. emb_iCurrentTickMarker %= MAX_TICKS_KEPT;
  315. return EMB_SUCCESS_OK;
  316. };
  317. int CEMsgBuffer::SetCurrentTick(float fTickTime)
  318. {
  319. int iErr;
  320. INDEX iTickIndex;
  321. iErr = GetTickIndex(fTickTime,iTickIndex);
  322. if (iErr != EMB_SUCCESS_OK) {
  323. return iErr;
  324. }
  325. emb_iCurrentTickMarker = iTickIndex;
  326. return EMB_SUCCESS_OK;
  327. };
  328. int CEMsgBuffer::GetTickIndex(float fTickTime,INDEX &iTickIndex)
  329. {
  330. INDEX iTickMarker;
  331. // 0.025 should be _pTimer->TickQuantum/2
  332. for (int i=0;i<emb_uwNumTickMarkers;i++) {
  333. iTickMarker = (i + emb_iFirstTickMarker) % MAX_TICKS_KEPT;
  334. if (fabs(emb_atmTickMarkers[iTickMarker].tm_fTickTime - fTickTime) < 0.025) {
  335. iTickIndex = iTickMarker;
  336. return EMB_SUCCESS_OK;
  337. }
  338. }
  339. iTickIndex = -1;
  340. return EMB_ERR_NOT_IN_BUFFER;
  341. };
  342. int CEMsgBuffer::GetTickOffset(float fTickTime,SLONG &slTickOffset)
  343. {
  344. INDEX iTickMarker;
  345. // 0.025 should be _pTimer->TickQuantum/2
  346. for (int i=0;i<emb_uwNumTickMarkers;i++) {
  347. iTickMarker = (i + emb_iFirstTickMarker) % MAX_TICKS_KEPT;
  348. if (fabs(emb_atmTickMarkers[iTickMarker].tm_fTickTime - fTickTime) < 0.025) {
  349. slTickOffset = emb_atmTickMarkers[iTickMarker].tm_slTickOffset;
  350. return EMB_SUCCESS_OK;
  351. }
  352. }
  353. slTickOffset = -1.0f;
  354. return EMB_ERR_NOT_IN_BUFFER;
  355. };
  356. int CEMsgBuffer::GetNextTickTime(float fTickTime,float &fNextTickTime)
  357. {
  358. INDEX iTickIndex;
  359. int iErr;
  360. if (fTickTime < 0) {
  361. if (emb_uwNumTickMarkers > 0) {
  362. fNextTickTime = emb_atmTickMarkers[0].tm_fTickTime;
  363. return EMB_SUCCESS_OK;
  364. } else {
  365. return EMB_ERR_NOT_IN_BUFFER;
  366. }
  367. }
  368. if (fTickTime < emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime) {
  369. fNextTickTime = emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime;
  370. return SUCCESS_OK;
  371. };
  372. iErr = GetTickIndex(fTickTime,iTickIndex);
  373. if (iErr != EMB_SUCCESS_OK) {
  374. return iErr;
  375. }
  376. iTickIndex = (iTickIndex + 1) % MAX_TICKS_KEPT;
  377. fNextTickTime = emb_atmTickMarkers[iTickIndex].tm_fTickTime;
  378. return EMB_SUCCESS_OK;
  379. };
  380. int CEMsgBuffer::RequestTickAcknowledge(float fTickTime,UBYTE ubNumAcknowledges)
  381. {
  382. ASSERT (fTickTime >= 0);
  383. INDEX iTickIndex;
  384. int iErr;
  385. iErr = GetTickIndex(fTickTime,iTickIndex);
  386. if (iErr == EMB_SUCCESS_OK) {
  387. emb_atmTickMarkers[iTickIndex].tm_ubAcknowledgesExpected += ubNumAcknowledges;
  388. return EMB_SUCCESS_OK;
  389. }
  390. return iErr;
  391. };
  392. int CEMsgBuffer::ReceiveTickAcknowledge(float fTickTime)
  393. {
  394. ASSERT (fTickTime >= 0);
  395. INDEX iTickIndex;
  396. INDEX iFirst;
  397. int iErr;
  398. int iNumMark = emb_uwNumTickMarkers;
  399. iErr = GetTickIndex(fTickTime,iTickIndex);
  400. if (iErr == EMB_SUCCESS_OK) {
  401. iFirst = emb_iFirstTickMarker;
  402. emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected--;
  403. while (iFirst!=iTickIndex) {
  404. iFirst++;
  405. iFirst%=MAX_TICKS_KEPT;
  406. emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected--;
  407. }
  408. iFirst = emb_iFirstTickMarker;
  409. if (emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected == 0 && iNumMark != 0) {
  410. while (emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected == 0 && iNumMark != 0) {
  411. if (iNumMark > 0) {
  412. iNumMark--;
  413. iFirst++;
  414. iFirst %= MAX_TICKS_KEPT;
  415. }
  416. }
  417. MoveToStartOfTick(emb_atmTickMarkers[iFirst].tm_fTickTime);
  418. }
  419. return EMB_SUCCESS_OK;
  420. }
  421. return iErr;
  422. };
  423. // does not advance the read offset - access is random, not sequential
  424. int CEMsgBuffer::ReadTick(float fTickTime,const void *pv, SLONG &slSize)
  425. {
  426. ASSERT (slSize>0);
  427. ASSERT (pv != NULL);
  428. ASSERT (fTickTime >= 0);
  429. int iErr;
  430. INDEX iTickIndex,iNextTickIndex;
  431. iErr = GetTickIndex(fTickTime,iTickIndex);
  432. if (iErr != EMB_SUCCESS_OK) {
  433. return iErr;
  434. }
  435. if (iTickIndex >= (emb_iFirstTickMarker + emb_uwNumTickMarkers - 1)) {
  436. return EMB_ERR_TICK_NOT_COMPLETE;
  437. }
  438. iNextTickIndex = (iTickIndex + 1) % MAX_TICKS_KEPT;
  439. SLONG slTickSize = emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset - emb_atmTickMarkers[iTickIndex].tm_slTickOffset;
  440. // if not wrapping
  441. if ( slTickSize > 0) {
  442. if (slSize < slTickSize) {
  443. return EMB_ERR_BUFFER_TOO_SMALL;
  444. }
  445. slSize = slTickSize;
  446. memcpy((UBYTE*)pv,bu_pubBuffer+emb_atmTickMarkers[iTickIndex].tm_slTickOffset,slTickSize);
  447. } else {
  448. if (slSize < (bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset) + emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset-1) {
  449. return EMB_ERR_BUFFER_TOO_SMALL;
  450. }
  451. slSize = (bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset) + emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset;
  452. // copy data from the start of this ick to the end of the bufer
  453. memcpy((UBYTE*)pv,bu_pubBuffer+emb_atmTickMarkers[iTickIndex].tm_slTickOffset,bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset);
  454. // copy datafrom the start of the buffer to the start of next tick
  455. memcpy(((UBYTE*)pv)+bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset,bu_pubBuffer,emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset);
  456. }
  457. return EMB_SUCCESS_OK;
  458. };
  459. void CEMsgBuffer::WriteTick(float tm_fTickTime,const void *pv, SLONG slSize)
  460. {
  461. ASSERT(slSize>=0 && pv!=NULL);
  462. StartNewTick(tm_fTickTime);
  463. WriteBytes(pv,slSize);
  464. };
  465. int CEMsgBuffer::MoveToStartOfTick(float fTickTime)
  466. {
  467. int iErr;
  468. INDEX iTickIndex;
  469. ASSERT(fTickTime >= emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime);
  470. iErr = GetTickIndex(fTickTime,iTickIndex);
  471. if (iErr != EMB_SUCCESS_OK) {
  472. return iErr;
  473. }
  474. // if not wrapping
  475. if (iTickIndex >= emb_iFirstTickMarker) {
  476. emb_uwNumTickMarkers -= iTickIndex - emb_iFirstTickMarker;
  477. } else {
  478. emb_uwNumTickMarkers -= iTickIndex + (MAX_TICKS_KEPT - emb_iFirstTickMarker);
  479. }
  480. emb_iFirstTickMarker = iTickIndex;
  481. if (bu_slReadOffset <= emb_atmTickMarkers[iTickIndex].tm_slTickOffset) {
  482. bu_slFree += emb_atmTickMarkers[iTickIndex].tm_slTickOffset - bu_slReadOffset;
  483. } else {
  484. bu_slFree += (bu_slSize - bu_slReadOffset) + emb_atmTickMarkers[iTickIndex].tm_slTickOffset;
  485. }
  486. bu_slReadOffset = emb_atmTickMarkers[iTickIndex].tm_slTickOffset;
  487. return EMB_SUCCESS_OK;
  488. };
  489. // expand buffer to be given number of bytes in size
  490. void CEMsgBuffer::Expand(SLONG slNewSize)
  491. {
  492. ASSERT(slNewSize>0);
  493. ASSERT(bu_slSize>=0);
  494. // if not already allocated
  495. if (bu_slSize==0) {
  496. // allocate a new empty buffer
  497. ASSERT(bu_pubBuffer==NULL);
  498. bu_pubBuffer = (UBYTE*)AllocMemory(slNewSize);
  499. bu_slWriteOffset = 0;
  500. bu_slReadOffset = 0;
  501. bu_slFree = slNewSize;
  502. bu_slSize = slNewSize;
  503. // if already allocated
  504. } else {
  505. ASSERT(slNewSize>bu_slSize);
  506. SLONG slSizeDiff = slNewSize-bu_slSize;
  507. ASSERT(bu_pubBuffer!=NULL);
  508. // grow buffer
  509. GrowMemory((void**)&bu_pubBuffer, slNewSize);
  510. cout << "EXPAND!\n";
  511. // if buffer is currently wrapping
  512. if (bu_slReadOffset>bu_slWriteOffset||bu_slFree==0) {
  513. cout << "WRAP!\n";
  514. // move part at the end of buffer to the end
  515. memmove(bu_pubBuffer+bu_slReadOffset+slSizeDiff, bu_pubBuffer+bu_slReadOffset,bu_slSize-bu_slReadOffset);
  516. for (int i=0;i<MAX_TICKS_KEPT;i++) {
  517. if (emb_atmTickMarkers[i].tm_slTickOffset >= bu_slReadOffset) {
  518. emb_atmTickMarkers[i].tm_slTickOffset += slSizeDiff;
  519. }
  520. }
  521. bu_slReadOffset+=slSizeDiff;
  522. }
  523. bu_slFree += slNewSize-bu_slSize;
  524. bu_slSize = slNewSize;
  525. ASSERT(bu_slReadOffset>=0 && bu_slReadOffset<bu_slSize);
  526. ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
  527. }
  528. }
  529. // write bytes to buffer
  530. void CEMsgBuffer::WriteBytes(const void *pv, SLONG slSize)
  531. {
  532. BOOL bWraping = FALSE;
  533. SLONG slOldReadOffset = bu_slReadOffset;
  534. // if buffer is currently wrapping
  535. ASSERT(slSize>=0 && pv!=NULL);
  536. // if there is nothing to write
  537. if (slSize==0) {
  538. // do nothing
  539. return;
  540. }
  541. // check for errors
  542. if (slSize<0) {
  543. cout << "WARNING: WriteBytes(): slSize<0\n!";
  544. return;
  545. }
  546. // if there is not enough free space
  547. if (bu_slFree<slSize) {
  548. SLONG slSizeDiff;
  549. SLONG slNewSize;
  550. slNewSize = bu_slSize + ((slSize-bu_slFree + bu_slAllocationStep - 1) / bu_slAllocationStep) * bu_slAllocationStep;
  551. slSizeDiff = slNewSize - bu_slSize;
  552. // if buffer is currently wrapping
  553. // if (bu_slReadOffset>bu_slWriteOffset||bu_slFree==0) {
  554. // bWraping = TRUE;
  555. // }
  556. // expand the buffer
  557. Expand(slNewSize);
  558. ASSERT(bu_slFree>=slSize);
  559. }
  560. UBYTE *pub = (UBYTE*)pv;
  561. // write part of block at the end of buffer
  562. SLONG slSizeEnd = __min(bu_slSize-bu_slWriteOffset, slSize);
  563. memcpy(bu_pubBuffer+bu_slWriteOffset, pub, slSizeEnd);
  564. pub+=slSizeEnd;
  565. memcpy(bu_pubBuffer, pub, slSize-slSizeEnd);
  566. // move write pointer
  567. bu_slWriteOffset+=slSize;
  568. bu_slWriteOffset%=bu_slSize;
  569. bu_slFree-=slSize;
  570. ASSERT(bu_slWriteOffset>=0 && bu_slWriteOffset<bu_slSize);
  571. ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
  572. };
  573. SLONG CEMsgBuffer::PeekBytes(const void *pv, SLONG slSize)
  574. {
  575. ASSERT(slSize>0 && pv!=NULL);
  576. UBYTE *pub = (UBYTE*)pv;
  577. // clamp size to amount of bytes actually in the buffer
  578. SLONG slUsed = bu_slSize-bu_slFree;
  579. if (slUsed<slSize) {
  580. slSize = slUsed;
  581. }
  582. // if there is nothing to read
  583. if (slSize==0) {
  584. // do nothing
  585. return 0;
  586. }
  587. // read part of block after read pointer to the end of buffer
  588. SLONG slSizeEnd = __min(bu_slSize-bu_slReadOffset, slSize);
  589. memcpy(pub, bu_pubBuffer+bu_slReadOffset, slSizeEnd);
  590. pub+=slSizeEnd;
  591. // if that is not all
  592. if (slSizeEnd<slSize) {
  593. // read rest from start of buffer
  594. memcpy(pub, bu_pubBuffer, slSize-slSizeEnd);
  595. }
  596. ASSERT(bu_slReadOffset>=0 && bu_slReadOffset<bu_slSize);
  597. ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
  598. return slSize;
  599. }
  600. SLONG CEMsgBuffer::PeekBytesAtOffset(const void *pv, SLONG slSize,SLONG &slTickOffset)
  601. {
  602. ASSERT(slSize>0 && pv!=NULL);
  603. UBYTE *pub = (UBYTE*)pv;
  604. // clamp size to amount of bytes actually in the buffer
  605. SLONG slUsed = bu_slSize-bu_slFree;
  606. if (slUsed<slSize) {
  607. slSize = slUsed;
  608. }
  609. // if there is nothing to read
  610. if (slSize==0) {
  611. // do nothing
  612. return 0;
  613. }
  614. // read part of block after read pointer to the end of buffer
  615. SLONG slSizeEnd = __min(bu_slSize-slTickOffset, slSize);
  616. memcpy(pub, bu_pubBuffer+slTickOffset, slSizeEnd);
  617. pub+=slSizeEnd;
  618. slTickOffset += slSizeEnd;
  619. // if that is not all
  620. if (slSizeEnd<slSize) {
  621. // read rest from start of buffer
  622. memcpy(pub, bu_pubBuffer, slSize-slSizeEnd);
  623. slTickOffset = slSize - slSizeEnd;
  624. }
  625. slTickOffset %= bu_slSize;
  626. ASSERT(slTickOffset>=0 && slTickOffset<bu_slSize);
  627. ASSERT(bu_slFree>=0 && bu_slFree<=bu_slSize);
  628. return slSize;
  629. }