diff options
Diffstat (limited to 'sword2/function.cpp')
| -rw-r--r-- | sword2/function.cpp | 365 |
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; } |
