Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

2
engines/griffon/POTFILES Normal file
View File

@@ -0,0 +1,2 @@
engines/griffon/griffon.cpp
engines/griffon/metaengine.cpp

1032
engines/griffon/combat.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
add_engine griffon "The Griffon Legend" yes "" "" "16bit"

View File

@@ -0,0 +1,66 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "gui/debugger.h"
#include "griffon/console.h"
namespace Griffon {
Console::Console() {
_godMode = kGodModeNone;
registerCmd("godmode", WRAP_METHOD(Console, Cmd_godMode));
registerCmd("nodamage", WRAP_METHOD(Console, Cmd_noDamage));
}
bool Console::Cmd_godMode(int argc, const char** argv) {
if (argc != 1) {
debugPrintf("Usage: %s\n", argv[0]);
debugPrintf("Enables/Disables invincibility and megadamage\n");
return true;
}
if (_godMode != kGodModeNone)
_godMode = kGodModeNone;
else
_godMode = kGodModeAll;
debugPrintf("God mode is now %s\n", _godMode == kGodModeAll ? "Invincibility/Damage" : "Disabled");
return true;
}
bool Console::Cmd_noDamage(int argc, const char** argv) {
if (argc != 1) {
debugPrintf("Usage: %s\n", argv[0]);
debugPrintf("Enables/Disables invincibility\n");
return true;
}
if (_godMode != kGodModeNone)
_godMode = kGodModeNone;
else
_godMode = kGodModeNoDamage;
debugPrintf("God mode is now %s\n", _godMode ? "Invincibility" : "Disabled");
return true;
}
} // End of namespace Griffon

47
engines/griffon/console.h Normal file
View File

@@ -0,0 +1,47 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef GRIFFON_CONSOLE_H
#define GRIFFON_CONSOLE_H
#include "gui/debugger.h"
namespace Griffon {
enum {
kGodModeNone = 0,
kGodModeAll = 1,
kGodModeNoDamage = 2
};
class Console : public GUI::Debugger {
public:
int _godMode;
explicit Console();
~Console(void) override {}
bool Cmd_godMode(int argc, const char** argv);
bool Cmd_noDamage(int argc, const char** argv);
};
}
#endif

View File

@@ -0,0 +1,3 @@
begin_section("Griffon");
add_person("Eugene Sandulenko", "sev", "");
end_section();

View File

@@ -0,0 +1,601 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "common/system.h"
#include "griffon/griffon.h"
#include "common/config-manager.h"
#include "common/text-to-speech.h"
namespace Griffon {
#define POLL_AND_CHECK_QUIT() if (g_system->getEventManager()->pollEvent(_event)) { \
if (_event.type == Common::EVENT_QUIT || _event.type == Common::EVENT_RETURN_TO_LAUNCHER) { \
_shouldQuit = true; \
return; \
} \
}
#define CHECK_QUIT() if (_event.type == Common::EVENT_QUIT || _event.type == Common::EVENT_RETURN_TO_LAUNCHER) { \
_shouldQuit = true; \
return; \
}
const char *story[48] = {
"The Griffon Legend",
"http://syn9.thehideoutgames.com/",
"",
"Programming/Graphics: Daniel Kennedy",
"Music/Sound effects: David Turner",
"",
"Porting to GCW-Zero: Dmitry Smagin",
"",
"",
"Story",
"Ever since I was a child",
"I remember being told the",
"Legend of the Griffon Knights,",
"who rid the world of the",
"Dragon Empire. These great",
"heroes inspired us to become",
"knights as well.",
" ",
"Now, 500 years after the war",
"ended, the Dragons have",
"returned. Cities are falling",
"from the lack of knights to",
"protect them.",
" ",
"We never saw it coming.",
" ",
"And now, here I am, making",
"my way into the lower town",
"of Fidelis, a small city on",
"the main continent. The rest",
"of my men have died over",
"the last couple days from",
"aerial attacks.",
" ",
"We believed we could find",
"shelter here, only to find",
"every last griffon dead,",
"the town burned to the ground,",
"and transformed into a garrison",
"for the Dragon forces.",
" ",
"In these dark times, I try to",
"draw strength from the stories",
"of those knights that risked",
"everything to protect their homeland,",
" ",
"and hope that I can die",
"with that honor as well."
};
const char *story2[27] = {
"After the fall of Margrave Gradius,",
"All the dragons, struck with panic,",
"evacuated the city immediately.",
" ",
"It\'s funny how without a leader",
"everyone is so weak.",
" ",
" ",
"But yet another leader will rise,",
"and another city will fall.",
" ",
" ",
"I should return home to Asherton",
"It\'s time to leave this place",
"and cleanse this blood stained",
"life of mine.",
" ",
"No one should have to see as much",
"death as I have.",
" ",
" ",
"Before, I said that I wanted",
"to die an honorable death.",
" ",
"Now I say that I have lived an",
"honorable life,",
"and I am free to die as I please."
};
int textToSpeech(int nextparagraph, const char *storyVariable[], int arraysize) {
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled") && storyVariable[nextparagraph][0] != 0) {
Common::String paragraph;
while (nextparagraph < arraysize && storyVariable[nextparagraph][0] != ' ') {
if (!paragraph.empty())
paragraph += " ";
paragraph += storyVariable[nextparagraph++];
}
while (nextparagraph < arraysize && storyVariable[nextparagraph][0] == ' ') {
nextparagraph += 1;
}
ttsMan->say(paragraph, Common::TextToSpeechManager::QUEUE_NO_REPEAT);
}
return nextparagraph;
}
void GriffonEngine::showLogos() {
_ticks = g_system->getMillis();
int ticks1 = _ticks;
do {
float y = 255.0;
if (_ticks < ticks1 + 1000) {
y = 255.0 * ((float)(_ticks - ticks1) / 1000.0);
y = CLIP<float>(y, 0.0, 255.0);
}
if (_ticks > ticks1 + 3000) {
y = 255.0 - 255.0 * ((float)(_ticks - ticks1 - 3000.0) / 1000.0);
y = CLIP<float>(y, 0.0, 255.0);
}
_videoBuffer->fillRect(Common::Rect(0, 0, 320, 240), 0);
_logosImg->blendBlitTo(*_videoBuffer, 0, 0, Graphics::FLIP_NONE, nullptr, MS_ARGB((int)y, (int)y, (int)y, (int)y));
g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
g_system->updateScreen();
if (g_system->getEventManager()->pollEvent(_event)) {
if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START && _event.customType == kGriffonMenu)
return;
CHECK_QUIT();
}
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
g_system->delayMillis(10);
if (_ticks > ticks1 + 4000)
break;
} while (!_shouldQuit);
}
void GriffonEngine::intro() {
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
_videoBuffer3->fillRect(Common::Rect(0, 0, _videoBuffer3->w, _videoBuffer3->h), 0);
_ticks = g_system->getMillis();
_videoBuffer->blendBlitTo(*_videoBuffer3);
_videoBuffer->blendBlitTo(*_videoBuffer2);
_fpsr = 0.0;
int y = 140;
if (config.music) {
haltSoundChannel(-1);
_musicChannel = playSound(_musicEndOfGame, true);
setChannelVolume(_musicChannel, 0);
}
_secsInGame = 0;
_secStart = 0;
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
bool ldStop = false;
bool speedUp = false;
int cnt = 0;
float xofs = 0.0;
float ld = 0.0;
int nextparagraph = 0;
do {
Common::Rect rc;
ld += 4 * _fpsr;
if ((int)ld > config.musicVol)
ld = config.musicVol;
if (!ldStop) {
setChannelVolume(_musicChannel, (int)ld);
if ((int)ld == config.musicVol)
ldStop = true;
}
rc.left = -xofs;
rc.top = 0;
_titleImg->blendBlitTo(*_videoBuffer, rc.left, rc.top);
rc.left = -xofs + 320;
rc.top = 0;
_titleImg->blendBlitTo(*_videoBuffer, rc.left, rc.top);
if (++cnt >= 6) {
cnt = 0;
y--;
}
for (int i = 0; i < ARRAYSIZE(story); i++) {
int yy = y + i * 10;
if (i == nextparagraph)
nextparagraph = textToSpeech(nextparagraph, story, ARRAYSIZE(story));
if (yy > -8 && yy < 240) {
int x = 160 - strlen(story[i]) * 4;
drawString(_videoBuffer, story[i], x, yy, 4);
}
if (yy < 10 && i == ARRAYSIZE(story) - 1) {
if (ttsMan == nullptr || ttsMan->isSpeaking() == false)
return;
}
}
g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
g_system->updateScreen();
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24.0;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
float add = 0.5 * _fpsr;
if (add > 1)
add = 1;
xofs += add;
if (xofs >= 320)
xofs -= 320;
if (g_system->getEventManager()->pollEvent(_event)) {
if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
if (_event.customType == kGriffonCutsceneSpeedUp) {
speedUp = true;
cnt = 6;
}
else if (_event.customType == kGriffonMenu) {
if (ttsMan != nullptr)
ttsMan->stop();
return;
}
} else if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_END) {
if (_event.customType == kGriffonCutsceneSpeedUp) {
speedUp = false;
}
}
CHECK_QUIT();
} else if (speedUp)
cnt = 6;
g_system->delayMillis(10);
} while (!_shouldQuit);
}
void GriffonEngine::endOfGame() {
float xofs = 0;
_ticks = g_system->getMillis();
float spd = 0.2f;
if (config.music) {
haltSoundChannel(-1);
_musicChannel = playSound(_musicEndOfGame, true);
setChannelVolume(_musicChannel, 0);
}
int ticks1 = _ticks;
int ya = 0;
float ld = 0;
bool ldstop = false; // CHECKME: Check if actually used
int nextparagraph = 0;
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
do {
ld += 4 * _fpsr;
if (ld > config.musicVol)
ld = config.musicVol;
if (!ldstop) {
setChannelVolume(_musicChannel, (int)ld);
if ((int)ld == config.musicVol)
ldstop = true;
}
ya = 0;
if (_ticks < ticks1 + 1500) {
ya = (255 * (_ticks - ticks1)) / 1500;
ya = CLIP(ya, 0, 255);
} else
break;
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
_videoBuffer->surfacePtr()->setAlpha(255 - ya);
_videoBuffer->blendBlitTo(*_videoBuffer2);
g_system->copyRectToScreen(_videoBuffer2->getPixels(), _videoBuffer2->pitch, 0, 0, _videoBuffer2->w, _videoBuffer2->h);
POLL_AND_CHECK_QUIT();
g_system->updateScreen();
g_system->delayMillis(10);
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
} while (1);
ticks1 = _ticks;
ya = 0;
float y = 140;
do {
Common::Rect rc;
rc.left = -xofs;
rc.top = 0;
_titleImg->blendBlitTo(*_videoBuffer, rc.left, rc.top);
rc.left = -xofs + 320;
rc.top = 0;
_titleImg->blendBlitTo(*_videoBuffer, rc.left, rc.top);
y = y - spd * _fpsr;
for (int i = 0; i < ARRAYSIZE(story2); i++) {
int yy = y + i * 10;
if (i == nextparagraph)
nextparagraph = textToSpeech(nextparagraph, story2, ARRAYSIZE(story2));
if (yy > -8 && yy < 240) {
int x = 160 - strlen(story2[i]) * 4;
drawString(_videoBuffer, story2[i], x, yy, 4);
}
if (yy < 10 && i == ARRAYSIZE(story2)-1) {
if (ttsMan == nullptr || ttsMan->isSpeaking() == false)
break;
}
}
ya = 255;
if (_ticks < ticks1 + 1000) {
ya = 255 * (_ticks - ticks1) / 1000;
ya = CLIP(ya, 0, 255);
}
_videoBuffer->surfacePtr()->setAlpha(ya);
g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
float add = 0.5 * _fpsr;
if (add > 1)
add = 1;
xofs += add;
if (xofs >= 320)
xofs -= 320;
if (g_system->getEventManager()->pollEvent(_event)) {
if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
if (_event.customType == kGriffonCutsceneSpeedUp)
spd = 1.0f;
else if (_event.customType == kGriffonMenu) {
if (ttsMan != nullptr)
ttsMan->stop();
break;
}
} else if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_END) {
if (_event.customType == kGriffonCutsceneSpeedUp)
spd = 0.2f;
}
CHECK_QUIT();
}
g_system->updateScreen();
g_system->delayMillis(10);
} while (1);
ticks1 = _ticks;
int y1 = 0;
_videoBuffer2->copyRectToSurface(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
do {
if (_ticks < ticks1 + 1500) {
y1 = 255 * (_ticks - ticks1) / 1500;
y1 = CLIP(y1, 0, 255);
} else
break;
_videoBuffer->fillRect(Common::Rect(0, 0, _videoBuffer->w, _videoBuffer->h), 0);
_videoBuffer->surfacePtr()->setAlpha(y1);
_videoBuffer2->blendBlitTo(*_videoBuffer3);
_videoBuffer->blendBlitTo(*_videoBuffer3);
g_system->copyRectToScreen(_videoBuffer3->getPixels(), _videoBuffer3->pitch, 0, 0, _videoBuffer3->w, _videoBuffer3->h);
g_system->updateScreen();
POLL_AND_CHECK_QUIT();
g_system->delayMillis(10);
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
} while (1);
int keywait = 2000 + _ticks;
ticks1 = _ticks;
y1 = 0;
do {
_videoBuffer->copyRectToSurface(_theEndImg->getPixels(), _theEndImg->pitch, 0, 0, _theEndImg->w, _theEndImg->h);
y1 = 255;
if (_ticks < ticks1 + 1000) {
y1 = 255 * (_ticks - ticks1) / 1000;
y1 = CLIP(y1, 0, 255);
}
_videoBuffer->surfacePtr()->setAlpha(y1);
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
_videoBuffer->blendBlitTo(*_videoBuffer2);
g_system->copyRectToScreen(_videoBuffer2->getPixels(), _videoBuffer2->pitch, 0, 0, _videoBuffer2->w, _videoBuffer2->h);
g_system->updateScreen();
g_system->delayMillis(10);
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
if (g_system->getEventManager()->pollEvent(_event)) {
CHECK_QUIT();
if ((_event.type == Common::EVENT_KEYDOWN || _event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) && keywait < _ticks)
break;
}
} while (1);
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
_videoBuffer3->fillRect(Common::Rect(0, 0, _videoBuffer3->w, _videoBuffer3->h), 0);
theEnd();
}
void GriffonEngine::theEnd() {
for (int i = 0; i < kMaxFloat; i++) {
_floatText[i].framesLeft = 0;
_floatIcon[i].framesLeft = 0;
}
for (float y = 0; y < 100; y += _fpsr) {
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
_videoBuffer->surfacePtr()->setAlpha((int)((100.0 - y) / 100 * 255));
_videoBuffer->blendBlitTo(*_videoBuffer2);
g_system->copyRectToScreen(_videoBuffer2->getPixels(), _videoBuffer2->pitch, 0, 0, _videoBuffer2->w, _videoBuffer2->h);
g_system->updateScreen();
POLL_AND_CHECK_QUIT();
g_system->delayMillis(10);
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24.0;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
}
}
} // end of namespace Griffon

