OSDN Git Service

going on vacation >.<
[proj16/16.git] / src / lib / hb / play / c6_play.c
1 /* Catacomb Apocalypse Source Code\r
2  * Copyright (C) 1993-2014 Flat Rock Software\r
3  *\r
4  * This program is free software; you can redistribute it and/or modify\r
5  * it under the terms of the GNU General Public License as published by\r
6  * the Free Software Foundation; either version 2 of the License, or\r
7  * (at your option) any later version.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License along\r
15  * with this program; if not, write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
17  */\r
18 \r
19 // C3_PLAY.C\r
20 \r
21 #include "DEF.H"\r
22 #include "gelib.h"\r
23 #pragma hdrstop\r
24 \r
25 /*\r
26 =============================================================================\r
27 \r
28                                                  LOCAL CONSTANTS\r
29 \r
30 =============================================================================\r
31 */\r
32 \r
33 #define POINTTICS       6\r
34 #define PAUSE 300\r
35 \r
36 /*\r
37 =============================================================================\r
38 \r
39                                                  GLOBAL VARIABLES\r
40 \r
41 =============================================================================\r
42 */\r
43 \r
44 byte bcolor;\r
45 short skytimer=-1,skytimer_reset;\r
46 short groundtimer=-1,groundtimer_reset;\r
47 \r
48 unsigned scolor,gcolor;\r
49 unsigned *skycolor,*groundcolor,debug_sky,debug_gnd;\r
50 \r
51 unsigned nocolorchange=0xFFFF;\r
52 byte BGFLAGS,                           // global that holds all current flags\r
53           bgflag;                               // used by BG changer, this flag is set when done\r
54 \r
55 \r
56 unsigned sky_daytonight[]={0x0909,0x0101,0x0808,0x0000,0xFFFF};\r
57 //unsigned gnd_daytonight[]={0x0202,0xFFFF};\r
58 \r
59 unsigned sky_lightning[]={0x0101,0x0909,0x0f0f,0x0808,0x0000,0xFFFF};\r
60 \r
61 unsigned sky_colors[NUMLEVELS]={0x0000,0x0000,0x0000,0x0000,0x0808,\r
62                                                                                   0x0404,0x0000,0x0000,0x0000,0x0000,\r
63                                                                                   0x0000,0x0000,0x0000,0x0000,0x0606,\r
64                                                                                   0x0000,0x0000,0x0000,0x0000,0x0000,\r
65                                                                                   0x0000};\r
66 unsigned gnd_colors[NUMLEVELS]={0x0202,0x0202,0x0606,0x0202,0x0707,\r
67                                                                                   0x0505,0x0808,0x0606,0x0101,0x0808,\r
68                                                                                   0x0606,0x0404,0x0808,0x0c0c,0x0e0e,\r
69                                                                                   0x0808,0x0808,0x0c0c,0x0000,0x0707,\r
70                                                                                   0x0808};\r
71 \r
72 \r
73 ControlInfo     control;\r
74 boolean         running=false; //,slowturn;\r
75 \r
76 int                     bordertime;\r
77 objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,*objfreelist;\r
78 \r
79 #if USE_INERT_LIST\r
80 inertobjtype inertobjlist[MAXINERTOBJ],*inert;\r
81 #endif\r
82 \r
83 unsigned        farmapylookup[MAPSIZE];\r
84 byte            *nearmapylookup[MAPSIZE];\r
85 \r
86 boolean         singlestep,godmode;\r
87 int                     extravbls;\r
88 status_flags    status_flag;\r
89 int             status_delay;\r
90 \r
91 //\r
92 // replacing refresh manager\r
93 //\r
94 unsigned        mapwidth,mapheight,tics,realtics;\r
95 boolean         compatability;\r
96 byte            *updateptr;\r
97 unsigned        mapwidthtable[64];\r
98 unsigned        uwidthtable[UPDATEHIGH];\r
99 unsigned        blockstarts[UPDATEWIDE*UPDATEHIGH];\r
100 #define UPDATESCREENSIZE        (UPDATEWIDE*PORTTILESHIGH+2)\r
101 #define UPDATESPARESIZE         (UPDATEWIDE*2+4)\r
102 #define UPDATESIZE                      (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
103 byte            update[UPDATESIZE];\r
104 \r
105 int             mousexmove,mouseymove;\r
106 int             pointcount,pointsleft;\r
107 \r
108 short BeepTime = 0;\r
109 \r
110 /*\r
111 =============================================================================\r
112 \r
113                                                  LOCAL VARIABLES\r
114 \r
115 =============================================================================\r
116 */\r
117 \r
118 void CalcBounds (objtype *ob);\r
119 void DrawPlayScreen (void);\r
120 void PreFullDisplay(void);\r
121 void PostFullDisplay(boolean draw_view);\r
122 \r
123 \r
124 //\r
125 // near data map array (wall values only, get text number from far data)\r
126 //\r
127 byte            tilemap[MAPSIZE][MAPSIZE];\r
128 byte            spotvis[MAPSIZE][MAPSIZE];\r
129 objtype         *actorat[MAPSIZE][MAPSIZE];\r
130 \r
131 objtype dummyobj;\r
132 \r
133 int bordertime;\r
134 int     objectcount;\r
135 \r
136 void StopMusic(void);\r
137 void StartMusic(void);\r
138 \r
139 void CalibrateJoystick(short joynum);\r
140 \r
141 //==========================================================================\r
142 \r
143 ///////////////////////////////////////////////////////////////////////////\r
144 //\r
145 //      CenterWindow() - Generates a window of a given width & height in the\r
146 //              middle of the screen\r
147 //\r
148 ///////////////////////////////////////////////////////////////////////////\r
149 \r
150 #define MAXX    320\r
151 #define MAXY    120\r
152 \r
153 void    CenterWindow(word w,word h)\r
154 {\r
155         US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);\r
156 }\r
157 \r
158 //===========================================================================\r
159 \r
160 \r
161 /*\r
162 =====================\r
163 =\r
164 = CheckKeys\r
165 =\r
166 =====================\r
167 */\r
168 \r
169 void CheckKeys (void)\r
170 {\r
171         extern boolean autofire;\r
172 \r
173         if (screenfaded)                        // don't do anything with a faded screen\r
174                 return;\r
175 \r
176 #if 0\r
177 //\r
178 // pause key wierdness can't be checked as a scan code\r
179 //\r
180         if (Paused)\r
181         {\r
182                 CenterWindow (8,3);\r
183                 US_PrintCentered ("PAUSED");\r
184                 VW_UpdateScreen ();\r
185 //              SD_MusicOff();\r
186                 IN_Ack();\r
187 //              SD_MusicOn();\r
188                 Paused = false;\r
189                 if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
190         }\r
191         else\r
192         if (Keyboard[sc_Enter])                 // P = pause with no screen disruptioon\r
193         {\r
194 //              SD_MusicOff();\r
195                 DisplaySMsg("PAUSED",NULL);\r
196                 IN_Ack();\r
197 //              SD_MusicOn();\r
198                 if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
199         }\r
200         else\r
201         if (Keyboard[sc_S])\r
202         {\r
203                 char *Text[] = {{"Slow Mode ON"},{"Slow Mode OFF"}};\r
204 \r
205                 SlowMode ^= 1;\r
206                 extravbls = SlowMode << 3;\r
207                 CenterWindow (8,3);\r
208                 US_PrintCentered (Text[SlowMode]);\r
209                 VW_UpdateScreen ();\r
210 //              SD_MusicOff();\r
211                 IN_Ack();\r
212 //              SD_MusicOn();\r
213                 if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
214         }\r
215 #endif\r
216 \r
217 \r
218 // F2 - SOUND OPTIONS\r
219 //\r
220         if (Keyboard[sc_F2])\r
221         {\r
222                 int height=7;\r
223                 boolean ChoiceMade = false;\r
224 \r
225                 if (AdLibPresent)\r
226                         height++;\r
227 \r
228                 VW_FixRefreshBuffer();\r
229                 CenterWindow(22,height);\r
230                 US_Print( "\n        1 )  NO SOUND \n");\r
231                 US_Print(   "        2 )  PC  AUDIO \n");\r
232 \r
233                 if (AdLibPresent)\r
234                         US_Print("        3 ) ADLIB AUDIO\n");\r
235 \r
236                 US_Print( "\n       ESC)    EXIT    ");\r
237                 VW_UpdateScreen();\r
238 \r
239                 // Switch audio device ON/OFF & load sounds if there\r
240                 // was a change in the device.\r
241 \r
242                 do {\r
243 \r
244                         if (Keyboard[1])                                                                // ESC - Exit\r
245                                 ChoiceMade = true;\r
246                         else\r
247                         if (Keyboard[2])                                                                // 1 - No Sound\r
248                         {\r
249                                 SD_SetSoundMode(sdm_Off);\r
250                                 ChoiceMade = true;\r
251                         }\r
252                         else\r
253                         if (Keyboard[3])                                                        // 2 - PC Audio\r
254                         {\r
255                                 SD_SetSoundMode(sdm_PC);\r
256 //                              if (oldsoundmode != sdm_PC)\r
257                                         CA_LoadAllSounds();\r
258                                 ChoiceMade = true;\r
259                         }\r
260                         else\r
261                         if ((Keyboard[4]) &&    AdLibPresent)           // 3 - AdLib Audio\r
262                         {\r
263                                 SD_SetSoundMode(sdm_AdLib);\r
264 //                              if (oldsoundmode != sdm_AdLib)\r
265                                         CA_LoadAllSounds();\r
266                                 ChoiceMade = true;\r
267                         }\r
268 \r
269                 } while (!ChoiceMade);\r
270                 tics = realtics = 1;\r
271                 IN_ClearKeysDown();\r
272         }\r
273 \r
274 // F5 - CALIBRATE JOYSTICK\r
275 //\r
276         if (Keyboard[sc_F5])\r
277         {\r
278                 CalibrateJoystick(0);\r
279                 tics = realtics = 1;\r
280                 IN_ClearKeysDown();\r
281         }\r
282 \r
283 deadloop:;\r
284 // ESCAPE - quits game\r
285 //\r
286         if ((Keyboard[sc_Escape]) || (Flags & FL_DEAD))\r
287         {\r
288                 char ch;\r
289 \r
290                 DisplaySMsg("Options", NULL);\r
291                 status_flag = S_NONE;\r
292 \r
293 \r
294                 if (Flags & FL_DEAD)\r
295                 {\r
296                         char choices[] = {sc_Escape,sc_R,sc_N,sc_Q,0};\r
297                         ch = DisplayMsg("Restore          New          Quit",choices);\r
298                         DisplayMsg("                                      ", NULL);\r
299                 }\r
300                 else\r
301                 {\r
302                         char choices[] = {sc_Escape,sc_S,sc_R,sc_N,sc_Q,0};\r
303                         ch = DisplayMsg("Save       Restore       New       Quit",choices);\r
304                 }\r
305                 DrawText(true);\r
306 \r
307                 switch (ch)\r
308                 {\r
309                         case sc_S:\r
310                                 if (!(Flags & FL_DEAD))\r
311                                         Keyboard[sc_F3] = true;\r
312                         break;\r
313 \r
314                         case sc_R:\r
315                                 Keyboard[sc_F4] = true;\r
316                         break;\r
317 \r
318                         case sc_N:\r
319                                 DisplaySMsg("Starting anew", NULL);\r
320                                 VW_WaitVBL(60);\r
321                                 playstate = ex_resetgame;\r
322                                 Flags &= ~FL_DEAD;\r
323                         break;\r
324 \r
325                         case sc_Q:\r
326                                 DisplaySMsg("FARE THEE WELL!", NULL);\r
327                                 VW_WaitVBL(120);\r
328                                 if (!Flags & FL_QUICK)\r
329                                         VW_FadeOut();\r
330                                 NormalScreen();\r
331                                 FreeUpMemory();\r
332                                 Quit(NULL);\r
333                         break;\r
334                 }\r
335                 tics = realtics = 1;\r
336         }\r
337 \r
338 // F1 - DISPLAY HELP\r
339 //\r
340         if (Keyboard[sc_F1])\r
341         {\r
342                 PrintHelp();\r
343 \r
344 #ifdef TEXT_PRESENTER\r
345 \r
346                 extern PresenterInfo MainHelpText;\r
347 \r
348                 VW_FadeOut();\r
349 \r
350                 FreeUpMemory();\r
351                 if (!LoadPresenterScript("HELP.TXT",&MainHelpText))\r
352                 {\r
353                         VW_FadeIn();\r
354                         CenterWindow(30,5);\r
355                         US_CPrint("\nError loading HELP file.\n");\r
356                         US_CPrint("Press any key.");\r
357                         IN_Ack();\r
358                         VW_FadeOut();\r
359                 }\r
360                 else\r
361                 {\r
362                         VW_SetSplitScreen(200);\r
363                         bufferofs = displayofs = screenloc[0];\r
364                         VW_Bar(0,0,320,200,0);\r
365 \r
366                         Display640();\r
367                         Presenter(&MainHelpText);\r
368                         Display320();\r
369                 }\r
370                 FreePresenterScript(&MainHelpText);\r
371 #endif\r
372                 VW_SetSplitScreen(120);\r
373                 VW_SetScreen(screenloc[0],0);\r
374                 screenpage = 0;\r
375                 CacheScaleds();\r
376 \r
377                 bufferofs = 0;\r
378                 RedrawStatusWindow();\r
379                 ThreeDRefresh();\r
380                 VW_FadeIn();\r
381                 Keyboard[sc_F1] = false;\r
382                 tics = realtics = 1;\r
383                 IN_ClearKeysDown();\r
384         }\r
385 \r
386 // F3 - SAVE GAME\r
387 //\r
388         if ((Keyboard[sc_F3]) && (!(Flags & FL_DEAD)))\r
389         {\r
390                 PreFullDisplay();\r
391                 GE_SaveGame();\r
392                 PostFullDisplay(true);\r
393                 tics = realtics = 1;\r
394                 IN_ClearKeysDown();\r
395         }\r
396 \r
397 // F4 - LOAD GAME\r
398 //\r
399         if (Keyboard[sc_F4])\r
400         {\r
401                 PreFullDisplay();\r
402                 if (GE_LoadGame())\r
403                 {\r
404                         loadedgame = true;\r
405                         playstate = ex_loadedgame;\r
406                         Flags &= ~FL_DEAD;\r
407                         lasttext = -1;\r
408                         PostFullDisplay(false);\r
409                 }\r
410                 else\r
411                 if (playstate == ex_victorious)\r
412                 {\r
413                         PostFullDisplay(false);\r
414                         Victory(false);\r
415                         IN_Ack();\r
416                         Quit(NULL);\r
417                 }\r
418                 else\r
419                         PostFullDisplay(true);\r
420                 Keyboard[sc_F5] = false;\r
421                 tics = realtics = 1;\r
422                 IN_ClearKeysDown();\r
423         }\r
424 \r
425         if (Flags & FL_DEAD)\r
426                 goto deadloop;\r
427 \r
428 //\r
429 // F10-? debug keys\r
430 //\r
431         if (Keyboard[sc_BackSpace])\r
432         {\r
433                 DebugKeys();\r
434                 if (MousePresent) Mouse(MDelta);        // Clear accumulated mouse movement\r
435                 lasttimecount = TimeCount;\r
436         }\r
437 }\r
438 \r
439 //-------------------------------------------------------------------------\r
440 // PreFullDisplay()\r
441 //-------------------------------------------------------------------------\r
442 void PreFullDisplay()\r
443 {\r
444         VW_FadeOut();\r
445         VW_SetSplitScreen(200);\r
446         bufferofs = displayofs = screenloc[0];\r
447         VW_Bar(0,0,320,200,0);\r
448 }\r
449 \r
450 //-------------------------------------------------------------------------\r
451 // PostFullDisplay()\r
452 //-------------------------------------------------------------------------\r
453 void PostFullDisplay(boolean draw_view)\r
454 {\r
455         VW_SetSplitScreen(120);\r
456         bufferofs = 0;\r
457         RedrawStatusWindow();\r
458         if (draw_view)\r
459         {\r
460                 ThreeDRefresh();\r
461                 VW_FadeIn();\r
462         }\r
463 }\r
464 \r
465 \r
466 //===========================================================================\r
467 \r
468 /*\r
469 #############################################################################\r
470 \r
471                                   The objlist data structure\r
472 \r
473 #############################################################################\r
474 \r
475 objlist containt structures for every actor currently playing.  The structure\r
476 is accessed as a linked list starting at *player, ending when ob->next ==\r
477 NULL.  GetNewObj inserts a new object at the end of the list, meaning that\r
478 if an actor spawn another actor, the new one WILL get to think and react the\r
479 same frame.  RemoveObj unlinks the given object and returns it to the free\r
480 list, but does not damage the objects ->next pointer, so if the current object\r
481 removes itself, a linked list following loop can still safely get to the\r
482 next element.\r
483 \r
484 <backwardly linked free list>\r
485 \r
486 #############################################################################\r
487 */\r
488 \r
489 \r
490 /*\r
491 =========================\r
492 =\r
493 = InitObjList\r
494 =\r
495 = Call to clear out the entire object list, returning them all to the free\r
496 = list.  Allocates a special spot for the player.\r
497 =\r
498 =========================\r
499 */\r
500 \r
501 void InitObjList (void)\r
502 {\r
503         int     i;\r
504 \r
505         for (i=0;i<MAXACTORS;i++)\r
506         {\r
507                 objlist[i].prev = &objlist[i+1];\r
508                 objlist[i].next = NULL;\r
509         }\r
510 \r
511         objlist[MAXACTORS-1].prev = NULL;\r
512 \r
513         objfreelist = &objlist[0];\r
514         lastobj = NULL;\r
515 \r
516         objectcount = 0;\r
517 \r
518 //\r
519 // give the player and score the first free spots\r
520 //\r
521         GetNewObj (false);\r
522         player = new;\r
523 \r
524 #if USE_INERT_LIST\r
525         inert = inertobjlist;\r
526 #endif\r
527 \r
528 }\r
529 \r
530 //===========================================================================\r
531 \r
532 /*\r
533 =========================\r
534 =\r
535 = GetNewObj\r
536 =\r
537 = Sets the global variable new to point to a free spot in objlist.\r
538 = The free spot is inserted at the end of the liked list\r
539 =\r
540 = When the object list is full, the caller can either have it bomb out ot\r
541 = return a dummy object pointer that will never get used\r
542 =\r
543 =========================\r
544 */\r
545 \r
546 void GetNewObj (boolean usedummy)\r
547 {\r
548         if (!objfreelist)\r
549         {\r
550                 if (usedummy)\r
551                 {\r
552                         new = &dummyobj;\r
553                         return;\r
554                 }\r
555                 Quit ("GetNewObj: No free spots in objlist!");\r
556         }\r
557 \r
558         new = objfreelist;\r
559         objfreelist = new->prev;\r
560         memset (new,0,sizeof(*new));\r
561 \r
562         if (lastobj)\r
563                 lastobj->next = new;\r
564         new->prev = lastobj;    // new->next is allready NULL from memset\r
565 \r
566         new->active = false;\r
567         lastobj = new;\r
568 \r
569         objectcount++;\r
570 }\r
571 \r
572 //===========================================================================\r
573 \r
574 /*\r
575 =========================\r
576 =\r
577 = RemoveObj\r
578 =\r
579 = Add the given object back into the free list, and unlink it from it's\r
580 = neighbors\r
581 =\r
582 =========================\r
583 */\r
584 \r
585 void RemoveObj (objtype *gone)\r
586 {\r
587         objtype **spotat;\r
588 \r
589         if (gone == player)\r
590                 Quit ("RemoveObj: Tried to remove the player!");\r
591 \r
592 //\r
593 // fix the next object's back link\r
594 //\r
595         if (gone == lastobj)\r
596                 lastobj = (objtype *)gone->prev;\r
597         else\r
598                 gone->next->prev = gone->prev;\r
599 \r
600 //\r
601 // fix the previous object's forward link\r
602 //\r
603         gone->prev->next = gone->next;\r
604 \r
605 //\r
606 // add it back in to the free list\r
607 //\r
608         gone->prev = objfreelist;\r
609         objfreelist = gone;\r
610 \r
611         objectcount--;\r
612 }\r
613 \r
614 #if USE_INERT_LIST\r
615 \r
616 //--------------------------------------------------------------------------\r
617 // MoveObjToInert()\r
618 //--------------------------------------------------------------------------\r
619 void MoveObjToInert(objtype *obj)\r
620 {\r
621 \r
622         if (inert == &inertobjlist[MAXINERTOBJ])\r
623                 return;\r
624 \r
625 // Transfer info needed by inert objtype\r
626 //\r
627         inert->x = obj->x;\r
628         inert->y = obj->y;\r
629         inert->size = obj->size;\r
630         inert->viewx = obj->viewx;\r
631         inert->tilex = obj->tilex;\r
632         inert->tiley = obj->tiley;\r
633         inert->state = obj->state;\r
634         inert->ticcount = obj->ticcount;\r
635 \r
636 // Setup links between inert objects\r
637 //\r
638         if (inert != inertobjlist)\r
639                 (inert-1)->next = inert;\r
640         inert->next = NULL;\r
641         inert++;\r
642 \r
643 // Free 'real' object from list.\r
644 //\r
645         RemoveObj(obj);\r
646 }\r
647 \r
648 #endif\r
649 \r
650 //==========================================================================\r
651 \r
652 /*\r
653 ===================\r
654 =\r
655 = PollControls\r
656 =\r
657 ===================\r
658 */\r
659 \r
660 void PollControls (void)\r
661 {\r
662         unsigned buttons;\r
663 \r
664         IN_ReadControl(0,&control);\r
665 \r
666         if (MousePresent)\r
667         {\r
668                 Mouse(MButtons);\r
669                 buttons = _BX;\r
670                 Mouse(MDelta);\r
671                 mousexmove = _CX;\r
672                 mouseymove = _DX;\r
673 \r
674                 if (buttons&1)\r
675                         control.button0 = 1;\r
676                 if (buttons&2)\r
677                         control.button1 = 1;\r
678 \r
679         }\r
680 \r
681         if (Keyboard[sc_V] || Keyboard[sc_Tab])\r
682                 running = true;\r
683         else\r
684                 running = false;\r
685 }\r
686 \r
687 //==========================================================================\r
688 \r
689 #if 0\r
690 /*\r
691 =================\r
692 =\r
693 = StopMusic\r
694 =\r
695 =================\r
696 */\r
697 \r
698 void StopMusic(void)\r
699 {\r
700         int     i;\r
701 \r
702         SD_MusicOff();\r
703         for (i = 0;i < LASTMUSIC;i++)\r
704                 if (audiosegs[STARTMUSIC + i])\r
705                 {\r
706                         MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);\r
707                         MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);\r
708                 }\r
709 }\r
710 \r
711 //==========================================================================\r
712 \r
713 \r
714 /*\r
715 =================\r
716 =\r
717 = StartMusic\r
718 =\r
719 =================\r
720 */\r
721 \r
722 // JAB - Cache & start the appropriate music for this level\r
723 void StartMusic(void)\r
724 {\r
725         musicnames      chunk;\r
726 \r
727         SD_MusicOff();\r
728         chunk = TOOHOT_MUS;\r
729 //      if ((chunk == -1) || (MusicMode != smm_AdLib))\r
730 //DEBUG control panel           return;\r
731 \r
732         MM_BombOnError (false);\r
733         CA_CacheAudioChunk(STARTMUSIC + chunk);\r
734         MM_BombOnError (true);\r
735         if (mmerror)\r
736                 mmerror = false;\r
737         else\r
738         {\r
739                 MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);\r
740                 SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);\r
741         }\r
742 }\r
743 #endif\r
744 \r
745 //==========================================================================\r
746 \r
747 \r
748 /*\r
749 ===================\r
750 =\r
751 = PlayLoop\r
752 =\r
753 ===================\r
754 */\r
755 \r
756 void PlayLoop (void)\r
757 {\r
758         char shot_color[3] = {4,9,14};\r
759 \r
760         int allgems[5]={GEM_DELAY_TIME,         // used for Q & D comparison\r
761                                                  GEM_DELAY_TIME,                // for having all gems...\r
762                                                  GEM_DELAY_TIME,                // the "allgems" declaration MUST\r
763                                                  GEM_DELAY_TIME,                // match the "gems" declaration in\r
764                                                  GEM_DELAY_TIME         // the gametype structure!\r
765                                                 };\r
766 \r
767 //      int originx=0;\r
768 //      int i=100;\r
769         signed long dx,dy,radius,psin,pcos,newx,newy;\r
770         int             give;\r
771         short objnum;\r
772         signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;\r
773         short o_radius;\r
774 \r
775         void (*think)();\r
776 \r
777         ingame = true;\r
778         playstate = TimeCount = 0;\r
779         gamestate.shotpower = handheight = 0;\r
780         pointcount = pointsleft = 0;\r
781 \r
782         status_flag = S_NONE;\r
783 \r
784 #if 0\r
785         // setup sky/ground colors and effects (based on level)\r
786         //\r
787         switch (gamestate.mapon)\r
788         {\r
789                 case 255:\r
790                         if (!(BGFLAGS & BGF_NIGHT))\r
791                         {\r
792                                 InitBgChange(3*60,sky_daytonight,-1,NULL,BGF_NIGHT);\r
793                                 groundcolor = &gnd_colors[0];\r
794                         }\r
795                         else\r
796                         {\r
797                                 skycolor = &sky_colors[0];\r
798                                 groundcolor = &gnd_colors[0];\r
799                         }\r
800                 break;\r
801 \r
802                 default:\r
803                         skycolor = &sky_colors[gamestate.mapon];\r
804                         groundcolor = &gnd_colors[gamestate.mapon];\r
805                         skytimer = groundtimer = -1;\r
806                 break;\r
807         }\r
808 #endif\r
809 \r
810         BGFLAGS |= BGF_NOT_LIGHTNING;\r
811         skytimer = groundtimer = -1;\r
812 \r
813         debug_gnd = *groundcolor;\r
814         debug_sky = *skycolor;\r
815         RedrawStatusWindow();\r
816         ThreeDRefresh();\r
817         if (screenfaded)\r
818                 VW_FadeIn();\r
819 \r
820 #ifndef PROFILE\r
821         fizzlein = true;                                // fizzle fade in the first refresh\r
822 #endif\r
823         TimeCount = lasttimecount = lastnuke = 0;\r
824 \r
825         PollControls ();                                // center mouse\r
826 //      StartMusic ();\r
827         do\r
828         {\r
829 #ifndef PROFILE\r
830                 PollControls();\r
831 #else\r
832                 control.xaxis = 1;\r
833                 if (++TimeCount == 300)\r
834                         return;\r
835 #endif\r
836                 DisplayStatus(&status_flag);\r
837 \r
838                 objnum=0;\r
839                 for (obj = player;obj;obj = obj->next)\r
840                 {\r
841                         if ((obj->active >= yes) && (!(FreezeTime && (obj!=player))))\r
842                         {\r
843                                 if (obj->ticcount)\r
844                                 {\r
845                                         obj->ticcount-=realtics;\r
846                                         while ( obj->ticcount <= 0)\r
847                                         {\r
848                                                 think = obj->state->think;\r
849                                                 if (think)\r
850                                                 {\r
851                                                         statetype *oldstate=obj->state;\r
852 \r
853                                                         think (obj);\r
854                                                         if (!obj->state)\r
855                                                         {\r
856                                                                 RemoveObj (obj);\r
857                                                                 goto nextactor;\r
858                                                         }\r
859                                                         if (obj->state != oldstate)\r
860                                                                 break;\r
861                                                 }\r
862 \r
863                                                 obj->state = obj->state->next;\r
864                                                 if (!obj->state)\r
865                                                 {\r
866                                                         RemoveObj (obj);\r
867                                                         goto nextactor;\r
868                                                 }\r
869                                                 if (!obj->state->tictime)\r
870                                                 {\r
871                                                         obj->ticcount = 0;\r
872                                                         goto nextactor;\r
873                                                 }\r
874                                                 if (obj->state->tictime>0)\r
875                                                         obj->ticcount += obj->state->tictime;\r
876                                         }\r
877                                 }\r
878 \r
879                                 think = obj->state->think;\r
880                                 if (think)\r
881                                 {\r
882                                         think (obj);\r
883                                         if (!obj->state)\r
884                                                 RemoveObj (obj);\r
885                                 }\r
886 nextactor:;\r
887                         }\r
888 \r
889                         // keep a list of objects around the player for radar updates\r
890                         //\r
891                                 if (obj == player)\r
892                                 {\r
893                                         px = player->x;\r
894                                         py = player->y;\r
895                                         psin = sintable[player->angle];\r
896                                         pcos = costable[player->angle];\r
897                                         xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;\r
898                                         xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;\r
899                                         yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
900                                         yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
901                                 }\r
902 \r
903                                 if (objnum > MAX_RADAR_BLIPS-2)\r
904                                         objnum = MAX_RADAR_BLIPS-2;\r
905 \r
906                                 ox = obj->x;\r
907                                 oy = obj->y;\r
908 \r
909 \r
910                                 if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))\r
911                                 {\r
912                                         norm_dx = (dx = px-ox)>>TILESHIFT;\r
913                                         norm_dy = (dy = oy-py)>>TILESHIFT;\r
914 \r
915                                         o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));\r
916 \r
917                                         if (o_radius < RADAR_RADIUS)\r
918                                         {\r
919                                                 newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);\r
920                                                 newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);\r
921 \r
922                                                 RadarXY[objnum][0]=newx>>TILESHIFT;\r
923                                                 RadarXY[objnum][1]=newy>>TILESHIFT;\r
924 \r
925                                                 // Define color to use for this object...\r
926                                                 //\r
927 \r
928                                                 switch (obj->obclass)\r
929                                                 {\r
930                         // NO GEM NEEDED\r
931                         //\r
932                                         // THE WIZARD! (YOU)\r
933                                         //\r
934                                                         case playerobj:\r
935                                                                 RadarXY[objnum++][2]=15;\r
936                                                         break;\r
937 \r
938                                         // WIZARD'S SHOTS\r
939                                         //\r
940                                                         case bounceobj:\r
941                                                         case pshotobj:\r
942                                                         case bigpshotobj:\r
943                                                                 RadarXY[objnum++][2]=shot_color[screenpage];\r
944                                                         break;\r
945 \r
946                         // RED GEM\r
947                         //\r
948                                         // STOMPY                                                                               (DK RED)\r
949                                         //\r
950                                                         case invisdudeobj:\r
951                                                         case stompyobj:\r
952                                                                 if (gamestate.gems[B_RGEM-B_RGEM])\r
953                                                                         if (obj->active == always)\r
954                                                                                 RadarXY[objnum++][2]=4;\r
955                                                         break;\r
956 \r
957                                         // BLOB                                                                                 (LT RED)\r
958                                         //\r
959                                                         case blobobj:\r
960                                                                 if (gamestate.gems[B_RGEM-B_RGEM])\r
961                                                                         if (obj->active == always)\r
962                                                                                 RadarXY[objnum++][2]=12;\r
963                                                         break;\r
964 \r
965                         // BLUE GEM\r
966                         //\r
967                                         // ROBOTANK                                                                             (LT BLUE)\r
968                                         //\r
969                                                         case robotankobj:\r
970                                                         case fmageobj:\r
971                                                                 if (gamestate.gems[B_BGEM-B_RGEM])\r
972                                                                         if (obj->active == always)\r
973                                                                                 RadarXY[objnum++][2]=9;\r
974                                                         break;\r
975 \r
976 #if 1\r
977                                         // BLUE DEMON                                                                   (DK BLUE)\r
978                                         //\r
979                                                         case demonobj:\r
980                                                                 if (gamestate.gems[B_GGEM-B_RGEM])\r
981                                                                         if (obj->active == always)\r
982                                                                                 RadarXY[objnum++][2]=1;\r
983                                                         break;\r
984 #endif\r
985 \r
986                         // GREEN GEM\r
987                         //\r
988                                         // WIZARD                                                                               (LT GREEN)\r
989                                         //\r
990                                                         case wizardobj:\r
991                                                                 if (gamestate.gems[B_GGEM-B_RGEM])\r
992                                                                         if (obj->active == always)\r
993                                                                                 RadarXY[objnum++][2]=10;\r
994                                                         break;\r
995 \r
996                                         // AQUA MAN                                                                             (DK GREEN)\r
997                                         //\r
998                                                         case aquamanobj:\r
999                                                                 if (gamestate.gems[B_GGEM-B_RGEM])\r
1000                                                                         if (obj->active == always)\r
1001                                                                                 RadarXY[objnum++][2]=2;\r
1002                                                         break;\r
1003 \r
1004                         // YELLOW GEM\r
1005                         //\r
1006                                         // EQYPTIAN HEAD                                                                (BROWN)\r
1007                                         //\r
1008                                                         case headobj:\r
1009                                                                 if (gamestate.gems[B_YGEM-B_RGEM])\r
1010                                                                         if (obj->active == always)\r
1011                                                                                 RadarXY[objnum++][2]=6;\r
1012                                                         break;\r
1013 \r
1014                                         //      RAMBONE                                                                         (YELLOW)\r
1015                                         //      TROLL\r
1016                                                         case ramboneobj:\r
1017                                                         case trollobj:\r
1018                                                                 if (gamestate.gems[B_YGEM-B_RGEM])\r
1019                                                                         if (obj->active == always)\r
1020                                                                                 RadarXY[objnum++][2]=14;\r
1021                                                         break;\r
1022 \r
1023                                         //      BUG                                                                                     (LIGHT GRAY)\r
1024                                                         case bugobj:\r
1025                                                                 if (gamestate.gems[B_YGEM-B_RGEM])\r
1026                                                                         if (obj->active == always)\r
1027                                                                                 RadarXY[objnum++][2]=7;\r
1028                                                         break;\r
1029 \r
1030                                         //      RAY                                                                                     (DARK GRAY)\r
1031                                                         case rayobj:\r
1032                                                                 if (gamestate.gems[B_YGEM-B_RGEM])\r
1033                                                                         if (obj->active == always)\r
1034                                                                                 RadarXY[objnum++][2]=8;\r
1035                                                         break;\r
1036 \r
1037                         // PURPLE GEM\r
1038                         //\r
1039                                         // MEC DEMON                                                                    (PURPLE)\r
1040                                         //\r
1041                                                         case cyborgdemonobj:\r
1042                                                                 if (gamestate.gems[B_PGEM-B_RGEM])\r
1043                                                                         if (obj->active == always)\r
1044                                                                                 RadarXY[objnum++][2]=5;\r
1045                                                         break;\r
1046 \r
1047                                         // EYE                                                                                  (LT PURPLE)\r
1048                                         //\r
1049                                                         case eyeobj:\r
1050                                                         case reyeobj:\r
1051                                                                 if (gamestate.gems[B_PGEM-B_RGEM])\r
1052                                                                         if (obj->active == always)\r
1053                                                                                 RadarXY[objnum++][2]=13;\r
1054                                                         break;\r
1055 \r
1056                         // ALL GEMS NEEDED\r
1057                         //\r
1058                                         // NEMESIS\r
1059                                         //\r
1060                                                         case grelmobj:\r
1061                                                                 if (!memcmp(gamestate.gems,allgems,sizeof(gamestate.gems)))\r
1062                                                                         if (obj->active == always)\r
1063                                                                                 RadarXY[objnum++][2]=15;\r
1064                                                         break;\r
1065                                                 }\r
1066                                         }\r
1067                                 }\r
1068                 }\r
1069                 RadarXY[objnum][2]=-1;          // Signals end of RadarXY list...\r
1070 \r
1071 #if USE_INERT_LIST\r
1072                 if (inert != inertobjlist)\r
1073                         for (obj=(objtype *)inertobjlist;obj;obj=obj->next)\r
1074                                 if (obj->ticcount)\r
1075                                 {\r
1076                                         obj->ticcount-=realtics;\r
1077                                         while ( obj->ticcount <= 0)\r
1078                                         {\r
1079                                                 obj->state = obj->state->next;\r
1080                                                 if (!obj->state)\r
1081                                                         Quit("Removable object in INERT list.");\r
1082 \r
1083                                                 if (!obj->state->tictime)\r
1084                                                 {\r
1085                                                         obj->ticcount = 0;\r
1086                                                         goto nextactor;\r
1087                                                 }\r
1088 \r
1089                                                 if (obj->state->tictime>0)\r
1090                                                         obj->ticcount += obj->state->tictime;\r
1091                                         }\r
1092                                 }\r
1093 #endif\r
1094 \r
1095                 if (bordertime)\r
1096                 {\r
1097                         bordertime -= realtics;\r
1098                         if (bordertime<=0)\r
1099                         {\r
1100                                 bordertime = 0;\r
1101                                 VW_ColorBorder(0);\r
1102                         }\r
1103                 }\r
1104 \r
1105 #if 1\r
1106 // random lightning?\r
1107 //\r
1108         if (BGFLAGS & (BGF_NOT_LIGHTNING))\r
1109         {\r
1110                 if ((scolor & 0xe0) && (!(random(20-realtics))))\r
1111                 {\r
1112                         BGFLAGS &= ~BGF_NOT_LIGHTNING;\r
1113                         InitBgChange(1,sky_lightning,-1,NULL,BGF_NOT_LIGHTNING);\r
1114                 }\r
1115         }\r
1116 \r
1117 // handle sky/ground color changes\r
1118 //\r
1119                 if (skytimer != -1)\r
1120                 {\r
1121                         skytimer -= realtics;\r
1122                         if (skytimer < 0)\r
1123                         {\r
1124                                 skycolor++;\r
1125                                 if (*skycolor == 0xffff)\r
1126                                 {\r
1127                                         skytimer = -1;\r
1128 //                                      skycolor--;\r
1129                                         skycolor = &scolor;\r
1130                                         if (groundtimer == -1)\r
1131                                                 BGFLAGS |= bgflag;\r
1132                                 }\r
1133                                 else\r
1134                                         skytimer = skytimer_reset;\r
1135                         }\r
1136                 }\r
1137 \r
1138                 if (groundtimer != -1)\r
1139                 {\r
1140                         groundtimer -= realtics;\r
1141                         if (groundtimer < 0)\r
1142                         {\r
1143                                 groundcolor++;\r
1144                                 if (*groundcolor == 0xffff)\r
1145                                 {\r
1146                                         groundtimer = -1;\r
1147 //                                      groundcolor--;\r
1148                                         groundcolor = &gcolor;\r
1149                                         if (skytimer == -1)\r
1150                                                 BGFLAGS |= bgflag;\r
1151                                 }\r
1152                                 else\r
1153                                         groundtimer = groundtimer_reset;\r
1154                         }\r
1155                 }\r
1156 #endif\r
1157 \r
1158 \r
1159 //\r
1160 //              Handle FreezeTime counter..\r
1161 //\r
1162                 if (FreezeTime)\r
1163                 {\r
1164                         if (FreezeTime<20*30)\r
1165                                 if ((BeepTime+=realtics)>=60)\r
1166                                 {\r
1167                                         BeepTime -= 60;\r
1168                                         SD_PlaySound(TICKSND);\r
1169                                 }\r
1170 \r
1171                         if ((FreezeTime-=realtics)<=0)\r
1172                         {\r
1173                                 FreezeTime=0;\r
1174                                 SD_PlaySound(TIMERETURNSND);\r
1175                                 DisplaySMsg(NULL,NULL);\r
1176                                 status_flag = S_NONE;\r
1177                         }\r
1178                 }\r
1179 \r
1180 \r
1181 // refresh all\r
1182 //\r
1183                 ThreeDRefresh ();\r
1184 \r
1185                 if (Flags & FL_DEAD)\r
1186                 {\r
1187                         SD_PlaySound (GAMEOVERSND);\r
1188                         DisplaySMsg("DEAD",NULL);\r
1189                         DrawHealth();\r
1190                 }\r
1191 \r
1192 // check for win\r
1193 //\r
1194                 if (playstate == ex_victorious)\r
1195                 {\r
1196                         Victory(true);\r
1197                         IN_Ack();\r
1198                         Quit(NULL);\r
1199                 }\r
1200 \r
1201                 CheckKeys();\r
1202 \r
1203         }while (!playstate);\r
1204 //      StopMusic ();\r
1205 \r
1206         ingame = false;\r
1207         if (bordertime)\r
1208         {\r
1209                 bordertime = 0;\r
1210                 VW_ColorBorder(0);\r
1211         }\r
1212 \r
1213         if (abortgame)\r
1214                 abortgame = false;\r
1215 }\r
1216 \r
1217 //--------------------------------------------------------------------------\r
1218 // IntSqrt() - by Master Programmer, George Leritte!\r
1219 //--------------------------------------------------------------------------\r
1220 int IntSqrt(long va)\r
1221 {\r
1222 asm     mov     AX, word ptr va\r
1223 asm     mov     DX, word ptr va+2\r
1224 asm     mov     bx,dx           // {bx = integer square root of dx:ax}\r
1225 asm     or      bx,ax           // {if dx:ax=0 then return}\r
1226 asm     jz      isq01\r
1227 asm     mov     bx,dx\r
1228 asm     shl     bx,1\r
1229 asm     or      bl,ah\r
1230 asm     or      bl,al\r
1231 asm     dec     bx\r
1232 asm     add     bx,dx           // { initial guess}\r
1233 asm     jg      isq10\r
1234 asm     inc     bx              // { don't return zero}\r
1235 asm     jg      isq10\r
1236 asm     mov     bx,7fffh\r
1237 isq01:;\r
1238                   goto    exitrout;\r
1239 \r
1240 isq10:;\r
1241 asm     push    ax\r
1242 asm     push    dx\r
1243 asm     div     bx\r
1244 asm     sub     ax,bx\r
1245 asm     cmp     ax,1\r
1246 asm     jbe     isq90\r
1247 asm     cmp     ax,-1\r
1248 asm     jae     isq90\r
1249 asm     sar     ax,1\r
1250 asm     add     bx,ax\r
1251 asm     pop     dx\r
1252 asm     pop     ax\r
1253 asm     jmp     isq10\r
1254 isq90:;\r
1255 asm     pop     dx\r
1256 asm     pop     ax\r
1257 exitrout:;\r
1258 asm     mov     ax,bx\r
1259 }\r
1260 \r
1261 //-------------------------------------------------------------------------\r
1262 // InitBgChange()\r
1263 //-------------------------------------------------------------------------\r
1264 void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag)\r
1265 {\r
1266         skytimer_reset = skytimer = stimer;\r
1267         if (scolors)\r
1268                 skycolor = scolors;\r
1269 \r
1270         groundtimer_reset = groundtimer = gtimer;\r
1271         if (gcolors)\r
1272                 groundcolor = gcolors;\r
1273 \r
1274         bgflag = flag;\r
1275 }\r
1276 \r
1277 ////////////////////////////////////////////////////////\r
1278 //\r
1279 // DisplayStatus\r
1280 //\r
1281 //  Stat_Flag -  contains the type of status displayed\r
1282 //  -- also uses status_delay (global variable) will not\r
1283 //     change display until this variable is zero.\r
1284 //  -- heirarchy is determined by the series of if statements,\r
1285 //        to change it, rearrange th if statements.\r
1286 //\r
1287 ////////////////////////////////////////////////////////\r
1288 \r
1289 #define MESSAGEDELAY  25\r
1290 void DisplayStatus (status_flags *stat_flag)\r
1291 {\r
1292         status_flags temp_status;\r
1293 \r
1294 \r
1295         if (*stat_flag == S_TIMESTOP)\r
1296           return;\r
1297 \r
1298         if (status_delay > 0)\r
1299         {\r
1300                 status_delay -= realtics;\r
1301                 return;\r
1302         }\r
1303         else\r
1304                 status_delay = 0;\r
1305 \r
1306         // check for a change in status from previous call\r
1307 \r
1308         temp_status = S_VIEWING;                             //precaution\r
1309 \r
1310         if (Keyboard[sc_Control] || control.button0)\r
1311                 temp_status = S_MISSLE;\r
1312 \r
1313         if (Keyboard[sc_Z] && !Keyboard[sc_F10])\r
1314                 temp_status = S_ZAPPER;\r
1315 \r
1316         if ((Keyboard[sc_X] && !Keyboard[sc_F10]) || Keyboard[sc_Enter])\r
1317                 temp_status = S_XTER;\r
1318 \r
1319         if (control.x)\r
1320                 temp_status = S_TURN;\r
1321 \r
1322         if ((Keyboard[sc_V] || Keyboard[sc_Tab]) && control.x)\r
1323                 temp_status = S_QTURN;\r
1324 \r
1325         if (Keyboard[sc_Alt] && control.x)\r
1326                 temp_status = S_SIDESTEP;\r
1327 \r
1328         if (control.y < 0)\r
1329                 temp_status = S_ADVANCE;\r
1330 \r
1331         if (control.y > 0)\r
1332                 temp_status = S_RETREAT;\r
1333 \r
1334         if (Keyboard[sc_F5])\r
1335                 temp_status = S_JOYSTICK;\r
1336 \r
1337         if (Keyboard[sc_F4])\r
1338                 temp_status = S_RESTORING;\r
1339 \r
1340         if (Keyboard[sc_F3])\r
1341                 temp_status = S_SAVING;\r
1342 \r
1343         if (Keyboard[sc_F2])\r
1344                 temp_status = S_SND;\r
1345 \r
1346         if (Keyboard[sc_F1])\r
1347                 temp_status = S_HELP;\r
1348 \r
1349         if (temp_status != *stat_flag)\r
1350         {\r
1351                 *stat_flag = temp_status;\r
1352 \r
1353 \r
1354                 switch (*stat_flag)\r
1355                 {\r
1356                         case S_MISSLE:\r
1357                                 DisplaySMsg("Magick Missile", NULL);\r
1358                                 status_delay = MESSAGEDELAY;\r
1359                         break;\r
1360 \r
1361                         case S_ZAPPER:\r
1362                                 if (gamestate.bolts)\r
1363                                 {\r
1364                                         DisplaySMsg("Zapper", NULL);\r
1365                                         status_delay = MESSAGEDELAY+10;\r
1366                                 }\r
1367                         break;\r
1368 \r
1369                         case S_XTER:\r
1370                                 if (gamestate.nukes)\r
1371                                 {\r
1372                                         DisplaySMsg("Xterminator", NULL);\r
1373                                         status_delay = MESSAGEDELAY+5;\r
1374                                 }\r
1375                         break;\r
1376 \r
1377                         case S_TURN:\r
1378                                 DisplaySMsg("Turning", NULL);\r
1379                                 status_delay = MESSAGEDELAY;\r
1380                         break;\r
1381 \r
1382                         case S_QTURN:\r
1383                                 DisplaySMsg("Quick Turning", NULL);\r
1384                                 status_delay = MESSAGEDELAY;\r
1385                         break;\r
1386 \r
1387                         case S_SIDESTEP:\r
1388                                 DisplaySMsg("Sidestepping", NULL);\r
1389                                 status_delay = MESSAGEDELAY;\r
1390                         break;\r
1391 \r
1392                         case S_ADVANCE:\r
1393                                 DisplaySMsg("Advancing", NULL);\r
1394                                 status_delay = MESSAGEDELAY;\r
1395                         break;\r
1396 \r
1397                         case S_RETREAT:\r
1398                                 DisplaySMsg("Retreating", NULL);\r
1399                                 status_delay = MESSAGEDELAY;\r
1400                         break;\r
1401 \r
1402                         case S_JOYSTICK:\r
1403                                 DisplaySMsg("Adjusting Joystick", NULL);\r
1404                         break;\r
1405 \r
1406                         case S_RESTORING:\r
1407                                 DisplaySMsg("Restoring", NULL);\r
1408                         break;\r
1409 \r
1410                         case S_SAVING:\r
1411                                 DisplaySMsg("Saving", NULL);\r
1412                         break;\r
1413 \r
1414                         case S_SND:\r
1415                                 DisplaySMsg("Select Sound", NULL);\r
1416                         break;\r
1417 \r
1418                         case S_HELP:\r
1419                                 DisplaySMsg("Getting Help", NULL);\r
1420                         break;\r
1421 \r
1422                         case S_VIEWING:\r
1423                                 DisplaySMsg("Viewing", NULL);\r
1424                         break;\r
1425                 }\r
1426                 bufferofs = displayofs = screenloc[screenpage];\r
1427 \r
1428         }\r
1429 }\r