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/got/POTFILES Normal file
View File

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

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]
add_engine got "Got" yes "" "" ""

187
engines/got/console.cpp Normal file
View File

@@ -0,0 +1,187 @@
/* 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 "got/console.h"
#include "common/savefile.h"
#include "common/system.h"
#include "got/events.h"
#include "got/got.h"
#include "got/vars.h"
namespace Got {
static const char *SAVE_FILENAMES[3] = {
"savegam1.got", "savegam1.gt2", "savegam1.gt3"};
Console::Console() : GUI::Debugger() {
registerCmd("view", WRAP_METHOD(Console, cmdView));
registerCmd("sound", WRAP_METHOD(Console, cmdSound));
registerCmd("music", WRAP_METHOD(Console, cmdMusic));
registerCmd("load", WRAP_METHOD(Console, cmdLoad));
registerCmd("save", WRAP_METHOD(Console, cmdSave));
registerCmd("magic", WRAP_METHOD(Console, cmdMagic));
registerCmd("freeze", WRAP_METHOD(Console, cmdFreeze));
registerCmd("level", WRAP_METHOD(Console, cmdLevel));
registerCmd("flying", WRAP_METHOD(Console, cmdFlying));
registerCmd("flag", WRAP_METHOD(Console, cmdFlag));
}
Console::~Console() {
}
bool Console::cmdView(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("view <view name>\n");
return true;
}
g_events->replaceView(argv[1], true);
return false;
}
bool Console::cmdSound(int argc, const char **argv) {
if (argc == 2)
_G(sound).playSound(atoi(argv[1]), true);
return false;
}
bool Console::cmdMusic(int argc, const char **argv) {
if (argc == 2)
_G(sound).musicPlay(atoi(argv[1]), true);
return false;
}
bool Console::cmdLoad(int argc, const char **argv) {
Common::String filename = SAVE_FILENAMES[_G(area) - 1];
if (argc == 2)
filename = argv[1];
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
if (f == nullptr) {
debugPrintf("Could not open %s\n", filename.c_str());
return true;
}
Common::Serializer s(f, nullptr);
g_engine->syncGame(s);
delete f;
return false;
}
bool Console::cmdSave(int argc, const char **argv) {
Common::String filename = SAVE_FILENAMES[_G(area) - 1];
if (argc == 2)
filename = argv[1];
Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(filename, false);
if (f == nullptr) {
debugPrintf("Could not create %s\n", filename.c_str());
} else {
Common::Serializer s(nullptr, f);
g_engine->syncGame(s);
delete f;
debugPrintf("Created %s\n", filename.c_str());
}
return true;
}
bool Console::cmdMagic(int argc, const char **argv) {
_G(thorInfo)._magic = (argc == 2) ? CLIP(atoi(argv[1]), 0, 150) : 150;
return false;
}
bool Console::cmdFreeze(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("freeze ['health', 'magic', 'gems']\n");
} else if (!strcmp(argv[1], "health")) {
_G(cheats)._freezeHealth = !_G(cheats)._freezeHealth;
debugPrintf("Health is %s\n", _G(cheats)._freezeHealth ? "frozen" : "unfrozen");
} else if (!strcmp(argv[1], "magic")) {
_G(cheats)._freezeMagic = !_G(cheats)._freezeMagic;
debugPrintf("Magic is %s\n", _G(cheats)._freezeMagic ? "frozen" : "unfrozen");
} else if (!strcmp(argv[1], "jewels")) {
_G(cheats)._freezeJewels = !_G(cheats)._freezeJewels;
debugPrintf("Jewels are %s\n", _G(cheats)._freezeJewels ? "frozen" : "unfrozen");
} else if (!strcmp(argv[1], "all")) {
_G(cheats)._freezeHealth = _G(cheats)._freezeMagic =
_G(cheats)._freezeJewels = !_G(cheats)._freezeHealth;
debugPrintf("All are %s\n", _G(cheats)._freezeHealth ? "frozen" : "unfrozen");
}
return true;
}
bool Console::cmdLevel(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("Current level = %d\n", _G(currentLevel));
return true;
}
_G(newLevel) = atoi(argv[1]);
_G(warpFlag) = true;
return false;
}
bool Console::cmdFlying(int argc, const char **argv) {
_G(thor)->_flying = !_G(thor)->_flying;
debugPrintf("Flying is %s\n", _G(thor)->_flying ? "on" : "off");
return true;
}
bool Console::cmdFlag(int argc, const char **argv) {
if (argc == 1) {
for (int start = 0; start < 64; start += 10) {
Common::String line;
for (int i = start; i < (start == 60 ? 64 : (start + 10)); ++i) {
if ((i % 5) == 0)
line += " ";
line += Common::String::format("%c",
_G(setup)._flags[i] ? 'T' : 'F');
}
debugPrintf("%s\n", line.c_str());
}
} else {
int flag = atoi(argv[1]);
if (flag < 1 || flag > 64) {
debugPrintf("Flags must be from 1 to 64\n");
} else if (argc == 2) {
debugPrintf("Flag #%d is %s\n", flag,
_G(setup)._flags[flag - 1] ? "true" : "false");
} else {
bool val = tolower(argv[2][0]) == 't';
_G(setup)._flags[flag - 1] = val;
debugPrintf("Flag #%d is %s\n", flag,
val ? "true" : "false");
}
}
return true;
}
} // namespace Got

50
engines/got/console.h Normal file
View File

@@ -0,0 +1,50 @@
/* 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 GOT_CONSOLE_H
#define GOT_CONSOLE_H
#include "gui/debugger.h"
namespace Got {
class Console : public GUI::Debugger {
private:
bool cmdView(int argc, const char **argv);
bool cmdSound(int argc, const char **argv);
bool cmdMusic(int argc, const char **argv);
bool cmdLoad(int argc, const char **argv);
bool cmdSave(int argc, const char **argv);
bool cmdMagic(int argc, const char **argv);
bool cmdFreeze(int argc, const char **argv);
bool cmdLevel(int argc, const char **argv);
bool cmdFlying(int argc, const char **argv);
bool cmdFlag(int argc, const char **argv);
public:
Console();
~Console() override;
};
} // End of namespace Got
#endif // GOT_CONSOLE_H

5
engines/got/credits.pl Normal file
View File

@@ -0,0 +1,5 @@
begin_section("Got");
add_person("Paul Gilbert", "DreamMaster", "");
add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
add_person("Coen Rampen", "NMIError", "");
end_section();

149
engines/got/data/actor.cpp Normal file
View File

@@ -0,0 +1,149 @@
/* 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 "got/data/actor.h"
#include "common/algorithm.h"
#include "common/memstream.h"
namespace Got {
void Actor::loadFixed(Common::SeekableReadStream *src) {
_moveType = src->readByte();
_width = src->readByte();
_height = src->readByte();
_directions = src->readByte();
_framesPerDirection = src->readByte();
_frameSpeed = src->readByte();
src->read(_frameSequence, 4);
_speed = src->readByte();
_sizeX = src->readByte();
_sizeY = src->readByte();
_hitStrength = src->readByte();
_health = src->readByte();
_numMoves = src->readByte();
_shotType = src->readByte();
_shotPattern = src->readByte();
_numShotsAllowed = src->readByte();
_solid = src->readByte();
_flying = src->readByte() == 1;
_dropRating = src->readByte();
_type = src->readByte();
src->read(_name, 9);
_funcNum = src->readByte();
_funcPass = src->readByte();
_magicHurts = src->readSint16LE();
src->skip(4);
}
void Actor::loadFixed(const byte *src) {
Common::MemoryReadStream stream(src, 40);
loadFixed(&stream);
}
void Actor::copyFixedAndPics(const Actor &src) {
_moveType = src._moveType;
_width = src._width;
_height = src._height;
_directions = src._directions;
_framesPerDirection = src._framesPerDirection;
_frameSpeed = src._frameSpeed;
Common::copy(src._frameSequence, src._frameSequence + 4, _frameSequence);
_speed = src._speed;
_sizeX = src._sizeX;
_sizeY = src._sizeY;
_hitStrength = src._hitStrength;
_health = src._health;
_numMoves = src._numMoves;
_shotType = src._shotType;
_shotPattern = src._shotPattern;
_numShotsAllowed = src._numShotsAllowed;
_solid = src._solid;
_flying = src._flying;
_dropRating = src._dropRating;
_type = src._type;
Common::copy(src._name, src._name + 9, _name);
_funcNum = src._funcNum;
_funcPass = src._funcPass;
_magicHurts = src._magicHurts;
// Copy all the surfaces for all the directions over
for (int d = 0; d < DIRECTION_COUNT; ++d) {
for (int f = 0; f < FRAME_COUNT; ++f)
pic[d][f].copyFrom(src.pic[d][f]);
}
}
Actor &Actor::operator=(const Actor &src) {
// First copy the fixed portion and the pics
copyFixedAndPics(src);
// Copy temporary fields
_frameCount = src._frameCount;
_dir = src._dir;
_lastDir = src._lastDir;
_x = src._x;
_y = src._y;
_center = src._center;
Common::copy(src._lastX, src._lastX + 2, _lastX);
Common::copy(src._lastY, src._lastY + 2, _lastY);
_active = src._active;
_nextFrame = src._nextFrame;
_moveCountdown = src._moveCountdown;
_vulnerableCountdown = src._vulnerableCountdown;
_shotCountdown = src._shotCountdown;
_currNumShots = src._currNumShots;
_creator = src._creator;
_unpauseCountdown = src._unpauseCountdown;
_actorNum = src._actorNum;
_moveCount = src._moveCount;
_dead = src._dead;
_toggle = src._toggle;
_centerX = src._centerX;
_centerY = src._centerY;
_show = src._show;
_temp1 = src._temp1;
_temp2 = src._temp2;
_counter = src._counter;
_moveCounter = src._moveCounter;
_edgeCounter = src._edgeCounter;
_temp3 = src._temp3;
_temp4 = src._temp4;
_temp5 = src._temp5;
_hitThor = src._hitThor;
_rand = src._rand;
_initDir = src._initDir;
_passValue = src._passValue;
_shotActor = src._shotActor;
_magicHit = src._magicHit;
_temp6 = src._temp6;
_i1 = src._i1;
_i2 = src._i2;
_i3 = src._i3;
_i4 = src._i4;
_i5 = src._i5;
_i6 = src._i6;
_initHealth = src._initHealth;
_talkCounter = src._talkCounter;
return *this;
}
} // namespace Got

123
engines/got/data/actor.h Normal file
View File

@@ -0,0 +1,123 @@
/* 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 GOT_DATA_ACTOR_H
#define GOT_DATA_ACTOR_H
#include "common/stream.h"
#include "graphics/managed_surface.h"
namespace Got {
#define DIRECTION_COUNT 4
#define FRAME_COUNT 4
struct Actor {
// First part loaded from disk
byte _moveType = 0; // Movement pattern (0=none)
byte _width = 0; // Physical width
byte _height = 0; // Physical height
byte _directions = 0; // 1, 2 or 4 (1=uni-directional)
byte _framesPerDirection = 0; // # frames per direction
byte _frameSpeed = 0; // # cycles between frame changes
byte _frameSequence[4] = {}; // Sequence
byte _speed = 0; // Move every Nth cycle
byte _sizeX = 0; // Non-physical padding on X coordinate
byte _sizeY = 0; // Non-physical padding on Y coordinate
byte _hitStrength = 0; // Hit strength
byte _health = 0; //
byte _numMoves = 0; // # of moves every <_speed> cycles
byte _shotType = 0; // Actor # of shot
byte _shotPattern = 0; // Func number to decide to shoot
byte _numShotsAllowed = 0; // # shots allowed on screen
byte _solid = 0; // 1=solid (not ghost,etc)
bool _flying = false; //
byte _dropRating = 0; // rnd(100) < _dropRating = jewel
byte _type = 0; // Actor (0 = thor, 1 = hammer, 2 = enemy, 3 = shot)
char _name[9] = {}; // Actors name
byte _funcNum = 0; // Special function when thor touches
byte _funcPass = 0; // Value to pass to func
uint16 _magicHurts = 0; // Bitwise magic hurts flags
// The rest is dynamic //size=216
// Direction/frame surfaces
Graphics::ManagedSurface pic[DIRECTION_COUNT][FRAME_COUNT];
byte _frameCount = 0; // Count to switch frames
byte _dir = 0; // Direction of travel
byte _lastDir = 0; // Last direction of travel
int _x = 0; // Actual X coordinate
int _y = 0; // Actual Y coordinate
int _center = 0; // Center of object
int _lastX[2] = {}; // Last X coordinate on each page
int _lastY[2] = {}; // Last Y coordinate on each page
bool _active = false; // true=active, false=not active
byte _nextFrame = 0; // Next frame to be shown
byte _moveCountdown = 0; // Count down to movement
byte _vulnerableCountdown = 0; // Count down to vulnerability
byte _shotCountdown = 0; // Count down to another shot
byte _currNumShots = 0; // # of shots currently on screen
byte _creator = 0; // Which actor # created this actor
byte _unpauseCountdown = 0; // Must be 0 to move
byte _actorNum = 0;
byte _moveCount = 0;
byte _dead = 0;
byte _toggle = 0;
byte _centerX = 0;
byte _centerY = 0;
byte _show = 0; // Display or not (for blinking)
byte _temp1 = 0;
byte _temp2 = 0;
byte _counter = 0;
byte _moveCounter = 0;
byte _edgeCounter = 0;
byte _temp3 = 0;
byte _temp4 = 0;
byte _temp5 = 0;
bool _hitThor = false;
int _rand = 0;
byte _initDir = 0;
byte _passValue = 0;
byte _shotActor = 0;
byte _magicHit = 0;
byte _temp6 = 0;
int _i1 = 0, _i2 = 0, _i3 = 0, _i4 = 0, _i5 = 0, _i6 = 0;
byte _initHealth = 0;
byte _talkCounter = 0;
void loadFixed(Common::SeekableReadStream *src);
void loadFixed(const byte *src);
/**
* Copies the fixed portion and pics from a source actor.
*/
void copyFixedAndPics(const Actor &src);
Actor &operator=(const Actor &src);
int getPos() const {
return ((_x + 7) / 16) + (((_y + 8) / 16) * 20);
}
};
} // namespace Got
#endif

View File

@@ -0,0 +1,72 @@
/* 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 GOT_DATA_DEFINES_H
#define GOT_DATA_DEFINES_H
#include "common/scummsys.h"
#include "common/serializer.h"
#include "got/data/actor.h"
namespace Got {
struct Header {
long _offset = 0;
long _length = 0;
void load(Common::SeekableReadStream *src) {
_offset = src->readUint32LE();
_length = src->readUint32LE();
}
};
//==========================================================================
// Defines
#define MAX_ACTORS 35
#define MAX_ENEMIES 16
#define STAMINA 20
#define GOT_Z 44
#define GOT_B 48
#define TMP_SIZE 5800
#define GAME1 (_G(area) == 1)
#define GAME2 (_G(area) == 2)
#define GAME3 (_G(area) == 3)
#define APPLE_MAGIC 1
#define LIGHTNING_MAGIC 2
#define BOOTS_MAGIC 4
#define WIND_MAGIC 8
#define SHIELD_MAGIC 16
#define THUNDER_MAGIC 32
#define BOSS_LEVEL1 59
#define BOSS_LEVEL2 60
#define BOSS_LEVEL3 95
#define ENDING_SCREEN 106
#define DEMO_LEN 3600
} // namespace Got
#endif

33
engines/got/data/flags.h Normal file
View File

@@ -0,0 +1,33 @@
/* 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 GOT_DATA_FLAGS_H
#define GOT_DATA_FLAGS_H
#include "got/data/defines.h"
namespace Got {
#define HERMIT_HAS_DOLL _G(setup).f04
} // namespace Got
#endif

View File

@@ -0,0 +1,106 @@
/* 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 "common/file.h"
#include "common/savefile.h"
#include "common/system.h"
#include "got/data/highscores.h"
#include "got/got.h"
namespace Got {
static const char *DEFAULT_NAMES[HIGH_SCORES_PER_AREA] = {
"Ron Davis", "Gary Sirois", "Adam Pedersen", "Jason Blochowiak",
"Roy Davis", "Wayne Timmerman", "Dan Linton"};
void HighScore::sync(Common::Serializer &s) {
s.syncAsUint16LE(_unused);
s.syncAsUint32LE(_total);
s.syncBytes((byte *)_name, 32);
}
void HighScores::sync(Common::Serializer &s) {
for (int area = 0; area < 3; ++area) {
for (int num = 0; num < HIGH_SCORES_PER_AREA; ++num)
_scores[area][num].sync(s);
}
}
void HighScores::load() {
Common::File f;
const Common::String scoresName = g_engine->getHighScoresSaveName();
Common::InSaveFile *sf = g_system->getSavefileManager()->openForLoading(scoresName);
if (sf != nullptr) {
// ScummVM high scores data present
Common::Serializer s(sf, nullptr);
sync(s);
delete sf;
} else if (f.open("config.got")) {
// Otherwise fall back on original generated config.got
f.seek(0x32);
Common::Serializer s(&f, nullptr);
sync(s);
} else {
// Generate new data
for (int area = 0; area < 3; ++area) {
for (int num = 0; num < HIGH_SCORES_PER_AREA; ++num)
_scores[area][num] = HighScore(DEFAULT_NAMES[num], 10000 - (num * 1000));
}
}
}
void HighScores::save() {
Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(g_engine->getHighScoresSaveName());
if (!sf)
error("Error creating high scores save file");
Common::Serializer s(nullptr, sf);
sync(s);
sf->finalize();
delete sf;
}
void HighScores::add(const int area, const Common::String &name, const uint total) {
// Find the index for the new score in the list
int newIndex;
for (newIndex = 0; newIndex < HIGH_SCORES_PER_AREA && total < _scores[area - 1][newIndex]._total; ++newIndex) {
}
if (newIndex == HIGH_SCORES_PER_AREA)
// Lower than all current scores, so ignore it
return;
// Shift any lower scores to make space
for (int i = HIGH_SCORES_PER_AREA - 1; i > newIndex; --i)
_scores[area - 1][i] = _scores[area - 1][i - 1];
// Insert in new score
HighScore &hs = _scores[area - 1][newIndex];
Common::fill(hs._name, hs._name + 32, 0);
Common::strcpy_s(hs._name, name.c_str());
hs._total = total;
// Save the resulting table
save();
}
} // namespace Got

View File

@@ -0,0 +1,57 @@
/* 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 GOT_DATA_HIGH_SCORE_H
#define GOT_DATA_HIGH_SCORE_H
#include "common/serializer.h"
namespace Got {
#define HIGH_SCORES_PER_AREA 7
struct HighScore {
uint16 _unused = 0;
uint32 _total = 0;
char _name[32] = {};
HighScore() {}
HighScore(const char *name, uint32 total) : _total(total) {
Common::strcpy_s(_name, name);
}
void sync(Common::Serializer &s);
};
struct HighScores {
private:
void sync(Common::Serializer &s);
public:
HighScore _scores[3][HIGH_SCORES_PER_AREA];
void load();
void save();
void add(int area, const Common::String &name, uint total);
};
} // namespace Got
#endif

View File

@@ -0,0 +1,69 @@
/* 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 "common/algorithm.h"
#include "common/memstream.h"
#include "got/data/defines.h"
#include "got/vars.h"
namespace Got {
void Level::sync(Common::Serializer &s) {
for (int i = 0; i < 12; ++i)
s.syncBytes(_iconGrid[i], 20);
s.syncAsByte(_backgroundColor);
s.syncAsByte(_music);
s.syncBytes(_actorType, 16);
s.syncBytes(_actorLoc, 16);
s.syncBytes(_actorValue, 16);
s.syncBytes(_palColors, 3);
s.syncBytes(_actorInvis, 16);
s.syncBytes(_extra, 13);
s.syncBytes(_staticObject, 30);
for (int i = 0; i < 30; ++i)
s.syncAsSint16LE(_staticX[i]);
for (int i = 0; i < 30; ++i)
s.syncAsSint16LE(_staticY[i]);
s.syncBytes(_newLevel, 10);
s.syncBytes(_newLevelLocation, 10);
s.syncAsByte(_area);
s.syncBytes(_actorDir, 16);
s.syncBytes(_filler, 3);
}
void Level::load(const int level) {
Common::MemoryReadStream src(_G(sdData)[level], 512);
Common::Serializer s(&src, nullptr);
sync(s);
}
void Level::save(const int level) {
Common::MemoryWriteStream dest(_G(sdData)[level], 512);
Common::Serializer s(nullptr, &dest);
sync(s);
}
} // namespace Got

67
engines/got/data/level.h Normal file
View File

@@ -0,0 +1,67 @@
/* 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 GOT_DATA_LEVEL_H
#define GOT_DATA_LEVEL_H
#include "common/serializer.h"
namespace Got {
#define OBJECTS_COUNT 30
struct Level {
private:
void sync(Common::Serializer &s);
public:
byte _iconGrid[12][20] = {}; // Grid of icons
byte _backgroundColor = 0; // Background color
byte _music = 0; // Music
byte _actorType[16] = {}; // Type of enemies (12 max)
byte _actorLoc[16] = {}; // Location of enemies
byte _actorValue[16] = {}; // Pass value
byte _palColors[3] = {}; // Change 251,253,254 to these three
byte _actorInvis[16] = {};
byte _extra[13] = {};
byte _staticObject[OBJECTS_COUNT] = {}; // Static objects (treasure, keys,etc)
int _staticX[OBJECTS_COUNT] = {}; // X coordinates of static objects
int _staticY[OBJECTS_COUNT] = {}; // Y coordinates of static objects
byte _newLevel[10] = {}; // Level jump for icon 200-204
byte _newLevelLocation[10] = {}; // Grid location to jump in to
byte _area = 0; // Game area (1=forest,etc)
byte _actorDir[16] = {}; // Initial _dir
byte _filler[3] = {};
/**
* Loads level data from the global sd_data for the given level
*/
void load(int level);
/**
* Saves the level data to the global sd_data
*/
void save(int level);
};
} // namespace Got
#endif

View File

@@ -0,0 +1,51 @@
/* 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 "got/data/sd_data.h"
#include "got/utils/file.h"
namespace Got {
#define SD_DATA_SIZE 61440
SdData::SdData() {
_data = new byte[SD_DATA_SIZE];
}
SdData::~SdData() {
delete[] _data;
}
void SdData::load() {
const Common::String fname = Common::String::format("SDAT%d", _area);
resourceRead(fname, _data);
}
void SdData::setArea(int area) {
_area = area;
load();
}
void SdData::sync(Common::Serializer &s) {
s.syncBytes(_data, SD_DATA_SIZE);
}
} // namespace Got

View File

@@ -0,0 +1,53 @@
/* 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 GOT_DATA_SD_DATA_H
#define GOT_DATA_SD_DATA_H
#include "common/serializer.h"
namespace Got {
class SdData {
private:
byte *_data;
int _area = 1;
public:
SdData();
~SdData();
void load();
bool getArea() const {
return _area;
}
void setArea(int area);
void sync(Common::Serializer &s);
byte *operator[](int level) const {
return _data + level * 512;
}
};
} // namespace Got
#endif

View File

@@ -0,0 +1,68 @@
/* 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 "got/data/setup.h"
#include "common/algorithm.h"
namespace Got {
SetupFlags &SetupFlags::operator=(const Got::SetupFlags &src) {
Common::copy(src._flags, src._flags + 64, _flags);
return *this;
}
void SetupFlags::sync(Common::Serializer &s) {
byte flags[8] = {};
if (s.isSaving()) {
for (int i = 0; i < 64; ++i) {
if (_flags[i])
flags[i / 8] = flags[i / 8] | (1 << (i % 8));
}
s.syncBytes(flags, 8);
} else {
s.syncBytes(flags, 8);
for (int i = 0; i < 64; ++i)
_flags[i] = (flags[i / 8] & (1 << (i % 8))) != 0;
}
}
void Setup::sync(Common::Serializer &s) {
// Sync the flags bit-fields
SetupFlags::sync(s);
s.syncBytes(_value, 16);
s.syncAsByte(_filler1);
s.syncAsByte(_game);
s.syncAsByte(_areaNum);
s.syncAsByte(_speakerSound);
s.syncAsByte(_digitalSound);
s.syncAsByte(_musicEnabled);
s.syncAsByte(_slowMode);
s.syncAsByte(_scrollFlag);
for (int i = 0; i < 3 ; ++i)
s.syncAsByte(_bossDead[i]);
s.syncAsByte(_difficultyLevel);
s.syncAsByte(_gameOver);
s.syncBytes(_filler2, 19);
}
} // namespace Got

122
engines/got/data/setup.h Normal file
View File

@@ -0,0 +1,122 @@
/* 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 GOT_DATA_SETUP_H
#define GOT_DATA_SETUP_H
#include "common/serializer.h"
namespace Got {
struct SetupFlags {
bool _flags[64] = {};
bool &f01 = _flags[0];
bool &f02 = _flags[1];
bool &f03 = _flags[2];
bool &f04 = _flags[3];
bool &f05 = _flags[4];
bool &f06 = _flags[5];
bool &f07 = _flags[6];
bool &f08 = _flags[7];
bool &f09 = _flags[8];
bool &f10 = _flags[9];
bool &f11 = _flags[10];
bool &f12 = _flags[11];
bool &f13 = _flags[12];
bool &f14 = _flags[13];
bool &f15 = _flags[14];
bool &f16 = _flags[15];
bool &f17 = _flags[16];
bool &f18 = _flags[17];
bool &f19 = _flags[18];
bool &f20 = _flags[19];
bool &f21 = _flags[20];
bool &f22 = _flags[21];
bool &f23 = _flags[22];
bool &f24 = _flags[23];
bool &f25 = _flags[24];
bool &f26 = _flags[25];
bool &f27 = _flags[26];
bool &f28 = _flags[27];
bool &f29 = _flags[28];
bool &f30 = _flags[29];
bool &f31 = _flags[30];
bool &f32 = _flags[31];
bool &f33 = _flags[32];
bool &f34 = _flags[33];
bool &f35 = _flags[34];
bool &f36 = _flags[35];
bool &f37 = _flags[36];
bool &f38 = _flags[37];
bool &f39 = _flags[38];
bool &f40 = _flags[39];
bool &f41 = _flags[40];
bool &f42 = _flags[41];
bool &f43 = _flags[42];
bool &f44 = _flags[43];
bool &f45 = _flags[44];
bool &f46 = _flags[45];
bool &f47 = _flags[46];
bool &f48 = _flags[47];
bool &f49 = _flags[48];
bool &f50 = _flags[49];
bool &f51 = _flags[50];
bool &f52 = _flags[51];
bool &f53 = _flags[52];
bool &f54 = _flags[53];
bool &f55 = _flags[54];
bool &f56 = _flags[55];
bool &f57 = _flags[56];
bool &f58 = _flags[57];
bool &f59 = _flags[58];
bool &f60 = _flags[59];
bool &f61 = _flags[60];
bool &f62 = _flags[61];
bool &f63 = _flags[62];
bool &f64 = _flags[63];
SetupFlags() {}
virtual ~SetupFlags() {}
virtual void sync(Common::Serializer &s);
SetupFlags &operator=(const Got::SetupFlags &src);
};
struct Setup : public SetupFlags {
byte _value[16] = {};
byte _filler1 = 0;
byte _game = 0; // Unused
byte _areaNum = 0; // 1,2,3
bool _speakerSound = false; // always disabled
bool _digitalSound = false; // true = enabled
bool _musicEnabled = false; // true = enabled
bool _slowMode = false; // true = slow mode (for slower 286's)
bool _scrollFlag = false; // true = scroll when changing from a room to the other
bool _bossDead[3] = {false, false, false};
byte _difficultyLevel = 0; // 0=easy, 1=normal, 2=hard
byte _gameOver = 0;
byte _filler2[19] = {};
void sync(Common::Serializer &s) override;
};
} // namespace Got
#endif

View File

@@ -0,0 +1,102 @@
/* 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
* as.syncAsUint32LE(with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/algorithm.h"
#include "got/data/thorinfo.h"
#include "got/game/back.h"
namespace Got {
void ThorInfo::clear() {
_magic = 0;
_keys = 0;
_jewels = 0;
_lastArea = 0;
_lastScreen = 0;
_lastIcon = 0;
_lastDir = 0;
_inventory = 0;
_selectedItem = 0;
_lastHealth = 0;
_lastMagic = 0;
_lastJewels = 0;
_lastKeys = 0;
_lastItem = 0;
_lastInventory = 0;
_level = 0;
_score = 0;
_lastScore = 0;
_object = 0;
_objectName = nullptr;
_lastObject = 0;
_lastObjectName = nullptr;
_armor = 0;
#ifdef USE_TTS
_previousJewels = -1;
_previousScore = -1;
_previousKeys = -1;
#endif
Common::fill(_filler, _filler + 65, 0);
}
void ThorInfo::sync(Common::Serializer &s) {
uint32 ptr = 0;
s.syncAsByte(_magic);
s.syncAsByte(_keys);
s.syncAsSint16LE(_jewels);
s.syncAsByte(_lastArea);
s.syncAsByte(_lastScreen);
s.syncAsByte(_lastIcon);
s.syncAsByte(_lastDir);
s.syncAsSint16LE(_inventory);
s.syncAsByte(_selectedItem);
s.syncAsByte(_lastHealth);
s.syncAsByte(_lastMagic);
s.syncAsSint16LE(_lastJewels);
s.syncAsByte(_lastKeys);
s.syncAsByte(_lastItem);
s.syncAsSint16LE(_lastInventory);
s.syncAsByte(_level);
s.syncAsUint32LE(_score);
s.syncAsUint32LE(_lastScore);
s.syncAsByte(_object);
s.syncAsUint16LE(ptr);
s.syncAsByte(_lastObject);
s.syncAsUint16LE(ptr);
s.syncAsByte(_armor);
s.syncBytes(_filler, 65);
if (s.isLoading()) {
_objectName = (_object == 0) ? nullptr : OBJECT_NAMES[_object - 1];
_lastObjectName = (_lastObject == 0) ? nullptr : OBJECT_NAMES[_lastObject - 1];
#ifdef USE_TTS
_previousJewels = -1;
_previousScore = -1;
_previousKeys = -1;
#endif
}
}
} // namespace Got

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/>.
*
*/
#ifndef GOT_DATA_THORINFO_H
#define GOT_DATA_THORINFO_H
#include "common/serializer.h"
namespace Got {
struct ThorInfo {
byte _magic = 0;
byte _keys = 0;
int _jewels = 0;
byte _lastArea = 0;
byte _lastScreen = 0;
byte _lastIcon = 0;
byte _lastDir = 0;
int _inventory = 0;
byte _selectedItem = 0; //currently selected item
byte _lastHealth = 0;
byte _lastMagic = 0;
int _lastJewels = 0;
byte _lastKeys = 0;
byte _lastItem = 0;
int _lastInventory = 0;
byte _level = 0; //current level (1,2,3)
long _score = 0;
long _lastScore = 0;
byte _object = 0;
const char *_objectName = nullptr;
byte _lastObject = 0;
const char *_lastObjectName = nullptr;
byte _armor = 0;
byte _filler[65] = {};
#ifdef USE_TTS
int _previousJewels = -1;
int _previousScore = -1;
int _previousKeys = -1;
#endif
void clear();
void sync(Common::Serializer &s);
};
} // namespace Got
#endif

44
engines/got/detection.cpp Normal file
View File

@@ -0,0 +1,44 @@
/* 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/file.h"
#include "common/md5.h"
#include "common/str-array.h"
#include "common/util.h"
#include "got/detection.h"
#include "got/detection_tables.h"
const DebugChannelDef GotMetaEngineDetection::debugFlagList[] = {
{ Got::kDebugGraphics, "Graphics", "Graphics debug level" },
{ Got::kDebugPath, "Path", "Pathfinding debug level" },
{ Got::kDebugFilePath, "FilePath", "File path debug level" },
{ Got::kDebugScan, "Scan", "Scan for unrecognised games" },
{ Got::kDebugScript, "Script", "Enable debug script dump" },
DEBUG_CHANNEL_END
};
GotMetaEngineDetection::GotMetaEngineDetection() : AdvancedMetaEngineDetection(
Got::gameDescriptions, Got::gotGames) {
}
REGISTER_PLUGIN_STATIC(GOT_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, GotMetaEngineDetection);

70
engines/got/detection.h Normal file
View File

@@ -0,0 +1,70 @@
/* 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 GOT_DETECTION_H
#define GOT_DETECTION_H
#include "engines/advancedDetector.h"
namespace Got {
enum GotDebugChannels {
kDebugGraphics = 1,
kDebugPath,
kDebugScan,
kDebugFilePath,
kDebugScript,
};
extern const PlainGameDescriptor gotGames[];
extern const ADGameDescription gameDescriptions[];
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
#define GAMEOPTION_TTS GUIO_GAMEOPTIONS2
} // End of namespace Got
class GotMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
static const DebugChannelDef debugFlagList[];
public:
GotMetaEngineDetection();
~GotMetaEngineDetection() override {}
const char *getName() const override {
return "got";
}
const char *getEngineName() const override {
return "Got";
}
const char *getOriginalCopyright() const override {
return "Got (C) 1993-1994 Ron Davis";
}
const DebugChannelDef *getDebugChannels() const override {
return debugFlagList;
}
};
#endif // GOT_DETECTION_H

View File

@@ -0,0 +1,69 @@
/* 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/>.
*
*/
namespace Got {
const PlainGameDescriptor gotGames[] = {
{"got", "God of Thunder"},
{nullptr, nullptr}
};
const ADGameDescription gameDescriptions[] = {
{
"got",
"v1.0:143",
AD_ENTRY1s("gotres.dat", "0fe859bcfd06772be0885bf510c2877d", 739732),
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO2(GUIO_NOSPEECH, GAMEOPTION_TTS)
},
{
"got",
"v1.0:143 Shareware",
AD_ENTRY1s("gotres.dat", "c316221a3b9d12a838faef55fde2f34c", 482738),
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_DEMO,
GUIO2(GUIO_NOSPEECH, GAMEOPTION_TTS)
},
{
"got",
"v1.1:144",
AD_ENTRY1s("gotres.dat", "747ed508ffa3808156a4eb080e9859f8", 739710),
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO2(GUIO_NOSPEECH, GAMEOPTION_TTS)
},
{
"got",
"v1.1:144 Shareware",
AD_ENTRY1s("gotres.dat", "c443aa09450566ee32998c3ebb15cbaa", 485858),
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_DEMO,
GUIO2(GUIO_NOSPEECH, GAMEOPTION_TTS)
},
AD_TABLE_END_MARKER};
} // End of namespace Got