View File

@@ -0,0 +1,74 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "base/plugins.h"
#include "engines/advancedDetector.h"
#include "common/text-to-speech.h"
#include "griffon/detection.h"
static const PlainGameDescriptor griffonGames[] = {
{"griffon", "The Griffon Legend"},
{nullptr, nullptr}
};
namespace Griffon {
static const ADGameDescription gameDescriptions[] = {
{
"griffon",
nullptr,
AD_ENTRY1s("objectdb.dat", "ec5371da28f01ccf88980b32d9de2232", 27754),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_DROPPLATFORM,
#ifdef USE_TTS
GUIO2(GUIO_NOMIDI, GAMEOPTION_TTS_NARRATOR)
#else
GUIO1(GUIO_NOMIDI)
#endif
},
AD_TABLE_END_MARKER
};
}
class GriffonMetaEngineDetection: public AdvancedMetaEngineDetection<ADGameDescription> {
public:
GriffonMetaEngineDetection() : AdvancedMetaEngineDetection(Griffon::gameDescriptions, griffonGames) {
}
const char *getName() const override {
return "griffon";
}
const char *getEngineName() const override {
return "Griffon Engine";
}
const char *getOriginalCopyright() const override {
return "The Griffon Legend (c) 2005 Syn9 (Daniel Kennedy)";
}
};
REGISTER_PLUGIN_STATIC(GRIFFON_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, GriffonMetaEngineDetection);

View File

@@ -0,0 +1,27 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef GRIFFON_DETECTION_H
#define GRIFFON_DETECTION_H
#define GAMEOPTION_TTS_NARRATOR GUIO_GAMEOPTIONS1
#endif

874
engines/griffon/dialogs.cpp Normal file
View File

