ID_US.C 90 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692
  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
  21. // v1.0d1
  22. // By Jason Blochowiak
  23. //
  24. //
  25. // This module handles dealing with user input & feedback
  26. //
  27. // Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,
  28. // and Refresh Mgrs, Memory Mgr for background save/restore
  29. //
  30. // Globals:
  31. // ingame - Flag set by game indicating if a game is in progress
  32. // abortgame - Flag set if the current game should be aborted (if a load
  33. // game fails)
  34. // loadedgame - Flag set if a game was loaded
  35. // abortprogram - Normally nil, this points to a terminal error message
  36. // if the program needs to abort
  37. // restartgame - Normally set to gd_Continue, this is set to one of the
  38. // difficulty levels if a new game should be started
  39. // PrintX, PrintY - Where the User Mgr will print (global coords)
  40. // WindowX,WindowY,WindowW,WindowH - The dimensions of the current
  41. // window
  42. //
  43. // DEBUG - handle LPT3 for Sound Source
  44. #include "ID_HEADS.H"
  45. #define CTL_M_ADLIBUPPIC CTL_S_ADLIBUPPIC
  46. #define CTL_M_ADLIBDNPIC CTL_S_ADLIBDNPIC
  47. #pragma hdrstop
  48. #pragma warn -pia
  49. #define MaxX 320
  50. #define MaxY 200
  51. #define MaxHelpLines 500
  52. #define MaxHighName 57
  53. #define MaxScores 10
  54. typedef struct
  55. {
  56. char name[MaxHighName + 1];
  57. long score;
  58. word completed;
  59. } HighScore;
  60. #define MaxGameName 32
  61. #define MaxSaveGames 7
  62. typedef struct
  63. {
  64. char signature[4];
  65. boolean present;
  66. char name[MaxGameName + 1];
  67. } SaveGame;
  68. // Hack import for TED launch support
  69. extern boolean tedlevel;
  70. extern word tedlevelnum;
  71. extern void TEDDeath(void);
  72. static char *ParmStrings[] = {"TEDLEVEL","NOWAIT",""};
  73. // Global variables
  74. boolean ingame,abortgame,loadedgame;
  75. char *abortprogram;
  76. GameDiff restartgame = gd_Continue;
  77. word PrintX,PrintY;
  78. word WindowX,WindowY,WindowW,WindowH;
  79. // Internal variables
  80. static boolean US_Started;
  81. static boolean GameIsDirty,
  82. HighScoresDirty,
  83. QuitToDos,
  84. ResumeGame,
  85. NoWait;
  86. static memptr LineOffsets;
  87. static boolean Button0,Button1,
  88. CursorBad;
  89. static int CursorX,CursorY;
  90. static void (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,
  91. (*USL_DrawString)(char far *) = VWB_DrawPropString;
  92. static boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);
  93. static void (*USL_ResetGame)(void);
  94. static SaveGame Games[MaxSaveGames];
  95. static HighScore Scores[MaxScores] =
  96. {
  97. {"Sir Lancelot",500},
  98. {"",0},
  99. {"",0},
  100. {"",0},
  101. {"",0},
  102. {"",0},
  103. {"",0},
  104. {"",0},
  105. {"",0},
  106. {"",0}
  107. };
  108. // Internal routines
  109. // Public routines
  110. ///////////////////////////////////////////////////////////////////////////
  111. //
  112. // USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed
  113. // from DOS.
  114. //
  115. ///////////////////////////////////////////////////////////////////////////
  116. #pragma warn -par
  117. #pragma warn -rch
  118. int
  119. USL_HardError(word errval,int ax,int bp,int si)
  120. {
  121. #define IGNORE 0
  122. #define RETRY 1
  123. #define ABORT 2
  124. extern void ShutdownId(void);
  125. static char buf[32];
  126. static WindowRec wr;
  127. static boolean oldleavedriveon;
  128. int di;
  129. char c,*s,*t;
  130. di = _DI;
  131. oldleavedriveon = LeaveDriveOn;
  132. LeaveDriveOn = false;
  133. if (ax < 0)
  134. s = "Device Error";
  135. else
  136. {
  137. if ((di & 0x00ff) == 0)
  138. s = "Drive ~ is Write Protected";
  139. else
  140. s = "Error on Drive ~";
  141. for (t = buf;*s;s++,t++) // Can't use sprintf()
  142. if ((*t = *s) == '~')
  143. *t = (ax & 0x00ff) + 'A';
  144. *t = '\0';
  145. s = buf;
  146. }
  147. c = peekb(0x40,0x49); // Get the current screen mode
  148. if ((c < 4) || (c == 7))
  149. goto oh_kill_me;
  150. // DEBUG - handle screen cleanup
  151. US_SaveWindow(&wr);
  152. US_CenterWindow(30,3);
  153. US_CPrint(s);
  154. US_CPrint("(R)etry or (A)bort?");
  155. VW_UpdateScreen();
  156. IN_ClearKeysDown();
  157. asm sti // Let the keyboard interrupts come through
  158. while (true)
  159. {
  160. switch (IN_WaitForASCII())
  161. {
  162. case key_Escape:
  163. case 'a':
  164. case 'A':
  165. goto oh_kill_me;
  166. break;
  167. case key_Return:
  168. case key_Space:
  169. case 'r':
  170. case 'R':
  171. US_ClearWindow();
  172. VW_UpdateScreen();
  173. US_RestoreWindow(&wr);
  174. LeaveDriveOn = oldleavedriveon;
  175. return(RETRY);
  176. break;
  177. }
  178. }
  179. oh_kill_me:
  180. abortprogram = s;
  181. ShutdownId();
  182. fprintf(stderr,"Terminal Error: %s\n",s);
  183. if (tedlevel)
  184. fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");
  185. return(ABORT);
  186. #undef IGNORE
  187. #undef RETRY
  188. #undef ABORT
  189. }
  190. #pragma warn +par
  191. #pragma warn +rch
  192. ///////////////////////////////////////////////////////////////////////////
  193. //
  194. // USL_GiveSaveName() - Returns a pointer to a static buffer that contains
  195. // the filename to use for the specified save game
  196. //
  197. ///////////////////////////////////////////////////////////////////////////
  198. static char *
  199. USL_GiveSaveName(word game)
  200. {
  201. static char filename[32];
  202. char *s,*t;
  203. for (s = "SAVEGM",t = filename;*s;)
  204. *t++ = *s++;
  205. *t++ = game + '0';
  206. for (s = "."EXTENSION;*s;)
  207. *t++ = *s++;
  208. *t = '\0';
  209. return(filename);
  210. }
  211. ///////////////////////////////////////////////////////////////////////////
  212. //
  213. // US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after
  214. // reading or writing the save game headers
  215. //
  216. ///////////////////////////////////////////////////////////////////////////
  217. void
  218. US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))
  219. {
  220. USL_LoadGame = load;
  221. USL_SaveGame = save;
  222. USL_ResetGame = reset;
  223. }
  224. ///////////////////////////////////////////////////////////////////////////
  225. //
  226. // USL_ReadConfig() - Reads the configuration file, if present, and sets
  227. // things up accordingly. If it's not present, uses defaults. This file
  228. // includes the high scores.
  229. //
  230. ///////////////////////////////////////////////////////////////////////////
  231. static void
  232. USL_ReadConfig(void)
  233. {
  234. boolean gotit;
  235. int file;
  236. SDMode sd;
  237. SMMode sm;
  238. ControlType ctl;
  239. if ((file = open("CONFIG."EXTENSION,O_BINARY | O_RDONLY)) != -1)
  240. {
  241. read(file,Scores,sizeof(HighScore) * MaxScores);
  242. read(file,&sd,sizeof(sd));
  243. read(file,&sm,sizeof(sm));
  244. read(file,&ctl,sizeof(ctl));
  245. read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));
  246. close(file);
  247. HighScoresDirty = false;
  248. gotit = true;
  249. }
  250. else
  251. {
  252. sd = sdm_Off;
  253. sm = smm_Off;
  254. ctl = ctrl_Keyboard;
  255. gotit = false;
  256. HighScoresDirty = true;
  257. }
  258. SD_Default(gotit,sd,sm);
  259. IN_Default(gotit,ctl);
  260. }
  261. ///////////////////////////////////////////////////////////////////////////
  262. //
  263. // USL_WriteConfig() - Writes out the current configuration, including the
  264. // high scores.
  265. //
  266. ///////////////////////////////////////////////////////////////////////////
  267. static void
  268. USL_WriteConfig(void)
  269. {
  270. int file;
  271. file = open("CONFIG."EXTENSION,O_CREAT | O_BINARY | O_WRONLY,
  272. S_IREAD | S_IWRITE | S_IFREG);
  273. if (file != -1)
  274. {
  275. write(file,Scores,sizeof(HighScore) * MaxScores);
  276. write(file,&SoundMode,sizeof(SoundMode));
  277. write(file,&MusicMode,sizeof(MusicMode));
  278. write(file,&(Controls[0]),sizeof(Controls[0]));
  279. write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));
  280. close(file);
  281. }
  282. }
  283. ///////////////////////////////////////////////////////////////////////////
  284. //
  285. // USL_CheckSavedGames() - Checks to see which saved games are present
  286. // & valid
  287. //
  288. ///////////////////////////////////////////////////////////////////////////
  289. static void
  290. USL_CheckSavedGames(void)
  291. {
  292. boolean ok;
  293. char *filename;
  294. word i;
  295. int file;
  296. SaveGame *game;
  297. USL_SaveGame = 0;
  298. USL_LoadGame = 0;
  299. for (i = 0,game = Games;i < MaxSaveGames;i++,game++)
  300. {
  301. filename = USL_GiveSaveName(i);
  302. ok = false;
  303. if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)
  304. {
  305. if
  306. (
  307. (read(file,game,sizeof(*game)) == sizeof(*game))
  308. && (!strcmp(game->signature,EXTENSION))
  309. )
  310. ok = true;
  311. close(file);
  312. }
  313. if (ok)
  314. game->present = true;
  315. else
  316. {
  317. strcpy(game->signature,EXTENSION);
  318. game->present = false;
  319. strcpy(game->name,"Empty");
  320. }
  321. }
  322. }
  323. ///////////////////////////////////////////////////////////////////////////
  324. //
  325. // US_Startup() - Starts the User Mgr
  326. //
  327. ///////////////////////////////////////////////////////////////////////////
  328. void
  329. US_Startup(void)
  330. {
  331. if (US_Started)
  332. return;
  333. harderr(USL_HardError); // Install the fatal error handler
  334. US_InitRndT(true); // Initialize the random number generator
  335. USL_ReadConfig(); // Read config file
  336. US_Started = true;
  337. }
  338. ///////////////////////////////////////////////////////////////////////////
  339. //
  340. // US_Setup() - Does the disk access part of the User Mgr's startup
  341. //
  342. ///////////////////////////////////////////////////////////////////////////
  343. void
  344. US_Setup(void)
  345. {
  346. USL_CheckSavedGames(); // Check which saved games are present
  347. }
  348. ///////////////////////////////////////////////////////////////////////////
  349. //
  350. // US_Shutdown() - Shuts down the User Mgr
  351. //
  352. ///////////////////////////////////////////////////////////////////////////
  353. void
  354. US_Shutdown(void)
  355. {
  356. if (!US_Started)
  357. return;
  358. if (!abortprogram)
  359. USL_WriteConfig();
  360. US_Started = false;
  361. }
  362. ///////////////////////////////////////////////////////////////////////////
  363. //
  364. // US_CheckParm() - checks to see if a string matches one of a set of
  365. // strings. The check is case insensitive. The routine returns the
  366. // index of the string that matched, or -1 if no matches were found
  367. //
  368. ///////////////////////////////////////////////////////////////////////////
  369. int
  370. US_CheckParm(char *parm,char **strings)
  371. {
  372. char cp,cs,
  373. *p,*s;
  374. int i;
  375. while (!isalpha(*parm)) // Skip non-alphas
  376. parm++;
  377. for (i = 0;*strings && **strings;i++)
  378. {
  379. for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)
  380. {
  381. cs = *s++;
  382. if (!cs)
  383. return(i);
  384. cp = *p++;
  385. if (isupper(cs))
  386. cs = tolower(cs);
  387. if (isupper(cp))
  388. cp = tolower(cp);
  389. }
  390. }
  391. return(-1);
  392. }
  393. ///////////////////////////////////////////////////////////////////////////
  394. //
  395. // USL_ScreenDraw() - Draws a chunk of the text screen (called only by
  396. // US_TextScreen())
  397. //
  398. ///////////////////////////////////////////////////////////////////////////
  399. static void
  400. USL_ScreenDraw(word x,word y,char *s,byte attr)
  401. {
  402. byte far *screen;
  403. screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));
  404. while (*s)
  405. {
  406. *screen++ = *s++;
  407. *screen++ = attr;
  408. }
  409. }
  410. ///////////////////////////////////////////////////////////////////////////
  411. //
  412. // USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,
  413. // and moves the cursor to the leftmost column of the bottom line
  414. //
  415. ///////////////////////////////////////////////////////////////////////////
  416. static void
  417. USL_ClearTextScreen(void)
  418. {
  419. // Set to 80x25 color text mode
  420. _AL = 3; // Mode 3
  421. _AH = 0x00;
  422. geninterrupt(0x10);
  423. // Use BIOS to move the cursor to the bottom of the screen
  424. _AH = 0x0f;
  425. geninterrupt(0x10); // Get current video mode into _BH
  426. _DL = 0; // Lefthand side of the screen
  427. _DH = 24; // Bottom row
  428. _AH = 0x02;
  429. geninterrupt(0x10);
  430. }
  431. ///////////////////////////////////////////////////////////////////////////
  432. //
  433. // US_TextScreen() - Puts up the startup text screen
  434. // Note: These are the only User Manager functions that can be safely called
  435. // before the User Mgr has been started up
  436. //
  437. ///////////////////////////////////////////////////////////////////////////
  438. void
  439. US_TextScreen(void)
  440. {
  441. word i,n,
  442. sx,sy;
  443. extern char far introscn;
  444. USL_ClearTextScreen();
  445. _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);
  446. // Check for TED launching here
  447. for (i = 1;i < _argc;i++)
  448. {
  449. n = US_CheckParm(_argv[i],ParmStrings);
  450. if (n == 0)
  451. {
  452. tedlevelnum = atoi(_argv[i + 1]);
  453. if (tedlevelnum >= 0)
  454. {
  455. tedlevel = true;
  456. return;
  457. }
  458. else
  459. break;
  460. }
  461. else if (n == 1)
  462. {
  463. NoWait = true;
  464. return;
  465. }
  466. }
  467. }
  468. ///////////////////////////////////////////////////////////////////////////
  469. //
  470. // USL_Show() - Changes the appearance of one of the fields on the text
  471. // screen. Possibly adds a checkmark in front of it and highlights it
  472. //
  473. ///////////////////////////////////////////////////////////////////////////
  474. static void
  475. USL_Show(word x,word y,word w,boolean show,boolean hilight)
  476. {
  477. byte far *screen;
  478. screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));
  479. *screen++ = show? 251 : ' '; // Checkmark char or space
  480. *screen = 0x48;
  481. if (show && hilight)
  482. {
  483. for (w++;w--;screen += 2)
  484. *screen = 0x4f;
  485. }
  486. }
  487. ///////////////////////////////////////////////////////////////////////////
  488. //
  489. // USL_ShowMem() - Right justifies a longword in one of the memory fields on
  490. // the text screen
  491. //
  492. ///////////////////////////////////////////////////////////////////////////
  493. static void
  494. USL_ShowMem(word x,word y,long mem)
  495. {
  496. char buf[16];
  497. word i;
  498. for (i = strlen(ltoa(mem,buf,10));i < 5;i++)
  499. USL_ScreenDraw(x++,y," ",0x48);
  500. USL_ScreenDraw(x,y,buf,0x48);
  501. }
  502. ///////////////////////////////////////////////////////////////////////////
  503. //
  504. // US_UpdateTextScreen() - Called after the ID libraries are started up.
  505. // Displays what hardware is present.
  506. //
  507. ///////////////////////////////////////////////////////////////////////////
  508. void
  509. US_UpdateTextScreen(void)
  510. {
  511. boolean b;
  512. byte far *screen;
  513. word i;
  514. longword totalmem;
  515. // Show video card info
  516. b = (grmode == CGAGR);
  517. USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);
  518. b = (grmode == EGAGR);
  519. USL_Show(21,8,4,(videocard >= EGAcard) && (videocard <= VGAcard),b);
  520. b = (grmode == VGAGR);
  521. USL_Show(21,9,4,videocard == VGAcard,b);
  522. if (compatability)
  523. USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);
  524. // Show input device info
  525. USL_Show(60,7,8,true,true);
  526. USL_Show(60,8,11,JoysPresent[0],true);
  527. USL_Show(60,9,11,JoysPresent[1],true);
  528. USL_Show(60,10,5,MousePresent,true);
  529. // Show sound hardware info
  530. USL_Show(21,14,11,true,SoundMode == sdm_PC);
  531. b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);
  532. USL_Show(21,15,5,AdLibPresent && !SoundBlasterPresent,
  533. b && !SoundBlasterPresent);
  534. USL_Show(21,16,13,SoundBlasterPresent,
  535. SoundBlasterPresent && (b || (SoundMode == sdm_SoundBlaster)));
  536. USL_Show(21,17,13,SoundSourcePresent,SoundMode == sdm_SoundSource);
  537. // Show memory available/used
  538. USL_ShowMem(63,15,mminfo.mainmem / 1024);
  539. USL_Show(53,15,23,true,true);
  540. USL_ShowMem(63,16,mminfo.EMSmem / 1024);
  541. USL_Show(53,16,23,mminfo.EMSmem? true : false,true);
  542. USL_ShowMem(63,17,mminfo.XMSmem / 1024);
  543. USL_Show(53,17,23,mminfo.XMSmem? true : false,true);
  544. totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;
  545. USL_ShowMem(63,18,totalmem / 1024);
  546. screen = MK_FP(0xb800,1 + (((63 - 1) * 2) + (18 * 80 * 2)));
  547. for (i = 0;i < 13;i++,screen += 2)
  548. *screen = 0x4f;
  549. // Change Initializing... to Loading...
  550. USL_ScreenDraw(27,22," Loading... ",0x9c);
  551. }
  552. ///////////////////////////////////////////////////////////////////////////
  553. //
  554. // US_FinishTextScreen() - After the main program has finished its initial
  555. // loading, this routine waits for a keypress and then clears the screen
  556. //
  557. ///////////////////////////////////////////////////////////////////////////
  558. void
  559. US_FinishTextScreen(void)
  560. {
  561. // Change Loading... to Press a Key
  562. USL_ScreenDraw(29,22," Ready - Press a Key ",0x9a);
  563. if (!(tedlevel || NoWait))
  564. {
  565. IN_ClearKeysDown();
  566. IN_Ack();
  567. }
  568. IN_ClearKeysDown();
  569. USL_ClearTextScreen();
  570. }
  571. // Window/Printing routines
  572. ///////////////////////////////////////////////////////////////////////////
  573. //
  574. // US_SetPrintRoutines() - Sets the routines used to measure and print
  575. // from within the User Mgr. Primarily provided to allow switching
  576. // between masked and non-masked fonts
  577. //
  578. ///////////////////////////////////////////////////////////////////////////
  579. void
  580. US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))
  581. {
  582. USL_MeasureString = measure;
  583. USL_DrawString = print;
  584. }
  585. ///////////////////////////////////////////////////////////////////////////
  586. //
  587. // US_Print() - Prints a string in the current window. Newlines are
  588. // supported.
  589. //
  590. ///////////////////////////////////////////////////////////////////////////
  591. void
  592. US_Print(char *s)
  593. {
  594. char c,*se;
  595. word w,h;
  596. while (*s)
  597. {
  598. se = s;
  599. while ((c = *se) && (c != '\n'))
  600. se++;
  601. *se = '\0';
  602. USL_MeasureString(s,&w,&h);
  603. px = PrintX;
  604. py = PrintY;
  605. USL_DrawString(s);
  606. s = se;
  607. if (c)
  608. {
  609. *se = c;
  610. s++;
  611. PrintX = WindowX;
  612. PrintY += h;
  613. }
  614. else
  615. PrintX += w;
  616. }
  617. }
  618. ///////////////////////////////////////////////////////////////////////////
  619. //
  620. // US_PrintUnsigned() - Prints an unsigned long
  621. //
  622. ///////////////////////////////////////////////////////////////////////////
  623. void
  624. US_PrintUnsigned(longword n)
  625. {
  626. char buffer[32];
  627. US_Print(ultoa(n,buffer,10));
  628. }
  629. ///////////////////////////////////////////////////////////////////////////
  630. //
  631. // US_PrintSigned() - Prints a signed long
  632. //
  633. ///////////////////////////////////////////////////////////////////////////
  634. void
  635. US_PrintSigned(long n)
  636. {
  637. char buffer[32];
  638. US_Print(ltoa(n,buffer,10));
  639. }
  640. ///////////////////////////////////////////////////////////////////////////
  641. //
  642. // USL_PrintInCenter() - Prints a string in the center of the given rect
  643. //
  644. ///////////////////////////////////////////////////////////////////////////
  645. static void
  646. USL_PrintInCenter(char *s,Rect r)
  647. {
  648. word w,h,
  649. rw,rh;
  650. USL_MeasureString(s,&w,&h);
  651. rw = r.lr.x - r.ul.x;
  652. rh = r.lr.y - r.ul.y;
  653. px = r.ul.x + ((rw - w) / 2);
  654. py = r.ul.y + ((rh - h) / 2);
  655. USL_DrawString(s);
  656. }
  657. ///////////////////////////////////////////////////////////////////////////
  658. //
  659. // US_PrintCentered() - Prints a string centered in the current window.
  660. //
  661. ///////////////////////////////////////////////////////////////////////////
  662. void
  663. US_PrintCentered(char *s)
  664. {
  665. Rect r;
  666. r.ul.x = WindowX;
  667. r.ul.y = WindowY;
  668. r.lr.x = r.ul.x + WindowW;
  669. r.lr.y = r.ul.y + WindowH;
  670. USL_PrintInCenter(s,r);
  671. }
  672. ///////////////////////////////////////////////////////////////////////////
  673. //
  674. // US_CPrintLine() - Prints a string centered on the current line and
  675. // advances to the next line. Newlines are not supported.
  676. //
  677. ///////////////////////////////////////////////////////////////////////////
  678. void
  679. US_CPrintLine(char *s)
  680. {
  681. word w,h;
  682. USL_MeasureString(s,&w,&h);
  683. if (w > WindowW)
  684. Quit("US_CPrintLine() - String exceeds width");
  685. px = WindowX + ((WindowW - w) / 2);
  686. py = PrintY;
  687. USL_DrawString(s);
  688. PrintY += h;
  689. }
  690. ///////////////////////////////////////////////////////////////////////////
  691. //
  692. // US_CPrint() - Prints a string in the current window. Newlines are
  693. // supported.
  694. //
  695. ///////////////////////////////////////////////////////////////////////////
  696. void
  697. US_CPrint(char *s)
  698. {
  699. char c,*se;
  700. word w,h;
  701. while (*s)
  702. {
  703. se = s;
  704. while ((c = *se) && (c != '\n'))
  705. se++;
  706. *se = '\0';
  707. US_CPrintLine(s);
  708. s = se;
  709. if (c)
  710. {
  711. *se = c;
  712. s++;
  713. }
  714. }
  715. }
  716. ///////////////////////////////////////////////////////////////////////////
  717. //
  718. // US_ClearWindow() - Clears the current window to white and homes the
  719. // cursor
  720. //
  721. ///////////////////////////////////////////////////////////////////////////
  722. void
  723. US_ClearWindow(void)
  724. {
  725. VWB_Bar(WindowX,WindowY,WindowW,WindowH,WHITE);
  726. PrintX = WindowX;
  727. PrintY = WindowY;
  728. }
  729. ///////////////////////////////////////////////////////////////////////////
  730. //
  731. // US_DrawWindow() - Draws a frame and sets the current window parms
  732. //
  733. ///////////////////////////////////////////////////////////////////////////
  734. void
  735. US_DrawWindow(word x,word y,word w,word h)
  736. {
  737. word i,
  738. sx,sy,sw,sh;
  739. WindowX = x * 8;
  740. WindowY = y * 8;
  741. WindowW = w * 8;
  742. WindowH = h * 8;
  743. PrintX = WindowX;
  744. PrintY = WindowY;
  745. sx = (x - 1) * 8;
  746. sy = (y - 1) * 8;
  747. sw = (w + 1) * 8;
  748. sh = (h + 1) * 8;
  749. US_ClearWindow();
  750. VWB_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);
  751. for (i = sx + 8;i <= sx + sw - 8;i += 8)
  752. VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);
  753. VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);
  754. for (i = sy + 8;i <= sy + sh - 8;i += 8)
  755. VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);
  756. }
  757. ///////////////////////////////////////////////////////////////////////////
  758. //
  759. // US_CenterWindow() - Generates a window of a given width & height in the
  760. // middle of the screen
  761. //
  762. ///////////////////////////////////////////////////////////////////////////
  763. void
  764. US_CenterWindow(word w,word h)
  765. {
  766. US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);
  767. }
  768. ///////////////////////////////////////////////////////////////////////////
  769. //
  770. // US_CenterSaveWindow() - Generates a window of a given width & height in
  771. // the middle of the screen, saving the background
  772. //
  773. ///////////////////////////////////////////////////////////////////////////
  774. void
  775. US_CenterSaveWindow(word w,word h,memptr *save)
  776. {
  777. word x,y,
  778. screen;
  779. x = ((MaxX / 8) - w) / 2;
  780. y = ((MaxY / 8) - h) / 2;
  781. MM_GetPtr(save,(w * h) * CHARWIDTH);
  782. screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);
  783. VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);
  784. US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);
  785. }
  786. ///////////////////////////////////////////////////////////////////////////
  787. //
  788. // US_RestoreSaveWindow() - Restores the background of the size of the
  789. // current window from the memory specified by save
  790. //
  791. ///////////////////////////////////////////////////////////////////////////
  792. void
  793. US_RestoreSaveWindow(memptr *save)
  794. {
  795. word screen;
  796. screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);
  797. VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);
  798. MM_FreePtr(save);
  799. }
  800. ///////////////////////////////////////////////////////////////////////////
  801. //
  802. // US_SaveWindow() - Saves the current window parms into a record for
  803. // later restoration
  804. //
  805. ///////////////////////////////////////////////////////////////////////////
  806. void
  807. US_SaveWindow(WindowRec *win)
  808. {
  809. win->x = WindowX;
  810. win->y = WindowY;
  811. win->w = WindowW;
  812. win->h = WindowH;
  813. win->px = PrintX;
  814. win->py = PrintY;
  815. }
  816. ///////////////////////////////////////////////////////////////////////////
  817. //
  818. // US_RestoreWindow() - Sets the current window parms to those held in the
  819. // record
  820. //
  821. ///////////////////////////////////////////////////////////////////////////
  822. void
  823. US_RestoreWindow(WindowRec *win)
  824. {
  825. WindowX = win->x;
  826. WindowY = win->y;
  827. WindowW = win->w;
  828. WindowH = win->h;
  829. PrintX = win->px;
  830. PrintY = win->py;
  831. }
  832. // Cursor routines
  833. ///////////////////////////////////////////////////////////////////////////
  834. //
  835. // US_StartCursor() - Sets up the cursor for User Mgr use
  836. //
  837. ///////////////////////////////////////////////////////////////////////////
  838. void
  839. US_StartCursor(void)
  840. {
  841. CursorInfo info;
  842. VW_SetCursor(CURSORARROWSPR);
  843. CursorX = MaxX / 2;
  844. CursorY = MaxY / 2;
  845. VW_MoveCursor(CursorX,CursorY);
  846. VW_ShowCursor();
  847. IN_ReadCursor(&info); // Dispose of any accumulated movement
  848. }
  849. ///////////////////////////////////////////////////////////////////////////
  850. //
  851. // US_ShutCursor() - Cleans up after US_StartCursor()
  852. //
  853. ///////////////////////////////////////////////////////////////////////////
  854. void
  855. US_ShutCursor(void)
  856. {
  857. VW_HideCursor();
  858. }
  859. ///////////////////////////////////////////////////////////////////////////
  860. //
  861. // US_UpdateCursor() - Gets the new cursor position & button states from
  862. // the Input Mgr and tells the View Mgr where the cursor is
  863. //
  864. ///////////////////////////////////////////////////////////////////////////
  865. boolean
  866. US_UpdateCursor(void)
  867. {
  868. CursorInfo info;
  869. IN_ReadCursor(&info);
  870. if (info.x || info.y || CursorBad)
  871. {
  872. CursorX += info.x;
  873. if (CursorX >= MaxX)
  874. CursorX = MaxX - 1;
  875. else if (CursorX < 0)
  876. CursorX = 0;
  877. CursorY += info.y;
  878. if (CursorY >= MaxY)
  879. CursorY = MaxY - 1;
  880. else if (CursorY < 0)
  881. CursorY = 0;
  882. VW_MoveCursor(CursorX,CursorY);
  883. CursorBad = false;
  884. }
  885. Button0 = info.button0;
  886. Button1 = info.button1;
  887. return(Button0 || Button1);
  888. }
  889. // Input routines
  890. ///////////////////////////////////////////////////////////////////////////
  891. //
  892. // USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()
  893. //
  894. ///////////////////////////////////////////////////////////////////////////
  895. static void
  896. USL_XORICursor(int x,int y,char *s,word cursor)
  897. {
  898. char buf[MaxString];
  899. word w,h;
  900. strcpy(buf,s);
  901. buf[cursor] = '\0';
  902. USL_MeasureString(buf,&w,&h);
  903. px = x + w - 1;
  904. py = y;
  905. USL_DrawString("\x80");
  906. }
  907. ///////////////////////////////////////////////////////////////////////////
  908. //
  909. // US_LineInput() - Gets a line of user input at (x,y), the string defaults
  910. // to whatever is pointed at by def. Input is restricted to maxchars
  911. // chars or maxwidth pixels wide. If the user hits escape (and escok is
  912. // true), nothing is copied into buf, and false is returned. If the
  913. // user hits return, the current string is copied into buf, and true is
  914. // returned
  915. //
  916. ///////////////////////////////////////////////////////////////////////////
  917. boolean
  918. US_LineInput(int x,int y,char *buf,char *def,boolean escok,
  919. int maxchars,int maxwidth)
  920. {
  921. boolean redraw,
  922. cursorvis,cursormoved,
  923. done,result;
  924. ScanCode sc;
  925. char c,
  926. s[MaxString],olds[MaxString];
  927. word i,
  928. cursor,
  929. w,h,
  930. len;
  931. longword lasttime;
  932. VW_HideCursor();
  933. if (def)
  934. strcpy(s,def);
  935. else
  936. *s = '\0';
  937. *olds = '\0';
  938. cursor = strlen(s);
  939. cursormoved = redraw = true;
  940. cursorvis = done = false;
  941. lasttime = TimeCount;
  942. LastASCII = key_None;
  943. LastScan = sc_None;
  944. while (!done)
  945. {
  946. if (cursorvis)
  947. USL_XORICursor(x,y,s,cursor);
  948. asm pushf
  949. asm cli
  950. sc = LastScan;
  951. LastScan = sc_None;
  952. c = LastASCII;
  953. LastASCII = key_None;
  954. asm popf
  955. switch (sc)
  956. {
  957. case sc_LeftArrow:
  958. if (cursor)
  959. cursor--;
  960. c = key_None;
  961. cursormoved = true;
  962. break;
  963. case sc_RightArrow:
  964. if (s[cursor])
  965. cursor++;
  966. c = key_None;
  967. cursormoved = true;
  968. break;
  969. case sc_Home:
  970. cursor = 0;
  971. c = key_None;
  972. cursormoved = true;
  973. break;
  974. case sc_End:
  975. cursor = strlen(s);
  976. c = key_None;
  977. cursormoved = true;
  978. break;
  979. case sc_Return:
  980. strcpy(buf,s);
  981. done = true;
  982. result = true;
  983. c = key_None;
  984. break;
  985. case sc_Escape:
  986. if (escok)
  987. {
  988. done = true;
  989. result = false;
  990. }
  991. c = key_None;
  992. break;
  993. case sc_BackSpace:
  994. if (cursor)
  995. {
  996. strcpy(s + cursor - 1,s + cursor);
  997. cursor--;
  998. redraw = true;
  999. }
  1000. c = key_None;
  1001. cursormoved = true;
  1002. break;
  1003. case sc_Delete:
  1004. if (s[cursor])
  1005. {
  1006. strcpy(s + cursor,s + cursor + 1);
  1007. redraw = true;
  1008. }
  1009. c = key_None;
  1010. cursormoved = true;
  1011. break;
  1012. case 0x4c: // Keypad 5
  1013. case sc_UpArrow:
  1014. case sc_DownArrow:
  1015. case sc_PgUp:
  1016. case sc_PgDn:
  1017. case sc_Insert:
  1018. c = key_None;
  1019. break;
  1020. }
  1021. if (c)
  1022. {
  1023. len = strlen(s);
  1024. USL_MeasureString(s,&w,&h);
  1025. if
  1026. (
  1027. isprint(c)
  1028. && (len < MaxString - 1)
  1029. && ((!maxchars) || (len < maxchars))
  1030. && ((!maxwidth) || (w < maxwidth))
  1031. )
  1032. {
  1033. for (i = len + 1;i > cursor;i--)
  1034. s[i] = s[i - 1];
  1035. s[cursor++] = c;
  1036. redraw = true;
  1037. }
  1038. }
  1039. if (redraw)
  1040. {
  1041. px = x;
  1042. py = y;
  1043. USL_DrawString(olds);
  1044. strcpy(olds,s);
  1045. px = x;
  1046. py = y;
  1047. USL_DrawString(s);
  1048. redraw = false;
  1049. }
  1050. if (cursormoved)
  1051. {
  1052. cursorvis = false;
  1053. lasttime = TimeCount - TickBase;
  1054. cursormoved = false;
  1055. }
  1056. if (TimeCount - lasttime > TickBase / 2)
  1057. {
  1058. lasttime = TimeCount;
  1059. cursorvis ^= true;
  1060. }
  1061. if (cursorvis)
  1062. USL_XORICursor(x,y,s,cursor);
  1063. VW_UpdateScreen();
  1064. }
  1065. if (cursorvis)
  1066. USL_XORICursor(x,y,s,cursor);
  1067. if (!result)
  1068. {
  1069. px = x;
  1070. py = y;
  1071. USL_DrawString(olds);
  1072. }
  1073. VW_ShowCursor();
  1074. VW_UpdateScreen();
  1075. IN_ClearKeysDown();
  1076. return(result);
  1077. }
  1078. // Control panel routines
  1079. static boolean FlushHelp;
  1080. static WindowRec HelpWindow,BottomWindow;
  1081. typedef enum
  1082. {
  1083. uic_Draw,uic_Hit
  1084. } UserCall;
  1085. typedef enum
  1086. {
  1087. uii_Bad,uii_Button,uii_RadioButton,uii_CheckBox,uii_KeyCap
  1088. } UIType;
  1089. #define ui_Normal 0
  1090. #define ui_Selected 1
  1091. #define ui_Disabled 2
  1092. // Prototype the custom routines
  1093. static boolean USL_CtlButtonCustom(UserCall,word,word),
  1094. USL_CtlPButtonCustom(UserCall,word,word),
  1095. USL_CtlPSButtonCustom(UserCall,word,word),
  1096. USL_CtlPRButtonCustom(UserCall,word,word),
  1097. USL_CtlHButtonCustom(UserCall,word,word),
  1098. USL_CtlDButtonCustom(UserCall,word,word),
  1099. USL_CtlDEButtonCustom(UserCall,word,word),
  1100. USL_CtlDLButtonCustom(UserCall,word,word),
  1101. USL_CtlDSButtonCustom(UserCall,word,word),
  1102. USL_CtlSButtonCustom(UserCall,word,word),
  1103. USL_CtlCButtonCustom(UserCall,word,word),
  1104. USL_CtlCKbdButtonCustom(UserCall,word,word),
  1105. USL_CtlCJoyButtonCustom(UserCall,word,word);
  1106. // The structure of a user interaction item
  1107. typedef struct {
  1108. Rect r; // The enclosing rectangle
  1109. UIType type; // The type of item
  1110. int picup,picdown; // What to draw when up/down
  1111. char *help; // Floating help string
  1112. ScanCode key; // Key equiv
  1113. word sel; // Interaction flags (ui_XXX)
  1114. boolean (*custom)(UserCall,word,word); // Custom routine
  1115. char *text; // Text for some items
  1116. } UserItem;
  1117. typedef struct {
  1118. ScanCode key;
  1119. word i,n, // Hit CtlPanels2[i][n]
  1120. toi,ton; // Move to CtlPanels2[toi][ton]
  1121. } HotKey; // MARK
  1122. static ScanCode *KeyMaps[] =
  1123. {
  1124. &KbdDefs[0].button0,&KbdDefs[0].button1,
  1125. &KbdDefs[0].upleft,&KbdDefs[0].up,&KbdDefs[0].upright,
  1126. &KbdDefs[0].left, &KbdDefs[0].right,
  1127. &KbdDefs[0].downleft,&KbdDefs[0].down,&KbdDefs[0].downright,
  1128. };
  1129. // Some macros to make rectangle definition quite a bit less unpleasant
  1130. #define CtlPanelX 8
  1131. #define CtlPanelY 4
  1132. #define CtlPanel2X (8*8)
  1133. #define CtlPanel2Y (2*8)
  1134. #define CtlPanel3X (8*8)
  1135. #define CtlPanel3Y (7*8)
  1136. #define CtlPanelR(n) { CtlPanelX,CtlPanelY+(32 * (n)),\
  1137. CtlPanelX+40,CtlPanelY+(32 * (n)) + 32}
  1138. #define CtlPanel2R(x,y) { CtlPanel2X+(x)*8,CtlPanel2Y+(y)*8,\
  1139. CtlPanel2X+32+(x)*8,CtlPanel2Y+24+(y)*8}
  1140. #define CtlPanel3R(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
  1141. CtlPanel3X+32+(x)*8,CtlPanel3Y+24+(y)*8}
  1142. static UserItem CtlPanels[] =
  1143. {
  1144. {CtlPanelR(0),uii_RadioButton,CTL_STARTUPPIC,CTL_STARTDNPIC,"Start or Resume a Game",sc_None,ui_Normal,USL_CtlButtonCustom},
  1145. {CtlPanelR(1),uii_RadioButton,CTL_HELPUPPIC,CTL_HELPDNPIC,"Get Help With Commander Keen",sc_None,ui_Normal,USL_CtlButtonCustom},
  1146. {CtlPanelR(2),uii_RadioButton,CTL_DISKUPPIC,CTL_DISKDNPIC,"Load / Save / Quit",sc_None,ui_Normal,USL_CtlButtonCustom},
  1147. {CtlPanelR(3),uii_RadioButton,CTL_CONTROLSUPPIC,CTL_CONTROLSDNPIC,"Choose Controls",sc_C,ui_Normal,USL_CtlButtonCustom},
  1148. {CtlPanelR(4),uii_RadioButton,CTL_SOUNDUPPIC,CTL_SOUNDDNPIC,"Select Sound Device",sc_F2,ui_Normal,USL_CtlButtonCustom},
  1149. {CtlPanelR(5),uii_RadioButton,CTL_MUSICUPPIC,CTL_MUSICDNPIC,"Turn Music On / Off",sc_F7,ui_Normal,USL_CtlButtonCustom},
  1150. {-1,-1,-1,-1,uii_Bad}
  1151. },
  1152. CtlPPanels[] =
  1153. {
  1154. {CtlPanel2R(10,0),uii_RadioButton,CTL_P_NEWGAMEUPPIC,CTL_P_NEWGAMEDNPIC,"Choose Difficulty for the New Game",sc_F5,ui_Normal,USL_CtlPButtonCustom},
  1155. {CtlPanel2R(15,0),uii_RadioButton,CTL_P_RESUMEUPPIC,CTL_P_RESUMEDNPIC,"Go Back to Current Game",sc_None,ui_Normal,USL_CtlPButtonCustom},
  1156. {-1,-1,-1,-1,uii_Bad}
  1157. },
  1158. CtlPSPanels[] =
  1159. {
  1160. {CtlPanel3R(13,5),uii_Button,CTL_P_MEDUPPIC,CTL_P_MEDDNPIC,"Start New Game in Normal Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},
  1161. {CtlPanel3R(8,5),uii_Button,CTL_P_EASYUPPIC,CTL_P_EASYDNPIC,"Start New Game in Easy Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},
  1162. {CtlPanel3R(18,5),uii_Button,CTL_P_HARDUPPIC,CTL_P_HARDDNPIC,"Start New Game in Hard Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},
  1163. {-1,-1,-1,-1,uii_Bad}
  1164. },
  1165. CtlPRPanels[] =
  1166. {
  1167. {CtlPanel3R(13,5),uii_Button,CTL_P_GORESUMEUPPIC,CTL_P_GORESUMEDNPIC,"Resume Current Game",sc_None,ui_Normal,USL_CtlPRButtonCustom},
  1168. {-1,-1,-1,-1,uii_Bad}
  1169. },
  1170. CtlHPanels[] =
  1171. {
  1172. {CtlPanel2R(8,0),uii_Button,CTL_H_LOSTUPPIC,CTL_H_LOSTDNPIC,"Help Me, I'm Lost!",sc_F1,ui_Normal,USL_CtlHButtonCustom},
  1173. {CtlPanel2R(13,0),uii_Button,CTL_H_CTRLUPPIC,CTL_H_CTRLDNPIC,"Get Help with Controls",sc_None,ui_Normal,USL_CtlHButtonCustom},
  1174. {CtlPanel2R(18,0),uii_Button,CTL_H_STORYUPPIC,CTL_H_STORYDNPIC,"Read Story & Game Tips",sc_None,ui_Normal,USL_CtlHButtonCustom},
  1175. {-1,-1,-1,-1,uii_Bad}
  1176. },
  1177. CtlDPanels[] =
  1178. {
  1179. {CtlPanel2R(9,0),uii_RadioButton,CTL_D_LSGAMEUPPIC,CTL_D_LSGAMEDNPIC,"Load or Save a Game",sc_F6,ui_Normal,USL_CtlDButtonCustom},
  1180. {CtlPanel2R(15,0),uii_RadioButton,CTL_D_DOSUPPIC,CTL_D_DOSDNPIC,"Exit to DOS",sc_Q,ui_Normal,USL_CtlDButtonCustom},
  1181. {-1,-1,-1,-1,uii_Bad}
  1182. },
  1183. CtlDLSPanels[] =
  1184. {
  1185. #define CtlPanel3LSR(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
  1186. CtlPanel3X+32+(x)*8,CtlPanel3Y+16+(y)*8}
  1187. {CtlPanel3LSR(1,0),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
  1188. {CtlPanel3LSR(6,0),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
  1189. {CtlPanel3LSR(1,2),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
  1190. {CtlPanel3LSR(6,2),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
  1191. {CtlPanel3LSR(1,4),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
  1192. {CtlPanel3LSR(6,4),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
  1193. {CtlPanel3LSR(1,6),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
  1194. {CtlPanel3LSR(6,6),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
  1195. {CtlPanel3LSR(1,8),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
  1196. {CtlPanel3LSR(6,8),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
  1197. {CtlPanel3LSR(1,10),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
  1198. {CtlPanel3LSR(6,10),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
  1199. {CtlPanel3LSR(1,12),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
  1200. {CtlPanel3LSR(6,12),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
  1201. {-1,-1,-1,-1,uii_Bad}
  1202. },
  1203. CtlDEPanels[] =
  1204. {
  1205. #define CtlPanel3ER(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
  1206. CtlPanel3X+40+(x)*8,CtlPanel3Y+24+(y)*8}
  1207. {CtlPanel3ER(12,5),uii_Button,CTL_D_EXITUPPIC,CTL_D_EXITDNPIC,"Really Exit to DOS",sc_None,ui_Normal,USL_CtlDEButtonCustom},
  1208. {-1,-1,-1,-1,uii_Bad}
  1209. },
  1210. CtlCPanels[] =
  1211. {
  1212. {CtlPanel2R(8,0),uii_RadioButton,CTL_C_KBDUPPIC,CTL_C_KBDDNPIC,"Use / Configure Keyboard",sc_F3,ui_Normal,USL_CtlCButtonCustom},
  1213. {CtlPanel2R(13,0),uii_RadioButton,CTL_C_JOY1UPPIC,CTL_C_JOY1DNPIC,"Use / Configure Joystick 1",sc_None,ui_Normal,USL_CtlCButtonCustom},
  1214. {CtlPanel2R(18,0),uii_RadioButton,CTL_C_JOY2UPPIC,CTL_C_JOY2DNPIC,"Use / Configure Joystick 2",sc_None,ui_Normal,USL_CtlCButtonCustom},
  1215. {-1,-1,-1,-1,uii_Bad}
  1216. },
  1217. #define CtlPanelKC3R(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
  1218. CtlPanel3X+56+(x)*8,CtlPanel3Y+32+(y)*8}
  1219. CtlCKbdPanels[] =
  1220. {
  1221. {CtlPanelKC3R(1,2),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Jumping",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1222. {CtlPanelKC3R(1,6),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Throwing",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1223. {CtlPanelKC3R(8,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1224. {CtlPanelKC3R(15,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1225. {CtlPanelKC3R(22,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1226. {CtlPanelKC3R(8,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1227. {CtlPanelKC3R(22,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1228. {CtlPanelKC3R(8,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1229. {CtlPanelKC3R(15,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1230. {CtlPanelKC3R(22,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
  1231. {-1,-1,-1,-1,uii_Bad}
  1232. },
  1233. CtlCJoyPanels[] =
  1234. {
  1235. {CtlPanel3R(13,5),uii_Button,CTL_C_CALIBRATEUPPIC,CTL_C_CALIBRATEDNPIC,"Configure Joystick",sc_None,ui_Normal,USL_CtlCJoyButtonCustom},
  1236. {-1,-1,-1,-1,uii_Bad}
  1237. },
  1238. CtlSPanels[] =
  1239. {
  1240. {CtlPanel2R(3,0),uii_RadioButton,CTL_S_NOSNDUPPIC,CTL_S_NOSNDDNPIC,"Turn Sound Off",sc_None,ui_Normal,USL_CtlSButtonCustom},
  1241. {CtlPanel2R(8,0),uii_RadioButton,CTL_S_PCSNDUPPIC,CTL_S_PCSNDDNPIC,"Use PC Speaker",sc_None,ui_Normal,USL_CtlSButtonCustom},
  1242. {CtlPanel2R(13,0),uii_RadioButton,CTL_S_ADLIBUPPIC,CTL_S_ADLIBDNPIC,"Use AdLib Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},
  1243. {CtlPanel2R(18,0),uii_RadioButton,CTL_S_SNDBLUPPIC,CTL_S_SNDBLDNPIC,"Use SoundBlaster Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},
  1244. {CtlPanel2R(23,0),uii_RadioButton,CTL_S_SNDSRCUPPIC,CTL_S_SNDSRCDNPIC,"Use Sound Source Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},
  1245. {-1,-1,-1,-1,uii_Bad}
  1246. },
  1247. CtlSSSPanels[] =
  1248. {
  1249. {CtlPanel3R(7,2),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Turn Tandy Mode On / Off",sc_None,ui_Normal,0,"Tandy Mode"},
  1250. {CtlPanel3R(7,6),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Switch between LPT1 & LPT2",sc_None,ui_Normal,0,"Use LPT2"},
  1251. {-1,-1,-1,-1,uii_Bad}
  1252. },
  1253. CtlMPanels[] =
  1254. {
  1255. {CtlPanel2R(9,0),uii_RadioButton,CTL_M_NOMUSUPPIC,CTL_M_NOMUSDNPIC,"Background Music Off"},
  1256. {CtlPanel2R(15,0),uii_RadioButton,CTL_M_ADLIBUPPIC,CTL_M_ADLIBDNPIC,"Use AdLib/SoundBlaster Music"},
  1257. {-1,-1,-1,-1,uii_Bad}
  1258. },
  1259. *CtlPanels2[] =
  1260. {
  1261. CtlPPanels, // Start
  1262. CtlHPanels, // Help
  1263. CtlDPanels, // Disk
  1264. CtlCPanels, // Controls
  1265. CtlSPanels, // Sound
  1266. CtlMPanels // Music
  1267. },
  1268. *TheItems[4] = {CtlPanels};
  1269. static int CtlPanelButton;
  1270. ///////////////////////////////////////////////////////////////////////////
  1271. //
  1272. // USL_TurnOff() - Goes through a list of UserItems and sets them all to
  1273. // the normal state
  1274. //
  1275. ///////////////////////////////////////////////////////////////////////////
  1276. static void
  1277. USL_TurnOff(UserItem *ip)
  1278. {
  1279. while (ip->type != uii_Bad)
  1280. {
  1281. ip->sel = ui_Normal;
  1282. ip++;
  1283. }
  1284. }
  1285. ///////////////////////////////////////////////////////////////////////////
  1286. //
  1287. // USL_FindDown() - Finds which UserItem, if any, is selected in the given
  1288. // list
  1289. //
  1290. ///////////////////////////////////////////////////////////////////////////
  1291. static int
  1292. USL_FindDown(UserItem *ip)
  1293. {
  1294. int i;
  1295. for (i = 0;ip->type != uii_Bad;i++,ip++)
  1296. if (ip->sel & ui_Selected)
  1297. return(i);
  1298. return(-1);
  1299. }
  1300. ///////////////////////////////////////////////////////////////////////////
  1301. //
  1302. // USL_ShowHelp() - Shows the specified string in the help window
  1303. //
  1304. ///////////////////////////////////////////////////////////////////////////
  1305. static void
  1306. USL_ShowHelp(char *s)
  1307. {
  1308. WindowRec wr;
  1309. if (!s)
  1310. return;
  1311. US_SaveWindow(&wr);
  1312. US_RestoreWindow(&HelpWindow);
  1313. US_ClearWindow();
  1314. US_PrintCentered(s);
  1315. US_RestoreWindow(&wr);
  1316. }
  1317. ///////////////////////////////////////////////////////////////////////////
  1318. //
  1319. // USL_HandleError() - Handles telling the user that there's been an error
  1320. //
  1321. ///////////////////////////////////////////////////////////////////////////
  1322. static void
  1323. USL_HandleError(int num)
  1324. {
  1325. char buf[64];
  1326. strcpy(buf,"Error: ");
  1327. if (num < 0)
  1328. strcat(buf,"Unknown");
  1329. else if (num == ENOMEM)
  1330. strcat(buf,"Disk is Full");
  1331. else if (num == EINVFMT)
  1332. strcat(buf,"File is Incomplete");
  1333. else
  1334. strcat(buf,sys_errlist[num]);
  1335. VW_HideCursor();
  1336. fontcolor = F_SECONDCOLOR;
  1337. USL_ShowHelp(buf);
  1338. fontcolor = F_BLACK;
  1339. VW_UpdateScreen();
  1340. IN_ClearKeysDown();
  1341. IN_Ack();
  1342. VW_ShowCursor();
  1343. VW_UpdateScreen();
  1344. }
  1345. ///////////////////////////////////////////////////////////////////////////
  1346. //
  1347. // USL_DrawItem() - Draws a UserItem. If there's a custom routine, this will
  1348. // call it with a uic_Draw command. If the custom routine returns true,
  1349. // then the routine handled all of the drawing. If it returns false,
  1350. // then this routine does the default drawing.
  1351. //
  1352. ///////////////////////////////////////////////////////////////////////////
  1353. static void
  1354. USL_DrawItem(word hiti,word hitn)
  1355. {
  1356. boolean handled,centered;
  1357. char *text;
  1358. word w,h;
  1359. int picup,picdown;
  1360. Rect r;
  1361. UserItem *ip;
  1362. ip = &TheItems[hiti][hitn];
  1363. if (ip->custom)
  1364. handled = ip->custom(uic_Draw,hiti,hitn);
  1365. else
  1366. handled = false;
  1367. if (!handled)
  1368. {
  1369. picup = ip->picup;
  1370. picdown = ip->picdown;
  1371. switch (ip->type)
  1372. {
  1373. case uii_CheckBox:
  1374. px = ip->r.lr.x + 8;
  1375. py = ip->r.ul.y + 8;
  1376. text = ip->text;
  1377. centered = false;
  1378. break;
  1379. case uii_KeyCap:
  1380. if (!(ip->sel & ui_Selected))
  1381. {
  1382. text = ip->text;
  1383. if (text)
  1384. {
  1385. r = ip->r;
  1386. centered = true;
  1387. }
  1388. }
  1389. else
  1390. text = nil;
  1391. break;
  1392. default:
  1393. text = nil;
  1394. break;
  1395. }
  1396. VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,
  1397. (ip->sel & ui_Selected)? picdown : picup);
  1398. if (text)
  1399. {
  1400. if (centered)
  1401. USL_PrintInCenter(text,r);
  1402. else
  1403. {
  1404. USL_MeasureString(text,&w,&h);
  1405. VWB_Bar(px,py,w + 7,h,WHITE);
  1406. USL_DrawString(text);
  1407. }
  1408. }
  1409. if (ip->sel & ui_Disabled)
  1410. {
  1411. if ((picup == CTL_D_LOADUPPIC) || (picup == CTL_D_SAVEUPPIC))
  1412. VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LSMASKPICM);
  1413. else
  1414. VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LITTLEMASKPICM);
  1415. }
  1416. }
  1417. }
  1418. ///////////////////////////////////////////////////////////////////////////
  1419. //
  1420. // USL_DoHit() - Handles a hit on a UserItem. If there's a custom routine,
  1421. // it will be called. If it returns true, then don't do anything
  1422. // more. If it returns false, then use the standard behaviour
  1423. //
  1424. ///////////////////////////////////////////////////////////////////////////
  1425. static void
  1426. USL_DoHit(word hiti,word hitn)
  1427. {
  1428. boolean handled;
  1429. word i;
  1430. UserItem *ip;
  1431. ip = &TheItems[hiti][hitn];
  1432. if (ip->custom)
  1433. handled = ip->custom(uic_Hit,hiti,hitn);
  1434. else
  1435. handled = false;
  1436. if (!handled)
  1437. {
  1438. if (TheItems[hiti][hitn].sel & ui_Disabled)
  1439. {
  1440. fontcolor = F_SECONDCOLOR;
  1441. USL_ShowHelp("This Item is Disabled");
  1442. fontcolor = F_BLACK;
  1443. return;
  1444. }
  1445. FlushHelp = true;
  1446. switch (ip->type)
  1447. {
  1448. case uii_Button:
  1449. // Must have a custom routine to handle hits - this just redraws
  1450. ip->sel ^= ui_Selected;
  1451. USL_DrawItem(hiti,hitn);
  1452. case uii_CheckBox:
  1453. ip->sel ^= ui_Selected;
  1454. USL_DrawItem(hiti,hitn);
  1455. break;
  1456. case uii_RadioButton:
  1457. for (i = 0,ip = TheItems[hiti];ip->type != uii_Bad;i++,ip++)
  1458. {
  1459. if
  1460. (
  1461. (i != hitn)
  1462. && (ip->type == uii_RadioButton)
  1463. && (ip->sel & ui_Selected)
  1464. )
  1465. {
  1466. ip->sel &= ~ui_Selected;
  1467. USL_DrawItem(hiti,i);
  1468. }
  1469. }
  1470. TheItems[hiti][hitn].sel |= ui_Selected;
  1471. USL_DrawItem(hiti,hitn);
  1472. break;
  1473. case uii_KeyCap:
  1474. break;
  1475. }
  1476. }
  1477. }
  1478. ///////////////////////////////////////////////////////////////////////////
  1479. //
  1480. // USL_IsInRect() - Checks to see if the coordinates given are within any
  1481. // of the Rects in the UserItem list. If so, returns true & sets the
  1482. // index & number for lookup. If not, returns false.
  1483. //
  1484. ///////////////////////////////////////////////////////////////////////////
  1485. static boolean
  1486. USL_IsInRect(word x,word y,word *index,word *number)
  1487. {
  1488. UserItem *item,**items;
  1489. items = TheItems;
  1490. *index = 0;
  1491. while (*items)
  1492. {
  1493. item = *items;
  1494. *number = 0;
  1495. while (item->type != uii_Bad)
  1496. {
  1497. if
  1498. (
  1499. (x >= item->r.ul.x)
  1500. && (x < item->r.lr.x)
  1501. && (y >= item->r.ul.y)
  1502. && (y < item->r.lr.y)
  1503. )
  1504. return(true);
  1505. (*number)++;
  1506. item++;
  1507. }
  1508. (*index)++;
  1509. items++;
  1510. }
  1511. return(false);
  1512. }
  1513. ///////////////////////////////////////////////////////////////////////////
  1514. //
  1515. // USL_TrackItem() - Tracks the given item. If the cursor is inside of the
  1516. // item, it's redrawn as down. If the cursor is outside, the item is
  1517. // drawn in its original state. Returns true if the button was released
  1518. // while the cursor was inside the item, or false if it wasn't.
  1519. //
  1520. ///////////////////////////////////////////////////////////////////////////
  1521. static boolean
  1522. USL_TrackItem(word hiti,word hitn)
  1523. {
  1524. boolean inside,last;
  1525. word ini,inn,
  1526. on,
  1527. sel,othersel;
  1528. UserItem *ip,*op;
  1529. ip = &TheItems[hiti][hitn];
  1530. sel = ip->sel;
  1531. if (ip->type == uii_RadioButton)
  1532. {
  1533. inside = false;
  1534. for (op = TheItems[hiti],on = 0;op->type != uii_Bad;op++,on++)
  1535. {
  1536. if (op->sel & ui_Selected)
  1537. {
  1538. inside = true;
  1539. break;
  1540. }
  1541. }
  1542. if (!inside)
  1543. op = ip;
  1544. othersel = op->sel;
  1545. }
  1546. else
  1547. op = nil;
  1548. if (ip->sel & ui_Disabled)
  1549. {
  1550. fontcolor = F_SECONDCOLOR;
  1551. USL_ShowHelp("This item is disabled");
  1552. fontcolor = F_BLACK;
  1553. while (US_UpdateCursor())
  1554. VW_UpdateScreen();
  1555. FlushHelp = true;
  1556. return(false);
  1557. }
  1558. last = false;
  1559. do
  1560. {
  1561. USL_IsInRect(CursorX,CursorY,&ini,&inn);
  1562. inside = (ini == hiti) && (inn == hitn);
  1563. if (inside != last)
  1564. {
  1565. if (inside)
  1566. {
  1567. if (op)
  1568. {
  1569. op->sel &= ~ui_Selected;
  1570. ip->sel |= ui_Selected;
  1571. }
  1572. else
  1573. ip->sel = sel ^ ui_Selected;
  1574. }
  1575. else
  1576. {
  1577. if (op && (op != ip))
  1578. {
  1579. op->sel |= ui_Selected;
  1580. ip->sel &= ~ui_Selected;
  1581. }
  1582. else
  1583. ip->sel = sel;
  1584. }
  1585. USL_DrawItem(hiti,hitn);
  1586. if (op && (op != ip))
  1587. USL_DrawItem(hiti,on);
  1588. last = inside;
  1589. }
  1590. VW_UpdateScreen();
  1591. } while (US_UpdateCursor());
  1592. if (op)
  1593. op->sel = othersel;
  1594. ip->sel = sel;
  1595. if (!inside)
  1596. {
  1597. if (op && (op != ip))
  1598. USL_DrawItem(hiti,on);
  1599. USL_DrawItem(hiti,hitn);
  1600. VW_UpdateScreen();
  1601. }
  1602. return(inside);
  1603. }
  1604. ///////////////////////////////////////////////////////////////////////////
  1605. //
  1606. // USL_GlideCursor() - Smoothly moves the cursor to the given location
  1607. //
  1608. ///////////////////////////////////////////////////////////////////////////
  1609. static void
  1610. USL_GlideCursor(long newx,long newy)
  1611. {
  1612. word steps;
  1613. long x,y,
  1614. dx,dy;
  1615. if (grmode == CGAGR)
  1616. steps = 1;
  1617. else
  1618. steps = 8;
  1619. x = (long)CursorX << 16;
  1620. dx = ((newx << 16) - x) / steps;
  1621. y = (long)CursorY << 16;
  1622. dy = ((newy << 16) - y) / steps;
  1623. while ((CursorX != newx) || (CursorY != newy))
  1624. {
  1625. x += dx;
  1626. y += dy;
  1627. CursorX = x >> 16;
  1628. CursorY = y >> 16;
  1629. VW_MoveCursor(CursorX,CursorY);
  1630. VW_UpdateScreen();
  1631. }
  1632. CursorBad = true;
  1633. }
  1634. ///////////////////////////////////////////////////////////////////////////
  1635. //
  1636. // USL_FindRect() - Code so ugly you'll puke! Given a Rect and direction,
  1637. // this routine will try to find a UserItem to move the cursor to
  1638. //
  1639. ///////////////////////////////////////////////////////////////////////////
  1640. static void
  1641. USL_FindRect(Rect r,Motion xd,Motion yd)
  1642. {
  1643. word i,i1,i2,i3;
  1644. Motion m1,m2;
  1645. Point diffs[9],diff,*dp;
  1646. Rect *rp,*good,*goods[9];
  1647. UserItem *ip,**items;
  1648. for (m1 = motion_Up,dp = diffs;m1 <= motion_Down;m1++)
  1649. {
  1650. for (m2 = motion_Left;m2 <= motion_Right;m2++,dp++)
  1651. {
  1652. dp->x = m2 * 1024;
  1653. dp->y = m1 * 1024;
  1654. }
  1655. }
  1656. for (i = 0;i < 9;i++)
  1657. goods[i] = nil;
  1658. // Find out which octants all of the rects (except r) are in
  1659. for (items = TheItems;*items;items++)
  1660. {
  1661. for (ip = *items;ip->type != uii_Bad;ip++)
  1662. {
  1663. rp = &ip->r;
  1664. diff.x = rp->ul.x - r.ul.x;
  1665. diff.y = rp->ul.y - r.ul.y;
  1666. if (!(diff.x || diff.y))
  1667. continue;
  1668. if // 1,4,7
  1669. (
  1670. ((rp->ul.x >= r.ul.x) && (rp->ul.x < r.lr.x))
  1671. || ((rp->lr.x > r.ul.x) && (rp->lr.x <= r.lr.x))
  1672. )
  1673. {
  1674. if (rp->lr.y <= r.ul.y)
  1675. {
  1676. if (!(goods[1] && (diff.y < diffs[1].y)))
  1677. {
  1678. goods[1] = rp;
  1679. diffs[1] = diff;
  1680. }
  1681. }
  1682. else if (rp->ul.y >= r.lr.y)
  1683. {
  1684. if (!(goods[7] && (diff.y > diffs[7].y)))
  1685. {
  1686. goods[7] = rp;
  1687. diffs[7] = diff;
  1688. }
  1689. }
  1690. }
  1691. if // 3,4,5
  1692. (
  1693. ((rp->ul.y >= r.ul.y) && (rp->ul.y < r.lr.y))
  1694. || ((rp->lr.y > r.ul.y) && (rp->lr.y <= r.lr.y))
  1695. )
  1696. {
  1697. if (rp->lr.x <= r.ul.x)
  1698. {
  1699. if (!(goods[3] && (diff.x < diffs[3].x)))
  1700. {
  1701. goods[3] = rp;
  1702. diffs[3] = diff;
  1703. }
  1704. }
  1705. else if (rp->ul.x >= r.lr.x)
  1706. {
  1707. if (!(goods[5] && (diff.x > diffs[5].x)))
  1708. {
  1709. goods[5] = rp;
  1710. diffs[5] = diff;
  1711. }
  1712. }
  1713. }
  1714. if (rp->ul.x < r.ul.x) // 0,6
  1715. {
  1716. if (rp->lr.y <= r.ul.y)
  1717. {
  1718. if
  1719. (
  1720. (!goods[0])
  1721. || (diff.y > diffs[0].y)
  1722. || (diff.x > diffs[6].x)
  1723. )
  1724. {
  1725. goods[0] = rp;
  1726. diffs[0] = diff;
  1727. }
  1728. }
  1729. else if (rp->ul.y >= r.lr.y)
  1730. {
  1731. if
  1732. (
  1733. (!goods[6])
  1734. || (diff.y < diffs[6].y)
  1735. || (diff.x > diffs[6].x)
  1736. )
  1737. {
  1738. goods[6] = rp;
  1739. diffs[6] = diff;
  1740. }
  1741. }
  1742. }
  1743. if (rp->lr.x > r.lr.x) // 2,8
  1744. {
  1745. if (rp->lr.y <= r.ul.y)
  1746. {
  1747. if
  1748. (
  1749. (!goods[2])
  1750. || (diff.y > diffs[2].y)
  1751. || (diff.x < diffs[2].x)
  1752. )
  1753. {
  1754. goods[2] = rp;
  1755. diffs[2] = diff;
  1756. }
  1757. }
  1758. else if (rp->ul.y >= r.lr.y)
  1759. {
  1760. if
  1761. (
  1762. (!goods[8])
  1763. || (diff.y < diffs[8].y)
  1764. || (diff.x < diffs[8].x)
  1765. )
  1766. {
  1767. goods[8] = rp;
  1768. diffs[8] = diff;
  1769. }
  1770. }
  1771. }
  1772. }
  1773. }
  1774. switch (yd)
  1775. {
  1776. case motion_Up:
  1777. i1 = 1,i2 = 0,i3 = 2;
  1778. break;
  1779. case motion_None:
  1780. switch (xd)
  1781. {
  1782. case motion_Left:
  1783. i1 = 3,i2 = 0,i3 = 6;
  1784. break;
  1785. case motion_Right:
  1786. i1 = 5,i2 = 8,i3 = 2;
  1787. break;
  1788. }
  1789. break;
  1790. case motion_Down:
  1791. i1 = 7,i2 = 8,i3 = 6;
  1792. break;
  1793. }
  1794. (
  1795. (good = goods[i1])
  1796. || (good = goods[i2])
  1797. || (good = goods[i3])
  1798. || (good = &r)
  1799. );
  1800. #if 0
  1801. CursorX = good->lr.x - 8;
  1802. CursorY = good->lr.y - 8;
  1803. CursorBad = true;
  1804. US_UpdateCursor();
  1805. #endif
  1806. USL_GlideCursor(good->lr.x - 8,good->lr.y - 8);
  1807. }
  1808. ///////////////////////////////////////////////////////////////////////////
  1809. //
  1810. // USL_CtlButtonCustom() - The custom routine for all of the Control Panel
  1811. // (leftmost) buttons. Clears all of the other item lists, clears the
  1812. // large area, and draws the line dividing the top and bottom areas.
  1813. // Then it sets up and draws the appropriate top row of icons.
  1814. //
  1815. ///////////////////////////////////////////////////////////////////////////
  1816. static boolean
  1817. USL_CtlButtonCustom(UserCall call,word i,word n)
  1818. {
  1819. word j;
  1820. UserItem *ip;
  1821. if (call != uic_Hit)
  1822. return(false);
  1823. if (n == CtlPanelButton)
  1824. return(true);
  1825. US_ClearWindow();
  1826. for (j = 8;j < 38;j++)
  1827. {
  1828. VWB_DrawTile8M(j * 8,6 * 8,10);
  1829. VWB_DrawTile8M(j * 8,21 * 8,10);
  1830. }
  1831. VWB_DrawTile8M(7 * 8,6 * 8,9);
  1832. VWB_DrawTile8M(38 * 8,6 * 8,11);
  1833. VWB_DrawTile8M(7 * 8,21 * 8,9);
  1834. VWB_DrawTile8M(38 * 8,21 * 8,11);
  1835. for (j = 1;j < 4;j++)
  1836. TheItems[j] = nil;
  1837. // Set to new button
  1838. CtlPanelButton = n;
  1839. // Draw new items
  1840. TheItems[1] = ip = CtlPanels2[CtlPanelButton];
  1841. j = 0;
  1842. while (ip && (ip->type != uii_Bad))
  1843. {
  1844. USL_DrawItem(i + 1,j);
  1845. if (ip->sel & ui_Selected)
  1846. USL_DoHit(i + 1,j);
  1847. j++;
  1848. ip++;
  1849. }
  1850. return(false);
  1851. }
  1852. ///////////////////////////////////////////////////////////////////////////
  1853. //
  1854. // USL_CtlCKbdButtonCustom() - The custom routine for the keyboard keycaps.
  1855. // This routine gets a scancode and puts it in the appropriate
  1856. // KbdDefs[0] member.
  1857. //
  1858. ///////////////////////////////////////////////////////////////////////////
  1859. static boolean
  1860. USL_CtlCKbdButtonCustom(UserCall call,word i,word n)
  1861. {
  1862. boolean state;
  1863. word j;
  1864. ScanCode scan;
  1865. longword time;
  1866. UserItem *ip;
  1867. if (call != uic_Hit)
  1868. return(false);
  1869. ip = &TheItems[i][n];
  1870. fontcolor = F_SECONDCOLOR;
  1871. USL_ShowHelp(ip->help);
  1872. fontcolor = F_BLACK;
  1873. VW_HideCursor();
  1874. VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picdown);
  1875. VW_UpdateScreen();
  1876. LastScan = sc_None;
  1877. time = TimeCount;
  1878. state = true;
  1879. do
  1880. {
  1881. if (TimeCount - time > 35) // Half-second delays
  1882. {
  1883. state ^= true;
  1884. VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,state? ip->picdown : ip->picup);
  1885. VW_UpdateScreen();
  1886. time = TimeCount;
  1887. }
  1888. if (US_UpdateCursor())
  1889. {
  1890. while (US_UpdateCursor())
  1891. ;
  1892. scan = sc_Escape;
  1893. break;
  1894. }
  1895. asm pushf
  1896. asm cli
  1897. if (LastScan == sc_LShift)
  1898. LastScan = sc_None;
  1899. asm popf
  1900. } while (!(scan = LastScan));
  1901. IN_ClearKey(scan);
  1902. if (scan != sc_Escape)
  1903. {
  1904. for (j = 0,state = false;j < 10;j++)
  1905. {
  1906. if (j == n)
  1907. continue;
  1908. if (*(KeyMaps[j]) == scan)
  1909. {
  1910. state = true;
  1911. break;
  1912. }
  1913. }
  1914. if (state)
  1915. {
  1916. fontcolor = F_SECONDCOLOR;
  1917. USL_ShowHelp("That Key is Already Used!");
  1918. fontcolor = F_BLACK;
  1919. }
  1920. else
  1921. {
  1922. ip->text = IN_GetScanName(scan);
  1923. *(KeyMaps[n]) = scan;
  1924. FlushHelp = true;
  1925. }
  1926. }
  1927. USL_DrawItem(i,n);
  1928. VW_ShowCursor();
  1929. VW_UpdateScreen();
  1930. return(true);
  1931. }
  1932. ///////////////////////////////////////////////////////////////////////////
  1933. //
  1934. // USL_CtlCJoyButtonCustom() - The custom button routine for joystick
  1935. // calibration
  1936. //
  1937. ///////////////////////////////////////////////////////////////////////////
  1938. static boolean
  1939. USL_CtlCJoyButtonCustom(UserCall call,word i,word n)
  1940. {
  1941. word joy,
  1942. minx,maxx,
  1943. miny,maxy;
  1944. i++,n++; // Shut the compiler up
  1945. if (call != uic_Hit)
  1946. return(false);
  1947. IN_ClearKeysDown();
  1948. joy = USL_FindDown(CtlCPanels) - 1;
  1949. VW_HideCursor();
  1950. FlushHelp = true;
  1951. fontcolor = F_SECONDCOLOR;
  1952. USL_ShowHelp("Move Joystick to the Upper-Left");
  1953. VW_UpdateScreen();
  1954. while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))
  1955. ;
  1956. if (LastScan != sc_Escape)
  1957. {
  1958. IN_GetJoyAbs(joy,&minx,&miny);
  1959. while (IN_GetJoyButtonsDB(joy))
  1960. ;
  1961. USL_ShowHelp("Move Joystick to the Lower-Right");
  1962. VW_UpdateScreen();
  1963. while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))
  1964. ;
  1965. if (LastScan != sc_Escape)
  1966. {
  1967. IN_GetJoyAbs(0,&maxx,&maxy);
  1968. IN_SetupJoy(joy,minx,maxx,miny,maxy);
  1969. }
  1970. }
  1971. if (LastScan != sc_Escape)
  1972. while (IN_GetJoyButtonsDB(joy))
  1973. ;
  1974. if (LastScan)
  1975. IN_ClearKeysDown();
  1976. fontcolor = F_BLACK;
  1977. VW_ShowCursor();
  1978. return(false);
  1979. }
  1980. ///////////////////////////////////////////////////////////////////////////
  1981. //
  1982. // USL_ClearBottom() - Clears the bottom part of the window
  1983. //
  1984. ///////////////////////////////////////////////////////////////////////////
  1985. static void
  1986. USL_ClearBottom(void)
  1987. {
  1988. WindowRec wr;
  1989. US_SaveWindow(&wr);
  1990. US_RestoreWindow(&BottomWindow);
  1991. US_ClearWindow();
  1992. US_RestoreWindow(&wr);
  1993. }
  1994. ///////////////////////////////////////////////////////////////////////////
  1995. //
  1996. // USL_FormatHelp() - Formats helptext. Runs through and calculates the
  1997. // number of lines, and the offset for the start of each line. Stops
  1998. // after len bytes or when it hits a tilde ('~'). Munges the text.
  1999. //
  2000. ///////////////////////////////////////////////////////////////////////////
  2001. static word
  2002. USL_FormatHelp(char far *text,long len)
  2003. {
  2004. word line,
  2005. w,h,
  2006. far *off;
  2007. char c,
  2008. far *s,far *l,far *le;
  2009. WindowX += 4;
  2010. WindowW -= 4;
  2011. MM_GetPtr(&LineOffsets,MaxHelpLines * sizeof(word));
  2012. off = (word far *)LineOffsets;
  2013. for (line = 0,le = l = s = text;(s - text < len) && (*s != '~');s++)
  2014. {
  2015. if ((c = *s) == '\n')
  2016. {
  2017. *s = '\0';
  2018. *off++ = l - text; // Save offset of start of line
  2019. line++; // Bump line number
  2020. le = l = s + 1; // Set start of line ptr
  2021. }
  2022. if (c == '\r')
  2023. c = *s = ' ';
  2024. if // Strip orphaned spaces
  2025. (
  2026. (c == ' ')
  2027. && (s == l)
  2028. && (*(s - 1) == '\0')
  2029. && (*(s + 1) != ' ')
  2030. && (s > text)
  2031. )
  2032. le = l = s + 1;
  2033. else if (c == ' ')
  2034. {
  2035. *s = '\0';
  2036. USL_MeasureString(l,&w,&h);
  2037. if (w >= WindowW) // If string width exceeds window,
  2038. {
  2039. *s = c; // Replace null char with proper char
  2040. *le = '\0'; // Go back to last line end
  2041. *off++ = l - text; // Save offset of start of line
  2042. line++; // Bump line number
  2043. l = s = le + 1; // Start next time through after last line end
  2044. }
  2045. else
  2046. {
  2047. *s = c; // Width still ok - put char back
  2048. le = s; // And save ptr to last ok end of word
  2049. }
  2050. }
  2051. }
  2052. WindowX -= 4;
  2053. WindowW += 4;
  2054. return(line);
  2055. }
  2056. ///////////////////////////////////////////////////////////////////////////
  2057. //
  2058. // USL_DrawHelp() - Draws helptext in the current window
  2059. //
  2060. ///////////////////////////////////////////////////////////////////////////
  2061. static void
  2062. USL_DrawHelp(char far *text,word start,word end,word line,word h,word far *lp)
  2063. {
  2064. px = WindowX + 4;
  2065. py = WindowY + (line * h);
  2066. for (lp += start;start < end;start++,px = WindowX + 4,py += h)
  2067. USL_DrawString(text + *lp++);
  2068. }
  2069. ///////////////////////////////////////////////////////////////////////////
  2070. //
  2071. // USL_DoHelp() - Formats and displays the specified help
  2072. //
  2073. ///////////////////////////////////////////////////////////////////////////
  2074. static void
  2075. USL_DoHelp(memptr text,long len)
  2076. {
  2077. boolean done,
  2078. moved;
  2079. int scroll;
  2080. word i,
  2081. pixdiv,
  2082. w,h,
  2083. lines,cur,page,
  2084. top,num,loc,
  2085. far *lp,
  2086. base,srcbase,destbase;
  2087. ScanCode waitkey;
  2088. longword lasttime;
  2089. WindowRec wr;
  2090. CursorInfo info;
  2091. USL_ShowHelp("Arrow Keys Move / Escape Exits");
  2092. fontcolor = F_BLACK;
  2093. US_SaveWindow(&wr);
  2094. US_RestoreWindow(&BottomWindow);
  2095. US_ClearWindow();
  2096. VW_HideCursor();
  2097. VW_UpdateScreen();
  2098. lines = USL_FormatHelp((char far *)text,len);
  2099. USL_MeasureString("",&w,&h);
  2100. page = WindowH / h;
  2101. cur = 0;
  2102. lp = LineOffsets;
  2103. IN_ClearKeysDown();
  2104. moved = true;
  2105. lasttime = 0;
  2106. scroll = 0;
  2107. done = false;
  2108. waitkey = sc_None;
  2109. while (!done)
  2110. {
  2111. if (moved)
  2112. {
  2113. while (TimeCount - lasttime < 5)
  2114. ;
  2115. lasttime = TimeCount;
  2116. if (scroll == -1)
  2117. {
  2118. top = cur;
  2119. num = 1;
  2120. loc = 0;
  2121. }
  2122. else if (scroll == +1)
  2123. {
  2124. num = 1;
  2125. loc = page - 1;
  2126. top = cur + loc;
  2127. }
  2128. else
  2129. {
  2130. top = cur;
  2131. num = (page < lines)? page : lines;
  2132. loc = 0;
  2133. }
  2134. if (scroll)
  2135. {
  2136. if (grmode == CGAGR)
  2137. {
  2138. pixdiv = 4;
  2139. base = bufferofs + panadjust + (WindowX / pixdiv);
  2140. }
  2141. else if (grmode == EGAGR)
  2142. {
  2143. VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);
  2144. USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);
  2145. pixdiv = 8;
  2146. base = displayofs + panadjust + (WindowX / pixdiv);
  2147. }
  2148. else if (grmode == VGAGR)
  2149. pixdiv = 1;
  2150. if (scroll == 1)
  2151. {
  2152. srcbase = base + ylookup[WindowY + h];
  2153. destbase = base + ylookup[WindowY];
  2154. if (grmode == EGAGR)
  2155. {
  2156. EGAWRITEMODE(1);
  2157. VW_WaitVBL(1);
  2158. }
  2159. VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,
  2160. WindowH - h);
  2161. }
  2162. else
  2163. {
  2164. i = WindowY + (h * (page - 1));
  2165. srcbase = base + ylookup[i - h];
  2166. destbase = base + ylookup[i];
  2167. base = ylookup[h];
  2168. for (i = page - 1;i;i--,srcbase -= base,destbase -= base)
  2169. VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,h);
  2170. }
  2171. if (grmode == CGAGR)
  2172. {
  2173. VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);
  2174. USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);
  2175. VW_UpdateScreen();
  2176. }
  2177. else if (grmode == EGAGR)
  2178. {
  2179. base = panadjust + (WindowX / pixdiv) +
  2180. ylookup[WindowY + (loc * h)];
  2181. VW_ScreenToScreen(base + bufferofs,base + displayofs,
  2182. WindowW / pixdiv,h);
  2183. }
  2184. }
  2185. else
  2186. {
  2187. US_ClearWindow();
  2188. USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);
  2189. VW_UpdateScreen();
  2190. }
  2191. moved = false;
  2192. scroll = 0;
  2193. }
  2194. if (waitkey)
  2195. while (IN_KeyDown(waitkey))
  2196. ;
  2197. waitkey = sc_None;
  2198. IN_ReadCursor(&info);
  2199. if (info.y < 0)
  2200. {
  2201. if (cur > 0)
  2202. {
  2203. scroll = -1;
  2204. cur--;
  2205. moved = true;
  2206. }
  2207. }
  2208. else if (info.y > 0)
  2209. {
  2210. if (cur + page < lines)
  2211. {
  2212. scroll = +1;
  2213. cur++;
  2214. moved = true;
  2215. }
  2216. }
  2217. else if (info.button0 || info.button1)
  2218. done = true;
  2219. else if (IN_KeyDown(LastScan))
  2220. {
  2221. switch (LastScan)
  2222. {
  2223. case sc_Escape:
  2224. done = true;
  2225. break;
  2226. case sc_UpArrow:
  2227. if (cur > 0)
  2228. {
  2229. scroll = -1;
  2230. cur--;
  2231. moved = true;
  2232. }
  2233. break;
  2234. case sc_DownArrow:
  2235. if (cur + page < lines)
  2236. {
  2237. scroll = +1;
  2238. cur++;
  2239. moved = true;
  2240. }
  2241. break;
  2242. case sc_PgUp:
  2243. if (cur > page)
  2244. cur -= page;
  2245. else
  2246. cur = 0;
  2247. moved = true;
  2248. waitkey = sc_PgUp;
  2249. break;
  2250. case sc_PgDn:
  2251. if (cur + page < lines)
  2252. {
  2253. cur += page;
  2254. if (cur + page >= lines)
  2255. cur = lines - page;
  2256. moved = true;
  2257. }
  2258. waitkey = sc_PgDn;
  2259. break;
  2260. }
  2261. }
  2262. }
  2263. IN_ClearKeysDown();
  2264. do
  2265. {
  2266. IN_ReadCursor(&info);
  2267. } while (info.button0 || info.button1);
  2268. VW_ShowCursor();
  2269. US_ClearWindow();
  2270. VW_UpdateScreen();
  2271. US_RestoreWindow(&wr);
  2272. }
  2273. ///////////////////////////////////////////////////////////////////////////
  2274. //
  2275. // USL_CtlHButtonCustom() - The custom routine for all of the help buttons
  2276. //
  2277. ///////////////////////////////////////////////////////////////////////////
  2278. static boolean
  2279. USL_CtlHButtonCustom(UserCall call,word i,word n)
  2280. {
  2281. word j;
  2282. UserItem *ip;
  2283. if (call != uic_Hit)
  2284. return(false);
  2285. ip = &TheItems[i][n];
  2286. if (ip->sel & ui_Disabled)
  2287. return(false);
  2288. ip->sel |= ui_Selected;
  2289. USL_DrawItem(i,n);
  2290. USL_ClearBottom();
  2291. fontcolor = F_SECONDCOLOR;
  2292. USL_ShowHelp("Loading & Formatting Text...");
  2293. VW_UpdateScreen();
  2294. #ifdef HELPTEXTLINKED // Ugly hack because of lack of disk space...
  2295. {
  2296. extern char far gametext,far context,far story;
  2297. char far *buf;
  2298. memptr dupe;
  2299. switch (n)
  2300. {
  2301. case 0:
  2302. buf = &gametext;
  2303. break;
  2304. case 1:
  2305. buf = &context;
  2306. break;
  2307. case 2:
  2308. buf = &story;
  2309. break;
  2310. }
  2311. MM_GetPtr(&dupe,5000);
  2312. _fmemcpy((char far *)dupe,buf,5000);
  2313. USL_DoHelp(dupe,5000);
  2314. MM_FreePtr(&dupe);
  2315. if (LineOffsets)
  2316. MM_FreePtr(&LineOffsets);
  2317. }
  2318. #else
  2319. {
  2320. char *name;
  2321. int file;
  2322. long len;
  2323. memptr buf;
  2324. switch (n)
  2325. {
  2326. case 0:
  2327. name = "GAMETEXT."EXTENSION;
  2328. break;
  2329. case 1:
  2330. name = "CONTEXT."EXTENSION;
  2331. break;
  2332. case 2:
  2333. name = "STORY."EXTENSION;
  2334. break;
  2335. default:
  2336. Quit("Bad help button number");
  2337. }
  2338. if ((file = open(name,O_RDONLY | O_TEXT)) == -1)
  2339. USL_HandleError(errno);
  2340. else
  2341. {
  2342. len = filelength(file);
  2343. MM_GetPtr(&buf,len);
  2344. if (CA_FarRead(file,(byte far *)buf,len))
  2345. USL_DoHelp(buf,len);
  2346. else
  2347. USL_HandleError(errno);
  2348. close(file);
  2349. MM_FreePtr(&buf);
  2350. }
  2351. if (LineOffsets)
  2352. MM_FreePtr(&LineOffsets);
  2353. }
  2354. #endif
  2355. fontcolor = F_BLACK;
  2356. ip->sel &= ~ui_Selected;
  2357. USL_DrawItem(i,n);
  2358. return(false);
  2359. }
  2360. ///////////////////////////////////////////////////////////////////////////
  2361. //
  2362. // USL_CtlDButtonCustom() - The custom routine for all of the disk buttons.
  2363. // Sets up the bottom area of the window with the appropriate buttons
  2364. //
  2365. ///////////////////////////////////////////////////////////////////////////
  2366. static boolean
  2367. USL_CtlDButtonCustom(UserCall call,word i,word n)
  2368. {
  2369. word j;
  2370. UserItem *ip;
  2371. if (call != uic_Hit)
  2372. return(false);
  2373. ip = &TheItems[i][n];
  2374. if (ip->sel & ui_Disabled)
  2375. return(false);
  2376. USL_ClearBottom();
  2377. j = 0;
  2378. TheItems[i + 1] = ip = n? CtlDEPanels : CtlDLSPanels;
  2379. while (ip && (ip->type != uii_Bad))
  2380. {
  2381. USL_DrawItem(i + 1,j++);
  2382. ip++;
  2383. }
  2384. return(false);
  2385. }
  2386. ///////////////////////////////////////////////////////////////////////////
  2387. //
  2388. // USL_DLSRect() - Draw the rectangle for the save game names
  2389. //
  2390. ///////////////////////////////////////////////////////////////////////////
  2391. static Rect
  2392. USL_DLSRect(UserItem *ip)
  2393. {
  2394. Rect r;
  2395. r.ul.x = ip->r.lr.x + 40 + 2;
  2396. r.ul.y = ip->r.ul.y + 2;
  2397. r.lr.x = WindowX + WindowW - 8 - 2;
  2398. r.lr.y = ip->r.lr.y - 2;
  2399. VWB_Bar(r.ul.x,r.ul.y,r.lr.x - r.ul.x,r.lr.y - r.ul.y,WHITE);
  2400. VWB_Hlin(r.ul.x,r.lr.x,r.ul.y,BLACK);
  2401. VWB_Hlin(r.ul.x,r.lr.x,r.lr.y,BLACK);
  2402. VWB_Vlin(r.ul.y,r.lr.y,r.ul.x,BLACK);
  2403. VWB_Vlin(r.ul.y,r.lr.y,r.lr.x,BLACK);
  2404. px = r.ul.x + 2;
  2405. py = r.ul.y + 2;
  2406. return(r);
  2407. }
  2408. ///////////////////////////////////////////////////////////////////////////
  2409. //
  2410. // USL_CtlDLButtonCustom() - The load game custom routine
  2411. //
  2412. ///////////////////////////////////////////////////////////////////////////
  2413. static boolean
  2414. USL_CtlDLButtonCustom(UserCall call,word i,word n)
  2415. {
  2416. char *filename,
  2417. msg[MaxGameName + 12];
  2418. word err;
  2419. int file;
  2420. UserItem *ip;
  2421. SaveGame *game;
  2422. WindowRec wr;
  2423. // DEBUG - deal with warning user about loading a game causing abort
  2424. game = &Games[n / 2];
  2425. ip = &TheItems[i][n];
  2426. switch (call)
  2427. {
  2428. case uic_Draw:
  2429. if (!loadedgame)
  2430. {
  2431. USL_DLSRect(ip);
  2432. fontcolor = game->present? F_BLACK : F_FIRSTCOLOR;
  2433. USL_DrawString(game->present? game->name : "Empty");
  2434. fontcolor = F_BLACK;
  2435. }
  2436. break;
  2437. case uic_Hit:
  2438. if (ip->sel & ui_Disabled)
  2439. return(false);
  2440. LeaveDriveOn++;
  2441. filename = USL_GiveSaveName(n / 2);
  2442. US_SaveWindow(&wr);
  2443. US_CenterWindow(30,3);
  2444. strcpy(msg,"Loading `");
  2445. strcat(msg,game->name);
  2446. strcat(msg,"\'");
  2447. US_PrintCentered(msg);
  2448. VW_HideCursor();
  2449. VW_UpdateScreen();
  2450. err = 0;
  2451. if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)
  2452. {
  2453. if (read(file,game,sizeof(*game)) == sizeof(*game))
  2454. {
  2455. if (USL_LoadGame)
  2456. if (!USL_LoadGame(file))
  2457. USL_HandleError(err = errno);
  2458. }
  2459. else
  2460. USL_HandleError(err = errno);
  2461. close(file);
  2462. }
  2463. else
  2464. USL_HandleError(err = errno);
  2465. if (err)
  2466. abortgame = true;
  2467. else
  2468. loadedgame = true;
  2469. game->present = true;
  2470. if (loadedgame)
  2471. Paused = true;
  2472. VW_ShowCursor();
  2473. US_RestoreWindow(&wr);
  2474. LeaveDriveOn--;
  2475. break;
  2476. }
  2477. return(false);
  2478. }
  2479. ///////////////////////////////////////////////////////////////////////////
  2480. //
  2481. // USL_CtlDSButtonCustom() - The save game custom routine
  2482. //
  2483. ///////////////////////////////////////////////////////////////////////////
  2484. static boolean
  2485. USL_CtlDSButtonCustom(UserCall call,word i,word n)
  2486. {
  2487. boolean ok;
  2488. char *filename;
  2489. word err;
  2490. int file;
  2491. Rect r;
  2492. UserItem *ip;
  2493. SaveGame *game;
  2494. WindowRec wr;
  2495. if (call != uic_Hit)
  2496. return(false);
  2497. game = &Games[n / 2];
  2498. ip = &TheItems[i][n];
  2499. if (ip->sel & ui_Disabled)
  2500. return(false);
  2501. FlushHelp = true;
  2502. fontcolor = F_SECONDCOLOR;
  2503. USL_ShowHelp("Enter Game Name / Escape Aborts");
  2504. fontcolor = F_BLACK;
  2505. r = USL_DLSRect(ip - 1);
  2506. ok = US_LineInput(px,py,game->name,game->present? game->name : nil,true,
  2507. MaxGameName,r.lr.x - r.ul.x - 8);
  2508. if (!strlen(game->name))
  2509. strcpy(game->name,"Untitled");
  2510. if (ok)
  2511. {
  2512. US_SaveWindow(&wr);
  2513. US_CenterWindow(10,3);
  2514. US_PrintCentered("Saving");
  2515. VW_HideCursor();
  2516. VW_UpdateScreen();
  2517. LeaveDriveOn++;
  2518. filename = USL_GiveSaveName(n / 2);
  2519. err = 0;
  2520. file = open(filename,O_CREAT | O_BINARY | O_WRONLY,
  2521. S_IREAD | S_IWRITE | S_IFREG);
  2522. if (file != -1)
  2523. {
  2524. if (write(file,game,sizeof(*game)) == sizeof(*game))
  2525. {
  2526. if (USL_SaveGame)
  2527. ok = USL_SaveGame(file);
  2528. if (!ok)
  2529. USL_HandleError(err = errno);
  2530. }
  2531. else
  2532. USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));
  2533. close(file);
  2534. }
  2535. else
  2536. USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));
  2537. if (err)
  2538. {
  2539. remove(filename);
  2540. ok = false;
  2541. }
  2542. LeaveDriveOn--;
  2543. VW_ShowCursor();
  2544. US_RestoreWindow(&wr);
  2545. USL_DoHit(i - 1,0);
  2546. VW_UpdateScreen();
  2547. }
  2548. if (!game->present)
  2549. game->present = ok;
  2550. if (ok)
  2551. {
  2552. GameIsDirty = false;
  2553. (ip - 1)->sel &= ~ui_Disabled;
  2554. }
  2555. USL_DrawItem(i,n - 1);
  2556. // USL_CtlDLButtonCustom(uic_Draw,i,n - 1);
  2557. return(true);
  2558. }
  2559. ///////////////////////////////////////////////////////////////////////////
  2560. //
  2561. // USL_CtlSButtonCustom() - The custom routine for all of the sound buttons
  2562. //
  2563. ///////////////////////////////////////////////////////////////////////////
  2564. static boolean
  2565. USL_CtlSButtonCustom(UserCall call,word i,word n)
  2566. {
  2567. word j;
  2568. UserItem *ip;
  2569. if (call != uic_Hit)
  2570. return(false);
  2571. ip = &TheItems[i][n];
  2572. if (ip->sel & ui_Disabled)
  2573. return(false);
  2574. USL_ClearBottom();
  2575. if (n == sdm_SoundSource)
  2576. {
  2577. j = 0;
  2578. TheItems[i + 1] = ip = CtlSSSPanels;
  2579. while (ip && (ip->type != uii_Bad))
  2580. {
  2581. USL_DrawItem(i + 1,j++);
  2582. ip++;
  2583. }
  2584. }
  2585. else
  2586. TheItems[i + 1] = nil;
  2587. return(false);
  2588. }
  2589. ///////////////////////////////////////////////////////////////////////////
  2590. //
  2591. // USL_CtlPButtonCustom() - The custom routine for all of the start game btns
  2592. //
  2593. ///////////////////////////////////////////////////////////////////////////
  2594. static boolean
  2595. USL_CtlPButtonCustom(UserCall call,word i,word n)
  2596. {
  2597. word j;
  2598. UserItem *ip;
  2599. if (call != uic_Hit)
  2600. return(false);
  2601. ip = &TheItems[i][n];
  2602. if (ip->sel & ui_Disabled)
  2603. return(false);
  2604. USL_ClearBottom();
  2605. j = 0;
  2606. TheItems[i + 1] = ip = n? CtlPRPanels : CtlPSPanels;
  2607. while (ip && (ip->type != uii_Bad))
  2608. {
  2609. USL_DrawItem(i + 1,j++);
  2610. ip++;
  2611. }
  2612. return(false);
  2613. }
  2614. ///////////////////////////////////////////////////////////////////////////
  2615. //
  2616. // USL_GiveAbortWarning() - Draws a string that warns the user that an
  2617. // action they're about to take will abort the game in progress
  2618. //
  2619. ///////////////////////////////////////////////////////////////////////////
  2620. static void
  2621. USL_GiveAbortWarning(void)
  2622. {
  2623. WindowRec wr;
  2624. if (!GameIsDirty)
  2625. return;
  2626. US_SaveWindow(&wr);
  2627. US_RestoreWindow(&BottomWindow);
  2628. US_HomeWindow();
  2629. PrintY += 5;
  2630. VWB_Bar(WindowX,WindowY,WindowW,30,WHITE);
  2631. fontcolor = F_SECONDCOLOR;
  2632. US_CPrint("Warning! If you do this, you'll");
  2633. US_CPrint("abort the current game.");
  2634. fontcolor = F_BLACK;
  2635. US_RestoreWindow(&wr);
  2636. }
  2637. ///////////////////////////////////////////////////////////////////////////
  2638. //
  2639. // USL_CtlPSButtonCustom() - The custom routine for the start game button
  2640. //
  2641. ///////////////////////////////////////////////////////////////////////////
  2642. static boolean
  2643. USL_CtlPSButtonCustom(UserCall call,word i,word n)
  2644. {
  2645. boolean result;
  2646. UserItem *ip;
  2647. i++; // Shut the compiler up
  2648. switch (call)
  2649. {
  2650. case uic_Hit:
  2651. switch (n)
  2652. {
  2653. case 0:
  2654. restartgame = gd_Normal;
  2655. break;
  2656. case 1:
  2657. restartgame = gd_Easy;
  2658. break;
  2659. case 2:
  2660. restartgame = gd_Hard;
  2661. break;
  2662. }
  2663. if (restartgame && ingame && USL_ResetGame)
  2664. USL_ResetGame();
  2665. result = false;
  2666. break;
  2667. case uic_Draw:
  2668. USL_GiveAbortWarning();
  2669. result = false;
  2670. break;
  2671. default:
  2672. result = false;
  2673. break;
  2674. }
  2675. return(result);
  2676. }
  2677. ///////////////////////////////////////////////////////////////////////////
  2678. //
  2679. // USL_CtlPRButtonCustom() - The custom routine for the resume game button
  2680. //
  2681. ///////////////////////////////////////////////////////////////////////////
  2682. static boolean
  2683. USL_CtlPRButtonCustom(UserCall call,word i,word n)
  2684. {
  2685. if (call != uic_Hit)
  2686. return(false);
  2687. i++,n++; // Shut the compiler up
  2688. ResumeGame = true;
  2689. return(false);
  2690. }
  2691. ///////////////////////////////////////////////////////////////////////////
  2692. //
  2693. // USL_CtlDEButtonCustom() - The custom routine for the exit to DOS button
  2694. //
  2695. ///////////////////////////////////////////////////////////////////////////
  2696. static boolean
  2697. USL_CtlDEButtonCustom(UserCall call,word i,word n)
  2698. {
  2699. boolean result;
  2700. UserItem *ip;
  2701. i++,n++; // Shut the compiler up
  2702. switch (call)
  2703. {
  2704. case uic_Hit:
  2705. QuitToDos = true;
  2706. break;
  2707. case uic_Draw:
  2708. USL_GiveAbortWarning();
  2709. default:
  2710. result = false;
  2711. break;
  2712. }
  2713. return(result);
  2714. }
  2715. ///////////////////////////////////////////////////////////////////////////
  2716. //
  2717. // USL_CtlCButtonCustom() - The custom routine for all of the control
  2718. // buttons
  2719. //
  2720. ///////////////////////////////////////////////////////////////////////////
  2721. static boolean
  2722. USL_CtlCButtonCustom(UserCall call,word i,word n)
  2723. {
  2724. word j;
  2725. Point p;
  2726. UserItem *ip;
  2727. if (call != uic_Hit)
  2728. return(false);
  2729. ip = &TheItems[i][n];
  2730. if (ip->sel & ui_Disabled)
  2731. return(false);
  2732. USL_ClearBottom();
  2733. if (n == 0) // Keyboard
  2734. {
  2735. TheItems[i + 1] = ip = CtlCKbdPanels;
  2736. p = CtlCKbdPanels[2].r.lr;
  2737. VWB_DrawPic(p.x,p.y,CTL_DIRSPIC);
  2738. }
  2739. else
  2740. TheItems[i + 1] = ip = CtlCJoyPanels;
  2741. j = 0;
  2742. while (ip && (ip->type != uii_Bad))
  2743. {
  2744. USL_DrawItem(i + 1,j++);
  2745. ip++;
  2746. }
  2747. return(false);
  2748. }
  2749. ///////////////////////////////////////////////////////////////////////////
  2750. //
  2751. // USL_HitHotKey() - After a hotkey was hit, move the cursor to the first
  2752. // selected item in the group after the group containing the item
  2753. // holding the hotkey
  2754. //
  2755. ///////////////////////////////////////////////////////////////////////////
  2756. static void
  2757. USL_HitHotKey(int i,int n)
  2758. {
  2759. UserItem *ip;
  2760. if (ip = TheItems[++i])
  2761. {
  2762. if ((n = USL_FindDown(TheItems[i])) == -1)
  2763. n = 0;
  2764. ip += n;
  2765. CursorX = ip->r.lr.x - 8;
  2766. CursorY = ip->r.lr.y - 8;
  2767. CursorBad = true;
  2768. }
  2769. }
  2770. ///////////////////////////////////////////////////////////////////////////
  2771. //
  2772. // USL_CheckScan() - Checks to see if the scancode in LastScan corresponds
  2773. // to anything in the list of useritems. If so, selects the item.
  2774. //
  2775. ///////////////////////////////////////////////////////////////////////////
  2776. static boolean
  2777. USL_CheckScan(word *ci,word *cn)
  2778. {
  2779. word i,n;
  2780. UserItem *ip;
  2781. if (!LastScan)
  2782. return(false);
  2783. #if 1 // DEBUG - probably kill this code
  2784. // Use 1..? for the items across the top row
  2785. if (TheItems[1] && !IN_KeyDown(sc_RShift))
  2786. {
  2787. for (i = 0,ip = TheItems[1];(ip->type != uii_Bad) && (i < 9);i++,ip++)
  2788. ;
  2789. for (n = 0;n < i;n++)
  2790. {
  2791. if (LastScan == 2 + n) // Numbers from 1..9
  2792. {
  2793. if (!(TheItems[1][n].sel & ui_Disabled))
  2794. {
  2795. LastScan = sc_None;
  2796. USL_DoHit(1,n);
  2797. return(true);
  2798. }
  2799. }
  2800. }
  2801. }
  2802. // Use Alt-1..6 for the items in the leftmost column
  2803. if (IN_KeyDown(sc_RShift))
  2804. {
  2805. n = LastScan - 2;
  2806. if (n < 6) // Numbers from 1..6
  2807. {
  2808. USL_DoHit(0,n);
  2809. LastScan = sc_None;
  2810. return(true);
  2811. }
  2812. }
  2813. #endif
  2814. // Check normal hotkeys for the leftmost column
  2815. for (i = 0;CtlPanels[i].type != uii_Bad;i++)
  2816. {
  2817. if (CtlPanels[i].key == LastScan)
  2818. {
  2819. LastScan = sc_None;
  2820. USL_DoHit(0,i);
  2821. *ci = 0;
  2822. *cn = i;
  2823. USL_HitHotKey(0,i);
  2824. return(true);
  2825. }
  2826. }
  2827. // Check normal hotkeys for the top row
  2828. for (i = 0;i < 6;i++)
  2829. {
  2830. for (n = 0,ip = CtlPanels2[i];ip && ip->type != uii_Bad;n++,ip++)
  2831. {
  2832. if ((ip->key == LastScan) && !(ip->sel & ui_Disabled))
  2833. {
  2834. LastScan = sc_None;
  2835. USL_DoHit(0,i);
  2836. USL_DoHit(1,n);
  2837. *ci = 1;
  2838. *cn = n;
  2839. USL_HitHotKey(1,n);
  2840. return(true);
  2841. }
  2842. }
  2843. }
  2844. return(false);
  2845. }
  2846. ///////////////////////////////////////////////////////////////////////////
  2847. //
  2848. // USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the
  2849. // values of all the appropriate variables
  2850. //
  2851. ///////////////////////////////////////////////////////////////////////////
  2852. static void
  2853. USL_SetUpCtlPanel(void)
  2854. {
  2855. word i,j;
  2856. GameIsDirty = ingame;
  2857. // Set up restart game
  2858. USL_TurnOff(CtlPPanels);
  2859. CtlPPanels[0].sel = ingame? ui_Normal : ui_Selected;
  2860. CtlPPanels[1].sel = ingame? ui_Selected : ui_Disabled;
  2861. // Set up disk stuff - default to load/save game
  2862. USL_TurnOff(CtlDPanels);
  2863. CtlDPanels[0].sel = ui_Selected;
  2864. // Set up load/save buttons
  2865. USL_TurnOff(CtlDLSPanels);
  2866. for (i = 0;i < MaxSaveGames;i++)
  2867. {
  2868. if (!Games[i].present)
  2869. CtlDLSPanels[i * 2].sel = ui_Disabled;
  2870. if (!ingame)
  2871. CtlDLSPanels[(i * 2) + 1].sel = ui_Disabled;
  2872. }
  2873. // Set up Controls
  2874. USL_TurnOff(CtlCPanels);
  2875. CtlCPanels[1].sel = JoysPresent[0]? ui_Normal : ui_Disabled;
  2876. CtlCPanels[2].sel = JoysPresent[1]? ui_Normal : ui_Disabled;
  2877. if (Controls[0] == ctrl_Keyboard)
  2878. i = 0;
  2879. else
  2880. i = (Controls[0] == ctrl_Joystick1)? 1 : 2;
  2881. CtlCPanels[i].sel |= ui_Selected;
  2882. if (JoysPresent[1] && !JoysPresent[0])
  2883. CtlCPanels[2].key = sc_F4;
  2884. else
  2885. CtlCPanels[1].key = sc_F4;
  2886. // Set up Keyboard
  2887. for (i = 0;i < 10;i++)
  2888. CtlCKbdPanels[i].text = IN_GetScanName(*(KeyMaps[i]));
  2889. // Set up Sounds
  2890. USL_TurnOff(CtlSPanels);
  2891. CtlSPanels[sdm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;
  2892. #if 0 // DEBUG - hack because no space for digitized sounds on Keen Dreams
  2893. CtlSPanels[sdm_SoundBlaster].sel =
  2894. SoundBlasterPresent? ui_Normal : ui_Disabled;
  2895. CtlSPanels[sdm_SoundSource].sel =
  2896. SoundSourcePresent? ui_Normal : ui_Disabled;
  2897. #else
  2898. CtlSPanels[sdm_SoundBlaster].sel = ui_Disabled;
  2899. CtlSPanels[sdm_SoundSource].sel = ui_Disabled;
  2900. #endif
  2901. CtlSPanels[SoundMode].sel |= ui_Selected;
  2902. // Set up SoundSource
  2903. USL_TurnOff(CtlSSSPanels);
  2904. CtlSSSPanels[0].sel = ssIsTandy? ui_Selected : ui_Normal;
  2905. CtlSSSPanels[1].sel = (ssPort == 2)? ui_Selected : ui_Normal;
  2906. // Set up Music
  2907. USL_TurnOff(CtlMPanels);
  2908. CtlMPanels[smm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;
  2909. CtlMPanels[MusicMode].sel |= ui_Selected;
  2910. }
  2911. ///////////////////////////////////////////////////////////////////////////
  2912. //
  2913. // USL_TearDownCtlPanel() - Given the state of the control panel, sets the
  2914. // modes and values as appropriate
  2915. //
  2916. ///////////////////////////////////////////////////////////////////////////
  2917. static void
  2918. USL_TearDownCtlPanel(void)
  2919. {
  2920. int i;
  2921. i = USL_FindDown(CtlCPanels);
  2922. if (i != -1)
  2923. {
  2924. i = i? (i == 1? ctrl_Joystick1 : ctrl_Joystick2) : ctrl_Keyboard;
  2925. IN_SetControlType(0,i);
  2926. }
  2927. CtlCPanels[1].key = CtlCPanels[2].key = sc_None;
  2928. i = USL_FindDown(CtlSPanels);
  2929. if (i != -1)
  2930. SD_SetSoundMode(i);
  2931. ssIsTandy = CtlSSSPanels[0].sel & ui_Selected;
  2932. ssPort = (CtlSSSPanels[1].sel & ui_Selected)? 2 : 1;
  2933. i = USL_FindDown(CtlMPanels);
  2934. if (i != -1)
  2935. {
  2936. SD_SetMusicMode(i);
  2937. if (!QuitToDos)
  2938. {
  2939. US_CenterWindow(20,8);
  2940. US_CPrint("Loading");
  2941. #if 0
  2942. fontcolor = F_SECONDCOLOR;
  2943. US_CPrint("Sounds");
  2944. fontcolor = F_BLACK;
  2945. #endif
  2946. VW_UpdateScreen();
  2947. CA_LoadAllSounds();
  2948. }
  2949. }
  2950. }
  2951. ///////////////////////////////////////////////////////////////////////////
  2952. //
  2953. // US_ControlPanel() - This is the main routine for the control panel
  2954. //
  2955. ///////////////////////////////////////////////////////////////////////////
  2956. void
  2957. US_ControlPanel(void)
  2958. {
  2959. char gamename[MaxGameName + 10 + 1];
  2960. ScanCode c;
  2961. boolean done,
  2962. buttondown,inrect;
  2963. word hiti,hitn,
  2964. i,n,
  2965. lasti,lastn,
  2966. lastx,lasty;
  2967. longword lasttime;
  2968. Point p;
  2969. Rect userect;
  2970. UserItem *ip;
  2971. c = LastScan;
  2972. if (c == sc_Escape) // Map escape from game to Exit to DOS
  2973. c = sc_Q;
  2974. CA_UpLevel();
  2975. for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)
  2976. CA_MarkGrChunk(i);
  2977. CA_MarkGrChunk(CTL_LITTLEMASKPICM);
  2978. CA_MarkGrChunk(CTL_LSMASKPICM);
  2979. CA_CacheMarks("Options Screen");
  2980. USL_SetUpCtlPanel();
  2981. US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);
  2982. fontcolor = F_BLACK;
  2983. VW_InitDoubleBuffer();
  2984. VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);
  2985. US_DrawWindow(8,22,30,2);
  2986. US_SaveWindow(&HelpWindow);
  2987. US_DrawWindow(8,7,30,14);
  2988. US_SaveWindow(&BottomWindow);
  2989. US_DrawWindow(8,1,30,20);
  2990. for (ip = CtlPanels;ip->type != uii_Bad;ip++)
  2991. VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picup);
  2992. US_StartCursor();
  2993. CursorX = (8 * 8) + ((MaxX - (8 * 8)) / 2);
  2994. CursorBad = true;
  2995. CtlPanelButton = -1;
  2996. LastScan = c;
  2997. USL_CheckScan(&i,&n);
  2998. if (CtlPanelButton == -1)
  2999. USL_DoHit(0,0);
  3000. ResumeGame = false;
  3001. done = false;
  3002. FlushHelp = true;
  3003. lastx = lasty = -1;
  3004. while
  3005. (
  3006. (restartgame == gd_Continue)
  3007. && !(done || loadedgame || ResumeGame)
  3008. )
  3009. {
  3010. VW_UpdateScreen();
  3011. buttondown = US_UpdateCursor();
  3012. inrect = USL_IsInRect(CursorX,CursorY,&i,&n);
  3013. if (FlushHelp)
  3014. {
  3015. lasti = -2;
  3016. lasttime = TimeCount;
  3017. FlushHelp = false;
  3018. }
  3019. if (inrect)
  3020. {
  3021. if ((lasti != i) || (lastn != n))
  3022. {
  3023. // If over a Load button
  3024. if
  3025. (
  3026. (CtlPanelButton == 2)
  3027. && (i == 2)
  3028. && (TheItems[1][0].sel & ui_Selected)
  3029. && (Games[n / 2].present)
  3030. && !(n & 1)
  3031. )
  3032. {
  3033. strcpy(gamename,"Load `");
  3034. strcat(gamename,Games[n / 2].name);
  3035. strcat(gamename,"'");
  3036. USL_ShowHelp(gamename);
  3037. }
  3038. else
  3039. USL_ShowHelp(TheItems[i][n].help);
  3040. lasti = i;
  3041. lastn = n;
  3042. }
  3043. }
  3044. else if (lasti != (word)-1)
  3045. {
  3046. USL_ShowHelp("Select a Button");
  3047. lasti = -1;
  3048. }
  3049. hiti = i;
  3050. hitn = n;
  3051. if (inrect)
  3052. userect = TheItems[i][n].r;
  3053. else
  3054. {
  3055. userect.ul.x = CursorX;
  3056. userect.ul.y = CursorY;
  3057. userect.lr = userect.ul;
  3058. }
  3059. if (IN_KeyDown(sc_UpArrow))
  3060. {
  3061. USL_FindRect(userect,motion_None,motion_Up);
  3062. buttondown = false;
  3063. IN_ClearKey(sc_UpArrow);
  3064. }
  3065. else if (IN_KeyDown(sc_DownArrow))
  3066. {
  3067. USL_FindRect(userect,motion_None,motion_Down);
  3068. buttondown = false;
  3069. IN_ClearKey(sc_DownArrow);
  3070. }
  3071. else if (IN_KeyDown(sc_LeftArrow))
  3072. {
  3073. USL_FindRect(userect,motion_Left,motion_None);
  3074. buttondown = false;
  3075. IN_ClearKey(sc_LeftArrow);
  3076. }
  3077. else if (IN_KeyDown(sc_RightArrow))
  3078. {
  3079. USL_FindRect(userect,motion_Right,motion_None);
  3080. buttondown = false;
  3081. IN_ClearKey(sc_RightArrow);
  3082. }
  3083. else if
  3084. (
  3085. IN_KeyDown(c = sc_Return)
  3086. || IN_KeyDown(c = KbdDefs[0].button0)
  3087. || IN_KeyDown(c = KbdDefs[0].button1)
  3088. )
  3089. {
  3090. IN_ClearKey(c);
  3091. if (inrect)
  3092. {
  3093. ip = &TheItems[hiti][hitn];
  3094. if ((ip->type == uii_Button) && !(ip->sel & ui_Disabled))
  3095. {
  3096. lasttime = TimeCount;
  3097. ip->sel |= ui_Selected;
  3098. USL_DrawItem(hiti,hitn);
  3099. VW_UpdateScreen();
  3100. while (TimeCount - lasttime < TickBase / 4)
  3101. ;
  3102. lasttime = TimeCount;
  3103. ip->sel &= ~ui_Selected;
  3104. USL_DrawItem(hiti,hitn);
  3105. VW_UpdateScreen();
  3106. while (TimeCount - lasttime < TickBase / 4)
  3107. ;
  3108. }
  3109. USL_DoHit(hiti,hitn);
  3110. }
  3111. }
  3112. else if (USL_CheckScan(&i,&n))
  3113. ;
  3114. else if (buttondown && inrect && USL_TrackItem(hiti,hitn))
  3115. USL_DoHit(hiti,hitn);
  3116. if (LastScan == sc_Escape)
  3117. {
  3118. IN_ClearKey(sc_Escape);
  3119. done = true;
  3120. }
  3121. if (QuitToDos)
  3122. done = true;
  3123. if ((lastx != CursorX) || (lasty != CursorY))
  3124. {
  3125. lastx = CursorX;
  3126. lasty = CursorY;
  3127. lasttime = TimeCount;
  3128. }
  3129. if (TimeCount - lasttime > TickBase * 10)
  3130. {
  3131. if (((TimeCount - lasttime) / TickBase) & 2)
  3132. fontcolor = F_SECONDCOLOR;
  3133. USL_ShowHelp("Press F1 for Help");
  3134. fontcolor = F_BLACK;
  3135. }
  3136. }
  3137. US_ShutCursor();
  3138. USL_TearDownCtlPanel();
  3139. if (restartgame && USL_ResetGame)
  3140. USL_ResetGame();
  3141. if (QuitToDos)
  3142. {
  3143. if (tedlevel)
  3144. TEDDeath();
  3145. else
  3146. {
  3147. US_CenterWindow(20,3);
  3148. fontcolor = F_SECONDCOLOR;
  3149. US_PrintCentered("Now Exiting to DOS...");
  3150. fontcolor = F_BLACK;
  3151. VW_UpdateScreen();
  3152. Quit(nil);
  3153. }
  3154. }
  3155. CA_DownLevel();
  3156. }
  3157. // High score routines
  3158. ///////////////////////////////////////////////////////////////////////////
  3159. //
  3160. // US_DisplayHighScores() - Assumes that double buffering has been started.
  3161. // If passed a -1 will just display the high scores, but if passed
  3162. // a non-negative number will display that entry in red and let the
  3163. // user type in a name
  3164. //
  3165. ///////////////////////////////////////////////////////////////////////////
  3166. void
  3167. US_DisplayHighScores(int which)
  3168. {
  3169. char buffer[16],*str;
  3170. word i,
  3171. w,h,
  3172. x,y;
  3173. HighScore *s;
  3174. US_CenterWindow(30,MaxScores + (MaxScores / 2));
  3175. x = WindowX + (WindowW / 2);
  3176. US_Print(" Name");
  3177. PrintX = x + 20;
  3178. US_Print("Score");
  3179. PrintX = x + 60;
  3180. US_Print("Done\n\n");
  3181. PrintY -= 3;
  3182. for (i = WindowX;i < WindowX + WindowW;i += 8)
  3183. VWB_DrawTile8M(i,WindowY + 8,10);
  3184. VWB_DrawTile8M(WindowX - 8,WindowY + 8,9);
  3185. VWB_DrawTile8M(WindowX + WindowW,WindowY + 8,11);
  3186. for (i = 0,s = Scores;i < MaxScores;i++,s++)
  3187. {
  3188. fontcolor = (i == which)? F_SECONDCOLOR : F_BLACK;
  3189. if (i != which)
  3190. {
  3191. US_Print(" ");
  3192. if (strlen(s->name))
  3193. US_Print(s->name);
  3194. else
  3195. US_Print("-");
  3196. }
  3197. else
  3198. y = PrintY;
  3199. PrintX = x + (7 * 8);
  3200. ultoa(s->score,buffer,10);
  3201. for (str = buffer;*str;str++)
  3202. *str = *str + (129 - '0'); // Used fixed-width numbers (129...)
  3203. USL_MeasureString(buffer,&w,&h);
  3204. PrintX -= w;
  3205. US_Print(buffer);
  3206. PrintX = x + 60;
  3207. if (s->completed)
  3208. US_PrintUnsigned(s->completed);
  3209. else
  3210. US_Print("-");
  3211. US_Print("\n");
  3212. }
  3213. if (which != -1)
  3214. {
  3215. fontcolor = F_SECONDCOLOR;
  3216. PrintY = y;
  3217. PrintX = WindowX;
  3218. US_Print(" ");
  3219. strcpy(Scores[which].name,"");
  3220. US_LineInput(PrintX,PrintY,Scores[which].name,nil,true,MaxHighName,
  3221. (WindowW / 2) - 8);
  3222. }
  3223. fontcolor = F_BLACK;
  3224. VW_UpdateScreen();
  3225. }
  3226. ///////////////////////////////////////////////////////////////////////////
  3227. //
  3228. // US_CheckHighScore() - Checks gamestate to see if the just-ended game
  3229. // should be entered in the high score list. If so, lets the user
  3230. // enter their name
  3231. //
  3232. ///////////////////////////////////////////////////////////////////////////
  3233. void
  3234. US_CheckHighScore(long score,word other)
  3235. {
  3236. word i,j,
  3237. n;
  3238. HighScore myscore;
  3239. strcpy(myscore.name,"");
  3240. myscore.score = score;
  3241. myscore.completed = other;
  3242. for (i = 0,n = -1;i < MaxScores;i++)
  3243. {
  3244. if
  3245. (
  3246. (myscore.score > Scores[i].score)
  3247. || (
  3248. (myscore.score == Scores[i].score)
  3249. && (myscore.completed > Scores[i].completed)
  3250. )
  3251. )
  3252. {
  3253. for (j = MaxScores;--j > i;)
  3254. Scores[j] = Scores[j - 1];
  3255. Scores[i] = myscore;
  3256. n = i;
  3257. HighScoresDirty = true;
  3258. break;
  3259. }
  3260. }
  3261. VW_InitDoubleBuffer();
  3262. VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);
  3263. US_DisplayHighScores(n);
  3264. IN_UserInput(5 * TickBase,false);
  3265. }