diff options
Diffstat (limited to 'engines')
44 files changed, 4631 insertions, 0 deletions
diff --git a/engines/engines.mk b/engines/engines.mk index 063ed75919..a822ab4ba3 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -126,6 +126,11 @@ DEFINES += -DENABLE_PARALLACTION=$(ENABLE_PARALLACTION)  MODULES += engines/parallaction  endif +ifdef ENABLE_PEGASUS +DEFINES += -DENABLE_PEGASUS=$(ENABLE_PEGASUS) +MODULES += engines/pegasus +endif +  ifdef ENABLE_QUEEN  DEFINES += -DENABLE_QUEEN=$(ENABLE_QUEEN)  MODULES += engines/queen 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  | 
