OSDN Git Service

going on vacation >.<
[proj16/16.git] / src / lib / hb / c3_main.c
1 /* Catacomb 3-D 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_MAIN.C\r
20 \r
21 #include "C3_DEF.H"\r
22 #pragma hdrstop\r
23 \r
24 /*\r
25 =============================================================================\r
26 \r
27                                                    CATACOMB 3-D\r
28 \r
29                                           An Id Software production\r
30 \r
31                                                    by John Carmack\r
32 \r
33 =============================================================================\r
34 */\r
35 \r
36 /*\r
37 =============================================================================\r
38 \r
39                                                  LOCAL CONSTANTS\r
40 \r
41 =============================================================================\r
42 */\r
43 \r
44 \r
45 /*\r
46 =============================================================================\r
47 \r
48                                                  GLOBAL VARIABLES\r
49 \r
50 =============================================================================\r
51 */\r
52 \r
53 memptr          scalesegs[NUMPICS];\r
54 char            str[80],str2[20];\r
55 unsigned        tedlevelnum;\r
56 boolean         tedlevel;\r
57 gametype        gamestate;\r
58 exittype        playstate;\r
59 \r
60 /*\r
61 =============================================================================\r
62 \r
63                                                  LOCAL VARIABLES\r
64 \r
65 =============================================================================\r
66 */\r
67 \r
68 \r
69 \r
70 //===========================================================================\r
71 \r
72 // JAB Hack begin\r
73 #define MyInterrupt     0x60\r
74 void interrupt (*intaddr)();\r
75 void interrupt (*oldintaddr)();\r
76         char    *JHParmStrings[] = {"no386",nil};\r
77 \r
78 void\r
79 jabhack(void)\r
80 {\r
81 extern void far jabhack2(void);\r
82 extern int far  CheckIs386(void);\r
83 \r
84         int     i;\r
85 \r
86         oldintaddr = getvect(MyInterrupt);\r
87 \r
88         for (i = 1;i < _argc;i++)\r
89                 if (US_CheckParm(_argv[i],JHParmStrings) == 0)\r
90                         return;\r
91 \r
92         if (CheckIs386())\r
93         {\r
94                 jabhack2();\r
95                 setvect(MyInterrupt,intaddr);\r
96         }\r
97 }\r
98 \r
99 void\r
100 jabunhack(void)\r
101 {\r
102         setvect(MyInterrupt,oldintaddr);\r
103 }\r
104 //      JAB Hack end\r
105 \r
106 //===========================================================================\r
107 \r
108 /*\r
109 =====================\r
110 =\r
111 = NewGame\r
112 =\r
113 = Set up new game to start from the beginning\r
114 =\r
115 =====================\r
116 */\r
117 \r
118 void NewGame (void)\r
119 {\r
120         memset (&gamestate,0,sizeof(gamestate));\r
121         gamestate.mapon = 0;\r
122         gamestate.body = MAXBODY;\r
123 }\r
124 \r
125 //===========================================================================\r
126 \r
127 #define RLETAG  0xABCD\r
128 \r
129 /*\r
130 ==================\r
131 =\r
132 = SaveTheGame\r
133 =\r
134 ==================\r
135 */\r
136 \r
137 boolean SaveTheGame(int file)\r
138 {\r
139         word    i,compressed,expanded;\r
140         objtype *o;\r
141         memptr  bigbuffer;\r
142 \r
143         if (!CA_FarWrite(file,(void far *)&gamestate,sizeof(gamestate)))\r
144                 return(false);\r
145 \r
146         expanded = mapwidth * mapheight * 2;\r
147         MM_GetPtr (&bigbuffer,expanded);\r
148 \r
149         for (i = 0;i < 3;i+=2)  // Write planes 0 and 2\r
150         {\r
151 //\r
152 // leave a word at start of compressed data for compressed length\r
153 //\r
154                 compressed = (unsigned)CA_RLEWCompress ((unsigned huge *)mapsegs[i]\r
155                         ,expanded,((unsigned huge *)bigbuffer)+1,RLETAG);\r
156 \r
157                 *(unsigned huge *)bigbuffer = compressed;\r
158 \r
159                 if (!CA_FarWrite(file,(void far *)bigbuffer,compressed+2) )\r
160                 {\r
161                         MM_FreePtr (&bigbuffer);\r
162                         return(false);\r
163                 }\r
164         }\r
165 \r
166         for (o = player;o;o = o->next)\r
167                 if (!CA_FarWrite(file,(void far *)o,sizeof(objtype)))\r
168                 {\r
169                         MM_FreePtr (&bigbuffer);\r
170                         return(false);\r
171                 }\r
172 \r
173         MM_FreePtr (&bigbuffer);\r
174 \r
175         return(true);\r
176 }\r
177 \r
178 //===========================================================================\r
179 \r
180 /*\r
181 ==================\r
182 =\r
183 = LoadTheGame\r
184 =\r
185 ==================\r
186 */\r
187 \r
188 boolean LoadTheGame(int file)\r
189 {\r
190         unsigned        i,x,y;\r
191         objtype         *obj,*prev,*next,*followed;\r
192         unsigned        compressed,expanded;\r
193         unsigned        far *map,tile;\r
194         memptr          bigbuffer;\r
195 \r
196         if (!CA_FarRead(file,(void far *)&gamestate,sizeof(gamestate)))\r
197                 return(false);\r
198 \r
199         SetupGameLevel ();              // load in and cache the base old level\r
200 \r
201         expanded = mapwidth * mapheight * 2;\r
202         MM_GetPtr (&bigbuffer,expanded);\r
203 \r
204         for (i = 0;i < 3;i+=2)  // Read planes 0 and 2\r
205         {\r
206                 if (!CA_FarRead(file,(void far *)&compressed,sizeof(compressed)) )\r
207                 {\r
208                         MM_FreePtr (&bigbuffer);\r
209                         return(false);\r
210                 }\r
211 \r
212                 if (!CA_FarRead(file,(void far *)bigbuffer,compressed) )\r
213                 {\r
214                         MM_FreePtr (&bigbuffer);\r
215                         return(false);\r
216                 }\r
217 \r
218                 CA_RLEWexpand ((unsigned huge *)bigbuffer,\r
219                         (unsigned huge *)mapsegs[i],expanded,RLETAG);\r
220         }\r
221 \r
222         MM_FreePtr (&bigbuffer);\r
223 //\r
224 // copy the wall data to a data segment array again, to handle doors and\r
225 // bomb walls that are allready opened\r
226 //\r
227         memset (tilemap,0,sizeof(tilemap));\r
228         memset (actorat,0,sizeof(actorat));\r
229         map = mapsegs[0];\r
230         for (y=0;y<mapheight;y++)\r
231                 for (x=0;x<mapwidth;x++)\r
232                 {\r
233                         tile = *map++;\r
234                         if (tile<NUMFLOORS)\r
235                         {\r
236                                 tilemap[x][y] = tile;\r
237                                 if (tile>0)\r
238                                         (unsigned)actorat[x][y] = tile;\r
239                         }\r
240                 }\r
241 \r
242 \r
243         // Read the object list back in - assumes at least one object in list\r
244 \r
245         InitObjList ();\r
246         new = player;\r
247         while (true)\r
248         {\r
249                 prev = new->prev;\r
250                 next = new->next;\r
251                 if (!CA_FarRead(file,(void far *)new,sizeof(objtype)))\r
252                         return(false);\r
253                 followed = new->next;\r
254                 new->prev = prev;\r
255                 new->next = next;\r
256                 actorat[new->tilex][new->tiley] = new;  // drop a new marker\r
257 \r
258                 if (followed)\r
259                         GetNewObj (false);\r
260                 else\r
261                         break;\r
262         }\r
263 \r
264         return(true);\r
265 }\r
266 \r
267 //===========================================================================\r
268 \r
269 /*\r
270 ==================\r
271 =\r
272 = ResetGame\r
273 =\r
274 ==================\r
275 */\r
276 \r
277 void ResetGame(void)\r
278 {\r
279         NewGame ();\r
280 \r
281         ca_levelnum--;\r
282         ca_levelbit>>=1;\r
283         CA_ClearMarks();\r
284         ca_levelbit<<=1;\r
285         ca_levelnum++;\r
286 }\r
287 \r
288 //===========================================================================\r
289 \r
290 \r
291 /*\r
292 ==========================\r
293 =\r
294 = ShutdownId\r
295 =\r
296 = Shuts down all ID_?? managers\r
297 =\r
298 ==========================\r
299 */\r
300 \r
301 void ShutdownId (void)\r
302 {\r
303   US_Shutdown ();\r
304 #ifndef PROFILE\r
305   SD_Shutdown ();\r
306   IN_Shutdown ();\r
307 #endif\r
308   VW_Shutdown ();\r
309   CA_Shutdown ();\r
310   MM_Shutdown ();\r
311 }\r
312 \r
313 \r
314 //===========================================================================\r
315 \r
316 /*\r
317 ==========================\r
318 =\r
319 = InitGame\r
320 =\r
321 = Load a few things right away\r
322 =\r
323 ==========================\r
324 */\r
325 \r
326 void InitGame (void)\r
327 {\r
328         unsigned        segstart,seglength;\r
329         int                     i,x,y;\r
330         unsigned        *blockstart;\r
331 \r
332 //      US_TextScreen();\r
333 \r
334         MM_Startup ();\r
335         VW_Startup ();\r
336 #ifndef PROFILE\r
337         IN_Startup ();\r
338         SD_Startup ();\r
339 #endif\r
340         US_Startup ();\r
341 \r
342 //      US_UpdateTextScreen();\r
343 \r
344         CA_Startup ();\r
345         US_Setup ();\r
346 \r
347         US_SetLoadSaveHooks(LoadTheGame,SaveTheGame,ResetGame);\r
348 \r
349 //\r
350 // load in and lock down some basic chunks\r
351 //\r
352 \r
353         CA_ClearMarks ();\r
354 \r
355         CA_MarkGrChunk(STARTFONT);\r
356         CA_MarkGrChunk(STARTTILE8);\r
357         CA_MarkGrChunk(STARTTILE8M);\r
358         CA_MarkGrChunk(HAND1PICM);\r
359         CA_MarkGrChunk(HAND2PICM);\r
360         CA_MarkGrChunk(ENTERPLAQUEPIC);\r
361 \r
362         CA_CacheMarks (NULL);\r
363 \r
364         MM_SetLock (&grsegs[STARTFONT],true);\r
365         MM_SetLock (&grsegs[STARTTILE8],true);\r
366         MM_SetLock (&grsegs[STARTTILE8M],true);\r
367         MM_SetLock (&grsegs[HAND1PICM],true);\r
368         MM_SetLock (&grsegs[HAND2PICM],true);\r
369         MM_SetLock (&grsegs[ENTERPLAQUEPIC],true);\r
370 \r
371         fontcolor = WHITE;\r
372 \r
373 \r
374 //\r
375 // build some tables\r
376 //\r
377         for (i=0;i<MAPSIZE;i++)\r
378                 nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i;\r
379 \r
380         for (i=0;i<PORTTILESHIGH;i++)\r
381                 uwidthtable[i] = UPDATEWIDE*i;\r
382 \r
383         blockstart = &blockstarts[0];\r
384         for (y=0;y<UPDATEHIGH;y++)\r
385                 for (x=0;x<UPDATEWIDE;x++)\r
386                         *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;\r
387 \r
388         BuildTables ();                 // 3-d tables\r
389 \r
390         SetupScaling ();\r
391 \r
392 #ifndef PROFILE\r
393 //      US_FinishTextScreen();\r
394 #endif\r
395 \r
396 //\r
397 // reclaim the memory from the linked in text screen\r
398 //\r
399         segstart = FP_SEG(&introscn);\r
400         seglength = 4000/16;\r
401         if (FP_OFF(&introscn))\r
402         {\r
403                 segstart++;\r
404                 seglength--;\r
405         }\r
406 \r
407         MML_UseSpace (segstart,seglength);\r
408 \r
409         VW_SetScreenMode (GRMODE);\r
410         VW_ColorBorder (3);\r
411         VW_ClearVideo (BLACK);\r
412 \r
413 //\r
414 // initialize variables\r
415 //\r
416         updateptr = &update[0];\r
417         *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;\r
418         bufferofs = 0;\r
419         displayofs = 0;\r
420         VW_SetLineWidth(SCREENWIDTH);\r
421 }\r
422 \r
423 //===========================================================================\r
424 \r
425 void clrscr (void);             // can't include CONIO.H because of name conflicts...\r
426 \r
427 /*\r
428 ==========================\r
429 =\r
430 = Quit\r
431 =\r
432 ==========================\r
433 */\r
434 \r
435 void Quit (char *error)\r
436 {\r
437         unsigned        finscreen;\r
438 \r
439 #if 0\r
440         if (!error)\r
441         {\r
442                 CA_SetAllPurge ();\r
443                 CA_CacheGrChunk (PIRACY);\r
444                 finscreen = (unsigned)grsegs[PIRACY];\r
445         }\r
446 #endif\r
447 \r
448         ShutdownId ();\r
449         if (error && *error)\r
450         {\r
451           puts(error);\r
452           exit(1);\r
453         }\r
454 \r
455 #if 0\r
456         if (!NoWait)\r
457         {\r
458                 movedata (finscreen,0,0xb800,0,4000);\r
459                 bioskey (0);\r
460                 clrscr();\r
461         }\r
462 #endif\r
463 \r
464         exit(0);\r
465 }\r
466 \r
467 //===========================================================================\r
468 \r
469 /*\r
470 ==================\r
471 =\r
472 = TEDDeath\r
473 =\r
474 ==================\r
475 */\r
476 \r
477 void    TEDDeath(void)\r
478 {\r
479         ShutdownId();\r
480         execlp("TED5.EXE","TED5.EXE","/LAUNCH",NULL);\r
481 }\r
482 \r
483 //===========================================================================\r
484 \r
485 /*\r
486 =====================\r
487 =\r
488 = DemoLoop\r
489 =\r
490 =====================\r
491 */\r
492 \r
493 static  char *ParmStrings[] = {"easy","normal","hard",""};\r
494 \r
495 void    DemoLoop (void)\r
496 {\r
497         int     i,level;\r
498 \r
499 //\r
500 // check for launch from ted\r
501 //\r
502         if (tedlevel)\r
503         {\r
504                 NewGame();\r
505                 gamestate.mapon = tedlevelnum;\r
506                 restartgame = gd_Normal;\r
507                 for (i = 1;i < _argc;i++)\r
508                 {\r
509                         if ( (level = US_CheckParm(_argv[i],ParmStrings)) == -1)\r
510                                 continue;\r
511 \r
512                         restartgame = gd_Easy+level;\r
513                         break;\r
514                 }\r
515                 GameLoop();\r
516                 TEDDeath();\r
517         }\r
518 \r
519 \r
520 //\r
521 // main game cycle\r
522 //\r
523         displayofs = bufferofs = 0;\r
524         VW_Bar (0,0,320,200,0);\r
525 \r
526         while (1)\r
527         {\r
528                 CA_CacheGrChunk (TITLEPIC);\r
529                 bufferofs = SCREEN2START;\r
530                 displayofs = SCREEN1START;\r
531                 VWB_DrawPic (0,0,TITLEPIC);\r
532                 MM_SetPurge (&grsegs[TITLEPIC],3);\r
533                 UNMARKGRCHUNK(TITLEPIC);\r
534                 FizzleFade (bufferofs,displayofs,320,200,true);\r
535 \r
536                 if (!IN_UserInput(TickBase*3,false))\r
537                 {\r
538                         CA_CacheGrChunk (CREDITSPIC);\r
539                         VWB_DrawPic (0,0,CREDITSPIC);\r
540                         MM_SetPurge (&grsegs[CREDITSPIC],3);\r
541                         UNMARKGRCHUNK(CREDITSPIC);\r
542                         FizzleFade (bufferofs,displayofs,320,200,true);\r
543 \r
544                 }\r
545 \r
546                 if (!IN_UserInput(TickBase*3,false))\r
547                 {\r
548 highscores:\r
549                         DrawHighScores ();\r
550                         FizzleFade (bufferofs,displayofs,320,200,true);\r
551                         IN_UserInput(TickBase*3,false);\r
552                 }\r
553 \r
554                 if (IN_IsUserInput())\r
555                 {\r
556                         US_ControlPanel ();\r
557 \r
558                         if (restartgame || loadedgame)\r
559                         {\r
560                                 GameLoop ();\r
561                                 goto highscores;\r
562                         }\r
563                 }\r
564 \r
565         }\r
566 }\r
567 \r
568 //===========================================================================\r
569 \r
570 /*\r
571 ==========================\r
572 =\r
573 = SetupScalePic\r
574 =\r
575 ==========================\r
576 */\r
577 \r
578 void SetupScalePic (unsigned picnum)\r
579 {\r
580         unsigned        scnum;\r
581 \r
582         scnum = picnum-FIRSTSCALEPIC;\r
583 \r
584         if (shapedirectory[scnum])\r
585         {\r
586                 MM_SetPurge (&(memptr)shapedirectory[scnum],0);\r
587                 return;                                 // allready in memory\r
588         }\r
589 \r
590         CA_CacheGrChunk (picnum);\r
591         DeplanePic (picnum);\r
592         shapesize[scnum] = BuildCompShape (&shapedirectory[scnum]);\r
593         grneeded[picnum]&= ~ca_levelbit;\r
594         MM_FreePtr (&grsegs[picnum]);\r
595 }\r
596 \r
597 //===========================================================================\r
598 \r
599 /*\r
600 ==========================\r
601 =\r
602 = SetupScaleWall\r
603 =\r
604 ==========================\r
605 */\r
606 \r
607 void SetupScaleWall (unsigned picnum)\r
608 {\r
609         int             x,y;\r
610         unsigned        scnum;\r
611         byte    far *dest;\r
612 \r
613         scnum = picnum-FIRSTWALLPIC;\r
614 \r
615         if (walldirectory[scnum])\r
616         {\r
617                 MM_SetPurge (&walldirectory[scnum],0);\r
618                 return;                                 // allready in memory\r
619         }\r
620 \r
621         CA_CacheGrChunk (picnum);\r
622         DeplanePic (picnum);\r
623         MM_GetPtr(&walldirectory[scnum],64*64);\r
624         dest = (byte far *)walldirectory[scnum];\r
625         for (x=0;x<64;x++)\r
626                 for (y=0;y<64;y++)\r
627                         *dest++ = spotvis[y][x];\r
628         grneeded[picnum]&= ~ca_levelbit;\r
629         MM_FreePtr (&grsegs[picnum]);\r
630 }\r
631 \r
632 //===========================================================================\r
633 \r
634 /*\r
635 ==========================\r
636 =\r
637 = SetupScaling\r
638 =\r
639 ==========================\r
640 */\r
641 \r
642 void SetupScaling (void)\r
643 {\r
644         int             i,x,y;\r
645         byte    far *dest;\r
646 \r
647 //\r
648 // build the compiled scalers\r
649 //\r
650         for (i=1;i<=VIEWWIDTH/2;i++)\r
651                 BuildCompScale (i*2,&scaledirectory[i]);\r
652 }\r
653 \r
654 //===========================================================================\r
655 \r
656 int     showscorebox;\r
657 \r
658 void RF_FixOfs (void)\r
659 {\r
660 }\r
661 \r
662 void HelpScreens (void)\r
663 {\r
664 }\r
665 \r
666 \r
667 /*\r
668 ==================\r
669 =\r
670 = CheckMemory\r
671 =\r
672 ==================\r
673 */\r
674 \r
675 #define MINMEMORY       335000l\r
676 \r
677 void    CheckMemory(void)\r
678 {\r
679         unsigned        finscreen;\r
680 \r
681         if (mminfo.nearheap+mminfo.farheap+mminfo.EMSmem+mminfo.XMSmem\r
682                 >= MINMEMORY)\r
683                 return;\r
684 \r
685         CA_CacheGrChunk (OUTOFMEM);\r
686         finscreen = (unsigned)grsegs[OUTOFMEM];\r
687         ShutdownId ();\r
688         movedata (finscreen,7,0xb800,0,4000);\r
689         gotoxy (1,24);\r
690         exit(1);\r
691 }\r
692 \r
693 //===========================================================================\r
694 \r
695 \r
696 /*\r
697 ==========================\r
698 =\r
699 = main\r
700 =\r
701 ==========================\r
702 */\r
703 \r
704 void main (void)\r
705 {\r
706         short i;\r
707 \r
708         if (stricmp(_argv[1], "/VER") == 0)\r
709         {\r
710                 printf("Catacomb 3-D version 1.22  (Rev 1)\n");\r
711                 printf("Copyright 1991-93 Softdisk Publishing\n");\r
712                 printf("Developed for use with 100%% IBM compatibles\n");\r
713                 printf("that have 640K memory and DOS version 3.3 or later\n");\r
714                 printf("and EGA graphics or better.\n");\r
715                 exit(0);\r
716         }\r
717 \r
718         if (stricmp(_argv[1], "/?") == 0)\r
719         {\r
720                 printf("Catacomb 3-D version 1.22\n");\r
721                 printf("Copyright 1991-93 Softdisk Publishing\n\n");\r
722                 printf("Syntax:\n");\r
723                 printf("CAT3D [/<switch>]\n\n");\r
724                 printf("Switch       What it does\n");\r
725                 printf("/?           This Information\n");\r
726                 printf("/VER         Display Program Version Information\n");\r
727                 printf("/COMP        Fix problems with SVGA screens\n");\r
728                 printf("/NOAL        No AdLib or SoundBlaster detection\n");\r
729                 printf("/NOJOYS      Tell program to ignore joystick\n");\r
730                 printf("/NOMOUSE     Tell program to ignore mouse\n");\r
731                 printf("/HIDDENCARD  Overrides video detection\n\n");\r
732                 printf("Each switch must include a '/' and multiple switches\n");\r
733                 printf("must be seperated by at least one space.\n\n");\r
734 \r
735                 exit(0);\r
736         }\r
737 \r
738         jabhack();\r
739 \r
740         InitGame ();\r
741 \r
742         CheckMemory ();\r
743 \r
744         LoadLatchMem ();\r
745 \r
746 #ifdef PROFILE\r
747         NewGame ();\r
748         GameLoop ();\r
749 #endif\r
750 \r
751 //NewGame ();\r
752 //GameLoop ();\r
753 \r
754         DemoLoop();\r
755         Quit("Demo loop exited???");\r
756 }\r