Merge branch 'i18n'
[hex-a-hop.git] / savestate.h
blob29ecfc86019fcf421f23ccf2adcba3350ecef88b
1 /*
2 Copyright (C) 2005-2007 Tom Beaumont
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
20 struct HexPuzzle;
22 class LevelSave
24 friend struct HexPuzzle;
26 // CHECKME: If char is larger than 8 bits (== 1 byte???)
27 // the code is no longer big endian safe? SWAP16/32 is necessary?
28 // Or is a byte always of the same size as char, e.g. 16 bits, so
29 // that int16_t is equally saved on big and little endian systems?
30 char * bestSolution;
31 int32_t bestSolutionLength;
32 int32_t bestScore;
33 #define NUM_LAST_SCORES 19
34 int32_t lastScores[NUM_LAST_SCORES];
35 int32_t unlocked;
36 public:
37 LevelSave()
39 Clear();
41 void Clear()
43 unlocked = 0;
44 bestSolution = 0;
45 bestScore = 0;
46 bestSolutionLength = 0;
47 memset(lastScores, 0, sizeof(lastScores));
49 void LoadSave(FILE* f, bool save)
51 typedef unsigned int _fn(void*, unsigned int, unsigned int, FILE*);
52 _fn * fn = save ? (_fn*)fwrite : (_fn*)fread;
54 // we write little endian data
55 bestSolutionLength = SWAP32(bestSolutionLength);
56 bestScore = SWAP32(bestScore);
57 for (int i=0; i<NUM_LAST_SCORES; ++i)
58 lastScores[i] = SWAP32(lastScores[i]);
59 unlocked = SWAP32(unlocked);
61 fn(&bestSolutionLength, sizeof(bestSolutionLength), 1, f);
62 fn(&bestScore, sizeof(bestScore), 1, f);
63 fn(&lastScores, sizeof(lastScores), 1, f);
64 fn(&unlocked, sizeof(unlocked), 1, f);
66 bestSolutionLength = SWAP32(bestSolutionLength);
67 bestScore = SWAP32(bestScore);
68 for (int i=0; i<NUM_LAST_SCORES; ++i)
69 lastScores[i] = SWAP32(lastScores[i]);
70 unlocked = SWAP32(unlocked);
72 if (bestSolutionLength)
74 if (!save) SetSolution(bestSolutionLength);
75 fn(bestSolution, sizeof(bestSolution[0]), bestSolutionLength, f);
79 void Dump()
81 for (int j=1; j<NUM_LAST_SCORES; j++)
82 if (lastScores[j]==lastScores[0])
83 lastScores[j] = 0;
85 /* for (int i=0; i<NUM_LAST_SCORES && lastScores[i]; i++)
86 if (lastScores[i] != bestScore)
87 printf("\t% 8d\n", lastScores[i]);*/
89 bool Completed()
91 return bestScore != 0;
93 bool IsNewCompletionBetter(int score)
95 for (int i=0; i<NUM_LAST_SCORES; i++)
97 if (lastScores[i]==0)
98 lastScores[i] = score;
99 if (lastScores[i]==score)
100 break;
103 if (!Completed())
104 return true;
106 return score <= bestScore;
108 bool PassesPar(int par)
110 if (!Completed())
111 return false;
112 return bestScore <= par;
114 int GetScore()
116 return bestScore;
118 void SetScore(int s)
120 bestScore = s;
122 void SetSolution(int l) {
123 delete [] bestSolution;
124 bestSolutionLength = l;
125 bestSolution = new char [ l ];
127 void SetSolutionStep(int pos, int val)
129 bestSolution[pos] = val;
133 class SaveState
135 struct X : public LevelSave
137 X* next;
138 char* name;
140 X(const char* n, X* nx=0) : next(nx)
142 name = new char[strlen(n)+1];
143 strcpy(name, n);
145 ~X()
147 delete [] name;
151 struct General {
152 /// Change big endian data into little endian data, do nothing on little endian systems
153 void SwapBytes()
155 scoringOn = SWAP32(scoringOn);
156 hintFlags = SWAP32(hintFlags);
157 completionPercentage = SWAP32(completionPercentage);
158 endSequence = SWAP32(endSequence);
159 masteredPercentage = SWAP32(masteredPercentage);
160 for (unsigned int i=0; i<sizeof(pad)/sizeof(int32_t); ++i)
161 pad[i] = SWAP32(pad[i]);
163 int32_t scoringOn;
164 int32_t hintFlags;
165 int32_t completionPercentage;
166 int32_t endSequence;
167 int32_t masteredPercentage;
168 int32_t pad[6];
171 X* first;
173 void ClearRaw()
175 memset(&general, 0, sizeof(general));
176 general.hintFlags = 1<<31 | 1<<30;
178 X* x=first;
179 while (x)
181 X* nx = x->next;
182 delete x;
183 x = nx;
185 first = 0;
189 public:
191 General general;
194 SaveState() : first(0)
196 Clear();
199 ~SaveState()
201 ClearRaw();
204 void Clear()
206 ClearRaw();
207 ApplyStuff();
210 void GetStuff();
211 void ApplyStuff();
213 void LoadSave(FILE* f, bool save)
215 if (save)
217 GetStuff();
219 //printf("----\n");
221 fputc('2', f);
222 general.SwapBytes(); // big==>little endian
223 fwrite(&general, sizeof(general), 1, f);
224 general.SwapBytes(); // revert changes
225 for(X* x=first; x; x=x->next)
227 int16_t len = strlen(x->name);
228 len = SWAP16(len);
229 fwrite(&len, sizeof(len), 1, f);
230 len = SWAP16(len);
231 fwrite(x->name, 1, len, f);
233 x->LoadSave(f,save);
235 if (x->Completed())
237 //printf("% 8d %s\n", x->GetScore(), x->name);
238 x->Dump();
242 else
244 ClearRaw();
245 int v = fgetc(f);
246 if (v=='2')
248 fread(&general, sizeof(general), 1, f);
249 general.SwapBytes();
250 v = '1';
252 if (v=='1')
254 while(!feof(f))
256 char temp[1000];
257 int16_t len;
258 fread(&len, sizeof(len), 1, f);
259 len = SWAP16(len);
260 if (feof(f)) break;
261 fread(temp, len, 1, f);
262 temp[len] = 0;
263 first = new X(temp, first);
265 first->LoadSave(f,save);
269 ApplyStuff();
273 LevelSave* GetLevel(const char * name, bool create)
275 char * l = strstr(name, "Levels");
276 if (l)
277 name = l;
279 X* x = first;
280 if (x && strcmp(name, x->name)==0) return x;
281 while (x && x->next)
283 if (strcmp(name, x->next->name)==0) return x->next;
284 x = x->next;
286 if (create)
288 X* n = new X(name);
289 if (x)
290 x->next = n;
291 else
292 first = n;
293 return n;
295 else
297 return 0;