[Scummvm-git-logs] scummvm master -> 13eb6f3be096392b48681a072e36ea6df75ea020
sev-
noreply at scummvm.org
Tue Feb 28 00:58:21 UTC 2023
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
4d5ec3c73c GRAPHICS: Rename DownscaleAllByHalfARM to downscaleAllByHalfARM
a99d59551e GRAPHICS: Add 2x downscaler for CLUT images
90f8c24265 ENGINES: Allow to specify several supported resolutions
7dba71d671 PLUMBERS: Remove need for highres
35d72e4487 PLUMBERS: Use smaller cursor on lower resolutions
573bd18cd3 PLUMBERS: Mark 3DO version as supported
13eb6f3be0 DREAMWEB: Don't use 640x480 if USE_HIGHRES is false
Commit: 4d5ec3c73caa90048f09c17cbdd40a1175a2f6d5
https://github.com/scummvm/scummvm/commit/4d5ec3c73caa90048f09c17cbdd40a1175a2f6d5
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-02-28T01:58:13+01:00
Commit Message:
GRAPHICS: Rename DownscaleAllByHalfARM to downscaleAllByHalfARM
Changed paths:
graphics/scaler/downscaler.cpp
graphics/scaler/downscalerARM.s
diff --git a/graphics/scaler/downscaler.cpp b/graphics/scaler/downscaler.cpp
index e107fdb7a52..5991df1fdd4 100644
--- a/graphics/scaler/downscaler.cpp
+++ b/graphics/scaler/downscaler.cpp
@@ -25,7 +25,7 @@ int gBitFormat = 565;
#ifdef USE_ARM_SCALER_ASM
extern "C" {
- void DownscaleAllByHalfARM(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height, int mask, int round);
+ void downscaleAllByHalfARM(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height, int mask, int round);
}
void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
@@ -34,7 +34,7 @@ void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uin
static const int redbluegreenMasks[] = { 0x03E07C1F, 0x07E0F81F };
const int maskUsed = (gBitFormat == 565);
- DownscaleAllByHalfARM(srcPtr, srcPitch, dstPtr, dstPitch, width, height, redbluegreenMasks[maskUsed], roundingconstants[maskUsed]);
+ downscaleAllByHalfARM(srcPtr, srcPitch, dstPtr, dstPitch, width, height, redbluegreenMasks[maskUsed], roundingconstants[maskUsed]);
}
#else
diff --git a/graphics/scaler/downscalerARM.s b/graphics/scaler/downscalerARM.s
index 1df83f035dc..8fe73b4f6a4 100644
--- a/graphics/scaler/downscalerARM.s
+++ b/graphics/scaler/downscalerARM.s
@@ -21,7 +21,7 @@
.text
- .global DownscaleAllByHalfARM
+ .global downscaleAllByHalfARM
@ ARM implementation of DownscaleAllByHalf scaler.
@ Scales a width x height block of 16bpp pixels from srcPtr to
@@ -29,7 +29,7 @@
@ lines. redblueMask and round allow for one routine to do both
@ 565 and 555 formats.
.align 2
-DownscaleAllByHalfARM:
+downscaleAllByHalfARM:
@ r0 = srcPtr
@ r1 = srcPitch
@ r2 = dstPtr
Commit: a99d59551ebb89884547fa36bc3a865ed8ad7991
https://github.com/scummvm/scummvm/commit/a99d59551ebb89884547fa36bc3a865ed8ad7991
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-02-28T01:58:13+01:00
Commit Message:
GRAPHICS: Add 2x downscaler for CLUT images
Changed paths:
graphics/module.mk
graphics/scaler/downscaler.cpp
graphics/scaler/downscaler.h
diff --git a/graphics/module.mk b/graphics/module.mk
index 1e63b227526..59e1ed4f08b 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -42,6 +42,7 @@ MODULE_OBJS := \
primitives.o \
renderer.o \
scalerplugin.o \
+ scaler/downscaler.o \
scaler/thumbnail_intern.o \
screen.o \
scaler/normal.o \
@@ -57,6 +58,11 @@ MODULE_OBJS := \
wincursor.o \
yuv_to_rgb.o
+ifdef USE_ARM_SCALER_ASM
+MODULE_OBJS += \
+ scaler/downscalerARM.o
+endif
+
ifdef USE_TINYGL
MODULE_OBJS += \
tinygl/api.o \
@@ -95,7 +101,6 @@ MODULE_OBJS += \
scaler/dotmatrix.o \
scaler/sai.o \
scaler/pm.o \
- scaler/downscaler.o \
scaler/scale2x.o \
scaler/scale3x.o \
scaler/scalebit.o \
@@ -103,7 +108,6 @@ MODULE_OBJS += \
ifdef USE_ARM_SCALER_ASM
MODULE_OBJS += \
- scaler/downscalerARM.o \
scaler/scale2xARM.o \
scaler/Normal2xARM.o
endif
diff --git a/graphics/scaler/downscaler.cpp b/graphics/scaler/downscaler.cpp
index 5991df1fdd4..8f1dab82f14 100644
--- a/graphics/scaler/downscaler.cpp
+++ b/graphics/scaler/downscaler.cpp
@@ -18,17 +18,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+#include "common/debug.h"
#include "graphics/scaler/downscaler.h"
#include "graphics/scaler/intern.h"
-int gBitFormat = 565;
+namespace Graphics {
#ifdef USE_ARM_SCALER_ASM
extern "C" {
void downscaleAllByHalfARM(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height, int mask, int round);
}
-void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
+void downscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height, int gBitFormat) {
// Rounding constants and masks used for different pixel formats
static const int roundingconstants[] = { 0x00200802, 0x00201002 };
static const int redbluegreenMasks[] = { 0x03E07C1F, 0x07E0F81F };
@@ -40,7 +41,7 @@ void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uin
#else
template<typename ColorMask>
-void DownscaleAllByHalfTemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
+void downscaleAllByHalfTemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
uint8 *work;
uint16 srcPitch16 = (uint16)(srcPitch / sizeof(uint16));
@@ -62,11 +63,82 @@ void DownscaleAllByHalfTemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dst
}
}
-void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
+void downscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height, int gBitFormat) {
if (gBitFormat == 565)
- DownscaleAllByHalfTemplate<Graphics::ColorMasks<565> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
+ downscaleAllByHalfTemplate<Graphics::ColorMasks<565> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
else
- DownscaleAllByHalfTemplate<Graphics::ColorMasks<555> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
+ downscaleAllByHalfTemplate<Graphics::ColorMasks<555> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
}
#endif
+
+namespace {
+uint32 getBrightness(byte col, const byte *pal) {
+ return pal[3 * col] * pal[3 * col] + pal[3 * col + 1] * pal[3 * col + 1] + pal[3 * col + 2] * pal[3 * col + 2];
+}
+
+void downscaleCLUT8ByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int maxX, int maxY, const byte *palette) {
+ const byte *src1 = srcPtr;
+ const byte *src2 = srcPtr + srcPitch;
+ byte *dst = dstPtr;
+ int32 srcSkip = 2 * srcPitch - maxX * 2;
+ int32 dstSkip = dstPitch - maxX;
+ for (int y = 0; y < maxY; y++) {
+ for (int x = 0; x < maxX; x++) {
+ // Choose the brightest pixel. Writing often is bright on
+ // a dark background, so this preserves text as much as we can.
+ byte colors[4] = {
+ *src1++,
+ *src1++,
+ *src2++,
+ *src2++
+ };
+
+ byte col = colors[0];
+ uint32 bri = getBrightness(col, palette);
+ for (uint i = 1; i < 4; i++) {
+ uint32 nbri = getBrightness(colors[i], palette);
+ if (nbri > bri) {
+ bri = nbri;
+ col = colors[i];
+ }
+ }
+
+ *dst++ = col;
+ }
+ src1 += srcSkip;
+ src2 += srcSkip;
+ dst += dstSkip;
+ }
+}
+}
+
+void downscaleSurfaceByHalf(Surface *out, const Surface *in, const byte *palette) {
+ if (in->format.isCLUT8() && out->format.isCLUT8() && palette != nullptr) {
+ downscaleCLUT8ByHalf((const byte *) in->getBasePtr(0, 0), in->pitch, (byte *) out->getBasePtr(0, 0), out->pitch,
+ MIN<int>(out->w, in->w / 2), MIN<int>(out->h, in->h / 2), palette);
+ return;
+ }
+
+ if ((in->format == PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)
+ && out->format == PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0))
+ || (in->format == PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)
+ && out->format == PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0))) {
+ downscaleAllByHalf((const byte *) in->getBasePtr(0, 0), in->pitch, (byte *) out->getBasePtr(0, 0), out->pitch,
+ MIN<int>(in->w, out->w * 2), MIN<int>(in->h, out->h * 2), 565);
+ return;
+ }
+
+ if ((in->format == PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)
+ && out->format == PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0))
+ || (in->format == PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0)
+ && out->format == PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0))) {
+ downscaleAllByHalf((const byte *) in->getBasePtr(0, 0), in->pitch, (byte *) out->getBasePtr(0, 0), out->pitch,
+ MIN<int>(in->w, out->w * 2), MIN<int>(in->h, out->h * 2), 555);
+ return;
+ }
+
+ error("downscaleCLUT8ByHalf(): Unsupported downscale format %s->%s", in->format.toString().c_str(), out->format.toString().c_str());
+}
+
+} // end of namespace Graphics
diff --git a/graphics/scaler/downscaler.h b/graphics/scaler/downscaler.h
index f75c7f6530f..c781572084d 100644
--- a/graphics/scaler/downscaler.h
+++ b/graphics/scaler/downscaler.h
@@ -23,12 +23,18 @@
#define GRAPHICS_SCALER_DOWNSCALER_H
#include "common/scummsys.h"
+#include "graphics/surface.h"
+namespace Graphics {
/**
* This filter (down)scales the source image by a factor of 1/2.
* For example, a 320x200 image is scaled to 160x100.
*/
-extern void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr,
- uint32 dstPitch, int width, int height);
+extern void downscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr,
+ uint32 dstPitch, int width, int height, int gBits = 565);
+
+void downscaleSurfaceByHalf(Surface *out, const Surface *in, const byte *palette);
+
+}
#endif
Commit: 90f8c24265aaaf207d2a505025a72708485f71a5
https://github.com/scummvm/scummvm/commit/90f8c24265aaaf207d2a505025a72708485f71a5
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-02-28T01:58:13+01:00
Commit Message:
ENGINES: Allow to specify several supported resolutions
This is useful in order to fallback resolutions even if supported
resolution is not known at compile time.
Changed paths:
engines/engine.cpp
engines/util.h
graphics/mode.h
diff --git a/engines/engine.cpp b/engines/engine.cpp
index d2da357cae5..dc93286b88a 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -310,37 +310,53 @@ void initGraphicsModes(const Graphics::ModeList &modes) {
g_system->initSizeHint(modes);
}
-void initGraphics(int width, int height, const Graphics::PixelFormat *format) {
-
- g_system->beginGFXTransaction();
+/**
+ * Inits any of the modes in "modes". "modes" is in the order of preference.
+ * Return value is index in modes of resulting mode.
+ */
+int initGraphicsAny(const Graphics::ModeWithFormatList &modes) {
+ int candidate = -1;
+ OSystem::TransactionError gfxError = OSystem::kTransactionSizeChangeFailed;
+ int last_width = 0, last_height = 0;
+ for (candidate = 0; candidate < (int)modes.size(); candidate++) {
+ g_system->beginGFXTransaction();
initCommonGFX();
#ifdef USE_RGB_COLOR
- if (format)
- g_system->initSize(width, height, format);
+ if (modes[candidate].hasFormat)
+ g_system->initSize(modes[candidate].width, modes[candidate].height, &modes[candidate].format);
else {
Graphics::PixelFormat bestFormat = g_system->getSupportedFormats().front();
- g_system->initSize(width, height, &bestFormat);
+ g_system->initSize(modes[candidate].width, modes[candidate].height, &bestFormat);
}
#else
- g_system->initSize(width, height);
+ g_system->initSize(modes[candidate].width, modes[candidate].height);
#endif
+ last_width = modes[candidate].width;
+ last_height = modes[candidate].height;
- OSystem::TransactionError gfxError = g_system->endGFXTransaction();
+ gfxError = g_system->endGFXTransaction();
- if (!splash && !GUI::GuiManager::instance()._launched)
- splashScreen();
+ if (!splash && !GUI::GuiManager::instance()._launched)
+ splashScreen();
- if (gfxError == OSystem::kTransactionSuccess)
- return;
+ if (gfxError == OSystem::kTransactionSuccess)
+ return candidate;
+
+ // If error is related to resolution, continue
+ if (gfxError & (OSystem::kTransactionSizeChangeFailed | OSystem::kTransactionFormatNotSupported))
+ continue;
+
+ break;
+ }
// Error out on size switch failure
if (gfxError & OSystem::kTransactionSizeChangeFailed) {
Common::U32String message;
- message = Common::U32String::format(_("Could not switch to resolution '%dx%d'."), width, height);
+ message = Common::U32String::format(_("Could not switch to resolution '%dx%d'."), last_width, last_height);
GUIErrorMessage(message);
- error("Could not switch to resolution '%dx%d'.", width, height);
+ error("Could not switch to resolution '%dx%d'.", last_width, last_height);
}
// Just show warnings then these occur:
@@ -383,6 +399,14 @@ void initGraphics(int width, int height, const Graphics::PixelFormat *format) {
GUI::MessageDialog dialog(_("Could not apply filtering setting."));
dialog.runModal();
}
+
+ return candidate;
+}
+
+void initGraphics(int width, int height, const Graphics::PixelFormat *format) {
+ Graphics::ModeWithFormatList modes;
+ modes.push_back(Graphics::ModeWithFormat(width, height, format));
+ initGraphicsAny(modes);
}
/**
diff --git a/engines/util.h b/engines/util.h
index d84ddbc4822..1310f451e57 100644
--- a/engines/util.h
+++ b/engines/util.h
@@ -79,5 +79,11 @@ void initGraphics(int width, int height, const Common::List<Graphics::PixelForma
* @overload
*/
void initGraphics3d(int width, int height);
+
+/**
+ * Inits any of the modes in "modes". "modes" is in the order of preference.
+ * Return value is index in modes of resulting mode.
+ */
+int initGraphicsAny(const Graphics::ModeWithFormatList &modes);
/** @} */
#endif
diff --git a/graphics/mode.h b/graphics/mode.h
index 9e16ddd216d..28cc12c5fe1 100644
--- a/graphics/mode.h
+++ b/graphics/mode.h
@@ -44,6 +44,28 @@ struct Mode {
typedef Common::Array<Mode> ModeList;
+/**
+ * Represents a hardware video mode with pixel format.
+ */
+struct ModeWithFormat {
+ int16 width; ///< The width in pixels
+ int16 height; ///< The height in pixels
+ bool hasFormat; ///< Whether pixel format is valid
+ Graphics::PixelFormat format; ///< Pixel format
+
+ ModeWithFormat(const int16 w, const int16 h) :
+ width(w), height(h), hasFormat(false) {}
+ ModeWithFormat(const int16 w, const int16 h, const Graphics::PixelFormat &f) :
+ width(w), height(h), hasFormat(true), format(f) {}
+ ModeWithFormat(const int16 w, const int16 h, const Graphics::PixelFormat *f) :
+ width(w), height(h), hasFormat(f != nullptr) {
+ if (f != nullptr)
+ format = *f;
+ }
+};
+
+typedef Common::Array<ModeWithFormat> ModeWithFormatList;
+
}
#endif
Commit: 7dba71d671e352b3c7e0d971d3601c31decb3f1c
https://github.com/scummvm/scummvm/commit/7dba71d671e352b3c7e0d971d3601c31decb3f1c
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-02-28T01:58:13+01:00
Commit Message:
PLUMBERS: Remove need for highres
Downscale images to 320x240 if highres is not supported.
Changed paths:
A engines/plumbers/3do.cpp
A engines/plumbers/POTFILES
A engines/plumbers/windows.cpp
engines/plumbers/configure.engine
engines/plumbers/metaengine.cpp
engines/plumbers/module.mk
engines/plumbers/plumbers.cpp
engines/plumbers/plumbers.h
diff --git a/engines/plumbers/3do.cpp b/engines/plumbers/3do.cpp
new file mode 100644
index 00000000000..f83a406c5ff
--- /dev/null
+++ b/engines/plumbers/3do.cpp
@@ -0,0 +1,702 @@
+/* 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 "plumbers/plumbers.h"
+#include "plumbers/console.h"
+
+#include "audio/decoders/aiff.h"
+#include "audio/decoders/wave.h"
+#include "audio/audiostream.h"
+
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/system.h"
+#include "common/timer.h"
+
+#include "engines/util.h"
+
+#include "graphics/cursorman.h"
+#include "graphics/font.h"
+#include "graphics/fontman.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
+#include "image/cel_3do.h"
+
+#include "video/3do_decoder.h"
+
+namespace Plumbers {
+// TODO(3do):
+// * effect when changing between scenes
+// * 3do boot logo
+// * return to previous scene
+// * hide cursor
+
+namespace {
+// TODO: discover correct offsets
+Common::Point getMikeStart(uint num, uint total) {
+ if (total == 2)
+ return Common::Point(140 * num + 10, 120 * num + 10);
+ return Common::Point(60 * num + 20, 70 * num + 20);
+}
+
+// TODO: discover correct offsets
+Common::Point getMikeSize(uint total) {
+ if (total == 2)
+ return Common::Point(80, 100);
+ return Common::Point(80, 60);
+}
+
+void makeMikeDecision(Scene &scene, uint num) {
+ scene._bitmapNum = 0;
+ scene._startBitmap = 0;
+ scene._decisionChoices = num;
+ scene._waveFilename = "";
+ scene._style = Scene::STYLE_DECISION_MIKE;
+
+ Common::Point sz = getMikeSize(num);
+
+ for (uint i = 0; i < num; i++) {
+ Common::Point ms = getMikeStart(i, num);
+ scene._choices[i]._region = Common::Rect(ms.x, ms.y, ms.x + 2 * sz.x, ms.y + sz.y);
+ }
+}
+
+void makeVideo(Scene &scene, const Common::String &videoName, const Common::String &nextScene) {
+ scene._bitmapNum = 0;
+ scene._startBitmap = 0;
+ scene._decisionChoices = 1;
+ scene._waveFilename = "";
+ scene._style = Scene::STYLE_VIDEO;
+ scene._sceneName = videoName;
+ scene._decisionBitmap = "";
+ scene._choices[0]._sceneName = nextScene;
+}
+
+const struct {
+ const char *from;
+ struct {
+ const char *scene;
+ int points;
+ } to[kMaxChoice];
+} tungraph[] = {
+ {
+ "dec13",
+ {
+ {"sc15", -10000},
+ {"sc17", -10000},
+ {"sc20", -50000}
+ }
+ },
+ {
+ "dec16",
+ {
+ {"dec13", -20000},
+ {"restart", 0}
+ }
+ },
+ {
+
+ "dec18",
+ {
+ {"dec13", -30000},
+ {"restart", 0}
+ }
+ },
+ {
+ "dec20",
+ {
+ {"sc21", -90000},
+ {"sc22", -90000}
+ }
+ },
+ {
+ "dec22",
+ {
+ {"dec20", -90000},
+ {"restart", 0}
+ }
+ },
+ {
+ "dec23",
+ {
+ {"sc24", 50000},
+ {"sc28", -50000}
+ }
+ },
+ {
+ "dec25",
+ {
+ {"sc26", -75000},
+ {"sc27", -90000}
+ }
+ },
+ {
+ "dec26",
+ {
+ {"dec25", -75000},
+ {"restart", 0}
+ }
+ },
+ {
+ "dec28",
+ {
+ {"dec23", -75000},
+ {"restart", 0}
+ }
+ },
+ {
+ "dec29",
+ {
+ {"sc30", -20000},
+ {"sc31", 90000}
+ }
+ },
+ {
+ "dec30",
+ {
+ {"sc32", 0},
+ {"restart", 0},
+ {"end", 0}
+ }
+ },
+ {
+ "dec31",
+ {
+ {"dec29", -20000},
+ {"end", 0}
+ }
+
+ }
+};
+
+static const Common::KeyCode cheatKbd[] = {
+ Common::KEYCODE_UP,
+ Common::KEYCODE_DOWN,
+ Common::KEYCODE_RIGHT,
+ Common::KEYCODE_LEFT,
+ Common::KEYCODE_DOWN,
+ Common::KEYCODE_RIGHT,
+ Common::KEYCODE_RETURN
+};
+
+static const Common::JoystickButton cheatJoy[] = {
+ Common::JOYSTICK_BUTTON_DPAD_UP,
+ Common::JOYSTICK_BUTTON_DPAD_DOWN,
+ Common::JOYSTICK_BUTTON_DPAD_RIGHT,
+ Common::JOYSTICK_BUTTON_DPAD_LEFT,
+ Common::JOYSTICK_BUTTON_DPAD_DOWN,
+ Common::JOYSTICK_BUTTON_DPAD_RIGHT,
+ Common::JOYSTICK_BUTTON_X
+};
+} // end of anonymous namespace
+
+PlumbersGame3DO::PlumbersGame3DO(OSystem *syst, const ADGameDescription *gameDesc) :
+ PlumbersGame(syst, gameDesc), _ctrlHelpImage(nullptr), _cheatEnabled(false), _cheatFSM(0), _leftShoulderPressed(false),
+ _hiLite(-1), _mouseHiLite(-1), _kbdHiLite(-1) {
+}
+
+void PlumbersGame3DO::readTables() {
+ Common::File file;
+ if (!file.open("launchme"))
+ error("sReadTables(): Error reading launchme file");
+
+ initTables();
+
+ file.seek(0x1ec08);
+
+ Common::HashMap<Common::String, int> imgCounter, firstImg;
+
+ uint bitmapCtr = 0;
+
+ for (; bitmapCtr < 287; bitmapCtr++) {
+ char buf[16];
+ file.read(buf, 16);
+ _bitmaps[bitmapCtr]._filename = Common::String(buf);
+ _bitmaps[bitmapCtr]._duration = (file.readSint32BE() * 1000) / 60;
+ Common::String scene = Common::String(buf).substr(0, 4);
+ scene.toLowercase();
+ imgCounter[scene]++;
+ if (!firstImg.contains(scene))
+ firstImg[scene] = bitmapCtr;
+ }
+
+ file.seek(0x205d0);
+
+ for (; bitmapCtr < 704; bitmapCtr++) {
+ char buf[16];
+ file.read(buf, 16);
+ _bitmaps[bitmapCtr]._filename = Common::String(buf);
+ _bitmaps[bitmapCtr]._duration = (file.readSint32BE() * 1000) / 60;
+ Common::String scene = Common::String(buf).substr(0, 4);
+ scene.toLowercase();
+ imgCounter[scene]++;
+ if (!firstImg.contains(scene))
+ firstImg[scene] = bitmapCtr;
+ }
+
+ uint scPtr = 0;
+ makeVideo(_scenes[scPtr++], "kirinweaver", "janp1weaver");
+ makeVideo(_scenes[scPtr++], "janp1weaver", "janp2weaver");
+ makeVideo(_scenes[scPtr++], "janp2weaver", "janp3weaver");
+ makeVideo(_scenes[scPtr++], "janp3weaver", "titleweaver");
+ makeVideo(_scenes[scPtr++], "titleweaver", "miketest/sc00");
+
+ makeMikeDecision(_scenes[scPtr], 2);
+ _scenes[scPtr]._sceneName = "miketest/sc00";
+ _scenes[scPtr]._decisionBitmap = "DEC00";
+ _scenes[scPtr]._choices[0]._sceneName = "miketest/sc01";
+ _scenes[scPtr++]._choices[1]._sceneName = "miketest/sc07a";
+
+ for (uint scNo = 1; scNo <= 13; scNo++, scPtr++) {
+ Common::String imgScene = scNo == 5 ?
+ "sc44" : Common::String::format("sc%02d", scNo);
+ _scenes[scPtr]._bitmapNum = imgCounter[imgScene];
+ _scenes[scPtr]._startBitmap = firstImg[imgScene];
+ _scenes[scPtr]._sceneName = scNo == 5 ? "miketest/sc04a" : Common::String::format("miketest/sc%02d", scNo);
+ _scenes[scPtr]._waveFilename = Common::String::format("DIA%02d.aiff", scNo == 5 ? 4 : scNo);
+ _scenes[scPtr]._style = Scene::STYLE_PC;
+ _scenes[scPtr]._decisionChoices = 1;
+ switch(scNo) {
+ case 4:
+ case 5:
+ _scenes[scPtr]._choices[0]._sceneName = "miketest/sc06";
+ break;
+ case 11:
+ _scenes[scPtr]._choices[0]._sceneName = "miketest/sc13";
+ break;
+ case 13:
+ _scenes[scPtr]._choices[0]._sceneName = "tuntest/dec/dec13";
+ break;
+ case 7:
+ case 8:
+ case 12:
+ _scenes[scPtr]._choices[0]._sceneName = Common::String::format("miketest/sc%02da", scNo);
+ break;
+ default:
+ _scenes[scPtr]._choices[0]._sceneName = Common::String::format("miketest/sc%02d", scNo + 1);
+ break;
+ }
+ }
+
+ makeMikeDecision(_scenes[scPtr], 3);
+ _scenes[scPtr]._sceneName = "miketest/sc07a";
+ _scenes[scPtr]._decisionBitmap = "DEC07";
+ _scenes[scPtr]._choices[0]._sceneName = "miketest/sc08";
+ _scenes[scPtr]._choices[0]._points = -10000;
+ _scenes[scPtr]._choices[1]._sceneName = "miketest/sc11";
+ _scenes[scPtr]._choices[1]._points = 10000;
+ _scenes[scPtr]._choices[2]._sceneName = "miketest/sc12";
+ _scenes[scPtr]._choices[2]._points = -20000;
+ scPtr++;
+
+ makeMikeDecision(_scenes[scPtr], 2);
+ _scenes[scPtr]._sceneName = "miketest/sc08a";
+ _scenes[scPtr]._decisionBitmap = "DEC08";
+ _scenes[scPtr]._choices[0]._sceneName = "miketest/sc09";
+ _scenes[scPtr]._choices[0]._points = 0;
+ _scenes[scPtr]._choices[1]._sceneName = "miketest/sc09";
+ _scenes[scPtr]._choices[1]._points = 10000;
+ scPtr++;
+
+ makeMikeDecision(_scenes[scPtr], 2);
+ _scenes[scPtr]._sceneName = "miketest/sc12a";
+ _scenes[scPtr]._decisionBitmap = "DEC12";
+ _scenes[scPtr]._choices[0]._sceneName = "miketest/sc07a";
+ _scenes[scPtr]._choices[0]._points = 0;
+ _scenes[scPtr]._choices[1]._sceneName = "restart";
+ _scenes[scPtr]._choices[1]._points = 0;
+ scPtr++;
+
+ for (uint scNo = 15; scNo <= 32; scNo++) {
+ // there is no sc19
+ if (scNo == 19)
+ continue;
+ Common::String imgScene = Common::String::format("sc%02d", scNo);
+ _scenes[scPtr]._bitmapNum = imgCounter[imgScene];
+ _scenes[scPtr]._startBitmap = firstImg[imgScene];
+ _scenes[scPtr]._sceneName = Common::String::format("tuntest/sc%02d", scNo);
+ _scenes[scPtr]._waveFilename = Common::String::format("sc%02d.aiff", scNo);
+ _scenes[scPtr]._style = Scene::STYLE_PC;
+ _scenes[scPtr]._decisionChoices = 1;
+ if (scNo == 32)
+ _scenes[scPtr]._choices[0]._sceneName = "end";
+ else if (scNo == 16 || scNo == 18 || scNo == 20 || scNo == 22 || scNo == 23 || scNo == 25
+ || scNo == 26 || scNo == 28 || scNo == 29 || scNo == 30 || scNo == 31)
+ _scenes[scPtr]._choices[0]._sceneName = Common::String::format("tuntest/dec/dec%02d", scNo);
+ else
+ _scenes[scPtr]._choices[0]._sceneName = Common::String::format("tuntest/sc%02d", scNo + 1);
+ scPtr++;
+ }
+
+ file.seek(0x20290);
+
+ for (int i = 0; i < 26; i++) {
+ char buf[16];
+ file.read(buf, 16);
+ uint32 x = file.readUint32BE();
+ uint32 y = file.readUint32BE();
+ uint32 w = file.readUint32BE();
+ uint32 h = file.readUint32BE();
+ Common::String shortName = Common::String(buf, 5);
+ Common::String sceneName = "tuntest/dec/" + shortName;
+ if (i == 0 || _scenes[scPtr - 1]._sceneName != sceneName) {
+ _scenes[scPtr]._bitmapNum = 0;
+ _scenes[scPtr]._startBitmap = 0;
+ _scenes[scPtr]._decisionChoices = 0;
+ _scenes[scPtr]._waveFilename = "";
+ _scenes[scPtr]._style = Scene::STYLE_DECISION_TUN;
+ _scenes[scPtr]._sceneName = sceneName;
+ _scenes[scPtr]._decisionBitmap = shortName;
+ scPtr++;
+ }
+
+ Scene &scene = _scenes[scPtr - 1];
+ assert(scene._decisionChoices < kMaxChoice);
+ scene._choices[scene._decisionChoices]._region = Common::Rect(x, y, x + w, y + h);
+ for (uint j = 0 ; j < ARRAYSIZE(tungraph); j++) {
+ if (shortName == tungraph[j].from) {
+ Common::String target = tungraph[j].to[scene._decisionChoices].scene;
+ if (target[0] == 's')
+ scene._choices[scene._decisionChoices]._sceneName = "tuntest/" + target;
+ else
+ scene._choices[scene._decisionChoices]._sceneName = "tuntest/dec/" + target;
+ scene._choices[scene._decisionChoices]._points = tungraph[j].to[scene._decisionChoices].points;
+ break;
+ }
+ }
+ scene._decisionChoices++;
+ }
+
+ _totScene = scPtr;
+}
+
+void PlumbersGame3DO::loadMikeDecision(const Common::String &dirname, const Common::String &baseFilename, uint num) {
+ Common::String baseName = dirname + "/" + baseFilename;
+ debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, baseName.c_str());
+ Graphics::Surface *surf = new Graphics::Surface();
+ surf->create(_screenW, _screenH, Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15));
+
+ delete _compositeSurface;
+ _compositeSurface = nullptr;
+
+ for (uint i = 0; i < num; i++) {
+ Common::Point p = getMikeStart(i, num);
+ Common::Point sz = getMikeSize(num);
+ Common::File fileP;
+ Common::String nameP = Common::String::format("%s%dP.CEL", baseName.c_str(), i + 1);
+ if (!fileP.open(nameP))
+ error("unable to load image %s", nameP.c_str());
+
+ _image->loadStream(fileP);
+ surf->copyRectToSurface(*_image->getSurface(), p.x, p.y,
+ Common::Rect(0, 0, sz.x, sz.y));
+
+ Common::File fileW;
+ Common::String nameW = Common::String::format("%s%dW.CEL", baseName.c_str(), i + 1);
+ if (!fileW.open(nameW))
+ error("unable to load image %s", nameW.c_str());
+
+ _image->loadStream(fileW);
+ surf->copyRectToSurface(*_image->getSurface(), p.x + sz.x, p.y,
+ Common::Rect(0, 0, sz.x, sz.y));
+ }
+
+ _compositeSurface = surf;
+
+ Common::File fileCtrl;
+ if (fileCtrl.open(dirname + "/CONTROLHELP.CEL"))
+ _ctrlHelpImage->loadStream(fileCtrl);
+}
+
+void PlumbersGame3DO::postSceneBitmaps() {
+ if (_scenes[_curSceneIdx]._style == Scene::STYLE_VIDEO) {
+ _videoDecoder = new Video::ThreeDOMovieDecoder();
+ _curChoice = 0;
+ if (!_videoDecoder->loadFile(_scenes[_curSceneIdx]._sceneName)) {
+ _actions.push(ChangeScene);
+ return;
+ }
+ _videoDecoder->start();
+ return;
+ }
+
+ if (_scenes[_curSceneIdx]._decisionChoices == 1) {
+ _curChoice = 0;
+ _actions.push(ChangeScene);
+ return;
+ }
+
+ _showScoreFl = true;
+ _leftButtonDownFl = true;
+ _setDurationFl = false;
+ if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_MIKE) {
+ loadMikeDecision(_scenes[_curSceneIdx]._sceneName, _scenes[_curSceneIdx]._decisionBitmap,
+ _scenes[_curSceneIdx]._decisionChoices);
+ _hiLite = 0;
+ _kbdHiLite = 0;
+ updateHiLite();
+ } else if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_TUN) {
+ loadImage(_scenes[_curSceneIdx]._sceneName + ".cel");
+ _hiLite = 0;
+ _kbdHiLite = 0;
+ updateHiLite();
+ Common::File fileCtrl;
+ if (fileCtrl.open("tuntest/dec/controlhelp.cel"))
+ _ctrlHelpImage->loadStream(fileCtrl);
+ } else {
+ loadImage(_scenes[_curSceneIdx]._sceneName + "/" + _scenes[_curSceneIdx]._decisionBitmap);
+ _hiLite = -1;
+ _kbdHiLite = -1;
+ }
+
+ _mouseHiLite = getMouseHiLite();
+}
+
+void PlumbersGame3DO::startGraphics() {
+ _image = new Image::Cel3DODecoder();
+ _ctrlHelpImage = new Image::Cel3DODecoder();
+ _screenW = 320;
+ _screenH = 240;
+ Graphics::PixelFormat pf(2, 5, 5, 5, 1, 10, 5, 0, 15);
+ initGraphics(_screenW, _screenH, &pf);
+}
+
+void PlumbersGame3DO::blitImage(Graphics::Surface *screen) {
+ const Graphics::Surface *surface;
+ bool ctrlHelp = false;
+ if (_leftShoulderPressed && _leftButtonDownFl && _ctrlHelpImage) {
+ surface = _ctrlHelpImage->getSurface();
+ ctrlHelp = true;
+ } else if (_videoDecoder)
+ surface = _videoDecoder->decodeNextFrame();
+ else if (_compositeSurface)
+ surface = _compositeSurface;
+ else
+ surface = _image->getSurface();
+
+ Graphics::Surface modSurf;
+ bool modded = false;
+
+ if (_hiLite >= 0 && _leftButtonDownFl && !ctrlHelp) {
+ Graphics::PixelFormat pf(2, 5, 5, 5, 1, 10, 5, 0, 15);
+ modSurf.create(surface->w, surface->h, pf);
+ modSurf.copyRectToSurface(*surface, 0, 0, Common::Rect(0, 0, surface->w, surface->h));
+ const Common::Rect rec = _scenes[_curSceneIdx]._choices[_hiLite]._region;
+
+ for (int y = rec.top; y <= rec.bottom; y++) {
+ uint16 *p = (uint16 *) modSurf.getPixels() + modSurf.w * y + rec.left;
+ for (int x = rec.left; x < rec.right; x++, p++) {
+ uint r, g, b;
+ r = (*p >> 10) & 0x1f;
+ g = (*p >> 5) & 0x1f;
+ b = (*p >> 0) & 0x1f;
+ // TODO: figure out the correct multipliers
+ r = MIN<int>(3 * r / 2, 0x1f);
+ g = MIN<int>(3 * g / 2, 0x1f);
+ b = MIN<int>(3 * b / 2, 0x1f);
+ *p = (*p & 0x8000) | (r << 10) | (g << 5) | (b);
+ }
+ }
+ modded = true;
+ }
+
+ blitImageSurface(screen, modded ? &modSurf : surface);
+}
+
+void PlumbersGame3DO::skipVideo() {
+ if (_scenes[_curSceneIdx]._sceneName == "janp1weaver"
+ || _scenes[_curSceneIdx]._sceneName == "janp2weaver") {
+ // Skip janp2weaver and janp3weaver
+ _curSceneIdx = getSceneNumb("titleweaver");
+ _actions.push(ShowScene);
+ } else {
+ _actions.push(ChangeScene);
+ }
+ _videoDecoder->close();
+ delete _videoDecoder;
+ _videoDecoder = nullptr;
+}
+
+void PlumbersGame3DO::joyUp() {
+ int decNum = _scenes[_curSceneIdx]._decisionChoices;
+ if (!_leftButtonDownFl)
+ return;
+ _kbdHiLite = _kbdHiLite < 0 ? 0 : (_kbdHiLite + decNum - 1) % decNum;
+ _hiLite = _kbdHiLite;
+ updateHiLite();
+}
+
+void PlumbersGame3DO::joyDown() {
+ if (!_leftButtonDownFl)
+ return;
+ int decNum = _scenes[_curSceneIdx]._decisionChoices;
+ _kbdHiLite = _kbdHiLite < 0 ? 0 : (_kbdHiLite + 1) % decNum;
+ _hiLite = _kbdHiLite;
+ updateHiLite();
+}
+
+void PlumbersGame3DO::joyA() {
+ if (_kbdHiLite < 0 || !_leftButtonDownFl)
+ return;
+ debugC(5, kDebugGeneral, "Accepting enter press with choice = %d", _kbdHiLite);
+ _curChoice = _kbdHiLite;
+ _totScore += _scenes[_curSceneIdx]._choices[_kbdHiLite]._points;
+ _actions.push(ChangeScene);
+ _leftButtonDownFl = false;
+}
+
+void PlumbersGame3DO::handleEvent(const Common::Event &event) {
+ switch (event.type) {
+ case Common::EVENT_JOYBUTTON_DOWN:
+ if (_videoDecoder) {
+ if (_cheatFSM < ARRAYSIZE(cheatJoy) && event.joystick.button == cheatJoy[_cheatFSM]) {
+ _cheatFSM++;
+ if (_cheatFSM == ARRAYSIZE(cheatJoy)) {
+ debugC(1, kDebugGeneral, "Cheat enabled");
+ _cheatEnabled = true;
+ }
+ } else if (event.joystick.button == cheatJoy[0])
+ _cheatFSM = 1;
+ else
+ _cheatFSM = 0;
+ }
+ if (_videoDecoder && (event.joystick.button == Common::JOYSTICK_BUTTON_A ||
+ event.joystick.button == Common::JOYSTICK_BUTTON_B ||
+ event.joystick.button == Common::JOYSTICK_BUTTON_X)) {
+ skipVideo();
+ return;
+ }
+ if (event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_UP ||
+ event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_LEFT) {
+ joyUp();
+ return;
+ }
+ if (event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_DOWN ||
+ event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_RIGHT) {
+ joyDown();
+ return;
+ }
+ if (event.joystick.button == Common::JOYSTICK_BUTTON_A) {
+ joyA();
+ return;
+ }
+ if (event.joystick.button == Common::JOYSTICK_BUTTON_LEFT_SHOULDER) {
+ _leftShoulderPressed = true;
+ if (_leftButtonDownFl && _ctrlHelpImage)
+ _actions.push(Redraw);
+ return;
+ }
+ break;
+ case Common::EVENT_JOYBUTTON_UP:
+ if (event.joystick.button == Common::JOYSTICK_BUTTON_LEFT_SHOULDER) {
+ _leftShoulderPressed = false;
+ if (_leftButtonDownFl && _ctrlHelpImage)
+ _actions.push(Redraw);
+ return;
+ }
+ break;
+ case Common::EVENT_KEYDOWN:
+ if (_videoDecoder) {
+ if (_cheatFSM < ARRAYSIZE(cheatKbd) && event.kbd.keycode == cheatKbd[_cheatFSM]) {
+ _cheatFSM++;
+ if (_cheatFSM == ARRAYSIZE(cheatKbd)) {
+ debugC(1, kDebugGeneral, "Cheat enabled");
+ _cheatEnabled = true;
+ }
+ } else if (event.kbd.keycode == cheatKbd[0])
+ _cheatFSM = 1;
+ else
+ _cheatFSM = 0;
+ }
+ if (event.kbd.keycode == Common::KEYCODE_SPACE && _videoDecoder) {
+ skipVideo();
+ return;
+ }
+ if ((event.kbd.keycode == Common::KEYCODE_UP ||
+ event.kbd.keycode == Common::KEYCODE_LEFT)) {
+ joyUp();
+ return;
+ }
+ if ((event.kbd.keycode == Common::KEYCODE_DOWN ||
+ event.kbd.keycode == Common::KEYCODE_RIGHT)) {
+ joyDown();
+ return;
+ }
+ if (event.kbd.keycode == Common::KEYCODE_RETURN) {
+ joyA();
+ return;
+ }
+ if (event.kbd.keycode == Common::KEYCODE_q) {
+ _leftShoulderPressed = true;
+ if (_leftButtonDownFl && _ctrlHelpImage)
+ _actions.push(Redraw);
+ return;
+ }
+ break;
+ case Common::EVENT_KEYUP:
+ if (event.kbd.keycode == Common::KEYCODE_q) {
+ _leftShoulderPressed = false;
+ if (_leftButtonDownFl && _ctrlHelpImage)
+ _actions.push(Redraw);
+ }
+ break;
+ default:
+ break;
+ }
+ PlumbersGame::handleEvent(event);
+}
+
+int PlumbersGame3DO::getSceneNumb(const Common::String &sName) {
+ debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, sName.c_str());
+ if (sName == "miketest/sc04" && _cheatEnabled)
+ return PlumbersGame::getSceneNumb("miketest/sc04a");
+
+ return PlumbersGame::getSceneNumb(sName);
+}
+
+void PlumbersGame3DO::updateHiLite() {
+ _actions.push(Redraw);
+ if (_hiLite < 0)
+ return;
+ if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_MIKE) {
+ playSound(Common::String::format("%s/%s%dS.Aiff",
+ _scenes[_curSceneIdx]._sceneName.c_str(),
+ _scenes[_curSceneIdx]._decisionBitmap.c_str(), _hiLite + 1));
+ } else if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_TUN) {
+ playSound(Common::String::format("%s%c.aiff", _scenes[_curSceneIdx]._sceneName.c_str(), _hiLite + 'a'));
+ }
+}
+
+void PlumbersGame3DO::preActions() {
+ if (_leftButtonDownFl) {
+ int nh = getMouseHiLite();
+ if (nh != _mouseHiLite) {
+ _mouseHiLite = nh;
+ _hiLite = _mouseHiLite;
+ updateHiLite();
+ }
+ }
+}
+}
diff --git a/engines/plumbers/POTFILES b/engines/plumbers/POTFILES
new file mode 100644
index 00000000000..d2f6832465b
--- /dev/null
+++ b/engines/plumbers/POTFILES
@@ -0,0 +1 @@
+engines/plumbers/metaengine.cpp
diff --git a/engines/plumbers/configure.engine b/engines/plumbers/configure.engine
index 7df809b57ad..4a309abcfb4 100644
--- a/engines/plumbers/configure.engine
+++ b/engines/plumbers/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine plumbers "Plumbers Don't Wear Ties" yes "" "" "highres 16bit"
+add_engine plumbers "Plumbers Don't Wear Ties" yes
diff --git a/engines/plumbers/metaengine.cpp b/engines/plumbers/metaengine.cpp
index 7357952b5d5..ead531071e1 100644
--- a/engines/plumbers/metaengine.cpp
+++ b/engines/plumbers/metaengine.cpp
@@ -21,7 +21,10 @@
#include "base/plugins.h"
+#include "common/translation.h"
+
#include "engines/advancedDetector.h"
+#include "gui/message.h"
#include "plumbers/plumbers.h"
@@ -40,7 +43,17 @@ class PlumbersMetaEngine : public AdvancedMetaEngine {
};
Common::Error PlumbersMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
- *engine = new Plumbers::PlumbersGame(syst, desc);
+ if (desc->platform == Common::kPlatform3DO) {
+#ifdef USE_RGB_COLOR
+ *engine = new Plumbers::PlumbersGame3DO(syst, desc);
+#else
+ // I18N: Plumbers is the title of the game. 3DO is the name of platform
+ GUI::MessageDialog dialog(_("3DO Plumbers requires RGB support."));
+ dialog.runModal();
+ return Common::kUnsupportedColorMode;
+#endif
+ } else
+ *engine = new Plumbers::PlumbersGameWindows(syst, desc);
return Common::kNoError;
}
diff --git a/engines/plumbers/module.mk b/engines/plumbers/module.mk
index 63fde172d33..11111cad180 100644
--- a/engines/plumbers/module.mk
+++ b/engines/plumbers/module.mk
@@ -3,7 +3,12 @@ MODULE := engines/plumbers
MODULE_OBJS = \
plumbers.o \
console.o \
- metaengine.o
+ metaengine.o \
+ windows.o
+
+ifdef USE_RGB_COLOR
+MODULE_OBJS += 3do.o
+endif
# This module can be built as a plugin
ifeq ($(ENABLE_PLUMBERS), DYNAMIC_PLUGIN)
diff --git a/engines/plumbers/plumbers.cpp b/engines/plumbers/plumbers.cpp
index 998619752b5..cfa44385bd7 100644
--- a/engines/plumbers/plumbers.cpp
+++ b/engines/plumbers/plumbers.cpp
@@ -40,38 +40,14 @@
#include "graphics/font.h"
#include "graphics/fontman.h"
#include "graphics/palette.h"
+#include "graphics/scaler/downscaler.h"
#include "graphics/surface.h"
-#include "image/bmp.h"
-#include "image/cel_3do.h"
-
-#include "video/3do_decoder.h"
-
namespace Plumbers {
-static const Common::KeyCode cheatKbd[] = {
- Common::KEYCODE_UP,
- Common::KEYCODE_DOWN,
- Common::KEYCODE_RIGHT,
- Common::KEYCODE_LEFT,
- Common::KEYCODE_DOWN,
- Common::KEYCODE_RIGHT,
- Common::KEYCODE_RETURN
-};
-
-static const Common::JoystickButton cheatJoy[] = {
- Common::JOYSTICK_BUTTON_DPAD_UP,
- Common::JOYSTICK_BUTTON_DPAD_DOWN,
- Common::JOYSTICK_BUTTON_DPAD_RIGHT,
- Common::JOYSTICK_BUTTON_DPAD_LEFT,
- Common::JOYSTICK_BUTTON_DPAD_DOWN,
- Common::JOYSTICK_BUTTON_DPAD_RIGHT,
- Common::JOYSTICK_BUTTON_X
-};
-
PlumbersGame::PlumbersGame(OSystem *syst, const ADGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _console(nullptr), _image(nullptr),
- _compositeSurface(nullptr), _videoDecoder(nullptr), _ctrlHelpImage(nullptr) {
+ _compositeSurface(nullptr), _videoDecoder(nullptr), _quit(false) {
_timerInstalled = false;
_showScoreFl = false;
_setDurationFl = false;
@@ -83,8 +59,6 @@ PlumbersGame::PlumbersGame(OSystem *syst, const ADGameDescription *gameDesc) :
_curChoice = 0;
_totScene = -1;
_totScore = 0;
- _cheatEnabled = false;
- _cheatFSM = 0;
}
PlumbersGame::~PlumbersGame() {
@@ -117,82 +91,35 @@ static const byte cursorPalette[] = {
0xff, 0xff, 0xff // White
};
-// TODO(3do):
-// * effect when changing between scenes
-// * 3do boot logo
-// * return to previous scene
-// * hide cursor
+void PlumbersGame::handleEvent(const Common::Event &event) {
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RETURN_TO_LAUNCHER:
+ _quit = true;
+ break;
-void PlumbersGame::updateHiLite() {
- _actions.push(Redraw);
- if (_hiLite < 0)
- return;
- if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_MIKE) {
- playSound(Common::String::format("%s/%s%dS.Aiff",
- _scenes[_curSceneIdx]._sceneName.c_str(),
- _scenes[_curSceneIdx]._decisionBitmap.c_str(), _hiLite + 1));
- } else if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_TUN) {
- playSound(Common::String::format("%s%c.aiff", _scenes[_curSceneIdx]._sceneName.c_str(), _hiLite + 'a'));
- }
-}
-
-void PlumbersGame::joyUp() {
- int decNum = _scenes[_curSceneIdx]._decisionChoices;
- if (!_leftButtonDownFl || !_hiLiteEnabled)
- return;
- _kbdHiLite = _kbdHiLite < 0 ? 0 : (_kbdHiLite + decNum - 1) % decNum;
- _hiLite = _kbdHiLite;
- updateHiLite();
-}
-
-void PlumbersGame::joyDown() {
- if (!_leftButtonDownFl || !_hiLiteEnabled)
- return;
- int decNum = _scenes[_curSceneIdx]._decisionChoices;
- _kbdHiLite = _kbdHiLite < 0 ? 0 : (_kbdHiLite + 1) % decNum;
- _hiLite = _kbdHiLite;
- updateHiLite();
-}
-
-void PlumbersGame::joyA() {
- if (_kbdHiLite < 0 || !_leftButtonDownFl || !_hiLiteEnabled)
- return;
- debugC(5, kDebugGeneral, "Accepting enter press with choice = %d", _kbdHiLite);
- _curChoice = _kbdHiLite;
- _totScore += _scenes[_curSceneIdx]._choices[_kbdHiLite]._points;
- _actions.push(ChangeScene);
- _leftButtonDownFl = false;
-}
+ case Common::EVENT_LBUTTONDOWN:
+ if (_leftButtonDownFl) {
+ _curChoice = getMouseHiLite();
-void PlumbersGame::skipVideo() {
- if (_scenes[_curSceneIdx]._sceneName == "janp1weaver"
- || _scenes[_curSceneIdx]._sceneName == "janp2weaver") {
- // Skip janp2weaver and janp3weaver
- _curSceneIdx = getSceneNumb("titleweaver");
- _actions.push(ShowScene);
- } else {
- _actions.push(ChangeScene);
+ if (_curChoice >= 0 && _curChoice < _scenes[_curSceneIdx]._decisionChoices) {
+ debugC(5, kDebugGeneral, "Accepting mouse click with choice = %d", _curChoice);
+ _totScore += _scenes[_curSceneIdx]._choices[_curChoice]._points;
+ _actions.push(ChangeScene);
+ _leftButtonDownFl = false;
+ }
+ } else if (_console->_allowSkip && _timerInstalled) {
+ // Allows to skip speech by skipping wait delay
+ onTimer(this);
+ }
+ break;
+ default:
+ break;
}
- _videoDecoder->close();
- delete _videoDecoder;
- _videoDecoder = nullptr;
}
-
Common::Error PlumbersGame::run() {
- if (getPlatform() == Common::kPlatform3DO) {
- _image = new Image::Cel3DODecoder();
- _ctrlHelpImage = new Image::Cel3DODecoder();
- _screenW = 320;
- _screenH = 240;
- Graphics::PixelFormat pf(2, 5, 5, 5, 1, 10, 5, 0, 15);
- initGraphics(_screenW, _screenH, &pf);
- } else {
- _image = new Image::BitmapDecoder();
- _screenW = 640;
- _screenH = 480;
- initGraphics(_screenW, _screenH);
- }
+ startGraphics();
_console = new Console();
setDebugger(_console);
@@ -201,142 +128,26 @@ Common::Error PlumbersGame::run() {
CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
CursorMan.showMouse(true);
- if (getPlatform() == Common::kPlatform3DO)
- readTables3DO("launchme");
- else
- readTablesPC("game.bin");
+ readTables();
_showScoreFl = false;
_leftButtonDownFl = false;
_endGameFl = false;
- // PC uses a palette, so we don't do highlighting.
- // Original does the same
- _hiLiteEnabled = getPlatform() == Common::kPlatform3DO;
_totScore = 0;
_curSceneIdx = _prvSceneIdx = 0;
_curChoice = 0;
- _kbdHiLite = -1;
- _mouseHiLite = -1;
- _hiLite = -1;
- _mouseHiLite = -1;
- _kbdHiLite = -1;
- _leftShoulderPressed = false;
_actions.clear();
_actions.push(ShowScene);
- bool quit = false;
+ _quit = false;
- while (!quit && !_endGameFl) {
+ while (!_quit && !_endGameFl) {
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_QUIT:
- case Common::EVENT_RETURN_TO_LAUNCHER:
- quit = true;
- break;
-
- case Common::EVENT_LBUTTONDOWN:
- if (_leftButtonDownFl) {
- _curChoice = getMouseHiLite();
-
- if (_curChoice >= 0 && _curChoice < _scenes[_curSceneIdx]._decisionChoices) {
- debugC(5, kDebugGeneral, "Accepting mouse click with choice = %d", _curChoice);
- _totScore += _scenes[_curSceneIdx]._choices[_curChoice]._points;
- _actions.push(ChangeScene);
- _leftButtonDownFl = false;
- }
- } else if (_console->_allowSkip && _timerInstalled) {
- // Allows to skip speech by skipping wait delay
- onTimer(this);
- }
- break;
- case Common::EVENT_JOYBUTTON_DOWN:
- if (_videoDecoder) {
- if (_cheatFSM < ARRAYSIZE(cheatJoy) && event.joystick.button == cheatJoy[_cheatFSM]) {
- _cheatFSM++;
- if (_cheatFSM == ARRAYSIZE(cheatJoy)) {
- debugC(1, kDebugGeneral, "Cheat enabled");
- _cheatEnabled = true;
- }
- } else if (event.joystick.button == cheatJoy[0])
- _cheatFSM = 1;
- else
- _cheatFSM = 0;
- }
- if (_videoDecoder && (event.joystick.button == Common::JOYSTICK_BUTTON_A ||
- event.joystick.button == Common::JOYSTICK_BUTTON_B ||
- event.joystick.button == Common::JOYSTICK_BUTTON_X)) {
- skipVideo();
- } else if (event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_UP ||
- event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_LEFT) {
- joyUp();
- } else if (event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_DOWN ||
- event.joystick.button == Common::JOYSTICK_BUTTON_DPAD_RIGHT) {
- joyDown();
- } else if (event.joystick.button == Common::JOYSTICK_BUTTON_A) {
- joyA();
- } else if (event.joystick.button == Common::JOYSTICK_BUTTON_LEFT_SHOULDER) {
- _leftShoulderPressed = true;
- if (_leftButtonDownFl && _ctrlHelpImage)
- _actions.push(Redraw);
- }
- break;
- case Common::EVENT_JOYBUTTON_UP:
- if (event.joystick.button == Common::JOYSTICK_BUTTON_LEFT_SHOULDER) {
- _leftShoulderPressed = false;
- if (_leftButtonDownFl && _ctrlHelpImage)
- _actions.push(Redraw);
- }
- break;
- case Common::EVENT_KEYDOWN:
- if (_videoDecoder) {
- if (_cheatFSM < ARRAYSIZE(cheatKbd) && event.kbd.keycode == cheatKbd[_cheatFSM]) {
- _cheatFSM++;
- if (_cheatFSM == ARRAYSIZE(cheatKbd)) {
- debugC(1, kDebugGeneral, "Cheat enabled");
- _cheatEnabled = true;
- }
- } else if (event.kbd.keycode == cheatKbd[0])
- _cheatFSM = 1;
- else
- _cheatFSM = 0;
- }
- if (event.kbd.keycode == Common::KEYCODE_SPACE && _videoDecoder) {
- skipVideo();
- } else if ((event.kbd.keycode == Common::KEYCODE_UP ||
- event.kbd.keycode == Common::KEYCODE_LEFT)) {
- joyUp();
- } else if ((event.kbd.keycode == Common::KEYCODE_DOWN ||
- event.kbd.keycode == Common::KEYCODE_RIGHT)) {
- joyDown();
- } else if (event.kbd.keycode == Common::KEYCODE_RETURN) {
- joyA();
- } else if (event.kbd.keycode == Common::KEYCODE_q) {
- _leftShoulderPressed = true;
- if (_leftButtonDownFl && _ctrlHelpImage)
- _actions.push(Redraw);
- }
- break;
- case Common::EVENT_KEYUP:
- if (event.kbd.keycode == Common::KEYCODE_q) {
- _leftShoulderPressed = false;
- if (_leftButtonDownFl && _ctrlHelpImage)
- _actions.push(Redraw);
- }
- break;
- default:
- break;
- }
+ handleEvent(event);
}
- if (_leftButtonDownFl) {
- int nh = getMouseHiLite();
- if (nh != _mouseHiLite) {
- _mouseHiLite = nh;
- _hiLite = _mouseHiLite;
- updateHiLite();
- }
- }
+ preActions();
while (!_actions.empty()) {
switch (_actions.pop()) {
@@ -392,56 +203,18 @@ void PlumbersGame::loadImage(const Common::String &name) {
_compositeSurface = nullptr;
}
-// TODO: discover correct offsets
-Common::Point getMikeStart(uint num, uint total) {
- if (total == 2)
- return Common::Point(140 * num + 10, 120 * num + 10);
- return Common::Point(60 * num + 20, 70 * num + 20);
-}
-
-// TODO: discover correct offsets
-Common::Point getMikeSize(uint total) {
- if (total == 2)
- return Common::Point(80, 100);
- return Common::Point(80, 60);
-}
+void PlumbersGame::blitImageSurface(Graphics::Surface *screen, const Graphics::Surface *surface) {
+ int w = CLIP<int>(surface->w, 0, _screenW);
+ int h = CLIP<int>(surface->h, 0, _screenH);
-void PlumbersGame::loadMikeDecision(const Common::String &dirname, const Common::String &baseFilename, uint num) {
- Common::String baseName = dirname + "/" + baseFilename;
- debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, baseName.c_str());
- Graphics::Surface *surf = new Graphics::Surface();
- surf->create(_screenW, _screenH, Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15));
+ int x = (_screenW - w) / 2;
+ int y = (_screenH - h) / 2;
- delete _compositeSurface;
- _compositeSurface = nullptr;
-
- for (uint i = 0; i < num; i++) {
- Common::Point p = getMikeStart(i, num);
- Common::Point sz = getMikeSize(num);
- Common::File fileP;
- Common::String nameP = Common::String::format("%s%dP.CEL", baseName.c_str(), i + 1);
- if (!fileP.open(nameP))
- error("unable to load image %s", nameP.c_str());
-
- _image->loadStream(fileP);
- surf->copyRectToSurface(*_image->getSurface(), p.x, p.y,
- Common::Rect(0, 0, sz.x, sz.y));
-
- Common::File fileW;
- Common::String nameW = Common::String::format("%s%dW.CEL", baseName.c_str(), i + 1);
- if (!fileW.open(nameW))
- error("unable to load image %s", nameW.c_str());
-
- _image->loadStream(fileW);
- surf->copyRectToSurface(*_image->getSurface(), p.x + sz.x, p.y,
- Common::Rect(0, 0, sz.x, sz.y));
- }
-
- _compositeSurface = surf;
+ screen->copyRectToSurface(*surface, x, y, Common::Rect(0, 0, w, h));
+}
- Common::File fileCtrl;
- if (fileCtrl.open(dirname + "/CONTROLHELP.CEL"))
- _ctrlHelpImage->loadStream(fileCtrl);
+void PlumbersGame::blitImage(Graphics::Surface *screen) {
+ blitImageSurface(screen, _compositeSurface ? _compositeSurface : _image->getSurface());
}
void PlumbersGame::drawScreen() {
@@ -457,51 +230,7 @@ void PlumbersGame::drawScreen() {
Graphics::Surface *screen = g_system->lockScreen();
screen->fillRect(Common::Rect(0, 0, g_system->getWidth(), g_system->getHeight()), 0);
- const Graphics::Surface *surface;
- bool ctrlHelp = false;
- if (_leftShoulderPressed && _leftButtonDownFl && _ctrlHelpImage) {
- surface = _ctrlHelpImage->getSurface();
- ctrlHelp = true;
- } else if (_videoDecoder)
- surface = _videoDecoder->decodeNextFrame();
- else if (_compositeSurface)
- surface = _compositeSurface;
- else
- surface = _image->getSurface();
-
- Graphics::Surface modSurf;
- bool modded = false;
-
- if (_hiLiteEnabled && _hiLite >= 0 && _leftButtonDownFl && !ctrlHelp) {
- Graphics::PixelFormat pf(2, 5, 5, 5, 1, 10, 5, 0, 15);
- modSurf.create(surface->w, surface->h, pf);
- modSurf.copyRectToSurface(*surface, 0, 0, Common::Rect(0, 0, surface->w, surface->h));
- const Common::Rect rec = _scenes[_curSceneIdx]._choices[_hiLite]._region;
-
- for (int y = rec.top; y <= rec.bottom; y++) {
- uint16 *p = (uint16 *) modSurf.getPixels() + modSurf.w * y + rec.left;
- for (int x = rec.left; x < rec.right; x++, p++) {
- uint r, g, b;
- r = (*p >> 10) & 0x1f;
- g = (*p >> 5) & 0x1f;
- b = (*p >> 0) & 0x1f;
- // TODO: figure out the correct multipliers
- r = MIN<int>(3 * r / 2, 0x1f);
- g = MIN<int>(3 * g / 2, 0x1f);
- b = MIN<int>(3 * b / 2, 0x1f);
- *p = (*p & 0x8000) | (r << 10) | (g << 5) | (b);
- }
- }
- modded = true;
- }
-
- int w = CLIP<int>(surface->w, 0, _screenW);
- int h = CLIP<int>(surface->h, 0, _screenH);
-
- int x = (_screenW - w) / 2;
- int y = (_screenH - h) / 2;
-
- screen->copyRectToSurface(modded ? modSurf : *surface, x, y, Common::Rect(0, 0, w, h));
+ blitImage(screen);
if (_showScoreFl) {
Common::String score = Common::String::format("Your Score is: %ld", _totScore);
@@ -532,7 +261,7 @@ void PlumbersGame::playSound(const Common::String &name) {
error("unable to load sound %s", name.c_str());
Audio::AudioStream *stream;
- if (name.hasSuffix(".aiff") || name.hasSuffix(".Aiff"))
+ if (name.hasSuffixIgnoreCase(".aiff"))
stream = Audio::makeAIFFStream(file, DisposeAfterUse::YES);
else
stream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
@@ -569,43 +298,7 @@ void PlumbersGame::updateScene() {
debugC(2, kDebugGeneral, "%s : %d", __FUNCTION__, _curBitmapIdx);
_curBitmapIdx++;
if (_curBitmapIdx >= _scenes[_curSceneIdx]._startBitmap + _scenes[_curSceneIdx]._bitmapNum) {
- if (_scenes[_curSceneIdx]._style == Scene::STYLE_VIDEO) {
- _videoDecoder = new Video::ThreeDOMovieDecoder();
- _curChoice = 0;
- if (!_videoDecoder->loadFile(_scenes[_curSceneIdx]._sceneName)) {
- _actions.push(ChangeScene);
- return;
- }
- _videoDecoder->start();
- } else if (_scenes[_curSceneIdx]._decisionChoices == 1) {
- _curChoice = 0;
- _actions.push(ChangeScene);
- } else {
- _showScoreFl = true;
- _leftButtonDownFl = true;
- _setDurationFl = false;
- if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_MIKE) {
- loadMikeDecision(_scenes[_curSceneIdx]._sceneName, _scenes[_curSceneIdx]._decisionBitmap,
- _scenes[_curSceneIdx]._decisionChoices);
- _hiLite = 0;
- _kbdHiLite = 0;
- updateHiLite();
- } else if (_scenes[_curSceneIdx]._style == Scene::STYLE_DECISION_TUN) {
- loadImage(_scenes[_curSceneIdx]._sceneName + ".cel");
- _hiLite = 0;
- _kbdHiLite = 0;
- updateHiLite();
- Common::File fileCtrl;
- if (fileCtrl.open("tuntest/dec/controlhelp.cel"))
- _ctrlHelpImage->loadStream(fileCtrl);
- } else {
- loadImage(_scenes[_curSceneIdx]._sceneName + "/" + _scenes[_curSceneIdx]._decisionBitmap);
- _hiLite = -1;
- _kbdHiLite = -1;
- }
-
- _mouseHiLite = getMouseHiLite();
- }
+ postSceneBitmaps();
} else {
loadImage(_scenes[_curSceneIdx]._sceneName + "/" + _bitmaps[_curBitmapIdx]._filename);
_setDurationFl = true;
@@ -678,353 +371,8 @@ void PlumbersGame::initTables() {
}
}
-void PlumbersGame::readTablesPC(const Common::String &fileName) {
- Common::File file;
- if (!file.open(fileName))
- error("sReadTables(): Error reading BIN file");
-
- initTables();
-
- _totScore = file.readSint32LE();
- file.skip(10);
- _totScene = file.readSint16LE();
- file.skip(6);
-
- char buf[kMaxName];
- for (int i = 0; i < kMaxScene; i++) {
- _scenes[i]._bitmapNum = file.readSint16LE();
- _scenes[i]._startBitmap = file.readSint16LE();
- _scenes[i]._decisionChoices = file.readSint16LE();
- file.read(buf, kMaxName);
- _scenes[i]._sceneName = Common::String(buf);
- file.read(buf, kMaxName);
- _scenes[i]._waveFilename = Common::String(buf);
- file.read(buf, kMaxName);
- _scenes[i]._decisionBitmap = Common::String(buf);
- _scenes[i]._style = Scene::STYLE_PC;
-
- for (int j = 0; j < kMaxChoice; j++) {
- _scenes[i]._choices[j]._points = file.readSint32LE();
- _scenes[i]._choices[j]._sceneName = Common::String::format("SC%02d", file.readSint16LE());
- _scenes[i]._choices[j]._skipScene = file.readSint16LE();
- int left = file.readSint16LE();
- int top = file.readSint16LE();
- int right = file.readSint16LE();
- int bottom = file.readSint16LE();
- _scenes[i]._choices[j]._region = Common::Rect(left, top, right, bottom);
- }
- }
-
- for (int i = 0; i < kMaxBitmaps; i++) {
- _bitmaps[i]._duration = file.readSint16LE() * 100;
- file.read(buf, kMaxName);
- _bitmaps[i]._filename = Common::String(buf);
- }
-}
-
-static void makeMikeDecision(Scene &scene, uint num) {
- scene._bitmapNum = 0;
- scene._startBitmap = 0;
- scene._decisionChoices = num;
- scene._waveFilename = "";
- scene._style = Scene::STYLE_DECISION_MIKE;
-
- Common::Point sz = getMikeSize(num);
-
- for (uint i = 0; i < num; i++) {
- Common::Point ms = getMikeStart(i, num);
- scene._choices[i]._region = Common::Rect(ms.x, ms.y, ms.x + 2 * sz.x, ms.y + sz.y);
- }
-}
-
-static void makeVideo(Scene &scene, const Common::String &videoName, const Common::String &nextScene) {
- scene._bitmapNum = 0;
- scene._startBitmap = 0;
- scene._decisionChoices = 1;
- scene._waveFilename = "";
- scene._style = Scene::STYLE_VIDEO;
- scene._sceneName = videoName;
- scene._decisionBitmap = "";
- scene._choices[0]._sceneName = nextScene;
-}
-
-static const struct {
- const char *from;
- struct {
- const char *scene;
- int points;
- } to[kMaxChoice];
-} tungraph[] = {
- {
- "dec13",
- {
- {"sc15", -10000},
- {"sc17", -10000},
- {"sc20", -50000}
- }
- },
- {
- "dec16",
- {
- {"dec13", -20000},
- {"restart", 0}
- }
- },
- {
-
- "dec18",
- {
- {"dec13", -30000},
- {"restart", 0}
- }
- },
- {
- "dec20",
- {
- {"sc21", -90000},
- {"sc22", -90000}
- }
- },
- {
- "dec22",
- {
- {"dec20", -90000},
- {"restart", 0}
- }
- },
- {
- "dec23",
- {
- {"sc24", 50000},
- {"sc28", -50000}
- }
- },
- {
- "dec25",
- {
- {"sc26", -75000},
- {"sc27", -90000}
- }
- },
- {
- "dec26",
- {
- {"dec25", -75000},
- {"restart", 0}
- }
- },
- {
- "dec28",
- {
- {"dec23", -75000},
- {"restart", 0}
- }
- },
- {
- "dec29",
- {
- {"sc30", -20000},
- {"sc31", 90000}
- }
- },
- {
- "dec30",
- {
- {"sc32", 0},
- {"restart", 0},
- {"end", 0}
- }
- },
- {
- "dec31",
- {
- {"dec29", -20000},
- {"end", 0}
- }
-
- }
-};
-
-void PlumbersGame::readTables3DO(const Common::String &fileName) {
- Common::File file;
- if (!file.open(fileName))
- error("sReadTables(): Error reading launchme file");
-
- initTables();
-
- file.seek(0x1ec08);
-
- Common::HashMap<Common::String, int> imgCounter, firstImg;
-
- uint bitmapCtr = 0;
-
- for (; bitmapCtr < 287; bitmapCtr++) {
- char buf[16];
- file.read(buf, 16);
- _bitmaps[bitmapCtr]._filename = Common::String(buf);
- _bitmaps[bitmapCtr]._duration = (file.readSint32BE() * 1000) / 60;
- Common::String scene = Common::String(buf).substr(0, 4);
- scene.toLowercase();
- imgCounter[scene]++;
- if (!firstImg.contains(scene))
- firstImg[scene] = bitmapCtr;
- }
-
- file.seek(0x205d0);
-
- for (; bitmapCtr < 704; bitmapCtr++) {
- char buf[16];
- file.read(buf, 16);
- _bitmaps[bitmapCtr]._filename = Common::String(buf);
- _bitmaps[bitmapCtr]._duration = (file.readSint32BE() * 1000) / 60;
- Common::String scene = Common::String(buf).substr(0, 4);
- scene.toLowercase();
- imgCounter[scene]++;
- if (!firstImg.contains(scene))
- firstImg[scene] = bitmapCtr;
- }
-
- uint scPtr = 0;
- makeVideo(_scenes[scPtr++], "kirinweaver", "janp1weaver");
- makeVideo(_scenes[scPtr++], "janp1weaver", "janp2weaver");
- makeVideo(_scenes[scPtr++], "janp2weaver", "janp3weaver");
- makeVideo(_scenes[scPtr++], "janp3weaver", "titleweaver");
- makeVideo(_scenes[scPtr++], "titleweaver", "miketest/sc00");
-
- makeMikeDecision(_scenes[scPtr], 2);
- _scenes[scPtr]._sceneName = "miketest/sc00";
- _scenes[scPtr]._decisionBitmap = "DEC00";
- _scenes[scPtr]._choices[0]._sceneName = "miketest/sc01";
- _scenes[scPtr++]._choices[1]._sceneName = "miketest/sc07a";
-
- for (uint scNo = 1; scNo <= 13; scNo++, scPtr++) {
- Common::String imgScene = scNo == 5 ?
- "sc44" : Common::String::format("sc%02d", scNo);
- _scenes[scPtr]._bitmapNum = imgCounter[imgScene];
- _scenes[scPtr]._startBitmap = firstImg[imgScene];
- _scenes[scPtr]._sceneName = scNo == 5 ? "miketest/sc04a" : Common::String::format("miketest/sc%02d", scNo);
- _scenes[scPtr]._waveFilename = Common::String::format("DIA%02d.aiff", scNo == 5 ? 4 : scNo);
- _scenes[scPtr]._style = Scene::STYLE_PC;
- _scenes[scPtr]._decisionChoices = 1;
- switch(scNo) {
- case 4:
- case 5:
- _scenes[scPtr]._choices[0]._sceneName = "miketest/sc06";
- break;
- case 11:
- _scenes[scPtr]._choices[0]._sceneName = "miketest/sc13";
- break;
- case 13:
- _scenes[scPtr]._choices[0]._sceneName = "tuntest/dec/dec13";
- break;
- case 7:
- case 8:
- case 12:
- _scenes[scPtr]._choices[0]._sceneName = Common::String::format("miketest/sc%02da", scNo);
- break;
- default:
- _scenes[scPtr]._choices[0]._sceneName = Common::String::format("miketest/sc%02d", scNo + 1);
- break;
- }
- }
-
- makeMikeDecision(_scenes[scPtr], 3);
- _scenes[scPtr]._sceneName = "miketest/sc07a";
- _scenes[scPtr]._decisionBitmap = "DEC07";
- _scenes[scPtr]._choices[0]._sceneName = "miketest/sc08";
- _scenes[scPtr]._choices[0]._points = -10000;
- _scenes[scPtr]._choices[1]._sceneName = "miketest/sc11";
- _scenes[scPtr]._choices[1]._points = 10000;
- _scenes[scPtr]._choices[2]._sceneName = "miketest/sc12";
- _scenes[scPtr]._choices[2]._points = -20000;
- scPtr++;
-
- makeMikeDecision(_scenes[scPtr], 2);
- _scenes[scPtr]._sceneName = "miketest/sc08a";
- _scenes[scPtr]._decisionBitmap = "DEC08";
- _scenes[scPtr]._choices[0]._sceneName = "miketest/sc09";
- _scenes[scPtr]._choices[0]._points = 0;
- _scenes[scPtr]._choices[1]._sceneName = "miketest/sc09";
- _scenes[scPtr]._choices[1]._points = 10000;
- scPtr++;
-
- makeMikeDecision(_scenes[scPtr], 2);
- _scenes[scPtr]._sceneName = "miketest/sc12a";
- _scenes[scPtr]._decisionBitmap = "DEC12";
- _scenes[scPtr]._choices[0]._sceneName = "miketest/sc07a";
- _scenes[scPtr]._choices[0]._points = 0;
- _scenes[scPtr]._choices[1]._sceneName = "restart";
- _scenes[scPtr]._choices[1]._points = 0;
- scPtr++;
-
- for (uint scNo = 15; scNo <= 32; scNo++) {
- // there is no sc19
- if (scNo == 19)
- continue;
- Common::String imgScene = Common::String::format("sc%02d", scNo);
- _scenes[scPtr]._bitmapNum = imgCounter[imgScene];
- _scenes[scPtr]._startBitmap = firstImg[imgScene];
- _scenes[scPtr]._sceneName = Common::String::format("tuntest/sc%02d", scNo);
- _scenes[scPtr]._waveFilename = Common::String::format("sc%02d.aiff", scNo);
- _scenes[scPtr]._style = Scene::STYLE_PC;
- _scenes[scPtr]._decisionChoices = 1;
- if (scNo == 32)
- _scenes[scPtr]._choices[0]._sceneName = "end";
- else if (scNo == 16 || scNo == 18 || scNo == 20 || scNo == 22 || scNo == 23 || scNo == 25
- || scNo == 26 || scNo == 28 || scNo == 29 || scNo == 30 || scNo == 31)
- _scenes[scPtr]._choices[0]._sceneName = Common::String::format("tuntest/dec/dec%02d", scNo);
- else
- _scenes[scPtr]._choices[0]._sceneName = Common::String::format("tuntest/sc%02d", scNo + 1);
- scPtr++;
- }
-
- file.seek(0x20290);
-
- for (int i = 0; i < 26; i++) {
- char buf[16];
- file.read(buf, 16);
- uint32 x = file.readUint32BE();
- uint32 y = file.readUint32BE();
- uint32 w = file.readUint32BE();
- uint32 h = file.readUint32BE();
- Common::String shortName = Common::String(buf).substr(0, 5);
- Common::String sceneName = "tuntest/dec/" + shortName;
- if (i == 0 || _scenes[scPtr - 1]._sceneName != sceneName) {
- _scenes[scPtr]._bitmapNum = 0;
- _scenes[scPtr]._startBitmap = 0;
- _scenes[scPtr]._decisionChoices = 0;
- _scenes[scPtr]._waveFilename = "";
- _scenes[scPtr]._style = Scene::STYLE_DECISION_TUN;
- _scenes[scPtr]._sceneName = sceneName;
- _scenes[scPtr]._decisionBitmap = shortName;
- scPtr++;
- }
-
- Scene &scene = _scenes[scPtr - 1];
- assert(scene._decisionChoices < kMaxChoice);
- scene._choices[scene._decisionChoices]._region = Common::Rect(x, y, x + w, y + h);
- for (uint j = 0 ; j < ARRAYSIZE(tungraph); j++) {
- if (shortName == tungraph[j].from) {
- Common::String target = tungraph[j].to[scene._decisionChoices].scene;
- if (target[0] == 's')
- scene._choices[scene._decisionChoices]._sceneName = "tuntest/" + target;
- else
- scene._choices[scene._decisionChoices]._sceneName = "tuntest/dec/" + target;
- scene._choices[scene._decisionChoices]._points = tungraph[j].to[scene._decisionChoices].points;
- break;
- }
- }
- scene._decisionChoices++;
- }
-
- _totScene = scPtr;
-}
-
int PlumbersGame::getSceneNumb(const Common::String &sName) {
debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, sName.c_str());
- if (sName == "miketest/sc04" && _cheatEnabled)
- return getSceneNumb("miketest/sc04a");
-
for (int sCurScene = 0; sCurScene < _totScene; sCurScene++) {
if (sName == _scenes[sCurScene]._sceneName)
return sCurScene;
diff --git a/engines/plumbers/plumbers.h b/engines/plumbers/plumbers.h
index 3aff5af0855..787390449ed 100644
--- a/engines/plumbers/plumbers.h
+++ b/engines/plumbers/plumbers.h
@@ -24,6 +24,7 @@
#include "engines/engine.h"
+#include "common/events.h"
#include "common/platform.h"
#include "common/queue.h"
#include "common/rect.h"
@@ -31,14 +32,11 @@
#include "audio/mixer.h"
-#include "video/3do_decoder.h"
+#include "video/video_decoder.h"
+#include "image/image_decoder.h"
struct ADGameDescription;
-namespace Image {
-class ImageDecoder;
-}
-
namespace Graphics {
struct Surface;
}
@@ -88,10 +86,23 @@ public:
const char *getGameId() const;
Common::Platform getPlatform() const;
-private:
+protected:
+ virtual void readTables() = 0;
+ virtual void postSceneBitmaps() = 0;
+ virtual bool handlePlatformJoyButton(int button) { return false; }
+ virtual bool handlePlatformKeyDown(int button) { return false; }
+ virtual void loadImage(const Common::String &name);
+ virtual void startGraphics() = 0;
+ void blitImageSurface(Graphics::Surface *screen, const Graphics::Surface *surface);
+ virtual void blitImage(Graphics::Surface *screen);
+ virtual void handleEvent(const Common::Event &event);
+ virtual int getSceneNumb(const Common::String &sName);
+ virtual void preActions() {}
+
static const int kMaxName = 13 + 1;
static const int kMaxBitmaps = 2000;
static const int kMaxScene = 100;
+ void initTables();
struct {
int _duration;
@@ -99,11 +110,12 @@ private:
} _bitmaps[kMaxBitmaps];
Scene _scenes[kMaxScene];
+ int _totScene;
+ long _totScore;
Image::ImageDecoder *_image;
- Image::ImageDecoder *_ctrlHelpImage;
Console *_console;
-
+ Video::VideoDecoder *_videoDecoder;
bool _showScoreFl;
bool _setDurationFl;
bool _leftButtonDownFl;
@@ -112,16 +124,8 @@ private:
int _curSceneIdx, _prvSceneIdx;
int _curBitmapIdx;
int _curChoice;
- int _totScene;
- long _totScore;
int _screenW, _screenH;
- int _kbdHiLite;
- int _mouseHiLite;
- int _hiLite;
- bool _hiLiteEnabled;
- bool _cheatEnabled;
- int _cheatFSM;
- bool _leftShoulderPressed;
+ bool _quit;
enum Action {
Redraw,
@@ -134,13 +138,9 @@ private:
Common::Queue<Action> _actions;
Graphics::Surface *_compositeSurface;
- void loadImage(const Common::String &name);
- void loadMikeDecision(const Common::String &dirname, const Common::String &baseFilename, uint num);
void drawScreen();
- void updateHiLite();
Audio::SoundHandle _soundHandle;
- Video::ThreeDOMovieDecoder *_videoDecoder;
void playSound(const Common::String &name);
void stopSound();
@@ -152,17 +152,53 @@ private:
void processTimer();
static void onTimer(void *arg);
- void initTables();
- void readTablesPC(const Common::String &fileName);
- void readTables3DO(const Common::String &fileName);
- int getSceneNumb(const Common::String &sName);
int getMouseHiLite();
+};
+
+class PlumbersGame3DO : public PlumbersGame {
+public:
+ PlumbersGame3DO(OSystem *syst, const ADGameDescription *gameDesc);
+
+protected:
+ void readTables() override;
+ void postSceneBitmaps() override;
+ void startGraphics() override;
+ void handleEvent(const Common::Event &event) override;
+ void blitImage(Graphics::Surface *screen) override;
+ int getSceneNumb(const Common::String &sName) override;
+ void preActions() override;
+private:
+ void skipVideo();
+ void loadMikeDecision(const Common::String &dirname, const Common::String &baseFilename, uint num);
void joyUp();
void joyDown();
void joyA();
- void skipVideo();
+ void updateHiLite();
+
+ bool _cheatEnabled;
+ int _cheatFSM;
+ bool _leftShoulderPressed;
+ int _kbdHiLite;
+ int _mouseHiLite;
+ int _hiLite;
+ Image::ImageDecoder *_ctrlHelpImage;
};
+
+class PlumbersGameWindows : public PlumbersGame {
+public:
+ PlumbersGameWindows(OSystem *syst, const ADGameDescription *gameDesc);
+
+protected:
+ void readTables() override;
+ void postSceneBitmaps() override;
+ void loadImage(const Common::String &name) override;
+ void startGraphics() override;
+
+private:
+ bool _halfSize;
+};
+
} // End of namespace Plumbers
#endif
diff --git a/engines/plumbers/windows.cpp b/engines/plumbers/windows.cpp
new file mode 100644
index 00000000000..2882fc6e957
--- /dev/null
+++ b/engines/plumbers/windows.cpp
@@ -0,0 +1,144 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "plumbers/plumbers.h"
+#include "plumbers/console.h"
+
+#include "audio/decoders/aiff.h"
+#include "audio/decoders/wave.h"
+#include "audio/audiostream.h"
+
+#include "common/debug.h"
+#include "common/debug-channels.h"
+#include "common/error.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/system.h"
+#include "common/timer.h"
+
+#include "engines/util.h"
+
+#include "graphics/cursorman.h"
+#include "graphics/font.h"
+#include "graphics/fontman.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+#include "graphics/scaler/downscaler.h"
+
+#include "image/bmp.h"
+
+namespace Plumbers {
+PlumbersGameWindows::PlumbersGameWindows(OSystem *syst, const ADGameDescription *gameDesc) : PlumbersGame(syst, gameDesc), _halfSize(false) {
+}
+
+void PlumbersGameWindows::loadImage(const Common::String &name) {
+ PlumbersGame::loadImage(name);
+
+ if (_halfSize) {
+ _compositeSurface = new Graphics::Surface();
+ const Graphics::Surface *inSurf = _image->getSurface();
+ _compositeSurface->create(_screenW, _screenH, inSurf->format);
+ Graphics::downscaleSurfaceByHalf(_compositeSurface, inSurf, _image->getPalette());
+ }
+}
+
+void PlumbersGameWindows::startGraphics() {
+ _image = new Image::BitmapDecoder();
+
+ Graphics::ModeWithFormatList modes = {
+ // First try for a 640x480 mode
+ Graphics::ModeWithFormat(640, 480),
+ // System doesn't support it, so fall back on 320x240 mode
+ Graphics::ModeWithFormat(320, 240),
+ };
+
+ int modeIdx = initGraphicsAny(modes);
+
+ if (modeIdx == 0) {
+ _screenW = 640;
+ _screenH = 480;
+ } else {
+ _halfSize = true;
+ _screenW = 320;
+ _screenH = 240;
+ }
+}
+
+void PlumbersGameWindows::readTables() {
+ Common::File file;
+ if (!file.open("game.bin"))
+ error("sReadTables(): Error reading BIN file");
+
+ initTables();
+
+ _totScore = file.readSint32LE();
+ file.skip(10);
+ _totScene = file.readSint16LE();
+ file.skip(6);
+
+ char buf[kMaxName];
+ for (int i = 0; i < kMaxScene; i++) {
+ _scenes[i]._bitmapNum = file.readSint16LE();
+ _scenes[i]._startBitmap = file.readSint16LE();
+ _scenes[i]._decisionChoices = file.readSint16LE();
+ file.read(buf, kMaxName);
+ _scenes[i]._sceneName = Common::String(buf);
+ file.read(buf, kMaxName);
+ _scenes[i]._waveFilename = Common::String(buf);
+ file.read(buf, kMaxName);
+ _scenes[i]._decisionBitmap = Common::String(buf);
+ _scenes[i]._style = Scene::STYLE_PC;
+
+ for (int j = 0; j < kMaxChoice; j++) {
+ _scenes[i]._choices[j]._points = file.readSint32LE();
+ _scenes[i]._choices[j]._sceneName = Common::String::format("SC%02d", file.readSint16LE());
+ _scenes[i]._choices[j]._skipScene = file.readSint16LE();
+ int left = file.readSint16LE();
+ int top = file.readSint16LE();
+ int right = file.readSint16LE();
+ int bottom = file.readSint16LE();
+ if (_halfSize)
+ _scenes[i]._choices[j]._region = Common::Rect(left / 2, top / 2, right / 2, bottom / 2);
+ else
+ _scenes[i]._choices[j]._region = Common::Rect(left, top, right, bottom);
+ }
+ }
+
+ for (int i = 0; i < kMaxBitmaps; i++) {
+ _bitmaps[i]._duration = file.readSint16LE() * 100;
+ file.read(buf, kMaxName);
+ _bitmaps[i]._filename = Common::String(buf);
+ }
+}
+
+void PlumbersGameWindows::postSceneBitmaps() {
+ if (_scenes[_curSceneIdx]._decisionChoices == 1) {
+ _curChoice = 0;
+ _actions.push(ChangeScene);
+ return;
+ }
+
+ _showScoreFl = true;
+ _leftButtonDownFl = true;
+ _setDurationFl = false;
+ loadImage(_scenes[_curSceneIdx]._sceneName + "/" + _scenes[_curSceneIdx]._decisionBitmap);
+}
+} // End of namespace Plumbers
Commit: 35d72e4487fccbc9271e82e8313327e72b2e94eb
https://github.com/scummvm/scummvm/commit/35d72e4487fccbc9271e82e8313327e72b2e94eb
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-02-28T01:58:13+01:00
Commit Message:
PLUMBERS: Use smaller cursor on lower resolutions
Changed paths:
engines/plumbers/plumbers.cpp
diff --git a/engines/plumbers/plumbers.cpp b/engines/plumbers/plumbers.cpp
index cfa44385bd7..2753844a9b5 100644
--- a/engines/plumbers/plumbers.cpp
+++ b/engines/plumbers/plumbers.cpp
@@ -85,6 +85,21 @@ static const byte MOUSECURSOR_SCI[] = {
0,0,0,0,0,0,1,2,2,1,0
};
+static const byte MOUSECURSOR_AMIGA[] = {
+ 1,1,0,0,0,0,0,0,
+ 1,2,1,0,0,0,0,0,
+ 1,2,2,1,0,0,0,0,
+ 1,2,2,2,1,0,0,0,
+ 1,2,2,2,2,1,0,0,
+ 1,2,2,2,2,2,1,0,
+ 1,1,1,2,2,1,1,0,
+ 0,0,0,1,2,1,0,0,
+ 0,0,0,1,2,2,1,0,
+ 0,0,0,0,1,2,1,0,
+ 0,0,0,0,1,2,2,1,
+ 0,0,0,0,0,1,1,0,
+};
+
static const byte cursorPalette[] = {
0, 0, 0, // Black / Transparent
0x80, 0x80, 0x80, // Gray
@@ -124,7 +139,10 @@ Common::Error PlumbersGame::run() {
_console = new Console();
setDebugger(_console);
- CursorMan.replaceCursor(MOUSECURSOR_SCI, 11, 16, 0, 0, 0);
+ if (_screenW > 320)
+ CursorMan.replaceCursor(MOUSECURSOR_SCI, 11, 16, 0, 0, 0);
+ else
+ CursorMan.replaceCursor(MOUSECURSOR_AMIGA, 8, 12, 0, 0, 0);
CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
CursorMan.showMouse(true);
Commit: 573bd18cd3ff6a9e4a165d272d94207049a8eeda
https://github.com/scummvm/scummvm/commit/573bd18cd3ff6a9e4a165d272d94207049a8eeda
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-02-28T01:58:13+01:00
Commit Message:
PLUMBERS: Mark 3DO version as supported
Changed paths:
engines/plumbers/detection.cpp
diff --git a/engines/plumbers/detection.cpp b/engines/plumbers/detection.cpp
index 5a2b03863dc..844494eebec 100644
--- a/engines/plumbers/detection.cpp
+++ b/engines/plumbers/detection.cpp
@@ -57,7 +57,7 @@ static const ADGameDescription gameDescriptions[] = {
AD_ENTRY1s("launchme", "d3ab77d1a8a2289422a0f51e7aa91821", 143300),
Common::EN_ANY,
Common::kPlatform3DO,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO1(GUIO_NOMIDI)
},
Commit: 13eb6f3be096392b48681a072e36ea6df75ea020
https://github.com/scummvm/scummvm/commit/13eb6f3be096392b48681a072e36ea6df75ea020
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2023-02-28T01:58:13+01:00
Commit Message:
DREAMWEB: Don't use 640x480 if USE_HIGHRES is false
Otherwise it leads to immediate crash on low-resolution devices.
Changed paths:
engines/dreamweb/titles.cpp
engines/dreamweb/vgagrafx.cpp
diff --git a/engines/dreamweb/titles.cpp b/engines/dreamweb/titles.cpp
index d6f1ff126ef..5dcf5ccb19c 100644
--- a/engines/dreamweb/titles.cpp
+++ b/engines/dreamweb/titles.cpp
@@ -27,6 +27,21 @@
namespace DreamWeb {
+namespace {
+void initTitlesGfx() {
+ Graphics::ModeWithFormatList modes = {
+#ifdef USE_HIGHRES
+ // First try for a 640x480 mode
+ Graphics::ModeWithFormat(640, 480),
+#endif
+ // System doesn't support it, so fall back on 320x240 mode
+ Graphics::ModeWithFormat(320, 240),
+ };
+
+ initGraphicsAny(modes);
+}
+}
+
void DreamWebEngine::endGame() {
loadTempText("T83");
monkSpeaking();
@@ -148,7 +163,7 @@ void DreamWebEngine::bibleQuote() {
break;
}
- initGraphics(640, 480);
+ initTitlesGfx();
showPCX("I00");
fadeScreenUps();
@@ -342,7 +357,7 @@ void DreamWebEngine::realCredits() {
_sound->loadRoomsSample(_roomsSample);
_sound->volumeSet(0);
- initGraphics(640, 480);
+ initTitlesGfx();
hangOn(35);
showPCX("I01");
diff --git a/engines/dreamweb/vgagrafx.cpp b/engines/dreamweb/vgagrafx.cpp
index 07b0c7954b9..a0523bfd5d9 100644
--- a/engines/dreamweb/vgagrafx.cpp
+++ b/engines/dreamweb/vgagrafx.cpp
@@ -23,6 +23,7 @@
#include "common/file.h"
#include "engines/util.h"
#include "graphics/surface.h"
+#include "graphics/scaler/downscaler.h"
#include "image/pcx.h"
namespace DreamWeb {
@@ -176,12 +177,17 @@ void DreamWebEngine::showPCX(const Common::String &suffix) {
}
Graphics::Surface *s = g_system->lockScreen();
- s->fillRect(Common::Rect(640, 480), 0);
+ s->fillRect(Common::Rect(s->w, s->h), 0);
const Graphics::Surface *pcxSurface = pcx.getSurface();
if (pcxSurface->format.bytesPerPixel != 1)
error("Invalid bytes per pixel in PCX surface (%d)", pcxSurface->format.bytesPerPixel);
- for (uint16 y = 0; y < pcxSurface->h; y++)
- memcpy((byte *)s->getBasePtr(0, y), pcxSurface->getBasePtr(0, y), pcxSurface->w);
+ if (pcxSurface->w >= s->w * 2)
+ Graphics::downscaleSurfaceByHalf(s, pcxSurface, _mainPal);
+ else {
+ int limitW = MIN(pcxSurface->w, s->w);
+ for (uint16 y = 0; y < pcxSurface->h; y++)
+ memcpy((byte *)s->getBasePtr(0, y), pcxSurface->getBasePtr(0, y), limitW);
+ }
g_system->unlockScreen();
}
More information about the Scummvm-git-logs
mailing list