aboutsummaryrefslogtreecommitdiff
path: root/sword2/function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sword2/function.cpp')
-rw-r--r--sword2/function.cpp365
1 files changed, 1 insertions, 364 deletions
diff --git a/sword2/function.cpp b/sword2/function.cpp
index 37affd9923..6508cee08a 100644
--- a/sword2/function.cpp
+++ b/sword2/function.cpp
@@ -2770,37 +2770,7 @@ int32 Logic::fnCheckMusicPlaying(int32 *params) {
return IR_CONT;
}
-// FIXME:
-//
-// The original credits used a different font. I think it's stored in the
-// font.clu file, but I don't know how to interpret it.
-//
-// The original used the entire screen. This version cuts off the top and
-// bottom of the screen, because that's where the menus would usually be.
-//
-// The original had some sort of smoke effect at the bottom of the screen.
-
-enum {
- LINE_LEFT,
- LINE_CENTER,
- LINE_RIGHT
-};
-
-struct CreditsLine {
- char *str;
- byte type;
- int top;
- int height;
- byte *sprite;
-};
-
-#define CREDITS_FONT_HEIGHT 25
-#define CREDITS_LINE_SPACING 20
-
int32 Logic::fnPlayCredits(int32 *params) {
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();
-
// This function just quits the game if this is the playable demo, ie.
// credits are NOT played in the demo any more!
@@ -2811,340 +2781,7 @@ int32 Logic::fnPlayCredits(int32 *params) {
return IR_STOP;
}
- // Prepare for the credits by fading down, stoping the music, etc.
-
- _vm->_mouse->setMouse(0);
-
- _vm->_sound->muteFx(true);
- _vm->_sound->muteSpeech(true);
-
- _vm->_screen->waitForFade();
- _vm->_screen->fadeDown();
- _vm->_screen->waitForFade();
-
- _vm->_mouse->closeMenuImmediately();
-
- // There are three files which I believe are involved in showing the
- // credits:
- //
- // credits.bmp - The "Smacker" logo, stored as follows:
- //
- // width 2 bytes, little endian
- // height 2 bytes, little endian
- // palette 3 * 256 bytes
- // data width * height bytes
- //
- // Note that the maximum colour component in the palette is 0x3F.
- // This is the same resolution as the _paletteMatch table. I doubt
- // that this is a coincidence, but let's use the image palette
- // directly anyway, just to be safe.
- //
- // credits.clu - The credits text
- //
- // This is simply a text file with CRLF line endings.
- // '^' is not shown, but used to mark the center of the line.
- // '@' is used as a placeholder for the "Smacker" logo. At least
- // when it appears alone.
- // Remaining lines are centered.
- //
- // fonts.clu - The credits font?
- //
- // FIXME: At this time I don't know how to interpret fonts.clu. For
- // now, let's just the standard speech font instead.
-
- SpriteInfo spriteInfo;
- File f;
- int i;
-
- // Read the "Smacker" logo
-
- uint16 logoWidth = 0;
- uint16 logoHeight = 0;
- byte *logoData = NULL;
- byte palette[256 * 4];
-
- if (f.open("credits.bmp")) {
- logoWidth = f.readUint16LE();
- logoHeight = f.readUint16LE();
-
- for (i = 0; i < 256; i++) {
- palette[i * 4 + 0] = f.readByte() << 2;
- palette[i * 4 + 1] = f.readByte() << 2;
- palette[i * 4 + 2] = f.readByte() << 2;
- palette[i * 4 + 3] = 0;
- }
-
- logoData = (byte *) malloc(logoWidth * logoHeight);
-
- f.read(logoData, logoWidth * logoHeight);
- f.close();
- } else {
- warning("Can't find credits.bmp");
- memset(palette, 0, sizeof(palette));
- palette[14 * 4 + 0] = 252;
- palette[14 * 4 + 1] = 252;
- palette[14 * 4 + 2] = 252;
- palette[14 * 4 + 3] = 0;
- }
-
- _vm->_screen->setPalette(0, 256, palette, RDPAL_INSTANT);
-
- // Read the credits text
-
- // This should be plenty
- CreditsLine creditsLines[350];
-
- for (i = 0; i < ARRAYSIZE(creditsLines); i++) {
- creditsLines[i].str = NULL;
- creditsLines[i].sprite = NULL;
- }
-
- if (!f.open("credits.clu")) {
- warning("Can't find credits.clu");
- return IR_CONT;
- }
-
- int lineTop = 400;
- int lineCount = 0;
- int paragraphStart = 0;
- bool hasCenterMark = false;
-
- while (1) {
- if (lineCount >= ARRAYSIZE(creditsLines)) {
- warning("Too many credits lines");
- break;
- }
-
- char buffer[80];
- char *line = f.readLine(buffer, sizeof(buffer));
-
- if (!line || *line == 0) {
- if (!hasCenterMark) {
- for (i = paragraphStart; i < lineCount; i++)
- creditsLines[i].type = LINE_CENTER;
- }
- paragraphStart = lineCount;
- hasCenterMark = false;
- if (paragraphStart == lineCount)
- lineTop += CREDITS_LINE_SPACING;
-
- if (!line)
- break;
-
- continue;
- }
-
- char *center_mark = strchr(line, '^');
-
- if (center_mark) {
- // The current paragraph has at least one center mark.
- hasCenterMark = true;
-
- if (center_mark != line) {
- // The center mark is somewhere inside the
- // line. Split it into left and right side.
- *center_mark = 0;
-
- creditsLines[lineCount].top = lineTop;
- creditsLines[lineCount].height = CREDITS_FONT_HEIGHT;
- creditsLines[lineCount].type = LINE_LEFT;
- creditsLines[lineCount].str = strdup(line);
-
- lineCount++;
-
- if (lineCount >= ARRAYSIZE(creditsLines)) {
- warning("Too many credits lines");
- break;
- }
-
- *center_mark = '^';
- }
-
- line = center_mark;
- }
-
- creditsLines[lineCount].top = lineTop;
-
- if (*line == '^') {
- creditsLines[lineCount].type = LINE_RIGHT;
- line++;
- } else
- creditsLines[lineCount].type = LINE_LEFT;
-
- if (strcmp(line, "@") == 0) {
- creditsLines[lineCount].height = logoHeight;
- lineTop += logoHeight;
- } else {
- creditsLines[lineCount].height = CREDITS_FONT_HEIGHT;
- lineTop += CREDITS_LINE_SPACING;
- }
-
- creditsLines[lineCount].str = strdup(line);
- lineCount++;
- }
-
- f.close();
-
- // We could easily add some ScummVM stuff to the credits, if we wanted
- // to. On the other hand, anyone with the attention span to actually
- // read all the credits probably already knows. :-)
-
- // Start the music and roll the credits
-
- // The credits music (which can also be heard briefly in the "carib"
- // cutscene) is played once.
-
- int32 pars[2];
-
- pars[0] = 309;
- pars[1] = FX_SPOT;
- fnPlayMusic(pars);
-
- _vm->_screen->clearScene();
- _vm->_screen->fadeUp(0);
-
- spriteInfo.scale = 0;
- spriteInfo.scaledWidth = 0;
- spriteInfo.scaledHeight = 0;
- spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
- spriteInfo.blend = 0;
-
- int startLine = 0;
- int scrollPos = 0;
-
- bool abortCredits = false;
-
- int scrollSteps = lineTop + CREDITS_FONT_HEIGHT;
- uint32 musicStart = _vm->getMillis();
-
- // Ideally the music should last just a tiny bit longer than the
- // credits. Note that musicTimeRemaining() will return 0 if the music
- // is muted, so we need a sensible fallback for that case.
-
- uint32 musicLength = MAX((int32) (1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32) scrollSteps);
-
- while (scrollPos < scrollSteps && !_vm->_quit) {
- bool foundStartLine = false;
-
- _vm->_screen->clearScene();
-
- for (i = startLine; i < lineCount; i++) {
- // Free any sprites that have scrolled off the screen
-
- if (creditsLines[i].top + creditsLines[i].height < scrollPos) {
- if (creditsLines[i].sprite) {
- free(creditsLines[i].sprite);
- creditsLines[i].sprite = NULL;
- debug(2, "Freeing sprite '%s'", creditsLines[i].str);
- }
- if (creditsLines[i].str) {
- free(creditsLines[i].str);
- creditsLines[i].str = NULL;
- }
- } else if (creditsLines[i].top < scrollPos + 400) {
- if (!foundStartLine) {
- startLine = i;
- foundStartLine = true;
- }
-
- if (!creditsLines[i].sprite) {
- debug(2, "Creating sprite '%s'", creditsLines[i].str);
- creditsLines[i].sprite = _vm->_fontRenderer->makeTextSprite((byte *) creditsLines[i].str, 600, 14, _vm->_speechFontId, 0);
- }
-
- FrameHeader *frame = (FrameHeader *) creditsLines[i].sprite;
-
- spriteInfo.y = creditsLines[i].top - scrollPos;
- spriteInfo.w = frame->width;
- spriteInfo.h = frame->height;
- spriteInfo.data = creditsLines[i].sprite + sizeof(FrameHeader);
-
- switch (creditsLines[i].type) {
- case LINE_LEFT:
- spriteInfo.x = RENDERWIDE / 2 - 5 - frame->width;
- break;
- case LINE_RIGHT:
- spriteInfo.x = RENDERWIDE / 2 + 5;
- break;
- case LINE_CENTER:
- if (strcmp(creditsLines[i].str, "@") == 0) {
- spriteInfo.data = logoData;
- spriteInfo.x = (RENDERWIDE - logoWidth) / 2;
- spriteInfo.w = logoWidth;
- spriteInfo.h = logoHeight;
- } else
- spriteInfo.x = (RENDERWIDE - frame->width) / 2;
- break;
- }
-
- if (spriteInfo.data)
- _vm->_screen->drawSprite(&spriteInfo);
- } else
- break;
- }
-
- _vm->_screen->updateDisplay();
-
- KeyboardEvent *ke = _vm->keyboardEvent();
-
- if (ke && ke->keycode == 27) {
- if (!abortCredits) {
- abortCredits = true;
- _vm->_screen->fadeDown();
- }
- }
-
- if (abortCredits && _vm->_screen->getFadeStatus() == RDFADE_BLACK)
- break;
-
- _vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps);
- scrollPos++;
- }
-
- // We're done. Clean up and try to put everything back where it was
- // before the credits.
-
- for (i = 0; i < lineCount; i++) {
- if (creditsLines[i].str)
- free(creditsLines[i].str);
- if (creditsLines[i].sprite)
- free(creditsLines[i].sprite);
- }
-
- if (logoData)
- free(logoData);
-
- if (!abortCredits) {
- // The music should either have stopped or be about to stop, so
- // wait for it to really happen.
-
- while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) {
- _vm->_screen->updateDisplay(false);
- _vm->_system->delayMillis(100);
- }
- }
-
- if (_vm->_quit)
- return IR_CONT;
-
- _vm->_sound->muteFx(false);
- _vm->_sound->muteSpeech(false);
-
- if (loopingMusicId) {
- pars[0] = loopingMusicId;
- pars[1] = FX_LOOP;
- fnPlayMusic(pars);
- } else
- fnStopMusic(NULL);
-
- screenInfo->new_palette = 99;
-
- if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing())
- _vm->_mouse->setMouse(NORMAL_MOUSE_ID);
-
- if (_scriptVars[DEAD])
- _vm->_mouse->buildSystemMenu();
-
+ _vm->_screen->rollCredits();
return IR_CONT;
}