rnd-20090623-1-src
[rocksndiamonds.git] / src / game_sp / modMPX.c
1 // ----------------------------------------------------------------------------
2 // modMPX.c
3 // ----------------------------------------------------------------------------
4
5 #include "modMPX.h"
6
7 void ReadMPX();
8 #if 0
9 static void SaveMPX(char *Path);
10 static void SaveSP(char *Path);
11 #endif
12
13 // static char *VB_Name = "modMPX";
14 // --- Option Explicit
15
16 char *gSignature;
17 boolean bSignatureAvailable;
18
19 const char MPX_ID[4] = "MPX ";
20
21 // ::: #ifndef HAS_LevelDescriptor
22 // ::: typedef struct
23 // ::: {
24 // :::   int Width;
25 // :::   int Height;
26 // :::   long OffSet;
27 // :::   long Size;
28 // ::: } LevelDescriptor;
29 // ::: #define HAS_LevelDescriptor
30 // ::: #endif
31
32 int MPXVersion;
33 int LevelCount;
34 boolean DemoAvailable;
35 LevelDescriptor *LDesc;
36 // int OFile;
37 FILE *OFile;
38
39 boolean MpxOpen(char *Path)
40 {
41   boolean MpxOpen;
42
43   // int i;
44   // byte T;
45   char readID[4];
46
47   MpxOpen = False;
48
49   // --- On Error GoTo OpenMPXEH
50   // OFile = FreeFile();
51   OFile = fopen(CurPath, "rb");
52   FILE_GET(OFile, -1, &readID, sizeof(readID));
53   if (readID != MPX_ID)
54     goto OpenMPXEH;
55
56   FILE_GET(OFile, -1, &MPXVersion, sizeof(MPXVersion));
57   FILE_GET(OFile, -1, &LevelCount, sizeof(LevelCount));
58   LDesc = REDIM_1D(sizeof(LevelDescriptor), 0, LevelCount + 1 - 1);
59   FILE_GET(OFile, -1, &LDesc, sizeof(LDesc));
60   MpxOpen = True;
61   return MpxOpen;
62
63 OpenMPXEH:
64   fclose(OFile);
65   OFile = 0;
66
67   return MpxOpen;
68 }
69
70 boolean MpxLoadLInfo(int i)
71 {
72   boolean MpxLoadLInfo;
73
74   long Off;
75
76   MpxLoadLInfo = False;
77   // if (OFile < 1)
78   if (OFile == 0)
79     return MpxLoadLInfo;
80
81   Off = LDesc[i].OffSet;
82   Off = Off + LDesc[i].Width * LDesc[i].Height;
83
84   // --- On Error GoTo MpxLoadLInfoEH
85   FILE_GET(OFile, Off, &LInfo, sizeof(LInfo));
86   MpxLoadLInfo = True;
87   return MpxLoadLInfo;
88
89   // MpxLoadLInfoEH:
90   fclose(OFile);
91   OFile = 0;
92
93   return MpxLoadLInfo;
94 }
95
96 void MpxClose()
97 {
98   if (0 < OFile)
99   {
100     fclose(OFile);
101     OFile = 0;
102   }
103 }
104
105 void ReadMPX()
106 {
107   // int FNum, i;
108   FILE *FNum;
109   int i;
110   // byte T;
111   char readID[4];
112
113   Trace("modMPX", "--> ReadMPX");
114
115   // --- On Error GoTo ReadMPXEH
116   // FNum = FreeFile();
117   Trace("modMPX", "open file");
118   FNum = fopen(CurPath, "rb");
119   FILE_GET(FNum, -1, &readID, sizeof(readID));
120   if (readID != MPX_ID)
121     goto ReadMPXEH;
122
123   FILE_GET(FNum, -1, &MPXVersion, sizeof(MPXVersion));
124   if (MPXVersion != 1)
125     goto ReadMPXEH;
126
127   FILE_GET(FNum, -1, &LevelCount, sizeof(LevelCount));
128   if (LevelCount < 1)
129     goto ReadMPXEH;
130
131   LDesc = REDIM_1D(sizeof(LevelDescriptor), 0, LevelCount + 1 - 1);
132   Trace("modMPX", "--> read LevelDescriptor");
133   FILE_GET(FNum, -1, &LDesc, sizeof(LDesc));
134   FieldWidth = LDesc[LevelNumber].Width;
135   FieldHeight = LDesc[LevelNumber].Height;
136   HeaderSize = 96;
137   FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1;
138   LevelMax = (FieldWidth * FieldHeight) - 1;
139   FileMax = LDesc[LevelNumber].Size - 1;
140   if (FileMax < FieldMax)
141     FileMax = FieldMax;
142
143   Trace("modMPX", "ReDim PlayField8");
144   PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax + 1 - 1);
145   DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
146   i = LDesc[LevelNumber].OffSet;
147   FILE_GET(FNum, i, &PlayField8, sizeof(PlayField8));
148   i = i + LevelMax + 1;
149   FILE_GET(FNum, i, &LInfo, sizeof(LInfo)); // store level info in an extra structure
150   fclose(FNum);
151   // --- On Error GoTo 0
152
153   Trace("modMPX", "file closed");
154   if (FieldMax < FileMax)
155     DemoAvailable = True;
156
157   Trace("modMPX", "read signature");
158   ReadSignature();
159   Trace("modMPX", "ReDim PlayField16");
160   PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax);
161   for (i = 0; i <= FieldMax; i++)
162   {
163     PlayField16[i] = PlayField8[i];
164     DisPlayField[i] = PlayField8[i];
165     PlayField8[i] = 0;
166   }
167
168   AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth);
169   AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth);
170   TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
171   GravityFlag = LInfo.InitialGravity;
172   FreezeZonks = LInfo.InitialFreezeZonks;
173   DemoPointer = FieldMax + 1;
174   DemoOffset = DemoPointer;
175   DemoKeyRepeatCounter = 0;
176   if (DemoFlag != 0)
177   {
178     // Debug.Print "ReadMPX: " & Hex(LInfo.DemoRandomSeed)
179     RandomSeed = LInfo.DemoRandomSeed;
180     DemoFlag = 1;
181   }
182   else
183   {
184     subRandomize();
185   }
186
187   MainForm.SetDisplayRegion();
188   LevelLoaded = True;
189   if (CurPath != TmpPath)
190     Let_ModifiedFlag(False);
191
192   Trace("modMPX", "--> ReadMPX");
193   return;
194
195 ReadMPXEH:
196   // Close();
197   fclose(FNum);
198   ReportError("modMPX", CAT("Error reading MPX file ", CurPath));
199   Trace("modMPX", "Error reading MPX file");
200   Trace("modMPX", "--> ReadMPX");
201 }
202
203 #if 0
204
205 static void SaveMPX(char *Path)
206 {
207   // int FNum, i;
208   FILE *FNum;
209   int i;
210   // byte T;
211   byte FF;
212
213   FF = 0xFF;
214   LevelNumber = 1;
215   LevelCount = 1;
216   MPXVersion = 1;
217   if ((FileMax < FieldMax) || ! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
218     FileMax = FieldMax;
219
220   LDesc = REDIM_1D(sizeof(LevelDescriptor), 0, LevelCount + 1 - 1);
221   {
222     LDesc[LevelNumber].Width = FieldWidth;
223     LDesc[LevelNumber].Height = FieldHeight;
224     LDesc[LevelNumber].OffSet = 4 + 2 * strlen(INT_TO_STR(LevelCount)) +
225       LevelCount * sizeof(LDesc[1]) + 1;
226     LDesc[LevelNumber].Size = FileMax + 1;
227     if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
228     {
229       LDesc[LevelNumber].Size = LDesc[LevelNumber].Size + DemoBuffer.Size + 2;
230       if (0 < strlen(MySignature))
231         LDesc[LevelNumber].Size = LDesc[LevelNumber].Size + strlen(MySignature) + 1;
232     }
233
234   }
235
236   // UnEdAll();
237
238   // --- On Error GoTo SaveMPXEH
239   // FNum = FreeFile();
240   if (FileExists(Path))
241     MayKill(Path);
242
243   FNum = fopen(Path, "wb");
244   FILE_PUT(FNum, -1, &MPX_ID, sizeof(MPX_ID));
245   FILE_PUT(FNum, -1, &MPXVersion, sizeof(MPXVersion));
246   FILE_PUT(FNum, -1, &LevelCount, sizeof(LevelCount));
247   FILE_PUT(FNum, -1, &LDesc, sizeof(LDesc));
248   i = LDesc[LevelNumber].OffSet;
249   FILE_PUT(FNum, i, &PlayField8, sizeof(PlayField8));
250   FILE_PUT(FNum, i, &DisPlayField, sizeof(DisPlayField));
251   i = i + LevelMax + 1;
252   FILE_PUT(FNum, i, &LInfo, sizeof(LInfo)); // store level info
253   if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) // demo was recorded
254   {
255     // Debug.Print "SaveMPX: " & Hex(LInfo.DemoRandomSeed)
256     FILE_PUT(FNum, -1, &FirstDemoByte, sizeof(FirstDemoByte));
257     if (! DemoBuffer.Serialize(FNum))
258       goto SaveMPXEH;
259
260     FILE_PUT(FNum, -1, &FF, sizeof(FF));
261     if (0 < strlen(MySignature))
262     {
263       FILE_PUT(FNum, -1, &MySignature, sizeof(MySignature));
264       FILE_PUT(FNum, -1, &FF, sizeof(FF));
265     }
266   }
267
268   fclose(FNum);
269   // --- On Error GoTo 0
270
271   CurPath = Path;
272
273   // EdAll();
274
275   if (Path != TmpPath)
276     Let_ModifiedFlag(False);
277
278   return;
279
280 SaveMPXEH:
281   // Close();
282   fclose(FNum);
283 }
284
285 #endif
286
287 #if 0
288
289 static void SaveSP(char *Path)
290 {
291   // int FNum, i;
292   FILE *FNum;
293   int i;
294   // byte T;
295
296   LevelNumber = 1;
297   LevelCount = 1;
298   if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
299     LInfo.CheckSumByte = DemoBuffer.CheckSumByte;
300
301   if ((FileMax < FieldMax) || ! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
302     FileMax = FieldMax;
303
304   // UnEdAll();
305
306   // --- On Error GoTo SaveSPEH
307   // FNum = FreeFile();
308   FNum = fopen(Path, "wb");
309   FILE_PUT(FNum, 1, &PlayField8, sizeof(PlayField8));
310   FILE_PUT(FNum, 1, &DisPlayField, sizeof(DisPlayField));
311   i = LevelMax + 2;
312   FILE_PUT(FNum, i, &LInfo, sizeof(LInfo)); // store level info
313   if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) // demo was recorded
314   {
315     // Debug.Print "SaveMPX: " & Hex(LInfo.DemoRandomSeed)
316     // If Not DemoBuffer.Serialize(FNum) Then GoTo SaveSPEH
317
318     // Debug.Assert(False);
319   }
320
321   fclose(FNum);
322   // --- On Error GoTo 0
323
324   CurPath = Path;
325
326   // EdAll();
327
328   if (Path != TmpPath)
329     Let_ModifiedFlag(False);
330
331   return;
332
333   // SaveSPEH:
334   // Close();
335 }
336
337 #endif
338
339 void CreateLevel(int LWidth, int LHeight)
340 {
341   long Tmp, i;
342   // byte T;
343
344   CurPath = "Untitled";
345   OrigPath = CurPath;
346   LevelNumber = 1;
347   FieldWidth = LWidth;
348   FieldHeight = LHeight;
349   HeaderSize = 96;
350   FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1;
351   LevelMax = (FieldWidth * FieldHeight) - 1;
352   FileMax = FieldMax;
353   PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax + 1 - 1);
354   DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
355   Tmp = FieldWidth * (FieldHeight - 1);
356   for (i = 0; i <= FieldWidth - 1; i++)
357   {
358     PlayField8[i] = fiHardWare;
359     PlayField8[Tmp + i] = fiHardWare;
360   }
361
362   Tmp = Tmp;
363   for (i = FieldWidth; i <= Tmp; i += FieldWidth)
364   {
365     PlayField8[i] = fiHardWare;
366     PlayField8[i - 1] = fiHardWare;
367   }
368
369   {
370     LInfo.DemoRandomSeed = 0;
371     LInfo.InfotronsNeeded = 0;
372     LInfo.InitialFreezeZonks = 0;
373     LInfo.InitialGravity = 0;
374     strcpy(LInfo.LevelTitle, "------ New Level ------");;
375     LInfo.SpecialPortCount = 0;
376     LInfo.Version = 0x74; // immitate speedfix version 5.4
377   }
378   PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax);
379   for (i = 0; i <= FieldMax; i++)
380   {
381     PlayField16[i] = PlayField8[i];
382     DisPlayField[i] = PlayField8[i];
383     PlayField8[i] = 0;
384   }
385
386   AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth);
387   AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth);
388   TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
389   GravityFlag = LInfo.InitialGravity;
390   FreezeZonks = LInfo.InitialFreezeZonks;
391   RandomSeed = LInfo.DemoRandomSeed;
392   DemoAvailable = False;
393   SET_TO_NOTHING(&DemoBuffer, sizeof(DemoBuffer));
394   LevelLoaded = True;
395   Let_ModifiedFlag(True);
396 }
397
398 void ReadSignature()
399 {
400   long i, iMin, iMax;
401
402   Trace("modMPX", "--> ReadSignature");
403   bSignatureAvailable = False;
404   gSignature = "";
405
406   // ##################################################### ReRecording-Test
407   if ((DemoFlag == 1) && (RecordDemoFlag == 1))
408   {
409     FirstDemoByte = PlayField8[DemoPointer];
410     MySignature = gSignature;
411   }
412
413   // ##################################################### ReRecording-Test
414
415   // gSignature = String(511, "A"): bSignatureAvailable = False: Exit Sub 'test
416   if (! (FieldMax < FileMax))
417     return;
418
419   // !!! Debug.Assert PlayField8(FileMax) = &HFF
420   Trace("modMPX", "settin iMin/Max");
421   iMin = FileMax - 512;
422   if (iMin < (FieldMax + 2))
423     iMin = FieldMax + 2;
424
425   iMax = FileMax - 1;
426   Trace("modMPX", "  For i == iMax To iMin Step -1");
427   for (i = iMax; i <= iMin; i += -1)
428   {
429     if (PlayField8[i] == 0xFF)
430       break;
431   }
432
433   if (i < iMin)
434     return;
435
436   for (i = i + 1; i <= iMax; i++)
437   {
438     gSignature = CAT(gSignature, (char)(PlayField8[i]));
439   }
440
441   // ##################################################### ReRecording-Test
442   if ((DemoFlag == 1) && (RecordDemoFlag == 1))
443     MySignature = gSignature;
444
445   // ##################################################### ReRecording-Test
446
447   if (iMin <= iMax)
448     bSignatureAvailable = True;
449
450   Trace("modMPX", "<-- ReadSignature");
451 }