From 5977243f786c5663abb2f8debdb1bebb33fa093a Mon Sep 17 00:00:00 2001 From: avolkov Date: Wed, 28 Dec 2005 15:54:13 +0000 Subject: [PATCH] Added unified credit roll w/ outtakes; first version git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2135 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/content/starcon.lst | 27 +- sc2/src/sc2code/comm.c | 20 +- sc2/src/sc2code/comm.h | 3 + sc2/src/sc2code/credits.c | 783 +++++++++++++++++++++++++++++++++---- sc2/src/sc2code/credits.h | 5 +- sc2/src/sc2code/ifontres.h | 3 + sc2/src/sc2code/igfxres.h | 21 +- sc2/src/sc2code/istrtab.h | 1 + sc2/src/sc2code/oscill.c | 4 + sc2/src/sc2code/oscill.h | 1 + sc2/src/sc2code/respkg.h | 42 +- sc2/src/sc2code/restart.c | 3 +- 12 files changed, 756 insertions(+), 157 deletions(-) diff --git a/sc2/content/starcon.lst b/sc2/content/starcon.lst index 96ff6aa1c..646ea0146 100644 --- a/sc2/content/starcon.lst +++ b/sc2/content/starcon.lst @@ -437,29 +437,14 @@ 260 262 2 lbm/yeg__med.ani 260 263 2 lbm/yeg__sml.ani 261 12 6 lbm/battle.mod -262 264 2 lbm/credit00.ani -263 265 2 lbm/credit01.ani -264 266 2 lbm/credit02.ani -265 267 2 lbm/credit03.ani -266 268 2 lbm/credit04.ani -267 269 2 lbm/credit05.ani -268 270 2 lbm/credit06.ani -269 271 2 lbm/credit07.ani -270 272 2 lbm/credit08.ani -271 273 2 lbm/credit09.ani -272 274 2 lbm/credit10.ani -273 275 2 lbm/credit11.ani -274 276 2 lbm/credit12.ani -275 277 2 lbm/credit13.ani -276 278 2 lbm/credit14.ani -277 279 2 lbm/credit15.ani -278 280 2 lbm/credit16.ani -279 281 2 lbm/credit17.ani -280 282 2 lbm/credit18.ani -281 283 2 lbm/credit19.ani -282 13 6 lbm/credits.mod +262 264 2 credits/credback.ani +282 13 6 credits/credits.mod 283 284 2 slides/ending/sis_skel.ani 284 285 2 ipanims/orbenter.ani 285 286 2 lbm/setupmenu.ani 286 98 4 slides/intro/intro.txt 287 99 4 slides/ending/ending.txt +288 5 3 credits/pt13.fon +288 6 3 credits/pt17.fon +288 7 3 credits/pt45.fon +289 100 4 credits/credits.txt diff --git a/sc2/src/sc2code/comm.c b/sc2/src/sc2code/comm.c index d016b868d..8913c3a23 100644 --- a/sc2/src/sc2code/comm.c +++ b/sc2/src/sc2code/comm.c @@ -139,6 +139,12 @@ static const UNICODE * volatile last_subtitle; CONTEXT TextCacheContext; FRAME TextCacheFrame; +RECT CommWndRect = { + // default values; actually inited by HailAlien() + {SIS_ORG_X, SIS_ORG_Y}, + {0, 0} +}; + /* _count_lines - sees how many lines a given input string would take to * display given the line wrapping information */ @@ -1373,11 +1379,7 @@ AlienTalkSegue (COUNT wait_track) } else { - r.corner.x = 0; - r.corner.y = 0; - r.extent.width = SCREEN_WIDTH; - r.extent.height = SCREEN_HEIGHT; - ScreenTransition (3, &r); + ScreenTransition (3, &CommWndRect); } UnbatchGraphics (); } @@ -1851,20 +1853,22 @@ HailAlien (void) SetContext (TaskContext); SetContextFGFrame (Screen); GetFrameRect (CommData.AlienFrame, &r); - r.corner.y = SIS_ORG_Y; r.extent.width = SIS_SCREEN_WIDTH; - + CommWndRect.extent = r.extent; + SetTransitionSource (NULL); BatchGraphics (); if (LOBYTE (GLOBAL (CurrentActivity)) == WON_LAST_BATTLE) { - r.corner.x = (SCREEN_WIDTH - SIS_SCREEN_WIDTH) >> 1; + r.corner = CommWndRect.corner; SetContextClipRect (&r); } else { r.corner.x = SIS_ORG_X; + r.corner.y = SIS_ORG_Y; SetContextClipRect (&r); + CommWndRect.corner = r.corner; if (pMenuState == 0) { diff --git a/sc2/src/sc2code/comm.h b/sc2/src/sc2code/comm.h index 533c2bb5a..350803c55 100644 --- a/sc2/src/sc2code/comm.h +++ b/sc2/src/sc2code/comm.h @@ -18,11 +18,14 @@ #define _COMM_H #include "libs/compiler.h" +#include "libs/gfxlib.h" extern void init_communication (void); extern void uninit_communication (void); extern int do_subtitles (UNICODE *pStr); extern void AlienTalkSegue (COUNT wait_track); +extern RECT CommWndRect; /* comm window rect */ + #endif /* _COMM_H */ diff --git a/sc2/src/sc2code/credits.c b/sc2/src/sc2code/credits.c index 99579a49f..a912054a4 100644 --- a/sc2/src/sc2code/credits.c +++ b/sc2/src/sc2code/credits.c @@ -22,100 +22,577 @@ #include "encount.h" #include "options.h" #include "oscill.h" +#include "comm.h" #include "resinst.h" +#include "nameref.h" #include "settings.h" +#include "sounds.h" #include "setup.h" #include "libs/graphics/gfx_common.h" #include "libs/sound/sound.h" +#include +// Rates in pixel lines per second +#define CREDITS_BASE_RATE 9 +#define CREDITS_MAX_RATE 130 +// Maximum frame rate +#define CREDITS_FRAME_RATE 36 -void -Credits (void) +#define CREDITS_TIMEOUT (ONE_SECOND * 5) + +static volatile int CreditsRate; +static volatile BOOLEAN OutTakesRunning; +static volatile BOOLEAN CreditsRunning; +static STRING CreditsTab; +static FRAME CreditsBack; + +typedef struct { -#define NUM_CREDITS 20 - COUNT i; - RES_TYPE rt; - RES_INSTANCE ri; - RES_PACKAGE rp; - RECT r; - FRAME f[NUM_CREDITS]; - STAMP s; - DWORD TimeIn; - MUSIC_REF hMusic; - BYTE fade_buf[1]; + int size; + DWORD res; + FONT font; +} FONT_SIZE_DEF; - if (GLOBAL (CurrentActivity) & CHECK_ABORT) - return; - - rt = GET_TYPE (CREDIT00_ANIM); - ri = GET_INSTANCE (CREDIT00_ANIM); - rp = GET_PACKAGE (CREDIT00_ANIM); - for (i = 0; i < NUM_CREDITS; ++i, ++rp, ++ri) +static FONT_SIZE_DEF CreditsFont[] = +{ + { 13, PT13AA_FONT, 0 }, + { 17, PT17AA_FONT, 0 }, + { 45, PT45AA_FONT, 0 }, + { 0, 0, 0 }, +}; + + +static FRAME +Credits_MakeTextFrame (int w, int h, COLOR TransColor) +{ + FRAME OldFrame; + FRAME f; + + f = CaptureDrawable (CreateDrawable (WANT_PIXMAP, w, h, 1)); + SetFrameTransparentColor (f, TransColor); + + OldFrame = SetContextFGFrame (f); + SetContextBackGroundColor (TransColor); + ClearDrawable (); + SetContextFGFrame (OldFrame); + + return f; +} + +static void +CopyTextString (char *Buffer, COUNT BufSize, const char *Src) +{ + strncpy (Buffer, Src, BufSize); + Buffer[BufSize - 1] = '\0'; +} + +static int +ParseTextLines (TEXT *Lines, int MaxLines, char *Buffer) +{ + int i; + const char* pEnd = Buffer + strlen(Buffer); + + for (i = 0; i < MaxLines && Buffer < pEnd; ++i, ++Lines) { - f[i] = CaptureDrawable (LoadGraphic ( - MAKE_RESOURCE (rp, rt, ri) - )); + char* pTerm = strchr(Buffer, '\n'); + if (!pTerm) + pTerm = Buffer + strlen(Buffer); + *pTerm = '\0'; /* terminate string */ + Lines->pStr = Buffer; + Lines->CharCount = ~0; + Buffer = pTerm + 1; } + return i; +} + +#define MAX_TEXT_LINES 50 +#define MAX_TEXT_COLS 5 + +static FRAME +Credits_RenderTextFrame (CONTEXT TempContext, int *istr, int dir, + COLOR BackColor, COLOR ForeColor) +{ + FRAME f; + CONTEXT OldContext; + FRAME OldFrame; + TEXT TextLines[MAX_TEXT_LINES]; + STRINGPTR pStr; + int size; + char salign[32]; + char *scol; + int scaned; + int i, rows, cnt; + char buf[2048]; + FONT_SIZE_DEF *fdef; + SIZE leading; + TEXT t; + RECT r; + typedef struct + { + TEXT_ALIGN align; + COORD basex; + } col_format_t; + col_format_t colfmt[MAX_TEXT_COLS]; + + if (*istr < 0 || *istr >= GetStringTableCount (CreditsTab)) + { // check if next one is within range + int next_s = *istr + dir; + + if (next_s < 0 || next_s >= GetStringTableCount (CreditsTab)) + return 0; + + *istr = next_s; + } + + // skip empty lines + while (*istr >= 0 && *istr < GetStringTableCount (CreditsTab)) + { + pStr = GetStringAddress ( + SetAbsStringTableIndex (CreditsTab, *istr)); + *istr += dir; + if (pStr && *pStr != '\0') + break; + } + + if (!pStr || *pStr == '\0') + return 0; - hMusic = LoadMusicInstance (CREDITS_MUSIC); - if (hMusic) - PlayMusic (hMusic, TRUE, 1); + if (2 != sscanf (pStr, "%d %32s %n", &size, salign, &scaned) + || size <= 0) + return 0; + pStr += scaned; + + CopyTextString (buf, sizeof (buf), pStr); + rows = ParseTextLines (TextLines, MAX_TEXT_LINES, buf); + if (rows == 0) + return 0; + // parse text columns + for (i = 0, cnt = rows; i < rows; ++i) + { + char *nextcol; + int icol; + + // we abuse the baseline here, but only a tiny bit + // every line starts at col 0 + TextLines[i].baseline.x = 0; + TextLines[i].baseline.y = i + 1; + + for (icol = 1, nextcol = strchr (TextLines[i].pStr, '\t'); + icol < MAX_TEXT_COLS && nextcol; + ++icol, nextcol = strchr (nextcol, '\t')) + { + *nextcol = '\0'; + ++nextcol; + + if (cnt < MAX_TEXT_LINES) + { + TextLines[cnt].pStr = nextcol; + TextLines[cnt].CharCount = ~0; + TextLines[cnt].baseline.x = icol; + TextLines[cnt].baseline.y = i + 1; + ++cnt; + } + } + } + + // init alignments + for (i = 0; i < MAX_TEXT_COLS; ++i) + { + colfmt[i].align = ALIGN_LEFT; + colfmt[i].basex = SCREEN_WIDTH / 64; + } + + // find the right font + for (fdef = CreditsFont; fdef->size && size > fdef->size; ++fdef) + ; + if (!fdef->size) + return 0; + + t.align = ALIGN_LEFT; + t.valign = VALIGN_MIDDLE; + t.baseline.x = 100; // any value will do + t.baseline.y = 100; // any value will do + t.pStr = " "; + t.CharCount = 1; LockMutex (GraphicsLock); - SetContext (ScreenContext); - GetContextClipRect (&r); - s.origin.x = s.origin.y = 0; - - BatchGraphics (); - s.frame = f[0]; - DrawStamp (&s); - UnbatchGraphics (); - - fade_buf[0] = FadeAllToColor; - SleepThreadUntil (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND / 2)); - - TimeIn = GetTimeCounter (); - for (i = 1; (i < NUM_CREDITS) && - !(GLOBAL (CurrentActivity) & CHECK_ABORT); ++i) + OldContext = SetContext (TempContext); + + // get font dimensions + SetContextFont (fdef->font); + GetContextFontLeading (&leading); + // get left/right margin + TextRect (&t, &r, NULL_PTR); + + // parse text column alignment + for (i = 0, scol = strtok (salign, ","); + scol && i < MAX_TEXT_COLS; + ++i, scol = strtok (NULL, ",")) { - SetTransitionSource (&r); - BatchGraphics (); - s.frame = f[0]; - DrawStamp (&s); - s.frame = f[i]; - DrawStamp (&s); - ScreenTransition (3, &r); - UnbatchGraphics (); - DestroyDrawable (ReleaseDrawable (f[i])); - - UnlockMutex (GraphicsLock); - while ((GetTimeCounter () - TimeIn < ONE_SECOND * 5) && - !(GLOBAL (CurrentActivity) & CHECK_ABORT)) + char c; + int x; + int n; + + // default + colfmt[i].align = ALIGN_LEFT; + colfmt[i].basex = r.extent.width; + + n = sscanf (scol, "%c/%d", &c, &x); + if (n < 1) + { // DOES NOT COMPUTE! :) + continue; + } + + switch (c) { - UpdateInputState (); - SleepThreadUntil (ONE_SECOND / 20); + case 'L': + colfmt[i].align = ALIGN_LEFT; + if (n >= 2) + colfmt[i].basex = x; + break; + case 'C': + colfmt[i].align = ALIGN_CENTER; + if (n >= 2) + colfmt[i].basex = x; + else + colfmt[i].basex = SCREEN_WIDTH / 2; + break; + case 'R': + colfmt[i].align = ALIGN_RIGHT; + if (n >= 2) + colfmt[i].basex = x; + else + colfmt[i].basex = SCREEN_WIDTH - r.extent.width; + break; } - LockMutex (GraphicsLock); - TimeIn = GetTimeCounter (); } + + for (i = 0; i < cnt; ++i) + { + // baseline contains coords in row/col quantities + col_format_t *fmt = colfmt + TextLines[i].baseline.x; + + TextLines[i].align = fmt->align; + TextLines[i].valign = VALIGN_MIDDLE; + TextLines[i].baseline.x = fmt->basex; + TextLines[i].baseline.y *= leading; + } + + f = Credits_MakeTextFrame (SCREEN_WIDTH, leading * rows + (leading >> 1), + BackColor); + OldFrame = SetContextFGFrame (f); + // draw text + SetContextForeGroundColor (ForeColor); + for (i = 0; i < cnt; ++i) + font_DrawText (TextLines + i); - DestroyDrawable (ReleaseDrawable (f[0])); + SetContextFGFrame (OldFrame); + SetContext (OldContext); UnlockMutex (GraphicsLock); - WaitAnyButtonOrQuit (FALSE); + return f; +} + +#define CREDIT_FRAMES 32 + +static int +credit_roll_task (void *data) +{ + Task task = (Task) data; + CONTEXT OldContext; + DWORD TimeIn; + CONTEXT DrawContext; + CONTEXT LocalContext; + FRAME Frame; + COLOR TransColor, TextFore, TextBack; + STAMP TaskStamp; + STAMP s; + FRAME cf[CREDIT_FRAMES]; // preped text frames + int ci[CREDIT_FRAMES]; // strtab indices + int first = 0, last; + int dy = 0, total_h, disp_h, deficit_h = 0; + int strcnt; + + CreditsRunning = TRUE; + + memset(cf, 0, sizeof(cf)); + + strcnt = GetStringTableCount (CreditsTab); + + TransColor = BUILD_COLOR (MAKE_RGB15 (0, 0, 0x10), 1); + TextBack = BUILD_COLOR (MAKE_RGB15 (0, 0, 0), 0); + TextFore = BUILD_COLOR (MAKE_RGB15 (0x1F, 0x1F, 0x1F), 0x0F); + + LocalContext = CaptureContext (CreateContext ()); + DrawContext = CaptureContext (CreateContext ()); - fade_buf[0] = FadeAllToBlack; - SleepThreadUntil (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND / 2)); - FlushColorXForms (); + total_h = disp_h = SCREEN_HEIGHT; + + LockMutex (GraphicsLock); + // prep our local context + OldContext = SetContext (LocalContext); - if (hMusic) + // prep the first frame + cf[0] = Credits_MakeTextFrame (1, total_h, TransColor); + ci[0] = -1; + last = 1; + // prep the local screen copy + Frame = Credits_MakeTextFrame (SCREEN_WIDTH, disp_h, TransColor); + SetContextFGFrame (Frame); + + // prep our task context + SetContext (DrawContext); + SetContextFGFrame (Screen); + + SetContext (OldContext); + UnlockMutex (GraphicsLock); + + TaskStamp.origin.x = TaskStamp.origin.y = 0; + TaskStamp.frame = Frame; + + // stary background is the first screen frame + LockMutex (GraphicsLock); + OldContext = SetContext (LocalContext); + // draw + s.origin.x = s.origin.y = 0; + s.frame = CreditsBack; + DrawStamp (&s); + // draw clipped rect, if any + if (OutTakesRunning) { - StopMusic (); - DestroyMusic (hMusic); + SetContextForeGroundColor (TransColor); + DrawFilledRectangle (&CommWndRect); + } + SetContext (OldContext); + UnlockMutex (GraphicsLock); + + while (!Task_ReadState (task, TASK_EXIT)) + { + RECT fr; + int i; + int rate, direction, dirstep; + + TimeIn = GetTimeCounter (); + + rate = abs (CreditsRate); + if (rate != 0) + { + // scroll direction; forward or backward + direction = CreditsRate / rate; + // step in pixels + dirstep = (rate + CREDITS_FRAME_RATE - 1) / CREDITS_FRAME_RATE; + rate = ONE_SECOND * dirstep / rate; + // step is also directional + dirstep *= direction; + } + else + { // scroll stopped + direction = 0; + dirstep = 0; + // one second interframe + rate = ONE_SECOND; + } + + // draw the credits + // comm animations play with contexts so we need to make + // sure the context is not desynced + LockMutex (GraphicsLock); + OldContext = SetContext (DrawContext); + DrawStamp (&TaskStamp); + SetContext (OldContext); + FlushGraphics (); + UnlockMutex (GraphicsLock); + + // prepare next screen frame + dy += dirstep; + // cap scroll + if (dy < -(disp_h / 20)) + { // at the begining + // accelerated slow down + if (CreditsRate < 0) + CreditsRate -= CreditsRate / 10 - 1; + } + else if (deficit_h > disp_h / 25) + { // frame deficit -- task almost over + // accelerated slow down + if (CreditsRate > 0) + CreditsRate -= CreditsRate / 10 + 1; + + CreditsRunning = (CreditsRate != 0); + } + else if (!CreditsRunning) + { // resumed + CreditsRunning = TRUE; + } + + if (first != last) + { // clean up frames that scrolled off the screen + if (direction > 0) + { // forward scroll + GetFrameRect (cf[first], &fr); + if (dy >= (int)fr.extent.height) + { // past this frame already + total_h -= fr.extent.height; + DestroyDrawable (ReleaseDrawable (cf[first])); + cf[first] = 0; + // next frame + first = (first + 1) % CREDIT_FRAMES; + dy = 0; + } + } + else if (direction < 0) + { // backward scroll + int index = (last - 1 + CREDIT_FRAMES) % CREDIT_FRAMES; + + GetFrameRect (cf[index], &fr); + if (total_h - dy - (int)fr.extent.height >= disp_h) + { // past this frame already + last = index; + total_h -= fr.extent.height; + DestroyDrawable (ReleaseDrawable (cf[last])); + cf[last] = 0; + } + } + } + + // render new text frames if needed + if (direction > 0) + { // forward scroll + int next_s = 0; + + // get next string + if (first != last) + next_s = ci[(last - 1 + CREDIT_FRAMES) % CREDIT_FRAMES] + 1; + + while (total_h - dy < disp_h && next_s < strcnt) + { + cf[last] = Credits_RenderTextFrame (LocalContext, + &next_s, direction, TextBack, TextFore); + ci[last] = next_s - 1; + if (cf[last]) + { + GetFrameRect (cf[last], &fr); + total_h += fr.extent.height; + + last = (last + 1) % CREDIT_FRAMES; + } + } + } + else if (direction < 0) + { // backward scroll + int next_s = strcnt - 1; + + // get next string + if (first != last) + next_s = ci[first] - 1; + + while (dy < 0 && next_s >= 0) + { + int index = (first - 1 + CREDIT_FRAMES) % CREDIT_FRAMES; + cf[index] = Credits_RenderTextFrame (LocalContext, + &next_s, direction, TextBack, TextFore); + ci[index] = next_s + 1; + if (cf[index]) + { + GetFrameRect (cf[index], &fr); + total_h += fr.extent.height; + + first = index; + dy += fr.extent.height; + } + } + } + + // draw next screen frame + LockMutex (GraphicsLock); + OldContext = SetContext (LocalContext); + // draw background + s.origin.x = s.origin.y = 0; + s.frame = CreditsBack; + DrawStamp (&s); + // draw text frames + s.origin.y = -dy; + for (i = first; i != last; i = (i + 1) % CREDIT_FRAMES) + { + s.frame = cf[i]; + DrawStamp (&s); + GetFrameRect (s.frame, &fr); + s.origin.y += fr.extent.height; + } + if (direction > 0) + deficit_h = disp_h - s.origin.y; + + // draw clipped rect, if any + if (OutTakesRunning) + { + SetContextForeGroundColor (TransColor); + DrawFilledRectangle (&CommWndRect); + } + SetContext (OldContext); + UnlockMutex (GraphicsLock); + + // wait till begining of next screen frame + while (GetTimeCounter () < TimeIn + rate + && !Task_ReadState (task, TASK_EXIT)) + { + SleepThreadUntil (ONE_SECOND / CREDITS_FRAME_RATE / 2); + } + } + + DestroyContext (ReleaseContext (DrawContext)); + DestroyContext (ReleaseContext (LocalContext)); + + // free remaining frames + DestroyDrawable (ReleaseDrawable (Frame)); + for ( ; first != last; first = (first + 1) % CREDIT_FRAMES) + DestroyDrawable (ReleaseDrawable (cf[first])); + + FinishTask (task); + return 0; +} + +static Task +StartCredits (void) +{ + Task task; + FONT_SIZE_DEF *fdef; + + CreditsTab = CaptureStringTable (LoadStringTable (CREDITS_STRTAB)); + if (!CreditsTab) + return 0; + CreditsBack = CaptureDrawable (LoadGraphic (CREDITS_BACK_ANIM)); + // load fonts + for (fdef = CreditsFont; fdef->size; ++fdef) + fdef->font = CaptureFont (LoadGraphic (fdef->res)); + + CreditsRate = CREDITS_BASE_RATE; + CreditsRunning = FALSE; + + task = AssignTask (credit_roll_task, 4096, "credit roll"); + + return task; +} + +static void +FreeCredits (void) +{ + FONT_SIZE_DEF *fdef; + + DestroyStringTable (ReleaseStringTable (CreditsTab)); + CreditsTab = 0; + + DestroyDrawable (ReleaseDrawable (CreditsBack)); + CreditsBack = 0; + + // free fonts + for (fdef = CreditsFont; fdef->size; ++fdef) + { + DestroyFont (ReleaseFont (fdef->font)); + fdef->font = 0; } } -void +static void OutTakes (void) { #define NUM_OUTTAKES 15 @@ -138,25 +615,12 @@ OutTakes (void) ARILOU_CONVERSATION }; - RECT r; BOOLEAN oldsubtitles = optSubtitles; int i = 0; - BYTE fade_buf[1]; optSubtitles = TRUE; sliderDisabled = TRUE; - - LockMutex (GraphicsLock); - SetContext (ScreenContext); - SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x0, 0x0, 0x0), 0x00)); - fade_buf[0] = FadeAllToColor; - XFormColorMap ((COLORMAPPTR)fade_buf, 0); - - r.corner.x = r.corner.y = 0; - r.extent.width = SCREEN_WIDTH; - r.extent.height = SCREEN_HEIGHT; - DrawFilledRectangle (&r); - UnlockMutex (GraphicsLock); + oscillDisabled = TRUE; for (i = 0; (i < NUM_OUTTAKES) && !(GLOBAL (CurrentActivity) & CHECK_ABORT); i++) @@ -164,12 +628,163 @@ OutTakes (void) InitCommunication (outtake_list[i]); } + optSubtitles = oldsubtitles; + sliderDisabled = FALSE; + oscillDisabled = FALSE; +} + +typedef struct +{ + // standard state required by DoInput + BOOLEAN (*InputFunc) (PVOID pInputState); + COUNT MenuRepeatDelay; + + BOOLEAN AllowCancel; + BOOLEAN AllowSpeedChange; + BOOLEAN CloseWhenDone; + DWORD CloseTimeOut; + +} CREDITS_INPUT_STATE; + +static BOOLEAN +DoCreditsInput (PVOID pIS) +{ + CREDITS_INPUT_STATE *pCIS = (CREDITS_INPUT_STATE *) pIS; + + if (CreditsRunning) + { // cancel timeout if resumed (or just running) + pCIS->CloseTimeOut = 0; + } + + if ((GLOBAL (CurrentActivity) & CHECK_ABORT) + || (pCIS->AllowCancel && + (PulsedInputState.key[KEY_MENU_SELECT] || + PulsedInputState.key[KEY_MENU_CANCEL])) + ) + { // aborted + return FALSE; + } + + if (pCIS->AllowSpeedChange + && (PulsedInputState.key[KEY_MENU_UP] + || PulsedInputState.key[KEY_MENU_DOWN])) + { // speed adjustment + int newrate = CreditsRate; + int step = abs (CreditsRate) / 5 + 1; + + if (PulsedInputState.key[KEY_MENU_DOWN]) + newrate += step; + else if (PulsedInputState.key[KEY_MENU_UP]) + newrate -= step; + if (newrate < -CREDITS_MAX_RATE) + newrate = -CREDITS_MAX_RATE; + else if (newrate > CREDITS_MAX_RATE) + newrate = CREDITS_MAX_RATE; + + CreditsRate = newrate; + } + + if (!CreditsRunning) + { // always allow cancelling once credits run through + pCIS->AllowCancel = TRUE; + } + + if (!CreditsRunning && pCIS->CloseWhenDone) + { // auto-close controlled by timeout + if (pCIS->CloseTimeOut == 0) + { // set timeout + pCIS->CloseTimeOut = GetTimeCounter () + CREDITS_TIMEOUT; + } + else if (GetTimeCounter () > pCIS->CloseTimeOut) + { // all done! + return FALSE; + } + } + + if (!CreditsRunning + && (PulsedInputState.key[KEY_MENU_SELECT] + || PulsedInputState.key[KEY_MENU_CANCEL])) + { // credits finished and exit requested + return FALSE; + } + + SleepThread (ONE_SECOND / 30); + + return TRUE; +} + +void +Credits (BOOLEAN WithOuttakes) +{ + BYTE fade_buf[1]; + MUSIC_REF hMusic; + Task CredTask; + CREDITS_INPUT_STATE cis; + + hMusic = LoadMusicInstance (CREDITS_MUSIC); + + LockMutex (GraphicsLock); + SetContext (ScreenContext); + SetContextClipRect (NULL_PTR); + SetContextBackGroundColor (BUILD_COLOR (MAKE_RGB15 (0x0, 0x0, 0x0), 0x00)); + ClearDrawable (); + fade_buf[0] = FadeAllToColor; + XFormColorMap ((COLORMAPPTR)fade_buf, 0); + UnlockMutex (GraphicsLock); + + // set the position of outtakes comm + CommWndRect.corner.x = ((SCREEN_WIDTH - SIS_SCREEN_WIDTH) >> 1); + CommWndRect.corner.y = 5; + + // launch credits and wait for the task to start up + CredTask = StartCredits (); + while (CredTask && !CreditsRunning + && !(GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + UpdateInputState (); + SleepThread(ONE_SECOND / 20); + } + + if (WithOuttakes) + { + OutTakesRunning = TRUE; + OutTakes (); + OutTakesRunning = FALSE; + } + + if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) + { + if (hMusic) + PlayMusic (hMusic, TRUE, 1); + + // nothing to do now but wait until credits + // are done or canceled by user + cis.MenuRepeatDelay = 0; + cis.InputFunc = DoCreditsInput; + cis.AllowCancel = !WithOuttakes; + cis.CloseWhenDone = !WithOuttakes; + cis.AllowSpeedChange = TRUE; + SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); + DoInput (&cis, TRUE); + } + + if (CredTask) + ConcludeTask (CredTask); + + FadeMusic (0, ONE_SECOND / 2); + LockMutex (GraphicsLock); SetContext (ScreenContext); fade_buf[0] = FadeAllToBlack; SleepThreadUntil (XFormColorMap ((COLORMAPPTR)fade_buf, ONE_SECOND / 2)); FlushColorXForms (); + UnlockMutex (GraphicsLock); - optSubtitles = oldsubtitles; - sliderDisabled = FALSE; + if (hMusic) + { + StopMusic (); + DestroyMusic (hMusic); + } + FadeMusic (NORMAL_VOLUME, 0); + + FreeCredits (); } - diff --git a/sc2/src/sc2code/credits.h b/sc2/src/sc2code/credits.h index c238f6d66..24fafa935 100644 --- a/sc2/src/sc2code/credits.h +++ b/sc2/src/sc2code/credits.h @@ -17,8 +17,9 @@ #ifndef _CREDITS_H #define _CREDITS_H -void OutTakes (void); -void Credits (void); +#include "libs/compiler.h" + +extern void Credits (BOOLEAN WithOuttakes); #endif /* _CREDITS_H */ diff --git a/sc2/src/sc2code/ifontres.h b/sc2/src/sc2code/ifontres.h index 8c2e227bd..ed63df743 100644 --- a/sc2/src/sc2code/ifontres.h +++ b/sc2/src/sc2code/ifontres.h @@ -4,4 +4,7 @@ #define LANDER_FONT 0x11400303L #define PLAYER_FONT 0x17a00403L +#define PT13AA_FONT 0x24000503L +#define PT17AA_FONT 0x24000603L +#define PT45AA_FONT 0x24000703L diff --git a/sc2/src/sc2code/igfxres.h b/sc2/src/sc2code/igfxres.h index b2505b6a3..64b88de15 100644 --- a/sc2/src/sc2code/igfxres.h +++ b/sc2/src/sc2code/igfxres.h @@ -262,26 +262,7 @@ #define PLANET58_BIG_MASK_PMAP_ANIM 0x20810502L #define PLANET58_MED_MASK_PMAP_ANIM 0x20810602L #define PLANET58_SML_MASK_PMAP_ANIM 0x20810702L -#define CREDIT00_ANIM 0x20c10802L -#define CREDIT01_ANIM 0x20e10902L -#define CREDIT02_ANIM 0x21010a02L -#define CREDIT03_ANIM 0x21210b02L -#define CREDIT04_ANIM 0x21410c02L -#define CREDIT05_ANIM 0x21610d02L -#define CREDIT06_ANIM 0x21810e02L -#define CREDIT07_ANIM 0x21a10f02L -#define CREDIT08_ANIM 0x21c11002L -#define CREDIT09_ANIM 0x21e11102L -#define CREDIT10_ANIM 0x22011202L -#define CREDIT11_ANIM 0x22211302L -#define CREDIT12_ANIM 0x22411402L -#define CREDIT13_ANIM 0x22611502L -#define CREDIT14_ANIM 0x22811602L -#define CREDIT15_ANIM 0x22a11702L -#define CREDIT16_ANIM 0x22c11802L -#define CREDIT17_ANIM 0x22e11902L -#define CREDIT18_ANIM 0x23011a02L -#define CREDIT19_ANIM 0x23211b02L +#define CREDITS_BACK_ANIM 0x20c10802L #define SISSKEL_MASK_PMAP_ANIM 0x23611c02L #define ORBENTER_PMAP_ANIM 0x23811d02L diff --git a/sc2/src/sc2code/istrtab.h b/sc2/src/sc2code/istrtab.h index 039cb3293..bd4fae813 100644 --- a/sc2/src/sc2code/istrtab.h +++ b/sc2/src/sc2code/istrtab.h @@ -99,4 +99,5 @@ #define HANGAR_COLOR_TAB 0x18a06104L #define INTROPRES_STRTAB 0x23c06204L #define FINALPRES_STRTAB 0x23e06304L +#define CREDITS_STRTAB 0x24206404L diff --git a/sc2/src/sc2code/oscill.c b/sc2/src/sc2code/oscill.c index 8bab90292..9c594adce 100644 --- a/sc2/src/sc2code/oscill.c +++ b/sc2/src/sc2code/oscill.c @@ -29,6 +29,7 @@ static int scope_init = 0; static TFB_Image *scope_bg = NULL; static TFB_Image *scope_surf = NULL; static UBYTE scope_data[RADAR_WIDTH - 2]; +BOOLEAN oscillDisabled = FALSE; void InitOscilloscope (DWORD x, DWORD y, DWORD width, DWORD height, FRAME f) @@ -84,6 +85,9 @@ Oscilloscope (DWORD grab_data) { STAMP s; + if (oscillDisabled) + return; + if (!grab_data) return; diff --git a/sc2/src/sc2code/oscill.h b/sc2/src/sc2code/oscill.h index e25073ba2..3b29d609a 100644 --- a/sc2/src/sc2code/oscill.h +++ b/sc2/src/sc2code/oscill.h @@ -21,6 +21,7 @@ #include "libs/gfxlib.h" extern BOOLEAN sliderDisabled; +extern BOOLEAN oscillDisabled; extern void InitOscilloscope (DWORD x, DWORD y, DWORD width, DWORD height, FRAME f); diff --git a/sc2/src/sc2code/respkg.h b/sc2/src/sc2code/respkg.h index e165cc76a..7c13adf9b 100644 --- a/sc2/src/sc2code/respkg.h +++ b/sc2/src/sc2code/respkg.h @@ -279,31 +279,33 @@ enum PLANET57_PACKAGE, PLANET58_PACKAGE, BATTLE_MUSIC_PACKAGE, - CREDIT00_PACKAGE, - CREDIT01_PACKAGE, - CREDIT02_PACKAGE, - CREDIT03_PACKAGE, - CREDIT04_PACKAGE, - CREDIT05_PACKAGE, - CREDIT06_PACKAGE, - CREDIT07_PACKAGE, - CREDIT08_PACKAGE, - CREDIT09_PACKAGE, - CREDIT10_PACKAGE, - CREDIT11_PACKAGE, - CREDIT12_PACKAGE, - CREDIT13_PACKAGE, - CREDIT14_PACKAGE, - CREDIT15_PACKAGE, - CREDIT16_PACKAGE, - CREDIT17_PACKAGE, - CREDIT18_PACKAGE, - CREDIT19_PACKAGE, + CREDITBKGD_PACKAGE, + UNUSED_01_PACKAGE_, + UNUSED_02_PACKAGE_, + UNUSED_03_PACKAGE_, + UNUSED_04_PACKAGE_, + UNUSED_05_PACKAGE_, + UNUSED_06_PACKAGE_, + UNUSED_07_PACKAGE_, + UNUSED_08_PACKAGE_, + UNUSED_09_PACKAGE_, + UNUSED_10_PACKAGE_, + UNUSED_11_PACKAGE_, + UNUSED_12_PACKAGE_, + UNUSED_13_PACKAGE_, + UNUSED_14_PACKAGE_, + UNUSED_15_PACKAGE_, + UNUSED_16_PACKAGE_, + UNUSED_17_PACKAGE_, + UNUSED_18_PACKAGE_, + UNUSED_19_PACKAGE_, CREDIT_MUSIC_PACKAGE, SISSKEL_PACKAGE, ORBENTER_PACKAGE, MENUBKG_PACKAGE, INTRO_PACKAGE, FINAL_PACKAGE, + CREDIT_FONTS_PACKAGE, + CREDITS_PACKAGE, }; diff --git a/sc2/src/sc2code/restart.c b/sc2/src/sc2code/restart.c index 0ff27577d..be45aeb06 100644 --- a/sc2/src/sc2code/restart.c +++ b/sc2/src/sc2code/restart.c @@ -316,8 +316,7 @@ LastActivity = WON_LAST_BATTLE; GLOBAL (CurrentActivity) = WON_LAST_BATTLE; Victory (); InitGameKernel (); - OutTakes (); - Credits (); + Credits (TRUE); FreeGameData ();