[Scummvm-cvs-logs] SF.net SVN: scummvm:[33260] scummvm/trunk/engines/parallaction

peres001 at users.sourceforge.net peres001 at users.sourceforge.net
Thu Jul 24 11:24:33 CEST 2008


Revision: 33260
          http://scummvm.svn.sourceforge.net/scummvm/?rev=33260&view=rev
Author:   peres001
Date:     2008-07-24 09:24:32 +0000 (Thu, 24 Jul 2008)

Log Message:
-----------
* Moved end intro and end game sequences code to gui.
* Rewrote all gui code to be run inside the main loop
* Added code to avoid crashes when a scene with no standard background is drawn

Modified Paths:
--------------
    scummvm/trunk/engines/parallaction/callables_ns.cpp
    scummvm/trunk/engines/parallaction/graphics.cpp
    scummvm/trunk/engines/parallaction/graphics.h
    scummvm/trunk/engines/parallaction/gui_ns.cpp
    scummvm/trunk/engines/parallaction/input.cpp
    scummvm/trunk/engines/parallaction/input.h
    scummvm/trunk/engines/parallaction/parallaction.cpp
    scummvm/trunk/engines/parallaction/parallaction.h
    scummvm/trunk/engines/parallaction/parallaction_ns.cpp

Modified: scummvm/trunk/engines/parallaction/callables_ns.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/callables_ns.cpp	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/callables_ns.cpp	2008-07-24 09:24:32 UTC (rev 33260)
@@ -37,18 +37,6 @@
 
 namespace Parallaction {
 
-// part completion messages
-static const char *endMsg0[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
-static const char *endMsg1[] = {"HAI FINITO QUESTA PARTE", "TU AS COMPLETE' CETTE AVENTURE", "YOU HAVE COMPLETED THIS PART", "DU HAST EIN ABENTEUER ERFOLGREICH"};
-static const char *endMsg2[] = {"ORA COMPLETA IL RESTO ", "AVEC SUCCES.",  "NOW GO ON WITH THE REST OF", "ZU ENDE GEFUHRT"};
-static const char *endMsg3[] = {"DELL' AVVENTURA",  "CONTINUE AVEC LES AUTRES", "THIS ADVENTURE", "MACH' MIT DEN ANDEREN WEITER"};
-// game completion messages
-static const char *endMsg4[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
-static const char *endMsg5[] = {"HAI FINITO LE TRE PARTI", "TU AS COMPLETE' LES TROIS PARTIES", "YOU HAVE COMPLETED THE THREE PARTS", "DU HAST DREI ABENTEURE ERFOLGREICH"};
-static const char *endMsg6[] = {"DELL' AVVENTURA", "DE L'AVENTURE", "OF THIS ADVENTURE", "ZU ENDE GEFUHRT"};
-static const char *endMsg7[] = {"ED ORA IL GRAN FINALE ", "ET MAINTENANT LE GRAND FINAL", "NOW THE GREAT FINAL", "UND YETZT DER GROSSE SCHLUSS!"};
-
-
 /*
 	intro callables data members
 */
@@ -143,18 +131,6 @@
 	0x00e0, 0x007b, 0x00e0, 0x0077
 };
 
-struct Credit {
-	const char *_role;
-	const char *_name;
-} _credits[] = {
-	{"Music and Sound Effects", "MARCO CAPRELLI"},
-	{"PC Version", "RICCARDO BALLARINO"},
-	{"Project Manager", "LOVRANO CANEPA"},
-	{"Production", "BRUNO BOZ"},
-	{"Special Thanks to", "LUIGI BENEDICENTI - GILDA and DANILO"},
-	{"Copyright 1992 Euclidea s.r.l ITALY", "All rights reserved"}
-};
-
 /*
 	game callables
 */
@@ -376,40 +352,13 @@
 	setPartComplete(_char);
 
 	cleanInventory();
+	cleanupGame();
+
 	_gfx->setPalette(_gfx->_palette);
 
-	uint id[4];
+	startEndPartSequence();
 
-	if (allPartsComplete()) {
-		id[0] = _gfx->createLabel(_menuFont, endMsg4[_language], 1);
-		id[1] = _gfx->createLabel(_menuFont, endMsg5[_language], 1);
-		id[2] = _gfx->createLabel(_menuFont, endMsg6[_language], 1);
-		id[3] = _gfx->createLabel(_menuFont, endMsg7[_language], 1);
-	} else {
-		id[0] = _gfx->createLabel(_menuFont, endMsg0[_language], 1);
-		id[1] = _gfx->createLabel(_menuFont, endMsg1[_language], 1);
-		id[2] = _gfx->createLabel(_menuFont, endMsg2[_language], 1);
-		id[3] = _gfx->createLabel(_menuFont, endMsg3[_language], 1);
-	}
 
-	_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 70);
-	_gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 100);
-	_gfx->showLabel(id[2], CENTER_LABEL_HORIZONTAL, 130);
-	_gfx->showLabel(id[3], CENTER_LABEL_HORIZONTAL, 160);
-
-	_gfx->updateScreen();
-	_input->waitForButtonEvent(kMouseLeftUp);
-
-	_gfx->freeLabels();
-
-	if (allPartsComplete()) {
-		scheduleLocationSwitch("estgrotta.drki");
-	} else {
-		selectStartLocation();
-	}
-
-	cleanupGame();
-
 	return;
 }
 
