[Scummvm-cvs-logs] SF.net SVN: scummvm: [20652] scummvm/trunk/engines/sword2
eriktorbjorn at users.sourceforge.net
eriktorbjorn at users.sourceforge.net
Sun Feb 12 11:40:01 CET 2006
Revision: 20652
Author: eriktorbjorn
Date: 2006-02-12 11:38:26 -0800 (Sun, 12 Feb 2006)
ViewCVS: http://svn.sourceforge.net/scummvm?rev=20652&view=rev
Log Message:
-----------
Oops. Forgot to tell SVN to actually *move* the files. I'll get the hang of it
eventually.
Added Paths:
-----------
scummvm/trunk/engines/sword2/saveload.cpp
scummvm/trunk/engines/sword2/saveload.h
scummvm/trunk/engines/sword2/screen.cpp
scummvm/trunk/engines/sword2/screen.h
Removed Paths:
-------------
scummvm/trunk/engines/sword2/build_display.cpp
scummvm/trunk/engines/sword2/build_display.h
scummvm/trunk/engines/sword2/save_rest.cpp
scummvm/trunk/engines/sword2/save_rest.h
Deleted: scummvm/trunk/engines/sword2/build_display.cpp
===================================================================
--- scummvm/trunk/engines/sword2/build_display.cpp 2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/build_display.cpp 2006-02-12 19:38:26 UTC (rev 20652)
@@ -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
Deleted: scummvm/trunk/engines/sword2/build_display.h
===================================================================
--- scummvm/trunk/engines/sword2/build_display.h 2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/build_display.h 2006-02-12 19:38:26 UTC (rev 20652)
@@ -1,441 +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$
- */
-
-#ifndef _BUILD_DISPLAY
-#define _BUILD_DISPLAY
-
-#include "common/rect.h"
-#include "common/stream.h"
-
-#define MAX_bgp0_sprites 6
-#define MAX_bgp1_sprites 6
-#define MAX_back_sprites 30
-#define MAX_sort_sprites 30
-#define MAX_fore_sprites 30
-#define MAX_fgp0_sprites 6
-#define MAX_fgp1_sprites 6
-
-#define PALTABLESIZE (64 * 64 * 64)
-
-#define BLOCKWIDTH 64
-#define BLOCKHEIGHT 64
-#define MAXLAYERS 5
-
-#define MENUDEEP 40
-#define RENDERWIDE 640
-#define RENDERDEEP (480 - (MENUDEEP * 2))
-
-// Maximum scaled size of a sprite
-#define SCALE_MAXWIDTH 512
-#define SCALE_MAXHEIGHT 512
-
-// Dirty grid cell size
-#define CELLWIDE 10
-#define CELLDEEP 20
-
-namespace Sword2 {
-
-class Sword2Engine;
-
-// Sprite defines
-
-enum {
- // This is the low byte part of the sprite type.
-
- RDSPR_TRANS = 0x0001,
- RDSPR_BLEND = 0x0004,
- RDSPR_FLIP = 0x0008,
- RDSPR_SHADOW = 0x0010,
- RDSPR_DISPLAYALIGN = 0x0020,
- RDSPR_NOCOMPRESSION = 0x0040,
- RDSPR_EDGEBLEND = 0x0080, // Unused
-
- // This is the high byte part of the sprite type, which defines what
- // type of compression is used. Unless RDSPR_NOCOMPRESSION is set.
-
- RDSPR_RLE16 = 0x0000,
- RDSPR_RLE256 = 0x0100,
- RDSPR_RLE256FAST = 0x0200
-};
-
-// Fading defines
-
-enum {
- RDFADE_NONE,
- RDFADE_UP,
- RDFADE_DOWN,
- RDFADE_BLACK
-};
-
-// Palette defines
-
-enum {
- RDPAL_FADE,
- RDPAL_INSTANT
-};
-
-// Blitting FX defines
-
-enum {
- RDBLTFX_SPRITEBLEND = 0x01,
- RDBLTFX_SHADOWBLEND = 0x02,
- RDBLTFX_EDGEBLEND = 0x04
-};
-
-// Structure filled out by each object to register its graphic printing
-// requrements
-
-struct BuildUnit {
- int16 x;
- int16 y;
- uint16 scaled_width;
- uint16 scaled_height;
- int16 sort_y;
- uint32 anim_resource;
- uint16 anim_pc;
-
- // Denotes a scaling sprite at print time - and holds the scaling value
- // for the shrink routine
-
- uint16 scale;
-
- // Non-zero means this item is a layer - retrieve from background layer
- // and send to special renderer
-
- uint16 layer_number;
-
- // True means we want this frame to be affected by the shading mask
-
- bool shadingFlag;
-};
-
-struct ScreenInfo {
- uint16 scroll_offset_x; // Position x
- uint16 scroll_offset_y; // Position y
- uint16 max_scroll_offset_x; // Calc'ed in fnInitBackground
- uint16 max_scroll_offset_y;
- int16 player_feet_x; // Feet coordinates to use - cant just
- int16 player_feet_y; // fetch the player compact anymore
- int16 feet_x; // Special offset-to-player position -
- int16 feet_y; // tweek as desired - always set in
- // screen manager object startup
- uint16 screen_wide; // Size of background layer - hence
- uint16 screen_deep; // size of back buffer itself (Paul
- // actually malloc's it)
- uint32 background_layer_id; // Id of the normal background layer
- // from the header of the main
- // background layer
- uint16 number_of_layers;
- uint8 new_palette; // Set to non zero to start the
- // palette held within layer file
- // fading up after a build_display
- uint8 scroll_flag; // Scroll mode 0 off 1 on
- bool mask_flag; // Using shading mask
-};
-
-// The SpriteInfo structure is used to tell the driver96 code what attributes
-// are linked to a sprite for drawing. These include position, scaling and
-// compression.
-
-struct SpriteInfo {
- int16 x; // coords for top-left of sprite
- int16 y;
- uint16 w; // dimensions of sprite (before scaling)
- uint16 h;
- uint16 scale; // scale at which to draw, given in 256ths ['0' or '256' MEANS DON'T SCALE]
- uint16 scaledWidth; // new dimensions (we calc these for the mouse area, so may as well pass to you to save time)
- uint16 scaledHeight; //
- uint16 type; // mask containing 'RDSPR_' bits specifying compression type, flip, transparency, etc
- uint16 blend; // holds the blending values.
- byte *data; // pointer to the sprite data
- byte *colourTable; // pointer to 16-byte colour table, only applicable to 16-col compression type
-};
-
-struct BlockSurface {
- byte data[BLOCKWIDTH * BLOCKHEIGHT];
- bool transparent;
-};
-
-struct Parallax {
- uint16 w;
- uint16 h;
-
- // The dimensions are followed by an offset table, but we don't know in
- // advance how big it is. See initializeBackgroundLayer().
-
- static const int size() {
- return 4;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- w = readS.readUint16LE();
- h = readS.readUint16LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint16LE(w);
- writeS.writeUint16LE(h);
- }
-};
-
-class Screen {
-private:
- Sword2Engine *_vm;
-
- // _thisScreen describes the current back buffer and its in-game scroll
- // positions, etc.
-
- ScreenInfo _thisScreen;
-
- int32 _renderCaps;
- int8 _renderLevel;
-
- byte *_buffer;
- byte *_lightMask;
-
- // Game screen metrics
- int16 _screenWide;
- int16 _screenDeep;
-
- bool _needFullRedraw;
-
- // Scroll variables. _scrollX and _scrollY hold the current scroll
- // position, and _scrollXTarget and _scrollYTarget are the target
- // position for the end of the game cycle.
-
- int16 _scrollX;
- int16 _scrollY;
-
- int16 _scrollXTarget;
- int16 _scrollYTarget;
- int16 _scrollXOld;
- int16 _scrollYOld;
-
- int16 _parallaxScrollX; // current x offset to link a sprite to the
- // parallax layer
- int16 _parallaxScrollY; // current y offset to link a sprite to the
- // parallax layer
- int16 _locationWide;
- int16 _locationDeep;
-
- // Dirty grid handling
- byte *_dirtyGrid;
-
- uint16 _gridWide;
- uint16 _gridDeep;
-
- byte _palette[256 * 4];
- byte _paletteMatch[PALTABLESIZE];
-
- uint8 _fadeStatus;
- int32 _fadeStartTime;
- int32 _fadeTotalTime;
-
- // 'frames per second' counting stuff
- uint32 _fps;
- uint32 _cycleTime;
- uint32 _frameCount;
-
- int32 _initialTime;
- int32 _startTime;
- int32 _totalTime;
- int32 _renderAverageTime;
- int32 _framesPerGameCycle;
- bool _renderTooSlow;
-
- void startNewPalette();
-
- void resetRenderEngine();
-
- void startRenderCycle();
- bool endRenderCycle();
-
- // Holds the order of the sort list, i.e. the list stays static and we
- // sort this array.
-
- uint16 _sortOrder[MAX_sort_sprites];
-
- BuildUnit _bgp0List[MAX_bgp0_sprites];
- BuildUnit _bgp1List[MAX_bgp1_sprites];
- BuildUnit _backList[MAX_back_sprites];
- BuildUnit _sortList[MAX_sort_sprites];
- BuildUnit _foreList[MAX_fore_sprites];
- BuildUnit _fgp0List[MAX_fgp0_sprites];
- BuildUnit _fgp1List[MAX_fgp1_sprites];
-
- uint32 _curBgp0;
- uint32 _curBgp1;
- uint32 _curBack;
- uint32 _curSort;
- uint32 _curFore;
- uint32 _curFgp0;
- uint32 _curFgp1;
-
- void drawBackPar0Frames();
- void drawBackPar1Frames();
- void drawBackFrames();
- void drawSortFrames(byte *file);
- void drawForeFrames();
- void drawForePar0Frames();
- void drawForePar1Frames();
-
- void processLayer(byte *file, uint32 layer_number);
- void processImage(BuildUnit *build_unit);
-
- uint8 _scrollFraction;
-
- // Last palette used - so that we can restore the correct one after a
- // pause (which dims the screen) and it's not always the main screen
- // palette that we want, eg. during the eclipse
-
- // This flag gets set in startNewPalette() and setFullPalette()
-
- uint32 _lastPaletteRes;
-
- // Debugging stuff
- uint32 _largestLayerArea;
- uint32 _largestSpriteArea;
- char _largestLayerInfo[128];
- char _largestSpriteInfo[128];
-
- void registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit);
-
- void mirrorSprite(byte *dst, byte *src, int16 w, int16 h);
- int32 decompressRLE256(byte *dst, byte *src, int32 decompSize);
- void unwindRaw16(byte *dst, byte *src, uint8 blockSize, byte *colTable);
- int32 decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable);
- void renderParallax(byte *ptr, int16 layer);
-
- void markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1);
-
- uint8 _xBlocks[MAXLAYERS];
- uint8 _yBlocks[MAXLAYERS];
-
- // An array of sub-blocks, one for each of the parallax layers.
-
- BlockSurface **_blockSurfaces[MAXLAYERS];
-
- uint16 _xScale[SCALE_MAXWIDTH];
- uint16 _yScale[SCALE_MAXHEIGHT];
-
- void blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect);
-
- uint16 _layer;
-
-public:
- Screen(Sword2Engine *vm, int16 width, int16 height);
- ~Screen();
-
- int8 getRenderLevel();
- void setRenderLevel(int8 level);
-
- byte *getScreen() { return _buffer; }
- byte *getPalette() { return _palette; }
- ScreenInfo *getScreenInfo() { return &_thisScreen; }
-
- int16 getScreenWide() { return _screenWide; }
- int16 getScreenDeep() { return _screenDeep; }
-
- uint32 getCurBgp0() { return _curBgp0; }
- uint32 getCurBgp1() { return _curBgp1; }
- uint32 getCurBack() { return _curBack; }
- uint32 getCurSort() { return _curSort; }
- uint32 getCurFore() { return _curFore; }
- uint32 getCurFgp0() { return _curFgp0; }
- uint32 getCurFgp1() { return _curFgp1; }
-
- uint32 getFps() { return _fps; }
-
- uint32 getLargestLayerArea() { return _largestLayerArea; }
- uint32 getLargestSpriteArea() { return _largestSpriteArea; }
- char *getLargestLayerInfo() { return _largestLayerInfo; }
- char *getLargestSpriteInfo() { return _largestSpriteInfo; }
-
- void setNeedFullRedraw();
-
- void clearScene();
-
- void resetRenderLists();
-
- void setLocationMetrics(uint16 w, uint16 h);
- int32 initialiseBackgroundLayer(byte *parallax);
- void closeBackgroundLayer();
-
- void initialiseRenderCycle();
-
- void initBackground(int32 res, int32 new_palette);
- void registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega);
-
- void setScrollFraction(uint8 f) { _scrollFraction = f; }
- void setScrollTarget(int16 x, int16 y);
- void setScrolling();
-
- void setFullPalette(int32 palRes);
- void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow);
- uint8 quickMatch(uint8 r, uint8 g, uint8 b);
- int32 fadeUp(float time = 0.75);
- int32 fadeDown(float time = 0.75);
- uint8 getFadeStatus();
- void dimPalette();
- void waitForFade();
- void fadeServer();
-
- void updateDisplay(bool redrawScene = true);
-
- void displayMsg(byte *text, int time);
-
- int32 createSurface(SpriteInfo *s, byte **surface);
- void drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect = NULL);
- void deleteSurface(byte *surface);
- int32 drawSprite(SpriteInfo *s);
-
- void scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth,
- uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
- uint16 srcHeight);
- void scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth,
- uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
- uint16 srcHeight, byte *backbuf);
-
- void updateRect(Common::Rect *r);
-
- int32 openLightMask(SpriteInfo *s);
- int32 closeLightMask();
-
- void buildDisplay();
-
- void plotPoint(int x, int y, uint8 colour);
- void drawLine(int x0, int y0, int x1, int y1, uint8 colour);
-
-#ifdef BACKEND_8BIT
- void plotYUV(byte *lut, int width, int height, byte *const *dat);
-#endif
-
- void rollCredits();
- void splashScreen();
-};
-
-} // End of namespace Sword2
-
-#endif
Deleted: scummvm/trunk/engines/sword2/save_rest.cpp
===================================================================
--- scummvm/trunk/engines/sword2/save_rest.cpp 2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/save_rest.cpp 2006-02-12 19:38:26 UTC (rev 20652)
@@ -1,414 +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$
- */
-
-// ---------------------------------------------------------------------------
-// SAVE_REST.CPP save, restore & restart functions
-//
-// James 05feb97
-//
-// "Jesus Saves", but could he Restore or Restart? He can now...
-//
-// ---------------------------------------------------------------------------
-
-#include "common/stdafx.h"
-#include "common/savefile.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-namespace Sword2 {
-
-// A savegame consists of a header and the global variables
-
-// Max length of a savegame filename
-#define MAX_FILENAME_LEN 128
-
-/**
- * Calculate size of required savegame buffer
- */
-
-uint32 Sword2Engine::findBufferSize() {
- // Size of savegame header + size of global variables
- return 212 + _resman->fetchLen(1);
-}
-
-/**
- * Save the game.
- */
-
-uint32 Sword2Engine::saveGame(uint16 slotNo, byte *desc) {
- char description[SAVE_DESCRIPTION_LEN];
- uint32 bufferSize = findBufferSize();
- byte *saveBuffer = (byte *)malloc(bufferSize);
- ScreenInfo *screenInfo = _screen->getScreenInfo();
-
- memset(description, 0, sizeof(description));
- strncpy(description, (char *)desc, SAVE_DESCRIPTION_LEN - 1);
-
- Common::MemoryWriteStream writeS(saveBuffer, bufferSize);
-
- byte *globalVars = _resman->openResource(1);
- byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
-
- // Script no. 7 - 'george_savedata_request' calls fnPassPlayerSaveData
- _logic->runResScript(CUR_PLAYER_ID, 7);
-
- writeS.writeUint32LE(0); // Checksum
- writeS.write(description, SAVE_DESCRIPTION_LEN);
- writeS.writeUint32LE(_resman->fetchLen(1));
- writeS.writeUint32LE(screenInfo->background_layer_id);
- writeS.writeUint32LE(_logic->getRunList());
- writeS.writeUint32LE(screenInfo->feet_x);
- writeS.writeUint32LE(screenInfo->feet_y);
- writeS.writeUint32LE(_sound->getLoopingMusicId());
- writeS.write(objectHub, ObjectHub::size());
- writeS.write(_logic->_saveLogic, ObjectLogic::size());
- writeS.write(_logic->_saveGraphic, ObjectGraphic::size());
- writeS.write(_logic->_saveMega, ObjectMega::size());
- writeS.write(globalVars, _resman->fetchLen(1));
-
- WRITE_LE_UINT32(saveBuffer, calcChecksum(saveBuffer + 4, bufferSize - 4));
-
- _resman->closeResource(CUR_PLAYER_ID);
- _resman->closeResource(1);
-
- uint32 errorCode = saveData(slotNo, saveBuffer, bufferSize);
-
- free(saveBuffer);
-
- if (errorCode != SR_OK) {
- uint32 textId;
-
- switch (errorCode) {
- case SR_ERR_FILEOPEN:
- textId = TEXT_SAVE_CANT_OPEN;
- break;
- default:
- textId = TEXT_SAVE_FAILED;
- break;
- }
-
- _screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
- }
-
- return errorCode;
-}
-
-uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
- char saveFileName[MAX_FILENAME_LEN];
-
- sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
- Common::OutSaveFile *out;
-
- if (!(out = _saveFileMan->openForSaving(saveFileName))) {
- return SR_ERR_FILEOPEN;
- }
-
- out->write(buffer, bufferSize);
- out->flush();
-
- if (!out->ioFailed()) {
- delete out;
- return SR_OK;
- }
-
- delete out;
- return SR_ERR_WRITEFAIL;
-}
-
-/**
- * Restore the game.
- */
-
-uint32 Sword2Engine::restoreGame(uint16 slotNo) {
- uint32 bufferSize = findBufferSize();
- byte *saveBufferMem = (byte *)malloc(bufferSize);
-
- uint32 errorCode = restoreData(slotNo, saveBufferMem, bufferSize);
-
- // If it was read in successfully, then restore the game from the
- // buffer & free the buffer. Note that restoreFromBuffer() frees the
- // buffer in order to clear it from memory before loading in the new
- // screen and runlist, so we only need to free it in case of failure.
-
- if (errorCode == SR_OK)
- errorCode = restoreFromBuffer(saveBufferMem, bufferSize);
- else
- free(saveBufferMem);
-
- if (errorCode != SR_OK) {
- uint32 textId;
-
- switch (errorCode) {
- case SR_ERR_FILEOPEN:
- textId = TEXT_RESTORE_CANT_OPEN;
- break;
- case SR_ERR_INCOMPATIBLE:
- textId = TEXT_RESTORE_INCOMPATIBLE;
- break;
- default:
- textId = TEXT_RESTORE_FAILED;
- break;
- }
-
- _screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
- } else {
- // Prime system with a game cycle
-
- // Reset the graphic 'BuildUnit' list before a new logic list
- // (see fnRegisterFrame)
- _screen->resetRenderLists();
-
- // Reset the mouse hot-spot list. See fnRegisterMouse()
- // and fnRegisterFrame()
- _mouse->resetMouseList();
-
- if (_logic->processSession())
- error("restore 1st cycle failed??");
- }
-
- // Force the game engine to pick a cursor. This appears to be needed
- // when using the -x command-line option to restore a game.
- _mouse->setMouseTouching(1);
- return errorCode;
-}
-
-uint32 Sword2Engine::restoreData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
- char saveFileName[MAX_FILENAME_LEN];
-
- sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
- Common::InSaveFile *in;
-
- if (!(in = _saveFileMan->openForLoading(saveFileName))) {
- // error: couldn't open file
- return SR_ERR_FILEOPEN;
- }
-
- // Read savegame into the buffer
- uint32 itemsRead = in->read(buffer, bufferSize);
-
- delete in;
-
- if (itemsRead != bufferSize) {
- // We didn't get all of it. At the moment we have no way of
- // knowing why, so assume that it's an incompatible savegame.
-
- return SR_ERR_INCOMPATIBLE;
- }
-
- return SR_OK;
-}
-
-uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
- Common::MemoryReadStream readS(buffer, size);
-
- // Calc checksum & check that aginst the value stored in the header
-
- if (readS.readUint32LE() != calcChecksum(buffer + 4, size - 4)) {
- free(buffer);
- return SR_ERR_INCOMPATIBLE;
- }
-
- readS.seek(SAVE_DESCRIPTION_LEN, SEEK_CUR);
-
- // Check savegame against length of current global variables resource
- // This would most probably be trapped by the checksum test anyway,
- // but it doesn't do any harm to check this as well.
-
- // Historical note: During development, earlier savegames would often
- // be shorter than the current expected length.
-
- if (readS.readUint32LE() != _resman->fetchLen(1)) {
- free(buffer);
- return SR_ERR_INCOMPATIBLE;
- }
-
- byte *globalVars = _resman->openResource(1);
- byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
-
- uint32 screenId = readS.readUint32LE();
- uint32 runListId = readS.readUint32LE();
- uint32 feetX = readS.readUint32LE();
- uint32 feetY = readS.readUint32LE();
- uint32 musicId = readS.readUint32LE();
-
- // Trash all resources from memory except player object & global vars
- _resman->killAll(false);
- _logic->resetKillList();
-
- readS.read(objectHub, ObjectHub::size());
- readS.read(_logic->_saveLogic, ObjectLogic::size());
- readS.read(_logic->_saveGraphic, ObjectGraphic::size());
- readS.read(_logic->_saveMega, ObjectMega::size());
-
- // Fill out the player object structures from the savegame structures.
- // Also run the appropriate scripts to set up George's anim tables and
- // walkdata, and Nico's anim tables.
-
- // Script no. 8 - 'george_savedata_return' calls fnGetPlayerSaveData
- _logic->runResScript(CUR_PLAYER_ID, 8);
-
- // Script no. 14 - 'set_up_nico_anim_tables'
- _logic->runResScript(CUR_PLAYER_ID, 14);
-
- // Which megaset was the player at the time of saving?
- ObjectMega obMega(_logic->_saveMega);
-
- uint32 scriptNo = 0;
-
- switch (obMega.getMegasetRes()) {
- case 36: // GeoMega:
- scriptNo = 9; // script no.9 - 'player_is_george'
- break;
- case 2003: // GeoMegaB:
- scriptNo = 13; // script no.13 - 'player_is_georgeB'
- break;
- case 1366: // NicMegaA:
- scriptNo = 11; // script no.11 - 'player_is_nicoA'
- break;
- case 1437: // NicMegaB:
- scriptNo = 12; // script no.12 - 'player_is_nicoB'
- break;
- case 1575: // NicMegaC:
- scriptNo = 10; // script no.10 - 'player_is_nicoC'
- break;
- }
-
- _logic->runResScript(CUR_PLAYER_ID, scriptNo);
-
- // Copy variables from savegame buffer to memory
- readS.read(globalVars, _resman->fetchLen(1));
-
- _resman->closeResource(CUR_PLAYER_ID);
- _resman->closeResource(1);
-
- free(buffer);
-
- int32 pars[2];
-
- pars[0] = screenId;
- pars[1] = 1;
- _logic->fnInitBackground(pars);
-
- ScreenInfo *screenInfo = _screen->getScreenInfo();
-
- // So palette not restored immediately after control panel - we want to
- // fade up instead!
- screenInfo->new_palette = 99;
-
- // These need setting after the defaults get set in fnInitBackground.
- // Remember that these can change through the game, so need saving &
- // restoring too.
-
- screenInfo->feet_x = feetX;
- screenInfo->feet_y = feetY;
-
- // Start the new run list
- _logic->expressChangeSession(runListId);
-
- // Force in the new scroll position, so unsightly scroll-catch-up does
- // not occur when screen first draws after returning from restore panel
-
- // Set the screen record of player position - ready for setScrolling()
-
- screenInfo->player_feet_x = obMega.getFeetX();
- screenInfo->player_feet_y = obMega.getFeetY();
-
- // if this screen is wide, recompute the scroll offsets now
- if (screenInfo->scroll_flag)
- _screen->setScrolling();
-
- // Any music required will be started after we've returned from
- // restoreControl() - see systemMenuMouse() in mouse.cpp!
-
- // Restart any looping music. Originally this was - and still is - done
- // in systemMenuMouse(), but with ScummVM we have other ways of
- // restoring savegames so it's easier to put it here as well.
-
- if (musicId) {
- pars[0] = musicId;
- pars[1] = FX_LOOP;
- _logic->fnPlayMusic(pars);
- } else
- _logic->fnStopMusic(NULL);
-
- return SR_OK;
-}
-
-/**
- * Get the description of a savegame
- */
-
-uint32 Sword2Engine::getSaveDescription(uint16 slotNo, byte *description) {
- char saveFileName[MAX_FILENAME_LEN];
-
- sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
- Common::InSaveFile *in;
-
- if (!(in = _saveFileMan->openForLoading(saveFileName))) {
- return SR_ERR_FILEOPEN;
- }
-
- in->readUint32LE();
- in->read(description, SAVE_DESCRIPTION_LEN);
-
- delete in;
- return SR_OK;
-}
-
-bool Sword2Engine::saveExists() {
- for (int i = 0; i <= 99; i++)
- if (saveExists(i))
- return true;
- return false;
-}
-
-bool Sword2Engine::saveExists(uint16 slotNo) {
- char saveFileName[MAX_FILENAME_LEN];
-
- sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
- Common::InSaveFile *in;
-
- if (!(in = _saveFileMan->openForLoading(saveFileName))) {
- return false;
- }
-
- delete in;
- return true;
-}
-
-uint32 Sword2Engine::calcChecksum(byte *buffer, uint32 size) {
- uint32 total = 0;
-
- for (uint32 pos = 0; pos < size; pos++)
- total += buffer[pos];
-
- return total;
-}
-
-} // End of namespace Sword2
Deleted: scummvm/trunk/engines/sword2/save_rest.h
===================================================================
--- scummvm/trunk/engines/sword2/save_rest.h 2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/save_rest.h 2006-02-12 19:38:26 UTC (rev 20652)
@@ -1,47 +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$
- */
-
-#ifndef SAVE_REST_H
-#define SAVE_REST_H
-
-namespace Sword2 {
-
-#define SAVE_DESCRIPTION_LEN 64
-
-// Save & Restore error codes
-
-enum {
- SR_OK, // No worries
- SR_ERR_FILEOPEN, // Can't open file - Couldn't create file for
- // saving, or couldn't find file for loading.
- SR_ERR_INCOMPATIBLE, // (Restore) Incompatible savegame data.
- // Savegame file is obsolete. (Won't happen
- // after development stops)
- SR_ERR_READFAIL, // (Restore) Failed on reading savegame file -
- // Something screwed up during the read
- SR_ERR_WRITEFAIL // (Save) Failed on writing savegame file -
- // Something screwed up during the write -
- // could be hard-drive full..?
-};
-
-} // End of namespace Sword2
-
-#endif
Copied: scummvm/trunk/engines/sword2/saveload.cpp (from rev 20651, scummvm/trunk/engines/sword2/save_rest.cpp)
===================================================================
--- scummvm/trunk/engines/sword2/saveload.cpp (rev 0)
+++ scummvm/trunk/engines/sword2/saveload.cpp 2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,414 @@
+/* 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$
+ */
+
+// ---------------------------------------------------------------------------
+// SAVE_REST.CPP save, restore & restart functions
+//
+// James 05feb97
+//
+// "Jesus Saves", but could he Restore or Restart? He can now...
+//
+// ---------------------------------------------------------------------------
+
+#include "common/stdafx.h"
+#include "common/savefile.h"
+#include "sword2/sword2.h"
+#include "sword2/defs.h"
+#include "sword2/logic.h"
+#include "sword2/mouse.h"
+#include "sword2/resman.h"
+#include "sword2/sound.h"
+
+namespace Sword2 {
+
+// A savegame consists of a header and the global variables
+
+// Max length of a savegame filename
+#define MAX_FILENAME_LEN 128
+
+/**
+ * Calculate size of required savegame buffer
+ */
+
+uint32 Sword2Engine::findBufferSize() {
+ // Size of savegame header + size of global variables
+ return 212 + _resman->fetchLen(1);
+}
+
+/**
+ * Save the game.
+ */
+
+uint32 Sword2Engine::saveGame(uint16 slotNo, byte *desc) {
+ char description[SAVE_DESCRIPTION_LEN];
+ uint32 bufferSize = findBufferSize();
+ byte *saveBuffer = (byte *)malloc(bufferSize);
+ ScreenInfo *screenInfo = _screen->getScreenInfo();
+
+ memset(description, 0, sizeof(description));
+ strncpy(description, (char *)desc, SAVE_DESCRIPTION_LEN - 1);
+
+ Common::MemoryWriteStream writeS(saveBuffer, bufferSize);
+
+ byte *globalVars = _resman->openResource(1);
+ byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
+
+ // Script no. 7 - 'george_savedata_request' calls fnPassPlayerSaveData
+ _logic->runResScript(CUR_PLAYER_ID, 7);
+
+ writeS.writeUint32LE(0); // Checksum
+ writeS.write(description, SAVE_DESCRIPTION_LEN);
+ writeS.writeUint32LE(_resman->fetchLen(1));
+ writeS.writeUint32LE(screenInfo->background_layer_id);
+ writeS.writeUint32LE(_logic->getRunList());
+ writeS.writeUint32LE(screenInfo->feet_x);
+ writeS.writeUint32LE(screenInfo->feet_y);
+ writeS.writeUint32LE(_sound->getLoopingMusicId());
+ writeS.write(objectHub, ObjectHub::size());
+ writeS.write(_logic->_saveLogic, ObjectLogic::size());
+ writeS.write(_logic->_saveGraphic, ObjectGraphic::size());
+ writeS.write(_logic->_saveMega, ObjectMega::size());
+ writeS.write(globalVars, _resman->fetchLen(1));
+
+ WRITE_LE_UINT32(saveBuffer, calcChecksum(saveBuffer + 4, bufferSize - 4));
+
+ _resman->closeResource(CUR_PLAYER_ID);
+ _resman->closeResource(1);
+
+ uint32 errorCode = saveData(slotNo, saveBuffer, bufferSize);
+
+ free(saveBuffer);
+
+ if (errorCode != SR_OK) {
+ uint32 textId;
+
+ switch (errorCode) {
+ case SR_ERR_FILEOPEN:
+ textId = TEXT_SAVE_CANT_OPEN;
+ break;
+ default:
+ textId = TEXT_SAVE_FAILED;
+ break;
+ }
+
+ _screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+ }
+
+ return errorCode;
+}
+
+uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
+ char saveFileName[MAX_FILENAME_LEN];
+
+ sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+ Common::OutSaveFile *out;
+
+ if (!(out = _saveFileMan->openForSaving(saveFileName))) {
+ return SR_ERR_FILEOPEN;
+ }
+
+ out->write(buffer, bufferSize);
+ out->flush();
+
+ if (!out->ioFailed()) {
+ delete out;
+ return SR_OK;
+ }
+
+ delete out;
+ return SR_ERR_WRITEFAIL;
+}
+
+/**
+ * Restore the game.
+ */
+
+uint32 Sword2Engine::restoreGame(uint16 slotNo) {
+ uint32 bufferSize = findBufferSize();
+ byte *saveBufferMem = (byte *)malloc(bufferSize);
+
+ uint32 errorCode = restoreData(slotNo, saveBufferMem, bufferSize);
+
+ // If it was read in successfully, then restore the game from the
+ // buffer & free the buffer. Note that restoreFromBuffer() frees the
+ // buffer in order to clear it from memory before loading in the new
+ // screen and runlist, so we only need to free it in case of failure.
+
+ if (errorCode == SR_OK)
+ errorCode = restoreFromBuffer(saveBufferMem, bufferSize);
+ else
+ free(saveBufferMem);
+
+ if (errorCode != SR_OK) {
+ uint32 textId;
+
+ switch (errorCode) {
+ case SR_ERR_FILEOPEN:
+ textId = TEXT_RESTORE_CANT_OPEN;
+ break;
+ case SR_ERR_INCOMPATIBLE:
+ textId = TEXT_RESTORE_INCOMPATIBLE;
+ break;
+ default:
+ textId = TEXT_RESTORE_FAILED;
+ break;
+ }
+
+ _screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+ } else {
+ // Prime system with a game cycle
+
+ // Reset the graphic 'BuildUnit' list before a new logic list
+ // (see fnRegisterFrame)
+ _screen->resetRenderLists();
+
+ // Reset the mouse hot-spot list. See fnRegisterMouse()
+ // and fnRegisterFrame()
+ _mouse->resetMouseList();
+
+ if (_logic->processSession())
+ error("restore 1st cycle failed??");
+ }
+
+ // Force the game engine to pick a cursor. This appears to be needed
+ // when using the -x command-line option to restore a game.
+ _mouse->setMouseTouching(1);
+ return errorCode;
+}
+
+uint32 Sword2Engine::restoreData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
+ char saveFileName[MAX_FILENAME_LEN];
+
+ sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+ Common::InSaveFile *in;
+
+ if (!(in = _saveFileMan->openForLoading(saveFileName))) {
+ // error: couldn't open file
+ return SR_ERR_FILEOPEN;
+ }
+
+ // Read savegame into the buffer
+ uint32 itemsRead = in->read(buffer, bufferSize);
+
+ delete in;
+
+ if (itemsRead != bufferSize) {
+ // We didn't get all of it. At the moment we have no way of
+ // knowing why, so assume that it's an incompatible savegame.
+
+ return SR_ERR_INCOMPATIBLE;
+ }
+
+ return SR_OK;
+}
+
+uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
+ Common::MemoryReadStream readS(buffer, size);
+
+ // Calc checksum & check that aginst the value stored in the header
+
+ if (readS.readUint32LE() != calcChecksum(buffer + 4, size - 4)) {
+ free(buffer);
+ return SR_ERR_INCOMPATIBLE;
+ }
+
+ readS.seek(SAVE_DESCRIPTION_LEN, SEEK_CUR);
+
+ // Check savegame against length of current global variables resource
+ // This would most probably be trapped by the checksum test anyway,
+ // but it doesn't do any harm to check this as well.
+
+ // Historical note: During development, earlier savegames would often
+ // be shorter than the current expected length.
+
+ if (readS.readUint32LE() != _resman->fetchLen(1)) {
+ free(buffer);
+ return SR_ERR_INCOMPATIBLE;
+ }
+
+ byte *globalVars = _resman->openResource(1);
+ byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
+
+ uint32 screenId = readS.readUint32LE();
+ uint32 runListId = readS.readUint32LE();
+ uint32 feetX = readS.readUint32LE();
+ uint32 feetY = readS.readUint32LE();
+ uint32 musicId = readS.readUint32LE();
+
+ // Trash all resources from memory except player object & global vars
+ _resman->killAll(false);
+ _logic->resetKillList();
+
+ readS.read(objectHub, ObjectHub::size());
+ readS.read(_logic->_saveLogic, ObjectLogic::size());
+ readS.read(_logic->_saveGraphic, ObjectGraphic::size());
+ readS.read(_logic->_saveMega, ObjectMega::size());
+
+ // Fill out the player object structures from the savegame structures.
+ // Also run the appropriate scripts to set up George's anim tables and
+ // walkdata, and Nico's anim tables.
+
+ // Script no. 8 - 'george_savedata_return' calls fnGetPlayerSaveData
+ _logic->runResScript(CUR_PLAYER_ID, 8);
+
+ // Script no. 14 - 'set_up_nico_anim_tables'
+ _logic->runResScript(CUR_PLAYER_ID, 14);
+
+ // Which megaset was the player at the time of saving?
+ ObjectMega obMega(_logic->_saveMega);
+
+ uint32 scriptNo = 0;
+
+ switch (obMega.getMegasetRes()) {
+ case 36: // GeoMega:
+ scriptNo = 9; // script no.9 - 'player_is_george'
+ break;
+ case 2003: // GeoMegaB:
+ scriptNo = 13; // script no.13 - 'player_is_georgeB'
+ break;
+ case 1366: // NicMegaA:
+ scriptNo = 11; // script no.11 - 'player_is_nicoA'
+ break;
+ case 1437: // NicMegaB:
+ scriptNo = 12; // script no.12 - 'player_is_nicoB'
+ break;
+ case 1575: // NicMegaC:
+ scriptNo = 10; // script no.10 - 'player_is_nicoC'
+ break;
+ }
+
+ _logic->runResScript(CUR_PLAYER_ID, scriptNo);
+
+ // Copy variables from savegame buffer to memory
+ readS.read(globalVars, _resman->fetchLen(1));
+
+ _resman->closeResource(CUR_PLAYER_ID);
+ _resman->closeResource(1);
+
+ free(buffer);
+
+ int32 pars[2];
+
+ pars[0] = screenId;
+ pars[1] = 1;
+ _logic->fnInitBackground(pars);
+
+ ScreenInfo *screenInfo = _screen->getScreenInfo();
+
+ // So palette not restored immediately after control panel - we want to
+ // fade up instead!
+ screenInfo->new_palette = 99;
+
+ // These need setting after the defaults get set in fnInitBackground.
+ // Remember that these can change through the game, so need saving &
+ // restoring too.
+
+ screenInfo->feet_x = feetX;
+ screenInfo->feet_y = feetY;
+
+ // Start the new run list
+ _logic->expressChangeSession(runListId);
+
+ // Force in the new scroll position, so unsightly scroll-catch-up does
+ // not occur when screen first draws after returning from restore panel
+
+ // Set the screen record of player position - ready for setScrolling()
+
+ screenInfo->player_feet_x = obMega.getFeetX();
+ screenInfo->player_feet_y = obMega.getFeetY();
+
+ // if this screen is wide, recompute the scroll offsets now
+ if (screenInfo->scroll_flag)
+ _screen->setScrolling();
+
+ // Any music required will be started after we've returned from
+ // restoreControl() - see systemMenuMouse() in mouse.cpp!
+
+ // Restart any looping music. Originally this was - and still is - done
+ // in systemMenuMouse(), but with ScummVM we have other ways of
+ // restoring savegames so it's easier to put it here as well.
+
+ if (musicId) {
+ pars[0] = musicId;
+ pars[1] = FX_LOOP;
+ _logic->fnPlayMusic(pars);
+ } else
+ _logic->fnStopMusic(NULL);
+
+ return SR_OK;
+}
+
+/**
+ * Get the description of a savegame
+ */
+
+uint32 Sword2Engine::getSaveDescription(uint16 slotNo, byte *description) {
+ char saveFileName[MAX_FILENAME_LEN];
+
+ sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+ Common::InSaveFile *in;
+
+ if (!(in = _saveFileMan->openForLoading(saveFileName))) {
+ return SR_ERR_FILEOPEN;
+ }
+
+ in->readUint32LE();
+ in->read(description, SAVE_DESCRIPTION_LEN);
+
+ delete in;
+ return SR_OK;
+}
+
+bool Sword2Engine::saveExists() {
+ for (int i = 0; i <= 99; i++)
+ if (saveExists(i))
+ return true;
+ return false;
+}
+
+bool Sword2Engine::saveExists(uint16 slotNo) {
+ char saveFileName[MAX_FILENAME_LEN];
+
+ sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+ Common::InSaveFile *in;
+
+ if (!(in = _saveFileMan->openForLoading(saveFileName))) {
+ return false;
+ }
+
+ delete in;
+ return true;
+}
+
+uint32 Sword2Engine::calcChecksum(byte *buffer, uint32 size) {
+ uint32 total = 0;
+
+ for (uint32 pos = 0; pos < size; pos++)
+ total += buffer[pos];
+
+ return total;
+}
+
+} // End of namespace Sword2
Copied: scummvm/trunk/engines/sword2/saveload.h (from rev 20651, scummvm/trunk/engines/sword2/save_rest.h)
===================================================================
--- scummvm/trunk/engines/sword2/saveload.h (rev 0)
+++ scummvm/trunk/engines/sword2/saveload.h 2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,47 @@
+/* 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$
+ */
+
+#ifndef SAVE_REST_H
+#define SAVE_REST_H
+
+namespace Sword2 {
+
+#define SAVE_DESCRIPTION_LEN 64
+
+// Save & Restore error codes
+
+enum {
+ SR_OK, // No worries
+ SR_ERR_FILEOPEN, // Can't open file - Couldn't create file for
+ // saving, or couldn't find file for loading.
+ SR_ERR_INCOMPATIBLE, // (Restore) Incompatible savegame data.
+ // Savegame file is obsolete. (Won't happen
+ // after development stops)
+ SR_ERR_READFAIL, // (Restore) Failed on reading savegame file -
+ // Something screwed up during the read
+ SR_ERR_WRITEFAIL // (Save) Failed on writing savegame file -
+ // Something screwed up during the write -
+ // could be hard-drive full..?
+};
+
+} // End of namespace Sword2
+
+#endif
Copied: scummvm/trunk/engines/sword2/screen.cpp (from rev 20651, scummvm/trunk/engines/sword2/build_display.cpp)
===================================================================
--- scummvm/trunk/engines/sword2/screen.cpp (rev 0)
+++ scummvm/trunk/engines/sword2/screen.cpp 2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,1070 @@
+/* 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
Copied: scummvm/trunk/engines/sword2/screen.h (from rev 20651, scummvm/trunk/engines/sword2/build_display.h)
===================================================================
--- scummvm/trunk/engines/sword2/screen.h (rev 0)
+++ scummvm/trunk/engines/sword2/screen.h 2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,441 @@
+/* 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$
+ */
+
+#ifndef _BUILD_DISPLAY
+#define _BUILD_DISPLAY
+
+#include "common/rect.h"
+#include "common/stream.h"
+
+#define MAX_bgp0_sprites 6
+#define MAX_bgp1_sprites 6
+#define MAX_back_sprites 30
+#define MAX_sort_sprites 30
+#define MAX_fore_sprites 30
+#define MAX_fgp0_sprites 6
+#define MAX_fgp1_sprites 6
+
+#define PALTABLESIZE (64 * 64 * 64)
+
+#define BLOCKWIDTH 64
+#define BLOCKHEIGHT 64
+#define MAXLAYERS 5
+
+#define MENUDEEP 40
+#define RENDERWIDE 640
+#define RENDERDEEP (480 - (MENUDEEP * 2))
+
+// Maximum scaled size of a sprite
+#define SCALE_MAXWIDTH 512
+#define SCALE_MAXHEIGHT 512
+
+// Dirty grid cell size
+#define CELLWIDE 10
+#define CELLDEEP 20
+
+namespace Sword2 {
+
+class Sword2Engine;
+
+// Sprite defines
+
+enum {
+ // This is the low byte part of the sprite type.
+
+ RDSPR_TRANS = 0x0001,
+ RDSPR_BLEND = 0x0004,
+ RDSPR_FLIP = 0x0008,
+ RDSPR_SHADOW = 0x0010,
+ RDSPR_DISPLAYALIGN = 0x0020,
+ RDSPR_NOCOMPRESSION = 0x0040,
+ RDSPR_EDGEBLEND = 0x0080, // Unused
+
+ // This is the high byte part of the sprite type, which defines what
+ // type of compression is used. Unless RDSPR_NOCOMPRESSION is set.
+
+ RDSPR_RLE16 = 0x0000,
+ RDSPR_RLE256 = 0x0100,
+ RDSPR_RLE256FAST = 0x0200
+};
+
+// Fading defines
+
+enum {
+ RDFADE_NONE,
+ RDFADE_UP,
+ RDFADE_DOWN,
+ RDFADE_BLACK
+};
+
+// Palette defines
+
+enum {
+ RDPAL_FADE,
+ RDPAL_INSTANT
+};
+
+// Blitting FX defines
+
+enum {
+ RDBLTFX_SPRITEBLEND = 0x01,
+ RDBLTFX_SHADOWBLEND = 0x02,
+ RDBLTFX_EDGEBLEND = 0x04
+};
+
+// Structure filled out by each object to register its graphic printing
+// requrements
+
+struct BuildUnit {
+ int16 x;
+ int16 y;
+ uint16 scaled_width;
+ uint16 scaled_height;
+ int16 sort_y;
+ uint32 anim_resource;
+ uint16 anim_pc;
+
+ // Denotes a scaling sprite at print time - and holds the scaling value
+ // for the shrink routine
+
+ uint16 scale;
+
+ // Non-zero means this item is a layer - retrieve from background layer
+ // and send to special renderer
+
+ uint16 layer_number;
+
+ // True means we want this frame to be affected by the shading mask
+
+ bool shadingFlag;
+};
+
+struct ScreenInfo {
+ uint16 scroll_offset_x; // Position x
+ uint16 scroll_offset_y; // Position y
+ uint16 max_scroll_offset_x; // Calc'ed in fnInitBackground
+ uint16 max_scroll_offset_y;
+ int16 player_feet_x; // Feet coordinates to use - cant just
+ int16 player_feet_y; // fetch the player compact anymore
+ int16 feet_x; // Special offset-to-player position -
+ int16 feet_y; // tweek as desired - always set in
+ // screen manager object startup
+ uint16 screen_wide; // Size of background layer - hence
+ uint16 screen_deep; // size of back buffer itself (Paul
+ // actually malloc's it)
+ uint32 background_layer_id; // Id of the normal background layer
+ // from the header of the main
+ // background layer
+ uint16 number_of_layers;
+ uint8 new_palette; // Set to non zero to start the
+ // palette held within layer file
+ // fading up after a buildDisplay()
+ uint8 scroll_flag; // Scroll mode 0 off 1 on
+ bool mask_flag; // Using shading mask
+};
+
+// The SpriteInfo structure is used to tell the driver96 code what attributes
+// are linked to a sprite for drawing. These include position, scaling and
+// compression.
+
+struct SpriteInfo {
+ int16 x; // coords for top-left of sprite
+ int16 y;
+ uint16 w; // dimensions of sprite (before scaling)
+ uint16 h;
+ uint16 scale; // scale at which to draw, given in 256ths ['0' or '256' MEANS DON'T SCALE]
+ uint16 scaledWidth; // new dimensions (we calc these for the mouse area, so may as well pass to you to save time)
+ uint16 scaledHeight; //
+ uint16 type; // mask containing 'RDSPR_' bits specifying compression type, flip, transparency, etc
+ uint16 blend; // holds the blending values.
+ byte *data; // pointer to the sprite data
+ byte *colourTable; // pointer to 16-byte colour table, only applicable to 16-col compression type
+};
+
+struct BlockSurface {
+ byte data[BLOCKWIDTH * BLOCKHEIGHT];
+ bool transparent;
+};
+
+struct Parallax {
+ uint16 w;
+ uint16 h;
+
+ // The dimensions are followed by an offset table, but we don't know in
+ // advance how big it is. See initializeBackgroundLayer().
+
+ static const int size() {
+ return 4;
+ }
+
+ void read(byte *addr) {
+ Common::MemoryReadStream readS(addr, size());
+
+ w = readS.readUint16LE();
+ h = readS.readUint16LE();
+ }
+
+ void write(byte *addr) {
+ Common::MemoryWriteStream writeS(addr, size());
+
+ writeS.writeUint16LE(w);
+ writeS.writeUint16LE(h);
+ }
+};
+
+class Screen {
+private:
+ Sword2Engine *_vm;
+
+ // _thisScreen describes the current back buffer and its in-game scroll
+ // positions, etc.
+
+ ScreenInfo _thisScreen;
+
+ int32 _renderCaps;
+ int8 _renderLevel;
+
+ byte *_buffer;
+ byte *_lightMask;
+
+ // Game screen metrics
+ int16 _screenWide;
+ int16 _screenDeep;
+
+ bool _needFullRedraw;
+
+ // Scroll variables. _scrollX and _scrollY hold the current scroll
+ // position, and _scrollXTarget and _scrollYTarget are the target
+ // position for the end of the game cycle.
+
+ int16 _scrollX;
+ int16 _scrollY;
+
+ int16 _scrollXTarget;
+ int16 _scrollYTarget;
+ int16 _scrollXOld;
+ int16 _scrollYOld;
+
+ int16 _parallaxScrollX; // current x offset to link a sprite to the
+ // parallax layer
+ int16 _parallaxScrollY; // current y offset to link a sprite to the
+ // parallax layer
+ int16 _locationWide;
+ int16 _locationDeep;
+
+ // Dirty grid handling
+ byte *_dirtyGrid;
+
+ uint16 _gridWide;
+ uint16 _gridDeep;
+
+ byte _palette[256 * 4];
+ byte _paletteMatch[PALTABLESIZE];
+
+ uint8 _fadeStatus;
+ int32 _fadeStartTime;
+ int32 _fadeTotalTime;
+
+ // 'frames per second' counting stuff
+ uint32 _fps;
+ uint32 _cycleTime;
+ uint32 _frameCount;
+
+ int32 _initialTime;
+ int32 _startTime;
+ int32 _totalTime;
+ int32 _renderAverageTime;
+ int32 _framesPerGameCycle;
+ bool _renderTooSlow;
+
+ void startNewPalette();
+
+ void resetRenderEngine();
+
+ void startRenderCycle();
+ bool endRenderCycle();
+
+ // Holds the order of the sort list, i.e. the list stays static and we
+ // sort this array.
+
+ uint16 _sortOrder[MAX_sort_sprites];
+
+ BuildUnit _bgp0List[MAX_bgp0_sprites];
+ BuildUnit _bgp1List[MAX_bgp1_sprites];
+ BuildUnit _backList[MAX_back_sprites];
+ BuildUnit _sortList[MAX_sort_sprites];
+ BuildUnit _foreList[MAX_fore_sprites];
+ BuildUnit _fgp0List[MAX_fgp0_sprites];
+ BuildUnit _fgp1List[MAX_fgp1_sprites];
+
+ uint32 _curBgp0;
+ uint32 _curBgp1;
+ uint32 _curBack;
+ uint32 _curSort;
+ uint32 _curFore;
+ uint32 _curFgp0;
+ uint32 _curFgp1;
+
+ void drawBackPar0Frames();
+ void drawBackPar1Frames();
+ void drawBackFrames();
+ void drawSortFrames(byte *file);
+ void drawForeFrames();
+ void drawForePar0Frames();
+ void drawForePar1Frames();
+
+ void processLayer(byte *file, uint32 layer_number);
+ void processImage(BuildUnit *build_unit);
+
+ uint8 _scrollFraction;
+
+ // Last palette used - so that we can restore the correct one after a
+ // pause (which dims the screen) and it's not always the main screen
+ // palette that we want, eg. during the eclipse
+
+ // This flag gets set in startNewPalette() and setFullPalette()
+
+ uint32 _lastPaletteRes;
+
+ // Debugging stuff
+ uint32 _largestLayerArea;
+ uint32 _largestSpriteArea;
+ char _largestLayerInfo[128];
+ char _largestSpriteInfo[128];
+
+ void registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit);
+
+ void mirrorSprite(byte *dst, byte *src, int16 w, int16 h);
+ int32 decompressRLE256(byte *dst, byte *src, int32 decompSize);
+ void unwindRaw16(byte *dst, byte *src, uint8 blockSize, byte *colTable);
+ int32 decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable);
+ void renderParallax(byte *ptr, int16 layer);
+
+ void markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1);
+
+ uint8 _xBlocks[MAXLAYERS];
+ uint8 _yBlocks[MAXLAYERS];
+
+ // An array of sub-blocks, one for each of the parallax layers.
+
+ BlockSurface **_blockSurfaces[MAXLAYERS];
+
+ uint16 _xScale[SCALE_MAXWIDTH];
+ uint16 _yScale[SCALE_MAXHEIGHT];
+
+ void blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect);
+
+ uint16 _layer;
+
+public:
+ Screen(Sword2Engine *vm, int16 width, int16 height);
+ ~Screen();
+
+ int8 getRenderLevel();
+ void setRenderLevel(int8 level);
+
+ byte *getScreen() { return _buffer; }
+ byte *getPalette() { return _palette; }
+ ScreenInfo *getScreenInfo() { return &_thisScreen; }
+
+ int16 getScreenWide() { return _screenWide; }
+ int16 getScreenDeep() { return _screenDeep; }
+
+ uint32 getCurBgp0() { return _curBgp0; }
+ uint32 getCurBgp1() { return _curBgp1; }
+ uint32 getCurBack() { return _curBack; }
+ uint32 getCurSort() { return _curSort; }
+ uint32 getCurFore() { return _curFore; }
+ uint32 getCurFgp0() { return _curFgp0; }
+ uint32 getCurFgp1() { return _curFgp1; }
+
+ uint32 getFps() { return _fps; }
+
+ uint32 getLargestLayerArea() { return _largestLayerArea; }
+ uint32 getLargestSpriteArea() { return _largestSpriteArea; }
+ char *getLargestLayerInfo() { return _largestLayerInfo; }
+ char *getLargestSpriteInfo() { return _largestSpriteInfo; }
+
+ void setNeedFullRedraw();
+
+ void clearScene();
+
+ void resetRenderLists();
+
+ void setLocationMetrics(uint16 w, uint16 h);
+ int32 initialiseBackgroundLayer(byte *parallax);
+ void closeBackgroundLayer();
+
+ void initialiseRenderCycle();
+
+ void initBackground(int32 res, int32 new_palette);
+ void registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega);
+
+ void setScrollFraction(uint8 f) { _scrollFraction = f; }
+ void setScrollTarget(int16 x, int16 y);
+ void setScrolling();
+
+ void setFullPalette(int32 palRes);
+ void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow);
+ uint8 quickMatch(uint8 r, uint8 g, uint8 b);
+ int32 fadeUp(float time = 0.75);
+ int32 fadeDown(float time = 0.75);
+ uint8 getFadeStatus();
+ void dimPalette();
+ void waitForFade();
+ void fadeServer();
+
+ void updateDisplay(bool redrawScene = true);
+
+ void displayMsg(byte *text, int time);
+
+ int32 createSurface(SpriteInfo *s, byte **surface);
+ void drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect = NULL);
+ void deleteSurface(byte *surface);
+ int32 drawSprite(SpriteInfo *s);
+
+ void scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth,
+ uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
+ uint16 srcHeight);
+ void scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth,
+ uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
+ uint16 srcHeight, byte *backbuf);
+
+ void updateRect(Common::Rect *r);
+
+ int32 openLightMask(SpriteInfo *s);
+ int32 closeLightMask();
+
+ void buildDisplay();
+
+ void plotPoint(int x, int y, uint8 colour);
+ void drawLine(int x0, int y0, int x1, int y1, uint8 colour);
+
+#ifdef BACKEND_8BIT
+ void plotYUV(byte *lut, int width, int height, byte *const *dat);
+#endif
+
+ void rollCredits();
+ void splashScreen();
+};
+
+} // End of namespace Sword2
+
+#endif
More information about the Scummvm-git-logs
mailing list