503
engines/got/events.cpp Normal file
View File

@@ -0,0 +1,503 @@
/* 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 "got/events.h"
#include "common/config-manager.h"
#include "got/gfx/palette.h"
#include "got/got.h"
#include "got/views/views.h"
#include "graphics/screen.h"
namespace Got {
Events *g_events;
// Index and RGB63 values used for palette animation
// like water effects and gems sparkling
static const uint16 PAL_CLR1[] = {0xf300, 0x003b, 0xf000, 0x003b, 0xf100, 0x003b, 0xf200, 0x003b};
static const uint16 PAL_SET1[] = {0xf027, 0x273f, 0xf127, 0x273f, 0xf227, 0x273f, 0xf327, 0x273f};
static const uint16 PAL_CLR2[] = {0xf73b, 0x0000, 0xf43b, 0x0000, 0xf53b, 0x0000, 0xf63b, 0x0000};
static const uint16 PAL_SET2[] = {0xf43f, 0x2727, 0xf53f, 0x2727, 0xf63f, 0x2727, 0xf73f, 0x2727};
Events::Events() : UIElement("Root", nullptr) {
g_events = this;
}
Events::~Events() {
g_events = nullptr;
}
void Events::runGame() {
uint nextFrameTime = 0;
int palCycleCtr = 0;
_screen = new Graphics::Screen();
Views::Views views; // Loads all views in the structure
// Set up the initial game view
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot != -1) {
if (g_engine->loadGameState(saveSlot).getCode() != Common::kNoError)
saveSlot = -1;
}
if (saveSlot == -1)
addView("SplashScreen");
// Main game loop
Common::Event e;
while (!_views.empty() && !shouldQuit()) {
while (g_system->getEventManager()->pollEvent(e)) {
if (e.type == Common::EVENT_QUIT ||
e.type == Common::EVENT_RETURN_TO_LAUNCHER) {
_views.clear();
break;
}
processEvent(e);
}
if (_views.empty())
break;
g_system->delayMillis(10);
// Rotate the palette
if (++palCycleCtr == 2) {
palCycleCtr = 0;
bool gameVisible = false;
for (uint i = 0; i < _views.size() && !gameVisible; ++i)
gameVisible = _views[i]->_name == "Game";
if (gameVisible)
rotatePalette();
}
uint currTime = g_system->getMillis();
if (currTime >= nextFrameTime) {
nextFrameTime = currTime + FRAME_DELAY;
nextFrame();
}
}
delete _screen;
}
void Events::nextFrame() {
// Update state variables
_G(rand1) = getRandomNumber(99);
_G(rand2) = getRandomNumber(99);
_G(pge) = _G(pge) ^ 1;
_G(shotOk) = true;
_G(magicCounter++);
// In demo mode, handle the next key
if (_G(demo) && focusedView()->getName() == "Game") {
if (_G(demoKeys).empty()) {
_G(demo) = false;
send("TitleBackground", GameMessage("MAIN_MENU"));
return;
}
processDemoEvent(_G(demoKeys).pop());
}
// Check if any script needs resuming
_G(scripts).runIfResuming();
// Do tick action to the views to handle gameplay logic
tick();
// Draw the current view's elements as needed, and update screen
drawElements();
_screen->update();
}
#define LOOP_THRESHOLD 5
void Events::rotatePalette() {
++_palLoop;
if (_palLoop > LOOP_THRESHOLD) {
_palLoop = 0;
} else {
const uint16 *entry;
switch (_palLoop) {
case LOOP_THRESHOLD - 4:
entry = &PAL_CLR2[_palCnt2];
break;
case LOOP_THRESHOLD - 3:
entry = &PAL_SET2[_palCnt2];
_palCnt2 += 2;
if (_palCnt2 >= 8)
_palCnt2 = 0;
break;
case LOOP_THRESHOLD - 2:
entry = &PAL_CLR1[_palCnt1];
break;
case LOOP_THRESHOLD - 1:
entry = &PAL_SET1[_palCnt1];
_palCnt1 += 2;
if (_palCnt1 >= 8)
_palCnt1 = 0;
break;
default:
return;
}
Gfx::xSetPal(entry[0] >> 8, (entry[0] & 0xff) << 2,
(entry[1] >> 8) << 2, (entry[1] & 0xff) << 2);
}
}
void Events::processEvent(Common::Event &ev) {
switch (ev.type) {
case Common::EVENT_KEYDOWN:
if (!_G(demo)) {
if (ev.kbd.keycode < 100)
_G(keyFlag[ev.kbd.keycode]) = true;
if (ev.kbd.keycode < Common::KEYCODE_NUMLOCK)
msgKeypress(KeypressMessage(ev.kbd));
}
break;
case Common::EVENT_KEYUP:
if (!_G(demo) && ev.kbd.keycode < 100)
_G(keyFlag[ev.kbd.keycode]) = false;
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
if (!_G(demo)) {
_G(keyFlag[actionToKeyFlag(ev.customType)]) = true;
msgAction(ActionMessage(ev.customType));
} else if (ev.customType == KEYBIND_ESCAPE) {
// The Escape action will return to main menu from demo
_G(demo) = false;
send("TitleBackground", GameMessage("MAIN_MENU"));
}
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
if (!_G(demo))
_G(keyFlag[actionToKeyFlag(ev.customType)]) = false;
break;
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
case Common::EVENT_MBUTTONDOWN:
if (!_G(demo))
msgMouseDown(MouseDownMessage(ev.type, ev.mouse));
break;
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
case Common::EVENT_MBUTTONUP:
if (!_G(demo))
msgMouseUp(MouseUpMessage(ev.type, ev.mouse));
break;
case Common::EVENT_MOUSEMOVE:
if (!_G(demo))
msgMouseMove(MouseMoveMessage(ev.type, ev.mouse));
break;
default:
break;
}
}
void Events::processDemoEvent(byte ev) {
if (!ev)
return;
bool flag = ev & 0x80;
ev &= 0x7f;
int action = -1;
switch (ev) {
case 72:
ev = key_up;
action = KEYBIND_UP;
break;
case 80:
ev = key_down;
break;
case 75:
ev = key_left;
break;
case 77:
ev = key_right;
break;
case 56:
ev = key_fire;
action = KEYBIND_FIRE;
break;
case 29:
ev = key_magic;
action = KEYBIND_MAGIC;
break;
case 39:
ev = key_select;
action = KEYBIND_SELECT;
break;
default:
break;
}
_G(keyFlag[ev]) = flag;
if (flag && action != -1)
msgAction(ActionMessage(action));
}
int Events::actionToKeyFlag(int action) const {
return (action == KEYBIND_ESCAPE) ? Common::KEYCODE_ESCAPE : (int)action;
}
void Events::replaceView(UIElement *ui, bool replaceAllViews, bool fadeOutIn) {
assert(ui);
UIElement *oldView = focusedView();
if (fadeOutIn)
Gfx::fadeOut();
if (replaceAllViews) {
clearViews();
} else if (!_views.empty()) {
oldView->msgUnfocus(UnfocusMessage());
_views.pop();
}
// Redraw any prior views to erase the removed view
for (uint i = 0; i < _views.size(); ++i) {
_views[i]->redraw();
_views[i]->draw();
}
// Add the new view
_views.push(ui);
ui->redraw();
ui->msgFocus(FocusMessage(oldView));
ui->draw();
if (fadeOutIn)
Gfx::fadeIn();
}
void Events::replaceView(const Common::String &name, bool replaceAllViews, bool fadeOutIn) {
replaceView(findView(name), replaceAllViews, fadeOutIn);
}
void Events::addView(UIElement *ui) {
assert(ui);
UIElement *oldView = focusedView();
if (!_views.empty())
oldView->msgUnfocus(UnfocusMessage());
_views.push(ui);
ui->redraw();
ui->msgFocus(FocusMessage(oldView));
}
void Events::addView(const Common::String &name) {
addView(findView(name));
}
void Events::popView() {
UIElement *oldView = focusedView();
oldView->msgUnfocus(UnfocusMessage());
_views.pop();
for (uint i = 0; i < _views.size(); ++i) {
_views[i]->redraw();
_views[i]->draw();
}
if (!_views.empty()) {
UIElement *view = focusedView();
view->msgFocus(FocusMessage(oldView));
view->redraw();
view->draw();
}
}
bool Events::isPresent(const Common::String &name) const {
for (uint i = 0; i < _views.size(); ++i) {
if (_views[i]->_name == name)
return true;
}
return false;
}
void Events::drawElements() {
if (!_views.empty())
focusedView()->drawElements();
}
void Events::clearViews() {
if (!_views.empty())
focusedView()->msgUnfocus(UnfocusMessage());
_views.clear();
}
/*------------------------------------------------------------------------*/
Bounds::Bounds(Common::Rect &innerBounds) : _bounds(0, 0, 320, 240),
_innerBounds(innerBounds),
left(_bounds.left), top(_bounds.top),
right(_bounds.right), bottom(_bounds.bottom) {
}
Bounds &Bounds::operator=(const Common::Rect &r) {
_bounds = r;
_innerBounds = r;
_innerBounds.grow(-_borderSize);
return *this;
}
void Bounds::setBorderSize(size_t borderSize) {
_borderSize = borderSize;
_innerBounds = *this;
_innerBounds.grow(-_borderSize);
}
/*------------------------------------------------------------------------*/
UIElement::UIElement(const Common::String &name) : _name(name), _parent(g_engine), _bounds(_innerBounds) {
g_engine->_children.push_back(this);
}
UIElement::UIElement(const Common::String &name, UIElement *uiParent) : _name(name), _parent(uiParent), _bounds(_innerBounds) {
if (_parent)
_parent->_children.push_back(this);
}
void UIElement::redraw() {
_needsRedraw = true;
for (size_t i = 0; i < _children.size(); ++i)
_children[i]->redraw();
}
void UIElement::drawElements() {
if (_needsRedraw) {
draw();
_needsRedraw = false;
}
for (size_t i = 0; i < _children.size(); ++i)
_children[i]->drawElements();
}
UIElement *UIElement::findViewGlobally(const Common::String &name) {
return g_events->findView(name);
}
void UIElement::close() {
assert(g_events->focusedView() == this);
g_events->popView();
#ifdef USE_TTS
stopTextToSpeech();
#endif
}
void UIElement::draw() {
for (size_t i = 0; i < _children.size(); ++i) {
_children[i]->draw();
}
}
bool UIElement::tick() {
if (_timeoutCtr && --_timeoutCtr == 0) {
timeout();
}
for (size_t i = 0; i < _children.size(); ++i) {
if (_children[i]->tick())
return true;
}
return false;
}
UIElement *UIElement::findView(const Common::String &name) {
if (_name.equalsIgnoreCase(name))
return this;
for (size_t i = 0; i < _children.size(); ++i) {
UIElement *result = _children[i]->findView(name);
if (result != nullptr)
return result;
}
return nullptr;
}
void UIElement::replaceView(UIElement *ui, bool replaceAllViews, bool fadeOutIn) {
g_events->replaceView(ui, replaceAllViews, fadeOutIn);
}
void UIElement::replaceView(const Common::String &name, bool replaceAllViews, bool fadeOutIn) {
g_events->replaceView(name, replaceAllViews, fadeOutIn);
}
void UIElement::addView(UIElement *ui) {
g_events->addView(ui);
}
void UIElement::addView(const Common::String &name) {
g_events->addView(name);
}
void UIElement::addView() {
g_events->addView(this);
}
GfxSurface UIElement::getSurface(bool innerBounds) const {
return GfxSurface(*g_events->getScreen(),
innerBounds ? _innerBounds : _bounds);
}
int UIElement::getRandomNumber(int minNumber, int maxNumber) {
return g_engine->getRandomNumber(maxNumber - minNumber + 1) + minNumber;
}
int UIElement::getRandomNumber(int maxNumber) {
return g_engine->getRandomNumber(maxNumber);
}
void UIElement::timeout() {
redraw();
}
#ifdef USE_TTS
void UIElement::stopTextToSpeech() {
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (ttsMan && ConfMan.getBool("tts_enabled") && ttsMan->isSpeaking()) {
ttsMan->stop();
}
_previousSaid.clear();
}
#endif
} // namespace Got

422
engines/got/events.h Normal file
View File

@@ -0,0 +1,422 @@
/* 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 GOT_EVENTS_H
#define GOT_EVENTS_H
#include "common/array.h"
#include "common/stack.h"
#include "got/gfx/gfx_surface.h"
#include "got/messages.h"
#include "graphics/screen.h"
namespace Got {
#define FRAME_RATE 60
#define FRAME_DELAY (1000 / FRAME_RATE)
using Gfx::GfxSurface;
class Events;
/**
* Implements a thunk layer around an element's bounds,
* allowing access to it as if it were a simple Common::Rect,
* but any changes to it will also be applied to a linked inner bounds
*/
struct Bounds {
private:
Common::Rect _bounds;
Common::Rect &_innerBounds;
int _borderSize = 0;
public:
const int16 &left;
const int16 &top;
const int16 &right;
const int16 &bottom;
public:
Bounds(Common::Rect &innerBounds);
operator const Common::Rect &() const {
return _bounds;
}
Bounds &operator=(const Common::Rect &r);
void setBorderSize(size_t borderSize);
size_t borderSize() const {
return _borderSize;
}
int16 width() const {
return _bounds.width();
}
int16 height() const {
return _bounds.height();
}
};
/**
* User interface element
*/
class UIElement {
friend class Events;
private:
int _timeoutCtr = 0;
protected:
UIElement *_parent;
Common::Array<UIElement *> _children;
Common::Rect _innerBounds;
Bounds _bounds;
bool _needsRedraw = true;
Common::String _name;
#ifdef USE_TTS
Common::String _previousSaid;
#endif
protected:
/**
* Returns true if a delay is active
*/
bool isDelayActive() const {
return _timeoutCtr != 0;
}
/**
* Cancels any active delay
*/
void cancelDelay() {
_timeoutCtr = 0;
}
/**
* Called when an active timeout countdown expired
*/
virtual void timeout();
private:
/**
* Outer method for doing drawing
*
*/
virtual void drawElements();
/**
* Finds a view globally
*/
static UIElement *findViewGlobally(const Common::String &name);
public:
UIElement(const Common::String &name, UIElement *uiParent);
UIElement(const Common::String &name);
virtual ~UIElement() {}
/**
* Returns true if the elements needs to be redrawn
*/
bool needsRedraw() const {
return _needsRedraw;
}
/**
* Sets that the element needs to be redrawn
*/
void redraw();
/**
* Closes the current view. The view must have been added
* via addView, so there's a remaining view afterwards
*/
virtual void close();
/**
* Sets the focus to a new view
*/
virtual void replaceView(UIElement *ui, bool replaceAllViews = false, bool fadeOutIn = false);
virtual void replaceView(const Common::String &name, bool replaceAllViews = false, bool fadeOutIn = false);
/**
* Adds a focused view to the view stack without replacing current one
*/
virtual void addView(UIElement *ui);
virtual void addView(const Common::String &name);
void addView();
void open() {
addView();
}
/**
* Returns a random number
*/
int getRandomNumber(int minNumber, int maxNumber);
int getRandomNumber(int maxNumber);
/**
* Sets the element's bounds
*/
virtual void setBounds(const Common::Rect &r) {
_bounds = r;
}
/**
* Gets the element's bounds
*/
Common::Rect getBounds() const {
return _bounds;
}
/**
* Gets a view's name
*/
const Common::String &getName() const {
return _name;
}
/**
* Returns a surface for drawing the element
*/
Gfx::GfxSurface getSurface(bool innerBounds = false) const;
/**
* Draws the element
*/
virtual void draw();
/**
* Called for game frame ticks
*/
virtual bool tick();
/**
* Find a view by name
*/
virtual UIElement *findView(const Common::String &name);
/**
* Handles events
*/
// Mouse move only has a minimal implementation for performance reasons
protected:
virtual bool msgMouseMove(const MouseMoveMessage &msg) {
return false;
}
#ifdef USE_TTS
/**
* Stops TTS voicing and clears the previously spoken text
*/
void stopTextToSpeech();
#endif
public:
bool send(const MouseMoveMessage &msg) {
return msgMouseMove(msg);
}
#define MESSAGE(NAME) \
protected: \
virtual bool msg##NAME(const NAME##Message &e) { \
for (Common::Array<UIElement *>::iterator it = _children.begin(); \
it != _children.end(); ++it) { \
if ((*it)->msg##NAME(e)) \
return true; \
} \
return false; \
} \
\
public: \
bool send(const Common::String &viewName, const NAME##Message &msg) { \
UIElement *view = UIElement::findViewGlobally(viewName); \
assert(view); \
return view->msg##NAME(msg); \
} \
bool send(const NAME##Message &msg) { \
return msg##NAME(msg); \
}
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(MouseEnter);
MESSAGE(MouseLeave);
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
MESSAGE(Action);
MESSAGE(Game);
MESSAGE(Value);
#undef MESSAGE
};
/**
* Main events and view manager. This is kept separate from the engine
* class because the engine may add a lot of globals and bring in other
* classes. So to save on compilation time, classes that only need to
* access basic view management methods like addView or replaceView
* only need to include events.h rather than the whole engine.
*/
class Events : public UIElement {
private:
Graphics::Screen *_screen = nullptr;
Common::Stack<UIElement *> _views;
int _palLoop = 0;
int _palCnt1 = 0;
int _palCnt2 = 0;
void nextFrame();
int actionToKeyFlag(int action) const;
void rotatePalette();
/**
* Process an event
*/
void processEvent(Common::Event &ev);
/**
* Process a demo event
*/
void processDemoEvent(byte ev);
protected:
/**
* Returns true if the game should quit
*/
virtual bool shouldQuit() const = 0;
/**
* Overrides events we want to only go to the focused view
*/
#define MESSAGE(NAME) \
bool msg##NAME(const NAME##Message &e) override { \
return !_views.empty() ? focusedView()->msg##NAME(e) : false; \
}
MESSAGE(Action);
MESSAGE(Focus);
MESSAGE(Unfocus);
MESSAGE(MouseEnter);
MESSAGE(MouseLeave);
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
MESSAGE(MouseMove);
#undef MESSAGE
public:
Events();
virtual ~Events();
virtual bool isDemo() const = 0;
/**
* Main game loop
*/
void runGame();
/**
* Sets the focus to a new view
*/
void replaceView(UIElement *ui, bool replaceAllViews = false, bool fadeOutIn = false) override;
void replaceView(const Common::String &name, bool replaceAllViews = false, bool fadeOutIn = false) override;
/**
* Adds a focused view to the view stack without replacing current one
*/
void addView(UIElement *ui) override;
void addView(const Common::String &name) override;
/**
* Clears the view list
*/
void clearViews();
/**
* Pops a view from the view stack
*/
void popView();
/**
* Returns the currently focused view, if any
*/
UIElement *focusedView() const {
return _views.empty() ? nullptr : _views.top();
}
/**
* Returns the view prior to the current view, if any
*/
UIElement *priorView() const {
return _views.size() < 2 ? nullptr : _views[_views.size() - 2];
}
/**
* Returns the first view in the stack
*/
UIElement *firstView() const {
return _views.empty() ? nullptr : _views[0];
}
/**
* Returns true if a view of a given name is present
* at all in the visible view stack
*/
bool isPresent(const Common::String &name) const;
/**
* Returns true if combat is active
*/
bool isInCombat() const {
return isPresent("Combat");
}
/**
* Returns the underlying screen
*/
Graphics::Screen *getScreen() const {
return _screen;
}
/**
* Draws the focused view
*/
void drawElements() override;
/**
* Events manager doesn't have any intrinsic drawing
*/
void draw() override {}
/**
* Called once every game frame
*/
bool tick() override {
return !_views.empty() ? focusedView()->tick() : false;
}
/**
* Calling the close method for g_events closes the active view
*/
void close() override {
focusedView()->close();
}
};
extern Events *g_events;
} // namespace Got
#endif

334
engines/got/game/back.cpp Normal file
View File

@@ -0,0 +1,334 @@
/* 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 "got/game/back.h"
#include "common/file.h"
#include "got/events.h"
#include "got/game/boss1.h"
#include "got/game/boss2.h"
#include "got/game/boss3.h"
#include "got/game/move.h"
#include "got/game/object.h"
#include "got/game/script.h"
#include "got/gfx/image.h"
#include "got/vars.h"
namespace Got {
const char *OBJECT_NAMES[] = {
"Shrub", "Child's Doll", "UNUSED", "FUTURE",
"FUTURE", "FUTURE", "FUTURE", "FUTURE", "FUTURE",
"FUTURE", "FUTURE", "FUTURE", "FUTURE", "FUTURE",
"FUTURE"};
const char *ITEM_NAMES[] = {
"Enchanted Apple", "Lightning Power",
"Winged Boots", "Wind Power",
"Amulet of Protection", "Thunder Power"};
static const char *odinEndMessage;
void showLevel(const int newLevel) {
if (_G(area) == 2 && newLevel == 105) { // Shovel Maze
_G(thorInfo)._armor = 2; // eyeballs mode
loadNewThor();
_G(eyeballs) = 1;
} else if (_G(eyeballs) == 1) {
_G(setup).f25 = 0;
_G(thorInfo)._armor = 1;
loadNewThor();
_G(eyeballs) = 0;
}
_G(bossActive) = false;
if (!_G(shieldOn))
_G(actor[2])._active = false;
_G(slipping) = false;
if (_G(scrn)._iconGrid[_G(thor)->_centerY][_G(thor)->_centerX] == 154)
_G(thor)->_dir = 0;
// The original copied 130 bytes from _G(scrn).static_object onwards into sd_data.
// This doesn't make sense, because that would put the ending in the middle of _staticY.
// Plus, it follows with an entire copy of scrn into sd_data anyway, so the first
// move seems entirely redundant.
_G(scrn).save(_G(currentLevel));
_G(scrn).load(_G(newLevel));
_G(levelMusic) = _G(scrn)._music;
_G(thor)->_nextFrame = 0;
showObjects();
showEnemies();
// The original was probably shortly displaying Thor in direction 0 before switching back to its prior position.
// This behavior wasn't noticed during initial playthrough by Dreammaster - Warning has been added so it can be checked eventually.
if (_G(scrn)._iconGrid[_G(thor)->_centerY][_G(thor)->_centerX] == 154)
warning("showLevel - Potential short move missing");
if (_G(warpFlag))
_G(currentLevel) = newLevel - 5; // Force phase
_G(warpFlag) = false;
if (_G(warpScroll)) {
_G(warpScroll) = false;
if (_G(thor)->_dir == 0)
_G(currentLevel) = newLevel + 10;
else if (_G(thor)->_dir == 1)
_G(currentLevel) = newLevel - 10;
else if (_G(thor)->_dir == 2)
_G(currentLevel) = newLevel + 1;
else if (_G(thor)->_dir == 3)
_G(currentLevel) = newLevel - 1;
}
if (!_G(setup)._scrollFlag)
_G(currentLevel) = newLevel; // Force no scroll
switch (_G(newLevel) - _G(currentLevel)) {
case 0:
// Nothing to do
showLevelDone();
break;
case -1:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_LEFT;
break;
case 1:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_RIGHT;
break;
case -10:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_UP;
break;
case 10:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_DOWN;
break;
default:
_G(gameMode) = MODE_AREA_CHANGE;
_G(transitionDir) = DIR_PHASED;
break;
}
}
void showLevelDone() {
_G(currentLevel) = _G(newLevel);
_G(thorInfo)._lastHealth = _G(thor)->_health;
_G(thorInfo)._lastMagic = _G(thorInfo)._magic;
_G(thorInfo)._lastJewels = _G(thorInfo)._jewels;
_G(thorInfo)._lastKeys = _G(thorInfo)._keys;
_G(thorInfo)._lastScore = _G(thorInfo)._score;
_G(thorInfo)._lastItem = _G(thorInfo)._selectedItem;
_G(thorInfo)._lastScreen = _G(currentLevel);
_G(thorInfo)._lastIcon = ((_G(thor)->_x + 8) / 16) + (((_G(thor)->_y + 14) / 16) * 20);
_G(thorInfo)._lastDir = _G(thor)->_dir;
_G(thorInfo)._lastInventory = _G(thorInfo)._inventory;
_G(thorInfo)._lastObject = _G(thorInfo)._object;
_G(thorInfo)._lastObjectName = _G(thorInfo)._objectName;
_G(lastSetup) = _G(setup);
bool f = true;
if (GAME1 && _G(newLevel) == BOSS_LEVEL1 && !_G(setup)._bossDead[0]) {
boss1SetupLevel();
f = false;
}
if (GAME2 && _G(newLevel) == BOSS_LEVEL2 && !_G(setup)._bossDead[1]) {
boss2SetupLevel();
f = false;
}
if (GAME3) {
if (_G(newLevel) == BOSS_LEVEL3 && !_G(setup)._bossDead[2]) {
boss3SetupLevel();
f = false;
}
if (_G(currentLevel) == ENDING_SCREEN) {
endingScreen();
f = false;
}
}
if (_G(startup))
f = false;
if (f)
musicPlay(_G(levelMusic), false);
}
static void odin_speaks_end() {
// In case Thor is now dead, flag as such
if (!_G(thor)->_health) {
_G(thor)->_show = 0;
_G(exitFlag) = 2;
}
// If there's an end message, pass it on to the view hierarchy.
// This is used in cases like the game end where multiple
// odinSpeaks are done in sequence
if (odinEndMessage)
g_events->send(GameMessage(odinEndMessage));
}
void odinSpeaks(const int index, int item, const char *endMessage) {
odinEndMessage = endMessage;
executeScript((long)index, _G(odin), odin_speaks_end);
}
int switchIcons() {
playSound(WOOP, false);
for (int y = 0; y < 12; y++) {
for (int x = 0; x < 20; x++) {
const int ix = x * 16;
const int iy = y * 16;
if (_G(scrn)._iconGrid[y][x] == 93) {
placeTile(x, y, 144);
} else if (_G(scrn)._iconGrid[y][x] == 144) {
placeTile(x, y, 93);
killEnemies(iy, ix);
}
if (_G(scrn)._iconGrid[y][x] == 94) {
placeTile(x, y, 146);
} else if (_G(scrn)._iconGrid[y][x] == 146) {
placeTile(x, y, 94);
killEnemies(iy, ix);
}
}
}
return 0;
}
int rotateArrows() {
playSound(WOOP, false);
for (int y = 0; y < 12; y++) {
for (int x = 0; x < 20; x++) {
if (_G(scrn)._iconGrid[y][x] == 205)
placeTile(x, y, 208);
else if (_G(scrn)._iconGrid[y][x] == 206)
placeTile(x, y, 207);
else if (_G(scrn)._iconGrid[y][x] == 207)
placeTile(x, y, 205);
else if (_G(scrn)._iconGrid[y][x] == 208)
placeTile(x, y, 206);
}
}
return 0;
}
void killEnemies(const int iy, const int ix) {
int x1, y1, x2, y2;
for (int i = 3; i < MAX_ACTORS; i++) {
if (_G(actor[i])._active) {
x1 = _G(actor[i])._x;
y1 = _G(actor[i])._y + _G(actor[i])._sizeY - 2;
x2 = (_G(actor[i])._x + _G(actor[i])._sizeX);
y2 = _G(actor[i])._y + _G(actor[i])._sizeY - 1;
if (pointWithin(x1, y1, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y1, ix, iy, ix + 15, iy + 15)
|| pointWithin(x1, y2, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y2, ix, iy, ix + 15, iy + 15))
actorDestroyed(&_G(actor[i]));
}
}
x1 = _G(thor)->_x;
y1 = _G(thor)->_y + 11;
x2 = x1 + 13;
y2 = y1 + 5;
if (pointWithin(x1, y1, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y1, ix, iy, ix + 15, iy + 15)
|| pointWithin(x1, y2, ix, iy, ix + 15, iy + 15) || pointWithin(x2, y2, ix, iy, ix + 15, iy + 15)) {
if (!_G(cheats)._freezeHealth) {
_G(thor)->_health = 0;
g_events->send(GameMessage("THOR_DIES"));
}
}
}
void removeObjects(const int y, const int x) {
const int p = (y * 20) + x;
if (_G(objectMap[p]) > 0) {
_G(objectMap[p]) = 0;
_G(objectIndex[p]) = 0;
}
}
void placeTile(const int x, const int y, const int tile) {
_G(scrn)._iconGrid[y][x] = tile;
removeObjects(y, x);
}
int backgroundTile(int x, int y) {
if (x < 0 || x >= 319 || y < 0 || y >= 191)
return 0;
x = (x + 1) >> 4;
y = (y + 1) >> 4;
return _G(scrn)._iconGrid[y][x];
}
void selectItem() {
// Only allow opening the dialog if something isn't currently going on
if (g_engine->canSaveAutosaveCurrently()) {
g_events->addView("SelectItem");
}
}
void actorSpeaks(const Actor *actor, int index, int item) {
if (actor->_type != 4)
return;
const int v = atoi(actor->_name);
if (v < 1 || v > 20)
return;
long lind = (long)_G(currentLevel);
lind = lind * 1000;
lind += (long)actor->_actorNum;
const Common::String str = Common::String::format("FACE%d", v);
if (Common::File::exists(Common::Path(str))) {
Gfx::Pics pics(str, 262);
executeScript(lind, pics);
} else {
executeScript(lind, _G(odin));
}
if (!_G(thor)->_health) {
_G(thor)->_show = 0;
_G(exitFlag) = 2;
}
}
} // namespace Got

52
engines/got/game/back.h Normal file
View File

@@ -0,0 +1,52 @@
/* 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 GOT_GAME_BACK_H
#define GOT_GAME_BACK_H
#include "got/data/defines.h"
namespace Got {
extern const char *OBJECT_NAMES[];
extern const char *ITEM_NAMES[];
/**
* Shows a new level
* In the original this did some initial actors setup and rendering.
* Now in ScummVM, it only does the setup portions, since the
* GameContent view takes care of the scene rendering.
*/
extern void showLevel(int newLevel);
extern void showLevelDone();
extern void odinSpeaks(int index, int item, const char *endMessage = nullptr);
extern int switchIcons();
extern int rotateArrows();
extern void killEnemies(int iy, int ix);
extern void removeObjects(int y, int x);
extern void placeTile(int x, int y, int tile);
extern int backgroundTile(int x, int y);
extern void selectItem();
extern void actorSpeaks(const Actor *actor, int index, int item);
} // namespace Got
#endif

298
engines/got/game/boss1.cpp Normal file
View File

