diff options
Diffstat (limited to 'engines/pegasus')
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 |