Example #1
0
static bool state_manager_pop(state_manager_t *state, const void **data)
{
   size_t start;
   uint8_t *out                 = NULL;
   const uint8_t *compressed    = NULL;

   *data = NULL;

   if (state->thisblock_valid)
   {
      state->thisblock_valid = false;
      state->entries--;
      *data = state->thisblock;
      return true;
   }

   if (state->head == state->tail)
      return false;

   start = read_size_t(state->head - sizeof(size_t));
   state->head = state->data + start;

   compressed = state->data + start + sizeof(size_t);
   out = state->thisblock;

   state_manager_raw_decompress(compressed,
         state->maxcompsize, out, state->blocksize);

   state->entries--;
   *data = state->thisblock;
   return true;
}
Example #2
0
bool state_manager_pop(state_manager_t *state, const void **data)
{
   size_t start;
   uint8_t *out;
   uint16_t *out16;
   const uint8_t *compressed = NULL;
   const uint16_t *compressed16 = NULL;

   *data = NULL;

   if (state->thisblock_valid)
   {
      state->thisblock_valid = false;
      state->entries--;
      *data = state->thisblock;
      return true;
   }

   if (state->head == state->tail)
      return false;

   start = read_size_t(state->head - sizeof(size_t));
   state->head = state->data + start;

   compressed = state->data + start + sizeof(size_t);
   out = state->thisblock;

   /* Begin decompression code
    * out is the last pushed (or returned) state */
   compressed16 = (const uint16_t*)compressed;
   out16 = (uint16_t*)out;

   for (;;)
   {
      uint16_t i;
      uint16_t numchanged = *(compressed16++);

      if (numchanged)
      {
         out16 += *compressed16++;

         /* We could do memcpy, but it seems that memcpy has a 
          * constant-per-call overhead that actually shows up.
          *
          * Our average size in here seems to be 8 or something.
          * Therefore, we do something with lower overhead. */
         for (i = 0; i < numchanged; i++)
            out16[i] = compressed16[i];

         compressed16 += numchanged;
         out16 += numchanged;
      }
      else
      {
         uint32_t numunchanged = compressed16[0] | (compressed16[1] << 16);

         if (!numunchanged)
            break;
         compressed16 += 2;
         out16 += numunchanged;
      }
   }
   /* End decompression code */

   state->entries--;
   *data = state->thisblock;
   return true;
}
Example #3
0
static void state_manager_push_do(state_manager_t *state)
{
#if STRICT_BUF_SIZE
   memcpy(state->nextblock, state->debugblock, state->debugsize);
#endif

   static struct retro_perf_counter gen_deltas = {0};
   uint8_t *swap = NULL;

   if (state->thisblock_valid)
   {
      const uint8_t *oldb, *newb;
      uint8_t *compressed;
      size_t headpos, tailpos, remaining;
      if (state->capacity < sizeof(size_t) + state->maxcompsize)
         return;

recheckcapacity:;

      headpos = state->head - state->data;
      tailpos = state->tail - state->data;
      remaining = (tailpos + state->capacity -
            sizeof(size_t) - headpos - 1) % state->capacity + 1;

      if (remaining <= state->maxcompsize)
      {
         state->tail = state->data + read_size_t(state->tail);
         state->entries--;
         goto recheckcapacity;
      }

      performance_counter_init(&gen_deltas, "gen_deltas");
      performance_counter_start(&gen_deltas);

      oldb        = state->thisblock;
      newb        = state->nextblock;
      compressed  = state->head + sizeof(size_t);

      compressed += state_manager_raw_compress(oldb, newb,
            state->blocksize, compressed);

      if (compressed - state->data + state->maxcompsize > state->capacity)
      {
         compressed = state->data;
         if (state->tail == state->data + sizeof(size_t))
            state->tail = state->data + read_size_t(state->tail);
      }
      write_size_t(compressed, state->head-state->data);
      compressed += sizeof(size_t);
      write_size_t(state->head, compressed-state->data);
      state->head = compressed;

      performance_counter_stop(&gen_deltas);
   }
   else
      state->thisblock_valid = true;

   swap             = state->thisblock;
   state->thisblock = state->nextblock;
   state->nextblock = swap;

   state->entries++;
}