mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-08 02:42:34 +00:00
1727 lines
39 KiB
C++
1727 lines
39 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include "common/scummsys.h"
|
|
#include "common/translation.h"
|
|
|
|
#include "common/savefile.h"
|
|
#include "graphics/thumbnail.h"
|
|
#include "common/config-manager.h"
|
|
#include "common/error.h"
|
|
#include "graphics/cursorman.h"
|
|
#include "graphics/surface.h"
|
|
#include "graphics/screen.h"
|
|
#include "graphics/palette.h"
|
|
#include "common/system.h"
|
|
#include "image/iff.h"
|
|
#include "engines/util.h"
|
|
#include "common/debug.h"
|
|
#include "common/debug-channels.h"
|
|
#include "common/stream.h"
|
|
#include "common/memstream.h"
|
|
#include "common/events.h"
|
|
#include "audio/audiostream.h"
|
|
#include "audio/mixer.h"
|
|
#include "audio/decoders/raw.h"
|
|
#include "gui/saveload.h"
|
|
#include "video/mve_decoder.h"
|
|
|
|
#include "kingdom/kingdom.h"
|
|
|
|
namespace Kingdom {
|
|
|
|
KingdomGame::KingdomGame(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
|
|
_console = nullptr;
|
|
_rnd = new Common::RandomSource("kingdom");
|
|
|
|
DebugMan.addDebugChannel(kDebugGeneral, "general", "General debug level");
|
|
|
|
_logic = nullptr;
|
|
|
|
_asPtr = nullptr;
|
|
_quit = false;
|
|
_kingartEntries = nullptr;
|
|
|
|
_tickCount = 0;
|
|
_oldTime = g_system->getMillis();
|
|
|
|
_showHotspots = false;
|
|
|
|
const Common::FSNode gameDataDir(ConfMan.get("path"));
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "MAPS");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "PICS");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "SOUNDS");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "SOUNDM");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "MOVIELF");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "MOVIES");
|
|
|
|
initVariables();
|
|
}
|
|
|
|
void KingdomGame::initVariables() {
|
|
_tsIconOnly = false;
|
|
_treeRightSta = 0;
|
|
_treeRightPic = 0;
|
|
_treeLeftSta = 0;
|
|
_treeLeftPic = 0;
|
|
_treeHGUPic = 0;
|
|
_treeHGTimer = 0;
|
|
_treeHGSta = 0;
|
|
_treeHGPic = 0;
|
|
_treeEyeTimer = 0;
|
|
_treeEyeSta = 0;
|
|
_treeEyePic = 0;
|
|
_noIFScreen = false;
|
|
_iconSel = 0;
|
|
_iconSelect = 0;
|
|
_iconsClosed = false;
|
|
for (int i = 0; i < 7; i++)
|
|
_iconPic[i] = 0;
|
|
|
|
_iconRedraw = false;
|
|
_healthTmr = 0;
|
|
_palStepFlag = false;
|
|
_skylarTimerFlag = false;
|
|
_skylarTimer = 0;
|
|
_cTimerFlag = false;
|
|
_cTimer = 0;
|
|
_bTimerFlag = false;
|
|
_bTimer = 0;
|
|
_aTimerFlag = false;
|
|
_aTimer = 0;
|
|
_zoom = 0;
|
|
_wizard = false;
|
|
_userInput = 0;
|
|
// _track = 0;
|
|
// _statMap = 0;
|
|
// _quitFlag = 0;
|
|
_soundNumber = 0;
|
|
_pMovie = 0;
|
|
_oldTRS = 0;
|
|
_oldTLS = 0;
|
|
_oldIconsClosed = false;
|
|
_fstFwd = false;
|
|
_noMusic = false;
|
|
_mouseValue = 0;
|
|
_mapEx = false;
|
|
_loopFlag = false;
|
|
_lastSound = 0;
|
|
_keyActive = false;
|
|
_itemInhibit = false;
|
|
_gameMode = 0;
|
|
_fullScreen = false;
|
|
_frameStop = 0;
|
|
_daelonCntr = 0;
|
|
_sound = false;
|
|
_asMode = false;
|
|
for (int i = 0; i < 510; i++) {
|
|
_rezPointers[i] = nullptr;
|
|
_rezSize[i] = 0;
|
|
}
|
|
_mouseDebound = false;
|
|
_mouseButton = 0;
|
|
_cursorDrawn = false;
|
|
_oldCursorPos = Common::Point(0, 0);
|
|
_oldCursorDef = 0;
|
|
_cursorDef = 0;
|
|
_cursorPos = Common::Point(0, 0);
|
|
_asMap = 0;
|
|
}
|
|
|
|
KingdomGame::~KingdomGame() {
|
|
delete _console;
|
|
delete _logic;
|
|
delete _rnd;
|
|
}
|
|
|
|
bool KingdomGame::isDemo() const {
|
|
return (bool)(_gameDescription->flags & ADGF_DEMO);
|
|
}
|
|
|
|
Common::Error KingdomGame::run() {
|
|
initGraphics(320, 200);
|
|
_console = new Console(this);
|
|
|
|
_logic = new Logic(this);
|
|
_logic->initVariables();
|
|
|
|
setupPics();
|
|
initTools();
|
|
titlePage();
|
|
|
|
initPlay();
|
|
initHelp();
|
|
|
|
while (!_quit) {
|
|
_loopFlag = false;
|
|
_logic->gameHelp();
|
|
if (_gameMode == 0) {
|
|
// Same behavior than in the original. Switching from a
|
|
// group to a higher one skips refreshScreen and (eventually)
|
|
// getUserInput
|
|
if (_logic->_statPlay < 250)
|
|
_logic->executeOpcode();
|
|
if (_logic->_statPlay > 249 && _logic->_statPlay < 500)
|
|
_logic->executeOpcode();
|
|
if (_logic->_statPlay > 499 && _logic->_statPlay < 900)
|
|
_logic->executeOpcode();
|
|
if (_logic->_statPlay > 899)
|
|
_logic->executeOpcode();
|
|
}
|
|
|
|
if (!_loopFlag)
|
|
getUserInput();
|
|
|
|
refreshScreen();
|
|
}
|
|
|
|
fadeToBlack2();
|
|
return Common::kNoError;
|
|
}
|
|
|
|
void KingdomGame::refreshScreen() {
|
|
displayDebugHotSpots();
|
|
|
|
g_system->updateScreen();
|
|
checkTimers();
|
|
|
|
// Signal the ScummVM debugger
|
|
_console->onFrame();
|
|
}
|
|
|
|
void KingdomGame::checkTimers() {
|
|
uint32 newTime = g_system->getMillis();
|
|
int32 delay = 11 - (newTime - _oldTime);
|
|
if (delay > 0)
|
|
g_system->delayMillis(delay);
|
|
_oldTime = newTime;
|
|
_tickCount++;
|
|
|
|
if (_tickCount == 5) {
|
|
_tickCount = 0;
|
|
} else
|
|
return;
|
|
|
|
if (_aTimer != 0) {
|
|
_aTimer--;
|
|
if (_aTimer == 0)
|
|
_aTimerFlag = true;
|
|
}
|
|
|
|
if (_bTimer != 0) {
|
|
_bTimer--;
|
|
if (_bTimer == 0)
|
|
_bTimerFlag = true;
|
|
}
|
|
|
|
if (_cTimer != 0) {
|
|
_cTimer--;
|
|
if (_cTimer == 0) {
|
|
_cTimerFlag = true;
|
|
_cTimer = 4;
|
|
}
|
|
} else
|
|
_cTimer = 4;
|
|
|
|
if (_skylarTimer != 0) {
|
|
_skylarTimer--;
|
|
if (_skylarTimer == 0)
|
|
_skylarTimerFlag = true;
|
|
}
|
|
|
|
_palStepFlag = false;
|
|
}
|
|
|
|
void KingdomGame::drawScreen() {
|
|
//TODO
|
|
|
|
_console->onFrame();
|
|
}
|
|
|
|
void KingdomGame::setupPics() {
|
|
loadKingArt();
|
|
}
|
|
|
|
void KingdomGame::initTools() {
|
|
initMouse();
|
|
//CHECKME: InitTimers?
|
|
showPic(124);
|
|
initCursor();
|
|
setMouse();
|
|
fadeToBlack2();
|
|
initMPlayer();
|
|
}
|
|
|
|
void KingdomGame::titlePage() {
|
|
// TODO: Check on QuitFlag == 2
|
|
if (shouldQuit())
|
|
return;
|
|
|
|
_fstFwd = true;
|
|
_noIFScreen = true;
|
|
_sound = false;
|
|
fadeToBlack2();
|
|
playMovie(200);
|
|
if (shouldQuit()) {
|
|
return;
|
|
}
|
|
|
|
fadeToBlack2();
|
|
playMovie(206);
|
|
if (shouldQuit()) {
|
|
return;
|
|
}
|
|
|
|
fadeToBlack2();
|
|
playMovie(198);
|
|
if (shouldQuit()) {
|
|
return;
|
|
}
|
|
|
|
fadeToBlack2();
|
|
}
|
|
|
|
void KingdomGame::initPlay() {
|
|
for (int i = 0; i < 7; i++)
|
|
_iconPic[i] = 89 + i;
|
|
|
|
_frameStop = 0;
|
|
_gameMode = 0;
|
|
_daelonCntr = 0;
|
|
_itemInhibit = false;
|
|
_asMode = false;
|
|
_aTimerFlag = false;
|
|
_bTimerFlag = false;
|
|
_cTimerFlag = false;
|
|
_skylarTimerFlag = false;
|
|
_aTimer = 0;
|
|
_bTimer = 0;
|
|
_cTimer = 0;
|
|
_skylarTimer = 0;
|
|
_mapEx = false;
|
|
_healthTmr = 0;
|
|
_treeEyeTimer = 0;
|
|
_treeHGTimer = 0;
|
|
_treeHGUPic = 147;
|
|
_treeLeftPic = 0;
|
|
_treeRightPic = 0;
|
|
_treeRightSta = 1;
|
|
_tsIconOnly = false;
|
|
_noIFScreen = true;
|
|
_noMusic = false;
|
|
_fstFwd = true;
|
|
|
|
delete[] _asPtr;
|
|
_asPtr = nullptr;
|
|
|
|
_logic->initPlay();
|
|
}
|
|
|
|
void KingdomGame::initHelp() {
|
|
_gameMode = 0;
|
|
}
|
|
|
|
void KingdomGame::fadeToBlack1() {
|
|
debug("STUB: FadeToBlack1");
|
|
}
|
|
|
|
void KingdomGame::fadeToBlack2() {
|
|
debug("STUB: FadeToBlack2");
|
|
}
|
|
|
|
void KingdomGame::loadKingArt() {
|
|
loadAResource(0x97);
|
|
Common::SeekableReadStream *kingartStream = _rezPointers[0x97];
|
|
int val = kingartStream->readUint32LE();
|
|
int size = val / 4;
|
|
uint32 *kingartIdx = new uint32[size + 1];
|
|
_kingartEntries = new KingArtEntry[size];
|
|
kingartIdx[0] = val;
|
|
for (int i = 1; i < size; i++)
|
|
kingartIdx[i] = kingartStream->readUint32LE();
|
|
kingartIdx[size] = kingartStream->size();
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
int chunkSize = kingartIdx[i + 1] - kingartIdx[i];
|
|
_kingartEntries[i]._width = kingartStream->readByte();
|
|
_kingartEntries[i]._height = kingartStream->readByte();
|
|
|
|
assert(_kingartEntries[i]._width * _kingartEntries[i]._height == chunkSize - 2);
|
|
|
|
_kingartEntries[i]._data = new byte[chunkSize - 2];
|
|
kingartStream->read(_kingartEntries[i]._data, chunkSize - 2);
|
|
}
|
|
|
|
delete[] kingartIdx;
|
|
}
|
|
|
|
void KingdomGame::loadAResource(int reznum) {
|
|
Common::String path = Common::String(_rezNames[reznum]);
|
|
path.toUppercase();
|
|
|
|
debug("Loading resource: %i (%s)\n", reznum, path.c_str());
|
|
|
|
if(!_rezSize[reznum]) {
|
|
Common::File *file = new Common::File();
|
|
if(!file->open(path))
|
|
warning("Failed to open %s", path.c_str());
|
|
else {
|
|
_rezSize[reznum] = file->size();
|
|
file->seek(0, SEEK_SET);
|
|
_rezPointers[reznum] = file->readStream(_rezSize[reznum]);
|
|
file->close();
|
|
delete file;
|
|
}
|
|
}
|
|
}
|
|
|
|
void KingdomGame::releaseAResource(int reznum) {
|
|
if (_rezSize[reznum]) {
|
|
delete _rezPointers[reznum];
|
|
_rezSize[reznum] = 0;
|
|
}
|
|
}
|
|
|
|
void KingdomGame::showPic(int reznum) {
|
|
eraseCursor();
|
|
|
|
loadAResource(reznum);
|
|
Image::IFFDecoder decoder;
|
|
if (!_rezPointers[reznum] || !decoder.loadStream(*_rezPointers[reznum]))
|
|
return;
|
|
|
|
const byte *palette = decoder.getPalette();
|
|
int paletteColorCount = decoder.getPaletteColorCount();
|
|
g_system->getPaletteManager()->setPalette(palette, 0, paletteColorCount);
|
|
|
|
const Graphics::Surface *surface = decoder.getSurface();
|
|
|
|
const byte *data = (const byte *)surface->getPixels();
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
for (uint curX = 0; curX < 320; curX++) {
|
|
for (uint curY = 0; curY < 200; curY++) {
|
|
const byte *src = data + (curY * 320) + curX;
|
|
byte *dst = (byte *)screen->getBasePtr(curX, curY);
|
|
if (*src != 0xFF)
|
|
*dst = *src;
|
|
}
|
|
}
|
|
g_system->unlockScreen();
|
|
g_system->updateScreen();
|
|
|
|
releaseAResource(reznum);
|
|
}
|
|
|
|
void KingdomGame::fShowPic(int reznum) {
|
|
eraseCursor();
|
|
fadeToBlack1();
|
|
drawRect(4, 17, 228, 161, 0);
|
|
showPic(reznum);
|
|
}
|
|
|
|
void KingdomGame::initCursor() {
|
|
initMouse();
|
|
setCursor(0x19C / 4);
|
|
_cursorDrawn = false;
|
|
drawCursor();
|
|
}
|
|
|
|
void KingdomGame::initMouse() {
|
|
// No implementation required
|
|
}
|
|
|
|
void KingdomGame::setMouse() {
|
|
g_system->warpMouse(272, 157);
|
|
_cursorPos = Common::Point(272, 157);
|
|
}
|
|
|
|
void KingdomGame::initMPlayer() {
|
|
// No implementation for ScummVM, everything is in the player class' constructor
|
|
}
|
|
|
|
void KingdomGame::playMovie(int movieNum) {
|
|
if (movieNum == 1 || movieNum == 3 || movieNum == 54 || movieNum == 198 || movieNum == 200 || movieNum == 206)
|
|
_fullScreen = true;
|
|
else
|
|
_fullScreen = false;
|
|
|
|
_mixer->stopAll();
|
|
|
|
_aTimer = 0;
|
|
_asMode = false;
|
|
|
|
eraseCursor();
|
|
|
|
if (!_fullScreen) {
|
|
_treeLeftSta = (_fstFwd == 0) ? 0 : 1;
|
|
_treeRightSta = 0;
|
|
_iconSel = _iconSelect;
|
|
_iconsClosed = true;
|
|
checkMainScreen();
|
|
setMouse();
|
|
_oldCursorPos = _cursorPos;
|
|
}
|
|
|
|
_pMovie = movieNum;
|
|
readMouse();
|
|
_mouseButton = 0;
|
|
_keyActive = false;
|
|
const Common::String path = Common::String::format("King%.3d.mve", movieNum);
|
|
|
|
// Check if the file is available. If not the original does the following: _ATimer = 55, display of error with a check of timer, exit
|
|
// That can be replaced by an error()
|
|
|
|
int x = _fullScreen ? 0 : 4;
|
|
int y = _fullScreen ? 0 : 17;
|
|
|
|
Video::MveDecoder *decoder = new Video::MveDecoder();
|
|
if (decoder->loadFile(path)) {
|
|
decoder->setAudioTrack(_sound);
|
|
decoder->start();
|
|
|
|
if (_frameStop) {
|
|
decoder->setEndFrame(_frameStop);
|
|
}
|
|
|
|
bool skipMovie = false;
|
|
while (!decoder->endOfVideo() && !skipMovie && !shouldQuit()) {
|
|
unsigned int delay = MIN<uint32>(decoder->getTimeToNextFrame(), 10u);
|
|
g_system->delayMillis(delay);
|
|
|
|
const Graphics::Surface *frame = nullptr;
|
|
|
|
if (decoder->needsUpdate()) {
|
|
frame = decoder->decodeNextFrame();
|
|
}
|
|
|
|
if (frame) {
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
screen->copyRectToSurface(*frame, x, y, Common::Rect(frame->w, frame->h));
|
|
g_system->unlockScreen();
|
|
|
|
if (decoder->hasDirtyPalette()) {
|
|
PaletteManager *paletteManager = g_system->getPaletteManager();
|
|
decoder->applyPalette(paletteManager);
|
|
}
|
|
|
|
g_system->updateScreen();
|
|
}
|
|
|
|
Common::Event event;
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_QUIT:
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
_quit = true;
|
|
break;
|
|
case Common::EVENT_KEYDOWN:
|
|
if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
|
|
skipMovie = true;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete decoder;
|
|
|
|
// This is hidden somewhere in RunMovieCtl callback...
|
|
showPic(300 + _pMovie);
|
|
|
|
if (!_fullScreen) {
|
|
_treeRightSta = 1;
|
|
_iconsClosed = false;
|
|
_iconSel = 9;
|
|
_treeLeftSta = _logic->_replay ? 2 : 0;
|
|
checkMainScreen();
|
|
drawCursor();
|
|
_fstFwd = true;
|
|
_frameStop = 0;
|
|
_lastSound = _sound;
|
|
_sound = false;
|
|
_userInput = 0;
|
|
}
|
|
}
|
|
|
|
void KingdomGame::saveAS() {
|
|
byte palette[256 * 3];
|
|
delete[] _asPtr;
|
|
_asPtr = new byte[224 * 146 + 768];
|
|
g_system->getPaletteManager()->grabPalette(palette, 0, 256);
|
|
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
for (uint curX = 0; curX < 224; curX++) {
|
|
for (uint curY = 0; curY < 146; curY++) {
|
|
byte *ptr = (byte *)screen->getBasePtr(curX + 4, curY + 15);
|
|
_asPtr[curY * 224 + curX] = *ptr;
|
|
}
|
|
}
|
|
|
|
for (uint i = 0; i < 768; i++)
|
|
_asPtr[224 * 146 + i] = palette[i];
|
|
|
|
g_system->unlockScreen();
|
|
g_system->updateScreen();
|
|
}
|
|
|
|
void KingdomGame::restoreAS() {
|
|
byte palette[256 * 3];
|
|
for (uint i = 0; i < 768; i++)
|
|
palette[i] = _asPtr[224 * 146 + i];
|
|
|
|
g_system->getPaletteManager()->setPalette(palette, 0, 256);
|
|
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
for (uint curX = 0; curX < 224; curX++) {
|
|
for (uint curY = 0; curY < 146; curY++) {
|
|
byte *ptr = (byte *)screen->getBasePtr(curX + 4, curY + 15);
|
|
*ptr = _asPtr[curY * 224 + curX];
|
|
}
|
|
}
|
|
|
|
g_system->unlockScreen();
|
|
g_system->updateScreen();
|
|
delete[] _asPtr;
|
|
_asPtr = nullptr;
|
|
}
|
|
|
|
void KingdomGame::drawHelpScreen() {
|
|
int picNum;
|
|
|
|
switch(_logic->_health) {
|
|
case 2:
|
|
picNum = 166;
|
|
break;
|
|
case 4:
|
|
picNum = 165;
|
|
break;
|
|
case 6:
|
|
picNum = 164;
|
|
break;
|
|
case 8:
|
|
picNum = 163;
|
|
break;
|
|
case 10:
|
|
picNum = 162;
|
|
break;
|
|
case 12:
|
|
default:
|
|
picNum = 161;
|
|
break;
|
|
}
|
|
|
|
if (_noMusic)
|
|
picNum += 6;
|
|
|
|
showPic(picNum);
|
|
}
|
|
|
|
void KingdomGame::drawRect(uint minX, uint minY, uint maxX, uint maxY, int color) {
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
for (uint curX = minX; curX < maxX; curX++) {
|
|
for (uint curY = minY; curY < maxY; curY++) {
|
|
byte *dst = (byte *)screen->getBasePtr(curX, curY);
|
|
*dst = color;
|
|
}
|
|
}
|
|
g_system->unlockScreen();
|
|
g_system->updateScreen();
|
|
}
|
|
|
|
void KingdomGame::drawEmptyRect(Common::Rect rect, int color) {
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
|
|
for (int curX = rect.left; curX < rect.right; curX++) {
|
|
byte *dst = (byte *)screen->getBasePtr(curX, rect.top);
|
|
*dst = color;
|
|
dst = (byte *)screen->getBasePtr(curX, rect.bottom);
|
|
*dst = color;
|
|
}
|
|
|
|
for (int curY = rect.top; curY < rect.bottom; curY++) {
|
|
byte *dst = (byte *)screen->getBasePtr(rect.left, curY);
|
|
*dst = color;
|
|
dst = (byte *)screen->getBasePtr(rect.right, curY);
|
|
*dst = color;
|
|
}
|
|
|
|
g_system->unlockScreen();
|
|
g_system->updateScreen();
|
|
}
|
|
|
|
void KingdomGame::drawInventory() {
|
|
fShowPic(108);
|
|
if (_logic->_nodes[28] == 1 || _logic->_nodes[67] == 1 || _itemInhibit)
|
|
return;
|
|
|
|
if (_logic->_inventory[0] > 0)
|
|
drawIcon(136, 102, 180);
|
|
|
|
if (_logic->_inventory[1] > 0)
|
|
drawIcon(73, 65, 175);
|
|
|
|
if (_logic->_inventory[2] > 0)
|
|
drawIcon(171, 96, 179);
|
|
|
|
if (_logic->_inventory[3] > 0)
|
|
drawIcon(120, 34, 174);
|
|
|
|
if (_logic->_inventory[4] > 0)
|
|
drawIcon(160, 41, 177);
|
|
|
|
if (_logic->_inventory[5] > 0)
|
|
drawIcon(21, 124, 184);
|
|
|
|
if (_logic->_inventory[6] > 0)
|
|
drawIcon(201, 42, 178);
|
|
|
|
if (_logic->_inventory[7] > 0)
|
|
drawIcon(76, 119, 186);
|
|
|
|
if (_logic->_inventory[8] > 0)
|
|
drawIcon(18, 31, 170);
|
|
|
|
if (_logic->_inventory[9] > 0)
|
|
drawIcon(57, 88, 185);
|
|
|
|
if (_logic->_inventory[10] > 0)
|
|
drawIcon(182, 124, 181);
|
|
|
|
if (_logic->_inventory[11] > 0)
|
|
drawIcon(176, 26, 183);
|
|
|
|
if (_logic->_inventory[12] > 0)
|
|
drawIcon(54, 23, 171);
|
|
|
|
if (_logic->_inventory[13] > 0)
|
|
drawIcon(120, 133, 182);
|
|
|
|
if (_logic->_inventory[14] > 0)
|
|
drawIcon(94, 92, 187);
|
|
|
|
if (_logic->_inventory[15] > 0)
|
|
drawIcon(135, 67, 176);
|
|
|
|
if (_logic->_inventory[16] > 0)
|
|
drawIcon(84, 30, 173);
|
|
|
|
if (_logic->_inventory[17] > 0)
|
|
drawIcon(20, 78, 172);
|
|
|
|
if (_logic->_inventory[0] > 0)
|
|
drawIcon(158, 117, 134 + _logic->_inventory[0]);
|
|
|
|
if (_logic->_inventory[1] > 0)
|
|
drawIcon(94, 67, 134 + _logic->_inventory[1]);
|
|
|
|
if (_logic->_inventory[2] > 0)
|
|
drawIcon(193, 105, 134 + _logic->_inventory[2]);
|
|
|
|
if (_logic->_inventory[3] > 0)
|
|
drawIcon(131, 39, 134 + _logic->_inventory[3]);
|
|
}
|
|
|
|
Common::String KingdomGame::getSavegameFilename(int slot) {
|
|
return Common::String::format("%s.%03d", _targetName.c_str(), slot);
|
|
}
|
|
|
|
void KingdomGame::saveGame() {
|
|
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
|
|
int16 savegameId = dialog->runModalWithCurrentTarget();
|
|
Common::String savegameDescription = dialog->getResultString();
|
|
delete dialog;
|
|
if (savegameId < 0)
|
|
return; // dialog aborted
|
|
saveGameState(savegameId, savegameDescription);
|
|
}
|
|
|
|
void KingdomGame::restoreGame() {
|
|
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
|
|
int16 savegameId = dialog->runModalWithCurrentTarget();
|
|
delete dialog;
|
|
|
|
if (savegameId < 0)
|
|
return; // dialog aborted
|
|
|
|
loadGameState(savegameId);
|
|
}
|
|
|
|
Common::Error KingdomGame::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
|
Common::String savegameFile = getSavegameFilename(slot);
|
|
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
|
|
Common::OutSaveFile *out = saveMan->openForSaving(savegameFile);
|
|
|
|
if (!out)
|
|
return Common::kCreatingFileFailed;
|
|
|
|
KingdomSavegameHeader header;
|
|
header._saveName = desc;
|
|
writeSavegameHeader(out, header);
|
|
|
|
Common::Serializer s(nullptr, out);
|
|
synchronize(s);
|
|
|
|
out->finalize();
|
|
delete out;
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
Common::Error KingdomGame::loadGameState(int slot) {
|
|
Common::String savegameFile = getSavegameFilename(slot);
|
|
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
|
|
Common::InSaveFile *inFile = saveMan->openForLoading(savegameFile);
|
|
if (!inFile)
|
|
return Common::kReadingFailed;
|
|
|
|
Common::Serializer s(inFile, nullptr);
|
|
|
|
KingdomSavegameHeader header;
|
|
if (!readSavegameHeader(inFile, header))
|
|
error("Invalid savegame");
|
|
|
|
if (header._thumbnail) {
|
|
header._thumbnail->free();
|
|
delete header._thumbnail;
|
|
}
|
|
|
|
// Load most of the savegame data
|
|
synchronize(s);
|
|
delete inFile;
|
|
|
|
delete[] _asPtr;
|
|
_asPtr = nullptr;
|
|
|
|
playSound(_soundNumber);
|
|
for (int i = 0; i < 7; i++)
|
|
_iconPic[i] = 89 + i;
|
|
|
|
_frameStop = 0;
|
|
_gameMode = 0;
|
|
_asMode = false;
|
|
_healthTmr = 0;
|
|
_noIFScreen = false;
|
|
_iconRedraw = true;
|
|
_treeRightSta = 1;
|
|
_aTimerFlag = false;
|
|
_aTimer = 0;
|
|
_bTimerFlag = false;
|
|
_bTimer = 0;
|
|
_treeEyeTimer = 0;
|
|
_treeEyePic = 0;
|
|
_treeHGUPic = 0;
|
|
_cursorDrawn = false;
|
|
showPic(106);
|
|
_gameMode = 0;
|
|
_iconsClosed = false;
|
|
drawRect(4, 17, 228, 161, 0);
|
|
_userInput = 0x43E;
|
|
_loopFlag = true;
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
void KingdomGame::synchronize(Common::Serializer &s) {
|
|
s.syncAsSint16LE(_asMap);
|
|
s.syncAsSint16LE(_daelonCntr);
|
|
s.syncAsSint16LE(_pMovie);
|
|
s.syncAsSint16LE(_soundNumber);
|
|
s.syncAsSint16LE(_treeEyePic);
|
|
s.syncAsSint16LE(_treeEyeSta);
|
|
s.syncAsSint16LE(_treeHGPic);
|
|
s.syncAsSint16LE(_treeHGSta);
|
|
s.syncAsSint16LE(_oldTLS);
|
|
s.syncAsSint16LE(_cTimer);
|
|
s.syncAsSint16LE(_skylarTimer);
|
|
s.syncAsByte(_fstFwd);
|
|
s.syncAsByte(_itemInhibit);
|
|
s.syncAsByte(_lastSound);
|
|
s.syncAsByte(_mapEx);
|
|
s.syncAsByte(_noMusic);
|
|
s.syncAsByte(_wizard);
|
|
s.syncAsByte(_tsIconOnly);
|
|
s.syncAsByte(_cTimerFlag);
|
|
s.syncAsByte(_skylarTimerFlag);
|
|
|
|
_logic->synchronize(s);
|
|
|
|
// Present in the original. Looks unused.
|
|
// s.syncAsSint16LE(_StatMap);
|
|
}
|
|
|
|
const char *const SAVEGAME_STR = "KTFR";
|
|
#define SAVEGAME_STR_SIZE 4
|
|
#define KTFR_SAVEGAME_VERSION 1
|
|
|
|
void KingdomGame::writeSavegameHeader(Common::OutSaveFile *out, KingdomSavegameHeader &header) {
|
|
// Write out a savegame header
|
|
out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
|
|
|
|
out->writeByte(KTFR_SAVEGAME_VERSION);
|
|
|
|
// Write savegame name
|
|
out->writeString(header._saveName);
|
|
out->writeByte('\0');
|
|
|
|
Common::MemoryWriteStreamDynamic *tempThumbnail = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
|
|
Graphics::saveThumbnail(*tempThumbnail);
|
|
out->write(tempThumbnail->getData(), tempThumbnail->size());
|
|
delete tempThumbnail;
|
|
|
|
// Write out the save date/time
|
|
TimeDate td;
|
|
g_system->getTimeAndDate(td);
|
|
out->writeSint16LE(td.tm_year + 1900);
|
|
out->writeSint16LE(td.tm_mon + 1);
|
|
out->writeSint16LE(td.tm_mday);
|
|
out->writeSint16LE(td.tm_hour);
|
|
out->writeSint16LE(td.tm_min);
|
|
}
|
|
|
|
bool KingdomGame::readSavegameHeader(Common::InSaveFile *in, KingdomSavegameHeader &header) {
|
|
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
|
|
header._thumbnail = nullptr;
|
|
|
|
// Validate the header Id
|
|
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
|
|
if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE))
|
|
return false;
|
|
|
|
header._version = in->readByte();
|
|
if (header._version > KTFR_SAVEGAME_VERSION)
|
|
return false;
|
|
|
|
// Read in the string
|
|
header._saveName.clear();
|
|
char ch;
|
|
while ((ch = (char)in->readByte()) != '\0')
|
|
header._saveName += ch;
|
|
|
|
// Get the thumbnail
|
|
Graphics::loadThumbnail(*in, header._thumbnail);
|
|
if (!header._thumbnail)
|
|
return false;
|
|
|
|
// Read in save date/time
|
|
header._year = in->readSint16LE();
|
|
header._month = in->readSint16LE();
|
|
header._day = in->readSint16LE();
|
|
header._hour = in->readSint16LE();
|
|
header._minute = in->readSint16LE();
|
|
|
|
return true;
|
|
}
|
|
|
|
void KingdomGame::playSound(int idx) {
|
|
if (idx > 43 || _soundNumber == idx)
|
|
return;
|
|
|
|
// Stop Sound
|
|
if (_mixer->isSoundHandleActive(_soundHandle)) {
|
|
_mixer->stopHandle(_soundHandle);
|
|
releaseAResource(idx);
|
|
}
|
|
|
|
_soundNumber = idx;
|
|
if (_soundNumber == 0 || _noMusic)
|
|
return;
|
|
|
|
int realIdx = _soundNumber + 200; // Or +250, depending in the original on the sound card
|
|
debug("PlaySound %d : %s", idx, _rezNames[realIdx]);
|
|
loadAResource(realIdx);
|
|
|
|
Common::SeekableReadStream *soundStream = _rezPointers[realIdx];
|
|
Audio::RewindableAudioStream *rewindableStream = Audio::makeRawStream(soundStream, 22050, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN, DisposeAfterUse::NO);
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
|
|
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, rewindableStream);
|
|
// In the original, there's an array describing whether a sound should loop or not.
|
|
// The array is full of 'false'. If a variant uses looping sound/music, the following code
|
|
// and the loop array should be added.
|
|
// Audio::AudioStream *stream = Audio::makeLoopingAudioStream(rewindableStream, _loopArray[idx]);
|
|
// _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, stream);
|
|
}
|
|
|
|
void KingdomGame::eraseCursor() {
|
|
CursorMan.showMouse(false);
|
|
}
|
|
|
|
void KingdomGame::readMouse() {
|
|
Common::EventManager *eventManager = g_system->getEventManager();
|
|
|
|
_mouseButton = eventManager->getButtonState();
|
|
_cursorPos = eventManager->getMousePos();
|
|
}
|
|
|
|
void KingdomGame::getUserInput() {
|
|
// CHECKME: _QuitFlag != 0
|
|
if (_quit)
|
|
return;
|
|
|
|
_userInput = waitKey();
|
|
|
|
if (_quit)
|
|
return;
|
|
|
|
if (_userInput == 2 && _logic->_eye)
|
|
_userInput = _asMode ? 0x43B : 0x43A;
|
|
|
|
if (_userInput == 1)
|
|
_userInput = _mouseValue;
|
|
|
|
if (_userInput == 0x2F5) {
|
|
_logic->_statPlay = 600;
|
|
_loopFlag = true;
|
|
}
|
|
|
|
if (_userInput == 0x42B && _logic->_statPlay != 53 && _gameMode == 0) {
|
|
_logic->_oldStatPlay = _logic->_statPlay;
|
|
_logic->_statPlay = 900;
|
|
_loopFlag = true;
|
|
}
|
|
|
|
if (_userInput == 0x12D && _logic->_currMap == 1)
|
|
// CHECKME: _quitFlag = 2;
|
|
_quit = true;
|
|
}
|
|
|
|
void KingdomGame::eraseCursorAsm() {
|
|
CursorMan.showMouse(false);
|
|
}
|
|
|
|
void KingdomGame::drawLocation() {
|
|
if (_daelonCntr > 0)
|
|
_daelonCntr--;
|
|
|
|
playSound(0);
|
|
_iconsClosed = true;
|
|
_tsIconOnly = false;
|
|
_aTimer = 0;
|
|
_aTimerFlag = false;
|
|
|
|
int emlValue = _emlTable[_logic->_nodeNum];
|
|
if (emlValue > 0)
|
|
_logic->enAll();
|
|
|
|
if (!_mapEx || !emlValue || _logic->_resurrect) {
|
|
if (_logic->_statPlay != 50)
|
|
_logic->_resurrect = false;
|
|
_iconsClosed = false;
|
|
} else {
|
|
_mapEx = false;
|
|
saveAS();
|
|
fShowPic(emlValue);
|
|
_bTimer = 16;
|
|
while(_bTimer) {
|
|
checkTimers();
|
|
refreshSound();
|
|
checkMainScreen();
|
|
}
|
|
fadeToBlack1();
|
|
drawRect(4, 17, 228, 161, 0);
|
|
_iconsClosed = false;
|
|
_tsIconOnly = false;
|
|
}
|
|
}
|
|
|
|
void KingdomGame::processMap(int mapNum, int zoom) {
|
|
int var6 = _zoomTable[mapNum][zoom][0];
|
|
if (!_asMode)
|
|
switchAtoM();
|
|
fShowPic(var6);
|
|
_logic->_currMap = _zoomTable[mapNum][zoom][1];
|
|
|
|
if (zoom > 0)
|
|
_treeLeftSta = _zoomTable[mapNum][zoom - 1][0] == 0 ? 0 : 3;
|
|
else
|
|
_treeLeftSta = 0;
|
|
|
|
if (zoom < 8)
|
|
_treeRightSta = _zoomTable[mapNum][zoom + 1][0] == 0 ? 0 : 2;
|
|
else
|
|
_treeRightSta = 0;
|
|
}
|
|
|
|
void KingdomGame::processMapInput(int mapNum) {
|
|
switch(_userInput) {
|
|
case 0x43B:
|
|
case 0x443:
|
|
switchMtoA();
|
|
_logic->_mapStat = 0;
|
|
_logic->_statPlay--;
|
|
break;
|
|
case 0x43F:
|
|
if (_treeLeftSta == 3) {
|
|
_zoom--;
|
|
processMap(mapNum, _zoom);
|
|
} else
|
|
_userInput = 0;
|
|
break;
|
|
case 0x440:
|
|
if (_treeRightSta == 2) {
|
|
_zoom++;
|
|
processMap(mapNum, _zoom);
|
|
} else
|
|
_userInput = 0;
|
|
break;
|
|
default:
|
|
if (_userInput > 0x3FF && _userInput < 0x428) {
|
|
_logic->_statPlay = _mapExit[_userInput - 0x400];
|
|
_mapEx = true;
|
|
_loopFlag = true;
|
|
_logic->switchAS();
|
|
}
|
|
|
|
if (_userInput > 0x440) {
|
|
switchMtoA();
|
|
_logic->_mapStat = false;
|
|
_logic->_statPlay--;
|
|
_loopFlag = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void KingdomGame::drawPic(int reznum) {
|
|
eraseCursor();
|
|
loadAResource(reznum);
|
|
|
|
Image::IFFDecoder decoder;
|
|
if (!decoder.loadStream(*_rezPointers[reznum]))
|
|
return;
|
|
|
|
const Graphics::Surface *surface = decoder.getSurface();
|
|
|
|
const byte *data = (const byte *)surface->getPixels();
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
for (uint curX = 0; curX < 320; curX++) {
|
|
for (uint curY = 0; curY < 200; curY++) {
|
|
const byte *src = data + (curY * 320) + curX;
|
|
byte *dst = (byte *)screen->getBasePtr(curX, curY);
|
|
if (*src != 0xFF)
|
|
*dst = *src;
|
|
}
|
|
}
|
|
g_system->unlockScreen();
|
|
g_system->updateScreen();
|
|
|
|
releaseAResource(reznum);
|
|
}
|
|
|
|
void KingdomGame::displayIcon(int reznum) {
|
|
// The demo isn't calling playsound(0).
|
|
// We keep the call because it stops properly the previous sound, if any.
|
|
playSound(0);
|
|
playSound(30);
|
|
saveAS();
|
|
fShowPic(reznum);
|
|
_bTimer = 76;
|
|
readMouse();
|
|
|
|
while(_bTimer != 0 && _mouseButton == 0) {
|
|
checkTimers();
|
|
refreshSound();
|
|
readMouse();
|
|
}
|
|
|
|
fadeToBlack1();
|
|
drawRect(4, 17, 228, 161, 0);
|
|
restoreAS();
|
|
}
|
|
|
|
void KingdomGame::setATimer() {
|
|
_aTimerFlag = true;
|
|
_aTimer = 0;
|
|
int wrkNodeNum = _logic->_nodeNum;
|
|
if (_logic->_nodes[28] == 1 || _logic->_nodes[67] == 1)
|
|
return;
|
|
|
|
if (_tsIconOnly)
|
|
wrkNodeNum = 79;
|
|
|
|
if (_logic->_nodeNum == 56 && _logic->_inventory[8] < 1 && _wizard)
|
|
wrkNodeNum = 80;
|
|
|
|
for (int i = 0; i < 7; i++) {
|
|
int idx = _iconActTable[wrkNodeNum][i];
|
|
if (_logic->_inventory[idx] > 0) {
|
|
_aTimerFlag = false;
|
|
_aTimer = _wizard ? 114 : 133;
|
|
playSound(0);
|
|
if (!isDemo())
|
|
playSound(34);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void KingdomGame::refreshSound() {
|
|
// No implementation needed in ScummVM
|
|
// The only useful check is against _sndReplayTbl, which determines
|
|
// which sound should be replayed. But this array contains only false
|
|
}
|
|
|
|
void KingdomGame::checkMainScreen() {
|
|
if (!_cTimerFlag || _logic->_statPlay == 900 || _logic->_statPlay == 901)
|
|
return;
|
|
|
|
_cTimerFlag = false;
|
|
if (_noIFScreen)
|
|
return;
|
|
|
|
if (_logic->_healthOld != _logic->_health) {
|
|
if (_healthTmr > 0)
|
|
_healthTmr--;
|
|
else {
|
|
if (_logic->_health <= _logic->_healthOld)
|
|
_logic->_healthOld--;
|
|
else
|
|
_logic->_healthOld++;
|
|
|
|
int iconIndex;
|
|
if (_logic->_healthOld == 0)
|
|
iconIndex = 12 - 1;
|
|
else
|
|
iconIndex = 12 - _logic->_healthOld;
|
|
|
|
drawIcon(4, 0, iconIndex);
|
|
_healthTmr = 1;
|
|
}
|
|
}
|
|
|
|
if (_iconRedraw) {
|
|
_iconRedraw = false;
|
|
drawIcon(4, 0, 12 - _logic->_healthOld);
|
|
drawIcon(11, 178, _iconPic[0]);
|
|
drawIcon(38, 178, _iconPic[1]);
|
|
drawIcon(65, 178, _iconPic[2]);
|
|
drawIcon(92, 178, _iconPic[3]);
|
|
drawIcon(119, 178, _iconPic[4]);
|
|
drawIcon(146, 178, _iconPic[5]);
|
|
drawIcon(173, 178, _iconPic[6]);
|
|
_treeLeftPic = 0;
|
|
_treeRightPic = 0;
|
|
_treeEyeTimer = 0;
|
|
if (_skylarTimer != 0 || _aTimer != 0) {
|
|
_treeHGTimer = 0;
|
|
_treeHGUPic = 0;
|
|
}
|
|
if (_logic->_tideCntl)
|
|
drawPic(178);
|
|
}
|
|
|
|
for (int i = 0; i < 7; i++) {
|
|
int wrkNodeNum = _logic->_nodeNum;
|
|
if (_tsIconOnly)
|
|
wrkNodeNum = 79;
|
|
if (_logic->_nodeNum == 56 && _logic->_inventory[16] < 1 && _wizard)
|
|
wrkNodeNum = 80;
|
|
if (_logic->_nodeNum == 21 && _logic->_nodes[21] == 9 && !isDemo())
|
|
wrkNodeNum = 81;
|
|
int idx = _iconActTable[wrkNodeNum][i];
|
|
|
|
if (_logic->_inventory[idx] >= 1 && _logic->_nodes[28] != 1 && _logic->_nodes[67] != 1 && !_itemInhibit && !_iconsClosed) {
|
|
if (_iconPic[i] != 12 + idx) {
|
|
if (_iconPic[i] == 89 + i)
|
|
_iconPic[i] = 96 + i;
|
|
else if (_iconPic[i] == 96 + i)
|
|
_iconPic[i] = 31;
|
|
else if (_iconPic[i] == 31)
|
|
_iconPic[i] = 32;
|
|
else if (_iconPic[i] == 32)
|
|
_iconPic[i] = 12 + idx;
|
|
else
|
|
_iconPic[i] = 89 + i;
|
|
}
|
|
} else if (_iconSel != i && _iconPic[i] != 89 + i) {
|
|
if (_iconPic[i] != 12 + idx)
|
|
_iconPic[i] = 32;
|
|
else if (_iconPic[i] == 32)
|
|
_iconPic[i] = 31;
|
|
else if (_iconPic[i] == 31)
|
|
_iconPic[i] = 96 + i;
|
|
else if (_iconPic[i] == 96 + i)
|
|
_iconPic[i] = 32;
|
|
else
|
|
_iconPic[i] = 89 + i;
|
|
} else
|
|
continue;
|
|
|
|
int posX = (27 * i) + 11;
|
|
drawIcon(posX, 178, _iconPic[i]);
|
|
}
|
|
|
|
switch (_treeLeftSta) {
|
|
case 0:
|
|
if (_treeLeftPic != 33) {
|
|
drawIcon(243, 141, 33);
|
|
_treeLeftPic = 33;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (_treeLeftPic != 34) {
|
|
drawIcon(243, 141, 34);
|
|
_treeLeftPic = 34;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (!_logic->_replay) {
|
|
if (_treeLeftPic != 33) {
|
|
drawIcon(243, 141, 33);
|
|
_treeLeftPic = 33;
|
|
}
|
|
} else if (_treeLeftPic != 35) {
|
|
drawIcon(243, 141, 35);
|
|
_treeLeftPic = 35;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (_treeLeftPic != 36) {
|
|
drawIcon(243, 141, 36);
|
|
_treeLeftPic = 36;
|
|
}
|
|
break;
|
|
default:
|
|
_treeLeftPic = 33;
|
|
_treeLeftSta = 0;
|
|
drawIcon(243, 141, 33);
|
|
break;
|
|
}
|
|
|
|
switch (_treeRightSta) {
|
|
case 0:
|
|
if (_treeRightPic == 37) {
|
|
drawIcon(290, 143, 37);
|
|
_treeRightPic = 37;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (_logic->_help) {
|
|
if (_treeRightPic != 38) {
|
|
drawIcon(290, 143, 38);
|
|
_treeRightPic = 38;
|
|
}
|
|
} else if (_treeRightPic != 37) {
|
|
drawIcon(290, 143, 37);
|
|
_treeRightPic = 37;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (_treeRightPic != 39) {
|
|
drawIcon(290, 143, 39);
|
|
_treeRightPic = 39;
|
|
}
|
|
break;
|
|
default:
|
|
_treeRightPic = 37;
|
|
_treeRightSta = 0;
|
|
drawIcon(290, 143, 37);
|
|
break;
|
|
}
|
|
|
|
if (_logic->_eye) {
|
|
if (_treeEyeTimer == 0) {
|
|
_treeEyePic = _teaSeq[_treeEyeSta][0];
|
|
drawIcon(261, 51, _treeEyePic);
|
|
_treeEyeTimer = _teaSeq[_treeEyeSta][1];
|
|
_treeEyeSta++;
|
|
if (_treeEyeSta == 5)
|
|
_treeEyeSta = 0;
|
|
} else
|
|
_treeEyeTimer--;
|
|
} else if (_treeEyePic != 37) {
|
|
drawIcon(261, 51, 146);
|
|
_treeEyePic = 37;
|
|
_treeEyeSta = 0;
|
|
_treeEyeTimer = 0;
|
|
}
|
|
|
|
int timer = 0;
|
|
int delta = 7; // CHECKME: the variable is the same than the one used for the first for(), and the value should therefore be 7
|
|
if (_skylarTimer != 0) {
|
|
delta = 772;
|
|
timer = _skylarTimer;
|
|
}
|
|
if (_aTimer != 0) {
|
|
delta = 19;
|
|
timer = _aTimer;
|
|
}
|
|
|
|
if (timer == 0) {
|
|
if (_treeHGUPic != 147) {
|
|
eraseCursor();
|
|
drawIcon(249, 171, 147);
|
|
_treeHGUPic = 147;
|
|
}
|
|
} else if (_treeHGTimer == 0) {
|
|
_treeHGPic = _hgaSeq[_treeHGSta][0];
|
|
drawIcon(249, 185, _treeHGPic);
|
|
_treeHGTimer = _hgaSeq[_treeHGSta][1];
|
|
_treeHGSta++;
|
|
if (_treeHGSta > 3)
|
|
_treeHGSta = 0;
|
|
|
|
int var2 = 6;
|
|
while (true) {
|
|
if (timer <= 1)
|
|
break;
|
|
|
|
timer -= delta;
|
|
if (timer > 1)
|
|
var2--;
|
|
else {
|
|
drawIcon(249, 171, 40 + var2);
|
|
_treeHGUPic = 40 + var2;
|
|
}
|
|
}
|
|
} else
|
|
_treeHGTimer--;
|
|
}
|
|
|
|
void KingdomGame::switchAtoM() {
|
|
_asMode = true;
|
|
_asMap = _logic->_currMap;
|
|
saveAS();
|
|
_iconSel = 9;
|
|
_oldTLS = _treeLeftSta;
|
|
_oldTRS = _treeRightSta;
|
|
_logic->_oldPouch = _logic->_pouch;
|
|
_logic->_oldHelp = _logic->_help;
|
|
_oldIconsClosed = _iconsClosed;
|
|
_treeLeftSta = 0;
|
|
_treeRightSta = 0;
|
|
_logic->_pouch = false;
|
|
_logic->_help = false;
|
|
_iconsClosed = true;
|
|
}
|
|
|
|
void KingdomGame::switchMtoA() {
|
|
_logic->switchAS();
|
|
fadeToBlack1();
|
|
drawRect(4, 17, 228, 161, 0);
|
|
restoreAS();
|
|
}
|
|
|
|
void KingdomGame::drawIcon(int x, int y, int index) {
|
|
const byte *data = _kingartEntries[index]._data;
|
|
int width = _kingartEntries[index]._width;
|
|
int height = _kingartEntries[index]._height;
|
|
|
|
::Graphics::Surface *screen = g_system->lockScreen();
|
|
for (int curX = 0; curX < width; curX++) {
|
|
for (int curY = 0; curY < height; curY++) {
|
|
const byte *src = data + (curY * width) + curX;
|
|
byte *dst = (byte *)screen->getBasePtr(curX + x, curY + y);
|
|
if (*src != 0xFF)
|
|
*dst = *src;
|
|
}
|
|
}
|
|
g_system->unlockScreen();
|
|
g_system->updateScreen();
|
|
|
|
}
|
|
|
|
int KingdomGame::getAKey() {
|
|
drawCursor();
|
|
|
|
if (_mouseButton == 0) {
|
|
_mouseDebound = false;
|
|
} else if (_mouseDebound == false) {
|
|
_mouseDebound = true;
|
|
return (_mouseButton & 2) ? 2 : 1;
|
|
}
|
|
|
|
int retval = 0;
|
|
Common::Event event;
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_QUIT:
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
_quit = true;
|
|
return 0;
|
|
break;
|
|
case Common::EVENT_KEYDOWN:
|
|
if (!event.kbd.hasFlags(Common::KBD_ALT)) {
|
|
retval = event.kbd.keycode;
|
|
if (event.kbd.hasFlags(Common::KBD_CTRL)) {
|
|
retval += 0x100;
|
|
}
|
|
}
|
|
|
|
// TODO: Reenable ScummVM custom key commands
|
|
|
|
// else if (event.kbd.keycode == Common::KEYCODE_d && event.kbd.hasFlags(Common::KBD_CTRL))
|
|
// _console->attach();
|
|
// else if (event.kbd.keycode == Common::KEYCODE_c && event.kbd.hasFlags(Common::KBD_CTRL)) {
|
|
// _userInput = 0x12D;
|
|
// _QuitFlag = 2;
|
|
// _quit = true;
|
|
// }
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If no keyboard, check timers
|
|
if (retval == 0) {
|
|
refreshSound();
|
|
checkMainScreen();
|
|
if (_aTimerFlag) {
|
|
_aTimerFlag = false;
|
|
retval = 0x2F1;
|
|
} else if (_bTimerFlag) {
|
|
_bTimerFlag = false;
|
|
retval = 0x2F2;
|
|
} else if (_skylarTimerFlag) {
|
|
_skylarTimerFlag = false;
|
|
retval = 0x2F5;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
int KingdomGame::waitKey() {
|
|
return getAKey();
|
|
}
|
|
|
|
void KingdomGame::drawCursor() {
|
|
readMouse();
|
|
|
|
cursorType();
|
|
setCursor(_cursorDef);
|
|
_oldCursorPos = _cursorPos;
|
|
_oldCursorDef = _cursorDef;
|
|
|
|
CursorMan.showMouse(true);
|
|
_cursorDrawn = true;
|
|
}
|
|
|
|
void KingdomGame::cursorType() {
|
|
_mouseValue = 0;
|
|
if (_logic->_currMap != 1 && _logic->_statPlay >= 30) {
|
|
int startId = _logic->_statPlay == 901 ? 16 : 0;
|
|
int hotspotCount = _logic->_statPlay == 901 ? 35 : 16;
|
|
HotSpot *mouseMapMS = isDemo() ? _mouseMapMSDemo : _mouseMapMSFull;
|
|
for (int i = 0; i < hotspotCount + 1; i++) {
|
|
if (i == hotspotCount) {
|
|
int tmpVal = checkMouseMapAS();
|
|
if (tmpVal == -1) {
|
|
cursorTypeExit();
|
|
return;
|
|
} else
|
|
_mouseValue = tmpVal;
|
|
} else if (mouseMapMS[startId + i]._area.contains(_cursorPos)) {
|
|
_mouseValue = mouseMapMS[startId + i]._mouseValue;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
int tmpVal = checkMouseMapAS();
|
|
if (tmpVal == -1) {
|
|
cursorTypeExit();
|
|
return;
|
|
} else {
|
|
_mouseValue = tmpVal;
|
|
}
|
|
}
|
|
|
|
switch(_mouseValue) {
|
|
case 0x18A:
|
|
if (_logic->_eye)
|
|
_mouseValue = !_asMode ? 0x43A : 0x43B;
|
|
else
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x18C:
|
|
if (_treeLeftSta == 1)
|
|
_mouseValue = 0x43D;
|
|
else if (_treeLeftSta == 3)
|
|
_mouseValue = 0x43F;
|
|
else if (_treeLeftSta == 0)
|
|
_mouseValue = 0;
|
|
else if (_treeLeftSta == 2 && _logic->_replay)
|
|
_mouseValue = 0x43E;
|
|
else
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x18D:
|
|
if (_treeRightSta == 1)
|
|
_mouseValue = _logic->_help ? 0x43C : 0;
|
|
if (_treeRightSta == 2)
|
|
_mouseValue = 0x440;
|
|
break;
|
|
case 0x24A:
|
|
// Restore game.
|
|
// No more check in ScummVM, we display the load screen
|
|
break;
|
|
case 0x407:
|
|
if (_logic->_statPlay == 182 && _logic->_nodes[18] < 9)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x40D:
|
|
if (_logic->_nodes[28] == 1)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x41F:
|
|
if (_logic->_nodes[31] == 0)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x422:
|
|
case 0x425:
|
|
if (!_wizard)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x428:
|
|
if (_logic->_nodeNum == 5 && _gameMode != 2 && _logic->_spell1)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x42A:
|
|
if (_logic->_nodeNum == 5 && _gameMode != 2 && _logic->_spell2)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x42B:
|
|
if (_logic->_nodeNum == 5 && _gameMode != 2 && _logic->_spell3)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x445:
|
|
if (_logic->_statPlay == 161 && _logic->_nodes[16] == 0 && _wizard)
|
|
_mouseValue = 0x450;
|
|
break;
|
|
case 0x44F:
|
|
if (!_logic->_pouch)
|
|
_mouseValue = 0;
|
|
break;
|
|
case 0x457:
|
|
if (!_logic->_tideCntl)
|
|
_mouseValue = 0;
|
|
break;
|
|
}
|
|
|
|
_iconSelect = 9;
|
|
for (int var6 = 0; var6 < 8; var6++) {
|
|
if (_mouseValue == 0x181 + var6) {
|
|
int var2 = _logic->_nodeNum;
|
|
if (_tsIconOnly)
|
|
var2 = 79;
|
|
if (_logic->_nodeNum == 56 && _logic->_inventory[8] < 1 && _wizard)
|
|
var2 = 80;
|
|
int indx = _iconActTable[var2][var6];
|
|
if (_logic->_inventory[indx] != 0 && _logic->_nodes[28] != 1 && _logic->_nodes[67] != 1 && !_iconsClosed && !_itemInhibit) {
|
|
_mouseValue = indx + 0x428;
|
|
_iconSelect = var6;
|
|
break;
|
|
}
|
|
_mouseValue = 0;
|
|
}
|
|
}
|
|
|
|
if (_logic->_currMap == 11) {
|
|
if (_mouseValue > 0x427 && _mouseValue < 0x43A) {
|
|
if (_logic->_inventory[_mouseValue - 0x428] < 1)
|
|
_mouseValue = 0x241;
|
|
}
|
|
}
|
|
cursorTypeExit();
|
|
}
|
|
|
|
void KingdomGame::cursorTypeExit() {
|
|
if (_mouseValue >= 0x400)
|
|
_cursorDef = _cursorTable[_mouseValue - 0x400];
|
|
else
|
|
_cursorDef = (_mouseValue != 0) ? 0x68 : 0x67;
|
|
}
|
|
|
|
int KingdomGame::checkMouseMapAS() {
|
|
HotSpot *curSceneHotspots;
|
|
if (isDemo())
|
|
curSceneHotspots = _mouseMapASDemo[_logic->_currMap];
|
|
else
|
|
curSceneHotspots = _mouseMapASFull[_logic->_currMap];
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
if (curSceneHotspots[i]._area.contains(_cursorPos))
|
|
return curSceneHotspots[i]._mouseValue;
|
|
}
|
|
|
|
if (_logic->_currMap != 11)
|
|
return -1;
|
|
|
|
if (isDemo())
|
|
curSceneHotspots = _mouseMapASDemo[12];
|
|
else
|
|
curSceneHotspots = _mouseMapASFull[12];
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
if (curSceneHotspots[i]._area.contains(_cursorPos))
|
|
return curSceneHotspots[i]._mouseValue;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void KingdomGame::displayDebugHotSpots() {
|
|
if (!_showHotspots)
|
|
return;
|
|
|
|
if (_logic->_currMap != 1 && _logic->_statPlay >= 30) {
|
|
int startId = _logic->_statPlay == 901 ? 16 : 0;
|
|
int hotspotCount = _logic->_statPlay == 901 ? 35 : 16;
|
|
HotSpot *mouseMapMS = isDemo() ? _mouseMapMSDemo : _mouseMapMSFull;
|
|
for (int i = 0; i < hotspotCount; i++) {
|
|
if (mouseMapMS[startId + i]._area != Common::Rect(0, 0, 0, 0))
|
|
drawEmptyRect(mouseMapMS[startId + i]._area, 0xDF);
|
|
}
|
|
}
|
|
|
|
HotSpot *curSceneHotspots;
|
|
if (isDemo())
|
|
curSceneHotspots = _mouseMapASDemo[_logic->_currMap];
|
|
else
|
|
curSceneHotspots = _mouseMapASFull[_logic->_currMap];
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
if (curSceneHotspots[i]._area != Common::Rect(0,0,0,0))
|
|
drawEmptyRect(curSceneHotspots[i]._area, 0xFF);
|
|
}
|
|
|
|
if (_logic->_currMap != 11)
|
|
return;
|
|
|
|
if (isDemo())
|
|
curSceneHotspots = _mouseMapASDemo[12];
|
|
else
|
|
curSceneHotspots = _mouseMapASFull[12];
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
if (curSceneHotspots[i]._area != Common::Rect(0, 0, 0, 0))
|
|
drawEmptyRect(curSceneHotspots[i]._area, 0xFF);
|
|
}
|
|
}
|
|
|
|
void KingdomGame::setCursor(int cursor) {
|
|
KingArtEntry Cursor = _kingartEntries[cursor];
|
|
CursorMan.replaceCursor(Cursor._data, Cursor._width, Cursor._height, 0, 0, 255);
|
|
}
|
|
|
|
} // End of namespace Kingdom
|