aboutsummaryrefslogtreecommitdiff
path: root/engines/gob
diff options
context:
space:
mode:
authorAlyssa Milburn2012-08-28 15:39:00 +0200
committerAlyssa Milburn2012-08-28 15:54:12 +0200
commit31801137b5c6908edd76f357b3f29b07e9e3be84 (patch)
tree33e973717545ae27da6ba4996d0d8fe1bcd437b3 /engines/gob
parent35fd91793b34b72624a89f2a76f45bc8e59020d2 (diff)
parent6ab8db638e4a1d547ee67db067b5d6c3d6c940a4 (diff)
downloadscummvm-rg350-31801137b5c6908edd76f357b3f29b07e9e3be84.tar.gz
scummvm-rg350-31801137b5c6908edd76f357b3f29b07e9e3be84.tar.bz2
scummvm-rg350-31801137b5c6908edd76f357b3f29b07e9e3be84.zip
Merge remote-tracking branch 'origin/master' into tony
Conflicts: common/coroutines.cpp common/coroutines.h devtools/create_project/msbuild.cpp devtools/create_project/visualstudio.cpp
Diffstat (limited to 'engines/gob')
-rw-r--r--engines/gob/anifile.cpp39
-rw-r--r--engines/gob/anifile.h3
-rw-r--r--engines/gob/aniobject.cpp125
-rw-r--r--engines/gob/aniobject.h34
-rw-r--r--engines/gob/backbuffer.cpp100
-rw-r--r--engines/gob/backbuffer.h59
-rw-r--r--engines/gob/cheater.h6
-rw-r--r--engines/gob/cheater_geisha.cpp11
-rw-r--r--engines/gob/cmpfile.cpp14
-rw-r--r--engines/gob/cmpfile.h2
-rw-r--r--engines/gob/decfile.cpp42
-rw-r--r--engines/gob/detection/detection.cpp220
-rw-r--r--engines/gob/detection/tables.h (renamed from engines/gob/detection.cpp)116
-rw-r--r--engines/gob/detection/tables_adi2.h203
-rw-r--r--engines/gob/detection/tables_adi4.h222
-rw-r--r--engines/gob/detection/tables_adibou.h247
-rw-r--r--engines/gob/detection/tables_ajworld.h45
-rw-r--r--engines/gob/detection/tables_bargon.h135
-rw-r--r--engines/gob/detection/tables_dynasty.h146
-rw-r--r--engines/gob/detection/tables_fallback.h564
-rw-r--r--engines/gob/detection/tables_fascin.h267
-rw-r--r--engines/gob/detection/tables_geisha.h132
-rw-r--r--engines/gob/detection/tables_gob1.h716
-rw-r--r--engines/gob/detection/tables_gob2.h641
-rw-r--r--engines/gob/detection/tables_gob3.h564
-rw-r--r--engines/gob/detection/tables_inca2.h249
-rw-r--r--engines/gob/detection/tables_lit.h484
-rw-r--r--engines/gob/detection/tables_littlered.h265
-rw-r--r--engines/gob/detection/tables_onceupon.h518
-rw-r--r--engines/gob/detection/tables_playtoons.h517
-rw-r--r--engines/gob/detection/tables_urban.h151
-rw-r--r--engines/gob/detection/tables_ween.h349
-rw-r--r--engines/gob/detection/tables_woodruff.h402
-rw-r--r--engines/gob/detection_tables.h5276
-rw-r--r--engines/gob/draw.cpp42
-rw-r--r--engines/gob/draw.h16
-rw-r--r--engines/gob/draw_fascin.cpp8
-rw-r--r--engines/gob/draw_playtoons.cpp4
-rw-r--r--engines/gob/draw_v1.cpp2
-rw-r--r--engines/gob/draw_v2.cpp87
-rw-r--r--engines/gob/game.cpp13
-rw-r--r--engines/gob/game.h4
-rw-r--r--engines/gob/global.cpp1
-rw-r--r--engines/gob/global.h1
-rw-r--r--engines/gob/gob.cpp108
-rw-r--r--engines/gob/gob.h34
-rw-r--r--engines/gob/hotspots.cpp181
-rw-r--r--engines/gob/hotspots.h4
-rw-r--r--engines/gob/init.cpp14
-rw-r--r--engines/gob/init.h1
-rw-r--r--engines/gob/init_fascin.cpp6
-rw-r--r--engines/gob/init_geisha.cpp7
-rw-r--r--engines/gob/init_v1.cpp2
-rw-r--r--engines/gob/init_v2.cpp2
-rw-r--r--engines/gob/inter.cpp15
-rw-r--r--engines/gob/inter.h32
-rw-r--r--engines/gob/inter_bargon.cpp4
-rw-r--r--engines/gob/inter_fascin.cpp3
-rw-r--r--engines/gob/inter_geisha.cpp25
-rw-r--r--engines/gob/inter_littlered.cpp118
-rw-r--r--engines/gob/inter_v1.cpp70
-rw-r--r--engines/gob/inter_v2.cpp10
-rw-r--r--engines/gob/inter_v5.cpp10
-rw-r--r--engines/gob/inter_v7.cpp144
-rw-r--r--engines/gob/minigames/geisha/diving.cpp8
-rw-r--r--engines/gob/minigames/geisha/evilfish.cpp2
-rw-r--r--engines/gob/minigames/geisha/evilfish.h2
-rw-r--r--engines/gob/minigames/geisha/meter.cpp26
-rw-r--r--engines/gob/minigames/geisha/meter.h10
-rw-r--r--engines/gob/minigames/geisha/mouth.cpp169
-rw-r--r--engines/gob/minigames/geisha/mouth.h75
-rw-r--r--engines/gob/minigames/geisha/penetration.cpp1412
-rw-r--r--engines/gob/minigames/geisha/penetration.h197
-rw-r--r--engines/gob/minigames/geisha/submarine.cpp256
-rw-r--r--engines/gob/minigames/geisha/submarine.h107
-rw-r--r--engines/gob/module.mk20
-rw-r--r--engines/gob/mult.cpp3
-rw-r--r--engines/gob/mult_v2.cpp2
-rw-r--r--engines/gob/palanim.cpp93
-rw-r--r--engines/gob/pregob/gctfile.cpp306
-rw-r--r--engines/gob/pregob/gctfile.h149
-rw-r--r--engines/gob/pregob/onceupon/abracadabra.cpp137
-rw-r--r--engines/gob/pregob/onceupon/abracadabra.h61
-rw-r--r--engines/gob/pregob/onceupon/babayaga.cpp137
-rw-r--r--engines/gob/pregob/onceupon/babayaga.h61
-rw-r--r--engines/gob/pregob/onceupon/brokenstrings.h60
-rw-r--r--engines/gob/pregob/onceupon/chargenchild.cpp117
-rw-r--r--engines/gob/pregob/onceupon/chargenchild.h60
-rw-r--r--engines/gob/pregob/onceupon/onceupon.cpp1904
-rw-r--r--engines/gob/pregob/onceupon/onceupon.h344
-rw-r--r--engines/gob/pregob/onceupon/palettes.h411
-rw-r--r--engines/gob/pregob/onceupon/parents.cpp217
-rw-r--r--engines/gob/pregob/onceupon/parents.h94
-rw-r--r--engines/gob/pregob/onceupon/stork.cpp234
-rw-r--r--engines/gob/pregob/onceupon/stork.h103
-rw-r--r--engines/gob/pregob/onceupon/title.cpp117
-rw-r--r--engines/gob/pregob/onceupon/title.h55
-rw-r--r--engines/gob/pregob/pregob.cpp351
-rw-r--r--engines/gob/pregob/pregob.h194
-rw-r--r--engines/gob/pregob/seqfile.cpp384
-rw-r--r--engines/gob/pregob/seqfile.h193
-rw-r--r--engines/gob/pregob/txtfile.cpp232
-rw-r--r--engines/gob/pregob/txtfile.h91
-rw-r--r--engines/gob/resources.cpp12
-rw-r--r--engines/gob/resources.h6
-rw-r--r--engines/gob/rxyfile.cpp19
-rw-r--r--engines/gob/rxyfile.h4
-rw-r--r--engines/gob/save/saveload.h27
-rw-r--r--engines/gob/save/saveload_ajworld.cpp94
-rw-r--r--engines/gob/sound/adlib.cpp1044
-rw-r--r--engines/gob/sound/adlib.h312
-rw-r--r--engines/gob/sound/adlplayer.cpp257
-rw-r--r--engines/gob/sound/adlplayer.h85
-rw-r--r--engines/gob/sound/musplayer.cpp391
-rw-r--r--engines/gob/sound/musplayer.h109
-rw-r--r--engines/gob/sound/sound.cpp107
-rw-r--r--engines/gob/sound/sound.h26
-rw-r--r--engines/gob/sound/soundblaster.cpp29
-rw-r--r--engines/gob/sound/soundblaster.h6
-rw-r--r--engines/gob/surface.cpp46
-rw-r--r--engines/gob/surface.h4
-rw-r--r--engines/gob/util.cpp155
-rw-r--r--engines/gob/util.h16
-rw-r--r--engines/gob/video.cpp31
-rw-r--r--engines/gob/video.h5
-rw-r--r--engines/gob/videoplayer.cpp50
-rw-r--r--engines/gob/videoplayer.h7
127 files changed, 18489 insertions, 6579 deletions
diff --git a/engines/gob/anifile.cpp b/engines/gob/anifile.cpp
index 2671fe0405..085ac800cd 100644
--- a/engines/gob/anifile.cpp
+++ b/engines/gob/anifile.cpp
@@ -37,30 +37,38 @@ ANIFile::ANIFile(GobEngine *vm, const Common::String &fileName,
uint16 width, uint8 bpp) : _vm(vm),
_width(width), _bpp(bpp), _hasPadding(false) {
- Common::SeekableReadStream *ani = _vm->_dataIO->getFile(fileName);
- if (ani) {
- Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), false, DisposeAfterUse::YES);
+ bool bigEndian = false;
+ Common::String endianFileName = fileName;
- load(sub, fileName);
- return;
- }
+ if ((_vm->getEndiannessMethod() == kEndiannessMethodAltFile) &&
+ !_vm->_dataIO->hasFile(fileName)) {
+ // If the game has alternate big-endian files, look if one exist
- // File doesn't exist, try to open the big-endian'd alternate file
- Common::String alternateFileName = fileName;
- alternateFileName.setChar('_', 0);
+ Common::String alternateFileName = fileName;
+ alternateFileName.setChar('_', 0);
- ani = _vm->_dataIO->getFile(alternateFileName);
+ if (_vm->_dataIO->hasFile(alternateFileName)) {
+ bigEndian = true;
+ endianFileName = alternateFileName;
+ }
+ } else if ((_vm->getEndiannessMethod() == kEndiannessMethodBE) ||
+ ((_vm->getEndiannessMethod() == kEndiannessMethodSystem) &&
+ (_vm->getEndianness() == kEndiannessBE)))
+ // Game always little endian or it follows the system and it is big endian
+ bigEndian = true;
+
+ Common::SeekableReadStream *ani = _vm->_dataIO->getFile(endianFileName);
if (ani) {
- Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), true, DisposeAfterUse::YES);
+ Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), bigEndian, DisposeAfterUse::YES);
// The big endian version pads a few fields to even size
- _hasPadding = true;
+ _hasPadding = bigEndian;
load(sub, fileName);
return;
}
- warning("ANIFile::ANIFile(): No such file \"%s\"", fileName.c_str());
+ warning("ANIFile::ANIFile(): No such file \"%s\" (\"%s\")", endianFileName.c_str(), fileName.c_str());
}
ANIFile::~ANIFile() {
@@ -281,4 +289,9 @@ void ANIFile::drawLayer(Surface &dest, uint16 layer, uint16 part,
_layers[layer]->draw(dest, part, x, y, transp);
}
+void ANIFile::recolor(uint8 from, uint8 to) {
+ for (LayerArray::iterator l = _layers.begin(); l != _layers.end(); ++l)
+ (*l)->recolor(from, to);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/anifile.h b/engines/gob/anifile.h
index b6d9c735b5..c930aafc6b 100644
--- a/engines/gob/anifile.h
+++ b/engines/gob/anifile.h
@@ -92,6 +92,9 @@ public:
/** Draw an animation frame. */
void draw(Surface &dest, uint16 animation, uint16 frame, int16 x, int16 y) const;
+ /** Recolor the animation sprites. */
+ void recolor(uint8 from, uint8 to);
+
private:
typedef Common::Array<CMPFile *> LayerArray;
typedef Common::Array<Animation> AnimationArray;
diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp
index 154f8e04ed..7e3668a0ce 100644
--- a/engines/gob/aniobject.cpp
+++ b/engines/gob/aniobject.cpp
@@ -28,23 +28,20 @@
namespace Gob {
ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), _cmp(0),
- _visible(false), _paused(false), _mode(kModeContinuous),
- _x(0), _y(0), _background(0), _drawn(false) {
+ _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) {
setAnimation(0);
setPosition();
}
ANIObject::ANIObject(const CMPFile &cmp) : _ani(0), _cmp(&cmp),
- _visible(false), _paused(false), _mode(kModeContinuous),
- _x(0), _y(0), _background(0), _drawn(false) {
+ _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) {
setAnimation(0);
setPosition();
}
ANIObject::~ANIObject() {
- delete _background;
}
void ANIObject::setVisible(bool visible) {
@@ -76,6 +73,10 @@ void ANIObject::rewind() {
_frame = 0;
}
+void ANIObject::setFrame(uint16 frame) {
+ _frame = frame % _ani->getAnimationInfo(_animation).frameCount;
+}
+
void ANIObject::setPosition() {
// CMP "animations" have no default position
if (_cmp)
@@ -100,7 +101,7 @@ void ANIObject::getPosition(int16 &x, int16 &y) const {
y = _y;
}
-void ANIObject::getFramePosition(int16 &x, int16 &y) const {
+void ANIObject::getFramePosition(int16 &x, int16 &y, uint16 n) const {
// CMP "animations" have no specific frame positions
if (_cmp) {
getPosition(x, y);
@@ -114,11 +115,24 @@ void ANIObject::getFramePosition(int16 &x, int16 &y) const {
if (_frame >= animation.frameCount)
return;
- x = _x + animation.frameAreas[_frame].left;
- y = _y + animation.frameAreas[_frame].top;
+ // If we're paused, we don't advance any frames
+ if (_paused)
+ n = 0;
+
+ // Number of cycles run through after n frames
+ uint16 cycles = (_frame + n) / animation.frameCount;
+ // Frame position after n frames
+ uint16 frame = (_frame + n) % animation.frameCount;
+
+ // Only doing one cycle?
+ if (_mode == kModeOnce)
+ cycles = MAX<uint16>(cycles, 1);
+
+ x = _x + animation.frameAreas[frame].left + cycles * animation.deltaX;
+ y = _y + animation.frameAreas[frame].top + cycles * animation.deltaY;
}
-void ANIObject::getFrameSize(int16 &width, int16 &height) const {
+void ANIObject::getFrameSize(int16 &width, int16 &height, uint16 n) const {
if (_cmp) {
width = _cmp->getWidth (_animation);
height = _cmp->getHeight(_animation);
@@ -133,8 +147,15 @@ void ANIObject::getFrameSize(int16 &width, int16 &height) const {
if (_frame >= animation.frameCount)
return;
- width = animation.frameAreas[_frame].right - animation.frameAreas[_frame].left + 1;
- height = animation.frameAreas[_frame].bottom - animation.frameAreas[_frame].top + 1;
+ // If we're paused, we don't advance any frames
+ if (_paused)
+ n = 0;
+
+ // Frame position after n frames
+ uint16 frame = (_frame + n) % animation.frameCount;
+
+ width = animation.frameAreas[frame].right - animation.frameAreas[frame].left + 1;
+ height = animation.frameAreas[frame].bottom - animation.frameAreas[frame].top + 1;
}
bool ANIObject::isIn(int16 x, int16 y) const {
@@ -167,102 +188,78 @@ bool ANIObject::isIn(const ANIObject &obj) const {
obj.isIn(frameX + frameWidth - 1, frameY + frameHeight - 1);
}
-void ANIObject::draw(Surface &dest, int16 &left, int16 &top,
+bool ANIObject::draw(Surface &dest, int16 &left, int16 &top,
int16 &right, int16 &bottom) {
if (!_visible)
- return;
+ return false;
if (_cmp)
- drawCMP(dest, left, top, right, bottom);
+ return drawCMP(dest, left, top, right, bottom);
else if (_ani)
- drawANI(dest, left, top, right, bottom);
+ return drawANI(dest, left, top, right, bottom);
+
+ return false;
}
-void ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top,
+bool ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top,
int16 &right, int16 &bottom) {
- if (!_background) {
+ if (!hasBuffer()) {
uint16 width, height;
_cmp->getMaxSize(width, height);
- _background = new Surface(width, height, dest.getBPP());
+ resizeBuffer(width, height);
}
- const uint16 cR = _cmp->getWidth (_animation) - 1;
- const uint16 cB = _cmp->getHeight(_animation) - 1;
-
- _backgroundLeft = CLIP<int16>( + _x, 0, dest.getWidth () - 1);
- _backgroundTop = CLIP<int16>( + _y, 0, dest.getHeight() - 1);
- _backgroundRight = CLIP<int16>(cR + _x, 0, dest.getWidth () - 1);
- _backgroundBottom = CLIP<int16>(cB + _y, 0, dest.getHeight() - 1);
+ left = _x;
+ top = _y;
+ right = _x + _cmp->getWidth (_animation) - 1;
+ bottom = _y + _cmp->getHeight(_animation) - 1;
- _background->blit(dest, _backgroundLeft , _backgroundTop,
- _backgroundRight, _backgroundBottom, 0, 0);
+ if (!saveScreen(dest, left, top, right, bottom))
+ return false;
_cmp->draw(dest, _animation, _x, _y, 0);
- _drawn = true;
-
- left = _backgroundLeft;
- top = _backgroundTop;
- right = _backgroundRight;
- bottom = _backgroundBottom;
+ return true;
}
-void ANIObject::drawANI(Surface &dest, int16 &left, int16 &top,
+bool ANIObject::drawANI(Surface &dest, int16 &left, int16 &top,
int16 &right, int16 &bottom) {
- if (!_background) {
+ if (!hasBuffer()) {
uint16 width, height;
_ani->getMaxSize(width, height);
- _background = new Surface(width, height, dest.getBPP());
+ resizeBuffer(width, height);
}
const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
if (_frame >= animation.frameCount)
- return;
+ return false;
const ANIFile::FrameArea &area = animation.frameAreas[_frame];
- _backgroundLeft = CLIP<int16>(area.left + _x, 0, dest.getWidth () - 1);
- _backgroundTop = CLIP<int16>(area.top + _y, 0, dest.getHeight() - 1);
- _backgroundRight = CLIP<int16>(area.right + _x, 0, dest.getWidth () - 1);
- _backgroundBottom = CLIP<int16>(area.bottom + _y, 0, dest.getHeight() - 1);
+ left = _x + area.left;
+ top = _y + area.top;
+ right = _x + area.right;
+ bottom = _y + area.bottom;
- _background->blit(dest, _backgroundLeft , _backgroundTop,
- _backgroundRight, _backgroundBottom, 0, 0);
+ if (!saveScreen(dest, left, top, right, bottom))
+ return false;
_ani->draw(dest, _animation, _frame, _x, _y);
- _drawn = true;
-
- left = _backgroundLeft;
- top = _backgroundTop;
- right = _backgroundRight;
- bottom = _backgroundBottom;
+ return true;
}
-void ANIObject::clear(Surface &dest, int16 &left, int16 &top,
+bool ANIObject::clear(Surface &dest, int16 &left, int16 &top,
int16 &right, int16 &bottom) {
- if (!_drawn)
- return;
-
- const int16 bgRight = _backgroundRight - _backgroundLeft;
- const int16 bgBottom = _backgroundBottom - _backgroundTop;
-
- dest.blit(*_background, 0, 0, bgRight, bgBottom, _backgroundLeft, _backgroundTop);
-
- _drawn = false;
-
- left = _backgroundLeft;
- top = _backgroundTop;
- right = _backgroundRight;
- bottom = _backgroundBottom;
+ return restoreScreen(dest, left, top, right, bottom);
}
void ANIObject::advance() {
diff --git a/engines/gob/aniobject.h b/engines/gob/aniobject.h
index c101d747b7..d8c8edc2b8 100644
--- a/engines/gob/aniobject.h
+++ b/engines/gob/aniobject.h
@@ -25,6 +25,8 @@
#include "common/system.h"
+#include "gob/backbuffer.h"
+
namespace Gob {
class ANIFile;
@@ -32,7 +34,7 @@ class CMPFile;
class Surface;
/** An ANI object, controlling an animation within an ANI file. */
-class ANIObject {
+class ANIObject : public BackBuffer {
public:
enum Mode {
kModeContinuous, ///< Play the animation continuously.
@@ -61,17 +63,17 @@ public:
void setMode(Mode mode);
/** Set the current position to the animation's default. */
- void setPosition();
+ virtual void setPosition();
/** Set the current position. */
- void setPosition(int16 x, int16 y);
+ virtual void setPosition(int16 x, int16 y);
/** Return the current position. */
void getPosition(int16 &x, int16 &y) const;
- /** Return the current frame position. */
- void getFramePosition(int16 &x, int16 &y) const;
- /** Return the current frame size. */
- void getFrameSize(int16 &width, int16 &height) const;
+ /** Return the frame position after another n frames. */
+ void getFramePosition(int16 &x, int16 &y, uint16 n = 0) const;
+ /** Return the current frame size after another n frames. */
+ void getFrameSize(int16 &width, int16 &height, uint16 n = 0) const;
/** Are there coordinates within the animation sprite? */
bool isIn(int16 x, int16 y) const;
@@ -84,6 +86,9 @@ public:
/** Rewind the current animation to the first frame. */
void rewind();
+ /** Set the animation to a specific frame. */
+ void setFrame(uint16 frame);
+
/** Return the current animation number. */
uint16 getAnimation() const;
/** Return the current frame number. */
@@ -93,9 +98,9 @@ public:
bool lastFrame() const;
/** Draw the current frame onto the surface and return the affected rectangle. */
- void draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+ virtual bool draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
/** Draw the current frame from the surface and return the affected rectangle. */
- void clear(Surface &dest, int16 &left , int16 &top, int16 &right, int16 &bottom);
+ virtual bool clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
/** Advance the animation to the next frame. */
virtual void advance();
@@ -115,16 +120,9 @@ private:
int16 _x; ///< The current X position.
int16 _y; ///< The current Y position.
- Surface *_background; ///< The saved background.
- bool _drawn; ///< Was the animation drawn?
-
- int16 _backgroundLeft; ///< The left position of the saved background.
- int16 _backgroundTop; ///< The top of the saved background.
- int16 _backgroundRight; ///< The right position of the saved background.
- int16 _backgroundBottom; ///< The bottom position of the saved background.
- void drawCMP(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
- void drawANI(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+ bool drawCMP(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+ bool drawANI(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
};
} // End of namespace Gob
diff --git a/engines/gob/backbuffer.cpp b/engines/gob/backbuffer.cpp
new file mode 100644
index 0000000000..752042d46e
--- /dev/null
+++ b/engines/gob/backbuffer.cpp
@@ -0,0 +1,100 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/util.h"
+
+#include "gob/backbuffer.h"
+#include "gob/surface.h"
+
+namespace Gob {
+
+BackBuffer::BackBuffer() : _background(0), _saved(false) {
+}
+
+BackBuffer::~BackBuffer() {
+ delete _background;
+}
+
+bool BackBuffer::hasBuffer() const {
+ return _background != 0;
+}
+
+bool BackBuffer::hasSavedBackground() const {
+ return _saved;
+}
+
+void BackBuffer::trashBuffer() {
+ _saved = false;
+}
+
+void BackBuffer::resizeBuffer(uint16 width, uint16 height) {
+ trashBuffer();
+
+ if (_background && (_background->getWidth() == width) && (_background->getHeight() == height))
+ return;
+
+ delete _background;
+
+ _background = new Surface(width, height, 1);
+}
+
+bool BackBuffer::saveScreen(const Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ if (!_background)
+ return false;
+
+ const int16 width = MIN<int16>(right - left + 1, _background->getWidth ());
+ const int16 height = MIN<int16>(bottom - top + 1, _background->getHeight());
+ if ((width <= 0) || (height <= 0))
+ return false;
+
+ right = left + width - 1;
+ bottom = top + height - 1;
+
+ _saveLeft = left;
+ _saveTop = top;
+ _saveRight = right;
+ _saveBottom = bottom;
+
+ _background->blit(dest, _saveLeft, _saveTop, _saveRight, _saveBottom, 0, 0);
+
+ _saved = true;
+
+ return true;
+}
+
+bool BackBuffer::restoreScreen(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ if (!_saved)
+ return false;
+
+ left = _saveLeft;
+ top = _saveTop;
+ right = _saveRight;
+ bottom = _saveBottom;
+
+ dest.blit(*_background, 0, 0, right - left, bottom - top, left, top);
+
+ _saved = false;
+
+ return true;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/backbuffer.h b/engines/gob/backbuffer.h
new file mode 100644
index 0000000000..c978689e9f
--- /dev/null
+++ b/engines/gob/backbuffer.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_BACKBUFFER_H
+#define GOB_BACKBUFFER_H
+
+#include "common/system.h"
+
+namespace Gob {
+
+class Surface;
+
+class BackBuffer {
+public:
+ BackBuffer();
+ ~BackBuffer();
+
+protected:
+ void trashBuffer();
+ void resizeBuffer(uint16 width, uint16 height);
+
+ bool saveScreen (const Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+ bool restoreScreen( Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+
+ bool hasBuffer() const;
+ bool hasSavedBackground() const;
+
+private:
+ Surface *_background; ///< The saved background.
+ bool _saved; ///< Was the background saved?
+
+ int16 _saveLeft; ///< The left position of the saved background.
+ int16 _saveTop; ///< The top of the saved background.
+ int16 _saveRight; ///< The right position of the saved background.
+ int16 _saveBottom; ///< The bottom position of the saved background.
+};
+
+} // End of namespace Gob
+
+#endif // GOB_BACKBUFFER_H
diff --git a/engines/gob/cheater.h b/engines/gob/cheater.h
index 334a5e88eb..bf6c1372fb 100644
--- a/engines/gob/cheater.h
+++ b/engines/gob/cheater.h
@@ -31,6 +31,7 @@ namespace Gob {
namespace Geisha {
class Diving;
+ class Penetration;
}
class GobEngine;
@@ -48,13 +49,14 @@ protected:
class Cheater_Geisha : public Cheater {
public:
- Cheater_Geisha(GobEngine *vm, Geisha::Diving *diving);
+ Cheater_Geisha(GobEngine *vm, Geisha::Diving *diving, Geisha::Penetration *penetration);
~Cheater_Geisha();
bool cheat(GUI::Debugger &console);
private:
- Geisha::Diving *_diving;
+ Geisha::Diving *_diving;
+ Geisha::Penetration *_penetration;
};
} // End of namespace Gob
diff --git a/engines/gob/cheater_geisha.cpp b/engines/gob/cheater_geisha.cpp
index 3d8c56707d..567333c12f 100644
--- a/engines/gob/cheater_geisha.cpp
+++ b/engines/gob/cheater_geisha.cpp
@@ -27,11 +27,12 @@
#include "gob/inter.h"
#include "gob/minigames/geisha/diving.h"
+#include "gob/minigames/geisha/penetration.h"
namespace Gob {
-Cheater_Geisha::Cheater_Geisha(GobEngine *vm, Geisha::Diving *diving) :
- Cheater(vm), _diving(diving) {
+Cheater_Geisha::Cheater_Geisha(GobEngine *vm, Geisha::Diving *diving, Geisha::Penetration *penetration) :
+ Cheater(vm), _diving(diving), _penetration(penetration) {
}
@@ -45,6 +46,12 @@ bool Cheater_Geisha::cheat(GUI::Debugger &console) {
return false;
}
+ // A cheat to get around the Penetration minigame
+ if (_penetration->isPlaying()) {
+ _penetration->cheatWin();
+ return false;
+ }
+
// A cheat to get around the mastermind puzzle
if (_vm->isCurrentTot("hard.tot") && _vm->_inter->_variables) {
uint32 digit1 = READ_VARO_UINT32(0x768);
diff --git a/engines/gob/cmpfile.cpp b/engines/gob/cmpfile.cpp
index 7b21c4c835..d304958f76 100644
--- a/engines/gob/cmpfile.cpp
+++ b/engines/gob/cmpfile.cpp
@@ -21,6 +21,7 @@
*/
#include "common/stream.h"
+#include "common/substream.h"
#include "common/str.h"
#include "gob/gob.h"
@@ -143,7 +144,13 @@ void CMPFile::loadCMP(Common::SeekableReadStream &cmp) {
}
void CMPFile::loadRXY(Common::SeekableReadStream &rxy) {
- _coordinates = new RXYFile(rxy);
+ bool bigEndian = (_vm->getEndiannessMethod() == kEndiannessMethodBE) ||
+ ((_vm->getEndiannessMethod() == kEndiannessMethodSystem) &&
+ (_vm->getEndianness() == kEndiannessBE));
+
+ Common::SeekableSubReadStreamEndian sub(&rxy, 0, rxy.size(), bigEndian, DisposeAfterUse::NO);
+
+ _coordinates = new RXYFile(sub);
for (uint i = 0; i < _coordinates->size(); i++) {
const RXYFile::Coordinates &c = (*_coordinates)[i];
@@ -243,4 +250,9 @@ uint16 CMPFile::addSprite(uint16 left, uint16 top, uint16 right, uint16 bottom)
return _coordinates->add(left, top, right, bottom);
}
+void CMPFile::recolor(uint8 from, uint8 to) {
+ if (_surface)
+ _surface->recolor(from, to);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/cmpfile.h b/engines/gob/cmpfile.h
index 2b669e4d38..9c858238af 100644
--- a/engines/gob/cmpfile.h
+++ b/engines/gob/cmpfile.h
@@ -70,6 +70,8 @@ public:
uint16 addSprite(uint16 left, uint16 top, uint16 right, uint16 bottom);
+ void recolor(uint8 from, uint8 to);
+
private:
GobEngine *_vm;
diff --git a/engines/gob/decfile.cpp b/engines/gob/decfile.cpp
index fb67c52627..85b4c09ca3 100644
--- a/engines/gob/decfile.cpp
+++ b/engines/gob/decfile.cpp
@@ -38,30 +38,38 @@ DECFile::DECFile(GobEngine *vm, const Common::String &fileName,
uint16 width, uint16 height, uint8 bpp) : _vm(vm),
_width(width), _height(height), _bpp(bpp), _hasPadding(false), _backdrop(0) {
- Common::SeekableReadStream *dec = _vm->_dataIO->getFile(fileName);
- if (dec) {
- Common::SeekableSubReadStreamEndian sub(dec, 0, dec->size(), false, DisposeAfterUse::YES);
-
- load(sub, fileName);
- return;
- }
-
- // File doesn't exist, try to open the big-endian'd alternate file
- Common::String alternateFileName = fileName;
- alternateFileName.setChar('_', 0);
-
- dec = _vm->_dataIO->getFile(alternateFileName);
- if (dec) {
- Common::SeekableSubReadStreamEndian sub(dec, 0, dec->size(), true, DisposeAfterUse::YES);
+ bool bigEndian = false;
+ Common::String endianFileName = fileName;
+
+ if ((_vm->getEndiannessMethod() == kEndiannessMethodAltFile) &&
+ !_vm->_dataIO->hasFile(fileName)) {
+ // If the game has alternate big-endian files, look if one exist
+
+ Common::String alternateFileName = fileName;
+ alternateFileName.setChar('_', 0);
+
+ if (_vm->_dataIO->hasFile(alternateFileName)) {
+ bigEndian = true;
+ endianFileName = alternateFileName;
+ }
+ } else if ((_vm->getEndiannessMethod() == kEndiannessMethodBE) ||
+ ((_vm->getEndiannessMethod() == kEndiannessMethodSystem) &&
+ (_vm->getEndianness() == kEndiannessBE)))
+ // Game always little endian or it follows the system and it is big endian
+ bigEndian = true;
+
+ Common::SeekableReadStream *ani = _vm->_dataIO->getFile(endianFileName);
+ if (ani) {
+ Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), bigEndian, DisposeAfterUse::YES);
// The big endian version pads a few fields to even size
- _hasPadding = true;
+ _hasPadding = bigEndian;
load(sub, fileName);
return;
}
- warning("DECFile::DECFile(): No such file \"%s\"", fileName.c_str());
+ warning("DECFile::DECFile(): No such file \"%s\" (\"%s\")", endianFileName.c_str(), fileName.c_str());
}
DECFile::~DECFile() {
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp
new file mode 100644
index 0000000000..8fb0052a5b
--- /dev/null
+++ b/engines/gob/detection/detection.cpp
@@ -0,0 +1,220 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "base/plugins.h"
+#include "engines/advancedDetector.h"
+#include "engines/obsolete.h"
+
+#include "gob/gob.h"
+#include "gob/dataio.h"
+
+#include "gob/detection/tables.h"
+
+class GobMetaEngine : public AdvancedMetaEngine {
+public:
+ GobMetaEngine();
+
+ virtual GameDescriptor findGame(const char *gameid) const;
+
+ virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+
+ virtual const char *getName() const;
+ virtual const char *getOriginalCopyright() const;
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+
+ virtual Common::Error createInstance(OSystem *syst, Engine **engine) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+
+private:
+ /**
+ * Inspect the game archives to detect which Once Upon A Time game this is.
+ */
+ static const Gob::GOBGameDescription *detectOnceUponATime(const Common::FSList &fslist);
+};
+
+GobMetaEngine::GobMetaEngine() :
+ AdvancedMetaEngine(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) {
+
+ _singleid = "gob";
+ _guioptions = GUIO1(GUIO_NOLAUNCHLOAD);
+}
+
+GameDescriptor GobMetaEngine::findGame(const char *gameid) const {
+ return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
+}
+
+const ADGameDescription *GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADFilePropertiesMap filesProps;
+
+ const Gob::GOBGameDescription *game;
+ game = (const Gob::GOBGameDescription *)detectGameFilebased(allFiles, fslist, Gob::fileBased, &filesProps);
+ if (!game)
+ return 0;
+
+ if (game->gameType == Gob::kGameTypeOnceUponATime) {
+ game = detectOnceUponATime(fslist);
+ if (!game)
+ return 0;
+ }
+
+ reportUnknown(fslist.begin()->getParent(), filesProps);
+ return (const ADGameDescription *)game;
+}
+
+const Gob::GOBGameDescription *GobMetaEngine::detectOnceUponATime(const Common::FSList &fslist) {
+ // Add the game path to the search manager
+ SearchMan.clear();
+ SearchMan.addDirectory(fslist.begin()->getParent().getPath(), fslist.begin()->getParent());
+
+ // Open the archives
+ Gob::DataIO dataIO;
+ if (!dataIO.openArchive("stk1.stk", true) ||
+ !dataIO.openArchive("stk2.stk", true) ||
+ !dataIO.openArchive("stk3.stk", true)) {
+
+ SearchMan.clear();
+ return 0;
+ }
+
+ Gob::OnceUponATime gameType = Gob::kOnceUponATimeInvalid;
+ Gob::OnceUponATimePlatform platform = Gob::kOnceUponATimePlatformInvalid;
+
+ // If these animal files are present, it's Abracadabra
+ if (dataIO.hasFile("arai.anm") &&
+ dataIO.hasFile("crab.anm") &&
+ dataIO.hasFile("crap.anm") &&
+ dataIO.hasFile("drag.anm") &&
+ dataIO.hasFile("guep.anm") &&
+ dataIO.hasFile("loup.anm") &&
+ dataIO.hasFile("mous.anm") &&
+ dataIO.hasFile("rhin.anm") &&
+ dataIO.hasFile("saut.anm") &&
+ dataIO.hasFile("scor.anm"))
+ gameType = Gob::kOnceUponATimeAbracadabra;
+
+ // If these animal files are present, it's Baba Yaga
+ if (dataIO.hasFile("abei.anm") &&
+ dataIO.hasFile("arai.anm") &&
+ dataIO.hasFile("drag.anm") &&
+ dataIO.hasFile("fauc.anm") &&
+ dataIO.hasFile("gren.anm") &&
+ dataIO.hasFile("rena.anm") &&
+ dataIO.hasFile("sang.anm") &&
+ dataIO.hasFile("serp.anm") &&
+ dataIO.hasFile("tort.anm") &&
+ dataIO.hasFile("vaut.anm"))
+ gameType = Gob::kOnceUponATimeBabaYaga;
+
+ // Detect the platform by endianness and existence of a MOD file
+ Common::SeekableReadStream *villeDEC = dataIO.getFile("ville.dec");
+ if (villeDEC && (villeDEC->size() > 6)) {
+ byte data[6];
+
+ if (villeDEC->read(data, 6) == 6) {
+ if (!memcmp(data, "\000\000\000\001\000\007", 6)) {
+ // Big endian -> Amiga or Atari ST
+
+ if (dataIO.hasFile("mod.babayaga"))
+ platform = Gob::kOnceUponATimePlatformAmiga;
+ else
+ platform = Gob::kOnceUponATimePlatformAtariST;
+
+ } else if (!memcmp(data, "\000\000\001\000\007\000", 6))
+ // Little endian -> DOS
+ platform = Gob::kOnceUponATimePlatformDOS;
+ }
+
+ delete villeDEC;
+ }
+
+ SearchMan.clear();
+
+ if ((gameType == Gob::kOnceUponATimeInvalid) || (platform == Gob::kOnceUponATimePlatformInvalid)) {
+ warning("GobMetaEngine::detectOnceUponATime(): Detection failed (%d, %d)",
+ (int) gameType, (int) platform);
+ return 0;
+ }
+
+ return &Gob::fallbackOnceUpon[gameType][platform];
+}
+
+const char *GobMetaEngine::getName() const {
+ return "Gob";
+}
+
+const char *GobMetaEngine::getOriginalCopyright() const {
+ return "Goblins Games (C) Coktel Vision";
+}
+
+bool GobMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return false;
+}
+
+bool Gob::GobEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL);
+}
+
+Common::Error GobMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
+ Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
+ return AdvancedMetaEngine::createInstance(syst, engine);
+}
+
+bool GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Gob::GOBGameDescription *gd = (const Gob::GOBGameDescription *)desc;
+ if (gd) {
+ *engine = new Gob::GobEngine(syst);
+ ((Gob::GobEngine *)*engine)->initGame(gd);
+ }
+ return gd != 0;
+}
+
+
+#if PLUGIN_ENABLED_DYNAMIC(GOB)
+ REGISTER_PLUGIN_DYNAMIC(GOB, PLUGIN_TYPE_ENGINE, GobMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(GOB, PLUGIN_TYPE_ENGINE, GobMetaEngine);
+#endif
+
+namespace Gob {
+
+void GobEngine::initGame(const GOBGameDescription *gd) {
+ if (gd->startTotBase == 0)
+ _startTot = "intro.tot";
+ else
+ _startTot = gd->startTotBase;
+
+ if (gd->startStkBase == 0)
+ _startStk = "intro.stk";
+ else
+ _startStk = gd->startStkBase;
+
+ _demoIndex = gd->demoIndex;
+
+ _gameType = gd->gameType;
+ _features = gd->features;
+ _language = gd->desc.language;
+ _platform = gd->desc.platform;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/detection.cpp b/engines/gob/detection/tables.h
index 17a2ae3da8..271f75af79 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection/tables.h
@@ -20,11 +20,8 @@
*
*/
-#include "base/plugins.h"
-#include "engines/advancedDetector.h"
-#include "engines/obsolete.h"
-
-#include "gob/gob.h"
+#ifndef GOB_DETECTION_TABLES_H
+#define GOB_DETECTION_TABLES_H
namespace Gob {
@@ -42,6 +39,7 @@ struct GOBGameDescription {
using namespace Common;
+// Game IDs and proper names
static const PlainGameDescriptor gobGames[] = {
{"gob", "Gob engine game"},
{"gob1", "Gobliiins"},
@@ -50,8 +48,11 @@ static const PlainGameDescriptor gobGames[] = {
{"gob2cd", "Gobliins 2 CD"},
{"ween", "Ween: The Prophecy"},
{"bargon", "Bargon Attack"},
- {"littlered", "Little Red Riding Hood"},
- {"ajworld", "A.J's World of Discovery"},
+ {"babayaga", "Once Upon A Time: Baba Yaga"},
+ {"abracadabra", "Once Upon A Time: Abracadabra"},
+ {"littlered", "Once Upon A Time: Little Red Riding Hood"},
+ {"onceupon", "Once Upon A Time"},
+ {"ajworld", "A.J.'s World of Discovery"},
{"gob3", "Goblins Quest 3"},
{"gob3cd", "Goblins Quest 3 CD"},
{"lit1", "Lost in Time Part 1"},
@@ -79,87 +80,42 @@ static const PlainGameDescriptor gobGames[] = {
{0, 0}
};
+// Obsolete IDs we don't want anymore
static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = {
{"gob1", "gob", kPlatformUnknown},
{"gob2", "gob", kPlatformUnknown},
{0, 0, kPlatformUnknown}
};
-#include "gob/detection_tables.h"
-
-class GobMetaEngine : public AdvancedMetaEngine {
-public:
- GobMetaEngine() : AdvancedMetaEngine(Gob::gameDescriptions, sizeof(Gob::GOBGameDescription), gobGames) {
- _singleid = "gob";
- _guioptions = GUIO1(GUIO_NOLAUNCHLOAD);
- }
-
- virtual GameDescriptor findGame(const char *gameid) const {
- return Engines::findGameID(gameid, _gameids, obsoleteGameIDsTable);
- }
-
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- return detectGameFilebased(allFiles, Gob::fileBased);
- }
-
- virtual const char *getName() const {
- return "Gob";
- }
-
- virtual const char *getOriginalCopyright() const {
- return "Goblins Games (C) Coktel Vision";
- }
-
- virtual bool hasFeature(MetaEngineFeature f) const;
+namespace Gob {
- virtual Common::Error createInstance(OSystem *syst, Engine **engine) const {
- Engines::upgradeTargetIfNecessary(obsoleteGameIDsTable);
- return AdvancedMetaEngine::createInstance(syst, engine);
- }
- virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+// Detection tables
+static const GOBGameDescription gameDescriptions[] = {
+ #include "gob/detection/tables_gob1.h" // Gobliiins
+ #include "gob/detection/tables_gob2.h" // Gobliins 2: The Prince Buffoon
+ #include "gob/detection/tables_gob3.h" // Goblins 3 / Goblins Quest 3
+ #include "gob/detection/tables_ween.h" // Ween: The Prophecy
+ #include "gob/detection/tables_bargon.h" // Bargon Attack
+ #include "gob/detection/tables_littlered.h" // Once Upon A Time: Little Red Riding Hood
+ #include "gob/detection/tables_onceupon.h" // Once Upon A Time: Baba Yaga and Abracadabra
+ #include "gob/detection/tables_lit.h" // Lost in Time
+ #include "gob/detection/tables_fascin.h" // Fascination
+ #include "gob/detection/tables_geisha.h" // Geisha
+ #include "gob/detection/tables_inca2.h" // Inca II: Wiracocha
+ #include "gob/detection/tables_woodruff.h" // (The Bizarre Adventures of) Woodruff and the Schnibble (of Azimuth)
+ #include "gob/detection/tables_dynasty.h" // The Last Dynasty
+ #include "gob/detection/tables_urban.h" // Urban Runner
+ #include "gob/detection/tables_playtoons.h" // The Playtoons series
+ #include "gob/detection/tables_adi2.h" // The ADI / Addy 2 series
+ #include "gob/detection/tables_adi4.h" // The ADI / Addy 4 series
+ #include "gob/detection/tables_adibou.h" // The Adibou / Addy Junior series
+ #include "gob/detection/tables_ajworld.h" // A.J.'s World of Discovery / ADI Jr.
+
+ { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0}
};
-bool GobMetaEngine::hasFeature(MetaEngineFeature f) const {
- return false;
-}
-
-bool Gob::GobEngine::hasFeature(EngineFeature f) const {
- return
- (f == kSupportsRTL);
-}
-bool GobMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- const Gob::GOBGameDescription *gd = (const Gob::GOBGameDescription *)desc;
- if (gd) {
- *engine = new Gob::GobEngine(syst);
- ((Gob::GobEngine *)*engine)->initGame(gd);
- }
- return gd != 0;
+// File-based fallback tables
+#include "gob/detection/tables_fallback.h"
}
-#if PLUGIN_ENABLED_DYNAMIC(GOB)
- REGISTER_PLUGIN_DYNAMIC(GOB, PLUGIN_TYPE_ENGINE, GobMetaEngine);
-#else
- REGISTER_PLUGIN_STATIC(GOB, PLUGIN_TYPE_ENGINE, GobMetaEngine);
-#endif
-
-namespace Gob {
-
-void GobEngine::initGame(const GOBGameDescription *gd) {
- if (gd->startTotBase == 0)
- _startTot = "intro.tot";
- else
- _startTot = gd->startTotBase;
-
- if (gd->startStkBase == 0)
- _startStk = "intro.stk";
- else
- _startStk = gd->startStkBase;
-
- _demoIndex = gd->demoIndex;
-
- _gameType = gd->gameType;
- _features = gd->features;
- _language = gd->desc.language;
- _platform = gd->desc.platform;
-}
-} // End of namespace Gob
+#endif // GOB_DETECTION_TABLES_H
diff --git a/engines/gob/detection/tables_adi2.h b/engines/gob/detection/tables_adi2.h
new file mode 100644
index 0000000000..da05a31f40
--- /dev/null
+++ b/engines/gob/detection/tables_adi2.h
@@ -0,0 +1,203 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for the ADI / Addy 2 series. */
+
+#ifndef GOB_DETECTION_TABLES_ADI2_H
+#define GOB_DETECTION_TABLES_ADI2_H
+
+// -- French: Adi --
+
+{
+ {
+ "adi2",
+ "Adi 2.0 for Teachers",
+ AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdi2,
+ kFeaturesNone,
+ "adi2.stk", "ediintro.tot", 0
+},
+{ // Found in french ADI 2 Francais-Maths CM1. Exact version not specified.
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+{ // Found in french ADI 2 Francais-Maths CE2. Exact version not specified.
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+{
+ {
+ "adi2",
+ "Adi 2.5",
+ AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+{
+ {
+ "adi2",
+ "Adi 2.5",
+ AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+{
+ {
+ "adi2",
+ "Adi 2.6",
+ AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+
+// -- German: Addy --
+
+{
+ {
+ "adi2",
+ "Adi 2.6",
+ AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+{
+ {
+ "adi2",
+ "Adi 2.7.1",
+ AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+
+// -- Spanish: Adi --
+
+{
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", "ediintro.tot", 0
+},
+
+// -- English: ADI (Amiga) --
+
+{
+ {
+ "adi2",
+ "Adi 2",
+ AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdi2,
+ kFeaturesNone,
+ "adi2.stk", "ediintro.tot", 0
+},
+
+// -- Demos --
+
+{
+ {
+ "adi2",
+ "Non-Interactive Demo",
+ {
+ {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168},
+ {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723},
+ {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731},
+ {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 1
+},
+
+#endif // GOB_DETECTION_TABLES_ADI2_H
diff --git a/engines/gob/detection/tables_adi4.h b/engines/gob/detection/tables_adi4.h
new file mode 100644
index 0000000000..4b967d76d3
--- /dev/null
+++ b/engines/gob/detection/tables_adi4.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for the ADI / Addy 4 series. */
+
+#ifndef GOB_DETECTION_TABLES_ADI4_H
+#define GOB_DETECTION_TABLES_ADI4_H
+
+// -- French: Adi --
+
+{
+ {
+ "adi4",
+ "Adi 4.0",
+ AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "Adi 4.0",
+ AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "Adi 4.0",
+ AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "Adi 4.0 Limited Edition",
+ AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "ADI 4.10",
+ AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "ADI 4.11",
+ AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "ADI 4.21",
+ AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+
+// -- German: Addy --
+
+{
+ {
+ "adi4",
+ "Addy 4 Grundschule Basis CD",
+ AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "Addy 4 Sekundarstufe Basis CD",
+ AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "Addy 4.21",
+ AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+
+// -- English: ADI --
+
+{
+ {
+ "adi4",
+ "ADI 4.10",
+ AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "adi4",
+ "Adi 4.0 Interactive Demo",
+ AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "adi4",
+ "Adi 4.0 / Adibou 2 Demo",
+ AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_ADI4_H
diff --git a/engines/gob/detection/tables_adibou.h b/engines/gob/detection/tables_adibou.h
new file mode 100644
index 0000000000..0e652839bb
--- /dev/null
+++ b/engines/gob/detection/tables_adibou.h
@@ -0,0 +1,247 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Adibou / Addy Junior series. */
+
+#ifndef GOB_DETECTION_TABLES_ADIBOU_H
+#define GOB_DETECTION_TABLES_ADIBOU_H
+
+// -- French: Adibou --
+
+{
+ {
+ "adibou1",
+ "ADIBOU 1 Environnement 4-7 ans",
+ AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAdibou1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "ADIBOU 2",
+ AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "Le Jardin Magique d'Adibou",
+ AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "ADIBOU Version Decouverte",
+ AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "ADIBOU 2.10 Environnement",
+ AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "ADIBOU 2.11 Environnement",
+ AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "ADIBOU 2.12 Environnement",
+ AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "ADIBOU 2.13s Environnement",
+ AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "adibou2",
+ "ADIBOO 2.14 Environnement",
+ AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- German: Addy Junior --
+
+{
+ {
+ "adibou2",
+ "ADIBOU 2",
+ AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Italian: Adibù --
+{
+ {
+ "adibou2",
+ "ADIB\xD9 2",
+ AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ kGameTypeAdibou2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "adibou2",
+ "Non-Interactive Demo",
+ {
+ {"demogb.scn", 0, "9291455a908ac0e6aaaca686e532609b", 105},
+ {"demogb.vmd", 0, "bc9c1db97db7bec8f566332444fa0090", 14320840},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeAdibou2,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 9
+},
+{
+ {
+ "adibou2",
+ "Non-Interactive Demo",
+ {
+ {"demoall.scn", 0, "c8fd308c037b829800006332b2c32674", 106},
+ {"demoall.vmd", 0, "4672b2deacc6fca97484840424b1921b", 14263433},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeAdibou2,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 10
+},
+{
+ {
+ "adibou2",
+ "Non-Interactive Demo",
+ {
+ {"demofra.scn", 0, "d1b2b1618af384ea1120def8b986c02b", 106},
+ {"demofra.vmd", 0, "b494cdec1aac7e54c3f2480512d2880e", 14297100},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeAdibou2,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 11
+},
+
+#endif // GOB_DETECTION_TABLES_ADIBOU_H
diff --git a/engines/gob/detection/tables_ajworld.h b/engines/gob/detection/tables_ajworld.h
new file mode 100644
index 0000000000..d86bdb16be
--- /dev/null
+++ b/engines/gob/detection/tables_ajworld.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for A.J.'s World of Discovery / ADI Jr. */
+
+#ifndef GOB_DETECTION_TABLES_AJWORLD_H
+#define GOB_DETECTION_TABLES_AJWORLD_H
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "ajworld",
+ "",
+ AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAJWorld,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_AJWORLD_H
diff --git a/engines/gob/detection/tables_bargon.h b/engines/gob/detection/tables_bargon.h
new file mode 100644
index 0000000000..ac90355476
--- /dev/null
+++ b/engines/gob/detection/tables_bargon.h
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Bargon Attack. */
+
+#ifndef GOB_DETECTION_TABLES_BARGON_H
+#define GOB_DETECTION_TABLES_BARGON_H
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "bargon",
+ "",
+ AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by cesardark in bug #1681649
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by paul66 in bug #1692667
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by kizkoool in bugreport #2089734
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by glorfindel in bugreport #1722142
+ {
+ "bargon",
+ "Fanmade",
+ AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Amiga --
+
+{ // Supplied by pwigren in bugreport #1764174
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Atari ST --
+
+{ // Supplied by Trekky in the forums
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109),
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_BARGON_H
diff --git a/engines/gob/detection/tables_dynasty.h b/engines/gob/detection/tables_dynasty.h
new file mode 100644
index 0000000000..147bf32075
--- /dev/null
+++ b/engines/gob/detection/tables_dynasty.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for The Last Dynasty. */
+
+#ifndef GOB_DETECTION_TABLES_DYNASTY_H
+#define GOB_DETECTION_TABLES_DYNASTY_H
+
+// -- Windows --
+
+{
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "dynasty",
+ "Demo",
+ AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864),
+ EN_USA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "dynasty",
+ "Demo",
+ AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774),
+ UNK_LANG,
+ kPlatformWindows,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ "lda1.stk", 0, 0
+},
+{
+ {
+ "dynasty",
+ "Demo",
+ AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_DEMO,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeDynasty,
+ kFeatures640x480,
+ "lda1.stk", 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_DYNASTY_H
diff --git a/engines/gob/detection/tables_fallback.h b/engines/gob/detection/tables_fallback.h
new file mode 100644
index 0000000000..05f579c08c
--- /dev/null
+++ b/engines/gob/detection/tables_fallback.h
@@ -0,0 +1,564 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_DETECTION_TABLES_FALLBACK_H
+#define GOB_DETECTION_TABLES_FALLBACK_H
+
+// -- Tables for the filename-based fallback --
+
+static const GOBGameDescription fallbackDescs[] = {
+ { //0
+ {
+ "gob1",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { //1
+ {
+ "gob1cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //2
+ {
+ "gob2",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //3
+ {
+ "gob2mac",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //4
+ {
+ "gob2cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //5
+ {
+ "bargon",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { //6
+ {
+ "gob3",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //7
+ {
+ "gob3cd",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //8
+ {
+ "woodruff",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //9
+ {
+ "lostintime",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //10
+ {
+ "lostintime",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+ },
+ { //11
+ {
+ "lostintime",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+ },
+ { //12
+ {
+ "urban",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+ },
+ { //13
+ {
+ "playtoons1",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //14
+ {
+ "playtoons2",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //15
+ {
+ "playtoons3",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //16
+ {
+ "playtoons4",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //17
+ {
+ "playtoons5",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //18
+ {
+ "playtoons construction kit",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //19
+ {
+ "bambou",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeBambou,
+ kFeatures640x480,
+ 0, 0, 0
+ },
+ { //20
+ {
+ "fascination",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+ },
+ { //21
+ {
+ "geisha",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA | kFeaturesAdLib,
+ "disk1.stk", "intro.tot", 0
+ },
+ { //22
+ {
+ "littlered",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { //23
+ {
+ "littlered",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesNone,
+ 0, 0, 0
+ },
+ { //24
+ {
+ "onceupon",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformUnknown,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeOnceUponATime,
+ kFeaturesEGA,
+ 0, 0, 0
+ },
+ { //25
+ {
+ "adi2",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeAdi2,
+ kFeatures640x480,
+ "adi2.stk", 0, 0
+ },
+ { //26
+ {
+ "adi4",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeAdi4,
+ kFeatures640x480,
+ "adif41.stk", 0, 0
+ },
+ { //27
+ {
+ "coktelplayer",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeaturesAdLib | kFeatures640x480 | kFeaturesSCNDemo,
+ "", "", 8
+ }
+};
+
+static const ADFileBasedFallback fileBased[] = {
+ { &fallbackDescs[ 0].desc, { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } },
+ { &fallbackDescs[ 1].desc, { "intro.stk", "gob.lic", 0 } },
+ { &fallbackDescs[ 2].desc, { "intro.stk", 0 } },
+ { &fallbackDescs[ 2].desc, { "intro.stk", "disk2.stk", "disk3.stk", 0 } },
+ { &fallbackDescs[ 3].desc, { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } },
+ { &fallbackDescs[ 4].desc, { "intro.stk", "gobnew.lic", 0 } },
+ { &fallbackDescs[ 5].desc, { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } },
+ { &fallbackDescs[ 6].desc, { "intro.stk", "imd.itk", 0 } },
+ { &fallbackDescs[ 7].desc, { "intro.stk", "mus_gob3.lic", 0 } },
+ { &fallbackDescs[ 8].desc, { "intro.stk", "woodruff.itk", 0 } },
+ { &fallbackDescs[ 9].desc, { "intro.stk", "commun1.itk", 0 } },
+ { &fallbackDescs[10].desc, { "intro.stk", "commun1.itk", "musmac1.mid", 0 } },
+ { &fallbackDescs[11].desc, { "intro.stk", "commun1.itk", "lost.lic", 0 } },
+ { &fallbackDescs[12].desc, { "intro.stk", "cd1.itk", "objet1.itk", 0 } },
+ { &fallbackDescs[13].desc, { "playtoon.stk", "archi.stk", 0 } },
+ { &fallbackDescs[14].desc, { "playtoon.stk", "spirou.stk", 0 } },
+ { &fallbackDescs[15].desc, { "playtoon.stk", "chato.stk", 0 } },
+ { &fallbackDescs[16].desc, { "playtoon.stk", "manda.stk", 0 } },
+ { &fallbackDescs[17].desc, { "playtoon.stk", "wakan.stk", 0 } },
+ { &fallbackDescs[18].desc, { "playtoon.stk", "dan.itk" } },
+ { &fallbackDescs[19].desc, { "intro.stk", "bambou.itk", 0 } },
+ { &fallbackDescs[20].desc, { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
+ { &fallbackDescs[21].desc, { "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
+ { &fallbackDescs[22].desc, { "intro.stk", "stk2.stk", "stk3.stk", 0 } },
+ { &fallbackDescs[23].desc, { "intro.stk", "stk2.stk", "stk3.stk", "mod.babayaga", 0 } },
+ { &fallbackDescs[24].desc, { "stk1.stk", "stk2.stk", "stk3.stk", 0 } },
+ { &fallbackDescs[25].desc, { "adi2.stk", 0 } },
+ { &fallbackDescs[26].desc, { "adif41.stk", "adim41.stk", 0 } },
+ { &fallbackDescs[27].desc, { "coktelplayer.scn", 0 } },
+ { 0, { 0 } }
+};
+
+// -- Tables for detecting the specific Once Upon A Time game --
+
+enum OnceUponATime {
+ kOnceUponATimeInvalid = -1,
+ kOnceUponATimeAbracadabra = 0,
+ kOnceUponATimeBabaYaga = 1,
+ kOnceUponATimeMAX
+};
+
+enum OnceUponATimePlatform {
+ kOnceUponATimePlatformInvalid = -1,
+ kOnceUponATimePlatformDOS = 0,
+ kOnceUponATimePlatformAmiga = 1,
+ kOnceUponATimePlatformAtariST = 2,
+ kOnceUponATimePlatformMAX
+};
+
+static const GOBGameDescription fallbackOnceUpon[kOnceUponATimeMAX][kOnceUponATimePlatformMAX] = {
+ { // kOnceUponATimeAbracadabra
+ { // kOnceUponATimePlatformDOS
+ {
+ "abracadabra",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // kOnceUponATimePlatformAmiga
+ {
+ "abracadabra",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // kOnceUponATimePlatformAtariST
+ {
+ "abracadabra",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+ }
+ },
+ { // kOnceUponATimeBabaYaga
+ { // kOnceUponATimePlatformDOS
+ {
+ "babayaga",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // kOnceUponATimePlatformAmiga
+ {
+ "babayaga",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+ },
+ { // kOnceUponATimePlatformAtariST
+ {
+ "babayaga",
+ "",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+ }
+ }
+};
+
+#endif // GOB_DETECTION_TABLES_FALLBACK_H
diff --git a/engines/gob/detection/tables_fascin.h b/engines/gob/detection/tables_fascin.h
new file mode 100644
index 0000000000..1c9cced303
--- /dev/null
+++ b/engines/gob/detection/tables_fascin.h
@@ -0,0 +1,267 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Fascination. */
+
+#ifndef GOB_DETECTION_TABLES_FASCIN_H
+#define GOB_DETECTION_TABLES_FASCIN_H
+
+// -- DOS VGA Floppy (1 disk) --
+
+{ // Supplied by scoriae
+ {
+ "fascination",
+ "VGA",
+ AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "VGA",
+ AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+},
+
+// -- DOS VGA Floppy (3 disks) --
+
+{ // Supplied by alex86r in bug report #3297633
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("disk0.stk", "ab3dfdce43917bc806812959d692fc8f", 1061929),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "Hebrew edition (censored)",
+ AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909),
+ HE_ISR,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "intro.stk", 0, 0
+},
+{ // Supplied by windlepoons in bug report #2809247
+ {
+ "fascination",
+ "VGA 3 disks edition",
+ AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesAdLib,
+ "disk0.stk", 0, 0
+},
+
+// -- DOS VGA CD --
+
+{
+ {
+ "fascination",
+ "CD Version (Censored)",
+ AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSUBTITLES)
+ },
+ kGameTypeFascination,
+ kFeaturesCD,
+ "intro.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "CD Version (Censored)",
+ AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSUBTITLES)
+ },
+ kGameTypeFascination,
+ kFeaturesCD,
+ "intro.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "CD Version (Censored)",
+ AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSUBTITLES)
+ },
+ kGameTypeFascination,
+ kFeaturesCD,
+ "intro.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "CD Version (Censored)",
+ AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSUBTITLES)
+ },
+ kGameTypeFascination,
+ kFeaturesCD,
+ "intro.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "CD Version (Censored)",
+ AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOSUBTITLES)
+ },
+ kGameTypeFascination,
+ kFeaturesCD,
+ "intro.stk", 0, 0
+},
+
+// -- Amiga --
+
+{
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005),
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+},
+{
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931),
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+},
+
+// -- Atari ST --
+
+{
+ {
+ "fascination",
+ "",
+ AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964),
+ EN_ANY,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeFascination,
+ kFeaturesNone,
+ "disk0.stk", 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_FASCIN_H
diff --git a/engines/gob/detection/tables_geisha.h b/engines/gob/detection/tables_geisha.h
new file mode 100644
index 0000000000..a32d1ebf81
--- /dev/null
+++ b/engines/gob/detection/tables_geisha.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Geisha. */
+
+#ifndef GOB_DETECTION_TABLES_GEISHA_H
+#define GOB_DETECTION_TABLES_GEISHA_H
+
+// -- DOS EGA Floppy --
+
+{
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA | kFeaturesAdLib,
+ "disk1.stk", "intro.tot", 0
+},
+{
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA | kFeaturesAdLib,
+ "disk1.stk", "intro.tot", 0
+},
+{ // Supplied by misterhands in bug report #3539797
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "0c4c16090921664f50baefdfd24d7f5d", 211889),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA | kFeaturesAdLib,
+ "disk1.stk", "intro.tot", 0
+},
+{ // Supplied by einstein95 in bug report #3544449
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "49107ac897e7c00af6c4ecd78a74a710", 212169),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA | kFeaturesAdLib,
+ "disk1.stk", "intro.tot", 0
+},
+{ // Supplied by einstein95 in bug report #3544449
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "49107ac897e7c00af6c4ecd78a74a710", 212169),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA | kFeaturesAdLib,
+ "disk1.stk", "intro.tot", 0
+},
+{
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA | kFeaturesAdLib,
+ "disk1.stk", "intro.tot", 0
+},
+
+// -- Amiga --
+
+{
+ {
+ "geisha",
+ "",
+ AD_ENTRY1s("disk1.stk", "e5892f00917c62423e93f5fd9920cf47", 208120),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGeisha,
+ kFeaturesEGA,
+ "disk1.stk", "intro.tot", 0
+},
+
+#endif // GOB_DETECTION_TABLES_GEISHA_H
diff --git a/engines/gob/detection/tables_gob1.h b/engines/gob/detection/tables_gob1.h
new file mode 100644
index 0000000000..e6086e990a
--- /dev/null
+++ b/engines/gob/detection/tables_gob1.h
@@ -0,0 +1,716 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Gobliiins. */
+
+#ifndef GOB_DETECTION_TABLES_GOB1_H
+#define GOB_DETECTION_TABLES_GOB1_H
+
+// -- DOS EGA Floppy --
+
+{ // Supplied by Florian Zeitz on scummvm-devel
+ {
+ "gob1",
+ "EGA",
+ AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesEGA | kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "EGA",
+ AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"),
+ RU_RUS,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesEGA | kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- DOS VGA Floppy --
+
+{ // Supplied by Theruler76 in bug report #1201233
+ {
+ "gob1",
+ "VGA",
+ AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by raziel_ in bug report #1891864
+ {
+ "gob1",
+ "VGA",
+ AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- DOS VGA CD --
+
+{ // Provided by pykman in the forums.
+ {
+ "gob1cd",
+ "Polish",
+ AD_ENTRY1s("intro.stk", "97d2443948b2e367cf567fe7e101f5f2", 4049267),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.000 version.
+ {
+ "gob1cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // CD 1.02 version. Multilingual
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob1cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesCD,
+ 0, 0, 0
+},
+
+// -- Mac --
+
+{ // Supplied by raina in the forums
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712),
+ EN_ANY,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ EN_ANY,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ DE_DEU,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ FR_FRA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ IT_ITA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by paul66 in bug report #1652352
+ {
+ "gob1",
+ "",
+ AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
+ ES_ESP,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Windows --
+
+{ // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "",
+ {
+ {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
+ {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "gob1",
+ "Demo",
+ AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "Interactive Demo",
+ AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2785958
+ {
+ "gob1",
+ "Interactive Demo",
+ AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "gob1",
+ "",
+ AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121),
+ FR_FRA,
+ kPlatformCDi,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob1,
+ kFeaturesAdLib,
+ 0, "AVT003.TOT", 0
+},
+
+#endif // GOB_DETECTION_TABLES_GOB1_H
diff --git a/engines/gob/detection/tables_gob2.h b/engines/gob/detection/tables_gob2.h
new file mode 100644
index 0000000000..659e6df063
--- /dev/null
+++ b/engines/gob/detection/tables_gob2.h
@@ -0,0 +1,641 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Gobliins 2: The Prince Buffoon. */
+
+#ifndef GOB_DETECTION_TABLES_GOB2_H
+#define GOB_DETECTION_TABLES_GOB2_H
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by raziel_ in bug report #1891867
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by blackwhiteeagle in bug report #1605235
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2602017
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"),
+ RU_RUS,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by arcepi in bug report #1659884
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- DOS VGA CD --
+
+{
+ {
+ "gob2cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by pykman in bug report #3067489
+ {
+ "gob2cd",
+ "v2.01 Polish",
+ AD_ENTRY1s("intro.stk", "3025f05482b646c18c2c79c615a3a1df", 5011726),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "gob2cd",
+ "v2.01",
+ AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob2cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+
+// -- Windows --
+
+{
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ EN_USA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ EN_USA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2 Francais-Maths CM1
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Mac --
+
+{ // Supplied by fac76 in bug report #1673397
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443},
+ {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
+ {0, 0, 0, 0}
+ },
+ UNK_LANG,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by koalet in bug report #2478585
+ {
+ "gob2",
+ "",
+ {
+ {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275},
+ {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Amiga --
+
+{ // Supplied by fac76 in bug report #1883808
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014),
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2602057
+ {
+ "gob2",
+ "",
+ AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"),
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by aldozx in the forums
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "abc3e786cd78197773954c75815b278b", 554721),
+ ES_ESP,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Atari ST --
+
+{ // Supplied by bgk in bug report #1706861
+ {
+ "gob2",
+ "",
+ AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680),
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "gob2",
+ "Non-Interactive Demo",
+ AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, "usa.tot", 0
+},
+{
+ {
+ "gob2",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob2",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by polluks in bug report #1895126
+ {
+ "gob2",
+ "Interactive Demo",
+ AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063),
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob2,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_GOB2_H
diff --git a/engines/gob/detection/tables_gob3.h b/engines/gob/detection/tables_gob3.h
new file mode 100644
index 0000000000..22ec69054b
--- /dev/null
+++ b/engines/gob/detection/tables_gob3.h
@@ -0,0 +1,564 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Goblins 3 / Goblins Quest 3. */
+
+#ifndef GOB_DETECTION_TABLES_GOB3_H
+#define GOB_DETECTION_TABLES_GOB3_H
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582),
+ HE_ISR,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by raziel_ in bug report #1891869
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by paul66 in bug report #1652352
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by Paranoimia on #scummvm
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"),
+ RU_RUS,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by SiRoCs in bug report #2098621
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Windows --
+
+{
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
+ {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in Found in french ADI 2.5 Anglais Multimedia 5e
+ {
+ "gob3",
+ "",
+ AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Mac --
+
+{ // Supplied by fac76 in bug report #1742716
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Amiga --
+
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
+ EN_GRB,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesNone,
+ 0, "menu.tot", 0
+},
+{
+ {
+ "gob3",
+ "",
+ AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesNone,
+ 0, "menu.tot", 0
+},
+
+// -- DOS VGA CD --
+
+{
+ {
+ "gob3cd",
+ "v1.000",
+ AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by pykman in bug report #3067489
+ {
+ "gob3cd",
+ "v1.02 Polish",
+ AD_ENTRY1s("intro.stk", "978afddcac81bb95a04757b61f78471c", 619825),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ HU_HUN,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2810082
+ {
+ "gob3cd",
+ "v1.02",
+ AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "gob3",
+ "Non-interactive Demo",
+ AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "Interactive Demo",
+ AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "Interactive Demo 2",
+ AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "gob3",
+ "Interactive Demo 3",
+ AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561),
+ EN_ANY,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeGob3,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_GOB3_H
diff --git a/engines/gob/detection/tables_inca2.h b/engines/gob/detection/tables_inca2.h
new file mode 100644
index 0000000000..26989f7d1a
--- /dev/null
+++ b/engines/gob/detection/tables_inca2.h
@@ -0,0 +1,249 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Inca II: Wiracocha. */
+
+#ifndef GOB_DETECTION_TABLES_INCA2_H
+#define GOB_DETECTION_TABLES_INCA2_H
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- DOS VGA CD --
+
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesCD,
+ 0, 0, 0
+},
+
+// -- Windows --
+
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ EN_USA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "inca2",
+ "Non-Interactive Demo",
+ {
+ {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804},
+ {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999},
+ {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871},
+ {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719},
+ {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609},
+ {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709},
+ {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250},
+ {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312},
+ {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637},
+ {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330},
+ {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeInca2,
+ kFeaturesAdLib | kFeaturesBATDemo,
+ 0, 0, 7
+},
+
+#endif // GOB_DETECTION_TABLES_INCA2_H
diff --git a/engines/gob/detection/tables_lit.h b/engines/gob/detection/tables_lit.h
new file mode 100644
index 0000000000..019d001f97
--- /dev/null
+++ b/engines/gob/detection/tables_lit.h
@@ -0,0 +1,484 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Lost in Time. */
+
+#ifndef GOB_DETECTION_TABLES_LIT_H
+#define GOB_DETECTION_TABLES_LIT_H
+
+// -- DOS VGA Floppy (Part I and II) --
+
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238),
+ HE_ISR,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by cartman_ on #scummvm
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2105220
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+{ // Supplied by SiRoCs in bug report #2093672
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ 0, 0, 0
+},
+
+// -- Windows (Part I and II) --
+
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Found in french ADI 2.6 Francais-Maths 4e
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Windows (Part I only) --
+{
+ {
+ "lit1",
+ "Light install",
+ {
+ {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
+ {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit1",
+ "Full install",
+ {
+ {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
+ {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Windows (Part II only) --
+
+{
+ {
+ "lit2",
+ "Light install",
+ AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "lit2",
+ "Full install",
+ {
+ {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318},
+ {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Mac (Part I and II) --
+
+{ // Supplied by koalet in bug report #2479034
+ {
+ "lit",
+ "",
+ {
+ {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310},
+ {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformMacintosh,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "lit",
+ "Demo",
+ AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ "demo.stk", "demo.tot", 0
+},
+{
+ {
+ "lit",
+ "Non-interactive Demo",
+ AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ "demo.stk", "demo.tot", 0
+},
+
+// -- Pirated! Do not re-add nor un-tag! --
+
+{
+ {
+ "lit",
+ "",
+ AD_ENTRY1s("intro.stk", "3712e7527ba8ce5637d2aadf62783005", 72318),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_PIRATED,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_LIT_H
diff --git a/engines/gob/detection/tables_littlered.h b/engines/gob/detection/tables_littlered.h
new file mode 100644
index 0000000000..2b41b65a71
--- /dev/null
+++ b/engines/gob/detection/tables_littlered.h
@@ -0,0 +1,265 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Once Upon A Time: Little Red Riding Hood. */
+
+#ifndef GOB_DETECTION_TABLES_LITTLERED_H
+#define GOB_DETECTION_TABLES_LITTLERED_H
+
+// -- DOS EGA Floppy --
+
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+
+// -- Windows --
+
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{ // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ FR_FRA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{ // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ ES_ESP,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{ // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ EN_GRB,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{ // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ IT_ITA,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{ // Found in french ADI 2 Francais-Maths CM1
+ {
+ "littlered",
+ "",
+ AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
+ DE_DEU,
+ kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+
+// -- Amiga --
+
+{
+ {
+ "littlered",
+ "",
+ {
+ {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490},
+ {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248},
+ {0, 0, 0, 0}
+ },
+ UNK_LANG,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeLittleRed,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_LITTLERED_H
diff --git a/engines/gob/detection/tables_onceupon.h b/engines/gob/detection/tables_onceupon.h
new file mode 100644
index 0000000000..366024d43c
--- /dev/null
+++ b/engines/gob/detection/tables_onceupon.h
@@ -0,0 +1,518 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Once Upon A Time: Baba Yaga and Abracadabra. */
+
+#ifndef GOB_DETECTION_TABLES_ONCEUPON_H
+#define GOB_DETECTION_TABLES_ONCEUPON_H
+
+// -- Once Upon A Time: Abracadabra, Amiga --
+
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "e4b21818af03930dc9cab2ad4c93cb5b", 362106},
+ {"stk3.stk", 0, "76874ad92782f9b2de57beafc05ec877", 353482},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "e4b21818af03930dc9cab2ad4c93cb5b", 362106},
+ {"stk3.stk", 0, "76874ad92782f9b2de57beafc05ec877", 353482},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "e4b21818af03930dc9cab2ad4c93cb5b", 362106},
+ {"stk3.stk", 0, "76874ad92782f9b2de57beafc05ec877", 353482},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "e4b21818af03930dc9cab2ad4c93cb5b", 362106},
+ {"stk3.stk", 0, "76874ad92782f9b2de57beafc05ec877", 353482},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "e4b21818af03930dc9cab2ad4c93cb5b", 362106},
+ {"stk3.stk", 0, "76874ad92782f9b2de57beafc05ec877", 353482},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+
+// -- Once Upon A Time: Abracadabra, Atari ST --
+
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "c6440aaf068ec3149ae89bc5c41ebf02", 362123},
+ {"stk3.stk", 0, "5af3c1202ba6fcf8dad2b2125e1c1383", 353257},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "c6440aaf068ec3149ae89bc5c41ebf02", 362123},
+ {"stk3.stk", 0, "5af3c1202ba6fcf8dad2b2125e1c1383", 353257},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "c6440aaf068ec3149ae89bc5c41ebf02", 362123},
+ {"stk3.stk", 0, "5af3c1202ba6fcf8dad2b2125e1c1383", 353257},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "c6440aaf068ec3149ae89bc5c41ebf02", 362123},
+ {"stk3.stk", 0, "5af3c1202ba6fcf8dad2b2125e1c1383", 353257},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "abracadabra",
+ "",
+ {
+ {"stk1.stk", 0, "a8e963eea170155548e5bc1d0f07d50d", 209806},
+ {"stk2.stk", 0, "c6440aaf068ec3149ae89bc5c41ebf02", 362123},
+ {"stk3.stk", 0, "5af3c1202ba6fcf8dad2b2125e1c1383", 353257},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeAbracadabra,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+
+// -- Once Upon A Time: Baba Yaga, DOS EGA Floppy --
+
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "3c777f43e6fb49fde9222543447e135a", 204813},
+ {"stk2.stk", 0, "6cf0b009dd185a8f589e91a1f9c33df5", 361582},
+ {"stk3.stk", 0, "6473183ca4db1b5b5cea047f9af59a26", 328925},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "3c777f43e6fb49fde9222543447e135a", 204813},
+ {"stk2.stk", 0, "6cf0b009dd185a8f589e91a1f9c33df5", 361582},
+ {"stk3.stk", 0, "6473183ca4db1b5b5cea047f9af59a26", 328925},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "3c777f43e6fb49fde9222543447e135a", 204813},
+ {"stk2.stk", 0, "6cf0b009dd185a8f589e91a1f9c33df5", 361582},
+ {"stk3.stk", 0, "6473183ca4db1b5b5cea047f9af59a26", 328925},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "3c777f43e6fb49fde9222543447e135a", 204813},
+ {"stk2.stk", 0, "6cf0b009dd185a8f589e91a1f9c33df5", 361582},
+ {"stk3.stk", 0, "6473183ca4db1b5b5cea047f9af59a26", 328925},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "3c777f43e6fb49fde9222543447e135a", 204813},
+ {"stk2.stk", 0, "6cf0b009dd185a8f589e91a1f9c33df5", 361582},
+ {"stk3.stk", 0, "6473183ca4db1b5b5cea047f9af59a26", 328925},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesAdLib | kFeaturesEGA,
+ 0, 0, 0
+},
+
+// -- Once Upon A Time: Baba Yaga, Amiga --
+
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "bcc823d2888057031e54716ed1b3c80e", 205090},
+ {"stk2.stk", 0, "f76bf7c2ff60d816d69962d1a593207c", 362122},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "bcc823d2888057031e54716ed1b3c80e", 205090},
+ {"stk2.stk", 0, "f76bf7c2ff60d816d69962d1a593207c", 362122},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "bcc823d2888057031e54716ed1b3c80e", 205090},
+ {"stk2.stk", 0, "f76bf7c2ff60d816d69962d1a593207c", 362122},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "bcc823d2888057031e54716ed1b3c80e", 205090},
+ {"stk2.stk", 0, "f76bf7c2ff60d816d69962d1a593207c", 362122},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "bcc823d2888057031e54716ed1b3c80e", 205090},
+ {"stk2.stk", 0, "f76bf7c2ff60d816d69962d1a593207c", 362122},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+
+// -- Once Upon A Time: Baba Yaga, Atari ST --
+
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "17a4e3e7a18cc97231c92d280c7878a1", 205095},
+ {"stk2.stk", 0, "bfbc380e5461f63af28e9e6b10f334b5", 362128},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "17a4e3e7a18cc97231c92d280c7878a1", 205095},
+ {"stk2.stk", 0, "bfbc380e5461f63af28e9e6b10f334b5", 362128},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "17a4e3e7a18cc97231c92d280c7878a1", 205095},
+ {"stk2.stk", 0, "bfbc380e5461f63af28e9e6b10f334b5", 362128},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "17a4e3e7a18cc97231c92d280c7878a1", 205095},
+ {"stk2.stk", 0, "bfbc380e5461f63af28e9e6b10f334b5", 362128},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+{
+ {
+ "babayaga",
+ "",
+ {
+ {"stk1.stk", 0, "17a4e3e7a18cc97231c92d280c7878a1", 205095},
+ {"stk2.stk", 0, "bfbc380e5461f63af28e9e6b10f334b5", 362128},
+ {"stk3.stk", 0, "6227d1aefdf39d88dcf83e38bea2a9af", 328922},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeBabaYaga,
+ kFeaturesEGA,
+ 0, 0, 0
+},
+
+#endif // GOB_DETECTION_TABLES_ONCEUPON_H
diff --git a/engines/gob/detection/tables_playtoons.h b/engines/gob/detection/tables_playtoons.h
new file mode 100644
index 0000000000..4eb5945b04
--- /dev/null
+++ b/engines/gob/detection/tables_playtoons.h
@@ -0,0 +1,517 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for the Playtoons series. */
+
+#ifndef GOB_DETECTION_TABLES_PLAYTOONS_H
+#define GOB_DETECTION_TABLES_PLAYTOONS_H
+
+// -- Playtoons 1: Uncle Archibald --
+
+{
+ {
+ "playtoons1",
+ "",
+ {
+ {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
+ {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons1",
+ "Pack mes histoires anim\xE9""es",
+ {
+ {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
+ {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons1",
+ "",
+ {
+ {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
+ {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{ // Supplied by scoriae in the forums
+ {
+ "playtoons1",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258},
+ {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210},
+ {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937},
+ {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228},
+ {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242},
+ {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719},
+ {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 3
+},
+{
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124},
+ {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 4
+},
+{
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"i.scn", 0, "8b3294474d39970463663edd22341730", 285},
+ {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533},
+ {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786},
+ {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
+ {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566},
+ {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 5
+},
+{
+ {
+ "playtoons1",
+ "Non-Interactive Demo",
+ {
+ {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251},
+ {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619},
+ {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838},
+ {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
+ {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
+ {0, 0, 0, 0}
+ },
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 6
+},
+
+// -- Playtoons 2: The Case of the Counterfeit Collaborator (Spirou) --
+
+{
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
+ {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154},
+ {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
+ {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{ // Supplied by Hkz
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "2572685400852d12759a2fbf09ec88eb", 9698780},
+ {"spirou.stk", 0, "d3cfeff920b6343a2ece55088f530dba", 7076608},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{ // Supplied by scoriae in the forums
+ {
+ "playtoons2",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+
+// -- Playtoons 3: The Secret of the Castle --
+
+{
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
+ {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons3",
+ "Pack mes histoires anim\xE9""es",
+ {
+ {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
+ {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
+ {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791},
+ {0, 0, 0, 0}
+ },
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "playtoons3",
+ "",
+ {
+ {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
+ {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+
+// -- Playtoons 4: The Mandarin Prince --
+
+{
+ {
+ "playtoons4",
+ "",
+ {
+ {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406},
+ {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+{ //Supplied by goodoldgeorg in bug report #2820006
+ {
+ "playtoons4",
+ "",
+ {
+ {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
+ {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+
+// -- Playtoons 5: The Stone of Wakan --
+
+{
+ {
+ "playtoons5",
+ "",
+ {
+ {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
+ {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+
+// -- Playtoons Construction Kit 1: Monsters --
+
+{
+ {
+ "playtnck1",
+ "",
+ {
+ {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+
+// -- Playtoons Construction Kit 2: Knights --
+
+{
+ {
+ "playtnck2",
+ "",
+ {
+ {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+
+// -- Playtoons Construction Kit 3: Far West --
+
+{
+ {
+ "playtnck3",
+ "",
+ {
+ {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
+ {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypePlaytoons,
+ kFeatures640x480,
+ "intro2.stk", 0, 0
+},
+
+// -- Bambou le sauveur de la jungle --
+
+{
+ {
+ "bambou",
+ "",
+ {
+ {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238},
+ {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192},
+ {0, 0, 0, 0}
+ },
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeBambou,
+ kFeatures640x480,
+ "intro.stk", "intro.tot", 0
+},
+
+#endif // GOB_DETECTION_TABLES_PLAYTOONS_H
diff --git a/engines/gob/detection/tables_urban.h b/engines/gob/detection/tables_urban.h
new file mode 100644
index 0000000000..d24f6a5011
--- /dev/null
+++ b/engines/gob/detection/tables_urban.h
@@ -0,0 +1,151 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Urban Runner. */
+
+#ifndef GOB_DETECTION_TABLES_URBAN_H
+#define GOB_DETECTION_TABLES_URBAN_H
+
+// -- Windows --
+
+{
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+},
+{ // Supplied by Collector9 in bug report #3228040
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "6ce3d878178932053267237ec4843ce1", 1252518),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+},
+{ // Supplied by gamin in the forums
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+},
+{ // Supplied by jvprat on #scummvm
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+},
+{ // Supplied by Alex on the gobsmacked blog
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "9ea647085a16dd0fb9ecd84cd8778ec9", 1253436),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+},
+{ // Supplied by alex86r in bug report #3297602
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "4e4a3c017fe5475353bf94c455fe3efd", 1253448),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2770340
+ {
+ "urban",
+ "",
+ AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "urban",
+ "Non-Interactive Demo",
+ {
+ {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87},
+ {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237},
+ {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOASPECT)
+ },
+ kGameTypeUrban,
+ kFeatures640x480 | kFeaturesTrueColor | kFeaturesSCNDemo,
+ 0, 0, 2
+},
+
+#endif // GOB_DETECTION_TABLES_URBAN_H
diff --git a/engines/gob/detection/tables_ween.h b/engines/gob/detection/tables_ween.h
new file mode 100644
index 0000000000..a02b931b85
--- /dev/null
+++ b/engines/gob/detection/tables_ween.h
@@ -0,0 +1,349 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for Ween: The Prophecy. */
+
+#ifndef GOB_DETECTION_TABLES_WEEN_H
+#define GOB_DETECTION_TABLES_WEEN_H
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by cybot_tmin in bug report #1667743
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by cartman_ on #scummvm
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by glorfindel in bugreport #1722142
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Amiga --
+
+{ // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719),
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458),
+ FR_FRA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by vampir_raziel in bug report #1658373
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192),
+ DE_DEU,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2563539
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458},
+ {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
+ {0, 0, 0, 0}
+ },
+ IT_ITA,
+ kPlatformAmiga,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- Atari ST --
+
+{ // Supplied by pwigren in bug report #1764174
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446},
+ {0, 0, 0, 0}
+ },
+ EN_GRB,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+},
+{
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"),
+ FR_FRA,
+ kPlatformAtariST,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
+ 0, 0, 0
+},
+
+// -- DOS VGA Floppy --
+
+{
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568),
+ EN_USA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by cybot_tmin in bug report #1667743
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by cartman_ on #scummvm
+ {
+ "ween",
+ "",
+ AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+{ // Supplied by glorfindel in bugreport #1722142
+ {
+ "ween",
+ "",
+ AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "ween",
+ "Demo",
+ AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"),
+ UNK_LANG,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, "show.tot", 0
+},
+{
+ {
+ "ween",
+ "Demo",
+ AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"),
+ EN_USA,
+ kPlatformPC,
+ ADGF_DEMO,
+ GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
+ },
+ kGameTypeWeen,
+ kFeaturesAdLib,
+ 0, "show.tot", 0
+},
+
+#endif // GOB_DETECTION_TABLES_WEEN_H
diff --git a/engines/gob/detection/tables_woodruff.h b/engines/gob/detection/tables_woodruff.h
new file mode 100644
index 0000000000..e369539984
--- /dev/null
+++ b/engines/gob/detection/tables_woodruff.h
@@ -0,0 +1,402 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* Detection tables for (The Bizarre Adventures of) Woodruff and the Schnibble (of Azimuth). */
+
+#ifndef GOB_DETECTION_TABLES_WOODRUFF_H
+#define GOB_DETECTION_TABLES_WOODRUFF_H
+
+// -- Windows CD --
+
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ EN_GRB,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ ES_ESP,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+{ // Supplied by goodoldgeorg in bug report #2098838
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979),
+ PL_POL,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480,
+ 0, 0, 0
+},
+
+// -- Demos --
+
+{
+ {
+ "woodruff",
+ "Non-Interactive Demo",
+ {
+ {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89},
+ {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
+ {0, 0, 0, 0}
+ },
+ EN_ANY,
+ kPlatformPC,
+ ADGF_NO_FLAGS,
+ GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
+ },
+ kGameTypeWoodruff,
+ kFeatures640x480 | kFeaturesSCNDemo,
+ 0, 0, 1
+},
+
+#endif // GOB_DETECTION_TABLES_WOODRUFF_H
diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h
deleted file mode 100644
index 7aa58b9b97..0000000000
--- a/engines/gob/detection_tables.h
+++ /dev/null
@@ -1,5276 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-namespace Gob {
-
-static const GOBGameDescription gameDescriptions[] = {
- { // Supplied by Florian Zeitz on scummvm-devel
- {
- "gob1",
- "EGA",
- AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "EGA",
- AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"),
- RU_RUS,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesEGA,
- 0, 0, 0
- },
- { // Supplied by Theruler76 in bug report #1201233
- {
- "gob1",
- "VGA",
- AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by raziel_ in bug report #1891864
- {
- "gob1",
- "VGA",
- AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by raina in the forums
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712),
- EN_ANY,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- EN_ANY,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- DE_DEU,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- FR_FRA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- IT_ITA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob1",
- "",
- AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"),
- ES_ESP,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- {
- {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972},
- {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Provided by pykman in the forums.
- {
- "gob1cd",
- "Polish",
- AD_ENTRY1s("intro.stk", "97d2443948b2e367cf567fe7e101f5f2", 4049267),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.000 version.
- {
- "gob1cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // CD 1.02 version. Multilingual
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- HU_HUN,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob1cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "Demo",
- AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"),
- UNK_LANG,
- kPlatformAmiga,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "Interactive Demo",
- AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2785958
- {
- "gob1",
- "Interactive Demo",
- AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob1",
- "",
- AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121),
- FR_FRA,
- kPlatformCDi,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesAdLib,
- 0, "AVT003.TOT", 0
- },
- { // Supplied by fac76 in bug report #1883808
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2602057
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"),
- IT_ITA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by aldozx in the forums
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "abc3e786cd78197773954c75815b278b", 554721),
- ES_ESP,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by bgk in bug report #1706861
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680),
- FR_FRA,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by fac76 in bug report #1673397
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443},
- {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
- {0, 0, 0, 0}
- },
- UNK_LANG,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by koalet in bug report #2478585
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275},
- {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by raziel_ in bug report #1891867
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by blackwhiteeagle in bug report #1605235
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2602017
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"),
- RU_RUS,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by arcepi in bug report #1659884
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- EN_USA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- EN_USA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "",
- {
- {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob2",
- "",
- AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by pykman in bug report #3067489
- {
- "gob2cd",
- "v2.01 Polish",
- AD_ENTRY1s("intro.stk", "3025f05482b646c18c2c79c615a3a1df", 5011726),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2cd",
- "v2.01",
- AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- HU_HUN,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob2cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "Non-Interactive Demo",
- AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, "usa.tot", 0
- },
- {
- {
- "gob2",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob2",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"),
- UNK_LANG,
- kPlatformAmiga,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by polluks in bug report #1895126
- {
- "gob2",
- "Interactive Demo",
- AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063),
- UNK_LANG,
- kPlatformAmiga,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- {
- {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
- {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719),
- FR_FRA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458),
- FR_FRA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by vampir_raziel in bug report #1658373
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2563539
- {
- "ween",
- "",
- {
- {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458},
- {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by pwigren in bug report #1764174
- {
- "ween",
- "",
- {
- {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
- {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"),
- FR_FRA,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by cybot_tmin in bug report #1667743
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by cartman_ on #scummvm
- {
- "ween",
- "",
- AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by glorfindel in bugreport #1722142
- {
- "ween",
- "",
- AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "ween",
- "Demo",
- AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, "show.tot", 0
- },
- {
- {
- "ween",
- "Demo",
- AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"),
- EN_USA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeWeen,
- kFeaturesAdLib,
- 0, "show.tot", 0
- },
- {
- {
- "bargon",
- "",
- AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by Trekky in the forums
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109),
- FR_FRA,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by cesardark in bug #1681649
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug #1692667
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by pwigren in bugreport #1764174
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by kizkoool in bugreport #2089734
- {
- "bargon",
- "",
- AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { // Supplied by glorfindel in bugreport #1722142
- {
- "bargon",
- "Fanmade",
- AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- {
- {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490},
- {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248},
- {0, 0, 0, 0}
- },
- UNK_LANG,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- {
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
- { // Found in french ADI 2 Francais-Maths CM1
- {
- "littlered",
- "",
- AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib | kFeaturesEGA,
- 0, 0, 0
- },
-// This version is not detected on purpose: it's a pirated version.
-// Tagged ADGF_PIRATED! Do not re-add nor un-tag!
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "3712e7527ba8ce5637d2aadf62783005", 72318),
- FR_FRA,
- kPlatformPC,
- ADGF_PIRATED,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238),
- HE_ISR,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by cartman_ on #scummvm
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2105220
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by koalet in bug report #2479034
- {
- "lit",
- "",
- {
- {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310},
- {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2093672
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in french ADI 2.6 Francais-Maths 4e
- {
- "lit",
- "",
- AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit1",
- "Full install",
- {
- {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
- {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit1",
- "Light install",
- {
- {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318},
- {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit2",
- "Light install",
- AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit2",
- "Full install",
- {
- {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318},
- {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "lit",
- "Demo",
- AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- "demo.stk", "demo.tot", 0
- },
- {
- {
- "lit",
- "Non-interactive Demo",
- AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- "demo.stk", "demo.tot", 0
- },
- { // Supplied by scoriae
- {
- "fascination",
- "VGA",
- AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- { // Supplied by alex86r in bug report #3297633
- {
- "fascination",
- "VGA 3 disks edition",
- AD_ENTRY1s("disk0.stk", "ab3dfdce43917bc806812959d692fc8f", 1061929),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "VGA 3 disks edition",
- AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "Hebrew edition (censored)",
- AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909),
- HE_ISR,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "intro.stk", 0, 0
- },
- { // Supplied by windlepoons in bug report #2809247
- {
- "fascination",
- "VGA 3 disks edition",
- AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "VGA",
- AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesAdLib,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005),
- FR_FRA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931),
- IT_ITA,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "",
- AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964),
- EN_ANY,
- kPlatformAtariST,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- {
- {
- "fascination",
- "CD Version (Censored)",
- AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOSUBTITLES)
- },
- kGameTypeFascination,
- kFeaturesCD,
- "intro.stk", 0, 0
- },
- {
- {
- "fascination",
- "CD Version (Censored)",
- AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOSUBTITLES)
- },
- kGameTypeFascination,
- kFeaturesCD,
- "intro.stk", 0, 0
- },
- {
- {
- "fascination",
- "CD Version (Censored)",
- AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOSUBTITLES)
- },
- kGameTypeFascination,
- kFeaturesCD,
- "intro.stk", 0, 0
- },
- {
- {
- "fascination",
- "CD Version (Censored)",
- AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOSUBTITLES)
- },
- kGameTypeFascination,
- kFeaturesCD,
- "intro.stk", 0, 0
- },
- {
- {
- "fascination",
- "CD Version (Censored)",
- AD_ENTRY1s("intro.stk", "9c61e9c22077f72921f07153e37ccf01", 545953),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOSUBTITLES)
- },
- kGameTypeFascination,
- kFeaturesCD,
- "intro.stk", 0, 0
- },
- {
- {
- "geisha",
- "",
- AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGeisha,
- kFeaturesEGA | kFeaturesAdLib,
- "disk1.stk", "intro.tot", 0
- },
- {
- {
- "geisha",
- "",
- AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGeisha,
- kFeaturesEGA | kFeaturesAdLib,
- "disk1.stk", "intro.tot", 0
- },
- {
- {
- "geisha",
- "",
- AD_ENTRY1s("disk1.stk", "e5892f00917c62423e93f5fd9920cf47", 208120),
- UNK_LANG,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGeisha,
- kFeaturesEGA,
- "disk1.stk", "intro.tot", 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582),
- HE_ISR,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by raziel_ in bug report #1891869
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by fac76 in bug report #1742716
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084},
- {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by paul66 in bug report #1652352
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by Paranoimia on #scummvm
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"),
- RU_RUS,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Supplied by SiRoCs in bug report #2098621
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
- EN_GRB,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesNone,
- 0, "menu.tot", 0
- },
- {
- {
- "gob3",
- "",
- AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"),
- DE_DEU,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesNone,
- 0, "menu.tot", 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "",
- {
- {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420},
- {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { // Found in Found in french ADI 2.5 Anglais Multimedia 5e
- {
- "gob3",
- "",
- AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3cd",
- "v1.000",
- AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by pykman in bug report #3067489
- {
- "gob3cd",
- "v1.02 Polish",
- AD_ENTRY1s("intro.stk", "978afddcac81bb95a04757b61f78471c", 619825),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- HU_HUN,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2810082
- {
- "gob3cd",
- "v1.02",
- AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Interactive Demo",
- AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Interactive Demo 2",
- AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Interactive Demo 3",
- AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561),
- EN_ANY,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "gob3",
- "Non-interactive Demo",
- AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"),
- UNK_LANG,
- kPlatformPC,
- ADGF_DEMO,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesCD,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- EN_USA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- DE_DEU,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- IT_ITA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- ES_ESP,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "",
- AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612),
- FR_FRA,
- kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "inca2",
- "Non-Interactive Demo",
- {
- {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804},
- {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999},
- {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871},
- {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719},
- {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609},
- {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709},
- {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250},
- {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312},
- {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637},
- {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330},
- {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeInca2,
- kFeaturesAdLib | kFeaturesBATDemo,
- 0, 0, 7
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by DjDiabolik in bug report #1971294
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2098838
- {
- "woodruff",
- "",
- AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979),
- PL_POL,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "woodruff",
- "Non-Interactive Demo",
- {
- {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89},
- {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 1
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "",
- AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "Demo",
- AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864),
- EN_USA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "dynasty",
- "Demo",
- AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774),
- UNK_LANG,
- kPlatformWindows,
- ADGF_DEMO,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- "lda1.stk", 0, 0
- },
- {
- {
- "dynasty",
- "Demo",
- AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724),
- DE_DEU,
- kPlatformWindows,
- ADGF_DEMO,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeDynasty,
- kFeatures640x480,
- "lda1.stk", 0, 0
- },
- {
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- { // Supplied by Collector9 in bug report #3228040
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "6ce3d878178932053267237ec4843ce1", 1252518),
- EN_USA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- { // Supplied by gamin in the forums
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- { // Supplied by jvprat on #scummvm
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- { // Supplied by Alex on the gobsmacked blog
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "9ea647085a16dd0fb9ecd84cd8778ec9", 1253436),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- { // Supplied by alex86r in bug report #3297602
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "4e4a3c017fe5475353bf94c455fe3efd", 1253448),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- { // Supplied by goodoldgeorg in bug report #2770340
- {
- "urban",
- "",
- AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- {
- {
- "urban",
- "Non-Interactive Demo",
- {
- {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87},
- {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237},
- {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor | kFeaturesSCNDemo,
- 0, 0, 2
- },
- {
- {
- "playtoons1",
- "",
- {
- {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
- {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons1",
- "Pack mes histoires anim\xE9""es",
- {
- {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
- {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons1",
- "",
- {
- {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
- {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- { // Supplied by scoriae in the forums
- {
- "playtoons1",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258},
- {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210},
- {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937},
- {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228},
- {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242},
- {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719},
- {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 3
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124},
- {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 4
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"i.scn", 0, "8b3294474d39970463663edd22341730", 285},
- {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533},
- {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786},
- {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
- {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566},
- {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 5
- },
- {
- {
- "playtoons1",
- "Non-Interactive Demo",
- {
- {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251},
- {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619},
- {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838},
- {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970},
- {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250},
- {0, 0, 0, 0}
- },
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 6
- },
- {
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
- {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154},
- {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
- {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- { // Supplied by Hkz
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "2572685400852d12759a2fbf09ec88eb", 9698780},
- {"spirou.stk", 0, "d3cfeff920b6343a2ece55088f530dba", 7076608},
- {0, 0, 0, 0}
- },
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- { // Supplied by scoriae in the forums
- {
- "playtoons2",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338},
- {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "Pack mes histoires anim\xE9""es",
- {
- {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
- {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926},
- {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- { // Supplied by Hkz on #scummvm
- {
- "playtoons3",
- "",
- {
- {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262},
- {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons4",
- "",
- {
- {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406},
- {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- { //Supplied by goodoldgeorg in bug report #2820006
- {
- "playtoons4",
- "",
- {
- {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506},
- {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtoons5",
- "",
- {
- {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474},
- {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "bambou",
- "",
- {
- {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238},
- {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeBambou,
- kFeatures640x480,
- "intro.stk", "intro.tot", 0
- },
- {
- {
- "playtnck1",
- "",
- {
- {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
- {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtnck2",
- "",
- {
- {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
- {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "playtnck3",
- "",
- {
- {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024},
- {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- "intro2.stk", 0, 0
- },
- {
- {
- "adi2",
- "Adi 2.0 for Teachers",
- AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdi2,
- kFeaturesNone,
- "adi2.stk", "ediintro.tot", 0
- },
- { // Found in french ADI 2 Francais-Maths CM1. Exact version not specified.
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified.
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132),
- EN_ANY,
- kPlatformAmiga,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdi2,
- kFeaturesNone,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2",
- AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132),
- ES_ESP,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.5",
- AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.5",
- AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.6",
- AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.6",
- AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Adi 2.7.1",
- AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", "ediintro.tot", 0
- },
- {
- {
- "adi2",
- "Non-Interactive Demo",
- {
- {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168},
- {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723},
- {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731},
- {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511},
- {0, 0, 0, 0}
- },
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 1
- },
- {
- {
- "adi4",
- "Addy 4 Grundschule Basis CD",
- AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Addy 4 Sekundarstufe Basis CD",
- AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0",
- AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0",
- AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0",
- AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0 Limited Edition",
- AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.10",
- AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144),
- EN_GRB,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.10",
- AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.11",
- AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Addy 4.21",
- AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "ADI 4.21",
- AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0 Interactive Demo",
- AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "adi4",
- "Adi 4.0 / Adibou 2 Demo",
- AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0),
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- 0, 0, 0
- },
- {
- {
- "ajworld",
- "",
- AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628),
- EN_ANY,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "adibou1",
- "ADIBOU 1 Environnement 4-7 ans",
- AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeAdibou1,
- kFeaturesAdLib,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2",
- AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "Le Jardin Magique d'Adibou",
- AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2",
- AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
- DE_DEU,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIB\xD9 2",
- AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
- IT_ITA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU Version Decouverte",
- AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.10 Environnement",
- AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.11 Environnement",
- AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.12 Environnement",
- AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOU 2.13s Environnement",
- AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "ADIBOO 2.14 Environnement",
- AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874),
- FR_FRA,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO0()
- },
- kGameTypeAdibou2,
- kFeaturesNone,
- 0, 0, 0
- },
- {
- {
- "adibou2",
- "Non-Interactive Demo",
- {
- {"demogb.scn", 0, "9291455a908ac0e6aaaca686e532609b", 105},
- {"demogb.vmd", 0, "bc9c1db97db7bec8f566332444fa0090", 14320840},
- {0, 0, 0, 0}
- },
- EN_GRB,
- kPlatformPC,
- ADGF_DEMO,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeAdibou2,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 9
- },
- {
- {
- "adibou2",
- "Non-Interactive Demo",
- {
- {"demoall.scn", 0, "c8fd308c037b829800006332b2c32674", 106},
- {"demoall.vmd", 0, "4672b2deacc6fca97484840424b1921b", 14263433},
- {0, 0, 0, 0}
- },
- DE_DEU,
- kPlatformPC,
- ADGF_DEMO,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeAdibou2,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 10
- },
- {
- {
- "adibou2",
- "Non-Interactive Demo",
- {
- {"demofra.scn", 0, "d1b2b1618af384ea1120def8b986c02b", 106},
- {"demofra.vmd", 0, "b494cdec1aac7e54c3f2480512d2880e", 14297100},
- {0, 0, 0, 0}
- },
- FR_FRA,
- kPlatformPC,
- ADGF_DEMO,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeAdibou2,
- kFeatures640x480 | kFeaturesSCNDemo,
- 0, 0, 11
- },
- { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0}
-};
-
-static const GOBGameDescription fallbackDescs[] = {
- { //0
- {
- "gob1",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesNone,
- 0, 0, 0
- },
- { //1
- {
- "gob1cd",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob1,
- kFeaturesCD,
- 0, 0, 0
- },
- { //2
- {
- "gob2",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //3
- {
- "gob2mac",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //4
- {
- "gob2cd",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob2,
- kFeaturesCD,
- 0, 0, 0
- },
- { //5
- {
- "bargon",
- "",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeBargon,
- kFeaturesNone,
- 0, 0, 0
- },
- { //6
- {
- "gob3",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //7
- {
- "gob3cd",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGob3,
- kFeaturesCD,
- 0, 0, 0
- },
- { //8
- {
- "woodruff",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeWoodruff,
- kFeatures640x480,
- 0, 0, 0
- },
- { //9
- {
- "lostintime",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //10
- {
- "lostintime",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformMacintosh,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesAdLib,
- 0, 0, 0
- },
- { //11
- {
- "lostintime",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeLostInTime,
- kFeaturesCD,
- 0, 0, 0
- },
- { //12
- {
- "urban",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeatures640x480 | kFeaturesTrueColor,
- 0, 0, 0
- },
- { //13
- {
- "playtoons1",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- 0, 0, 0
- },
- { //14
- {
- "playtoons2",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- 0, 0, 0
- },
- { //15
- {
- "playtoons3",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- 0, 0, 0
- },
- { //16
- {
- "playtoons4",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- 0, 0, 0
- },
- { //17
- {
- "playtoons5",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- 0, 0, 0
- },
- { //18
- {
- "playtoons construction kit",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypePlaytoons,
- kFeatures640x480,
- 0, 0, 0
- },
- { //19
- {
- "bambou",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeBambou,
- kFeatures640x480,
- 0, 0, 0
- },
- { //20
- {
- "fascination",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeFascination,
- kFeaturesNone,
- "disk0.stk", 0, 0
- },
- { //21
- {
- "geisha",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSUBTITLES, GUIO_NOSPEECH)
- },
- kGameTypeGeisha,
- kFeaturesEGA,
- "disk1.stk", "intro.tot", 0
- },
- { //22
- {
- "adi2",
- "",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeAdi2,
- kFeatures640x480,
- "adi2.stk", 0, 0
- },
- { //23
- {
- "adi4",
- "",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO3(GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOASPECT)
- },
- kGameTypeAdi4,
- kFeatures640x480,
- "adif41.stk", 0, 0
- },
- { //24
- {
- "coktelplayer",
- "unknown",
- AD_ENTRY1(0, 0),
- UNK_LANG,
- kPlatformPC,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- kGameTypeUrban,
- kFeaturesAdLib | kFeatures640x480 | kFeaturesSCNDemo,
- "", "", 8
- }
-};
-
-static const ADFileBasedFallback fileBased[] = {
- { &fallbackDescs[ 0].desc, { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } },
- { &fallbackDescs[ 1].desc, { "intro.stk", "gob.lic", 0 } },
- { &fallbackDescs[ 2].desc, { "intro.stk", 0 } },
- { &fallbackDescs[ 2].desc, { "intro.stk", "disk2.stk", "disk3.stk", 0 } },
- { &fallbackDescs[ 3].desc, { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } },
- { &fallbackDescs[ 4].desc, { "intro.stk", "gobnew.lic", 0 } },
- { &fallbackDescs[ 5].desc, { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } },
- { &fallbackDescs[ 6].desc, { "intro.stk", "imd.itk", 0 } },
- { &fallbackDescs[ 7].desc, { "intro.stk", "mus_gob3.lic", 0 } },
- { &fallbackDescs[ 8].desc, { "intro.stk", "woodruff.itk", 0 } },
- { &fallbackDescs[ 9].desc, { "intro.stk", "commun1.itk", 0 } },
- { &fallbackDescs[10].desc, { "intro.stk", "commun1.itk", "musmac1.mid", 0 } },
- { &fallbackDescs[11].desc, { "intro.stk", "commun1.itk", "lost.lic", 0 } },
- { &fallbackDescs[12].desc, { "intro.stk", "cd1.itk", "objet1.itk", 0 } },
- { &fallbackDescs[13].desc, { "playtoon.stk", "archi.stk", 0 } },
- { &fallbackDescs[14].desc, { "playtoon.stk", "spirou.stk", 0 } },
- { &fallbackDescs[15].desc, { "playtoon.stk", "chato.stk", 0 } },
- { &fallbackDescs[16].desc, { "playtoon.stk", "manda.stk", 0 } },
- { &fallbackDescs[17].desc, { "playtoon.stk", "wakan.stk", 0 } },
- { &fallbackDescs[18].desc, { "playtoon.stk", "dan.itk" } },
- { &fallbackDescs[19].desc, { "intro.stk", "bambou.itk", 0 } },
- { &fallbackDescs[20].desc, { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
- { &fallbackDescs[21].desc, { "disk1.stk", "disk2.stk", "disk3.stk", 0 } },
- { &fallbackDescs[22].desc, { "adi2.stk", 0 } },
- { &fallbackDescs[23].desc, { "adif41.stk", "adim41.stk", 0 } },
- { &fallbackDescs[24].desc, { "coktelplayer.scn", 0 } },
- { 0, { 0 } }
-};
-
-}
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index 4b659f51de..8c6919416d 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -117,6 +117,15 @@ Draw::Draw(GobEngine *vm) : _vm(vm) {
_cursorAnimDelays[i] = 0;
}
+ _cursorCount = 0;
+ _doCursorPalettes = 0;
+ _cursorPalettes = 0;
+ _cursorKeyColors = 0;
+ _cursorPaletteStarts = 0;
+ _cursorPaletteCounts = 0;
+ _cursorHotspotsX = 0;
+ _cursorHotspotsY = 0;
+
_palLoadData1[0] = 0;
_palLoadData1[1] = 17;
_palLoadData1[2] = 34;
@@ -134,6 +143,14 @@ Draw::Draw(GobEngine *vm) : _vm(vm) {
}
Draw::~Draw() {
+ delete[] _cursorPalettes;
+ delete[] _doCursorPalettes;
+ delete[] _cursorKeyColors;
+ delete[] _cursorPaletteStarts;
+ delete[] _cursorPaletteCounts;
+ delete[] _cursorHotspotsX;
+ delete[] _cursorHotspotsY;
+
for (int i = 0; i < kFontCount; i++)
delete _fonts[i];
}
@@ -239,7 +256,7 @@ void Draw::blitInvalidated() {
if (_cursorIndex == 4)
blitCursor();
- if (_vm->_inter->_terminate)
+ if (_vm->_inter && _vm->_inter->_terminate)
return;
if (_noInvalidated && !_applyPal)
@@ -254,7 +271,9 @@ void Draw::blitInvalidated() {
return;
}
- _showCursor = (_showCursor & ~2) | ((_showCursor & 1) << 1);
+ if (_cursorSprites)
+ _showCursor = (_showCursor & ~2) | ((_showCursor & 1) << 1);
+
if (_applyPal) {
clearPalette();
forceBlit();
@@ -408,28 +427,13 @@ int Draw::stringLength(const char *str, uint16 fontIndex) {
return len;
}
-void Draw::drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2,
- int16 transp, Surface &dest, const Font &font) {
-
- while (*str != '\0') {
- const int16 charRight = x + font.getCharWidth(*str);
- const int16 charBottom = y + font.getCharHeight();
-
- if ((charRight <= dest.getWidth()) && (charBottom <= dest.getHeight()))
- font.drawLetter(dest, *str, x, y, color1, color2, transp);
-
- x += font.getCharWidth(*str);
- str++;
- }
-}
-
void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right,
int16 bottom, const char *str, int16 fontIndex, int16 color) {
adjustCoords(1, &left, &top);
adjustCoords(1, &right, &bottom);
- uint16 centerOffset = _vm->_game->_script->getFunctionOffset(TOTFile::kFunctionCenter);
+ uint16 centerOffset = _vm->_game->_script ? _vm->_game->_script->getFunctionOffset(TOTFile::kFunctionCenter) : 0;
if (centerOffset != 0) {
_vm->_game->_script->call(centerOffset);
@@ -488,7 +492,7 @@ void Draw::oPlaytoons_sub_F_1B(uint16 id, int16 left, int16 top, int16 right, in
adjustCoords(1, &left, &top);
adjustCoords(1, &right, &bottom);
- uint16 centerOffset = _vm->_game->_script->getFunctionOffset(TOTFile::kFunctionCenter);
+ uint16 centerOffset = _vm->_game->_script ? _vm->_game->_script->getFunctionOffset(TOTFile::kFunctionCenter) : 0;
if (centerOffset != 0) {
_vm->_game->_script->call(centerOffset);
diff --git a/engines/gob/draw.h b/engines/gob/draw.h
index 393822c33a..b51c6466e0 100644
--- a/engines/gob/draw.h
+++ b/engines/gob/draw.h
@@ -32,7 +32,8 @@ namespace Gob {
#define RENDERFLAG_COLLISIONS 0x0004
#define RENDERFLAG_CAPTUREPOP 0x0008
#define RENDERFLAG_USEDELTAS 0x0010
-#define RENDERFLAG_UNKNOWN 0x0080
+#define RENDERFLAG_BORDERHOTSPOTS 0x0040
+#define RENDERFLAG_HASWINDOWS 0x0080
#define RENDERFLAG_NOBLITINVALIDATED 0x0200
#define RENDERFLAG_NOSUBTITLES 0x0400
#define RENDERFLAG_FROMSPLIT 0x0800
@@ -145,6 +146,15 @@ public:
int8 _cursorAnimHigh[40];
int8 _cursorAnimDelays[40];
+ int32 _cursorCount;
+ bool *_doCursorPalettes;
+ byte *_cursorPalettes;
+ byte *_cursorKeyColors;
+ uint16 *_cursorPaletteStarts;
+ uint16 *_cursorPaletteCounts;
+ int32 *_cursorHotspotsX;
+ int32 *_cursorHotspotsY;
+
int16 _palLoadData1[4];
int16 _palLoadData2[4];
@@ -184,8 +194,6 @@ public:
adjustCoords(adjust, (int16 *)coord1, (int16 *)coord2);
}
int stringLength(const char *str, uint16 fontIndex);
- void drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2,
- int16 transp, Surface &dest, const Font &font);
void printTextCentered(int16 id, int16 left, int16 top, int16 right,
int16 bottom, const char *str, int16 fontIndex, int16 color);
void oPlaytoons_sub_F_1B( uint16 id, int16 left, int16 top, int16 right, int16 bottom, char *paramStr, int16 var3, int16 var4, int16 shortId);
@@ -249,6 +257,8 @@ public:
private:
uint8 _mayorWorkaroundStatus;
+
+ void fixLittleRedStrings();
};
class Draw_Bargon: public Draw_v2 {
diff --git a/engines/gob/draw_fascin.cpp b/engines/gob/draw_fascin.cpp
index 69e04f74c9..12009d7ee5 100644
--- a/engines/gob/draw_fascin.cpp
+++ b/engines/gob/draw_fascin.cpp
@@ -222,8 +222,8 @@ void Draw_Fascination::spriteOperation(int16 operation) {
_destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency);
}
} else {
- drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor,
- _backColor, _transparency, *_spritesArray[_destSurface], *font);
+ font->drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor,
+ _backColor, _transparency, *_spritesArray[_destSurface]);
_destSpriteX += len * font->getCharWidth();
}
} else {
@@ -747,7 +747,7 @@ int16 Draw_Fascination::openWin(int16 id) {
int16 Draw_Fascination::getWinFromCoord(int16 &dx, int16 &dy) {
int16 bestMatch = -1;
- if ((_renderFlags & 128) == 0)
+ if (!(_renderFlags & RENDERFLAG_HASWINDOWS))
return -1;
for (int i = 0; i < 10; i++) {
@@ -790,7 +790,7 @@ int16 Draw_Fascination::handleCurWin() {
int8 matchNum = 0;
int16 bestMatch = -1;
- if ((_vm->_game->_mouseButtons != 1) || ((_renderFlags & 128) == 0))
+ if ((_vm->_game->_mouseButtons != 1) || !(_renderFlags & RENDERFLAG_HASWINDOWS))
return 0;
for (int i = 0; i < 10; i++) {
diff --git a/engines/gob/draw_playtoons.cpp b/engines/gob/draw_playtoons.cpp
index a443f81ccf..76e2ae591c 100644
--- a/engines/gob/draw_playtoons.cpp
+++ b/engines/gob/draw_playtoons.cpp
@@ -283,8 +283,8 @@ void Draw_Playtoons::spriteOperation(int16 operation) {
_destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency);
}
} else {
- drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor,
- _backColor, _transparency, *_spritesArray[_destSurface], *font);
+ font->drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor,
+ _backColor, _transparency, *_spritesArray[_destSurface]);
_destSpriteX += len * font->getCharWidth();
}
} else {
diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp
index fb15fdbc19..878c1dc265 100644
--- a/engines/gob/draw_v1.cpp
+++ b/engines/gob/draw_v1.cpp
@@ -123,7 +123,7 @@ void Draw_v1::animateCursor(int16 cursor) {
(cursorIndex + 1) * _cursorWidth - 1,
_cursorHeight - 1, 0, 0);
CursorMan.replaceCursor(_scummvmCursor->getData(),
- _cursorWidth, _cursorHeight, hotspotX, hotspotY, 0, 1, &_vm->getPixelFormat());
+ _cursorWidth, _cursorHeight, hotspotX, hotspotY, 0, false, &_vm->getPixelFormat());
if (_frontSurface != _backSurface) {
_showCursor = 3;
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index 78702f2ec9..f5475278c4 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -74,16 +74,19 @@ void Draw_v2::closeScreen() {
}
void Draw_v2::blitCursor() {
- if (_cursorIndex == -1)
+ if (!_cursorSprites || (_cursorIndex == -1))
return;
_showCursor = (_showCursor & ~2) | ((_showCursor & 1) << 1);
}
void Draw_v2::animateCursor(int16 cursor) {
+ if (!_cursorSprites)
+ return;
+
int16 cursorIndex = cursor;
int16 newX = 0, newY = 0;
- uint16 hotspotX = 0, hotspotY = 0;
+ uint16 hotspotX, hotspotY;
_showCursor |= 1;
@@ -133,27 +136,42 @@ void Draw_v2::animateCursor(int16 cursor) {
}
// '------
- newX = _vm->_global->_inter_mouseX;
- newY = _vm->_global->_inter_mouseY;
+ hotspotX = 0;
+ hotspotY = 0;
+
if (_cursorHotspotXVar != -1) {
- newX -= hotspotX = (uint16) VAR(_cursorIndex + _cursorHotspotXVar);
- newY -= hotspotY = (uint16) VAR(_cursorIndex + _cursorHotspotYVar);
+ hotspotX = (uint16) VAR(_cursorIndex + _cursorHotspotXVar);
+ hotspotY = (uint16) VAR(_cursorIndex + _cursorHotspotYVar);
} else if (_cursorHotspotX != -1) {
- newX -= hotspotX = _cursorHotspotX;
- newY -= hotspotY = _cursorHotspotY;
+ hotspotX = _cursorHotspotX;
+ hotspotY = _cursorHotspotY;
+ } else if (_cursorHotspotsX != 0) {
+ hotspotX = _cursorHotspotsX[_cursorIndex];
+ hotspotY = _cursorHotspotsY[_cursorIndex];
}
+ newX = _vm->_global->_inter_mouseX - hotspotX;
+ newY = _vm->_global->_inter_mouseY - hotspotY;
+
_scummvmCursor->clear();
_scummvmCursor->blit(*_cursorSprites,
cursorIndex * _cursorWidth, 0,
(cursorIndex + 1) * _cursorWidth - 1,
_cursorHeight - 1, 0, 0);
- if ((_vm->getGameType() != kGameTypeAdibou2) &&
- (_vm->getGameType() != kGameTypeAdi2) &&
- (_vm->getGameType() != kGameTypeAdi4))
- CursorMan.replaceCursor(_scummvmCursor->getData(),
- _cursorWidth, _cursorHeight, hotspotX, hotspotY, 0, 1, &_vm->getPixelFormat());
+ uint32 keyColor = 0;
+ if (_doCursorPalettes && _cursorKeyColors && _doCursorPalettes[cursorIndex])
+ keyColor = _cursorKeyColors[cursorIndex];
+
+ CursorMan.replaceCursor(_scummvmCursor->getData(),
+ _cursorWidth, _cursorHeight, hotspotX, hotspotY, keyColor, false, &_vm->getPixelFormat());
+
+ if (_doCursorPalettes && _doCursorPalettes[cursorIndex]) {
+ CursorMan.replaceCursorPalette(_cursorPalettes + (cursorIndex * 256 * 3),
+ _cursorPaletteStarts[cursorIndex], _cursorPaletteCounts[cursorIndex]);
+ CursorMan.disableCursorPalette(false);
+ } else
+ CursorMan.disableCursorPalette(true);
if (_frontSurface != _backSurface) {
if (!_noInvalidated) {
@@ -790,6 +808,10 @@ void Draw_v2::spriteOperation(int16 operation) {
break;
case DRAW_PRINTTEXT:
+ // WORKAROUND: There's mistakes in Little Red's animal names.
+ // See this function for details.
+ fixLittleRedStrings();
+
len = strlen(_textToPrint);
left = _destSpriteX;
@@ -812,8 +834,8 @@ void Draw_v2::spriteOperation(int16 operation) {
getColor(_backColor), _transparency);
}
} else {
- drawString(_textToPrint, _destSpriteX, _destSpriteY, getColor(_frontColor),
- getColor(_backColor), _transparency, *_spritesArray[_destSurface], *font);
+ font->drawString(_textToPrint, _destSpriteX, _destSpriteY, getColor(_frontColor),
+ getColor(_backColor), _transparency, *_spritesArray[_destSurface]);
_destSpriteX += len * font->getCharWidth();
}
} else {
@@ -918,4 +940,39 @@ void Draw_v2::spriteOperation(int16 operation) {
}
}
+/* WORKAROUND: Fix wrong German animal names in Once Upon A Time: Little Red Riding Hood.
+ *
+ * The DOS, Amiga and Atari version of Little Red come with a small screen, accessible
+ * through the main menu, that lets children read and listen to animal names in 5
+ * languages: French, German, English, Spanish and Italian.
+ * Unfortunately, the German names are partially wrong. This is especially tragic
+ * because this is a game for small children and they're supposed to learn something
+ * here. We fix this.
+ *
+ * However, there's also problems with the recorded spoken German names:
+ * - "Der Rabe" has a far too short "a", sounding more like "Rabbe"
+ * - The wrong article for "Schmetterling" is very audible
+ * - In general, the words are way too overpronounced
+ * These are, of course, way harder to fix.
+ */
+
+static const char *kLittleRedStrings[][2] = {
+ {"die Heule" , "die Eule"},
+ {"das Schmetterling" , "der Schmetterling"},
+ {"die Vespe" , "die Wespe"},
+ {"das Eich\224rnchen" , "das Eichh\224rnchen"}
+};
+
+void Draw_v2::fixLittleRedStrings() {
+ if (!_textToPrint || (_vm->getGameType() != kGameTypeLittleRed))
+ return;
+
+ for (int i = 0; i < ARRAYSIZE(kLittleRedStrings); i++) {
+ if (!strcmp(_textToPrint, kLittleRedStrings[i][0])) {
+ _textToPrint = kLittleRedStrings[i][1];
+ return;
+ }
+ }
+}
+
} // End of namespace Gob
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 502a440005..de0c3f2d5c 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -64,7 +64,7 @@ void Environments::clear() {
// Deleting unique variables, script and resources
for (uint i = 0; i < kEnvironmentCount; i++) {
- if (_environments[i].variables == _vm->_inter->_variables)
+ if (_vm->_inter && (_environments[i].variables == _vm->_inter->_variables))
continue;
if (!has(_environments[i].variables, i + 1))
@@ -167,6 +167,13 @@ bool Environments::has(Resources *resources, uint8 startEnv, int16 except) const
return false;
}
+void Environments::deleted(Variables *variables) {
+ for (uint i = 0; i < kEnvironmentCount; i++) {
+ if (_environments[i].variables == variables)
+ _environments[i].variables = 0;
+ }
+}
+
bool Environments::clearMedia(uint8 env) {
if (env >= kEnvironmentCount)
return false;
@@ -947,6 +954,10 @@ void Game::switchTotSub(int16 index, int16 function) {
_environments.get(_curEnvironment);
}
+void Game::deletedVars(Variables *variables) {
+ _environments.deleted(variables);
+}
+
void Game::clearUnusedEnvironment() {
if (!_environments.has(_script)) {
delete _script;
diff --git a/engines/gob/game.h b/engines/gob/game.h
index b3057ac262..995baa5629 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -52,6 +52,8 @@ public:
bool has(Script *script , uint8 startEnv = 0, int16 except = -1) const;
bool has(Resources *resources, uint8 startEnv = 0, int16 except = -1) const;
+ void deleted(Variables *variables);
+
void clear();
bool setMedia(uint8 env);
@@ -169,6 +171,8 @@ public:
void totSub(int8 flags, const Common::String &totFile);
void switchTotSub(int16 index, int16 function);
+ void deletedVars(Variables *variables);
+
bool loadFunctions(const Common::String &tot, uint16 flags);
bool callFunction(const Common::String &tot, const Common::String &function, int16 param);
diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp
index 1264c09860..87656a5fad 100644
--- a/engines/gob/global.cpp
+++ b/engines/gob/global.cpp
@@ -111,7 +111,6 @@ Global::Global(GobEngine *vm) : _vm(vm) {
_dontSetPalette = false;
_debugFlag = 0;
- _inVM = 0;
_inter_animDataSize = 10;
diff --git a/engines/gob/global.h b/engines/gob/global.h
index fa2f2c9637..175331dd83 100644
--- a/engines/gob/global.h
+++ b/engines/gob/global.h
@@ -127,7 +127,6 @@ public:
SurfacePtr _primarySurfDesc;
int16 _debugFlag;
- int16 _inVM;
int16 _inter_animDataSize;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 4e7aa467b5..fcf98f0355 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -48,6 +48,10 @@
#include "gob/videoplayer.h"
#include "gob/save/saveload.h"
+#include "gob/pregob/pregob.h"
+#include "gob/pregob/onceupon/abracadabra.h"
+#include "gob/pregob/onceupon/babayaga.h"
+
namespace Gob {
#define MAX_TIME_DELTA 100
@@ -115,7 +119,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst), _rnd("gob") {
_vidPlayer = 0; _init = 0; _inter = 0;
_map = 0; _palAnim = 0; _scenery = 0;
_draw = 0; _util = 0; _video = 0;
- _saveLoad = 0;
+ _saveLoad = 0; _preGob = 0;
_pauseStart = 0;
@@ -180,6 +184,10 @@ void GobEngine::validateVideoMode(int16 videoMode) {
error("Video mode 0x%X is not supported", videoMode);
}
+EndiannessMethod GobEngine::getEndiannessMethod() const {
+ return _endiannessMethod;
+}
+
Endianness GobEngine::getEndianness() const {
if ((getPlatform() == Common::kPlatformAmiga) ||
(getPlatform() == Common::kPlatformMacintosh) ||
@@ -233,6 +241,10 @@ bool GobEngine::isDemo() const {
return (isSCNDemo() || isBATDemo());
}
+bool GobEngine::hasResourceSizeWorkaround() const {
+ return _resourceSizeWorkaround;
+}
+
bool GobEngine::isCurrentTot(const Common::String &tot) const {
return _game->_curTotFile.equalsIgnoreCase(tot);
}
@@ -270,15 +282,15 @@ void GobEngine::setTrueColor(bool trueColor) {
}
Common::Error GobEngine::run() {
- if (!initGameParts()) {
- GUIErrorMessage("GobEngine::init(): Unknown version of game engine");
- return Common::kUnknownError;
- }
+ Common::Error err;
- if (!initGraphics()) {
- GUIErrorMessage("GobEngine::init(): Failed to set up graphics");
- return Common::kUnknownError;
- }
+ err = initGameParts();
+ if (err.getCode() != Common::kNoError)
+ return err;
+
+ err = initGraphics();
+ if (err.getCode() != Common::kNoError)
+ return err;
// On some systems it's not safe to run CD audio games from the CD.
if (isCD())
@@ -364,11 +376,12 @@ void GobEngine::pauseEngineIntern(bool pause) {
_game->_startTimeKey += duration;
_draw->_cursorTimeKey += duration;
- if (_inter->_soundEndTimeKey != 0)
+ if (_inter && (_inter->_soundEndTimeKey != 0))
_inter->_soundEndTimeKey += duration;
}
- _vidPlayer->pauseAll(pause);
+ if (_vidPlayer)
+ _vidPlayer->pauseAll(pause);
_mixer->pauseAll(pause);
}
@@ -388,10 +401,13 @@ void GobEngine::pauseGame() {
pauseEngineIntern(false);
}
-bool GobEngine::initGameParts() {
+Common::Error GobEngine::initGameParts() {
+ _resourceSizeWorkaround = false;
+
// just detect some devices some of which will be always there if the music is not disabled
_noMusic = MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB)) == MT_NULL ? true : false;
- _saveLoad = 0;
+
+ _endiannessMethod = kEndiannessMethodSystem;
_global = new Global(this);
_util = new Util(this);
@@ -423,6 +439,8 @@ bool GobEngine::initGameParts() {
_goblin = new Goblin_v1(this);
_scenery = new Scenery_v1(this);
_saveLoad = new SaveLoad_Geisha(this, _targetName.c_str());
+
+ _endiannessMethod = kEndiannessMethodAltFile;
break;
case kGameTypeFascination:
@@ -462,6 +480,33 @@ bool GobEngine::initGameParts() {
_saveLoad = new SaveLoad_v2(this, _targetName.c_str());
break;
+ case kGameTypeLittleRed:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_LittleRed(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+
+ // WORKAROUND: Little Red Riding Hood has a small resource size glitch in the
+ // screen where Little Red needs to find the animals' homes.
+ _resourceSizeWorkaround = true;
+ break;
+
+ case kGameTypeAJWorld:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_AJWorld(this, _targetName.c_str());
+ break;
+
case kGameTypeGob3:
_init = new Init_v3(this);
_video = new Video_v2(this);
@@ -572,20 +617,45 @@ bool GobEngine::initGameParts() {
_scenery = new Scenery_v2(this);
_saveLoad = new SaveLoad_v2(this, _targetName.c_str());
break;
+
+ case kGameTypeAbracadabra:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _preGob = new OnceUpon::Abracadabra(this);
+ break;
+
+ case kGameTypeBabaYaga:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _preGob = new OnceUpon::BabaYaga(this);
+ break;
+
default:
deinitGameParts();
- return false;
+ return Common::kUnsupportedGameidError;
}
// Setup mixer
syncSoundSettings();
- _inter->setupOpcodes();
+ if (_inter)
+ _inter->setupOpcodes();
- return true;
+ return Common::kNoError;
}
void GobEngine::deinitGameParts() {
+ delete _preGob; _preGob = 0;
delete _saveLoad; _saveLoad = 0;
delete _mult; _mult = 0;
delete _vidPlayer; _vidPlayer = 0;
@@ -604,10 +674,10 @@ void GobEngine::deinitGameParts() {
delete _dataIO; _dataIO = 0;
}
-bool GobEngine::initGraphics() {
+Common::Error GobEngine::initGraphics() {
if (is800x600()) {
warning("GobEngine::initGraphics(): 800x600 games currently unsupported");
- return false;
+ return Common::kUnsupportedGameidError;
} else if (is640x480()) {
_width = 640;
_height = 480;
@@ -631,7 +701,7 @@ bool GobEngine::initGraphics() {
_global->_primarySurfDesc = SurfacePtr(new Surface(_width, _height, _pixelFormat.bytesPerPixel));
- return true;
+ return Common::kNoError;
}
} // End of namespace Gob
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index ea2323807a..df73404596 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -50,6 +50,11 @@ class StaticTextWidget;
* - Bargon Attack
* - Lost in Time
* - The Bizarre Adventures of Woodruff and the Schnibble
+ * - Fascination
+ * - Urban Runner
+ * - Bambou le sauveur de la jungle
+ * - Geisha
+ * - Once Upon A Time: Little Red Riding Hood
*/
namespace Gob {
@@ -70,6 +75,7 @@ class Scenery;
class Util;
class SaveLoad;
class GobConsole;
+class PreGob;
#define WRITE_VAR_UINT32(var, val) _vm->_inter->_variables->writeVar32(var, val)
#define WRITE_VAR_UINT16(var, val) _vm->_inter->_variables->writeVar16(var, val)
@@ -123,7 +129,12 @@ enum GameType {
kGameTypeAdi2,
kGameTypeAdi4,
kGameTypeAdibou2,
- kGameTypeAdibou1
+ kGameTypeAdibou1,
+ kGameTypeAbracadabra,
+ kGameTypeBabaYaga,
+ kGameTypeLittleRed,
+ kGameTypeOnceUponATime, // Need more inspection to see if Baba Yaga or Abracadabra
+ kGameTypeAJWorld
};
enum Features {
@@ -138,6 +149,13 @@ enum Features {
kFeaturesTrueColor = 1 << 7
};
+enum EndiannessMethod {
+ kEndiannessMethodLE, ///< Always little endian.
+ kEndiannessMethodBE, ///< Always big endian.
+ kEndiannessMethodSystem, ///< Follows system endianness.
+ kEndiannessMethodAltFile ///< Different endianness in alternate file.
+};
+
enum {
kDebugFuncOp = 1 << 0,
kDebugDrawOp = 1 << 1,
@@ -161,6 +179,8 @@ private:
int32 _features;
Common::Platform _platform;
+ EndiannessMethod _endiannessMethod;
+
uint32 _pauseStart;
// Engine APIs
@@ -169,10 +189,10 @@ private:
virtual void pauseEngineIntern(bool pause);
virtual void syncSoundSettings();
- bool initGameParts();
- void deinitGameParts();
+ Common::Error initGameParts();
+ Common::Error initGraphics();
- bool initGraphics();
+ void deinitGameParts();
public:
static const Common::Language _gobToScummVMLang[];
@@ -195,6 +215,8 @@ public:
GobConsole *_console;
+ bool _resourceSizeWorkaround;
+
Global *_global;
Util *_util;
DataIO *_dataIO;
@@ -211,6 +233,7 @@ public:
Inter *_inter;
SaveLoad *_saveLoad;
VideoPlayer *_vidPlayer;
+ PreGob *_preGob;
const char *getLangDesc(int16 language) const;
void validateLanguage();
@@ -218,6 +241,7 @@ public:
void pauseGame();
+ EndiannessMethod getEndiannessMethod() const;
Endianness getEndianness() const;
Common::Platform getPlatform() const;
GameType getGameType() const;
@@ -231,6 +255,8 @@ public:
bool isTrueColor() const;
bool isDemo() const;
+ bool hasResourceSizeWorkaround() const;
+
bool isCurrentTot(const Common::String &tot) const;
void setTrueColor(bool trueColor);
diff --git a/engines/gob/hotspots.cpp b/engines/gob/hotspots.cpp
index 9a89f11923..ecab9bb906 100644
--- a/engines/gob/hotspots.cpp
+++ b/engines/gob/hotspots.cpp
@@ -532,34 +532,46 @@ void Hotspots::leave(uint16 index) {
call(spot.funcLeave);
}
-int16 Hotspots::curWindow(int16 &dx, int16 &dy) const {
- if ((_vm->_draw->_renderFlags & 0x80)==0)
- return(0);
+int16 Hotspots::windowCursor(int16 &dx, int16 &dy) const {
+ if (!(_vm->_draw->_renderFlags & RENDERFLAG_HASWINDOWS))
+ return 0;
+
for (int i = 0; i < 10; i++) {
- if (_vm->_draw->_fascinWin[i].id != -1) {
- if (_vm->_global->_inter_mouseX >= _vm->_draw->_fascinWin[i].left &&
- _vm->_global->_inter_mouseX < _vm->_draw->_fascinWin[i].left + _vm->_draw->_fascinWin[i].width &&
- _vm->_global->_inter_mouseY >= _vm->_draw->_fascinWin[i].top &&
- _vm->_global->_inter_mouseY < _vm->_draw->_fascinWin[i].top + _vm->_draw->_fascinWin[i].height) {
- if (_vm->_draw->_fascinWin[i].id == _vm->_draw->_winCount-1) {
- dx = _vm->_draw->_fascinWin[i].left;
- dy = _vm->_draw->_fascinWin[i].top;
- if (_vm->_global->_inter_mouseX < _vm->_draw->_fascinWin[i].left + 12 &&
- _vm->_global->_inter_mouseY < _vm->_draw->_fascinWin[i].top + 12 &&
- (VAR((_vm->_draw->_winVarArrayStatus / 4) + i) & 2))
- // Cursor on 'Close Window'
- return(5);
- if (_vm->_global->_inter_mouseX >= _vm->_draw->_fascinWin[i].left + _vm->_draw->_fascinWin[i].width - 12 &&
- _vm->_global->_inter_mouseY < _vm->_draw->_fascinWin[i].top + 12 &&
- (VAR((_vm->_draw->_winVarArrayStatus / 4) + i) & 4))
- // Cursor on 'Move Window'
- return(6);
- return(-i);
- }
- }
- }
+ if (_vm->_draw->_fascinWin[i].id == -1)
+ // No such windows
+ continue;
+
+ const int left = _vm->_draw->_fascinWin[i].left;
+ const int top = _vm->_draw->_fascinWin[i].top;
+ const int right = _vm->_draw->_fascinWin[i].left + _vm->_draw->_fascinWin[i].width - 1;
+ const int bottom = _vm->_draw->_fascinWin[i].top + _vm->_draw->_fascinWin[i].height - 1;
+
+ if ((_vm->_global->_inter_mouseX < left) || (_vm->_global->_inter_mouseX > right) ||
+ (_vm->_global->_inter_mouseY < top ) || (_vm->_global->_inter_mouseY > bottom))
+ // We're not inside that window
+ continue;
+
+ if (_vm->_draw->_fascinWin[i].id != (_vm->_draw->_winCount - 1))
+ // Only consider the top-most window
+ continue;
+
+ dx = _vm->_draw->_fascinWin[i].left;
+ dy = _vm->_draw->_fascinWin[i].top;
+
+ if ((_vm->_global->_inter_mouseX < (left + 12)) && (_vm->_global->_inter_mouseY < (top + 12)) &&
+ (VAR((_vm->_draw->_winVarArrayStatus / 4) + i) & 2))
+ // Cursor on 'Close Window'
+ return 5;
+
+ if ((_vm->_global->_inter_mouseX > (right - 12)) & (_vm->_global->_inter_mouseY < (top + 12)) &&
+ (VAR((_vm->_draw->_winVarArrayStatus / 4) + i) & 4))
+ // Cursor on 'Move Window'
+ return 6;
+
+ return -1;
}
- return(0);
+
+ return 0;
}
uint16 Hotspots::checkMouse(Type type, uint16 &id, uint16 &index) const {
@@ -1226,13 +1238,13 @@ void Hotspots::evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs,
ids[i] = 0;
// Type and window
- byte type = _vm->_game->_script->readByte();
+ byte type = _vm->_game->_script->readByte();
byte windowNum = 0;
if ((type & 0x40) != 0) {
// Got a window ID
- type -= 0x40;
+ type -= 0x40;
windowNum = _vm->_game->_script->readByte();
}
@@ -1254,31 +1266,31 @@ void Hotspots::evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs,
width = _vm->_game->_script->readUint16();
height = _vm->_game->_script->readUint16();
}
- if (_vm->_draw->_renderFlags & 64) {
- _vm->_draw->_invalidatedTops[0] = 0;
- _vm->_draw->_invalidatedLefts[0] = 0;
- _vm->_draw->_invalidatedRights[0] = 319;
- _vm->_draw->_invalidatedBottoms[0] = 199;
- _vm->_draw->_invalidatedCount = 1;
+ type &= 0x7F;
+
+ // Draw a border around the hotspot
+ if (_vm->_draw->_renderFlags & RENDERFLAG_BORDERHOTSPOTS) {
+ Surface &surface = *_vm->_draw->_spritesArray[_vm->_draw->_destSurface];
+
+ _vm->_video->dirtyRectsAll();
+
if (windowNum == 0) {
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left + width - 1, top, left + width - 1, top + height - 1, 0);
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left, top + height - 1, 0);
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left + width - 1, top, 0);
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top + height - 1, left + width - 1, top + height - 1, 0);
+ // The hotspot is not inside a window, just draw border it
+ surface.drawRect(left, top, left + width - 1, top + height - 1, 0);
+
} else {
- if ((_vm->_draw->_fascinWin[windowNum].id != -1) && (_vm->_draw->_fascinWin[windowNum].id == _vm->_draw->_winCount - 1)) {
- left += _vm->_draw->_fascinWin[windowNum].left;
- top += _vm->_draw->_fascinWin[windowNum].top;
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left + width - 1, top, left + width - 1, top + height - 1, 0);
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left, top + height - 1, 0);
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left + width - 1, top, 0);
- _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top + height - 1, left + width - 1, top + height - 1, 0);
- left -= _vm->_draw->_fascinWin[windowNum].left;
- top -= _vm->_draw->_fascinWin[windowNum].top;
+ // The hotspot is inside a window, only draw it if it's the topmost window
+
+ if ((_vm->_draw->_fascinWin[windowNum].id != -1) &&
+ (_vm->_draw->_fascinWin[windowNum].id == (_vm->_draw->_winCount - 1))) {
+
+ const uint16 wLeft = left + _vm->_draw->_fascinWin[windowNum].left;
+ const uint16 wTop = top + _vm->_draw->_fascinWin[windowNum].top;
+
+ surface.drawRect(wLeft, wTop, wLeft + width - 1, wTop + height - 1, 0);
}
}
}
- type &= 0x7F;
// Apply global drawing offset
if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) {
@@ -1667,38 +1679,19 @@ int16 Hotspots::findCursor(uint16 x, uint16 y) const {
int16 deltax = 0;
int16 deltay = 0;
- if (_vm->getGameType() == kGameTypeFascination)
- cursor = curWindow(deltax, deltay);
+ // Fascination uses hard-coded windows
+ if (_vm->getGameType() == kGameTypeFascination) {
+ cursor = windowCursor(deltax, deltay);
- if (cursor == 0) {
- for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) {
- const Hotspot &spot = _hotspots[i];
+ // We're in a window and in an area that forces a specific cursor
+ if (cursor > 0)
+ return cursor;
- if ((spot.getWindow() != 0) || spot.isDisabled())
- // Ignore disabled and non-main-windowed hotspots
- continue;
-
- if (!spot.isIn(x, y))
- // We're not in that hotspot, ignore it
- continue;
-
- if (spot.getCursor() == 0) {
- // Hotspot doesn't itself specify a cursor...
- if (spot.getType() >= kTypeInput1NoLeave) {
- // ...but the type has a generic one
- cursor = 3;
- break;
- } else if ((spot.getButton() != kMouseButtonsRight) && (cursor == 0))
- // ...but there's a generic "click" cursor
- cursor = 1;
- } else if (cursor == 0)
- // Hotspot had an attached cursor index
- cursor = spot.getCursor();
- }
- } else {
+ // We're somewhere else inside a window
if (cursor < 0) {
- int16 curType = - cursor * 256;
+ int16 curType = -cursor * 256;
cursor = 0;
+
for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) {
const Hotspot &spot = _hotspots[i];
// this check is /really/ Fascination specific.
@@ -1712,10 +1705,40 @@ int16 Hotspots::findCursor(uint16 x, uint16 y) const {
break;
}
}
+
+ if (_vm->_draw->_cursorAnimLow[cursor] == -1)
+ // If the cursor is invalid... there's a generic "click" cursor
+ cursor = 1;
+
+ return cursor;
}
- if (_vm->_draw->_cursorAnimLow[cursor] == -1)
- // If the cursor is invalid... there's a generic "click" cursor
- cursor = 1;
+
+ }
+
+ // Normal, non-window cursor handling
+ for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) {
+ const Hotspot &spot = _hotspots[i];
+
+ if ((spot.getWindow() != 0) || spot.isDisabled())
+ // Ignore disabled and non-main-windowed hotspots
+ continue;
+
+ if (!spot.isIn(x, y))
+ // We're not in that hotspot, ignore it
+ continue;
+
+ if (spot.getCursor() == 0) {
+ // Hotspot doesn't itself specify a cursor...
+ if (spot.getType() >= kTypeInput1NoLeave) {
+ // ...but the type has a generic one
+ cursor = 3;
+ break;
+ } else if ((spot.getButton() != kMouseButtonsRight) && (cursor == 0))
+ // ...but there's a generic "click" cursor
+ cursor = 1;
+ } else if (cursor == 0)
+ // Hotspot had an attached cursor index
+ cursor = spot.getCursor();
}
return cursor;
diff --git a/engines/gob/hotspots.h b/engines/gob/hotspots.h
index b348f9cd70..bd7b281c10 100644
--- a/engines/gob/hotspots.h
+++ b/engines/gob/hotspots.h
@@ -202,8 +202,8 @@ private:
/** Handling hotspot leave events. */
void leave(uint16 index);
- /** Which window is the mouse cursor currently in? (Fascination) */
- int16 curWindow(int16 &dx, int16 &dy) const;
+ /** Check whether a specific part of the window forces a certain cursor. */
+ int16 windowCursor(int16 &dx, int16 &dy) const;
/** Which hotspot is the mouse cursor currently at? */
uint16 checkMouse(Type type, uint16 &id, uint16 &index) const;
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index a61261f355..814d4d1821 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -34,9 +34,13 @@
#include "gob/inter.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
+
+#include "gob/sound/sound.h"
+
#include "gob/demos/scnplayer.h"
#include "gob/demos/batplayer.h"
-#include "gob/sound/sound.h"
+
+#include "gob/pregob/pregob.h"
namespace Gob {
@@ -118,6 +122,14 @@ void Init::initGame() {
return;
}
+ if (_vm->_preGob) {
+ _vm->_preGob->run();
+ delete _palDesc;
+ _vm->_video->initPrimary(-1);
+ cleanup();
+ return;
+ }
+
Common::SeekableReadStream *infFile = _vm->_dataIO->getFile("intro.inf");
if (!infFile) {
diff --git a/engines/gob/init.h b/engines/gob/init.h
index 946a3fa4f1..ac460fd654 100644
--- a/engines/gob/init.h
+++ b/engines/gob/init.h
@@ -62,7 +62,6 @@ public:
~Init_Geisha();
void initVideo();
- void initGame();
};
class Init_v2 : public Init_v1 {
diff --git a/engines/gob/init_fascin.cpp b/engines/gob/init_fascin.cpp
index b87d816406..e6d82faa68 100644
--- a/engines/gob/init_fascin.cpp
+++ b/engines/gob/init_fascin.cpp
@@ -44,10 +44,10 @@ void Init_Fascination::updateConfig() {
}
void Init_Fascination::initGame() {
-// HACK - Suppress ADLIB_FLAG as the MDY/TBR player is not working. suppress
-// the PC Speaker too, as the script checks in the intro for it's presence
+// HACK - Suppress
+// the PC Speaker, as the script checks in the intro for it's presence
// to play or not some noices.
- _vm->_global->_soundFlags = MIDI_FLAG | BLASTER_FLAG;
+ _vm->_global->_soundFlags = MIDI_FLAG | BLASTER_FLAG | ADLIB_FLAG;
Init::initGame();
}
diff --git a/engines/gob/init_geisha.cpp b/engines/gob/init_geisha.cpp
index b5bbcff400..01081a5af6 100644
--- a/engines/gob/init_geisha.cpp
+++ b/engines/gob/init_geisha.cpp
@@ -44,11 +44,4 @@ void Init_Geisha::initVideo() {
_vm->_draw->_transparentCursor = 1;
}
-void Init_Geisha::initGame() {
- // HACK - Since the MDY/TBR player is not working, claim we have no AdLib
- _vm->_global->_soundFlags = 0;
-
- Init::initGame();
-}
-
} // End of namespace Gob
diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp
index 25d521aca6..a8e8cbe2c3 100644
--- a/engines/gob/init_v1.cpp
+++ b/engines/gob/init_v1.cpp
@@ -41,8 +41,6 @@ void Init_v1::initVideo() {
_vm->_global->_mousePresent = 1;
- _vm->_global->_inVM = 0;
-
if ((_vm->_global->_videoMode == 0x13) && !_vm->isEGA())
_vm->_global->_colorCount = 256;
diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp
index 1289d561ea..c204b04a40 100644
--- a/engines/gob/init_v2.cpp
+++ b/engines/gob/init_v2.cpp
@@ -45,8 +45,6 @@ void Init_v2::initVideo() {
_vm->_global->_mousePresent = 1;
- _vm->_global->_inVM = 0;
-
_vm->_global->_colorCount = 16;
if (!_vm->isEGA() &&
((_vm->getPlatform() == Common::kPlatformPC) ||
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index 9df3c06c74..4460274561 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -52,6 +52,7 @@ Inter::Inter(GobEngine *vm) : _vm(vm), _varStack(600) {
_soundEndTimeKey = 0;
_soundStopVal = 0;
+ _lastBusyWait = 0;
_noBusyWait = false;
_variables = 0;
@@ -358,6 +359,9 @@ void Inter::allocateVars(uint32 count) {
}
void Inter::delocateVars() {
+ if (_vm->_game)
+ _vm->_game->deletedVars(_variables);
+
delete _variables;
_variables = 0;
}
@@ -452,4 +456,15 @@ uint32 Inter::readValue(uint16 index, uint16 type) {
return 0;
}
+void Inter::handleBusyWait() {
+ uint32 now = _vm->_util->getTimeKey();
+
+ if (!_noBusyWait)
+ if ((now - _lastBusyWait) <= 20)
+ _vm->_util->longDelay(1);
+
+ _lastBusyWait = now;
+ _noBusyWait = false;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index c79b6e2260..63bf3eb1c6 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -31,6 +31,10 @@
#include "gob/iniconfig.h"
#include "gob/databases.h"
+namespace Common {
+ class PEResources;
+}
+
namespace Gob {
class Cheater_Geisha;
@@ -138,8 +142,9 @@ protected:
VariableStack _varStack;
- // The busy-wait detection in o1_keyFunc breaks fast scrolling in Ween
- bool _noBusyWait;
+ // Busy-wait detection
+ bool _noBusyWait;
+ uint32 _lastBusyWait;
GobEngine *_vm;
@@ -168,6 +173,8 @@ protected:
void storeString(const char *value);
uint32 readValue(uint16 index, uint16 type);
+
+ void handleBusyWait();
};
class Inter_v1 : public Inter {
@@ -509,6 +516,20 @@ protected:
void oFascin_setWinFlags();
};
+class Inter_LittleRed : public Inter_v2 {
+public:
+ Inter_LittleRed(GobEngine *vm);
+ virtual ~Inter_LittleRed() {}
+
+protected:
+ virtual void setupOpcodesDraw();
+ virtual void setupOpcodesFunc();
+ virtual void setupOpcodesGob();
+
+ void oLittleRed_keyFunc(OpFuncParams &params);
+ void oLittleRed_playComposition(OpFuncParams &params);
+};
+
class Inter_v3 : public Inter_v2 {
public:
Inter_v3(GobEngine *vm);
@@ -648,7 +669,7 @@ private:
class Inter_v7 : public Inter_Playtoons {
public:
Inter_v7(GobEngine *vm);
- virtual ~Inter_v7() {}
+ virtual ~Inter_v7();
protected:
virtual void setupOpcodesDraw();
@@ -684,7 +705,12 @@ private:
INIConfig _inis;
Databases _databases;
+ Common::PEResources *_cursors;
+
Common::String findFile(const Common::String &mask);
+
+ bool loadCursorFile();
+ void resizeCursors(int16 width, int16 height, int16 count, bool transparency);
};
} // End of namespace Gob
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index 134203fa9d..029f7c697b 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -119,7 +119,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
MouseButtons buttons;
SurfacePtr surface;
SoundDesc samples[4];
- int16 comp[5] = { 0, 1, 2, 3, -1 };
+ static const int16 comp[5] = { 0, 1, 2, 3, -1 };
static const char *const sndFiles[] = {"1INTROII.snd", "2INTROII.snd", "1INTRO3.snd", "2INTRO3.snd"};
surface = _vm->_video->initSurfDesc(320, 200);
@@ -167,8 +167,8 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
MouseButtons buttons;
Video::Color *palBak;
SoundDesc samples[2];
- int16 comp[3] = { 0, 1, -1 };
byte *palettes[4];
+ static const int16 comp[3] = { 0, 1, -1 };
static const char *const sndFiles[] = {"1INTROIV.snd", "2INTROIV.snd"};
static const char *const palFiles[] = {"2ou2.clt", "2ou3.clt", "2ou4.clt", "2ou5.clt"};
diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp
index 081b48fbad..001ec06635 100644
--- a/engines/gob/inter_fascin.cpp
+++ b/engines/gob/inter_fascin.cpp
@@ -248,12 +248,11 @@ void Inter_Fascination::oFascin_playTira(OpGobParams &params) {
void Inter_Fascination::oFascin_loadExtasy(OpGobParams &params) {
_vm->_sound->adlibLoadTBR("extasy.tbr");
_vm->_sound->adlibLoadMDY("extasy.mdy");
+ _vm->_sound->adlibSetRepeating(-1);
}
void Inter_Fascination::oFascin_adlibPlay(OpGobParams &params) {
-#ifdef ENABLE_FASCIN_ADLIB
_vm->_sound->adlibPlay();
-#endif
}
void Inter_Fascination::oFascin_adlibStop(OpGobParams &params) {
diff --git a/engines/gob/inter_geisha.cpp b/engines/gob/inter_geisha.cpp
index 7f21ceb91d..8d05cefa66 100644
--- a/engines/gob/inter_geisha.cpp
+++ b/engines/gob/inter_geisha.cpp
@@ -55,7 +55,7 @@ Inter_Geisha::Inter_Geisha(GobEngine *vm) : Inter_v1(vm),
_diving = new Geisha::Diving(vm);
_penetration = new Geisha::Penetration(vm);
- _cheater = new Cheater_Geisha(vm, _diving);
+ _cheater = new Cheater_Geisha(vm, _diving, _penetration);
_vm->_console->registerCheater(_cheater);
}
@@ -200,8 +200,12 @@ void Inter_Geisha::oGeisha_checkData(OpFuncParams &params) {
if (mode == SaveLoad::kSaveModeNone) {
exists = _vm->_dataIO->hasFile(file);
- if (!exists)
- warning("File \"%s\" not found", file.c_str());
+ if (!exists) {
+ // NOTE: Geisha looks if fin.tot exists to check if it needs to open disk3.stk.
+ // This is completely normal, so don't print a warning.
+ if (file != "fin.tot")
+ warning("File \"%s\" not found", file.c_str());
+ }
} else if (mode == SaveLoad::kSaveModeSave)
exists = _vm->_saveLoad->getSize(file.c_str()) >= 0;
@@ -272,12 +276,12 @@ void Inter_Geisha::oGeisha_writeData(OpFuncParams &params) {
}
void Inter_Geisha::oGeisha_gamePenetration(OpGobParams &params) {
- uint16 var1 = _vm->_game->_script->readUint16();
- uint16 var2 = _vm->_game->_script->readUint16();
- uint16 var3 = _vm->_game->_script->readUint16();
- uint16 resultVar = _vm->_game->_script->readUint16();
+ uint16 hasAccessPass = _vm->_game->_script->readUint16();
+ uint16 hasMaxEnergy = _vm->_game->_script->readUint16();
+ uint16 testMode = _vm->_game->_script->readUint16();
+ uint16 resultVar = _vm->_game->_script->readUint16();
- bool result = _penetration->play(var1, var2, var3);
+ bool result = _penetration->play(hasAccessPass, hasMaxEnergy, testMode);
WRITE_VAR_UINT32(resultVar, result ? 1 : 0);
}
@@ -298,9 +302,8 @@ void Inter_Geisha::oGeisha_loadTitleMusic(OpGobParams &params) {
}
void Inter_Geisha::oGeisha_playMusic(OpGobParams &params) {
- // TODO: The MDYPlayer is still broken!
- warning("Geisha Stub: oGeisha_playMusic");
- // _vm->_sound->adlibPlay();
+ _vm->_sound->adlibSetRepeating(-1);
+ _vm->_sound->adlibPlay();
}
void Inter_Geisha::oGeisha_stopMusic(OpGobParams &params) {
diff --git a/engines/gob/inter_littlered.cpp b/engines/gob/inter_littlered.cpp
new file mode 100644
index 0000000000..01aa4c2158
--- /dev/null
+++ b/engines/gob/inter_littlered.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/gob.h"
+#include "gob/inter.h"
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/draw.h"
+#include "gob/game.h"
+#include "gob/script.h"
+#include "gob/hotspots.h"
+#include "gob/sound/sound.h"
+
+namespace Gob {
+
+#define OPCODEVER Inter_LittleRed
+#define OPCODEDRAW(i, x) _opcodesDraw[i]._OPCODEDRAW(OPCODEVER, x)
+#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
+#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
+
+Inter_LittleRed::Inter_LittleRed(GobEngine *vm) : Inter_v2(vm) {
+}
+
+void Inter_LittleRed::setupOpcodesDraw() {
+ Inter_v2::setupOpcodesDraw();
+}
+
+void Inter_LittleRed::setupOpcodesFunc() {
+ Inter_v2::setupOpcodesFunc();
+
+ OPCODEFUNC(0x14, oLittleRed_keyFunc);
+
+ OPCODEFUNC(0x3D, oLittleRed_playComposition);
+}
+
+void Inter_LittleRed::setupOpcodesGob() {
+ OPCODEGOB(1, o_gobNOP); // Sets some sound timer interrupt
+ OPCODEGOB(2, o_gobNOP); // Sets some sound timer interrupt
+
+ OPCODEGOB(500, o2_playProtracker);
+ OPCODEGOB(501, o2_stopProtracker);
+}
+
+void Inter_LittleRed::oLittleRed_keyFunc(OpFuncParams &params) {
+ animPalette();
+ _vm->_draw->blitInvalidated();
+
+ handleBusyWait();
+
+ int16 cmd = _vm->_game->_script->readInt16();
+ int16 key;
+ uint32 keyState;
+
+ switch (cmd) {
+ case -1:
+ break;
+
+ case 0:
+ _vm->_draw->_showCursor &= ~2;
+ _vm->_util->longDelay(1);
+ key = _vm->_game->_hotspots->check(0, 0);
+ storeKey(key);
+
+ _vm->_util->clearKeyBuf();
+ break;
+
+ case 1:
+ _vm->_util->forceMouseUp(true);
+ key = _vm->_game->checkKeys(&_vm->_global->_inter_mouseX,
+ &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons, 0);
+ storeKey(key);
+ break;
+
+ case 2:
+ _vm->_util->processInput(true);
+ keyState = _vm->_util->getKeyState();
+
+ WRITE_VAR(0, keyState);
+ _vm->_util->clearKeyBuf();
+ break;
+
+ default:
+ _vm->_sound->speakerOnUpdate(cmd);
+ if (cmd < 20) {
+ _vm->_util->delay(cmd);
+ _noBusyWait = true;
+ } else
+ _vm->_util->longDelay(cmd);
+ break;
+ }
+}
+
+void Inter_LittleRed::oLittleRed_playComposition(OpFuncParams &params) {
+ o1_playComposition(params);
+
+ _vm->_sound->blasterRepeatComposition(-1);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 9aa190a456..dc533a210a 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -286,10 +286,40 @@ void Inter_v1::o1_loadMult() {
}
void Inter_v1::o1_playMult() {
- int16 checkEscape;
+ // NOTE: The EGA version of Gobliiins has an MDY tune.
+ // While the original doesn't play it, we do.
+ bool isGob1EGAIntro = _vm->getGameType() == kGameTypeGob1 &&
+ _vm->isEGA() &&
+ _vm->_game->_script->pos() == 1010 &&
+ _vm->isCurrentTot("intro.tot") &&
+ VAR(57) != 0xFFFFFFFF &&
+ _vm->_dataIO->hasFile("goblins.mdy") &&
+ _vm->_dataIO->hasFile("goblins.tbr");
+
+ int16 checkEscape = _vm->_game->_script->readInt16();
+
+ if (isGob1EGAIntro) {
+ _vm->_sound->adlibLoadTBR("goblins.tbr");
+ _vm->_sound->adlibLoadMDY("goblins.mdy");
+ _vm->_sound->adlibSetRepeating(-1);
+
+ _vm->_sound->adlibPlay();
+ }
- checkEscape = _vm->_game->_script->readInt16();
_vm->_mult->playMult(VAR(57), -1, checkEscape, 0);
+
+ if (isGob1EGAIntro) {
+
+ // User didn't escape the intro mult, wait for an escape here
+ if (VAR(57) != 0xFFFFFFFF) {
+ while (_vm->_util->getKey() != kKeyEscape) {
+ _vm->_util->processInput();
+ _vm->_util->longDelay(1);
+ }
+ }
+
+ _vm->_sound->adlibUnload();
+ }
}
void Inter_v1::o1_freeMultKeys() {
@@ -1159,26 +1189,15 @@ void Inter_v1::o1_palLoad(OpFuncParams &params) {
}
void Inter_v1::o1_keyFunc(OpFuncParams &params) {
- static uint32 lastCalled = 0;
- int16 cmd;
- int16 key;
- uint32 now;
-
if (!_vm->_vidPlayer->isPlayingLive()) {
_vm->_draw->forceBlit();
_vm->_video->retrace();
}
- cmd = _vm->_game->_script->readInt16();
animPalette();
_vm->_draw->blitInvalidated();
- now = _vm->_util->getTimeKey();
- if (!_noBusyWait)
- if ((now - lastCalled) <= 20)
- _vm->_util->longDelay(1);
- lastCalled = now;
- _noBusyWait = false;
+ handleBusyWait();
// WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter
// to become 5000. We deliberately slow down busy-waiting, so we shorten
@@ -1187,6 +1206,9 @@ void Inter_v1::o1_keyFunc(OpFuncParams &params) {
(_vm->_game->_script->pos() == 729) && _vm->isCurrentTot("intro5.tot"))
WRITE_VAR(59, 4000);
+ int16 cmd = _vm->_game->_script->readInt16();
+ int16 key;
+
switch (cmd) {
case -1:
break;
@@ -1554,14 +1576,13 @@ void Inter_v1::o1_waitEndPlay(OpFuncParams &params) {
}
void Inter_v1::o1_playComposition(OpFuncParams &params) {
- int16 composition[50];
- int16 dataVar;
- int16 freqVal;
+ int16 dataVar = _vm->_game->_script->readVarIndex();
+ int16 freqVal = _vm->_game->_script->readValExpr();
- dataVar = _vm->_game->_script->readVarIndex();
- freqVal = _vm->_game->_script->readValExpr();
+ int16 composition[50];
+ int maxEntries = MIN<int>(50, (_variables->getSize() - dataVar) / 4);
for (int i = 0; i < 50; i++)
- composition[i] = (int16) VAR_OFFSET(dataVar + i * 4);
+ composition[i] = (i < maxEntries) ? ((int16) VAR_OFFSET(dataVar + i * 4)) : -1;
_vm->_sound->blasterPlayComposition(composition, freqVal);
}
@@ -1744,10 +1765,15 @@ void Inter_v1::o1_writeData(OpFuncParams &params) {
void Inter_v1::o1_manageDataFile(OpFuncParams &params) {
Common::String file = _vm->_game->_script->evalString();
- if (!file.empty())
+ if (!file.empty()) {
_vm->_dataIO->openArchive(file, true);
- else
+ } else {
_vm->_dataIO->closeArchive(true);
+
+ // NOTE: Lost in Time might close a data file without explicitely closing a video in it.
+ // So we make sure that all open videos are still available.
+ _vm->_vidPlayer->reopenAll();
+ }
}
void Inter_v1::o1_setState(OpGobParams &params) {
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 1e5b7bb24c..cb58fe86f7 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1002,6 +1002,10 @@ void Inter_v2::o2_openItk() {
void Inter_v2::o2_closeItk() {
_vm->_dataIO->closeArchive(false);
+
+ // NOTE: Lost in Time might close a data file without explicitely closing a video in it.
+ // So we make sure that all open videos are still available.
+ _vm->_vidPlayer->reopenAll();
}
void Inter_v2::o2_setImdFrontSurf() {
@@ -1244,7 +1248,7 @@ void Inter_v2::o2_checkData(OpFuncParams &params) {
file = "EMAP2011.TOT";
int32 size = -1;
- SaveLoad::SaveMode mode = _vm->_saveLoad->getSaveMode(file.c_str());
+ SaveLoad::SaveMode mode = _vm->_saveLoad ? _vm->_saveLoad->getSaveMode(file.c_str()) : SaveLoad::kSaveModeNone;
if (mode == SaveLoad::kSaveModeNone) {
size = _vm->_dataIO->fileSize(file);
@@ -1273,7 +1277,7 @@ void Inter_v2::o2_readData(OpFuncParams &params) {
debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)",
file, dataVar, size, offset);
- SaveLoad::SaveMode mode = _vm->_saveLoad->getSaveMode(file);
+ SaveLoad::SaveMode mode = _vm->_saveLoad ? _vm->_saveLoad->getSaveMode(file) : SaveLoad::kSaveModeNone;
if (mode == SaveLoad::kSaveModeSave) {
WRITE_VAR(1, 1);
@@ -1345,7 +1349,7 @@ void Inter_v2::o2_writeData(OpFuncParams &params) {
WRITE_VAR(1, 1);
- SaveLoad::SaveMode mode = _vm->_saveLoad->getSaveMode(file);
+ SaveLoad::SaveMode mode = _vm->_saveLoad ? _vm->_saveLoad->getSaveMode(file) : SaveLoad::kSaveModeNone;
if (mode == SaveLoad::kSaveModeSave) {
if (!_vm->_saveLoad->save(file, dataVar, size, offset)) {
diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp
index c0e8978afd..24905b08d1 100644
--- a/engines/gob/inter_v5.cpp
+++ b/engines/gob/inter_v5.cpp
@@ -281,7 +281,7 @@ void Inter_v5::o5_getSystemCDSpeed(OpGobParams &params) {
Font *font;
if ((font = _vm->_draw->loadFont("SPEED.LET"))) {
- _vm->_draw->drawString("100 %", 402, 89, 112, 144, 0, *_vm->_draw->_backSurface, *font);
+ font->drawString("100 %", 402, 89, 112, 144, 0, *_vm->_draw->_backSurface);
_vm->_draw->forceBlit();
delete font;
@@ -293,7 +293,7 @@ void Inter_v5::o5_getSystemRAM(OpGobParams &params) {
Font *font;
if ((font = _vm->_draw->loadFont("SPEED.LET"))) {
- _vm->_draw->drawString("100 %", 402, 168, 112, 144, 0, *_vm->_draw->_backSurface, *font);
+ font->drawString("100 %", 402, 168, 112, 144, 0, *_vm->_draw->_backSurface);
_vm->_draw->forceBlit();
delete font;
@@ -305,7 +305,7 @@ void Inter_v5::o5_getSystemCPUSpeed(OpGobParams &params) {
Font *font;
if ((font = _vm->_draw->loadFont("SPEED.LET"))) {
- _vm->_draw->drawString("100 %", 402, 248, 112, 144, 0, *_vm->_draw->_backSurface, *font);
+ font->drawString("100 %", 402, 248, 112, 144, 0, *_vm->_draw->_backSurface);
_vm->_draw->forceBlit();
delete font;
@@ -317,7 +317,7 @@ void Inter_v5::o5_getSystemDrawSpeed(OpGobParams &params) {
Font *font;
if ((font = _vm->_draw->loadFont("SPEED.LET"))) {
- _vm->_draw->drawString("100 %", 402, 326, 112, 144, 0, *_vm->_draw->_backSurface, *font);
+ font->drawString("100 %", 402, 326, 112, 144, 0, *_vm->_draw->_backSurface);
_vm->_draw->forceBlit();
delete font;
@@ -329,7 +329,7 @@ void Inter_v5::o5_totalSystemSpecs(OpGobParams &params) {
Font *font;
if ((font = _vm->_draw->loadFont("SPEED.LET"))) {
- _vm->_draw->drawString("100 %", 402, 405, 112, 144, 0, *_vm->_draw->_backSurface, *font);
+ font->drawString("100 %", 402, 405, 112, 144, 0, *_vm->_draw->_backSurface);
_vm->_draw->forceBlit();
delete font;
diff --git a/engines/gob/inter_v7.cpp b/engines/gob/inter_v7.cpp
index 81547f7362..6cf69ed9df 100644
--- a/engines/gob/inter_v7.cpp
+++ b/engines/gob/inter_v7.cpp
@@ -22,8 +22,11 @@
#include "common/endian.h"
#include "common/archive.h"
+#include "common/winexe.h"
+#include "common/winexe_pe.h"
#include "graphics/cursorman.h"
+#include "graphics/wincursor.h"
#include "gob/gob.h"
#include "gob/global.h"
@@ -42,7 +45,11 @@ namespace Gob {
#define OPCODEFUNC(i, x) _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
#define OPCODEGOB(i, x) _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
-Inter_v7::Inter_v7(GobEngine *vm) : Inter_Playtoons(vm) {
+Inter_v7::Inter_v7(GobEngine *vm) : Inter_Playtoons(vm), _cursors(0) {
+}
+
+Inter_v7::~Inter_v7() {
+ delete _cursors;
}
void Inter_v7::setupOpcodesDraw() {
@@ -86,27 +93,121 @@ void Inter_v7::o7_draw0x0C() {
WRITE_VAR(17, 0);
}
+void Inter_v7::resizeCursors(int16 width, int16 height, int16 count, bool transparency) {
+ if (width <= 0)
+ width = _vm->_draw->_cursorWidth;
+ if (height <= 0)
+ height = _vm->_draw->_cursorHeight;
+
+ width = MAX<uint16>(width , _vm->_draw->_cursorWidth);
+ height = MAX<uint16>(height, _vm->_draw->_cursorHeight);
+
+ _vm->_draw->_transparentCursor = transparency;
+
+ // Cursors sprite already big enough
+ if ((_vm->_draw->_cursorWidth >= width) && (_vm->_draw->_cursorHeight >= height) &&
+ (_vm->_draw->_cursorCount >= count))
+ return;
+
+ _vm->_draw->_cursorCount = count;
+ _vm->_draw->_cursorWidth = width;
+ _vm->_draw->_cursorHeight = height;
+
+ _vm->_draw->freeSprite(Draw::kCursorSurface);
+ _vm->_draw->_cursorSprites.reset();
+ _vm->_draw->_cursorSpritesBack.reset();
+ _vm->_draw->_scummvmCursor.reset();
+
+ _vm->_draw->initSpriteSurf(Draw::kCursorSurface, width * count, height, 2);
+
+ _vm->_draw->_cursorSpritesBack = _vm->_draw->_spritesArray[Draw::kCursorSurface];
+ _vm->_draw->_cursorSprites = _vm->_draw->_cursorSpritesBack;
+
+ _vm->_draw->_scummvmCursor = _vm->_video->initSurfDesc(width, height, SCUMMVM_CURSOR);
+
+ for (int i = 0; i < 40; i++) {
+ _vm->_draw->_cursorAnimLow[i] = -1;
+ _vm->_draw->_cursorAnimDelays[i] = 0;
+ _vm->_draw->_cursorAnimHigh[i] = 0;
+ }
+ _vm->_draw->_cursorAnimLow[1] = 0;
+
+ delete[] _vm->_draw->_doCursorPalettes;
+ delete[] _vm->_draw->_cursorPalettes;
+ delete[] _vm->_draw->_cursorKeyColors;
+ delete[] _vm->_draw->_cursorPaletteStarts;
+ delete[] _vm->_draw->_cursorPaletteCounts;
+ delete[] _vm->_draw->_cursorHotspotsX;
+ delete[] _vm->_draw->_cursorHotspotsY;
+
+ _vm->_draw->_cursorPalettes = new byte[256 * 3 * count];
+ _vm->_draw->_doCursorPalettes = new bool[count];
+ _vm->_draw->_cursorKeyColors = new byte[count];
+ _vm->_draw->_cursorPaletteStarts = new uint16[count];
+ _vm->_draw->_cursorPaletteCounts = new uint16[count];
+ _vm->_draw->_cursorHotspotsX = new int32[count];
+ _vm->_draw->_cursorHotspotsY = new int32[count];
+
+ memset(_vm->_draw->_cursorPalettes , 0, count * 256 * 3);
+ memset(_vm->_draw->_doCursorPalettes , 0, count * sizeof(bool));
+ memset(_vm->_draw->_cursorKeyColors , 0, count * sizeof(byte));
+ memset(_vm->_draw->_cursorPaletteStarts, 0, count * sizeof(uint16));
+ memset(_vm->_draw->_cursorPaletteCounts, 0, count * sizeof(uint16));
+ memset(_vm->_draw->_cursorHotspotsX , 0, count * sizeof(int32));
+ memset(_vm->_draw->_cursorHotspotsY , 0, count * sizeof(int32));
+}
+
void Inter_v7::o7_loadCursor() {
int16 cursorIndex = _vm->_game->_script->readValExpr();
- Common::String cursorFile = _vm->_game->_script->evalString();
+ Common::String cursorName = _vm->_game->_script->evalString();
+
+ // Clear the cursor sprite at that index
+ _vm->_draw->_cursorSprites->fillRect(cursorIndex * _vm->_draw->_cursorWidth, 0,
+ cursorIndex * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1,
+ _vm->_draw->_cursorHeight - 1, 0);
+
+ // If the cursor name is empty, that cursor will be drawn by the scripts
+ if (cursorName.empty()) {
+ // Make sure the cursors sprite is big enough and set to non-extern palette
+ resizeCursors(-1, -1, cursorIndex + 1, true);
+ _vm->_draw->_doCursorPalettes[cursorIndex] = false;
+ return;
+ }
+
+ Graphics::WinCursorGroup *cursorGroup = 0;
+ Graphics::Cursor *defaultCursor = 0;
+
+ // Load the cursor file and cursor group
+ if (loadCursorFile())
+ cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_cursors, Common::WinResourceID(cursorName));
+
+ // If the requested cursor does not exist, create a default one
+ const Graphics::Cursor *cursor = 0;
+ if (!cursorGroup || cursorGroup->cursors.empty() || !cursorGroup->cursors[0].cursor) {
+ defaultCursor = Graphics::makeDefaultWinCursor();
+
+ cursor = defaultCursor;
+ } else
+ cursor = cursorGroup->cursors[0].cursor;
- warning("Addy Stub: Load cursor \"%s\" to %d", cursorFile.c_str(), cursorIndex);
+ // Make sure the cursors sprite it big enough
+ resizeCursors(cursor->getWidth(), cursor->getHeight(), cursorIndex + 1, true);
- byte cursor[9];
- byte palette[6];
+ Surface cursorSurf(cursor->getWidth(), cursor->getHeight(), 1, cursor->getSurface());
- cursor[0] = 0; cursor[1] = 0; cursor[2] = 0;
- cursor[3] = 0; cursor[4] = 1; cursor[5] = 0;
- cursor[6] = 0; cursor[7] = 0; cursor[8] = 0;
+ _vm->_draw->_cursorSprites->blit(cursorSurf, cursorIndex * _vm->_draw->_cursorWidth, 0);
- palette[0] = 0; palette[1] = 0; palette[2] = 0;
- palette[3] = 255; palette[4] = 255; palette[5] = 255;
+ memcpy(_vm->_draw->_cursorPalettes + cursorIndex * 256 * 3, cursor->getPalette(), cursor->getPaletteCount() * 3);
- CursorMan.pushCursorPalette(palette, 0, 2);
- CursorMan.disableCursorPalette(false);
- CursorMan.replaceCursor(cursor, 3, 3, 1, 1, 255);
+ _vm->_draw->_doCursorPalettes [cursorIndex] = true;
+ _vm->_draw->_cursorKeyColors [cursorIndex] = cursor->getKeyColor();
+ _vm->_draw->_cursorPaletteStarts[cursorIndex] = cursor->getPaletteStartIndex();
+ _vm->_draw->_cursorPaletteCounts[cursorIndex] = cursor->getPaletteCount();
+ _vm->_draw->_cursorHotspotsX [cursorIndex] = cursor->getHotspotX();
+ _vm->_draw->_cursorHotspotsY [cursorIndex] = cursor->getHotspotY();
- CursorMan.showMouse(true);
+ delete cursorGroup;
+ delete defaultCursor;
}
void Inter_v7::o7_displayWarning() {
@@ -529,4 +630,19 @@ Common::String Inter_v7::findFile(const Common::String &mask) {
return files.front()->getName();
}
+bool Inter_v7::loadCursorFile() {
+ if (_cursors)
+ return true;
+
+ _cursors = new Common::PEResources();
+
+ if (_cursors->loadFromEXE("cursor32.dll"))
+ return true;
+
+ delete _cursors;
+ _cursors = 0;
+
+ return false;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/diving.cpp b/engines/gob/minigames/geisha/diving.cpp
index 6f4c6e168a..56c7b5213c 100644
--- a/engines/gob/minigames/geisha/diving.cpp
+++ b/engines/gob/minigames/geisha/diving.cpp
@@ -706,16 +706,16 @@ void Diving::updateAnims() {
for (Common::List<ANIObject *>::iterator a = _anims.reverse_begin();
a != _anims.end(); --a) {
- (*a)->clear(*_vm->_draw->_backSurface, left, top, right, bottom);
- _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ if ((*a)->clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
}
// Draw the current animation frames
for (Common::List<ANIObject *>::iterator a = _anims.begin();
a != _anims.end(); ++a) {
- (*a)->draw(*_vm->_draw->_backSurface, left, top, right, bottom);
- _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ if ((*a)->draw(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
(*a)->advance();
}
diff --git a/engines/gob/minigames/geisha/evilfish.cpp b/engines/gob/minigames/geisha/evilfish.cpp
index c7ef9d5622..05ae9d0ad4 100644
--- a/engines/gob/minigames/geisha/evilfish.cpp
+++ b/engines/gob/minigames/geisha/evilfish.cpp
@@ -171,7 +171,7 @@ void EvilFish::mutate(uint16 animSwimLeft, uint16 animSwimRight,
}
}
-bool EvilFish::isDead() {
+bool EvilFish::isDead() const {
return !isVisible() || (_state == kStateNone) || (_state == kStateDie);
}
diff --git a/engines/gob/minigames/geisha/evilfish.h b/engines/gob/minigames/geisha/evilfish.h
index 81efb676e2..4c82629461 100644
--- a/engines/gob/minigames/geisha/evilfish.h
+++ b/engines/gob/minigames/geisha/evilfish.h
@@ -58,7 +58,7 @@ public:
uint16 animTurnLeft, uint16 animTurnRight, uint16 animDie);
/** Is the fish dead? */
- bool isDead();
+ bool isDead() const;
private:
enum State {
diff --git a/engines/gob/minigames/geisha/meter.cpp b/engines/gob/minigames/geisha/meter.cpp
index e3b9bd1ccf..7ec3119866 100644
--- a/engines/gob/minigames/geisha/meter.cpp
+++ b/engines/gob/minigames/geisha/meter.cpp
@@ -42,6 +42,10 @@ Meter::~Meter() {
delete _surface;
}
+int32 Meter::getMaxValue() const {
+ return _maxValue;
+}
+
int32 Meter::getValue() const {
return _value;
}
@@ -59,22 +63,36 @@ void Meter::setMaxValue() {
setValue(_maxValue);
}
-void Meter::increase(int32 n) {
+int32 Meter::increase(int32 n) {
+ if (n < 0)
+ return decrease(-n);
+
+ int32 overflow = MAX<int32>(0, (_value + n) - _maxValue);
+
int32 value = CLIP<int32>(_value + n, 0, _maxValue);
if (_value == value)
- return;
+ return overflow;
_value = value;
_needUpdate = true;
+
+ return overflow;
}
-void Meter::decrease(int32 n) {
+int32 Meter::decrease(int32 n) {
+ if (n < 0)
+ return increase(-n);
+
+ int32 underflow = -MIN<int32>(0, _value - n);
+
int32 value = CLIP<int32>(_value - n, 0, _maxValue);
if (_value == value)
- return;
+ return underflow;
_value = value;
_needUpdate = true;
+
+ return underflow;
}
void Meter::draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) {
diff --git a/engines/gob/minigames/geisha/meter.h b/engines/gob/minigames/geisha/meter.h
index a9bdb14d0f..30dc826de0 100644
--- a/engines/gob/minigames/geisha/meter.h
+++ b/engines/gob/minigames/geisha/meter.h
@@ -44,6 +44,8 @@ public:
Direction direction);
~Meter();
+ /** Return the max value the meter is measuring. */
+ int32 getMaxValue() const;
/** Return the current value the meter is measuring. */
int32 getValue() const;
@@ -53,10 +55,10 @@ public:
/** Set the current value the meter is measuring to the max value. */
void setMaxValue();
- /** Increase the current value the meter is measuring. */
- void increase(int32 n = 1);
- /** Decrease the current value the meter is measuring. */
- void decrease(int32 n = 1);
+ /** Increase the current value the meter is measuring, returning the overflow. */
+ int32 increase(int32 n = 1);
+ /** Decrease the current value the meter is measuring, returning the underflow. */
+ int32 decrease(int32 n = 1);
/** Draw the meter onto the surface and return the affected rectangle. */
void draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
diff --git a/engines/gob/minigames/geisha/mouth.cpp b/engines/gob/minigames/geisha/mouth.cpp
new file mode 100644
index 0000000000..7ba9f86f8c
--- /dev/null
+++ b/engines/gob/minigames/geisha/mouth.cpp
@@ -0,0 +1,169 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/util.h"
+
+#include "gob/minigames/geisha/mouth.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+Mouth::Mouth(const ANIFile &ani, const CMPFile &cmp,
+ uint16 mouthAnim, uint16 mouthSprite, uint16 floorSprite) : ANIObject(ani) {
+
+ _sprite = new ANIObject(cmp);
+ _sprite->setAnimation(mouthSprite);
+ _sprite->setVisible(true);
+
+ for (int i = 0; i < kFloorCount; i++) {
+ _floor[i] = new ANIObject(cmp);
+ _floor[i]->setAnimation(floorSprite);
+ _floor[i]->setVisible(true);
+ }
+
+ _state = kStateDeactivated;
+
+ setAnimation(mouthAnim);
+ setMode(kModeOnce);
+ setPause(true);
+ setVisible(true);
+}
+
+Mouth::~Mouth() {
+ for (int i = 0; i < kFloorCount; i++)
+ delete _floor[i];
+
+ delete _sprite;
+}
+
+void Mouth::advance() {
+ if (_state != kStateActivated)
+ return;
+
+ // Animation finished, set state to dead
+ if (isPaused()) {
+ _state = kStateDead;
+ return;
+ }
+
+ ANIObject::advance();
+}
+
+void Mouth::activate() {
+ if (_state != kStateDeactivated)
+ return;
+
+ _state = kStateActivated;
+
+ setPause(false);
+}
+
+bool Mouth::isDeactivated() const {
+ return _state == kStateDeactivated;
+}
+
+void Mouth::setPosition(int16 x, int16 y) {
+ ANIObject::setPosition(x, y);
+
+ int16 floorWidth, floorHeight;
+ _floor[0]->getFrameSize(floorWidth, floorHeight);
+
+ _sprite->setPosition(x, y);
+
+ for (int i = 0; i < kFloorCount; i++)
+ _floor[i]->setPosition(x + (i * floorWidth), y);
+}
+
+bool Mouth::draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ // If the mouth is deactivated, draw the default mouth sprite
+ if (_state == kStateDeactivated)
+ return _sprite->draw(dest, left, top, right, bottom);
+
+ // If the mouth is activated, draw the current mouth animation sprite
+ if (_state == kStateActivated)
+ return ANIObject::draw(dest, left, top, right, bottom);
+
+ // If the mouth is dead, draw the floor tiles
+ if (_state == kStateDead) {
+ int16 fLeft, fRight, fTop, fBottom;
+ bool drawn = false;
+
+ left = 0x7FFF;
+ top = 0x7FFF;
+ right = 0;
+ bottom = 0;
+
+ for (int i = 0; i < kFloorCount; i++) {
+ if (_floor[i]->draw(dest, fLeft, fTop, fRight, fBottom)) {
+ drawn = true;
+ left = MIN(left , fLeft);
+ top = MIN(top , fTop);
+ right = MAX(right , fRight);
+ bottom = MAX(bottom, fBottom);
+ }
+ }
+
+ return drawn;
+ }
+
+ return false;
+}
+
+bool Mouth::clear(Surface &dest, int16 &left , int16 &top, int16 &right, int16 &bottom) {
+ // If the mouth is deactivated, clear the default mouth sprite
+ if (_state == kStateDeactivated)
+ return _sprite->clear(dest, left, top, right, bottom);
+
+ // If the mouth is activated, clear the current mouth animation sprite
+ if (_state == kStateActivated)
+ return ANIObject::clear(dest, left, top, right, bottom);
+
+ // If the mouth is clear, draw the floor tiles
+ if (_state == kStateDead) {
+ int16 fLeft, fRight, fTop, fBottom;
+ bool cleared = false;
+
+ left = 0x7FFF;
+ top = 0x7FFF;
+ right = 0;
+ bottom = 0;
+
+ for (int i = 0; i < kFloorCount; i++) {
+ if (_floor[i]->clear(dest, fLeft, fTop, fRight, fBottom)) {
+ cleared = true;
+ left = MIN(left , fLeft);
+ top = MIN(top , fTop);
+ right = MAX(right , fRight);
+ bottom = MAX(bottom, fBottom);
+ }
+ }
+
+ return cleared;
+ }
+
+ return false;
+}
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/mouth.h b/engines/gob/minigames/geisha/mouth.h
new file mode 100644
index 0000000000..2e0cfcd5d0
--- /dev/null
+++ b/engines/gob/minigames/geisha/mouth.h
@@ -0,0 +1,75 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_MINIGAMES_GEISHA_MOUTH_H
+#define GOB_MINIGAMES_GEISHA_MOUTH_H
+
+#include "gob/aniobject.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+/** A kissing/biting mouth in Geisha's "Penetration" minigame. */
+class Mouth : public ANIObject {
+public:
+ Mouth(const ANIFile &ani, const CMPFile &cmp,
+ uint16 mouthAnim, uint16 mouthSprite, uint16 floorSprite);
+ ~Mouth();
+
+ /** Advance the animation to the next frame. */
+ void advance();
+
+ /** Active the mouth's animation. */
+ void activate();
+
+ /** Is the mouth deactivated? */
+ bool isDeactivated() const;
+
+ /** Set the current position. */
+ void setPosition(int16 x, int16 y);
+
+ /** Draw the current frame onto the surface and return the affected rectangle. */
+ bool draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+ /** Draw the current frame from the surface and return the affected rectangle. */
+ bool clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+
+private:
+ static const int kFloorCount = 2;
+
+ enum State {
+ kStateDeactivated,
+ kStateActivated,
+ kStateDead
+ };
+
+ ANIObject *_sprite;
+ ANIObject *_floor[kFloorCount];
+
+ State _state;
+};
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
+
+#endif // GOB_MINIGAMES_GEISHA_MOUTH_H
diff --git a/engines/gob/minigames/geisha/penetration.cpp b/engines/gob/minigames/geisha/penetration.cpp
index 121a45bc40..c8c4f2bba7 100644
--- a/engines/gob/minigames/geisha/penetration.cpp
+++ b/engines/gob/minigames/geisha/penetration.cpp
@@ -20,87 +20,1449 @@
*
*/
+#include "common/events.h"
+
#include "gob/global.h"
#include "gob/util.h"
+#include "gob/palanim.h"
#include "gob/draw.h"
#include "gob/video.h"
#include "gob/decfile.h"
+#include "gob/cmpfile.h"
#include "gob/anifile.h"
+#include "gob/aniobject.h"
+
+#include "gob/sound/sound.h"
#include "gob/minigames/geisha/penetration.h"
+#include "gob/minigames/geisha/meter.h"
+#include "gob/minigames/geisha/mouth.h"
namespace Gob {
namespace Geisha {
-static const byte kPalette[48] = {
- 0x16, 0x16, 0x16,
- 0x12, 0x14, 0x16,
- 0x34, 0x00, 0x25,
- 0x1D, 0x1F, 0x22,
- 0x24, 0x27, 0x2A,
- 0x2C, 0x0D, 0x22,
- 0x2B, 0x2E, 0x32,
- 0x12, 0x09, 0x20,
- 0x3D, 0x3F, 0x00,
- 0x3F, 0x3F, 0x3F,
- 0x00, 0x00, 0x00,
- 0x15, 0x15, 0x3F,
- 0x25, 0x22, 0x2F,
- 0x1A, 0x14, 0x28,
- 0x3F, 0x00, 0x00,
- 0x15, 0x3F, 0x15
+static const int kColorShield = 11;
+static const int kColorHealth = 15;
+static const int kColorBlack = 10;
+static const int kColorFloor = 13;
+static const int kColorFloorText = 14;
+static const int kColorExitText = 15;
+
+enum Sprite {
+ kSpriteFloorShield = 25,
+ kSpriteExit = 29,
+ kSpriteFloor = 30,
+ kSpriteWall = 31,
+ kSpriteMouthBite = 32,
+ kSpriteMouthKiss = 33,
+ kSpriteBulletN = 65,
+ kSpriteBulletS = 66,
+ kSpriteBulletW = 67,
+ kSpriteBulletE = 68,
+ kSpriteBulletSW = 85,
+ kSpriteBulletSE = 86,
+ kSpriteBulletNW = 87,
+ kSpriteBulletNE = 88
+};
+
+enum Animation {
+ kAnimationEnemyRound = 0,
+ kAnimationEnemyRoundExplode = 1,
+ kAnimationEnemySquare = 2,
+ kAnimationEnemySquareExplode = 3,
+ kAnimationMouthKiss = 33,
+ kAnimationMouthBite = 34
+};
+
+static const int kMapTileWidth = 24;
+static const int kMapTileHeight = 24;
+
+static const int kPlayAreaX = 120;
+static const int kPlayAreaY = 7;
+static const int kPlayAreaWidth = 192;
+static const int kPlayAreaHeight = 113;
+
+static const int kPlayAreaBorderWidth = kPlayAreaWidth / 2;
+static const int kPlayAreaBorderHeight = kPlayAreaHeight / 2;
+
+static const int kTextAreaLeft = 9;
+static const int kTextAreaTop = 7;
+static const int kTextAreaRight = 104;
+static const int kTextAreaBottom = 107;
+
+static const int kTextAreaBigBottom = 142;
+
+const byte Penetration::kPalettes[kFloorCount][3 * kPaletteSize] = {
+ {
+ 0x16, 0x16, 0x16,
+ 0x12, 0x14, 0x16,
+ 0x34, 0x00, 0x25,
+ 0x1D, 0x1F, 0x22,
+ 0x24, 0x27, 0x2A,
+ 0x2C, 0x0D, 0x22,
+ 0x2B, 0x2E, 0x32,
+ 0x12, 0x09, 0x20,
+ 0x3D, 0x3F, 0x00,
+ 0x3F, 0x3F, 0x3F,
+ 0x00, 0x00, 0x00,
+ 0x15, 0x15, 0x3F,
+ 0x25, 0x22, 0x2F,
+ 0x1A, 0x14, 0x28,
+ 0x3F, 0x00, 0x00,
+ 0x15, 0x3F, 0x15
+ },
+ {
+ 0x16, 0x16, 0x16,
+ 0x12, 0x14, 0x16,
+ 0x37, 0x00, 0x24,
+ 0x1D, 0x1F, 0x22,
+ 0x24, 0x27, 0x2A,
+ 0x30, 0x0E, 0x16,
+ 0x2B, 0x2E, 0x32,
+ 0x22, 0x0E, 0x26,
+ 0x3D, 0x3F, 0x00,
+ 0x3F, 0x3F, 0x3F,
+ 0x00, 0x00, 0x00,
+ 0x15, 0x15, 0x3F,
+ 0x36, 0x28, 0x36,
+ 0x30, 0x1E, 0x2A,
+ 0x3F, 0x00, 0x00,
+ 0x15, 0x3F, 0x15
+ },
+ {
+ 0x16, 0x16, 0x16,
+ 0x12, 0x14, 0x16,
+ 0x3F, 0x14, 0x22,
+ 0x1D, 0x1F, 0x22,
+ 0x24, 0x27, 0x2A,
+ 0x30, 0x10, 0x10,
+ 0x2B, 0x2E, 0x32,
+ 0x2A, 0x12, 0x12,
+ 0x3D, 0x3F, 0x00,
+ 0x3F, 0x3F, 0x3F,
+ 0x00, 0x00, 0x00,
+ 0x15, 0x15, 0x3F,
+ 0x3F, 0x23, 0x31,
+ 0x39, 0x20, 0x2A,
+ 0x3F, 0x00, 0x00,
+ 0x15, 0x3F, 0x15
+ }
+};
+
+const byte Penetration::kMaps[kModeCount][kFloorCount][kMapWidth * kMapHeight] = {
+ {
+ { // Real mode, floor 0
+ 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0,
+ 50, 50, 0, 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50,
+ 50, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50,
+ 50, 0, 0, 50, 0, 0, 52, 53, 0, 0, 0, 0, 0, 0, 50, 0, 50,
+ 50, 0, 50, 0, 0, 50, 50, 50, 50, 0, 54, 55, 0, 0, 50, 0, 50,
+ 50, 0, 50, 49, 0, 50, 0, 52, 53, 0, 50, 50, 50, 0, 0, 0, 50,
+ 50, 57, 0, 50, 0, 0, 0, 50, 50, 50, 0, 0, 56, 50, 54, 55, 50,
+ 50, 50, 0, 0, 50, 50, 50, 0, 0, 0, 0, 50, 0, 0, 50, 0, 50,
+ 50, 51, 50, 0, 54, 55, 0, 0, 50, 50, 50, 50, 52, 53, 50, 0, 50,
+ 50, 0, 50, 0, 0, 0, 0, 0, 54, 55, 0, 0, 0, 50, 0, 0, 50,
+ 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 50,
+ 50, 50, 0, 52, 53, 0, 0, 0, 0, 0, 0, 52, 53, 0, 0, 50, 50,
+ 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0
+ },
+ { // Real mode, floor 1
+ 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0,
+ 50, 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,
+ 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50,
+ 50, 0, 50, 51, 52, 53, 0, 0, 52, 53, 0, 0, 0, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 50, 0, 50, 0, 50, 0, 50, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 52, 53, 0, 0, 0, 0, 0, 52, 53, 0, 52, 53, 50,
+ 50, 57, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50,
+ 50, 0, 50, 52, 53, 0, 0, 52, 53, 0, 0, 0, 0, 0, 54, 55, 50,
+ 50, 0, 50, 0, 50, 0, 50, 50, 0, 50, 50, 0, 50, 0, 50, 50, 50,
+ 50, 0, 50, 49, 0, 0, 52, 53, 0, 52, 53, 0, 0, 0, 50, 56, 50,
+ 50, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 50,
+ 50, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 0, 0, 0, 0, 0, 50,
+ 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0
+ },
+ { // Real mode, floor 2
+ 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0,
+ 50, 52, 53, 0, 0, 0, 0, 50, 50, 50, 0, 0, 0, 0, 52, 53, 50,
+ 50, 0, 50, 50, 50, 0, 0, 0, 50, 0, 0, 0, 50, 50, 50, 0, 50,
+ 50, 0, 50, 52, 53, 50, 50, 52, 53, 0, 50, 50, 54, 55, 50, 0, 50,
+ 50, 0, 50, 0, 0, 0, 0, 50, 0, 50, 0, 0, 0, 0, 50, 0, 50,
+ 50, 0, 0, 0, 50, 0, 0, 0, 50, 0, 0, 0, 50, 0, 52, 53, 50,
+ 0, 50, 0, 50, 50, 50, 0, 57, 50, 51, 0, 50, 50, 50, 0, 50, 0,
+ 50, 0, 0, 0, 50, 0, 0, 0, 50, 0, 52, 53, 50, 0, 0, 0, 50,
+ 50, 0, 50, 0, 0, 0, 0, 50, 56, 50, 0, 0, 0, 0, 50, 0, 50,
+ 50, 0, 50, 54, 55, 50, 50, 0, 0, 0, 50, 50, 54, 55, 50, 0, 50,
+ 50, 0, 50, 50, 50, 0, 0, 0, 50, 0, 0, 0, 50, 50, 50, 0, 50,
+ 50, 52, 53, 0, 0, 0, 0, 50, 50, 50, 0, 0, 0, 0, 52, 53, 50,
+ 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0
+ }
+ },
+ {
+ { // Test mode, floor 0
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 56, 0, 50, 0, 0, 52, 53, 0, 0, 0, 0, 52, 53, 0, 51, 50,
+ 50, 0, 0, 50, 0, 0, 0, 50, 0, 54, 55, 50, 0, 50, 50, 50, 50,
+ 50, 52, 53, 50, 50, 0, 0, 50, 50, 50, 50, 50, 0, 50, 0, 0, 50,
+ 50, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 50, 49, 50, 0, 0, 50,
+ 50, 0, 54, 55, 0, 50, 50, 54, 55, 0, 50, 50, 50, 0, 0, 0, 50,
+ 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 0, 0, 54, 55, 50,
+ 50, 0, 50, 0, 50, 0, 0, 50, 0, 0, 0, 50, 0, 0, 0, 0, 50,
+ 50, 0, 50, 0, 50, 54, 55, 50, 0, 50, 50, 50, 0, 50, 0, 0, 50,
+ 50, 50, 50, 50, 50, 0, 0, 50, 0, 0, 0, 0, 0, 50, 54, 55, 50,
+ 50, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 0, 0, 0, 50,
+ 50, 57, 0, 52, 53, 0, 0, 0, 0, 54, 55, 0, 0, 0, 0, 56, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50
+ },
+ { // Test mode, floor 1
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,
+ 50, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 54, 55, 0, 50,
+ 50, 0, 50, 52, 53, 0, 0, 50, 0, 0, 54, 55, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 0, 52, 53, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 50, 50, 50, 50, 49, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 0, 50, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 51, 0, 0, 52, 53, 50, 0, 50, 0, 50,
+ 50, 57, 50, 0, 50, 0, 50, 50, 50, 50, 50, 50, 50, 0, 50, 0, 50,
+ 50, 50, 50, 0, 50, 56, 0, 0, 0, 54, 55, 0, 0, 0, 50, 0, 50,
+ 50, 56, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 50,
+ 50, 50, 50, 50, 0, 0, 0, 0, 52, 53, 0, 0, 0, 0, 0, 0, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50
+ },
+ { // Test mode, floor 2
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 57, 50, 54, 55, 0, 50, 54, 55, 0, 50, 0, 52, 53, 50, 51, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 0, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 52, 53, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50, 0, 50,
+ 50, 0, 0, 0, 50, 0, 50, 0, 50, 0, 0, 0, 50, 0, 50, 0, 50,
+ 50, 0, 0, 0, 50, 52, 53, 0, 50, 52, 53, 56, 50, 0, 54, 55, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50
+ }
+ }
+};
+
+static const int kLanguageCount = 5;
+static const int kFallbackLanguage = 2; // English
+
+enum String {
+ kString3rdBasement = 0,
+ kString2ndBasement,
+ kString1stBasement,
+ kStringNoExit,
+ kStringYouHave,
+ kString2Exits,
+ kString1Exit,
+ kStringToReach,
+ kStringUpperLevel1,
+ kStringUpperLevel2,
+ kStringLevel0,
+ kStringPenetration,
+ kStringSuccessful,
+ kStringDanger,
+ kStringGynoides,
+ kStringActivated,
+ kStringCount
};
-Penetration::Penetration(GobEngine *vm) : _vm(vm), _background(0), _objects(0) {
+static const char *kStrings[kLanguageCount][kStringCount] = {
+ { // French
+ "3EME SOUS-SOL",
+ "2EME SOUS-SOL",
+ "1ER SOUS-SOL",
+ "SORTIE REFUSEE",
+ "Vous disposez",
+ "de deux sorties",
+ "d\'une sortie",
+ "pour l\'acc\212s au",
+ "niveau",
+ "sup\202rieur",
+ "- NIVEAU 0 -",
+ "PENETRATION",
+ "REUSSIE",
+ "DANGER",
+ "GYNOIDES",
+ "ACTIVEES"
+ },
+ { // German
+ // NOTE: The original had very broken German there. We provide proper(ish) German instead.
+ // B0rken text in the comments after each line
+ "3. UNTERGESCHOSS", // "3. U.-GESCHOSS""
+ "2. UNTERGESCHOSS", // "2. U.-GESCHOSS"
+ "1. UNTERGESCHOSS", // "1. U.-GESCHOSS"
+ "AUSGANG GESPERRT",
+ "Sie haben",
+ "zwei Ausg\204nge", // "zwei Ausgang"
+ "einen Ausgang", // "Fortsetztung"
+ "um das obere", // ""
+ "Stockwerk zu", // ""
+ "erreichen", // ""
+ "- STOCKWERK 0 -", // "0 - HOHE"
+ "PENETRATION", // "DURCHDRIGEN"
+ "ERFOLGREICH", // "ERFOLG"
+ "GEFAHR",
+ "GYNOIDE",
+ "AKTIVIERT",
+ },
+ { // English
+ "3RD BASEMENT",
+ "2ND BASEMENT",
+ "1ST BASEMENT",
+ "NO EXIT",
+ "You have",
+ "2 exits",
+ "1 exit",
+ "to reach upper",
+ "level",
+ "",
+ "- 0 LEVEL -",
+ "PENETRATION",
+ "SUCCESSFUL",
+ "DANGER",
+ "GYNOIDES",
+ "ACTIVATED",
+ },
+ { // Spanish
+ "3ER. SUBSUELO",
+ "2D. SUBSUELO",
+ "1ER. SUBSUELO",
+ "SALIDA RECHAZADA",
+ "Dispones",
+ "de dos salidas",
+ "de una salida",
+ "para acceso al",
+ "nivel",
+ "superior",
+ "- NIVEL 0 -",
+ "PENETRACION",
+ "CONSEGUIDA",
+ "PELIGRO",
+ "GYNOIDAS",
+ "ACTIVADAS",
+ },
+ { // Italian
+ "SOTTOSUOLO 3",
+ "SOTTOSUOLO 2",
+ "SOTTOSUOLO 1",
+ "NON USCITA",
+ "avete",
+ "due uscite",
+ "un\' uscita",
+ "per accedere al",
+ "livello",
+ "superiore",
+ "- LIVELLO 0 -",
+ "PENETRAZIONE",
+ "RIUSCITA",
+ "PERICOLO",
+ "GYNOIDI",
+ "ATTIVATE",
+ }
+};
+
+
+Penetration::MapObject::MapObject(uint16 tX, uint16 tY, uint16 mX, uint16 mY, uint16 w, uint16 h) :
+ tileX(tX), tileY(tY), mapX(mX), mapY(mY), width(w), height(h) {
+
+ isBlocking = true;
+}
+
+Penetration::MapObject::MapObject(uint16 tX, uint16 tY, uint16 w, uint16 h) :
+ tileX(tX), tileY(tY), width(w), height(h) {
+
+ isBlocking = true;
+
+ setMapFromTilePosition();
+}
+
+void Penetration::MapObject::setTileFromMapPosition() {
+ tileX = (mapX + (width / 2)) / kMapTileWidth;
+ tileY = (mapY + (height / 2)) / kMapTileHeight;
+}
+
+void Penetration::MapObject::setMapFromTilePosition() {
+ mapX = tileX * kMapTileWidth;
+ mapY = tileY * kMapTileHeight;
+}
+
+bool Penetration::MapObject::isIn(uint16 mX, uint16 mY) const {
+ if ((mX < mapX) || (mY < mapY))
+ return false;
+ if ((mX > (mapX + width - 1)) || (mY > (mapY + height - 1)))
+ return false;
+
+ return true;
+}
+
+bool Penetration::MapObject::isIn(uint16 mX, uint16 mY, uint16 w, uint16 h) const {
+ return isIn(mX , mY ) ||
+ isIn(mX + w - 1, mY ) ||
+ isIn(mX , mY + h - 1) ||
+ isIn(mX + w - 1, mY + h - 1);
+}
+
+bool Penetration::MapObject::isIn(const MapObject &obj) const {
+ return isIn(obj.mapX, obj.mapY, obj.width, obj.height);
+}
+
+
+Penetration::ManagedMouth::ManagedMouth(uint16 tX, uint16 tY, MouthType t) :
+ MapObject(tX, tY, 0, 0), mouth(0), type(t) {
+
+}
+
+Penetration::ManagedMouth::~ManagedMouth() {
+ delete mouth;
+}
+
+
+Penetration::ManagedSub::ManagedSub(uint16 tX, uint16 tY) :
+ MapObject(tX, tY, kMapTileWidth, kMapTileHeight), sub(0) {
+
+}
+
+Penetration::ManagedSub::~ManagedSub() {
+ delete sub;
+}
+
+
+Penetration::ManagedEnemy::ManagedEnemy() : MapObject(0, 0, 0, 0), enemy(0), dead(false) {
+}
+
+Penetration::ManagedEnemy::~ManagedEnemy() {
+ delete enemy;
+}
+
+void Penetration::ManagedEnemy::clear() {
+ delete enemy;
+
+ enemy = 0;
+}
+
+
+Penetration::ManagedBullet::ManagedBullet() : MapObject(0, 0, 0, 0), bullet(0) {
+}
+
+Penetration::ManagedBullet::~ManagedBullet() {
+ delete bullet;
+}
+
+void Penetration::ManagedBullet::clear() {
+ delete bullet;
+
+ bullet = 0;
+}
+
+
+Penetration::Penetration(GobEngine *vm) : _vm(vm), _background(0), _sprites(0), _objects(0), _sub(0),
+ _shieldMeter(0), _healthMeter(0), _floor(0), _isPlaying(false) {
+
_background = new Surface(320, 200, 1);
+
+ _shieldMeter = new Meter(11, 119, 92, 3, kColorShield, kColorBlack, 920, Meter::kFillToRight);
+ _healthMeter = new Meter(11, 137, 92, 3, kColorHealth, kColorBlack, 920, Meter::kFillToRight);
+
+ _map = new Surface(kMapWidth * kMapTileWidth + kPlayAreaWidth ,
+ kMapHeight * kMapTileHeight + kPlayAreaHeight, 1);
}
Penetration::~Penetration() {
deinit();
+ delete _map;
+
+ delete _shieldMeter;
+ delete _healthMeter;
+
delete _background;
}
-bool Penetration::play(uint16 var1, uint16 var2, uint16 var3) {
+bool Penetration::play(bool hasAccessPass, bool hasMaxEnergy, bool testMode) {
+ _hasAccessPass = hasAccessPass;
+ _hasMaxEnergy = hasMaxEnergy;
+ _testMode = testMode;
+
+ _isPlaying = true;
+
init();
initScreen();
+ drawFloorText();
+
_vm->_draw->blitInvalidated();
_vm->_video->retrace();
- while (!_vm->_util->keyPressed() && !_vm->shouldQuit())
- _vm->_util->longDelay(1);
+
+ while (!_vm->shouldQuit() && !_quit && !isDead() && !hasWon()) {
+ enemiesCreate();
+ bulletsMove();
+ updateAnims();
+
+ // Draw, fade in if necessary and wait for the end of the frame
+ _vm->_draw->blitInvalidated();
+ fadeIn();
+ _vm->_util->waitEndFrame(false);
+
+ // Handle the input
+ checkInput();
+
+ // Handle the sub movement
+ handleSub();
+
+ // Handle the enemies movement
+ enemiesMove();
+
+ checkExited();
+
+ if (_shotCoolDown > 0)
+ _shotCoolDown--;
+ }
deinit();
- return true;
+ drawEndText();
+
+ _isPlaying = false;
+
+ return hasWon();
+}
+
+bool Penetration::isPlaying() const {
+ return _isPlaying;
+}
+
+void Penetration::cheatWin() {
+ _floor = 3;
}
void Penetration::init() {
+ // Load sounds
+ _vm->_sound->sampleLoad(&_soundShield , SOUND_SND, "boucl.snd");
+ _vm->_sound->sampleLoad(&_soundBite , SOUND_SND, "pervet.snd");
+ _vm->_sound->sampleLoad(&_soundKiss , SOUND_SND, "baise.snd");
+ _vm->_sound->sampleLoad(&_soundShoot , SOUND_SND, "tirgim.snd");
+ _vm->_sound->sampleLoad(&_soundExit , SOUND_SND, "trouve.snd");
+ _vm->_sound->sampleLoad(&_soundExplode, SOUND_SND, "virmor.snd");
+
+ _quit = false;
+ for (int i = 0; i < kKeyCount; i++)
+ _keys[i] = false;
+
_background->clear();
_vm->_video->drawPackedSprite("hyprmef2.cmp", *_background);
+ _sprites = new CMPFile(_vm, "tcifplai.cmp", 320, 200);
_objects = new ANIFile(_vm, "tcite.ani", 320);
+
+ // The shield starts down
+ _shieldMeter->setValue(0);
+
+ // If we don't have the max energy tokens, the health starts at 1/3 strength
+ if (_hasMaxEnergy)
+ _healthMeter->setMaxValue();
+ else
+ _healthMeter->setValue(_healthMeter->getMaxValue() / 3);
+
+ _floor = 0;
+
+ _shotCoolDown = 0;
+
+ createMap();
}
void Penetration::deinit() {
+ _soundShield.free();
+ _soundBite.free();
+ _soundKiss.free();
+ _soundShoot.free();
+ _soundExit.free();
+ _soundExplode.free();
+
+ clearMap();
+
delete _objects;
+ delete _sprites;
_objects = 0;
+ _sprites = 0;
+}
+
+void Penetration::clearMap() {
+ _mapAnims.clear();
+ _anims.clear();
+
+ _blockingObjects.clear();
+
+ _walls.clear();
+ _exits.clear();
+ _shields.clear();
+ _mouths.clear();
+
+ for (int i = 0; i < kEnemyCount; i++)
+ _enemies[i].clear();
+ for (int i = 0; i < kMaxBulletCount; i++)
+ _bullets[i].clear();
+
+ delete _sub;
+
+ _sub = 0;
+
+ _map->fill(kColorBlack);
+}
+
+void Penetration::createMap() {
+ if (_floor >= kFloorCount)
+ error("Geisha: Invalid floor %d in minigame penetration", _floor);
+
+ clearMap();
+
+ const byte *mapTiles = kMaps[_testMode ? 1 : 0][_floor];
+
+ bool exitWorks;
+
+ // Draw the map tiles
+ for (int y = 0; y < kMapHeight; y++) {
+ for (int x = 0; x < kMapWidth; x++) {
+ const byte mapTile = mapTiles[y * kMapWidth + x];
+
+ const int posX = kPlayAreaBorderWidth + x * kMapTileWidth;
+ const int posY = kPlayAreaBorderHeight + y * kMapTileHeight;
+
+ switch (mapTile) {
+ case 0: // Floor
+ _sprites->draw(*_map, kSpriteFloor, posX, posY);
+ break;
+
+ case 49: // Emergency exit (needs access pass)
+
+ exitWorks = _hasAccessPass;
+ if (exitWorks) {
+ _sprites->draw(*_map, kSpriteExit, posX, posY);
+ _exits.push_back(MapObject(x, y, 0, 0));
+ } else {
+ _sprites->draw(*_map, kSpriteWall, posX, posY);
+ _walls.push_back(MapObject(x, y, kMapTileWidth, kMapTileHeight));
+ }
+
+ break;
+
+ case 50: // Wall
+ _sprites->draw(*_map, kSpriteWall, posX, posY);
+ _walls.push_back(MapObject(x, y, kMapTileWidth, kMapTileHeight));
+ break;
+
+ case 51: // Regular exit
+
+ // A regular exit works always in test mode.
+ // But if we're in real mode, and on the last floor, it needs an access pass
+ exitWorks = _testMode || (_floor < 2) || _hasAccessPass;
+
+ if (exitWorks) {
+ _sprites->draw(*_map, kSpriteExit, posX, posY);
+ _exits.push_back(MapObject(x, y, 0, 0));
+ } else {
+ _sprites->draw(*_map, kSpriteWall, posX, posY);
+ _walls.push_back(MapObject(x, y, kMapTileWidth, kMapTileHeight));
+ }
+
+ break;
+
+ case 52: // Left side of biting mouth
+ _mouths.push_back(ManagedMouth(x, y, kMouthTypeBite));
+
+ _mouths.back().mouth =
+ new Mouth(*_objects, *_sprites, kAnimationMouthBite, kSpriteMouthBite, kSpriteFloor);
+
+ _mouths.back().mouth->setPosition(posX, posY);
+ break;
+
+ case 53: // Right side of biting mouth
+ break;
+
+ case 54: // Left side of kissing mouth
+ _mouths.push_back(ManagedMouth(x, y, kMouthTypeKiss));
+
+ _mouths.back().mouth =
+ new Mouth(*_objects, *_sprites, kAnimationMouthKiss, kSpriteMouthKiss, kSpriteFloor);
+
+ _mouths.back().mouth->setPosition(posX, posY);
+ break;
+
+ case 55: // Right side of kissing mouth
+ break;
+
+ case 56: // Shield lying on the floor
+ _sprites->draw(*_map, kSpriteFloor , posX , posY ); // Floor
+ _sprites->draw(*_map, kSpriteFloorShield, posX + 4, posY + 8); // Shield
+
+ _map->fillRect(posX + 4, posY + 8, posX + 7, posY + 18, kColorFloor); // Area left to shield
+ _map->fillRect(posX + 17, posY + 8, posX + 20, posY + 18, kColorFloor); // Area right to shield
+
+ _shields.push_back(MapObject(x, y, 0, 0));
+ break;
+
+ case 57: // Start position
+ _sprites->draw(*_map, kSpriteFloor, posX, posY);
+
+ delete _sub;
+
+ _sub = new ManagedSub(x, y);
+
+ _sub->sub = new Submarine(*_objects);
+ _sub->sub->setPosition(kPlayAreaX + kPlayAreaBorderWidth, kPlayAreaY + kPlayAreaBorderHeight);
+ break;
+ }
+ }
+ }
+
+ if (!_sub)
+ error("Geisha: No starting position in floor %d (testmode: %d)", _floor, _testMode);
+
+ // Walls
+ for (Common::List<MapObject>::iterator w = _walls.begin(); w != _walls.end(); ++w)
+ _blockingObjects.push_back(&*w);
+
+ // Mouths
+ for (Common::List<ManagedMouth>::iterator m = _mouths.begin(); m != _mouths.end(); ++m)
+ _mapAnims.push_back(m->mouth);
+
+ // Sub
+ _blockingObjects.push_back(_sub);
+ _anims.push_back(_sub->sub);
+
+ // Moving enemies
+ for (int i = 0; i < kEnemyCount; i++) {
+ _enemies[i].enemy = new ANIObject(*_objects);
+
+ _enemies[i].enemy->setPause(true);
+ _enemies[i].enemy->setVisible(false);
+
+ _enemies[i].isBlocking = false;
+
+ _blockingObjects.push_back(&_enemies[i]);
+ _mapAnims.push_back(_enemies[i].enemy);
+ }
+
+ // Bullets
+ for (int i = 0; i < kMaxBulletCount; i++) {
+ _bullets[i].bullet = new ANIObject(*_sprites);
+
+ _bullets[i].bullet->setPause(true);
+ _bullets[i].bullet->setVisible(false);
+
+ _bullets[i].isBlocking = false;
+
+ _mapAnims.push_back(_bullets[i].bullet);
+ }
+}
+
+void Penetration::drawFloorText() {
+ _vm->_draw->_backSurface->fillRect(kTextAreaLeft, kTextAreaTop, kTextAreaRight, kTextAreaBottom, kColorBlack);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, kTextAreaLeft, kTextAreaTop, kTextAreaRight, kTextAreaBottom);
+
+ const Font *font = _vm->_draw->_fonts[2];
+ if (!font)
+ return;
+
+ const char **strings = kStrings[getLanguage()];
+
+ const char *floorString = 0;
+ if (_floor == 0)
+ floorString = strings[kString3rdBasement];
+ else if (_floor == 1)
+ floorString = strings[kString2ndBasement];
+ else if (_floor == 2)
+ floorString = strings[kString1stBasement];
+
+ Surface &surface = *_vm->_draw->_backSurface;
+
+ if (floorString)
+ font->drawString(floorString, 10, 15, kColorFloorText, kColorBlack, 1, surface);
+
+ if (_exits.size() > 0) {
+ int exitCount = kString2Exits;
+ if (_exits.size() == 1)
+ exitCount = kString1Exit;
+
+ font->drawString(strings[kStringYouHave] , 10, 38, kColorExitText, kColorBlack, 1, surface);
+ font->drawString(strings[exitCount] , 10, 53, kColorExitText, kColorBlack, 1, surface);
+ font->drawString(strings[kStringToReach] , 10, 68, kColorExitText, kColorBlack, 1, surface);
+ font->drawString(strings[kStringUpperLevel1], 10, 84, kColorExitText, kColorBlack, 1, surface);
+ font->drawString(strings[kStringUpperLevel2], 10, 98, kColorExitText, kColorBlack, 1, surface);
+
+ } else
+ font->drawString(strings[kStringNoExit], 10, 53, kColorExitText, kColorBlack, 1, surface);
+}
+
+void Penetration::drawEndText() {
+ // Only draw the end text when we've won and this isn't a test run
+ if (!hasWon() || _testMode)
+ return;
+
+ _vm->_draw->_backSurface->fillRect(kTextAreaLeft, kTextAreaTop, kTextAreaRight, kTextAreaBigBottom, kColorBlack);
+
+ const Font *font = _vm->_draw->_fonts[2];
+ if (!font)
+ return;
+
+ Surface &surface = *_vm->_draw->_backSurface;
+
+ const char **strings = kStrings[getLanguage()];
+
+ font->drawString(strings[kStringLevel0] , 11, 21, kColorExitText, kColorBlack, 1, surface);
+ font->drawString(strings[kStringPenetration], 11, 42, kColorExitText, kColorBlack, 1, surface);
+ font->drawString(strings[kStringSuccessful] , 11, 58, kColorExitText, kColorBlack, 1, surface);
+
+ font->drawString(strings[kStringDanger] , 11, 82, kColorFloorText, kColorBlack, 1, surface);
+ font->drawString(strings[kStringGynoides] , 11, 98, kColorFloorText, kColorBlack, 1, surface);
+ font->drawString(strings[kStringActivated], 11, 113, kColorFloorText, kColorBlack, 1, surface);
+
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, kTextAreaLeft, kTextAreaTop, kTextAreaRight, kTextAreaBigBottom);
+ _vm->_draw->blitInvalidated();
+ _vm->_video->retrace();
+}
+
+void Penetration::fadeIn() {
+ if (!_needFadeIn)
+ return;
+
+ // Fade to palette
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
+ _needFadeIn = false;
+}
+
+void Penetration::setPalette() {
+ // Fade to black
+ _vm->_palAnim->fade(0, 0, 0);
+
+ // Set palette
+ memcpy(_vm->_draw->_vgaPalette , kPalettes[_floor], 3 * kPaletteSize);
+ memcpy(_vm->_draw->_vgaSmallPalette, kPalettes[_floor], 3 * kPaletteSize);
+
+ _needFadeIn = true;
}
void Penetration::initScreen() {
_vm->_util->setFrameRate(15);
- memcpy(_vm->_draw->_vgaPalette , kPalette, 48);
- memcpy(_vm->_draw->_vgaSmallPalette, kPalette, 48);
+ setPalette();
+
+ // Draw the shield meter
+ _sprites->draw(*_background, 0, 0, 95, 6, 9, 117, 0); // Meter frame
+ _sprites->draw(*_background, 271, 176, 282, 183, 9, 108, 0); // Shield
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ // Draw the health meter
+ _sprites->draw(*_background, 0, 0, 95, 6, 9, 135, 0); // Meter frame
+ _sprites->draw(*_background, 283, 176, 292, 184, 9, 126, 0); // Heart
_vm->_draw->_backSurface->blit(*_background);
_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
}
+void Penetration::enemiesCreate() {
+ for (int i = 0; i < kEnemyCount; i++) {
+ ManagedEnemy &enemy = _enemies[i];
+
+ if (enemy.enemy->isVisible())
+ continue;
+
+ enemy.enemy->setAnimation((i & 1) ? kAnimationEnemySquare : kAnimationEnemyRound);
+ enemy.enemy->setMode(ANIObject::kModeContinuous);
+ enemy.enemy->setPause(false);
+ enemy.enemy->setVisible(true);
+
+ int16 width, height;
+ enemy.enemy->getFrameSize(width, height);
+
+ enemy.width = width;
+ enemy.height = height;
+
+ do {
+ enemy.mapX = _vm->_util->getRandom(kMapWidth) * kMapTileWidth + 2;
+ enemy.mapY = _vm->_util->getRandom(kMapHeight) * kMapTileHeight + 4;
+ enemy.setTileFromMapPosition();
+ } while (isBlocked(enemy, enemy.mapX, enemy.mapY));
+
+ const int posX = kPlayAreaBorderWidth + enemy.mapX;
+ const int posY = kPlayAreaBorderHeight + enemy.mapY;
+
+ enemy.enemy->setPosition(posX, posY);
+
+ enemy.isBlocking = true;
+ enemy.dead = false;
+ }
+}
+
+void Penetration::enemyMove(ManagedEnemy &enemy, int x, int y) {
+ if ((x == 0) && (y == 0))
+ return;
+
+ MapObject *blockedBy;
+ findPath(enemy, x, y, &blockedBy);
+
+ enemy.setTileFromMapPosition();
+
+ const int posX = kPlayAreaBorderWidth + enemy.mapX;
+ const int posY = kPlayAreaBorderHeight + enemy.mapY;
+
+ enemy.enemy->setPosition(posX, posY);
+
+ if (blockedBy == _sub)
+ enemyAttack(enemy);
+}
+
+void Penetration::enemiesMove() {
+ for (int i = 0; i < kEnemyCount; i++) {
+ ManagedEnemy &enemy = _enemies[i];
+
+ if (!enemy.enemy->isVisible() || enemy.dead)
+ continue;
+
+ int x = 0, y = 0;
+
+ if (enemy.mapX > _sub->mapX)
+ x = -8;
+ else if (enemy.mapX < _sub->mapX)
+ x = 8;
+
+ if (enemy.mapY > _sub->mapY)
+ y = -8;
+ else if (enemy.mapY < _sub->mapY)
+ y = 8;
+
+ enemyMove(enemy, x, y);
+ }
+}
+
+void Penetration::enemyAttack(ManagedEnemy &enemy) {
+ // If we have shields, the enemy explodes at them, taking a huge chunk of energy with it.
+ // Otherwise, the enemy nibbles a small amount of health away.
+
+ if (_shieldMeter->getValue() > 0) {
+ enemyExplode(enemy);
+
+ healthLose(80);
+ } else
+ healthLose(5);
+}
+
+void Penetration::enemyExplode(ManagedEnemy &enemy) {
+ enemy.dead = true;
+ enemy.isBlocking = false;
+
+ bool isSquare = enemy.enemy->getAnimation() == kAnimationEnemySquare;
+
+ enemy.enemy->setAnimation(isSquare ? kAnimationEnemySquareExplode : kAnimationEnemyRoundExplode);
+ enemy.enemy->setMode(ANIObject::kModeOnce);
+
+ _vm->_sound->blasterPlay(&_soundExplode, 1, 0);
+}
+
+void Penetration::checkInput() {
+ Common::Event event;
+ Common::EventManager *eventMan = g_system->getEventManager();
+
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
+ _quit = true;
+ else if (event.kbd.keycode == Common::KEYCODE_UP)
+ _keys[kKeyUp ] = true;
+ else if (event.kbd.keycode == Common::KEYCODE_DOWN)
+ _keys[kKeyDown ] = true;
+ else if (event.kbd.keycode == Common::KEYCODE_LEFT)
+ _keys[kKeyLeft ] = true;
+ else if (event.kbd.keycode == Common::KEYCODE_RIGHT)
+ _keys[kKeyRight] = true;
+ else if (event.kbd.keycode == Common::KEYCODE_SPACE)
+ _keys[kKeySpace] = true;
+ else if (event.kbd.keycode == Common::KEYCODE_d) {
+ _vm->getDebugger()->attach();
+ _vm->getDebugger()->onFrame();
+ }
+ break;
+
+ case Common::EVENT_KEYUP:
+ if (event.kbd.keycode == Common::KEYCODE_UP)
+ _keys[kKeyUp ] = false;
+ else if (event.kbd.keycode == Common::KEYCODE_DOWN)
+ _keys[kKeyDown ] = false;
+ else if (event.kbd.keycode == Common::KEYCODE_LEFT)
+ _keys[kKeyLeft ] = false;
+ else if (event.kbd.keycode == Common::KEYCODE_RIGHT)
+ _keys[kKeyRight] = false;
+ else if (event.kbd.keycode == Common::KEYCODE_SPACE)
+ _keys[kKeySpace] = false;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void Penetration::handleSub() {
+ int x, y;
+ Submarine::Direction direction = getDirection(x, y);
+
+ subMove(x, y, direction);
+
+ if (_keys[kKeySpace])
+ subShoot();
+}
+
+bool Penetration::isBlocked(const MapObject &self, int16 x, int16 y, MapObject **blockedBy) {
+
+ if ((x < 0) || (y < 0))
+ return true;
+ if (((x + self.width - 1) >= (kMapWidth * kMapTileWidth)) ||
+ ((y + self.height - 1) >= (kMapHeight * kMapTileHeight)))
+ return true;
+
+ MapObject checkSelf(0, 0, self.width, self.height);
+
+ checkSelf.mapX = x;
+ checkSelf.mapY = y;
+
+ for (Common::List<MapObject *>::iterator o = _blockingObjects.begin(); o != _blockingObjects.end(); ++o) {
+ MapObject &obj = **o;
+
+ if (&obj == &self)
+ continue;
+
+ if (!obj.isBlocking)
+ continue;
+
+ if (obj.isIn(checkSelf) || checkSelf.isIn(obj)) {
+ if (blockedBy && !*blockedBy)
+ *blockedBy = &obj;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Penetration::findPath(MapObject &obj, int x, int y, MapObject **blockedBy) {
+ if (blockedBy)
+ *blockedBy = 0;
+
+ while ((x != 0) || (y != 0)) {
+ uint16 oldX = obj.mapX;
+ uint16 oldY = obj.mapY;
+
+ uint16 newX = obj.mapX;
+ if (x > 0) {
+ newX++;
+ x--;
+ } else if (x < 0) {
+ newX--;
+ x++;
+ }
+
+ if (!isBlocked(obj, newX, obj.mapY, blockedBy))
+ obj.mapX = newX;
+
+ uint16 newY = obj.mapY;
+ if (y > 0) {
+ newY++;
+ y--;
+ } else if (y < 0) {
+ newY--;
+ y++;
+ }
+
+ if (!isBlocked(obj, obj.mapX, newY, blockedBy))
+ obj.mapY = newY;
+
+ if ((obj.mapX == oldX) && (obj.mapY == oldY))
+ break;
+ }
+}
+
+void Penetration::subMove(int x, int y, Submarine::Direction direction) {
+ if (!_sub->sub->canMove())
+ return;
+
+ if ((x == 0) && (y == 0))
+ return;
+
+ findPath(*_sub, x, y);
+
+ _sub->setTileFromMapPosition();
+
+ _sub->sub->turn(direction);
+
+ checkShields();
+ checkMouths();
+ checkExits();
+}
+
+void Penetration::subShoot() {
+ if (!_sub->sub->canMove() || _sub->sub->isShooting())
+ return;
+
+ if (_shotCoolDown > 0)
+ return;
+
+ // Creating a bullet
+ int slot = findEmptyBulletSlot();
+ if (slot < 0)
+ return;
+
+ ManagedBullet &bullet = _bullets[slot];
+
+ bullet.bullet->setAnimation(directionToBullet(_sub->sub->getDirection()));
+
+ setBulletPosition(*_sub, bullet);
+
+ const int posX = kPlayAreaBorderWidth + bullet.mapX;
+ const int posY = kPlayAreaBorderHeight + bullet.mapY;
+
+ bullet.bullet->setPosition(posX, posY);
+ bullet.bullet->setVisible(true);
+
+ // Shooting
+ _sub->sub->shoot();
+ _vm->_sound->blasterPlay(&_soundShoot, 1, 0);
+
+ _shotCoolDown = 3;
+}
+
+void Penetration::setBulletPosition(const ManagedSub &sub, ManagedBullet &bullet) const {
+ bullet.mapX = sub.mapX;
+ bullet.mapY= sub.mapY;
+
+ int16 sWidth, sHeight;
+ sub.sub->getFrameSize(sWidth, sHeight);
+
+ int16 bWidth, bHeight;
+ bullet.bullet->getFrameSize(bWidth, bHeight);
+
+ switch (sub.sub->getDirection()) {
+ case Submarine::kDirectionN:
+ bullet.mapX += sWidth / 2;
+ bullet.mapY -= bHeight;
+
+ bullet.deltaX = 0;
+ bullet.deltaY = -8;
+ break;
+
+ case Submarine::kDirectionNE:
+ bullet.mapX += sWidth;
+ bullet.mapY -= bHeight * 2;
+
+ bullet.deltaX = 8;
+ bullet.deltaY = -8;
+ break;
+
+ case Submarine::kDirectionE:
+ bullet.mapX += sWidth;
+ bullet.mapY += sHeight / 2 - bHeight;
+
+ bullet.deltaX = 8;
+ bullet.deltaY = 0;
+ break;
+
+ case Submarine::kDirectionSE:
+ bullet.mapX += sWidth;
+ bullet.mapY += sHeight;
+
+ bullet.deltaX = 8;
+ bullet.deltaY = 8;
+ break;
+
+ case Submarine::kDirectionS:
+ bullet.mapX += sWidth / 2;
+ bullet.mapY += sHeight;
+
+ bullet.deltaX = 0;
+ bullet.deltaY = 8;
+ break;
+
+ case Submarine::kDirectionSW:
+ bullet.mapX -= bWidth;
+ bullet.mapY += sHeight;
+
+ bullet.deltaX = -8;
+ bullet.deltaY = 8;
+ break;
+
+ case Submarine::kDirectionW:
+ bullet.mapX -= bWidth;
+ bullet.mapY += sHeight / 2 - bHeight;
+
+ bullet.deltaX = -8;
+ bullet.deltaY = 0;
+ break;
+
+ case Submarine::kDirectionNW:
+ bullet.mapX -= bWidth;
+ bullet.mapY -= bHeight;
+
+ bullet.deltaX = -8;
+ bullet.deltaY = -8;
+ break;
+
+ default:
+ break;
+ }
+}
+
+uint16 Penetration::directionToBullet(Submarine::Direction direction) const {
+ switch (direction) {
+ case Submarine::kDirectionN:
+ return kSpriteBulletN;
+
+ case Submarine::kDirectionNE:
+ return kSpriteBulletNE;
+
+ case Submarine::kDirectionE:
+ return kSpriteBulletE;
+
+ case Submarine::kDirectionSE:
+ return kSpriteBulletSE;
+
+ case Submarine::kDirectionS:
+ return kSpriteBulletS;
+
+ case Submarine::kDirectionSW:
+ return kSpriteBulletSW;
+
+ case Submarine::kDirectionW:
+ return kSpriteBulletW;
+
+ case Submarine::kDirectionNW:
+ return kSpriteBulletNW;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int Penetration::findEmptyBulletSlot() const {
+ for (int i = 0; i < kMaxBulletCount; i++)
+ if (!_bullets[i].bullet->isVisible())
+ return i;
+
+ return -1;
+}
+
+void Penetration::bulletsMove() {
+ for (int i = 0; i < kMaxBulletCount; i++)
+ if (_bullets[i].bullet->isVisible())
+ bulletMove(_bullets[i]);
+}
+
+void Penetration::bulletMove(ManagedBullet &bullet) {
+ MapObject *blockedBy;
+ findPath(bullet, bullet.deltaX, bullet.deltaY, &blockedBy);
+
+ if (blockedBy) {
+ checkShotEnemy(*blockedBy);
+ bullet.bullet->setVisible(false);
+ return;
+ }
+
+ const int posX = kPlayAreaBorderWidth + bullet.mapX;
+ const int posY = kPlayAreaBorderHeight + bullet.mapY;
+
+ bullet.bullet->setPosition(posX, posY);
+}
+
+void Penetration::checkShotEnemy(MapObject &shotObject) {
+ for (int i = 0; i < kEnemyCount; i++) {
+ ManagedEnemy &enemy = _enemies[i];
+
+ if ((&enemy == &shotObject) && !enemy.dead && enemy.enemy->isVisible()) {
+ enemyExplode(enemy);
+ return;
+ }
+ }
+}
+
+Submarine::Direction Penetration::getDirection(int &x, int &y) const {
+ x = _keys[kKeyRight] ? 3 : (_keys[kKeyLeft] ? -3 : 0);
+ y = _keys[kKeyDown ] ? 3 : (_keys[kKeyUp ] ? -3 : 0);
+
+ if ((x > 0) && (y > 0))
+ return Submarine::kDirectionSE;
+ if ((x > 0) && (y < 0))
+ return Submarine::kDirectionNE;
+ if ((x < 0) && (y > 0))
+ return Submarine::kDirectionSW;
+ if ((x < 0) && (y < 0))
+ return Submarine::kDirectionNW;
+ if (x > 0)
+ return Submarine::kDirectionE;
+ if (x < 0)
+ return Submarine::kDirectionW;
+ if (y > 0)
+ return Submarine::kDirectionS;
+ if (y < 0)
+ return Submarine::kDirectionN;
+
+ return Submarine::kDirectionNone;
+}
+
+void Penetration::checkShields() {
+ for (Common::List<MapObject>::iterator s = _shields.begin(); s != _shields.end(); ++s) {
+ if ((s->tileX == _sub->tileX) && (s->tileY == _sub->tileY)) {
+ // Charge shields
+ _shieldMeter->setMaxValue();
+
+ // Play the shield sound
+ _vm->_sound->blasterPlay(&_soundShield, 1, 0);
+
+ // Erase the shield from the map
+ _sprites->draw(*_map, 30, s->mapX + kPlayAreaBorderWidth, s->mapY + kPlayAreaBorderHeight);
+ _shields.erase(s);
+ break;
+ }
+ }
+}
+
+void Penetration::checkMouths() {
+ for (Common::List<ManagedMouth>::iterator m = _mouths.begin(); m != _mouths.end(); ++m) {
+ if (!m->mouth->isDeactivated())
+ continue;
+
+ if ((( m->tileX == _sub->tileX) && (m->tileY == _sub->tileY)) ||
+ (((m->tileX + 1) == _sub->tileX) && (m->tileY == _sub->tileY))) {
+
+ m->mouth->activate();
+
+ // Play the mouth sound and do health gain/loss
+ if (m->type == kMouthTypeBite) {
+ _vm->_sound->blasterPlay(&_soundBite, 1, 0);
+ healthLose(230);
+ } else if (m->type == kMouthTypeKiss) {
+ _vm->_sound->blasterPlay(&_soundKiss, 1, 0);
+ healthGain(120);
+ }
+ }
+ }
+}
+
+void Penetration::checkExits() {
+ if (!_sub->sub->canMove())
+ return;
+
+ for (Common::List<MapObject>::iterator e = _exits.begin(); e != _exits.end(); ++e) {
+ if ((e->tileX == _sub->tileX) && (e->tileY == _sub->tileY)) {
+ _sub->setMapFromTilePosition();
+
+ _sub->sub->leave();
+
+ _vm->_sound->blasterPlay(&_soundExit, 1, 0);
+ break;
+ }
+ }
+}
+
+void Penetration::healthGain(int amount) {
+ if (_shieldMeter->getValue() > 0)
+ _healthMeter->increase(_shieldMeter->increase(amount));
+ else
+ _healthMeter->increase(amount);
+}
+
+void Penetration::healthLose(int amount) {
+ _healthMeter->decrease(_shieldMeter->decrease(amount));
+
+ if (_healthMeter->getValue() == 0)
+ _sub->sub->die();
+}
+
+void Penetration::checkExited() {
+ if (_sub->sub->hasExited()) {
+ _floor++;
+
+ if (_floor >= kFloorCount)
+ return;
+
+ setPalette();
+ createMap();
+ drawFloorText();
+ }
+}
+
+bool Penetration::isDead() const {
+ return _sub && _sub->sub->isDead();
+}
+
+bool Penetration::hasWon() const {
+ return _floor >= kFloorCount;
+}
+
+int Penetration::getLanguage() const {
+ if (_vm->_global->_language < kLanguageCount)
+ return _vm->_global->_language;
+
+ return kFallbackLanguage;
+}
+
+void Penetration::updateAnims() {
+ int16 left = 0, top = 0, right = 0, bottom = 0;
+
+ // Clear the previous map animation frames
+ for (Common::List<ANIObject *>::iterator a = _mapAnims.reverse_begin();
+ a != _mapAnims.end(); --a) {
+
+ (*a)->clear(*_map, left, top, right, bottom);
+ }
+
+ // Draw the current map animation frames
+ for (Common::List<ANIObject *>::iterator a = _mapAnims.begin();
+ a != _mapAnims.end(); ++a) {
+
+ (*a)->draw(*_map, left, top, right, bottom);
+ (*a)->advance();
+ }
+
+ // Clear the previous animation frames
+ for (Common::List<ANIObject *>::iterator a = _anims.reverse_begin();
+ a != _anims.end(); --a) {
+
+ if ((*a)->clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ }
+
+ if (_sub) {
+ // Draw the map
+
+ _vm->_draw->_backSurface->blit(*_map, _sub->mapX, _sub->mapY,
+ _sub->mapX + kPlayAreaWidth - 1, _sub->mapY + kPlayAreaHeight - 1, kPlayAreaX, kPlayAreaY);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, kPlayAreaX, kPlayAreaY,
+ kPlayAreaX + kPlayAreaWidth - 1, kPlayAreaY + kPlayAreaHeight - 1);
+ }
+
+ // Draw the current animation frames
+ for (Common::List<ANIObject *>::iterator a = _anims.begin();
+ a != _anims.end(); ++a) {
+
+ if ((*a)->draw(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+
+ (*a)->advance();
+ }
+
+ // Draw the meters
+ _shieldMeter->draw(*_vm->_draw->_backSurface, left, top, right, bottom);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+
+ _healthMeter->draw(*_vm->_draw->_backSurface, left, top, right, bottom);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+}
+
} // End of namespace Geisha
} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/penetration.h b/engines/gob/minigames/geisha/penetration.h
index c346a7bf5a..50004eba8e 100644
--- a/engines/gob/minigames/geisha/penetration.h
+++ b/engines/gob/minigames/geisha/penetration.h
@@ -24,34 +24,229 @@
#define GOB_MINIGAMES_GEISHA_PENETRATION_H
#include "common/system.h"
+#include "common/list.h"
+
+#include "gob/sound/sounddesc.h"
+
+#include "gob/minigames/geisha/submarine.h"
namespace Gob {
class GobEngine;
class Surface;
+class CMPFile;
class ANIFile;
namespace Geisha {
+class Meter;
+class Mouth;
+
/** Geisha's "Penetration" minigame. */
class Penetration {
public:
Penetration(GobEngine *vm);
~Penetration();
- bool play(uint16 var1, uint16 var2, uint16 var3);
+ bool play(bool hasAccessPass, bool hasMaxEnergy, bool testMode);
+
+ bool isPlaying() const;
+ void cheatWin();
private:
+ static const int kModeCount = 2;
+ static const int kFloorCount = 3;
+
+ static const int kMapWidth = 17;
+ static const int kMapHeight = 13;
+
+ static const int kPaletteSize = 16;
+
+ static const byte kPalettes[kFloorCount][3 * kPaletteSize];
+ static const byte kMaps[kModeCount][kFloorCount][kMapWidth * kMapHeight];
+
+ static const int kEnemyCount = 9;
+ static const int kMaxBulletCount = 10;
+
+ struct MapObject {
+ uint16 tileX;
+ uint16 tileY;
+
+ uint16 mapX;
+ uint16 mapY;
+
+ uint16 width;
+ uint16 height;
+
+ bool isBlocking;
+
+ MapObject(uint16 tX, uint16 tY, uint16 mX, uint16 mY, uint16 w, uint16 h);
+ MapObject(uint16 tX, uint16 tY, uint16 w, uint16 h);
+
+ void setTileFromMapPosition();
+ void setMapFromTilePosition();
+
+ bool isIn(uint16 mX, uint16 mY) const;
+ bool isIn(uint16 mX, uint16 mY, uint16 w, uint16 h) const;
+ bool isIn(const MapObject &obj) const;
+ };
+
+ enum MouthType {
+ kMouthTypeBite,
+ kMouthTypeKiss
+ };
+
+ struct ManagedMouth : public MapObject {
+ Mouth *mouth;
+
+ MouthType type;
+
+ ManagedMouth(uint16 tX, uint16 tY, MouthType t);
+ ~ManagedMouth();
+ };
+
+ struct ManagedSub : public MapObject {
+ Submarine *sub;
+
+ ManagedSub(uint16 tX, uint16 tY);
+ ~ManagedSub();
+ };
+
+ struct ManagedEnemy : public MapObject {
+ ANIObject *enemy;
+
+ bool dead;
+
+ ManagedEnemy();
+ ~ManagedEnemy();
+
+ void clear();
+ };
+
+ struct ManagedBullet : public MapObject {
+ ANIObject *bullet;
+
+ int16 deltaX;
+ int16 deltaY;
+
+ ManagedBullet();
+ ~ManagedBullet();
+
+ void clear();
+ };
+
+ enum Keys {
+ kKeyUp = 0,
+ kKeyDown,
+ kKeyLeft,
+ kKeyRight,
+ kKeySpace,
+ kKeyCount
+ };
+
GobEngine *_vm;
+ bool _hasAccessPass;
+ bool _hasMaxEnergy;
+ bool _testMode;
+
+ bool _needFadeIn;
+
+ bool _quit;
+ bool _keys[kKeyCount];
+
Surface *_background;
+ CMPFile *_sprites;
ANIFile *_objects;
+ Common::List<ANIObject *> _anims;
+ Common::List<ANIObject *> _mapAnims;
+
+ Meter *_shieldMeter;
+ Meter *_healthMeter;
+
+ uint8 _floor;
+
+ Surface *_map;
+
+ ManagedSub *_sub;
+
+ Common::List<MapObject> _walls;
+ Common::List<MapObject> _exits;
+ Common::List<MapObject> _shields;
+ Common::List<ManagedMouth> _mouths;
+
+ ManagedEnemy _enemies[kEnemyCount];
+ ManagedBullet _bullets[kMaxBulletCount];
+
+ Common::List<MapObject *> _blockingObjects;
+
+ uint8 _shotCoolDown;
+
+ SoundDesc _soundShield;
+ SoundDesc _soundBite;
+ SoundDesc _soundKiss;
+ SoundDesc _soundShoot;
+ SoundDesc _soundExit;
+ SoundDesc _soundExplode;
+
+ bool _isPlaying;
+
void init();
void deinit();
+ void clearMap();
+ void createMap();
+
void initScreen();
+
+ void setPalette();
+ void fadeIn();
+
+ void drawFloorText();
+ void drawEndText();
+
+ bool isBlocked(const MapObject &self, int16 x, int16 y, MapObject **blockedBy = 0);
+ void findPath(MapObject &obj, int x, int y, MapObject **blockedBy = 0);
+
+ void updateAnims();
+
+ void checkInput();
+
+ Submarine::Direction getDirection(int &x, int &y) const;
+
+ void handleSub();
+ void subMove(int x, int y, Submarine::Direction direction);
+ void subShoot();
+
+ int findEmptyBulletSlot() const;
+ uint16 directionToBullet(Submarine::Direction direction) const;
+ void setBulletPosition(const ManagedSub &sub, ManagedBullet &bullet) const;
+
+ void bulletsMove();
+ void bulletMove(ManagedBullet &bullet);
+ void checkShotEnemy(MapObject &shotObject);
+
+ void checkExits();
+ void checkShields();
+ void checkMouths();
+
+ void healthGain(int amount);
+ void healthLose(int amount);
+
+ void checkExited();
+
+ void enemiesCreate();
+ void enemiesMove();
+ void enemyMove(ManagedEnemy &enemy, int x, int y);
+ void enemyAttack(ManagedEnemy &enemy);
+ void enemyExplode(ManagedEnemy &enemy);
+
+ bool isDead() const;
+ bool hasWon() const;
+
+ int getLanguage() const;
};
} // End of namespace Geisha
diff --git a/engines/gob/minigames/geisha/submarine.cpp b/engines/gob/minigames/geisha/submarine.cpp
new file mode 100644
index 0000000000..bf15306e5a
--- /dev/null
+++ b/engines/gob/minigames/geisha/submarine.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/minigames/geisha/submarine.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+enum Animation {
+ kAnimationDriveS = 4,
+ kAnimationDriveE = 5,
+ kAnimationDriveN = 6,
+ kAnimationDriveW = 7,
+ kAnimationDriveSE = 8,
+ kAnimationDriveNE = 9,
+ kAnimationDriveSW = 10,
+ kAnimationDriveNW = 11,
+ kAnimationShootS = 12,
+ kAnimationShootN = 13,
+ kAnimationShootW = 14,
+ kAnimationShootE = 15,
+ kAnimationShootNE = 16,
+ kAnimationShootSE = 17,
+ kAnimationShootSW = 18,
+ kAnimationShootNW = 19,
+ kAnimationExplodeN = 28,
+ kAnimationExplodeS = 29,
+ kAnimationExplodeW = 30,
+ kAnimationExplodeE = 31,
+ kAnimationExit = 32
+};
+
+
+Submarine::Submarine(const ANIFile &ani) : ANIObject(ani), _state(kStateMove), _direction(kDirectionNone) {
+ turn(kDirectionN);
+}
+
+Submarine::~Submarine() {
+}
+
+Submarine::Direction Submarine::getDirection() const {
+ return _direction;
+}
+
+void Submarine::turn(Direction to) {
+ // Nothing to do
+ if ((to == kDirectionNone) || ((_state == kStateMove) && (_direction == to)))
+ return;
+
+ _direction = to;
+
+ move();
+}
+
+void Submarine::move() {
+ uint16 frame = getFrame();
+ uint16 anim = (_state == kStateShoot) ? directionToShoot(_direction) : directionToMove(_direction);
+
+ setAnimation(anim);
+ setFrame(frame);
+ setPause(false);
+ setVisible(true);
+
+ setMode((_state == kStateShoot) ? kModeOnce : kModeContinuous);
+}
+
+void Submarine::shoot() {
+ _state = kStateShoot;
+
+ setAnimation(directionToShoot(_direction));
+ setMode(kModeOnce);
+ setPause(false);
+ setVisible(true);
+}
+
+void Submarine::die() {
+ if (!canMove())
+ return;
+
+ _state = kStateDie;
+
+ setAnimation(directionToExplode(_direction));
+ setMode(kModeOnce);
+ setPause(false);
+ setVisible(true);
+}
+
+void Submarine::leave() {
+ _state = kStateExit;
+
+ setAnimation(kAnimationExit);
+ setMode(kModeOnce);
+ setPause(false);
+ setVisible(true);
+}
+
+void Submarine::advance() {
+ ANIObject::advance();
+
+ switch (_state) {
+ case kStateShoot:
+ if (isPaused()) {
+ _state = kStateMove;
+
+ move();
+ }
+ break;
+
+ case kStateExit:
+ if (isPaused())
+ _state = kStateExited;
+
+ break;
+
+ case kStateDie:
+ if (isPaused())
+ _state = kStateDead;
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool Submarine::canMove() const {
+ return (_state == kStateMove) || (_state == kStateShoot);
+}
+
+bool Submarine::isDead() const {
+ return _state == kStateDead;
+}
+
+bool Submarine::isShooting() const {
+ return _state == kStateShoot;
+}
+
+bool Submarine::hasExited() const {
+ return _state == kStateExited;
+}
+
+uint16 Submarine::directionToMove(Direction direction) const {
+ switch (direction) {
+ case kDirectionN:
+ return kAnimationDriveN;
+
+ case kDirectionNE:
+ return kAnimationDriveNE;
+
+ case kDirectionE:
+ return kAnimationDriveE;
+
+ case kDirectionSE:
+ return kAnimationDriveSE;
+
+ case kDirectionS:
+ return kAnimationDriveS;
+
+ case kDirectionSW:
+ return kAnimationDriveSW;
+
+ case kDirectionW:
+ return kAnimationDriveW;
+
+ case kDirectionNW:
+ return kAnimationDriveNW;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+uint16 Submarine::directionToShoot(Direction direction) const {
+ switch (direction) {
+ case kDirectionN:
+ return kAnimationShootN;
+
+ case kDirectionNE:
+ return kAnimationShootNE;
+
+ case kDirectionE:
+ return kAnimationShootE;
+
+ case kDirectionSE:
+ return kAnimationShootSE;
+
+ case kDirectionS:
+ return kAnimationShootS;
+
+ case kDirectionSW:
+ return kAnimationShootSW;
+
+ case kDirectionW:
+ return kAnimationShootW;
+
+ case kDirectionNW:
+ return kAnimationShootNW;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+uint16 Submarine::directionToExplode(Direction direction) const {
+ // Only 4 exploding animations (spinning clockwise)
+
+ switch (direction) {
+ case kDirectionNW:
+ case kDirectionN:
+ return kAnimationExplodeN;
+
+ case kDirectionNE:
+ case kDirectionE:
+ return kAnimationExplodeE;
+
+ case kDirectionSE:
+ case kDirectionS:
+ return kAnimationExplodeS;
+
+ case kDirectionSW:
+ case kDirectionW:
+ return kAnimationExplodeW;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/submarine.h b/engines/gob/minigames/geisha/submarine.h
new file mode 100644
index 0000000000..a6eae57095
--- /dev/null
+++ b/engines/gob/minigames/geisha/submarine.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_MINIGAMES_GEISHA_SUBMARINE_H
+#define GOB_MINIGAMES_GEISHA_SUBMARINE_H
+
+#include "gob/aniobject.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+/** The submarine Geisha's "Penetration" minigame. */
+class Submarine : public ANIObject {
+public:
+ enum Direction {
+ kDirectionNone,
+ kDirectionN,
+ kDirectionNE,
+ kDirectionE,
+ kDirectionSE,
+ kDirectionS,
+ kDirectionSW,
+ kDirectionW,
+ kDirectionNW
+ };
+
+ Submarine(const ANIFile &ani);
+ ~Submarine();
+
+ Direction getDirection() const;
+
+ /** Turn to the specified direction. */
+ void turn(Direction to);
+
+ /** Play the shoot animation. */
+ void shoot();
+
+ /** Play the exploding animation. */
+ void die();
+
+ /** Play the exiting animation. */
+ void leave();
+
+ /** Advance the animation to the next frame. */
+ void advance();
+
+ /** Can the submarine move at the moment? */
+ bool canMove() const;
+
+ /** Is the submarine dead? */
+ bool isDead() const;
+
+ /** Is the submarine shooting? */
+ bool isShooting() const;
+
+ /** Has the submarine finished exiting the level? */
+ bool hasExited() const;
+
+private:
+ enum State {
+ kStateNone = 0,
+ kStateMove,
+ kStateShoot,
+ kStateExit,
+ kStateExited,
+ kStateDie,
+ kStateDead
+ };
+
+ State _state;
+ Direction _direction;
+
+ /** Map the directions to move animation indices. */
+ uint16 directionToMove(Direction direction) const;
+ /** Map the directions to shoot animation indices. */
+ uint16 directionToShoot(Direction direction) const;
+ /** Map the directions to explode animation indices. */
+ uint16 directionToExplode(Direction direction) const;
+
+ void move();
+};
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
+
+#endif // GOB_MINIGAMES_GEISHA_SUBMARINE_H
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 9da5a82de2..d5ee6478be 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/gob
MODULE_OBJS := \
anifile.o \
aniobject.o \
+ backbuffer.o \
cheater.o \
cheater_geisha.o \
cmpfile.o \
@@ -11,7 +12,6 @@ MODULE_OBJS := \
databases.o \
dbase.o \
decfile.o \
- detection.o \
draw.o \
draw_v1.o \
draw_v2.o \
@@ -44,6 +44,7 @@ MODULE_OBJS := \
inter_v2.o \
inter_bargon.o \
inter_fascin.o \
+ inter_littlered.o \
inter_inca2.o \
inter_playtoons.o \
inter_v3.o \
@@ -76,10 +77,24 @@ MODULE_OBJS := \
demos/demoplayer.o \
demos/scnplayer.o \
demos/batplayer.o \
+ detection/detection.o \
+ pregob/pregob.o \
+ pregob/txtfile.o \
+ pregob/gctfile.o \
+ pregob/seqfile.o \
+ pregob/onceupon/onceupon.o \
+ pregob/onceupon/abracadabra.o \
+ pregob/onceupon/babayaga.o \
+ pregob/onceupon/title.o \
+ pregob/onceupon/parents.o \
+ pregob/onceupon/stork.o \
+ pregob/onceupon/chargenchild.o \
minigames/geisha/evilfish.o \
minigames/geisha/oko.o \
minigames/geisha/meter.o \
minigames/geisha/diving.o \
+ minigames/geisha/mouth.o \
+ minigames/geisha/submarine.o \
minigames/geisha/penetration.o \
save/savefile.o \
save/savehandler.o \
@@ -91,6 +106,7 @@ MODULE_OBJS := \
save/saveload_v7.o \
save/saveload_geisha.o \
save/saveload_fascin.o \
+ save/saveload_ajworld.o \
save/saveload_inca2.o \
save/saveload_playtoons.o \
save/saveconverter.o \
@@ -101,6 +117,8 @@ MODULE_OBJS := \
sound/sounddesc.o \
sound/pcspeaker.o \
sound/adlib.o \
+ sound/musplayer.o \
+ sound/adlplayer.o \
sound/infogrames.o \
sound/protracker.o \
sound/soundmixer.o \
diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp
index 06a7130cef..b3d7ea6263 100644
--- a/engines/gob/mult.cpp
+++ b/engines/gob/mult.cpp
@@ -366,10 +366,11 @@ void Mult::doPalAnim() {
palPtr->blue, 0, 0x13);
palPtr = _vm->_global->_pPaletteDesc->vgaPal;
- for (_counter = 0; _counter < 16; _counter++, palPtr++)
+ for (_counter = 0; _counter < 16; _counter++, palPtr++) {
_vm->_global->_redPalette[_counter] = palPtr->red;
_vm->_global->_greenPalette[_counter] = palPtr->green;
_vm->_global->_bluePalette[_counter] = palPtr->blue;
+ }
} else
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 6593565e6a..64b9d19e33 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -1082,7 +1082,7 @@ void Mult_v2::animate() {
continue;
for (int j = 0; j < numAnims; j++) {
- Mult_Object &animObj2 = *_renderObjs[i];
+ Mult_Object &animObj2 = *_renderObjs[j];
Mult_AnimData &animData2 = *(animObj2.pAnimData);
if (i == j)
diff --git a/engines/gob/palanim.cpp b/engines/gob/palanim.cpp
index 8a5327c3f1..f90b141725 100644
--- a/engines/gob/palanim.cpp
+++ b/engines/gob/palanim.cpp
@@ -75,47 +75,28 @@ bool PalAnim::fadeStepColor(int color) {
bool PalAnim::fadeStep(int16 oper) {
bool stop = true;
- byte newRed;
- byte newGreen;
- byte newBlue;
if (oper == 0) {
- if (_vm->_global->_setAllPalette) {
- if (_vm->_global->_inVM != 0)
- error("PalAnim::fadeStep(): _vm->_global->_inVM != 0 not supported");
-
- for (int i = 0; i < 256; i++) {
- newRed = fadeColor(_vm->_global->_redPalette[i], _toFadeRed[i]);
- newGreen = fadeColor(_vm->_global->_greenPalette[i], _toFadeGreen[i]);
- newBlue = fadeColor(_vm->_global->_bluePalette[i], _toFadeBlue[i]);
-
- if ((_vm->_global->_redPalette[i] != newRed) ||
- (_vm->_global->_greenPalette[i] != newGreen) ||
- (_vm->_global->_bluePalette[i] != newBlue)) {
-
- _vm->_video->setPalElem(i, newRed, newGreen, newBlue, 0, 0x13);
-
- _vm->_global->_redPalette[i] = newRed;
- _vm->_global->_greenPalette[i] = newGreen;
- _vm->_global->_bluePalette[i] = newBlue;
- stop = false;
- }
- }
- } else {
- for (int i = 0; i < 16; i++) {
-
- _vm->_video->setPalElem(i,
- fadeColor(_vm->_global->_redPalette[i], _toFadeRed[i]),
- fadeColor(_vm->_global->_greenPalette[i], _toFadeGreen[i]),
- fadeColor(_vm->_global->_bluePalette[i], _toFadeBlue[i]),
- -1, _vm->_global->_videoMode);
-
- if ((_vm->_global->_redPalette[i] != _toFadeRed[i]) ||
- (_vm->_global->_greenPalette[i] != _toFadeGreen[i]) ||
- (_vm->_global->_bluePalette[i] != _toFadeBlue[i]))
- stop = false;
+ int colorCount = _vm->_global->_setAllPalette ? _vm->_global->_colorCount : 256;
+
+ for (int i = 0; i < colorCount; i++) {
+ byte newRed = fadeColor(_vm->_global->_redPalette [i], _toFadeRed [i]);
+ byte newGreen = fadeColor(_vm->_global->_greenPalette[i], _toFadeGreen[i]);
+ byte newBlue = fadeColor(_vm->_global->_bluePalette [i], _toFadeBlue [i]);
+
+ if ((_vm->_global->_redPalette [i] != newRed ) ||
+ (_vm->_global->_greenPalette[i] != newGreen) ||
+ (_vm->_global->_bluePalette [i] != newBlue)) {
+
+ _vm->_video->setPalElem(i, newRed, newGreen, newBlue, 0, 0x13);
+
+ _vm->_global->_redPalette [i] = newRed;
+ _vm->_global->_greenPalette[i] = newGreen;
+ _vm->_global->_bluePalette [i] = newBlue;
+ stop = false;
}
}
+
} else if ((oper > 0) && (oper < 4))
stop = fadeStepColor(oper - 1);
@@ -124,44 +105,18 @@ bool PalAnim::fadeStep(int16 oper) {
void PalAnim::fade(Video::PalDesc *palDesc, int16 fadeV, int16 allColors) {
bool stop;
- int16 i;
if (_vm->shouldQuit())
return;
_fadeValue = (fadeV < 0) ? -fadeV : 2;
- if (!_vm->_global->_setAllPalette) {
- if (!palDesc) {
- for (i = 0; i < 16; i++) {
- _toFadeRed[i] = 0;
- _toFadeGreen[i] = 0;
- _toFadeBlue[i] = 0;
- }
- } else {
- for (i = 0; i < 16; i++) {
- _toFadeRed[i] = palDesc->vgaPal[i].red;
- _toFadeGreen[i] = palDesc->vgaPal[i].green;
- _toFadeBlue[i] = palDesc->vgaPal[i].blue;
- }
- }
- } else {
- if (_vm->_global->_inVM != 0)
- error("PalAnim::fade(): _vm->_global->_inVM != 0 is not supported");
-
- if (!palDesc) {
- for (i = 0; i < 256; i++) {
- _toFadeRed[i] = 0;
- _toFadeGreen[i] = 0;
- _toFadeBlue[i] = 0;
- }
- } else {
- for (i = 0; i < 256; i++) {
- _toFadeRed[i] = palDesc->vgaPal[i].red;
- _toFadeGreen[i] = palDesc->vgaPal[i].green;
- _toFadeBlue[i] = palDesc->vgaPal[i].blue;
- }
- }
+ int colorCount = _vm->_global->_setAllPalette ? _vm->_global->_colorCount : 256;
+
+ for (int i = 0; i < colorCount; i++) {
+ _toFadeRed [i] = (palDesc == 0) ? 0 : palDesc->vgaPal[i].red;
+ _toFadeGreen[i] = (palDesc == 0) ? 0 : palDesc->vgaPal[i].green;
+ _toFadeBlue [i] = (palDesc == 0) ? 0 : palDesc->vgaPal[i].blue;
}
if (allColors == 0) {
diff --git a/engines/gob/pregob/gctfile.cpp b/engines/gob/pregob/gctfile.cpp
new file mode 100644
index 0000000000..08c32cda76
--- /dev/null
+++ b/engines/gob/pregob/gctfile.cpp
@@ -0,0 +1,306 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/random.h"
+#include "common/stream.h"
+
+#include "gob/surface.h"
+#include "gob/video.h"
+
+#include "gob/pregob/gctfile.h"
+
+namespace Gob {
+
+GCTFile::Chunk::Chunk() : type(kChunkTypeNone) {
+}
+
+
+GCTFile::GCTFile(Common::SeekableReadStream &gct, Common::RandomSource &rnd) : _rnd(&rnd),
+ _areaLeft(0), _areaTop(0), _areaRight(0), _areaBottom(0), _currentItem(0xFFFF) {
+
+ load(gct);
+}
+
+GCTFile::~GCTFile() {
+}
+
+void GCTFile::load(Common::SeekableReadStream &gct) {
+ gct.skip(4); // Required buffer size
+ gct.skip(2); // Unknown
+
+ // Read the selector and line counts for each item
+ const uint16 itemCount = gct.readUint16LE();
+ _items.resize(itemCount);
+
+ for (Items::iterator i = _items.begin(); i != _items.end(); ++i) {
+ const uint16 selector = gct.readUint16LE();
+ const uint16 lineCount = gct.readUint16LE();
+
+ i->selector = selector;
+ i->lines.resize(lineCount);
+ }
+
+ // Read all item lines
+ for (Items::iterator i = _items.begin(); i != _items.end(); ++i) {
+ for (Lines::iterator l = i->lines.begin(); l != i->lines.end(); ++l) {
+ const uint16 lineSize = gct.readUint16LE();
+
+ readLine(gct, *l, lineSize);
+ }
+ }
+
+ if (gct.err())
+ error("GCTFile::load(): Failed reading GCT");
+}
+
+void GCTFile::readLine(Common::SeekableReadStream &gct, Line &line, uint16 lineSize) const {
+ line.chunks.push_back(Chunk());
+
+ while (lineSize > 0) {
+ byte c = gct.readByte();
+ lineSize--;
+
+ if (c == 0) {
+ // Command byte
+
+ if (lineSize == 0)
+ break;
+
+ byte cmd = gct.readByte();
+ lineSize--;
+
+ // Line end command
+ if (cmd == 0)
+ break;
+
+ // Item reference command
+ if (cmd == 1) {
+ if (lineSize < 2) {
+ warning("GCTFile::readLine(): Item reference command is missing parameters");
+ break;
+ }
+
+ const uint32 itemRef = gct.readUint16LE();
+ lineSize -= 2;
+
+ line.chunks.push_back(Chunk());
+ line.chunks.back().type = kChunkTypeItem;
+ line.chunks.back().item = itemRef;
+
+ line.chunks.push_back(Chunk());
+ continue;
+ }
+
+ warning("GCTFile::readLine(): Invalid command 0x%02X", cmd);
+ break;
+ }
+
+ // Text
+ line.chunks.back().type = kChunkTypeString;
+ line.chunks.back().text += (char)c;
+ }
+
+ // Skip bytes we didn't read (because of errors)
+ gct.skip(lineSize);
+
+ // Remove empty chunks from the end of the list
+ while (!line.chunks.empty() && (line.chunks.back().type == kChunkTypeNone))
+ line.chunks.pop_back();
+}
+
+uint16 GCTFile::getLineCount(uint item) const {
+ if (item >= _items.size())
+ return 0;
+
+ return _items[item].lines.size();
+}
+
+void GCTFile::selectLine(uint item, uint16 line) {
+ if ((item >= _items.size()) && (item != kSelectorAll) && (item != kSelectorRandom))
+ return;
+
+ _items[item].selector = line;
+}
+
+void GCTFile::setText(uint item, uint16 line, const Common::String &text) {
+ if ((item >= _items.size()) || (line >= _items[item].lines.size()))
+ return;
+
+ _items[item].lines[line].chunks.clear();
+ _items[item].lines[line].chunks.push_back(Chunk());
+
+ _items[item].lines[line].chunks.back().type = kChunkTypeString;
+ _items[item].lines[line].chunks.back().text = text;
+}
+
+void GCTFile::setText(uint item, const Common::String &text) {
+ if (item >= _items.size())
+ return;
+
+ _items[item].selector = 0;
+
+ _items[item].lines.resize(1);
+
+ setText(item, 0, text);
+}
+
+void GCTFile::reset() {
+ _currentItem = 0xFFFF;
+ _currentText.clear();
+}
+
+Common::String GCTFile::getLineText(const Line &line) const {
+ Common::String text;
+
+ // Go over all chunks in this line
+ for (Chunks::const_iterator c = line.chunks.begin(); c != line.chunks.end(); ++c) {
+ // A chunk is either a direct string, or a reference to another item
+
+ if (c->type == kChunkTypeItem) {
+ Common::List<Common::String> lines;
+
+ getItemText(c->item, lines);
+ if (lines.empty())
+ continue;
+
+ if (lines.size() > 1)
+ warning("GCTFile::getLineText(): Referenced item has multiple lines");
+
+ text += lines.front();
+ } else if (c->type == kChunkTypeString)
+ text += c->text;
+ }
+
+ return text;
+}
+
+void GCTFile::getItemText(uint item, Common::List<Common::String> &text) const {
+ text.clear();
+
+ if ((item >= _items.size()) || _items[item].lines.empty())
+ return;
+
+ uint16 line = _items[item].selector;
+
+ // Draw all lines
+ if (line == kSelectorAll) {
+ for (Lines::const_iterator l = _items[item].lines.begin(); l != _items[item].lines.end(); ++l)
+ text.push_back(getLineText(*l));
+
+ return;
+ }
+
+ // Draw random line
+ if (line == kSelectorRandom)
+ line = _rnd->getRandomNumber(_items[item].lines.size() - 1);
+
+ if (line >= _items[item].lines.size())
+ return;
+
+ text.push_back(getLineText(_items[item].lines[line]));
+}
+
+void GCTFile::setArea(int16 left, int16 top, int16 right, int16 bottom) {
+ trashBuffer();
+
+ _hasArea = false;
+
+ const int16 width = right - left + 1;
+ const int16 height = bottom - top + 1;
+ if ((width <= 0) || (height <= 0))
+ return;
+
+ _areaLeft = left;
+ _areaTop = top;
+ _areaRight = right;
+ _areaBottom = bottom;
+
+ _hasArea = true;
+
+ resizeBuffer(width, height);
+}
+
+bool GCTFile::clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ return restoreScreen(dest, left, top, right, bottom);
+}
+
+bool GCTFile::fill(Surface &dest, uint8 color, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ left = _areaLeft;
+ top = _areaTop;
+ right = _areaRight;
+ bottom = _areaBottom;
+
+ if (!hasSavedBackground())
+ saveScreen(dest, left, top, right, bottom);
+
+ dest.fillRect(left, top, right, bottom, color);
+
+ return true;
+}
+
+bool GCTFile::finished() const {
+ return (_currentItem != 0xFFFF) && _currentText.empty();
+}
+
+bool GCTFile::draw(Surface &dest, uint16 item, const Font &font, uint8 color,
+ int16 &left, int16 &top, int16 &right, int16 &bottom) {
+
+ if ((item >= _items.size()) || !_hasArea)
+ return false;
+
+ left = _areaLeft;
+ top = _areaTop;
+ right = _areaRight;
+ bottom = _areaBottom;
+
+ const int16 width = right - left + 1;
+ const int16 height = bottom - top + 1;
+
+ const uint lineCount = height / font.getCharHeight();
+ if (lineCount == 0)
+ return false;
+
+ if (!hasSavedBackground())
+ saveScreen(dest, left, top, right, bottom);
+
+ if (item != _currentItem) {
+ _currentItem = item;
+
+ getItemText(_currentItem, _currentText);
+ }
+
+ if (_currentText.empty())
+ return false;
+
+ int16 y = top;
+ for (uint i = 0; (i < lineCount) && !_currentText.empty(); i++, y += font.getCharHeight()) {
+ const Common::String &line = _currentText.front();
+ const int16 x = left + ((width - (line.size() * font.getCharWidth())) / 2);
+
+ font.drawString(line, x, y, color, 0, true, dest);
+ _currentText.pop_front();
+ }
+
+ return true;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/gctfile.h b/engines/gob/pregob/gctfile.h
new file mode 100644
index 0000000000..ed6351b7a8
--- /dev/null
+++ b/engines/gob/pregob/gctfile.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_GCTFILE_H
+#define GOB_PREGOB_GCTFILE_H
+
+#include "common/str.h"
+#include "common/array.h"
+#include "common/list.h"
+
+#include "gob/backbuffer.h"
+
+namespace Common {
+ class RandomSource;
+ class SeekableReadStream;
+}
+
+namespace Gob {
+
+class Surface;
+class Font;
+
+class GCTFile : public BackBuffer {
+public:
+ static const uint16 kSelectorAll = 0xFFFE; ///< Print all lines.
+ static const uint16 kSelectorRandom = 0xFFFF; ///< Print a random line.
+
+
+ GCTFile(Common::SeekableReadStream &gct, Common::RandomSource &rnd);
+ ~GCTFile();
+
+ /** Return the number of lines in an item. */
+ uint16 getLineCount(uint item) const;
+
+ /** Set the area the text will be printed in. */
+ void setArea(int16 left, int16 top, int16 right, int16 bottom);
+
+ /** Set which line of this item should be printed. */
+ void selectLine(uint item, uint16 line);
+
+ /** Change the text of an items' line. */
+ void setText(uint item, uint16 line, const Common::String &text);
+ /** Change the item into one one line and set that line's text. */
+ void setText(uint item, const Common::String &text);
+
+ /** Reset the item drawing state. */
+ void reset();
+
+ /** Clear the drawn text, restoring the original content. */
+ bool clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+
+ /** Fill the text area with a color. */
+ bool fill(Surface &dest, uint8 color, int16 &left, int16 &top, int16 &right, int16 &bottom);
+
+ /** Draw an item onto the surface, until all text has been drawn or the area is filled. */
+ bool draw(Surface &dest, uint16 item, const Font &font, uint8 color,
+ int16 &left, int16 &top, int16 &right, int16 &bottom);
+
+ /** Did we draw all text? */
+ bool finished() const;
+
+private:
+ /** The type of a chunk. */
+ enum ChunkType {
+ kChunkTypeNone = 0, ///< Do nothing.
+ kChunkTypeString , ///< A direct string.
+ kChunkTypeItem ///< A reference to an item to print instead.
+ };
+
+ /** A chunk in an item text line. */
+ struct Chunk {
+ ChunkType type; ///< The type of the chunk.
+
+ Common::String text; ///< Text to print.
+
+ int item; ///< Item to print instead.
+
+ Chunk();
+ };
+
+ typedef Common::List<Chunk> Chunks;
+
+ /** A line in an item. */
+ struct Line {
+ Chunks chunks; ///< The chunks that make up the line.
+ };
+
+ typedef Common::Array<Line> Lines;
+
+ /** A GCT item. */
+ struct Item {
+ Lines lines; ///< The text lines in the item
+ uint16 selector; ///< Which line to print.
+ };
+
+ typedef Common::Array<Item> Items;
+
+
+ Common::RandomSource *_rnd;
+
+ Items _items; ///< All GCT items.
+
+ // The area on which to print
+ bool _hasArea;
+ int16 _areaLeft;
+ int16 _areaTop;
+ int16 _areaRight;
+ int16 _areaBottom;
+
+ /** Index of the current item we're drawing. */
+ uint16 _currentItem;
+ /** Text left to draw. */
+ Common::List<Common::String> _currentText;
+
+
+ // -- Loading helpers --
+
+ void load(Common::SeekableReadStream &gct);
+ void readLine(Common::SeekableReadStream &gct, Line &line, uint16 lineSize) const;
+
+
+ // -- Draw helpers --
+
+ Common::String getLineText(const Line &line) const;
+ void getItemText(uint item, Common::List<Common::String> &text) const;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_GCTFILE_H
diff --git a/engines/gob/pregob/onceupon/abracadabra.cpp b/engines/gob/pregob/onceupon/abracadabra.cpp
new file mode 100644
index 0000000000..2cf6855ef8
--- /dev/null
+++ b/engines/gob/pregob/onceupon/abracadabra.cpp
@@ -0,0 +1,137 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/textconsole.h"
+
+#include "gob/gob.h"
+
+#include "gob/pregob/onceupon/abracadabra.h"
+
+static const uint8 kCopyProtectionColors[7] = {
+ 14, 11, 13, 1, 7, 12, 2
+};
+
+static const uint8 kCopyProtectionShapes[7 * 20] = {
+ 3, 4, 3, 0, 1, 2, 0, 2, 2, 0, 2, 4, 0, 3, 4, 1, 1, 4, 1, 3,
+ 0, 2, 0, 4, 2, 4, 4, 2, 3, 0, 1, 1, 1, 1, 3, 0, 4, 2, 3, 4,
+ 0, 0, 1, 2, 1, 1, 2, 4, 3, 1, 4, 2, 4, 4, 2, 4, 1, 2, 3, 3,
+ 1, 0, 2, 3, 4, 2, 3, 2, 2, 0, 0, 0, 4, 2, 3, 4, 4, 0, 4, 1,
+ 4, 2, 1, 1, 1, 1, 4, 3, 4, 2, 3, 0, 0, 3, 0, 2, 3, 0, 2, 4,
+ 4, 2, 4, 3, 0, 4, 0, 2, 3, 1, 4, 1, 3, 1, 0, 0, 2, 1, 3, 2,
+ 3, 1, 0, 3, 1, 3, 4, 2, 4, 4, 3, 2, 0, 2, 0, 1, 2, 0, 1, 4
+};
+
+static const uint8 kCopyProtectionObfuscate[4] = {
+ 1, 0, 2, 3
+};
+
+namespace Gob {
+
+namespace OnceUpon {
+
+const OnceUpon::MenuButton Abracadabra::kAnimalsButtons = {
+ true, 131, 127, 183, 164, 193, 0, 243, 35, 132, 128, 0
+};
+
+const OnceUpon::MenuButton Abracadabra::kAnimalButtons[] = {
+ {false, 37, 89, 95, 127, 37, 89, 95, 127, 131, 25, 0},
+ {false, 114, 65, 172, 111, 114, 65, 172, 111, 131, 25, 1},
+ {false, 186, 72, 227, 96, 186, 72, 227, 96, 139, 25, 2},
+ {false, 249, 87, 282, 112, 249, 87, 282, 112, 143, 25, 3},
+ {false, 180, 102, 234, 138, 180, 102, 234, 138, 133, 25, 4},
+ {false, 197, 145, 242, 173, 197, 145, 242, 173, 137, 25, 5},
+ {false, 113, 151, 171, 176, 113, 151, 171, 176, 131, 25, 6},
+ {false, 114, 122, 151, 150, 114, 122, 151, 150, 141, 25, 7},
+ {false, 36, 136, 94, 176, 36, 136, 94, 176, 131, 25, 8},
+ {false, 243, 123, 295, 155, 243, 123, 295, 155, 136, 25, 9}
+};
+
+const char *Abracadabra::kAnimalNames[] = {
+ "loup",
+ "drag",
+ "arai",
+ "crap",
+ "crab",
+ "mous",
+ "saut",
+ "guep",
+ "rhin",
+ "scor"
+};
+
+// The houses where the stork can drop a bundle
+const OnceUpon::MenuButton Abracadabra::kStorkHouses[] = {
+ {false, 16, 80, 87, 125, 0, 0, 0, 0, 0, 0, 0}, // Castle , Lord & Lady
+ {false, 61, 123, 96, 149, 0, 0, 0, 0, 0, 0, 1}, // Cottage, Farmers
+ {false, 199, 118, 226, 137, 0, 0, 0, 0, 0, 0, 2}, // Hut , Woodcutters
+ {false, 229, 91, 304, 188, 0, 0, 0, 0, 0, 0, 3} // Palace , King & Queen
+};
+
+// The stork bundle drop parameters
+const Stork::BundleDrop Abracadabra::kStorkBundleDrops[] = {
+ { 14, 65, 127, true },
+ { 14, 76, 152, true },
+ { 14, 204, 137, true },
+ { 11, 275, 179, false }
+};
+
+// Parameters for the stork section.
+const OnceUpon::StorkParam Abracadabra::kStorkParam = {
+ "present.cmp", ARRAYSIZE(kStorkHouses), kStorkHouses, kStorkBundleDrops
+};
+
+
+Abracadabra::Abracadabra(GobEngine *vm) : OnceUpon(vm) {
+}
+
+Abracadabra::~Abracadabra() {
+}
+
+void Abracadabra::run() {
+ init();
+
+ // Copy protection
+ bool correctCP = doCopyProtection(kCopyProtectionColors, kCopyProtectionShapes, kCopyProtectionObfuscate);
+ if (_vm->shouldQuit() || !correctCP)
+ return;
+
+ // Show the intro
+ showIntro();
+ if (_vm->shouldQuit())
+ return;
+
+ // Handle the start menu
+ doStartMenu(&kAnimalsButtons, ARRAYSIZE(kAnimalButtons), kAnimalButtons, kAnimalNames);
+ if (_vm->shouldQuit())
+ return;
+
+ // Play the actual game
+ playGame();
+}
+
+const OnceUpon::StorkParam &Abracadabra::getStorkParameters() const {
+ return kStorkParam;
+}
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/onceupon/abracadabra.h b/engines/gob/pregob/onceupon/abracadabra.h
new file mode 100644
index 0000000000..8048213f5f
--- /dev/null
+++ b/engines/gob/pregob/onceupon/abracadabra.h
@@ -0,0 +1,61 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_ABRACADABRA_H
+#define GOB_PREGOB_ONCEUPON_ABRACADABRA_H
+
+#include "gob/pregob/onceupon/onceupon.h"
+
+namespace Gob {
+
+namespace OnceUpon {
+
+class Abracadabra : public OnceUpon {
+public:
+ Abracadabra(GobEngine *vm);
+ ~Abracadabra();
+
+ void run();
+
+protected:
+ const StorkParam &getStorkParameters() const;
+
+private:
+ /** Definition of the menu button that leads to the animal names screen. */
+ static const MenuButton kAnimalsButtons;
+
+ /** Definition of the buttons that make up the animals in the animal names screen. */
+ static const MenuButton kAnimalButtons[];
+ /** File prefixes for the name of each animal. */
+ static const char *kAnimalNames[];
+
+ // Parameters for the stork section.
+ static const MenuButton kStorkHouses[];
+ static const Stork::BundleDrop kStorkBundleDrops[];
+ static const struct StorkParam kStorkParam;
+};
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_ONCEUPON_ABRACADABRA_H
diff --git a/engines/gob/pregob/onceupon/babayaga.cpp b/engines/gob/pregob/onceupon/babayaga.cpp
new file mode 100644
index 0000000000..ef56b9dd0b
--- /dev/null
+++ b/engines/gob/pregob/onceupon/babayaga.cpp
@@ -0,0 +1,137 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/textconsole.h"
+
+#include "gob/gob.h"
+
+#include "gob/pregob/onceupon/babayaga.h"
+
+static const uint8 kCopyProtectionColors[7] = {
+ 14, 11, 13, 1, 7, 12, 2
+};
+
+static const uint8 kCopyProtectionShapes[7 * 20] = {
+ 0, 0, 1, 2, 1, 1, 2, 4, 3, 1, 4, 2, 4, 4, 2, 4, 1, 2, 3, 3,
+ 3, 1, 0, 3, 1, 3, 4, 2, 4, 4, 3, 2, 0, 2, 0, 1, 2, 0, 1, 4,
+ 1, 0, 2, 3, 4, 2, 3, 2, 2, 0, 0, 0, 4, 2, 3, 4, 4, 0, 4, 1,
+ 0, 2, 0, 4, 2, 4, 4, 2, 3, 0, 1, 1, 1, 1, 3, 0, 4, 2, 3, 4,
+ 3, 4, 3, 0, 1, 2, 0, 2, 2, 0, 2, 4, 0, 3, 4, 1, 1, 4, 1, 3,
+ 4, 2, 1, 1, 1, 1, 4, 3, 4, 2, 3, 0, 0, 3, 0, 2, 3, 0, 2, 4,
+ 4, 2, 4, 3, 0, 4, 0, 2, 3, 1, 4, 1, 3, 1, 0, 0, 2, 1, 3, 2
+};
+
+static const uint8 kCopyProtectionObfuscate[4] = {
+ 0, 1, 2, 3
+};
+
+namespace Gob {
+
+namespace OnceUpon {
+
+const OnceUpon::MenuButton BabaYaga::kAnimalsButtons = {
+ true, 131, 127, 183, 164, 193, 0, 245, 37, 131, 127, 0
+};
+
+const OnceUpon::MenuButton BabaYaga::kAnimalButtons[] = {
+ {false, 34, 84, 92, 127, 34, 84, 92, 127, 131, 25, 0},
+ {false, 114, 65, 172, 111, 114, 65, 172, 111, 131, 25, 1},
+ {false, 186, 72, 227, 96, 186, 72, 227, 96, 139, 25, 2},
+ {false, 249, 87, 282, 112, 249, 87, 282, 112, 143, 25, 3},
+ {false, 180, 97, 234, 138, 180, 97, 234, 138, 133, 25, 4},
+ {false, 197, 145, 242, 173, 197, 145, 242, 173, 137, 25, 5},
+ {false, 113, 156, 171, 176, 113, 156, 171, 176, 131, 25, 6},
+ {false, 114, 127, 151, 150, 114, 127, 151, 150, 141, 25, 7},
+ {false, 36, 136, 94, 176, 36, 136, 94, 176, 131, 25, 8},
+ {false, 245, 123, 293, 155, 245, 123, 293, 155, 136, 25, 9}
+};
+
+const char *BabaYaga::kAnimalNames[] = {
+ "vaut",
+ "drag",
+ "arai",
+ "gren",
+ "fauc",
+ "abei",
+ "serp",
+ "tort",
+ "sang",
+ "rena"
+};
+
+// The houses where the stork can drop a bundle
+const OnceUpon::MenuButton BabaYaga::kStorkHouses[] = {
+ {false, 16, 80, 87, 125, 0, 0, 0, 0, 0, 0, 0}, // Castle , Lord & Lady
+ {false, 61, 123, 96, 149, 0, 0, 0, 0, 0, 0, 1}, // Cottage, Farmers
+ {false, 199, 118, 226, 137, 0, 0, 0, 0, 0, 0, 2}, // Hut , Woodcutters
+ {false, 229, 91, 304, 188, 0, 0, 0, 0, 0, 0, 3} // Palace , King & Queen
+};
+
+// The stork bundle drop parameters
+const Stork::BundleDrop BabaYaga::kStorkBundleDrops[] = {
+ { 14, 35, 129, true },
+ { 14, 70, 148, true },
+ { 14, 206, 136, true },
+ { 11, 260, 225, false }
+};
+
+// Parameters for the stork section.
+const OnceUpon::StorkParam BabaYaga::kStorkParam = {
+ "present2.cmp", ARRAYSIZE(kStorkHouses), kStorkHouses, kStorkBundleDrops
+};
+
+
+BabaYaga::BabaYaga(GobEngine *vm) : OnceUpon(vm) {
+}
+
+BabaYaga::~BabaYaga() {
+}
+
+void BabaYaga::run() {
+ init();
+
+ // Copy protection
+ bool correctCP = doCopyProtection(kCopyProtectionColors, kCopyProtectionShapes, kCopyProtectionObfuscate);
+ if (_vm->shouldQuit() || !correctCP)
+ return;
+
+ // Show the intro
+ showIntro();
+ if (_vm->shouldQuit())
+ return;
+
+ // Handle the start menu
+ doStartMenu(&kAnimalsButtons, ARRAYSIZE(kAnimalButtons), kAnimalButtons, kAnimalNames);
+ if (_vm->shouldQuit())
+ return;
+
+ // Play the actual game
+ playGame();
+}
+
+const OnceUpon::StorkParam &BabaYaga::getStorkParameters() const {
+ return kStorkParam;
+}
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/onceupon/babayaga.h b/engines/gob/pregob/onceupon/babayaga.h
new file mode 100644
index 0000000000..0241f78f4e
--- /dev/null
+++ b/engines/gob/pregob/onceupon/babayaga.h
@@ -0,0 +1,61 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_BABAYAGA_H
+#define GOB_PREGOB_ONCEUPON_BABAYAGA_H
+
+#include "gob/pregob/onceupon/onceupon.h"
+
+namespace Gob {
+
+namespace OnceUpon {
+
+class BabaYaga : public OnceUpon {
+public:
+ BabaYaga(GobEngine *vm);
+ ~BabaYaga();
+
+ void run();
+
+protected:
+ const StorkParam &getStorkParameters() const;
+
+private:
+ /** Definition of the menu button that leads to the animal names screen. */
+ static const MenuButton kAnimalsButtons;
+
+ /** Definition of the buttons that make up the animals in the animal names screen. */
+ static const MenuButton kAnimalButtons[];
+ /** File prefixes for the name of each animal. */
+ static const char *kAnimalNames[];
+
+ // Parameters for the stork section.
+ static const MenuButton kStorkHouses[];
+ static const Stork::BundleDrop kStorkBundleDrops[];
+ static const struct StorkParam kStorkParam;
+};
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_ONCEUPON_BABAYAGA_H
diff --git a/engines/gob/pregob/onceupon/brokenstrings.h b/engines/gob/pregob/onceupon/brokenstrings.h
new file mode 100644
index 0000000000..89acb1c6bd
--- /dev/null
+++ b/engines/gob/pregob/onceupon/brokenstrings.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_BROKENSTRINGS_H
+#define GOB_PREGOB_ONCEUPON_BROKENSTRINGS_H
+
+struct BrokenString {
+ const char *wrong;
+ const char *correct;
+};
+
+struct BrokenStringLanguage {
+ const BrokenString *strings;
+ uint count;
+};
+
+static const BrokenString kBrokenStringsGerman[] = {
+ { "Zeichungen von Kaki," , "Zeichnungen von Kaki," },
+ { "die es in seine Wachtr\204ume", "die es in seine Tagtr\204ume" },
+ { " Spielerfahrung" , " Spielerfahren" },
+ { " Fortgeschrittene" , " Fortgeschritten" },
+ { "die Vespe" , "die Wespe" },
+ { "das Rhinoceros" , "das Rhinozeros" },
+ { "die Heusschrecke" , "die Heuschrecke" },
+ { "Das, von Drachen gebrachte" , "Das vom Drachen gebrachte" },
+ { "Am Waldesrand es sieht" , "Am Waldesrand sieht es" },
+ { " das Kind den Palast." , "das Kind den Palast." },
+ { "Am Waldessaum sieht" , "Am Waldesrand sieht" },
+ { "tipp auf ESC!" , "dr\201cke ESC!" },
+ { "Wohin fliegt der Drachen?" , "Wohin fliegt der Drache?" }
+};
+
+static const BrokenStringLanguage kBrokenStrings[kLanguageCount] = {
+ { 0, 0 }, // French
+ { kBrokenStringsGerman, ARRAYSIZE(kBrokenStringsGerman) }, // German
+ { 0, 0 }, // English
+ { 0, 0 }, // Spanish
+ { 0, 0 }, // Italian
+};
+
+#endif // GOB_PREGOB_ONCEUPON_BROKENSTRINGS_H
diff --git a/engines/gob/pregob/onceupon/chargenchild.cpp b/engines/gob/pregob/onceupon/chargenchild.cpp
new file mode 100644
index 0000000000..ba099e4937
--- /dev/null
+++ b/engines/gob/pregob/onceupon/chargenchild.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/surface.h"
+#include "gob/anifile.h"
+
+#include "gob/pregob/onceupon/chargenchild.h"
+
+enum Animation {
+ kAnimWalkLeft = 0,
+ kAnimWalkRight = 1,
+ kAnimJumpLeft = 2,
+ kAnimJumpRight = 3,
+ kAnimTapFoot = 14
+};
+
+namespace Gob {
+
+namespace OnceUpon {
+
+CharGenChild::CharGenChild(const ANIFile &ani) : ANIObject(ani) {
+ setPosition(265, 110);
+ setAnimation(kAnimWalkLeft);
+ setVisible(true);
+ setPause(false);
+}
+
+CharGenChild::~CharGenChild() {
+}
+
+void CharGenChild::advance() {
+ bool wasLastFrame = lastFrame();
+
+ ANIObject::advance();
+
+ int16 x, y, left, top, width, height;
+ getPosition(x, y);
+ getFramePosition(left, top);
+ getFrameSize(width, height);
+
+ const int16 right = left + width - 1;
+
+ switch (getAnimation()) {
+ case kAnimWalkLeft:
+ if (left <= 147)
+ setAnimation(kAnimWalkRight);
+ break;
+
+ case kAnimWalkRight:
+ if (right >= 290) {
+ setAnimation(kAnimJumpLeft);
+
+ setPosition(x, y - 14);
+ }
+ break;
+
+ case kAnimJumpLeft:
+ if (wasLastFrame) {
+ setAnimation(kAnimTapFoot);
+
+ setPosition(x, y - 10);
+ }
+ break;
+
+ case kAnimTapFoot:
+ if (wasLastFrame) {
+ setAnimation(kAnimJumpRight);
+
+ setPosition(x, y + 10);
+ }
+ break;
+
+ case kAnimJumpRight:
+ if (wasLastFrame) {
+ setAnimation(kAnimWalkLeft);
+
+ setPosition(x, y + 14);
+ }
+ break;
+ }
+}
+
+CharGenChild::Sound CharGenChild::shouldPlaySound() const {
+ const uint16 anim = getAnimation();
+ const uint16 frame = getFrame();
+
+ if (((anim == kAnimWalkLeft) || (anim == kAnimWalkRight)) && ((frame == 1) || (frame == 6)))
+ return kSoundWalk;
+
+ if (((anim == kAnimJumpLeft) || (anim == kAnimJumpRight)) && (frame == 0))
+ return kSoundJump;
+
+ return kSoundNone;
+}
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/onceupon/chargenchild.h b/engines/gob/pregob/onceupon/chargenchild.h
new file mode 100644
index 0000000000..3b09ef112a
--- /dev/null
+++ b/engines/gob/pregob/onceupon/chargenchild.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_CHARGENCHILD_H
+#define GOB_PREGOB_ONCEUPON_CHARGENCHILD_H
+
+#include "common/system.h"
+
+#include "gob/aniobject.h"
+
+namespace Gob {
+
+class Surface;
+class ANIFile;
+
+namespace OnceUpon {
+
+/** The child running around on the character generator screen. */
+class CharGenChild : public ANIObject {
+public:
+ enum Sound {
+ kSoundNone = 0,
+ kSoundWalk ,
+ kSoundJump
+ };
+
+ CharGenChild(const ANIFile &ani);
+ ~CharGenChild();
+
+ /** Advance the animation to the next frame. */
+ void advance();
+
+ /** Should we play a sound right now? */
+ Sound shouldPlaySound() const;
+};
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_ONCEUPON_CHARGENCHILD_H
diff --git a/engines/gob/pregob/onceupon/onceupon.cpp b/engines/gob/pregob/onceupon/onceupon.cpp
new file mode 100644
index 0000000000..e4c2df34c0
--- /dev/null
+++ b/engines/gob/pregob/onceupon/onceupon.cpp
@@ -0,0 +1,1904 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/gob.h"
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/dataio.h"
+#include "gob/surface.h"
+#include "gob/draw.h"
+#include "gob/video.h"
+#include "gob/anifile.h"
+#include "gob/aniobject.h"
+
+#include "gob/sound/sound.h"
+
+#include "gob/pregob/txtfile.h"
+#include "gob/pregob/gctfile.h"
+
+#include "gob/pregob/onceupon/onceupon.h"
+#include "gob/pregob/onceupon/palettes.h"
+#include "gob/pregob/onceupon/title.h"
+#include "gob/pregob/onceupon/parents.h"
+#include "gob/pregob/onceupon/chargenchild.h"
+
+static const uint kLanguageCount = 5;
+
+static const uint kCopyProtectionHelpStringCount = 3;
+
+static const char *kCopyProtectionHelpStrings[Gob::OnceUpon::OnceUpon::kLanguageCount][kCopyProtectionHelpStringCount] = {
+ { // French
+ "Consulte le livret des animaux, rep\212re la",
+ "page correspondant \205 la couleur de l\'\202cran",
+ "et clique le symbole associ\202 \205 l\'animal affich\202.",
+ },
+ { // German
+ "Suche im Tieralbum die Seite, die der Farbe auf",
+ "dem Bildschirm entspricht und klicke auf das",
+ "Tiersymbol.",
+ },
+ { // English
+ "Consult the book of animals, find the page",
+ "corresponding to the colour of screen and click",
+ "the symbol associated with the animal displayed.",
+ },
+ { // Spanish
+ "Consulta el libro de los animales, localiza la ",
+ "p\240gina que corresponde al color de la pantalla.",
+ "Cliquea el s\241mbolo asociado al animal que aparece.",
+ },
+ { // Italian
+ "Guarda il libretto degli animali, trova la",
+ "pagina che corrisponde al colore dello schermo,",
+ "clicca il simbolo associato all\'animale presentato",
+ }
+};
+
+static const char *kCopyProtectionWrongStrings[Gob::OnceUpon::OnceUpon::kLanguageCount] = {
+ "Tu t\'es tromp\202, dommage...", // French
+ "Schade, du hast dich geirrt." , // German
+ "You are wrong, what a pity!" , // English
+ "Te equivocas, l\240stima..." , // Spanish
+ "Sei Sbagliato, peccato..." // Italian
+};
+
+static const uint kCopyProtectionShapeCount = 5;
+
+static const int16 kCopyProtectionShapeCoords[kCopyProtectionShapeCount][6] = {
+ { 0, 51, 26, 75, 60, 154},
+ { 28, 51, 58, 81, 96, 151},
+ { 60, 51, 94, 79, 136, 152},
+ { 96, 51, 136, 71, 180, 155},
+ {140, 51, 170, 77, 228, 153}
+};
+
+enum ClownAnimation {
+ kClownAnimationClownCheer = 0,
+ kClownAnimationClownStand = 1,
+ kClownAnimationClownCry = 6
+};
+
+// 12 seconds delay for one area full of GCT text
+static const uint32 kGCTDelay = 12000;
+
+namespace Gob {
+
+namespace OnceUpon {
+
+const OnceUpon::MenuButton OnceUpon::kMainMenuDifficultyButton[] = {
+ {false, 29, 18, 77, 57, 0, 0, 0, 0, 0, 0, (int)kDifficultyBeginner},
+ {false, 133, 18, 181, 57, 0, 0, 0, 0, 0, 0, (int)kDifficultyIntermediate},
+ {false, 241, 18, 289, 57, 0, 0, 0, 0, 0, 0, (int)kDifficultyAdvanced},
+};
+
+const OnceUpon::MenuButton OnceUpon::kSectionButtons[] = {
+ {false, 27, 121, 91, 179, 0, 0, 0, 0, 0, 0, 0},
+ { true, 95, 121, 159, 179, 4, 1, 56, 49, 100, 126, 2},
+ { true, 163, 121, 227, 179, 64, 1, 120, 49, 168, 126, 6},
+ { true, 231, 121, 295, 179, 128, 1, 184, 49, 236, 126, 10}
+};
+
+const OnceUpon::MenuButton OnceUpon::kIngameButtons[] = {
+ {true, 108, 83, 139, 116, 0, 0, 31, 34, 108, 83, 0},
+ {true, 144, 83, 175, 116, 36, 0, 67, 34, 144, 83, 1},
+ {true, 180, 83, 211, 116, 72, 0, 103, 34, 180, 83, 2}
+};
+
+const OnceUpon::MenuButton OnceUpon::kAnimalNamesBack = {
+ true, 19, 13, 50, 46, 36, 0, 67, 34, 19, 13, 1
+};
+
+const OnceUpon::MenuButton OnceUpon::kLanguageButtons[] = {
+ {true, 43, 80, 93, 115, 0, 55, 50, 90, 43, 80, 0},
+ {true, 132, 80, 182, 115, 53, 55, 103, 90, 132, 80, 1},
+ {true, 234, 80, 284, 115, 106, 55, 156, 90, 234, 80, 2},
+ {true, 43, 138, 93, 173, 159, 55, 209, 90, 43, 138, 3},
+ {true, 132, 138, 182, 173, 212, 55, 262, 90, 132, 138, 4},
+ {true, 234, 138, 284, 173, 265, 55, 315, 90, 234, 138, 2}
+};
+
+const char *OnceUpon::kSound[kSoundCount] = {
+ "diamant.snd", // kSoundClick
+ "cigogne.snd", // kSoundStork
+ "saute.snd" // kSoundJump
+};
+
+const OnceUpon::SectionFunc OnceUpon::kSectionFuncs[kSectionCount] = {
+ &OnceUpon::sectionStork,
+ &OnceUpon::sectionChapter1,
+ &OnceUpon::sectionParents,
+ &OnceUpon::sectionChapter2,
+ &OnceUpon::sectionForest0,
+ &OnceUpon::sectionChapter3,
+ &OnceUpon::sectionEvilCastle,
+ &OnceUpon::sectionChapter4,
+ &OnceUpon::sectionForest1,
+ &OnceUpon::sectionChapter5,
+ &OnceUpon::sectionBossFight,
+ &OnceUpon::sectionChapter6,
+ &OnceUpon::sectionForest2,
+ &OnceUpon::sectionChapter7,
+ &OnceUpon::sectionEnd
+};
+
+
+OnceUpon::ScreenBackup::ScreenBackup() : palette(-1), changedCursor(false), cursorVisible(false) {
+ screen = new Surface(320, 200, 1);
+}
+
+OnceUpon::ScreenBackup::~ScreenBackup() {
+ delete screen;
+}
+
+
+OnceUpon::OnceUpon(GobEngine *vm) : PreGob(vm), _openedArchives(false),
+ _jeudak(0), _lettre(0), _plettre(0), _glettre(0) {
+
+}
+
+OnceUpon::~OnceUpon() {
+ deinit();
+}
+
+void OnceUpon::init() {
+ deinit();
+
+ // Open data files
+
+ bool hasSTK1 = _vm->_dataIO->openArchive("stk1.stk", true);
+ bool hasSTK2 = _vm->_dataIO->openArchive("stk2.stk", true);
+ bool hasSTK3 = _vm->_dataIO->openArchive("stk3.stk", true);
+
+ if (!hasSTK1 || !hasSTK2 || !hasSTK3)
+ error("OnceUpon::OnceUpon(): Failed to open archives");
+
+ _openedArchives = true;
+
+ // Open fonts
+
+ _jeudak = _vm->_draw->loadFont("jeudak.let");
+ _lettre = _vm->_draw->loadFont("lettre.let");
+ _plettre = _vm->_draw->loadFont("plettre.let");
+ _glettre = _vm->_draw->loadFont("glettre.let");
+
+ if (!_jeudak || !_lettre || !_plettre || !_glettre)
+ error("OnceUpon::OnceUpon(): Failed to fonts (%d, %d, %d, %d)",
+ _jeudak != 0, _lettre != 0, _plettre != 0, _glettre != 0);
+
+ // Verify the language
+
+ if (_vm->_global->_language == kLanguageAmerican)
+ _vm->_global->_language = kLanguageBritish;
+
+ if ((_vm->_global->_language >= kLanguageCount))
+ error("We do not support the language \"%s\".\n"
+ "If you are certain that your game copy includes this language,\n"
+ "please contact the ScummVM team with details about this version.\n"
+ "Thanks", _vm->getLangDesc(_vm->_global->_language));
+
+ // Load all our sounds and init the screen
+
+ loadSounds(kSound, kSoundCount);
+ initScreen();
+
+ // We start with an invalid palette
+ _palette = -1;
+
+ // No quit requested at start
+ _quit = false;
+
+ // We start with no selected difficulty and at section 0
+ _difficulty = kDifficultyCount;
+ _section = 0;
+
+ // Default name
+ _name = "Nemo";
+
+ // Default character properties
+ _house = 0;
+ _head = 0;
+ _colorHair = 0;
+ _colorJacket = 0;
+ _colorTrousers = 0;
+}
+
+void OnceUpon::deinit() {
+ // Free sounds
+ freeSounds();
+
+ // Free fonts
+
+ delete _jeudak;
+ delete _lettre;
+ delete _plettre;
+ delete _glettre;
+
+ _jeudak = 0;
+ _lettre = 0;
+ _plettre = 0;
+ _glettre = 0;
+
+ // Close archives
+
+ if (_openedArchives) {
+ _vm->_dataIO->closeArchive(true);
+ _vm->_dataIO->closeArchive(true);
+ _vm->_dataIO->closeArchive(true);
+ }
+
+ _openedArchives = false;
+}
+
+void OnceUpon::setGamePalette(uint palette) {
+ if (palette >= kPaletteCount)
+ return;
+
+ _palette = palette;
+
+ setPalette(kGamePalettes[palette], kPaletteSize);
+}
+
+void OnceUpon::setGameCursor() {
+ Surface cursor(320, 16, 1);
+
+ // Set the default game cursor
+ _vm->_video->drawPackedSprite("icon.cmp", cursor);
+ setCursor(cursor, 105, 0, 120, 15, 0, 0);
+}
+
+void OnceUpon::drawLineByLine(const Surface &src, int16 left, int16 top, int16 right, int16 bottom,
+ int16 x, int16 y) const {
+
+ // A special way of drawing something:
+ // Draw every other line "downwards", wait a bit after each line
+ // Then, draw the remaining lines "upwards" and again wait a bit after each line.
+
+ if (_vm->shouldQuit())
+ return;
+
+ const int16 width = right - left + 1;
+ const int16 height = bottom - top + 1;
+
+ if ((width <= 0) || (height <= 0))
+ return;
+
+ // Draw the even lines downwards
+ for (int16 i = 0; i < height; i += 2) {
+ if (_vm->shouldQuit())
+ return;
+
+ _vm->_draw->_backSurface->blit(src, left, top + i, right, top + i, x, y + i);
+
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, x, y + i, x + width - 1, y + 1);
+ _vm->_draw->blitInvalidated();
+
+ _vm->_util->longDelay(1);
+ }
+
+ // Draw the odd lines upwards
+ for (int16 i = (height & 1) ? height : (height - 1); i >= 0; i -= 2) {
+ if (_vm->shouldQuit())
+ return;
+
+ _vm->_draw->_backSurface->blit(src, left, top + i, right, top + i, x, y + i);
+
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, x, y + i, x + width - 1, y + 1);
+ _vm->_draw->blitInvalidated();
+
+ _vm->_util->longDelay(1);
+ }
+}
+
+void OnceUpon::backupScreen(ScreenBackup &backup, bool setDefaultCursor) {
+ // Backup the screen and palette
+ backup.screen->blit(*_vm->_draw->_backSurface);
+ backup.palette = _palette;
+
+ // Backup the cursor
+
+ backup.cursorVisible = isCursorVisible();
+
+ backup.changedCursor = false;
+ if (setDefaultCursor) {
+ backup.changedCursor = true;
+
+ addCursor();
+ setGameCursor();
+ }
+}
+
+void OnceUpon::restoreScreen(ScreenBackup &backup) {
+ if (_vm->shouldQuit())
+ return;
+
+ // Restore the screen
+ _vm->_draw->_backSurface->blit(*backup.screen);
+ _vm->_draw->forceBlit();
+
+ // Restore the palette
+ if (backup.palette >= 0)
+ setGamePalette(backup.palette);
+
+ // Restore the cursor
+
+ if (!backup.cursorVisible)
+ hideCursor();
+
+ if (backup.changedCursor)
+ removeCursor();
+
+ backup.changedCursor = false;
+}
+
+void OnceUpon::fixTXTStrings(TXTFile &txt) const {
+ TXTFile::LineArray &lines = txt.getLines();
+ for (uint i = 0; i < lines.size(); i++)
+ lines[i].text = fixString(lines[i].text);
+}
+
+#include "gob/pregob/onceupon/brokenstrings.h"
+Common::String OnceUpon::fixString(const Common::String &str) const {
+ const BrokenStringLanguage &broken = kBrokenStrings[_vm->_global->_language];
+
+ for (uint i = 0; i < broken.count; i++) {
+ if (str == broken.strings[i].wrong)
+ return broken.strings[i].correct;
+ }
+
+ return str;
+}
+
+enum ClownAnimation {
+ kClownAnimationStand = 0,
+ kClownAnimationCheer = 1,
+ kClownAnimationCry = 2
+};
+
+const PreGob::AnimProperties OnceUpon::kClownAnimations[] = {
+ { 1, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 0, 0, ANIObject::kModeOnce , true, false, false, 0, 0},
+ { 6, 0, ANIObject::kModeOnce , true, false, false, 0, 0}
+};
+
+enum CopyProtectionState {
+ kCPStateSetup, // Set up the screen
+ kCPStateWaitUser, // Waiting for the user to pick a shape
+ kCPStateWaitClown, // Waiting for the clown animation to finish
+ kCPStateFinish // Finishing
+};
+
+bool OnceUpon::doCopyProtection(const uint8 colors[7], const uint8 shapes[7 * 20], const uint8 obfuscate[4]) {
+ fadeOut();
+ setPalette(kCopyProtectionPalette, kPaletteSize);
+
+ // Load the copy protection sprites
+ Surface sprites[2] = {Surface(320, 200, 1), Surface(320, 200, 1)};
+
+ _vm->_video->drawPackedSprite("grille1.cmp", sprites[0]);
+ _vm->_video->drawPackedSprite("grille2.cmp", sprites[1]);
+
+ // Load the clown animation
+ ANIFile ani (_vm, "grille.ani", 320);
+ ANIList anims;
+
+ loadAnims(anims, ani, 1, &kClownAnimations[kClownAnimationStand]);
+
+ // Set the copy protection cursor
+ setCursor(sprites[1], 5, 110, 20, 134, 3, 0);
+
+ // We start with 2 tries left, not having a correct answer and the copy protection not set up yet
+ CopyProtectionState state = kCPStateSetup;
+
+ uint8 triesLeft = 2;
+ int8 animalShape = -1;
+ bool hasCorrect = false;
+
+ while (!_vm->shouldQuit() && (state != kCPStateFinish)) {
+ clearAnim(anims);
+
+ // Set up the screen
+ if (state == kCPStateSetup) {
+ animalShape = cpSetup(colors, shapes, obfuscate, sprites);
+
+ setAnim(*anims[0], kClownAnimations[kClownAnimationStand]);
+ state = kCPStateWaitUser;
+ }
+
+ drawAnim(anims);
+
+ // If we're waiting for the clown and he finished, evaluate if we're finished
+ if (!anims[0]->isVisible() && (state == kCPStateWaitClown))
+ state = (hasCorrect || (--triesLeft == 0)) ? kCPStateFinish : kCPStateSetup;
+
+ showCursor();
+ fadeIn();
+
+ endFrame(true);
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ checkInput(mouseX, mouseY, mouseButtons);
+
+ if (state == kCPStateWaitUser) {
+ // Look if we clicked a shaped and got it right
+
+ int8 guessedShape = -1;
+ if (mouseButtons == kMouseButtonsLeft)
+ guessedShape = cpFindShape(mouseX, mouseY);
+
+ if (guessedShape >= 0) {
+ hasCorrect = guessedShape == animalShape;
+ animalShape = -1;
+
+ setAnim(*anims[0], kClownAnimations[hasCorrect ? kClownAnimationCheer : kClownAnimationCry]);
+ state = kCPStateWaitClown;
+ }
+ }
+ }
+
+ freeAnims(anims);
+
+ fadeOut();
+ hideCursor();
+ clearScreen();
+
+ // Display the "You are wrong" screen
+ if (!hasCorrect)
+ cpWrong();
+
+ return hasCorrect;
+}
+
+int8 OnceUpon::cpSetup(const uint8 colors[7], const uint8 shapes[7 * 20], const uint8 obfuscate[4],
+ const Surface sprites[2]) {
+
+ fadeOut();
+ hideCursor();
+
+ // Get a random animal and animal color
+ int8 animalColor = _vm->_util->getRandom(7);
+ while ((colors[animalColor] == 1) || (colors[animalColor] == 7) || (colors[animalColor] == 11))
+ animalColor = _vm->_util->getRandom(7);
+
+ int8 animal = _vm->_util->getRandom(20);
+
+ int8 animalShape = shapes[animalColor * 20 + animal];
+ if (animal < 4)
+ animal = obfuscate[animal];
+
+ // Get the position of the animal sprite
+ int16 animalLeft = (animal % 4) * 80;
+ int16 animalTop = (animal / 4) * 50;
+
+ uint8 sprite = 0;
+ if (animalTop >= 200) {
+ animalTop -= 200;
+ sprite = 1;
+ }
+
+ int16 animalRight = animalLeft + 80 - 1;
+ int16 animalBottom = animalTop + 50 - 1;
+
+ // Fill with the animal color
+ _vm->_draw->_backSurface->fill(colors[animalColor]);
+
+ // Print the help line strings
+ for (uint i = 0; i < kCopyProtectionHelpStringCount; i++) {
+ const char * const helpString = kCopyProtectionHelpStrings[_vm->_global->_language][i];
+
+ const int x = 160 - (strlen(helpString) * _plettre->getCharWidth()) / 2;
+ const int y = i * 10 + 5;
+
+ _plettre->drawString(helpString, x, y, 8, 0, true, *_vm->_draw->_backSurface);
+ }
+
+ // White rectangle with black border
+ _vm->_draw->_backSurface->fillRect( 93, 43, 226, 134, 15);
+ _vm->_draw->_backSurface->drawRect( 92, 42, 227, 135, 0);
+
+ // Draw the animal in the animal color
+ _vm->_draw->_backSurface->fillRect(120, 63, 199, 112, colors[animalColor]);
+ _vm->_draw->_backSurface->blit(sprites[sprite], animalLeft, animalTop, animalRight, animalBottom, 120, 63, 0);
+
+ // Draw the shapes
+ for (uint i = 0; i < kCopyProtectionShapeCount; i++) {
+ const int16 * const coords = kCopyProtectionShapeCoords[i];
+
+ _vm->_draw->_backSurface->blit(sprites[1], coords[0], coords[1], coords[2], coords[3], coords[4], coords[5], 0);
+ }
+
+ _vm->_draw->forceBlit();
+
+ return animalShape;
+}
+
+int8 OnceUpon::cpFindShape(int16 x, int16 y) const {
+ // Look through all shapes and check if the coordinates are inside one of them
+ for (uint i = 0; i < kCopyProtectionShapeCount; i++) {
+ const int16 * const coords = kCopyProtectionShapeCoords[i];
+
+ const int16 left = coords[4];
+ const int16 top = coords[5];
+ const int16 right = coords[4] + (coords[2] - coords[0] + 1) - 1;
+ const int16 bottom = coords[5] + (coords[3] - coords[1] + 1) - 1;
+
+ if ((x >= left) && (x <= right) && (y >= top) && (y <= bottom))
+ return i;
+ }
+
+ return -1;
+}
+
+void OnceUpon::cpWrong() {
+ // Display the "You are wrong" string, centered
+
+ const char * const wrongString = kCopyProtectionWrongStrings[_vm->_global->_language];
+ const int wrongX = 160 - (strlen(wrongString) * _plettre->getCharWidth()) / 2;
+
+ _vm->_draw->_backSurface->clear();
+ _plettre->drawString(wrongString, wrongX, 100, 15, 0, true, *_vm->_draw->_backSurface);
+
+ _vm->_draw->forceBlit();
+
+ fadeIn();
+
+ waitInput();
+
+ fadeOut();
+ clearScreen();
+}
+
+void OnceUpon::showIntro() {
+ // Show all intro parts
+
+ // "Loading"
+ showWait(10);
+ if (_vm->shouldQuit())
+ return;
+
+ // Quote about fairy tales
+ showQuote();
+ if (_vm->shouldQuit())
+ return;
+
+ // Once Upon A Time title
+ showTitle();
+ if (_vm->shouldQuit())
+ return;
+
+ // Game title screen
+ showChapter(0);
+ if (_vm->shouldQuit())
+ return;
+
+ // "Loading"
+ showWait(17);
+}
+
+void OnceUpon::showWait(uint palette) {
+ // Show the loading floppy
+
+ fadeOut();
+ clearScreen();
+ setGamePalette(palette);
+
+ Surface wait(320, 43, 1);
+
+ _vm->_video->drawPackedSprite("wait.cmp", wait);
+ _vm->_draw->_backSurface->blit(wait, 0, 0, 72, 33, 122, 84);
+
+ _vm->_draw->forceBlit();
+
+ fadeIn();
+}
+
+void OnceUpon::showQuote() {
+ // Show the quote about fairytales
+
+ fadeOut();
+ clearScreen();
+ setGamePalette(11);
+
+ static const Font *fonts[3] = { _plettre, _glettre, _plettre };
+
+ TXTFile *quote = loadTXT(getLocFile("gene.tx"), TXTFile::kFormatStringPositionColorFont);
+ quote->draw(*_vm->_draw->_backSurface, fonts, ARRAYSIZE(fonts));
+ delete quote;
+
+ _vm->_draw->forceBlit();
+
+ fadeIn();
+
+ waitInput();
+
+ fadeOut();
+}
+
+const PreGob::AnimProperties OnceUpon::kTitleAnimation = {
+ 8, 0, ANIObject::kModeContinuous, true, false, false, 0, 0
+};
+
+void OnceUpon::showTitle() {
+ fadeOut();
+ setGamePalette(10);
+
+ Title title(_vm);
+ title.play();
+}
+
+void OnceUpon::showChapter(int chapter) {
+ // Display the intro text to a chapter
+
+ fadeOut();
+ clearScreen();
+ setGamePalette(11);
+
+ // Parchment background
+ _vm->_video->drawPackedSprite("parch.cmp", *_vm->_draw->_backSurface);
+
+ static const Font *fonts[3] = { _plettre, _glettre, _plettre };
+
+ const Common::String chapterFile = getLocFile(Common::String::format("gene%d.tx", chapter));
+
+ TXTFile *gameTitle = loadTXT(chapterFile, TXTFile::kFormatStringPositionColorFont);
+ gameTitle->draw(*_vm->_draw->_backSurface, fonts, ARRAYSIZE(fonts));
+ delete gameTitle;
+
+ _vm->_draw->forceBlit();
+
+ fadeIn();
+
+ waitInput();
+
+ fadeOut();
+}
+
+void OnceUpon::showByeBye() {
+ fadeOut();
+ hideCursor();
+ clearScreen();
+ setGamePalette(1);
+
+ _plettre->drawString("Bye Bye....", 140, 80, 2, 0, true, *_vm->_draw->_backSurface);
+ _vm->_draw->forceBlit();
+
+ fadeIn();
+
+ _vm->_util->longDelay(1000);
+
+ fadeOut();
+}
+
+void OnceUpon::doStartMenu(const MenuButton *animalsButton, uint animalCount,
+ const MenuButton *animalButtons, const char * const *animalNames) {
+ clearScreen();
+
+ // Wait until we clicked on of the difficulty buttons and are ready to start playing
+ while (!_vm->shouldQuit()) {
+ MenuAction action = handleStartMenu(animalsButton);
+ if (action == kMenuActionPlay)
+ break;
+
+ // If we pressed the "listen to animal names" button, handle that screen
+ if (action == kMenuActionAnimals)
+ handleAnimalNames(animalCount, animalButtons, animalNames);
+ }
+}
+
+OnceUpon::MenuAction OnceUpon::handleStartMenu(const MenuButton *animalsButton) {
+ ScreenBackup screenBackup;
+ backupScreen(screenBackup, true);
+
+ fadeOut();
+ setGamePalette(17);
+ drawStartMenu(animalsButton);
+ showCursor();
+ fadeIn();
+
+ MenuAction action = kMenuActionNone;
+ while (!_vm->shouldQuit() && (action == kMenuActionNone)) {
+ endFrame(true);
+
+ // Check user input
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ int16 key = checkInput(mouseX, mouseY, mouseButtons);
+ if (key == kKeyEscape)
+ // ESC -> Quit
+ return kMenuActionQuit;
+
+ if (mouseButtons != kMouseButtonsLeft)
+ continue;
+
+ playSound(kSoundClick);
+
+ // If we clicked on a difficulty button, show the selected difficulty and start the game
+ int diff = checkButton(kMainMenuDifficultyButton, ARRAYSIZE(kMainMenuDifficultyButton), mouseX, mouseY);
+ if (diff >= 0) {
+ _difficulty = (Difficulty)diff;
+ action = kMenuActionPlay;
+
+ drawStartMenu(animalsButton);
+ _vm->_util->longDelay(1000);
+ }
+
+ if (animalsButton && (checkButton(animalsButton, 1, mouseX, mouseY) != -1))
+ action = kMenuActionAnimals;
+
+ }
+
+ fadeOut();
+ restoreScreen(screenBackup);
+
+ return action;
+}
+
+OnceUpon::MenuAction OnceUpon::handleMainMenu() {
+ ScreenBackup screenBackup;
+ backupScreen(screenBackup, true);
+
+ fadeOut();
+ setGamePalette(17);
+ drawMainMenu();
+ showCursor();
+ fadeIn();
+
+ MenuAction action = kMenuActionNone;
+ while (!_vm->shouldQuit() && (action == kMenuActionNone)) {
+ endFrame(true);
+
+ // Check user input
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ int16 key = checkInput(mouseX, mouseY, mouseButtons);
+ if (key == kKeyEscape)
+ // ESC -> Quit
+ return kMenuActionQuit;
+
+ if (mouseButtons != kMouseButtonsLeft)
+ continue;
+
+ playSound(kSoundClick);
+
+ // If we clicked on a difficulty button, change the current difficulty level
+ int diff = checkButton(kMainMenuDifficultyButton, ARRAYSIZE(kMainMenuDifficultyButton), mouseX, mouseY);
+ if ((diff >= 0) && (diff != (int)_difficulty)) {
+ _difficulty = (Difficulty)diff;
+
+ drawMainMenu();
+ }
+
+ // If we clicked on a section button, restart the game from this section
+ int section = checkButton(kSectionButtons, ARRAYSIZE(kSectionButtons), mouseX, mouseY);
+ if ((section >= 0) && (section <= _section)) {
+ _section = section;
+ action = kMenuActionRestart;
+ }
+
+ }
+
+ fadeOut();
+ restoreScreen(screenBackup);
+
+ return action;
+}
+
+OnceUpon::MenuAction OnceUpon::handleIngameMenu() {
+ ScreenBackup screenBackup;
+ backupScreen(screenBackup, true);
+
+ drawIngameMenu();
+ showCursor();
+
+ MenuAction action = kMenuActionNone;
+ while (!_vm->shouldQuit() && (action == kMenuActionNone)) {
+ endFrame(true);
+
+ // Check user input
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ int16 key = checkInput(mouseX, mouseY, mouseButtons);
+ if ((key == kKeyEscape) || (mouseButtons == kMouseButtonsRight))
+ // ESC or right mouse button -> Dismiss the menu
+ action = kMenuActionPlay;
+
+ if (mouseButtons != kMouseButtonsLeft)
+ continue;
+
+ int button = checkButton(kIngameButtons, ARRAYSIZE(kIngameButtons), mouseX, mouseY);
+ if (button == 0)
+ action = kMenuActionQuit;
+ else if (button == 1)
+ action = kMenuActionMainMenu;
+ else if (button == 2)
+ action = kMenuActionPlay;
+
+ }
+
+ clearIngameMenu(*screenBackup.screen);
+ restoreScreen(screenBackup);
+
+ return action;
+}
+
+void OnceUpon::drawStartMenu(const MenuButton *animalsButton) {
+ // Draw the background
+ _vm->_video->drawPackedSprite("menu2.cmp", *_vm->_draw->_backSurface);
+
+ // Draw the "Listen to animal names" button
+ if (animalsButton) {
+ Surface elements(320, 38, 1);
+ _vm->_video->drawPackedSprite("elemenu.cmp", elements);
+ _vm->_draw->_backSurface->fillRect(animalsButton->left , animalsButton->top,
+ animalsButton->right, animalsButton->bottom, 0);
+ drawButton(*_vm->_draw->_backSurface, elements, *animalsButton);
+ }
+
+ // Highlight the current difficulty
+ drawMenuDifficulty();
+
+ _vm->_draw->forceBlit();
+}
+
+void OnceUpon::drawMainMenu() {
+ // Draw the background
+ _vm->_video->drawPackedSprite("menu.cmp", *_vm->_draw->_backSurface);
+
+ // Highlight the current difficulty
+ drawMenuDifficulty();
+
+ // Draw the section buttons
+ Surface elements(320, 200, 1);
+ _vm->_video->drawPackedSprite("elemenu.cmp", elements);
+
+ for (uint i = 0; i < ARRAYSIZE(kSectionButtons); i++) {
+ const MenuButton &button = kSectionButtons[i];
+
+ if (!button.needDraw)
+ continue;
+
+ if (_section >= (int)button.id)
+ drawButton(*_vm->_draw->_backSurface, elements, button);
+ }
+
+ _vm->_draw->forceBlit();
+}
+
+void OnceUpon::drawIngameMenu() {
+ Surface menu(320, 34, 1);
+ _vm->_video->drawPackedSprite("icon.cmp", menu);
+
+ // Draw the menu in a special way, button by button
+ for (uint i = 0; i < ARRAYSIZE(kIngameButtons); i++) {
+ const MenuButton &button = kIngameButtons[i];
+
+ drawLineByLine(menu, button.srcLeft, button.srcTop, button.srcRight, button.srcBottom,
+ button.dstX, button.dstY);
+ }
+
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+}
+
+void OnceUpon::drawMenuDifficulty() {
+ if (_difficulty == kDifficultyCount)
+ return;
+
+ TXTFile *difficulties = loadTXT(getLocFile("diffic.tx"), TXTFile::kFormatStringPositionColor);
+
+ // Draw the difficulty name
+ difficulties->draw((uint) _difficulty, *_vm->_draw->_backSurface, &_plettre, 1);
+
+ // Draw a border around the current difficulty
+ drawButtonBorder(kMainMenuDifficultyButton[_difficulty], difficulties->getLines()[_difficulty].color);
+
+ delete difficulties;
+}
+
+void OnceUpon::clearIngameMenu(const Surface &background) {
+ if (_vm->shouldQuit())
+ return;
+
+ // Find the area encompassing the whole ingame menu
+
+ int16 left = 0x7FFF;
+ int16 top = 0x7FFF;
+ int16 right = 0x0000;
+ int16 bottom = 0x0000;
+
+ for (uint i = 0; i < ARRAYSIZE(kIngameButtons); i++) {
+ const MenuButton &button = kIngameButtons[i];
+
+ if (!button.needDraw)
+ continue;
+
+ left = MIN<int16>(left , button.dstX);
+ top = MIN<int16>(top , button.dstY);
+ right = MAX<int16>(right , button.dstX + (button.srcRight - button.srcLeft + 1) - 1);
+ bottom = MAX<int16>(bottom, button.dstY + (button.srcBottom - button.srcTop + 1) - 1);
+ }
+
+ if ((left > right) || (top > bottom))
+ return;
+
+ // Clear it line by line
+ drawLineByLine(background, left, top, right, bottom, left, top);
+}
+
+OnceUpon::MenuAction OnceUpon::doIngameMenu() {
+ // Show the ingame menu
+ MenuAction action = handleIngameMenu();
+
+ if ((action == kMenuActionQuit) || _vm->shouldQuit()) {
+
+ // User pressed the quit button, or quit ScummVM
+ _quit = true;
+ action = kMenuActionQuit;
+
+ } else if (action == kMenuActionPlay) {
+
+ // User pressed the return to game button
+ action = kMenuActionPlay;
+
+ } else if (kMenuActionMainMenu) {
+
+ // User pressed the return to main menu button
+ action = handleMainMenu();
+ }
+
+ return action;
+}
+
+OnceUpon::MenuAction OnceUpon::doIngameMenu(int16 &key, MouseButtons &mouseButtons) {
+ if ((key != kKeyEscape) && (mouseButtons != kMouseButtonsRight))
+ return kMenuActionNone;
+
+ key = 0;
+ mouseButtons = kMouseButtonsNone;
+
+ MenuAction action = doIngameMenu();
+ if (action == kMenuActionPlay)
+ action = kMenuActionNone;
+
+ return action;
+}
+
+int OnceUpon::checkButton(const MenuButton *buttons, uint count, int16 x, int16 y, int failValue) const {
+ // Look through all buttons, and return the ID of the button we're in
+
+ for (uint i = 0; i < count; i++) {
+ const MenuButton &button = buttons[i];
+
+ if ((x >= button.left) && (x <= button.right) && (y >= button.top) && (y <= button.bottom))
+ return (int)button.id;
+ }
+
+ // We're in none of these buttons, return the fail value
+ return failValue;
+}
+
+void OnceUpon::drawButton(Surface &dest, const Surface &src, const MenuButton &button, int transp) const {
+ dest.blit(src, button.srcLeft, button.srcTop, button.srcRight, button.srcBottom, button.dstX, button.dstY, transp);
+}
+
+void OnceUpon::drawButtons(Surface &dest, const Surface &src, const MenuButton *buttons, uint count, int transp) const {
+ for (uint i = 0; i < count; i++) {
+ const MenuButton &button = buttons[i];
+
+ if (!button.needDraw)
+ continue;
+
+ drawButton(dest, src, button, transp);
+ }
+}
+
+void OnceUpon::drawButtonBorder(const MenuButton &button, uint8 color) {
+ _vm->_draw->_backSurface->drawRect(button.left, button.top, button.right, button.bottom, color);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, button.left, button.top, button.right, button.bottom);
+}
+
+enum AnimalNamesState {
+ kANStateChoose, // We're in the animal chooser
+ kANStateNames, // We're in the language chooser
+ kANStateFinish // We're finished
+};
+
+void OnceUpon::handleAnimalNames(uint count, const MenuButton *buttons, const char * const *names) {
+ fadeOut();
+ clearScreen();
+ setGamePalette(19);
+
+ bool cursorVisible = isCursorVisible();
+
+ // Set the cursor
+ addCursor();
+ setGameCursor();
+
+ anSetupChooser();
+
+ int8 _animal = -1;
+
+ AnimalNamesState state = kANStateChoose;
+ while (!_vm->shouldQuit() && (state != kANStateFinish)) {
+ showCursor();
+ fadeIn();
+
+ endFrame(true);
+
+ // Check user input
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ checkInput(mouseX, mouseY, mouseButtons);
+
+ // If we moused over an animal button, draw a border around it
+ int animal = checkButton(buttons, count, mouseX, mouseY);
+ if ((state == kANStateChoose) && (animal != _animal)) {
+ // Erase the old border
+ if (_animal >= 0)
+ drawButtonBorder(buttons[_animal], 15);
+
+ _animal = animal;
+
+ // Draw the new border
+ if (_animal >= 0)
+ drawButtonBorder(buttons[_animal], 10);
+ }
+
+ if (mouseButtons != kMouseButtonsLeft)
+ continue;
+
+ playSound(kSoundClick);
+
+ // We clicked on a language button, play the animal name
+ int language = checkButton(kLanguageButtons, ARRAYSIZE(kLanguageButtons), mouseX, mouseY);
+ if ((state == kANStateNames) && (language >= 0))
+ anPlayAnimalName(names[_animal], language);
+
+ // We clicked on an animal
+ if ((state == kANStateChoose) && (_animal >= 0)) {
+ anSetupNames(buttons[_animal]);
+
+ state = kANStateNames;
+ }
+
+ // If we clicked on the back button, go back
+ if (checkButton(&kAnimalNamesBack, 1, mouseX, mouseY) != -1) {
+ if (state == kANStateNames) {
+ anSetupChooser();
+
+ state = kANStateChoose;
+ } else if (state == kANStateChoose)
+ state = kANStateFinish;
+ }
+ }
+
+ fadeOut();
+
+ // Restore the cursor
+ if (!cursorVisible)
+ hideCursor();
+ removeCursor();
+}
+
+void OnceUpon::anSetupChooser() {
+ fadeOut();
+
+ _vm->_video->drawPackedSprite("dico.cmp", *_vm->_draw->_backSurface);
+
+ // Draw the back button
+ Surface menu(320, 34, 1);
+ _vm->_video->drawPackedSprite("icon.cmp", menu);
+ drawButton(*_vm->_draw->_backSurface, menu, kAnimalNamesBack);
+
+ // "Choose an animal"
+ TXTFile *choose = loadTXT(getLocFile("choisi.tx"), TXTFile::kFormatStringPosition);
+ choose->draw(*_vm->_draw->_backSurface, &_plettre, 1, 14);
+ delete choose;
+
+ _vm->_draw->forceBlit();
+}
+
+void OnceUpon::anSetupNames(const MenuButton &animal) {
+ fadeOut();
+
+ Surface background(320, 200, 1);
+
+ _vm->_video->drawPackedSprite("dico.cmp", background);
+
+ // Draw the background and clear what we don't need
+ _vm->_draw->_backSurface->blit(background);
+ _vm->_draw->_backSurface->fillRect(19, 19, 302, 186, 15);
+
+ // Draw the back button
+ Surface menu(320, 34, 1);
+ _vm->_video->drawPackedSprite("icon.cmp", menu);
+ drawButton(*_vm->_draw->_backSurface, menu, kAnimalNamesBack);
+
+ // Draw the animal
+ drawButton(*_vm->_draw->_backSurface, background, animal);
+
+ // Draw the language buttons
+ Surface elements(320, 200, 1);
+ _vm->_video->drawPackedSprite("elemenu.cmp", elements);
+ drawButtons(*_vm->_draw->_backSurface, elements, kLanguageButtons, ARRAYSIZE(kLanguageButtons));
+
+ // Draw the language names
+ _plettre->drawString("Fran\207ais", 43, 70, 10, 15, true, *_vm->_draw->_backSurface);
+ _plettre->drawString("Deutsch" , 136, 70, 10, 15, true, *_vm->_draw->_backSurface);
+ _plettre->drawString("English" , 238, 70, 10, 15, true, *_vm->_draw->_backSurface);
+ _plettre->drawString("Italiano" , 43, 128, 10, 15, true, *_vm->_draw->_backSurface);
+ _plettre->drawString("Espa\244ol" , 136, 128, 10, 15, true, *_vm->_draw->_backSurface);
+ _plettre->drawString("English" , 238, 128, 10, 15, true, *_vm->_draw->_backSurface);
+
+ _vm->_draw->forceBlit();
+}
+
+void OnceUpon::anPlayAnimalName(const Common::String &animal, uint language) {
+ // Sound file to play
+ Common::String soundFile = animal + "_" + kLanguageSuffixLong[language] + ".snd";
+
+ // Get the name of the animal
+ TXTFile *names = loadTXT(animal + ".anm", TXTFile::kFormatString);
+ Common::String name = names->getLines()[language].text;
+ delete names;
+
+ // It should be centered on the screen
+ const int nameX = 160 - (name.size() * _plettre->getCharWidth()) / 2;
+
+ // Backup the screen surface
+ Surface backup(162, 23, 1);
+ backup.blit(*_vm->_draw->_backSurface, 78, 123, 239, 145, 0, 0);
+
+ // Draw the name border
+ Surface nameBorder(162, 23, 1);
+ _vm->_video->drawPackedSprite("mot.cmp", nameBorder);
+ _vm->_draw->_backSurface->blit(nameBorder, 0, 0, 161, 22, 78, 123);
+
+ // Print the animal name
+ _plettre->drawString(name, nameX, 129, 10, 0, true, *_vm->_draw->_backSurface);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 78, 123, 239, 145);
+
+ playSoundFile(soundFile);
+
+ // Restore the screen
+ _vm->_draw->_backSurface->blit(backup, 0, 0, 161, 22, 78, 123);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 78, 123, 239, 145);
+}
+
+void OnceUpon::playGame() {
+ while (!_vm->shouldQuit() && !_quit) {
+ // Play a section and advance to the next section if we finished it
+ if (playSection())
+ _section = MIN(_section + 1, kSectionCount - 1);
+ }
+
+ // If we quit through the game and not through ScummVM, show the "Bye Bye" screen
+ if (!_vm->shouldQuit())
+ showByeBye();
+}
+
+bool OnceUpon::playSection() {
+ if ((_section < 0) || (_section >= ARRAYSIZE(kSectionFuncs))) {
+ _quit = true;
+ return false;
+ }
+
+ return (this->*kSectionFuncs[_section])();
+}
+
+const PreGob::AnimProperties OnceUpon::kSectionStorkAnimations[] = {
+ { 0, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 1, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 2, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 3, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 4, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 5, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 6, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 7, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 8, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ {17, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ {16, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ {15, 0, ANIObject::kModeContinuous, true, false, false, 0, 0}
+};
+
+enum StorkState {
+ kStorkStateWaitUser,
+ kStorkStateWaitBundle,
+ kStorkStateFinish
+};
+
+bool OnceUpon::sectionStork() {
+ fadeOut();
+ hideCursor();
+ setGamePalette(0);
+ setGameCursor();
+
+ const StorkParam &param = getStorkParameters();
+
+ Surface backdrop(320, 200, 1);
+
+ // Draw the frame
+ _vm->_video->drawPackedSprite("cadre.cmp", *_vm->_draw->_backSurface);
+
+ // Draw the backdrop
+ _vm->_video->drawPackedSprite(param.backdrop, backdrop);
+ _vm->_draw->_backSurface->blit(backdrop, 0, 0, 288, 175, 16, 12);
+
+ // "Where does the stork go?"
+ TXTFile *whereStork = loadTXT(getLocFile("ouva.tx"), TXTFile::kFormatStringPositionColor);
+ whereStork->draw(*_vm->_draw->_backSurface, &_plettre, 1);
+
+ // Where the stork actually goes
+ GCTFile *thereStork = loadGCT(getLocFile("choix.gc"));
+ thereStork->setArea(17, 18, 303, 41);
+
+ ANIFile ani(_vm, "present.ani", 320);
+ ANIList anims;
+
+ Stork *stork = new Stork(_vm, ani);
+
+ loadAnims(anims, ani, ARRAYSIZE(kSectionStorkAnimations), kSectionStorkAnimations);
+ anims.push_back(stork);
+
+ drawAnim(anims);
+
+ _vm->_draw->forceBlit();
+
+ int8 storkSoundWait = 0;
+
+ StorkState state = kStorkStateWaitUser;
+ MenuAction action = kMenuActionNone;
+ while (!_vm->shouldQuit() && (state != kStorkStateFinish)) {
+ // Play the stork sound
+ if (--storkSoundWait == 0)
+ playSound(kSoundStork);
+ if (storkSoundWait <= 0)
+ storkSoundWait = 50 - _vm->_util->getRandom(30);
+
+ // Check if the bundle landed
+ if ((state == kStorkStateWaitBundle) && stork->hasBundleLanded())
+ state = kStorkStateFinish;
+
+ // Check user input
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ int16 key = checkInput(mouseX, mouseY, mouseButtons);
+
+ action = doIngameMenu(key, mouseButtons);
+ if (action != kMenuActionNone) {
+ state = kStorkStateFinish;
+ break;
+ }
+
+ clearAnim(anims);
+
+ if (mouseButtons == kMouseButtonsLeft) {
+ stopSound();
+ playSound(kSoundClick);
+
+ int house = checkButton(param.houses, param.houseCount, mouseX, mouseY);
+ if ((state == kStorkStateWaitUser) && (house >= 0)) {
+
+ _house = house;
+
+ stork->dropBundle(param.drops[house]);
+ state = kStorkStateWaitBundle;
+
+ // Remove the "Where does the stork go?" text
+ int16 left, top, right, bottom;
+ if (whereStork->clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+
+ // Print the text where the stork actually goes
+ thereStork->selectLine(3, house); // The house
+ thereStork->selectLine(4, house); // The house's inhabitants
+ if (thereStork->draw(*_vm->_draw->_backSurface, 2, *_plettre, 10, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ }
+ }
+
+ drawAnim(anims);
+ showCursor();
+ fadeIn();
+
+ endFrame(true);
+ }
+
+ freeAnims(anims);
+ delete thereStork;
+ delete whereStork;
+
+ fadeOut();
+ hideCursor();
+
+ // Didn't complete the section
+ if (action != kMenuActionNone)
+ return false;
+
+ // Move on to the character generator
+
+ CharGenAction charGenAction = kCharGenRestart;
+ while (charGenAction == kCharGenRestart)
+ charGenAction = characterGenerator();
+
+ // Did we successfully create a character?
+ return charGenAction == kCharGenDone;
+}
+
+const OnceUpon::MenuButton OnceUpon::kCharGenHeadButtons[] = {
+ {true, 106, 146, 152, 180, 0, 0, 47, 34, 106, 146, 0},
+ {true, 155, 146, 201, 180, 49, 0, 96, 34, 155, 146, 1},
+ {true, 204, 146, 250, 180, 98, 0, 145, 34, 204, 146, 2},
+ {true, 253, 146, 299, 180, 147, 0, 194, 34, 253, 146, 3}
+};
+
+const OnceUpon::MenuButton OnceUpon::kCharGenHeads[] = {
+ {true, 0, 0, 0, 0, 29, 4, 68, 31, 40, 51, 0},
+ {true, 0, 0, 0, 0, 83, 4, 113, 31, 45, 51, 1},
+ {true, 0, 0, 0, 0, 132, 4, 162, 31, 45, 51, 2},
+ {true, 0, 0, 0, 0, 182, 4, 211, 31, 45, 51, 3}
+};
+
+const OnceUpon::MenuButton OnceUpon::kCharGenHairButtons[] = {
+ {true, 105, 55, 124, 70, 271, 1, 289, 15, 105, 55, 0x04},
+ {true, 105, 74, 124, 89, 271, 20, 289, 34, 105, 74, 0x07}
+};
+
+const OnceUpon::MenuButton OnceUpon::kCharGenJacketButtons[] = {
+ {true, 105, 90, 124, 105, 271, 39, 289, 53, 105, 90, 0x06},
+ {true, 105, 109, 124, 124, 271, 58, 289, 72, 105, 109, 0x02}
+};
+
+const OnceUpon::MenuButton OnceUpon::kCharGenTrousersButtons[] = {
+ {true, 105, 140, 124, 155, 271, 77, 289, 91, 105, 140, 0x01},
+ {true, 105, 159, 124, 174, 271, 96, 289, 110, 105, 159, 0x03}
+};
+
+const OnceUpon::MenuButton OnceUpon::kCharGenNameEntry[] = {
+ {true, 0, 0, 0, 0, 0, 38, 54, 48, 140, 145, 0},
+ {true, 0, 0, 0, 0, 106, 38, 159, 48, 195, 145, 0},
+ {true, 0, 0, 0, 0, 0, 105, 54, 121, 140, 156, 0},
+ {true, 0, 0, 0, 0, 106, 105, 159, 121, 195, 156, 0}
+};
+
+enum CharGenState {
+ kCharGenStateHead = 0, // Choose a head
+ kCharGenStateHair , // Choose hair color
+ kCharGenStateJacket , // Choose jacket color
+ kCharGenStateTrousers , // Choose trousers color
+ kCharGenStateName , // Choose name
+ kCharGenStateSure , // "Are you sure?"
+ kCharGenStateStoryName , // "We're going to tell the story of $NAME"
+ kCharGenStateFinish // Finished
+};
+
+void OnceUpon::charGenSetup(uint stage) {
+ Surface choix(320, 200, 1), elchoix(320, 200, 1), paperDoll(65, 137, 1);
+
+ _vm->_video->drawPackedSprite("choix.cmp" , choix);
+ _vm->_video->drawPackedSprite("elchoix.cmp", elchoix);
+
+ paperDoll.blit(choix, 200, 0, 264, 136, 0, 0);
+
+ GCTFile *text = loadGCT(getLocFile("choix.gc"));
+ text->setArea(17, 18, 303, 41);
+ text->setText(9, _name);
+
+ // Background
+ _vm->_video->drawPackedSprite("cadre.cmp", *_vm->_draw->_backSurface);
+ _vm->_draw->_backSurface->fillRect(16, 50, 303, 187, 5);
+
+ // Character sprite frame
+ _vm->_draw->_backSurface->blit(choix, 0, 38, 159, 121, 140, 54);
+
+ // Recolor the paper doll parts
+ if (_colorHair != 0xFF)
+ elchoix.recolor(0x0C, _colorHair);
+
+ if (_colorJacket != 0xFF)
+ paperDoll.recolor(0x0A, _colorJacket);
+
+ if (_colorTrousers != 0xFF)
+ paperDoll.recolor(0x09, _colorTrousers);
+
+ _vm->_draw->_backSurface->blit(paperDoll, 32, 51);
+
+ // Paper doll head
+ if (_head != 0xFF)
+ drawButton(*_vm->_draw->_backSurface, elchoix, kCharGenHeads[_head], 0);
+
+ if (stage == kCharGenStateHead) {
+ // Head buttons
+ drawButtons(*_vm->_draw->_backSurface, choix, kCharGenHeadButtons, ARRAYSIZE(kCharGenHeadButtons));
+
+ // "Choose a head"
+ int16 left, top, right, bottom;
+ text->draw(*_vm->_draw->_backSurface, 5, *_plettre, 10, left, top, right, bottom);
+
+ } else if (stage == kCharGenStateHair) {
+ // Hair color buttons
+ drawButtons(*_vm->_draw->_backSurface, choix, kCharGenHairButtons, ARRAYSIZE(kCharGenHairButtons));
+
+ // "What color is the hair?"
+ int16 left, top, right, bottom;
+ text->draw(*_vm->_draw->_backSurface, 6, *_plettre, 10, left, top, right, bottom);
+
+ } else if (stage == kCharGenStateJacket) {
+ // Jacket color buttons
+ drawButtons(*_vm->_draw->_backSurface, choix, kCharGenJacketButtons, ARRAYSIZE(kCharGenJacketButtons));
+
+ // "What color is the jacket?"
+ int16 left, top, right, bottom;
+ text->draw(*_vm->_draw->_backSurface, 7, *_plettre, 10, left, top, right, bottom);
+
+ } else if (stage == kCharGenStateTrousers) {
+ // Trousers color buttons
+ drawButtons(*_vm->_draw->_backSurface, choix, kCharGenTrousersButtons, ARRAYSIZE(kCharGenTrousersButtons));
+
+ // "What color are the trousers?"
+ int16 left, top, right, bottom;
+ text->draw(*_vm->_draw->_backSurface, 8, *_plettre, 10, left, top, right, bottom);
+
+ } else if (stage == kCharGenStateName) {
+ // Name entry field
+ drawButtons(*_vm->_draw->_backSurface, choix, kCharGenNameEntry, ARRAYSIZE(kCharGenNameEntry));
+
+ // "Enter name"
+ int16 left, top, right, bottom;
+ text->draw(*_vm->_draw->_backSurface, 10, *_plettre, 10, left, top, right, bottom);
+
+ charGenDrawName();
+ } else if (stage == kCharGenStateSure) {
+ // Name entry field
+ drawButtons(*_vm->_draw->_backSurface, choix, kCharGenNameEntry, ARRAYSIZE(kCharGenNameEntry));
+
+ // "Are you sure?"
+ TXTFile *sure = loadTXT(getLocFile("estu.tx"), TXTFile::kFormatStringPositionColor);
+ sure->draw(*_vm->_draw->_backSurface, &_plettre, 1);
+ delete sure;
+
+ charGenDrawName();
+ } else if (stage == kCharGenStateStoryName) {
+
+ // "We're going to tell the story of $NAME"
+ int16 left, top, right, bottom;
+ text->draw(*_vm->_draw->_backSurface, 11, *_plettre, 10, left, top, right, bottom);
+ }
+
+ delete text;
+}
+
+bool OnceUpon::enterString(Common::String &name, int16 key, uint maxLength, const Font &font) {
+ if (key == 0)
+ return true;
+
+ if (key == kKeyBackspace) {
+ name.deleteLastChar();
+ return true;
+ }
+
+ if (key == kKeySpace)
+ key = ' ';
+
+ if ((key >= ' ') && (key <= 0xFF)) {
+ if (name.size() >= maxLength)
+ return false;
+
+ if (!font.hasChar(key))
+ return false;
+
+ name += (char) key;
+ return true;
+ }
+
+ return false;
+}
+
+void OnceUpon::charGenDrawName() {
+ _vm->_draw->_backSurface->fillRect(147, 151, 243, 166, 1);
+
+ const int16 nameY = 151 + ((166 - 151 + 1 - _plettre->getCharHeight()) / 2);
+ const int16 nameX = 147 + ((243 - 147 + 1 - (15 * _plettre->getCharWidth ())) / 2);
+
+ _plettre->drawString(_name, nameX, nameY, 10, 0, true, *_vm->_draw->_backSurface);
+
+ const int16 cursorLeft = nameX + _name.size() * _plettre->getCharWidth();
+ const int16 cursorTop = nameY;
+ const int16 cursorRight = cursorLeft + _plettre->getCharWidth() - 1;
+ const int16 cursorBottom = cursorTop + _plettre->getCharHeight() - 1;
+
+ _vm->_draw->_backSurface->fillRect(cursorLeft, cursorTop, cursorRight, cursorBottom, 10);
+
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 147, 151, 243, 166);
+}
+
+OnceUpon::CharGenAction OnceUpon::characterGenerator() {
+ fadeOut();
+ hideCursor();
+ setGameCursor();
+
+ showWait(1);
+
+ _name.clear();
+
+ _head = 0xFF;
+ _colorHair = 0xFF;
+ _colorJacket = 0xFF;
+ _colorTrousers = 0xFF;
+
+ CharGenState state = kCharGenStateHead;
+ charGenSetup(state);
+
+ ANIFile ani(_vm, "ba.ani", 320);
+
+ ani.recolor(0x0F, 0x0C);
+ ani.recolor(0x0E, 0x0A);
+ ani.recolor(0x08, 0x09);
+
+ CharGenChild *child = new CharGenChild(ani);
+
+ ANIList anims;
+ anims.push_back(child);
+
+ fadeOut();
+ _vm->_draw->forceBlit();
+
+ CharGenAction action = kCharGenRestart;
+ while (!_vm->shouldQuit() && (state != kCharGenStateFinish)) {
+ // Check user input
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ int16 key = checkInput(mouseX, mouseY, mouseButtons);
+
+ MenuAction menuAction = doIngameMenu(key, mouseButtons);
+ if (menuAction != kMenuActionNone) {
+ state = kCharGenStateFinish;
+ action = kCharGenAbort;
+ break;
+ }
+
+ clearAnim(anims);
+
+ if (state == kCharGenStateStoryName) {
+ if ((mouseButtons != kMouseButtonsNone) || (key != 0)) {
+ state = kCharGenStateFinish;
+ action = kCharGenDone;
+ break;
+ }
+ }
+
+ if (state == kCharGenStateSure) {
+ // Not sure => restart
+ if ((key == 'N') || (key == 'n')) { // No / Nein / Non
+ state = kCharGenStateFinish;
+ action = kCharGenRestart;
+ break;
+ }
+
+ if ((key == 'Y') || (key == 'y') || // Yes
+ (key == 'J') || (key == 'j') || // Ja
+ (key == 'S') || (key == 's') || // Si
+ (key == 'O') || (key == 'o')) { // Oui
+
+ state = kCharGenStateStoryName;
+ charGenSetup(state);
+ _vm->_draw->forceBlit();
+ }
+ }
+
+ if (state == kCharGenStateName) {
+ if (enterString(_name, key, 14, *_plettre)) {
+ _vm->_draw->_backSurface->fillRect(147, 151, 243, 166, 1);
+
+ const int16 nameY = 151 + ((166 - 151 + 1 - _plettre->getCharHeight()) / 2);
+ const int16 nameX = 147 + ((243 - 147 + 1 - (15 * _plettre->getCharWidth ())) / 2);
+
+ _plettre->drawString(_name, nameX, nameY, 10, 0, true, *_vm->_draw->_backSurface);
+
+ const int16 cursorLeft = nameX + _name.size() * _plettre->getCharWidth();
+ const int16 cursorTop = nameY;
+ const int16 cursorRight = cursorLeft + _plettre->getCharWidth() - 1;
+ const int16 cursorBottom = cursorTop + _plettre->getCharHeight() - 1;
+
+ _vm->_draw->_backSurface->fillRect(cursorLeft, cursorTop, cursorRight, cursorBottom, 10);
+
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 147, 151, 243, 166);
+ }
+
+ if ((key == kKeyReturn) && !_name.empty()) {
+ _name.trim();
+ _name.setChar(Util::toCP850Upper(_name[0]), 0);
+
+ state = kCharGenStateSure;
+ charGenSetup(state);
+ _vm->_draw->forceBlit();
+ }
+ }
+
+ if (mouseButtons == kMouseButtonsLeft) {
+ stopSound();
+ playSound(kSoundClick);
+
+ int trousers = checkButton(kCharGenTrousersButtons, ARRAYSIZE(kCharGenTrousersButtons), mouseX, mouseY);
+ if ((state == kCharGenStateTrousers) && (trousers >= 0)) {
+ _colorTrousers = trousers;
+
+ ani.recolor(0x09, _colorTrousers);
+
+ state = kCharGenStateName;
+ charGenSetup(state);
+ _vm->_draw->forceBlit();
+ }
+
+ int jacket = checkButton(kCharGenJacketButtons, ARRAYSIZE(kCharGenJacketButtons), mouseX, mouseY);
+ if ((state == kCharGenStateJacket) && (jacket >= 0)) {
+ _colorJacket = jacket;
+
+ ani.recolor(0x0A, _colorJacket);
+
+ state = kCharGenStateTrousers;
+ charGenSetup(state);
+ _vm->_draw->forceBlit();
+ }
+
+ int hair = checkButton(kCharGenHairButtons, ARRAYSIZE(kCharGenHairButtons), mouseX, mouseY);
+ if ((state == kCharGenStateHair) && (hair >= 0)) {
+ _colorHair = hair;
+
+ ani.recolor(0x0C, _colorHair);
+
+ state = kCharGenStateJacket;
+ charGenSetup(state);
+ _vm->_draw->forceBlit();
+ }
+
+ int head = checkButton(kCharGenHeadButtons, ARRAYSIZE(kCharGenHeadButtons), mouseX, mouseY);
+ if ((state == kCharGenStateHead) && (head >= 0)) {
+ _head = head;
+
+ state = kCharGenStateHair;
+ charGenSetup(state);
+ _vm->_draw->forceBlit();
+ }
+ }
+
+ drawAnim(anims);
+
+ // Play the child sounds
+ CharGenChild::Sound childSound = child->shouldPlaySound();
+ if (childSound == CharGenChild::kSoundWalk) {
+ beep(50, 10);
+ } else if (childSound == CharGenChild::kSoundJump) {
+ stopSound();
+ playSound(kSoundJump);
+ }
+
+ showCursor();
+ fadeIn();
+
+ endFrame(true);
+ }
+
+ fadeOut();
+ hideCursor();
+
+ freeAnims(anims);
+
+ if (_vm->shouldQuit())
+ return kCharGenAbort;
+
+ return action;
+}
+
+bool OnceUpon::sectionChapter1() {
+ showChapter(1);
+ return true;
+}
+
+bool OnceUpon::sectionParents() {
+ fadeOut();
+ setGamePalette(14);
+ clearScreen();
+
+ const Common::String seq = ((_house == 1) || (_house == 2)) ? "parents.seq" : "parents2.seq";
+ const Common::String gct = getLocFile("mefait.gc");
+
+ Parents parents(_vm, seq, gct, _name, _house, *_plettre, kGamePalettes[14], kGamePalettes[13], kPaletteSize);
+ parents.play();
+
+ warning("OnceUpon::sectionParents(): TODO: Item search");
+ return true;
+}
+
+bool OnceUpon::sectionChapter2() {
+ showChapter(2);
+ return true;
+}
+
+bool OnceUpon::sectionForest0() {
+ warning("OnceUpon::sectionForest0(): TODO");
+ return true;
+}
+
+bool OnceUpon::sectionChapter3() {
+ showChapter(3);
+ return true;
+}
+
+bool OnceUpon::sectionEvilCastle() {
+ warning("OnceUpon::sectionEvilCastle(): TODO");
+ return true;
+}
+
+bool OnceUpon::sectionChapter4() {
+ showChapter(4);
+ return true;
+}
+
+bool OnceUpon::sectionForest1() {
+ warning("OnceUpon::sectionForest1(): TODO");
+ return true;
+}
+
+bool OnceUpon::sectionChapter5() {
+ showChapter(5);
+ return true;
+}
+
+bool OnceUpon::sectionBossFight() {
+ warning("OnceUpon::sectionBossFight(): TODO");
+ return true;
+}
+
+bool OnceUpon::sectionChapter6() {
+ showChapter(6);
+ return true;
+}
+
+bool OnceUpon::sectionForest2() {
+ warning("OnceUpon::sectionForest2(): TODO");
+ return true;
+}
+
+bool OnceUpon::sectionChapter7() {
+ showChapter(7);
+ return true;
+}
+
+const PreGob::AnimProperties OnceUpon::kSectionEndAnimations[] = {
+ { 0, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 6, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 9, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ {11, 0, ANIObject::kModeContinuous, true, false, false, 0, 0}
+};
+
+bool OnceUpon::sectionEnd() {
+ fadeOut();
+ setGamePalette(9);
+
+ _vm->_video->drawPackedSprite("cadre.cmp", *_vm->_draw->_backSurface);
+
+ Surface endBackground(320, 200, 1);
+ _vm->_video->drawPackedSprite("fin.cmp", endBackground);
+
+ _vm->_draw->_backSurface->blit(endBackground, 0, 0, 288, 137, 16, 50);
+
+ GCTFile *endText = loadGCT(getLocFile("final.gc"));
+ endText->setArea(17, 18, 303, 41);
+ endText->setText(1, _name);
+
+ ANIFile ani(_vm, "fin.ani", 320);
+ ANIList anims;
+
+ loadAnims(anims, ani, ARRAYSIZE(kSectionEndAnimations), kSectionEndAnimations);
+ drawAnim(anims);
+
+ _vm->_draw->forceBlit();
+
+ uint32 textStartTime = 0;
+
+ MenuAction action = kMenuActionNone;
+ while (!_vm->shouldQuit() && (action == kMenuActionNone)) {
+ // Check user input
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ int16 key = checkInput(mouseX, mouseY, mouseButtons);
+
+ action = doIngameMenu(key, mouseButtons);
+ if (action != kMenuActionNone)
+ break;
+
+ clearAnim(anims);
+
+ // Pressed a key or mouse button => Skip to next area-full of text
+ if ((mouseButtons == kMouseButtonsLeft) || (key != 0))
+ textStartTime = 0;
+
+ // Draw the next area-full of text
+ uint32 now = _vm->_util->getTimeKey();
+ if (!endText->finished() && ((textStartTime == 0) || (now >= (textStartTime + kGCTDelay)))) {
+ textStartTime = now;
+
+ int16 left, top, right, bottom;
+ if (endText->clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+
+ if (endText->draw(*_vm->_draw->_backSurface, 0, *_plettre, 10, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ }
+
+ drawAnim(anims);
+ fadeIn();
+
+ endFrame(true);
+ }
+
+ freeAnims(anims);
+ delete endText;
+
+ // Restart requested
+ if (action == kMenuActionRestart)
+ return false;
+
+ // Last scene. Even if we didn't explicitly request a quit, the game ends here
+ _quit = true;
+ return false;
+}
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/onceupon/onceupon.h b/engines/gob/pregob/onceupon/onceupon.h
new file mode 100644
index 0000000000..66ef877618
--- /dev/null
+++ b/engines/gob/pregob/onceupon/onceupon.h
@@ -0,0 +1,344 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_ONCEUPON_H
+#define GOB_PREGOB_ONCEUPON_ONCEUPON_H
+
+#include "common/system.h"
+#include "common/str.h"
+
+#include "gob/pregob/pregob.h"
+
+#include "gob/pregob/onceupon/stork.h"
+
+namespace Gob {
+
+class Surface;
+class Font;
+
+class ANIObject;
+
+namespace OnceUpon {
+
+class OnceUpon : public PreGob {
+public:
+ /** Number of languages we support. */
+ static const uint kLanguageCount = 5;
+
+
+ OnceUpon(GobEngine *vm);
+ ~OnceUpon();
+
+
+protected:
+ /** A description of a menu button. */
+ struct MenuButton {
+ bool needDraw; ///< Does the button need drawing?
+
+ int16 left; ///< Left coordinate of the button.
+ int16 top; ///< Top coordinate of the button.
+ int16 right; ///< Right coordinate of the button.
+ int16 bottom; ///< Bottom coordinate of the button.
+
+ int16 srcLeft; ///< Left coordinate of the button's sprite.
+ int16 srcTop; ///< Top coordinate of the button's sprite.
+ int16 srcRight; ///< Right coordinate of the button's sprite.
+ int16 srcBottom; ///< Right coordinate of the button's sprite.
+
+ int16 dstX; ///< Destination X coordinate of the button's sprite.
+ int16 dstY; ///< Destination Y coordinate of the button's sprite.
+
+ uint id; ///< The button's ID.
+ };
+
+ /** Parameters for the stork section. */
+ struct StorkParam {
+ const char *backdrop; ///< Backdrop image file.
+
+ uint houseCount; ///< Number of houses.
+ const MenuButton *houses; ///< House button definitions.
+
+ const Stork::BundleDrop *drops; ///< The bundle drop parameters.
+ };
+
+ void init();
+ void deinit();
+
+ /** Handle the copy protection.
+ *
+ * @param colors Colors the copy protection animals can be.
+ * @param shapes The shape that's the correct answer for each animal in each color.
+ * @param obfuscate Extra obfuscate table. correctShape = shapes[colors][obfuscate[animal]].
+ * @return true if the user guessed the correct shape, false otherwise.
+ */
+ bool doCopyProtection(const uint8 colors[7], const uint8 shapes[7 * 20], const uint8 obfuscate[4]);
+
+ /** Show the intro. */
+ void showIntro();
+
+ /** Handle the start menu.
+ *
+ * @param animalsButton Definition of the menu button that leads to the animal names screen. Can be 0.
+ * @param animalCount Number of animals in the animal names screen.
+ * @param animalButtons Definition of the buttons that make up the animals in the animal names screen.
+ * @param animalNames File prefixes for the name of each animal.
+ */
+ void doStartMenu(const MenuButton *animalsButton, uint animalCount,
+ const MenuButton *animalButtons, const char * const *animalNames);
+
+ /** Play the game proper. */
+ void playGame();
+
+
+ /** Return the parameters for the stork section. */
+ virtual const StorkParam &getStorkParameters() const = 0;
+
+
+private:
+ /** All actions a user can request in a menu. */
+ enum MenuAction {
+ kMenuActionNone = 0, ///< No action.
+ kMenuActionAnimals , ///< Do the animal names.
+ kMenuActionPlay , ///< Play the game.
+ kMenuActionRestart , ///< Restart the section.
+ kMenuActionMainMenu, ///< Go to the main menu.
+ kMenuActionQuit ///< Quit the game.
+ };
+
+ /** Difficulty levels. */
+ enum Difficulty {
+ kDifficultyBeginner = 0,
+ kDifficultyIntermediate = 1,
+ kDifficultyAdvanced = 2,
+ kDifficultyCount
+ };
+
+ /** The different sounds common in the game. */
+ enum Sound {
+ kSoundClick = 0,
+ kSoundStork ,
+ kSoundJump ,
+ kSoundCount
+ };
+
+ /** Action the character generation wants us to take. */
+ enum CharGenAction {
+ kCharGenDone = 0, ///< Created a character, move on.
+ kCharGenAbort , ///< Aborted the character generation.
+ kCharGenRestart ///< Restart the character generation.
+ };
+
+ /** A complete screen backup. */
+ struct ScreenBackup {
+ Surface *screen; ///< Screen contents.
+ int palette; ///< Screen palette.
+
+ bool changedCursor; ///< Did we change the cursor?
+ bool cursorVisible; ///< Was the cursor visible?
+
+ ScreenBackup();
+ ~ScreenBackup();
+ };
+
+
+ /** The number of game sections. */
+ static const int kSectionCount = 15;
+
+ static const MenuButton kMainMenuDifficultyButton[]; ///< Difficulty buttons.
+ static const MenuButton kSectionButtons[]; ///< Section buttons.
+
+ static const MenuButton kIngameButtons[]; ///< Ingame menu buttons.
+
+ static const MenuButton kAnimalNamesBack; ///< "Back" button in the animal names screens.
+ static const MenuButton kLanguageButtons[]; ///< Language buttons in the animal names screen.
+
+ static const MenuButton kSectionStorkHouses[];
+
+ static const MenuButton kCharGenHeadButtons[];
+ static const MenuButton kCharGenHeads[];
+ static const MenuButton kCharGenHairButtons[];
+ static const MenuButton kCharGenJacketButtons[];
+ static const MenuButton kCharGenTrousersButtons[];
+ static const MenuButton kCharGenNameEntry[];
+
+ /** All general game sounds we know about. */
+ static const char *kSound[kSoundCount];
+
+
+ static const AnimProperties kClownAnimations[];
+ static const AnimProperties kTitleAnimation;
+ static const AnimProperties kSectionStorkAnimations[];
+ static const AnimProperties kSectionEndAnimations[];
+
+
+ /** Function pointer type for a section handler. */
+ typedef bool (OnceUpon::*SectionFunc)();
+ /** Section handler function. */
+ static const SectionFunc kSectionFuncs[kSectionCount];
+
+
+ /** Did we open the game archives? */
+ bool _openedArchives;
+
+ // Fonts
+ Font *_jeudak;
+ Font *_lettre;
+ Font *_plettre;
+ Font *_glettre;
+
+ /** The current palette. */
+ int _palette;
+
+ bool _quit; ///< Did the user request a normal game quit?
+
+ Difficulty _difficulty; ///< The current difficulty.
+ int _section; ///< The current game section.
+
+ Common::String _name; ///< The name of the child.
+
+ uint8 _house;
+
+ uint8 _head;
+ uint8 _colorHair;
+ uint8 _colorJacket;
+ uint8 _colorTrousers;
+
+
+ // -- General helpers --
+
+ void setGamePalette(uint palette); ///< Set a game palette.
+ void setGameCursor(); ///< Set the default game cursor.
+
+ /** Draw this sprite in a fancy, animated line-by-line way. */
+ void drawLineByLine(const Surface &src, int16 left, int16 top, int16 right, int16 bottom,
+ int16 x, int16 y) const;
+
+ /** Backup the screen contents. */
+ void backupScreen(ScreenBackup &backup, bool setDefaultCursor = false);
+ /** Restore the screen contents with a previously made backup. */
+ void restoreScreen(ScreenBackup &backup);
+
+ Common::String fixString(const Common::String &str) const; ///< Fix a string if necessary.
+ void fixTXTStrings(TXTFile &txt) const; ///< Fix all strings in a TXT.
+
+
+ // -- Copy protection helpers --
+
+ /** Set up the copy protection. */
+ int8 cpSetup(const uint8 colors[7], const uint8 shapes[7 * 20],
+ const uint8 obfuscate[4], const Surface sprites[2]);
+ /** Find the shape under these coordinates. */
+ int8 cpFindShape(int16 x, int16 y) const;
+ /** Display the "You are wrong" screen. */
+ void cpWrong();
+
+
+ // -- Show different game screens --
+
+ void showWait(uint palette = 0xFFFF); ///< Show the wait / loading screen.
+ void showQuote(); ///< Show the quote about fairytales.
+ void showTitle(); ///< Show the Once Upon A Time title.
+ void showChapter(int chapter); ///< Show a chapter intro text.
+ void showByeBye(); ///< Show the "bye bye" screen.
+
+ /** Handle the "listen to animal names" part. */
+ void handleAnimalNames(uint count, const MenuButton *buttons, const char * const *names);
+
+
+ // -- Menu helpers --
+
+ MenuAction handleStartMenu(const MenuButton *animalsButton); ///< Handle the start menu.
+ MenuAction handleMainMenu(); ///< Handle the main menu.
+ MenuAction handleIngameMenu(); ///< Handle the ingame menu.
+
+ void drawStartMenu(const MenuButton *animalsButton); ///< Draw the start menu.
+ void drawMainMenu(); ///< Draw the main menu.
+ void drawIngameMenu(); ///< Draw the ingame menu.
+
+ /** Draw the difficulty label. */
+ void drawMenuDifficulty();
+
+ /** Clear the ingame menu in an animated way. */
+ void clearIngameMenu(const Surface &background);
+
+ /** Handle the whole ingame menu. */
+ MenuAction doIngameMenu();
+ /** Handle the whole ingame menu if ESC or right mouse button was pressed. */
+ MenuAction doIngameMenu(int16 &key, MouseButtons &mouseButtons);
+
+
+ // -- Menu button helpers --
+
+ /** Find the button under these coordinates. */
+ int checkButton(const MenuButton *buttons, uint count, int16 x, int16 y, int failValue = -1) const;
+
+ /** Draw a menu button. */
+ void drawButton (Surface &dest, const Surface &src, const MenuButton &button, int transp = -1) const;
+ /** Draw multiple menu buttons. */
+ void drawButtons(Surface &dest, const Surface &src, const MenuButton *buttons, uint count, int transp = -1) const;
+
+ /** Draw a border around a button. */
+ void drawButtonBorder(const MenuButton &button, uint8 color);
+
+
+ // -- Animal names helpers --
+
+ /** Set up the animal chooser. */
+ void anSetupChooser();
+ /** Set up the language chooser for one animal. */
+ void anSetupNames(const MenuButton &animal);
+ /** Play / Display the name of an animal in one language. */
+ void anPlayAnimalName(const Common::String &animal, uint language);
+
+
+ // -- Game sections --
+
+ bool playSection();
+
+ bool sectionStork();
+ bool sectionChapter1();
+ bool sectionParents();
+ bool sectionChapter2();
+ bool sectionForest0();
+ bool sectionChapter3();
+ bool sectionEvilCastle();
+ bool sectionChapter4();
+ bool sectionForest1();
+ bool sectionChapter5();
+ bool sectionBossFight();
+ bool sectionChapter6();
+ bool sectionForest2();
+ bool sectionChapter7();
+ bool sectionEnd();
+
+ CharGenAction characterGenerator();
+ void charGenSetup(uint stage);
+ void charGenDrawName();
+
+ static bool enterString(Common::String &name, int16 key, uint maxLength, const Font &font);
+};
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_ONCEUPON_ONCEUPON_H
diff --git a/engines/gob/pregob/onceupon/palettes.h b/engines/gob/pregob/onceupon/palettes.h
new file mode 100644
index 0000000000..952581041c
--- /dev/null
+++ b/engines/gob/pregob/onceupon/palettes.h
@@ -0,0 +1,411 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_PALETTES_H
+#define GOB_PREGOB_ONCEUPON_PALETTES_H
+
+static const int kPaletteSize = 16;
+static const uint kPaletteCount = 20;
+
+static const byte kCopyProtectionPalette[3 * kPaletteSize] = {
+ 0x00, 0x00, 0x00,
+ 0x19, 0x00, 0x19,
+ 0x00, 0x3F, 0x00,
+ 0x00, 0x2A, 0x2A,
+ 0x2A, 0x00, 0x00,
+ 0x2A, 0x00, 0x2A,
+ 0x2A, 0x15, 0x00,
+ 0x00, 0x19, 0x12,
+ 0x00, 0x00, 0x00,
+ 0x15, 0x15, 0x3F,
+ 0x15, 0x3F, 0x15,
+ 0x00, 0x20, 0x3F,
+ 0x3F, 0x00, 0x00,
+ 0x3F, 0x00, 0x20,
+ 0x3F, 0x3F, 0x00,
+ 0x3F, 0x3F, 0x3F
+};
+
+static const byte kGamePalettes[kPaletteCount][3 * kPaletteSize] = {
+ {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x18,
+ 0x00, 0x00, 0x3C,
+ 0x1C, 0x28, 0x00,
+ 0x10, 0x18, 0x00,
+ 0x1C, 0x1C, 0x20,
+ 0x14, 0x14, 0x14,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x14, 0x20, 0x04,
+ 0x3C, 0x2C, 0x00,
+ 0x02, 0x00, 0x18,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x38, 0x20, 0x3C,
+ 0x2C, 0x10, 0x30,
+ 0x20, 0x08, 0x28,
+ 0x14, 0x00, 0x1C,
+ 0x20, 0x20, 0x38,
+ 0x18, 0x18, 0x2C,
+ 0x10, 0x10, 0x24,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x20, 0x20,
+ 0x24, 0x14, 0x14,
+ 0x1C, 0x10, 0x10,
+ 0x14, 0x0C, 0x0C,
+ 0x1C, 0x1C, 0x1C,
+ 0x18, 0x18, 0x18,
+ 0x10, 0x10, 0x10,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x10, 0x28, 0x1C,
+ 0x10, 0x1C, 0x10,
+ 0x10, 0x14, 0x0C,
+ 0x1C, 0x1C, 0x3C,
+ 0x24, 0x24, 0x3C,
+ 0x18, 0x18, 0x24,
+ 0x10, 0x10, 0x18,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x3F, 0x26, 0x3F,
+ 0x36, 0x1C, 0x36,
+ 0x2C, 0x12, 0x2A,
+ 0x27, 0x0C, 0x24,
+ 0x22, 0x07, 0x1E,
+ 0x1D, 0x03, 0x18,
+ 0x16, 0x00, 0x10,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3A,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x3F, 0x39, 0x26,
+ 0x38, 0x34, 0x1C,
+ 0x30, 0x2F, 0x13,
+ 0x27, 0x29, 0x0C,
+ 0x1D, 0x22, 0x07,
+ 0x14, 0x1B, 0x03,
+ 0x0C, 0x14, 0x00,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3A,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x24, 0x3C, 0x3C,
+ 0x1C, 0x34, 0x38,
+ 0x14, 0x2C, 0x30,
+ 0x0C, 0x20, 0x2C,
+ 0x08, 0x18, 0x28,
+ 0x04, 0x10, 0x20,
+ 0x00, 0x08, 0x1C,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x38,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x24,
+ 0x38, 0x24, 0x1C,
+ 0x30, 0x1C, 0x14,
+ 0x28, 0x18, 0x0C,
+ 0x20, 0x10, 0x04,
+ 0x1C, 0x0C, 0x00,
+ 0x14, 0x08, 0x00,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x38,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x34, 0x24,
+ 0x38, 0x2C, 0x1C,
+ 0x30, 0x24, 0x14,
+ 0x2C, 0x1C, 0x10,
+ 0x30, 0x30, 0x3C,
+ 0x1C, 0x1C, 0x38,
+ 0x0C, 0x0C, 0x38,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0C,
+ 0x02, 0x03, 0x14,
+ 0x07, 0x07, 0x1D,
+ 0x0E, 0x0E, 0x25,
+ 0x17, 0x17, 0x2E,
+ 0x21, 0x22, 0x36,
+ 0x2F, 0x2F, 0x3F,
+ 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3B, 0x0D,
+ 0x3A, 0x31, 0x0A,
+ 0x35, 0x28, 0x07,
+ 0x30, 0x21, 0x04,
+ 0x2B, 0x19, 0x02,
+ 0x26, 0x12, 0x01,
+ 0x16, 0x0B, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00,
+ 0x21, 0x01, 0x00,
+ 0x2A, 0x02, 0x00,
+ 0x33, 0x03, 0x00,
+ 0x3D, 0x06, 0x00,
+ 0x2A, 0x19, 0x05,
+ 0x15, 0x14, 0x14,
+ 0x22, 0x1F, 0x1E,
+ 0x2F, 0x2C, 0x28,
+ 0x3F, 0x3C, 0x29,
+ 0x3F, 0x38, 0x0B,
+ 0x3B, 0x30, 0x0A,
+ 0x37, 0x29, 0x08,
+ 0x33, 0x23, 0x07,
+ 0x2F, 0x1D, 0x06
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x38,
+ 0x34, 0x30, 0x28,
+ 0x2C, 0x24, 0x1C,
+ 0x24, 0x18, 0x10,
+ 0x1C, 0x10, 0x08,
+ 0x14, 0x04, 0x04,
+ 0x10, 0x00, 0x00,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x38,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x38,
+ 0x34, 0x30, 0x28,
+ 0x2C, 0x24, 0x1C,
+ 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x38,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x1A, 0x30, 0x37,
+ 0x14, 0x28, 0x31,
+ 0x10, 0x20, 0x2C,
+ 0x0C, 0x19, 0x27,
+ 0x08, 0x12, 0x21,
+ 0x05, 0x0C, 0x1C,
+ 0x03, 0x07, 0x16,
+ 0x01, 0x03, 0x11,
+ 0x00, 0x00, 0x0C,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x34, 0x30, 0x34,
+ 0x30, 0x24, 0x30,
+ 0x28, 0x1C, 0x28,
+ 0x24, 0x14, 0x24,
+ 0x1C, 0x0C, 0x1C,
+ 0x18, 0x08, 0x18,
+ 0x14, 0x04, 0x14,
+ 0x0C, 0x04, 0x0C,
+ 0x08, 0x00, 0x08,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x2C, 0x24, 0x0C,
+ 0x34, 0x34, 0x28,
+ 0x2C, 0x2C, 0x1C,
+ 0x24, 0x24, 0x10,
+ 0x1C, 0x18, 0x08,
+ 0x14, 0x14, 0x08,
+ 0x10, 0x10, 0x04,
+ 0x0C, 0x0C, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x38,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+ 0x14, 0x28, 0x31,
+ 0x10, 0x20, 0x2C,
+ 0x0C, 0x19, 0x27,
+ 0x08, 0x12, 0x21,
+ 0x05, 0x0C, 0x1C,
+ 0x03, 0x07, 0x16,
+ 0x01, 0x03, 0x11,
+ 0x00, 0x3C, 0x00,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x10, 0x28, 0x1C,
+ 0x10, 0x1C, 0x10,
+ 0x10, 0x14, 0x0C,
+ 0x1C, 0x1C, 0x3C,
+ 0x24, 0x24, 0x3C,
+ 0x18, 0x18, 0x24,
+ 0x10, 0x10, 0x18,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ },
+ {
+ 0x00, 0x00, 0x00,
+ 0x10, 0x28, 0x1C,
+ 0x10, 0x1C, 0x10,
+ 0x10, 0x14, 0x0C,
+ 0x1C, 0x1C, 0x3C,
+ 0x24, 0x24, 0x3C,
+ 0x18, 0x18, 0x24,
+ 0x10, 0x10, 0x18,
+ 0x14, 0x20, 0x04,
+ 0x00, 0x00, 0x24,
+ 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00,
+ 0x3C, 0x2C, 0x00,
+ 0x3C, 0x18, 0x00,
+ 0x3C, 0x04, 0x00,
+ 0x1C, 0x00, 0x00
+ }
+};
+
+#endif // GOB_PREGOB_ONCEUPON_PALETTES_H
diff --git a/engines/gob/pregob/onceupon/parents.cpp b/engines/gob/pregob/onceupon/parents.cpp
new file mode 100644
index 0000000000..cdaee6a38d
--- /dev/null
+++ b/engines/gob/pregob/onceupon/parents.cpp
@@ -0,0 +1,217 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/gob.h"
+#include "gob/global.h"
+#include "gob/dataio.h"
+#include "gob/palanim.h"
+#include "gob/draw.h"
+#include "gob/video.h"
+
+#include "gob/sound/sound.h"
+
+#include "gob/pregob/gctfile.h"
+
+#include "gob/pregob/onceupon/palettes.h"
+#include "gob/pregob/onceupon/parents.h"
+
+namespace Gob {
+
+namespace OnceUpon {
+
+const char *Parents::kSound[kSoundCount] = {
+ "rire.snd", // kSoundCackle
+ "tonn.snd" // kSoundThunder
+};
+
+// So that every GCT line is displayed for 12 seconds
+const uint16 Parents::kLoop[kLoopCount][3] = {
+ { 72, 77, 33},
+ {105, 109, 38},
+ {141, 145, 38},
+ {446, 454, 23},
+ {456, 464, 23},
+ {466, 474, 23},
+ {476, 484, 23}
+};
+
+
+Parents::Parents(GobEngine *vm, const Common::String &seq, const Common::String &gct,
+ const Common::String &childName, uint8 house, const Font &font,
+ const byte *normalPalette, const byte *brightPalette, uint paletteSize) :
+ SEQFile(vm, seq),
+ _gct(0), _house(house), _font(&font),
+ _paletteSize(paletteSize), _normalPalette(normalPalette), _brightPalette(brightPalette) {
+
+ // Load sounds
+ for (int i = 0; i < kSoundCount; i++)
+ _vm->_sound->sampleLoad(&_sounds[i], SOUND_SND, kSound[i]);
+
+ // Load GCT
+ Common::SeekableReadStream *gctStream = _vm->_dataIO->getFile(gct);
+ if (gctStream) {
+ _gct = new GCTFile(*gctStream, _vm->_rnd);
+
+ delete gctStream;
+ } else
+ error("Parents::Parents(): Failed to open \"%s\"", gct.c_str());
+
+ _gct->setArea(17, 18, 303, 41);
+ _gct->setText(1, childName);
+
+ _gct->selectLine(2, _house);
+ _gct->selectLine(4, _house);
+
+ for (uint i = 0; i < kLoopCount; i++)
+ _loopID[i] = addLoop(kLoop[i][0], kLoop[i][1], kLoop[i][2]);
+}
+
+Parents::~Parents() {
+ delete _gct;
+}
+
+void Parents::play() {
+ _currentLoop = 0;
+
+ SEQFile::play(true, 496, 15);
+
+ // After playback, fade out
+ if (!_vm->shouldQuit())
+ _vm->_palAnim->fade(0, 0, 0);
+}
+
+void Parents::handleFrameEvent() {
+ switch (getFrame()) {
+ case 0:
+ // On fame 0, fade in
+ _vm->_draw->forceBlit();
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
+ break;
+
+ case 4:
+ drawGCT(0);
+ break;
+
+ case 55:
+ drawGCT(3, 0);
+ break;
+
+ case 79:
+ drawGCT(_house + 5, 1);
+ break;
+
+ case 110:
+ drawGCT(_house + 9, 2);
+ break;
+
+ case 146:
+ drawGCT(17);
+ break;
+
+ case 198:
+ drawGCT(13);
+ break;
+
+ case 445:
+ drawGCT(14, 3);
+ break;
+
+ case 455:
+ drawGCT(18, 4);
+ break;
+
+ case 465:
+ drawGCT(19, 5);
+ break;
+
+ case 475:
+ drawGCT(20, 6);
+ break;
+
+ case 188:
+ case 228:
+ case 237:
+ case 257:
+ case 275:
+ case 426:
+ lightningEffect();
+ break;
+
+ case 203:
+ case 243:
+ case 252:
+ case 272:
+ case 290:
+ case 441:
+ playSound(kSoundThunder);
+ break;
+
+ case 340:
+ playSound(kSoundCackle);
+ break;
+ }
+}
+
+void Parents::handleInput(int16 key, int16 mouseX, int16 mouseY, MouseButtons mouseButtons) {
+ if ((key == kKeyEscape) || (mouseButtons == kMouseButtonsRight))
+ abortPlay();
+
+ if (((key == kKeySpace) || (mouseButtons == kMouseButtonsLeft)) && (_currentLoop < kLoopCount))
+ skipLoop(_loopID[_currentLoop]);
+}
+
+void Parents::playSound(Sound sound) {
+ _vm->_sound->blasterStop(0);
+ _vm->_sound->blasterPlay(&_sounds[sound], 0, 0);
+}
+
+void Parents::lightningEffect() {
+ for (int i = 0; (i < 5) && !_vm->shouldQuit(); i++) {
+
+ setPalette(_brightPalette, _paletteSize);
+ _vm->_util->delay(5);
+
+ setPalette(_normalPalette, _paletteSize);
+ _vm->_util->delay(5);
+ }
+}
+
+void Parents::setPalette(const byte *palette, uint size) {
+ memcpy(_vm->_draw->_vgaPalette, palette, 3 * size);
+
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ _vm->_video->retrace();
+}
+
+void Parents::drawGCT(uint item, uint loop) {
+ int16 left, top, right, bottom;
+ if (_gct->clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ if (_gct->draw(*_vm->_draw->_backSurface, item, *_font, 10, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+
+ _currentLoop = loop;
+}
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/onceupon/parents.h b/engines/gob/pregob/onceupon/parents.h
new file mode 100644
index 0000000000..f5c8307b73
--- /dev/null
+++ b/engines/gob/pregob/onceupon/parents.h
@@ -0,0 +1,94 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_PARENTS_H
+#define GOB_PREGOB_ONCEUPON_PARENTS_H
+
+#include "gob/sound/sounddesc.h"
+
+#include "gob/pregob/seqfile.h"
+
+namespace Gob {
+
+class Font;
+
+class GCTFile;
+
+namespace OnceUpon {
+
+/** The home / parents animation sequence. */
+class Parents : public SEQFile {
+public:
+ Parents(GobEngine *vm, const Common::String &seq, const Common::String &gct,
+ const Common::String &childName, uint8 house, const Font &font,
+ const byte *normalPalette, const byte *brightPalette, uint paletteSize);
+ ~Parents();
+
+ void play();
+
+protected:
+ void handleFrameEvent();
+ void handleInput(int16 key, int16 mouseX, int16 mouseY, MouseButtons mouseButtons);
+
+private:
+ static const uint kLoopCount = 7;
+
+ static const uint16 kLoop[kLoopCount][3];
+
+ enum Sound {
+ kSoundCackle = 0,
+ kSoundThunder ,
+ kSoundCount
+ };
+
+ static const char *kSound[kSoundCount];
+
+
+ uint8 _house;
+
+ const Font *_font;
+
+ uint _paletteSize;
+ const byte *_normalPalette;
+ const byte *_brightPalette;
+
+ SoundDesc _sounds[kSoundCount];
+
+ GCTFile *_gct;
+
+ uint _loopID[kLoopCount];
+ uint _currentLoop;
+
+
+ void lightningEffect();
+
+ void playSound(Sound sound);
+ void setPalette(const byte *palette, uint size);
+
+ void drawGCT(uint item, uint loop = 0xFFFF);
+};
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_ONCEUPON_PARENTS_H
diff --git a/engines/gob/pregob/onceupon/stork.cpp b/engines/gob/pregob/onceupon/stork.cpp
new file mode 100644
index 0000000000..3c38037d08
--- /dev/null
+++ b/engines/gob/pregob/onceupon/stork.cpp
@@ -0,0 +1,234 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/str.h"
+
+#include "gob/gob.h"
+#include "gob/surface.h"
+#include "gob/anifile.h"
+#include "gob/video.h"
+
+#include "gob/pregob/onceupon/stork.h"
+
+enum Animation {
+ kAnimFlyNearWithBundle = 9,
+ kAnimFlyFarWithBundle = 12,
+ kAnimFlyNearWithoutBundle = 10,
+ kAnimFlyFarWithoutBundle = 13,
+ kAnimBundleNear = 11,
+ kAnimBundleFar = 14
+};
+
+namespace Gob {
+
+namespace OnceUpon {
+
+Stork::Stork(GobEngine *vm, const ANIFile &ani) : ANIObject(ani), _shouldDrop(false) {
+ _frame = new Surface(320, 200, 1);
+ vm->_video->drawPackedSprite("cadre.cmp", *_frame);
+
+ _bundle = new ANIObject(ani);
+
+ _bundle->setVisible(false);
+ _bundle->setPause(true);
+
+ setState(kStateFlyNearWithBundle, kAnimFlyNearWithBundle, -80);
+}
+
+Stork::~Stork() {
+ delete _frame;
+
+ delete _bundle;
+}
+
+bool Stork::hasBundleLanded() const {
+ if (!_shouldDrop || !_bundle->isVisible() || _bundle->isPaused())
+ return false;
+
+ int16 x, y, width, height;
+ _bundle->getFramePosition(x, y);
+ _bundle->getFrameSize(width, height);
+
+ return (y + height) >= _bundleDrop.landY;
+}
+
+void Stork::dropBundle(const BundleDrop &drop) {
+ if (_shouldDrop)
+ return;
+
+ _shouldDrop = true;
+ _bundleDrop = drop;
+}
+
+bool Stork::draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ left = 0x7FFF;
+ top = 0x7FFF;
+ right = 0x0000;
+ bottom = 0x0000;
+
+ bool drawn = ANIObject::draw(dest, left, top, right, bottom);
+ if (drawn) {
+ // Left frame edge
+ if (left <= 15)
+ dest.blit(*_frame, left, top, MIN<int16>(15, right), bottom, left, top);
+
+ // Right frame edge
+ if (right >= 304)
+ dest.blit(*_frame, MAX<int16>(304, left), top, right, bottom, MAX<int16>(304, left), top);
+ }
+
+ int16 bLeft, bTop, bRight, bBottom;
+ if (_bundle->draw(dest, bLeft, bTop, bRight, bBottom)) {
+ // Bottom frame edge
+ if (bBottom >= 188)
+ dest.blit(*_frame, bLeft, MAX<int16>(188, bTop), bRight, bBottom, bLeft, MAX<int16>(188, bTop));
+
+ left = MIN(left , bLeft );
+ top = MIN(top , bTop );
+ right = MAX(right , bRight );
+ bottom = MAX(bottom, bBottom);
+
+ drawn = true;
+ }
+
+ return drawn;
+}
+
+bool Stork::clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ left = 0x7FFF;
+ top = 0x7FFF;
+ right = 0x0000;
+ bottom = 0x0000;
+
+ bool cleared = _bundle->clear(dest, left, top, right, bottom);
+
+ int16 sLeft, sTop, sRight, sBottom;
+ if (ANIObject::clear(dest, sLeft, sTop, sRight, sBottom)) {
+ left = MIN(left , sLeft );
+ top = MIN(top , sTop );
+ right = MAX(right , sRight );
+ bottom = MAX(bottom, sBottom);
+
+ cleared = true;
+ }
+
+ return cleared;
+}
+
+void Stork::advance() {
+ _bundle->advance();
+
+ ANIObject::advance();
+
+ int16 curX, curY, curWidth, curHeight;
+ getFramePosition(curX, curY, 0);
+ getFrameSize(curWidth, curHeight, 0);
+
+ const int16 curRight = curX + curWidth - 1;
+
+ int16 nextX, nextY, nextWidth, nextHeight;
+ getFramePosition(nextX, nextY, 1);
+ getFrameSize(nextWidth, nextHeight, 1);
+
+ const int16 nextRight = nextX + nextWidth - 1;
+
+ switch (_state) {
+ case kStateFlyNearWithBundle:
+ if (curX >= 330)
+ setState(kStateFlyFarWithBundle, kAnimFlyFarWithBundle, 330);
+
+ if ((curRight <= _bundleDrop.dropX) &&
+ (nextRight >= _bundleDrop.dropX) && _shouldDrop && !_bundleDrop.dropWhileFar)
+ dropBundle(kStateFlyNearWithoutBundle, kAnimFlyNearWithoutBundle);
+
+ break;
+
+ case kStateFlyFarWithBundle:
+ if (curX <= -80)
+ setState(kStateFlyNearWithBundle, kAnimFlyNearWithBundle, -80);
+
+ if ((curX >= _bundleDrop.dropX) &&
+ (nextX <= _bundleDrop.dropX) && _shouldDrop && _bundleDrop.dropWhileFar)
+ dropBundle(kStateFlyFarWithoutBundle, kAnimFlyFarWithoutBundle);
+
+ break;
+
+ case kStateFlyNearWithoutBundle:
+ if (curX >= 330)
+ setState(kStateFlyFarWithoutBundle, kAnimFlyFarWithoutBundle, 330);
+ break;
+
+ case kStateFlyFarWithoutBundle:
+ if (curX <= -80)
+ setState(kStateFlyNearWithoutBundle, kAnimFlyNearWithoutBundle, -80);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Stork::dropBundle(State state, uint16 anim) {
+ setState(state, anim);
+
+ int16 x, y, width, height;
+ getFramePosition(x, y);
+ getFrameSize(width, height);
+
+ _bundle->setAnimation(_bundleDrop.anim);
+ _bundle->setPause(false);
+ _bundle->setVisible(true);
+
+ int16 bWidth, bHeight;
+ _bundle->getFrameSize(bWidth, bHeight);
+
+ // Drop position
+ x = _bundleDrop.dropX;
+ y = y + height - bHeight;
+
+ // If the stork is flying near (from left to right), drop the bundle at the right edge
+ if (!_bundleDrop.dropWhileFar)
+ x = x - bWidth;
+
+ _bundle->setPosition(x, y);
+}
+
+void Stork::setState(State state, uint16 anim) {
+ setAnimation(anim);
+ setVisible(true);
+ setPause(false);
+
+ _state = state;
+}
+
+void Stork::setState(State state, uint16 anim, int16 x) {
+ setState(state, anim);
+ setPosition();
+
+ int16 pX, pY;
+ getPosition(pX, pY);
+ setPosition( x, pY);
+}
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/onceupon/stork.h b/engines/gob/pregob/onceupon/stork.h
new file mode 100644
index 0000000000..756f5258c7
--- /dev/null
+++ b/engines/gob/pregob/onceupon/stork.h
@@ -0,0 +1,103 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_STORK_H
+#define GOB_PREGOB_ONCEUPON_STORK_H
+
+#include "common/system.h"
+
+#include "gob/aniobject.h"
+
+namespace Common {
+ class String;
+}
+
+namespace Gob {
+
+class GobEngine;
+
+class Surface;
+class ANIFile;
+
+namespace OnceUpon {
+
+/** The stork in Baba Yaga / dragon in Abracadabra. */
+class Stork : public ANIObject {
+public:
+ /** Information on how to drop the bundle. */
+ struct BundleDrop {
+ int16 anim; ///< Animation of the bundle floating down
+
+ int16 dropX; ///< X position the stork drops the bundle
+ int16 landY; ///< Y position the bundle lands
+
+ bool dropWhileFar; ///< Does the stork drop the bundle while far instead of near?
+ };
+
+ Stork(GobEngine *vm, const ANIFile &ani);
+ ~Stork();
+
+ /** Has the bundle landed? */
+ bool hasBundleLanded() const;
+
+ /** Drop the bundle. */
+ void dropBundle(const BundleDrop &drop);
+
+ /** Draw the current frame onto the surface and return the affected rectangle. */
+ bool draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+ /** Draw the current frame from the surface and return the affected rectangle. */
+ bool clear(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+
+ /** Advance the animation to the next frame. */
+ void advance();
+
+private:
+ enum State {
+ kStateFlyNearWithBundle = 0,
+ kStateFlyFarWithBundle ,
+ kStateFlyNearWithoutBundle ,
+ kStateFlyFarWithoutBundle
+ };
+
+
+ GobEngine *_vm;
+
+ Surface *_frame;
+ ANIObject *_bundle;
+
+ State _state;
+
+ bool _shouldDrop;
+ BundleDrop _bundleDrop;
+
+
+ void setState(State state, uint16 anim);
+ void setState(State state, uint16 anim, int16 x);
+
+ void dropBundle(State state, uint16 anim);
+};
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_ONCEUPON_STORK_H
diff --git a/engines/gob/pregob/onceupon/title.cpp b/engines/gob/pregob/onceupon/title.cpp
new file mode 100644
index 0000000000..5163ff6822
--- /dev/null
+++ b/engines/gob/pregob/onceupon/title.cpp
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/gob.h"
+#include "gob/global.h"
+#include "gob/palanim.h"
+#include "gob/draw.h"
+
+#include "gob/sound/sound.h"
+
+#include "gob/pregob/onceupon/title.h"
+
+namespace Gob {
+
+namespace OnceUpon {
+
+Title::Title(GobEngine *vm) : SEQFile(vm, "ville.seq") {
+}
+
+Title::~Title() {
+}
+
+void Title::play() {
+ SEQFile::play(true, 0xFFFF, 15);
+
+ // After playback, fade out and stop the music
+ if (!_vm->shouldQuit())
+ _vm->_palAnim->fade(0, 0, 0);
+
+ stopMusic();
+}
+
+void Title::handleFrameEvent() {
+ // On fame 0, start the music and fade in
+ if (getFrame() == 0) {
+ playMusic();
+
+ _vm->_draw->forceBlit();
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
+ }
+}
+
+void Title::playMusic() {
+ // Look at what platform this is and play the appropriate music type
+
+ if (_vm->getPlatform() == Common::kPlatformPC)
+ playMusicDOS();
+ else if (_vm->getPlatform() == Common::kPlatformAmiga)
+ playMusicAmiga();
+ else if (_vm->getPlatform() == Common::kPlatformAtariST)
+ playMusicAtariST();
+}
+
+void Title::playMusicDOS() {
+ // Play an AdLib track
+
+ _vm->_sound->adlibLoadTBR("babayaga.tbr");
+ _vm->_sound->adlibLoadMDY("babayaga.mdy");
+ _vm->_sound->adlibSetRepeating(-1);
+ _vm->_sound->adlibPlay();
+}
+
+void Title::playMusicAmiga() {
+ // Play a Protracker track
+
+ _vm->_sound->protrackerPlay("mod.babayaga");
+}
+
+void Title::playMusicAtariST() {
+ // Play a Soundblaster composition
+
+ static const int16 titleMusic[21] = { 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, -1};
+ static const char * const titleFiles[ 3] = {"baba1.snd", "baba2.snd", "baba3.snd"};
+
+ for (uint i = 0; i < ARRAYSIZE(titleFiles); i++)
+ _vm->_sound->sampleLoad(_vm->_sound->sampleGetBySlot(i), SOUND_SND, titleFiles[i]);
+
+ _vm->_sound->blasterPlayComposition(titleMusic, 0);
+ _vm->_sound->blasterRepeatComposition(-1);
+}
+
+void Title::stopMusic() {
+ // Just stop everything
+
+ _vm->_sound->adlibSetRepeating(0);
+ _vm->_sound->blasterRepeatComposition(0);
+
+ _vm->_sound->adlibStop();
+ _vm->_sound->blasterStopComposition();
+ _vm->_sound->protrackerStop();
+
+ for (int i = 0; i < ::Gob::Sound::kSoundsCount; i++)
+ _vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(i));
+}
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/onceupon/title.h b/engines/gob/pregob/onceupon/title.h
new file mode 100644
index 0000000000..5e7ef76d40
--- /dev/null
+++ b/engines/gob/pregob/onceupon/title.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_ONCEUPON_TITLE_H
+#define GOB_PREGOB_ONCEUPON_TITLE_H
+
+#include "gob/pregob/seqfile.h"
+
+namespace Gob {
+
+namespace OnceUpon {
+
+/** The Once Upon A Time title animation sequence. */
+class Title : public SEQFile {
+public:
+ Title(GobEngine *vm);
+ ~Title();
+
+ void play();
+
+protected:
+ void handleFrameEvent();
+
+private:
+ void playMusic(); ///< Play the title music.
+ void playMusicDOS(); ///< Play the title music of the DOS version.
+ void playMusicAmiga(); ///< Play the title music of the Amiga version.
+ void playMusicAtariST(); ///< Play the title music of the Atari ST version.
+ void stopMusic(); ///< Stop the title music.
+};
+
+} // End of namespace OnceUpon
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_ONCEUPON_TITLE_H
diff --git a/engines/gob/pregob/pregob.cpp b/engines/gob/pregob/pregob.cpp
new file mode 100644
index 0000000000..54eb3c6795
--- /dev/null
+++ b/engines/gob/pregob/pregob.cpp
@@ -0,0 +1,351 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "graphics/cursorman.h"
+
+#include "gob/gob.h"
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/surface.h"
+#include "gob/dataio.h"
+#include "gob/palanim.h"
+#include "gob/draw.h"
+#include "gob/video.h"
+#include "gob/aniobject.h"
+
+#include "gob/sound/sound.h"
+
+#include "gob/pregob/pregob.h"
+#include "gob/pregob/gctfile.h"
+
+
+namespace Gob {
+
+const char PreGob::kLanguageSuffixShort[5] = { 't', 'g', 'a', 'e', 'i'};
+const char *PreGob::kLanguageSuffixLong [5] = {"fr", "al", "an", "it", "es"};
+
+
+PreGob::PreGob(GobEngine *vm) : _vm(vm), _fadedOut(false) {
+}
+
+PreGob::~PreGob() {
+}
+
+void PreGob::fadeOut() {
+ if (_fadedOut || _vm->shouldQuit())
+ return;
+
+ // Fade to black
+ _vm->_palAnim->fade(0, 0, 0);
+
+ _fadedOut = true;
+}
+
+void PreGob::fadeIn() {
+ if (!_fadedOut || _vm->shouldQuit())
+ return;
+
+ // Fade to palette
+ _vm->_draw->blitInvalidated();
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
+
+ _fadedOut = false;
+}
+
+void PreGob::clearScreen() {
+ _vm->_draw->_backSurface->clear();
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
+ _vm->_draw->blitInvalidated();
+ _vm->_video->retrace();
+}
+
+void PreGob::initScreen() {
+ _vm->_util->setFrameRate(15);
+
+ _fadedOut = true;
+
+ _vm->_draw->initScreen();
+
+ _vm->_draw->_backSurface->clear();
+ _vm->_util->clearPalette();
+
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+
+ _vm->_util->processInput();
+}
+
+void PreGob::setPalette(const byte *palette, uint16 size) {
+ memcpy(_vm->_draw->_vgaPalette, palette, 3 * size);
+
+ // If we didn't fade out prior, immediately set the palette
+ if (!_fadedOut)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+}
+
+void PreGob::addCursor() {
+ CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
+}
+
+void PreGob::removeCursor() {
+ CursorMan.popCursor();
+}
+
+void PreGob::setCursor(Surface &sprite, int16 hotspotX, int16 hotspotY) {
+ CursorMan.replaceCursor(sprite.getData(), sprite.getWidth(), sprite.getHeight(), hotspotX, hotspotY, 0);
+}
+
+void PreGob::setCursor(Surface &sprite, int16 left, int16 top, int16 right, int16 bottom,
+ int16 hotspotX, int16 hotspotY) {
+
+ const int width = right - left + 1;
+ const int height = bottom - top + 1;
+
+ if ((width <= 0) || (height <= 0))
+ return;
+
+ Surface cursor(width, height, 1);
+
+ cursor.blit(sprite, left, top, right, bottom, 0, 0);
+
+ setCursor(cursor, hotspotX, hotspotX);
+}
+
+void PreGob::showCursor() {
+ CursorMan.showMouse(true);
+
+ _vm->_draw->_showCursor = 4;
+}
+
+void PreGob::hideCursor() {
+ CursorMan.showMouse(false);
+
+ _vm->_draw->_showCursor = 0;
+}
+
+bool PreGob::isCursorVisible() const {
+ return CursorMan.isVisible();
+}
+
+void PreGob::loadSounds(const char * const *sounds, uint soundCount) {
+ freeSounds();
+
+ _sounds.resize(soundCount);
+
+ for (uint i = 0; i < soundCount; i++)
+ loadSound(_sounds[i], sounds[i]);
+}
+
+void PreGob::freeSounds() {
+ _sounds.clear();
+}
+
+bool PreGob::loadSound(SoundDesc &sound, const Common::String &file) const {
+ return _vm->_sound->sampleLoad(&sound, SOUND_SND, file.c_str());
+}
+
+void PreGob::playSound(uint sound, int16 frequency, int16 repCount) {
+ if (sound >= _sounds.size())
+ return;
+
+ _vm->_sound->blasterPlay(&_sounds[sound], repCount, frequency);
+}
+
+void PreGob::stopSound() {
+ _vm->_sound->blasterStop(0);
+}
+
+void PreGob::playSoundFile(const Common::String &file, int16 frequency, int16 repCount, bool interruptible) {
+ stopSound();
+
+ SoundDesc sound;
+ if (!loadSound(sound, file))
+ return;
+
+ _vm->_sound->blasterPlay(&sound, repCount, frequency);
+
+ _vm->_util->forceMouseUp();
+
+ bool finished = false;
+ while (!_vm->shouldQuit() && !finished && _vm->_sound->blasterPlayingSound()) {
+ endFrame(true);
+
+ finished = hasInput();
+ }
+
+ _vm->_util->forceMouseUp();
+
+ stopSound();
+}
+
+void PreGob::beep(int16 frequency, int32 length) {
+ _vm->_sound->speakerOn(frequency, length);
+}
+
+void PreGob::endFrame(bool doInput) {
+ _vm->_draw->blitInvalidated();
+ _vm->_util->waitEndFrame();
+
+ if (doInput)
+ _vm->_util->processInput();
+}
+
+int16 PreGob::checkInput(int16 &mouseX, int16 &mouseY, MouseButtons &mouseButtons) {
+ _vm->_util->getMouseState(&mouseX, &mouseY, &mouseButtons);
+ _vm->_util->forceMouseUp();
+
+ return _vm->_util->checkKey();
+}
+
+int16 PreGob::waitInput(int16 &mouseX, int16 &mouseY, MouseButtons &mouseButtons) {
+ bool finished = false;
+
+ int16 key = 0;
+ while (!_vm->shouldQuit() && !finished) {
+ endFrame(true);
+
+ key = checkInput(mouseX, mouseY, mouseButtons);
+
+ finished = (mouseButtons != kMouseButtonsNone) || (key != 0);
+ }
+
+ return key;
+}
+
+int16 PreGob::waitInput() {
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ return waitInput(mouseX, mouseY, mouseButtons);
+}
+
+bool PreGob::hasInput() {
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ return checkInput(mouseX, mouseY, mouseButtons) || (mouseButtons != kMouseButtonsNone);
+}
+
+void PreGob::clearAnim(ANIObject &anim) {
+ int16 left, top, right, bottom;
+
+ if (anim.clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+}
+
+void PreGob::drawAnim(ANIObject &anim) {
+ int16 left, top, right, bottom;
+
+ if (anim.draw(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ anim.advance();
+}
+
+void PreGob::redrawAnim(ANIObject &anim) {
+ clearAnim(anim);
+ drawAnim(anim);
+}
+
+void PreGob::clearAnim(const ANIList &anims) {
+ for (int i = (anims.size() - 1); i >= 0; i--)
+ clearAnim(*anims[i]);
+}
+
+void PreGob::drawAnim(const ANIList &anims) {
+ for (ANIList::const_iterator a = anims.begin(); a != anims.end(); ++a)
+ drawAnim(**a);
+}
+
+void PreGob::redrawAnim(const ANIList &anims) {
+ clearAnim(anims);
+ drawAnim(anims);
+}
+
+void PreGob::loadAnims(ANIList &anims, ANIFile &ani, uint count, const AnimProperties *props) const {
+ freeAnims(anims);
+
+ anims.resize(count);
+ for (uint i = 0; i < count; i++) {
+ anims[i] = new ANIObject(ani);
+
+ setAnim(*anims[i], props[i]);
+ }
+}
+
+void PreGob::freeAnims(ANIList &anims) const {
+ for (ANIList::iterator a = anims.begin(); a != anims.end(); ++a)
+ delete *a;
+
+ anims.clear();
+}
+
+void PreGob::setAnim(ANIObject &anim, const AnimProperties &props) const {
+ anim.setAnimation(props.animation);
+ anim.setFrame(props.frame);
+ anim.setMode(props.mode);
+ anim.setPause(props.paused);
+ anim.setVisible(props.visible);
+
+ if (props.hasPosition)
+ anim.setPosition(props.x, props.y);
+ else
+ anim.setPosition();
+}
+
+Common::String PreGob::getLocFile(const Common::String &file) const {
+ if (_vm->_global->_language >= ARRAYSIZE(kLanguageSuffixShort))
+ return file;
+
+ return file + kLanguageSuffixShort[_vm->_global->_language];
+}
+
+TXTFile *PreGob::loadTXT(const Common::String &txtFile, TXTFile::Format format) const {
+ Common::SeekableReadStream *txtStream = _vm->_dataIO->getFile(txtFile);
+ if (!txtStream)
+ error("PreGob::loadTXT(): Failed to open \"%s\"", txtFile.c_str());
+
+ TXTFile *txt = new TXTFile(*txtStream, format);
+
+ delete txtStream;
+
+ fixTXTStrings(*txt);
+
+ return txt;
+}
+
+void PreGob::fixTXTStrings(TXTFile &txt) const {
+}
+
+GCTFile *PreGob::loadGCT(const Common::String &gctFile) const {
+ Common::SeekableReadStream *gctStream = _vm->_dataIO->getFile(gctFile);
+ if (!gctStream)
+ error("PreGob::loadGCT(): Failed to open \"%s\"", gctFile.c_str());
+
+ GCTFile *gct = new GCTFile(*gctStream, _vm->_rnd);
+
+ delete gctStream;
+
+ return gct;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/pregob.h b/engines/gob/pregob/pregob.h
new file mode 100644
index 0000000000..632f85b88e
--- /dev/null
+++ b/engines/gob/pregob/pregob.h
@@ -0,0 +1,194 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_PREGOB_H
+#define GOB_PREGOB_PREGOB_H
+
+#include "common/str.h"
+#include "common/array.h"
+
+#include "gob/util.h"
+#include "gob/aniobject.h"
+
+#include "gob/sound/sounddesc.h"
+
+#include "gob/pregob/txtfile.h"
+
+namespace Gob {
+
+class GobEngine;
+class Surface;
+
+class GCTFile;
+
+class PreGob {
+public:
+ PreGob(GobEngine *vm);
+ virtual ~PreGob();
+
+ virtual void run() = 0;
+
+ struct AnimProperties {
+ uint16 animation;
+ uint16 frame;
+
+ ANIObject::Mode mode;
+
+ bool visible;
+ bool paused;
+
+ bool hasPosition;
+ int16 x;
+ int16 y;
+ };
+
+protected:
+ typedef Common::Array<ANIObject *> ANIList;
+
+ static const char kLanguageSuffixShort[5];
+ static const char *kLanguageSuffixLong [5];
+
+
+ GobEngine *_vm;
+
+
+ // -- Graphics --
+
+ /** Initialize the game screen. */
+ void initScreen();
+
+ void fadeOut(); ///< Fade to black.
+ void fadeIn(); ///< Fade to the current palette.
+
+ void clearScreen();
+
+ /** Change the palette.
+ *
+ * @param palette The palette to change to.
+ * @param size Size of the palette in colors.
+ */
+ void setPalette(const byte *palette, uint16 size); ///< Change the palette
+
+ /** Add a new cursor that can be manipulated to the stack. */
+ void addCursor();
+ /** Remove the top-most cursor from the stack. */
+ void removeCursor();
+
+ /** Set the current cursor. */
+ void setCursor(Surface &sprite, int16 hotspotX, int16 hotspotY);
+ /** Set the current cursor. */
+ void setCursor(Surface &sprite, int16 left, int16 top, int16 right, int16 bottom,
+ int16 hotspotX, int16 hotspotY);
+
+ /** Show the cursor. */
+ void showCursor();
+ /** Hide the cursor. */
+ void hideCursor();
+
+ /** Is the cursor currently visible? */
+ bool isCursorVisible() const;
+
+ /** Remove an animation from the screen. */
+ void clearAnim(ANIObject &anim);
+ /** Draw an animation to the screen, advancing it. */
+ void drawAnim(ANIObject &anim);
+ /** Clear and draw an animation to the screen, advancing it. */
+ void redrawAnim(ANIObject &anim);
+
+ /** Remove animations from the screen. */
+ void clearAnim(const ANIList &anims);
+ /** Draw animations to the screen, advancing them. */
+ void drawAnim(const ANIList &anims);
+ /** Clear and draw animations to the screen, advancing them. */
+ void redrawAnim(const ANIList &anims);
+
+ void loadAnims(ANIList &anims, ANIFile &ani, uint count, const AnimProperties *props) const;
+ void freeAnims(ANIList &anims) const;
+
+ void setAnim(ANIObject &anim, const AnimProperties &props) const;
+
+ /** Wait for the frame to end, handling screen updates and optionally update input. */
+ void endFrame(bool doInput);
+
+
+ // -- Sound --
+
+ /** Load all sounds that can be played interactively in the game. */
+ void loadSounds(const char * const *sounds, uint soundCount);
+ /** Free all loaded sound. */
+ void freeSounds();
+
+ /** Play a loaded sound. */
+ void playSound(uint sound, int16 frequency = 0, int16 repCount = 0);
+ /** Stop all sound playback. */
+ void stopSound();
+
+ /** Play a sound until it ends or is interrupted by a keypress. */
+ void playSoundFile(const Common::String &file, int16 frequency = 0, int16 repCount = 0, bool interruptible = true);
+
+ /** Beep the PC speaker. */
+ void beep(int16 frequency, int32 length);
+
+
+ // -- Input --
+
+ /** Check mouse and keyboard input. */
+ int16 checkInput(int16 &mouseX, int16 &mouseY, MouseButtons &mouseButtons);
+ /** Wait for mouse or keyboard input. */
+ int16 waitInput (int16 &mouseX, int16 &mouseY, MouseButtons &mouseButtons);
+ /** Wait for mouse or keyboard input, but don't care about what was done with the mouse. */
+ int16 waitInput();
+ /** Did we have mouse or keyboard input? */
+ bool hasInput();
+
+
+ // -- TXT helpers --
+
+ /** Get the name of a localized file. */
+ Common::String getLocFile(const Common::String &file) const;
+ /** Open a TXT file. */
+ TXTFile *loadTXT(const Common::String &txtFile, TXTFile::Format format) const;
+
+ /** Called by loadTXT() to fix strings within the TXT file. */
+ virtual void fixTXTStrings(TXTFile &txt) const;
+
+
+ // -- GCT helpers --
+
+ GCTFile *loadGCT(const Common::String &gctFile) const;
+
+
+private:
+ /** Did we fade out? */
+ bool _fadedOut;
+
+ /** All loaded sounds. */
+ Common::Array<SoundDesc> _sounds;
+
+
+ /** Load a sound file. */
+ bool loadSound(SoundDesc &sound, const Common::String &file) const;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_PREGOB_H
diff --git a/engines/gob/pregob/seqfile.cpp b/engines/gob/pregob/seqfile.cpp
new file mode 100644
index 0000000000..91973bbb85
--- /dev/null
+++ b/engines/gob/pregob/seqfile.cpp
@@ -0,0 +1,384 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/str.h"
+#include "common/stream.h"
+
+#include "gob/gob.h"
+#include "gob/dataio.h"
+#include "gob/draw.h"
+#include "gob/decfile.h"
+#include "gob/anifile.h"
+#include "gob/aniobject.h"
+
+#include "gob/pregob/seqfile.h"
+
+namespace Gob {
+
+SEQFile::SEQFile(GobEngine *vm, const Common::String &fileName) : _vm(vm) {
+ for (uint i = 0; i < kObjectCount; i++)
+ _objects[i].object = 0;
+
+ Common::SeekableReadStream *seq = _vm->_dataIO->getFile(Util::setExtension(fileName, ".SEQ"));
+ if (!seq) {
+ warning("SEQFile::SEQFile(): No such file \"%s\"", fileName.c_str());
+ return;
+ }
+
+ load(*seq);
+
+ delete seq;
+}
+
+SEQFile::~SEQFile() {
+ for (uint i = 0; i < kObjectCount; i++)
+ delete _objects[i].object;
+
+ for (Backgrounds::iterator b = _backgrounds.begin(); b != _backgrounds.end(); ++b)
+ delete *b;
+
+ for (Animations::iterator a = _animations.begin(); a != _animations.end(); ++a)
+ delete *a;
+}
+
+void SEQFile::load(Common::SeekableReadStream &seq) {
+ const uint16 decCount = (uint16)seq.readByte() + 1;
+ const uint16 aniCount = (uint16)seq.readByte() + 1;
+
+ // Load backgrounds
+ _backgrounds.reserve(decCount);
+ for (uint i = 0; i < decCount; i++) {
+ const Common::String dec = Util::readString(seq, 13);
+
+ if (!_vm->_dataIO->hasFile(dec)) {
+ warning("SEQFile::load(): No such background \"%s\"", dec.c_str());
+ return;
+ }
+
+ _backgrounds.push_back(new DECFile(_vm, dec, 320, 200));
+ }
+
+ // Load animations
+ _animations.reserve(aniCount);
+ for (uint i = 0; i < aniCount; i++) {
+ const Common::String ani = Util::readString(seq, 13);
+
+ if (!_vm->_dataIO->hasFile(ani)) {
+ warning("SEQFile::load(): No such animation \"%s\"", ani.c_str());
+ return;
+ }
+
+ _animations.push_back(new ANIFile(_vm, ani));
+ }
+
+ _frameRate = seq.readUint16LE();
+
+ // Load background change keys
+
+ const uint16 bgKeyCount = seq.readUint16LE();
+ _bgKeys.resize(bgKeyCount);
+
+ for (uint16 i = 0; i < bgKeyCount; i++) {
+ const uint16 frame = seq.readUint16LE();
+ const uint16 index = seq.readUint16LE();
+
+ _bgKeys[i].frame = frame;
+ _bgKeys[i].background = index < _backgrounds.size() ? _backgrounds[index] : 0;
+ }
+
+ // Load animation keys for all 4 objects
+
+ for (uint i = 0; i < kObjectCount; i++) {
+ const uint16 animKeyCount = seq.readUint16LE();
+ _animKeys.reserve(_animKeys.size() + animKeyCount);
+
+ for (uint16 j = 0; j < animKeyCount; j++) {
+ _animKeys.push_back(AnimationKey());
+
+ const uint16 frame = seq.readUint16LE();
+ const uint16 index = seq.readUint16LE();
+
+ uint16 animation;
+ const ANIFile *ani = findANI(index, animation);
+
+ _animKeys.back().object = i;
+ _animKeys.back().frame = frame;
+ _animKeys.back().ani = ani;
+ _animKeys.back().animation = animation;
+ _animKeys.back().x = seq.readSint16LE();
+ _animKeys.back().y = seq.readSint16LE();
+ _animKeys.back().order = seq.readSint16LE();
+ }
+ }
+
+}
+
+const ANIFile *SEQFile::findANI(uint16 index, uint16 &animation) {
+ animation = 0xFFFF;
+
+ // 0xFFFF = remove animation
+ if (index == 0xFFFF)
+ return 0;
+
+ for (Animations::const_iterator a = _animations.begin(); a != _animations.end(); ++a) {
+ if (index < (*a)->getAnimationCount()) {
+ animation = index;
+ return *a;
+ }
+
+ index -= (*a)->getAnimationCount();
+ }
+
+ return 0;
+}
+
+void SEQFile::play(bool abortable, uint16 endFrame, uint16 frameRate) {
+ if (_bgKeys.empty() && _animKeys.empty())
+ // Nothing to do
+ return;
+
+ // Init
+
+ _frame = 0;
+ _abortPlay = false;
+
+ for (uint i = 0; i < kObjectCount; i++) {
+ delete _objects[i].object;
+
+ _objects[i].object = 0;
+ _objects[i].order = 0;
+ }
+
+ for (Loops::iterator l = _loops.begin(); l != _loops.end(); ++l)
+ l->currentLoop = 0;
+
+ // Set the frame rate
+
+ int16 frameRateBack = _vm->_util->getFrameRate();
+
+ if (frameRate == 0)
+ frameRate = _frameRate;
+
+ _vm->_util->setFrameRate(frameRate);
+
+ _abortable = abortable;
+
+ while (!_vm->shouldQuit() && !_abortPlay) {
+ // Handle the frame contents
+ playFrame();
+
+ // Handle extra frame events
+ handleFrameEvent();
+
+ // Wait for the frame to end
+ _vm->_draw->blitInvalidated();
+ _vm->_util->waitEndFrame();
+
+ // Handle input
+
+ _vm->_util->processInput();
+
+ int16 key = _vm->_util->checkKey();
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+ _vm->_util->getMouseState(&mouseX, &mouseY, &mouseButtons);
+ _vm->_util->forceMouseUp();
+
+ handleInput(key, mouseX, mouseY, mouseButtons);
+
+ // Loop
+
+ bool looped = false;
+ for (Loops::iterator l = _loops.begin(); l != _loops.end(); ++l) {
+ if ((l->endFrame == _frame) && (l->currentLoop < l->loopCount)) {
+ _frame = l->startFrame;
+
+ l->currentLoop++;
+ looped = true;
+ }
+ }
+
+ // If we didn't loop, advance the frame and look if we should end here
+
+ if (!looped) {
+ _frame++;
+ if (_frame >= endFrame)
+ break;
+ }
+ }
+
+ // Restore the frame rate
+ _vm->_util->setFrameRate(frameRateBack);
+}
+
+void SEQFile::playFrame() {
+ // Remove the current animation frames
+ clearAnims();
+
+ // Handle background keys, directly updating the background
+ for (BackgroundKeys::const_iterator b = _bgKeys.begin(); b != _bgKeys.end(); ++b) {
+ if (!b->background || (b->frame != _frame))
+ continue;
+
+ b->background->draw(*_vm->_draw->_backSurface);
+
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
+ }
+
+ // Handle the animation keys, updating the objects
+ for (AnimationKeys::const_iterator a = _animKeys.begin(); a != _animKeys.end(); ++a) {
+ if (a->frame != _frame)
+ continue;
+
+ Object &object = _objects[a->object];
+
+ delete object.object;
+ object.object = 0;
+
+ // No valid animation => remove
+ if ((a->animation == 0xFFFF) || !a->ani)
+ continue;
+
+ // Change the animation
+
+ object.object = new ANIObject(*a->ani);
+
+ object.object->setAnimation(a->animation);
+ object.object->setPosition(a->x, a->y);
+ object.object->setVisible(true);
+ object.object->setPause(false);
+
+ object.order = a->order;
+ }
+
+ // Draw the animations
+ drawAnims();
+}
+
+// NOTE: This is really not at all efficient. However, since there's only a
+// small number of objects, it should matter. We really do need a stable
+// sort, though, so Common::sort() is out.
+SEQFile::Objects SEQFile::getOrderedObjects() {
+ int16 minOrder = (int16)0x7FFF;
+ int16 maxOrder = (int16)0x8000;
+
+ Objects objects;
+
+ // Find the span of order values
+ for (uint i = 0; i < kObjectCount; i++) {
+ if (!_objects[i].object)
+ continue;
+
+ minOrder = MIN(minOrder, _objects[i].order);
+ maxOrder = MAX(maxOrder, _objects[i].order);
+ }
+
+ // Stably sort the objects by order value
+ for (int16 o = minOrder; o <= maxOrder; o++)
+ for (uint i = 0; i < kObjectCount; i++)
+ if (_objects[i].object && (_objects[i].order == o))
+ objects.push_back(_objects[i]);
+
+ return objects;
+}
+
+void SEQFile::clearAnims() {
+ Objects objects = getOrderedObjects();
+
+ // Remove the animation frames, in reverse drawing order
+ for (Objects::iterator o = objects.reverse_begin(); o != objects.end(); --o) {
+ int16 left, top, right, bottom;
+
+ if (o->object->clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+ }
+}
+
+void SEQFile::drawAnims() {
+ Objects objects = getOrderedObjects();
+
+ // Draw the animation frames and advance the animation
+ for (Objects::iterator o = objects.begin(); o != objects.end(); ++o) {
+ int16 left, top, right, bottom;
+
+ if (o->object->draw(*_vm->_draw->_backSurface, left, top, right, bottom))
+ _vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+
+ o->object->advance();
+ }
+}
+
+uint16 SEQFile::getFrame() const {
+ return _frame;
+}
+
+void SEQFile::seekFrame(uint16 frame) {
+ _frame = frame;
+}
+
+uint SEQFile::addLoop(uint16 startFrame, uint16 endFrame, uint16 loopCount) {
+ _loops.resize(_loops.size() + 1);
+
+ _loops.back().startFrame = startFrame;
+ _loops.back().endFrame = endFrame;
+ _loops.back().loopCount = loopCount;
+ _loops.back().currentLoop = 0;
+ _loops.back().empty = false;
+
+ return _loops.size() - 1;
+}
+
+void SEQFile::skipLoop(uint loopID) {
+ if (loopID >= _loops.size())
+ return;
+
+ _loops[loopID].currentLoop = 0xFFFF;
+}
+
+void SEQFile::delLoop(uint loopID) {
+ if (loopID >= _loops.size())
+ return;
+
+ _loops[loopID].empty = true;
+
+ cleanLoops();
+}
+
+void SEQFile::cleanLoops() {
+ while (!_loops.empty() && _loops.back().empty)
+ _loops.pop_back();
+}
+
+void SEQFile::abortPlay() {
+ _abortPlay = true;
+}
+
+void SEQFile::handleFrameEvent() {
+}
+
+void SEQFile::handleInput(int16 key, int16 mouseX, int16 mouseY, MouseButtons mouseButtons) {
+ if (_abortable && ((key != 0) || (mouseButtons != kMouseButtonsNone)))
+ abortPlay();
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/seqfile.h b/engines/gob/pregob/seqfile.h
new file mode 100644
index 0000000000..5e12962ef9
--- /dev/null
+++ b/engines/gob/pregob/seqfile.h
@@ -0,0 +1,193 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_SEQFILE_H
+#define GOB_PREGOB_SEQFILE_H
+
+#include "common/system.h"
+#include "common/array.h"
+#include "common/list.h"
+
+#include "gob/util.h"
+
+namespace Common {
+ class String;
+ class SeekableReadStream;
+}
+
+namespace Gob {
+
+class GobEngine;
+
+class DECFile;
+class ANIFile;
+class ANIObject;
+
+/** A SEQ file, describing a complex animation sequence.
+ *
+ * Used in early hardcoded gob games.
+ * The principle is similar to the Mult class (see mult.h), but instead
+ * of depending on all the externally loaded animations, backgrounds and
+ * objects, a SEQ file references animation and background directly by
+ * filename.
+ */
+class SEQFile {
+public:
+ SEQFile(GobEngine *vm, const Common::String &fileName);
+ virtual ~SEQFile();
+
+ /** Play the SEQ.
+ *
+ * @param abortable If true, end playback on any user input.
+ * @param endFrame The frame on where to end, or 0xFFFF for infinite playback.
+ * @param frameRate The frame rate at which to play the SEQ, or 0 for playing at
+ * the speed the SEQ itself wants to.
+ */
+ void play(bool abortable = true, uint16 endFrame = 0xFFFF, uint16 frameRate = 0);
+
+
+protected:
+ GobEngine *_vm;
+
+
+ /** Returns the current frame number. */
+ uint16 getFrame() const;
+
+ /** Seek to a specific frame. */
+ void seekFrame(uint16 frame);
+
+ /** Add a frame loop. */
+ uint addLoop(uint16 startFrame, uint16 endFrame, uint16 loopCount);
+
+ /** Skip a frame loop. */
+ void skipLoop(uint loopID);
+
+ /** Delete a frame loop. */
+ void delLoop(uint loopID);
+
+ /** Ends SEQ playback. */
+ void abortPlay();
+
+ /** Callback for special frame events. */
+ virtual void handleFrameEvent();
+ /** Callback for special user input handling. */
+ virtual void handleInput(int16 key, int16 mouseX, int16 mouseY, MouseButtons mouseButtons);
+
+
+private:
+ /** Number of animation objects that are visible at the same time. */
+ static const uint kObjectCount = 4;
+
+ /** A key for changing the background. */
+ struct BackgroundKey {
+ uint16 frame; ///< Frame the change is to happen.
+
+ const DECFile *background; ///< The background to use.
+ };
+
+ /** A key for playing an object animation. */
+ struct AnimationKey {
+ uint object; ///< The object this key belongs to.
+
+ uint16 frame; ///< Frame the change is to happen.
+
+ const ANIFile *ani; ///< The ANI to use.
+
+ uint16 animation; ///< The animation to use.
+
+ int16 x; ///< X position of the animation.
+ int16 y; ///< Y position of the animation.
+
+ int16 order; ///< Used to determine in which order to draw the objects.
+ };
+
+ /** A managed animation object. */
+ struct Object {
+ ANIObject *object; ///< The actual animation object.
+
+ int16 order; ///< The current drawing order.
+ };
+
+ /** A frame loop. */
+ struct Loop {
+ uint16 startFrame;
+ uint16 endFrame;
+
+ uint16 loopCount;
+ uint16 currentLoop;
+
+ bool empty;
+ };
+
+ typedef Common::Array<DECFile *> Backgrounds;
+ typedef Common::Array<ANIFile *> Animations;
+
+ typedef Common::Array<BackgroundKey> BackgroundKeys;
+ typedef Common::Array<AnimationKey> AnimationKeys;
+
+ typedef Common::List<Object> Objects;
+
+ typedef Common::Array<Loop> Loops;
+
+
+ uint16 _frame; ///< The current frame.
+ bool _abortPlay; ///< Was the end of the playback requested?
+
+ uint16 _frameRate;
+
+ Backgrounds _backgrounds; ///< All backgrounds in this SEQ.
+ Animations _animations; ///< All animations in this SEQ.
+
+ BackgroundKeys _bgKeys; ///< The background change keyframes.
+ AnimationKeys _animKeys; ///< The animation change keyframes.
+
+ Object _objects[kObjectCount]; ///< The managed animation objects.
+
+ Loops _loops;
+
+ /** Whether the playback should be abortable by user input. */
+ bool _abortable;
+
+
+ // -- Loading helpers --
+
+ void load(Common::SeekableReadStream &seq);
+
+ const ANIFile *findANI(uint16 index, uint16 &animation);
+
+ // -- Playback helpers --
+
+ void playFrame();
+
+ /** Get a list of objects ordered by drawing order. */
+ Objects getOrderedObjects();
+
+ void clearAnims(); ///< Remove all animation frames.
+ void drawAnims(); ///< Draw the animation frames.
+
+ /** Look if we can compact the loop array. */
+ void cleanLoops();
+};
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_SEQFILE_H
diff --git a/engines/gob/pregob/txtfile.cpp b/engines/gob/pregob/txtfile.cpp
new file mode 100644
index 0000000000..3ff0d4b039
--- /dev/null
+++ b/engines/gob/pregob/txtfile.cpp
@@ -0,0 +1,232 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/stream.h"
+
+#include "gob/draw.h"
+
+#include "gob/pregob/txtfile.h"
+
+namespace Gob {
+
+TXTFile::TXTFile(Common::SeekableReadStream &txt, Format format) {
+ load(txt, format);
+}
+
+TXTFile::~TXTFile() {
+}
+
+TXTFile::LineArray &TXTFile::getLines() {
+ return _lines;
+}
+
+void TXTFile::load(Common::SeekableReadStream &txt, Format format) {
+ if (format == kFormatStringPositionColorFont) {
+ int numLines = getInt(txt);
+
+ _lines.reserve(numLines);
+ }
+
+ while (!txt.eos()) {
+ Line line;
+
+ line.text = getStr(txt);
+ line.x = (format >= kFormatStringPosition) ? getInt(txt) : 0;
+ line.y = (format >= kFormatStringPosition) ? getInt(txt) : 0;
+ line.color = (format >= kFormatStringPositionColor) ? getInt(txt) : 0;
+ line.font = (format >= kFormatStringPositionColorFont) ? getInt(txt) : 0;
+
+ _lines.push_back(line);
+ }
+
+ while (!_lines.empty() && _lines.back().text.empty())
+ _lines.pop_back();
+}
+
+bool TXTFile::draw(Surface &surface, int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount, int color) {
+
+ trashBuffer();
+
+ if (!getArea(left, top, right, bottom, fonts, fontCount))
+ return false;
+
+ resizeBuffer(right - left + 1, bottom - top + 1);
+ saveScreen(surface, left, top, right, bottom);
+
+ for (LineArray::const_iterator l = _lines.begin(); l != _lines.end(); ++l) {
+ if (l->font >= fontCount)
+ continue;
+
+ fonts[l->font]->drawString(l->text, l->x, l->y, (color < 0) ? l->color : color, 0, true, surface);
+ }
+
+ return true;
+}
+
+bool TXTFile::draw(uint line, Surface &surface, int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount, int color) {
+
+ trashBuffer();
+
+ if (!getArea(line, left, top, right, bottom, fonts, fontCount))
+ return false;
+
+ resizeBuffer(right - left + 1, bottom - top + 1);
+ saveScreen(surface, left, top, right, bottom);
+
+ const Line &l = _lines[line];
+
+ fonts[l.font]->drawString(l.text, l.x, l.y, (color < 0) ? l.color : color, 0, true, surface);
+
+ return true;
+}
+
+bool TXTFile::draw(Surface &surface, const Font * const *fonts, uint fontCount, int color) {
+ int16 left, top, right, bottom;
+
+ return draw(surface, left, top, right, bottom, fonts, fontCount, color);
+}
+
+bool TXTFile::draw(uint line, Surface &surface, const Font * const *fonts, uint fontCount, int color) {
+ int16 left, top, right, bottom;
+
+ return draw(line, surface, left, top, right, bottom, fonts, fontCount, color);
+}
+
+bool TXTFile::clear(Surface &surface, int16 &left, int16 &top, int16 &right, int16 &bottom) {
+ return restoreScreen(surface, left, top, right, bottom);
+}
+
+bool TXTFile::getArea(int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount) const {
+
+ bool hasLine = false;
+
+ left = 0x7FFF;
+ top = 0x7FFF;
+ right = 0x0000;
+ bottom = 0x0000;
+
+ for (uint i = 0; i < _lines.size(); i++) {
+ int16 lLeft, lTop, lRight, lBottom;
+
+ if (getArea(i, lLeft, lTop, lRight, lBottom, fonts, fontCount)) {
+ left = MIN(left , lLeft );
+ top = MIN(top , lTop );
+ right = MAX(right , lRight );
+ bottom = MAX(bottom, lBottom);
+
+ hasLine = true;
+ }
+ }
+
+ return hasLine;
+}
+
+bool TXTFile::getArea(uint line, int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount) const {
+
+
+ if ((line >= _lines.size()) || (_lines[line].font >= fontCount))
+ return false;
+
+ const Line &l = _lines[line];
+
+ left = l.x;
+ top = l.y;
+ right = l.x + l.text.size() * fonts[l.font]->getCharWidth() - 1;
+ bottom = l.y + fonts[l.font]->getCharHeight() - 1;
+
+ return true;
+}
+
+Common::String TXTFile::getStr(Common::SeekableReadStream &txt) {
+ // Skip all ' ', '\n' and '\r'
+ while (!txt.eos()) {
+ char c = txt.readByte();
+ if (txt.eos())
+ break;
+
+ if ((c != ' ') && (c != '\n') && (c != '\r')) {
+ txt.seek(-1, SEEK_CUR);
+ break;
+ }
+ }
+
+ if (txt.eos())
+ return "";
+
+ // Read string until ' ', '\n' or '\r'
+ Common::String string;
+ while (!txt.eos()) {
+ char c = txt.readByte();
+ if ((c == ' ') || (c == '\n') || (c == '\r'))
+ break;
+
+ string += c;
+ }
+
+ // Replace all '#' with ' ' and throw out non-printables
+ Common::String cleanString;
+
+ for (uint i = 0; i < string.size(); i++) {
+ if (string[i] == '#')
+ cleanString += ' ';
+ else if ((unsigned char)string[i] >= ' ')
+ cleanString += string[i];
+ }
+
+ return cleanString;
+}
+
+int TXTFile::getInt(Common::SeekableReadStream &txt) {
+ // Skip all [^-0-9]
+ while (!txt.eos()) {
+ char c = txt.readByte();
+ if (txt.eos())
+ break;
+
+ if ((c == '-') || ((c >= '0') && (c <= '9'))) {
+ txt.seek(-1, SEEK_CUR);
+ break;
+ }
+ }
+
+ if (txt.eos())
+ return 0;
+
+ // Read until [^-0-9]
+ Common::String string;
+ while (!txt.eos()) {
+ char c = txt.readByte();
+ if ((c != '-') && ((c < '0') || (c > '9')))
+ break;
+
+ string += c;
+ }
+
+ // Convert to integer
+ return atoi(string.c_str());
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/pregob/txtfile.h b/engines/gob/pregob/txtfile.h
new file mode 100644
index 0000000000..c623b58859
--- /dev/null
+++ b/engines/gob/pregob/txtfile.h
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_PREGOB_TXTFILE_H
+#define GOB_PREGOB_TXTFILE_H
+
+#include "common/system.h"
+#include "common/str.h"
+#include "common/array.h"
+
+#include "gob/backbuffer.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Gob {
+
+class Surface;
+class Font;
+
+class TXTFile : public BackBuffer {
+public:
+ enum Format {
+ kFormatString,
+ kFormatStringPosition,
+ kFormatStringPositionColor,
+ kFormatStringPositionColorFont
+ };
+
+ struct Line {
+ Common::String text;
+ int x, y;
+ int color;
+ uint font;
+ };
+
+ typedef Common::Array<Line> LineArray;
+
+ TXTFile(Common::SeekableReadStream &txt, Format format);
+ ~TXTFile();
+
+ LineArray &getLines();
+
+ bool draw( Surface &surface, const Font * const *fonts, uint fontCount, int color = -1);
+ bool draw(uint line, Surface &surface, const Font * const *fonts, uint fontCount, int color = -1);
+
+ bool draw( Surface &surface, int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount, int color = -1);
+ bool draw(uint line, Surface &surface, int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount, int color = -1);
+
+ bool clear(Surface &surface, int16 &left, int16 &top, int16 &right, int16 &bottom);
+
+private:
+ LineArray _lines;
+
+ void load(Common::SeekableReadStream &txt, Format format);
+
+ Common::String getStr(Common::SeekableReadStream &txt);
+ int getInt(Common::SeekableReadStream &txt);
+
+
+ bool getArea( int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount) const;
+ bool getArea(uint line, int16 &left, int16 &top, int16 &right, int16 &bottom,
+ const Font * const *fonts, uint fontCount) const;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_PREGOB_TXTFILE_H
diff --git a/engines/gob/resources.cpp b/engines/gob/resources.cpp
index d5497c25be..a84f4ac4b8 100644
--- a/engines/gob/resources.cpp
+++ b/engines/gob/resources.cpp
@@ -716,7 +716,7 @@ byte *Resources::getIMData(TOTResourceItem &totItem) const {
return _imData + offset;
}
-byte *Resources::getEXTData(EXTResourceItem &extItem, uint32 size) const {
+byte *Resources::getEXTData(EXTResourceItem &extItem, uint32 &size) const {
Common::SeekableReadStream *stream = _vm->_dataIO->getFile(_extFile);
if (!stream)
return 0;
@@ -726,6 +726,10 @@ byte *Resources::getEXTData(EXTResourceItem &extItem, uint32 size) const {
return 0;
}
+ // If that workaround is active, limit the resource size instead of throwing an error
+ if (_vm->hasResourceSizeWorkaround())
+ size = MIN<int>(size, stream->size() - extItem.offset);
+
byte *data = new byte[extItem.packed ? (size + 2) : size];
if (stream->read(data, size) != size) {
delete[] data;
@@ -737,7 +741,7 @@ byte *Resources::getEXTData(EXTResourceItem &extItem, uint32 size) const {
return data;
}
-byte *Resources::getEXData(EXTResourceItem &extItem, uint32 size) const {
+byte *Resources::getEXData(EXTResourceItem &extItem, uint32 &size) const {
Common::SeekableReadStream *stream = _vm->_dataIO->getFile(_exFile);
if (!stream)
return 0;
@@ -747,6 +751,10 @@ byte *Resources::getEXData(EXTResourceItem &extItem, uint32 size) const {
return 0;
}
+ // If that workaround is active, limit the resource size instead of throwing an error
+ if (_vm->hasResourceSizeWorkaround())
+ size = MIN<int>(size, stream->size() - extItem.offset);
+
byte *data = new byte[extItem.packed ? (size + 2) : size];
if (stream->read(data, size) != size) {
delete[] data;
diff --git a/engines/gob/resources.h b/engines/gob/resources.h
index 39155c5176..04b3b9d31e 100644
--- a/engines/gob/resources.h
+++ b/engines/gob/resources.h
@@ -103,7 +103,7 @@ private:
static const int kTOTTextItemSize = 2 + 2;
enum ResourceType {
- kResourceTOT,
+ kResourceTOT = 0,
kResourceIM,
kResourceEXT,
kResourceEX
@@ -201,8 +201,8 @@ private:
byte *getTOTData(TOTResourceItem &totItem) const;
byte *getIMData(TOTResourceItem &totItem) const;
- byte *getEXTData(EXTResourceItem &extItem, uint32 size) const;
- byte *getEXData(EXTResourceItem &extItem, uint32 size) const;
+ byte *getEXTData(EXTResourceItem &extItem, uint32 &size) const;
+ byte *getEXData(EXTResourceItem &extItem, uint32 &size) const;
};
} // End of namespace Gob
diff --git a/engines/gob/rxyfile.cpp b/engines/gob/rxyfile.cpp
index 9702dc8c7f..2ff8c121cd 100644
--- a/engines/gob/rxyfile.cpp
+++ b/engines/gob/rxyfile.cpp
@@ -21,12 +21,19 @@
*/
#include "common/stream.h"
+#include "common/substream.h"
#include "gob/rxyfile.h"
namespace Gob {
RXYFile::RXYFile(Common::SeekableReadStream &rxy) : _width(0), _height(0) {
+ Common::SeekableSubReadStreamEndian sub(&rxy, 0, rxy.size(), false, DisposeAfterUse::NO);
+
+ load(sub);
+}
+
+RXYFile::RXYFile(Common::SeekableSubReadStreamEndian &rxy) : _width(0), _height(0) {
load(rxy);
}
@@ -64,22 +71,22 @@ const RXYFile::Coordinates &RXYFile::operator[](uint i) const {
return _coords[i];
}
-void RXYFile::load(Common::SeekableReadStream &rxy) {
+void RXYFile::load(Common::SeekableSubReadStreamEndian &rxy) {
if (rxy.size() < 2)
return;
rxy.seek(0);
- _realCount = rxy.readUint16LE();
+ _realCount = rxy.readUint16();
uint16 count = (rxy.size() - 2) / 8;
_coords.resize(count);
for (CoordArray::iterator c = _coords.begin(); c != _coords.end(); ++c) {
- c->left = rxy.readUint16LE();
- c->right = rxy.readUint16LE();
- c->top = rxy.readUint16LE();
- c->bottom = rxy.readUint16LE();
+ c->left = rxy.readUint16();
+ c->right = rxy.readUint16();
+ c->top = rxy.readUint16();
+ c->bottom = rxy.readUint16();
if (c->left != 0xFFFF) {
_width = MAX<uint16>(_width , c->right + 1);
diff --git a/engines/gob/rxyfile.h b/engines/gob/rxyfile.h
index bc9600b5b0..4fd46c5e40 100644
--- a/engines/gob/rxyfile.h
+++ b/engines/gob/rxyfile.h
@@ -28,6 +28,7 @@
namespace Common {
class SeekableReadStream;
+ class SeekableSubReadStreamEndian;
}
namespace Gob {
@@ -46,6 +47,7 @@ public:
};
RXYFile(Common::SeekableReadStream &rxy);
+ RXYFile(Common::SeekableSubReadStreamEndian &rxy);
RXYFile(uint16 width, uint16 height);
~RXYFile();
@@ -71,7 +73,7 @@ private:
uint16 _height;
- void load(Common::SeekableReadStream &rxy);
+ void load(Common::SeekableSubReadStreamEndian &rxy);
};
} // End of namespace Gob
diff --git a/engines/gob/save/saveload.h b/engines/gob/save/saveload.h
index 66b3482bac..834484757b 100644
--- a/engines/gob/save/saveload.h
+++ b/engines/gob/save/saveload.h
@@ -257,6 +257,33 @@ protected:
SaveFile *getSaveFile(const char *fileName);
};
+/** Save/Load class for A.J.'s World of Discovery. */
+class SaveLoad_AJWorld : public SaveLoad {
+public:
+ SaveLoad_AJWorld(GobEngine *vm, const char *targetName);
+ virtual ~SaveLoad_AJWorld();
+
+ SaveMode getSaveMode(const char *fileName) const;
+
+protected:
+ struct SaveFile {
+ const char *sourceName;
+ SaveMode mode;
+ SaveHandler *handler;
+ const char *description;
+ };
+
+ static SaveFile _saveFiles[];
+
+ TempSpriteHandler *_tempSpriteHandler;
+
+ SaveHandler *getHandler(const char *fileName) const;
+ const char *getDescription(const char *fileName) const;
+
+ const SaveFile *getSaveFile(const char *fileName) const;
+ SaveFile *getSaveFile(const char *fileName);
+};
+
/** Save/Load class for Goblins 3 and Lost in Time. */
class SaveLoad_v3 : public SaveLoad {
public:
diff --git a/engines/gob/save/saveload_ajworld.cpp b/engines/gob/save/saveload_ajworld.cpp
new file mode 100644
index 0000000000..727d071b3e
--- /dev/null
+++ b/engines/gob/save/saveload_ajworld.cpp
@@ -0,0 +1,94 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/save/saveload.h"
+#include "gob/save/saveconverter.h"
+#include "gob/inter.h"
+#include "gob/variables.h"
+
+namespace Gob {
+
+SaveLoad_AJWorld::SaveFile SaveLoad_AJWorld::_saveFiles[] = {
+ { "menu.inf", kSaveModeSave, 0, "temporary sprite"}
+};
+
+
+SaveLoad_AJWorld::SaveLoad_AJWorld(GobEngine *vm, const char *targetName) :
+ SaveLoad(vm) {
+
+ _tempSpriteHandler = new TempSpriteHandler(vm);
+
+ _saveFiles[0].handler = _tempSpriteHandler;
+}
+
+SaveLoad_AJWorld::~SaveLoad_AJWorld() {
+ delete _tempSpriteHandler;
+}
+
+const SaveLoad_AJWorld::SaveFile *SaveLoad_AJWorld::getSaveFile(const char *fileName) const {
+ fileName = stripPath(fileName);
+
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return &_saveFiles[i];
+
+ return 0;
+}
+
+SaveLoad_AJWorld::SaveFile *SaveLoad_AJWorld::getSaveFile(const char *fileName) {
+ fileName = stripPath(fileName);
+
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return &_saveFiles[i];
+
+ return 0;
+}
+
+SaveHandler *SaveLoad_AJWorld::getHandler(const char *fileName) const {
+ const SaveFile *saveFile = getSaveFile(fileName);
+
+ if (saveFile)
+ return saveFile->handler;
+
+ return 0;
+}
+
+const char *SaveLoad_AJWorld::getDescription(const char *fileName) const {
+ const SaveFile *saveFile = getSaveFile(fileName);
+
+ if (saveFile)
+ return saveFile->description;
+
+ return 0;
+}
+
+SaveLoad::SaveMode SaveLoad_AJWorld::getSaveMode(const char *fileName) const {
+ const SaveFile *saveFile = getSaveFile(fileName);
+
+ if (saveFile)
+ return saveFile->mode;
+
+ return kSaveModeNone;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index f1ab2a2d79..d9fc362547 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -20,771 +20,621 @@
*
*/
-#include "common/debug.h"
-#include "common/file.h"
-#include "common/endian.h"
+#include "common/util.h"
#include "common/textconsole.h"
+#include "common/debug.h"
+#include "common/config-manager.h"
+
+#include "audio/fmopl.h"
#include "gob/gob.h"
#include "gob/sound/adlib.h"
namespace Gob {
-const unsigned char AdLib::_operators[] = {0, 1, 2, 8, 9, 10, 16, 17, 18};
-const unsigned char AdLib::_volRegNums[] = {
- 3, 4, 5,
- 11, 12, 13,
- 19, 20, 21
+static const int kPitchTom = 24;
+static const int kPitchTomToSnare = 7;
+static const int kPitchSnareDrum = kPitchTom + kPitchTomToSnare;
+
+
+// Is the operator a modulator (0) or a carrier (1)?
+const uint8 AdLib::kOperatorType[kOperatorCount] = {
+ 0, 0, 0, 1, 1, 1,
+ 0, 0, 0, 1, 1, 1,
+ 0, 0, 0, 1, 1, 1
+};
+
+// Operator number to register offset on the OPL
+const uint8 AdLib::kOperatorOffset[kOperatorCount] = {
+ 0, 1, 2, 3, 4, 5,
+ 8, 9, 10, 11, 12, 13,
+ 16, 17, 18, 19, 20, 21
+};
+
+// For each operator, the voice it belongs to
+const uint8 AdLib::kOperatorVoice[kOperatorCount] = {
+ 0, 1, 2,
+ 0, 1, 2,
+ 3, 4, 5,
+ 3, 4, 5,
+ 6, 7, 8,
+ 6, 7, 8,
+};
+
+// Voice to operator set, for the 9 melodyvoices (only 6 useable in percussion mode)
+const uint8 AdLib::kVoiceMelodyOperator[kOperatorsPerVoice][kMelodyVoiceCount] = {
+ {0, 1, 2, 6, 7, 8, 12, 13, 14},
+ {3, 4, 5, 9, 10, 11, 15, 16, 17}
};
-AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) {
- init();
+// Voice to operator set, for the 5 percussion voices (only useable in percussion mode)
+const uint8 AdLib::kVoicePercussionOperator[kOperatorsPerVoice][kPercussionVoiceCount] = {
+ {12, 16, 14, 17, 13},
+ {15, 0, 0, 0, 0}
+};
+
+// Mask bits to set each percussion instrument on/off
+const byte AdLib::kPercussionMasks[kPercussionVoiceCount] = {0x10, 0x08, 0x04, 0x02, 0x01};
+
+// Default instrument presets
+const uint16 AdLib::kPianoParams [kOperatorsPerVoice][kParamCount] = {
+ { 1, 1, 3, 15, 5, 0, 1, 3, 15, 0, 0, 0, 1, 0},
+ { 0, 1, 1, 15, 7, 0, 2, 4, 0, 0, 0, 1, 0, 0} };
+const uint16 AdLib::kBaseDrumParams[kOperatorsPerVoice][kParamCount] = {
+ { 0, 0, 0, 10, 4, 0, 8, 12, 11, 0, 0, 0, 1, 0 },
+ { 0, 0, 0, 13, 4, 0, 6, 15, 0, 0, 0, 0, 1, 0 } };
+const uint16 AdLib::kSnareDrumParams[kParamCount] = {
+ 0, 12, 0, 15, 11, 0, 8, 5, 0, 0, 0, 0, 0, 0 };
+const uint16 AdLib::kTomParams [kParamCount] = {
+ 0, 4, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0 };
+const uint16 AdLib::kCymbalParams [kParamCount] = {
+ 0, 1, 0, 15, 11, 0, 5, 5, 0, 0, 0, 0, 0, 0 };
+const uint16 AdLib::kHihatParams [kParamCount] = {
+ 0, 1, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0 };
+
+
+AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer), _opl(0),
+ _toPoll(0), _repCount(0), _first(true), _playing(false), _ended(true) {
+
+ _rate = _mixer->getOutputRate();
+
+ initFreqs();
+
+ createOPL();
+ initOPL();
+
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
+ this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLib::~AdLib() {
- Common::StackLock slock(_mutex);
-
_mixer->stopHandle(_handle);
- OPLDestroy(_opl);
- if (_data && _freeData)
- delete[] _data;
-}
-void AdLib::init() {
- _index = -1;
- _data = 0;
- _playPos = 0;
- _dataSize = 0;
+ delete _opl;
+}
- _rate = _mixer->getOutputRate();
+// Creates the OPL. Try to use the DOSBox emulator, unless that one is not compiled in,
+// or the user explicitly wants the MAME emulator. The MAME one is slightly buggy, leading
+// to some wrong sounds, especially noticeable in the title music of Gobliins 2, so we
+// really don't want to use it, if we can help it.
+void AdLib::createOPL() {
+ Common::String oplDriver = ConfMan.get("opl_driver");
- _opl = makeAdLibOPL(_rate);
+ if (oplDriver.empty() || (oplDriver == "auto") || (OPL::Config::parse(oplDriver) == -1)) {
+ // User has selected OPL driver auto detection or an invalid OPL driver.
+ // Set it to our preferred driver (DOSBox), if we can.
- _first = true;
- _ended = false;
- _playing = false;
+ if (OPL::Config::parse("db") <= 0) {
+ warning("The DOSBox AdLib emulator is not compiled in. Please keep in mind that the MAME one is buggy");
+ } else
+ oplDriver = "db";
- _freeData = false;
+ } else if (oplDriver == "mame") {
+ // User has selected the MAME OPL driver. It is buggy, so warn the user about that.
- _repCount = -1;
- _samplesTillPoll = 0;
+ warning("You have selected the MAME AdLib emulator. It is buggy; AdLib music might be slightly glitchy now");
+ }
- for (int i = 0; i < 16; i ++)
- _pollNotes[i] = 0;
- setFreqs();
+ _opl = OPL::Config::create(OPL::Config::parse(oplDriver), OPL::Config::kOpl2);
+ if (!_opl || !_opl->init(_rate)) {
+ delete _opl;
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
- this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ error("Could not create an AdLib emulator");
+ }
}
int AdLib::readBuffer(int16 *buffer, const int numSamples) {
Common::StackLock slock(_mutex);
- int samples;
- int render;
- if (!_playing || (numSamples < 0)) {
+ // Nothing to do, fill with silence
+ if (!_playing) {
memset(buffer, 0, numSamples * sizeof(int16));
return numSamples;
}
- if (_first) {
- memset(buffer, 0, numSamples * sizeof(int16));
- pollMusic();
- return numSamples;
- }
- samples = numSamples;
+ // Read samples from the OPL, polling in more music when necessary
+ uint32 samples = numSamples;
while (samples && _playing) {
- if (_samplesTillPoll) {
- render = (samples > _samplesTillPoll) ? (_samplesTillPoll) : (samples);
+ if (_toPoll) {
+ const uint32 render = MIN(samples, _toPoll);
+
+ _opl->readBuffer(buffer, render);
+
+ buffer += render;
samples -= render;
- _samplesTillPoll -= render;
- YM3812UpdateOne(_opl, buffer, render);
- buffer += render;
+ _toPoll -= render;
+
} else {
- pollMusic();
+ // Song ended, fill the rest with silence
if (_ended) {
memset(buffer, 0, samples * sizeof(int16));
samples = 0;
+ break;
}
+
+ // Poll more music
+ _toPoll = pollMusic(_first);
+ _first = false;
}
}
+ // Song ended, loop if requested
if (_ended) {
- _first = true;
- _ended = false;
+ _toPoll = 0;
- rewind();
+ // _repCount == 0: No looping (anymore); _repCount < 0: Infinite looping
+ if (_repCount != 0) {
+ if (_repCount > 0)
+ _repCount--;
+
+ _first = true;
+ _ended = false;
- _samplesTillPoll = 0;
- if (_repCount == -1) {
- reset();
- setVoices();
- } else if (_repCount > 0) {
- _repCount--;
reset();
- setVoices();
- }
- else
+ rewind();
+ } else
_playing = false;
}
- return numSamples;
-}
-void AdLib::writeOPL(byte reg, byte val) {
- debugC(6, kDebugSound, "AdLib::writeOPL (%02X, %02X)", reg, val);
- OPLWriteReg(_opl, reg, val);
+ return numSamples;
}
-void AdLib::setFreqs() {
- byte lin;
- byte col;
- long val = 0;
-
- // Run through the 11 channels
- for (lin = 0; lin < 11; lin ++) {
- _notes[lin] = 0;
- _notCol[lin] = 0;
- _notLin[lin] = 0;
- _notOn[lin] = false;
- }
-
- // Run through the 25 lines
- for (lin = 0; lin < 25; lin ++) {
- // Run through the 12 columns
- for (col = 0; col < 12; col ++) {
- if (!col)
- val = (((0x2710L + lin * 0x18) * 0xCB78 / 0x3D090) << 0xE) *
- 9 / 0x1B503;
- _freqs[lin][col] = (short)((val + 4) >> 3);
- val = val * 0x6A / 0x64;
- }
- }
+bool AdLib::isStereo() const {
+ return _opl->isStereo();
}
-void AdLib::reset() {
- _first = true;
- OPLResetChip(_opl);
- _samplesTillPoll = 0;
-
- setFreqs();
- // Set frequencies and octave to 0; notes off
- for (int i = 0; i < 9; i++) {
- writeOPL(0xA0 | i, 0);
- writeOPL(0xB0 | i, 0);
- writeOPL(0xE0 | _operators[i] , 0);
- writeOPL(0xE0 |(_operators[i] + 3), 0);
- }
-
- // Authorize the control of the waveformes
- writeOPL(0x01, 0x20);
-}
-
-void AdLib::setKey(byte voice, byte note, bool on, bool spec) {
- short freq = 0;
- short octa = 0;
-
- // Instruction AX
- if (spec) {
- // 0x7F donne 0x16B;
- // 7F
- // << 7 = 3F80
- // + E000 = 11F80
- // & FFFF = 1F80
- // * 19 = 31380
- // / 2000 = 18 => Ligne 18h, colonne 0 => freq 16B
-
- // 0x3A donne 0x2AF;
- // 3A
- // << 7 = 1D00
- // + E000 = FD00 negatif
- // * 19 = xB500
- // / 2000 = -2 => Ligne 17h, colonne -1
-
- // 2E
- // << 7 = 1700
- // + E000 = F700 negatif
- // * 19 = x1F00
- // / 2000 =
- short a;
- short lin;
- short col;
-
- a = (note << 7) + 0xE000; // Volontairement tronque
- a = (short)((long)a * 25 / 0x2000);
- if (a < 0) {
- col = - ((24 - a) / 25);
- lin = (-a % 25);
- if (lin)
- lin = 25 - lin;
- }
- else {
- col = a / 25;
- lin = a % 25;
- }
-
- _notCol[voice] = col;
- _notLin[voice] = lin;
- note = _notes[voice];
- }
- // Instructions 0X 9X 8X
- else {
- note -= 12;
- _notOn[voice] = on;
- }
-
- _notes[voice] = note;
- note += _notCol[voice];
- note = MIN((byte) 0x5F, note);
- octa = note / 12;
- freq = _freqs[_notLin[voice]][note - octa * 12];
-
- writeOPL(0xA0 + voice, freq & 0xFF);
- writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | (0x20 * (on ? 1 : 0)));
-
- if (!freq)
- warning("AdLib::setKey Voice %d, note %02X unknown", voice, note);
+bool AdLib::endOfData() const {
+ return !_playing;
}
-void AdLib::setVolume(byte voice, byte volume) {
- debugC(6, kDebugSound, "AdLib::setVolume(%d, %d)", voice, volume);
- //assert(voice >= 0 && voice <= 9);
- volume = 0x3F - ((volume * 0x7E) + 0x7F) / 0xFE;
- writeOPL(0x40 + _volRegNums[voice], volume);
+bool AdLib::endOfStream() const {
+ return false;
}
-void AdLib::pollMusic() {
- if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) {
- _ended = true;
- return;
- }
-
- interpret();
-}
-
-void AdLib::unload() {
- _playing = false;
- _index = -1;
-
- if (_data && _freeData)
- delete[] _data;
-
- _freeData = false;
+int AdLib::getRate() const {
+ return _rate;
}
bool AdLib::isPlaying() const {
return _playing;
}
-bool AdLib::getRepeating() const {
- return _repCount != 0;
+int32 AdLib::getRepeating() const {
+ Common::StackLock slock(_mutex);
+
+ return _repCount;
}
void AdLib::setRepeating(int32 repCount) {
+ Common::StackLock slock(_mutex);
+
_repCount = repCount;
}
-int AdLib::getIndex() const {
- return _index;
+uint32 AdLib::getSamplesPerSecond() const {
+ return _rate * (isStereo() ? 2 : 1);
}
void AdLib::startPlay() {
- if (_data) _playing = true;
+ Common::StackLock slock(_mutex);
+
+ _playing = true;
+ _ended = false;
+ _first = true;
+
+ reset();
+ rewind();
}
void AdLib::stopPlay() {
Common::StackLock slock(_mutex);
+
+ end(true);
+
_playing = false;
}
-ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer) {
-}
+void AdLib::writeOPL(byte reg, byte val) {
+ debugC(6, kDebugSound, "AdLib::writeOPL (%02X, %02X)", reg, val);
-ADLPlayer::~ADLPlayer() {
+ _opl->writeReg(reg, val);
}
-bool ADLPlayer::load(const char *fileName) {
- Common::File song;
+void AdLib::reset() {
+ allOff();
+ initOPL();
+}
- unload();
- song.open(fileName);
- if (!song.isOpen())
- return false;
+void AdLib::allOff() {
+ // NOTE: Explicit casts are necessary, because of 5.16 paragraph 4 of the C++ standard
+ int numVoices = isPercussionMode() ? (int)kMaxVoiceCount : (int)kMelodyVoiceCount;
- _freeData = true;
- _dataSize = song.size();
- _data = new byte[_dataSize];
- song.read(_data, _dataSize);
- song.close();
+ for (int i = 0; i < numVoices; i++)
+ noteOff(i);
+}
+void AdLib::end(bool killRepeat) {
reset();
- setVoices();
- _playPos = _data + 3 + (_data[1] + 1) * 0x38;
- return true;
+ _ended = true;
+
+ if (killRepeat)
+ _repCount = 0;
}
-bool ADLPlayer::load(byte *data, uint32 size, int index) {
- unload();
- _repCount = 0;
+void AdLib::initOPL() {
+ _tremoloDepth = false;
+ _vibratoDepth = false;
+ _keySplit = false;
- _dataSize = size;
- _data = data;
- _index = index;
+ _enableWaveSelect = true;
- reset();
- setVoices();
- _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+ for (int i = 0; i < kMaxVoiceCount; i++) {
+ _voiceNote[i] = 0;
+ _voiceOn [i] = 0;
+ }
+
+ _opl->reset();
+
+ initOperatorVolumes();
+ resetFreqs();
+
+ setPercussionMode(false);
+
+ setTremoloDepth(false);
+ setVibratoDepth(false);
+ setKeySplit(false);
+
+ for(int i = 0; i < kMelodyVoiceCount; i++)
+ voiceOff(i);
- return true;
+ setPitchRange(1);
+
+ enableWaveSelect(true);
}
-void ADLPlayer::unload() {
- AdLib::unload();
+bool AdLib::isPercussionMode() const {
+ return _percussionMode;
}
-void ADLPlayer::interpret() {
- unsigned char instr;
- byte channel;
- byte note;
- byte volume;
- uint16 tempo;
+void AdLib::setPercussionMode(bool percussion) {
+ if (percussion) {
+ voiceOff(kVoiceBaseDrum);
+ voiceOff(kVoiceSnareDrum);
+ voiceOff(kVoiceTom);
- // First tempo, we'll ignore it...
- if (_first) {
- tempo = *(_playPos++);
- // Tempo on 2 bytes
- if (tempo & 0x80)
- tempo = ((tempo & 3) << 8) | *(_playPos++);
- }
- _first = false;
-
- // Instruction
- instr = *(_playPos++);
- channel = instr & 0x0F;
-
- switch (instr & 0xF0) {
- // Note on + Volume
- case 0x00:
- note = *(_playPos++);
- _pollNotes[channel] = note;
- setVolume(channel, *(_playPos++));
- setKey(channel, note, true, false);
- break;
- // Note on
- case 0x90:
- note = *(_playPos++);
- _pollNotes[channel] = note;
- setKey(channel, note, true, false);
- break;
- // Last note off
- case 0x80:
- note = _pollNotes[channel];
- setKey(channel, note, false, false);
- break;
- // Frequency on/off
- case 0xA0:
- note = *(_playPos++);
- setKey(channel, note, _notOn[channel], true);
- break;
- // Volume
- case 0xB0:
- volume = *(_playPos++);
- setVolume(channel, volume);
- break;
- // Program change
- case 0xC0:
- setVoice(channel, *(_playPos++), false);
- break;
- // Special
- case 0xF0:
- switch (instr & 0x0F) {
- case 0xF: // End instruction
- _ended = true;
- _samplesTillPoll = 0;
- return;
- default:
- warning("ADLPlayer: Unknown special command %X, stopping playback",
- instr & 0x0F);
- _repCount = 0;
- _ended = true;
- break;
- }
- break;
- default:
- warning("ADLPlayer: Unknown command %X, stopping playback",
- instr & 0xF0);
- _repCount = 0;
- _ended = true;
- break;
+ /* set the frequency for the last 4 percussion voices: */
+ setFreq(kVoiceTom, kPitchTom, 0);
+ setFreq(kVoiceSnareDrum, kPitchSnareDrum, 0);
}
- // Temporization
- tempo = *(_playPos++);
- // End tempo
- if (tempo == 0xFF) {
- _ended = true;
- return;
- }
- // Tempo on 2 bytes
- if (tempo & 0x80)
- tempo = ((tempo & 3) << 8) | *(_playPos++);
- if (!tempo)
- tempo ++;
+ _percussionMode = percussion;
+ _percussionBits = 0;
- _samplesTillPoll = tempo * (_rate / 1000);
+ initOperatorParams();
+ writeTremoloVibratoDepthPercMode();
}
-void ADLPlayer::reset() {
- AdLib::reset();
+void AdLib::enableWaveSelect(bool enable) {
+ _enableWaveSelect = enable;
+
+ for (int i = 0; i < kOperatorCount; i++)
+ writeOPL(0xE0 + kOperatorOffset[i], 0);
+
+ writeOPL(0x011, _enableWaveSelect ? 0x20 : 0);
}
-void ADLPlayer::rewind() {
- _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+void AdLib::setPitchRange(uint8 range) {
+ _pitchRange = CLIP<uint8>(range, 0, 12);
+ _pitchRangeStep = _pitchRange * kPitchStepCount;
}
-void ADLPlayer::setVoices() {
- // Definitions of the 9 instruments
- for (int i = 0; i < 9; i++)
- setVoice(i, i, true);
+void AdLib::setTremoloDepth(bool tremoloDepth) {
+ _tremoloDepth = tremoloDepth;
+
+ writeTremoloVibratoDepthPercMode();
}
-void ADLPlayer::setVoice(byte voice, byte instr, bool set) {
- uint16 strct[27];
- byte channel;
- byte *dataPtr;
+void AdLib::setVibratoDepth(bool vibratoDepth) {
+ _vibratoDepth = vibratoDepth;
- // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26
- // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
- for (int i = 0; i < 2; i++) {
- dataPtr = _data + 3 + instr * 0x38 + i * 0x1A;
- for (int j = 0; j < 27; j++) {
- strct[j] = READ_LE_UINT16(dataPtr);
- dataPtr += 2;
- }
- channel = _operators[voice] + i * 3;
- writeOPL(0xBD, 0x00);
- writeOPL(0x08, 0x00);
- writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
- if (!i)
- writeOPL(0xC0 | voice,
- ((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
- writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
- writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
- writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
- ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
- ((strct[11] & 1) << 4) | (strct[1] & 0xF));
- if (!i)
- writeOPL(0xE0 | channel, (strct[26] & 3));
- else
- writeOPL(0xE0 | channel, (strct[14] & 3));
- if (i && set)
- writeOPL(0x40 | channel, 0);
+ writeTremoloVibratoDepthPercMode();
+}
+
+void AdLib::setKeySplit(bool keySplit) {
+ _keySplit = keySplit;
+
+ writeKeySplit();
+}
+
+void AdLib::setVoiceTimbre(uint8 voice, const uint16 *params) {
+ const uint16 *params0 = params;
+ const uint16 *params1 = params + kParamCount - 1;
+ const uint16 *waves = params + 2 * (kParamCount - 1);
+
+ const int voicePerc = voice - kVoiceBaseDrum;
+
+ if (!isPercussionMode() || (voice < kVoiceBaseDrum)) {
+ setOperatorParams(kVoiceMelodyOperator[0][voice], params0, waves[0]);
+ setOperatorParams(kVoiceMelodyOperator[1][voice], params1, waves[1]);
+ } else if (voice == kVoiceBaseDrum) {
+ setOperatorParams(kVoicePercussionOperator[0][voicePerc], params0, waves[0]);
+ setOperatorParams(kVoicePercussionOperator[1][voicePerc], params1, waves[1]);
+ } else {
+ setOperatorParams(kVoicePercussionOperator[0][voicePerc], params0, waves[0]);
}
}
+void AdLib::setVoiceVolume(uint8 voice, uint8 volume) {
+ int oper;
+
+ const int voicePerc = voice - kVoiceBaseDrum;
-MDYPlayer::MDYPlayer(Audio::Mixer &mixer) : AdLib(mixer) {
- init();
+ if (!isPercussionMode() || (voice < kVoiceBaseDrum))
+ oper = kVoiceMelodyOperator[1][ voice];
+ else
+ oper = kVoicePercussionOperator[voice == kVoiceBaseDrum ? 1 : 0][voicePerc];
+
+ _operatorVolume[oper] = MIN<uint8>(volume, kMaxVolume);
+ writeKeyScaleLevelVolume(oper);
}
-MDYPlayer::~MDYPlayer() {
+void AdLib::bendVoicePitch(uint8 voice, uint16 pitchBend) {
+ if (isPercussionMode() && (voice > kVoiceBaseDrum))
+ return;
+
+ changePitch(voice, MIN<uint16>(pitchBend, kMaxPitch));
+ setFreq(voice, _voiceNote[voice], _voiceOn[voice]);
}
-void MDYPlayer::init() {
- _soundMode = 0;
+void AdLib::noteOn(uint8 voice, uint8 note) {
+ note = MAX<int>(0, note - (kStandardMidC - kOPLMidC));
+
+ if (isPercussionMode() && (voice >= kVoiceBaseDrum)) {
+
+ if (voice == kVoiceBaseDrum) {
+ setFreq(kVoiceBaseDrum , note , false);
+ } else if (voice == kVoiceTom) {
+ setFreq(kVoiceTom , note , false);
+ setFreq(kVoiceSnareDrum, note + kPitchTomToSnare, false);
+ }
+
+ _percussionBits |= kPercussionMasks[voice - kVoiceBaseDrum];
+ writeTremoloVibratoDepthPercMode();
- _timbres = 0;
- _tbrCount = 0;
- _tbrStart = 0;
- _timbresSize = 0;
+ } else
+ setFreq(voice, note, true);
}
-bool MDYPlayer::loadMDY(Common::SeekableReadStream &stream) {
- unloadMDY();
+void AdLib::noteOff(uint8 voice) {
+ if (isPercussionMode() && (voice >= kVoiceBaseDrum)) {
+ _percussionBits &= ~kPercussionMasks[voice - kVoiceBaseDrum];
+ writeTremoloVibratoDepthPercMode();
+ } else
+ setFreq(voice, _voiceNote[voice], false);
+}
- _freeData = true;
+void AdLib::writeKeyScaleLevelVolume(uint8 oper) {
+ uint16 volume = 0;
- byte mdyHeader[70];
- stream.read(mdyHeader, 70);
+ volume = (63 - (_operatorParams[oper][kParamLevel] & 0x3F)) * _operatorVolume[oper];
+ volume = 63 - ((2 * volume + kMaxVolume) / (2 * kMaxVolume));
- _tickBeat = mdyHeader[36];
- _beatMeasure = mdyHeader[37];
- _totalTick = mdyHeader[38] + (mdyHeader[39] << 8) + (mdyHeader[40] << 16) + (mdyHeader[41] << 24);
- _dataSize = mdyHeader[42] + (mdyHeader[43] << 8) + (mdyHeader[44] << 16) + (mdyHeader[45] << 24);
- _nrCommand = mdyHeader[46] + (mdyHeader[47] << 8) + (mdyHeader[48] << 16) + (mdyHeader[49] << 24);
-// _soundMode is either 0 (melodic) or 1 (percussive)
- _soundMode = mdyHeader[58];
- assert((_soundMode == 0) || (_soundMode == 1));
+ uint8 keyScale = _operatorParams[oper][kParamKeyScaleLevel] << 6;
- _pitchBendRangeStep = 25*mdyHeader[59];
- _basicTempo = mdyHeader[60] + (mdyHeader[61] << 8);
+ writeOPL(0x40 + kOperatorOffset[oper], volume | keyScale);
+}
- if (_pitchBendRangeStep < 25)
- _pitchBendRangeStep = 25;
- else if (_pitchBendRangeStep > 300)
- _pitchBendRangeStep = 300;
+void AdLib::writeKeySplit() {
+ writeOPL(0x08, _keySplit ? 0x40 : 0);
+}
- _data = new byte[_dataSize];
- stream.read(_data, _dataSize);
+void AdLib::writeFeedbackFM(uint8 oper) {
+ if (kOperatorType[oper] == 1)
+ return;
- reset();
- _playPos = _data;
+ uint8 value = 0;
- return true;
+ value |= _operatorParams[oper][kParamFeedback] << 1;
+ value |= _operatorParams[oper][kParamFM] ? 0 : 1;
+
+ writeOPL(0xC0 + kOperatorVoice[oper], value);
}
-bool MDYPlayer::loadMDY(const char *fileName) {
- Common::File song;
+void AdLib::writeAttackDecay(uint8 oper) {
+ uint8 value = 0;
+
+ value |= _operatorParams[oper][kParamAttack] << 4;
+ value |= _operatorParams[oper][kParamDecay] & 0x0F;
- song.open(fileName);
- if (!song.isOpen())
- return false;
+ writeOPL(0x60 + kOperatorOffset[oper], value);
+}
- bool loaded = loadMDY(song);
+void AdLib::writeSustainRelease(uint8 oper) {
+ uint8 value = 0;
- song.close();
+ value |= _operatorParams[oper][kParamSustain] << 4;
+ value |= _operatorParams[oper][kParamRelease] & 0x0F;
- return loaded;
+ writeOPL(0x80 + kOperatorOffset[oper], value);
}
-bool MDYPlayer::loadTBR(Common::SeekableReadStream &stream) {
- unloadTBR();
+void AdLib::writeTremoloVibratoSustainingKeyScaleRateFreqMulti(uint8 oper) {
+ uint8 value = 0;
- _timbresSize = stream.size();
+ value |= _operatorParams[oper][kParamAM] ? 0x80 : 0;
+ value |= _operatorParams[oper][kParamVib] ? 0x40 : 0;
+ value |= _operatorParams[oper][kParamSustaining] ? 0x20 : 0;
+ value |= _operatorParams[oper][kParamKeyScaleRate] ? 0x10 : 0;
+ value |= _operatorParams[oper][kParamFreqMulti] & 0x0F;
- _timbres = new byte[_timbresSize];
- stream.read(_timbres, _timbresSize);
+ writeOPL(0x20 + kOperatorOffset[oper], value);
+}
- reset();
- setVoices();
+void AdLib::writeTremoloVibratoDepthPercMode() {
+ uint8 value = 0;
+
+ value |= _tremoloDepth ? 0x80 : 0;
+ value |= _vibratoDepth ? 0x40 : 0;
+ value |= isPercussionMode() ? 0x20 : 0;
+ value |= _percussionBits;
- return true;
+ writeOPL(0xBD, value);
}
-bool MDYPlayer::loadTBR(const char *fileName) {
- Common::File timbres;
+void AdLib::writeWaveSelect(uint8 oper) {
+ uint8 wave = 0;
+ if (_enableWaveSelect)
+ wave = _operatorParams[oper][kParamWaveSelect] & 0x03;
- timbres.open(fileName);
- if (!timbres.isOpen())
- return false;
+ writeOPL(0xE0 + kOperatorOffset[ oper], wave);
+}
- bool loaded = loadTBR(timbres);
+void AdLib::writeAllParams(uint8 oper) {
+ writeTremoloVibratoDepthPercMode();
+ writeKeySplit();
+ writeKeyScaleLevelVolume(oper);
+ writeFeedbackFM(oper);
+ writeAttackDecay(oper);
+ writeSustainRelease(oper);
+ writeTremoloVibratoSustainingKeyScaleRateFreqMulti(oper);
+ writeWaveSelect(oper);
+}
- timbres.close();
+void AdLib::initOperatorParams() {
+ for (int i = 0; i < kOperatorCount; i++)
+ setOperatorParams(i, kPianoParams[kOperatorType[i]], kPianoParams[kOperatorType[i]][kParamCount - 1]);
- return loaded;
+ if (isPercussionMode()) {
+ setOperatorParams(12, kBaseDrumParams [0], kBaseDrumParams [0][kParamCount - 1]);
+ setOperatorParams(15, kBaseDrumParams [1], kBaseDrumParams [1][kParamCount - 1]);
+ setOperatorParams(16, kSnareDrumParams , kSnareDrumParams [kParamCount - 1]);
+ setOperatorParams(14, kTomParams , kTomParams [kParamCount - 1]);
+ setOperatorParams(17, kCymbalParams , kCymbalParams [kParamCount - 1]);
+ setOperatorParams(13, kHihatParams , kHihatParams [kParamCount - 1]);
+ }
}
-void MDYPlayer::unload() {
- unloadTBR();
- unloadMDY();
+void AdLib::initOperatorVolumes() {
+ for(int i = 0; i < kOperatorCount; i++)
+ _operatorVolume[i] = kMaxVolume;
}
-void MDYPlayer::unloadMDY() {
- AdLib::unload();
+void AdLib::setOperatorParams(uint8 oper, const uint16 *params, uint8 wave) {
+ byte *operParams = _operatorParams[oper];
+
+ for (int i = 0; i < (kParamCount - 1); i++)
+ operParams[i] = params[i];
+
+ operParams[kParamCount - 1] = wave & 0x03;
+
+ writeAllParams(oper);
+}
+
+void AdLib::voiceOff(uint8 voice) {
+ writeOPL(0xA0 + voice, 0);
+ writeOPL(0xB0 + voice, 0);
}
-void MDYPlayer::unloadTBR() {
- delete[] _timbres;
+int32 AdLib::calcFreq(int32 deltaDemiToneNum, int32 deltaDemiToneDenom) {
+ int32 freq = 0;
- _timbres = 0;
- _timbresSize = 0;
+ freq = ((deltaDemiToneDenom * 100) + 6 * deltaDemiToneNum) * 52088;
+ freq /= deltaDemiToneDenom * 2500;
+
+ return (freq * 147456) / 111875;
}
-void MDYPlayer::interpret() {
- unsigned char instr;
- byte channel;
- byte note;
- byte volume;
- uint8 tempoMult, tempoFrac;
- uint8 ctrlByte1, ctrlByte2;
- uint8 timbre;
+void AdLib::setFreqs(uint16 *freqs, int32 num, int32 denom) {
+ int32 val = calcFreq(num, denom);
-// TODO : Verify the loop for percussive mode (11 ?)
- if (_first) {
- for (int i = 0; i < 9; i ++)
- setVolume(i, 0);
+ *freqs++ = (4 + val) >> 3;
-// TODO : Set pitch range
+ for (int i = 1; i < kHalfToneCount; i++) {
+ val = (val * 106) / 100;
- _tempo = _basicTempo;
- _wait = *(_playPos++);
- _first = false;
+ *freqs++ = (4 + val) >> 3;
}
- do {
- instr = *_playPos;
- debugC(6, kDebugSound, "MDYPlayer::interpret instr 0x%X", instr);
- switch (instr) {
- case 0xF8:
- _wait = *(_playPos++);
- break;
- case 0xFC:
- _ended = true;
- _samplesTillPoll = 0;
- return;
- case 0xF0:
- _playPos++;
- ctrlByte1 = *(_playPos++);
- ctrlByte2 = *(_playPos++);
- debugC(6, kDebugSound, "MDYPlayer::interpret ctrlBytes 0x%X 0x%X", ctrlByte1, ctrlByte2);
- if (ctrlByte1 != 0x7F || ctrlByte2 != 0) {
- _playPos -= 2;
- while (*(_playPos++) != 0xF7)
- ;
- } else {
- tempoMult = *(_playPos++);
- tempoFrac = *(_playPos++);
- _tempo = _basicTempo * tempoMult + (unsigned)(((long)_basicTempo * tempoFrac) >> 7);
- _playPos++;
- }
- _wait = *(_playPos++);
- break;
- default:
- if (instr >= 0x80) {
- _playPos++;
- }
- channel = (int)(instr & 0x0f);
-
- switch (instr & 0xf0) {
- case 0x90:
- note = *(_playPos++);
- volume = *(_playPos++);
- _pollNotes[channel] = note;
- setVolume(channel, volume);
- setKey(channel, note, true, false);
- break;
- case 0x80:
- _playPos += 2;
- note = _pollNotes[channel];
- setKey(channel, note, false, false);
- break;
- case 0xA0:
- setVolume(channel, *(_playPos++));
- break;
- case 0xC0:
- timbre = *(_playPos++);
- setVoice(channel, timbre, false);
- break;
- case 0xE0:
- warning("MDYPlayer: Pitch bend not yet implemented");
+}
- note = *(_playPos)++;
- note += (unsigned)(*(_playPos++)) << 7;
+void AdLib::initFreqs() {
+ const int numStep = 100 / kPitchStepCount;
- setKey(channel, note, _notOn[channel], true);
+ for (int i = 0; i < kPitchStepCount; i++)
+ setFreqs(_freqs[i], i * numStep, 100);
- break;
- case 0xB0:
- _playPos += 2;
- break;
- case 0xD0:
- _playPos++;
- break;
- default:
- warning("MDYPlayer: Bad MIDI instr byte: 0%X", instr);
- while ((*_playPos) < 0x80)
- _playPos++;
- if (*_playPos != 0xF8)
- _playPos--;
- break;
- } //switch instr & 0xF0
- _wait = *(_playPos++);
- break;
- } //switch instr
- } while (_wait == 0);
-
- if (_wait == 0xF8) {
- _wait = 0xF0;
- if (*_playPos != 0xF8)
- _wait += *(_playPos++) & 0x0F;
+ resetFreqs();
+}
+
+void AdLib::resetFreqs() {
+ for (int i = 0; i < kMaxVoiceCount; i++) {
+ _freqPtr [i] = _freqs[0];
+ _halfToneOffset[i] = 0;
}
-// _playPos++;
- _samplesTillPoll = _wait * (_rate / 1000);
}
-void MDYPlayer::reset() {
- AdLib::reset();
+void AdLib::changePitch(uint8 voice, uint16 pitchBend) {
+
+ int full = 0;
+ int frac = 0;
+ int amount = ((pitchBend - kMidPitch) * _pitchRangeStep) / kMidPitch;
+
+ if (amount >= 0) {
+ // Bend up
+
+ full = amount / kPitchStepCount;
+ frac = amount % kPitchStepCount;
-// _soundMode 1 : Percussive mode.
- if (_soundMode == 1) {
- writeOPL(0xA6, 0);
- writeOPL(0xB6, 0);
- writeOPL(0xA7, 0);
- writeOPL(0xB7, 0);
- writeOPL(0xA8, 0);
- writeOPL(0xB8, 0);
+ } else {
+ // Bend down
+
+ amount = kPitchStepCount - 1 - amount;
+
+ full = -(amount / kPitchStepCount);
+ frac = (amount - kPitchStepCount + 1) % kPitchStepCount;
+ if (frac)
+ frac = kPitchStepCount - frac;
-// TODO set the correct frequency for the last 4 percussive voices
}
+
+ _halfToneOffset[voice] = full;
+ _freqPtr [voice] = _freqs[frac];
}
-void MDYPlayer::rewind() {
- _playPos = _data;
-}
-
-void MDYPlayer::setVoices() {
- byte *timbrePtr;
-
- timbrePtr = _timbres;
- debugC(6, kDebugSound, "MDYPlayer::setVoices TBR version: %X.%X", timbrePtr[0], timbrePtr[1]);
- timbrePtr += 2;
-
- _tbrCount = READ_LE_UINT16(timbrePtr);
- debugC(6, kDebugSound, "MDYPlayer::setVoices Timbres counter: %d", _tbrCount);
- timbrePtr += 2;
- _tbrStart = READ_LE_UINT16(timbrePtr);
-
- timbrePtr += 2;
- for (int i = 0; i < _tbrCount; i++)
- setVoice(i, i, true);
-}
-
-void MDYPlayer::setVoice(byte voice, byte instr, bool set) {
-// uint16 strct[27];
- uint8 strct[27];
- byte channel;
- byte *timbrePtr;
- char timbreName[10];
-
- timbreName[9] = '\0';
- for (int j = 0; j < 9; j++)
- timbreName[j] = _timbres[6 + j + (instr * 9)];
- debugC(6, kDebugSound, "MDYPlayer::setVoice Loading timbre %s", timbreName);
-
- // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26
- // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27
- for (int i = 0; i < 2; i++) {
- timbrePtr = _timbres + _tbrStart + instr * 0x38 + i * 0x1A;
- for (int j = 0; j < 27; j++) {
- if (timbrePtr >= (_timbres + _timbresSize)) {
- warning("MDYPlayer: Instrument %d out of range (%d, %d)", instr,
- (uint32) (timbrePtr - _timbres), _timbresSize);
- strct[j] = 0;
- } else
- //strct[j] = READ_LE_UINT16(timbrePtr);
- strct[j] = timbrePtr[0];
- //timbrePtr += 2;
- timbrePtr++;
- }
- channel = _operators[voice] + i * 3;
- writeOPL(0xBD, 0x00);
- writeOPL(0x08, 0x00);
- writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
- if (!i)
- writeOPL(0xC0 | voice,
- ((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
- writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
- writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
- writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
- ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) |
- ((strct[11] & 1) << 4) | (strct[1] & 0xF));
- if (!i)
- writeOPL(0xE0 | channel, (strct[26] & 3));
- else {
- writeOPL(0xE0 | channel, (strct[14] & 3));
- writeOPL(0x40 | channel, 0);
- }
- }
+void AdLib::setFreq(uint8 voice, uint16 note, bool on) {
+ _voiceOn [voice] = on;
+ _voiceNote[voice] = note;
+
+ note = CLIP<int>(note + _halfToneOffset[voice], 0, kNoteCount - 1);
+
+ uint16 freq = _freqPtr[voice][note % kHalfToneCount];
+
+ uint8 value = 0;
+ value |= on ? 0x20 : 0;
+ value |= ((note / kHalfToneCount) << 2) | ((freq >> 8) & 0x03);
+
+ writeOPL(0xA0 + voice, freq);
+ writeOPL(0xB0 + voice, value);
}
} // End of namespace Gob
diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h
index 934e9966eb..bd1778d2ed 100644
--- a/engines/gob/sound/adlib.h
+++ b/engines/gob/sound/adlib.h
@@ -24,148 +24,282 @@
#define GOB_SOUND_ADLIB_H
#include "common/mutex.h"
+
#include "audio/audiostream.h"
#include "audio/mixer.h"
-#include "audio/fmopl.h"
-namespace Gob {
+namespace OPL {
+ class OPL;
+}
-class GobEngine;
+namespace Gob {
+/** Base class for a player of an AdLib music format. */
class AdLib : public Audio::AudioStream {
public:
AdLib(Audio::Mixer &mixer);
virtual ~AdLib();
- bool isPlaying() const;
- int getIndex() const;
- bool getRepeating() const;
+ bool isPlaying() const; ///< Are we currently playing?
+ int32 getRepeating() const; ///< Return number of times left to loop.
+ /** Set the loop counter.
+ *
+ * @param repCount Number of times to loop (i.e. number of additional
+ * paythroughs to the first one, not overall).
+ * A negative value means infinite looping.
+ */
void setRepeating(int32 repCount);
void startPlay();
void stopPlay();
- virtual void unload();
-
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return false; }
- bool endOfData() const { return !_playing; }
- bool endOfStream() const { return false; }
- int getRate() const { return _rate; }
+ bool isStereo() const;
+ bool endOfData() const;
+ bool endOfStream() const;
+ int getRate() const;
protected:
- static const unsigned char _operators[];
- static const unsigned char _volRegNums [];
+ enum kVoice {
+ kVoiceMelody0 = 0,
+ kVoiceMelody1 = 1,
+ kVoiceMelody2 = 2,
+ kVoiceMelody3 = 3,
+ kVoiceMelody4 = 4,
+ kVoiceMelody5 = 5,
+ kVoiceMelody6 = 6, // Only available in melody mode.
+ kVoiceMelody7 = 7, // Only available in melody mode.
+ kVoiceMelody8 = 8, // Only available in melody mode.
+ kVoiceBaseDrum = 6, // Only available in percussion mode.
+ kVoiceSnareDrum = 7, // Only available in percussion mode.
+ kVoiceTom = 8, // Only available in percussion mode.
+ kVoiceCymbal = 9, // Only available in percussion mode.
+ kVoiceHihat = 10 // Only available in percussion mode.
+ };
+
+ /** Operator parameters. */
+ enum kParam {
+ kParamKeyScaleLevel = 0,
+ kParamFreqMulti = 1,
+ kParamFeedback = 2,
+ kParamAttack = 3,
+ kParamSustain = 4,
+ kParamSustaining = 5,
+ kParamDecay = 6,
+ kParamRelease = 7,
+ kParamLevel = 8,
+ kParamAM = 9,
+ kParamVib = 10,
+ kParamKeyScaleRate = 11,
+ kParamFM = 12,
+ kParamWaveSelect = 13
+ };
+
+ static const int kOperatorCount = 18; ///< Number of operators.
+ static const int kParamCount = 14; ///< Number of operator parameters.
+ static const int kPitchStepCount = 25; ///< Number of pitch bend steps in a half tone.
+ static const int kOctaveCount = 8; ///< Number of octaves we can play.
+ static const int kHalfToneCount = 12; ///< Number of half tones in an octave.
+
+ static const int kOperatorsPerVoice = 2; ///< Number of operators per voice.
+
+ static const int kMelodyVoiceCount = 9; ///< Number of melody voices.
+ static const int kPercussionVoiceCount = 5; ///< Number of percussion voices.
+ static const int kMaxVoiceCount = 11; ///< Max number of voices.
+
+ /** Number of notes we can play. */
+ static const int kNoteCount = kHalfToneCount * kOctaveCount;
+
+ static const int kMaxVolume = 0x007F;
+ static const int kMaxPitch = 0x3FFF;
+ static const int kMidPitch = 0x2000;
+
+ static const int kStandardMidC = 60; ///< A mid C in standard MIDI.
+ static const int kOPLMidC = 48; ///< A mid C for the OPL.
+
+
+ /** Return the number of samples per second. */
+ uint32 getSamplesPerSecond() const;
+
+ /** Write a value into an OPL register. */
+ void writeOPL(byte reg, byte val);
+
+ /** Signal that the playback ended.
+ *
+ * @param killRepeat Explicitly request that the song is not to be looped.
+ */
+ void end(bool killRepeat = false);
+
+ /** The callback function that's called for polling more AdLib commands.
+ *
+ * @param first Is this the first poll since the start of the song?
+ * @return The number of samples until the next poll.
+ */
+ virtual uint32 pollMusic(bool first) = 0;
+
+ /** Rewind the song. */
+ virtual void rewind() = 0;
+
+ /** Return whether we're in percussion mode. */
+ bool isPercussionMode() const;
+
+ /** Set percussion or melody mode. */
+ void setPercussionMode(bool percussion);
+
+ /** Enable/Disable the wave select operator parameters.
+ *
+ * When disabled, all operators use the sine wave, regardless of the parameter.
+ */
+ void enableWaveSelect(bool enable);
+
+ /** Change the pitch bend range.
+ *
+ * @param range The range in half tones from 1 to 12 inclusive.
+ * See bendVoicePitch() for how this works in practice.
+ */
+ void setPitchRange(uint8 range);
+
+ /** Set the tremolo (amplitude vibrato) depth.
+ *
+ * @param tremoloDepth false: 1.0dB, true: 4.8dB.
+ */
+ void setTremoloDepth(bool tremoloDepth);
+
+ /** Set the frequency vibrato depth.
+ *
+ * @param vibratoDepth false: 7 cent, true: 14 cent. 1 cent = 1/100 half tone.
+ */
+ void setVibratoDepth(bool vibratoDepth);
+
+ /** Set the keyboard split point. */
+ void setKeySplit(bool keySplit);
+
+ /** Set the timbre of a voice.
+ *
+ * Layout of the operator parameters is as follows:
+ * - First 13 parameter for the first operator
+ * - First 13 parameter for the second operator
+ * - 14th parameter (wave select) for the first operator
+ * - 14th parameter (wave select) for the second operator
+ */
+ void setVoiceTimbre(uint8 voice, const uint16 *params);
+
+ /** Set a voice's volume. */
+ void setVoiceVolume(uint8 voice, uint8 volume);
+
+ /** Bend a voice's pitch.
+ *
+ * The pitchBend parameter is a value between 0 (full down) and kMaxPitch (full up).
+ * The actual frequency depends on the pitch range set previously by setPitchRange(),
+ * with full down being -range half tones and full up range half tones.
+ */
+ void bendVoicePitch(uint8 voice, uint16 pitchBend);
+
+ /** Switch a voice on.
+ *
+ * Plays one of the kNoteCount notes. However, the valid range of a note is between
+ * 0 and 127, of which only 12 to 107 are audible.
+ */
+ void noteOn(uint8 voice, uint8 note);
+
+ /** Switch a voice off. */
+ void noteOff(uint8 voice);
+
+private:
+ static const uint8 kOperatorType [kOperatorCount];
+ static const uint8 kOperatorOffset[kOperatorCount];
+ static const uint8 kOperatorVoice [kOperatorCount];
+
+ static const uint8 kVoiceMelodyOperator [kOperatorsPerVoice][kMelodyVoiceCount];
+ static const uint8 kVoicePercussionOperator[kOperatorsPerVoice][kPercussionVoiceCount];
+
+ static const byte kPercussionMasks[kPercussionVoiceCount];
+
+ static const uint16 kPianoParams [kOperatorsPerVoice][kParamCount];
+ static const uint16 kBaseDrumParams [kOperatorsPerVoice][kParamCount];
+
+ static const uint16 kSnareDrumParams[kParamCount];
+ static const uint16 kTomParams [kParamCount];
+ static const uint16 kCymbalParams [kParamCount];
+ static const uint16 kHihatParams [kParamCount];
+
Audio::Mixer *_mixer;
Audio::SoundHandle _handle;
- FM_OPL *_opl;
+ OPL::OPL *_opl;
Common::Mutex _mutex;
uint32 _rate;
- byte *_data;
- byte *_playPos;
- uint32 _dataSize;
-
- short _freqs[25][12];
- byte _notes[11];
- byte _notCol[11];
- byte _notLin[11];
- bool _notOn[11];
- byte _pollNotes[16];
+ uint32 _toPoll;
- int _samplesTillPoll;
int32 _repCount;
- bool _playing;
bool _first;
+ bool _playing;
bool _ended;
- bool _freeData;
+ bool _tremoloDepth;
+ bool _vibratoDepth;
+ bool _keySplit;
- int _index;
+ bool _enableWaveSelect;
- unsigned char _wait;
- uint8 _tickBeat;
- uint8 _beatMeasure;
- uint32 _totalTick;
- uint32 _nrCommand;
- uint16 _pitchBendRangeStep;
- uint16 _basicTempo, _tempo;
+ bool _percussionMode;
+ byte _percussionBits;
- void writeOPL(byte reg, byte val);
- void setFreqs();
- void setKey(byte voice, byte note, bool on, bool spec);
- void setVolume(byte voice, byte volume);
- void pollMusic();
+ uint8 _pitchRange;
+ uint16 _pitchRangeStep;
- virtual void interpret() = 0;
+ uint8 _voiceNote[kMaxVoiceCount]; // Last note of each voice
+ uint8 _voiceOn [kMaxVoiceCount]; // Whether each voice is currently on
- virtual void reset();
- virtual void rewind() = 0;
- virtual void setVoices() = 0;
+ uint8 _operatorVolume[kOperatorCount]; // Volume of each operator
-private:
- void init();
-};
+ byte _operatorParams[kOperatorCount][kParamCount]; // All operator parameters
-class ADLPlayer : public AdLib {
-public:
- ADLPlayer(Audio::Mixer &mixer);
- ~ADLPlayer();
+ uint16 _freqs[kPitchStepCount][kHalfToneCount];
+ uint16 *_freqPtr[kMaxVoiceCount];
- bool load(const char *fileName);
- bool load(byte *data, uint32 size, int index = -1);
+ int _halfToneOffset[kMaxVoiceCount];
- void unload();
-protected:
- void interpret();
+ void createOPL();
+ void initOPL();
void reset();
- void rewind();
+ void allOff();
- void setVoices();
- void setVoice(byte voice, byte instr, bool set);
-};
+ // Write global parameters into the OPL
+ void writeTremoloVibratoDepthPercMode();
+ void writeKeySplit();
-class MDYPlayer : public AdLib {
-public:
- MDYPlayer(Audio::Mixer &mixer);
- ~MDYPlayer();
-
- bool loadMDY(const char *fileName);
- bool loadMDY(Common::SeekableReadStream &stream);
- bool loadTBR(const char *fileName);
- bool loadTBR(Common::SeekableReadStream &stream);
-
- void unload();
-
-protected:
- byte _soundMode;
-
- byte *_timbres;
- uint16 _tbrCount;
- uint16 _tbrStart;
- uint32 _timbresSize;
+ // Write operator parameters into the OPL
+ void writeWaveSelect(uint8 oper);
+ void writeTremoloVibratoSustainingKeyScaleRateFreqMulti(uint8 oper);
+ void writeSustainRelease(uint8 oper);
+ void writeAttackDecay(uint8 oper);
+ void writeFeedbackFM(uint8 oper);
+ void writeKeyScaleLevelVolume(uint8 oper);
+ void writeAllParams(uint8 oper);
- void interpret();
+ void initOperatorParams();
+ void initOperatorVolumes();
+ void setOperatorParams(uint8 oper, const uint16 *params, uint8 wave);
- void reset();
- void rewind();
+ void voiceOff(uint8 voice);
- void setVoices();
- void setVoice(byte voice, byte instr, bool set);
+ void initFreqs();
+ void setFreqs(uint16 *freqs, int32 num, int32 denom);
+ int32 calcFreq(int32 deltaDemiToneNum, int32 deltaDemiToneDenom);
+ void resetFreqs();
- void unloadTBR();
- void unloadMDY();
+ void changePitch(uint8 voice, uint16 pitchBend);
-private:
- void init();
+ void setFreq(uint8 voice, uint16 note, bool on);
};
} // End of namespace Gob
diff --git a/engines/gob/sound/adlplayer.cpp b/engines/gob/sound/adlplayer.cpp
new file mode 100644
index 0000000000..ee23191c0d
--- /dev/null
+++ b/engines/gob/sound/adlplayer.cpp
@@ -0,0 +1,257 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/stream.h"
+#include "common/memstream.h"
+#include "common/textconsole.h"
+
+#include "gob/sound/adlplayer.h"
+
+namespace Gob {
+
+ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer),
+ _songData(0), _songDataSize(0), _playPos(0) {
+
+}
+
+ADLPlayer::~ADLPlayer() {
+ unload();
+}
+
+void ADLPlayer::unload() {
+ stopPlay();
+
+ _timbres.clear();
+
+ delete[] _songData;
+
+ _songData = 0;
+ _songDataSize = 0;
+
+ _playPos = 0;
+}
+
+uint32 ADLPlayer::pollMusic(bool first) {
+ if (_timbres.empty() || !_songData || !_playPos || (_playPos >= (_songData + _songDataSize))) {
+ end();
+ return 0;
+ }
+
+ // We'll ignore the first delay
+ if (first)
+ _playPos += (*_playPos & 0x80) ? 2 : 1;
+
+ byte cmd = *_playPos++;
+
+ // Song end marker
+ if (cmd == 0xFF) {
+ end();
+ return 0;
+ }
+
+ // Set the instrument that should be modified
+ if (cmd == 0xFE)
+ _modifyInstrument = *_playPos++;
+
+ if (cmd >= 0xD0) {
+ // Modify an instrument
+
+ if (_modifyInstrument == 0xFF)
+ warning("ADLPlayer: No instrument to modify");
+ else if (_modifyInstrument >= _timbres.size())
+ warning("ADLPlayer: Can't modify invalid instrument %d (%d)", _modifyInstrument, _timbres.size());
+ else
+ _timbres[_modifyInstrument].params[_playPos[0]] = _playPos[1];
+
+ _playPos += 2;
+
+ // If we currently have that instrument loaded, reload it
+ for (int i = 0; i < kMaxVoiceCount; i++)
+ if (_currentInstruments[i] == _modifyInstrument)
+ setInstrument(i, _modifyInstrument);
+ } else {
+ // Voice command
+
+ uint8 voice = cmd & 0x0F;
+ uint8 note, volume;
+
+ switch (cmd & 0xF0) {
+ case 0x00: // Note on with volume
+ note = *_playPos++;
+ volume = *_playPos++;
+
+ setVoiceVolume(voice, volume);
+ noteOn(voice, note);
+ break;
+
+ case 0xA0: // Pitch bend
+ bendVoicePitch(voice, ((uint16)*_playPos++) << 7);
+ break;
+
+ case 0xB0: // Set volume
+ setVoiceVolume(voice, *_playPos++);
+ break;
+
+ case 0xC0: // Set instrument
+ setInstrument(voice, *_playPos++);
+ break;
+
+ case 0x90: // Note on
+ noteOn(voice, *_playPos++);
+ break;
+
+ case 0x80: // Note off
+ noteOff(voice);
+ break;
+
+ default:
+ warning("ADLPlayer: Unsupported command: 0x%02X. Stopping playback.", cmd);
+ end(true);
+ return 0;
+ }
+ }
+
+ uint16 delay = *_playPos++;
+
+ if (delay & 0x80)
+ delay = ((delay & 3) << 8) | *_playPos++;
+
+ return getSampleDelay(delay);
+}
+
+uint32 ADLPlayer::getSampleDelay(uint16 delay) const {
+ if (delay == 0)
+ return 0;
+
+ return ((uint32)delay * getSamplesPerSecond()) / 1000;
+}
+
+void ADLPlayer::rewind() {
+ // Reset song data
+ _playPos = _songData;
+
+ // Set melody/percussion mode
+ setPercussionMode(_soundMode != 0);
+
+ // Reset instruments
+ for (Common::Array<Timbre>::iterator t = _timbres.begin(); t != _timbres.end(); ++t)
+ memcpy(t->params, t->startParams, kOperatorsPerVoice * kParamCount * sizeof(uint16));
+
+ for (int i = 0; i < kMaxVoiceCount; i++)
+ _currentInstruments[i] = 0;
+
+ // Reset voices
+ int numVoice = MIN<int>(_timbres.size(), _soundMode ? (int)kMaxVoiceCount : (int)kMelodyVoiceCount);
+ for (int i = 0; i < numVoice; i++) {
+ setInstrument(i, _currentInstruments[i]);
+ setVoiceVolume(i, kMaxVolume);
+ }
+
+ _modifyInstrument = 0xFF;
+}
+
+bool ADLPlayer::load(Common::SeekableReadStream &adl) {
+ unload();
+
+ int timbreCount;
+ if (!readHeader(adl, timbreCount)) {
+ unload();
+ return false;
+ }
+
+ if (!readTimbres(adl, timbreCount) || !readSongData(adl) || adl.err()) {
+ unload();
+ return false;
+ }
+
+ rewind();
+
+ return true;
+}
+
+bool ADLPlayer::readHeader(Common::SeekableReadStream &adl, int &timbreCount) {
+ // Sanity check
+ if (adl.size() < 60) {
+ warning("ADLPlayer::readHeader(): File too small (%d)", adl.size());
+ return false;
+ }
+
+ _soundMode = adl.readByte();
+ timbreCount = adl.readByte() + 1;
+
+ adl.skip(1);
+
+ return true;
+}
+
+bool ADLPlayer::readTimbres(Common::SeekableReadStream &adl, int timbreCount) {
+ _timbres.resize(timbreCount);
+ for (Common::Array<Timbre>::iterator t = _timbres.begin(); t != _timbres.end(); ++t) {
+ for (int i = 0; i < (kOperatorsPerVoice * kParamCount); i++)
+ t->startParams[i] = adl.readUint16LE();
+ }
+
+ if (adl.err()) {
+ warning("ADLPlayer::readTimbres(): Read failed");
+ return false;
+ }
+
+ return true;
+}
+
+bool ADLPlayer::readSongData(Common::SeekableReadStream &adl) {
+ _songDataSize = adl.size() - adl.pos();
+ _songData = new byte[_songDataSize];
+
+ if (adl.read(_songData, _songDataSize) != _songDataSize) {
+ warning("ADLPlayer::readSongData(): Read failed");
+ return false;
+ }
+
+ return true;
+}
+
+bool ADLPlayer::load(const byte *data, uint32 dataSize, int index) {
+ unload();
+
+ Common::MemoryReadStream stream(data, dataSize);
+ if (!load(stream))
+ return false;
+
+ _index = index;
+ return true;
+}
+
+void ADLPlayer::setInstrument(int voice, int instrument) {
+ if ((voice >= kMaxVoiceCount) || ((uint)instrument >= _timbres.size()))
+ return;
+
+ _currentInstruments[voice] = instrument;
+
+ setVoiceTimbre(voice, _timbres[instrument].params);
+}
+
+int ADLPlayer::getIndex() const {
+ return _index;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/adlplayer.h b/engines/gob/sound/adlplayer.h
new file mode 100644
index 0000000000..9596447bbc
--- /dev/null
+++ b/engines/gob/sound/adlplayer.h
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_SOUND_ADLPLAYER_H
+#define GOB_SOUND_ADLPLAYER_H
+
+#include "common/array.h"
+
+#include "gob/sound/adlib.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Gob {
+
+/** A player for Coktel Vision's ADL music format. */
+class ADLPlayer : public AdLib {
+public:
+ ADLPlayer(Audio::Mixer &mixer);
+ ~ADLPlayer();
+
+ bool load(Common::SeekableReadStream &adl);
+ bool load(const byte *data, uint32 dataSize, int index = -1);
+ void unload();
+
+ int getIndex() const;
+
+protected:
+ // AdLib interface
+ uint32 pollMusic(bool first);
+ void rewind();
+
+private:
+ struct Timbre {
+ uint16 startParams[kOperatorsPerVoice * kParamCount];
+ uint16 params[kOperatorsPerVoice * kParamCount];
+ };
+
+ uint8 _soundMode;
+
+ Common::Array<Timbre> _timbres;
+
+ byte *_songData;
+ uint32 _songDataSize;
+
+ const byte *_playPos;
+
+ int _index;
+
+ uint8 _modifyInstrument;
+ uint16 _currentInstruments[kMaxVoiceCount];
+
+
+ void setInstrument(int voice, int instrument);
+
+ bool readHeader (Common::SeekableReadStream &adl, int &timbreCount);
+ bool readTimbres (Common::SeekableReadStream &adl, int timbreCount);
+ bool readSongData(Common::SeekableReadStream &adl);
+
+ uint32 getSampleDelay(uint16 delay) const;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_ADLPLAYER_H
diff --git a/engines/gob/sound/musplayer.cpp b/engines/gob/sound/musplayer.cpp
new file mode 100644
index 0000000000..3e41dc6ed1
--- /dev/null
+++ b/engines/gob/sound/musplayer.cpp
@@ -0,0 +1,391 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/stream.h"
+#include "common/textconsole.h"
+
+#include "gob/sound/musplayer.h"
+
+namespace Gob {
+
+MUSPlayer::MUSPlayer(Audio::Mixer &mixer) : AdLib(mixer),
+ _songData(0), _songDataSize(0), _playPos(0), _songID(0) {
+
+}
+
+MUSPlayer::~MUSPlayer() {
+ unload();
+}
+
+void MUSPlayer::unload() {
+ stopPlay();
+
+ unloadSND();
+ unloadMUS();
+}
+
+uint32 MUSPlayer::getSampleDelay(uint16 delay) const {
+ if (delay == 0)
+ return 0;
+
+ uint32 freq = (_ticksPerBeat * _tempo) / 60;
+
+ return ((uint32)delay * getSamplesPerSecond()) / freq;
+}
+
+void MUSPlayer::skipToTiming() {
+ while (*_playPos < 0x80)
+ _playPos++;
+
+ if (*_playPos != 0xF8)
+ _playPos--;
+}
+
+uint32 MUSPlayer::pollMusic(bool first) {
+ if (_timbres.empty() || !_songData || !_playPos || (_playPos >= (_songData + _songDataSize))) {
+ end();
+ return 0;
+ }
+
+ if (first)
+ return getSampleDelay(*_playPos++);
+
+ uint16 delay = 0;
+ while (delay == 0) {
+ byte cmd = *_playPos;
+
+ // Delay overflow
+ if (cmd == 0xF8) {
+ _playPos++;
+ delay = 0xF8;
+ break;
+ }
+
+ // Song end marker
+ if (cmd == 0xFC) {
+ end();
+ return 0;
+ }
+
+ // Global command
+ if (cmd == 0xF0) {
+ _playPos++;
+
+ byte type1 = *_playPos++;
+ byte type2 = *_playPos++;
+
+ if ((type1 == 0x7F) && (type2 == 0)) {
+ // Tempo change, as a fraction of the base tempo
+
+ uint32 num = *_playPos++;
+ uint32 denom = *_playPos++;
+
+ _tempo = _baseTempo * num + ((_baseTempo * denom) >> 7);
+
+ _playPos++;
+ } else {
+
+ // Unsupported global command, skip it
+ _playPos -= 2;
+ while(*_playPos++ != 0xF7)
+ ;
+ }
+
+ delay = *_playPos++;
+ break;
+ }
+
+ // Voice command
+
+ if (cmd >= 0x80) {
+ _playPos++;
+
+ _lastCommand = cmd;
+ } else
+ cmd = _lastCommand;
+
+ uint8 voice = cmd & 0x0F;
+ uint8 note, volume;
+ uint16 pitch;
+
+ switch (cmd & 0xF0) {
+ case 0x80: // Note off
+ _playPos += 2;
+ noteOff(voice);
+ break;
+
+ case 0x90: // Note on
+ note = *_playPos++;
+ volume = *_playPos++;
+
+ if (volume) {
+ setVoiceVolume(voice, volume);
+ noteOn(voice, note);
+ } else
+ noteOff(voice);
+ break;
+
+ case 0xA0: // Set volume
+ setVoiceVolume(voice, *_playPos++);
+ break;
+
+ case 0xB0:
+ _playPos += 2;
+ break;
+
+ case 0xC0: // Set instrument
+ setInstrument(voice, *_playPos++);
+ break;
+
+ case 0xD0:
+ _playPos++;
+ break;
+
+ case 0xE0: // Pitch bend
+ pitch = *_playPos++;
+ pitch += *_playPos++ << 7;
+ bendVoicePitch(voice, pitch);
+ break;
+
+ default:
+ warning("MUSPlayer: Unsupported command: 0x%02X", cmd);
+ skipToTiming();
+ break;
+ }
+
+ delay = *_playPos++;
+ }
+
+ if (delay == 0xF8) {
+ delay = 240;
+
+ if (*_playPos != 0xF8)
+ delay += *_playPos++;
+ }
+
+ return getSampleDelay(delay);
+}
+
+void MUSPlayer::rewind() {
+ _playPos = _songData;
+ _tempo = _baseTempo;
+
+ _lastCommand = 0;
+
+ setPercussionMode(_soundMode != 0);
+ setPitchRange(_pitchBendRange);
+}
+
+bool MUSPlayer::loadSND(Common::SeekableReadStream &snd) {
+ unloadSND();
+
+ int timbreCount, timbrePos;
+ if (!readSNDHeader(snd, timbreCount, timbrePos))
+ return false;
+
+ if (!readSNDTimbres(snd, timbreCount, timbrePos) || snd.err()) {
+ unloadSND();
+ return false;
+ }
+
+ return true;
+}
+
+bool MUSPlayer::readString(Common::SeekableReadStream &stream, Common::String &string, byte *buffer, uint size) {
+ if (stream.read(buffer, size) != size)
+ return false;
+
+ buffer[size] = '\0';
+
+ string = (char *) buffer;
+
+ return true;
+}
+
+bool MUSPlayer::readSNDHeader(Common::SeekableReadStream &snd, int &timbreCount, int &timbrePos) {
+ // Sanity check
+ if (snd.size() <= 6) {
+ warning("MUSPlayer::readSNDHeader(): File too small (%d)", snd.size());
+ return false;
+ }
+
+ // Version
+ const uint8 versionMajor = snd.readByte();
+ const uint8 versionMinor = snd.readByte();
+
+ if ((versionMajor != 1) && (versionMinor != 0)) {
+ warning("MUSPlayer::readSNDHeader(): Unsupported version %d.%d", versionMajor, versionMinor);
+ return false;
+ }
+
+ // Number of timbres and where they start
+ timbreCount = snd.readUint16LE();
+ timbrePos = snd.readUint16LE();
+
+ const uint16 minTimbrePos = 6 + timbreCount * 9;
+
+ // Sanity check
+ if (timbrePos < minTimbrePos) {
+ warning("MUSPlayer::readSNDHeader(): Timbre offset too small: %d < %d", timbrePos, minTimbrePos);
+ return false;
+ }
+
+ const uint32 timbreParametersSize = snd.size() - timbrePos;
+ const uint32 paramSize = kOperatorsPerVoice * kParamCount * sizeof(uint16);
+
+ // Sanity check
+ if (timbreParametersSize != (timbreCount * paramSize)) {
+ warning("MUSPlayer::loadSND(): Timbre parameters size mismatch: %d != %d",
+ timbreParametersSize, timbreCount * paramSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool MUSPlayer::readSNDTimbres(Common::SeekableReadStream &snd, int timbreCount, int timbrePos) {
+ _timbres.resize(timbreCount);
+
+ // Read names
+ byte nameBuffer[10];
+ for (Common::Array<Timbre>::iterator t = _timbres.begin(); t != _timbres.end(); ++t) {
+ if (!readString(snd, t->name, nameBuffer, 9)) {
+ warning("MUSPlayer::readMUSTimbres(): Failed to read timbre name");
+ return false;
+ }
+ }
+
+ if (!snd.seek(timbrePos)) {
+ warning("MUSPlayer::readMUSTimbres(): Failed to seek to timbres");
+ return false;
+ }
+
+ // Read parameters
+ for (Common::Array<Timbre>::iterator t = _timbres.begin(); t != _timbres.end(); ++t) {
+ for (int i = 0; i < (kOperatorsPerVoice * kParamCount); i++)
+ t->params[i] = snd.readUint16LE();
+ }
+
+ return true;
+}
+
+bool MUSPlayer::loadMUS(Common::SeekableReadStream &mus) {
+ unloadMUS();
+
+ if (!readMUSHeader(mus) || !readMUSSong(mus) || mus.err()) {
+ unloadMUS();
+ return false;
+ }
+
+ rewind();
+
+ return true;
+}
+
+bool MUSPlayer::readMUSHeader(Common::SeekableReadStream &mus) {
+ // Sanity check
+ if (mus.size() <= 6)
+ return false;
+
+ // Version
+ const uint8 versionMajor = mus.readByte();
+ const uint8 versionMinor = mus.readByte();
+
+ if ((versionMajor != 1) && (versionMinor != 0)) {
+ warning("MUSPlayer::readMUSHeader(): Unsupported version %d.%d", versionMajor, versionMinor);
+ return false;
+ }
+
+ _songID = mus.readUint32LE();
+
+ byte nameBuffer[31];
+ if (!readString(mus, _songName, nameBuffer, 30)) {
+ warning("MUSPlayer::readMUSHeader(): Failed to read the song name");
+ return false;
+ }
+
+ _ticksPerBeat = mus.readByte();
+ _beatsPerMeasure = mus.readByte();
+
+ mus.skip(4); // Length of song in ticks
+
+ _songDataSize = mus.readUint32LE();
+
+ mus.skip(4); // Number of commands
+ mus.skip(8); // Unused
+
+ _soundMode = mus.readByte();
+ _pitchBendRange = mus.readByte();
+ _baseTempo = mus.readUint16LE();
+
+ mus.skip(8); // Unused
+
+ return true;
+}
+
+bool MUSPlayer::readMUSSong(Common::SeekableReadStream &mus) {
+ const uint32 realSongDataSize = mus.size() - mus.pos();
+
+ if (realSongDataSize < _songDataSize) {
+ warning("MUSPlayer::readMUSSong(): File too small for the song data: %d < %d", realSongDataSize, _songDataSize);
+ return false;
+ }
+
+ _songData = new byte[_songDataSize];
+
+ if (mus.read(_songData, _songDataSize) != _songDataSize) {
+ warning("MUSPlayer::readMUSSong(): Read failed");
+ return false;
+ }
+
+ return true;
+}
+
+void MUSPlayer::unloadSND() {
+ _timbres.clear();
+}
+
+void MUSPlayer::unloadMUS() {
+ delete[] _songData;
+
+ _songData = 0;
+ _songDataSize = 0;
+
+ _playPos = 0;
+}
+
+uint32 MUSPlayer::getSongID() const {
+ return _songID;
+}
+
+const Common::String &MUSPlayer::getSongName() const {
+ return _songName;
+}
+
+void MUSPlayer::setInstrument(uint8 voice, uint8 instrument) {
+ if (instrument >= _timbres.size())
+ return;
+
+ setVoiceTimbre(voice, _timbres[instrument].params);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/musplayer.h b/engines/gob/sound/musplayer.h
new file mode 100644
index 0000000000..6cc2a2d2ca
--- /dev/null
+++ b/engines/gob/sound/musplayer.h
@@ -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 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_SOUND_MUSPLAYER_H
+#define GOB_SOUND_MUSPLAYER_H
+
+#include "common/str.h"
+#include "common/array.h"
+
+#include "gob/sound/adlib.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Gob {
+
+/** A player for the AdLib MUS format, with the instrument information in SND files.
+ *
+ * In the Gob engine, those files are usually named .MDY and .TBR instead.
+ */
+class MUSPlayer : public AdLib {
+public:
+ MUSPlayer(Audio::Mixer &mixer);
+ ~MUSPlayer();
+
+ /** Load the instruments (.SND or .TBR) */
+ bool loadSND(Common::SeekableReadStream &snd);
+ /** Load the melody (.MUS or .MDY) */
+ bool loadMUS(Common::SeekableReadStream &mus);
+
+ void unload();
+
+ uint32 getSongID() const;
+ const Common::String &getSongName() const;
+
+protected:
+ // AdLib interface
+ uint32 pollMusic(bool first);
+ void rewind();
+
+private:
+ struct Timbre {
+ Common::String name;
+
+ uint16 params[kOperatorsPerVoice * kParamCount];
+ };
+
+ Common::Array<Timbre> _timbres;
+
+ byte *_songData;
+ uint32 _songDataSize;
+
+ const byte *_playPos;
+
+ uint32 _songID;
+ Common::String _songName;
+
+ uint8 _ticksPerBeat;
+ uint8 _beatsPerMeasure;
+
+ uint8 _soundMode;
+ uint8 _pitchBendRange;
+
+ uint16 _baseTempo;
+
+ uint16 _tempo;
+
+ byte _lastCommand;
+
+
+ void unloadSND();
+ void unloadMUS();
+
+ bool readSNDHeader (Common::SeekableReadStream &snd, int &timbreCount, int &timbrePos);
+ bool readSNDTimbres(Common::SeekableReadStream &snd, int timbreCount, int timbrePos);
+
+ bool readMUSHeader(Common::SeekableReadStream &mus);
+ bool readMUSSong (Common::SeekableReadStream &mus);
+
+ uint32 getSampleDelay(uint16 delay) const;
+ void setInstrument(uint8 voice, uint8 instrument);
+ void skipToTiming();
+
+ static bool readString(Common::SeekableReadStream &stream, Common::String &string, byte *buffer, uint size);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_MUSPLAYER_H
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index bfe0394390..63af6aeef4 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -30,7 +30,8 @@
#include "gob/sound/pcspeaker.h"
#include "gob/sound/soundblaster.h"
-#include "gob/sound/adlib.h"
+#include "gob/sound/adlplayer.h"
+#include "gob/sound/musplayer.h"
#include "gob/sound/infogrames.h"
#include "gob/sound/protracker.h"
#include "gob/sound/cdrom.h"
@@ -50,6 +51,8 @@ Sound::Sound(GobEngine *vm) : _vm(vm) {
_hasAdLib = (!_vm->_noMusic && _vm->hasAdLib());
+ _hasAdLibBg = _hasAdLib;
+
if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga)) {
_infogrames = new Infogrames(*_vm->_mixer);
_protracker = new Protracker(*_vm->_mixer);
@@ -106,7 +109,7 @@ int Sound::sampleGetNextFreeSlot() const {
return -1;
}
-bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName, bool tryExist) {
+bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName) {
if (!sndDesc)
return false;
@@ -114,12 +117,15 @@ bool Sound::sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName,
int32 size;
byte *data = _vm->_dataIO->getFile(fileName, size);
- if (!data) {
- warning("Can't open sample file \"%s\"", fileName);
+
+ if (!data || !sndDesc->load(type, data, size)) {
+ delete data;
+
+ warning("Sound::sampleLoad(): Failed to load sound \"%s\"", fileName);
return false;
}
- return sndDesc->load(type, data, size);
+ return true;
}
void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdLib, int index) {
@@ -131,10 +137,7 @@ void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdLib, int index) {
if (noteAdLib) {
if (_adlPlayer)
if ((index == -1) || (_adlPlayer->getIndex() == index))
- _adlPlayer->stopPlay();
- if (_mdyPlayer)
- if ((index == -1) || (_mdyPlayer->getIndex() == index))
- _mdyPlayer->stopPlay();
+ _adlPlayer->unload();
}
} else {
@@ -235,7 +238,17 @@ bool Sound::adlibLoadADL(const char *fileName) {
debugC(1, kDebugSound, "AdLib: Loading ADL data (\"%s\")", fileName);
- return _adlPlayer->load(fileName);
+ Common::SeekableReadStream *stream = _vm->_dataIO->getFile(fileName);
+ if (!stream) {
+ warning("Can't open ADL file \"%s\"", fileName);
+ return false;
+ }
+
+ bool loaded = _adlPlayer->load(*stream);
+
+ delete stream;
+
+ return loaded;
}
bool Sound::adlibLoadADL(byte *data, uint32 size, int index) {
@@ -266,8 +279,7 @@ bool Sound::adlibLoadMDY(const char *fileName) {
if (!_hasAdLib)
return false;
- if (!_mdyPlayer)
- _mdyPlayer = new MDYPlayer(*_vm->_mixer);
+ createMDYPlayer();
debugC(1, kDebugSound, "AdLib: Loading MDY data (\"%s\")", fileName);
@@ -277,7 +289,7 @@ bool Sound::adlibLoadMDY(const char *fileName) {
return false;
}
- bool loaded = _mdyPlayer->loadMDY(*stream);
+ bool loaded = _mdyPlayer->loadMUS(*stream);
delete stream;
@@ -288,8 +300,7 @@ bool Sound::adlibLoadTBR(const char *fileName) {
if (!_hasAdLib)
return false;
- if (!_mdyPlayer)
- _mdyPlayer = new MDYPlayer(*_vm->_mixer);
+ createMDYPlayer();
Common::SeekableReadStream *stream = _vm->_dataIO->getFile(fileName);
if (!stream) {
@@ -299,7 +310,7 @@ bool Sound::adlibLoadTBR(const char *fileName) {
debugC(1, kDebugSound, "AdLib: Loading MDY instruments (\"%s\")", fileName);
- bool loaded = _mdyPlayer->loadTBR(*stream);
+ bool loaded = _mdyPlayer->loadSND(*stream);
delete stream;
@@ -310,28 +321,23 @@ void Sound::adlibPlayTrack(const char *trackname) {
if (!_hasAdLib)
return;
- if (!_adlPlayer)
- _adlPlayer = new ADLPlayer(*_vm->_mixer);
+ createADLPlayer();
if (_adlPlayer->isPlaying())
return;
- debugC(1, kDebugSound, "AdLib: Playing ADL track \"%s\"", trackname);
-
- _adlPlayer->unload();
- _adlPlayer->load(trackname);
- _adlPlayer->startPlay();
+ if (adlibLoadADL(trackname))
+ adlibPlay();
}
void Sound::adlibPlayBgMusic() {
- if (!_hasAdLib)
+ if (!_hasAdLib || _hasAdLibBg)
return;
- if (!_adlPlayer)
- _adlPlayer = new ADLPlayer(*_vm->_mixer);
+ createADLPlayer();
static const char *const tracksMac[] = {
-// "musmac1.adl", // TODO: This track isn't played correctly at all yet
+// "musmac1.adl", // This track seems to be missing instruments...
"musmac2.adl",
"musmac3.adl",
"musmac4.adl",
@@ -347,13 +353,18 @@ void Sound::adlibPlayBgMusic() {
"musmac5.mid"
};
- if (_vm->getPlatform() == Common::kPlatformWindows) {
- int track = _vm->_util->getRandom(ARRAYSIZE(tracksWin));
- adlibPlayTrack(tracksWin[track]);
- } else {
- int track = _vm->_util->getRandom(ARRAYSIZE(tracksMac));
- adlibPlayTrack(tracksMac[track]);
+ const char *track = 0;
+ if (_vm->getPlatform() == Common::kPlatformWindows)
+ track = tracksWin[_vm->_util->getRandom(ARRAYSIZE(tracksWin))];
+ else
+ track = tracksMac[_vm->_util->getRandom(ARRAYSIZE(tracksMac))];
+
+ if (!track || !_vm->_dataIO->hasFile(track)) {
+ _hasAdLibBg = false;
+ return;
}
+
+ adlibPlayTrack(track);
}
void Sound::adlibPlay() {
@@ -398,13 +409,11 @@ int Sound::adlibGetIndex() const {
if (_adlPlayer)
return _adlPlayer->getIndex();
- if (_mdyPlayer)
- return _mdyPlayer->getIndex();
return -1;
}
-bool Sound::adlibGetRepeating() const {
+int32 Sound::adlibGetRepeating() const {
if (!_hasAdLib)
return false;
@@ -439,6 +448,10 @@ void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount,
_blaster->playSample(*sndDesc, repCount, frequency, fadeLength);
}
+void Sound::blasterRepeatComposition(int32 repCount) {
+ _blaster->repeatComposition(repCount);
+}
+
void Sound::blasterStop(int16 fadeLength, SoundDesc *sndDesc) {
if (!_blaster)
return;
@@ -448,7 +461,7 @@ void Sound::blasterStop(int16 fadeLength, SoundDesc *sndDesc) {
_blaster->stopSound(fadeLength, sndDesc);
}
-void Sound::blasterPlayComposition(int16 *composition, int16 freqVal,
+void Sound::blasterPlayComposition(const int16 *composition, int16 freqVal,
SoundDesc *sndDescs, int8 sndCount) {
if (!_blaster)
return;
@@ -719,4 +732,24 @@ void Sound::bgUnshade() {
_bgatmos->unshade();
}
+void Sound::createMDYPlayer() {
+ if (_mdyPlayer)
+ return;
+
+ delete _adlPlayer;
+ _adlPlayer = 0;
+
+ _mdyPlayer = new MUSPlayer(*_vm->_mixer);
+}
+
+void Sound::createADLPlayer() {
+ if (_adlPlayer)
+ return;
+
+ delete _mdyPlayer;
+ _mdyPlayer= 0;
+
+ _adlPlayer = new ADLPlayer(*_vm->_mixer);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h
index 585cf36703..bbc182d172 100644
--- a/engines/gob/sound/sound.h
+++ b/engines/gob/sound/sound.h
@@ -32,7 +32,7 @@ class GobEngine;
class PCSpeaker;
class SoundBlaster;
class ADLPlayer;
-class MDYPlayer;
+class MUSPlayer;
class Infogrames;
class Protracker;
class CDROM;
@@ -51,7 +51,7 @@ public:
const SoundDesc *sampleGetBySlot(int slot) const;
int sampleGetNextFreeSlot() const;
- bool sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName, bool tryExist = true);
+ bool sampleLoad(SoundDesc *sndDesc, SoundType type, const char *fileName);
void sampleFree(SoundDesc *sndDesc, bool noteAdLib = false, int index = -1);
@@ -60,9 +60,10 @@ public:
int16 frequency, int16 fadeLength = 0);
void blasterStop(int16 fadeLength, SoundDesc *sndDesc = 0);
- void blasterPlayComposition(int16 *composition, int16 freqVal,
+ void blasterPlayComposition(const int16 *composition, int16 freqVal,
SoundDesc *sndDescs = 0, int8 sndCount = kSoundsCount);
void blasterStopComposition();
+ void blasterRepeatComposition(int32 repCount);
char blasterPlayingSound() const;
@@ -92,7 +93,7 @@ public:
bool adlibIsPlaying() const;
int adlibGetIndex() const;
- bool adlibGetRepeating() const;
+ int32 adlibGetRepeating() const;
void adlibSetRepeating(int32 repCount);
@@ -142,17 +143,30 @@ private:
GobEngine *_vm;
bool _hasAdLib;
+ bool _hasAdLibBg;
SoundDesc _sounds[kSoundsCount];
+ // Speaker
PCSpeaker *_pcspeaker;
+
+ // PCM based
SoundBlaster *_blaster;
+ BackgroundAtmosphere *_bgatmos;
+
+ // AdLib
+ MUSPlayer *_mdyPlayer;
ADLPlayer *_adlPlayer;
- MDYPlayer *_mdyPlayer;
+
+ // Amiga Paula
Infogrames *_infogrames;
Protracker *_protracker;
+
+ // Audio CD
CDROM *_cdrom;
- BackgroundAtmosphere *_bgatmos;
+
+ void createMDYPlayer();
+ void createADLPlayer();
};
} // End of namespace Gob
diff --git a/engines/gob/sound/soundblaster.cpp b/engines/gob/sound/soundblaster.cpp
index 4ff555b0e3..f267eee32d 100644
--- a/engines/gob/sound/soundblaster.cpp
+++ b/engines/gob/sound/soundblaster.cpp
@@ -31,6 +31,8 @@ SoundBlaster::SoundBlaster(Audio::Mixer &mixer) : SoundMixer(mixer, Audio::Mixer
_compositionSamples = 0;
_compositionSampleCount = 0;
_compositionPos = -1;
+
+ _compositionRepCount = 0;
}
SoundBlaster::~SoundBlaster() {
@@ -47,6 +49,8 @@ void SoundBlaster::stopSound(int16 fadeLength, SoundDesc *sndDesc) {
if (sndDesc && (sndDesc != _curSoundDesc))
return;
+ _compositionRepCount = 0;
+
if (fadeLength <= 0)
_curSoundDesc = 0;
@@ -62,6 +66,7 @@ void SoundBlaster::stopComposition() {
void SoundBlaster::endComposition() {
_compositionPos = -1;
+ _compositionRepCount = 0;
}
void SoundBlaster::nextCompositionPos() {
@@ -79,10 +84,11 @@ void SoundBlaster::nextCompositionPos() {
if (_compositionPos == 49)
_compositionPos = -1;
}
+
_compositionPos = -1;
}
-void SoundBlaster::playComposition(int16 *composition, int16 freqVal,
+void SoundBlaster::playComposition(const int16 *composition, int16 freqVal,
SoundDesc *sndDescs, int8 sndCount) {
_compositionSamples = sndDescs;
@@ -98,6 +104,10 @@ void SoundBlaster::playComposition(int16 *composition, int16 freqVal,
nextCompositionPos();
}
+void SoundBlaster::repeatComposition(int32 repCount) {
+ _compositionRepCount = repCount;
+}
+
void SoundBlaster::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
int16 fadeLength) {
@@ -106,10 +116,21 @@ void SoundBlaster::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency
}
void SoundBlaster::checkEndSample() {
- if (_compositionPos != -1)
+ if (_compositionPos != -1) {
nextCompositionPos();
- else
- SoundMixer::checkEndSample();
+ return;
+ }
+
+ if (_compositionRepCount != 0) {
+ if (_compositionRepCount > 0)
+ _compositionRepCount--;
+
+ nextCompositionPos();
+ if (_compositionPos != -1)
+ return;
+ }
+
+ SoundMixer::checkEndSample();
}
void SoundBlaster::endFade() {
diff --git a/engines/gob/sound/soundblaster.h b/engines/gob/sound/soundblaster.h
index c2704c5482..3c4968d611 100644
--- a/engines/gob/sound/soundblaster.h
+++ b/engines/gob/sound/soundblaster.h
@@ -41,11 +41,13 @@ public:
int16 frequency, int16 fadeLength = 0);
void stopSound(int16 fadeLength, SoundDesc *sndDesc = 0);
- void playComposition(int16 *composition, int16 freqVal,
+ void playComposition(const int16 *composition, int16 freqVal,
SoundDesc *sndDescs = 0, int8 sndCount = 60);
void stopComposition();
void endComposition();
+ void repeatComposition(int32 repCount);
+
protected:
Common::Mutex _mutex;
@@ -54,6 +56,8 @@ protected:
int16 _composition[50];
int8 _compositionPos;
+ int32 _compositionRepCount;
+
SoundDesc *_curSoundDesc;
void setSample(SoundDesc &sndDesc, int16 repCount,
diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp
index e294209ed7..afbb7c3bae 100644
--- a/engines/gob/surface.cpp
+++ b/engines/gob/surface.cpp
@@ -280,6 +280,18 @@ Surface::Surface(uint16 width, uint16 height, uint8 bpp, byte *vidMem) :
_ownVidMem = false;
}
+Surface::Surface(uint16 width, uint16 height, uint8 bpp, const byte *vidMem) :
+ _width(width), _height(height), _bpp(bpp), _vidMem(0) {
+
+ assert((_width > 0) && (_height > 0));
+ assert((_bpp == 1) || (_bpp == 2));
+
+ _vidMem = new byte[_bpp * _width * _height];
+ _ownVidMem = true;
+
+ memcpy(_vidMem, vidMem, _bpp * _width * _height);
+}
+
Surface::~Surface() {
if (_ownVidMem)
delete[] _vidMem;
@@ -672,6 +684,12 @@ void Surface::shadeRect(uint16 left, uint16 top, uint16 right, uint16 bottom,
}
+void Surface::recolor(uint8 from, uint8 to) {
+ for (Pixel p = get(); p.isValid(); ++p)
+ if (p.get() == from)
+ p.set(to);
+}
+
void Surface::putPixel(uint16 x, uint16 y, uint32 color) {
if ((x >= _width) || (y >= _height))
return;
@@ -683,6 +701,34 @@ void Surface::drawLine(uint16 x0, uint16 y0, uint16 x1, uint16 y1, uint32 color)
Graphics::drawLine(x0, y0, x1, y1, color, &plotPixel, this);
}
+void Surface::drawRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uint32 color) {
+ // Just in case those are swapped
+ if (left > right)
+ SWAP(left, right);
+ if (top > bottom)
+ SWAP(top, bottom);
+
+ if ((left >= _width) || (top >= _height))
+ // Nothing to do
+ return;
+
+ // Area to actually draw
+ const uint16 width = CLIP<int32>(right - left + 1, 0, _width - left);
+ const uint16 height = CLIP<int32>(bottom - top + 1, 0, _height - top);
+
+ if ((width == 0) || (height == 0))
+ // Nothing to do
+ return;
+
+ right = left + width - 1;
+ bottom = top + height - 1;
+
+ drawLine(left , top , left , bottom, color);
+ drawLine(right, top , right, bottom, color);
+ drawLine(left , top , right, top , color);
+ drawLine(left , bottom, right, bottom, color);
+}
+
/*
* The original's version of the Bresenham Algorithm was a bit "unclean"
* and produced strange edges at 45, 135, 225 and 315 degrees, so using the
diff --git a/engines/gob/surface.h b/engines/gob/surface.h
index 866e63490f..8f895a7910 100644
--- a/engines/gob/surface.h
+++ b/engines/gob/surface.h
@@ -122,6 +122,7 @@ private:
class Surface {
public:
Surface(uint16 width, uint16 height, uint8 bpp, byte *vidMem = 0);
+ Surface(uint16 width, uint16 height, uint8 bpp, const byte *vidMem);
~Surface();
uint16 getWidth () const;
@@ -155,8 +156,11 @@ public:
void shadeRect(uint16 left, uint16 top, uint16 right, uint16 bottom,
uint32 color, uint8 strength);
+ void recolor(uint8 from, uint8 to);
+
void putPixel(uint16 x, uint16 y, uint32 color);
void drawLine(uint16 x0, uint16 y0, uint16 x1, uint16 y1, uint32 color);
+ void drawRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uint32 color);
void drawCircle(uint16 x0, uint16 y0, uint16 radius, uint32 color, int16 pattern = 0);
void blitToScreen(uint16 left, uint16 top, uint16 right, uint16 bottom, uint16 x, uint16 y) const;
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 7f9c6131fd..5ac4ef024e 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -21,7 +21,6 @@
*/
#include "common/stream.h"
-#include "common/events.h"
#include "graphics/palette.h"
@@ -45,6 +44,8 @@ Util::Util(GobEngine *vm) : _vm(vm) {
_frameRate = 12;
_frameWaitTime = 0;
_startFrameTime = 0;
+
+ _keyState = 0;
}
uint32 Util::getTimeKey() {
@@ -116,6 +117,8 @@ void Util::processInput(bool scroll) {
_mouseButtons = (MouseButtons) (((uint32) _mouseButtons) & ~((uint32) kMouseButtonsRight));
break;
case Common::EVENT_KEYDOWN:
+ keyDown(event);
+
if (event.kbd.hasFlags(Common::KBD_CTRL)) {
if (event.kbd.keycode == Common::KEYCODE_f)
_fastMode ^= 1;
@@ -132,6 +135,7 @@ void Util::processInput(bool scroll) {
addKeyToBuffer(event.kbd);
break;
case Common::EVENT_KEYUP:
+ keyUp(event);
break;
default:
break;
@@ -185,12 +189,27 @@ bool Util::getKeyFromBuffer(Common::KeyState &key) {
return true;
}
+static const uint16 kLatin1ToCP850[] = {
+ 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5, 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,
+ 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA, 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,
+ 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80, 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,
+ 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E, 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1,
+ 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87, 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,
+ 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6, 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98
+};
+
+int16 Util::toCP850(uint16 latin1) {
+ if ((latin1 < 0xA0) || ((latin1 - 0xA0) >= ARRAYSIZE(kLatin1ToCP850)))
+ return 0;
+
+ return kLatin1ToCP850[latin1 - 0xA0];
+}
+
int16 Util::translateKey(const Common::KeyState &key) {
static struct keyS {
int16 from;
int16 to;
} keys[] = {
- {Common::KEYCODE_INVALID, kKeyNone },
{Common::KEYCODE_BACKSPACE, kKeyBackspace},
{Common::KEYCODE_SPACE, kKeySpace },
{Common::KEYCODE_RETURN, kKeyReturn },
@@ -212,20 +231,88 @@ int16 Util::translateKey(const Common::KeyState &key) {
{Common::KEYCODE_F10, kKeyF10 }
};
+ // Translate special keys
for (int i = 0; i < ARRAYSIZE(keys); i++)
if (key.keycode == keys[i].from)
return keys[i].to;
- if ((key.keycode >= Common::KEYCODE_SPACE) &&
- (key.keycode <= Common::KEYCODE_DELETE)) {
-
- // Used as a user input in Gobliins 2 notepad, in the save dialog, ...
+ // Return the ascii value, for text input
+ if ((key.ascii >= 32) && (key.ascii <= 127))
return key.ascii;
- }
+
+ // Translate international characters into CP850 characters
+ if ((key.ascii >= 160) && (key.ascii <= 255))
+ return toCP850(key.ascii);
return 0;
}
+static const uint8 kLowerToUpper[][2] = {
+ {0x81, 0x9A},
+ {0x82, 0x90},
+ {0x83, 0xB6},
+ {0x84, 0x8E},
+ {0x85, 0xB7},
+ {0x86, 0x8F},
+ {0x87, 0x80},
+ {0x88, 0xD2},
+ {0x89, 0xD3},
+ {0x8A, 0xD4},
+ {0x8B, 0xD8},
+ {0x8C, 0xD7},
+ {0x8D, 0xDE},
+ {0x91, 0x92},
+ {0x93, 0xE2},
+ {0x94, 0x99},
+ {0x95, 0xE3},
+ {0x96, 0xEA},
+ {0x97, 0xEB},
+ {0x95, 0xE3},
+ {0x96, 0xEA},
+ {0x97, 0xEB},
+ {0x9B, 0x9D},
+ {0xA0, 0xB5},
+ {0xA1, 0xD6},
+ {0xA2, 0xE0},
+ {0xA3, 0xE9},
+ {0xA4, 0xA5},
+ {0xC6, 0xC7},
+ {0xD0, 0xD1},
+ {0xE4, 0xE5},
+ {0xE7, 0xE8},
+ {0xEC, 0xED}
+};
+
+char Util::toCP850Lower(char cp850) {
+ const uint8 cp = (unsigned char)cp850;
+ if (cp <= 32)
+ return cp850;
+
+ if (cp <= 127)
+ return tolower(cp850);
+
+ for (uint i = 0; i < ARRAYSIZE(kLowerToUpper); i++)
+ if (cp == kLowerToUpper[i][1])
+ return (char)kLowerToUpper[i][0];
+
+ return cp850;
+}
+
+char Util::toCP850Upper(char cp850) {
+ const uint8 cp = (unsigned char)cp850;
+ if (cp <= 32)
+ return cp850;
+
+ if (cp <= 127)
+ return toupper(cp850);
+
+ for (uint i = 0; i < ARRAYSIZE(kLowerToUpper); i++)
+ if (cp == kLowerToUpper[i][0])
+ return (char)kLowerToUpper[i][1];
+
+ return cp850;
+}
+
int16 Util::getKey() {
Common::KeyState key;
@@ -363,21 +450,29 @@ void Util::notifyNewAnim() {
_startFrameTime = getTimeKey();
}
-void Util::waitEndFrame() {
+void Util::waitEndFrame(bool handleInput) {
int32 time;
- _vm->_video->waitRetrace();
-
time = getTimeKey() - _startFrameTime;
if ((time > 1000) || (time < 0)) {
+ _vm->_video->retrace();
_startFrameTime = getTimeKey();
return;
}
- int32 toWait = _frameWaitTime - time;
+ int32 toWait = 0;
+ do {
+ if (toWait > 0)
+ delay(MIN<int>(toWait, 10));
- if (toWait > 0)
- delay(toWait);
+ if (handleInput)
+ processInput();
+
+ _vm->_video->retrace();
+
+ time = getTimeKey() - _startFrameTime;
+ toWait = _frameWaitTime - time;
+ } while (toWait > 0);
_startFrameTime = getTimeKey();
}
@@ -576,4 +671,38 @@ void Util::checkJoystick() {
_vm->_global->_useJoystick = 0;
}
+uint32 Util::getKeyState() const {
+ return _keyState;
+}
+
+void Util::keyDown(const Common::Event &event) {
+ if (event.kbd.keycode == Common::KEYCODE_UP)
+ _keyState |= 0x0001;
+ else if (event.kbd.keycode == Common::KEYCODE_DOWN)
+ _keyState |= 0x0002;
+ else if (event.kbd.keycode == Common::KEYCODE_RIGHT)
+ _keyState |= 0x0004;
+ else if (event.kbd.keycode == Common::KEYCODE_LEFT)
+ _keyState |= 0x0008;
+ else if (event.kbd.keycode == Common::KEYCODE_SPACE)
+ _keyState |= 0x0020;
+ else if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
+ _keyState |= 0x0040;
+}
+
+void Util::keyUp(const Common::Event &event) {
+ if (event.kbd.keycode == Common::KEYCODE_UP)
+ _keyState &= ~0x0001;
+ else if (event.kbd.keycode == Common::KEYCODE_DOWN)
+ _keyState &= ~0x0002;
+ else if (event.kbd.keycode == Common::KEYCODE_RIGHT)
+ _keyState &= ~0x0004;
+ else if (event.kbd.keycode == Common::KEYCODE_LEFT)
+ _keyState &= ~0x0008;
+ else if (event.kbd.keycode == Common::KEYCODE_SPACE)
+ _keyState &= ~0x0020;
+ else if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
+ _keyState &= ~0x0040;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/util.h b/engines/gob/util.h
index 4228dac768..a4984c6207 100644
--- a/engines/gob/util.h
+++ b/engines/gob/util.h
@@ -25,6 +25,7 @@
#include "common/str.h"
#include "common/keyboard.h"
+#include "common/events.h"
namespace Common {
class SeekableReadStream;
@@ -110,6 +111,8 @@ public:
bool checkKey(int16 &key);
bool keyPressed();
+ uint32 getKeyState() const;
+
void getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons);
void setMousePos(int16 x, int16 y);
void waitMouseUp();
@@ -121,7 +124,7 @@ public:
int16 getFrameRate();
void setFrameRate(int16 rate);
void notifyNewAnim();
- void waitEndFrame();
+ void waitEndFrame(bool handleInput = true);
void setScrollOffset(int16 x = -1, int16 y = -1);
static void insertStr(const char *str1, char *str2, int16 pos);
@@ -140,6 +143,11 @@ public:
/** Read a constant-length string out of a stream. */
static Common::String readString(Common::SeekableReadStream &stream, int n);
+ /** Convert a character in CP850 encoding to the equivalent lower case character. */
+ static char toCP850Lower(char cp850);
+ /** Convert a character in CP850 encoding to the equivalent upper case character. */
+ static char toCP850Upper(char cp850);
+
Util(GobEngine *vm);
protected:
@@ -155,13 +163,19 @@ protected:
int16 _frameWaitTime;
uint32 _startFrameTime;
+ uint32 _keyState;
+
GobEngine *_vm;
bool keyBufferEmpty();
void addKeyToBuffer(const Common::KeyState &key);
bool getKeyFromBuffer(Common::KeyState &key);
int16 translateKey(const Common::KeyState &key);
+ int16 toCP850(uint16 latin1);
void checkJoystick();
+
+ void keyDown(const Common::Event &event);
+ void keyUp(const Common::Event &event);
};
} // End of namespace Gob
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index ee5ff4abff..64af34cf62 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -25,7 +25,6 @@
#include "engines/util.h"
#include "graphics/cursorman.h"
-#include "graphics/fontman.h"
#include "graphics/palette.h"
#include "graphics/surface.h"
@@ -85,6 +84,10 @@ uint16 Font::getCharCount() const {
return _endItem - _startItem + 1;
}
+bool Font::hasChar(uint8 c) const {
+ return (c >= _startItem) && (c <= _endItem);
+}
+
bool Font::isMonospaced() const {
return _charWidths == 0;
}
@@ -135,6 +138,23 @@ void Font::drawLetter(Surface &surf, uint8 c, uint16 x, uint16 y,
}
}
+void Font::drawString(const Common::String &str, int16 x, int16 y, int16 color1, int16 color2,
+ bool transp, Surface &dest) const {
+
+ const char *s = str.c_str();
+
+ while (*s != '\0') {
+ const int16 charRight = x + getCharWidth(*s);
+ const int16 charBottom = y + getCharHeight();
+
+ if ((x >= 0) && (y >= 0) && (charRight <= dest.getWidth()) && (charBottom <= dest.getHeight()))
+ drawLetter(dest, *s, x, y, color1, color2, transp);
+
+ x += getCharWidth(*s);
+ s++;
+ }
+}
+
const byte *Font::getCharData(uint8 c) const {
if (_endItem == 0) {
warning("Font::getCharData(): _endItem == 0");
@@ -226,10 +246,7 @@ void Video::setSize(bool defaultTo1XScaler) {
void Video::retrace(bool mouse) {
if (mouse)
- if ((_vm->getGameType() != kGameTypeAdibou2) &&
- (_vm->getGameType() != kGameTypeAdi2) &&
- (_vm->getGameType() != kGameTypeAdi4))
- CursorMan.showMouse((_vm->_draw->_showCursor & 2) != 0);
+ CursorMan.showMouse((_vm->_draw->_showCursor & 6) != 0);
if (_vm->_global->_primarySurfDesc) {
int screenX = _screenDeltaX;
@@ -336,6 +353,10 @@ void Video::drawPackedSprite(byte *sprBuf, int16 width, int16 height,
void Video::drawPackedSprite(const char *path, Surface &dest, int width) {
int32 size;
byte *data = _vm->_dataIO->getFile(path, size);
+ if (!data) {
+ warning("Video::drawPackedSprite(): Failed to open sprite \"%s\"", path);
+ return;
+ }
drawPackedSprite(data, width, dest.getHeight(), 0, 0, 0, dest);
delete[] data;
diff --git a/engines/gob/video.h b/engines/gob/video.h
index ecbb579c5f..122c1e47d5 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -41,11 +41,16 @@ public:
uint8 getCharWidth () const;
uint8 getCharHeight() const;
+ bool hasChar(uint8 c) const;
+
bool isMonospaced() const;
void drawLetter(Surface &surf, uint8 c, uint16 x, uint16 y,
uint32 color1, uint32 color2, bool transp) const;
+ void drawString(const Common::String &str, int16 x, int16 y, int16 color1, int16 color2,
+ bool transp, Surface &dest) const;
+
private:
const byte *_dataPtr;
const byte *_data;
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index 221f5ab3c9..a478492ccc 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -234,6 +234,23 @@ void VideoPlayer::closeAll() {
closeVideo(i);
}
+bool VideoPlayer::reopenVideo(int slot) {
+ Video *video = getVideoBySlot(slot);
+ if (!video)
+ return true;
+
+ return reopenVideo(*video);
+}
+
+bool VideoPlayer::reopenAll() {
+ bool all = true;
+ for (int i = 0; i < kVideoSlotCount; i++)
+ if (!reopenVideo(i))
+ all = false;
+
+ return all;
+}
+
void VideoPlayer::pauseVideo(int slot, bool pause) {
Video *video = getVideoBySlot(slot);
if (!video || !video->decoder)
@@ -850,6 +867,39 @@ Common::String VideoPlayer::findFile(const Common::String &file, Properties &pro
return video;
}
+bool VideoPlayer::reopenVideo(Video &video) {
+ if (video.isEmpty())
+ return true;
+
+ if (video.fileName.empty()) {
+ video.close();
+ return false;
+ }
+
+ Properties properties;
+
+ properties.type = video.properties.type;
+
+ Common::String fileName = findFile(video.fileName, properties);
+ if (fileName.empty()) {
+ video.close();
+ return false;
+ }
+
+ Common::SeekableReadStream *stream = _vm->_dataIO->getFile(fileName);
+ if (!stream) {
+ video.close();
+ return false;
+ }
+
+ if (!video.decoder->reloadStream(stream)) {
+ delete stream;
+ return false;
+ }
+
+ return true;
+}
+
void VideoPlayer::copyPalette(const Video &video, int16 palStart, int16 palEnd) {
if (!video.decoder->hasPalette() || !video.decoder->isPaletted())
return;
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
index bc7cb48768..129ccef67a 100644
--- a/engines/gob/videoplayer.h
+++ b/engines/gob/videoplayer.h
@@ -110,6 +110,9 @@ public:
void closeLiveSound();
void closeAll();
+ bool reopenVideo(int slot = 0);
+ bool reopenAll();
+
void pauseVideo(int slot, bool pause);
void pauseAll(bool pause);
@@ -163,6 +166,8 @@ private:
bool isEmpty() const;
void close();
+
+ void reopen();
};
static const int kVideoSlotCount = 32;
@@ -188,6 +193,8 @@ private:
::Video::CoktelDecoder *openVideo(const Common::String &file, Properties &properties);
+ bool reopenVideo(Video &video);
+
bool playFrame(int slot, Properties &properties);
void checkAbort(Video &video, Properties &properties);