rnd-20091012-1-src
[rocksndiamonds.git] / src / game_sp / MainGameLoop.c
1 // ----------------------------------------------------------------------------
2 // MainGameLoop.c
3 // ----------------------------------------------------------------------------
4
5 #include "MainGameLoop.h"
6
7 // static char *VB_Name = "modMainGameLoop";
8
9 // --- Option Explicit
10
11 int GameLoopRunning;
12 boolean bPlaying;
13 int LeadOutCounter, EnterRepeatCounter;
14 int ForcedExitFlag;
15 int ExitToMenuFlag;
16 int SavedGameFlag;
17 boolean UserDragFlag;
18 boolean AutoScrollFlag;
19
20 // ==========================================================================
21 //                              SUBROUTINE
22 // Play a game/demo
23 // ==========================================================================
24
25 int subMainGameLoop_Init()
26 {
27   int subMainGameLoop;
28
29   // int al, bx;
30   // int bx;
31 #if 0
32   TickCountObject Clock;
33   currency LastFrame;
34 #endif
35
36   if (DemoFlag != 0)
37   {
38 #if 1
39     printf("::: playing demo ...\n");
40 #endif
41
42     // EP set level success byte: demo, not game
43     WasDemoFlag = 1;
44     EP_GameDemoVar0DAA = 0; // demo
45   }
46   else // loc_g_1836:
47   {
48 #if 1
49     printf("::: playing game ...\n");
50 #endif
51
52     // EP set level success byte: game, not demo
53     WasDemoFlag = 0;
54     EP_GameDemoVar0DAA = 1; // game
55   }
56
57   // RestartGameLoop:
58   //  If RecordDemoFlag = 1 Then
59   //    RecordDemoFlag = 0 ' clear Demo Recording flag
60   //    Call subDisplayPlayingTime                 ' playing time on screen
61   //    ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
62   //    While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
63   //      ' yes -> wait until released
64   //      ' should we DoEvents here???? ... depends on how ... but yes!
65   //      ' ...or we can rather poll the keyboardstate inside this loop???
66   //    Wend
67   //    Call subInitGameConditions     ' Init game conditions (vars)
68   //    If MusicOnFlag = 0 Then Call subMusicInit
69   //    WasDemoFlag = 0          ' no demo anymore
70   //    EP_GameDemoVar0DAA = 1 ' force game
71   //  End If
72
73   // This was a bug in the original Supaplex: sometimes red disks could not
74   // be released.  This happened If Murphy was killed DURING a red disk release
75   // and the next try started.
76
77   RedDiskReleasePhase = 0; // (re-)enable red disk release
78   UpdatedFlag = 0;
79   GameLoopRunning = 1;
80   LevelStatus = 0;
81
82   return subMainGameLoop;
83 }
84
85 int subMainGameLoop_Main()
86 {
87   int subMainGameLoop;
88   int bx;
89
90   // ----------------------------------------------------------------------------
91   // --------------------- START OF GAME-BUSY LOOP ------------------------------
92   // ----------------------------------------------------------------------------
93
94 locRepeatMainGameLoop:                           // start repeating game loop
95
96   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
97   // FS   synchronization
98   while (PauseMode != 0)
99   {
100     DoEvents();
101   }
102
103   do
104   {
105     DoEvents(); // user may klick on menus or move the window here ...
106   }
107 #if 1
108   while (0);
109 #else
110   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
111 #endif
112
113   //   never any additional code between here!
114 #if 0
115   LastFrame = Clock.TickNow(); // store the frame time
116 #endif
117   //   never any additional code between here!
118   if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
119     Stage.Blt();
120
121   // FS   end of synchronization
122   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
123   if (EndFlag)
124     goto locExitMainGameLoop;
125
126   // If DemoFlag = 0 Then Call subCheckJoystick    ' check joystick
127   // bx = subCheckRightMouseButton()                ' check (right) mouse button
128   // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
129
130   //  If DebugVersionFlag <> 0 Then ' debug mode on?
131   //    If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
132   //    If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
133   //                                          ' fixes ENTER bug If no mouse driver!
134   //    If bx <> 1 Then GoTo loc_g_186F  ' Left button=Init game field
135   //                                    ' Also Enter If no mouse!
136   //    If Data_SubRest <> 0 Then GoTo loc_g_186F
137   //    Data_SubRest = 10
138   //    Call subRestoreFancy
139   //    Call subDisplayLevel         ' Paint (Init) game field
140   //    Call subConvertToEasySymbols ' Convert to easy symbols
141   //  End If
142
143   // loc_g_186F:
144
145   subProcessKeyboardInput();                 // Check keyboard, act on keys
146
147   // 'HACK:
148   //  TimerVar = TimerVar + 1
149   //  DoEvents
150   //  GoTo loc_g_186F
151   // 'END HACK
152   // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
153
154   // ----------------------------------------------------------------------------
155   //
156
157 #if 0
158   printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
159 #endif
160
161   subDoGameStuff();                 // do all game stuff
162
163 #if 0
164   printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
165 #endif
166
167   //
168   // ----------------------------------------------------------------------------
169
170   //  Call subDisplayPlayingTime                 ' playing time on screen
171
172   subCheckRestoreRedDiskCountDisplay();    // Restore panel: red-disk hole
173
174   subRedDiskReleaseExplosion();       // Red Disk release and explode
175   subFollowUpExplosions();  // every explosion may cause up to 8 following explosions
176
177   bx = subCalculateScreenScrollPos();     // calculate screen start addrs
178
179   ScreenPosition = bx;
180
181   // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
182   data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
183   data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
184   if ((! UserDragFlag) && AutoScrollFlag)
185   {
186 #if 0
187     printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
188 #endif
189
190     ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
191   }
192
193   if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
194     goto locExitMainGameLoop;
195
196   TimerVar = TimerVar + 1;
197
198 #if 0
199   if (bCapturePane)
200     MainForm.SaveSnapshot(TimerVar);
201 #endif
202
203   //  If Not NoDisplayFlag Then
204   //    With MainForm.lblFrameCount
205   //      .Caption = TimerVar
206   //      .Refresh
207   //    End With
208   //  End If
209
210   if (ExitToMenuFlag == 1)
211     goto locExitMainGameLoop;
212
213 #if 1
214   if (LeadOutCounter == 0) // no lead-out: game busy
215     return subMainGameLoop;
216 #else
217   if (LeadOutCounter == 0) // no lead-out: game busy
218     goto locRepeatMainGameLoop;
219 #endif
220
221   // ----------------------------------------------------------------------------
222   // ---------------------- END OF GAME-BUSY LOOP -------------------------------
223   // ----------------------------------------------------------------------------
224   LeadOutCounter = LeadOutCounter - 1;             // do more lead-out after quit
225   if (LeadOutCounter != 0) // lead-out not ready: more
226     goto locRepeatMainGameLoop;
227
228   // lead-out done: exit now
229   // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
230
231 locExitMainGameLoop:
232   do
233   {
234     DoEvents(); // user may klick on menus or move the window here ...
235   }
236 #if 1
237   while (0);
238 #else
239   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
240 #endif
241
242   Stage.Blt(); // blit the last frame
243   GameLoopRunning = 0;
244
245 #if 0
246   MainForm.menStop_Click();
247   MainForm.PanelVisible = True;
248 #endif
249
250   // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
251   if (SavedGameFlag != 0) // after savegame: no update!
252   {
253     SavedGameFlag = 0;
254     return subMainGameLoop;
255   }
256
257   SavedGameFlag = 0;
258   if (UpdateTimeFlag == 0) // update time?
259     return subMainGameLoop;
260
261   if (UpdatedFlag == 0) // update playing time
262     subUpdatePlayingTime();
263
264
265   return subMainGameLoop;
266 } // subMainGameLoop
267
268 int subMainGameLoop()
269 {
270   int subMainGameLoop;
271
272   // int al, bx;
273   int bx;
274 #if 0
275   TickCountObject Clock;
276   currency LastFrame;
277 #endif
278
279   if (DemoFlag != 0)
280   {
281 #if 1
282     printf("::: playing demo ...\n");
283 #endif
284
285     // EP set level success byte: demo, not game
286     WasDemoFlag = 1;
287     EP_GameDemoVar0DAA = 0; // demo
288   }
289   else // loc_g_1836:
290   {
291 #if 1
292     printf("::: playing game ...\n");
293 #endif
294
295     // EP set level success byte: game, not demo
296     WasDemoFlag = 0;
297     EP_GameDemoVar0DAA = 1; // game
298   }
299
300   // RestartGameLoop:
301   //  If RecordDemoFlag = 1 Then
302   //    RecordDemoFlag = 0 ' clear Demo Recording flag
303   //    Call subDisplayPlayingTime                 ' playing time on screen
304   //    ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
305   //    While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
306   //      ' yes -> wait until released
307   //      ' should we DoEvents here???? ... depends on how ... but yes!
308   //      ' ...or we can rather poll the keyboardstate inside this loop???
309   //    Wend
310   //    Call subInitGameConditions     ' Init game conditions (vars)
311   //    If MusicOnFlag = 0 Then Call subMusicInit
312   //    WasDemoFlag = 0          ' no demo anymore
313   //    EP_GameDemoVar0DAA = 1 ' force game
314   //  End If
315
316   // This was a bug in the original Supaplex: sometimes red disks could not
317   // be released.  This happened If Murphy was killed DURING a red disk release
318   // and the next try started.
319
320   RedDiskReleasePhase = 0; // (re-)enable red disk release
321   UpdatedFlag = 0;
322   GameLoopRunning = 1;
323   LevelStatus = 0;
324
325   // ----------------------------------------------------------------------------
326   // --------------------- START OF GAME-BUSY LOOP ------------------------------
327   // ----------------------------------------------------------------------------
328
329 locRepeatMainGameLoop:                           // start repeating game loop
330
331   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
332   // FS   synchronization
333   while (PauseMode != 0)
334   {
335     DoEvents();
336   }
337
338   do
339   {
340     DoEvents(); // user may klick on menus or move the window here ...
341   }
342 #if 1
343   while (0);
344 #else
345   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
346 #endif
347
348   //   never any additional code between here!
349 #if 0
350   LastFrame = Clock.TickNow(); // store the frame time
351 #endif
352   //   never any additional code between here!
353   if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
354     Stage.Blt();
355
356   // FS   end of synchronization
357   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
358   if (EndFlag)
359     goto locExitMainGameLoop;
360
361   // If DemoFlag = 0 Then Call subCheckJoystick    ' check joystick
362   // bx = subCheckRightMouseButton()                ' check (right) mouse button
363   // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
364
365   //  If DebugVersionFlag <> 0 Then ' debug mode on?
366   //    If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
367   //    If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
368   //                                          ' fixes ENTER bug If no mouse driver!
369   //    If bx <> 1 Then GoTo loc_g_186F  ' Left button=Init game field
370   //                                    ' Also Enter If no mouse!
371   //    If Data_SubRest <> 0 Then GoTo loc_g_186F
372   //    Data_SubRest = 10
373   //    Call subRestoreFancy
374   //    Call subDisplayLevel         ' Paint (Init) game field
375   //    Call subConvertToEasySymbols ' Convert to easy symbols
376   //  End If
377
378   // loc_g_186F:
379
380   subProcessKeyboardInput();                 // Check keyboard, act on keys
381
382   // 'HACK:
383   //  TimerVar = TimerVar + 1
384   //  DoEvents
385   //  GoTo loc_g_186F
386   // 'END HACK
387   // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
388
389   // ----------------------------------------------------------------------------
390   //
391
392 #if 0
393   printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
394 #endif
395
396   subDoGameStuff();                 // do all game stuff
397
398 #if 0
399   printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
400 #endif
401
402   //
403   // ----------------------------------------------------------------------------
404
405   //  Call subDisplayPlayingTime                 ' playing time on screen
406
407   subCheckRestoreRedDiskCountDisplay();    // Restore panel: red-disk hole
408
409   subRedDiskReleaseExplosion();       // Red Disk release and explode
410   subFollowUpExplosions();  // every explosion may cause up to 8 following explosions
411
412   bx = subCalculateScreenScrollPos();     // calculate screen start addrs
413
414   ScreenPosition = bx;
415
416   // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
417   data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
418   data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
419   if ((! UserDragFlag) && AutoScrollFlag)
420   {
421 #if 0
422     printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
423 #endif
424
425     ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
426   }
427
428   if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
429     goto locExitMainGameLoop;
430
431   TimerVar = TimerVar + 1;
432
433 #if 0
434   if (bCapturePane)
435     MainForm.SaveSnapshot(TimerVar);
436 #endif
437
438   //  If Not NoDisplayFlag Then
439   //    With MainForm.lblFrameCount
440   //      .Caption = TimerVar
441   //      .Refresh
442   //    End With
443   //  End If
444   if (ExitToMenuFlag == 1)
445     goto locExitMainGameLoop;
446
447   if (LeadOutCounter == 0) // no lead-out: game busy
448     goto locRepeatMainGameLoop;
449
450   // ----------------------------------------------------------------------------
451   // ---------------------- END OF GAME-BUSY LOOP -------------------------------
452   // ----------------------------------------------------------------------------
453   LeadOutCounter = LeadOutCounter - 1;             // do more lead-out after quit
454   if (LeadOutCounter != 0) // lead-out not ready: more
455     goto locRepeatMainGameLoop;
456
457   // lead-out done: exit now
458   // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
459
460 locExitMainGameLoop:
461   do
462   {
463     DoEvents(); // user may klick on menus or move the window here ...
464   }
465 #if 1
466   while (0);
467 #else
468   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
469 #endif
470
471   Stage.Blt(); // blit the last frame
472   GameLoopRunning = 0;
473
474 #if 0
475   MainForm.menStop_Click();
476   MainForm.PanelVisible = True;
477 #endif
478
479   // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
480   if (SavedGameFlag != 0) // after savegame: no update!
481   {
482     SavedGameFlag = 0;
483     return subMainGameLoop;
484   }
485
486   SavedGameFlag = 0;
487   if (UpdateTimeFlag == 0) // update time?
488     return subMainGameLoop;
489
490   if (UpdatedFlag == 0) // update playing time
491     subUpdatePlayingTime();
492
493
494   return subMainGameLoop;
495 } // subMainGameLoop
496
497 void subUpdatePlayingTime()
498 {
499 }
500
501 int subCalculateScreenScrollPos()
502 {
503   int subCalculateScreenScrollPos;
504
505   int ax, Ay;
506
507   if (ExplosionShake != 0)
508   {
509     subGetRandomNumber();
510   }
511
512   {
513     ax = MainForm.picPane.Width / 2;
514     Ay = MainForm.picPane.Height / 2;
515   }
516
517 #if 1
518   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 16) - ax;
519   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 16) - Ay;
520 #else
521   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax;
522   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay;
523 #endif
524
525 #if 0
526   printf("::: MainGameLoop.c: subCalculateScreenScrollPos(): %d, %d [%d, %d] -> %d, %d\n",
527          MainForm.picPane.Width, MainForm.picPane.Height,
528          MurphyScreenXPos, MurphyScreenYPos,
529          ScreenScrollXPos, ScreenScrollYPos);
530 #endif
531
532   return subCalculateScreenScrollPos;
533 }