OSDN Git Service

extrcted keen code remake
[proj16/16.git] / 16 / keen456 / KEEN4-6 / ID_US_2.C
1 /* Reconstructed Commander Keen 4-6 Source Code\r
2  * Copyright (C) 2021 K1n9_Duk3\r
3  *\r
4  * This file is primarily based on:\r
5  * Catacomb 3-D Source Code\r
6  * Copyright (C) 1993-2014 Flat Rock Software\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License along\r
19  * with this program; if not, write to the Free Software Foundation, Inc.,\r
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
21  */\r
22 \r
23 //\r
24 //      ID Engine\r
25 //      ID_US.c - User Manager - User interface\r
26 //      v1.1d1\r
27 //      By Jason Blochowiak\r
28 //      Hacked up for Catacomb 3D\r
29 //\r
30 \r
31 #include "ID_HEADS.H"\r
32 #pragma hdrstop\r
33 \r
34 #pragma warn    -pia\r
35 \r
36 //      Special imports\r
37 extern  boolean         showscorebox;\r
38 #ifdef  KEEN\r
39 extern  boolean         jerk;\r
40 extern  boolean         oldshooting;\r
41 extern  ScanCode        firescan;\r
42 void    USL_CheckSavedGames(void);\r
43 #else\r
44                 ScanCode        firescan;\r
45 #endif\r
46 \r
47 //      Global variables\r
48                 boolean         ingame,abortgame,loadedgame;\r
49                 GameDiff        restartgame = gd_Continue;\r
50 \r
51 //      Internal variables\r
52 static  boolean         GameIsDirty,\r
53                                         QuitToDos,\r
54                                         CtlPanelDone;\r
55 \r
56 #ifdef KEEN6\r
57         int             listindex = -1;\r
58         boolean         checkpassed;\r
59 #endif\r
60 \r
61 //      Forward reference prototypes\r
62 static void     USL_SetupCard(void);\r
63 \r
64 //      Control panel data\r
65 \r
66 #define CtlPanelSX      74\r
67 #define CtlPanelSY      48\r
68 #define CtlPanelEX      234\r
69 #define CtlPanelEY      150\r
70 #define CtlPanelW       (CtlPanelEX - CtlPanelSX)\r
71 #define CtlPanelH       (CtlPanelEY - CtlPanelSY)\r
72 \r
73 #ifdef KEEN\r
74 \r
75 #define TileBase        92\r
76 \r
77 #if GRMODE == CGAGR\r
78 \r
79 #define BackColor               0\r
80 #define HiliteColor             (BackColor ^ 3)\r
81 #define NohiliteColor   (BackColor ^ 2)\r
82 \r
83 #else\r
84 \r
85 #define BackColor               8\r
86 #define HiliteColor             (BackColor ^ 10)\r
87 #define NohiliteColor   (BackColor ^ 2)\r
88 \r
89 #endif  // if GRMODE == CGAGR ... else ...\r
90 \r
91 #else   // ifdef KEEN\r
92 \r
93 #define TileBase        92\r
94 \r
95 // DEBUG - CGA\r
96 #define BackColor               0\r
97 #define HiliteColor             (BackColor ^ 12)\r
98 #define NohiliteColor   (BackColor ^ 4)\r
99 \r
100 #endif\r
101 \r
102 typedef enum\r
103                 {\r
104                         uc_None,\r
105                         uc_Return,\r
106                         uc_Abort,\r
107                         uc_Quit,\r
108                         uc_Loaded,\r
109                         uc_SEasy,\r
110                         uc_SNormal,\r
111                         uc_SHard,\r
112                 } UComm;\r
113 typedef enum\r
114                 {\r
115                         uii_Bad,\r
116                         uii_Button,uii_RadioButton,uii_Folder\r
117                 } UIType;\r
118 typedef enum\r
119                 {\r
120                         ui_Normal = 0,\r
121                         ui_Pushed = 1,\r
122                         ui_Selected = 2,\r
123                         ui_Disabled = 4,\r
124                         ui_Separated = 8\r
125                 } UIFlags;\r
126 #define UISelectFlags (ui_Pushed | ui_Selected | ui_Disabled)\r
127 \r
128 typedef enum\r
129                 {\r
130                         uic_SetupCard,uic_DrawCard,uic_TouchupCard,\r
131                         uic_DrawIcon,uic_Draw,uic_Hit\r
132                 } UserCall;\r
133 \r
134 typedef struct  UserItem\r
135                 {\r
136                                 UIType                  type;\r
137                                 UIFlags                 flags;\r
138                                 ScanCode                hotkey;\r
139                                 char                    *text;\r
140                                 UComm                   comm;\r
141                                 void                    far *child;     // Should be (UserItemGroup *)\r
142 \r
143                                 word                    x,y;\r
144                 } UserItem;\r
145 typedef struct  UserItemGroup\r
146                 {\r
147                                 word                    x,y;\r
148                                 graphicnums             title;\r
149                                 ScanCode                hotkey;\r
150                                 UserItem                far *items;\r
151                                 boolean                 (*custom)(UserCall,struct UserItem far *);      // Custom routine\r
152 \r
153                                 word                    cursor;\r
154                 struct  UserItemGroup   far *parent;\r
155                 } UserItemGroup;\r
156 \r
157 static  char            *BottomS1,*BottomS2,*BottomS3;\r
158 static  UComm           Communication;\r
159 static  ScanCode        *KeyMaps[] =\r
160                                         {\r
161                                                 &KbdDefs[0].button0,\r
162                                                 &KbdDefs[0].button1,\r
163                                                 &firescan,\r
164                                                 &KbdDefs[0].upleft,\r
165                                                 &KbdDefs[0].up,\r
166                                                 &KbdDefs[0].upright,\r
167                                                 &KbdDefs[0].right,\r
168                                                 &KbdDefs[0].downright,\r
169                                                 &KbdDefs[0].down,\r
170                                                 &KbdDefs[0].downleft,\r
171                                                 &KbdDefs[0].left\r
172                                         };\r
173 \r
174 // Custom routine prototypes\r
175 static  boolean USL_ConfigCustom(UserCall call,struct UserItem far *item),\r
176                                 USL_KeyCustom(UserCall call,struct UserItem far *item),\r
177                                 USL_KeySCustom(UserCall call,struct UserItem far *item),\r
178                                 USL_Joy1Custom(UserCall call,struct UserItem far *item),\r
179                                 USL_Joy2Custom(UserCall call,struct UserItem far *item),\r
180                                 USL_JoyGCustom(UserCall call,struct UserItem far *item),\r
181                                 USL_LoadCustom(UserCall call,struct UserItem far *item),\r
182                                 USL_SaveCustom(UserCall call,struct UserItem far *item),\r
183                                 USL_ScoreCustom(UserCall call,struct UserItem far *item),\r
184                                 USL_CompCustom(UserCall call,struct UserItem far *item),\r
185                                 USL_SmoothCustom(UserCall call,struct UserItem far *item),\r
186 #ifdef KEEN\r
187                                 USL_TwoCustom(UserCall call,struct UserItem far *item),\r
188 #endif\r
189                                 USL_PongCustom(UserCall call,struct UserItem far *item);\r
190 \r
191 #define DefButton(key,text)                             uii_Button,ui_Normal,key,text\r
192 #define DefRButton(key,text)                    uii_RadioButton,ui_Normal,key,text\r
193 #define DefFolder(key,text,child)               uii_Folder,ui_Normal,key,text,uc_None,child\r
194 #define CustomGroup(title,key,custom)   0,0,title,key,0,custom\r
195         UserItem far holder[] =\r
196         {\r
197                 {DefButton(sc_None,"DEBUG")},\r
198                 {uii_Bad}\r
199         };\r
200         UserItemGroup   far holdergroup = {0,0,CP_MAINMENUPIC,sc_None,holder};\r
201 \r
202         // Sound menu\r
203         UserItem far soundi[] =\r
204         {\r
205                 {DefRButton(sc_N,"NO SOUND EFFECTS")},\r
206                 {DefRButton(sc_P,"PC SPEAKER")},\r
207                 {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
208                 {DefRButton(sc_Q,"QUIET ADLIB/SOUNDBLASTER")},\r
209                 {uii_Bad}\r
210         };\r
211         UserItemGroup   far soundgroup = {8,0,CP_SOUNDMENUPIC,sc_None,soundi};\r
212 \r
213         // Music menu\r
214         UserItem far musici[] =\r
215         {\r
216                 {DefRButton(sc_N,"NO MUSIC")},\r
217                 {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
218                 {uii_Bad}\r
219         };\r
220         UserItemGroup   far musicgroup = {8,0,CP_MUSICMENUPIC,sc_None,musici};\r
221 \r
222         // New game menu\r
223         UserItem far newgamei[] =\r
224         {\r
225                 {DefButton(sc_E,"BEGIN EASY GAME"),uc_SEasy},\r
226                 {DefButton(sc_N,"BEGIN NORMAL GAME"),uc_SNormal},\r
227                 {DefButton(sc_H,"BEGIN HARD GAME"),uc_SHard},\r
228                 {uii_Bad}\r
229         };\r
230         UserItemGroup   far newgamegroup = {8,0,CP_NEWGAMEMENUPIC,sc_None,newgamei,0,1};\r
231 \r
232         // Load/Save game menu\r
233         UserItem far loadsavegamei[] =\r
234         {\r
235 #ifdef CAT3D\r
236                 {uii_Button,ui_Normal,sc_None},\r
237                 {uii_Button,ui_Normal,sc_None},\r
238                 {uii_Button,ui_Normal,sc_None},\r
239                 {uii_Button,ui_Normal,sc_None},\r
240                 {uii_Button,ui_Normal,sc_None},\r
241                 {uii_Button,ui_Normal,sc_None},\r
242 #else\r
243                 {uii_Button,ui_Normal,sc_1},\r
244                 {uii_Button,ui_Normal,sc_2},\r
245                 {uii_Button,ui_Normal,sc_3},\r
246                 {uii_Button,ui_Normal,sc_4},\r
247                 {uii_Button,ui_Normal,sc_5},\r
248                 {uii_Button,ui_Normal,sc_6},\r
249 #endif\r
250                 {uii_Bad}\r
251         };\r
252         UserItemGroup   far loadgamegroup = {4,3,CP_LOADMENUPIC,sc_None,loadsavegamei,USL_LoadCustom};\r
253         UserItemGroup   far savegamegroup = {4,3,CP_SAVEMENUPIC,sc_None,loadsavegamei,USL_SaveCustom};\r
254 \r
255         // Options menu\r
256         UserItemGroup   far scoregroup = {0,0,0,sc_None,0,USL_ScoreCustom};\r
257 #ifdef KEEN\r
258         UserItemGroup   far twogroup = {0,0,0,sc_None,0,USL_TwoCustom};\r
259 #endif\r
260 #if GRMODE != CGAGR\r
261         UserItemGroup   far smoothgroup = {0,0,0,sc_None,0,USL_SmoothCustom};\r
262         UserItemGroup   far compgroup = {0,0,0,sc_None,0,USL_CompCustom};\r
263 #endif\r
264 \r
265         UserItem far optionsi[] =\r
266         {\r
267                 {DefFolder(sc_S,"",&scoregroup)},\r
268 #ifdef KEEN\r
269                 {DefFolder(sc_T,"",&twogroup)},\r
270 #endif\r
271 #if GRMODE != CGAGR\r
272                 {DefFolder(sc_M,"",&smoothgroup)},\r
273                 {DefFolder(sc_C,"",&compgroup)},\r
274 #endif\r
275                 {uii_Bad}\r
276         };\r
277         UserItemGroup   far optionsgroup = {8,0,CP_OPTIONSMENUPIC,sc_None,optionsi};\r
278 \r
279         // Keyboard menu\r
280         UserItem far keyi[] =\r
281         {\r
282                 {DefButton(sc_None,"UP & LEFT")},\r
283                 {DefButton(sc_None,"UP")},\r
284                 {DefButton(sc_None,"UP & RIGHT")},\r
285                 {DefButton(sc_None,"RIGHT")},\r
286                 {DefButton(sc_None,"DOWN & RIGHT")},\r
287                 {DefButton(sc_None,"DOWN")},\r
288                 {DefButton(sc_None,"DOWN & LEFT")},\r
289                 {DefButton(sc_None,"LEFT")},\r
290                 {uii_Bad}\r
291         };\r
292         UserItemGroup   far keygroup = {0,0,CP_KEYMOVEMENTPIC,sc_None,keyi,USL_KeyCustom};\r
293         UserItem far keybi[] =\r
294         {\r
295 #ifdef  KEEN\r
296                 {DefButton(sc_J,"JUMP")},\r
297                 {DefButton(sc_P,"POGO")},\r
298                 {DefButton(sc_F,"FIRE")},\r
299 #endif\r
300 #ifdef  CAT3D\r
301                 {DefButton(sc_J,"FIRE")},\r
302                 {DefButton(sc_P,"STRAFE")},\r
303 #endif\r
304 #ifdef  CPD\r
305                 {DefButton(sc_J,"SHOOT")},\r
306                 {DefButton(sc_P,"BOMB")},\r
307 #endif\r
308                 {uii_Bad}\r
309         };\r
310         UserItemGroup   far keybgroup = {0,0,CP_KEYBUTTONPIC,sc_None,keybi,USL_KeyCustom};\r
311         UserItem far keysi[] =\r
312         {\r
313                 {DefFolder(sc_M,"MOVEMENT",&keygroup)},\r
314                 {DefFolder(sc_B,"BUTTONS",&keybgroup)},\r
315                 {uii_Bad}\r
316         };\r
317         UserItemGroup   far keysgroup = {8,0,CP_KEYBOARDMENUPIC,sc_None,keysi,USL_KeySCustom};\r
318 \r
319         // Joystick #1 & #2\r
320         UserItemGroup   far joy1group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy1Custom)};\r
321         UserItemGroup   far joy2group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy2Custom)};\r
322         UserItemGroup   far gravisgroup = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_JoyGCustom)};\r
323 \r
324         // Config menu\r
325         UserItem far configi[] =\r
326         {\r
327                 {DefFolder(sc_S,"SOUND",&soundgroup)},\r
328                 {DefFolder(sc_M,"MUSIC",&musicgroup)},\r
329 #ifndef CAT3D\r
330                 {DefFolder(sc_O,"OPTIONS",&optionsgroup)},\r
331 #endif\r
332                 {uii_Folder,ui_Separated,sc_K,"USE KEYBOARD",uc_None,&keysgroup},\r
333                 {DefFolder(sc_1,"USE JOYSTICK #1",&joy1group)},\r
334                 {DefFolder(sc_2,"USE JOYSTICK #2",&joy2group)},\r
335                 {DefFolder(sc_G,"",&gravisgroup)},\r
336                 {uii_Bad}\r
337         };\r
338 #ifdef CAT3D\r
339         UserItemGroup   far configgroup = {8,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
340 #else\r
341         UserItemGroup   far configgroup = {0,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
342 #endif\r
343 \r
344         // Main menu\r
345         UserItemGroup   far ponggroup = {0,0,0,sc_None,0,USL_PongCustom};\r
346         UserItem far rooti[] =\r
347         {\r
348                 {DefFolder(sc_N,"NEW GAME",&newgamegroup)},\r
349                 {DefFolder(sc_L,"LOAD GAME",&loadgamegroup)},\r
350                 {DefFolder(sc_S,"SAVE GAME",&savegamegroup)},\r
351                 {DefFolder(sc_C,"CONFIGURE",&configgroup)},\r
352                 {DefButton(sc_R,nil),uc_Return},        // Return to Game/Demo\r
353                 {DefButton(sc_E,"END GAME"),uc_Abort},\r
354 #ifdef KEEN\r
355                 {DefFolder(sc_P,"PADDLE WAR",&ponggroup)},\r
356 #elif defined CAT3D\r
357                 {DefFolder(sc_B,"SKULL 'N' BONES",&ponggroup)},\r
358 #endif\r
359                 {DefButton(sc_Q,"QUIT"),uc_Quit},\r
360                 {uii_Bad}\r
361         };\r
362         UserItemGroup   far rootgroup = {32,4,CP_MAINMENUPIC,sc_None,rooti};\r
363 #undef  DefButton\r
364 #undef  DefFolder\r
365 \r
366 #define MaxCards        7\r
367         word                    cstackptr;\r
368         UserItemGroup   far *cardstack[MaxCards],\r
369                                         far *topcard;\r
370 \r
371 //      Card stack code\r
372 static void\r
373 USL_SetupStack(void)\r
374 {\r
375         cstackptr = 0;\r
376         cardstack[0] = topcard = &rootgroup;\r
377 }\r
378 \r
379 static void\r
380 USL_PopCard(void)\r
381 {\r
382         if (!cstackptr)\r
383                 return;\r
384 \r
385         topcard = cardstack[--cstackptr];\r
386 }\r
387 \r
388 static void\r
389 USL_PushCard(UserItemGroup far *card)\r
390 {\r
391         if (cstackptr == MaxCards - 1)\r
392                 return;\r
393 \r
394         topcard = cardstack[++cstackptr] = card;\r
395 }\r
396 \r
397 static void\r
398 USL_DrawItemIcon(UserItem far *item)\r
399 {\r
400         word    flags,tile;\r
401 \r
402         if (topcard->custom && topcard->custom(uic_DrawIcon,item))\r
403                 return;\r
404 \r
405         flags = item->flags;\r
406         if (flags & ui_Disabled)\r
407                 tile = TileBase + ((flags & ui_Selected)? 5 : 4);\r
408         else if ((item->type == uii_RadioButton) && (!(flags & ui_Pushed)))\r
409                 tile = TileBase + ((flags & ui_Selected)? 3 : 2);\r
410         else\r
411                 tile = TileBase + ((flags & ui_Selected)? 1 : 0);\r
412         VWB_DrawTile8(item->x,item->y,tile);\r
413 }\r
414 \r
415 static void\r
416 USL_DrawItem(UserItem far *item)\r
417 {\r
418         if (topcard->custom && topcard->custom(uic_Draw,item))\r
419                 return;\r
420 \r
421         VWB_Bar(CtlPanelSX + 1,item->y,\r
422                         CtlPanelEX - CtlPanelSX - 1,8,BackColor);       // Clear out background\r
423         USL_DrawItemIcon(item);\r
424         if ((item->flags & ui_Selected) && !(item->flags & ui_Disabled))\r
425                 fontcolor = HiliteColor;\r
426         else\r
427                 fontcolor = NohiliteColor;\r
428         px = item->x + 8;\r
429         py = item->y + 1;\r
430         USL_DrawString(item->text);\r
431         fontcolor = F_BLACK;\r
432 }\r
433 \r
434 #ifdef KEEN\r
435 #if GRMODE == CGAGR\r
436 #define MyLine(y)       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,3);\r
437 #else\r
438 #define MyLine(y)       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,10);\r
439 #endif\r
440 #else\r
441 #define MyLine(y)       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,12);\r
442 #endif\r
443 \r
444 static void\r
445 USL_DrawBottom(void)\r
446 {\r
447         word    w,h;\r
448 \r
449         fontcolor = NohiliteColor;\r
450 \r
451         px = CtlPanelSX + 4;\r
452         py = CtlPanelEY - 15;\r
453         USL_DrawString(BottomS1);\r
454 \r
455         USL_MeasureString(BottomS2,&w,&h);\r
456         px = CtlPanelEX - 4 - w;\r
457         USL_DrawString(BottomS2);\r
458 \r
459         USL_MeasureString(BottomS3,&w,&h);\r
460         px = CtlPanelSX + ((CtlPanelEX - CtlPanelSX - w) / 2);\r
461         py += h + 1;\r
462         USL_DrawString(BottomS3);\r
463 \r
464         fontcolor = F_WHITE;\r
465         MyLine(CtlPanelEY - 17);\r
466 }\r
467 \r
468 static void\r
469 USL_DrawCtlPanelContents(void)\r
470 {\r
471         int                             x,y;\r
472         UserItem                far *item;\r
473 \r
474         if (topcard->custom && topcard->custom(uic_DrawCard,nil))\r
475                 return;\r
476 \r
477         if (topcard->title)\r
478         {\r
479                 // Draw the title\r
480                 MyLine(CtlPanelSY + 7);\r
481                 VWB_DrawPic(CtlPanelSX + 6,CtlPanelSY,topcard->title);\r
482         }\r
483 \r
484         USL_DrawBottom();\r
485 \r
486         if (!topcard->items)\r
487                 return;\r
488 \r
489         x = topcard->x + CtlPanelSX;\r
490         if (x % 8)\r
491                 x += 8 - (x % 8);\r
492         y = topcard->y + CtlPanelSY + 12;\r
493         for (item = topcard->items;item->type != uii_Bad;item++)\r
494         {\r
495                 if (item->flags & ui_Separated)\r
496                         y += 8;\r
497 \r
498                 item->x = x;\r
499                 item->y = y;\r
500                 USL_DrawItem(item);\r
501                 y += 8;\r
502         }\r
503         if (topcard->custom)\r
504                 topcard->custom(uic_TouchupCard,nil);\r
505 }\r
506 \r
507 static void\r
508 USL_DrawCtlPanel(void)\r
509 {\r
510         if (topcard->items || topcard->title)\r
511         {\r
512                 // Draw the backdrop\r
513                 VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
514 \r
515                 // Draw the contents\r
516                 USL_DrawCtlPanelContents();\r
517         }\r
518 \r
519         // Refresh the screen\r
520         VW_UpdateScreen();\r
521 }\r
522 \r
523 static void\r
524 USL_DialogSetup(word w,word h,word *x,word *y)\r
525 {\r
526         VWB_DrawMPic(CtlPanelSX,CtlPanelSY,CP_MENUMASKPICM);\r
527 \r
528         *x = CtlPanelSX + ((CtlPanelW - w) / 2);\r
529         *y = CtlPanelSY + ((CtlPanelH - h) / 2);\r
530         VWB_Bar(*x,*y,w + 1,h + 1,BackColor);\r
531         VWB_Hlin(*x - 1,*x + w + 1,*y - 1,NohiliteColor);\r
532         VWB_Hlin(*x - 1,*x + w + 1,*y + h + 1,NohiliteColor);\r
533         VWB_Vlin(*y - 1,*y + h + 1,*x - 1,NohiliteColor);\r
534         VWB_Vlin(*y - 1,*y + h + 1,*x + w + 1,NohiliteColor);\r
535 }\r
536 \r
537 static void\r
538 USL_ShowLoadSave(char *s,char *name)\r
539 {\r
540         word    x,y,\r
541                         w,h,\r
542                         tw,sw;\r
543         char    msg[MaxGameName + 4];\r
544 \r
545         strcpy(msg,"'");\r
546         strcat(msg,name);\r
547         strcat(msg,"'");\r
548         USL_MeasureString(s,&sw,&h);\r
549         USL_MeasureString(msg,&w,&h);\r
550         tw = ((sw > w)? sw : w) + 6;\r
551         USL_DialogSetup(tw,(h * 2) + 2,&x,&y);\r
552         py = y + 2;\r
553         px = x + ((tw - sw) / 2);\r
554         USL_DrawString(s);\r
555         py += h;\r
556         px = x + ((tw - w) / 2);\r
557         USL_DrawString(msg);\r
558 \r
559         VW_UpdateScreen();\r
560 #ifdef CAT3D\r
561         IN_UserInput(100, true);\r
562 #endif\r
563 }\r
564 \r
565 static boolean\r
566 USL_CtlDialog(char *s1,char *s2,char *s3)\r
567 {\r
568         word            w,h,sh,\r
569                                 w1,w2,w3,\r
570                                 x,y;\r
571         ScanCode        c;\r
572         CursorInfo      cursorinfo;\r
573 \r
574         USL_MeasureString(s1,&w1,&h);\r
575         USL_MeasureString(s2,&w2,&h);\r
576         if (s3)\r
577                 USL_MeasureString(s3,&w3,&h);\r
578         else\r
579                 w3 = 0;\r
580         w = (w1 > w2)? ((w1 > w3)? w1 : w3) : ((w2 > w3)? w2 : w3);\r
581         w += 7;\r
582         sh = h;\r
583         h *= s3? 5 : 4;\r
584 \r
585         USL_DialogSetup(w,h,&x,&y);\r
586 \r
587         fontcolor = HiliteColor;\r
588         px = x + ((w - w1) / 2);\r
589         py = y + sh + 1;\r
590         USL_DrawString(s1);\r
591         py += (sh * 2) - 1;\r
592 \r
593         VWB_Hlin(x + 3,x + w - 3,py,NohiliteColor);\r
594         py += 2;\r
595 \r
596         fontcolor = NohiliteColor;\r
597         px = x + ((w - w2) / 2);\r
598         USL_DrawString(s2);\r
599         py += sh;\r
600 \r
601         if (s3)\r
602         {\r
603                 px = x + ((w - w3) / 2);\r
604                 USL_DrawString(s3);\r
605         }\r
606 \r
607         VW_UpdateScreen();\r
608 \r
609         IN_ClearKeysDown();\r
610         do\r
611         {\r
612                 IN_ReadCursor(&cursorinfo);\r
613                 if (cursorinfo.button0)\r
614                         c = sc_Y;\r
615                 else if (cursorinfo.button1)\r
616                         c = sc_Escape;\r
617                 else\r
618                         c = LastScan;\r
619         } while (c == sc_None);\r
620         do\r
621         {\r
622                 IN_ReadCursor(&cursorinfo);\r
623         } while (cursorinfo.button0 || cursorinfo.button1);\r
624 \r
625         IN_ClearKeysDown();\r
626         USL_DrawCtlPanel();\r
627         return(c == sc_Y);\r
628 }\r
629 \r
630 static boolean\r
631 USL_ConfirmComm(UComm comm)\r
632 {\r
633         boolean confirm,dialog;\r
634         char    *s1,*s2,*s3;\r
635 \r
636         if (!comm)\r
637                 Quit("USL_ConfirmComm() - empty comm");\r
638 \r
639         confirm = true;\r
640         dialog = false;\r
641         s3 = "ESC TO BACK OUT";\r
642         switch (comm)\r
643         {\r
644         case uc_Abort:\r
645                 s1 = "REALLY END CURRENT GAME?";\r
646                 s2 = "PRESS Y TO END IT";\r
647                 if (ingame && GameIsDirty)\r
648                         dialog = true;\r
649                 break;\r
650         case uc_Quit:\r
651                 s1 = "REALLY QUIT?";\r
652                 s2 = "PRESS Y TO QUIT";\r
653                 dialog = true;\r
654                 break;\r
655         case uc_Loaded:\r
656                 s1 = "YOU'RE IN A GAME";\r
657                 s2 = "PRESS Y TO LOAD GAME";\r
658                 if (ingame && GameIsDirty)\r
659                         dialog = true;\r
660                 break;\r
661         case uc_SEasy:\r
662         case uc_SNormal:\r
663         case uc_SHard:\r
664                 s1 = "YOU'RE IN A GAME";\r
665                 s2 = "PRESS Y FOR NEW GAME";\r
666                 if (ingame && GameIsDirty)\r
667                         dialog = true;\r
668                 break;\r
669         }\r
670 \r
671         confirm = dialog? USL_CtlDialog(s1,s2,s3) : true;\r
672         if (confirm)\r
673         {\r
674                 Communication = comm;\r
675                 CtlPanelDone = true;\r
676         }\r
677         return(confirm);\r
678 }\r
679 \r
680 ///////////////////////////////////////////////////////////////////////////\r
681 //\r
682 //      USL_HandleError() - Handles telling the user that there's been an error\r
683 //\r
684 ///////////////////////////////////////////////////////////////////////////\r
685 static void\r
686 USL_HandleError(int num)\r
687 {\r
688         char    buf[64];\r
689 \r
690         strcpy(buf,"Error: ");\r
691         if (num < 0)\r
692                 strcat(buf,"Unknown");\r
693         else if (num == ENOMEM)\r
694                 strcat(buf,"Disk is Full");\r
695         else if (num == EINVFMT)\r
696                 strcat(buf,"File is Incomplete");\r
697         else\r
698                 strcat(buf,sys_errlist[num]);\r
699 \r
700         VW_HideCursor();\r
701 \r
702         USL_CtlDialog(buf,"PRESS ANY KEY",nil);\r
703         VW_UpdateScreen();\r
704 \r
705         IN_ClearKeysDown();\r
706         IN_Ack();\r
707 \r
708         VW_ShowCursor();\r
709         VW_UpdateScreen();\r
710 }\r
711 \r
712 //      Custom routines\r
713 #if 0\r
714 static boolean\r
715 USL_GenericCustom(UserCall call,UserItem far *item)\r
716 {\r
717         boolean result;\r
718 \r
719         result = false;\r
720         switch (call)\r
721         {\r
722         }\r
723         return(result);\r
724 }\r
725 #endif\r
726 \r
727 static void\r
728 USL_SetOptionsText(void)\r
729 {\r
730         optionsi[0].text = showscorebox? "SCORE BOX (ON)" : "SCORE BOX (OFF)";\r
731         optionsi[1].text = oldshooting? "TWO-BUTTON FIRING (ON)" : "TWO-BUTTON FIRING (OFF)";\r
732 #if GRMODE != CGAGR\r
733         optionsi[2].text = jerk? "FIX JERKY MOTION (ON)" : "FIX JERKY MOTION (OFF)";\r
734         optionsi[3].text = compatability? "SVGA COMPATIBILITY (ON)" : "SVGA COMPATIBILITY (OFF)";\r
735 #endif\r
736 \r
737         keybi[2].flags &= ~ui_Disabled;\r
738         if (oldshooting)\r
739                 keybi[2].flags |= ui_Disabled;\r
740 \r
741         // gravis option is only enabled when a joystick is selected\r
742         configi[6].flags |= ui_Disabled;\r
743         if (Controls[0] == ctrl_Joystick1 || Controls[0] == ctrl_Joystick2)\r
744                 configi[6].flags &= ~ui_Disabled;\r
745 \r
746         configi[6].text = GravisGamepad? "USE GRAVIS GAMEPAD (ON)" : "USE GRAVIS GAMEPAD (OFF)";\r
747 }\r
748 \r
749 #pragma argsused\r
750 static boolean\r
751 USL_ScoreCustom(UserCall call,UserItem far *item)\r
752 {\r
753         if (call != uic_SetupCard)\r
754                 return(false);\r
755 \r
756         showscorebox ^= true;\r
757         USL_CtlDialog(showscorebox? "Score box now on" : "Score box now off",\r
758                                         "Press any key",nil);\r
759         USL_SetOptionsText();\r
760         return(true);\r
761 }\r
762 \r
763 #pragma argsused\r
764 static boolean\r
765 USL_SmoothCustom(UserCall call,UserItem far *item)\r
766 {\r
767         if (call != uic_SetupCard)\r
768                 return(false);\r
769 \r
770         jerk ^= true;\r
771         USL_CtlDialog(jerk? "Jerky motion fix enabled" : "Jerky motion fix disabled",\r
772                                         "Press any key",nil);\r
773         USL_SetOptionsText();\r
774         return(true);\r
775 }\r
776 \r
777 #pragma argsused\r
778 static boolean\r
779 USL_CompCustom(UserCall call,UserItem far *item)\r
780 {\r
781         if (call != uic_SetupCard)\r
782                 return(false);\r
783 \r
784         compatability ^= true;\r
785         USL_CtlDialog(compatability? "SVGA compatibility now on" : "SVGA compatibility now off",\r
786                                         "Press any key",nil);\r
787         USL_SetOptionsText();\r
788         return(true);\r
789 }\r
790 \r
791 #ifdef  KEEN\r
792 #pragma argsused\r
793 static boolean\r
794 USL_TwoCustom(UserCall call,UserItem far *item)\r
795 {\r
796         if (call != uic_SetupCard)\r
797                 return(false);\r
798 \r
799         oldshooting ^= true;\r
800         USL_CtlDialog(oldshooting? "Two-button firing now on" : "Two-button firing now off",\r
801                                         "Press any key",nil);\r
802         USL_SetOptionsText();\r
803         return(true);\r
804 }\r
805 #endif\r
806 \r
807 static boolean\r
808 USL_ConfigCustom(UserCall call,UserItem far *item)\r
809 {\r
810 static  char    *CtlNames[] = {"KEYBOARD","KEYBOARD","JOYSTICK #1","JOYSTICK #2","MOUSE"};\r
811                 char    *s;\r
812                 word    w,h,\r
813                                 tw;\r
814 \r
815         if (call == uic_TouchupCard)\r
816         {\r
817                 s = "CONTROL: ";\r
818                 USL_MeasureString(s,&w,&h);\r
819                 tw = w;\r
820                 USL_MeasureString(CtlNames[Controls[0]],&w,&h);\r
821                 tw += w;\r
822                 py = CtlPanelEY - 18 - h;\r
823                 px = CtlPanelSX + ((CtlPanelW - tw) / 2);\r
824                 fontcolor = NohiliteColor;\r
825                 USL_DrawString(s);\r
826                 USL_DrawString(CtlNames[Controls[0]]);\r
827         }\r
828         item++; // Shut the compiler up\r
829         return(false);\r
830 }\r
831 \r
832 static void\r
833 USL_CKSetKey(UserItem far *item,word i)\r
834 {\r
835         boolean         on;\r
836         word            j;\r
837         ScanCode        scan;\r
838         longword        time;\r
839         CursorInfo      cursorinfo;\r
840 \r
841         on = false;\r
842         time = 0;\r
843         LastScan = sc_None;\r
844         fontcolor = HiliteColor;\r
845         do\r
846         {\r
847                 if (TimeCount >= time)\r
848                 {\r
849                         on ^= true;\r
850                         VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
851                         VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
852                         if (on)\r
853                                 VWB_DrawTile8(item->x + 90 + 16,item->y,TileBase + 8);\r
854                         VW_UpdateScreen();\r
855 \r
856                         time = TimeCount + (TickBase / 2);\r
857                 }\r
858 \r
859                 IN_ReadCursor(&cursorinfo);\r
860                 while (cursorinfo.button0 || cursorinfo.button1)\r
861                 {\r
862                         IN_ReadCursor(&cursorinfo);\r
863                         LastScan = sc_Escape;\r
864                 }\r
865 \r
866         asm     pushf\r
867         asm     cli\r
868                 if (LastScan == sc_LShift)\r
869                         LastScan = sc_None;\r
870         asm     popf\r
871         } while (!(scan = LastScan));\r
872 \r
873         if (scan != sc_Escape)\r
874         {\r
875                 for (j = 0,on = false;j < 11;j++)\r
876                 {\r
877                         if (j == i)\r
878                                 continue;\r
879                         if (*(KeyMaps[j]) == scan)\r
880                         {\r
881                                 on = true;\r
882                                 break;\r
883                         }\r
884                 }\r
885                 if (on)\r
886 #ifdef KEEN\r
887                         USL_CtlDialog("Key already used","Press any key",nil);\r
888 #else\r
889                         USL_CtlDialog("Key already used","Press a key",nil);\r
890 #endif\r
891                 else\r
892                         *(KeyMaps[i]) = scan;\r
893         }\r
894         IN_ClearKeysDown();\r
895 }\r
896 \r
897 #pragma argsused\r
898 static boolean\r
899 USL_KeySCustom(UserCall call,UserItem far *item)\r
900 {\r
901         if (call == uic_SetupCard)\r
902         {\r
903                 Controls[0] = ctrl_Keyboard;\r
904                 GravisGamepad = false;\r
905                 USL_SetOptionsText();\r
906         }\r
907         return(false);\r
908 }\r
909 \r
910 #pragma argsused\r
911 static boolean\r
912 USL_KeyCustom(UserCall call,UserItem far *item)\r
913 {\r
914         boolean result;\r
915         word    i;\r
916 \r
917         result = false;\r
918         i = (topcard == &keygroup)? (3 + (item - keyi)) : (item - keybi);\r
919         switch (call)\r
920         {\r
921         case uic_SetupCard:\r
922                 Controls[0] = ctrl_Keyboard;\r
923                 break;\r
924         case uic_Draw:\r
925                 VWB_Bar(CtlPanelSX + 1,item->y,\r
926                                 CtlPanelEX - CtlPanelSX - 1,8,BackColor);       // Clear out background\r
927                 USL_DrawItemIcon(item);\r
928                 fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
929                 px = item->x + 8;\r
930                 py = item->y + 1;\r
931                 USL_DrawString(item->text);\r
932                 VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
933                 VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
934                 px = item->x + 90 + 6;\r
935                 py = item->y + 1;\r
936                 USL_DrawString(IN_GetScanName(*KeyMaps[i]));\r
937                 result = true;\r
938                 break;\r
939         case uic_Hit:\r
940                 USL_KeyCustom(uic_Draw,item);\r
941                 USL_CKSetKey(item,i);\r
942                 USL_DrawCtlPanel();\r
943                 result = true;\r
944                 break;\r
945         }\r
946         return(result);\r
947 }\r
948 \r
949 static void\r
950 USL_CJDraw(char *s1,char *s2)\r
951 {\r
952         word    w,h;\r
953 \r
954         USL_MeasureString(s1,&w,&h);\r
955         px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
956         py = CtlPanelEY - 34;\r
957         VWB_Bar(CtlPanelSX + 1,py,CtlPanelW - 2,h * 2,BackColor);\r
958         fontcolor = HiliteColor;\r
959         USL_DrawString(s1);\r
960         py += h;\r
961         USL_MeasureString(s2,&w,&h);\r
962         px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
963         USL_DrawString(s2);\r
964 }\r
965 \r
966 static boolean\r
967 USL_CJGet(word joy,word button,word x,word y,word *xaxis,word *yaxis)\r
968 {\r
969         boolean         on;\r
970         longword        time;\r
971 \r
972         while (IN_GetJoyButtonsDB(joy))\r
973                 if (LastScan == sc_Escape)\r
974                         return(false);\r
975 \r
976         on = false;\r
977         time = 0;\r
978         while (!(IN_GetJoyButtonsDB(joy) & (1 << button)))\r
979         {\r
980                 if (TimeCount >= time)\r
981                 {\r
982                         on ^= true;\r
983                         time = TimeCount + (TickBase / 2);\r
984                         VWB_DrawTile8(x,y,TileBase + on);\r
985                         VW_UpdateScreen();\r
986                 }\r
987 \r
988                 if (LastScan == sc_Escape)\r
989                         return(false);\r
990         }\r
991         IN_GetJoyAbs(joy,xaxis,yaxis);\r
992         return(true);\r
993 }\r
994 \r
995 static boolean\r
996 USL_ConfigJoystick(word joy)\r
997 {\r
998         word    x,y,\r
999                         minx,miny,\r
1000                         maxx,maxy;\r
1001 \r
1002         BottomS1 = BottomS2 = "";\r
1003 #ifdef KEEN\r
1004         BottomS3 = "ESC to back out";\r
1005 #else\r
1006         BottomS3 = "Esc to back out";\r
1007 #endif\r
1008         USL_DrawCtlPanel();\r
1009         x = CtlPanelSX + 60;\r
1010         y = CtlPanelSY + 19;\r
1011         VWB_DrawPic(x,y,CP_JOYSTICKPIC);\r
1012 \r
1013         USL_CJDraw("Move Joystick to upper left","and press button #1");\r
1014         VWB_DrawTile8(x + 24,y + 8,TileBase + 6);\r
1015         VWB_DrawTile8(x + 8,y + 8,TileBase + 1);\r
1016         VWB_DrawTile8(x + 8,y + 24,TileBase + 0);\r
1017         VW_UpdateScreen();\r
1018         if (!USL_CJGet(joy,0,x + 8,y + 8,&minx,&miny))\r
1019                 return(false);\r
1020 \r
1021         USL_CJDraw("Move Joystick to lower right","and press button #2");\r
1022         VWB_DrawTile8(x + 24,y + 8,TileBase - 25);\r
1023         VWB_DrawTile8(x + 40,y + 24,TileBase + 7);\r
1024         VWB_DrawTile8(x + 8,y + 8,TileBase + 0);\r
1025         VWB_DrawTile8(x + 8,y + 24,TileBase + 1);\r
1026         VW_UpdateScreen();\r
1027         if (!USL_CJGet(joy,1,x + 8,y + 24,&maxx,&maxy))\r
1028                 return(false);\r
1029 \r
1030         while (IN_GetJoyButtonsDB(joy))\r
1031                 ;\r
1032 \r
1033 #ifdef KEEN\r
1034         if (minx != maxx && miny != maxy)\r
1035         {\r
1036                 IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
1037                 return(true);\r
1038         }\r
1039         return(false);\r
1040 #else\r
1041         IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
1042         return(true);\r
1043 #endif\r
1044 }\r
1045 \r
1046 #pragma argsused\r
1047 static boolean\r
1048 USL_Joy1Custom(UserCall call,UserItem far *item)\r
1049 {\r
1050         if (call == uic_SetupCard)\r
1051         {\r
1052                 if (USL_ConfigJoystick(0))\r
1053                 {\r
1054                         Controls[0] = ctrl_Joystick1;\r
1055                         USL_CtlDialog("USING JOYSTICK #1","PRESS ANY KEY",nil);\r
1056                         USL_SetOptionsText();\r
1057                 }\r
1058                 return(true);\r
1059         }\r
1060         else\r
1061                 return(false);\r
1062 }\r
1063 \r
1064 #pragma argsused\r
1065 static boolean\r
1066 USL_Joy2Custom(UserCall call,UserItem far *item)\r
1067 {\r
1068         if (call == uic_SetupCard)\r
1069         {\r
1070                 if (USL_ConfigJoystick(1))\r
1071                 {\r
1072                         Controls[0] = ctrl_Joystick2;\r
1073                         USL_CtlDialog("USING JOYSTICK #2","PRESS ANY KEY",nil);\r
1074                         USL_SetOptionsText();\r
1075                 }\r
1076                 return(true);\r
1077         }\r
1078         else\r
1079                 return(false);\r
1080 }\r
1081 \r
1082 static void\r
1083 USL_CGDraw(char *s1, char *s2, int buttonsDone)\r
1084 {\r
1085         static char *GButtonNames[4] = {"Red","Blue","Yellow","Green"};\r
1086         static char *GActionNames[4] = {"Jump","Pogo","Fire","Status"};\r
1087 \r
1088         int     i, n;\r
1089         char    *actionstr;\r
1090         word    w, h;\r
1091 \r
1092         VWB_Bar(CtlPanelSX+1, CtlPanelSY+16, CtlPanelW-2, 68, BackColor);\r
1093         px = CtlPanelSX+8;\r
1094         py = CtlPanelSY+16;\r
1095         USL_DrawString("Make sure that the button");\r
1096         px = CtlPanelSX+8;\r
1097         py = CtlPanelSY+24;\r
1098         USL_DrawString("switch is set for 4 buttons");\r
1099 \r
1100         for (i=0; i<4; i++)\r
1101         {\r
1102                 px = CtlPanelSX+8;\r
1103                 py = i*8 + CtlPanelSY+40;\r
1104                 USL_DrawString(GButtonNames[i]);\r
1105                 USL_DrawString(":");\r
1106                 actionstr = "?";\r
1107                 for (n=0;n<buttonsDone;n++)\r
1108                 {\r
1109                         if (GravisMap[n] == i)\r
1110                                 actionstr = GActionNames[n];\r
1111                 }\r
1112                 px = CtlPanelSX+56;\r
1113                 USL_DrawString(actionstr);\r
1114         }\r
1115 \r
1116         USL_MeasureString(s1, &w, &h);\r
1117         px = w;\r
1118         USL_MeasureString(s2, &w, &h);\r
1119         px = (CtlPanelW-px-w)/2 + CtlPanelSX;\r
1120         py = CtlPanelSY+76;\r
1121         USL_DrawString(s1);\r
1122         USL_DrawString(s2);\r
1123         VW_UpdateScreen();\r
1124 }\r
1125 \r
1126 static boolean\r
1127 USL_CGGet(int buttonsDone, char *action)\r
1128 {\r
1129         word    buttons, i, n;\r
1130 \r
1131         USL_CGDraw("PRESS BUTTON FOR ", action, buttonsDone);\r
1132 \r
1133 redo:\r
1134         do\r
1135         {\r
1136                 if (LastScan == sc_Escape)\r
1137                 {\r
1138                         Keyboard[sc_Escape] = false;\r
1139                         if (LastScan == sc_Escape)\r
1140                                 LastScan = sc_None;\r
1141                         return false;\r
1142                 }\r
1143 \r
1144                 buttons = IN_GetJoyButtonsDB(2);\r
1145                 if (!buttons)\r
1146                         continue;\r
1147 \r
1148                 for(i=n=0; i<4; i++)\r
1149                 {\r
1150                         if (buttons & (1 << i))\r
1151                                 n += i+1;\r
1152                 }\r
1153 \r
1154                 if (!n || n >= 5)\r
1155                         continue;\r
1156 \r
1157                 n--;\r
1158                 for (i=0; i<buttonsDone; i++)\r
1159                 {\r
1160                         if (GravisMap[i] == n)\r
1161                                 goto redo;\r
1162                 }\r
1163 \r
1164                 GravisMap[buttonsDone] = n;\r
1165                 return true;\r
1166         } while (true);\r
1167 }\r
1168 \r
1169 #pragma argsused\r
1170 static boolean\r
1171 USL_JoyGCustom(UserCall call,UserItem far *item)\r
1172 {\r
1173         if (call == uic_SetupCard)\r
1174         {\r
1175                 if (GravisGamepad)\r
1176                 {\r
1177                         GravisGamepad = false;\r
1178                 }\r
1179                 else\r
1180                 {\r
1181                         BottomS1 = BottomS2 = "";\r
1182                         BottomS3 = "ESC to back out";\r
1183                         USL_DrawCtlPanel();\r
1184                         fontcolor = HiliteColor;\r
1185                         px = CtlPanelSX + 8;\r
1186                         py = CtlPanelSX + 8;\r
1187                         fontcolor = HiliteColor;        // redundant...\r
1188                         IN_ClearKeysDown();\r
1189                         if (  USL_CGGet(0, "JUMP")\r
1190                                 && USL_CGGet(1, "POGO")\r
1191                                 && USL_CGGet(2, "FIRE")\r
1192                                 && USL_CGGet(3, "STATUS") )\r
1193                         {\r
1194                                 GravisGamepad = true;\r
1195                                 USL_CGDraw("PRESS ANY KEY", "", 4);\r
1196                                 IN_Ack();\r
1197                         }\r
1198                         else\r
1199                         {\r
1200                                 GravisGamepad = false;\r
1201                         }\r
1202                 }\r
1203                 USL_SetOptionsText();\r
1204                 return true;\r
1205         }\r
1206         return false;\r
1207 }\r
1208 \r
1209 static void\r
1210 USL_DrawFileIcon(UserItem far *item)\r
1211 {\r
1212         word    color;\r
1213 \r
1214         item->y = topcard->y + CtlPanelSY + 12;\r
1215         item->y += (item - loadsavegamei) * 11;\r
1216 \r
1217         fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
1218         color = fontcolor ^ BackColor;  // Blech!\r
1219         VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y,color);\r
1220         VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y + 9,color);\r
1221         VWB_Vlin(item->y,item->y + 9,item->x,color);\r
1222         VWB_Vlin(item->y,item->y + 9,item->x + (CtlPanelW - 12),color);\r
1223 }\r
1224 \r
1225 static void\r
1226 USL_DoLoadGame(UserItem far *item)\r
1227 {\r
1228         char            *filename;\r
1229         word            n,\r
1230                                 err;\r
1231         int                     file;\r
1232         SaveGame        *game;\r
1233 \r
1234         if (!USL_ConfirmComm(uc_Loaded))\r
1235                 return;\r
1236 \r
1237         n = item - loadsavegamei;\r
1238         game = &Games[n];\r
1239 \r
1240         USL_ShowLoadSave("Loading",game->name);\r
1241 \r
1242         err = 0;\r
1243         filename = USL_GiveSaveName(n);\r
1244         if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
1245         {\r
1246                 if (read(file,game,sizeof(*game)) == sizeof(*game))\r
1247                 {\r
1248                         if (USL_LoadGame)\r
1249                                 if (!USL_LoadGame(file))\r
1250                                         USL_HandleError(err = errno);\r
1251                 }\r
1252                 else\r
1253                         USL_HandleError(err = errno);\r
1254                 close(file);\r
1255         }\r
1256         else\r
1257                 USL_HandleError(err = errno);\r
1258         if (err)\r
1259         {\r
1260                 abortgame = true;\r
1261                 Communication = uc_None;\r
1262                 CtlPanelDone = false;\r
1263         }\r
1264         else\r
1265                 loadedgame = true;\r
1266         game->present = true;\r
1267 \r
1268         if (loadedgame)\r
1269                 Paused = true;\r
1270 \r
1271         USL_DrawCtlPanel();\r
1272 }\r
1273 \r
1274 static boolean\r
1275 USL_LoadCustom(UserCall call,UserItem far *item)\r
1276 {\r
1277         boolean result;\r
1278         word    i;\r
1279 \r
1280         result = false;\r
1281         switch (call)\r
1282         {\r
1283         case uic_SetupCard:\r
1284 #ifdef KEEN\r
1285                 if (getenv("UID"))\r
1286                         USL_CheckSavedGames();\r
1287 #endif\r
1288                 for (i = 0;i < MaxSaveGames;i++)\r
1289                 {\r
1290                         if (Games[i].present)\r
1291                                 loadsavegamei[i].flags &= ~ui_Disabled;\r
1292                         else\r
1293                                 loadsavegamei[i].flags |= ui_Disabled;\r
1294                 }\r
1295                 break;\r
1296         case uic_DrawIcon:\r
1297                 USL_DrawFileIcon(item);\r
1298                 result = true;\r
1299                 break;\r
1300         case uic_Draw:\r
1301                 USL_DrawFileIcon(item);\r
1302                 VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
1303 \r
1304                 i = item - loadsavegamei;\r
1305                 if (Games[i].present)\r
1306                         px = item->x + 2;\r
1307                 else\r
1308                         px = item->x + 60;\r
1309                 py = item->y + 2;\r
1310                 USL_DrawString(Games[i].present? Games[i].name : "Empty");\r
1311                 result = true;\r
1312                 break;\r
1313         case uic_Hit:\r
1314                 USL_DoLoadGame(item);\r
1315                 result = true;\r
1316                 break;\r
1317         }\r
1318         return(result);\r
1319 }\r
1320 \r
1321 static void\r
1322 USL_DoSaveGame(UserItem far *item)\r
1323 {\r
1324         boolean         ok;\r
1325         char            *filename;\r
1326         word            n,err;\r
1327         int         file;\r
1328         SaveGame        *game;\r
1329 \r
1330         BottomS1 = "Type name";\r
1331         BottomS2 = "Enter accepts";\r
1332         USL_DrawCtlPanel();\r
1333 \r
1334         n = item - loadsavegamei;\r
1335         game = &Games[n];\r
1336         fontcolor = HiliteColor;\r
1337         VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
1338         game->oldtest = &PrintX;\r
1339         ok = US_LineInput(item->x + 2,item->y + 2,\r
1340                                                 game->name,game->present? game->name : nil,\r
1341                                                 true,MaxGameName,\r
1342                                                 CtlPanelW - 22);\r
1343         if (!strlen(game->name))\r
1344                 strcpy(game->name,"Untitled");\r
1345         if (ok)\r
1346         {\r
1347                 USL_ShowLoadSave("Saving",game->name);\r
1348 \r
1349                 filename = USL_GiveSaveName(n);\r
1350                 err = 0;\r
1351                 file = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
1352                                         S_IREAD | S_IWRITE | S_IFREG);\r
1353                 if (file != -1)\r
1354                 {\r
1355                         if (write(file,game,sizeof(*game)) == sizeof(*game))\r
1356                         {\r
1357                                 if (USL_SaveGame)\r
1358                                         ok = USL_SaveGame(file);\r
1359                                 if (!ok)\r
1360                                         USL_HandleError(err = errno);\r
1361                         }\r
1362                         else\r
1363                                 USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
1364                         close(file);\r
1365                 }\r
1366                 else\r
1367                         USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
1368                 if (err)\r
1369                 {\r
1370                         remove(filename);\r
1371                         ok = false;\r
1372                 }\r
1373 \r
1374         }\r
1375 \r
1376         if (!game->present)\r
1377                 game->present = ok;\r
1378 \r
1379         if (ok)\r
1380                 GameIsDirty = false;\r
1381         USL_SetupCard();\r
1382 }\r
1383 \r
1384 static boolean\r
1385 USL_SaveCustom(UserCall call,UserItem far *item)\r
1386 {\r
1387         word    i;\r
1388 \r
1389         switch (call)\r
1390         {\r
1391         case uic_SetupCard:\r
1392 #ifdef KEEN\r
1393                 if (getenv("UID"))\r
1394                         USL_CheckSavedGames();\r
1395 #endif\r
1396                 for (i = 0;i < MaxSaveGames;i++)\r
1397                         loadsavegamei[i].flags &= ~ui_Disabled;\r
1398                 return(false);\r
1399         case uic_Hit:\r
1400                 USL_DoSaveGame(item);\r
1401                 return(true);\r
1402 //              break;\r
1403         }\r
1404         return(USL_LoadCustom(call,item));\r
1405 }\r
1406 \r
1407 #define PaddleMinX      (CtlPanelSX + 4)\r
1408 #define PaddleMaxX      (CtlPanelEX - 15)\r
1409 #define BallMinX        (CtlPanelSX + 4)\r
1410 #define BallMinY        (CtlPanelSY + 12 + 2)\r
1411 #define BallMaxX        (CtlPanelEX - 6)\r
1412 #define BallMaxY        (CtlPanelEY - 13)\r
1413 #define CPaddleY        (BallMinY + 4)\r
1414 #define KPaddleY        (BallMaxY - 2)\r
1415 void\r
1416 USL_DrawPongScore(word k,word c)\r
1417 {\r
1418         fontcolor = HiliteColor;\r
1419         PrintY = py = CtlPanelSY + 4;\r
1420         px = CtlPanelSX + 6;\r
1421         VWB_Bar(px,py,42,6,BackColor);\r
1422         USL_DrawString("KEEN:");\r
1423         PrintX = px;\r
1424         US_PrintUnsigned(k);\r
1425         px = CtlPanelSX + 108;\r
1426         VWB_Bar(px,py,50,6,BackColor);\r
1427         USL_DrawString("COMP:");\r
1428         PrintX = px;\r
1429         US_PrintUnsigned(c);\r
1430 }\r
1431 \r
1432 void\r
1433 USL_PlayPong(void)\r
1434 {\r
1435         boolean         ball,killball,revdir,done,lastscore;\r
1436         word            cycle,\r
1437                                 x,y,\r
1438                                 kx,cx,\r
1439                                 rx,\r
1440                                 bx,by,\r
1441                                 oldkx,oldcx,oldbx,oldby,\r
1442                                 kscore,cscore,\r
1443                                 speedup;\r
1444         int                     bdx,bdy;\r
1445         longword        balltime,lasttime,waittime;\r
1446         CursorInfo      cursorinfo;\r
1447 \r
1448         kx = cx = PaddleMinX + ((PaddleMaxX - PaddleMinX) / 2);\r
1449         bx = by = bdx = bdy = 0;\r
1450         oldbx = oldcx = oldkx = PaddleMinX;\r
1451         oldby = BallMinY;\r
1452         kscore = cscore = 0;\r
1453         USL_DrawPongScore(0,0);\r
1454         cycle = 0;\r
1455         revdir = false;\r
1456         killball = true;\r
1457         done = false;\r
1458         lastscore = false;\r
1459         lasttime = TimeCount;\r
1460         do\r
1461         {\r
1462                 while ((waittime = TimeCount - lasttime) == 0)\r
1463                         ;\r
1464 \r
1465                 lasttime = TimeCount;\r
1466                 if (waittime > 4)\r
1467                         waittime = 4;\r
1468 \r
1469                 while (waittime-- && !done && LastScan != sc_Escape)\r
1470                 {\r
1471                         IN_ReadCursor(&cursorinfo);\r
1472                         if (((cursorinfo.x < 0) || IN_KeyDown(sc_LeftArrow)) && (kx > PaddleMinX))\r
1473                                 kx -= 2;\r
1474                         else if (((cursorinfo.x > 0) || IN_KeyDown(sc_RightArrow)) && (kx < PaddleMaxX))\r
1475                                 kx += 2;\r
1476 \r
1477                         if (killball)\r
1478                         {\r
1479                                 ball = false;\r
1480                                 balltime = TickBase;\r
1481                                 speedup = 10;\r
1482                                 killball = false;\r
1483                                 VWB_Bar(oldbx,oldby,5,5,BackColor);\r
1484                         }\r
1485 \r
1486                         if (ball && (cycle++ % 3))\r
1487                         {\r
1488                                 x = (bx >> 2);\r
1489                                 if (!(x & 1))\r
1490                                         x += (US_RndT() & 1);\r
1491 \r
1492                                 if ((cx + 6 < x) && (cx < PaddleMaxX))\r
1493                                         cx += 1;\r
1494                                 else if ((cx + 6 > x) && (cx > PaddleMinX))\r
1495                                         cx -= 1;\r
1496                         }\r
1497 \r
1498                         if (!ball && !--balltime)\r
1499                         {\r
1500                                 ball = true;\r
1501                                 bdx = 1 - (US_RndT() % 3);\r
1502                                 bdy = 3;\r
1503                                 if (lastscore)\r
1504                                         bdy = -bdy;\r
1505                                 bx = (BallMinX + ((BallMaxX - BallMinX) / 2)) << 2;\r
1506                                 by = (BallMinY + ((BallMaxY - BallMinY) / 2)) << 2;\r
1507                         }\r
1508 \r
1509                         if (ball)\r
1510                         {\r
1511                                 if\r
1512                                 (\r
1513                                         (((bx + bdx) >> 2) > BallMaxX)\r
1514                                 ||      (((bx + bdx) >> 2) < BallMinX)\r
1515                                 )\r
1516                                 {\r
1517                                         SD_PlaySound(BALLBOUNCESND);\r
1518                                         bdx = -bdx;\r
1519                                 }\r
1520                                 bx += bdx;\r
1521 \r
1522                                 if (((by + bdy) >> 2) > BallMaxY)\r
1523                                 {\r
1524                                         killball = true;\r
1525                                         lastscore = false;\r
1526                                         cscore++;\r
1527                                         SD_PlaySound(COMPSCOREDSND);\r
1528                                         USL_DrawPongScore(kscore,cscore);\r
1529                                         if (cscore == 21)\r
1530                                         {\r
1531                                                 USL_CtlDialog("You lost!","Press any key",nil);\r
1532                                                 done = true;\r
1533                                                 continue;\r
1534                                         }\r
1535                                 }\r
1536                                 else if (((by + bdy) >> 2) < BallMinY)\r
1537                                 {\r
1538                                         killball = true;\r
1539                                         lastscore = true;\r
1540                                         kscore++;\r
1541                                         SD_PlaySound(KEENSCOREDSND);\r
1542                                         USL_DrawPongScore(kscore,cscore);\r
1543                                         if (kscore == 21)\r
1544                                         {\r
1545                                                 USL_CtlDialog("You won!","Press any key",nil);\r
1546                                                 done = true;\r
1547                                                 continue;\r
1548                                         }\r
1549                                 }\r
1550                                 by += bdy;\r
1551 \r
1552                                 x = bx >> 2;\r
1553                                 y = by >> 2;\r
1554                                 if (!killball)\r
1555                                 {\r
1556                                         if\r
1557                                         (\r
1558                                                 (bdy < 0)\r
1559                                         &&      ((y >= CPaddleY) && (y < CPaddleY + 3))\r
1560                                         &&      ((x >= (cx - 5)) && (x < (cx + 11)))\r
1561                                         )\r
1562                                         {\r
1563                                                 rx = cx;\r
1564                                                 revdir = true;\r
1565                                                 SD_PlaySound(COMPPADDLESND);\r
1566                                         }\r
1567                                         else if\r
1568                                         (\r
1569                                                 (bdy > 0)\r
1570                                         &&      ((y >= (KPaddleY - 3)) && (y < KPaddleY))\r
1571                                         &&      ((x >= (kx - 5)) && (x < (kx + 11)))\r
1572                                         )\r
1573                                         {\r
1574                                                 if (((bdy >> 2) < 3) && !(--speedup))\r
1575                                                 {\r
1576                                                         bdy++;\r
1577                                                         speedup = 10;\r
1578                                                 }\r
1579                                                 rx = kx;\r
1580                                                 revdir = true;\r
1581                                                 SD_PlaySound(KEENPADDLESND);\r
1582                                         }\r
1583                                         if (revdir)\r
1584                                         {\r
1585                                                 bdy = -bdy;\r
1586                                                 bdx = ((x + 5 - rx) >> 1) - (1 << 2);\r
1587                                                 if (!bdx)\r
1588                                                         bdx--;\r
1589                                                 revdir = false;\r
1590                                         }\r
1591                                 }\r
1592                         }\r
1593                 }\r
1594 \r
1595                 if (ball)\r
1596                 {\r
1597                         VWB_Bar(oldbx,oldby,5,5,BackColor);\r
1598                         oldbx = x;\r
1599                         oldby = y;\r
1600 #if GRMODE == CGAGR\r
1601                         {\r
1602                                 static int ballsprites[4] = {BALLSPR, BALL1PIXELTOTHERIGHTSPR, BALL2PIXELSTOTHERIGHTSPR, BALL3PIXELSTOTHERIGHTSPR};\r
1603                                 VWB_DrawSprite(x,y,ballsprites[x & 3]);\r
1604                         }\r
1605 #else\r
1606                         VWB_DrawSprite(x,y,(x & 1)? BALL1PIXELTOTHERIGHTSPR : BALLSPR);\r
1607 #endif\r
1608                 }\r
1609                 VWB_Bar(oldcx-3,CPaddleY,16,3,BackColor);\r
1610                 oldcx = cx;\r
1611                 VWB_DrawSprite(cx,CPaddleY,PADDLESPR);\r
1612                 VWB_Bar(oldkx-3,KPaddleY,16,3,BackColor);\r
1613                 oldkx = kx;\r
1614                 VWB_DrawSprite(kx,KPaddleY,PADDLESPR);\r
1615 \r
1616                 VW_UpdateScreen();\r
1617         } while ((LastScan != sc_Escape) && !done);\r
1618         IN_ClearKeysDown();\r
1619 }\r
1620 \r
1621 #pragma argsused\r
1622 static boolean\r
1623 USL_PongCustom(UserCall call,struct UserItem far *item)\r
1624 {\r
1625         if (call != uic_SetupCard)\r
1626                 return(false);\r
1627 \r
1628         VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
1629         VWB_DrawPic(CtlPanelSX + 56,CtlPanelSY,CP_PADDLEWARPIC);\r
1630         VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelSY + 12,HiliteColor ^ BackColor);\r
1631         VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelEY - 7,HiliteColor ^ BackColor);\r
1632         USL_PlayPong();\r
1633 \r
1634         return(true);\r
1635 }\r
1636 \r
1637 //      Flag management stuff\r
1638 static void\r
1639 USL_ClearFlags(UserItemGroup far *node)\r
1640 {\r
1641         UserItem        far *i;\r
1642 \r
1643         if (!node->items)\r
1644                 return;\r
1645 \r
1646         for (i = node->items;i->type != uii_Bad;i++)\r
1647         {\r
1648                 i->flags &= ~UISelectFlags;\r
1649                 if (i->child)\r
1650                         USL_ClearFlags((UserItemGroup far *)i->child);\r
1651         }\r
1652 }\r
1653 \r
1654 static int\r
1655 USL_FindPushedItem(UserItemGroup far *group)\r
1656 {\r
1657         word            i;\r
1658         UserItem        far *item;\r
1659 \r
1660         for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
1661                 if (item->flags & ui_Pushed)\r
1662                         return(i);\r
1663         return(-1);\r
1664 }\r
1665 \r
1666 static void\r
1667 USL_SelectItem(UserItemGroup far *group,word index,boolean draw)\r
1668 {\r
1669         UserItem        far *item;\r
1670 \r
1671         if (index != group->cursor)\r
1672         {\r
1673                 item = &group->items[group->cursor];\r
1674                 item->flags &= ~ui_Selected;\r
1675                 if (draw)\r
1676                         USL_DrawItem(item);\r
1677         }\r
1678 \r
1679         group->cursor = index;\r
1680         item = &group->items[group->cursor];\r
1681         group->items[group->cursor].flags |= ui_Selected;\r
1682         if (draw)\r
1683                 USL_DrawItem(item);\r
1684 }\r
1685 \r
1686 static void\r
1687 USL_PushItem(UserItemGroup far *group,word index,boolean draw)\r
1688 {\r
1689         word            i;\r
1690         UserItem        far *item;\r
1691 \r
1692         USL_SelectItem(group,index,draw);\r
1693         for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
1694         {\r
1695                 if (item->type != uii_RadioButton)\r
1696                         continue;\r
1697 \r
1698                 if (i == index)\r
1699                 {\r
1700                         item->flags |= ui_Pushed;\r
1701                         if (draw)\r
1702                                 USL_DrawItem(item);\r
1703                 }\r
1704                 else if (item->flags & ui_Pushed)\r
1705                 {\r
1706                         item->flags &= ~ui_Pushed;\r
1707                         if (draw)\r
1708                                 USL_DrawItem(item);\r
1709                 }\r
1710         }\r
1711 }\r
1712 \r
1713 static void\r
1714 USL_NextItem(void)\r
1715 {\r
1716         if (topcard->items[topcard->cursor + 1].type == uii_Bad)\r
1717                 return;\r
1718         USL_SelectItem(topcard,topcard->cursor + 1,true);\r
1719 }\r
1720 \r
1721 static void\r
1722 USL_PrevItem(void)\r
1723 {\r
1724         if (!topcard->cursor)\r
1725                 return;\r
1726         USL_SelectItem(topcard,topcard->cursor - 1,true);\r
1727 }\r
1728 \r
1729 static void\r
1730 USL_SetupCard(void)\r
1731 {\r
1732         BottomS1 = "Arrows move";\r
1733         BottomS2 = "Enter selects";\r
1734         BottomS3 = cstackptr? "ESC to back out" : "ESC to quit";\r
1735 \r
1736         USL_SelectItem(topcard,topcard->cursor,false);\r
1737         USL_DrawCtlPanel();     // Contents?\r
1738 }\r
1739 \r
1740 static void\r
1741 USL_DownLevel(UserItemGroup far *group)\r
1742 {\r
1743         if (!group)\r
1744                 Quit("USL_DownLevel() - nil card");\r
1745         USL_PushCard(group);\r
1746         if (group->custom && group->custom(uic_SetupCard,nil))\r
1747                 USL_PopCard();\r
1748         USL_SetupCard();\r
1749 }\r
1750 \r
1751 static void\r
1752 USL_UpLevel(void)\r
1753 {\r
1754         if (!cstackptr)\r
1755         {\r
1756                 USL_ConfirmComm(uc_Quit);\r
1757                 return;\r
1758         }\r
1759 \r
1760         if (topcard->items)\r
1761                 topcard->items[topcard->cursor].flags &= ~ui_Selected;\r
1762         USL_PopCard();\r
1763         USL_SetupCard();\r
1764 }\r
1765 \r
1766 static void\r
1767 USL_DoItem(void)\r
1768 {\r
1769         // DEBUG - finish this routine\r
1770         UserItem                far *item;\r
1771 \r
1772         item = &topcard->items[topcard->cursor];\r
1773         if (item->flags & ui_Disabled)\r
1774                 SD_PlaySound(NOWAYSND);\r
1775         else\r
1776         {\r
1777                 switch (item->type)\r
1778                 {\r
1779                 case uii_Button:\r
1780                         if (!(topcard->custom && topcard->custom(uic_Hit,item)))\r
1781                                 USL_ConfirmComm(item->comm);\r
1782                         break;\r
1783                 case uii_RadioButton:\r
1784                         USL_PushItem(topcard,topcard->cursor,true);\r
1785                         break;\r
1786                 case uii_Folder:\r
1787                         USL_DownLevel(item->child);\r
1788                         break;\r
1789                 }\r
1790         }\r
1791 }\r
1792 \r
1793 static void\r
1794 USL_SetControlValues(void)\r
1795 {\r
1796         int sndindex;\r
1797 \r
1798         sndindex = SoundMode;\r
1799         if (sndindex == sdm_AdLib && QuietFX)\r
1800                 sndindex++;\r
1801 \r
1802         USL_PushItem(&soundgroup,sndindex,false);\r
1803         USL_PushItem(&musicgroup,MusicMode,false);\r
1804         if (!AdLibPresent)\r
1805         {\r
1806                 soundi[2].flags |= ui_Disabled; // AdLib sound effects\r
1807                 soundi[3].flags |= ui_Disabled; // Quiet AdLib sound effects\r
1808                 musici[1].flags |= ui_Disabled; // AdLib music\r
1809         }\r
1810 \r
1811 #ifdef CAT3D\r
1812         if (!JoysPresent[0])\r
1813                 configi[3].flags |= ui_Disabled;\r
1814         if (!JoysPresent[1])\r
1815                 configi[4].flags |= ui_Disabled;\r
1816 #else\r
1817         if (!JoysPresent[0])\r
1818                 configi[4].flags |= ui_Disabled;\r
1819         if (!JoysPresent[1])\r
1820                 configi[5].flags |= ui_Disabled;\r
1821         if (!JoysPresent[0] && !JoysPresent[1])\r
1822                 configi[6].flags |= ui_Disabled;\r
1823 #endif\r
1824 \r
1825         rooti[4].text = ingame? "RETURN TO GAME" : "RETURN TO DEMO";\r
1826         if (!ingame)\r
1827         {\r
1828                 rooti[2].flags |= ui_Disabled;  // Save Game\r
1829                 rooti[5].flags |= ui_Disabled;  // End Game\r
1830         }\r
1831         rootgroup.cursor = ingame? 4 : 0;\r
1832         USL_SetOptionsText();\r
1833         // DEBUG - write the rest of this\r
1834 }\r
1835 \r
1836 ///////////////////////////////////////////////////////////////////////////\r
1837 //\r
1838 //      USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the\r
1839 //              values of all the appropriate variables\r
1840 //\r
1841 ///////////////////////////////////////////////////////////////////////////\r
1842 static void\r
1843 USL_SetUpCtlPanel(void)\r
1844 {\r
1845         int     i;\r
1846 \r
1847         // Cache in all of the stuff for the control panel\r
1848         CA_UpLevel();\r
1849         for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)\r
1850                 CA_MarkGrChunk(i);\r
1851         for (i = PADDLE_LUMP_START;i <= PADDLE_LUMP_END;i++)\r
1852                 CA_MarkGrChunk(i);\r
1853         CA_MarkGrChunk(STARTFONT+1);            // Little font\r
1854         CA_MarkGrChunk(CP_MENUMASKPICM);        // Mask for dialogs\r
1855         CA_CacheMarks("Control Panel");\r
1856         CA_LoadAllSounds();\r
1857 \r
1858         // Do some other setup\r
1859         fontnumber = 1;\r
1860         US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);\r
1861         fontcolor = F_BLACK;\r
1862 #ifdef CAT3D\r
1863         VW_Bar (0,0,320,200,3); // CAT3D patch\r
1864 #else\r
1865         VW_ClearVideo(3);\r
1866 #endif\r
1867         RF_FixOfs();\r
1868         VW_InitDoubleBuffer();\r
1869 \r
1870         Communication = uc_None;\r
1871         USL_ClearFlags(&rootgroup);\r
1872         USL_SetControlValues();\r
1873         USL_SetupStack();\r
1874         USL_SetupCard();\r
1875 \r
1876         if (ingame)\r
1877                 GameIsDirty = true;\r
1878 \r
1879         IN_ClearKeysDown();\r
1880 }\r
1881 \r
1882 static void\r
1883 USL_HandleComm(UComm comm)\r
1884 {\r
1885         switch (comm)\r
1886         {\r
1887         case uc_Loaded:\r
1888         case uc_Return:\r
1889                 break;\r
1890         case uc_Abort:\r
1891                 abortgame = true;\r
1892                 break;\r
1893         case uc_Quit:\r
1894                 QuitToDos = true;\r
1895                 break;\r
1896         case uc_SEasy:\r
1897                 restartgame = gd_Easy;\r
1898                 break;\r
1899         case uc_SNormal:\r
1900                 restartgame = gd_Normal;\r
1901                 break;\r
1902         case uc_SHard:\r
1903                 restartgame = gd_Hard;\r
1904                 break;\r
1905 \r
1906         default:\r
1907                 Quit("USL_HandleComm() - unknown");\r
1908                 break;\r
1909         }\r
1910 }\r
1911 \r
1912 static void\r
1913 USL_GetControlValues(void)\r
1914 {\r
1915         int     i;\r
1916 \r
1917         // DEBUG - write the rest of this\r
1918         i = USL_FindPushedItem(&soundgroup);\r
1919         if (i == 3)\r
1920         {\r
1921                 QuietFX = true;\r
1922                 i--;\r
1923         }\r
1924         else\r
1925         {\r
1926                 QuietFX = false;\r
1927         }\r
1928         if (i != SoundMode)\r
1929                 SD_SetSoundMode(i);\r
1930 \r
1931         i = USL_FindPushedItem(&musicgroup);\r
1932         if (i != MusicMode)\r
1933                 SD_SetMusicMode(i);\r
1934 }\r
1935 \r
1936 ///////////////////////////////////////////////////////////////////////////\r
1937 //\r
1938 //      USL_TearDownCtlPanel() - Given the state of the control panel, sets the\r
1939 //              modes and values as appropriate\r
1940 //\r
1941 ///////////////////////////////////////////////////////////////////////////\r
1942 static void\r
1943 USL_TearDownCtlPanel(void)\r
1944 {\r
1945         USL_GetControlValues();\r
1946         if (Communication)\r
1947                 USL_HandleComm(Communication);\r
1948 \r
1949         fontnumber = 0; // Normal font\r
1950         fontcolor = F_BLACK;\r
1951         if (restartgame && USL_ResetGame)\r
1952                 USL_ResetGame();\r
1953         else if (QuitToDos)\r
1954         {\r
1955                 if (tedlevel)\r
1956                         TEDDeath();\r
1957                 else\r
1958                 {\r
1959                         US_CenterWindow(20,3);\r
1960                         fontcolor = F_SECONDCOLOR;\r
1961                         US_PrintCentered("Quitting...");\r
1962                         fontcolor = F_BLACK;\r
1963                         VW_UpdateScreen();\r
1964                         Quit(nil);\r
1965                 }\r
1966         }\r
1967 \r
1968         IN_ClearKeysDown();\r
1969         SD_WaitSoundDone();\r
1970 #ifdef CAT3D\r
1971         VW_Bar (0,0,320,200,3); // CAT3D patch\r
1972 #else\r
1973         VW_ClearVideo(3);\r
1974 #endif\r
1975         CA_DownLevel();\r
1976         CA_LoadAllSounds();\r
1977 }\r
1978 \r
1979 ///////////////////////////////////////////////////////////////////////////\r
1980 //\r
1981 //      US_ControlPanel() - This is the main routine for the control panel\r
1982 //\r
1983 ///////////////////////////////////////////////////////////////////////////\r
1984 #define MoveMin 40\r
1985 void\r
1986 US_ControlPanel(void)\r
1987 {\r
1988 extern void HelpScreens(void);\r
1989 \r
1990         boolean         resetitem,on;\r
1991         word            i;\r
1992         int                     ydelta;\r
1993         longword        flashtime;\r
1994         UserItem        far *item;\r
1995         CursorInfo      cursorinfo;\r
1996 \r
1997 #if 0\r
1998         // DEBUG!!!\r
1999         {\r
2000                 USL_SetUpCtlPanel();\r
2001                 Communication = uc_Loaded;\r
2002                 CtlPanelDone = true;\r
2003                 loadedgame = true;\r
2004                 USL_TearDownCtlPanel();\r
2005                 return;\r
2006         }\r
2007 #endif\r
2008 \r
2009         if ((LastScan < sc_F1) || (LastScan > sc_F10))\r
2010                 IN_ClearKeysDown();\r
2011 \r
2012         USL_SetUpCtlPanel();\r
2013         USL_DrawCtlPanel();\r
2014 \r
2015         ydelta = 0;\r
2016         for (CtlPanelDone = false,resetitem = on = true;!CtlPanelDone;)\r
2017         {\r
2018                 item = &(topcard->items[topcard->cursor]);\r
2019 \r
2020                 if (resetitem)\r
2021                 {\r
2022                         flashtime = TimeCount + (TickBase / 2);\r
2023                         resetitem = false;\r
2024                 }\r
2025 \r
2026                 if (TimeCount >= flashtime)\r
2027                 {\r
2028                         on ^= true;\r
2029                         resetitem = true;\r
2030                         if (!on)\r
2031                                 item->flags &= ~ui_Selected;\r
2032                         USL_DrawItemIcon(item);\r
2033                         item->flags |= ui_Selected;\r
2034                 }\r
2035 \r
2036                 VW_UpdateScreen();\r
2037 \r
2038                 if (LastScan)\r
2039                 {\r
2040                         switch (LastScan)\r
2041                         {\r
2042                         case sc_UpArrow:\r
2043                                 USL_PrevItem();\r
2044                                 resetitem = true;\r
2045                                 break;\r
2046                         case sc_DownArrow:\r
2047                                 USL_NextItem();\r
2048                                 resetitem = true;\r
2049                                 break;\r
2050                         case sc_Return:\r
2051                                 USL_DoItem();\r
2052                                 resetitem = true;\r
2053                                 break;\r
2054                         case sc_Escape:\r
2055                                 USL_UpLevel();\r
2056                                 resetitem = true;\r
2057                                 break;\r
2058 #ifndef KEEN6\r
2059                         case sc_F1:\r
2060                                 HelpScreens();\r
2061                                 USL_DrawCtlPanel();\r
2062                                 resetitem = true;\r
2063                                 break;\r
2064 #endif\r
2065                         }\r
2066 \r
2067                         if\r
2068                         (\r
2069                                 (!resetitem)\r
2070                         &&      (\r
2071                                         (LastScan == KbdDefs[0].button0)\r
2072                                 ||      (LastScan == KbdDefs[0].button1)\r
2073                                 )\r
2074                         )\r
2075                         {\r
2076                                 USL_DoItem();\r
2077                                 resetitem = true;\r
2078                         }\r
2079 \r
2080                         if (!resetitem)\r
2081                         {\r
2082                                 for (item = topcard->items,i = 0;item->type != uii_Bad;item++,i++)\r
2083                                 {\r
2084                                         if (item->hotkey == LastScan)\r
2085                                         {\r
2086                                                 USL_SelectItem(topcard,i,true);\r
2087                                                 resetitem = true;\r
2088                                                 break;\r
2089                                         }\r
2090                                 }\r
2091                         }\r
2092 \r
2093                         IN_ClearKeysDown();\r
2094                 }\r
2095                 else\r
2096                 {\r
2097                         IN_ReadCursor(&cursorinfo);\r
2098                         ydelta += cursorinfo.y;\r
2099                         if (cursorinfo.button0)\r
2100                         {\r
2101                                 do\r
2102                                 {\r
2103                                         IN_ReadCursor(&cursorinfo);\r
2104                                 } while (cursorinfo.button0);\r
2105                                 USL_DoItem();\r
2106                                 resetitem = true;\r
2107                         }\r
2108                         else if (cursorinfo.button1)\r
2109                         {\r
2110                                 do\r
2111                                 {\r
2112                                         IN_ReadCursor(&cursorinfo);\r
2113                                 } while (cursorinfo.button1);\r
2114                                 USL_UpLevel();\r
2115                                 resetitem = true;\r
2116                         }\r
2117                         else if (ydelta < -MoveMin)\r
2118                         {\r
2119                                 ydelta += MoveMin;\r
2120                                 USL_PrevItem();\r
2121                                 resetitem = true;\r
2122                         }\r
2123                         else if (ydelta > MoveMin)\r
2124                         {\r
2125                                 ydelta -= MoveMin;\r
2126                                 USL_NextItem();\r
2127                                 resetitem = true;\r
2128                         }\r
2129                 }\r
2130         }\r
2131 \r
2132         USL_TearDownCtlPanel();\r
2133 }\r
2134 \r
2135 #ifdef KEEN6\r
2136 \r
2137 boolean US_ManualCheck(void)\r
2138 {\r
2139         typedef struct {\r
2140                 char far *name;\r
2141                 int shapenum;\r
2142                 int x, y;\r
2143         } creatureinfo;\r
2144 \r
2145         static creatureinfo list[] = {\r
2146                 {"BIP",       BIPSHIPRSPR,        -2,  0},\r
2147                 {"BABOBBA",   BABOBBAR1SPR,        0,  0},\r
2148                 {"BLORB",     BLORB1SPR,          -2,  0},\r
2149                 {"GIK",       GIKWALKR1SPR,       -1,  0},\r
2150                 {"CEILICK",   CEILICK1SPR,         0,  0},\r
2151                 {"BLOOGLET",  RBLOOGLETWALKR1SPR, -2,  0},\r
2152                 {"BLOOGUARD", BLOOGUARDWALKL1SPR, -3, -1},\r
2153                 {"FLECT",     FLECTSTANDSPR,      -1,  0},\r
2154                 {"BOBBA",     BOBBAR1SPR,         -2,  0},\r
2155                 {"NOSPIKE",   NOSPIKESTANDSPR,    -2,  0},\r
2156                 {"ORBATRIX",  ORBATRIXR1SPR,      -2,  1},\r
2157                 {"FLEEX",     FLEEXWALKR1SPR,     -2,  0}\r
2158         };\r
2159 \r
2160         boolean correct;\r
2161         char far *name;\r
2162         char c;\r
2163         char *ptr;\r
2164         unsigned spriteheight, spritewidth;\r
2165         int x, y;\r
2166         int editwidth;\r
2167         creatureinfo info;\r
2168         char strbuf[16];\r
2169 \r
2170         if (checkpassed)\r
2171                 return true;\r
2172 \r
2173         correct = false;\r
2174         if (listindex == -1)\r
2175         {\r
2176                 _AH = 0x2C;     // get time\r
2177                 geninterrupt(0x21);\r
2178                 x = _CH;        // store hours\r
2179                 _AH = 0x2A;     // get date\r
2180                 geninterrupt(0x21);\r
2181                 y = _DL;        // store day\r
2182 \r
2183                 listindex = (x + y) % (int)(sizeof(list)/sizeof(creatureinfo));\r
2184         }\r
2185 \r
2186         CA_UpLevel();\r
2187         info = list[listindex];\r
2188         name = info.name;\r
2189         CA_ClearMarks();\r
2190         CA_MarkGrChunk(info.shapenum);\r
2191         CA_CacheMarks(NULL);\r
2192 \r
2193         VWB_Bar(0, 0, 320, 200, BackColor);\r
2194         spritewidth = spritetable[info.shapenum - STARTSPRITES].width;\r
2195         spriteheight = spritetable[info.shapenum - STARTSPRITES].height;\r
2196         US_CenterWindow(30, (spriteheight+41)/8 + 1);\r
2197         PrintY = WindowY + 2;\r
2198         US_CPrint("What is the name of this creature?");\r
2199 \r
2200         x = WindowX + (WindowW-spritewidth)/2 + info.x*8;\r
2201         y = WindowY + 15;\r
2202         if (info.shapenum == CEILICK1SPR)\r
2203         {\r
2204                 y++;\r
2205         }\r
2206         else\r
2207         {\r
2208                 y += info.y * 8;\r
2209         }\r
2210         VWB_DrawSprite(x, y, info.shapenum);\r
2211 \r
2212         y = WindowY + WindowH - 16;\r
2213         editwidth = 100;\r
2214         x = WindowX + (WindowW - 100) / 2;\r
2215         VWB_Bar(x, y, editwidth, 14, BLACK);\r
2216         VWB_Bar(x+1, y+1, editwidth-2, 12, WHITE);\r
2217         x += 2;\r
2218         y += 2;\r
2219         editwidth -= 8;\r
2220         VW_UpdateScreen();\r
2221 \r
2222         if (US_LineInput(x, y, strbuf, NULL, true, sizeof(strbuf), editwidth))\r
2223         {\r
2224                 ptr = strbuf;\r
2225                 correct = true;\r
2226                 while (*name)\r
2227                 {\r
2228                         c = *ptr;\r
2229                         if ((islower(c)? _toupper(c) : c) != *name)\r
2230                         {\r
2231                                 correct = false;\r
2232                         }\r
2233 \r
2234                         ptr++;\r
2235                         name++;\r
2236                 }\r
2237                 if (*ptr)\r
2238                 {\r
2239                         correct = false;\r
2240                 }\r
2241 \r
2242                 if (!correct)\r
2243                 {\r
2244                         VWB_Bar(0, 0, 320, 200, BackColor);\r
2245                         US_CenterWindow(35, 5);\r
2246                         PrintY += 11;\r
2247                         US_CPrint("Sorry, that's not quite right.");\r
2248                         US_CPrint("Please check your manual and try again.");\r
2249                         VW_UpdateScreen();\r
2250                         IN_Ack();\r
2251                 }\r
2252         }\r
2253 \r
2254         VWB_Bar(0, 0, 320, 200, BackColor);\r
2255         CA_DownLevel();\r
2256         checkpassed = correct;\r
2257         return correct;\r
2258 }\r
2259 \r
2260 #endif