rnd-20090719-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 #if 1
148   FILE_GET(FNum, i, PlayField8, FileMax + 1);
149 #else
150   FILE_GET(FNum, i, &PlayField8, sizeof(PlayField8));
151 #endif
152   i = i + LevelMax + 1;
153   FILE_GET(FNum, i, &LInfo, sizeof(LInfo)); // store level info in an extra structure
154   fclose(FNum);
155   // --- On Error GoTo 0
156
157   Trace("modMPX", "file closed");
158   if (FieldMax < FileMax)
159     DemoAvailable = True;
160
161   Trace("modMPX", "read signature");
162   ReadSignature();
163   Trace("modMPX", "ReDim PlayField16");
164   PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax);
165   for (i = 0; i <= FieldMax; i++)
166   {
167     PlayField16[i] = PlayField8[i];
168     DisPlayField[i] = PlayField8[i];
169     PlayField8[i] = 0;
170   }
171
172   AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth);
173   AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth);
174   TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
175   GravityFlag = LInfo.InitialGravity;
176   FreezeZonks = LInfo.InitialFreezeZonks;
177   DemoPointer = FieldMax + 1;
178   DemoOffset = DemoPointer;
179   DemoKeyRepeatCounter = 0;
180   if (DemoFlag != 0)
181   {
182     // Debug.Print "ReadMPX: " & Hex(LInfo.DemoRandomSeed)
183     RandomSeed = LInfo.DemoRandomSeed;
184     DemoFlag = 1;
185   }
186   else
187   {
188     subRandomize();
189   }
190
191   MainForm.SetDisplayRegion();
192   LevelLoaded = True;
193   if (CurPath != TmpPath)
194     Let_ModifiedFlag(False);
195
196   Trace("modMPX", "--> ReadMPX");
197   return;
198
199 ReadMPXEH:
200   // Close();
201   fclose(FNum);
202   ReportError("modMPX", CAT("Error reading MPX file ", CurPath));
203   Trace("modMPX", "Error reading MPX file");
204   Trace("modMPX", "--> ReadMPX");
205 }
206
207 #if 0
208
209 static void SaveMPX(char *Path)
210 {
211   // int FNum, i;
212   FILE *FNum;
213   int i;
214   // byte T;
215   byte FF;
216
217   FF = 0xFF;
218   LevelNumber = 1;
219   LevelCount = 1;
220   MPXVersion = 1;
221   if ((FileMax < FieldMax) || ! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
222     FileMax = FieldMax;
223
224   LDesc = REDIM_1D(sizeof(LevelDescriptor), 0, LevelCount + 1 - 1);
225   {
226     LDesc[LevelNumber].Width = FieldWidth;
227     LDesc[LevelNumber].Height = FieldHeight;
228     LDesc[LevelNumber].OffSet = 4 + 2 * strlen(INT_TO_STR(LevelCount)) +
229       LevelCount * sizeof(LDesc[1]) + 1;
230     LDesc[LevelNumber].Size = FileMax + 1;
231     if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
232     {
233       LDesc[LevelNumber].Size = LDesc[LevelNumber].Size + DemoBuffer.Size + 2;
234       if (0 < strlen(MySignature))
235         LDesc[LevelNumber].Size = LDesc[LevelNumber].Size + strlen(MySignature) + 1;
236     }
237
238   }
239
240   // UnEdAll();
241
242   // --- On Error GoTo SaveMPXEH
243   // FNum = FreeFile();
244   if (FileExists(Path))
245     MayKill(Path);
246
247   FNum = fopen(Path, "wb");
248   FILE_PUT(FNum, -1, &MPX_ID, sizeof(MPX_ID));
249   FILE_PUT(FNum, -1, &MPXVersion, sizeof(MPXVersion));
250   FILE_PUT(FNum, -1, &LevelCount, sizeof(LevelCount));
251   FILE_PUT(FNum, -1, &LDesc, sizeof(LDesc));
252   i = LDesc[LevelNumber].OffSet;
253   FILE_PUT(FNum, i, &PlayField8, sizeof(PlayField8));
254   FILE_PUT(FNum, i, &DisPlayField, sizeof(DisPlayField));
255   i = i + LevelMax + 1;
256   FILE_PUT(FNum, i, &LInfo, sizeof(LInfo)); // store level info
257   if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) // demo was recorded
258   {
259     // Debug.Print "SaveMPX: " & Hex(LInfo.DemoRandomSeed)
260     FILE_PUT(FNum, -1, &FirstDemoByte, sizeof(FirstDemoByte));
261     if (! DemoBuffer.Serialize(FNum))
262       goto SaveMPXEH;
263
264     FILE_PUT(FNum, -1, &FF, sizeof(FF));
265     if (0 < strlen(MySignature))
266     {
267       FILE_PUT(FNum, -1, &MySignature, sizeof(MySignature));
268       FILE_PUT(FNum, -1, &FF, sizeof(FF));
269     }
270   }
271
272   fclose(FNum);
273   // --- On Error GoTo 0
274
275   CurPath = Path;
276
277   // EdAll();
278
279   if (Path != TmpPath)
280     Let_ModifiedFlag(False);
281
282   return;
283
284 SaveMPXEH:
285   // Close();
286   fclose(FNum);
287 }
288
289 #endif
290
291 #if 0
292
293 static void SaveSP(char *Path)
294 {
295   // int FNum, i;
296   FILE *FNum;
297   int i;
298   // byte T;
299
300   LevelNumber = 1;
301   LevelCount = 1;
302   if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
303     LInfo.CheckSumByte = DemoBuffer.CheckSumByte;
304
305   if ((FileMax < FieldMax) || ! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer)))
306     FileMax = FieldMax;
307
308   // UnEdAll();
309
310   // --- On Error GoTo SaveSPEH
311   // FNum = FreeFile();
312   FNum = fopen(Path, "wb");
313   FILE_PUT(FNum, 1, &PlayField8, sizeof(PlayField8));
314   FILE_PUT(FNum, 1, &DisPlayField, sizeof(DisPlayField));
315   i = LevelMax + 2;
316   FILE_PUT(FNum, i, &LInfo, sizeof(LInfo)); // store level info
317   if (! IS_NOTHING(&DemoBuffer, sizeof(DemoBuffer))) // demo was recorded
318   {
319     // Debug.Print "SaveMPX: " & Hex(LInfo.DemoRandomSeed)
320     // If Not DemoBuffer.Serialize(FNum) Then GoTo SaveSPEH
321
322     // Debug.Assert(False);
323   }
324
325   fclose(FNum);
326   // --- On Error GoTo 0
327
328   CurPath = Path;
329
330   // EdAll();
331
332   if (Path != TmpPath)
333     Let_ModifiedFlag(False);
334
335   return;
336
337   // SaveSPEH:
338   // Close();
339 }
340
341 #endif
342
343 void CreateLevel(int LWidth, int LHeight)
344 {
345   long Tmp, i;
346   // byte T;
347
348   CurPath = "Untitled";
349   OrigPath = CurPath;
350   LevelNumber = 1;
351   FieldWidth = LWidth;
352   FieldHeight = LHeight;
353   HeaderSize = 96;
354   FieldMax = (FieldWidth * FieldHeight) + HeaderSize - 1;
355   LevelMax = (FieldWidth * FieldHeight) - 1;
356   FileMax = FieldMax;
357   PlayField8 = REDIM_1D(sizeof(byte), 0, FileMax + 1 - 1);
358   DisPlayField = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
359   Tmp = FieldWidth * (FieldHeight - 1);
360   for (i = 0; i <= FieldWidth - 1; i++)
361   {
362     PlayField8[i] = fiHardWare;
363     PlayField8[Tmp + i] = fiHardWare;
364   }
365
366   Tmp = Tmp;
367   for (i = FieldWidth; i <= Tmp; i += FieldWidth)
368   {
369     PlayField8[i] = fiHardWare;
370     PlayField8[i - 1] = fiHardWare;
371   }
372
373   {
374     LInfo.DemoRandomSeed = 0;
375     LInfo.InfotronsNeeded = 0;
376     LInfo.InitialFreezeZonks = 0;
377     LInfo.InitialGravity = 0;
378     strcpy(LInfo.LevelTitle, "------ New Level ------");;
379     LInfo.SpecialPortCount = 0;
380     LInfo.Version = 0x74; // immitate speedfix version 5.4
381   }
382   PlayField16 = REDIM_1D(sizeof(int), -FieldWidth, FieldMax);
383   for (i = 0; i <= FieldMax; i++)
384   {
385     PlayField16[i] = PlayField8[i];
386     DisPlayField[i] = PlayField8[i];
387     PlayField8[i] = 0;
388   }
389
390   AnimationPosTable = REDIM_1D(sizeof(int), 0, LevelMax - 2 *FieldWidth);
391   AnimationSubTable = REDIM_1D(sizeof(byte), 0, LevelMax - 2 *FieldWidth);
392   TerminalState = REDIM_1D(sizeof(byte), 0, FieldMax + 1 - 1);
393   GravityFlag = LInfo.InitialGravity;
394   FreezeZonks = LInfo.InitialFreezeZonks;
395   RandomSeed = LInfo.DemoRandomSeed;
396   DemoAvailable = False;
397   SET_TO_NOTHING(&DemoBuffer, sizeof(DemoBuffer));
398   LevelLoaded = True;
399   Let_ModifiedFlag(True);
400 }
401
402 void ReadSignature()
403 {
404   long i, iMin, iMax;
405
406   Trace("modMPX", "--> ReadSignature");
407   bSignatureAvailable = False;
408   gSignature = "";
409
410   // ##################################################### ReRecording-Test
411   if ((DemoFlag == 1) && (RecordDemoFlag == 1))
412   {
413     FirstDemoByte = PlayField8[DemoPointer];
414     MySignature = gSignature;
415   }
416
417   // ##################################################### ReRecording-Test
418
419   // gSignature = String(511, "A"): bSignatureAvailable = False: Exit Sub 'test
420   if (! (FieldMax < FileMax))
421     return;
422
423   // !!! Debug.Assert PlayField8(FileMax) = &HFF
424   Trace("modMPX", "settin iMin/Max");
425   iMin = FileMax - 512;
426   if (iMin < (FieldMax + 2))
427     iMin = FieldMax + 2;
428
429   iMax = FileMax - 1;
430   Trace("modMPX", "  For i == iMax To iMin Step -1");
431   for (i = iMax; i <= iMin; i += -1)
432   {
433     if (PlayField8[i] == 0xFF)
434       break;
435   }
436
437   if (i < iMin)
438     return;
439
440   for (i = i + 1; i <= iMax; i++)
441   {
442     gSignature = CAT(gSignature, (char)(PlayField8[i]));
443   }
444
445   // ##################################################### ReRecording-Test
446   if ((DemoFlag == 1) && (RecordDemoFlag == 1))
447     MySignature = gSignature;
448
449   // ##################################################### ReRecording-Test
450
451   if (iMin <= iMax)
452     bSignatureAvailable = True;
453
454   Trace("modMPX", "<-- ReadSignature");
455 }