]> 4ch.mooo.com Git - 16.git/blob - 16/cawat/ID_US_2.C
35828037834ad1242cede7f2a4e06055dad2923e
[16.git] / 16 / cawat / ID_US_2.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 //\r
20 //      ID Engine\r
21 //      ID_US.c - User Manager - User interface\r
22 //      v1.1d1\r
23 //      By Jason Blochowiak\r
24 //      Hacked up for Catacomb 3D\r
25 //\r
26 \r
27 #include "ID_HEADS.H"\r
28 #pragma hdrstop\r
29 \r
30 #pragma warn    -pia\r
31 \r
32 //      Special imports\r
33 extern  boolean         showscorebox;\r
34 #ifdef  KEEN\r
35 extern  boolean         oldshooting;\r
36 extern  ScanCode        firescan;\r
37 #else\r
38                 ScanCode        firescan;\r
39 #endif\r
40 \r
41 //      Global variables\r
42                 boolean         ingame,abortgame,loadedgame;\r
43                 GameDiff        restartgame = gd_Continue;\r
44 \r
45 //      Internal variables\r
46 static  boolean         GameIsDirty,\r
47                                         QuitToDos,\r
48                                         CtlPanelDone;\r
49 \r
50 //      Forward reference prototypes\r
51 static void     USL_SetupCard(void);\r
52 \r
53 //      Control panel data\r
54 \r
55 #define CtlPanelSX      74\r
56 #define CtlPanelSY      48\r
57 #define CtlPanelEX      234\r
58 #define CtlPanelEY      150\r
59 #define CtlPanelW       (CtlPanelEX - CtlPanelSX)\r
60 #define CtlPanelH       (CtlPanelEY - CtlPanelSY)\r
61 \r
62 #define TileBase        92\r
63 \r
64 // DEBUG - CGA\r
65 #define BackColor               0\r
66 #define HiliteColor             (BackColor ^ 12)\r
67 #define NohiliteColor   (BackColor ^ 4)\r
68 \r
69 typedef enum\r
70                 {\r
71                         uc_None,\r
72                         uc_Return,\r
73                         uc_Abort,\r
74                         uc_Quit,\r
75                         uc_Loaded,\r
76                         uc_SEasy,\r
77                         uc_SNormal,\r
78                         uc_SHard,\r
79                 } UComm;\r
80 typedef enum\r
81                 {\r
82                         uii_Bad,\r
83                         uii_Button,uii_RadioButton,uii_Folder\r
84                 } UIType;\r
85 typedef enum\r
86                 {\r
87                         ui_Normal = 0,\r
88                         ui_Pushed = 1,\r
89                         ui_Selected = 2,\r
90                         ui_Disabled = 4,\r
91                         ui_Separated = 8\r
92                 } UIFlags;\r
93 #define UISelectFlags (ui_Pushed | ui_Selected | ui_Disabled)\r
94 \r
95 typedef enum\r
96                 {\r
97                         uic_SetupCard,uic_DrawCard,uic_TouchupCard,\r
98                         uic_DrawIcon,uic_Draw,uic_Hit\r
99                 } UserCall;\r
100 \r
101 typedef struct  UserItem\r
102                 {\r
103                                 UIType                  type;\r
104                                 UIFlags                 flags;\r
105                                 ScanCode                hotkey;\r
106                                 char                    *text;\r
107                                 UComm                   comm;\r
108                                 void                    far *child;     // Should be (UserItemGroup *)\r
109 \r
110                                 word                    x,y;\r
111                 } UserItem;\r
112 typedef struct  UserItemGroup\r
113                 {\r
114                                 word                    x,y;\r
115                                 graphicnums             title;\r
116                                 ScanCode                hotkey;\r
117                                 UserItem                far *items;\r
118                                 boolean                 (*custom)(UserCall,struct UserItem far *);      // Custom routine\r
119 \r
120                                 word                    cursor;\r
121                 struct  UserItemGroup   far *parent;\r
122                 } UserItemGroup;\r
123 \r
124 static  char            *BottomS1,*BottomS2,*BottomS3;\r
125 static  UComm           Communication;\r
126 static  ScanCode        *KeyMaps[] =\r
127                                         {\r
128                                                 &KbdDefs[0].button0,\r
129                                                 &KbdDefs[0].button1,\r
130                                                 &firescan,\r
131                                                 &KbdDefs[0].upleft,\r
132                                                 &KbdDefs[0].up,\r
133                                                 &KbdDefs[0].upright,\r
134                                                 &KbdDefs[0].right,\r
135                                                 &KbdDefs[0].downright,\r
136                                                 &KbdDefs[0].down,\r
137                                                 &KbdDefs[0].downleft,\r
138                                                 &KbdDefs[0].left\r
139                                         };\r
140 \r
141 // Custom routine prototypes\r
142 static  boolean USL_ConfigCustom(UserCall call,struct UserItem far *item),\r
143                                 USL_KeyCustom(UserCall call,struct UserItem far *item),\r
144                                 USL_KeySCustom(UserCall call,struct UserItem far *item),\r
145                                 USL_Joy1Custom(UserCall call,struct UserItem far *item),\r
146                                 USL_Joy2Custom(UserCall call,struct UserItem far *item),\r
147                                 USL_LoadCustom(UserCall call,struct UserItem far *item),\r
148                                 USL_SaveCustom(UserCall call,struct UserItem far *item),\r
149                                 USL_ScoreCustom(UserCall call,struct UserItem far *item),\r
150                                 USL_CompCustom(UserCall call,struct UserItem far *item);\r
151 #ifdef KEEN\r
152                                 USL_TwoCustom(UserCall call,struct UserItem far *item),\r
153 #endif\r
154 //                              USL_PongCustom(UserCall call,struct UserItem far *item);\r
155 \r
156 #define DefButton(key,text)                             uii_Button,ui_Normal,key,text\r
157 #define DefRButton(key,text)                    uii_RadioButton,ui_Normal,key,text\r
158 #define DefFolder(key,text,child)               uii_Folder,ui_Normal,key,text,uc_None,child\r
159 #define CustomGroup(title,key,custom)   0,0,title,key,0,custom\r
160         UserItem far holder[] =\r
161         {\r
162                 {DefButton(sc_None,"DEBUG")},\r
163                 {uii_Bad}\r
164         };\r
165         UserItemGroup   far holdergroup = {0,0,CP_MAINMENUPIC,sc_None,holder};\r
166 \r
167         // Sound menu\r
168         UserItem far soundi[] =\r
169         {\r
170                 {DefRButton(sc_N,"NO SOUND EFFECTS")},\r
171                 {DefRButton(sc_P,"PC SPEAKER")},\r
172                 {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
173                 {uii_Bad}\r
174         };\r
175         UserItemGroup   far soundgroup = {8,0,CP_SOUNDMENUPIC,sc_None,soundi};\r
176 \r
177         // Music menu\r
178         UserItem far musici[] =\r
179         {\r
180                 {DefRButton(sc_N,"NO MUSIC")},\r
181                 {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
182                 {uii_Bad}\r
183         };\r
184         UserItemGroup   far musicgroup = {8,0,CP_MUSICMENUPIC,sc_None,musici};\r
185 \r
186         // New game menu\r
187         UserItem far newgamei[] =\r
188         {\r
189                 {DefButton(sc_E,"BEGIN EASY GAME"),uc_SEasy},\r
190                 {DefButton(sc_N,"BEGIN NORMAL GAME"),uc_SNormal},\r
191                 {DefButton(sc_H,"BEGIN HARD GAME"),uc_SHard},\r
192                 {uii_Bad}\r
193         };\r
194         UserItemGroup   far newgamegroup = {8,0,CP_NEWGAMEMENUPIC,sc_None,newgamei,0,1};\r
195 \r
196         // Load/Save game menu\r
197         UserItem far loadsavegamei[] =\r
198         {\r
199                 {uii_Button,ui_Normal,sc_None},\r
200                 {uii_Button,ui_Normal,sc_None},\r
201                 {uii_Button,ui_Normal,sc_None},\r
202                 {uii_Button,ui_Normal,sc_None},\r
203                 {uii_Button,ui_Normal,sc_None},\r
204                 {uii_Button,ui_Normal,sc_None},\r
205                 {uii_Bad}\r
206         };\r
207         UserItemGroup   far loadgamegroup = {4,3,CP_LOADMENUPIC,sc_None,loadsavegamei,USL_LoadCustom};\r
208         UserItemGroup   far savegamegroup = {4,3,CP_SAVEMENUPIC,sc_None,loadsavegamei,USL_SaveCustom};\r
209 \r
210         // Options menu\r
211         UserItemGroup   far scoregroup = {0,0,0,sc_None,0,USL_ScoreCustom};\r
212         UserItemGroup   far compgroup = {0,0,0,sc_None,0,USL_CompCustom};\r
213 #ifdef KEEN\r
214         UserItemGroup   far twogroup = {0,0,0,sc_None,0,USL_TwoCustom};\r
215 #endif\r
216         UserItem far optionsi[] =\r
217         {\r
218                 {DefFolder(sc_S,"",&scoregroup)},\r
219                 {DefFolder(sc_C,"",&compgroup)},\r
220 #ifdef KEEN\r
221                 {DefFolder(sc_T,"",&twogroup)},\r
222 #endif\r
223                 {uii_Bad}\r
224         };\r
225         UserItemGroup   far optionsgroup = {8,0,CP_OPTIONSMENUPIC,sc_None,optionsi};\r
226 \r
227         // Keyboard menu\r
228         UserItem far keyi[] =\r
229         {\r
230                 {DefButton(sc_None,"UP & LEFT")},\r
231                 {DefButton(sc_None,"UP")},\r
232                 {DefButton(sc_None,"UP & RIGHT")},\r
233                 {DefButton(sc_None,"RIGHT")},\r
234                 {DefButton(sc_None,"DOWN & RIGHT")},\r
235                 {DefButton(sc_None,"DOWN")},\r
236                 {DefButton(sc_None,"DOWN & LEFT")},\r
237                 {DefButton(sc_None,"LEFT")},\r
238                 {uii_Bad}\r
239         };\r
240         UserItemGroup   far keygroup = {0,0,CP_KEYMOVEMENTPIC,sc_None,keyi,USL_KeyCustom};\r
241         UserItem far keybi[] =\r
242         {\r
243 #ifdef  KEEN\r
244                 {DefButton(sc_J,"JUMP")},\r
245                 {DefButton(sc_P,"POGO")},\r
246                 {DefButton(sc_F,"FIRE")},\r
247 #endif\r
248 #ifdef  CAT3D\r
249                 {DefButton(sc_J,"FIRE")},\r
250                 {DefButton(sc_P,"STRAFE")},\r
251 #endif\r
252 #ifdef  CPD\r
253                 {DefButton(sc_J,"SHOOT")},\r
254                 {DefButton(sc_P,"BOMB")},\r
255 #endif\r
256                 {uii_Bad}\r
257         };\r
258         UserItemGroup   far keybgroup = {0,0,CP_KEYBUTTONPIC,sc_None,keybi,USL_KeyCustom};\r
259         UserItem far keysi[] =\r
260         {\r
261                 {DefFolder(sc_M,"MOVEMENT",&keygroup)},\r
262                 {DefFolder(sc_B,"BUTTONS",&keybgroup)},\r
263                 {uii_Bad}\r
264         };\r
265         UserItemGroup   far keysgroup = {8,0,CP_KEYBOARDMENUPIC,sc_None,keysi,USL_KeySCustom};\r
266 \r
267         // Joystick #1 & #2\r
268         UserItemGroup   far joy1group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy1Custom)};\r
269         UserItemGroup   far joy2group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy2Custom)};\r
270 \r
271         // Config menu\r
272         UserItem far configi[] =\r
273         {\r
274                 {DefFolder(sc_S,"SOUND",&soundgroup)},\r
275                 {DefFolder(sc_M,"MUSIC",&musicgroup)},\r
276                 {uii_Folder,ui_Separated,sc_K,"USE KEYBOARD",uc_None,&keysgroup},\r
277                 {DefFolder(sc_None,"USE JOYSTICK #1",&joy1group)},\r
278                 {DefFolder(sc_None,"USE JOYSTICK #2",&joy2group)},\r
279                 {uii_Bad}\r
280         };\r
281         UserItemGroup   far configgroup = {8,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
282 \r
283         // Main menu\r
284 //      UserItemGroup   far ponggroup = {0,0,0,sc_None,0,USL_PongCustom};\r
285         UserItem far rooti[] =\r
286         {\r
287                 {DefFolder(sc_N,"NEW GAME",&newgamegroup)},\r
288                 {DefFolder(sc_L,"LOAD GAME",&loadgamegroup)},\r
289                 {DefFolder(sc_S,"SAVE GAME",&savegamegroup)},\r
290                 {DefFolder(sc_C,"CONFIGURE",&configgroup)},\r
291                 {DefButton(sc_R,nil),uc_Return},        // Return to Game/Demo\r
292                 {DefButton(sc_E,"END GAME"),uc_Abort},\r
293 //              {DefFolder(sc_B,"SKULL 'N' BONES",&ponggroup)},\r
294                 {DefButton(sc_Q,"QUIT"),uc_Quit},\r
295                 {uii_Bad}\r
296         };\r
297         UserItemGroup   far rootgroup = {32,4,CP_MAINMENUPIC,sc_None,rooti};\r
298 #undef  DefButton\r
299 #undef  DefFolder\r
300 \r
301 #define MaxCards        7\r
302         word                    cstackptr;\r
303         UserItemGroup   far *cardstack[MaxCards],\r
304                                         far *topcard;\r
305 \r
306 //      Card stack code\r
307 static void\r
308 USL_SetupStack(void)\r
309 {\r
310         cstackptr = 0;\r
311         cardstack[0] = topcard = &rootgroup;\r
312 }\r
313 \r
314 static void\r
315 USL_PopCard(void)\r
316 {\r
317         if (!cstackptr)\r
318                 return;\r
319 \r
320         topcard = cardstack[--cstackptr];\r
321 }\r
322 \r
323 static void\r
324 USL_PushCard(UserItemGroup far *card)\r
325 {\r
326         if (cstackptr == MaxCards - 1)\r
327                 return;\r
328 \r
329         topcard = cardstack[++cstackptr] = card;\r
330 }\r
331 \r
332 static void\r
333 USL_DrawItemIcon(UserItem far *item)\r
334 {\r
335         word    flags,tile;\r
336 \r
337         if (topcard->custom && topcard->custom(uic_DrawIcon,item))\r
338                 return;\r
339 \r
340         flags = item->flags;\r
341         if (flags & ui_Disabled)\r
342                 tile = TileBase + ((flags & ui_Selected)? 5 : 4);\r
343         else if ((item->type == uii_RadioButton) && (!(flags & ui_Pushed)))\r
344                 tile = TileBase + ((flags & ui_Selected)? 3 : 2);\r
345         else\r
346                 tile = TileBase + ((flags & ui_Selected)? 1 : 0);\r
347         VWB_DrawTile8(item->x,item->y,tile);\r
348 }\r
349 \r
350 static void\r
351 USL_DrawItem(UserItem far *item)\r
352 {\r
353         if (topcard->custom && topcard->custom(uic_Draw,item))\r
354                 return;\r
355 \r
356         VWB_Bar(CtlPanelSX + 1,item->y,\r
357                         CtlPanelEX - CtlPanelSX - 1,8,BackColor);       // Clear out background\r
358         USL_DrawItemIcon(item);\r
359         if ((item->flags & ui_Selected) && !(item->flags & ui_Disabled))\r
360                 fontcolor = HiliteColor;\r
361         else\r
362                 fontcolor = NohiliteColor;\r
363         px = item->x + 8;\r
364         py = item->y + 1;\r
365         USL_DrawString(item->text);\r
366         fontcolor = F_BLACK;\r
367 }\r
368 \r
369 #define MyLine(y)       VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,12);\r
370 \r
371 static void\r
372 USL_DrawBottom(void)\r
373 {\r
374         word    w,h;\r
375 \r
376         fontcolor = NohiliteColor;\r
377 \r
378         px = CtlPanelSX + 4;\r
379         py = CtlPanelEY - 15;\r
380         USL_DrawString(BottomS1);\r
381 \r
382         USL_MeasureString(BottomS2,&w,&h);\r
383         px = CtlPanelEX - 4 - w;\r
384         USL_DrawString(BottomS2);\r
385 \r
386         USL_MeasureString(BottomS3,&w,&h);\r
387         px = CtlPanelSX + ((CtlPanelEX - CtlPanelSX - w) / 2);\r
388         py += h + 1;\r
389         USL_DrawString(BottomS3);\r
390 \r
391         fontcolor = F_WHITE;\r
392         MyLine(CtlPanelEY - 17);\r
393 }\r
394 \r
395 static void\r
396 USL_DrawCtlPanelContents(void)\r
397 {\r
398         int                             x,y;\r
399         UserItem                far *item;\r
400 \r
401         if (topcard->custom && topcard->custom(uic_DrawCard,nil))\r
402                 return;\r
403 \r
404         if (topcard->title)\r
405         {\r
406                 // Draw the title\r
407                 MyLine(CtlPanelSY + 7);\r
408                 VWB_DrawPic(CtlPanelSX + 6,CtlPanelSY,topcard->title);\r
409         }\r
410 \r
411         USL_DrawBottom();\r
412 \r
413         if (!topcard->items)\r
414                 return;\r
415 \r
416         x = topcard->x + CtlPanelSX;\r
417         if (x % 8)\r
418                 x += 8 - (x % 8);\r
419         y = topcard->y + CtlPanelSY + 12;\r
420         for (item = topcard->items;item->type != uii_Bad;item++)\r
421         {\r
422                 if (item->flags & ui_Separated)\r
423                         y += 8;\r
424 \r
425                 item->x = x;\r
426                 item->y = y;\r
427                 USL_DrawItem(item);\r
428                 y += 8;\r
429         }\r
430         if (topcard->custom)\r
431                 topcard->custom(uic_TouchupCard,nil);\r
432 }\r
433 \r
434 static void\r
435 USL_DrawCtlPanel(void)\r
436 {\r
437         if (topcard->items || topcard->title)\r
438         {\r
439                 // Draw the backdrop\r
440                 VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
441 \r
442                 // Draw the contents\r
443                 USL_DrawCtlPanelContents();\r
444         }\r
445 \r
446         // Refresh the screen\r
447         VW_UpdateScreen();\r
448 }\r
449 \r
450 static void\r
451 USL_DialogSetup(word w,word h,word *x,word *y)\r
452 {\r
453         VWB_DrawMPic(CtlPanelSX,CtlPanelSY,CP_MENUMASKPICM);\r
454 \r
455         *x = CtlPanelSX + ((CtlPanelW - w) / 2);\r
456         *y = CtlPanelSY + ((CtlPanelH - h) / 2);\r
457         VWB_Bar(*x,*y,w + 1,h + 1,BackColor);\r
458         VWB_Hlin(*x - 1,*x + w + 1,*y - 1,NohiliteColor);\r
459         VWB_Hlin(*x - 1,*x + w + 1,*y + h + 1,NohiliteColor);\r
460         VWB_Vlin(*y - 1,*y + h + 1,*x - 1,NohiliteColor);\r
461         VWB_Vlin(*y - 1,*y + h + 1,*x + w + 1,NohiliteColor);\r
462 }\r
463 \r
464 static void\r
465 USL_ShowLoadSave(char *s,char *name)\r
466 {\r
467         word    x,y,\r
468                         w,h,\r
469                         tw,sw;\r
470         char    msg[MaxGameName + 4];\r
471 \r
472         strcpy(msg,"'");\r
473         strcat(msg,name);\r
474         strcat(msg,"'");\r
475         USL_MeasureString(s,&sw,&h);\r
476         USL_MeasureString(msg,&w,&h);\r
477         tw = ((sw > w)? sw : w) + 6;\r
478         USL_DialogSetup(tw,(h * 2) + 2,&x,&y);\r
479         py = y + 2;\r
480         px = x + ((tw - sw) / 2);\r
481         USL_DrawString(s);\r
482         py += h;\r
483         px = x + ((tw - w) / 2);\r
484         USL_DrawString(msg);\r
485 \r
486         VW_UpdateScreen();\r
487 \r
488         IN_UserInput(100, true);\r
489 }\r
490 \r
491 static boolean\r
492 USL_CtlDialog(char *s1,char *s2,char *s3)\r
493 {\r
494         word            w,h,sh,\r
495                                 w1,w2,w3,\r
496                                 x,y;\r
497         ScanCode        c;\r
498         CursorInfo      cursorinfo;\r
499 \r
500         USL_MeasureString(s1,&w1,&h);\r
501         USL_MeasureString(s2,&w2,&h);\r
502         if (s3)\r
503                 USL_MeasureString(s3,&w3,&h);\r
504         else\r
505                 w3 = 0;\r
506         w = (w1 > w2)? ((w1 > w3)? w1 : w3) : ((w2 > w3)? w2 : w3);\r
507         w += 7;\r
508         sh = h;\r
509         h *= s3? 5 : 4;\r
510 \r
511         USL_DialogSetup(w,h,&x,&y);\r
512 \r
513         fontcolor = HiliteColor;\r
514         px = x + ((w - w1) / 2);\r
515         py = y + sh + 1;\r
516         USL_DrawString(s1);\r
517         py += (sh * 2) - 1;\r
518 \r
519         VWB_Hlin(x + 3,x + w - 3,py,NohiliteColor);\r
520         py += 2;\r
521 \r
522         fontcolor = NohiliteColor;\r
523         px = x + ((w - w2) / 2);\r
524         USL_DrawString(s2);\r
525         py += sh;\r
526 \r
527         if (s3)\r
528         {\r
529                 px = x + ((w - w3) / 2);\r
530                 USL_DrawString(s3);\r
531         }\r
532 \r
533         VW_UpdateScreen();\r
534 \r
535         IN_ClearKeysDown();\r
536         do\r
537         {\r
538                 IN_ReadCursor(&cursorinfo);\r
539                 if (cursorinfo.button0)\r
540                         c = sc_Y;\r
541                 else if (cursorinfo.button1)\r
542                         c = sc_Escape;\r
543                 else\r
544                         c = LastScan;\r
545         } while (c == sc_None);\r
546         do\r
547         {\r
548                 IN_ReadCursor(&cursorinfo);\r
549         } while (cursorinfo.button0 || cursorinfo.button1);\r
550 \r
551         IN_ClearKeysDown();\r
552         USL_DrawCtlPanel();\r
553         return(c == sc_Y);\r
554 }\r
555 \r
556 static boolean\r
557 USL_ConfirmComm(UComm comm)\r
558 {\r
559         boolean confirm,dialog;\r
560         char    *s1,*s2,*s3;\r
561 \r
562         if (!comm)\r
563                 Quit("USL_ConfirmComm() - empty comm");\r
564 \r
565         confirm = true;\r
566         dialog = false;\r
567         s3 = "ESC TO BACK OUT";\r
568         switch (comm)\r
569         {\r
570         case uc_Abort:\r
571                 s1 = "REALLY END CURRENT GAME?";\r
572                 s2 = "PRESS Y TO END IT";\r
573                 if (ingame && GameIsDirty)\r
574                         dialog = true;\r
575                 break;\r
576         case uc_Quit:\r
577                 s1 = "REALLY QUIT?";\r
578                 s2 = "PRESS Y TO QUIT";\r
579                 dialog = true;\r
580                 break;\r
581         case uc_Loaded:\r
582                 s1 = "YOU'RE IN A GAME";\r
583                 s2 = "PRESS Y TO LOAD GAME";\r
584                 if (ingame && GameIsDirty)\r
585                         dialog = true;\r
586                 break;\r
587         case uc_SEasy:\r
588         case uc_SNormal:\r
589         case uc_SHard:\r
590                 s1 = "YOU'RE IN A GAME";\r
591                 s2 = "PRESS Y FOR NEW GAME";\r
592                 if (ingame && GameIsDirty)\r
593                         dialog = true;\r
594                 break;\r
595         }\r
596 \r
597         confirm = dialog? USL_CtlDialog(s1,s2,s3) : true;\r
598         if (confirm)\r
599         {\r
600                 Communication = comm;\r
601                 CtlPanelDone = true;\r
602         }\r
603         return(confirm);\r
604 }\r
605 \r
606 ///////////////////////////////////////////////////////////////////////////\r
607 //\r
608 //      USL_HandleError() - Handles telling the user that there's been an error\r
609 //\r
610 ///////////////////////////////////////////////////////////////////////////\r
611 static void\r
612 USL_HandleError(int num)\r
613 {\r
614         char    buf[64];\r
615 \r
616         strcpy(buf,"Error: ");\r
617         if (num < 0)\r
618                 strcat(buf,"Unknown");\r
619         else if (num == ENOMEM)\r
620                 strcat(buf,"Disk is Full");\r
621         else if (num == EINVFMT)\r
622                 strcat(buf,"File is Incomplete");\r
623         else\r
624                 strcat(buf,sys_errlist[num]);\r
625 \r
626         VW_HideCursor();\r
627 \r
628         USL_CtlDialog(buf,"PRESS ANY KEY",nil);\r
629         VW_UpdateScreen();\r
630 \r
631         IN_ClearKeysDown();\r
632         IN_Ack();\r
633 \r
634         VW_ShowCursor();\r
635         VW_UpdateScreen();\r
636 }\r
637 \r
638 //      Custom routines\r
639 #if 0\r
640 static boolean\r
641 USL_GenericCustom(UserCall call,UserItem far *item)\r
642 {\r
643         boolean result;\r
644 \r
645         result = false;\r
646         switch (call)\r
647         {\r
648         }\r
649         return(result);\r
650 }\r
651 #endif\r
652 \r
653 static void\r
654 USL_SetOptionsText(void)\r
655 {\r
656         optionsi[0].text = showscorebox? "SCORE BOX (ON)" : "SCORE BOX (OFF)";\r
657         optionsi[1].text = compatability? "SVGA COMPATIBILITY (ON)" : "SVGA COMPATIBILITY (OFF)";\r
658 #ifdef KEEN\r
659         optionsi[2].text = oldshooting? "TWO-BUTTON FIRING (ON)" : "TWO-BUTTON FIRING (OFF)";\r
660 \r
661         keybi[2].flags &= ~ui_Disabled;\r
662         if (oldshooting)\r
663                 keybi[2].flags |= ui_Disabled;\r
664 #endif\r
665 }\r
666 \r
667 #pragma argsused\r
668 static boolean\r
669 USL_ScoreCustom(UserCall call,UserItem far *item)\r
670 {\r
671         if (call != uic_SetupCard)\r
672                 return(false);\r
673 \r
674         showscorebox ^= true;\r
675         USL_CtlDialog(showscorebox? "Score box now on" : "Score box now off",\r
676                                         "Press any key",nil);\r
677         USL_SetOptionsText();\r
678         return(true);\r
679 }\r
680 \r
681 #pragma argsused\r
682 static boolean\r
683 USL_CompCustom(UserCall call,UserItem far *item)\r
684 {\r
685         if (call != uic_SetupCard)\r
686                 return(false);\r
687 \r
688         compatability ^= true;\r
689         USL_CtlDialog(compatability? "SVGA compatibility now on" : "SVGA compatibility now off",\r
690                                         "Press any key",nil);\r
691         USL_SetOptionsText();\r
692         return(true);\r
693 }\r
694 \r
695 #ifdef  KEEN\r
696 #pragma argsused\r
697 static boolean\r
698 USL_TwoCustom(UserCall call,UserItem far *item)\r
699 {\r
700         if (call != uic_SetupCard)\r
701                 return(false);\r
702 \r
703         oldshooting ^= true;\r
704         USL_CtlDialog(oldshooting? "Two-button firing now on" : "Two-button firing now off",\r
705                                         "Press any key",nil);\r
706         USL_SetOptionsText();\r
707         return(true);\r
708 }\r
709 #endif\r
710 \r
711 static boolean\r
712 USL_ConfigCustom(UserCall call,UserItem far *item)\r
713 {\r
714 static  char    *CtlNames[] = {"KEYBOARD","KEYBOARD","JOYSTICK #1","JOYSTICK #2","MOUSE"};\r
715                 char    *s;\r
716                 word    w,h,\r
717                                 tw;\r
718 \r
719         if (call == uic_TouchupCard)\r
720         {\r
721                 s = "CONTROL: ";\r
722                 USL_MeasureString(s,&w,&h);\r
723                 tw = w;\r
724                 USL_MeasureString(CtlNames[Controls[0]],&w,&h);\r
725                 tw += w;\r
726                 py = CtlPanelEY - 18 - h;\r
727                 px = CtlPanelSX + ((CtlPanelW - tw) / 2);\r
728                 fontcolor = NohiliteColor;\r
729                 USL_DrawString(s);\r
730                 USL_DrawString(CtlNames[Controls[0]]);\r
731         }\r
732         item++; // Shut the compiler up\r
733         return(false);\r
734 }\r
735 \r
736 static void\r
737 USL_CKSetKey(UserItem far *item,word i)\r
738 {\r
739         boolean         on;\r
740         word            j;\r
741         ScanCode        scan;\r
742         longword        time;\r
743         CursorInfo      cursorinfo;\r
744 \r
745         on = false;\r
746         time = 0;\r
747         LastScan = sc_None;\r
748         fontcolor = HiliteColor;\r
749         do\r
750         {\r
751                 if (TimeCount >= time)\r
752                 {\r
753                         on ^= true;\r
754                         VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
755                         VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
756                         if (on)\r
757                                 VWB_DrawTile8(item->x + 90 + 16,item->y,TileBase + 8);\r
758                         VW_UpdateScreen();\r
759 \r
760                         time = TimeCount + (TickBase / 2);\r
761                 }\r
762 \r
763                 IN_ReadCursor(&cursorinfo);\r
764                 while (cursorinfo.button0 || cursorinfo.button1)\r
765                 {\r
766                         IN_ReadCursor(&cursorinfo);\r
767                         LastScan = sc_Escape;\r
768                 }\r
769 \r
770         asm     pushf\r
771         asm     cli\r
772                 if (LastScan == sc_LShift)\r
773                         LastScan = sc_None;\r
774         asm     popf\r
775         } while (!(scan = LastScan));\r
776 \r
777         if (scan != sc_Escape)\r
778         {\r
779                 for (j = 0,on = false;j < 11;j++)\r
780                 {\r
781                         if (j == i)\r
782                                 continue;\r
783                         if (*(KeyMaps[j]) == scan)\r
784                         {\r
785                                 on = true;\r
786                                 break;\r
787                         }\r
788                 }\r
789                 if (on)\r
790                         USL_CtlDialog("Key already used","Press a key",nil);\r
791                 else\r
792                         *(KeyMaps[i]) = scan;\r
793         }\r
794         IN_ClearKeysDown();\r
795 }\r
796 \r
797 #pragma argsused\r
798 static boolean\r
799 USL_KeySCustom(UserCall call,UserItem far *item)\r
800 {\r
801         if (call == uic_SetupCard)\r
802                 Controls[0] = ctrl_Keyboard;\r
803         return(false);\r
804 }\r
805 \r
806 #pragma argsused\r
807 static boolean\r
808 USL_KeyCustom(UserCall call,UserItem far *item)\r
809 {\r
810         boolean result;\r
811         word    i;\r
812 \r
813         result = false;\r
814         i = (topcard == &keygroup)? (3 + (item - keyi)) : (item - keybi);\r
815         switch (call)\r
816         {\r
817         case uic_SetupCard:\r
818                 Controls[0] = ctrl_Keyboard;\r
819                 break;\r
820         case uic_Draw:\r
821                 VWB_Bar(CtlPanelSX + 1,item->y,\r
822                                 CtlPanelEX - CtlPanelSX - 1,8,BackColor);       // Clear out background\r
823                 USL_DrawItemIcon(item);\r
824                 fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
825                 px = item->x + 8;\r
826                 py = item->y + 1;\r
827                 USL_DrawString(item->text);\r
828                 VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
829                 VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
830                 px = item->x + 90 + 6;\r
831                 py = item->y + 1;\r
832                 USL_DrawString(IN_GetScanName(*KeyMaps[i]));\r
833                 result = true;\r
834                 break;\r
835         case uic_Hit:\r
836                 USL_KeyCustom(uic_Draw,item);\r
837                 USL_CKSetKey(item,i);\r
838                 USL_DrawCtlPanel();\r
839                 result = true;\r
840                 break;\r
841         }\r
842         return(result);\r
843 }\r
844 \r
845 static void\r
846 USL_CJDraw(char *s1,char *s2)\r
847 {\r
848         word    w,h;\r
849 \r
850         USL_MeasureString(s1,&w,&h);\r
851         px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
852         py = CtlPanelEY - 34;\r
853         VWB_Bar(CtlPanelSX + 1,py,CtlPanelW - 2,h * 2,BackColor);\r
854         fontcolor = HiliteColor;\r
855         USL_DrawString(s1);\r
856         py += h;\r
857         USL_MeasureString(s2,&w,&h);\r
858         px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
859         USL_DrawString(s2);\r
860 }\r
861 \r
862 static boolean\r
863 USL_CJGet(word joy,word button,word x,word y,word *xaxis,word *yaxis)\r
864 {\r
865         boolean         on;\r
866         longword        time;\r
867 \r
868         while (IN_GetJoyButtonsDB(joy))\r
869                 if (LastScan == sc_Escape)\r
870                         return(false);\r
871 \r
872         on = false;\r
873         time = 0;\r
874         while (!(IN_GetJoyButtonsDB(joy) & (1 << button)))\r
875         {\r
876                 if (TimeCount >= time)\r
877                 {\r
878                         on ^= true;\r
879                         time = TimeCount + (TickBase / 2);\r
880                         VWB_DrawTile8(x,y,TileBase + on);\r
881                         VW_UpdateScreen();\r
882                 }\r
883 \r
884                 if (LastScan == sc_Escape)\r
885                         return(false);\r
886         }\r
887         IN_GetJoyAbs(joy,xaxis,yaxis);\r
888         return(true);\r
889 }\r
890 \r
891 static boolean\r
892 USL_ConfigJoystick(word joy)\r
893 {\r
894         word    x,y,\r
895                         minx,miny,\r
896                         maxx,maxy;\r
897 \r
898         BottomS1 = BottomS2 = "";\r
899         BottomS3 = "Esc to back out";\r
900         USL_DrawCtlPanel();\r
901         x = CtlPanelSX + 60;\r
902         y = CtlPanelSY + 19;\r
903         VWB_DrawPic(x,y,CP_JOYSTICKPIC);\r
904 \r
905         USL_CJDraw("Move Joystick to upper left","and press button #1");\r
906         VWB_DrawTile8(x + 24,y + 8,TileBase + 6);\r
907         VWB_DrawTile8(x + 8,y + 8,TileBase + 1);\r
908         VWB_DrawTile8(x + 8,y + 24,TileBase + 0);\r
909         VW_UpdateScreen();\r
910         if (!USL_CJGet(joy,0,x + 8,y + 8,&minx,&miny))\r
911                 return(false);\r
912 \r
913         USL_CJDraw("Move Joystick to lower right","and press button #2");\r
914         VWB_DrawTile8(x + 24,y + 8,TileBase - 25);\r
915         VWB_DrawTile8(x + 40,y + 24,TileBase + 7);\r
916         VWB_DrawTile8(x + 8,y + 8,TileBase + 0);\r
917         VWB_DrawTile8(x + 8,y + 24,TileBase + 1);\r
918         VW_UpdateScreen();\r
919         if (!USL_CJGet(joy,1,x + 8,y + 24,&maxx,&maxy))\r
920                 return(false);\r
921 \r
922         while (IN_GetJoyButtonsDB(joy))\r
923                 ;\r
924 \r
925         IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
926         return(true);\r
927 }\r
928 \r
929 #pragma argsused\r
930 static boolean\r
931 USL_Joy1Custom(UserCall call,UserItem far *item)\r
932 {\r
933         if (call == uic_SetupCard)\r
934         {\r
935                 if (USL_ConfigJoystick(0))\r
936                 {\r
937                         Controls[0] = ctrl_Joystick1;\r
938                         USL_CtlDialog("USING JOYSTICK #1","PRESS ANY KEY",nil);\r
939                 }\r
940                 return(true);\r
941         }\r
942         else\r
943                 return(false);\r
944 }\r
945 \r
946 #pragma argsused\r
947 static boolean\r
948 USL_Joy2Custom(UserCall call,UserItem far *item)\r
949 {\r
950         if (call == uic_SetupCard)\r
951         {\r
952                 if (USL_ConfigJoystick(1))\r
953                 {\r
954                         Controls[0] = ctrl_Joystick2;\r
955                         USL_CtlDialog("USING JOYSTICK #2","PRESS ANY KEY",nil);\r
956                 }\r
957                 return(true);\r
958         }\r
959         else\r
960                 return(false);\r
961 }\r
962 \r
963 static void\r
964 USL_DrawFileIcon(UserItem far *item)\r
965 {\r
966         word    color;\r
967 \r
968         item->y = topcard->y + CtlPanelSY + 12;\r
969         item->y += (item - loadsavegamei) * 11;\r
970 \r
971         fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
972         color = fontcolor ^ BackColor;  // Blech!\r
973         VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y,color);\r
974         VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y + 9,color);\r
975         VWB_Vlin(item->y,item->y + 9,item->x,color);\r
976         VWB_Vlin(item->y,item->y + 9,item->x + (CtlPanelW - 12),color);\r
977 }\r
978 \r
979 static void\r
980 USL_DoLoadGame(UserItem far *item)\r
981 {\r
982         char            *filename;\r
983         word            n,\r
984                                 err;\r
985         int                     file;\r
986         SaveGame        *game;\r
987 \r
988         if (!USL_ConfirmComm(uc_Loaded))\r
989                 return;\r
990 \r
991         n = item - loadsavegamei;\r
992         game = &Games[n];\r
993 \r
994         USL_ShowLoadSave("Loading",game->name);\r
995 \r
996         err = 0;\r
997         filename = USL_GiveSaveName(n);\r
998         if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
999         {\r
1000                 if (read(file,game,sizeof(*game)) == sizeof(*game))\r
1001                 {\r
1002                         if (USL_LoadGame)\r
1003                                 if (!USL_LoadGame(file))\r
1004                                         USL_HandleError(err = errno);\r
1005                 }\r
1006                 else\r
1007                         USL_HandleError(err = errno);\r
1008                 close(file);\r
1009         }\r
1010         else\r
1011                 USL_HandleError(err = errno);\r
1012         if (err)\r
1013         {\r
1014                 abortgame = true;\r
1015                 Communication = uc_None;\r
1016                 CtlPanelDone = false;\r
1017         }\r
1018         else\r
1019                 loadedgame = true;\r
1020         game->present = true;\r
1021 \r
1022         if (loadedgame)\r
1023                 Paused = true;\r
1024 \r
1025         USL_DrawCtlPanel();\r
1026 }\r
1027 \r
1028 static boolean\r
1029 USL_LoadCustom(UserCall call,UserItem far *item)\r
1030 {\r
1031         boolean result;\r
1032         word    i;\r
1033 \r
1034         result = false;\r
1035         switch (call)\r
1036         {\r
1037         case uic_SetupCard:\r
1038                 for (i = 0;i < MaxSaveGames;i++)\r
1039                 {\r
1040                         if (Games[i].present)\r
1041                                 loadsavegamei[i].flags &= ~ui_Disabled;\r
1042                         else\r
1043                                 loadsavegamei[i].flags |= ui_Disabled;\r
1044                 }\r
1045                 break;\r
1046         case uic_DrawIcon:\r
1047                 USL_DrawFileIcon(item);\r
1048                 result = true;\r
1049                 break;\r
1050         case uic_Draw:\r
1051                 USL_DrawFileIcon(item);\r
1052                 VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
1053 \r
1054                 i = item - loadsavegamei;\r
1055                 if (Games[i].present)\r
1056                         px = item->x + 2;\r
1057                 else\r
1058                         px = item->x + 60;\r
1059                 py = item->y + 2;\r
1060                 USL_DrawString(Games[i].present? Games[i].name : "Empty");\r
1061                 result = true;\r
1062                 break;\r
1063         case uic_Hit:\r
1064                 USL_DoLoadGame(item);\r
1065                 result = true;\r
1066                 break;\r
1067         }\r
1068         return(result);\r
1069 }\r
1070 \r
1071 static void\r
1072 USL_DoSaveGame(UserItem far *item)\r
1073 {\r
1074         boolean         ok;\r
1075         char            *filename;\r
1076         word            n,err;\r
1077         int         file;\r
1078         SaveGame        *game;\r
1079 \r
1080         BottomS1 = "Type name";\r
1081         BottomS2 = "Enter accepts";\r
1082         USL_DrawCtlPanel();\r
1083 \r
1084         n = item - loadsavegamei;\r
1085         game = &Games[n];\r
1086         fontcolor = HiliteColor;\r
1087         VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
1088         game->oldtest = &PrintX;\r
1089         ok = US_LineInput(item->x + 2,item->y + 2,\r
1090                                                 game->name,game->present? game->name : nil,\r
1091                                                 true,MaxGameName,\r
1092                                                 CtlPanelW - 22);\r
1093         if (!strlen(game->name))\r
1094                 strcpy(game->name,"Untitled");\r
1095         if (ok)\r
1096         {\r
1097                 USL_ShowLoadSave("Saving",game->name);\r
1098 \r
1099                 filename = USL_GiveSaveName(n);\r
1100                 err = 0;\r
1101                 file = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
1102                                         S_IREAD | S_IWRITE | S_IFREG);\r
1103                 if (file != -1)\r
1104                 {\r
1105                         if (write(file,game,sizeof(*game)) == sizeof(*game))\r
1106                         {\r
1107                                 if (USL_SaveGame)\r
1108                                         ok = USL_SaveGame(file);\r
1109                                 if (!ok)\r
1110                                         USL_HandleError(err = errno);\r
1111                         }\r
1112                         else\r
1113                                 USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
1114                         close(file);\r
1115                 }\r
1116                 else\r
1117                         USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
1118                 if (err)\r
1119                 {\r
1120                         remove(filename);\r
1121                         ok = false;\r
1122                 }\r
1123 \r
1124         }\r
1125 \r
1126         if (!game->present)\r
1127                 game->present = ok;\r
1128 \r
1129         if (ok)\r
1130                 GameIsDirty = false;\r
1131         USL_SetupCard();\r
1132 }\r
1133 \r
1134 static boolean\r
1135 USL_SaveCustom(UserCall call,UserItem far *item)\r
1136 {\r
1137         word    i;\r
1138 \r
1139         switch (call)\r
1140         {\r
1141         case uic_SetupCard:\r
1142                 for (i = 0;i < MaxSaveGames;i++)\r
1143                         loadsavegamei[i].flags &= ~ui_Disabled;\r
1144                 return(false);\r
1145         case uic_Hit:\r
1146                 USL_DoSaveGame(item);\r
1147                 return(true);\r
1148 //              break;\r
1149         }\r
1150         return(USL_LoadCustom(call,item));\r
1151 }\r
1152 \r
1153 #if 0\r
1154 \r
1155 #define PaddleMinX      (CtlPanelSX + 3)\r
1156 #define PaddleMaxX      (CtlPanelEX - 15)\r
1157 #define BallMinX        (CtlPanelSX + 2)\r
1158 #define BallMinY        (CtlPanelSY + 12 + 2)\r
1159 #define BallMaxX        (CtlPanelEX - 6)\r
1160 #define BallMaxY        (CtlPanelEY - 13)\r
1161 #define CPaddleY        (BallMinY + 4)\r
1162 #define KPaddleY        (BallMaxY - 2)\r
1163 void\r
1164 USL_DrawPongScore(word k,word c)\r
1165 {\r
1166         fontcolor = HiliteColor;\r
1167         PrintY = py = CtlPanelSY + 4;\r
1168         px = CtlPanelSX + 6;\r
1169         VWB_Bar(px,py,42,6,BackColor);\r
1170         USL_DrawString("YOU:");\r
1171         PrintX = px;\r
1172         US_PrintUnsigned(k);\r
1173         px = CtlPanelSX + 108;\r
1174         VWB_Bar(px,py,50,6,BackColor);\r
1175         USL_DrawString("COMP:");\r
1176         PrintX = px;\r
1177         US_PrintUnsigned(c);\r
1178 }\r
1179 \r
1180 void\r
1181 USL_PlayPong(void)\r
1182 {\r
1183         boolean         ball,killball,revdir,done,lastscore;\r
1184         word            cycle,\r
1185                                 x,y,\r
1186                                 kx,cx,\r
1187                                 rx,\r
1188                                 bx,by,\r
1189                                 kscore,cscore,\r
1190                                 speedup;\r
1191         int                     bdx,bdy;\r
1192         longword        balltime,waittime;\r
1193         CursorInfo      cursorinfo;\r
1194 \r
1195         kx = cx = PaddleMinX + ((PaddleMaxX - PaddleMinX) / 2);\r
1196         bx = by = bdx = bdy = 0;\r
1197         kscore = cscore = 0;\r
1198         USL_DrawPongScore(0,0);\r
1199         cycle = 0;\r
1200         revdir = false;\r
1201         killball = true;\r
1202         done = false;\r
1203         lastscore = false;\r
1204         do\r
1205         {\r
1206                 waittime = TimeCount;\r
1207 \r
1208                 IN_ReadCursor(&cursorinfo);\r
1209                 if (((cursorinfo.x < 0) || IN_KeyDown(sc_LeftArrow)) && (kx > PaddleMinX))\r
1210                         kx -= 2;\r
1211                 else if (((cursorinfo.x > 0) || IN_KeyDown(sc_RightArrow)) && (kx < PaddleMaxX))\r
1212                         kx += 2;\r
1213 \r
1214                 if (killball)\r
1215                 {\r
1216                         ball = false;\r
1217                         balltime = TimeCount + TickBase;\r
1218                         speedup = 10;\r
1219                         killball = false;\r
1220                 }\r
1221 \r
1222                 if (ball && (cycle++ % 3))\r
1223                 {\r
1224                         x = (bx >> 2);\r
1225                         if (!(x & 1))\r
1226                                 x += (US_RndT() & 1);\r
1227 \r
1228                         if ((cx + 6 < x) && (cx < PaddleMaxX))\r
1229                                 cx += 1;\r
1230                         else if ((cx + 6 > x) && (cx > PaddleMinX))\r
1231                                 cx -= 1;\r
1232                 }\r
1233 \r
1234                 VWB_Bar(BallMinX,BallMinY - 1,\r
1235                                 BallMaxX - BallMinX + 5,BallMaxY - BallMinY + 7,\r
1236                                 BackColor);\r
1237                 VWB_DrawSprite(cx,CPaddleY,PADDLESPR);\r
1238                 VWB_DrawSprite(kx,KPaddleY,PADDLESPR);\r
1239                 if (ball)\r
1240                 {\r
1241                         if\r
1242                         (\r
1243                                 (((bx + bdx) >> 2) > BallMaxX)\r
1244                         ||      (((bx + bdx) >> 2) < BallMinX)\r
1245                         )\r
1246                         {\r
1247                                 SD_PlaySound(BALLBOUNCESND);\r
1248                                 bdx = -bdx;\r
1249                         }\r
1250                         bx += bdx;\r
1251 \r
1252                         if (((by + bdy) >> 2) > BallMaxY)\r
1253                         {\r
1254                                 killball = true;\r
1255                                 lastscore = false;\r
1256                                 cscore++;\r
1257                                 SD_PlaySound(COMPSCOREDSND);\r
1258                                 USL_DrawPongScore(kscore,cscore);\r
1259                                 if (cscore == 21)\r
1260                                 {\r
1261                                         USL_CtlDialog("You lost!","Press any key",nil);\r
1262                                         done = true;\r
1263                                         continue;\r
1264                                 }\r
1265                         }\r
1266                         else if (((by + bdy) >> 2) < BallMinY)\r
1267                         {\r
1268                                 killball = true;\r
1269                                 lastscore = true;\r
1270                                 kscore++;\r
1271                                 SD_PlaySound(KEENSCOREDSND);\r
1272                                 USL_DrawPongScore(kscore,cscore);\r
1273                                 if (kscore == 21)\r
1274                                 {\r
1275                                         USL_CtlDialog("You won!","Press any key",nil);\r
1276                                         done = true;\r
1277                                         continue;\r
1278                                 }\r
1279                         }\r
1280                         by += bdy;\r
1281 \r
1282                         x = bx >> 2;\r
1283                         y = by >> 2;\r
1284                         if (!killball)\r
1285                         {\r
1286                                 if\r
1287                                 (\r
1288                                         (bdy < 0)\r
1289                                 &&      ((y >= CPaddleY) && (y < CPaddleY + 3))\r
1290                                 &&      ((x >= (cx - 5)) && (x < (cx + 11)))\r
1291                                 )\r
1292                                 {\r
1293                                         rx = cx;\r
1294                                         revdir = true;\r
1295                                         SD_PlaySound(COMPPADDLESND);\r
1296                                 }\r
1297                                 else if\r
1298                                 (\r
1299                                         (bdy > 0)\r
1300                                 &&      ((y >= (KPaddleY - 3)) && (y < KPaddleY))\r
1301                                 &&      ((x >= (kx - 5)) && (x < (kx + 11)))\r
1302                                 )\r
1303                                 {\r
1304                                         if (((bdy >> 2) < 3) && !(--speedup))\r
1305                                         {\r
1306                                                 bdy++;\r
1307                                                 speedup = 10;\r
1308                                         }\r
1309                                         rx = kx;\r
1310                                         revdir = true;\r
1311                                         SD_PlaySound(KEENPADDLESND);\r
1312                                 }\r
1313                                 if (revdir)\r
1314                                 {\r
1315                                         bdy = -bdy;\r
1316                                         bdx = ((x + 5 - rx) >> 1) - (1 << 2);\r
1317                                         if (!bdx)\r
1318                                                 bdx--;\r
1319                                         revdir = false;\r
1320                                 }\r
1321                         }\r
1322                         VWB_DrawSprite(x,y,(x & 1)? BALL1PIXELTOTHERIGHTSPR : BALLSPR);\r
1323                 }\r
1324                 else if (TimeCount >= balltime)\r
1325                 {\r
1326                         ball = true;\r
1327                         bdx = 1 - (US_RndT() % 3);\r
1328                         bdy = 2;\r
1329                         if (lastscore)\r
1330                                 bdy = -bdy;\r
1331                         bx = (BallMinX + ((BallMaxX - BallMinX) / 2)) << 2;\r
1332                         by = (BallMinY + ((BallMaxY - BallMinY) / 2)) << 2;\r
1333                 }\r
1334                 VW_UpdateScreen();\r
1335                 while (waittime == TimeCount)\r
1336                         ;       // DEBUG - do adaptiveness\r
1337         } while ((LastScan != sc_Escape) && !done);\r
1338         IN_ClearKeysDown();\r
1339 }\r
1340 \r
1341 #pragma argsused\r
1342 static boolean\r
1343 USL_PongCustom(UserCall call,struct UserItem far *item)\r
1344 {\r
1345         if (call != uic_SetupCard)\r
1346                 return(false);\r
1347 \r
1348         VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
1349         VWB_DrawPic(CtlPanelSX + 56,CtlPanelSY,CP_PADDLEWARPIC);\r
1350         VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelSY + 12,HiliteColor ^ BackColor);\r
1351         VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelEY - 7,HiliteColor ^ BackColor);\r
1352         USL_PlayPong();\r
1353 \r
1354         return(true);\r
1355 }\r
1356 \r
1357 #endif\r
1358 \r
1359 //      Flag management stuff\r
1360 static void\r
1361 USL_ClearFlags(UserItemGroup far *node)\r
1362 {\r
1363         UserItem        far *i;\r
1364 \r
1365         if (!node->items)\r
1366                 return;\r
1367 \r
1368         for (i = node->items;i->type != uii_Bad;i++)\r
1369         {\r
1370                 i->flags &= ~UISelectFlags;\r
1371                 if (i->child)\r
1372                         USL_ClearFlags((UserItemGroup far *)i->child);\r
1373         }\r
1374 }\r
1375 \r
1376 static int\r
1377 USL_FindPushedItem(UserItemGroup far *group)\r
1378 {\r
1379         word            i;\r
1380         UserItem        far *item;\r
1381 \r
1382         for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
1383                 if (item->flags & ui_Pushed)\r
1384                         return(i);\r
1385         return(-1);\r
1386 }\r
1387 \r
1388 static void\r
1389 USL_SelectItem(UserItemGroup far *group,word index,boolean draw)\r
1390 {\r
1391         UserItem        far *item;\r
1392 \r
1393         if (index != group->cursor)\r
1394         {\r
1395                 item = &group->items[group->cursor];\r
1396                 item->flags &= ~ui_Selected;\r
1397                 if (draw)\r
1398                         USL_DrawItem(item);\r
1399         }\r
1400 \r
1401         group->cursor = index;\r
1402         item = &group->items[group->cursor];\r
1403         group->items[group->cursor].flags |= ui_Selected;\r
1404         if (draw)\r
1405                 USL_DrawItem(item);\r
1406 }\r
1407 \r
1408 static void\r
1409 USL_PushItem(UserItemGroup far *group,word index,boolean draw)\r
1410 {\r
1411         word            i;\r
1412         UserItem        far *item;\r
1413 \r
1414         USL_SelectItem(group,index,draw);\r
1415         for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
1416         {\r
1417                 if (item->type != uii_RadioButton)\r
1418                         continue;\r
1419 \r
1420                 if (i == index)\r
1421                 {\r
1422                         item->flags |= ui_Pushed;\r
1423                         if (draw)\r
1424                                 USL_DrawItem(item);\r
1425                 }\r
1426                 else if (item->flags & ui_Pushed)\r
1427                 {\r
1428                         item->flags &= ~ui_Pushed;\r
1429                         if (draw)\r
1430                                 USL_DrawItem(item);\r
1431                 }\r
1432         }\r
1433 }\r
1434 \r
1435 static void\r
1436 USL_NextItem(void)\r
1437 {\r
1438         if (topcard->items[topcard->cursor + 1].type == uii_Bad)\r
1439                 return;\r
1440         USL_SelectItem(topcard,topcard->cursor + 1,true);\r
1441 }\r
1442 \r
1443 static void\r
1444 USL_PrevItem(void)\r
1445 {\r
1446         if (!topcard->cursor)\r
1447                 return;\r
1448         USL_SelectItem(topcard,topcard->cursor - 1,true);\r
1449 }\r
1450 \r
1451 static void\r
1452 USL_SetupCard(void)\r
1453 {\r
1454         BottomS1 = "Arrows move";\r
1455         BottomS2 = "Enter selects";\r
1456         BottomS3 = cstackptr? "ESC to back out" : "ESC to quit";\r
1457 \r
1458         USL_SelectItem(topcard,topcard->cursor,false);\r
1459         USL_DrawCtlPanel();     // Contents?\r
1460 }\r
1461 \r
1462 static void\r
1463 USL_DownLevel(UserItemGroup far *group)\r
1464 {\r
1465         if (!group)\r
1466                 Quit("USL_DownLevel() - nil card");\r
1467         USL_PushCard(group);\r
1468         if (group->custom && group->custom(uic_SetupCard,nil))\r
1469                 USL_PopCard();\r
1470         USL_SetupCard();\r
1471 }\r
1472 \r
1473 static void\r
1474 USL_UpLevel(void)\r
1475 {\r
1476         if (!cstackptr)\r
1477         {\r
1478                 USL_ConfirmComm(uc_Quit);\r
1479                 return;\r
1480         }\r
1481 \r
1482         if (topcard->items)\r
1483                 topcard->items[topcard->cursor].flags &= ~ui_Selected;\r
1484         USL_PopCard();\r
1485         USL_SetupCard();\r
1486 }\r
1487 \r
1488 static void\r
1489 USL_DoItem(void)\r
1490 {\r
1491         // DEBUG - finish this routine\r
1492         UserItem                far *item;\r
1493 \r
1494         item = &topcard->items[topcard->cursor];\r
1495         if (item->flags & ui_Disabled)\r
1496                 SD_PlaySound(NOWAYSND);\r
1497         else\r
1498         {\r
1499                 switch (item->type)\r
1500                 {\r
1501                 case uii_Button:\r
1502                         if (!(topcard->custom && topcard->custom(uic_Hit,item)))\r
1503                                 USL_ConfirmComm(item->comm);\r
1504                         break;\r
1505                 case uii_RadioButton:\r
1506                         USL_PushItem(topcard,topcard->cursor,true);\r
1507                         break;\r
1508                 case uii_Folder:\r
1509                         USL_DownLevel(item->child);\r
1510                         break;\r
1511                 }\r
1512         }\r
1513 }\r
1514 \r
1515 static void\r
1516 USL_SetControlValues(void)\r
1517 {\r
1518         USL_PushItem(&soundgroup,SoundMode,false);\r
1519         USL_PushItem(&musicgroup,MusicMode,false);\r
1520         if (!AdLibPresent)\r
1521         {\r
1522                 soundi[2].flags |= ui_Disabled; // AdLib sound effects\r
1523                 musici[1].flags |= ui_Disabled; // AdLib music\r
1524         }\r
1525 \r
1526         if (!JoysPresent[0])\r
1527                 configi[3].flags |= ui_Disabled;\r
1528         if (!JoysPresent[1])\r
1529                 configi[4].flags |= ui_Disabled;\r
1530 \r
1531         rooti[4].text = ingame? "RETURN TO GAME" : "RETURN TO DEMO";\r
1532         if (!ingame)\r
1533         {\r
1534                 rooti[2].flags |= ui_Disabled;  // Save Game\r
1535                 rooti[5].flags |= ui_Disabled;  // End Game\r
1536         }\r
1537         rootgroup.cursor = ingame? 4 : 0;\r
1538         USL_SetOptionsText();\r
1539         // DEBUG - write the rest of this\r
1540 }\r
1541 \r
1542 ///////////////////////////////////////////////////////////////////////////\r
1543 //\r
1544 //      USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the\r
1545 //              values of all the appropriate variables\r
1546 //\r
1547 ///////////////////////////////////////////////////////////////////////////\r
1548 static void\r
1549 USL_SetUpCtlPanel(void)\r
1550 {\r
1551         int     i;\r
1552 \r
1553         // Cache in all of the stuff for the control panel\r
1554         CA_UpLevel();\r
1555         for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)\r
1556                 CA_MarkGrChunk(i);\r
1557 //      for (i = PADDLE_LUMP_START;i <= PADDLE_LUMP_END;i++)\r
1558 //              CA_MarkGrChunk(i);\r
1559         CA_MarkGrChunk(STARTFONT+1);            // Little font\r
1560         CA_MarkGrChunk(CP_MENUMASKPICM);        // Mask for dialogs\r
1561         CA_CacheMarks("Control Panel");\r
1562         CA_LoadAllSounds();\r
1563 \r
1564         // Do some other setup\r
1565         fontnumber = 1;\r
1566         US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);\r
1567         fontcolor = F_BLACK;\r
1568         VW_Bar (0,0,320,200,3); // CAT3D patch\r
1569         RF_FixOfs();\r
1570         VW_InitDoubleBuffer();\r
1571 \r
1572         Communication = uc_None;\r
1573         USL_ClearFlags(&rootgroup);\r
1574         USL_SetControlValues();\r
1575         USL_SetupStack();\r
1576         USL_SetupCard();\r
1577 \r
1578         if (ingame)\r
1579                 GameIsDirty = true;\r
1580 \r
1581         IN_ClearKeysDown();\r
1582 }\r
1583 \r
1584 static void\r
1585 USL_HandleComm(UComm comm)\r
1586 {\r
1587         switch (comm)\r
1588         {\r
1589         case uc_Loaded:\r
1590         case uc_Return:\r
1591                 break;\r
1592         case uc_Abort:\r
1593                 abortgame = true;\r
1594                 break;\r
1595         case uc_Quit:\r
1596                 QuitToDos = true;\r
1597                 break;\r
1598         case uc_SEasy:\r
1599                 restartgame = gd_Easy;\r
1600                 break;\r
1601         case uc_SNormal:\r
1602                 restartgame = gd_Normal;\r
1603                 break;\r
1604         case uc_SHard:\r
1605                 restartgame = gd_Hard;\r
1606                 break;\r
1607 \r
1608         default:\r
1609                 Quit("USL_HandleComm() - unknown");\r
1610                 break;\r
1611         }\r
1612 }\r
1613 \r
1614 static void\r
1615 USL_GetControlValues(void)\r
1616 {\r
1617         int     i;\r
1618 \r
1619         // DEBUG - write the rest of this\r
1620         i = USL_FindPushedItem(&soundgroup);\r
1621         if (i != SoundMode)\r
1622                 SD_SetSoundMode(i);\r
1623 \r
1624         i = USL_FindPushedItem(&musicgroup);\r
1625         if (i != MusicMode)\r
1626                 SD_SetMusicMode(i);\r
1627 }\r
1628 \r
1629 ///////////////////////////////////////////////////////////////////////////\r
1630 //\r
1631 //      USL_TearDownCtlPanel() - Given the state of the control panel, sets the\r
1632 //              modes and values as appropriate\r
1633 //\r
1634 ///////////////////////////////////////////////////////////////////////////\r
1635 static void\r
1636 USL_TearDownCtlPanel(void)\r
1637 {\r
1638         USL_GetControlValues();\r
1639         if (Communication)\r
1640                 USL_HandleComm(Communication);\r
1641 \r
1642         fontnumber = 0; // Normal font\r
1643         fontcolor = F_BLACK;\r
1644         if (restartgame && USL_ResetGame)\r
1645                 USL_ResetGame();\r
1646         else if (QuitToDos)\r
1647         {\r
1648                 if (tedlevel)\r
1649                         TEDDeath();\r
1650                 else\r
1651                 {\r
1652                         US_CenterWindow(20,3);\r
1653                         fontcolor = F_SECONDCOLOR;\r
1654                         US_PrintCentered("Quitting...");\r
1655                         fontcolor = F_BLACK;\r
1656                         VW_UpdateScreen();\r
1657                         Quit(nil);\r
1658                 }\r
1659         }\r
1660 \r
1661         IN_ClearKeysDown();\r
1662         SD_WaitSoundDone();\r
1663         VW_Bar (0,0,320,200,3); // CAT3D patch\r
1664         CA_DownLevel();\r
1665         CA_LoadAllSounds();\r
1666 }\r
1667 \r
1668 ///////////////////////////////////////////////////////////////////////////\r
1669 //\r
1670 //      US_ControlPanel() - This is the main routine for the control panel\r
1671 //\r
1672 ///////////////////////////////////////////////////////////////////////////\r
1673 #define MoveMin 40\r
1674 void\r
1675 US_ControlPanel(void)\r
1676 {\r
1677 extern void HelpScreens(void);\r
1678 \r
1679         boolean         resetitem,on;\r
1680         word            i;\r
1681         int                     ydelta;\r
1682         longword        flashtime;\r
1683         UserItem        far *item;\r
1684         CursorInfo      cursorinfo;\r
1685 \r
1686 #if 0\r
1687         // DEBUG!!!\r
1688         {\r
1689                 USL_SetUpCtlPanel();\r
1690                 Communication = uc_Loaded;\r
1691                 CtlPanelDone = true;\r
1692                 loadedgame = true;\r
1693                 USL_TearDownCtlPanel();\r
1694                 return;\r
1695         }\r
1696 #endif\r
1697 \r
1698         if ((LastScan < sc_F1) || (LastScan > sc_F10))\r
1699                 IN_ClearKeysDown();\r
1700 \r
1701         USL_SetUpCtlPanel();\r
1702         USL_DrawCtlPanel();\r
1703 \r
1704         ydelta = 0;\r
1705         for (CtlPanelDone = false,resetitem = on = true;!CtlPanelDone;)\r
1706         {\r
1707                 item = &(topcard->items[topcard->cursor]);\r
1708 \r
1709                 if (resetitem)\r
1710                 {\r
1711                         flashtime = TimeCount + (TickBase / 2);\r
1712                         resetitem = false;\r
1713                 }\r
1714 \r
1715                 if (TimeCount >= flashtime)\r
1716                 {\r
1717                         on ^= true;\r
1718                         resetitem = true;\r
1719                         if (!on)\r
1720                                 item->flags &= ~ui_Selected;\r
1721                         USL_DrawItemIcon(item);\r
1722                         item->flags |= ui_Selected;\r
1723                 }\r
1724 \r
1725                 VW_UpdateScreen();\r
1726 \r
1727                 if (LastScan)\r
1728                 {\r
1729                         switch (LastScan)\r
1730                         {\r
1731                         case sc_UpArrow:\r
1732                                 USL_PrevItem();\r
1733                                 resetitem = true;\r
1734                                 break;\r
1735                         case sc_DownArrow:\r
1736                                 USL_NextItem();\r
1737                                 resetitem = true;\r
1738                                 break;\r
1739                         case sc_Return:\r
1740                                 USL_DoItem();\r
1741                                 resetitem = true;\r
1742                                 break;\r
1743                         case sc_Escape:\r
1744                                 USL_UpLevel();\r
1745                                 resetitem = true;\r
1746                                 break;\r
1747 #ifndef KEEN6\r
1748                         case sc_F1:\r
1749                                 HelpScreens();\r
1750                                 USL_DrawCtlPanel();\r
1751                                 resetitem = true;\r
1752                                 break;\r
1753 #endif\r
1754                         }\r
1755 \r
1756                         if\r
1757                         (\r
1758                                 (!resetitem)\r
1759                         &&      (\r
1760                                         (LastScan == KbdDefs[0].button0)\r
1761                                 ||      (LastScan == KbdDefs[0].button1)\r
1762                                 )\r
1763                         )\r
1764                         {\r
1765                                 USL_DoItem();\r
1766                                 resetitem = true;\r
1767                         }\r
1768 \r
1769                         if (!resetitem)\r
1770                         {\r
1771                                 for (item = topcard->items,i = 0;item->type != uii_Bad;item++,i++)\r
1772                                 {\r
1773                                         if (item->hotkey == LastScan)\r
1774                                         {\r
1775                                                 USL_SelectItem(topcard,i,true);\r
1776                                                 resetitem = true;\r
1777                                                 break;\r
1778                                         }\r
1779                                 }\r
1780                         }\r
1781 \r
1782                         IN_ClearKeysDown();\r
1783                 }\r
1784                 else\r
1785                 {\r
1786                         IN_ReadCursor(&cursorinfo);\r
1787                         ydelta += cursorinfo.y;\r
1788                         if (cursorinfo.button0)\r
1789                         {\r
1790                                 do\r
1791                                 {\r
1792                                         IN_ReadCursor(&cursorinfo);\r
1793                                 } while (cursorinfo.button0);\r
1794                                 USL_DoItem();\r
1795                                 resetitem = true;\r
1796                         }\r
1797                         else if (cursorinfo.button1)\r
1798                         {\r
1799                                 do\r
1800                                 {\r
1801                                         IN_ReadCursor(&cursorinfo);\r
1802                                 } while (cursorinfo.button1);\r
1803                                 USL_UpLevel();\r
1804                                 resetitem = true;\r
1805                         }\r
1806                         else if (ydelta < -MoveMin)\r
1807                         {\r
1808                                 ydelta += MoveMin;\r
1809                                 USL_PrevItem();\r
1810                                 resetitem = true;\r
1811                         }\r
1812                         else if (ydelta > MoveMin)\r
1813                         {\r
1814                                 ydelta -= MoveMin;\r
1815                                 USL_NextItem();\r
1816                                 resetitem = true;\r
1817                         }\r
1818                 }\r
1819         }\r
1820 \r
1821         USL_TearDownCtlPanel();\r
1822 }\r