@@ -475,43 +424,7 @@
 }
 
 void Parallaction_ns::_c_endIntro(void *parm) {
-
-	debugC(1, kDebugExec, "endIntro()");
-
-	uint id[2];
-	for (uint16 _si = 0; _si < 6; _si++) {
-		id[0] = _gfx->createLabel(_menuFont, _credits[_si]._role, 1);
-		id[1] = _gfx->createLabel(_menuFont, _credits[_si]._name, 1);
-
-		_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 80);
-		_gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 100);
-
-		_gfx->updateScreen();
-
-		_input->waitForButtonEvent(kMouseLeftUp, 5500);
-
-		_gfx->freeLabels();
-	}
-	debugC(1, kDebugExec, "endIntro(): done showing credits");
-
-	_soundMan->stopMusic();
-
-	if ((getFeatures() & GF_DEMO) == 0) {
-
-		id[0] = _gfx->createLabel(_menuFont, "CLICK MOUSE BUTTON TO START", 1);
-		_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 80);
-		_gfx->updateScreen();
-		_input->waitForButtonEvent(kMouseLeftUp);
-		_gfx->freeLabels();
-		_engineFlags &= ~kEngineBlockInput;
-		selectStartLocation();
-		cleanupGame();
-	} else {
-		_gfx->updateScreen();
-		_input->waitForButtonEvent(kMouseLeftUp);
-	}
-
-	return;
+	startCreditSequence();
 }
 
 void Parallaction_ns::_c_moveSheet(void *parm) {

Modified: scummvm/trunk/engines/parallaction/graphics.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/graphics.cpp	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/graphics.cpp	2008-07-24 09:24:32 UTC (rev 33260)
@@ -352,29 +352,30 @@
 }
 
 void Gfx::beginFrame() {
+	_skipBackground = (_backgroundInfo.bg.pixels == 0);	// don't render frame if background is missing
 
-	int32 oldBackgroundMode = _varBackgroundMode;
-	_varBackgroundMode = getVar("background_mode");
-
-	if (oldBackgroundMode != _varBackgroundMode) {
-		switch (_varBackgroundMode) {
-		case 1:
-			_bitmapMask.free();
-			break;
-		case 2:
-			_bitmapMask.create(_backgroundInfo.width, _backgroundInfo.height, 1);
-			byte *data = (byte*)_bitmapMask.pixels;
-			for (uint y = 0; y < _bitmapMask.h; y++) {
-				for (uint x = 0; x < _bitmapMask.w; x++) {
-					*data++ = _backgroundInfo.mask.getValue(x, y);
+	if (!_skipBackground) {
+		int32 oldBackgroundMode = _varBackgroundMode;
+		_varBackgroundMode = getVar("background_mode");
+		if (oldBackgroundMode != _varBackgroundMode) {
+			switch (_varBackgroundMode) {
+			case 1:
+				_bitmapMask.free();
+				break;
+			case 2:
+				_bitmapMask.create(_backgroundInfo.width, _backgroundInfo.height, 1);
+				byte *data = (byte*)_bitmapMask.pixels;
+				for (uint y = 0; y < _bitmapMask.h; y++) {
+					for (uint x = 0; x < _bitmapMask.w; x++) {
+						*data++ = _backgroundInfo.mask.getValue(x, y);
+					}
 				}
+				break;
 			}
-			break;
 		}
 	}
 
-
-	if (_vm->_screenWidth >= _backgroundInfo.width) {
+	if (_skipBackground || (_vm->_screenWidth >= _backgroundInfo.width)) {
 		_varScrollX = 0;
 	} else {
 		_varScrollX = getVar("scroll_x");
@@ -399,25 +400,26 @@
 
 void Gfx::updateScreen() {
 
-	// background may not cover the whole screen, so adjust bulk update size
-	uint w = MIN(_vm->_screenWidth, (int32)_backgroundInfo.width);
-	uint h = MIN(_vm->_screenHeight, (int32)_backgroundInfo.height);
+	if (!_skipBackground) {
+		// background may not cover the whole screen, so adjust bulk update size
+		uint w = MIN(_vm->_screenWidth, (int32)_backgroundInfo.width);
+		uint h = MIN(_vm->_screenHeight, (int32)_backgroundInfo.height);
 
-	byte *backgroundData = 0;
-	uint16 backgroundPitch = 0;
-	switch (_varBackgroundMode) {
-	case 1:
-		backgroundData = (byte*)_backgroundInfo.bg.getBasePtr(_varScrollX, 0);
-		backgroundPitch = _backgroundInfo.bg.pitch;
-		break;
-	case 2:
-		backgroundData = (byte*)_bitmapMask.getBasePtr(_varScrollX, 0);
-		backgroundPitch = _bitmapMask.pitch;
-		break;
+		byte *backgroundData = 0;
+		uint16 backgroundPitch = 0;
+		switch (_varBackgroundMode) {
+		case 1:
+			backgroundData = (byte*)_backgroundInfo.bg.getBasePtr(_varScrollX, 0);
+			backgroundPitch = _backgroundInfo.bg.pitch;
+			break;
+		case 2:
+			backgroundData = (byte*)_bitmapMask.getBasePtr(_varScrollX, 0);
+			backgroundPitch = _bitmapMask.pitch;
+			break;
+		}
+		g_system->copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo.x, _backgroundInfo.y, w, h);
 	}
-	g_system->copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo.x, _backgroundInfo.y, w, h);
 
-
 	_varRenderMode = _varAnimRenderMode;
 
 	// TODO: transform objects coordinates to be drawn with scrolling
@@ -847,6 +849,8 @@
 		_palette.clone(_backgroundInfo.palette);
 	} else {
 		_disk->loadSlide(_backgroundInfo, name);
+		for (uint i = 0; i < 6; i++)
+			_backgroundInfo.ranges[i]._flags = 0;	// disable palette cycling for slides
 		setPalette(_backgroundInfo.palette);
 	}
 

Modified: scummvm/trunk/engines/parallaction/graphics.h
===================================================================
--- scummvm/trunk/engines/parallaction/graphics.h	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/graphics.h	2008-07-24 09:24:32 UTC (rev 33260)
@@ -553,6 +553,8 @@
 	Parallaction*		_vm;
 	bool				_halfbrite;
 
+	bool 				_skipBackground;
+
 	Common::Point		_hbCirclePos;
 	int				_hbCircleRadius;
 

Modified: scummvm/trunk/engines/parallaction/gui_ns.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/gui_ns.cpp	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/gui_ns.cpp	2008-07-24 09:24:32 UTC (rev 33260)
@@ -24,6 +24,7 @@
  */
 
 #include "common/system.h"
+#include "common/hashmap.h"
 
 #include "parallaction/input.h"
 #include "parallaction/parallaction.h"
@@ -32,318 +33,633 @@
 
 namespace Parallaction {
 
-const char *introMsg1[] = {
-	"INSERISCI IL CODICE",
-	"ENTREZ CODE",
-	"ENTER CODE",
-	"GIB DEN KODE EIN"
-};
 
-const char *introMsg2[] = {
-	"CODICE ERRATO",
-	"CODE ERRONE",
-	"WRONG CODE",
-	"GIB DEN KODE EIN"
-};
+class MenuInputState;
 
-const char *introMsg3[] = {
-	"PRESS LEFT MOUSE BUTTON",
-	"TO SEE INTRO",
-	"PRESS RIGHT MOUSE BUTTON",
-	"TO START"
-};
+class MenuInputHelper {
+	typedef	Common::HashMap<Common::String, MenuInputState*> StateMap;
 
-const char *newGameMsg[] = {
-	"NUOVO GIOCO",
-	"NEUF JEU",
-	"NEW GAME",
-	"NEUES SPIEL"
-};
+	StateMap	_map;
+	MenuInputState	*_state;
+	MenuInputState *_newState;
 
-const char *loadGameMsg[] = {
-	"GIOCO SALVATO",
-	"JEU SAUVE'",
-	"SAVED GAME",
-	"SPIEL GESPEICHERT"
-};
+public:
+	MenuInputHelper() : _state(0) {
+	}
 
+	~MenuInputHelper();
 
-#define BLOCK_WIDTH		16
-#define BLOCK_HEIGHT	24
+	void setState(const Common::String &name) {
+		// bootstrap routine
+		_newState = getState(name);
+		assert(_newState);
+	}
 
-#define BLOCK_X			112
-#define BLOCK_Y			130
+	void addState(const Common::String &name, MenuInputState *state) {
+		_map.setVal(name, state);
+	}
 
-#define BLOCK_SELECTION_X		  (BLOCK_X-1)
-#define BLOCK_SELECTION_Y		  (BLOCK_Y-1)
+	MenuInputState *getState(const Common::String &name) {
+		return _map[name];
+	}
 
-#define BLOCK_X_OFFSET	(BLOCK_WIDTH+1)
-#define BLOCK_Y_OFFSET	9
+	bool run();
+};
 
-//	destination slots for code blocks
-//
-#define SLOT_X			61
-#define SLOT_Y			64
-#define SLOT_WIDTH		(BLOCK_WIDTH+2)
+class MenuInputState {
 
-#define PASSWORD_LEN	6
+protected:
+	MenuInputHelper *_helper;
 
-#define CHAR_DINO	0
-#define CHAR_DONNA	1
-#define CHAR_DOUGH	2
+public:
+	MenuInputState(const Common::String &name, MenuInputHelper *helper) : _helper(helper), _name(name) {
+		debugC(3, kDebugExec, "MenuInputState(%s)", name.c_str());
+		_helper->addState(name, this);
+	}
 
-static const uint16 _amigaKeys[][PASSWORD_LEN] = {
-	{ 5, 3, 6, 2, 2, 7 },		// dino
-	{ 0, 3, 6, 2, 2, 6 },		// donna
-	{ 1, 3 ,7, 2, 4, 6 }		// dough
-};
+	Common::String	_name;
 
-static const uint16 _pcKeys[][PASSWORD_LEN] = {
-	{ 5, 3, 6, 1, 4, 7 },		// dino
-	{ 0, 2, 8, 5, 5, 1 },		// donna
-	{ 1, 7 ,7, 2, 2, 6 }		// dough
-};
+	virtual ~MenuInputState() { }
 
-static const char *_charStartLocation[] = {
-	"test.dino",
-	"test.donna",
-	"test.dough"
+	virtual MenuInputState* run() = 0;
+	virtual void enter() = 0;
 };
 
-enum {
-	NEW_GAME,
-	LOAD_GAME
-};
+bool MenuInputHelper::run() {
+	if (_newState == 0) {
+		debugC(3, kDebugExec, "MenuInputHelper has set NULL state");
+		return false;
+	}
 
-enum {
-	START_DEMO,
-	START_INTRO,
-	GAME_LOADED,
-	SELECT_CHARACTER
-};
+	if (_newState != _state) {
+		debugC(3, kDebugExec, "MenuInputHelper changing state to '%s'", _newState->_name.c_str());
 
-void Parallaction_ns::guiStart() {
+		_newState->enter();
+		_state = _newState;
+	}
 
-	_disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
+	_newState = _state->run();
 
-	guiSplash();
+	return true;
+}
 
-	_language = guiChooseLanguage();
-	_disk->setLanguage(_language);
+MenuInputHelper::~MenuInputHelper() {
+	StateMap::iterator b = _map.begin();
+	for ( ; b != _map.end(); b++) {
+		delete b->_value;
+	}
+	_map.clear();
+}
 
-	int event;
 
-	if (getFeatures() & GF_DEMO) {
-		event = START_DEMO;
-	} else {
-		if (guiSelectGame() == NEW_GAME) {
-			event = guiNewGame();
-		} else {
-			event = loadGame() ? GAME_LOADED : START_INTRO;
+class SplashInputState : public MenuInputState {
+protected:
+	Common::String _slideName;
+	uint32 _timeOut;
+	Common::String _nextState;
+	uint32	_startTime;
+
+	Parallaction_ns *_vm;
+
+public:
+	SplashInputState(Parallaction_ns *vm, const Common::String &name, MenuInputHelper *helper) : MenuInputState(name, helper), _vm(vm)  {
+	}
+
+	virtual MenuInputState* run() {
+		uint32 curTime = g_system->getMillis();
+		if (curTime - _startTime > _timeOut) {
+			_vm->freeBackground();
+			return _helper->getState(_nextState);
 		}
+		return this;
 	}
 
-	switch (event) {
-	case START_DEMO:
-		strcpy(_location._name, "fognedemo.dough");
-		break;
+	virtual void enter() {
+		_vm->showSlide(_slideName.c_str());
+		_startTime = g_system->getMillis();
+	}
+};
 
-	case START_INTRO:
-		strcpy(_location._name, "fogne.dough");
-		break;
+class SplashInputState0 : public SplashInputState {
 
-	case GAME_LOADED:
-		// nothing to do here
-		return;
+public:
+	SplashInputState0(Parallaction_ns *vm, MenuInputHelper *helper) : SplashInputState(vm, "intro0", helper)  {
+		_slideName = "intro";
+		_timeOut = 2000;
+		_nextState = "intro1";
+	}
+};
 
-	case SELECT_CHARACTER:
-		selectStartLocation();
-		break;
+class SplashInputState1 : public SplashInputState {
 
+public:
+	SplashInputState1(Parallaction_ns *vm, MenuInputHelper *helper) : SplashInputState(vm, "intro1", helper) {
+		_slideName = "minintro";
+		_timeOut = 2000;
+		_nextState = "chooselanguage";
 	}
+};
 
-	return;
-}
 
-void Parallaction_ns::selectStartLocation() {
-	_inTestResult = false;
+class ChooseLanguageInputState : public MenuInputState {
+	#define BLOCK_WIDTH		16
+	#define BLOCK_HEIGHT	24
 
-	int character = guiSelectCharacter();
-	if (character == -1)
-		error("invalid character selected from menu screen");
+	#define BLOCK_X			112
+	#define BLOCK_Y			130
 
-	scheduleLocationSwitch(_charStartLocation[character]);
-}
+	#define BLOCK_SELECTION_X		  (BLOCK_X-1)
+	#define BLOCK_SELECTION_Y		  (BLOCK_Y-1)
 
+	#define BLOCK_X_OFFSET	(BLOCK_WIDTH+1)
+	#define BLOCK_Y_OFFSET	9
 
-void Parallaction_ns::guiSplash() {
+	//	destination slots for code blocks
+	//
+	#define SLOT_X			61
+	#define SLOT_Y			64
+	#define SLOT_WIDTH		(BLOCK_WIDTH+2)
 
-	showSlide("intro");
-	_gfx->updateScreen();
-	g_system->delayMillis(2000);
-	freeBackground();
+	int	_language;
+	bool	_allowChoice;
+	Common::String _nextState;
 
-	showSlide("minintro");
-	_gfx->updateScreen();
-	g_system->delayMillis(2000);
-	freeBackground();
-}
+	static const Common::Rect _dosLanguageSelectBlocks[4];
+	static const Common::Rect _amigaLanguageSelectBlocks[4];
+	const Common::Rect *_blocks;
 
-int Parallaction_ns::guiNewGame() {
+	Parallaction_ns *_vm;
 
-	const char **v14 = introMsg3;
+public:
+	ChooseLanguageInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("chooselanguage", helper), _vm(vm) {
+		_allowChoice = false;
+		_nextState = "selectgame";
 
-	_disk->selectArchive("disk1");
+		if (_vm->getPlatform() == Common::kPlatformAmiga) {
+			if (!(_vm->getFeatures() & GF_LANG_MULT)) {
+				if (_vm->getFeatures() & GF_DEMO) {
+					_language = 1;	// Amiga Demo supports English
+					_nextState = "startdemo";
+					return;
+				} else {
+					_language = 0;	// The only other non multi-lingual version just supports Italian
+					return;
+				}
+			}
 
-	setBackground("test", NULL, NULL);
+			_blocks = _amigaLanguageSelectBlocks;
+		} else {
+			_blocks = _dosLanguageSelectBlocks;
+		}
 
-	_gfx->updateScreen();
+		_language = -1;
+		_allowChoice = true;
+	}
 
-	uint id[4];
-	id[0] = _gfx->createLabel(_menuFont, v14[0], 1);
-	id[1] = _gfx->createLabel(_menuFont, v14[1], 1);
-	id[2] = _gfx->createLabel(_menuFont, v14[2], 1);
-	id[3] = _gfx->createLabel(_menuFont, v14[3], 1);
-	_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 50);
-	_gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 70);
-	_gfx->showLabel(id[2], CENTER_LABEL_HORIZONTAL, 100);
-	_gfx->showLabel(id[3], CENTER_LABEL_HORIZONTAL, 120);
+	virtual MenuInputState* run() {
+		if (!_allowChoice) {
+			_vm->setInternLanguage(_language);
+			return _helper->getState(_nextState);
+		}
 
-	_input->showCursor(false);
+		int event = _vm->_input->getLastButtonEvent();
+		if (event != kMouseLeftUp) {
+			return this;
+		}
 
-	_gfx->updateScreen();
+		Common::Point p;
+		_vm->_input->getCursorPos(p);
 
-	_input->waitForButtonEvent(kMouseLeftUp | kMouseRightUp);
-	uint32 event = _input->getLastButtonEvent();
+		for (uint16 i = 0; i < 4; i++) {
+			if (_blocks[i].contains(p)) {
+				_vm->setInternLanguage(i);
+				_vm->beep();
+				_vm->_gfx->freeLabels();
+				return _helper->getState(_nextState);
+			}
+		}
 
-	_input->showCursor(true);
+		return this;
+	}
 
-	_gfx->freeLabels();
+	virtual void enter() {
+		if (!_allowChoice) {
+			return;
+		}
 
-	if (event != kMouseRightUp) {
-		return START_INTRO;
+		// user can choose language in this version
+		_vm->showSlide("lingua");
+
+		uint id = _vm->_gfx->createLabel(_vm->_introFont, "SELECT LANGUAGE", 1);
+		_vm->_gfx->showLabel(id, 60, 30);
+
+		_vm->setArrowCursor();
 	}
+};
 
-	return SELECT_CHARACTER;
-}
-
-static const Common::Rect _dosLanguageSelectBlocks[4] = {
+const Common::Rect ChooseLanguageInputState::_dosLanguageSelectBlocks[4] = {
 	Common::Rect(  80, 110, 128, 180 ),	// Italian
 	Common::Rect( 129,  85, 177, 155 ),	// French
 	Common::Rect( 178,  60, 226, 130 ),	// English
 	Common::Rect( 227,  35, 275, 105 )	// German
 };
 
-static const Common::Rect _amigaLanguageSelectBlocks[4] = {
+const Common::Rect ChooseLanguageInputState::_amigaLanguageSelectBlocks[4] = {
 	Common::Rect(  -1,  -1,  -1,  -1 ),	// Italian: not supported by Amiga multi-lingual version
 	Common::Rect( 129,  85, 177, 155 ),	// French
 	Common::Rect( 178,  60, 226, 130 ),	// English
 	Common::Rect( 227,  35, 275, 105 )	// German
 };
 
+class SelectGameInputState : public MenuInputState {
 
-uint16 Parallaction_ns::guiChooseLanguage() {
+	int _choice, _oldChoice;
+	Common::String _nextState[2];
 
-	const Common::Rect *blocks;
+	uint	_labels[2];
 
-	if (getPlatform() == Common::kPlatformAmiga) {
-		if (!(getFeatures() & GF_LANG_MULT)) {
-			if (getFeatures() & GF_DEMO) {
-				return 1;		// Amiga Demo supports English
-			} else {
-				return 0;		// The only other non multi-lingual version just supports Italian
+	Parallaction_ns *_vm;
+
+	static const char *newGameMsg[4];
+	static const char *loadGameMsg[4];
+
+public:
+	SelectGameInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("selectgame", helper), _vm(vm) {
+		_choice = 0;
+		_oldChoice = -1;
+
+		_nextState[0] = "newgame";
+		_nextState[1] = "loadgame";
+	}
+
+
+	virtual MenuInputState *run() {
+		int event = _vm->_input->getLastButtonEvent();
+
+		if (event == kMouseLeftUp) {
+			_vm->_gfx->freeLabels();
+			return _helper->getState(_nextState[_choice]);
+		}
+
+		Common::Point p;
+		_vm->_input->getCursorPos(p);
+		_choice = (p.x > 160) ? 1 : 0;
+
+		if (_choice != _oldChoice) {
+			if (_oldChoice != -1)
+				_vm->_gfx->hideLabel(_labels[_oldChoice]);
+
+			if (_choice != -1)
+				_vm->_gfx->showLabel(_labels[_choice], 60, 30);
+
+			_oldChoice = _choice;
+		}
+
+		return this;
+	}
+
+	virtual void enter() {
+		_vm->showSlide("restore");
+
+		_labels[0] = _vm->_gfx->createLabel(_vm->_introFont, newGameMsg[_vm->getInternLanguage()], 1);
+		_labels[1] = _vm->_gfx->createLabel(_vm->_introFont, loadGameMsg[_vm->getInternLanguage()], 1);
+	}
+
+};
+
+const char *SelectGameInputState::newGameMsg[4] = {
+	"NUOVO GIOCO",
+	"NEUF JEU",
+	"NEW GAME",
+	"NEUES SPIEL"
+};
+
+const char *SelectGameInputState::loadGameMsg[4] = {
+	"GIOCO SALVATO",
+	"JEU SAUVE'",
+	"SAVED GAME",
+	"SPIEL GESPEICHERT"
+};
+
+
+
+class LoadGameInputState : public MenuInputState {
+	bool _result;
+	Parallaction_ns *_vm;
+
+public:
+	LoadGameInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("loadgame", helper), _vm(vm) { }
+
+	virtual MenuInputState* run() {
+		if (!_result) {
+			_vm->scheduleLocationSwitch("fogne.dough");
+		}
+		return 0;
+	}
+
+	virtual void enter() {
+		_result = _vm->loadGame();
+	}
+};
+
+
+
+class NewGameInputState : public MenuInputState {
+	Parallaction_ns *_vm;
+
+	static const char *introMsg3[4];
+
+public:
+	NewGameInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("newgame", helper), _vm(vm) {
+	}
+
+	virtual MenuInputState* run() {
+		int event = _vm->_input->getLastButtonEvent();
+
+		if (event == kMouseLeftUp || event == kMouseRightUp) {
+			_vm->_input->showCursor(true);
+			_vm->_gfx->freeLabels();
+
+			if (event == kMouseLeftUp) {
+				_vm->scheduleLocationSwitch("fogne.dough");
+				return 0;
 			}
+
+			return _helper->getState("selectcharacter");
 		}
 
-		blocks = _amigaLanguageSelectBlocks;
-	} else {
-		blocks = _dosLanguageSelectBlocks;
+		return this;
 	}
 
-	// user can choose language in dos version
-	showSlide("lingua");
+	virtual void enter() {
+		_vm->_disk->selectArchive("disk1");
+		_vm->setBackground("test", NULL, NULL);
+		_vm->_input->showCursor(false);
 
-	uint id = _gfx->createLabel(_introFont, "SELECT LANGUAGE", 1);
-	_gfx->showLabel(id, 60, 30);
+		uint id[4];
+		id[0] = _vm->_gfx->createLabel(_vm->_menuFont, introMsg3[0], 1);
+		id[1] = _vm->_gfx->createLabel(_vm->_menuFont, introMsg3[1], 1);
+		id[2] = _vm->_gfx->createLabel(_vm->_menuFont, introMsg3[2], 1);
+		id[3] = _vm->_gfx->createLabel(_vm->_menuFont, introMsg3[3], 1);
+		_vm->_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 50);
+		_vm->_gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 70);
+		_vm->_gfx->showLabel(id[2], CENTER_LABEL_HORIZONTAL, 100);
+		_vm->_gfx->showLabel(id[3], CENTER_LABEL_HORIZONTAL, 120);
+	}
+};
 
-	setArrowCursor();
+const char *NewGameInputState::introMsg3[4] = {
+	"PRESS LEFT MOUSE BUTTON",
+	"TO SEE INTRO",
+	"PRESS RIGHT MOUSE BUTTON",
+	"TO START"
+};
 
-	Common::Point p;
 
-	int selection = -1;
-	int event;
-	while (selection == -1) {
-		_input->readInput();
-		event = _input->getLastButtonEvent();
 
-		if (event == kMouseLeftUp) {
-			_input->getCursorPos(p);
-			for (uint16 i = 0; i < 4; i++) {
-				if (blocks[i].contains(p)) {
-					selection = i;
-					break;
-				}
+class StartDemoInputState : public MenuInputState {
+	Parallaction_ns *_vm;
+
+public:
+	StartDemoInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("startdemo", helper), _vm(vm) {
+	}
+
+	virtual MenuInputState* run() {
+		_vm->scheduleLocationSwitch("fognedemo.dough");
+		return 0;
+	}
+
+	virtual void enter() {	}
+};
+
+class SelectCharacterInputState : public MenuInputState {
+
+	#define PASSWORD_LEN	6
+
+	#define CHAR_DINO	0
+	#define CHAR_DONNA	1
+	#define CHAR_DOUGH	2
+
+	static const Common::Rect codeSelectBlocks[9];
+	static const Common::Rect codeTrueBlocks[9];
+
+	Parallaction_ns *_vm;
+
+	int guiGetSelectedBlock(const Common::Point &p) {
+
+		int selection = -1;
+
+		for (uint16 i = 0; i < 9; i++) {
+			if (codeSelectBlocks[i].contains(p)) {
+				selection = i;
+				break;
 			}
 		}
 
-		_gfx->updateScreen();
+		if ((selection != -1) && (_vm->getPlatform() == Common::kPlatformAmiga)) {
+			_vm->_gfx->invertBackground(codeTrueBlocks[selection]);
+			_vm->_gfx->updateScreen();
+			_vm->beep();
+			g_system->delayMillis(100);
+			_vm->_gfx->invertBackground(codeTrueBlocks[selection]);
+			_vm->_gfx->updateScreen();
+		}
+
+		return selection;
 	}
 
-	beep();
+	byte	_points[3];
+	bool 	_fail;
+	const uint16 (*_keys)[PASSWORD_LEN];
+	Graphics::Surface _block;
+	Graphics::Surface _emptySlots;
 
-	_gfx->freeLabels();
+	uint	_labels[2];
+	uint	_len;
+	uint32	_startTime;
 
-	return selection;
-}
+	enum {
+		CHOICE,
+		FAIL,
+		SUCCESS,
+		DELAY
+	};
 
+	uint	_state;
 
+	static const char *introMsg1[4];
+	static const char *introMsg2[4];
 
-uint16 Parallaction_ns::guiSelectGame() {
-//	  printf("selectGame()\n");
+	static const uint16 _amigaKeys[3][PASSWORD_LEN];
+	static const uint16 _pcKeys[3][PASSWORD_LEN];
+	static const char *_charStartLocation[3];
 
-	showSlide("restore");
 
-	uint16 _si = 0;
-	uint16 _di = 3;
+public:
+	SelectCharacterInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("selectcharacter", helper), _vm(vm) {
+		_keys = (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT)) ? _amigaKeys : _pcKeys;
+		_block.create(BLOCK_WIDTH, BLOCK_HEIGHT, 1);
+	}
 
-	uint id0, id1;
-	id0 = _gfx->createLabel(_introFont, loadGameMsg[_language], 1);
-	id1 = _gfx->createLabel(_introFont, newGameMsg[_language], 1);
+	void cleanup() {
+		_points[0] = _points[1] = _points[2] = 0;
+		_vm->_gfx->hideLabel(_labels[1]);
+		_vm->_gfx->showLabel(_labels[0], 60, 30);
+		_fail = false;
+		_len = 0;
+	}
 
-	Common::Point p;
+	void delay() {
+		if (g_system->getMillis() - _startTime < 2000) {
+			return;
+		}
+		cleanup();
+		_state = CHOICE;
+	}
 
-	uint32 event = kMouseNone;
-	while (event != kMouseLeftUp) {
+	void choice() {
+		int event = _vm->_input->getLastButtonEvent();
+		if (event != kMouseLeftUp) {
+			return;
+		}
 
-		_input->readInput();
-		_input->getCursorPos(p);
-		event = _input->getLastButtonEvent();
+		Common::Point p;
+		_vm->_input->getCursorPos(p);
+		int _si = guiGetSelectedBlock(p);
 
-		_si = (p.x > 160) ? 1 : 0;
+		if (_si != -1) {
+			_vm->_gfx->grabBackground(codeTrueBlocks[_si], _block);
+			_vm->_gfx->patchBackground(_block, _len * SLOT_WIDTH + SLOT_X, SLOT_Y, false);
 
-		if (_si != _di) {
-			if (_si != 0) {
-				// load a game
-				_gfx->hideLabel(id1);
-				_gfx->showLabel(id0, 60, 30);
-			} else {
-				// new game
-				_gfx->hideLabel(id0);
-				_gfx->showLabel(id1, 60, 30);
+			if (_keys[0][_len] != _si && _keys[1][_len] != _si && _keys[2][_len] != _si) {
+				_fail = true;
 			}
-			_di = _si;
+
+			// build user preference
+			_points[0] += (_keys[0][_len] == _si);
+			_points[1] += (_keys[1][_len] == _si);
+			_points[2] += (_keys[2][_len] == _si);
+
+			_len++;
 		}
 
-		_gfx->updateScreen();
-		g_system->delayMillis(30);
+		if (_len == PASSWORD_LEN) {
+			_state = _fail ? FAIL : SUCCESS;
+		}
 	}
 
-	_gfx->freeLabels();
+	void fail() {
+		_vm->_gfx->patchBackground(_emptySlots, SLOT_X, SLOT_Y, false);
+		_vm->_gfx->hideLabel(_labels[0]);
+		_vm->_gfx->showLabel(_labels[1], 60, 30);
+		_startTime = g_system->getMillis();
+		_state = DELAY;
+	}
 
-	return _si ? LOAD_GAME : NEW_GAME;
-}
+	void success() {
+		_vm->_gfx->freeLabels();
+		_vm->_gfx->setBlackPalette();
+		_emptySlots.free();
 
-static const Common::Rect codeSelectBlocks[9] = {
+		// actually select character
+		int character = -1;
+		if (_points[0] >= _points[1] && _points[0] >= _points[2]) {
+			character = CHAR_DINO;
+		} else
+		if (_points[1] >= _points[0] && _points[1] >= _points[2]) {
+			character = CHAR_DONNA;
+		} else
+		if (_points[2] >= _points[0] && _points[2] >= _points[1]) {
+			character = CHAR_DOUGH;
+		} else {
+			error("If you read this, either your CPU or transivity is broken (we believe the former).");
+		}
+
+		_vm->_inTestResult = false;
+		_vm->cleanupGame();
+		_vm->scheduleLocationSwitch(_charStartLocation[character]);
+	}
+
+	virtual MenuInputState* run() {
+		MenuInputState* nextState = this;
+
+		switch (_state) {
+		case DELAY:
+			delay();
+			break;
+
+		case CHOICE:
+			choice();
+			break;
+
+		case FAIL:
+			fail();
+			break;
+
+		case SUCCESS:
+			success();
+			nextState = 0;
+			break;
+
+		default:
+			error("unknown state in SelectCharacterInputState");
+		}
+
+		return nextState;
+	}
+
+	virtual void enter() {
+		_vm->setArrowCursor();
+		_vm->_soundMan->stopMusic();
+		_vm->_disk->selectArchive((_vm->getFeatures() & GF_DEMO) ? "disk0" : "disk1");
+		_vm->showSlide("password");
+
+		_emptySlots.create(BLOCK_WIDTH * 8, BLOCK_HEIGHT, 1);
+		Common::Rect rect(SLOT_X, SLOT_Y, SLOT_X + BLOCK_WIDTH * 8, SLOT_Y + BLOCK_HEIGHT);
+		_vm->_gfx->grabBackground(rect, _emptySlots);
+
+		_labels[0] = _vm->_gfx->createLabel(_vm->_introFont, introMsg1[_vm->getInternLanguage()], 1);
+		_labels[1] = _vm->_gfx->createLabel(_vm->_introFont, introMsg2[_vm->getInternLanguage()], 1);
+
+		cleanup();
+		_state = CHOICE;
+	}
+};
+
+const char *SelectCharacterInputState::introMsg1[4] = {
+	"INSERISCI IL CODICE",
+	"ENTREZ CODE",
+	"ENTER CODE",
+	"GIB DEN KODE EIN"
+};
+
+const char *SelectCharacterInputState::introMsg2[4] = {
+	"CODICE ERRATO",
+	"CODE ERRONE",
+	"WRONG CODE",
+	"GIB DEN KODE EIN"
+};
+
+const uint16 SelectCharacterInputState::_amigaKeys[][PASSWORD_LEN] = {
+	{ 5, 3, 6, 2, 2, 7 },		// dino
+	{ 0, 3, 6, 2, 2, 6 },		// donna
+	{ 1, 3 ,7, 2, 4, 6 }		// dough
+};
+
+const uint16 SelectCharacterInputState::_pcKeys[][PASSWORD_LEN] = {
+	{ 5, 3, 6, 1, 4, 7 },		// dino
+	{ 0, 2, 8, 5, 5, 1 },		// donna
+	{ 1, 7 ,7, 2, 2, 6 }		// dough
+};
+
+const char *SelectCharacterInputState::_charStartLocation[] = {
+	"test.dino",
+	"test.donna",
+	"test.dough"
+};
+
+
+const Common::Rect SelectCharacterInputState::codeSelectBlocks[9] = {
 	Common::Rect( 111, 129, 127, 153 ),		// na
 	Common::Rect( 128, 120, 144, 144 ),		// wa
 	Common::Rect( 145, 111, 161, 135 ),		// ra
@@ -355,7 +671,7 @@
 	Common::Rect( 247, 57, 263, 81 )		// ka
 };
 
-static const Common::Rect codeTrueBlocks[9] = {
+const Common::Rect SelectCharacterInputState::codeTrueBlocks[9] = {
 	Common::Rect( 112, 130, 128, 154 ),
 	Common::Rect( 129, 121, 145, 145 ),
 	Common::Rect( 146, 112, 162, 136 ),
@@ -368,151 +684,252 @@
 };
 
 
-int Parallaction_ns::guiGetSelectedBlock(const Common::Point &p) {
+class ShowCreditsInputState : public MenuInputState {
+	Parallaction_ns *_vm;
+	int	_current;
+	uint32 _startTime;
 
-	int selection = -1;
+	struct Credit {
+		const char *_role;
+		const char *_name;
+	};
 
-	for (uint16 i = 0; i < 9; i++) {
-		if (codeSelectBlocks[i].contains(p)) {
-			selection = i;
-			break;
-		}
+	static const Credit _credits[6];
+
+public:
+	ShowCreditsInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("showcredits", helper), _vm(vm) {
 	}
 
-	if ((selection != -1) && (getPlatform() == Common::kPlatformAmiga)) {
-		_gfx->invertBackground(codeTrueBlocks[selection]);
-		_gfx->updateScreen();
-		beep();
-		g_system->delayMillis(100);
-		_gfx->invertBackground(codeTrueBlocks[selection]);
-		_gfx->updateScreen();
+	void drawCurrentLabel() {
+		uint id[2];
+		id[0] = _vm->_gfx->createLabel(_vm->_menuFont, _credits[_current]._role, 1);
+		id[1] = _vm->_gfx->createLabel(_vm->_menuFont, _credits[_current]._name, 1);
+		_vm->_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 80);
+		_vm->_gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 100);
 	}
 
-	return selection;
-}
 
+	virtual MenuInputState* run() {
+		if (_current == -1) {
+			_startTime = g_system->getMillis();
+			_current = 0;
+			drawCurrentLabel();
+			return this;
+		}
 
-//
-//	character selection and protection
-//
-int Parallaction_ns::guiSelectCharacter() {
-	debugC(1, kDebugMenu, "Parallaction_ns::guiselectCharacter()");
+		int event = _vm->_input->getLastButtonEvent();
+		uint32 curTime = g_system->getMillis();
+		if ((event == kMouseLeftUp) || (curTime - _startTime > 5500)) {
+			_current++;
+			_startTime = curTime;
+			_vm->_gfx->freeLabels();
 
-	setArrowCursor();
-	_soundMan->stopMusic();
+			if (_current == 6) {
+				return _helper->getState("endintro");
+			}
 
-	_disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
+			drawCurrentLabel();
+		}
 
-	showSlide("password");
+		return this;
+	}
 
+	virtual void enter() {
+		_current = -1;
+	}
+};
 
-	const uint16 (*keys)[PASSWORD_LEN] = (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT)) ? _amigaKeys : _pcKeys;
-	uint16 _di = 0;
-	byte points[3] = { 0, 0, 0 };
+const ShowCreditsInputState::Credit ShowCreditsInputState::_credits[6] = {
+	{"Music and Sound Effects", "MARCO CAPRELLI"},
+	{"PC Version", "RICCARDO BALLARINO"},
+	{"Project Manager", "LOVRANO CANEPA"},
+	{"Production", "BRUNO BOZ"},
+	{"Special Thanks to", "LUIGI BENEDICENTI - GILDA and DANILO"},
+	{"Copyright 1992 Euclidea s.r.l ITALY", "All rights reserved"}
+};
 
-	bool fail;
+class EndIntroInputState : public MenuInputState {
+	Parallaction_ns *_vm;
+	bool _isDemo;
 
-	uint id[2];
-	id[0] = _gfx->createLabel(_introFont, introMsg1[_language], 1);
-	id[1] = _gfx->createLabel(_introFont, introMsg2[_language], 1);
+public:
+	EndIntroInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("endintro", helper), _vm(vm) {
+		_isDemo = (_vm->getFeatures() & GF_DEMO) != 0;
+	}
 
-	Graphics::Surface v14;
-	v14.create(BLOCK_WIDTH * 8, BLOCK_HEIGHT, 1);
-	Common::Rect rect(SLOT_X, SLOT_Y, SLOT_X + BLOCK_WIDTH * 8, SLOT_Y + BLOCK_HEIGHT);
-	_gfx->grabBackground(rect, v14);
+	virtual MenuInputState* run() {
 
-	Graphics::Surface block;
-	block.create(BLOCK_WIDTH, BLOCK_HEIGHT, 1);
+		int event = _vm->_input->getLastButtonEvent();
+		if (event != kMouseLeftUp) {
+			return this;
+		}
 
-	Common::Point p;
+		if (_isDemo) {
+			_engineFlags |= kEngineQuit;
+			return 0;
+		}
 
-	while (true) {
+		_vm->_gfx->freeLabels();
+		_engineFlags &= ~kEngineBlockInput;
+		return _helper->getState("selectcharacter");
+	}
 
-		points[0] = 0;
-		points[1] = 0;
-		points[2] = 0;
-		fail = false;
+	virtual void enter() {
+		_vm->_soundMan->stopMusic();
 
-		_gfx->hideLabel(id[1]);
-		_gfx->showLabel(id[0], 60, 30);
+		if (!_isDemo) {
+			int label = _vm->_gfx->createLabel(_vm->_menuFont, "CLICK MOUSE BUTTON TO START", 1);
+			_vm->_gfx->showLabel(label, CENTER_LABEL_HORIZONTAL, 80);
+		}
+	}
+};
 
-		_di = 0;
-		int event;
-		while (_di < PASSWORD_LEN) {
-			_input->readInput();
-			event = _input->getLastButtonEvent();
-			if (event == kMouseLeftUp) {
 
-				_input->getCursorPos(p);
+class EndPartInputState : public MenuInputState {
+	Parallaction_ns *_vm;
+	bool _allPartsComplete;
 
-				int _si = guiGetSelectedBlock(p);
+	// part completion messages
+	static const char *endMsg0[4];
+	static const char *endMsg1[4];
+	static const char *endMsg2[4];
+	static const char *endMsg3[4];
+	// game completion messages
+	static const char *endMsg4[4];
+	static const char *endMsg5[4];
+	static const char *endMsg6[4];
+	static const char *endMsg7[4];
 
-				if (_si != -1) {
-					_gfx->grabBackground(codeTrueBlocks[_si], block);
-					_gfx->patchBackground(block, _di * SLOT_WIDTH + SLOT_X, SLOT_Y, false);
 
-					if (keys[0][_di] == _si) {
-						points[0]++;
-					} else
-					if (keys[1][_di] == _si) {
-						points[1]++;
-					} else
-					if (keys[2][_di] == _si) {
-						points[2]++;
-					} else {
-						fail = true;
-					}
+public:
+	EndPartInputState(Parallaction_ns *vm, MenuInputHelper *helper) : MenuInputState("endpart", helper), _vm(vm) {
+	}
 
-					// build user preference
-					points[0] += (keys[0][_di] == _si);
-					points[1] += (keys[1][_di] == _si);
-					points[2] += (keys[2][_di] == _si);
-
-					_di++;
-				}
-			}
-			_gfx->updateScreen();
+	virtual MenuInputState* run() {
+		int event = _vm->_input->getLastButtonEvent();
+		if (event != kMouseLeftUp) {
+			return this;
 		}
 
-		if (!fail) {
-			break;
+		_vm->_gfx->freeLabels();
+
+		if (_allPartsComplete) {
+			_vm->scheduleLocationSwitch("estgrotta.drki");
+			return 0;
 		}
 
-		_gfx->patchBackground(v14, SLOT_X, SLOT_Y, false);
+		return _helper->getState("selectcharacter");
+	}
 
-		_gfx->hideLabel(id[0]);
-		_gfx->showLabel(id[1], 60, 30);
+	virtual void enter() {
+		_allPartsComplete = _vm->allPartsComplete();
 
-		_gfx->updateScreen();
+		uint id[4];
+		if (_allPartsComplete) {
+			id[0] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg4[_language], 1);
+			id[1] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg5[_language], 1);
+			id[2] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg6[_language], 1);
+			id[3] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg7[_language], 1);
+		} else {
+			id[0] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg0[_language], 1);
+			id[1] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg1[_language], 1);
+			id[2] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg2[_language], 1);
+			id[3] = _vm->_gfx->createLabel(_vm->_menuFont, endMsg3[_language], 1);
+		}
 
-		g_system->delayMillis(2000);
+		_vm->_gfx->showLabel(id[0], CENTER_LABEL_HORIZONTAL, 70);
+		_vm->_gfx->showLabel(id[1], CENTER_LABEL_HORIZONTAL, 100);
+		_vm->_gfx->showLabel(id[2], CENTER_LABEL_HORIZONTAL, 130);
+		_vm->_gfx->showLabel(id[3], CENTER_LABEL_HORIZONTAL, 160);
 	}
+};
 
-	_gfx->freeLabels();
+// part completion messages
+const char *EndPartInputState::endMsg0[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
+const char *EndPartInputState::endMsg1[] = {"HAI FINITO QUESTA PARTE", "TU AS COMPLETE' CETTE AVENTURE", "YOU HAVE COMPLETED THIS PART", "DU HAST EIN ABENTEUER ERFOLGREICH"};
+const char *EndPartInputState::endMsg2[] = {"ORA COMPLETA IL RESTO ", "AVEC SUCCES.",  "NOW GO ON WITH THE REST OF", "ZU ENDE GEFUHRT"};
+const char *EndPartInputState::endMsg3[] = {"DELL' AVVENTURA",  "CONTINUE AVEC LES AUTRES", "THIS ADVENTURE", "MACH' MIT DEN ANDEREN WEITER"};
+// game completion messages
+const char *EndPartInputState::endMsg4[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
+const char *EndPartInputState::endMsg5[] = {"HAI FINITO LE TRE PARTI", "TU AS COMPLETE' LES TROIS PARTIES", "YOU HAVE COMPLETED THE THREE PARTS", "DU HAST DREI ABENTEURE ERFOLGREICH"};
+const char *EndPartInputState::endMsg6[] = {"DELL' AVVENTURA", "DE L'AVENTURE", "OF THIS ADVENTURE", "ZU ENDE GEFUHRT"};
+const char *EndPartInputState::endMsg7[] = {"ED ORA IL GRAN FINALE ", "ET MAINTENANT LE GRAND FINAL", "NOW THE GREAT FINAL", "UND YETZT DER GROSSE SCHLUSS!"};
 
-	_gfx->setBlackPalette();
-	_gfx->updateScreen();
+void Parallaction_ns::startGui() {
+	_disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
 
-	v14.free();
+	_menuHelper = new MenuInputHelper;
+	assert(_menuHelper);
 
+	new SelectGameInputState(this, _menuHelper);
+	new LoadGameInputState(this, _menuHelper);
+	new NewGameInputState(this, _menuHelper);
+	new StartDemoInputState(this, _menuHelper);
+	new SelectCharacterInputState(this, _menuHelper);
+	new ChooseLanguageInputState(this, _menuHelper);
+	new SplashInputState1(this, _menuHelper);
+	new SplashInputState0(this, _menuHelper);
+	_menuHelper->setState("intro0");
 
-	// actually select character
+	_input->_inputMode = Input::kInputModeMenu;
+}
 
-	int character = -1;
-	if (points[0] >= points[1] && points[0] >= points[2]) {
-		character = CHAR_DINO;
-	} else
-	if (points[1] >= points[0] && points[1] >= points[2]) {
-		character = CHAR_DONNA;
-	} else
-	if (points[2] >= points[0] && points[2] >= points[1]) {
-		character = CHAR_DOUGH;
-	} else {
-		error("If you read this, either your CPU or transivity is broken (we believe the former).");
+void Parallaction_ns::startCreditSequence() {
+	_menuHelper = new MenuInputHelper;
+	assert(_menuHelper);
+
+	new ShowCreditsInputState(this, _menuHelper);
+	new EndIntroInputState(this, _menuHelper);
+	new SelectCharacterInputState(this, _menuHelper);
+	_menuHelper->setState("showcredits");
+
+	_input->_inputMode = Input::kInputModeMenu;
+}
+
+void Parallaction_ns::startEndPartSequence() {
+	_menuHelper = new MenuInputHelper;
+	assert(_menuHelper);
+
+	new EndPartInputState(this, _menuHelper);
+	new SelectCharacterInputState(this, _menuHelper);
+	_menuHelper->setState("endpart");
+
+	_input->_inputMode = Input::kInputModeMenu;
+}
+
+
+void Parallaction::runGuiFrame() {
+	if (_input->_inputMode != Input::kInputModeMenu) {
+		return;
 	}
 
-	return character;
+	if (!_menuHelper) {
+		error("No menu helper defined!");
+	}
+
+	bool res = _menuHelper->run();
+
+	if (!res) {
+		cleanupGui();
+		_input->_inputMode = Input::kInputModeGame;
+	}
+
 }
 
+void Parallaction::cleanupGui() {
+	delete _menuHelper;
+	_menuHelper = 0;
+}
 
+void Parallaction::setInternLanguage(uint id) {
+	//TODO: assert id!
+
+	_language = id;
+	_disk->setLanguage(id);
+}
+
+uint Parallaction::getInternLanguage() {
+	return _language;
+}
+
 } // namespace Parallaction

Modified: scummvm/trunk/engines/parallaction/input.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/input.cpp	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/input.cpp	2008-07-24 09:24:32 UTC (rev 33260)
@@ -166,6 +166,7 @@
 	switch (_inputMode) {
 	case kInputModeComment:
 	case kInputModeDialogue:
+	case kInputModeMenu:
 		readInput();
 		break;
 

Modified: scummvm/trunk/engines/parallaction/input.h
===================================================================
--- scummvm/trunk/engines/parallaction/input.h	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/input.h	2008-07-24 09:24:32 UTC (rev 33260)
@@ -85,7 +85,8 @@
 		kInputModeGame = 0,
 		kInputModeComment = 1,
 		kInputModeDialogue = 2,
-		kInputModeInventory = 3
+		kInputModeInventory = 3,
+		kInputModeMenu = 4
 	};
 
 

Modified: scummvm/trunk/engines/parallaction/parallaction.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/parallaction.cpp	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/parallaction.cpp	2008-07-24 09:24:32 UTC (rev 33260)
@@ -98,6 +98,8 @@
 	freeCharacter();
 	destroyInventory();
 
+	cleanupGui();
+
 	delete _localFlagNames;
 	delete _gfx;
 	delete _soundMan;
@@ -136,6 +138,8 @@
 
 	_debugger = new Debugger(this);
 
+	_menuHelper = 0;
+
 	setupBalloonManager();
 
 	return 0;
@@ -325,6 +329,7 @@
 	if (_engineFlags & kEngineQuit)
 		return;
 
+	runGuiFrame();
 	runDialogueFrame();
 	runCommentFrame();
 

Modified: scummvm/trunk/engines/parallaction/parallaction.h
===================================================================
--- scummvm/trunk/engines/parallaction/parallaction.h	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/parallaction.h	2008-07-24 09:24:32 UTC (rev 33260)
@@ -158,6 +158,7 @@
 class SoundMan;
 class Input;
 class DialogueManager;
+class MenuInputHelper;
 
 struct Location {
 
@@ -416,11 +417,18 @@
 	void exitDialogueMode();
 	void runDialogueFrame();
 
+	MenuInputHelper *_menuHelper;
+	void runGuiFrame();
+	void cleanupGui();
+
 	ZonePtr	_commentZone;
 	void enterCommentMode(ZonePtr z);
 	void exitCommentMode();
 	void runCommentFrame();
 
+	void setInternLanguage(uint id);
+	uint getInternLanguage();
+
 };
 
 
@@ -485,7 +493,14 @@
 	bool saveGame();
 
 	void		switchBackground(const char* background, const char* mask);
+	void		showSlide(const char *name);
+	void 		setArrowCursor();
 
+	// TODO: this should be private!!!!!!!
+	bool	_inTestResult;
+	void cleanupGame();
+	bool allPartsComplete();
+
 private:
 	LocationParser_ns		*_locationParser;
 	ProgramParser_ns		*_programParser;
@@ -496,16 +511,13 @@
 	Common::String genSaveFileName(uint slot, bool oldStyle = false);
 	Common::InSaveFile *getInSaveFile(uint slot);
 	Common::OutSaveFile *getOutSaveFile(uint slot);
-	bool allPartsComplete();
 	void setPartComplete(const Character& character);
 
 private:
 	void changeLocation(char *location);
 	void changeCharacter(const char *name);
 	void runPendingZones();
-	void cleanupGame();
 
-	void setArrowCursor();
 	void setInventoryCursor(int pos);
 
 
@@ -539,9 +551,6 @@
 	ZonePtr _moveSarcExaZones[5];
 	AnimationPtr _rightHandAnim;
 
-	bool	_inTestResult;
-
-
 	// common callables
 	void _c_play_boogie(void*);
 	void _c_startIntro(void*);
@@ -586,15 +595,9 @@
 
 	void		selectStartLocation();
 
-	void		guiStart();
-	int			guiSelectCharacter();
-	void		guiSplash();
-	int			guiNewGame();
-	uint16		guiChooseLanguage();
-	uint16		guiSelectGame();
-	int			guiGetSelectedBlock(const Common::Point &p);
-
-	void		showSlide(const char *name);
+	void		startGui();
+	void		startCreditSequence();
+	void		startEndPartSequence();
 };
 
 

Modified: scummvm/trunk/engines/parallaction/parallaction_ns.cpp
===================================================================
--- scummvm/trunk/engines/parallaction/parallaction_ns.cpp	2008-07-24 08:59:17 UTC (rev 33259)
+++ scummvm/trunk/engines/parallaction/parallaction_ns.cpp	2008-07-24 09:24:32 UTC (rev 33260)
@@ -240,17 +240,8 @@
 
 	_globalTable = _disk->loadTable("global");
 
-	guiStart();
+	startGui();
 
-	if (_engineFlags & kEngineQuit)
-		return 0;
-
-	changeLocation(_location._name);
-
-	if (_engineFlags & kEngineQuit)
-		return 0;
-
-	_input->_inputMode = Input::kInputModeGame;
 	while ((_engineFlags & kEngineQuit) == 0) {
 		runGame();
 	}


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list