[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