@@ -0,0 +1,874 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "common/system.h"
#include "common/config-manager.h"
#include "griffon/griffon.h"
#include "common/text-to-speech.h"
namespace Griffon {
#define MINCURSEL 7
#define MAXCURSEL 16
#define SY 25
void GriffonEngine::title(int mode) {
const char *optionTitles[4] = {
"new game/save/load",
"options",
"quit game",
"return"
};
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
float xofs = 0;
_itemyloc = 0;
bool exitTitle = false;
rcSrc.left = 0;
rcSrc.top = 0;
rcSrc.setWidth(320);
rcSrc.setHeight(240);
_videoBuffer2->fillRect(rcSrc, 0);
_videoBuffer3->fillRect(rcSrc, 0);
_ticks = g_system->getMillis();
_videoBuffer->blendBlitTo(*_videoBuffer3);
_videoBuffer->blendBlitTo(*_videoBuffer2);
int cursel = 0;
int ticks1 = _ticks;
if (config.music) {
setChannelVolume(_musicChannel, 0);
pauseSoundChannel(_musicChannel);
_menuChannel = playSound(_musicMenu, true);
setChannelVolume(_menuChannel, config.musicVol);
_pmenu = true;
}
bool ldstop = false;
float ld = 0;
do {
Common::Rect rc;
ld += 4.0 * _fpsr;
if (ld > config.musicVol)
ld = config.musicVol;
if (!ldstop) {
setChannelVolume(_menuChannel, (int)ld);
if ((int)ld == config.musicVol)
ldstop = true;
}
rc.left = -xofs;
rc.top = 0;
_titleImg->blendBlitTo(*_videoBuffer, rc.left, rc.top);
rc.left = -xofs + 320.0;
rc.top = 0;
_titleImg->blendBlitTo(*_videoBuffer, rc.left, rc.top);
rc.left = 0;
rc.top = 0;
_titleImg2->blendBlitTo(*_videoBuffer, rc.left, rc.top);
int y = 172;
int x = 160 - 14 * 4;
drawString(_videoBuffer, optionTitles[0], x, y, 4);
drawString(_videoBuffer, optionTitles[1], x, y + 16, 4);
drawString(_videoBuffer, optionTitles[2], x, y + 32, 4);
if (mode == 1)
drawString(_videoBuffer, optionTitles[3], x, y + 48, 4);
else
drawString(_videoBuffer, "(c) 2005 by Daniel 'Syn9' Kennedy", 28, 224, 4);
rc.left = (int16)(x - 16 - 4 * cos(2 * M_PI * _itemyloc / 16));
rc.top = (int16)(y - 4 + 16 * cursel);
_itemImg[15]->blendBlitTo(*_videoBuffer, rc.left, rc.top);
float yf = 255.0;
if (_ticks < ticks1 + 1000) {
yf = 255.0 * ((float)(_ticks - ticks1) / 1000.0);
yf = CLIP<float>(yf, 0.0, 255.0);
}
_videoBuffer->surfacePtr()->setAlpha((int)yf);
g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
g_system->updateScreen();
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24.0;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
float add = 0.5 * _fpsr;
if (add > 1)
add = 1;
xofs += add;
if (xofs >= 320.0)
xofs -= 320.0;
_itemyloc += 0.75 * _fpsr;
while (_itemyloc >= 16)
_itemyloc = _itemyloc - 16;
if (g_system->getEventManager()->pollEvent(_event)) {
if (_event.type == Common::EVENT_QUIT || _event.type == Common::EVENT_RETURN_TO_LAUNCHER)
_shouldQuit = true;
if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
switch(_event.customType) {
case kGriffonMenu:
if (mode == 1)
exitTitle = true;
break;
case kGriffonUp:
cursel--;
if (cursel < 0)
cursel = (mode == 1 ? 3 : 2);
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan->say(optionTitles[cursel]);
break;
case kGriffonDown:
cursel++;
if (cursel >= (mode == 1 ? 4 : 3))
cursel = 0;
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan->say(optionTitles[cursel]);
break;
case kGriffonConfirm:
if (ttsMan != nullptr)
ttsMan->stop();
switch(cursel) {
case 0:
_ticks = g_system->getMillis();
ticks1 = _ticks;
saveLoadNew();
if (_gameMode == kGameModeNewGame || _gameMode == kGameModeLoadGame) {
exitTitle = true;
}
break;
case 1:
configMenu();
_ticks = g_system->getMillis();
ticks1 = _ticks;
break;
case 2:
_shouldQuit = true;
break;
case 3:
exitTitle = true;
default:
break;
}
break;
default:
break;
}
}
}
g_system->delayMillis(10);
} while (!_shouldQuit && !exitTitle && _gameMode != kGameModeNewGame && _gameMode != kGameModeLoadGame);
_itemTicks = _ticks + 210;
if (config.music) {
haltSoundChannel(_menuChannel);
resumeSoundChannel(_musicChannel);
setChannelVolume(_musicChannel, config.musicVol);
_pmenu = false;
}
}
static Common::String formatPercent(int val) {
val = val / 2.55;
return Common::String::format("%d percent", val - val % 10);
}
static void speakMenuItem(int mapTitles, int mapValues, const char *mapTitleText[], const char *mapValueText[]) {
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled")) {
Common::TextToSpeechManager::Action valueAction = Common::TextToSpeechManager::INTERRUPT;
if (mapTitles != 0) {
ttsMan->say(mapTitleText[mapTitles]);
valueAction = Common::TextToSpeechManager::QUEUE;
}
if (mapValues != 0)
ttsMan->say(mapValueText[mapValues], valueAction);
}
}
void GriffonEngine::configMenu() {
static const char *optionTitles[25] = {
"", "",
"", "", "", "",
"", "", "",
"Music:", "", "",
"Sound Effects:", "", "",
"Text to Speech:", "", "",
"Music Volume:", "",
"Effects Volume:", "", "", "", ""
};
static const char *optionValues[25] = {
"", "",
"", "", "", "",
"", "", "",
"On", "Off", "",
"On", "Off", "",
"On", "Off", "",
"[----------]", "",
"[----------]", "",
"Exit + Save", "",
"Exit"
};
static const int curselMapTitles[MAXCURSEL+1] = {
0, 0, 0, 0, 0,
0, 0, 9, 9, 12,
12, 15, 15, 18, 20,
0, 0
};
static const int curselMapValues[MAXCURSEL+1] = {
0, 0, 0, 0, 0,
0, 0, 9, 10, 12,
13, 15, 16, 0, 0,
22, 24
};
int cursel = MINCURSEL;
bool exitMenu = false;
_ticks = g_system->getMillis();
Graphics::ManagedSurface *configwindow = loadImage("art/configwindow.bmp", true);
configwindow->surfacePtr()->setAlpha(160, true);
int ticks1 = _ticks;
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
do {
_videoBuffer->fillRect(Common::Rect(0, 0, _videoBuffer->w, _videoBuffer->h), 0);
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
rcDest.left = 256 + 256 * cos(M_PI / 180 * _cloudAngle * 40);
rcDest.top = 192 + 192 * sin(M_PI / 180 * _cloudAngle * 40);
rcDest.setWidth(320);
rcDest.setHeight(240);
_cloudImg->blendBlitTo(*_videoBuffer, 0, 0, Graphics::FLIP_NONE, &rcDest, MS_ARGB(128, 255, 255, 255));
rcDest.left = 256;
rcDest.top = 192;
rcDest.setWidth(320);
rcDest.setHeight(240);
_cloudImg->blendBlitTo(*_videoBuffer, 0, 0, Graphics::FLIP_NONE, &rcDest, MS_ARGB(128, 255, 255, 255));
configwindow->blendBlitTo(*_videoBuffer);
int sy = SY;
for (int i = 0; i <= 24; i++) {
static char line[24];
int destColumn = 3;
if (i == 9 && config.music)
destColumn = 0;
else if (i == 10 && !config.music)
destColumn = 0;
else if (i == 12 && config.effects)
destColumn = 0;
else if (i == 13 && !config.effects)
destColumn = 0;
else if (i == 15 && ConfMan.getBool("tts_enabled"))
destColumn = 0;
else if (i == 16 && !ConfMan.getBool("tts_enabled"))
destColumn = 0;
else if (i == 18|| i == 20) {
int vol = (i ==18 ? config.musicVol : config.effectsVol) * 9 / 255;
vol = CLIP(vol, 0, 9);
Common::strcpy_s(line, "[----------]");
line[vol + 1] = 'X';
optionValues[i] = line;
} else if (i > 21)
destColumn = 0;
drawString(_videoBuffer, optionTitles[i], 156 - 8 * strlen(optionTitles[i]), sy + i * 8, 0);
drawString(_videoBuffer, optionValues[i], 164, sy + i * 8, destColumn);
}
int curselt = cursel + 2;
if (cursel > 8)
curselt += 1;
if (cursel > 10)
curselt += 1;
if (cursel > 12)
curselt += 1;
if (cursel > 13)
curselt += 1;
if (cursel > 14)
curselt += 1;
if (cursel > 15)
curselt += 1;
Common::Rect rc;
rc.left = 148 + 3 * cos(2 * M_PI * _itemyloc / 16.0);
rc.top = sy + 8 * curselt - 4;
_itemImg[15]->blendBlitTo(*_videoBuffer, rc.left, rc.top);
if (_ticks < ticks1 + 1000) {
float yy = 255.0 * ((float)(_ticks - ticks1) / 1000.0);
yy = CLIP<float>(yy, 0.0, 255.0);
_videoBuffer->surfacePtr()->setAlpha((uint8)yy);
}
_videoBuffer->blendBlitTo(*_videoBuffer2);
g_system->copyRectToScreen(_videoBuffer2->getPixels(), _videoBuffer2->pitch, 0, 0, _videoBuffer2->w, _videoBuffer2->h);
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
_itemyloc += 0.75 * _fpsr;
while (_itemyloc >= 16)
_itemyloc -= 16;
while (g_system->getEventManager()->pollEvent(_event)) {
switch (_event.type) {
case Common::EVENT_QUIT:
case Common::EVENT_RETURN_TO_LAUNCHER:
_shouldQuit = true;
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
switch (_event.customType) {
case kGriffonMenu:
exitMenu = true;
break;
case kGriffonLeft:
if (cursel == 13) {
config.musicVol = CLIP(config.musicVol - 25, 0, 255);
setChannelVolume(_musicChannel, config.musicVol);
setChannelVolume(_menuChannel, config.musicVol);
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan->say(formatPercent(config.musicVol));
} else if (cursel == 14) {
config.effectsVol = CLIP(config.effectsVol - 25, 0, 255);
setChannelVolume(-1, config.effectsVol);
setChannelVolume(_musicChannel, config.musicVol);
setChannelVolume(_menuChannel, config.musicVol);
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan->say(formatPercent(config.effectsVol));
if (config.effects) {
int snd = playSound(_sfx[kSndDoor]);
setChannelVolume(snd, config.effectsVol);
}
}
break;
case kGriffonRight:
if (cursel == 13) {
config.musicVol = CLIP(config.musicVol + 25, 0, 255);
setChannelVolume(_musicChannel, config.musicVol);
setChannelVolume(_menuChannel, config.musicVol);
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan->say(formatPercent(config.musicVol));
} else if (cursel == 14) {
config.effectsVol = CLIP(config.effectsVol + 25, 0, 255);
setChannelVolume(-1, config.effectsVol);
setChannelVolume(_musicChannel, config.musicVol);
setChannelVolume(_menuChannel, config.musicVol);
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan->say(formatPercent(config.effectsVol));
if (config.effects) {
int snd = playSound(_sfx[kSndDoor]);
setChannelVolume(snd, config.effectsVol);
}
}
break;
case kGriffonUp:
cursel--;
if (cursel < MINCURSEL)
cursel = MAXCURSEL;
speakMenuItem(curselMapTitles[cursel], curselMapValues[cursel], optionTitles, optionValues);
break;
case kGriffonDown:
++cursel;
if (cursel > MAXCURSEL)
cursel = MINCURSEL;
speakMenuItem(curselMapTitles[cursel], curselMapValues[cursel], optionTitles, optionValues);
break;
case kGriffonConfirm:
switch (cursel) {
case 7:
if (!config.music) {
config.music = true;
_menuChannel = playSound(_musicMenu, true);
setChannelVolume(_menuChannel, config.musicVol);
}
break;
case 8:
if (config.music) {
config.music = false;
haltSoundChannel(_musicChannel);
haltSoundChannel(_menuChannel);
}
break;
case 9:
if (!config.effects) {
config.effects = true;
int snd = playSound(_sfx[kSndDoor]);
setChannelVolume(snd, config.effectsVol);
}
break;
case 10:
if (config.effects)
config.effects = false;
break;
case 11:
if (!ConfMan.getBool("tts_enabled")) {
ConfMan.setBool("tts_enabled", true);
}
break;
case 12:
if (ConfMan.getBool("tts_enabled")) {
ConfMan.setBool("tts_enabled", false);
}
break;
case 15:
saveConfig();
// fall through
case 16:
if (ttsMan != nullptr)
ttsMan->stop();
exitMenu = true;
break;
default:
break;
}
break;
default:
break;
}
default:
break;
}
}
_cloudAngle += 0.01 * _fpsr;
while (_cloudAngle >= 360)
_cloudAngle -= 360;
g_system->updateScreen();
g_system->delayMillis(10);
} while (!_shouldQuit && !exitMenu && _gameMode != kGameModeNewGame && _gameMode != kGameModeLoadGame);
configwindow->free();
_itemTicks = _ticks + 210;
}
void GriffonEngine::renderSaveStates() {
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
for (int ff = 0; ff <= 3; ff++) {
loadPlayer(ff);
if (_playera.level > 0) {
int sx = 8;
int sy = 57 + ff * 48;
// time
int ase = _asecstart;
int h = ((ase - (ase % 3600)) / 3600);
ase = (ase - h * 3600);
int m = ((ase - (ase % 60)) / 60);
int s = (ase - m * 60);
char line[256];
Common::sprintf_s(line, "Game Time: %02i:%02i:%02i", h, m, s);
drawString(_videoBuffer2, line, 160 - strlen(line) * 4, sy, 0);
sx = 12;
sy += 11;
int cc = 0;
Common::sprintf_s(line, "Health: %i/%i", _playera.hp, _playera.maxHp);
drawString(_videoBuffer2, line, sx, sy, cc);
if (_playera.level == 22)
Common::strcpy_s(line, "Level: MAX");
else
Common::sprintf_s(line, "Level: %i", _playera.level);
drawString(_videoBuffer2, line, sx, sy + 11, 0);
rcSrc.left = sx + 15 * 8 + 24;
rcSrc.top = sy + 1;
int ss = (_playera.sword - 1) * 3;
if (_playera.sword == 3)
ss = 18;
_itemImg[ss]->blendBlitTo(*_videoBuffer2, rcSrc.left, rcSrc.top);
rcSrc.left += 16;
ss = (_playera.shield - 1) * 3 + 1;
if (_playera.shield == 3)
ss = 19;
_itemImg[ss]->blendBlitTo(*_videoBuffer2, rcSrc.left, rcSrc.top);
rcSrc.left += 16;
ss = (_playera.armour - 1) * 3 + 2;
if (_playera.armour == 3)
ss = 20;
_itemImg[ss]->blendBlitTo(*_videoBuffer2, rcSrc.left, rcSrc.top);
int nx = rcSrc.left + 13 + 3 * 8;
rcSrc.left = nx - 17;
if (_playera.foundSpell[0]) {
for (int i = 0; i < 5; i++) {
rcSrc.left += 17;
if (_playera.foundSpell[i])
_itemImg[7 + i]->blendBlitTo(*_videoBuffer2, rcSrc.left, rcSrc.top);
}
}
} else {
int sy = 57 + ff * 48;
drawString(_videoBuffer2, "Empty", 160 - 5 * 4, sy, 0);
}
}
}
void GriffonEngine::saveLoadNew() {
const char *optionTitles[4] = {
"new game", "", "load", "return",
};
_cloudAngle = 0;
int curRow = 0;
int curCol = 0;
bool lowerLock = false;
_ticks = g_system->getMillis();
int ticks1 = _ticks;
int tickPause = _ticks + 150;
renderSaveStates();
delete _saveLoadImg;
_saveLoadImg = loadImage("art/saveloadnew.bmp", true);
if (_gameMode == kGameModeIntro) {
uint32 color = *(uint32 *)_saveLoadImg->getBasePtr(120, 10);
_saveLoadImg->fillRect(Common::Rect(125, 15, 160, 33), color);
}
_saveLoadImg->surfacePtr()->setAlpha(192, true);
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
// Main menu loop
do {
_videoBuffer->fillRect(Common::Rect(0, 0, _videoBuffer->w, _videoBuffer->h), 0);
rcDest.left = 256 + 256 * cos(M_PI / 180 * _cloudAngle * 40);
rcDest.top = 192 + 192 * sin(M_PI / 180 * _cloudAngle * 40);
rcDest.setWidth(320);
rcDest.setHeight(240);
_cloudImg->blendBlitTo(*_videoBuffer, 0, 0, Graphics::FLIP_NONE, &rcDest, MS_ARGB(128, 255, 255, 255));
rcDest.left = 256;
rcDest.top = 192;
rcDest.setWidth(320);
rcDest.setHeight(240);
_cloudImg->blendBlitTo(*_videoBuffer, 0, 0, Graphics::FLIP_NONE, &rcDest, MS_ARGB(128, 255, 255, 255));
_saveLoadImg->blendBlitTo(*_videoBuffer);
if (g_system->getEventManager()->pollEvent(_event)) {
if (_event.type == Common::EVENT_QUIT || _event.type == Common::EVENT_RETURN_TO_LAUNCHER) {
_shouldQuit = true;
return;
}
if (tickPause < _ticks && _event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
_itemTicks = _ticks + 220;
if (_event.customType == kGriffonConfirm) {
if (curRow == 0) {
if (curCol == 0) {
// NEW GAME
if (ttsMan != nullptr)
ttsMan->stop();
_gameMode = kGameModeNewGame;
return;
} else if (curCol == 1) {
// SAVE GAME
lowerLock = true;
curRow = 1 + _saveSlot;
tickPause = _ticks + 125;
} else if (curCol == 2) {
// LOAD GAME
lowerLock = true;
curRow = 1;
tickPause = _ticks + 125;
} else if (curCol == 3) {
if (ttsMan != nullptr)
ttsMan->stop();
// RETURN
return;
} else if (curCol == 4) {
// QUIT - non existent :)
_shouldQuit = true;
return;
}
}
if (lowerLock && tickPause < _ticks) {
if ((curCol == 1) && saveGameState(curRow - 1, "", false).getCode() == Common::kNoError) {
_secStart += _secsInGame;
_secsInGame = 0;
lowerLock = false;
_saveSlot = curRow - 1;
curRow = 0;
renderSaveStates();
} else if ((curCol == 2) && loadGameState(curRow - 1).getCode() == Common::kNoError) {
return;
}
tickPause = _ticks + 125;
}
}
switch (_event.customType) {
case kGriffonMenu:
if (curRow == 0)
return;
lowerLock = false;
curRow = 0;
tickPause = _ticks + 125;
break;
case kGriffonDown:
if (lowerLock) {
++curRow;
if (curRow == 5)
curRow = 1;
tickPause = _ticks + 125;
}
break;
case kGriffonUp:
if (lowerLock) {
--curRow;
if (curRow == 0)
curRow = 4;
tickPause = _ticks + 125;
}
break;
case kGriffonLeft:
if (!lowerLock) {
--curCol;
if (curCol == -1)
curCol = 3;
if (curCol == 1 && _gameMode == kGameModeIntro)
curCol = 0;
tickPause = _ticks + 125;
}
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan -> say(optionTitles[curCol]);
break;
case kGriffonRight:
if (!lowerLock) {
++curCol;
if (curCol == 4)
curCol = 0;
if (curCol == 1 && _gameMode == kGameModeIntro)
curCol = 2;
tickPause = _ticks + 125;
}
if (ttsMan != nullptr && ConfMan.getBool("tts_enabled"))
ttsMan -> say(optionTitles[curCol]);
break;
default:
;
}
}
}
// Render savestates
_videoBuffer2->blendBlitTo(*_videoBuffer);
// ------------------------------------------
if (curRow == 0) {
rcDest.top = 18;
switch(curCol) {
case 0:
rcDest.left = 10;
break;
case 1:
rcDest.left = 108;
break;
case 2:
rcDest.left = 170;
break;
case 3:
rcDest.left = 230;
default:
break;
}
rcDest.left += (int16)(2 + 2 * sin(2 * M_PI * _itemyloc / 16));
}
if (curRow > 0) {
rcDest.left = (int16)(0 + 2 * sin(2 * M_PI * _itemyloc / 16));
rcDest.top = (int16)(53 + (curRow - 1) * 48);
}
_itemImg[15]->blendBlitTo(*_videoBuffer, rcDest.left, rcDest.top);
if (curRow != 0) {
rcDest.top = 18;
if (curCol == 1)
rcDest.left = 108;
else if (curCol == 2)
rcDest.left = 170;
_itemImg[15]->blendBlitTo(*_videoBuffer, rcDest.left, rcDest.top);
}
if (_ticks < ticks1 + 1000) {
int yy = 255 * (_ticks - ticks1) / 1000;
yy = CLIP(yy, 0, 255);
_videoBuffer->surfacePtr()->setAlpha((uint8)yy);
}
_videoBuffer3->fillRect(Common::Rect(0, 0, _videoBuffer3->w, _videoBuffer3->h), 0);
_videoBuffer->blendBlitTo(*_videoBuffer3);
g_system->copyRectToScreen(_videoBuffer3->getPixels(), _videoBuffer3->pitch, 0, 0, _videoBuffer3->w, _videoBuffer3->h);
g_system->updateScreen();
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
_cloudAngle += 0.01 * _fpsr;
while (_cloudAngle >= 360)
_cloudAngle -= 360;
_itemyloc += 0.6 * _fpsr;
while (_itemyloc >= 16)
_itemyloc -= 16;
g_system->delayMillis(10);
} while (!_shouldQuit);
}
} // end of namespace Griffon

