[Scummvm-git-logs] scummvm master -> 33918158324e0150ab623f9268135e52e4666ea6

whoozle noreply at scummvm.org
Sun Jul 19 12:54:53 UTC 2026


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
3391815832 PHOENIXVR: Add V2 cursor management


Commit: 33918158324e0150ab623f9268135e52e4666ea6
    https://github.com/scummvm/scummvm/commit/33918158324e0150ab623f9268135e52e4666ea6
Author: Vladimir Menshakov (vladimir.menshakov at gmail.com)
Date: 2026-07-19T13:53:10+01:00

Commit Message:
PHOENIXVR: Add V2 cursor management

Fix first argument parsing.

Changed paths:
    engines/phoenixvr/commands_v2.cpp
    engines/phoenixvr/phoenixvr.cpp
    engines/phoenixvr/phoenixvr.h
    engines/phoenixvr/script_v2.cpp


diff --git a/engines/phoenixvr/commands_v2.cpp b/engines/phoenixvr/commands_v2.cpp
index 41d1eabef7d..c2ebb09d0ba 100644
--- a/engines/phoenixvr/commands_v2.cpp
+++ b/engines/phoenixvr/commands_v2.cpp
@@ -79,13 +79,53 @@ struct Play_Sound : public Command {
 	}
 };
 
+struct Stop_All_Sounds : public Command {
+	Stop_All_Sounds(const Common::Array<Common::String> &args) {}
+
+	void exec(ExecutionContext &ctx) const override {
+		g_engine->stopAllSounds();
+	}
+};
+
+struct Cursor_Load : public Command {
+	Common::String index;
+	Common::String path;
+	Common::String width;
+	Common::String height;
+
+	Cursor_Load(const Common::Array<Common::String> &args) : index(args[0]), path(args[1]), width(args.size() > 2 ? args[2].c_str() : "0"), height(args.size() > 3 ? args[3].c_str() : "0") {}
+
+	void exec(ExecutionContext &ctx) const override {
+		g_engine->loadCursor(valueOf(index), path, valueOf(width), valueOf(height));
+	}
+};
+
+struct Cursor_Set : public Command {
+	Common::String type;
+	Common::String index;
+
+	Cursor_Set(const Common::Array<Common::String> &args) : type(args[0]), index(args[1]) {}
+
+	void exec(ExecutionContext &ctx) const override {
+		if (type == "_ON_IDDLE")
+			g_engine->setCursorDefault(0, valueOf(index));
+		else if (type == "_ON_TEST")
+			g_engine->setCursorDefault(1, valueOf(index));
+		else
+			warning("invalid cursor type %s", type.c_str());
+	}
+};
+
 } // namespace
 
 #define COMMAND_LIST(E) \
 	E(Add)              \
-	E(Sub)              \
+	E(Cursor_Load)      \
+	E(Cursor_Set)       \
 	E(Play_Sound)       \
