diff options
Diffstat (limited to 'sword2/build_display.cpp')
| -rw-r--r-- | sword2/build_display.cpp | 1070 |
1 files changed, 0 insertions, 1070 deletions
diff --git a/sword2/build_display.cpp b/sword2/build_display.cpp deleted file mode 100644 index bc5a31a1f9..0000000000 --- a/sword2/build_display.cpp +++ /dev/null @@ -1,1070 +0,0 @@ -/* Copyright (C) 1994-1998 Revolution Software Ltd. - * Copyright (C) 2003-2006 The ScummVM project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - */ - -// --------------------------------------------------------------------------- -// BUILD_DISPLAY.CPP like the old spr_engi but slightly more aptly named -// --------------------------------------------------------------------------- - -#include "common/stdafx.h" -#include "common/system.h" - -#include "sword2/sword2.h" -#include "sword2/console.h" -#include "sword2/defs.h" -#include "sword2/logic.h" -#include "sword2/maketext.h" -#include "sword2/mouse.h" -#include "sword2/resman.h" -#include "sword2/sound.h" - -namespace Sword2 { - -Screen::Screen(Sword2Engine *vm, int16 width, int16 height) { - _vm = vm; - - _dirtyGrid = _buffer = NULL; - - _vm->_system->initSize(width, height); - - _screenWide = width; - _screenDeep = height; - - _gridWide = width / CELLWIDE; - _gridDeep = height / CELLDEEP; - - if ((width % CELLWIDE) || (height % CELLDEEP)) - error("Bad cell size"); - - _dirtyGrid = (byte *)calloc(_gridWide, _gridDeep); - if (!_dirtyGrid) - error("Could not initialise dirty grid"); - - _buffer = (byte *)malloc(width * height); - if (!_buffer) - error("Could not initialise display"); - - for (int i = 0; i < ARRAYSIZE(_blockSurfaces); i++) - _blockSurfaces[i] = NULL; - - _lightMask = NULL; - _needFullRedraw = false; - - memset(&_thisScreen, 0, sizeof(_thisScreen)); - - _fps = 0; - _frameCount = 0; - _cycleTime = 0; - - _lastPaletteRes = 0; - - _scrollFraction = 16; - - _largestLayerArea = 0; - _largestSpriteArea = 0; - - strcpy(_largestLayerInfo, "largest layer: none registered"); - strcpy(_largestSpriteInfo, "largest sprite: none registered"); - - _fadeStatus = RDFADE_NONE; - _renderAverageTime = 60; - - _layer = 0; -} - -Screen::~Screen() { - free(_buffer); - free(_dirtyGrid); - closeBackgroundLayer(); - free(_lightMask); -} - -void Screen::buildDisplay() { - if (_thisScreen.new_palette) { - // start the layer palette fading up - startNewPalette(); - - // should be reset to zero at start of each screen change - _largestLayerArea = 0; - _largestSpriteArea = 0; - } - - // Does this ever happen? - if (!_thisScreen.background_layer_id) - return; - - // there is a valid screen to run - - setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y); - _vm->_mouse->animateMouse(); - startRenderCycle(); - - byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id); - - MultiScreenHeader screenLayerTable; - - screenLayerTable.read(file + ResHeader::size()); - - // Render at least one frame, but if the screen is scrolling, and if - // there is time left, we will render extra frames to smooth out the - // scrolling. - - do { - // first background parallax + related anims - if (screenLayerTable.bg_parallax[0]) { - renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0); - drawBackPar0Frames(); - } - - // second background parallax + related anims - if (screenLayerTable.bg_parallax[1]) { - renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1); - drawBackPar1Frames(); - } - - // normal backround layer (just the one!) - renderParallax(_vm->fetchBackgroundLayer(file), 2); - - // sprites & layers - drawBackFrames(); // background sprites - drawSortFrames(file); // sorted sprites & layers - drawForeFrames(); // foreground sprites - - // first foreground parallax + related anims - - if (screenLayerTable.fg_parallax[0]) { - renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3); - drawForePar0Frames(); - } - - // second foreground parallax + related anims - - if (screenLayerTable.fg_parallax[1]) { - renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4); - drawForePar1Frames(); - } - - _vm->_debugger->drawDebugGraphics(); - _vm->_fontRenderer->printTextBlocs(); - _vm->_mouse->processMenu(); - - updateDisplay(); - - _frameCount++; - if (_vm->getMillis() > _cycleTime) { - _fps = _frameCount; - _frameCount = 0; - _cycleTime = _vm->getMillis() + 1000; - } - } while (!endRenderCycle()); - - _vm->_resman->closeResource(_thisScreen.background_layer_id); -} - -/** - * Fades down and displays a message on the screen. - * @param text The message - * @param time The number of seconds to display the message, or 0 to display it - * until the user clicks the mouse or presses a key. - */ - -void Screen::displayMsg(byte *text, int time) { - byte pal[256 * 4]; - byte oldPal[256 * 4]; - - debug(2, "DisplayMsg: %s", text); - - if (getFadeStatus() != RDFADE_BLACK) { - fadeDown(); - waitForFade(); - } - - _vm->_mouse->setMouse(0); - _vm->_mouse->setLuggage(0); - _vm->_mouse->closeMenuImmediately(); - - clearScene(); - - byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId); - - FrameHeader frame; - - frame.read(text_spr); - - SpriteInfo spriteInfo; - - spriteInfo.x = _screenWide / 2 - frame.width / 2; - if (!time) - spriteInfo.y = _screenDeep / 2 - frame.height / 2 - MENUDEEP; - else - spriteInfo.y = 400 - frame.height; - spriteInfo.w = frame.width; - spriteInfo.h = frame.height; - spriteInfo.scale = 0; - spriteInfo.scaledWidth = 0; - spriteInfo.scaledHeight = 0; - spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS; - spriteInfo.blend = 0; - spriteInfo.data = text_spr + FrameHeader::size(); - spriteInfo.colourTable = 0; - - uint32 rv = drawSprite(&spriteInfo); - if (rv) - error("Driver Error %.8x (in DisplayMsg)", rv); - - memcpy(oldPal, _palette, sizeof(oldPal)); - memset(pal, 0, sizeof(pal)); - - pal[187 * 4 + 0] = 255; - pal[187 * 4 + 1] = 255; - pal[187 * 4 + 2] = 255; - - setPalette(0, 256, pal, RDPAL_FADE); - fadeUp(); - free(text_spr); - waitForFade(); - - if (time > 0) { - uint32 targetTime = _vm->getMillis() + (time * 1000); - _vm->sleepUntil(targetTime); - } else { - while (!_vm->_quit) { - MouseEvent *me = _vm->mouseEvent(); - if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN))) - break; - - if (_vm->keyboardEvent()) - break; - - updateDisplay(); - _vm->_system->delayMillis(50); - } - } - - fadeDown(); - waitForFade(); - clearScene(); - setPalette(0, 256, oldPal, RDPAL_FADE); - fadeUp(); -} - -void Screen::drawBackPar0Frames() { - // frame attached to 1st background parallax - for (uint i = 0; i < _curBgp0; i++) - processImage(&_bgp0List[i]); -} - -void Screen::drawBackPar1Frames() { - // frame attached to 2nd background parallax - for (uint i = 0; i < _curBgp1; i++) - processImage(&_bgp1List[i]); -} - -void Screen::drawBackFrames() { - // background sprite, fixed to main background - for (uint i = 0; i < _curBack; i++) - processImage(&_backList[i]); -} - -void Screen::drawSortFrames(byte *file) { - uint i, j; - - // Sort the sort list. Used to be a separate function, but it was only - // called once, right before calling drawSortFrames(). - - if (_curSort > 1) { - for (i = 0; i < _curSort - 1; i++) { - for (j = 0; j < _curSort - 1; j++) { - if (_sortList[_sortOrder[j]].sort_y > _sortList[_sortOrder[j + 1]].sort_y) { - SWAP(_sortOrder[j], _sortOrder[j + 1]); - } - } - } - } - - // Draw the sorted frames - layers, shrinkers & normal flat sprites - - for (i = 0; i < _curSort; i++) { - if (_sortList[_sortOrder[i]].layer_number) { - // it's a layer - minus 1 for true layer number - // we need to know from the BuildUnit because the - // layers will have been sorted in random order - processLayer(file, _sortList[_sortOrder[i]].layer_number - 1); - } else { - // it's a sprite - processImage(&_sortList[_sortOrder[i]]); - } - } -} - -void Screen::drawForeFrames() { - // foreground sprite, fixed to main background - for (uint i = 0; i < _curFore; i++) - processImage(&_foreList[i]); -} - -void Screen::drawForePar0Frames() { - // frame attached to 1st foreground parallax - for (uint i = 0; i < _curFgp0; i++) - processImage(&_fgp0List[i]); -} - -void Screen::drawForePar1Frames() { - // frame attached to 2nd foreground parallax - for (uint i = 0; i < _curFgp1; i++) - processImage(&_fgp1List[i]); -} - -void Screen::processLayer(byte *file, uint32 layer_number) { - LayerHeader layer_head; - - layer_head.read(_vm->fetchLayerHeader(file, layer_number)); - - SpriteInfo spriteInfo; - - spriteInfo.x = layer_head.x; - spriteInfo.y = layer_head.y; - spriteInfo.w = layer_head.width; - spriteInfo.scale = 0; - spriteInfo.scaledWidth = 0; - spriteInfo.scaledHeight = 0; - spriteInfo.h = layer_head.height; - spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST; - spriteInfo.blend = 0; - spriteInfo.data = file + ResHeader::size() + layer_head.offset; - spriteInfo.colourTable = 0; - - // check for largest layer for debug info - - uint32 current_layer_area = layer_head.width * layer_head.height; - - if (current_layer_area > _largestLayerArea) { - byte buf[NAME_LEN]; - - _largestLayerArea = current_layer_area; - sprintf(_largestLayerInfo, - "largest layer: %s layer(%d) is %dx%d", - _vm->_resman->fetchName(_thisScreen.background_layer_id, buf), - layer_number, layer_head.width, layer_head.height); - } - - uint32 rv = drawSprite(&spriteInfo); - if (rv) - error("Driver Error %.8x in processLayer(%d)", rv, layer_number); -} - -void Screen::processImage(BuildUnit *build_unit) { - byte *file = _vm->_resman->openResource(build_unit->anim_resource); - byte *colTablePtr = NULL; - - byte *frame = _vm->fetchFrameHeader(file, build_unit->anim_pc); - - AnimHeader anim_head; - CdtEntry cdt_entry; - FrameHeader frame_head; - - anim_head.read(_vm->fetchAnimHeader(file)); - cdt_entry.read(_vm->fetchCdtEntry(file, build_unit->anim_pc)); - frame_head.read(frame); - - // so that 0-colour is transparent - uint32 spriteType = RDSPR_TRANS; - - if (anim_head.blend) - spriteType |= RDSPR_BLEND; - - // if the frame is to be flipped (only really applicable to frames - // using offsets) - if (cdt_entry.frameType & FRAME_FLIPPED) - spriteType |= RDSPR_FLIP; - - if (cdt_entry.frameType & FRAME_256_FAST) { - // scaling, shading & blending don't work with RLE256FAST - // but the same compression can be decompressed using the - // RLE256 routines! - - // NOTE: If this restriction refers to drawSprite(), I don't - // think we have it any more. But I'm not sure. - - if (build_unit->scale || anim_head.blend || build_unit->shadingFlag) - spriteType |= RDSPR_RLE256; - else - spriteType |= RDSPR_RLE256FAST; - } else { - switch (anim_head.runTimeComp) { - case NONE: - spriteType |= RDSPR_NOCOMPRESSION; - break; - case RLE256: - spriteType |= RDSPR_RLE256; - break; - case RLE16: - spriteType |= RDSPR_RLE16; - // points to just after last cdt_entry, ie. - // start of colour table - colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size() + anim_head.noAnimFrames * CdtEntry::size(); - break; - } - } - - // if we want this frame to be affected by the shading mask, - // add the status bit - if (build_unit->shadingFlag) - spriteType |= RDSPR_SHADOW; - - SpriteInfo spriteInfo; - - spriteInfo.x = build_unit->x; - spriteInfo.y = build_unit->y; - spriteInfo.w = frame_head.width; - spriteInfo.h = frame_head.height; - spriteInfo.scale = build_unit->scale; - spriteInfo.scaledWidth = build_unit->scaled_width; - spriteInfo.scaledHeight = build_unit->scaled_height; - spriteInfo.type = spriteType; - spriteInfo.blend = anim_head.blend; - // points to just after frame header, ie. start of sprite data - spriteInfo.data = frame + FrameHeader::size(); - spriteInfo.colourTable = colTablePtr; - - // check for largest layer for debug info - uint32 current_sprite_area = frame_head.width * frame_head.height; - - if (current_sprite_area > _largestSpriteArea) { - byte buf[NAME_LEN]; - - _largestSpriteArea = current_sprite_area; - sprintf(_largestSpriteInfo, - "largest sprite: %s frame(%d) is %dx%d", - _vm->_resman->fetchName(build_unit->anim_resource, buf), - build_unit->anim_pc, - frame_head.width, - frame_head.height); - } - - if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) { // see anims.cpp - // bring the anim into the visible screen - // but leave extra pixel at edge for box - if (spriteInfo.x + spriteInfo.scaledWidth >= 639) - spriteInfo.x = 639 - spriteInfo.scaledWidth; - - if (spriteInfo.y + spriteInfo.scaledHeight >= 399) - spriteInfo.y = 399 - spriteInfo.scaledHeight; - - if (spriteInfo.x < 1) - spriteInfo.x = 1; - - if (spriteInfo.y < 1) - spriteInfo.y = 1; - - // create box to surround sprite - just outside sprite box - _vm->_debugger->_rectX1 = spriteInfo.x - 1; - _vm->_debugger->_rectY1 = spriteInfo.y - 1; - _vm->_debugger->_rectX2 = spriteInfo.x + spriteInfo.scaledWidth; - _vm->_debugger->_rectY2 = spriteInfo.y + spriteInfo.scaledHeight; - } - - uint32 rv = drawSprite(&spriteInfo); - if (rv) { - byte buf[NAME_LEN]; - - error("Driver Error %.8x with sprite %s (%d) in processImage", - rv, - _vm->_resman->fetchName(build_unit->anim_resource, buf), - build_unit->anim_resource); - } - - // release the anim resource - _vm->_resman->closeResource(build_unit->anim_resource); -} - -void Screen::resetRenderLists() { - // reset the sort lists - do this before a logic loop - // takes into account the fact that the start of the list is pre-built - // with the special sortable layers - - _curBgp0 = 0; - _curBgp1 = 0; - _curBack = 0; - // beginning of sort list is setup with the special sort layers - _curSort = _thisScreen.number_of_layers; - _curFore = 0; - _curFgp0 = 0; - _curFgp1 = 0; - - if (_curSort) { - // there are some layers - so rebuild the sort order list - for (uint i = 0; i < _curSort; i++) - _sortOrder[i] = i; - } -} - -void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit) { - ObjectGraphic obGraph(ob_graph); - ObjectMega obMega(ob_mega); - - assert(obGraph.getAnimResource()); - - byte *file = _vm->_resman->openResource(obGraph.getAnimResource()); - - AnimHeader anim_head; - CdtEntry cdt_entry; - FrameHeader frame_head; - - anim_head.read(_vm->fetchAnimHeader(file)); - cdt_entry.read(_vm->fetchCdtEntry(file, obGraph.getAnimPc())); - frame_head.read(_vm->fetchFrameHeader(file, obGraph.getAnimPc())); - - // update player graphic details for on-screen debug info - if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) { - _vm->_debugger->_graphType = obGraph.getType(); - _vm->_debugger->_graphAnimRes = obGraph.getAnimResource(); - // counting 1st frame as 'frame 1' - _vm->_debugger->_graphAnimPc = obGraph.getAnimPc() + 1; - _vm->_debugger->_graphNoFrames = anim_head.noAnimFrames; - } - - // fill in the BuildUnit structure for this frame - - build_unit->anim_resource = obGraph.getAnimResource(); - build_unit->anim_pc = obGraph.getAnimPc(); - build_unit->layer_number = 0; - - // Affected by shading mask? - if (obGraph.getType() & SHADED_SPRITE) - build_unit->shadingFlag = true; - else - build_unit->shadingFlag = false; - - // Check if this frame has offsets ie. this is a scalable mega frame - - int scale = 0; - - if (cdt_entry.frameType & FRAME_OFFSET) { - scale = obMega.calcScale(); - - // calc final render coordinates (top-left of sprite), based - // on feet coords & scaled offsets - - // add scaled offsets to feet coords - build_unit->x = obMega.getFeetX() + (cdt_entry.x * scale) / 256; - build_unit->y = obMega.getFeetY() + (cdt_entry.y * scale) / 256; - - // Work out new width and height. Always divide by 256 after - // everything else, to maintain accurary - build_unit->scaled_width = ((scale * frame_head.width) / 256); - build_unit->scaled_height = ((scale * frame_head.height) / 256); - } else { - // It's a non-scaling anim. Get render coords for sprite, from cdt - build_unit->x = cdt_entry.x; - build_unit->y = cdt_entry.y; - - // Get width and height - build_unit->scaled_width = frame_head.width; - build_unit->scaled_height = frame_head.height; - } - - // either 0 or required scale, depending on whether 'scale' computed - build_unit->scale = scale; - - // calc the bottom y-coord for sorting purposes - build_unit->sort_y = build_unit->y + build_unit->scaled_height - 1; - - if (ob_mouse) { - // passed a mouse structure, so add to the _mouseList - _vm->_mouse->registerMouse(ob_mouse, build_unit); - - } - - _vm->_resman->closeResource(obGraph.getAnimResource()); -} - -void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega) { - ObjectGraphic obGraph(ob_graph); - - // check low word for sprite type - switch (obGraph.getType() & 0x0000ffff) { - case BGP0_SPRITE: - assert(_curBgp0 < MAX_bgp0_sprites); - registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp0List[_curBgp0]); - _curBgp0++; - break; - case BGP1_SPRITE: - assert(_curBgp1 < MAX_bgp1_sprites); - registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp1List[_curBgp1]); - _curBgp1++; - break; - case BACK_SPRITE: - assert(_curBack < MAX_back_sprites); - registerFrame(ob_mouse, ob_graph, ob_mega, &_backList[_curBack]); - _curBack++; - break; - case SORT_SPRITE: - assert(_curSort < MAX_sort_sprites); - _sortOrder[_curSort] = _curSort; - registerFrame(ob_mouse, ob_graph, ob_mega, &_sortList[_curSort]); - _curSort++; - break; - case FORE_SPRITE: - assert(_curFore < MAX_fore_sprites); - registerFrame(ob_mouse, ob_graph, ob_mega, &_foreList[_curFore]); - _curFore++; - break; - case FGP0_SPRITE: - assert(_curFgp0 < MAX_fgp0_sprites); - registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp0List[_curFgp0]); - _curFgp0++; - break; - case FGP1_SPRITE: - assert(_curFgp1 < MAX_fgp1_sprites); - registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp1List[_curFgp1]); - _curFgp1++; - break; - default: - // NO_SPRITE no registering! - break; - } -} - -// 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; - - CreditsLine() { - str = NULL; - sprite = NULL; - }; - - ~CreditsLine() { - free(str); - free(sprite); - str = NULL; - sprite = NULL; - } -}; - -#define CREDITS_FONT_HEIGHT 25 -#define CREDITS_LINE_SPACING 20 - -void Screen::rollCredits() { - uint32 loopingMusicId = _vm->_sound->getLoopingMusicId(); - - // Prepare for the credits by fading down, stoping the music, etc. - - _vm->_mouse->setMouse(0); - - _vm->_sound->muteFx(true); - _vm->_sound->muteSpeech(true); - - waitForFade(); - fadeDown(); - 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. - // The German version also contains character code 9 for no - // apparent reason. We ignore them. - // - // 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; - Common::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; - } - - setPalette(0, 256, palette, RDPAL_INSTANT); - - // Read the credits text - - Common::Array<CreditsLine *> creditsLines; - - int lineCount = 0; - int lineTop = 400; - int paragraphStart = 0; - bool hasCenterMark = false; - - if (!f.open("credits.clu")) { - warning("Can't find credits.clu"); - return; - } - - while (1) { - 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; - } - - // The German credits contains character code 9. We don't want - // the credits to show the 'dud' symbol, so we replace them - // with spaces. - - for (char *ptr = line; *ptr; ptr++) { - if (*ptr < 32) - *ptr = 32; - } - - char *center_mark = strchr(line, '^'); - - if (center_mark) { - // The current paragraph has at least one center mark. - hasCenterMark = true; - - if (center_mark != line) { - creditsLines.push_back(new CreditsLine); - - // 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++; - *center_mark = '^'; - } - - line = center_mark; - } - - creditsLines.push_back(new CreditsLine); - - 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. - - _vm->_sound->streamCompMusic(309, false); - - clearScene(); - 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) { - clearScene(); - - for (i = startLine; i < lineCount; i++) { - if (!creditsLines[i]) - continue; - - // Free any sprites that have scrolled off the screen - - if (creditsLines[i]->top + creditsLines[i]->height < scrollPos) { - debug(2, "Freeing line %d: '%s'", i, creditsLines[i]->str); - - delete creditsLines[i]; - creditsLines[i] = NULL; - - startLine = i + 1; - } else if (creditsLines[i]->top < scrollPos + 400) { - if (!creditsLines[i]->sprite) { - debug(2, "Creating line %d: '%s'", i, creditsLines[i]->str); - creditsLines[i]->sprite = _vm->_fontRenderer->makeTextSprite((byte *)creditsLines[i]->str, 600, 14, _vm->_speechFontId, 0); - } - - FrameHeader frame; - - frame.read(creditsLines[i]->sprite); - - spriteInfo.y = creditsLines[i]->top - scrollPos; - spriteInfo.w = frame.width; - spriteInfo.h = frame.height; - spriteInfo.data = creditsLines[i]->sprite + FrameHeader::size(); - - 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) - drawSprite(&spriteInfo); - } else - break; - } - - updateDisplay(); - - KeyboardEvent *ke = _vm->keyboardEvent(); - - if (ke && ke->keycode == 27) { - if (!abortCredits) { - abortCredits = true; - fadeDown(); - } - } - - if (abortCredits && 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++) { - delete creditsLines[i]; - } - - free(logoData); - - if (!abortCredits) { - fadeDown(); - - // The music should either have stopped or be about to stop, so - // wait for it to really happen. - - while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) { - updateDisplay(false); - _vm->_system->delayMillis(100); - } - } - - if (_vm->_quit) - return; - - waitForFade(); - - _vm->_sound->muteFx(false); - _vm->_sound->muteSpeech(false); - - if (loopingMusicId) - _vm->_sound->streamCompMusic(loopingMusicId, true); - else - _vm->_sound->stopMusic(false); - - if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing()) - _vm->_mouse->setMouse(NORMAL_MOUSE_ID); - - if (_vm->_logic->readVar(DEAD)) - _vm->_mouse->buildSystemMenu(); -} - -// This image used to be shown by CacheNewCluster() while copying a data file -// from the CD to the hard disk. ScummVM doesn't do that, so the image is never -// shown. It'd be nice if we could do something useful with it some day... - -void Screen::splashScreen() { - byte *bgfile = _vm->_resman->openResource(2950); - - initialiseBackgroundLayer(NULL); - initialiseBackgroundLayer(NULL); - initialiseBackgroundLayer(_vm->fetchBackgroundLayer(bgfile)); - initialiseBackgroundLayer(NULL); - initialiseBackgroundLayer(NULL); - - setPalette(0, 256, _vm->fetchPalette(bgfile), RDPAL_FADE); - renderParallax(_vm->fetchBackgroundLayer(bgfile), 2); - - closeBackgroundLayer(); - - byte *loadingBar = _vm->_resman->openResource(2951); - byte *frame = _vm->fetchFrameHeader(loadingBar, 0); - - AnimHeader animHead; - CdtEntry cdt; - FrameHeader frame_head; - - animHead.read(_vm->fetchAnimHeader(loadingBar)); - cdt.read(_vm->fetchCdtEntry(loadingBar, 0)); - frame_head.read(_vm->fetchFrameHeader(loadingBar, 0)); - - SpriteInfo barSprite; - - barSprite.x = cdt.x; - barSprite.y = cdt.y; - barSprite.w = frame_head.width; - barSprite.h = frame_head.height; - barSprite.scale = 0; - barSprite.scaledWidth = 0; - barSprite.scaledHeight = 0; - barSprite.type = RDSPR_RLE256FAST | RDSPR_TRANS; - barSprite.blend = 0; - barSprite.colourTable = 0; - barSprite.data = frame + FrameHeader::size(); - - drawSprite(&barSprite); - - fadeUp(); - waitForFade(); - - for (int i = 0; i < animHead.noAnimFrames; i++) { - frame = _vm->fetchFrameHeader(loadingBar, i); - barSprite.data = frame + FrameHeader::size(); - drawSprite(&barSprite); - updateDisplay(); - _vm->_system->delayMillis(30); - } - - _vm->_resman->closeResource(2951); - - fadeDown(); - waitForFade(); -} - -} // End of namespace Sword2 |