@@ -0,0 +1,298 @@
/* 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 "got/game/boss1.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/move_patterns.h"
#include "got/game/status.h"
#include "got/gfx/image.h"
#include "got/sound.h"
#include "got/vars.h"
namespace Got {
static int boss1_dead();
int boss1Movement(Actor *actor) {
bool f = false;
if (_G(bossDead))
return boss1_dead();
int d = actor->_lastDir;
int x1 = actor->_x;
int y1 = actor->_y;
if (actor->_edgeCounter) {
actor->_edgeCounter--;
goto done;
}
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 30, actor->_y + 30,
_G(thor)->_x, _G(thor)->_y + 8, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
thorDamaged(actor);
}
if (actor->_temp3) { //start striking
actor->_temp3--;
if (!actor->_temp3)
playSound(BOSS11, false);
actor->_numMoves = 6;
goto done0;
}
// Strike
if (actor->_temp1) {
actor->_temp1--;
if (actor->_x < (_G(thorX1) + 12))
actor->_temp1 = 0;
actor->_temp2 = 1;
d = 2;
actor->_x -= 2;
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 32, actor->_y + 30,
_G(thor)->_x, _G(thor)->_y + 8, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
actor->_temp1 = 0;
goto done1;
}
actor->_nextFrame = 3;
actor->_numMoves = _G(setup)._difficultyLevel + 2;
goto done1;
}
if (actor->_temp2) { // Retreating
if (actor->_x < 256) {
d = 3;
actor->_x += 2;
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 32, actor->_y + 30,
_G(thor)->_x, _G(thor)->_y + 8, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
goto done1;
}
actor->_numMoves = _G(setup)._difficultyLevel + 1;
goto done0;
}
actor->_temp2 = 0;
}
if (actor->_x > _G(thorX1) && ABS((_G(thorY1)) - (actor->_y + 20)) < 8) {
actor->_temp3 = 75;
actor->_temp1 = 130;
actor->_temp2 = 0;
}
if (actor->_counter) {
actor->_counter--;
switch (d) {
case 1:
case 3:
x1 = _G(actor[5])._x;
y1 = _G(actor[5])._y;
y1 += 2;
if (!checkMove2(x1, y1, &_G(actor[5])))
f = true;
else {
actor->_x = _G(actor[5])._x;
actor->_y = _G(actor[5])._y - 16;
}
break;
case 0:
case 2:
y1 -= 2;
if (!checkMove2(x1, y1, actor))
f = true;
break;
default:
break;
}
} else
f = true;
if (f) {
actor->_counter = g_events->getRandomNumber(10, 99);
d = g_events->getRandomNumber(1);
actor->_edgeCounter = 20;
}
done:
if (d > 1)
d -= 2;
done0:
nextFrame(actor);
if (actor->_nextFrame == 3)
actor->_nextFrame = 0;
done1:
actor->_lastDir = d;
_G(actor[4])._nextFrame = actor->_nextFrame;
_G(actor[5])._nextFrame = actor->_nextFrame;
_G(actor[6])._nextFrame = actor->_nextFrame;
_G(actor[4])._lastDir = d;
_G(actor[5])._lastDir = d;
_G(actor[6])._lastDir = d;
_G(actor[4])._x = actor->_x + 16;
_G(actor[4])._y = actor->_y;
_G(actor[5])._x = actor->_x;
_G(actor[5])._y = actor->_y + 16;
_G(actor[6])._x = actor->_x + 16;
_G(actor[6])._y = actor->_y + 16;
_G(actor[4])._numMoves = actor->_numMoves;
_G(actor[5])._numMoves = actor->_numMoves;
_G(actor[6])._numMoves = actor->_numMoves;
if (actor->_directions == 1)
return 0;
return d;
}
void boss1CheckHit(const Actor *actor, const int x1, const int y1, const int x2, const int y2, const int actorNum) {
if (actor->_moveType == 15 && actorNum == 4) {
if ((!_G(actor[3])._vulnerableCountdown) && (_G(actor[3])._nextFrame != 3) &&
overlap(x1, y1, x2, y2, actor->_x + 6, actor->_y + 4, actor->_x + 14, actor->_y + 20)) {
actorDamaged(&_G(actor[3]), _G(hammer)->_hitStrength);
if (_G(cheat) && _G(keyFlag[GOT_Z]))
_G(actor[3])._health = 0;
else
_G(actor[3])._health -= 10;
_G(actor[3])._moveCountdown = 50;
_G(actor[3])._vulnerableCountdown = 100;
playSound(BOSS13, true);
_G(actor[3])._nextFrame = 1;
for (int rep = 4; rep < 7; rep++) {
_G(actor[rep])._nextFrame = 1;
_G(actor[rep])._moveCountdown = 50;
}
if (_G(actor[3])._health == 0)
_G(bossDead) = true;
}
}
}
void boss1SetupLevel() {
setupBoss(1);
_G(bossActive) = true;
musicPause();
playSound(BOSS11, true);
g_events->send("Game", GameMessage("PAUSE", 40));
musicPlay(5, true);
}
static int boss1_dead() {
if (_G(bossDead)) {
for (int rep = 0; rep < 4; rep++) {
const int x1 = _G(actor[3 + rep])._lastX[_G(pge)];
const int y1 = _G(actor[3 + rep])._lastY[_G(pge)];
const int x = _G(actor[3 + rep])._x;
const int y = _G(actor[3 + rep])._y;
const int n = _G(actor[3 + rep])._actorNum;
const int r = _G(actor[3 + rep])._dropRating;
_G(actor[3 + rep]) = _G(explosion);
_G(actor[3 + rep])._actorNum = n;
_G(actor[3 + rep])._dropRating = r;
_G(actor[3 + rep])._x = x;
_G(actor[3 + rep])._y = y;
_G(actor[3 + rep])._lastX[_G(pge)] = x1;
_G(actor[3 + rep])._lastX[_G(pge) ^ 1] = x;
_G(actor[3 + rep])._lastY[_G(pge)] = y1;
_G(actor[3 + rep])._lastY[_G(pge) ^ 1] = y;
_G(actor[3 + rep])._active = true;
_G(actor[3 + rep])._vulnerableCountdown = 255;
_G(actor[3 + rep])._moveType = 6;
_G(actor[3 + rep])._nextFrame = rep;
_G(actor[3 + rep])._speed = g_events->getRandomNumber(6, 8);
_G(actor[3 + rep])._currNumShots = (10 - _G(actor[3 + rep])._speed) * 10;
_G(actor[3 + rep])._moveCountdown = _G(actor[3 + rep])._speed;
}
playSound(EXPLODE, true);
_G(bossDead) = true;
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
}
return _G(actor[3])._lastDir;
}
void boss1ClosingSequence1() {
_G(gameOver) = true;
musicPlay(4, true);
odinSpeaks(1001, 13, "CLOSING");
}
void boss1ClosingSequence2() {
_G(thorInfo)._armor = 1;
loadNewThor();
_G(thor)->_dir = 1;
_G(thor)->_nextFrame = 0;
fillScore(20, "CLOSING");
}
void boss1ClosingSequence3() {
fillHealth();
fillMagic();
odinSpeaks(1002, 0, "CLOSING");
}
void boss1ClosingSequence4() {
for (int rep = 0; rep < 16; rep++)
_G(scrn)._actorType[rep] = 0;
_G(bossDead) = false;
_G(setup)._bossDead[0] = true;
_G(bossActive) = false;
_G(scrn)._music = 4;
showLevel(BOSS_LEVEL1);
#ifdef USE_TTS
_G(thorInfo)._previousScore = -1;
#endif
playSound(ANGEL, true);
placeTile(18, 6, 148);
placeTile(19, 6, 202);
actorVisible(1);
actorVisible(2);
Level lvl;
lvl.load(59);
lvl._iconGrid[6][18] = 148;
lvl._iconGrid[6][19] = 202;
lvl.save(59);
}
} // namespace Got

40
engines/got/game/boss1.h Normal file
View File

@@ -0,0 +1,40 @@
/* 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 GOT_GAME_BOSS1_H
#define GOT_GAME_BOSS1_H
#include "got/data/defines.h"
namespace Got {
// Boss 1 - Snake (Jormangund)
extern int boss1Movement(Actor *actor);
extern void boss1CheckHit(const Actor *actor, int x1, int y1, int x2, int y2, int actorNum);
extern void boss1SetupLevel();
extern void boss1ClosingSequence1();
extern void boss1ClosingSequence2();
extern void boss1ClosingSequence3();
extern void boss1ClosingSequence4();
} // namespace Got
#endif

436
engines/got/game/boss2.cpp Normal file
View File

@@ -0,0 +1,436 @@
/* 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 "got/game/boss2.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/status.h"
#include "got/gfx/image.h"
#include "got/sound.h"
#include "got/vars.h"
namespace Got {
static const byte EXPLOSION[] = {
61, 62, 65, 66, 69, 70, 73, 74, 77, 78,
81, 82, 85, 86, 89, 90, 93, 94, 97, 98,
101, 102, 105, 106, 109, 110, 113, 114, 117, 118,
121, 122, 125, 126, 129, 130, 133, 134, 137, 138,
141, 142, 145, 146, 149, 150, 153, 154, 157, 158,
161, 162, 165, 166, 169, 170, 173, 174, 177, 178
};
static bool expf[60];
static byte numSkulls;
static byte numSpikes;
static bool dropFlag;
static byte su[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int boss2MovementExplode(Actor *actor);
static int boss2MovementShake(Actor *actor);
static int boss2Die();
static void bossSet(byte d, int x, int y);
int boss2Movement(Actor *actor) {
switch (_G(setup)._difficultyLevel) {
case 0:
numSkulls = 3;
numSpikes = 5;
break;
case 1:
numSkulls = 6;
numSpikes = 8;
break;
case 2:
numSkulls = 9;
numSpikes = 11;
break;
default:
break;
}
if (_G(bossDead))
return boss2Die();
if (actor->_i1) {
if (actor->_i1 == 1)
return boss2MovementExplode(actor);
return boss2MovementShake(actor);
}
byte d = actor->_lastDir;
int x = actor->_x;
if (actor->_temp6)
actor->_temp6--;
if (!actor->_temp6) {
bool f = false;
dropFlag = false;
if (actor->_temp5)
actor->_temp5--;
if (!actor->_temp5)
f = true;
else {
if (d == 2) {
if (x > 18)
actor->_x -= 2;
else
f = true;
} else if (d == 3) {
if (x < 272)
actor->_x += 2;
else
f = true;
}
}
if (f) {
actor->_temp5 = _G(rand1) + 60;
if (d == 2)
d = 3;
else
d = 2;
}
}
const int count = actor->_frameCount - 1;
if (count <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 2)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = count;
x = actor->_x;
if (actor->_currNumShots < numSkulls && !dropFlag) {
if (x == 48 || x == 112 || x == 176 || x == 240) {
dropFlag = true;
_G(actor[3])._temp6 = 40;
actorAlwaysShoots(actor, 1);
playSound(FALL, false);
_G(actor[actor->_shotActor])._x = actor->_x + 12;
_G(actor[actor->_shotActor])._y = actor->_y + 32;
_G(actor[actor->_shotActor])._temp2 = 0;
_G(actor[actor->_shotActor])._temp3 = 4;
_G(actor[actor->_shotActor])._temp4 = 4;
}
}
bossSet(d, x, actor->_y);
if (actor->_directions == 1)
return 0;
return d;
}
static void bossSet(const byte d, const int x, const int y) {
_G(actor[4])._nextFrame = _G(actor[3])._nextFrame;
_G(actor[5])._nextFrame = _G(actor[3])._nextFrame;
_G(actor[6])._nextFrame = _G(actor[3])._nextFrame;
_G(actor[3])._lastDir = d;
_G(actor[4])._lastDir = d;
_G(actor[5])._lastDir = d;
_G(actor[6])._lastDir = d;
_G(actor[4])._x = x + 16;
_G(actor[4])._y = y;
_G(actor[5])._x = x;
_G(actor[5])._y = y + 16;
_G(actor[6])._x = x + 16;
_G(actor[6])._y = y + 16;
}
void boss2CheckHit(Actor *actor) {
if (!_G(actor[3])._vulnerableCountdown) {
actorDamaged(&_G(actor[3]), _G(hammer)->_hitStrength);
_G(actor[3])._health -= 10;
if (_G(actor[3])._health == 50) {
playSound(BOSS12, true);
g_events->send("Game", GameMessage("PAUSE", 40));
_G(actor[3])._i1 = 1;
_G(actor[3])._i2 = 0;
memset(expf, 0, sizeof(expf));
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
_G(actor[3])._currNumShots = 0;
} else
playSound(BOSS13, true);
_G(actor[3])._moveCountdown = 75;
_G(actor[3])._vulnerableCountdown = 75;
_G(actor[3])._nextFrame = 1;
for (int rep = 4; rep < 7; rep++) {
_G(actor[rep])._nextFrame = 1;
_G(actor[rep])._moveCountdown = 50;
}
if (_G(actor[3])._health == 0) {
_G(bossDead) = true;
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
}
}
}
void boss2SetupLevel() {
setupBoss(2);
_G(bossActive) = true;
musicPause();
playSound(BOSS11, true);
dropFlag = false;
Common::fill(su, su + 18, 0);
g_events->send("Game", GameMessage("PAUSE", 40));
musicPlay(7, true);
}
static int boss2Die() {
_G(thunderSnakeCounter) = 0;
if (_G(bossDead)) {
for (int rep = 0; rep < 4; rep++) {
const int x1 = _G(actor[3 + rep])._lastX[_G(pge)];
const int y1 = _G(actor[3 + rep])._lastY[_G(pge)];
const int x = _G(actor[3 + rep])._x;
const int y = _G(actor[3 + rep])._y;
const int n = _G(actor[3 + rep])._actorNum;
const int r = _G(actor[3 + rep])._dropRating;
_G(actor[3 + rep]) = _G(explosion);
_G(actor[3 + rep])._actorNum = n;
_G(actor[3 + rep])._dropRating = r;
_G(actor[3 + rep])._x = x;
_G(actor[3 + rep])._y = y;
_G(actor[3 + rep])._lastX[_G(pge)] = x1;
_G(actor[3 + rep])._lastX[_G(pge) ^ 1] = x;
_G(actor[3 + rep])._lastY[_G(pge)] = y1;
_G(actor[3 + rep])._lastY[_G(pge) ^ 1] = y;
_G(actor[3 + rep])._active = true;
_G(actor[3 + rep])._vulnerableCountdown = 255;
_G(actor[3 + rep])._moveType = 6;
_G(actor[3 + rep])._nextFrame = rep;
_G(actor[3 + rep])._speed = g_events->getRandomNumber(6, 8);
_G(actor[3 + rep])._currNumShots = (10 - _G(actor[3 + rep])._speed) * 10;
_G(actor[3 + rep])._moveCountdown = _G(actor[3 + rep])._speed;
}
playSound(EXPLODE, true);
_G(bossDead) = true;
}
return _G(actor[3])._lastDir;
}
// Boss - skull (explode)
static int boss2MovementExplode(Actor *actor) {
nextFrame(actor);
_G(actor[4])._nextFrame = actor->_nextFrame;
_G(actor[5])._nextFrame = actor->_nextFrame;
_G(actor[6])._nextFrame = actor->_nextFrame;
actor->_vulnerableCountdown = 20;
if (actor->_currNumShots || _G(actor[5])._currNumShots)
return 0;
playSound(EXPLODE, true);
actorAlwaysShoots(&_G(actor[5]), 0);
const int an = _G(actor[5])._shotActor;
_G(actor[an])._moveType = 9;
int r = _G(rand1) % 60;
while (expf[r]) {
r++;
if (r > 59)
r = 0;
}
expf[r] = true;
const int x = (EXPLOSION[r] % 20) * 16;
const int y = (EXPLOSION[r] / 20) * 16;
_G(actor[an])._x = x;
_G(actor[an])._y = y;
_G(scrn)._iconGrid[y / 16][x / 16] = _G(scrn)._backgroundColor;
_G(actor[3])._i2++;
if (_G(actor[3])._i2 > 59) {
_G(actor[3])._i1 = 2;
_G(actor[3])._i2 = 0;
_G(actor[3])._numMoves = 3;
}
return 0;
}
// Boss - skull - shake
static int boss2MovementShake(Actor *actor) {
int rep, hx;
if (_G(hammer)->_active && _G(hammer)->_moveType != 5) {
hx = _G(hammer)->_x;
const int hy = _G(hammer)->_y;
for (rep = 7; rep < 15; rep++) {
if (!_G(actor[rep])._active)
continue;
if (overlap(hx + 1, hy + 1, hx + 10, hy + 10, _G(actor[rep])._x, _G(actor[rep])._y,
_G(actor[rep])._x + _G(actor[rep])._sizeX - 1, _G(actor[rep])._y + _G(actor[rep])._sizeY - 1)) {
_G(hammer)->_moveType = 5;
_G(hammer)->_dir = reverseDirection(_G(hammer));
break;
}
}
}
if (actor->_i4) {
actor->_i4--;
if (!actor->_i4)
_G(thunderSnakeCounter) = 0;
}
if (!actor->_i2) {
if (actor->_x < 144)
actor->_x += 2;
else if (actor->_x > 144)
actor->_x -= 2;
else {
actor->_i2 = 1;
actor->_i3 = 0;
}
goto done;
}
if (_G(actor[4])._currNumShots)
goto done;
if (!actor->_i3) {
actor->_i3 = g_events->getRandomNumber(2, 3);
}
if (actor->_i3 == 2)
actor->_x -= 2;
else
actor->_x += 2;
if (actor->_x < 20 || actor->_x > 270) {
_G(thunderSnakeCounter) = 100;
actor->_i4 = 50;
playSound(EXPLODE, true);
actor->_i2 = 0;
Common::fill(su, su + 18, 0);
actorAlwaysShoots(&_G(actor[4]), 1);
int an = _G(actor[4])._shotActor;
hx = (_G(thor)->_x / 16);
_G(actor[an])._x = _G(thor)->_x; //hx*16;
_G(actor[an])._y = g_events->getRandomNumber(15);
su[hx] = 1;
_G(actor[an])._nextFrame = g_events->getRandomNumber(3);
for (rep = 0; rep < numSpikes; rep++) {
while (true) {
hx = g_events->getRandomNumber(17);
if (!su[hx])
break;
}
su[hx] = 1;
actorAlwaysShoots(&_G(actor[4]), 1);
an = _G(actor[4])._shotActor;
_G(actor[an])._nextFrame = g_events->getRandomNumber(3);
_G(actor[an])._x = 16 + hx * 16;
_G(actor[an])._y = g_events->getRandomNumber(15);
}
}
done:
nextFrame(actor);
bossSet(actor->_dir, actor->_x, actor->_y);
return 0;
}
void boss2ClosingSequence1() {
musicPlay(6, true);
odinSpeaks(1001, 0, "CLOSING");
}
void boss2ClosingSequence2() {
_G(thorInfo)._armor = 10;
loadNewThor();
_G(thor)->_dir = 1;
_G(thor)->_nextFrame = 0;
fillScore(20, "CLOSING");
}
void boss2ClosingSequence3() {
fillHealth();
fillMagic();
odinSpeaks(1002, 0, "CLOSING");
}
void boss2ClosingSequence4() {
for (int rep = 0; rep < 16; rep++)
_G(scrn)._actorType[rep] = 0;
_G(bossDead) = false;
_G(setup)._bossDead[1] = true;
_G(gameOver) = true;
_G(bossActive) = false;
_G(scrn)._music = 6;
showLevel(BOSS_LEVEL2);
#ifdef USE_TTS
_G(thorInfo)._previousScore = -1;
#endif
playSound(ANGEL, true);
placeTile(18, 10, 152);
placeTile(19, 10, 202);
actorVisible(1);
actorVisible(2);
_G(actor[7])._x = 288;
_G(actor[7])._y = 160;
_G(actor[8])._x = 304;
_G(actor[8])._y = 160;
Level lvl;
lvl.load(BOSS_LEVEL2);
lvl._iconGrid[6][18] = 152;
lvl._iconGrid[6][19] = 202;
lvl.save(BOSS_LEVEL2);
}
} // namespace Got

40
engines/got/game/boss2.h Normal file
View File

@@ -0,0 +1,40 @@
/* 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 GOT_GAME_BOSS2_H
#define GOT_GAME_BOSS2_H
#include "got/data/defines.h"
namespace Got {
// Boss 2 - Skull (Nognir)
extern int boss2Movement(Actor *actor);
extern void boss2CheckHit(Actor *actor);
extern void boss2SetupLevel();
extern void boss2ClosingSequence1();
extern void boss2ClosingSequence2();
extern void boss2ClosingSequence3();
extern void boss2ClosingSequence4();
} // namespace Got
#endif

666
engines/got/game/boss3.cpp Normal file
View File

@@ -0,0 +1,666 @@
/* 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 "got/game/boss3.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/move_patterns.h"
#include "got/game/status.h"
#include "got/sound.h"
#include "got/vars.h"
namespace Got {
#define LFC 10
static const byte EXPLOSION[4][8] = {
{126, 127, 128, 129, 130, 131, 132, 133},
{146, 147, 148, 149, 150, 151, 152, 153},
{166, 167, 168, 169, 170, 171, 172, 173},
{186, 187, 188, 189, 190, 191, 192, 193}
};
static int bossMode;
static int numPods1;
static byte podSpeed;
static bool explosionFlag[4][8];
static byte explosionCounter;
static int bossDie();
static void boss3CheckHit();
static void bossChangeMode();
static void setBoss(Actor *actor) {
_G(actor[4])._nextFrame = actor->_nextFrame;
_G(actor[5])._nextFrame = actor->_nextFrame;
_G(actor[6])._nextFrame = actor->_nextFrame;
_G(actor[4])._lastDir = actor->_dir;
_G(actor[5])._lastDir = actor->_dir;
_G(actor[6])._lastDir = actor->_dir;
_G(actor[4])._dir = actor->_dir;
_G(actor[5])._dir = actor->_dir;
_G(actor[6])._dir = actor->_dir;
_G(actor[4])._x = actor->_x + 16;
_G(actor[4])._y = actor->_y;
_G(actor[5])._x = actor->_x;
_G(actor[5])._y = actor->_y + 16;
_G(actor[6])._x = actor->_x + 16;
_G(actor[6])._y = actor->_y + 16;
}
// Boss - Loki-2
static int boss3Movement1(Actor *actor) {
int rx, ry, i, numPods = 0;
int fcount;
actor->_numMoves = 2;
podSpeed = 2;
switch (_G(setup)._difficultyLevel) {
case 0:
numPods = 3;
break;
case 1:
numPods = 5;
break;
case 2:
numPods = 8;
break;
default:
break;
}
if (!actor->_temp1) {
// Disappear
actor->_dir = 1;
actor->_frameCount = LFC;
actor->_nextFrame = 0;
actor->_temp1 = 1;
actor->_i6 = 1;
actor->_solid |= 128;
_G(actor[4])._solid |= 128;
_G(actor[5])._solid |= 128;
_G(actor[6])._solid |= 128;
playSound(EXPLODE, true);
goto done;
}
if (actor->_i6) {
// Fade out
fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 2) {
actor->_i6 = 0;
actor->_temp3 = 160;
}
actor->_frameCount = 3;
} else
actor->_frameCount = fcount;
goto done1;
}
if (actor->_temp3 > 1) {
actor->_temp3--;
goto done1;
}
if (actor->_temp3) {
for (i = 0; i < numPods1; i++)
if (_G(actor[19 + i])._active)
goto done1;
while (true) {
rx = g_events->getRandomNumber(255) + 16;
ry = g_events->getRandomNumber(143);
if (!overlap(rx, ry, rx + 32, ry + 32, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2)))
break;
}
actor->_x = rx;
actor->_y = ry;
actor->_frameCount = LFC;
actor->_temp4 = 40;
actor->_temp3 = 0;
playSound(EXPLODE, true);
goto done1;
}
if (actor->_temp4) {
// Fade in
fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame--;
if (actor->_nextFrame > 254) {
actor->_nextFrame = 0;
actor->_dir = 0;
actor->_temp4 = 0;
actor->_temp5 = 80;
actor->_solid &= 0x7f;
_G(actor[4])._solid &= 0x7f;
_G(actor[5])._solid &= 0x7f;
_G(actor[6])._solid &= 0x7f;
}
actor->_frameCount = 3;
} else
actor->_frameCount = fcount;
goto done1;
}
if (actor->_temp5) {
// Shoot
actor->_temp5--;
if (actor->_temp5 == 20) {
actor->_nextFrame = 3;
goto done1;
}
if (!actor->_temp5) {
if (_G(actor[4])._currNumShots < _G(actor[4])._numShotsAllowed) {
actorAlwaysShoots(&_G(actor[4]), 0);
const byte shot_actor = _G(actor[4])._shotActor;
_G(actor[shot_actor])._numMoves = podSpeed;
_G(actor[shot_actor])._x = actor->_x + 8;
_G(actor[shot_actor])._y = actor->_y + 16;
_G(actor[shot_actor])._temp5 = 0;
for (i = 0; i < numPods; i++)
_G(actor[20 + i]) = _G(actor[19]);
numPods1 = numPods;
actor->_temp1 = 0;
}
}
if (actor->_temp5 < 31)
goto done1;
}
done:
fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 2)
actor->_nextFrame = 0;
actor->_frameCount = LFC;
} else
actor->_frameCount = fcount;
done1:
setBoss(actor);
return actor->_dir;
}
// Boss - Loki-1
int boss3Movement(Actor *actor) {
int x1, y1, ox, oy;
int fcount;
if (actor->_temp2)
actor->_temp2--;
if (_G(bossDead))
return bossDie();
boss3CheckHit();
if (!bossMode)
return boss3Movement1(actor);
numPods1 = 10;
switch (_G(setup)._difficultyLevel) {
case 0:
actor->_numMoves = 3;
actor->_speed = 2;
break;
case 1:
actor->_numMoves = 2;
actor->_speed = 1;
break;
case 2:
actor->_numMoves = 5;
actor->_speed = 2;
break;
default:
break;
}
int d = actor->_lastDir;
actor->_temp3++;
int f = 0;
if (actor->_temp4) {
actor->_temp4--;
if (!actor->_temp4) {
actor->_temp3 = 0;
_G(actor[3])._frameSpeed = 4;
_G(actor[3])._dir = 0;
_G(actor[3])._lastDir = 0;
_G(actor[3])._nextFrame = 3;
_G(actor[4])._dir = 0;
_G(actor[4])._lastDir = 0;
_G(actor[4])._nextFrame = 3;
}
goto skip_move;
}
if (actor->_edgeCounter)
actor->_edgeCounter--;
else
goto new_dir;
if (overlap(actor->_x + 2, actor->_y + 8, actor->_x + 30, actor->_y + 30, _G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15))
thorDamaged(actor);
ox = actor->_x;
oy = actor->_y;
switch (actor->_temp5) {
case 0:
x1 = _G(actor[3])._x;
y1 = _G(actor[3])._y - 2;
if (!checkMove2(x1, y1, &_G(actor[3]))) {
f = 1;
break;
}
if (!checkMove2(x1 + 16, y1, &_G(actor[4])))
f = 1;
actor->_y = oy - 2;
break;
case 1:
x1 = _G(actor[5])._x;
y1 = _G(actor[5])._y + 2;
if (!checkMove2(x1, y1, &_G(actor[5]))) {
f = 1;
break;
}
if (!checkMove2(x1 + 16, y1, &_G(actor[6])))
f = 1;
actor->_y = oy + 2;
break;
case 2:
x1 = _G(actor[3])._x - 2;
y1 = _G(actor[3])._y;
if (!checkMove2(x1, y1, &_G(actor[3]))) {
f = 1;
break;
}
if (!checkMove2(x1, y1 + 16, &_G(actor[5])))
f = 1;
actor->_x = ox - 2;
break;
case 3:
x1 = _G(actor[4])._x + 2;
y1 = _G(actor[4])._y;
if (!checkMove2(x1, y1, &_G(actor[4]))) {
f = 1;
break;
}
if (!checkMove2(x1, y1 + 16, &_G(actor[6])))
f = 1;
actor->_x = ox + 2;
break;
case 4: //ul
x1 = _G(actor[3])._x - 2;
y1 = _G(actor[3])._y - 2;
if (!checkMove2(x1, y1, &_G(actor[3]))) {
f = 1;
break;
}
actor->_x = ox - 2;
actor->_y = oy - 2;
break;
case 5:
x1 = _G(actor[4])._x + 2;
y1 = _G(actor[4])._y - 2;
if (!checkMove2(x1, y1, &_G(actor[4]))) {
f = 1;
break;
}
actor->_x = ox + 2;
actor->_y = oy - 2;
break;
case 6:
x1 = _G(actor[6])._x + 2;
y1 = _G(actor[6])._y + 2;
if (!checkMove2(x1, y1, &_G(actor[6]))) {
f = 1;
break;
}
actor->_x = ox + 2;
actor->_y = oy + 2;
break;
case 7:
x1 = _G(actor[5])._x - 2;
y1 = _G(actor[5])._y + 2;
if (!checkMove2(x1, y1, &_G(actor[5]))) {
f = 1;
break;
}
actor->_x = ox - 2;
actor->_y = oy + 2;
break;
default:
break;
}
fcount = actor->_frameCount - 1;
if (fcount) {
actor->_nextFrame++;
if (actor->_nextFrame > 2)
actor->_nextFrame = 0;
actor->_frameCount = 30;
} else
actor->_frameCount = fcount;
skip_move:
setBoss(actor);
if (!f)
goto done;
new_dir:
if (actor->_temp3 < 120)
goto new_dir1;
_G(actor[3])._frameSpeed = 8;
_G(actor[3])._nextFrame = 3;
_G(actor[4])._nextFrame = 3;
actor->_temp4 = 120;
actorAlwaysShoots(actor, 0);
_G(actor[actor->_shotActor])._x = actor->_x + 8;
_G(actor[actor->_shotActor])._y = actor->_y - 8;
_G(actor[actor->_shotActor])._temp1 = g_events->getRandomNumber(90, 189);
_G(actor[actor->_shotActor])._temp5 = 30;
_G(actor[actor->_shotActor])._speed = 2;
playSound(BOSS12, true);
new_dir1:
actor->_temp5 = _G(rand1) % 8;
actor->_edgeCounter = _G(rand2) + 60;
done:
if (actor->_directions == 1)
return 0;
return d;
}
static void boss3CheckHit() {
if (_G(actor[3])._solid & 128) {
for (int rep = 3; rep < 7; rep++)
_G(actor[rep])._magicHit = 0;
return;
}
if (_G(actor[3])._magicHit || _G(actor[4])._magicHit || _G(actor[5])._magicHit || _G(actor[6])._magicHit) {
if (!_G(actor[3])._temp2) {
actorDamaged(&_G(actor[3]), 10);
if (_G(cheat) && _G(keyFlag[GOT_Z]))
_G(actor[3])._health -= 50;
else
_G(actor[3])._health -= 10;
_G(actor[3])._moveCountdown = 50;
_G(actor[3])._vulnerableCountdown = 50;
playSound(BOSS13, true);
for (int rep = 4; rep < 7; rep++) {
_G(actor[rep])._magicHit = 0;
_G(actor[rep])._nextFrame = 1;
_G(actor[rep])._moveCountdown = 50;
}
if (_G(actor[3])._health == 0) {
_G(bossDead) = true;
for (int rep = 7; rep < MAX_ACTORS; rep++) {
if (_G(actor[rep])._active)
actorDestroyed(&_G(actor[rep]));
}
}
if (_G(actor[3])._health == 50) {
bossChangeMode();
_G(actor[3])._temp1 = 0;
_G(actor[3])._temp2 = 0;
_G(actor[3])._temp3 = 0;
_G(actor[3])._temp4 = 0;
_G(actor[3])._temp5 = 0;
_G(actor[3])._i6 = 0;
_G(actor[3])._moveCountdown = 2;
} else {
_G(actor[3])._temp2 = 40;
}
}
for (int rep = 3; rep < 7; rep++)
_G(actor[rep])._magicHit = 0;
}
}
static void bossChangeMode() {
if (!_G(bossIntro2)) {
Gfx::Pics loki("FACE18", 262);
executeScript(1003, loki);
_G(bossIntro2) = true;
}
bossMode = 0;
}
void boss3SetupLevel() {
setupBoss(3);
_G(bossActive) = true;
musicPause();
playSound(BOSS11, true);
g_events->send("Game", GameMessage("PAUSE", 40));
if (!_G(bossIntro1)) {
Gfx::Pics loki("FACE18", 262);
executeScript(1002, loki);
_G(bossIntro1) = true;
}
musicPlay(7, true);
_G(appleDropCounter) = 0;
bossMode = 1;
}
static int bossDie() {
if (_G(bossDead)) {
for (int rep = 0; rep < 4; rep++) {
const int x1 = _G(actor[3 + rep])._lastX[_G(pge)];
const int y1 = _G(actor[3 + rep])._lastY[_G(pge)];
const int x = _G(actor[3 + rep])._x;
const int y = _G(actor[3 + rep])._y;
const int n = _G(actor[3 + rep])._actorNum;
const int r = _G(actor[3 + rep])._dropRating;
_G(actor[3 + rep]) = _G(explosion);
_G(actor[3 + rep])._actorNum = n;
_G(actor[3 + rep])._dropRating = r;
_G(actor[3 + rep])._x = x;
_G(actor[3 + rep])._y = y;
_G(actor[3 + rep])._lastX[_G(pge)] = x1;
_G(actor[3 + rep])._lastX[_G(pge) ^ 1] = x;
_G(actor[3 + rep])._lastY[_G(pge)] = y1;
_G(actor[3 + rep])._lastY[_G(pge) ^ 1] = y;
_G(actor[3 + rep])._active = true;
_G(actor[3 + rep])._vulnerableCountdown = 255;
_G(actor[3 + rep])._moveType = 6;
_G(actor[3 + rep])._nextFrame = rep;
_G(actor[3 + rep])._speed = g_events->getRandomNumber(6, 8);
_G(actor[3 + rep])._currNumShots = (10 - _G(actor[3 + rep])._speed) * 10;
_G(actor[3 + rep])._moveCountdown = _G(actor[3 + rep])._speed;
}
playSound(EXPLODE, true);
_G(bossDead) = true;
}
return _G(actor[3])._lastDir;
}
void boss3ClosingSequence1() {
musicPlay(6, true);
odinSpeaks(1001, 0, "CLOSING");
}
void boss3ClosingSequence2() {
fillScore(20, "CLOSING");
}
void boss3ClosingSequence3() {
fillHealth();
fillMagic();
for (int rep = 0; rep < 16; rep++)
_G(scrn)._actorType[rep] = 0;
_G(bossDead) = false;
_G(setup)._bossDead[2] = true;
_G(gameOver) = true;
_G(bossActive) = false;
_G(scrn)._music = 6;
showLevel(BOSS_LEVEL3);
#ifdef USE_TTS
_G(thorInfo)._previousScore = -1;
#endif
_G(exitFlag) = 0;
musicPause();
_G(newLevel) = ENDING_SCREEN;
_G(thor)->_x = 152;
_G(thor)->_y = 160;
_G(thor)->_dir = 1;
}
void endingScreen() {
for (int i = 3; i < MAX_ACTORS; i++)
_G(actor[i])._moveType = 1;
musicPlay(6, true);
memset(explosionFlag, 0, sizeof(explosionFlag));
_G(endGame) = 1;
_G(explosionRow) = 0;
explosionCounter = 0;
_G(actor[34]) = _G(explosion);
_G(actor[34])._active = false;
_G(actor[34])._speed = 2;
_G(actor[34])._moveCountdown = _G(actor[34])._speed;
_G(actor[34])._currNumShots = 3; // Used to reverse explosion
_G(actor[34])._vulnerableCountdown = 255;
_G(actor[34])._i2 = 6;
}
// Explode
int endgame_one() {
if (_G(actor[34])._i2) {
_G(actor[34])._i2--;
return 0;
}
_G(actor[34])._i2 = 6;
playSound(EXPLODE, true);
int r = _G(rand1) % 32;
while (explosionFlag[r / 8][r % 8]) {
r++;
if (r > 31)
r = 0;
}
explosionFlag[r / 8][r % 8] = true;
int x = (EXPLOSION[r / 8][r % 8] % 20) * 16;
int y = (EXPLOSION[r / 8][r % 8] / 20) * 16;
_G(actor[34])._x = x;
_G(actor[34])._y = y;
_G(actor[34])._active = true;
_G(actor[34])._nextFrame = 0;
_G(actor[34])._currNumShots = 3;
_G(scrn)._iconGrid[y / 16][x / 16] = _G(scrn)._backgroundColor;
_G(endGame++);
if (_G(endGame) > 32) {
_G(actor[34])._active = false;
_G(endGame) = 0;
}
return 1;
}
// Explode
int endGameMovement() {
if (!_G(endGame))
return 0;
if (explosionCounter > 3) {
endgame_one();
return 0;
}
if (_G(actor[34])._i2) {
_G(actor[34])._i2--;
return 0;
}
_G(actor[34])._i2 = 6;
playSound(EXPLODE, true);
int r = _G(rand1) % 8;
while (explosionFlag[_G(explosionRow)][r]) {
r++;
if (r > 7)
r = 0;
}
explosionFlag[_G(explosionRow)][r] = true;
const int x = (EXPLOSION[_G(explosionRow)][r] % 20) * 16;
const int y = (EXPLOSION[_G(explosionRow)][r] / 20) * 16;
_G(actor[34])._x = x;
_G(actor[34])._y = y;
_G(actor[34])._active = true;
_G(actor[34])._nextFrame = 0;
_G(actor[34])._currNumShots = 3;
_G(scrn)._iconGrid[y / 16][x / 16] = _G(scrn)._backgroundColor;
_G(scrn)._iconGrid[(y / 16) - 4][x / 16] = _G(scrn)._backgroundColor;
_G(endGame++);
if (_G(endGame) > 8) {
_G(endGame) = 1;
_G(explosionRow++);
explosionCounter++;
if (explosionCounter > 3) {
memset(explosionFlag, 0, sizeof(explosionFlag));
}
}
return 1;
}
} // namespace Got

40
engines/got/game/boss3.h Normal file
View File

@@ -0,0 +1,40 @@
/* 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 GOT_GAME_BOSS3_H
#define GOT_GAME_BOSS3_H
#include "got/data/defines.h"
namespace Got {
// Boss 3 - Loki
extern int boss3Movement(Actor *actor);
extern void boss3SetupLevel();
extern void endingScreen();
extern void boss3ClosingSequence1();
extern void boss3ClosingSequence2();
extern void boss3ClosingSequence3();
extern int endGameMovement();
} // namespace Got
#endif

118
engines/got/game/init.cpp Normal file
View File

@@ -0,0 +1,118 @@
/* 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 "got/game/init.h"
#include "common/memstream.h"
#include "common/textconsole.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/gfx/image.h"
#include "got/sound.h"
#include "got/utils/file.h"
#include "got/vars.h"
namespace Got {
void setupPlayer() {
_G(thorInfo).clear();
_G(thorInfo)._inventory = 0;
if (_G(area) > 1)
_G(thorInfo)._inventory |= APPLE_MAGIC + LIGHTNING_MAGIC;
if (_G(area) > 2)
_G(thorInfo)._inventory |= BOOTS_MAGIC + WIND_MAGIC;
_G(thor)->_health = 150;
_G(thorInfo)._magic = _G(area) > 1 ? 150 : 0;
_G(thorInfo)._jewels = 0;
_G(thorInfo)._score = 0;
_G(thorInfo)._keys = 0;
_G(thorInfo)._lastItem = 0;
_G(thorInfo)._object = 0;
_G(thorInfo)._objectName = nullptr;
_G(thor)->_lastX[0] = _G(thor)->_x;
_G(thor)->_lastX[1] = _G(thor)->_x;
_G(thor)->_lastY[0] = _G(thor)->_y;
_G(thor)->_lastY[1] = _G(thor)->_y;
_G(thorInfo)._lastIcon = (6 * 20) + 8;
_G(thorInfo)._lastScreen = 23;
_G(thor)->_dir = 1;
switch (_G(area)) {
case 1:
_G(thor)->_x = 152;
_G(thor)->_y = 96;
break;
case 2:
_G(thor)->_x = 32;
_G(thor)->_y = 32;
break;
case 3:
_G(thor)->_x = 272;
_G(thor)->_y = 80;
break;
default:
break;
}
}
void initGame() {
if (_G(area) == 2)
_G(thorInfo)._armor = 1;
if (_G(area) == 3)
_G(thorInfo)._armor = 10;
loadStandardActors();
setupPlayer();
if (_G(demo)) {
g_vars->setArea(1);
_G(thor)->_health = 100;
_G(thorInfo)._magic = 100;
_G(thorInfo)._jewels = 463;
_G(thorInfo)._score = 12455;
_G(setup)._difficultyLevel = 0;
_G(thorInfo)._inventory = 1 + 2;
_G(currentLevel) = 54;
_G(thorInfo)._selectedItem = 2;
File f("DEMO");
_G(demoKeys).clear();
for (int i = 0; i < DEMO_LEN; ++i)
_G(demoKeys).push(f.readByte());
// Drop the first six bytes off. This comprises of
// the "part I" display in the original, and ScummVM
// doesn't do demo key processing until the game view
for (int i = 0; i < 6; ++i)
_G(demoKeys).pop();
}
_G(thor)->_moveCountdown = 6;
// Load level data
_G(newLevel) = _G(currentLevel);
_G(scrn).load(_G(currentLevel));
showLevel(_G(currentLevel));
g_vars->resetEndGameFlags();
_G(startup) = false;
}
} // namespace Got

34
engines/got/game/init.h Normal file
View File

@@ -0,0 +1,34 @@
/* 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 GOT_GAME_INIT_H
#define GOT_GAME_INIT_H
namespace Got {
/**
* Handles in-game initialization the first time
*/
extern void initGame();
} // namespace Got
#endif