-	E(Play_AnimBloc)
+	E(Play_AnimBloc)    \
+	E(Stop_All_Sounds)  \
+	E(Sub)
 
 #define ADD_COMMAND(NAME)            \
 	if (cmd.equalsIgnoreCase(#NAME)) \
diff --git a/engines/phoenixvr/phoenixvr.cpp b/engines/phoenixvr/phoenixvr.cpp
index 33266d0d42c..75872c4c28b 100644
--- a/engines/phoenixvr/phoenixvr.cpp
+++ b/engines/phoenixvr/phoenixvr.cpp
@@ -43,6 +43,7 @@
 #include "graphics/palette.h"
 #include "image/gif.h"
 #include "image/pcx.h"
+#include "image/tga.h"
 #include "phoenixvr/arn.h"
 #include "phoenixvr/console.h"
 #include "phoenixvr/game_state.h"
@@ -300,6 +301,7 @@ PhoenixVREngine::PhoenixVREngine(OSystem *syst, const ADGameDescription *gameDes
 																					 _rgb565(2, 5, 6, 5, 0, 11, 5, 0, 0),
 																					 _thumbnail(isAmerzoneGame(gameDesc) ? 232 : 139, isAmerzoneGame(gameDesc) ? 174 : 103, _rgb565),
 																					 _lockKey(13),
+																					 _loadedCursors(16),
 																					 _fov(kPi2),
 																					 _angleX(0),
 																					 _angleY(-kPi2),
@@ -806,6 +808,11 @@ void PhoenixVREngine::setCursorDefault(int idx, const Common::String &path) {
 		warning("only 2 default cursors supported, got %d", idx);
 }
 
+void PhoenixVREngine::setCursorDefault(int idx, int cursorIdx) {
+	auto &desc = _loadedCursors[cursorIdx];
+	setCursorDefault(idx, desc.path);
+}
+
 void PhoenixVREngine::setCursor(const Common::String &path, const Common::String &wname, int idx) {
 	debug("setCursor %s %s:%d", path.c_str(), wname.c_str(), idx);
 	auto warp = _script->getWarp(wname);
@@ -1183,6 +1190,8 @@ Graphics::ManagedSurface *PhoenixVREngine::loadSurface(const Common::String &pat
 		dec.reset(new Image::PCXDecoder);
 	} else if (filename.hasSuffixIgnoreCase(".gif")) {
 		dec.reset(new Image::GIFDecoder);
+	} else if (filename.hasSuffixIgnoreCase(".cur")) {
+		dec.reset(new Image::TGADecoder);
 	} else {
 		warning("can't find decoder for %s", filename.c_str());
 		return nullptr;
@@ -1201,19 +1210,30 @@ Graphics::ManagedSurface *PhoenixVREngine::loadSurface(const Common::String &pat
 	return s;
 }
 
-Graphics::ManagedSurface *PhoenixVREngine::loadCursor(const Common::String &path) {
+Graphics::ManagedSurface *PhoenixVREngine::loadCursor(const Common::String &path, int w, int h) {
 	if (path.empty())
 		return nullptr;
 	auto it = _cursorCache.find(path);
 	if (it != _cursorCache.end())
 		return it->_value;
-	auto s = loadSurface(path);
+	Common::ScopedPtr<Graphics::ManagedSurface> s(loadSurface(path));
 	if (!s) {
 		warning("can't load cursor from %s", path.c_str());
 		return nullptr;
 	}
-	_cursorCache[path] = s;
-	return s;
+	if (w > 0 && h > 0) {
+		s.reset(s->scale(w, h, true));
+	}
+	_cursorCache[path] = s.get();
+	return s.release();
+}
+
+void PhoenixVREngine::loadCursor(int idx, const Common::String &path, int w, int h) {
+	debug("load cursor %d %s %d %d", idx, path.c_str(), w, h);
+	auto &desc = _loadedCursors[idx];
+	desc.path = path;
+	_cursorCache.erase(path);
+	loadCursor(desc.path, w, h);
 }
 
 void PhoenixVREngine::scheduleTest(int idx) {
diff --git a/engines/phoenixvr/phoenixvr.h b/engines/phoenixvr/phoenixvr.h
index 78722442dc1..62912bce683 100644
--- a/engines/phoenixvr/phoenixvr.h
+++ b/engines/phoenixvr/phoenixvr.h
@@ -130,7 +130,9 @@ public:
 	void setNextScript(const Common::String &path);
 	bool goToWarp(const Common::String &warp, bool savePrev = false);
 	void returnToWarp();
+	void loadCursor(int idx, const Common::String &path, int w, int h);
 	void setCursorDefault(int idx, const Common::String &path);
+	void setCursorDefault(int idx, int cursorIdx);
 	void setCursor(const Common::String &path, const Common::String &warp, int idx);
 	void hideCursor(const Common::String &warp, int idx);
 
@@ -249,7 +251,7 @@ private:
 	Common::SeekableReadStream *tryOpen(const Common::Path &name, Common::String *origName);
 
 	Graphics::ManagedSurface *loadSurface(const Common::String &path);
-	Graphics::ManagedSurface *loadCursor(const Common::String &path);
+	Graphics::ManagedSurface *loadCursor(const Common::String &path, int w = 0, int h = 0);
 	PointF currentVRPos() const {
 		return RectF::transform(_angleX.angle(), _angleY.angle(), _fov);
 	}
@@ -318,6 +320,11 @@ private:
 
 	Common::ScopedPtr<RegionSet> _regSet;
 
+	struct PreloadedCursor {
+		Common::String path;
+	};
+	Common::Array<PreloadedCursor> _loadedCursors;
+
 	Common::HashMap<Common::String, Graphics::ManagedSurface *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _cursorCache;
 
 	Common::Array<Common::Array<Common::String>> _cursors;
diff --git a/engines/phoenixvr/script_v2.cpp b/engines/phoenixvr/script_v2.cpp
index 3165ef4a762..958a3923ca3 100644
--- a/engines/phoenixvr/script_v2.cpp
+++ b/engines/phoenixvr/script_v2.cpp
@@ -108,11 +108,12 @@ void ScriptV2::parseLine(const Common::String &line, uint lineno) {
 			if (!p.atEnd())
 				error("garbage at the end of the assignment, line %d", lineno);
 			command.reset(new SetVariable(name, Common::move(value)));
-		} else {
+		} else if (p.maybe('(')) {
 			auto args = p.readStringList();
 			p.expect(')');
 			command = createV2Command(name, args, lineno);
-		}
+		} else
+			error("invalid syntax at %d", lineno);
 
 		auto &commands = _currentTest->scope.commands;
 		if (command)




More information about the Scummvm-git-logs mailing list