1212
engines/griffon/draw.cpp Normal file

File diff suppressed because it is too large Load Diff

340
engines/griffon/engine.cpp Normal file
View File

@@ -0,0 +1,340 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "griffon/griffon.h"
#include "griffon/console.h"
#include "common/system.h"
namespace Griffon {
void Player::reset() {
px = 0;
py = 0;
opx = 0;
opy = 0;
walkDir = 0;
walkFrame = 0;
walkSpeed = 0;
attackFrame = 0;
attackSpeed = 0;
hp = 0;
maxHp = 0;
hpflash = 0;
hpflashb = 0;
level = 0;
maxLevel = 0;
sword = 0;
shield = 0;
armour = 0;
for (int i = 0; i < 5; i++) {
foundSpell[i] = 0;
spellCharge[i] = 0;
inventory[i] = 0;
}
attackStrength = 0;
itemselshade = 0;
spellDamage = 0;
swordDamage = 0;
exp = 0;
nextLevel = 0;
}
// copypaste from hRnd_CRT()
float GriffonEngine::RND() {
/* return between 0 and 1 (but never 1) */
return (float)_rnd->getRandomNumber(32767) * (1.0f / 32768.0f);
}
void GriffonEngine::mainLoop() {
swash();
if (_pmenu) {
haltSoundChannel(_menuChannel);
_pmenu = false;
}
_gameMode = kGameModePlay;
do {
if (!_forcePause) {
updateAnims();
updateNPCs();
}
checkTrigger();
checkInputs();
if (!_forcePause)
handleWalking();
updateY();
drawView();
updateMusic();
updateEngine();
} while (!_shouldQuit && _gameMode == kGameModePlay);
}
void GriffonEngine::updateEngine() {
g_system->updateScreen();
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24.0;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
_secsInGame = _secsInGame + 1;
}
if (_attacking) {
_player.attackFrame += _player.attackSpeed * _fpsr;
if (_player.attackFrame >= 16) {
_attacking = false;
_player.attackFrame = 0;
_player.walkFrame = 0;
}
int pa = (int)(_player.attackFrame);
for (int i = 0; i <= pa; i++) {
if (!_playerAttackOfs[_player.walkDir][i].completed) {
_playerAttackOfs[_player.walkDir][i].completed = true;
float opx = _player.px;
float opy = _player.py;
_player.px += _playerAttackOfs[_player.walkDir][i].x;
_player.py += _playerAttackOfs[_player.walkDir][i].y;
int sx = (int)(_player.px / 2 + 6);
int sy = (int)(_player.py / 2 + 10);
uint32 *temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
uint32 bgc = *temp;
if (bgc > 0) {
_player.px = opx;
_player.py = opy;
}
}
}
_player.opx = _player.px;
_player.opy = _player.py;
checkHit();
if (_gameMode != kGameModePlay)
return;
}
for (int i = 0; i < kMaxFloat; i++) {
if (_floatText[i].framesLeft > 0) {
float spd = 0.5 * _fpsr;
_floatText[i].framesLeft -= spd;
_floatText[i].y -= spd;
if (_floatText[i].framesLeft < 0)
_floatText[i].framesLeft = 0;
}
if (_floatIcon[i].framesLeft > 0) {
float spd = 0.5 * _fpsr;
_floatIcon[i].framesLeft -= spd;
_floatIcon[i].y -= spd;
if (_floatIcon[i].framesLeft < 0)
_floatIcon[i].framesLeft = 0;
}
}
if (_player.level == _player.maxLevel)
_player.exp = 0;
if (_player.exp >= _player.nextLevel) {
_player.level = _player.level + 1;
addFloatText("LEVEL UP!", _player.px + 16 - 36, _player.py + 16, 3);
_player.exp = _player.exp - _player.nextLevel;
_player.nextLevel = _player.nextLevel * 3 / 2; // 1.5
_player.maxHp = _player.maxHp + _player.level * 3;
if (_player.maxHp > 999)
_player.maxHp = 999;
_player.hp = _player.maxHp;
_player.swordDamage = _player.level * 14 / 10;
_player.spellDamage = _player.level * 13 / 10;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
}
_clipBg->copyRectToSurface(_clipBg2->getPixels(), _clipBg2->pitch, 0, 0, _clipBg2->w, _clipBg2->h);
Common::Rect rc;
rc.left = _player.px - 2;
rc.top = _player.py - 2;
rc.setWidth(5);
rc.setHeight(5);
_clipBg->fillRect(rc, 1000);
if (!_forcePause) {
for (int i = 0; i < 5; i++) {
if (_player.foundSpell[i])
_player.spellCharge[i] += 1 * _player.level * 0.01 * _fpsr;
if (_player.spellCharge[i] > 100)
_player.spellCharge[i] = 100;
}
if (_player.foundSpell[0]) {
_player.spellStrength += 3 * _player.level * .01 * _fpsr;
}
_player.attackStrength += (30 + 3 * (float)_player.level) / 50 * _fpsr;
}
if (_player.attackStrength > 100)
_player.attackStrength = 100;
if (_player.spellStrength > 100)
_player.spellStrength = 100;
_itemyloc += 0.75 * _fpsr;
while (_itemyloc >= 16)
_itemyloc -= 16;
if (_player.hp <= 0) {
theEnd();
_gameMode = kGameModeIntro;
return;
}
if (_roomLock) {
_roomLock = false;
for (int i = 1; i <= _lastNpc; i++)
if (_npcInfo[i].hp > 0)
_roomLock = true;
}
_cloudAngle += 0.1 * _fpsr;
while (_cloudAngle >= 360)
_cloudAngle = _cloudAngle - 360;
_player.hpflash = _player.hpflash + 0.1 * _fpsr;
if (_player.hpflash >= 2) {
_player.hpflash = 0;
_player.hpflashb = _player.hpflashb + 1;
if (_player.hpflashb == 2)
_player.hpflashb = 0;
if (config.effects && _player.hpflashb == 0 && _player.hp < _player.maxHp / 4) {
int snd = playSound(_sfx[kSndBeep]);
setChannelVolume(snd, config.effectsVol);
}
}
// _cloudsOn = false
if (_itemSelOn)
_player.itemselshade = _player.itemselshade + 2 * _fpsr;
if (_player.itemselshade > 24)
_player.itemselshade = 24;
for (int i = 0; i <= 4; i++)
if (_player.inventory[i] > 9)
_player.inventory[i] = 9;
}
void GriffonEngine::newGame() {
intro();
if (_shouldQuit)
return;
_player.reset();
_playera.reset();
memset(_scriptFlag, 0, sizeof(_scriptFlag));
memset(_objectMapFull, 0, sizeof(_objectMapFull));
memset(_roomLocks, 0, sizeof(_roomLocks));
_roomLocks[66] = 2;
_roomLocks[24] = 2;
_roomLocks[17] = 1;
_roomLocks[34] = 1;
_roomLocks[50] = 1;
_roomLocks[73] = 1;
_roomLocks[82] = 2;
_player.walkSpeed = 1.1f;
_animSpeed = 0.5f;
_attacking = false;
_player.attackSpeed = 1.5f;
_player.sword = 1;
_player.level = 1;
_player.maxLevel = 22;
_player.nextLevel = 50;
_player.shield = 1;
_player.armour = 1;
_player.hp = 14;
_player.maxHp = _player.hp;
_player.swordDamage = _player.level * 2;
_player.spellDamage = _player.level * 3 / 2;
_player.px = 15 * 16 - 4;
_player.py = 6 * 16 - 4;
_player.walkDir = 1;
_playingGardens = false;
_playingBoss = false;
_player.spellStrength = 0;
loadMap(2);
mainLoop();
}
} // end of namespace Griffon

170
engines/griffon/gfx.cpp Normal file
View File

@@ -0,0 +1,170 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "common/system.h"
#include "griffon/griffon.h"
namespace Griffon {
void GriffonEngine::addFloatIcon(int ico, float xloc, float yloc) {
for (int i = 0; i < kMaxFloat; i++) {
if (ABS(_floatIcon[i].framesLeft) < kEpsilon) {
_floatIcon[i].framesLeft = 32;
_floatIcon[i].x = xloc;
_floatIcon[i].y = yloc;
_floatIcon[i].ico = ico;
return;
}
}
}
void GriffonEngine::addFloatText(const char *stri, float xloc, float yloc, int col) {
for (int i = 0; i < kMaxFloat; i++) {
if (ABS(_floatText[i].framesLeft) < kEpsilon) {
_floatText[i].framesLeft = 32;
_floatText[i].x = xloc;
_floatText[i].y = yloc;
_floatText[i].col = col;
Common::strcpy_s(_floatText[i].text, 64, stri);
return;
}
}
}
void GriffonEngine::eventText(const char *stri) {
_videoBuffer2->fillRect(Common::Rect(0, 0, _videoBuffer2->w, _videoBuffer2->h), 0);
_videoBuffer3->fillRect(Common::Rect(0, 0, _videoBuffer3->w, _videoBuffer3->h), 0);
int x = 160 - 4 * strlen(stri);
_ticks = g_system->getMillis();
int pause_ticks = _ticks + 500;
int b_ticks = _ticks;
_videoBuffer->blendBlitTo(*_videoBuffer3);
_videoBuffer->blendBlitTo(*_videoBuffer2);
do {
g_system->getEventManager()->pollEvent(_event);
if ((_event.type == Common::EVENT_KEYDOWN || _event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) && pause_ticks < _ticks)
break;
_videoBuffer2->blendBlitTo(*_videoBuffer);
int fr = 192;
if (pause_ticks > _ticks)
fr = 192 * (_ticks - b_ticks) / 500;
if (fr > 192)
fr = 192;
_windowImg->surfacePtr()->setAlpha(fr, true);
_windowImg->blendBlitTo(*_videoBuffer);
if (pause_ticks < _ticks)
drawString(_videoBuffer, stri, x, 15, 0);
g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
g_system->updateScreen();
g_system->getEventManager()->pollEvent(_event);
g_system->delayMillis(10);
_ticksPassed = _ticks;
_ticks = g_system->getMillis();
_ticksPassed = _ticks - _ticksPassed;
_fpsr = (float)_ticksPassed / 24.0;
_fp++;
if (_ticks > _nextTicks) {
_nextTicks = _ticks + 1000;
_fps = _fp;
_fp = 0;
}
g_system->delayMillis(10);
} while (1);
_videoBuffer3->blendBlitTo(*_videoBuffer);
_itemTicks = _ticks + 210;
}
void GriffonEngine::drawLine(Graphics::ManagedSurface *buffer, int x1, int y1, int x2, int y2, int col) {
int xdif = x2 - x1;
int ydif = y2 - y1;
if (xdif == 0) {
for (int y = y1; y <= y2; y++) {
uint32 *temp = (uint32 *)buffer->getBasePtr(x1, y);
*temp = col;
}
}
if (ydif == 0) {
for (int x = x1; x <= x2; x++) {
uint32 *temp = (uint32 *)buffer->getBasePtr(x, y1);
*temp = col;
}
}
}
void GriffonEngine::drawString(Graphics::ManagedSurface *buffer, const char *stri, int xloc, int yloc, int col) {
int l = strlen(stri);
for (int i = 0; i < l; i++) {
rcDest.left = xloc + i * 8;
rcDest.top = yloc;
_fontChr[stri[i] - 32][col]->blendBlitTo(*buffer, rcDest.left, rcDest.top);
}
}
void GriffonEngine::drawProgress(int w, int wm) {
long ccc = _videoBuffer->format.RGBToColor(0, 255, 0);
rcDest.setWidth(w * 74 / wm);
_videoBuffer->fillRect(rcDest, ccc);
g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
g_system->updateScreen();
g_system->getEventManager()->pollEvent(_event);
}
} // end of namespace Griffon

208
engines/griffon/griffon.cpp Normal file
View File

