Wing Commander II
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
intro.c
Go to the documentation of this file.
1/*
2 * Title orchestra sequence and victory fireworks.
3 *
4 * Retail object 0x407E40-0x40911F (link order; see docs/ORDER.md).
5 */
6#include "game.h"
7
8typedef struct TitleActorMotion {
9 short x;
10 short y;
11 short velocityX;
12 short velocityY;
14
16 "opoqopoqopoqopoqqrstrq"; /* 0x00491c68 */
17
19 "abcdefghijkaakkkkaaaalllllllmmll",
20 "aaaaaaaabcddeeddccffgghhgghhiiih",
21 "aaaaaaaaaabbccbbaaccccccccccaccc",
22 "aaaabbbcccddeeddccffggaaggffcaaa",
23 "aabbbaacccddddddccddeeeeeeddccca",
24 "aaaaaabbbaaabbaaaabbbbaabbbbaccc",
25 "aabbcdbbbeaaaaaaeeaaaaaaaaaabaaa",
26 "abbbaacccdeeaaeeddaaaaaaaaaadacc",
27 "aaaaaaaaabbbccbbbbccddddddccaaaa",
28 "abccdefgghiijjiihhkkllmmllkkhnnn"
29}; /* 0x00491c80 */
30
32 { 58, 94, -1, 1 },
33 { 186, 94, 0, 1 },
34 { 278, 94, 1, 1 },
35 { 58, 102, -3, 2 },
36 { 186, 102, 0, 2 },
37 { 278, 102, 3, 2 },
38 { 58, 110, -5, 3 },
39 { 186, 110, 0, 3 },
40 { 278, 110, 5, 3 },
41 { 158, 74, 0, 4 }
42}; /* 0x00491ca8 */
43
44unsigned char *g_pTitleFieldShape = 0; /* 0x00491cf8 */
45
46extern unsigned char *g_apTitleSections[13]; /* 0x005d3f70 */
47
48extern void *g_pTitleMusic; /* 0x005d3fa4 */
49
50/* Function start: 0x407E40 */
52{
53 int waitCount;
54 short sectionIndex;
55
56 waitCount = 0;
59 FetchDiskPacketRetrying("music.r00", 19, 0);
61 FetchDiskPacketRetrying("field.v00", 1, 0);
62 for (sectionIndex = 0; sectionIndex < 12; sectionIndex++) {
63 g_apTitleSections[sectionIndex] =
64 FetchDiskPacketRetrying("title.vga",
65 (short)(sectionIndex + 1), 0);
66 }
70 FetchDiskPacketRetrying("title.vga", 0, 0);
73 while (1) {
77 break;
80 break;
83 break;
86 break;
87 sectionIndex = RevealTitleLogo();
88 if (g_nMusicDriverMode == 2 ||
89 g_nMusicDriverMode == 1) {
90 while (g_nTitleMusicSequenceStage < 3 &&
91 waitCount < 3) {
92 if (WaitForInputKey() != 0)
95 break;
96 waitCount++;
97 }
98 }
100 break;
101 ShowVictoryScreen(sectionIndex);
102 break;
103 }
104 StopMusic(0);
111 for (sectionIndex = 0; sectionIndex < 13; sectionIndex++)
116}
117
118/* Function start: 0x40809D */
126
127/* Function start: 0x4080DF */
129{
130 short actor;
131
132 DrawTitleSky(24);
133 for (actor = 0; actor < 10; actor++) {
136 g_aTitleActorMotion[actor].x,
137 g_aTitleActorMotion[actor].y,
138 g_apTitleSections[actor + 1], 0);
139 }
142}
143
144/* Random-range callee from the event manager. */
145unsigned short RandomInRange(unsigned short lo, unsigned short hi);
146
147/* Function start: 0x40815F */
149{
150 int repeat;
151 short frameNumber;
152 short actorIndex;
153 short minimumFrame;
154 short totalFrames;
155
156 minimumFrame = 0;
157 totalFrames = 0;
158 repeat = 0;
160 do {
161 for (frameNumber = minimumFrame; frameNumber < 32; frameNumber++) {
163 if (g_nFrameSkipCountdown < 1) {
165 DrawTitleSky(24);
166 for (actorIndex = 0; actorIndex < 10; actorIndex++) {
169 g_aTitleActorMotion[actorIndex].x,
170 g_aTitleActorMotion[actorIndex].y,
171 g_apTitleSections[actorIndex + 1],
172 (short)(g_apszTitleActorFrames[actorIndex]
173 [frameNumber] - 'a'));
174 }
176 }
177 if (WaitForInputKey() != 0)
181 return;
182 totalFrames++;
183 }
184 minimumFrame = (short)(
185 (unsigned short)RandomInRange(0, 13) + 9);
186 for (frameNumber = 31; frameNumber >= minimumFrame; frameNumber--) {
188 if (g_nFrameSkipCountdown < 1) {
190 DrawTitleSky(24);
191 for (actorIndex = 0; actorIndex < 10; actorIndex++) {
194 g_aTitleActorMotion[actorIndex].x,
195 g_aTitleActorMotion[actorIndex].y,
196 g_apTitleSections[actorIndex + 1],
197 (short)(g_apszTitleActorFrames[actorIndex]
198 [frameNumber] - 'a'));
199 }
201 }
202 if (WaitForInputKey() != 0)
206 return;
207 totalFrames++;
208 }
209 if ((g_nMusicDriverMode == 0 ||
210 g_nMusicDriverMode == 3) &&
211 totalFrames > 30)
212 return;
213 repeat++;
214 if (repeat > 1)
215 return;
216 } while (1);
217}
218
219/* Function start: 0x4083E6 */
221{
222 int repeat;
223 short cueNumber;
224 short actor;
225
226 repeat = 0;
228 for (cueNumber = 0; cueNumber < 20; cueNumber++) {
229 if (g_szTitleConductorFrames[cueNumber] == 'p') {
230 if (g_nMusicDriverMode == 2)
232 else if (g_nMusicDriverMode == 1)
234 } else if (g_szTitleConductorFrames[cueNumber] == 'q') {
235 if (g_nMusicDriverMode == 2)
237 else if (g_nMusicDriverMode == 1)
239 }
241 if (g_nFrameSkipCountdown < 1) {
243 DrawTitleSky(24);
244 for (actor = 0; actor < 9; actor++) {
247 g_aTitleActorMotion[actor].x,
248 g_aTitleActorMotion[actor].y,
249 g_apTitleSections[actor + 1],
250 (short)(g_apszTitleActorFrames[actor][31]
251 - 'a'));
252 }
258 (short)(g_szTitleConductorFrames[cueNumber] - 'a'));
260 }
261 if (WaitForInputKey() != 0)
264 return;
265 }
266
267 DrawTitleSky(24);
272 (short)(g_apszTitleActorFrames[0][31] - 'a'));
277 (short)(g_apszTitleActorFrames[1][31] - 'a'));
282 (short)(g_apszTitleActorFrames[2][31] - 'a'));
287 (short)(g_apszTitleActorFrames[3][31] - 'a'));
292 (short)(g_apszTitleActorFrames[4][31] - 'a'));
297 (short)(g_apszTitleActorFrames[5][31] - 'a'));
302 (short)(g_apszTitleActorFrames[6][31] - 'a'));
307 (short)(g_apszTitleActorFrames[7][31] - 'a'));
312 (short)(g_apszTitleActorFrames[8][31] - 'a'));
317 (short)(g_szTitleConductorFrames[20] - 'a'));
318 if (g_nMusicDriverMode == 2 ||
319 g_nMusicDriverMode == 1) {
320 do {
321 if (WaitForInputKey() != 0)
326 break;
327 }
328 repeat++;
329 if (repeat > 1)
330 break;
331 } while (1);
332 }
333}
334
335/* Function start: 0x4087FF */
336void DrawScaledTitleLogo(short y, short scale)
337{
338 short bounds[4];
339
342 g_apTitleSections[0], 1, 0, scale, 0, bounds);
344 g_apTitleSections[0], 0, 0, scale, 0);
346 g_apTitleSections[0], 1, 0, scale, 0);
348 (short)(bounds[2] + 1), y,
349 g_apTitleSections[0], 2, 0, scale, 0);
350}
351
352/* Function start: 0x4088A9 */
354{
355 short x;
356 short y;
357 short actor;
358 short step;
359
361 for (step = 1; step < 120;
362 step = (short)(step + step / 4 + 1)) {
364 if (g_nFrameSkipCountdown < 1) {
366 DrawTitleSky(24);
367 for (actor = 0; actor < 9; actor++) {
368 x = (short)(g_aTitleActorMotion[actor].x +
369 g_aTitleActorMotion[actor].velocityX *
370 step);
371 y = (short)(g_aTitleActorMotion[actor].y +
372 g_aTitleActorMotion[actor].velocityY *
373 step);
376 g_apTitleSections[actor + 1],
377 (short)(g_apszTitleActorFrames[actor][31]
378 - 'a'),
379 0,
380 (short)(g_aTitleActorMotion[actor].velocityY *
381 step * 4 + 0x100),
382 0);
383 }
384 x = (short)(g_aTitleActorMotion[9].x +
385 g_aTitleActorMotion[9].velocityX * step);
386 y = (short)(g_aTitleActorMotion[9].y +
387 g_aTitleActorMotion[9].velocityY * step);
391 (short)(g_szTitleConductorFrames[21] - 'a'),
392 0,
393 (short)(g_aTitleActorMotion[9].velocityY *
394 step * 4 + 0x100),
395 0);
397 }
398 if (WaitForInputKey() != 0)
401 break;
402 }
403}
404
405/* Function start: 0x408A88 */
407{
408 short scale;
409 short distance;
410 short titleY;
411 short planetDelay;
412 short logoCovers;
413 short redraw;
414 short extent[4];
415 short aborted;
416 short logoTimer;
417 short planetY;
418
419 aborted = 0;
420 logoCovers = 0;
421 titleY = 59;
423 distance = 5000;
424 planetDelay = 0;
425 logoTimer = 0;
426 for (; distance >= 1000;
427 distance--, planetDelay--, logoTimer--) {
428 redraw = 0;
429 if (planetDelay == 0) {
430 redraw = 1;
431 planetY = (short)(120000 / (int)distance);
432 planetDelay = 200;
433 }
434 if (logoTimer == 0) {
435 redraw = 1;
436 scale = (short)(256000 / (int)distance);
437 if (distance > 3000)
438 titleY = (short)(titleY - 2);
439 else
440 titleY = (short)(titleY + 2);
441 logoTimer = 100;
442 }
443 if (redraw != 0) {
445 if (g_nFrameSkipCountdown < 1) {
448 0, 0,
451 &g_stSecondaryViewBufferBlock, 162, titleY,
452 g_apTitleSections[0], 1, 0,
453 scale, 0, extent);
454 if (extent[3] < planetY)
455 logoCovers = 1;
456 if (logoCovers == 0) {
457 DrawScaledTitleLogo(titleY, scale);
460 160, planetY,
461 g_apTitleSections[12], 0);
462 } else {
465 160, planetY,
466 g_apTitleSections[12], 0);
467 DrawScaledTitleLogo(titleY, scale);
468 }
470 }
471 }
472 if (WaitForInputKey() != 0)
475 return titleY;
476 }
479 DrawScaledTitleLogo(titleY, scale);
481 return titleY;
482}
483
484/* Function start: 0x408CC8 */
485void ShowVictoryScreen(short logoY)
486{
487 int loopCount;
488 short fadeOut;
489 short finalEmptyCount;
490 short inactive;
491 short firework;
492 short frameCount;
493 short spawnFirework;
494
495 fadeOut = 0;
496 frameCount = 0;
497 loopCount = 0;
500 do {
501 if (fadeOut == 0) {
502 if (g_nMusicDriverMode == 2 ||
503 g_nMusicDriverMode == 1) {
505 spawnFirework = (short)(
506 (unsigned short)RandomInRange(0, 0) == 0);
507 } else {
508 spawnFirework = (short)(
509 (unsigned short)RandomInRange(0, 5) == 0);
510 }
511 } else {
512 spawnFirework = (short)(
513 (unsigned short)RandomInRange(0, 0) == 0);
514 }
515 }
516 if (spawnFirework != 0 && fadeOut == 0) {
517 for (firework = 0; firework < 5; firework++) {
518 if (g_16_aFireworks[firework].frame == -1) {
519 g_16_aFireworks[firework].frame = 0;
520 g_16_aFireworks[firework].x =
521 RandomInRange(0, 319);
522 g_16_aFireworks[firework].y =
523 RandomInRange(0, 127);
524 g_16_aFireworks[firework].variant =
525 RandomInRange(0, 2);
526 break;
527 }
528 }
529 }
532 inactive = TheEndFireWorks(
534 DrawScaledTitleLogo(logoY, 0x100);
536 frameCount++;
537 if (fadeOut == 1 && inactive == 5)
538 break;
539 if (g_nMusicDriverMode == 2 ||
540 g_nMusicDriverMode == 1) {
542 fadeOut = 1;
543 } else if (frameCount > 10) {
544 fadeOut = 1;
545 }
546 if (WaitForInputKey() != 0)
549 return;
550 loopCount++;
551 if (loopCount > 10)
552 break;
553 /* The SDL build drops the iteration cap: the real MS-DOS WC2.EXE's
554 * equivalent loop has none (see the comment above
555 * SdlPaceTitleFrame). The fadeOut/inactive==5 break above (DOS's
556 * own only real exit) and the escape-key return are what end it.
557 * Non-music-driven mode still ends the same way DOS does --
558 * frameCount > 10 sets fadeOut, then that break fires once every
559 * firework has finished animating. */
560 } while (1);
561
562 for (firework = 0; firework < 29; firework++) {
563 g_16_aFireworks[firework].frame = 0;
564 g_16_aFireworks[firework].x = RandomInRange(0, 319);
565 g_16_aFireworks[firework].y = RandomInRange(0, 127);
566 g_16_aFireworks[firework].variant = RandomInRange(0, 2);
567 }
568 inactive = 0;
569 finalEmptyCount = 0;
570 while (inactive != 30) {
571 finalEmptyCount++;
572 if (finalEmptyCount == 4) {
573 g_16_aFireworks[29].frame = 0;
574 g_16_aFireworks[29].x = RandomInRange(0, 319);
575 g_16_aFireworks[29].y = RandomInRange(0, 127);
577 }
580 inactive = TheEndFireWorks(
582 DrawScaledTitleLogo(logoY, 0x100);
584 if (WaitForInputKey() != 0)
587 return;
588 }
589
590 for (firework = 29; firework >= 0; firework--) {
591 if (g_16_aFireworks[firework].frame != -1) {
592 ((void (__cdecl *)(int, short))FlushSoundEffect)(
593 g_16_aFireworks[firework].soundHandle, firework);
594 }
595 }
596}
597
598/* Linker commons defined here. LINK lays a unit's commons out by the
599 * identifiers' hash keys, so these spellings follow the original addresses. */
600unsigned char *g_apTitleSections[13]; /* 0x005d3f70 */
601void *g_pTitleMusic; /* 0x005d3fa4 */
void(__cdecl *g_pIxFree)(void *)
void DrawTitleSky(short planetY)
Definition intro.c:119
void FadeViewportPaletteToColour(Viewport *viewport, unsigned short colour, short enabled)
Definition palfade.c:10
short GetTransformedShapeBounds(Viewport *viewport, short x, short y, unsigned char *shape, short frame, short angle, short scale, short flip, short *bounds)
Definition gr.c:1518
short StartMusic(void *music)
Definition music.c:37
void RefreshMemoryStatusOverlay(void)
Definition main.c:283
void ResetScreenClipToFullHeight(void)
Definition message.c:125
void PushTitleOrchestraAway(void)
Definition intro.c:353
void StopMusic(short enabled)
Definition music.c:30
void AnimateTitleOrchestra(void)
Definition intro.c:148
void RestoreGamePalette(void)
Definition palette.c:21
void DrawTitleOrchestra(void)
Definition intro.c:128
void DrawSpriteDefault(Viewport *viewport, short x, short y, unsigned char *shape, short frame)
Definition gr.c:682
short WaitForInputKey(void)
Definition disk.c:319
void * FetchDiskPacketRetrying(char *fileName, short section, short flags)
Definition disk.c:187
void InitializeConversationViewport(void)
Definition message.c:108
void InitializeFireworks(void)
Definition starfld.c:17
void PanToScreen(Viewport *source, Viewport *destination)
Definition pan.c:10
short TheEndFireWorks(Viewport *viewport, short count)
Definition starfld.c:26
void ClearViewport(Viewport *viewport, short colour)
Definition gr.c:1027
void DrawScaledTitleLogo(short y, short scale)
Definition intro.c:336
void Title_Sequence(void)
Definition intro.c:51
void ReleasePacketHandle(void *handle)
Definition memapi.c:108
void DrawSpriteScaled(Viewport *viewport, short x, short y, unsigned char *shape, short frame, short angle, short scale, short flip)
Definition gr.c:1494
void FlushSoundEffect(void)
Definition music.c:61
void ShowVictoryScreen(short logoY)
Definition intro.c:485
short RevealTitleLogo(void)
Definition intro.c:406
unsigned short RandomInRange(unsigned short lo, unsigned short hi)
Definition eventmgr.c:31
void FreePacketAndClear(void *slot, unsigned short releaseFlags)
Definition disk.c:45
void FlushSoundEffects(void)
Definition music.c:68
void PlayTitleConductorCue(void)
Definition intro.c:220
Shared Win32 declarations, types and library interfaces.
short g_nFrameSkip
Definition main.c:1940
signed char g_bSceneEscapeRequested
Definition eventmgr.c:2420
FireworkState g_16_aFireworks[30]
Definition starfld.c:233
unsigned char * g_1_pTitleFireworkShape
Definition starfld.c:234
unsigned char g_cSecondaryViewBufferColour
Definition startup.c:544
short g_nMusicDriverMode
Definition music.c:522
Viewport g_2_stModalSourceWindow
Definition message.c:231
Viewport g_101_stScrViewInfo
Definition cockpt.c:3831
Viewport g_stSecondaryViewBufferBlock
Definition message.c:234
short g_18_nInterfaceEventMode
Definition eventmgr.c:2570
short g_nFrameSkipCountdown
Definition main.c:1939
short g_nTitleMusicSequenceStage
Definition music.c:524
char g_szTitleConductorFrames[]
Definition intro.c:15
char * g_apszTitleActorFrames[10]
Definition intro.c:18
unsigned char * g_apTitleSections[13]
Definition intro.c:600
TitleActorMotion g_aTitleActorMotion[10]
Definition intro.c:31
unsigned char * g_pTitleFieldShape
Definition intro.c:44
void * g_pTitleMusic
Definition intro.c:601
short velocityY
Definition intro.c:12
short velocityX
Definition intro.c:11