rnd-20091011-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   if (ExitToMenuFlag == 1)
210     goto locExitMainGameLoop;
211
212   if (LeadOutCounter == 0) // no lead-out: game busy
213     goto locRepeatMainGameLoop;
214
215   // ----------------------------------------------------------------------------
216   // ---------------------- END OF GAME-BUSY LOOP -------------------------------
217   // ----------------------------------------------------------------------------
218   LeadOutCounter = LeadOutCounter - 1;             // do more lead-out after quit
219   if (LeadOutCounter != 0) // lead-out not ready: more
220     goto locRepeatMainGameLoop;
221
222   // lead-out done: exit now
223   // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
224
225 locExitMainGameLoop:
226   do
227   {
228     DoEvents(); // user may klick on menus or move the window here ...
229   }
230 #if 1
231   while (0);
232 #else
233   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
234 #endif
235
236   Stage.Blt(); // blit the last frame
237   GameLoopRunning = 0;
238
239 #if 0
240   MainForm.menStop_Click();
241   MainForm.PanelVisible = True;
242 #endif
243
244   // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
245   if (SavedGameFlag != 0) // after savegame: no update!
246   {
247     SavedGameFlag = 0;
248     return subMainGameLoop;
249   }
250
251   SavedGameFlag = 0;
252   if (UpdateTimeFlag == 0) // update time?
253     return subMainGameLoop;
254
255   if (UpdatedFlag == 0) // update playing time
256     subUpdatePlayingTime();
257
258
259   return subMainGameLoop;
260 } // subMainGameLoop
261
262 int subMainGameLoop()
263 {
264   int subMainGameLoop;
265
266   // int al, bx;
267   int bx;
268 #if 0
269   TickCountObject Clock;
270   currency LastFrame;
271 #endif
272
273   if (DemoFlag != 0)
274   {
275 #if 1
276     printf("::: playing demo ...\n");
277 #endif
278
279     // EP set level success byte: demo, not game
280     WasDemoFlag = 1;
281     EP_GameDemoVar0DAA = 0; // demo
282   }
283   else // loc_g_1836:
284   {
285 #if 1
286     printf("::: playing game ...\n");
287 #endif
288
289     // EP set level success byte: game, not demo
290     WasDemoFlag = 0;
291     EP_GameDemoVar0DAA = 1; // game
292   }
293
294   // RestartGameLoop:
295   //  If RecordDemoFlag = 1 Then
296   //    RecordDemoFlag = 0 ' clear Demo Recording flag
297   //    Call subDisplayPlayingTime                 ' playing time on screen
298   //    ' Record key still pressed?' >= (Ctrl-)F1 and <= (Ctrl-)F10
299   //    While &H3B <= KeyScanCode7 And KeyScanCode7 <= &H44
300   //      ' yes -> wait until released
301   //      ' should we DoEvents here???? ... depends on how ... but yes!
302   //      ' ...or we can rather poll the keyboardstate inside this loop???
303   //    Wend
304   //    Call subInitGameConditions     ' Init game conditions (vars)
305   //    If MusicOnFlag = 0 Then Call subMusicInit
306   //    WasDemoFlag = 0          ' no demo anymore
307   //    EP_GameDemoVar0DAA = 1 ' force game
308   //  End If
309
310   // This was a bug in the original Supaplex: sometimes red disks could not
311   // be released.  This happened If Murphy was killed DURING a red disk release
312   // and the next try started.
313
314   RedDiskReleasePhase = 0; // (re-)enable red disk release
315   UpdatedFlag = 0;
316   GameLoopRunning = 1;
317   LevelStatus = 0;
318
319   // ----------------------------------------------------------------------------
320   // --------------------- START OF GAME-BUSY LOOP ------------------------------
321   // ----------------------------------------------------------------------------
322
323 locRepeatMainGameLoop:                           // start repeating game loop
324
325   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
326   // FS   synchronization
327   while (PauseMode != 0)
328   {
329     DoEvents();
330   }
331
332   do
333   {
334     DoEvents(); // user may klick on menus or move the window here ...
335   }
336 #if 1
337   while (0);
338 #else
339   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
340 #endif
341
342   //   never any additional code between here!
343 #if 0
344   LastFrame = Clock.TickNow(); // store the frame time
345 #endif
346   //   never any additional code between here!
347   if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen
348     Stage.Blt();
349
350   // FS   end of synchronization
351   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
352   if (EndFlag)
353     goto locExitMainGameLoop;
354
355   // If DemoFlag = 0 Then Call subCheckJoystick    ' check joystick
356   // bx = subCheckRightMouseButton()                ' check (right) mouse button
357   // If bx = 2 And LeadOutCounter < 1 Then KillMurphyFlag = 1 ' lead-out busy after quit? -> kill Murphy!
358
359   //  If DebugVersionFlag <> 0 Then ' debug mode on?
360   //    If Data_SubRest <> 0 Then Data_SubRest = Data_SubRest - 1
361   //    If keyEnter <> 0 Then GoTo loc_g_186F ' Was it the Enter key? -> yes--skip! No mouse!
362   //                                          ' fixes ENTER bug If no mouse driver!
363   //    If bx <> 1 Then GoTo loc_g_186F  ' Left button=Init game field
364   //                                    ' Also Enter If no mouse!
365   //    If Data_SubRest <> 0 Then GoTo loc_g_186F
366   //    Data_SubRest = 10
367   //    Call subRestoreFancy
368   //    Call subDisplayLevel         ' Paint (Init) game field
369   //    Call subConvertToEasySymbols ' Convert to easy symbols
370   //  End If
371
372   // loc_g_186F:
373
374   subProcessKeyboardInput();                 // Check keyboard, act on keys
375
376   // 'HACK:
377   //  TimerVar = TimerVar + 1
378   //  DoEvents
379   //  GoTo loc_g_186F
380   // 'END HACK
381   // If RecordDemoFlag = 1 Then GoTo RestartGameLoop
382
383   // ----------------------------------------------------------------------------
384   //
385
386 #if 0
387   printf("::: >>>>>>>>>> MainGameLoop.c: subDoGameStuff() START\n");
388 #endif
389
390   subDoGameStuff();                 // do all game stuff
391
392 #if 0
393   printf("::: <<<<<<<<<< MainGameLoop.c: subDoGameStuff() END\n");
394 #endif
395
396   //
397   // ----------------------------------------------------------------------------
398
399   //  Call subDisplayPlayingTime                 ' playing time on screen
400
401   subCheckRestoreRedDiskCountDisplay();    // Restore panel: red-disk hole
402
403   subRedDiskReleaseExplosion();       // Red Disk release and explode
404   subFollowUpExplosions();  // every explosion may cause up to 8 following explosions
405
406   bx = subCalculateScreenScrollPos();     // calculate screen start addrs
407
408   ScreenPosition = bx;
409
410   // Now new X and new Y are calculated, and bx = screen position = ScreenPosition
411   data_h_Ytmp = ScreenScrollYPos; // copy Y for next soft scroll
412   data_h_Xtmp = ScreenScrollXPos; // copy X for next soft scroll
413   if ((! UserDragFlag) && AutoScrollFlag)
414   {
415 #if 0
416     printf("::: MainGameLoop.c: subMainGameLoop(): %d, %d\n", ScreenScrollXPos, ScreenScrollYPos);
417 #endif
418
419     ScrollTowards(ScreenScrollXPos, ScreenScrollYPos);
420   }
421
422   if (ForcedExitFlag != 0) // Forced Exit?' yes--exit!
423     goto locExitMainGameLoop;
424
425   TimerVar = TimerVar + 1;
426
427 #if 0
428   if (bCapturePane)
429     MainForm.SaveSnapshot(TimerVar);
430 #endif
431
432   //  If Not NoDisplayFlag Then
433   //    With MainForm.lblFrameCount
434   //      .Caption = TimerVar
435   //      .Refresh
436   //    End With
437   //  End If
438   if (ExitToMenuFlag == 1)
439     goto locExitMainGameLoop;
440
441   if (LeadOutCounter == 0) // no lead-out: game busy
442     goto locRepeatMainGameLoop;
443
444   // ----------------------------------------------------------------------------
445   // ---------------------- END OF GAME-BUSY LOOP -------------------------------
446   // ----------------------------------------------------------------------------
447   LeadOutCounter = LeadOutCounter - 1;             // do more lead-out after quit
448   if (LeadOutCounter != 0) // lead-out not ready: more
449     goto locRepeatMainGameLoop;
450
451   // lead-out done: exit now
452   // ---------------------- END OF GAME-BUSY LOOP (including lead-out) ----------
453
454 locExitMainGameLoop:
455   do
456   {
457     DoEvents(); // user may klick on menus or move the window here ...
458   }
459 #if 1
460   while (0);
461 #else
462   while (Clock.TickDiffUS(LastFrame) < DeltaT); // wait till its time for the next frame
463 #endif
464
465   Stage.Blt(); // blit the last frame
466   GameLoopRunning = 0;
467
468 #if 0
469   MainForm.menStop_Click();
470   MainForm.PanelVisible = True;
471 #endif
472
473   // If DemoRecordingFlag <> 0 Then Call subCloseDemoRecordingFile ' Demo recording on? -> close opened demo file (w)
474   if (SavedGameFlag != 0) // after savegame: no update!
475   {
476     SavedGameFlag = 0;
477     return subMainGameLoop;
478   }
479
480   SavedGameFlag = 0;
481   if (UpdateTimeFlag == 0) // update time?
482     return subMainGameLoop;
483
484   if (UpdatedFlag == 0) // update playing time
485     subUpdatePlayingTime();
486
487
488   return subMainGameLoop;
489 } // subMainGameLoop
490
491 void subUpdatePlayingTime()
492 {
493 }
494
495 int subCalculateScreenScrollPos()
496 {
497   int subCalculateScreenScrollPos;
498
499   int ax, Ay;
500
501   if (ExplosionShake != 0)
502   {
503     subGetRandomNumber();
504   }
505
506   {
507     ax = MainForm.picPane.Width / 2;
508     Ay = MainForm.picPane.Height / 2;
509   }
510
511 #if 1
512   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 16) - ax;
513   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 16) - Ay;
514 #else
515   ScreenScrollXPos = Stretch * (MurphyScreenXPos + 8) - ax;
516   ScreenScrollYPos = Stretch * (MurphyScreenYPos + 8) - Ay;
517 #endif
518
519 #if 0
520   printf("::: MainGameLoop.c: subCalculateScreenScrollPos(): %d, %d [%d, %d] -> %d, %d\n",
521          MainForm.picPane.Width, MainForm.picPane.Height,
522          MurphyScreenXPos, MurphyScreenYPos,
523          ScreenScrollXPos, ScreenScrollYPos);
524 #endif
525
526   return subCalculateScreenScrollPos;
527 }