aboutsummaryrefslogtreecommitdiff
path: root/sword2
diff options
context:
space:
mode:
authorMax Horn2006-02-11 22:45:04 +0000
committerMax Horn2006-02-11 22:45:04 +0000
commit26ee630756ebdd7c96bccede0881a8c8b98e8f2b (patch)
tree26e378d5cf990a2b81c2c96e9e683a7f333b62e8 /sword2
parent2a9a0d4211b1ea5723f1409d91cb95de8984429e (diff)
downloadscummvm-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 'sword2')
-rw-r--r--sword2/_mouse.cpp247
-rw-r--r--sword2/animation.cpp535
-rw-r--r--sword2/animation.h103
-rw-r--r--sword2/anims.cpp308
-rw-r--r--sword2/build_display.cpp1070
-rw-r--r--sword2/build_display.h441
-rw-r--r--sword2/console.cpp826
-rw-r--r--sword2/console.h127
-rw-r--r--sword2/controls.cpp1416
-rw-r--r--sword2/controls.h183
-rw-r--r--sword2/d_draw.cpp71
-rw-r--r--sword2/debug.cpp377
-rw-r--r--sword2/debug.h33
-rw-r--r--sword2/defs.h205
-rw-r--r--sword2/events.cpp99
-rw-r--r--sword2/function.cpp2479
-rw-r--r--sword2/header.h502
-rw-r--r--sword2/icons.cpp216
-rw-r--r--sword2/icons.h41
-rw-r--r--sword2/interpreter.cpp753
-rw-r--r--sword2/interpreter.h96
-rw-r--r--sword2/layers.cpp191
-rw-r--r--sword2/layers.h29
-rw-r--r--sword2/logic.cpp267
-rw-r--r--sword2/logic.h316
-rw-r--r--sword2/maketext.cpp579
-rw-r--r--sword2/maketext.h119
-rw-r--r--sword2/memory.cpp244
-rw-r--r--sword2/memory.h70
-rw-r--r--sword2/menu.cpp291
-rw-r--r--sword2/module.mk48
-rw-r--r--sword2/mouse.cpp1437
-rw-r--r--sword2/mouse.h257
-rw-r--r--sword2/music.cpp856
-rw-r--r--sword2/object.h342
-rw-r--r--sword2/palette.cpp267
-rw-r--r--sword2/protocol.cpp216
-rw-r--r--sword2/rdwin.cpp118
-rw-r--r--sword2/render.cpp584
-rw-r--r--sword2/resman.cpp633
-rw-r--r--sword2/resman.h134
-rw-r--r--sword2/router.cpp2506
-rw-r--r--sword2/router.h255
-rw-r--r--sword2/save_rest.cpp414
-rw-r--r--sword2/save_rest.h47
-rw-r--r--sword2/scroll.cpp151
-rw-r--r--sword2/sound.cpp319
-rw-r--r--sword2/sound.h272
-rw-r--r--sword2/speech.cpp229
-rw-r--r--sword2/sprite.cpp655
-rw-r--r--sword2/startup.cpp173
-rw-r--r--sword2/sword2.cpp689
-rw-r--r--sword2/sword2.h240
-rw-r--r--sword2/sync.cpp76
-rw-r--r--sword2/walker.cpp454
55 files changed, 0 insertions, 23606 deletions
diff --git a/sword2/_mouse.cpp b/sword2/_mouse.cpp
deleted file mode 100644
index db0cf00f73..0000000000
--- a/sword2/_mouse.cpp
+++ /dev/null
@@ -1,247 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/system.h"
-#include "common/stream.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/mouse.h"
-
-namespace Sword2 {
-
-// This is the maximum mouse cursor size in the SDL backend
-#define MAX_MOUSE_W 80
-#define MAX_MOUSE_H 80
-
-#define MOUSEFLASHFRAME 6
-
-void Mouse::decompressMouse(byte *decomp, byte *comp, uint8 frame, int width, int height, int pitch, int xOff, int yOff) {
- int32 size = width * height;
- int32 i = 0;
- int x = 0;
- int y = 0;
-
- comp = comp + READ_LE_UINT32(comp + frame * 4) - MOUSE_ANIM_HEADER_SIZE;
-
- while (i < size) {
- if (*comp > 183) {
- decomp[(y + yOff) * pitch + x + xOff] = *comp++;
- if (++x >= width) {
- x = 0;
- y++;
- }
- i++;
- } else {
- x += *comp;
- while (x >= width) {
- y++;
- x -= width;
- }
- i += *comp++;
- }
- }
-}
-
-void Mouse::drawMouse() {
- byte mouseData[MAX_MOUSE_W * MAX_MOUSE_H];
-
- if (!_mouseAnim.data && !_luggageAnim.data)
- return;
-
- // When an object is used in the game, the mouse cursor should be a
- // combination of a standard mouse cursor and a luggage cursor.
- //
- // However, judging by the original code luggage cursors can also
- // appear on their own. I have no idea which cases though.
-
- uint16 mouse_width = 0;
- uint16 mouse_height = 0;
- uint16 hotspot_x = 0;
- uint16 hotspot_y = 0;
- int deltaX = 0;
- int deltaY = 0;
-
- if (_mouseAnim.data) {
- hotspot_x = _mouseAnim.xHotSpot;
- hotspot_y = _mouseAnim.yHotSpot;
- mouse_width = _mouseAnim.mousew;
- mouse_height = _mouseAnim.mouseh;
- }
-
- if (_luggageAnim.data) {
- if (!_mouseAnim.data) {
- hotspot_x = _luggageAnim.xHotSpot;
- hotspot_y = _luggageAnim.yHotSpot;
- }
- if (_luggageAnim.mousew > mouse_width)
- mouse_width = _luggageAnim.mousew;
- if (_luggageAnim.mouseh > mouse_height)
- mouse_height = _luggageAnim.mouseh;
- }
-
- if (_mouseAnim.data && _luggageAnim.data) {
- deltaX = _mouseAnim.xHotSpot - _luggageAnim.xHotSpot;
- deltaY = _mouseAnim.yHotSpot - _luggageAnim.yHotSpot;
- }
-
- assert(deltaX >= 0);
- assert(deltaY >= 0);
-
- // HACK for maximum cursor size. (The SDL backend imposes this
- // restriction)
-
- if (mouse_width + deltaX > MAX_MOUSE_W)
- deltaX = 80 - mouse_width;
- if (mouse_height + deltaY > MAX_MOUSE_H)
- deltaY = 80 - mouse_height;
-
- mouse_width += deltaX;
- mouse_height += deltaY;
-
- if ((uint32)(mouse_width * mouse_height) > sizeof(mouseData)) {
- warning("Mouse cursor too large");
- return;
- }
-
- memset(mouseData, 0, mouse_width * mouse_height);
-
- if (_luggageAnim.data)
- decompressMouse(mouseData, _luggageAnim.data, 0,
- _luggageAnim.mousew, _luggageAnim.mouseh,
- mouse_width, deltaX, deltaY);
-
- if (_mouseAnim.data)
- decompressMouse(mouseData, _mouseAnim.data, _mouseFrame,
- _mouseAnim.mousew, _mouseAnim.mouseh, mouse_width);
-
- _vm->_system->setMouseCursor(mouseData, mouse_width, mouse_height, hotspot_x, hotspot_y, 0);
-}
-
-/**
- * Animates the current mouse pointer
- */
-
-int32 Mouse::animateMouse() {
- uint8 prevMouseFrame = _mouseFrame;
-
- if (!_mouseAnim.data)
- return RDERR_UNKNOWN;
-
- if (++_mouseFrame == _mouseAnim.noAnimFrames)
- _mouseFrame = MOUSEFLASHFRAME;
-
- if (_mouseFrame != prevMouseFrame)
- drawMouse();
-
- return RD_OK;
-}
-
-/**
- * Sets the mouse cursor animation.
- * @param ma a pointer to the animation data, or NULL to clear the current one
- * @param size the size of the mouse animation data
- * @param mouseFlash RDMOUSE_FLASH or RDMOUSE_NOFLASH, depending on whether
- * or not there is a lead-in animation
- */
-
-int32 Mouse::setMouseAnim(byte *ma, int32 size, int32 mouseFlash) {
- free(_mouseAnim.data);
- _mouseAnim.data = NULL;
-
- if (ma) {
- if (mouseFlash == RDMOUSE_FLASH)
- _mouseFrame = 0;
- else
- _mouseFrame = MOUSEFLASHFRAME;
-
- Common::MemoryReadStream readS(ma, size);
-
- _mouseAnim.runTimeComp = readS.readByte();
- _mouseAnim.noAnimFrames = readS.readByte();
- _mouseAnim.xHotSpot = readS.readSByte();
- _mouseAnim.yHotSpot = readS.readSByte();
- _mouseAnim.mousew = readS.readByte();
- _mouseAnim.mouseh = readS.readByte();
-
- _mouseAnim.data = (byte *)malloc(size - MOUSE_ANIM_HEADER_SIZE);
- if (!_mouseAnim.data)
- return RDERR_OUTOFMEMORY;
-
- readS.read(_mouseAnim.data, size - MOUSE_ANIM_HEADER_SIZE);
-
- animateMouse();
- drawMouse();
-
- _vm->_system->showMouse(true);
- } else {
- if (_luggageAnim.data)
- drawMouse();
- else
- _vm->_system->showMouse(false);
- }
-
- return RD_OK;
-}
-
-/**
- * Sets the "luggage" animation to accompany the mouse animation. Luggage
- * sprites are of the same format as mouse sprites.
- * @param ma a pointer to the animation data, or NULL to clear the current one
- * @param size the size of the animation data
- */
-
-int32 Mouse::setLuggageAnim(byte *ma, int32 size) {
- free(_luggageAnim.data);
- _luggageAnim.data = NULL;
-
- if (ma) {
- Common::MemoryReadStream readS(ma, size);
-
- _luggageAnim.runTimeComp = readS.readByte();
- _luggageAnim.noAnimFrames = readS.readByte();
- _luggageAnim.xHotSpot = readS.readSByte();
- _luggageAnim.yHotSpot = readS.readSByte();
- _luggageAnim.mousew = readS.readByte();
- _luggageAnim.mouseh = readS.readByte();
-
- _luggageAnim.data = (byte *)malloc(size - MOUSE_ANIM_HEADER_SIZE);
- if (!_luggageAnim.data)
- return RDERR_OUTOFMEMORY;
-
- readS.read(_luggageAnim.data, size - MOUSE_ANIM_HEADER_SIZE);
-
- animateMouse();
- drawMouse();
-
- _vm->_system->showMouse(true);
- } else {
- if (_mouseAnim.data)
- drawMouse();
- else
- _vm->_system->showMouse(false);
- }
-
- return RD_OK;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/animation.cpp b/sword2/animation.cpp
deleted file mode 100644
index 2ba5df6792..0000000000
--- a/sword2/animation.cpp
+++ /dev/null
@@ -1,535 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/file.h"
-#include "common/config-manager.h"
-#include "common/system.h"
-#include "sound/vorbis.h"
-#include "sound/mp3.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/maketext.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-#include "sword2/animation.h"
-
-namespace Sword2 {
-
-AnimationState::AnimationState(Sword2Engine *vm)
- : BaseAnimationState(vm->_mixer, vm->_system, 640, 480), _vm(vm) {
-}
-
-AnimationState::~AnimationState() {
-}
-
-#ifdef BACKEND_8BIT
-
-void AnimationState::setPalette(byte *pal) {
- _vm->_screen->setPalette(0, 256, pal, RDPAL_INSTANT);
-}
-
-#else
-
-void AnimationState::drawTextObject(SpriteInfo *s, byte *src) {
- OverlayColor *dst = _overlay + RENDERWIDE * s->y + s->x;
-
- // FIXME: These aren't the "right" colours, but look good to me.
-
- OverlayColor pen = _sys->RGBToColor(255, 255, 255);
- OverlayColor border = _sys->RGBToColor(0, 0, 0);
-
- for (int y = 0; y < s->h; y++) {
- for (int x = 0; x < s->w; x++) {
- switch (src[x]) {
- case 1:
- dst[x] = border;
- break;
- case 255:
- dst[x] = pen;
- break;
- default:
- break;
- }
- }
- dst += RENDERWIDE;
- src += s->w;
- }
-}
-
-#endif
-
-void AnimationState::clearScreen() {
-#ifdef BACKEND_8BIT
- memset(_vm->_screen->getScreen(), 0, _movieWidth * _movieHeight);
-#else
- OverlayColor black = _sys->RGBToColor(0, 0, 0);
-
- for (int i = 0; i < _movieWidth * _movieHeight; i++)
- _overlay[i] = black;
-#endif
-}
-
-void AnimationState::updateScreen() {
-#ifdef BACKEND_8BIT
- byte *buf = _vm->_screen->getScreen() + ((480 - _movieHeight) / 2) * RENDERWIDE + (640 - _movieWidth) / 2;
-
- _vm->_system->copyRectToScreen(buf, _movieWidth, (640 - _movieWidth) / 2, (480 - _movieHeight) / 2, _movieWidth, _movieHeight);
-#else
- _sys->copyRectToOverlay(_overlay, _movieWidth, 0, 0, _movieWidth, _movieHeight);
-#endif
- _vm->_system->updateScreen();
-}
-
-void AnimationState::drawYUV(int width, int height, byte *const *dat) {
-#ifdef BACKEND_8BIT
- _vm->_screen->plotYUV(_lut, width, height, dat);
-#else
- plotYUV(width, height, dat);
-#endif
-}
-
-MovieInfo MoviePlayer::_movies[] = {
- { "carib", 222, false },
- { "escape", 187, false },
- { "eye", 248, false },
- { "finale", 1485, false },
- { "guard", 75, false },
- { "intro", 1800, false },
- { "jungle", 186, false },
- { "museum", 167, false },
- { "pablo", 75, false },
- { "pyramid", 60, false },
- { "quaram", 184, false },
- { "river", 656, false },
- { "sailing", 138, false },
- { "shaman", 788, true },
- { "stone1", 34, false },
- { "stone2", 282, false },
- { "stone3", 65, false },
- { "demo", 60, false },
- { "enddemo", 110, false }
-};
-
-MoviePlayer::MoviePlayer(Sword2Engine *vm)
- : _vm(vm), _snd(_vm->_mixer), _sys(_vm->_system), _textSurface(NULL) {
-}
-
-void MoviePlayer::openTextObject(MovieTextObject *obj) {
- if (obj->textSprite)
- _vm->_screen->createSurface(obj->textSprite, &_textSurface);
-}
-
-void MoviePlayer::closeTextObject(MovieTextObject *obj) {
- if (_textSurface) {
- _vm->_screen->deleteSurface(_textSurface);
- _textSurface = NULL;
- }
-}
-
-void MoviePlayer::drawTextObject(AnimationState *anim, MovieTextObject *obj) {
- if (obj->textSprite && _textSurface) {
-#ifdef BACKEND_8BIT
- _vm->_screen->drawSurface(obj->textSprite, _textSurface);
-#else
- if (anim)
- anim->drawTextObject(obj->textSprite, _textSurface);
- else
- _vm->_screen->drawSurface(obj->textSprite, _textSurface);
-#endif
- }
-}
-
-/**
- * Plays an animated cutscene.
- * @param filename the file name of the cutscene file
- * @param text the subtitles and voiceovers for the cutscene
- * @param leadInRes lead-in music resource id
- * @param leadOutRes lead-out music resource id
- */
-
-int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], int32 leadInRes, int32 leadOutRes) {
- Audio::SoundHandle leadInHandle;
-
- // This happens if the user quits during the "eye" smacker
- if (_vm->_quit)
- return RD_OK;
-
- if (leadInRes) {
- byte *leadIn = _vm->_resman->openResource(leadInRes);
- uint32 leadInLen = _vm->_resman->fetchLen(leadInRes) - ResHeader::size();
-
- assert(_vm->_resman->fetchType(leadIn) == WAV_FILE);
-
- leadIn += ResHeader::size();
-
- _vm->_sound->playFx(&leadInHandle, leadIn, leadInLen, Audio::Mixer::kMaxChannelVolume, 0, false, Audio::Mixer::kMusicSoundType);
- }
-
- byte *leadOut = NULL;
- uint32 leadOutLen = 0;
-
- if (leadOutRes) {
- leadOut = _vm->_resman->openResource(leadOutRes);
- leadOutLen = _vm->_resman->fetchLen(leadOutRes) - ResHeader::size();
-
- assert(_vm->_resman->fetchType(leadOut) == WAV_FILE);
-
- leadOut += ResHeader::size();
- }
-
- _leadOutFrame = (uint)-1;
-
- int i;
-
- for (i = 0; i < ARRAYSIZE(_movies); i++) {
- if (scumm_stricmp(filename, _movies[i].name) == 0) {
- _seamless = _movies[i].seamless;
- if (_movies[i].frames > 60)
- _leadOutFrame = _movies[i].frames - 60;
- break;
- }
- }
-
- if (i == ARRAYSIZE(_movies))
- warning("Unknown movie, '%s'", filename);
-
-#ifdef USE_MPEG2
- playMPEG(filename, text, leadOut, leadOutLen);
-#else
- // No MPEG2? Use the old 'Narration Only' hack
- playDummy(filename, text, leadOut, leadOutLen);
-#endif
-
- _snd->stopHandle(leadInHandle);
-
- // Wait for the lead-out to stop, if there is any. Though don't do it
- // for seamless movies, since they are meant to blend into the rest of
- // the game.
-
- if (!_seamless) {
- while (_vm->_mixer->isSoundHandleActive(_leadOutHandle)) {
- _vm->_screen->updateDisplay();
- _vm->_system->delayMillis(30);
- }
- }
-
- if (leadInRes)
- _vm->_resman->closeResource(leadInRes);
-
- if (leadOutRes)
- _vm->_resman->closeResource(leadOutRes);
-
- return RD_OK;
-}
-
-void MoviePlayer::playMPEG(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen) {
- uint frameCounter = 0, textCounter = 0;
- Audio::SoundHandle handle;
- bool skipCutscene = false, textVisible = false;
- uint32 flags = Audio::Mixer::FLAG_16BITS;
- bool startNextText = false;
-
- byte oldPal[256 * 4];
- memcpy(oldPal, _vm->_screen->getPalette(), sizeof(oldPal));
-
- AnimationState *anim = new AnimationState(_vm);
-
- if (!anim->init(filename)) {
- delete anim;
- // Missing Files? Use the old 'Narration Only' hack
- playDummy(filename, text, leadOut, leadOutLen);
- return;
- }
-
- // Clear the screen, because whatever is on it will be visible when the
- // overlay is removed. And if there isn't an overlay, we don't want it
- // to be visible during the cutscene. (Not all cutscenes cover the
- // entire screen.)
- _vm->_screen->clearScene();
- _vm->_screen->updateDisplay();
-
-#ifndef SCUMM_BIG_ENDIAN
- flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
-#endif
-
- while (!skipCutscene && anim->decodeFrame()) {
- // The frame has been drawn. Now draw the subtitles, if any,
- // before updating the screen.
-
- if (text && text[textCounter]) {
- if (frameCounter == text[textCounter]->startFrame) {
- openTextObject(text[textCounter]);
- textVisible = true;
-
- if (text[textCounter]->speech) {
- startNextText = true;
- }
- }
-
- if (startNextText && !_snd->isSoundHandleActive(handle)) {
- _snd->playRaw(&handle, text[textCounter]->speech, text[textCounter]->speechBufferSize, 22050, flags);
- startNextText = false;
- }
-
- if (frameCounter == text[textCounter]->endFrame) {
- closeTextObject(text[textCounter]);
- textCounter++;
- textVisible = false;
- }
-
- if (textVisible)
- drawTextObject(anim, text[textCounter]);
- }
-
- anim->updateScreen();
- frameCounter++;
-
- if (frameCounter == _leadOutFrame && leadOut)
- _vm->_sound->playFx(&_leadOutHandle, leadOut, leadOutLen, Audio::Mixer::kMaxChannelVolume, 0, false, Audio::Mixer::kMusicSoundType);
-
- OSystem::Event event;
- while (_sys->pollEvent(event)) {
- switch (event.type) {
-#ifndef BACKEND_8BIT
- case OSystem::EVENT_SCREEN_CHANGED:
- anim->buildLookup();
- break;
-#endif
- case OSystem::EVENT_KEYDOWN:
- if (event.kbd.keycode == 27)
- skipCutscene = true;
- break;
- case OSystem::EVENT_QUIT:
- _vm->closeGame();
- skipCutscene = true;
- break;
- default:
- break;
- }
- }
- }
-
- if (!skipCutscene) {
- // Sleep for one frame so that the last frame is displayed.
- _sys->delayMillis(1000 / 12);
- }
-
- if (!_seamless) {
- // Most movies fade to black on their own, but not all of them.
- // Since we may be hanging around in the cutscene player for a
- // while longer, waiting for the lead-out sound to finish,
- // paint the overlay black.
-
- anim->clearScreen();
- }
-
- // If the speech is still playing, redraw the subtitles. At least in
- // the English version this is most noticeable in the "carib" cutscene.
-
- if (textVisible && _snd->isSoundHandleActive(handle))
- drawTextObject(anim, text[textCounter]);
-
- if (text)
- closeTextObject(text[textCounter]);
-
- anim->updateScreen();
-
- // Wait for the voice to stop playing. This is to make sure that we
- // don't cut off the speech in mid-sentence, and - even more
- // importantly - that we don't free the sound buffer while it's in use.
-
- if (skipCutscene)
- _snd->stopHandle(handle);
-
- while (_snd->isSoundHandleActive(handle)) {
- _vm->_screen->updateDisplay(false);
- _sys->delayMillis(100);
- }
-
- if (!_seamless) {
- // Clear the screen again
- anim->clearScreen();
- anim->updateScreen();
- }
-
- _vm->_screen->setPalette(0, 256, oldPal, RDPAL_INSTANT);
-
- delete anim;
-}
-
-/**
- * This just plays the cutscene with voiceovers / subtitles, in case the files
- * are missing.
- */
-
-void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen) {
- if (!text)
- return;
-
- int frameCounter = 0, textCounter = 0;
-
- byte oldPal[256 * 4];
- byte tmpPal[256 * 4];
-
- _vm->_screen->clearScene();
-
- // HACK: Draw instructions
- //
- // I'm using the the menu area, because that's unlikely to be touched
- // by anything else during the cutscene.
-
- memset(_vm->_screen->getScreen(), 0, _vm->_screen->getScreenWide() * MENUDEEP);
-
- byte *data;
-
- // Russian version substituted latin characters with cyrillic. That's
- // why it renders completely unreadable with default message
- if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) {
- byte msg[] = "Po\344uk - to\344\345ko pev\345: hagmute k\344abuwy Ucke\343n, u\344u nocetute ca\343t npoekta u ckava\343te budeo po\344uku";
- data = _vm->_fontRenderer->makeTextSprite(msg, RENDERWIDE, 255, _vm->_speechFontId);
- } else {
- // TODO: Translate message to other languages?
-#ifdef USE_MPEG2
- byte msg[] = "Cutscene - Narration Only: Press ESC to exit, or visit www.scummvm.org to download cutscene videos";
-#else
- byte msg[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with MPEG2 support";
-#endif
-
- data = _vm->_fontRenderer->makeTextSprite(msg, RENDERWIDE, 255, _vm->_speechFontId);
- }
-
- FrameHeader frame_head;
- SpriteInfo msgSprite;
- byte *msgSurface;
-
- frame_head.read(data);
-
- msgSprite.x = _vm->_screen->getScreenWide() / 2 - frame_head.width / 2;
- msgSprite.y = MENUDEEP / 2 - frame_head.height / 2;
- msgSprite.w = frame_head.width;
- msgSprite.h = frame_head.height;
- msgSprite.type = RDSPR_NOCOMPRESSION;
- msgSprite.data = data + FrameHeader::size();
-
- _vm->_screen->createSurface(&msgSprite, &msgSurface);
- _vm->_screen->drawSurface(&msgSprite, msgSurface);
- _vm->_screen->deleteSurface(msgSurface);
-
- free(data);
-
- // In case the cutscene has a long lead-in, start just before the first
- // line of text.
-
- frameCounter = text[0]->startFrame - 12;
-
- // Fake a palette that will hopefully make the text visible. In the
- // opening cutscene it seems to use colours 1 (black) and 255 (white).
-
- memcpy(oldPal, _vm->_screen->getPalette(), sizeof(oldPal));
- memset(tmpPal, 0, sizeof(tmpPal));
- tmpPal[255 * 4 + 0] = 255;
- tmpPal[255 * 4 + 1] = 255;
- tmpPal[255 * 4 + 2] = 255;
- _vm->_screen->setPalette(0, 256, tmpPal, RDPAL_INSTANT);
-
- Audio::SoundHandle handle;
-
- bool skipCutscene = false;
-
- uint32 flags = Audio::Mixer::FLAG_16BITS;
-
-#ifndef SCUMM_BIG_ENDIAN
- flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
-#endif
-
- while (1) {
- if (!text[textCounter])
- break;
-
- if (frameCounter == text[textCounter]->startFrame) {
- _vm->_screen->clearScene();
- openTextObject(text[textCounter]);
- drawTextObject(NULL, text[textCounter]);
- if (text[textCounter]->speech) {
- _snd->playRaw(&handle, text[textCounter]->speech, text[textCounter]->speechBufferSize, 22050, flags);
- }
- }
-
- if (frameCounter == text[textCounter]->endFrame) {
- closeTextObject(text[textCounter]);
- _vm->_screen->clearScene();
- _vm->_screen->setNeedFullRedraw();
- textCounter++;
- }
-
- frameCounter++;
- _vm->_screen->updateDisplay();
-
- KeyboardEvent *ke = _vm->keyboardEvent();
-
- if ((ke && ke->keycode == 27) || _vm->_quit) {
- _snd->stopHandle(handle);
- skipCutscene = true;
- break;
- }
-
- // Simulate ~12 frames per second. I don't know what frame rate
- // the original movies had, or even if it was constant, but
- // this seems to work reasonably.
-
- _sys->delayMillis(90);
- }
-
- // Wait for the voice to stop playing. This is to make sure that we
- // don't cut off the speech in mid-sentence, and - even more
- // importantly - that we don't free the sound buffer while it's in use.
-
- while (_snd->isSoundHandleActive(handle)) {
- _vm->_screen->updateDisplay(false);
- _sys->delayMillis(100);
- }
-
- closeTextObject(text[textCounter]);
-
- _vm->_screen->clearScene();
- _vm->_screen->setNeedFullRedraw();
-
- // HACK: Remove the instructions created above
- Common::Rect r;
-
- memset(_vm->_screen->getScreen(), 0, _vm->_screen->getScreenWide() * MENUDEEP);
- r.left = r.top = 0;
- r.right = _vm->_screen->getScreenWide();
- r.bottom = MENUDEEP;
- _vm->_screen->updateRect(&r);
-
- // FIXME: For now, only play the lead-out music for cutscenes that have
- // subtitles.
-
- if (!skipCutscene && leadOut)
- _vm->_sound->playFx(&_leadOutHandle, leadOut, leadOutLen, Audio::Mixer::kMaxChannelVolume, 0, false, Audio::Mixer::kMusicSoundType);
-
- _vm->_screen->setPalette(0, 256, oldPal, RDPAL_INSTANT);
-}
-
-} // End of namespace Sword2
diff --git a/sword2/animation.h b/sword2/animation.h
deleted file mode 100644
index e3a554ccd7..0000000000
--- a/sword2/animation.h
+++ /dev/null
@@ -1,103 +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 ANIMATION_H
-#define ANIMATION_H
-
-#include "graphics/animation.h"
-#include "sound/mixer.h"
-
-namespace Sword2 {
-
-struct SpriteInfo;
-
-// This is the structure which is passed to the sequence player. It includes
-// the smack to play, and any text lines which are to be displayed over the top
-// of the sequence.
-
-struct MovieTextObject {
- uint16 startFrame;
- uint16 endFrame;
- SpriteInfo *textSprite;
- uint32 speechBufferSize;
- uint16 *speech;
-};
-
-class AnimationState : public ::Graphics::BaseAnimationState {
-private:
- Sword2Engine *_vm;
-
-public:
- AnimationState(Sword2Engine *vm);
- ~AnimationState();
-
-#ifndef BACKEND_8BIT
- void drawTextObject(SpriteInfo *s, byte *src);
-#endif
-
- void clearScreen();
- void updateScreen();
-
-private:
- void drawYUV(int width, int height, byte *const *dat);
-
-#ifdef BACKEND_8BIT
- void setPalette(byte *pal);
-#endif
-};
-
-struct MovieInfo {
- char name[9];
- uint frames;
- bool seamless;
-};
-
-class MoviePlayer {
-private:
- Sword2Engine *_vm;
- Audio::Mixer *_snd;
- OSystem *_sys;
-
- byte *_textSurface;
-
- Audio::SoundHandle _leadOutHandle;
-
- uint _leadOutFrame;
- bool _seamless;
-
- static struct MovieInfo _movies[];
-
- void openTextObject(MovieTextObject *obj);
- void closeTextObject(MovieTextObject *obj);
- void drawTextObject(AnimationState *anim, MovieTextObject *obj);
-
- void playMPEG(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen);
- void playDummy(const char *filename, MovieTextObject *text[], byte *leadOut, uint32 leadOutLen);
-
-public:
- MoviePlayer(Sword2Engine *vm);
- int32 play(const char *filename, MovieTextObject *text[], int32 leadInRes, int32 leadOutRes);
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/anims.cpp b/sword2/anims.cpp
deleted file mode 100644
index e64903a61f..0000000000
--- a/sword2/anims.cpp
+++ /dev/null
@@ -1,308 +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$
- */
-
-// ---------------------------------------------------------------------------
-// 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
diff --git a/sword2/build_display.cpp b/sword2/build_display.cpp
deleted file mode 100644
index bc5a31a1f9..0000000000
--- a/sword2/build_display.cpp
+++ /dev/null
@@ -1,1070 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-2006 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-// ---------------------------------------------------------------------------
-// BUILD_DISPLAY.CPP like the old spr_engi but slightly more aptly named
-// ---------------------------------------------------------------------------
-
-#include "common/stdafx.h"
-#include "common/system.h"
-
-#include "sword2/sword2.h"
-#include "sword2/console.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-namespace Sword2 {
-
-Screen::Screen(Sword2Engine *vm, int16 width, int16 height) {
- _vm = vm;
-
- _dirtyGrid = _buffer = NULL;
-
- _vm->_system->initSize(width, height);
-
- _screenWide = width;
- _screenDeep = height;
-
- _gridWide = width / CELLWIDE;
- _gridDeep = height / CELLDEEP;
-
- if ((width % CELLWIDE) || (height % CELLDEEP))
- error("Bad cell size");
-
- _dirtyGrid = (byte *)calloc(_gridWide, _gridDeep);
- if (!_dirtyGrid)
- error("Could not initialise dirty grid");
-
- _buffer = (byte *)malloc(width * height);
- if (!_buffer)
- error("Could not initialise display");
-
- for (int i = 0; i < ARRAYSIZE(_blockSurfaces); i++)
- _blockSurfaces[i] = NULL;
-
- _lightMask = NULL;
- _needFullRedraw = false;
-
- memset(&_thisScreen, 0, sizeof(_thisScreen));
-
- _fps = 0;
- _frameCount = 0;
- _cycleTime = 0;
-
- _lastPaletteRes = 0;
-
- _scrollFraction = 16;
-
- _largestLayerArea = 0;
- _largestSpriteArea = 0;
-
- strcpy(_largestLayerInfo, "largest layer: none registered");
- strcpy(_largestSpriteInfo, "largest sprite: none registered");
-
- _fadeStatus = RDFADE_NONE;
- _renderAverageTime = 60;
-
- _layer = 0;
-}
-
-Screen::~Screen() {
- free(_buffer);
- free(_dirtyGrid);
- closeBackgroundLayer();
- free(_lightMask);
-}
-
-void Screen::buildDisplay() {
- if (_thisScreen.new_palette) {
- // start the layer palette fading up
- startNewPalette();
-
- // should be reset to zero at start of each screen change
- _largestLayerArea = 0;
- _largestSpriteArea = 0;
- }
-
- // Does this ever happen?
- if (!_thisScreen.background_layer_id)
- return;
-
- // there is a valid screen to run
-
- setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y);
- _vm->_mouse->animateMouse();
- startRenderCycle();
-
- byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
-
- MultiScreenHeader screenLayerTable;
-
- screenLayerTable.read(file + ResHeader::size());
-
- // Render at least one frame, but if the screen is scrolling, and if
- // there is time left, we will render extra frames to smooth out the
- // scrolling.
-
- do {
- // first background parallax + related anims
- if (screenLayerTable.bg_parallax[0]) {
- renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0);
- drawBackPar0Frames();
- }
-
- // second background parallax + related anims
- if (screenLayerTable.bg_parallax[1]) {
- renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1);
- drawBackPar1Frames();
- }
-
- // normal backround layer (just the one!)
- renderParallax(_vm->fetchBackgroundLayer(file), 2);
-
- // sprites & layers
- drawBackFrames(); // background sprites
- drawSortFrames(file); // sorted sprites & layers
- drawForeFrames(); // foreground sprites
-
- // first foreground parallax + related anims
-
- if (screenLayerTable.fg_parallax[0]) {
- renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3);
- drawForePar0Frames();
- }
-
- // second foreground parallax + related anims
-
- if (screenLayerTable.fg_parallax[1]) {
- renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4);
- drawForePar1Frames();
- }
-
- _vm->_debugger->drawDebugGraphics();
- _vm->_fontRenderer->printTextBlocs();
- _vm->_mouse->processMenu();
-
- updateDisplay();
-
- _frameCount++;
- if (_vm->getMillis() > _cycleTime) {
- _fps = _frameCount;
- _frameCount = 0;
- _cycleTime = _vm->getMillis() + 1000;
- }
- } while (!endRenderCycle());
-
- _vm->_resman->closeResource(_thisScreen.background_layer_id);
-}
-
-/**
- * Fades down and displays a message on the screen.
- * @param text The message
- * @param time The number of seconds to display the message, or 0 to display it
- * until the user clicks the mouse or presses a key.
- */
-
-void Screen::displayMsg(byte *text, int time) {
- byte pal[256 * 4];
- byte oldPal[256 * 4];
-
- debug(2, "DisplayMsg: %s", text);
-
- if (getFadeStatus() != RDFADE_BLACK) {
- fadeDown();
- waitForFade();
- }
-
- _vm->_mouse->setMouse(0);
- _vm->_mouse->setLuggage(0);
- _vm->_mouse->closeMenuImmediately();
-
- clearScene();
-
- byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId);
-
- FrameHeader frame;
-
- frame.read(text_spr);
-
- SpriteInfo spriteInfo;
-
- spriteInfo.x = _screenWide / 2 - frame.width / 2;
- if (!time)
- spriteInfo.y = _screenDeep / 2 - frame.height / 2 - MENUDEEP;
- else
- spriteInfo.y = 400 - frame.height;
- spriteInfo.w = frame.width;
- spriteInfo.h = frame.height;
- spriteInfo.scale = 0;
- spriteInfo.scaledWidth = 0;
- spriteInfo.scaledHeight = 0;
- spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
- spriteInfo.blend = 0;
- spriteInfo.data = text_spr + FrameHeader::size();
- spriteInfo.colourTable = 0;
-
- uint32 rv = drawSprite(&spriteInfo);
- if (rv)
- error("Driver Error %.8x (in DisplayMsg)", rv);
-
- memcpy(oldPal, _palette, sizeof(oldPal));
- memset(pal, 0, sizeof(pal));
-
- pal[187 * 4 + 0] = 255;
- pal[187 * 4 + 1] = 255;
- pal[187 * 4 + 2] = 255;
-
- setPalette(0, 256, pal, RDPAL_FADE);
- fadeUp();
- free(text_spr);
- waitForFade();
-
- if (time > 0) {
- uint32 targetTime = _vm->getMillis() + (time * 1000);
- _vm->sleepUntil(targetTime);
- } else {
- while (!_vm->_quit) {
- MouseEvent *me = _vm->mouseEvent();
- if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)))
- break;
-
- if (_vm->keyboardEvent())
- break;
-
- updateDisplay();
- _vm->_system->delayMillis(50);
- }
- }
-
- fadeDown();
- waitForFade();
- clearScene();
- setPalette(0, 256, oldPal, RDPAL_FADE);
- fadeUp();
-}
-
-void Screen::drawBackPar0Frames() {
- // frame attached to 1st background parallax
- for (uint i = 0; i < _curBgp0; i++)
- processImage(&_bgp0List[i]);
-}
-
-void Screen::drawBackPar1Frames() {
- // frame attached to 2nd background parallax
- for (uint i = 0; i < _curBgp1; i++)
- processImage(&_bgp1List[i]);
-}
-
-void Screen::drawBackFrames() {
- // background sprite, fixed to main background
- for (uint i = 0; i < _curBack; i++)
- processImage(&_backList[i]);
-}
-
-void Screen::drawSortFrames(byte *file) {
- uint i, j;
-
- // Sort the sort list. Used to be a separate function, but it was only
- // called once, right before calling drawSortFrames().
-
- if (_curSort > 1) {
- for (i = 0; i < _curSort - 1; i++) {
- for (j = 0; j < _curSort - 1; j++) {
- if (_sortList[_sortOrder[j]].sort_y > _sortList[_sortOrder[j + 1]].sort_y) {
- SWAP(_sortOrder[j], _sortOrder[j + 1]);
- }
- }
- }
- }
-
- // Draw the sorted frames - layers, shrinkers & normal flat sprites
-
- for (i = 0; i < _curSort; i++) {
- if (_sortList[_sortOrder[i]].layer_number) {
- // it's a layer - minus 1 for true layer number
- // we need to know from the BuildUnit because the
- // layers will have been sorted in random order
- processLayer(file, _sortList[_sortOrder[i]].layer_number - 1);
- } else {
- // it's a sprite
- processImage(&_sortList[_sortOrder[i]]);
- }
- }
-}
-
-void Screen::drawForeFrames() {
- // foreground sprite, fixed to main background
- for (uint i = 0; i < _curFore; i++)
- processImage(&_foreList[i]);
-}
-
-void Screen::drawForePar0Frames() {
- // frame attached to 1st foreground parallax
- for (uint i = 0; i < _curFgp0; i++)
- processImage(&_fgp0List[i]);
-}
-
-void Screen::drawForePar1Frames() {
- // frame attached to 2nd foreground parallax
- for (uint i = 0; i < _curFgp1; i++)
- processImage(&_fgp1List[i]);
-}
-
-void Screen::processLayer(byte *file, uint32 layer_number) {
- LayerHeader layer_head;
-
- layer_head.read(_vm->fetchLayerHeader(file, layer_number));
-
- SpriteInfo spriteInfo;
-
- spriteInfo.x = layer_head.x;
- spriteInfo.y = layer_head.y;
- spriteInfo.w = layer_head.width;
- spriteInfo.scale = 0;
- spriteInfo.scaledWidth = 0;
- spriteInfo.scaledHeight = 0;
- spriteInfo.h = layer_head.height;
- spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST;
- spriteInfo.blend = 0;
- spriteInfo.data = file + ResHeader::size() + layer_head.offset;
- spriteInfo.colourTable = 0;
-
- // check for largest layer for debug info
-
- uint32 current_layer_area = layer_head.width * layer_head.height;
-
- if (current_layer_area > _largestLayerArea) {
- byte buf[NAME_LEN];
-
- _largestLayerArea = current_layer_area;
- sprintf(_largestLayerInfo,
- "largest layer: %s layer(%d) is %dx%d",
- _vm->_resman->fetchName(_thisScreen.background_layer_id, buf),
- layer_number, layer_head.width, layer_head.height);
- }
-
- uint32 rv = drawSprite(&spriteInfo);
- if (rv)
- error("Driver Error %.8x in processLayer(%d)", rv, layer_number);
-}
-
-void Screen::processImage(BuildUnit *build_unit) {
- byte *file = _vm->_resman->openResource(build_unit->anim_resource);
- byte *colTablePtr = NULL;
-
- byte *frame = _vm->fetchFrameHeader(file, build_unit->anim_pc);
-
- AnimHeader anim_head;
- CdtEntry cdt_entry;
- FrameHeader frame_head;
-
- anim_head.read(_vm->fetchAnimHeader(file));
- cdt_entry.read(_vm->fetchCdtEntry(file, build_unit->anim_pc));
- frame_head.read(frame);
-
- // so that 0-colour is transparent
- uint32 spriteType = RDSPR_TRANS;
-
- if (anim_head.blend)
- spriteType |= RDSPR_BLEND;
-
- // if the frame is to be flipped (only really applicable to frames
- // using offsets)
- if (cdt_entry.frameType & FRAME_FLIPPED)
- spriteType |= RDSPR_FLIP;
-
- if (cdt_entry.frameType & FRAME_256_FAST) {
- // scaling, shading & blending don't work with RLE256FAST
- // but the same compression can be decompressed using the
- // RLE256 routines!
-
- // NOTE: If this restriction refers to drawSprite(), I don't
- // think we have it any more. But I'm not sure.
-
- if (build_unit->scale || anim_head.blend || build_unit->shadingFlag)
- spriteType |= RDSPR_RLE256;
- else
- spriteType |= RDSPR_RLE256FAST;
- } else {
- switch (anim_head.runTimeComp) {
- case NONE:
- spriteType |= RDSPR_NOCOMPRESSION;
- break;
- case RLE256:
- spriteType |= RDSPR_RLE256;
- break;
- case RLE16:
- spriteType |= RDSPR_RLE16;
- // points to just after last cdt_entry, ie.
- // start of colour table
- colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size() + anim_head.noAnimFrames * CdtEntry::size();
- break;
- }
- }
-
- // if we want this frame to be affected by the shading mask,
- // add the status bit
- if (build_unit->shadingFlag)
- spriteType |= RDSPR_SHADOW;
-
- SpriteInfo spriteInfo;
-
- spriteInfo.x = build_unit->x;
- spriteInfo.y = build_unit->y;
- spriteInfo.w = frame_head.width;
- spriteInfo.h = frame_head.height;
- spriteInfo.scale = build_unit->scale;
- spriteInfo.scaledWidth = build_unit->scaled_width;
- spriteInfo.scaledHeight = build_unit->scaled_height;
- spriteInfo.type = spriteType;
- spriteInfo.blend = anim_head.blend;
- // points to just after frame header, ie. start of sprite data
- spriteInfo.data = frame + FrameHeader::size();
- spriteInfo.colourTable = colTablePtr;
-
- // check for largest layer for debug info
- uint32 current_sprite_area = frame_head.width * frame_head.height;
-
- if (current_sprite_area > _largestSpriteArea) {
- byte buf[NAME_LEN];
-
- _largestSpriteArea = current_sprite_area;
- sprintf(_largestSpriteInfo,
- "largest sprite: %s frame(%d) is %dx%d",
- _vm->_resman->fetchName(build_unit->anim_resource, buf),
- build_unit->anim_pc,
- frame_head.width,
- frame_head.height);
- }
-
- if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) { // see anims.cpp
- // bring the anim into the visible screen
- // but leave extra pixel at edge for box
- if (spriteInfo.x + spriteInfo.scaledWidth >= 639)
- spriteInfo.x = 639 - spriteInfo.scaledWidth;
-
- if (spriteInfo.y + spriteInfo.scaledHeight >= 399)
- spriteInfo.y = 399 - spriteInfo.scaledHeight;
-
- if (spriteInfo.x < 1)
- spriteInfo.x = 1;
-
- if (spriteInfo.y < 1)
- spriteInfo.y = 1;
-
- // create box to surround sprite - just outside sprite box
- _vm->_debugger->_rectX1 = spriteInfo.x - 1;
- _vm->_debugger->_rectY1 = spriteInfo.y - 1;
- _vm->_debugger->_rectX2 = spriteInfo.x + spriteInfo.scaledWidth;
- _vm->_debugger->_rectY2 = spriteInfo.y + spriteInfo.scaledHeight;
- }
-
- uint32 rv = drawSprite(&spriteInfo);
- if (rv) {
- byte buf[NAME_LEN];
-
- error("Driver Error %.8x with sprite %s (%d) in processImage",
- rv,
- _vm->_resman->fetchName(build_unit->anim_resource, buf),
- build_unit->anim_resource);
- }
-
- // release the anim resource
- _vm->_resman->closeResource(build_unit->anim_resource);
-}
-
-void Screen::resetRenderLists() {
- // reset the sort lists - do this before a logic loop
- // takes into account the fact that the start of the list is pre-built
- // with the special sortable layers
-
- _curBgp0 = 0;
- _curBgp1 = 0;
- _curBack = 0;
- // beginning of sort list is setup with the special sort layers
- _curSort = _thisScreen.number_of_layers;
- _curFore = 0;
- _curFgp0 = 0;
- _curFgp1 = 0;
-
- if (_curSort) {
- // there are some layers - so rebuild the sort order list
- for (uint i = 0; i < _curSort; i++)
- _sortOrder[i] = i;
- }
-}
-
-void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit) {
- ObjectGraphic obGraph(ob_graph);
- ObjectMega obMega(ob_mega);
-
- assert(obGraph.getAnimResource());
-
- byte *file = _vm->_resman->openResource(obGraph.getAnimResource());
-
- AnimHeader anim_head;
- CdtEntry cdt_entry;
- FrameHeader frame_head;
-
- anim_head.read(_vm->fetchAnimHeader(file));
- cdt_entry.read(_vm->fetchCdtEntry(file, obGraph.getAnimPc()));
- frame_head.read(_vm->fetchFrameHeader(file, obGraph.getAnimPc()));
-
- // update player graphic details for on-screen debug info
- if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
- _vm->_debugger->_graphType = obGraph.getType();
- _vm->_debugger->_graphAnimRes = obGraph.getAnimResource();
- // counting 1st frame as 'frame 1'
- _vm->_debugger->_graphAnimPc = obGraph.getAnimPc() + 1;
- _vm->_debugger->_graphNoFrames = anim_head.noAnimFrames;
- }
-
- // fill in the BuildUnit structure for this frame
-
- build_unit->anim_resource = obGraph.getAnimResource();
- build_unit->anim_pc = obGraph.getAnimPc();
- build_unit->layer_number = 0;
-
- // Affected by shading mask?
- if (obGraph.getType() & SHADED_SPRITE)
- build_unit->shadingFlag = true;
- else
- build_unit->shadingFlag = false;
-
- // Check if this frame has offsets ie. this is a scalable mega frame
-
- int scale = 0;
-
- if (cdt_entry.frameType & FRAME_OFFSET) {
- scale = obMega.calcScale();
-
- // calc final render coordinates (top-left of sprite), based
- // on feet coords & scaled offsets
-
- // add scaled offsets to feet coords
- build_unit->x = obMega.getFeetX() + (cdt_entry.x * scale) / 256;
- build_unit->y = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
-
- // Work out new width and height. Always divide by 256 after
- // everything else, to maintain accurary
- build_unit->scaled_width = ((scale * frame_head.width) / 256);
- build_unit->scaled_height = ((scale * frame_head.height) / 256);
- } else {
- // It's a non-scaling anim. Get render coords for sprite, from cdt
- build_unit->x = cdt_entry.x;
- build_unit->y = cdt_entry.y;
-
- // Get width and height
- build_unit->scaled_width = frame_head.width;
- build_unit->scaled_height = frame_head.height;
- }
-
- // either 0 or required scale, depending on whether 'scale' computed
- build_unit->scale = scale;
-
- // calc the bottom y-coord for sorting purposes
- build_unit->sort_y = build_unit->y + build_unit->scaled_height - 1;
-
- if (ob_mouse) {
- // passed a mouse structure, so add to the _mouseList
- _vm->_mouse->registerMouse(ob_mouse, build_unit);
-
- }
-
- _vm->_resman->closeResource(obGraph.getAnimResource());
-}
-
-void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega) {
- ObjectGraphic obGraph(ob_graph);
-
- // check low word for sprite type
- switch (obGraph.getType() & 0x0000ffff) {
- case BGP0_SPRITE:
- assert(_curBgp0 < MAX_bgp0_sprites);
- registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp0List[_curBgp0]);
- _curBgp0++;
- break;
- case BGP1_SPRITE:
- assert(_curBgp1 < MAX_bgp1_sprites);
- registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp1List[_curBgp1]);
- _curBgp1++;
- break;
- case BACK_SPRITE:
- assert(_curBack < MAX_back_sprites);
- registerFrame(ob_mouse, ob_graph, ob_mega, &_backList[_curBack]);
- _curBack++;
- break;
- case SORT_SPRITE:
- assert(_curSort < MAX_sort_sprites);
- _sortOrder[_curSort] = _curSort;
- registerFrame(ob_mouse, ob_graph, ob_mega, &_sortList[_curSort]);
- _curSort++;
- break;
- case FORE_SPRITE:
- assert(_curFore < MAX_fore_sprites);
- registerFrame(ob_mouse, ob_graph, ob_mega, &_foreList[_curFore]);
- _curFore++;
- break;
- case FGP0_SPRITE:
- assert(_curFgp0 < MAX_fgp0_sprites);
- registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp0List[_curFgp0]);
- _curFgp0++;
- break;
- case FGP1_SPRITE:
- assert(_curFgp1 < MAX_fgp1_sprites);
- registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp1List[_curFgp1]);
- _curFgp1++;
- break;
- default:
- // NO_SPRITE no registering!
- break;
- }
-}
-
-// FIXME:
-//
-// The original credits used a different font. I think it's stored in the
-// font.clu file, but I don't know how to interpret it.
-//
-// The original used the entire screen. This version cuts off the top and
-// bottom of the screen, because that's where the menus would usually be.
-//
-// The original had some sort of smoke effect at the bottom of the screen.
-
-enum {
- LINE_LEFT,
- LINE_CENTER,
- LINE_RIGHT
-};
-
-struct CreditsLine {
- char *str;
- byte type;
- int top;
- int height;
- byte *sprite;
-
- CreditsLine() {
- str = NULL;
- sprite = NULL;
- };
-
- ~CreditsLine() {
- free(str);
- free(sprite);
- str = NULL;
- sprite = NULL;
- }
-};
-
-#define CREDITS_FONT_HEIGHT 25
-#define CREDITS_LINE_SPACING 20
-
-void Screen::rollCredits() {
- uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();
-
- // Prepare for the credits by fading down, stoping the music, etc.
-
- _vm->_mouse->setMouse(0);
-
- _vm->_sound->muteFx(true);
- _vm->_sound->muteSpeech(true);
-
- waitForFade();
- fadeDown();
- waitForFade();
-
- _vm->_mouse->closeMenuImmediately();
-
- // There are three files which I believe are involved in showing the
- // credits:
- //
- // credits.bmp - The "Smacker" logo, stored as follows:
- //
- // width 2 bytes, little endian
- // height 2 bytes, little endian
- // palette 3 * 256 bytes
- // data width * height bytes
- //
- // Note that the maximum colour component in the palette is 0x3F.
- // This is the same resolution as the _paletteMatch table. I doubt
- // that this is a coincidence, but let's use the image palette
- // directly anyway, just to be safe.
- //
- // credits.clu - The credits text
- //
- // This is simply a text file with CRLF line endings.
- // '^' is not shown, but used to mark the center of the line.
- // '@' is used as a placeholder for the "Smacker" logo. At least
- // when it appears alone.
- // Remaining lines are centered.
- // The German version also contains character code 9 for no
- // apparent reason. We ignore them.
- //
- // fonts.clu - The credits font?
- //
- // FIXME: At this time I don't know how to interpret fonts.clu. For
- // now, let's just the standard speech font instead.
-
- SpriteInfo spriteInfo;
- Common::File f;
- int i;
-
- // Read the "Smacker" logo
-
- uint16 logoWidth = 0;
- uint16 logoHeight = 0;
- byte *logoData = NULL;
- byte palette[256 * 4];
-
- if (f.open("credits.bmp")) {
- logoWidth = f.readUint16LE();
- logoHeight = f.readUint16LE();
-
- for (i = 0; i < 256; i++) {
- palette[i * 4 + 0] = f.readByte() << 2;
- palette[i * 4 + 1] = f.readByte() << 2;
- palette[i * 4 + 2] = f.readByte() << 2;
- palette[i * 4 + 3] = 0;
- }
-
- logoData = (byte *)malloc(logoWidth * logoHeight);
-
- f.read(logoData, logoWidth * logoHeight);
- f.close();
- } else {
- warning("Can't find credits.bmp");
- memset(palette, 0, sizeof(palette));
- palette[14 * 4 + 0] = 252;
- palette[14 * 4 + 1] = 252;
- palette[14 * 4 + 2] = 252;
- palette[14 * 4 + 3] = 0;
- }
-
- setPalette(0, 256, palette, RDPAL_INSTANT);
-
- // Read the credits text
-
- Common::Array<CreditsLine *> creditsLines;
-
- int lineCount = 0;
- int lineTop = 400;
- int paragraphStart = 0;
- bool hasCenterMark = false;
-
- if (!f.open("credits.clu")) {
- warning("Can't find credits.clu");
- return;
- }
-
- while (1) {
- char buffer[80];
- char *line = f.readLine(buffer, sizeof(buffer));
-
- if (!line || *line == 0) {
- if (!hasCenterMark) {
- for (i = paragraphStart; i < lineCount; i++)
- creditsLines[i]->type = LINE_CENTER;
- }
- paragraphStart = lineCount;
- hasCenterMark = false;
- if (paragraphStart == lineCount)
- lineTop += CREDITS_LINE_SPACING;
-
- if (!line)
- break;
-
- continue;
- }
-
- // The German credits contains character code 9. We don't want
- // the credits to show the 'dud' symbol, so we replace them
- // with spaces.
-
- for (char *ptr = line; *ptr; ptr++) {
- if (*ptr < 32)
- *ptr = 32;
- }
-
- char *center_mark = strchr(line, '^');
-
- if (center_mark) {
- // The current paragraph has at least one center mark.
- hasCenterMark = true;
-
- if (center_mark != line) {
- creditsLines.push_back(new CreditsLine);
-
- // The center mark is somewhere inside the
- // line. Split it into left and right side.
- *center_mark = 0;
-
- creditsLines[lineCount]->top = lineTop;
- creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
- creditsLines[lineCount]->type = LINE_LEFT;
- creditsLines[lineCount]->str = strdup(line);
-
- lineCount++;
- *center_mark = '^';
- }
-
- line = center_mark;
- }
-
- creditsLines.push_back(new CreditsLine);
-
- creditsLines[lineCount]->top = lineTop;
-
- if (*line == '^') {
- creditsLines[lineCount]->type = LINE_RIGHT;
- line++;
- } else
- creditsLines[lineCount]->type = LINE_LEFT;
-
- if (strcmp(line, "@") == 0) {
- creditsLines[lineCount]->height = logoHeight;
- lineTop += logoHeight;
- } else {
- creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
- lineTop += CREDITS_LINE_SPACING;
- }
-
- creditsLines[lineCount]->str = strdup(line);
- lineCount++;
- }
-
- f.close();
-
- // We could easily add some ScummVM stuff to the credits, if we wanted
- // to. On the other hand, anyone with the attention span to actually
- // read all the credits probably already knows. :-)
-
- // Start the music and roll the credits
-
- // The credits music (which can also be heard briefly in the "carib"
- // cutscene) is played once.
-
- _vm->_sound->streamCompMusic(309, false);
-
- clearScene();
- fadeUp(0);
-
- spriteInfo.scale = 0;
- spriteInfo.scaledWidth = 0;
- spriteInfo.scaledHeight = 0;
- spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
- spriteInfo.blend = 0;
-
- int startLine = 0;
- int scrollPos = 0;
-
- bool abortCredits = false;
-
- int scrollSteps = lineTop + CREDITS_FONT_HEIGHT;
- uint32 musicStart = _vm->getMillis();
-
- // Ideally the music should last just a tiny bit longer than the
- // credits. Note that musicTimeRemaining() will return 0 if the music
- // is muted, so we need a sensible fallback for that case.
-
- uint32 musicLength = MAX((int32)(1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32)scrollSteps);
-
- while (scrollPos < scrollSteps && !_vm->_quit) {
- clearScene();
-
- for (i = startLine; i < lineCount; i++) {
- if (!creditsLines[i])
- continue;
-
- // Free any sprites that have scrolled off the screen
-
- if (creditsLines[i]->top + creditsLines[i]->height < scrollPos) {
- debug(2, "Freeing line %d: '%s'", i, creditsLines[i]->str);
-
- delete creditsLines[i];
- creditsLines[i] = NULL;
-
- startLine = i + 1;
- } else if (creditsLines[i]->top < scrollPos + 400) {
- if (!creditsLines[i]->sprite) {
- debug(2, "Creating line %d: '%s'", i, creditsLines[i]->str);
- creditsLines[i]->sprite = _vm->_fontRenderer->makeTextSprite((byte *)creditsLines[i]->str, 600, 14, _vm->_speechFontId, 0);
- }
-
- FrameHeader frame;
-
- frame.read(creditsLines[i]->sprite);
-
- spriteInfo.y = creditsLines[i]->top - scrollPos;
- spriteInfo.w = frame.width;
- spriteInfo.h = frame.height;
- spriteInfo.data = creditsLines[i]->sprite + FrameHeader::size();
-
- switch (creditsLines[i]->type) {
- case LINE_LEFT:
- spriteInfo.x = RENDERWIDE / 2 - 5 - frame.width;
- break;
- case LINE_RIGHT:
- spriteInfo.x = RENDERWIDE / 2 + 5;
- break;
- case LINE_CENTER:
- if (strcmp(creditsLines[i]->str, "@") == 0) {
- spriteInfo.data = logoData;
- spriteInfo.x = (RENDERWIDE - logoWidth) / 2;
- spriteInfo.w = logoWidth;
- spriteInfo.h = logoHeight;
- } else
- spriteInfo.x = (RENDERWIDE - frame.width) / 2;
- break;
- }
-
- if (spriteInfo.data)
- drawSprite(&spriteInfo);
- } else
- break;
- }
-
- updateDisplay();
-
- KeyboardEvent *ke = _vm->keyboardEvent();
-
- if (ke && ke->keycode == 27) {
- if (!abortCredits) {
- abortCredits = true;
- fadeDown();
- }
- }
-
- if (abortCredits && getFadeStatus() == RDFADE_BLACK)
- break;
-
- _vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps);
- scrollPos++;
- }
-
- // We're done. Clean up and try to put everything back where it was
- // before the credits.
-
- for (i = 0; i < lineCount; i++) {
- delete creditsLines[i];
- }
-
- free(logoData);
-
- if (!abortCredits) {
- fadeDown();
-
- // The music should either have stopped or be about to stop, so
- // wait for it to really happen.
-
- while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) {
- updateDisplay(false);
- _vm->_system->delayMillis(100);
- }
- }
-
- if (_vm->_quit)
- return;
-
- waitForFade();
-
- _vm->_sound->muteFx(false);
- _vm->_sound->muteSpeech(false);
-
- if (loopingMusicId)
- _vm->_sound->streamCompMusic(loopingMusicId, true);
- else
- _vm->_sound->stopMusic(false);
-
- if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing())
- _vm->_mouse->setMouse(NORMAL_MOUSE_ID);
-
- if (_vm->_logic->readVar(DEAD))
- _vm->_mouse->buildSystemMenu();
-}
-
-// This image used to be shown by CacheNewCluster() while copying a data file
-// from the CD to the hard disk. ScummVM doesn't do that, so the image is never
-// shown. It'd be nice if we could do something useful with it some day...
-
-void Screen::splashScreen() {
- byte *bgfile = _vm->_resman->openResource(2950);
-
- initialiseBackgroundLayer(NULL);
- initialiseBackgroundLayer(NULL);
- initialiseBackgroundLayer(_vm->fetchBackgroundLayer(bgfile));
- initialiseBackgroundLayer(NULL);
- initialiseBackgroundLayer(NULL);
-
- setPalette(0, 256, _vm->fetchPalette(bgfile), RDPAL_FADE);
- renderParallax(_vm->fetchBackgroundLayer(bgfile), 2);
-
- closeBackgroundLayer();
-
- byte *loadingBar = _vm->_resman->openResource(2951);
- byte *frame = _vm->fetchFrameHeader(loadingBar, 0);
-
- AnimHeader animHead;
- CdtEntry cdt;
- FrameHeader frame_head;
-
- animHead.read(_vm->fetchAnimHeader(loadingBar));
- cdt.read(_vm->fetchCdtEntry(loadingBar, 0));
- frame_head.read(_vm->fetchFrameHeader(loadingBar, 0));
-
- SpriteInfo barSprite;
-
- barSprite.x = cdt.x;
- barSprite.y = cdt.y;
- barSprite.w = frame_head.width;
- barSprite.h = frame_head.height;
- barSprite.scale = 0;
- barSprite.scaledWidth = 0;
- barSprite.scaledHeight = 0;
- barSprite.type = RDSPR_RLE256FAST | RDSPR_TRANS;
- barSprite.blend = 0;
- barSprite.colourTable = 0;
- barSprite.data = frame + FrameHeader::size();
-
- drawSprite(&barSprite);
-
- fadeUp();
- waitForFade();
-
- for (int i = 0; i < animHead.noAnimFrames; i++) {
- frame = _vm->fetchFrameHeader(loadingBar, i);
- barSprite.data = frame + FrameHeader::size();
- drawSprite(&barSprite);
- updateDisplay();
- _vm->_system->delayMillis(30);
- }
-
- _vm->_resman->closeResource(2951);
-
- fadeDown();
- waitForFade();
-}
-
-} // End of namespace Sword2
diff --git a/sword2/build_display.h b/sword2/build_display.h
deleted file mode 100644
index 1a362da137..0000000000
--- a/sword2/build_display.h
+++ /dev/null
@@ -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
diff --git a/sword2/console.cpp b/sword2/console.cpp
deleted file mode 100644
index b465dc369f..0000000000
--- a/sword2/console.cpp
+++ /dev/null
@@ -1,826 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/console.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/memory.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-#include "common/debugger.cpp"
-
-namespace Sword2 {
-
-Debugger::Debugger(Sword2Engine *vm)
- : Common::Debugger<Debugger>() {
- _vm = vm;
-
- memset(_debugTextBlocks, 0, sizeof(_debugTextBlocks));
- memset(_showVar, 0, sizeof(_showVar));
-
- _displayDebugText = false; // "INFO"
- _displayWalkGrid = false; // "WALKGRID"
- _displayMouseMarker = false; // "MOUSE"
- _displayTime = false; // "TIME"
- _displayPlayerMarker = false; // "PLAYER"
- _displayTextNumbers = false; // "TEXT"
-
- _definingRectangles = false; // "RECT"
- _draggingRectangle = 0; // 0 = waiting to start new rect
- // 1 = currently dragging a rectangle
-
- _rectX1 = _rectY1 = 0;
- _rectX2 = _rectY2 = 0;
- _rectFlicker = false;
-
- _testingSnR = false; // "SAVEREST" - for system to kill all
- // object resources (except player) in
- // fnAddHuman()
-
- _speechScriptWaiting = 0; // The id of whoever we're waiting for
- // in a speech script. See fnTheyDo(),
- // fnTheyDoWeWait(), fnWeWait(), and
- // fnTimedWait().
-
- _startTime = 0; // "TIMEON" & "TIMEOFF" - system start
- // time
-
- _textNumber = 0; // Current system text line number
-
- _graphNoFrames = 0; // No. of frames in currently displayed
- // anim
-
- // Register commands
-
- DCmd_Register("continue", &Debugger::Cmd_Exit);
- DCmd_Register("exit", &Debugger::Cmd_Exit);
- DCmd_Register("quit", &Debugger::Cmd_Exit);
- DCmd_Register("q", &Debugger::Cmd_Exit);
- DCmd_Register("help", &Debugger::Cmd_Help);
- DCmd_Register("mem", &Debugger::Cmd_Mem);
- DCmd_Register("tony", &Debugger::Cmd_Tony);
- DCmd_Register("res", &Debugger::Cmd_Res);
- DCmd_Register("reslist", &Debugger::Cmd_ResList);
- DCmd_Register("starts", &Debugger::Cmd_Starts);
- DCmd_Register("start", &Debugger::Cmd_Start);
- DCmd_Register("s", &Debugger::Cmd_Start);
- DCmd_Register("info", &Debugger::Cmd_Info);
- DCmd_Register("walkgrid", &Debugger::Cmd_WalkGrid);
- DCmd_Register("mouse", &Debugger::Cmd_Mouse);
- DCmd_Register("player", &Debugger::Cmd_Player);
- DCmd_Register("reslook", &Debugger::Cmd_ResLook);
- DCmd_Register("cur", &Debugger::Cmd_CurrentInfo);
- DCmd_Register("runlist", &Debugger::Cmd_RunList);
- DCmd_Register("kill", &Debugger::Cmd_Kill);
- DCmd_Register("nuke", &Debugger::Cmd_Nuke);
- DCmd_Register("var", &Debugger::Cmd_Var);
- DCmd_Register("rect", &Debugger::Cmd_Rect);
- DCmd_Register("clear", &Debugger::Cmd_Clear);
- DCmd_Register("debugon", &Debugger::Cmd_DebugOn);
- DCmd_Register("debugoff", &Debugger::Cmd_DebugOff);
- DCmd_Register("saverest", &Debugger::Cmd_SaveRest);
- DCmd_Register("timeon", &Debugger::Cmd_TimeOn);
- DCmd_Register("timeoff", &Debugger::Cmd_TimeOff);
- DCmd_Register("text", &Debugger::Cmd_Text);
- DCmd_Register("showvar", &Debugger::Cmd_ShowVar);
- DCmd_Register("hidevar", &Debugger::Cmd_HideVar);
- DCmd_Register("version", &Debugger::Cmd_Version);
- DCmd_Register("animtest", &Debugger::Cmd_AnimTest);
- DCmd_Register("texttest", &Debugger::Cmd_TextTest);
- DCmd_Register("linetest", &Debugger::Cmd_LineTest);
- DCmd_Register("events", &Debugger::Cmd_Events);
- DCmd_Register("sfx", &Debugger::Cmd_Sfx);
- DCmd_Register("english", &Debugger::Cmd_English);
- DCmd_Register("finnish", &Debugger::Cmd_Finnish);
- DCmd_Register("polish", &Debugger::Cmd_Polish);
-}
-
-void Debugger::varGet(int var) {
- DebugPrintf("%d\n", _vm->_logic->readVar(var));
-}
-
-void Debugger::varSet(int var, int val) {
- DebugPrintf("was %d, ", _vm->_logic->readVar(var));
- _vm->_logic->writeVar(var, val);
- DebugPrintf("now %d\n", _vm->_logic->readVar(var));
-}
-
-void Debugger::preEnter() {
- // Pause sound output
- if (_vm->_sound) {
- _vm->_sound->pauseFx();
- _vm->_sound->pauseSpeech();
- _vm->_sound->pauseMusic();
- }
-}
-
-void Debugger::postEnter() {
- if (_vm->_sound) {
- // Resume previous sound state
- _vm->_sound->unpauseFx();
- _vm->_sound->unpauseSpeech();
- _vm->_sound->unpauseMusic();
- }
-
- if (_vm->_mouse) {
- // Restore old mouse cursor
- _vm->_mouse->drawMouse();
- }
-}
-
-// Now the fun stuff: Commands
-
-bool Debugger::Cmd_Exit(int argc, const char **argv) {
- _detach_now = true;
- _vm->clearInputEvents();
- return false;
-}
-
-bool Debugger::Cmd_Help(int argc, const char **argv) {
- // console normally has 78 line width
- // wrap around nicely
- int width = 0;
-
- DebugPrintf("Commands are:\n");
- for (int i = 0 ; i < _dcmd_count ; i++) {
- int size = strlen(_dcmds[i].name) + 1;
-
- if (width + size >= 75) {
- DebugPrintf("\n");
- width = size;
- } else
- width += size;
-
- DebugPrintf("%s ", _dcmds[i].name);
- }
-
- DebugPrintf("\n");
- return true;
-}
-
-static int compare_blocks(const void *p1, const void *p2) {
- const MemBlock *m1 = *(const MemBlock * const *)p1;
- const MemBlock *m2 = *(const MemBlock * const *)p2;
-
- if (m1->size < m2->size)
- return 1;
- if (m1->size > m2->size)
- return -1;
- return 0;
-}
-
-bool Debugger::Cmd_Mem(int argc, const char **argv) {
- int16 numBlocks = _vm->_memory->getNumBlocks();
- MemBlock *memBlocks = _vm->_memory->getMemBlocks();
-
- MemBlock **blocks = (MemBlock **)malloc(numBlocks * sizeof(MemBlock));
-
- int i, j;
-
- for (i = 0, j = 0; i < MAX_MEMORY_BLOCKS; i++) {
- if (memBlocks[i].ptr)
- blocks[j++] = &memBlocks[i];
- }
-
- qsort(blocks, numBlocks, sizeof(MemBlock *), compare_blocks);
-
- DebugPrintf(" size id res type name\n");
- DebugPrintf("---------------------------------------------------------------------------\n");
-
- for (i = 0; i < numBlocks; i++) {
- const char *type;
-
- switch (_vm->_resman->fetchType(blocks[i]->ptr)) {
- case ANIMATION_FILE:
- type = "ANIMATION_FILE";
- break;
- case SCREEN_FILE:
- type = "SCREEN_FILE";
- break;
- case GAME_OBJECT:
- type = "GAME_OBJECT";
- break;
- case WALK_GRID_FILE:
- type = "WALK_GRID_FILE";
- break;
- case GLOBAL_VAR_FILE:
- type = "GLOBAL_VAR_FILE";
- break;
- case PARALLAX_FILE_null:
- type = "PARALLAX_FILE_null";
- break;
- case RUN_LIST:
- type = "RUN_LIST";
- break;
- case TEXT_FILE:
- type = "TEXT_FILE";
- break;
- case SCREEN_MANAGER:
- type = "SCREEN_MANAGER";
- break;
- case MOUSE_FILE:
- type = "MOUSE_FILE";
- break;
- case WAV_FILE:
- type = "WAV_FILE";
- break;
- case ICON_FILE:
- type = "ICON_FILE";
- break;
- case PALETTE_FILE:
- type = "PALETTE_FILE";
- break;
- default:
- type = "<unknown>";
- break;
- }
-
- DebugPrintf("%9ld %-3d %-4d %-20s %s\n", blocks[i]->size, blocks[i]->id, blocks[i]->uid, type, _vm->_resman->fetchName(blocks[i]->ptr));
- }
-
- free(blocks);
-
- DebugPrintf("---------------------------------------------------------------------------\n");
- DebugPrintf("%9ld\n", _vm->_memory->getTotAlloc());
-
- return true;
-}
-
-bool Debugger::Cmd_Tony(int argc, const char **argv) {
- DebugPrintf("What about him?\n");
- return true;
-}
-
-bool Debugger::Cmd_Res(int argc, const char **argv) {
- uint32 numClusters = _vm->_resman->getNumClusters();
-
- if (!numClusters) {
- DebugPrintf("Argh! No resources!\n");
- return true;
- }
-
- ResourceFile *resFiles = _vm->_resman->getResFiles();
-
- for (uint i = 0; i < numClusters; i++) {
- const char *locStr[3] = { "HDD", "CD1", "CD2" };
-
- DebugPrintf("%-20s %d\n", resFiles[i].fileName, locStr[resFiles[i].cd]);
- }
-
- DebugPrintf("%d resources\n", _vm->_resman->getNumResFiles());
- return true;
-}
-
-bool Debugger::Cmd_ResList(int argc, const char **argv) {
- // By default, list only resources that are being held open.
- uint minCount = 1;
-
- if (argc > 1)
- minCount = atoi(argv[1]);
-
- uint32 numResFiles = _vm->_resman->getNumResFiles();
- Resource *resList = _vm->_resman->getResList();
-
- for (uint i = 0; i < numResFiles; i++) {
- if (resList[i].ptr && resList[i].refCount >= minCount) {
- DebugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount);
- }
- }
-
- return true;
-}
-
-bool Debugger::Cmd_Starts(int argc, const char **argv) {
- uint32 numStarts = _vm->getNumStarts();
-
- if (!numStarts) {
- DebugPrintf("Sorry - no startup positions registered?\n");
-
- uint32 numScreenManagers = _vm->getNumScreenManagers();
-
- if (!numScreenManagers)
- DebugPrintf("There is a problem with startup.inf\n");
- else
- DebugPrintf(" (%d screen managers found in startup.inf)\n", numScreenManagers);
- return true;
- }
-
- StartUp *startList = _vm->getStartList();
-
- for (uint i = 0; i < numStarts; i++)
- DebugPrintf("%d (%s)\n", i, startList[i].description);
-
- return true;
-}
-
-bool Debugger::Cmd_Start(int argc, const char **argv) {
- uint8 pal[4] = { 255, 255, 255, 0 };
-
- if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
- return true;
- }
-
- uint32 numStarts = _vm->getNumStarts();
-
- if (!numStarts) {
- DebugPrintf("Sorry - there are no startups!\n");
- return true;
- }
-
- int start = atoi(argv[1]);
-
- if (start < 0 || start >= (int)numStarts) {
- DebugPrintf("Not a legal start position\n");
- return true;
- }
-
- DebugPrintf("Running start %d\n", start);
-
- _vm->runStart(start);
- _vm->_screen->setPalette(187, 1, pal, RDPAL_INSTANT);
- return true;
-}
-
-bool Debugger::Cmd_Info(int argc, const char **argv) {
- _displayDebugText = !_displayDebugText;
-
- if (_displayDebugText)
- DebugPrintf("Info text on\n");
- else
- DebugPrintf("Info Text off\n");
-
- return true;
-}
-
-bool Debugger::Cmd_WalkGrid(int argc, const char **argv) {
- _displayWalkGrid = !_displayWalkGrid;
-
- if (_displayWalkGrid)
- DebugPrintf("Walk-grid display on\n");
- else
- DebugPrintf("Walk-grid display off\n");
-
- return true;
-}
-
-bool Debugger::Cmd_Mouse(int argc, const char **argv) {
- _displayMouseMarker = !_displayMouseMarker;
-
- if (_displayMouseMarker)
- DebugPrintf("Mouse marker on\n");
- else
- DebugPrintf("Mouse marker off\n");
-
- return true;
-}
-
-bool Debugger::Cmd_Player(int argc, const char **argv) {
- _displayPlayerMarker = !_displayPlayerMarker;
-
- if (_displayPlayerMarker)
- DebugPrintf("Player feet marker on\n");
- else
- DebugPrintf("Player feet marker off\n");
-
- return true;
-}
-
-bool Debugger::Cmd_ResLook(int argc, const char **argv) {
- if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
- return true;
- }
-
- int res = atoi(argv[1]);
- uint32 numResFiles = _vm->_resman->getNumResFiles();
-
- if (res < 0 || res >= (int)numResFiles) {
- DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
- res, numResFiles, numResFiles - 1);
- return true;
- }
-
- if (!_vm->_resman->checkValid(res)) {
- DebugPrintf("%d is a null & void resource number\n", res);
- return true;
- }
-
- // Open up the resource and take a look inside!
- uint8 type = _vm->_resman->fetchType(res);;
- byte name[NAME_LEN];
-
- _vm->_resman->fetchName(res, name);
-
- switch (type) {
- case ANIMATION_FILE:
- DebugPrintf("<anim> %s\n", name);
- break;
- case SCREEN_FILE:
- DebugPrintf("<layer> %s\n", name);
- break;
- case GAME_OBJECT:
- DebugPrintf("<game object> %s\n", name);
- break;
- case WALK_GRID_FILE:
- DebugPrintf("<walk grid> %s\n", name);
- break;
- case GLOBAL_VAR_FILE:
- DebugPrintf("<global variables> %s\n", name);
- break;
- case PARALLAX_FILE_null:
- DebugPrintf("<parallax file NOT USED!> %s\n", name);
- break;
- case RUN_LIST:
- DebugPrintf("<run list> %s\n", name);
- break;
- case TEXT_FILE:
- DebugPrintf("<text file> %s\n", name);
- break;
- case SCREEN_MANAGER:
- DebugPrintf("<screen manager> %s\n", name);
- break;
- case MOUSE_FILE:
- DebugPrintf("<mouse pointer> %s\n", name);
- break;
- case ICON_FILE:
- DebugPrintf("<menu icon> %s\n", name);
- break;
- default:
- DebugPrintf("unrecognised fileType %d\n", type);
- break;
- }
-
- return true;
-}
-
-bool Debugger::Cmd_CurrentInfo(int argc, const char **argv) {
- // prints general stuff about the screen, etc.
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- if (screenInfo->background_layer_id) {
- DebugPrintf("background layer id %d\n", screenInfo->background_layer_id);
- DebugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep);
- DebugPrintf("%d normal layers\n", screenInfo->number_of_layers);
-
- Cmd_RunList(argc, argv);
- } else
- DebugPrintf("No screen\n");
- return true;
-}
-
-bool Debugger::Cmd_RunList(int argc, const char **argv) {
- uint32 runList = _vm->_logic->getRunList();
-
- if (runList) {
- Common::MemoryReadStream readS(_vm->_resman->openResource(runList), _vm->_resman->fetchLen(runList));
-
- readS.seek(ResHeader::size());
-
- DebugPrintf("Runlist number %d\n", runList);
-
- while (1) {
- uint32 res = readS.readUint32LE();
- if (!res)
- break;
-
- byte name[NAME_LEN];
-
- DebugPrintf("%d %s\n", res, _vm->_resman->fetchName(res, name));
- }
-
- _vm->_resman->closeResource(runList);
- } else
- DebugPrintf("No run list set\n");
-
- return true;
-}
-
-bool Debugger::Cmd_Kill(int argc, const char **argv) {
- if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
- return true;
- }
-
- int res = atoi(argv[1]);
- uint32 numResFiles = _vm->_resman->getNumResFiles();
-
- if (res < 0 || res >= (int)numResFiles) {
- DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n",
- res, numResFiles, numResFiles - 1);
- return true;
- }
-
- Resource *resList = _vm->_resman->getResList();
-
- if (!resList[res].ptr) {
- DebugPrintf("Resource %d is not in memory\n", res);
- return true;
- }
-
- if (resList[res].refCount) {
- DebugPrintf("Resource %d is open - cannot remove\n", res);
- return true;
- }
-
- _vm->_resman->remove(res);
- DebugPrintf("Trashed %d\n", res);
- return true;
-}
-
-bool Debugger::Cmd_Nuke(int argc, const char **argv) {
- DebugPrintf("Killing all resources except variable file and player object\n");
- _vm->_resman->killAll(true);
- return true;
-}
-
-bool Debugger::Cmd_Var(int argc, const char **argv) {
- switch (argc) {
- case 2:
- varGet(atoi(argv[1]));
- break;
- case 3:
- varSet(atoi(argv[1]), atoi(argv[2]));
- break;
- default:
- DebugPrintf("Usage: %s number value\n", argv[0]);
- break;
- }
-
- return true;
-}
-
-bool Debugger::Cmd_Rect(int argc, const char **argv) {
- uint32 filter = _vm->setInputEventFilter(0);
-
- _definingRectangles = !_definingRectangles;
-
- if (_definingRectangles) {
- _vm->setInputEventFilter(filter & ~(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP));
- DebugPrintf("Mouse rectangles enabled\n");
- } else {
- _vm->setInputEventFilter(filter | RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP);
- DebugPrintf("Mouse rectangles disabled\n");
- }
-
- _draggingRectangle = 0;
- return true;
-}
-
-bool Debugger::Cmd_Clear(int argc, const char **argv) {
- _vm->_resman->killAllObjects(true);
- return true;
-}
-
-bool Debugger::Cmd_DebugOn(int argc, const char **argv) {
- _displayDebugText = true;
- _displayWalkGrid = true;
- _displayMouseMarker = true;
- _displayPlayerMarker = true;
- _displayTextNumbers = true;
- DebugPrintf("Enabled all on-screen debug info\n");
- return true;
-}
-
-bool Debugger::Cmd_DebugOff(int argc, const char **argv) {
- _displayDebugText = false;
- _displayWalkGrid = false;
- _displayMouseMarker = false;
- _displayPlayerMarker = false;
- _displayTextNumbers = false;
- DebugPrintf("Disabled all on-screen debug info\n");
- return true;
-}
-
-bool Debugger::Cmd_SaveRest(int argc, const char **argv) {
- _testingSnR = !_testingSnR;
-
- if (_testingSnR)
- DebugPrintf("Enabled S&R logic_script stability checking\n");
- else
- DebugPrintf("Disabled S&R logic_script stability checking\n");
-
- return true;
-}
-
-bool Debugger::Cmd_TimeOn(int argc, const char **argv) {
- if (argc == 2)
- _startTime = _vm->_system->getMillis() - atoi(argv[1]) * 1000;
- else if (_startTime == 0)
- _startTime = _vm->_system->getMillis();
- _displayTime = true;
- DebugPrintf("Timer display on\n");
- return true;
-}
-
-bool Debugger::Cmd_TimeOff(int argc, const char **argv) {
- _displayTime = false;
- DebugPrintf("Timer display off\n");
- return true;
-}
-
-bool Debugger::Cmd_Text(int argc, const char **argv) {
- _displayTextNumbers = !_displayTextNumbers;
-
- if (_displayTextNumbers)
- DebugPrintf("Text numbers on\n");
- else
- DebugPrintf("Text numbers off\n");
-
- return true;
-}
-
-bool Debugger::Cmd_ShowVar(int argc, const char **argv) {
- int32 showVarNo = 0;
- int32 varNo;
-
- if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
- return true;
- }
-
- varNo = atoi(argv[1]);
-
- // search for a spare slot in the watch-list, but also watch out for
- // this variable already being in the list
-
- while (showVarNo < MAX_SHOWVARS && _showVar[showVarNo] != 0 && _showVar[showVarNo] != varNo)
- showVarNo++;
-
- // if we've found a spare slot or the variable's already there
- if (showVarNo < MAX_SHOWVARS) {
- if (_showVar[showVarNo] == 0) {
- // empty slot - add it to the list at this slot
- _showVar[showVarNo] = varNo;
- DebugPrintf("var(%d) added to the watch-list\n", varNo);
- } else
- DebugPrintf("var(%d) already in the watch-list!\n", varNo);
- } else
- DebugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n");
-
- return true;
-}
-
-bool Debugger::Cmd_HideVar(int argc, const char **argv) {
- int32 showVarNo = 0;
- int32 varNo;
-
- if (argc != 2) {
- DebugPrintf("Usage: %s number\n", argv[0]);
- return true;
- }
-
- varNo = atoi(argv[1]);
-
- // search for 'varNo' in the watch-list
- while (showVarNo < MAX_SHOWVARS && _showVar[showVarNo] != varNo)
- showVarNo++;
-
- if (showVarNo < MAX_SHOWVARS) {
- // We've found 'varNo' in the list - clear this slot
- _showVar[showVarNo] = 0;
- DebugPrintf("var(%d) removed from watch-list\n", varNo);
- } else
- DebugPrintf("Sorry - can't find var(%d) in the list\n", varNo);
-
- return true;
-}
-
-bool Debugger::Cmd_Version(int argc, const char **argv) {
- // This function used to print more information, but nothing we
- // particularly care about.
-
- DebugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n");
- return true;
-}
-
-bool Debugger::Cmd_AnimTest(int argc, const char **argv) {
- if (argc != 2) {
- DebugPrintf("Usage: %s value\n", argv[0]);
- return true;
- }
-
- // Automatically do "s 32" to run the animation testing start script
- _vm->runStart(32);
-
- // Same as typing "VAR 912 <value>" at the console
- varSet(912, atoi(argv[1]));
-
- DebugPrintf("Setting flag 'system_testing_anims'\n");
- return true;
-}
-
-bool Debugger::Cmd_TextTest(int argc, const char **argv) {
- if (argc != 2) {
- DebugPrintf("Usage: %s value\n", argv[0]);
- return true;
- }
-
- // Automatically do "s 33" to run the text/speech testing start script
- _vm->runStart(33);
-
- // Same as typing "VAR 1230 <value>" at the console
- varSet(1230, atoi(argv[1]));
-
- _displayTextNumbers = true;
-
- DebugPrintf("Setting flag 'system_testing_text'\n");
- DebugPrintf("Text numbers on\n");
- return true;
-}
-
-bool Debugger::Cmd_LineTest(int argc, const char **argv) {
- if (argc != 3) {
- DebugPrintf("Usage: %s value1 value2\n", argv[0]);
- return true;
- }
-
- // Automatically do "s 33" to run the text/speech testing start script
- _vm->runStart(33);
-
- // Same as typing "VAR 1230 <value>" at the console
- varSet(1230, atoi(argv[1]));
-
- // Same as typing "VAR 1264 <value>" at the console
- varSet(1264, atoi(argv[2]));
-
- _displayTextNumbers = true;
-
- DebugPrintf("Setting flag 'system_testing_text'\n");
- DebugPrintf("Setting flag 'system_test_line_no'\n");
- DebugPrintf("Text numbers on\n");
- return true;
-}
-
-bool Debugger::Cmd_Events(int argc, const char **argv) {
- EventUnit *eventList = _vm->_logic->getEventList();
-
- DebugPrintf("EVENT LIST:\n");
-
- for (uint32 i = 0; i < MAX_events; i++) {
- if (eventList[i].id) {
- byte buf[NAME_LEN];
- uint32 target = eventList[i].id;
- uint32 script = eventList[i].interact_id;
-
- DebugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target, buf), target);
- DebugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536, buf), script / 65536, script % 65536);
- }
- }
-
- return true;
-}
-
-bool Debugger::Cmd_Sfx(int argc, const char **argv) {
- _vm->_wantSfxDebug = !_vm->_wantSfxDebug;
-
- if (_vm->_wantSfxDebug)
- DebugPrintf("SFX logging activated\n");
- else
- DebugPrintf("SFX logging deactivated\n");
-
- return true;
-}
-
-bool Debugger::Cmd_English(int argc, const char **argv) {
- _vm->initialiseFontResourceFlags(DEFAULT_TEXT);
- DebugPrintf("Default fonts selected\n");
- return true;
-}
-
-bool Debugger::Cmd_Finnish(int argc, const char **argv) {
- _vm->initialiseFontResourceFlags(FINNISH_TEXT);
- DebugPrintf("Finnish fonts selected\n");
- return true;
-}
-
-bool Debugger::Cmd_Polish(int argc, const char **argv) {
- _vm->initialiseFontResourceFlags(POLISH_TEXT);
- DebugPrintf("Polish fonts selected\n");
- return true;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/console.h b/sword2/console.h
deleted file mode 100644
index 95bfbe946d..0000000000
--- a/sword2/console.h
+++ /dev/null
@@ -1,127 +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 C_ONSOLE_H
-#define C_ONSOLE_H
-
-#include "common/debugger.h"
-#include "sword2/debug.h"
-
-namespace Sword2 {
-
-class Debugger : public Common::Debugger<Debugger> {
-private:
- void varGet(int var);
- void varSet(int var, int val);
-
- bool _displayDebugText;
- bool _displayWalkGrid;
- bool _displayMouseMarker;
- bool _displayTime;
- bool _displayPlayerMarker;
- bool _displayTextNumbers;
-
- bool _rectFlicker;
-
- int32 _startTime;
-
- int32 _showVar[MAX_SHOWVARS];
-
- byte _debugTextBlocks[MAX_DEBUG_TEXTS];
-
- void clearDebugTextBlocks();
- void makeDebugTextBlock(char *text, int16 x, int16 y);
-
- void plotCrossHair(int16 x, int16 y, uint8 pen);
- void drawRect(int16 x, int16 y, int16 x2, int16 y2, uint8 pen);
-
-public:
- Debugger(Sword2Engine *vm);
-
- int16 _rectX1, _rectY1;
- int16 _rectX2, _rectY2;
-
- uint8 _draggingRectangle;
- bool _definingRectangles;
-
- bool _testingSnR;
-
- int32 _speechScriptWaiting;
-
- int32 _textNumber;
-
- int32 _graphType;
- int32 _graphAnimRes;
- int32 _graphAnimPc;
- uint32 _graphNoFrames;
-
- void buildDebugText();
- void drawDebugGraphics();
-
-protected:
- Sword2Engine *_vm;
-
- virtual void preEnter();
- virtual void postEnter();
-
- // Commands
- bool Cmd_Exit(int argc, const char **argv);
- bool Cmd_Help(int argc, const char **argv);
- bool Cmd_Mem(int argc, const char **argv);
- bool Cmd_Tony(int argc, const char **argv);
- bool Cmd_Res(int argc, const char **argv);
- bool Cmd_ResList(int argc, const char **argv);
- bool Cmd_Starts(int argc, const char **argv);
- bool Cmd_Start(int argc, const char **argv);
- bool Cmd_Info(int argc, const char **argv);
- bool Cmd_WalkGrid(int argc, const char **argv);
- bool Cmd_Mouse(int argc, const char **argv);
- bool Cmd_Player(int argc, const char **argv);
- bool Cmd_ResLook(int argc, const char **argv);
- bool Cmd_CurrentInfo(int argc, const char **argv);
- bool Cmd_RunList(int argc, const char **argv);
- bool Cmd_Kill(int argc, const char **argv);
- bool Cmd_Nuke(int argc, const char **argv);
- bool Cmd_Var(int argc, const char **argv);
- bool Cmd_Rect(int argc, const char **argv);
- bool Cmd_Clear(int argc, const char **argv);
- bool Cmd_DebugOn(int argc, const char **argv);
- bool Cmd_DebugOff(int argc, const char **argv);
- bool Cmd_SaveRest(int argc, const char **argv);
- bool Cmd_TimeOn(int argc, const char **argv);
- bool Cmd_TimeOff(int argc, const char **argv);
- bool Cmd_Text(int argc, const char **argv);
- bool Cmd_ShowVar(int argc, const char **argv);
- bool Cmd_HideVar(int argc, const char **argv);
- bool Cmd_Version(int argc, const char **argv);
- bool Cmd_AnimTest(int argc, const char **argv);
- bool Cmd_TextTest(int argc, const char **argv);
- bool Cmd_LineTest(int argc, const char **argv);
- bool Cmd_Events(int argc, const char **argv);
- bool Cmd_Sfx(int argc, const char **argv);
- bool Cmd_English(int argc, const char **argv);
- bool Cmd_Finnish(int argc, const char **argv);
- bool Cmd_Polish(int argc, const char **argv);
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/controls.cpp b/sword2/controls.cpp
deleted file mode 100644
index df1b38c83e..0000000000
--- a/sword2/controls.cpp
+++ /dev/null
@@ -1,1416 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/rect.h"
-#include "common/config-manager.h"
-#include "common/system.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/controls.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-#define MAX_STRING_LEN 64 // 20 was too low; better to be safe ;)
-#define CHARACTER_OVERLAP 2 // overlap characters by 3 pixels
-
-// our fonts start on SPACE character (32)
-#define SIZE_OF_CHAR_SET (256 - 32)
-
-namespace Sword2 {
-
-static int baseSlot = 0;
-
-class Widget;
-
-/**
- * Base class for all widgets.
- */
-
-class Widget {
-protected:
- Sword2Engine *_vm;
- Dialog *_parent;
-
- SpriteInfo *_sprites;
-
- struct WidgetSurface {
- byte *_surface;
- bool _original;
- };
-
- WidgetSurface *_surfaces;
- int _numStates;
- int _state;
-
- Common::Rect _hitRect;
-
-public:
- Widget(Dialog *parent, int states);
-
- virtual ~Widget();
-
- void createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc);
- void linkSurfaceImage(Widget *from, int state, int x, int y);
-
- void createSurfaceImages(uint32 res, int x, int y);
- void linkSurfaceImages(Widget *from, int x, int y);
-
- void setHitRect(int x, int y, int width, int height);
- bool isHit(int16 x, int16 y);
-
- void setState(int state);
- int getState();
-
- virtual void paint(Common::Rect *clipRect = NULL);
-
- virtual void onMouseEnter() {}
- virtual void onMouseExit() {}
- virtual void onMouseMove(int x, int y) {}
- virtual void onMouseDown(int x, int y) {}
- virtual void onMouseUp(int x, int y) {}
- virtual void onWheelUp(int x, int y) {}
- virtual void onWheelDown(int x, int y) {}
- virtual void onKey(KeyboardEvent *ke) {}
- virtual void onTick() {}
-
- virtual void releaseMouse(int x, int y) {}
-};
-
-/**
- * This class is used to draw text in dialogs, buttons, etc.
- */
-
-class FontRendererGui {
-private:
- Sword2Engine *_vm;
-
- struct Glyph {
- byte *_data;
- int _width;
- int _height;
- };
-
- Glyph _glyph[SIZE_OF_CHAR_SET];
-
- int _fontId;
-
-public:
- enum {
- kAlignLeft,
- kAlignRight,
- kAlignCenter
- };
-
- FontRendererGui(Sword2Engine *vm, int fontId);
- ~FontRendererGui();
-
- void fetchText(uint32 textId, byte *buf);
-
- int getCharWidth(byte c);
- int getCharHeight(byte c);
-
- int getTextWidth(byte *text);
- int getTextWidth(uint32 textId);
-
- void drawText(byte *text, int x, int y, int alignment = kAlignLeft);
- void drawText(uint32 textId, int x, int y, int alignment = kAlignLeft);
-};
-
-FontRendererGui::FontRendererGui(Sword2Engine *vm, int fontId)
- : _vm(vm), _fontId(fontId) {
- byte *font = _vm->_resman->openResource(fontId);
- SpriteInfo sprite;
-
- sprite.type = RDSPR_NOCOMPRESSION | RDSPR_TRANS;
-
- for (int i = 0; i < SIZE_OF_CHAR_SET; i++) {
- byte *frame = _vm->fetchFrameHeader(font, i);
-
- FrameHeader frame_head;
-
- frame_head.read(frame);
-
- sprite.data = frame + FrameHeader::size();
- sprite.w = frame_head.width;
- sprite.h = frame_head.height;
- _vm->_screen->createSurface(&sprite, &_glyph[i]._data);
- _glyph[i]._width = frame_head.width;
- _glyph[i]._height = frame_head.height;
- }
-
- _vm->_resman->closeResource(fontId);
-}
-
-FontRendererGui::~FontRendererGui() {
- for (int i = 0; i < SIZE_OF_CHAR_SET; i++)
- _vm->_screen->deleteSurface(_glyph[i]._data);
-}
-
-void FontRendererGui::fetchText(uint32 textId, byte *buf) {
- byte *data = _vm->fetchTextLine(_vm->_resman->openResource(textId / SIZE), textId & 0xffff);
- int i;
-
- for (i = 0; data[i + 2]; i++) {
- if (buf)
- buf[i] = data[i + 2];
- }
-
- buf[i] = 0;
- _vm->_resman->closeResource(textId / SIZE);
-}
-
-int FontRendererGui::getCharWidth(byte c) {
- if (c < 32)
- return 0;
- return _glyph[c - 32]._width;
-}
-
-int FontRendererGui::getCharHeight(byte c) {
- if (c < 32)
- return 0;
- return _glyph[c - 32]._height;
-}
-
-int FontRendererGui::getTextWidth(byte *text) {
- int textWidth = 0;
-
- for (int i = 0; text[i]; i++)
- if (text[i] >= ' ')
- textWidth += (getCharWidth(text[i]) - CHARACTER_OVERLAP);
- return textWidth;
-}
-
-int FontRendererGui::getTextWidth(uint32 textId) {
- byte text[MAX_STRING_LEN];
-
- fetchText(textId, text);
- return getTextWidth(text);
-}
-
-void FontRendererGui::drawText(byte *text, int x, int y, int alignment) {
- SpriteInfo sprite;
- int i;
-
- if (alignment != kAlignLeft) {
- int textWidth = getTextWidth(text);
-
- switch (alignment) {
- case kAlignRight:
- x -= textWidth;
- break;
- case kAlignCenter:
- x -= (textWidth / 2);
- break;
- }
- }
-
- sprite.x = x;
- sprite.y = y;
-
- for (i = 0; text[i]; i++) {
- if (text[i] >= ' ') {
- sprite.w = getCharWidth(text[i]);
- sprite.h = getCharHeight(text[i]);
-
- _vm->_screen->drawSurface(&sprite, _glyph[text[i] - 32]._data);
-
- sprite.x += (getCharWidth(text[i]) - CHARACTER_OVERLAP);
- }
- }
-}
-
-void FontRendererGui::drawText(uint32 textId, int x, int y, int alignment) {
- byte text[MAX_STRING_LEN];
-
- fetchText(textId, text);
- drawText(text, x, y, alignment);
-}
-
-//
-// Dialog class functions
-//
-
-Dialog::Dialog(Sword2Engine *vm)
- : _numWidgets(0), _finish(false), _result(0), _vm(vm) {
- _vm->_screen->setFullPalette(CONTROL_PANEL_PALETTE);
- _vm->_screen->clearScene();
- _vm->_screen->updateDisplay();
-
- // Usually the mouse pointer will already be "normal", but not always.
- _vm->_mouse->setMouse(NORMAL_MOUSE_ID);
-}
-
-Dialog::~Dialog() {
- for (int i = 0; i < _numWidgets; i++)
- delete _widgets[i];
- _vm->_screen->clearScene();
- _vm->_screen->updateDisplay();
-}
-
-void Dialog::registerWidget(Widget *widget) {
- if (_numWidgets < MAX_WIDGETS)
- _widgets[_numWidgets++] = widget;
-}
-
-void Dialog::paint() {
- _vm->_screen->clearScene();
- for (int i = 0; i < _numWidgets; i++)
- _widgets[i]->paint();
-}
-
-void Dialog::setResult(int result) {
- _result = result;
- _finish = true;
-}
-
-int Dialog::runModal() {
- uint32 oldFilter = _vm->setInputEventFilter(0);
-
- int i;
-
- paint();
-
- int oldMouseX = -1;
- int oldMouseY = -1;
-
- while (!_finish) {
- // So that the menu icons will reach their full size
- _vm->_mouse->processMenu();
- _vm->_screen->updateDisplay(false);
-
- int newMouseX, newMouseY;
-
- _vm->_mouse->getPos(newMouseX, newMouseY);
-
- newMouseY += 40;
-
- MouseEvent *me = _vm->mouseEvent();
- KeyboardEvent *ke = _vm->keyboardEvent();
-
- if (ke) {
- if (ke->keycode == 27)
- setResult(0);
- else if (ke->keycode == '\n' || ke->keycode == '\r')
- setResult(1);
- }
-
- int oldHit = -1;
- int newHit = -1;
-
- // Find out which widget the mouse was over the last time, and
- // which it is currently over. This assumes the widgets do not
- // overlap.
-
- for (i = 0; i < _numWidgets; i++) {
- if (_widgets[i]->isHit(oldMouseX, oldMouseY))
- oldHit = i;
- if (_widgets[i]->isHit(newMouseX, newMouseY))
- newHit = i;
- }
-
- // Was the mouse inside a widget the last time?
-
- if (oldHit >= 0) {
- if (newHit != oldHit)
- _widgets[oldHit]->onMouseExit();
- }
-
- // Is the mouse currently in a widget?
-
- if (newHit >= 0) {
- if (newHit != oldHit)
- _widgets[newHit]->onMouseEnter();
-
- if (me) {
- switch (me->buttons) {
- case RD_LEFTBUTTONDOWN:
- _widgets[newHit]->onMouseDown(newMouseX, newMouseY);
- break;
- case RD_LEFTBUTTONUP:
- _widgets[newHit]->onMouseUp(newMouseX, newMouseY);
- break;
- case RD_WHEELUP:
- _widgets[newHit]->onWheelUp(newMouseX, newMouseY);
- break;
- case RD_WHEELDOWN:
- _widgets[newHit]->onWheelDown(newMouseX, newMouseY);
- break;
- }
- }
- }
-
- // Some events are passed to the widgets regardless of where
- // the mouse cursor is.
-
- for (i = 0; i < _numWidgets; i++) {
- if (me && me->buttons == RD_LEFTBUTTONUP) {
- // So that slider widgets will know when the
- // user releases the mouse button, even if the
- // cursor is outside of the slider's hit area.
- _widgets[i]->releaseMouse(newMouseX, newMouseY);
- }
-
- // This is to make it easier to drag the slider widget
-
- if (newMouseX != oldMouseX || newMouseY != oldMouseY)
- _widgets[i]->onMouseMove(newMouseX, newMouseY);
-
- if (ke)
- _widgets[i]->onKey(ke);
-
- _widgets[i]->onTick();
- }
-
- oldMouseX = newMouseX;
- oldMouseY = newMouseY;
-
- _vm->_system->delayMillis(20);
-
- if (_vm->_quit)
- setResult(0);
- }
-
- _vm->setInputEventFilter(oldFilter);
- return _result;
-}
-
-//
-// Widget functions
-//
-
-Widget::Widget(Dialog *parent, int states)
- : _vm(parent->_vm), _parent(parent), _numStates(states), _state(0) {
- _sprites = (SpriteInfo *)calloc(states, sizeof(SpriteInfo));
- _surfaces = (WidgetSurface *)calloc(states, sizeof(WidgetSurface));
-
- _hitRect.left = _hitRect.right = _hitRect.top = _hitRect.bottom = -1;
-}
-
-Widget::~Widget() {
- for (int i = 0; i < _numStates; i++) {
- if (_surfaces[i]._original)
- _vm->_screen->deleteSurface(_surfaces[i]._surface);
- }
- free(_sprites);
- free(_surfaces);
-}
-
-void Widget::createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc) {
- byte *file, *colTablePtr = NULL;
- AnimHeader anim_head;
- FrameHeader frame_head;
- CdtEntry cdt_entry;
- uint32 spriteType = RDSPR_TRANS;
-
- // open anim resource file, point to base
- file = _vm->_resman->openResource(res);
-
- byte *frame = _vm->fetchFrameHeader(file, pc);
-
- anim_head.read(_vm->fetchAnimHeader(file));
- cdt_entry.read(_vm->fetchCdtEntry(file, pc));
- frame_head.read(frame);
-
- // If the frame is flipped. (Only really applicable to frames using
- // offsets.)
-
- if (cdt_entry.frameType & FRAME_FLIPPED)
- spriteType |= RDSPR_FLIP;
-
- // Which compression was used?
-
- switch (anim_head.runTimeComp) {
- case NONE:
- spriteType |= RDSPR_NOCOMPRESSION;
- break;
- case RLE256:
- spriteType |= RDSPR_RLE256;
- break;
- case RLE16:
- spriteType |= RDSPR_RLE256;
- // Points to just after last cdt_entry, i.e. start of colour
- // table
- colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size()
- + anim_head.noAnimFrames * CdtEntry::size();
- break;
- }
-
- _sprites[state].x = x;
- _sprites[state].y = y;
- _sprites[state].w = frame_head.width;
- _sprites[state].h = frame_head.height;
- _sprites[state].scale = 0;
- _sprites[state].type = spriteType;
- _sprites[state].blend = anim_head.blend;
-
- // Points to just after frame header, ie. start of sprite data
- _sprites[state].data = frame + FrameHeader::size();
-
- _vm->_screen->createSurface(&_sprites[state], &_surfaces[state]._surface);
- _surfaces[state]._original = true;
-
- // Release the anim resource
- _vm->_resman->closeResource(res);
-}
-
-void Widget::linkSurfaceImage(Widget *from, int state, int x, int y) {
- _sprites[state].x = x;
- _sprites[state].y = y;
- _sprites[state].w = from->_sprites[state].w;
- _sprites[state].h = from->_sprites[state].h;
- _sprites[state].scale = from->_sprites[state].scale;
- _sprites[state].type = from->_sprites[state].type;
- _sprites[state].blend = from->_sprites[state].blend;
-
- _surfaces[state]._surface = from->_surfaces[state]._surface;
- _surfaces[state]._original = false;
-}
-
-void Widget::createSurfaceImages(uint32 res, int x, int y) {
- for (int i = 0; i < _numStates; i++)
- createSurfaceImage(i, res, x, y, i);
-}
-
-void Widget::linkSurfaceImages(Widget *from, int x, int y) {
- for (int i = 0; i < from->_numStates; i++)
- linkSurfaceImage(from, i, x, y);
-}
-
-void Widget::setHitRect(int x, int y, int width, int height) {
- _hitRect.left = x;
- _hitRect.right = x + width;
- _hitRect.top = y;
- _hitRect.bottom = y + height;
-}
-
-bool Widget::isHit(int16 x, int16 y) {
- return _hitRect.left >= 0 && _hitRect.contains(x, y);
-}
-
-void Widget::setState(int state) {
- if (state != _state) {
- _state = state;
- paint();
- }
-}
-
-int Widget::getState() {
- return _state;
-}
-
-void Widget::paint(Common::Rect *clipRect) {
- _vm->_screen->drawSurface(&_sprites[_state], _surfaces[_state]._surface, clipRect);
-}
-
-/**
- * Standard button class.
- */
-
-class Button : public Widget {
-public:
- Button(Dialog *parent, int x, int y, int w, int h)
- : Widget(parent, 2) {
- setHitRect(x, y, w, h);
- }
-
- virtual void onMouseExit() {
- setState(0);
- }
-
- virtual void onMouseDown(int x, int y) {
- setState(1);
- }
-
- virtual void onMouseUp(int x, int y) {
- if (getState() != 0) {
- setState(0);
- _parent->onAction(this);
- }
- }
-};
-
-/**
- * Scroll buttons are used to scroll the savegame list. The difference between
- * this and a normal button is that we want this to repeat.
- */
-
-class ScrollButton : public Widget {
-private:
- uint32 _holdCounter;
-
-public:
- ScrollButton(Dialog *parent, int x, int y, int w, int h)
- : Widget(parent, 2), _holdCounter(0) {
- setHitRect(x, y, w, h);
- }
-
- virtual void onMouseExit() {
- setState(0);
- }
-
- virtual void onMouseDown(int x, int y) {
- setState(1);
- _parent->onAction(this);
- _holdCounter = 0;
- }
-
- virtual void onMouseUp(int x, int y) {
- setState(0);
- }
-
- virtual void onTick() {
- if (getState() != 0) {
- _holdCounter++;
- if (_holdCounter > 16 && (_holdCounter % 4) == 0)
- _parent->onAction(this);
- }
- }
-};
-
-/**
- * A switch is a button that changes state when clicked, and keeps that state
- * until clicked again.
- */
-
-class Switch : public Widget {
-private:
- bool _holding, _value;
- int _upState, _downState;
-
-public:
- Switch(Dialog *parent, int x, int y, int w, int h)
- : Widget(parent, 2), _holding(false), _value(false),
- _upState(0), _downState(1) {
- setHitRect(x, y, w, h);
- }
-
- // The sound mute switches have 0 as their "down" state and 1 as
- // their "up" state, so this function is needed to get consistent
- // behaviour.
-
- void reverseStates() {
- _upState = 1;
- _downState = 0;
- }
-
- void setValue(bool value) {
- _value = value;
- if (_value)
- setState(_downState);
- else
- setState(_upState);
- }
-
- bool getValue() {
- return _value;
- }
-
- virtual void onMouseExit() {
- if (_holding && !_value)
- setState(_upState);
- _holding = false;
- }
-
- virtual void onMouseDown(int x, int y) {
- _holding = true;
- setState(_downState);
- }
-
- virtual void onMouseUp(int x, int y) {
- if (_holding) {
- _holding = false;
- _value = !_value;
- if (_value)
- setState(_downState);
- else
- setState(_upState);
- _parent->onAction(this, getState());
- }
- }
-};
-
-/**
- * A slider is used to specify a value within a pre-defined range.
- */
-
-class Slider : public Widget {
-private:
- Widget *_background;
- bool _dragging;
- int _value, _targetValue;
- int _maxValue;
- int _valueStep;
- int _dragOffset;
-
- int posFromValue(int value) {
- return _hitRect.left + (value * (_hitRect.width() - 38)) / _maxValue;
- }
-
- int valueFromPos(int x) {
- return (int)((double)(_maxValue * (x - _hitRect.left)) / (double)(_hitRect.width() - 38) + 0.5);
- }
-
-public:
- Slider(Dialog *parent, Widget *background, int max,
- int x, int y, int w, int h, int step, Widget *base = NULL)
- : Widget(parent, 1), _background(background),
- _dragging(false), _value(0), _targetValue(0),
- _maxValue(max), _valueStep(step) {
- setHitRect(x, y, w, h);
-
- if (_valueStep <= 0)
- _valueStep = 1;
-
- if (base)
- linkSurfaceImages(base, x, y);
- else
- createSurfaceImages(3406, x, y);
- }
-
- virtual void paint(Common::Rect *clipRect = NULL) {
- // This will redraw a bit more than is strictly necessary,
- // but I doubt that will make any noticeable difference.
-
- _background->paint(&_hitRect);
- Widget::paint(clipRect);
- }
-
- void setValue(int value) {
- _value = value;
- _targetValue = value;
- _sprites[0].x = posFromValue(_value);
- paint();
- }
-
- int getValue() {
- return _value;
- }
-
- virtual void onMouseMove(int x, int y) {
- if (_dragging) {
- int newX = x - _dragOffset;
- int newValue;
-
- if (newX < _hitRect.left)
- newX = _hitRect.left;
- else if (newX + 38 > _hitRect.right)
- newX = _hitRect.right - 38;
-
- _sprites[0].x = newX;
-
- newValue = valueFromPos(newX);
- if (newValue != _value) {
- _value = newValue;
- _targetValue = newValue;
- _parent->onAction(this, newValue);
- }
-
- paint();
- }
- }
-
- virtual void onMouseDown(int x, int y) {
- if (x >= _sprites[0].x && x < _sprites[0].x + 38) {
- _dragging = true;
- _dragOffset = x - _sprites[0].x;
- } else if (x < _sprites[0].x) {
- if (_targetValue >= _valueStep)
- _targetValue -= _valueStep;
- else
- _targetValue = 0;
- } else {
- if (_targetValue < _maxValue - _valueStep)
- _targetValue += _valueStep;
- else
- _targetValue = _maxValue;
- }
- }
-
- virtual void releaseMouse(int x, int y) {
- if (_dragging)
- _dragging = false;
- }
-
- virtual void onTick() {
- if (!_dragging) {
- int target = posFromValue(_targetValue);
-
- if (target != _sprites[0].x) {
- if (target < _sprites[0].x) {
- _sprites[0].x -= 4;
- if (_sprites[0].x < target)
- _sprites[0].x = target;
- } else if (target > _sprites[0].x) {
- _sprites[0].x += 4;
- if (_sprites[0].x > target)
- _sprites[0].x = target;
- }
-
- int newValue = valueFromPos(_sprites[0].x);
- if (newValue != _value) {
- _value = newValue;
- _parent->onAction(this, newValue);
- }
-
- paint();
- }
- }
- }
-};
-
-/**
- * The "mini" dialog.
- */
-
-MiniDialog::MiniDialog(Sword2Engine *vm, uint32 headerTextId, uint32 okTextId, uint32 cancelTextId) : Dialog(vm) {
- _headerTextId = headerTextId;
- _okTextId = okTextId;
- _cancelTextId = cancelTextId;
-
- _fr = new FontRendererGui(_vm, _vm->_controlsFontId);
-
- _panel = new Widget(this, 1);
- _panel->createSurfaceImages(1996, 203, 104);
-
- _okButton = new Button(this, 243, 214, 24, 24);
- _okButton->createSurfaceImages(2002, 243, 214);
-
- _cancelButton = new Button(this, 243, 276, 24, 24);
- _cancelButton->linkSurfaceImages(_okButton, 243, 276);
-
- registerWidget(_panel);
- registerWidget(_okButton);
- registerWidget(_cancelButton);
-}
-
-MiniDialog::~MiniDialog() {
- delete _fr;
-}
-
-void MiniDialog::paint() {
- Dialog::paint();
-
- if (_headerTextId)
- _fr->drawText(_headerTextId, 310, 134, FontRendererGui::kAlignCenter);
- _fr->drawText(_okTextId, 270, 214);
- _fr->drawText(_cancelTextId, 270, 276);
-}
-
-void MiniDialog::onAction(Widget *widget, int result) {
- if (widget == _okButton)
- setResult(1);
- else if (widget == _cancelButton)
- setResult(0);
-}
-
-StartDialog::StartDialog(Sword2Engine *vm) : MiniDialog(vm, 0) {}
-
-int StartDialog::runModal() {
- while (1) {
- MiniDialog startDialog(_vm, 0, TEXT_RESTART, TEXT_RESTORE);
-
- if (startDialog.runModal())
- return 1;
-
- if (_vm->_quit)
- return 0;
-
- RestoreDialog restoreDialog(_vm);
-
- if (restoreDialog.runModal())
- return 0;
-
- if (_vm->_quit)
- return 0;
- }
-
- return 1;
-}
-
-/**
- * The restart dialog.
- */
-
-RestartDialog::RestartDialog(Sword2Engine *vm) : MiniDialog(vm, TEXT_RESTART) {}
-
-int RestartDialog::runModal() {
- int result = MiniDialog::runModal();
-
- if (result)
- _vm->restartGame();
-
- return result;
-}
-
-/**
- * The quit dialog.
- */
-
-QuitDialog::QuitDialog(Sword2Engine *vm) : MiniDialog(vm, TEXT_QUIT) {}
-
-int QuitDialog::runModal() {
- int result = MiniDialog::runModal();
-
- if (result)
- _vm->closeGame();
-
- return result;
-}
-
-/**
- * The game settings dialog.
- */
-
-OptionsDialog::OptionsDialog(Sword2Engine *vm) : Dialog(vm) {
- _fr = new FontRendererGui(_vm, _vm->_controlsFontId);
-
- _mixer = _vm->_mixer;
-
- _panel = new Widget(this, 1);
- _panel->createSurfaceImages(3405, 0, 40);
-
- _objectLabelsSwitch = new Switch(this, 304, 100, 53, 32);
- _objectLabelsSwitch->createSurfaceImages(3687, 304, 100);
-
- _subtitlesSwitch = new Switch(this, 510, 100, 53, 32);
- _subtitlesSwitch->linkSurfaceImages(_objectLabelsSwitch, 510, 100);
-
- _reverseStereoSwitch = new Switch(this, 304, 293, 53, 32);
- _reverseStereoSwitch->linkSurfaceImages(_objectLabelsSwitch, 304, 293);
-
- _musicSwitch = new Switch(this, 516, 157, 40, 32);
- _musicSwitch->createSurfaceImages(3315, 516, 157);
- _musicSwitch->reverseStates();
-
- _speechSwitch = new Switch(this, 516, 205, 40, 32);
- _speechSwitch->linkSurfaceImages(_musicSwitch, 516, 205);
- _speechSwitch->reverseStates();
-
- _fxSwitch = new Switch(this, 516, 250, 40, 32);
- _fxSwitch->linkSurfaceImages(_musicSwitch, 516, 250);
- _fxSwitch->reverseStates();
-
- int volStep = Audio::Mixer::kMaxMixerVolume / 10;
-
- _musicSlider = new Slider(this, _panel, Audio::Mixer::kMaxMixerVolume, 309, 161, 170, 27, volStep);
- _speechSlider = new Slider(this, _panel, Audio::Mixer::kMaxMixerVolume, 309, 208, 170, 27, volStep, _musicSlider);
- _fxSlider = new Slider(this, _panel, Audio::Mixer::kMaxMixerVolume, 309, 254, 170, 27, volStep, _musicSlider);
- _gfxSlider = new Slider(this, _panel, 3, 309, 341, 170, 27, 1, _musicSlider);
-
- _gfxPreview = new Widget(this, 4);
- _gfxPreview->createSurfaceImages(256, 495, 310);
-
- _okButton = new Button(this, 203, 382, 53, 32);
- _okButton->createSurfaceImages(901, 203, 382);
-
- _cancelButton = new Button(this, 395, 382, 53, 32);
- _cancelButton->linkSurfaceImages(_okButton, 395, 382);
-
- registerWidget(_panel);
- registerWidget(_objectLabelsSwitch);
- registerWidget(_subtitlesSwitch);
- registerWidget(_reverseStereoSwitch);
- registerWidget(_musicSwitch);
- registerWidget(_speechSwitch);
- registerWidget(_fxSwitch);
- registerWidget(_musicSlider);
- registerWidget(_speechSlider);
- registerWidget(_fxSlider);
- registerWidget(_gfxSlider);
- registerWidget(_gfxPreview);
- registerWidget(_okButton);
- registerWidget(_cancelButton);
-
- _objectLabelsSwitch->setValue(_vm->_mouse->getObjectLabels());
- _subtitlesSwitch->setValue(_vm->getSubtitles());
- _reverseStereoSwitch->setValue(_vm->_sound->isReverseStereo());
- _musicSwitch->setValue(!_vm->_sound->isMusicMute());
- _speechSwitch->setValue(!_vm->_sound->isSpeechMute());
- _fxSwitch->setValue(!_vm->_sound->isFxMute());
-
- _musicSlider->setValue(_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
- _speechSlider->setValue(_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
- _fxSlider->setValue(_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
-
- _gfxSlider->setValue(_vm->_screen->getRenderLevel());
- _gfxPreview->setState(_vm->_screen->getRenderLevel());
-}
-
-OptionsDialog::~OptionsDialog() {
- delete _fr;
-}
-
-void OptionsDialog::paint() {
- Dialog::paint();
-
- int maxWidth = 0;
- int width;
-
- uint32 alignTextIds[] = {
- TEXT_OBJECT_LABELS,
- TEXT_MUSIC_VOLUME,
- TEXT_SPEECH_VOLUME,
- TEXT_FX_VOLUME,
- TEXT_GFX_QUALITY,
- TEXT_REVERSE_STEREO
- };
-
- for (int i = 0; i < ARRAYSIZE(alignTextIds); i++) {
- width = _fr->getTextWidth(alignTextIds[i]);
- if (width > maxWidth)
- maxWidth = width;
- }
-
- _fr->drawText(TEXT_OPTIONS, 321, 55, FontRendererGui::kAlignCenter);
- _fr->drawText(TEXT_SUBTITLES, 500, 103, FontRendererGui::kAlignRight);
- _fr->drawText(TEXT_OBJECT_LABELS, 299 - maxWidth, 103);
- _fr->drawText(TEXT_MUSIC_VOLUME, 299 - maxWidth, 161);
- _fr->drawText(TEXT_SPEECH_VOLUME, 299 - maxWidth, 208);
- _fr->drawText(TEXT_FX_VOLUME, 299 - maxWidth, 254);
- _fr->drawText(TEXT_REVERSE_STEREO, 299 - maxWidth, 296);
- _fr->drawText(TEXT_GFX_QUALITY, 299 - maxWidth, 341);
- _fr->drawText(TEXT_OK, 193, 382, FontRendererGui::kAlignRight);
- _fr->drawText(TEXT_CANCEL, 385, 382, FontRendererGui::kAlignRight);
-}
-
-void OptionsDialog::onAction(Widget *widget, int result) {
- // Since there is music playing while the dialog is displayed we need
- // to update music volume immediately.
-
- if (widget == _musicSwitch) {
- _vm->_sound->muteMusic(result != 0);
- } else if (widget == _musicSlider) {
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, result);
- _vm->_sound->muteMusic(result == 0);
- _musicSwitch->setValue(result != 0);
- } else if (widget == _speechSlider) {
- _speechSwitch->setValue(result != 0);
- } else if (widget == _fxSlider) {
- _fxSwitch->setValue(result != 0);
- } else if (widget == _gfxSlider) {
- _gfxPreview->setState(result);
- _vm->_screen->setRenderLevel(result);
- } else if (widget == _okButton) {
- // Apply the changes
- _vm->setSubtitles(_subtitlesSwitch->getValue());
- _vm->_mouse->setObjectLabels(_objectLabelsSwitch->getValue());
- _vm->_sound->muteMusic(!_musicSwitch->getValue());
- _vm->_sound->muteSpeech(!_speechSwitch->getValue());
- _vm->_sound->muteFx(!_fxSwitch->getValue());
- _vm->_sound->setReverseStereo(_reverseStereoSwitch->getValue());
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _musicSlider->getValue());
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _speechSlider->getValue());
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _fxSlider->getValue());
- _vm->_screen->setRenderLevel(_gfxSlider->getValue());
-
- _vm->writeSettings();
- setResult(1);
- } else if (widget == _cancelButton) {
- // Revert the changes
- _vm->readSettings();
- setResult(0);
- }
-}
-
-// Slot button actions. Note that keyboard input generates positive actions
-
-enum {
- kSelectSlot = -1,
- kDeselectSlot = -2,
- kWheelDown = -3,
- kWheelUp = -4,
- kStartEditing = -5,
- kCursorTick = -6
-};
-
-class Slot : public Widget {
-private:
- int _mode;
- FontRendererGui *_fr;
- byte _text[SAVE_DESCRIPTION_LEN];
- bool _clickable;
- bool _editable;
-
-public:
- Slot(Dialog *parent, int x, int y, int w, int h)
- : Widget(parent, 2), _clickable(false), _editable(false) {
- setHitRect(x, y, w, h);
- _text[0] = 0;
- }
-
- void setMode(int mode) {
- _mode = mode;
- }
-
- void setClickable(bool clickable) {
- _clickable = clickable;
- }
-
- void setEditable(bool editable) {
- _editable = editable;
- _vm->_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, editable);
- }
-
- bool isEditable() {
- return _editable;
- }
-
- void setText(FontRendererGui *fr, int slot, byte *text) {
- _fr = fr;
- if (text)
- sprintf((char *)_text, "%d. %s", slot, text);
- else
- sprintf((char *)_text, "%d. ", slot);
- }
-
- byte *getText() {
- return &_text[0];
- }
-
- virtual void paint(Common::Rect *clipRect = NULL) {
- Widget::paint();
-
- // HACK: The main dialog is responsible for drawing the text
- // when in editing mode.
-
- if (!_editable)
- _fr->drawText(_text, _sprites[0].x + 16, _sprites[0].y + 4 + 2 * getState());
- }
-
- virtual void onMouseDown(int x, int y) {
- if (_clickable) {
- if (getState() == 0) {
- setState(1);
- _parent->onAction(this, kSelectSlot);
- if (_mode == kSaveDialog)
- _parent->onAction(this, kStartEditing);
- } else if (_mode == kRestoreDialog) {
- setState(0);
- _parent->onAction(this, kDeselectSlot);
- }
- }
- }
-
- virtual void onWheelUp(int x, int y) {
- _parent->onAction(this, kWheelUp);
- }
-
- virtual void onWheelDown(int x, int y) {
- _parent->onAction(this, kWheelDown);
- }
-
- virtual void onKey(KeyboardEvent *ke) {
- if (_editable) {
- if (ke->keycode == 8)
- _parent->onAction(this, 8);
- else if (ke->ascii >= ' ' && ke->ascii <= 255) {
- // Accept the character if the font renderer
- // has what looks like a valid glyph for it.
- if (_fr->getCharWidth(ke->ascii))
- _parent->onAction(this, ke->ascii);
- }
- }
- }
-
- virtual void onTick() {
- if (_editable)
- _parent->onAction(this, kCursorTick);
- }
-
- void setY(int y) {
- for (int i = 0; i < _numStates; i++)
- _sprites[i].y = y;
- setHitRect(_hitRect.left, y, _hitRect.width(), _hitRect.height());
- }
-
- int getY() {
- return _sprites[0].y;
- }
-};
-
-SaveRestoreDialog::SaveRestoreDialog(Sword2Engine *vm, int mode) : Dialog(vm) {
- int i;
-
- _mode = mode;
- _selectedSlot = -1;
-
- // FIXME: The "control font" and the "red font" are currently always
- // the same font, so one should be eliminated.
-
- _fr1 = new FontRendererGui(_vm, _vm->_controlsFontId);
- _fr2 = new FontRendererGui(_vm, _vm->_redFontId);
-
- _panel = new Widget(this, 1);
- _panel->createSurfaceImages(2016, 0, 40);
-
- for (i = 0; i < 4; i++) {
- _slotButton[i] = new Slot(this, 114, 0, 384, 36);
- _slotButton[i]->createSurfaceImages(2006 + i, 114, 0);
- _slotButton[i]->setMode(mode);
- _slotButton[i + 4] = new Slot(this, 114, 0, 384, 36);
- _slotButton[i + 4]->linkSurfaceImages(_slotButton[i], 114, 0);
- _slotButton[i + 4]->setMode(mode);
- }
-
- updateSlots();
-
- _zupButton = new ScrollButton(this, 516, 65, 17, 17);
- _zupButton->createSurfaceImages(1982, 516, 65);
-
- _upButton = new ScrollButton(this, 516, 85, 17, 17);
- _upButton->createSurfaceImages(2067, 516, 85);
-
- _downButton = new ScrollButton(this, 516, 329, 17, 17);
- _downButton->createSurfaceImages(1986, 516, 329);
-
- _zdownButton = new ScrollButton(this, 516, 350, 17, 17);
- _zdownButton->createSurfaceImages(1988, 516, 350);
-
- _okButton = new Button(this, 130, 377, 24, 24);
- _okButton->createSurfaceImages(2002, 130, 377);
-
- _cancelButton = new Button(this, 350, 377, 24, 24);
- _cancelButton->linkSurfaceImages(_okButton, 350, 377);
-
- registerWidget(_panel);
-
- for (i = 0; i < 8; i++)
- registerWidget(_slotButton[i]);
-
- registerWidget(_zupButton);
- registerWidget(_upButton);
- registerWidget(_downButton);
- registerWidget(_zdownButton);
- registerWidget(_okButton);
- registerWidget(_cancelButton);
-}
-
-SaveRestoreDialog::~SaveRestoreDialog() {
- delete _fr1;
- delete _fr2;
-}
-
-// There aren't really a hundred different button objects of course, there are
-// only eight. Re-arrange them to simulate scrolling.
-
-void SaveRestoreDialog::updateSlots() {
- for (int i = 0; i < 8; i++) {
- Slot *slot = _slotButton[(baseSlot + i) % 8];
- FontRendererGui *fr;
- byte description[SAVE_DESCRIPTION_LEN];
-
- slot->setY(72 + i * 36);
-
- if (baseSlot + i == _selectedSlot) {
- slot->setEditable(_mode == kSaveDialog);
- slot->setState(1);
- fr = _fr2;
- } else {
- slot->setEditable(false);
- slot->setState(0);
- fr = _fr1;
- }
-
- if (_vm->getSaveDescription(baseSlot + i, description) == SR_OK) {
- slot->setText(fr, baseSlot + i, description);
- slot->setClickable(true);
- } else {
- slot->setText(fr, baseSlot + i, NULL);
- slot->setClickable(_mode == kSaveDialog);
- }
-
- if (slot->isEditable())
- drawEditBuffer(slot);
- else
- slot->paint();
- }
-}
-
-void SaveRestoreDialog::drawEditBuffer(Slot *slot) {
- if (_selectedSlot == -1)
- return;
-
- // This will redraw a bit more than is strictly necessary, but I doubt
- // that will make any noticeable difference.
-
- slot->paint();
- _fr2->drawText(_editBuffer, 130, 78 + (_selectedSlot - baseSlot) * 36);
-}
-
-void SaveRestoreDialog::onAction(Widget *widget, int result) {
- if (widget == _zupButton) {
- if (baseSlot > 0) {
- if (baseSlot >= 8)
- baseSlot -= 8;
- else
- baseSlot = 0;
- updateSlots();
- }
- } else if (widget == _upButton) {
- if (baseSlot > 0) {
- baseSlot--;
- updateSlots();
- }
- } else if (widget == _downButton) {
- if (baseSlot < 92) {
- baseSlot++;
- updateSlots();
- }
- } else if (widget == _zdownButton) {
- if (baseSlot < 92) {
- if (baseSlot <= 84)
- baseSlot += 8;
- else
- baseSlot = 92;
- updateSlots();
- }
- } else if (widget == _okButton) {
- setResult(1);
- } else if (widget == _cancelButton) {
- setResult(0);
- } else {
- Slot *slot = (Slot *)widget;
- int textWidth;
- byte tmp;
- int i;
- int j;
-
- switch (result) {
- case kWheelUp:
- onAction(_upButton);
- break;
- case kWheelDown:
- onAction(_downButton);
- break;
- case kSelectSlot:
- case kDeselectSlot:
- if (result == kSelectSlot)
- _selectedSlot = baseSlot + (slot->getY() - 72) / 35;
- else if (result == kDeselectSlot)
- _selectedSlot = -1;
-
- for (i = 0; i < 8; i++)
- if (widget == _slotButton[i])
- break;
-
- for (j = 0; j < 8; j++) {
- if (j != i) {
- _slotButton[j]->setEditable(false);
- _slotButton[j]->setState(0);
- }
- }
- break;
- case kStartEditing:
- if (_selectedSlot >= 10)
- _firstPos = 5;
- else
- _firstPos = 4;
-
- strcpy((char *)_editBuffer, (char *)slot->getText());
- _editPos = strlen((char *)_editBuffer);
- _cursorTick = 0;
- _editBuffer[_editPos] = '_';
- _editBuffer[_editPos + 1] = 0;
- slot->setEditable(true);
- drawEditBuffer(slot);
- break;
- case kCursorTick:
- _cursorTick++;
- if (_cursorTick == 7) {
- _editBuffer[_editPos] = ' ';
- drawEditBuffer(slot);
- } else if (_cursorTick == 14) {
- _cursorTick = 0;
- _editBuffer[_editPos] = '_';
- drawEditBuffer(slot);
- }
- break;
- case 8:
- if (_editPos > _firstPos) {
- _editBuffer[_editPos - 1] = _editBuffer[_editPos];
- _editBuffer[_editPos--] = 0;
- drawEditBuffer(slot);
- }
- break;
- default:
- tmp = _editBuffer[_editPos];
- _editBuffer[_editPos] = 0;
- textWidth = _fr2->getTextWidth(_editBuffer);
- _editBuffer[_editPos] = tmp;
-
- if (textWidth < 340 && _editPos < SAVE_DESCRIPTION_LEN - 2) {
- _editBuffer[_editPos + 1] = _editBuffer[_editPos];
- _editBuffer[_editPos + 2] = 0;
- _editBuffer[_editPos++] = result;
- drawEditBuffer(slot);
- }
- break;
- }
- }
-}
-
-void SaveRestoreDialog::paint() {
- Dialog::paint();
-
- _fr1->drawText((_mode == kRestoreDialog) ? TEXT_RESTORE : TEXT_SAVE, 165, 377);
- _fr1->drawText(TEXT_CANCEL, 382, 377);
-}
-
-void SaveRestoreDialog::setResult(int result) {
- if (result) {
- if (_selectedSlot == -1)
- return;
-
- if (_mode == kSaveDialog) {
- if (_editPos <= _firstPos)
- return;
- }
- }
-
- Dialog::setResult(result);
-}
-
-int SaveRestoreDialog::runModal() {
- int result = Dialog::runModal();
-
- if (result) {
- switch (_mode) {
- case kSaveDialog:
- // Remove the cursor character from the savegame name
- _editBuffer[_editPos] = 0;
-
- if (_vm->saveGame(_selectedSlot, (byte *)&_editBuffer[_firstPos]) != SR_OK)
- result = 0;
- break;
- case kRestoreDialog:
- if (_vm->restoreGame(_selectedSlot) != SR_OK)
- result = 0;
- break;
- }
- }
-
- return result;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/controls.h b/sword2/controls.h
deleted file mode 100644
index 719489b3ae..0000000000
--- a/sword2/controls.h
+++ /dev/null
@@ -1,183 +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 _CONTROL_S
-#define _CONTROL_S
-
-#include "sword2/defs.h"
-
-#define MAX_WIDGETS 25
-
-namespace Sword2 {
-
-class Sword2Engine;
-class FontRendererGui;
-class Widget;
-class Switch;
-class Slider;
-class Button;
-class ScrollButton;
-class Slot;
-
-enum {
- kSaveDialog,
- kRestoreDialog
-};
-
-/**
- * Base class for all dialogs.
- */
-
-class Dialog {
-private:
- int _numWidgets;
- Widget *_widgets[MAX_WIDGETS];
- bool _finish;
- int _result;
-
-public:
- Sword2Engine *_vm;
-
- Dialog(Sword2Engine *vm);
- virtual ~Dialog();
-
- void registerWidget(Widget *widget);
-
- virtual void paint();
- virtual void setResult(int result);
-
- virtual int runModal();
-
- virtual void onAction(Widget *widget, int result = 0) {}
-};
-
-class OptionsDialog : public Dialog {
-private:
- FontRendererGui *_fr;
- Widget *_panel;
- Switch *_objectLabelsSwitch;
- Switch *_subtitlesSwitch;
- Switch *_reverseStereoSwitch;
- Switch *_musicSwitch;
- Switch *_speechSwitch;
- Switch *_fxSwitch;
- Slider *_musicSlider;
- Slider *_speechSlider;
- Slider *_fxSlider;
- Slider *_gfxSlider;
- Widget *_gfxPreview;
- Button *_okButton;
- Button *_cancelButton;
-
- Audio::Mixer *_mixer;
-
-public:
- OptionsDialog(Sword2Engine *vm);
- ~OptionsDialog();
-
- virtual void paint();
- virtual void onAction(Widget *widget, int result = 0);
-};
-
-class SaveRestoreDialog : public Dialog {
-private:
- int _mode, _selectedSlot;
- byte _editBuffer[SAVE_DESCRIPTION_LEN];
- int _editPos, _firstPos;
- int _cursorTick;
-
- FontRendererGui *_fr1;
- FontRendererGui *_fr2;
- Widget *_panel;
- Slot *_slotButton[8];
- ScrollButton *_zupButton;
- ScrollButton *_upButton;
- ScrollButton *_downButton;
- ScrollButton *_zdownButton;
- Button *_okButton;
- Button *_cancelButton;
-
-public:
- SaveRestoreDialog(Sword2Engine *vm, int mode);
- ~SaveRestoreDialog();
-
- void updateSlots();
- void drawEditBuffer(Slot *slot);
-
- virtual void onAction(Widget *widget, int result = 0);
- virtual void paint();
- virtual void setResult(int result);
- virtual int runModal();
-};
-
-/**
- * A "mini" dialog is usually a yes/no question, but also used for the
- * restart/restore dialog at the beginning of the game.
- */
-
-class MiniDialog : public Dialog {
-private:
- uint32 _headerTextId;
- uint32 _okTextId;
- uint32 _cancelTextId;
- FontRendererGui *_fr;
- Widget *_panel;
- Button *_okButton;
- Button *_cancelButton;
-
-public:
- MiniDialog(Sword2Engine *vm, uint32 headerTextId, uint32 okTextId = TEXT_OK, uint32 cancelTextId = TEXT_CANCEL);
- virtual ~MiniDialog();
- virtual void paint();
- virtual void onAction(Widget *widget, int result = 0);
-};
-
-class StartDialog : public MiniDialog {
-public:
- StartDialog(Sword2Engine *vm);
- virtual int runModal();
-};
-
-class RestartDialog : public MiniDialog {
-public:
- RestartDialog(Sword2Engine *vm);
- virtual int runModal();
-};
-
-class QuitDialog : public MiniDialog {
-public:
- QuitDialog(Sword2Engine *vm);
- virtual int runModal();
-};
-
-class SaveDialog : public SaveRestoreDialog {
-public:
- SaveDialog(Sword2Engine *vm) : SaveRestoreDialog(vm, kSaveDialog) {}
-};
-
-class RestoreDialog : public SaveRestoreDialog {
-public:
- RestoreDialog(Sword2Engine *vm) : SaveRestoreDialog(vm, kRestoreDialog) {}
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/d_draw.cpp b/sword2/d_draw.cpp
deleted file mode 100644
index 7f278996fb..0000000000
--- a/sword2/d_draw.cpp
+++ /dev/null
@@ -1,71 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/system.h"
-#include "sword2/sword2.h"
-#include "sword2/mouse.h"
-
-namespace Sword2 {
-
-/**
- * @return the graphics detail setting
- */
-
-int8 Screen::getRenderLevel() {
- return _renderLevel;
-}
-
-void Screen::setRenderLevel(int8 level) {
- _renderLevel = level;
-
- switch (_renderLevel) {
- case 0:
- // Lowest setting: no fancy stuff
- _renderCaps = 0;
- break;
- case 1:
- // Medium-low setting: transparency-blending
- _renderCaps = RDBLTFX_SPRITEBLEND;
- break;
- case 2:
- // Medium-high setting: transparency-blending + shading
- _renderCaps = RDBLTFX_SPRITEBLEND | RDBLTFX_SHADOWBLEND;
- break;
- case 3:
- // Highest setting: transparency-blending + shading +
- // edge-blending + improved stretching
- _renderCaps = RDBLTFX_SPRITEBLEND | RDBLTFX_SHADOWBLEND | RDBLTFX_EDGEBLEND;
- break;
- }
-}
-
-/**
- * Fill the screen buffer with palette colour zero. Note that it does not
- * touch the menu areas of the screen.
- */
-
-void Screen::clearScene() {
- memset(_buffer + MENUDEEP * _screenWide, 0, _screenWide * RENDERDEEP);
- _needFullRedraw = true;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/debug.cpp b/sword2/debug.cpp
deleted file mode 100644
index 53fc200241..0000000000
--- a/sword2/debug.cpp
+++ /dev/null
@@ -1,377 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/console.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/memory.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-
-namespace Sword2 {
-
-void Debugger::clearDebugTextBlocks() {
- uint8 blockNo = 0;
-
- while (blockNo < MAX_DEBUG_TEXTS && _debugTextBlocks[blockNo] > 0) {
- // kill the system text block
- _vm->_fontRenderer->killTextBloc(_debugTextBlocks[blockNo]);
-
- // clear this element of our array of block numbers
- _debugTextBlocks[blockNo] = 0;
-
- blockNo++;
- }
-}
-
-void Debugger::makeDebugTextBlock(char *text, int16 x, int16 y) {
- uint8 blockNo = 0;
-
- while (blockNo < MAX_DEBUG_TEXTS && _debugTextBlocks[blockNo] > 0)
- blockNo++;
-
- assert(blockNo < MAX_DEBUG_TEXTS);
-
- _debugTextBlocks[blockNo] = _vm->_fontRenderer->buildNewBloc((byte *)text, x, y, 640 - x, 0, RDSPR_DISPLAYALIGN, CONSOLE_FONT_ID, NO_JUSTIFICATION);
-}
-
-void Debugger::buildDebugText() {
- char buf[128];
-
- int32 showVarNo; // for variable watching
- int32 showVarPos;
- int32 varNo;
-
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- // clear the array of text block numbers for the debug text
- clearDebugTextBlocks();
-
- // mouse coords
- // print mouse coords beside mouse-marker, if it's being displayed
- if (_displayMouseMarker) {
- int mouseX, mouseY;
-
- _vm->_mouse->getPos(mouseX, mouseY);
-
- sprintf(buf, "%d,%d", mouseX + screenInfo->scroll_offset_x, mouseY + screenInfo->scroll_offset_y);
- if (mouseX > 560)
- makeDebugTextBlock(buf, mouseX - 50, mouseY - 15);
- else
- makeDebugTextBlock(buf, mouseX + 5, mouseY - 15);
- }
-
- // mouse area coords
-
- // defining a mouse area the easy way, by creating a box on-screen
- if (_draggingRectangle || _vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
- // so we can see what's behind the lines
- _rectFlicker = !_rectFlicker;
-
- sprintf(buf, "x1=%d", _rectX1);
- makeDebugTextBlock(buf, 0, 120);
-
- sprintf(buf, "y1=%d", _rectY1);
- makeDebugTextBlock(buf, 0, 135);
-
- sprintf(buf, "x2=%d", _rectX2);
- makeDebugTextBlock(buf, 0, 150);
-
- sprintf(buf, "y2=%d", _rectY2);
- makeDebugTextBlock(buf, 0, 165);
- }
-
- // testingSnR indicator
-
- if (_testingSnR) { // see fnAddHuman()
- sprintf(buf, "TESTING LOGIC STABILITY!");
- makeDebugTextBlock(buf, 0, 105);
- }
-
-#ifdef SWORD2_DEBUG
- // speed-up indicator
-
- if (_vm->_renderSkip) { // see sword2.cpp
- sprintf(buf, "SKIPPING FRAMES FOR SPEED-UP!");
- makeDebugTextBlock(buf, 0, 120);
- }
-#endif
-
- // debug info at top of screen - enabled/disabled as one complete unit
-
- if (_displayTime) {
- int32 time = _vm->getMillis();
-
- if ((time - _startTime) / 1000 >= 10000)
- _startTime = time;
-
- time -= _startTime;
- sprintf(buf, "Time %.2d:%.2d:%.2d.%.3d", (time / 3600000) % 60, (time / 60000) % 60, (time / 1000) % 60, time % 1000);
- makeDebugTextBlock(buf, 500, 360);
- sprintf(buf, "Game %d", _vm->_gameCycle);
- makeDebugTextBlock(buf, 500, 380);
- }
-
- // current text number & speech-sample resource id
-
- if (_displayTextNumbers) {
- if (_textNumber) {
- if (_vm->_logic->readVar(SYSTEM_TESTING_TEXT)) {
- if (_vm->_logic->readVar(SYSTEM_WANT_PREVIOUS_LINE))
- sprintf(buf, "backwards");
- else
- sprintf(buf, "forwards");
-
- makeDebugTextBlock(buf, 0, 340);
- }
-
- sprintf(buf, "res: %d", _textNumber / SIZE);
- makeDebugTextBlock(buf, 0, 355);
-
- sprintf(buf, "pos: %d", _textNumber & 0xffff);
- makeDebugTextBlock(buf, 0, 370);
-
- sprintf(buf, "TEXT: %d", _vm->_logic->_officialTextNumber);
- makeDebugTextBlock(buf, 0, 385);
- }
- }
-
- // resource number currently being checking for animation
-
- if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
- sprintf(buf, "trying resource %d", _vm->_logic->readVar(SYSTEM_TESTING_ANIMS));
- makeDebugTextBlock(buf, 0, 90);
- }
-
- // general debug info
-
- if (_displayDebugText) {
- byte name[NAME_LEN];
-
-/*
- // CD in use
- sprintf(buf, "CD-%d", currentCD);
- makeDebugTextBlock(buf, 0, 0);
-*/
-
- // mouse coords & object pointed to
-
- if (_vm->_logic->readVar(CLICKED_ID))
- sprintf(buf, "last click at %d,%d (id %d: %s)",
- _vm->_logic->readVar(MOUSE_X),
- _vm->_logic->readVar(MOUSE_Y),
- _vm->_logic->readVar(CLICKED_ID),
- _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), name));
- else
- sprintf(buf, "last click at %d,%d (---)",
- _vm->_logic->readVar(MOUSE_X),
- _vm->_logic->readVar(MOUSE_Y));
-
- makeDebugTextBlock(buf, 0, 15);
-
- uint32 mouseTouching = _vm->_mouse->getMouseTouching();
-
- int mouseX, mouseY;
-
- _vm->_mouse->getPos(mouseX, mouseY);
-
- if (mouseTouching)
- sprintf(buf, "mouse %d,%d (id %d: %s)",
- mouseX + screenInfo->scroll_offset_x,
- mouseY + screenInfo->scroll_offset_y,
- mouseTouching,
- _vm->_resman->fetchName(mouseTouching, name));
- else
- sprintf(buf, "mouse %d,%d (not touching)",
- mouseX + screenInfo->scroll_offset_x,
- mouseY + screenInfo->scroll_offset_y);
-
- makeDebugTextBlock(buf, 0, 30);
-
- // player coords & graphic info
- // if player objct has a graphic
-
- if (_graphAnimRes)
- sprintf(buf, "player %d,%d %s (%d) #%d/%d",
- screenInfo->player_feet_x,
- screenInfo->player_feet_y,
- _vm->_resman->fetchName(_graphAnimRes, name),
- _graphAnimRes,
- _graphAnimPc,
- _graphNoFrames);
- else
- sprintf(buf, "player %d,%d --- %d",
- screenInfo->player_feet_x,
- screenInfo->player_feet_y,
- _graphAnimPc);
-
- makeDebugTextBlock(buf, 0, 45);
-
- // frames-per-second counter
-
- sprintf(buf, "fps %d", _vm->_screen->getFps());
- makeDebugTextBlock(buf, 440, 0);
-
- // location number
-
- sprintf(buf, "location=%d", _vm->_logic->readVar(LOCATION));
- makeDebugTextBlock(buf, 440, 15);
-
- // "result" variable
-
- sprintf(buf, "result=%d", _vm->_logic->readVar(RESULT));
- makeDebugTextBlock(buf, 440, 30);
-
- // no. of events in event list
-
- sprintf(buf, "events=%d", _vm->_logic->countEvents());
- makeDebugTextBlock(buf, 440, 45);
-
- // sprite list usage
-
- sprintf(buf, "bgp0: %d/%d", _vm->_screen->getCurBgp0(), MAX_bgp0_sprites);
- makeDebugTextBlock(buf, 560, 0);
-
- sprintf(buf, "bgp1: %d/%d", _vm->_screen->getCurBgp1(), MAX_bgp1_sprites);
- makeDebugTextBlock(buf, 560, 15);
-
- sprintf(buf, "back: %d/%d", _vm->_screen->getCurBack(), MAX_back_sprites);
- makeDebugTextBlock(buf, 560, 30);
-
- sprintf(buf, "sort: %d/%d", _vm->_screen->getCurSort(), MAX_sort_sprites);
- makeDebugTextBlock(buf, 560, 45);
-
- sprintf(buf, "fore: %d/%d", _vm->_screen->getCurFore(), MAX_fore_sprites);
- makeDebugTextBlock(buf, 560, 60);
-
- sprintf(buf, "fgp0: %d/%d", _vm->_screen->getCurFgp0(), MAX_fgp0_sprites);
- makeDebugTextBlock(buf, 560, 75);
-
- sprintf(buf, "fgp1: %d/%d", _vm->_screen->getCurFgp1(), MAX_fgp1_sprites);
- makeDebugTextBlock(buf, 560, 90);
-
- // largest layer & sprite
-
- // NB. Strings already constructed in Build_display.cpp
- makeDebugTextBlock(_vm->_screen->getLargestLayerInfo(), 0, 60);
- makeDebugTextBlock(_vm->_screen->getLargestSpriteInfo(), 0, 75);
-
- // "waiting for person" indicator - set form fnTheyDo and
- // fnTheyDoWeWait
-
- if (_speechScriptWaiting) {
- sprintf(buf, "script waiting for %s (%d)",
- _vm->_resman->fetchName(_speechScriptWaiting, name),
- _speechScriptWaiting);
- makeDebugTextBlock(buf, 0, 90);
- }
-
- // variable watch display
-
- showVarPos = 115; // y-coord for first showVar
-
- for (showVarNo = 0; showVarNo < MAX_SHOWVARS; showVarNo++) {
- varNo = _showVar[showVarNo]; // get variable number
-
- // if non-zero ie. cannot watch 'id' but not needed
- // anyway because it changes throughout the logic loop
-
- if (varNo) {
- sprintf(buf, "var(%d) = %d", varNo, _vm->_logic->readVar(varNo));
- makeDebugTextBlock(buf, 530, showVarPos);
- showVarPos += 15; // next line down
- }
- }
-
- // memory indicator - this should come last, to show all the
- // sprite blocks above!
-
- uint32 totAlloc = _vm->_memory->getTotAlloc();
- int16 numBlocks = _vm->_memory->getNumBlocks();
-
- if (totAlloc < 1024)
- sprintf(buf, "%u bytes in %d memory blocks", totAlloc, numBlocks);
- else if (totAlloc < 1024 * 1024)
- sprintf(buf, "%uK in %d memory blocks", totAlloc / 1024, numBlocks);
- else
- sprintf(buf, "%.02fM in %d memory blocks", totAlloc / 1048576., numBlocks);
-
- makeDebugTextBlock(buf, 0, 0);
- }
-}
-
-void Debugger::drawDebugGraphics() {
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- // walk-grid
-
- if (_displayWalkGrid)
- _vm->_logic->_router->plotWalkGrid();
-
- // player feet coord marker
-
- if (_displayPlayerMarker)
- plotCrossHair(screenInfo->player_feet_x, screenInfo->player_feet_y, 215);
-
- // mouse marker & coords
-
- if (_displayMouseMarker) {
- int mouseX, mouseY;
-
- _vm->_mouse->getPos(mouseX, mouseY);
-
- plotCrossHair(mouseX + screenInfo->scroll_offset_x, mouseY + screenInfo->scroll_offset_y, 215);
- }
-
- // mouse area rectangle / sprite box rectangle when testing anims
-
- if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
- // draw box around current frame
- drawRect(_rectX1, _rectY1, _rectX2, _rectY2, 184);
- } else if (_draggingRectangle) {
- // defining a mouse area the easy way, by creating a box
- // on-screen
- if (_rectFlicker)
- drawRect(_rectX1, _rectY1, _rectX2, _rectY2, 184);
- }
-}
-
-void Debugger::plotCrossHair(int16 x, int16 y, uint8 pen) {
- _vm->_screen->plotPoint(x, y, pen);
-
- _vm->_screen->drawLine(x - 2, y, x - 5, y, pen);
- _vm->_screen->drawLine(x + 2, y, x + 5, y, pen);
-
- _vm->_screen->drawLine(x, y - 2, x, y - 5, pen);
- _vm->_screen->drawLine(x, y + 2, x, y + 5, pen);
-}
-
-void Debugger::drawRect(int16 x1, int16 y1, int16 x2, int16 y2, uint8 pen) {
- _vm->_screen->drawLine(x1, y1, x2, y1, pen); // top edge
- _vm->_screen->drawLine(x1, y2, x2, y2, pen); // bottom edge
- _vm->_screen->drawLine(x1, y1, x1, y2, pen); // left edge
- _vm->_screen->drawLine(x2, y1, x2, y2, pen); // right edge
-}
-
-} // End of namespace Sword2
diff --git a/sword2/debug.h b/sword2/debug.h
deleted file mode 100644
index 9b0b40f9ec..0000000000
--- a/sword2/debug.h
+++ /dev/null
@@ -1,33 +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 D_DEBUG
-#define D_DEBUG
-
-// FIXME: I don't know how large this constant used to be
-#define MAX_DEBUG_TEXTS 55
-
-#define MAX_SHOWVARS 15
-
-namespace Sword2 {
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/defs.h b/sword2/defs.h
deleted file mode 100644
index 4acb484f34..0000000000
--- a/sword2/defs.h
+++ /dev/null
@@ -1,205 +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 DEFS
-#define DEFS
-
-#define SIZE 0x10000 // 65536 items per section
-#define NuSIZE 0xffff // & with this
-
-// Return codes
-
-enum {
- // Generic error codes
- RD_OK = 0x00000000,
- RDERR_UNKNOWN = 0x00000001,
- RDERR_OUTOFMEMORY = 0x00000003,
- RDERR_INVALIDFILENAME = 0x00000004,
-
- // Drawing error codes
- RDERR_DECOMPRESSION = 0x00010007,
-
- // Sprite drawing error codes
- RDERR_NOTIMPLEMENTED = 0x00060001,
- RDERR_NOTCLOSED = 0x00050005,
- RDERR_NOTOPEN = 0x00050006,
-
- // Menubar error codes
- RDERR_INVALIDMENU = 0x00060000,
- RDERR_INVALIDPOCKET = 0x00060001,
- RDERR_INVALIDCOMMAND = 0x00060002,
-
- // Palette fading error codes
- RDERR_FADEINCOMPLETE = 0x00070000,
-
- // Sound engine error codes
- RDERR_SPEECHPLAYING = 0x00080004,
- RDERR_SPEECHNOTPLAYING = 0x00080005,
- RDERR_INVALIDWAV = 0x00080006,
- RDERR_FXALREADYOPEN = 0x00080009,
- RDERR_FXNOTOPEN = 0x0008000B,
- RDERR_INVALIDID = 0x0008000D
-};
-
-// Text ids for the control panel etc.
-
-enum {
- TEXT_OK = 0x08EB0000,
- TEXT_CANCEL = 0x08EB0001,
- TEXT_RESTORE = 0x08EB0002,
- TEXT_SAVE = 0x08EB0003,
- TEXT_QUIT = 0x08EB0004,
- TEXT_RESTART = 0x08EB0005,
- TEXT_OPTIONS = 0x08EB000A,
- TEXT_SUBTITLES = 0x08EB000B,
- TEXT_OBJECT_LABELS = 0x08EB000C,
- TEXT_MUSIC_VOLUME = 0x08EB000E,
- TEXT_SPEECH_VOLUME = 0x08EB000F,
- TEXT_FX_VOLUME = 0x08EB0010,
- TEXT_GFX_QUALITY = 0x08EB0011,
- TEXT_REVERSE_STEREO = 0x08EB0015,
- TEXT_RESTORE_CANT_OPEN = 0x0CBA017E,
- TEXT_RESTORE_INCOMPATIBLE = 0x0CBA017F,
- TEXT_RESTORE_FAILED = 0x0CBA0181,
- TEXT_SAVE_CANT_OPEN = 0x0CBA0182,
- TEXT_SAVE_FAILED = 0x0CBA0184
-};
-
-// Always 8 (George object used for Nico player character as well)
-#define CUR_PLAYER_ID 8
-
-// Global variable references
-
-enum {
- ID = 0,
- RESULT = 1,
- PLAYER_ACTION = 2,
- // CUR_PLAYER_ID = 3,
- PLAYER_ID = 305,
- TALK_FLAG = 13,
-
- MOUSE_X = 4,
- MOUSE_Y = 5,
- LEFT_BUTTON = 109,
- RIGHT_BUTTON = 110,
- CLICKED_ID = 178,
-
- IN_SUBJECT = 6,
- COMBINE_BASE = 7,
- OBJECT_HELD = 14,
-
- SPEECH_ID = 9,
- INS1 = 10,
- INS2 = 11,
- INS3 = 12,
- INS4 = 60,
- INS5 = 61,
- INS_COMMAND = 59,
-
- PLAYER_FEET_X = 141,
- PLAYER_FEET_Y = 142,
- PLAYER_CUR_DIR = 937,
-
- // for debug.cpp
- LOCATION = 62,
-
- // so scripts can force scroll offsets
- SCROLL_X = 345,
- SCROLL_Y = 346,
-
- EXIT_CLICK_ID = 710,
- EXIT_FADING = 713,
-
- SYSTEM_TESTING_ANIMS = 912,
- SYSTEM_TESTING_TEXT = 1230,
- SYSTEM_WANT_PREVIOUS_LINE = 1245,
-
- // 1=on 0=off (set in fnAddHuman and fnNoHuman)
- MOUSE_AVAILABLE = 686,
-
- // used in fnChoose
- AUTO_SELECTED = 1115,
-
- // see fnStartConversation and fnChooser
- CHOOSER_COUNT_FLAG = 15,
-
- // signifies a demo mode
- DEMO = 1153,
-
- // Indicates to script whether this is the Playstation version.
- // PSXFLAG = 1173,
-
- // for the poor PSX so it knows what language is running.
- // GAME_LANGUAGE = 111,
-
- // 1 = dead
- DEAD = 1256,
-
- // If set indicates that the speech anim is to run through only once.
- SPEECHANIMFLAG = 1278,
-
- // for the engine
- SCROLL_OFFSET_X = 1314
-};
-
-// Resource IDs
-
-enum {
- // mouse mointers - It's pretty much safe to do it like this
- NORMAL_MOUSE_ID = 17,
- SCROLL_LEFT_MOUSE_ID = 1440,
- SCROLL_RIGHT_MOUSE_ID = 1441,
-
- // Console Font - does not use game text - only English required
- CONSOLE_FONT_ID = 340,
-
- // Speech Font
- ENGLISH_SPEECH_FONT_ID = 341,
- FINNISH_SPEECH_FONT_ID = 956,
- POLISH_SPEECH_FONT_ID = 955,
-
- // Control Panel Font (and un-selected savegame descriptions)
- ENGLISH_CONTROLS_FONT_ID = 2005,
- FINNISH_CONTROLS_FONT_ID = 959,
- POLISH_CONTROLS_FONT_ID = 3686,
-
- // Red Font (for selected savegame descriptions)
- // BS2 doesn't draw selected savegames in red, so I guess this is a
- // left-over from BS1
- ENGLISH_RED_FONT_ID = 2005, // 1998 // Redfont
- FINNISH_RED_FONT_ID = 959, // 960 // FinRedFn
- POLISH_RED_FONT_ID = 3686, // 3688 // PolRedFn
-
- // Control panel palette resource id
- CONTROL_PANEL_PALETTE = 261,
-
- // res id's of the system menu icons
- OPTIONS_ICON = 344,
- QUIT_ICON = 335,
- SAVE_ICON = 366,
- RESTORE_ICON = 364,
- RESTART_ICON = 342,
-
- // conversation exit icon, 'EXIT' menu icon (used in fnChoose)
- EXIT_ICON = 65
-};
-
-#endif
diff --git a/sword2/events.cpp b/sword2/events.cpp
deleted file mode 100644
index e8090414aa..0000000000
--- a/sword2/events.cpp
+++ /dev/null
@@ -1,99 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-
-namespace Sword2 {
-
-void Logic::sendEvent(uint32 id, uint32 interact_id) {
- for (int i = 0; i < ARRAYSIZE(_eventList); i++) {
- if (_eventList[i].id == id || !_eventList[i].id) {
- _eventList[i].id = id;
- _eventList[i].interact_id = interact_id;
- return;
- }
- }
-
- error("sendEvent() ran out of event slots");
-}
-
-void Logic::setPlayerActionEvent(uint32 id, uint32 interact_id) {
- // Full script id of action script number 2
- sendEvent(id, (interact_id << 16) | 2);
-}
-
-int Logic::checkEventWaiting() {
- for (int i = 0; i < ARRAYSIZE(_eventList); i++) {
- if (_eventList[i].id == readVar(ID))
- return 1;
- }
-
- return 0;
-}
-
-void Logic::startEvent() {
- // call this from stuff like fnWalk
- // you must follow with a return IR_TERMINATE
-
- for (int i = 0; i < ARRAYSIZE(_eventList); i++) {
- if (_eventList[i].id == readVar(ID)) {
- logicOne(_eventList[i].interact_id);
- _eventList[i].id = 0;
- return;
- }
- }
-
- error("startEvent() can't find event for id %d", readVar(ID));
-}
-
-void Logic::clearEvent(uint32 id) {
- for (int i = 0; i < ARRAYSIZE(_eventList); i++) {
- if (_eventList[i].id == id) {
- _eventList[i].id = 0;
- return;
- }
- }
-}
-
-void Logic::killAllIdsEvents(uint32 id) {
- for (int i = 0; i < ARRAYSIZE(_eventList); i++) {
- if (_eventList[i].id == id)
- _eventList[i].id = 0;
- }
-}
-
-// For the debugger
-
-uint32 Logic::countEvents() {
- uint32 count = 0;
-
- for (int i = 0; i < ARRAYSIZE(_eventList); i++) {
- if (_eventList[i].id)
- count++;
- }
-
- return count;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/function.cpp b/sword2/function.cpp
deleted file mode 100644
index e749e7b497..0000000000
--- a/sword2/function.cpp
+++ /dev/null
@@ -1,2479 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/system.h"
-#include "common/file.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/build_display.h"
-#include "sword2/console.h"
-#include "sword2/interpreter.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-#include "sword2/sound.h"
-#include "sword2/animation.h"
-
-namespace Sword2 {
-
-int32 Logic::fnTestFunction(int32 *params) {
- // params: 0 address of a flag
- return IR_CONT;
-}
-
-int32 Logic::fnTestFlags(int32 *params) {
- // params: 0 value of flag
- return IR_CONT;
-}
-
-int32 Logic::fnRegisterStartPoint(int32 *params) {
- // params: 0 id of startup script to call - key
- // 1 pointer to ascii message
-
- int32 key = params[0];
- char *name = (char *)decodePtr(params[1]);
-
- _vm->registerStartPoint(key, name);
- return IR_CONT;
-}
-
-int32 Logic::fnInitBackground(int32 *params) {
- // this screen defines the size of the back buffer
-
- // params: 0 res id of normal background layer - cannot be 0
- // 1 1 yes 0 no for a new palette
-
- _vm->_screen->initBackground(params[0], params[1]);
- return IR_CONT;
-}
-
-/**
- * This function is used by start scripts.
- */
-
-int32 Logic::fnSetSession(int32 *params) {
- // params: 0 id of new run list
-
- expressChangeSession(params[0]);
- return IR_CONT;
-}
-
-int32 Logic::fnBackSprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), BACK_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnSortSprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), SORT_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnForeSprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), FORE_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnRegisterMouse(int32 *params) {
- // this call would be made from an objects service script 0
- // the object would be one with no graphic but with a mouse - i.e. a
- // floor or one whose mouse area is manually defined rather than
- // intended to fit sprite shape
-
- // params: 0 pointer to ObjectMouse or 0 for no write to mouse
- // list
-
- _vm->_mouse->registerMouse(decodePtr(params[0]), NULL);
- return IR_CONT;
-}
-
-int32 Logic::fnAnim(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 resource id of animation file
-
- // Normal forward animation
- return _router->doAnimate(
- decodePtr(params[0]),
- decodePtr(params[1]),
- params[2], false);
-}
-
-int32 Logic::fnRandom(int32 *params) {
- // params: 0 min
- // 1 max
-
- writeVar(RESULT, _vm->_rnd.getRandomNumberRng(params[0], params[1]));
- return IR_CONT;
-}
-
-int32 Logic::fnPreLoad(int32 *params) {
- // Forces a resource into memory before it's "officially" opened for
- // use. eg. if an anim needs to run on smoothly from another,
- // "preloading" gets it into memory in advance to avoid the cacheing
- // delay that normally occurs before the first frame.
-
- // params: 0 resource to preload
-
- _vm->_resman->openResource(params[0]);
- _vm->_resman->closeResource(params[0]);
- return IR_CONT;
-}
-
-int32 Logic::fnAddSubject(int32 *params) {
- // params: 0 id
- // 1 daves reference number
- _vm->_mouse->addSubject(params[0], params[1]);
- return IR_CONT;
-}
-
-int32 Logic::fnInteract(int32 *params) {
- // Run targets action on a subroutine. Called by player on his base
- // level 0 idle, for example.
-
- // params: 0 id of target from which we derive action script
- // reference
-
- writeVar(PLAYER_ACTION, 0); // must clear this
- logicUp((params[0] << 16) | 2); // 3rd script of clicked on id
-
- // Out, up and around again - pc is saved for current level to be
- // returned to.
- return IR_GOSUB;
-}
-
-int32 Logic::fnChoose(int32 *params) {
- // params: none
-
- // This opcode is used to open the conversation menu. The human is
- // switched off so there will be no normal mouse engine.
-
- // The player's choice is piggy-backed on the standard opcode return
- // values, to be used with the CP_JUMP_ON_RETURNED opcode. As far as I
- // can tell, this is the only function that uses that feature.
-
- uint32 response = _vm->_mouse->chooseMouse();
-
- if (response == (uint32)-1)
- return IR_REPEAT;
-
- return IR_CONT | (response << 3);
-}
-
-/**
- * Walk mega to (x,y,dir). Set RESULT to 0 if it succeeded. Otherwise, set
- * RESULT to 1.
- */
-
-int32 Logic::fnWalk(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to object's walkdata structure
- // 4 target x-coord
- // 5 target y-coord
- // 6 target direction (8 means end walk on ANY direction)
-
- return _router->doWalk(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- params[4], params[5], params[6]);
-}
-
-/**
- * Walk mega to start position of anim
- */
-
-int32 Logic::fnWalkToAnim(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to object's walkdata structure
- // 4 anim resource id
-
- return _router->walkToAnim(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- params[4]);
-}
-
-/**
- * Turn mega to the specified direction.
- */
-
-int32 Logic::fnTurn(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to object's walkdata structure
- // 4 target direction
-
- return _router->doFace(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- params[4]);
-}
-
-/**
- * Stand mega at (x,y,dir)
- * Sets up the graphic object, but also needs to set the new 'current_dir' in
- * the mega object, so the router knows in future
- */
-
-int32 Logic::fnStandAt(int32 *params) {
- // params: 0 pointer to object's graphic structure
- // 1 pointer to object's mega structure
- // 2 target x-coord
- // 3 target y-coord
- // 4 target direction
-
- _router->standAt(
- decodePtr(params[0]),
- decodePtr(params[1]),
- params[2], params[3], params[4]);
- return IR_CONT;
-}
-
-/**
- * Stand mega into the specified direction at current feet coords.
- * Just needs to call standAt() with current feet coords.
- */
-
-int32 Logic::fnStand(int32 *params) {
- // params: 0 pointer to object's graphic structure
- // 1 pointer to object's mega structure
- // 2 target direction
- byte *ob_mega = decodePtr(params[1]);
-
- ObjectMega obMega(ob_mega);
-
- _router->standAt(
- decodePtr(params[0]),
- ob_mega, obMega.getFeetX(), obMega.getFeetY(), params[2]);
- return IR_CONT;
-}
-
-/**
- * stand mega at end position of anim
- */
-
-int32 Logic::fnStandAfterAnim(int32 *params) {
- // params: 0 pointer to object's graphic structure
- // 1 pointer to object's mega structure
- // 2 anim resource id
-
- _router->standAfterAnim(
- decodePtr(params[0]),
- decodePtr(params[1]),
- params[2]);
- return IR_CONT;
-}
-
-int32 Logic::fnPause(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 number of game-cycles to pause
-
- // NB. Pause-value of 0 causes script to continue, 1 causes a 1-cycle
- // quit, 2 gives 2 cycles, etc.
-
- ObjectLogic obLogic(decodePtr(params[0]));
-
- if (obLogic.getLooping() == 0) {
- obLogic.setLooping(1);
- obLogic.setPause(params[1]);
- }
-
- if (obLogic.getPause()) {
- obLogic.setPause(obLogic.getPause() - 1);
- return IR_REPEAT;
- }
-
- obLogic.setLooping(0);
- return IR_CONT;
-}
-
-int32 Logic::fnMegaTableAnim(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to animation table
-
- // Normal forward anim
- return _router->megaTableAnimate(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- false);
-}
-
-int32 Logic::fnAddMenuObject(int32 *params) {
- // params: 0 pointer to a MenuObject structure to copy down
-
- _vm->_mouse->addMenuObject(decodePtr(params[0]));
- return IR_CONT;
-}
-
-/**
- * Start a conversation.
- *
- * Note that fnStartConversation() might accidentally be called every time the
- * script loops back for another chooser, but we only want to reset the chooser
- * count flag the first time this function is called, i.e. when the talk flag
- * is zero.
- */
-
-int32 Logic::fnStartConversation(int32 *params) {
- // params: none
-
- _vm->_mouse->startConversation();
- return IR_CONT;
-}
-
-/**
- * End a conversation.
- */
-
-int32 Logic::fnEndConversation(int32 *params) {
- // params: none
-
- _vm->_mouse->endConversation();
- return IR_CONT;
-}
-
-int32 Logic::fnSetFrame(int32 *params) {
- // params: 0 pointer to object's graphic structure
- // 1 resource id of animation file
- // 2 frame flag (0=first 1=last)
-
- int32 res = params[1];
- assert(res);
-
- // open the resource (& check it's valid)
- byte *anim_file = _vm->_resman->openResource(res);
-
- assert(_vm->_resman->fetchType(res) == ANIMATION_FILE);
-
- // set up pointer to the animation header
- AnimHeader anim_head;
-
- anim_head.read(_vm->fetchAnimHeader(anim_file));
-
- // set up anim resource in graphic object
- ObjectGraphic obGraph(decodePtr(params[0]));
-
- obGraph.setAnimResource(res);
- obGraph.setAnimPc(params[2] ? anim_head.noAnimFrames - 1 : 0);
-
- // Close the anim file and drop out of script
- _vm->_resman->closeResource(obGraph.getAnimResource());
- return IR_CONT;
-}
-
-int32 Logic::fnRandomPause(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 minimum number of game-cycles to pause
- // 2 maximum number of game-cycles to pause
-
- ObjectLogic obLogic(decodePtr(params[0]));
- int32 pars[2];
-
- if (obLogic.getLooping() == 0) {
- pars[0] = params[1];
- pars[1] = params[2];
- fnRandom(pars);
- pars[1] = readVar(RESULT);
- }
-
- pars[0] = params[0];
- return fnPause(pars);
-}
-
-int32 Logic::fnRegisterFrame(int32 *params) {
- // this call would be made from an objects service script 0
-
- // params: 0 pointer to mouse structure or NULL for no write to
- // mouse list (non-zero means write sprite-shape to
- // mouse list)
- // 1 pointer to graphic structure
- // 2 pointer to mega structure or NULL if not a mega
-
- _vm->_screen->registerFrame(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]));
- return IR_CONT;
-}
-
-int32 Logic::fnNoSprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), NO_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnSendSync(int32 *params) {
- // params: 0 sync's recipient
- // 1 sync value
-
- sendSync(params[0], params[1]);
- return IR_CONT;
-}
-
-int32 Logic::fnUpdatePlayerStats(int32 *params) {
- // engine needs to know certain info about the player
-
- // params: 0 pointer to mega structure
-
- ObjectMega obMega(decodePtr(params[0]));
-
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- screenInfo->player_feet_x = obMega.getFeetX();
- screenInfo->player_feet_y = obMega.getFeetY();
-
- // for the script
- writeVar(PLAYER_FEET_X, obMega.getFeetX());
- writeVar(PLAYER_FEET_Y, obMega.getFeetY());
- writeVar(PLAYER_CUR_DIR, obMega.getCurDir());
- writeVar(SCROLL_OFFSET_X, screenInfo->scroll_offset_x);
-
- debug(5, "fnUpdatePlayerStats: %d %d",
- obMega.getFeetX(), obMega.getFeetY());
-
- return IR_CONT;
-}
-
-int32 Logic::fnPassGraph(int32 *params) {
- // makes an engine local copy of passed ObjectGraphic - run script 4
- // of an object to request this used by fnTurnTo(id) etc
- //
- // remember, we cannot simply read a compact any longer but instead
- // must request it from the object itself
-
- // params: 0 pointer to an ObjectGraphic structure
-
- warning("fnPassGraph() is a no-op now");
- return IR_CONT;
-}
-
-int32 Logic::fnInitFloorMouse(int32 *params) {
- // params: 0 pointer to object's mouse structure
-
- byte *ob_mouse = decodePtr(params[0]);
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- // floor is always lowest priority
-
- ObjectMouse mouse;
-
- mouse.x1 = 0;
- mouse.y1 = 0;
- mouse.x2 = screenInfo->screen_wide - 1;
- mouse.y2 = screenInfo->screen_deep - 1;
- mouse.priority = 9;
- mouse.pointer = NORMAL_MOUSE_ID;
-
- mouse.write(ob_mouse);
- return IR_CONT;
-}
-
-int32 Logic::fnPassMega(int32 *params) {
- // makes an engine local copy of passed mega_structure - run script 4
- // of an object to request this used by fnTurnTo(id) etc
- //
- // remember, we cannot simply read a compact any longer but instead
- // must request it from the object itself
-
- // params: 0 pointer to a mega structure
-
- memcpy(_engineMega, decodePtr(params[0]), ObjectMega::size());
- return IR_CONT;
-}
-
-/**
- * Turn mega to face point (x,y) on the floor
- */
-
-int32 Logic::fnFaceXY(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to object's walkdata structure
- // 4 target x-coord
- // 5 target y-coord
-
- return _router->faceXY(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- params[4], params[5]);
-}
-
-/**
- * Causes no more objects in this logic loop to be processed. The logic engine
- * will restart at the beginning of the new list. The current screen will not
- * be drawn!
- */
-
-int32 Logic::fnEndSession(int32 *params) {
- // params: 0 id of new run-list
-
- // terminate current and change to next run-list
- expressChangeSession(params[0]);
-
- // stop the script - logic engine will now go around and the new
- // screen will begin
- return IR_STOP;
-}
-
-int32 Logic::fnNoHuman(int32 *params) {
- // params: none
-
- _vm->_mouse->noHuman();
- return IR_CONT;
-}
-
-int32 Logic::fnAddHuman(int32 *params) {
- // params: none
-
- _vm->_mouse->addHuman();
- return IR_CONT;
-}
-
-/**
- * Wait for a target to become waiting, i.e. not busy.
- */
-
-int32 Logic::fnWeWait(int32 *params) {
- // params: 0 target
-
- assert(_vm->_resman->fetchType(params[0]) == GAME_OBJECT);
-
- // Run the target's get-speech-state script
- runResScript(params[0], 5);
-
- if (readVar(RESULT) == 0) {
- // The target is busy. Try again.
- _vm->_debugger->_speechScriptWaiting = params[0];
- return IR_REPEAT;
- }
-
- // The target is waiting, i.e. not busy.
-
- _vm->_debugger->_speechScriptWaiting = 0;
- return IR_CONT;
-}
-
-/**
- * Wait for a target to become waiting, i.e. not busy, send a command to it,
- * then wait for it to finish.
- */
-
-int32 Logic::fnTheyDoWeWait(int32 *params) {
- // params: 0 pointer to ob_logic
- // 1 target
- // 2 command
- // 3 ins1
- // 4 ins2
- // 5 ins3
- // 6 ins4
- // 7 ins5
-
- assert(_vm->_resman->fetchType(params[1]) == GAME_OBJECT);
-
- // Run the target's get-speech-state script
- runResScript(params[1], 5);
-
- ObjectLogic obLogic(decodePtr(params[0]));
-
- if (readVar(RESULT) == 1 && readVar(INS_COMMAND) == 0 && obLogic.getLooping() == 0) {
- // The target is waiting, i.e. not busy, and there is no other
- // command queued. We haven't sent the command yet, so do it.
-
- debug(5, "fnTheyDoWeWait: sending command to %d", params[1]);
-
- _vm->_debugger->_speechScriptWaiting = params[1];
- obLogic.setLooping(1);
-
- writeVar(SPEECH_ID, params[1]);
- writeVar(INS_COMMAND, params[2]);
- writeVar(INS1, params[3]);
- writeVar(INS2, params[4]);
- writeVar(INS3, params[5]);
- writeVar(INS4, params[6]);
- writeVar(INS5, params[7]);
-
- return IR_REPEAT;
- }
-
- if (obLogic.getLooping() == 0) {
- // The command has not been sent yet. Keep waiting.
- _vm->_debugger->_speechScriptWaiting = params[1];
- return IR_REPEAT;
- }
-
- if (readVar(RESULT) == 0) {
- // The command has been sent, and the target is busy doing it.
- // Wait for it to finish.
-
- debug(5, "fnTheyDoWeWait: Waiting for %d to finish", params[1]);
-
- _vm->_debugger->_speechScriptWaiting = params[1];
- return IR_REPEAT;
- }
-
- debug(5, "fnTheyDoWeWait: %d finished", params[1]);
-
- obLogic.setLooping(0);
- _vm->_debugger->_speechScriptWaiting = 0;
- return IR_CONT;
-}
-
-/**
- * Wait for a target to become waiting, i.e. not busy, then send a command to
- * it.
- */
-
-int32 Logic::fnTheyDo(int32 *params) {
- // params: 0 target
- // 1 command
- // 2 ins1
- // 3 ins2
- // 4 ins3
- // 5 ins4
- // 6 ins5
-
- assert(_vm->_resman->fetchType(params[0]) == GAME_OBJECT);
-
- // Run the target's get-speech-state script
- runResScript(params[0], 5);
-
- if (readVar(RESULT) == 1 && !readVar(INS_COMMAND)) {
- // The target is waiting, i.e. not busy, and there is no other
- // command queued. Send the command.
-
- debug(5, "fnTheyDo: sending command to %d", params[0]);
-
- _vm->_debugger->_speechScriptWaiting = 0;
-
- writeVar(SPEECH_ID, params[0]);
- writeVar(INS_COMMAND, params[1]);
- writeVar(INS1, params[2]);
- writeVar(INS2, params[3]);
- writeVar(INS3, params[4]);
- writeVar(INS4, params[5]);
- writeVar(INS5, params[6]);
-
- return IR_CONT;
- }
-
- // The target is busy. Come back again next cycle.
-
- _vm->_debugger->_speechScriptWaiting = params[0];
- return IR_REPEAT;
-}
-
-/**
- * Route to the left or right hand side of target id, if possible.
- */
-
-int32 Logic::fnWalkToTalkToMega(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to object's walkdata structure
- // 4 id of target mega to face
- // 5 separation
-
- return _router->walkToTalkToMega(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- params[4], params[5]);
-}
-
-int32 Logic::fnFadeDown(int32 *params) {
- // NONE means up! can only be called when screen is fully faded up -
- // multiple calls wont have strange effects
-
- // params: none
-
- if (_vm->_screen->getFadeStatus() == RDFADE_NONE)
- _vm->_screen->fadeDown();
-
- return IR_CONT;
-}
-
-enum {
- S_OB_GRAPHIC = 0,
- S_OB_SPEECH = 1,
- S_OB_LOGIC = 2,
- S_OB_MEGA = 3,
-
- S_TEXT = 4,
- S_WAV = 5,
- S_ANIM = 6,
- S_DIR_TABLE = 7,
- S_ANIM_MODE = 8
-};
-
-/**
- * It's the super versatile fnSpeak. Text and wavs can be selected in any
- * combination.
- *
- * @note We can assume no human - there should be no human, at least!
- */
-
-int32 Logic::fnISpeak(int32 *params) {
- // params: 0 pointer to ob_graphic
- // 1 pointer to ob_speech
- // 2 pointer to ob_logic
- // 3 pointer to ob_mega
- // 4 encoded text number
- // 5 wav res id
- // 6 anim res id
- // 7 anim table res id
- // 8 animation mode 0 lip synced,
- // 1 just straight animation
-
- static bool cycle_skip = false;
- static bool speechRunning;
-
- // Set up the pointers which we know we'll always need
-
- ObjectLogic obLogic(decodePtr(params[S_OB_LOGIC]));
- ObjectGraphic obGraph(decodePtr(params[S_OB_GRAPHIC]));
-
- // FIRST TIME ONLY: create the text, load the wav, set up the anim,
- // etc.
-
- if (obLogic.getLooping() == 0) {
- // New fudge to wait for smacker samples to finish
- // since they can over-run into the game
-
- if (_vm->_sound->getSpeechStatus() != RDSE_SAMPLEFINISHED)
- return IR_REPEAT;
-
- // New fudge for 'fx' subtitles: If subtitles switched off, and
- // we don't want to use a wav for this line either, then just
- // quit back to script right now!
-
- if (!_vm->getSubtitles() && !wantSpeechForLine(params[S_WAV]))
- return IR_CONT;
-
- // Drop out for 1st cycle to allow walks/anims to end and
- // display last frame before system locks while speech loaded
-
- if (!cycle_skip) {
- cycle_skip = true;
- return IR_REPEAT;
- }
-
- cycle_skip = false;
-
- _vm->_debugger->_textNumber = params[S_TEXT];
-
- // Pull out the text line to get the official text number
- // (for wav id). Once the wav id's go into all script text
- // commands, we'll only need this for debugging.
-
- uint32 text_res = params[S_TEXT] / SIZE;
- uint32 local_text = params[S_TEXT] & 0xffff;
-
- // For testing all text & speech!
- //
- // A script loop can send any text number to fnISpeak and it
- // will only run the valid ones or return with 'result' equal
- // to '1' or '2' to mean 'invalid text resource' and 'text
- // number out of range' respectively
- //
- // See 'testing_routines' object in George's Player Character
- // section of linc
-
- if (readVar(SYSTEM_TESTING_TEXT)) {
- if (!_vm->_resman->checkValid(text_res)) {
- // Not a valid resource number - invalid (null
- // resource)
- writeVar(RESULT, 1);
- return IR_CONT;
- }
-
- if (_vm->_resman->fetchType(text_res) != TEXT_FILE) {
- // Invalid - not a text resource
- _vm->_resman->closeResource(text_res);
- writeVar(RESULT, 1);
- return IR_CONT;
- }
-
- if (!_vm->checkTextLine(_vm->_resman->openResource(text_res), local_text)) {
- // Line number out of range
- _vm->_resman->closeResource(text_res);
- writeVar(RESULT, 2);
- return IR_CONT;
- }
-
- _vm->_resman->closeResource(text_res);
- writeVar(RESULT, 0);
- }
-
- byte *text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
- _officialTextNumber = READ_LE_UINT16(text);
- _vm->_resman->closeResource(text_res);
-
- // Prevent dud lines from appearing while testing text & speech
- // since these will not occur in the game anyway
-
- if (readVar(SYSTEM_TESTING_TEXT)) {
- // If actor number is 0 and text line is just a 'dash'
- // character
- if (_officialTextNumber == 0 && text[2] == '-' && text[3] == 0) {
- writeVar(RESULT, 3);
- return IR_CONT;
- }
- }
-
- // Set the 'looping_flag' and the text-click-delays. We can
- // left-click past the text after half a second, and
- // right-click past it after a quarter of a second.
-
- obLogic.setLooping(1);
- _leftClickDelay = 6;
- _rightClickDelay = 3;
-
- if (readVar(PLAYER_ID) != CUR_PLAYER_ID)
- debug(5, "(%d) Nico: %s", _officialTextNumber, text + 2);
- else {
- byte buf[NAME_LEN];
-
- debug(5, "(%d) %s: %s", _officialTextNumber, _vm->_resman->fetchName(readVar(ID), buf), text + 2);
- }
-
- // Set up the speech animation
-
- if (params[S_ANIM]) {
- // Just a straight anim.
- _animId = params[6];
- } else if (params[S_DIR_TABLE]) {
- // Use this direction table to derive the anim
- // NB. ASSUMES WE HAVE A MEGA OBJECT!!
-
- ObjectMega obMega(decodePtr(params[S_OB_MEGA]));
- byte *anim_table = decodePtr(params[S_DIR_TABLE]);
-
- _animId = READ_LE_UINT32(anim_table + 4 * obMega.getCurDir());
- } else {
- // No animation choosen
- _animId = 0;
- }
-
- if (_animId) {
- // Set the talker's graphic to the first frame of this
- // speech anim for now.
-
- _speechAnimType = readVar(SPEECHANIMFLAG);
- obGraph.setAnimResource(_animId);
- obGraph.setAnimPc(0);
- }
-
- // Default back to looped lip synced anims.
- writeVar(SPEECHANIMFLAG, 0);
-
- // Set up _textX and _textY for speech panning and/or text
- // sprite position.
-
- locateTalker(params);
-
- // Is it to be speech or subtitles or both?
-
- // Assume not running until know otherwise
- speechRunning = false;
-
- // New fudge for 'fx' subtitles: If speech is selected, and
- // this line is allowed speech (not if it's an fx subtitle!)
-
- if (!_vm->_sound->isSpeechMute() && wantSpeechForLine(_officialTextNumber)) {
- // If the wavId parameter is zero because not yet
- // compiled into speech command, we can still get it
- // from the 1st 2 chars of the text line.
-
- if (!params[S_WAV])
- params[S_WAV] = (int32)_officialTextNumber;
-
- // Panning goes from -16 (left) to 16 (right)
- int8 speech_pan = ((_textX - 320) * 16) / 320;
-
- if (speech_pan < -16)
- speech_pan = -16;
- else if (speech_pan > 16)
- speech_pan = 16;
-
- uint32 rv = _vm->_sound->playCompSpeech(params[S_WAV], 16, speech_pan);
-
- if (rv == RD_OK) {
- // Ok, we've got something to play. Set it
- // playing now. (We might want to do this the
- // next cycle, don't know yet.)
-
- speechRunning = true;
- _vm->_sound->unpauseSpeech();
- } else {
- debug(5, "ERROR: PlayCompSpeech(wav=%d (res=%d pos=%d)) returned %.8x", params[S_WAV], text_res, local_text, rv);
- }
- }
-
- if (_vm->getSubtitles() || !speechRunning) {
- // We want subtitles, or the speech failed to load.
- // Either way, we're going to show the text so create
- // the text sprite.
-
- formText(params);
- }
- }
-
- // EVERY TIME: run a cycle of animation, if there is one
-
- if (_animId) {
- // There is an animation - Increment the anim frame number.
- obGraph.setAnimPc(obGraph.getAnimPc() + 1);
-
- byte *anim_file = _vm->_resman->openResource(obGraph.getAnimResource());
- AnimHeader anim_head;
-
- anim_head.read(_vm->fetchAnimHeader(anim_file));
-
- if (!_speechAnimType) {
- // ANIM IS TO BE LIP-SYNC'ED & REPEATING
-
- if (obGraph.getAnimPc() == (int32)anim_head.noAnimFrames) {
- // End of animation - restart from frame 0
- obGraph.setAnimPc(0);
- } else if (speechRunning && _vm->_sound->amISpeaking() == RDSE_QUIET) {
- // The speech is running, but we're at a quiet
- // bit. Restart from frame 0 (closed mouth).
- obGraph.setAnimPc(0);
- }
- } else {
- // ANIM IS TO PLAY ONCE ONLY
- if (obGraph.getAnimPc() == (int32)anim_head.noAnimFrames - 1) {
- // Reached the last frame of the anim. Hold
- // anim on this last frame
- _animId = 0;
- }
- }
-
- _vm->_resman->closeResource(obGraph.getAnimResource());
- } else if (_speechAnimType) {
- // Placed here so we actually display the last frame of the
- // anim.
- _speechAnimType = 0;
- }
-
- // EVERY TIME: FIND OUT IF WE NEED TO STOP THE SPEECH NOW...
-
- // If there is a wav then we're using that to end the speech naturally
-
- bool speechFinished = false;
-
- // If playing a sample
-
- if (speechRunning) {
- // Has it finished?
- if (_vm->_sound->getSpeechStatus() == RDSE_SAMPLEFINISHED)
- speechFinished = true;
- } else if (!speechRunning && _speechTime) {
- // Counting down text time because there is no sample - this
- // ends the speech
-
- // if no sample then we're using _speechTime to end speech
- // naturally
-
- _speechTime--;
- if (!_speechTime)
- speechFinished = true;
- }
-
- // Ok, all is running along smoothly - but a click means stop
- // unnaturally
-
- int mouseX, mouseY;
-
- _vm->_mouse->getPos(mouseX, mouseY);
-
- // So that we can go to the options panel while text & speech is
- // being tested
- if (readVar(SYSTEM_TESTING_TEXT) == 0 || mouseY > 0) {
- MouseEvent *me = _vm->mouseEvent();
-
- // Note that we now have TWO click-delays - one for LEFT
- // button, one for RIGHT BUTTON
-
- if ((!_leftClickDelay && me && (me->buttons & RD_LEFTBUTTONDOWN)) ||
- (!_rightClickDelay && me && (me->buttons & RD_RIGHTBUTTONDOWN))) {
- // Mouse click, after click_delay has expired -> end
- // the speech.
-
- // if testing text & speech
- if (readVar(SYSTEM_TESTING_TEXT)) {
- // and RB used to click past text
- if (me->buttons & RD_RIGHTBUTTONDOWN) {
- // then we want the previous line again
- writeVar(SYSTEM_WANT_PREVIOUS_LINE, 1);
- } else {
- // LB just want next line again
- writeVar(SYSTEM_WANT_PREVIOUS_LINE, 0);
- }
- }
-
- speechFinished = true;
-
- // if speech sample playing, halt it prematurely
- if (speechRunning)
- _vm->_sound->stopSpeech();
- }
- }
-
- // If we are finishing the speech this cycle, do the business
-
- // !speechAnimType, as we want an anim which is playing once to have
- // finished.
-
- if (speechFinished && !_speechAnimType) {
- // If there is text, kill it
- if (_speechTextBlocNo) {
- _vm->_fontRenderer->killTextBloc(_speechTextBlocNo);
- _speechTextBlocNo = 0;
- }
-
- // if there is a speech anim, end it on closed mouth frame
- if (_animId) {
- _animId = 0;
- obGraph.setAnimPc(0);
- }
-
- speechRunning = false;
-
- // no longer in a script function loop
- obLogic.setLooping(0);
-
- _vm->_debugger->_textNumber = 0;
-
- // reset to zero, in case text line not even extracted (since
- // this number comes from the text line)
- _officialTextNumber = 0;
-
- writeVar(RESULT, 0);
- return IR_CONT;
- }
-
- // Speech still going, so decrement the click_delay if it's still
- // active
-
- if (_leftClickDelay)
- _leftClickDelay--;
-
- if (_rightClickDelay)
- _rightClickDelay--;
-
- return IR_REPEAT;
-}
-
-/**
- * Reset the object and restart script 1 on level 0
- */
-
-int32 Logic::fnTotalRestart(int32 *params) {
- // mega runs this to restart its base logic again - like being cached
- // in again
-
- // params: none
-
- _curObjectHub.setLogicLevel(0);
- _curObjectHub.setScriptPc(0, 1);
-
- return IR_TERMINATE;
-}
-
-int32 Logic::fnSetWalkGrid(int32 *params) {
- // params: none
-
- warning("fnSetWalkGrid() is no longer a valid opcode");
- return IR_CONT;
-}
-
-/**
- * Receive and sequence the commands sent from the conversation script. We have
- * to do this in a slightly tweeky manner as we can no longer have generic
- * scripts.
- */
-
-enum {
- INS_talk = 1,
- INS_anim = 2,
- INS_reverse_anim = 3,
- INS_walk = 4,
- INS_turn = 5,
- INS_face = 6,
- INS_trace = 7,
- INS_no_sprite = 8,
- INS_sort = 9,
- INS_foreground = 10,
- INS_background = 11,
- INS_table_anim = 12,
- INS_reverse_table_anim = 13,
- INS_walk_to_anim = 14,
- INS_set_frame = 15,
- INS_stand_after_anim = 16,
- INS_quit = 42
-};
-
-int32 Logic::fnSpeechProcess(int32 *params) {
- // params: 0 pointer to ob_graphic
- // 1 pointer to ob_speech
- // 2 pointer to ob_logic
- // 3 pointer to ob_mega
- // 4 pointer to ob_walkdata
-
- ObjectSpeech obSpeech(decodePtr(params[1]));
-
- while (1) {
- int32 pars[9];
-
- // Check which command we're waiting for, and call the
- // appropriate function. Once we're done, clear the command
- // and set wait_state to 1.
- //
- // Note: we could save a var and ditch wait_state and check
- // 'command' for non zero means busy
- //
- // Note: I can't see that we ever check the value of wait_state
- // but perhaps it accesses that memory location directly?
-
- switch (obSpeech.getCommand()) {
- case 0:
- break;
- case INS_talk:
- pars[0] = params[0]; // ob_graphic
- pars[1] = params[1]; // ob_speech
- pars[2] = params[2]; // ob_logic
- pars[3] = params[3]; // ob_mega
- pars[4] = obSpeech.getIns1(); // encoded text number
- pars[5] = obSpeech.getIns2(); // wav res id
- pars[6] = obSpeech.getIns3(); // anim res id
- pars[7] = obSpeech.getIns4(); // anim table res id
- pars[8] = obSpeech.getIns5(); // animation mode - 0 lip synced, 1 just straight animation
-
- if (fnISpeak(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_turn:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = params[3]; // ob_mega
- pars[3] = params[4]; // ob_walkdata
- pars[4] = obSpeech.getIns1(); // direction to turn to
-
- if (fnTurn(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_face:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = params[3]; // ob_mega
- pars[3] = params[4]; // ob_walkdata
- pars[4] = obSpeech.getIns1(); // target
-
- if (fnFaceMega(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_anim:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = obSpeech.getIns1(); // anim res
-
- if (fnAnim(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_reverse_anim:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = obSpeech.getIns1(); // anim res
-
- if (fnReverseAnim(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_table_anim:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = params[3]; // ob_mega
- pars[3] = obSpeech.getIns1(); // pointer to anim table
-
- if (fnMegaTableAnim(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_reverse_table_anim:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = params[3]; // ob_mega
- pars[3] = obSpeech.getIns1(); // pointer to anim table
-
- if (fnReverseMegaTableAnim(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_no_sprite:
- fnNoSprite(params); // ob_graphic
-
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- return IR_REPEAT ;
- case INS_sort:
- fnSortSprite(params); // ob_graphic
-
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- return IR_REPEAT;
- case INS_foreground:
- fnForeSprite(params); // ob_graphic
-
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- return IR_REPEAT;
- case INS_background:
- fnBackSprite(params); // ob_graphic
-
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- return IR_REPEAT;
- case INS_walk:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = params[3]; // ob_mega
- pars[3] = params[4]; // ob_walkdata
- pars[4] = obSpeech.getIns1(); // target x
- pars[5] = obSpeech.getIns2(); // target y
- pars[6] = obSpeech.getIns3(); // target direction
-
- if (fnWalk(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_walk_to_anim:
- pars[0] = params[2]; // ob_logic
- pars[1] = params[0]; // ob_graphic
- pars[2] = params[3]; // ob_mega
- pars[3] = params[4]; // ob_walkdata
- pars[4] = obSpeech.getIns1(); // anim resource
-
- if (fnWalkToAnim(pars) != IR_REPEAT) {
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- }
-
- return IR_REPEAT;
- case INS_stand_after_anim:
- pars[0] = params[0]; // ob_graphic
- pars[1] = params[3]; // ob_mega
- pars[2] = obSpeech.getIns1(); // anim resource
-
- fnStandAfterAnim(pars);
-
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- return IR_REPEAT;
- case INS_set_frame:
- pars[0] = params[0]; // ob_graphic
- pars[1] = obSpeech.getIns1(); // anim_resource
- pars[2] = obSpeech.getIns2(); // FIRST_FRAME or LAST_FRAME
- fnSetFrame(pars);
-
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- return IR_REPEAT;
- case INS_quit:
- // That's it - we're finished with this
- obSpeech.setCommand(0);
- // obSpeech.setWaitState(0);
- return IR_CONT;
- default:
- // Unimplemented command - just cancel
- obSpeech.setCommand(0);
- obSpeech.setWaitState(1);
- break;
- }
-
- if (readVar(SPEECH_ID) == readVar(ID)) {
- // There's a new command for us! Grab the command -
- // potentially we only have this cycle to do this - and
- // set things up so that the command will be picked up
- // on the next iteration of the while loop.
-
- debug(5, "fnSpeechProcess: Received new command %d", readVar(INS_COMMAND));
-
- writeVar(SPEECH_ID, 0);
-
- obSpeech.setCommand(readVar(INS_COMMAND));
- obSpeech.setIns1(readVar(INS1));
- obSpeech.setIns2(readVar(INS2));
- obSpeech.setIns3(readVar(INS3));
- obSpeech.setIns4(readVar(INS4));
- obSpeech.setIns5(readVar(INS5));
- obSpeech.setWaitState(0);
-
- writeVar(INS_COMMAND, 0);
- } else {
- // No new command. We could run a blink anim (or
- // something) here.
-
- obSpeech.setWaitState(1);
- return IR_REPEAT;
- }
- }
-}
-
-int32 Logic::fnSetScaling(int32 *params) {
- // params: 0 pointer to object's mega structure
- // 1 scale constant A
- // 2 scale constant B
-
- // 256 * s = A * y + B
-
- // Where s is system scale, which itself is (256 * actual_scale) ie.
- // s == 128 is half size
-
- ObjectMega obMega(decodePtr(params[0]));
-
- obMega.setScaleA(params[1]);
- obMega.setScaleB(params[2]);
-
- return IR_CONT;
-}
-
-int32 Logic::fnStartEvent(int32 *params) {
- // params: none
-
- startEvent();
- return IR_TERMINATE;
-}
-
-int32 Logic::fnCheckEventWaiting(int32 *params) {
- // params: none
-
- writeVar(RESULT, checkEventWaiting());
- return IR_CONT;
-}
-
-int32 Logic::fnRequestSpeech(int32 *params) {
- // change current script - must be followed by a TERMINATE script
- // directive
-
- // params: 0 id of target to catch the event and startup speech
- // servicing
-
- // Full script id to interact with - megas run their own 7th script
- sendEvent(params[0], (params[0] << 16) | 6);
- return IR_CONT;
-}
-
-int32 Logic::fnGosub(int32 *params) {
- // params: 0 id of script
-
- // Hurray, script subroutines. Logic goes up - pc is saved for current
- // level.
- logicUp(params[0]);
- return IR_GOSUB;
-}
-
-/**
- * Wait for a target to become waiting, i.e. not busy, or until we time out.
- * This is useful when clicking on a target to talk to it, and it doesn't
- * reply. This way, we won't lock up.
- *
- * If the target becomes waiting, RESULT is set to 0. If we time out, RESULT is
- * set to 1.
- */
-
-int32 Logic::fnTimedWait(int32 *params) {
- // params: 0 ob_logic
- // 1 target
- // 2 number of cycles before give up
-
- assert(_vm->_resman->fetchType(params[1]) == GAME_OBJECT);
-
- ObjectLogic obLogic(decodePtr(params[0]));
-
- if (obLogic.getLooping() == 0) {
- // This is the first time, so set up the time-out.
- obLogic.setLooping(params[2]);
- }
-
- // Run the target's get-speech-state script
- runResScript(params[1], 5);
-
- if (readVar(RESULT) == 1) {
- // The target is waiting, i.e. not busy
-
- _vm->_debugger->_speechScriptWaiting = 0;
-
- obLogic.setLooping(0);
- writeVar(RESULT, 0);
- return IR_CONT;
- }
-
- obLogic.setLooping(obLogic.getLooping() - 1);
-
- if (obLogic.getLooping() == 0) {
- // Time's up.
-
- debug(5, "fnTimedWait: Timed out waiting for %d", params[1]);
- _vm->_debugger->_speechScriptWaiting = 0;
-
- // Clear the event that hasn't been picked up - in theory,
- // none of this should ever happen.
-
- killAllIdsEvents(params[1]);
- writeVar(RESULT, 1);
- return IR_CONT;
- }
-
- // Target is busy. Keep trying.
-
- _vm->_debugger->_speechScriptWaiting = params[1];
- return IR_REPEAT;
-}
-
-int32 Logic::fnPlayFx(int32 *params) {
- // params: 0 sample resource id
- // 1 type (FX_SPOT, FX_RANDOM, FX_LOOP)
- // 2 delay (0..65535)
- // 3 volume (0..16)
- // 4 pan (-16..16)
-
- // example script:
- // fnPlayFx (FXWATER, FX_LOOP, 0, 10, 15);
- // // fx_water is just a local script flag
- // fx_water = result;
- // .
- // .
- // .
- // fnStopFx (fx_water);
-
- int32 res = params[0];
- int32 type = params[1];
- int32 delay = params[2];
- int32 volume = params[3];
- int32 pan = params[4];
-
- _vm->_sound->queueFx(res, type, delay, volume, pan);
- return IR_CONT;
-}
-
-int32 Logic::fnStopFx(int32 *params) {
- // params: 0 position in queue
- if (_vm->_sound->stopFx(params[0]) != RD_OK)
- debug(5, "SFX ERROR: Trying to stop an inactive sound slot");
-
- return IR_CONT;
-}
-
-/**
- * Start a tune playing, to play once or to loop until stopped or next one
- * played.
- */
-
-int32 Logic::fnPlayMusic(int32 *params) {
- // params: 0 tune id
- // 1 loop flag (0 or 1)
-
- char filename[128];
- bool loopFlag;
- uint32 rv;
-
- loopFlag = (params[1] == FX_LOOP);
-
- rv = _vm->_sound->streamCompMusic(params[0], loopFlag);
-
- if (rv)
- debug(5, "ERROR: streamCompMusic(%s, %d, %d) returned error 0x%.8x", filename, params[0], loopFlag, rv);
-
- return IR_CONT;
-}
-
-int32 Logic::fnStopMusic(int32 *params) {
- // params: none
-
- _vm->_sound->stopMusic(false);
- return IR_CONT;
-}
-
-int32 Logic::fnSetValue(int32 *params) {
- // temp. function!
-
- // used for setting far-referenced megaset resource field in mega
- // object, from start script
-
- // params: 0 pointer to object's mega structure
- // 1 value to set it to
-
- ObjectMega obMega(decodePtr(params[0]));
-
- obMega.setMegasetRes(params[1]);
- return IR_CONT;
-}
-
-int32 Logic::fnNewScript(int32 *params) {
- // change current script - must be followed by a TERMINATE script
- // directive
-
- // params: 0 id of script
-
- writeVar(PLAYER_ACTION, 0); // must clear this
- logicReplace(params[0]);
- return IR_TERMINATE;
-}
-
-/**
- * Like getSync(), but called from scripts. Sets the RESULT variable to
- * the sync value, or 0 if none is found.
- */
-
-int32 Logic::fnGetSync(int32 *params) {
- // params: none
-
- int slot = getSync();
-
- writeVar(RESULT, (slot != -1) ? _syncList[slot].sync : 0);
- return IR_CONT;
-}
-
-/**
- * Wait for sync to happen. Sets the RESULT variable to the sync value, once
- * it has been found.
- */
-
-int32 Logic::fnWaitSync(int32 *params) {
- // params: none
-
- debug(6, "fnWaitSync: %d waits", readVar(ID));
-
- int slot = getSync();
-
- if (slot == -1)
- return IR_REPEAT;
-
- debug(5, "fnWaitSync: %d got sync %d", readVar(ID), _syncList[slot].sync);
- writeVar(RESULT, _syncList[slot].sync);
- return IR_CONT;
-}
-
-int32 Logic::fnRegisterWalkGrid(int32 *params) {
- // params: none
-
- warning("fnRegisterWalkGrid() is no longer a valid opcode");
- return IR_CONT;
-}
-
-int32 Logic::fnReverseMegaTableAnim(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to animation table
-
- // Reverse anim
- return _router->megaTableAnimate(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- true);
-}
-
-int32 Logic::fnReverseAnim(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 resource id of animation file
-
- // Reverse anim
- return _router->doAnimate(
- decodePtr(params[0]),
- decodePtr(params[1]),
- params[2], true);
-}
-
-/**
- * Mark this object for killing - to be killed when player leaves this screen.
- * Object reloads and script restarts upon re-entry to screen, which causes
- * this object's startup logic to be re-run every time we enter the screen.
- * "Which is nice."
- *
- * @note Call ONCE from object's logic script, i.e. in startup code, so not
- * re-called every time script frops off and restarts!
- */
-
-int32 Logic::fnAddToKillList(int32 *params) {
- // params: none
- uint32 id = readVar(ID);
-
- // DON'T EVER KILL GEORGE!
- if (id == CUR_PLAYER_ID)
- return IR_CONT;
-
- // Scan the list to see if it's already included
-
- for (uint32 i = 0; i < _kills; i++) {
- if (_objectKillList[i] == id)
- return IR_CONT;
- }
-
- assert(_kills < OBJECT_KILL_LIST_SIZE); // no room at the inn
-
- _objectKillList[_kills++] = id;
-
- // "another one bites the dust"
-
- // When we leave the screen, all these object resources are to be
- // cleaned out of memory and the kill list emptied by doing
- // '_kills = 0', ensuring that all resources are in fact still in
- // memory and, more importantly, closed before killing!
-
- return IR_CONT;
-}
-
-/**
- * Set the standby walk coords to be used by fnWalkToAnim() and
- * fnStandAfterAnim() when the anim header's start/end coords are zero.
- * Useful during development; can stay in final game anyway.
- */
-
-int32 Logic::fnSetStandbyCoords(int32 *params) {
- // params: 0 x-coord
- // 1 y-coord
- // 2 direction (0..7)
-
- _router->setStandbyCoords(params[0], params[1], params[2]);
- return IR_CONT;
-}
-
-int32 Logic::fnBackPar0Sprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), BGP0_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnBackPar1Sprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), BGP1_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnForePar0Sprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), FGP0_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnForePar1Sprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteStatus(decodePtr(params[0]), FGP1_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnSetPlayerActionEvent(int32 *params) {
- // we want to intercept the player character and have him interact
- // with an object - from script this code is the same as the mouse
- // engine calls when you click on an object - here, a third party
- // does the clicking IYSWIM
-
- // note - this routine used CUR_PLAYER_ID as the target
-
- // params: 0 id to interact with
-
- setPlayerActionEvent(CUR_PLAYER_ID, params[0]);
- return IR_CONT;
-}
-
-/**
- * Set the special scroll offset variables
- *
- * Call when starting screens and to change the camera within screens
- *
- * call AFTER fnInitBackground() to override the defaults
- */
-
-int32 Logic::fnSetScrollCoordinate(int32 *params) {
- // params: 0 feet_x value
- // 1 feet_y value
-
- // Called feet_x and feet_y to retain intellectual compatibility with
- // Sword1!
- //
- // feet_x & feet_y refer to the physical screen coords where the
- // system will try to maintain George's feet
-
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- screenInfo->feet_x = params[0];
- screenInfo->feet_y = params[1];
- return IR_CONT;
-}
-
-/**
- * Stand mega at start position of anim
- */
-
-int32 Logic::fnStandAtAnim(int32 *params) {
- // params: 0 pointer to object's graphic structure
- // 1 pointer to object's mega structure
- // 2 anim resource id
-
- _router->standAtAnim(
- decodePtr(params[0]),
- decodePtr(params[1]),
- params[2]);
- return IR_CONT;
-}
-
-#define SCROLL_MOUSE_WIDTH 20
-
-int32 Logic::fnSetScrollLeftMouse(int32 *params) {
- // params: 0 pointer to object's mouse structure
-
- byte *ob_mouse = decodePtr(params[0]);
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- // Highest priority
-
- ObjectMouse mouse;
-
- mouse.x1 = 0;
- mouse.y1 = 0;
- mouse.x2 = screenInfo->scroll_offset_x + SCROLL_MOUSE_WIDTH;
- mouse.y2 = screenInfo->screen_deep - 1;
- mouse.priority = 0;
-
- if (screenInfo->scroll_offset_x > 0) {
- // not fully scrolled to the left
- mouse.pointer = SCROLL_LEFT_MOUSE_ID;
- } else {
- // so the mouse area doesn't get registered
- mouse.pointer = 0;
- }
-
- mouse.write(ob_mouse);
- return IR_CONT;
-}
-
-int32 Logic::fnSetScrollRightMouse(int32 *params) {
- // params: 0 pointer to object's mouse structure
-
- byte *ob_mouse = decodePtr(params[0]);
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- // Highest priority
-
- ObjectMouse mouse;
-
- mouse.x1 = screenInfo->scroll_offset_x + _vm->_screen->getScreenWide() - SCROLL_MOUSE_WIDTH;
- mouse.y1 = 0;
- mouse.x2 = screenInfo->screen_wide - 1;
- mouse.y2 = screenInfo->screen_deep - 1;
- mouse.priority = 0;
-
- if (screenInfo->scroll_offset_x < screenInfo->max_scroll_offset_x) {
- // not fully scrolled to the right
- mouse.pointer = SCROLL_RIGHT_MOUSE_ID;
- } else {
- // so the mouse area doesn't get registered
- mouse.pointer = 0;
- }
-
- mouse.write(ob_mouse);
- return IR_CONT;
-}
-
-int32 Logic::fnColour(int32 *params) {
- // set border colour - useful during script development
- // eg. set to colour during a timer situation, then black when timed
- // out
-
- // params 0: colour (see defines above)
-
-#ifdef SWORD2_DEBUG
- // what colour?
- switch (params[0]) {
- case BLACK:
- _vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
- break;
- case WHITE:
- _vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
- break;
- case RED:
- _vm->_screen->setPalette(0, 1, red, RDPAL_INSTANT);
- break;
- case GREEN:
- _vm->_screen->setPalette(0, 1, green, RDPAL_INSTANT);
- break;
- case BLUE:
- _vm->_screen->setPalette(0, 1, blue, RDPAL_INSTANT);
- break;
- }
-#endif
-
- return IR_CONT;
-}
-
-#ifdef SWORD2_DEBUG
-#define BLACK 0
-#define WHITE 1
-#define RED 2
-#define GREEN 3
-#define BLUE 4
-
-static uint8 black[4] = { 0, 0, 0, 0 };
-static uint8 white[4] = { 255, 255, 255, 0 };
-static uint8 red[4] = { 255, 0, 0, 0 };
-static uint8 green[4] = { 0, 255, 0, 0 };
-static uint8 blue[4] = { 0, 0, 255, 0 };
-#endif
-
-int32 Logic::fnFlash(int32 *params) {
- // flash colour 0 (ie. border) - useful during script development
- // eg. fnFlash(BLUE) where a text line is missed; RED when some code
- // missing, etc
-
- // params: 0 colour to flash
-
-#ifdef SWORD2_DEBUG
- // what colour?
- switch (params[0]) {
- case WHITE:
- _vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
- break;
- case RED:
- _vm->_screen->setPalette(0, 1, red, RDPAL_INSTANT);
- break;
- case GREEN:
- _vm->_screen->setPalette(0, 1, green, RDPAL_INSTANT);
- break;
- case BLUE:
- _vm->_screen->setPalette(0, 1, blue, RDPAL_INSTANT);
- break;
- }
-
- // There used to be a busy-wait loop here, so I don't know how long
- // the delay was meant to be. Probably doesn't matter much.
-
- _vm->_screen->updateDisplay();
- _vm->_system->delayMillis(250);
- _vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
-#endif
-
- return IR_CONT;
-}
-
-int32 Logic::fnPreFetch(int32 *params) {
- // Go fetch resource in the background.
-
- // params: 0 resource to fetch [guess]
-
- return IR_CONT;
-}
-
-/**
- * Reverse of fnPassPlayerSaveData() - run script 8 of player object.
- */
-
-int32 Logic::fnGetPlayerSaveData(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
-
- byte *ob_logic = decodePtr(params[0]);
- byte *ob_graph = decodePtr(params[1]);
- byte *ob_mega = decodePtr(params[2]);
-
- // Copy from savegame buffers to player object
-
- memcpy(ob_logic, _saveLogic, ObjectLogic::size());
- memcpy(ob_graph, _saveGraphic, ObjectGraphic::size());
- memcpy(ob_mega, _saveMega, ObjectMega::size());
-
- // Any walk-data must be cleared - the player will be set to stand if
- // he was walking when saved.
-
- ObjectMega obMega(ob_mega);
-
- if (obMega.getIsWalking()) {
- ObjectLogic obLogic(ob_logic);
-
- obMega.setIsWalking(0);
-
- int32 pars[3];
-
- pars[0] = params[1]; // ob_graphic;
- pars[1] = params[2]; // ob_mega
- pars[2] = obMega.getCurDir();
-
- fnStand(pars);
-
- // Reset looping flag (which would have been 1 during fnWalk)
- obLogic.setLooping(0);
- }
-
- return IR_CONT;
-}
-
-/**
- * Copies the 4 essential player structures into the savegame header - run
- * script 7 of player object to request this.
- *
- * Remember, we cannot simply read a compact any longer but instead must
- * request it from the object itself.
- */
-
-int32 Logic::fnPassPlayerSaveData(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
-
- // Copy from player object to savegame buffers
-
- memcpy(_saveLogic, decodePtr(params[0]), ObjectLogic::size());
- memcpy(_saveGraphic, decodePtr(params[1]), ObjectGraphic::size());
- memcpy(_saveMega, decodePtr(params[2]), ObjectMega::size());
-
- return IR_CONT;
-}
-
-int32 Logic::fnSendEvent(int32 *params) {
- // we want to intercept the player character and have him interact
- // with an object - from script
-
- // params: 0 id to receive event
- // 1 script to run
-
- sendEvent(params[0], params[1]);
- return IR_CONT;
-}
-
-/**
- * Add this walkgrid resource to the list of those used for routing in this
- * location. Note that this is ignored if the resource is already in the list.
- */
-
-int32 Logic::fnAddWalkGrid(int32 *params) {
- // params: 0 id of walkgrid resource
-
- // All objects that add walkgrids must be restarted whenever we
- // re-enter a location.
-
- // DON'T EVER KILL GEORGE!
- if (readVar(ID) != CUR_PLAYER_ID) {
- // Need to call this in case it wasn't called in script!
- fnAddToKillList(NULL);
- }
-
- _router->addWalkGrid(params[0]);
- fnPreLoad(params);
- return IR_CONT;
-}
-
-/**
- * Remove this walkgrid resource from the list of those used for routing in
- * this location. Note that this is ignored if the resource isn't actually
- * in the list.
- */
-
-int32 Logic::fnRemoveWalkGrid(int32 *params) {
- // params: 0 id of walkgrid resource
-
- _router->removeWalkGrid(params[0]);
- return IR_CONT;
-}
-
-// like fnCheckEventWaiting, but starts the event rather than setting RESULT
-// to 1
-
-int32 Logic::fnCheckForEvent(int32 *params) {
- // params: none
-
- if (checkEventWaiting()) {
- startEvent();
- return IR_TERMINATE;
- }
-
- return IR_CONT;
-}
-
-// combination of fnPause and fnCheckForEvent
-// - ie. does a pause, but also checks for event each cycle
-
-int32 Logic::fnPauseForEvent(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 number of game-cycles to pause
-
- ObjectLogic obLogic(decodePtr(params[0]));
-
- if (checkEventWaiting()) {
- obLogic.setLooping(0);
- startEvent();
- return IR_TERMINATE;
- }
-
- return fnPause(params);
-}
-
-int32 Logic::fnClearEvent(int32 *params) {
- // params: none
-
- clearEvent(readVar(ID));
- return IR_CONT;
-}
-
-int32 Logic::fnFaceMega(int32 *params) {
- // params: 0 pointer to object's logic structure
- // 1 pointer to object's graphic structure
- // 2 pointer to object's mega structure
- // 3 pointer to object's walkdata structure
- // 4 id of target mega to face
-
- return _router->faceMega(
- decodePtr(params[0]),
- decodePtr(params[1]),
- decodePtr(params[2]),
- decodePtr(params[3]),
- params[4]);
-}
-
-int32 Logic::fnPlaySequence(int32 *params) {
- // params: 0 pointer to null-terminated ascii filename
- // 1 number of frames in the sequence, used for PSX.
-
- char filename[30];
- MovieTextObject *sequenceSpeechArray[MAX_SEQUENCE_TEXT_LINES + 1];
-
- // The original code had some #ifdef blocks for skipping or muting the
- // cutscenes - fondly described as "the biggest fudge in the history
- // of computer games" - but at the very least we want to show the
- // cutscene subtitles, so I removed them.
-
- debug(5, "fnPlaySequence(\"%s\");", (const char *)decodePtr(params[0]));
-
- // add the appropriate file extension & play it
-
- strcpy(filename, (const char *)decodePtr(params[0]));
-
- // Write to walkthrough file (zebug0.txt)
- debug(5, "PLAYING SEQUENCE \"%s\"", filename);
-
- // now create the text sprites, if any
-
- if (_sequenceTextLines)
- createSequenceSpeech(sequenceSpeechArray);
-
- // don't want to carry on streaming game music when smacker starts!
- fnStopMusic(NULL);
-
- // pause sfx during sequence
- _vm->_sound->pauseFx();
-
- MoviePlayer player(_vm);
- uint32 rv;
-
- if (_sequenceTextLines && !readVar(DEMO))
- rv = player.play(filename, sequenceSpeechArray, _smackerLeadIn, _smackerLeadOut);
- else
- rv = player.play(filename, NULL, _smackerLeadIn, _smackerLeadOut);
-
- // check the error return-value
- if (rv)
- debug(5, "MoviePlayer.play(\"%s\") returned 0x%.8x", filename, rv);
-
- // unpause sound fx again, in case we're staying in same location
- _vm->_sound->unpauseFx();
-
- _smackerLeadIn = 0;
- _smackerLeadOut = 0;
-
- // now clear the text sprites, if any
-
- if (_sequenceTextLines)
- clearSequenceSpeech(sequenceSpeechArray);
-
- // now clear the screen in case the Sequence was quitted (using ESC)
- // rather than fading down to black
-
- _vm->_screen->clearScene();
-
- // zero the entire palette in case we're about to fade up!
-
- byte pal[4 * 256];
-
- memset(pal, 0, sizeof(pal));
- _vm->_screen->setPalette(0, 256, pal, RDPAL_INSTANT);
-
- debug(5, "fnPlaySequence FINISHED");
- return IR_CONT;
-}
-
-int32 Logic::fnShadedSprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteShading(decodePtr(params[0]), SHADED_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnUnshadedSprite(int32 *params) {
- // params: 0 pointer to object's graphic structure
- _router->setSpriteShading(decodePtr(params[0]), UNSHADED_SPRITE);
- return IR_CONT;
-}
-
-int32 Logic::fnFadeUp(int32 *params) {
- // params: none
-
- _vm->_screen->waitForFade();
-
- if (_vm->_screen->getFadeStatus() == RDFADE_BLACK)
- _vm->_screen->fadeUp();
-
- return IR_CONT;
-}
-
-int32 Logic::fnDisplayMsg(int32 *params) {
- // Display a message to the user on the screen.
-
- // params: 0 Text number of message to be displayed.
-
- uint32 local_text = params[0] & 0xffff;
- uint32 text_res = params[0] / SIZE;
-
- // Display message for three seconds.
-
- // +2 to skip the encoded text number in the first 2 chars; 3 is
- // duration in seconds
-
- _vm->_screen->displayMsg(_vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text) + 2, 3);
- _vm->_resman->closeResource(text_res);
-
- return IR_CONT;
-}
-
-int32 Logic::fnSetObjectHeld(int32 *params) {
- // params: 0 luggage icon to set
- uint32 res = (uint32)params[0];
-
- _vm->_mouse->setObjectHeld(res);
- return IR_CONT;
-}
-
-int32 Logic::fnAddSequenceText(int32 *params) {
- // params: 0 text number
- // 1 frame number to start the text displaying
- // 2 frame number to stop the text dispalying
-
- assert(_sequenceTextLines < MAX_SEQUENCE_TEXT_LINES);
-
- _sequenceTextList[_sequenceTextLines].textNumber = params[0];
- _sequenceTextList[_sequenceTextLines].startFrame = params[1];
- _sequenceTextList[_sequenceTextLines].endFrame = params[2];
- _sequenceTextLines++;
- return IR_CONT;
-}
-
-int32 Logic::fnResetGlobals(int32 *params) {
- // fnResetGlobals is used by the demo - so it can loop back & restart
- // itself
-
- // params: none
-
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- byte *globals = _vm->_resman->openResource(1) + ResHeader::size();
- int32 size = _vm->_resman->fetchLen(1) - ResHeader::size();
-
- debug(5, "globals size: %d", size);
-
- // blank each global variable
- memset(globals, 0, size);
-
- _vm->_resman->closeResource(1);
-
- // all objects but george
- _vm->_resman->killAllObjects(false);
-
- // FOR THE DEMO - FORCE THE SCROLLING TO BE RESET!
- // - this is taken from fnInitBackground
-
- // switch on scrolling (2 means first time on screen)
- screenInfo->scroll_flag = 2;
-
- // Used to be IR_CONT, but that's a bad idea. We may just have killed
- // our own script resource -- continuing will cause a bad memory read
- // access.
- return IR_STOP;
-}
-
-int32 Logic::fnSetPalette(int32 *params) {
- // params: 0 resource number of palette file, or 0 if it's to be
- // the palette from the current screen
-
- _vm->_screen->setFullPalette(params[0]);
- return IR_CONT;
-}
-
-// use this in the object's service script prior to registering the mouse area
-// ie. before fnRegisterMouse or fnRegisterFrame
-// - best if kept at very top of service script
-
-int32 Logic::fnRegisterPointerText(int32 *params) {
- // params: 0 local id of text line to use as pointer text
-
- _vm->_mouse->registerPointerText(params[0]);
- return IR_CONT;
-}
-
-int32 Logic::fnFetchWait(int32 *params) {
- // Fetches a resource in the background but prevents the script from
- // continuing until the resource is in memory.
-
- // params: 0 resource to fetch [guess]
-
- return IR_CONT;
-}
-
-int32 Logic::fnRelease(int32 *params) {
- // Releases a resource from memory. Used for freeing memory for
- // sprites that have just been used and will not be used again.
- // Sometimes it is better to kick out a sprite straight away so that
- // the memory can be used for more frequent animations.
-
- // params: 0 resource to release [guess]
-
- return IR_CONT;
-}
-
-int32 Logic::fnPrepareMusic(int32 *params) {
- // params: 1 id of music to prepare [guess]
- return IR_CONT;
-}
-
-int32 Logic::fnSoundFetch(int32 *params) {
- // params: 0 id of sound to fetch [guess]
- return IR_CONT;
-}
-
-int32 Logic::fnSmackerLeadIn(int32 *params) {
- // params: 0 id of lead-in music
-
- // ready for use in fnPlaySequence
- _smackerLeadIn = params[0];
- return IR_CONT;
-}
-
-int32 Logic::fnSmackerLeadOut(int32 *params) {
- // params: 0 id of lead-out music
-
- // ready for use in fnPlaySequence
- _smackerLeadOut = params[0];
- return IR_CONT;
-}
-
-/**
- * Stops all FX and clears the entire FX queue.
- */
-
-int32 Logic::fnStopAllFx(int32 *params) {
- // params: none
-
- _vm->_sound->clearFxQueue();
- return IR_CONT;
-}
-
-int32 Logic::fnCheckPlayerActivity(int32 *params) {
- // Used to decide when to trigger music cues described as "no player
- // activity for a while"
-
- // params: 0 threshold delay in seconds, ie. what we want to
- // check the actual delay against
-
- uint32 seconds = (uint32)params[0];
-
- _vm->_mouse->checkPlayerActivity(seconds);
- return IR_CONT;
-}
-
-int32 Logic::fnResetPlayerActivityDelay(int32 *params) {
- // Use if you want to deliberately reset the "no player activity"
- // counter for any reason
-
- // params: none
-
- _vm->_mouse->resetPlayerActivityDelay();
- return IR_CONT;
-}
-
-int32 Logic::fnCheckMusicPlaying(int32 *params) {
- // params: none
-
- // sets result to no. of seconds of current tune remaining
- // or 0 if no music playing
-
- // in seconds, rounded up to the nearest second
- writeVar(RESULT, _vm->_sound->musicTimeRemaining());
- return IR_CONT;
-}
-
-int32 Logic::fnPlayCredits(int32 *params) {
- // This function just quits the game if this is the playable demo, ie.
- // credits are NOT played in the demo any more!
-
- // params: none
-
- if (readVar(DEMO)) {
- _vm->closeGame();
- return IR_STOP;
- }
-
- _vm->_screen->rollCredits();
- return IR_CONT;
-}
-
-int32 Logic::fnSetScrollSpeedNormal(int32 *params) {
- // params: none
-
- _vm->_screen->setScrollFraction(16);
- return IR_CONT;
-}
-
-int32 Logic::fnSetScrollSpeedSlow(int32 *params) {
- // params: none
-
- _vm->_screen->setScrollFraction(32);
- return IR_CONT;
-}
-
-// Called from speech scripts to remove the chooser bar when it's not
-// appropriate to keep it displayed
-
-int32 Logic::fnRemoveChooser(int32 *params) {
- // params: none
-
- _vm->_mouse->hideMenu(RDMENU_BOTTOM);
- return IR_CONT;
-}
-
-/**
- * Alter the volume and pan of a currently playing FX
- */
-
-int32 Logic::fnSetFxVolAndPan(int32 *params) {
- // params: 0 id of fx (ie. the id returned in 'result' from
- // fnPlayFx
- // 1 new volume (0..16)
- // 2 new pan (-16..16)
-
- debug(5, "fnSetFxVolAndPan(%d, %d, %d)", params[0], params[1], params[2]);
-
- _vm->_sound->setFxIdVolumePan(params[0], params[1], params[2]);
- return IR_CONT;
-}
-
-/**
- * Alter the volume of a currently playing FX
- */
-
-int32 Logic::fnSetFxVol(int32 *params) {
- // params: 0 id of fx (ie. the id returned in 'result' from
- // fnPlayFx
- // 1 new volume (0..16)
-
- _vm->_sound->setFxIdVolumePan(params[0], params[1]);
- return IR_CONT;
-}
-
-int32 Logic::fnRestoreGame(int32 *params) {
- // params: none
- return IR_CONT;
-}
-
-int32 Logic::fnRefreshInventory(int32 *params) {
- // Called from 'menu_look_or_combine' script in 'menu_master' object
- // to update the menu to display a combined object while George runs
- // voice-over. Note that 'object_held' must be set to the graphic of
- // the combined object
-
- // params: none
-
- _vm->_mouse->refreshInventory();
- return IR_CONT;
-}
-
-int32 Logic::fnChangeShadows(int32 *params) {
- // params: none
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- // if last screen was using a shading mask (see below)
- if (screenInfo->mask_flag) {
- uint32 rv = _vm->_screen->closeLightMask();
- if (rv)
- error("Driver Error %.8x", rv);
- screenInfo->mask_flag = false;
- }
-
- return IR_CONT;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/header.h b/sword2/header.h
deleted file mode 100644
index 9aefa52832..0000000000
--- a/sword2/header.h
+++ /dev/null
@@ -1,502 +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 _HEADER
-#define _HEADER
-
-#include "common/stream.h"
-
-namespace Sword2 {
-
-//----------------------------------------------------------
-// SYSTEM FILE & FRAME HEADERS
-//----------------------------------------------------------
-
-//----------------------------------------------------------
-// ALL FILES
-//----------------------------------------------------------
-
-// Standard File Header
-
-#define NAME_LEN 34
-
-struct ResHeader {
- uint8 fileType; // Byte to define file type (see below)
- uint8 compType; // Type of file compression used ie.
- // on whole file (see below)
- uint32 compSize; // Length of compressed file (ie.
- // length on disk)
- uint32 decompSize; // Length of decompressed file held in
- // memory (NB. frames still held
- // compressed)
- byte name[NAME_LEN]; // Name of object
-
- static const int size() {
- return 44;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- fileType = readS.readByte();
- compType = readS.readByte();
- compSize = readS.readUint32LE();
- decompSize = readS.readUint32LE();
- readS.read(name, NAME_LEN);
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeByte(fileType);
- writeS.writeByte(compType);
- writeS.writeUint32LE(compSize);
- writeS.writeUint32LE(decompSize);
- writeS.write(name, NAME_LEN);
- }
-};
-
-// fileType
-
-enum {
- // 0 something's wrong!
- ANIMATION_FILE = 1, // All normal animations & sprites
- // including mega-sets & font files
- // which are the same format (but all
- // frames always uncompressed)
- SCREEN_FILE = 2, // Each contains background, palette,
- // layer sprites, parallax layers &
- // shading mask
- GAME_OBJECT = 3, // Each contains object hub +
- // structures + script data
- WALK_GRID_FILE = 4, // Walk-grid data
- GLOBAL_VAR_FILE = 5, // All the global script variables in
- // one file; "there can be only one"
- PARALLAX_FILE_null = 6, // NOT USED
- RUN_LIST = 7, // Each contains a list of object
- // resource id's
- TEXT_FILE = 8, // Each contains all the lines of text
- // for a location or a character's
- // conversation script
- SCREEN_MANAGER = 9, // One for each location; this contains
- // special startup scripts
- MOUSE_FILE = 10, // Mouse pointers and luggage icons
- // (sprites in General / Mouse pointers
- // & Luggage icons)
- WAV_FILE = 11, // WAV file
- ICON_FILE = 12, // Menu icon (sprites in General / Menu
- // icons)
- PALETTE_FILE = 13 // separate palette file (see also
- // _paletteHeader)
-};
-
-// compType
-
-enum {
- NO_COMPRESSION = 0,
- FILE_COMPRESSION = 1 // standard whole-file compression
- // (not yet devised!)
-};
-
-//----------------------------------------------------------
-// (1) ANIMATION FILES
-//----------------------------------------------------------
-
-// an animation file consists of:
-//
-// standard file header
-// animation header
-// a string of CDT entries (one per frame of the anim)
-// a 16-byte colour table ONLY if (runTimeComp==RLE16)
-// a string of groups of (frame header + frame data)
-
-// Animation Header
-
-struct AnimHeader {
- uint8 runTimeComp; // Type of runtime compression used for the
- // frame data (see below)
- uint16 noAnimFrames; // Number of frames in the anim (ie. no. of
- // CDT entries)
- uint16 feetStartX; // Start coords for mega to walk to, before
- uint16 feetStartY; // running anim
- uint8 feetStartDir; // Direction to start in before running anim
- uint16 feetEndX; // End coords for mega to stand at after
- uint16 feetEndY; // running anim (vital if anim starts from an
- // off-screen position, or ends in a different
- // place from the start)
- uint8 feetEndDir; // Direction to start in after running anim
- uint16 blend;
-
- static const int size() {
- return 15;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- runTimeComp = readS.readByte();
- noAnimFrames = readS.readUint16LE();
- feetStartX = readS.readUint16LE();
- feetStartY = readS.readUint16LE();
- feetStartDir = readS.readByte();
- feetEndX = readS.readUint16LE();
- feetEndY = readS.readUint16LE();
- feetEndDir = readS.readByte();
- blend = readS.readUint16LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeByte(runTimeComp);
- writeS.writeUint16LE(noAnimFrames);
- writeS.writeUint16LE(feetStartX);
- writeS.writeUint16LE(feetStartY);
- writeS.writeByte(feetStartDir);
- writeS.writeUint16LE(feetEndX);
- writeS.writeUint16LE(feetEndY);
- writeS.writeByte(feetEndDir);
- writeS.writeUint16LE(blend);
- }
-
-};
-
-// runtimeComp - compression used on each frame of the anim
-
-enum {
- NONE = 0, // No frame compression
- RLE256 = 1, // James's RLE for 256-colour sprites
- RLE16 = 2 // James's RLE for 16- or 17-colour sprites
- // (raw blocks have max 16 colours for 2 pixels
- // per byte, so '0's are encoded only as FLAT
- // for 17-colour sprites eg. George's mega-set)
-};
-
-// CDT Entry
-
-struct CdtEntry {
- int16 x; // sprite x-coord OR offset to add to mega's
- // feet x-coord to calc sprite y-coord
- int16 y; // sprite y-coord OR offset to add to mega's
- // feet y-coord to calc sprite y-coord
- uint32 frameOffset; // points to start of frame header (from start
- // of file header)
- uint8 frameType; // 0 = print sprite normally with top-left
- // corner at (x,y), otherwise see below...
-
- static const int size() {
- return 9;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- x = readS.readUint16LE();
- y = readS.readUint16LE();
- frameOffset = readS.readUint32LE();
- frameType = readS.readByte();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint16LE(x);
- writeS.writeUint16LE(y);
- writeS.writeUint32LE(frameOffset);
- writeS.writeByte(frameType);
- }
-};
-
-// 'frameType' bit values
-
-enum {
- FRAME_OFFSET = 1, // Print at (feetX + x, feetY + y), with
- // scaling according to feetY
- FRAME_FLIPPED = 2, // Print the frame flipped Left->Right
- FRAME_256_FAST = 4 // Frame has been compressed using Pauls fast
- // RLE 256 compression.
-};
-
-// Frame Header
-
-struct FrameHeader {
- uint32 compSize; // Compressed size of frame - NB. compression
- // type is now in Anim Header
- uint16 width; // Dimensions of frame
- uint16 height;
-
- static const int size() {
- return 8;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- compSize = readS.readUint32LE();
- width = readS.readUint16LE();
- height = readS.readUint16LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint32LE(compSize);
- writeS.writeUint16LE(width);
- writeS.writeUint16LE(height);
- }
-};
-
-//----------------------------------------------------------
-// (2) SCREEN FILES
-//----------------------------------------------------------
-// a screen file consists of:
-//
-// standard file header
-// multi screen header
-// 4 * 256 bytes of palette data
-// 256k palette match table
-// 2 background parallax layers
-// 1 background layer with screen header
-// 2 foreground parallax layers
-// a string of layer headers
-// a string of layer masks
-
-// Multi screen header
-// Goes at the beginning of a screen file after the standard header.
-// Gives offsets from start of table of each of the components
-
-struct MultiScreenHeader {
- uint32 palette;
- uint32 bg_parallax[2];
- uint32 screen;
- uint32 fg_parallax[2];
- uint32 layers;
- uint32 paletteTable;
- uint32 maskOffset;
-
- static const int size() {
- return 36;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- palette = readS.readUint32LE();
- bg_parallax[0] = readS.readUint32LE();
- bg_parallax[1] = readS.readUint32LE();
- screen = readS.readUint32LE();
- fg_parallax[0] = readS.readUint32LE();
- fg_parallax[1] = readS.readUint32LE();
- layers = readS.readUint32LE();
- paletteTable = readS.readUint32LE();
- maskOffset = readS.readUint32LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint32LE(palette);
- writeS.writeUint32LE(bg_parallax[0]);
- writeS.writeUint32LE(bg_parallax[1]);
- writeS.writeUint32LE(screen);
- writeS.writeUint32LE(fg_parallax[0]);
- writeS.writeUint32LE(fg_parallax[1]);
- writeS.writeUint32LE(layers);
- writeS.writeUint32LE(paletteTable);
- writeS.writeUint32LE(maskOffset);
- }
-};
-
-// Screen Header
-
-struct ScreenHeader {
- uint16 width; // dimensions of the background screen
- uint16 height;
- uint16 noLayers; // number of layer areas
-
- static const int size() {
- return 6;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- width = readS.readUint16LE();
- height = readS.readUint16LE();
- noLayers = readS.readUint16LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint16LE(width);
- writeS.writeUint16LE(height);
- writeS.writeUint16LE(noLayers);
- }
-};
-
-// Layer Header
-
-// Note that all the layer headers are kept together, rather than being placed
-// before each layer mask, in order to simplify the sort routine.
-
-struct LayerHeader {
- uint16 x; // coordinates of top-left pixel of area
- uint16 y;
- uint16 width;
- uint16 height;
- uint32 maskSize;
- uint32 offset; // where to find mask data (from start of
- // standard file header)
-
- static const int size() {
- return 16;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- x = readS.readUint16LE();
- y = readS.readUint16LE();
- width = readS.readUint16LE();
- height = readS.readUint16LE();
- maskSize = readS.readUint32LE();
- offset = readS.readUint32LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint16LE(x);
- writeS.writeUint16LE(y);
- writeS.writeUint16LE(width);
- writeS.writeUint16LE(height);
- writeS.writeUint32LE(maskSize);
- writeS.writeUint32LE(offset);
- }
-};
-
-//----------------------------------------------------------
-// (3) SCRIPT OBJECT FILES
-//----------------------------------------------------------
-// a script object file consists of:
-//
-// standard file header
-// script object header
-// script object data
-
-//----------------------------------------------------------
-// (5) PALETTE FILES
-//----------------------------------------------------------
-// a palette file consists of:
-//
-// standard file header
-// 4 * 256 bytes of palette data
-// 256k palette match table
-
-// an object hub - which represents all that remains of the compact concept
-
-class ObjectHub {
- // int32 type; // type of object
- // uint32 logic_level; // what level?
- // uint32 logic[3] // NOT USED
- // uint32 script_id[3] // need this if script
- // uint32 script_pc[3] // need this also
-
-private:
- byte *_addr;
-
-public:
- ObjectHub() {
- _addr = NULL;
- }
-
- static const int size() {
- return 44;
- }
-
- byte *data() {
- return _addr;
- }
-
- void setAddress(byte *addr) {
- _addr = addr;
- }
-
- byte *getScriptPcPtr(int level) {
- return _addr + 32 + 4 * level;
- }
-
- uint32 getLogicLevel() {
- return READ_LE_UINT32(_addr + 4);
- }
- uint32 getScriptId(int level) {
- return READ_LE_UINT32(_addr + 20 + 4 * level);
- }
- uint32 getScriptPc(int level) {
- return READ_LE_UINT32(_addr + 32 + 4 * level);
- }
-
- void setLogicLevel(uint32 x) {
- WRITE_LE_UINT32(_addr + 4, x);
- }
- void setScriptId(int level, uint32 x) {
- WRITE_LE_UINT32(_addr + 20 + 4 * level, x);
- }
- void setScriptPc(int level, uint32 x) {
- WRITE_LE_UINT32(_addr + 32 + 4 * level, x);
- }
-};
-
-// (6) text module header
-
-struct TextHeader {
- uint32 noOfLines; // how many lines of text are there in this
- // module
-
- static const int size() {
- return 4;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- noOfLines = readS.readUint32LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint32LE(noOfLines);
- }
-};
-
-// a text file has:
-//
-// ResHeader
-// TextHeader
-// look up table, to
-// line of text,0
-// line of text,0
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/icons.cpp b/sword2/icons.cpp
deleted file mode 100644
index 980c20e3b4..0000000000
--- a/sword2/icons.cpp
+++ /dev/null
@@ -1,216 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/stream.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-
-namespace Sword2 {
-
-void Mouse::addMenuObject(byte *ptr) {
- assert(_totalTemp < TOTAL_engine_pockets);
-
- Common::MemoryReadStream readS(ptr, 2 * sizeof(int32));
-
- _tempList[_totalTemp].icon_resource = readS.readSint32LE();
- _tempList[_totalTemp].luggage_resource = readS.readSint32LE();
- _totalTemp++;
-}
-
-void Mouse::addSubject(int32 id, int32 ref) {
- uint32 in_subject = _vm->_logic->readVar(IN_SUBJECT);
-
- if (in_subject == 0) {
- // This is the start of the new subject list. Set the default
- // repsonse id to zero in case we're never passed one.
- _defaultResponseId = 0;
- }
-
- if (id == -1) {
- // Id -1 is used for setting the default response, i.e. the
- // response when someone uses an object on a person and he
- // doesn't know anything about it. See fnChoose().
-
- _defaultResponseId = ref;
- } else {
- debug(5, "fnAddSubject res %d, uid %d", id, ref);
- _subjectList[in_subject].res = id;
- _subjectList[in_subject].ref = ref;
- _vm->_logic->writeVar(IN_SUBJECT, in_subject + 1);
- }
-}
-
-/**
- * Create and start the inventory (bottom) menu
- */
-
-void Mouse::buildMenu() {
- uint32 i, j;
-
- // Clear the temporary inventory list, since we are going to build a
- // new one from scratch.
-
- for (i = 0; i < TOTAL_engine_pockets; i++)
- _tempList[i].icon_resource = 0;
-
- _totalTemp = 0;
-
- // Run the 'build_menu' script in the 'menu_master' object. This will
- // register all carried menu objects.
-
- _vm->_logic->runResScript(MENU_MASTER_OBJECT, 0);
-
- // Create a new master list based on the old master inventory list and
- // the new temporary inventory list. The purpose of all this is, as
- // far as I can tell, that the new list is ordered in the same way as
- // the old list, with new objects added to the end of it.
-
- // Compare new with old. Anything in master thats not in new gets
- // removed from master - if found in new too, remove from temp
-
- for (i = 0; i < _totalMasters; i++) {
- bool found_in_temp = false;
-
- for (j = 0; j < TOTAL_engine_pockets; j++) {
- if (_masterMenuList[i].icon_resource == _tempList[j].icon_resource) {
- // We alread know about this object, so kill it
- // in the temporary list.
- _tempList[j].icon_resource = 0;
- found_in_temp = true;
- break;
- }
- }
-
- if (!found_in_temp) {
- // The object is in the master list, but not in the
- // temporary list. The player must have lost the object
- // since the last time we checked, so kill it in the
- // master list.
- _masterMenuList[i].icon_resource = 0;
- }
- }
-
- // Eliminate blank entries from the master list.
-
- _totalMasters = 0;
-
- for (i = 0; i < TOTAL_engine_pockets; i++) {
- if (_masterMenuList[i].icon_resource) {
- if (i != _totalMasters) {
- memcpy(&_masterMenuList[_totalMasters], &_masterMenuList[i], sizeof(MenuObject));
- _masterMenuList[i].icon_resource = 0;
- }
- _totalMasters++;
- }
- }
-
- // Add the new objects - i.e. the ones still in the temporary list but
- // not yet in the master list - to the end of the master.
-
- for (i = 0; i < TOTAL_engine_pockets; i++) {
- if (_tempList[i].icon_resource) {
- memcpy(&_masterMenuList[_totalMasters++], &_tempList[i], sizeof(MenuObject));
- }
- }
-
- // Initialise the menu from the master list.
-
- for (i = 0; i < 15; i++) {
- uint32 res = _masterMenuList[i].icon_resource;
- byte *icon = NULL;
-
- if (res) {
- bool icon_coloured;
-
- uint32 object_held = _vm->_logic->readVar(OBJECT_HELD);
- uint32 combine_base = _vm->_logic->readVar(COMBINE_BASE);
-
- if (_examiningMenuIcon) {
- // When examining an object, that object is
- // coloured. The rest are greyed out.
- icon_coloured = (res == object_held);
- } else if (combine_base) {
- // When combining two menu object (i.e. using
- // one on another), both are coloured. The rest
- // are greyed out.
- icon_coloured = (res == object_held || combine_base);
- } else {
- // If an object is selected but we are not yet
- // doing anything with it, the selected object
- // is greyed out. The rest are coloured.
- icon_coloured = (res != object_held);
- }
-
- icon = _vm->_resman->openResource(res) + ResHeader::size();
-
- // The coloured icon is stored directly after the
- // greyed out one.
-
- if (icon_coloured)
- icon += (RDMENU_ICONWIDE * RDMENU_ICONDEEP);
- }
-
- setMenuIcon(RDMENU_BOTTOM, i, icon);
-
- if (res)
- _vm->_resman->closeResource(res);
- }
-
- showMenu(RDMENU_BOTTOM);
-}
-
-/**
- * Build a fresh system (top) menu.
- */
-
-void Mouse::buildSystemMenu() {
- uint32 icon_list[5] = {
- OPTIONS_ICON,
- QUIT_ICON,
- SAVE_ICON,
- RESTORE_ICON,
- RESTART_ICON
- };
-
- // Build them all high in full colour - when one is clicked on all the
- // rest will grey out.
-
- for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
- byte *icon = _vm->_resman->openResource(icon_list[i]) + ResHeader::size();
-
- // The only case when an icon is grayed is when the player
- // is dead. Then SAVE is not available.
-
- if (!_vm->_logic->readVar(DEAD) || icon_list[i] != SAVE_ICON)
- icon += (RDMENU_ICONWIDE * RDMENU_ICONDEEP);
-
- setMenuIcon(RDMENU_TOP, i, icon);
- _vm->_resman->closeResource(icon_list[i]);
- }
-
- showMenu(RDMENU_TOP);
-}
-
-} // End of namespace Sword2
diff --git a/sword2/icons.h b/sword2/icons.h
deleted file mode 100644
index ab5ea578ca..0000000000
--- a/sword2/icons.h
+++ /dev/null
@@ -1,41 +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 _ICONS
-#define _ICONS
-
-#define MENU_MASTER_OBJECT 44
-#define TOTAL_subjects (375 - 256 + 1) // the speech subject bar
-#define TOTAL_engine_pockets (15 + 10) // +10 for overflow
-
-namespace Sword2 {
-
-// define these in a script and then register them with the system
-
-struct MenuObject {
- int32 icon_resource; // icon graphic graphic
- int32 luggage_resource; // luggage icon resource (for attaching to
- // mouse pointer)
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/interpreter.cpp b/sword2/interpreter.cpp
deleted file mode 100644
index 1a6e7080b8..0000000000
--- a/sword2/interpreter.cpp
+++ /dev/null
@@ -1,753 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/util.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/interpreter.h"
-#include "sword2/logic.h"
-#include "sword2/memory.h"
-#include "sword2/resman.h"
-
-namespace Sword2 {
-
-#define STACK_SIZE 10
-
-// The machine code table
-
-#ifndef REDUCE_MEMORY_USAGE
-# define OPCODE(x) { &Logic::x, #x }
-#else
-# define OPCODE(x) { &Logic::x, "" }
-#endif
-
-typedef int32 (Logic::*OpcodeProc)(int32 *);
-struct OpcodeEntry {
- OpcodeProc proc;
- const char *desc;
-};
-
-static const OpcodeEntry opcodes[] = {
- /* 00 */
- OPCODE(fnTestFunction),
- OPCODE(fnTestFlags),
- OPCODE(fnRegisterStartPoint),
- OPCODE(fnInitBackground),
- /* 04 */
- OPCODE(fnSetSession),
- OPCODE(fnBackSprite),
- OPCODE(fnSortSprite),
- OPCODE(fnForeSprite),
- /* 08 */
- OPCODE(fnRegisterMouse),
- OPCODE(fnAnim),
- OPCODE(fnRandom),
- OPCODE(fnPreLoad),
- /* 0C */
- OPCODE(fnAddSubject),
- OPCODE(fnInteract),
- OPCODE(fnChoose),
- OPCODE(fnWalk),
- /* 10 */
- OPCODE(fnWalkToAnim),
- OPCODE(fnTurn),
- OPCODE(fnStandAt),
- OPCODE(fnStand),
- /* 14 */
- OPCODE(fnStandAfterAnim),
- OPCODE(fnPause),
- OPCODE(fnMegaTableAnim),
- OPCODE(fnAddMenuObject),
- /* 18 */
- OPCODE(fnStartConversation),
- OPCODE(fnEndConversation),
- OPCODE(fnSetFrame),
- OPCODE(fnRandomPause),
- /* 1C */
- OPCODE(fnRegisterFrame),
- OPCODE(fnNoSprite),
- OPCODE(fnSendSync),
- OPCODE(fnUpdatePlayerStats),
- /* 20 */
- OPCODE(fnPassGraph),
- OPCODE(fnInitFloorMouse),
- OPCODE(fnPassMega),
- OPCODE(fnFaceXY),
- /* 24 */
- OPCODE(fnEndSession),
- OPCODE(fnNoHuman),
- OPCODE(fnAddHuman),
- OPCODE(fnWeWait),
- /* 28 */
- OPCODE(fnTheyDoWeWait),
- OPCODE(fnTheyDo),
- OPCODE(fnWalkToTalkToMega),
- OPCODE(fnFadeDown),
- /* 2C */
- OPCODE(fnISpeak),
- OPCODE(fnTotalRestart),
- OPCODE(fnSetWalkGrid),
- OPCODE(fnSpeechProcess),
- /* 30 */
- OPCODE(fnSetScaling),
- OPCODE(fnStartEvent),
- OPCODE(fnCheckEventWaiting),
- OPCODE(fnRequestSpeech),
- /* 34 */
- OPCODE(fnGosub),
- OPCODE(fnTimedWait),
- OPCODE(fnPlayFx),
- OPCODE(fnStopFx),
- /* 38 */
- OPCODE(fnPlayMusic),
- OPCODE(fnStopMusic),
- OPCODE(fnSetValue),
- OPCODE(fnNewScript),
- /* 3C */
- OPCODE(fnGetSync),
- OPCODE(fnWaitSync),
- OPCODE(fnRegisterWalkGrid),
- OPCODE(fnReverseMegaTableAnim),
- /* 40 */
- OPCODE(fnReverseAnim),
- OPCODE(fnAddToKillList),
- OPCODE(fnSetStandbyCoords),
- OPCODE(fnBackPar0Sprite),
- /* 44 */
- OPCODE(fnBackPar1Sprite),
- OPCODE(fnForePar0Sprite),
- OPCODE(fnForePar1Sprite),
- OPCODE(fnSetPlayerActionEvent),
- /* 48 */
- OPCODE(fnSetScrollCoordinate),
- OPCODE(fnStandAtAnim),
- OPCODE(fnSetScrollLeftMouse),
- OPCODE(fnSetScrollRightMouse),
- /* 4C */
- OPCODE(fnColour),
- OPCODE(fnFlash),
- OPCODE(fnPreFetch),
- OPCODE(fnGetPlayerSaveData),
- /* 50 */
- OPCODE(fnPassPlayerSaveData),
- OPCODE(fnSendEvent),
- OPCODE(fnAddWalkGrid),
- OPCODE(fnRemoveWalkGrid),
- /* 54 */
- OPCODE(fnCheckForEvent),
- OPCODE(fnPauseForEvent),
- OPCODE(fnClearEvent),
- OPCODE(fnFaceMega),
- /* 58 */
- OPCODE(fnPlaySequence),
- OPCODE(fnShadedSprite),
- OPCODE(fnUnshadedSprite),
- OPCODE(fnFadeUp),
- /* 5C */
- OPCODE(fnDisplayMsg),
- OPCODE(fnSetObjectHeld),
- OPCODE(fnAddSequenceText),
- OPCODE(fnResetGlobals),
- /* 60 */
- OPCODE(fnSetPalette),
- OPCODE(fnRegisterPointerText),
- OPCODE(fnFetchWait),
- OPCODE(fnRelease),
- /* 64 */
- OPCODE(fnPrepareMusic),
- OPCODE(fnSoundFetch),
- OPCODE(fnPrepareMusic), // Again, apparently
- OPCODE(fnSmackerLeadIn),
- /* 68 */
- OPCODE(fnSmackerLeadOut),
- OPCODE(fnStopAllFx),
- OPCODE(fnCheckPlayerActivity),
- OPCODE(fnResetPlayerActivityDelay),
- /* 6C */
- OPCODE(fnCheckMusicPlaying),
- OPCODE(fnPlayCredits),
- OPCODE(fnSetScrollSpeedNormal),
- OPCODE(fnSetScrollSpeedSlow),
- /* 70 */
- OPCODE(fnRemoveChooser),
- OPCODE(fnSetFxVolAndPan),
- OPCODE(fnSetFxVol),
- OPCODE(fnRestoreGame),
- /* 74 */
- OPCODE(fnRefreshInventory),
- OPCODE(fnChangeShadows)
-};
-
-#define push(value) \
-do { \
- assert(stackPtr < ARRAYSIZE(stack)); \
- stack[stackPtr++] = (value); \
-} while (false)
-
-#define push_ptr(ptr) push(_vm->_memory->encodePtr(ptr))
-
-#define pop() (assert(stackPtr < ARRAYSIZE(stack)), stack[--stackPtr])
-
-int Logic::runResScript(uint32 scriptRes, uint32 offset) {
- byte *scriptAddr;
- int result;
-
- scriptAddr = _vm->_resman->openResource(scriptRes);
- result = runScript(scriptAddr, scriptAddr, offset);
- _vm->_resman->closeResource(scriptRes);
-
- return result;
-}
-
-int Logic::runResObjScript(uint32 scriptRes, uint32 objRes, uint32 offset) {
- byte *scriptAddr, *objAddr;
- int result;
-
- scriptAddr = _vm->_resman->openResource(scriptRes);
- objAddr = _vm->_resman->openResource(objRes);
- result = runScript(scriptAddr, objAddr, offset);
- _vm->_resman->closeResource(objRes);
- _vm->_resman->closeResource(scriptRes);
-
- return result;
-}
-
-int Logic::runScript(byte *scriptData, byte *objectData, uint32 offset) {
- byte pc[4];
-
- WRITE_LE_UINT32(pc, offset);
- return runScript2(scriptData, objectData, pc);
-}
-
-// This form of the runScript function is only called directly from
-// the processSession() function, which uses it to update the script PC in the
-// current object hub. For reasons which I do not understand, I couldn't get it
-// to work if I called the function first with a dummy offset variable, and
-// and then updated the object hub myself.
-
-int Logic::runScript2(byte *scriptData, byte *objectData, byte *offsetPtr) {
- // Interestingly, unlike our BASS engine the stack is a local variable.
- // I don't know whether or not this is relevant to the working of the
- // BS2 engine.
-
- int32 stack[STACK_SIZE];
- int32 stackPtr = 0;
-
- uint32 offset = READ_LE_UINT32(offsetPtr);
-
- ResHeader header;
-
- header.read(scriptData);
-
- scriptData += ResHeader::size() + ObjectHub::size();
-
- // The script data format:
- // int32_TYPE 1 Size of variable space in bytes
- // ... The variable space
- // int32_TYPE 1 numberOfScripts
- // int32_TYPE numberOfScripts The offsets for each script
-
- // Initialise some stuff
-
- uint32 ip = 0; // Code pointer
- int scriptNumber;
-
- // Get the start of variables and start of code
-
- byte *localVars = scriptData + 4;
- byte *code = scriptData + READ_LE_UINT32(scriptData) + 4;
- uint32 noScripts = READ_LE_UINT32(code);
-
- code += 4;
-
- byte *offsetTable = code;
-
- if (offset < noScripts) {
- ip = READ_LE_UINT32(offsetTable + offset * 4);
- scriptNumber = offset;
- debug(8, "Starting script %d from %d", scriptNumber, ip);
- } else {
- uint i;
-
- ip = offset;
-
- for (i = 1; i < noScripts; i++) {
- if (READ_LE_UINT32(offsetTable + 4 * i) >= ip)
- break;
- }
-
- scriptNumber = i - 1;
- debug(8, "Resuming script %d from %d", scriptNumber, ip);
- }
-
- // There are a couple of known script bugs related to interacting with
- // certain objects. We try to work around a few of them.
-
- bool checkMopBug = false;
- bool checkPyramidBug = false;
- bool checkElevatorBug = false;
-
- if (scriptNumber == 2) {
- if (strcmp((char *)header.name, "mop_73") == 0)
- checkMopBug = true;
- else if (strcmp((char *)header.name, "titipoco_81") == 0)
- checkPyramidBug = true;
- else if (strcmp((char *)header.name, "lift_82") == 0)
- checkElevatorBug = true;
- }
-
- code += noScripts * 4;
-
- // Code should now be pointing at an identifier and a checksum
- byte *checksumBlock = code;
-
- code += 4 * 3;
-
- if (READ_LE_UINT32(checksumBlock) != 12345678) {
- error("Invalid script in object %s", header.name);
- return 0;
- }
-
- int32 codeLen = READ_LE_UINT32(checksumBlock + 4);
- int32 checksum = 0;
-
- for (int i = 0; i < codeLen; i++)
- checksum += (unsigned char) code[i];
-
- if (checksum != (int32)READ_LE_UINT32(checksumBlock + 8)) {
- debug(1, "Checksum error in object %s", header.name);
- // This could be bad, but there has been a report about someone
- // who had problems running the German version because of
- // checksum errors. Could there be a version where checksums
- // weren't properly calculated?
- }
-
- bool runningScript = true;
-
- int parameterReturnedFromMcodeFunction = 0; // Allow scripts to return things
- int savedStartOfMcode = 0; // For saving start of mcode commands
-
- while (runningScript) {
- int i;
- int32 a, b;
- int curCommand, parameter, value; // Command and parameter variables
- int retVal;
- int caseCount;
- bool foundCase;
- byte *ptr;
-
- curCommand = code[ip++];
-
- switch (curCommand) {
-
- // Script-related opcodes
-
- case CP_END_SCRIPT:
- // End the script
- runningScript = false;
-
- // WORKAROUND: The dreaded pyramid bug makes the torch
- // untakeable when you speak to Titipoco. This is
- // because one of the conditions for the torch to be
- // takeable is that Titipoco isn't doing anything out
- // of the ordinary. Global variable 913 has to be 0 to
- // signify that he is in his "idle" state.
- //
- // Unfortunately, simply the act of speaking to him
- // sets variable 913 to 1 (probably to stop him from
- // turning around every now and then). The script may
- // then go on to set the variable to different values
- // to trigger various behaviours in him, but if you
- // have run out of these cases the script won't ever
- // set it back to 0 again.
- //
- // So if his click hander finishes, and variable 913 is
- // 1, we set it back to 0 manually.
-
- if (checkPyramidBug && readVar(913) == 1) {
- warning("Working around pyramid bug: Resetting Titipoco's state");
- writeVar(913, 0);
- }
-
- // WORKAROUND: The not-so-known-but-should-be-dreaded
- // elevator bug.
- //
- // The click handler for the top of the elevator only
- // handles using the elevator, not examining it. When
- // examining it, the mouse cursor is removed but never
- // restored.
-
- if (checkElevatorBug && readVar(RIGHT_BUTTON)) {
- warning("Working around elevator bug: Restoring mouse pointer");
- fnAddHuman(NULL);
- }
-
- debug(9, "CP_END_SCRIPT");
- break;
- case CP_QUIT:
- // Quit out for a cycle
- WRITE_LE_UINT32(offsetPtr, ip);
- debug(9, "CP_QUIT");
- return 0;
- case CP_TERMINATE:
- // Quit out immediately without affecting the offset
- // pointer
- debug(9, "CP_TERMINATE");
- return 3;
- case CP_RESTART_SCRIPT:
- // Start the script again
- ip = FROM_LE_32(offsetTable[scriptNumber]);
- debug(9, "CP_RESTART_SCRIPT");
- break;
-
- // Stack-related opcodes
-
- case CP_PUSH_INT32:
- // Push a long word value on to the stack
- Read32ip(parameter);
- push(parameter);
- debug(9, "CP_PUSH_INT32: %d", parameter);
- break;
- case CP_PUSH_LOCAL_VAR32:
- // Push the contents of a local variable
- Read16ip(parameter);
- push(READ_LE_UINT32(localVars + parameter));
- debug(9, "CP_PUSH_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, READ_LE_UINT32(localVars + parameter));
- break;
- case CP_PUSH_GLOBAL_VAR32:
- // Push a global variable
- Read16ip(parameter);
- push(readVar(parameter));
- debug(9, "CP_PUSH_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, readVar(parameter));
- break;
- case CP_PUSH_LOCAL_ADDR:
- // Push the address of a local variable
-
- // From what I understand, some scripts store data
- // (e.g. mouse pointers) in their local variable space
- // from the very beginning, and use this mechanism to
- // pass that data to the opcode function. I don't yet
- // know the conceptual difference between this and the
- // CP_PUSH_DEREFERENCED_STRUCTURE opcode.
-
- Read16ip(parameter);
- push_ptr(localVars + parameter);
- debug(9, "CP_PUSH_LOCAL_ADDR: &localVars[%d] => %p", parameter / 4, localVars + parameter);
- break;
- case CP_PUSH_STRING:
- // Push the address of a string on to the stack
- // Get the string size
- Read8ip(parameter);
-
- // ip now points to the string
- ptr = code + ip;
- push_ptr(ptr);
- debug(9, "CP_PUSH_STRING: \"%s\"", ptr);
- ip += (parameter + 1);
- break;
- case CP_PUSH_DEREFERENCED_STRUCTURE:
- // Push the address of a dereferenced structure
- Read32ip(parameter);
- ptr = objectData + 4 + ResHeader::size() + ObjectHub::size() + parameter;
- push_ptr(ptr);
- debug(9, "CP_PUSH_DEREFERENCED_STRUCTURE: %d => %p", parameter, ptr);
- break;
- case CP_POP_LOCAL_VAR32:
- // Pop a value into a local word variable
- Read16ip(parameter);
- value = pop();
- WRITE_LE_UINT32(localVars + parameter, value);
- debug(9, "CP_POP_LOCAL_VAR32: localVars[%d] = %d", parameter / 4, value);
- break;
- case CP_POP_GLOBAL_VAR32:
- // Pop a global variable
- Read16ip(parameter);
- value = pop();
-
- // WORKAROUND for bug #1214168: The not-at-all dreaded
- // mop bug.
- //
- // At the London Docks, global variable 1003 keeps
- // track of Nico:
- //
- // 0: Hiding behind the first crate.
- // 1: Hiding behind the second crate.
- // 2: Standing in plain view on the deck.
- // 3: Hiding on the roof.
- //
- // The bug happens when trying to pick up the mop while
- // hiding on the roof. Nico climbs down, the mop is
- // picked up, but the variable remains set to 3.
- // Visually, everything looks ok. But as far as the
- // scripts are concerned, she's still hiding up on the
- // roof. This is not fatal, but leads to a number of
- // glitches until the state is corrected. E.g. trying
- // to climb back up the ladder will cause Nico to climb
- // down again.
- //
- // Global variable 1017 keeps track of the mop. Setting
- // it to 2 means that the mop has been picked up. We
- // use that as the signal that Nico's state needs to be
- // updated as well.
-
- if (checkMopBug && parameter == 1017 && readVar(1003) != 2) {
- warning("Working around mop bug: Setting Nico's state");
- writeVar(1003, 2);
- }
-
- writeVar(parameter, value);
- debug(9, "CP_POP_GLOBAL_VAR32: scriptsVars[%d] = %d", parameter, value);
- break;
- case CP_ADDNPOP_LOCAL_VAR32:
- Read16ip(parameter);
- value = READ_LE_UINT32(localVars + parameter) + pop();
- WRITE_LE_UINT32(localVars + parameter, value);
- debug(9, "CP_ADDNPOP_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, value);
- break;
- case CP_SUBNPOP_LOCAL_VAR32:
- Read16ip(parameter);
- value = READ_LE_UINT32(localVars + parameter) - pop();
- WRITE_LE_UINT32(localVars + parameter, value);
- debug(9, "CP_SUBNPOP_LOCAL_VAR32: localVars[%d] => %d", parameter / 4, value);
- break;
- case CP_ADDNPOP_GLOBAL_VAR32:
- // Add and pop a global variable
- Read16ip(parameter);
- value = readVar(parameter) + pop();
- writeVar(parameter, value);
- debug(9, "CP_ADDNPOP_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, value);
- break;
- case CP_SUBNPOP_GLOBAL_VAR32:
- // Sub and pop a global variable
- Read16ip(parameter);
- value = readVar(parameter) - pop();
- writeVar(parameter, value);
- debug(9, "CP_SUBNPOP_GLOBAL_VAR32: scriptVars[%d] => %d", parameter, value);
- break;
-
- // Jump opcodes
-
- case CP_SKIPONTRUE:
- // Skip if the value on the stack is true
- Read32ipLeaveip(parameter);
- value = pop();
- if (!value) {
- ip += 4;
- debug(9, "CP_SKIPONTRUE: %d (IS FALSE (NOT SKIPPED))", parameter);
- } else {
- ip += parameter;
- debug(9, "CP_SKIPONTRUE: %d (IS TRUE (SKIPPED))", parameter);
- }
- break;
- case CP_SKIPONFALSE:
- // Skip if the value on the stack is false
- Read32ipLeaveip(parameter);
- value = pop();
- if (value) {
- ip += 4;
- debug(9, "CP_SKIPONFALSE: %d (IS TRUE (NOT SKIPPED))", parameter);
- } else {
- ip += parameter;
- debug(9, "CP_SKIPONFALSE: %d (IS FALSE (SKIPPED))", parameter);
- }
- break;
- case CP_SKIPALWAYS:
- // skip a block
- Read32ipLeaveip(parameter);
- ip += parameter;
- debug(9, "CP_SKIPALWAYS: %d", parameter);
- break;
- case CP_SWITCH:
- // switch
- value = pop();
- Read32ip(caseCount);
-
- // Search the cases
- foundCase = false;
- for (i = 0; i < caseCount && !foundCase; i++) {
- if (value == (int32)READ_LE_UINT32(code + ip)) {
- // We have found the case, so lets
- // jump to it
- foundCase = true;
- ip += READ_LE_UINT32(code + ip + 4);
- } else
- ip += 4 * 2;
- }
-
- // If we found no matching case then use the default
-
- if (!foundCase)
- ip += READ_LE_UINT32(code + ip);
-
- debug(9, "CP_SWITCH: [SORRY, NO DEBUG INFO]");
- break;
- case CP_SAVE_MCODE_START:
- // Save the start position on an mcode instruction in
- // case we need to restart it again
- savedStartOfMcode = ip - 1;
- debug(9, "CP_SAVE_MCODE_START");
- break;
- case CP_CALL_MCODE:
- // Call an mcode routine
- Read16ip(parameter);
- assert(parameter < ARRAYSIZE(opcodes));
- // amount to adjust stack by (no of parameters)
- Read8ip(value);
- debug(9, "CP_CALL_MCODE: '%s', %d", opcodes[parameter].desc, value);
- stackPtr -= value;
- assert(stackPtr >= 0);
- retVal = (this->*opcodes[parameter].proc)(&stack[stackPtr]);
-
- switch (retVal & 7) {
- case IR_STOP:
- // Quit out for a cycle
- WRITE_LE_UINT32(offsetPtr, ip);
- return 0;
- case IR_CONT:
- // Continue as normal
- break;
- case IR_TERMINATE:
- // Return without updating the offset
- return 2;
- case IR_REPEAT:
- // Return setting offset to start of this
- // function call
- WRITE_LE_UINT32(offsetPtr, savedStartOfMcode);
- return 0;
- case IR_GOSUB:
- // that's really neat
- WRITE_LE_UINT32(offsetPtr, ip);
- return 2;
- default:
- error("Bad return code (%d) from '%s'", retVal & 7, opcodes[parameter].desc);
- }
- parameterReturnedFromMcodeFunction = retVal >> 3;
- break;
- case CP_JUMP_ON_RETURNED:
- // Jump to a part of the script depending on
- // the return value from an mcode routine
-
- // Get the maximum value
- Read8ip(parameter);
- debug(9, "CP_JUMP_ON_RETURNED: %d => %d",
- parameterReturnedFromMcodeFunction,
- READ_LE_UINT32(code + ip + parameterReturnedFromMcodeFunction * 4));
- ip += READ_LE_UINT32(code + ip + parameterReturnedFromMcodeFunction * 4);
- break;
-
- // Operators
-
- case OP_ISEQUAL:
- b = pop();
- a = pop();
- push(a == b);
- debug(9, "OP_ISEQUAL: RESULT = %d", a == b);
- break;
- case OP_NOTEQUAL:
- b = pop();
- a = pop();
- push(a != b);
- debug(9, "OP_NOTEQUAL: RESULT = %d", a != b);
- break;
- case OP_GTTHAN:
- b = pop();
- a = pop();
- push(a > b);
- debug(9, "OP_GTTHAN: RESULT = %d", a > b);
- break;
- case OP_LSTHAN:
- b = pop();
- a = pop();
- push(a < b);
- debug(9, "OP_LSTHAN: RESULT = %d", a < b);
- break;
- case OP_GTTHANE:
- b = pop();
- a = pop();
- push(a >= b);
- debug(9, "OP_GTTHANE: RESULT = %d", a >= b);
- break;
- case OP_LSTHANE:
- b = pop();
- a = pop();
- push(a <= b);
- debug(9, "OP_LSTHANE: RESULT = %d", a <= b);
- break;
- case OP_PLUS:
- b = pop();
- a = pop();
- push(a + b);
- debug(9, "OP_PLUS: RESULT = %d", a + b);
- break;
- case OP_MINUS:
- b = pop();
- a = pop();
- push(a - b);
- debug(9, "OP_MINUS: RESULT = %d", a - b);
- break;
- case OP_TIMES:
- b = pop();
- a = pop();
- push(a * b);
- debug(9, "OP_TIMES: RESULT = %d", a * b);
- break;
- case OP_DIVIDE:
- b = pop();
- a = pop();
- push(a / b);
- debug(9, "OP_DIVIDE: RESULT = %d", a / b);
- break;
- case OP_ANDAND:
- b = pop();
- a = pop();
- push(a && b);
- debug(9, "OP_ANDAND: RESULT = %d", a && b);
- break;
- case OP_OROR:
- b = pop();
- a = pop();
- push(a || b);
- debug(9, "OP_OROR: RESULT = %d", a || b);
- break;
-
- // Debugging opcodes, I think
-
- case CP_DEBUGON:
- debug(9, "CP_DEBUGON");
- break;
- case CP_DEBUGOFF:
- debug(9, "CP_DEBUGOFF");
- break;
- case CP_TEMP_TEXT_PROCESS:
- Read32ip(parameter);
- debug(9, "CP_TEMP_TEXT_PROCESS: %d", parameter);
- break;
- default:
- error("Invalid script command %d", curCommand);
- return 3;
- }
- }
-
- return 1;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/interpreter.h b/sword2/interpreter.h
deleted file mode 100644
index 365f818a98..0000000000
--- a/sword2/interpreter.h
+++ /dev/null
@@ -1,96 +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 _INTERPRETER
-#define _INTERPRETER
-
-namespace Sword2 {
-
-// Interpreter return codes
-
-enum {
- IR_STOP = 0, // Quit for a cycle
- IR_CONT = 1, // Continue as normal
- IR_TERMINATE = 2, // Return without updating the offset
- IR_REPEAT = 3, // Return; offset at start of function call
- IR_GOSUB = 4 // Return with updated offset
-};
-
-// Get parameter fix so that the playstation version can handle words not on
-// word boundaries
-
-#define Read8ip(var) { var = code[ip]; ip++; }
-#define Read16ip(var) { var = (int16)READ_LE_UINT16(code + ip); ip += 2; }
-#define Read32ip(var) { var = (int32)READ_LE_UINT32(code + ip); ip += 4; }
-#define Read32ipLeaveip(var) { var = (int32)READ_LE_UINT32(code + ip); }
-
-enum {
- // Compiled tokens
-
- CP_END_SCRIPT = 0,
- CP_PUSH_LOCAL_VAR32 = 1, // Push a local variable on to the stack
- CP_PUSH_GLOBAL_VAR32 = 2, // Push a global variable
- CP_POP_LOCAL_VAR32 = 3, // Pop a local variable from the stack
- CP_CALL_MCODE = 4, // Call a machine code function
- CP_PUSH_LOCAL_ADDR = 5, // Push the address of a local variable
- CP_PUSH_INT32 = 6, // Adjust the stack after calling an fn function
- CP_SKIPONFALSE = 7, // Skip if the bottom value on the stack is false
- CP_SKIPALWAYS = 8, // Skip a block of code
- CP_SWITCH = 9, // Switch on last stack value
- CP_ADDNPOP_LOCAL_VAR32 = 10, // Add to a local varible
- CP_SUBNPOP_LOCAL_VAR32 = 11, // Subtract from a local variable
- CP_SKIPONTRUE = 12, // Skip if the bottom value on the stack is true
- CP_POP_GLOBAL_VAR32 = 13, // Pop a global variable
- CP_ADDNPOP_GLOBAL_VAR32 = 14, // Add to a global variable
- CP_SUBNPOP_GLOBAL_VAR32 = 15, // Subtract from a global variable
- CP_DEBUGON = 16, // Turn debugging on
- CP_DEBUGOFF = 17, // Turn debugging off
- CP_QUIT = 18, // Quit for a cycle
- CP_TERMINATE = 19, // Quit script completely
-
- // Operators
-
- OP_ISEQUAL = 20, // '=='
- OP_PLUS = 21, // '+'
- OP_MINUS = 22, // '-'
- OP_TIMES = 23, // '*'
- OP_DIVIDE = 24, // '/'
- OP_NOTEQUAL = 25, // '=='
- OP_ANDAND = 26, // '&&'
- OP_GTTHAN = 27, // '>'
- OP_LSTHAN = 28, // '<'
-
- // More tokens, mixed types
-
- CP_JUMP_ON_RETURNED = 29, // Use table of jumps with value returned from fn_mcode
- CP_TEMP_TEXT_PROCESS = 30, // A dummy text process command for me
- CP_SAVE_MCODE_START = 31, // Save the mcode code start for restarting when necessary
- CP_RESTART_SCRIPT = 32, // Start the script from the beginning
- CP_PUSH_STRING = 33, // Push a pointer to a string on the stack
- CP_PUSH_DEREFERENCED_STRUCTURE = 34, // Push the address of a structure thing
- OP_GTTHANE = 35, // >=
- OP_LSTHANE = 36, // <=
- OP_OROR = 37 // || or OR
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/layers.cpp b/sword2/layers.cpp
deleted file mode 100644
index 0b59b5a9b1..0000000000
--- a/sword2/layers.cpp
+++ /dev/null
@@ -1,191 +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$
- */
-
-// high level layer initialising
-
-// the system supports:
-// 1 optional background parallax layer
-// 1 not optional normal backdrop layer
-// 3 normal sorted layers
-// up to 2 foreground parallax layers
-
-#include "common/stdafx.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 {
-
-/**
- * This function is called when entering a new room.
- * @param res resource id of the normal background layer
- * @param new_palette 1 for new palette, otherwise 0
- */
-
-void Screen::initBackground(int32 res, int32 new_palette) {
- byte buf[NAME_LEN];
- int i;
-
- assert(res);
-
- _vm->_sound->clearFxQueue();
- waitForFade();
-
- debug(1, "CHANGED TO LOCATION \"%s\"", _vm->_resman->fetchName(res, buf));
-
- // if last screen was using a shading mask (see below)
- if (_thisScreen.mask_flag) {
- if (closeLightMask() != RD_OK)
- error("Could not close light mask");
- }
-
- // Close the previous screen, if one is open
- if (_thisScreen.background_layer_id)
- closeBackgroundLayer();
-
- _thisScreen.background_layer_id = res;
- _thisScreen.new_palette = new_palette;
-
- // ok, now read the resource and pull out all the normal sort layer
- // info/and set them up at the beginning of the sort list - why do it
- // each cycle
-
- byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
- ScreenHeader screen_head;
-
- screen_head.read(_vm->fetchScreenHeader(file));
-
- // set number of special sort layers
- _thisScreen.number_of_layers = screen_head.noLayers;
- _thisScreen.screen_wide = screen_head.width;
- _thisScreen.screen_deep = screen_head.height;
-
- debug(2, "layers=%d width=%d depth=%d", screen_head.noLayers, screen_head.width, screen_head.height);
-
- // initialise the driver back buffer
- setLocationMetrics(screen_head.width, screen_head.height);
-
- for (i = 0; i < screen_head.noLayers; i++) {
- debug(3, "init layer %d", i);
-
- LayerHeader layer;
-
- layer.read(_vm->fetchLayerHeader(file, i));
-
- // Add the layer to the sort list. We only provide just enough
- // information so that it's clear that it's a layer, and where
- // to sort it in relation to other things in the list.
-
- _sortList[i].layer_number = i + 1;
- _sortList[i].sort_y = layer.y + layer.height;
- }
-
- // reset scroll offsets
- _thisScreen.scroll_offset_x = 0;
- _thisScreen.scroll_offset_y = 0;
-
- if (screen_head.width > _screenWide || screen_head.height > _screenDeep) {
- // The layer is larger than the physical screen. Switch on
- // scrolling. (2 means first time on screen)
- _thisScreen.scroll_flag = 2;
-
- // Note: if we've already set the player up then we could do
- // the initial scroll set here
-
- // Calculate the maximum scroll offsets to prevent scrolling
- // off the edge. The minimum offsets are both 0.
-
- _thisScreen.max_scroll_offset_x = screen_head.width - _screenWide;
- _thisScreen.max_scroll_offset_y = screen_head.height - (_screenDeep - (MENUDEEP * 2));
- } else {
- // The later fits on the phyiscal screen. Switch off scrolling.
- _thisScreen.scroll_flag = 0;
- }
-
- resetRenderEngine();
-
- // These are the physical screen coords where the system will try to
- // maintain George's actual feet coords.
-
- _thisScreen.feet_x = 320;
- _thisScreen.feet_y = 340;
-
- // shading mask
-
- MultiScreenHeader screenLayerTable;
-
- screenLayerTable.read(file + ResHeader::size());
-
- if (screenLayerTable.maskOffset) {
- SpriteInfo spriteInfo;
-
- spriteInfo.x = 0;
- spriteInfo.y = 0;
- spriteInfo.w = screen_head.width;
- spriteInfo.h = screen_head.height;
- spriteInfo.scale = 0;
- spriteInfo.scaledWidth = 0;
- spriteInfo.scaledHeight = 0;
- spriteInfo.type = 0;
- spriteInfo.blend = 0;
- spriteInfo.data = _vm->fetchShadingMask(file);
- spriteInfo.colourTable = 0;
-
- if (openLightMask(&spriteInfo) != RD_OK)
- error("Could not open light mask");
-
- // so we know to close it later! (see above)
- _thisScreen.mask_flag = true;
- } else {
- // no need to close a mask later
- _thisScreen.mask_flag = false;
- }
-
- // Background parallax layers
-
- for (i = 0; i < 2; i++) {
- if (screenLayerTable.bg_parallax[i])
- initialiseBackgroundLayer(_vm->fetchBackgroundParallaxLayer(file, i));
- else
- initialiseBackgroundLayer(NULL);
- }
-
- // Normal backround layer
-
- initialiseBackgroundLayer(_vm->fetchBackgroundLayer(file));
-
- // Foreground parallax layers
-
- for (i = 0; i < 2; i++) {
- if (screenLayerTable.fg_parallax[i])
- initialiseBackgroundLayer(_vm->fetchForegroundParallaxLayer(file, i));
- else
- initialiseBackgroundLayer(NULL);
- }
-
- _vm->_resman->closeResource(_thisScreen.background_layer_id);
-}
-
-} // End of namespace Sword2
diff --git a/sword2/layers.h b/sword2/layers.h
deleted file mode 100644
index 88aff933b3..0000000000
--- a/sword2/layers.h
+++ /dev/null
@@ -1,29 +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 _LAYERS
-#define _LAYERS
-
-namespace Sword2 {
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/logic.cpp b/sword2/logic.cpp
deleted file mode 100644
index c26d5615b9..0000000000
--- a/sword2/logic.cpp
+++ /dev/null
@@ -1,267 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-#include "sword2/sound.h"
-
-namespace Sword2 {
-
-Logic::Logic(Sword2Engine *vm) :
- _vm(vm), _kills(0), _currentRunList(0), _smackerLeadIn(0),
- _smackerLeadOut(0), _sequenceTextLines(0), _speechTime(0), _animId(0),
- _speechAnimType(0), _leftClickDelay(0), _rightClickDelay(0),
- _officialTextNumber(0), _speechTextBlocNo(0) {
-
- _scriptVars = NULL;
- memset(_eventList, 0, sizeof(_eventList));
- memset(_syncList, 0, sizeof(_syncList));
- _router = new Router(_vm);
-}
-
-Logic::~Logic() {
- delete _router;
-}
-
-/**
- * Do one cycle of the current session.
- */
-
-int Logic::processSession() {
- // might change during the session, so take a copy here
- uint32 run_list = _currentRunList;
-
- _pc = 0; // first object in list
-
- // by minusing the pc we can cause an immediate cessation of logic
- // processing on the current list
-
- while (_pc != 0xffffffff) {
- byte *game_object_list, *head, *raw_script_ad, *raw_data_ad;
- uint32 level, ret, script, id;
-
- game_object_list = _vm->_resman->openResource(run_list) + ResHeader::size();
-
- assert(_vm->_resman->fetchType(run_list) == RUN_LIST);
-
- // read the next id
- id = READ_LE_UINT32(game_object_list + 4 * _pc);
- _pc++;
-
- writeVar(ID, id);
-
- _vm->_resman->closeResource(run_list);
-
- if (!id) {
- // End of list - end the session naturally
- return 0;
- }
-
- assert(_vm->_resman->fetchType(id) == GAME_OBJECT);
-
- head = _vm->_resman->openResource(id);
- _curObjectHub.setAddress(head + ResHeader::size());
-
- level = _curObjectHub.getLogicLevel();
-
- debug(5, "Level %d id(%d) pc(%d)",
- level,
- _curObjectHub.getScriptId(level),
- _curObjectHub.getScriptPc(level));
-
- // Do the logic for this object. We keep going until a function
- // says to stop - remember, system operations are run via
- // function calls to drivers now.
-
- do {
- // There is a distinction between running one of our
- // own scripts and that of another object.
-
- level = _curObjectHub.getLogicLevel();
- script = _curObjectHub.getScriptId(level);
-
- if (script / SIZE == readVar(ID)) {
- // It's our own script
-
- debug(5, "Run script %d pc=%d",
- script / SIZE,
- _curObjectHub.getScriptPc(level));
-
- // This is the script data. Script and data
- // object are the same.
-
- raw_script_ad = head;
-
- ret = runScript2(raw_script_ad, raw_script_ad, _curObjectHub.getScriptPcPtr(level));
- } else {
- // We're running the script of another game
- // object - get our data object address.
-
- uint8 type = _vm->_resman->fetchType(script / SIZE);
-
- assert(type == GAME_OBJECT || type == SCREEN_MANAGER);
-
- raw_script_ad = _vm->_resman->openResource(script / SIZE);
- raw_data_ad = head;
-
- ret = runScript2(raw_script_ad, raw_data_ad, _curObjectHub.getScriptPcPtr(level));
-
- _vm->_resman->closeResource(script / SIZE);
-
- // reset to us for service script
- raw_script_ad = raw_data_ad;
- }
-
- if (ret == 1) {
- level = _curObjectHub.getLogicLevel();
-
- // The script finished - drop down a level
- if (level) {
- _curObjectHub.setLogicLevel(level - 1);
- } else {
- // Hmmm, level 0 terminated :-| Let's
- // be different this time and simply
- // let it restart next go :-)
-
- // Note that this really does happen a
- // lot, so don't make it a warning.
-
- debug(5, "object %d script 0 terminated!", id);
-
- // reset to rerun, drop out for a cycle
- _curObjectHub.setScriptPc(level, _curObjectHub.getScriptId(level) & 0xffff);
- ret = 0;
- }
- } else if (ret > 2) {
- error("processSession: illegal script return type %d", ret);
- }
-
- // if ret == 2 then we simply go around again - a new
- // script or subroutine will kick in and run
-
- // keep processing scripts until 0 for quit is returned
- } while (ret);
-
- // Any post logic system requests to go here
-
- // Clear any syncs that were waiting for this character - it
- // has used them or now looses them
-
- clearSyncs(readVar(ID));
-
- if (_pc != 0xffffffff) {
- // The session is still valid so run the graphics/mouse
- // service script
- runScript(raw_script_ad, raw_script_ad, 0);
- }
-
- // and that's it so close the object resource
-
- _vm->_resman->closeResource(readVar(ID));
- }
-
- // Leaving a room so remove all ids that must reboot correctly. Then
- // restart the loop.
-
- for (uint32 i = 0; i < _kills; i++)
- _vm->_resman->remove(_objectKillList[i]);
-
- resetKillList();
- return 1;
-}
-
-/**
- * Bring an immediate halt to the session and cause a new one to start without
- * a screen update.
- */
-
-void Logic::expressChangeSession(uint32 sesh_id) {
- // Set new session and force the old one to quit.
- _currentRunList = sesh_id;
- _pc = 0xffffffff;
-
- // Reset now in case we double-clicked an exit prior to changing screen
- writeVar(EXIT_FADING, 0);
-
- // We're trashing the list - presumably to change room. In theory,
- // sync waiting in the list could be left behind and never removed -
- // so we trash the lot
- memset(_syncList, 0, sizeof(_syncList));
-
- // Various clean-ups
- _router->clearWalkGridList();
- _vm->_sound->clearFxQueue();
- _router->freeAllRouteMem();
-}
-
-/**
- * @return The private _currentRunList variable.
- */
-
-uint32 Logic::getRunList() {
- return _currentRunList;
-}
-
-/**
- * Move the current object up a level. Called by fnGosub command. Remember:
- * only the logic object has access to _curObjectHub.
- */
-
-void Logic::logicUp(uint32 new_script) {
- debug(5, "new pc = %d", new_script & 0xffff);
-
- // going up a level - and we'll keep going this cycle
- _curObjectHub.setLogicLevel(_curObjectHub.getLogicLevel() + 1);
-
- assert(_curObjectHub.getLogicLevel() < 3); // Can be 0, 1, 2
- logicReplace(new_script);
-}
-
-/**
- * Force the level to one.
- */
-
-void Logic::logicOne(uint32 new_script) {
- _curObjectHub.setLogicLevel(1);
- logicReplace(new_script);
-}
-
-/**
- * Change current logic. Script must quit with a TERMINATE directive, which
- * does not write to &pc
- */
-
-void Logic::logicReplace(uint32 new_script) {
- uint32 level = _curObjectHub.getLogicLevel();
-
- _curObjectHub.setScriptId(level, new_script);
- _curObjectHub.setScriptPc(level, new_script & 0xffff);
-}
-
-void Logic::resetKillList() {
- _kills = 0;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/logic.h b/sword2/logic.h
deleted file mode 100644
index 9e264f603c..0000000000
--- a/sword2/logic.h
+++ /dev/null
@@ -1,316 +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$
- */
-
-// logic management
-
-#ifndef _LOGIC
-#define _LOGIC
-
-#include "sword2/memory.h"
-
-namespace Sword2 {
-
-struct MovieTextObject;
-
-#define MAX_events 10
-
-#define TREE_SIZE 3
-
-// This must allow for the largest number of objects in a screen
-#define OBJECT_KILL_LIST_SIZE 50
-
-#define MAX_SEQUENCE_TEXT_LINES 15
-
-class Sword2Engine;
-class Router;
-
-struct EventUnit {
- uint32 id;
- uint32 interact_id;
-};
-
-class Logic {
-private:
- Sword2Engine *_vm;
-
- inline byte *decodePtr(int32 n) {
- return _vm->_memory->decodePtr(n);
- }
-
- uint32 _objectKillList[OBJECT_KILL_LIST_SIZE];
-
- // keeps note of no. of objects in the kill list
- uint32 _kills;
-
- // denotes the res id of the game-object-list in current use
- uint32 _currentRunList;
-
- //pc during logic loop
- uint32 _pc;
-
- // each object has one of these tacked onto the beginning
- ObjectHub _curObjectHub;
-
- EventUnit _eventList[MAX_events];
-
- // Resource id of the wav to use as lead-in/lead-out from smacker
- uint32 _smackerLeadIn;
- uint32 _smackerLeadOut;
-
- // keeps count of number of text lines to disaply during the sequence
- uint32 _sequenceTextLines;
-
- // FOR TEXT LINES IN SEQUENCE PLAYER
-
- struct SequenceTextInfo {
- uint32 textNumber;
- uint16 startFrame;
- uint16 endFrame;
- byte *text_mem;
- uint32 speechBufferSize;
- uint16 *speech_mem;
- };
-
- SequenceTextInfo _sequenceTextList[MAX_SEQUENCE_TEXT_LINES];
-
- void createSequenceSpeech(MovieTextObject *sequenceText[]);
- void clearSequenceSpeech(MovieTextObject *sequenceText[]);
-
- // when not playing a wav we calculate the speech time based upon
- // length of ascii
-
- uint32 _speechTime;
-
- uint32 _animId;
-
- // 0 lip synced and repeating - 1 normal once through
- uint32 _speechAnimType;
-
- uint32 _leftClickDelay; // click-delay for LEFT mouse button
- uint32 _rightClickDelay; // click-delay for RIGHT mouse button
-
- // calculated by locateTalker() for use in speech-panning & text-sprite
- // positioning
-
- int16 _textX, _textY;
-
- void locateTalker(int32 *params);
- void formText(int32 *params);
- bool wantSpeechForLine(uint32 wavId);
-
- // Set by fnPassMega()
- byte _engineMega[56];
-
-public:
- Logic(Sword2Engine *vm);
- ~Logic();
-
- EventUnit *getEventList() { return _eventList; }
- byte *getEngineMega() { return _engineMega; }
-
- byte _saveLogic[8];
- byte _saveGraphic[12];
- byte _saveMega[56];
-
- // Point to the global variable data
- byte *_scriptVars;
-
- // "TEXT" - current official text line number - will match the wav
- // filenames
-
- int16 _officialTextNumber;
-
- // so speech text cleared when running a new start-script
- uint32 _speechTextBlocNo;
-
- uint32 readVar(int n) {
- return READ_LE_UINT32(_scriptVars + 4 * n);
- }
-
- void writeVar(int n, uint32 value) {
- WRITE_LE_UINT32(_scriptVars + 4 * n, value);
- }
-
- int runResScript(uint32 scriptRes, uint32 offset);
- int runResObjScript(uint32 scriptRes, uint32 objRes, uint32 offset);
- int runScript(byte *scriptData, byte *objectData, uint32 offset);
- int runScript2(byte *scriptData, byte *objectData, byte *offset);
-
- void sendEvent(uint32 id, uint32 interact_id);
- void setPlayerActionEvent(uint32 id, uint32 interact_id);
- void startEvent();
- int checkEventWaiting();
- void clearEvent(uint32 id);
- void killAllIdsEvents(uint32 id);
-
- uint32 countEvents();
-
- struct SyncUnit {
- uint32 id;
- uint32 sync;
- };
-
- // There won't be many, will there? Probably 2 at most i reckon
- SyncUnit _syncList[10];
-
- void clearSyncs(uint32 id);
- void sendSync(uint32 id, uint32 sync);
- int getSync();
-
- Router *_router;
-
- int32 fnTestFunction(int32 *params);
- int32 fnTestFlags(int32 *params);
- int32 fnRegisterStartPoint(int32 *params);
- int32 fnInitBackground(int32 *params);
- int32 fnSetSession(int32 *params);
- int32 fnBackSprite(int32 *params);
- int32 fnSortSprite(int32 *params);
- int32 fnForeSprite(int32 *params);
- int32 fnRegisterMouse(int32 *params);
- int32 fnAnim(int32 *params);
- int32 fnRandom(int32 *params);
- int32 fnPreLoad(int32 *params);
- int32 fnAddSubject(int32 *params);
- int32 fnInteract(int32 *params);
- int32 fnChoose(int32 *params);
- int32 fnWalk(int32 *params);
- int32 fnWalkToAnim(int32 *params);
- int32 fnTurn(int32 *params);
- int32 fnStandAt(int32 *params);
- int32 fnStand(int32 *params);
- int32 fnStandAfterAnim(int32 *params);
- int32 fnPause(int32 *params);
- int32 fnMegaTableAnim(int32 *params);
- int32 fnAddMenuObject(int32 *params);
- int32 fnStartConversation(int32 *params);
- int32 fnEndConversation(int32 *params);
- int32 fnSetFrame(int32 *params);
- int32 fnRandomPause(int32 *params);
- int32 fnRegisterFrame(int32 *params);
- int32 fnNoSprite(int32 *params);
- int32 fnSendSync(int32 *params);
- int32 fnUpdatePlayerStats(int32 *params);
- int32 fnPassGraph(int32 *params);
- int32 fnInitFloorMouse(int32 *params);
- int32 fnPassMega(int32 *params);
- int32 fnFaceXY(int32 *params);
- int32 fnEndSession(int32 *params);
- int32 fnNoHuman(int32 *params);
- int32 fnAddHuman(int32 *params);
- int32 fnWeWait(int32 *params);
- int32 fnTheyDoWeWait(int32 *params);
- int32 fnTheyDo(int32 *params);
- int32 fnWalkToTalkToMega(int32 *params);
- int32 fnFadeDown(int32 *params);
- int32 fnISpeak(int32 *params);
- int32 fnTotalRestart(int32 *params);
- int32 fnSetWalkGrid(int32 *params);
- int32 fnSpeechProcess(int32 *params);
- int32 fnSetScaling(int32 *params);
- int32 fnStartEvent(int32 *params);
- int32 fnCheckEventWaiting(int32 *params);
- int32 fnRequestSpeech(int32 *params);
- int32 fnGosub(int32 *params);
- int32 fnTimedWait(int32 *params);
- int32 fnPlayFx(int32 *params);
- int32 fnStopFx(int32 *params);
- int32 fnPlayMusic(int32 *params);
- int32 fnStopMusic(int32 *params);
- int32 fnSetValue(int32 *params);
- int32 fnNewScript(int32 *params);
- int32 fnGetSync(int32 *params);
- int32 fnWaitSync(int32 *params);
- int32 fnRegisterWalkGrid(int32 *params);
- int32 fnReverseMegaTableAnim(int32 *params);
- int32 fnReverseAnim(int32 *params);
- int32 fnAddToKillList(int32 *params);
- int32 fnSetStandbyCoords(int32 *params);
- int32 fnBackPar0Sprite(int32 *params);
- int32 fnBackPar1Sprite(int32 *params);
- int32 fnForePar0Sprite(int32 *params);
- int32 fnForePar1Sprite(int32 *params);
- int32 fnSetPlayerActionEvent(int32 *params);
- int32 fnSetScrollCoordinate(int32 *params);
- int32 fnStandAtAnim(int32 *params);
- int32 fnSetScrollLeftMouse(int32 *params);
- int32 fnSetScrollRightMouse(int32 *params);
- int32 fnColour(int32 *params);
- int32 fnFlash(int32 *params);
- int32 fnPreFetch(int32 *params);
- int32 fnGetPlayerSaveData(int32 *params);
- int32 fnPassPlayerSaveData(int32 *params);
- int32 fnSendEvent(int32 *params);
- int32 fnAddWalkGrid(int32 *params);
- int32 fnRemoveWalkGrid(int32 *params);
- int32 fnCheckForEvent(int32 *params);
- int32 fnPauseForEvent(int32 *params);
- int32 fnClearEvent(int32 *params);
- int32 fnFaceMega(int32 *params);
- int32 fnPlaySequence(int32 *params);
- int32 fnShadedSprite(int32 *params);
- int32 fnUnshadedSprite(int32 *params);
- int32 fnFadeUp(int32 *params);
- int32 fnDisplayMsg(int32 *params);
- int32 fnSetObjectHeld(int32 *params);
- int32 fnAddSequenceText(int32 *params);
- int32 fnResetGlobals(int32 *params);
- int32 fnSetPalette(int32 *params);
- int32 fnRegisterPointerText(int32 *params);
- int32 fnFetchWait(int32 *params);
- int32 fnRelease(int32 *params);
- int32 fnPrepareMusic(int32 *params);
- int32 fnSoundFetch(int32 *params);
- int32 fnSmackerLeadIn(int32 *params);
- int32 fnSmackerLeadOut(int32 *params);
- int32 fnStopAllFx(int32 *params);
- int32 fnCheckPlayerActivity(int32 *params);
- int32 fnResetPlayerActivityDelay(int32 *params);
- int32 fnCheckMusicPlaying(int32 *params);
- int32 fnPlayCredits(int32 *params);
- int32 fnSetScrollSpeedNormal(int32 *params);
- int32 fnSetScrollSpeedSlow(int32 *params);
- int32 fnRemoveChooser(int32 *params);
- int32 fnSetFxVolAndPan(int32 *params);
- int32 fnSetFxVol(int32 *params);
- int32 fnRestoreGame(int32 *params);
- int32 fnRefreshInventory(int32 *params);
- int32 fnChangeShadows(int32 *params);
-
- // do one cycle of the current session
- int processSession();
-
- // cause the logic loop to terminate and drop out
- void expressChangeSession(uint32 sesh_id);
-
- uint32 getRunList();
-
- // setup script_id and script_pc in _curObjectHub - called by fnGosub()
- void logicUp(uint32 new_script);
-
- void logicReplace(uint32 new_script);
- void logicOne(uint32 new_script);
- void resetKillList();
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/maketext.cpp b/sword2/maketext.cpp
deleted file mode 100644
index 5edaf5e41e..0000000000
--- a/sword2/maketext.cpp
+++ /dev/null
@@ -1,579 +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$
- */
-
-// MAKETEXT - Constructs a single-frame text sprite: returns a handle to a
-// FLOATING memory block containing the sprite, given a
-// null-terminated string, max width allowed, pen colour and
-// pointer to required character set.
-//
-// NB 1) The routine does not create a standard file header or
-// an anim header for the text sprite - the data simply begins
-// with the frame header.
-//
-// NB 2) If pen colour is zero, it copies the characters into
-// the sprite without remapping the colours.
-// ie. It can handle both the standard 2-colour font for speech
-// and any multicoloured fonts for control panels, etc.
-//
-// Based on textsprt.c as used for Broken Sword 1, but updated
-// for new system by JEL on 9oct96 and updated again (for font
-// as a resource) on 5dec96.
-
-#include "common/stdafx.h"
-#include "common/system.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/resman.h"
-
-namespace Sword2 {
-
-#define MAX_LINES 30 // max character lines in output sprite
-
-#define BORDER_COL 200 // source colour for character border (only
- // needed for remapping colours)
-#define LETTER_COL 193 // source colour for bulk of character ( " )
-#define SPACE ' '
-#define FIRST_CHAR SPACE // first character in character set
-#define LAST_CHAR 255 // last character in character set
-#define DUD 64 // the first "chequered flag" (dud) symbol in
- // our character set is in the '@' position
-
-/**
- * This function creates a new text sprite. The sprite data contains a
- * FrameHeader, but not a standard file header.
- *
- * @param sentence pointer to a null-terminated string
- * @param maxWidth the maximum allowed text sprite width in pixels
- * @param pen the text colour, or zero to use the source colours
- * @param fontRes the font resource id
- * @param border the border colour; black by default
- * @return a handle to a floating memory block containing the text sprite
- * @note The sentence must contain no leading, trailing or extra spaces.
- * Out-of-range characters in the string are replaced by a special
- * error-signal character (chequered flag)
- */
-
-byte *FontRenderer::makeTextSprite(byte *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes, uint8 border) {
- debug(5, "makeTextSprite(\"%s\", maxWidth=%u)", sentence, maxWidth);
-
- _borderPen = border;
-
- // Line- and character spacing are hard-wired, rather than being part
- // of the resource.
-
- if (fontRes == _vm->_speechFontId) {
- _lineSpacing = -6;
- _charSpacing = -3;
- } else if (fontRes == CONSOLE_FONT_ID) {
- _lineSpacing = 0;
- _charSpacing = 1;
- } else {
- _lineSpacing = 0;
- _charSpacing = 0;
- }
-
- // Allocate memory for array of lineInfo structures
-
- byte *line = (byte *)malloc(MAX_LINES * sizeof(LineInfo));
-
- // Get details of sentence breakdown into array of LineInfo structures
- // and get the number of lines involved
-
- uint16 noOfLines = analyseSentence(sentence, maxWidth, fontRes, (LineInfo *)line);
-
- // Construct the sprite based on the info gathered - returns floating
- // mem block
-
- byte *textSprite = buildTextSprite(sentence, fontRes, pen, (LineInfo *)line, noOfLines);
-
- free(line);
- return textSprite;
-}
-
-uint16 FontRenderer::analyseSentence(byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line) {
- // joinWidth = how much extra space is needed to append a word to a
- // line. NB. SPACE requires TWICE the '_charSpacing' to join a word
- // to line
-
- uint16 joinWidth = charWidth(SPACE, fontRes) + 2 * _charSpacing;
-
- uint16 lineNo = 0;
- uint16 pos = 0;
- bool firstWord = true;
-
- byte ch;
-
- do {
- uint16 wordWidth = 0;
- uint16 wordLength = 0;
-
- // Calculate the width of the word.
-
- ch = sentence[pos++];
-
- while (ch && ch != SPACE) {
- wordWidth += charWidth(ch, fontRes) + _charSpacing;
- wordLength++;
- ch = sentence[pos++];
- }
-
- // Don't include any character spacing at the end of the word.
- wordWidth -= _charSpacing;
-
- // 'ch' is now the SPACE or NULL following the word
- // 'pos' indexes to the position following 'ch'
-
- if (firstWord) {
- // This is the first word on the line, so no separating
- // space is needed.
-
- line[0].width = wordWidth;
- line[0].length = wordLength;
- firstWord = false;
- } else {
- // See how much extra space this word will need to
- // fit on current line (with a separating space
- // character - also overlapped)
-
- uint16 spaceNeeded = joinWidth + wordWidth;
-
- if (line[lineNo].width + spaceNeeded <= maxWidth) {
- // The word fits on this line.
- line[lineNo].width += spaceNeeded;
- line[lineNo].length += (1 + wordLength);
- } else {
- // The word spills over to the next line, i.e.
- // no separating space.
-
- lineNo++;
-
- assert(lineNo < MAX_LINES);
-
- line[lineNo].width = wordWidth;
- line[lineNo].length = wordLength;
- }
- }
- } while (ch);
-
- return lineNo + 1;
-}
-
-/**
- * This function creates a new text sprite in a movable memory block. It must
- * be locked before use, i.e. lock, draw sprite, unlock/free. The sprite data
- * contains a FrameHeader, but not a standard file header.
- *
- * @param sentence pointer to a null-terminated string
- * @param fontRes the font resource id
- * @param pen the text colour, or zero to use the source colours
- * @param line array of LineInfo structures, created by analyseSentence()
- * @param noOfLines the number of lines, i.e. the number of elements in 'line'
- * @return a handle to a floating memory block containing the text sprite
- * @note The sentence must contain no leading, trailing or extra spaces.
- * Out-of-range characters in the string are replaced by a special
- * error-signal character (chequered flag)
- */
-
-byte *FontRenderer::buildTextSprite(byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines) {
- uint16 i;
-
- // Find the width of the widest line in the output text
-
- uint16 spriteWidth = 0;
-
- for (i = 0; i < noOfLines; i++)
- if (line[i].width > spriteWidth)
- spriteWidth = line[i].width;
-
- // Find the total height of the text sprite: the total height of the
- // text lines, plus the total height of the spacing between them.
-
- uint16 char_height = charHeight(fontRes);
- uint16 spriteHeight = char_height * noOfLines + _lineSpacing * (noOfLines - 1);
-
- // Allocate memory for the text sprite
-
- uint32 sizeOfSprite = spriteWidth * spriteHeight;
- byte *textSprite = (byte *)malloc(FrameHeader::size() + sizeOfSprite);
-
- // At this stage, textSprite points to an unmovable memory block. Set
- // up the frame header.
-
- FrameHeader frame_head;
-
- frame_head.compSize = 0;
- frame_head.width = spriteWidth;
- frame_head.height = spriteHeight;
-
- frame_head.write(textSprite);
-
- debug(4, "Text sprite size: %ux%u", spriteWidth, spriteHeight);
-
- // Clear the entire sprite to make it transparent.
-
- byte *linePtr = textSprite + FrameHeader::size();
- memset(linePtr, 0, sizeOfSprite);
-
- byte *charSet = _vm->_resman->openResource(fontRes);
-
- // Build the sprite, one line at a time
-
- uint16 pos = 0;
-
- for (i = 0; i < noOfLines; i++) {
- // Center each line
- byte *spritePtr = linePtr + (spriteWidth - line[i].width) / 2;
-
- // copy the sprite for each character in this line to the
- // text sprite and inc the sprite ptr by the character's
- // width minus the 'overlap'
-
- for (uint j = 0; j < line[i].length; j++) {
- byte *charPtr = findChar(sentence[pos++], charSet);
-
- frame_head.read(charPtr);
-
- assert(frame_head.height == char_height);
- copyChar(charPtr, spritePtr, spriteWidth, pen);
- spritePtr += frame_head.width + _charSpacing;
- }
-
- // Skip space at end of last word in this line
- pos++;
-
- linePtr += (char_height + _lineSpacing) * spriteWidth;
- }
-
- _vm->_resman->closeResource(fontRes);
-
- return textSprite;
-}
-
-/**
- * @param ch the ASCII code of the character
- * @param fontRes the font resource id
- * @return the width of the character
- */
-
-uint16 FontRenderer::charWidth(byte ch, uint32 fontRes) {
- byte *charSet = _vm->_resman->openResource(fontRes);
-
- FrameHeader frame_head;
-
- frame_head.read(findChar(ch, charSet));
- _vm->_resman->closeResource(fontRes);
-
- return frame_head.width;
-}
-
-/**
- * @param fontRes the font resource id
- * @return the height of a character sprite
- * @note All characters in a font are assumed to have the same height, so
- * there is no need to specify which one to look at.
- */
-
-// Returns the height of a character sprite, given the character's ASCII code
-// and a pointer to the start of the character set.
-
-uint16 FontRenderer::charHeight(uint32 fontRes) {
- byte *charSet = _vm->_resman->openResource(fontRes);
-
- FrameHeader frame_head;
-
- frame_head.read(findChar(FIRST_CHAR, charSet));
- _vm->_resman->closeResource(fontRes);
-
- return frame_head.height;
-}
-
-/**
- * @param ch the ASCII code of the character to find
- * @param charSet pointer to the start of the character set
- * @return pointer to the requested character or, if it's out of range, the
- * 'dud' character (chequered flag)
- */
-
-byte *FontRenderer::findChar(byte ch, byte *charSet) {
- if (ch < FIRST_CHAR)
- ch = DUD;
- return _vm->fetchFrameHeader(charSet, ch - FIRST_CHAR);
-}
-
-/**
- * Copies a character sprite to the sprite buffer.
- * @param charPtr pointer to the character sprite
- * @param spritePtr pointer to the sprite buffer
- * @param spriteWidth the width of the character
- * @param pen If zero, copy the data directly. Otherwise remap the
- * sprite's colours from BORDER_COL to _borderPen and from
- * LETTER_COL to pen.
- */
-
-void FontRenderer::copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen) {
- FrameHeader frame;
-
- frame.read(charPtr);
-
- byte *source = charPtr + FrameHeader::size();
- byte *rowPtr = spritePtr;
-
- for (uint i = 0; i < frame.height; i++) {
- byte *dest = rowPtr;
-
- if (pen) {
- // Use the specified colours
- for (uint j = 0; j < frame.width; j++) {
- switch (*source++) {
- case LETTER_COL:
- *dest = pen;
- break;
- case BORDER_COL:
- // Don't do a border pixel if there's
- // already a bit of another character
- // underneath (for overlapping!)
- if (!*dest)
- *dest = _borderPen;
- break;
- default:
- // Do nothing if source pixel is zero,
- // ie. transparent
- break;
- }
- dest++;
- }
- } else {
- // Pen is zero, so just copy character sprites
- // directly into text sprite without remapping colours.
- // Apparently overlapping is never considered here?
- memcpy(dest, source, frame.width);
- source += frame.width;
- }
- rowPtr += spriteWidth;
- }
-}
-
-// Distance to keep speech text from edges of screen
-#define TEXT_MARGIN 12
-
-/**
- * Creates a text bloc in the list and returns the bloc number. The list of
- * blocs is read and blitted at render time. Choose alignment type
- * RDSPR_DISPLAYALIGN or 0
- */
-
-uint32 FontRenderer::buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification) {
- uint32 i = 0;
-
- while (i < MAX_text_blocs && _blocList[i].text_mem)
- i++;
-
- assert(i < MAX_text_blocs);
-
- // Create and position the sprite
-
- _blocList[i].text_mem = makeTextSprite(ascii, width, pen, fontRes);
-
- // 'NO_JUSTIFICATION' means print sprite with top-left at (x,y)
- // without margin checking - used for debug text
-
- if (justification != NO_JUSTIFICATION) {
- FrameHeader frame_head;
-
- frame_head.read(_blocList[i].text_mem);
-
- switch (justification) {
- case POSITION_AT_CENTRE_OF_BASE:
- // This one is always used for SPEECH TEXT; possibly
- // also for pointer text
- x -= (frame_head.width / 2);
- y -= frame_head.height;
- break;
- case POSITION_AT_CENTRE_OF_TOP:
- x -= (frame_head.width / 2);
- break;
- case POSITION_AT_LEFT_OF_TOP:
- // The given coords are already correct for this!
- break;
- case POSITION_AT_RIGHT_OF_TOP:
- x -= frame_head.width;
- break;
- case POSITION_AT_LEFT_OF_BASE:
- y -= frame_head.height;
- break;
- case POSITION_AT_RIGHT_OF_BASE:
- x -= frame_head.width;
- y -= frame_head.height;
- break;
- case POSITION_AT_LEFT_OF_CENTRE:
- y -= (frame_head.height / 2);
- break;
- case POSITION_AT_RIGHT_OF_CENTRE:
- x -= frame_head.width;
- y -= (frame_head.height) / 2;
- break;
- }
-
- // Ensure text sprite is a few pixels inside the visible screen
- // remember - it's RDSPR_DISPLAYALIGN
-
- uint16 text_left_margin = TEXT_MARGIN;
- uint16 text_right_margin = 640 - TEXT_MARGIN - frame_head.width;
- uint16 text_top_margin = TEXT_MARGIN;
- uint16 text_bottom_margin = 400 - TEXT_MARGIN - frame_head.height;
-
- // Move if too far left or too far right
-
- if (x < text_left_margin)
- x = text_left_margin;
- else if (x > text_right_margin)
- x = text_right_margin;
-
- // Move if too high or too low
-
- if (y < text_top_margin)
- y = text_top_margin;
- else if (y > text_bottom_margin)
- y = text_bottom_margin;
- }
-
- // The sprite is always uncompressed
- _blocList[i].type = type | RDSPR_NOCOMPRESSION;
-
- _blocList[i].x = x;
- _blocList[i].y = y;
-
- return i + 1;
-}
-
-/**
- * Called by buildDisplay()
- */
-
-void FontRenderer::printTextBlocs() {
- for (uint i = 0; i < MAX_text_blocs; i++) {
- if (_blocList[i].text_mem) {
- FrameHeader frame_head;
- SpriteInfo spriteInfo;
-
- frame_head.read(_blocList[i].text_mem);
-
- spriteInfo.x = _blocList[i].x;
- spriteInfo.y = _blocList[i].y;
- spriteInfo.w = frame_head.width;
- spriteInfo.h = frame_head.height;
- spriteInfo.scale = 0;
- spriteInfo.scaledWidth = 0;
- spriteInfo.scaledHeight = 0;
- spriteInfo.type = _blocList[i].type;
- spriteInfo.blend = 0;
- spriteInfo.data = _blocList[i].text_mem + FrameHeader::size();
- spriteInfo.colourTable = 0;
-
- uint32 rv = _vm->_screen->drawSprite(&spriteInfo);
- if (rv)
- error("Driver Error %.8x in printTextBlocs", rv);
- }
- }
-}
-
-void FontRenderer::killTextBloc(uint32 bloc_number) {
- bloc_number--;
- free(_blocList[bloc_number].text_mem);
- _blocList[bloc_number].text_mem = NULL;
-}
-
-// Resource 3258 contains text from location script for 152 (install, save &
-// restore text, etc)
-
-#define TEXT_RES 3258
-
-// Local line number of "save" (actor no. 1826)
-
-#define SAVE_LINE_NO 1
-
-void Sword2Engine::initialiseFontResourceFlags() {
- byte *textFile = _resman->openResource(TEXT_RES);
-
- // If language is Polish or Finnish it requires alternate fonts.
- // Otherwise, use regular fonts
-
- // "tallenna" Finnish for "save"
- // "zapisz" Polish for "save"
-
- // Get the text line (& skip the 2 chars containing the wavId)
- char *textLine = (char *)fetchTextLine(textFile, SAVE_LINE_NO) + 2;
-
- if (strcmp(textLine, "tallenna") == 0)
- initialiseFontResourceFlags(FINNISH_TEXT);
- else if (strcmp(textLine, "zapisz") == 0)
- initialiseFontResourceFlags(POLISH_TEXT);
- else
- initialiseFontResourceFlags(DEFAULT_TEXT);
-
- // Get the game name for the windows application
-
- // According to the GetNameFunction(), which was never called and has
- // therefore been removed, the name of the game is:
- //
- // ENGLISH: "Broken Sword II"
- // AMERICAN: "Circle of Blood II"
- // GERMAN: "Baphomet's Fluch II"
- // default: "Some game or other, part 86"
- //
- // But we get it from the text resource instead.
-
- if (_logic->readVar(DEMO))
- textLine = (char *)fetchTextLine(textFile, 451) + 2;
- else
- textLine = (char *)fetchTextLine(textFile, 54) + 2;
-
- _system->setWindowCaption(textLine);
- _resman->closeResource(TEXT_RES);
-}
-
-/**
- * Called from initialiseFontResourceFlags(), and also from console.cpp
- */
-
-void Sword2Engine::initialiseFontResourceFlags(uint8 language) {
- switch (language) {
- case FINNISH_TEXT:
- _speechFontId = FINNISH_SPEECH_FONT_ID;
- _controlsFontId = FINNISH_CONTROLS_FONT_ID;
- _redFontId = FINNISH_RED_FONT_ID;
- break;
- case POLISH_TEXT:
- _speechFontId = POLISH_SPEECH_FONT_ID;
- _controlsFontId = POLISH_CONTROLS_FONT_ID;
- _redFontId = POLISH_RED_FONT_ID;
- break;
- default:
- _speechFontId = ENGLISH_SPEECH_FONT_ID;
- _controlsFontId = ENGLISH_CONTROLS_FONT_ID;
- _redFontId = ENGLISH_RED_FONT_ID;
- break;
- }
-}
-
-} // End of namespace Sword2
diff --git a/sword2/maketext.h b/sword2/maketext.h
deleted file mode 100644
index 364a412857..0000000000
--- a/sword2/maketext.h
+++ /dev/null
@@ -1,119 +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 _MAKETEXT_H
-#define _MAKETEXT_H
-
-#include "sword2/debug.h"
-
-namespace Sword2 {
-
-// Output colour for character border - should be be black but note that we
-// have to use a different pen number during sequences
-
-#define BORDER_PEN 194
-
-// Usually the only texts on screen are the subtitles and the mouse-over text,
-// but there can also be a considerable number of debugging messages...
-
-#define MAX_text_blocs MAX_DEBUG_TEXTS + 1
-
-enum {
- // Doesn't keep the text inside the screen - only for debug text!
- NO_JUSTIFICATION = 0,
-
- // These all force text inside the screen edge margin when necessary
- POSITION_AT_CENTRE_OF_BASE = 1,
- POSITION_AT_CENTRE_OF_TOP = 2,
- POSITION_AT_LEFT_OF_TOP = 3,
- POSITION_AT_RIGHT_OF_TOP = 4,
- POSITION_AT_LEFT_OF_BASE = 5,
- POSITION_AT_RIGHT_OF_BASE = 6,
- POSITION_AT_LEFT_OF_CENTRE = 7,
- POSITION_AT_RIGHT_OF_CENTRE = 8
-};
-
-enum {
- DEFAULT_TEXT = 0,
- FINNISH_TEXT = 1,
- POLISH_TEXT = 2
-};
-
-// Info about the text, used to create the SpriteInfo struct
-
- struct TextBloc {
- int16 x;
- int16 y;
- uint16 type;
- byte *text_mem;
-};
-
-// Info for each line of words in the output text sprite
-
-struct LineInfo {
- uint16 width; // Width in pixels
- uint16 length; // Length in characters
-};
-
-class FontRenderer {
-private:
- Sword2Engine *_vm;
- TextBloc _blocList[MAX_text_blocs];
-
- // Layout variables - these used to be defines, but now we're dealing
- // with three character sets
-
- int8 _lineSpacing; // no. of pixels to separate lines of
- // characters in the output sprite - negative
- // for overlap
- int8 _charSpacing; // no. of pixels to separate characters along
- // each line - negative for overlap
- uint8 _borderPen; // output pen colour of character borders
-
- uint16 analyseSentence(byte *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line);
- byte *buildTextSprite(byte *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines);
- uint16 charWidth(byte ch, uint32 fontRes);
- uint16 charHeight(uint32 fontRes);
- byte *findChar(byte ch, byte *charSet);
- void copyChar(byte *charPtr, byte *spritePtr, uint16 spriteWidth, uint8 pen);
-
-public:
- FontRenderer(Sword2Engine *vm) : _vm(vm) {
- for (int i = 0; i < MAX_text_blocs; i++)
- _blocList[i].text_mem = NULL;
- }
-
- ~FontRenderer() {
- for (int i = 0; i < MAX_text_blocs; i++)
- free(_blocList[i].text_mem);
- }
-
- byte *makeTextSprite(byte *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes, uint8 border = BORDER_PEN);
-
- void killTextBloc(uint32 bloc_number);
- void printTextBlocs();
-
- uint32 buildNewBloc(byte *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification);
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/memory.cpp b/sword2/memory.cpp
deleted file mode 100644
index 7da4e86b51..0000000000
--- a/sword2/memory.cpp
+++ /dev/null
@@ -1,244 +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$
- */
-
-// The new memory manager, now only used by the resource manager. The original
-// one would allocated a 12 MB memory pool at startup, which may have been
-// appropriate for the original Playstation version but didn't work very well
-// with our PocketPC version.
-//
-// There is one thing that prevents us from replacing the whole memory manager
-// with the standard memory allocation functions: Broken Sword 2 absolutely,
-// positively needs to be able to encode pointers as 32-bit integers. The
-// original engine did this simply by casting between pointers and integers,
-// but as far as I know that's not a very portable thing to do.
-//
-// If it had only used pointers as opcode parameters it would have been
-// possible, albeit messy, to extend the stack data type. However, there is
-// code in walker.cpp that obviously violates that assumption, and there are
-// probably other cases as well.
-//
-// Instead, we take advantage of the fact that the original memory manager
-// could only handle up to 999 blocks of memory. That means we can encode a
-// pointer as a 10-bit id and a 22-bit offset into the block. Judging by early
-// testing, both should be plenty.
-//
-// The number zero is used to represent the NULL pointer.
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/memory.h"
-
-namespace Sword2 {
-
-MemoryManager::MemoryManager(Sword2Engine *vm) : _vm(vm) {
- // The id stack contains all the possible ids for the memory blocks.
- // We use this to ensure that no two blocks ever have the same id.
-
- // The memory blocks are stored in an array, indexed on the block's
- // id. This means that given a block id we can find the pointer with a
- // simple array lookup.
-
- // The memory block index is an array of pointers to the memory block
- // array, sorted on the memory block's pointer. This means that given
- // a pointer into a memory block we can find its id with binary
- // searching.
- //
- // A balanced tree might have been more efficient - the index has to
- // be re-sorted every time a block is allocated or freed - but such
- // beasts are tricky to implement. Anyway, it wouldn't have made
- // encoding or decoding pointers any faster, and these are by far the
- // most common operations.
-
- _idStack = (int16 *)malloc(MAX_MEMORY_BLOCKS * sizeof(int16));
- _memBlocks = (MemBlock *)malloc(MAX_MEMORY_BLOCKS * sizeof(MemBlock));
- _memBlockIndex = (MemBlock **)malloc(MAX_MEMORY_BLOCKS * sizeof(MemBlock *));
-
- _totAlloc = 0;
- _numBlocks = 0;
-
- for (int i = 0; i < MAX_MEMORY_BLOCKS; i++) {
- _idStack[i] = MAX_MEMORY_BLOCKS - i - 1;
- _memBlocks[i].ptr = NULL;
- _memBlockIndex[i] = NULL;
- }
-
- _idStackPtr = MAX_MEMORY_BLOCKS;
-}
-
-MemoryManager::~MemoryManager() {
- for (int i = 0; i < MAX_MEMORY_BLOCKS; i++)
- free(_memBlocks[i].ptr);
- free(_memBlocks);
- free(_memBlockIndex);
- free(_idStack);
-}
-
-int32 MemoryManager::encodePtr(byte *ptr) {
- if (ptr == NULL)
- return 0;
-
- int idx = findPointerInIndex(ptr);
-
- assert(idx != -1);
-
- uint32 id = _memBlockIndex[idx]->id;
- uint32 offset = ptr - _memBlocks[id].ptr;
-
- assert(id < 0x03ff);
- assert(offset <= 0x003fffff);
- assert(offset < _memBlocks[id].size);
-
- return ((id + 1) << 22) | (ptr - _memBlocks[id].ptr);
-}
-
-byte *MemoryManager::decodePtr(int32 n) {
- if (n == 0)
- return NULL;
-
- uint32 id = ((n & 0xffc00000) >> 22) - 1;
- uint32 offset = n & 0x003fffff;
-
- assert(_memBlocks[id].ptr);
- assert(offset < _memBlocks[id].size);
-
- return _memBlocks[id].ptr + offset;
-}
-
-int16 MemoryManager::findExactPointerInIndex(byte *ptr) {
- int left = 0;
- int right = _numBlocks - 1;
-
- while (right >= left) {
- int n = (left + right) / 2;
-
- if (_memBlockIndex[n]->ptr == ptr)
- return n;
-
- if (_memBlockIndex[n]->ptr > ptr)
- right = n - 1;
- else
- left = n + 1;
- }
-
- return -1;
-}
-
-int16 MemoryManager::findPointerInIndex(byte *ptr) {
- int left = 0;
- int right = _numBlocks - 1;
-
- while (right >= left) {
- int n = (left + right) / 2;
-
- if (_memBlockIndex[n]->ptr <= ptr && _memBlockIndex[n]->ptr + _memBlockIndex[n]->size > ptr)
- return n;
-
- if (_memBlockIndex[n]->ptr > ptr)
- right = n - 1;
- else
- left = n + 1;
- }
-
- return -1;
-}
-
-int16 MemoryManager::findInsertionPointInIndex(byte *ptr) {
- if (_numBlocks == 0)
- return 0;
-
- int left = 0;
- int right = _numBlocks - 1;
- int n = 0;
-
- while (right >= left) {
- n = (left + right) / 2;
-
- if (_memBlockIndex[n]->ptr == ptr)
- return -1;
-
- if (_memBlockIndex[n]->ptr > ptr)
- right = n - 1;
- else
- left = n + 1;
- }
-
- if (_memBlockIndex[n]->ptr < ptr)
- n++;
-
- return n;
-}
-
-byte *MemoryManager::memAlloc(uint32 size, int16 uid) {
- assert(_idStackPtr > 0);
-
- // Get the new block's id from the stack.
- int16 id = _idStack[--_idStackPtr];
-
- // Allocate the new memory block
- byte *ptr = (byte *)malloc(size);
-
- assert(ptr);
-
- _memBlocks[id].id = id;
- _memBlocks[id].uid = uid;
- _memBlocks[id].ptr = ptr;
- _memBlocks[id].size = size;
-
- // Update the memory block index.
- int16 idx = findInsertionPointInIndex(ptr);
-
- assert(idx != -1);
-
- for (int i = _numBlocks; i > idx; i--)
- _memBlockIndex[i] = _memBlockIndex[i - 1];
-
- _memBlockIndex[idx] = &_memBlocks[id];
- _numBlocks++;
- _totAlloc += size;
-
- return _memBlocks[id].ptr;
-}
-
-void MemoryManager::memFree(byte *ptr) {
- int16 idx = findExactPointerInIndex(ptr);
-
- if (idx == -1) {
- warning("Freeing non-allocated pointer %p", ptr);
- return;
- }
-
- // Put back the id on the stack
- _idStack[_idStackPtr++] = _memBlockIndex[idx]->id;
-
- // Release the memory block
- free(_memBlockIndex[idx]->ptr);
- _memBlockIndex[idx]->ptr = NULL;
-
- _totAlloc -= _memBlockIndex[idx]->size;
-
- // Remove the memory block from the index
- _numBlocks--;
-
- for (int i = idx; i < _numBlocks; i++)
- _memBlockIndex[i] = _memBlockIndex[i + 1];
-}
-
-} // End of namespace Sword2
diff --git a/sword2/memory.h b/sword2/memory.h
deleted file mode 100644
index 3154842cd9..0000000000
--- a/sword2/memory.h
+++ /dev/null
@@ -1,70 +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 MEMORY_H
-#define MEMORY_H
-
-#define MAX_MEMORY_BLOCKS 999
-
-namespace Sword2 {
-
-struct MemBlock {
- int16 id;
- int16 uid;
- byte *ptr;
- uint32 size;
-};
-
-class MemoryManager {
-private:
- Sword2Engine *_vm;
-
- MemBlock *_memBlocks;
- MemBlock **_memBlockIndex;
- int16 _numBlocks;
-
- uint32 _totAlloc;
-
- int16 *_idStack;
- int16 _idStackPtr;
-
- int16 findExactPointerInIndex(byte *ptr);
- int16 findPointerInIndex(byte *ptr);
- int16 findInsertionPointInIndex(byte *ptr);
-
-public:
- MemoryManager(Sword2Engine *vm);
- ~MemoryManager();
-
- int16 getNumBlocks() { return _numBlocks; }
- uint32 getTotAlloc() { return _totAlloc; }
- MemBlock *getMemBlocks() { return _memBlocks; }
-
- int32 encodePtr(byte *ptr);
- byte *decodePtr(int32 n);
-
- byte *memAlloc(uint32 size, int16 uid);
- void memFree(byte *ptr);
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/menu.cpp b/sword2/menu.cpp
deleted file mode 100644
index 07e00accb6..0000000000
--- a/sword2/menu.cpp
+++ /dev/null
@@ -1,291 +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$
- */
-
-#include "common/stdafx.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/mouse.h"
-
-namespace Sword2 {
-
-#define MENUDEEP 40
-#define MAXMENUANIMS 8
-
-void Mouse::clearIconArea(int menu, int pocket, Common::Rect *r) {
- byte *buf = _vm->_screen->getScreen();
- int16 screenWide = _vm->_screen->getScreenWide();
-
- r->top = menu * (RENDERDEEP + MENUDEEP) + (MENUDEEP - RDMENU_ICONDEEP) / 2;
- r->bottom = r->top + RDMENU_ICONDEEP;
- r->left = RDMENU_ICONSTART + pocket * (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
- r->right = r->left + RDMENU_ICONWIDE;
-
- byte *dst = buf + r->top * screenWide + r->left;
-
- for (int i = 0; i < RDMENU_ICONDEEP; i++) {
- memset(dst, 0, RDMENU_ICONWIDE);
- dst += screenWide;
- }
-}
-
-/**
- * This function should be called regularly to process the menubar system. The
- * rate at which this function is called will dictate how smooth the menu
- * system is.
- */
-
-void Mouse::processMenu() {
- uint8 menu;
- uint8 i, j;
- uint8 frameCount;
- Common::Rect r1, r2;
- static int32 lastTime = 0;
-
- byte *buf = _vm->_screen->getScreen();
- int16 screenWide = _vm->_screen->getScreenWide();
-
- if (lastTime == 0) {
- lastTime = _vm->getMillis();
- frameCount = 1;
- } else {
- int32 delta = _vm->getMillis() - lastTime;
-
- if (delta > 250) {
- lastTime += delta;
- delta = 250;
- frameCount = 1;
- } else {
- frameCount = (uint8) ((_iconCount + 8) * delta / 750);
- lastTime += frameCount * 750 / (_iconCount + 8);
- }
- }
-
- // Note: The "almost hidden" menu state exists only so that the menu
- // will be redrawn one last time before it's completely hidden. We do
- // not need a corresponding "almost shown" state because the menu will
- // always be redrawn while it's shown anyway. (We may want to change
- // this later.)
-
- while (frameCount-- > 0) {
- for (menu = RDMENU_TOP; menu <= RDMENU_BOTTOM; menu++) {
- if (_menuStatus[menu] == RDMENU_HIDDEN || _menuStatus[menu] == RDMENU_ALMOST_HIDDEN || _menuStatus[menu] == RDMENU_SHOWN)
- continue;
-
- int target, direction, nextState;
-
- if (_menuStatus[menu] == RDMENU_OPENING) {
- target = MAXMENUANIMS;
- direction = 1;
- nextState = RDMENU_SHOWN;
- } else {
- target = 0;
- direction = -1;
- nextState = RDMENU_ALMOST_HIDDEN;
- }
-
- bool complete = true;
-
- // Propagate animation from the first icon...
- for (i = RDMENU_MAXPOCKETS - 1; i > 0; i--) {
- _pocketStatus[menu][i] = _pocketStatus[menu][i - 1];
-
- if (_pocketStatus[menu][i] != target)
- complete = false;
- }
-
- if (_pocketStatus[menu][i] != target)
- complete = false;
-
- // ...and animate the first icon
- if (_pocketStatus[menu][0] != target)
- _pocketStatus[menu][0] += direction;
-
- if (complete)
- _menuStatus[menu] = nextState;
- }
- }
-
- for (menu = RDMENU_TOP; menu <= RDMENU_BOTTOM; menu++) {
- if (_menuStatus[menu] == RDMENU_HIDDEN)
- continue;
-
- if (_menuStatus[menu] == RDMENU_ALMOST_HIDDEN)
- _menuStatus[menu] = RDMENU_HIDDEN;
-
- // Draw the menu here.
- int32 curx = RDMENU_ICONSTART + RDMENU_ICONWIDE / 2;
- int32 cury = (MENUDEEP / 2) + (RENDERDEEP + MENUDEEP) * menu;
-
- for (i = 0; i < RDMENU_MAXPOCKETS; i++) {
- if (_icons[menu][i]) {
- int32 xoff, yoff;
-
- // Since we no longer clear the screen after
- // each frame we need to clear the icon area.
-
- clearIconArea(menu, i, &r1);
-
- if (_pocketStatus[menu][i] == MAXMENUANIMS) {
- xoff = (RDMENU_ICONWIDE / 2);
- r2.left = curx - xoff;
- r2.right = r2.left + RDMENU_ICONWIDE;
- yoff = (RDMENU_ICONDEEP / 2);
- r2.top = cury - yoff;
- r2.bottom = r2.top + RDMENU_ICONDEEP;
- } else {
- xoff = (RDMENU_ICONWIDE / 2) * _pocketStatus[menu][i] / MAXMENUANIMS;
- r2.left = curx - xoff;
- r2.right = curx + xoff;
- yoff = (RDMENU_ICONDEEP / 2) * _pocketStatus[menu][i] / MAXMENUANIMS;
- r2.top = cury - yoff;
- r2.bottom = cury + yoff;
- }
-
- if (xoff != 0 && yoff != 0) {
- byte *dst = buf + r2.top * screenWide + r2.left;
- byte *src = _icons[menu][i];
-
- if (_pocketStatus[menu][i] != MAXMENUANIMS) {
- _vm->_screen->scaleImageFast(
- dst, screenWide, r2.right - r2.left, r2.bottom - r2.top,
- src, RDMENU_ICONWIDE, RDMENU_ICONWIDE, RDMENU_ICONDEEP);
- } else {
- for (j = 0; j < RDMENU_ICONDEEP; j++) {
- memcpy(dst, src, RDMENU_ICONWIDE);
- src += RDMENU_ICONWIDE;
- dst += screenWide;
- }
- }
- }
- _vm->_screen->updateRect(&r1);
- }
- curx += (RDMENU_ICONSPACING + RDMENU_ICONWIDE);
- }
- }
-}
-
-/**
- * This function brings a specified menu into view.
- * @param menu RDMENU_TOP or RDMENU_BOTTOM, depending on which menu to show
- * @return RD_OK, or an error code
- */
-
-int32 Mouse::showMenu(uint8 menu) {
- // Check for invalid menu parameter
- if (menu > RDMENU_BOTTOM)
- return RDERR_INVALIDMENU;
-
- // Check that the menu is not currently shown, or in the process of
- // being shown.
- if (_menuStatus[menu] == RDMENU_SHOWN || _menuStatus[menu] == RDMENU_OPENING)
- return RDERR_INVALIDCOMMAND;
-
- _menuStatus[menu] = RDMENU_OPENING;
- return RD_OK;
-}
-
-/**
- * This function hides a specified menu.
- * @param menu RDMENU_TOP or RDMENU_BOTTOM depending on which menu to hide
- * @return RD_OK, or an error code
- */
-
-int32 Mouse::hideMenu(uint8 menu) {
- // Check for invalid menu parameter
- if (menu > RDMENU_BOTTOM)
- return RDERR_INVALIDMENU;
-
- // Check that the menu is not currently hidden, or in the process of
- // being hidden.
- if (_menuStatus[menu] == RDMENU_HIDDEN || _menuStatus[menu] == RDMENU_CLOSING)
- return RDERR_INVALIDCOMMAND;
-
- _menuStatus[menu] = RDMENU_CLOSING;
- return RD_OK;
-}
-
-/**
- * This function hides both menus immediately.
- */
-
-void Mouse::closeMenuImmediately() {
- Common::Rect r;
- int i;
-
- _menuStatus[RDMENU_TOP] = RDMENU_HIDDEN;
- _menuStatus[RDMENU_BOTTOM] = RDMENU_HIDDEN;
-
- for (i = 0; i < RDMENU_MAXPOCKETS; i++) {
- if (_icons[RDMENU_TOP][i]) {
- clearIconArea(RDMENU_TOP, i, &r);
- _vm->_screen->updateRect(&r);
- }
- if (_icons[RDMENU_BOTTOM][i]) {
- clearIconArea(RDMENU_BOTTOM, i, &r);
- _vm->_screen->updateRect(&r);
- }
- }
-
- memset(_pocketStatus, 0, sizeof(uint8) * 2 * RDMENU_MAXPOCKETS);
-}
-
-/**
- * This function sets a menubar icon.
- * @param menu RDMENU_TOP or RDMENU_BOTTOM, depending on which menu to change
- * @param pocket the menu pocket to change
- * @param icon icon data, or NULL to clear the icon
- * @return RD_OK, or an error code
- */
-
-int32 Mouse::setMenuIcon(uint8 menu, uint8 pocket, byte *icon) {
- Common::Rect r;
-
- // Check for invalid menu parameter.
- if (menu > RDMENU_BOTTOM)
- return RDERR_INVALIDMENU;
-
- // Check for invalid pocket parameter
- if (pocket >= RDMENU_MAXPOCKETS)
- return RDERR_INVALIDPOCKET;
-
- // If there is an icon in the requested menu/pocket, clear it out.
- if (_icons[menu][pocket]) {
- _iconCount--;
- free(_icons[menu][pocket]);
- _icons[menu][pocket] = NULL;
- clearIconArea(menu, pocket, &r);
- _vm->_screen->updateRect(&r);
- }
-
- // Only put the icon in the pocket if it is not NULL
- if (icon != NULL) {
- _iconCount++;
- _icons[menu][pocket] = (byte *)malloc(RDMENU_ICONWIDE * RDMENU_ICONDEEP);
- if (_icons[menu][pocket] == NULL)
- return RDERR_OUTOFMEMORY;
- memcpy(_icons[menu][pocket], icon, RDMENU_ICONWIDE * RDMENU_ICONDEEP);
- }
-
- return RD_OK;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/module.mk b/sword2/module.mk
deleted file mode 100644
index fb020ba633..0000000000
--- a/sword2/module.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-MODULE := sword2
-
-MODULE_OBJS := \
- sword2/_mouse.o \
- sword2/animation.o \
- sword2/anims.o \
- sword2/build_display.o \
- sword2/console.o \
- sword2/controls.o \
- sword2/d_draw.o \
- sword2/debug.o \
- sword2/events.o \
- sword2/function.o \
- sword2/icons.o \
- sword2/interpreter.o \
- sword2/layers.o \
- sword2/logic.o \
- sword2/maketext.o \
- sword2/memory.o \
- sword2/menu.o \
- sword2/mouse.o \
- sword2/music.o \
- sword2/palette.o \
- sword2/protocol.o \
- sword2/rdwin.o \
- sword2/render.o \
- sword2/resman.o \
- sword2/router.o \
- sword2/save_rest.o \
- sword2/scroll.o \
- sword2/sound.o \
- sword2/speech.o \
- sword2/sprite.o \
- sword2/startup.o \
- sword2/sword2.o \
- sword2/sync.o \
- sword2/walker.o
-
-MODULE_DIRS += \
- sword2
-
-# This module can be built as a plugin
-ifdef BUILD_PLUGINS
-PLUGIN := 1
-endif
-
-# Include common rules
-include $(srcdir)/common.rules
diff --git a/sword2/mouse.cpp b/sword2/mouse.cpp
deleted file mode 100644
index f8c315a47f..0000000000
--- a/sword2/mouse.cpp
+++ /dev/null
@@ -1,1437 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/console.h"
-#include "sword2/controls.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 {
-
-// Pointer resource id's
-
-enum {
- CROSHAIR = 18,
- EXIT0 = 788,
- EXIT1 = 789,
- EXIT2 = 790,
- EXIT3 = 791,
- EXIT4 = 792,
- EXIT5 = 793,
- EXIT6 = 794,
- EXIT7 = 795,
- EXITDOWN = 796,
- EXITUP = 797,
- MOUTH = 787,
- NORMAL = 17,
- PICKUP = 3099,
- SCROLL_L = 1440,
- SCROLL_R = 1441,
- USE = 3100
-};
-
-Mouse::Mouse(Sword2Engine *vm) {
- _vm = vm;
-
- setPos(0, 0);
- resetMouseList();
-
- _mouseTouching = 0;
- _oldMouseTouching = 0;
- _menuSelectedPos = 0;
- _examiningMenuIcon = false;
- _mousePointerRes = 0;
- _mouseMode = 0;
- _mouseStatus = false;
- _mouseModeLocked = false;
- _currentLuggageResource = 0;
- _oldButton = 0;
- _buttonClick = 0;
- _pointerTextBlocNo = 0;
- _playerActivityDelay = 0;
- _realLuggageItem = 0;
-
- _mouseAnim.data = NULL;
- _luggageAnim.data = NULL;
-
- // For the menus
- _totalTemp = 0;
- memset(_tempList, 0, sizeof(_tempList));
-
- _totalMasters = 0;
- memset(_masterMenuList, 0, sizeof(_masterMenuList));
- memset(_mouseList, 0, sizeof(_mouseList));
- memset(_subjectList, 0, sizeof(_subjectList));
-
- _defaultResponseId = 0;
- _choosing = false;
-
- _iconCount = 0;
-
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < RDMENU_MAXPOCKETS; j++) {
- _icons[i][j] = NULL;
- _pocketStatus[i][j] = 0;
- }
-
- _menuStatus[i] = RDMENU_HIDDEN;
- }
-}
-
-Mouse::~Mouse() {
- free(_mouseAnim.data);
- free(_luggageAnim.data);
- for (int i = 0; i < 2; i++)
- for (int j = 0; j < RDMENU_MAXPOCKETS; j++)
- free(_icons[i][j]);
-}
-
-void Mouse::getPos(int &x, int &y) {
- x = _pos.x;
- y = _pos.y;
-}
-
-void Mouse::setPos(int x, int y) {
- _pos.x = x;
- _pos.y = y;
-}
-
-/**
- * Call at beginning of game loop
- */
-
-void Mouse::resetMouseList() {
- _curMouse = 0;
-}
-
-void Mouse::registerMouse(byte *ob_mouse, BuildUnit *build_unit) {
- assert(_curMouse < TOTAL_mouse_list);
-
- ObjectMouse mouse;
-
- mouse.read(ob_mouse);
-
- if (!mouse.pointer)
- return;
-
- if (build_unit) {
- _mouseList[_curMouse].rect.left = build_unit->x;
- _mouseList[_curMouse].rect.top = build_unit->y;
- _mouseList[_curMouse].rect.right = 1 + build_unit->x + build_unit->scaled_width;
- _mouseList[_curMouse].rect.bottom = 1 + build_unit->y + build_unit->scaled_height;
- } else {
- _mouseList[_curMouse].rect.left = mouse.x1;
- _mouseList[_curMouse].rect.top = mouse.y1;
- _mouseList[_curMouse].rect.right = 1 + mouse.x2;
- _mouseList[_curMouse].rect.bottom = 1 + mouse.y2;
- }
-
- _mouseList[_curMouse].priority = mouse.priority;
- _mouseList[_curMouse].pointer = mouse.pointer;
-
- // Change all COGS pointers to CROSHAIR. I'm guessing that this was a
- // design decision made in mid-development and they didn't want to go
- // back and re-generate the resource files.
-
- if (_mouseList[_curMouse].pointer == USE)
- _mouseList[_curMouse].pointer = CROSHAIR;
-
- // Check if pointer text field is set due to previous object using this
- // slot (ie. not correct for this one)
-
- // If 'pointer_text' field is set, but the 'id' field isn't same is
- // current id then we don't want this "left over" pointer text
-
- if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32)_vm->_logic->readVar(ID))
- _mouseList[_curMouse].pointer_text = 0;
-
- // Get id from system variable 'id' which is correct for current object
- _mouseList[_curMouse].id = _vm->_logic->readVar(ID);
-
- _curMouse++;
-}
-
-void Mouse::registerPointerText(int32 text_id) {
- assert(_curMouse < TOTAL_mouse_list);
-
- // current object id - used for checking pointer_text when mouse area
- // registered (in fnRegisterMouse and fnRegisterFrame)
-
- _mouseList[_curMouse].id = _vm->_logic->readVar(ID);
- _mouseList[_curMouse].pointer_text = text_id;
-}
-
-/**
- * This function is called every game cycle.
- */
-
-void Mouse::mouseEngine() {
- monitorPlayerActivity();
- clearPointerText();
-
- // If George is dead, the system menu is visible all the time, and is
- // the only thing that can be used.
-
- if (_vm->_logic->readVar(DEAD)) {
- if (_mouseMode != MOUSE_system_menu) {
- _mouseMode = MOUSE_system_menu;
-
- if (_mouseTouching) {
- _oldMouseTouching = 0;
- _mouseTouching = 0;
- }
-
- setMouse(NORMAL_MOUSE_ID);
- buildSystemMenu();
- }
- systemMenuMouse();
- return;
- }
-
- // If the mouse is not visible, do nothing
-
- if (_mouseStatus)
- return;
-
- switch (_mouseMode) {
- case MOUSE_normal:
- normalMouse();
- break;
- case MOUSE_menu:
- menuMouse();
- break;
- case MOUSE_drag:
- dragMouse();
- break;
- case MOUSE_system_menu:
- systemMenuMouse();
- break;
- case MOUSE_holding:
- if (_pos.y < 400) {
- _mouseMode = MOUSE_normal;
- debug(5, " releasing");
- }
- break;
- default:
- break;
- }
-}
-
-#if RIGHT_CLICK_CLEARS_LUGGAGE
-bool Mouse::heldIsInInventory() {
- int32 object_held = (int32)_vm->_logic->readVar(OBJECT_HELD);
-
- for (uint i = 0; i < _totalMasters; i++) {
- if (_masterMenuList[i].icon_resource == object_held)
- return true;
- }
- return false;
-}
-#endif
-
-int Mouse::menuClick(int menu_items) {
- if (_pos.x < RDMENU_ICONSTART)
- return -1;
-
- if (_pos.x > RDMENU_ICONSTART + menu_items * (RDMENU_ICONWIDE + RDMENU_ICONSPACING) - RDMENU_ICONSPACING)
- return -1;
-
- return (_pos.x - RDMENU_ICONSTART) / (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
-}
-
-void Mouse::systemMenuMouse() {
- uint32 safe_looping_music_id;
- MouseEvent *me;
- int hit;
- byte *icon;
- int32 pars[2];
- uint32 icon_list[5] = {
- OPTIONS_ICON,
- QUIT_ICON,
- SAVE_ICON,
- RESTORE_ICON,
- RESTART_ICON
- };
-
- // If the mouse is moved off the menu, close it. Unless the player is
- // dead, in which case the menu should always be visible.
-
- if (_pos.y > 0 && !_vm->_logic->readVar(DEAD)) {
- _mouseMode = MOUSE_normal;
- hideMenu(RDMENU_TOP);
- return;
- }
-
- // Check if the user left-clicks anywhere in the menu area.
-
- me = _vm->mouseEvent();
-
- if (!me || !(me->buttons & RD_LEFTBUTTONDOWN))
- return;
-
- if (_pos.y > 0)
- return;
-
- hit = menuClick(ARRAYSIZE(icon_list));
-
- if (hit < 0)
- return;
-
- // No save when dead
-
- if (icon_list[hit] == SAVE_ICON && _vm->_logic->readVar(DEAD))
- return;
-
- // Gray out all he icons, except the one that was clicked
-
- for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
- if (i != hit) {
- icon = _vm->_resman->openResource(icon_list[i]) + ResHeader::size();
- setMenuIcon(RDMENU_TOP, i, icon);
- _vm->_resman->closeResource(icon_list[i]);
- }
- }
-
- _vm->_sound->pauseFx();
-
- // NB. Need to keep a safe copy of '_loopingMusicId' for savegame & for
- // playing when returning from control panels because control panel
- // music will overwrite it!
-
- safe_looping_music_id = _vm->_sound->getLoopingMusicId();
-
- pars[0] = 221;
- pars[1] = FX_LOOP;
- _vm->_logic->fnPlayMusic(pars);
-
- // HACK: Restore proper looping_music_id
- _vm->_sound->setLoopingMusicId(safe_looping_music_id);
-
- processMenu();
-
- // call the relevant screen
-
- switch (hit) {
- case 0:
- {
- OptionsDialog dialog(_vm);
- dialog.runModal();
- }
- break;
- case 1:
- {
- QuitDialog dialog(_vm);
- dialog.runModal();
- }
- break;
- case 2:
- {
- SaveDialog dialog(_vm);
- dialog.runModal();
- }
- break;
- case 3:
- {
- RestoreDialog dialog(_vm);
- dialog.runModal();
- }
- break;
- case 4:
- {
- RestartDialog dialog(_vm);
- dialog.runModal();
- }
- break;
- }
-
- // Menu stays open on death screen. Otherwise it's closed.
-
- if (!_vm->_logic->readVar(DEAD)) {
- _mouseMode = MOUSE_normal;
- hideMenu(RDMENU_TOP);
- } else {
- setMouse(NORMAL_MOUSE_ID);
- buildSystemMenu();
- }
-
- // Back to the game again
-
- processMenu();
-
- // Reset game palette, but not after a successful restore or restart!
- // See RestoreFromBuffer() in save_rest.cpp
-
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- if (screenInfo->new_palette != 99) {
- // 0 means put back game screen palette; see build_display.cpp
- _vm->_screen->setFullPalette(0);
-
- // Stop the engine fading in the restored screens palette
- screenInfo->new_palette = 0;
- } else
- screenInfo->new_palette = 1;
-
- _vm->_sound->unpauseFx();
-
- // If there was looping music before coming into the control panels
- // then restart it! NB. If a game has been restored the music will be
- // restarted twice, but this shouldn't cause any harm.
-
- if (_vm->_sound->getLoopingMusicId()) {
- pars[0] = _vm->_sound->getLoopingMusicId();
- pars[1] = FX_LOOP;
- _vm->_logic->fnPlayMusic(pars);
- } else
- _vm->_logic->fnStopMusic(NULL);
-}
-
-void Mouse::dragMouse() {
- byte buf1[NAME_LEN], buf2[NAME_LEN];
- MouseEvent *me;
- int hit;
-
- // We can use dragged object both on other inventory objects, or on
- // objects in the scene, so if the mouse moves off the inventory menu,
- // then close it.
-
- if (_pos.y < 400) {
- _mouseMode = MOUSE_normal;
- hideMenu(RDMENU_BOTTOM);
- return;
- }
-
- // Handles cursors and the luggage on/off according to type
-
- mouseOnOff();
-
- // Now do the normal click stuff
-
- me = _vm->mouseEvent();
-
- if (!me)
- return;
-
-#if RIGHT_CLICK_CLEARS_LUGGAGE
- if ((me->buttons & RD_RIGHTBUTTONDOWN) && heldIsInInventory()) {
- _vm->_logic->writeVar(OBJECT_HELD, 0);
- _menuSelectedPos = 0;
- _mouseMode = MOUSE_menu;
- setLuggage(0);
- buildMenu();
- return;
- }
-#endif
-
- if (!(me->buttons & RD_LEFTBUTTONDOWN))
- return;
-
- // there's a mouse event to be processed
-
- // could be clicking on an on screen object or on the menu
- // which is currently displayed
-
- if (_mouseTouching) {
- // mouse is over an on screen object - and we have luggage
-
- // Depending on type we'll maybe kill the object_held - like
- // for exits
-
- // Set global script variable 'button'. We know that it was the
- // left button, not the right one.
-
- _vm->_logic->writeVar(LEFT_BUTTON, 1);
- _vm->_logic->writeVar(RIGHT_BUTTON, 0);
-
- // These might be required by the action script about to be run
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- _vm->_logic->writeVar(MOUSE_X, _pos.x + screenInfo->scroll_offset_x);
- _vm->_logic->writeVar(MOUSE_Y, _pos.y + screenInfo->scroll_offset_y);
-
- // For scripts to know what's been clicked. First used for
- // 'room_13_turning_script' in object 'biscuits_13'
-
- _vm->_logic->writeVar(CLICKED_ID, _mouseTouching);
-
- _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
-
- debug(2, "Used \"%s\" on \"%s\"",
- _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf1),
- _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf2));
-
- // Hide menu - back to normal menu mode
-
- hideMenu(RDMENU_BOTTOM);
- _mouseMode = MOUSE_normal;
-
- return;
- }
-
- // Better check for combine/cancel. Cancel puts us back in MOUSE_menu
- // mode
-
- hit = menuClick(TOTAL_engine_pockets);
-
- if (hit < 0 || !_masterMenuList[hit].icon_resource)
- return;
-
- // Always back into menu mode. Remove the luggage as well.
-
- _mouseMode = MOUSE_menu;
- setLuggage(0);
-
- if ((uint)hit == _menuSelectedPos) {
- // If we clicked on the same icon again, reset the first icon
-
- _vm->_logic->writeVar(OBJECT_HELD, 0);
- _menuSelectedPos = 0;
- } else {
- // Otherwise, combine the two icons
-
- _vm->_logic->writeVar(COMBINE_BASE, _masterMenuList[hit].icon_resource);
- _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
-
- // Turn off mouse now, to prevent player trying to click
- // elsewhere BUT leave the bottom menu open
-
- hideMouse();
-
- debug(2, "Used \"%s\" on \"%s\"",
- _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf1),
- _vm->_resman->fetchName(_vm->_logic->readVar(COMBINE_BASE), buf2));
- }
-
- // Refresh the menu
-
- buildMenu();
-}
-
-void Mouse::menuMouse() {
- byte buf[NAME_LEN];
- MouseEvent *me;
- int hit;
-
- // If the mouse is moved off the menu, close it.
-
- if (_pos.y < 400) {
- _mouseMode = MOUSE_normal;
- hideMenu(RDMENU_BOTTOM);
- return;
- }
-
- me = _vm->mouseEvent();
-
- if (!me)
- return;
-
- hit = menuClick(TOTAL_engine_pockets);
-
- // Check if we clicked on an actual icon.
-
- if (hit < 0 || !_masterMenuList[hit].icon_resource)
- return;
-
- if (me->buttons & RD_RIGHTBUTTONDOWN) {
- // Right button - examine an object, identified by its icon
- // resource id.
-
- _examiningMenuIcon = true;
- _vm->_logic->writeVar(OBJECT_HELD, _masterMenuList[hit].icon_resource);
-
- // Must clear this so next click on exit becomes 1st click
- // again
-
- _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
-
- _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
-
- // Refresh the menu
-
- buildMenu();
-
- // Turn off mouse now, to prevent player trying to click
- // elsewhere BUT leave the bottom menu open
-
- hideMouse();
-
- debug(2, "Right-click on \"%s\" icon",
- _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf));
-
- return;
- }
-
- if (me->buttons & RD_LEFTBUTTONDOWN) {
- // Left button - bung us into drag luggage mode. The object is
- // identified by its icon resource id. We need the luggage
- // resource id for mouseOnOff
-
- _mouseMode = MOUSE_drag;
-
- _menuSelectedPos = hit;
- _vm->_logic->writeVar(OBJECT_HELD, _masterMenuList[hit].icon_resource);
- _currentLuggageResource = _masterMenuList[hit].luggage_resource;
-
- // Must clear this so next click on exit becomes 1st click
- // again
-
- _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
-
- // Refresh the menu
-
- buildMenu();
-
- setLuggage(_masterMenuList[hit].luggage_resource);
-
- debug(2, "Left-clicked on \"%s\" icon - switch to drag mode",
- _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf));
- }
-}
-
-void Mouse::normalMouse() {
- // The gane is playing and none of the menus are activated - but, we
- // need to check if a menu is to start. Note, won't have luggage
-
- MouseEvent *me;
-
- // Check if the cursor has moved onto the system menu area. No save in
- // big-object menu lock situation, of if the player is dragging an
- // object.
-
- if (_pos.y < 0 && !_mouseModeLocked && !_vm->_logic->readVar(OBJECT_HELD)) {
- _mouseMode = MOUSE_system_menu;
-
- if (_mouseTouching) {
- // We were on something, but not anymore
- _oldMouseTouching = 0;
- _mouseTouching = 0;
- }
-
- // Reset mouse cursor - in case we're between mice
-
- setMouse(NORMAL_MOUSE_ID);
- buildSystemMenu();
- return;
- }
-
- // Check if the cursor has moved onto the inventory menu area. No
- // inventory in big-object menu lock situation,
-
- if (_pos.y > 399 && !_mouseModeLocked) {
- // If an object is being held, i.e. if the mouse cursor has a
- // luggage, go to drag mode instead of menu mode, but the menu
- // is still opened.
- //
- // That way, we can still use an object on another inventory
- // object, even if the inventory menu was closed after the
- // first object was selected.
-
- if (!_vm->_logic->readVar(OBJECT_HELD))
- _mouseMode = MOUSE_menu;
- else
- _mouseMode = MOUSE_drag;
-
- // If mouse is moving off an object and onto the menu then do a
- // standard get-off
-
- if (_mouseTouching) {
- _oldMouseTouching = 0;
- _mouseTouching = 0;
- }
-
- // Reset mouse cursor
-
- setMouse(NORMAL_MOUSE_ID);
- buildMenu();
- return;
- }
-
- // Check for moving the mouse on or off things
-
- mouseOnOff();
-
- me = _vm->mouseEvent();
-
- if (!me)
- return;
-
- bool button_down = (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)) != 0;
-
- // For debugging. We can draw a rectangle on the screen and see its
- // coordinates. This was probably used to help defining hit areas.
-
- if (_vm->_debugger->_definingRectangles) {
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- if (_vm->_debugger->_draggingRectangle == 0) {
- // Not yet dragging a rectangle, so need click to start
-
- if (button_down) {
- // set both (x1,y1) and (x2,y2) to this point
- _vm->_debugger->_rectX1 = _vm->_debugger->_rectX2 = (uint32)_pos.x + screenInfo->scroll_offset_x;
- _vm->_debugger->_rectY1 = _vm->_debugger->_rectY2 = (uint32)_pos.y + screenInfo->scroll_offset_y;
- _vm->_debugger->_draggingRectangle = 1;
- }
- } else if (_vm->_debugger->_draggingRectangle == 1) {
- // currently dragging a rectangle - click means reset
-
- if (button_down) {
- // lock rectangle, so you can let go of mouse
- // to type in the coords
- _vm->_debugger->_draggingRectangle = 2;
- } else {
- // drag rectangle
- _vm->_debugger->_rectX2 = (uint32)_pos.x + screenInfo->scroll_offset_x;
- _vm->_debugger->_rectY2 = (uint32)_pos.y + screenInfo->scroll_offset_y;
- }
- } else {
- // currently locked to avoid knocking out of place
- // while reading off the coords
-
- if (button_down) {
- // click means reset - back to start again
- _vm->_debugger->_draggingRectangle = 0;
- }
- }
-
- return;
- }
-
-#if RIGHT_CLICK_CLEARS_LUGGAGE
- if (_vm->_logic->readVar(OBJECT_HELD) && (me->buttons & RD_RIGHTBUTTONDOWN) && heldIsInInventory()) {
- _vm->_logic->writeVar(OBJECT_HELD, 0);
- _menuSelectedPos = 0;
- setLuggage(0);
- return;
- }
-#endif
-
- // Now do the normal click stuff
-
- // We only care about down clicks when the mouse is over an object.
-
- if (!_mouseTouching || !button_down)
- return;
-
- // There's a mouse event to be processed and the mouse is on something.
- // Notice that the floor itself is considered an object.
-
- // There are no menus about so its nice and simple. This is as close to
- // the old advisor_188 script as we get, I'm sorry to say.
-
- // If player is walking or relaxing then those need to terminate
- // correctly. Otherwise set player run the targets action script or, do
- // a special walk if clicking on the scroll-more icon
-
- // PLAYER_ACTION script variable - whatever catches this must reset to
- // 0 again
- // _vm->_logic->writeVar(PLAYER_ACTION, _mouseTouching);
-
- // Idle or router-anim will catch it
-
- // Set global script variable 'button'
-
- if (me->buttons & RD_LEFTBUTTONDOWN) {
- _vm->_logic->writeVar(LEFT_BUTTON, 1);
- _vm->_logic->writeVar(RIGHT_BUTTON, 0);
- _buttonClick = 0; // for re-click
- } else {
- _vm->_logic->writeVar(LEFT_BUTTON, 0);
- _vm->_logic->writeVar(RIGHT_BUTTON, 1);
- _buttonClick = 1; // for re-click
- }
-
- // These might be required by the action script about to be run
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- _vm->_logic->writeVar(MOUSE_X, _pos.x + screenInfo->scroll_offset_x);
- _vm->_logic->writeVar(MOUSE_Y, _pos.y + screenInfo->scroll_offset_y);
-
- if (_mouseTouching == _vm->_logic->readVar(EXIT_CLICK_ID) && (me->buttons & RD_LEFTBUTTONDOWN)) {
- // It's the exit double click situation. Let the existing
- // interaction continue and start fading down. Switch the human
- // off too
-
- noHuman();
- _vm->_logic->fnFadeDown(NULL);
-
- // Tell the walker
-
- _vm->_logic->writeVar(EXIT_FADING, 1);
- } else if (_oldButton == _buttonClick && _mouseTouching == _vm->_logic->readVar(CLICKED_ID) && _mousePointerRes != NORMAL_MOUSE_ID) {
- // Re-click. Do nothing, except on floors
- } else {
- // For re-click
-
- _oldButton = _buttonClick;
-
- // For scripts to know what's been clicked. First used for
- // 'room_13_turning_script' in object 'biscuits_13'
-
- _vm->_logic->writeVar(CLICKED_ID, _mouseTouching);
-
- // Must clear these two double-click control flags - do it here
- // so reclicks after exit clicks are cleared up
-
- _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
- _vm->_logic->writeVar(EXIT_FADING, 0);
-
- _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
-
- byte buf1[NAME_LEN], buf2[NAME_LEN];
-
- if (_vm->_logic->readVar(OBJECT_HELD))
- debug(2, "Used \"%s\" on \"%s\"",
- _vm->_resman->fetchName(_vm->_logic->readVar(OBJECT_HELD), buf1),
- _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf2));
- else if (_vm->_logic->readVar(LEFT_BUTTON))
- debug(2, "Left-clicked on \"%s\"",
- _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf1));
- else // RIGHT BUTTON
- debug(2, "Right-clicked on \"%s\"",
- _vm->_resman->fetchName(_vm->_logic->readVar(CLICKED_ID), buf1));
- }
-}
-
-uint32 Mouse::chooseMouse() {
- // Unlike the other mouse "engines", this one is called directly by the
- // fnChoose() opcode.
-
- uint i;
-
- _vm->_logic->writeVar(AUTO_SELECTED, 0);
-
- uint32 in_subject = _vm->_logic->readVar(IN_SUBJECT);
- uint32 object_held = _vm->_logic->readVar(OBJECT_HELD);
-
- if (object_held) {
- // The player used an object on a person. In this case it
- // triggered a conversation menu. Act as if the user tried to
- // talk to the person about that object. If the person doesn't
- // know anything about it, use the default response.
-
- uint32 response = _defaultResponseId;
-
- for (i = 0; i < in_subject; i++) {
- if (_subjectList[i].res == object_held) {
- response = _subjectList[i].ref;
- break;
- }
- }
-
- // The user won't be holding the object any more, and the
- // conversation menu will be closed.
-
- _vm->_logic->writeVar(OBJECT_HELD, 0);
- _vm->_logic->writeVar(IN_SUBJECT, 0);
- return response;
- }
-
- if (_vm->_logic->readVar(CHOOSER_COUNT_FLAG) == 0 && in_subject == 1 && _subjectList[0].res == EXIT_ICON) {
- // This is the first time the chooser is coming up in this
- // conversation, there is only one subject and that's the
- // EXIT icon.
- //
- // In other words, the player doesn't have anything to talk
- // about. Skip it.
-
- // The conversation menu will be closed. We set AUTO_SELECTED
- // because the speech script depends on it.
-
- _vm->_logic->writeVar(AUTO_SELECTED, 1);
- _vm->_logic->writeVar(IN_SUBJECT, 0);
- return _subjectList[0].ref;
- }
-
- byte *icon;
-
- if (!_choosing) {
- // This is a new conversation menu.
-
- if (!in_subject)
- error("fnChoose with no subjects");
-
- for (i = 0; i < in_subject; i++) {
- icon = _vm->_resman->openResource(_subjectList[i].res) + ResHeader::size() + RDMENU_ICONWIDE * RDMENU_ICONDEEP;
- setMenuIcon(RDMENU_BOTTOM, i, icon);
- _vm->_resman->closeResource(_subjectList[i].res);
- }
-
- for (; i < 15; i++)
- setMenuIcon(RDMENU_BOTTOM, (uint8) i, NULL);
-
- showMenu(RDMENU_BOTTOM);
- setMouse(NORMAL_MOUSE_ID);
- _choosing = true;
- return (uint32)-1;
- }
-
- // The menu is there - we're just waiting for a click. We only care
- // about left clicks.
-
- MouseEvent *me = _vm->mouseEvent();
- int mouseX, mouseY;
-
- getPos(mouseX, mouseY);
-
- if (!me || !(me->buttons & RD_LEFTBUTTONDOWN) || mouseY < 400)
- return (uint32)-1;
-
- // Check for click on a menu.
-
- int hit = _vm->_mouse->menuClick(in_subject);
- if (hit < 0)
- return (uint32)-1;
-
- // Hilight the clicked icon by greying the others. This can look a bit
- // odd when you click on the exit icon, but there are also cases when
- // it looks strange if you don't do it.
-
- for (i = 0; i < in_subject; i++) {
- if ((int)i != hit) {
- icon = _vm->_resman->openResource(_subjectList[i].res) + ResHeader::size();
- _vm->_mouse->setMenuIcon(RDMENU_BOTTOM, i, icon);
- _vm->_resman->closeResource(_subjectList[i].res);
- }
- }
-
- // For non-speech scripts that manually call the chooser
- _vm->_logic->writeVar(RESULT, _subjectList[hit].res);
-
- // The conversation menu will be closed
-
- _choosing = false;
- _vm->_logic->writeVar(IN_SUBJECT, 0);
- setMouse(0);
-
- return _subjectList[hit].ref;
-}
-
-void Mouse::mouseOnOff() {
- // this handles the cursor graphic when moving on and off mouse areas
- // it also handles the luggage thingy
-
- uint32 pointer_type;
- static uint8 mouse_flicked_off = 0;
-
- _oldMouseTouching = _mouseTouching;
-
- // don't detect objects that are hidden behind the menu bars (ie. in
- // the scrolled-off areas of the screen)
-
- if (_pos.y < 0 || _pos.y > 399) {
- pointer_type = 0;
- _mouseTouching = 0;
- } else {
- // set '_mouseTouching' & return pointer_type
- pointer_type = checkMouseList();
- }
-
- // same as previous cycle?
- if (!mouse_flicked_off && _oldMouseTouching == _mouseTouching) {
- // yes, so nothing to do
- // BUT CARRY ON IF MOUSE WAS FLICKED OFF!
- return;
- }
-
- // can reset this now
- mouse_flicked_off = 0;
-
- //the cursor has moved onto something
- if (!_oldMouseTouching && _mouseTouching) {
- // make a copy of the object we've moved onto because one day
- // we'll move back off again! (but the list positioning could
- // theoretically have changed)
-
- // we can only move onto something from being on nothing - we
- // stop the system going from one to another when objects
- // overlap
-
- _oldMouseTouching = _mouseTouching;
-
- // run get on
-
- if (pointer_type) {
- // 'pointer_type' holds the resource id of the
- // pointer anim
-
- setMouse(pointer_type);
-
- // setup luggage icon
- if (_vm->_logic->readVar(OBJECT_HELD)) {
- setLuggage(_currentLuggageResource);
- }
- } else {
- byte buf[NAME_LEN];
-
- error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, _vm->_resman->fetchName(_mouseTouching, buf));
- }
- } else if (_oldMouseTouching && !_mouseTouching) {
- // the cursor has moved off something - reset cursor to
- // normal pointer
-
- _oldMouseTouching = 0;
- setMouse(NORMAL_MOUSE_ID);
-
- // reset luggage only when necessary
- } else if (_oldMouseTouching && _mouseTouching) {
- // The cursor has moved off something and onto something
- // else. Flip to a blank cursor for a cycle.
-
- // ignore the new id this cycle - should hit next cycle
- _mouseTouching = 0;
- _oldMouseTouching = 0;
- setMouse(0);
-
- // so we know to set the mouse pointer back to normal if 2nd
- // hot-spot doesn't register because mouse pulled away
- // quickly (onto nothing)
-
- mouse_flicked_off = 1;
-
- // reset luggage only when necessary
- } else {
- // Mouse was flicked off for one cycle, but then moved onto
- // nothing before 2nd hot-spot registered
-
- // both '_oldMouseTouching' & '_mouseTouching' will be zero
- // reset cursor to normal pointer
-
- setMouse(NORMAL_MOUSE_ID);
- }
-
- // possible check for edge of screen more-to-scroll here on large
- // screens
-}
-
-void Mouse::setMouse(uint32 res) {
- // high level - whats the mouse - for the engine
- _mousePointerRes = res;
-
- if (res) {
- byte *icon = _vm->_resman->openResource(res) + ResHeader::size();
- uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();
-
- // don't pulse the normal pointer - just do the regular anim
- // loop
-
- if (res == NORMAL_MOUSE_ID)
- setMouseAnim(icon, len, RDMOUSE_NOFLASH);
- else
- setMouseAnim(icon, len, RDMOUSE_FLASH);
-
- _vm->_resman->closeResource(res);
- } else {
- // blank cursor
- setMouseAnim(NULL, 0, 0);
- }
-}
-
-void Mouse::setLuggage(uint32 res) {
- _realLuggageItem = res;
-
- if (res) {
- byte *icon = _vm->_resman->openResource(res) + ResHeader::size();
- uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();
-
- setLuggageAnim(icon, len);
- _vm->_resman->closeResource(res);
- } else
- setLuggageAnim(NULL, 0);
-}
-
-void Mouse::setObjectHeld(uint32 res) {
- setLuggage(res);
-
- _vm->_logic->writeVar(OBJECT_HELD, res);
- _currentLuggageResource = res;
-
- // mode locked - no menu available
- _mouseModeLocked = true;
-}
-
-uint32 Mouse::checkMouseList() {
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- Common::Point mousePos(_pos.x + screenInfo->scroll_offset_x, _pos.y + screenInfo->scroll_offset_y);
-
- // Number of priorities subject to implementation needs
- for (int priority = 0; priority < 10; priority++) {
- for (uint i = 0; i < _curMouse; i++) {
- // If the mouse pointer is over this
- // mouse-detection-box
-
- if (_mouseList[i].priority == priority && _mouseList[i].rect.contains(mousePos)) {
- // Record id
- _mouseTouching = _mouseList[i].id;
-
- createPointerText(_mouseList[i].pointer_text, _mouseList[i].pointer);
-
- // Return pointer type
- return _mouseList[i].pointer;
- }
- }
- }
-
- // Touching nothing; no pointer to return
- _mouseTouching = 0;
- return 0;
-}
-
-#define POINTER_TEXT_WIDTH 640 // just in case!
-#define POINTER_TEXT_PEN 184 // white
-
-void Mouse::createPointerText(uint32 text_id, uint32 pointer_res) {
- uint32 local_text;
- uint32 text_res;
- byte *text;
- // offsets for pointer text sprite from pointer position
- int16 xOffset, yOffset;
- uint8 justification;
-
- if (!_objectLabels || !text_id)
- return;
-
- // Check what the pointer is, to set offsets correctly for text
- // position
-
- switch (pointer_res) {
- case CROSHAIR:
- yOffset = -7;
- xOffset = +10;
- break;
- case EXIT0:
- yOffset = +15;
- xOffset = +20;
- break;
- case EXIT1:
- yOffset = +16;
- xOffset = -10;
- break;
- case EXIT2:
- yOffset = +10;
- xOffset = -22;
- break;
- case EXIT3:
- yOffset = -16;
- xOffset = -10;
- break;
- case EXIT4:
- yOffset = -15;
- xOffset = +15;
- break;
- case EXIT5:
- yOffset = -12;
- xOffset = +10;
- break;
- case EXIT6:
- yOffset = +10;
- xOffset = +25;
- break;
- case EXIT7:
- yOffset = +16;
- xOffset = +20;
- break;
- case EXITDOWN:
- yOffset = -20;
- xOffset = -10;
- break;
- case EXITUP:
- yOffset = +20;
- xOffset = +20;
- break;
- case MOUTH:
- yOffset = -10;
- xOffset = +15;
- break;
- case NORMAL:
- yOffset = -10;
- xOffset = +15;
- break;
- case PICKUP:
- yOffset = -40;
- xOffset = +10;
- break;
- case SCROLL_L:
- yOffset = -20;
- xOffset = +20;
- break;
- case SCROLL_R:
- yOffset = -20;
- xOffset = -20;
- break;
- case USE:
- yOffset = -8;
- xOffset = +20;
- break;
- default:
- // Shouldn't happen if we cover all the different mouse
- // pointers above
- yOffset = -10;
- xOffset = +10;
- break;
- }
-
- // Set up justification for text sprite, based on its offsets from the
- // pointer position
-
- if (yOffset < 0) {
- // Above pointer
- if (xOffset < 0) {
- // Above left
- justification = POSITION_AT_RIGHT_OF_BASE;
- } else if (xOffset > 0) {
- // Above right
- justification = POSITION_AT_LEFT_OF_BASE;
- } else {
- // Above centre
- justification = POSITION_AT_CENTRE_OF_BASE;
- }
- } else if (yOffset > 0) {
- // Below pointer
- if (xOffset < 0) {
- // Below left
- justification = POSITION_AT_RIGHT_OF_TOP;
- } else if (xOffset > 0) {
- // Below right
- justification = POSITION_AT_LEFT_OF_TOP;
- } else {
- // Below centre
- justification = POSITION_AT_CENTRE_OF_TOP;
- }
- } else {
- // Same y-coord as pointer
- if (xOffset < 0) {
- // Centre left
- justification = POSITION_AT_RIGHT_OF_CENTRE;
- } else if (xOffset > 0) {
- // Centre right
- justification = POSITION_AT_LEFT_OF_CENTRE;
- } else {
- // Centre centre - shouldn't happen anyway!
- justification = POSITION_AT_LEFT_OF_CENTRE;
- }
- }
-
- // Text resource number, and line number within the resource
-
- text_res = text_id / SIZE;
- local_text = text_id & 0xffff;
-
- // open text file & get the line
- text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
-
- // 'text+2' to skip the first 2 bytes which form the
- // line reference number
-
- _pointerTextBlocNo = _vm->_fontRenderer->buildNewBloc(
- text + 2, _pos.x + xOffset,
- _pos.y + yOffset,
- POINTER_TEXT_WIDTH, POINTER_TEXT_PEN,
- RDSPR_TRANS | RDSPR_DISPLAYALIGN,
- _vm->_speechFontId, justification);
-
- // now ok to close the text file
- _vm->_resman->closeResource(text_res);
-}
-
-void Mouse::clearPointerText() {
- if (_pointerTextBlocNo) {
- _vm->_fontRenderer->killTextBloc(_pointerTextBlocNo);
- _pointerTextBlocNo = 0;
- }
-}
-
-void Mouse::hideMouse() {
- // leaves the menus open
- // used by the system when clicking right on a menu item to examine
- // it and when combining objects
-
- // for logic scripts
- _vm->_logic->writeVar(MOUSE_AVAILABLE, 0);
-
- // human/mouse off
- _mouseStatus = true;
-
- setMouse(0);
- setLuggage(0);
-}
-
-void Mouse::noHuman() {
- hideMouse();
- clearPointerText();
-
- // Must be normal mouse situation or a largely neutral situation -
- // special menus use hideMouse()
-
- // Don't hide menu in conversations
- if (_vm->_logic->readVar(TALK_FLAG) == 0)
- hideMenu(RDMENU_BOTTOM);
-
- if (_mouseMode == MOUSE_system_menu) {
- // Close menu
- _mouseMode = MOUSE_normal;
- hideMenu(RDMENU_TOP);
- }
-}
-
-void Mouse::addHuman() {
- // For logic scripts
- _vm->_logic->writeVar(MOUSE_AVAILABLE, 1);
-
- if (_mouseStatus) {
- // Force engine to choose a cursor
- _mouseStatus = false;
- _mouseTouching = 1;
- }
-
- // Clear this to reset no-second-click system
- _vm->_logic->writeVar(CLICKED_ID, 0);
-
- // This is now done outside the OBJECT_HELD check in case it's set to
- // zero before now!
-
- // Unlock the mouse from possible large object lock situtations - see
- // syphon in rm 3
-
- _mouseModeLocked = false;
-
- if (_vm->_logic->readVar(OBJECT_HELD)) {
- // Was dragging something around - need to clear this again
- _vm->_logic->writeVar(OBJECT_HELD, 0);
-
- // And these may also need clearing, just in case
- _examiningMenuIcon = false;
- _vm->_logic->writeVar(COMBINE_BASE, 0);
-
- setLuggage(0);
- }
-
- // If mouse is over menu area
- if (_pos.y > 399) {
- if (_mouseMode != MOUSE_holding) {
- // VITAL - reset things & rebuild the menu
- _mouseMode = MOUSE_normal;
- }
- setMouse(NORMAL_MOUSE_ID);
- }
-
- // Enabled/disabled from console; status printed with on-screen debug
- // info
-
- if (_vm->_debugger->_testingSnR) {
- uint8 black[4] = { 0, 0, 0, 0 };
- uint8 white[4] = { 255, 255, 255, 0 };
-
- // Testing logic scripts by simulating instant Save & Restore
-
- _vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
-
- // Stops all fx & clears the queue - eg. when leaving a room
- _vm->_sound->clearFxQueue();
-
- // Trash all object resources so they load in fresh & restart
- // their logic scripts
-
- _vm->_resman->killAllObjects(false);
-
- _vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
- }
-}
-
-void Mouse::refreshInventory() {
- // Can reset this now
- _vm->_logic->writeVar(COMBINE_BASE, 0);
-
- // Cause 'object_held' icon to be greyed. The rest are coloured.
- _examiningMenuIcon = true;
- buildMenu();
- _examiningMenuIcon = false;
-}
-
-void Mouse::startConversation() {
- if (_vm->_logic->readVar(TALK_FLAG) == 0) {
- // See fnChooser & speech scripts
- _vm->_logic->writeVar(CHOOSER_COUNT_FLAG, 0);
- }
-
- noHuman();
-}
-
-void Mouse::endConversation() {
- hideMenu(RDMENU_BOTTOM);
-
- if (_pos.y > 399) {
- // Will wait for cursor to move off the bottom menu
- _mouseMode = MOUSE_holding;
- }
-
- // In case DC forgets
- _vm->_logic->writeVar(TALK_FLAG, 0);
-}
-
-void Mouse::monitorPlayerActivity() {
- // if there is at least one mouse event outstanding
- if (_vm->checkForMouseEvents()) {
- // reset activity delay counter
- _playerActivityDelay = 0;
- } else {
- // no. of game cycles since mouse event queue last empty
- _playerActivityDelay++;
- }
-}
-
-void Mouse::checkPlayerActivity(uint32 seconds) {
- // Convert seconds to game cycles
- uint32 threshold = seconds * 12;
-
- // If the actual delay is at or above the given threshold, reset the
- // activity delay counter now that we've got a positive check.
-
- if (_playerActivityDelay >= threshold) {
- _playerActivityDelay = 0;
- _vm->_logic->writeVar(RESULT, 1);
- } else
- _vm->_logic->writeVar(RESULT, 0);
-}
-
-void Mouse::pauseGame() {
- // Make the mouse cursor normal. This is the only place where we are
- // allowed to clear the luggage this way.
-
- clearPointerText();
- setLuggageAnim(NULL, 0);
- setMouse(0);
- setMouseTouching(1);
-}
-
-void Mouse::unpauseGame() {
- if (_vm->_logic->readVar(OBJECT_HELD) && _realLuggageItem)
- setLuggage(_realLuggageItem);
-}
-
-} // End of namespace Sword2
diff --git a/sword2/mouse.h b/sword2/mouse.h
deleted file mode 100644
index bed5e032ba..0000000000
--- a/sword2/mouse.h
+++ /dev/null
@@ -1,257 +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 MOUSE_H
-#define MOUSE_H
-
-#define MAX_SUBJECT_LIST 30 // is that enough?
-
-#define TOTAL_mouse_list 50
-
-namespace Sword2 {
-
-struct BuildUnit;
-
-// Menubar defines.
-
-#define RDMENU_TOP 0
-#define RDMENU_BOTTOM 1
-
-enum {
- MOUSE_normal = 0, // normal in game
- MOUSE_menu = 1, // menu chooser
- MOUSE_drag = 2, // dragging luggage
- MOUSE_system_menu = 3, // system menu chooser
- MOUSE_holding = 4 // special
-};
-
-enum {
- RDMOUSE_NOFLASH,
- RDMOUSE_FLASH
-};
-
-enum {
- RDMENU_HIDDEN,
- RDMENU_SHOWN,
- RDMENU_OPENING,
- RDMENU_CLOSING,
- RDMENU_ALMOST_HIDDEN
-};
-
-#define RDMENU_ICONWIDE 35
-#define RDMENU_ICONDEEP 30
-#define RDMENU_ICONSTART 24
-#define RDMENU_ICONSPACING 5
-#define RDMENU_MAXPOCKETS 15
-
-#define MOUSE_ANIM_HEADER_SIZE 6
-
-struct MouseAnim {
- uint8 runTimeComp; // type of runtime compression used for the
- // frame data
- uint8 noAnimFrames; // number of frames in the anim
- int8 xHotSpot;
- int8 yHotSpot;
- uint8 mousew;
- uint8 mouseh;
-
- byte *data;
-};
-
-// The MOUSE_holding mode is entered when the conversation menu is closed, and
-// exited when the mouse cursor moves off that menu area. I don't know why yet.
-
-// mouse unit - like ObjectMouse, but with anim resource & pc (needed if
-// sprite is to act as mouse detection mask)
-
-struct MouseUnit {
- // Basically the same information as in ObjectMouse, except the
- // coordinates are adjusted to conform to standard ScummVM usage.
-
- Common::Rect rect;
- int32 priority;
- int32 pointer;
-
- // In addition, we need an id when checking the mouse list, and a
- // text id for mouse-overs.
-
- int32 id;
- int32 pointer_text;
-};
-
-// Array of these for subject menu build up
-
- struct SubjectUnit {
- uint32 res;
- uint32 ref;
-};
-
-class Mouse {
-private:
- Sword2Engine *_vm;
-
- Common::Point _pos;
-
- MouseUnit _mouseList[TOTAL_mouse_list];
- uint32 _curMouse;
-
- MenuObject _tempList[TOTAL_engine_pockets];
- uint32 _totalTemp;
-
- MenuObject _masterMenuList[TOTAL_engine_pockets];
- uint32 _totalMasters;
-
- SubjectUnit _subjectList[MAX_SUBJECT_LIST];
-
- // ref number for default response when luggage icon is used on a
- // person & it doesn't match any of the icons which would have been in
- // the chooser
-
- uint32 _defaultResponseId;
-
- // could alternately use logic->looping of course
- bool _choosing;
-
- uint8 _menuStatus[2];
- byte *_icons[2][RDMENU_MAXPOCKETS];
- uint8 _pocketStatus[2][RDMENU_MAXPOCKETS];
-
- uint8 _iconCount;
-
- // If it's NORMAL_MOUSE_ID (ie. normal pointer) then it's over a floor
- // area (or hidden hot-zone)
-
- uint32 _mousePointerRes;
-
- MouseAnim _mouseAnim;
- MouseAnim _luggageAnim;
-
- uint8 _mouseFrame;
-
- uint32 _mouseMode;
-
- bool _mouseStatus; // Human 0 on/1 off
- bool _mouseModeLocked; // 0 not !0 mode cannot be changed from
- // normal mouse to top menu (i.e. when
- // carrying big objects)
- uint32 _realLuggageItem; // Last minute for pause mode
- uint32 _currentLuggageResource;
- uint32 _oldButton; // For the re-click stuff - must be
- // the same button you see
- uint32 _buttonClick;
- uint32 _pointerTextBlocNo;
- uint32 _playerActivityDelay; // Player activity delay counter
-
- bool _examiningMenuIcon;
-
- // Set by checkMouseList()
- uint32 _mouseTouching;
- uint32 _oldMouseTouching;
-
- bool _objectLabels;
-
- uint32 _menuSelectedPos;
-
- void decompressMouse(byte *decomp, byte *comp, uint8 frame, int width, int height, int pitch, int xOff = 0, int yOff = 0);
-
- int32 setMouseAnim(byte *ma, int32 size, int32 mouseFlash);
- int32 setLuggageAnim(byte *la, int32 size);
-
- void clearIconArea(int menu, int pocket, Common::Rect *r);
-
-public:
- Mouse(Sword2Engine *vm);
- ~Mouse();
-
- void getPos(int &x, int &y);
- void setPos(int x, int y);
-
- bool getObjectLabels() { return _objectLabels; }
- void setObjectLabels(bool b) { _objectLabels = b; }
-
- bool getMouseStatus() { return _mouseStatus; }
- uint32 getMouseTouching() { return _mouseTouching; }
- void setMouseTouching(uint32 touching) { _mouseTouching = touching; }
-
- void pauseGame();
- void unpauseGame();
-
- void setMouse(uint32 res);
- void setLuggage(uint32 res);
-
- void setObjectHeld(uint32 res);
-
- void resetMouseList();
-
- void registerMouse(byte *ob_mouse, BuildUnit *build_unit);
- void registerPointerText(int32 text_id);
-
- void createPointerText(uint32 text_id, uint32 pointer_res);
- void clearPointerText();
-
- void drawMouse();
- int32 animateMouse();
-
- void processMenu();
-
- void addMenuObject(byte *ptr);
- void addSubject(int32 id, int32 ref);
-
- void buildMenu();
- void buildSystemMenu();
-
- int32 showMenu(uint8 menu);
- int32 hideMenu(uint8 menu);
- int32 setMenuIcon(uint8 menu, uint8 pocket, byte *icon);
-
- void closeMenuImmediately();
-
- void refreshInventory();
-
- void startConversation();
- void endConversation();
-
- void hideMouse();
- void noHuman();
- void addHuman();
-
- void resetPlayerActivityDelay() { _playerActivityDelay = 0; }
- void monitorPlayerActivity();
- void checkPlayerActivity(uint32 seconds);
-
- void mouseOnOff();
- uint32 checkMouseList();
- void mouseEngine();
-
- void normalMouse();
- void menuMouse();
- void dragMouse();
- void systemMenuMouse();
-
- bool isChoosing() { return _choosing; }
- uint32 chooseMouse();
-
- int menuClick(int menu_items);
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/music.cpp b/sword2/music.cpp
deleted file mode 100644
index 847f4808cf..0000000000
--- a/sword2/music.cpp
+++ /dev/null
@@ -1,856 +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$
- */
-
-// One feature still missing is the original's DipMusic() function which, as
-// far as I can understand, softened the music volume when someone was
-// speaking, but only (?) if the music was playing loudly at the time.
-//
-// All things considered, I think this is more bother than it's worth.
-
-#include "common/stdafx.h"
-#include "common/file.h"
-#include "common/system.h"
-#include "sound/mp3.h"
-#include "sound/vorbis.h"
-#include "sound/flac.h"
-#include "sound/rate.h"
-#include "sound/wave.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-namespace Sword2 {
-
-static AudioStream *makeCLUStream(Common::File *fp, int size);
-
-static AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) {
- debug(3, "Playing %s from CD %d", base, cd);
-
- if (!fh->file.isOpen()) {
- struct {
- const char *ext;
- int mode;
- } file_types[] = {
- #ifdef USE_MAD
- { "cl3", kMP3Mode },
- #endif
- #ifdef USE_VORBIS
- { "clg", kVorbisMode },
- #endif
- #ifdef USE_FLAC
- { "clf", kFlacMode },
- #endif
- { "clu", kCLUMode }
- };
-
- int soundMode = 0;
- char filename[20];
-
- for (int i = 0; i < ARRAYSIZE(file_types); i++) {
- Common::File f;
-
- sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext);
- if (f.open(filename)) {
- soundMode = file_types[i].mode;
- break;
- }
-
- sprintf(filename, "%s.%s", base, file_types[i].ext);
- if (f.open(filename)) {
- soundMode = file_types[i].mode;
- break;
- }
- }
-
- if (soundMode == 0)
- return NULL;
-
- fh->file.open(filename);
- fh->fileType = soundMode;
- if (!fh->file.isOpen()) {
- warning("Very strange fopen error");
- return NULL;
- }
- if (fh->fileSize != fh->file.size()) {
- if (fh->idxTab) {
- free(fh->idxTab);
- fh->idxTab = NULL;
- }
- }
- }
-
- uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3;
-
- if (!fh->idxTab) {
- fh->file.seek(0);
- fh->idxLen = fh->file.readUint32LE();
- fh->file.seek(entrySize * 4);
-
- fh->idxTab = (uint32*)malloc(fh->idxLen * 3 * sizeof(uint32));
- for (uint32 cnt = 0; cnt < fh->idxLen; cnt++) {
- fh->idxTab[cnt * 3 + 0] = fh->file.readUint32LE();
- fh->idxTab[cnt * 3 + 1] = fh->file.readUint32LE();
- if (fh->fileType == kCLUMode) {
- fh->idxTab[cnt * 3 + 2] = fh->idxTab[cnt * 3 + 1];
- fh->idxTab[cnt * 3 + 1]--;
- } else
- fh->idxTab[cnt * 3 + 2] = fh->file.readUint32LE();
- }
- }
-
- uint32 pos = fh->idxTab[id * 3 + 0];
- uint32 len = fh->idxTab[id * 3 + 1];
- uint32 enc_len = fh->idxTab[id * 3 + 2];
-
- if (numSamples)
- *numSamples = len;
-
- if (!pos || !len) {
- fh->file.close();
- return NULL;
- }
-
- fh->file.seek(pos, SEEK_SET);
-
- switch (fh->fileType) {
- case kCLUMode:
- return makeCLUStream(&fh->file, enc_len);
-#ifdef USE_MAD
- case kMP3Mode:
- return makeMP3Stream(&fh->file, enc_len);
-#endif
-#ifdef USE_VORBIS
- case kVorbisMode:
- return makeVorbisStream(&fh->file, enc_len);
-#endif
-#ifdef USE_FLAC
- case kFlacMode:
- return makeFlacStream(&fh->file, enc_len);
-#endif
- default:
- return NULL;
- }
-}
-
-// ----------------------------------------------------------------------------
-// Custom AudioStream class to handle Broken Sword 2's audio compression.
-// ----------------------------------------------------------------------------
-
-#define GetCompressedShift(n) ((n) >> 4)
-#define GetCompressedSign(n) (((n) >> 3) & 1)
-#define GetCompressedAmplitude(n) ((n) & 7)
-
-CLUInputStream::CLUInputStream(Common::File *file, int size)
- : _file(file), _firstTime(true), _bufferEnd(_outbuf + BUFFER_SIZE) {
-
- _file->incRef();
-
- // Determine the end position.
- _file_pos = _file->pos();
- _end_pos = _file_pos + size;
-
- // Read in initial data
- refill();
-}
-
-CLUInputStream::~CLUInputStream() {
- _file->decRef();
-}
-
-int CLUInputStream::readBuffer(int16 *buffer, const int numSamples) {
- int samples = 0;
- while (samples < numSamples && !eosIntern()) {
- const int len = MIN(numSamples - samples, (int)(_bufferEnd - _pos));
- memcpy(buffer, _pos, len * 2);
- buffer += len;
- _pos += len;
- samples += len;
- if (_pos >= _bufferEnd) {
- refill();
- }
- }
- return samples;
-}
-
-void CLUInputStream::refill() {
- byte *in = _inbuf;
- int16 *out = _outbuf;
-
- _file->seek(_file_pos, SEEK_SET);
-
- uint len_left = _file->read(in, MIN((uint32)BUFFER_SIZE, _end_pos - _file->pos()));
-
- _file_pos = _file->pos();
-
- while (len_left > 0) {
- uint16 sample;
-
- if (_firstTime) {
- _firstTime = false;
- _prev = READ_LE_UINT16(in);
- sample = _prev;
- len_left -= 2;
- in += 2;
- } else {
- uint16 delta = GetCompressedAmplitude(*in) << GetCompressedShift(*in);
- if (GetCompressedSign(*in))
- sample = _prev - delta;
- else
- sample = _prev + delta;
-
- _prev = sample;
- len_left--;
- in++;
- }
-
- *out++ = sample;
- }
-
- _pos = _outbuf;
- _bufferEnd = out;
-}
-
-AudioStream *makeCLUStream(Common::File *file, int size) {
- return new CLUInputStream(file, size);
-}
-
-// ----------------------------------------------------------------------------
-// Another custom AudioStream class, to wrap around the various AudioStream
-// classes used for music decompression, and to add looping, fading, etc.
-// ----------------------------------------------------------------------------
-
-// The length of a fade-in/out, in milliseconds.
-#define FADE_LENGTH 3000
-
-MusicInputStream::MusicInputStream(int cd, SoundFileHandle *fh, uint32 musicId, bool looping) {
- _cd = cd;
- _fh = fh;
- _musicId = musicId;
- _looping = looping;
-
- _bufferEnd = _buffer + BUFFER_SIZE;
- _remove = false;
- _fading = 0;
-
- _decoder = getAudioStream(_fh, "music", _cd, _musicId, &_numSamples);
- if (_decoder) {
- _samplesLeft = _numSamples;
- _fadeSamples = (getRate() * FADE_LENGTH) / 1000;
- fadeUp();
-
- // Read in initial data
- refill();
- }
-}
-
-MusicInputStream::~MusicInputStream() {
- delete _decoder;
-}
-
-int MusicInputStream::readBuffer(int16 *buffer, const int numSamples) {
- if (!_decoder)
- return 0;
-
- int samples = 0;
- while (samples < numSamples && !eosIntern()) {
- const int len = MIN(numSamples - samples, (int)(_bufferEnd - _pos));
- memcpy(buffer, _pos, len * 2);
- buffer += len;
- _pos += len;
- samples += len;
- if (_pos >= _bufferEnd) {
- refill();
- }
- }
- return samples;
-}
-
-void MusicInputStream::refill() {
- int16 *buf = _buffer;
- uint32 numSamples = 0;
- uint32 len_left;
- bool endFade = false;
-
- len_left = BUFFER_SIZE;
-
- if (_fading > 0 && (uint32)_fading < len_left)
- len_left = _fading;
-
- if (_samplesLeft < len_left)
- len_left = _samplesLeft;
-
- if (!_looping) {
- // Non-looping music is faded out at the end. If this fade
- // out would have started somewhere within the len_left samples
- // to read, we only read up to that point. This way, we can
- // treat this fade as any other.
-
- if (!_fading) {
- uint32 currentlyAt = _numSamples - _samplesLeft;
- uint32 fadeOutAt = _numSamples - _fadeSamples;
- uint32 readTo = currentlyAt + len_left;
-
- if (fadeOutAt == currentlyAt)
- fadeDown();
- else if (fadeOutAt > currentlyAt && fadeOutAt <= readTo) {
- len_left = fadeOutAt - currentlyAt;
- endFade = true;
- }
- }
- }
-
- int desired = len_left - numSamples;
- int len = _decoder->readBuffer(buf, desired);
-
- // Shouldn't happen, but if it does it could cause an infinite loop.
- // Of course there were bugs that caused it to happen several times
- // during development. :-)
-
- if (len < desired) {
- warning("Expected %d samples, but got %d", desired, len);
- _samplesLeft = len;
- }
-
- buf += len;
- numSamples += len;
- len_left -= len;
- _samplesLeft -= len;
-
- int16 *ptr;
-
- if (_fading > 0) {
- // Fade down
- for (ptr = _buffer; ptr < buf; ptr++) {
- if (_fading > 0) {
- _fading--;
- *ptr = (*ptr * _fading) / _fadeSamples;
- }
- if (_fading == 0) {
- _looping = false;
- _remove = true;
- *ptr = 0;
- }
- }
- } else if (_fading < 0) {
- // Fade up
- for (ptr = _buffer; ptr < buf; ptr++) {
- _fading--;
- *ptr = -(*ptr * _fading) / _fadeSamples;
- if (_fading <= -_fadeSamples) {
- _fading = 0;
- break;
- }
- }
- }
-
- if (endFade)
- fadeDown();
-
- if (!_samplesLeft) {
- if (_looping) {
- delete _decoder;
- _decoder = getAudioStream(_fh, "music", _cd, _musicId, &_numSamples);
- _samplesLeft = _numSamples;
- } else
- _remove = true;
- }
-
- _pos = _buffer;
- _bufferEnd = buf;
-}
-
-void MusicInputStream::fadeUp() {
- if (_fading > 0)
- _fading = -_fading;
- else if (_fading == 0)
- _fading = -1;
-}
-
-void MusicInputStream::fadeDown() {
- if (_fading < 0)
- _fading = -_fading;
- else if (_fading == 0)
- _fading = _fadeSamples;
-}
-
-bool MusicInputStream::readyToRemove() {
- return _remove;
-}
-
-int32 MusicInputStream::getTimeRemaining() {
- // This is far from exact, but it doesn't have to be.
- return (_samplesLeft + BUFFER_SIZE) / getRate();
-}
-
-// ----------------------------------------------------------------------------
-// Main sound class
-// ----------------------------------------------------------------------------
-
-// AudioStream API
-
-int Sound::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock lock(_mutex);
- int i;
-
- if (_musicPaused)
- return 0;
-
- for (i = 0; i < MAXMUS; i++) {
- if (_music[i] && _music[i]->readyToRemove()) {
- delete _music[i];
- _music[i] = NULL;
- }
- }
-
- memset(buffer, 0, 2 * numSamples);
-
- if (!_mixBuffer || numSamples > _mixBufferLen) {
- if (_mixBuffer)
- _mixBuffer = (int16 *)realloc(_mixBuffer, 2 * numSamples);
- else
- _mixBuffer = (int16 *)malloc(2 * numSamples);
-
- _mixBufferLen = numSamples;
- }
-
- if (!_mixBuffer)
- return 0;
-
- for (i = 0; i < MAXMUS; i++) {
- if (!_music[i])
- continue;
-
- int len = _music[i]->readBuffer(_mixBuffer, numSamples);
-
- if (!_musicMuted) {
- for (int j = 0; j < len; j++) {
- Audio::clampedAdd(buffer[j], _mixBuffer[j]);
- }
- }
- }
-
- bool inUse[MAXMUS];
-
- for (i = 0; i < MAXMUS; i++)
- inUse[i] = false;
-
- for (i = 0; i < MAXMUS; i++) {
- if (_music[i]) {
- if (_music[i]->getCD() == 1)
- inUse[0] = true;
- else
- inUse[1] = true;
- }
- }
-
- for (i = 0; i < MAXMUS; i++) {
- if (!inUse[i] && !_musicFile[i].inUse && _musicFile[i].file.isOpen())
- _musicFile[i].file.close();
- }
-
- return numSamples;
-}
-
-bool Sound::endOfData() const {
- for (int i = 0; i < MAXMUS; i++) {
- if (_musicFile[i].file.isOpen())
- return false;
- }
-
- return true;
-}
-
-// ----------------------------------------------------------------------------
-// MUSIC
-// ----------------------------------------------------------------------------
-
-/**
- * Stops the music dead in its tracks. Any music that is currently being
- * streamed is paused.
- */
-
-void Sound::pauseMusic() {
- Common::StackLock lock(_mutex);
-
- _musicPaused = true;
-}
-
-/**
- * Restarts the music from where it was stopped.
- */
-
-void Sound::unpauseMusic() {
- Common::StackLock lock(_mutex);
-
- _musicPaused = false;
-}
-
-/**
- * Fades out and stops the music.
- */
-
-void Sound::stopMusic(bool immediately) {
- Common::StackLock lock(_mutex);
-
- _loopingMusicId = 0;
-
- for (int i = 0; i < MAXMUS; i++) {
- if (_music[i]) {
- if (immediately) {
- delete _music[i];
- _music[i] = NULL;
- } else
- _music[i]->fadeDown();
- }
- }
-}
-
-/**
- * Streams music from a cluster file.
- * @param musicId the id of the music to stream
- * @param loop true if the music is to loop back to the start
- * @return RD_OK or an error code
- */
-int32 Sound::streamCompMusic(uint32 musicId, bool loop) {
- //Common::StackLock lock(_mutex);
-
- _mutex.lock();
- int cd = _vm->_resman->getCD();
-
- if (loop)
- _loopingMusicId = musicId;
- else
- _loopingMusicId = 0;
-
- int primary = -1;
- int secondary = -1;
-
- // If both music streams are active, one of them will have to go.
-
- if (_music[0] && _music[1]) {
- int32 fade0 = _music[0]->isFading();
- int32 fade1 = _music[1]->isFading();
-
- if (!fade0 && !fade1) {
- // Neither is fading. This shouldn't happen, so just
- // pick one and be done with it.
- primary = 0;
- } else if (fade0 && !fade1) {
- // Stream 0 is fading, so pick that one.
- primary = 0;
- } else if (!fade0 && fade1) {
- // Stream 1 is fading, so pick that one.
- primary = 1;
- } else {
- // Both streams are fading. Pick the one that is
- // closest to silent.
- if (ABS(fade0) < ABS(fade1))
- primary = 0;
- else
- primary = 1;
- }
-
- delete _music[primary];
- _music[primary] = NULL;
- }
-
- // Pick the available music stream. If no music is playing it doesn't
- // matter which we use.
-
- if (_music[0] || _music[1]) {
- if (_music[0]) {
- primary = 1;
- secondary = 0;
- } else {
- primary = 0;
- secondary = 1;
- }
- } else
- primary = 0;
-
- // Don't start streaming if the volume is off.
- if (isMusicMute()) {
- _mutex.unlock();
- return RD_OK;
- }
-
- if (secondary != -1)
- _music[secondary]->fadeDown();
- SoundFileHandle *fh = (cd == 1) ? &_musicFile[0] : &_musicFile[1];
- fh->inUse = true;
- _mutex.unlock();
-
- MusicInputStream *tmp = new MusicInputStream(cd, fh, musicId, loop);
-
- if (tmp->isReady()) {
- _mutex.lock();
- _music[primary] = tmp;
- fh->inUse = false;
- _mutex.unlock();
- return RD_OK;
- } else {
- _mutex.lock();
- fh->inUse = false;
- _mutex.unlock();
- delete tmp;
- return RDERR_INVALIDFILENAME;
- }
-}
-
-/**
- * @return the time left for the current music, in seconds.
- */
-
-int32 Sound::musicTimeRemaining() {
- Common::StackLock lock(_mutex);
-
- for (int i = 0; i < MAXMUS; i++) {
- if (_music[i] && _music[i]->isFading() <= 0)
- return _music[i]->getTimeRemaining();
- }
-
- return 0;
-}
-
-// ----------------------------------------------------------------------------
-// SPEECH
-// ----------------------------------------------------------------------------
-
-/**
- * Mutes/Unmutes the speech.
- * @param mute If mute is false, restore the volume to the last set master
- * level. Otherwise the speech is muted (volume 0).
- */
-
-void Sound::muteSpeech(bool mute) {
- _speechMuted = mute;
-
- if (_vm->_mixer->isSoundHandleActive(_soundHandleSpeech)) {
- uint volume = mute ? 0 : Audio::Mixer::kMaxChannelVolume;
-
- _vm->_mixer->setChannelVolume(_soundHandleSpeech, volume);
- }
-}
-
-/**
- * Stops the speech dead in its tracks.
- */
-
-void Sound::pauseSpeech() {
- _speechPaused = true;
- _vm->_mixer->pauseHandle(_soundHandleSpeech, true);
-}
-
-/**
- * Restarts the speech from where it was stopped.
- */
-
-void Sound::unpauseSpeech() {
- _speechPaused = false;
- _vm->_mixer->pauseHandle(_soundHandleSpeech, false);
-}
-
-/**
- * Stops the speech from playing.
- */
-
-int32 Sound::stopSpeech() {
- if (_vm->_mixer->isSoundHandleActive(_soundHandleSpeech)) {
- _vm->_mixer->stopHandle(_soundHandleSpeech);
- return RD_OK;
- }
-
- return RDERR_SPEECHNOTPLAYING;
-}
-
-/**
- * @return Either RDSE_SAMPLEPLAYING or RDSE_SAMPLEFINISHED
- */
-
-int32 Sound::getSpeechStatus() {
- return _vm->_mixer->isSoundHandleActive(_soundHandleSpeech) ? RDSE_SAMPLEPLAYING : RDSE_SAMPLEFINISHED;
-}
-
-/**
- * Returns either RDSE_QUIET or RDSE_SPEAKING
- */
-
-int32 Sound::amISpeaking() {
- if (!_speechMuted && !_speechPaused && _vm->_mixer->isSoundHandleActive(_soundHandleSpeech))
- return RDSE_SPEAKING;
-
- return RDSE_QUIET;
-}
-
-/**
- * This function loads and decompresses a list of speech from a cluster, but
- * does not play it. This is used for cutscene voice-overs, presumably to
- * avoid having to read from more than one file on the CD during playback.
- * @param speechId the text line id used to reference the speech
- * @param buf a pointer to the buffer that will be allocated for the sound
- */
-
-uint32 Sound::preFetchCompSpeech(uint32 speechId, uint16 **buf) {
- int cd = _vm->_resman->getCD();
- uint32 numSamples;
-
- SoundFileHandle *fh = (cd == 1) ? &_speechFile[0] : &_speechFile[1];
-
- AudioStream *input = getAudioStream(fh, "speech", cd, speechId, &numSamples);
-
- if (!input)
- return 0;
-
- *buf = NULL;
-
- // Decompress data into speech buffer.
-
- uint32 bufferSize = 2 * numSamples;
-
- *buf = (uint16 *)malloc(bufferSize);
- if (!*buf) {
- delete input;
- fh->file.close();
- return 0;
- }
-
- uint32 readSamples = input->readBuffer((int16 *)*buf, numSamples);
-
- fh->file.close();
- delete input;
-
- return 2 * readSamples;
-}
-
-/**
- * This function loads, decompresses and plays a line of speech. An error
- * occurs if speech is already playing.
- * @param speechId the text line id used to reference the speech
- * @param vol volume, 0 (minimum) to 16 (maximum)
- * @param pan panning, -16 (full left) to 16 (full right)
- */
-
-int32 Sound::playCompSpeech(uint32 speechId, uint8 vol, int8 pan) {
- if (_speechMuted)
- return RD_OK;
-
- if (getSpeechStatus() == RDERR_SPEECHPLAYING)
- return RDERR_SPEECHPLAYING;
-
- int cd = _vm->_resman->getCD();
- SoundFileHandle *fh = (cd == 1) ? &_speechFile[0] : &_speechFile[1];
-
- AudioStream *input = getAudioStream(fh, "speech", cd, speechId, NULL);
-
- if (!input)
- return RDERR_INVALIDID;
-
- // Modify the volume according to the master volume
-
- byte volume = _speechMuted ? 0 : vol * Audio::Mixer::kMaxChannelVolume / 16;
- int8 p = (pan * 127) / 16;
-
- if (isReverseStereo())
- p = -p;
-
- // Start the speech playing
- _vm->_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_soundHandleSpeech, input, -1, volume, p);
- return RD_OK;
-}
-
-// ----------------------------------------------------------------------------
-// SOUND EFFECTS
-// ----------------------------------------------------------------------------
-
-/**
- * Mutes/Unmutes the sound effects.
- * @param mute If mute is false, restore the volume to the last set master
- * level. Otherwise the sound effects are muted (volume 0).
- */
-
-void Sound::muteFx(bool mute) {
- _fxMuted = mute;
-
- // Now update the volume of any fxs playing
- for (int i = 0; i < FXQ_LENGTH; i++) {
- if (_fxQueue[i].resource) {
- _vm->_mixer->setChannelVolume(_fxQueue[i].handle, mute ? 0 : _fxQueue[i].volume);
- }
- }
-}
-
-/**
- * Sets the volume and pan of the sample which is currently playing
- * @param id the id of the sample
- * @param vol volume
- * @param pan panning
- */
-
-int32 Sound::setFxIdVolumePan(int32 id, int vol, int pan) {
- if (!_fxQueue[id].resource)
- return RDERR_FXNOTOPEN;
-
- if (vol > 16)
- vol = 16;
-
- _fxQueue[id].volume = (vol * Audio::Mixer::kMaxChannelVolume) / 16;
-
- if (pan != 255) {
- if (isReverseStereo())
- pan = -pan;
- _fxQueue[id].pan = (pan * 127) / 16;
- }
-
- if (!_fxMuted && _vm->_mixer->isSoundHandleActive(_fxQueue[id].handle)) {
- _vm->_mixer->setChannelVolume(_fxQueue[id].handle, _fxQueue[id].volume);
- if (pan != -1)
- _vm->_mixer->setChannelBalance(_fxQueue[id].handle, _fxQueue[id].pan);
- }
-
- return RD_OK;
-}
-
-void Sound::pauseFx() {
- if (_fxPaused)
- return;
-
- for (int i = 0; i < FXQ_LENGTH; i++) {
- if (_fxQueue[i].resource)
- _vm->_mixer->pauseHandle(_fxQueue[i].handle, true);
- }
-
- _fxPaused = true;
-}
-
-void Sound::unpauseFx() {
- if (!_fxPaused)
- return;
-
- for (int i = 0; i < FXQ_LENGTH; i++)
- if (_fxQueue[i].resource)
- _vm->_mixer->pauseHandle(_fxQueue[i].handle, false);
-
- _fxPaused = false;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/object.h b/sword2/object.h
deleted file mode 100644
index 1fd434f8a0..0000000000
--- a/sword2/object.h
+++ /dev/null
@@ -1,342 +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 _SCRIPT_STRUCTURES
-#define _SCRIPT_STRUCTURES
-
-#include "common/stream.h"
-
-namespace Sword2 {
-
-// these structures represent the broken up compact components
-// these here declared to the system must be the same as those declared to
-// LINC (or it wont work)
-
-// mouse structure - defines mouse detection area, detection priority &
-// 'type' flag
-
-struct ObjectMouse {
- int32 x1; // Top-left and bottom-right of mouse
- int32 y1; // area. (These coords are inclusive.)
- int32 x2;
- int32 y2;
- int32 priority;
- int32 pointer; // type (or resource id?) of pointer used over this area
-
- static const int size() {
- return 24;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- x1 = readS.readSint32LE();
- y1 = readS.readSint32LE();
- x2 = readS.readSint32LE();
- y2 = readS.readSint32LE();
- priority = readS.readSint32LE();
- pointer = readS.readSint32LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeSint32LE(x1);
- writeS.writeSint32LE(y1);
- writeS.writeSint32LE(x2);
- writeS.writeSint32LE(y2);
- writeS.writeSint32LE(priority);
- writeS.writeSint32LE(pointer);
- }
-};
-
-// logic structure - contains fields used in logic script processing
-
-class ObjectLogic {
- // int32 looping; // 0 when first calling fn<function>;
- // 1 when calling subsequent times in
- // same loop
- // int32 pause; // pause count, used by fnPause()
-
-private:
- byte *_addr;
-
-public:
- ObjectLogic(byte *addr) {
- _addr = addr;
- }
-
- static const int size() {
- return 8;
- }
-
- byte *data() {
- return _addr;
- }
-
- int32 getLooping() { return READ_LE_UINT32(_addr); }
- int32 getPause() { return READ_LE_UINT32(_addr + 4); }
-
- void setLooping(int32 x) { WRITE_LE_UINT32(_addr, x); }
- void setPause(int32 x) { WRITE_LE_UINT32(_addr + 4, x); }
-};
-
-// status bits for 'type' field of ObjectGraphic)
-
-// in low word:
-
-#define NO_SPRITE 0x00000000 // don't print
-#define BGP0_SPRITE 0x00000001 // fixed to background parallax[0]
-#define BGP1_SPRITE 0x00000002 // fixed to background parallax[1]
-#define BACK_SPRITE 0x00000004 // 'background' sprite, fixed to main background
-#define SORT_SPRITE 0x00000008 // 'sorted' sprite, fixed to main background
-#define FORE_SPRITE 0x00000010 // 'foreground' sprite, fixed to main background
-#define FGP0_SPRITE 0x00000020 // fixed to foreground parallax[0]
-#define FGP1_SPRITE 0x00000040 // fixed to foreground parallax[0]
-
-// in high word:
-
-#define UNSHADED_SPRITE 0x00000000 // not to be shaded
-#define SHADED_SPRITE 0x00010000 // to be shaded, based on shading mask
-
-// graphic structure - contains fields appropriate to sprite output
-
-class ObjectGraphic {
- // int32 type; // see above
- // int32 anim_resource; // resource id of animation file
- // int32 anim_pc; // current frame number of animation
-
-private:
- byte *_addr;
-
-public:
- ObjectGraphic(byte *addr) {
- _addr = addr;
- }
-
- static const int size() {
- return 12;
- }
-
- byte *data() {
- return _addr;
- }
-
- int32 getType() { return READ_LE_UINT32(_addr); }
- int32 getAnimResource() { return READ_LE_UINT32(_addr + 4); }
- int32 getAnimPc() { return READ_LE_UINT32(_addr + 8); }
-
- void setType(int32 x) { WRITE_LE_UINT32(_addr, x); }
- void setAnimResource(int32 x) { WRITE_LE_UINT32(_addr + 4, x); }
- void setAnimPc(int32 x) { WRITE_LE_UINT32(_addr + 8, x); }
-};
-
-// speech structure - contains fields used by speech scripts & text output
-
-class ObjectSpeech {
- // int32 pen; // colour to use for body of characters
- // int32 width; // max width of text sprite
- // int32 command; // speech script command id
- // int32 ins1; // speech script instruction parameters
- // int32 ins2;
- // int32 ins3;
- // int32 ins4;
- // int32 ins5;
- // int32 wait_state; // 0 not waiting,
- // 1 waiting for next speech command
-
-private:
- byte *_addr;
-
-public:
- ObjectSpeech(byte *addr) {
- _addr = addr;
- }
-
- static const int size() {
- return 36;
- }
-
- byte *data() {
- return _addr;
- }
-
- int32 getPen() { return READ_LE_UINT32(_addr); }
- int32 getWidth() { return READ_LE_UINT32(_addr + 4); }
- int32 getCommand() { return READ_LE_UINT32(_addr + 8); }
- int32 getIns1() { return READ_LE_UINT32(_addr + 12); }
- int32 getIns2() { return READ_LE_UINT32(_addr + 16); }
- int32 getIns3() { return READ_LE_UINT32(_addr + 20); }
- int32 getIns4() { return READ_LE_UINT32(_addr + 24); }
- int32 getIns5() { return READ_LE_UINT32(_addr + 28); }
- int32 getWaitState() { return READ_LE_UINT32(_addr + 32); }
-
- void setPen(int32 x) { WRITE_LE_UINT32(_addr, x); }
- void setWidth(int32 x) { WRITE_LE_UINT32(_addr + 4, x); }
- void setCommand(int32 x) { WRITE_LE_UINT32(_addr + 8, x); }
- void setIns1(int32 x) { WRITE_LE_UINT32(_addr + 12, x); }
- void setIns2(int32 x) { WRITE_LE_UINT32(_addr + 16, x); }
- void setIns3(int32 x) { WRITE_LE_UINT32(_addr + 20, x); }
- void setIns4(int32 x) { WRITE_LE_UINT32(_addr + 24, x); }
- void setIns5(int32 x) { WRITE_LE_UINT32(_addr + 28, x); }
- void setWaitState(int32 x) { WRITE_LE_UINT32(_addr + 32, x); }
-};
-
-// mega structure - contains fields used for mega-character & mega-set
-// processing
-
-class ObjectMega {
- // int32 NOT_USED_1; // only free roaming megas need to
- // check this before registering their
- // graphics for drawing
- // int32 NOT_USED_2; // id of floor on which we are standing
- // int32 NOT_USED_3; // id of object which we are getting to
- // int32 NOT_USED_4; // pixel distance to stand from player
- // character when in conversation
- // int32 currently_walking; // number given us by the auto router
- // int32 walk_pc; // current frame number of walk-anim
- // int32 scale_a; // current scale factors, taken from
- // int32 scale_b; // floor data
- // int32 feet_x; // mega feet coords - frame-offsets are
- // int32 feet_y; // added to these position mega frames
- // int32 current_dir; // current dirction faced by mega; used
- // by autorouter to determine turns
- // required
- // int32 NOT_USED_5; // means were currently avoiding a
- // collision (see fnWalk)
- // int32 megaset_res; // resource id of mega-set file
- // int32 NOT_USED_6; // NOT USED
-
-private:
- byte *_addr;
-
-public:
- ObjectMega(byte *addr) {
- _addr = addr;
- }
-
- static const int size() {
- return 56;
- }
-
- byte *data() {
- return _addr;
- }
-
- int32 getIsWalking() { return READ_LE_UINT32(_addr + 16); }
- int32 getWalkPc() { return READ_LE_UINT32(_addr + 20); }
- int32 getScaleA() { return READ_LE_UINT32(_addr + 24); }
- int32 getScaleB() { return READ_LE_UINT32(_addr + 28); }
- int32 getFeetX() { return READ_LE_UINT32(_addr + 32); }
- int32 getFeetY() { return READ_LE_UINT32(_addr + 36); }
- int32 getCurDir() { return READ_LE_UINT32(_addr + 40); }
- int32 getMegasetRes() { return READ_LE_UINT32(_addr + 48); }
-
- void setIsWalking(int32 x) { WRITE_LE_UINT32(_addr + 16, x); }
- void setWalkPc(int32 x) { WRITE_LE_UINT32(_addr + 20, x); }
- void setScaleA(int32 x) { WRITE_LE_UINT32(_addr + 24, x); }
- void setScaleB(int32 x) { WRITE_LE_UINT32(_addr + 28, x); }
- void setFeetX(int32 x) { WRITE_LE_UINT32(_addr + 32, x); }
- void setFeetY(int32 x) { WRITE_LE_UINT32(_addr + 36, x); }
- void setCurDir(int32 x) { WRITE_LE_UINT32(_addr + 40, x); }
- void setMegasetRes(int32 x) { WRITE_LE_UINT32(_addr + 48, x); }
-
- int32 calcScale() {
- // Calc scale at which to print the sprite, based on feet
- // y-coord & scaling constants (NB. 'scale' is actually
- // 256 * true_scale, to maintain accuracy)
-
- // Ay+B gives 256 * scale ie. 256 * 256 * true_scale for even
- // better accuracy, ie. scale = (Ay + B) / 256
- return (getScaleA() * getFeetY() + getScaleB()) / 256;
- }
-};
-
-// walk-data structure - contains details of layout of frames in the
-// mega-set, and how they are to be used
-
-struct ObjectWalkdata {
- int32 nWalkFrames; // no. of frames per walk-cycle
- int32 usingStandingTurnFrames; // 0 = no 1 = yes
- int32 usingWalkingTurnFrames; // 0 = no 1 = yes
- int32 usingSlowInFrames; // 0 = no 1 = yes
- int32 usingSlowOutFrames; // 0 = no !0 = number of slow-out frames in each direction
- int32 nSlowInFrames[8]; // no. of slow-in frames in each direction
- int32 leadingLeg[8]; // leading leg for walk in each direction (0 = left 1 = right)
- int32 dx[8 * (12 + 1)]; // walk step distances in x direction
- int32 dy[8 * (12 + 1)]; // walk step distances in y direction
-
- static const int size() {
- return 916;
- }
-
- void read(byte *addr) {
- Common::MemoryReadStream readS(addr, size());
-
- nWalkFrames = readS.readUint32LE();
- usingStandingTurnFrames = readS.readUint32LE();
- usingWalkingTurnFrames = readS.readUint32LE();
- usingSlowInFrames = readS.readUint32LE();
- usingSlowOutFrames = readS.readUint32LE();
-
- int i;
-
- for (i = 0; i < ARRAYSIZE(nSlowInFrames); i++)
- nSlowInFrames[i] = readS.readUint32LE();
-
- for (i = 0; i < ARRAYSIZE(leadingLeg); i++)
- leadingLeg[i] = readS.readUint32LE();
-
- for (i = 0; i < ARRAYSIZE(dx); i++)
- dx[i] = readS.readUint32LE();
-
- for (i = 0; i < ARRAYSIZE(dy); i++)
- dy[i] = readS.readUint32LE();
- }
-
- void write(byte *addr) {
- Common::MemoryWriteStream writeS(addr, size());
-
- writeS.writeUint32LE(nWalkFrames);
- writeS.writeUint32LE(usingStandingTurnFrames);
- writeS.writeUint32LE(usingWalkingTurnFrames);
- writeS.writeUint32LE(usingSlowInFrames);
- writeS.writeUint32LE(usingSlowOutFrames);
-
- int i;
-
- for (i = 0; i < ARRAYSIZE(nSlowInFrames); i++)
- writeS.writeUint32LE(nSlowInFrames[i]);
-
- for (i = 0; i < ARRAYSIZE(leadingLeg); i++)
- writeS.writeUint32LE(leadingLeg[i]);
-
- for (i = 0; i < ARRAYSIZE(dx); i++)
- writeS.writeUint32LE(dx[i]);
-
- for (i = 0; i < ARRAYSIZE(dy); i++)
- writeS.writeUint32LE(dy[i]);
- }
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/palette.cpp b/sword2/palette.cpp
deleted file mode 100644
index 0b6b7a8ca2..0000000000
--- a/sword2/palette.cpp
+++ /dev/null
@@ -1,267 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/system.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/resman.h"
-
-namespace Sword2 {
-
-/**
- * Start layer palette fading up
- */
-
-void Screen::startNewPalette() {
- // If the screen is still fading down then wait for black - could
- // happen when everythings cached into a large memory model
- waitForFade();
-
- byte *screenFile = _vm->_resman->openResource(_thisScreen.background_layer_id);
-
- memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(screenFile), PALTABLESIZE);
- setPalette(0, 256, _vm->fetchPalette(screenFile), RDPAL_FADE);
-
- // Indicating that it's a screen palette
- _lastPaletteRes = 0;
-
- _vm->_resman->closeResource(_thisScreen.background_layer_id);
- fadeUp();
- _thisScreen.new_palette = 0;
-}
-
-void Screen::setFullPalette(int32 palRes) {
- // fudge for hut interior
- // - unpausing should restore last palette as normal (could be screen
- // palette or 'dark_palette_13')
- // - but restoring the screen palette after 'dark_palette_13' should
- // now work properly too!
-
- // "Hut interior" refers to the watchman's hut in Marseille, and this
- // is apparently needed for the palette to be restored properly when
- // you turn the light off. (I didn't even notice the light switch!)
-
- if (_vm->_logic->readVar(LOCATION) == 13) {
- // unpausing
- if (palRes == -1) {
- // restore whatever palette was last set (screen
- // palette or 'dark_palette_13')
- palRes = _lastPaletteRes;
- }
- } else {
- // check if we're just restoring the current screen palette
- // because we might actually need to use a separate palette
- // file anyway eg. for pausing & unpausing during the eclipse
-
- // unpausing (fudged for location 13)
- if (palRes == -1) {
- // we really meant '0'
- palRes = 0;
- }
-
- if (palRes == 0 && _lastPaletteRes)
- palRes = _lastPaletteRes;
- }
-
- // If non-zero, set palette to this separate palette file. Otherwise,
- // set palette to current screen palette.
-
- if (palRes) {
- byte *pal = _vm->_resman->openResource(palRes);
-
- assert(_vm->_resman->fetchType(pal) == PALETTE_FILE);
-
- pal += ResHeader::size();
-
- // always set colour 0 to black because most background screen
- // palettes have a bright colour 0 although it should come out
- // as black in the game!
-
- pal[0] = 0;
- pal[1] = 0;
- pal[2] = 0;
- pal[3] = 0;
-
- setPalette(0, 256, pal, RDPAL_INSTANT);
- _vm->_resman->closeResource(palRes);
- } else {
- if (_thisScreen.background_layer_id) {
- byte *data = _vm->_resman->openResource(_thisScreen.background_layer_id);
- memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(data), PALTABLESIZE);
- setPalette(0, 256, _vm->fetchPalette(data), RDPAL_INSTANT);
- _vm->_resman->closeResource(_thisScreen.background_layer_id);
- } else
- error("setFullPalette(0) called, but no current screen available!");
- }
-
- if (palRes != CONTROL_PANEL_PALETTE)
- _lastPaletteRes = palRes;
-}
-
-/**
- * Matches a colour triplet to a palette index.
- * @param r red colour component
- * @param g green colour component
- * @param b blue colour component
- * @return the palette index of the closest matching colour in the palette
- */
-
-// FIXME: This used to be inlined - probably a good idea - but the
-// linker complained when I tried to use it in sprite.cpp.
-
-uint8 Screen::quickMatch(uint8 r, uint8 g, uint8 b) {
- return _paletteMatch[((int32)(r >> 2) << 12) + ((int32)(g >> 2) << 6) + (b >> 2)];
-}
-
-/**
- * Sets the palette.
- * @param startEntry the first colour entry to set
- * @param noEntries the number of colour entries to set
- * @param colourTable the new colour entries
- * @param fadeNow whether to perform the change immediately or delayed
- */
-
-void Screen::setPalette(int16 startEntry, int16 noEntries, byte *colourTable, uint8 fadeNow) {
- assert(noEntries > 0);
-
- memcpy(&_palette[4 * startEntry], colourTable, noEntries * 4);
-
- if (fadeNow == RDPAL_INSTANT) {
- _vm->_system->setPalette(_palette, startEntry, noEntries);
- setNeedFullRedraw();
- }
-}
-
-void Screen::dimPalette() {
- byte *p = _palette;
-
- for (int i = 0; i < 256; i++) {
- p[i * 4 + 0] /= 2;
- p[i * 4 + 1] /= 2;
- p[i * 4 + 2] /= 2;
- }
-
- _vm->_system->setPalette(p, 0, 256);
- setNeedFullRedraw();
-}
-
-/**
- * Fades the palette up from black to the current palette.
- * @param time the time it will take the palette to fade up
- */
-
-int32 Screen::fadeUp(float time) {
- if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
- return RDERR_FADEINCOMPLETE;
-
- _fadeTotalTime = (int32)(time * 1000);
- _fadeStatus = RDFADE_UP;
- _fadeStartTime = _vm->_system->getMillis();
-
- return RD_OK;
-}
-
-/**
- * Fades the palette down to black from the current palette.
- * @param time the time it will take the palette to fade down
- */
-
-int32 Screen::fadeDown(float time) {
- if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
- return RDERR_FADEINCOMPLETE;
-
- _fadeTotalTime = (int32)(time * 1000);
- _fadeStatus = RDFADE_DOWN;
- _fadeStartTime = _vm->_system->getMillis();
-
- return RD_OK;
-}
-
-/**
- * Get the current fade status
- * @return RDFADE_UP (fading up), RDFADE_DOWN (fading down), RDFADE_NONE
- * (not faded), or RDFADE_BLACK (completely faded down)
- */
-
-uint8 Screen::getFadeStatus() {
- return _fadeStatus;
-}
-
-void Screen::waitForFade() {
- while (getFadeStatus() != RDFADE_NONE && getFadeStatus() != RDFADE_BLACK && !_vm->_quit) {
- updateDisplay();
- _vm->_system->delayMillis(20);
- }
-}
-
-void Screen::fadeServer() {
- static int32 previousTime = 0;
- byte fadePalette[256 * 4];
- byte *newPalette = fadePalette;
- int32 currentTime;
- int16 fadeMultiplier;
- int16 i;
-
- // If we're not in the process of fading, do nothing.
- if (getFadeStatus() != RDFADE_UP && getFadeStatus() != RDFADE_DOWN)
- return;
-
- // I don't know if this is necessary, but let's limit how often the
- // palette is updated, just to be safe.
- currentTime = _vm->_system->getMillis();
- if (currentTime - previousTime <= 25)
- return;
-
- previousTime = currentTime;
-
- if (getFadeStatus() == RDFADE_UP) {
- if (currentTime >= _fadeStartTime + _fadeTotalTime) {
- _fadeStatus = RDFADE_NONE;
- newPalette = _palette;
- } else {
- fadeMultiplier = (int16)(((int32)(currentTime - _fadeStartTime) * 256) / _fadeTotalTime);
- for (i = 0; i < 256; i++) {
- newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 2] = (_palette[i * 4 + 2] * fadeMultiplier) >> 8;
- }
- }
- } else {
- if (currentTime >= _fadeStartTime + _fadeTotalTime) {
- _fadeStatus = RDFADE_BLACK;
- memset(newPalette, 0, sizeof(fadePalette));
- } else {
- fadeMultiplier = (int16)(((int32)(_fadeTotalTime - (currentTime - _fadeStartTime)) * 256) / _fadeTotalTime);
- for (i = 0; i < 256; i++) {
- newPalette[i * 4 + 0] = (_palette[i * 4 + 0] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 1] = (_palette[i * 4 + 1] * fadeMultiplier) >> 8;
- newPalette[i * 4 + 2] = (_palette[i * 4 + 2] * fadeMultiplier) >> 8;
- }
- }
- }
-
- _vm->_system->setPalette(newPalette, 0, 256);
- setNeedFullRedraw();
-}
-
-} // End of namespace Sword2
diff --git a/sword2/protocol.cpp b/sword2/protocol.cpp
deleted file mode 100644
index 23010e27a9..0000000000
--- a/sword2/protocol.cpp
+++ /dev/null
@@ -1,216 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/resman.h"
-
-namespace Sword2 {
-
-/**
- * Returns a pointer to the first palette entry, given the pointer to the start
- * of the screen file.
- */
-
-byte *Sword2Engine::fetchPalette(byte *screenFile) {
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
-
- byte *palette = screenFile + ResHeader::size() + mscreenHeader.palette;
-
- // Always set colour 0 to black, because while most background screen
- // palettes have a bright colour 0 it should come out as black in the
- // game.
-
- palette[0] = 0;
- palette[1] = 0;
- palette[2] = 0;
- palette[3] = 0;
-
- return palette;
-}
-
-/**
- * Returns a pointer to the start of the palette match table, given the pointer
- * to the start of the screen file.
- */
-
-byte *Sword2Engine::fetchPaletteMatchTable(byte *screenFile) {
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
-
- return screenFile + ResHeader::size() + mscreenHeader.paletteTable;
-}
-
-/**
- * Returns a pointer to the screen header, given the pointer to the start of
- * the screen file.
- */
-
-byte *Sword2Engine::fetchScreenHeader(byte *screenFile) {
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
-
- return screenFile + ResHeader::size() + mscreenHeader.screen;
-}
-
-/**
- * Returns a pointer to the requested layer header, given the pointer to the
- * start of the screen file. Drops out if the requested layer number exceeds
- * the number of layers on this screen.
- */
-
-byte *Sword2Engine::fetchLayerHeader(byte *screenFile, uint16 layerNo) {
-#ifdef SWORD2_DEBUG
- ScreenHeader screenHead;
-
- screenHead.read(fetchScreenHeader(screenFile));
- assert(layerNo < screenHead.noLayers);
-#endif
-
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
-
- return screenFile + ResHeader::size() + mscreenHeader.layers + layerNo * LayerHeader::size();
-}
-
-/**
- * Returns a pointer to the start of the shading mask, given the pointer to the
- * start of the screen file.
- */
-
-byte *Sword2Engine::fetchShadingMask(byte *screenFile) {
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
-
- return screenFile + ResHeader::size() + mscreenHeader.maskOffset;
-}
-
-/**
- * Returns a pointer to the anim header, given the pointer to the start of the
- * anim file.
- */
-
-byte *Sword2Engine::fetchAnimHeader(byte *animFile) {
- return animFile + ResHeader::size();
-}
-
-/**
- * Returns a pointer to the requested frame number's cdtEntry, given the
- * pointer to the start of the anim file. Drops out if the requested frame
- * number exceeds the number of frames in this anim.
- */
-
-byte *Sword2Engine::fetchCdtEntry(byte *animFile, uint16 frameNo) {
-#ifdef SWORD2_DEBUG
- AnimHeader animHead;
-
- animHead.read(fetchAnimHeader(animFile));
-
- if (frameNo > animHead->noAnimFrames - 1)
- error("fetchCdtEntry(animFile,%d) - anim only %d frames", frameNo, animHead.noAnimFrames);
-#endif
-
- return fetchAnimHeader(animFile) + AnimHeader::size() + frameNo * CdtEntry::size();
-}
-
-/**
- * Returns a pointer to the requested frame number's header, given the pointer
- * to the start of the anim file. Drops out if the requested frame number
- * exceeds the number of frames in this anim
- */
-
-byte *Sword2Engine::fetchFrameHeader(byte *animFile, uint16 frameNo) {
- // required address = (address of the start of the anim header) + frameOffset
- CdtEntry cdt;
-
- cdt.read(fetchCdtEntry(animFile, frameNo));
-
- return animFile + ResHeader::size() + cdt.frameOffset;
-}
-
-/**
- * Returns a pointer to the requested parallax layer data.
- */
-
-byte *Sword2Engine::fetchBackgroundParallaxLayer(byte *screenFile, int layer) {
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
- assert(mscreenHeader.bg_parallax[layer]);
-
- return screenFile + ResHeader::size() + mscreenHeader.bg_parallax[layer];
-}
-
-byte *Sword2Engine::fetchBackgroundLayer(byte *screenFile) {
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
- assert(mscreenHeader.screen);
-
- return screenFile + ResHeader::size() + mscreenHeader.screen + ScreenHeader::size();
-}
-
-byte *Sword2Engine::fetchForegroundParallaxLayer(byte *screenFile, int layer) {
- MultiScreenHeader mscreenHeader;
-
- mscreenHeader.read(screenFile + ResHeader::size());
- assert(mscreenHeader.fg_parallax[layer]);
-
- return screenFile + ResHeader::size() + mscreenHeader.fg_parallax[layer];
-}
-
-byte *Sword2Engine::fetchTextLine(byte *file, uint32 text_line) {
- TextHeader text_header;
- static byte errorLine[128];
-
- text_header.read(file + ResHeader::size());
-
- if (text_line >= text_header.noOfLines) {
- sprintf((char *)errorLine, "xxMissing line %d of %s (only 0..%d)", text_line, _resman->fetchName(file), text_header.noOfLines - 1);
-
- // first 2 chars are NULL so that actor-number comes out as '0'
- errorLine[0] = 0;
- errorLine[1] = 0;
- return errorLine;
- }
-
- // The "number of lines" field is followed by a lookup table
-
- return file + READ_LE_UINT32(file + ResHeader::size() + 4 + 4 * text_line);
-}
-
-// Used for testing text & speech (see fnISpeak in speech.cpp)
-
-bool Sword2Engine::checkTextLine(byte *file, uint32 text_line) {
- TextHeader text_header;
-
- text_header.read(file + ResHeader::size());
-
- return text_line < text_header.noOfLines;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/rdwin.cpp b/sword2/rdwin.cpp
deleted file mode 100644
index 310b66abf7..0000000000
--- a/sword2/rdwin.cpp
+++ /dev/null
@@ -1,118 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/system.h"
-#include "sword2/sword2.h"
-
-namespace Sword2 {
-
-/**
- * Tell updateDisplay() that the scene needs to be completely updated.
- */
-
-void Screen::setNeedFullRedraw() {
- _needFullRedraw = true;
-}
-
-/**
- * Mark an area of the screen as dirty, first generation.
- */
-
-void Screen::markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1) {
- int16 gridX0 = x0 / CELLWIDE;
- int16 gridY0 = y0 / CELLDEEP;
- int16 gridX1 = x1 / CELLWIDE;
- int16 gridY1 = y1 / CELLDEEP;
-
- for (int16 i = gridY0; i <= gridY1; i++)
- for (int16 j = gridX0; j <= gridX1; j++)
- _dirtyGrid[i * _gridWide + j] = 2;
-}
-
-/**
- * This function has two purposes: It redraws the scene, and it handles input
- * events, palette fading, etc. It should be called at a high rate (> 20 per
- * second), but the scene is usually only redrawn about 12 times per second,
- * except when then screen is scrolling.
- *
- * @param redrawScene If true, redraw the scene.
- */
-
-void Screen::updateDisplay(bool redrawScene) {
- _vm->parseInputEvents();
- fadeServer();
-
- if (redrawScene) {
- int i;
-
- // Note that the entire scene is always rendered, which is less
- // than optimal, but at least we can try to be intelligent
- // about updating the screen afterwards.
-
- if (_needFullRedraw) {
- // Update the entire screen. This is necessary when
- // scrolling, fading, etc.
-
- _vm->_system->copyRectToScreen(_buffer + MENUDEEP * _screenWide, _screenWide, 0, MENUDEEP, _screenWide, _screenDeep - 2 * MENUDEEP);
- _needFullRedraw = false;
- } else {
- // Update only the dirty areas of the screen
-
- int j, x, y;
- int stripWide;
-
- for (i = 0; i < _gridDeep; i++) {
- stripWide = 0;
-
- for (j = 0; j < _gridWide; j++) {
- if (_dirtyGrid[i * _gridWide + j]) {
- stripWide++;
- } else if (stripWide) {
- x = CELLWIDE * (j - stripWide);
- y = CELLDEEP * i;
- _vm->_system->copyRectToScreen(_buffer + y * _screenWide + x, _screenWide, x, y, stripWide * CELLWIDE, CELLDEEP);
- stripWide = 0;
- }
- }
-
- if (stripWide) {
- x = CELLWIDE * (j - stripWide);
- y = CELLDEEP * i;
- _vm->_system->copyRectToScreen(_buffer + y * _screenWide + x, _screenWide, x, y, stripWide * CELLWIDE, CELLDEEP);
- stripWide = 0;
- }
- }
- }
-
- // Age the dirty cells one generation. This way we keep track
- // of both the cells that were updated this time, and the ones
- // that were updated the last time.
-
- for (i = 0; i < _gridWide * _gridDeep; i++)
- _dirtyGrid[i] >>= 1;
- }
-
- // We always need to update because of fades, menu animations, etc.
- _vm->_system->updateScreen();
-}
-
-} // End of namespace Sword2
diff --git a/sword2/render.cpp b/sword2/render.cpp
deleted file mode 100644
index da60ecd6d9..0000000000
--- a/sword2/render.cpp
+++ /dev/null
@@ -1,584 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/system.h"
-
-#include "graphics/primitives.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/build_display.h"
-
-#ifdef BACKEND_8BIT
-#include "sword2/animation.h"
-#endif
-
-namespace Sword2 {
-
-#define MILLISECSPERCYCLE 83
-#define RENDERAVERAGETOTAL 4
-
-void Screen::updateRect(Common::Rect *r) {
- _vm->_system->copyRectToScreen(_buffer + r->top * _screenWide + r->left,
- _screenWide, r->left, r->top, r->right - r->left,
- r->bottom - r->top);
-}
-
-void Screen::blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect) {
- if (!r->intersects(*clipRect))
- return;
-
- byte *src = s->data;
-
- if (r->top < clipRect->top) {
- src -= BLOCKWIDTH * (r->top - clipRect->top);
- r->top = clipRect->top;
- }
- if (r->left < clipRect->left) {
- src -= (r->left - clipRect->left);
- r->left = clipRect->left;
- }
- if (r->bottom > clipRect->bottom)
- r->bottom = clipRect->bottom;
- if (r->right > clipRect->right)
- r->right = clipRect->right;
-
- byte *dst = _buffer + r->top * _screenWide + r->left;
- int i;
-
- if (s->transparent) {
- for (i = 0; i < r->bottom - r->top; i++) {
- for (int j = 0; j < r->right - r->left; j++) {
- if (src[j])
- dst[j] = src[j];
- }
- src += BLOCKWIDTH;
- dst += _screenWide;
- }
- } else {
- for (i = 0; i < r->bottom - r->top; i++) {
- memcpy(dst, src, r->right - r->left);
- src += BLOCKWIDTH;
- dst += _screenWide;
- }
- }
-}
-
-// There are two different separate functions for scaling the image - one fast
-// and one good. Or at least that's the theory. I'm sure there are better ways
-// to scale an image than this. The latter is used at the highest graphics
-// quality setting. Note that the "good" scaler takes an extra parameter, a
-// pointer to the area of the screen where the sprite will be drawn.
-//
-// This code isn't quite like the original DrawSprite(), but should be close
-// enough.
-
-void Screen::scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight) {
- int x, y;
-
- for (x = 0; x < dstWidth; x++)
- _xScale[x] = (x * srcWidth) / dstWidth;
-
- for (y = 0; y < dstHeight; y++)
- _yScale[y] = (y * srcHeight) / dstHeight;
-
- for (y = 0; y < dstHeight; y++) {
- for (x = 0; x < dstWidth; x++) {
- dst[x] = src[_yScale[y] * srcPitch + _xScale[x]];
- }
- dst += dstPitch;
- }
-}
-
-void Screen::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight, byte *backbuf) {
- for (int y = 0; y < dstHeight; y++) {
- for (int x = 0; x < dstWidth; x++) {
- uint8 c1, c2, c3, c4;
-
- uint32 xPos = (x * srcWidth) / dstWidth;
- uint32 yPos = (y * srcHeight) / dstHeight;
- uint32 xFrac = dstWidth - (x * srcWidth) % dstWidth;
- uint32 yFrac = dstHeight - (y * srcHeight) % dstHeight;
-
- byte *srcPtr = src + yPos * srcPitch + xPos;
- byte *backPtr = backbuf + y * _screenWide + x;
-
- bool transparent = true;
-
- if (*srcPtr) {
- c1 = *srcPtr;
- transparent = false;
- } else
- c1 = *backPtr;
-
- if (x < dstWidth - 1) {
- if (*(srcPtr + 1)) {
- c2 = *(srcPtr + 1);
- transparent = false;
- } else
- c2 = *(backPtr + 1);
- } else
- c2 = c1;
-
- if (y < dstHeight - 1) {
- if (*(srcPtr + srcPitch)) {
- c3 = *(srcPtr + srcPitch);
- transparent = false;
- } else
- c3 = *(backPtr + _screenWide);
- } else
- c3 = c1;
-
- if (x < dstWidth - 1 && y < dstHeight - 1) {
- if (*(srcPtr + srcPitch + 1)) {
- c4 = *(srcPtr + srcPitch + 1);
- transparent = false;
- } else
- c4 = *(backPtr + _screenWide + 1);
- } else
- c4 = c3;
-
- if (!transparent) {
- uint32 r1 = _palette[c1 * 4 + 0];
- uint32 g1 = _palette[c1 * 4 + 1];
- uint32 b1 = _palette[c1 * 4 + 2];
-
- uint32 r2 = _palette[c2 * 4 + 0];
- uint32 g2 = _palette[c2 * 4 + 1];
- uint32 b2 = _palette[c2 * 4 + 2];
-
- uint32 r3 = _palette[c3 * 4 + 0];
- uint32 g3 = _palette[c3 * 4 + 1];
- uint32 b3 = _palette[c3 * 4 + 2];
-
- uint32 r4 = _palette[c4 * 4 + 0];
- uint32 g4 = _palette[c4 * 4 + 1];
- uint32 b4 = _palette[c4 * 4 + 2];
-
- uint32 r5 = (r1 * xFrac + r2 * (dstWidth - xFrac)) / dstWidth;
- uint32 g5 = (g1 * xFrac + g2 * (dstWidth - xFrac)) / dstWidth;
- uint32 b5 = (b1 * xFrac + b2 * (dstWidth - xFrac)) / dstWidth;
-
- uint32 r6 = (r3 * xFrac + r4 * (dstWidth - xFrac)) / dstWidth;
- uint32 g6 = (g3 * xFrac + g4 * (dstWidth - xFrac)) / dstWidth;
- uint32 b6 = (b3 * xFrac + b4 * (dstWidth - xFrac)) / dstWidth;
-
- uint32 r = (r5 * yFrac + r6 * (dstHeight - yFrac)) / dstHeight;
- uint32 g = (g5 * yFrac + g6 * (dstHeight - yFrac)) / dstHeight;
- uint32 b = (b5 * yFrac + b6 * (dstHeight - yFrac)) / dstHeight;
-
- dst[y * dstWidth + x] = quickMatch(r, g, b);
- } else
- dst[y * dstWidth + x] = 0;
- }
- }
-}
-
-/**
- * Plots a point relative to the top left corner of the screen. This is only
- * used for debugging.
- * @param x x-coordinate of the point
- * @param y y-coordinate of the point
- * @param colour colour of the point
- */
-
-void Screen::plotPoint(int x, int y, uint8 colour) {
- byte *buf = _buffer + MENUDEEP * RENDERWIDE;
-
- x -= _scrollX;
- y -= _scrollY;
-
- if (x >= 0 && x < RENDERWIDE && y >= 0 && y < RENDERDEEP) {
- buf[y * RENDERWIDE + x] = colour;
- markAsDirty(x, y + MENUDEEP, x, y + MENUDEEP);
- }
-}
-
-static void plot(int x, int y, int colour, void *data) {
- Screen *screen = (Screen *)data;
- screen->plotPoint(x, y, (uint8) colour);
-}
-
-/**
- * Draws a line from one point to another. This is only used for debugging.
- * @param x0 x-coordinate of the start point
- * @param y0 y-coordinate of the start point
- * @param x1 x-coordinate of the end point
- * @param y1 y-coordinate of the end point
- * @param colour colour of the line
- */
-
-void Screen::drawLine(int x0, int y0, int x1, int y1, uint8 colour) {
- Graphics::drawLine(x0, y0, x1, y1, colour, &plot, this);
-}
-
-/**
- * This function tells the driver the size of the background screen for the
- * current location.
- * @param w width of the current location
- * @param h height of the current location
- */
-
-void Screen::setLocationMetrics(uint16 w, uint16 h) {
- _locationWide = w;
- _locationDeep = h;
- setNeedFullRedraw();
-}
-
-/**
- * Draws a parallax layer at the current position determined by the scroll. A
- * parallax can be either foreground, background or the main screen.
- */
-
-void Screen::renderParallax(byte *ptr, int16 l) {
- Parallax p;
- int16 x, y;
- Common::Rect r;
-
- p.read(ptr);
-
- if (_locationWide == _screenWide)
- x = 0;
- else
- x = ((int32)((p.w - _screenWide) * _scrollX) / (int32)(_locationWide - _screenWide));
-
- if (_locationDeep == _screenDeep - MENUDEEP * 2)
- y = 0;
- else
- y = ((int32)((p.h - (_screenDeep - MENUDEEP * 2)) * _scrollY) / (int32)(_locationDeep - (_screenDeep - MENUDEEP * 2)));
-
- Common::Rect clipRect;
-
- // Leave enough space for the top and bottom menues
-
- clipRect.left = 0;
- clipRect.right = _screenWide;
- clipRect.top = MENUDEEP;
- clipRect.bottom = _screenDeep - MENUDEEP;
-
- for (int j = 0; j < _yBlocks[l]; j++) {
- for (int i = 0; i < _xBlocks[l]; i++) {
- if (_blockSurfaces[l][i + j * _xBlocks[l]]) {
- r.left = i * BLOCKWIDTH - x;
- r.right = r.left + BLOCKWIDTH;
- r.top = j * BLOCKHEIGHT - y + MENUDEEP;
- r.bottom = r.top + BLOCKHEIGHT;
- blitBlockSurface(_blockSurfaces[l][i + j * _xBlocks[l]], &r, &clipRect);
- }
- }
- }
-
- _parallaxScrollX = _scrollX - x;
- _parallaxScrollY = _scrollY - y;
-}
-
-// Uncomment this when benchmarking the drawing routines.
-#define LIMIT_FRAME_RATE
-
-/**
- * Initialises the timers before the render loop is entered.
- */
-
-void Screen::initialiseRenderCycle() {
- _initialTime = _vm->_system->getMillis();
- _totalTime = _initialTime + MILLISECSPERCYCLE;
-}
-
-/**
- * This function should be called when the game engine is ready to start the
- * render cycle.
- */
-
-void Screen::startRenderCycle() {
- _scrollXOld = _scrollX;
- _scrollYOld = _scrollY;
-
- _startTime = _vm->_system->getMillis();
-
- if (_startTime + _renderAverageTime >= _totalTime) {
- _scrollX = _scrollXTarget;
- _scrollY = _scrollYTarget;
- _renderTooSlow = true;
- } else {
- _scrollX = (int16)(_scrollXOld + ((_scrollXTarget - _scrollXOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
- _scrollY = (int16)(_scrollYOld + ((_scrollYTarget - _scrollYOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
- _renderTooSlow = false;
- }
-
- if (_scrollXOld != _scrollX || _scrollYOld != _scrollY)
- setNeedFullRedraw();
-
- _framesPerGameCycle = 0;
-}
-
-/**
- * This function should be called at the end of the render cycle.
- * @return true if the render cycle is to be terminated,
- * or false if it should continue
- */
-
-bool Screen::endRenderCycle() {
- static int32 renderTimeLog[4] = { 60, 60, 60, 60 };
- static int32 renderCountIndex = 0;
- int32 time;
-
- time = _vm->_system->getMillis();
- renderTimeLog[renderCountIndex] = time - _startTime;
- _startTime = time;
- _renderAverageTime = (renderTimeLog[0] + renderTimeLog[1] + renderTimeLog[2] + renderTimeLog[3]) >> 2;
-
- _framesPerGameCycle++;
-
- if (++renderCountIndex == RENDERAVERAGETOTAL)
- renderCountIndex = 0;
-
- if (_renderTooSlow) {
- initialiseRenderCycle();
- return true;
- }
-
- if (_startTime + _renderAverageTime >= _totalTime) {
- _totalTime += MILLISECSPERCYCLE;
- _initialTime = time;
- return true;
- }
-
-#ifdef LIMIT_FRAME_RATE
- if (_scrollXTarget == _scrollX && _scrollYTarget == _scrollY) {
- // If we have already reached the scroll target sleep for the
- // rest of the render cycle.
- _vm->sleepUntil(_totalTime);
- _initialTime = _vm->_system->getMillis();
- _totalTime += MILLISECSPERCYCLE;
- return true;
- }
-#endif
-
- // This is an attempt to ensure that we always reach the scroll target.
- // Otherwise the game frequently tries to pump out new interpolation
- // frames without ever getting anywhere.
-
- if (ABS(_scrollX - _scrollXTarget) <= 1 && ABS(_scrollY - _scrollYTarget) <= 1) {
- _scrollX = _scrollXTarget;
- _scrollY = _scrollYTarget;
- } else {
- _scrollX = (int16)(_scrollXOld + ((_scrollXTarget - _scrollXOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
- _scrollY = (int16)(_scrollYOld + ((_scrollYTarget - _scrollYOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
- }
-
- if (_scrollX != _scrollXOld || _scrollY != _scrollYOld)
- setNeedFullRedraw();
-
-#ifdef LIMIT_FRAME_RATE
- // Give the other threads some breathing space. This apparently helps
- // against bug #875683, though I was never able to reproduce it for
- // myself.
- _vm->_system->delayMillis(10);
-#endif
-
- return false;
-}
-
-/**
- * Reset scrolling stuff. This function is called from initBackground()
- */
-
-void Screen::resetRenderEngine() {
- _parallaxScrollX = 0;
- _parallaxScrollY = 0;
- _scrollX = 0;
- _scrollY = 0;
-}
-
-/**
- * This function should be called five times with either the parallax layer
- * or a NULL pointer in order of background parallax to foreground parallax.
- */
-
-int32 Screen::initialiseBackgroundLayer(byte *parallax) {
- Parallax p;
- uint16 i, j, k;
- byte *data;
- byte *dst;
-
- debug(2, "initialiseBackgroundLayer");
-
- assert(_layer < MAXLAYERS);
-
- if (!parallax) {
- _layer++;
- return RD_OK;
- }
-
- p.read(parallax);
-
- _xBlocks[_layer] = (p.w + BLOCKWIDTH - 1) / BLOCKWIDTH;
- _yBlocks[_layer] = (p.h + BLOCKHEIGHT - 1) / BLOCKHEIGHT;
-
- _blockSurfaces[_layer] = (BlockSurface **)calloc(_xBlocks[_layer] * _yBlocks[_layer], sizeof(BlockSurface *));
- if (!_blockSurfaces[_layer])
- return RDERR_OUTOFMEMORY;
-
- // Decode the parallax layer into a large chunk of memory
-
- byte *memchunk = (byte *)calloc(_xBlocks[_layer] * _yBlocks[_layer], BLOCKWIDTH * BLOCKHEIGHT);
- if (!memchunk)
- return RDERR_OUTOFMEMORY;
-
- for (i = 0; i < p.h; i++) {
- uint32 p_offset = READ_LE_UINT32(parallax + Parallax::size() + 4 * i);
-
- if (!p_offset)
- continue;
-
- byte *pLine = parallax + p_offset;
- uint16 packets = READ_LE_UINT16(pLine);
- uint16 offset = READ_LE_UINT16(pLine + 2);
-
- data = pLine + 4;
- dst = memchunk + i * p.w + offset;
-
- if (!packets) {
- memcpy(dst, data, p.w);
- continue;
- }
-
- bool zeros = false;
-
- for (j = 0; j < packets; j++) {
- if (zeros) {
- dst += *data;
- offset += *data;
- data++;
- zeros = false;
- } else if (!*data) {
- data++;
- zeros = true;
- } else {
- uint16 count = *data++;
- memcpy(dst, data, count);
- data += count;
- dst += count;
- offset += count;
- zeros = true;
- }
- }
- }
-
- // The large memory chunk is now divided into a number of smaller
- // surfaces. For most parallax layers, we'll end up using less memory
- // this way, and it will be faster to draw since completely transparent
- // surfaces are discarded.
-
- for (i = 0; i < _xBlocks[_layer] * _yBlocks[_layer]; i++) {
- bool block_has_data = false;
- bool block_is_transparent = false;
-
- int x = BLOCKWIDTH * (i % _xBlocks[_layer]);
- int y = BLOCKHEIGHT * (i / _xBlocks[_layer]);
-
- data = memchunk + p.w * y + x;
-
- for (j = 0; j < BLOCKHEIGHT; j++) {
- for (k = 0; k < BLOCKWIDTH; k++) {
- if (x + k < p.w && y + j < p.h) {
- if (data[j * p.w + k])
- block_has_data = true;
- else
- block_is_transparent = true;
- }
- }
- }
-
- // Only assign a surface to the block if it contains data.
-
- if (block_has_data) {
- _blockSurfaces[_layer][i] = (BlockSurface *)malloc(sizeof(BlockSurface));
-
- // Copy the data into the surfaces.
- dst = _blockSurfaces[_layer][i]->data;
- for (j = 0; j < BLOCKHEIGHT; j++) {
- memcpy(dst, data, BLOCKWIDTH);
- data += p.w;
- dst += BLOCKWIDTH;
- }
-
- _blockSurfaces[_layer][i]->transparent = block_is_transparent;
-
- } else
- _blockSurfaces[_layer][i] = NULL;
- }
-
- free(memchunk);
- _layer++;
-
- return RD_OK;
-}
-
-/**
- * Should be called once after leaving the room to free up memory.
- */
-
-void Screen::closeBackgroundLayer() {
- debug(2, "CloseBackgroundLayer");
-
- for (int i = 0; i < MAXLAYERS; i++) {
- if (_blockSurfaces[i]) {
- for (int j = 0; j < _xBlocks[i] * _yBlocks[i]; j++)
- if (_blockSurfaces[i][j])
- free(_blockSurfaces[i][j]);
- free(_blockSurfaces[i]);
- _blockSurfaces[i] = NULL;
- }
- }
-
- _layer = 0;
-}
-
-#ifdef BACKEND_8BIT
-void Screen::plotYUV(byte *lut, int width, int height, byte *const *dat) {
- byte *buf = _buffer + ((480 - height) / 2) * RENDERWIDE + (640 - width) / 2;
-
- int x, y;
-
- int ypos = 0;
- int cpos = 0;
- int linepos = 0;
-
- for (y = 0; y < height; y += 2) {
- for (x = 0; x < width; x += 2) {
- int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * (BITDEPTH + 1)) + ((dat[1][cpos] + ROUNDADD) >> SHIFT)) * (BITDEPTH + 1);
- cpos++;
-
- buf[linepos ] = lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
- buf[RENDERWIDE + linepos++] = lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
- buf[linepos ] = lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
- buf[RENDERWIDE + linepos++] = lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
- }
- linepos += (2 * RENDERWIDE - width);
- ypos += width;
- }
-}
-#endif
-
-
-} // End of namespace Sword2
diff --git a/sword2/resman.cpp b/sword2/resman.cpp
deleted file mode 100644
index 7387dc8f50..0000000000
--- a/sword2/resman.cpp
+++ /dev/null
@@ -1,633 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/file.h"
-#include "common/system.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/console.h"
-#include "sword2/logic.h"
-#include "sword2/memory.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-#include "sword2/sound.h"
-
-#define Debug_Printf _vm->_debugger->DebugPrintf
-
-namespace Sword2 {
-
-// Welcome to the easy resource manager - written in simple code for easy
-// maintenance
-//
-// The resource compiler will create two files
-//
-// resource.inf which is a list of ascii cluster file names
-// resource.tab which is a table which tells us which cluster a resource
-// is located in and the number within the cluster
-
-enum {
- BOTH = 0x0, // Cluster is on both CDs
- CD1 = 0x1, // Cluster is on CD1 only
- CD2 = 0x2, // Cluster is on CD2 only
- LOCAL_CACHE = 0x4, // Cluster is cached on HDD
- LOCAL_PERM = 0x8 // Cluster is on HDD.
-};
-
-struct CdInf {
- uint8 clusterName[20]; // Null terminated cluster name.
- uint8 cd; // Cd cluster is on and whether it is on the local drive or not.
-};
-
-ResourceManager::ResourceManager(Sword2Engine *vm) {
- _vm = vm;
-
- // Until proven differently, assume we're on CD 1. This is so the start
- // dialog will be able to play any music at all.
- setCD(1);
-
- // We read in the resource info which tells us the names of the
- // resource cluster files ultimately, although there might be groups
- // within the clusters at this point it makes no difference. We only
- // wish to know what resource files there are and what is in each
-
- Common::File file;
- uint32 size;
- byte *temp;
-
- _totalClusters = 0;
- _resConvTable = NULL;
-
- if (!file.open("resource.inf"))
- error("Cannot open resource.inf");
-
- size = file.size();
-
- // Get some space for the incoming resource file - soon to be trashed
- temp = (byte *)malloc(size);
-
- if (file.read(temp, size) != size) {
- file.close();
- error("init cannot *READ* resource.inf");
- }
-
- file.close();
-
- // Ok, we've loaded in the resource.inf file which contains a list of
- // all the files now extract the filenames.
-
- // Using this method the Gode generated resource.inf must have #0d0a on
- // the last entry
-
- uint32 i = 0;
- uint32 j = 0;
-
- do {
- // item must have an #0d0a
- while (temp[i] != 13) {
- _resFiles[_totalClusters].fileName[j] = temp[i];
- i++;
- j++;
- }
-
- // NULL terminate our extracted string
- _resFiles[_totalClusters].fileName[j] = '\0';
- _resFiles[_totalClusters].numEntries = -1;
- _resFiles[_totalClusters].entryTab = NULL;
-
- // Reset position in current slot between entries, skip the
- // 0x0a in the source and increase the number of clusters.
-
- j = 0;
- i += 2;
- _totalClusters++;
-
- // TODO: put overload check here
- } while (i != size);
-
- free(temp);
-
- // Now load in the binary id to res conversion table
- if (!file.open("resource.tab"))
- error("Cannot open resource.tab");
-
- // Find how many resources
- size = file.size();
-
- _totalResFiles = size / 4;
-
- // Table seems ok so malloc some space
- _resConvTable = (uint16 *)malloc(size);
-
- for (i = 0; i < size / 2; i++)
- _resConvTable[i] = file.readUint16LE();
-
- if (file.ioFailed()) {
- file.close();
- error("Cannot read resource.tab");
- }
-
- file.close();
-
- if (!file.open("cd.inf"))
- error("Cannot open cd.inf");
-
- CdInf *cdInf = new CdInf[_totalClusters];
-
- for (i = 0; i < _totalClusters; i++) {
- file.read(cdInf[i].clusterName, sizeof(cdInf[i].clusterName));
-
- cdInf[i].cd = file.readByte();
-
- if (file.ioFailed())
- error("Cannot read cd.inf");
-
- // It has been reported that there are two different versions
- // of the cd.inf file: One where all clusters on CD also have
- // the LOCAL_CACHE bit set. This bit is no longer used. To
- // avoid future problems, let's normalize the flag once and for
- // all here.
-
- if (cdInf[i].cd & LOCAL_PERM)
- cdInf[i].cd = 0;
- else if (cdInf[i].cd & CD1)
- cdInf[i].cd = 1;
- else if (cdInf[i].cd & CD2)
- cdInf[i].cd = 2;
- else
- cdInf[i].cd = 0;
- }
-
- file.close();
-
- for (i = 0; i < _totalClusters; i++) {
- for (j = 0; j < _totalClusters; j++) {
- if (scumm_stricmp((char *)cdInf[j].clusterName, _resFiles[i].fileName) == 0)
- break;
- }
-
- if (j == _totalClusters)
- error("%s is not in cd.inf", _resFiles[i].fileName);
-
- _resFiles[i].cd = cdInf[j].cd;
- }
-
- delete [] cdInf;
-
- debug(1, "%d resources in %d cluster files", _totalResFiles, _totalClusters);
- for (i = 0; i < _totalClusters; i++)
- debug(2, "filename of cluster %d: -%s (%d)", i, _resFiles[i].fileName, _resFiles[i].cd);
-
- _resList = (Resource *)malloc(_totalResFiles * sizeof(Resource));
-
- for (i = 0; i < _totalResFiles; i++) {
- _resList[i].ptr = NULL;
- _resList[i].size = 0;
- _resList[i].refCount = 0;
- _resList[i].prev = _resList[i].next = NULL;
- }
- _cacheStart = _cacheEnd = NULL;
- _usedMem = 0;
-}
-
-ResourceManager::~ResourceManager() {
- Resource *res = _cacheStart;
- while (res) {
- _vm->_memory->memFree(res->ptr);
- res = res->next;
- }
- for (uint i = 0; i < _totalClusters; i++)
- free(_resFiles[i].entryTab);
- free(_resList);
- free(_resConvTable);
-}
-
-/**
- * Returns the address of a resource. Loads if not in memory. Retains a count.
- */
-
-byte *ResourceManager::openResource(uint32 res, bool dump) {
- assert(res < _totalResFiles);
-
- // Is the resource in memory already? If not, load it.
-
- if (!_resList[res].ptr) {
- // Fetch the correct file and read in the correct portion.
- uint16 cluFileNum = _resConvTable[res * 2]; // points to the number of the ascii filename
- assert(cluFileNum != 0xffff);
-
- // Relative resource within the file
- // First we have to find the file via the _resConvTable
- uint16 actual_res = _resConvTable[(res * 2) + 1];
-
- debug(5, "openResource %s res %d", _resFiles[cluFileNum].fileName, res);
-
- // If we're loading a cluster that's only available from one
- // of the CDs, remember which one so that we can play the
- // correct speech and music.
-
- setCD(_resFiles[cluFileNum].cd);
-
- // Actually, as long as the file can be found we don't really
- // care which CD it's on. But if we can't find it, keep asking
- // for the CD until we do.
-
- Common::File *file = openCluFile(cluFileNum);
-
- if (_resFiles[cluFileNum].entryTab == NULL) {
- // we didn't read from this file before, get its index table
- readCluIndex(cluFileNum, file);
- }
-
- uint32 pos = _resFiles[cluFileNum].entryTab[actual_res * 2 + 0];
- uint32 len = _resFiles[cluFileNum].entryTab[actual_res * 2 + 1];
-
- file->seek(pos, SEEK_SET);
-
- debug(6, "res len %d", len);
-
- // Ok, we know the length so try and allocate the memory.
- _resList[res].ptr = _vm->_memory->memAlloc(len, res);
- _resList[res].size = len;
- _resList[res].refCount = 0;
-
- file->read(_resList[res].ptr, len);
-
- debug(3, "Loaded resource '%s' from '%s' on CD %d (%d)", fetchName(_resList[res].ptr), _resFiles[cluFileNum].fileName, getCD(), _resFiles[cluFileNum].cd);
-
- if (dump) {
- char buf[256];
- const char *tag;
- Common::File out;
-
- switch (fetchType(_resList[res].ptr)) {
- case ANIMATION_FILE:
- tag = "anim";
- break;
- case SCREEN_FILE:
- tag = "layer";
- break;
- case GAME_OBJECT:
- tag = "object";
- break;
- case WALK_GRID_FILE:
- tag = "walkgrid";
- break;
- case GLOBAL_VAR_FILE:
- tag = "globals";
- break;
- case PARALLAX_FILE_null:
- tag = "parallax"; // Not used!
- break;
- case RUN_LIST:
- tag = "runlist";
- break;
- case TEXT_FILE:
- tag = "text";
- break;
- case SCREEN_MANAGER:
- tag = "screen";
- break;
- case MOUSE_FILE:
- tag = "mouse";
- break;
- case WAV_FILE:
- tag = "wav";
- break;
- case ICON_FILE:
- tag = "icon";
- break;
- case PALETTE_FILE:
- tag = "palette";
- break;
- default:
- tag = "unknown";
- break;
- }
-
-#if defined(MACOS_CARBON)
- sprintf(buf, ":dumps:%s-%d.dmp", tag, res);
-#else
- sprintf(buf, "dumps/%s-%d.dmp", tag, res);
-#endif
-
- if (!out.exists(buf, "")) {
- if (out.open(buf, Common::File::kFileWriteMode, ""))
- out.write(_resList[res].ptr, len);
- }
- }
-
- // close the cluster
- file->close();
- delete file;
-
- _usedMem += len;
- checkMemUsage();
- } else if (_resList[res].refCount == 0)
- removeFromCacheList(_resList + res);
-
- _resList[res].refCount++;
-
- return _resList[res].ptr;
-}
-
-void ResourceManager::closeResource(uint32 res) {
- assert(res < _totalResFiles);
-
- // Don't try to close the resource if it has already been forcibly
- // closed, e.g. by fnResetGlobals().
-
- if (_resList[res].ptr == NULL)
- return;
-
- assert(_resList[res].refCount > 0);
-
- _resList[res].refCount--;
- if (_resList[res].refCount == 0)
- addToCacheList(_resList + res);
-
- // It's tempting to free the resource immediately when refCount
- // reaches zero, but that'd be a mistake. Closing a resource does not
- // mean "I'm not going to use this resource any more". It means that
- // "the next time I use this resource I'm going to ask for a new
- // pointer to it".
- //
- // Since the original memory manager had to deal with memory
- // fragmentation, keeping a resource open - and thus locked down to a
- // specific memory address - was considered a bad thing.
-}
-
-void ResourceManager::removeFromCacheList(Resource *res) {
- if (_cacheStart == res)
- _cacheStart = res->next;
-
- if (_cacheEnd == res)
- _cacheEnd = res->prev;
-
- if (res->prev)
- res->prev->next = res->next;
- if (res->next)
- res->next->prev = res->prev;
- res->prev = res->next = NULL;
-}
-
-void ResourceManager::addToCacheList(Resource *res) {
- res->prev = NULL;
- res->next = _cacheStart;
- if (_cacheStart)
- _cacheStart->prev = res;
- _cacheStart = res;
- if (!_cacheEnd)
- _cacheEnd = res;
-}
-
-Common::File *ResourceManager::openCluFile(uint16 fileNum) {
- Common::File *file = new Common::File;
- while (!file->open(_resFiles[fileNum].fileName)) {
- // HACK: We have to check for this, or it'll be impossible to
- // quit while the game is asking for the user to insert a CD.
- // But recovering from this situation gracefully is just too
- // much trouble, so quit now.
- if (_vm->_quit)
- g_system->quit();
-
- // If the file is supposed to be on hard disk, or we're
- // playing a demo, then we're in trouble if the file
- // can't be found!
-
- if ((_vm->_features & GF_DEMO) || _resFiles[fileNum].cd == 0)
- error("Could not find '%s'", _resFiles[fileNum].fileName);
-
- askForCD(_resFiles[fileNum].cd);
- }
- return file;
-}
-
-void ResourceManager::readCluIndex(uint16 fileNum, Common::File *file) {
- if (_resFiles[fileNum].entryTab == NULL) {
- // we didn't read from this file before, get its index table
- if (file == NULL)
- file = openCluFile(fileNum);
- else
- file->incRef();
-
- // 1st DWORD of a cluster is an offset to the look-up table
- uint32 table_offset = file->readUint32LE();
- debug(6, "table offset = %d", table_offset);
- uint32 tableSize = file->size() - table_offset; // the table is stored at the end of the file
- file->seek(table_offset);
-
- assert((tableSize % 8) == 0);
- _resFiles[fileNum].entryTab = (uint32*)malloc(tableSize);
- _resFiles[fileNum].numEntries = tableSize / 8;
- file->read(_resFiles[fileNum].entryTab, tableSize);
- if (file->ioFailed())
- error("unable to read index table from file %s\n", _resFiles[fileNum].fileName);
-#ifdef SCUMM_BIG_ENDIAN
- for (int tabCnt = 0; tabCnt < _resFiles[fileNum].numEntries * 2; tabCnt++)
- _resFiles[fileNum].entryTab[tabCnt] = FROM_LE_32(_resFiles[fileNum].entryTab[tabCnt]);
-#endif
- file->decRef();
- }
-}
-
-/**
- * Returns true if resource is valid, otherwise false.
- */
-
-bool ResourceManager::checkValid(uint32 res) {
- // Resource number out of range
- if (res >= _totalResFiles)
- return false;
-
- // Points to the number of the ascii filename
- uint16 parent_res_file = _resConvTable[res * 2];
-
- // Null & void resource
- if (parent_res_file == 0xffff)
- return false;
-
- return true;
-}
-
-/**
- * Returns the total file length of a resource - i.e. all headers are included
- * too.
- */
-
-uint32 ResourceManager::fetchLen(uint32 res) {
- if (_resList[res].ptr)
- return _resList[res].size;
-
- // Does this ever happen?
- warning("fetchLen: Resource %u is not loaded; reading length from file", res);
-
- // Points to the number of the ascii filename
- uint16 parent_res_file = _resConvTable[res * 2];
-
- // relative resource within the file
- uint16 actual_res = _resConvTable[(res * 2) + 1];
-
- // first we have to find the file via the _resConvTable
- // open the cluster file
-
- if (_resFiles[parent_res_file].entryTab == NULL) {
- readCluIndex(parent_res_file);
- }
- return _resFiles[parent_res_file].entryTab[actual_res * 2 + 1];
-}
-
-void ResourceManager::checkMemUsage() {
- while (_usedMem > MAX_MEM_CACHE) {
- // we're using up more memory than we wanted to. free some old stuff.
- // Newly loaded objects are added to the start of the list,
- // we start freeing from the end, to free the oldest items first
- if (_cacheEnd) {
- Resource *tmp = _cacheEnd;
- assert((tmp->refCount == 0) && (tmp->ptr) && (tmp->next == NULL));
- removeFromCacheList(tmp);
-
- _vm->_memory->memFree(tmp->ptr);
- tmp->ptr = NULL;
- _usedMem -= tmp->size;
- } else {
- warning("%d bytes of memory used, but cache list is empty!\n");
- return;
- }
- }
-}
-
-void ResourceManager::remove(int res) {
- if (_resList[res].ptr) {
- removeFromCacheList(_resList + res);
-
- _vm->_memory->memFree(_resList[res].ptr);
- _resList[res].ptr = NULL;
- _resList[res].refCount = 0;
- _usedMem -= _resList[res].size;
- }
-}
-
-/**
- * Remove all res files from memory - ready for a total restart. This includes
- * the player object and global variables resource.
- */
-
-void ResourceManager::removeAll() {
- // We need to clear the FX queue, because otherwise the sound system
- // will still believe that the sound resources are in memory, and that
- // it's ok to close them.
-
- _vm->_sound->clearFxQueue();
-
- for (uint i = 0; i < _totalResFiles; i++)
- remove(i);
-}
-
-/**
- * Remove all resources from memory.
- */
-
-void ResourceManager::killAll(bool wantInfo) {
- int nuked = 0;
-
- // We need to clear the FX queue, because otherwise the sound system
- // will still believe that the sound resources are in memory, and that
- // it's ok to close them.
-
- _vm->_sound->clearFxQueue();
-
- for (uint i = 0; i < _totalResFiles; i++) {
- // Don't nuke the global variables or the player object!
- if (i == 1 || i == CUR_PLAYER_ID)
- continue;
-
- if (_resList[i].ptr) {
- if (wantInfo)
- Debug_Printf("Nuked %5d: %s\n", i, fetchName(_resList[i].ptr));
-
- remove(i);
- nuked++;
- }
- }
-
- if (wantInfo)
- Debug_Printf("Expelled %d resources\n", nuked);
-}
-
-/**
- * Like killAll but only kills objects (except George & the variable table of
- * course) - ie. forcing them to reload & restart their scripts, which
- * simulates the effect of a save & restore, thus checking that each object's
- * re-entrant logic works correctly, and doesn't cause a statuette to
- * disappear forever, or some plaster-filled holes in sand to crash the game &
- * get James in trouble again.
- */
-
-void ResourceManager::killAllObjects(bool wantInfo) {
- int nuked = 0;
-
- for (uint i = 0; i < _totalResFiles; i++) {
- // Don't nuke the global variables or the player object!
- if (i == 1 || i == CUR_PLAYER_ID)
- continue;
-
- if (_resList[i].ptr) {
- if (fetchType(_resList[i].ptr) == GAME_OBJECT) {
- if (wantInfo)
- Debug_Printf("Nuked %5d: %s\n", i, fetchName(_resList[i].ptr));
-
- remove(i);
- nuked++;
- }
- }
- }
-
- if (wantInfo)
- Debug_Printf("Expelled %d resources\n", nuked);
-}
-
-void ResourceManager::askForCD(int cd) {
- byte *textRes;
-
- // Stop any music from playing - so the system no longer needs the
- // current CD - otherwise when we take out the CD, Windows will
- // complain!
-
- _vm->_sound->stopMusic(true);
-
- textRes = openResource(2283);
- _vm->_screen->displayMsg(_vm->fetchTextLine(textRes, 5 + cd) + 2, 0);
- closeResource(2283);
-
- // The original code probably determined automagically when the correct
- // CD had been inserted, but our backend doesn't support that, and
- // anyway I don't know if all systems allow that sort of thing. So we
- // wait for the user to press any key instead, or click the mouse.
- //
- // But just in case we ever try to identify the CDs by their labels,
- // they should be:
- //
- // CD1: "RBSII1" (or "PCF76" for the PCF76 version, whatever that is)
- // CD2: "RBSII2"
-}
-
-} // End of namespace Sword2
diff --git a/sword2/resman.h b/sword2/resman.h
deleted file mode 100644
index 18b5cb8765..0000000000
--- a/sword2/resman.h
+++ /dev/null
@@ -1,134 +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 RESMAN_H
-#define RESMAN_H
-
-namespace Common {
- class File;
-}
-
-#define MAX_MEM_CACHE (8 * 1024 * 1024) // we keep up to 8 megs of resource data files in memory
-#define MAX_res_files 20
-
-namespace Sword2 {
-
-class Sword2Engine;
-
-struct Resource {
- byte *ptr;
- uint32 size;
- uint32 refCount;
- Resource *next, *prev;
-};
-
-struct ResourceFile {
- char fileName[20];
- int32 numEntries;
- uint32 *entryTab;
- uint8 cd;
-};
-
-class ResourceManager {
-private:
- Common::File *openCluFile(uint16 fileNum);
- void readCluIndex(uint16 fileNum, Common::File *file = NULL);
- void removeFromCacheList(Resource *res);
- void addToCacheList(Resource *res);
- void checkMemUsage();
-
- Sword2Engine *_vm;
-
- int _curCD;
- uint32 _totalResFiles;
- uint32 _totalClusters;
-
- // Gode generated res-id to res number/rel number conversion table
-
- uint16 *_resConvTable;
- ResourceFile _resFiles[MAX_res_files];
- Resource *_resList;
-
- Resource *_cacheStart, *_cacheEnd;
- uint32 _usedMem; // amount of used memory in bytes
-
-public:
- ResourceManager(Sword2Engine *vm); // read in the config file
- ~ResourceManager();
-
- uint32 getNumResFiles() { return _totalResFiles; }
- uint32 getNumClusters() { return _totalClusters; }
- ResourceFile *getResFiles() { return _resFiles; }
- Resource *getResList() { return _resList; }
-
- byte *openResource(uint32 res, bool dump = false);
- void closeResource(uint32 res);
-
- bool checkValid(uint32 res);
- uint32 fetchLen(uint32 res);
- uint8 fetchType(uint32 res) {
- byte *ptr = openResource(res);
- uint8 type = ptr[0];
- closeResource(res);
-
- return type;
- }
-
- uint8 fetchType(byte *ptr) {
- return ptr[0];
- }
-
- byte *fetchName(uint32 res, byte *buf) {
- byte *ptr = openResource(res);
- memcpy(buf, ptr + 10, NAME_LEN);
- closeResource(res);
-
- return buf;
- }
-
- byte *fetchName(byte *ptr) {
- return ptr + 10;
- }
-
- // Prompts the user for the specified CD.
- void askForCD(int cd);
-
- void setCD(int cd) {
- if (cd)
- _curCD = cd;
- }
-
- int getCD() {
- return _curCD;
- }
-
- void remove(int res);
- void removeAll();
-
- // ----console commands
-
- void killAll(bool wantInfo);
- void killAllObjects(bool wantInfo);
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/router.cpp b/sword2/router.cpp
deleted file mode 100644
index bbca609e3c..0000000000
--- a/sword2/router.cpp
+++ /dev/null
@@ -1,2506 +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$
- */
-
-// ---------------------------------------------------------------------------
-// ROUTER.CPP by James
-//
-// A rehash of Jeremy's original jrouter.c, containing low-level system
-// routines for calculating routes between points inside a walk-grid, and
-// constructing walk animations from mega-sets.
-//
-// jrouter.c underwent 2 major reworks from the original:
-// (1) Restructured to allow more flexibility in the mega-sets, ie. more info
-// taken from the walk-data
-// - the new George & Nico mega-sets & walk-data were then tested &
-// tweaked in the Sword1 system
-// (2) Updated for the new Sword2 system, ie. new object structures
-// - now compatible with Sword2, the essential code already having been
-// tested
-//
-// ---------------------------------------------------------------------------
-
-/****************************************************************************
- * JROUTER.C polygon router with modular walks
- * using a tree of modules
- * 21 july 94
- * 3 november 94
- * System currently works by scanning grid data and coming up with a ROUTE
- * as a series of way points(nodes), the smoothest eight directional PATH
- * through these nodes is then found, and a WALK created to fit the PATH.
- *
- * Two funtions are called by the user, RouteFinder creates a route as a
- * module list, HardWalk creates an animation list from the module list.
- * The split is only provided to allow the possibility of turning the
- * autorouter over two game cycles.
- ****************************************************************************
- *
- * Routine timings on osborne 486
- *
- * Read floor resource (file already loaded) 112 pixels
- *
- * Read mega resource (file already loaded) 112 pixels
- *
- *
- *
- ****************************************************************************
- *
- * Modified 12 Oct 95
- *
- * Target Points within 1 pixel of a line are ignored ???
- *
- * Modules split into Points within 1 pixel of a line are ignored ???
- *
- ****************************************************************************
- *
- * TOTALLY REHASHED BY JAMES FOR NEW MEGAS USING OLD SYSTEM
- * THEN REINCARNATED BY JAMES FOR NEW MEGAS USING NEW SYSTEM
- *
- ****************************************************************************/
-
-#include "common/stdafx.h"
-#include "common/stream.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-
-namespace Sword2 {
-
-//----------------------------------------------------------
-// (4) WALK-GRID FILES
-//----------------------------------------------------------
-// a walk-grid file consists of:
-//
-// standard file header
-// walk-grid file header
-// walk-grid data
-
-// Walk-Grid Header - taken directly from old "header.h" in STD_INC
-
-struct WalkGridHeader {
- int32 numBars; // number of bars on the floor
- int32 numNodes; // number of nodes
-};
-
-uint8 Router::returnSlotNo(uint32 megaId) {
- if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
- // George (8)
- return 0;
- } else {
- // One of Nico's mega id's
- return 1;
- }
-}
-
-void Router::allocateRouteMem() {
- uint8 slotNo;
-
- // Player character always always slot 0, while the other mega
- // (normally Nico) always uses slot 1
- // Better this way, so that if mega object removed from memory while
- // in middle of route, the old route will be safely cleared from
- // memory just before they create a new one
-
- slotNo = returnSlotNo(_vm->_logic->readVar(ID));
-
- // if this slot is already used, then it can't be needed any more
- // because this id is creating a new route!
-
- if (_routeSlots[slotNo])
- freeRouteMem();
-
- _routeSlots[slotNo] = (WalkData *)malloc(sizeof(WalkData) * O_WALKANIM_SIZE);
-
- // 12000 bytes were used for this in Sword1 mega compacts, based on
- // 20 bytes per 'WalkData' frame
- // ie. allowing for 600 frames including end-marker
- // Now 'WalkData' is 8 bytes, so 8*600 = 4800 bytes.
- // Note that a 600 frame walk lasts about 48 seconds!
- // (600fps / 12.5s = 48s)
-
- // mega keeps note of which slot contains the pointer to it's walk
- // animation mem block
- // +1 so that '0' can mean "not walking"
- // megaObject->route_slot_id = slotNo + 1;
-}
-
-WalkData *Router::getRouteMem() {
- uint8 slotNo = returnSlotNo(_vm->_logic->readVar(ID));
-
- return (WalkData *)_routeSlots[slotNo];
-}
-
-void Router::freeRouteMem() {
- uint8 slotNo = returnSlotNo(_vm->_logic->readVar(ID));
-
- free(_routeSlots[slotNo]);
- _routeSlots[slotNo] = NULL;
-}
-
-void Router::freeAllRouteMem() {
- for (int i = 0; i < TOTAL_ROUTE_SLOTS; i++) {
- free(_routeSlots[i]);
- _routeSlots[i] = NULL;
- }
-}
-
-int32 Router::routeFinder(byte *ob_mega, byte *ob_walkdata, int32 x, int32 y, int32 dir) {
- /*********************************************************************
- * RouteFinder.C polygon router with modular walks
- * 21 august 94
- * 3 november 94
- * routeFinder creates a list of modules that enables HardWalk to
- * create an animation list.
- *
- * routeFinder currently works by scanning grid data and coming up
- * with a ROUTE as a series of way points(nodes), the smoothest eight
- * directional PATH through these nodes is then found, this
- * information is made available to HardWalk for a WALK to be created
- * to fit the PATH.
- *
- * 30 november 94 return values modified
- *
- * return 0 = failed to find a route
- *
- * 1 = found a route
- *
- * 2 = mega already at target
- *
- *********************************************************************/
-
- int32 routeFlag = 0;
- int32 solidFlag = 0;
- WalkData *walkAnim;
-
- // megaId = id;
-
- setUpWalkGrid(ob_mega, x, y, dir);
- loadWalkData(ob_walkdata);
-
- walkAnim = getRouteMem();
-
- // All route data now loaded start finding a route
-
- // Check if we can get a route through the floor. changed 12 Oct95 JPS
-
- routeFlag = getRoute();
-
- switch (routeFlag) {
- case 2:
- // special case for zero length route
-
- // if target direction specified as any
- if (_targetDir > 7)
- _targetDir = _startDir;
-
- // just a turn on the spot is required set an end module for
- // the route let the animator deal with it
- // modularPath is normally set by extractRoute
-
- _modularPath[0].dir = _startDir;
- _modularPath[0].num = 0;
- _modularPath[0].x = _startX;
- _modularPath[0].y = _startY;
- _modularPath[1].dir = _targetDir;
- _modularPath[1].num = 0;
- _modularPath[1].x = _startX;
- _modularPath[1].y = _startY;
- _modularPath[2].dir = 9;
- _modularPath[2].num = ROUTE_END_FLAG;
-
- slidyWalkAnimator(walkAnim);
- routeFlag = 2;
- break;
- case 1:
- // A normal route. Convert the route to an exact path
- smoothestPath();
-
- // The Route had waypoints and direction options
-
- // The Path is an exact set of lines in 8 directions that
- // reach the target.
-
- // The path is in module format, but steps taken in each
- // direction are not accurate
-
- // if target dir = 8 then the walk isn't linked to an anim so
- // we can create a route without sliding and miss the exact
- // target
-
-#ifndef FORCE_SLIDY
- if (_targetDir == 8) {
- // can end facing ANY direction (ie. exact end
- // position not vital) - so use SOLID walk to
- // avoid sliding to exact position
-
- solidPath();
- solidFlag = solidWalkAnimator(walkAnim);
- }
-#endif
-
- if (!solidFlag) {
- // if we failed to create a SOLID route, do a SLIDY
- // one instead
-
- slidyPath();
- slidyWalkAnimator(walkAnim);
- }
-
- break;
- default:
- // Route didn't reach target so assume point was off the floor
- // routeFlag = 0;
- break;
- }
-
- return routeFlag; // send back null route
-}
-
-int32 Router::getRoute() {
- /*********************************************************************
- * GetRoute.C extract a path from walk grid
- * 12 october 94
- *
- * GetRoute currently works by scanning grid data and coming up with
- * a ROUTE as a series of way points(nodes).
- *
- * static routeData _route[O_ROUTE_SIZE];
- *
- * return 0 = failed to find a route
- *
- * 1 = found a route
- *
- * 2 = mega already at target
- *
- * 3 = failed to find a route because target was on a line
- *
- *********************************************************************/
-
- int32 routeGot = 0;
-
- if (_startX == _targetX && _startY == _targetY)
- routeGot = 2;
- else {
- // 'else' added by JEL (23jan96) otherwise 'routeGot' affected
- // even when already set to '2' above - causing some 'turns'
- // to walk downwards on the spot
-
- // returns 3 if target on a line ( +- 1 pixel )
- routeGot = checkTarget(_targetX, _targetY);
- }
-
- if (routeGot == 0) {
- // still looking for a route check if target is within a pixel
- // of a line
-
- // scan through the nodes linking each node to its nearest
- // neighbour until no more nodes change
-
- // This is the routine that finds a route using scan()
-
- int32 level = 1;
-
- while (scan(level))
- level++;
-
- // Check to see if the route reached the target
-
- if (_node[_nNodes].dist < 9999) {
- // it did so extract the route as nodes and the
- // directions to go between each node
-
- routeGot = 1;
- extractRoute();
-
- // route.X,route.Y and route.Dir now hold all the
- // route infomation with the target dir or route
- // continuation
- }
- }
-
- return routeGot;
-}
-
-// THE SLIDY PATH ROUTINES
-
-int32 Router::smoothestPath() {
- // This is the second big part of the route finder and the the only
- // bit that tries to be clever (the other bits are clever).
- //
- // This part of the autorouter creates a list of modules from a set of
- // lines running across the screen. The task is complicated by two
- // things:
- //
- // Firstly in choosing a route through the maze of nodes the routine
- // tries to minimise the amount of each individual turn avoiding 90
- // degree and greater turns (where possible) and reduces the total
- // number of turns (subject to two 45 degree turns being better than
- // one 90 degree turn).
- //
- // Secondly when walking in a given direction the number of steps
- // required to reach the end of that run is not calculated accurately.
- // This is because I was unable to derive a function to relate number
- // of steps taken between two points to the shrunken step size
-
- int i;
- int32 steps = 0;
- int32 lastDir;
- int32 tempturns[4];
- int32 turns[4];
- int32 turntable[NO_DIRECTIONS] = { 0, 1, 3, 5, 7, 5, 3, 1 };
-
- // route.X route.Y and route.Dir start at far end
-
- _smoothPath[0].x = _startX;
- _smoothPath[0].y = _startY;
- _smoothPath[0].dir = _startDir;
- _smoothPath[0].num = 0;
-
- lastDir = _startDir;
-
- // for each section of the route
-
- for (int p = 0; p < _routeLength; p++) {
- int32 dirS = _route[p].dirS;
- int32 dirD = _route[p].dirD;
- int32 nextDirS = _route[p + 1].dirS;
- int32 nextDirD = _route[p + 1].dirD;
-
- // Check directions into and out of a pair of nodes going in
- int32 dS = dirS - lastDir;
- if (dS < 0)
- dS = dS + NO_DIRECTIONS;
-
- int32 dD = dirD - lastDir;
- if (dD < 0)
- dD = dD + NO_DIRECTIONS;
-
- // coming out
- int32 dSS = dirS - nextDirS;
- if (dSS < 0)
- dSS = dSS + NO_DIRECTIONS;
-
- int32 dDD = dirD - nextDirD;
- if (dDD < 0)
- dDD = dDD + NO_DIRECTIONS;
-
- int32 dSD = dirS - nextDirD;
- if (dSD < 0)
- dSD = dSD + NO_DIRECTIONS;
-
- int32 dDS = dirD - nextDirS;
- if (dDS < 0)
- dDS = dDS + NO_DIRECTIONS;
-
- // Determine the amount of turning involved in each possible
- // path
-
- dS = turntable[dS];
- dD = turntable[dD];
- dSS = turntable[dSS];
- dDD = turntable[dDD];
- dSD = turntable[dSD];
- dDS = turntable[dDS];
-
- // get the best path out ie assume next section uses best
- // direction
-
- if (dSD < dSS)
- dSS = dSD;
-
- if (dDS < dDD)
- dDD = dDS;
-
- // Rate each option. Split routes look crap so weight against
- // them
-
- int32 SS = dS + dSS + 3;
- int32 SD = dS + dDD;
- int32 DS = dD + dSS;
- int32 DD = dD + dDD + 3;
-
- // set up turns as a sorted array of the turn values
-
- tempturns[0] = SS;
- turns[0] = 0;
- tempturns[1] = SD;
- turns[1] = 1;
- tempturns[2] = DS;
- turns[2] = 2;
- tempturns[3] = DD;
- turns[3] = 3;
-
- for (i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- if (tempturns[j] > tempturns[j + 1]) {
- SWAP(turns[j], turns[j + 1]);
- SWAP(tempturns[j], tempturns[j + 1]);
- }
- }
- }
-
- // best option matched in order of the priority we would like
- // to see on the screen but each option must be checked to see
- // if it can be walked
-
- int32 options = newCheck(1, _route[p].x, _route[p].y, _route[p + 1].x, _route[p + 1].y);
-
- assert(options);
-
- i = 0;
- steps = 0;
-
- do {
- int32 opt = 1 << turns[i];
- if (options & opt)
- steps = smoothCheck(turns[i], p, dirS, dirD);
- i++;
- } while (steps == 0 && i < 4);
-
- assert(steps);
-
- // route.X route.Y route.dir and bestTurns start at far end
- }
-
- // best turns will end heading as near as possible to target dir rest
- // is down to anim for now
-
- _smoothPath[steps].dir = 9;
- _smoothPath[steps].num = ROUTE_END_FLAG;
- return 1;
-}
-
-int32 Router::smoothCheck(int32 best, int32 p, int32 dirS, int32 dirD) {
- /*********************************************************************
- * Slip sliding away
- * This path checker checks to see if a walk that exactly follows the
- * path would be valid. This should be inherently true for atleast one
- * of the turn options.
- * No longer checks the data it only creates the smoothPath array JPS
- *********************************************************************/
-
- static int32 k;
- int32 dsx, dsy;
- int32 ddx, ddy;
- int32 ss0, ss1, ss2;
- int32 sd0, sd1, sd2;
-
- if (p == 0)
- k = 1;
-
- int32 x = _route[p].x;
- int32 y = _route[p].y;
- int32 x2 = _route[p + 1].x;
- int32 y2 = _route[p + 1].y;
- int32 ldx = x2 - x;
- int32 ldy = y2 - y;
- int32 dirX = 1;
- int32 dirY = 1;
-
- if (ldx < 0) {
- ldx = -ldx;
- dirX = -1;
- }
-
- if (ldy < 0) {
- ldy = -ldy;
- dirY = -1;
- }
-
- // set up sd0-ss2 to reflect possible movement in each direction
-
- if (dirS == 0 || dirS == 4) { // vert and diag
- ddx = ldx;
- ddy = (ldx * _diagonaly) / _diagonalx;
- dsy = ldy - ddy;
- ddx = ddx * dirX;
- ddy = ddy * dirY;
- dsy = dsy * dirY;
- dsx = 0;
-
- sd0 = (ddx + _modX[dirD] / 2) / _modX[dirD];
- ss0 = (dsy + _modY[dirS] / 2) / _modY[dirS];
- sd1 = sd0 / 2;
- ss1 = ss0 / 2;
- sd2 = sd0 - sd1;
- ss2 = ss0 - ss1;
- } else {
- ddy = ldy;
- ddx = (ldy * _diagonalx) / _diagonaly;
- dsx = ldx - ddx;
- ddy = ddy * dirY;
- ddx = ddx * dirX;
- dsx = dsx * dirX;
- dsy = 0;
-
- sd0 = (ddy + _modY[dirD] / 2) / _modY[dirD];
- ss0 = (dsx + _modX[dirS] / 2) / _modX[dirS];
- sd1 = sd0 / 2;
- ss1 = ss0 / 2;
- sd2 = sd0 - sd1;
- ss2 = ss0 - ss1;
- }
-
- switch (best) {
- case 0: // halfsquare, diagonal, halfsquare
- _smoothPath[k].x = x + dsx / 2;
- _smoothPath[k].y = y + dsy / 2;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss1;
- k++;
-
- _smoothPath[k].x = x + dsx / 2 + ddx;
- _smoothPath[k].y = y + dsy / 2 + ddy;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd0;
- k++;
-
- _smoothPath[k].x = x + dsx + ddx;
- _smoothPath[k].y = y + dsy + ddy;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss2;
- k++;
-
- break;
- case 1: // square, diagonal
- _smoothPath[k].x = x + dsx;
- _smoothPath[k].y = y + dsy;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss0;
- k++;
-
- _smoothPath[k].x = x2;
- _smoothPath[k].y = y2;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd0;
- k++;
-
- break;
- case 2: // diagonal square
- _smoothPath[k].x = x + ddx;
- _smoothPath[k].y = y + ddy;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd0;
- k++;
-
- _smoothPath[k].x = x2;
- _smoothPath[k].y = y2;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss0;
- k++;
-
- break;
- default: // halfdiagonal, square, halfdiagonal
- _smoothPath[k].x = x + ddx / 2;
- _smoothPath[k].y = y + ddy / 2;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd1;
- k++;
-
- _smoothPath[k].x = x + dsx + ddx / 2;
- _smoothPath[k].y = y + dsy + ddy / 2;
- _smoothPath[k].dir = dirS;
- _smoothPath[k].num = ss0;
- k++;
-
- _smoothPath[k].x = x2;
- _smoothPath[k].y = y2;
- _smoothPath[k].dir = dirD;
- _smoothPath[k].num = sd2;
- k++;
-
- break;
- }
-
- return k;
-}
-
-void Router::slidyPath() {
- /*********************************************************************
- * slidyPath creates a path based on part steps with no sliding to get
- * as near as possible to the target without any sliding this routine
- * is intended for use when just clicking about.
- *
- * produce a module list from the line data
- *********************************************************************/
-
- int32 smooth = 1;
- int32 slidy = 1;
-
- // strip out the short sections
-
- _modularPath[0].x = _smoothPath[0].x;
- _modularPath[0].y = _smoothPath[0].y;
- _modularPath[0].dir = _smoothPath[0].dir;
- _modularPath[0].num = 0;
-
- while (_smoothPath[smooth].num < ROUTE_END_FLAG) {
- int32 scale = _scaleA * _smoothPath[smooth].y + _scaleB;
- int32 deltaX = _smoothPath[smooth].x - _modularPath[slidy - 1].x;
- int32 deltaY = _smoothPath[smooth].y - _modularPath[slidy - 1].y;
- // quarter a step minimum
- int32 stepX = (scale * _modX[_smoothPath[smooth].dir]) >> 19;
- int32 stepY = (scale * _modY[_smoothPath[smooth].dir]) >> 19;
-
- if (ABS(deltaX) >= ABS(stepX) && ABS(deltaY) >= ABS(stepY)) {
- _modularPath[slidy].x = _smoothPath[smooth].x;
- _modularPath[slidy].y = _smoothPath[smooth].y;
- _modularPath[slidy].dir = _smoothPath[smooth].dir;
- _modularPath[slidy].num = 1;
- slidy++;
- }
- smooth++;
- }
-
- // in case the last bit had no steps
-
- if (slidy > 1) {
- _modularPath[slidy - 1].x = _smoothPath[smooth - 1].x;
- _modularPath[slidy - 1].y = _smoothPath[smooth - 1].y;
- }
-
- // set up the end of the walk
-
- _modularPath[slidy].x = _smoothPath[smooth - 1].x;
- _modularPath[slidy].y = _smoothPath[smooth - 1].y;
- _modularPath[slidy].dir = _targetDir;
- _modularPath[slidy].num = 0;
- slidy++;
-
- _modularPath[slidy].x = _smoothPath[smooth - 1].x;
- _modularPath[slidy].y = _smoothPath[smooth - 1].y;
- _modularPath[slidy].dir = 9;
- _modularPath[slidy].num = ROUTE_END_FLAG;
- slidy++;
-}
-
-// SLOW IN
-
-bool Router::addSlowInFrames(WalkData *walkAnim) {
- if (_walkData.usingSlowInFrames && _modularPath[1].num > 0) {
- for (int slowInFrameNo = 0; slowInFrameNo < _walkData.nSlowInFrames[_currentDir]; slowInFrameNo++) {
- walkAnim[_stepCount].frame = _firstSlowInFrame[_currentDir] + slowInFrameNo;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = _currentDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
- return true;
- }
-
- return false;
-}
-
-void Router::earlySlowOut(byte *ob_mega, byte *ob_walkdata) {
- int32 slowOutFrameNo;
- int32 walk_pc;
- WalkData *walkAnim;
-
- ObjectMega obMega(ob_mega);
-
- debug(5, "EARLY SLOW-OUT");
-
- loadWalkData(ob_walkdata);
-
- debug(5, "********************************");
- debug(5, "_framesPerStep = %d", _framesPerStep);
- debug(5, "_numberOfSlowOutFrames = %d", _numberOfSlowOutFrames);
- debug(5, "_firstWalkingTurnLeftFrame = %d", _firstWalkingTurnLeftFrame);
- debug(5, "_firstWalkingTurnRightFrame = %d", _firstWalkingTurnRightFrame);
- debug(5, "_firstSlowOutFrame = %d", _firstSlowOutFrame);
- debug(5, "********************************");
-
- walk_pc = obMega.getWalkPc();
-
- walkAnim = getRouteMem();
-
- // if this mega does actually have slow-out frames
- if (_walkData.usingSlowOutFrames) {
- // overwrite the next step (half a cycle) of the walk
- // (ie .step - 0..5)
-
- do {
- debug(5, "STEP NUMBER: walkAnim[%d].step = %d", walk_pc, walkAnim[walk_pc].step);
- debug(5, "ORIGINAL FRAME: walkAnim[%d].frame = %d", walk_pc, walkAnim[walk_pc].frame);
-
- // map from existing walk frame across to correct
- // frame number of slow-out - remember, there may be
- // more slow-out frames than walk-frames!
-
- if (walkAnim[walk_pc].frame >= _firstWalkingTurnRightFrame) {
- // if it's a walking turn-right, rather than a
- // normal step, then map it to a normal step
- // frame first
-
- walkAnim[walk_pc].frame -= _firstWalkingTurnRightFrame;
- debug(5, "MAPPED TO WALK: walkAnim[%d].frame = %d (walking turn-right frame --> walk frame)", walk_pc, walkAnim[walk_pc].frame);
- } else if (walkAnim[walk_pc].frame >= _firstWalkingTurnLeftFrame) {
- // if it's a walking turn-left, rather than a
- // normal step, then map it to a normal step
- // frame first
-
- walkAnim[walk_pc].frame -= _firstWalkingTurnLeftFrame;
- debug(5, "MAPPED TO WALK: walkAnim[%d].frame = %d (walking turn-left frame --> walk frame)", walk_pc, walkAnim[walk_pc].frame);
- }
-
- walkAnim[walk_pc].frame += _firstSlowOutFrame + ((walkAnim[walk_pc].frame / _framesPerStep) * (_numberOfSlowOutFrames - _framesPerStep));
- walkAnim[walk_pc].step = 0;
- debug(5, "SLOW-OUT FRAME: walkAnim[%d].frame = %d",walk_pc, walkAnim[walk_pc].frame);
- walk_pc++;
- } while (walkAnim[walk_pc].step > 0);
-
- // add stationary frame(s) (OPTIONAL)
-
- for (slowOutFrameNo = _framesPerStep; slowOutFrameNo < _numberOfSlowOutFrames; slowOutFrameNo++) {
- walkAnim[walk_pc].frame = walkAnim[walk_pc - 1].frame + 1;
- debug(5, "EXTRA FRAME: walkAnim[%d].frame = %d", walk_pc, walkAnim[walk_pc].frame);
- walkAnim[walk_pc].step = 0;
- walkAnim[walk_pc].dir = walkAnim[walk_pc - 1].dir;
- walkAnim[walk_pc].x = walkAnim[walk_pc - 1].x;
- walkAnim[walk_pc].y = walkAnim[walk_pc - 1].y;
- walk_pc++;
- }
- } else {
- // this mega doesn't have slow-out frames
- // stand in current direction
-
- walkAnim[walk_pc].frame = _firstStandFrame + walkAnim[walk_pc - 1].dir;
- walkAnim[walk_pc].step = 0;
- walkAnim[walk_pc].dir = walkAnim[walk_pc - 1].dir;
- walkAnim[walk_pc].x = walkAnim[walk_pc - 1].x;
- walkAnim[walk_pc].y = walkAnim[walk_pc - 1].y;
- walk_pc++;
- }
-
- // end of sequence
- walkAnim[walk_pc].frame = 512;
-
- // so that this doesn't happen again while 'george_walking' is still
- // '2'
- walkAnim[walk_pc].step = 99;
-}
-
-// SLOW OUT
-
-void Router::addSlowOutFrames(WalkData *walkAnim) {
- int32 slowOutFrameNo;
-
- // if the mega did actually walk, we overwrite the last step (half a
- // cycle) with slow-out frames + add any necessary stationary frames
-
- if (_walkData.usingSlowOutFrames && _lastCount >= _framesPerStep) {
- // place stop frames here
- // slowdown at the end of the last walk
-
- slowOutFrameNo = _lastCount - _framesPerStep;
-
- debug(5, "SLOW OUT: slowOutFrameNo(%d) = _lastCount(%d) - _framesPerStep(%d)", slowOutFrameNo, _lastCount, _framesPerStep);
-
- // overwrite the last step (half a cycle) of the walk
-
- do {
- // map from existing walk frame across to correct
- // frame number of slow-out - remember, there may be
- // more slow-out frames than walk-frames!
-
- walkAnim[slowOutFrameNo].frame += _firstSlowOutFrame + ((walkAnim[slowOutFrameNo].frame / _framesPerStep) * (_numberOfSlowOutFrames - _framesPerStep));
-
- // because no longer a normal walk-step
- walkAnim[slowOutFrameNo].step = 0;
-
- debug(5, "walkAnim[%d].frame = %d",slowOutFrameNo,walkAnim[slowOutFrameNo].frame);
- slowOutFrameNo++;
- } while (slowOutFrameNo < _lastCount);
-
- // add stationary frame(s) (OPTIONAL)
-
- for (slowOutFrameNo = _framesPerStep; slowOutFrameNo < _numberOfSlowOutFrames; slowOutFrameNo++) {
- walkAnim[_stepCount].frame = walkAnim[_stepCount - 1].frame + 1;
-
- debug(5, "EXTRA FRAMES: walkAnim[%d].frame = %d", _stepCount, walkAnim[_stepCount].frame);
-
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = walkAnim[_stepCount - 1].dir;
- walkAnim[_stepCount].x = walkAnim[_stepCount - 1].x;
- walkAnim[_stepCount].y = walkAnim[_stepCount - 1].y;
- _stepCount++;
- }
- }
-}
-
-void Router::slidyWalkAnimator(WalkData *walkAnim) {
- /*********************************************************************
- * Skidding every where HardWalk creates an animation that exactly
- * fits the smoothPath and uses foot slipping to fit whole steps into
- * the route
- *
- * Parameters: georgeg, mouseg
- * Returns: rout
- *
- * produce a module list from the line data
- *********************************************************************/
-
- static int32 left = 0;
- int32 p;
- int32 lastDir;
- int32 lastRealDir;
- int32 turnDir;
- int32 scale;
- int32 step;
- int32 module;
- int32 moduleEnd;
- int32 module16X;
- int32 module16Y;
- int32 stepX;
- int32 stepY;
- int32 errorX;
- int32 errorY;
- int32 lastErrorX;
- int32 lastErrorY;
- int32 frameCount;
- int32 frames;
-
- p = 0;
- lastDir = _modularPath[0].dir;
- _currentDir = _modularPath[1].dir;
-
- if (_currentDir == NO_DIRECTIONS)
- _currentDir = lastDir;
-
- _moduleX = _startX;
- _moduleY = _startY;
- module16X = _moduleX << 16;
- module16Y = _moduleY << 16;
- _stepCount = 0;
-
- // START THE WALK WITH THE FIRST STANDFRAME THIS MAY CAUSE A DELAY
- // BUT IT STOPS THE PLAYER MOVING FOR COLLISIONS ARE DETECTED
-
- debug(5, "SLIDY: STARTING THE WALK");
-
- module = _framesPerChar + lastDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
-
- // TURN TO START THE WALK
-
- debug(5, "SLIDY: TURNING TO START THE WALK");
- // rotate if we need to
-
- if (lastDir != _currentDir) {
- // get the direction to turn
- turnDir = _currentDir - lastDir;
- if (turnDir < 0)
- turnDir += NO_DIRECTIONS;
-
- if (turnDir > 4)
- turnDir = -1;
- else if (turnDir > 0)
- turnDir = 1;
-
- // rotate to new walk direction
- // for george and nico put in a head turn at the start
-
- if (_walkData.usingStandingTurnFrames) {
- // new frames for turn frames 29oct95jps
- if (turnDir < 0)
- module = _firstStandingTurnLeftFrame + lastDir;
- else
- module = _firstStandingTurnRightFrame + lastDir;
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // rotate till were facing new dir then go back 45 degrees
- while (lastDir != _currentDir) {
- lastDir += turnDir;
-
- // new frames for turn frames 29oct95jps
- if (turnDir < 0) {
- if ( lastDir < 0)
- lastDir += NO_DIRECTIONS;
- module = _firstStandingTurnLeftFrame + lastDir;
- } else {
- if ( lastDir > 7)
- lastDir -= NO_DIRECTIONS;
- module = _firstStandingTurnRightFrame + lastDir;
- }
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // the back 45 degrees bit
- // step back one because new head turn for george takes us
- // past the new dir
- _stepCount--;
- }
-
- // his head is in the right direction
- lastRealDir = _currentDir;
-
- // SLIDY: THE SLOW IN
-
- addSlowInFrames(walkAnim);
-
- // THE WALK
-
- debug(5, "SLIDY: THE WALK");
-
- // start the walk on the left or right leg, depending on how the
- // slow-in frames were drawn
-
- // (0 = left; 1 = right)
-
- if (_walkData.leadingLeg[_currentDir] == 0) {
- // start the walk on the left leg (ie. at beginning of the
- // first step of the walk cycle)
- left = 0;
- } else {
- // start the walk on the right leg (ie. at beginning of the
- // second step of the walk cycle)
- left = _framesPerStep;
- }
-
- _lastCount = _stepCount;
-
- // this ensures that we don't put in turn frames for the start
- lastDir = 99;
-
- // this ensures that we don't put in turn frames for the start
- _currentDir = 99;
-
- do {
- assert(_stepCount < O_WALKANIM_SIZE);
- while (_modularPath[p].num == 0) {
- p++;
- if (_currentDir != 99)
- lastRealDir = _currentDir;
- lastDir = _currentDir;
- _lastCount = _stepCount;
- }
-
- // calculate average amount to lose in each step on the way
- // to the next node
-
- _currentDir = _modularPath[p].dir;
-
- if (_currentDir < NO_DIRECTIONS) {
- module = _currentDir * _framesPerStep * 2 + left;
-
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
-
- moduleEnd = module + _framesPerStep;
- step = 0;
- scale = (_scaleA * _moduleY + _scaleB);
-
- do {
- module16X += _walkData.dx[module] * scale;
- module16Y += _walkData.dy[module] * scale;
- _moduleX = module16X >> 16;
- _moduleY = module16Y >> 16;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = step; // normally 0,1,2,3,4,5,0,1,2,etc
- walkAnim[_stepCount].dir = _currentDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- step++;
- module++;
- } while (module < moduleEnd);
-
- stepX = _modX[_modularPath[p].dir];
- stepY = _modY[_modularPath[p].dir];
- errorX = _modularPath[p].x - _moduleX;
- errorX = errorX * stepX;
- errorY = _modularPath[p].y - _moduleY;
- errorY = errorY * stepY;
-
- if (errorX < 0 || errorY < 0) {
- _modularPath[p].num = 0; // the end of the path
-
- // okay those last steps took us past our
- // target but do we want to scoot or moonwalk
-
- frames = _stepCount - _lastCount;
- errorX = _modularPath[p].x - walkAnim[_stepCount - 1].x;
- errorY = _modularPath[p].y - walkAnim[_stepCount - 1].y;
-
- if (frames > _framesPerStep) {
- lastErrorX = _modularPath[p].x - walkAnim[_stepCount - 7].x;
- lastErrorY = _modularPath[p].y - walkAnim[_stepCount - 7].y;
-
- if (stepX == 0) {
- if (3 * ABS(lastErrorY) < ABS(errorY)) {
- // the last stop was
- // closest
- _stepCount -= _framesPerStep;
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
- }
- } else {
- if (3 * ABS(lastErrorX) < ABS(errorX)) {
- //the last stop was
- // closest
- _stepCount -= _framesPerStep;
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
- }
- }
- }
-
- errorX = _modularPath[p].x - walkAnim[_stepCount-1].x;
- errorY = _modularPath[p].y - walkAnim[_stepCount-1].y;
-
- // okay we've reached the end but we still
- // have an error
-
- if (errorX != 0) {
- frameCount = 0;
- frames = _stepCount - _lastCount;
-
- do {
- frameCount++;
- walkAnim[_lastCount + frameCount - 1].x += errorX * frameCount / frames;
- } while (frameCount < frames);
- }
-
- if (errorY != 0) {
- frameCount = 0;
- frames = _stepCount - _lastCount;
- do {
- frameCount++;
- walkAnim[_lastCount + frameCount - 1].y += errorY * frameCount / frames;
- } while (frameCount < frames);
- }
-
- // Now is the time to put in the turn frames
- // for the last turn
-
- if (frames < _framesPerStep) {
- // this ensures that we don't put in
- // turn frames for this walk or the
- // next
- _currentDir = 99;
- }
-
- if (_currentDir != 99)
- lastRealDir = _currentDir;
-
- // check each turn condition in turn
-
- // only for george
- if (lastDir != 99 && _currentDir != 99 && _walkData.usingWalkingTurnFrames) {
- // 1 and -7 going right -1 and 7 going
- // left
- lastDir = _currentDir - lastDir;
-
- if (lastDir == -1 || lastDir == 7 || lastDir == -2 || lastDir == 6) {
- // turn at the end of the last
- // walk
-
- _frame = _lastCount - _framesPerStep;
- do {
- // turning left
- walkAnim[_frame].frame += _firstWalkingTurnLeftFrame;
- _frame++;
- } while (_frame < _lastCount);
- } else if (lastDir == 1 || lastDir == -7 || lastDir == 2 || lastDir == -6) {
- // turn at the end of the
- // current walk
-
- _frame = _lastCount - _framesPerStep;
- do {
- // turning right
- walkAnim[_frame].frame += _firstWalkingTurnRightFrame;
- _frame++;
- } while (_frame < _lastCount);
- }
- lastDir = _currentDir;
- }
-
- // all turns checked
-
- _lastCount = _stepCount;
- _moduleX = walkAnim[_stepCount - 1].x;
- _moduleY = walkAnim[_stepCount - 1].y;
- module16X = _moduleX << 16;
- module16Y = _moduleY << 16;
- }
- }
- } while (_modularPath[p].dir < NO_DIRECTIONS);
-
-#ifdef SWORD2_DEBUG
- if (lastRealDir == 99)
- error("slidyWalkAnimatorlast direction error");
-#endif
-
- // THE SLOW OUT
- addSlowOutFrames(walkAnim);
-
- // TURNS TO END THE WALK ?
-
- // We've done the walk now put in any turns at the end
-
- if (_targetDir == 8) {
- // ANY direction -> stand in the last direction
-
- module = _firstStandFrame + lastRealDir;
- _targetDir = lastRealDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- if (_targetDir == 9) {
- // 'stance' was non-zero
- if (_stepCount == 0) {
- module = _framesPerChar + lastRealDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
- } else if (_targetDir != lastRealDir) {
- // rotate to target direction
- turnDir = _targetDir - lastRealDir;
- if ( turnDir < 0)
- turnDir += NO_DIRECTIONS;
-
- if (turnDir > 4)
- turnDir = -1;
- else if (turnDir > 0)
- turnDir = 1;
-
- // rotate to target direction
- // for george and nico put in a head turn at the start
-
- if (_walkData.usingStandingTurnFrames) {
- // new frames for turn frames 29oct95jps
- if (turnDir < 0)
- module = _firstStandingTurnLeftFrame + lastDir;
- else
- module = _firstStandingTurnRightFrame + lastDir;
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // rotate if we need to
-
- while (lastRealDir != _targetDir) {
- lastRealDir += turnDir;
-
- // new frames for turn frames 29oct95jps
- if (turnDir < 0) {
- if (lastRealDir < 0)
- lastRealDir += NO_DIRECTIONS;
- module = _firstStandingTurnLeftFrame + lastRealDir;
- } else {
- if (lastRealDir > 7)
- lastRealDir -= NO_DIRECTIONS;
- module = _firstStandingTurnRightFrame + lastRealDir;
- }
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- module = _firstStandFrame + lastRealDir;
- walkAnim[_stepCount - 1].frame = module;
- } else {
- // just stand at the end
- module = _firstStandFrame + lastRealDir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastRealDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
-
- // write all the frames to "debug.txt"
- debug(5, "THE WALKDATA:");
-
- for (_frame = 0; _frame <= _stepCount; _frame++)
- debug(5, "walkAnim[%d].frame=%d", _frame, walkAnim[_frame].frame);
-
- debug(5, "routeFinder RouteSize is %d", _stepCount);
- return;
-}
-
-#ifndef FORCE_SLIDY
-
-// THE SOLID PATH ROUTINES
-
-int32 Router::solidPath() {
- /*********************************************************************
- * SolidPath creates a path based on whole steps with no sliding to
- * get as near as possible to the target without any sliding this
- * routine is currently unused, but is intended for use when just
- * clicking about.
- *
- * produce a module list from the line data
- *********************************************************************/
-
- int32 smooth;
- int32 solid;
- int32 scale;
- int32 stepX;
- int32 stepY;
- int32 deltaX;
- int32 deltaY;
-
- // strip out the short sections
-
- solid = 1;
- smooth = 1;
- _modularPath[0].x = _smoothPath[0].x;
- _modularPath[0].y = _smoothPath[0].y;
- _modularPath[0].dir = _smoothPath[0].dir;
- _modularPath[0].num = 0;
-
- do {
- scale = _scaleA * _smoothPath[smooth].y + _scaleB;
- deltaX = _smoothPath[smooth].x - _modularPath[solid - 1].x;
- deltaY = _smoothPath[smooth].y - _modularPath[solid - 1].y;
- stepX = _modX[_smoothPath[smooth].dir];
- stepY = _modY[_smoothPath[smooth].dir];
- stepX = stepX * scale;
- stepY = stepY * scale;
- stepX = stepX >> 16;
- stepY = stepY >> 16;
-
- if (ABS(deltaX) >= ABS(stepX) && ABS(deltaY) >= ABS(stepY)) {
- _modularPath[solid].x = _smoothPath[smooth].x;
- _modularPath[solid].y = _smoothPath[smooth].y;
- _modularPath[solid].dir = _smoothPath[smooth].dir;
- _modularPath[solid].num = 1;
- solid++;
- }
-
- smooth++;
- } while (_smoothPath[smooth].num < ROUTE_END_FLAG);
-
- // in case the last bit had no steps
-
- if (solid == 1) {
- // there were no paths so put in a dummy end
- solid = 2;
- _modularPath[1].dir = _smoothPath[0].dir;
- _modularPath[1].num = 0;
- }
-
- _modularPath[solid - 1].x = _smoothPath[smooth - 1].x;
- _modularPath[solid - 1].y = _smoothPath[smooth - 1].y;
-
- // set up the end of the walk
- _modularPath[solid].x = _smoothPath[smooth - 1].x;
- _modularPath[solid].y = _smoothPath[smooth - 1].y;
- _modularPath[solid].dir = 9;
- _modularPath[solid].num = ROUTE_END_FLAG;
-
- return 1;
-}
-
-int32 Router::solidWalkAnimator(WalkData *walkAnim) {
- /*********************************************************************
- * SolidWalk creates an animation based on whole steps with no sliding
- * to get as near as possible to the target without any sliding. This
- * routine is is intended for use when just clicking about.
- *
- * produce a module list from the line data
- *
- * returns 0 if solid route not found
- *********************************************************************/
-
- int32 left;
- int32 turnDir;
- int32 scale;
- int32 step;
- int32 errorX;
- int32 errorY;
- int32 moduleEnd;
- bool slowStart = false;
-
- // start at the beginning for a change
-
- int32 lastDir = _modularPath[0].dir;
- int32 module = _framesPerChar + lastDir;
-
- _currentDir = _modularPath[1].dir;
- _moduleX = _startX;
- _moduleY = _startY;
- _stepCount = 0;
-
- int32 module16X = _moduleX << 16;
- int32 module16Y = _moduleY << 16;
-
- // START THE WALK WITH THE FIRST STANDFRAME THIS MAY CAUSE A DELAY
- // BUT IT STOPS THE PLAYER MOVING FOR COLLISIONS ARE DETECTED
-
- debug(5, "SOLID: STARTING THE WALK");
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
-
- // TURN TO START THE WALK
-
- debug(5, "SOLID: TURNING TO START THE WALK");
-
- // rotate if we need to
-
- if (lastDir != _currentDir) {
- // get the direction to turn
- turnDir = _currentDir - lastDir;
- if (turnDir < 0)
- turnDir += NO_DIRECTIONS;
-
- if (turnDir > 4)
- turnDir = -1;
- else if (turnDir > 0)
- turnDir = 1;
-
- // rotate to new walk direction
- // for george and nico put in a head turn at the start
-
- if (_walkData.usingStandingTurnFrames) {
- // new frames for turn frames 29oct95jps
- if (turnDir < 0)
- module = _firstStandingTurnLeftFrame + lastDir;
- else
- module = _firstStandingTurnRightFrame + lastDir;
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // rotate till were facing new dir then go back 45 degrees
-
- while (lastDir != _currentDir) {
- lastDir += turnDir;
-
- // new frames for turn frames
- if (turnDir < 0) {
- if (lastDir < 0)
- lastDir += NO_DIRECTIONS;
- module = _firstStandingTurnLeftFrame + lastDir;
- } else {
- if (lastDir > 7)
- lastDir -= NO_DIRECTIONS;
- module = _firstStandingTurnRightFrame + lastDir;
- }
-
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = lastDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- }
-
- // the back 45 degrees bit
- // step back one because new head turn for george takes us
- // past the new dir
-
- _stepCount--;
- }
-
- // THE SLOW IN
-
- slowStart = addSlowInFrames(walkAnim);
-
- // THE WALK
-
- debug(5, "SOLID: THE WALK");
-
- // start the walk on the left or right leg, depending on how the
- // slow-in frames were drawn
-
- // (0 = left; 1 = right)
- if (_walkData.leadingLeg[_currentDir] == 0) {
- // start the walk on the left leg (ie. at beginning of the
- // first step of the walk cycle)
- left = 0;
- } else {
- // start the walk on the right leg (ie. at beginning of the
- // second step of the walk cycle)
- left = _framesPerStep;
- }
-
- _lastCount = _stepCount;
-
- // this ensures that we don't put in turn frames for the start
- lastDir = 99;
-
- // this ensures that we don't put in turn frames for the start
- _currentDir = 99;
-
- int32 p = 1;
-
- do {
- while (_modularPath[p].num > 0) {
- _currentDir = _modularPath[p].dir;
- if (_currentDir < NO_DIRECTIONS) {
- module = _currentDir * _framesPerStep * 2 + left;
-
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
-
- moduleEnd = module + _framesPerStep;
- step = 0;
- scale = (_scaleA * _moduleY + _scaleB);
-
- do {
- module16X += _walkData.dx[module] * scale;
- module16Y += _walkData.dy[module] * scale;
- _moduleX = module16X >> 16;
- _moduleY = module16Y >> 16;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = step; // normally 0,1,2,3,4,5,0,1,2,etc
- walkAnim[_stepCount].dir = _currentDir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
- module++;
- step++;
- } while (module < moduleEnd);
-
- errorX = _modularPath[p].x - _moduleX;
- errorX = errorX * _modX[_modularPath[p].dir];
- errorY = _modularPath[p].y - _moduleY;
- errorY = errorY * _modY[_modularPath[p].dir];
-
- if (errorX < 0 || errorY < 0) {
- _modularPath[p].num = 0;
- _stepCount -= _framesPerStep;
-
- if (left == 0)
- left = _framesPerStep;
- else
- left = 0;
-
- // Okay this is the end of a section
-
- _moduleX = walkAnim[_stepCount - 1].x;
- _moduleY = walkAnim[_stepCount - 1].y;
- module16X = _moduleX << 16;
- module16Y = _moduleY << 16;
- _modularPath[p].x = _moduleX;
- _modularPath[p].y = _moduleY;
-
- // Now is the time to put in the turn
- // frames for the last turn
-
- if (_stepCount - _lastCount < _framesPerStep) {
- // no step taken
-
- // clean up if a slow in but no
- // walk
-
- if (slowStart) {
- _stepCount -= _walkData.nSlowInFrames[_currentDir];
- _lastCount -= _walkData.nSlowInFrames[_currentDir];
- slowStart = false;
- }
-
- // this ensures that we don't
- // put in turn frames for this
- // walk or the next
-
- _currentDir = 99;
- }
-
- // check each turn condition in turn
- if (lastDir != 99 && _currentDir != 99 && _walkData.usingWalkingTurnFrames) {
- // only for george
- // 1 and -7 going right -1 and
- // 7 going left
-
- lastDir = _currentDir - lastDir;
-
- if (lastDir == -1 || lastDir == 7 || lastDir == -2 || lastDir == 6) {
- // turn at the end of
- // the last walk
-
- _frame = _lastCount - _framesPerStep;
-
- do {
- // turning left
- walkAnim[_frame].frame += _firstWalkingTurnLeftFrame;
- _frame++;
- } while (_frame < _lastCount);
- } else if (lastDir == 1 || lastDir == -7 || lastDir == 2 || lastDir == -6) {
- // turn at the end of
- // the current walk
-
- _frame = _lastCount - _framesPerStep;
- do {
- // turning right
- walkAnim[_frame].frame += _firstWalkingTurnRightFrame;
- _frame++;
- } while (_frame < _lastCount);
- }
- }
-
- // all turns checked
- _lastCount = _stepCount;
- }
- }
- }
- p++;
- lastDir = _currentDir;
-
- // can only be valid first time round
- slowStart = false;
- } while (_modularPath[p].dir < NO_DIRECTIONS);
-
- // THE SLOW OUT
-
- addSlowOutFrames(walkAnim);
-
- module = _framesPerChar + _modularPath[p - 1].dir;
- walkAnim[_stepCount].frame = module;
- walkAnim[_stepCount].step = 0;
- walkAnim[_stepCount].dir = _modularPath[p - 1].dir;
- walkAnim[_stepCount].x = _moduleX;
- walkAnim[_stepCount].y = _moduleY;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
- _stepCount++;
-
- walkAnim[_stepCount].frame = 512;
- walkAnim[_stepCount].step = 99;
-
- debug(5, "THE WALKDATA:");
-
- for (_frame = 0; _frame <= _stepCount; _frame++)
- debug(5, "walkAnim[%d].frame=%d", _frame, walkAnim[_frame].frame);
-
- // NO END TURNS
-
- debug(5, "routeFinder RouteSize is %d", _stepCount);
- // now check the route
-
- int i = 0;
-
- do {
- if (!check(_modularPath[i].x, _modularPath[i].y, _modularPath[i + 1].x, _modularPath[i + 1].y))
- p = 0;
- i++;
- } while (i < p - 1);
-
- if (p != 0) {
- _targetDir = _modularPath[p - 1].dir;
- if (checkTarget(_moduleX, _moduleY) == 3) {
- // new target on a line
- p = 0;
- debug(5, "Solid walk target was on a line %d %d", _moduleX, _moduleY);
- }
- }
-
- return p;
-}
-#endif
-
-// THE SCAN ROUTINES
-
-bool Router::scan(int32 level) {
- /*********************************************************************
- * Called successively from routeFinder until no more changes take
- * place in the grid array, ie he best path has been found
- *
- * Scans through every point in the node array and checks if there is
- * a route between each point and if this route gives a new route.
- *
- * This routine could probably halve its processing time if it doubled
- * up on the checks after each route check
- *
- *********************************************************************/
-
- int32 x1, y1, x2, y2;
- int32 distance;
- bool changed = false;
-
- // For all the nodes that have new values and a distance less than
- // enddist, ie dont check for new routes from a point we checked
- // before or from a point that is already further away than the best
- // route so far.
-
- for (int i = 0; i < _nNodes; i++) {
- if (_node[i].dist < _node[_nNodes].dist && _node[i].level == level) {
- x1 = _node[i].x;
- y1 = _node[i].y;
-
- for (int j = _nNodes; j > 0; j--) {
- if (_node[j].dist > _node[i].dist) {
- x2 = _node[j].x;
- y2 = _node[j].y;
-
- if (ABS(x2 - x1) > 4.5 * ABS(y2 - y1))
- distance = (8 * ABS(x2 - x1) + 18 * ABS(y2 - y1)) / (54 * 8) + 1;
- else
- distance = (6 * ABS(x2 - x1) + 36 * ABS(y2 - y1)) / (36 * 14) + 1;
-
- if (distance + _node[i].dist < _node[_nNodes].dist && distance + _node[i].dist < _node[j].dist) {
- if (newCheck(0, x1, y1, x2, y2)) {
- _node[j].level = level + 1;
- _node[j].dist = distance + _node[i].dist;
- _node[j].prev = i;
- changed = true;
- }
- }
- }
- }
- }
- }
-
- return changed;
-}
-
-int32 Router::newCheck(int32 status, int32 x1, int32 y1, int32 x2, int32 y2) {
- /*********************************************************************
- * newCheck routine checks if the route between two points can be
- * achieved without crossing any of the bars in the Bars array.
- *
- * newCheck differs from check in that that 4 route options are
- * considered corresponding to actual walked routes.
- *
- * Note distance doesnt take account of shrinking ???
- *
- * Note Bars array must be properly calculated ie min max dx dy co
- *********************************************************************/
-
- int32 ldx;
- int32 ldy;
- int32 dlx;
- int32 dly;
- int32 dirX;
- int32 dirY;
- int32 step1;
- int32 step2;
- int32 step3;
- int32 steps;
- int32 options;
-
- steps = 0;
- options = 0;
- ldx = x2 - x1;
- ldy = y2 - y1;
- dirX = 1;
- dirY = 1;
-
- if (ldx < 0) {
- ldx = -ldx;
- dirX = -1;
- }
-
- if (ldy < 0) {
- ldy = -ldy;
- dirY = -1;
- }
-
- // make the route options
-
- if (_diagonaly * ldx > _diagonalx * ldy) {
- // dir = 1,2 or 2,3 or 5,6 or 6,7
-
- dly = ldy;
- dlx = (ldy * _diagonalx) / _diagonaly;
- ldx = ldx - dlx;
- dlx = dlx * dirX;
- dly = dly * dirY;
- ldx = ldx * dirX;
- ldy = 0;
-
- // options are square, diagonal a code 1 route
-
- step1 = check(x1, y1, x1 + ldx, y1);
- if (step1 != 0) {
- step2 = check(x1 + ldx, y1, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 2;
- }
- }
-
- // diagonal, square a code 2 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + dlx, y1 + dly);
- if (step1 != 0) {
- step2 = check(x1 + dlx, y2, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 4;
- }
- }
- }
-
- // halfsquare, diagonal, halfsquare a code 0 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + ldx / 2, y1);
- if (step1 != 0) {
- step2 = check(x1 + ldx / 2, y1, x1 + ldx / 2 + dlx, y2);
- if (step2 != 0) {
- step3 = check(x1 + ldx / 2 + dlx, y2, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 1;
- }
- }
- }
- }
-
- //halfdiagonal, square, halfdiagonal a code 3 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + dlx / 2, y1 + dly / 2);
- if (step1 != 0) {
- step2 = check(x1 + dlx / 2, y1 + dly / 2, x1 + ldx + dlx / 2, y1 + dly / 2);
- if (step2 != 0) {
- step3 = check(x1 + ldx + dlx / 2, y1 + dly / 2, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 8;
- }
- }
- }
- }
- } else {
- // dir = 7,0 or 0,1 or 3,4 or 4,5
-
- dlx = ldx;
- dly = (ldx * _diagonaly) / _diagonalx;
- ldy = ldy - dly;
- dlx = dlx * dirX;
- dly = dly * dirY;
- ldy = ldy * dirY;
- ldx = 0;
-
- // options are square, diagonal a code 1 route
-
- step1 = check(x1 ,y1, x1, y1 + ldy);
- if (step1 != 0) {
- step2 = check(x1, y1 + ldy, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 2;
- }
- }
-
- // diagonal, square a code 2 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x2, y1 + dly);
- if (step1 != 0) {
- step2 = check(x2, y1 + dly, x2, y2);
- if (step2 != 0) {
- steps = step1 + step2;
- options |= 4;
- }
- }
- }
-
- // halfsquare, diagonal, halfsquare a code 0 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1, y1 + ldy / 2);
- if (step1 != 0) {
- step2 = check(x1, y1 + ldy / 2, x2, y1 + ldy / 2 + dly);
- if (step2 != 0) {
- step3 = check(x2, y1 + ldy / 2 + dly, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 1;
- }
- }
- }
- }
-
- // halfdiagonal, square, halfdiagonal a code 3 route
-
- if (steps == 0 || status == 1) {
- step1 = check(x1, y1, x1 + dlx / 2, y1 + dly / 2);
- if (step1 != 0) {
- step2 = check(x1 + dlx / 2, y1 + dly / 2, x1 + dlx / 2, y1 + ldy + dly / 2);
- if (step2 != 0) {
- step3 = check(x1 + dlx / 2, y1 + ldy + dly / 2, x2, y2);
- if (step3 != 0) {
- steps = step1 + step2 + step3;
- options |= 8;
- }
- }
- }
- }
- }
-
- if (status == 0)
- status = steps;
- else
- status = options;
-
- return status;
-}
-
-// CHECK ROUTINES
-
-bool Router::check(int32 x1, int32 y1, int32 x2, int32 y2) {
- // call the fastest line check for the given line
- // returns true if line didn't cross any bars
-
- if (x1 == x2 && y1 == y2)
- return true;
-
- if (x1 == x2)
- return vertCheck(x1, y1, y2);
-
- if (y1 == y2)
- return horizCheck(x1, y1, x2);
-
- return lineCheck(x1, y1, x2, y2);
-}
-
-bool Router::lineCheck(int32 x1, int32 y1, int32 x2, int32 y2) {
- bool linesCrossed = true;
-
- int32 xmin = MIN(x1, x2);
- int32 xmax = MAX(x1, x2);
- int32 ymin = MIN(y1, y2);
- int32 ymax = MAX(y1, y2);
-
- // Line set to go one step in chosen direction so ignore if it hits
- // anything
-
- int32 dirx = x2 - x1;
- int32 diry = y2 - y1;
-
- int32 co = (y1 * dirx) - (x1 * diry); // new line equation
-
- for (int i = 0; i < _nBars && linesCrossed; i++) {
- // skip if not on module
- if (xmax >= _bars[i].xmin && xmin <= _bars[i].xmax && ymax >= _bars[i].ymin && ymin <= _bars[i].ymax) {
- // Okay, it's a valid line. Calculate an intercept. Wow
- // but all this arithmetic we must have loads of time
-
- // slope it he slope between the two lines
- int32 slope = (_bars[i].dx * diry) - (_bars[i].dy *dirx);
- // assuming parallel lines don't cross
- if (slope != 0) {
- // calculate x intercept and check its on both
- // lines
- int32 xc = ((_bars[i].co * dirx) - (co * _bars[i].dx)) / slope;
-
- // skip if not on module
- if (xc >= xmin - 1 && xc <= xmax + 1) {
- // skip if not on line
- if (xc >= _bars[i].xmin - 1 && xc <= _bars[i].xmax + 1) {
- int32 yc = ((_bars[i].co * diry) - (co * _bars[i].dy)) / slope;
-
- // skip if not on module
- if (yc >= ymin - 1 && yc <= ymax + 1) {
- // skip if not on line
- if (yc >= _bars[i].ymin - 1 && yc <= _bars[i].ymax + 1) {
- linesCrossed = false;
- }
- }
- }
- }
- }
- }
- }
-
- return linesCrossed;
-}
-
-bool Router::horizCheck(int32 x1, int32 y, int32 x2) {
- bool linesCrossed = true;
-
- int32 xmin = MIN(x1, x2);
- int32 xmax = MAX(x1, x2);
-
- // line set to go one step in chosen direction so ignore if it hits
- // anything
-
- for (int i = 0; i < _nBars && linesCrossed; i++) {
- // skip if not on module
- if (xmax >= _bars[i].xmin && xmin <= _bars[i].xmax && y >= _bars[i].ymin && y <= _bars[i].ymax) {
- // Okay, it's a valid line calculate an intercept. Wow
- // but all this arithmetic we must have loads of time
-
- if (_bars[i].dy == 0)
- linesCrossed = false;
- else {
- int32 ldy = y - _bars[i].y1;
- int32 xc = _bars[i].x1 + (_bars[i].dx * ldy) / _bars[i].dy;
- // skip if not on module
- if (xc >= xmin - 1 && xc <= xmax + 1)
- linesCrossed = false;
- }
- }
- }
-
- return linesCrossed;
-}
-
-bool Router::vertCheck(int32 x, int32 y1, int32 y2) {
- bool linesCrossed = true;
-
- int32 ymin = MIN(y1, y2);
- int32 ymax = MAX(y1, y2);
-
- // Line set to go one step in chosen direction so ignore if it hits
- // anything
-
- for (int i = 0; i < _nBars && linesCrossed; i++) {
- // skip if not on module
- if (x >= _bars[i].xmin && x <= _bars[i].xmax && ymax >= _bars[i].ymin && ymin <= _bars[i].ymax) {
- // Okay, it's a valid line calculate an intercept. Wow
- // but all this arithmetic we must have loads of time
-
- // both lines vertical and overlap in x and y so they
- // cross
-
- if (_bars[i].dx == 0)
- linesCrossed = false;
- else {
- int32 ldx = x - _bars[i].x1;
- int32 yc = _bars[i].y1 + (_bars[i].dy * ldx) / _bars[i].dx;
- // the intercept overlaps
- if (yc >= ymin - 1 && yc <= ymax + 1)
- linesCrossed = false;
- }
- }
- }
-
- return linesCrossed;
-}
-
-int32 Router::checkTarget(int32 x, int32 y) {
- int32 onLine = 0;
-
- int32 xmin = x - 1;
- int32 xmax = x + 1;
- int32 ymin = y - 1;
- int32 ymax = y + 1;
-
- // check if point +- 1 is on the line
- // so ignore if it hits anything
-
- for (int i = 0; i < _nBars && onLine == 0; i++) {
- // overlapping line
- if (xmax >= _bars[i].xmin && xmin <= _bars[i].xmax && ymax >= _bars[i].ymin && ymin <= _bars[i].ymax) {
- int32 xc, yc;
-
- // okay this line overlaps the target calculate
- // an y intercept for x
-
- // vertical line so we know it overlaps y
- if (_bars[i].dx == 0)
- yc = 0;
- else {
- int ldx = x - _bars[i].x1;
- yc = _bars[i].y1 + (_bars[i].dy * ldx) / _bars[i].dx;
- }
-
- // overlapping point for y
- if (yc >= ymin && yc <= ymax) {
- // target on a line so drop out
- onLine = 3;
- debug(5, "RouteFail due to target on a line %d %d", x, y);
- } else {
- // vertical line so we know it overlaps y
- if (_bars[i].dy == 0)
- xc = 0;
- else {
- int32 ldy = y - _bars[i].y1;
- xc = _bars[i].x1 + (_bars[i].dx * ldy) / _bars[i].dy;
- }
-
- // skip if not on module
- if (xc >= xmin && xc <= xmax) {
- // target on a line so drop out
- onLine = 3;
- debug(5, "RouteFail due to target on a line %d %d", x, y);
- }
- }
- }
- }
-
- return onLine;
-}
-
-// THE SETUP ROUTINES
-
-void Router::loadWalkData(byte *ob_walkdata) {
- uint16 firstFrameOfDirection;
- uint16 walkFrameNo;
- uint32 frameCounter = 0; // starts at frame 0 of mega set
- int i;
-
- _walkData.read(ob_walkdata);
-
- // 0 = not using slow out frames; non-zero = using that many frames
- // for each leading leg for each direction
-
- _numberOfSlowOutFrames = _walkData.usingSlowOutFrames;
-
- for (i = 0; i < NO_DIRECTIONS; i++) {
- firstFrameOfDirection = i * _walkData.nWalkFrames;
-
- _modX[i] = 0;
- _modY[i] = 0;
-
- for (walkFrameNo = firstFrameOfDirection; walkFrameNo < firstFrameOfDirection + _walkData.nWalkFrames / 2; walkFrameNo++) {
- // eg. _modX[0] is the sum of the x-step sizes for the
- // first half of the walk cycle for direction 0
- _modX[i] += _walkData.dx[walkFrameNo];
- _modY[i] += _walkData.dy[walkFrameNo];
- }
- }
-
- _diagonalx = _modX[3];
- _diagonaly = _modY[3];
-
- // interpret the walk data
-
- _framesPerStep = _walkData.nWalkFrames / 2;
- _framesPerChar = _walkData.nWalkFrames * NO_DIRECTIONS;
-
- // offset pointers added Oct 30 95 JPS
- // mega id references removed 16sep96 by JEL
-
- // WALK FRAMES
- // start on frame 0
-
- frameCounter += _framesPerChar;
-
- // STAND FRAMES
- // stand frames come after the walk frames
- // one stand frame for each direction
-
- _firstStandFrame = frameCounter;
- frameCounter += NO_DIRECTIONS;
-
- // STANDING TURN FRAMES - OPTIONAL!
- // standing turn-left frames come after the slow-out frames
- // one for each direction
- // standing turn-left frames come after the standing turn-right frames
- // one for each direction
-
- if (_walkData.usingStandingTurnFrames) {
- _firstStandingTurnLeftFrame = frameCounter;
- frameCounter += NO_DIRECTIONS;
-
- _firstStandingTurnRightFrame = frameCounter;
- frameCounter += NO_DIRECTIONS;
- } else {
- // refer instead to the normal stand frames
- _firstStandingTurnLeftFrame = _firstStandFrame;
- _firstStandingTurnRightFrame = _firstStandFrame;
- }
-
- // WALKING TURN FRAMES - OPTIONAL!
- // walking left-turn frames come after the stand frames
- // walking right-turn frames come after the walking left-turn frames
-
- if (_walkData.usingWalkingTurnFrames) {
- _firstWalkingTurnLeftFrame = frameCounter;
- frameCounter += _framesPerChar;
-
- _firstWalkingTurnRightFrame = frameCounter;
- frameCounter += _framesPerChar;
- } else {
- _firstWalkingTurnLeftFrame = 0;
- _firstWalkingTurnRightFrame = 0;
- }
-
- // SLOW-IN FRAMES - OPTIONAL!
- // slow-in frames come after the walking right-turn frames
-
- if (_walkData.usingSlowInFrames) {
- // Make note of frame number of first slow-in frame for each
- // direction. There may be a different number of slow-in
- // frames in each direction
-
- for (i = 0; i < NO_DIRECTIONS; i++) {
- _firstSlowInFrame[i] = frameCounter;
- frameCounter += _walkData.nSlowInFrames[i];
- }
- }
-
- // SLOW-OUT FRAMES - OPTIONAL!
- // slow-out frames come after the slow-in frames
-
- if (_walkData.usingSlowOutFrames)
- _firstSlowOutFrame = frameCounter;
-}
-
-// THE ROUTE EXTRACTOR
-
-void Router::extractRoute() {
- /*********************************************************************
- * extractRoute gets route from the node data after a full scan, route
- * is written with just the basic way points and direction options for
- * heading to the next point.
- *********************************************************************/
-
- int32 prev;
- int32 prevx;
- int32 prevy;
- int32 last;
- int32 point;
- int32 p;
- int32 dirx;
- int32 diry;
- int32 dir;
- int32 ldx;
- int32 ldy;
-
- // extract the route from the node data
-
- prev = _nNodes;
- last = prev;
- point = O_ROUTE_SIZE - 1;
- _route[point].x = _node[last].x;
- _route[point].y = _node[last].y;
-
- do {
- point--;
- prev = _node[last].prev;
- prevx = _node[prev].x;
- prevy = _node[prev].y;
- _route[point].x = prevx;
- _route[point].y = prevy;
- last = prev;
- } while (prev > 0);
-
- // now shuffle route down in the buffer
-
- _routeLength = 0;
-
- do {
- _route[_routeLength].x = _route[point].x;
- _route[_routeLength].y = _route[point].y;
- point++;
- _routeLength++;
- } while (point < O_ROUTE_SIZE);
-
- _routeLength--;
-
- // okay the route exists as a series point now put in some directions
-
- p = 0;
-
- do {
- ldx = _route[p + 1].x - _route[p].x;
- ldy = _route[p + 1].y - _route[p].y;
- dirx = 1;
- diry = 1;
-
- if (ldx < 0) {
- ldx = -ldx;
- dirx = -1;
- }
-
- if (ldy < 0) {
- ldy = -ldy;
- diry = -1;
- }
-
- if (_diagonaly * ldx > _diagonalx * ldy) {
- // dir = 1,2 or 2,3 or 5,6 or 6,7
-
- // 2 or 6
- dir = 4 - 2 * dirx;
- _route[p].dirS = dir;
-
- // 1, 3, 5 or 7
- dir = dir + diry * dirx;
- _route[p].dirD = dir;
- } else {
- // dir = 7,0 or 0,1 or 3,4 or 4,5
-
- // 0 or 4
- dir = 2 + 2 * diry;
- _route[p].dirS = dir;
-
- // 2 or 6
- dir = 4 - 2 * dirx;
-
- // 1, 3, 5 or 7
- dir = dir + diry * dirx;
- _route[p].dirD = dir;
- }
- p++;
- } while (p < _routeLength);
-
- // set the last dir to continue previous route unless specified
-
- if (_targetDir == 8) {
- // ANY direction
- _route[p].dirS = _route[p - 1].dirS;
- _route[p].dirD = _route[p - 1].dirD;
- } else {
- _route[p].dirS = _targetDir;
- _route[p].dirD = _targetDir;
- }
-
- return;
-}
-
-void Router::setUpWalkGrid(byte *ob_mega, int32 x, int32 y, int32 dir) {
- ObjectMega obMega(ob_mega);
-
- // get walk grid file + extra grid into 'bars' & 'node' arrays
- loadWalkGrid();
-
- // copy the mega structure into the local variables for use in all
- // subroutines
-
- _startX = obMega.getFeetX();
- _startY = obMega.getFeetY();
- _startDir = obMega.getCurDir();
- _targetX = x;
- _targetY = y;
- _targetDir = dir;
-
- _scaleA = obMega.getScaleA();
- _scaleB = obMega.getScaleB();
-
- // mega's current position goes into first node
-
- _node[0].x = _startX;
- _node[0].y = _startY;
- _node[0].level = 1;
- _node[0].prev = 0;
- _node[0].dist = 0;
-
- // reset other nodes
-
- for (int i = 1; i < _nNodes; i++) {
- _node[i].level = 0;
- _node[i].prev = 0;
- _node[i].dist = 9999;
- }
-
- // target position goes into final node
- _node[_nNodes].x = _targetX;
- _node[_nNodes].y = _targetY;
- _node[_nNodes].level = 0;
- _node[_nNodes].prev = 0;
- _node[_nNodes].dist = 9999;
-}
-
-void Router::plotWalkGrid() {
- int32 i;
-
- // get walk grid file + extra grid into 'bars' & 'node' arrays
- loadWalkGrid();
-
- // lines
-
- for (i = 0; i < _nBars; i++)
- _vm->_screen->drawLine(_bars[i].x1, _bars[i].y1, _bars[i].x2, _bars[i].y2, 254);
-
- // nodes
-
- // leave node 0 for start node
- for (i = 1; i < _nNodes; i++)
- plotCross(_node[i].x, _node[i].y, 184);
-}
-
-void Router::plotCross(int16 x, int16 y, uint8 colour) {
- _vm->_screen->drawLine(x - 1, y - 1, x + 1, y + 1, colour);
- _vm->_screen->drawLine(x + 1, y - 1, x - 1, y + 1, colour);
-}
-
-void Router::loadWalkGrid() {
- WalkGridHeader floorHeader;
- byte *fPolygrid;
- uint16 fPolygridLen;
-
- _nBars = 0; // reset counts
- _nNodes = 1; // leave node 0 for start-node
-
- // STATIC GRIDS (added/removed by object logics)
-
- // go through walkgrid list
- for (int i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i]) {
- int j;
-
- // open walk grid file
- fPolygrid = _vm->_resman->openResource(_walkGridList[i]);
- fPolygridLen = _vm->_resman->fetchLen(_walkGridList[i]);
-
- Common::MemoryReadStream readS(fPolygrid, fPolygridLen);
-
- readS.seek(ResHeader::size());
-
- floorHeader.numBars = readS.readSint32LE();
- floorHeader.numNodes = readS.readSint32LE();
-
- // check that we're not going to exceed the max
- // allowed in the complete walkgrid arrays
-
- assert(_nBars + floorHeader.numBars < O_GRID_SIZE);
- assert(_nNodes + floorHeader.numNodes < O_GRID_SIZE);
-
- // lines
-
- for (j = 0; j < floorHeader.numBars; j++) {
- _bars[_nBars + j].x1 = readS.readSint16LE();
- _bars[_nBars + j].y1 = readS.readSint16LE();
- _bars[_nBars + j].x2 = readS.readSint16LE();
- _bars[_nBars + j].y2 = readS.readSint16LE();
- _bars[_nBars + j].xmin = readS.readSint16LE();
- _bars[_nBars + j].ymin = readS.readSint16LE();
- _bars[_nBars + j].xmax = readS.readSint16LE();
- _bars[_nBars + j].ymax = readS.readSint16LE();
- _bars[_nBars + j].dx = readS.readSint16LE();
- _bars[_nBars + j].dy = readS.readSint16LE();
- _bars[_nBars + j].co = readS.readSint32LE();
- }
-
- // nodes
-
- // leave node 0 for start node
- for (j = 0; j < floorHeader.numNodes; j++) {
- _node[_nNodes + j].x = readS.readSint16LE();
- _node[_nNodes + j].y = readS.readSint16LE();
- }
-
- // close walk grid file
- _vm->_resman->closeResource(_walkGridList[i]);
-
- // increment counts of total bars & nodes in whole
- // walkgrid
-
- _nBars += floorHeader.numBars;
- _nNodes += floorHeader.numNodes;
- }
- }
-}
-
-void Router::clearWalkGridList() {
- memset(_walkGridList, 0, sizeof(_walkGridList));
-}
-
-// called from fnAddWalkGrid
-
-void Router::addWalkGrid(int32 gridResource) {
- int i;
- // First, scan the list to see if this grid is already included
-
- for (i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i] == gridResource)
- return;
- }
-
- // Scan the list for a free slot
-
- for (i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i] == 0) {
- _walkGridList[i] = gridResource;
- return;
- }
- }
-
- error("_walkGridList[] full");
-}
-
-// called from fnRemoveWalkGrid
-
-void Router::removeWalkGrid(int32 gridResource) {
- for (int i = 0; i < MAX_WALKGRIDS; i++) {
- if (_walkGridList[i] == gridResource) {
- // If we've found it in the list, reset entry to zero.
- // Otherwise just ignore the request.
- _walkGridList[i] = 0;
- break;
- }
- }
-}
-
-} // End of namespace Sword2
diff --git a/sword2/router.h b/sword2/router.h
deleted file mode 100644
index 45efd046bd..0000000000
--- a/sword2/router.h
+++ /dev/null
@@ -1,255 +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 _ROUTER_H
-#define _ROUTER_H
-
-// This used to be a variable, but it was never set. Actually, it wasn't even
-// initialised!
-//
-// Define this to force the use of slidy router (so solid path not used when
-// ending walk in ANY direction)
-//
-// #define FORCE_SLIDY
-
-#include "sword2/object.h"
-
-namespace Sword2 {
-
-struct WalkData {
- uint16 frame;
- int16 x;
- int16 y;
- uint8 step;
- uint8 dir;
-};
-
-struct BarData {
- int16 x1;
- int16 y1;
- int16 x2;
- int16 y2;
- int16 xmin;
- int16 ymin;
- int16 xmax;
- int16 ymax;
- int16 dx; // x2 - x1
- int16 dy; // y2 - y1
- int32 co; // co = (y1 * dx) - (x1 * dy) from an equation for a
- // line y * dx = x * dy + co
-};
-
-struct NodeData {
- int16 x;
- int16 y;
- int16 level;
- int16 prev;
- int16 dist;
-};
-
-// because we only have 2 megas in the game!
-#define TOTAL_ROUTE_SLOTS 2
-
-#define MAX_FRAMES_PER_CYCLE 16
-#define NO_DIRECTIONS 8
-#define MAX_FRAMES_PER_CHAR (MAX_FRAMES_PER_CYCLE * NO_DIRECTIONS)
-#define ROUTE_END_FLAG 255
-
-#define MAX_WALKGRIDS 10
-
-#define O_WALKANIM_SIZE 600 // max number of nodes in router output
-#define O_GRID_SIZE 200 // max 200 lines & 200 points
-#define O_ROUTE_SIZE 50 // max number of modules in a route
-
-struct RouteData {
- int32 x;
- int32 y;
- int32 dirS;
- int32 dirD;
-};
-
-struct PathData {
- int32 x;
- int32 y;
- int32 dir;
- int32 num;
-};
-
-class Router {
-private:
- Sword2Engine *_vm;
-
- int16 _standbyX; // see fnSetStandbyCoords()
- int16 _standbyY;
- int16 _standbyDir;
-
- // stores pointers to mem blocks containing routes created & used by
- // megas (NULL if slot not in use)
- WalkData *_routeSlots[TOTAL_ROUTE_SLOTS];
-
- BarData _bars[O_GRID_SIZE];
- NodeData _node[O_GRID_SIZE];
-
- int32 _walkGridList[MAX_WALKGRIDS];
-
- int32 _nBars;
- int32 _nNodes;
-
- int32 _startX;
- int32 _startY;
- int32 _startDir;
- int32 _targetX;
- int32 _targetY;
- int32 _targetDir;
- int32 _scaleA;
- int32 _scaleB;
-
- RouteData _route[O_ROUTE_SIZE];
- PathData _smoothPath[O_ROUTE_SIZE];
- PathData _modularPath[O_ROUTE_SIZE];
- int32 _routeLength;
-
- int32 _framesPerStep;
- int32 _framesPerChar;
-
- ObjectWalkdata _walkData;
-
- int8 _modX[NO_DIRECTIONS];
- int8 _modY[NO_DIRECTIONS];
- int32 _diagonalx;
- int32 _diagonaly;
-
- int32 _firstStandFrame;
-
- int32 _firstStandingTurnLeftFrame;
- int32 _firstStandingTurnRightFrame;
-
- int32 _firstWalkingTurnLeftFrame; // left walking turn
- int32 _firstWalkingTurnRightFrame; // right walking turn
-
- uint32 _firstSlowInFrame[NO_DIRECTIONS];
-
- int32 _firstSlowOutFrame;
-
- // number of slow-out frames on for each leading-leg in each direction
- // ie. total number of slow-out frames = (numberOfSlowOutFrames * 2 *
- // NO_DIRECTIONS)
-
- int32 _numberOfSlowOutFrames;
-
- int32 _stepCount;
-
- int32 _moduleX;
- int32 _moduleY;
- int32 _currentDir;
- int32 _lastCount;
- int32 _frame;
-
- uint8 returnSlotNo(uint32 megaId);
-
- int32 getRoute();
- void extractRoute();
- void loadWalkGrid();
- void setUpWalkGrid(byte *ob_mega, int32 x, int32 y, int32 dir);
- void loadWalkData(byte *ob_walkdata);
- bool scan(int32 level);
-
- int32 newCheck(int32 status, int32 x1, int32 y1, int32 x2, int32 y2);
- bool lineCheck(int32 x1, int32 x2, int32 y1, int32 y2);
- bool vertCheck(int32 x, int32 y1, int32 y2);
- bool horizCheck(int32 x1, int32 y, int32 x2);
- bool check(int32 x1, int32 y1, int32 x2, int32 y2);
- int32 checkTarget(int32 x, int32 y);
-
- int32 smoothestPath();
- void slidyPath();
-
- int32 smoothCheck(int32 best, int32 p, int32 dirS, int32 dirD);
-
- bool addSlowInFrames(WalkData *walkAnim);
- void addSlowOutFrames(WalkData *walkAnim);
- void slidyWalkAnimator(WalkData *walkAnim);
-
-#ifndef FORCE_SLIDY
- int32 solidPath();
- int32 solidWalkAnimator(WalkData *walkAnim);
-#endif
-
- void plotCross(int16 x, int16 y, uint8 colour);
-
-public:
- Router(Sword2Engine *vm) : _vm(vm), _diagonalx(0), _diagonaly(0) {
- memset(_routeSlots, 0, sizeof(_routeSlots));
- memset(_bars, 0, sizeof(_bars));
- memset(_node, 0, sizeof(_node));
- memset(_walkGridList, 0, sizeof(_walkGridList));
- memset(_route, 0, sizeof(_route));
- memset(_smoothPath, 0, sizeof(_smoothPath));
- memset(_modularPath, 0, sizeof(_modularPath));
- memset(_modX, 0, sizeof(_modX));
- memset(_modY, 0, sizeof(_modY));
- memset(_firstSlowInFrame, 0, sizeof(_firstSlowInFrame));
- }
-
- void setStandbyCoords(int16 x, int16 y, uint8 dir);
- int whatTarget(int startX, int startY, int destX, int destY);
-
- // Sprites
- void setSpriteStatus(byte *ob_graph, uint32 type);
- void setSpriteShading(byte *ob_graph, uint32 type);
-
- // Animation
- int doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool reverse);
- int megaTableAnimate(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *animTable, bool reverse);
-
- // Walking
- int doWalk(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir);
- int walkToAnim(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 animRes);
- int walkToTalkToMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId, uint32 separation);
-
- // Turning
- int doFace(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint8 target_dir);
- int faceXY(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y);
- int faceMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId);
-
- // Standing
- void standAt(byte *ob_graph, byte *ob_mega, int32 x, int32 y, int32 dir);
- void standAfterAnim(byte *ob_graph, byte *ob_mega, uint32 animRes);
- void standAtAnim(byte *ob_graph, byte *ob_mega, uint32 animRes);
-
- int32 routeFinder(byte *ob_mega, byte *ob_walkdata, int32 x, int32 y, int32 dir);
-
- void earlySlowOut(byte *ob_mega, byte *ob_walkdata);
-
- void allocateRouteMem();
- WalkData *getRouteMem();
- void freeRouteMem();
- void freeAllRouteMem();
- void addWalkGrid(int32 gridResource);
- void removeWalkGrid(int32 gridResource);
- void clearWalkGridList();
-
- void plotWalkGrid();
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/save_rest.cpp b/sword2/save_rest.cpp
deleted file mode 100644
index df03c21be3..0000000000
--- a/sword2/save_rest.cpp
+++ /dev/null
@@ -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
diff --git a/sword2/save_rest.h b/sword2/save_rest.h
deleted file mode 100644
index 9463f3fd4a..0000000000
--- a/sword2/save_rest.h
+++ /dev/null
@@ -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
diff --git a/sword2/scroll.cpp b/sword2/scroll.cpp
deleted file mode 100644
index 3d0a263bc6..0000000000
--- a/sword2/scroll.cpp
+++ /dev/null
@@ -1,151 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-
-namespace Sword2 {
-
-// Max no of pixel allowed to scroll per cycle
-#define MAX_SCROLL_DISTANCE 8
-
-/**
- * Sets the scroll target position for the end of the game cycle. The driver
- * will then automatically scroll as many times as it can to reach this
- * position in the allotted time.
- */
-
-void Screen::setScrollTarget(int16 sx, int16 sy) {
- _scrollXTarget = sx;
- _scrollYTarget = sy;
-}
-
-/**
- * If the room is larger than the physical screen, this function is called
- * every game cycle to update the scroll offsets.
- */
-
-void Screen::setScrolling() {
- // Normally we aim to get George's feet at (320,250) from top left
- // of screen window
- // feet_x = 128 + 320
- // feet_y = 128 + 250
-
- // Set scroll offsets according to the player's coords
-
- // If the scroll offsets are being forced in script, ensure that they
- // are neither too far to the right nor too far down.
- uint32 scrollX = _vm->_logic->readVar(SCROLL_X);
- uint32 scrollY = _vm->_logic->readVar(SCROLL_Y);
-
- if (scrollX || scrollY) {
- _thisScreen.scroll_offset_x = MIN((uint16)scrollX, _thisScreen.max_scroll_offset_x);
- _thisScreen.scroll_offset_y = MIN((uint16)scrollY, _thisScreen.max_scroll_offset_y);
- return;
- }
-
- // George's offset from the centre - the desired position for him
-
- int16 offset_x = _thisScreen.player_feet_x - _thisScreen.feet_x;
- int16 offset_y = _thisScreen.player_feet_y - _thisScreen.feet_y;
-
- // Prevent scrolling too far left/right/up/down
-
- if (offset_x < 0)
- offset_x = 0;
- else if (offset_x > _thisScreen.max_scroll_offset_x)
- offset_x = _thisScreen.max_scroll_offset_x;
-
- if (offset_y < 0)
- offset_y = 0;
- else if (offset_y > _thisScreen.max_scroll_offset_y)
- offset_y = _thisScreen.max_scroll_offset_y;
-
- // First time on this screen - need absolute scroll immediately!
-
- if (_thisScreen.scroll_flag == 2) {
- debug(5, "init scroll");
- _thisScreen.scroll_offset_x = offset_x;
- _thisScreen.scroll_offset_y = offset_y;
- _thisScreen.scroll_flag = 1;
- return;
- }
-
- // Catch up with required scroll offsets - speed depending on distance
- // to catch up (dx and dy) and _scrollFraction used, but limit to
- // certain number of pixels per cycle (MAX_SCROLL_DISTANCE)
-
- int16 dx = _thisScreen.scroll_offset_x - offset_x;
- int16 dy = _thisScreen.scroll_offset_y - offset_y;
-
- uint16 scroll_distance_x; // how much we want to scroll
- uint16 scroll_distance_y;
-
- if (dx < 0) {
- // Current scroll_offset_x is less than the required value
-
- // NB. I'm adding 1 to the result of dx / SCROLL_FRACTION,
- // because it would otherwise not scroll at all when
- // dx < SCROLL_FRACTION
-
- // => inc by (fraction of the differnce) NB. dx is -ve, so we
- // subtract dx / SCROLL_FRACTION
-
- scroll_distance_x = 1 - dx / _scrollFraction;
-
- if (scroll_distance_x > MAX_SCROLL_DISTANCE)
- scroll_distance_x = MAX_SCROLL_DISTANCE;
-
- _thisScreen.scroll_offset_x += scroll_distance_x;
- } else if (dx > 0) {
- // Current scroll_offset_x is greater than
- // the required value
-
- // => dec by (fraction of the differnce)
-
- scroll_distance_x = 1 + dx / _scrollFraction;
-
- if (scroll_distance_x > MAX_SCROLL_DISTANCE)
- scroll_distance_x = MAX_SCROLL_DISTANCE;
-
- _thisScreen.scroll_offset_x -= scroll_distance_x;
- }
-
- if (dy < 0) {
- scroll_distance_y = 1 - dy / _scrollFraction;
-
- if (scroll_distance_y > MAX_SCROLL_DISTANCE)
- scroll_distance_y = MAX_SCROLL_DISTANCE;
-
- _thisScreen.scroll_offset_y += scroll_distance_y;
- } else if (dy > 0) {
- scroll_distance_y = 1 + dy / _scrollFraction;
-
- if (scroll_distance_y > MAX_SCROLL_DISTANCE)
- scroll_distance_y = MAX_SCROLL_DISTANCE;
-
- _thisScreen.scroll_offset_y -= scroll_distance_y;
- }
-}
-
-} // End of namespace Sword2
diff --git a/sword2/sound.cpp b/sword2/sound.cpp
deleted file mode 100644
index d855e88afb..0000000000
--- a/sword2/sound.cpp
+++ /dev/null
@@ -1,319 +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$
- */
-
-// ---------------------------------------------------------------------------
-// BROKEN SWORD 2
-//
-// SOUND.CPP Contains the sound engine, fx & music functions
-// Some very 'sound' code in here ;)
-//
-// (16Dec96 JEL)
-//
-// ---------------------------------------------------------------------------
-
-#include "common/stdafx.h"
-#include "common/file.h"
-#include "common/system.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-#include "sound/wave.h"
-
-namespace Sword2 {
-
-Sound::Sound(Sword2Engine *vm) {
- int i;
-
- _vm = vm;
-
- for (i = 0; i < FXQ_LENGTH; i++)
- _fxQueue[i].resource = 0;
-
- for (i = 0; i < MAXMUS; i++) {
- _music[i] = NULL;
-
- _musicFile[i].idxTab = NULL;
- _musicFile[i].idxLen = 0;
- _musicFile[i].fileSize = 0;
- _musicFile[i].fileType = 0;
- _musicFile[i].inUse = false;
-
- _speechFile[i].idxTab = NULL;
- _speechFile[i].idxLen = 0;
- _speechFile[i].fileSize = 0;
- _speechFile[i].fileType = 0;
- _speechFile[i].inUse = false;
- }
-
- _speechPaused = false;
- _musicPaused = false;
- _fxPaused = false;
-
- _speechMuted = false;
- _musicMuted = false;
- _fxMuted = false;
-
- _reverseStereo = false;
-
- _loopingMusicId = 0;
-
- _mixBuffer = NULL;
- _mixBufferLen = 0;
-
- _vm->_mixer->setupPremix(this, Audio::Mixer::kMusicSoundType);
-}
-
-Sound::~Sound() {
- _vm->_mixer->setupPremix(0);
-
- clearFxQueue();
- stopMusic(true);
- stopSpeech();
-
- free(_mixBuffer);
-
- for (int i = 0; i < MAXMUS; i++) {
- if (_musicFile[i].file.isOpen())
- _musicFile[i].file.close();
- if (_speechFile[i].file.isOpen())
- _speechFile[i].file.close();
-
- free(_musicFile[i].idxTab);
- free(_speechFile[i].idxTab);
- }
-}
-
-void Sound::setReverseStereo(bool reverse) {
- if (reverse != _reverseStereo) {
- _reverseStereo = reverse;
-
- for (int i = 0; i < FXQ_LENGTH; i++) {
- if (!_fxQueue[i].resource)
- continue;
-
- _fxQueue[i].pan = -_fxQueue[i].pan;
- _vm->_mixer->setChannelBalance(_fxQueue[i].handle, _fxQueue[i].pan);
- }
- }
-}
-
-/**
- * Stop all sounds, close their resources and clear the FX queue.
- */
-
-void Sound::clearFxQueue() {
- for (int i = 0; i < FXQ_LENGTH; i++) {
- if (_fxQueue[i].resource) {
- stopFx(i);
- }
- }
-}
-
-/**
- * Process the FX queue. This function is called once every game cycle.
- */
-
-void Sound::processFxQueue() {
- for (int i = 0; i < FXQ_LENGTH; i++) {
- if (!_fxQueue[i].resource)
- continue;
-
- switch (_fxQueue[i].type) {
- case FX_RANDOM:
- // 1 in 'delay' chance of this fx occurring
- if (_vm->_rnd.getRandomNumber(_fxQueue[i].delay) == 0)
- playFx(&_fxQueue[i]);
- break;
- case FX_SPOT:
- if (_fxQueue[i].delay)
- _fxQueue[i].delay--;
- else {
- playFx(&_fxQueue[i]);
- _fxQueue[i].type = FX_SPOT2;
- }
- break;
- case FX_LOOP:
- playFx(&_fxQueue[i]);
- _fxQueue[i].type = FX_LOOPING;
- break;
- case FX_SPOT2:
- // Once the FX has finished remove it from the queue.
- if (!_vm->_mixer->isSoundHandleActive(_fxQueue[i].handle)) {
- _vm->_resman->closeResource(_fxQueue[i].resource);
- _fxQueue[i].resource = 0;
- }
- break;
- case FX_LOOPING:
- // Once the looped FX has started we can ignore it,
- // but we can't close it since the WAV data is in use.
- break;
- }
- }
-}
-
-/**
- * Queue a sound effect for playing later.
- * @param res the sound resource number
- * @param type the type of sound effect
- * @param delay when to play the sound effect
- * @param volume the sound effect volume (0 through 16)
- * @param pan the sound effect panning (-16 through 16)
- */
-
-void Sound::queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan) {
- if (_vm->_wantSfxDebug) {
- const char *typeStr;
-
- switch (type) {
- case FX_SPOT:
- typeStr = "SPOT";
- break;
- case FX_LOOP:
- typeStr = "LOOPED";
- break;
- case FX_RANDOM:
- typeStr = "RANDOM";
- break;
- default:
- typeStr = "INVALID";
- break;
- }
-
- byte buf[NAME_LEN];
-
- debug(0, "SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", _vm->_resman->fetchName(res, buf), volume, pan, delay, typeStr);
- }
-
- for (int i = 0; i < FXQ_LENGTH; i++) {
- if (!_fxQueue[i].resource) {
- byte *data = _vm->_resman->openResource(res);
-
- assert(_vm->_resman->fetchType(data) == WAV_FILE);
-
- uint32 len = _vm->_resman->fetchLen(res) - ResHeader::size();
-
- if (type == FX_RANDOM) {
- // For spot effects and loops the delay is the
- // number of frames to wait. For random
- // effects, however, it's the average number of
- // seconds between playing the sound, so we
- // have to multiply by the frame rate.
- delay *= 12;
- }
-
- volume = (volume * Audio::Mixer::kMaxChannelVolume) / 16;
- pan = (pan * 127) / 16;
-
- if (isReverseStereo())
- pan = -pan;
-
- _fxQueue[i].resource = res;
- _fxQueue[i].data = data + ResHeader::size();
- _fxQueue[i].len = len;
- _fxQueue[i].delay = delay;
- _fxQueue[i].volume = volume;
- _fxQueue[i].pan = pan;
- _fxQueue[i].type = type;
-
- // Keep track of the index in the loop so that
- // fnStopFx() can be used later to kill this sound.
- // Mainly for FX_LOOP and FX_RANDOM.
-
- _vm->_logic->writeVar(RESULT, i);
- return;
- }
- }
-
- warning("No free slot in FX queue");
-}
-
-int32 Sound::playFx(FxQueueEntry *fx) {
- return playFx(&fx->handle, fx->data, fx->len, fx->volume, fx->pan, (fx->type == FX_LOOP), Audio::Mixer::kSFXSoundType);
-}
-
-int32 Sound::playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, Audio::Mixer::SoundType soundType) {
- if (_fxMuted)
- return RD_OK;
-
- if (_vm->_mixer->isSoundHandleActive(*handle))
- return RDERR_FXALREADYOPEN;
-
- Common::MemoryReadStream stream(data, len);
- int rate, size;
- byte flags;
-
- if (!loadWAVFromStream(stream, size, rate, flags)) {
- warning("playFX: Not a valid WAV file");
- return RDERR_INVALIDWAV;
- }
-
- // The resource manager must have complete control over when resources
- // are freed, or reference counting will break horribly. Besides, the
- // data pointer is not valid for passing to free(). Why the hell is the
- // AUTOFREE flag set by default anyway?
-
- flags &= ~Audio::Mixer::FLAG_AUTOFREE;
-
- if (isReverseStereo())
- flags |= Audio::Mixer::FLAG_REVERSE_STEREO;
-
- if (loop)
- flags |= Audio::Mixer::FLAG_LOOP;
-
- _vm->_mixer->playRaw(handle, data + stream.pos(), size, rate, flags, -1, vol, pan, 0, 0, soundType);
- return RD_OK;
-}
-
-/**
- * This function closes a sound effect which has been previously opened for
- * playing. Sound effects must be closed when they are finished with, otherwise
- * you will run out of sound effect buffers.
- * @param i the index of the sound to close
- */
-
-int32 Sound::stopFx(int32 i) {
- if (!_fxQueue[i].resource)
- return RDERR_FXNOTOPEN;
-
- _vm->_mixer->stopHandle(_fxQueue[i].handle);
-
- _vm->_resman->closeResource(_fxQueue[i].resource);
- _fxQueue[i].resource = 0;
- return RD_OK;
-}
-
-void Sound::pauseAllSound() {
- pauseMusic();
- pauseSpeech();
- pauseFx();
-}
-
-void Sound::unpauseAllSound() {
- unpauseMusic();
- unpauseSpeech();
- unpauseFx();
-}
-
-} // End of namespace Sword2
diff --git a/sword2/sound.h b/sword2/sound.h
deleted file mode 100644
index 7390a60bbc..0000000000
--- a/sword2/sound.h
+++ /dev/null
@@ -1,272 +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$
- */
-
-/*****************************************************************************
- * SOUND.H Sound engine
- *
- * SOUND.CPP Contains the sound engine, fx & music functions
- * Some very 'sound' code in here ;)
- *
- * (16Dec96 JEL)
- *
- ****************************************************************************/
-
-#ifndef SOUND_H
-#define SOUND_H
-
-#include "common/file.h"
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-
-// Max number of sound fx
-#define MAXMUS 2
-
-// Max number of fx in queue at once
-#define FXQ_LENGTH 32
-
-#define BUFFER_SIZE 4096
-
-namespace Sword2 {
-
-enum {
- kCLUMode = 1,
- kMP3Mode,
- kVorbisMode,
- kFlacMode
-};
-
-enum {
- // These three types correspond to types set by the scripts
- FX_SPOT = 0,
- FX_LOOP = 1,
- FX_RANDOM = 2,
-
- // These are used for FX queue bookkeeping
- FX_SPOT2 = 3,
- FX_LOOPING = 4
-};
-
-// Sound defines
-
-enum {
- RDSE_SAMPLEFINISHED = 0,
- RDSE_SAMPLEPLAYING = 1,
- RDSE_FXTOCLEAR = 0, // Unused
- RDSE_FXCACHED = 1, // Unused
- RDSE_FXSPOT = 0,
- RDSE_FXLOOP = 1,
- RDSE_FXLEADIN = 2,
- RDSE_FXLEADOUT = 3,
- RDSE_QUIET = 1,
- RDSE_SPEAKING = 0
-};
-
-class CLUInputStream : public AudioStream {
-private:
- Common::File *_file;
- bool _firstTime;
- uint32 _file_pos;
- uint32 _end_pos;
- int16 _outbuf[BUFFER_SIZE];
- byte _inbuf[BUFFER_SIZE];
- const int16 *_bufferEnd;
- const int16 *_pos;
-
- uint16 _prev;
-
- void refill();
-
- inline bool eosIntern() const {
- return _pos >= _bufferEnd;
- }
-
-public:
- CLUInputStream(Common::File *file, int size);
- ~CLUInputStream();
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool endOfData() const { return eosIntern(); }
- bool isStereo() const { return false; }
- int getRate() const { return 22050; }
-};
-
-struct SoundFileHandle {
- Common::File file;
- uint32 *idxTab;
- uint32 idxLen;
- uint32 fileSize;
- uint32 fileType;
- volatile bool inUse;
-};
-
-class MusicInputStream : public AudioStream {
-private:
- int _cd;
- SoundFileHandle *_fh;
- uint32 _musicId;
- AudioStream *_decoder;
- int16 _buffer[BUFFER_SIZE];
- const int16 *_bufferEnd;
- const int16 *_pos;
- bool _remove;
- uint32 _numSamples;
- uint32 _samplesLeft;
- bool _looping;
- int32 _fading;
- int32 _fadeSamples;
- bool _paused;
-
- void refill();
-
- inline bool eosIntern() const {
- if (_looping)
- return false;
- return _remove || _pos >= _bufferEnd;
- }
-
-public:
- MusicInputStream(int cd, SoundFileHandle *fh, uint32 musicId, bool looping);
- ~MusicInputStream();
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool endOfData() const { return eosIntern(); }
- bool isStereo() const { return _decoder->isStereo(); }
- int getRate() const { return _decoder->getRate(); }
-
- int getCD() { return _cd; }
-
- void fadeUp();
- void fadeDown();
-
- bool isReady() { return _decoder != NULL; }
- int32 isFading() { return _fading; }
-
- bool readyToRemove();
- int32 getTimeRemaining();
-};
-
-class Sound : public AudioStream {
-private:
- Sword2Engine *_vm;
-
- Common::Mutex _mutex;
-
- struct FxQueueEntry {
- Audio::SoundHandle handle; // sound handle
- uint32 resource; // resource id of sample
- byte *data; // pointer to WAV data
- uint32 len; // WAV data length
- uint16 delay; // cycles to wait before playing (or 'random chance' if FX_RANDOM)
- uint8 volume; // sound volume
- int8 pan; // sound panning
- uint8 type; // FX_SPOT, FX_RANDOM, FX_LOOP
- };
-
- FxQueueEntry _fxQueue[FXQ_LENGTH];
-
- void triggerFx(uint8 i);
-
- bool _reverseStereo;
-
- bool _speechMuted;
- bool _fxMuted;
- bool _musicMuted;
-
- bool _speechPaused;
- bool _fxPaused;
- bool _musicPaused;
-
- int32 _loopingMusicId;
-
- Audio::SoundHandle _soundHandleSpeech;
-
- MusicInputStream *_music[MAXMUS];
- SoundFileHandle _musicFile[MAXMUS];
- SoundFileHandle _speechFile[MAXMUS];
-
- int16 *_mixBuffer;
- int _mixBufferLen;
-
-public:
- Sound(Sword2Engine *vm);
- ~Sound();
-
- // AudioStream API
-
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return false; }
- bool endOfData() const;
- int getRate() const { return 22050; }
-
- // End of AudioStream API
-
- void clearFxQueue();
- void processFxQueue();
-
- void setReverseStereo(bool reverse);
- bool isReverseStereo() const { return _reverseStereo; }
-
- void muteSpeech(bool mute);
- bool isSpeechMute() const { return _speechMuted; }
-
- void muteFx(bool mute);
- bool isFxMute() const { return _fxMuted; }
-
- void muteMusic(bool mute) { _musicMuted = mute; }
- bool isMusicMute() const { return _musicMuted; }
-
- void setLoopingMusicId(int32 id) { _loopingMusicId = id; }
- int32 getLoopingMusicId() const { return _loopingMusicId; }
-
- void pauseSpeech();
- void unpauseSpeech();
-
- void pauseFx();
- void unpauseFx();
-
- void pauseMusic();
- void unpauseMusic();
-
- void pauseAllSound();
- void unpauseAllSound();
-
- void queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan);
- int32 playFx(FxQueueEntry *fx);
- int32 playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, Audio::Mixer::SoundType soundType);
- int32 stopFx(int32 i);
- int32 setFxIdVolumePan(int32 id, int vol, int pan = 255);
-
- int32 getSpeechStatus();
- int32 amISpeaking();
- int32 playCompSpeech(uint32 speechId, uint8 vol, int8 pan);
- uint32 preFetchCompSpeech(uint32 speechId, uint16 **buf);
- int32 stopSpeech();
-
- int32 streamCompMusic(uint32 musicId, bool loop);
- void stopMusic(bool immediately);
- int32 musicTimeRemaining();
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/speech.cpp b/sword2/speech.cpp
deleted file mode 100644
index da6bd258ea..0000000000
--- a/sword2/speech.cpp
+++ /dev/null
@@ -1,229 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/file.h"
-
-#include "sword2/sword2.h"
-#include "sword2/console.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/resman.h"
-
-namespace Sword2 {
-
-// To request the status of a target, we run its 4th script, get-speech-state.
-// This will cause RESULT to be set to either 1 (target is waiting) or 0
-// (target is busy).
-
-// Distance kept above talking sprite
-#define GAP_ABOVE_HEAD 20
-
-enum {
- S_OB_GRAPHIC = 0,
- S_OB_SPEECH = 1,
- S_OB_LOGIC = 2,
- S_OB_MEGA = 3,
-
- S_TEXT = 4,
- S_WAV = 5,
- S_ANIM = 6,
- S_DIR_TABLE = 7,
- S_ANIM_MODE = 8
-};
-
-/**
- * Sets _textX and _textY for position of text sprite. Note that _textX is
- * also used to calculate speech pan.
- */
-
-void Logic::locateTalker(int32 *params) {
- // params: 0 pointer to ob_graphic
- // 1 pointer to ob_speech
- // 2 pointer to ob_logic
- // 3 pointer to ob_mega
- // 4 encoded text number
- // 5 wav res id
- // 6 anim res id
- // 7 pointer to anim table
- // 8 animation mode 0 lip synced,
- // 1 just straight animation
-
- if (!_animId) {
- // There is no animation. Assume it's voice-over text, and put
- // it at the bottom of the screen.
-
- _textX = 320;
- _textY = 400;
- return;
- }
-
- byte *file = _vm->_resman->openResource(_animId);
-
- // '0' means 1st frame
-
- CdtEntry cdt_entry;
- FrameHeader frame_head;
-
- cdt_entry.read(_vm->fetchCdtEntry(file, 0));
- frame_head.read(_vm->fetchFrameHeader(file, 0));
-
- // Note: This part of the code is quite similar to registerFrame().
-
- if (cdt_entry.frameType & FRAME_OFFSET) {
- // The frame has offsets, i.e. it's a scalable mega frame
- ObjectMega obMega(decodePtr(params[S_OB_MEGA]));
-
- uint16 scale = obMega.calcScale();
-
- // Calc suitable centre point above the head, based on scaled
- // height
-
- // just use 'feet_x' as centre
- _textX = obMega.getFeetX();
-
- // Add scaled y-offset to feet_y coord to get top of sprite
- _textY = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
- } else {
- // It's a non-scaling anim - calc suitable centre point above
- // the head, based on scaled width
-
- // x-coord + half of width
- _textX = cdt_entry.x + frame_head.width / 2;
- _textY = cdt_entry.y;
- }
-
- _vm->_resman->closeResource(_animId);
-
- // Leave space above their head
- _textY -= GAP_ABOVE_HEAD;
-
- // Adjust the text coords for RDSPR_DISPLAYALIGN
-
- ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
-
- _textX -= screenInfo->scroll_offset_x;
- _textY -= screenInfo->scroll_offset_y;
-}
-
-/**
- * This function is called the first time to build the text, if we need one. If
- * If necessary it also brings in the wav and sets up the animation.
- *
- * If there is an animation it can be repeating lip-sync or run-once.
- *
- * If there is no wav, then the text comes up instead. There can be any
- * combination of text/wav playing.
- */
-
-void Logic::formText(int32 *params) {
- // params 0 pointer to ob_graphic
- // 1 pointer to ob_speech
- // 2 pointer to ob_logic
- // 3 pointer to ob_mega
- // 4 encoded text number
- // 5 wav res id
- // 6 anim res id
- // 7 pointer to anim table
- // 8 animation mode 0 lip synced,
- // 1 just straight animation
-
- // There should always be a text line, as all text is derived from it.
- // If there is none, that's bad...
-
- if (!params[S_TEXT]) {
- warning("No text line for speech wav %d", params[S_WAV]);
- return;
- }
-
- ObjectSpeech obSpeech(decodePtr(params[S_OB_SPEECH]));
-
- // Establish the max width allowed for this text sprite.
- uint32 textWidth = obSpeech.getWidth();
-
- if (!textWidth)
- textWidth = 400;
-
- // Pull out the text line, and make the sprite and text block
-
- uint32 text_res = params[S_TEXT] / SIZE;
- uint32 local_text = params[S_TEXT] & 0xffff;
- byte *text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
-
- // 'text + 2' to skip the first 2 bytes which form the line reference
- // number
-
- _speechTextBlocNo = _vm->_fontRenderer->buildNewBloc(
- text + 2, _textX, _textY,
- textWidth, obSpeech.getPen(),
- RDSPR_TRANS | RDSPR_DISPLAYALIGN,
- _vm->_speechFontId, POSITION_AT_CENTRE_OF_BASE);
-
- _vm->_resman->closeResource(text_res);
-
- // Set speech duration, in case not using a wav.
- _speechTime = strlen((char *)text) + 30;
-}
-
-/**
- * There are some hard-coded cases where speech is used to illustrate a sound
- * effect. In this case there is no sound associated with the speech itself.
- */
-
-bool Logic::wantSpeechForLine(uint32 wavId) {
- switch (wavId) {
- case 1328: // AttendantSpeech
- // SFX(Phone71);
- // FX <Telephone rings>
- case 2059: // PabloSpeech
- // SFX (2059);
- // FX <Sound of sporadic gunfire from below>
- case 4082: // DuaneSpeech
- // SFX (4082);
- // FX <Pffffffffffft! Frp. (Unimpressive, flatulent noise.)>
- case 4214: // cat_52
- // SFX (4214);
- // 4214FXMeow!
- case 4568: // trapdoor_13
- // SFX (4568);
- // 4568fx<door slamming>
- case 4913: // LobineauSpeech
- // SFX (tone2);
- // FX <Lobineau hangs up>
- case 5120: // bush_66
- // SFX (5120);
- // 5120FX<loud buzzing>
- case 528: // PresidentaSpeech
- // SFX (528);
- // FX <Nearby Crash of Collapsing Masonry>
- case 920: // Zombie Island forest maze (bird)
- case 923: // Zombie Island forest maze (monkey)
- case 926: // Zombie Island forest maze (zombie)
- // Don't want speech for these lines!
- return false;
- default:
- // Ok for all other lines
- return true;
- }
-}
-
-} // End of namespace Sword2
diff --git a/sword2/sprite.cpp b/sword2/sprite.cpp
deleted file mode 100644
index a0ba7f7189..0000000000
--- a/sword2/sprite.cpp
+++ /dev/null
@@ -1,655 +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$
- */
-
-#include "common/stdafx.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/build_display.h"
-
-namespace Sword2 {
-
-/**
- * This function takes a sprite and creates a mirror image of it.
- * @param dst destination buffer
- * @param src source buffer
- * @param w width of the sprite
- * @param h height of the sprite
- */
-
-void Screen::mirrorSprite(byte *dst, byte *src, int16 w, int16 h) {
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- *dst++ = *(src + w - x - 1);
- }
- src += w;
- }
-}
-
-/**
- * This function takes a compressed frame of a sprite with up to 256 colours
- * and decompresses it.
- * @param dst destination buffer
- * @param src source buffer
- * @param decompSize the expected size of the decompressed sprite
- */
-
-int32 Screen::decompressRLE256(byte *dst, byte *src, int32 decompSize) {
- // PARAMETERS:
- // source points to the start of the sprite data for input
- // decompSize gives size of decompressed data in bytes
- // dest points to start of destination buffer for decompressed
- // data
-
- byte headerByte; // block header byte
- byte *endDest = dst + decompSize; // pointer to byte after end of decomp buffer
- int32 rv;
-
- while (1) {
- // FLAT block
- // read FLAT block header & increment 'scan' to first pixel
- // of block
- headerByte = *src++;
-
- // if this isn't a zero-length block
- if (headerByte) {
- if (dst + headerByte > endDest) {
- rv = 1;
- break;
- }
-
- // set the next 'headerByte' pixels to the next colour
- // at 'source'
- memset(dst, *src, headerByte);
-
- // increment destination pointer to just after this
- // block
- dst += headerByte;
-
- // increment source pointer to just after this colour
- src++;
-
- // if we've decompressed all of the data
- if (dst == endDest) {
- rv = 0; // return "OK"
- break;
- }
- }
-
- // RAW block
- // read RAW block header & increment 'scan' to first pixel of
- // block
- headerByte = *src++;
-
- // if this isn't a zero-length block
- if (headerByte) {
- if (dst + headerByte > endDest) {
- rv = 1;
- break;
- }
-
- // copy the next 'headerByte' pixels from source to
- // destination
- memcpy(dst, src, headerByte);
-
- // increment destination pointer to just after this
- // block
- dst += headerByte;
-
- // increment source pointer to just after this block
- src += headerByte;
-
- // if we've decompressed all of the data
- if (dst == endDest) {
- rv = 0; // return "OK"
- break;
- }
- }
- }
-
- return rv;
-}
-
-/**
- * Unwinds a run of 16-colour data into 256-colour palette data.
- */
-
-void Screen::unwindRaw16(byte *dst, byte *src, uint8 blockSize, byte *colTable) {
- // for each pair of pixels
- while (blockSize > 1) {
- // 1st colour = number in table at position given by upper
- // nibble of source byte
- *dst++ = colTable[(*src) >> 4];
-
- // 2nd colour = number in table at position given by lower
- // nibble of source byte
- *dst++ = colTable[(*src) & 0x0f];
-
- // point to next source byte
- src++;
-
- // decrement count of how many pixels left to read
- blockSize -= 2;
- }
-
- // if there's a final odd pixel
- if (blockSize) {
- // colour = number in table at position given by upper nibble
- // of source byte
- *dst++ = colTable[(*src) >> 4];
- }
-}
-
-/**
- * This function takes a compressed frame of a sprite (with up to 16 colours)
- * and decompresses it.
- * @param dst destination buffer
- * @param src source buffer
- * @param decompSize the expected size of the uncompressed sprite
- * @param colTable mapping from the 16 encoded colours to the current palette
- */
-
-int32 Screen::decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable) {
- byte headerByte; // block header byte
- byte *endDest = dst + decompSize; // pointer to byte after end of decomp buffer
- int32 rv;
-
- while (1) {
- // FLAT block
- // read FLAT block header & increment 'scan' to first pixel
- // of block
- headerByte = *src++;
-
- // if this isn't a zero-length block
- if (headerByte) {
- if (dst + headerByte > endDest) {
- rv = 1;
- break;
- }
-
- // set the next 'headerByte' pixels to the next
- // colour at 'source'
- memset(dst, *src, headerByte);
-
- // increment destination pointer to just after this
- // block
- dst += headerByte;
-
- // increment source pointer to just after this colour
- src++;
-
- // if we've decompressed all of the data
- if (dst == endDest) {
- rv = 0; // return "OK"
- break;
- }
- }
-
- // RAW block
- // read RAW block header & increment 'scan' to first pixel of
- // block
- headerByte = *src++;
-
- // if this isn't a zero-length block
- if (headerByte) {
- if (dst + headerByte > endDest) {
- rv = 1;
- break;
- }
-
- // copy the next 'headerByte' pixels from source to
- // destination (NB. 2 pixels per byte)
- unwindRaw16(dst, src, headerByte, colTable);
-
- // increment destination pointer to just after this
- // block
- dst += headerByte;
-
- // increment source pointer to just after this block
- // (NB. headerByte gives pixels, so /2 for bytes)
- src += (headerByte + 1) / 2;
-
- // if we've decompressed all of the data
- if (dst >= endDest) {
- rv = 0; // return "OK"
- break;
- }
- }
- }
-
- return rv;
-}
-
-/**
- * Creates a sprite surface. Sprite surfaces are used by the in-game dialogs
- * and for displaying cutscene subtitles, which makes them much easier to draw
- * than standard sprites.
- * @param s information about how to decode the sprite
- * @param sprite the buffer that will be created to store the surface
- * @return RD_OK, or an error code
- */
-
-int32 Screen::createSurface(SpriteInfo *s, byte **sprite) {
- *sprite = (byte *)malloc(s->w * s->h);
- if (!*sprite)
- return RDERR_OUTOFMEMORY;
-
- // Surfaces are either uncompressed or RLE256-compressed. No need to
- // test for anything else.
-
- if (s->type & RDSPR_NOCOMPRESSION) {
- memcpy(*sprite, s->data, s->w * s->h);
- } else if (decompressRLE256(*sprite, s->data, s->w * s->h)) {
- free(*sprite);
- return RDERR_DECOMPRESSION;
- }
-
- return RD_OK;
-}
-
-/**
- * Draws the sprite surface created earlier.
- * @param s information about how to place the sprite
- * @param surface pointer to the surface created earlier
- * @param clipRect the clipping rectangle
- */
-
-void Screen::drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect) {
- Common::Rect rd, rs;
- uint16 x, y;
- byte *src, *dst;
-
- rs.left = 0;
- rs.right = s->w;
- rs.top = 0;
- rs.bottom = s->h;
-
- rd.left = s->x;
- rd.right = rd.left + rs.right;
- rd.top = s->y;
- rd.bottom = rd.top + rs.bottom;
-
- Common::Rect defClipRect(0, 0, _screenWide, _screenDeep);
-
- if (!clipRect) {
- clipRect = &defClipRect;
- }
-
- if (clipRect->left > rd.left) {
- rs.left += (clipRect->left - rd.left);
- rd.left = clipRect->left;
- }
-
- if (clipRect->top > rd.top) {
- rs.top += (clipRect->top - rd.top);
- rd.top = clipRect->top;
- }
-
- if (clipRect->right < rd.right) {
- rd.right = clipRect->right;
- }
-
- if (clipRect->bottom < rd.bottom) {
- rd.bottom = clipRect->bottom;
- }
-
- if (rd.width() <= 0 || rd.height() <= 0)
- return;
-
- src = surface + rs.top * s->w + rs.left;
- dst = _buffer + _screenWide * rd.top + rd.left;
-
- // Surfaces are always transparent.
-
- for (y = 0; y < rd.height(); y++) {
- for (x = 0; x < rd.width(); x++) {
- if (src[x])
- dst[x] = src[x];
- }
- src += s->w;
- dst += _screenWide;
- }
-
- updateRect(&rd);
-}
-
-/**
- * Destroys a surface.
- */
-
-void Screen::deleteSurface(byte *surface) {
- free(surface);
-}
-
-/**
- * Draws a sprite onto the screen. The type of the sprite can be a combination
- * of the following flags, some of which are mutually exclusive:
- * RDSPR_DISPLAYALIGN The sprite is drawn relative to the top left corner
- * of the screen
- * RDSPR_FLIP The sprite is mirrored
- * RDSPR_TRANS The sprite has a transparent colour zero
- * RDSPR_BLEND The sprite is translucent
- * RDSPR_SHADOW The sprite is affected by the light mask. (Scaled
- * sprites always are.)
- * RDSPR_NOCOMPRESSION The sprite data is not compressed
- * RDSPR_RLE16 The sprite data is a 16-colour compressed sprite
- * RDSPR_RLE256 The sprite data is a 256-colour compressed sprite
- * @param s all the information needed to draw the sprite
- * @warning Sprites will only be drawn onto the background, not over menubar
- * areas.
- */
-
-// FIXME: I'm sure this could be optimized. There's plenty of data copying and
-// mallocing here.
-
-int32 Screen::drawSprite(SpriteInfo *s) {
- byte *src, *dst;
- byte *sprite, *newSprite;
- uint16 scale;
- int16 i, j;
- uint16 srcPitch;
- bool freeSprite = false;
- Common::Rect rd, rs;
-
- // -----------------------------------------------------------------
- // Decompression and mirroring
- // -----------------------------------------------------------------
-
- if (s->type & RDSPR_NOCOMPRESSION)
- sprite = s->data;
- else {
- sprite = (byte *)malloc(s->w * s->h);
- freeSprite = true;
- if (!sprite)
- return RDERR_OUTOFMEMORY;
- if ((s->type & 0xff00) == RDSPR_RLE16) {
- if (decompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) {
- free(sprite);
- return RDERR_DECOMPRESSION;
- }
- } else {
- if (decompressRLE256(sprite, s->data, s->w * s->h)) {
- free(sprite);
- return RDERR_DECOMPRESSION;
- }
- }
- }
-
- if (s->type & RDSPR_FLIP) {
- newSprite = (byte *)malloc(s->w * s->h);
- if (newSprite == NULL) {
- if (freeSprite)
- free(sprite);
- return RDERR_OUTOFMEMORY;
- }
- mirrorSprite(newSprite, sprite, s->w, s->h);
- if (freeSprite)
- free(sprite);
- sprite = newSprite;
- freeSprite = true;
- }
-
- // -----------------------------------------------------------------
- // Positioning and clipping.
- // -----------------------------------------------------------------
-
- int16 spriteX = s->x;
- int16 spriteY = s->y;
-
- if (!(s->type & RDSPR_DISPLAYALIGN)) {
- spriteX += _parallaxScrollX;
- spriteY += _parallaxScrollY;
- }
-
- spriteY += MENUDEEP;
-
- // A scale factor 0 or 256 means don't scale. Why do they use two
- // different values to mean the same thing? Normalize it here for
- // convenience.
-
- scale = (s->scale == 0) ? 256 : s->scale;
-
- rs.top = 0;
- rs.left = 0;
-
- if (scale != 256) {
- rs.right = s->scaledWidth;
- rs.bottom = s->scaledHeight;
- srcPitch = s->scaledWidth;
- } else {
- rs.right = s->w;
- rs.bottom = s->h;
- srcPitch = s->w;
- }
-
- rd.top = spriteY;
- rd.left = spriteX;
-
- if (!(s->type & RDSPR_DISPLAYALIGN)) {
- rd.top -= _scrollY;
- rd.left -= _scrollX;
- }
-
- rd.right = rd.left + rs.right;
- rd.bottom = rd.top + rs.bottom;
-
- // Check if the sprite would end up completely outside the screen.
-
- if (rd.left > RENDERWIDE || rd.top > RENDERDEEP + MENUDEEP || rd.right < 0 || rd.bottom < MENUDEEP) {
- if (freeSprite)
- free(sprite);
- return RD_OK;
- }
-
- if (rd.top < MENUDEEP) {
- rs.top = MENUDEEP - rd.top;
- rd.top = MENUDEEP;
- }
- if (rd.bottom > RENDERDEEP + MENUDEEP) {
- rd.bottom = RENDERDEEP + MENUDEEP;
- rs.bottom = rs.top + (rd.bottom - rd.top);
- }
- if (rd.left < 0) {
- rs.left = -rd.left;
- rd.left = 0;
- }
- if (rd.right > RENDERWIDE) {
- rd.right = RENDERWIDE;
- rs.right = rs.left + (rd.right - rd.left);
- }
-
- // -----------------------------------------------------------------
- // Scaling
- // -----------------------------------------------------------------
-
- if (scale != 256) {
- if (s->scaledWidth > SCALE_MAXWIDTH || s->scaledHeight > SCALE_MAXHEIGHT) {
- if (freeSprite)
- free(sprite);
- return RDERR_NOTIMPLEMENTED;
- }
-
- newSprite = (byte *)malloc(s->scaledWidth * s->scaledHeight);
- if (newSprite == NULL) {
- if (freeSprite)
- free(sprite);
- return RDERR_OUTOFMEMORY;
- }
-
- if (_renderCaps & RDBLTFX_EDGEBLEND)
- scaleImageGood(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h, _buffer + _screenWide * rd.top + rd.left);
- else
- scaleImageFast(newSprite, s->scaledWidth, s->scaledWidth, s->scaledHeight, sprite, s->w, s->w, s->h);
-
- if (freeSprite)
- free(sprite);
- sprite = newSprite;
- freeSprite = true;
- }
-
- // -----------------------------------------------------------------
- // Light masking
- // -----------------------------------------------------------------
-
- // The light mask is an optional layer that covers the entire room
- // and which is used to simulate light and shadows. Scaled sprites
- // (actors, presumably) are always affected.
-
- if ((_renderCaps & RDBLTFX_SHADOWBLEND) && _lightMask && (scale != 256 || (s->type & RDSPR_SHADOW))) {
- byte *lightMap;
-
- // Make sure that we never apply the shadow to the original
- // resource data. This could only ever happen in the
- // RDSPR_NOCOMPRESSION case.
-
- if (!freeSprite) {
- newSprite = (byte *)malloc(s->w * s->h);
- memcpy(newSprite, sprite, s->w * s->h);
- sprite = newSprite;
- freeSprite = true;
- }
-
- src = sprite + rs.top * srcPitch + rs.left;
- lightMap = _lightMask + (rd.top + _scrollY - MENUDEEP) * _locationWide + rd.left + _scrollX;
-
- for (i = 0; i < rs.height(); i++) {
- for (j = 0; j < rs.width(); j++) {
- if (src[j] && lightMap[j]) {
- uint8 r = ((32 - lightMap[j]) * _palette[src[j] * 4 + 0]) >> 5;
- uint8 g = ((32 - lightMap[j]) * _palette[src[j] * 4 + 1]) >> 5;
- uint8 b = ((32 - lightMap[j]) * _palette[src[j] * 4 + 2]) >> 5;
- src[j] = quickMatch(r, g, b);
- }
- }
- src += srcPitch;
- lightMap += _locationWide;
- }
- }
-
- // -----------------------------------------------------------------
- // Drawing
- // -----------------------------------------------------------------
-
- src = sprite + rs.top * srcPitch + rs.left;
- dst = _buffer + _screenWide * rd.top + rd.left;
-
- if (s->type & RDSPR_BLEND) {
- // The original code had two different blending cases. One for
- // s->blend & 0x01 and one for s->blend & 0x02. However, the
- // only values that actually appear in the cluster files are
- // 0, 513 and 1025 so the s->blend & 0x02 case was never used.
- // Which is just as well since that code made no sense to me.
-
- if (!(_renderCaps & RDBLTFX_SPRITEBLEND)) {
- for (i = 0; i < rs.height(); i++) {
- for (j = 0; j < rs.width(); j++) {
- if (src[j] && ((i & 1) == (j & 1)))
- dst[j] = src[j];
- }
- src += srcPitch;
- dst += _screenWide;
- }
- } else {
- uint8 n = s->blend >> 8;
-
- for (i = 0; i < rs.height(); i++) {
- for (j = 0; j < rs.width(); j++) {
- if (src[j]) {
- uint8 r1 = _palette[src[j] * 4 + 0];
- uint8 g1 = _palette[src[j] * 4 + 1];
- uint8 b1 = _palette[src[j] * 4 + 2];
- uint8 r2 = _palette[dst[j] * 4 + 0];
- uint8 g2 = _palette[dst[j] * 4 + 1];
- uint8 b2 = _palette[dst[j] * 4 + 2];
-
- uint8 r = (r1 * n + r2 * (8 - n)) >> 3;
- uint8 g = (g1 * n + g2 * (8 - n)) >> 3;
- uint8 b = (b1 * n + b2 * (8 - n)) >> 3;
- dst[j] = quickMatch(r, g, b);
- }
- }
- src += srcPitch;
- dst += _screenWide;
- }
- }
- } else {
- if (s->type & RDSPR_TRANS) {
- for (i = 0; i < rs.height(); i++) {
- for (j = 0; j < rs.width(); j++) {
- if (src[j])
- dst[j] = src[j];
- }
- src += srcPitch;
- dst += _screenWide;
- }
- } else {
- for (i = 0; i < rs.height(); i++) {
- memcpy(dst, src, rs.width());
- src += srcPitch;
- dst += _screenWide;
- }
- }
- }
-
- if (freeSprite)
- free(sprite);
-
- markAsDirty(rd.left, rd.top, rd.right - 1, rd.bottom - 1);
- return RD_OK;
-}
-
-/**
- * Opens the light masking sprite for a room.
- */
-
-int32 Screen::openLightMask(SpriteInfo *s) {
- // FIXME: The light mask is only needed on higher graphics detail
- // settings, so to save memory we could simply ignore it on lower
- // settings. But then we need to figure out how to ensure that it
- // is properly loaded if the user changes the settings in mid-game.
-
- if (_lightMask)
- return RDERR_NOTCLOSED;
-
- _lightMask = (byte *)malloc(s->w * s->h);
- if (!_lightMask)
- return RDERR_OUTOFMEMORY;
-
- if (decompressRLE256(_lightMask, s->data, s->w * s->h))
- return RDERR_DECOMPRESSION;
-
- return RD_OK;
-}
-
-/**
- * Closes the light masking sprite for a room.
- */
-
-int32 Screen::closeLightMask() {
- if (!_lightMask)
- return RDERR_NOTOPEN;
-
- free(_lightMask);
- _lightMask = NULL;
- return RD_OK;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/startup.cpp b/sword2/startup.cpp
deleted file mode 100644
index 2e1dd7b0ae..0000000000
--- a/sword2/startup.cpp
+++ /dev/null
@@ -1,173 +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$
- */
-
-#include "common/stdafx.h"
-#include "common/file.h"
-
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/memory.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-#include "sword2/sound.h"
-
-namespace Sword2 {
-
-bool Sword2Engine::initStartMenu() {
- // Print out a list of all the start points available.
- // There should be a linc produced file called startup.txt.
- // This file should contain ascii numbers of all the resource game
- // objects that are screen managers.
- // We query each in turn and setup an array of start structures.
- // If the file doesn't exist then we say so and return a 0.
-
- Common::File fp;
-
- // ok, load in the master screen manager file
-
- _totalStartups = 0;
- _totalScreenManagers = 0;
-
- if (!fp.open("startup.inf")) {
- warning("Cannot open startup.inf - the debugger won't have a start menu");
- return false;
- }
-
- // The startup.inf file which contains a list of all the files. Now
- // extract the filenames
-
- int start_ids[MAX_starts];
-
- while (1) {
- bool done = false;
-
- start_ids[_totalScreenManagers] = 0;
-
- // Scan the string until the LF in CRLF
-
- int b;
-
- do {
- b = fp.readByte();
-
- if (fp.ioFailed()) {
- done = true;
- break;
- }
-
- if (isdigit(b)) {
- start_ids[_totalScreenManagers] *= 10;
- start_ids[_totalScreenManagers] += (b - '0');
- }
- } while (b != 10);
-
- if (done)
- break;
-
- _totalScreenManagers++;
-
- if (_totalScreenManagers == MAX_starts) {
- warning("MAX_starts exceeded");
- break;
- }
- }
-
- fp.close();
-
- // Using this method the Gode generated resource.inf must have #0d0a
- // on the last entry
-
- debug(1, "%d screen manager objects", _totalScreenManagers);
-
- // Open each object and make a query call. The object must fill in a
- // startup structure. It may fill in several if it wishes - for
- // instance a startup could be set for later in the game where
- // specific vars are set
-
- for (uint i = 0; i < _totalScreenManagers; i++) {
- _startRes = start_ids[i];
-
- debug(2, "Querying screen manager %d", _startRes);
-
- // Open each one and run through the interpreter. Script 0 is
- // the query request script
-
- // if the resource number is within range & it's not a null
- // resource
- // - need to check in case un-built sections included in
- // start list
-
- if (_resman->checkValid(_startRes)) {
- _logic->runResScript(_startRes, 0);
- } else
- warning("Start menu resource %d invalid", _startRes);
- }
-
- return 1;
-}
-
-void Sword2Engine::registerStartPoint(int32 key, char *name) {
- assert(_totalStartups < MAX_starts);
-
- _startList[_totalStartups].start_res_id = _startRes;
- _startList[_totalStartups].key = key;
-
- strncpy(_startList[_totalStartups].description, name, MAX_description);
- _startList[_totalStartups].description[MAX_description - 1] = 0;
-
- _totalStartups++;
-}
-
-void Sword2Engine::runStart(int start) {
- // Restarting - stop sfx, music & speech!
-
- _sound->clearFxQueue();
- _logic->fnStopMusic(NULL);
- _sound->unpauseSpeech();
- _sound->stopSpeech();
-
- // Remove all resources from memory, including player object and global
- // variables
-
- _resman->removeAll();
-
- // Reopen global variables resource and player object
- setupPersistentResources();
-
- // Free all the route memory blocks from previous game
- _logic->_router->freeAllRouteMem();
-
- // If there was speech text, kill the text block
- if (_logic->_speechTextBlocNo) {
- _fontRenderer->killTextBloc(_logic->_speechTextBlocNo);
- _logic->_speechTextBlocNo = 0;
- }
-
- _logic->runResObjScript(_startList[start].start_res_id, CUR_PLAYER_ID, _startList[start].key & 0xffff);
-
- // Make sure there's a mouse, in case restarting while mouse not
- // available
- _logic->fnAddHuman(NULL);
-}
-
-} // End of namespace Sword2
diff --git a/sword2/sword2.cpp b/sword2/sword2.cpp
deleted file mode 100644
index 6056d636b7..0000000000
--- a/sword2/sword2.cpp
+++ /dev/null
@@ -1,689 +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$
- */
-
-#include "common/stdafx.h"
-
-#include "backends/fs/fs.h"
-
-#include "base/gameDetector.h"
-#include "base/plugins.h"
-
-#include "common/config-manager.h"
-#include "common/file.h"
-#include "common/system.h"
-
-#include "sword2/sword2.h"
-#include "sword2/console.h"
-#include "sword2/controls.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/memory.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-#include "sword2/sound.h"
-
-#ifdef _WIN32_WCE
-extern bool isSmartphone();
-#endif
-
-struct Sword2GameSettings {
- const char *gameid;
- const char *description;
- uint32 features;
- const char *detectname;
- GameSettings toGameSettings() const {
- GameSettings dummy = { gameid, description, features };
- return dummy;
- }
-};
-
-static const Sword2GameSettings sword2_settings[] = {
- /* Broken Sword 2 */
- {"sword2", "Broken Sword 2: The Smoking Mirror", GF_DEFAULT_TO_1X_SCALER, "players.clu" },
- {"sword2alt", "Broken Sword 2: The Smoking Mirror (alt)", GF_DEFAULT_TO_1X_SCALER, "r2ctlns.ocx" },
- {"sword2demo", "Broken Sword 2: The Smoking Mirror (Demo)", GF_DEFAULT_TO_1X_SCALER | Sword2::GF_DEMO, "players.clu" },
- {NULL, NULL, 0, NULL}
-};
-
-GameList Engine_SWORD2_gameList() {
- const Sword2GameSettings *g = sword2_settings;
- GameList games;
- while (g->gameid) {
- games.push_back(g->toGameSettings());
- g++;
- }
- return games;
-}
-
-DetectedGameList Engine_SWORD2_detectGames(const FSList &fslist) {
- DetectedGameList detectedGames;
- const Sword2GameSettings *g;
-
- // TODO: It would be nice if we had code here which distinguishes
- // between the 'sword2' and 'sword2demo' targets. The current code
- // can't do that since they use the same detectname.
-
- for (g = sword2_settings; g->gameid; ++g) {
- // Iterate over all files in the given directory
- for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
- if (!file->isDirectory()) {
- const char *gameName = file->displayName().c_str();
-
- if (0 == scumm_stricmp(g->detectname, gameName)) {
- // Match found, add to list of candidates, then abort inner loop.
- detectedGames.push_back(g->toGameSettings());
- break;
- }
- }
- }
- }
- return detectedGames;
-}
-
-Engine *Engine_SWORD2_create(GameDetector *detector, OSystem *syst) {
- return new Sword2::Sword2Engine(detector, syst);
-}
-
-REGISTER_PLUGIN(SWORD2, "Broken Sword 2")
-
-namespace Sword2 {
-
-Sword2Engine::Sword2Engine(GameDetector *detector, OSystem *syst) : Engine(syst) {
- // Add default file directories
- Common::File::addDefaultDirectory(_gameDataPath + "CLUSTERS/");
- Common::File::addDefaultDirectory(_gameDataPath + "SWORD2/");
- Common::File::addDefaultDirectory(_gameDataPath + "VIDEO/");
- Common::File::addDefaultDirectory(_gameDataPath + "clusters/");
- Common::File::addDefaultDirectory(_gameDataPath + "sword2/");
- Common::File::addDefaultDirectory(_gameDataPath + "video/");
-
- _features = detector->_game.features;
- _targetName = detector->_targetName;
-
- _bootParam = ConfMan.getInt("boot_param");
- _saveSlot = ConfMan.getInt("save_slot");
-
- _memory = NULL;
- _resman = NULL;
- _sound = NULL;
- _screen = NULL;
- _mouse = NULL;
- _logic = NULL;
- _fontRenderer = NULL;
- _debugger = NULL;
-
- _keyboardEvent.pending = false;
- _keyboardEvent.repeat = 0;
- _mouseEvent.pending = false;
-
- _wantSfxDebug = false;
-
-#ifdef SWORD2_DEBUG
- _stepOneCycle = false;
- _renderSkip = false;
-#endif
-
- _gamePaused = false;
- _graphicsLevelFudged = false;
-
- _gameCycle = 0;
-
- _quit = false;
-}
-
-Sword2Engine::~Sword2Engine() {
- delete _debugger;
- delete _sound;
- delete _fontRenderer;
- delete _screen;
- delete _mouse;
- delete _logic;
- delete _resman;
- delete _memory;
-}
-
-void Sword2Engine::errorString(const char *buf1, char *buf2) {
- strcpy(buf2, buf1);
-
-#ifdef _WIN32_WCE
- if (isSmartphone())
- return;
-#endif
-
- // Unless an error -originated- within the debugger, spawn the
- // debugger. Otherwise exit out normally.
- if (_debugger && !_debugger->isAttached()) {
- // (Print it again in case debugger segfaults)
- printf("%s\n", buf2);
- _debugger->attach(buf2);
- _debugger->onFrame();
- }
-}
-
-void Sword2Engine::registerDefaultSettings() {
- ConfMan.registerDefault("music_mute", false);
- ConfMan.registerDefault("speech_mute", false);
- ConfMan.registerDefault("sfx_mute", false);
- ConfMan.registerDefault("gfx_details", 2);
- ConfMan.registerDefault("subtitles", false);
- ConfMan.registerDefault("reverse_stereo", false);
-}
-
-void Sword2Engine::readSettings() {
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- setSubtitles(ConfMan.getBool("subtitles"));
- _sound->muteMusic(ConfMan.getBool("music_mute"));
- _sound->muteSpeech(ConfMan.getBool("speech_mute"));
- _sound->muteFx(ConfMan.getBool("sfx_mute"));
- _sound->setReverseStereo(ConfMan.getBool("reverse_stereo"));
- _mouse->setObjectLabels(ConfMan.getBool("object_labels"));
- _screen->setRenderLevel(ConfMan.getInt("gfx_details"));
-}
-
-void Sword2Engine::writeSettings() {
- ConfMan.set("music_volume", _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
- ConfMan.set("speech_volume", _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
- ConfMan.set("sfx_volume", _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
- ConfMan.set("music_mute", _sound->isMusicMute());
- ConfMan.set("speech_mute", _sound->isSpeechMute());
- ConfMan.set("sfx_mute", _sound->isFxMute());
- ConfMan.set("gfx_details", _screen->getRenderLevel());
- ConfMan.set("subtitles", getSubtitles());
- ConfMan.set("object_labels", _mouse->getObjectLabels());
- ConfMan.set("reverse_stereo", _sound->isReverseStereo());
-
- ConfMan.flushToDisk();
-}
-
-/**
- * The global script variables and player object should be kept open throughout
- * the game, so that they are never expelled by the resource manager.
- */
-
-void Sword2Engine::setupPersistentResources() {
- _logic->_scriptVars = _resman->openResource(1) + ResHeader::size();
- _resman->openResource(CUR_PLAYER_ID);
-}
-
-int Sword2Engine::init(GameDetector &detector) {
- // Get some falling RAM and put it in your pocket, never let it slip
- // away
-
- _system->beginGFXTransaction();
- initCommonGFX(detector);
- _screen = new Screen(this, 640, 480);
- _system->endGFXTransaction();
-
- // Create the debugger as early as possible (but not before the
- // screen object!) so that errors can be displayed in it. In
- // particular, we want errors about missing files to be clearly
- // visible to the user.
-
- _debugger = new Debugger(this);
-
- _memory = new MemoryManager(this);
- _resman = new ResourceManager(this);
- _logic = new Logic(this);
- _fontRenderer = new FontRenderer(this);
- _sound = new Sound(this);
- _mouse = new Mouse(this);
-
- // Setup mixer
- if (!_mixer->isReady())
- warning("Sound initialization failed");
-
- registerDefaultSettings();
- readSettings();
-
- initStartMenu();
-
- // During normal gameplay, we care neither about mouse button releases
- // nor the scroll wheel.
- setInputEventFilter(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP | RD_WHEELUP | RD_WHEELDOWN);
-
- setupPersistentResources();
- initialiseFontResourceFlags();
-
- if (_features & GF_DEMO)
- _logic->writeVar(DEMO, 1);
- else
- _logic->writeVar(DEMO, 0);
-
- if (_saveSlot != -1) {
- if (saveExists(_saveSlot))
- restoreGame(_saveSlot);
- else {
- RestoreDialog dialog(this);
- if (!dialog.runModal())
- startGame();
- }
- } else if (!_bootParam && saveExists()) {
- int32 pars[2] = { 221, FX_LOOP };
- bool result;
-
- _mouse->setMouse(NORMAL_MOUSE_ID);
- _logic->fnPlayMusic(pars);
-
- StartDialog dialog(this);
-
- result = (dialog.runModal() != 0);
-
- // If the game is started from the beginning, the cutscene
- // player will kill the music for us. Otherwise, the restore
- // will either have killed the music, or done a crossfade.
-
- if (_quit)
- return 0;
-
- if (result)
- startGame();
- } else
- startGame();
-
- _screen->initialiseRenderCycle();
-
- return 0;
-}
-
-int Sword2Engine::go() {
- while (1) {
- if (_debugger->isAttached())
- _debugger->onFrame();
-
-#ifdef SWORD2_DEBUG
- if (_stepOneCycle) {
- pauseGame();
- _stepOneCycle = false;
- }
-#endif
-
- KeyboardEvent *ke = keyboardEvent();
-
- if (ke) {
- if ((ke->modifiers == OSystem::KBD_CTRL && ke->keycode == 'd') || ke->ascii == '#' || ke->ascii == '~') {
- _debugger->attach();
- } else if (ke->modifiers == 0 || ke->modifiers == OSystem::KBD_SHIFT) {
- switch (ke->keycode) {
- case 'p':
- if (_gamePaused)
- unpauseGame();
- else
- pauseGame();
- break;
- case 'c':
- if (!_logic->readVar(DEMO) && !_mouse->isChoosing()) {
- ScreenInfo *screenInfo = _screen->getScreenInfo();
- _logic->fnPlayCredits(NULL);
- screenInfo->new_palette = 99;
- }
- break;
-#ifdef SWORD2_DEBUG
- case ' ':
- if (_gamePaused) {
- _stepOneCycle = true;
- unpauseGame();
- }
- break;
- case 's':
- _renderSkip = !_renderSkip;
- break;
-#endif
- default:
- break;
- }
- }
- }
-
- // skip GameCycle if we're paused
- if (!_gamePaused) {
- _gameCycle++;
- gameCycle();
- }
-
- // We can't use this as termination condition for the loop,
- // because we want the break to happen before updating the
- // screen again.
-
- if (_quit)
- break;
-
- // creates the debug text blocks
- _debugger->buildDebugText();
-
-#ifdef SWORD2_DEBUG
- // if not in console & '_renderSkip' is set, only render
- // display once every 4 game-cycles
-
- if (!_renderSkip || (_gameCycle % 4) == 0)
- _screen->buildDisplay();
-#else
- _screen->buildDisplay();
-#endif
- }
-
- return 0;
-}
-
-void Sword2Engine::closeGame() {
- _quit = true;
-}
-
-void Sword2Engine::restartGame() {
- ScreenInfo *screenInfo = _screen->getScreenInfo();
- uint32 temp_demo_flag;
-
- _mouse->closeMenuImmediately();
-
- // Restart the game. To do this, we must...
-
- // Stop music instantly!
- _sound->stopMusic(true);
-
- // In case we were dead - well we're not anymore!
- _logic->writeVar(DEAD, 0);
-
- // Restart the game. Clear all memory and reset the globals
- temp_demo_flag = _logic->readVar(DEMO);
-
- // Remove all resources from memory, including player object and
- // global variables
- _resman->removeAll();
-
- // Reopen global variables resource and player object
- setupPersistentResources();
-
- _logic->writeVar(DEMO, temp_demo_flag);
-
- // Free all the route memory blocks from previous game
- _logic->_router->freeAllRouteMem();
-
- // Call the same function that first started us up
- startGame();
-
- // 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();
-
- _mouse->closeMenuImmediately();
-
- // FOR THE DEMO - FORCE THE SCROLLING TO BE RESET!
- // - this is taken from fnInitBackground
- // switch on scrolling (2 means first time on screen)
- screenInfo->scroll_flag = 2;
-
- if (_logic->processSession())
- error("restart 1st cycle failed??");
-
- // So palette not restored immediately after control panel - we want
- // to fade up instead!
- screenInfo->new_palette = 99;
-}
-
-bool Sword2Engine::checkForMouseEvents() {
- return _mouseEvent.pending;
-}
-
-MouseEvent *Sword2Engine::mouseEvent() {
- if (!_mouseEvent.pending)
- return NULL;
-
- _mouseEvent.pending = false;
- return &_mouseEvent;
-}
-
-KeyboardEvent *Sword2Engine::keyboardEvent() {
- if (!_keyboardEvent.pending)
- return NULL;
-
- _keyboardEvent.pending = false;
- return &_keyboardEvent;
-}
-
-uint32 Sword2Engine::setInputEventFilter(uint32 filter) {
- uint32 oldFilter = _inputEventFilter;
-
- _inputEventFilter = filter;
- return oldFilter;
-}
-
-/**
- * Clear the input events. This is so that we won't get any keyboard repeat
- * right after using the debugging console.
- */
-
-void Sword2Engine::clearInputEvents() {
- _keyboardEvent.pending = false;
- _keyboardEvent.repeat = 0;
- _mouseEvent.pending = false;
-}
-
-/**
- * OSystem Event Handler. Full of cross platform goodness and 99% fat free!
- */
-
-void Sword2Engine::parseInputEvents() {
- OSystem::Event event;
-
- uint32 now = _system->getMillis();
-
- while (_system->pollEvent(event)) {
- switch (event.type) {
- case OSystem::EVENT_KEYDOWN:
- if (!(_inputEventFilter & RD_KEYDOWN)) {
- _keyboardEvent.pending = true;
- _keyboardEvent.repeat = now + 400;
- _keyboardEvent.ascii = event.kbd.ascii;
- _keyboardEvent.keycode = event.kbd.keycode;
- _keyboardEvent.modifiers = event.kbd.flags;
- }
- break;
- case OSystem::EVENT_KEYUP:
- _keyboardEvent.repeat = 0;
- break;
- case OSystem::EVENT_MOUSEMOVE:
- if (!(_inputEventFilter & RD_KEYDOWN)) {
- _mouse->setPos(event.mouse.x, event.mouse.y - MENUDEEP);
- }
- break;
- case OSystem::EVENT_LBUTTONDOWN:
- if (!(_inputEventFilter & RD_LEFTBUTTONDOWN)) {
- _mouseEvent.pending = true;
- _mouseEvent.buttons = RD_LEFTBUTTONDOWN;
- }
- break;
- case OSystem::EVENT_RBUTTONDOWN:
- if (!(_inputEventFilter & RD_RIGHTBUTTONDOWN)) {
- _mouseEvent.pending = true;
- _mouseEvent.buttons = RD_RIGHTBUTTONDOWN;
- }
- break;
- case OSystem::EVENT_LBUTTONUP:
- if (!(_inputEventFilter & RD_LEFTBUTTONUP)) {
- _mouseEvent.pending = true;
- _mouseEvent.buttons = RD_LEFTBUTTONUP;
- }
- break;
- case OSystem::EVENT_RBUTTONUP:
- if (!(_inputEventFilter & RD_RIGHTBUTTONUP)) {
- _mouseEvent.pending = true;
- _mouseEvent.buttons = RD_RIGHTBUTTONUP;
- }
- break;
- case OSystem::EVENT_WHEELUP:
- if (!(_inputEventFilter & RD_WHEELUP)) {
- _mouseEvent.pending = true;
- _mouseEvent.buttons = RD_WHEELUP;
- }
- break;
- case OSystem::EVENT_WHEELDOWN:
- if (!(_inputEventFilter & RD_WHEELDOWN)) {
- _mouseEvent.pending = true;
- _mouseEvent.buttons = RD_WHEELDOWN;
- }
- break;
- case OSystem::EVENT_QUIT:
- closeGame();
- break;
- default:
- break;
- }
- }
-
- // Handle keyboard auto-repeat
- if (!_keyboardEvent.pending && _keyboardEvent.repeat && now >= _keyboardEvent.repeat) {
- _keyboardEvent.pending = true;
- _keyboardEvent.repeat = now + 100;
- }
-}
-
-void Sword2Engine::gameCycle() {
- // Do one game cycle, that is run the logic session until a full loop
- // has been performed.
-
- if (_logic->getRunList()) {
- do {
- // Reset the 'BuildUnit' and mouse hot-spot lists
- // before each new logic list. The service scripts
- // will fill thrm through fnRegisterFrame() and
- // fnRegisterMouse().
-
- _screen->resetRenderLists();
- _mouse->resetMouseList();
-
- // Keep going as long as new lists keep getting put in
- // - i.e. screen changes.
- } while (_logic->processSession());
- } else {
- // Start the console and print the start options perhaps?
- _debugger->attach("AWAITING START COMMAND: (Enter 's 1' then 'q' to start from beginning)");
- }
-
- // If this screen is wide, recompute the scroll offsets every cycle
- ScreenInfo *screenInfo = _screen->getScreenInfo();
-
- if (screenInfo->scroll_flag)
- _screen->setScrolling();
-
- _mouse->mouseEngine();
- _sound->processFxQueue();
-}
-
-void Sword2Engine::startGame() {
- // Boot the game straight into a start script. It's always George's
- // script #1, but with different ScreenManager objects depending on
- // if it's the demo or the full game, or if we're using a boot param.
-
- int screen_manager_id = 0;
-
- debug(5, "startGame() STARTING:");
-
- if (!_bootParam) {
- if (_logic->readVar(DEMO))
- screen_manager_id = 19; // DOCKS SECTION START
- else
- screen_manager_id = 949; // INTRO & PARIS START
- } else {
- // FIXME this could be validated against startup.inf for valid
- // numbers to stop people shooting themselves in the foot
-
- if (_bootParam != 0)
- screen_manager_id = _bootParam;
- }
-
- _logic->runResObjScript(screen_manager_id, CUR_PLAYER_ID, 1);
-}
-
-// FIXME: Move this to some better place?
-
-void Sword2Engine::sleepUntil(uint32 time) {
- while (getMillis() < time) {
- // Make sure menu animations and fades don't suffer, but don't
- // redraw the entire scene.
- _mouse->processMenu();
- _screen->updateDisplay(false);
- _system->delayMillis(10);
- }
-}
-
-void Sword2Engine::pauseGame() {
- // Don't allow Pause while screen fading or while black
- if (_screen->getFadeStatus() != RDFADE_NONE)
- return;
-
- _sound->pauseAllSound();
- _mouse->pauseGame();
-
- // If render level is at max, turn it down because palette-matching
- // won't work when the palette is dimmed.
-
- if (_screen->getRenderLevel() == 3) {
- _screen->setRenderLevel(2);
- _graphicsLevelFudged = true;
- }
-
-#ifdef SWORD2_DEBUG
- // Don't dim it if we're single-stepping through frames
- // dim the palette during the pause
-
- if (!_stepOneCycle)
- _screen->dimPalette();
-#else
- _screen->dimPalette();
-#endif
-
- _gamePaused = true;
-}
-
-void Sword2Engine::unpauseGame() {
- _mouse->unpauseGame();
- _sound->unpauseAllSound();
-
- // Put back game screen palette; see build_display.cpp
- _screen->setFullPalette(-1);
-
- // If graphics level at max, turn up again
- if (_graphicsLevelFudged) {
- _screen->setRenderLevel(3);
- _graphicsLevelFudged = false;
- }
-
- _gamePaused = false;
-
- // If mouse is about or we're in a chooser menu
- if (!_mouse->getMouseStatus() || _mouse->isChoosing())
- _mouse->setMouse(NORMAL_MOUSE_ID);
-}
-
-uint32 Sword2Engine::getMillis() {
- return _system->getMillis();
-}
-
-} // End of namespace Sword2
diff --git a/sword2/sword2.h b/sword2/sword2.h
deleted file mode 100644
index bcb80ec957..0000000000
--- a/sword2/sword2.h
+++ /dev/null
@@ -1,240 +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 _SWORD2
-#define _SWORD2
-
-// Enable this to make it possible to clear the mouse cursor luggage by
-// right-clicking. The original didn't do this, but it feels natural to me.
-// However, I'm afraid that it'll interfer badly with parts of the game, so
-// for now I'll keep it disabled.
-
-#define RIGHT_CLICK_CLEARS_LUGGAGE 0
-
-#include "base/engine.h"
-
-#include "common/util.h"
-
-#include "sword2/build_display.h"
-#include "sword2/header.h"
-#include "sword2/icons.h"
-#include "sword2/object.h"
-#include "sword2/save_rest.h"
-
-#define MAX_starts 100
-#define MAX_description 100
-
-class GameDetector;
-class OSystem;
-
-namespace Sword2 {
-
-enum {
- GF_DEMO = 1 << 0
-};
-
-class MemoryManager;
-class ResourceManager;
-class Sound;
-class Screen;
-class Mouse;
-class Logic;
-class FontRenderer;
-class Gui;
-class Debugger;
-
-enum {
- RD_LEFTBUTTONDOWN = 0x01,
- RD_LEFTBUTTONUP = 0x02,
- RD_RIGHTBUTTONDOWN = 0x04,
- RD_RIGHTBUTTONUP = 0x08,
- RD_WHEELUP = 0x10,
- RD_WHEELDOWN = 0x20,
- RD_KEYDOWN = 0x40,
- RD_MOUSEMOVE = 0x80
-};
-
-struct MouseEvent {
- bool pending;
- uint16 buttons;
-};
-
-struct KeyboardEvent {
- bool pending;
- uint32 repeat;
- uint16 ascii;
- int keycode;
- int modifiers;
-};
-
-struct StartUp {
- char description[MAX_description];
-
- // id of screen manager object
- uint32 start_res_id;
-
- // Tell the manager which startup you want (if there are more than 1)
- // (i.e more than 1 entrance to a screen and/or separate game boots)
- uint32 key;
-};
-
-class Sword2Engine : public Engine {
-private:
- uint32 _inputEventFilter;
-
- // The event "buffers"
- MouseEvent _mouseEvent;
- KeyboardEvent _keyboardEvent;
-
- uint32 _bootParam;
- int32 _saveSlot;
-
- void getPlayerStructures();
- void putPlayerStructures();
-
- uint32 saveData(uint16 slotNo, byte *buffer, uint32 bufferSize);
- uint32 restoreData(uint16 slotNo, byte *buffer, uint32 bufferSize);
-
- uint32 calcChecksum(byte *buffer, uint32 size);
-
- void pauseGame();
- void unpauseGame();
-
- uint32 _totalStartups;
- uint32 _totalScreenManagers;
- uint32 _startRes;
-
- bool _useSubtitles;
-
- StartUp _startList[MAX_starts];
-
-public:
- Sword2Engine(GameDetector *detector, OSystem *syst);
- ~Sword2Engine();
- int go();
- int init(GameDetector &detector);
-
- void registerDefaultSettings();
- void readSettings();
- void writeSettings();
-
- void setupPersistentResources();
-
- bool getSubtitles() { return _useSubtitles; }
- void setSubtitles(bool b) { _useSubtitles = b; }
-
- bool _quit;
-
- uint32 _features;
- Common::String _targetName; // target name for saves
-
- MemoryManager *_memory;
- ResourceManager *_resman;
- Sound *_sound;
- Screen *_screen;
- Mouse *_mouse;
- Logic *_logic;
- FontRenderer *_fontRenderer;
-
- Debugger *_debugger;
-
- Common::RandomSource _rnd;
-
- uint32 _speechFontId;
- uint32 _controlsFontId;
- uint32 _redFontId;
-
- uint32 setInputEventFilter(uint32 filter);
-
- void clearInputEvents();
- void parseInputEvents();
-
- bool checkForMouseEvents();
- MouseEvent *mouseEvent();
- KeyboardEvent *keyboardEvent();
-
- bool _wantSfxDebug;
-
- int32 _gameCycle;
-
-#ifdef SWORD2_DEBUG
- bool _renderSkip;
- bool _stepOneCycle;
-#endif
-
-#if RIGHT_CLICK_CLEARS_LUGGAGE
- bool heldIsInInventory();
-#endif
-
- byte *fetchPalette(byte *screenFile);
- byte *fetchScreenHeader(byte *screenFile);
- byte *fetchLayerHeader(byte *screenFile, uint16 layerNo);
- byte *fetchShadingMask(byte *screenFile);
-
- byte *fetchAnimHeader(byte *animFile);
- byte *fetchCdtEntry(byte *animFile, uint16 frameNo);
- byte *fetchFrameHeader(byte *animFile, uint16 frameNo);
- byte *fetchBackgroundParallaxLayer(byte *screenFile, int layer);
- byte *fetchBackgroundLayer(byte *screenFile);
- byte *fetchForegroundParallaxLayer(byte *screenFile, int layer);
- byte *fetchTextLine(byte *file, uint32 text_line);
- bool checkTextLine(byte *file, uint32 text_line);
- byte *fetchPaletteMatchTable(byte *screenFile);
-
- uint32 saveGame(uint16 slotNo, byte *description);
- uint32 restoreGame(uint16 slotNo);
- uint32 getSaveDescription(uint16 slotNo, byte *description);
- bool saveExists();
- bool saveExists(uint16 slotNo);
- uint32 restoreFromBuffer(byte *buffer, uint32 size);
- uint32 findBufferSize();
-
- bool _gamePaused;
- bool _graphicsLevelFudged;
-
- void startGame();
- void gameCycle();
- void closeGame();
- void restartGame();
-
- void sleepUntil(uint32 time);
-
- void errorString(const char *buf_input, char *buf_output);
- void initialiseFontResourceFlags();
- void initialiseFontResourceFlags(uint8 language);
-
- bool initStartMenu();
- void registerStartPoint(int32 key, char *name);
-
- uint32 getNumStarts() { return _totalStartups; }
- uint32 getNumScreenManagers() { return _totalScreenManagers; }
- StartUp *getStartList() { return _startList; }
-
- void runStart(int start);
-
- // Convenience alias for OSystem::getMillis().
- // This is a bit hackish, of course :-).
- uint32 getMillis();
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/sync.cpp b/sword2/sync.cpp
deleted file mode 100644
index 205e273873..0000000000
--- a/sword2/sync.cpp
+++ /dev/null
@@ -1,76 +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$
- */
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-
-namespace Sword2 {
-
-/**
- * Clear any syncs registered for this id. Call this just after the id has been
- * processed. Theoretically there could be more than one sync waiting for us,
- * so clear the lot.
- */
-
-void Logic::clearSyncs(uint32 id) {
- for (int i = 0; i < ARRAYSIZE(_syncList); i++) {
- if (_syncList[i].id == id) {
- debug(5, "removing sync %d for %d", i, id);
- _syncList[i].id = 0;
- }
- }
-}
-
-void Logic::sendSync(uint32 id, uint32 sync) {
- for (int i = 0; i < ARRAYSIZE(_syncList); i++) {
- if (_syncList[i].id == 0) {
- debug(5, "%d sends sync %d to %d", readVar(ID), sync, id);
- _syncList[i].id = id;
- _syncList[i].sync = sync;
- return;
- }
- }
-
- // The original code didn't even check for this condition, so maybe
- // it should be a fatal error?
-
- warning("No free sync slot");
-}
-
-/**
- * Check for a sync waiting for this character. Called from fnAnim() to see if
- * animation is to be finished. Returns an index into _syncList[], or -1.
- */
-
-int Logic::getSync() {
- uint32 id = readVar(ID);
-
- for (int i = 0; i < ARRAYSIZE(_syncList); i++) {
- if (_syncList[i].id == id)
- return i;
- }
-
- return -1;
-}
-
-} // End of namespace Sword2
diff --git a/sword2/walker.cpp b/sword2/walker.cpp
deleted file mode 100644
index 82ef80f65f..0000000000
--- a/sword2/walker.cpp
+++ /dev/null
@@ -1,454 +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$
- */
-
-// WALKER.CPP by James (14nov96)
-
-// Functions for moving megas about the place & also for keeping tabs on them
-
-#include "common/stdafx.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/interpreter.h"
-#include "sword2/logic.h"
-#include "sword2/resman.h"
-#include "sword2/router.h"
-
-namespace Sword2 {
-
-void Router::setStandbyCoords(int16 x, int16 y, uint8 dir) {
- assert(dir <= 7);
-
- _standbyX = x;
- _standbyY = y;
- _standbyDir = dir;
-}
-
-/**
- * Work out direction from start to dest.
- */
-
-// Used in whatTarget(); not valid for all megas
-#define diagonalx 36
-#define diagonaly 8
-
-int Router::whatTarget(int startX, int startY, int destX, int destY) {
- int deltaX = destX - startX;
- int deltaY = destY - startY;
-
- // 7 0 1
- // 6 2
- // 5 4 3
-
- // Flat route
-
- if (ABS(deltaY) * diagonalx < ABS(deltaX) * diagonaly / 2)
- return (deltaX > 0) ? 2 : 6;
-
- // Vertical route
-
- if (ABS(deltaY) * diagonalx / 2 > ABS(deltaX) * diagonaly)
- return (deltaY > 0) ? 4 : 0;
-
- // Diagonal route
-
- if (deltaX > 0)
- return (deltaY > 0) ? 3 : 1;
-
- return (deltaY > 0) ? 5 : 7;
-}
-
-/**
- * Walk meta to (x,y,dir). Set RESULT to 0 if it succeeded. Otherwise, set
- * RESULT to 1. Return true if the mega has finished walking.
- */
-
-int Router::doWalk(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y, uint8 target_dir) {
- ObjectLogic obLogic(ob_logic);
- ObjectGraphic obGraph(ob_graph);
- ObjectMega obMega(ob_mega);
-
- // If this is the start of the walk, calculate the route.
-
- if (obLogic.getLooping() == 0) {
- // If we're already there, don't even bother allocating
- // memory and calling the router, just quit back & continue
- // the script! This avoids an embarassing mega stand frame
- // appearing for one cycle when we're already in position for
- // an anim eg. repeatedly clicking on same object to repeat
- // an anim - no mega frame will appear in between runs of the
- // anim.
-
- if (obMega.getFeetX() == target_x && obMega.getFeetY() == target_y && obMega.getCurDir() == target_dir) {
- _vm->_logic->writeVar(RESULT, 0);
- return IR_CONT;
- }
-
- assert(target_dir <= 8);
-
- obMega.setWalkPc(0);
-
- // Set up mem for _walkData in route_slots[] & set mega's
- // 'route_slot_id' accordingly
- allocateRouteMem();
-
- int32 route = routeFinder(ob_mega, ob_walkdata, target_x, target_y, target_dir);
-
- // 0 = can't make route to target
- // 1 = created route
- // 2 = zero route but may need to turn
-
- if (route != 1 && route != 2) {
- freeRouteMem();
- _vm->_logic->writeVar(RESULT, 1);
- return IR_CONT;
- }
-
- // Walk is about to start
-
- obMega.setIsWalking(1);
- obLogic.setLooping(1);
- obGraph.setAnimResource(obMega.getMegasetRes());
- } else if (_vm->_logic->readVar(EXIT_FADING) && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
- // Double clicked an exit, and the screen has faded down to
- // black. Ok, that's it. Back to script and change screen.
-
- // We have to clear te EXIT_CLICK_ID variable in case there's a
- // walk instruction on the new screen, or it'd be cut short.
-
- freeRouteMem();
-
- obLogic.setLooping(0);
- obMega.setIsWalking(0);
- _vm->_logic->writeVar(EXIT_CLICK_ID, 0);
- _vm->_logic->writeVar(RESULT, 0);
-
- return IR_CONT;
- }
-
- // Get pointer to walkanim & current frame position
-
- WalkData *walkAnim = getRouteMem();
- int32 walk_pc = obMega.getWalkPc();
-
- // If stopping the walk early, overwrite the next step with a
- // slow-out, then finish
-
- if (_vm->_logic->checkEventWaiting() && walkAnim[walk_pc].step == 0 && walkAnim[walk_pc + 1].step == 1) {
- // At the beginning of a step
- earlySlowOut(ob_mega, ob_walkdata);
- }
-
- // Get new frame of walk
-
- obGraph.setAnimPc(walkAnim[walk_pc].frame);
- obMega.setCurDir(walkAnim[walk_pc].dir);
- obMega.setFeetX(walkAnim[walk_pc].x);
- obMega.setFeetY(walkAnim[walk_pc].y);
-
- // Is the NEXT frame is the end-marker (512) of the walk sequence?
-
- if (walkAnim[walk_pc + 1].frame != 512) {
- // No, it wasn't. Increment the walk-anim frame number and
- // come back next cycle.
- obMega.setWalkPc(obMega.getWalkPc() + 1);
- return IR_REPEAT;
- }
-
- // We have reached the end-marker, which means we can return to the
- // script just as the final (stand) frame of the walk is set.
-
- freeRouteMem();
- obLogic.setLooping(0);
- obMega.setIsWalking(0);
-
- // If George's walk has been interrupted to run a new action script for
- // instance or Nico's walk has been interrupted by player clicking on
- // her to talk
-
- // There used to be code here for checking if two megas were colliding,
- // but it had been commented out, and it was only run if a function
- // that always returned zero returned non-zero.
-
- if (_vm->_logic->checkEventWaiting()) {
- _vm->_logic->startEvent();
- _vm->_logic->writeVar(RESULT, 1);
- return IR_TERMINATE;
- }
-
- _vm->_logic->writeVar(RESULT, 0);
-
- // CONTINUE the script so that RESULT can be checked! Also, if an anim
- // command follows the fnWalk command, the 1st frame of the anim (which
- // is always a stand frame itself) can replace the final stand frame of
- // the walk, to hide the slight difference between the shrinking on the
- // mega frames and the pre-shrunk anim start-frame.
-
- return IR_CONT;
-}
-
-/**
- * Walk mega to start position of anim
- */
-
-int Router::walkToAnim(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 animRes) {
- int16 target_x = 0;
- int16 target_y = 0;
- uint8 target_dir = 0;
-
- // Walkdata is needed for earlySlowOut if player clicks elsewhere
- // during the walk.
-
- // If this is the start of the walk, read anim file to get start coords
-
- ObjectLogic obLogic(ob_logic);
-
- if (obLogic.getLooping() == 0) {
- byte *anim_file = _vm->_resman->openResource(animRes);
- AnimHeader anim_head;
-
- anim_head.read(_vm->fetchAnimHeader(anim_file));
-
- target_x = anim_head.feetStartX;
- target_y = anim_head.feetStartY;
- target_dir = anim_head.feetStartDir;
-
- _vm->_resman->closeResource(animRes);
-
- // If start coords not yet set in anim header, use the standby
- // coords (which should be set beforehand in the script).
-
- if (target_x == 0 && target_y == 0) {
- target_x = _standbyX;
- target_y = _standbyY;
- target_dir = _standbyDir;
- }
-
- assert(target_dir <= 7);
- }
-
- return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
-}
-
-/**
- * Route to the left or right hand side of target id, if possible.
- */
-
-int Router::walkToTalkToMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId, uint32 separation) {
- ObjectMega obMega(ob_mega);
-
- int16 target_x = 0;
- int16 target_y = 0;
- uint8 target_dir = 0;
-
- // If this is the start of the walk, calculate the route.
-
- ObjectLogic obLogic(ob_logic);
-
- if (obLogic.getLooping() == 0) {
- assert(_vm->_resman->fetchType(megaId) == GAME_OBJECT);
-
- // Call the base script. This is the graphic/mouse service
- // call, and will set _engineMega to the ObjectMega of mega we
- // want to route to.
-
- _vm->_logic->runResScript(megaId, 3);
-
- ObjectMega targetMega(_vm->_logic->getEngineMega());
-
- // Stand exactly beside the mega, ie. at same y-coord
- target_y = targetMega.getFeetY();
-
- int scale = obMega.calcScale();
- int mega_separation = (separation * scale) / 256;
-
- debug(4, "Target is at (%d, %d), separation %d", targetMega.getFeetX(), targetMega.getFeetY(), mega_separation);
-
- if (targetMega.getFeetX() < obMega.getFeetX()) {
- // Target is left of us, so aim to stand to their
- // right. Face down_left
-
- target_x = targetMega.getFeetX() + mega_separation;
- target_dir = 5;
- } else {
- // Ok, must be right of us so aim to stand to their
- // left. Face down_right.
-
- target_x = targetMega.getFeetX() - mega_separation;
- target_dir = 3;
- }
- }
-
- return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
-}
-/**
- * Turn mega to the specified direction. Just needs to call doWalk() with
- * current feet coords, so router can produce anim of turn frames.
- */
-
-int Router::doFace(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint8 target_dir) {
- int16 target_x = 0;
- int16 target_y = 0;
-
- // If this is the start of the turn, get the mega's current feet
- // coords + the required direction
-
- ObjectLogic obLogic(ob_logic);
-
- if (obLogic.getLooping() == 0) {
- assert(target_dir <= 7);
-
- ObjectMega obMega(ob_mega);
-
- target_x = obMega.getFeetX();
- target_y = obMega.getFeetY();
- }
-
- return doWalk(ob_logic, ob_graph, ob_mega, ob_walkdata, target_x, target_y, target_dir);
-}
-
-/**
- * Turn mega to face point (x,y) on the floor
- */
-
-int Router::faceXY(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, int16 target_x, int16 target_y) {
- uint8 target_dir = 0;
-
- // If this is the start of the turn, get the mega's current feet
- // coords + the required direction
-
- ObjectLogic obLogic(ob_logic);
-
- if (obLogic.getLooping() == 0) {
- ObjectMega obMega(ob_mega);
-
- target_dir = whatTarget(obMega.getFeetX(), obMega.getFeetY(), target_x, target_y);
- }
-
- return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
-}
-
-/**
- * Turn mega to face another mega.
- */
-
-int Router::faceMega(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *ob_walkdata, uint32 megaId) {
- uint8 target_dir = 0;
-
- // If this is the start of the walk, decide where to walk to.
-
- ObjectLogic obLogic(ob_logic);
-
- if (obLogic.getLooping() == 0) {
- assert(_vm->_resman->fetchType(megaId) == GAME_OBJECT);
-
- // Call the base script. This is the graphic/mouse service
- // call, and will set _engineMega to the ObjectMega of mega we
- // want to turn to face.
-
- _vm->_logic->runResScript(megaId, 3);
-
- ObjectMega obMega(ob_mega);
- ObjectMega targetMega(_vm->_logic->getEngineMega());
-
- target_dir = whatTarget(obMega.getFeetX(), obMega.getFeetY(), targetMega.getFeetX(), targetMega.getFeetY());
- }
-
- return doFace(ob_logic, ob_graph, ob_mega, ob_walkdata, target_dir);
-}
-
-/**
- * Stand mega at (x,y,dir)
- * Sets up the graphic object, but also needs to set the new 'current_dir' in
- * the mega object, so the router knows in future
- */
-
-void Router::standAt(byte *ob_graph, byte *ob_mega, int32 x, int32 y, int32 dir) {
- assert(dir >= 0 && dir <= 7);
-
- ObjectGraphic obGraph(ob_graph);
- ObjectMega obMega(ob_mega);
-
- // Set up the stand frame & set the mega's new direction
-
- obMega.setFeetX(x);
- obMega.setFeetY(y);
- obMega.setCurDir(dir);
-
- // Mega-set animation file
- obGraph.setAnimResource(obMega.getMegasetRes());
-
- // Dir + first stand frame (always frame 96)
- obGraph.setAnimPc(dir + 96);
-}
-
-/**
- * Stand mega at end position of anim
- */
-
-void Router::standAfterAnim(byte *ob_graph, byte *ob_mega, uint32 animRes) {
- byte *anim_file = _vm->_resman->openResource(animRes);
- AnimHeader anim_head;
-
- anim_head.read(_vm->fetchAnimHeader(anim_file));
-
- int32 x = anim_head.feetEndX;
- int32 y = anim_head.feetEndY;
- int32 dir = anim_head.feetEndDir;
-
- _vm->_resman->closeResource(animRes);
-
- // If start coords not available either use the standby coords (which
- // should be set beforehand in the script)
-
- if (x == 0 && y == 0) {
- x = _standbyX;
- y = _standbyY;
- dir = _standbyDir;
- }
-
- standAt(ob_graph, ob_mega, x, y, dir);
-}
-
-void Router::standAtAnim(byte *ob_graph, byte *ob_mega, uint32 animRes) {
- byte *anim_file = _vm->_resman->openResource(animRes);
- AnimHeader anim_head;
-
- anim_head.read(_vm->fetchAnimHeader(anim_file));
-
- int32 x = anim_head.feetStartX;
- int32 y = anim_head.feetStartY;
- int32 dir = anim_head.feetStartDir;
-
- _vm->_resman->closeResource(animRes);
-
- // If start coords not available use the standby coords (which should
- // be set beforehand in the script)
-
- if (x == 0 && y == 0) {
- x = _standbyX;
- y = _standbyY;
- dir = _standbyDir;
- }
-
- standAt(ob_graph, ob_mega, x, y, dir);
-}
-
-} // End of namespace Sword2