80
engines/got/game/main.cpp Normal file
View File

@@ -0,0 +1,80 @@
/* 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 "common/memstream.h"
#include "got/game/back.h"
#include "got/vars.h"
#include "got/gfx/image.h" // loadNewThor
namespace Got {
void setupLoad() {
_G(thor)->_active = true;
_G(newLevel) = _G(thorInfo)._lastScreen;
_G(thor)->_x = (_G(thorInfo)._lastIcon % 20) * 16;
_G(thor)->_y = ((_G(thorInfo)._lastIcon / 20) * 16) - 1;
if (_G(thor)->_x < 1)
_G(thor)->_x = 1;
if (_G(thor)->_y < 0)
_G(thor)->_y = 0;
_G(thor)->_lastX[0] = _G(thor)->_x;
_G(thor)->_lastX[1] = _G(thor)->_x;
_G(thor)->_lastY[0] = _G(thor)->_y;
_G(thor)->_lastY[1] = _G(thor)->_y;
_G(thor)->_dir = _G(thorInfo)._lastDir;
_G(thor)->_lastDir = _G(thorInfo)._lastDir;
_G(thor)->_health = _G(thorInfo)._lastHealth;
_G(thorInfo)._magic = _G(thorInfo)._lastMagic;
_G(thorInfo)._jewels = _G(thorInfo)._lastJewels;
_G(thorInfo)._keys = _G(thorInfo)._lastKeys;
_G(thorInfo)._score = _G(thorInfo)._lastScore;
_G(thorInfo)._selectedItem = _G(thorInfo)._lastItem;
_G(thorInfo)._inventory = _G(thorInfo)._lastInventory;
_G(thorInfo)._object = _G(thorInfo)._lastObject;
_G(thorInfo)._objectName = _G(thorInfo)._lastObjectName;
_G(thor)->_numMoves = 1;
_G(thor)->_vulnerableCountdown = 60;
_G(thor)->_show = 60;
_G(appleFlag) = false;
_G(thunderSnakeCounter) = 0;
_G(tornadoUsed) = false;
_G(shieldOn) = false;
_G(actor[1])._active = false;
_G(actor[2])._active = false;
_G(thor)->_moveCountdown = 6;
_G(scrn).load(_G(newLevel));
_G(currentLevel) = _G(newLevel);
showLevel(_G(newLevel));
if (_G(area) == 2 && _G(currentLevel) == 105) { // Shovel Maze
_G(thorInfo)._armor = 2; // eyeballs mode
loadNewThor();
_G(eyeballs) = 1;
}
}
void pause(int delay) {
g_system->delayMillis(delay);
}
} // namespace Got

32
engines/got/game/main.h Normal file
View File

@@ -0,0 +1,32 @@
/* 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 GOT_GAME_MAIN_H
#define GOT_GAME_MAIN_H
namespace Got {
extern void setupLoad();
extern void pause(int delay);
} // namespace Got
#endif

380
engines/got/game/move.cpp Normal file
View File

@@ -0,0 +1,380 @@
/* 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 "got/game/move.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move_patterns.h"
#include "got/game/shot_movement.h"
#include "got/game/shot_pattern.h"
#include "got/game/status.h"
#include "got/vars.h"
namespace Got {
void nextFrame(Actor *actor) {
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 3)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
}
bool pointWithin(int x, int y, int x1, int y1, int x2, int y2) {
return ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2));
}
bool overlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
if ((x1 >= x3) && (x1 <= x4) && (y1 >= y3) && (y1 <= y4))
return true;
if ((x2 >= x3) && (x2 <= x4) && (y2 >= y3) && (y2 <= y4))
return true;
if ((x1 >= x3) && (x1 <= x4) && (y2 >= y3) && (y2 <= y4))
return true;
if ((x2 >= x3) && (x2 <= x4) && (y1 >= y3) && (y1 <= y4))
return true;
if ((x3 >= x1) && (x3 <= x2) && (y3 >= y1) && (y3 <= y2))
return true;
if ((x4 >= x1) && (x4 <= x2) && (y4 >= y1) && (y4 <= y2))
return true;
if ((x3 >= x1) && (x3 <= x2) && (y4 >= y1) && (y4 <= y2))
return true;
if ((x4 >= x1) && (x4 <= x2) && (y3 >= y1) && (y3 <= y2))
return true;
return false;
}
int reverseDirection(Actor *actor) {
if (actor->_dir == 1)
return 0;
if (actor->_dir == 2)
return 3;
if (actor->_dir == 3)
return 2;
return 1;
}
void thorShoots() {
if (!_G(hammer)->_active && (!_G(hammer)->_dead) && (!_G(thor)->_shotCountdown)) {
playSound(SWISH, false);
_G(thor)->_shotCountdown = 20;
_G(hammer)->_active = true;
_G(hammer)->_dir = _G(thor)->_dir;
_G(hammer)->_lastDir = _G(thor)->_dir;
_G(hammer)->_x = _G(thor)->_x;
_G(hammer)->_y = _G(thor)->_y + 2;
_G(hammer)->_moveType = 2;
_G(hammer)->_nextFrame = 0;
_G(hammer)->_lastX[0] = _G(hammer)->_x;
_G(hammer)->_lastX[1] = _G(hammer)->_x;
_G(hammer)->_lastY[0] = _G(hammer)->_y;
_G(hammer)->_lastY[1] = _G(hammer)->_y;
}
}
int killGoodGuy() {
if (!_G(killGoodGuyInform) && !_G(thunderSnakeCounter)) {
odinSpeaks(2010, 0);
_G(killGoodGuyInform) = true;
}
addScore(-1000);
return 0;
}
void actorDamaged(Actor *actor, int damage) {
if (!_G(setup)._difficultyLevel)
damage *= 2;
else if (_G(setup)._difficultyLevel == 2)
damage /= 2;
if (!actor->_vulnerableCountdown && actor->_type != 3 && (actor->_solid & 0x7f) != 2) {
actor->_vulnerableCountdown = STAMINA;
if (damage >= actor->_health) {
if (actor->_type != 4) {
addScore(actor->_initHealth * 10);
} else {
killGoodGuy();
}
actorDestroyed(actor);
} else {
actor->_show = 10;
actor->_health -= damage;
actor->_moveCountdown += 8;
}
} else if (!actor->_vulnerableCountdown) {
actor->_vulnerableCountdown = STAMINA;
if (actor->_funcNum == 4) {
switchIcons();
}
if (actor->_funcNum == 7) {
rotateArrows();
}
}
}
void thorDamaged(Actor *actor) {
actor->_hitThor = true;
// If we're invincible, ignore any damage
if (_G(cheats)._freezeHealth)
return;
if (GAME3 && actor->_funcNum == 11) {
if (actor->_talkCounter) {
actor->_talkCounter--;
return;
}
const int currType = actor->_type;
actor->_type = 4;
actorSpeaks(actor, 0, 0);
actor->_type = currType;
actor->_talkCounter = 30;
return;
}
int damage = actor->_hitStrength;
if (damage != 255) {
if (!_G(setup)._difficultyLevel)
damage /= 2;
else if (_G(setup)._difficultyLevel == 2)
damage *= 2;
}
if ((!_G(thor)->_vulnerableCountdown && !_G(shieldOn)) || damage == 255) {
if (damage >= _G(thor)->_health) {
_G(thor)->_vulnerableCountdown = 40;
_G(thor)->_show = 0;
_G(thor)->_health = 0;
_G(exitFlag) = 2;
g_events->send(GameMessage("THOR_DIES"));
} else if (damage) {
_G(thor)->_vulnerableCountdown = 40;
_G(sound).playSound(OW, false);
_G(thor)->_show = 10;
_G(thor)->_health -= damage;
}
}
}
void actorDestroyed(Actor *actor) {
if (actor->_actorNum > 2) {
const int curPage = _G(pge);
const int x = actor->_lastX[curPage ^ 1];
const int y = actor->_lastY[curPage ^ 1];
const int x1 = actor->_lastX[curPage];
const int y1 = actor->_lastY[curPage];
const int r = actor->_dropRating;
const int n = actor->_actorNum;
const int t = actor->_type;
if (actor->_funcNum == 255)
actor->copyFixedAndPics(_G(explosion));
else
actor->copyFixedAndPics(_G(sparkle));
actor->_type = t;
actor->_actorNum = n;
actor->_dropRating = r;
actor->_x = x;
actor->_y = y;
actor->_lastX[curPage] = x1;
actor->_lastX[curPage ^ 1] = x;
actor->_lastY[curPage] = y1;
actor->_lastY[curPage ^ 1] = y;
actor->_moveCountdown = actor->_speed;
actor->_active = true;
actor->_currNumShots = 3; // used to reverse explosion
actor->_vulnerableCountdown = 255;
} else {
actor->_dead = 2;
actor->_active = false;
}
}
int _actor_shoots(Actor *actor, int dir) {
const int t = actor->_shotType - 1;
for (int i = MAX_ENEMIES + 3; i < MAX_ACTORS; i++) {
if ((!_G(actor[i])._active) && (!_G(actor[i])._dead)) {
Actor *act = &_G(actor[i]);
*act = _G(shot[t]);
int cx, cy;
if (actor->_sizeY < act->_sizeY)
cy = actor->_y - ((act->_sizeY - actor->_sizeY) / 2);
else
cy = actor->_y + ((actor->_sizeY - act->_sizeY) / 2);
if (actor->_sizeX < act->_sizeX)
cx = actor->_x - ((act->_sizeX - actor->_sizeX) / 2);
else
cx = actor->_x + ((actor->_sizeX - act->_sizeX) / 2);
if (cy > 174)
cy = 174;
if (cx > 304)
cx = 304;
act->_x = cx;
act->_y = cy;
act->_lastDir = dir;
act->_nextFrame = 0;
act->_dir = dir;
if (act->_directions == 1)
act->_dir = 0;
else if (act->_directions == 4 && act->_framesPerDirection == 1) {
act->_nextFrame = dir;
act->_dir = 0;
}
act->_frameCount = act->_frameSpeed;
act->_moveCountdown = act->_speed;
act->_lastX[0] = cx;
act->_lastX[1] = cx;
act->_lastX[0] = actor->_x;
act->_lastX[1] = actor->_x;
act->_lastY[0] = cy;
act->_lastY[1] = cy;
act->_active = true;
act->_creator = actor->_actorNum;
act->_moveCount = act->_numMoves;
act->_dead = 0;
actor->_shotActor = i;
actor->_currNumShots++;
actor->_shotCountdown = 20;
_G(shotOk) = false;
return 1;
}
}
return 0;
}
void actorAlwaysShoots(Actor *actor, int dir) {
_actor_shoots(actor, dir);
}
int actorShoots(Actor *actor, int dir) {
const int cx = (actor->_x + (actor->_sizeX / 2)) >> 4;
const int cy = ((actor->_y + actor->_sizeY) - 2) >> 4;
const int tx = _G(thor)->_centerX;
const int ty = _G(thor)->_centerY;
int icn = 140;
if (_G(shot[actor->_shotType - 1])._flying)
icn = 80;
switch (dir) {
case 0:
for (int i = ty + 1; i <= cy; i++) {
if (_G(scrn)._iconGrid[i][cx] < icn)
return 0;
}
break;
case 1:
for (int i = cy; i <= ty; i++) {
if (_G(scrn)._iconGrid[i][cx] < icn)
return 0;
}
break;
case 2:
for (int i = tx; i < cx; i++) {
if (_G(scrn)._iconGrid[cy][i] < icn)
return 0;
}
break;
case 3:
for (int i = cx; i < tx; i++) {
if (_G(scrn)._iconGrid[cy][i] < icn)
return 0;
}
break;
default:
break;
}
return _actor_shoots(actor, dir);
}
void moveActor(Actor *actor) {
if (actor->_vulnerableCountdown != 0)
actor->_vulnerableCountdown--;
if (actor->_shotCountdown != 0)
actor->_shotCountdown--;
if (actor->_show != 0)
actor->_show--;
if (!actor->_shotCountdown && _G(shotOk) && actor->_numShotsAllowed && actor->_currNumShots < actor->_numShotsAllowed) {
shotPatternFunc[actor->_shotPattern](actor);
}
const int scount = actor->_moveCountdown - 1;
if (scount <= 0) {
if (!actor->_moveCounter)
actor->_moveCountdown = actor->_speed;
else
actor->_moveCountdown = (actor->_speed << 1);
int i;
if (actor->_type == 3)
i = shotMovementFunc[actor->_moveType](actor);
else
i = _movementFunc[actor->_moveType](actor);
if (actor->_directions == 2)
i &= 1;
if (i != actor->_dir)
actor->_dir = i;
if (actor->_moveType == 0 && _G(currentLevel) != _G(newLevel) && _G(shieldOn)) {
_G(actor[2])._x = actor->_x - 2;
if (_G(actor[2])._x < 0)
_G(actor[2])._x = 0;
_G(actor[2])._y = actor->_y;
_G(actor[2])._lastX[0] = _G(actor[2])._x;
_G(actor[2])._lastX[1] = _G(actor[2])._x;
_G(actor[2])._lastY[0] = _G(actor[2])._y;
_G(actor[2])._lastY[1] = _G(actor[2])._y;
}
} else
actor->_moveCountdown = scount;
actor->_x &= 0xfffe;
}
} // namespace Got

43
engines/got/game/move.h Normal file
View File

@@ -0,0 +1,43 @@
/* 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 GOT_GAME_MOVE_H
#define GOT_GAME_MOVE_H
#include "got/data/defines.h"
namespace Got {
extern void nextFrame(Actor *actor);
extern bool pointWithin(int x, int y, int x1, int y1, int x2, int y2);
extern bool overlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
extern int reverseDirection(Actor *actor);
extern void thorShoots();
extern void thorDamaged(Actor *actor);
extern void actorDestroyed(Actor *actor);
extern int actorShoots(Actor *actor, int dir);
extern void actorAlwaysShoots(Actor *actor, int dir);
extern void actorDamaged(Actor *actor, int damage);
extern void moveActor(Actor *actor);
} // namespace Got
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
/* 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 GOT_GAME_MOVE_PATTERNS_H
#define GOT_GAME_MOVE_PATTERNS_H
#include "got/data/defines.h"
namespace Got {
extern int (*const _movementFunc[]) (Actor *actor);
int checkMove2(int x, int y, Actor *actor);
int checkMove3(int x, int y, Actor *actor);
int checkMove4(int x, int y, Actor *actor);
void setThorVars();
} // namespace Got
#endif

437
engines/got/game/object.cpp Normal file
View File

@@ -0,0 +1,437 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property _G(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 _G(of) the GNU General Public License as published by
* the Free Software Foundation, either version 3 _G(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 _G(of)
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy _G(of) the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "got/game/object.h"
#include "got/data/flags.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/move.h"
#include "got/game/status.h"
#include "got/gfx/image.h"
#include "got/vars.h"
namespace Got {
void notEnoughMagic();
void cannotCarryMore();
void showObjects() {
Common::fill(_G(objectMap), _G(objectMap) + TILES_COUNT, 0);
Common::fill(_G(objectIndex), _G(objectIndex) + TILES_COUNT, 0);
for (int i = 0; i < OBJECTS_COUNT; i++) {
if (_G(scrn)._staticObject[i]) {
const int p = _G(scrn)._staticX[i] + (_G(scrn)._staticY[i] * TILES_X);
_G(objectIndex[p]) = i;
_G(objectMap[p]) = _G(scrn)._staticObject[i];
}
}
}
void pickUpObject(int p) {
switch (_G(objectMap[p])) {
case 1: // Red jewel
if (_G(thorInfo)._jewels >= 999) {
cannotCarryMore();
return;
}
addJewels(10);
break;
case 2: // Blue jewel
if (_G(thorInfo)._jewels >= 999) {
cannotCarryMore();
return;
}
addJewels(1);
break;
case 3: // Red potion
if (_G(thorInfo)._magic >= 150) {
cannotCarryMore();
return;
}
addMagic(10);
break;
case 4: // Blue potion
if (_G(thorInfo)._magic >= 150) {
cannotCarryMore();
return;
}
addMagic(3);
break;
case 5: // Good apple
if (_G(thor)->_health >= 150) {
cannotCarryMore();
return;
}
playSound(GULP, false);
addHealth(5);
break;
case 6: // Bad apple
playSound(OW, false);
addHealth(-10);
break;
case 7: // Key (reset on exit)
addKeys(1);
break;
case 8: // Treasure
if (_G(thorInfo)._jewels >= 999) {
cannotCarryMore();
return;
}
addJewels(50);
break;
case 9: // Trophy
addScore(100);
break;
case 10: // Crown
addScore(1000);
break;
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
if (_G(objectMap[p]) == 13 && HERMIT_HAS_DOLL)
return;
_G(thor)->_numMoves = 1;
_G(hammer)->_numMoves = 2;
_G(actor[2])._active = false;
_G(shieldOn) = false;
_G(tornadoUsed) = false;
_G(thorInfo)._inventory |= 64;
_G(thorInfo)._selectedItem = 7;
_G(thorInfo)._object = _G(objectMap[p]) - 11;
_G(thorInfo)._objectName = OBJECT_NAMES[_G(thorInfo)._object - 1];
odinSpeaks((_G(objectMap[p]) - 12) + 501, _G(objectMap[p]) - 1);
break;
case 27:
case 28:
case 29:
case 30:
case 31:
case 32: {
_G(thunderSnakeCounter) = 0;
_G(shieldOn) = false;
_G(tornadoUsed) = false;
_G(hammer)->_numMoves = 2;
_G(thor)->_numMoves = 1;
_G(actor[2])._active = false;
const int s = 1 << (_G(objectMap[p]) - 27);
_G(thorInfo)._inventory |= s;
odinSpeaks((_G(objectMap[p]) - 27) + 516, _G(objectMap[p]) - 1);
_G(thorInfo)._selectedItem = _G(objectMap[p]) - 26;
addMagic(150);
fillScore(5);
}
break;
default:
break;
}
playSound(YAH, false);
_G(objectMap[p]) = 0;
// Reset so it doesn't reappear on reentry to screen
if (_G(objectIndex[p]) < 30)
_G(scrn)._staticObject[_G(objectIndex[p])] = 0;
_G(objectIndex[p]) = 0;
}
void dropRandomObject(Actor *actor) {
int objId;
const int rnd1 = g_events->getRandomNumber(99);
const int rnd2 = g_events->getRandomNumber(99);
if (rnd1 < 25)
objId = 5; // Apple
else if (rnd1 & 1) {
// Jewels
if (rnd2 < 10)
objId = 1; // Red
else
objId = 2; // Blue
} else {
// Potion
if (rnd2 < 10)
objId = 3; // Red
else
objId = 4; // Blue
}
dropObject(actor, objId);
}
bool dropObject(Actor *actor, const int objId) {
const int p = (actor->_x + (actor->_sizeX / 2)) / 16 + (((actor->_y + (actor->_sizeY / 2)) / 16) * 20);
if (!_G(objectMap[p]) && _G(scrn)._iconGrid[p / 20][p % 20] >= 140) { //nothing there and solid
_G(objectMap[p]) = objId;
_G(objectIndex[p]) = 27 + actor->_actorNum; //actor is 3-15
return true;
}
return false;
}
bool useApple(int flag) {
if (_G(thor)->_health == 150)
return false;
if (flag && _G(thorInfo)._magic > 0) {
if (!_G(appleFlag)) {
_G(magicCounter) = 0;
addMagic(-2);
addHealth(1);
playSound(ANGEL, false);
} else if (_G(magicCounter) > 8) {
_G(magicCounter) = 0;
addMagic(-2);
addHealth(1);
if (!soundPlaying())
playSound(ANGEL, false);
}
_G(appleFlag) = true;
return true;
}
_G(appleFlag) = false;
if (flag)
notEnoughMagic();
return false;
}
bool useThunder(int flag) {
if (flag && _G(thorInfo)._magic > 29) {
if (!_G(thunderSnakeCounter)) {
addMagic(-30);
playSound(THUNDER, false);
_G(thunderSnakeCounter) = 60;
}
return true;
}
if (flag && !_G(thunderSnakeCounter))
notEnoughMagic();
if (_G(thunderSnakeCounter))
return true;
return false;
}
bool useBoots(int flag) {
if (flag) {
if (_G(thorInfo)._magic > 0) {
if (_G(thor)->_numMoves == 1 || _G(magicCounter) > 8) {
_G(magicCounter) = 0;
addMagic(-1);
}
_G(thor)->_numMoves = 2;
_G(hammer)->_numMoves = 3;
return true;
}
notEnoughMagic();
_G(thor)->_numMoves = 1;
_G(hammer)->_numMoves = 2;
} else {
_G(thor)->_numMoves = 1;
_G(hammer)->_numMoves = 2;
}
return false;
}
bool useShield(int flag) {
if (flag) {
if (_G(thorInfo)._magic) {
if (!_G(shieldOn)) {
_G(magicCounter) = 0;
addMagic(-1);
setupMagicItem(1);
_G(actor[2]) = _G(magicItem[1]);
setupActor(&_G(actor[2]), 2, 0, _G(thor)->_x, _G(thor)->_y);
_G(actor[2])._moveCountdown = 1;
_G(actor[2])._speed = 1;
_G(shieldOn) = true;
} else if (_G(magicCounter) > 8) {
_G(magicCounter) = 0;
addMagic(-1);
}
return true;
}
notEnoughMagic();
}
if (_G(shieldOn)) {
_G(actor[2])._dead = 2;
_G(actor[2])._active = false;
_G(shieldOn) = false;
}
return false;
}
bool useLightning(int flag) {
if (flag) {
if (_G(thorInfo)._magic > 14) {
addMagic(-15);
g_events->send("Game", GameMessage("THROW_LIGHTNING"));
} else {
notEnoughMagic();
return false;
}
}
return true;
}
bool useTornado(int flag) {
if (flag) {
if (_G(thorInfo)._magic > 10) {
if (!_G(tornadoUsed) && !_G(actor[2])._dead && _G(magicCounter) > 20) {
_G(magicCounter) = 0;
addMagic(-10);
setupMagicItem(0);
_G(actor[2]) = _G(magicItem[0]);
setupActor(&_G(actor[2]), 2, 0, _G(thor)->_x, _G(thor)->_y);
_G(actor[2])._lastDir = _G(thor)->_dir;
_G(actor[2])._moveType = 16;
_G(tornadoUsed) = true;
playSound(WIND, false);
}
} else if (!_G(tornadoUsed)) {
notEnoughMagic();
return false;
}
if (_G(magicCounter) > 8) {
if (_G(tornadoUsed)) {
_G(magicCounter) = 0;
addMagic(-1);
}
}
if (_G(thorInfo)._magic < 1) {
actorDestroyed(&_G(actor[2]));
_G(tornadoUsed) = false;
notEnoughMagic();
return false;
}
return true;
}
return false;
}
bool useObject(int flag) {
if (!flag || !(_G(thorInfo)._inventory & 64))
return false;
odinSpeaks((_G(thorInfo)._object - 1) + 5501, _G(thorInfo)._object - 1);
return true;
}
void useItem() {
bool ret = false;
const int kf = _G(keyFlag[key_magic]);
if (!kf && _G(tornadoUsed)) {
actorDestroyed(&_G(actor[2]));
_G(tornadoUsed) = false;
}
const bool mf = _G(magicMissingInform);
switch (_G(thorInfo)._selectedItem) {
case 1:
ret = useApple(kf);
break;
case 2:
ret = useLightning(kf);
break;
case 3:
ret = useBoots(kf);
break;
case 4:
ret = useTornado(kf);
break;
case 5:
ret = useShield(kf);
break;
case 6:
ret = useThunder(kf);
break;
case 7:
ret = useObject(kf);
break;
default:
break;
}
if (kf) {
if (!ret && !_G(useItemFlag)) {
if (mf)
playSound(BRAAPP, false);
_G(useItemFlag) = true;
}
} else {
_G(useItemFlag) = false;
}
}
void notEnoughMagic() {
if (_G(magicMissingInform))
return;
odinSpeaks(2006, 0);
_G(magicMissingInform) = true;
}
void cannotCarryMore() {
if (_G(cantCarryInform))
return;
odinSpeaks(2007, 0);
_G(cantCarryInform) = true;
}
void deleteObject() {
_G(thorInfo)._inventory &= 0xbf;
_G(thorInfo)._selectedItem = 1;
}
} // namespace Got

38
engines/got/game/object.h Normal file
View File

@@ -0,0 +1,38 @@
/* 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 GOT_GAME_OBJECT_H
#define GOT_GAME_OBJECT_H
#include "got/data/defines.h"
namespace Got {
extern void showObjects();
extern void pickUpObject(int p);
extern void dropRandomObject(Actor *actor);
extern bool dropObject(Actor *actor, int objId);
extern void deleteObject();
extern void useItem();
} // namespace Got
#endif

1265
engines/got/game/script.cpp Normal file

File diff suppressed because it is too large Load Diff

127
engines/got/game/script.h Normal file
View File

@@ -0,0 +1,127 @@
/* 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 GOT_GAME_SCRIPT_H
#define GOT_GAME_SCRIPT_H
#include "got/data/defines.h"
#include "got/gfx/gfx_pics.h"
namespace Got {
typedef void (*ScriptEndFn)();
enum ScriptPause {
SCRIPT_READY, SCRIPT_PAUSED, SCRIPT_RESUMING
};
class Scripts {
public:
Scripts();
~Scripts();
void executeScript(long index, const Gfx::Pics &speakerIcon, ScriptEndFn endFn = nullptr);
void pause();
void resume();
void setAskResponse(int option);
void runIfResuming();
private:
ScriptEndFn _endFn = nullptr;
long _numVar[26] = {}; // numeric variables
char _strVar[26][81] = {}; // string vars
char _lineLabel[32][9] = {}; // line label look up table
char *_linePtr[32] = {}; // line label pointers
char *_newPtr = nullptr;
int _numLabels = 0; // number of labels
char *_gosubStack[32] = {}; // stack for GOSUB return addresses
int _gosubPtr = 0; // GOSUB stack pointer
char *_forStack[11] = {}; // FOR stack
long _forVal[11] = {}; // current FOR value
int8 _forVar[11] = {}; // ending FOR value (target var)
int8 _forPtr = 0; // FOR stack pointer
char *_buffPtr = nullptr; // pointer to current command
char *_buffEnd = nullptr; // pointer to end of buffer
char *_buffer = nullptr; // buffer space (alloc'ed)
long _scrIndex = 0;
Gfx::Pics _scrPic;
long _lValue = 0;
long _lTemp = 0;
char _tempS[255] = {};
ScriptPause _paused = SCRIPT_READY;
int _askVar = -1;
private:
int readScriptFile();
void scriptError(int err_num);
int getCommand();
int skipColon();
int calcValue();
int getNextValue();
int calcString(int mode);
void getStr();
int getInternalVariable();
int execCommand(int num);
int getLine(char *src, char *dst);
void scriptEntry() {}
void scriptExit();
int cmd_goto();
int cmd_if();
int cmd_run();
int cmd_addJewels();
int cmd_addHealth();
int cmd_addMagic();
int cmd_addKeys();
int cmd_addScore();
int cmd_say(int mode, int type);
int cmd_ask();
int cmd_sound();
int cmd_setTile();
int cmd_itemGive();
int cmd_itemTake();
int cmd_setFlag();
int cmd_ltoa();
int cmd_pause();
int cmd_visible();
int cmd_random();
int cmd_exec();
void scr_func1();
void scr_func2();
void scr_func3();
void scr_func4();
void scr_func5();
typedef void (Scripts:: *ScrFunction)();
static ScrFunction scr_func[5];
void runScript(bool firstTime = true);
void scriptLoop();
};
extern void executeScript(long index, const Gfx::Pics &speakerIcon,
ScriptEndFn endFn = nullptr);
} // namespace Got
#endif

View File

@@ -0,0 +1,734 @@
/* 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 "got/game/shot_movement.h"
#include "got/events.h"
#include "got/game/move.h"
#include "got/game/move_patterns.h"
#include "got/game/object.h"
#include "got/vars.h"
namespace Got {
int shotMovementNone(Actor *actor);
int shotMovementOne(Actor *actor);
int shotMovementTwo(Actor *actor);
int shotMovementThree(Actor *actor);
int shotMovementFour(Actor *actor);
int shotMovementFive(Actor *actor);
int shotMovementSix(Actor *actor);
int shotMovementSeven(Actor *actor);
int shotMovementEight(Actor *actor);
int shotMovementNine(Actor *actor);
int shotMovementTen(Actor *actor);
int shotMovementEleven(Actor *actor);
int shotMovementTwelve(Actor *actor);
int shotMovementThirteen(Actor *actor);
int (*const shotMovementFunc[])(Actor *actor) = {
shotMovementNone,
shotMovementOne,
shotMovementTwo,
shotMovementThree,
shotMovementFour,
shotMovementFive,
shotMovementSix,
shotMovementSeven,
shotMovementEight,
shotMovementNine,
shotMovementTen,
shotMovementEleven,
shotMovementTwelve,
shotMovementThirteen
};
void next_shot_frame(Actor *actor) {
if (actor->_directions == 4 && actor->_framesPerDirection == 1) {
actor->_nextFrame = actor->_lastDir;
actor->_dir = 0;
} else {
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 3)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
}
}
// Boss - snake
int shotMovementNone(Actor *actor) {
actor->_temp3--;
if (!actor->_temp3) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
}
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
int shotMovementOne(Actor *actor) {
int x1 = 0, y1 = 0;
const int d = actor->_lastDir;
switch (d) {
case 0:
x1 = actor->_x;
y1 = actor->_y - 2;
break;
case 1:
x1 = actor->_x;
y1 = actor->_y + 2;
break;
case 2:
x1 = actor->_x - 2;
y1 = actor->_y;
break;
case 3:
x1 = actor->_x + 2;
y1 = actor->_y;
break;
default:
break;
}
if (!checkMove3(x1, y1, actor)) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else {
next_shot_frame(actor);
actor->_lastDir = d;
}
if (actor->_directions == 1)
return 0;
if (actor->_directions == 4 && actor->_framesPerDirection == 1)
return 0;
return d;
}
int shotMovementTwo(Actor *actor) {
int x1 = 0, y1 = 0;
const int d = actor->_lastDir;
switch (d) {
case 0:
x1 = actor->_x;
y1 = actor->_y - 2;
break;
case 1:
x1 = actor->_x;
y1 = actor->_y + 2;
break;
case 2:
x1 = actor->_x - 2;
y1 = actor->_y;
break;
case 3:
x1 = actor->_x + 2;
y1 = actor->_y;
break;
default:
break;
}
if (!checkMove4(x1, y1, actor)) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else {
next_shot_frame(actor);
actor->_lastDir = d;
}
if (actor->_directions == 1)
return 0;
if (actor->_directions == 4 && actor->_framesPerDirection == 1)
return 0;
return d;
}
// Serpent fire
int shotMovementThree(Actor *actor) {
const int d = actor->_lastDir;
actor->_x -= 2;
actor->_temp3--;
actor->_temp4--;
if (overlap(_G(thorX1) - 1, _G(thorY1) - 1, _G(thorX2) + 1, _G(thorY2) + 1,
actor->_x, actor->_y, actor->_x + 15, actor->_y + 15)) {
actor->_moveType = 0;
actor->_speed = 6;
thorDamaged(actor);
actor->_x += 2;
}
if (!actor->_temp4) {
actor->_temp4 = actor->_temp5;
actor->_speed++;
if (actor->_speed > 6)
actor->_moveType = 0;
}
if (!actor->_temp3) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else {
next_shot_frame(actor);
actor->_lastDir = d;
}
if (actor->_directions == 1)
return 0;
return d;
}
// Wraith balls
int shotMovementFour(Actor *actor) {
if (actor->_temp1) {
actor->_temp1--;
if (!actor->_temp1) {
actorDestroyed(actor);
_G(appleDropCounter++);
if (_G(appleDropCounter) == 4) {
if (dropObject(actor, 5))
_G(appleDropCounter) = 0;
else
_G(appleDropCounter) = 3;
} else
dropObject(actor, 3);
return 0;
}
}
if (overlap(_G(thor)->_x - 1, _G(thor)->_y - 1, _G(thorX2) + 1, _G(thorY2) + 1,
actor->_x, actor->_y, actor->_x + 15, actor->_y + 15)) {
thorDamaged(actor);
actorDestroyed(actor);
return 0;
}
int x1 = actor->_x;
int y1 = actor->_y;
int yd = 0;
int xd = 0;
int d = actor->_lastDir;
if ((x1 > (_G(thorX1)) + 1))
xd = -2;
else if ((x1 < (_G(thorX1)) - 1))
xd = 2;
if (actor->_actorNum == 1) {
if (y1 < (_G(thorY1) - 6))
yd = 2;
else if (y1 > (_G(thorY1) - 6))
yd = -2;
} else {
if (y1 < (_G(thorRealY1) - 1))
yd = 2;
else if (y1 > (_G(thorRealY1) + 1))
yd = -2;
}
if (xd && yd) {
if (xd == -2 && ABS(yd) == 2)
d = 2;
else if (xd == 2 && ABS(yd) == 2)
d = 3;
x1 += xd;
y1 += yd;
if (checkMove3(x1, y1, actor)) {
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
} else if (xd == 0 && yd == 2)
d = 1;
else if (xd == 0 && yd == -2)
d = 0;
else if (xd == 2 && yd == 0)
d = 3;
else if (xd == -2 && yd == 0)
d = 2;
x1 = actor->_x;
y1 = actor->_y;
actor->_toggle ^= 1;
if (actor->_toggle) {
if (xd) {
x1 += xd;
if (checkMove3(x1, y1, actor)) {
if (xd > 0)
d = 3;
else
d = 2;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
x1 = actor->_x;
}
if (yd) {
y1 += yd;
if (checkMove3(x1, y1, actor)) {
if (yd > 0)
d = 1;
else
d = 0;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
}
} else {
if (yd) {
y1 += yd;
if (checkMove3(x1, y1, actor)) {
if (yd > 0)
d = 1;
else
d = 0;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
y1 = actor->_y;
}
if (xd) {
x1 += xd;
if (checkMove3(x1, y1, actor)) {
if (xd > 0)
d = 3;
else
d = 2;
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
}
}
checkMove3(actor->_x, actor->_y, actor);
nextFrame(actor);
actor->_lastDir = d;
if (actor->_directions == 1)
return 0;
return d;
}
// No move, frame cycle
int shotMovementFive(Actor *actor) {
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Wraith spots
int shotMovementSix(Actor *actor) {
actor->_temp1--;
if (!actor->_temp1) {
actorDestroyed(actor);
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
} else
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
#define YV actor->_i1
#define YC actor->_i2
#define BC actor->_i3
#define YD actor->_i4
#define XD actor->_i5
#define XC actor->_i6
#define IV 100
#define IC 50
// Skull drop
int shotMovementSeven(Actor *actor) {
if (actor->_temp3) {
actor->_temp3--;
goto done;
}
if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY,
_G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15))
thorDamaged(actor);
actor->_temp2++;
if (actor->_temp2 > 2) {
if (actor->_temp4)
actor->_temp4--;
actor->_temp2 = 0;
}
actor->_temp3 = actor->_temp4;
actor->_y += 2;
if (actor->_y > 160 - 36) {
actor->_x += (4 - g_events->getRandomNumber(8));
actor->_moveType = 8;
YV = IV;
YC = 0;
BC = IC;
YD = 0;
XC = 3;
if (actor->_x < 150)
XD = 1;
else
XD = 0;
}
done:
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Skull bounce
int shotMovementEight(Actor *actor) {
int x = actor->_x;
int y = actor->_y;
XC--;
if (!XC) {
XC = 3;
if (XD)
x += 2;
else
x -= 2;
}
YC += YV;
if (YC > (IV - 1)) {
if (!YD) {
YV -= 8;
YC -= IV;
y -= 2;
} else {
YV += 8;
YC -= IV;
y += 2;
}
}
if (YV < 0) {
YV = 0;
BC = 1;
}
if (YV > IV) {
YV = IV;
BC = 1;
}
BC--;
if (!BC) {
BC = IC;
if (YD)
YV = IV;
YD ^= 1;
}
if (y > 164)
y = 164;
// 8 311
if (x < 1 || x > (319 - actor->_sizeX)) {
if (!actor->_dead)
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
}
if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY,
_G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15))
thorDamaged(actor);
actor->_x = x;
actor->_y = y;
//done:
next_shot_frame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Skull explode
int shotMovementNine(Actor *actor) {
actor->_nextFrame++;
if (actor->_nextFrame == 3) {
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
return 0;
}
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Skull - stalagtites
int shotMovementTen(Actor *actor) {
bool check = false;
actor->_y += 2;
if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY,
_G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15)) {
thorDamaged(actor);
check = true;
}
if (actor->_y > 160 || check) {
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
}
return 0;
}
#undef YD
#undef XD
#define YA actor->_i1
#define XA actor->_i2
#define YD actor->_i3
#define XD actor->_i4
#define DIR actor->_i5
#define CNT actor->_i6
void calc_angle(const int x1, const int y1, const int x2, const int y2, Actor *actor) {
if (x1 < x2) {
XA = -2;
XD = x2 - x1;
} else if (x1 > x2) {
XA = 2;
XD = x1 - x2;
} else {
XA = 0;
XD = 0;
}
if (y1 < y2) {
YA = -2;
YD = y2 - y1;
} else if (y1 > y2) {
YA = 2;
YD = y1 - y2;
} else {
YA = 0;
YD = 0;
}
if (YD >= XD)
DIR = 1;
else
DIR = 0;
CNT = 0;
}
// Angle throw
int shotMovementEleven(Actor *actor) {
int x1 = actor->_x;
int y1 = actor->_y;
if (!actor->_temp1) {
calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor);
actor->_temp1 = 1;
}
if (DIR) {
y1 += YA;
CNT += XD;
if (CNT >= YD) {
x1 += XA;
CNT -= YD;
}
} else {
x1 += XA;
CNT += YD;
if (CNT >= XD) {
y1 += YA;
CNT -= XD;
}
}
if (!checkMove3(x1, y1, actor)) {
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
} else
nextFrame(actor);
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Angle throw Loki
int shotMovementTwelve(Actor *actor) {
int x1 = actor->_x;
int y1 = actor->_y;
if (!actor->_temp5) {
calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor);
actor->_temp5 = 1;
}
if (DIR) {
y1 += YA;
CNT += XD;
if (CNT >= YD) {
x1 += XA;
CNT -= YD;
}
} else {
x1 += XA;
CNT += YD;
if (CNT >= XD) {
y1 += YA;
CNT -= XD;
}
}
if (x1 < 16 || x1 > 287 || y1 < 16 || y1 > 159) {
calc_angle(g_events->getRandomNumber(319),
g_events->getRandomNumber(191), x1, y1, actor);
actor->_moveType = 13;
actor->_temp4 = 240;
actor->_nextFrame = 2;
} else {
if (overlap(x1 + 2, y1 + 2, x1 + 14, y1 + 14, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2))) {
thorDamaged(actor);
}
actor->_x = x1;
actor->_y = y1;
}
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 1)
actor->_nextFrame = 0;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
// Angle throw Loki-2
int shotMovementThirteen(Actor *actor) {
int x1 = actor->_x;
int y1 = actor->_y;
if (!actor->_temp5) {
calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor);
actor->_temp5 = 1;
}
if (DIR) {
y1 += YA;
CNT += XD;
if (CNT >= YD) {
x1 += XA;
CNT -= YD;
}
} else {
x1 += XA;
CNT += YD;
if (CNT >= XD) {
y1 += YA;
CNT -= XD;
}
}
if (actor->_temp4)
actor->_temp4--;
if (!actor->_temp4) {
if (_G(actor[actor->_creator])._currNumShots)
_G(actor[actor->_creator])._currNumShots--;
actorDestroyed(actor);
_G(appleDropCounter++);
if (_G(appleDropCounter) > 4) {
if (dropObject(actor, 5))
_G(appleDropCounter) = 0;
else
_G(appleDropCounter) = 4;
} else
dropObject(actor, 4);
return 0;
}
if (x1 < 16 || x1 > 287 || y1 < 16 || y1 > 159) {
if (x1 < 16 || x1 > 287)
XA = 0 - XA;
else
YA = 0 - YA;
} else {
if (overlap(x1 + 4, y1 + 4, x1 + 12, y1 + 12, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2))) {
thorDamaged(actor);
}
actor->_x = x1;
actor->_y = y1;
}
const int fcount = actor->_frameCount - 1;
if (fcount <= 0) {
actor->_nextFrame++;
if (actor->_nextFrame > 3)
actor->_nextFrame = 2;
actor->_frameCount = actor->_frameSpeed;
} else
actor->_frameCount = fcount;
if (actor->_directions == 1)
return 0;
return actor->_lastDir;
}
} // namespace Got

View File

@@ -0,0 +1,33 @@
/* 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 GOT_GAME_SHOT_MOVEMENT_H
#define GOT_GAME_SHOT_MOVEMENT_H
#include "got/data/defines.h"
namespace Got {
extern int (*const shotMovementFunc[]) (Actor *actor);
} // namespace Got
#endif

View File

@@ -0,0 +1,222 @@
/* 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 "got/game/shot_pattern.h"
#include "got/game/move.h"
#include "got/vars.h"
namespace Got {
int shotPatternNone(Actor *actor);
int shotPatternOne(Actor *actor);
int shotPatternTwo(Actor *actor);
int shotPatternThree(Actor *actor);
int shotPatternFour(Actor *actor);
int shotPatternFive(Actor *actor);
int shotPatternSix(Actor *actor);
int shotPatternSeven(Actor *actor);
int shotPatternEight(Actor *actor);
int (*const shotPatternFunc[])(Actor *actor) = {
shotPatternNone,
shotPatternOne,
shotPatternTwo,
shotPatternThree,
shotPatternFour,
shotPatternFive,
shotPatternSix,
shotPatternSeven,
shotPatternEight,
};
// No shooting
int shotPatternNone(Actor *actor) {
return 0;
}
// Uni-directional seek
int shotPatternOne(Actor *actor) {
switch (actor->_lastDir) {
case 0:
if (ABS(_G(thorX1) - actor->_x) < 8) {
if (actor->_y > _G(thorRealY1)) { //r
if (actorShoots(actor, 0))
return 1;
}
}
break;
case 1:
if (ABS(_G(thorX1) - actor->_x) < 8) {
if (actor->_y < _G(thorRealY1)) { //r
if (actorShoots(actor, 1))
return 1;
}
}
break;
case 2:
if (ABS(_G(thorRealY1) - actor->_y) < 8) { //r
if (actor->_x > _G(thorX1)) {
if (actorShoots(actor, 2))
return 1;
}
}
break;
case 3:
if (ABS(_G(thorRealY1) - actor->_y) < 8) { //r
if (actor->_x < _G(thorX1)) {
if (actorShoots(actor, 3))
return 1;
}
}
break;
default:
break;
}
return 0;
}
// Omni directional
int shotPatternTwo(Actor *actor) {
if (ABS(_G(thor)->_x - actor->_x) < 8) {
if (_G(thor)->_y > actor->_y)
actorShoots(actor, 1);
else if (_G(thor)->_y < actor->_y)
actorShoots(actor, 0);
else
return 0;
} else if (ABS(_G(thor)->_y - actor->_y) < 8) {
if (_G(thor)->_x > actor->_x)
actorShoots(actor, 3);
else if (_G(thor)->_x < actor->_x)
actorShoots(actor, 2);
} else {
return 0;
}
return 1;
}
// Uni directional (backwards)
int shotPatternThree(Actor *actor) {
const int oldDir = actor->_lastDir;
if (shotPatternOne(actor)) {
actor->_lastDir = reverseDirection(actor);
return 1;
}
actor->_lastDir = reverseDirection(actor);
shotPatternOne(actor);
actor->_lastDir = oldDir;
return 1;
}
// Omni-directional not solid shot
int shotPatternFour(Actor *actor) {
if (ABS(_G(thor)->_x - actor->_x) < 8) {
if (_G(thor)->_y > actor->_y)
actorAlwaysShoots(actor, 1);
else if (_G(thor)->_y < actor->_y)
actorAlwaysShoots(actor, 0);
else
return 0;
} else if (ABS(_G(thor)->_y - actor->_y) < 8) {
if (_G(thor)->_x > actor->_x)
actorAlwaysShoots(actor, 3);
else if (_G(thor)->_x < actor->_x)
actorAlwaysShoots(actor, 2);
} else {
return 0;
}
return 1;
}
// Boss - snake
int shotPatternFive(Actor *actor) {
if (_G(rand1) < 15 && (actor->_temp1 == 0) && (actor->_temp2 == 0)) {
actor->_y += 16;
actor->_numShotsAllowed = 3 + _G(setup)._difficultyLevel;
actorShoots(actor, 2);
playSound(BOSS12, false);
const int num = actor->_shotActor;
actor->_shotCountdown = 50;
_G(actor[num])._temp3 = 120;
_G(actor[num])._temp4 = 5 + (_G(rand2) % 17);
_G(actor[num])._temp5 = _G(actor[num])._temp4;
actor->_y -= 16;
return 1;
}
return 0;
}
// 4 surrounding squares
int shotPatternSix(Actor *actor) {
const int pos = ((actor->_x) / 16) + (((actor->_y) / 16) * 20);
if (_G(thorPos) == pos - 20)
actorShoots(actor, 0);
else if (_G(thorPos) == pos + 20)
actorShoots(actor, 1);
else if (_G(thorPos) == pos - 1)
actorShoots(actor, 2);
else if (_G(thorPos) == pos + 1)
actorShoots(actor, 3);
else
return 0;
actor->_frameSequence[3] = 3;
actor->_nextFrame = 3;
return 1;
}
// none
int shotPatternSeven(Actor *actor) {
return 0;
}
// random
int shotPatternEight(Actor *actor) {
if (!actor->_i2) {
actor->_i1 = actor->_funcPass;
actor->_i2 = 1;
}
if (actor->_i1) {
actor->_i1--;
} else if (_G(rand1) < 10) {
actor->_i1 = actor->_funcPass;
actor->_i2 = _G(thorRealY1);
actorShoots(actor, 0);
return 1;
}
return 0;
}
} // namespace Got

View File

@@ -0,0 +1,33 @@
/* 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 GOT_GAME_SHOT_PATTERN_H
#define GOT_GAME_SHOT_PATTERN_H
#include "got/data/defines.h"
namespace Got {
extern int (*const shotPatternFunc[])(Actor *actor);
} // namespace Got
#endif

View File

@@ -0,0 +1,290 @@
/* 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 "got/game/special_tile.h"
#include "got/events.h"
#include "got/game/back.h"
#include "got/game/object.h"
#include "got/gfx/image.h"
#include "got/vars.h"
namespace Got {
int openDoor1(int y, int x);
int cashDoor1(int y, int x, int amount);
void eraseDoor(int x, int y);
int specialTileThor(const int x, const int y, const int icon) {
int cx, cy;
int f = 0;
switch (icon) {
case 201:
return openDoor1(x, y);
case 202:
if (GAME3) {
if (_G(thorInfo)._inventory & 64) {
if (_G(thorInfo)._object == 4) {
eraseDoor(y, x);
deleteObject();
return 1;
}
}
return 0;
}
if (_G(thor)->_x > 300)
// Ending bridge
_G(endTile) = true;
return 1;
case 203:
if (!GAME1) {
if ((_G(thorInfo)._inventory & 64) && _G(thorInfo)._object == 5) {
odinSpeaks(2012, 0);
deleteObject();
_G(setup).f10 = true;
} else if (!_G(setup).f10) {
odinSpeaks(2011, 0);
_G(setup).f10 = true;
}
return 1;
}
return 0;
case 204:
if (GAME2) {
if (!_G(setup).f19)
_G(slipFlag) = true;
return 1;
}
if (GAME3) {
if (_G(thor)->_x < 4)
_G(endTile) = true;
return 1;
}
return 0;
case 205:
if (!_G(diag) && _G(thor)->_dir != 1)
return 1;
break;
case 206:
if (!_G(diag) && _G(thor)->_dir != 0)
return 1;
break;
case 207:
if (!_G(diag) && _G(thor)->_dir != 3)
return 1;
break;
case 208:
if (!_G(diag) && _G(thor)->_dir != 2)
return 1;
break;
case 209:
return cashDoor1(x, y, 10);
case 210:
return cashDoor1(x, y, 100);
case 211:
if (GAME1) {
placeTile(y, x, 79);
_G(exitFlag) = 2;
} else if (GAME2) {
if (_G(thor)->_dir == 0 && _G(setup).f29 && _G(setup).f21 && !_G(setup).f22) {
actorVisible(1);
actorVisible(2);
actorVisible(3);
actorVisible(4);
actorVisible(5);
Common::fill(_G(scrn)._actorInvis, _G(scrn)._actorInvis + 16, 0);
_G(thunderSnakeCounter) = 60;
playSound(THUNDER, true);
_G(setup).f22 = true;
}
} else {
// Game 3
return 0;
}
return 1;
case 212:
case 213:
return 0;
case 214: // Teleport tiles
case 215:
case 216:
case 217:
if ((GAME2 && icon == 217) || GAME3) {
cx = (_G(thorX1) + 7) / 16;
cy = (_G(thorRealY1) + 8) / 16;
if (_G(scrn)._iconGrid[cy][cx] == icon) {
_G(thor)->_vulnerableCountdown = STAMINA;
playSound(WOOP, false);
const int nt = _G(scrn)._newLevelLocation[icon - 214];
const int displayPage = _G(pge);
const int drawPage = _G(pge) ^ 1;
_G(thor)->_lastX[displayPage] = _G(thor)->_x;
_G(thor)->_lastY[displayPage] = _G(thor)->_y;
_G(thor)->_x = (nt % 20) * 16;
_G(thor)->_y = ((nt / 20) * 16) - 2;
_G(thor)->_lastX[drawPage] = _G(thor)->_x;
_G(thor)->_lastY[drawPage] = _G(thor)->_y;
return 0;
}
return 1;
}
return 0;
case 218:
case 219:
// Hole tiles
f = 1;
// fall through
case 220:
case 221:
case 222:
case 223:
case 224:
case 225:
case 226:
case 227:
case 228:
case 229:
// Hole tiles
cx = (_G(thorX1) + 7) / 16;
cy = (_G(thorRealY1) + 8) / 16;
if (_G(scrn)._iconGrid[cy][cx] == icon) {
_G(thor)->_vulnerableCountdown = STAMINA;
if (icon < 224 && icon > 219)
playSound(FALL, false);
_G(newLevel) = _G(scrn)._newLevel[icon - 220 + (f * 6)];
_G(warpScroll) = false;
if (_G(newLevel) > 119) {
_G(warpScroll) = true;
_G(newLevel) -= 128;
}
_G(newLevelTile) = _G(scrn)._newLevelLocation[icon - 220 + (f * 6)];
_G(warpFlag) = true;
if (_G(warpScroll)) {
if (_G(thor)->_dir == 0)
_G(thor)->_y = 175;
else if (_G(thor)->_dir == 1)
_G(thor)->_y = 0;
else if (_G(thor)->_dir == 2)
_G(thor)->_x = 304;
else if (_G(thor)->_dir == 3)
_G(thor)->_x = 0;
} else {
_G(thor)->_x = (_G(newLevelTile) % 20) * 16;
_G(thor)->_y = ((_G(newLevelTile) / 20) * 16) - 2;
}
_G(thor)->_lastX[0] = _G(thor)->_x;
_G(thor)->_lastX[1] = _G(thor)->_x;
_G(thor)->_lastY[0] = _G(thor)->_y;
_G(thor)->_lastY[1] = _G(thor)->_y;
return 0;
}
return 1;
default:
break;
}
return 0;
}
int specialTile(const Actor *actor, int x, int y, const int icon) {
switch (icon) {
case 201:
case 202:
case 203:
case 204:
break;
case 205:
case 206:
case 207:
case 208:
return 1;
case 209:
case 210:
case 214:
case 215:
case 216:
case 217:
return 0;
case 224:
case 225:
case 226:
case 227:
if (!actor->_flying)
return 0;
return 1;
default:
return 1;
}
return 0;
}
void eraseDoor(const int x, const int y) {
playSound(DOOR, false);
_G(scrn)._iconGrid[y][x] = _G(scrn)._backgroundColor;
}
int openDoor1(const int y, const int x) {
if (_G(thorInfo)._keys > 0) {
eraseDoor(x, y);
_G(thorInfo)._keys--;
return 1;
}
if (!_G(keyDoorInform)) {
odinSpeaks(2003, 0);
_G(keyDoorInform) = true;
}
return 0;
}
int cashDoor1(const int y, const int x, const int amount) {
if (_G(thorInfo)._jewels >= amount) {
eraseDoor(x, y);
_G(thorInfo)._jewels -= amount;
return 1;
}
if (amount == 10 && !_G(cashDoor1Inform)) {
odinSpeaks(2005, 0);
_G(cashDoor1Inform) = true;
}
if (amount == 100 && !_G(cashDoor2Inform)) {
odinSpeaks(2004, 0);
_G(cashDoor2Inform) = true;
}
return 0;
}
} // namespace Got

View File

@@ -0,0 +1,34 @@
/* 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 GOT_GAME_SPECIAL_TILE_H
#define GOT_GAME_SPECIAL_TILE_H
#include "got/data/defines.h"
namespace Got {
extern int specialTileThor(int x, int y, int icon);
extern int specialTile(const Actor *actor, int x, int y, int icon);
} // namespace Got
#endif

View File

@@ -0,0 +1,67 @@
/* 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 "got/game/status.h"
#include "got/events.h"
#include "got/vars.h"
namespace Got {
void addJewels(int num) {
_G(thorInfo)._jewels = CLIP(_G(thorInfo)._jewels + num, 0, 999);
}
void addScore(int num) {
_G(thorInfo)._score = CLIP(_G(thorInfo)._score + num, 0l, 999999l);
}
void addMagic(int num) {
_G(thorInfo)._magic = CLIP(_G(thorInfo)._magic + num, 0, 150);
}
void addHealth(int num) {
_G(thor)->_health = CLIP(_G(thor)->_health + num, 0, 150);
if (_G(thor)->_health < 1)
g_events->send(GameMessage("THOR_DIES"));
}
void addKeys(int num) {
_G(thorInfo)._keys = CLIP(_G(thorInfo)._keys + num, 0, 99);
}
void fillHealth() {
addHealth(150);
}
void fillMagic() {
addMagic(150);
}
void fillScore(int num, const char *endMessage) {
GameMessage msg("FILL_SCORE");
if (endMessage)
msg._stringValue = endMessage;
msg._value = num;
g_events->send("GameStatus", msg);
}
} // namespace Got

38
engines/got/game/status.h Normal file
View File

@@ -0,0 +1,38 @@
/* 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 GOT_GAME_STATUS_H
#define GOT_GAME_STATUS_H
namespace Got {
extern void addJewels(int num);
extern void addScore(int num);
extern void addMagic(int num);
extern void addHealth(int num);
extern void addKeys(int num);
extern void fillHealth();
extern void fillMagic();
extern void fillScore(int num, const char *endMessage = nullptr);
} // namespace Got
#endif

93
engines/got/gfx/font.cpp Normal file
View File

@@ -0,0 +1,93 @@
/* 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 "got/gfx/font.h"
#include "common/file.h"
#include "got/gfx/gfx_pics.h"
namespace Got {
namespace Gfx {
const byte DIALOG_COLOR[] = {14, 54, 120, 138, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
void Font::load() {
Common::File f;
if (!f.open("TEXT"))
error("Could not open font");
_font.resize(f.size() / 72 + 32);
for (uint i = 32; i < _font.size(); ++i) {
byte buff[8 * 9];
f.read(buff, 8 * 9);
_font[i].create(8, 9);
convertPaneDataToSurface(buff, _font[i]);
}
}
void Font::drawString(Graphics::ManagedSurface *src, const Common::Point &pos, const Common::String &text, int color) {
const char *string = text.c_str();
Common::Point pt = pos;
while (*string) {
char ch = *string++;
if (ch == '~' && Common::isXDigit(*string)) {
ch = *string++;
if (Common::isDigit(ch)) {
ch -= 48;
} else {
ch = toupper(ch) - 55;
}
color = DIALOG_COLOR[(byte)ch];
continue;
}
if (ch > 31 && ch < 127)
drawChar(src, ch, pt.x, pt.y, color);
pt.x += 8;
}
}
void Font::drawChar(Graphics::Surface *dst, const uint32 chr, const int x, const int y, const uint32 color) const {
// Character drawing is done twice in the original:
// first at y + 1 with color 0, then at y with the given color
rawDrawChar(dst, chr, x, y + 1, 0);
rawDrawChar(dst, chr, x, y, color);
}
void Font::rawDrawChar(Graphics::Surface *dst, const uint32 chr, const int x, const int y, const uint32 color) const {
const Graphics::ManagedSurface &glyph = _font[chr];
for (int yp = 0; yp < glyph.h; ++yp) {
const int startY = y + yp;
const byte *srcP = (const byte *)glyph.getBasePtr(0, yp);
byte *destP = (byte *)dst->getBasePtr(x, startY);
for (int xp = 0; xp < glyph.w; ++xp, ++srcP, ++destP) {
if (*srcP)
*destP = color;
}
}
}
} // namespace Gfx
} // namespace Got

63
engines/got/gfx/font.h Normal file
View File

@@ -0,0 +1,63 @@
/* 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 GOT_GFX_FONT_H
#define GOT_GFX_FONT_H
#include "common/array.h"
#include "graphics/font.h"
#include "graphics/managed_surface.h"
namespace Got {
namespace Gfx {
extern const byte DIALOG_COLOR[];
class Font : public Graphics::Font {
private:
Common::Array<Graphics::ManagedSurface> _font;
public:
void load();
int getFontHeight() const override {
return 9;
}
int getMaxCharWidth() const override {
return 8;
}
int getCharWidth(uint32 chr) const override {
return 8;
}
void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
void drawChar(Graphics::ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const override {
Graphics::Font::drawChar(dst, chr, x, y, color);
}
void rawDrawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const;
void drawString(Graphics::ManagedSurface *src, const Common::Point &pos,
const Common::String &text, int color);
};
} // namespace Gfx
} // namespace Got
#endif

View File

@@ -0,0 +1,146 @@
/* 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 "got/gfx/gfx_chunks.h"
#include "common/file.h"
#include "got/utils/compression.h"
namespace Got {
namespace Gfx {
void GraphicChunk::load(Common::SeekableReadStream *src, const byte *data) {
_compressMode = src->readUint16LE();
_offset = src->readUint32LE();
_uncompressedSize = src->readUint16LE();
_compressedSize = src->readUint16LE();
_width = src->readUint16LE();
_height = src->readUint16LE();
_data = data + _offset;
}
void GraphicChunk::enable() {
// Data already uncompressed, nothing further needed
if (_compressMode == UNCOMPRESSED)
return;
_decompressedData.resize(_uncompressedSize);
switch (_compressMode) {
case LZSS:
decompressLzss(_data, &_decompressedData[0], _uncompressedSize);
break;
case RLE:
decompressRle(_data, &_decompressedData[0], _uncompressedSize);
break;
default:
error("Unknown compression type %d", _compressMode);
}
// Mark the entry as uncompressed, and point to the data
_compressMode = UNCOMPRESSED;
_data = &_decompressedData[0];
}
GraphicChunk::operator const Graphics::ManagedSurface() const {
Graphics::ManagedSurface s;
s.w = s.pitch = _width;
s.h = _height;
s.format = Graphics::PixelFormat::createFormatCLUT8();
s.setPixels(const_cast<byte *>(_data));
return s;
}
GraphicChunk::operator const Gfx::Palette63() const {
return Gfx::Palette63(_data);
}
void GfxChunks::load() {
// Get stream to access images
Common::SeekableReadStream *f = getStream();
#if 0
Common::DumpFile df;
if (df.open("got.gfx")) {
df.writeStream(f);
f->seek(0);
}
df.close();
#endif
// Keep a copy in memory for decoding images as needed
_data = new byte[f->size()];
f->read(_data, f->size());
// Set the number of images
f->seek(0);
_chunks.resize(f->readUint16LE());
// Iterate through loading the image metrics
for (uint i = 0; i < _chunks.size(); ++i)
_chunks[i].load(f, _data);
// Close the file
delete f;
// Decompress two ranges of chunks by default
for (uint i = 0; i < 34; ++i)
_chunks[i].enable();
}
GraphicChunk &GfxChunks::operator[](uint idx) {
GraphicChunk &chunk = _chunks[idx];
chunk.enable();
return chunk;
}
Common::SeekableReadStream *GfxChunks::getStream() const {
// Check for stand-alone graphics file
Common::File *f = new Common::File;
if (f->open("got.gfx"))
return f;
delete f;
// Check for got.exe executable
Common::File fExe;
if (!fExe.open("got.exe"))
error("Could not locate got graphics");
if (fExe.readUint16BE() != MKTAG16('M', 'Z'))
error("Invalid exe header");
const int lastPageSize = fExe.readUint16LE();
const int totalPages = fExe.readUint16LE();
const int offset = lastPageSize ? ((totalPages - 1) << 9) + lastPageSize : totalPages << 9;
fExe.seek(offset);
if (fExe.readUint16BE() != MKTAG16(0xe2, 0x4a))
error("Invalid embedded graphics signature");
return fExe.readStream(fExe.size() - fExe.pos());
}
} // namespace Gfx
} // namespace Got

View File

@@ -0,0 +1,109 @@
/* 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 GOT_GFX_GFX_CHUNKS_H
#define GOT_GFX_GFX_CHUNKS_H
#include "common/stream.h"
#include "got/gfx/palette.h"
#include "graphics/managed_surface.h"
namespace Got {
namespace Gfx {
class GfxChunks;
enum CompressMode { UNCOMPRESSED = 0,
LZSS = 1,
RLE = 2 };
struct GraphicChunk {
private:
Common::Array<byte> _decompressedData;
public:
int _compressMode = UNCOMPRESSED;
uint32 _offset = 0;
uint16 _uncompressedSize = 0;
uint16 _compressedSize = 0;
uint16 _width = 0;
uint16 _height = 0;
const byte *_data = nullptr;
/**
* Load the overall info for a chunk
*/
void load(Common::SeekableReadStream *src, const byte *data);
/**
* Handles any decompression necessary for the entry
*/
void enable();
/**
* Provides a managed surface wrapper for raw data
*/
operator const Graphics::ManagedSurface() const;
/**
* Provides a data pointer, used for getting palette chunks
*/
operator const Gfx::Palette63() const;
};
/**
* Interface for accessing the graphics.got file.
* In the release, this is embedded in the executable starting
* at offset 18af2h onwards. The preceding two bytes should be E2 4A.
* The collection is mostly images, but there are some palettes and
* sounds included as well.
*/
class GfxChunks {
private:
Common::Array<GraphicChunk> _chunks;
byte *_data = nullptr;
/**
* Opens the graphics for access
*/
Common::SeekableReadStream *getStream() const;
public:
~GfxChunks() {
delete[] _data;
}
/**
* Loads the graphic data
*/
void load();
/**
* Access a chunk
*/
GraphicChunk &operator[](uint idx);
};
} // namespace Gfx
} // namespace Got
#endif

