Index: /code/branches/netp4/src/network/GamestateManager.cc
===================================================================
--- /code/branches/netp4/src/network/GamestateManager.cc	(revision 3119)
+++ /code/branches/netp4/src/network/GamestateManager.cc	(revision 3120)
@@ -133,5 +133,8 @@
 //       COUT(3) << "diffing" << std::endl;
 //       packet::Gamestate* gs1  = gs;
-      gs = gs->diff(client);
+      packet::Gamestate *diffed = gs->diff(client);
+      //packet::Gamestate *gs2 = diffed->undiff(gs);
+//       assert(*gs == *gs2);
+      gs = diffed;
 //       packet::Gamestate* gs2 = gs->undiff(client);
 //       gs = new packet::Gamestate(*gs);
Index: /code/branches/netp4/src/network/packet/Acknowledgement.cc
===================================================================
--- /code/branches/netp4/src/network/packet/Acknowledgement.cc	(revision 3119)
+++ /code/branches/netp4/src/network/packet/Acknowledgement.cc	(revision 3120)
@@ -64,5 +64,5 @@
 
 bool Acknowledgement::process(){
-COUT(6) << "processing ACK with ID: " << getAckID() << endl;
+  COUT(5) << "processing ACK with ID: " << getAckID() << endl;
   bool b = GamestateHandler::ackGamestate(getAckID(), clientID_);
   delete this;
Index: /code/branches/netp4/src/network/packet/Gamestate.cc
===================================================================
--- /code/branches/netp4/src/network/packet/Gamestate.cc	(revision 3119)
+++ /code/branches/netp4/src/network/packet/Gamestate.cc	(revision 3120)
@@ -138,4 +138,5 @@
   header_->setDataSize( currentsize );
   header_->setID( id );
+  header_->setBaseID( GAMESTATEID_INITIAL );
   header_->setDiffed( false );
   header_->setComplete( true );
@@ -208,5 +209,4 @@
   }
 #endif
-
   return true;
 }
@@ -321,5 +321,5 @@
 }
 
-Gamestate *Gamestate::diff(Gamestate *base)
+/*Gamestate *Gamestate::diff(Gamestate *base)
 {
   assert(data_);
@@ -356,5 +356,70 @@
   g->packetDirection_ = packetDirection_;
   return g;
-}
+}*/
+
+Gamestate *Gamestate::diff(Gamestate *base)
+{
+  assert(this && base); assert(data_ && base->data_);
+  assert(!header_->isCompressed() && !base->header_->isCompressed());
+  assert(!header_->isDiffed());
+  
+  uint8_t *basep = GAMESTATE_START(base->data_);
+  uint8_t *gs = GAMESTATE_START(this->data_);
+  uint32_t dest_length = header_->getDataSize();
+  
+  if(dest_length==0)
+    return NULL;
+  
+  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()];
+  uint8_t *dest = GAMESTATE_START(ndata);
+  
+  rawDiff( dest, gs, basep, header_->getDataSize(), base->header_->getDataSize() );
+#ifndef NDEBUG
+  uint8_t *dest2 = new uint8_t[dest_length];
+  rawDiff( dest2, dest, basep, header_->getDataSize(), base->header_->getDataSize() );
+  assert( memcmp( dest2, gs, dest_length) == 0 );
+#endif
+
+  Gamestate *g = new Gamestate(ndata, getClientID());
+  assert(g->header_);
+  *(g->header_) = *header_;
+  g->header_->setDiffed( true );
+  g->header_->setBaseID( base->getID() );
+  g->flags_=flags_;
+  g->packetDirection_ = packetDirection_;
+  assert(g->isDiffed());
+  assert(!g->isCompressed());
+  return g;
+}
+
+Gamestate *Gamestate::undiff(Gamestate *base)
+{
+  assert(this && base); assert(data_ && base->data_);
+  assert(!header_->isCompressed() && !base->header_->isCompressed());
+  assert(header_->isDiffed());
+  
+  uint8_t *basep = GAMESTATE_START(base->data_);
+  uint8_t *gs = GAMESTATE_START(this->data_);
+  uint32_t dest_length = header_->getDataSize();
+  
+  if(dest_length==0)
+    return NULL;
+  
+  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()];
+  uint8_t *dest = ndata + GamestateHeader::getSize();
+  
+  rawDiff( dest, gs, basep, header_->getDataSize(), base->header_->getDataSize() );
+  
+  Gamestate *g = new Gamestate(ndata, getClientID());
+  assert(g->header_);
+  *(g->header_) = *header_;
+  g->header_->setDiffed( false );
+  g->flags_=flags_;
+  g->packetDirection_ = packetDirection_;
+  assert(!g->isDiffed());
+  assert(!g->isCompressed());
+  return g;
+}
+
 
 // Gamestate *Gamestate::diff(Gamestate *base)
@@ -410,4 +475,31 @@
 // }
 
+
+void Gamestate::rawDiff( uint8_t* newdata, uint8_t* data, uint8_t* basedata, uint32_t datalength, uint32_t baselength)
+{
+  uint64_t* gd = (uint64_t*)data;
+  uint64_t* bd = (uint64_t*)basedata;
+  uint64_t* nd = (uint64_t*)newdata;
+  
+  unsigned int i;
+  for( i=0; i<datalength/8; i++ )
+  {
+    if( i<baselength/8 )
+      *(nd+i) = *(gd+i) ^ *(bd+i);  // xor the data
+    else
+      *(nd+i) = *(gd+i); // just copy over the data
+  }
+  unsigned int j;
+  // now process the rest (when datalength isn't a multiple of 4)
+  for( j = 8*(datalength/8); j<datalength; j++ )
+  {
+    if( j<baselength )
+      *(newdata+j) = *(data+j) ^ *(basedata+j); // xor
+    else
+      *(newdata+j) = *(data+j); // just copy
+  }
+  assert(j==datalength);
+}
+
 Gamestate* Gamestate::doSelection(unsigned int clientID, unsigned int targetSize){
   assert(data_);
@@ -479,5 +571,5 @@
 
 
-Gamestate *Gamestate::undiff(Gamestate *base)
+/*Gamestate *Gamestate::undiff(Gamestate *base)
 {
   assert(this && base);assert(data_);
@@ -515,6 +607,5 @@
   assert(!g->isCompressed());
   return g;
-}
-
+}*/
 
 uint32_t Gamestate::calcGamestateSize(int32_t id, uint8_t mode)
Index: /code/branches/netp4/src/network/packet/Gamestate.h
===================================================================
--- /code/branches/netp4/src/network/packet/Gamestate.h	(revision 3119)
+++ /code/branches/netp4/src/network/packet/Gamestate.h	(revision 3120)
@@ -124,4 +124,5 @@
     // Packet functions
   private:
+    void rawDiff( uint8_t* newdata, uint8_t* data, uint8_t* basedata, uint32_t datalength, uint32_t baselength);
     virtual uint32_t getSize() const;
     virtual inline bool process();
