Wing Commander
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
barracks.c
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup campaign
4 * @brief The barracks: campaign save and load.
5 *
6 * Address range 41a9d0-41c50f. The menu tables precede the modal renderer's
7 * literals, then the SAVEGAME.WLD literals; the palette flag that follows
8 * starts a separate unit after this file's string pool.
9 */
10#include "wc1.h"
11#include <process.h>
12#include <sys/stat.h>
13
15 { 1, 137, 88, 149, 94 },
16 { 1, 110, 88, 136, 94 },
17 { 1, 172, 88, 184, 94 },
18 { 1, 185, 88, 210, 94 },
19 { 1, 133, 98, 146, 107 },
20 { 1, 100, 98, 132, 107 },
21 { 1, 174, 98, 189, 107 },
22 { 1, 190, 98, 220, 107 },
23 { 1, 124, 114, 142, 128 },
24 { 1, 81, 114, 123, 128 },
25 { 1, 178, 114, 197, 128 },
26 { 1, 198, 114, 238, 128 },
27 { 1, 109, 141, 135, 164 },
28 { 1, 50, 141, 108, 164 },
29 { 1, 185, 141, 213, 164 },
30 { 1, 214, 141, 268, 164 },
31 { 1, 288, 39, 311, 85 },
32 { 1, 9, 33, 39, 95 },
33 { 1, 218, 37, 248, 78 },
34 { 1, 86, 44, 181, 78 },
35 { -1, 0, 0, 0, 0 }
36}; /* 0x00463008 */
37
39 {109, 86}, {170, 86}, {98, 95}, {173, 95},
40 {78, 110}, {176, 110}, {42, 136}, {183, 136}
41}; /* 0x004693c8 */
43 "Save this campaign ",
44 "Save this campaign "
45}; /* 0x004693e8 */
47 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0,
49 "Mission Hangar",
50 "Return to the Bar",
51 "Quit Wing Commander",
52 "View your medals"
53}; /* 0x004693f0 */
54ShortRect stModalTextBounds = { 24, 40, 296, 60 }; /* 0x00469440 */
55ModalTextPanel *pModalTextPanel = 0; /* 0x00469448 */
56short asCampaignPilotFiles[3] = {58, 61, 74}; /* 0x00469450 */
57short asCampaignBriefingFiles[3] = {10, 62, 73}; /* 0x00469458 */
58short asMissionDataFiles[3] = {15, 52, 72}; /* 0x00469460 */
59
60/* Linker commons defined here; LINK orders them by identifier hash. */
61int bSavedGameExists; /* 0x005a7d9c */
62
63/* Function start: 0x41A9D0 */
64short InitializeModalTextPanel(ModalTextPanel *panel, short fontIndex,
65 ShortRect bounds,
66 short clearColour,
67 short backgroundColour,
68 short borderColour)
69{
70 *(ShortRect *)&panel->left = bounds;
72 pCurTextContext = &panel->context;
74 if (fontIndex == -1)
75 fontIndex = 1;
76 InitializeTextContextFromFont(&panel->context, fontIndex,
77 (unsigned char)clearColour,
78 (signed char)backgroundColour);
80 *(ShortRect *)&panel->viewport.left =
81 *(ShortRect *)&panel->savedBackground.left =
82 *(ShortRect *)&panel->left;
83 if (AllocateViewport(&panel->savedBackground, clearColour, 0) == 0)
84 return 0;
87 panel->context.viewport = &panel->viewport;
90 DrawViewportBorder(&panel->viewport, panel->left, panel->top,
91 panel->right, panel->bottom, borderColour);
92 return 1;
93}
94
95/* Function start: 0x41AAE0 */
96void DrawModalTextPanel(ModalTextPanel *panel, short x, short y,
97 unsigned char alignment,
98 const char *format, ...)
99{
100 char text[84];
101
102 va_list arguments;
103
104 va_start(arguments, format);
105 vsprintf(text, format, arguments);
106 va_end(arguments);
107 SetTextCursor((unsigned short)(panel->left + x),
108 (unsigned short)(panel->top + y));
109 panel->context.alignment = alignment;
110 strcat(text, "%P");
112}
113
114/* Function start: 0x41AB60 */
121
122/* Function start: 0x41AB90 */
123short ShowModalTextPanel(short fontIndex, const char *format, ...)
124{
125 ShortRect bounds;
126 short halfWidth;
127 char text[52];
128
129 vsprintf(text, format, (char *)(&format + 1));
130 bounds = stModalTextBounds;
131 if (pModalTextPanel == 0) {
133 }
134 if (pModalTextPanel == 0)
135 return 0;
139 cBlackColour) == 0) {
141 pModalTextPanel = 0;
142 return 0;
143 }
144 halfWidth = MeasureTextPixelWidthClamped(text);
145 halfWidth = (short)((int)halfWidth * 8 / 16);
147 bounds.left = (short)(159 - halfWidth);
148 bounds.right = (short)(161 + halfWidth);
150 bounds, cViewportClearColour,
151 cBlueColour, cRedColour) == 0) {
153 pModalTextPanel = 0;
154 return 0;
155 }
156 DrawModalTextPanel(pModalTextPanel, 0, 6, 2, text);
157 DIBslam();
158 DIBslamReal();
159 return 1;
160}
161
162/* Function start: 0x41AD10 */
173
174/* Function start: 0x41AD50 */
175short AnySavedGames(void)
176{
177 SaveGameRecord gameRecord;
178 short slot;
179 short found;
180
181 found = 0;
182 for (slot = 0; slot < 8; slot++) {
183 if (LoadGame(slot, &gameRecord) != 0) {
184 found = 1;
185 if (gameRecord.campaign.campaignIndex > 0)
187 }
188 }
189 return found;
190}
191
192/* Function start: 0x41ADA0 */
194{
195 SaveGameDiskRecord diskRecord;
196 SaveGameRecord gameRecord;
197 SaveGameDiskObjective *diskObjective;
198 MissionObjective *gameObjective;
199 unsigned char *diskBytes;
200 unsigned char *gameBytes;
201 short *diskDeathMission;
202 int *gameDeathMission;
203 short file;
204 short slot;
205 int index;
206 SaveGameDiskCampaignState *diskCampaign = &diskRecord.campaign;
207
208 slot = 0;
209 gameRecord.occupied = 0;
211 file = CreateDataFile("SAVEGAME.WLD");
212 if (file >= 0) {
213 for (; slot < 8; slot++) {
214 sprintf(gameRecord.description, "game %d", (int)slot + 1);
215 diskBytes = (unsigned char *)diskRecord.description;
216 gameBytes = (unsigned char *)gameRecord.description;
217 memcpy(diskBytes, gameBytes, sizeof(diskRecord.description));
218 diskRecord.occupied = gameRecord.occupied;
219 memcpy(diskRecord.pilots, gameRecord.pilots,
220 sizeof(diskRecord.pilots));
221 diskCampaign->currentPilot =
222 (short)(int)gameRecord.campaign.currentPilot;
223 diskCampaign->playerShipType =
224 (short)gameRecord.campaign.playerShipType;
225
226 diskBytes = diskCampaign->medals;
227 gameBytes = gameRecord.campaign.medals;
228 for (index = 0; index < 5; index++) {
229 diskBytes[index] = gameBytes[index];
230 }
231
232 diskBytes = diskCampaign->badges;
233 gameBytes = gameRecord.campaign.badges;
234 for (index = 0; index < 12; index++) {
235 diskBytes[index] = gameBytes[index];
236 }
237
238 diskCampaign->currentMission =
239 gameRecord.campaign.currentMission;
240 diskCampaign->currentSeries =
241 gameRecord.campaign.currentSeries;
242 diskCampaign->seriesHistoryCount =
243 gameRecord.campaign.seriesHistoryCount;
244 diskBytes = (unsigned char *)
245 diskCampaign->seriesHistory;
246 gameBytes = (unsigned char *)
247 gameRecord.campaign.seriesHistory;
248 for (index = 0; index < 8; index++) {
249 diskBytes[index] = gameBytes[index];
250 }
251
252 gameDeathMission =
254 diskDeathMission =
255 diskCampaign->personalityDeathMission;
256 for (; diskDeathMission <
257 diskCampaign->personalityDeathMission + 8;
258 gameDeathMission++, diskDeathMission++) {
259 *diskDeathMission = (short)*gameDeathMission;
260 }
261
262 diskBytes = diskCampaign->aceFlags;
263 gameBytes = gameRecord.campaign.aceFlags;
264 for (index = 0; index < 4; index++) {
265 diskBytes[index] = gameBytes[index];
266 }
267 diskCampaign->currentDate =
268 gameRecord.campaign.currentDate;
269 diskCampaign->elapsedDate.day =
270 gameRecord.campaign.elapsedDate.day;
271 diskCampaign->elapsedDate.year =
272 gameRecord.campaign.elapsedDate.year;
273 diskCampaign->promotionScore =
274 gameRecord.campaign.promotionScore;
275 diskCampaign->missionScore =
276 gameRecord.campaign.missionScore;
277 diskCampaign->seriesScore =
278 gameRecord.campaign.seriesScore;
279 diskCampaign->campaignIndex =
280 gameRecord.campaign.campaignIndex;
281
282 gameObjective = gameRecord.objectives;
283 diskObjective = diskRecord.objectives;
284 for (; diskObjective < diskRecord.objectives + 16;
285 gameObjective++, diskObjective++) {
286 diskObjective->mapX = gameObjective->mapX;
287 diskObjective->mapY = gameObjective->mapY;
288 diskObjective->field_4 = gameObjective->field_4;
289 diskObjective->type = (short)gameObjective->type;
290 diskObjective->index = gameObjective->index;
291 diskObjective->flags = gameObjective->flags;
292 diskObjective->displayName =
293 (short)(int)gameObjective->displayName;
294 diskObjective->name = (short)(int)gameObjective->name;
295 gameBytes = (unsigned char *)&gameObjective->position;
296 diskBytes = (unsigned char *)&diskObjective->position;
297 ((FixedVector *)diskBytes)->x = ((FixedVector *)gameBytes)->x;
298 ((FixedVector *)diskBytes)->y = ((FixedVector *)gameBytes)->y;
299 ((FixedVector *)diskBytes)->z = ((FixedVector *)gameBytes)->z;
300 }
301
302 WriteDataFileAtOffset((unsigned short)file,
303 (int)slot * 0x33c, 0x33c,
304 &diskRecord);
305 }
306 CloseDataFile((unsigned short)file);
307 }
308}
309
310/* Function start: 0x41B020 */
312{
313 short file;
314 long length;
315
317 file = OpenDataFileOrDie("SAVEGAME.WLD");
318 if (file < 0) {
320 return;
321 }
322 length = filelength((int)file);
323 CloseDataFile((unsigned short)file);
324 if (length != 0x19e0)
326}
327
328/* Function start: 0x41B070 */
330{
331 short bunk;
332
333 for (bunk = 0; bunk < 8; bunk++) {
334 state->bunks[bunk].animationFrame =
335 RandomInRange(0, 13);
336 state->bunks[bunk].animationPeriod =
337 (short)(RandomInRange(0, 12) + 13);
338 state->bunks[bunk].animationTick = 0;
339 }
340 state->fallingY = -99;
341 state->fallingDelay = 20;
342 state->impactFrame = 49;
343 state->blinkDelay = 0;
344 state->fallingVelocity = 0;
345 state->animationTick = 0;
346 state->menuLabel = 0;
347 state->eyesOpen = 1;
348}
349
350/* Function start: 0x41B0E0 */
351void FreeBarracksMenuLabel(char **label)
352{
353 if (*label != 0 &&
354 *label != apszSaveCampaignMenuLabels[0] &&
355 *label != apszSaveCampaignMenuLabels[1]) {
356 ReleasePacketHandle(*label);
357 *label = 0;
358 }
359}
360
361/* Function start: 0x41B110 */
362void SetAwakenBarracksMenuLabel(char **label, short series, short mission,
363 char *description)
364{
366 sprintf(szTxtWorkspaceBuffer, "Awaken %Fs.", description);
367 *label = AllocateTaggedMemory(
368 strlen(szTxtWorkspaceBuffer) + 2, 0);
370 strlen(szTxtWorkspaceBuffer) + 2);
371}
372
373/* Function start: 0x41B180 */
375{
376 const char *saveCampaignLabel;
377 short bunk;
378
379 saveCampaignLabel = apszSaveCampaignMenuLabels[0];
380 for (bunk = 0; bunk < 8; bunk++) {
381 if (apszBarracksMenuLabels[bunk * 2] !=
382 saveCampaignLabel) {
384 &apszBarracksMenuLabels[bunk * 2]);
386 &apszBarracksMenuLabels[bunk * 2 + 1]);
387 saveCampaignLabel =
389 }
390 }
392}
393
394/* Function start: 0x41B1E0 */
395short SaveGame(short slot, SaveGameRecord *gameRecord)
396{
397 int index;
398 SaveGameDiskRecord diskRecord;
399 SaveGameDiskCampaignState *diskCampaign = &diskRecord.campaign;
400 SaveGameDiskObjective *diskObjective;
401 MissionObjective *gameObjective;
402 unsigned char *diskBytes;
403 short *diskDeathMission;
404 int *gameDeathMission;
405 short file;
406 int written;
407
409 diskBytes = (unsigned char *)diskRecord.description;
410 memcpy(diskBytes, gameRecord->description,
411 sizeof(diskRecord.description));
412 diskRecord.occupied = gameRecord->occupied;
413 memcpy(diskRecord.pilots, gameRecord->pilots,
414 sizeof(diskRecord.pilots));
415 diskCampaign->currentPilot =
416 (short)(int)gameRecord->campaign.currentPilot;
417 diskCampaign->playerShipType =
418 (short)gameRecord->campaign.playerShipType;
419 diskBytes = diskCampaign->medals;
420 for (index = 0; index < 5; index++) {
421 diskBytes[index] = gameRecord->campaign.medals[index];
422 }
423
424 diskBytes = diskCampaign->badges;
425 for (index = 0; index < 12; index++) {
426 diskBytes[index] = gameRecord->campaign.badges[index];
427 }
428 diskCampaign->currentMission =
429 gameRecord->campaign.currentMission;
430 diskCampaign->currentSeries =
431 gameRecord->campaign.currentSeries;
432 diskCampaign->seriesHistoryCount =
433 gameRecord->campaign.seriesHistoryCount;
434 diskBytes = (unsigned char *)diskCampaign->seriesHistory;
435 for (index = 0; index < 8; index++) {
436 diskBytes[index] =
437 (unsigned char)gameRecord->campaign.seriesHistory[index];
438 }
439
440 gameDeathMission = gameRecord->campaign.personalityDeathMission;
441 diskDeathMission = diskCampaign->personalityDeathMission;
442 for (; diskDeathMission <
443 diskCampaign->personalityDeathMission + 8;
444 gameDeathMission++, diskDeathMission++) {
445 *diskDeathMission = (short)*gameDeathMission;
446 }
447
448 diskBytes = diskCampaign->aceFlags;
449 for (index = 0; index < 4; index++) {
450 diskBytes[index] = gameRecord->campaign.aceFlags[index];
451 }
452 diskCampaign->currentDate =
453 gameRecord->campaign.currentDate;
454 diskCampaign->elapsedDate.day =
455 gameRecord->campaign.elapsedDate.day;
456 diskCampaign->elapsedDate.year =
457 gameRecord->campaign.elapsedDate.year;
458 diskCampaign->promotionScore =
459 gameRecord->campaign.promotionScore;
460 diskCampaign->missionScore =
461 gameRecord->campaign.missionScore;
462 diskCampaign->seriesScore =
463 gameRecord->campaign.seriesScore;
464 diskCampaign->campaignIndex =
465 gameRecord->campaign.campaignIndex;
466
467 gameObjective = gameRecord->objectives;
468 diskObjective = diskRecord.objectives;
469 for (; diskObjective < diskRecord.objectives + 16;
470 gameObjective++, diskObjective++) {
471 diskObjective->mapX = gameObjective->mapX;
472 diskObjective->mapY = gameObjective->mapY;
473 diskObjective->field_4 = gameObjective->field_4;
474 diskObjective->type = (short)gameObjective->type;
475 diskObjective->index = gameObjective->index;
476 diskObjective->flags = gameObjective->flags;
477 diskObjective->displayName =
478 (short)(int)gameObjective->displayName;
479 diskObjective->name = (short)(int)gameObjective->name;
480 diskObjective->position = gameObjective->position;
481 }
482
483 file = OpenDataFileOrDie("SAVEGAME.WLD");
484 written = WriteDataFileAtOffset((unsigned short)file,
485 (int)slot * 0x33c, 0x33c,
486 &diskRecord);
487 CloseDataFile((unsigned short)file);
488 return ((written != 0) & (file >= 0)) & 1;
489}
490
491/* Function start: 0x41B420 */
492short PromptForTextInput(short x, short y, const char *prompt,
493 char *destination, short maximumLength,
494 short inputMode)
495{
496 ModalTextPanel panel;
497 ShortRect bounds;
498 short result;
499
500 result = 0;
501 bounds.top = y;
502 bounds.left = x;
503 bounds.bottom = (short)(y + 20);
504 InitializeModalTextPanel(&panel, 0,
508 bounds.right = (short)(x +
509 ((int)MeasureTextPixelWidthClamped("M") * (int)maximumLength +
510 (int)MeasureTextPixelWidthClamped(prompt)) * 16 / 15);
511 RestoreModalTextPanel(&panel);
512 if (InitializeModalTextPanel(&panel, 0,
513 bounds,
515 cBlueColour, cRedColour) != 0) {
516 DrawModalTextPanel(&panel, 3, 6, 0, prompt);
517 DIBslam();
518 DIBslamReal();
519 if (ReadTextInput(destination, maximumLength, inputMode) != 0)
520 result = 1;
521 RestoreModalTextPanel(&panel);
522 }
523 return result;
524}
525
526/* Function start: 0x41B550 */
528{
529 InputEventState event;
530 short key;
531
533 key = 0;
534 if (ShowModalTextPanel(0, "Load a game first.") != 0) {
535 while (PollInputEvent(&event, 0xff) != 0) {
536 }
537 key = WaitForInputKey();
538 while (PollInputEvent(&event, 0xff) != 0) {
539 }
541 }
543 return (int)key;
544}
545
546/* Function start: 0x41B5C0 */
547void SaveGameWithNamePrompt(short slot, CampaignState *campaign,
548 PilotRecord *pilots,
549 MissionObjective *objectives)
550{
551 SaveGameRecord gameRecord;
552 char oldLabel[40];
553 char *separator;
554
555 if (bCampaignActive == 0) {
557 return;
558 }
559 DosStrcpy(oldLabel,
560 apszBarracksMenuLabels[slot * 2]);
561 if (strcmp(oldLabel,
563 oldLabel[0] = 0;
564 separator = DosStrchr(oldLabel, ' ');
565 if (separator != 0)
566 DosStrcpy(oldLabel, separator + 1);
567 separator = DosStrchr(oldLabel, '.');
568 if (separator != 0)
569 *separator = 0;
570 DosStrcpy(gameRecord.description, oldLabel);
571 if (PromptForTextInput(40, 24, "Game Name: ",
572 gameRecord.description, 16, 1) != 0) {
573 gameRecord.occupied = 1;
574 gameRecord.campaign = *campaign;
575 memcpy(gameRecord.pilots, pilots,
576 sizeof(gameRecord.pilots));
577 DosMemcpy(gameRecord.objectives, objectives, 0x1f0);
578 if (SaveGame(slot, &gameRecord) == 0)
579 ShowModalMessage("Error: Game %s not saved.",
580 gameRecord.description);
581 }
582}
583
584/* Function start: 0x41B710 */
585int LoadGame(short slot, SaveGameRecord *gameRecord)
586{
587 int index;
588 SaveGameDiskRecord diskRecord;
589 SaveGameDiskObjective *diskObjective;
590 MissionObjective *gameObjective;
591 unsigned char *diskBytes;
592 int *gameDeathMission;
593 short *diskDeathMission;
594 short file;
595 short fileOpen;
596 int read;
597 SaveGameDiskCampaignState *diskCampaign = &diskRecord.campaign;
598
600 file = OpenDataFileOrDie("SAVEGAME.WLD");
601 fileOpen = (file >= 0) & 1;
602 read = ReadDataFileAtOffset((unsigned short)file,
603 (int)slot * 0x33c, 0x33c,
604 &diskRecord);
605 diskBytes = (unsigned char *)diskRecord.description;
606 memcpy(gameRecord->description, diskBytes,
607 sizeof(gameRecord->description));
608 gameRecord->occupied = ((SaveGameDiskRecord *)diskBytes)->occupied;
609 memcpy(gameRecord->pilots, diskRecord.pilots,
610 sizeof(gameRecord->pilots));
611 gameRecord->campaign.currentPilot =
612 (PilotRecord *)(int)diskCampaign->currentPilot;
613 gameRecord->campaign.playerShipType =
614 (enum ObjectType)diskCampaign->playerShipType;
615 diskBytes = diskCampaign->medals;
616 for (index = 0; index < 5; index++) {
617 gameRecord->campaign.medals[index] = diskBytes[index];
618 }
619
620 diskBytes = diskCampaign->badges;
621 for (index = 0; index < 12; index++) {
622 gameRecord->campaign.badges[index] = diskBytes[index];
623 }
624 gameRecord->campaign.currentMission =
625 diskCampaign->currentMission;
626 gameRecord->campaign.currentSeries =
627 diskCampaign->currentSeries;
628 gameRecord->campaign.seriesHistoryCount =
629 diskCampaign->seriesHistoryCount;
630 diskBytes = (unsigned char *)diskCampaign->seriesHistory;
631 for (index = 0; index < 8; index++) {
632 gameRecord->campaign.seriesHistory[index] = diskBytes[index];
633 }
634
635 diskDeathMission = diskCampaign->personalityDeathMission;
636 gameDeathMission = gameRecord->campaign.personalityDeathMission;
637 for (; diskDeathMission <
638 diskCampaign->personalityDeathMission + 8;
639 diskDeathMission++, gameDeathMission++) {
640 *gameDeathMission = (int)*diskDeathMission;
641 }
642
643 diskBytes = diskCampaign->aceFlags;
644 for (index = 0; index < 4; index++) {
645 gameRecord->campaign.aceFlags[index] = diskBytes[index];
646 }
647 gameRecord->campaign.currentDate =
648 diskCampaign->currentDate;
649 gameRecord->campaign.elapsedDate.day =
650 diskCampaign->elapsedDate.day;
651 gameRecord->campaign.elapsedDate.year =
652 diskCampaign->elapsedDate.year;
653 gameRecord->campaign.promotionScore =
654 diskCampaign->promotionScore;
655 gameRecord->campaign.missionScore =
656 diskCampaign->missionScore;
657 gameRecord->campaign.seriesScore =
658 diskCampaign->seriesScore;
659 gameRecord->campaign.campaignIndex =
660 diskCampaign->campaignIndex;
661
662 diskObjective = diskRecord.objectives;
663 gameObjective = gameRecord->objectives;
664 for (; diskObjective < diskRecord.objectives + 16;
665 diskObjective++, gameObjective++) {
666 gameObjective->mapX = diskObjective->mapX;
667 gameObjective->mapY = diskObjective->mapY;
668 gameObjective->field_4 = diskObjective->field_4;
669 gameObjective->type = (int)diskObjective->type;
670 gameObjective->index = diskObjective->index;
671 gameObjective->flags = diskObjective->flags;
672 gameObjective->displayName =
673 (const char *)(int)diskObjective->displayName;
674 gameObjective->name = (char *)(int)diskObjective->name;
675 gameObjective->position = diskObjective->position;
676 }
677
678 fileOpen &= read != 0;
679 CloseDataFile((unsigned short)file);
680 if (fileOpen != 0 && gameRecord->occupied != 0)
681 return 1;
682 return 0;
683}
684
685/* Function start: 0x41B980 */
686void LoadGameFromSlot(short slot, CampaignState *campaign,
687 PilotRecord *pilots,
688 MissionObjective *objectives)
689{
690 short loaded;
691 SaveGameRecord gameRecord;
692
694 if (ShowModalTextPanel(0, "Loading Game...") != 0) {
695 loaded = LoadGame(slot, &gameRecord);
696 if (loaded != 0) {
697 memcpy(pilots, gameRecord.pilots,
698 sizeof(gameRecord.pilots));
699 *campaign = gameRecord.campaign;
709 DosMemcpy(objectives, gameRecord.objectives, 0x1f0);
711 bCampaignActive = 1;
712 }
714 if (loaded == 0) {
715 ShowModalMessage("Error: Game %d not loaded.", (int)slot);
716 } else if (nOriginDevUnlock != 0) {
717 strcpy(campaign->currentPilot->callsign, "CHEATER");
718 }
719 }
721}
722
723/* Function start: 0x41BAD0 */
724void SetBunkMenuLabel(short occupied, short side, char **label,
725 short series, short mission, char *description)
726{
727 if (occupied == 0) {
728 *label = (char *)apszSaveCampaignMenuLabels[0];
729 return;
730 }
731 if (side == 0) {
732 SetAwakenBarracksMenuLabel(label, series, mission, description);
733 return;
734 }
735 *label = (char *)apszSaveCampaignMenuLabels[1];
736}
737
738/* Function start: 0x41BB20 */
740{
741 SaveGameRecord gameRecord;
742 short bunk;
743
745 for (bunk = 0; bunk < 8; bunk++) {
746 state->bunks[bunk].occupied =
747 (short)LoadGame(bunk, &gameRecord);
749 state->bunks[bunk].occupied, 0,
750 &apszBarracksMenuLabels[bunk * 2],
751 gameRecord.campaign.currentSeries,
752 gameRecord.campaign.currentMission,
753 gameRecord.description);
755 state->bunks[bunk].occupied, 1,
756 &apszBarracksMenuLabels[bunk * 2 + 1],
757 gameRecord.campaign.currentSeries,
758 gameRecord.campaign.currentMission,
759 gameRecord.description);
760 }
761}
762
763/* Function start: 0x41BBD0 */
764void DrawBarracksBunks(Viewport *viewport, struct Shape *shape,
766{
767 short frame;
768 short bunk;
769
770 DrawSpriteDefault(viewport, 0, 0, shape, 0);
771 for (bunk = 0; bunk < 8; bunk++) {
772 frame = 10;
773 if (state->bunks[bunk].occupied != 0) {
775 viewport, aBarracksBunkOrigins[bunk].x,
776 aBarracksBunkOrigins[bunk].y,
777 shape, (short)(bunk + 1));
778 frame = 9;
779 }
780 DrawSpriteDefault(viewport,
781 (short)((bunk % 2) * 31 + 143),
782 (short)((short)(bunk / 2) * 5 + 167),
783 shape, frame);
784 }
786}
787
788/* Function start: 0x41BC90 */
790 struct Shape *shape)
791{
792 DrawSpriteDefault(viewport, 147, 167, shape, 25);
793 CheckCursor();
794 DrawSpriteDefault(viewport, 304, 144, shape, 36);
795 CheckCursor();
796}
797
798/* Function start: 0x41BCE0 */
799void AnimateBarracks(Viewport *viewport, struct Shape *shape,
801{
802 BarracksBunkState *bunkState;
803 int frameTick;
804 int bunkTick;
805 short bunk;
806 short frame;
807
808 frameTick = (int)nTickCount60Hz / 3;
809 for (bunk = 0; bunk < 8; bunk++) {
810 frame = 11;
811 bunkState = &state->bunks[bunk];
812 if (bunkState->occupied != 0) {
813 bunkTick = frameTick / 4;
814 if (bunkState->animationTick != bunkTick) {
815 bunkState->animationTick = bunkTick;
816 bunkState->animationFrame++;
817 if (bunkState->animationTick %
818 (int)bunkState->animationPeriod == 0)
819 bunkState->animationFrame = 0;
820 }
821 if (bunkState->animationFrame < 13)
822 frame = (short)(24 - bunkState->animationFrame);
823 else
824 frame = 24;
825 }
826 DrawSpriteDefault(viewport,
827 (short)((bunk % 2) * 14 + 148),
828 (short)((bunk / 2) * 5 + 166),
829 shape, frame);
830 }
831
832 if ((int)state->animationTick != frameTick) {
833 state->animationTick = (short)frameTick;
834 state->fallingDelay--;
835 if (state->fallingDelay == 0) {
836 state->fallingY = -5;
837 state->fallingVelocity = 3;
838 }
839 if (state->fallingY != -99) {
840 state->fallingY += state->fallingVelocity;
841 state->fallingVelocity++;
842 if (state->fallingY > 115) {
843 state->fallingY = -99;
844 state->impactFrame = 37;
845 state->fallingDelay = 20;
846 PlaySfxWaveFileByNumber(35, -1, 0);
847 }
848 }
849 }
850 if (state->fallingY != -99) {
851 DrawSpriteDefault(viewport, 298, (short)state->fallingY,
852 shape,
853 (short)(state->fallingY / 40 + 27));
854 DrawSpriteDefault(viewport, 305, 46, shape, 35);
855 }
856 frame = state->impactFrame;
857 if (frame != 49) {
858 state->impactFrame++;
859 DrawSpriteDefault(viewport, 298, 139, shape, frame);
860 }
861
862 if (state->blinkDelay != 0) {
863 state->eyesOpen = (short)(state->eyesOpen == 0);
864 state->blinkDelay--;
865 if (state->blinkDelay == 0 &&
866 (unsigned short)RandomInRange(0, 100) < 90)
867 state->eyesOpen = 1;
868 } else if (RandomInRange(0, 70) == 0) {
869 state->blinkDelay = (short)(RandomInRange(0, 15) + 2);
870 }
871 if (state->eyesOpen != 0)
872 DrawSpriteDefault(viewport, 45, 0, shape, 49);
873 else
874 DrawSpriteDefault(viewport, 45, 0, shape, 26);
875 CheckCursor();
878 DrawSpriteDefault(viewport, 319, 199, shape, 50);
879 }
880}
881
882/* Function start: 0x41BF10 */
884{
885 short confirmed;
886
888 confirmed = 0;
889 if (ShowModalTextPanel(0, "Quit Wing Commander? (Y/N)") != 0) {
890 confirmed = (short)((short)toupper(
891 WaitForStreamInputKey()) == 'Y');
893 }
895 return (int)confirmed;
896}
897
898/* Function start: 0x41BF60 */
900{
901 SaveGameRecord gameRecord;
902 short confirmed;
903
904 confirmed = 0;
905 if (LoadGame(slot, &gameRecord) == 0)
906 ShowModalMessage("Error: data may be bad.");
908 if (ShowModalTextPanel(0, "Awaken %s? (Y/N)",
909 gameRecord.description) != 0) {
910 confirmed = (short)((short)toupper(
911 WaitForStreamInputKey()) == 'Y');
913 }
915 return (int)confirmed;
916}
917
918/* Function start: 0x41BFE0 */
920{
921 SaveGameRecord gameRecord;
922 short confirmed;
923
924 confirmed = 0;
925 if (bCampaignActive == 0) {
927 return 0;
928 }
929 if (LoadGame(slot, &gameRecord) == 0)
930 strcpy(gameRecord.description, "FAULTY DATA");
932 if (ShowModalTextPanel(0, "Replace %s? (Y/N)",
933 gameRecord.description) != 0) {
934 confirmed = (short)((short)toupper(
935 WaitForStreamInputKey()) == 'Y');
937 }
939 return (int)confirmed;
940}
941
942/* Function start: 0x41C090 */
944 struct Shape *shape,
946 short region)
947{
949 if (state->bunks[region / 2].occupied == 0) {
952 } else if (region % 2 == 0) {
953 if (ConfirmAwakenAfterBadData(region / 2) != 0)
956 } else if (ConfirmReplaceFaultyData(region / 2) != 0) {
959 }
960 GetBunkInfo(state);
961 DrawBarracksBunks(viewport, shape, state);
963}
964
965/* Function start: 0x41C140 */
966void UpdateBarracksScreen(Viewport *viewport, struct Shape *shape,
968{
969 DrawBarracksStaticDetails(viewport, shape);
970 AnimateBarracks(viewport, shape, state);
972}
973
974/* Function start: 0x41C170 */
975short BarracksScreen(void)
976{
977 InputEventState event;
978 BarracksAnimationState animation;
979 int lastMedalsTick;
980 short clicked;
981 short result;
982 struct Shape *background;
983 short eventType;
984 short region;
985
986 result = 0;
987 lastMedalsTick = 0;
989 spacetrack(35, 2, 1);
991 background = FetchDiskPacketRetrying(5, 12, 0);
995 szDefaultTxtBuf, 2);
997 InitializeBarracksAnimation(&animation);
998 GetBunkInfo(&animation);
999 DrawBarracksBunks(&stSceneBuffer, background, &animation);
1001 WarpMouseTo(160, 100);
1005 bInputModeState = 1;
1010
1011 while (result == 0) {
1012 if ((short)IsFrameTickElapsed() != 0) {
1014 background, &animation);
1016 }
1017 eventType = PollInputEvent(&event, 0xff);
1018 switch (eventType) {
1019 case 3:
1020 case 5:
1021 clicked = 0;
1023 switch ((short)event.value) {
1024 case 0x1c:
1025 case 0x39:
1026 clicked = 1;
1027 break;
1028 case 0x24:
1030 break;
1031 default:
1033 break;
1034 }
1035 if (clicked == 0)
1036 break;
1037 /* Fall through to the shared mouse/keyboard activation. */
1038 case 2:
1039 case 10:
1040 region = FindMenuRegionAtPoint(
1041 event.x, event.y, aBarracksMenuRegions);
1042 if (region >= 0 && region < 16) {
1044 &stSceneBuffer, background, &animation, region);
1045 } else {
1046 switch (region) {
1047 case 16:
1048 if (bCampaignActive == 0)
1050 else
1051 result = 7;
1052 break;
1053 case 17:
1054 if (bCampaignActive == 0)
1056 else
1057 result = 8;
1058 break;
1059 case 18:
1060 if (ConfirmQuitWingCommander() != 0) {
1063 "You step out of the airlock and into...");
1064 }
1065 break;
1066 case 19:
1067 if (bCampaignActive == 0) {
1069 } else {
1074 if ((int)(nTickCount60Hz - lastMedalsTick) >
1078 cBlackColour);
1079 stSceneBuffer.bottom = 127;
1080 stScreenView.top = 24;
1081 stScreenView.bottom = 151;
1082 ViewMedals();
1083 lastMedalsTick = (int)nTickCount60Hz;
1085 cBlackColour);
1086 stScreenView.top = 0;
1087 stScreenView.bottom = 199;
1088 stSceneBuffer.bottom = 199;
1089 DrawBarracksBunks(&stSceneBuffer, background,
1090 &animation);
1094 background, &animation);
1095 }
1096 }
1097 break;
1098 }
1099 }
1100 break;
1101 case 13:
1103 break;
1104 }
1106 DIBslam();
1107 DIBslamReal();
1108 }
1109
1116 ReleasePacketHandle(background);
1117 ReleaseTextFont(0);
1121 return result;
1122}
const char * apszSaveCampaignMenuLabels[2]
Definition barracks.c:42
ModalTextPanel * pModalTextPanel
Definition barracks.c:55
const TitleMenuRegion aBarracksMenuRegions[21]
Definition barracks.c:14
ShortPoint aBarracksBunkOrigins[8]
Definition barracks.c:38
char * apszBarracksMenuLabels[20]
Definition barracks.c:46
ShortRect stModalTextBounds
Definition barracks.c:54
short asCampaignBriefingFiles[3]
Definition barracks.c:57
short asMissionDataFiles[3]
Definition barracks.c:58
unsigned char cRedColour
Definition init.c:16
short nCampaignDataSet
Definition gameflow.c:30
TextContext stDefaultTxtContext
Definition targ.c:14
unsigned char cBlackColour
Definition init.c:12
int nInputTickScale
Definition data.c:245
char szTxtWorkspaceBuffer[256]
Definition screens.c:164
Viewport stRoomScreenViewport
Definition gr.c:1526
TextContext * pCurTextContext
Definition data.c:244
unsigned char cBlueColour
Definition init.c:14
unsigned char cViewportClearColour
Definition init.c:13
ConstellationObjectDefinition * pConstellationDefinitionsPtr
Definition gr.c:1532
short nMenuPointerSpeed
Definition input.c:11
unsigned char bInputModeState
Definition eventmgr.c:21
MouseCursorState stMouseCursorState
Definition strdos.c:19
Viewport stSceneBuffer
Definition select.c:17
char szDefaultTxtBuf[0xc8]
Definition timer.c:18
Viewport stScreenView
Definition launch.c:50
short nQueuedCampaignIndex
Definition gameflow.c:28
int bSavedGameExists
Definition barracks.c:61
int nTickCount60Hz
Definition mathfp.c:23
CampaignState stCampaignState
Definition dib.c:107
int bCampaignActive
Definition gameflow.c:22
MissionObjective aMissionObjectivesArray[MISSION_OBJECTIVE_COUNT]
Definition screen.c:24
Viewport stModalSrcViewport
Definition select.c:14
short nMenuInputRepeatDelay
Definition objdata.c:597
short nSavedRoomCtrlX
Definition gr.c:1527
unsigned char * pMissionCampaignInfo
Definition gr.c:1529
short asCampaignPilotFiles[3]
Definition barracks.c:56
PilotRecord aPilotEntriesList[9]
Definition gr.c:1531
RoomMenu stCurrentRoomMenu
Definition killbrd.c:184
int nOriginDevUnlock
Definition main.c:34
const char * menuLabel
Definition wcdata.h:980
BarracksBunkState bunks[8]
Definition wcdata.h:972
short animationFrame
Definition wcdata.h:966
short animationPeriod
Definition wcdata.h:967
short day
Definition wcdata.h:607
short year
Definition wcdata.h:608
signed char seriesHistory[8]
Definition wcdata.h:717
PilotRecord * currentPilot
Definition wcdata.h:710
CampaignDate currentDate
Definition wcdata.h:720
signed char seriesHistoryCount
Definition wcdata.h:716
short missionScore
Definition wcdata.h:723
CampaignDate elapsedDate
Definition wcdata.h:721
short seriesScore
Definition wcdata.h:724
unsigned char badges[12]
Definition wcdata.h:713
short campaignIndex
Definition wcdata.h:725
short promotionScore
Definition wcdata.h:722
enum ObjectType playerShipType
Definition wcdata.h:711
signed char currentSeries
Definition wcdata.h:715
unsigned char aceFlags[4]
Definition wcdata.h:719
int personalityDeathMission[8]
Definition wcdata.h:718
unsigned char medals[5]
Definition wcdata.h:712
signed char currentMission
Definition wcdata.h:714
unsigned int value
Definition wc1base.h:140
const char * displayName
Definition wcdata.h:929
unsigned char flags
Definition wcdata.h:928
unsigned char field_4
Definition wcdata.h:925
signed char index
Definition wcdata.h:927
FixedVector position
Definition wcdata.h:931
TextContext context
Definition wc1base.h:260
TextContext * previousContext
Definition wc1base.h:263
Viewport viewport
Definition wc1base.h:262
Viewport savedBackground
Definition wc1base.h:261
Viewport * viewport
Definition wc1base.h:110
char callsign[14]
Definition wcdata.h:598
const char * currentLabel
Definition wc1base.h:290
unsigned char medals[5]
Definition wcdata.h:734
signed char currentMission
Definition wcdata.h:736
signed char currentSeries
Definition wcdata.h:737
signed char seriesHistoryCount
Definition wcdata.h:738
unsigned char badges[12]
Definition wcdata.h:735
CampaignDate currentDate
Definition wcdata.h:742
signed char seriesHistory[8]
Definition wcdata.h:739
CampaignDate elapsedDate
Definition wcdata.h:743
short personalityDeathMission[8]
Definition wcdata.h:740
unsigned char aceFlags[4]
Definition wcdata.h:741
unsigned char flags
Definition wcdata.h:942
FixedVector position
Definition wcdata.h:945
unsigned char field_4
Definition wcdata.h:939
signed char index
Definition wcdata.h:941
PilotRecord pilots[9]
Definition wcdata.h:959
unsigned char occupied
Definition wcdata.h:958
SaveGameDiskCampaignState campaign
Definition wcdata.h:960
char description[17]
Definition wcdata.h:957
SaveGameDiskObjective objectives[16]
Definition wcdata.h:961
PilotRecord pilots[9]
Definition wcdata.h:951
MissionObjective objectives[16]
Definition wcdata.h:953
char description[17]
Definition wcdata.h:949
unsigned char occupied
Definition wcdata.h:950
CampaignState campaign
Definition wcdata.h:952
short top
Definition wcdata.h:441
short left
Definition wcdata.h:440
short right
Definition wcdata.h:442
short bottom
Definition wcdata.h:443
char * text
Definition wc1base.h:242
Viewport * viewport
Definition wc1base.h:236
unsigned char alignment
Definition wc1base.h:244
short bottom
Definition wc1base.h:79
short left
Definition wc1base.h:76
short top
Definition wc1base.h:77
Umbrella header for the game core.
void * AllocateTaggedMemory(int size, unsigned short flags)
Definition ending.c:31
void HandleBarracksBunkSelection(Viewport *viewport, struct Shape *shape, BarracksAnimationState *state, short region)
Definition barracks.c:943
void FormatTextBufferFromStart(const char *format,...)
Definition cockpt.c:211
void LeaveAllocationScope(void)
Definition eventmgr.c:556
void DIBslam(void)
Definition dib.c:513
void MoveMenuPointerFromKeyboard(InputEventState *event)
Definition disk.c:551
unsigned int InitializeTextContextFromFont(TextContext *context, short fontIndex, unsigned char colour, signed char background)
Definition disk.c:192
int ConfirmQuitWingCommander(void)
Definition barracks.c:883
short __stdcall PollInputEvent(InputEventState *event, short filter)
Definition eventmgr.c:336
char *__stdcall DosStrchr(const char *s, short c)
Definition strdos.c:43
void RestoreModalTextPanel(ModalTextPanel *panel)
Definition barracks.c:115
unsigned short __stdcall AllocateViewport(Viewport *viewport, short clearColour, short flags)
Definition view.c:758
int ConfirmAwakenAfterBadData(short slot)
Definition barracks.c:899
void UpdateRoomMenuCursor(void)
Definition main.c:2181
void * FetchDiskPacketRetrying(short logicalFile, short section, short flags)
Definition disk.c:126
void __stdcall SetTextCursor(unsigned short a, unsigned short b)
Definition mathfp.c:145
void CalibrateJoystickInteractive()
Definition joystick.c:13
void InitializeRoomViewports(void)
Definition killbrd.c:287
void DrawBarracksStaticDetails(Viewport *viewport, struct Shape *shape)
Definition barracks.c:789
void __stdcall PromptInsertNumberedDisk(short logicalFile)
Definition disk.c:322
void ClearInputKeyStatePreservingModifiers(void)
Definition eventmgr.c:787
unsigned int spacetrack(int track, int mode, short enabled)
Definition music.c:411
int FindMenuRegionAtPoint(short x, short y, const TitleMenuRegion *regions)
Definition killbrd.c:274
short ReadTextInput(char *destination, short maximumLength, short mode)
Definition trainsim.c:323
short SaveGame(short slot, SaveGameRecord *gameRecord)
Definition barracks.c:395
void DrawModalTextPanel(ModalTextPanel *panel, short x, short y, unsigned char alignment, const char *format,...)
Definition barracks.c:96
short __stdcall MeasureTextPixelWidthClamped(const char *text)
Definition geom.c:18
void DrawSpriteDefault(Viewport *viewport, short x, short y, struct Shape *shape, short frame)
Definition gr.c:660
int __stdcall ReadDataFileAtOffset(unsigned short fd, int offset, unsigned int length, void *data)
Definition mono.c:61
int IsFrameTickElapsed(void)
Definition eventmgr.c:629
void StopMusicUnlessSuppressed(void)
Definition music.c:419
void FlushInputEvents(void)
Definition eventmgr.c:381
unsigned int ViewMedals(void)
Definition screens.c:220
void AnimateBarracks(Viewport *viewport, struct Shape *shape, BarracksAnimationState *state)
Definition barracks.c:799
void * LoadPacketIntoBuffer(short logicalFile, short section, void *destination)
Definition disk.c:80
void ShowModalMessage(const char *format,...)
Definition main.c:1258
void DIBslamReal(void)
Definition dib.c:519
short WaitForInputKey(void)
Definition disk.c:467
void __stdcall DosMemcpy(void *dst, const void *src, unsigned short n)
unsigned int PreloadMusicTrackHook(short track)
Definition logic.c:2044
void InitializeRoomMenu(const TitleMenuRegion *regions, char **labels, Viewport *viewport, char *text, unsigned char alignment)
Definition killbrd.c:254
void __stdcall CloseDataFile(unsigned short fd)
Definition mono.c:23
short PromptForTextInput(short x, short y, const char *prompt, char *destination, short maximumLength, short inputMode)
Definition barracks.c:492
void InitializeBarracksAnimation(BarracksAnimationState *state)
Definition barracks.c:329
void EnterAllocationScope(void)
Definition eventmgr.c:550
int ConfirmReplaceFaultyData(short slot)
Definition barracks.c:919
char *__stdcall DosStrcpy(char *dst, const char *src)
Definition strdos.c:49
short BarracksScreen(void)
Definition barracks.c:975
void SetAwakenBarracksMenuLabel(char **label, short series, short mission, char *description)
Definition barracks.c:362
void CheckCursor(void)
Definition eventmgr.c:405
short __stdcall OpenDataFileOrDie(const char *path)
Definition winsys.c:297
void __stdcall SetFrameTimerPeriodDirect(short p)
Definition eventmgr.c:617
void __stdcall WarpMouseTo(short x, short y)
Definition winmain.c:501
unsigned int ReleaseMusicTrackHook(short track)
Definition logic.c:2051
short __stdcall CreateDataFile(const char *path)
Definition mono.c:47
short WaitForStreamInputKey(void)
Definition disk.c:649
void SaveGameWithNamePrompt(short slot, CampaignState *campaign, PilotRecord *pilots, MissionObjective *objectives)
Definition barracks.c:547
unsigned int LoadMissionData(short series, short mission)
Definition cmpgn.c:586
void RefreshRoomMenuLabel(void)
Definition killbrd.c:228
void FreeBarracksMenuLabels(void)
Definition barracks.c:374
unsigned short EraseTextContextBackground(TextContext *context)
Definition trainsim.c:45
void FreeBarracksMenuLabel(char **label)
Definition barracks.c:351
void EnsureSaveGameFile(void)
Definition barracks.c:311
void DrawBarracksBunks(Viewport *viewport, struct Shape *shape, BarracksAnimationState *state)
Definition barracks.c:764
void DrawViewportBorder(Viewport *viewport, short left, short top, short right, short bottom, short colour)
Definition gr.c:1052
void ClearViewport(Viewport *viewport, short colour)
Definition gr.c:963
void exit_squadron(const char *msg)
Definition main.c:122
void PlaySfxWaveFileByNumber()
short InitializeModalTextPanel(ModalTextPanel *panel, short fontIndex, ShortRect bounds, short clearColour, short backgroundColour, short borderColour)
Definition barracks.c:64
void CorrectPointers(void)
Definition killbrd.c:189
void __stdcall free_viewport(Viewport *viewport)
Definition gameflow.c:420
void ReleasePacketHandle(void *handle)
Definition ending.c:50
void UpdateBarracksScreen(Viewport *viewport, struct Shape *shape, BarracksAnimationState *state)
Definition barracks.c:966
int LoadGame(short slot, SaveGameRecord *gameRecord)
Definition barracks.c:585
short __stdcall WriteDataFileAtOffset(unsigned short fd, int offset, unsigned int length, const void *data)
Definition mono.c:29
void GetBunkInfo(BarracksAnimationState *state)
Definition barracks.c:739
void __stdcall EventManagerHook(void(*callback)(void))
Definition strdos.c:120
unsigned int ShowMemoryStatusDebug(void)
Definition main.c:135
void ReleaseModalTextPanel(void)
Definition barracks.c:163
void SetBunkMenuLabel(short occupied, short side, char **label, short series, short mission, char *description)
Definition barracks.c:724
unsigned int ReleaseTextFont(short fontIndex)
Definition disk.c:222
short __stdcall RandomInRange(short lo, short hi)
Definition mathfp.c:49
short AnySavedGames(void)
Definition barracks.c:175
int WarnLoadGameFirst(void)
Definition barracks.c:527
void LoadGameFromSlot(short slot, CampaignState *campaign, PilotRecord *pilots, MissionObjective *objectives)
Definition barracks.c:686
char *__stdcall ResetStringBuilder(TextContext *context)
Definition mono.c:411
void CopyViewportContents(Viewport *source, Viewport *destination)
Definition gr.c:945
short ShowModalTextPanel(short fontIndex, const char *format,...)
Definition barracks.c:123
void ShutdownEventManager(void)
Definition strdos.c:101
void CreateEmptySaveGameFile(void)
Definition barracks.c:193
ObjectType
Definition wcdata.h:54