@@ -0,0 +1,208 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/system.h"
#include "common/translation.h"
#include "graphics/pixelformat.h"
#include "common/text-to-speech.h"
#include "engines/util.h"
#include "griffon/griffon.h"
#include "griffon/console.h"
namespace Griffon {
GriffonEngine::GriffonEngine(OSystem *syst) : Engine(syst) {
const Common::FSNode gameDataDir(ConfMan.getPath("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
_rnd = new Common::RandomSource("griffon");
_console = nullptr;
_mixer = nullptr;
_shouldQuit = false;
_gameMode = kGameModeIntro;
_musicChannel = -1;
_menuChannel = -1;
_cloudAngle = 0.0f;
_dontDrawOver = false;
_firsty = 0;
_lasty = 0;
_saveSlot = 0;
_ticks = g_system->getMillis();
_ticksAtPauseStart = 0;
for (int i = 0; i < 33; ++i) {
for (int j = 0; j < 6; ++j) {
_objectInfo[i].nFrames = 0;
_objectInfo[i].xTiles = 0;
_objectInfo[i].yTiles = 0;
_objectInfo[i].speed = 0;
_objectInfo[i].type = 0;
_objectInfo[i].script = 0;
}
}
for (int i = 0; i < 256; ++i) {
_objectFrame[i][0] = 0;
_objectFrame[i][1] = 0;
}
// Synchronize the sound settings from ScummVM
syncSoundSettings();
}
GriffonEngine::~GriffonEngine() {
delete _rnd;
//delete _console; Debugger is deleted by Engine
}
void GriffonEngine::syncSoundSettings() {
Engine::syncSoundSettings();
bool mute = false;
config.music = config.effects = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
if (!mute) {
config.music = !ConfMan.getBool("music_mute");
config.effects = !ConfMan.getBool("sfx_mute");
}
config.musicVol = ConfMan.getInt("music_volume");
config.effectsVol = ConfMan.getInt("sfx_volume");
}
void GriffonEngine::saveConfig() {
ConfMan.setBool("mute", !(config.music || config.effectsVol));
ConfMan.setBool("music_mute", !config.music);
ConfMan.setBool("sfx_mute", !config.effects);
ConfMan.setInt("music_volume", config.musicVol);
ConfMan.setInt("sfx_volume", config.effectsVol);
ConfMan.flushToDisk();
}
Common::Error GriffonEngine::run() {
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (ttsMan != nullptr) {
ttsMan->setLanguage("en");
ttsMan->enable(ConfMan.getBool("tts_enabled"));
}
Graphics::PixelFormat pixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
initGraphics(320, 240, &pixelFormat);
_mixer = g_system->getMixer();
_console = new Console();
setDebugger(_console);
initialize();
if (ConfMan.hasKey("save_slot")) {
_saveSlot = ConfMan.getInt("save_slot");
loadGameState(_saveSlot);
_gameMode = kGameModeLoadGame;
} else {
showLogos();
_gameMode = kGameModeIntro;
}
if (_shouldQuit)
return Common::kNoError;
while (!_shouldQuit) {
switch (_gameMode) {
case kGameModeIntro:
case kGameModePlay:
title(0);
break;
case kGameModeNewGame:
newGame();
break;
case kGameModeLoadGame:
_player.walkSpeed = 1.1f;
_animSpeed = 0.5f;
_attacking = false;
_player.attackSpeed = 1.5f;
_playingGardens = false;
_playingBoss = false;
haltSoundChannel(-1);
_secsInGame = 0;
loadMap(_curMap);
mainLoop();
break;
default:
error("Bad game mode: %d", _gameMode);
}
}
return Common::kNoError;
}
void GriffonEngine::pauseEngineIntern(bool pause) {
if (pause) {
_ticksAtPauseStart = _ticks;
} else {
uint32 diff = _system->getMillis() - _ticksAtPauseStart;
_ticks += diff;
_nextTicks += diff;
}
}
}

582
engines/griffon/griffon.h Normal file
View File

@@ -0,0 +1,582 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#ifndef GRIFFON_GRIFFON_H
#define GRIFFON_GRIFFON_H
#include "common/scummsys.h"
#include "common/error.h"
#include "common/events.h"
#include "common/random.h"
#include "engines/engine.h"
#include "audio/mixer.h"
#include "graphics/managed_surface.h"
namespace Griffon {
class Console;
#define kSoundHandles 16
#define kMaxNPC 32
#define kMaxFloat 32
#define kMaxSpell 32
// spells
enum {
kSpellIce = 0,
kSpellSteel,
kSpellWood,
kSpellRock,
kSpellFire
};
// inventory items
enum {
kInvFlask = 0,
kInvDoubleFlask,
kInvShock,
kInvNormalKey,
kInvMasterKey
};
enum {
kSndBite = 0,
kSndCrystal,
kSndDoor,
kSndEnemyHit,
kSndIce,
kSndLever,
kSndLightning,
kSndMetalHit,
kSndPowerUp,
kSndRocks,
kSndSwordHit,
kSndThrow,
kSndChest,
kSndFire,
kSndBeep
};
// in game scripts
enum {
kScriptFlask = 0, // get flask
kScriptMasterKey = 2, // find master key
kScriptFindCrystal = 3, // find crystal
kScriptFindShield = 4, // find shield - obj 8
kScriptFindSword = 5, // find sword - obj 9
kScriptKeyChest = 6, // regular key chest
kScriptBlueFlask = 7, // blue flask
kScriptGardenMasterKey = 8, // garden's master key
kScriptLightningBomb = 9, // lightning bomb
kScriptBlueFlaskChest = 10, // blue flask chest
kScriptLightningChest = 11, // lightning chest
kScriptArmourChest = 12, // armour chest
kScriptCitadelMasterKey = 13, // citadel master key
kScriptEndOfGame = 14, // end of game
kScriptGetSword3 = 15, // get sword3
kScriptShield3 = 16, // shield3
kScriptArmour3 = 17, // armour3
kScriptKeyChest1 = 20, // key chest 1
kScriptLever = 60 // lever
};
// monsters
enum {
kMonsterBabyDragon = 1, // baby dragon
kMonsterOneWing = 2, // one wing
kMonsterBoss1 = 3, // boss 1
kMonsterBlackKnight = 4, // black knight
kMonsterFireHydra = 5, // fire hydra
kMonsterRedDragon = 6, // red dragon
kMonsterPriest = 7, // priest
kMonsterYellowDragon = 8, // yellow fire dragon
kMonsterTwoWing = 9, // two wing
kMonsterDragon2 = 10, // dragon2
kMonsterFinalBoss = 11, // final boss
kMonsterBatKitty = 12 // bat kitty
};
// engine actions
enum GriffonActions {
kGriffonLeft,
kGriffonRight,
kGriffonUp,
kGriffonDown,
kGriffonAttack,
kGriffonInventory,
kGriffonMenu,
kGriffonConfirm,
kGriffonCutsceneSpeedUp
};
#define kEpsilon 0.001
struct Player {
float px;
float py;
float opx;
float opy;
int walkDir;
float walkFrame;
float walkSpeed;
float attackFrame;
float attackSpeed;
int hp;
int maxHp;
float hpflash;
int hpflashb;
int level;
int maxLevel;
int sword;
int shield;
int armour;
int foundSpell[5];
float spellCharge[5];
int inventory[5];
float attackStrength;
float spellStrength;
int spellDamage;
int swordDamage;
int exp;
int nextLevel;
int pause;
float itemselshade;
int ysort;
void reset();
};
struct BodySection {
float x;
float y;
int parentID;
int isbase;
int sprite;
int bonelength; // the 'bone' that connects the body sections
};
struct NPC {
float x;
float y;
int spriteset;
int x1; // patrol area
int y1;
int x2;
int y2;
int attitude;
int hp;
int maxhp;
int item1;
int item2;
int item3;
int script;
float frame;
float frame2; // end boss specific
int cframe;
bool onMap; // is this npc set to be genned in the mapfile
int ticks;
int pause;
int shake;
int movementmode;
int walkdir;
float walkspd;
int movingdir;
bool moving;
bool attacking;
float attackframe;
int cattackframe;
float attackspd;
int attackdelay;
int attacknext;
int attackattempt;
int spellDamage;
int attackDamage;
// one wing and firehydra specific
BodySection bodysection[31];
float swayAngle;
float swaySpeed;
float headTargetX[4];
float headTargetY[4];
int castPause;
// firehydra specific
int attacknext2[4];
bool attacking2[4];
int attackframe2[4];
// dragon2 specific
float floating;
};
struct Spell {
int spellnum;
float homex;
float homey;
float enemyx;
float enemyy;
float frame;
int damagewho; // 0 = npc, 1 = player
// for earthslide
float rocky[9]; // CHECKME: Looks unused
int rockimg[9];
int rockdeflect[9];
float strength;
// fire
int legalive[5];
// spell 6 specific
float fireballs[7][4]; // x,y,targetx, targety
int nfballs;
int ballon[7];
int npc;
};
struct AnimSet {
int x; // xyloc on spriteimageset
int y;
int xofs; // the actual place to paste the sprite in reference to the bodypart loc on screen
int yofs;
int w; // w/h of the sprite in the imageset
int h;
};
struct DataChunk {
byte *data;
int size;
};
struct FloatTextStruct {
float framesLeft;
float x;
float y;
int col;
char *text;
};
struct FloatIconStruct {
float framesLeft;
float x;
float y;
int ico;
};
struct AttackOffsetStruct {
float x;
float y;
bool completed;
};
struct Config {
bool music;
int musicVol;
bool effects;
int effectsVol;
};
struct ObjectInfoStruct {
int nFrames;
int xTiles;
int yTiles;
int speed;
int type;
int script;
};
enum {
kGameModeIntro,
kGameModePlay,
kGameModeNewGame,
kGameModeLoadGame
};
class GriffonEngine : public Engine {
public:
GriffonEngine(OSystem *syst);
~GriffonEngine() override;
Common::Error run() override;
void syncSoundSettings() override;
private:
Common::RandomSource *_rnd;
bool _shouldQuit;
int _gameMode;
Console *_console;
private:
// combat.cpp
void attack();
void castSpell(int spellnum, float homex, float homey, float enemyx, float enemyy, int damagewho);
void checkHit();
void damageNPC(int npcnum, int damage, int spell);
void damagePlayer(int damage);
// cutscenes.cpp
void showLogos();
void intro();
void endOfGame();
void theEnd();
// dialogs.cpp
void title(int mode);
void configMenu();
void saveLoadNew();
void renderSaveStates();
// draw.cpp
void drawAnims(int Layer);
void drawHud();
void drawNPCs(int mode);
void drawOver(int modx, int mody);
void drawPlayer();
void drawView();
void swash();
// engine.cpp
float RND();
void mainLoop();
void updateEngine();
void newGame();
// gfx.cpp
void addFloatIcon(int ico, float xloc, float yloc);
void addFloatText(const char *stri, float xloc, float yloc, int col);
void eventText(const char *stri);
void drawLine(Graphics::ManagedSurface *buffer, int x1, int y1, int x2, int y2, int col);
void drawString(Graphics::ManagedSurface *buffer, const char *stri, int xloc, int yloc, int col);
void drawProgress(int w, int wm);
// input.cpp
void checkInputs();
void handleWalking();
void checkTrigger();
void processTrigger(int trignum);
// logic.cpp
void updateAnims();
void updateY();
void updateNPCs();
void updateSpells();
void updateSpellsUnder();
// resources.cpp
void initialize();
Graphics::ManagedSurface *loadImage(const char *name, bool colorkey = false);
void loadMap(int mapnum);
void loadAnims();
void loadFont();
void loadItemImgs();
void loadTiles();
void loadTriggers();
void loadObjectDB();
// saveload.cpp
Common::String getSaveStateName(int slot) const override;
int loadPlayer(int slotnum);
Common::Error loadGameState(int slot) override;
Common::Error saveGameState(int slot, const Common::String &desc, bool isAutosave = false) override;
Common::Error loadGameStream(Common::SeekableReadStream *file) override;
Common::Error saveGameStream(Common::WriteStream *file, bool isAutosave) override;
// sound.cpp
void setChannelVolume(int channel, int volume);
int getSoundHandle();
int playSound(DataChunk *chunk, bool looped = false);
void pauseSoundChannel(int channel);
void haltSoundChannel(int channel);
void resumeSoundChannel(int channel);
bool isSoundChannelPlaying(int channel);
void setupAudio();
void updateMusic();
// Common engine overrides
void pauseEngineIntern(bool pause) override;
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override { return true; }
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override { return _gameMode == kGameModePlay; }
int getAutosaveSlot() const override { return 4; }
bool hasFeature(EngineFeature f) const override;
private:
Graphics::ManagedSurface *_video, *_videoBuffer, *_videoBuffer2, *_videoBuffer3;
// system
Graphics::ManagedSurface *_titleImg, *_titleImg2, *_inventoryImg;
Graphics::ManagedSurface *_logosImg, *_theEndImg;
Common::Event _event;
Graphics::ManagedSurface *_mapBg, *_clipBg, *_clipBg2;
unsigned int _clipSurround[4][4];
float _animSpeed; // CHECKME: it seems to always be 0.5
int _rampData[40][24];
int _curMap;
Graphics::ManagedSurface *_fontChr[224][5]; // 256 - 32
Graphics::ManagedSurface *_itemImg[21], *_windowImg;
Graphics::ManagedSurface *_spellImg;
bool _itemSelOn;
int _curItem, _itemTicks;
float _itemyloc;
bool _selEnemyOn;
int _curEnemy;
bool _forcePause;
bool _roomLock; // set to disable any room jumps while in the room
int _scriptFlag[100][10], _saveSlot; // script, flag
// timer related - move to local later
int _ticks, _ticksPassed, _nextTicks, _ticksAtPauseStart;
float _fp, _fps, _fpsr; // CHECKME: _fp and _fps seems to be integers
int _secsInGame, _secStart;
Graphics::ManagedSurface *mapImg[4];
Common::Rect rcSrc, rcDest;
// -----------special case
bool _dontDrawOver; // used in map24 so that the candles don't draw over the boss, default set to 0
// saveload info
Graphics::ManagedSurface *_saveLoadImg;
// post info
float _postInfo[21][3];
int _postInfoNbr;
// cloud info
Graphics::ManagedSurface *_cloudImg;
float _cloudAngle;
int _cloudsOn;
// spell info
Spell _spellInfo[kMaxSpell];
// player info
Player _player;
Player _playera;
bool _movingUp, _movingDown, _movingLeft, _movingRight;
bool _attacking;
int _asecstart;
// tile info
Graphics::ManagedSurface *_tiles[4];
int _tileinfo[3][40][24][3]; // maplayer, x, y, tiledata (tile, tilelayer)
// animation info
Graphics::ManagedSurface *_anims[100];
// id number 0&1 = players
Graphics::ManagedSurface *_animsAttack[100];
// attack anims
AttackOffsetStruct _playerAttackOfs[4][16];
FloatTextStruct _floatText[kMaxFloat];
FloatIconStruct _floatIcon[kMaxFloat];
// special for animset2
AnimSet _animSet2[7], _animSet9[7];
// object info
float _objectFrame[256][2];
int _lastObj;
// frame!, curframe
ObjectInfoStruct _objectInfo[33];
int _objectTile[33][9][3][3][2];
// [objnum] [frame] [x] [y] [tile/layer]
int _objectMap[21][15];
int _objectMapFull[1000][21][15];
// [mapnum] x, y set to 1 to make this objmap spot stay at -1
// trigger info
int _triggers[10000][9];
// [map#][index], [var]
// map#,x,y
int _triggerLoc[320][240], _triggerNbr;
// npc info
NPC _npcInfo[kMaxNPC];
int _lastNpc;
// music info
DataChunk *_musicGardens1, *_musicGardens2, *_musicGardens3, *_musicGardens4, *_musicBoss, *_musicMenu, *_musicEndOfGame;
int _musicChannel, _menuChannel;
bool _playingBoss, _playingGardens;
DataChunk *_sfx[15];
Audio::SoundHandle _handles[kSoundHandles];
Audio::Mixer *_mixer;
// set to 1 for normal key, set to 2 for master, set to 0 if unlocked
int _roomLocks[201], _lockType;
int _roomToUnlock;
bool _canUseKey;
bool _saidLocked;
bool _saidJammed;
// ysort
int _ysort[2401], _lasty, _firsty;
bool _pmenu;
Config config;
void saveConfig();
};
}
#endif // GRIFFON_GRIFFON_H

691
engines/griffon/input.cpp Normal file
View File

@@ -0,0 +1,691 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "common/system.h"
#include "griffon/griffon.h"
#include "griffon/console.h"
namespace Griffon {
void GriffonEngine::checkInputs() {
int ntickdelay = 175;
bool _keyPressed = false;
if (g_system->getEventManager()->pollEvent(_event))
_keyPressed = true;
_postInfoNbr = 0;
for (int i = 0; i <= 20; i++) {
_postInfo[i][0] = 0;
_postInfo[i][1] = 0;
}
for (int x = 0; x <= 19; x++) {
for (int y = 0; y <= 14; y++) {
int o = _objectMap[x][y];
if (_objectInfo[o].type == 3) {
_postInfo[_postInfoNbr][0] = x * 16;
_postInfo[_postInfoNbr][1] = y * 16;
_postInfoNbr = _postInfoNbr + 1;
}
}
}
if (_attacking || (_forcePause && !_itemSelOn))
return;
if (_event.type == Common::EVENT_QUIT || _event.type == Common::EVENT_RETURN_TO_LAUNCHER) {
_shouldQuit = true;
return;
}
if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
if (_event.customType == kGriffonMenu) {
if (_itemTicks < _ticks)
title(1);
} else if (_event.customType == kGriffonAttack) {
if (!_itemSelOn && (_itemTicks < _ticks))
attack();
if (_itemSelOn && _itemTicks < _ticks) {
if (_curItem == 0 && _player.inventory[kInvFlask] > 0) {
_itemTicks = _ticks + ntickdelay;
int heal = 50;
int maxh = _player.maxHp - _player.hp;
if (heal > maxh)
heal = maxh;
_player.hp = _player.hp + heal;
char text[256];
Common::sprintf_s(text, "+%i", heal);
addFloatText(text, _player.px + 16 - 4 * strlen(text), _player.py + 16, 5);
_player.inventory[kInvFlask]--;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
_itemSelOn = false;
_forcePause = false;
}
if (_curItem == 1 && _player.inventory[kInvDoubleFlask] > 0) {
_itemTicks = _ticks + ntickdelay;
int heal = 200;
int maxHeal = _player.maxHp - _player.hp;
if (heal > maxHeal)
heal = maxHeal;
_player.hp += heal;
char text[256];
Common::sprintf_s(text, "+%i", heal);
addFloatText(text, _player.px + 16 - 4 * strlen(text), _player.py + 16, 5);
_player.inventory[kInvDoubleFlask]--;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
_itemSelOn = false;
_forcePause = false;
}
if (_curItem == 2 && _player.inventory[kInvShock] > 0) {
castSpell(8, _player.px, _player.py, _npcInfo[_curEnemy].x, _npcInfo[_curEnemy].y, 0);
_forcePause = true;
_player.inventory[kInvShock]--;
_itemTicks = _ticks + ntickdelay;
_selEnemyOn = false;
_itemSelOn = false;
}
if (_curItem == 3 && _player.inventory[kInvNormalKey] > 0 && _canUseKey && _lockType == 1) {
_roomLocks[_roomToUnlock] = 0;
eventText("UnLocked!");
_player.inventory[kInvNormalKey]--;
_itemTicks = _ticks + ntickdelay;
_selEnemyOn = false;
_itemSelOn = false;
return;
}
if (_curItem == 4 && _player.inventory[kInvMasterKey] > 0 && _canUseKey && _lockType == 2) {
_roomLocks[_roomToUnlock] = 0;
eventText("UnLocked!");
_player.inventory[kInvMasterKey]--;
_itemTicks = _ticks + ntickdelay;
_selEnemyOn = false;
_itemSelOn = false;
return;
}
if (_curItem == 5 && _player.spellCharge[0] == 100) {
castSpell(5, _player.px, _player.py, _npcInfo[_curEnemy].x, _npcInfo[_curEnemy].y, 0);
_player.spellCharge[0] = 0;
_forcePause = true;
_itemTicks = _ticks + ntickdelay;
_selEnemyOn = false;
_itemSelOn = false;
}
if (_curItem > 5 && _selEnemyOn) {
if (_curEnemy <= _lastNpc) {
castSpell(_curItem - 6, _player.px, _player.py, _npcInfo[_curEnemy].x, _npcInfo[_curEnemy].y, 0);
} else {
int pst = _curEnemy - _lastNpc - 1;
castSpell(_curItem - 6, _player.px, _player.py, _postInfo[pst][0], _postInfo[pst][1], 0);
}
_player.spellCharge[_curItem - 5] = 0;
_player.spellStrength = 0;
_itemTicks = _ticks + ntickdelay;
_selEnemyOn = false;
_itemSelOn = false;
_forcePause = false;
}
if (_curItem > 5 && !_selEnemyOn && _itemSelOn) {
if (ABS(_player.spellCharge[_curItem - 5] - 100) < kEpsilon) {
_itemTicks = _ticks + ntickdelay;
_selEnemyOn = true;
int i = 0;
do {
if (_npcInfo[i].hp > 0) {
_curEnemy = i;
goto __exit_do;
}
i = i + 1;
if (i == _lastNpc + 1) {
_selEnemyOn = false;
goto __exit_do;
}
} while (1);
__exit_do:
if (_postInfoNbr > 0 && !_selEnemyOn) {
_selEnemyOn = true;
_curEnemy = _lastNpc + 1;
}
}
}
}
} else if (_event.customType == kGriffonInventory) {
if (_itemTicks < _ticks) {
_selEnemyOn = false;
if (_itemSelOn) {
_itemSelOn = false;
_itemTicks = _ticks + 220;
_forcePause = false;
} else {
_itemSelOn = true;
_itemTicks = _ticks + 220;
_forcePause = true;
_player.itemselshade = 0;
}
}
}
}
if (!_itemSelOn) {
_movingUp = false;
_movingDown = false;
_movingLeft = false;
_movingRight = false;
// We continue moving even after the key has been released until we receive a different event
if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START || _event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_END) {
if (_event.customType == kGriffonUp)
_movingUp = true;
if (_event.customType == kGriffonDown)
_movingDown = true;
if (_event.customType == kGriffonLeft)
_movingLeft = true;
if (_event.customType == kGriffonRight)
_movingRight = true;
}
} else {
_movingUp = false;
_movingDown = false;
_movingLeft = false;
_movingRight = false;
if (_selEnemyOn) {
if (_itemTicks < _ticks) {
if (_event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
if (_event.customType == kGriffonLeft) {
int origin = _curEnemy;
do {
_curEnemy = _curEnemy - 1;
if (_curEnemy < 1)
_curEnemy = _lastNpc + _postInfoNbr;
if (_curEnemy == origin)
break;
if (_curEnemy <= _lastNpc && _npcInfo[_curEnemy].hp > 0)
break;
if (_curEnemy > _lastNpc)
break;
} while (1);
_itemTicks = _ticks + ntickdelay;
}
if (_event.customType == kGriffonRight) {
int origin = _curEnemy;
do {
_curEnemy = _curEnemy + 1;
if (_curEnemy > _lastNpc + _postInfoNbr)
_curEnemy = 1;
if (_curEnemy == origin)
break;
if (_curEnemy <= _lastNpc && _npcInfo[_curEnemy].hp > 0)
break;
if (_curEnemy > _lastNpc)
break;
} while (1);
_itemTicks = _ticks + ntickdelay;
}
}
if (_curEnemy > _lastNpc + _postInfoNbr)
_curEnemy = 1;
if (_curEnemy < 1)
_curEnemy = _lastNpc + _postInfoNbr;
}
} else {
if (_keyPressed && _event.type == Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
if (_event.customType == kGriffonUp) {
_curItem = _curItem - 1;
_itemTicks = _ticks + ntickdelay;
if (_curItem == 4)
_curItem = 9;
if (_curItem == -1)
_curItem = 4;
}
if (_event.customType == kGriffonDown) {
_curItem = _curItem + 1;
_itemTicks = _ticks + ntickdelay;
if (_curItem == 5)
_curItem = 0;
if (_curItem == 10)
_curItem = 5;
}
if (_event.customType == kGriffonLeft) {
_curItem = _curItem - 5;
_itemTicks = _ticks + ntickdelay;
}
if (_event.customType == kGriffonRight) {
_curItem = _curItem + 5;
_itemTicks = _ticks + ntickdelay;
}
}
if (_curItem > 9)
_curItem = _curItem - 10;
if (_curItem < 0)
_curItem = _curItem + 10;
}
}
}
void GriffonEngine::handleWalking() {
int xmax = 20 * 16 - 25;
int ymax = 15 * 16 - 25;
float px = _player.px;
float py = _player.py;
float opx = px;
float opy = py;
float spd = _player.walkSpeed * _fpsr;
float nx = (px / 2 + 6);
float ny = (py / 2 + 10);
float npx = px + 12;
float npy = py + 20;
int lx = (int)npx / 16;
int ly = (int)npy / 16;
int ramp = _rampData[lx][ly];
if (ramp == 1 && _movingUp)
spd *= 2;
if (ramp == 1 && _movingDown)
spd *= 2;
if (ramp == 2 && _movingLeft)
_movingUp = true;
if (ramp == 2 && _movingRight)
_movingDown = true;
if (ramp == 3 && _movingRight)
_movingUp = true;
if (ramp == 3 && _movingLeft)
_movingDown = true;
uint32 *temp/*, c*/, bgc;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
int sx = nx + x;
int sy = ny + y;
_clipSurround[x + 1][y + 1] = 0;
if (sx > -1 && sx < 320 && sy > -1 && sy < 192) {
temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
_clipSurround[x + 1][y + 1] = *temp;
}
}
}
if (_movingUp)
_player.walkDir = 0;
if (_movingDown)
_player.walkDir = 1;
if (_movingLeft)
_player.walkDir = 2;
if (_movingRight)
_player.walkDir = 3;
if (_movingUp && _clipSurround[1][0] == 0) {
py -= spd;
_player.walkDir = 0;
} else if (_movingUp && _clipSurround[1][0] > 0) {
// move upleft
if (!_movingRight && _clipSurround[0][0] == 0) {
py -= spd;
px -= spd;
}
// move upright
if (!_movingLeft && _clipSurround[2][0] == 0) {
py -= spd;
px += spd;
}
}
if (_movingDown && _clipSurround[1][2] == 0) {
py += spd;
_player.walkDir = 1;
} else if (_movingDown && _clipSurround[1][2] > 0) {
// move downleft
if (_movingRight == 0 && _clipSurround[0][2] == 0) {
py += spd;
px -= spd;
}
// move downright
if (_movingLeft == 0 && _clipSurround[2][2] == 0) {
py += spd;
px += spd;
}
}
if (_movingLeft && _clipSurround[0][1] == 0) {
px -= spd;
_player.walkDir = 2;
} else if (_movingLeft && _clipSurround[0][1] > 0) {
// move leftup
if (!_movingDown && _clipSurround[0][0] == 0) {
py -= spd;
px -= spd;
}
// move leftdown
if (!_movingUp && _clipSurround[0][2] == 0) {
py += spd;
px -= spd;
}
}
if (_movingRight && _clipSurround[2][1] == 0) {
px += spd;
_player.walkDir = 3;
} else if (_movingRight && _clipSurround[2][1] > 0) {
// move rightup
if (!_movingDown && _clipSurround[2][0] == 0) {
px += spd;
py -= spd;
}
// move rightdown
if (!_movingUp && _clipSurround[2][2] == 0) {
py += spd;
px += spd;
}
}
if (px < -8)
px = -8;
if (px > xmax)
px = xmax;
if (py < -8)
py = -8;
if (py > ymax)
py = ymax;
int pass = 1;
int sx = (px / 2 + 6);
int sy = (py / 2 + 10);
temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
bgc = *temp;
if (bgc > 0 && bgc != 1000) {
px = opx;
py = opy;
pass = 0;
}
// push npc
if (pass == 1) {
for (int i = 1; i <= _lastNpc; i++) {
if (_npcInfo[i].hp > 0) {
npx = _npcInfo[i].x;
npy = _npcInfo[i].y;
opx = npx;
opy = npy;
int xdif = _player.px - npx;
int ydif = _player.py - npy;
if (_player.walkDir == 0) {
if (ABS(xdif) <= 8 && ydif > 0 && ydif < 8)
_npcInfo[i].y -= spd;
} else if (_player.walkDir == 1) {
if (ABS(xdif) <= 8 && ydif < 0 && ydif > -8)
_npcInfo[i].y += spd;
} else if (_player.walkDir == 2) {
if (ABS(ydif) <= 8 && xdif > 0 && xdif < 8)
_npcInfo[i].x -= spd;
} else if (_player.walkDir == 3) {
if (ABS(ydif) <= 8 && xdif < 0 && xdif > -8)
_npcInfo[i].x += spd;
}
npx = _npcInfo[i].x;
npy = _npcInfo[i].y;
sx = (int)(npx / 2 + 6);
sy = (int)(npy / 2 + 10);
temp = (uint32 *)_clipBg->getBasePtr(sx, sy);
bgc = *temp;
if (bgc > 0) {
_npcInfo[i].x = opx;
_npcInfo[i].y = opy;
}
}
}
}
_player.opx = _player.px;
_player.opy = _player.py;
_player.px = px;
_player.py = py;
if (_player.px != _player.opx || _player.py != _player.opy)
_player.walkFrame += _animSpeed * _fpsr;
if (_player.walkFrame >= 16)
_player.walkFrame -= 16;
// walking over items to pickup :::
int o = _objectMap[lx][ly];
if (o > -1) {
// fsk
if (_objectInfo[o].type == 2 && _player.inventory[kInvFlask] < 9) {
_objectMap[lx][ly] = -1;
_player.inventory[kInvFlask]++;
addFloatIcon(6, lx * 16, ly * 16);
_objectMapFull[_curMap][lx][ly] = 1;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
}
if (_objectInfo[o].script == 7 && _player.inventory[kInvDoubleFlask] < 9) {
_objectMap[lx][ly] = -1;
_player.inventory[kInvDoubleFlask]++;
addFloatIcon(12, lx * 16, ly * 16);
_objectMapFull[_curMap][lx][ly] = 1;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
}
if (_objectInfo[o].script == 9 && _player.inventory[kInvShock] < 9 && (_curMap == 41 && _scriptFlag[kScriptLightningBomb][1] == 0)) {
_objectMap[lx][ly] = -1;
_player.inventory[kInvShock]++;
addFloatIcon(17, lx * 16, ly * 16);
_objectMapFull[_curMap][lx][ly] = 1;
if (_curMap == 41)
_scriptFlag[kScriptLightningBomb][1] = 1;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
}
if (_objectInfo[o].script == 9 && _player.inventory[kInvShock] < 9) {
_objectMap[lx][ly] = -1;
_player.inventory[kInvShock]++;
addFloatIcon(17, lx * 16, ly * 16);
_objectMapFull[_curMap][lx][ly] = 1;
if (config.effects) {
int snd = playSound(_sfx[kSndPowerUp]);
setChannelVolume(snd, config.effectsVol);
}
}
}
}
void GriffonEngine::checkTrigger() {
int npx = _player.px + 12;
int npy = _player.py + 20;
int lx = (int)npx / 16;
int ly = (int)npy / 16;
_canUseKey = false;
if (_triggerLoc[lx][ly] > -1)
processTrigger(_triggerLoc[lx][ly]);
}
void GriffonEngine::processTrigger(int trignum) {
int trigtype = _triggers[trignum][0];
if (_roomLock)
return;
// map jump------------------------------
if (trigtype == 0) {
int tx = _triggers[trignum][1];
int ty = _triggers[trignum][2];
int tmap = _triggers[trignum][3];
int tjumpstyle = _triggers[trignum][4];
if (_roomLocks[tmap] > 0) {
if (!_saidLocked)
eventText("Locked");
_saidLocked = true;
_canUseKey = true;
_lockType = _roomLocks[tmap];
_roomToUnlock = tmap;
return;
}
if (tmap == 1) {
if (!_saidJammed)
eventText("Door Jammed!");
_saidJammed = true;
return;
}
_saidLocked = false;
_saidJammed = false;
// loc-sxy+oldmaploc
if (tjumpstyle == 0) {
int tsx = _triggers[trignum][5];
int tsy = _triggers[trignum][6];
_player.px += (tx - tsx) * 16;
_player.py += (ty - tsy) * 16;
// HACKFIX
if (_player.px < 0)
_player.px = 0;
if (_player.py < 0)
_player.py = 0;
if (tmap > 0) {
if (config.effects) {
int snd = playSound(_sfx[kSndDoor]);
setChannelVolume(snd, config.effectsVol);
}
loadMap(tmap);
swash();
}
}
}
for (int i = 0; i < kMaxFloat; i++) {
_floatText[i].framesLeft = 0;
_floatIcon[i].framesLeft = 0;
}
}
} // end of namespace Griffon

