ID_US_2.C 40 KB

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