1 /*
2  *  Copyright (C) 2016-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "LinearMemoryStream.h"
12 
13 #include <deque>
14 #include <vector>
15 
16 namespace KODI
17 {
18 namespace RETRO
19 {
20 /*!
21  * \brief Implementation of a linear memory stream using XOR deltas
22  */
23 class CDeltaPairMemoryStream : public CLinearMemoryStream
24 {
25 public:
26   CDeltaPairMemoryStream() = default;
27 
28   ~CDeltaPairMemoryStream() override = default;
29 
30   // implementation of IMemoryStream via CLinearMemoryStream
31   void Reset() override;
32   uint64_t PastFramesAvailable() const override;
33   uint64_t RewindFrames(uint64_t frameCount) override;
34 
35 protected:
36   // implementation of CLinearMemoryStream
37   void SubmitFrameInternal() override;
38   void CullPastFrames(uint64_t frameCount) override;
39 
40   /*!
41    * Rewinding is implemented by applying XOR deltas on the specific parts of
42    * the save state buffer which have changed. In practice, this is very fast
43    * and simple (linear scan) and allows deltas to be compressed down to 1-3%
44    * of original save state size depending on the system. The algorithm runs
45    * on 32 bits at a time for speed.
46    *
47    * Use std::deque here to achieve amortized O(1) on pop/push to front and
48    * back.
49    */
50   struct DeltaPair
51   {
52     size_t pos;
53     uint32_t delta;
54   };
55 
56   using DeltaPairVector = std::vector<DeltaPair>;
57 
58   struct MemoryFrame
59   {
60     DeltaPairVector buffer;
61     uint64_t frameHistoryCount;
62   };
63 
64   std::deque<MemoryFrame> m_rewindBuffer;
65 };
66 } // namespace RETRO
67 } // namespace KODI
68