aboutsummaryrefslogtreecommitdiff
path: root/engines/pegasus
diff options
context:
space:
mode:
Diffstat (limited to 'engines/pegasus')
-rwxr-xr-xengines/pegasus/Game_Shell/CGameState.cpp252
-rwxr-xr-xengines/pegasus/Game_Shell/CGameState.h107
-rwxr-xr-xengines/pegasus/Game_Shell/CInventory.cpp175
-rwxr-xr-xengines/pegasus/Game_Shell/CInventory.h80
-rwxr-xr-xengines/pegasus/Game_Shell/CItem.cpp111
-rwxr-xr-xengines/pegasus/Game_Shell/CItem.h84
-rwxr-xr-xengines/pegasus/Game_Shell/CItemList.cpp79
-rwxr-xr-xengines/pegasus/Game_Shell/CItemList.h60
-rwxr-xr-xengines/pegasus/Game_Shell/Headers/Game_Shell_Constants.h81
-rwxr-xr-xengines/pegasus/Game_Shell/Headers/Game_Shell_Types.h80
-rwxr-xr-xengines/pegasus/MMShell/Base_Classes/MMAction.h40
-rwxr-xr-xengines/pegasus/MMShell/Base_Classes/MMFunctionPtr.cpp48
-rwxr-xr-xengines/pegasus/MMShell/Base_Classes/MMFunctionPtr.h51
-rwxr-xr-xengines/pegasus/MMShell/MMConstants.h63
-rwxr-xr-xengines/pegasus/MMShell/MMTypes.h103
-rwxr-xr-xengines/pegasus/MMShell/Notification/MMNotification.cpp99
-rwxr-xr-xengines/pegasus/MMShell/Notification/MMNotification.h85
-rwxr-xr-xengines/pegasus/MMShell/Notification/MMNotificationManager.cpp61
-rwxr-xr-xengines/pegasus/MMShell/Notification/MMNotificationManager.h58
-rwxr-xr-xengines/pegasus/MMShell/Notification/MMNotificationReceiver.cpp46
-rwxr-xr-xengines/pegasus/MMShell/Notification/MMNotificationReceiver.h53
-rwxr-xr-xengines/pegasus/MMShell/Sounds/MMSound.cpp126
-rwxr-xr-xengines/pegasus/MMShell/Sounds/MMSound.h84
-rwxr-xr-xengines/pegasus/MMShell/Utilities/MMIDObject.h68
-rwxr-xr-xengines/pegasus/MMShell/Utilities/MMResourceFile.cpp106
-rwxr-xr-xengines/pegasus/MMShell/Utilities/MMResourceFile.h75
-rwxr-xr-xengines/pegasus/MMShell/Utilities/MMTimeValue.cpp60
-rwxr-xr-xengines/pegasus/MMShell/Utilities/MMTimeValue.h52
-rwxr-xr-xengines/pegasus/MMShell/Utilities/MMUtilities.cpp63
-rwxr-xr-xengines/pegasus/MMShell/Utilities/MMUtilities.h43
-rw-r--r--engines/pegasus/console.cpp38
-rw-r--r--engines/pegasus/console.h46
-rw-r--r--engines/pegasus/credits.cpp174
-rw-r--r--engines/pegasus/detection.cpp118
-rw-r--r--engines/pegasus/graphics.cpp250
-rw-r--r--engines/pegasus/graphics.h83
-rw-r--r--engines/pegasus/menu.cpp207
-rw-r--r--engines/pegasus/module.mk32
-rw-r--r--engines/pegasus/overview.cpp142
-rw-r--r--engines/pegasus/pegasus.cpp392
-rw-r--r--engines/pegasus/pegasus.h271
-rw-r--r--engines/pegasus/video.cpp288
-rw-r--r--engines/pegasus/video.h92
43 files changed, 4626 insertions, 0 deletions
diff --git a/engines/pegasus/Game_Shell/CGameState.cpp b/engines/pegasus/Game_Shell/CGameState.cpp
new file mode 100755
index 0000000000..70a55450dd
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CGameState.cpp
@@ -0,0 +1,252 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/error.h"
+#include "common/stream.h"
+
+#include "pegasus/Game_Shell/CGameState.h"
+#include "pegasus/Game_Shell/Headers/Game_Shell_Constants.h"
+
+namespace Pegasus {
+
+tNeighborhoodID CGameState::gCurrentNeighborhood = kNoNeighborhoodID;
+tRoomID CGameState::gCurrentRoom = kNoRoomID;
+tDirectionConstant CGameState::gCurrentDirection = kNoDirection;
+tNeighborhoodID CGameState::gNextNeighborhoodID = kNoNeighborhoodID;
+tRoomID CGameState::gNextRoomID = kNoRoomID;
+tDirectionConstant CGameState::gNextDirection = kNoDirection;
+tNeighborhoodID CGameState::gLastNeighborhood = kNoNeighborhoodID;
+tRoomID CGameState::gLastRoom = kNoRoomID;
+tDirectionConstant CGameState::gLastDirection = kNoDirection;
+tRoomID CGameState::gOpenDoorRoom = kNoRoomID;
+tDirectionConstant CGameState::gOpenDoorDirection = kNoDirection;
+
+Common::Error CGameState::WriteGameState(Common::WriteStream *stream) {
+ stream->writeUint16BE(gCurrentNeighborhood);
+ stream->writeUint16BE(gCurrentRoom);
+ stream->writeByte(gCurrentDirection);
+ stream->writeUint16BE(gNextNeighborhoodID);
+ stream->writeUint16BE(gNextRoomID);
+ stream->writeByte(gNextDirection);
+ stream->writeUint16BE(gLastNeighborhood);
+ stream->writeUint16BE(gLastRoom);
+ stream->writeUint16BE(gOpenDoorRoom);
+ stream->writeByte(gOpenDoorDirection);
+
+ if (stream->err())
+ return Common::kWritingFailed;
+
+ return Common::kNoError;
+}
+
+Common::Error CGameState::ReadGameState(Common::ReadStream *stream) {
+ gCurrentNeighborhood = stream->readUint16BE();
+ gCurrentRoom = stream->readUint16BE();
+ gCurrentDirection = stream->readByte();
+ gNextNeighborhoodID = stream->readUint16BE();
+ gNextRoomID = stream->readUint16BE();
+ gNextDirection = stream->readByte();
+ gLastNeighborhood = stream->readUint16BE();
+ gLastRoom = stream->readUint16BE();
+ gOpenDoorRoom = stream->readUint16BE();
+ gOpenDoorDirection = stream->readByte();
+
+ if (stream->err())
+ return Common::kReadingFailed;
+
+ return Common::kNoError;
+}
+
+void CGameState::ResetGameState() {
+ gCurrentNeighborhood = kNoNeighborhoodID;
+ gCurrentRoom = kNoRoomID;
+ gCurrentDirection = kNoDirection;
+ gNextNeighborhoodID = kNoNeighborhoodID;
+ gNextRoomID = kNoRoomID;
+ gNextDirection = kNoDirection;
+ gLastNeighborhood = kNoNeighborhoodID;
+ gLastRoom = kNoRoomID;
+ gLastDirection = kNoDirection;
+ gOpenDoorRoom = kNoRoomID;
+ gOpenDoorDirection = kNoDirection;
+}
+
+void CGameState::GetCurrentLocation(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction) {
+ neighborhood = gCurrentNeighborhood;
+ room = gCurrentRoom;
+ direction = gCurrentDirection;
+}
+
+void CGameState::SetCurrentLocation(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction) {
+ gLastNeighborhood = gCurrentNeighborhood;
+ gLastRoom = gCurrentRoom;
+ gLastDirection = gCurrentDirection;
+ gCurrentNeighborhood = neighborhood;
+ gCurrentRoom = room;
+ gCurrentDirection = direction;
+}
+
+tNeighborhoodID CGameState::GetCurrentNeighborhood() {
+ return gCurrentNeighborhood;
+}
+
+void CGameState::SetCurrentNeighborhood(const tNeighborhoodID neighborhood) {
+ gLastNeighborhood = gCurrentNeighborhood;
+ gCurrentNeighborhood = neighborhood;
+}
+
+tRoomID CGameState::GetCurrentRoom() {
+ return gCurrentRoom;
+}
+
+void CGameState::SetCurrentRoom(const tRoomID room) {
+ gLastRoom = gCurrentRoom;
+ gCurrentRoom = room;
+}
+
+tDirectionConstant CGameState::GetCurrentDirection() {
+ return gCurrentDirection;
+}
+
+void CGameState::SetCurrentDirection(const tDirectionConstant direction) {
+ gLastDirection = gCurrentDirection;
+ gCurrentDirection = direction;
+}
+
+tRoomViewID CGameState::GetCurrentRoomAndView() {
+ return MakeRoomView(gCurrentRoom, gCurrentDirection);
+}
+
+void CGameState::GetNextLocation(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction) {
+ neighborhood = gNextNeighborhoodID;
+ room = gNextRoomID;
+ direction = gNextDirection;
+}
+
+void CGameState::SetNextLocation(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction) {
+ gNextNeighborhoodID = neighborhood;
+ gNextRoomID = room;
+ gNextDirection = direction;
+}
+
+tNeighborhoodID CGameState::GetNextNeighborhood() {
+ return gNextNeighborhoodID;
+}
+
+void CGameState::SetNextNeighborhood(const tNeighborhoodID neighborhood) {
+ gNextNeighborhoodID = neighborhood;
+}
+
+tRoomID CGameState::GetNextRoom() {
+ return gNextRoomID;
+}
+
+void CGameState::SetNextRoom(const tRoomID room) {
+ gNextRoomID = room;
+}
+
+tDirectionConstant CGameState::GetNextDirection() {
+ return gNextDirection;
+}
+
+void CGameState::SetNextDirection(const tDirectionConstant direction) {
+ gNextDirection = direction;
+}
+
+void CGameState::GetLastLocation(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction) {
+ neighborhood = gCurrentNeighborhood;
+ room = gCurrentRoom;
+ direction = gCurrentDirection;
+}
+
+void CGameState::SetLastLocation(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction) {
+ gCurrentNeighborhood = neighborhood;
+ gCurrentRoom = room;
+ gCurrentDirection = direction;
+}
+
+tNeighborhoodID CGameState::GetLastNeighborhood() {
+ return gLastNeighborhood;
+}
+
+void CGameState::SetLastNeighborhood(const tNeighborhoodID neighborhood) {
+ gLastNeighborhood = neighborhood;
+}
+
+tRoomID CGameState::GetLastRoom() {
+ return gLastRoom;
+}
+
+void CGameState::SetLastRoom(const tRoomID room) {
+ gLastRoom = room;
+}
+
+tDirectionConstant CGameState::GetLastDirection() {
+ return gLastDirection;
+}
+
+void CGameState::SetLastDirection(const tDirectionConstant direction) {
+ gLastDirection = direction;
+}
+
+tRoomViewID CGameState::GetLastRoomAndView() {
+ return MakeRoomView(gLastRoom, gLastDirection);
+}
+
+void CGameState::GetOpenDoorLocation(tRoomID &room, tDirectionConstant &direction) {
+ room = gOpenDoorRoom;
+ direction = gOpenDoorDirection;
+}
+
+void CGameState::SetOpenDoorLocation(const tRoomID room, const tDirectionConstant direction) {
+ gOpenDoorRoom = room;
+ gOpenDoorDirection = direction;
+}
+
+tRoomID CGameState::GetOpenDoorRoom() {
+ return gOpenDoorRoom;
+}
+
+void CGameState::SetOpenDoorRoom(const tRoomID room) {
+ gOpenDoorRoom = room;
+}
+
+tDirectionConstant CGameState::GetOpenDoorDirection() {
+ return gOpenDoorDirection;
+}
+
+void CGameState::SetOpenDoorDirection(const tDirectionConstant direction) {
+ gOpenDoorDirection = direction;
+}
+
+tRoomViewID CGameState::GetDoorOpenRoomAndView() {
+ return MakeRoomView(gOpenDoorRoom, gOpenDoorDirection);
+}
+
+bool CGameState::IsCurrentDoorOpen() {
+ return gOpenDoorRoom == gCurrentRoom && gOpenDoorDirection == gCurrentDirection;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/Game_Shell/CGameState.h b/engines/pegasus/Game_Shell/CGameState.h
new file mode 100755
index 0000000000..b7ad71bb50
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CGameState.h
@@ -0,0 +1,107 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_GAMESHELL_CGAMESTATE_H
+#define PEGASUS_GAMESHELL_CGAMESTATE_H
+
+#include "pegasus/Game_Shell/Headers/Game_Shell_Types.h"
+
+namespace Common {
+ class Error;
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class CGameState {
+public:
+ static Common::Error WriteGameState(Common::WriteStream *stream);
+ static Common::Error ReadGameState(Common::ReadStream *stream);
+
+ static void ResetGameState();
+
+ static void GetCurrentLocation(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction);
+ static void SetCurrentLocation(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction);
+
+ static tNeighborhoodID GetCurrentNeighborhood();
+ static void SetCurrentNeighborhood(const tNeighborhoodID neighborhood);
+ static tRoomID GetCurrentRoom();
+ static void SetCurrentRoom(const tRoomID room);
+ static tDirectionConstant GetCurrentDirection();
+ static void SetCurrentDirection(const tDirectionConstant direction);
+
+ static tRoomViewID GetCurrentRoomAndView();
+
+ static void GetNextLocation(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction);
+ static void SetNextLocation(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction);
+
+ static tNeighborhoodID GetNextNeighborhood();
+ static void SetNextNeighborhood(const tNeighborhoodID neighborhood);
+ static tRoomID GetNextRoom();
+ static void SetNextRoom(const tRoomID room);
+ static tDirectionConstant GetNextDirection();
+ static void SetNextDirection(const tDirectionConstant direction);
+
+ static void GetLastLocation(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction);
+ static void SetLastLocation(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction);
+
+ static tNeighborhoodID GetLastNeighborhood();
+ static void SetLastNeighborhood(const tNeighborhoodID neighborhood);
+ static tRoomID GetLastRoom();
+ static void SetLastRoom(const tRoomID room);
+ static tDirectionConstant GetLastDirection();
+ static void SetLastDirection(const tDirectionConstant direction);
+
+ static tRoomViewID GetLastRoomAndView();
+
+ static void GetOpenDoorLocation(tRoomID &room, tDirectionConstant &direction);
+ static void SetOpenDoorLocation(const tRoomID room, const tDirectionConstant direction);
+ static tRoomID GetOpenDoorRoom();
+ static void SetOpenDoorRoom(const tRoomID room);
+ static tDirectionConstant GetOpenDoorDirection();
+ static void SetOpenDoorDirection(const tDirectionConstant direction);
+
+ static tRoomViewID GetDoorOpenRoomAndView();
+
+ static bool IsCurrentDoorOpen();
+
+protected:
+ static tNeighborhoodID gCurrentNeighborhood;
+ static tRoomID gCurrentRoom;
+ static tDirectionConstant gCurrentDirection;
+ static tNeighborhoodID gNextNeighborhoodID;
+ static tRoomID gNextRoomID;
+ static tDirectionConstant gNextDirection;
+ static tNeighborhoodID gLastNeighborhood;
+ static tRoomID gLastRoom;
+ static tDirectionConstant gLastDirection;
+ static tRoomID gOpenDoorRoom;
+ static tDirectionConstant gOpenDoorDirection;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/Game_Shell/CInventory.cpp b/engines/pegasus/Game_Shell/CInventory.cpp
new file mode 100755
index 0000000000..3747beda89
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CInventory.cpp
@@ -0,0 +1,175 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/Game_Shell/CItem.h"
+#include "pegasus/Game_Shell/CInventory.h"
+#include "pegasus/Game_Shell/Headers/Game_Shell_Constants.h"
+
+namespace Pegasus {
+
+CInventory::CInventory() {
+ fWeightLimit = 100;
+ fOwnerID = kNoActorID;
+ fReferenceCount = 0;
+}
+
+CInventory::~CInventory() {
+}
+
+void CInventory::SetWeightLimit(tWeightType limit) {
+ fWeightLimit = limit;
+ // *** What to do if the new weight limit is greater than the current weight?
+}
+
+tWeightType CInventory::GetWeight() {
+ tWeightType result = 0;
+
+ for (CItemIterator it = fInventoryList.begin(); it != fInventoryList.end(); it++)
+ result += (*it)->GetItemWeight();
+
+ return result;
+}
+
+// If the item already belongs, just return kInventoryOK.
+tInventoryResult CInventory::AddItem(CItem *item) {
+ if (ItemInInventory(item))
+ return kInventoryOK;
+
+ if (GetWeight() + item->GetItemWeight() > fWeightLimit)
+ return kTooMuchWeight;
+
+ fInventoryList.push_back(item);
+ item->SetItemOwner(fOwnerID);
+
+ ++fReferenceCount;
+ return kInventoryOK;
+}
+
+tInventoryResult CInventory::RemoveItem(CItem *item) {
+ for (CItemIterator it = fInventoryList.begin(); it != fInventoryList.end(); it++) {
+ if (*it == item) {
+ fInventoryList.erase(it);
+ item->SetItemOwner(kNoActorID);
+
+ ++fReferenceCount;
+ return kInventoryOK;
+ }
+ }
+
+ return kItemNotInInventory;
+}
+
+tInventoryResult CInventory::RemoveItem(tItemID id) {
+ CItem *item = FindItemByID(id);
+
+ if (item) {
+ fInventoryList.remove(item);
+ item->SetItemOwner(kNoActorID);
+
+ ++fReferenceCount;
+ return kInventoryOK;
+ }
+
+ return kItemNotInInventory;
+}
+
+void CInventory::RemoveAllItems() {
+ fInventoryList.clear();
+ ++fReferenceCount;
+}
+
+bool CInventory::ItemInInventory(CItem *item) {
+ for (CItemIterator it = fInventoryList.begin(); it != fInventoryList.end(); it++)
+ if (*it == item)
+ return true;
+
+ return false;
+}
+
+bool CInventory::ItemInInventory(tItemID id) {
+ return FindItemByID(id) != NULL;
+}
+
+CItem *CInventory::GetItemAt(int32 index) {
+ int32 i = 0;
+ for (CItemIterator it = fInventoryList.begin(); it != fInventoryList.end(); it++, i++)
+ if (i == index)
+ return *it;
+
+ return 0;
+}
+
+tItemID CInventory::GetItemIDAt(int32 index) {
+ CItem *item = GetItemAt(index);
+
+ if (item)
+ return item->GetObjectID();
+
+ return kNoItemID;
+}
+
+CItem *CInventory::FindItemByID(tItemID id) {
+ return fInventoryList.FindItemByID(id);
+}
+
+// Return -1 if not found.
+
+int32 CInventory::FindIndexOf(CItem *item) {
+ uint32 i = 0;
+ for (CItemIterator it = fInventoryList.begin(); it != fInventoryList.end(); it++, i++)
+ if (*it == item)
+ return i;
+
+ return -1;
+}
+
+// Return -1 if not found.
+
+int32 CInventory::FindIndexOf(tItemID id) {
+ uint32 i = 0;
+ for (CItemIterator it = fInventoryList.begin(); it != fInventoryList.end(); it++, i++)
+ if ((*it)->GetObjectID() == id)
+ return i;
+
+ return -1;
+}
+
+tWeightType CInventory::GetWeightLimit() {
+ return fWeightLimit;
+}
+
+int32 CInventory::GetNumItems() {
+ return fInventoryList.size();
+}
+
+void CInventory::SetOwnerID(const tActorID id) {
+ fOwnerID = id;
+}
+
+tActorID CInventory::GetOwnerID() const {
+ return fOwnerID;
+}
+
+} // End of namespae Pegasus
diff --git a/engines/pegasus/Game_Shell/CInventory.h b/engines/pegasus/Game_Shell/CInventory.h
new file mode 100755
index 0000000000..57ea1c99cc
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CInventory.h
@@ -0,0 +1,80 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_GAMESHELL_CINVENTORY_H
+#define PEGASUS_GAMESHELL_CINVENTORY_H
+
+#include "pegasus/Game_Shell/CItemList.h"
+#include "pegasus/Game_Shell/Headers/Game_Shell_Types.h"
+
+namespace Pegasus {
+
+class CItem;
+
+// Inventories have a "current item". This item is the default item the player can
+// use. In a text adventure system, the current item would be "it", as in
+// "Hit the troll with it," where "it" would refer to some weapon which is the current
+// item. In a graphic adventure, the current item would be the item the user selects
+// to use with the mouse or other pointing device.
+
+class CInventory {
+public:
+ CInventory();
+ virtual ~CInventory();
+
+ tWeightType GetWeightLimit();
+ void SetWeightLimit(tWeightType limit);
+ tWeightType GetWeight();
+
+ virtual tInventoryResult AddItem(CItem *item);
+ virtual tInventoryResult RemoveItem(CItem *item);
+ virtual tInventoryResult RemoveItem(tItemID id);
+ virtual bool ItemInInventory(CItem *item);
+ virtual bool ItemInInventory(tItemID id);
+ virtual CItem *GetItemAt(int32 index);
+ virtual tItemID GetItemIDAt(int32 index);
+ virtual CItem *FindItemByID(tItemID id);
+ virtual int32 FindIndexOf(CItem *item);
+ virtual int32 FindIndexOf(tItemID id);
+ int32 GetNumItems();
+ virtual void RemoveAllItems();
+
+ void SetOwnerID(const tActorID id);
+ tActorID GetOwnerID() const;
+
+ uint32 GetReferenceCount() { return fReferenceCount; }
+
+protected:
+ tWeightType fWeightLimit;
+ tActorID fOwnerID;
+ CItemList fInventoryList;
+
+private:
+ uint32 fReferenceCount;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/Game_Shell/CItem.cpp b/engines/pegasus/Game_Shell/CItem.cpp
new file mode 100755
index 0000000000..af0bff42e3
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CItem.cpp
@@ -0,0 +1,111 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/error.h"
+#include "common/stream.h"
+
+#include "pegasus/Game_Shell/CItem.h"
+#include "pegasus/Game_Shell/CItemList.h"
+#include "pegasus/Game_Shell/Headers/Game_Shell_Constants.h"
+
+namespace Pegasus {
+
+CItem::CItem(const tItemID id, const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction) : MMIDObject(id) {
+ fItemNeighborhood = neighborhood;
+ fItemRoom = room;
+ fItemDirection = direction;
+ fItemWeight = 1;
+ fItemOwnerID = kNoActorID;
+ fItemState = 0;
+
+ gAllItems.push_back(this);
+}
+
+CItem::~CItem() {
+}
+
+Common::Error CItem::WriteToStream(Common::WriteStream *stream) {
+ stream->writeUint16BE(fItemNeighborhood);
+ stream->writeUint16BE(fItemRoom);
+ stream->writeByte(fItemDirection);
+ stream->writeUint16BE(fItemOwnerID);
+ stream->writeUint16BE(fItemState);
+
+ if (stream->err())
+ return Common::kWritingFailed;
+
+ return Common::kNoError;
+}
+
+Common::Error CItem::ReadFromStream(Common::ReadStream *stream) {
+ fItemNeighborhood = stream->readUint16BE();
+ fItemRoom = stream->readUint16BE();
+ fItemDirection = stream->readByte();
+ fItemOwnerID = stream->readUint16BE();
+ fItemState = stream->readUint16BE();
+
+ if (stream->err())
+ return Common::kReadingFailed;
+
+ return Common::kNoError;
+}
+
+tActorID CItem::GetItemOwner() const {
+ return fItemOwnerID;
+}
+
+void CItem::SetItemOwner(const tActorID owner) {
+ fItemOwnerID = owner;
+}
+
+tWeightType CItem::GetItemWeight() {
+ return fItemWeight;
+}
+
+tItemState CItem::GetItemState() const {
+ return fItemState;
+}
+
+void CItem::SetItemState(const tItemState state) {
+ fItemState = state;
+}
+
+void CItem::GetItemRoom(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction) const {
+ neighborhood = fItemNeighborhood;
+ room = fItemRoom;
+ direction = fItemDirection;
+}
+
+void CItem::SetItemRoom(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction) {
+ fItemNeighborhood = neighborhood;
+ fItemRoom = room;
+ fItemDirection = direction;
+}
+
+tNeighborhoodID CItem::GetItemNeighborhood() const {
+ return fItemNeighborhood;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/Game_Shell/CItem.h b/engines/pegasus/Game_Shell/CItem.h
new file mode 100755
index 0000000000..cb0931c8bd
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CItem.h
@@ -0,0 +1,84 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_GAMESHELL_CITEM_H
+#define PEGASUS_GAMESHELL_CITEM_H
+
+#include "pegasus/MMShell/Utilities/MMIDObject.h"
+#include "pegasus/Game_Shell/Headers/Game_Shell_Types.h"
+
+namespace Common {
+ class Error;
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+/*
+
+ CItem is an object which can be picked up and carried around.
+ CItems have
+ a location
+ an ID.
+ weight
+ an owner (kNoActorID if no one is carrying the CItem)
+
+*/
+
+class CItem : public MMIDObject {
+public:
+ CItem(const tItemID id, const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction);
+ virtual ~CItem();
+
+ // WriteToStream writes everything EXCEPT the item's ID.
+ // It is assumed that the calling function will write and read the ID.
+ virtual Common::Error WriteToStream(Common::WriteStream *stream);
+ virtual Common::Error ReadFromStream(Common::ReadStream *stream);
+
+ virtual tActorID GetItemOwner() const;
+ virtual void SetItemOwner(const tActorID owner);
+
+ void GetItemRoom(tNeighborhoodID &neighborhood, tRoomID &room, tDirectionConstant &direction) const;
+ void SetItemRoom(const tNeighborhoodID neighborhood, const tRoomID room, const tDirectionConstant direction);
+ tNeighborhoodID GetItemNeighborhood() const;
+
+ virtual tWeightType GetItemWeight();
+
+ virtual void SetItemState(const tItemState state);
+ virtual tItemState GetItemState() const;
+
+protected:
+ tNeighborhoodID fItemNeighborhood;
+ tRoomID fItemRoom;
+ tDirectionConstant fItemDirection;
+ tActorID fItemOwnerID;
+ tWeightType fItemWeight;
+ tItemState fItemState;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/Game_Shell/CItemList.cpp b/engines/pegasus/Game_Shell/CItemList.cpp
new file mode 100755
index 0000000000..256a895797
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CItemList.cpp
@@ -0,0 +1,79 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/error.h"
+#include "common/stream.h"
+
+#include "engines/pegasus/Game_Shell/CItem.h"
+#include "engines/pegasus/Game_Shell/CItemList.h"
+
+namespace Pegasus {
+
+// TODO: Don't use global construction!
+CItemList gAllItems;
+
+CItemList::CItemList() {
+}
+
+CItemList::~CItemList() {
+}
+
+Common::Error CItemList::WriteToStream(Common::WriteStream *stream) {
+ stream->writeUint32BE(size());
+
+ for (CItemIterator it = begin(); it != end(); it++) {
+ stream->writeUint16BE((*it)->GetObjectID());
+ (*it)->WriteToStream(stream);
+ }
+
+ if (stream->err())
+ return Common::kWritingFailed;
+
+ return Common::kNoError;
+}
+
+Common::Error CItemList::ReadFromStream(Common::ReadStream *stream) {
+ uint32 itemCount = stream->readUint32BE();
+
+ for (uint32 i = 0; i < itemCount; i++) {
+ tItemID itemID = stream->readUint16BE();
+ gAllItems.FindItemByID(itemID)->ReadFromStream(stream);
+ }
+
+ if (stream->err())
+ return Common::kReadingFailed;
+
+ return Common::kNoError;
+}
+
+CItem *CItemList::FindItemByID(const tItemID id) {
+ for (CItemIterator it = begin(); it != end(); it++)
+ if ((*it)->GetObjectID() == id)
+ return *it;
+
+ return 0;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/Game_Shell/CItemList.h b/engines/pegasus/Game_Shell/CItemList.h
new file mode 100755
index 0000000000..75a34a0213
--- /dev/null
+++ b/engines/pegasus/Game_Shell/CItemList.h
@@ -0,0 +1,60 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_GAMESHELL_CITEMLIST_H
+#define PEGASUS_GAMESHELL_CITEMLIST_H
+
+#include "common/list.h"
+
+#include "pegasus/Game_Shell/Headers/Game_Shell_Types.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class CItem;
+
+class CItemList : public Common::List<CItem *> {
+public:
+ CItemList();
+ virtual ~CItemList();
+
+ virtual Common::Error WriteToStream(Common::WriteStream *stream);
+ virtual Common::Error ReadFromStream(Common::ReadStream *stream);
+
+ CItem *FindItemByID(const tItemID id);
+};
+
+typedef CItemList::iterator CItemIterator;
+
+// TODO: Don't use global construction!
+extern CItemList gAllItems;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/Game_Shell/Headers/Game_Shell_Constants.h b/engines/pegasus/Game_Shell/Headers/Game_Shell_Constants.h
new file mode 100755
index 0000000000..5d64629d95
--- /dev/null
+++ b/engines/pegasus/Game_Shell/Headers/Game_Shell_Constants.h
@@ -0,0 +1,81 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_GAMESHELL_HEADERS_GAMESHELLCONSTANTS
+#define PEGASUS_GAMESHELL_HEADERS_GAMESHELLCONSTANTS
+
+#include "engines/pegasus/MMShell/MMConstants.h"
+#include "engines/pegasus/Game_Shell/Headers/Game_Shell_Types.h"
+
+namespace Pegasus {
+
+const tGameID kGameIDNothing = -1;
+
+const tActorID kNoActorID = kGameIDNothing;
+const tActorID kPlayerID = 0;
+const tItemID kNoItemID = kGameIDNothing;
+const tRoomID kNoRoomID = kGameIDNothing;
+const tExtraID kNoExtraID = 0xFFFFFFFF;
+const tNeighborhoodID kNoNeighborhoodID = kGameIDNothing;
+const tAlternateID kNoAlternateID = 0;
+const tGameMenuCommand kMenuCmdNoCommand = 0;
+
+const tHotSpotActivationID kActivateHotSpotAlways = 0;
+const tHotSpotActivationID kActivateHotSpotNever = -1;
+
+const tItemState kNoItemState = -1;
+
+const tDirectionConstant kNoDirection = 0xFF;
+
+const tTurnDirection kNoTurn = 0xFF;
+const tTurnDirection kTurnLeft = 0;
+const tTurnDirection kTurnRight = 1;
+const tTurnDirection kTurnUp = 2;
+const tTurnDirection kTurnDown = 3;
+const tTurnDirection kMaxTurns = 4;
+
+const tGameMode kNoMode = -1;
+const tGameMode kModeNavigation = 0;
+const tGameMode kLastGameShellMode = kModeNavigation;
+
+const tCanMoveForwardReason kCanMoveForward = 0;
+const tCanMoveForwardReason kCantMoveBlocked = kCanMoveForward + 1;
+const tCanMoveForwardReason kCantMoveDoorClosed = kCantMoveBlocked + 1;
+const tCanMoveForwardReason kCantMoveDoorLocked = kCantMoveDoorClosed + 1;
+const tCanMoveForwardReason kCantMoveLastReason = kCantMoveDoorLocked;
+
+const tCanTurnReason kCanTurn = 0;
+const tCanTurnReason kCantTurnNoTurn = kCanTurn + 1;
+const tCanTurnReason kCantTurnLastReason = kCantTurnNoTurn;
+
+const tCanOpenDoorReason kCanOpenDoor = 0;
+const tCanOpenDoorReason kCantOpenNoDoor = kCanOpenDoor + 1;
+const tCanOpenDoorReason kCantOpenLocked = kCantOpenNoDoor + 1;
+const tCanOpenDoorReason kCantOpenAlreadyOpen = kCantOpenLocked + 1;
+const tCanOpenDoorReason kCantOpenLastReason = kCantOpenAlreadyOpen;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/Game_Shell/Headers/Game_Shell_Types.h b/engines/pegasus/Game_Shell/Headers/Game_Shell_Types.h
new file mode 100755
index 0000000000..923f7a72dd
--- /dev/null
+++ b/engines/pegasus/Game_Shell/Headers/Game_Shell_Types.h
@@ -0,0 +1,80 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_GAMESHELL_HEADERS_GAMESHELLTYPES
+#define PEGASUS_GAMESHELL_HEADERS_GAMESHELLTYPES
+
+#include "pegasus/MMShell/MMTypes.h"
+
+namespace Pegasus {
+
+typedef tMM16BitID tGameID;
+
+typedef tGameID tItemID;
+typedef tGameID tActorID;
+typedef tGameID tRoomID;
+typedef tGameID tNeighborhoodID;
+typedef tMM8BitU tAlternateID;
+typedef tMM8BitS tHotSpotActivationID;
+
+typedef tMM16BitS tWeightType;
+
+typedef tMM8BitU tDirectionConstant;
+typedef tMM8BitU tTurnDirection;
+
+// Meant to be room in low 16 bits and direction in high 16 bits.
+typedef tMM32BitU tRoomViewID;
+
+#define MakeRoomView(room, direction) (((tRoomViewID) (room)) | (((tRoomViewID) (direction)) << 16))
+
+typedef tMM32BitU tExtraID;
+
+typedef tMM16BitS tGameMode;
+
+typedef tMM16BitS tWeightType;
+
+typedef tMM16BitS tItemState;
+
+typedef tMM8BitS tDeathReason;
+
+typedef tMM32BitS tGameMenuCommand;
+
+typedef tMM32BitS tGameScoreType;
+
+typedef long tCanMoveForwardReason;
+
+typedef long tCanTurnReason;
+
+typedef long tCanOpenDoorReason;
+
+enum tInventoryResult {
+ kInventoryOK,
+ kTooMuchWeight,
+ kItemNotInInventory
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Base_Classes/MMAction.h b/engines/pegasus/MMShell/Base_Classes/MMAction.h
new file mode 100755
index 0000000000..8ad34a8d3e
--- /dev/null
+++ b/engines/pegasus/MMShell/Base_Classes/MMAction.h
@@ -0,0 +1,40 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_BASECLASSES_MMACTION_H
+#define PEGASUS_MMSHELL_BASECLASSES_MMACTION_H
+
+namespace Pegasus {
+
+class MMAction {
+public:
+ virtual ~MMAction() {}
+
+ virtual void InvokeAction() {}
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Base_Classes/MMFunctionPtr.cpp b/engines/pegasus/MMShell/Base_Classes/MMFunctionPtr.cpp
new file mode 100755
index 0000000000..9a2543db7b
--- /dev/null
+++ b/engines/pegasus/MMShell/Base_Classes/MMFunctionPtr.cpp
@@ -0,0 +1,48 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/MMShell/Base_Classes/MMFunctionPtr.h"
+
+namespace Pegasus {
+
+MMFunctionPtr::MMFunctionPtr() {
+ fTheFunction = 0;
+ fFunctionArg = 0;
+}
+
+MMFunctionPtr::~MMFunctionPtr() {
+}
+
+void MMFunctionPtr::SetFunctionPtr(tFunctionPtr theFunction, void *functionArg) {
+ fTheFunction = theFunction;
+ fFunctionArg = functionArg;
+}
+
+void MMFunctionPtr::CallFunction() {
+ if (fTheFunction != 0)
+ (*fTheFunction)(this, fFunctionArg);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/MMShell/Base_Classes/MMFunctionPtr.h b/engines/pegasus/MMShell/Base_Classes/MMFunctionPtr.h
new file mode 100755
index 0000000000..4aa18cac81
--- /dev/null
+++ b/engines/pegasus/MMShell/Base_Classes/MMFunctionPtr.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_BASECLASSES_MMFUNCTIONPTR_H
+#define PEGASUS_MMSHELL_BASECLASSES_MMFUNCTIONPTR_H
+
+namespace Pegasus {
+
+class MMFunctionPtr;
+
+typedef void (*tFunctionPtr)(MMFunctionPtr *theFunction, void *functionArg);
+
+class MMFunctionPtr {
+public:
+ MMFunctionPtr();
+ virtual ~MMFunctionPtr();
+
+ void SetFunctionPtr(tFunctionPtr theFunction, void *functionArg);
+
+protected:
+ void CallFunction();
+
+ tFunctionPtr fTheFunction;
+ void *fFunctionArg;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/MMConstants.h b/engines/pegasus/MMShell/MMConstants.h
new file mode 100755
index 0000000000..1b36c81cea
--- /dev/null
+++ b/engines/pegasus/MMShell/MMConstants.h
@@ -0,0 +1,63 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_MMCONSTANTS_H
+#define PEGASUS_MMSHELL_MMCONSTANTS_H
+
+#include "pegasus/MMShell/MMTypes.h"
+
+namespace Pegasus {
+
+const tDisplayElementID kNoDisplayElement = -1;
+const tDisplayElementID kHighestReservedElementID = -2;
+
+const tDisplayElementID kCursorID = kHighestReservedElementID;
+const tDisplayElementID kLoadScreenID = kCursorID - 1;
+
+const tDisplayOrder kMinAvailableOrder = 0;
+const tDisplayOrder kMaxAvailableOrder = 999998;
+const tDisplayOrder kLoadScreenOrder = 900000;
+const tDisplayOrder kCursorOrder = 1000000;
+
+const tHotSpotID kNoHotSpotID = -1;
+const tHotSpotFlags kNoHotSpotFlags = 0;
+const tHotSpotFlags kAllHotSpotFlags = ~kNoHotSpotFlags;
+
+const tNotificationFlags kNoNotificationFlags = 0;
+
+const tDisplayElementID kCurrentDragSpriteID = 1000;
+
+// TODO
+//const Fixed kFixed1 = 1 << 16;
+//const Fixed kFixedMinus1 = -1 << 16;
+
+const TimeScale kDefaultTimeScale = 600;
+
+// TODO
+//const RGBColor kWhiteRGB = {0xFFFF, 0xFFFF, 0xFFFF};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/MMTypes.h b/engines/pegasus/MMShell/MMTypes.h
new file mode 100755
index 0000000000..a4bc547e2a
--- /dev/null
+++ b/engines/pegasus/MMShell/MMTypes.h
@@ -0,0 +1,103 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_MMTYPES_H
+#define PEGASUS_MMSHELL_MMTYPES_H
+
+#include "common/scummsys.h"
+
+namespace Pegasus {
+
+// TODO: All of the "tMM"-prefixed defines should be replaced eventually
+// TODO: Probably all of these don't really need to be typedef'd...
+typedef int8 tMM8BitS;
+typedef uint8 tMM8BitU;
+
+typedef int16 tMM16BitS;
+typedef uint16 tMM16BitU;
+
+typedef int32 tMM32BitS;
+typedef uint32 tMM32BitU;
+
+typedef tMM8BitS tMM8BitID;
+typedef tMM16BitS tMM16BitID;
+typedef tMM32BitS tMM32BitID;
+
+typedef tMM8BitU tMM8BitFlags;
+typedef tMM16BitU tMM16BitFlags;
+typedef tMM32BitU tMM32BitFlags;
+
+typedef tMM32BitID tDisplayElementID;
+typedef tMM32BitS tDisplayOrder;
+
+typedef tMM16BitID tHotSpotID;
+typedef tMM32BitFlags tHotSpotFlags;
+
+typedef tMM8BitFlags tButtonState;
+typedef tMM32BitFlags tInputBits;
+
+typedef tMM8BitU tKeyMapType[16];
+typedef tMM8BitU tKeyType;
+typedef tMM8BitU tKeyMapIndexType;
+typedef tMM8BitU tKeyMapBitType;
+
+typedef tMM32BitID tNotificationID;
+typedef tMM32BitFlags tNotificationFlags;
+
+// Mac types.
+typedef tMM16BitS tResIDType;
+typedef tMM16BitS tCoordType;
+typedef tMM16BitS tQDCopyMode;
+typedef tMM16BitS tResItemCountType;
+
+enum tCopyMode {
+ kNoMask,
+ kUseClipArea,
+ kUseTransparency
+};
+
+enum tSlideDirection {
+ kSlideLeftMask = 1,
+ kSlideRightMask = kSlideLeftMask << 1,
+ kSlideUpMask = kSlideRightMask << 1 << 1,
+ kSlideDownMask = kSlideUpMask << 1,
+
+ kSlideHorizMask = kSlideLeftMask | kSlideRightMask,
+ kSlideVertMask = kSlideUpMask | kSlideDownMask,
+
+ kSlideUpLeftMask = kSlideLeftMask | kSlideUpMask,
+ kSlideUpRightMask = kSlideRightMask | kSlideUpMask,
+ kSlideDownLeftMask = kSlideLeftMask | kSlideDownMask,
+ kSlideDownRightMask = kSlideRightMask | kSlideDownMask
+};
+
+// ScummVM QuickTime/QuickDraw replacement types
+typedef uint TimeValue;
+typedef uint TimeScale;
+// TODO: Fixed and RGBColor
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Notification/MMNotification.cpp b/engines/pegasus/MMShell/Notification/MMNotification.cpp
new file mode 100755
index 0000000000..8b8d694358
--- /dev/null
+++ b/engines/pegasus/MMShell/Notification/MMNotification.cpp
@@ -0,0 +1,99 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/MMShell/MMConstants.h"
+#include "pegasus/MMShell/Notification/MMNotification.h"
+#include "pegasus/MMShell/Notification/MMNotificationManager.h"
+#include "pegasus/MMShell/Notification/MMNotificationReceiver.h"
+
+namespace Pegasus {
+
+typedef tReceiverList::iterator tReceiverIterator;
+
+MMNotification::MMNotification(const tNotificationID id, MMNotificationManager *owner) : MMIDObject(id) {
+ fOwner = owner;
+ fCurrentFlags = kNoNotificationFlags;
+ if (fOwner)
+ fOwner->AddNotification(this);
+}
+
+MMNotification::~MMNotification() {
+ for (tReceiverIterator it = fReceivers.begin(); it != fReceivers.end(); it++)
+ it->fReceiver->NewNotification(NULL);
+
+ if (fOwner)
+ fOwner->RemoveNotification(this);
+}
+
+// Selectively set or clear notificiation bits.
+// Wherever mask is 0, leave existing bits untouched.
+// Wherever mask is 1, set bit equivalent to flags.
+void MMNotification::NotifyMe(MMNotificationReceiver* receiver, tNotificationFlags flags, tNotificationFlags mask) {
+ for (tReceiverIterator it = fReceivers.begin(); it != fReceivers.end(); it++) {
+ if (it->fReceiver == receiver) {
+ it->fMask = (it->fMask & ~mask) | (flags & mask);
+ receiver->NewNotification(this);
+ return;
+ }
+ }
+
+ tReceiverEntry newEntry;
+ newEntry.fReceiver = receiver;
+ newEntry.fMask = flags;
+ fReceivers.push_back(newEntry);
+
+ receiver->NewNotification(this);
+}
+
+void MMNotification::CancelNotification(MMNotificationReceiver *receiver) {
+ for (tReceiverIterator it = fReceivers.begin(); it != fReceivers.end(); it++)
+ if (it->fReceiver == receiver)
+ fReceivers.erase(it);
+}
+
+void MMNotification::SetNotificationFlags(tNotificationFlags flags, tNotificationFlags mask) {
+ fCurrentFlags = (fCurrentFlags & ~mask) | flags;
+}
+
+void MMNotification::CheckReceivers() {
+ tNotificationFlags currentFlags = fCurrentFlags;
+ fCurrentFlags = kNoNotificationFlags;
+
+ for (tReceiverIterator it = fReceivers.begin(); it != fReceivers.end(); it++)
+ if (it->fMask & currentFlags)
+ it->fReceiver->ReceiveNotification(this, currentFlags);
+}
+
+// Receiver entries are equal if their receivers are equal.
+
+int operator==(const tReceiverEntry &entry1, const tReceiverEntry &entry2) {
+ return entry1.fReceiver == entry2.fReceiver;
+}
+
+int operator!=(const tReceiverEntry &entry1, const tReceiverEntry &entry2) {
+ return entry1.fReceiver != entry2.fReceiver;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/MMShell/Notification/MMNotification.h b/engines/pegasus/MMShell/Notification/MMNotification.h
new file mode 100755
index 0000000000..8ad7f733fd
--- /dev/null
+++ b/engines/pegasus/MMShell/Notification/MMNotification.h
@@ -0,0 +1,85 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_NOTIFICATION_MMNOTIFICATION_H
+#define PEGASUS_MMSHELL_NOTIFICATION_MMNOTIFICATION_H
+
+#include "common/list.h"
+
+#include "pegasus/MMShell/MMTypes.h"
+#include "pegasus/MMShell/Utilities/MMIDObject.h"
+
+namespace Pegasus {
+
+class MMNotificationManager;
+class MMNotificationReceiver;
+
+struct tReceiverEntry {
+ MMNotificationReceiver *fReceiver;
+ tNotificationFlags fMask;
+};
+
+int operator==(const tReceiverEntry &entry1, const tReceiverEntry &entry1);
+int operator!=(const tReceiverEntry &entry1, const tReceiverEntry &entry1);
+
+typedef Common::List<tReceiverEntry> tReceiverList;
+
+/*
+ A notification can have 32 flags associated with it, which can be user-defined.
+*/
+
+class MMNotification : public MMIDObject {
+friend class MMNotificationManager;
+
+public:
+ MMNotification(const tNotificationID id, MMNotificationManager *owner);
+ virtual ~MMNotification();
+
+ // NotifyMe will have this receiver notified when any of the specified notification
+ // flags are set.
+ // If there is already a notification set for this receiver, NotifyMe does a bitwise
+ // OR with the receiver's current notification flags.
+
+ // Can selectively set or clear notification bits by using the flags and mask argument.
+
+ void NotifyMe(MMNotificationReceiver*, tNotificationFlags flags, tNotificationFlags mask);
+ void CancelNotification(MMNotificationReceiver *receiver);
+
+ void SetNotificationFlags(tNotificationFlags flags, tNotificationFlags mask);
+ tNotificationFlags GetNotificationFlags() { return fCurrentFlags; }
+
+ void ClearNotificationFlags() { SetNotificationFlags(0, ~(tNotificationFlags)0); }
+
+protected:
+ void CheckReceivers();
+
+ MMNotificationManager *fOwner;
+ tReceiverList fReceivers;
+ tNotificationFlags fCurrentFlags;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Notification/MMNotificationManager.cpp b/engines/pegasus/MMShell/Notification/MMNotificationManager.cpp
new file mode 100755
index 0000000000..2a1f1bedd5
--- /dev/null
+++ b/engines/pegasus/MMShell/Notification/MMNotificationManager.cpp
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/MMShell/MMConstants.h"
+#include "pegasus/MMShell/Notification/MMNotificationManager.h"
+
+namespace Pegasus {
+
+typedef tNotificationList::iterator tNotificationIterator;
+
+MMNotificationManager::MMNotificationManager() {
+}
+
+MMNotificationManager::~MMNotificationManager() {
+ DetachNotifications();
+}
+
+void MMNotificationManager::AddNotification(MMNotification *notification) {
+ fNotifications.push_back(notification);
+}
+
+void MMNotificationManager::RemoveNotification(MMNotification *notification) {
+ for (tNotificationIterator it = fNotifications.begin(); it != fNotifications.end(); it++)
+ if ((*it) == notification)
+ fNotifications.erase(it);
+}
+
+void MMNotificationManager::DetachNotifications() {
+ for (tNotificationIterator it = fNotifications.begin(); it != fNotifications.end(); it++)
+ (*it)->fOwner = 0;
+}
+
+void MMNotificationManager::CheckNotifications() {
+ for (tNotificationIterator it = fNotifications.begin(); it != fNotifications.end(); it++)
+ if ((*it)->fCurrentFlags != kNoNotificationFlags)
+ (*it)->CheckReceivers();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/MMShell/Notification/MMNotificationManager.h b/engines/pegasus/MMShell/Notification/MMNotificationManager.h
new file mode 100755
index 0000000000..3df455fafd
--- /dev/null
+++ b/engines/pegasus/MMShell/Notification/MMNotificationManager.h
@@ -0,0 +1,58 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_NOTIFICATION_MMNOTIFICATIONMANAGER_H
+#define PEGASUS_MMSHELL_NOTIFICATION_MMNOTIFICATIONMANAGER_H
+
+#include "common/list.h"
+
+#include "pegasus/MMShell/Notification/MMNotificationReceiver.h"
+
+namespace Pegasus {
+
+class MMNotification;
+
+typedef Common::List<MMNotification *> tNotificationList;
+
+class MMNotificationManager : public MMNotificationReceiver {
+friend class MMNotification;
+
+public:
+ MMNotificationManager();
+ virtual ~MMNotificationManager();
+
+ void CheckNotifications();
+
+protected:
+ void AddNotification(MMNotification *notification);
+ void RemoveNotification(MMNotification *notification);
+ void DetachNotifications();
+
+ tNotificationList fNotifications;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Notification/MMNotificationReceiver.cpp b/engines/pegasus/MMShell/Notification/MMNotificationReceiver.cpp
new file mode 100755
index 0000000000..037cf185db
--- /dev/null
+++ b/engines/pegasus/MMShell/Notification/MMNotificationReceiver.cpp
@@ -0,0 +1,46 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/MMShell/Notification/MMNotificationReceiver.h"
+
+namespace Pegasus {
+
+MMNotificationReceiver::MMNotificationReceiver() {
+ fNotification = NULL;
+}
+
+MMNotificationReceiver::~MMNotificationReceiver() {
+ if (fNotification)
+ fNotification->CancelNotification(this);
+}
+
+void MMNotificationReceiver::ReceiveNotification(MMNotification *, const tNotificationFlags) {
+}
+
+void MMNotificationReceiver::NewNotification(MMNotification *notification) {
+ fNotification = notification;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/MMShell/Notification/MMNotificationReceiver.h b/engines/pegasus/MMShell/Notification/MMNotificationReceiver.h
new file mode 100755
index 0000000000..cb72047f37
--- /dev/null
+++ b/engines/pegasus/MMShell/Notification/MMNotificationReceiver.h
@@ -0,0 +1,53 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_NOTIFICATION_MMNOTIFICATIONRECEIVER_H
+#define PEGASUS_MMSHELL_NOTIFICATION_MMNOTIFICATIONRECEIVER_H
+
+#include "pegasus/MMShell/Notification/MMNotification.h"
+
+namespace Pegasus {
+
+class MMNotificationReceiver {
+friend class MMNotification;
+
+public:
+ MMNotificationReceiver();
+ virtual ~MMNotificationReceiver();
+
+protected:
+ // ReceiveNotification is called automatically whenever a notification that this
+ // receiver depends on has its flags set
+
+ virtual void ReceiveNotification(MMNotification *, const tNotificationFlags);
+ virtual void NewNotification(MMNotification *notification);
+
+private:
+ MMNotification *fNotification;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Sounds/MMSound.cpp b/engines/pegasus/MMShell/Sounds/MMSound.cpp
new file mode 100755
index 0000000000..23ac60bced
--- /dev/null
+++ b/engines/pegasus/MMShell/Sounds/MMSound.cpp
@@ -0,0 +1,126 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "audio/audiostream.h"
+#include "audio/decoders/aiff.h"
+#include "common/file.h"
+#include "common/system.h"
+
+#include "engines/pegasus/MMShell/Sounds/MMSound.h"
+
+namespace Pegasus {
+
+MMSound::MMSound() {
+ _aiffStream = 0;
+ _volume = 0xFF;
+}
+
+MMSound::~MMSound() {
+ DisposeSound();
+}
+
+void MMSound::DisposeSound() {
+ StopSound();
+ delete _aiffStream; _aiffStream = 0;
+}
+
+void MMSound::InitFromAIFFFile(const Common::String &fileName) {
+ Common::File *file = new Common::File();
+ if (!file->open(fileName)) {
+ delete file;
+ return;
+ }
+
+ _aiffStream = Audio::makeAIFFStream(file, DisposeAfterUse::YES);
+}
+
+#if 0
+// TODO!
+void MMSound::AttachFader(MMSoundFader *theFader) {
+ if (fTheFader)
+ fTheFader->AttachSound(NULL);
+
+ fTheFader = theFader;
+
+ if (fTheFader)
+ fTheFader->AttachSound(this);
+}
+#endif
+
+void MMSound::PlaySound() {
+ if (!SoundLoaded())
+ return;
+
+ StopSound();
+
+#if 0
+ // TODO!
+ if (fTheFader)
+ this->SetVolume(fTheFader->GetFaderValue());
+#endif
+
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, _aiffStream, -1, _volume, 0, DisposeAfterUse::NO);
+}
+
+void MMSound::LoopSound() {
+ if (!SoundLoaded())
+ return;
+
+ StopSound();
+
+ // Create a looping stream
+ Audio::AudioStream *loopStream = new Audio::LoopingAudioStream(_aiffStream, 0, DisposeAfterUse::NO);
+
+#if 0
+ // TODO!
+ // Assume that if there is a fader, we're going to fade the sound in.
+ if (fTheFader)
+ this->SetVolume(0);
+#endif
+
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopStream, -1, _volume, 0, DisposeAfterUse::YES);
+}
+
+void MMSound::StopSound(void) {
+ g_system->getMixer()->stopHandle(_handle);
+}
+
+void MMSound::SetVolume(const uint16 volume) {
+ // Clipping the volume to [0x00, 0xFF] instead of Apple's [0, 0x100]
+ // We store the volume in case SetVolume is called before the sound starts
+
+ _volume = (volume == 0x100) ? 0xFF : volume;
+ g_system->getMixer()->setChannelVolume(_handle, _volume);
+}
+
+bool MMSound::IsPlaying() {
+ return SoundLoaded() && g_system->getMixer()->isSoundHandleActive(_handle);
+}
+
+bool MMSound::SoundLoaded() const {
+ return _aiffStream != 0;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/MMShell/Sounds/MMSound.h b/engines/pegasus/MMShell/Sounds/MMSound.h
new file mode 100755
index 0000000000..bb5578266d
--- /dev/null
+++ b/engines/pegasus/MMShell/Sounds/MMSound.h
@@ -0,0 +1,84 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_SOUNDS_MMSOUND_H
+#define PEGASUS_MMSHELL_SOUNDS_MMSOUND_H
+
+#include "audio/mixer.h"
+#include "common/str.h"
+
+namespace Audio {
+ class AudioStream;
+ class RewindableAudioStream;
+}
+
+namespace Pegasus {
+
+// TODO!
+//class MMSoundFader;
+
+// Things you might want to do with sound:
+// Start it
+// Stop it
+// Loop it
+// Pause it
+// Set the volume
+// Set the pitch (rate)
+// Pan the sound
+// Change these settings dynamically over time
+
+class MMSound {
+public:
+ MMSound();
+ ~MMSound();
+
+ // We only have one access point here because we should
+ // only be opening an AIFF file from a file name. We're
+ // not using the resource fork string resources.
+ void InitFromAIFFFile(const Common::String &fileName);
+
+ void DisposeSound();
+ bool SoundLoaded() const;
+ void PlaySound();
+ void LoopSound();
+ void StopSound();
+ void SetVolume(const uint16 volume);
+ bool IsPlaying();
+
+ // TODO!
+ //void AttachFader(MMSoundFader*);
+
+protected:
+ Audio::RewindableAudioStream *_aiffStream;
+ Audio::SoundHandle _handle;
+ byte _volume;
+
+ // TODO!
+ //MMSoundFader *fTheFader;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Utilities/MMIDObject.h b/engines/pegasus/MMShell/Utilities/MMIDObject.h
new file mode 100755
index 0000000000..4cca1c056e
--- /dev/null
+++ b/engines/pegasus/MMShell/Utilities/MMIDObject.h
@@ -0,0 +1,68 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_MMIDOBJECT_H
+#define PEGASUS_MMSHELL_MMIDOBJECT_H
+
+#include "pegasus/MMShell/MMTypes.h"
+
+namespace Pegasus {
+
+class MMIDObject {
+friend inline int operator==(const MMIDObject &arg1, const MMIDObject &arg1);
+friend inline int operator!=(const MMIDObject &arg2, const MMIDObject &arg2);
+
+public:
+ MMIDObject(const tMM32BitID id);
+ ~MMIDObject();
+
+ tMM32BitID GetObjectID() const;
+
+private:
+ tMM32BitID fObjectID;
+};
+
+inline MMIDObject::MMIDObject(const tMM32BitID id) {
+ fObjectID = id;
+}
+
+inline MMIDObject::~MMIDObject() {
+}
+
+inline tMM32BitID MMIDObject::GetObjectID() const {
+ return fObjectID;
+}
+
+inline int operator==(const MMIDObject &arg1, const MMIDObject &arg2) {
+ return arg1.fObjectID == arg2.fObjectID;
+}
+
+inline int operator!=(const MMIDObject &arg1, const MMIDObject &arg2) {
+ return arg1.fObjectID != arg2.fObjectID;
+}
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Utilities/MMResourceFile.cpp b/engines/pegasus/MMShell/Utilities/MMResourceFile.cpp
new file mode 100755
index 0000000000..6743a8b905
--- /dev/null
+++ b/engines/pegasus/MMShell/Utilities/MMResourceFile.cpp
@@ -0,0 +1,106 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/endian.h"
+#include "common/error.h"
+#include "common/macresman.h"
+#include "common/stream.h"
+
+#include "pegasus/MMShell/Utilities/MMResourceFile.h"
+
+namespace Pegasus {
+
+MMResourceFile::MMResourceFile() {
+ _resFork = 0;
+}
+
+MMResourceFile::~MMResourceFile() {
+ if (IsFileOpen())
+ CloseResourceFile();
+}
+
+Common::Error MMResourceFile::UsePathname(const Common::String &str) {
+ if (IsFileOpen())
+ return Common::kUnknownError;
+
+ _fileName = str;
+ return Common::kNoError;
+}
+
+Common::Error MMResourceFile::OpenResourceFile() {
+ if (IsFileOpen() || _fileName.empty())
+ return Common::kUnknownError;
+
+ _resFork = new Common::MacResManager();
+
+ if (!_resFork->open(_fileName)) {
+ delete _resFork; _resFork = 0;
+ return Common::kReadingFailed;
+ }
+
+ return Common::kNoError;
+}
+
+Common::Error MMResourceFile::CloseResourceFile() {
+ if (!IsFileOpen())
+ return Common::kUnknownError;
+
+ delete _resFork;
+ _resFork = 0;
+ return Common::kNoError;
+}
+
+Common::Error MMResourceFile::GetResource(const uint32 type, const tResIDType id, Common::SeekableReadStream *&h) {
+ if (!IsFileOpen())
+ return Common::kUnknownError;
+
+ // Look how well our API fits in!
+ h = _resFork->getResource(type, id);
+ return Common::kNoError;
+}
+
+Common::Error MMResourceFile::GetResource(const uint32 type, const Common::String &name, Common::SeekableReadStream *&h) {
+ if (!IsFileOpen())
+ return Common::kUnknownError;
+
+ // Look how well our API fits in!
+ h = _resFork->getResource(type, name);
+ return Common::kNoError;
+}
+
+Common::Error MMResourceFile::GetCIcon(const tResIDType id, Common::SeekableReadStream *&icon) {
+ Common::Error err = GetResource(MKTAG('c', 'i', 'c', 'n'), id, icon);
+
+ if (err.getCode() != Common::kNoError)
+ return err;
+
+ return (icon == 0) ? Common::kUnknownError : Common::kNoError;
+}
+
+bool MMResourceFile::IsFileOpen() const {
+ return _resFork != 0;
+}
+
+} // End of namespace Pegasus \ No newline at end of file
diff --git a/engines/pegasus/MMShell/Utilities/MMResourceFile.h b/engines/pegasus/MMShell/Utilities/MMResourceFile.h
new file mode 100755
index 0000000000..47c82fd909
--- /dev/null
+++ b/engines/pegasus/MMShell/Utilities/MMResourceFile.h
@@ -0,0 +1,75 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_UTILITIES_MMRESOURCEFILE
+#define PEGASUS_MMSHELL_UTILITIES_MMRESOURCEFILE
+
+#include "common/str.h"
+
+#include "pegasus/MMShell/MMTypes.h"
+
+namespace Common {
+ class Error;
+ class MacResManager;
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+class MMResourceFile {
+public:
+ MMResourceFile();
+ virtual ~MMResourceFile();
+
+ Common::Error UsePathname(const Common::String &str);
+
+ // For ScummVM, we don't need this function
+ //OSErr MMResourceFile::UseFSSpec(const FSSpec&);
+
+ virtual Common::Error OpenResourceFile();
+ virtual Common::Error CloseResourceFile();
+ bool IsFileOpen() const;
+
+ virtual Common::Error GetResource(const uint32 type, const tResIDType id, Common::SeekableReadStream *&h);
+ virtual Common::Error GetResource(const uint32 type, const Common::String &name, Common::SeekableReadStream *&h);
+
+ // This function is unused!
+ //virtual OSErr PutResource(const ResType, const tResIDType, const Common::String &, Handle);
+
+ // For ScummVM, we will be hardcoding the file names so these two functions
+ // do nothing for us
+ //virtual OSErr GetIndString(const tResIDType, const short, Str255&);
+ //virtual OSErr GetIndString(const Str255, const short, Str255&);
+
+ virtual Common::Error GetCIcon(const tResIDType id, Common::SeekableReadStream *&icon);
+
+protected:
+ Common::MacResManager *_resFork;
+ Common::String _fileName;
+};
+
+} // End of namespace Pegasus
+
+#endif \ No newline at end of file
diff --git a/engines/pegasus/MMShell/Utilities/MMTimeValue.cpp b/engines/pegasus/MMShell/Utilities/MMTimeValue.cpp
new file mode 100755
index 0000000000..c3bf85b993
--- /dev/null
+++ b/engines/pegasus/MMShell/Utilities/MMTimeValue.cpp
@@ -0,0 +1,60 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/MMShell/MMConstants.h"
+#include "pegasus/MMShell/Utilities/MMTimeValue.h"
+
+namespace Pegasus {
+
+MMTimeValue::MMTimeValue() {
+ fTheTime = 0;
+ fTheScale = kDefaultTimeScale;
+}
+
+TimeValue MMTimeValue::GetTime() const {
+ return fTheTime;
+}
+
+void MMTimeValue::GetTime(TimeValue &time, const TimeScale scale) const {
+ time = fTheTime * fTheScale / scale;
+}
+
+void MMTimeValue::SetTime(const TimeValue time) {
+ fTheTime = time;
+}
+
+void MMTimeValue::SetTime(const TimeValue time, const TimeScale scale) {
+ fTheTime = time * scale / fTheScale;
+}
+
+TimeScale MMTimeValue::GetScale() const {
+ return fTheScale;
+}
+
+void MMTimeValue::SetScale(const TimeScale scale) {
+ fTheScale = scale;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/MMShell/Utilities/MMTimeValue.h b/engines/pegasus/MMShell/Utilities/MMTimeValue.h
new file mode 100755
index 0000000000..4060322f8e
--- /dev/null
+++ b/engines/pegasus/MMShell/Utilities/MMTimeValue.h
@@ -0,0 +1,52 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_MMTIMEVALUE_H
+#define PEGASUS_MMSHELL_MMTIMEVALUE_H
+
+#include "pegasus/MMShell/MMTypes.h"
+
+namespace Pegasus {
+
+class MMTimeValue {
+public:
+ MMTimeValue();
+
+ TimeValue GetTime() const;
+ void GetTime(TimeValue &time, const TimeScale scale) const;
+ void SetTime(const TimeValue time);
+ void SetTime(const TimeValue time, const TimeScale scale);
+
+ TimeScale GetScale() const;
+ void SetScale(const TimeScale scale);
+
+protected:
+ TimeValue fTheTime;
+ TimeScale fTheScale;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/MMShell/Utilities/MMUtilities.cpp b/engines/pegasus/MMShell/Utilities/MMUtilities.cpp
new file mode 100755
index 0000000000..e6bd146a08
--- /dev/null
+++ b/engines/pegasus/MMShell/Utilities/MMUtilities.cpp
@@ -0,0 +1,63 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/random.h"
+#include "common/util.h"
+
+#include "pegasus/MMShell/Utilities/MMUtilities.h"
+
+namespace Pegasus {
+
+inline int32 Round(const int32 a, const int32 b) {
+ if (b < 0)
+ if (a < 0)
+ return -((a - (-b >> 1)) / -b);
+ else
+ return -((a + (-b >> 1)) / -b);
+ else
+ if (a < 0)
+ return (a - (b >> 1)) / b;
+ else
+ return (a + (b >> 1)) / b;
+}
+
+int32 LinearInterp(const int32 start1, const int32 stop1, const int32 current1, const int32 start2, const int32 stop2) {
+ if (start2 == stop2)
+ return start2;
+ else
+ return start2 + Round((current1 - start1) * (stop2 - start2), (stop1 - start1));
+}
+
+void ShuffleArray(int32 *arr, int32 count, Common::RandomSource &random) {
+ if (count > 1) {
+ for (int32 i = 1; i < count; ++i) {
+ int32 j = random.getRandomNumber(i);
+ if (j != i)
+ SWAP(arr[i], arr[j]);
+ }
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/MMShell/Utilities/MMUtilities.h b/engines/pegasus/MMShell/Utilities/MMUtilities.h
new file mode 100755
index 0000000000..d5f7e541de
--- /dev/null
+++ b/engines/pegasus/MMShell/Utilities/MMUtilities.h
@@ -0,0 +1,43 @@
+/* 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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_MMSHELL_UTILITIES_MMUTILITIES_H
+#define PEGASUS_MMSHELL_UTILITIES_MMUTILITIES_H
+
+#include "common/scummsys.h"
+
+namespace Common {
+ class RandomSource;
+}
+
+namespace Pegasus {
+
+int32 LinearInterp(const int32 start1, const int32 stop1, const int32 current1, const int32 start2, const int32 stop2);
+
+void ShuffleArray(int32 *arr, int32 count, Common::RandomSource &random);
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/console.cpp b/engines/pegasus/console.cpp
new file mode 100644
index 0000000000..d6a8c1e2ec
--- /dev/null
+++ b/engines/pegasus/console.cpp
@@ -0,0 +1,38 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "pegasus/console.h"
+#include "pegasus/pegasus.h"
+
+namespace Pegasus {
+
+PegasusConsole::PegasusConsole(PegasusEngine *vm) : GUI::Debugger(), _vm(vm) {
+ // TODO! :P
+}
+
+PegasusConsole::~PegasusConsole() {
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/console.h b/engines/pegasus/console.h
new file mode 100644
index 0000000000..f544344c24
--- /dev/null
+++ b/engines/pegasus/console.h
@@ -0,0 +1,46 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef PEGASUS_CONSOLE_H
+#define PEGASUS_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace Pegasus {
+
+class PegasusEngine;
+
+class PegasusConsole : public GUI::Debugger {
+public:
+ PegasusConsole(PegasusEngine *vm);
+ virtual ~PegasusConsole();
+
+private:
+ PegasusEngine *_vm;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/credits.cpp b/engines/pegasus/credits.cpp
new file mode 100644
index 0000000000..3c625faf32
--- /dev/null
+++ b/engines/pegasus/credits.cpp
@@ -0,0 +1,174 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/events.h"
+#include "common/textconsole.h"
+#include "video/qt_decoder.h"
+
+#include "pegasus/pegasus.h"
+
+namespace Pegasus {
+
+enum {
+ kCreditsCore = 0,
+ kCreditsSupport,
+ kCreditsOriginal,
+ kCreditsTalent,
+ kCreditsOther,
+ kCreditsMainMenu
+};
+
+static const int s_startCreditsSegment[] = { 0, 16, 25, 37, 39 };
+
+static int findButtonForFrame(int frame) {
+ int button = kCreditsCore;
+ for (int i = kCreditsCore; i < kCreditsMainMenu; i++)
+ if (frame >= s_startCreditsSegment[i])
+ button = i;
+
+ return button;
+}
+
+void PegasusEngine::runCredits() {
+ Video::QuickTimeDecoder *creditsVideo = new Video::QuickTimeDecoder();
+ if (!creditsVideo->loadFile("Images/Credits/Credits.movie"))
+ error("Could not open credits movie");
+
+ // We're not playing, just retrieving frames
+ creditsVideo->pauseVideo(true);
+
+ int curButton = kCreditsCore;
+ int frame = 0;
+
+ drawCredits(curButton, false, frame, creditsVideo);
+ _system->updateScreen();
+
+ bool continueLooping = true;
+ while (!shouldQuit() && continueLooping) {
+ Common::Event event;
+ while (_eventMan->pollEvent(event)) {
+ bool needsUpdate = false;
+
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_UP:
+ if (curButton != kCreditsCore)
+ curButton--;
+ frame = s_startCreditsSegment[curButton];
+ needsUpdate = true;
+ break;
+ case Common::KEYCODE_DOWN:
+ if (curButton != kCreditsMainMenu) {
+ curButton++;
+ if (curButton == kCreditsMainMenu)
+ frame = 43;
+ else
+ frame = s_startCreditsSegment[curButton];
+ needsUpdate = true;
+ }
+ break;
+ case Common::KEYCODE_LEFT:
+ if (frame > 0) {
+ frame--;
+ curButton = findButtonForFrame(frame);
+ needsUpdate = true;
+ }
+ break;
+ case Common::KEYCODE_RIGHT:
+ if (frame < 43) {
+ frame++;
+ curButton = findButtonForFrame(frame);
+ needsUpdate = true;
+ }
+ break;
+ case Common::KEYCODE_RETURN:
+ drawCredits(curButton, true, frame, creditsVideo);
+ _system->updateScreen();
+ continueLooping = (curButton != kCreditsMainMenu);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (needsUpdate) {
+ drawCredits(curButton, false, frame, creditsVideo);
+ _system->updateScreen();
+ }
+ }
+
+ _system->delayMillis(10);
+ }
+
+ delete creditsVideo;
+}
+
+void PegasusEngine::drawCredits(int button, bool highlight, int frame, Video::QuickTimeDecoder *video) {
+ static const int s_creditsButtonY[] = { 224, 260, 296, 332, 366, 407 };
+
+ _gfx->drawPict("Images/Credits/CredScrn.pict", 0, 0, false);
+
+ if (highlight)
+ _gfx->drawPict("Images/Credits/MainMenu.pict", 32, 412, false);
+
+ if (button == kCreditsMainMenu)
+ _gfx->drawPictTransparent("Images/Credits/SelectL.pict", 30, s_creditsButtonY[button], _gfx->getColor(0xf8, 0xf8, 0xf8));
+ else
+ _gfx->drawPictTransparent("Images/Credits/SelectS.pict", 40, s_creditsButtonY[button], _gfx->getColor(0xf8, 0xf8, 0xf8));
+
+ video->seekToTime(frame * 200);
+ _video->copyFrameToScreen(video->decodeNextFrame(), video->getWidth(), video->getHeight(), 288, 0);
+}
+
+void PegasusEngine::runDemoCredits() {
+ _gfx->drawPict("Images/Demo/DemoCredits.pict", 0, 0, true);
+
+ bool continueLooping = true;
+ while (!shouldQuit() && continueLooping) {
+ Common::Event event;
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ _system->updateScreen();
+ break;
+ case Common::EVENT_KEYDOWN:
+ // Break on any keypress, but ignore the meta keys
+ // Except for num lock! num lock on OS9 is 'clear' and we need that for the inventory panel (along with the tilde)
+ continueLooping = (event.kbd.keycode == Common::KEYCODE_INVALID || (event.kbd.keycode >= Common::KEYCODE_CAPSLOCK && event.kbd.keycode <= Common::KEYCODE_COMPOSE));
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ continueLooping = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ _system->delayMillis(10);
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
new file mode 100644
index 0000000000..9c486f7548
--- /dev/null
+++ b/engines/pegasus/detection.cpp
@@ -0,0 +1,118 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+#include "common/config-manager.h"
+#include "common/file.h"
+
+#include "pegasus/pegasus.h"
+
+namespace Pegasus {
+
+struct PegasusGameDescription {
+ ADGameDescription desc;
+};
+
+bool PegasusEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL);
+}
+
+bool PegasusEngine::isDemo() const {
+ return (_gameDescription->desc.flags & ADGF_DEMO) != 0;
+}
+
+} // End of namespace Pegasus
+
+static const PlainGameDescriptor pegasusGames[] = {
+ {"pegasus", "The Journeyman Project: Pegasus Prime"},
+ {0, 0}
+};
+
+
+namespace Pegasus {
+
+static const PegasusGameDescription gameDescriptions[] = {
+ {
+ {
+ "pegasus",
+ "",
+ AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 2009943),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_MACRESFORK,
+ Common::GUIO_NONE
+ },
+ },
+
+ {
+ {
+ "pegasus",
+ "",
+ AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 360129),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_MACRESFORK|ADGF_DEMO,
+ Common::GUIO_NONE
+ },
+ },
+
+ { AD_TABLE_END_MARKER }
+};
+
+} // End of namespace Pegasus
+
+
+class PegasusMetaEngine : public AdvancedMetaEngine {
+public:
+ PegasusMetaEngine() : AdvancedMetaEngine(Pegasus::gameDescriptions, sizeof(Pegasus::PegasusGameDescription), pegasusGames) {
+ _singleid = "pegasus";
+ }
+
+ virtual const char *getName() const {
+ return "The Journeyman Project: Pegasus Prime";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "The Journeyman Project: Pegasus Prime (C) Presto Studios";
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+};
+
+bool PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Pegasus::PegasusGameDescription *gd = (const Pegasus::PegasusGameDescription *)desc;
+
+ if (gd)
+ *engine = new Pegasus::PegasusEngine(syst, gd);
+
+ return (gd != 0);
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(PEGASUS)
+ REGISTER_PLUGIN_DYNAMIC(PEGASUS, PLUGIN_TYPE_ENGINE, PegasusMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(PEGASUS, PLUGIN_TYPE_ENGINE, PegasusMetaEngine);
+#endif
+
diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp
new file mode 100644
index 0000000000..2042b8f712
--- /dev/null
+++ b/engines/pegasus/graphics.cpp
@@ -0,0 +1,250 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/graphics.h"
+
+#include "common/endian.h"
+#include "common/file.h"
+#include "common/textconsole.h"
+#include "engines/util.h"
+#include "graphics/cursorman.h"
+
+namespace Pegasus {
+
+GraphicsManager::GraphicsManager(PegasusEngine *vm) : _vm(vm) {
+ initGraphics(640, 480, true, NULL);
+
+ _pictDecoder = new Graphics::PictDecoder(_vm->_system->getScreenFormat());
+
+ for (int i = 0; i < kImageCacheSize; i++)
+ _cache[i].surface = 0;
+}
+
+GraphicsManager::~GraphicsManager() {
+ delete _pictDecoder;
+
+ for (int i = 0; i < kImageCacheSize; i++) {
+ if (_cache[i].surface) {
+ _cache[i].surface->free();
+ delete _cache[i].surface;
+ }
+ }
+}
+
+Graphics::Surface *GraphicsManager::decodeImage(const Common::String &filename) {
+ int imageSlot = getImageSlot(filename);
+
+ if (_cache[imageSlot].surface)
+ return _cache[imageSlot].surface;
+
+ Common::File file;
+ if (!file.open(filename))
+ error("Could not open \'%s\'", filename.c_str());
+
+ byte palette[256 * 3];
+ Graphics::Surface *image = _pictDecoder->decodeImage(&file, palette);
+
+ // For <= 8bpp, we need to convert
+ if (image->format.bytesPerPixel == 1) {
+ Graphics::PixelFormat format = _vm->_system->getScreenFormat();
+ Graphics::Surface *output = new Graphics::Surface();
+ output->create(image->w, image->h, format);
+
+ for (uint16 y = 0; y < image->h; y++) {
+ for (uint16 x = 0; x < image->w; x++) {
+ byte c = *((byte *)image->getBasePtr(x, y));
+ byte r = palette[c * 3];
+ byte g = palette[c * 3 + 1];
+ byte b = palette[c * 3 + 2];
+
+ if (format.bytesPerPixel == 2) {
+ uint16 color = format.RGBToColor(r, g, b);
+ memcpy(output->getBasePtr(x, y), &color, 2);
+ } else if (format.bytesPerPixel == 4) {
+ uint32 color = format.RGBToColor(r, g, b);
+ memcpy(output->getBasePtr(x, y), &color, 4);
+ }
+ }
+ }
+
+ image->free();
+ delete image;
+ image = output;
+ }
+
+ _cache[imageSlot].surface = image;
+ return image;
+}
+
+void GraphicsManager::drawPict(Common::String filename, int x, int y, bool updateScreen) {
+ Graphics::Surface *surface = decodeImage(filename);
+
+ _vm->_system->copyRectToScreen((byte *)surface->pixels, surface->pitch, x, y, surface->w, surface->h);
+
+ if (updateScreen)
+ _vm->_system->updateScreen();
+}
+
+void GraphicsManager::drawPictTransparent(Common::String filename, int x, int y, uint32 transparency, bool updateScreen) {
+ if (_vm->_system->getScreenFormat().bytesPerPixel == 2)
+ transparency &= 0xffff;
+
+ Graphics::Surface *surface = decodeImage(filename);
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+
+ for (uint16 i = 0; i < surface->h; i++) {
+ for (uint16 j = 0; j < surface->w; j++) {
+ if (_vm->_system->getScreenFormat().bytesPerPixel == 2) {
+ uint16 color = *((uint16 *)surface->getBasePtr(j, i));
+ if (color != transparency)
+ memcpy(screen->getBasePtr(j + x, i + y), &color, 2);
+ } else if (_vm->_system->getScreenFormat().bytesPerPixel == 4) {
+ uint32 color = *((uint32 *)surface->getBasePtr(j, i));
+ if (color != transparency)
+ memcpy(screen->getBasePtr(j + x, i + y), &color, 4);
+ }
+ }
+ }
+
+ _vm->_system->unlockScreen();
+
+ if (updateScreen)
+ _vm->_system->updateScreen();
+}
+
+uint32 GraphicsManager::getColor(byte r, byte g, byte b) {
+ return _vm->_system->getScreenFormat().RGBToColor(r, g, b);
+}
+
+void GraphicsManager::setCursor(uint16 cursor) {
+ Common::SeekableReadStream *cicnStream = _vm->_resFork->getResource(MKTAG('c', 'i', 'c', 'n'), cursor);
+
+ // PixMap section
+ Graphics::PictDecoder::PixMap pixMap = _pictDecoder->readPixMap(cicnStream);
+
+ // Mask section
+ cicnStream->readUint32BE(); // mask baseAddr
+ uint16 maskRowBytes = cicnStream->readUint16BE(); // mask rowBytes
+ cicnStream->skip(3 * 2); // mask rect
+ /* uint16 maskHeight = */ cicnStream->readUint16BE();
+
+ // Bitmap section
+ cicnStream->readUint32BE(); // baseAddr
+ uint16 rowBytes = cicnStream->readUint16BE();
+ cicnStream->readUint16BE(); // top
+ cicnStream->readUint16BE(); // left
+ uint16 height = cicnStream->readUint16BE(); // bottom
+ cicnStream->readUint16BE(); // right
+
+ // Data section
+ cicnStream->readUint32BE(); // icon handle
+ cicnStream->skip(maskRowBytes * height); // FIXME: maskHeight doesn't work here, though the specs say it should
+ cicnStream->skip(rowBytes * height);
+
+ // Palette section
+ cicnStream->readUint32BE(); // always 0
+ cicnStream->readUint16BE(); // always 0
+ uint16 colorCount = cicnStream->readUint16BE() + 1;
+
+ byte *colors = new byte[256 * 3];;
+ for (uint16 i = 0; i < colorCount; i++) {
+ cicnStream->readUint16BE();
+ colors[i * 3] = cicnStream->readUint16BE() >> 8;
+ colors[i * 3 + 1] = cicnStream->readUint16BE() >> 8;
+ colors[i * 3 + 2] = cicnStream->readUint16BE() >> 8;
+ }
+
+ // PixMap data
+ byte *data = new byte[pixMap.rowBytes * pixMap.bounds.height()];
+ cicnStream->read(data, pixMap.rowBytes * pixMap.bounds.height());
+ delete cicnStream;
+
+ // Now to go get the hotspots
+ Common::SeekableReadStream *cursStream = NULL;
+
+ if (cursor >= kMainCursor && cursor <= kGrabbingHand)
+ cursStream = _vm->_resFork->getResource(MKTAG('C', 'u', 'r', 's'), kMainCursor);
+ else // if (cursor == kTargetingReticle1 || cursor == kTargetingReticle2)
+ cursStream = _vm->_resFork->getResource(MKTAG('C', 'u', 'r', 's'), kTargetingReticle1);
+
+ // Go through the stream until we find the right cursor hotspot
+ uint16 x = 0, y = 0;
+ uint16 numHotspots = cursStream->readUint16BE();
+
+ for (uint16 i = 0; i < numHotspots; i++) {
+ uint16 res = cursStream->readUint16BE();
+ uint16 tempX = cursStream->readUint16BE();
+ uint16 tempY = cursStream->readUint16BE();
+
+ if (res == cursor) {
+ x = tempX;
+ y = tempY;
+ break;
+ }
+ }
+
+ // We have the bitmap and the hotspot, let's do this!
+ CursorMan.replaceCursorPalette(colors, 0, colorCount);
+ CursorMan.replaceCursor(data, pixMap.rowBytes, pixMap.bounds.height(), x, y, 0);
+ CursorMan.showMouse(true);
+ _vm->_system->updateScreen();
+
+ delete[] colors;
+ delete[] data;
+}
+
+int GraphicsManager::getImageSlot(const Common::String &filename) {
+ // Let's find a match, an open slot, or the oldest image slot
+ uint32 oldestAge = 0xffffffff;
+ int slot = 0;
+
+ for (int i = 0; i < kImageCacheSize; i++) {
+ if (_cache[i].filename.equalsIgnoreCase(filename)) {
+ //warning("Found image %s at slot %d", filename.c_str(), i);
+ _cache[i].lastUsed = _vm->_system->getMillis();
+ return i;
+ }
+
+ if (!_cache[i].surface) {
+ //warning("Putting image %s in empty slot %d", filename.c_str(), i);
+ _cache[i].filename = filename;
+ _cache[i].lastUsed = _vm->_system->getMillis();
+ return i;
+ }
+
+ if (_cache[i].lastUsed < oldestAge) {
+ oldestAge = _cache[i].lastUsed;
+ slot = i;
+ }
+ }
+
+ // Let's make sure that's cleaned out
+ //warning("Replacing old image %s with %s in slot %d", _cache[slot].filename.c_str(), filename.c_str(), slot);
+ _cache[slot].filename = filename;
+ _cache[slot].surface->free();
+ delete _cache[slot].surface;
+ _cache[slot].surface = 0;
+ _cache[slot].lastUsed = _vm->_system->getMillis();
+ return slot;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/graphics.h b/engines/pegasus/graphics.h
new file mode 100644
index 0000000000..7607c626d5
--- /dev/null
+++ b/engines/pegasus/graphics.h
@@ -0,0 +1,83 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_GRAPHICS_H
+#define PEGASUS_GRAPHICS_H
+
+#include "common/rect.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "graphics/pict.h"
+#include "graphics/surface.h"
+
+#include "pegasus/pegasus.h"
+
+namespace Pegasus {
+
+enum {
+ // The main cursors
+ kMainCursor = 128,
+ kZoomInCursor = 129,
+ kZoomOutCursor = 130,
+ kPointingCursor = 131,
+ kInteractHand = 132,
+ kGrabbingHand = 133,
+
+ // Reticles when using the Mars shuttle
+ kTargetingReticle1 = 900,
+ kTargetingReticle2 = 901
+};
+
+enum {
+ kImageCacheSize = 10
+};
+
+struct ImageCache {
+ Common::String filename;
+ Graphics::Surface *surface;
+ uint32 lastUsed;
+};
+
+class PegasusEngine;
+
+class GraphicsManager {
+public:
+ GraphicsManager(PegasusEngine *vm);
+ ~GraphicsManager();
+
+ void drawPict(Common::String filename, int x, int y, bool updateScreen = true);
+ void drawPictTransparent(Common::String filename, int x, int y, uint32 transparency, bool updateScreen = true);
+ void setCursor(uint16 cursor);
+ uint32 getColor(byte r, byte g, byte b);
+
+private:
+ PegasusEngine *_vm;
+ Graphics::PictDecoder *_pictDecoder;
+
+ Graphics::Surface *decodeImage(const Common::String &filename);
+ ImageCache _cache[kImageCacheSize];
+ int getImageSlot(const Common::String &filename);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp
new file mode 100644
index 0000000000..577d96aa82
--- /dev/null
+++ b/engines/pegasus/menu.cpp
@@ -0,0 +1,207 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/events.h"
+#include "common/textconsole.h"
+
+#include "pegasus/console.h"
+#include "pegasus/pegasus.h"
+
+#include "pegasus/MMShell/Sounds/MMSound.h"
+
+namespace Pegasus {
+
+enum {
+ kInterfaceOverviewButton = 0,
+ kStartButton = 1,
+ kRestoreButton = 2,
+ kDifficultyButton = 3,
+ kCreditsButton = 4,
+ kQuitButton = 5
+};
+
+enum {
+ kDemoStartButton = 0,
+ kDemoCreditsButton = 1,
+ kDemoQuitButton = 2
+};
+
+void PegasusEngine::runMainMenu() {
+ MMSound sound;
+ sound.InitFromAIFFFile("Sounds/Main Menu.aiff");
+ sound.LoopSound();
+
+ // Note down how long since the last click
+ uint32 lastClickTime = _system->getMillis();
+
+ int buttonSelected = 0;
+ drawMenu(buttonSelected);
+
+ while (!shouldQuit() && _system->getMillis() - lastClickTime < 60 * 1000) {
+ Common::Event event;
+
+ // Ignore events for now
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_UP:
+ if (buttonSelected > 0) {
+ buttonSelected--;
+ drawMenu(buttonSelected);
+ }
+ break;
+ case Common::KEYCODE_DOWN:
+ if ((isDemo() && buttonSelected < 2) || (!isDemo() && buttonSelected < 5)) {
+ buttonSelected++;
+ drawMenu(buttonSelected);
+ }
+ break;
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_RIGHT:
+ if (buttonSelected == kDifficultyButton) {
+ _adventureMode = !_adventureMode;
+ drawMenu(buttonSelected);
+ }
+ break;
+ case Common::KEYCODE_RETURN:
+ if (buttonSelected != kDifficultyButton) {
+ drawMenuButtonSelected(buttonSelected);
+ sound.StopSound();
+ setGameMode(buttonSelected);
+
+ if (_gameMode != kMainMenuMode)
+ return;
+
+ drawMenu(buttonSelected);
+ sound.LoopSound();
+ }
+ break;
+ case Common::KEYCODE_d:
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ _console->attach();
+ _console->onFrame();
+ }
+ break;
+ default:
+ break;
+ }
+
+ // Update our last press time too
+ lastClickTime = _system->getMillis();
+ break;
+ default:
+ break;
+ }
+ }
+
+ //_system->updateScreen();
+ _system->delayMillis(10);
+ }
+
+ if (shouldQuit())
+ return;
+
+ // Too slow! Go back and show the intro again.
+ sound.StopSound();
+ _video->playMovie(_introDirectory + "/LilMovie.movie");
+ _gameMode = kIntroMode;
+}
+
+void PegasusEngine::drawMenu(int buttonSelected) {
+ if (isDemo()) {
+ _gfx->drawPict("Images/Demo/DemoMenu.pict", 0, 0, false);
+ } else {
+ _gfx->drawPict("Images/Main Menu/MainMenu.mac", 0, 0, false);
+ if (!_adventureMode)
+ _gfx->drawPict("Images/Main Menu/BtnWlk.pict", 320, 340, false);
+ }
+
+ drawMenuButtonHighlighted(buttonSelected);
+}
+
+// FIXME: Most of these coordinates can use tweaking
+
+static const int kMainMenuButtonX = 152;
+static const char s_mainMenuButtonSuffix[] = { 'L', 'S', 'S', 'L', 'S', 'S' };
+static const int s_mainMenuButtonY[] = { 202, 252, 292, 337, 382, 422 };
+static const char s_demoMainMenuButtonSuffix[] = { 'S', 'S', 'L' }; // SSL!
+static const int s_demoMainMenuButtonX[] = { 38, 38, 28 };
+static const int s_demoMainMenuButtonY[] = { 332, 366, 408 };
+
+void PegasusEngine::drawMenuButtonHighlighted(int buttonSelected) {
+ if (isDemo())
+ _gfx->drawPictTransparent(Common::String("Images/Demo/Select") + s_demoMainMenuButtonSuffix[buttonSelected] + ".pict", s_demoMainMenuButtonX[buttonSelected], s_demoMainMenuButtonY[buttonSelected], _gfx->getColor(0xff, 0xff, 0xff), true);
+ else
+ _gfx->drawPictTransparent(Common::String("Images/Main Menu/Select") + s_mainMenuButtonSuffix[buttonSelected] + ".pict", kMainMenuButtonX, s_mainMenuButtonY[buttonSelected], _gfx->getColor(0xf8, 0xf8, 0xf8), true);
+}
+
+static const char *s_mainMenuButtonSelSuffix[] = { "Overvi", "Start", "Restor", "", "Credit", "Quit" };
+static const char *s_demoMainMenuButtonSel[] = { "Start", "Credits", "Quit" };
+static const int s_mainMenuSelButtonX[] = { 198, 210, 210, 0, 210, 210 };
+static const int s_demoMainMenuSelButtonX[] = { 43, 43, 34 };
+static const int s_demoMainMenuSelButtonY[] = { 338, 373, 410 };
+
+void PegasusEngine::drawMenuButtonSelected(int buttonSelected) {
+ if (isDemo())
+ _gfx->drawPict(Common::String("Images/Demo/") + s_demoMainMenuButtonSel[buttonSelected] + ".pict", s_demoMainMenuSelButtonX[buttonSelected], s_demoMainMenuSelButtonY[buttonSelected], false);
+ else
+ _gfx->drawPict(Common::String("Images/Main Menu/pb") + s_mainMenuButtonSelSuffix[buttonSelected] + ".pict", s_mainMenuSelButtonX[buttonSelected], s_mainMenuButtonY[buttonSelected] + 5, false);
+
+ drawMenuButtonHighlighted(buttonSelected);
+}
+
+void PegasusEngine::setGameMode(int buttonSelected) {
+ if (isDemo()) {
+ switch (buttonSelected) {
+ case kDemoStartButton:
+ _gameMode = kMainGameMode;
+ break;
+ case kDemoCreditsButton:
+ runDemoCredits();
+ break;
+ case kDemoQuitButton:
+ _gameMode = kQuitMode;
+ break;
+ }
+ } else {
+ switch (buttonSelected) {
+ case kInterfaceOverviewButton:
+ runInterfaceOverview();
+ break;
+ case kStartButton:
+ _gameMode = kMainGameMode;
+ break;
+ case kRestoreButton:
+ showLoadDialog();
+ break;
+ case kCreditsButton:
+ runCredits();
+ break;
+ case kQuitButton:
+ _gameMode = kQuitMode;
+ break;
+ }
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk
new file mode 100644
index 0000000000..ca5017b575
--- /dev/null
+++ b/engines/pegasus/module.mk
@@ -0,0 +1,32 @@
+MODULE := engines/pegasus
+
+MODULE_OBJS = \
+ console.o \
+ credits.o \
+ detection.o \
+ graphics.o \
+ menu.o \
+ overview.o \
+ pegasus.o \
+ video.o \
+ Game_Shell/CGameState.o \
+ Game_Shell/CInventory.o \
+ Game_Shell/CItem.o \
+ Game_Shell/CItemList.o \
+ MMShell/Base_Classes/MMFunctionPtr.o \
+ MMShell/Notification/MMNotification.o \
+ MMShell/Notification/MMNotificationManager.o \
+ MMShell/Notification/MMNotificationReceiver.o \
+ MMShell/Sounds/MMSound.o \
+ MMShell/Utilities/MMResourceFile.o \
+ MMShell/Utilities/MMTimeValue.o \
+ MMShell/Utilities/MMUtilities.o
+
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_PEGASUS), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/pegasus/overview.cpp b/engines/pegasus/overview.cpp
new file mode 100644
index 0000000000..adbfbdbbe8
--- /dev/null
+++ b/engines/pegasus/overview.cpp
@@ -0,0 +1,142 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/events.h"
+#include "common/textconsole.h"
+#include "graphics/cursorman.h"
+#include "video/qt_decoder.h"
+
+#include "pegasus/pegasus.h"
+
+namespace Pegasus {
+
+void PegasusEngine::runInterfaceOverview() {
+ CursorMan.showMouse(true);
+ _gfx->setCursor(kPointingCursor);
+
+ Video::QuickTimeDecoder *overviewVideo = new Video::QuickTimeDecoder();
+ if (!overviewVideo->loadFile("Images/Interface/Overview Mac.movie"))
+ error("Could not open overview video");
+
+ // Pause the video, we're only getting frames from it
+ overviewVideo->pauseVideo(true);
+
+ static const OverviewHotspot overviewHotspots[] = {
+ { Common::Rect(0, 0, 640, 480), 1000 }, // Main
+ { Common::Rect(131, 39, 212, 63), 660 }, // Date
+ { Common::Rect(210, 33, 326, 63), 330 }, // Compass
+ { Common::Rect(324, 39, 448, 63), 800 }, // Energy Bar
+ { Common::Rect(531, 35, 601, 57), 2330 }, // Energy Alert
+ { Common::Rect(63, 63, 577, 321), 1730 }, // View Window
+ { Common::Rect(69, 317, 355, 331), 1360 }, // Inventory Panel
+ { Common::Rect(353, 317, 559, 331), 130 }, // BioChip Panel
+ { Common::Rect(75, 333, 173, 431), 1460 }, // Inventory Box
+ { Common::Rect(171, 333, 365, 431), 2060 }, // Inventory/BioChip Display
+ { Common::Rect(363, 333, 461, 431), 1860 }, // BioChip Box
+ { Common::Rect(540, 348, 640, 468), 530 }, // Keyboard
+ };
+
+ // Draw the rest of the interface
+ int curHotspot;
+ for (int i = 0; i < ARRAYSIZE(overviewHotspots); i++)
+ if (overviewHotspots[i].rect.contains(_eventMan->getMousePos()))
+ curHotspot = i;
+ drawInterfaceOverview(overviewHotspots[curHotspot], overviewVideo);
+ _system->updateScreen();
+
+ bool continueLooping = true;
+ while (!shouldQuit() && continueLooping) {
+ Common::Event event;
+ while (_eventMan->pollEvent(event)) {
+ bool updateScreen = false;
+
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ updateScreen = true;
+ break;
+ case Common::EVENT_KEYDOWN:
+ // Break on any keypress, but ignore the meta keys
+ // Except for num lock! num lock on OS9 is 'clear' and we need that for the inventory panel (along with the tilde)
+ continueLooping = (event.kbd.keycode == Common::KEYCODE_INVALID || (event.kbd.keycode >= Common::KEYCODE_CAPSLOCK && event.kbd.keycode <= Common::KEYCODE_COMPOSE));
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ continueLooping = false;
+ break;
+ default:
+ break;
+ }
+
+ int oldHotspot = curHotspot;
+
+ for (int i = 0; i < ARRAYSIZE(overviewHotspots); i++)
+ if (overviewHotspots[i].rect.contains(_eventMan->getMousePos()))
+ curHotspot = i;
+
+ if (oldHotspot != curHotspot) {
+ drawInterfaceOverview(overviewHotspots[curHotspot], overviewVideo);
+ updateScreen = true;
+ }
+
+ if (updateScreen)
+ _system->updateScreen();
+ }
+
+ _system->delayMillis(10);
+ }
+
+ CursorMan.showMouse(false);
+ delete overviewVideo;
+}
+
+void PegasusEngine::drawInterfaceOverview(const OverviewHotspot &hotspot, Video::QuickTimeDecoder *video) {
+ _gfx->drawPict("Images/Interface/OVTop.mac", 0, 0, false);
+ _gfx->drawPict("Images/Interface/OVLeft.mac", 0, kViewScreenOffset, false);
+ _gfx->drawPict("Images/Interface/OVRight.mac", 640 - kViewScreenOffset, kViewScreenOffset, false);
+ _gfx->drawPict("Images/Interface/OVBottom.mac", 0, kViewScreenOffset + 256, false);
+
+ video->seekToTime(hotspot.time);
+ _video->copyFrameToScreen(video->decodeNextFrame(), video->getWidth(), video->getHeight(), kViewScreenOffset, kViewScreenOffset);
+
+ if (hotspot.time == 530) {
+ // The keyboard is special
+ // Interesting how the file is "controller" and not keyboard. The PlayStation/Pippin versions probably
+ // had similar names...
+ _gfx->drawPict("Images/Interface/OVcontrollerHilite.mac", hotspot.rect.left, hotspot.rect.top, false);
+ } else if (hotspot.time != 1000) {
+ // Draw a yellow outline around the hotspot
+ Common::Rect rect = hotspot.rect;
+ uint32 color = _system->getScreenFormat().RGBToColor(232, 232, 0); // Yellow
+ Graphics::Surface *screen = _system->lockScreen();
+ screen->frameRect(rect, color);
+ rect.grow(1);
+ screen->frameRect(rect, color);
+ rect.grow(1);
+ screen->frameRect(rect, color);
+ screen->hLine(rect.left + 1, rect.top - 1, rect.right - 2, color);
+ screen->hLine(rect.left + 1, rect.bottom, rect.right - 2, color);
+ screen->vLine(rect.left - 1, rect.top + 1, rect.bottom - 2, color);
+ screen->vLine(rect.right, rect.top + 1, rect.bottom - 2, color);
+ _system->unlockScreen();
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
new file mode 100644
index 0000000000..4e68007c03
--- /dev/null
+++ b/engines/pegasus/pegasus.cpp
@@ -0,0 +1,392 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/config-manager.h"
+#include "common/error.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/fs.h"
+#include "common/textconsole.h"
+#include "common/translation.h"
+#include "base/plugins.h"
+#include "base/version.h"
+#include "gui/saveload.h"
+
+#include "pegasus/console.h"
+#include "pegasus/pegasus.h"
+
+//#define RUN_SUB_MOVIE // :D :D :D :D :D :D
+//#define RUN_INTERFACE_TEST
+
+#ifdef RUN_INTERFACE_TEST
+#include "pegasus/MMShell/Sounds/MMSound.h"
+#endif
+
+namespace Pegasus {
+
+PegasusEngine::PegasusEngine(OSystem *syst, const PegasusGameDescription *gamedesc) : Engine(syst), _gameDescription(gamedesc) {
+}
+
+PegasusEngine::~PegasusEngine() {
+ delete _video;
+ delete _gfx;
+ delete _resFork;
+ delete _inventoryLid;
+ delete _biochipLid;
+ delete _console;
+}
+
+Common::Error PegasusEngine::run() {
+ _console = new PegasusConsole(this);
+ _gfx = new GraphicsManager(this);
+ _video = new VideoManager(this);
+ _resFork = new Common::MacResManager();
+ _inventoryLid = new Common::MacResManager();
+ _biochipLid = new Common::MacResManager();
+ _gameMode = kIntroMode;
+ _adventureMode = true;
+
+ if (!_resFork->open("JMP PP Resources") || !_resFork->hasResFork())
+ error("Could not load JMP PP Resources");
+
+ if (!_inventoryLid->open("Images/Lids/Inventory Lid Sequence") || !_inventoryLid->hasResFork())
+ error("Could not open Inventory Lid Sequence");
+
+ if (!_biochipLid->open("Images/Lids/Biochip Lid Sequence") || !_biochipLid->hasResFork())
+ error("Could not open Biochip Lid Sequence");
+
+ loadItemLocationData();
+
+ if (!isDemo() && !detectOpeningClosingDirectory()) {
+ Common::String message = "Missing intro directory. ";
+
+ // Give Mac OS X a more specific message because we can
+#ifdef MACOSX
+ message += "Make sure \"Opening/Closing\" is present.";
+#else
+ message += "Be sure to rename \"Opening/Closing\" to \"Opening_Closing\".";
+#endif
+
+ GUIErrorMessage(message);
+ warning("%s", message.c_str());
+ return Common::kNoGameDataFoundError;
+ }
+
+#if 0
+ Common::MacResIDArray pictIds = _biochipLid->getResIDArray(MKID_BE('PICT'));
+ for (uint32 i = 0; i < pictIds.size(); i++) {
+ Common::String filename = Common::String::printf("PICT_%d.pict", pictIds[i]);
+ Common::DumpFile file;
+ assert(file.open(filename));
+ Common::SeekableReadStream *res = _biochipLid->getResource(MKID_BE('PICT'), pictIds[i]);
+ byte *data = new byte[res->size()];
+ res->read(data, res->size());
+ for (int j = 0; j < 512; j++)
+ file.writeByte(0);
+ file.write(data, res->size());
+ file.close();
+ delete res;
+ delete[] data;
+ }
+#endif
+
+#if defined(RUN_SUB_MOVIE)
+ _video->playMovie("Images/Norad Alpha/Sub Chase Movie");
+#elif defined(RUN_INTERFACE_TEST)
+ drawInterface();
+ _gfx->setCursor(kMainCursor);
+ MMSound sound;
+ sound.InitFromAIFFFile("Sounds/Caldoria/Apartment Music.aiff");
+ sound.LoopSound();
+
+ while (!shouldQuit()) {
+ Common::Event event;
+ // Ignore events for now
+ while (_eventMan->pollEvent(event)) {
+ if (event.type == Common::EVENT_MOUSEMOVE)
+ _system->updateScreen();
+ }
+
+ _system->delayMillis(10);
+ }
+#else
+ while (!shouldQuit()) {
+ switch (_gameMode) {
+ case kIntroMode:
+ if (!isDemo())
+ runIntro();
+ _gameMode = kMainMenuMode;
+ break;
+ case kMainMenuMode:
+ runMainMenu();
+ break;
+ case kMainGameMode:
+ if (isDemo())
+ changeLocation(kLocPrehistoric);
+ else
+ changeLocation(kLocCaldoria);
+ mainGameLoop();
+ break;
+ case kQuitMode:
+ return Common::kNoError;
+ default:
+ _gameMode = kMainMenuMode;
+ break;
+ }
+ }
+#endif
+
+ return Common::kNoError;
+}
+
+bool PegasusEngine::detectOpeningClosingDirectory() {
+ // We need to detect what our Opening/Closing directory is listed as
+ // On the original disc, it was 'Opening/Closing' but only HFS(+) supports the slash
+ // Mac OS X will display this as 'Opening:Closing' and we can use that directly
+ // On other systems, users will need to rename to "Opening_Closing"
+
+ Common::FSNode gameDataDir(ConfMan.get("path"));
+ gameDataDir = gameDataDir.getChild("Images");
+
+ if (!gameDataDir.exists())
+ return false;
+
+ Common::FSList fsList;
+ if (!gameDataDir.getChildren(fsList, Common::FSNode::kListDirectoriesOnly, true))
+ return false;
+
+ for (uint i = 0; i < fsList.size() && _introDirectory.empty(); i++) {
+ Common::String name = fsList[i].getName();
+
+ if (name.equalsIgnoreCase("Opening:Closing"))
+ _introDirectory = name;
+ else if (name.equalsIgnoreCase("Opening_Closing"))
+ _introDirectory = name;
+ }
+
+ if (_introDirectory.empty())
+ return false;
+
+ debug(0, "Detected intro location as '%s'", _introDirectory.c_str());
+ _introDirectory = Common::String("Images/") + _introDirectory;
+ return true;
+}
+
+void PegasusEngine::loadItemLocationData() {
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('N', 'I', 't', 'm'), 0x80);
+
+ uint16 entryCount = res->readUint16BE();
+
+ for (uint16 i = 0; i < entryCount; i++) {
+ ItemLocationData loc;
+ loc.id = res->readUint16BE(); // Which is always == i, anyway
+ loc.location = (ItemLocation)res->readUint16BE();
+ loc.u0 = res->readUint16BE();
+ loc.u1 = res->readByte();
+ debug(1, "Item[%d]: ID = %d, location = %x, u0 = %d, u1 = %d", i, loc.id, loc.location, loc.u0, loc.u1);
+ res->readByte();
+ _itemLocationData.push_back(loc);
+ }
+
+ delete res;
+}
+
+void PegasusEngine::runIntro() {
+ _video->playMovieCentered(_introDirectory + "/BandaiLogo.movie");
+ VideoHandle handle = _video->playBackgroundMovie(_introDirectory + "/Big Movie.movie");
+ _video->seekToTime(handle, 10 * 600);
+ _video->waitUntilMovieEnds(handle);
+}
+
+void PegasusEngine::drawInterface() {
+ _gfx->drawPict("Images/Interface/3DInterface Top", 0, 0, false);
+ _gfx->drawPict("Images/Interface/3DInterface Left", 0, kViewScreenOffset, false);
+ _gfx->drawPict("Images/Interface/3DInterface Right", 640 - kViewScreenOffset, kViewScreenOffset, false);
+ _gfx->drawPict("Images/Interface/3DInterface Bottom", 0, kViewScreenOffset + 256, false);
+ //drawCompass();
+ _system->updateScreen();
+}
+
+void PegasusEngine::mainGameLoop() {
+ // TODO: Yeah...
+ _system->fillScreen(0);
+ _video->playMovieCentered("Images/Caldoria/Pullback.movie");
+ drawInterface();
+
+ Common::String navMovie = Common::String::format("Images/%s/%s.movie", getTimeZoneFolder(_timeZone).c_str(), getTimeZoneDesc(_timeZone).c_str());
+ _video->playMovie(navMovie, kViewScreenOffset, kViewScreenOffset);
+
+ _gameMode = kQuitMode;
+}
+
+void PegasusEngine::changeLocation(TimeZone timeZone) {
+ _timeZone = timeZone;
+ loadViews(_timeZone);
+ //loadExits(_timeZone);
+ loadDoors(_timeZone);
+ //loadHSLs(_timeZone);
+ //loadHSIn(_timeZone);
+ loadSoundSpots(_timeZone);
+ //loadTurns(_timeZone);
+ loadZooms(_timeZone);
+ loadExtras(_timeZone);
+}
+
+void PegasusEngine::loadViews(TimeZone timeZone) {
+ _currentViews.clear();
+
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('V', 'i', 'e', 'w'), getTimeZoneDesc(timeZone));
+
+ uint32 entryCount = res->readUint32BE();
+
+ for (uint32 i = 0; i < entryCount; i++) {
+ View view;
+ view.u0 = res->readUint16BE(); // Compass reading?
+ view.u1 = res->readByte(); // Always 0-3, direction?
+ view.u2 = res->readByte(); // Usually 0, rarely 3
+ view.frameTime = res->readUint32BE();
+ debug(1, "View[%d]: u0 = %d, u1 = %d, u2 = %d, time = %d", i, view.u0, view.u1, view.u2, view.frameTime);
+ _currentViews.push_back(view);
+ }
+
+ delete res;
+}
+
+void PegasusEngine::loadDoors(TimeZone timeZone) {
+ _currentDoors.clear();
+
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('D', 'o', 'o', 'r'), getTimeZoneDesc(timeZone));
+
+ uint32 entryCount = res->readUint32BE();
+
+ for (uint32 i = 0; i < entryCount; i++) {
+ Door door;
+ door.u0 = res->readUint16BE();
+ door.u1 = res->readUint16BE(); // Always divisible by 256?
+ door.startTime = res->readUint32BE();
+ door.endTime = res->readUint32BE();
+ door.u2 = res->readUint16BE();
+ debug(1, "Door[%d]: u0 = %d, u1 = %d, startTime = %d, endTime = %d, u2 = %d", i, door.u0, door.u1, door.startTime, door.endTime, door.u2);
+ _currentDoors.push_back(door);
+ }
+
+ delete res;
+}
+
+void PegasusEngine::loadSoundSpots(TimeZone timeZone) {
+ _currentSoundSpots.clear();
+
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('S', 'p', 'o', 't'), getTimeZoneDesc(timeZone));
+
+ uint32 entryCount = res->readUint32BE();
+
+ for (uint32 i = 0; i < entryCount; i++) {
+ SoundSpot spot;
+ spot.u0 = res->readUint16BE();
+ spot.u1 = res->readUint16BE();
+ spot.u2 = res->readUint16BE(); // 0/1 or 768/769
+ spot.startTime = res->readUint32BE();
+ spot.endTime = res->readUint32BE();
+ spot.u3 = res->readUint16BE();
+ debug(1, "Sound Spot[%d]: u0 = %d, u1 = %d, u2 = %d, startTime = %d, endTime = %d, u3 = %d", i, spot.u0, spot.u1, spot.u2, spot.startTime, spot.endTime, spot.u3);
+ _currentSoundSpots.push_back(spot);
+ }
+
+ delete res;
+}
+
+void PegasusEngine::loadZooms(TimeZone timeZone) {
+ _currentZooms.clear();
+
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('Z', 'o', 'o', 'm'), getTimeZoneDesc(timeZone));
+
+ uint32 entryCount = res->readUint32BE();
+
+ for (uint32 i = 0; i < entryCount; i++) {
+ Zoom zoom;
+ zoom.u0 = res->readUint16BE();
+ zoom.u1 = res->readUint16BE();
+ zoom.startTime = res->readUint32BE();
+ zoom.endTime = res->readUint32BE();
+ zoom.u2 = res->readUint16BE();
+ debug(1, "Zoom[%d]: u0 = %d, u1 = %d, startTime = %d, endTime = %d, u2 = %d", i, zoom.u0, zoom.u1, zoom.startTime, zoom.endTime, zoom.u2);
+ _currentZooms.push_back(zoom);
+ }
+
+ delete res;
+}
+
+void PegasusEngine::loadExtras(TimeZone timeZone) {
+ _currentExtras.clear();
+
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('X', 't', 'r', 'a'), getTimeZoneDesc(timeZone));
+
+ uint32 entryCount = res->readUint32BE();
+
+ for (uint32 i = 0; i < entryCount; i++) {
+ Extra extra;
+ extra.u0 = res->readUint32BE();
+ extra.startTime = res->readUint32BE();
+ extra.endTime = res->readUint32BE();
+ debug(1, "Extra[%d]: u0 = %d, startTime = %d, endTime = %d", i, extra.u0, extra.startTime, extra.endTime);
+ _currentExtras.push_back(extra);
+ }
+
+ delete res;
+}
+
+void PegasusEngine::showLoadDialog() {
+ GUI::SaveLoadChooser slc(_("Load game:"), _("Load"));
+ slc.setSaveMode(false);
+
+ Common::String gameId = ConfMan.get("gameid");
+
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+
+ int slot = slc.runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+
+ if (slot >= 0) {
+ warning("TODO: Load game");
+ _gameMode = kMainGameMode;
+ }
+
+ slc.close();
+}
+
+Common::String PegasusEngine::getTimeZoneDesc(TimeZone timeZone) {
+ static const char *names[] = { "Prehistoric", "Mars", "WSC", "Tiny TSA", "Full TSA", "Norad Alpha", "Caldoria", "Norad Delta" };
+ return names[timeZone];
+}
+
+Common::String PegasusEngine::getTimeZoneFolder(TimeZone timeZone) {
+ if (timeZone == kLocFullTSA || timeZone == kLocTinyTSA)
+ return "TSA";
+
+ return getTimeZoneDesc(timeZone);
+}
+
+GUI::Debugger *PegasusEngine::getDebugger() {
+ return _console;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h
new file mode 100644
index 0000000000..9f546337b5
--- /dev/null
+++ b/engines/pegasus/pegasus.h
@@ -0,0 +1,271 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_H
+#define PEGASUS_H
+
+#include "common/macresman.h"
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/rect.h"
+#include "common/util.h"
+
+#include "engines/engine.h"
+
+#include "pegasus/graphics.h"
+#include "pegasus/video.h"
+
+namespace Video {
+ class Video::QuickTimeDecoder;
+}
+
+namespace Pegasus {
+
+class PegasusConsole;
+struct PegasusGameDescription;
+class SoundManager;
+class VideoManager;
+class GraphicsManager;
+
+enum ItemLocation {
+ kItemLocationCaldoria = 0,
+ kItemLocationTSA = 1,
+ kItemLocationNorad = 4, // ???
+ kItemLocationMars = 5,
+ kItemLocationWSC = 6,
+ kItemLocationPrehistoric = 7,
+ kItemLocationBuiltIn = 0xffff
+};
+
+static const int kViewScreenOffset = 64;
+
+struct ItemLocationData {
+ uint16 id;
+ ItemLocation location;
+ uint16 u0;
+ byte u1;
+};
+
+struct View {
+ uint16 u0;
+ byte u1;
+ byte u2;
+ uint32 frameTime;
+};
+
+struct Door {
+ uint16 u0;
+ uint16 u1;
+ uint32 startTime;
+ uint32 endTime;
+ uint16 u2;
+};
+
+struct SoundSpot {
+ uint16 u0;
+ uint16 u1;
+ uint16 u2;
+ uint32 startTime;
+ uint32 endTime;
+ uint16 u3;
+};
+
+struct Zoom {
+ uint16 u0;
+ uint32 startTime;
+ uint32 endTime;
+ uint16 u1;
+ uint16 u2;
+};
+
+struct Extra {
+ uint32 u0;
+ uint32 startTime;
+ uint32 endTime;
+};
+
+struct InventoryPanelEntry {
+ uint32 startTime;
+ uint32 endTime;
+};
+
+struct InventoryItemData {
+ uint32 leftFrameTime;
+ uint32 rightStartTime;
+ uint32 rightEndTime;
+ uint16 pict; // Cannot use item at this spot
+ uint16 usablePict; // Can use item at this spot
+};
+
+struct InventoryExtra {
+ uint32 id;
+ uint16 movie;
+ uint32 startTime;
+ uint32 endTime;
+};
+
+struct LeftAreaData {
+ uint16 frame;
+ uint32 time;
+};
+
+struct MiddleAreaData {
+ uint16 id;
+ uint32 time;
+};
+
+struct RightAreaData {
+ uint16 frame;
+ uint32 time;
+};
+
+struct OverviewHotspot {
+ Common::Rect rect;
+ uint32 time;
+};
+
+enum TimeZone {
+ kLocPrehistoric = 0,
+ kLocMars = 1,
+ kLocWSC = 2,
+ kLocTinyTSA = 3,
+ kLocFullTSA = 4,
+ kLocNoradAlpha = 5,
+ kLocCaldoria = 6,
+ kLocNoradDelta = 7
+};
+
+// Taken from JMP PP Resources
+enum Item {
+ kAIBiochip = 128,
+ kInterfaceBiochip = 129, // NOT USED!
+ kMapBiochip = 130,
+ kOpticalBiochip = 131,
+ kPegasusBiochip = 132,
+ kRetinalScanBiochip = 133,
+ kShieldBiochip = 134,
+ kAirMask = 135,
+ kAntidote = 136,
+ kArgonCanister = 137,
+ kCardBomb = 138,
+ kCrowbar = 139,
+ kGasCanister = 140,
+ kHistoricalLog = 141,
+ kJourneymanKey = 142,
+ kKeyCard = 143,
+ kMachineGun = 144, // What the hell is this?
+ kMarsCard = 145,
+ kNitrogenCanister = 146,
+ kOrangeJuiceGlassFull = 147,
+ kOrangeJuiceGlassEmpty = 148,
+ kPoisonDart = 149,
+ kSinclairKey = 150,
+ kStunGun = 151,
+ kArgonPickup = 152 // ???
+};
+
+enum GameMode {
+ kIntroMode,
+ kMainMenuMode,
+ kMainGameMode,
+ kQuitMode
+};
+
+class PegasusEngine : public ::Engine {
+protected:
+ Common::Error run();
+
+public:
+ PegasusEngine(OSystem *syst, const PegasusGameDescription *gamedesc);
+ virtual ~PegasusEngine();
+
+ const PegasusGameDescription *_gameDescription;
+ bool hasFeature(EngineFeature f) const;
+ GUI::Debugger *getDebugger();
+
+ VideoManager *_video;
+ GraphicsManager *_gfx;
+ Common::MacResManager *_resFork, *_inventoryLid, *_biochipLid;
+
+ bool isDemo() const;
+
+private:
+ // Intro
+ void runIntro();
+ void runMainMenu();
+ void drawMenu(int buttonSelected);
+ void drawMenuButtonHighlighted(int buttonSelected);
+ void drawMenuButtonSelected(int buttonSelected);
+ //void runInterfaceOverview();
+ void setGameMode(int buttonSelected);
+
+ // Interface
+ void drawInterface();
+ //void drawCompass();
+ //void runPauseMenu();
+ void showLoadDialog();
+
+ // Interface Overview
+ void runInterfaceOverview();
+ void drawInterfaceOverview(const OverviewHotspot &hotspot, Video::QuickTimeDecoder *video);
+
+ // Credits
+ void runCredits();
+ void drawCredits(int button, bool highlight, int frame, Video::QuickTimeDecoder *video);
+ void runDemoCredits();
+
+ // Main Game Functions
+ void mainGameLoop();
+ void loadItemLocationData();
+ void changeLocation(TimeZone timeZone);
+ void loadViews(TimeZone timeZone);
+ void loadDoors(TimeZone timeZone);
+ void loadSoundSpots(TimeZone timeZone);
+ void loadZooms(TimeZone timeZone);
+ void loadExtras(TimeZone timeZone);
+
+ // Misc Functions
+ static Common::String getTimeZoneFolder(TimeZone timeZone);
+ static Common::String getTimeZoneDesc(TimeZone timeZone);
+
+ // Game Variables
+ bool _adventureMode;
+ GameMode _gameMode;
+ TimeZone _timeZone;
+ Common::Array<ItemLocationData> _itemLocationData;
+ Common::Array<View> _currentViews;
+ Common::Array<Door> _currentDoors;
+ Common::Array<SoundSpot> _currentSoundSpots;
+ Common::Array<Zoom> _currentZooms;
+ Common::Array<Extra> _currentExtras;
+
+ // Console
+ PegasusConsole *_console;
+
+ // Intro Directory Code
+ bool detectOpeningClosingDirectory();
+ Common::String _introDirectory;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/video.cpp b/engines/pegasus/video.cpp
new file mode 100644
index 0000000000..89884e042f
--- /dev/null
+++ b/engines/pegasus/video.cpp
@@ -0,0 +1,288 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/pegasus.h"
+#include "pegasus/video.h"
+
+#include "common/events.h"
+#include "common/textconsole.h"
+#include "graphics/scaler.h"
+#include "video/qt_decoder.h"
+
+namespace Pegasus {
+
+VideoManager::VideoManager(PegasusEngine *vm) : _vm(vm) {
+ _timeZoneVideo = 0;
+}
+
+VideoManager::~VideoManager() {
+ stopVideos();
+ delete _timeZoneVideo;
+}
+
+bool VideoManager::loadTimeZoneVideo(const Common::String &filename) {
+ Video::QuickTimeDecoder *video = new Video::QuickTimeDecoder();
+
+ if (!video->loadFile(filename)) {
+ delete video;
+ return false;
+ }
+
+ delete _timeZoneVideo;
+ _timeZoneVideo = video;
+
+ // Set it on pause
+ _timeZoneVideo->pauseVideo(true);
+ return true;
+}
+
+void VideoManager::drawTimeZoneVideoFrame(uint32 time) {
+ assert(_timeZoneVideo);
+
+ if (!_timeZoneVideo->isPaused())
+ _timeZoneVideo->pauseVideo(true);
+
+ _timeZoneVideo->seekToTime(Audio::Timestamp(0, time, 600));
+
+ const Graphics::Surface *frame = _timeZoneVideo->decodeNextFrame();
+
+ if (!frame)
+ error("Could not find frame at time %d", time);
+
+ copyFrameToScreen(frame, _timeZoneVideo->getWidth(), _timeZoneVideo->getHeight(), kViewScreenOffset, kViewScreenOffset);
+ _vm->_system->updateScreen();
+}
+
+void VideoManager::playTimeZoneVideoSegment(uint32 startTime, uint32 endTime) {
+ assert(_timeZoneVideo);
+
+ _timeZoneVideo->seekToTime(Audio::Timestamp(0, startTime, 600));
+
+ if (_timeZoneVideo->isPaused())
+ _timeZoneVideo->pauseVideo(false);
+
+ // Convert the end time to ms
+ endTime = Audio::Timestamp(0, endTime, 600).msecs();
+
+ bool continuePlaying = true;
+ while (!_timeZoneVideo->endOfVideo() && _timeZoneVideo->getElapsedTime() < endTime && !_vm->shouldQuit() && continuePlaying) {
+ if (_timeZoneVideo->needsUpdate()) {
+ const Graphics::Surface *frame = _timeZoneVideo->decodeNextFrame();
+
+ if (frame) {
+ copyFrameToScreen(frame, _timeZoneVideo->getWidth(), _timeZoneVideo->getHeight(), kViewScreenOffset, kViewScreenOffset);
+ _vm->_system->updateScreen();
+ }
+ }
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_RTL:
+ case Common::EVENT_QUIT:
+ continuePlaying = false;
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ continuePlaying = false;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Cut down on CPU usage
+ _vm->_system->delayMillis(10);
+ }
+
+ _timeZoneVideo->pauseVideo(true);
+}
+
+void VideoManager::pauseVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ _videoStreams[i]->pauseVideo(true);
+}
+
+void VideoManager::resumeVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++)
+ _videoStreams[i]->pauseVideo(false);
+}
+
+void VideoManager::stopVideos() {
+ for (uint16 i = 0; i < _videoStreams.size(); i++) {
+ delete _videoStreams[i].video;
+ _videoStreams[i].video = 0;
+ }
+}
+
+void VideoManager::playMovie(Common::String filename, uint16 x, uint16 y) {
+ VideoHandle videoHandle = playBackgroundMovie(filename, x, y, false);
+
+ if (videoHandle != NULL_VID_HANDLE)
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::playMovieCentered(Common::String filename) {
+ VideoHandle videoHandle = playBackgroundMovie(filename, 0, 0, false);
+
+ if (videoHandle == NULL_VID_HANDLE)
+ return;
+
+ _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
+ _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2;
+
+ waitUntilMovieEnds(videoHandle);
+}
+
+void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
+ bool continuePlaying = true;
+
+ while (!_videoStreams[videoHandle]->endOfVideo() && !_vm->shouldQuit() && continuePlaying) {
+ if (updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_RTL:
+ case Common::EVENT_QUIT:
+ continuePlaying = false;
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ continuePlaying = false;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Cut down on CPU usage
+ _vm->_system->delayMillis(10);
+ }
+
+ delete _videoStreams[videoHandle].video;
+ _videoStreams.clear();
+}
+
+bool VideoManager::updateBackgroundMovies() {
+ bool updateScreen = false;
+
+ for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) {
+ // Skip deleted videos
+ if (!_videoStreams[i].video)
+ continue;
+
+ // Remove any videos that are over
+ if (_videoStreams[i]->endOfVideo()) {
+ if (_videoStreams[i].loop) {
+ _videoStreams[i]->rewind();
+ } else {
+ delete _videoStreams[i].video;
+ memset(&_videoStreams[i], 0, sizeof(VideoEntry));
+ _videoStreams[i].video = NULL;
+ continue;
+ }
+ }
+
+ // Check if we need to draw a frame
+ if (_videoStreams[i]->needsUpdate()) {
+ const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame();
+
+ if (frame) {
+ copyFrameToScreen(frame, _videoStreams[i]->getWidth(), _videoStreams[i]->getHeight(), _videoStreams[i].x, _videoStreams[i].y);
+
+ // We've drawn something to the screen, make sure we update it
+ updateScreen = true;
+ }
+ }
+ }
+
+ // Return true if we need to update the screen
+ return updateScreen;
+}
+
+VideoHandle VideoManager::playBackgroundMovie(Common::String filename, int x, int y, bool loop) {
+ // First, check to see if that video is already playing
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (_videoStreams[i].filename == filename)
+ return i;
+
+ // Otherwise, create a new entry
+ VideoEntry entry;
+ entry.video = new Video::QuickTimeDecoder();
+ entry.x = x;
+ entry.y = y;
+ entry.filename = filename;
+ entry.loop = loop;
+
+ if (!entry->loadFile(filename))
+ return NULL_VID_HANDLE;
+
+ // Search for any deleted videos so we can take a formerly used slot
+ for (uint32 i = 0; i < _videoStreams.size(); i++)
+ if (!_videoStreams[i].video) {
+ _videoStreams[i] = entry;
+ return i;
+ }
+
+ // Otherwise, just add it to the list
+ _videoStreams.push_back(entry);
+ return _videoStreams.size() - 1;
+}
+
+void VideoManager::seekToTime(VideoHandle handle, uint32 time) {
+ if (handle != NULL_VID_HANDLE)
+ _videoStreams[handle]->seekToTime(Audio::Timestamp(0, time, 600));
+}
+
+void VideoManager::copyFrameToScreen(const Graphics::Surface *frame, int width, int height, int x, int y) {
+ if (frame->format.bytesPerPixel == 1)
+ error("Unhandled 8bpp frames"); // Cut out because Pegasus Prime shouldn't need this
+
+ // Clip the width/height to make sure we stay on the screen
+ width = MIN<int32>(width, _vm->_system->getWidth() - x);
+ height = MIN<int32>(height, _vm->_system->getHeight() - y);
+
+ if (width == 320 && height == 240) {
+ // TODO: Is this right? At least "Big Movie" and the "Sub Chase Movie" need to be scaled...
+ // FIXME: Normal2x is only compiled in when USE_SCALERS is defined
+ Graphics::Surface scaledSurf;
+ scaledSurf.create(frame->w * 2, frame->h * 2, frame->format);
+ Normal2x((byte *)frame->pixels, frame->pitch, (byte *)scaledSurf.pixels, scaledSurf.pitch, frame->w, frame->h);
+ _vm->_system->copyRectToScreen((byte *)scaledSurf.pixels, scaledSurf.pitch, 0, 0, width * 2, height * 2);
+ scaledSurf.free();
+ } else
+ _vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, width, height);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/video.h b/engines/pegasus/video.h
new file mode 100644
index 0000000000..56339e4c42
--- /dev/null
+++ b/engines/pegasus/video.h
@@ -0,0 +1,92 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PEGASUS_VIDEO_H
+#define PEGASUS_VIDEO_H
+
+#include "common/array.h"
+
+namespace Common {
+ class String;
+}
+
+namespace Video {
+ class QuickTimeDecoder;
+}
+
+namespace Pegasus {
+
+class PegasusEngine;
+
+struct VideoEntry {
+ Video::QuickTimeDecoder *video;
+ uint16 x;
+ uint16 y;
+ bool loop;
+ Common::String filename;
+
+ Video::QuickTimeDecoder *operator->() const { assert(video); return video; }
+};
+
+typedef int32 VideoHandle;
+
+enum {
+ NULL_VID_HANDLE = -1
+};
+
+class VideoManager {
+public:
+ VideoManager(PegasusEngine *vm);
+ ~VideoManager();
+
+ bool loadTimeZoneVideo(const Common::String &filename);
+ void drawTimeZoneVideoFrame(uint32 time);
+ void playTimeZoneVideoSegment(uint32 startTime, uint32 endTime);
+
+ // Generic movie functions
+ void playMovie(Common::String filename, uint16 x = 0, uint16 y = 0);
+ void playMovieCentered(Common::String filename);
+ VideoHandle playBackgroundMovie(Common::String filename, int x = 0, int y = 0, bool loop = false);
+ bool updateBackgroundMovies();
+ void pauseVideos();
+ void resumeVideos();
+ void stopVideos();
+ void waitUntilMovieEnds(VideoHandle videoHandle);
+
+ void seekToTime(VideoHandle handle, uint32 time);
+
+ // Helper functions
+ void copyFrameToScreen(const Graphics::Surface *frame, int width, int height, int x, int y);
+
+private:
+ PegasusEngine *_vm;
+
+ Video::QuickTimeDecoder *_timeZoneVideo;
+
+ // Keep tabs on any videos playing
+ Common::Array<VideoEntry> _videoStreams;
+ uint32 _pauseStart;
+};
+
+} // End of namespace Pegasus
+
+#endif