2354
engines/griffon/logic.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,172 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "base/plugins.h"
#include "common/config-manager.h"
#include "common/translation.h"
#include "engines/advancedDetector.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymap.h"
#include "backends/keymapper/standard-actions.h"
#include "griffon/griffon.h"
#include "griffon/detection.h"
#ifdef USE_TTS
static const ADExtraGuiOptionsMap optionsList[] = {
{
GAMEOPTION_TTS_NARRATOR,
{
_s("Enable Text to Speech"),
_s("Use TTS to read the descriptions (if TTS is available)"),
"tts_enabled",
false,
0,
0
}
},
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
#endif
class GriffonMetaEngine: public AdvancedMetaEngine<ADGameDescription> {
public:
const char *getName() const override {
return "griffon";
}
#ifdef USE_TTS
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
return optionsList;
}
#endif
int getMaximumSaveSlot() const override {
return ConfMan.getInt("autosave_period") ? 4 : 3;
}
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
int getAutosaveSlot() const override {
return 4;
}
Common::String getSavegameFile(int saveGameIdx, const char *target = nullptr) const override;
Common::KeymapArray initKeymaps(const char *target) const override;
};
Common::String GriffonMetaEngine::getSavegameFile(int saveGameIdx, const char *target) const {
if (saveGameIdx == kSavegameFilePattern) {
// Pattern requested
return Common::String::format("%s.s##", target == nullptr ? getName() : target);
} else {
// Specific filename requested
return Common::String::format("%s.s%02d", target == nullptr ? getName() : target, saveGameIdx);
}
}
bool Griffon::GriffonEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
Common::Error GriffonMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
*engine = new Griffon::GriffonEngine(syst);
return Common::kNoError;
}
Common::KeymapArray GriffonMetaEngine::initKeymaps(const char *target) const {
using namespace Common;
Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "griffon", "The Griffon Legend");
Action *act;
act = new Action(kStandardActionSkip, _("Menu / Skip"));
act->setCustomEngineActionEvent(Griffon::kGriffonMenu);
act->addDefaultInputMapping("ESCAPE");
act->addDefaultInputMapping("JOY_Y");
engineKeyMap->addAction(act);
act = new Action("RETURN", _("Confirm"));
act->setCustomEngineActionEvent(Griffon::kGriffonConfirm);
act->addDefaultInputMapping("RETURN");
act->addDefaultInputMapping("JOY_X");
engineKeyMap->addAction(act);
act = new Action(kStandardActionMoveUp, _("Up"));
act->setCustomEngineActionEvent(Griffon::kGriffonUp);
act->addDefaultInputMapping("UP");
act->addDefaultInputMapping("JOY_UP");
engineKeyMap->addAction(act);
act = new Action(kStandardActionMoveDown, _("Down"));
act->setCustomEngineActionEvent(Griffon::kGriffonDown);
act->addDefaultInputMapping("DOWN");
act->addDefaultInputMapping("JOY_DOWN");
engineKeyMap->addAction(act);
act = new Action(kStandardActionMoveLeft, _("Left"));
act->setCustomEngineActionEvent(Griffon::kGriffonLeft);
act->addDefaultInputMapping("LEFT");
act->addDefaultInputMapping("JOY_LEFT");
engineKeyMap->addAction(act);
act = new Action(kStandardActionMoveRight, _("Right"));
act->setCustomEngineActionEvent(Griffon::kGriffonRight);
act->addDefaultInputMapping("RIGHT");
act->addDefaultInputMapping("JOY_RIGHT");
engineKeyMap->addAction(act);
act = new Action("ATTACK", _("Attack"));
act->setCustomEngineActionEvent(Griffon::kGriffonAttack);
act->addDefaultInputMapping("LCTRL");
act->addDefaultInputMapping("RCTRL");
act->addDefaultInputMapping("JOY_A");
engineKeyMap->addAction(act);
act = new Action("INVENTORY", _("Inventory"));
act->setCustomEngineActionEvent(Griffon::kGriffonInventory);
act->addDefaultInputMapping("LALT");
act->addDefaultInputMapping("RALT");
act->addDefaultInputMapping("JOY_B");
engineKeyMap->addAction(act);
act = new Action("SPEEDUP", _("Speed up cutscene"));
act->setCustomEngineActionEvent(Griffon::kGriffonCutsceneSpeedUp);
act->addDefaultInputMapping("LSHIFT");
act->addDefaultInputMapping("RSHIFT");
engineKeyMap->addAction(act);
return Keymap::arrayOf(engineKeyMap);
}
#if PLUGIN_ENABLED_DYNAMIC(GRIFFON)
REGISTER_PLUGIN_DYNAMIC(GRIFFON, PLUGIN_TYPE_ENGINE, GriffonMetaEngine);
#else
REGISTER_PLUGIN_STATIC(GRIFFON, PLUGIN_TYPE_ENGINE, GriffonMetaEngine);
#endif

