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