View File

@@ -0,0 +1,117 @@
/* 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 "got/gfx/gfx_pics.h"
#include "common/file.h"
#include "got/utils/file.h"
namespace Got {
namespace Gfx {
void convertPaneDataToSurface(const byte *src, Graphics::ManagedSurface &surf) {
surf.setTransparentColor(0);
// It's split into 4 panes per 4 pixels, so we need
// to juggle the pixels into their correct order
for (int plane = 0; plane < 4; ++plane) {
for (int y = 0; y < surf.h; ++y) {
byte *dest = (byte *)surf.getBasePtr(plane, y);
for (int x = 0; x < (surf.w / 4); ++x, dest += 4, ++src) {
// For some reason, both '0' and '15' are both hard-coded
// as transparent colors in the graphics drawing. Simplify
// this for ScummVM by changing all 15's to 0
*dest = (*src == 15) ? 0 : *src;
}
}
}
}
void GfxPics::clear() {
delete[] _array;
_array = nullptr;
}
void GfxPics::resize(uint newSize) {
assert(!_array); // Don't support multiple resizes
_array = new Graphics::ManagedSurface[newSize];
_size = newSize;
}
void GfxPics::load(const Common::String &name, int blockSize) {
File f(name);
// Set up array of images
clear();
if (blockSize == -1) {
// Only a single image
resize(1);
blockSize = f.size();
} else {
resize(f.size() / blockSize);
}
byte *buff = new byte[blockSize];
for (uint idx = 0; idx < size(); ++idx) {
int w = f.readUint16LE() * 4;
int h = f.readUint16LE();
f.skip(2); // Unused transparent color. It's always 15
f.read(buff, blockSize - 6);
Graphics::ManagedSurface &s = (*this)[idx];
s.create(w, h);
convertPaneDataToSurface(buff, s);
}
delete[] buff;
}
GfxPics &GfxPics::operator=(const GfxPics &src) {
clear();
resize(src._size);
for (size_t i = 0; i < _size; ++i)
_array[i].copyFrom(src._array[i]);
return *this;
}
void BgPics::setArea(int area) {
_area = area;
load();
}
void BgPics::load() {
const Common::String name = Common::String::format("BPICS%d", _area);
GfxPics::load(name, 262);
if (_area == 2) {
// FIXME: Background tile 0xbe in part 2 is used for the invisible
// maze in part 2 to get the shovel, but it's not drawing as black.
// Manually set the transparent color for it so it's properly transparent
(*this)[0xbe].setTransparentColor(31);
}
}
} // namespace Gfx
} // namespace Got

View File

@@ -0,0 +1,98 @@
/* 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 GOT_GFX_GFX_PICS_H
#define GOT_GFX_GFX_PICS_H
#include "graphics/managed_surface.h"
namespace Got {
namespace Gfx {
/**
* The original graphics screen was set up to use 4 panes,
* where each pane had a single pixel, repeating every 4 pixels.
* Because of this, graphics were stored with all the data for
* each pane one at a time. This helper methods takes care of
* "de-paneing" the graphics into a provided surface
*/
extern void convertPaneDataToSurface(const byte *src, Graphics::ManagedSurface &surf);
class GfxPics {
private:
Graphics::ManagedSurface *_array = nullptr;
size_t _size = 0;
protected:
public:
~GfxPics() {
clear();
}
void clear();
void resize(uint newSize);
void load(const Common::String &name, int blockSize);
Graphics::ManagedSurface &operator[](uint idx) {
return _array[idx];
}
size_t size() const {
return _size;
}
GfxPics &operator=(const GfxPics &src);
};
class BgPics : public GfxPics {
private:
int _area = 1;
public:
void load();
bool getArea() const {
return _area;
}
void setArea(int area);
};
class Pics : public GfxPics {
private:
Common::String _resName;
int _blockSize = -1;
public:
Pics(const Common::String &resName, int blockSize = -1,
bool immediateLoad = true) : _resName(resName), _blockSize(blockSize) {
if (immediateLoad)
load();
}
Pics() {}
void load() {
GfxPics::load(_resName, _blockSize);
}
};
} // namespace Gfx
} // namespace Got
#endif