31
engines/griffon/module.mk Normal file
View File

@@ -0,0 +1,31 @@
MODULE := engines/griffon
MODULE_OBJS := \
combat.o \
console.o \
cutscenes.o \
dialogs.o \
draw.o \
engine.o \
gfx.o \
griffon.o \
input.o \
logic.o \
metaengine.o \
resources.o \
saveload.o \
sound.o
MODULE_DIRS += \
engines/griffon
# This module can be built as a plugin
ifeq ($(ENABLE_GRIFFON), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,258 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "griffon/griffon.h"
#include "common/savefile.h"
#include "engines/metaengine.h"
namespace Griffon {
#define PRINT(A,B) \
do { \
char line[256]; \
Common::sprintf_s(line, A "\n", B); \
file->write(line, strlen(line)); \
} while(0)
#define INPUT(A, B) \
do { \
Common::String line; \
line = file->readLine(); \
sscanf(line.c_str(), A, B); \
} while(0)
Common::String GriffonEngine::getSaveStateName(int slot) const {
return (_targetName + Common::String::format(".s%02d", slot));
}
Common::Error GriffonEngine::loadGameState(int slot) {
Common::Error result = Engine::loadGameState(slot);
if (result.getCode() == Common::kNoError) {
_saveSlot = slot;
_gameMode = kGameModeLoadGame;
}
return result;
}
Common::Error GriffonEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
Common::String saveDesc = Common::String::format("Level: %d Map: %d", _player.level, _curMap);
return Engine::saveGameState(slot, isAutosave ? desc : saveDesc, isAutosave);
}
Common::Error GriffonEngine::loadGameStream(Common::SeekableReadStream *file) {
INPUT("%i", &_player.level);
if (_player.level > 0) {
char temp[256];
INPUT("%i", &_secStart);
INPUT("%s", temp);
INPUT("%f", &_player.px);
INPUT("%f", &_player.py);
INPUT("%f", &_player.opx);
INPUT("%f", &_player.opy);
INPUT("%i", &_player.walkDir);
INPUT("%f", &_player.walkFrame);
INPUT("%f", &_player.walkSpeed);
INPUT("%f", &_player.attackFrame);
INPUT("%f", &_player.attackSpeed);
INPUT("%i", &_player.hp);
INPUT("%i", &_player.maxHp);
INPUT("%f", &_player.hpflash);
INPUT("%i", &_player.level);
INPUT("%i", &_player.maxLevel);
INPUT("%i", &_player.sword);
INPUT("%i", &_player.shield);
INPUT("%i", &_player.armour);
for (int i = 0; i < 5; i++) {
INPUT("%i", &_player.foundSpell[i]);
INPUT("%f", &_player.spellCharge[i]);
}
for (int a = 0; a < 5; a++) {
INPUT("%i", &_player.inventory[a]);
}
INPUT("%f", &_player.attackStrength);
INPUT("%i", &_player.spellDamage);
INPUT("%i", &_player.swordDamage);
INPUT("%i", &_player.exp);
INPUT("%i", &_player.nextLevel);
for (int a = 0; a <= 99; a++) {
for (int b = 0; b <= 9; b++) {
INPUT("%i", &_scriptFlag[a][b]);
}
}
INPUT("%i", &_curMap);
for (int a = 0; a <= 999; a++) {
for (int b = 0; b <= 20; b++) {
for (int c = 0; c <= 14; c++) {
INPUT("%i", &_objectMapFull[a][b][c]);
}
}
}
for (int a = 0; a <= 200; a++) {
INPUT("%i", &_roomLocks[a]);
}
INPUT("%f", &_player.spellStrength);
return Common::kNoError;
}
return Common::kReadingFailed;
}
/* fill PLAYERTYPE _playera; */
int GriffonEngine::loadPlayer(int slotnum) {
Common::String filename = getSaveStateName(slotnum);
Common::InSaveFile *file;
_playera.level = 0;
if (!(file = _saveFileMan->openForLoading(filename)))
return 0;
INPUT("%i", &_playera.level);
if (_playera.level > 0) {
char temp[256];
INPUT("%i", &_asecstart);
INPUT("%s", temp);
INPUT("%f", &_playera.px);
INPUT("%f", &_playera.py);
INPUT("%f", &_playera.opx);
INPUT("%f", &_playera.opy);
INPUT("%i", &_playera.walkDir);
INPUT("%f", &_playera.walkFrame);
INPUT("%f", &_playera.walkSpeed);
INPUT("%f", &_playera.attackFrame);
INPUT("%f", &_playera.attackSpeed);
INPUT("%i", &_playera.hp);
INPUT("%i", &_playera.maxHp);
INPUT("%f", &_playera.hpflash);
INPUT("%i", &_playera.level);
INPUT("%i", &_playera.maxLevel);
INPUT("%i", &_playera.sword);
INPUT("%i", &_playera.shield);
INPUT("%i", &_playera.armour);
for (int i = 0; i < 5; i++) {
INPUT("%i", &_playera.foundSpell[i]);
INPUT("%f", &_playera.spellCharge[i]);
}
for (int a = 0; a < 5; a++) {
INPUT("%i", &_playera.inventory[a]);
}
INPUT("%f", &_playera.attackStrength);
INPUT("%i", &_playera.spellDamage);
INPUT("%i", &_playera.swordDamage);
INPUT("%i", &_playera.exp);
INPUT("%i", &_playera.nextLevel);
return 1; // success
}
return 0; // fail
}
Common::Error GriffonEngine::saveGameStream(Common::WriteStream *file, bool) {
PRINT("%i", _player.level);
if (_player.level > 0) {
PRINT("%i", (_secStart + _secsInGame));
PRINT("%s", "a");
PRINT("%f", _player.px);
PRINT("%f", _player.py);
PRINT("%f", _player.opx);
PRINT("%f", _player.opy);
PRINT("%i", _player.walkDir);
PRINT("%f", _player.walkFrame);
PRINT("%f", _player.walkSpeed);
PRINT("%f", _player.attackFrame);
PRINT("%f", _player.attackSpeed);
PRINT("%i", _player.hp);
PRINT("%i", _player.maxHp);
PRINT("%f", _player.hpflash);
PRINT("%i", _player.level);
PRINT("%i", _player.maxLevel);
PRINT("%i", _player.sword);
PRINT("%i", _player.shield);
PRINT("%i", _player.armour);
for (int i = 0; i < 5; i++) {
PRINT("%i", _player.foundSpell[i]);
PRINT("%f", _player.spellCharge[i]);
}
for (int a = 0; a < 5; a++) {
PRINT("%i", _player.inventory[a]);
}
PRINT("%f", _player.attackStrength);
PRINT("%i", _player.spellDamage);
PRINT("%i", _player.swordDamage);
PRINT("%i", _player.exp);
PRINT("%i", _player.nextLevel);
for (int a = 0; a <= 99; a++) {
for (int b = 0; b <= 9; b++) {
PRINT("%i", _scriptFlag[a][b]);
}
}
PRINT("%i", _curMap);
for (int a = 0; a <= 999; a++) {
for (int b = 0; b <= 20; b++) {
for (int c = 0; c <= 14; c++) {
PRINT("%i", _objectMapFull[a][b][c]);
}
}
}
for (int a = 0; a <= 200; a++) {
PRINT("%i", _roomLocks[a]);
}
PRINT("%f", _player.spellStrength);
}
drawView();
return Common::kNoError;
}
} // end of namespace Griffon

