added step-based engine snapshots to undo/redo game steps (continued)
[rocksndiamonds.git] / src / libgame / snapshot.c
1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // snapshot.c
10 // ============================================================================
11
12 #include "snapshot.h"
13
14
15 static ListNode *snapshot_single = NULL;
16 static ListNode *snapshot_list = NULL;
17 static ListNode *snapshot_current = NULL;
18
19 static int num_snapshots_in_list = 0;
20
21
22 #ifdef DEBUG
23 #define DEBUG_SNAPSHOTS                 0
24 #endif
25
26
27 // -----------------------------------------------------------------------------
28 // functions for handling buffers for a single snapshot
29 // -----------------------------------------------------------------------------
30
31 void SaveSnapshotBuffer(ListNode **snapshot_buffers, void *buffer, int size)
32 {
33   struct SnapshotNodeInfo *bi =
34     checked_calloc(sizeof(struct SnapshotNodeInfo));
35
36   bi->buffer_orig = buffer;
37   bi->buffer_copy = checked_malloc(size);
38   bi->size = size;
39
40   memcpy(bi->buffer_copy, buffer, size);
41
42   addNodeToList(snapshot_buffers, NULL, bi);
43 }
44
45 static void LoadSnapshotBuffer(struct SnapshotNodeInfo *bi)
46 {
47   memcpy(bi->buffer_orig, bi->buffer_copy, bi->size);
48 }
49
50 void LoadSnapshotBuffers(ListNode *snapshot_buffers)
51 {
52   while (snapshot_buffers != NULL)
53   {
54     LoadSnapshotBuffer((struct SnapshotNodeInfo *)snapshot_buffers->content);
55
56     snapshot_buffers = snapshot_buffers->next;
57   }
58 }
59
60 void FreeSnapshotBuffers(ListNode *snapshot_buffers)
61 {
62   while (snapshot_buffers != NULL)
63     deleteNodeFromList(&snapshot_buffers, snapshot_buffers->key, checked_free);
64 }
65
66 // -----------------------------------------------------------------------------
67 // functions for handling one of several snapshots
68 // -----------------------------------------------------------------------------
69
70 static void FreeSnapshotExt(void *snapshot_buffers_ptr)
71 {
72   FreeSnapshotBuffers(snapshot_buffers_ptr);
73 }
74
75 void FreeSnapshotSingle()
76 {
77   FreeSnapshotBuffers(snapshot_single);
78
79   snapshot_single = NULL;
80 }
81
82 void FreeSnapshotList_UpToNode(ListNode *node)
83 {
84   while (snapshot_list != node)
85   {
86     deleteNodeFromList(&snapshot_list, snapshot_list->key, FreeSnapshotExt);
87
88     num_snapshots_in_list--;
89   }
90 }
91
92 void FreeSnapshotList()
93 {
94   FreeSnapshotList_UpToNode(NULL);
95
96   snapshot_current = NULL;
97 }
98
99 void SaveSnapshotSingle(ListNode *snapshot_buffers)
100 {
101   if (snapshot_single)
102     FreeSnapshotSingle();
103
104   snapshot_single = snapshot_buffers;
105 }
106
107 void SaveSnapshotToList(ListNode *snapshot_buffers)
108 {
109   if (snapshot_current != snapshot_list)
110     FreeSnapshotList_UpToNode(snapshot_current);
111
112   addNodeToList(&snapshot_list, i_to_a(num_snapshots_in_list),
113                 snapshot_buffers);
114
115   snapshot_current = snapshot_list;
116
117   num_snapshots_in_list++;
118
119 #if DEBUG_SNAPSHOTS
120   printf("::: SaveSnapshotToList() [%s]\n", snapshot_current->key);
121 #endif
122 }
123
124 boolean LoadSnapshotSingle()
125 {
126   if (snapshot_single)
127   {
128     LoadSnapshotBuffers(snapshot_single);
129
130     return TRUE;
131   }
132
133   return FALSE;
134 }
135
136 boolean LoadSnapshotFromList_Older(int steps)
137 {
138   if (snapshot_current->next)
139   {
140     while (snapshot_current->next && steps--)
141       snapshot_current = snapshot_current->next;
142
143     LoadSnapshotBuffers(snapshot_current->content);
144
145 #if DEBUG_SNAPSHOTS
146     printf("::: LoadSnapshotFromList_Older() [%s]\n", snapshot_current->key);
147 #endif
148
149     return TRUE;
150   }
151
152   return FALSE;
153 }
154
155 boolean LoadSnapshotFromList_Newer(int steps)
156 {
157   if (snapshot_current->prev)
158   {
159     while (snapshot_current->prev && steps--)
160       snapshot_current = snapshot_current->prev;
161
162     LoadSnapshotBuffers(snapshot_current->content);
163
164 #if DEBUG_SNAPSHOTS
165     printf("::: LoadSnapshotFromList_Newer() [%s]\n", snapshot_current->key);
166 #endif
167
168     return TRUE;
169   }
170
171   return FALSE;
172 }