View File

@@ -0,0 +1,42 @@
/* 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 "got/gfx/gfx_surface.h"
#include "got/vars.h"
namespace Got {
namespace Gfx {
void GfxSurface::print(const Common::Point &pos,
const Common::String &text, int color) {
_G(font).drawString(this, pos, text, color);
}
void GfxSurface::printChar(uint32 chr, int x, int y, uint32 color) {
_G(font).drawChar(this, chr, x, y, color);
}
void GfxSurface::rawPrintChar(uint32 chr, int x, int y, uint32 color) {
_G(font).rawDrawChar(surfacePtr(), chr, x, y, color);
}
} // namespace Gfx
} // namespace Got

View File

@@ -0,0 +1,46 @@
/* 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 GOT_GFX_SURFACE_H
#define GOT_GFX_SURFACE_H
#include "graphics/managed_surface.h"
namespace Got {
namespace Gfx {
class GfxSurface : public Graphics::ManagedSurface {
public:
GfxSurface() : Graphics::ManagedSurface() {}
GfxSurface(Graphics::ManagedSurface &surf, const Common::Rect &bounds) : Graphics::ManagedSurface(surf, bounds) {}
/**
* Write some text to the surface
*/
void print(const Common::Point &pos, const Common::String &text, int color);
void printChar(uint32 chr, int x, int y, uint32 color);
void rawPrintChar(uint32 chr, int x, int y, uint32 color);
};
} // namespace Gfx
} // namespace Got
#endif

273
engines/got/gfx/image.cpp Normal file
View File

@@ -0,0 +1,273 @@
/* 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 "got/gfx/image.h"
#include "common/memstream.h"
#include "got/events.h"
#include "got/got.h"
#include "got/utils/file.h"
#include "got/vars.h"
namespace Got {
static void createSurface(Graphics::ManagedSurface &s, const byte *src) {
s.create(16, 16);
// Both 0 and 15 are transparent colors, so as we load the
// surface, standard on a single color
byte *dest = (byte *)s.getPixels();
for (int i = 0; i < 16 * 16; ++i, ++src, ++dest)
*dest = (*src == 15) ? 0 : *src;
s.setTransparentColor(0);
}
void setupActor(Actor *actor, const char num, const char dir, const int x, const int y) {
actor->_nextFrame = 0; // Next frame to be shown
actor->_frameCount = actor->_frameSpeed;
actor->_dir = dir; // Direction of travel
actor->_lastDir = dir; // Last direction of travel
if (actor->_directions == 1)
actor->_dir = 0;
if (actor->_directions == 2)
actor->_dir &= 1;
if (actor->_directions == 4 && actor->_framesPerDirection == 1) {
actor->_dir = 0;
actor->_nextFrame = dir;
}
actor->_x = x; // Actual X coordinates
actor->_y = y; // Actual Y coordinates
actor->_width = 16; // Actual X coordinates
actor->_height = 16; // Actual Y coordinates
actor->_center = 0; // Center of object
actor->_lastX[0] = x; // Last X coordinates on each page
actor->_lastX[1] = x;
actor->_lastY[0] = y; // Last Y coordinates on each page
actor->_lastY[1] = y;
actor->_active = true; // true=active, false=not active
actor->_moveCountdown = 8; // Count down to movement
actor->_vulnerableCountdown = STAMINA; // Count down to vulnerability
actor->_shotCountdown = 20; // Count down to another shot
actor->_currNumShots = 0; // # of shots currently on screen
actor->_creator = 0; // which actor # created this actor
actor->_unpauseCountdown = 0; // Pause must be 0 to move
actor->_show = 0;
actor->_actorNum = num;
actor->_counter = 0;
actor->_moveCounter = 0;
actor->_edgeCounter = 20;
actor->_hitThor = false;
actor->_rand = g_engine->getRandomNumber(99);
actor->_temp1 = 0;
actor->_initHealth = actor->_health;
}
void make_actor_surface(Actor *actor) {
assert(actor->_directions <= 4 && actor->_framesPerDirection <= 4);
for (int d = 0; d < actor->_directions; d++) {
for (int f = 0; f < actor->_framesPerDirection; f++) {
Graphics::ManagedSurface &s = actor->pic[d][f];
const byte *src = &_G(tmpBuff[256 * ((d * 4) + f)]);
createSurface(s, src);
}
}
}
int loadStandardActors() {
loadActor(0, 100 + _G(thorInfo)._armor); // Load Thor
_G(actor[0]).loadFixed(_G(tmpBuff) + 5120);
setupActor(&_G(actor[0]), 0, 0, 100, 100);
_G(thor) = &_G(actor[0]);
make_actor_surface(&_G(actor[0]));
_G(thorX1) = _G(thor)->_x + 2;
_G(thorY1) = _G(thor)->_y + 2;
_G(thorX2) = _G(thor)->_x + 14;
_G(thorY2) = _G(thor)->_y + 14;
loadActor(0, 103 + _G(thorInfo)._armor); // Load hammer
_G(actor[1]).loadFixed(_G(tmpBuff) + 5120);
setupActor(&_G(actor[1]), 1, 0, 100, 100);
_G(actor[1])._active = false;
_G(hammer) = &_G(actor[1]);
make_actor_surface(&_G(actor[1]));
// Load sparkle
loadActor(0, 106);
_G(sparkle).loadFixed(_G(tmpBuff) + 5120);
setupActor(&_G(sparkle), 20, 0, 100, 100);
_G(sparkle)._active = false;
make_actor_surface(&_G(sparkle));
// Load explosion
loadActor(0, 107);
_G(explosion).loadFixed(_G(tmpBuff) + 5120);
setupActor(&_G(explosion), 21, 0, 100, 100);
_G(explosion)._active = false;
make_actor_surface(&_G(explosion));
// Load tornado
loadActor(0, 108);
_G(magicItem[0]).loadFixed((const byte *)_G(tmpBuff) + 5120);
Common::copy(_G(tmpBuff), _G(tmpBuff) + 1024, _G(magicPic[0]));
setupActor(&_G(magicItem[0]), 20, 0, 0, 0);
_G(magicItem[0])._active = false;
// Load shield
loadActor(0, 109);
_G(magicItem[1]).loadFixed((const byte *)_G(tmpBuff) + 5120);
Common::copy(_G(tmpBuff), _G(tmpBuff) + 1024, _G(magicPic[1]));
setupActor(&_G(magicItem[1]), 20, 0, 0, 0);
_G(magicItem[1])._active = false;
_G(actor[2])._active = false;
make_actor_surface(&_G(magicItem[0]));
return 1;
}
void showEnemies() {
for (int i = 3; i < MAX_ACTORS; i++)
_G(actor[i])._active = false;
for (int i = 0; i < MAX_ENEMIES; i++)
_G(enemyType[i]) = 0;
for (int i = 0; i < MAX_ENEMIES; i++) {
if (_G(scrn)._actorType[i] > 0) {
const int id = loadEnemy(_G(scrn)._actorType[i]);
if (id >= 0) {
_G(actor[i + 3]) = _G(enemy[id]);
const int d = _G(scrn)._actorDir[i];
setupActor(&_G(actor[i + 3]), i + 3, d, (_G(scrn)._actorLoc[i] % 20) * 16,
(_G(scrn)._actorLoc[i] / 20) * 16);
_G(actor[i + 3])._initDir = _G(scrn)._actorDir[i];
_G(actor[i + 3])._passValue = _G(scrn)._actorValue[i];
if (_G(actor[i + 3])._moveType == 23) {
// Spinball
if (_G(actor[i + 3])._passValue & 1)
_G(actor[i + 3])._moveType = 24;
}
if (_G(scrn)._actorInvis[i])
_G(actor[i + 3])._active = false;
}
_G(etype[i]) = id;
}
}
}
int loadEnemy(const int type) {
for (int i = 0; i < MAX_ENEMIES; i++) {
if (_G(enemyType[i]) == type)
return i;
}
if (!loadActor(1, type)) {
return -1;
}
int e = -1;
for (int i = 0; i < MAX_ENEMIES; i++) {
if (!_G(enemyType[i])) {
e = i;
break;
}
}
if (e == -1)
return -1;
Common::MemoryReadStream inf(_G(tmpBuff) + 5120, 40);
_G(enemy[e]).loadFixed(&inf);
make_actor_surface(&_G(enemy[e]));
_G(enemyType[e]) = type;
_G(enemy[e])._shotType = 0;
if (_G(enemy[e])._numShotsAllowed) {
_G(enemy[e])._shotType = e + 1;
// Set up shot info
_G(shot[e]).loadFixed(_G(tmpBuff) + 5160);
// Loop to set up graphics
for (int d = 0; d < _G(shot[e])._directions; d++) {
for (int f = 0; f < _G(shot[e])._framesPerDirection; f++) {
if (_G(shot[e])._directions < _G(shot[e])._framesPerDirection) {
Graphics::ManagedSurface &s = _G(shot[e]).pic[d][f];
const byte *src = &_G(tmpBuff[4096 + (256 * ((d * 4) + f))]);
createSurface(s, src);
} else {
Graphics::ManagedSurface &s = _G(shot[e]).pic[f][d];
const byte *src = &_G(tmpBuff[4096 + (256 * ((f * 4) + d))]);
createSurface(s, src);
}
}
}
}
return e;
}
int actorVisible(const int invisNum) {
for (int i = 0; i < MAX_ENEMIES; i++) {
if (_G(scrn)._actorInvis[i] == invisNum) {
const int etype = _G(etype[i]);
if (etype >= 0 && !_G(actor[i + 3])._active) {
_G(actor[i + 3]) = _G(enemy[etype]);
int d = _G(scrn)._actorDir[i];
setupActor(&_G(actor[i + 3]), i + 3, d, (_G(scrn)._actorLoc[i] % 20) * 16,
(_G(scrn)._actorLoc[i] / 20) * 16);
_G(actor[i + 3])._initDir = _G(scrn)._actorDir[i];
_G(actor[i + 3])._passValue = _G(scrn)._actorValue[i];
return i;
}
return -1;
}
}
return -1;
}
void setupMagicItem(const int item) {
for (int i = 0; i < 4; i++) {
createSurface(_G(magicItem[item]).pic[i / 4][i % 4], &_G(magicPic[item][256 * i]));
}
}
void loadNewThor() {
loadActor(0, 100 + _G(thorInfo)._armor); // Load Thor
make_actor_surface(&_G(actor[0]));
}
} // namespace Got

39
engines/got/gfx/image.h Normal file
View File

@@ -0,0 +1,39 @@
/* 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 GOT_GFX_IMAGE_H
#define GOT_GFX_IMAGE_H
#include "got/data/defines.h"
namespace Got {
extern void setupActor(Actor *actor, char num, char dir, int x, int y);
extern int loadStandardActors();
extern void showEnemies();
extern int loadEnemy(int type);
extern int actorVisible(int invisNum);
extern void setupMagicItem(int item);
extern void loadNewThor();
} // namespace Got
#endif

144
engines/got/gfx/palette.cpp Normal file
View File

@@ -0,0 +1,144 @@
/* 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 "got/gfx/palette.h"
#include "common/events.h"
#include "common/system.h"
#include "got/got.h"
#include "got/utils/file.h"
#include "got/vars.h"
#include "graphics/paletteman.h"
namespace Got {
namespace Gfx {
#define FADE_STEPS 10
static byte saved_palette[Graphics::PALETTE_SIZE];
Palette63::Palette63(const byte *pal) {
for (uint i = 0; i < Graphics::PALETTE_SIZE; ++i)
_pal[i] = pal[i] << 2;
}
void loadPalette() {
if (resourceRead("PALETTE", saved_palette) < 0)
error("Cannot Read PALETTE");
g_system->getPaletteManager()->setPalette(saved_palette, 0, 256);
}
void setScreenPal() {
byte pal[3];
xGetPal(pal, 1, _G(scrn)._palColors[0]);
xSetPal(251, pal[0], pal[1], pal[2]);
xGetPal(pal, 1, _G(scrn)._palColors[1]);
xSetPal(252, pal[0], pal[1], pal[2]);
xGetPal(pal, 1, _G(scrn)._palColors[2]);
xSetPal(253, pal[0], pal[1], pal[2]);
}
void xSetPal(const byte color, const byte R, const byte G, const byte B) {
byte rgb[3] = {R, G, B};
g_system->getPaletteManager()->setPalette(rgb, color, 1);
}
void xSetPal(const byte *pal) {
g_system->getPaletteManager()->setPalette(pal, 0, Graphics::PALETTE_COUNT);
}
void setPalette(const byte *pal) {
xSetPal(pal);
Common::copy(pal, pal + Graphics::PALETTE_SIZE, saved_palette);
}
void xGetPal(byte *pal, const int numColors, const int startIndex) {
g_system->getPaletteManager()->grabPalette(pal, startIndex, numColors);
}
void fadeOut() {
byte tempPal[Graphics::PALETTE_SIZE];
const byte *srcP;
byte *destP;
int count;
Common::Event evt;
xGetPal(saved_palette, Graphics::PALETTE_COUNT, 0);
for (int step = FADE_STEPS - 1; step >= 0; --step) {
// Set each palette RGB proportionately
for (srcP = &saved_palette[0], destP = &tempPal[0], count = 0;
count < Graphics::PALETTE_SIZE; ++count, ++srcP, ++destP) {
*destP = *srcP * step / FADE_STEPS;
}
// Set new palette
xSetPal(tempPal);
// Use up any pending events and update the screen
while (g_system->getEventManager()->pollEvent(evt)) {
if (evt.type == Common::EVENT_QUIT)
return;
}
g_events->getScreen()->update();
g_system->delayMillis(10);
}
}
void fadeIn(const byte *pal) {
byte tempPal[Graphics::PALETTE_SIZE];
const byte *srcP;
byte *destP;
int count;
Common::Event evt;
if (pal)
Common::copy(pal, pal + Graphics::PALETTE_SIZE, saved_palette);
// Start with a black palette
Common::fill(tempPal, tempPal + Graphics::PALETTE_SIZE, 0);
xSetPal(tempPal);
for (int step = 1; step <= FADE_STEPS; ++step) {
// Set each palette RGB proportionately
for (srcP = &saved_palette[0], destP = &tempPal[0], count = 0;
count < Graphics::PALETTE_SIZE; ++count, ++srcP, ++destP) {
*destP = *srcP * step / FADE_STEPS;
}
// Set new palette
xSetPal(tempPal);
// Use up any pending events and update the screen
while (g_system->getEventManager()->pollEvent(evt)) {
if (evt.type == Common::EVENT_QUIT)
return;
}
g_events->getScreen()->update();
g_system->delayMillis(10);
}
}
} // namespace Gfx
} // namespace Got

52
engines/got/gfx/palette.h Normal file
View File

@@ -0,0 +1,52 @@
/* 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 GOT_GFX_PALETTE_H
#define GOT_GFX_PALETTE_H
#include "graphics/paletteman.h"
namespace Got {
namespace Gfx {
struct Palette63 {
byte _pal[Graphics::PALETTE_SIZE] = {};
Palette63() {}
Palette63(const byte *pal);
operator const byte *() const {
return _pal;
}
};
extern void loadPalette();
extern void setScreenPal();
extern void setPalette(const byte *pal);
extern void xSetPal(byte color, byte R, byte G, byte B);
extern void xSetPal(const byte *pal);
extern void xGetPal(byte *pal, int numColors, int startIndex);
extern void fadeOut();
extern void fadeIn(const byte *pal = nullptr);
} // namespace Gfx
} // namespace Got
#endif

256
engines/got/got.cpp Normal file
View File

@@ -0,0 +1,256 @@
/* 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 "got/got.h"
#include "common/config-manager.h"
#include "common/scummsys.h"
#include "common/system.h"
#include "common/translation.h"
#include "engines/util.h"
#include "got/console.h"
#include "got/game/init.h"
#include "got/game/main.h"
#include "got/game/move.h"
#include "got/gfx/image.h"
#include "got/utils/res_archive.h"
#include "got/views/game_content.h"
#include "graphics/paletteman.h"
namespace Got {
#define SAVEGAME_VERSION 1
GotEngine *g_engine;
GotEngine::GotEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Got") {
g_engine = this;
}
GotEngine::~GotEngine() {
_mixer->stopAll();
}
uint32 GotEngine::getFeatures() const {
return _gameDescription->flags;
}
bool GotEngine::isDemo() const {
return (_gameDescription->flags & ADGF_DEMO) != 0;
}
Common::String GotEngine::getGameId() const {
return _gameDescription->gameId;
}
Common::Error GotEngine::run() {
// Initialize 320x240 paletted graphics mode. Note that the original
// main menu/dialogs ran at 320x200, but the game ran at 320x240.
initGraphics(320, 240);
// Set the engine's debugger console
setDebugger(new Console());
// Initialize resources and variables
resInit();
_vars.load();
// General initialization
if (_G(demo))
initGame();
syncSoundSettings();
#ifdef USE_TTS
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (ttsMan) {
ttsMan->enable(ConfMan.getBool("tts_enabled"));
ttsMan->setLanguage(ConfMan.get("language"));
}
#endif
runGame();
return Common::kNoError;
}
Common::Error GotEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
stream->writeByte(SAVEGAME_VERSION);
Common::Serializer s(nullptr, stream);
s.setVersion(SAVEGAME_VERSION);
return syncGame(s);
}
Common::Error GotEngine::loadGameStream(Common::SeekableReadStream *stream) {
byte version = stream->readByte();
if (version != SAVEGAME_VERSION)
error("Invalid savegame version");
Common::Serializer s(stream, nullptr);
s.setVersion(version);
return syncGame(s);
}
Common::Error GotEngine::syncGame(Common::Serializer &s) {
char title[32];
Common::fill(title, title + 32, 0);
Common::strcpy_s(title, _G(playerName).c_str());
s.syncBytes((byte *)title, 32);
if (s.isLoading())
_G(playerName) = title;
_G(setup).sync(s);
if (s.isLoading()) {
// For savegames loaded directly from the ScummVM launcher,
// take care of initializing game defaults before rest of loading
if (!firstView() || firstView()->getName() != "Game")
initGame();
int area = _G(setup)._areaNum;
if (area == 0)
area = 1;
if (area != _G(area)) {
_G(area) = area;
g_vars->loadArea();
}
}
_G(thorInfo).sync(s);
_G(sdData).sync(s);
if (s.isLoading())
savegameLoaded();
return Common::kNoError;
}
void GotEngine::savegameLoaded() {
_G(currentArea) = _G(thorInfo)._lastScreen;
_G(thor)->_x = (_G(thorInfo)._lastIcon % 20) * 16;
_G(thor)->_y = ((_G(thorInfo)._lastIcon / 20) * 16) - 1;
if (_G(thor)->_x < 1)
_G(thor)->_x = 1;
if (_G(thor)->_y < 0)
_G(thor)->_y = 0;
_G(thor)->_dir = _G(thorInfo)._lastDir;
_G(thor)->_lastDir = _G(thorInfo)._lastDir;
_G(thor)->_health = _G(thorInfo)._lastHealth;
_G(thor)->_numMoves = 1;
_G(thor)->_vulnerableCountdown = 60;
_G(thor)->_show = 60;
_G(thor)->_moveCountdown = 6;
if (_G(area) == 2)
_G(thorInfo)._armor = 1;
if (_G(area) == 3)
_G(thorInfo)._armor = 10;
loadNewThor();
g_vars->resetEndGameFlags();
_G(setup)._musicEnabled = _G(musicFlag);
_G(setup)._digitalSound = _G(soundFlag);
if (_G(setup)._musicEnabled) {
if (GAME1 && _G(currentArea) == 59) {
musicPlay(5, true);
} else {
musicPlay(_G(levelMusic), true);
}
} else {
_G(setup)._musicEnabled = true;
musicPause();
_G(setup)._musicEnabled = false;
}
_G(gameOver) = _G(setup)._gameOver != 0;
_G(slowMode) = _G(setup)._slowMode;
g_events->replaceView("Game", true);
setupLoad();
}
bool GotEngine::canLoadGameStateCurrently(Common::U32String *msg) {
if (_G(demo)) {
*msg = _("Savegames are not available in demo mode");
return false;
}
// Only allow if not in the middle of area transition, dying, etc.
return _G(gameMode) == MODE_NORMAL;
}
bool GotEngine::canSaveGameStateCurrently(Common::U32String *msg) {
if (_G(demo)) {
*msg = _("Savegames are not available in demo mode");
return false;
}
// Don't allowing saving when not in-game
if (!firstView() || firstView()->getName() != "Game" || _G(gameOver))
return false;
// Only allow if not in the middle of area transition, dying, etc.
return _G(gameMode) == MODE_NORMAL;
}
void GotEngine::syncSoundSettings() {
Engine::syncSoundSettings();
_G(sound).syncSoundSettings();
}
void GotEngine::pauseEngineIntern(bool pause) {
g_vars->clearKeyFlags();
if (_G(gameMode) == MODE_LIGHTNING)
_G(gameMode) = MODE_NORMAL;
if (_G(tornadoUsed)) {
_G(tornadoUsed) = false;
actorDestroyed(&_G(actor[2]));
}
if (_G(shieldOn)) {
_G(actor[2])._dead = 2;
_G(actor[2])._active = false;
_G(shieldOn) = false;
}
_G(thunderSnakeCounter) = 0;
if (pause) {
_G(sound).musicPause();
}
else {
_G(sound).musicResume();
}
Engine::pauseEngineIntern(pause);
}
Common::String GotEngine::getHighScoresSaveName() const {
return Common::String::format("%s-scores.dat", _targetName.c_str());
}
} // End of namespace Got

107
engines/got/got.h Normal file
View File

@@ -0,0 +1,107 @@
/* 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 GOT_H
#define GOT_H
#include "common/error.h"
#include "common/random.h"
#include "common/scummsys.h"
#include "common/serializer.h"
#include "common/system.h"
#include "engines/engine.h"
#include "got/events.h"
#include "got/vars.h"
namespace Got {
struct GotGameDescription;
class GotEngine : public Engine, public Events {
private:
const ADGameDescription *_gameDescription;
Common::RandomSource _randomSource;
void savegameLoaded();
protected:
// Engine APIs
Common::Error run() override;
/**
* Returns true if the game should quit
*/
bool shouldQuit() const override {
return Engine::shouldQuit();
}
public:
Vars _vars;
public:
GotEngine(OSystem *syst, const ADGameDescription *gameDesc);
~GotEngine() override;
uint32 getFeatures() const;
bool isDemo() const override;
/**
* Returns the game Id
*/
Common::String getGameId() const;
/**
* Gets a random number
*/
uint32 getRandomNumber(uint maxNum) {
return _randomSource.getRandomNumber(maxNum);
}
bool hasFeature(EngineFeature f) const override {
return (f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime) ||
(f == kSupportsReturnToLauncher);
};
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override;
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override;
/**
* Uses a serializer to allow implementing savegame
* loading and saving using a single method
*/
Common::Error syncGame(Common::Serializer &s);
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
void syncSoundSettings() override;
void pauseEngineIntern(bool pause) override;
Common::String getHighScoresSaveName() const;
};
extern GotEngine *g_engine;
#define SHOULD_QUIT ::Got::g_engine->shouldQuit()
} // End of namespace Got
#endif // GOT_H

43
engines/got/messages.cpp Normal file
View File

@@ -0,0 +1,43 @@
/* 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 "got/messages.h"
namespace Got {
MouseMessage::MouseMessage(Common::EventType type,
const Common::Point &pos) : Message(), _pos(pos) {
switch (type) {
case Common::EVENT_RBUTTONDOWN:
case Common::EVENT_RBUTTONUP:
_button = MB_RIGHT;
break;
case Common::EVENT_MBUTTONDOWN:
case Common::EVENT_MBUTTONUP:
_button = MB_MIDDLE;
break;
default:
_button = MB_LEFT;
break;
}
}
} // namespace Got

99
engines/got/messages.h Normal file
View File

@@ -0,0 +1,99 @@
/* 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 GOT_MESSAGES_H
#define GOT_MESSAGES_H
#include "common/events.h"
#include "common/str.h"
namespace Got {
class UIElement;
struct Message {};
struct FocusMessage : public Message {
UIElement *_priorView = nullptr;
FocusMessage() : Message() {}
FocusMessage(UIElement *priorView) : Message(), _priorView(priorView) {}
};
struct UnfocusMessage : public Message {};
struct MouseEnterMessage : public Message {};
struct MouseLeaveMessage : public Message {};
struct KeypressMessage : public Message, public Common::KeyState {
KeypressMessage() : Message() {}
KeypressMessage(const Common::KeyState &ks) : Message(), Common::KeyState(ks) {}
};
struct MouseMessage : public Message {
enum Button { MB_LEFT,
MB_RIGHT,
MB_MIDDLE };
Button _button;
Common::Point _pos;
MouseMessage() : Message(), _button(MB_LEFT) {}
MouseMessage(Button btn, const Common::Point &pos) : Message(), _button(btn), _pos(pos) {}
MouseMessage(Common::EventType type, const Common::Point &pos);
};
struct MouseDownMessage : public MouseMessage {
MouseDownMessage() : MouseMessage() {}
MouseDownMessage(Button btn, const Common::Point &pos) : MouseMessage(btn, pos) {}
MouseDownMessage(Common::EventType type, const Common::Point &pos) : MouseMessage(type, pos) {}
};
struct MouseUpMessage : public MouseMessage {
MouseUpMessage() : MouseMessage() {}
MouseUpMessage(Button btn, const Common::Point &pos) : MouseMessage(btn, pos) {}
MouseUpMessage(Common::EventType type, const Common::Point &pos) : MouseMessage(type, pos) {}
};
typedef MouseMessage MouseMoveMessage;
struct GameMessage : public Message {
Common::String _name;
int _value;
Common::String _stringValue;
GameMessage() : Message(), _value(-1) {}
GameMessage(const Common::String &name) : Message(), _name(name), _value(-1) {}
GameMessage(const Common::String &name, int value) : Message(), _name(name), _value(value) {}
GameMessage(const Common::String &name, const Common::String &value) : Message(), _name(name), _stringValue(value), _value(0) {}
};
struct ValueMessage : public Message {
int _value;
ValueMessage() : Message(), _value(0) {}
ValueMessage(int value) : Message(), _value(value) {}
};
struct ActionMessage : public Message {
int _action;
ActionMessage() : Message(), _action(0) {}
ActionMessage(int action) : Message(), _action(action) {}
};
} // namespace Got
#endif

128
engines/got/metaengine.cpp Normal file
View File

@@ -0,0 +1,128 @@
/* 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 "common/translation.h"
#include "backends/keymapper/action.h"
#include "backends/keymapper/keymapper.h"
#include "got/metaengine.h"
#include "got/detection.h"
#include "got/got.h"
namespace Got {
static const ADExtraGuiOptionsMap optionsList[] = {
{
GAMEOPTION_ORIGINAL_SAVELOAD,
{
_s("Use original save/load screens"),
_s("Use the original save/load screens instead of the ScummVM ones"),
"original_menus",
false,
0,
0
}
},
#ifdef USE_TTS
{
GAMEOPTION_TTS,
{
_s("Enable Text to Speech"),
_s("Use TTS to read text in the game (if TTS is available)"),
"tts_enabled",
false,
0,
0
}
},
#endif
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
struct KeybindingRecord {
KeybindingAction _action;
const char *_id;
const char *_desc;
const char *_key;
const char *_joy;
};
static const KeybindingRecord GAME_KEYS[] = {
{ KEYBIND_UP, "UP", _s("Up"), "UP", "JOY_UP"},
{ KEYBIND_DOWN, "DOWN", _s("Down"), "DOWN", "JOY_DOWN"},
{ KEYBIND_LEFT, "LEFT", _s("Left"), "LEFT", "JOY_LEFT"},
{ KEYBIND_RIGHT, "RIGHT", _s("Right"), "RIGHT", "JOY_RIGHT"},
{ KEYBIND_FIRE, "FIRE", _s("Fire"), "LALT", "JOY_A" },
{ KEYBIND_MAGIC, "MAGIC", _s("Magic"), "LCTRL", "JOY_B" },
{ KEYBIND_SELECT, "SELECT", _s("Select"), "SPACE", "JOY_X" },
// I18N: ESC key
{ KEYBIND_ESCAPE, "ESCAPE", _s("Escape"), "ESCAPE", "JOY_Y" },
{ KEYBIND_THOR_DIES, "THOR_DIES", _s("Thor dies"), "d", nullptr },
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
};
} // End of namespace Got
const char *GotMetaEngine::getName() const {
return "got";
}
const ADExtraGuiOptionsMap *GotMetaEngine::getAdvancedExtraGuiOptions() const {
return Got::optionsList;
}
Common::Error GotMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
*engine = new Got::GotEngine(syst, desc);
return Common::kNoError;
}
bool GotMetaEngine::hasFeature(MetaEngineFeature f) const {
return checkExtendedSaves(f) ||
(f == kSupportsLoadingDuringStartup);
}
Common::Array<Common::Keymap *> GotMetaEngine::initKeymaps(const char *target) const {
Common::KeymapArray keymapArray;
Common::Keymap *keyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "got", _s("Game Keys"));
keymapArray.push_back(keyMap);
for (const Got::KeybindingRecord *r = Got::GAME_KEYS; r->_id; ++r) {
Common::Action *act = new Common::Action(r->_id, _(r->_desc));
act->setCustomEngineActionEvent(r->_action);
act->addDefaultInputMapping(r->_key);
if (r->_joy)
act->addDefaultInputMapping(r->_joy);
if (r->_action == Got::KEYBIND_SELECT)
act->addDefaultInputMapping("RETURN");
keyMap->addAction(act);
}
return keymapArray;
}
#if PLUGIN_ENABLED_DYNAMIC(GOT)
REGISTER_PLUGIN_DYNAMIC(GOT, PLUGIN_TYPE_ENGINE, GotMetaEngine);
#else
REGISTER_PLUGIN_STATIC(GOT, PLUGIN_TYPE_ENGINE, GotMetaEngine);
#endif

62
engines/got/metaengine.h Normal file
View File

@@ -0,0 +1,62 @@
/* 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 GOT_METAENGINE_H
#define GOT_METAENGINE_H
#include "engines/advancedDetector.h"
namespace Got {
enum KeybindingAction {
KEYBIND_NONE,
KEYBIND_UP,
KEYBIND_DOWN,
KEYBIND_LEFT,
KEYBIND_RIGHT,
KEYBIND_SELECT,
KEYBIND_FIRE,
KEYBIND_MAGIC,
KEYBIND_ESCAPE,
KEYBIND_THOR_DIES
};
} // namespace Got
class GotMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
public:
const char *getName() const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
/**
* Determine whether the engine supports the specified MetaEngine feature.
*
* Used by e.g. the launcher to determine whether to enable the Load button.
*/
bool hasFeature(MetaEngineFeature f) const override;
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override;
Common::Array<Common::Keymap *> initKeymaps(const char *target) const override;
};
#endif // GOT_METAENGINE_H

