[Scummvm-git-logs] scummvm master -> 53b24ac793c46992ea91244675f953eb82790a0f
mduggan
noreply at scummvm.org
Sun Jul 28 04:15:33 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
53b24ac793 DGDS: Implement Willy Beamish scroll
Commit: 53b24ac793c46992ea91244675f953eb82790a0f
https://github.com/scummvm/scummvm/commit/53b24ac793c46992ea91244675f953eb82790a0f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-07-28T14:14:35+10:00
Commit Message:
DGDS: Implement Willy Beamish scroll
Still not totally rendering correctly, but partly works (eg, scroll in
Principal's office at start of game)
Changed paths:
engines/dgds/dgds.cpp
engines/dgds/dgds.h
engines/dgds/dialog.cpp
engines/dgds/font.cpp
engines/dgds/image.cpp
engines/dgds/image.h
engines/dgds/ttm.cpp
engines/dgds/ttm.h
diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index b3fcfb15837..db433cf0df0 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -82,7 +82,7 @@ DgdsEngine::DgdsEngine(OSystem *syst, const ADGameDescription *gameDesc)
_soundPlayer(nullptr), _decompressor(nullptr), _scene(nullptr), _shellGame(nullptr),
_gdsScene(nullptr), _resource(nullptr), _gamePals(nullptr), _gameGlobals(nullptr),
_detailLevel(kDgdsDetailHigh), _textSpeed(1), _justChangedScene1(false), _justChangedScene2(false),
- _random("dgds"), _currentCursor(-1), _menuToTrigger(kMenuNone), _isLoading(true),
+ _random("dgds"), _currentCursor(-1), _menuToTrigger(kMenuNone), _isLoading(true), _flipMode(false),
_rstFileName(nullptr), _difficulty(1), _menu(nullptr), _adsInterp(nullptr), _isDemo(false) {
syncSoundSettings();
diff --git a/engines/dgds/dgds.h b/engines/dgds/dgds.h
index 6a8409813ed..ae60cf04614 100644
--- a/engines/dgds/dgds.h
+++ b/engines/dgds/dgds.h
@@ -145,6 +145,7 @@ private:
const char *_rstFileName;
bool _isDemo;
+ bool _flipMode;
public:
DgdsEngine(OSystem *syst, const ADGameDescription *gameDesc);
@@ -219,6 +220,7 @@ public:
ShellGame *getShellGame() { return _shellGame; }
static DgdsEngine *getInstance() { return static_cast<DgdsEngine *>(g_engine); }
+ void setFlipMode(bool mode) { _flipMode = mode; }
private:
Common::Error syncGame(Common::Serializer &s);
diff --git a/engines/dgds/dialog.cpp b/engines/dgds/dialog.cpp
index f13791fbca8..6b3100613c6 100644
--- a/engines/dgds/dialog.cpp
+++ b/engines/dgds/dialog.cpp
@@ -91,6 +91,8 @@ const DgdsFont *Dialog::getDlgTextFont() const {
fontType = FontManager::k8x8Font;
else if (_fontSize == 3)
fontType = FontManager::k4x5Font;
+ else if (_fontSize == 4 && DgdsEngine::getInstance()->getGameId() == GID_WILLY)
+ fontType = FontManager::kGameFont;
else if (_fontSize == 5 && DgdsEngine::getInstance()->getGameId() == GID_HOC)
fontType = FontManager::kChinaFont;
return fontman->getFont(fontType);
@@ -171,7 +173,7 @@ void Dialog::drawType2BackgroundBeamish(Graphics::ManagedSurface *dst, const Com
// TODO: Maybe should measure the font?
_state->_loc.y += 11;
_state->_loc.height -= 11;
- RequestData::drawHeader(dst, _rect.x, _rect.y, _rect.width, 2, title, _fontColor, false, 0, 0);
+ RequestData::drawHeader(dst, _rect.x, _rect.y + 5, _rect.width, 2, title, _fontColor, false, 0, 0);
}
}
diff --git a/engines/dgds/font.cpp b/engines/dgds/font.cpp
index 53b8f0a0525..69ac6f0c222 100644
--- a/engines/dgds/font.cpp
+++ b/engines/dgds/font.cpp
@@ -220,8 +220,8 @@ FontManager::FontType FontManager::fontTypeByName(const Common::String &filename
if (filename == "HOC.FNT") return kGameFont;
if (filename == "CHINA.FNT") return kGameDlgFont;
if (filename == "CHINESE.FNT") return kChinaFont;
- if (filename == "WILLY.FNT") return kGameDlgFont;
- if (filename == "COMIX_16.FNT") return kGameFont;
+ if (filename == "WILLY.FNT") return kGameFont;
+ if (filename == "COMIX_16.FNT") return kGameDlgFont;
if (filename == "WVCR.FNT") return kVCRFont;
if (filename == "EXIT.FNT") return kVCRFont;
if (filename == "SSM1_12.FNT") return kGameFont;
diff --git a/engines/dgds/image.cpp b/engines/dgds/image.cpp
index 94f5ddde80d..160d196d5aa 100644
--- a/engines/dgds/image.cpp
+++ b/engines/dgds/image.cpp
@@ -37,7 +37,7 @@
namespace Dgds {
-Image::Image(ResourceManager *resourceMan, Decompressor *decompressor) : _resourceMan(resourceMan), _decompressor(decompressor) {
+Image::Image(ResourceManager *resourceMan, Decompressor *decompressor) : _resourceMan(resourceMan), _decompressor(decompressor), _matrixX(0), _matrixY(0) {
}
Image::~Image() {
@@ -143,7 +143,7 @@ void Image::loadBitmap(const Common::String &filename) {
if (chunk.isSection(ID_INF)) {
Common::Array<Common::Point> tileSizes;
uint16 tileCount = stream->readUint16LE();
- if (tileCount > 256)
+ if (tileCount > 1024)
error("Image::loadBitmap: Unexpectedly large number of tiles in image (%d)", tileCount);
_frames.resize(tileCount);
tileSizes.resize(tileCount);
@@ -159,20 +159,17 @@ void Image::loadBitmap(const Common::String &filename) {
}
} else if (chunk.isSection(ID_MTX)) {
// Scroll offset
- Common::Array<uint16> mtxVals;
- uint16 mw, mh;
- mw = stream->readUint16LE();
- mh = stream->readUint16LE();
- uint32 mcount = uint32(mw) * mh;
- mtxVals.resize(mcount);
- debug(" %ux%u: mtx vals", mw, mh);
+ _matrixX = stream->readUint16LE();
+ _matrixY = stream->readUint16LE();
+ uint32 mcount = (uint32)_matrixX * _matrixY;
+ _tileMatrix.resize(mcount);
+ debug(" %u x %u: mtx vals", _matrixX, _matrixY);
for (uint32 k = 0; k < mcount; k++) {
uint16 tile;
tile = stream->readUint16LE();
- mtxVals[k] = tile;
+ _tileMatrix[k] = tile;
}
- // TODO: Use mtxVals ?
} else if (chunk.isSection(ID_BIN)) {
for (auto & frame : _frames) {
loadBitmap4(frame.get(), 0, stream, false);
@@ -283,6 +280,47 @@ void Image::drawBitmap(uint frameno, int x, int y, const Common::Rect &drawWin,
}
}
+void Image::drawScrollBitmap(int16 x, int16 y, int16 width, int16 height, int16 scrollX, int16 scrollY, const Common::Rect &drawWin, Graphics::ManagedSurface &dstSurf) const {
+ if (_frames.empty())
+ error("Trying to draw scroll for empty image.");
+ if (_tileMatrix.empty())
+ error("Trying to draw scroll with non-tiled image.");
+ int tileW = _frames[0]->w;
+ int tileH = _frames[0]->h;
+ byte *dst = (byte *)dstSurf.getBasePtr(0, 0);
+
+ for (int yTile = 0; yTile < height / tileH; yTile++) {
+ int tileDstY = y + yTile * tileH;
+ int tileRowIndex = (yTile + scrollY) % _matrixY;
+ if (tileRowIndex < 0)
+ tileRowIndex += _matrixY;
+ for (int xTile = 0; xTile < width / tileW; xTile++) {
+ int tileDstX = x + xTile * tileW;
+ Common::Rect tileDest(Common::Point(tileDstX, tileDstY), tileW, tileH);
+ tileDest.clip(drawWin);
+ if (tileDest.isEmpty())
+ continue;
+
+ int tileColIndex = (xTile + scrollX) % _matrixX;
+ if (tileColIndex < 0)
+ tileColIndex += _matrixX;
+
+ uint16 tileNo = _tileMatrix[tileRowIndex + tileColIndex * _matrixY];
+ Common::SharedPtr<Graphics::ManagedSurface> tile = _frames[tileNo];
+ const byte *src = (const byte *)tile->getBasePtr(0, 0);
+
+ for (int dstY = tileDstY; dstY < tileDstY + tileH; dstY++) {
+ for (int dstX = tileDstX; dstX < tileDstX + tileW; dstX++) {
+ if (!tileDest.contains(dstX, dstY))
+ continue;
+ dst[dstY * dstSurf.pitch + dstX] = src[(dstY - tileDstY) * tile->pitch + (dstX - tileDstX)];
+ }
+ }
+ }
+ }
+}
+
+
void Image::loadBitmap4(Graphics::ManagedSurface *surf, uint32 toffset, Common::SeekableReadStream *stream, bool highByte) {
uint32 tw = surf->w;
uint32 th = surf->h;
diff --git a/engines/dgds/image.h b/engines/dgds/image.h
index f1913fc0f8e..abcd28acd7d 100644
--- a/engines/dgds/image.h
+++ b/engines/dgds/image.h
@@ -58,6 +58,7 @@ public:
void loadBitmap(const Common::String &filename);
int frameCount(const Common::String &filename);
void drawBitmap(uint frameno, int x, int y, const Common::Rect &drawWin, Graphics::ManagedSurface &dst, ImageFlipMode flip = kImageFlipNone, int dstWidth = 0, int dstHeight = 0) const;
+ void drawScrollBitmap(int16 x, int16 y, int16 width, int16 height, int16 scrollX, int16 scrollY, const Common::Rect &drawWin, Graphics::ManagedSurface &dst) const;
Common::SharedPtr<Graphics::ManagedSurface> getSurface(uint frameno) const;
@@ -82,6 +83,11 @@ private:
Decompressor *_decompressor;
Common::String _filename; // the file this was loaded from - only used for debugging
+
+ // Used if the image is a scrolling image.
+ int16 _matrixX;
+ int16 _matrixY;
+ Common::Array<uint16> _tileMatrix;
};
} // End of namespace Dgds
diff --git a/engines/dgds/ttm.cpp b/engines/dgds/ttm.cpp
index a80ba9ab939..65c06b57e22 100644
--- a/engines/dgds/ttm.cpp
+++ b/engines/dgds/ttm.cpp
@@ -158,7 +158,7 @@ static const char *ttmOpName(uint16 op) {
case 0x2000: return "SET DRAW COLORS";
case 0x2010: return "SET FRAME";
case 0x2020: return "SET RANDOM DELAY";
- case 0x2030: return "SET SCROLL 2030??";
+ case 0x2030: return "SET SCROLL OFFSET";
case 0x2300: return "PAL SET BLOCK SWAP 0";
case 0x2310: return "PAL SET BLOCK SWAP 1";
case 0x2320: return "PAL SET BLOCK SWAP 2";
@@ -215,6 +215,7 @@ static const char *ttmOpName(uint16 op) {
case 0xf040: return "LOAD FONT";
case 0xf050: return "LOAD PAL";
case 0xf060: return "LOAD SONG";
+ case 0xf080: return "LOAD SCROLL";
case 0xf100: return "SET STRING 0";
case 0xf110: return "SET STRING 1";
case 0xf120: return "SET STRING 2";
@@ -542,6 +543,12 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
break;
warning("TODO: 0x0400 Reset palette");
break;
+ case 0x0500: // FLIP MODE ON
+ DgdsEngine::getInstance()->setFlipMode(true);
+ break;
+ case 0x0510: // FLIP MODE OFF
+ DgdsEngine::getInstance()->setFlipMode(false);
+ break;
case 0x0ff0: // REFRESH: void
break;
case 0x1020: // SET DELAY: i:int [0..n]
@@ -604,6 +611,29 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
_vm->adsInterpreter()->setScriptDelay((int)(sleep * MS_PER_FRAME));
break;
}
+ case 0x2030: { // SET SCROLL mode,val: int
+ if (seq._executed) // this is a one-shot op.
+ break;
+
+ // mode chooses x/y and +/- for scroll offset.
+ switch(ivals[0]) {
+ case 0:
+ env._yScroll -= ivals[1];
+ break;
+ case 1:
+ env._yScroll += ivals[1];
+ break;
+ case 2:
+ env._xScroll -= ivals[1];
+ break;
+ case 3:
+ env._xScroll += ivals[1];
+ break;
+ default:
+ error("TTM 0x2030 Invalid scroll mode %d (should be 0-3)", ivals[0]);
+ }
+ break;
+ }
case 0x2300:
case 0x2310:
case 0x2320: {
@@ -627,9 +657,8 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
int64 prevPos = env.scr->pos();
env.scr->seek(env._frameOffsets[target]);
- // TODO: Set some other render-related globals here
- if (ivals[0] || ivals[1])
- warning("TODO: TTM 0x3000 GOSUB use offsets (%d, %d)", ivals[0], ivals[1]);
+ env._xOff = ivals[0];
+ env._yOff = ivals[1];
run(env, seq);
env.scr->seek(prevPos);
@@ -644,6 +673,7 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
if (seq._executed) // this is a one-shot op.
break;
warning("TODO: TTM 0x3100 SCROLL %d %d %d", ivals[0], ivals[1], ivals[2]);
+ break;
}
case 0x4000: // SET CLIP WINDOW x,y,x2,y2:int [0..320,0..200]
// NOTE: params are xmax/ymax, NOT w/h
@@ -810,7 +840,8 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
Common::SharedPtr<Image> img = env._scriptShapes[bmpNo];
if (img)
- img->drawBitmap(frameno, ivals[0], ivals[1], seq._drawWin, _vm->_compositionBuffer, flipMode, dstWidth, dstHeight);
+ img->drawBitmap(frameno, env._xOff + ivals[0], env._yOff + ivals[1],
+ seq._drawWin, _vm->_compositionBuffer, flipMode, dstWidth, dstHeight);
else
warning("Trying to draw image %d in env %d which is not loaded", bmpNo, env._enviro);
break;
@@ -829,6 +860,15 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
Common::Point(r.left, r.top));
break;
}
+ case 0xa700: { // DRAW scrollshape? x,y,w,h??
+ if (!env._scrollShape) {
+ warning("Trying to draw scroll with no scrollshape loaded");
+ } else {
+ env._scrollShape->drawScrollBitmap(ivals[0], ivals[1], ivals[2], ivals[3],
+ env._xScroll, env._yScroll, seq._drawWin, _vm->_compositionBuffer);
+ }
+ break;
+ }
case 0xaf00: { // FLOOD FILL x,y
Graphics::FloodFill f(_vm->_compositionBuffer.surfacePtr(), 0, seq._drawColFG);
f.addSeed(ivals[0], ivals[1]);
@@ -950,6 +990,15 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
_vm->_soundPlayer->playMusic(seq._currentSongId);
}
break;
+ case 0xf080: { // LOAD SCROLL: filename:str
+ if (seq._executed) // this is a one-shot op
+ break;
+ env._scrollShape.reset(new Image(_vm->getResourceManager(), _vm->getDecompressor()));
+ env._scrollShape->loadBitmap(sval);
+ env._xScroll = 0;
+ env._yScroll = 0;
+ break;
+ }
case 0xf100: // 0xf1n0 - SET STRING n: s:str - set the nth string in the table
case 0xf110:
case 0xf120:
diff --git a/engines/dgds/ttm.h b/engines/dgds/ttm.h
index be1ef66214c..3afe2bb2c93 100644
--- a/engines/dgds/ttm.h
+++ b/engines/dgds/ttm.h
@@ -38,7 +38,8 @@ public:
class TTMEnviro : public ScriptParserData {
public:
TTMEnviro() : _totalFrames(330), _enviro(0), _creditScrollMeasure(0),
- _creditScrollYOffset(0), ScriptParserData() {
+ _creditScrollYOffset(0), _xOff(0), _yOff(0), _xScroll(0), _yScroll(0),
+ ScriptParserData() {
ARRAYCLEAR(_scriptPals);
}
@@ -54,6 +55,13 @@ public:
Common::Array<FontManager::FontType> _fonts;
int16 _creditScrollMeasure;
int16 _creditScrollYOffset;
+ // The below are all globals in the original, but never get access from
+ // multiple environments so cleaner to keep here?
+ int16 _xOff;
+ int16 _yOff;
+ Common::SharedPtr<Image> _scrollShape;
+ int16 _xScroll;
+ int16 _yScroll;
};
enum TTMRunType {
More information about the Scummvm-git-logs
mailing list