[Scummvm-git-logs] scummvm master -> 50969e049ac8068a3548fca79ad0d5befdf50f99

sev- noreply at scummvm.org
Sat Jul 18 21:03:35 UTC 2026


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

Summary:
527e90be32 DIRECTOR: Add detection for Jablko, Hackers DPK, Lingo Expo (FM Towns)
50969e049a DIRECTOR: Implement GetPath and HitMap xlibs for Night Light


Commit: 527e90be321ee2b359e3eceb7bce2de1b74d149b
    https://github.com/scummvm/scummvm/commit/527e90be321ee2b359e3eceb7bce2de1b74d149b
Author: eientei95 (einstein95 at users.noreply.github.com)
Date: 2026-07-18T23:03:29+02:00

Commit Message:
DIRECTOR: Add detection for Jablko, Hackers DPK, Lingo Expo (FM Towns)

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 08c4daf8bcd..c85233abfca 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -935,6 +935,7 @@ static const PlainGameDescriptor directorGames[] = {
 	{ "limit0inici",		"Límit 0 Inici" },
 
 	// Czech titles
+	{ "jablko",				"Jablko" },
 	{ "nemcina",			"Německá gramatika cvičebnice" },           // German grammar workbook
 
 	// Danish titles
@@ -1947,6 +1948,7 @@ static const PlainGameDescriptor directorGames[] = {
 	{ "hoaddams2",			"Hollywood Online: Addams Family Values" },
 	{ "hoangus",			"Hollywood Online: Angus" },
 	{ "hodolores",			"Hollywood Online: Dolores Claiborne" },
+	{ "hohackers",			"Hollywood Online: Hackers" },
 	{ "horobroy",			"Hollywood Online: Rob Roy: Legend of the Mist" },
 	{ "hostargate",			"Hollywood Online: Stargate" },
 	{ "hothenet",			"Hollywood Online: The Net" },
@@ -2811,6 +2813,12 @@ static const DirectorGameDescription gameDescriptions[] = {
 	MACGAME1("hodolores", "", "Dolores Claiborne Interactive", "r:7f443f2e63fd497a9ad85b10dc880a91", 1475680, 313),
 	WINGAME1("hodolores", "", "DOLRES.EXE", "65d06b5fef155a2473434571aff5bc29", 1671516, 313),
 
+	// Found at https://web.archive.org/web/19970501051247/http://www.hollywood.com/movies/hackers/director/index.html
+	// Hackers 1.7
+	MACGAME1("hohackers", "v1.7", "Hackers Interactive Kit", "r:7f443f2e63fd497a9ad85b10dc880a91", 1828685, 313),
+	// HackersPC 1.7
+	WINGAME1("hohackers", "v1.7", "HACKERS.EXE", "t:7d5b476cbf998c72474f81d6601bf238", 2189900, 300),
+
 	MACGAME1("horobroy", "", "Rob Roy Interactive Kit",	"rt:3adfc08d711bcfa8701afa7f545ef971", 1801032, 313),
 	WINGAME1("horobroy", "", "ROBROY.EXE",				"t:78cecfc070a663eedb6118a2a19c0034",  2047746, 313),
 
@@ -2952,6 +2960,8 @@ static const DirectorGameDescription gameDescriptions[] = {
 
 	MACGAME1("lingoexpo", "", "Navigator", "4dacf23c1bb75093a882c4fd89dededb", 38, 400),
 	WINGAME1("lingoexpo", "", "NAVIGATR.DIR", "c7bfbd3e1224a1e82a8a98e8edb9f959", 1335612, 400),
+	// Found on Towns System Software v2.1 L51
+	FMTGAME1("lingoexpo", "", "NAVIGATR.DIR", "c47ebf627b9d038ca9a5bd9b9a6c9651", 1335612, 400),
 
 	MACGAME1_l("lvi", "Nº1", "xn--LVI8Mo-ka28a", "7f443f2e63fd497a9ad85b10dc880a91", 384206, Common::FR_FRA, 310),
 	WINGAME1_l("lvi", "Nº1", "LVI.EXE", "65d06b5fef155a2473434571aff5bc29", 634203, Common::FR_FRA, 310),
@@ -3847,13 +3857,13 @@ static const DirectorGameDescription gameDescriptions[] = {
 
 	// Demo is from covermount of PC Guide (UK) Feb 1997
 	MACGAME1("bht", "",   "A Brief History Of Time 16megs", "8719de9c083aca942fc0e5c0a127b6dc", 486726, 404),
-	MACGAME1_l("bht", "", "Eine kurze Geschichte der Zeit", "8719de9c083aca942fc0e5c0a127b6dc", 486726, Common::DE_DEU, 404),
 	WINGAME2("bht", "",		"BHT.EXE",		"d2f280d5ec355b252ffdadbe19332893", 692381,
 							"PLAY_BHT.DIR", "663acc406405b6fcac7e2d89230c4cc2", 8398, 404),
-	WINDEMO2("bht", "Demo", "BHT.EXE",		"d2f280d5ec355b252ffdadbe19332893", 692381,
-							"PLAY_BHT.DIR", "9417d6ebe716c963a4424a1611aaa2ca", 3522, 404),
+	MACGAME1_l("bht", "", "Eine kurze Geschichte der Zeit", "8719de9c083aca942fc0e5c0a127b6dc", 486726, Common::DE_DEU, 404),
 	WINGAME2_l("bht", "",	"BHT.EXE",		"d2f280d5ec355b252ffdadbe19332893", 692381,
 							"PLAY_BHT.DIR", "a11fe20066d9e84423df6c3ef4966636", 69068, Common::DE_DEU, 404),
+	WINDEMO2("bht", "Demo", "BHT.EXE",		"d2f280d5ec355b252ffdadbe19332893", 692381,
+							"PLAY_BHT.DIR", "9417d6ebe716c963a4424a1611aaa2ca", 3522, 404),
 
 	WINDEMO2t("baseballhits", "Demo", "BASEBALL.EXE", "008d1690b0b764f8a75e4f4c6542b739", 3569928,
 									  "WINDEMO.DIR", "e8e44e90e25c0efe74ddb77df545db1e", 2958900, 400),
@@ -5609,25 +5619,25 @@ static const DirectorGameDescription gameDescriptions[] = {
 	MACDEMO1("openingnight", "Demo", "MECC Demos/Opening Night", "rt:0051fe5d492ce27807a1c43798118e05",  285282, 404),
 	WINDEMO1("openingnight", "Demo", "MECCDEMO/OPN.EXE",		 "t:2b31be5e4d57745e1c6859cfff485209", 14762491, 404),
 
-	MACGAME2("operafatal", "",	 "OPERA FATAL",		 "f5033f237ad1b1639fc46d01a82ac380", 285310,
+	MACGAME2("operafatal", "",	 "OPERA FATAL",		 "r:f5033f237ad1b1639fc46d01a82ac380", 285310,
 								 "Opera/SPRINT.Dxr", "3e86f01eeac5fa3349c5177378997a7f", 694912, 400),
 	WINGAME2("operafatal", "",	 "OPERA.EXE",		 "t:1708e82d4b297a1e74fe683f86521dc4", 697739,
 								 "OPERA/SPRINT.DXR", "d:9415903c9259c67731d24a70d9d9e1e0", 694758, 400),
 	MACGAME2_l("operafatal", "", "OPERA FATAL",		 "r:f5033f237ad1b1639fc46d01a82ac380", 285310,
 								 "Opera/SPRINT.Dxr", "f:7055a0b9f2385f9b78f55494c8a010d4", 479518, Common::IT_ITA, 404),
 	// From bugreport #13466, Italian hybrid Mac/Win CD
-	MACGAME2_l("operafatal", "Hybrid release", "OPERA FATAL",		 "f5033f237ad1b1639fc46d01a82ac380", 285310,
-											 "Opera/SPRINT.Dxr", "26c83c0cac1d40e91487e3a142d29733", 479390, Common::IT_ITA, 404),
-	WINGAME2_l("operafatal", "",	 "OPERA.EXE",		 "t:1708e82d4b297a1e74fe683f86521dc4", 697739,
-								 "OPERA/SPRINT.DXR", "d:26c83c0cac1d40e91487e3a142d29733", 479390, Common::IT_ITA, 400),
-
-	MACDEMO1("orgotto", "Demo", "ORGOTTO",	   "r:0c7bbb4b24823e5ab871cb4c1d6f3710", 484095, 404),
-	WINDEMO1("orgotto", "Demo", "ORGOTTO.EXE", "t:46a65dad38808f407277b933b707289e", 760137, 404),
+	MACGAME2_l("operafatal", "Hybrid release", "OPERA FATAL",	   "f5033f237ad1b1639fc46d01a82ac380", 285310,
+											   "Opera/SPRINT.Dxr", "26c83c0cac1d40e91487e3a142d29733", 479390, Common::IT_ITA, 404),
+	WINGAME2_l("operafatal", "",			   "OPERA.EXE",		   "t:1708e82d4b297a1e74fe683f86521dc4", 697739,
+											   "OPERA/SPRINT.DXR", "d:26c83c0cac1d40e91487e3a142d29733", 479390, Common::IT_ITA, 400),
 
 	// Full game is not Director
 	// Found on Oregon Trail (Mac/Win)
-	MACDEMO1("oregontrail2", "Demo", "MECC Demos/Oregon Trail II", "rt:3290f9ad726052f93d2ecb0f9f771fd8", 482582, 404),
-	WINDEMO1("oregontrail2", "Demo", "MECCDEMO/OREGONII.EXE",	   "t:7a24eed984ba064d5f354ebb2bf7fc70", 10288091, 404),
+	MACDEMO1("oregontrail2", "Demo", "Oregon Trail II", "rt:3290f9ad726052f93d2ecb0f9f771fd8", 482582, 404),
+	WINDEMO1("oregontrail2", "Demo", "OREGONII.EXE", "t:7a24eed984ba064d5f354ebb2bf7fc70", 10288091, 404),
+
+	MACDEMO1("orgotto", "Demo", "ORGOTTO",	   "r:0c7bbb4b24823e5ab871cb4c1d6f3710", 484095, 404),
+	WINDEMO1("orgotto", "Demo", "ORGOTTO.EXE", "t:46a65dad38808f407277b933b707289e", 760137, 404),
 
 	// Found on PC Gamer (US) demo discs #1,3,4,6
 	// V10 found on Czech Super Hry III (FMI)
@@ -7457,6 +7467,7 @@ static const DirectorGameDescription gameDescriptions[] = {
 	WINGAME2("megapuzzlepack", "", "PUZPCK.EXE", "t:0519d6692a747a3595e5a40ecbf42783", 932385,
 								   "BOX1A.Dxr",	 "f:21c4e3829aa31a76e4d50b3c2e4d55de", 408342, 501),
 
+
 	MACGAME1f_l("microphonefiend", "8", "MF8/Microphone Fiend8", "tr:b2229850cb4e8ccb977c2f7c25650d6c", 719785, Common::JA_JPN, 501, GF_DESKTOP|GF_640x480),
 	MACGAME1f_l("microphonefiend", "16", "MF16/Microphone Fiend16", "tr:f2cb0ca9bce3a7fad18ba9f7c8c9f400", 117830, Common::JA_JPN, 501, GF_DESKTOP|GF_640x480),
 
@@ -7626,11 +7637,12 @@ static const DirectorGameDescription gameDescriptions[] = {
 	// All versions require installation to extract executable
 	MACGAME1("nine", "", "The Last Resort",		"r:957d819f99e30d54f68824ebe3d5d4ae",  730504, 500),
 	// European release
-	WINGAME2("nine", "", "nine_95.exe",			"t:9ad7cf866f886d30da20f1f0bceae082", 1555823,
-						 "LR_DATA/LR_MENU.DIR", "f:2bf898b9439c33ea03d5edfbdd3e4b99", 7094072, 501),
+	// SETUP32/_SETUP.1, InstallShield v3
+	WINGAME2f("nine", "", "nine_95.exe",			"t:9ad7cf866f886d30da20f1f0bceae082", 1555823,
+						 "LR_DATA/LR_MENU.DIR", "f:2bf898b9439c33ea03d5edfbdd3e4b99", 7094072, 501, GF_640x480),
 	// USA release
-	WINGAME2("nine", "", "NINE.EXE",			"t:9ad7cf866f886d30da20f1f0bceae082", 1554473,
-						 "LR_DATA/LR_MENU.DIR", "f:511b38690e3a358df4f9b2ffbd9fc727", 7076132, 501),
+	WINGAME2f("nine", "", "NINE.EXE",			"t:9ad7cf866f886d30da20f1f0bceae082", 1554473,
+						 "LR_DATA/LR_MENU.DIR", "f:511b38690e3a358df4f9b2ffbd9fc727", 7076132, 501, GF_640x480),
 
 	WINGAME2_l("norgesjakten", "Windows 95", "DATA/STARTW95.EXE", "t:5f330f89a31a02dd9ce8c1c62828e73d", 1412717,
 											 "LOGOS.DXR",		  "f:03374db319b1eb2d1a6de1c0913b6c33",   43466, Common::NB_NOR, 501),
@@ -9624,6 +9636,11 @@ static const DirectorGameDescription gameDescriptions[] = {
 	MACGAME1("intvlives", "", "Intellivision Lives!", "rt:81dedcc0cf0bfb62bc83b9da140387e7",  118022, 702),
 	WINGAME1("intvlives", "", "Inty_Lives.exe",		  "t:494733c3a5311ae6f465d5d2a3fed173",  2725946, 702),
 
+	// Found on Chip 1999-12
+	// Run from Jablko.exe (not Director) which checks that the screen is at least 800x600x16
+	// Later uses GLU32 to run Zobraz.dll which checks that Jablko.exe is running
+	WINGAME1("jablko", "", "Jablko_99.exe", "t:648446f880e8334fdd60597c45ea2fdc", 1085982, 700),
+
 	// 1999 Re-Release
 	// Original version is D4
 	MACGAME2("jewels1", "", "Jewels of the Oracle", "rt:16c2ecaec18295224eee09850d66f7f3", 109106,


Commit: 50969e049ac8068a3548fca79ad0d5befdf50f99
    https://github.com/scummvm/scummvm/commit/50969e049ac8068a3548fca79ad0d5befdf50f99
Author: eientei95 (einstein95 at users.noreply.github.com)
Date: 2026-07-18T23:03:29+02:00

Commit Message:
DIRECTOR: Implement GetPath and HitMap xlibs for Night Light

Changed paths:
  A engines/director/lingo/xlibs/g/getpath.cpp
  A engines/director/lingo/xlibs/g/getpath.h
    engines/director/lingo/lingo-object.cpp
    engines/director/lingo/xlibs/h/hitmap.cpp
    engines/director/lingo/xlibs/h/hitmap.h
    engines/director/module.mk


diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 92002ac9bfa..f54fb268dca 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -75,6 +75,7 @@
 #include "director/lingo/xlibs/f/fsutil.h"
 #include "director/lingo/xlibs/f/flushmousexfcn.h"
 #include "director/lingo/xlibs/g/genutils.h"
+#include "director/lingo/xlibs/g/getpath.h"
 #include "director/lingo/xlibs/g/getscreenrectsxfcn.h"
 #include "director/lingo/xlibs/g/getscreensizexfcn.h"
 #include "director/lingo/xlibs/g/getsoundinlevel.h"
@@ -316,6 +317,7 @@ static const struct XLibProto {
 	XLIBDEF(GLU32Xtra,			kXtraObj,					500),	// D5
 	XLIBDEF(GenUtilsXObj,		kXObj,			400),	// D4
 	XLIBDEF(GetDirXtra,			kXtraObj,					500),	// D5
+	XLIBDEF(GetPathXObj,			kXObj,					400),	// D4
 	XLIBDEF(GetScreenRectsXFCN,	kXObj,			300),	// D3
 	XLIBDEF(GetScreenSizeXFCN,	kXObj,			300),	// D3
 	XLIBDEF(GetSoundInLevelXObj,kXObj,			400),	// D4
@@ -323,7 +325,7 @@ static const struct XLibProto {
 	XLIBDEF(GetUInfoXObj,			kXObj,					400),	// D4
 	XLIBDEF(GpidXObj,			kXObj,			400),	// D4
 	XLIBDEF(HenryXObj,			kXObj,			400),	// D4
-	XLIBDEF(HitMap,				kXObj,			400),	// D4
+	XLIBDEF(HitMapXObj,			kXObj,			400),	// D4
 	XLIBDEF(IniXObj,			kXObj,			400),	// D4
 	XLIBDEF(InstObjXObj,		kXObj,			400),	// D4
 	XLIBDEF(IsCD,				kXObj,			300),	// D3
diff --git a/engines/director/lingo/xlibs/g/getpath.cpp b/engines/director/lingo/xlibs/g/getpath.cpp
new file mode 100644
index 00000000000..3e605759a9e
--- /dev/null
+++ b/engines/director/lingo/xlibs/g/getpath.cpp
@@ -0,0 +1,143 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "common/fs.h"
+#include "common/system.h"
+#include "common/config-manager.h"
+
+#include "director/director.h"
+#include "director/lingo/lingo-object.h"
+#include "director/lingo/lingo-utils.h"
+#include "director/lingo/lingo.h"
+#include "director/lingo/xlibs/g/getpath.h"
+
+/**************************************************
+ *
+ * USED IN:
+ * Night Light
+ *
+ **************************************************/
+
+/*
+-- External Factory. 30JAN95
+--GetPath
+S       mName                           --
+I       mStatus                         --
+I       mNew                            --
+SS      mGetPath, hDirName              --
+SS      mGetCDPath, hCDFileName         --
+X       mDispose                        --
+ */
+
+namespace Director {
+
+const char *GetPathXObj::xlibName = "GetPath";
+const XlibFileDesc GetPathXObj::fileNames[] = {
+	{"GETPATH", nullptr},
+	{nullptr, nullptr},
+};
+
+static MethodProto xlibMethods[] = {
+	{"name",	  GetPathXObj::m_name,		0, 0, 400},
+	{"status",	  GetPathXObj::m_status,	0, 0, 400},
+	{"new",		  GetPathXObj::m_new,		0, 0, 400},
+	{"getPath",	  GetPathXObj::m_getPath,	1, 1, 400},
+	{"getCDPath", GetPathXObj::m_getCDPath, 1, 1, 400},
+	{"dispose",	  GetPathXObj::m_dispose,	0, 0, 400},
+	{nullptr,	  nullptr,					0, 0, 0  }
+};
+
+static BuiltinProto xlibBuiltins[] = {
+	{nullptr, nullptr, 0, 0, 0, VOIDSYM}};
+
+GetPathXObject::GetPathXObject(ObjectType ObjectType) : Object<GetPathXObject>("GetPath") {
+	_objType = ObjectType;
+}
+
+void GetPathXObj::open(ObjectType type, const Common::Path &path) {
+	GetPathXObject::initMethods(xlibMethods);
+	GetPathXObject *xobj = new GetPathXObject(type);
+	if (type == kXtraObj) {
+		g_lingo->_openXtras.push_back(xlibName);
+		g_lingo->_openXtraObjects.push_back(xobj);
+	}
+	g_lingo->exposeXObject(xlibName, xobj);
+	g_lingo->initBuiltIns(xlibBuiltins);
+}
+
+void GetPathXObj::close(ObjectType type) {
+	GetPathXObject::cleanupMethods();
+	g_lingo->_globalvars[xlibName] = Datum();
+}
+
+void GetPathXObj::m_new(int nargs) {
+	GetPathXObject *me = static_cast<GetPathXObject *>(g_lingo->_state->me.u.obj);
+
+	debugC(5, kDebugLingoExec, "GetPathXObj::m_new");
+
+	// Return the object instance
+	g_lingo->push(g_lingo->_state->me);
+}
+
+void GetPathXObj::m_name(int nargs) {
+	debugC(5, kDebugLingoExec, "GetPathXObj::m_name");
+
+	// Return "GetPath" string
+	g_lingo->push(Datum("GetPath"));
+}
+
+void GetPathXObj::m_status(int nargs) {
+	// Return no error
+	g_lingo->push(Datum(0));
+}
+
+
+void GetPathXObj::m_getPath(int nargs) {
+	// Pop the subfolder argument
+	Common::String subpath = g_lingo->pop().asString();
+
+	debugC(5, kDebugLingoExec, "GetPathXObj::m_getPath: subfolder='%s'", subpath.c_str());
+
+	Common::String fullPath = ""; // savePrefix()  + subpath;
+
+	debugC(5, kDebugLingoExec, "GetPathXObj::m_getPath: Returning path '%s'", fullPath.c_str());
+
+	// Return the full path
+	g_lingo->push(Datum(fullPath));
+}
+
+
+void GetPathXObj::m_getCDPath(int nargs) {
+	// Pop the subpath argument
+	Common::String subpath = g_lingo->pop().asString();
+
+	debugC(5, kDebugLingoExec, "GetPathXObj::m_getCDPath: subfolder='%s'", subpath.c_str());
+
+	// Returns the drive letter of the CD-ROM drive
+	g_lingo->push(Datum("E"));
+}
+
+void GetPathXObj::m_dispose(int nargs) {
+	debugC(5, kDebugLingoExec, "GetPathXObj::m_dispose");
+}
+
+} // namespace Director
diff --git a/engines/director/lingo/xlibs/g/getpath.h b/engines/director/lingo/xlibs/g/getpath.h
new file mode 100644
index 00000000000..570f8e07159
--- /dev/null
+++ b/engines/director/lingo/xlibs/g/getpath.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DIRECTOR_LINGO_XLIBS_GETPATH_H
+#define DIRECTOR_LINGO_XLIBS_GETPATH_H
+
+namespace Director {
+
+class GetPathXObject : public Object<GetPathXObject> {
+public:
+	GetPathXObject(ObjectType objType);
+};
+
+namespace GetPathXObj {
+
+extern const char *xlibName;
+extern const XlibFileDesc fileNames[];
+
+void open(ObjectType type, const Common::Path &path);
+void close(ObjectType type);
+
+void m_name(int nargs);
+void m_status(int nargs);
+void m_new(int nargs);
+void m_getPath(int nargs);
+void m_getCDPath(int nargs);
+void m_dispose(int nargs);
+
+} // End of namespace GetPathXObj
+
+} // End of namespace Director
+
+#endif
diff --git a/engines/director/lingo/xlibs/h/hitmap.cpp b/engines/director/lingo/xlibs/h/hitmap.cpp
index 91db150b913..20d1a1e9a64 100644
--- a/engines/director/lingo/xlibs/h/hitmap.cpp
+++ b/engines/director/lingo/xlibs/h/hitmap.cpp
@@ -22,81 +22,240 @@
 /*************************************
  *
  * USED IN:
- * Night Light (Mac)
+ * Night Light
  *
  *************************************/
 /*
 -- HitMap XObject
-ISIII		mNew, path, xOffset, yOffset, scale	-- path, xOffset, yOffset, scale
-X			mDispose
-III		mWhere, x, y						-- Return GWorld Index
+ISIII   mNew, path, xOffset, yOffset, scale -- path, xOffset, yOffset, scale
+X       mDispose
+III     mWhere, x, y                        -- Return GWorld Index
 
 -- Hitmap Scale Factor 27.JUL.94
 hitmap
-S		mName         										--Returns the XObject name (hitmap)
-S		mGetSys         									--Returns Windows System Directory Path(hitmap)
-ISIII	mNew, hitBitMapfile, hitmaposx, hitmaposy, factor   --Creates new instance of XObject
-III	mWhere, xpos, ypos									--coordinate position
-X		mDispose												--Dispose of memory allocation
+S       mName                                               --Returns the XObject name (hitmap)
+S       mGetSys                                             --Returns Windows System Directory Path(hitmap)
+ISIII   mNew, hitBitMapfile, hitmaposx, hitmaposy, factor   --Creates new instance of XObject
+III     mWhere, xpos, ypos                                  --coordinate position
+X       mDispose                                            --Dispose of memory allocation
 */
 
+#include "common/file.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+#include "image/bmp.h"
+
 #include "director/director.h"
-#include "director/lingo/lingo.h"
 #include "director/lingo/lingo-object.h"
+#include "director/lingo/lingo-utils.h"
+#include "director/lingo/lingo.h"
 #include "director/lingo/xlibs/h/hitmap.h"
 
-
 namespace Director {
 
-const char *const HitMap::xlibName = "HitMap";
-const XlibFileDesc HitMap::fileNames[] = {
-	{ "HitMap",		nullptr },
-	{ "maskXobj",	nullptr },
-	{ nullptr,		nullptr },
+const char *const HitMapXObj::xlibName = "HitMap";
+const XlibFileDesc HitMapXObj::fileNames[] = {
+	{"HitMap", nullptr},
+	{"maskXobj", nullptr},
+	{nullptr, nullptr},
 };
 
 static const MethodProto xlibMethods[] = {
-	{ "New",	HitMap::m_new,		4,	4,	400 },	// D4
-	{ "Where",	HitMap::m_where,	2,	2,	400 },	// D4
-	{ nullptr, nullptr, 0, 0, 0 }
+	{"new",		HitMapXObj::m_new,	   4, 4, 400},  // D4
+	{"where",	HitMapXObj::m_where,   2, 2, 400},  // D4
+	{"name",	HitMapXObj::m_name,	   0, 0, 400},  // D4
+	{"getSys",  HitMapXObj::m_getSys,  0, 0, 400},  // D4
+	{"dispose", HitMapXObj::m_dispose, 0, 0, 400},  // D4
+	{nullptr,	nullptr,			   0, 0, 0  }
 };
 
-void HitMap::open(ObjectType type, const Common::Path &path) {
+void HitMapXObj::open(ObjectType type, const Common::Path &path) {
 	if (type == kXObj) {
-		HitMapObject::initMethods(xlibMethods);
-		HitMapObject *xobj = new HitMapObject(kXObj);
+		HitMapXObject::initMethods(xlibMethods);
+		HitMapXObject *xobj = new HitMapXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
 	}
 }
 
-void HitMap::close(ObjectType type) {
+void HitMapXObj::close(ObjectType type) {
 	if (type == kXObj) {
-		HitMapObject::cleanupMethods();
+		HitMapXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
 	}
 }
 
+HitMapXObject::HitMapXObject(ObjectType objType) : Object<HitMapXObject>("HitMap") {
+	_objType = objType;
+	_width = 0;
+	_height = 0;
+	_xOffset = 0;
+	_yOffset = 0;
+	_scale = 1;
+}
 
-HitMapObject::HitMapObject(ObjectType ObjectType) :Object<HitMapObject>("HitMap") {
-	_objType = ObjectType;
+HitMapXObject::~HitMapXObject() {
+	_bitmapData.clear();
 }
 
-void HitMap::m_new(int nargs) {
-	// Common::String hitBitMapfile = g_lingo->pop().asString();
-	// int hitmaposx = g_lingo->pop().asInt();
-	// int hitmaposy = g_lingo->pop().asInt();
-	// int factor = g_lingo->pop().asInt();
-	g_lingo->printSTUBWithArglist("HitMap::m_new", nargs);
-	g_lingo->dropStack(nargs);
+void HitMapXObj::m_new(int nargs) {
+	HitMapXObject *me = static_cast<HitMapXObject *>(g_lingo->_state->me.u.obj);
+
+	// Pop arguments in reverse order (factor, yOffset, xOffset, filename)
+	int scale = g_lingo->pop().asInt();
+	int yOffset = g_lingo->pop().asInt();
+	int xOffset = g_lingo->pop().asInt();
+	Common::String fileName = g_lingo->pop().asString();
+
+	debugC(5, kDebugLingoExec, "HitMapXObj::m_new: file='%s', x=%d, y=%d, scale=%d",
+		   fileName.c_str(), xOffset, yOffset, scale);
+
+	// Store parameters
+	me->_xOffset = xOffset;
+	me->_yOffset = yOffset;
+	me->_scale = scale > 0 ? scale : 1;
+
+	// Try to open the file
+	Common::File bmpFile;
+	if (!bmpFile.open(findPath(fileName))) {
+		warning("HitMapXObj::m_new: Could not open file '%s'", fileName.c_str());
+		g_lingo->push(g_lingo->_state->me);
+		return;
+	}
+
+	// Load bitmap using BMP decoder
+	Image::BitmapDecoder bmpDecoder;
+	if (!bmpDecoder.loadStream(bmpFile)) {
+		warning("HitMapXObj::m_new: Could not decode bitmap '%s'", fileName.c_str());
+		bmpFile.close();
+		g_lingo->push(g_lingo->_state->me);
+		return;
+	}
+
+	// Get the decoded surface
+	const Graphics::Surface *surface = bmpDecoder.getSurface();
+	if (!surface) {
+		warning("HitMapXObj::m_new: No surface data in bitmap '%s'", fileName.c_str());
+		bmpFile.close();
+		g_lingo->push(g_lingo->_state->me);
+		return;
+	}
+
+	// Store dimensions
+	me->_width = surface->w;
+	me->_height = surface->h;
+
+	debugC(5, kDebugLingoExec, "HitMapXObj::m_new: Loaded bitmap %dx%d", me->_width, me->_height);
+
+	// Allocate hitmap data buffer
+	uint32 dataSize = me->_width * me->_height;
+	me->_bitmapData.resize(dataSize);
+
+	// Convert surface to byte array for hitmap lookup
+	const byte *srcPixels = (const byte *)surface->getPixels();
+
+	if (surface->format.bytesPerPixel == 1) {
+		// Direct copy for 8-bit indexed color
+		memcpy(me->_bitmapData.data(), srcPixels, dataSize);
+	} else {
+		// Extract first byte for higher bit depths
+		for (uint32 i = 0; i < dataSize; i++) {
+			me->_bitmapData[i] = srcPixels[i * surface->format.bytesPerPixel];
+		}
+	}
+
+	bmpFile.close();
+
+	// Return the object instance
 	g_lingo->push(g_lingo->_state->me);
 }
 
-void HitMap::m_where(int nargs) {
-	// int xpos = g_lingo->pop().asInt();
-	// int ypos = g_lingo->pop().asInt();
-	g_lingo->printSTUBWithArglist("HitMap::m_where", nargs);
-	g_lingo->dropStack(nargs);
-	g_lingo->push(Datum(0));
+void HitMapXObj::m_where(int nargs) {
+	HitMapXObject *me = static_cast<HitMapXObject *>(g_lingo->_state->me.u.obj);
+
+	// Pop arguments (y, then x due to stack order)
+	int screenY = g_lingo->pop().asInt();
+	int screenX = g_lingo->pop().asInt();
+
+	// Check if hitmap was loaded
+	if (me->_bitmapData.empty() || me->_width == 0 || me->_height == 0) {
+		warning("HitMapXObj::m_where: No hitmap data loaded");
+		g_lingo->push(Datum(-1));
+		return;
+	}
+
+	// Calculate scaled dimensions for bounds checking
+	int scaledWidth = me->_width * me->_scale;
+	int scaledHeight = me->_height * me->_scale;
+
+	// Check if coordinates are out of bounds
+	if (screenX < 0 || screenX >= scaledWidth ||
+		screenY < 0 || screenY >= scaledHeight) {
+		debugC(5, kDebugLingoExec, "HitMapXObj::m_where: Out of bounds (%d, %d)", screenX, screenY);
+		g_lingo->push(Datum(-1));
+		return;
+	}
+
+	// Adjust coordinates by the object's position offset
+	int adjustedX = screenX - me->_xOffset;
+	int adjustedY = screenY - me->_yOffset;
+
+	// Convert from screen coordinates to bitmap coordinates
+	int bitmapX = adjustedX / me->_scale;
+	int bitmapY = adjustedY / me->_scale;
+
+	// Additional bounds check after adjustment
+	if (bitmapX < 0 || bitmapX >= (int)me->_width ||
+		bitmapY < 0 || bitmapY >= (int)me->_height) {
+		debugC(5, kDebugLingoExec, "HitMapXObj::m_where: Adjusted coords out of bounds (%d, %d)", bitmapX, bitmapY);
+		g_lingo->push(Datum(-1));
+		return;
+	}
+
+	// Calculate offset into bitmap data
+	// BMP format is bottom-up, so invert Y coordinate
+	// Formula: x * width + (width - y - 1)
+	uint32 offset = bitmapX * me->_width + (me->_width - bitmapY - 1);
+
+	// Final safety check
+	if (offset >= me->_bitmapData.size()) {
+		warning("HitMapXObj::m_where: Calculated offset %d exceeds data size %d", offset, me->_bitmapData.size());
+		g_lingo->push(Datum(-1));
+		return;
+	}
+
+	// Get and return the hitmap value
+	byte value = me->_bitmapData[offset];
+	debugC(5, kDebugLingoExec, "HitMapXObj::m_where: (%d, %d) -> bitmap(%d, %d) = %d",
+		   screenX, screenY, bitmapX, bitmapY, value);
+
+	g_lingo->push(Datum((int)value));
+}
+
+void HitMapXObj::m_name(int nargs) {
+	g_lingo->push(Datum("hitmap_name"));
+}
+
+void HitMapXObj::m_getSys(int nargs) {
+	// Get current working directory
+	Common::String sysDir = g_director->getCurrentPath();
+
+	if (sysDir.empty()) {
+		// Original Windows implementation returned "Aw_Shishi" on failure
+		g_lingo->push(Datum("Aw_Shishi"));
+	} else {
+		g_lingo->push(Datum(sysDir));
+	}
+}
+
+void HitMapXObj::m_dispose(int nargs) {
+	HitMapXObject *me = static_cast<HitMapXObject *>(g_lingo->_state->me.u.obj);
+
+	// Clear bitmap data
+	me->_bitmapData.clear();
+	me->_width = 0;
+	me->_height = 0;
+
+	debugC(5, kDebugLingoExec, "HitMapXObj::m_dispose: Freed hitmap data");
 }
 
 } // End of namespace Director
diff --git a/engines/director/lingo/xlibs/h/hitmap.h b/engines/director/lingo/xlibs/h/hitmap.h
index b1ac31681ca..e3c4409bf93 100644
--- a/engines/director/lingo/xlibs/h/hitmap.h
+++ b/engines/director/lingo/xlibs/h/hitmap.h
@@ -24,12 +24,21 @@
 
 namespace Director {
 
-class HitMapObject : public Object<HitMapObject> {
+class HitMapXObject : public Object<HitMapXObject> {
 public:
-    HitMapObject(ObjectType objType);
+	HitMapXObject(ObjectType objType);
+	~HitMapXObject() override;
+
+	// Hitmap data storage
+	Common::Array<byte> _bitmapData;
+	uint32 _width;
+	uint32 _height;
+	int32 _xOffset;
+	int32 _yOffset;
+	uint32 _scale;
 };
 
-namespace HitMap {
+namespace HitMapXObj {
 
 extern const char *const xlibName;
 extern const XlibFileDesc fileNames[];
@@ -39,8 +48,11 @@ void close(ObjectType type);
 
 void m_new(int nargs);
 void m_where(int nargs);
+void m_name(int nargs);
+void m_getSys(int nargs);
+void m_dispose(int nargs);
 
-} // End of namespace HitMap
+} // End of namespace HitMapXObj
 
 } // End of namespace Director
 
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 817740df20b..7778af7f3b6 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -106,6 +106,7 @@ MODULE_OBJS = \
 	lingo/xlibs/f/fplayxobj.o \
 	lingo/xlibs/f/fsutil.o \
 	lingo/xlibs/g/genutils.o \
+	lingo/xlibs/g/getpath.o \
 	lingo/xlibs/g/getscreenrectsxfcn.o \
 	lingo/xlibs/g/getscreensizexfcn.o \
 	lingo/xlibs/g/getsoundinlevel.o \




More information about the Scummvm-git-logs mailing list