1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // https://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
16 #define DEBUG_SNAPSHOTS 0
19 static ListNode *snapshot_single = NULL;
20 static ListNode *snapshot_list = NULL;
21 static ListNode *snapshot_current = NULL;
23 static int num_snapshots = 0;
24 static int num_snapshot_buffers = 0;
25 static int num_snapshot_bytes = 0;
26 static int next_snapshot_key = 0;
29 // -----------------------------------------------------------------------------
30 // functions for handling buffers for a single snapshot
31 // -----------------------------------------------------------------------------
33 void SaveSnapshotBuffer(ListNode **snapshot_buffers, void *buffer, int size)
35 struct SnapshotNodeInfo *bi =
36 checked_calloc(sizeof(struct SnapshotNodeInfo));
38 bi->buffer_orig = buffer;
39 bi->buffer_copy = checked_malloc(size);
42 memcpy(bi->buffer_copy, buffer, size);
44 addNodeToList(snapshot_buffers, NULL, bi);
46 num_snapshot_buffers++;
47 num_snapshot_bytes += size;
50 static void LoadSnapshotBuffer(struct SnapshotNodeInfo *bi)
52 memcpy(bi->buffer_orig, bi->buffer_copy, bi->size);
55 void LoadSnapshotBuffers(ListNode *snapshot_buffers)
57 while (snapshot_buffers != NULL)
59 LoadSnapshotBuffer((struct SnapshotNodeInfo *)snapshot_buffers->content);
61 snapshot_buffers = snapshot_buffers->next;
65 static void FreeSnapshotBuffer(void *bi_raw)
67 struct SnapshotNodeInfo *bi = (struct SnapshotNodeInfo *)bi_raw;
69 num_snapshot_buffers--;
70 num_snapshot_bytes -= bi->size;
72 checked_free(bi->buffer_copy);
76 void FreeSnapshotBuffers(ListNode *snapshot_buffers)
78 while (snapshot_buffers != NULL)
79 deleteNodeFromList(&snapshot_buffers, NULL, FreeSnapshotBuffer);
82 // -----------------------------------------------------------------------------
83 // functions for handling single shapshot or list of snapshots
84 // -----------------------------------------------------------------------------
86 static void FreeSnapshot(void *snapshot_buffers_ptr)
88 FreeSnapshotBuffers(snapshot_buffers_ptr);
91 void FreeSnapshotSingle(void)
93 FreeSnapshotBuffers(snapshot_single);
95 snapshot_single = NULL;
98 static void FreeSnapshotList_UpToNode(ListNode *node)
100 while (snapshot_list != node)
103 Debug("snapshot:FreeSnapshotList_UpToNode", "[%s, %d, %d]",
104 snapshot_list->key, num_snapshot_buffers, num_snapshot_bytes);
107 deleteNodeFromList(&snapshot_list, snapshot_list->key, FreeSnapshot);
110 next_snapshot_key = (snapshot_list ? atoi(snapshot_list->key) + 1 : 0);
114 void FreeSnapshotList(void)
117 Debug("snapshot:FreeSnapshotList", "");
120 FreeSnapshotList_UpToNode(NULL);
123 num_snapshot_buffers = 0;
124 num_snapshot_bytes = 0;
125 next_snapshot_key = 0;
127 snapshot_current = NULL;
130 static void ReduceSnapshotList(void)
133 int num_snapshots_last = num_snapshots;
136 // maximum number of snapshots exceeded -- thin out list of snapshots
137 ListNode *node = snapshot_list;
138 int num_snapshots_to_skip = num_snapshots / 10;
140 // do not remove the newest snapshots from the list
141 while (node && num_snapshots_to_skip--)
144 // remove every second snapshot from the remaining list
147 // never delete the first list node (snapshot at game start)
148 if (node->next == NULL)
151 // in alternation, delete one node from the list ...
152 deleteNodeFromList(&node, node->key, FreeSnapshot);
155 // ... and keep one node (which always exists here)
160 Debug("snapshot:ReduceSnapshotList",
161 "(Reducing number of snapshots from %d to %d.)",
162 num_snapshots_last, num_snapshots);
165 node = snapshot_list;
168 Debug("snapshot:ReduceSnapshotList", "key: %s", node->key);
176 void SaveSnapshotSingle(ListNode *snapshot_buffers)
179 FreeSnapshotSingle();
181 snapshot_single = snapshot_buffers;
184 void SaveSnapshotToList(ListNode *snapshot_buffers)
186 if (snapshot_current != snapshot_list)
187 FreeSnapshotList_UpToNode(snapshot_current);
190 Debug("snapshot:SaveSnapshotToList",
191 "[%d] [%d snapshots, %d buffers, %d bytes]",
192 next_snapshot_key, num_snapshots,
193 num_snapshot_buffers, num_snapshot_bytes);
196 addNodeToList(&snapshot_list, i_to_a(next_snapshot_key),
199 snapshot_current = snapshot_list;
204 if (num_snapshot_bytes > setup.engine_snapshot_memory)
205 ReduceSnapshotList();
208 boolean LoadSnapshotSingle(void)
212 LoadSnapshotBuffers(snapshot_single);
220 boolean LoadSnapshotFromList_Older(int steps)
222 if (snapshot_current && snapshot_current->next)
224 while (snapshot_current->next && steps--)
225 snapshot_current = snapshot_current->next;
227 LoadSnapshotBuffers(snapshot_current->content);
230 Debug("snapshot:LoadSnapshotFromList_Older", "[%s]", snapshot_current->key);
239 boolean LoadSnapshotFromList_Newer(int steps)
241 if (snapshot_current && snapshot_current->prev)
243 while (snapshot_current->prev && steps--)
244 snapshot_current = snapshot_current->prev;
246 LoadSnapshotBuffers(snapshot_current->content);
249 Debug("snapshot:LoadSnapshotFromList_Newer", "[%s]", snapshot_current->key);
258 boolean CheckSnapshotList(void)
260 return (snapshot_list ? TRUE : FALSE);