249
engines/griffon/sound.cpp Normal file
View File

@@ -0,0 +1,249 @@
/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*
* Originally written by Syn9 in FreeBASIC with SDL
* http://syn9.thehideoutgames.com/index_backup.php
*
* Ported to plain C for GCW-Zero handheld by Dmitry Smagin
* http://github.com/dmitrysmagin/griffon_legend
*
*
* Programming/Graphics: Daniel "Syn9" Kennedy
* Music/Sound effects: David Turner
*
* Beta testing and gameplay design help:
* Deleter, Cha0s, Aether Fox, and Kiz
*
*/
#include "audio/audiostream.h"
#include "audio/decoders/vorbis.h"
#include "common/memstream.h"
#include "common/file.h"
#include "common/system.h"
#include "griffon/griffon.h"
namespace Griffon {
void GriffonEngine::setChannelVolume(int channel, int volume) {
if (channel >= 0 && channel < kSoundHandles)
_mixer->setChannelVolume(_handles[channel], volume);
}
int GriffonEngine::getSoundHandle() {
for (uint i = 0; i < kSoundHandles; i++) {
if (!_mixer->isSoundHandleActive(_handles[i])) {
return i;
}
}
return -1;
}
int GriffonEngine::playSound(DataChunk *chunk, bool looped) {
int ch = -1;
#ifdef USE_VORBIS
if ((ch = getSoundHandle()) != -1) {
Audio::SeekableAudioStream *audioStream = Audio::makeVorbisStream(new Common::MemoryReadStream(chunk->data, chunk->size), DisposeAfterUse::YES);
if (looped) {
Audio::AudioStream *loopingStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_handles[ch], loopingStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, false, false);
} else {
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_handles[ch], audioStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES, false, false);
}
}
#endif // USE_VORBIS
return ch;
}
void GriffonEngine::pauseSoundChannel(int channel) {
if (channel >= 0 && channel < kSoundHandles)
_mixer->pauseHandle(_handles[channel], true);
}
void GriffonEngine::haltSoundChannel(int channel) {
if (channel == -1) {
for (int i = 0; i < kSoundHandles; i++)
_mixer->stopHandle(_handles[i]);
} else if (channel >= 0 && channel < kSoundHandles) {
_mixer->stopHandle(_handles[channel]);
}
}
void GriffonEngine::resumeSoundChannel(int channel) {
if (channel >= 0 && channel < kSoundHandles)
_mixer->pauseHandle(_handles[channel], false);
}
bool GriffonEngine::isSoundChannelPlaying(int channel) {
return (channel >= 0 && channel < kSoundHandles) ? _mixer->isSoundHandleActive(_handles[channel]) : false;
}
DataChunk *cacheSound(const char *name) {
Common::File file;
DataChunk *res = new DataChunk;
file.open(name);
if (!file.isOpen())
error("Cannot open file %s", name);
res->size = file.size();
res->data = (byte *)malloc(res->size);
file.read(res->data, res->size);
return res;
}
void GriffonEngine::setupAudio() {
const char *stri = "Loading...";
drawString(_videoBuffer, stri, 160 - 4 * strlen(stri), 116, 0);
Graphics::ManagedSurface *loadimg = loadImage("art/load.bmp", true);
rcSrc.left = 0;
rcSrc.top = 0;
rcSrc.setWidth(88);
rcSrc.setHeight(32);
rcDest.left = 160 - 44;
rcDest.top = 116 + 12;
loadimg->blendBlitTo(*_videoBuffer, rcDest.left, rcDest.top, Graphics::FLIP_NONE, &rcSrc, MS_ARGB(160, 255, 255, 255));
g_system->copyRectToScreen(_videoBuffer->getPixels(), _videoBuffer->pitch, 0, 0, _videoBuffer->w, _videoBuffer->h);
g_system->updateScreen();
rcDest.left = 160 - 44 + 7;
rcDest.top = 116 + 12 + 12;
rcDest.setHeight(8);
_musicBoss = cacheSound("music/boss.ogg");
drawProgress(1, 21);
_musicGardens1 = cacheSound("music/gardens.ogg");
drawProgress(2, 21);
_musicGardens2 = cacheSound("music/gardens2.ogg");
drawProgress(3, 21);
_musicGardens3 = cacheSound("music/gardens3.ogg");
drawProgress(4, 21);
_musicGardens4 = cacheSound("music/gardens4.ogg");
drawProgress(5, 21);
_musicEndOfGame = cacheSound("music/endofgame.ogg");
drawProgress(6, 21);
_musicMenu = cacheSound("music/menu.ogg");
drawProgress(7, 21);
_sfx[kSndBite] = cacheSound("sfx/bite.ogg");
drawProgress(8, 21);
_sfx[kSndCrystal] = cacheSound("sfx/crystal.ogg");
drawProgress(9, 21);
_sfx[kSndDoor] = cacheSound("sfx/door.ogg");
drawProgress(10, 21);
_sfx[kSndEnemyHit] = cacheSound("sfx/enemyhit.ogg");
drawProgress(11, 21);
_sfx[kSndIce] = cacheSound("sfx/ice.ogg");
drawProgress(12, 21);
_sfx[kSndLever] = cacheSound("sfx/lever.ogg");
drawProgress(13, 21);
_sfx[kSndLightning] = cacheSound("sfx/lightning.ogg");
drawProgress(14, 21);
_sfx[kSndMetalHit] = cacheSound("sfx/metalhit.ogg");
drawProgress(15, 21);
_sfx[kSndPowerUp] = cacheSound("sfx/powerup.ogg");
drawProgress(16, 21);
_sfx[kSndRocks] = cacheSound("sfx/rocks.ogg");
drawProgress(17, 21);
_sfx[kSndSwordHit] = cacheSound("sfx/swordhit.ogg");
drawProgress(18, 21);
_sfx[kSndThrow] = cacheSound("sfx/throw.ogg");
drawProgress(19, 21);
_sfx[kSndChest] = cacheSound("sfx/chest.ogg");
drawProgress(20, 21);
_sfx[kSndFire] = cacheSound("sfx/fire.ogg");
drawProgress(21, 21);
_sfx[kSndBeep] = cacheSound("sfx/beep.ogg");
}
void GriffonEngine::updateMusic() {
static int loopseta = 0;
DataChunk *iplaysound = nullptr;
if (config.music) {
// if(_curmap > 5 && _curmap < 42) iplaysound = macademy;
// if(_curmap > 47) iplaysound = _mgardens;
iplaysound = _musicGardens1;
if (_roomLock)
iplaysound = _musicBoss;
if (iplaysound == _musicBoss && _playingBoss)
iplaysound = nullptr;
if (iplaysound == _musicGardens1 && _playingGardens)
iplaysound = nullptr;
if (iplaysound != nullptr) {
haltSoundChannel(_musicChannel);
_playingBoss = (iplaysound == _musicBoss);
_playingGardens = (iplaysound == _musicGardens1);
_musicChannel = playSound(iplaysound, true);
setChannelVolume(_musicChannel, config.musicVol);
} else {
if (!isSoundChannelPlaying(_musicChannel)) {
loopseta += 1;
if (loopseta == 4)
loopseta = 0;
if (_playingGardens) {
haltSoundChannel(_musicChannel);
if (_playingGardens) {
switch (loopseta) {
case 0:
playSound(_musicGardens1);
break;
case 1:
playSound(_musicGardens2);
break;
case 2:
playSound(_musicGardens3);
break;
case 3:
playSound(_musicGardens4);
default:
break;
}
}
}
setChannelVolume(_musicChannel, config.musicVol);
}
}
}
}
} // end of namespace Griffon