diff options
author | Max Horn | 2006-02-11 22:45:04 +0000 |
---|---|---|
committer | Max Horn | 2006-02-11 22:45:04 +0000 |
commit | 26ee630756ebdd7c96bccede0881a8c8b98e8f2b (patch) | |
tree | 26e378d5cf990a2b81c2c96e9e683a7f333b62e8 /engines/sword2/anims.cpp | |
parent | 2a9a0d4211b1ea5723f1409d91cb95de8984429e (diff) | |
download | scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.gz scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.bz2 scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.zip |
Moved engines to the new engines/ directory
svn-id: r20582
Diffstat (limited to 'engines/sword2/anims.cpp')
-rw-r--r-- | engines/sword2/anims.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/engines/sword2/anims.cpp b/engines/sword2/anims.cpp new file mode 100644 index 0000000000..e64903a61f --- /dev/null +++ b/engines/sword2/anims.cpp @@ -0,0 +1,308 @@ +/* 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$ + */ + +// --------------------------------------------------------------------------- +// A more intelligent version of the old ANIMS.C +// All this stuff by James +// DON'T TOUCH! +// --------------------------------------------------------------------------- + +#include "common/stdafx.h" +#include "common/file.h" + +#include "sword2/sword2.h" +#include "sword2/defs.h" +#include "sword2/build_display.h" +#include "sword2/interpreter.h" +#include "sword2/logic.h" +#include "sword2/maketext.h" +#include "sword2/resman.h" +#include "sword2/router.h" +#include "sword2/sound.h" +#include "sword2/animation.h" + +namespace Sword2 { + +int Router::doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool reverse) { + AnimHeader anim_head; + byte *anim_file; + + ObjectLogic obLogic(ob_logic); + ObjectGraphic obGraph(ob_graph); + + if (obLogic.getLooping() == 0) { + byte *ptr; + + // This is the start of the anim - set up the first frame + + // For testing all anims! + // A script loop can send every resource number to the anim + // function & it will only run the valid ones. See + // 'testing_routines' object in George's Player Character + // section of linc + + if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) { + if (!_vm->_resman->checkValid(animRes)) { + // Not a valid resource number. Switch off + // the sprite. Don't animate - just continue + // script next cycle. + setSpriteStatus(ob_graph, NO_SPRITE); + return IR_STOP; + } + + ptr = _vm->_resman->openResource(animRes); + + // if it's not an animation file + if (_vm->_resman->fetchType(animRes) != ANIMATION_FILE) { + _vm->_resman->closeResource(animRes); + + // switch off the sprite + // don't animate - just continue + // script next cycle + setSpriteStatus(ob_graph, NO_SPRITE); + return IR_STOP; + } + + _vm->_resman->closeResource(animRes); + + // switch on the sprite + setSpriteStatus(ob_graph, SORT_SPRITE); + } + + assert(animRes); + + // open anim file + anim_file = _vm->_resman->openResource(animRes); + + assert(_vm->_resman->fetchType(animRes) == ANIMATION_FILE); + + // point to anim header + anim_head.read(_vm->fetchAnimHeader(anim_file)); + + // now running an anim, looping back to this call again + obLogic.setLooping(1); + obGraph.setAnimResource(animRes); + + if (reverse) + obGraph.setAnimPc(anim_head.noAnimFrames - 1); + else + obGraph.setAnimPc(0); + } else if (_vm->_logic->getSync() != -1) { + // We've received a sync - return to script immediately + debug(5, "**sync stopped %d**", _vm->_logic->readVar(ID)); + + // If sync received, anim finishes right now (remaining on + // last frame). Quit animation, but continue script. + obLogic.setLooping(0); + return IR_CONT; + } else { + // Not first frame, and no sync received - set up the next + // frame of the anim. + + // open anim file and point to anim header + anim_file = _vm->_resman->openResource(obGraph.getAnimResource()); + anim_head.read(_vm->fetchAnimHeader(anim_file)); + + if (reverse) + obGraph.setAnimPc(obGraph.getAnimPc() - 1); + else + obGraph.setAnimPc(obGraph.getAnimPc() + 1); + } + + // check for end of anim + + if (reverse) { + if (obGraph.getAnimPc() == 0) + obLogic.setLooping(0); + } else { + if (obGraph.getAnimPc() == anim_head.noAnimFrames - 1) + obLogic.setLooping(0); + } + + // close the anim file + _vm->_resman->closeResource(obGraph.getAnimResource()); + + // check if we want the script to loop back & call this function again + return obLogic.getLooping() ? IR_REPEAT : IR_STOP; +} + +int Router::megaTableAnimate(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *animTable, bool reverse) { + int32 animRes = 0; + + // If this is the start of the anim, read the anim table to get the + // appropriate anim resource + + ObjectLogic obLogic(ob_logic); + + if (obLogic.getLooping() == 0) { + ObjectMega obMega(ob_mega); + + // Appropriate anim resource is in 'table[direction]' + animRes = READ_LE_UINT32(animTable + 4 * obMega.getCurDir()); + } + + return doAnimate(ob_logic, ob_graph, animRes, reverse); +} + +void Router::setSpriteStatus(byte *ob_graph, uint32 type) { + ObjectGraphic obGraph(ob_graph); + + // Remove the previous status, but don't affect the shading upper-word + obGraph.setType((obGraph.getType() & 0xffff0000) | type); +} + +void Router::setSpriteShading(byte *ob_graph, uint32 type) { + ObjectGraphic obGraph(ob_graph); + + // Remove the previous shading, but don't affect the status lower-word. + // Note that mega frames may still be shaded automatically, even when + // not sent 'RDSPR_SHADOW'. + obGraph.setType((obGraph.getType() & 0x0000ffff) | type); +} + +void Logic::createSequenceSpeech(MovieTextObject *sequenceText[]) { + uint32 line; + uint32 local_text; + uint32 text_res; + byte *text; + uint32 wavId; // ie. offical text number (actor text number) + bool speechRunning; + + // for each sequence text line that's been logged + for (line = 0; line < _sequenceTextLines; line++) { + // allocate this structure + sequenceText[line] = new MovieTextObject; + + sequenceText[line]->startFrame = _sequenceTextList[line].startFrame; + sequenceText[line]->endFrame = _sequenceTextList[line].endFrame; + + // pull out the text line to get the official text number + // (for wav id) + + text_res = _sequenceTextList[line].textNumber / SIZE; + local_text = _sequenceTextList[line].textNumber & 0xffff; + + // open text resource & get the line + text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text); + wavId = (int32)READ_LE_UINT16(text); + + // now ok to close the text file + _vm->_resman->closeResource(text_res); + + // 1st word of text line is the official line number + debug(5,"(%d) SEQUENCE TEXT: %s", READ_LE_UINT16(text), text + 2); + + // is it to be speech or subtitles or both? + // assume speech is not running until know otherwise + + speechRunning = false; + _sequenceTextList[line].speech_mem = NULL; + sequenceText[line]->speech = NULL; + + if (!_vm->_sound->isSpeechMute()) { + _sequenceTextList[line].speechBufferSize = _vm->_sound->preFetchCompSpeech(wavId, &_sequenceTextList[line].speech_mem); + if (_sequenceTextList[line].speechBufferSize) { + // ok, we've got speech! + speechRunning = true; + } + } + + // if we want subtitles, or speech failed to load + + if (_vm->getSubtitles() || !speechRunning) { + // open text resource & get the line + text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text); + // make the sprite + // 'text+2' to skip the first 2 bytes which form the + // line reference number + + // NB. The mem block containing the text sprite is + // currently FLOATING! + + // When rendering text over a sequence we need a + // different colour for the border. + + _sequenceTextList[line].text_mem = _vm->_fontRenderer->makeTextSprite(text + 2, 600, 255, _vm->_speechFontId, 1); + + // ok to close the text resource now + _vm->_resman->closeResource(text_res); + } else { + _sequenceTextList[line].text_mem = NULL; + sequenceText[line]->textSprite = NULL; + } + } + + // for drivers: NULL-terminate the array of pointers to + // MovieTextObject's + sequenceText[_sequenceTextLines] = NULL; + + for (line = 0; line < _sequenceTextLines; line++) { + // if we've made a text sprite for this line... + + if (_sequenceTextList[line].text_mem) { + // now fill out the SpriteInfo structure in the + // MovieTextObjectStructure + FrameHeader frame; + + frame.read(_sequenceTextList[line].text_mem); + + sequenceText[line]->textSprite = new SpriteInfo; + + // center text at bottom of screen + sequenceText[line]->textSprite->x = 320 - frame.width / 2; + sequenceText[line]->textSprite->y = 440 - frame.height; + sequenceText[line]->textSprite->w = frame.width; + sequenceText[line]->textSprite->h = frame.height; + sequenceText[line]->textSprite->type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION; + sequenceText[line]->textSprite->data = _sequenceTextList[line].text_mem + FrameHeader::size(); + } + + // if we've loaded a speech sample for this line... + + if (_sequenceTextList[line].speech_mem) { + // for drivers: set up pointer to decompressed wav in + // memory + + sequenceText[line]->speechBufferSize = _sequenceTextList[line].speechBufferSize; + sequenceText[line]->speech = _sequenceTextList[line].speech_mem; + } + } +} + +void Logic::clearSequenceSpeech(MovieTextObject *sequenceText[]) { + for (uint i = 0; i < _sequenceTextLines; i++) { + // free up the memory used by this MovieTextObject + delete sequenceText[i]; + + // free up the mem block containing this text sprite + if (_sequenceTextList[i].text_mem) + free(_sequenceTextList[i].text_mem); + + // free up the mem block containing this speech sample + if (_sequenceTextList[i].speech_mem) + free(_sequenceTextList[i].speech_mem); + } + + // IMPORTANT! Reset the line count ready for the next sequence! + _sequenceTextLines = 0; +} + +} // End of namespace Sword2 |