80
engines/got/module.mk Normal file
View File

@@ -0,0 +1,80 @@
MODULE := engines/got
MODULE_OBJS = \
got.o \
console.o \
events.o \
messages.o \
metaengine.o \
musicdriver.o \
musicdriver_adlib.o \
musicparser.o \
sound.o \
vars.o \
data/actor.o \
data/highscores.o \
data/level.o \
data/sd_data.o \
data/setup.o \
data/thorinfo.o \
game/boss1.o \
game/boss2.o \
game/boss3.o \
game/back.o \
game/init.o \
game/main.o \
game/move.o \
game/move_patterns.o \
game/object.o \
game/script.o \
game/shot_movement.o \
game/shot_pattern.o \
game/special_tile.o \
game/status.o \
gfx/font.o \
gfx/gfx_chunks.o \
gfx/gfx_pics.o \
gfx/gfx_surface.o \
gfx/image.o \
gfx/palette.o \
utils/compression.o \
utils/file.o \
utils/res_archive.o \
views/view.o \
views/credits.o \
views/game.o \
views/game_content.o \
views/game_status.o \
views/opening.o \
views/part_title.o \
views/splash_screen.o \
views/story.o \
views/title_background.o \
views/dialogs/dialog.o \
views/dialogs/select_option.o \
views/dialogs/ask.o \
views/dialogs/high_scores.o \
views/dialogs/main_menu.o \
views/dialogs/options_menu.o \
views/dialogs/quit.o \
views/dialogs/quit_game.o \
views/dialogs/save_game.o \
views/dialogs/say.o \
views/dialogs/select_game.o \
views/dialogs/select_item.o \
views/dialogs/select_scroll.o \
views/dialogs/select_slow.o \
views/dialogs/set_music.o \
views/dialogs/set_sound.o \
views/dialogs/skill_level.o
# This module can be built as a plugin
ifeq ($(ENABLE_GOT), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o

View File

@@ -0,0 +1,88 @@
/* 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 "got/musicdriver.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/system.h"
namespace Got {
MusicDriver_Got::MusicDriver_Got(uint8 timerFrequency) : _isOpen(false), _timer_param(nullptr), _timer_proc(nullptr) {
setTimerFrequency(timerFrequency);
}
bool MusicDriver_Got::isOpen() const {
return _isOpen;
}
void MusicDriver_Got::setTimerFrequency(uint8 timerFrequency) {
assert(timerFrequency > 0);
_timerFrequency = timerFrequency;
}
void MusicDriver_Got::onTimer() {
if (_timer_proc && _timer_param)
_timer_proc(_timer_param);
}
void MusicDriver_Got::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
_timer_param = timer_param;
_timer_proc = timer_proc;
}
int MusicDriver_Got_NULL::open() {
// There is no output device, so register a timer to trigger the callbacks.
g_system->getTimerManager()->installTimerProc(timerCallback, 1000000 / _timerFrequency, this, "MusicDriver_Got_NULL");
_isOpen = true;
return 0;
}
void MusicDriver_Got_NULL::close() {
if (!_isOpen)
return;
g_system->getTimerManager()->removeTimerProc(timerCallback);
_isOpen = false;
}
void MusicDriver_Got_NULL::setTimerFrequency(uint8 timerFrequency) {
if (timerFrequency == _timerFrequency)
return;
MusicDriver_Got::setTimerFrequency(timerFrequency);
// Update the timer frequency.
g_system->getTimerManager()->removeTimerProc(timerCallback);
g_system->getTimerManager()->installTimerProc(timerCallback, 1000000 / _timerFrequency, this, "MusicDriver_Got_NULL");
}
void MusicDriver_Got_NULL::timerCallback(void *data) {
MusicDriver_Got_NULL *driver = (MusicDriver_Got_NULL *)data;
driver->onTimer();
}
} // namespace Got

77
engines/got/musicdriver.h Normal file
View File

@@ -0,0 +1,77 @@
/* 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 GOT_MUSICDRIVER_H
#define GOT_MUSICDRIVER_H
#include "common/timer.h"
namespace Got {
class MusicDriver_Got {
public:
MusicDriver_Got(uint8 timerFrequency);
virtual ~MusicDriver_Got() { };
virtual int open() = 0;
bool isOpen() const;
virtual void close() = 0;
virtual void syncSoundSettings() = 0;
virtual void send(uint16 b) = 0;
virtual void stopAllNotes() = 0;
virtual void setTimerFrequency(uint8 timerFrequency);
void onTimer();
void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
protected:
// True if the driver has been successfully opened.
bool _isOpen;
// The number of timer callbacks per second.
int _timerFrequency;
// External timer callback
void *_timer_param;
Common::TimerManager::TimerProc _timer_proc;
};
class MusicDriver_Got_NULL : public MusicDriver_Got {
public:
MusicDriver_Got_NULL(uint8 timerFrequency) : MusicDriver_Got(timerFrequency) { };
~MusicDriver_Got_NULL() { };
int open() override;
void close() override;
void syncSoundSettings() override { };
void send(uint16 b) override { };
void stopAllNotes() override { };
void setTimerFrequency(uint8 timerFrequency) override;
static void timerCallback(void *data);
};
} // namespace Got
#endif

View File

@@ -0,0 +1,289 @@
/* 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 "got/musicdriver_adlib.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "audio/mididrv.h"
namespace Got {
MusicDriver_Got_AdLib::MusicDriver_Got_AdLib(uint8 timerFrequency) : MusicDriver_Got(timerFrequency),
_opl(nullptr),
_userMusicVolume(256),
_userMute(false) {
Common::fill(_channelOp0LevelRegisterValues, _channelOp0LevelRegisterValues + ARRAYSIZE(_channelOp0LevelRegisterValues), 0);
Common::fill(_channelOp1LevelRegisterValues, _channelOp1LevelRegisterValues + ARRAYSIZE(_channelOp1LevelRegisterValues), 0);
Common::fill(_channelBxRegisterValues, _channelBxRegisterValues + ARRAYSIZE(_channelBxRegisterValues), 0);
Common::fill(_channelConnectionValues, _channelConnectionValues + ARRAYSIZE(_channelConnectionValues), 0);
}
MusicDriver_Got_AdLib::~MusicDriver_Got_AdLib() {
close();
}
int MusicDriver_Got_AdLib::open() {
if (_isOpen)
return MidiDriver::MERR_ALREADY_OPEN;
int8 detectResult = OPL::Config::detect(OPL::Config::kOpl2);
if (detectResult == -1)
return MidiDriver::MERR_DEVICE_NOT_AVAILABLE;
// Create the emulator / hardware interface.
_opl = OPL::Config::create(OPL::Config::kOpl2);
if (_opl == nullptr)
return MidiDriver::MERR_CANNOT_CONNECT;
// Initialize emulator / hardware interface.
if (!_opl->init())
return MidiDriver::MERR_CANNOT_CONNECT;
_isOpen = true;
// Set default OPL register values.
initOpl();
// Start the emulator / hardware interface. This will also start the timer
// callbacks.
_opl->start(new Common::Functor0Mem<void, MusicDriver_Got_AdLib>(this, &MusicDriver_Got_AdLib::onTimer), _timerFrequency);
return 0;
}
void MusicDriver_Got_AdLib::close() {
if (!_isOpen)
return;
_isOpen = false;
stopAllNotes();
if (_opl) {
_opl->stop();
delete _opl;
_opl = nullptr;
}
}
void MusicDriver_Got_AdLib::syncSoundSettings() {
// Get user volume settings.
_userMusicVolume = MIN(256, ConfMan.getInt("music_volume"));
_userMute = ConfMan.getBool("mute") || ConfMan.getBool("music_mute");
// Apply the user volume.
recalculateVolumes();
}
void MusicDriver_Got_AdLib::send(uint16 b) {
uint8 oplRegister = b >> 8;
uint8 value = b & 0xFF;
if (oplRegister >= OPL_REGISTER_BASE_LEVEL && oplRegister < OPL_REGISTER_BASE_LEVEL + 0x20) {
// Write to a level register.
// Determine the channel and operator from the register number.
uint8 regOffset = oplRegister - OPL_REGISTER_BASE_LEVEL;
uint8 oplChannel = ((regOffset / 8) * 3) + ((regOffset % 8) % 3);
uint8 oplOperator = (regOffset % 8) / 3;
assert(oplChannel < OPL2_NUM_CHANNELS);
assert(oplOperator < 2);
// Store the new register value.
if (oplOperator == 0) {
_channelOp0LevelRegisterValues[oplChannel] = value;
} else {
_channelOp1LevelRegisterValues[oplChannel] = value;
}
// Apply user volume settings to the level.
uint8 scaledLevel = calculateVolume(oplChannel, oplOperator);
// Add the KSL bits to the new level value.
value = (value & 0xC0) | scaledLevel;
} else if ((oplRegister & 0xF0) == OPL_REGISTER_BASE_FNUMHIGH_BLOCK_KEYON) {
// Write to an F-num high / block / key on register.
uint8 oplChannel = oplRegister & 0x0F;
assert(oplChannel < OPL2_NUM_CHANNELS);
// Store the value, but clear the key on bit.
_channelBxRegisterValues[oplChannel] = value & 0x1F;
} else if ((oplRegister & 0xF0) == OPL_REGISTER_BASE_CONNECTION_FEEDBACK_PANNING) {
// Write to a connection register.
uint8 oplChannel = oplRegister & 0x0F;
assert(oplChannel < OPL2_NUM_CHANNELS);
// Store the connection bit.
_channelConnectionValues[oplChannel] = value & 0x01;
}
// Write the new register value to the OPL chip.
writeRegister(oplRegister, value);
}
void MusicDriver_Got_AdLib::stopAllNotes() {
// Clear the key on bit on all OPL channels.
for (int i = 0; i < OPL2_NUM_CHANNELS; i++) {
writeRegister(0xB0 | i, _channelBxRegisterValues[i]);
}
}
void MusicDriver_Got_AdLib::initOpl() {
// Clear test flags and enable waveform select.
writeRegister(0x01, 0x20);
// Clear, stop and mask the timers and reset the interrupt.
writeRegister(0x02, 0);
writeRegister(0x03, 0);
writeRegister(0x04, 0x60);
writeRegister(0x04, 0x80);
// Set note select mode 0 and disable CSM mode.
writeRegister(0x08, 0);
// Clear operator registers.
for (int i = 0; i < 5; i++) {
uint8 baseReg = 0;
switch (i) {
case 0:
baseReg = OPL_REGISTER_BASE_FREQMULT_MISC;
break;
case 1:
baseReg = OPL_REGISTER_BASE_LEVEL;
break;
case 2:
baseReg = OPL_REGISTER_BASE_DECAY_ATTACK;
break;
case 3:
baseReg = OPL_REGISTER_BASE_RELEASE_SUSTAIN;
break;
case 4:
baseReg = OPL_REGISTER_BASE_WAVEFORMSELECT;
break;
}
for (int j = 0; j < OPL2_NUM_CHANNELS; j++) {
writeRegister(baseReg + determineOperatorRegisterOffset(j, 0), 0);
writeRegister(baseReg + determineOperatorRegisterOffset(j, 1), 0);
}
}
// Clear channel registers.
for (int i = 0; i < 3; i++) {
uint8 baseReg = 0;
switch (i) {
case 0:
baseReg = OPL_REGISTER_BASE_FNUMLOW;
break;
case 1:
baseReg = OPL_REGISTER_BASE_FNUMHIGH_BLOCK_KEYON;
break;
case 2:
baseReg = OPL_REGISTER_BASE_CONNECTION_FEEDBACK_PANNING;
break;
}
for (int j = 0; j < OPL2_NUM_CHANNELS; j++) {
writeRegister(baseReg + j, 0);
}
}
// Disable rhythm mode and set modulation and vibrato depth to low.
writeRegister(0xBD, 0);
}
void MusicDriver_Got_AdLib::recalculateVolumes() {
// Determine the value for all level registers and write them out.
for (int i = 0; i < OPL2_NUM_CHANNELS; i++) {
uint8 oplRegister = OPL_REGISTER_BASE_LEVEL + determineOperatorRegisterOffset(i, 0);
uint8 value = (_channelOp0LevelRegisterValues[i] & 0xC0) | calculateVolume(i, 0);
writeRegister(oplRegister, value);
oplRegister = OPL_REGISTER_BASE_LEVEL + determineOperatorRegisterOffset(i, 1);
value = (_channelOp1LevelRegisterValues[i] & 0xC0) | calculateVolume(i, 1);
writeRegister(oplRegister, value);
}
}
uint8 MusicDriver_Got_AdLib::calculateVolume(uint8 channel, uint8 operatorNum) {
// Get the last written level for this operator.
uint8 operatorDefVolume = (operatorNum == 0 ? _channelOp0LevelRegisterValues[channel] : _channelOp1LevelRegisterValues[channel]) & 0x3F;
// Determine if volume settings should be applied to this operator.
if (!isVolumeApplicableToOperator(channel, operatorNum))
// No need to apply volume settings; just use the level as written.
return operatorDefVolume;
uint8 invertedVolume = 0x3F - operatorDefVolume;
// Scale by user volume.
if (_userMute) {
invertedVolume = 0;
} else {
invertedVolume = (invertedVolume * _userMusicVolume) >> 8;
}
uint8 scaledVolume = 0x3F - invertedVolume;
return scaledVolume;
}
bool MusicDriver_Got_AdLib::isVolumeApplicableToOperator(uint8 channel, uint8 operatorNum) {
// 2 operator instruments have 2 different operator connections:
// additive (0x01) or FM (0x00) synthesis. Carrier operators in FM
// synthesis and both operators in additive synthesis need to have
// volume settings applied; modulator operators just use the level
// as written. In FM synthesis connection, operator 1 is a carrier.
return _channelConnectionValues[channel] == 0x01 || operatorNum == 1;
}
uint16 MusicDriver_Got_AdLib::determineOperatorRegisterOffset(uint8 oplChannel, uint8 operatorNum) {
// 2 operator register offset for each channel and operator:
//
// Channel | 0 | 1 | 2 | 0 | 1 | 2 | 3 | 4 | 5 | 3 | 4 | 5 | 6 | 7 | 8 | 6 | 7 | 8 |
// Operator | 0 | 1 | 0 | 1 | 0 | 1 |
// Register | 0 | 1 | 2 | 3 | 4 | 5 | 8 | 9 | A | B | C | D |10 |11 |12 |13 |14 |15 |
return (oplChannel / 3 * 8) + (oplChannel % 3) + (operatorNum * 3);
}
void MusicDriver_Got_AdLib::writeRegister(uint8 oplRegister, uint8 value) {
//debug("Writing register %X %X", oplRegister, value);
_opl->writeReg(oplRegister, value);
}
void MusicDriver_Got_AdLib::setTimerFrequency(uint8 timerFrequency) {
if (timerFrequency == _timerFrequency)
return;
MusicDriver_Got::setTimerFrequency(timerFrequency);
if (isOpen()) {
// Update OPL timer frequency.
_opl->stop();
_opl->start(new Common::Functor0Mem<void, MusicDriver_Got_AdLib>(this, &MusicDriver_Got_AdLib::onTimer), _timerFrequency);
}
}
} // namespace Got

View File

@@ -0,0 +1,120 @@
/* 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 GOT_MUSICDRIVER_ADLIB_H
#define GOT_MUSICDRIVER_ADLIB_H
#include "got/musicdriver.h"
#include "common/scummsys.h"
#include "common/timer.h"
#include "audio/fmopl.h"
namespace Got {
class MusicDriver_Got_AdLib : public MusicDriver_Got {
public:
/**
* The number of available channels on the OPL2 chip.
*/
static const uint8 OPL2_NUM_CHANNELS = 9;
/**
* OPL operator base registers.
*/
static const uint8 OPL_REGISTER_BASE_FREQMULT_MISC = 0x20;
static const uint8 OPL_REGISTER_BASE_LEVEL = 0x40;
static const uint8 OPL_REGISTER_BASE_DECAY_ATTACK = 0x60;
static const uint8 OPL_REGISTER_BASE_RELEASE_SUSTAIN = 0x80;
static const uint8 OPL_REGISTER_BASE_WAVEFORMSELECT = 0xE0;
/**
* OPL channel base registers.
*/
static const uint8 OPL_REGISTER_BASE_FNUMLOW = 0xA0;
static const uint8 OPL_REGISTER_BASE_FNUMHIGH_BLOCK_KEYON = 0xB0;
static const uint8 OPL_REGISTER_BASE_CONNECTION_FEEDBACK_PANNING = 0xC0;
MusicDriver_Got_AdLib(uint8 timerFrequency);
~MusicDriver_Got_AdLib();
int open() override;
void close() override;
void syncSoundSettings() override;
void send(uint16 b) override;
void stopAllNotes() override;
void setTimerFrequency(uint8 timerFrequency) override;
protected:
/**
* Initializes the OPL registers to their default values.
*/
void initOpl();
void recalculateVolumes();
uint8 calculateVolume(uint8 channel, uint8 operatorNum);
/**
* Determines if volume settings should be applied to the operator level.
* This depends on the type of the operator (carrier or modulator), which
* depends on the type of connection specified on the channel.
*
* @param oplChannel The OPL channel
* @param operatorNum The number of the operator (0-1)
* @return True if volume should be applied, false otherwise
*/
bool isVolumeApplicableToOperator(uint8 oplChannel, uint8 operatorNum);
/**
* Determines the offset from a base register for the specified operator of
* the specified OPL channel.
* Add the offset to the base register to get the correct register for this
* operator and channel.
*
* @param oplChannel The OPL channel for which to determine the offset.
* @param operatorNum The operator for which to determine the offset (0-1).
* @return The offset to the base register for this operator.
*/
uint16 determineOperatorRegisterOffset(uint8 oplChannel, uint8 operatorNum);
void writeRegister(uint8 oplRegister, uint8 value);
// The OPL emulator / hardware interface.
OPL::OPL *_opl;
// Last written value to the operator 0 level register for each channel.
uint8 _channelOp0LevelRegisterValues[OPL2_NUM_CHANNELS];
// Last written value to the operator 1 level register for each channel.
uint8 _channelOp1LevelRegisterValues[OPL2_NUM_CHANNELS];
// Last written value to the F-num high / block / key on register for each
// channel, with the key on bit cleared.
uint8 _channelBxRegisterValues[OPL2_NUM_CHANNELS];
// Last written value of the connection bit for each channel.
uint8 _channelConnectionValues[OPL2_NUM_CHANNELS];
// User volume settings.
uint16 _userMusicVolume;
bool _userMute;
};
} // namespace Got
#endif

195
engines/got/musicparser.cpp Normal file
View File

@@ -0,0 +1,195 @@
/* 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 "got/musicparser.h"
#include "common/endian.h"
#include "common/textconsole.h"
namespace Got {
MusicParser_Got::MusicParser_Got() :
_pause(false),
_abortParse(false),
_currentDelta(0),
_driver(nullptr),
_track(nullptr),
_trackLength(0),
_playPos(nullptr),
_loopStart(-1) { }
MusicParser_Got::~MusicParser_Got() {
stopPlaying();
}
void MusicParser_Got::sendToDriver(uint16 b) {
if (_driver == nullptr)
return;
_driver->send(b);
}
void MusicParser_Got::sendToDriver(byte reg, byte value) {
// OPL register and value are sent as a uint16 to the driver.
sendToDriver((reg << 8) | value);
}
void MusicParser_Got::allNotesOff() {
if (_driver == nullptr)
return;
_driver->stopAllNotes();
}
void MusicParser_Got::resetTracking() {
_playPos = nullptr;
}
bool MusicParser_Got::startPlaying() {
if (_track == nullptr || _pause)
return false;
if (_playPos == nullptr) {
_playPos = _track;
}
return true;
}
void MusicParser_Got::pausePlaying() {
if (isPlaying() && !_pause) {
_pause = true;
allNotesOff();
}
}
void MusicParser_Got::resumePlaying() {
_pause = false;
}
void MusicParser_Got::stopPlaying() {
if (isPlaying())
allNotesOff();
resetTracking();
_pause = false;
}
bool MusicParser_Got::isPlaying() {
return _playPos != nullptr;
}
void MusicParser_Got::setMusicDriver(MusicDriver_Got *driver) {
_driver = driver;
}
bool MusicParser_Got::loadMusic(byte* data, uint32 size) {
assert(size >= 5);
// Data starts with a word defining the loop point.
uint16 loopHeader = READ_LE_UINT16(data);
data += 2;
// Rest of the data is music events.
_track = data;
_trackLength = size - 2;
if (loopHeader == 0) {
// No loop point defined.
_loopStart = -1;
} else {
// Loop point is defined as the number of words from the start of the
// data (including the header).
_loopStart = (loopHeader - 1) * 2;
if ((uint32)_loopStart >= _trackLength) {
warning("MusicParser_Got::loadMusic - Music data has loop start point after track end");
_loopStart = -1;
}
}
return true;
}
void MusicParser_Got::unloadMusic() {
if (_track == nullptr)
// No music data loaded
return;
stopPlaying();
_abortParse = true;
_track = nullptr;
}
void MusicParser_Got::onTimer() {
if (_playPos == nullptr || !_driver || _pause)
return;
if (_currentDelta > 0) {
_currentDelta--;
if (_currentDelta > 0)
// More ticks to go to the next event.
return;
}
_abortParse = false;
while (!_abortParse && isPlaying() && _currentDelta == 0) {
assert((_playPos + 3) < (_track + _trackLength));
// An event consists of a delta, followed by an OPL register / value pair.
// A delta consists of 1 or 2 bytes. Bit 7 in the first byte indicates
// if a second byte is used.
uint16 newDelta = *_playPos++;
if ((newDelta & 0x80) > 0) {
assert((_playPos + 3) < (_track + _trackLength));
newDelta &= 0x7F;
newDelta <<= 8;
newDelta |= *_playPos++;
}
// The delta is the number of ticks from this event to the next event,
// not the number of ticks preceding this event.
_currentDelta = newDelta;
// Next, read the OPL register / value pair.
byte oplRegister = *_playPos++;
byte oplRegValue = *_playPos++;
if (oplRegister == 0 && oplRegValue == 0) {
// End of track is indicated by an event with OPL register and value 0.
if (_loopStart >= 0) {
// Continue playback at the loop point.
_playPos = _track + _loopStart;
}
else {
stopPlaying();
}
}
else {
// Write the specified OPL register value.
sendToDriver(oplRegister, oplRegValue);
}
}
}
void MusicParser_Got::timerCallback(void *data) {
((MusicParser_Got *)data)->onTimer();
}
} // namespace Got

77
engines/got/musicparser.h Normal file
View File

@@ -0,0 +1,77 @@
/* 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 GOT_MUSICPARSER_H
#define GOT_MUSICPARSER_H
#include "got/musicdriver_adlib.h"
#include "common/scummsys.h"
namespace Got {
class MusicParser_Got {
public:
MusicParser_Got();
~MusicParser_Got();
bool startPlaying();
void pausePlaying();
void resumePlaying();
void stopPlaying();
bool isPlaying();
void setMusicDriver(MusicDriver_Got *driver);
bool loadMusic(byte *data, uint32 size);
void unloadMusic();
void onTimer();
static void timerCallback(void *data);
protected:
void allNotesOff();
void sendToDriver(uint16 b);
void sendToDriver(byte reg, byte value);
void resetTracking();
bool _pause;
bool _abortParse;
// Number of ticks to the next event to process.
uint16 _currentDelta;
MusicDriver_Got *_driver;
// Points to start of current track data, or nullptr if no track is loaded.
byte *_track;
// The length of the track data.
uint32 _trackLength;
// The current play position in the track data, or nullptr if the parser is
// not playing.
byte *_playPos;
// The offset from the start of _track where playback should restart if the
// track has reached the end. -1 if there is no (valid) loop point defined.
int32 _loopStart;
};
} // namespace Got
#endif

379
engines/got/sound.cpp Normal file
View File

@@ -0,0 +1,379 @@
/* 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 "got/sound.h"
#include "got/got.h"
#include "got/musicdriver_adlib.h"
#include "got/utils/file.h"
#include "common/config-manager.h"
#include "common/memstream.h"
#include "audio/mididrv.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/voc.h"
namespace Got {
static const byte SOUND_PRIORITY[] = {1, 2, 3, 3, 3, 1, 4, 4, 4, 5, 4, 3, 1, 2, 2, 5, 1, 3, 1};
static const char *MUSIC_MENU_DATA_FILENAME = "GOT.AUD";
Sound::Sound() {
for (int i = 0; i < 3; i++)
_bossSounds[i] = nullptr;
}
Sound::~Sound() {
delete[] _soundData;
for (int i = 0; i < ARRAYSIZE(_bossSounds); i++) {
delete[] _bossSounds[i];
}
if (_musicParser != nullptr) {
musicStop();
}
if (_musicDriver != nullptr) {
_musicDriver->setTimerCallback(nullptr, nullptr);
_musicDriver->close();
}
delete _musicParser;
delete _musicDriver;
delete[] _musicData;
}
void Sound::load() {
File f("DIGSOUND");
// Load index
for (int i = 0; i < 16; ++i)
_digiSounds[i].load(&f);
// Allocate memory and load sound data
_soundData = new byte[f.size() - 16 * 8];
f.read(_soundData, f.size() - 16 * 8);
// Initialize music.
// Check the type of music device that the user has configured.
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB);
MusicType deviceType = MidiDriver::getMusicType(dev);
// Initialize the appropriate driver.
switch (deviceType) {
case MT_ADLIB:
_musicDriver = new MusicDriver_Got_AdLib(MUSIC_TIMER_FREQUENCY_GAME);
break;
default:
// No support for music other than AdLib.
_musicDriver = new MusicDriver_Got_NULL(MUSIC_TIMER_FREQUENCY_GAME);
break;
}
// Initialize the parser.
_musicParser = new MusicParser_Got();
// Open the driver.
int returnCode = _musicDriver->open();
if (returnCode != 0) {
warning("Sound::load - Failed to open music driver - error code %d.", returnCode);
return;
}
// Apply user volume settings.
syncSoundSettings();
// Connect the driver and the parser.
_musicParser->setMusicDriver(_musicDriver);
_musicDriver->setTimerCallback(_musicParser, &_musicParser->timerCallback);
}
void Sound::setupBoss(const int num) {
if (_currentBossLoaded == num)
// Boss sounds are already loaded
return;
if (_currentBossLoaded) {
// Boss sounds have already been loaded. Delete them to avoid memory leak
for (int i = 0; i < 3; i++)
delete(_bossSounds[i]);
}
// Information concerning boss sounds is stored in _digiSounds 16 to 18, but the data is stored in _bossSounds
for (int i = 0; i < 3; ++i) {
Common::String resourceName = Common::String::format("BOSSV%d%d", num, i + 1);
File f(resourceName);
const int size = f.size();
_bossSounds[i] = new byte[size];
_digiSounds[16 + i]._length = size;
_digiSounds[16 + i]._offset = 0;
f.read(_bossSounds[i], size);
f.close();
}
_currentBossLoaded = num;
}
void Sound::playSound(const int index, const bool override) {
if (index >= NUM_SOUNDS)
return;
byte newPriority = SOUND_PRIORITY[index];
// If a sound is playing, stop it unless there is a priority override
if (soundPlaying()) {
if (!override && _currentPriority < newPriority)
return;
g_engine->_mixer->stopHandle(_soundHandle);
}
_currentPriority = newPriority;
Common::MemoryReadStream *stream;
if (index >= 16) {
// Boss sounds are not stored in the normal sound data, it's in 3 buffers in _bossSounds.
stream = new Common::MemoryReadStream(_bossSounds[index - 16], _digiSounds[index]._length);
} else {
// Normal digital sound
stream = new Common::MemoryReadStream(_soundData + _digiSounds[index]._offset, _digiSounds[index]._length);
}
// Play the new sound
Audio::AudioStream *audioStream = Audio::makeVOCStream(stream, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream);
}
void Sound::playSound(const Gfx::GraphicChunk &src) {
if (soundPlaying())
g_engine->_mixer->stopHandle(_soundHandle);
// Play the new sound
Common::MemoryReadStream *stream = new Common::MemoryReadStream(
src._data, src._uncompressedSize);
Audio::AudioStream *audioStream = Audio::makeVOCStream(stream, Audio::FLAG_UNSIGNED,
DisposeAfterUse::YES);
g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream);
}
bool Sound::soundPlaying() const {
return g_engine->_mixer->isSoundHandleActive(_soundHandle);
}
void Sound::musicPlay(const char *name, bool override) {
if (_currentMusic == nullptr || strcmp(name, _currentMusic) || override) {
_musicParser->stopPlaying();
_musicParser->unloadMusic();
delete[] _musicData;
_currentMusic = name;
File file;
if (!strcmp(name, "MENU")) {
// Title menu music is embedded in the executable.
// It has been extracted and included with ScummVM.
if (!file.exists(MUSIC_MENU_DATA_FILENAME)) {
warning("Could not find %s", MUSIC_MENU_DATA_FILENAME);
return;
}
file.open(MUSIC_MENU_DATA_FILENAME);
// Title music uses an alternate timer frequency.
_musicDriver->setTimerFrequency(MUSIC_TIMER_FREQUENCY_TITLE);
} else {
file.open(name);
_musicDriver->setTimerFrequency(MUSIC_TIMER_FREQUENCY_GAME);
}
// Copy music data to local buffer and load it into the parser.
_musicData = new byte[file.size()];
file.read(_musicData, file.size());
if (!_musicParser->loadMusic(_musicData, file.size())) {
warning("Could not load music track %s", name);
return;
}
//debug("Playing music track %s", name);
_musicParser->startPlaying();
}
}
void Sound::musicPause() {
_musicParser->pausePlaying();
}
void Sound::musicResume() {
_musicParser->resumePlaying();
}
void Sound::musicStop() {
_musicParser->stopPlaying();
_currentMusic = nullptr;
}
bool Sound::musicIsOn() const {
return _musicParser->isPlaying();
}
const char *Sound::getMusicName(const int num) const {
const char *name = nullptr;
switch (_G(area)) {
case 1:
switch (num) {
case 0:
name = "SONG1";
break;
case 1:
name = "SONG2";
break;
case 2:
name = "SONG3";
break;
case 3:
name = "SONG4";
break;
case 4:
name = "WINSONG";
break;
case 5:
name = "BOSSSONG";
break;
default:
break;
}
break;
case 2:
switch (num) {
case 0:
name = "SONG21";
break;
case 1:
name = "SONG22";
break;
case 2:
name = "SONG23";
break;
case 3:
name = "SONG24";
break;
case 4:
name = "SONG35";
break;
case 5:
name = "SONG25";
break;
case 6:
name = "WINSONG";
break;
case 7:
name = "BOSSSONG";
break;
default:
break;
}
break;
case 3:
switch (num) {
case 0:
name = "SONG31";
break;
case 1:
name = "SONG32";
break;
case 2:
name = "SONG33";
break;
case 3:
name = "SONG34";
break;
case 4:
name = "SONG35";
break;
case 5:
name = "SONG36";
break;
case 6:
name = "WINSONG";
break;
case 7:
name = "BOSSSONG";
break;
default:
break;
}
break;
default:
break;
}
if (!name)
error("Invalid music");
return name;
}
void Sound::syncSoundSettings() {
g_engine->_mixer->muteSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getBool("sfx_mute") || ConfMan.getBool("mute"));
if (_musicDriver)
_musicDriver->syncSoundSettings();
}
void playSound(const int index, const bool override) {
_G(sound).playSound(index, override);
}
void playSound(const Gfx::GraphicChunk &src) {
_G(sound).playSound(src);
}
bool soundPlaying() {
return _G(sound).soundPlaying();
}
void musicPlay(const int num, const bool override) {
_G(sound).musicPlay(num, override);
}
void musicPlay(const char *name, const bool override) {
_G(sound).musicPlay(name, override);
}
void musicPause() {
_G(sound).musicPause();
}
void musicResume() {
_G(sound).musicResume();
}
void setupBoss(int num) {
_G(sound).setupBoss(num);
}
} // namespace Got

111
engines/got/sound.h Normal file
View File

@@ -0,0 +1,111 @@
/* 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 GOT_SOUND_H
#define GOT_SOUND_H
#include "got/musicdriver.h"
#include "got/musicparser.h"
#include "got/data/defines.h"
#include "got/gfx/gfx_chunks.h"
#include "audio/mixer.h"
namespace Got {
enum {
OW,
GULP,
SWISH,
YAH,
ELECTRIC,
THUNDER,
DOOR,
FALL,
ANGEL,
WOOP,
DEAD,
BRAAPP,
WIND,
PUNCH1,
CLANG,
EXPLODE,
BOSS11,
BOSS12,
BOSS13
};
#define NUM_SOUNDS 19
class Sound {
private:
static const uint8 MUSIC_TIMER_FREQUENCY_GAME = 120;
static const uint8 MUSIC_TIMER_FREQUENCY_TITLE = 140;
byte *_soundData = nullptr;
byte *_bossSounds[3];
Header _digiSounds[NUM_SOUNDS];
Audio::SoundHandle _soundHandle;
byte _currentPriority = 0;
int8 _currentBossLoaded = 0;
const char *_currentMusic = nullptr;
byte *_musicData = nullptr;
MusicDriver_Got *_musicDriver = nullptr;
MusicParser_Got *_musicParser = nullptr;
const char *getMusicName(int num) const;
public:
Sound();
~Sound();
void load();
void setupBoss(int num);
void playSound(int index, bool override);
void playSound(const Gfx::GraphicChunk &src);
bool soundPlaying() const;
void musicPlay(const int num, const bool override) {
musicPlay(getMusicName(num), override);
}
void musicPlay(const char *name, bool override);
void musicPause();
void musicResume();
void musicStop();
bool musicIsOn() const;
void syncSoundSettings();
};
extern void playSound(int index, bool override);
extern void playSound(const Gfx::GraphicChunk &src);
extern bool soundPlaying();
extern void musicPlay(int num, bool override);
extern void musicPlay(const char *name, bool override);
extern void musicPause();
extern void musicResume();
extern void setupBoss(int num);
} // namespace Got
#endif

View File

@@ -0,0 +1,78 @@
/* 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 "got/utils/compression.h"
#include "common/algorithm.h"
#include "common/endian.h"
namespace Got {
void decompressLzss(const byte *src, byte *dest, const size_t destSize) {
byte *endP = dest + destSize;
for (;;) {
byte v = *src++;
for (int bits = 8; bits > 0; --bits) {
if (endP == dest)
return;
const bool bit = (v & 1) != 0;
v >>= 1;
if (bit) {
*dest++ = *src++;
} else {
uint16 offset = READ_LE_UINT16(src);
src += 2;
const int count = (offset >> 12) + 2;
offset &= 0xfff;
Common::copy(dest - offset, dest - offset + count, dest);
dest += count;
}
}
}
}
void decompressRle(const byte *src, byte *dest, const size_t destSize) {
byte *endP = dest + destSize;
for (;;) {
byte val = *src++;
if ((val & 0x80) != 0) {
const byte rep = *src++;
val &= 0x7f;
Common::fill(dest, dest + val, rep);
dest += val;
} else if (val > 0) {
Common::copy(src, src + val, dest);
src += val;
dest += val;
} else {
break;
}
}
assert(dest == endP);
}
} // namespace Got

View File

@@ -0,0 +1,41 @@
/* 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 GOT_UTILS_COMPRESSION_H
#define GOT_UTILS_COMPRESSION_H
#include "common/scummsys.h"
namespace Got {
/**
* LZSS decompressor
*/
void decompressLzss(const byte *src, byte *dest, size_t destSize);
/**
* RLE decoding
*/
void decompressRle(const byte *src, byte *dest, size_t destSize);
} // namespace Got
#endif

