[Scummvm-git-logs] scummvm master -> 00cf269f55c7bec272c73669d5af69f5d0546277
sev-
noreply at scummvm.org
Mon Aug 24 23:07:33 UTC 2026
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
7b33926daa SKY: Add options icon in iBASS
0428182bc9 SKY: Add Help icon for ibass and remove the boundary check
27d06bd963 IMAGE: Implement CgBI decoder
8e73273bde SKY: Load help window in ibass
00cf269f55 SKY: Implement hint system for ibass
Commit: 7b33926daa9eddfdf0f2894c4b302ae5f0451eab
https://github.com/scummvm/scummvm/commit/7b33926daa9eddfdf0f2894c4b302ae5f0451eab
Author: Priyanshu (10b.priyanshu at gmail.com)
Date: 2026-08-25T01:07:27+02:00
Commit Message:
SKY: Add options icon in iBASS
Changed paths:
engines/sky/screen.cpp
diff --git a/engines/sky/screen.cpp b/engines/sky/screen.cpp
index 26e9e58c520..28e261e1e6c 100644
--- a/engines/sky/screen.cpp
+++ b/engines/sky/screen.cpp
@@ -290,6 +290,7 @@ void Screen::renderFinalFrame() {
update32BitScreen(_currentScreen, 0, 0, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);
_paletteDirty = false;
setIcon(UI_ICON_INV, 0, GAME_SCREEN_HEIGHT - 35);
+ setIcon(UI_ICON_OPTIONS, 4, 4);
drawIbassIcon();
drawIbassInventory();
if (_screen32.getPixels()) {
Commit: 0428182bc9d4d8afd16afecd59e50c206a497973
https://github.com/scummvm/scummvm/commit/0428182bc9d4d8afd16afecd59e50c206a497973
Author: Priyanshu (10b.priyanshu at gmail.com)
Date: 2026-08-25T01:07:27+02:00
Commit Message:
SKY: Add Help icon for ibass and remove the boundary check
Changed paths:
engines/sky/screen.cpp
diff --git a/engines/sky/screen.cpp b/engines/sky/screen.cpp
index 28e261e1e6c..87baa8911ea 100644
--- a/engines/sky/screen.cpp
+++ b/engines/sky/screen.cpp
@@ -73,8 +73,7 @@ void Screen::drawIbassIcon() {
// get the current animation frame
Graphics::Surface *currentFrame = _uiIcon[i]._anim->_frames[_uiIcon[i]._curFrame];
- if ((_uiIcon[i]._x + currentFrame->w) <= _screen32.w)
- Graphics::alphaBlit((byte *)_screen32.getBasePtr(_uiIcon[i]._x, _uiIcon[i]._y), (const byte *)currentFrame->getPixels(), _screen32.pitch, currentFrame->pitch, currentFrame->w, currentFrame->h, _screen32.format, currentFrame->format, 0, 255);
+ Graphics::alphaBlit((byte *)_screen32.getBasePtr(_uiIcon[i]._x, _uiIcon[i]._y), (const byte *)currentFrame->getPixels(), _screen32.pitch, currentFrame->pitch, currentFrame->w, currentFrame->h, _screen32.format, currentFrame->format, 0, 255);
}
}
@@ -291,6 +290,7 @@ void Screen::renderFinalFrame() {
_paletteDirty = false;
setIcon(UI_ICON_INV, 0, GAME_SCREEN_HEIGHT - 35);
setIcon(UI_ICON_OPTIONS, 4, 4);
+ setIcon(UI_ICON_HELP, FULL_SCREEN_WIDTH - 30, 2);
drawIbassIcon();
drawIbassInventory();
if (_screen32.getPixels()) {
Commit: 27d06bd963391de5bcfd75b4359f98ef1813c6ce
https://github.com/scummvm/scummvm/commit/27d06bd963391de5bcfd75b4359f98ef1813c6ce
Author: Priyanshu (10b.priyanshu at gmail.com)
Date: 2026-08-25T01:07:27+02:00
Commit Message:
IMAGE: Implement CgBI decoder
Changed paths:
A image/cgbi.cpp
A image/cgbi.h
image/module.mk
diff --git a/image/cgbi.cpp b/image/cgbi.cpp
new file mode 100644
index 00000000000..ebd1f03ad7e
--- /dev/null
+++ b/image/cgbi.cpp
@@ -0,0 +1,237 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "image/cgbi.h"
+#include "common/compression/deflate.h"
+#include "common/crc.h"
+#include "common/memstream.h"
+#include "common/stream.h"
+#include "common/debug.h"
+
+namespace Image {
+
+CgBIDecoder::CgBIDecoder() : _surface(nullptr), _palette(0) {}
+
+CgBIDecoder::~CgBIDecoder() {
+ destroy();
+}
+
+void CgBIDecoder::destroy() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = nullptr;
+ }
+ _palette.clear();
+}
+
+bool CgBIDecoder::loadStream(Common::SeekableReadStream &stream) {
+ destroy();
+ if (stream.readUint32BE() != MKTAG(0x89, 'P', 'N', 'G')) {
+ debug(1, "Invalid file format");
+ return false;
+ }
+ stream.seek(0, SEEK_SET);
+ byte buffer[8];
+ stream.read(buffer, 8);
+ for (int i = 0; i < 8; i++)
+ debug(1, "%X", buffer[i]);
+
+ uint32 width = 0, height = 0;
+ uint8 bitDepth = 0, colorType = 0;
+ uint32 bpp = 0;
+
+ bool inIdat = false;
+ bool idatProcessed = false;
+ Common::MemoryWriteStreamDynamic idatData(DisposeAfterUse::YES);
+
+ while (true) {
+ uint32 size = stream.readUint32BE();
+ uint32 type = stream.readUint32BE();
+ if (!size && type != MKTAG('I', 'E', 'N', 'D')) {
+ debug(1, "End of file.");
+ break;
+ }
+ if (type == MKTAG('C', 'g', 'B', 'I')) {
+ stream.seek(size + 4, SEEK_CUR);
+ continue;
+ }
+ if (type == MKTAG('I', 'H', 'D', 'R')) {
+ uint8 *payloadBuffer = new uint8[size + 4];
+ stream.read(payloadBuffer, size + 4);
+
+ width = READ_BE_UINT32(payloadBuffer);
+ height = READ_BE_UINT32(payloadBuffer + 4);
+ bitDepth = payloadBuffer[8];
+ colorType = payloadBuffer[9];
+
+ switch (colorType) {
+ case 0:
+ bpp = bitDepth / 8; // greyscale
+ break;
+ case 2:
+ bpp = 3 * (bitDepth / 8); // RGB
+ break;
+ case 3:
+ bpp = 1; // palette
+ break;
+ case 4:
+ bpp = 2 * (bitDepth / 8); // greyscale + alpha
+ break;
+ case 6:
+ bpp = 4 * (bitDepth / 8); // RGBA
+ break;
+ }
+ delete[] payloadBuffer;
+ continue;
+ }
+ if (type == MKTAG('I', 'D', 'A', 'T')) {
+ inIdat = true;
+ uint8 *payloadBuffer = new uint8[size + 4];
+ stream.read(payloadBuffer, size + 4);
+ idatData.write(payloadBuffer, size);
+ delete[] payloadBuffer;
+ continue;
+ }
+ if (inIdat && !idatProcessed) {
+ Common::MemoryReadStream *rawCompressed = new Common::MemoryReadStream(idatData.getData(), idatData.size(), DisposeAfterUse::NO);
+ Common::SeekableReadStream *deCompressed = Common::wrapDeflateReadStream(rawCompressed, DisposeAfterUse::YES);
+ uint32 decompressedSize = height * (1 + width * bpp);
+ uint8 *filteredBuffer = new uint8[decompressedSize];
+ deCompressed->read(filteredBuffer, decompressedSize);
+ delete deCompressed;
+
+ uint8 *pixelBuffer = new uint8[height * width * 4];
+ unfilterScanlines(filteredBuffer, width, height, bpp);
+ convertBGRAtoRGBA(filteredBuffer, pixelBuffer, width, height, bpp, colorType == 6);
+ delete[] filteredBuffer;
+
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, Graphics::PixelFormat::createFormatRGBA32());
+ memcpy(_surface->getPixels(), pixelBuffer, width * height * 4);
+ delete[] pixelBuffer;
+
+ idatProcessed = true;
+ break;
+ }
+
+ if (size > (uint32)(stream.size() - stream.pos())) {
+ debug(1, "Corrupt chunk length, aborting!");
+ return false;
+ }
+ uint8 *payloadBuffer = new uint8[size + 4];
+ stream.read(payloadBuffer, size + 4);
+ delete[] payloadBuffer;
+ if (type == MKTAG('I', 'E', 'N', 'D'))
+ break;
+ }
+ return idatProcessed;
+}
+
+void CgBIDecoder::unfilterScanline(uint8 *scanline, uint8 *prev, int scanlineLen, int bpp) {
+ uint8 filter = scanline[0];
+ uint8 *dst = scanline + 1;
+
+ switch (filter) {
+ case 0: // data is already raw
+ break;
+ case 1: // sub
+ for (int i = 0; i < scanlineLen; i ++) {
+ uint8 left = (i >= bpp) ? dst[i - bpp] : 0;
+ dst[i] += left;
+ }
+ break;
+ case 2: // up
+ if (prev)
+ for (int i = 0; i < scanlineLen; i++)
+ dst[i] += prev[i];
+ break;
+ case 3: // average
+ for (int i = 0; i < scanlineLen; i++) {
+ int left = (i >= bpp) ? dst[i - bpp] : 0;
+ int above = prev ? prev[i] : 0;
+ dst[i] += (left + above) / 2;
+ }
+ break;
+ case 4: // paeth
+ for (int i = 0; i < scanlineLen; i++) {
+ int a = (i >= bpp) ? dst[i - bpp] : 0;
+ int b = prev ? prev[i] : 0;
+ int c = (i >= bpp && prev) ? prev[i - bpp] : 0;
+ int p = a + b - c;
+ int pa = ABS(p - a);
+ int pb = ABS(p - b);
+ int pc = ABS(p - c);
+ int pr = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
+ dst[i] += pr;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void CgBIDecoder::unfilterScanlines(uint8 *filtered, uint32 width, uint32 height, uint32 bpp) {
+ uint32 rowBytes = width * bpp;
+ uint8 *prev = nullptr;
+
+ for (uint32 y = 0; y < height; y++) {
+ uint8 *scanline = filtered + (size_t)y * (1 + rowBytes);
+ unfilterScanline(scanline, prev, rowBytes, bpp);
+ prev = scanline + 1;
+ }
+}
+
+void CgBIDecoder::convertBGRAtoRGBA(const byte *filtered, byte *out, uint32 width, uint32 height, uint32 bpp, bool hasAlpha) {
+ uint32 rowBytes = width * bpp;
+ for (uint32 y = 0; y < height; y++) {
+ const byte *src = filtered + (size_t)y * (1 + rowBytes) + 1;
+ byte *rowOut = out + (size_t)y * width * 4;
+
+ for (uint32 x = 0; x < width; x++) {
+ byte b = src[0];
+ byte g = src[1];
+ byte r = src[2];
+ byte a;
+
+ if (hasAlpha) {
+ a = src[3];
+ if (a > 0 && a < 255) {
+ r = (byte)((uint32)r * 255 / a);
+ g = (byte)((uint32)g * 255 / a);
+ b = (byte)((uint32)b * 255 / a);
+ }
+ src += 4;
+ } else {
+ a = 255;
+ src += 3;
+ }
+ rowOut[0] = r;
+ rowOut[1] = g;
+ rowOut[2] = b;
+ rowOut[3] = a;
+ rowOut += 4;
+ }
+ }
+}
+
+} // End of namespace Image
diff --git a/image/cgbi.h b/image/cgbi.h
new file mode 100644
index 00000000000..ea86016993e
--- /dev/null
+++ b/image/cgbi.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IMAGE_CGBI_H
+#define IMAGE_CGBI_H
+
+#include "common/scummsys.h"
+#include "image/image_decoder.h"
+#include "image/png.h"
+#include "graphics/surface.h"
+
+namespace Image {
+
+class CgBIDecoder : public ImageDecoder {
+public:
+ CgBIDecoder();
+ ~CgBIDecoder();
+
+ bool loadStream(Common::SeekableReadStream &stream) override;
+ void destroy() override;
+ Graphics::Surface *getSurface() const override {
+ return _surface;
+ }
+ const Graphics::Palette &getPalette() const override {
+ return _palette;
+ }
+ void unfilterScanline(uint8 *scanline, uint8 *prev, int scanlineLen, int bpp);
+ void unfilterScanlines(uint8 *filtered, uint32 width, uint32 height, uint32 bpp);
+ void convertBGRAtoRGBA(const byte *filtered, byte *out, uint32 width, uint32 height, uint32 bpp, bool hasAlpha);
+
+private:
+ Graphics::Surface *_surface;
+ Graphics::Palette _palette;
+};
+
+} // End of namespace Image
+
+#endif
diff --git a/image/module.mk b/image/module.mk
index 8cf9104bf6d..92ba987c75e 100644
--- a/image/module.mk
+++ b/image/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS := \
ani.o \
bmp.o \
cel_3do.o \
+ cgbi.o \
cicn.o \
icocur.o \
iff.o \
Commit: 8e73273bde7fa92e14e3989704b3f8b260f6dae3
https://github.com/scummvm/scummvm/commit/8e73273bde7fa92e14e3989704b3f8b260f6dae3
Author: Priyanshu (10b.priyanshu at gmail.com)
Date: 2026-08-25T01:07:27+02:00
Commit Message:
SKY: Load help window in ibass
Changed paths:
engines/sky/control.cpp
engines/sky/control.h
engines/sky/mouse.cpp
diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp
index 07ebf328ba9..96c4b1ab1d0 100644
--- a/engines/sky/control.cpp
+++ b/engines/sky/control.cpp
@@ -25,11 +25,13 @@
#include "common/endian.h"
#include "common/config-manager.h"
#include "common/events.h"
+#include "common/file.h"
#include "common/system.h"
#include "common/savefile.h"
#include "common/textconsole.h"
#include "gui/message.h"
+#include "image/cgbi.h"
#include "sky/compact.h"
#include "sky/control.h"
#include "sky/disk.h"
@@ -271,6 +273,46 @@ void Control::removePanel() {
}
}
+void Control::initHelpPanel() {
+ Image::CgBIDecoder d;
+ Common::File f;
+ if (!f.open("hints_txtbox.png") || !d.loadStream(f)) {
+ debug("Cannot open file");
+ return;
+ }
+ Graphics::Surface *surface = d.getSurface();
+ if (!surface) {
+ debug("No surface");
+ return;
+ }
+ Graphics::Surface *converted = surface->convertTo(_skyScreen->_screen32.format);
+
+ float scaleX = (float)GAME_SCREEN_WIDTH / converted->w;
+ float scaleY = (float)FULL_SCREEN_HEIGHT / converted->h;
+ float scaleFactor = MIN(scaleX, scaleY);
+
+ int16 newW = (int16)(converted->w * scaleFactor);
+ int16 newH = (int16)(converted->h * scaleFactor);
+
+ Graphics::Surface *scaled = converted->scale(newW, newH, true);
+ converted->free();
+ delete converted;
+
+ int destX = (GAME_SCREEN_WIDTH - newW) / 2;
+ int destY = (FULL_SCREEN_HEIGHT - newH) / 2;
+ _skyScreen->_screen32.fillRect(Common::Rect(0, 0, _skyScreen->_screen32.w, _skyScreen->_screen32.h), 0);
+ _skyScreen->_screen32.copyRectToSurface(*scaled, destX, destY, Common::Rect(0, 0, scaled->w, scaled->h));
+ scaled->free();
+ delete scaled;
+
+ _mouseClicked = false;
+ while (!_mouseClicked && !Engine::shouldQuit()) {
+ _system->copyRectToScreen(_skyScreen->_screen32.getPixels(), _skyScreen->_screen32.pitch, 0, 0, _skyScreen->_screen32.w, _skyScreen->_screen32.h);
+ _system->updateScreen();
+ delay(ANIM_DELAY);
+ }
+}
+
void Control::initPanel() {
_screenBuf = (uint8 *)malloc(GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT);
memset(_screenBuf, 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT);
@@ -559,6 +601,10 @@ void Control::doControlPanel() {
_skyText->fnSetFont(_savedCharSet);
}
+void Control::doHelpPanel() {
+ initHelpPanel();
+}
+
uint16 Control::handleClick(ConResource *pButton) {
char quitDos[50] = "Quit to DOS?";
char restart[50] = "Restart?";
diff --git a/engines/sky/control.h b/engines/sky/control.h
index 82a690acd85..4f275436dc7 100644
--- a/engines/sky/control.h
+++ b/engines/sky/control.h
@@ -182,6 +182,7 @@ class Control {
public:
Control(SkyEngine *vm, Common::SaveFileManager *saveFileMan, Screen *screen, Disk *disk, Mouse *mouse, Text *text, MusicBase *music, Logic *logic, Sound *sound, SkyCompact *skyCompact, OSystem *system, Common::Keymap *shortcutsKeymap);
void doControlPanel();
+ void doHelpPanel();
void doLoadSavePanel();
void restartGame();
void showGameQuitMsg();
@@ -201,6 +202,7 @@ private:
int displayMessage(MSVC_PRINTF const char *message, ...) GCC_PRINTF(2, 3);
void initPanel();
+ void initHelpPanel(); // for ibass
void removePanel();
void drawMainPanel();
diff --git a/engines/sky/mouse.cpp b/engines/sky/mouse.cpp
index 7a6a5ee6780..7cea2552557 100644
--- a/engines/sky/mouse.cpp
+++ b/engines/sky/mouse.cpp
@@ -1266,6 +1266,7 @@ void Mouse::pointerEngineIBASS(uint16 xPos, uint16 yPos) {
}
// help screen
if (xPos > HOTSPOT_helpx && yPos < HOTSPOT_helpy) {
+ _skyControl->doHelpPanel();
_skyScreen->clearAllProximityIcons(false);
_skyScreen->clearAllIbassIcons(false);
_mouseB = 0;
Commit: 00cf269f55c7bec272c73669d5af69f5d0546277
https://github.com/scummvm/scummvm/commit/00cf269f55c7bec272c73669d5af69f5d0546277
Author: Priyanshu (10b.priyanshu at gmail.com)
Date: 2026-08-25T01:07:27+02:00
Commit Message:
SKY: Implement hint system for ibass
Changed paths:
A engines/sky/ibasstext.cpp
A engines/sky/ibasstext.h
engines/sky/control.cpp
engines/sky/control.h
engines/sky/module.mk
engines/sky/sky.cpp
engines/sky/sky.h
diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp
index 96c4b1ab1d0..487b4f36b14 100644
--- a/engines/sky/control.cpp
+++ b/engines/sky/control.cpp
@@ -31,6 +31,8 @@
#include "common/textconsole.h"
#include "gui/message.h"
+#include "graphics/font.h"
+#include "graphics/fonts/ttf.h"
#include "image/cgbi.h"
#include "sky/compact.h"
#include "sky/control.h"
@@ -273,16 +275,863 @@ void Control::removePanel() {
}
}
+Common::Array<Hint> Control::buildHints() {
+ Common::Array<Hint> hints;
+ Hint h;
+
+ switch (SkyEngine::giveCurrentScreen()) {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ if (!SkyEngine::hasSeenScreen(5)) {
+ debug(1, "Section RECYCLING PLANT 1");
+
+ // fire exit unopened, fire_exit_flag == 106
+ if (2 == SkyEngine::giveScriptVar(106)) {
+ h.question = 0;
+ h.answers.clear();
+ h.answers.push_back(1057);
+ h.answers.push_back(1058);
+ hints.push_back(h);
+ break;
+ }
+
+ // if joey not alive and on transporter screen - joey_born == 125
+ if (!SkyEngine::giveScriptVar(125)) {
+ if (SkyEngine::giveCurrentScreen() == 2) {
+ h.question = 1;
+ h.answers.clear();
+ h.answers.push_back(1059);
+ h.answers.push_back(1060);
+ hints.push_back(h);
+ } else {
+ h.question = 50;
+ h.answers.clear();
+ h.answers.push_back(1213);
+ hints.push_back(h);
+ }
+ break;
+ }
+
+ h.question = 2;
+ h.answers.clear();
+ h.answers.push_back(1061);
+ h.answers.push_back(1062);
+ h.answers.push_back(1063);
+ hints.push_back(h);
+ h.question = 3;
+ h.answers.clear();
+ h.answers.push_back(1064);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(90) && !SkyEngine::hasSeenScreen(90)) {
+ h.question = 19;
+ h.answers.clear();
+ h.answers.push_back(1108);
+ h.answers.push_back(1109);
+ hints.push_back(h);
+ break;
+ }
+ break;
+ case 3: // furnace
+ if (!SkyEngine::hasSeenScreen(6)) {
+ h.question = 4;
+ h.answers.clear();
+ h.answers.push_back(1065);
+ h.answers.push_back(1066);
+ hints.push_back(h);
+ }
+ break;
+ case 10:
+ case 11:
+ if (SkyEngine::giveScriptVar(337) && !SkyEngine::giveScriptVar(788)) {
+ h.question = 31;
+ h.answers.clear();
+ h.answers.push_back(1146);
+ h.answers.push_back(1147);
+ h.answers.push_back(1148);
+ hints.push_back(h);
+ break;
+ }
+
+ if (SkyEngine::giveScriptVar(822) && !SkyEngine::giveScriptVar(337)) {
+ h.question = 29;
+ h.answers.clear();
+ h.answers.push_back(1139);
+ h.answers.push_back(1140);
+ h.answers.push_back(1141);
+ h.answers.push_back(1142);
+ hints.push_back(h);
+ break;
+ }
+
+ h.question = 20;
+ h.answers.clear();
+ h.answers.push_back(1110);
+ hints.push_back(h);
+
+ if (SkyEngine::hasSeenScreen(93)) {
+ h.question = 24;
+ h.answers.clear();
+ h.answers.push_back(1123);
+ h.answers.push_back(1124);
+ h.answers.push_back(1125);
+ h.answers.push_back(1126);
+ h.answers.push_back(1127);
+ hints.push_back(h);
+ break;
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 18:
+ if (SkyEngine::giveScriptVar(787)) {
+ break;
+ }
+ if (SkyEngine::giveScriptVar(830) && !SkyEngine::giveScriptVar(787)) {
+ h.question = 33;
+ h.answers.clear();
+ h.answers.push_back(1153);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(337) && !SkyEngine::giveScriptVar(788)) {
+ h.question = 31;
+ h.answers.clear();
+ h.answers.push_back(1146);
+ h.answers.push_back(1147);
+ h.answers.push_back(1148);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(822) && !SkyEngine::giveScriptVar(337)) {
+ h.question = 29;
+ h.answers.clear();
+ h.answers.push_back(1139);
+ h.answers.push_back(1140);
+ h.answers.push_back(1141);
+ h.answers.push_back(1142);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(190) && !SkyEngine::giveScriptVar(256)) {
+ h.question = 15;
+ h.answers.clear();
+ h.answers.push_back(1096);
+ h.answers.push_back(1097);
+ h.answers.push_back(1098);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(90)) {
+ if (!SkyEngine::hasSeenScreen(31)) {
+ h.question = 53;
+ h.answers.clear();
+ h.answers.push_back(1216);
+ hints.push_back(h);
+ }
+ break;
+ }
+ if (SkyEngine::giveScriptVar(90)) {
+ h.question = 19;
+ h.answers.clear();
+ h.answers.push_back(1108);
+ h.answers.push_back(1109);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(282) && !SkyEngine::hasSeenScreen(18)) {
+ h.question = 14;
+ h.answers.clear();
+ h.answers.push_back(1092);
+ h.answers.push_back(1093);
+ h.answers.push_back(1094);
+ h.answers.push_back(1095);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(12) && !SkyEngine::giveScriptVar(428)) {
+ h.question = 5;
+ h.answers.clear();
+ h.answers.push_back(1067);
+ h.answers.push_back(1068);
+ h.answers.push_back(1069);
+ h.answers.push_back(1070);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(12) && !SkyEngine::giveScriptVar(446)) {
+ h.question = 6;
+ h.answers.clear();
+ h.answers.push_back(1071);
+ h.answers.push_back(1072);
+ h.answers.push_back(1073);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(13)) {
+ if (SkyEngine::giveScriptVar(224) != 42 && !SkyEngine::giveScriptVar(75)) {
+ h.question = 7;
+ h.answers.clear();
+ h.answers.push_back(1074);
+ h.answers.push_back(1075);
+ hints.push_back(h);
+
+ if (SkyEngine::giveScriptVar(270)) {
+ h.question = 8;
+ h.answers.clear();
+ h.answers.push_back(1076);
+ h.answers.push_back(1077);
+ hints.push_back(h);
+ }
+ }
+ }
+ if (SkyEngine::hasSeenScreen(18)) {
+ if (SkyEngine::giveScriptVar(224) != 42) {
+ h.question = 9;
+ h.answers.clear();
+ h.answers.push_back(1078);
+ h.answers.push_back(1079);
+ hints.push_back(h);
+ }
+ if (!SkyEngine::giveScriptVar(445) && SkyEngine::giveScriptVar(75)) {
+ h.question = 10;
+ h.answers.clear();
+ h.answers.push_back(1080);
+ h.answers.push_back(1081);
+ h.answers.push_back(1082);
+ h.answers.push_back(1083);
+ h.answers.push_back(1084);
+ hints.push_back(h);
+ }
+ }
+ if (!SkyEngine::hasSeenScreen(29) && SkyEngine::giveScriptVar(445)) {
+ h.question = 11;
+ h.answers.clear();
+ h.answers.push_back(1085);
+ h.answers.push_back(1086);
+ hints.push_back(h);
+ break;
+ }
+ if (!SkyEngine::hasSeenScreen(12)) {
+ h.question = 51;
+ h.answers.clear();
+ h.answers.push_back(1214);
+ hints.push_back(h);
+ }
+ if (!SkyEngine::hasSeenScreen(18)) {
+ if (SkyEngine::giveScriptVar(75) && SkyEngine::giveScriptVar(224) != 42) {
+ h.question = 52;
+ h.answers.clear();
+ h.answers.push_back(1215);
+ hints.push_back(h);
+ }
+ }
+ break;
+ case 16:
+ case 17:
+ if (SkyEngine::giveScriptVar(822) && !SkyEngine::giveScriptVar(337)) {
+ h.question = 29;
+ h.answers.clear();
+ h.answers.push_back(1139);
+ h.answers.push_back(1140);
+ h.answers.push_back(1141);
+ h.answers.push_back(1142);
+ hints.push_back(h);
+ }
+ break;
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 28:
+ case 29:
+ if (SkyEngine::giveScriptVar(282) && !SkyEngine::giveScriptVar(190)) {
+ h.question = 14;
+ h.answers.clear();
+ h.answers.push_back(1092);
+ h.answers.push_back(1093);
+ h.answers.push_back(1094);
+ h.answers.push_back(1095);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(787)) {
+ h.question = 34;
+ h.answers.clear();
+ h.answers.push_back(1154);
+ h.answers.push_back(1155);
+ h.answers.push_back(1156);
+ h.answers.push_back(1157);
+ h.answers.push_back(1158);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(830) && !SkyEngine::giveScriptVar(787)) {
+ h.question = 33;
+ h.answers.clear();
+ h.answers.push_back(1153);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(337) && !SkyEngine::giveScriptVar(788)) {
+ h.question = 31;
+ h.answers.clear();
+ h.answers.push_back(1146);
+ h.answers.push_back(1147);
+ h.answers.push_back(1148);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(822) && !SkyEngine::giveScriptVar(337)) {
+ h.question = 29;
+ h.answers.clear();
+ h.answers.push_back(1139);
+ h.answers.push_back(1140);
+ h.answers.push_back(1141);
+ h.answers.push_back(1142);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(38) && !SkyEngine::giveScriptVar(814)) {
+ h.question = 26;
+ h.answers.clear();
+ h.answers.push_back(1131);
+ h.answers.push_back(1132);
+ h.answers.push_back(1133);
+ h.answers.push_back(1134);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(90)) {
+ if (!SkyEngine::hasSeenScreen(31)) {
+ h.question = 53;
+ h.answers.clear();
+ h.answers.push_back(1216);
+ hints.push_back(h);
+ }
+ break;
+ }
+ if (SkyEngine::giveScriptVar(90)) {
+ h.question = 19;
+ h.answers.clear();
+ h.answers.push_back(1108);
+ h.answers.push_back(1109);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(190) && !SkyEngine::giveScriptVar(256)) {
+ h.question = 15;
+ h.answers.clear();
+ h.answers.push_back(1096);
+ h.answers.push_back(1097);
+ h.answers.push_back(1098);
+ hints.push_back(h);
+ break;
+ }
+ if (!SkyEngine::giveScriptVar(282)) {
+ if (!SkyEngine::giveScriptVar(88)) {
+ h.question = 12;
+ h.answers.clear();
+ h.answers.push_back(1087);
+ h.answers.push_back(1088);
+ h.answers.push_back(1089);
+ h.answers.push_back(1090);
+ hints.push_back(h);
+ }
+ if (SkyEngine::giveScriptVar(88)) {
+ h.question = 13;
+ h.answers.clear();
+ h.answers.push_back(1091);
+ hints.push_back(h);
+ }
+ break;
+ }
+ if (!SkyEngine::giveScriptVar(83) && !SkyEngine::giveScriptVar(90)) {
+ h.question = 17;
+ h.answers.clear();
+ h.answers.push_back(1100);
+ h.answers.push_back(1101);
+ h.answers.push_back(1102);
+ h.answers.push_back(1103);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(83)) {
+ h.question = 18;
+ h.answers.clear();
+ h.answers.push_back(1104);
+ h.answers.push_back(1105);
+ h.answers.push_back(1106);
+ h.answers.push_back(1107);
+ hints.push_back(h);
+ break;
+ }
+ break;
+ case 27:
+ if (SkyEngine::giveScriptVar(830) && !SkyEngine::giveScriptVar(787)) {
+ h.question = 33;
+ h.answers.clear();
+ h.answers.push_back(1153);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(256)) {
+ h.question = 16;
+ h.answers.clear();
+ h.answers.push_back(1099);
+ hints.push_back(h);
+ break;
+ }
+ break;
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ if (SkyEngine::giveScriptVar(703) == 1) {
+ h.question = 44;
+ h.answers.clear();
+ if (SkyEngine::giveScriptVar(497) != 6) {
+ h.answers.push_back(1191);
+ } else {
+ h.answers.push_back(1192);
+ h.answers.push_back(1193);
+ h.answers.push_back(1194);
+ h.answers.push_back(1195);
+ h.answers.push_back(1196);
+ }
+ hints.push_back(h);
+ }
+ if (SkyEngine::giveScriptVar(82)) {
+ if (!SkyEngine::giveScriptVar(337)) {
+ h.question = 30;
+ h.answers.clear();
+ h.answers.push_back(1143);
+ h.answers.push_back(1144);
+ h.answers.push_back(1145);
+ hints.push_back(h);
+ }
+ break;
+ }
+ if (SkyEngine::giveCurrentScreen() == 90 || SkyEngine::giveCurrentScreen() == 91) {
+ h.question = 21;
+ h.answers.clear();
+ h.answers.push_back(1111);
+ h.answers.push_back(1112);
+ h.answers.push_back(1113);
+ h.answers.push_back(1114);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveCurrentScreen() == 92) {
+ h.question = 22;
+ h.answers.clear();
+ h.answers.push_back(1115);
+ h.answers.push_back(1116);
+ h.answers.push_back(1117);
+ h.answers.push_back(1118);
+ hints.push_back(h);
+ break;
+ }
+ h.question = 23;
+ h.answers.clear();
+ h.answers.push_back(1119);
+ h.answers.push_back(1120);
+ h.answers.push_back(1121);
+ h.answers.push_back(1122);
+ hints.push_back(h);
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 38:
+ if (SkyEngine::giveScriptVar(787)) {
+ h.question = 34;
+ h.answers.clear();
+ h.answers.push_back(1154);
+ h.answers.push_back(1155);
+ h.answers.push_back(1156);
+ h.answers.push_back(1157);
+ h.answers.push_back(1158);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(830) && !SkyEngine::giveScriptVar(787)) {
+ h.question = 33;
+ h.answers.clear();
+ h.answers.push_back(1153);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(788) || SkyEngine::giveScriptVar(789)) {
+ h.question = 32;
+ h.answers.clear();
+ h.answers.push_back(1149);
+ h.answers.push_back(1150);
+ h.answers.push_back(1151);
+ h.answers.push_back(1152);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(337) && !SkyEngine::giveScriptVar(788)) {
+ h.question = 31;
+ h.answers.clear();
+ h.answers.push_back(1146);
+ h.answers.push_back(1147);
+ h.answers.push_back(1148);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(822) && !SkyEngine::giveScriptVar(337)) {
+ h.question = 29;
+ h.answers.clear();
+ h.answers.push_back(1139);
+ h.answers.push_back(1140);
+ h.answers.push_back(1141);
+ h.answers.push_back(1142);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(38) && !SkyEngine::giveScriptVar(814)) {
+ h.question = 26;
+ h.answers.clear();
+ h.answers.push_back(1131);
+ h.answers.push_back(1132);
+ h.answers.push_back(1133);
+ h.answers.push_back(1134);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::hasSeenScreen(38)) {
+ h.question = 25;
+ h.answers.clear();
+ h.answers.push_back(1128);
+ h.answers.push_back(1129);
+ h.answers.push_back(1130);
+ hints.push_back(h);
+ }
+ if (SkyEngine::giveCurrentScreen() != 38 && SkyEngine::hasSeenScreen(38)) {
+ h.question = 27;
+ h.answers.clear();
+ h.answers.push_back(1135);
+ h.answers.push_back(1136);
+ h.answers.push_back(1137);
+ hints.push_back(h);
+ }
+ break;
+ case 39:
+ case 40:
+ case 41:
+ h.question = 28;
+ h.answers.clear();
+ h.answers.push_back(1138);
+ hints.push_back(h);
+ if (SkyEngine::giveScriptVar(822) && !SkyEngine::giveScriptVar(337)) {
+ h.question = 29;
+ h.answers.clear();
+ h.answers.push_back(1139);
+ h.answers.push_back(1140);
+ h.answers.push_back(1141);
+ h.answers.push_back(1142);
+ hints.push_back(h);
+ }
+ break;
+ case 37:
+ h.question = 34;
+ h.answers.clear();
+ h.answers.push_back(1154);
+ h.answers.push_back(1155);
+ h.answers.push_back(1156);
+ h.answers.push_back(1157);
+ h.answers.push_back(1158);
+ hints.push_back(h);
+ if (!SkyEngine::giveScriptVar(79) && SkyEngine::giveScriptVar(813) == 1) {
+ h.question = 35;
+ h.answers.clear();
+ h.answers.push_back(1159);
+ h.answers.push_back(1160);
+ h.answers.push_back(1161);
+ h.answers.push_back(1162);
+ hints.push_back(h);
+ }
+ if (SkyEngine::giveScriptVar(813) == 1) {
+ h.question = 36;
+ h.answers.clear();
+ h.answers.push_back(1163);
+ h.answers.push_back(1164);
+ hints.push_back(h);
+ }
+ break;
+ case 48:
+ h.question = 37;
+ h.answers.clear();
+ h.answers.push_back(1165);
+ hints.push_back(h);
+ break;
+ case 67:
+ h.question = 38;
+ h.answers.clear();
+ h.answers.push_back(1166);
+ h.answers.push_back(1168);
+ h.answers.push_back(1169);
+ h.answers.push_back(1170);
+ hints.push_back(h);
+ break;
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ if (!SkyEngine::giveScriptVar(700)) {
+ if (SkyEngine::hasSeenScreen(70) && !SkyEngine::giveScriptVar(696)) {
+ h.question = 39;
+ h.answers.clear();
+ h.answers.push_back(1171);
+ h.answers.push_back(1172);
+ h.answers.push_back(1173);
+ h.answers.push_back(1174);
+ hints.push_back(h);
+ }
+ if (SkyEngine::giveScriptVar(72) > 0) {
+ h.question = 40;
+ h.answers.clear();
+ h.answers.push_back(1175);
+ h.answers.push_back(1176);
+ h.answers.push_back(1177);
+ h.answers.push_back(1178);
+ hints.push_back(h);
+ }
+ if (!SkyEngine::giveScriptVar(72)) {
+ h.question = 41;
+ h.answers.clear();
+ h.answers.push_back(1179);
+ h.answers.push_back(1180);
+ h.answers.push_back(1181);
+ h.answers.push_back(1182);
+ h.answers.push_back(1183);
+ hints.push_back(h);
+ }
+ break;
+ }
+ if (!SkyEngine::giveScriptVar(703)) {
+ h.question = 42;
+ h.answers.clear();
+ h.answers.push_back(1184);
+ h.answers.push_back(1185);
+ h.answers.push_back(1186);
+ h.answers.push_back(1187);
+ h.answers.push_back(1188);
+ hints.push_back(h);
+ break;
+ }
+ if (!SkyEngine::giveScriptVar(642)) {
+ h.question = 43;
+ h.answers.clear();
+ h.answers.push_back(1189);
+ h.answers.push_back(1190);
+ hints.push_back(h);
+ break;
+ }
+ if (!SkyEngine::giveScriptVar(713)) {
+ h.question = 45;
+ h.answers.clear();
+ h.answers.push_back(1197);
+ h.answers.push_back(1198);
+ h.answers.push_back(1199);
+ h.answers.push_back(1200);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(719) != 2) {
+ h.question = 46;
+ h.answers.clear();
+ h.answers.push_back(1201);
+ h.answers.push_back(1202);
+ h.answers.push_back(1203);
+ hints.push_back(h);
+ break;
+ }
+ if (SkyEngine::giveScriptVar(708) != 3) {
+ h.question = 47;
+ h.answers.clear();
+ h.answers.push_back(1204);
+ h.answers.push_back(1205);
+ h.answers.push_back(1206);
+ h.answers.push_back(1207);
+ hints.push_back(h);
+ break;
+ } else {
+ h.question = 48;
+ h.answers.clear();
+ h.answers.push_back(1208);
+ h.answers.push_back(1209);
+ h.answers.push_back(1210);
+ h.answers.push_back(1211);
+ hints.push_back(h);
+ break;
+ }
+ break;
+ case 81:
+ h.question = 49;
+ h.answers.clear();
+ h.answers.push_back(1212);
+ hints.push_back(h);
+ break;
+ default:
+ break;
+ }
+ h.question = 54;
+ h.answers.clear();
+ hints.push_back(h);
+ h.question = 55;
+ hints.push_back(h);
+
+ if (2 == SkyEngine::giveScriptVar(106)) {
+ h.question = 56;
+ hints.push_back(h);
+ }
+ return hints;
+}
+
+int Control::drawHintList(Graphics::Surface *scaled, int destX, int destY, int newW, Graphics::Font *font, const Common::Array<Hint> &hints, Common::Array<Common::Rect> &hintRects, int scrollOffset) {
+ _skyScreen->_screen32.fillRect(Common::Rect(0, 0, _skyScreen->_screen32.w, _skyScreen->_screen32.h), 0);
+ _skyScreen->_screen32.copyRectToSurface(*scaled, destX, destY, Common::Rect(0, 0, scaled->w, scaled->h));
+ hintRects.clear();
+
+ int textWrapWidth = newW - 30;
+ uint32 colorWhite = _skyScreen->_screen32.format.RGBToColor(255, 255, 255);
+ int y = destY + 40 - scrollOffset;
+
+ for (uint i = 0; i < hints.size(); i++) {
+ Common::U32String text = SkyEngine::lookUpAscii(hints[i].question + 1000);
+ Common::Array<Common::U32String> lines;
+ font->wordWrapText(text, textWrapWidth, lines);
+ int startY = y;
+ for (uint l = 0; l < lines.size(); l++) {
+ if (y >= destY + 20 && y + font->getFontHeight() <= destY + scaled->h - 20)
+ font->drawString(&_skyScreen->_screen32, lines[l], destX + 10, y, textWrapWidth, colorWhite);
+ y += font->getFontHeight() + 2;
+ }
+ hintRects.push_back(Common::Rect(destX + 10, startY, destX + 10 + textWrapWidth, y));
+ y += 8;
+ }
+ return y;
+}
+
+TappableAnswer Control::drawHintDetail(Graphics::Surface *scaled, int destX, int destY, int newW, Graphics::Font *font, const Hint &hint, int detailScrollOffset, int &detailContentBottom) {
+ _skyScreen->_screen32.fillRect(Common::Rect(0, 0, _skyScreen->_screen32.w, _skyScreen->_screen32.h), 0);
+ _skyScreen->_screen32.copyRectToSurface(*scaled, destX, destY, Common::Rect(0, 0, scaled->w, scaled->h));
+
+ int textWrapWidth = newW - 30;
+ uint32 colorWhite = _skyScreen->_screen32.format.RGBToColor(255, 255, 255);
+ int y = destY + 40 - detailScrollOffset;
+ int topBound = destY + 20;
+ int bottomBound = destY + scaled->h - 20;
+
+ // question text
+ Common::U32String qText = SkyEngine::lookUpAscii(hint.question + 1000);
+ Common::Array<Common::U32String> qLines;
+ font->wordWrapText(qText, textWrapWidth, qLines);
+ for (uint l = 0; l < qLines.size(); l++) {
+ if (y >= topBound && y + font->getFontHeight() <= bottomBound)
+ font->drawString(&_skyScreen->_screen32, qLines[l], destX + 10, y, textWrapWidth, colorWhite);
+ y += font->getFontHeight() + 2;
+ }
+ y += 12;
+
+ // answers
+ TappableAnswer tappable;
+ tappable.answerId = -1;
+ bool foundTappable = false;
+ for (uint j = 0; j < hint.answers.size(); j++) {
+ int answer = hint.answers[j];
+ bool seen = SkyEngine::isHintAnswerSeen(answer - 1057);
+ debug(1, "answer %d, normalized %d, seen %d", answer, answer - 1057, (int)seen);
+
+ Common::U32String text;
+ if (seen) {
+ text = SkyEngine::lookUpAscii(answer);
+ } else {
+ Common::String fmt = Common::String::format(SkyEngine::lookUpAscii(1254).c_str(), j + 1, (int)hint.answers.size());
+ text = Common::U32String(fmt);
+ }
+
+ int startY = y;
+ Common::Array<Common::U32String> lines;
+ font->wordWrapText(text, textWrapWidth, lines);
+ for (uint l = 0; l < lines.size(); l++) {
+ if (y >= topBound && y + font->getFontHeight() <= bottomBound)
+ font->drawString(&_skyScreen->_screen32, lines[l], destX + 10, y, textWrapWidth, colorWhite);
+ y += font->getFontHeight() + 2;
+ }
+
+ if (!seen) {
+ if (!foundTappable) {
+ foundTappable = true;
+ tappable.rect = Common::Rect(destX + 10, startY, destX + 10 + textWrapWidth, y);
+ tappable.answerId = answer;
+ } else {
+ break;
+ }
+ }
+ y += 8;
+ }
+ detailContentBottom = y;
+ return tappable;
+}
+
+void Control::drawScrollButtons(Graphics::Font *font, Graphics::Surface &screen, int destX, int destY, int newW, int panelBottom, int scrollOffset, int contentBottom, uint32 colorGray, Common::Rect &scrollUpRect, Common::Rect &scrollDownRect) {
+ scrollUpRect = Common::Rect();
+ scrollDownRect = Common::Rect();
+ if (scrollOffset > 0) {
+ scrollUpRect = Common::Rect(destX + newW / 2 - 20, destY + 42, destX + newW / 2 + 20, destY + 58);
+ font->drawString(&screen, Common::U32String("^"), scrollUpRect.left, scrollUpRect.top, 40, colorGray);
+ }
+ int textBottomBound = panelBottom - 10;
+ if (contentBottom > textBottomBound) {
+ scrollDownRect = Common::Rect(destX + newW / 2 - 20, panelBottom - 16, destX + newW / 2 + 20, panelBottom);
+ font->drawString(&screen, Common::U32String("v"), scrollDownRect.left, scrollDownRect.top, 40, colorGray);
+ }
+}
+
void Control::initHelpPanel() {
Image::CgBIDecoder d;
Common::File f;
- if (!f.open("hints_txtbox.png") || !d.loadStream(f)) {
- debug("Cannot open file");
+ Common::String fileName = SkyEngine::giveButton("hints_txtbox.png");
+ if (!f.open(Common::Path(fileName)) || !d.loadStream(f)) {
+ debug(1, "Cannot open file");
return;
}
Graphics::Surface *surface = d.getSurface();
if (!surface) {
- debug("No surface");
+ debug(1, "No surface");
return;
}
Graphics::Surface *converted = surface->convertTo(_skyScreen->_screen32.format);
@@ -300,17 +1149,82 @@ void Control::initHelpPanel() {
int destX = (GAME_SCREEN_WIDTH - newW) / 2;
int destY = (FULL_SCREEN_HEIGHT - newH) / 2;
- _skyScreen->_screen32.fillRect(Common::Rect(0, 0, _skyScreen->_screen32.w, _skyScreen->_screen32.h), 0);
- _skyScreen->_screen32.copyRectToSurface(*scaled, destX, destY, Common::Rect(0, 0, scaled->w, scaled->h));
- scaled->free();
- delete scaled;
-
+ Graphics::Font *font = Graphics::loadTTFFontFromArchive("NotoSans-Regular.ttf", 12);
+ Common::Array<Hint> hints = buildHints();
+ Common::Array<Common::Rect> hintRects;
+ TappableAnswer currentTappable;
+ currentTappable.answerId = -1;
+ int selectedHint = -1;
+ int scrollOffset = 0;
+ int detailScrollOffset = 0;
+ int detailContentBottom = 0;
+ Common::Rect scrollUpRect;
+ Common::Rect scrollDownRect;
+ int contentBottom = drawHintList(scaled, destX, destY, newW, font, hints, hintRects, scrollOffset);
+ int panelBottom = destY + newH - 10;
+ uint32 colorGray = _skyScreen->_screen32.format.RGBToColor(180, 180, 180);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, scrollOffset, contentBottom, colorGray, scrollUpRect, scrollDownRect);
_mouseClicked = false;
- while (!_mouseClicked && !Engine::shouldQuit()) {
- _system->copyRectToScreen(_skyScreen->_screen32.getPixels(), _skyScreen->_screen32.pitch, 0, 0, _skyScreen->_screen32.w, _skyScreen->_screen32.h);
+ while (!Engine::shouldQuit()) {
+ if (_skyScreen->_screen32.getPixels())
+ _system->copyRectToScreen(_skyScreen->_screen32.getPixels(), _skyScreen->_screen32.pitch, 0, 0, _skyScreen->_screen32.w, _skyScreen->_screen32.h);
_system->updateScreen();
delay(ANIM_DELAY);
+ if (_action == kSkyActionSkip)
+ break;
+
+ if (_mouseClicked) {
+ Common::Point mouse = _system->getEventManager()->getMousePos();
+ _mouseClicked = false;
+ if (selectedHint == -1) {
+ if (scrollUpRect.width() > 0 && scrollUpRect.contains(mouse)) {
+ scrollOffset = MAX(0, scrollOffset - 50);
+ contentBottom = drawHintList(scaled, destX, destY, newW, font, hints, hintRects, scrollOffset);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, scrollOffset, contentBottom, colorGray, scrollUpRect, scrollDownRect);
+ } else if (scrollDownRect.width() > 0 && scrollDownRect.contains(mouse)) {
+ scrollOffset += 50;
+ contentBottom = drawHintList(scaled, destX, destY, newW, font, hints, hintRects, scrollOffset);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, scrollOffset, contentBottom, colorGray, scrollUpRect, scrollDownRect);
+ } else {
+ for (uint i = 0; i < hintRects.size(); i++) {
+ if (hintRects[i].contains(mouse)) {
+ selectedHint = (int)i;
+ detailScrollOffset = 0;
+ currentTappable = drawHintDetail(scaled, destX, destY, newW, font, hints[selectedHint], detailScrollOffset, detailContentBottom);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, detailScrollOffset, detailContentBottom, colorGray, scrollUpRect, scrollDownRect);
+ break;
+ }
+ }
+ }
+ } else {
+ if (scrollUpRect.width() > 0 && scrollUpRect.contains(mouse)) {
+ detailScrollOffset = MAX(0, detailScrollOffset - 50);
+ currentTappable = drawHintDetail(scaled, destX, destY, newW, font, hints[selectedHint], detailScrollOffset, detailContentBottom);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, detailScrollOffset, detailContentBottom, colorGray, scrollUpRect, scrollDownRect);
+ } else if (scrollDownRect.width() > 0 && scrollDownRect.contains(mouse)) {
+ detailScrollOffset += 50;
+ currentTappable = drawHintDetail(scaled, destX, destY, newW, font, hints[selectedHint], detailScrollOffset, detailContentBottom);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, detailScrollOffset, detailContentBottom, colorGray, scrollUpRect, scrollDownRect);
+ } else if (currentTappable.answerId != -1 && currentTappable.rect.contains(mouse)) {
+ SkyEngine::setHintAnswerSeen(currentTappable.answerId - 1057);
+ currentTappable = drawHintDetail(scaled, destX, destY, newW, font, hints[selectedHint], detailScrollOffset, detailContentBottom);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, detailScrollOffset, detailContentBottom, colorGray, scrollUpRect, scrollDownRect);
+ debug(1, "tappable answerId: %d, rect: (%d, %d, %d, %d)", currentTappable.answerId, currentTappable.rect.left, currentTappable.rect.top, currentTappable.rect.right, currentTappable.rect.bottom);
+ } else {
+ // back to question
+ selectedHint = -1;
+ currentTappable.answerId = -1;
+ contentBottom = drawHintList(scaled, destX, destY, newW, font, hints, hintRects, scrollOffset);
+ drawScrollButtons(font, _skyScreen->_screen32, destX, destY, newW, panelBottom, scrollOffset, contentBottom, colorGray, scrollUpRect, scrollDownRect);
+ }
+ }
+ }
}
+ _skyScreen->forceRefresh();
+ _skyScreen->setPaletteEndian((uint8 *)_skyCompact->fetchCpt(SkyEngine::_systemVars->currentPalette));
+ delete font;
+ scaled->free();
+ delete scaled;
}
void Control::initPanel() {
@@ -1605,6 +2519,15 @@ void Control::restartGame() {
uint8 *resetData = _skyCompact->createResetData((uint16)SkyEngine::_systemVars->gameVersion);
parseSaveData((uint8 *)resetData);
free(resetData);
+
+ // reset the hints
+ for (int i = 0; i < TOTAL_HINT_ANSWERS; i++)
+ SkyEngine::_systemVars->pastIntro = true;
+
+ // seen screen flags
+ for (int i = 0; i < TOTAL_SCREENS; i++)
+ SkyEngine::_systemVars->pastIntro = true;
+
_skyScreen->forceRefresh();
memset(_skyScreen->giveCurrent(), 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT);
diff --git a/engines/sky/control.h b/engines/sky/control.h
index 4f275436dc7..9ac2ba9ae7c 100644
--- a/engines/sky/control.h
+++ b/engines/sky/control.h
@@ -26,6 +26,7 @@
#include "common/events.h"
#include "common/scummsys.h"
#include "common/str-array.h"
+#include "graphics/font.h"
class OSystem;
namespace Common {
@@ -132,6 +133,16 @@ struct AllocedMem {
AllocedMem *next;
};
+struct Hint {
+ int question;
+ Common::Array<int> answers;
+};
+
+struct TappableAnswer {
+ Common::Rect rect;
+ int answerId;
+};
+
class ConResource {
public:
ConResource(void *pSpData, uint32 pNSprites, uint32 pCurSprite, uint16 pX, uint16 pY, uint32 pText, uint8 pOnClick, OSystem *system, uint8 *screen);
@@ -189,6 +200,9 @@ public:
uint16 quickXRestore(uint16 slot);
bool loadSaveAllowed();
bool isControlPanelOpen();
+ int drawHintList(Graphics::Surface *scaled, int destX, int destY, int newW, Graphics::Font *font, const Common::Array<Hint> &hints, Common::Array<Common::Rect> &hintRects, int scrollOffset);
+ TappableAnswer drawHintDetail(Graphics::Surface *scaled, int destX, int destY, int newW, Graphics::Font *font, const Hint &hint, int detailScrollOffset, int &detailContentBottom);
+ void drawScrollButtons(Graphics::Font *font, Graphics::Surface &screen, int destX, int destY, int newW, int panelBottom, int scrollOffset, int contentBottom, uint32 colorGray, Common::Rect &scrollUpRect, Common::Rect &scrollDownRect);
SkyEngine *_vm;
@@ -203,6 +217,7 @@ private:
void initPanel();
void initHelpPanel(); // for ibass
+ Common::Array<Hint> buildHints();
void removePanel();
void drawMainPanel();
diff --git a/engines/sky/ibasstext.cpp b/engines/sky/ibasstext.cpp
new file mode 100644
index 00000000000..602e6bfa501
--- /dev/null
+++ b/engines/sky/ibasstext.cpp
@@ -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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sky/ibasstext.h"
+#include "common/array.h"
+
+namespace Sky {
+
+const char *const ukAscii[] = {
+ "The Firedoor is locked â how do I open it?",
+ "I do wish that Joey was with me â what should I do?",
+ "How do I get that elevator working?",
+ "How do I get down the elevator shaft?",
+ "How do I get out of the furnace room?",
+ "I need to de-activate the welder robot. Help!",
+ "How do I get the welder shell for Joey?",
+ "How can I get into the storeroom?",
+ "How can I stop things I get from the storeroom being confiscated?",
+ "How can I get rid of the man in the power room?",
+ "How can I restore power?",
+ "How can I use that elevator?",
+ "How do I get a ticket from the travel agent?",
+ "What should I do with this ticket?",
+ "Lamb has my ticket â what now?",
+ "How do I get into the surgery?",
+ "How do I get a Schriebmann port?",
+ "How can I get that anchor?",
+ "Iâve got the anchor â what now?",
+ "What do I do with this grappling hook?",
+ "Iâm in the security HQ. What next?",
+ "Iâm stuck in the LINC world â what should I do?",
+ "Iâm in a cyber maze â how do I get through it?",
+ "Iâm through the cyber maze â what now?",
+ "How do I get out of LINC space?",
+ "Iâve got to ground level. What should I do now?",
+ "How do I get those dog biscuits?",
+ "How do I get past the security man?",
+ "Iâm in the cathedral â what now?",
+ "Anitaâs been murdered. What should I do?",
+ "Iâve got Anitaâs card â maybe she left some clues?",
+ "Iâve read Anitaâs message â how do I make contact with Eduardo?",
+ "Iâve made contact with Eduardo. What now?",
+ "Iâve got Colstonâs glass, but why?",
+ "How do get through to the subway?",
+ "Iâve made a hole in the grill â how do I enlarge the hole?",
+ "Iâve made a hole in the grill â what now?",
+ "Thereâs a creature that grabs me â how can I avoid it?",
+ "How do I get through the big metal door?",
+ "Thereâs a strange pit â what do I do with it?",
+ "What do I do in this strange underworld?",
+ "How can we get past the android in the lab?",
+ "I killed the android. What next?",
+ "Anita mentioned a virus â how do I get it?",
+ "I'm back in LINC â how do I get the virus?",
+ "Poor old Joey â how do I get resurrect him? Again!",
+ "Iâve turned Joey into an android. What I do with him?",
+ "Iâve got the virus from LINC â how do I get it into the real world?",
+ "Iâve got some infected tissue â what now?",
+ "Iâve met my own father â how do I save humanity?",
+ "I've out-foxed the guard - what now?",
+ "I'm in an industrial area. What should I do?",
+ "I've found some putty-like substance - but what now?",
+ "I've given myself special security status on LINC - now what?",
+ "User interface and game controls â help!",
+ "Inventory Instructions",
+ "First screen walkthrough",
+ // Hint answers
+ "Get the rung from the top of the stairs on the left of the gantry.",
+ "Open your inventory and use the rung on the fire door to lever it open. See the 'First Screen Walkthrough' for detailed explanation.",
+ "Examine the junk in the foreground to reveal the robot shell.",
+ "Use the circuit board on the robot shell.",
+ "Examine the transport droid.",
+ "Talk to Hobbins until you get option to ask him about the transport droid â and he tells you whatâs wrong with it.",
+ "Ask Joey to start the transport droid (you may need to talk nicely to him about a range of subjects beforehand).",
+ "When the elevator descends, quickly climb down the shaft.",
+ "Examine the lock on the door.",
+ "When joey arrives, ask him to open the door.",
+ "You need to âthrow a wrench in the worksâ.",
+ "Did you find the wrench in Hobbinsâs workshop? If not, then return to Hobbinsâs workshop, open the cupboard and take the wrench.",
+ "Return to the production line â in the room beyond the welder robot you will see some gears.",
+ "If you havenât done so, talk to Anita and then Lamb until he leaves. Then throw the wrench into the gears.",
+ "Retrieve the wrench from the cogs.",
+ "Use the wrench on the welder robot.",
+ "Talk to Joey, and offer him a new shell.",
+ "Attempt to enter the storeroom.",
+ "Tell Joey to check out the storeroom. When he reports that he has found the fusebox, tell him to disable the fuse box.",
+ "Lift the gangway on the floor.",
+ "Pick up the putty (plastic explosive) which was under the gangway. This is the only object that you can keep after leaving.",
+ "Use the wrench on each of the two buttons beneath the pipes on the right.",
+ "Tell Joey to press the right hand button, then press the other as he does so.",
+ "Turn off the switch on the control panel on the left.",
+ "Remove the light bulb.",
+ "Put the putty in the light fitting.",
+ "Turn the switch back on.",
+ "Pull the right hand power switch down to restore power to the lift.",
+ "Examine Reichâs corpse in the furnace room to get his ID.",
+ "Use Reichâs ID card on the lift slot.",
+ "Go to Reichâs apartment and lift the pillow to reveal a motorbiking magazine.",
+ "Go to the travel agent and ask him about the tours.",
+ "Ask for the economy tour.",
+ "Give him the motorbiking magazine in return for a tour ticket.",
+ "Give the ticket to Lamb to be invited on a tour of the pipe factory.",
+ "Ask Lamb about the tour â he will leave when he sees that the conveyor has stopped.",
+ "Talk to Anita.",
+ "She will eventually offer you a âjammerâ â give her Reichâs ID.",
+ "Talk further to learn about the Schriebmann port.",
+ "Talk to the surgery receptionist by clicking on the projector.",
+ "Ask for a Schriebmann port.",
+ "Ask Joey to talk to the receptionist to gain admittance to the surgery.",
+ "Talk to Burke until you get an offer to fit a Schriebmann port.",
+ "After the operation, keep talking to Burke to learn about Anchorâs âspecial policyâ.",
+ "Visit Anchor in the insurance office and mention Burkeâs name to get him out of the room.",
+ "Ask Joey to get the anchor from the statue.",
+ "Pick up the anchor after Joey has melted the statueâs arm.",
+ "If you donât have it, now would be a good time to get the cable hanging from the Industrial level.",
+ "Ask Joey to cut the loose cable - get out of his way.",
+ "Retrieve the cable which has fallen onto the Belle Vue level.",
+ "Use the anchor on the cable to create a grappling hook.",
+ "Go to the fire door in Hobbins's recycling plant and walk out on the ledge.",
+ "Use the grappling hook on the security sign on the opposite wall.",
+ "In the Security HQ, use the ID card on the slot and sit down.",
+ "Pick up the ball (compressed data) in area 1.",
+ "Go right to area 2 and use open (in inventory) on the carpet bag.",
+ "Get the birthday surprise (decompress). Use decompress on compressed data (in inventory).",
+ "Get magnifying glass (decrypt) and use it on report.doc and briefing.doc (in inventory).",
+ "Use green password on lower row / left tile. Use red password on lower row / centre tile.",
+ "Pick up the green password and use on middle row / left tile.",
+ "Pick up the red password and use on central tile.",
+ "Pick up the green password and use on lower row / right tile.",
+ "Get book (phoenix.doc).",
+ "Use decrypt on phoenix.doc.",
+ "Get bust (phoenix program).",
+ "Disconnect from LINC.",
+ "Use ID card on LINC terminal.",
+ "Select âSecurity servicesâ. Select âview documentsâ",
+ "Read each document. Note that they need to have been decrypted in LINC space.",
+ "Select âspecial operationsâ. Select âspecial status requestâ.",
+ "Select âfile adjustmentâ to D-LINC Lamb.",
+ "Talk to Henri, the bouncer, to find out about sponsorship for the club.",
+ "Talk to Danielle to be invited back to her apartment.",
+ "Go back to Danielleâs Apartment.",
+ "You will need the cat video from Lambâs apartment.",
+ "D-LINC Lamb from âfile adjustmentâ on the LINC terminal, and then talk to him.",
+ "While Danielle is on the phone, play the video.",
+ "While the dog is distracted, get the dog biscuits.",
+ "Go to the see-saw by the lake and use the dog biscuits on the plank.",
+ "When the dog is nearby, pull the rope.",
+ "When the dog gets onto the plank, release the rope.",
+ "Explore the lockers in the lower level - until you discover the terrible truth.",
+ "Return to the reactor in the factory and put on the radiation suit.",
+ "Go to the terminal and open the reactor. Inside, pick up Anitaâs ID card.",
+ "Go back through the Security building.",
+ "Enter LINC using Anitaâs card.",
+ "Use âblindâ on the eyeball in area 2.",
+ "Use âplaybackâ on the holographic projector (âwellâ) to view Anitaâs message.",
+ "Disconnect from LINC.",
+ "Return to Hyde Park.",
+ "Talk to Vincent to find out about the gardener.",
+ "Talk to the gardener until he tells you about the virus.",
+ "Walk into the courtroom to witness Hobbinsâs trial.",
+ "Go to the club.",
+ "Select âYou search, but find nothingâ on jukebox.",
+ "Get Colstonâs glass while he is away from the table.",
+ "Give the glass to Burke to get fingerprints.",
+ "Touch the plate to open the door to the wine cellar.",
+ "Use the crowbar on the large box on the left.",
+ "Get the lid and use it on the smaller box.",
+ "Climb on top of the box.",
+ "Use the crowbar on the grill.",
+ "If you havenât found the secateurs then go to the shed in the park.",
+ "Look at the door.",
+ "Use the ID card on the lock.",
+ "Enter the shed and get the secateurs.",
+ "Use the secateurs on the grill.",
+ "Climb through the grill.",
+ "Use the light bulb on the light socket to the left of the creatureâs hole.",
+ "Use the crowbar on the crumbling plaster, then again on the brickwork to obtain a brick.",
+ "-",
+ "Use the crowbar on the clot in the vein.",
+ "Use the brick on the crowbar to puncture the clot.",
+ "Wait until the medical robot comes to repair the puncture, then exit through the door to the right.",
+ "Close the cover over the pit using the terminal beside the pit.",
+ "Climb on top of the pit cover.",
+ "Pull the retaining bar on the grill above your head to loosen the grill.",
+ "Return to the room above.",
+ "Look through the grills to warn of any impending danger.",
+ "Look through the first grill that you encounter.",
+ "Walk right to the room where the medical robot is recharging.",
+ "Use the circuit board on the medical robot.",
+ "Talk to Joey and send him into the tank room.",
+ "Ask Joey what he saw in the tank room.",
+ "Ask Joey about the tank.",
+ "Tell Joey to open the tap.",
+ "Enter the tank room and watch the android plunge to his death.",
+ "Walk to the right of the tanks, into the computer room.",
+ "Use Reichâs ID card on the terminal (to the left of the bank of computers).",
+ "Open the access door.",
+ "Leave the computer room and watch Joey get destroyed again.",
+ "Take Gallagherâs card from his remains.",
+ "Return to the computer room.",
+ "Enter LINC using Gallagherâs card.",
+ "You need to enter LINC using Gallagherâs card. Drop out, then return again.",
+ "Use blind on the eyeball in area 1. Quickly go to area 2 and blind the eyeball.",
+ "Get the oscillator (tuning fork).",
+ "Go to the Crusader room. Use âdivine wrathâ to remove the Crusader.",
+ "Enter the crystal room. Use the oscillator on the crystal.",
+ "Get the virus. Disconnect from LINC.",
+ "Go to the special android room. Open the cabinet on the middle console.",
+ "Insert the circuit board in the cabinet.",
+ "Use the monitor to download the data from the board.",
+ "Run the android start-up program.",
+ "Go right to the room with the large tanks.",
+ "Ask Joey/Ken to put his hand on the door panel.",
+ "Put your own hand on the other panel.",
+ "Go to the tank of tissue samples and get the tongs from the wall (just to right of tank).",
+ "Use Gallagherâs card (or whichever card contains the virus) on the console to infect the tissue with the virus.",
+ "Remove a sample of infected tissue with the tongs.",
+ "Put the sample of tissue into the nitrogen tank to freeze it.",
+ "Go to the end of the pipes. Attach the cable to the pipe support.",
+ "Use the rungs to descend to the feeding orifice.",
+ "Drop the infected tissue into the orifice.",
+ "Use the hanging rope to swing into the final room.",
+ "When Joey/Ken enters tell him to sit in the chair.",
+ "Explore the factory. Perhaps you'll be able to get Joey working again.",
+ "Take a look around - there must be someone around who can help.",
+ "Explore some more - there's sure to be more to find.",
+ "Take the elevator down to the level below, and then take the next elevator down to ground level.",
+ "Moving around the environment",
+ "Tap a point on the floor area and Foster will walk there - if he can. To leave an area, you will need to interact with the exit arrow icon.",
+ "Interacting with the environment",
+ "Slide your finger around the game screen to find areas of interest (hotspots). Animating blue circles will appear over hotspots as your finger gets close to them. Slide your finger over the blue circle and action icons will be displayed to indicate what actions Foster can perform. To perform that action, lift your finger and tap the specific icon.",
+ "DUMMY LINE",
+ "The inventory â what is it?",
+ "Items that Foster picks up go into the âinventoryâ. Tap the box icon to display the items in the inventory. Tap an item to get a description of it.",
+ "How to use an inventory item on background objects and people",
+ "Open the inventory and press on an item for a few moments until it appears above your finger. While continuing to press the screen, drag the item over a hotspot and release when it highlights with a blue outline.",
+ "Combining inventory items",
+ "Sometimes you will need to combine two inventory items to create a third item. To do this, select the first item by pressing on it for a few moments until it appears above your finger. Now drag the item straight onto the second item â release when both are highlighted with a blue outline.",
+ "Walkthrough for getting Foster to open the fire-door",
+ "Slide your finger over the rung that is to the far left of the screen. A blue circle will animate over the rung as you get close. When your finger is over the rung, two icons will appear â turning cogs (interact) and a blinking eye (examine), and the word 'Rung' will appear at the top of the screen. Lift your finger and tap the cogs. The cogs will flash, and Foster will walk to the rung and pull it off. He will automatically put the rung into his inventory - where it will appear as 'Metal Bar.'",
+ "LINE DELETED",
+ "Open the inventory by tapping on the box icon. Press on the metal bar icon until it is displayed above your finger with a blue outline, then drag it across to the fire door until your finger is over the blue circle and 'Door' is displayed at the top of the screen, then lift your finger. Foster will now use the metal bar to lever open the fire door. Foster will then automatically walk out. Good luck!",
+ "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?",
+ "Hint %d of %d"
+};
+
+const uint kUkAsciiCount = ARRAYSIZE(ukAscii);
+
+}
diff --git a/engines/sky/ibasstext.h b/engines/sky/ibasstext.h
new file mode 100644
index 00000000000..e867ab22052
--- /dev/null
+++ b/engines/sky/ibasstext.h
@@ -0,0 +1,34 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SKY_IBASSTEXT_H
+#define SKY_IBASSTEXT_H
+
+#include "common/scummsys.h"
+
+namespace Sky {
+
+extern const char *const ukAscii[];
+extern const uint kUkAsciiCount;
+
+}
+
+#endif
diff --git a/engines/sky/module.mk b/engines/sky/module.mk
index efb19e77cf9..fae3317711b 100644
--- a/engines/sky/module.mk
+++ b/engines/sky/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS := \
disk.o \
grid.o \
hufftext.o \
+ ibasstext.o \
intro.o \
inventory.o \
logic.o \
diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp
index be9355bb613..81baee63729 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -101,6 +101,8 @@ SkyEngine::SkyEngine(OSystem *syst)
_skyDisk = nullptr;
_skyControl = nullptr;
_skyCompact = nullptr;
+
+ _curScreen = 0xFFFF;
}
SkyEngine::~SkyEngine() {
@@ -243,10 +245,15 @@ Common::Error SkyEngine::go() {
uint32 delayCount = _system->getMillis();
while (!shouldQuit()) {
_skySound->checkFxQueue();
- if (SkyEngine::isIbass())
+ if (SkyEngine::isIbass()) {
+ if (_curScreen != Logic::_scriptVariables[SCREEN]) {
+ _curScreen = Logic::_scriptVariables[SCREEN];
+ setSeenScreen(_curScreen);
+ }
_skyMouse->mouseEngineIBASS();
- else
+ } else {
_skyMouse->mouseEngine();
+ }
handleKey();
if (_systemVars->paused) {
do {
@@ -606,4 +613,57 @@ bool SkyEngine::isIbass() {
return false;
}
+int SkyEngine::giveCurrentScreen() {
+ return Logic::_scriptVariables[SCREEN];
+}
+
+uint32 SkyEngine::giveScriptVar(uint32 s) {
+ return Logic::_scriptVariables[s];
+}
+
+void SkyEngine::setSeenScreen(int screen) {
+ if (screen >= TOTAL_SCREENS) {
+ debug(1, "setSeenScreen: illegal screen %d", screen);
+ return;
+ }
+ SkyEngine::_systemVars->_seenScreen[screen] = true;
+}
+
+bool SkyEngine::hasSeenScreen(int screen) {
+ if (screen >= TOTAL_SCREENS) {
+ debug(1, "hasSeenScreen: illegal screen %d", screen);
+ return false;
+ }
+ return SkyEngine::_systemVars->_seenScreen[screen];
+}
+
+void SkyEngine::setHintAnswerSeen(int answer) {
+ if (answer >= TOTAL_HINT_ANSWERS) {
+ debug(1, "setHintAnswerSeen: illegal answer %d", answer);
+ return;
+ }
+ SkyEngine::_systemVars->_answerSeen[answer] = true;
+}
+
+bool SkyEngine::isHintAnswerSeen(int answer) {
+ if (answer >= TOTAL_HINT_ANSWERS) {
+ debug(1, "isHintAnswerSeen: illegal answer %d", answer);
+ return false;
+ }
+ return SkyEngine::_systemVars->_answerSeen[answer];
+}
+
+Common::String SkyEngine::lookUpAscii(int line) {
+ line -= 1000;
+ if (line < 0 || line >= (int)kUkAsciiCount) {
+ debug(1, "lookUpAscii: illegal line %d", line);
+ return Common::U32String("???");
+ }
+ return Common::U32String(ukAscii[line]);
+}
+
+Common::String SkyEngine::giveButton(const Common::String &button) {
+ return button;
+}
+
} // End of namespace Sky
diff --git a/engines/sky/sky.h b/engines/sky/sky.h
index bb878abffd8..8b0b8ce28a6 100644
--- a/engines/sky/sky.h
+++ b/engines/sky/sky.h
@@ -28,6 +28,7 @@
#include "common/keyboard.h"
#include "engines/engine.h"
#include "graphics/big5.h"
+#include "sky/ibasstext.h"
/**
* This is the namespace of the Sky engine.
@@ -39,6 +40,10 @@
*/
namespace Sky {
+
+#define TOTAL_SCREENS 100
+#define TOTAL_HINT_ANSWERS 164
+
struct SystemVars {
uint32 systemFlags;
uint32 gameVersion;
@@ -50,6 +55,8 @@ struct SystemVars {
bool pastIntro;
bool paused;
bool textDirRTL;
+ bool _seenScreen[TOTAL_SCREENS];
+ bool _answerSeen[TOTAL_HINT_ANSWERS];
};
class Sound;
@@ -118,7 +125,18 @@ public:
Graphics::Big5Font *_big5Font;
bool canSaveGameStateCurrently();
- int giveCurrentScreen();
+ static int giveCurrentScreen();
+
+ static uint32 giveScriptVar(uint32 s);
+ void setSeenScreen(int screen);
+ static bool hasSeenScreen(int screen);
+ static void setHintAnswerSeen(int answer);
+ static bool isHintAnswerSeen(int answer);
+
+ uint16 _curScreen;
+
+ static Common::String lookUpAscii(int line);
+ static Common::String giveButton(const Common::String &button);
protected:
// Engine APIs
More information about the Scummvm-git-logs
mailing list