]> 4ch.mooo.com Git - 16.git/blob - 16/cawat/GELIB.C
5e0bd6f94f817ba553c4fe429a608e61f74f5ab2
[16.git] / 16 / cawat / GELIB.C
1 /* Catacomb Armageddon 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 #include <dos.h>\r
20 #include <conio.h>\r
21 #include <stdio.h>\r
22 #include <dir.h>\r
23 #include "mem.h"\r
24 #include "string.h"\r
25 #include "time.h"\r
26 #include "stdarg.h"\r
27 #include "io.h"\r
28 \r
29 #include "DEF.H"\r
30 #include "gelib.h"\r
31 #include "sl_file.h"\r
32 \r
33 \r
34 #define MAX_GAMELIST_NAMES 20\r
35 #define FNAME_LEN                               9\r
36 \r
37 ////////////////////////////////////////////////////////////////////////////\r
38 //\r
39 // Global variables\r
40 //\r
41 boolean InLoadSaveGame = false;\r
42 //AudioDeviceType ge_DigiMode;\r
43 boolean ConserveMemory = false;\r
44 char GameListNames[MAX_GAMELIST_NAMES+1][FNAME_LEN],current_disk=1;\r
45 short NumGames;\r
46 short PPT_LeftEdge=0,PPT_RightEdge=320;\r
47 boolean LeaveDriveOn=false,ge_textmode=true;\r
48 char Filename[FILENAME_LEN+1], ID[sizeof(GAMENAME)], VER[sizeof(SAVEVER_DATA)];\r
49 short wall_anim_delay,wall_anim_time = 7;\r
50 BufferedIO lzwBIO;\r
51 \r
52 \r
53 \r
54 \r
55 \r
56 ////////////////////////////////////////////////////////////////////////////\r
57 //\r
58 // CalibrateJoystick()\r
59 //\r
60 void CalibrateJoystick(short joynum)\r
61 {\r
62         word    minx,maxx,\r
63                         miny,maxy;\r
64 \r
65         IN_ClearKeysDown();\r
66 \r
67         VW_HideCursor();\r
68 \r
69         VW_FixRefreshBuffer();\r
70         CenterWindow(30,8);\r
71 \r
72         US_Print("\n");\r
73         US_CPrintLine("Move joystick to the upper-left");\r
74         US_CPrintLine("and press one of the buttons.");\r
75         VW_UpdateScreen();\r
76 \r
77         while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joynum));\r
78         if (LastScan == sc_Escape)\r
79                 return;\r
80 \r
81         IN_GetJoyAbs(joynum,&minx,&miny);\r
82         while (IN_GetJoyButtonsDB(joynum));\r
83 \r
84         US_Print("\n");\r
85         US_CPrintLine("Move joystick to the lower-right");\r
86         US_CPrintLine("and press one of the buttons.");\r
87         VW_UpdateScreen();\r
88 \r
89         while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joynum));\r
90         if (LastScan == sc_Escape)\r
91                 return;\r
92 \r
93         IN_GetJoyAbs(joynum,&maxx,&maxy);\r
94         if ((minx == maxx) && (miny == maxy))\r
95                 return;\r
96 \r
97         IN_SetupJoy(joynum,minx,maxx,miny,maxy);\r
98 \r
99         while (IN_GetJoyButtonsDB(joynum));\r
100         if (LastScan)\r
101                 IN_ClearKeysDown();\r
102 \r
103         JoystickCalibrated = true;\r
104 }\r
105 \r
106 ////////////////////////////////////////////////////////////////////////////\r
107 //\r
108 // WaitKeyVBL()\r
109 //\r
110 void WaitKeyVBL(short key, short vbls)\r
111 {\r
112         while (vbls--)\r
113         {\r
114                 VW_WaitVBL(1);\r
115                 IN_ReadControl(0,&control);\r
116                 if ((control.button0|control.button1)||(Keyboard[key]))\r
117                         break;\r
118         }\r
119 }\r
120 \r
121 ////////////////////////////////////////////////////////////////////////////\r
122 //\r
123 // MoveScreen()\r
124 //\r
125 // panadjust must be saved and restored if MoveScreen is being called from\r
126 // inside a level.\r
127 //\r
128 void MoveScreen(short x, short y)\r
129 {\r
130         unsigned address;\r
131 \r
132         address = (y*linewidth)+(x/8);\r
133         VW_SetScreen(address,0);\r
134         bufferofs = displayofs = address;\r
135         panadjust=0;\r
136 }\r
137 \r
138 ////////////////////////////////////////////////////////////////////////////\r
139 //\r
140 // MoveGfxDst()\r
141 //\r
142 void MoveGfxDst(short x, short y)\r
143 {\r
144         unsigned address;\r
145 \r
146         address = (y*linewidth)+(x/8);\r
147         bufferofs = displayofs = address;\r
148 }\r
149 \r
150 #if 0\r
151 \r
152 #if GRAPHIC_PIRATE\r
153 \r
154 ///////////////////////////////////////////////////////////////////////////\r
155 //\r
156 // DoPiracy() - Graphics piracy code...\r
157 //\r
158 void DoPiracy()\r
159 {\r
160         struct Shape Pirate1Shp;\r
161         struct Shape Pirate2Shp;\r
162 \r
163         VW_SetScreenMode (EGA320GR);\r
164         VW_ClearVideo(BLACK);\r
165 \r
166         // Load shapes...\r
167         //\r
168         if (LoadShape("PIRATE1E."EXT,&Pirate1Shp))\r
169                 TrashProg("Can't load PIRATE1E.BIO");\r
170 \r
171         if (LoadShape("PIRATE2E."EXT,&Pirate2Shp))\r
172                 TrashProg("Can't load PIRATE2E.BIO");\r
173 \r
174         // Deal with shapes...\r
175         //\r
176         VW_SetLineWidth(40);\r
177 \r
178         VW_FadeOut();\r
179 \r
180         MoveScreen(0,0);\r
181         UnpackEGAShapeToScreen(&Pirate1Shp,(linewidth-Pirate1Shp.BPR)<<2,0);\r
182 \r
183         MoveScreen(0,200);\r
184         UnpackEGAShapeToScreen(&Pirate2Shp,(linewidth-Pirate2Shp.BPR)<<2,0);\r
185 \r
186         MoveScreen(0,0);\r
187         VW_FadeIn();\r
188         WaitKeyVBL(57,200);\r
189         while (Keyboard[57]);\r
190 \r
191         SD_PlaySound(GOOD_PICKSND);\r
192 \r
193         MoveScreen(0,200);\r
194         WaitKeyVBL(57,300);\r
195         while (Keyboard[57]);\r
196         VW_FadeOut();\r
197 \r
198         FreeShape(&Pirate1Shp);\r
199         FreeShape(&Pirate2Shp);\r
200 }\r
201 \r
202 #else\r
203 \r
204 ///////////////////////////////////////////////////////////////////////////\r
205 //\r
206 // DoPiracy() - Text-based piracy code...\r
207 //\r
208 void DoPiracy()\r
209 {\r
210 }\r
211 \r
212 #endif\r
213 #endif\r
214 \r
215 //--------------------------------------------------------------------------\r
216 // BlackPalette()\r
217 //--------------------------------------------------------------------------\r
218 void BlackPalette()\r
219 {\r
220         extern char colors[7][17];\r
221 \r
222         _ES=FP_SEG(&colors[0]);\r
223         _DX=FP_OFF(&colors[0]);\r
224         _AX=0x1002;\r
225         geninterrupt(0x10);\r
226         screenfaded = true;\r
227 }\r
228 \r
229 //--------------------------------------------------------------------------\r
230 // ColoredPalette()\r
231 //--------------------------------------------------------------------------\r
232 void ColoredPalette()\r
233 {\r
234         extern char colors[7][17];\r
235 \r
236         _ES=FP_SEG(&colors[3]);\r
237         _DX=FP_OFF(&colors[3]);\r
238         _AX=0x1002;\r
239         geninterrupt(0x10);\r
240         screenfaded = false;\r
241 }\r
242 \r
243 ////////////////////////////////////////////////////////////////////////////\r
244 //\r
245 // Verify()\r
246 //\r
247 long Verify(char *filename)\r
248 {\r
249         int handle;\r
250         long size;\r
251 \r
252         if ((handle=open(filename,O_BINARY))==-1)\r
253                 return (0);\r
254         size=filelength(handle);\r
255         close(handle);\r
256         return(size);\r
257 }\r
258 \r
259 ///////////////////////////////////////////////////////////////////////////\r
260 //\r
261 //      GE_SaveGame\r
262 //\r
263 //      Handles user i/o for saving a game\r
264 //\r
265 ///////////////////////////////////////////////////////////////////////////\r
266 \r
267 void GE_SaveGame()\r
268 {\r
269         boolean GettingFilename=true;\r
270 //      char Filename[FILENAME_LEN+1]; //, ID[sizeof(GAMENAME)], VER[sizeof(SAVEVER_DATA)];\r
271         int handle;\r
272         struct dfree dfree;\r
273         long davail;\r
274 \r
275         VW_FixRefreshBuffer();\r
276         ReadGameList();\r
277         while (GettingFilename)\r
278         {\r
279                 DisplayGameList(2,7,3,10);\r
280                 US_DrawWindow(5,1,30,3);\r
281                 memset(Filename,0,sizeof(Filename));\r
282                 US_CPrint("Enter name to SAVE this game:");\r
283                 VW_UpdateScreen();\r
284                 if (screenfaded)\r
285                         VW_FadeIn();\r
286                 if (!US_LineInput((linewidth<<2)-32,20,Filename,"",true,8,0))\r
287                         goto EXIT_FUNC;\r
288                 if (!strlen(Filename))\r
289                         goto EXIT_FUNC;\r
290                 getdfree(getdisk()+1,&dfree);\r
291                 davail = (long)dfree.df_avail*(long)dfree.df_bsec*(long)dfree.df_sclus;\r
292                 if (davail < 10000)\r
293                 {\r
294                         US_CenterWindow(22,4);\r
295                         US_Print("\n");\r
296                         US_CPrintLine("Disk Full: Can't save game.");\r
297                         US_CPrintLine("Try inserting another disk.");\r
298                         VW_UpdateScreen();\r
299 \r
300                         IN_Ack();\r
301                 }\r
302                 else\r
303                 {\r
304                         strcat(Filename,".SAV");\r
305                         GettingFilename = false;\r
306                         if (Verify(Filename))                                                           // FILE EXISTS\r
307                         {\r
308                                 US_CenterWindow(22,4);\r
309                                 US_CPrintLine("That file already exists...");\r
310                                 US_CPrintLine("Overwrite it ????");\r
311                                 US_CPrintLine("(Y)es or (N)o?");\r
312                                 VW_UpdateScreen();\r
313 \r
314                                 while((!Keyboard[21]) && (!Keyboard[49]) && !Keyboard[27]);\r
315 \r
316                                 if (Keyboard[27])\r
317                                         goto EXIT_FUNC;\r
318                                 if (Keyboard[49])\r
319                                 {\r
320                                         GettingFilename = true;\r
321                                         VW_UpdateScreen();\r
322                                 }\r
323                         }\r
324                 }\r
325         }\r
326 \r
327         handle = open(Filename,O_RDWR|O_CREAT|O_BINARY,S_IREAD|S_IWRITE);\r
328         if (handle==-1)\r
329                 goto EXIT_FUNC;\r
330 \r
331         if ((!CA_FarWrite(handle,(void far *)GAMENAME,sizeof(GAMENAME))) || (!CA_FarWrite(handle,(void far *)SAVEVER_DATA,sizeof(SAVEVER_DATA))))\r
332         {\r
333                 if (!screenfaded)\r
334                         VW_FadeOut();\r
335 \r
336                 return;\r
337         }\r
338 \r
339         if (!USL_SaveGame(handle))\r
340                 Quit("Save game error");\r
341 \r
342 \r
343 \r
344 EXIT_FUNC:;\r
345 \r
346         if (handle!=-1)\r
347                 close(handle);\r
348 \r
349         if (handle==-1)\r
350         {\r
351                 remove(Filename);\r
352                 US_CenterWindow(22,6);\r
353                 US_CPrintLine("DISK ERROR");\r
354                 US_CPrintLine("Check: Write protect...");\r
355                 US_CPrintLine("File name...");\r
356                 US_CPrintLine("Bytes free on disk...");\r
357                 US_CPrintLine("Press SPACE to continue.");\r
358                 VW_UpdateScreen();\r
359                 while (!Keyboard[57]);\r
360                 while (Keyboard[57]);\r
361         }\r
362 \r
363         while (Keyboard[1]);\r
364 \r
365         if (!screenfaded)\r
366                 VW_FadeOut();\r
367 }\r
368 \r
369 \r
370 ///////////////////////////////////////////////////////////////////////////\r
371 //\r
372 //      GE_LoadGame\r
373 //\r
374 //      Handles user i/o for loading a game\r
375 //\r
376 ///////////////////////////////////////////////////////////////////////////\r
377 \r
378 boolean GE_LoadGame()\r
379 {\r
380         boolean GettingFilename=true,rt_code=false;\r
381         int handle;\r
382 \r
383         IN_ClearKeysDown();\r
384         memset(ID,0,sizeof(ID));\r
385         memset(VER,0,sizeof(VER));\r
386         VW_FixRefreshBuffer();\r
387         ReadGameList();\r
388         while (GettingFilename)\r
389         {\r
390                 DisplayGameList(2,7,3,10);\r
391                 US_DrawWindow(5,1,30,3);\r
392                 memset(Filename,0,sizeof(Filename));\r
393                 US_CPrint("Enter name of game to RESTORE:");\r
394                 VW_UpdateScreen();\r
395                 if (screenfaded)\r
396                         VW_FadeIn();\r
397                 if (!US_LineInput((linewidth<<2)-32,20,Filename,"",true,8,0))\r
398                         goto EXIT_FUNC;\r
399                 strcat(Filename,".SAV");\r
400                 GettingFilename = false;\r
401 \r
402                 if (!Verify(Filename))                                                          // FILE DOESN'T EXIST\r
403                 {\r
404                         US_CenterWindow(22,3);\r
405                         US_CPrintLine(" That file doesn't exist....");\r
406                         US_CPrintLine("Press SPACE to try again.");\r
407                         VW_UpdateScreen();\r
408 \r
409                         while (!Keyboard[57]);\r
410                         while (Keyboard[57]);\r
411                         GettingFilename = true;\r
412                 }\r
413         }\r
414 \r
415         handle = open(Filename,O_RDWR|O_BINARY);\r
416         if (handle==-1)\r
417                 goto EXIT_FUNC;\r
418 \r
419         if ((!CA_FarRead(handle,(void far *)&ID,sizeof(ID))) || (!CA_FarRead(handle,(void far *)&VER,sizeof(VER))))\r
420                 return(false);\r
421 \r
422         if ((strcmp(ID,GAMENAME)) || (strcmp(VER,SAVEVER_DATA)))\r
423         {\r
424                 US_CenterWindow(32,4);\r
425                 US_CPrintLine("That isn't a "GAMENAME);\r
426                 US_CPrintLine(".SAV file.");\r
427                 US_CPrintLine("Press SPACE to continue.");\r
428                 VW_UpdateScreen();\r
429                 while (!Keyboard[57]);\r
430                 while (Keyboard[57]);\r
431 \r
432                 if (!screenfaded)\r
433                         VW_FadeOut();\r
434 \r
435                 return(false);\r
436         }\r
437 \r
438         if (!USL_LoadGame(handle))\r
439                 Quit("Load game error.");\r
440 \r
441         rt_code = true;\r
442 \r
443 \r
444 EXIT_FUNC:;\r
445         if (handle==-1)\r
446         {\r
447                 US_CenterWindow(22,3);\r
448                 US_CPrintLine("DISK ERROR ** LOAD **");\r
449                 US_CPrintLine("Press SPACE to continue.");\r
450                 while (!Keyboard[57]);\r
451                 while (Keyboard[57]);\r
452         }\r
453         else\r
454                 close(handle);\r
455 \r
456         if (!screenfaded)\r
457                 VW_FadeOut();\r
458 \r
459         return(rt_code);\r
460 }\r
461 \r
462 ///////////////////////////////////////////////////////////////////////////\r
463 //\r
464 //      GE_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
465 //                      from DOS. Hard coded to ignore if during Load/Save Game.\r
466 //\r
467 ///////////////////////////////////////////////////////////////////////////\r
468 #pragma warn    -par\r
469 #pragma warn    -rch\r
470 int GE_HardError(word errval,int ax,int bp,int si)\r
471 {\r
472 #define IGNORE  0\r
473 #define RETRY   1\r
474 #define ABORT   2\r
475 extern  void    ShutdownId(void);\r
476 \r
477 static  char            buf[32];\r
478 static  WindowRec       wr;\r
479 static  boolean         oldleavedriveon;\r
480                 int                     di;\r
481                 char            c,*s,*t;\r
482 boolean holdscreenfaded;\r
483 \r
484         if (InLoadSaveGame)\r
485                 hardresume(IGNORE);\r
486 \r
487 \r
488         di = _DI;\r
489 \r
490         oldleavedriveon = LeaveDriveOn;\r
491         LeaveDriveOn = false;\r
492 \r
493         if (ax < 0)\r
494                 s = "Device Error";\r
495         else\r
496         {\r
497                 if ((di & 0x00ff) == 0)\r
498                         s = "Drive ~ is Write Protected";\r
499                 else\r
500                         s = "Error on Drive ~";\r
501                 for (t = buf;*s;s++,t++)        // Can't use sprintf()\r
502                         if ((*t = *s) == '~')\r
503                                 *t = (ax & 0x00ff) + 'A';\r
504                 *t = '\0';\r
505                 s = buf;\r
506         }\r
507 \r
508         c = peekb(0x40,0x49);   // Get the current screen mode\r
509         if ((c < 4) || (c == 7))\r
510                 goto oh_kill_me;\r
511 \r
512         // DEBUG - handle screen cleanup\r
513         holdscreenfaded=screenfaded;\r
514 \r
515         US_SaveWindow(&wr);\r
516         VW_ClearVideo(0);            ////////////// added for exiting\r
517         US_CenterWindow(30,3);\r
518         US_CPrint(s);\r
519         US_CPrint("(R)etry or (A)bort?");\r
520         VW_UpdateScreen();\r
521         if (holdscreenfaded)\r
522                 VW_FadeIn();\r
523         IN_ClearKeysDown();\r
524 \r
525 asm     sti     // Let the keyboard interrupts come through\r
526 \r
527         while (true)\r
528         {\r
529                 switch (IN_WaitForASCII())\r
530                 {\r
531                 case key_Escape:\r
532                 case 'a':\r
533                 case 'A':\r
534                         goto oh_kill_me;\r
535                         break;\r
536                 case key_Return:\r
537                 case key_Space:\r
538                 case 'r':\r
539                 case 'R':\r
540                         if (holdscreenfaded)\r
541                                 VW_FadeOut();\r
542                         US_ClearWindow();\r
543                         VW_UpdateScreen();\r
544                         US_RestoreWindow(&wr);\r
545                         LeaveDriveOn = oldleavedriveon;\r
546                         return(RETRY);\r
547                         break;\r
548                 }\r
549         }\r
550 \r
551 oh_kill_me:\r
552         abortprogram = s;\r
553         TrashProg("Terminal Error: %s\n",s);\r
554 //      if (tedlevel)\r
555 //              fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
556 \r
557         return(ABORT);\r
558 #undef  IGNORE\r
559 #undef  RETRY\r
560 #undef  ABORT\r
561 }\r
562 #pragma warn    +par\r
563 #pragma warn    +rch\r
564 \r
565 //--------------------------------------------------------------------------\r
566 //\r
567 //\r
568 //                          B O B   ROUTINES\r
569 //\r
570 //\r
571 //--------------------------------------------------------------------------\r
572 \r
573 \r
574 \r
575 #ifdef BOBLIST\r
576 \r
577 ////////////////////////////////////////////////////////////////////////////\r
578 //\r
579 // UpdateBOBList() - Adds a sprite to an objects BOBlist.  The BOB List\r
580 //                                                      must already be allocated and have an available slot.\r
581 //\r
582 //      RETURNS : true = Success adding Sprite / false = Failure.\r
583 //\r
584 // NOTE : This also sets the users 'needtoreact' flag to true.\r
585 //\r
586 boolean UpdateBOBList(objtype *obj,struct Simple_Shape *Shape,shapeclass Class, short priority, spriteflags sprflags)\r
587 {\r
588         struct BOB_Shape *CurBOBShape = NULL;\r
589 \r
590 #pragma warn -pia\r
591 \r
592         if (CurBOBShape = obj->nextshape)\r
593         {\r
594                 // Treverse down BOBList looking for a sprite with the same class\r
595                 // OR an empty shape struct to store the new shape.\r
596 \r
597                 while ((CurBOBShape->class != Class) && (CurBOBShape->class) && CurBOBShape)\r
598                 {\r
599                         CurBOBShape = CurBOBShape->nextshape;\r
600                 }\r
601 \r
602                 if (CurBOBShape)\r
603                 {\r
604                         RF_RemoveSprite(&CurBOBShape->sprite);\r
605                         CurBOBShape->shapenum = Shape->shapenum;\r
606                         CurBOBShape->x_offset = Shape->x_offset;\r
607                         CurBOBShape->y_offset = Shape->y_offset;\r
608                         CurBOBShape->priority = priority;\r
609                         CurBOBShape->sprflags = sprflags;\r
610                         CurBOBShape->class = Class;\r
611                         return(true);\r
612                 }\r
613         }\r
614         return(false);\r
615 \r
616 #pragma warn +pia\r
617 \r
618 }\r
619 \r
620 /////////////////////////////////////////////////////////////////////////////\r
621 //\r
622 // RemoveBOBShape() - Removes a sprite from a BOBList.\r
623 //\r
624 // RETURNS : true = Success / false = Failure (shape not found)\r
625 //\r
626 boolean RemoveBOBShape(objtype *obj, shapeclass Class)\r
627 {\r
628         struct BOB_Shape *CurBOBShape = NULL;\r
629 \r
630 #pragma warn -pia\r
631 \r
632         if (CurBOBShape = obj->nextshape)\r
633         {\r
634                 while ((CurBOBShape->class != Class) && (!CurBOBShape->class) && CurBOBShape)\r
635                 {\r
636                         CurBOBShape = CurBOBShape->nextshape;\r
637                 }\r
638 \r
639                 if (CurBOBShape)\r
640                 {\r
641                         CurBOBShape->class = noshape;\r
642                         return(true);\r
643                 }\r
644         }\r
645         return(false);\r
646 \r
647 #pragma warn +pia\r
648 \r
649 }\r
650 \r
651 \r
652 /////////////////////////////////////////////////////////////////////////////\r
653 //\r
654 // RemoveBOBList() - Removes an entire BOBList attached to an object.\r
655 //\r
656 //\r
657 void RemoveBOBList(objtype *obj)\r
658 {\r
659         struct BOB_Shape *CurBOBShape;\r
660 \r
661 #pragma warn -pia\r
662 \r
663         if (CurBOBShape = obj->nextshape)\r
664         {\r
665                 // Treverse down BOBList looking for a sprite with the same class\r
666                 // OR an empty shape struct to store the new shape.\r
667 \r
668                 while (CurBOBShape)\r
669                 {\r
670                         if (CurBOBShape->class)\r
671                         {\r
672                                 CurBOBShape->class = noshape;\r
673                                 RF_RemoveSprite (&CurBOBShape->sprite);\r
674                         }\r
675                         CurBOBShape = CurBOBShape->nextshape;\r
676                 }\r
677         }\r
678 \r
679 #pragma warn +pia\r
680 \r
681 }\r
682 \r
683 \r
684 \r
685 /////////////////////////////////////////////////////////////////////////////\r
686 //\r
687 // InitBOBList() -- This initializes a BOB list for all the possible shapes\r
688 //                                                attached at one time.  This is done with an array of\r
689 //                                                BOB_Shape structs and links the 'nextshape' pointer to\r
690 //                                                to the next element.\r
691 //\r
692 //\r
693 void InitBOBList(objtype *obj, struct BOB_Shape *BOB_Shape, short NumElements)\r
694 {\r
695         struct BOB_Shape *CurShape;\r
696         short loop;\r
697 \r
698         obj->nextshape = BOB_Shape;\r
699 \r
700         for (loop=1;loop<NumElements;loop++)\r
701         {\r
702                 CurShape = BOB_Shape++;\r
703                 CurShape->nextshape = BOB_Shape;\r
704         }\r
705 \r
706         BOB_Shape->nextshape = NULL;\r
707 }\r
708 \r
709 \r
710 ////////////////////////////////////////////////////////////////////////////\r
711 //\r
712 // RefreshBOBList() -- This routine updates all sprites attached to the\r
713 //                                                        BOBList and refreshes there position in the sprite\r
714 //                                                        list.\r
715 //\r
716 void RefreshBOBList(objtype *obj)\r
717 {\r
718         struct BOB_Shape *Shape;\r
719 \r
720         Shape = obj->nextshape;\r
721 \r
722         while (Shape)\r
723         {\r
724                 if (Shape->class)\r
725                         RF_PlaceSprite(&Shape->sprite,obj->x+Shape->x_offset,obj->y+Shape->y_offset, Shape->shapenum, spritedraw,Shape->priority,Shape->sprflags);\r
726                 Shape = Shape->nextshape;\r
727         }\r
728 }\r
729 #endif\r
730 \r
731 \r
732 \r
733 //--------------------------------------------------------------------------\r
734 // InitBufferedIO()\r
735 //--------------------------------------------------------------------------\r
736 memptr InitBufferedIO(int handle, BufferedIO *bio)\r
737 {\r
738         bio->handle = handle;\r
739         bio->offset = BIO_BUFFER_LEN;\r
740         bio->status = 0;\r
741         MM_GetPtr(&bio->buffer,BIO_BUFFER_LEN);\r
742 \r
743         return(bio->buffer);\r
744 }\r
745 \r
746 //--------------------------------------------------------------------------\r
747 // FreeBufferedIO()\r
748 //--------------------------------------------------------------------------\r
749 void FreeBufferedIO(BufferedIO *bio)\r
750 {\r
751         if (bio->buffer)\r
752                 MM_FreePtr(&bio->buffer);\r
753 }\r
754 \r
755 //--------------------------------------------------------------------------\r
756 // bio_readch()\r
757 //--------------------------------------------------------------------------\r
758 byte bio_readch(BufferedIO *bio)\r
759 {\r
760         byte far *buffer;\r
761 \r
762         if (bio->offset == BIO_BUFFER_LEN)\r
763         {\r
764                 bio->offset = 0;\r
765                 bio_fillbuffer(bio);\r
766         }\r
767 \r
768         buffer = MK_FP(bio->buffer,bio->offset++);\r
769 \r
770         return(*buffer);\r
771 }\r
772 \r
773 //--------------------------------------------------------------------------\r
774 // bio_fillbuffer()\r
775 //\r
776 // BUGS (Not really bugs... More like RULES!)\r
777 //\r
778 //    1) This code assumes BIO_BUFFER_LEN is no smaller than\r
779 //       NEAR_BUFFER_LEN!!\r
780 //\r
781 //    2) BufferedIO.status should be altered by this code to report\r
782 //       read errors, end of file, etc... If you know how big the file\r
783 //       is you're reading, determining EOF should be no problem.\r
784 //\r
785 //--------------------------------------------------------------------------\r
786 void bio_fillbuffer(BufferedIO *bio)\r
787 {\r
788         #define NEAR_BUFFER_LEN (64)\r
789         byte near_buffer[NEAR_BUFFER_LEN];\r
790         short bio_length,bytes_read,bytes_requested;\r
791 \r
792         bytes_read = 0;\r
793         bio_length = BIO_BUFFER_LEN;\r
794         while (bio_length)\r
795         {\r
796                 if (bio_length > NEAR_BUFFER_LEN-1)\r
797                         bytes_requested = NEAR_BUFFER_LEN;\r
798                 else\r
799                         bytes_requested = bio_length;\r
800 \r
801                 read(bio->handle,near_buffer,bytes_requested);\r
802                 _fmemcpy(MK_FP(bio->buffer,bytes_read),near_buffer,bytes_requested);\r
803 \r
804                 bio_length -= bytes_requested;\r
805                 bytes_read += bytes_requested;\r
806         }\r
807 }\r
808 \r
809 ///////////////////////////////////////////////////////////////////////////\r
810 //\r
811 // SwapLong()\r
812 //\r
813 void SwapLong(long far *Var)\r
814 {\r
815         asm             les     bx,Var\r
816         asm             mov     ax,[es:bx]\r
817         asm             xchg    ah,al\r
818         asm             xchg    ax,[es:bx+2]\r
819         asm             xchg    ah,al\r
820         asm             mov     [es:bx],ax\r
821 }\r
822 \r
823 ///////////////////////////////////////////////////////////////////////////\r
824 //\r
825 // SwapWord()\r
826 //\r
827 void SwapWord(unsigned int far *Var)\r
828 {\r
829         asm             les     bx,Var\r
830         asm             mov     ax,[es:bx]\r
831         asm             xchg    ah,al\r
832         asm             mov     [es:bx],ax\r
833 }\r
834 \r
835 \r
836 #if 0\r
837 \r
838 ////////////////////////////////////////////////////////////////////////////\r
839 //\r
840 // LoadShape()\r
841 //\r
842 int LoadShape(char *Filename,struct Shape *SHP)\r
843 {\r
844         #define CHUNK(Name)     (*ptr == *Name) &&                      \\r
845                                                                 (*(ptr+1) == *(Name+1)) &&      \\r
846                                                                 (*(ptr+2) == *(Name+2)) &&      \\r
847                                                                 (*(ptr+3) == *(Name+3))\r
848 \r
849 \r
850         int RT_CODE;\r
851 //      struct ffblk ffblk;\r
852         FILE *fp;\r
853         char CHUNK[5];\r
854         char far *ptr;\r
855         memptr IFFfile = NULL;\r
856         unsigned long FileLen, size, ChunkLen;\r
857         int loop;\r
858 \r
859 \r
860         RT_CODE = 1;\r
861 \r
862         // Decompress to ram and return ptr to data and return len of data in\r
863         //      passed variable...\r
864 \r
865         if (!(FileLen = BLoad(Filename,&IFFfile)))\r
866                 TrashProg("Can't load Compressed Shape - Possibly corrupt file!");\r
867 \r
868         // Evaluate the file\r
869         //\r
870         ptr = MK_FP(IFFfile,0);\r
871         if (!CHUNK("FORM"))\r
872                 goto EXIT_FUNC;\r
873         ptr += 4;\r
874 \r
875         FileLen = *(long far *)ptr;\r
876         SwapLong((long far *)&FileLen);\r
877         ptr += 4;\r
878 \r
879         if (!CHUNK("ILBM"))\r
880                 goto EXIT_FUNC;\r
881         ptr += 4;\r
882 \r
883         FileLen += 4;\r
884         while (FileLen)\r
885         {\r
886                 ChunkLen = *(long far *)(ptr+4);\r
887                 SwapLong((long far *)&ChunkLen);\r
888                 ChunkLen = (ChunkLen+1) & 0xFFFFFFFE;\r
889 \r
890                 if (CHUNK("BMHD"))\r
891                 {\r
892                         ptr += 8;\r
893                         SHP->bmHdr.w = ((struct BitMapHeader far *)ptr)->w;\r
894                         SHP->bmHdr.h = ((struct BitMapHeader far *)ptr)->h;\r
895                         SHP->bmHdr.x = ((struct BitMapHeader far *)ptr)->x;\r
896                         SHP->bmHdr.y = ((struct BitMapHeader far *)ptr)->y;\r
897                         SHP->bmHdr.d = ((struct BitMapHeader far *)ptr)->d;\r
898                         SHP->bmHdr.trans = ((struct BitMapHeader far *)ptr)->trans;\r
899                         SHP->bmHdr.comp = ((struct BitMapHeader far *)ptr)->comp;\r
900                         SHP->bmHdr.pad = ((struct BitMapHeader far *)ptr)->pad;\r
901                         SwapWord(&SHP->bmHdr.w);\r
902                         SwapWord(&SHP->bmHdr.h);\r
903                         SwapWord(&SHP->bmHdr.x);\r
904                         SwapWord(&SHP->bmHdr.y);\r
905                         ptr += ChunkLen;\r
906                 }\r
907                 else\r
908                 if (CHUNK("BODY"))\r
909                 {\r
910                         ptr += 4;\r
911                         size = *((long far *)ptr);\r
912                         ptr += 4;\r
913                         SwapLong((long far *)&size);\r
914                         SHP->BPR = (SHP->bmHdr.w+7) >> 3;\r
915                         MM_GetPtr(&SHP->Data,size);\r
916                         if (!SHP->Data)\r
917                                 goto EXIT_FUNC;\r
918                         movedata(FP_SEG(ptr),FP_OFF(ptr),FP_SEG(SHP->Data),0,size);\r
919                         ptr += ChunkLen;\r
920 \r
921                         break;\r
922                 }\r
923                 else\r
924                         ptr += ChunkLen+8;\r
925 \r
926                 FileLen -= ChunkLen+8;\r
927         }\r
928 \r
929         RT_CODE = 0;\r
930 \r
931 EXIT_FUNC:;\r
932         if (IFFfile)\r
933         {\r
934 //              segptr = (memptr)FP_SEG(IFFfile);\r
935                 MM_FreePtr(&IFFfile);\r
936         }\r
937 \r
938         return (RT_CODE);\r
939 }\r
940 \r
941 #endif\r
942 \r
943 ////////////////////////////////////////////////////////////////////////////\r
944 //\r
945 // FreeShape()\r
946 //\r
947 void FreeShape(struct Shape *shape)\r
948 {\r
949         if (shape->Data)\r
950                 MM_FreePtr(&shape->Data);\r
951 }\r
952 \r
953 ////////////////////////////////////////////////////////////////////////////\r
954 //\r
955 // UnpackEGAShapeToScreen()\r
956 //\r
957 int UnpackEGAShapeToScreen(struct Shape *SHP,int startx,int starty)\r
958 {\r
959         int currenty;\r
960         signed char n, Rep, far *Src, far *Dst[8], loop, Plane;\r
961         unsigned int BPR, Height;\r
962         boolean NotWordAligned;\r
963 \r
964         NotWordAligned = SHP->BPR & 1;\r
965         startx>>=3;\r
966         Src = MK_FP(SHP->Data,0);\r
967         currenty = starty;\r
968         Plane = 0;\r
969         Height = SHP->bmHdr.h;\r
970         while (Height--)\r
971         {\r
972                 Dst[0] = (MK_FP(0xA000,displayofs));\r
973                 Dst[0] += ylookup[currenty];\r
974                 Dst[0] += startx;\r
975                 for (loop=1; loop<SHP->bmHdr.d; loop++)\r
976                         Dst[loop] = Dst[0];\r
977 \r
978 \r
979                 for (Plane=0; Plane<SHP->bmHdr.d; Plane++)\r
980                 {\r
981                         outport(0x3c4,((1<<Plane)<<8)|2);\r
982 \r
983                         BPR = ((SHP->BPR+1) >> 1) << 1;               // IGNORE WORD ALIGN\r
984                         while (BPR)\r
985                         {\r
986                                 if (SHP->bmHdr.comp)\r
987                                         n = *Src++;\r
988                                 else\r
989                                         n = BPR-1;\r
990 \r
991                                 if (n < 0)\r
992                                 {\r
993                                         if (n != -128)\r
994                                         {\r
995                                                 n = (-n)+1;\r
996                                                 BPR -= n;\r
997                                                 Rep = *Src++;\r
998                                                 if ((!BPR) && (NotWordAligned))   // IGNORE WORD ALIGN\r
999                                                         n--;\r
1000 \r
1001                                                 while (n--)\r
1002                                                         *Dst[Plane]++ = Rep;\r
1003                                         }\r
1004                                         else\r
1005                                                 BPR--;\r
1006                                 }\r
1007                                 else\r
1008                                 {\r
1009                                         n++;\r
1010                                         BPR -= n;\r
1011                                         if ((!BPR) && (NotWordAligned))     // IGNORE WORD ALIGN\r
1012                                                 n--;\r
1013 \r
1014                                         while (n--)\r
1015                                                 *Dst[Plane]++ = *Src++;\r
1016 \r
1017                                         if ((!BPR) && (NotWordAligned))     // IGNORE WORD ALIGN\r
1018                                                 Src++;\r
1019                                 }\r
1020                         }\r
1021                 }\r
1022                 currenty++;\r
1023         }\r
1024 \r
1025         return(0);\r
1026 }\r
1027 \r
1028 ////////////////////////////////////////////////////////////////////////////\r
1029 //\r
1030 // GetKeyChoice()\r
1031 //\r
1032 char GetKeyChoice(char *choices,boolean clear)\r
1033 {\r
1034         extern void DoEvents(void);\r
1035 \r
1036         boolean waiting;\r
1037         char *s,*ss;\r
1038 \r
1039         IN_ClearKeysDown();\r
1040 \r
1041         waiting = true;\r
1042         while (waiting)\r
1043         {\r
1044                 s = choices;\r
1045                 while (*s)\r
1046                 {\r
1047                         if (Keyboard[*s++])\r
1048                         {\r
1049                                 waiting=false;\r
1050                                 break;\r
1051                         }\r
1052                 }\r
1053         }\r
1054 \r
1055         IN_ClearKeysDown();\r
1056 \r
1057         return(*(--s));\r
1058 }\r
1059 \r
1060 #if 0\r
1061 \r
1062 ////////////////////////////////////////////////////////////////////////////\r
1063 //\r
1064 // AnimateObj()\r
1065 //\r
1066 boolean AnimateObj(objtype *obj)\r
1067 {\r
1068         boolean Done;\r
1069 \r
1070         Done = false;\r
1071 \r
1072         if (obj->animtype == at_NONE)           // Animation finished?\r
1073                 return(true);                                           // YEP!\r
1074 \r
1075         if (obj->animdelay)                                     // Check animation delay.\r
1076         {\r
1077                 obj->animdelay -= tics;\r
1078                 if (obj->animdelay < 0)\r
1079                         obj->animdelay = 0;\r
1080                 return(false);\r
1081         }\r
1082 \r
1083         switch (obj->animtype)                          // Animate this object!\r
1084         {\r
1085                 case at_ONCE:\r
1086                 case at_CYCLE:\r
1087                         switch (obj->animdir)\r
1088                         {\r
1089                                 case at_FWD:\r
1090                                         if (obj->curframe < obj->maxframe)\r
1091                                                 AdvanceAnimFWD(obj);\r
1092                                         else\r
1093                                                 if (obj->animtype == at_CYCLE)\r
1094                                                 {\r
1095                                                         obj->curframe = 0;               // RESET CYCLE ANIMATION\r
1096                                                         obj->animdelay=1;\r
1097                                                 }\r
1098                                                 else\r
1099                                                 {\r
1100                                                         obj->animtype = at_NONE; // TERMINATE ONCE ANIM\r
1101                                                         Done = true;\r
1102                                                 }\r
1103                                         break;\r
1104 \r
1105                                 case at_REV:\r
1106                                         if (obj->curframe > 0)\r
1107                                                 AdvanceAnimREV(obj);\r
1108                                         else\r
1109                                                 if (obj->animtype == at_CYCLE)\r
1110                                                 {\r
1111                                                         obj->curframe = obj->maxframe;  // RESET CYCLE ANIMATION\r
1112                                                         obj->animdelay = 1;\r
1113                                                 }\r
1114                                                 else\r
1115                                                 {\r
1116                                                         obj->animtype = at_NONE;   // TERMINATE ONCE ANIM\r
1117                                                         Done = true;\r
1118                                                 }\r
1119                                         break; // REV\r
1120                         }\r
1121                         break;\r
1122 \r
1123                 case at_REBOUND:\r
1124                         switch (obj->animdir)\r
1125                         {\r
1126                                 case at_FWD:\r
1127                                         if (obj->curframe < obj->maxframe)\r
1128                                                 AdvanceAnimFWD(obj);\r
1129                                         else\r
1130                                         {\r
1131                                                 obj->animdir = at_REV;\r
1132                                                 obj->animdelay = 1;\r
1133                                         }\r
1134                                         break;\r
1135 \r
1136                                 case at_REV:\r
1137                                         if (obj->curframe > 0)\r
1138                                                 AdvanceAnimREV(obj);\r
1139                                         else\r
1140                                         {\r
1141                                                 obj->animdir = at_FWD;\r
1142                                                 obj->animdelay = 1;\r
1143                                                 Done = true;\r
1144                                         }\r
1145                                         break;\r
1146                         }\r
1147                         break; /* REBOUND */\r
1148 \r
1149                 case at_WAIT:\r
1150                         Done = true;\r
1151                         break;\r
1152         }\r
1153 \r
1154         return(Done);\r
1155 }\r
1156 \r
1157 void AdvanceAnimFWD(objtype *obj)       // Advances a Frame of ANIM for ONCE,CYCLE, REBOUND\r
1158 {\r
1159         obj->curframe++; // INC frames\r
1160         obj->animdelay = obj->maxdelay;          // Init Delay Counter.\r
1161         obj->needtoreact = true;\r
1162 }\r
1163 \r
1164 \r
1165 void AdvanceAnimREV(objtype *obj)  // Advances a Frame of ANIM for ONCE,CYCLE, REBOUND\r
1166 {\r
1167         obj->curframe--; // DEC frames\r
1168         obj->animdelay = obj->maxdelay;          // Init Delay Counter.\r
1169         obj->needtoreact = true;\r
1170 }\r
1171 #endif\r
1172 \r
1173 #if 0\r
1174 ///////////////////////////////////////////////////////////////////////////\r
1175 //\r
1176 // LoadASArray()  - Load an array of audio samples in FAR memory.\r
1177 //\r
1178 void LoadASArray(struct Sample *ASArray)\r
1179 {\r
1180         int loop = 0;\r
1181 \r
1182         while (ASArray[loop].filename)\r
1183         {\r
1184           if (!BLoad(ASArray[loop].filename,(memptr *)&ASArray[loop].data))\r
1185                   TrashProg("Unable to load sample in LoadASArray()");\r
1186           loop++;\r
1187         }\r
1188 }\r
1189 \r
1190 \r
1191 \r
1192 ////////////////////////////////////////////////////////////////////////////\r
1193 //\r
1194 // FreeASArray() - Frees an ASArray from memory that has been loaded with\r
1195 //                                               LoadASArray()\r
1196 //\r
1197 void FreeASArray(struct Sample *ASArray)\r
1198 {\r
1199         unsigned loop = 0;\r
1200 \r
1201         while (ASArray[loop].data)\r
1202         {\r
1203                 MM_SetPurge((memptr *)&ASArray[loop++].data,3);\r
1204                 MM_FreePtr((memptr *)&ASArray[loop++].data);\r
1205         }\r
1206 }\r
1207 \r
1208 ///////////////////////////////////////////////////////////////////////////\r
1209 //\r
1210 // GE_LoadAllDigiSounds()       - This is a hook that CA_LoadAllSounds()\r
1211 //                                                                        calls to load all of the Digitized sounds for\r
1212 //                                                                        Sound Blaster & Sound Source.\r
1213 //\r
1214 // NOTE : This stub would do any other necessary routines for DigiSounds\r
1215 //                       specific to GAMERS EDGE code. (Keeping seperate from ID's)\r
1216 //\r
1217 void GE_LoadAllDigiSounds()\r
1218 {\r
1219         LoadASArray(DigiSounds);\r
1220 }\r
1221 \r
1222 \r
1223 \r
1224 /////////////////////////////////////////////////////////////////////////\r
1225 //\r
1226 // GE_FreeAllDigiSounds() -- This is a hook that CA_LoadAllSounds()\r
1227 //                                                                        calls to free all digitized sounds for\r
1228 //                                                                        which ever hardware and allow for any necessary\r
1229 //                                                                        clean up.\r
1230 //\r
1231 //\r
1232 // NOTE : This stub would do any other necessary routines for DigiSounds\r
1233 //                       specific to GAMERS EDGE code. (Keeping seperate from ID's)\r
1234 //\r
1235 void GE_FreeAllDigiSounds()\r
1236 {\r
1237         FreeASArray(DigiSounds);\r
1238 }\r
1239 \r
1240 \r
1241 \r
1242 ///////////////////////////////////////////////////////////////////////////\r
1243 //\r
1244 // GE_LoadAllSounds()   - Loads ALL sounds needed for detected hardware.\r
1245 //\r
1246 void GE_LoadAllSounds()\r
1247 {\r
1248         unsigned i,start;\r
1249 \r
1250         start = STARTPCSOUNDS;\r
1251         for (i=0;i<NUMSOUNDS;i++,start++)\r
1252                 CA_CacheAudioChunk (start);\r
1253 \r
1254         if (AdLibPresent)\r
1255         {\r
1256                 start = STARTADLIBSOUNDS;\r
1257                 for (i=0;i<NUMSOUNDS;i++,start++)\r
1258                         CA_CacheAudioChunk (start);\r
1259         }\r
1260 \r
1261         if (SoundBlasterPresent)\r
1262                 LoadASArray(DigiSounds);\r
1263 }\r
1264 \r
1265 \r
1266 //////////////////////////////////////////////////////////////////////////\r
1267 //\r
1268 // GE_PurgeAllSounds() - Frees all sounds that were loaded.\r
1269 //\r
1270 void GE_PurgeAllSounds()\r
1271 {\r
1272         unsigned start,i;\r
1273 \r
1274         start = STARTPCSOUNDS;\r
1275         for (i=0;i<NUMSOUNDS;i++,start++)\r
1276                 if (audiosegs[start])\r
1277                         MM_SetPurge (&(memptr)audiosegs[start],3);              // make purgable\r
1278 \r
1279 \r
1280         if (AdLibPresent)\r
1281         {\r
1282                 start = STARTADLIBSOUNDS;\r
1283                 for (i=0;i<NUMSOUNDS;i++,start++)\r
1284                         if (audiosegs[start])\r
1285                                 MM_SetPurge (&(memptr)audiosegs[start],3);              // make purgable\r
1286         }\r
1287 \r
1288         if (SoundBlasterPresent)\r
1289                 GE_FreeAllDigiSounds();\r
1290 }\r
1291 \r
1292 \r
1293 /////////////////////////////////////////////////////////////////////////////\r
1294 //\r
1295 // PlaySample() -- Plays a DIGITIZED sample using SoundBlaster OR SoundSource\r
1296 //\r
1297 // PARAMETERS : Sample Number (Corresponding to ASArray "DigiSounds[]".\r
1298 //\r
1299 void PlaySample(unsigned SampleNum)\r
1300 {\r
1301 \r
1302         if (!DigiSounds[SampleNum].data)\r
1303                 TrashProg("PlaySample - Trying to play an unloaded digi sound!");\r
1304 \r
1305 \r
1306         switch (SoundMode)                              // external variable in ID_SD for sound mode..\r
1307         {\r
1308                 case sdm_SoundBlaster:\r
1309                 case sdm_SoundBlasterAdLib:\r
1310                         SDL_SBPlaySample(MK_FP(DigiSounds[SampleNum].data,0));\r
1311                         break;\r
1312 \r
1313                 default:\r
1314                         TrashProg("PlaySample() - incorrect SoundMode for PlaySample()");\r
1315                         break;\r
1316         }\r
1317 }\r
1318 \r
1319 \r
1320 /////////////////////////////////////////////////////////////////////////////\r
1321 //\r
1322 // SelectDigiAudio() -- This routine intergrates multi sound hardware with\r
1323 //                                                              id's routines.\r
1324 //\r
1325 void SelectDigiAudio(AudioDeviceType Device)\r
1326 {\r
1327         switch (Device)\r
1328         {\r
1329                 case ged_SoundSource:\r
1330                 case ged_SoundBlaster:\r
1331                         break;\r
1332         }\r
1333 }\r
1334 #endif\r
1335 \r
1336 ///////////////////////////////////////////////////////////////////////////\r
1337 //\r
1338 // DisplayGameList()\r
1339 //\r
1340 void DisplayGameList(short winx, short winy, short list_width, short list_height)\r
1341 {\r
1342         #define SPACES 2\r
1343 \r
1344         short width,col,row,orgcol,games_printed=0,h;\r
1345 \r
1346         // Possibly shrink window.\r
1347         //\r
1348         h = (NumGames / list_width) + ((NumGames % list_width) > 0);\r
1349         if (h < list_height)\r
1350                 list_height = h;\r
1351 \r
1352         // Open window and print header...\r
1353         //\r
1354         US_DrawWindow(winx,winy,list_width*(8+SPACES*2),list_height+3);\r
1355         US_CPrintLine("LIST OF SAVED GAMES");\r
1356         US_Print("\n");\r
1357 \r
1358         col = orgcol = PrintX;\r
1359         row = PrintY;\r
1360 \r
1361         // Display as many 'save game' files as can fit in the window.\r
1362         //\r
1363         width = list_width;\r
1364         while ((games_printed<NumGames) && (list_height))\r
1365         {\r
1366                 // Print filename and padding spaces.\r
1367                 //\r
1368                 US_Printxy(col+(SPACES*8),row,GameListNames[games_printed]);\r
1369                 col += 8*((SPACES*2)+8);\r
1370 \r
1371                 // Check for end-of-line or end-of-window.\r
1372                 //\r
1373                 width--;\r
1374                 if (!width)\r
1375                 {\r
1376                         col = orgcol;\r
1377                         row += 8;\r
1378                         width = list_width;\r
1379                         list_height--;\r
1380                         US_Print("\n");\r
1381                 }\r
1382 \r
1383                 games_printed++;\r
1384         }\r
1385 }\r
1386 \r
1387 ////////////////////////////////////////////////////////////////////////////\r
1388 //\r
1389 // ReadGameList()\r
1390 //\r
1391 void ReadGameList()\r
1392 {\r
1393         struct ffblk ffblk;\r
1394         short done,len;\r
1395 \r
1396         NumGames = -1;\r
1397         done = findfirst("*.sav",&ffblk,0);\r
1398 \r
1399         while (!done)\r
1400         {\r
1401                 if (NumGames == MAX_GAMELIST_NAMES)\r
1402                         memcpy(GameListNames,GameListNames[1],MAX_GAMELIST_NAMES*sizeof(GameListNames[0]));\r
1403                 else\r
1404                         NumGames++;\r
1405 \r
1406                 fnsplit(ffblk.ff_name,NULL,NULL,GameListNames[NumGames],NULL);\r
1407 \r
1408                 done=findnext(&ffblk);\r
1409         }\r
1410 \r
1411         NumGames++;\r
1412 }\r
1413 \r
1414 #if 0\r
1415 ////////////////////////////////////////////////////////////////////////////\r
1416 //\r
1417 // CenterObj()\r
1418 //\r
1419 void CenterObj(objtype *obj, unsigned x, unsigned y)\r
1420 {\r
1421         spritetabletype far *sprite;\r
1422         unsigned width, height;\r
1423 \r
1424         sprite=&spritetable[obj->baseshape+obj->curframe-STARTSPRITES];\r
1425 \r
1426         width = (sprite->xh-sprite->xl+(1<<G_P_SHIFT)) >> 1;\r
1427         if (obj->sprflags&sf_vertflip)\r
1428         {\r
1429                 height = (sprite->yl-(sprite->height<<G_P_SHIFT) + sprite->yh+(1<<G_P_SHIFT)) >> 1;\r
1430         }\r
1431         else\r
1432                 height = (sprite->yh-sprite->yl+(1<<G_P_SHIFT)) >> 1;\r
1433 \r
1434         obj->x = x-width;\r
1435         obj->y = y-height;\r
1436 }\r
1437 #endif\r
1438 \r
1439 #if 0\r
1440 //-------------------------------------------------------------------------\r
1441 // cacheout()\r
1442 //-------------------------------------------------------------------------\r
1443 void cacheout(short s,short e)\r
1444 {\r
1445         short i;\r
1446 \r
1447         for(i=(s);i<=(e);i++)\r
1448         {\r
1449                 grneeded[i]&=~ca_levelbit;\r
1450                 if (grsegs[i])\r
1451                         MM_SetPurge(&grsegs[i],3);\r
1452         }\r
1453 \r
1454 }\r
1455 \r
1456 //-------------------------------------------------------------------------\r
1457 // cachein()\r
1458 //-------------------------------------------------------------------------\r
1459 void cachein(short s,short e)\r
1460 {\r
1461         short i;\r
1462 \r
1463         for(i=(s);i<=(e);i++)\r
1464         {\r
1465                 CA_MarkGrChunk(i);\r
1466                 if (grsegs[i])\r
1467                         MM_SetPurge(&grsegs[i],0);\r
1468         }\r
1469 }\r
1470 #endif\r
1471 \r
1472 #if 0\r
1473 ////////////////////////////////////////////////////////////////////////////\r
1474 //\r
1475 // SetUpdateBlock()\r
1476 //\r
1477 void SetUpdateBlock(unsigned x,unsigned y,unsigned width,unsigned height,char refresh)\r
1478 {\r
1479         eraseblocktype *erase;\r
1480 \r
1481 #if 0 //SP unsure if this is needed\r
1482         x = (x+((MAPBORDER+MAPXLEFTOFFSET)<<4))>>3;\r
1483         y += ((MAPBORDER+MAPYTOPOFFSET)<<4);\r
1484 #else\r
1485         x = (x+(MAPBORDER<<4))>>3;\r
1486         y += (MAPBORDER<<4);\r
1487 #endif\r
1488         width >>= 3;\r
1489 \r
1490         if (refresh & 1)\r
1491         {\r
1492                 erase = eraselistptr[0]++;\r
1493                 erase->screenx=x;\r
1494                 erase->screeny=y;\r
1495                 erase->width=width;\r
1496                 erase->height=height;\r
1497         }\r
1498 \r
1499         if (refresh & 2)\r
1500         {\r
1501                 erase = eraselistptr[1]++;\r
1502                 erase->screenx=x;\r
1503                 erase->screeny=y;\r
1504                 erase->width=width;\r
1505                 erase->height=height;\r
1506         }\r
1507 }\r
1508 \r
1509 \r
1510 ////////////////////////////////////////////////////////////////////////////\r
1511 //\r
1512 // ObjHeight\r
1513 //\r
1514 unsigned ObjHeight(objtype *obj)\r
1515 {\r
1516         spritetabletype far *sprite;\r
1517 \r
1518         sprite=&spritetable[obj->baseshape+obj->curframe-STARTSPRITES];\r
1519 \r
1520         if (obj->sprflags&sf_vertflip)\r
1521         {\r
1522                 return((sprite->yl-(sprite->height<<G_P_SHIFT) + sprite->yh+(1<<G_P_SHIFT)) >> 1);\r
1523         }\r
1524         else\r
1525                 return((sprite->yh-sprite->yl+(1<<G_P_SHIFT)) >> 1);\r
1526 }\r
1527 \r
1528 \r
1529 ////////////////////////////////////////////////////////////////////////////\r
1530 //\r
1531 // ObjWidth\r
1532 //\r
1533 unsigned ObjWidth(objtype *obj)\r
1534 {\r
1535         spritetabletype far *sprite;\r
1536 \r
1537         sprite=&spritetable[obj->baseshape+obj->curframe-STARTSPRITES];\r
1538 \r
1539         return((sprite->xh-sprite->xl+(1<<G_P_SHIFT)) >> 1);\r
1540 }\r
1541 #endif\r
1542 \r
1543 #if 0\r
1544 //--------------------------------------------------------------------------\r
1545 // visible_on()\r
1546 //--------------------------------------------------------------------------\r
1547 boolean visible_on(objtype *obj)\r
1548 {\r
1549         if (!(obj->flags & of_visible))\r
1550         {\r
1551                 obj->needtoreact=true;\r
1552                 obj->flags |= of_visible;\r
1553                 return(true);\r
1554         }\r
1555 \r
1556         return(false);\r
1557 }\r
1558 \r
1559 //--------------------------------------------------------------------------\r
1560 // visible_off()\r
1561 //--------------------------------------------------------------------------\r
1562 boolean visible_off(objtype *obj)\r
1563 {\r
1564         if (obj->flags & of_visible)\r
1565         {\r
1566                 obj->needtoreact=true;\r
1567                 obj->flags &= ~of_visible;\r
1568                 return(true);\r
1569         }\r
1570 \r
1571         return(false);\r
1572 }\r
1573 #endif\r
1574 \r
1575 \r
1576 /*\r
1577 ===================\r
1578 =\r
1579 = FizzleFade\r
1580 =\r
1581 ===================\r
1582 */\r
1583 \r
1584 #define PIXPERFRAME     10000\r
1585 \r
1586 void FizzleFade (unsigned source, unsigned dest,\r
1587         unsigned width,unsigned height, boolean abortable)\r
1588 {\r
1589         unsigned        drawofs,pagedelta;\r
1590         unsigned        char maskb[8] = {1,2,4,8,16,32,64,128};\r
1591         unsigned        x,y,p,frame;\r
1592         long            rndval;\r
1593         ScanCode                         lastLastScan=LastScan=0;\r
1594 \r
1595         width--;\r
1596         height--;\r
1597 \r
1598         pagedelta = dest-source;\r
1599 //      VW_SetScreen (dest,0);\r
1600         rndval = 1;\r
1601         y = 0;\r
1602 \r
1603 asm     mov     es,[screenseg]\r
1604 asm     mov     dx,SC_INDEX\r
1605 asm     mov     al,SC_MAPMASK\r
1606 asm     out     dx,al\r
1607 \r
1608         TimeCount=frame=0;\r
1609         do      // while (1)\r
1610         {\r
1611                 if ((abortable) || (Flags & FL_QUICK))\r
1612                 {\r
1613                         IN_ReadControl(0,&control);\r
1614                         if (control.button0 || control.button1 || (lastLastScan != LastScan)\r
1615                         || Keyboard[sc_Escape] || (Flags & FL_QUICK))\r
1616                         {\r
1617                                 VW_ScreenToScreen (source,dest,(width+1)/8,height+1);\r
1618                                 goto exitfunc;\r
1619                         }\r
1620                 }\r
1621 \r
1622                 for (p=0;p<PIXPERFRAME;p++)\r
1623                 {\r
1624                         //\r
1625                         // seperate random value into x/y pair\r
1626                         //\r
1627                         asm     mov     ax,[WORD PTR rndval]\r
1628                         asm     mov     dx,[WORD PTR rndval+2]\r
1629                         asm     mov     bx,ax\r
1630                         asm     dec     bl\r
1631                         asm     mov     [BYTE PTR y],bl                 // low 8 bits - 1 = y xoordinate\r
1632                         asm     mov     bx,ax\r
1633                         asm     mov     cx,dx\r
1634                         asm     shr     cx,1\r
1635                         asm     rcr     bx,1\r
1636                         asm     shr     bx,1\r
1637                         asm     shr     bx,1\r
1638                         asm     shr     bx,1\r
1639                         asm     shr     bx,1\r
1640                         asm     shr     bx,1\r
1641                         asm     shr     bx,1\r
1642                         asm     shr     bx,1\r
1643                         asm     mov     [x],bx                                  // next 9 bits = x xoordinate\r
1644                         //\r
1645                         // advance to next random element\r
1646                         //\r
1647                         asm     shr     dx,1\r
1648                         asm     rcr     ax,1\r
1649                         asm     jnc     noxor\r
1650                         asm     xor     dx,0x0001\r
1651                         asm     xor     ax,0x2000\r
1652 noxor:\r
1653                         asm     mov     [WORD PTR rndval],ax\r
1654                         asm     mov     [WORD PTR rndval+2],dx\r
1655 \r
1656                         if (x>width || y>height)\r
1657                                 continue;\r
1658                         drawofs = source+ylookup[y];\r
1659 \r
1660                         asm     mov     cx,[x]\r
1661                         asm     mov     si,cx\r
1662                         asm     and     si,7\r
1663                         asm     mov dx,GC_INDEX\r
1664                         asm     mov al,GC_BITMASK\r
1665                         asm     mov     ah,BYTE PTR [maskb+si]\r
1666                         asm     out dx,ax\r
1667 \r
1668                         asm     mov     si,[drawofs]\r
1669                         asm     shr     cx,1\r
1670                         asm     shr     cx,1\r
1671                         asm     shr     cx,1\r
1672                         asm     add     si,cx\r
1673                         asm     mov     di,si\r
1674                         asm     add     di,[pagedelta]\r
1675 \r
1676                         asm     mov     dx,GC_INDEX\r
1677                         asm     mov     al,GC_READMAP                   // leave GC_INDEX set to READMAP\r
1678                         asm     out     dx,al\r
1679 \r
1680                         asm     mov     dx,SC_INDEX+1\r
1681                         asm     mov     al,1\r
1682                         asm     out     dx,al\r
1683                         asm     mov     dx,GC_INDEX+1\r
1684                         asm     mov     al,0\r
1685                         asm     out     dx,al\r
1686 \r
1687                         asm     mov     bl,[es:si]\r
1688                         asm     xchg [es:di],bl\r
1689 \r
1690                         asm     mov     dx,SC_INDEX+1\r
1691                         asm     mov     al,2\r
1692                         asm     out     dx,al\r
1693                         asm     mov     dx,GC_INDEX+1\r
1694                         asm     mov     al,1\r
1695                         asm     out     dx,al\r
1696 \r
1697                         asm     mov     bl,[es:si]\r
1698                         asm     xchg [es:di],bl\r
1699 \r
1700                         asm     mov     dx,SC_INDEX+1\r
1701                         asm     mov     al,4\r
1702                         asm     out     dx,al\r
1703                         asm     mov     dx,GC_INDEX+1\r
1704                         asm     mov     al,2\r
1705                         asm     out     dx,al\r
1706 \r
1707                         asm     mov     bl,[es:si]\r
1708                         asm     xchg [es:di],bl\r
1709 \r
1710                         asm     mov     dx,SC_INDEX+1\r
1711                         asm     mov     al,8\r
1712                         asm     out     dx,al\r
1713                         asm     mov     dx,GC_INDEX+1\r
1714                         asm     mov     al,3\r
1715                         asm     out     dx,al\r
1716 \r
1717                         asm     mov     bl,[es:si]\r
1718                         asm     xchg [es:di],bl\r
1719 \r
1720                         if (rndval == 1)                // entire sequence has been completed\r
1721                                 goto exitfunc;\r
1722                 }\r
1723 //              frame++;\r
1724 //              while (TimeCount<frame);         // don't go too fast\r
1725 \r
1726         } while (1);\r
1727 \r
1728 exitfunc:;\r
1729         EGABITMASK(255);\r
1730         EGAMAPMASK(15);\r
1731         return;\r
1732 }\r
1733 \r
1734 #if 0\r
1735 //-------------------------------------------------------------------------\r
1736 // mprintf()\r
1737 //-------------------------------------------------------------------------\r
1738 void mprintf(char *msg, ...)\r
1739 {\r
1740         static char x=0;\r
1741         static char y=0;\r
1742         static char far *video = MK_FP(0xb000,0x0000);\r
1743         char buffer[100],*ptr;\r
1744 \r
1745         va_list(ap);\r
1746 \r
1747         va_start(ap,msg);\r
1748 \r
1749         vsprintf(buffer,msg,ap);\r
1750 \r
1751         ptr = buffer;\r
1752         while (*ptr)\r
1753         {\r
1754                 switch (*ptr)\r
1755                 {\r
1756                         case '\n':\r
1757                                 if (y >= 23)\r
1758                                 {\r
1759                                         video -= (x<<1);\r
1760                                         _fmemcpy(MK_FP(0xb000,0x0000),MK_FP(0xb000,0x00a0),3840);\r
1761                                 }\r
1762                                 else\r
1763                                 {\r
1764                                         y++;\r
1765                                         video += ((80-x)<<1);\r
1766                                 }\r
1767                                 x=0;\r
1768                         break;\r
1769 \r
1770                         default:\r
1771                                 *video = *ptr;\r
1772                                 video[1] = 15;\r
1773                                 video += 2;\r
1774                                 x++;\r
1775                         break;\r
1776                 }\r
1777                 ptr++;\r
1778         }\r
1779 \r
1780         va_end(ap);\r
1781 }\r
1782 #endif\r
1783 \r
1784 #if 0\r
1785 \r
1786 //--------------------------------------------------------------------------\r
1787 //                                                               FULL SCREEN REFRESH/ANIM MANAGERS\r
1788 //--------------------------------------------------------------------------\r
1789 \r
1790 ///////////////////////////////////////////////////////////////////////////\r
1791 //\r
1792 //  InitLatchRefresh() -- Loads an ILBM (JAMPAK'd) into the Master Latch\r
1793 //                                                                to be used as the background refresh screen...\r
1794 //\r
1795 void InitLatchRefresh(char *filename)\r
1796 {\r
1797         struct Shape RefreshShp;\r
1798         short yofs;\r
1799 \r
1800         VW_ClearVideo(0);\r
1801 \r
1802         if (LoadShape(filename,&RefreshShp))\r
1803                 TrashProg("Can't load %s",filename);\r
1804 \r
1805         VW_SetLineWidth(RefreshShp.BPR);\r
1806 \r
1807         yofs = masterswap/SCREENWIDTH;\r
1808         MoveGfxDst(0,yofs);                                                             // Handle title screen\r
1809         UnpackEGAShapeToScreen(&RefreshShp,0,0);\r
1810         FreeShape(&RefreshShp);\r
1811 \r
1812         MoveScreen(0,0);\r
1813         VW_InitDoubleBuffer();\r
1814 \r
1815         RF_NewPosition(0,0);\r
1816 \r
1817         RF_Refresh();\r
1818 \r
1819         SetUpdateBlock(0,0,RefreshShp.bmHdr.w,RefreshShp.bmHdr.h,3);\r
1820 }\r
1821 \r
1822 \r
1823 ////////////////////////////////////////////////////////////////////////////\r
1824 //\r
1825 // InitFullScreenAnim() -- Initialize ALL necessary functions for full screen\r
1826 //                                                                      animation types.\r
1827 //\r
1828 // filename - filename for background lbm.\r
1829 // SpawnAll - spawn function to call to spawn all inital objects..\r
1830 //\r
1831 void InitFullScreenAnim(char *filename, void (*SpawnAll)())\r
1832 {\r
1833         unsigned old_flags;\r
1834 \r
1835         old_flags = GE_SystemFlags.flags;\r
1836         GE_SystemFlags.flags &= ~(GEsf_Tiles | GEsf_Panning | GEsf_RefreshVec);\r
1837 \r
1838         CA_ClearMarks();\r
1839 \r
1840         RFL_InitSpriteList();\r
1841         InitObjArray();\r
1842 \r
1843         if (SpawnAll)\r
1844                 SpawnAll();\r
1845 \r
1846         CA_CacheMarks(NULL);\r
1847 \r
1848         CalcInactivate();\r
1849         CalcSprites();\r
1850 \r
1851         InitLatchRefresh(filename);\r
1852 \r
1853         RF_ForceRefresh();\r
1854         RF_ForceRefresh();\r
1855 \r
1856         GE_SystemFlags.flags = old_flags;\r
1857 }\r
1858 \r
1859 \r
1860 \r
1861 ///////////////////////////////////////////////////////////////////////////\r
1862 //\r
1863 // DoFullScreenAnim()   -- a General "Do-Every-Thing" function that\r
1864 //                                                                      displays a full screen animation...\r
1865 //\r
1866 // filename - Filename of background lbm\r
1867 //      SpawnAll        - Function to call to spawn all inital objects (REQUIRED)\r
1868 //      CheckKey - Function to call every cycle - The function called must\r
1869 //                                return a value of greater than zero (0) to terminate the\r
1870 //                                animation cycle.                                                                        (REQUIRED)\r
1871 //      CleanUp - Function to call upon exiting the animation. (OPTIONAL)\r
1872 //\r
1873 void DoFullScreenAnim(char *filename, void (*SpawnAll)(), short (*CheckKey)(),void (*CleanUp)())\r
1874 {\r
1875         unsigned old_flags;\r
1876         boolean ExitAnim = false;\r
1877 \r
1878         // Save off the current system flags....\r
1879 \r
1880         old_flags = GE_SystemFlags.flags;\r
1881         GE_SystemFlags.flags &= ~(GEsf_Tiles | GEsf_Panning);\r
1882 \r
1883 //      randomize();\r
1884 \r
1885         // Init refresh latch screen, initalize all object, and setup video mode.\r
1886 \r
1887         InitFullScreenAnim(filename,SpawnAll);\r
1888 \r
1889         VW_FadeIn();\r
1890 \r
1891         while (!ExitAnim)\r
1892         {\r
1893                 CalcInactivate();\r
1894                 CalcSprites();\r
1895                 RF_Refresh();\r
1896 \r
1897                 ExitAnim = (boolean)CheckKey();\r
1898         }\r
1899 \r
1900 //      RemoveBOBList(player);\r
1901 //      CalcInactivate();\r
1902 \r
1903         if (CleanUp)\r
1904                 CleanUp();\r
1905 \r
1906         // Restore old system flags...\r
1907 \r
1908         GE_SystemFlags.flags = old_flags;\r
1909 }\r
1910 \r
1911 #endif\r
1912 \r
1913 //--------------------------------------------------------------------------\r
1914 // FindFile()\r
1915 //--------------------------------------------------------------------------\r
1916 boolean FindFile(char *filename,char *disktext,char disknum)\r
1917 {\r
1918         extern boolean splitscreen;\r
1919 \r
1920         char command[100];\r
1921         char choices[]={sc_Escape,sc_Space,0},drive[2];\r
1922         boolean fadeitout=false,rt_code=2;\r
1923 \r
1924         if (!disktext)\r
1925                 disktext = GAMENAME;\r
1926         drive[0] = getdisk() + 'A';\r
1927         drive[1] = 0;\r
1928         while (rt_code == 2)\r
1929         {\r
1930                 if (Verify(filename))\r
1931                         rt_code = true;\r
1932                 else\r
1933                 {\r
1934                         if (ge_textmode)\r
1935                         {\r
1936                                 clrscr();\r
1937                                 gotoxy(1,1);\r
1938                                 printf("\nInsert %s disk %d into drive %s.\n",disktext,disknum,drive);\r
1939                                 printf("Press SPACE to continue, ESC to abort.\n");\r
1940                         }\r
1941                         else\r
1942                         {\r
1943                                 if (splitscreen)\r
1944                                 {\r
1945                                         bufferofs = displayofs = screenloc[screenpage];\r
1946                                         CenterWindow(38,5);\r
1947                                 }\r
1948                                 else\r
1949                                 {\r
1950                                         bufferofs = displayofs = 0;\r
1951                                         US_CenterWindow(38,5);\r
1952                                 }\r
1953 \r
1954                                 strcpy(command,"\nInsert ");\r
1955                                 strcat(command,disktext);\r
1956                                 strcat(command," disk");\r
1957                                 if (disknum != -1)\r
1958                                 {\r
1959                                         strcat(command," ");\r
1960                                         itoa(disknum,command+strlen(command),10);\r
1961                                 }\r
1962                                 strcat(command," into drive ");\r
1963                                 strcat(command,drive);\r
1964                                 strcat(command,".");\r
1965                                 US_CPrint(command);\r
1966                                 US_CPrint("Press SPACE to continue, ESC to abort.");\r
1967                         }\r
1968 \r
1969                         sound(300);\r
1970                         VW_WaitVBL(20);\r
1971                         nosound();\r
1972 \r
1973                         if (!ge_textmode)\r
1974                         {\r
1975                                 if (screenfaded)\r
1976                                 {\r
1977                                         VW_FadeIn();\r
1978                                         fadeitout=true;\r
1979                                 }\r
1980                         }\r
1981                         if (GetKeyChoice(choices,true) == sc_Escape)\r
1982                                 rt_code = false;\r
1983                 }\r
1984         }\r
1985 \r
1986         if (!ge_textmode)\r
1987                 if (fadeitout)\r
1988                         VW_FadeOut();\r
1989 \r
1990         return(rt_code);\r
1991 }\r
1992 \r
1993 #if 0\r
1994 //--------------------------------------------------------------------------\r
1995 // CacheAll()\r
1996 //--------------------------------------------------------------------------\r
1997 void CacheAV(char *title)\r
1998 {\r
1999         if (Verify("EGAGRAPH."EXT))\r
2000         {\r
2001                 CA_CacheMarks(title);\r
2002                 if (!FindFile("EGAGRAPH."EXT,AUDIO_DISK))\r
2003                         TrashProg("Can't find graphics files.");\r
2004 \r
2005 // cache in audio\r
2006 \r
2007                 current_disk = AUDIO_DISK;\r
2008         }\r
2009         else\r
2010         {\r
2011 \r
2012 // cache in audio\r
2013 \r
2014                 if (!FindFile("EGAGRAPH."EXT,VIDEO_DISK))\r
2015                         TrashProg("Can't find audio files.");\r
2016                 CA_CacheMarks(title);\r
2017 \r
2018                 current_disk = VIDEO_DISK;\r
2019         }\r
2020 }\r
2021 #endif\r
2022 \r
2023 #ifdef TEXT_PRESENTER\r
2024 //--------------------------------------------------------------------------\r
2025 //\r
2026 //                         TEXT PRESENTER CODE\r
2027 //\r
2028 //--------------------------------------------------------------------------\r
2029 \r
2030 typedef enum pi_stype {pis_pic2x,pis_latch_pic} pi_stype;\r
2031 \r
2032 \r
2033 typedef struct {                                                // 4 bytes\r
2034         unsigned shapenum;\r
2035         pi_stype shape_type;\r
2036 } pi_shape_info;\r
2037 \r
2038 #define pia_active      0x01\r
2039 \r
2040 typedef struct {                                                // 10 bytes\r
2041         char baseshape;\r
2042         char frame;\r
2043         char maxframes;\r
2044         short delay;\r
2045         short maxdelay;\r
2046         short x,y;\r
2047 } pi_anim_info;\r
2048 \r
2049         #define PI_CASE_SENSITIVE\r
2050 \r
2051         #define PI_RETURN_CHAR                  '\n'\r
2052         #define PI_CONTROL_CHAR                 '^'\r
2053 \r
2054         #define PI_CNVT_CODE(c1,c2)     ((c1)|(c2<<8))\r
2055 \r
2056 // shape table provides a way for the presenter to access and\r
2057 // display any shape.\r
2058 //\r
2059 pi_shape_info far pi_shape_table[] = {\r
2060 \r
2061                                                                                         {BOLTOBJPIC,pis_pic2x},                         // 0\r
2062                                                                                         {NUKEOBJPIC,pis_pic2x},\r
2063                                                                                         {SKELETON_1PIC,pis_pic2x},\r
2064                                                                                         {EYE_WALK1PIC,pis_pic2x},\r
2065                                                                                         {ZOMB_WALK1PIC,pis_pic2x},\r
2066 \r
2067                                                                                         {TIMEOBJ1PIC,pis_pic2x},                        // 5\r
2068                                                                                         {POTIONOBJPIC,pis_pic2x},\r
2069                                                                                         {RKEYOBJPIC,pis_pic2x},\r
2070                                                                                         {YKEYOBJPIC,pis_pic2x},\r
2071                                                                                         {GKEYOBJPIC,pis_pic2x},\r
2072 \r
2073                                                                                         {BKEYOBJPIC,pis_pic2x},                         // 10\r
2074                                                                                         {RGEM1PIC,pis_pic2x},\r
2075                                                                                         {GGEM1PIC,pis_pic2x},\r
2076                                                                                         {BGEM1PIC,pis_pic2x},\r
2077                                                                                         {YGEM1PIC,pis_pic2x},\r
2078 \r
2079                                                                                         {PGEM1PIC,pis_pic2x},                           // 15\r
2080                                                                                         {CHESTOBJPIC,pis_pic2x},\r
2081                                                                                         {PSHOT1PIC,pis_pic2x},\r
2082                                                                                         {RED_DEMON1PIC,pis_pic2x},\r
2083                                                                                         {MAGE1PIC,pis_pic2x},\r
2084 \r
2085                                                                                         {BAT1PIC,pis_pic2x},                                    // 20\r
2086                                                                                         {GREL1PIC,pis_pic2x},\r
2087                                                                                         {GODESS_WALK1PIC,pis_pic2x},\r
2088                                                                                         {ANT_WALK1PIC,pis_pic2x},\r
2089                                                                                         {FATDEMON_WALK1PIC,pis_pic2x},\r
2090 \r
2091                                                                                         {SUCCUBUS_WALK1PIC,pis_pic2x},  //25\r
2092                                                                                         {TREE_WALK1PIC,pis_pic2x},\r
2093                                                                                         {DRAGON_WALK1PIC,pis_pic2x},\r
2094                                                                                         {BUNNY_LEFT1PIC,pis_pic2x},\r
2095 \r
2096 };\r
2097 \r
2098 // anim table holds info about each different animation.\r
2099 //\r
2100 pi_anim_info far pi_anim_table[] = {{0,0,3,0,10},               // 0            BOLT\r
2101                                                                                                 {1,0,3,0,10},     //       NUKE\r
2102                                                                                                 {2,0,4,0,10},     //       SKELETON\r
2103                                                                                                 {3,0,3,0,10},     //       EYE\r
2104                                                                                                 {4,0,3,0,10},     //       ZOMBIE\r
2105 \r
2106                                                                                                 {5,0,2,0,10},     // 5     FREEZE TIME\r
2107                                                                                                 {11,0,2,0,10},    //                    RED GEM\r
2108                                                                                                 {12,0,2,0,10},    //       GREEN GEM\r
2109                                                                                                 {13,0,2,0,10},    //       BLUE GEM\r
2110                                                                                                 {14,0,2,0,10},    //       YELLOW GEM\r
2111 \r
2112                                                                                                 {15,0,2,0,10},    // 10    PURPLE GEM\r
2113                                                                                                 {17,0,2,0,10},    //       PLAYER'S SHOT\r
2114                                                                                                 {18,0,3,0,10},    //       RED DEMON\r
2115                                                                                                 {19,0,2,0,10},    //       MAGE\r
2116                                                                                                 {20,0,4,0,10},    //       BAT\r
2117 \r
2118                                                                                                 {21,0,2,0,10},    // 15    GRELMINAR\r
2119                                                                                                 {22,0,3,0,10},    //       GODESS\r
2120                                                                                                 {23,0,3,0,10},    //       ANT\r
2121                                                                                                 {24,0,4,0,10},    //       FAT DEMON\r
2122                                                                                                 {25,0,4,0,10},    //       SUCCUBUS\r
2123 \r
2124                                                                                                 {26,0,2,0,10},    // 20    TREE\r
2125                                                                                                 {27,0,3,0,10},    //       DRAGON\r
2126                                                                                                 {28,0,2,0,10},    //       BUNNY\r
2127 };\r
2128 \r
2129 // anim list is created on the fly from the anim table...\r
2130 // this allows a single animation to be display in more than\r
2131 // one place...\r
2132 //\r
2133 pi_anim_info far pi_anim_list[PI_MAX_ANIMS];\r
2134 boolean pi_recursing=false;\r
2135 \r
2136 //--------------------------------------------------------------------------\r
2137 // Presenter() - DANGEROUS DAVE "Presenter()" is more up-to-date than this.\r
2138 //\r
2139 //\r
2140 // Active control codes:\r
2141 //\r
2142 //  ^CE                         - center text between 'left margin' and 'right margin'\r
2143 //  ^FCn                                - set font color\r
2144 //  ^LMnnn                      - set left margin (if 'nnn' == "fff" uses current x)\r
2145 //  ^RMnnn                      - set right margin (if 'nnn' == "fff" uses current x)\r
2146 //  ^EP                         - end of page (waits for up/down arrow)\r
2147 //  ^PXnnn                      - move x to coordinate 'n'\r
2148 //  ^PYnnn                      - move y to coordinate 'n'\r
2149 //  ^XX                         - exit presenter\r
2150 //  ^LJ                         - left justify  --\ ^RJ doesn't handle imbedded control\r
2151 //  ^RJ                         - right justify --/ codes properly. Use with caution.\r
2152 //  ^BGn                                - set background color\r
2153 //  ^ANnn                       - define animation\r
2154 //  ^SHnnn                      - display shape 'n' at current x,y\r
2155 //\r
2156 //\r
2157 // Future control codes:\r
2158 //\r
2159 //  ^OBnnn                      - activate object 'n'\r
2160 //  ^FL                         - flush to edges (whatever it's called)\r
2161 //\r
2162 //\r
2163 // Other info:\r
2164 //\r
2165 // All 'n' values are hex numbers (0 - f), case insensitive.\r
2166 // The number of N's listed is the number of digits REQUIRED by that control\r
2167 // code. (IE: ^LMnnn MUST have 3 values! --> 003, 1a2, 01f, etc...)\r
2168 //\r
2169 // If a line consists only of control codes, the cursor is NOT advanced\r
2170 // to the next line (the ending <CR><LF> is skipped). If just ONE non-control\r
2171 // code is added, the number "8" for example, then the "8" is displayed\r
2172 // and the cursor is advanced to the next line.\r
2173 //\r
2174 // ^CE must be on the same line as the text it should center!\r
2175 //\r
2176 //--------------------------------------------------------------------------\r
2177 void Presenter(PresenterInfo *pi)\r
2178 {\r
2179 #ifdef AMIGA\r
2180         XBitMap **font = pi->font;\r
2181 \r
2182         #define ch_width(ch) font[ch]->pad\r
2183         char font_height = font[0]->Rows;\r
2184 #else\r
2185         fontstruct _seg *font = (fontstruct _seg *)grsegs[STARTFONT];\r
2186 \r
2187         #define MAX_PB 150\r
2188         #define ch_width(ch) font->width[ch]\r
2189         char font_height = font->height-1;              // "-1" squeezes font vertically\r
2190         char pb[MAX_PB];\r
2191         short length;\r
2192 #endif\r
2193 \r
2194         enum {jm_left,jm_right,jm_flush};\r
2195         char justify_mode = jm_left;\r
2196         boolean centering=false;\r
2197 \r
2198         short bgcolor = pi->bgcolor;\r
2199         short xl=pi->xl,yl=pi->yl,xh=pi->xh,yh=pi->yh;\r
2200         short cur_x = xl, cur_y = yl;\r
2201         char far *first_ch = pi->script[0];\r
2202 \r
2203         char far *scan_ch,temp;\r
2204         short scan_x,PageNum=0,numanims=0;\r
2205         boolean up_released=true,dn_released=true;\r
2206         boolean presenting=true,start_of_line=true;\r
2207 \r
2208 // if set background is first thing in file, make sure initial screen\r
2209 // clear uses this color.\r
2210 //\r
2211         if (!_fstrncmp(first_ch,"^BG",3))\r
2212                 bgcolor = PI_VALUE(first_ch+3,1);\r
2213 \r
2214         if (!pi_recursing)\r
2215         {\r
2216                 PurgeAllGfx();\r
2217                 CachePage(first_ch);\r
2218         }\r
2219         VW_Bar(xl,yl,xh-xl+1,yh-yl+1,bgcolor);\r
2220 \r
2221         while (presenting)\r
2222         {\r
2223 //\r
2224 // HANDLE WORD-WRAPPING TEXT\r
2225 //\r
2226                 if (*first_ch != PI_CONTROL_CHAR)\r
2227                 {\r
2228                         start_of_line = false;\r
2229 \r
2230         // Parse script until one of the following:\r
2231         //\r
2232         // 1) text extends beyond right margin\r
2233         // 2) NULL termination is reached\r
2234         // 3) PI_RETURN_CHAR is reached\r
2235         // 4) PI_CONTROL_CHAR is reached\r
2236         //\r
2237                         scan_x = cur_x;\r
2238                         scan_ch = first_ch;\r
2239                         while ((scan_x+ch_width(*scan_ch) <= xh) && (*scan_ch) &&\r
2240                                          (*scan_ch != PI_RETURN_CHAR) && (*scan_ch != PI_CONTROL_CHAR))\r
2241                                 scan_x += ch_width(*scan_ch++);\r
2242 \r
2243         // if 'text extends beyond right margin', scan backwards for\r
2244         // a SPACE\r
2245         //\r
2246                         if (scan_x+ch_width(*scan_ch) > xh)\r
2247                         {\r
2248                                 short last_x = scan_x;\r
2249                                 char far *last_ch = scan_ch;\r
2250 \r
2251                                 while ((scan_ch != first_ch) && (*scan_ch != ' ') && (*scan_ch != PI_RETURN_CHAR))\r
2252                                         scan_x -= ch_width(*scan_ch--);\r
2253 \r
2254                                 if (scan_ch == first_ch)\r
2255                                         scan_ch = last_ch, scan_x = last_x;\r
2256                         }\r
2257 \r
2258         // print current line\r
2259         //\r
2260 #ifdef AMIGA\r
2261                         while (first_ch < scan_ch)\r
2262                         {\r
2263                                 qBlit(font[*first_ch++],pi->dst,cur_x,cur_y);\r
2264 //                              qBlit(font[*first_ch],pi->dst,cur_x,cur_y);\r
2265 //                              cur_x += ch_width(*first_ch++);\r
2266                         }\r
2267 #else\r
2268                         temp = *scan_ch;\r
2269                         *scan_ch = 0;\r
2270 \r
2271                         if ((justify_mode == jm_right)&&(!centering))\r
2272                         {\r
2273                                 unsigned width,height;\r
2274 \r
2275                                 VWL_MeasureString(first_ch,&width,&height,font);\r
2276                                 cur_x = xh-width;\r
2277                                 if (cur_x < xl)\r
2278                                         cur_x = xl;\r
2279                         }\r
2280 \r
2281                         px = cur_x;\r
2282                         py = cur_y;\r
2283 \r
2284                         length = scan_ch-first_ch+1;            // USL_DrawString only works with\r
2285                         if (length > MAX_PB)\r
2286                                 Quit("Presenter(): Print buffer string too long!");\r
2287                         _fmemcpy(pb,first_ch,length);    // near pointers...\r
2288 \r
2289                         if (*first_ch != '\n')\r
2290                                 USL_DrawString(pb);\r
2291 \r
2292                         *scan_ch = temp;\r
2293                         first_ch = scan_ch;\r
2294 #endif\r
2295                         cur_x = scan_x;\r
2296                         centering = false;\r
2297 \r
2298         // skip SPACES / RETURNS at end of line\r
2299         //\r
2300                         if ((*first_ch==' ') || (*first_ch==PI_RETURN_CHAR))\r
2301                                 first_ch++;\r
2302 \r
2303         // PI_CONTROL_CHARs don't advance to next character line\r
2304         //\r
2305                         if (*scan_ch != PI_CONTROL_CHAR)\r
2306                         {\r
2307                                 cur_x = xl;\r
2308                                 cur_y += font_height;\r
2309                         }\r
2310                 }\r
2311                 else\r
2312 //\r
2313 // HANDLE CONTROL CODES\r
2314 //\r
2315                 {\r
2316                         PresenterInfo endmsg;\r
2317                         pi_anim_info far *anim;\r
2318                         pi_shape_info far *shape_info;\r
2319                         unsigned shapenum;\r
2320                         short length;\r
2321                         char far *s;\r
2322 \r
2323                         if (first_ch[-1] == '\n')\r
2324                                 start_of_line = true;\r
2325 \r
2326                         first_ch++;\r
2327 #ifndef PI_CASE_SENSITIVE\r
2328                         *first_ch=toupper(*first_ch);\r
2329                         *(first_ch+1)=toupper(*(first_ch+1));\r
2330 #endif\r
2331                         switch (*((unsigned far *)first_ch)++)\r
2332                         {\r
2333                 // CENTER TEXT ------------------------------------------------------\r
2334                 //\r
2335                                 case PI_CNVT_CODE('C','E'):\r
2336                                         length = 0;\r
2337                                         s = first_ch;\r
2338                                         while (*s && (*s != PI_RETURN_CHAR))\r
2339                                         {\r
2340                                                 switch (*s)\r
2341                                                 {\r
2342                                                         case PI_CONTROL_CHAR:\r
2343                                                                 s++;\r
2344                                                                 switch (*((unsigned *)s)++)\r
2345                                                                 {\r
2346 #ifndef AMIGA\r
2347                                                                         case PI_CNVT_CODE('F','C'):\r
2348                                                                         case PI_CNVT_CODE('B','G'):\r
2349                                                                                 s++;\r
2350                                                                         break;\r
2351 #endif\r
2352 \r
2353                                                                         case PI_CNVT_CODE('L','M'):\r
2354                                                                         case PI_CNVT_CODE('R','M'):\r
2355                                                                         case PI_CNVT_CODE('S','H'):\r
2356                                                                         case PI_CNVT_CODE('P','X'):\r
2357                                                                         case PI_CNVT_CODE('P','Y'):\r
2358                                                                                 s += 3;\r
2359                                                                         break;\r
2360 \r
2361                                                                         case PI_CNVT_CODE('L','J'):\r
2362                                                                         case PI_CNVT_CODE('R','J'):\r
2363                                                                                 // No parameters to pass over!\r
2364                                                                         break;\r
2365                                                                 }\r
2366                                                         break;\r
2367 \r
2368                                                         default:\r
2369                                                                 length += ch_width(*s++);\r
2370                                                         break;\r
2371                                                 }\r
2372                                         }\r
2373                                         cur_x = ((xh-xl+1)-length)/2;\r
2374                                         centering = true;\r
2375                                 break;\r
2376 \r
2377                 // DRAW SHAPE -------------------------------------------------------\r
2378                 //\r
2379                                 case PI_CNVT_CODE('S','H'):\r
2380                                         shapenum = PI_VALUE(first_ch,3);\r
2381                                         first_ch += 3;\r
2382                                         shape_info = &pi_shape_table[shapenum];\r
2383                                         switch (shape_info->shape_type)\r
2384                                         {\r
2385                                                 short width;\r
2386 \r
2387                                                 case pis_pic2x:\r
2388                                                         cur_x = ((cur_x+2) + 7) & 0xFFF8;\r
2389                                                         width=BoxAroundPic(cur_x-2,cur_y-1,shape_info->shapenum,pi);\r
2390                                                         VW_DrawPic2x(cur_x>>3,cur_y,shape_info->shapenum);\r
2391                                                         cur_x += width;\r
2392                                                 break;\r
2393                                         }\r
2394                                 break;\r
2395 \r
2396                 // INIT ANIMATION ---------------------------------------------------\r
2397                 //\r
2398                                 case PI_CNVT_CODE('A','N'):\r
2399                                         shapenum = PI_VALUE(first_ch,2);\r
2400                                         first_ch += 2;\r
2401                                         _fmemcpy(&pi_anim_list[numanims],&pi_anim_table[shapenum],sizeof(pi_anim_info));\r
2402                                         anim = &pi_anim_list[numanims++];\r
2403                                         shape_info = &pi_shape_table[anim->baseshape+anim->frame];\r
2404                                         switch (shape_info->shape_type)\r
2405                                         {\r
2406                                                 short width;\r
2407 \r
2408                                                 case pis_pic2x:\r
2409                                                         cur_x = ((cur_x+2) + 7) & 0xFFF8;\r
2410                                                         width=BoxAroundPic(cur_x-2,cur_y-1,shape_info->shapenum,pi);\r
2411                                                         VW_DrawPic2x(cur_x>>3,cur_y,shape_info->shapenum);\r
2412                                                         anim->x = cur_x>>3;\r
2413                                                         anim->y = cur_y;\r
2414                                                         cur_x += width;\r
2415                                                 break;\r
2416                                         }\r
2417                                 break;\r
2418 \r
2419 #ifndef AMIGA\r
2420                 // FONT COLOR -------------------------------------------------------\r
2421                 //\r
2422                                 case PI_CNVT_CODE('F','C'):\r
2423                                         fontcolor = bgcolor ^ PI_VALUE(first_ch++,1);\r
2424                                 break;\r
2425 #endif\r
2426 \r
2427                 // BACKGROUND COLOR -------------------------------------------------\r
2428                 //\r
2429                                 case PI_CNVT_CODE('B','G'):\r
2430                                         bgcolor = PI_VALUE(first_ch++,1);\r
2431                                 break;\r
2432 \r
2433                 // LEFT MARGIN ------------------------------------------------------\r
2434                 //\r
2435                                 case PI_CNVT_CODE('L','M'):\r
2436                                         shapenum = PI_VALUE(first_ch,3);\r
2437                                         first_ch += 3;\r
2438                                         if (shapenum == 0xfff)\r
2439                                                 xl = cur_x;\r
2440                                         else\r
2441                                                 xl = shapenum;\r
2442                                 break;\r
2443 \r
2444                 // RIGHT MARGIN -----------------------------------------------------\r
2445                 //\r
2446                                 case PI_CNVT_CODE('R','M'):\r
2447                                         shapenum = PI_VALUE(first_ch,3);\r
2448                                         first_ch += 3;\r
2449                                         if (shapenum == 0xfff)\r
2450                                                 xh = cur_x;\r
2451                                         else\r
2452                                                 xh = shapenum;\r
2453                                 break;\r
2454 \r
2455                 // SET X COORDINATE -------------------------------------------------\r
2456                 //\r
2457                                 case PI_CNVT_CODE('P','X'):\r
2458                                         cur_x = PI_VALUE(first_ch,3);\r
2459                                         first_ch += 3;\r
2460                                 break;\r
2461 \r
2462                 // SET Y COORDINATE -------------------------------------------------\r
2463                 //\r
2464                                 case PI_CNVT_CODE('P','Y'):\r
2465                                         cur_y = PI_VALUE(first_ch,3);\r
2466                                         first_ch += 3;\r
2467                                 break;\r
2468 \r
2469                 // LEFT JUSTIFY -----------------------------------------------------\r
2470                 //\r
2471                                 case PI_CNVT_CODE('L','J'):\r
2472                                         justify_mode = jm_left;\r
2473                                 break;\r
2474 \r
2475                 // RIGHT JUSTIFY ----------------------------------------------------\r
2476                 //\r
2477                                 case PI_CNVT_CODE('R','J'):\r
2478                                         justify_mode = jm_right;\r
2479                                 break;\r
2480 \r
2481                 // END OF PAGE ------------------------------------------------------\r
2482                 //\r
2483                                 case PI_CNVT_CODE('E','P'):\r
2484                                         if (pi_recursing)\r
2485                                                 Quit("Presenter(): Can't use ^EP when recursing!");\r
2486 \r
2487                                         endmsg.xl = cur_x;\r
2488                                         endmsg.yl = yh-(font_height+2);\r
2489                                         endmsg.xh = xh;\r
2490                                         endmsg.yh = yh;\r
2491                                         endmsg.bgcolor = bgcolor;\r
2492                                         endmsg.ltcolor = pi->ltcolor;\r
2493                                         endmsg.dkcolor = pi->dkcolor;\r
2494                                         endmsg.script[0] = (char far *)"^CE^FC8-  ^FC0ESC ^FC8to return to play, or ^FC0ARROW KEYS ^FC8to page through more Help  -^XX";\r
2495 \r
2496                                         pi_recursing = true;\r
2497                                         Presenter(&endmsg);\r
2498                                         pi_recursing = false;\r
2499 \r
2500 #ifndef AMIGA\r
2501                                         if (screenfaded)\r
2502                                                 VW_FadeIn();\r
2503                                         VW_ColorBorder(8 | 56);\r
2504 #endif\r
2505 \r
2506                                         while (1)\r
2507                                         {\r
2508 #ifndef AMIGA\r
2509                                                 long newtime;\r
2510 \r
2511                                                 VW_WaitVBL(1);\r
2512                                                 newtime = TimeCount;\r
2513                                                 realtics = tics = newtime-lasttimecount;\r
2514                                                 lasttimecount = newtime;\r
2515 #else\r
2516                                                 WaitVBL(1);\r
2517                                                 CALC_TICS;\r
2518 #endif\r
2519                                                 AnimatePage(numanims);\r
2520                                                 IN_ReadControl(0,&control);\r
2521 \r
2522                                                 if (control.button1 || Keyboard[1])\r
2523                                                 {\r
2524                                                         presenting=false;\r
2525                                                         break;\r
2526                                                 }\r
2527                                                 else\r
2528                                                 {\r
2529                                                         if (ControlTypeUsed != ctrl_Keyboard)\r
2530                                                                 control.dir = dir_None;\r
2531 \r
2532                                                         if (((control.dir == dir_North) || (control.dir == dir_West)) && (PageNum))\r
2533                                                         {\r
2534                                                                 if (up_released)\r
2535                                                                 {\r
2536                                                                         PageNum--;\r
2537                                                                         up_released = false;\r
2538                                                                         break;\r
2539                                                                 }\r
2540                                                         }\r
2541                                                         else\r
2542                                                         {\r
2543                                                                 up_released = true;\r
2544                                                                 if (((control.dir == dir_South) || (control.dir == dir_East)) && (PageNum < pi->numpages-1))\r
2545                                                                 {\r
2546                                                                         if (dn_released)\r
2547                                                                         {\r
2548                                                                                 PageNum++;\r
2549                                                                                 dn_released = false;\r
2550                                                                                 break;\r
2551                                                                         }\r
2552                                                                 }\r
2553                                                                 else\r
2554                                                                         dn_released = true;\r
2555                                                         }\r
2556                                                 }\r
2557                                         }\r
2558 \r
2559                                         cur_x = xl;\r
2560                                         cur_y = yl;\r
2561                                         if (cur_y+font_height > yh)\r
2562                                                 cur_y = yh-font_height;\r
2563                                         first_ch = pi->script[PageNum];\r
2564 \r
2565                                         numanims = 0;\r
2566                                         PurgeAllGfx();\r
2567                                         CachePage(first_ch);\r
2568 \r
2569                                         VW_Bar(xl,yl,xh-xl+1,yh-yl+1,bgcolor);\r
2570                                 break;\r
2571 \r
2572                 // EXIT PRESENTER ---------------------------------------------------\r
2573                 //\r
2574                                 case PI_CNVT_CODE('X','X'):\r
2575                                         presenting=false;\r
2576                                 break;\r
2577                         }\r
2578 \r
2579                         if ((first_ch[0] == ' ') && (first_ch[1] == '\n') && start_of_line)\r
2580                                 first_ch += 2;\r
2581                 }\r
2582         }\r
2583 }\r
2584 \r
2585 //--------------------------------------------------------------------------\r
2586 // ResetAnims()\r
2587 //--------------------------------------------------------------------------\r
2588 void ResetAnims()\r
2589 {\r
2590         pi_anim_list[0].baseshape = -1;\r
2591 }\r
2592 \r
2593 //--------------------------------------------------------------------------\r
2594 // AnimatePage()\r
2595 //--------------------------------------------------------------------------\r
2596 void AnimatePage(short numanims)\r
2597 {\r
2598         pi_anim_info far *anim=pi_anim_list;\r
2599         pi_shape_info far *shape_info;\r
2600 \r
2601         while (numanims--)\r
2602         {\r
2603                 anim->delay += tics;\r
2604                 if (anim->delay >= anim->maxdelay)\r
2605                 {\r
2606                         anim->delay = 0;\r
2607                         anim->frame++;\r
2608                         if (anim->frame == anim->maxframes)\r
2609                                 anim->frame = 0;\r
2610 \r
2611 #if ANIM_USES_SHAPETABLE\r
2612                         shape_info = &pi_shape_table[anim->baseshape+anim->frame];\r
2613 #else\r
2614                         shape_info = &pi_shape_table[anim->baseshape];\r
2615 #endif\r
2616                         switch (shape_info->shape_type)\r
2617                         {\r
2618                                 case pis_pic2x:\r
2619 #if ANIM_USES_SHAPETABLE\r
2620                                         VW_DrawPic2x(anim->x,anim->y,shape_info->shapenum);\r
2621 #else\r
2622                                         VW_DrawPic2x(anim->x,anim->y,shape_info->shapenum+anim->frame);\r
2623 #endif\r
2624                                 break;\r
2625                         }\r
2626                 }\r
2627                 anim++;\r
2628         }\r
2629 }\r
2630 \r
2631 //--------------------------------------------------------------------------\r
2632 // BoxAroundPic()\r
2633 //--------------------------------------------------------------------------\r
2634 short BoxAroundPic(short x1, short y1, unsigned picnum, PresenterInfo *pi)\r
2635 {\r
2636         short x2,y2;\r
2637 \r
2638         x2 = x1+(pictable[picnum-STARTPICS].width<<4)+2;\r
2639         y2 = y1+(pictable[picnum-STARTPICS].height)+1;\r
2640         VWB_Hlin(x1,x2,y1,pi->ltcolor);\r
2641         VWB_Hlin(x1,x2,y2,pi->dkcolor);\r
2642         VWB_Vlin(y1,y2,x1,pi->ltcolor);\r
2643         VWB_Vlin(y1,y2,x1+1,pi->ltcolor);\r
2644         VWB_Vlin(y1,y2,x2,pi->dkcolor);\r
2645         VWB_Vlin(y1,y2,x2+1,pi->dkcolor);\r
2646 \r
2647         return(x2-x1+1);\r
2648 }\r
2649 \r
2650 //--------------------------------------------------------------------------\r
2651 // PurgeAllGfx()\r
2652 //--------------------------------------------------------------------------\r
2653 void PurgeAllGfx()\r
2654 {\r
2655         ResetAnims();\r
2656         FreeUpMemory();\r
2657 }\r
2658 \r
2659 //--------------------------------------------------------------------------\r
2660 // CachePage()\r
2661 //--------------------------------------------------------------------------\r
2662 void CachePage(char far *script)\r
2663 {\r
2664         pi_anim_info far *anim;\r
2665         short loop;\r
2666         unsigned shapenum;\r
2667         boolean end_of_page=false;\r
2668         short numanims=0;\r
2669 \r
2670         while (!end_of_page)\r
2671         {\r
2672                 switch (*script++)\r
2673                 {\r
2674                         case PI_CONTROL_CHAR:\r
2675 #ifndef PI_CASE_SENSITIVE\r
2676                                 *script=toupper(*script);\r
2677                                 *(script+1)=toupper(*(script+1));\r
2678 #endif\r
2679                                 switch (*((unsigned far *)script)++)\r
2680                                 {\r
2681                                         case PI_CNVT_CODE('S','H'):\r
2682                                                 shapenum = PI_VALUE(script,3);\r
2683                                                 script += 3;\r
2684                                                 CA_MarkGrChunk(pi_shape_table[shapenum].shapenum);\r
2685                                         break;\r
2686 \r
2687                                         case PI_CNVT_CODE('A','N'):\r
2688                                                 shapenum = PI_VALUE(script,2);\r
2689                                                 script += 2;\r
2690 \r
2691                                                 if (numanims++ == PI_MAX_ANIMS)\r
2692                                                         Quit("CachePage(): Too many anims on one page.");\r
2693 \r
2694                                                 anim = &pi_anim_table[shapenum];\r
2695 #if ANIM_USES_SHAPETABLE\r
2696                                                 for (loop=anim->baseshape;loop < anim->baseshape+anim->maxframes; loop++)\r
2697                                                         CA_MarkGrChunk(pi_shape_table[loop].shapenum);\r
2698 #else\r
2699                                                 shapenum = pi_shape_table[anim->baseshape].shapenum;\r
2700                                                 for (loop=0; loop<anim->maxframes; loop++)\r
2701                                                         CA_MarkGrChunk(shapenum+loop);\r
2702 #endif\r
2703                                         break;\r
2704 \r
2705                                         case PI_CNVT_CODE('X','X'):\r
2706                                         case PI_CNVT_CODE('E','P'):\r
2707                                                 end_of_page = true;\r
2708                                         break;\r
2709                                 }\r
2710                         break;\r
2711                 }\r
2712         }\r
2713 \r
2714         CA_CacheMarks(NULL);\r
2715 }\r
2716 \r
2717 //--------------------------------------------------------------------------\r
2718 // PI_VALUE()\r
2719 //--------------------------------------------------------------------------\r
2720 unsigned PI_VALUE(char far *ptr,char num_nybbles)\r
2721 {\r
2722         char ch,nybble,shift;\r
2723         unsigned value=0;\r
2724 \r
2725         for (nybble=0; nybble<num_nybbles; nybble++)\r
2726         {\r
2727                 shift = 4*(num_nybbles-nybble-1);\r
2728 \r
2729                 ch = *ptr++;\r
2730                 if (isxdigit(ch))\r
2731                         if (isalpha(ch))\r
2732                                 value |= (toupper(ch)-'A'+10)<<shift;\r
2733                         else\r
2734                                 value |= (ch-'0')<<shift;\r
2735         }\r
2736 \r
2737         return(value);\r
2738 }\r
2739 \r
2740 //--------------------------------------------------------------------------\r
2741 // LoadPresenterScript()\r
2742 //--------------------------------------------------------------------------\r
2743 long LoadPresenterScript(char *filename,PresenterInfo *pi)\r
2744 {\r
2745 #pragma warn -pia\r
2746         long size;\r
2747 \r
2748         if (!(size=BLoad(filename,&pi->scriptstart)))\r
2749                 return(0);\r
2750         pi->script[0] = MK_FP(pi->scriptstart,0);\r
2751         pi->script[0][size-1] = 0;                                      // Last byte is trashed!\r
2752         InitPresenterScript(pi);\r
2753 \r
2754         return(size);\r
2755 #pragma warn +pia\r
2756 }\r
2757 \r
2758 //-------------------------------------------------------------------------\r
2759 // FreePresenterScript()\r
2760 //-------------------------------------------------------------------------\r
2761 void FreePresenterScript(PresenterInfo *pi)\r
2762 {\r
2763         if (pi->script)\r
2764                 MM_FreePtr(&pi->scriptstart);\r
2765 }\r
2766 \r
2767 //-------------------------------------------------------------------------\r
2768 // InitPresenterScript()\r
2769 //-------------------------------------------------------------------------\r
2770 void InitPresenterScript(PresenterInfo *pi)\r
2771 {\r
2772         char far *script = pi->script[0];\r
2773 \r
2774         pi->numpages = 1;               // Assume at least 1 page\r
2775         while (*script)\r
2776         {\r
2777                 switch (*script++)\r
2778                 {\r
2779                         case PI_CONTROL_CHAR:\r
2780 #ifndef PI_CASE_SENSITIVE\r
2781                                 *script=toupper(*script);\r
2782                                 *(script+1)=toupper(*(script+1));\r
2783 #endif\r
2784                                 switch (*((unsigned far *)script)++)\r
2785                                 {\r
2786                                         case PI_CNVT_CODE('E','P'):\r
2787                                                 if (pi->numpages < PI_MAX_PAGES)\r
2788                                                         pi->script[pi->numpages++] = script;\r
2789                                                 else\r
2790                                                         TrashProg("GE ERROR: Too many Presenter() pages. --> %d",pi->numpages);\r
2791                                         break;\r
2792                                 }\r
2793                         break;\r
2794 \r
2795                         case '\r':\r
2796                                 if (*script == '\n')\r
2797                                 {\r
2798                                         *(script-1) = ' ';\r
2799                                         script++;\r
2800                                 }\r
2801                         break;\r
2802                 }\r
2803         }\r
2804 \r
2805         pi->numpages--; // Last page defined is not a real page.\r
2806 }\r
2807 #endif\r
2808 \r
2809 \r
2810 //-------------------------------------------------------------------------\r
2811 // AnimateWallList()\r
2812 //-------------------------------------------------------------------------\r
2813 void AnimateWallList(void)\r
2814 {\r
2815         walltype *wall, *check;\r
2816         unsigned i;\r
2817         int tile,org_tile;\r
2818 \r
2819         if (wall_anim_delay>0)\r
2820         {\r
2821                 wall_anim_delay-=realtics;\r
2822                 return;\r
2823         }\r
2824 \r
2825         //\r
2826         // Re-Init our counter...\r
2827         //\r
2828 \r
2829         wall_anim_delay = wall_anim_time;\r
2830 \r
2831         //\r
2832         // Clear all previous flags marking animation being DONE.\r
2833         //\r
2834 \r
2835         for (i=0;i<NUMFLOORS;i++)\r
2836                 TILE_FLAGS(i) &= ~tf_MARKED;\r
2837 \r
2838 \r
2839         //\r
2840         // Run though wall list updating only then needed animations\r
2841         //\r
2842 \r
2843         for (wall=&walls[1];wall<rightwall;wall++)\r
2844         {\r
2845                 org_tile = tile = wall->color + wall_anim_pos[wall->color];\r
2846 \r
2847                 if (ANIM_FLAGS(tile))\r
2848                 {\r
2849                         do\r
2850                         {\r
2851                                 if (!(TILE_FLAGS(tile) & tf_MARKED))\r
2852                                 {\r
2853                                         //\r
2854                                         // update our offset table (0-NUMANIMS)\r
2855                                         //\r
2856 \r
2857                                         wall_anim_pos[tile] += (char signed)ANIM_FLAGS(tile+(char signed)wall_anim_pos[tile]);\r
2858 \r
2859                                         //\r
2860                                         // Mark tile as being already updated..\r
2861                                         //\r
2862 \r
2863                                         TILE_FLAGS(tile) |= tf_MARKED;\r
2864                                 }\r
2865 \r
2866                                 //\r
2867                                 // Check rest of tiles in this animation string...\r
2868                                 //\r
2869 \r
2870                                 tile += (char signed)ANIM_FLAGS(tile);\r
2871 \r
2872                         } while (tile != org_tile);\r
2873                 }\r
2874         }\r
2875 }\r
2876 \r