132
engines/got/utils/file.cpp Normal file
View File

@@ -0,0 +1,132 @@
/* 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 "common/file.h"
#include "got/utils/file.h"
#include "got/vars.h"
namespace Got {
bool File::open(const Common::Path &filename) {
if (!Common::File::open(filename))
error("Could not open - %s", filename.baseName().c_str());
return true;
}
bool loadActor(int /*file*/, int num) {
Common::String fname = Common::String::format("ACTOR%d", num);
if (resourceRead(fname, _G(tmpBuff), true) < 0)
return false;
return true;
}
bool loadSpeech(int index) {
char tmps[5];
Common::String fname = Common::String::format("SPEAK%d", _G(area));
char *sp = new char[30000];
if (resourceRead(fname, sp) < 0) {
delete[] sp;
return false;
}
char *p = sp;
int cnt = 0;
for (;;) {
if (*p == ':') {
p++;
cnt++;
strncpy(tmps, p, 4);
tmps[4] = '\0';
if (atoi(tmps) == index) {
break;
}
}
p++;
cnt++;
}
while (*p != 10)
p++;
p++;
char *pm = p;
cnt = 0;
for (;;) {
if (*p == 13)
*p = 32;
if (*p == ':') {
if ((*(p + 1) == 'E') && (*(p + 2) == 'N') && (*(p + 3) == 'D'))
break;
}
p++;
cnt++;
if (cnt > 5799) {
delete[] sp;
return false;
}
}
if (*(p - 1) == 10)
*(p - 1) = 0;
*p = 0;
Common::copy(pm, pm + cnt, _G(tmpBuff));
_G(tmpBuff)
[cnt] = 0;
delete[] sp;
return true;
}
long resourceRead(const Common::String &name, void *buff, bool failAllowed) {
Common::File f;
if (f.open(Common::Path(name))) {
return f.read(buff, f.size());
}
if (!failAllowed)
error("Could not load - %s", name.c_str());
return -1;
}
void *resourceAllocRead(const Common::String &name) {
Common::File f;
if (f.open(Common::Path(name))) {
byte *result = (byte *)malloc(f.size());
f.read(result, f.size());
return result;
}
return nullptr;
}
} // End of namespace Got

47
engines/got/utils/file.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 GOT_UTILS_FILE_H
#define GOT_UTILS_FILE_H
#include "common/file.h"
namespace Got {
extern bool loadActor(int, int num);
extern void setupFilenames(int level);
extern bool loadSpeech(int index);
extern long resourceRead(const Common::String &name, void *buff, bool failAllowed = false);
extern void *resourceAllocRead(const Common::String &name);
class File : public Common::File {
public:
File() : Common::File() {}
File(const Common::String &filename) : Common::File() {
File::open(Common::Path(filename));
}
bool open(const Common::Path &filename) override;
};
} // namespace Got
#endif

View File

@@ -0,0 +1,147 @@
/* 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 "common/file.h"
#include "common/memstream.h"
#include "got/utils/compression.h"
#include "got/utils/res_archive.h"
namespace Got {
static const char *RES_FILENAME = "gotres.dat";
void resInit() {
ResArchive *a = new ResArchive();
SearchMan.add("Res", a);
}
void ResHeader::load(Common::SeekableReadStream *src) {
char buf[10];
src->read(buf, 9);
buf[9] = '\0';
_name = buf;
_offset = src->readUint32LE();
_size = src->readUint32LE();
_originalSize = src->readUint32LE();
_key = src->readUint16LE();
}
ResArchive::ResArchive() {
Common::File f;
if (!f.open(RES_FILENAME))
error("Could not open %s", RES_FILENAME);
// Read in header data and decrypt it
byte buf[RES_MAX_ENTRIES * RES_HEADER_ENTRY_SIZE];
if (f.read(buf, RES_MAX_ENTRIES * RES_HEADER_ENTRY_SIZE) !=
(RES_MAX_ENTRIES * RES_HEADER_ENTRY_SIZE))
error("Could not read in resource headers");
decrypt(buf, RES_MAX_ENTRIES * RES_HEADER_ENTRY_SIZE, 128);
// Load headers
Common::MemoryReadStream hdrData(buf, RES_MAX_ENTRIES * RES_HEADER_ENTRY_SIZE);
for (int i = 0; i < RES_MAX_ENTRIES; ++i) {
ResHeader hdr;
hdr.load(&hdrData);
if (!(hdr._offset == 0 && hdr._size == 0))
_headers.push_back(hdr);
}
}
void ResArchive::decrypt(byte *buf, size_t len, byte key) const {
for (size_t i = 0; i < len; ++i)
*buf++ ^= key++;
}
int ResArchive::indexOf(const Common::String &name) const {
for (uint i = 0; i < _headers.size(); ++i) {
if (_headers[i]._name.equalsIgnoreCase(name))
return i;
}
return -1;
}
bool ResArchive::hasFile(const Common::Path &path) const {
return indexOf(path.baseName()) != -1;
}
int ResArchive::listMembers(Common::ArchiveMemberList &list) const {
int count = 0;
for (uint i = 0; i < _headers.size(); ++i) {
list.push_back(Common::ArchiveMemberList::value_type(
new Common::GenericArchiveMember(_headers[i]._name, *this)));
++count;
}
return count;
}
const Common::ArchiveMemberPtr ResArchive::getMember(const Common::Path &path) const {
if (!hasFile(path))
return Common::ArchiveMemberPtr();
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
}
Common::SeekableReadStream *ResArchive::createReadStreamForMember(const Common::Path &path) const {
// Get the index of the header entry for this file
const int hdrIndex = indexOf(path.baseName());
if (hdrIndex == -1)
return nullptr;
Common::File f;
if (!f.open(RES_FILENAME))
error("Error reading resource");
// Set up buffers
const ResHeader &hdr = _headers[hdrIndex];
byte *buf = (byte *)malloc(hdr._size);
f.seek(hdr._offset);
if (f.read(buf, hdr._size) != hdr._size)
error("Error reading resource");
// Decrypt if necessary
if (hdr._key != 0) {
byte *temp = buf;
buf = (byte *)malloc(hdr._originalSize);
lzssDecompress(temp, buf);
free(temp);
}
return new Common::MemoryReadStream(buf, hdr._originalSize,
DisposeAfterUse::YES);
}
void ResArchive::lzssDecompress(const byte *src, byte *dest) const {
const uint16 size = READ_LE_UINT16(src);
assert(READ_LE_UINT16(src + 2) == 1);
src += 4;
decompressLzss(src, dest, size);
}
} // namespace Got

View File

@@ -0,0 +1,102 @@
/* 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 GOT_UTILS_RES_ARCHIVE_H
#define GOT_UTILS_RES_ARCHIVE_H
#include "common/archive.h"
#include "common/stream.h"
namespace Got {
struct ResHeader {
Common::String _name;
uint32 _offset = 0;
uint32 _size = 0;
uint32 _originalSize = 0;
int _key = 0;
void load(Common::SeekableReadStream *src);
};
#define RES_MAX_ENTRIES 256 // Max # of elements
#define RES_HEADER_ENTRY_SIZE 23 // Size of a single header entry
class ResArchive : public Common::Archive {
private:
Common::Array<ResHeader> _headers;
/**
* Decrypts a passed buffer
* @param buf Pointer to buffer
* @param len Buffer size
* @param key Starting key to use for decryption
*/
void decrypt(byte *buf, size_t len, byte key) const;
/**
* Decodes a passed buffer
*/
void lzssDecompress(const byte *src, byte *dest) const;
/**
* Returns the index of a header for a given filename
*/
int indexOf(const Common::String &name) const;
public:
/**
* Constructor
*/
ResArchive();
/**
* Check if a member with the given name is present in the Archive.
* Patterns are not allowed, as this is meant to be a quick File::exists()
* replacement.
*/
bool hasFile(const Common::Path &path) const override;
/**
* Add all members of the Archive to list.
* Must only append to list, and not remove elements from it.
*
* @return the number of names added to list
*/
int listMembers(Common::ArchiveMemberList &list) const override;
/**
* Returns a ArchiveMember representation of the given file.
*/
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
/**
* Create a stream bound to a member with the specified name in the
* archive. If no member with this name exists, 0 is returned.
* @return the newly created input stream
*/
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
};
extern void resInit();
} // namespace Got
#endif

119
engines/got/vars.cpp Normal file
View File

@@ -0,0 +1,119 @@
/* 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 "got/vars.h"
#include "common/algorithm.h"
#include "common/config-manager.h"
#include "got/gfx/palette.h"
#include "got/got.h"
#include "got/utils/file.h"
namespace Got {
Vars *g_vars;
Vars::Vars() : _hampic("HAMPIC", 262, false),
_odin("ODINPIC", 262, false),
_objects("OBJECTS", 262, false),
_status("STATUS", -1, false) {
g_vars = this;
}
void Vars::load() {
_bgPics.load();
_font.load();
_gfx.load();
_hampic.load();
_objects.load();
_odin.load();
_sdData.load();
_sound.load();
_status.load();
_highScores.load();
_musicFlag = !ConfMan.getBool("music_mute");
_soundFlag = !ConfMan.getBool("sfx_mute");
if (_currentLevel != 23)
_storyFlag = false;
_setup._musicEnabled = _musicFlag;
_setup._digitalSound = _soundFlag;
_setup._speakerSound = false;
_setup._scrollFlag = true;
_setup._slowMode = _slowMode;
_setup._difficultyLevel = 1;
_tmpBuff = new byte[TMP_SIZE];
Gfx::loadPalette();
}
Vars::~Vars() {
g_vars = nullptr;
delete[] _tmpBuff;
}
void Vars::setArea(int areaNum) {
_area = areaNum;
_setup = Setup();
loadArea();
}
void Vars::loadArea() {
int areaNum = _area;
_setup._areaNum = areaNum;
_sdData.setArea(areaNum);
_bgPics.setArea(areaNum);
switch (areaNum) {
case 1:
_currentLevel = 23;
break;
case 2:
_currentLevel = 51;
break;
case 3:
_currentLevel = 33;
break;
default:
break;
}
}
void Vars::clearKeyFlags() {
Common::fill(_keyFlag, _keyFlag + 100, 0);
}
void Vars::resetEndGameFlags() {
_gameMode = MODE_NORMAL;
_endTile = false;
_bossDead = false;
_gameOver = false;
_bossIntro1 = _bossIntro2 = false;
}
} // namespace Got

214
engines/got/vars.h Normal file
View File

@@ -0,0 +1,214 @@
/* 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 GOT_VARS_H
#define GOT_VARS_H
#include "common/events.h"
#include "common/queue.h"
#include "got/data/defines.h"
#include "got/data/highscores.h"
#include "got/data/level.h"
#include "got/data/sd_data.h"
#include "got/data/setup.h"
#include "got/data/thorinfo.h"
#include "got/game/script.h"
#include "got/gfx/font.h"
#include "got/gfx/gfx_chunks.h"
#include "got/gfx/gfx_pics.h"
#include "got/metaengine.h"
#include "got/sound.h"
#include "graphics/screen.h"
namespace Got {
#define TILE_SIZE 16
#define TILES_X (320 / TILE_SIZE)
#define TILES_Y (192 / TILE_SIZE)
#define TILES_COUNT (TILES_X * TILES_Y)
class Vars;
extern Vars *g_vars;
enum Key {
key_none = KEYBIND_NONE,
key_up = KEYBIND_UP,
key_down = KEYBIND_DOWN,
key_left = KEYBIND_LEFT,
key_right = KEYBIND_RIGHT,
key_fire = KEYBIND_FIRE,
key_magic = KEYBIND_MAGIC,
key_select = KEYBIND_SELECT
};
enum GameMode {
MODE_NORMAL,
MODE_AREA_CHANGE,
MODE_THUNDER,
MODE_THOR_DIES,
MODE_ADD_SCORE,
MODE_LIGHTNING,
MODE_PAUSE,
MODE_SCORE_INV
};
enum TransitionDir {
DIR_LEFT,
DIR_RIGHT,
DIR_UP,
DIR_DOWN,
DIR_PHASED
};
struct Cheats {
bool _freezeHealth = false;
bool _freezeMagic = false;
bool _freezeJewels = false;
};
class Vars {
public:
Vars();
~Vars();
void load();
void setArea(int areaNum);
void loadArea();
void clearKeyFlags();
void resetEndGameFlags();
Common::String _playerName = "ScummVM";
Gfx::GfxChunks _gfx;
Gfx::BgPics _bgPics;
Gfx::Font _font;
Gfx::Pics _hampic;
Gfx::Pics _objects;
Gfx::Pics _odin;
Gfx::Pics _status;
HighScores _highScores;
SdData _sdData;
Sound _sound;
Scripts _scripts;
GameMode _gameMode = MODE_NORMAL;
TransitionDir _transitionDir = DIR_LEFT;
Cheats _cheats;
Common::Queue<byte> _demoKeys;
bool _useItemFlag = false;
bool _slipFlag = false;
bool _slipping = false;
int _slipCount = 0;
bool _bossIntro1 = false;
bool _bossIntro2 = false;
int8 _pge = 0;
int _exitFlag = 0;
byte _keyFlag[100] = {};
int8 _diag = 0;
bool _diagFlag = false;
bool _slowMode = false;
bool _startup = true;
bool _shotOk = false;
int _thorX1 = 0;
int _thorY1 = 0;
int _thorX2 = 0;
int _thorY2 = 0;
int _thorRealY1 = 0;
int _thorPos = 0;
uint _magicCounter = 0;
byte _objectMap[TILES_COUNT] = {};
byte _objectIndex[TILES_COUNT] = {};
int8 _thorIcon1 = 0;
int8 _thorIcon2 = 0;
int8 _thorIcon3 = 0;
int8 _thorIcon4 = 0;
int8 _levelMusic = 0;
int8 _currentMusic = -1;
int8 _appleDropCounter = 0;
bool _cheat = false;
int8 _area = 1;
Level _scrn;
Setup _setup;
Setup _lastSetup;
byte *_tmpBuff = nullptr;
Actor _actor[MAX_ACTORS] = {}; //current actors
Actor _enemy[MAX_ENEMIES] = {}; //current enemies
Actor _shot[MAX_ENEMIES] = {}; //current shots
int8 _enemyType[MAX_ENEMIES] = {};
int _etype[MAX_ENEMIES] = {};
Actor _magicItem[2] = {};
byte _magicPic[2][1024] = {};
bool _warpScroll = false;
Actor *_thor = nullptr;
Actor *_hammer = nullptr;
Actor _explosion;
Actor _sparkle;
ThorInfo _thorInfo;
bool _bossDead = false;
byte _endGame = 0;
bool _warpFlag = false;
int _rand1 = 0;
int _rand2 = 0;
int _thunderSnakeCounter = 0;
bool _tornadoUsed = false;
bool _shieldOn = false;
bool _appleFlag = false;
int _switchUsed = 0;
bool _musicFlag = false;
bool _soundFlag = false;
bool _cashDoor1Inform = false;
bool _cashDoor2Inform = false;
bool _keyDoorInform = false;
bool _magicMissingInform = false;
bool _cantCarryInform = false;
bool _killGoodGuyInform = false;
bool _bossActive = false;
bool _storyFlag = true;
int8 *_scr = nullptr;
bool _demo = false;
bool _gameOver = false;
bool _endTile = false;
int _currentLevel = 23;
int _newLevel = 0;
int _newLevelTile = 0;
int _currentArea = 0;
bool _thorSpecialFlag = false;
byte _explosionRow = 0;
bool _eyeballs = 0;
};
#define _G(X) (g_vars->_##X)
} // namespace Got
#endif

View File

@@ -0,0 +1,158 @@
/* 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 "got/views/credits.h"
#include "got/vars.h"
namespace Got {
namespace Views {
#ifdef USE_TTS
static const char *creditsText[] = {
"Programming: Ron Davis",
"Graphics: Gary Sirois",
"Level Design: Adam Pedersen",
"Additional Programming: Jason Blochowiak",
"Music: Roy Davis",
"Title Screen Art: Wayne C. Timmerman",
"Additional Level Design: Ron Davis, Doug Howell, Ken Heckbert, Evan Heckbert",
"Play Testing: Ken Heckbert, Doug Howell, Tom King",
"Play Testing: Kelly Rogers, Michael Smith, Rik Pierce"
};
#endif
#define CREDITS_COUNT 9
#define FADE_FRAMES 15
#define DISPLAY_TIME 15
#define CREDIT_TIME (FADE_FRAMES * 2 + DISPLAY_TIME)
bool Credits::msgFocus(const FocusMessage &msg) {
_delayCtr = 0;
_frameCtr = 0;
draw();
const Gfx::Palette63 pal = _G(gfx[41]);
fadeIn(pal);
return true;
}
void Credits::draw() {
GfxSurface s = getSurface();
// Draw scroll background
const Graphics::ManagedSurface &bg = _G(gfx[42]);
s.clear(*(const byte *)bg.getPixels());
s.simpleBlitFrom(bg, Common::Point(0, 24));
const int creditNum = _frameCtr / CREDIT_TIME;
int subNum = _frameCtr % CREDIT_TIME;
if (subNum >= (FADE_FRAMES + DISPLAY_TIME)) {
subNum = (FADE_FRAMES - 1) - (subNum - (FADE_FRAMES + DISPLAY_TIME));
} else if (subNum >= FADE_FRAMES) {
subNum = FADE_FRAMES - 1;
}
if (creditNum < CREDITS_COUNT) {
const int gfxNum1 = 43 + creditNum;
const int gfxNum2 = 67 + creditNum;
const int gfxNum3 = 52 + subNum;
const int gfxNum4 = 76 + subNum;
drawCredit(s, gfxNum1, gfxNum3, 16, 40 + 24);
drawCredit(s, gfxNum2, gfxNum4, 16, 40 + 24);
#ifdef USE_TTS
sayText(creditsText[creditNum]);
#endif
}
s.markAllDirty();
}
void Credits::drawCredit(GfxSurface &s, int gfxNum1, int gfxNum2, int x, int y) {
const Gfx::GraphicChunk &data = _G(gfx[gfxNum1]);
const Gfx::GraphicChunk &lookup = _G(gfx[gfxNum2]);
const byte *lines = data._data;
const byte *lineData = data._data + 2 * data._height;
assert(x >= 0 && (x + data._width) <= 320);
assert(y >= 0 && (y + data._height) <= 200);
for (int yCtr = 0; yCtr < data._height; ++yCtr) {
byte *dest = (byte *)s.getBasePtr(x, y + yCtr);
uint16 lineParts = READ_LE_UINT16(lines);
lines += 2;
if (lineParts == 0)
// Nothing on line, move to next
continue;
for (; lineParts > 0; --lineParts) {
byte count = *lineData++;
if (count & 0x80) {
// Shade a range of pixels using lookup table
count &= 0x7f;
for (int i = 0; i < count; ++i, ++dest)
*dest = lookup._data[*dest];
} else {
dest += count;
}
}
}
}
bool Credits::tick() {
if (++_delayCtr >= 3) {
_delayCtr = 0;
if (_frameCtr == (CREDIT_TIME * CREDITS_COUNT) + 10) {
replaceView("HighScores", true, true);
} else {
#ifdef USE_TTS
// Pause credits progression until TTS is finished
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (_frameCtr % CREDIT_TIME < FADE_FRAMES + DISPLAY_TIME || !ttsMan || !ttsMan->isSpeaking())
#endif
++_frameCtr;
redraw();
}
}
return true;
}
bool Credits::msgAction(const ActionMessage &msg) {
if (msg._action == KEYBIND_ESCAPE) {
fadeOut();
send("TitleBackground", GameMessage("MAIN_MENU"));
return true;
}
return false;
}
} // namespace Views
} // namespace Got

View File

@@ -0,0 +1,50 @@
/* 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 GOT_VIEWS_CREDITS_H
#define GOT_VIEWS_CREDITS_H
#include "got/views/view.h"
namespace Got {
namespace Views {
class Credits : public View {
private:
int _delayCtr = 0;
int _frameCtr = 0;
void drawCredit(GfxSurface &s, int gfxNum1, int gfxNum2, int x, int y);
public:
Credits() : View("Credits") {}
virtual ~Credits() {}
bool msgFocus(const FocusMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
void draw() override;
bool tick() override;
};
} // namespace Views
} // namespace Got
#endif

View File

@@ -0,0 +1,48 @@
/* 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 "got/views/dialogs/ask.h"
#include "got/vars.h"
namespace Got {
namespace Views {
namespace Dialogs {
Ask::Ask() : SelectOption("Ask") {
}
void Ask::show(const Common::String &title, const Common::StringArray &options) {
Ask *view = (Ask *)g_events->findView("Ask");
view->setContent(title, options);
view->addView();
}
void Ask::closed() {
_G(scripts).setAskResponse(0);
}
void Ask::selected() {
_G(scripts).setAskResponse(_selectedItem + 1);
}
} // namespace Dialogs
} // namespace Views
} // namespace Got

View File

@@ -0,0 +1,45 @@
/* 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 GOT_VIEWS_DIALOGS_ASK_H
#define GOT_VIEWS_DIALOGS_ASK_H
#include "got/views/dialogs/select_option.h"
namespace Got {
namespace Views {
namespace Dialogs {
class Ask : public SelectOption {
public:
Ask();
virtual ~Ask() {}
static void show(const Common::String &title, const Common::StringArray &options);
void closed() override;
void selected() override;
};
} // namespace Dialogs
} // namespace Views
} // namespace Got
#endif

View File

@@ -0,0 +1,62 @@
/* 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 "got/views/dialogs/dialog.h"
#include "got/vars.h"
namespace Got {
namespace Views {
namespace Dialogs {
Dialog::Dialog(const Common::String &name) : View(name) {
_bounds.setBorderSize(16);
}
void Dialog::draw() {
// Clear the inner content first
GfxSurface s = getSurface(true);
s.clear(215);
s = getSurface();
assert((s.w % 16) == 0 && (s.h % 16) == 0);
// Draw four corners
s.simpleBlitFrom(_G(bgPics[192]), Common::Point(0, 0));
s.simpleBlitFrom(_G(bgPics[193]), Common::Point(_bounds.width() - 16, 0));
s.simpleBlitFrom(_G(bgPics[194]), Common::Point(0, _bounds.height() - 16));
s.simpleBlitFrom(_G(bgPics[195]), Common::Point(_bounds.width() - 16, _bounds.height() - 16));
// Draw top/bottom horizontal lines
for (int x = 16; x < _bounds.width() - 16; x += 16) {
s.simpleBlitFrom(_G(bgPics[196]), Common::Point(x, 0));
s.simpleBlitFrom(_G(bgPics[197]), Common::Point(x, _bounds.height() - 16));
}
// Draw left/right vertical lines
for (int y = 16; y < _bounds.height() - 16; y += 16) {
s.simpleBlitFrom(_G(bgPics[198]), Common::Point(0, y));
s.simpleBlitFrom(_G(bgPics[199]), Common::Point(_bounds.width() - 16, y));
}
}
} // namespace Dialogs
} // namespace Views
} // namespace Got

View File

@@ -0,0 +1,43 @@
/* 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 GOT_VIEWS_DIALOGS_DIALOG_H
#define GOT_VIEWS_DIALOGS_DIALOG_H
#include "got/views/view.h"
namespace Got {
namespace Views {
namespace Dialogs {
class Dialog : public View {
public:
Dialog(const Common::String &name);
virtual ~Dialog() {}
void draw() override;
};
} // namespace Dialogs
} // namespace Views
} // namespace Got
#endif

View File

@@ -0,0 +1,145 @@
/* 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 "got/views/dialogs/high_scores.h"
#include "got/vars.h"
namespace Got {
namespace Views {
namespace Dialogs {
#define TIMEOUT 500
HighScores::HighScores() : Dialog("HighScores") {
setBounds(Common::Rect(0, 0 + 24, 320, 192 + 24));
}
void HighScores::draw() {
// Draw background outside dialog
GfxSurface s = GfxSurface(*g_events->getScreen(), Common::Rect(0, 0, 320, 240));
for (int col = 0, xp = 0; col < 10; ++col, xp += 32) {
for (int yp = 0; yp < 240; yp += 32)
s.simpleBlitFrom(_G(gfx[26]), Common::Point(xp, yp));
}
// Draw the dialog frame
Dialog::draw();
// Clear the inner content first
s = getSurface(true);
s.clear(215);
// Draw title
Common::String title = "High Scores - Part I";
for (int area = 2; area <= _currentArea; ++area)
title += 'I';
const int titleStart = (s.w - title.size() * 8) / 2;
s.print(Common::Point(titleStart, 4), title, 54);
#ifdef USE_TTS
sayText(title);
#endif
for (int i = 0; i < 7; ++i) {
const HighScore &hs = _G(highScores)._scores[_currentArea - 1][i];
// Draw frames for name and score
s.frameRect(Common::Rect(10, 20 + i * 18, 210, 20 + i * 18 + 16), 206);
s.frameRect(Common::Rect(220, 20 + i * 18, 280, 20 + i * 18 + 16), 206);
// Write out the name and scores
s.print(Common::Point(15, 24 + i * 18), hs._name, 14);
Common::String score = Common::String::format("%d", hs._total);
s.print(Common::Point(275 - (score.size() * 8), 24 + i * 18), score, 14);
#ifdef USE_TTS
sayText(Common::String::format("%s: %d", hs._name, hs._total), Common::TextToSpeechManager::QUEUE);
_previousSaid.clear();
#endif
}
}
bool HighScores::msgFocus(const FocusMessage &msg) {
_currentArea = 1;
_showAll = true;
_timeoutCtr = TIMEOUT;
Gfx::loadPalette();
return true;
}
bool HighScores::msgGame(const GameMessage &msg) {
if (msg._name == "HIGH_SCORES") {
// Finished one of the parts of the game, so just
// set the view to show only scores for that area
replaceView("HighScores", true);
_currentArea = msg._value;
_showAll = false;
draw();
fadeIn();
return true;
}
return false;
}
bool HighScores::msgAction(const ActionMessage &msg) {
if (msg._action == KEYBIND_ESCAPE) {
goToMainMenu();
} else {
goToNextArea();
}
return true;
}
void HighScores::goToMainMenu() {
fadeOut();
send("TitleBackground", GameMessage("MAIN_MENU"));
}
void HighScores::goToNextArea() {
if (_showAll && _currentArea < 3) {
fadeOut();
++_currentArea;
draw();
fadeIn();
_timeoutCtr = TIMEOUT;
} else {
// Done all the areas, so
goToMainMenu();
}
}
bool HighScores::tick() {
Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
if (--_timeoutCtr < 0 && (!ttsMan || !ttsMan->isSpeaking()))
goToNextArea();
return true;
}
} // namespace Dialogs
} // namespace Views
} // namespace Got

View File

@@ -0,0 +1,56 @@
/* 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 GOT_VIEWS_DIALOGS_HIGH_SCORES_H
#define GOT_VIEWS_DIALOGS_HIGH_SCORES_H
#include "got/views/dialogs/dialog.h"
namespace Got {
namespace Views {
namespace Dialogs {
class HighScores : public Dialog {
private:
int _currentArea = 0;
bool _showAll = false;
int _timeoutCtr = 0;
void goToMainMenu();
void goToNextArea();
public:
HighScores();
virtual ~HighScores() {
}
void draw() override;
bool msgFocus(const FocusMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
bool tick() override;
};
} // namespace Dialogs
} // namespace Views
} // namespace Got
#endif

View File

@@ -0,0 +1,99 @@
/* 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 "got/views/dialogs/main_menu.h"
#include "got/game/init.h"
#include "got/vars.h"
namespace Got {
namespace Views {
namespace Dialogs {
static const char *OPTIONS[] = {"Play Game", "Load Game", "High Scores", "Credits", "Demo", "Quit", nullptr};
static const char *OPTIONS_NO_DEMO[] = {"Play Game", "Load Game", "High Scores", "Credits", "Quit", nullptr};
MainMenu::MainMenu() : SelectOption("MainMenu", "God of Thunder Menu",
gDebugLevel > 0 ? OPTIONS : OPTIONS_NO_DEMO) {
}
bool MainMenu::msgFocus(const FocusMessage &msg) {
g_vars->resetEndGameFlags();
musicPlay("MENU", false);
return SelectOption::msgFocus(msg);
}
void MainMenu::closed() {
_selectedItem = 4; // Quit game
selected();
}
void MainMenu::selected() {
switch (_selectedItem) {
case 0:
_G(demo) = false;
if (g_events->isDemo()) {
// The shareware release only has part 1
g_vars->setArea(1);
initGame();
replaceView("Story", true, true);
} else {
// Full game. Select the game part
addView("SelectGame");
}
break;
case 1:
if (!g_engine->loadGameDialog())
addView("SelectGame");
break;
case 2:
replaceView("HighScores", true, true);
break;
case 3:
addView("Credits");
break;
case 4:
if (gDebugLevel > 0) {
_G(demo) = true;
initGame();
replaceView("PartTitle", true, true);
} else {
addView("Quit");
}
break;
case 5:
addView("Quit");
break;
default:
break;
}
}
} // namespace Dialogs
} // namespace Views
} // namespace Got

View File

@@ -0,0 +1,45 @@
/* 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 GOT_VIEWS_DIALOGS_MAIN_MENU_H
#define GOT_VIEWS_DIALOGS_MAIN_MENU_H
#include "got/views/dialogs/select_option.h"
namespace Got {
namespace Views {
namespace Dialogs {
class MainMenu : public SelectOption {
public:
MainMenu();
virtual ~MainMenu() {}
bool msgFocus(const FocusMessage &msg) override;
void closed() override;
void selected() override;
};
} // namespace Dialogs
} // namespace Views
} // namespace Got
#endif

View File

@@ -0,0 +1,69 @@
/* 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 "got/views/dialogs/options_menu.h"
#include "got/game/back.h"
#include "got/vars.h"
namespace Got {
namespace Views {
namespace Dialogs {
static const char *OPTIONS[] = {"Sound/Music", "Skill Level", "Save Game", "Load Game", "Die", "Turbo Mode", "Help", "Quit", nullptr};
OptionsMenu::OptionsMenu() : SelectOption("OptionsMenu", "Options Menu", OPTIONS) {
}
void OptionsMenu::selected() {
switch (_selectedItem) {
case 0:
addView("SetSound");
break;
case 1:
addView("SkillLevel");
break;
case 2:
g_engine->saveGameDialog();
break;
case 3:
g_engine->loadGameDialog();
break;
case 4:
g_events->send(GameMessage("THOR_DIES"));
break;
case 5:
addView("SelectSlow");
break;
case 6:
// Help
odinSpeaks(2008, -1);
break;
case 7:
addView("QuitGame");
break;
default:
break;
}
}
} // namespace Dialogs
} // namespace Views
} // namespace Got

View File

@@ -0,0 +1,43 @@
/* 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 GOT_VIEWS_DIALOGS_OPTIONS_MENU_H
#define GOT_VIEWS_DIALOGS_OPTIONS_MENU_H
#include "got/views/dialogs/select_option.h"
namespace Got {
namespace Views {
namespace Dialogs {
class OptionsMenu : public SelectOption {
public:
OptionsMenu();
virtual ~OptionsMenu() {}
void selected() override;
};
} // namespace Dialogs
} // namespace Views
} // namespace Got
#endif

View File

@@ -0,0 +1,51 @@
/* 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 "got/views/dialogs/quit.h"
#include "got/got.h"
namespace Got {
namespace Views {
namespace Dialogs {
Quit::Quit() : SelectOption("Quit", "Quit Game?", YES_NO) {
}
void Quit::selected() {
switch (_selectedItem) {
case 0:
g_engine->quitGame();
break;
case 1:
addView("MainMenu");
break;
default:
break;
}
}
void Quit::closed() {
addView("MainMenu");
}
} // namespace Dialogs
} // namespace Views
} // namespace Got

Some files were not shown because too many files have changed in this diff Show More