[Scummvm-git-logs] scummvm master -> 7b8ad76c20fc7ad0d733f6ed940aa27da19f1d31

sev- sev at scummvm.org
Sun Oct 31 18:16:06 UTC 2021


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

Summary:
feb7ca25db HYPNO: basic parsing of mis files and intro
ce9c242002 HYPNO: better parsing and preliminary cursor rendering
212c177ab3 HYPNO: better parsing, more actions and improved detection tables
104a141840 HYPNO: state variables, more actions and improved video playback
e868e7bde8 HYPNO: parsing of data structure used for arcade sequences and refactoring
77e9d1bc69 HYPNO: parsing of list of shoots and collision detection in arcade mode
43acfd7fbd HYPNO: simplified code to parse lib files and first attempt to play raw sounds
559ad7d46f HYPNO: fixed use-after-free and small refactoring of code
d93066eb08 HYPNO: parsing, loading and playing of background music
5165f94f3c HYPNO: basic parsing of TALK sequences
bd7dd0b4fe HYPNO: basic handling of TALK sequences
f101808b43 HYPNO: improved detection and refactored arcade code
9e9aa99ea9 HYPNO: video handling code refactored
aa6e7d4fc8 COMMON: added SmackerDecoder::forceSeekToFrame function
2eb12c6b3e HYPNO: improved and refactored arcade code
d75d4c9be0 HYPNO: refactored spiderman and wetlands engines
1f61e81e83 HYPNO: improved detection of wetlands releases
abd5a028db HYPNO: refactored engines to better parse arcade sequences
51683aaa8b HYPNO: improved wetlands demo support and refactored engines
fb15c9477f HYPNO: refactored both games
2acec33542 HYPNO: implemented missing puzzle and fixes
1753841da8 HYPNO: fixed name and original copyright
8d244e072a HYPNO: refactoring and linting
b5afc381b3 HYPNO: improved parsing and sound in arcade sequences
7f55b9cad0 HYPNO: improved arcade sequences, pointers and basic detection of Soldier Boyz
87afe2d933 HYPNO: refactored code, added basic debugging capabilities and fixes
ce723aeb60 HYPNO: Improved debugging capabilities and memory management
1d2593d11c HYPNO: Improved arcade sequences and refactored parsing code
0c4fdf44b4 HYPNO: Removed some memory leaks
a18c5f8a98 HYPNO: run clang-format and minor fixes
a571caa306 HYPNO: removed debugs
18c81f9b30 HYPNO: added typeinfo include and license in actions.cpp
a0bce5377f HYPNO: added typeinfo include to scene.cpp
7387391aa3 HYPNO: removed useless override
d5a9ef4511 HYPNO: removed useless local variables
5f4e72ab9e HYPNO: added pregenerated flex/lex code
d5277d97ef HYPNO: try to keep the compiler happy regarding LibFile class
38b3a96d60 HYPNO: added score, credits and fixed some minor issues
8a158c72ec HYPNO: fixed secondary shoot in Wetlands and added support for static frame transitions
2f5417faf6 HYPNO: fixed LibFile class after rebase
303704a71e HYPNO: improved spider shoot animation
9df22aecbb HYPNO: use empty() instead of size() and removed some useless allocations
f5b458f175 HYPNO: fixed grammar_arc.y and regenerated code
6c0b31e33e HYPNO: fixed grammar_mis.y format and regenerated code
4486f3692d HYPNO: fixed grammar_mis.y format and regenerated code
01fecf214c HYPNO: fixed modules.mk format
13e94f868e HYPNO: preallocate elements in the afiles array
7ca44fa607 HYPNO: fixed lexer_arc.l format and regenerated code
2fa66d32c2 HYPNO: fixed lexer_mis.l format and regenerated code
266939c541 HYPNO: added missing new lines
51aeec71ba HYPNO: fixed usage of hoverHotspot
53f780d8a3 HYPNO: allow to read the game data directly from the CD without installing
ceaf573ecf COMMON: extended InstallShieldV3 support to read all the files in every subdirectory
c608f28f05 COMMON: removed convertPath
c510c683b0 HYPNO: use references to pass arguments and some minor fixes
7fd92f3a22 HYPNO: added missing newline
267ba8d113 HYPNO: enabled health tracking
da95a4ba2e HYPNO: fixed a race condition in the usage of the timer callback
8100ee54a4 HYPNO: fixed missing headers, removed C++isms and better errors among others
2a45d0908e HYPNO: readded typeinfo header
0925d2b823 COMMON: changed type of variable in the directory count loop
35f970ae1e HYPNO: fixed missing headers, removed C++isms and reduced variable scopes among others
754afa4e7b HYPNO: replaced asserts with better code
f7b2ee5d1f HYPNO: replaced asserts with better code
d4c82e641c HYPNO: replaced std::min with MIN macro
713529f49a HYPNO: reduced scope of more variables
a92ddb455a HYPNO: added support for more wetlands demo, refactored code and added some fixes
5a0e34e41e HYPNO: started basic support for full versions and some fixes
b58cb9d7ca HYPNO: reduced maxScanDepth and adjusted detection tables
d2cc360828 HYPNO: reduce variable scopes and some various fixed here and there
f278a2fd0a HYPNO: improved detection and added POTFILES file
65754da57e HYPNO: refactored object initialization to use explicit constructors
341c6f960f HYPNO: sorted module.mk list of objects
a87c50f498 HYPNO: added functions to start implementing gameplay from full versions of Wetlands and Spiderman games as well as some
28e84c94e5 HYPNO: code formatting in arguments, detection tables and others
dc1e09f15c HYPNO: correctly parse complete wetlands missions
3e8117ba9d HYPNO: added explicit action type and refactored affected code
00d7a05c94 HYPNO: replaced typeid code with enumarated type
e67832818a HYPNO: refactored Hotspot
cdc58ab15f HYPNO: improved video decoding, implemented initial version of wetland main menu and some other fixes
8d35d2577e HYPNO: more code formating fixes in c++ code and grammars
844aab5156 HYPNO: added header and newline to video.cpp
815c0138b8 HYPNO: fixed formating for detection tables
7b8ad76c20 HYPNO: added intro to wetlands full game


Commit: feb7ca25db3d385590929c225b91fc438e2679da
    https://github.com/scummvm/scummvm/commit/feb7ca25db3d385590929c225b91fc438e2679da
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: basic parsing of mis files and intro

Changed paths:
  A engines/hypno/configure.engine
  A engines/hypno/cursors.cpp
  A engines/hypno/detection.cpp
  A engines/hypno/grammar.h
  A engines/hypno/grammar.y
  A engines/hypno/hypno.cpp
  A engines/hypno/hypno.h
  A engines/hypno/lexer.l
  A engines/hypno/metaengine.cpp
  A engines/hypno/module.mk


diff --git a/engines/hypno/configure.engine b/engines/hypno/configure.engine
new file mode 100644
index 0000000000..6428240265
--- /dev/null
+++ b/engines/hypno/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine hypno "Hypnotix Inc." yes "" "" "highres 16bit"
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
new file mode 100644
index 0000000000..5aada0ac67
--- /dev/null
+++ b/engines/hypno/cursors.cpp
@@ -0,0 +1,86 @@
+/* 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/rect.h"
+#include "graphics/cursorman.h"
+
+#include "hypno/hypno.h"
+
+namespace Hypno {
+
+static const byte MOUSECURSOR_SCI[] = {
+	1,1,0,0,0,0,0,0,0,0,0,
+	1,2,1,0,0,0,0,0,0,0,0,
+	1,2,2,1,0,0,0,0,0,0,0,
+	1,2,2,2,1,0,0,0,0,0,0,
+	1,2,2,2,2,1,0,0,0,0,0,
+	1,2,2,2,2,2,1,0,0,0,0,
+	1,2,2,2,2,2,2,1,0,0,0,
+	1,2,2,2,2,2,2,2,1,0,0,
+	1,2,2,2,2,2,2,2,2,1,0,
+	1,2,2,2,2,2,2,2,2,2,1,
+	1,2,2,2,2,2,1,0,0,0,0,
+	1,2,1,0,1,2,2,1,0,0,0,
+	1,1,0,0,1,2,2,1,0,0,0,
+	0,0,0,0,0,1,2,2,1,0,0,
+	0,0,0,0,0,1,2,2,1,0,0,
+	0,0,0,0,0,0,1,2,2,1,0
+};
+
+static const byte cursorPalette[] = {
+	0x00, 0x00, 0x00,  // Black / Transparent
+	0x01, 0x01, 0x01,  // Gray
+	0xff, 0xff, 0xff,  // White
+	0xff, 0x00, 0x00   // Red
+};
+
+struct CursorTable {
+	const char *name;
+	const char *aname;
+	const void *buf;
+	int w;
+	int h;
+	int hotspotX;
+	int hotspotY;
+};
+
+static const CursorTable cursorTable[] = {
+	{ "default",    "", MOUSECURSOR_SCI,        11, 16, 0,  0  },
+	{ nullptr,      nullptr, nullptr,           0,  0,  0,  0  }
+};
+
+void HypnoEngine::changeCursor(const Common::String &cursor) {
+	const CursorTable *entry = cursorTable;
+	while (entry->name) {
+		if (cursor == entry->name || cursor == entry->aname)
+			break;
+		entry++;
+	}
+	if (!entry->name)
+		return;
+
+	CursorMan.replaceCursor(entry->buf, entry->w, entry->h, entry->hotspotX, entry->hotspotY, 0);
+	CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
+	CursorMan.showMouse(true);
+}
+
+} // End of namespace Hypno
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
new file mode 100644
index 0000000000..718b597ed5
--- /dev/null
+++ b/engines/hypno/detection.cpp
@@ -0,0 +1,86 @@
+/* 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 "common/translation.h"
+#include "engines/advancedDetector.h"
+#include "hypno/hypno.h"
+
+static const DebugChannelDef debugFlagList[] = {
+	{Hypno::kHypnoDebugFunction, "functions", "Function execution debug channel"},
+	{Hypno::kHypnoDebugCode, "code", "Code execution debug channel"},
+	{Hypno::kHypnoDebugScript, "script", "Script execution debug channel"},
+	DEBUG_CHANNEL_END
+};
+
+namespace Hypno {
+static const PlainGameDescriptor hypnoGames[] = {
+	{ "sinister-six", "Spiderman and the Sinister Six" },
+	{ 0, 0 }
+};
+
+static const ADGameDescription gameDescriptions[] = {
+	{
+		"sinister-six", // Demo from the US release
+		"Demo",
+		AD_ENTRY2s("COMBAT.EXE", "15a6b1b3819ef002438df340509b5373", 643471,
+  				   "SPIDER.EXE", "15a6b1b3819ef002438df340509b5373", 603587),
+		Common::EN_USA,
+		Common::kPlatformWindows,
+		ADGF_TESTING | ADGF_DEMO,
+		GUIO1(GUIO_NOMIDI)
+	},
+	AD_TABLE_END_MARKER
+};
+} // End of namespace Hypno
+
+static const char *const directoryGlobs[] = {
+	"sixdemo",
+	"factory",
+	0
+};
+
+class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
+public:
+	HypnoMetaEngineDetection() : AdvancedMetaEngineDetection(Hypno::gameDescriptions, sizeof(ADGameDescription), Hypno::hypnoGames) {
+		_maxScanDepth = 2;
+		_directoryGlobs = directoryGlobs;
+	}
+
+	const char *getEngineId() const override {
+		return "hypno";
+	}
+
+	const char *getName() const override {
+		return "Spiderman and the Sinister Six";
+	}
+
+	const char *getOriginalCopyright() const override {
+		return "Copyright (C) Brooklyn Multimedia";
+	}
+
+	const DebugChannelDef *getDebugChannels() const override {
+		return debugFlagList;
+	}
+};
+
+REGISTER_PLUGIN_STATIC(HYPNO_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, HypnoMetaEngineDetection);
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
new file mode 100644
index 0000000000..2067a322f4
--- /dev/null
+++ b/engines/hypno/grammar.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.
+ *
+ * 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 HYPNO_GRAMMAR_H
+#define HYPNO_GRAMMAR_H
+
+#include "common/str.h"
+#include "common/hash-str.h"
+#include "common/hash-ptr.h"
+#include "common/queue.h"
+#include "common/list.h"
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace Hypno {
+
+enum HotspotType {
+    MakeMenu,
+ 	MakeHotspot
+};
+
+class Action {
+	public:
+	virtual ~Action() {}; // needed to make Action polymorphic
+};
+
+typedef Common::List<Action*> Actions;
+
+class Hotspot { 
+  public:
+    HotspotType type;
+    Common::String stype;
+	Common::String stypeFlag;
+	int x0, y0;
+	int x1, y1;
+	Actions actions;
+};
+
+class Mice : public Action {
+  public:
+	Common::String path;
+	int index;
+};
+
+class Palette : public Action {
+  public:
+	Common::String path;
+};
+
+class Background : public Action {
+  public:
+	Common::String path;
+	Common::Point origin;
+};
+
+typedef Common::List<Hotspot> Hotspots;
+typedef Common::HashMap<Common::String, Hotspots> Settings;
+
+extern Settings setts;
+extern Hotspot *hot;
+extern Hotspots hots;
+
+} // End of namespace Hypno
+
+#endif
diff --git a/engines/hypno/grammar.y b/engines/hypno/grammar.y
new file mode 100644
index 0000000000..c365d1eda5
--- /dev/null
+++ b/engines/hypno/grammar.y
@@ -0,0 +1,162 @@
+/* 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.
+ *
+ */
+
+// Heavily inspired by hoc
+// Copyright (C) AT&T 1995
+// All Rights Reserved
+//
+// Permission to use, copy, modify, and distribute this software and
+// its documentation for any purpose and without fee is hereby
+// granted, provided that the above copyright notice appear in all
+// copies and that both that the copyright notice and this
+// permission notice and warranty disclaimer appear in supporting
+// documentation, and that the name of AT&T or any of its entities
+// not be used in advertising or publicity pertaining to
+// distribution of the software without specific, written prior
+// permission.
+//
+// AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+// IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+// SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+// THIS SOFTWARE.
+
+%require "3.0"
+%defines "engines/hypno/tokens.h"
+%output "engines/hypno/grammar.cpp"
+%define api.prefix {HYPNO_}
+
+%{
+
+//#include "private/private.h"
+#include "hypno/grammar.h"
+#include <stdio.h>
+
+#undef yyerror
+#define yyerror	 HYPNO_xerror
+
+extern int HYPNO_lex();
+extern int HYPNO_parse();
+extern int yylineno;
+
+void HYPNO_xerror(const char *str) {
+	debug("ERROR: %s", str);
+}
+
+int HYPNO_wrap() {
+    return 1;
+}
+
+using namespace Hypno;
+
+%} 
+
+
+%union {
+	char *s;	     	/* string value */
+	int i;	         	/* integer value */
+}
+
+%token<s> NAME FILENAME FLAG COMMENT
+%token<i> NUM
+%token HOTSTOK CUTSTOK BITMAPTOK BACKTOK RETTOK  TIMETOK PALETOK BBOXTOK OVERTOK WALNTOK MICETOK PLAYTOK ENDTOK 
+%token MENUTOK SMENTOK ESCPTOK NRTOK
+%token GLOBTOK TONTOK TOFFTOK GSSWITCH
+
+%%
+
+lines:   line RETTOK lines
+       | line
+	   | end lines            
+	   ; 
+
+end: RETTOK  { debug("implicit END"); }
+    ; 
+
+line:    MENUTOK NAME mflag  {
+	     assert(hot == NULL);
+	     hot = new Hotspot(); 
+		 hot->type = MakeMenu;
+		 debug("MENU %d.", hot->type); 
+	  }
+      |	 HOTSTOK BBOXTOK NUM NUM NUM NUM  { 
+         if (hot != NULL)
+		    hots.push_back(*hot);
+
+	     hot = new Hotspot(); 
+		 hot->type = MakeHotspot;
+		 hot->x0 = $3;
+		 debug("HOTS %d", hot->x0); 
+      }
+	  |  SMENTOK { 
+		  hot = NULL;
+		  debug("SUBMENU"); }
+      |  ESCPTOK                                   { debug("ESC SUBMENU"); }
+	  |  TIMETOK NUM                               { debug("TIME %d", $2); } 
+      |  BACKTOK FILENAME NUM NUM gsswitch flag    {
+		  	Background *a = new Background();
+		  	a->path = $2;
+		  	a->origin = Common::Point($3, $4);
+		  	hot->actions.push_back(a);
+		}
+      |  GLOBTOK gsswitch command                  { debug("GLOB."); }
+	  |  PLAYTOK FILENAME NUM NUM gsswitch flag    { debug("PLAY %s.", $2); }
+      |  OVERTOK FILENAME NUM NUM flag    		   { debug("OVER %s.", $2); }
+	  |  PALETOK FILENAME                          {
+			Palette *a = new Palette();
+			a->path = $2; 
+		    hot->actions.push_back(a);
+		}
+	  |  CUTSTOK FILENAME                          { debug("CUTS %s.", $2); }
+	  |  WALNTOK FILENAME NUM NUM gsswitch flag    { debug("WALN %s %d %d.", $2, $3, $4); } 
+	  |  MICETOK FILENAME NUM {
+		  	  //Mice a;
+			  //a.path = $2; 
+			  //a.index = $3;
+		      //hot->actions.push_back(a);
+	  }
+	  |  ENDTOK RETTOK { 
+		  debug("explicit END"); 
+		  if (hot == NULL)
+			error("Invalid END during MIS parsing");
+		  hots.push_back(*hot);
+		  }   		               
+	  ;
+
+mflag:  NRTOK
+      | /*nothing*/
+	  ;
+
+flag:   BITMAPTOK                         { debug("flag: BITMAP"); }
+      | /* nothing */
+	  ;
+
+gsswitch:   GSSWITCH                      { debug("flag: GS_SWITCH"); }
+          | /* nothing */
+	      ;
+
+command:   TONTOK 
+         | TOFFTOK
+		 ;
\ No newline at end of file
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
new file mode 100644
index 0000000000..d4b3d73ee1
--- /dev/null
+++ b/engines/hypno/hypno.cpp
@@ -0,0 +1,473 @@
+/* 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 "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/debug.h"
+#include "common/error.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "common/timer.h"
+#include "engines/util.h"
+#include "image/bmp.h"
+
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+
+namespace Hypno {
+
+Hotspot *hot;
+Hotspots hots;
+Settings setts;
+
+extern int parse(const char *);
+
+HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
+	: Engine(syst), _gameDescription(gd), _image(nullptr), _videoDecoder(nullptr),
+	  _compositeSurface(nullptr), _transparentColor(0), _frame(nullptr),
+	  _maxNumberClicks(0), _sirenWarning(0), _screenW(640), _screenH(480) {
+	_rnd = new Common::RandomSource("hypno");
+}
+
+HypnoEngine::~HypnoEngine() {
+	// Dispose your resources here
+	delete _frame;
+	delete _rnd;
+}
+
+void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
+	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
+}
+
+void HypnoEngine::loadMis(Common::String filename) {
+    filename = convertPath(filename);
+	Common::File *test = new Common::File();
+	Common::SeekableReadStream *file = NULL;
+	assert(isDemo());
+    assert(test->open(filename.c_str()));
+
+	const uint32 fileSize = test->size();
+	char *buf = (char *)malloc(fileSize + 1);
+	test->read(buf, fileSize);
+	buf[fileSize] = '\0';
+	parse(buf);
+	setts[filename] = hots;
+	debug("Loaded hots size: %d", hots.size());
+}
+
+LibData HypnoEngine::loadLib(char *filename) {
+	Common::File libfile;
+    assert(libfile.open(filename));
+	const uint32 fileSize = libfile.size();
+	byte *buf = (byte *)malloc(fileSize + 1);
+	byte *it = buf;
+	libfile.read(buf, fileSize);
+	uint32 i = 0;
+	uint32 j = 0;
+	bool cont = false;
+	Common::String entry;
+	LibData r;
+
+	while (true) {
+		cont = true;
+		entry.clear();
+		for (j = 0; j < 24; j++) {
+			if (cont && it[i] != 0x96 && it[i] != NULL) {
+				entry += char(it[i]);
+			}
+			else
+				cont = false;
+			i++;			
+		}
+		if (!cont && entry.size() > 0) {
+			debug("Found %s", entry.c_str());
+			r.filenames.push_back(entry);
+		}
+		else {
+			break;
+		}
+
+	}
+
+	while (it[i] != '\n')
+	    i++;
+
+	//ByteArray *files = new ByteArray();
+
+	for (; i < fileSize; i++) {
+		if (it[i] != '\n')
+			it[i] = it[i] ^ 0xfe;
+		r.data.push_back(it[i]);
+	}
+	
+	return r;
+}
+
+Common::Error HypnoEngine::run() {
+	_language = Common::parseLanguage(ConfMan.get("language"));
+	_platform = Common::parsePlatform(ConfMan.get("platform"));
+    /*
+	LibData files = loadLib("C_MISC/MISSIONS.LIB");
+	uint32 i = 0;
+	uint32 j = 0;
+	uint32 k = 0;
+
+	debug("file: %s",files.filenames[j].c_str());
+	for (i = 0; i < files.data.size(); i++) {
+		debugN("%c", files.data[i]);
+		if (files.data[i] == 'X') {
+			if (j == files.filenames.size()-1) {
+				debug("Finished at %d from %d", i, files.data.size()); 
+				for (k = i; k < files.data.size(); k++)
+					debugN("%c", files.data[k]);
+				break;
+			}
+
+			j++;
+			debugN("\n************file: %s**************",files.filenames[j].c_str());
+		}
+	}
+	*/	
+	// Read assets file
+	loadMis("mis/demo.mis");
+	loadMis("mis/order.mis");
+	//loadMis("mis/alley.mis");
+	//loadMis("MIS/SHOCTALK.MIS");
+
+	// Initialize graphics
+	initGraphics(_screenW, _screenH, nullptr);
+	_pixelFormat = g_system->getScreenFormat();
+	if (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8())
+		return Common::kUnsupportedColorMode;
+
+	_transparentColor = _pixelFormat.RGBToColor(0, 255, 0);
+	_safeColor = _pixelFormat.RGBToColor(65, 65, 65);
+	screenRect = Common::Rect(0, 0, _screenW, _screenH);
+	//changeCursor("default");
+	_origin = Common::Point(0, 0);
+	_image = new Image::BitmapDecoder();
+	_compositeSurface = new Graphics::ManagedSurface();
+	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
+	_compositeSurface->setTransparentColor(_transparentColor);
+
+	// Main event loop
+	Common::Event event;
+	Common::Point mousePos;
+	_videoDecoder = nullptr;
+	/*int saveSlot = ConfMan.getInt("save_slot");
+	if (saveSlot >= 0) { // load the savegame
+		loadGameState(saveSlot);
+	} else {
+		_nextSetting = getGoIntroSetting();
+	}*/
+	Common::String logoIntro = "DEMO/DCINE1.SMK";
+	Common::String movieIntro = "DEMO/DCINE2.SMK";
+	_nextMovie = logoIntro;
+
+	while (_nextMovie != "" || _currentMovie != "") {
+			while (g_system->getEventManager()->pollEvent(event)) {
+			// Events
+			switch (event.type) {
+			case Common::EVENT_KEYDOWN:
+				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder)
+					// Ugly hack to play two intro movies.
+					if (_currentMovie == logoIntro)
+						_nextMovie = movieIntro;
+					else
+					    skipVideo();
+
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		// Movies
+		if (!_nextMovie.empty()) {
+			_videoDecoder = new Video::SmackerDecoder();
+			playVideo(_nextMovie);
+			_currentMovie = _nextMovie;
+			_nextMovie = "";
+			continue;
+		}
+
+		if (_videoDecoder && !_videoDecoder->isPaused()) {
+			if (_videoDecoder->getCurFrame() == 0)
+				stopSound(true);
+			if (_videoDecoder->endOfVideo()) {
+				_videoDecoder->close();
+				delete _videoDecoder;
+				_videoDecoder = nullptr;
+				// Ugly hack to play two intro movies.
+				if (_currentMovie == logoIntro)
+					_nextMovie = movieIntro;
+				else 
+					_nextMovie = "";
+			} else if (_videoDecoder->needsUpdate()) {
+				drawScreen();
+				g_system->delayMillis(10);
+			}
+			continue;
+		}
+
+		g_system->updateScreen();
+		g_system->delayMillis(10);
+	}
+
+	_nextSetting = "mis/demo.mis";
+	changeCursor("default");
+
+	while (!shouldQuit()) {
+		
+		while (g_system->getEventManager()->pollEvent(event)) {
+			mousePos = g_system->getEventManager()->getMousePos();
+			// Events
+			switch (event.type) {
+			case Common::EVENT_KEYDOWN:
+				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder)
+					skipVideo();
+
+				break;
+
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_LBUTTONDOWN:
+				// if (selectDossierNextSuspect(mousePos))
+				// 	break;
+				// else if (selectDossierPrevSuspect(mousePos))
+				// 	break;
+				// else if (selectDossierNextSheet(mousePos))
+				// 	break;
+				// else if (selectDossierPrevSheet(mousePos))
+				// 	break;
+				// else if (selectSafeDigit(mousePos))
+				// 	break;
+
+				// selectPauseMovie(mousePos);
+				// selectPhoneArea(mousePos);
+				// selectPoliceRadioArea(mousePos);
+				// selectAMRadioArea(mousePos);
+				// selectLoadGame(mousePos);
+				// selectSaveGame(mousePos);
+				// if (_nextSetting.empty())
+				// 	selectMask(mousePos);
+				// if (_nextSetting.empty())
+				// 	selectExit(mousePos);
+				break;
+
+			case Common::EVENT_MOUSEMOVE:
+				// Reset cursor to default
+				//changeCursor("default");
+				// The following functions will return true
+				// if the cursor is changed
+				//if (cursorPauseMovie(mousePos)) {
+				//} else if (cursorMask(mousePos)) {
+				//} else
+				//	cursorExit(mousePos);
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		// Movies
+		if (!_nextMovie.empty()) {
+			//removeTimer();
+			_videoDecoder = new Video::SmackerDecoder();
+			playVideo(_nextMovie);
+			_currentMovie = _nextMovie;
+			_nextMovie = "";
+			continue;
+		}
+
+		if (_videoDecoder && !_videoDecoder->isPaused()) {
+			if (_videoDecoder->getCurFrame() == 0)
+				stopSound(true);
+			if (_videoDecoder->endOfVideo()) {
+				_videoDecoder->close();
+				delete _videoDecoder;
+				_videoDecoder = nullptr;
+				_currentMovie = "";
+			} else if (_videoDecoder->needsUpdate()) {
+				drawScreen();
+				g_system->delayMillis(10);
+			}
+			continue;
+		}
+
+		if (!_nextSetting.empty()) {
+
+			debug("Executing %s", _nextSetting.c_str());
+			//clearAreas();
+			_currentSetting = _nextSetting;
+			//Settings::g_setts->load(_nextSetting);
+			prepareHotspots(setts[_currentSetting]);
+			_nextSetting = "";
+			//Gen::g_vm->run();
+			//changeCursor("default");
+			drawScreen();
+		}
+
+		g_system->updateScreen();
+		g_system->delayMillis(10);
+	}
+	return Common::kNoError;
+}
+
+void HypnoEngine::prepareHotspots(Hotspots hs) {
+	for (Hotspots::const_iterator it = hs.begin(); it != hs.end(); ++it) {
+		debug("hotspot type: %d", it->type);
+		for (Actions::const_iterator itt = it->actions.begin(); itt != it->actions.end(); ++itt) {
+			Action *action = *itt;
+			if (typeid(*action) == typeid(Background))
+				runBackground((Background*) action);
+		}	
+	}
+}
+
+void HypnoEngine::runBackground(Background *a) {
+	Common::Point origin = a->origin;
+	loadImage(a->path, origin.x, origin.y);
+}
+
+void HypnoEngine::loadImage(const Common::String &name, int x, int y) {
+	Graphics::Surface *surf = decodeFrame(name, 0);
+	_compositeSurface->transBlitFrom(*surf, _origin + Common::Point(x, y), _transparentColor);
+}
+
+Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n) {
+	Common::File *file = new Common::File();
+	Common::String path = convertPath(name);
+
+	if (!file->open(path))
+		error("unable to find video file %s", path.c_str());
+
+	_videoDecoder = new Video::SmackerDecoder();
+	if (!_videoDecoder->loadStream(file))
+		error("unable to load video %s", path.c_str());
+
+    for(int f = 0; f < n; f++) 
+		_videoDecoder->decodeNextFrame();
+
+	const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
+	Graphics::Surface *sframe = frame->scale(_screenW, _screenH);
+	Graphics::Surface *cframe = sframe->convertTo(_pixelFormat, _videoDecoder->getPalette());
+
+	sframe->free();
+	delete sframe;
+	
+	delete _videoDecoder;
+	_videoDecoder = nullptr;
+
+	return cframe;
+}
+
+
+void HypnoEngine::drawScreen() {
+	Graphics::ManagedSurface *surface = _compositeSurface;
+
+	if (_videoDecoder && !_videoDecoder->isPaused()) {
+		const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
+		Graphics::Surface *sframe = frame->scale(_screenW, _screenH);
+		Graphics::Surface *cframe = sframe->convertTo(_pixelFormat, _videoDecoder->getPalette());
+		Common::Point center(0, 0);
+		surface->blitFrom(*cframe, center);
+
+		sframe->free();
+		delete sframe;
+
+		cframe->free();
+		delete cframe;
+	}
+
+	Common::Rect w(_origin.x, _origin.y, _screenW - _origin.x, _screenH - _origin.y);
+	Graphics::Surface sa = surface->getSubArea(w);
+	g_system->copyRectToScreen(sa.getPixels(), sa.pitch, _origin.x, _origin.y, sa.w, sa.h);
+	g_system->updateScreen();
+}
+
+// Video handling
+
+void HypnoEngine::playVideo(const Common::String &name) {
+	//debugC(1, kPrivateDebugFunction, "%s(%s)", __FUNCTION__, name.c_str());
+	Common::File *file = new Common::File();
+	Common::String path = convertPath(name);
+
+	if (!file->open(path))
+		error("unable to find video file %s", path.c_str());
+
+	if (!_videoDecoder->loadStream(file))
+		error("unable to load video %s", path.c_str());
+	_videoDecoder->start();
+}
+
+void HypnoEngine::skipVideo() {
+	_videoDecoder->close();
+	delete _videoDecoder;
+	_videoDecoder = nullptr;	
+	_currentMovie = "";
+}
+
+// Sound handling
+
+void HypnoEngine::stopSound(bool all) {
+	// debugC(1, kPrivateDebugFunction, "%s(%d)", __FUNCTION__, all);
+
+	// if (all) {
+	// 	_mixer->stopHandle(_fgSoundHandle);
+	// 	_mixer->stopHandle(_bgSoundHandle);
+	// } else {
+	// 	_mixer->stopHandle(_fgSoundHandle);
+	// }
+}
+
+// Path handling
+
+Common::String HypnoEngine::convertPath(const Common::String &name) {
+	Common::String path(name);
+	Common::String s1("\\");
+	Common::String s2("/");
+
+	while (path.contains(s1))
+		Common::replace(path, s1, s2);
+
+	s1 = Common::String("\"");
+	s2 = Common::String("");
+
+	Common::replace(path, s1, s2);
+	Common::replace(path, s1, s2);
+
+	path.toLowercase();
+	return path;
+}
+
+} // End of namespace Hypno
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
new file mode 100644
index 0000000000..2d3bd2e6e7
--- /dev/null
+++ b/engines/hypno/hypno.h
@@ -0,0 +1,247 @@
+/* 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 HYPNO_H
+#define HYPNO_H
+
+#include "common/installshieldv3_archive.h"
+#include "common/random.h"
+#include "common/str-array.h"
+#include "common/array.h"
+#include "common/serializer.h"
+#include "engines/engine.h"
+#include "graphics/managed_surface.h"
+#include "video/smk_decoder.h"
+
+#include "hypno/grammar.h"
+
+namespace Image {
+class ImageDecoder;
+}
+
+namespace Graphics {
+class ManagedSurface;
+}
+
+struct ADGameDescription;
+
+namespace Hypno {
+
+// debug channels
+enum {
+	kHypnoDebugFunction = 1 << 0,
+	kHypnoDebugCode = 1 << 1,
+	kHypnoDebugScript = 1 << 2
+};
+
+
+typedef Common::Array<byte> ByteArray;
+typedef struct LibData {
+	Common::Array<Common::String> filenames;
+	ByteArray data;
+} LibData;
+
+class HypnoEngine : public Engine {
+private:
+	Common::RandomSource *_rnd;
+	Graphics::PixelFormat _pixelFormat;
+	Image::ImageDecoder *_image;
+	int _screenW, _screenH;
+
+public:
+	HypnoEngine(OSystem *syst, const ADGameDescription *gd);
+	~HypnoEngine();
+
+	const ADGameDescription *_gameDescription;
+	bool isDemo() const;
+	Common::Language _language;
+	Common::Platform _platform;
+
+	Audio::SoundHandle _fgSoundHandle;
+	Audio::SoundHandle _bgSoundHandle;
+	Video::SmackerDecoder *_videoDecoder;
+	Common::InstallShieldV3 _installerArchive;
+
+	Common::Error run() override;
+	void restartGame();
+	void clearAreas();
+	void initializePath(const Common::FSNode &gamePath) override;
+	void loadMis(Common::String filename);
+	LibData loadLib(char *filename);
+
+	// Functions
+
+	void initFuncs();
+
+	// User input
+	void selectPauseMovie(Common::Point);
+	void selectMask(Common::Point);
+	void selectExit(Common::Point);
+	void selectLoadGame(Common::Point);
+	void selectSaveGame(Common::Point);
+
+	// Cursors
+	bool cursorPauseMovie(Common::Point);
+	bool cursorExit(Common::Point);
+	bool cursorMask(Common::Point);
+
+	//bool hasFeature(EngineFeature f) const override;
+	bool canLoadGameStateCurrently() override {
+		return true;
+	}
+	bool canSaveAutosaveCurrently() override  {
+		return false;
+	}
+	bool canSaveGameStateCurrently() override {
+		return true;
+	}
+
+	void ignoreEvents();
+	//Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
+	//Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
+	void syncGameStream(Common::Serializer &s);
+
+	Common::String convertPath(const Common::String &);
+	void playVideo(const Common::String &);
+	void skipVideo();
+
+	Graphics::Surface *decodeImage(const Common::String &file);
+	Graphics::Surface *decodeFrame(const Common::String &name, int frame);
+	void loadImage(const Common::String &file, int x, int y);
+	void drawScreenFrame();
+
+	// Cursors
+	void changeCursor(const Common::String &);
+	Common::String getInventoryCursor();
+	Common::String getExitCursor();
+
+	// Rendering
+	void prepareHotspots(Hotspots hs);
+    void runBackground(Background *a);
+
+	Graphics::ManagedSurface *_compositeSurface;
+	Graphics::Surface *loadMask(const Common::String &, int, int, bool);
+	void drawMask(Graphics::Surface *);
+	void fillRect(uint32, Common::Rect);
+	bool inMask(Graphics::Surface *, Common::Point);
+	uint32 _transparentColor;
+	Common::Rect screenRect;
+	Common::String _framePath;
+	Graphics::Surface *_frame;
+	Common::String _nextVS;
+	Common::Point _origin;
+	void drawScreen();
+
+	// settings
+	Common::String _nextSetting;
+	Common::String _pausedSetting;
+	Common::String _currentSetting;
+	Common::String getPauseMovieSetting();
+	Common::String getGoIntroSetting();
+	Common::String getMainDesktopSetting();
+	Common::String getPOGoBustMovieSetting();
+	Common::String getPoliceBustFromMOSetting();
+	Common::String getAlternateGameVariable();
+	Common::String getPoliceIndexVariable();
+	Common::String getWallSafeValueVariable();
+
+	// movies
+	Common::String _nextMovie;
+	Common::String _currentMovie;
+
+	// Dossiers
+	bool selectDossierNextSuspect(Common::Point);
+	bool selectDossierPrevSuspect(Common::Point);
+	bool selectDossierNextSheet(Common::Point);
+	bool selectDossierPrevSheet(Common::Point);
+	void loadDossier();
+
+	// Police Bust
+	void policeBust();
+	bool _policeBustEnabled;
+	void startPoliceBust();
+	void checkPoliceBust();
+	int _numberClicks;
+	int _maxNumberClicks;
+	int _sirenWarning;
+	Common::String _policeBustSetting;
+
+	// Diary
+	Common::String _diaryLocPrefix;
+	void loadLocations(const Common::Rect &);
+	void loadInventory(uint32, const Common::Rect &, const Common::Rect &);
+	bool _toTake;
+
+	// Save/Load games
+	int _mode;
+	bool _modified;
+	Common::String _repeatedMovieExit;
+
+	// Masks/Exits
+
+	// Sounds
+	void playSound(const Common::String &, uint, bool, bool);
+	void stopSound(bool);
+	bool isSoundActive();
+	bool _noStopSounds;
+
+	Common::String getPaperShuffleSound();
+	Common::String _globalAudioPath;
+
+	Common::String getTakeSound();
+	Common::String getTakeLeaveSound();
+	Common::String getLeaveSound();
+	Common::String _sirenSound;
+
+	// Radios
+	Common::String _infaceRadioPath;
+	Common::String _phonePrefix;
+	Common::String _phoneCallSound;
+
+	Common::String getRandomPhoneClip(const char *, int, int);
+	void selectAMRadioArea(Common::Point);
+	void selectPoliceRadioArea(Common::Point);
+	void selectPhoneArea(Common::Point);
+	void checkPhoneCall();
+
+	// Safe
+	uint32 _safeColor;
+	Common::String _safeNumberPath;
+	Common::Rect _safeDigitRect[3];
+
+	bool selectSafeDigit(Common::Point);
+	void addSafeDigit(uint32, Common::Rect*);
+	void renderSafeDigit(uint32);
+
+	// Random values
+	bool getRandomBool(uint);
+
+	// Timers
+	bool installTimer(uint32, Common::String *);
+	void removeTimer();
+};
+
+//extern PrivateEngine *g_private;
+
+} // End of namespace Hypno
+
+#endif
diff --git a/engines/hypno/lexer.l b/engines/hypno/lexer.l
new file mode 100644
index 0000000000..a322189087
--- /dev/null
+++ b/engines/hypno/lexer.l
@@ -0,0 +1,86 @@
+/* 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.
+ *
+ */
+
+%option noyywrap
+%option noinput
+%option yylineno
+%option never-interactive
+
+%option outfile="engines/hypno/lexer.cpp"
+%option prefix="HYPNO_"
+
+%{
+#define YY_NO_UNISTD_H
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+#include "hypno/tokens.h"
+
+%}
+
+%%
+\;[A-Za-z_0-9 \t\*]*	    /* return COMMENT; */
+MENU				    	return MENUTOK;
+BACK                    	return BACKTOK;
+CUTS                    	return CUTSTOK;
+GLOB						return GLOBTOK;
+PALE						return PALETOK;
+HOTS                        return HOTSTOK;
+WAL[0-1]                    return WALNTOK;
+MICE                        return MICETOK;
+END                         return ENDTOK;
+TIME						return TIMETOK;
+OVER                        return OVERTOK;
+SMEN                        return SMENTOK;
+ESCP                        return ESCPTOK;
+PLAY						return PLAYTOK;
+TURNON						return TONTOK;
+TURNOFF						return TOFFTOK;
+NO_RETURN                   return NRTOK;
+GS_[A-Za-z_0-9]+            return GSSWITCH;
+\/BITMAP					return BITMAPTOK;
+\/BBOX\=					return BBOXTOK;
+\/[A-Za-z_0-9]*  			HYPNO_lval.s = scumm_strdup(HYPNO_text); return FLAG;
+[A-Za-z_][A-Za-z_0-9]*  	HYPNO_lval.s = scumm_strdup(HYPNO_text); return NAME;
+[A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_lval.s = scumm_strdup(HYPNO_text); return FILENAME;
+[\-]?[0-9]+		        	HYPNO_lval.i = atoi(HYPNO_text); return NUM;
+\r\n						return RETTOK;
+[ \t]+		            	/* ignore whitespace */;
+.				        	debug("<no match>"); return *yytext;
+%%
+
+namespace Hypno {
+
+int parse(const char *code) {
+	hot = NULL;
+	hots.clear();
+	YY_BUFFER_STATE bp;
+	yy_delete_buffer(YY_CURRENT_BUFFER);
+	bp = yy_scan_string(code);
+	yy_switch_to_buffer(bp);
+	HYPNO_parse();
+	yy_delete_buffer(bp);
+	return 0;
+}
+
+} // End of namespace Hypno
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
new file mode 100644
index 0000000000..bad8738f9a
--- /dev/null
+++ b/engines/hypno/metaengine.cpp
@@ -0,0 +1,55 @@
+/* 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 "engines/advancedDetector.h"
+#include "graphics/scaler.h"
+
+#include "hypno/hypno.h"
+
+class HypnoMetaEngine : public AdvancedMetaEngine {
+public:
+	const char *getName() const override {
+		return "hypno";
+	}
+
+	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+	//void getSavegameThumbnail(Graphics::Surface &thumb) override;
+};
+
+Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
+	*engine = new Hypno::HypnoEngine(syst, gd);
+	return Common::kNoError;
+}
+
+namespace Hypno {
+
+bool HypnoEngine::isDemo() const {
+	return (bool)(_gameDescription->flags & ADGF_DEMO);
+}
+
+} // End of namespace Hypno
+
+#if PLUGIN_ENABLED_DYNAMIC(HYPNO)
+REGISTER_PLUGIN_DYNAMIC(HYPNO, PLUGIN_TYPE_ENGINE, HypnoMetaEngine);
+#else
+REGISTER_PLUGIN_STATIC(HYPNO, PLUGIN_TYPE_ENGINE, HypnoMetaEngine);
+#endif
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
new file mode 100644
index 0000000000..ed0245afd1
--- /dev/null
+++ b/engines/hypno/module.mk
@@ -0,0 +1,29 @@
+MODULE := engines/hypno
+
+MODULE_OBJS := \
+	cursors.o \
+	metaengine.o \
+	lexer.o \
+	grammar.o \
+	hypno.o
+
+MODULE_DIRS += \
+	engines/hypno
+
+# HACK: Skip this when including the file for detection objects.
+ifeq "$(USE_RULES)" "1"
+hypno-grammar:
+	flex engines/hypno/lexer.l
+	bison engines/hypno/grammar.y
+endif
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_HYPNO), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
+
+# Detection objects
+DETECT_OBJS += $(MODULE)/detection.o


Commit: ce9c242002804a631549b97f69b1e45d2af8c815
    https://github.com/scummvm/scummvm/commit/ce9c242002804a631549b97f69b1e45d2af8c815
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: better parsing and preliminary cursor rendering

Changed paths:
    engines/hypno/cursors.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/lexer.l


diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index 5aada0ac67..cbb85e3c18 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -48,9 +48,9 @@ static const byte MOUSECURSOR_SCI[] = {
 
 static const byte cursorPalette[] = {
 	0x00, 0x00, 0x00,  // Black / Transparent
-	0x01, 0x01, 0x01,  // Gray
-	0xff, 0xff, 0xff,  // White
-	0xff, 0x00, 0x00   // Red
+	0x82, 0x00, 0x00,  // ???
+	0x00, 0x82, 0x00,  // ???
+	0x82, 0x82, 0x00   // ???
 };
 
 struct CursorTable {
@@ -68,18 +68,12 @@ static const CursorTable cursorTable[] = {
 	{ nullptr,      nullptr, nullptr,           0,  0,  0,  0  }
 };
 
-void HypnoEngine::changeCursor(const Common::String &cursor) {
-	const CursorTable *entry = cursorTable;
-	while (entry->name) {
-		if (cursor == entry->name || cursor == entry->aname)
-			break;
-		entry++;
-	}
-	if (!entry->name)
-		return;
+void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
 
-	CursorMan.replaceCursor(entry->buf, entry->w, entry->h, entry->hotspotX, entry->hotspotY, 0);
-	CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
+	Graphics::Surface *entry = decodeFrame(cursor, n, false);
+	debug("cursor: %d %d", entry->w, entry->h);
+	CursorMan.replaceCursor(entry->getPixels(), entry->w, entry->h, 0, 0, 0);
+	//CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
 	CursorMan.showMouse(true);
 }
 
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 2067a322f4..f8bf929c01 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -45,6 +45,9 @@ class Action {
 
 typedef Common::List<Action*> Actions;
 
+class Hotspot;
+typedef Common::Array<Hotspot> Hotspots;
+
 class Hotspot { 
   public:
     HotspotType type;
@@ -53,12 +56,13 @@ class Hotspot {
 	int x0, y0;
 	int x1, y1;
 	Actions actions;
+	Hotspots *smenu;
 };
 
 class Mice : public Action {
   public:
 	Common::String path;
-	int index;
+	uint32 index;
 };
 
 class Palette : public Action {
@@ -70,14 +74,21 @@ class Background : public Action {
   public:
 	Common::String path;
 	Common::Point origin;
+	Common::String condition;
 };
 
-typedef Common::List<Hotspot> Hotspots;
+class Overlay : public Action {
+  public:
+	Common::String path;
+	Common::Point origin;
+	Common::String flag;
+};
+
+
 typedef Common::HashMap<Common::String, Hotspots> Settings;
 
 extern Settings setts;
-extern Hotspot *hot;
-extern Hotspots hots;
+extern Hotspots *hots;
 
 } // End of namespace Hypno
 
diff --git a/engines/hypno/grammar.y b/engines/hypno/grammar.y
index c365d1eda5..5f6c61379e 100644
--- a/engines/hypno/grammar.y
+++ b/engines/hypno/grammar.y
@@ -51,6 +51,7 @@
 %{
 
 //#include "private/private.h"
+#include "common/array.h"
 #include "hypno/grammar.h"
 #include <stdio.h>
 
@@ -61,6 +62,9 @@ extern int HYPNO_lex();
 extern int HYPNO_parse();
 extern int yylineno;
 
+Common::Array<uint32> smenu_idx;
+Common::Array<Hypno::Hotspots *> stack;
+
 void HYPNO_xerror(const char *str) {
 	debug("ERROR: %s", str);
 }
@@ -73,20 +77,27 @@ using namespace Hypno;
 
 %} 
 
-
 %union {
 	char *s;	     	/* string value */
 	int i;	         	/* integer value */
 }
 
-%token<s> NAME FILENAME FLAG COMMENT
+%token<s> NAME FILENAME FLAG COMMENT GSSWITCH
 %token<i> NUM
 %token HOTSTOK CUTSTOK BITMAPTOK BACKTOK RETTOK  TIMETOK PALETOK BBOXTOK OVERTOK WALNTOK MICETOK PLAYTOK ENDTOK 
 %token MENUTOK SMENTOK ESCPTOK NRTOK
-%token GLOBTOK TONTOK TOFFTOK GSSWITCH
+%token GLOBTOK TONTOK TOFFTOK
+
+%type<s> gsswitch
 
 %%
 
+start: init lines 
+       ;
+
+init: { smenu_idx.push_back(-1);
+	    stack.push_back(new Hotspots()); }
+
 lines:   line RETTOK lines
        | line
 	   | end lines            
@@ -96,52 +107,88 @@ end: RETTOK  { debug("implicit END"); }
     ; 
 
 line:    MENUTOK NAME mflag  {
-	     assert(hot == NULL);
-	     hot = new Hotspot(); 
+	     Hotspot *hot = new Hotspot(); 
 		 hot->type = MakeMenu;
-		 debug("MENU %d.", hot->type); 
-	  }
-      |	 HOTSTOK BBOXTOK NUM NUM NUM NUM  { 
-         if (hot != NULL)
-		    hots.push_back(*hot);
+		 hot->smenu = NULL;
+		 debug("MENU %d.", hot->type);
+		 Hotspots *cur = stack.back();
+		 cur->push_back(*hot);
+
+		 // We don't care about menus, only hotspots
+     	 int idx = smenu_idx.back();
+		 idx++;
+		 smenu_idx.pop_back();
+		 smenu_idx.push_back(idx);
 
-	     hot = new Hotspot(); 
+	  }
+      |	 HOTSTOK BBOXTOK NUM NUM NUM NUM  {  
+	     Hotspot *hot = new Hotspot(); 
 		 hot->type = MakeHotspot;
-		 hot->x0 = $3;
-		 debug("HOTS %d", hot->x0); 
+		 hot->smenu = NULL;
+		 debug("HOTS %d.", hot->type);
+		 Hotspots *cur = stack.back();
+		 cur->push_back(*hot); 
       }
 	  |  SMENTOK { 
-		  hot = NULL;
-		  debug("SUBMENU"); }
+		  // This should always point to a hotspot
+		  int idx = smenu_idx.back();
+		  idx++;
+		  smenu_idx.pop_back();
+		  smenu_idx.push_back(idx);
+
+		  Hotspots *cur = stack.back();
+		  Hotspot hot = (*cur)[idx];
+
+		  smenu_idx.push_back(-1);
+		  hot.smenu = new Hotspots();
+	      stack.push_back(hot.smenu);
+		  debug("SUBMENU"); 
+		}
       |  ESCPTOK                                   { debug("ESC SUBMENU"); }
 	  |  TIMETOK NUM                               { debug("TIME %d", $2); } 
       |  BACKTOK FILENAME NUM NUM gsswitch flag    {
-		  	Background *a = new Background();
-		  	a->path = $2;
-		  	a->origin = Common::Point($3, $4);
-		  	hot->actions.push_back(a);
+			Background *a = new Background();
+			a->path = $2;
+			a->origin = Common::Point($3, $4);
+			a->condition = $5;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
 		}
       |  GLOBTOK gsswitch command                  { debug("GLOB."); }
 	  |  PLAYTOK FILENAME NUM NUM gsswitch flag    { debug("PLAY %s.", $2); }
-      |  OVERTOK FILENAME NUM NUM flag    		   { debug("OVER %s.", $2); }
+      |  OVERTOK FILENAME NUM NUM flag { 
+		  	Overlay *a = new Overlay();
+			a->path = $2;
+			a->origin = Common::Point($3, $4);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+	   }
 	  |  PALETOK FILENAME                          {
 			Palette *a = new Palette();
 			a->path = $2; 
-		    hot->actions.push_back(a);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
 		}
 	  |  CUTSTOK FILENAME                          { debug("CUTS %s.", $2); }
 	  |  WALNTOK FILENAME NUM NUM gsswitch flag    { debug("WALN %s %d %d.", $2, $3, $4); } 
 	  |  MICETOK FILENAME NUM {
-		  	  //Mice a;
-			  //a.path = $2; 
-			  //a.index = $3;
-		      //hot->actions.push_back(a);
+		  	//Mice *a = new Mice();
+			//a->path = $2; 
+			//a->index = $3;
+			//if (smenu_idx == -1)
+		    //	hot->actions.push_back(a);
+			//else 
+			//	hots[smenu_idx].smenu.push_back(a);
+			//debug("mice!");
 	  }
 	  |  ENDTOK RETTOK { 
-		  debug("explicit END"); 
-		  if (hot == NULL)
-			error("Invalid END during MIS parsing");
-		  hots.push_back(*hot);
+		  debug("explicit END");
+		  hots = stack.back(); 
+		  stack.pop_back();
+		  smenu_idx.pop_back();
 		  }   		               
 	  ;
 
@@ -153,8 +200,8 @@ flag:   BITMAPTOK                         { debug("flag: BITMAP"); }
       | /* nothing */
 	  ;
 
-gsswitch:   GSSWITCH                      { debug("flag: GS_SWITCH"); }
-          | /* nothing */
+gsswitch:   GSSWITCH                      { $$ = $1; debug("flag: GS_SWITCH"); }
+          | /* nothing */                 { $$ = scumm_strdup(""); }
 	      ;
 
 command:   TONTOK 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index d4b3d73ee1..415ca136bf 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -41,8 +41,7 @@
 
 namespace Hypno {
 
-Hotspot *hot;
-Hotspots hots;
+Hotspots *hots;
 Settings setts;
 
 extern int parse(const char *);
@@ -76,8 +75,8 @@ void HypnoEngine::loadMis(Common::String filename) {
 	test->read(buf, fileSize);
 	buf[fileSize] = '\0';
 	parse(buf);
-	setts[filename] = hots;
-	debug("Loaded hots size: %d", hots.size());
+	setts[filename] = *hots;
+	debug("Loaded hots size: %d", hots->size());
 }
 
 LibData HypnoEngine::loadLib(char *filename) {
@@ -156,7 +155,7 @@ Common::Error HypnoEngine::run() {
 	// Read assets file
 	loadMis("mis/demo.mis");
 	loadMis("mis/order.mis");
-	//loadMis("mis/alley.mis");
+	loadMis("mis/alley.mis");
 	//loadMis("MIS/SHOCTALK.MIS");
 
 	// Initialize graphics
@@ -189,7 +188,7 @@ Common::Error HypnoEngine::run() {
 	Common::String movieIntro = "DEMO/DCINE2.SMK";
 	_nextMovie = logoIntro;
 
-	while (_nextMovie != "" || _currentMovie != "") {
+	while ((_nextMovie != "" || _currentMovie != "") && !shouldQuit()) {
 			while (g_system->getEventManager()->pollEvent(event)) {
 			// Events
 			switch (event.type) {
@@ -240,8 +239,9 @@ Common::Error HypnoEngine::run() {
 		g_system->delayMillis(10);
 	}
 
+	//_nextSetting = "mis/alley.mis";
 	_nextSetting = "mis/demo.mis";
-	changeCursor("default");
+	changeCursor("mouse/cursor1.smk", 0);
 
 	while (!shouldQuit()) {
 		
@@ -345,26 +345,42 @@ Common::Error HypnoEngine::run() {
 
 void HypnoEngine::prepareHotspots(Hotspots hs) {
 	for (Hotspots::const_iterator it = hs.begin(); it != hs.end(); ++it) {
-		debug("hotspot type: %d", it->type);
+		const Hotspot h = *it;
+		debug("hotspot type: %d action size: %d", it->type, it->actions.size());
 		for (Actions::const_iterator itt = it->actions.begin(); itt != it->actions.end(); ++itt) {
 			Action *action = *itt;
 			if (typeid(*action) == typeid(Background))
-				runBackground((Background*) action);
+				runBackground(h, (Background*) action);
+			else if (typeid(*action) == typeid(Overlay))
+				runOverlay(h, (Overlay*) action);
+			//else if (typeid(*action) == typeid(Mice))
+			//	runMice(h, (Mice*) action);
 		}	
 	}
 }
 
-void HypnoEngine::runBackground(Background *a) {
+void HypnoEngine::runBackground(const Hotspot h, Background *a) {
+	Common::Point origin = a->origin;
+	if (a->condition.size() == 0)
+		loadImage(a->path, origin.x, origin.y);
+}
+
+void HypnoEngine::runOverlay(const Hotspot h, Overlay *a) {
 	Common::Point origin = a->origin;
 	loadImage(a->path, origin.x, origin.y);
 }
 
+void HypnoEngine::runMice(const Hotspot h, Mice *a) {
+	if (h.type == MakeMenu)
+    	changeCursor(a->path, a->index);
+}
+
 void HypnoEngine::loadImage(const Common::String &name, int x, int y) {
 	Graphics::Surface *surf = decodeFrame(name, 0);
 	_compositeSurface->transBlitFrom(*surf, _origin + Common::Point(x, y), _transparentColor);
 }
 
-Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n) {
+Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, bool convert) {
 	Common::File *file = new Common::File();
 	Common::String path = convertPath(name);
 
@@ -379,16 +395,20 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n) {
 		_videoDecoder->decodeNextFrame();
 
 	const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
-	Graphics::Surface *sframe = frame->scale(_screenW, _screenH);
-	Graphics::Surface *cframe = sframe->convertTo(_pixelFormat, _videoDecoder->getPalette());
+	Graphics::Surface *rframe;
+
+	if (convert) {
+		rframe = frame->convertTo(_pixelFormat, _videoDecoder->getPalette());
+	} else {
+		rframe = frame->convertTo(frame->format, _videoDecoder->getPalette());
+		//rframe->create(frame->w, frame->h, frame->format);
+		//rframe->copyRectToSurface(frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h);
+	}
 
-	sframe->free();
-	delete sframe;
-	
 	delete _videoDecoder;
 	_videoDecoder = nullptr;
 
-	return cframe;
+	return rframe;
 }
 
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 2d3bd2e6e7..cd005b3229 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -125,18 +125,20 @@ public:
 	void skipVideo();
 
 	Graphics::Surface *decodeImage(const Common::String &file);
-	Graphics::Surface *decodeFrame(const Common::String &name, int frame);
+	Graphics::Surface *decodeFrame(const Common::String &name, int frame, bool convert = true);
 	void loadImage(const Common::String &file, int x, int y);
 	void drawScreenFrame();
 
 	// Cursors
-	void changeCursor(const Common::String &);
+	void changeCursor(const Common::String &, uint32);
 	Common::String getInventoryCursor();
 	Common::String getExitCursor();
 
-	// Rendering
+	// Actions
 	void prepareHotspots(Hotspots hs);
-    void runBackground(Background *a);
+    void runBackground(const Hotspot h, Background *a);
+	void runOverlay(const Hotspot h, Overlay *a);
+	void runMice(const Hotspot h, Mice *a);
 
 	Graphics::ManagedSurface *_compositeSurface;
 	Graphics::Surface *loadMask(const Common::String &, int, int, bool);
diff --git a/engines/hypno/lexer.l b/engines/hypno/lexer.l
index a322189087..f17a02dd2b 100644
--- a/engines/hypno/lexer.l
+++ b/engines/hypno/lexer.l
@@ -57,7 +57,7 @@ PLAY						return PLAYTOK;
 TURNON						return TONTOK;
 TURNOFF						return TOFFTOK;
 NO_RETURN                   return NRTOK;
-GS_[A-Za-z_0-9]+            return GSSWITCH;
+GS_[A-Za-z_0-9]+            HYPNO_lval.s = scumm_strdup(HYPNO_text); return GSSWITCH;
 \/BITMAP					return BITMAPTOK;
 \/BBOX\=					return BBOXTOK;
 \/[A-Za-z_0-9]*  			HYPNO_lval.s = scumm_strdup(HYPNO_text); return FLAG;
@@ -72,8 +72,6 @@ GS_[A-Za-z_0-9]+            return GSSWITCH;
 namespace Hypno {
 
 int parse(const char *code) {
-	hot = NULL;
-	hots.clear();
 	YY_BUFFER_STATE bp;
 	yy_delete_buffer(YY_CURRENT_BUFFER);
 	bp = yy_scan_string(code);


Commit: 212c177ab34d4048c078ff0a8d175b4c89799810
    https://github.com/scummvm/scummvm/commit/212c177ab34d4048c078ff0a8d175b4c89799810
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: better parsing, more actions and improved detection tables

Changed paths:
    engines/hypno/cursors.cpp
    engines/hypno/detection.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h


diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index cbb85e3c18..f2f79b4b8a 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -71,7 +71,7 @@ static const CursorTable cursorTable[] = {
 void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
 
 	Graphics::Surface *entry = decodeFrame(cursor, n, false);
-	debug("cursor: %d %d", entry->w, entry->h);
+	//debug("cursor: %d %d", entry->w, entry->h);
 	CursorMan.replaceCursor(entry->getPixels(), entry->w, entry->h, 0, 0, 0);
 	//CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
 	CursorMan.showMouse(true);
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 718b597ed5..a7d86ca4c8 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -34,7 +34,7 @@ static const DebugChannelDef debugFlagList[] = {
 
 namespace Hypno {
 static const PlainGameDescriptor hypnoGames[] = {
-	{ "sinister-six", "Spiderman and the Sinister Six" },
+	{ "sinister-six", "Marvel Comics Spider-Man: The Sinister Six" },
 	{ 0, 0 }
 };
 
@@ -49,6 +49,16 @@ static const ADGameDescription gameDescriptions[] = {
 		ADGF_TESTING | ADGF_DEMO,
 		GUIO1(GUIO_NOMIDI)
 	},
+	{
+		"sinister-six", // US release
+		"",
+		AD_ENTRY2s("COMBAT.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 255115,
+  				   "SPIDER.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 248056),
+		Common::EN_USA,
+		Common::kPlatformWindows,
+		ADGF_TESTING,
+		GUIO1(GUIO_NOMIDI)
+	},
 	AD_TABLE_END_MARKER
 };
 } // End of namespace Hypno
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index f8bf929c01..137fdbddd4 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -47,14 +47,14 @@ typedef Common::List<Action*> Actions;
 
 class Hotspot;
 typedef Common::Array<Hotspot> Hotspots;
+typedef Common::Array<Hotspots *> HotspotsStack;
 
 class Hotspot { 
   public:
     HotspotType type;
     Common::String stype;
 	Common::String stypeFlag;
-	int x0, y0;
-	int x1, y1;
+	Common::Rect rect;
 	Actions actions;
 	Hotspots *smenu;
 };
@@ -84,11 +84,19 @@ class Overlay : public Action {
 	Common::String flag;
 };
 
+class Escape : public Action {
+};
+
+class Cutscene : public Action {
+  public:
+	Common::String path;
+};
+
 
 typedef Common::HashMap<Common::String, Hotspots> Settings;
 
-extern Settings setts;
-extern Hotspots *hots;
+extern Hotspots *g_parsedHots;
+extern Settings g_settings;
 
 } // End of namespace Hypno
 
diff --git a/engines/hypno/grammar.y b/engines/hypno/grammar.y
index 5f6c61379e..40cbfe14ce 100644
--- a/engines/hypno/grammar.y
+++ b/engines/hypno/grammar.y
@@ -63,7 +63,7 @@ extern int HYPNO_parse();
 extern int yylineno;
 
 Common::Array<uint32> smenu_idx;
-Common::Array<Hypno::Hotspots *> stack;
+Hypno::HotspotsStack stack;
 
 void HYPNO_xerror(const char *str) {
 	debug("ERROR: %s", str);
@@ -109,6 +109,7 @@ end: RETTOK  { debug("implicit END"); }
 line:    MENUTOK NAME mflag  {
 	     Hotspot *hot = new Hotspot(); 
 		 hot->type = MakeMenu;
+		 hot->stype = $2;
 		 hot->smenu = NULL;
 		 debug("MENU %d.", hot->type);
 		 Hotspots *cur = stack.back();
@@ -125,6 +126,7 @@ line:    MENUTOK NAME mflag  {
 	     Hotspot *hot = new Hotspot(); 
 		 hot->type = MakeHotspot;
 		 hot->smenu = NULL;
+		 hot->rect = Common::Rect($3, $4, $5, $6);
 		 debug("HOTS %d.", hot->type);
 		 Hotspots *cur = stack.back();
 		 cur->push_back(*hot); 
@@ -137,14 +139,19 @@ line:    MENUTOK NAME mflag  {
 		  smenu_idx.push_back(idx);
 
 		  Hotspots *cur = stack.back();
-		  Hotspot hot = (*cur)[idx];
+		  Hotspot *hot = &(*cur)[idx];
 
 		  smenu_idx.push_back(-1);
-		  hot.smenu = new Hotspots();
-	      stack.push_back(hot.smenu);
+		  hot->smenu = new Hotspots();
+	      stack.push_back(hot->smenu);
 		  debug("SUBMENU"); 
 		}
-      |  ESCPTOK                                   { debug("ESC SUBMENU"); }
+      |  ESCPTOK  {
+			Escape *a = new Escape();
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+		  	debug("ESC SUBMENU"); }
 	  |  TIMETOK NUM                               { debug("TIME %d", $2); } 
       |  BACKTOK FILENAME NUM NUM gsswitch flag    {
 			Background *a = new Background();
@@ -172,21 +179,26 @@ line:    MENUTOK NAME mflag  {
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
 		}
-	  |  CUTSTOK FILENAME                          { debug("CUTS %s.", $2); }
+	  |  CUTSTOK FILENAME { 
+		  	Cutscene *a = new Cutscene();
+			a->path = $2;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);		  
+		    debug("CUTS %s.", $2); 
+		}
 	  |  WALNTOK FILENAME NUM NUM gsswitch flag    { debug("WALN %s %d %d.", $2, $3, $4); } 
 	  |  MICETOK FILENAME NUM {
-		  	//Mice *a = new Mice();
-			//a->path = $2; 
-			//a->index = $3;
-			//if (smenu_idx == -1)
-		    //	hot->actions.push_back(a);
-			//else 
-			//	hots[smenu_idx].smenu.push_back(a);
-			//debug("mice!");
+		  	Mice *a = new Mice();
+			a->path = $2; 
+			a->index = $3-1;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
 	  }
 	  |  ENDTOK RETTOK { 
 		  debug("explicit END");
-		  hots = stack.back(); 
+		  g_parsedHots = stack.back(); 
 		  stack.pop_back();
 		  smenu_idx.pop_back();
 		  }   		               
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 415ca136bf..70ddcd9d0c 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -41,15 +41,16 @@
 
 namespace Hypno {
 
-Hotspots *hots;
-Settings setts;
+Hotspots *g_parsedHots;
+Settings g_settings;
 
 extern int parse(const char *);
 
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	: Engine(syst), _gameDescription(gd), _image(nullptr), _videoDecoder(nullptr),
-	  _compositeSurface(nullptr), _transparentColor(0), _frame(nullptr),
-	  _maxNumberClicks(0), _sirenWarning(0), _screenW(640), _screenH(480) {
+	  _compositeSurface(nullptr), _transparentColor(0), _frame(nullptr), 
+	  _nextHotsToAdd(nullptr), _nextHotsToRemove(nullptr),
+	  _screenW(640), _screenH(480) {
 	_rnd = new Common::RandomSource("hypno");
 }
 
@@ -66,7 +67,6 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 void HypnoEngine::loadMis(Common::String filename) {
     filename = convertPath(filename);
 	Common::File *test = new Common::File();
-	Common::SeekableReadStream *file = NULL;
 	assert(isDemo());
     assert(test->open(filename.c_str()));
 
@@ -75,8 +75,8 @@ void HypnoEngine::loadMis(Common::String filename) {
 	test->read(buf, fileSize);
 	buf[fileSize] = '\0';
 	parse(buf);
-	setts[filename] = *hots;
-	debug("Loaded hots size: %d", hots->size());
+	g_settings[filename] = *g_parsedHots;
+	debug("Loaded hots size: %d", g_parsedHots->size());
 }
 
 LibData HypnoEngine::loadLib(char *filename) {
@@ -96,7 +96,7 @@ LibData HypnoEngine::loadLib(char *filename) {
 		cont = true;
 		entry.clear();
 		for (j = 0; j < 24; j++) {
-			if (cont && it[i] != 0x96 && it[i] != NULL) {
+			if (cont && it[i] != 0x96 && it[i] != 0x0) {
 				entry += char(it[i]);
 			}
 			else
@@ -130,9 +130,8 @@ LibData HypnoEngine::loadLib(char *filename) {
 Common::Error HypnoEngine::run() {
 	_language = Common::parseLanguage(ConfMan.get("language"));
 	_platform = Common::parsePlatform(ConfMan.get("platform"));
-    /*
 	LibData files = loadLib("C_MISC/MISSIONS.LIB");
-	uint32 i = 0;
+	/*uint32 i = 0;
 	uint32 j = 0;
 	uint32 k = 0;
 
@@ -164,8 +163,7 @@ Common::Error HypnoEngine::run() {
 	if (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8())
 		return Common::kUnsupportedColorMode;
 
-	_transparentColor = _pixelFormat.RGBToColor(0, 255, 0);
-	_safeColor = _pixelFormat.RGBToColor(65, 65, 65);
+	_transparentColor = _pixelFormat.RGBToColor(0, 0x82, 0);
 	screenRect = Common::Rect(0, 0, _screenW, _screenH);
 	//changeCursor("default");
 	_origin = Common::Point(0, 0);
@@ -184,22 +182,52 @@ Common::Error HypnoEngine::run() {
 	} else {
 		_nextSetting = getGoIntroSetting();
 	}*/
-	Common::String logoIntro = "DEMO/DCINE1.SMK";
-	Common::String movieIntro = "DEMO/DCINE2.SMK";
-	_nextMovie = logoIntro;
+	runIntro("DEMO/DCINE1.SMK", "DEMO/DCINE2.SMK");
+	while (!shouldQuit()) {
+		runMis("mis/alley.mis");
+	}
+	return Common::kNoError;
+}
 
-	while ((_nextMovie != "" || _currentMovie != "") && !shouldQuit()) {
-			while (g_system->getEventManager()->pollEvent(event)) {
+
+void HypnoEngine::runMis(Common::String name) {
+	Common::Event event;
+	Common::Point mousePos;
+	
+	stack.clear();
+	assert(g_settings.contains(name));
+	_nextHotsToAdd = &g_settings[name];
+	changeCursor("mouse/cursor1.smk", 0);
+
+	while (!shouldQuit()) {
+		
+		while (g_system->getEventManager()->pollEvent(event)) {
+			mousePos = g_system->getEventManager()->getMousePos();
 			// Events
 			switch (event.type) {
 			case Common::EVENT_KEYDOWN:
 				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder)
-					// Ugly hack to play two intro movies.
-					if (_currentMovie == logoIntro)
-						_nextMovie = movieIntro;
-					else
-					    skipVideo();
+					skipVideo();
+
+				break;
 
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_LBUTTONDOWN:
+				if (!_nextHotsToAdd || !_nextHotsToRemove)
+				 	clickedHotspot(mousePos);
+				break;
+
+			case Common::EVENT_MOUSEMOVE:
+				// Reset cursor to default
+				//changeCursor("default");
+				// The following functions will return true
+				// if the cursor is changed
+				if (hoverHotspot(mousePos)) {
+				} else
+					changeCursor("mouse/cursor1.smk", 0);
 				break;
 
 			default:
@@ -209,6 +237,7 @@ Common::Error HypnoEngine::run() {
 
 		// Movies
 		if (!_nextMovie.empty()) {
+			//removeTimer();
 			_videoDecoder = new Video::SmackerDecoder();
 			playVideo(_nextMovie);
 			_currentMovie = _nextMovie;
@@ -223,11 +252,12 @@ Common::Error HypnoEngine::run() {
 				_videoDecoder->close();
 				delete _videoDecoder;
 				_videoDecoder = nullptr;
-				// Ugly hack to play two intro movies.
-				if (_currentMovie == logoIntro)
-					_nextMovie = movieIntro;
-				else 
-					_nextMovie = "";
+				_currentMovie = "";
+
+				// refresh current scene
+				runMenu(*stack.back());
+				drawScreen();
+
 			} else if (_videoDecoder->needsUpdate()) {
 				drawScreen();
 				g_system->delayMillis(10);
@@ -235,63 +265,42 @@ Common::Error HypnoEngine::run() {
 			continue;
 		}
 
+		if (_nextHotsToRemove) {
+			debug("Removing a hotspot list!");
+			stack.pop_back();
+			runMenu(*stack.back());
+			_nextHotsToRemove = NULL;
+			drawScreen();
+		} else if (_nextHotsToAdd) {
+			debug("Adding a hotspot list!");
+			//clearAreas();
+			stack.push_back(_nextHotsToAdd);
+			runMenu(*stack.back());
+			_nextHotsToAdd = NULL;
+			drawScreen();
+		}
+
 		g_system->updateScreen();
 		g_system->delayMillis(10);
 	}
+}
 
-	//_nextSetting = "mis/alley.mis";
-	_nextSetting = "mis/demo.mis";
-	changeCursor("mouse/cursor1.smk", 0);
+void HypnoEngine::runIntro(Common::String logoIntro, Common::String movieIntro) {
+	Common::Event event;
+	_nextMovie = logoIntro;
 
-	while (!shouldQuit()) {
-		
-		while (g_system->getEventManager()->pollEvent(event)) {
-			mousePos = g_system->getEventManager()->getMousePos();
+	while ((_nextMovie != "" || _currentMovie != "") && !shouldQuit()) {
+			while (g_system->getEventManager()->pollEvent(event)) {
 			// Events
 			switch (event.type) {
 			case Common::EVENT_KEYDOWN:
-				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder)
-					skipVideo();
-
-				break;
-
-			case Common::EVENT_QUIT:
-			case Common::EVENT_RETURN_TO_LAUNCHER:
-				break;
-
-			case Common::EVENT_LBUTTONDOWN:
-				// if (selectDossierNextSuspect(mousePos))
-				// 	break;
-				// else if (selectDossierPrevSuspect(mousePos))
-				// 	break;
-				// else if (selectDossierNextSheet(mousePos))
-				// 	break;
-				// else if (selectDossierPrevSheet(mousePos))
-				// 	break;
-				// else if (selectSafeDigit(mousePos))
-				// 	break;
-
-				// selectPauseMovie(mousePos);
-				// selectPhoneArea(mousePos);
-				// selectPoliceRadioArea(mousePos);
-				// selectAMRadioArea(mousePos);
-				// selectLoadGame(mousePos);
-				// selectSaveGame(mousePos);
-				// if (_nextSetting.empty())
-				// 	selectMask(mousePos);
-				// if (_nextSetting.empty())
-				// 	selectExit(mousePos);
-				break;
+				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder) {
+					if (_currentMovie == logoIntro)
+						_nextMovie = movieIntro;
+					else
+					    skipVideo();
+				}
 
-			case Common::EVENT_MOUSEMOVE:
-				// Reset cursor to default
-				//changeCursor("default");
-				// The following functions will return true
-				// if the cursor is changed
-				//if (cursorPauseMovie(mousePos)) {
-				//} else if (cursorMask(mousePos)) {
-				//} else
-				//	cursorExit(mousePos);
 				break;
 
 			default:
@@ -301,7 +310,6 @@ Common::Error HypnoEngine::run() {
 
 		// Movies
 		if (!_nextMovie.empty()) {
-			//removeTimer();
 			_videoDecoder = new Video::SmackerDecoder();
 			playVideo(_nextMovie);
 			_currentMovie = _nextMovie;
@@ -316,7 +324,10 @@ Common::Error HypnoEngine::run() {
 				_videoDecoder->close();
 				delete _videoDecoder;
 				_videoDecoder = nullptr;
-				_currentMovie = "";
+				if (_currentMovie == logoIntro)
+					_nextMovie = movieIntro;
+				else 
+					_nextMovie = "";
 			} else if (_videoDecoder->needsUpdate()) {
 				drawScreen();
 				g_system->delayMillis(10);
@@ -324,39 +335,33 @@ Common::Error HypnoEngine::run() {
 			continue;
 		}
 
-		if (!_nextSetting.empty()) {
-
-			debug("Executing %s", _nextSetting.c_str());
-			//clearAreas();
-			_currentSetting = _nextSetting;
-			//Settings::g_setts->load(_nextSetting);
-			prepareHotspots(setts[_currentSetting]);
-			_nextSetting = "";
-			//Gen::g_vm->run();
-			//changeCursor("default");
-			drawScreen();
-		}
-
 		g_system->updateScreen();
 		g_system->delayMillis(10);
 	}
-	return Common::kNoError;
 }
 
-void HypnoEngine::prepareHotspots(Hotspots hs) {
-	for (Hotspots::const_iterator it = hs.begin(); it != hs.end(); ++it) {
-		const Hotspot h = *it;
-		debug("hotspot type: %d action size: %d", it->type, it->actions.size());
-		for (Actions::const_iterator itt = it->actions.begin(); itt != it->actions.end(); ++itt) {
-			Action *action = *itt;
-			if (typeid(*action) == typeid(Background))
-				runBackground(h, (Background*) action);
-			else if (typeid(*action) == typeid(Overlay))
-				runOverlay(h, (Overlay*) action);
-			//else if (typeid(*action) == typeid(Mice))
-			//	runMice(h, (Mice*) action);
-		}	
+
+//Actions
+
+void HypnoEngine::runMenu(Hotspots hs) {
+	const Hotspot h = *hs.begin();
+	assert(h.type == MakeMenu);
+
+	debug("hotspot actions size: %d", h.actions.size());
+	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
+		Action *action = *itt;
+		if (typeid(*action) == typeid(Background))
+			runBackground(h, (Background*) action);
+		else if (typeid(*action) == typeid(Overlay))
+			runOverlay(h, (Overlay*) action);
+		//else if (typeid(*action) == typeid(Mice))
+		//	runMice(h, (Mice*) action);
 	}
+
+	if (h.stype == "SINGLE_RUN")
+		loadImage("int_main/mainbutt.smk", 0, 0);
+	else if (h.stype == "AUTO_BUTTONS")
+		loadImage("int_main/resume.smk", 0, 0);
 }
 
 void HypnoEngine::runBackground(const Hotspot h, Background *a) {
@@ -371,8 +376,92 @@ void HypnoEngine::runOverlay(const Hotspot h, Overlay *a) {
 }
 
 void HypnoEngine::runMice(const Hotspot h, Mice *a) {
-	if (h.type == MakeMenu)
-    	changeCursor(a->path, a->index);
+    changeCursor(a->path, a->index);
+}
+
+void HypnoEngine::runEscape(const Hotspot h, Escape *a) {
+    _nextHotsToRemove = stack.back();
+}
+
+void HypnoEngine::runCutscene(const Hotspot h, Cutscene *a) {
+    _nextMovie = a->path;
+}
+
+// Hotspots
+
+void HypnoEngine::clickedHotspot(Common::Point mousePos) {
+	debug("clicked in %d %d", mousePos.x, mousePos.y);
+	Hotspots *hots = stack.back();
+	Hotspot selected;
+	bool found = false;
+	int rs = 100000000;
+	int cs = 0;
+	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
+		const Hotspot h = *it;
+		if (h.type != MakeHotspot)
+			continue;
+
+		cs = h.rect.width() * h.rect.height();
+		if (h.rect.contains(mousePos)) {
+			if (cs < rs) {
+				selected = h;
+				found = true;
+				rs = cs;
+			}
+		}
+	}
+	if (found) {
+		//debug("Hotspot found! %x", selected.smenu);
+		if (selected.smenu) {
+			debug("SMenu found!");
+			assert(selected.smenu->size() > 0);
+			_nextHotsToAdd = selected.smenu;
+		}
+
+		debug("hotspot clicked actions size: %d", selected.actions.size());
+		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
+			Action *action = *itt;
+			if (typeid(*action) == typeid(Escape))
+				runEscape(selected, (Escape*) action);
+			if (typeid(*action) == typeid(Cutscene))
+				runCutscene(selected, (Cutscene*) action);
+		}
+
+	}
+}
+
+bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
+	Hotspots *hots = stack.back();
+	Hotspot selected;
+	bool found = false;
+	int rs = 100000000;
+	int cs = 0;
+	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
+		const Hotspot h = *it;
+		if (h.type != MakeHotspot)
+			continue;
+
+		cs = h.rect.width() * h.rect.height();
+		if (h.rect.contains(mousePos)) {
+			if (cs < rs) {
+				selected = h;
+				found = true;
+				rs = cs;
+			}
+		}
+	}
+	if (found) {
+		debug("Hovered over %d %d %d %d!", selected.rect.left, selected.rect.top, selected.rect.bottom, selected.rect.right);
+
+		//debug("hotspot actions size: %d", h.actions.size());
+		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
+			Action *action = *itt;
+			if (typeid(*action) == typeid(Mice))
+				runMice(selected, (Mice*) action);
+		}
+		return true;
+	}
+	return false;
 }
 
 void HypnoEngine::loadImage(const Common::String &name, int x, int y) {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index cd005b3229..96e0d5e0c1 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -82,6 +82,10 @@ public:
 	Common::InstallShieldV3 _installerArchive;
 
 	Common::Error run() override;
+	void runIntro(Common::String logoIntro, Common::String movieIntro);
+	void runMis(Common::String name);
+
+
 	void restartGame();
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
@@ -93,11 +97,8 @@ public:
 	void initFuncs();
 
 	// User input
-	void selectPauseMovie(Common::Point);
-	void selectMask(Common::Point);
-	void selectExit(Common::Point);
-	void selectLoadGame(Common::Point);
-	void selectSaveGame(Common::Point);
+	void clickedHotspot(Common::Point);
+	bool hoverHotspot(Common::Point);
 
 	// Cursors
 	bool cursorPauseMovie(Common::Point);
@@ -135,10 +136,12 @@ public:
 	Common::String getExitCursor();
 
 	// Actions
-	void prepareHotspots(Hotspots hs);
+	void runMenu(Hotspots hs);
     void runBackground(const Hotspot h, Background *a);
 	void runOverlay(const Hotspot h, Overlay *a);
 	void runMice(const Hotspot h, Mice *a);
+	void runEscape(const Hotspot h, Escape *a);
+	void runCutscene(const Hotspot h, Cutscene *a);
 
 	Graphics::ManagedSurface *_compositeSurface;
 	Graphics::Surface *loadMask(const Common::String &, int, int, bool);
@@ -153,46 +156,15 @@ public:
 	Common::Point _origin;
 	void drawScreen();
 
-	// settings
-	Common::String _nextSetting;
-	Common::String _pausedSetting;
-	Common::String _currentSetting;
-	Common::String getPauseMovieSetting();
-	Common::String getGoIntroSetting();
-	Common::String getMainDesktopSetting();
-	Common::String getPOGoBustMovieSetting();
-	Common::String getPoliceBustFromMOSetting();
-	Common::String getAlternateGameVariable();
-	Common::String getPoliceIndexVariable();
-	Common::String getWallSafeValueVariable();
+	// hotspots
+	Hotspots *_nextHotsToAdd;
+	Hotspots *_nextHotsToRemove;
+	HotspotsStack stack;
 
 	// movies
 	Common::String _nextMovie;
 	Common::String _currentMovie;
 
-	// Dossiers
-	bool selectDossierNextSuspect(Common::Point);
-	bool selectDossierPrevSuspect(Common::Point);
-	bool selectDossierNextSheet(Common::Point);
-	bool selectDossierPrevSheet(Common::Point);
-	void loadDossier();
-
-	// Police Bust
-	void policeBust();
-	bool _policeBustEnabled;
-	void startPoliceBust();
-	void checkPoliceBust();
-	int _numberClicks;
-	int _maxNumberClicks;
-	int _sirenWarning;
-	Common::String _policeBustSetting;
-
-	// Diary
-	Common::String _diaryLocPrefix;
-	void loadLocations(const Common::Rect &);
-	void loadInventory(uint32, const Common::Rect &, const Common::Rect &);
-	bool _toTake;
-
 	// Save/Load games
 	int _mode;
 	bool _modified;
@@ -206,34 +178,6 @@ public:
 	bool isSoundActive();
 	bool _noStopSounds;
 
-	Common::String getPaperShuffleSound();
-	Common::String _globalAudioPath;
-
-	Common::String getTakeSound();
-	Common::String getTakeLeaveSound();
-	Common::String getLeaveSound();
-	Common::String _sirenSound;
-
-	// Radios
-	Common::String _infaceRadioPath;
-	Common::String _phonePrefix;
-	Common::String _phoneCallSound;
-
-	Common::String getRandomPhoneClip(const char *, int, int);
-	void selectAMRadioArea(Common::Point);
-	void selectPoliceRadioArea(Common::Point);
-	void selectPhoneArea(Common::Point);
-	void checkPhoneCall();
-
-	// Safe
-	uint32 _safeColor;
-	Common::String _safeNumberPath;
-	Common::Rect _safeDigitRect[3];
-
-	bool selectSafeDigit(Common::Point);
-	void addSafeDigit(uint32, Common::Rect*);
-	void renderSafeDigit(uint32);
-
 	// Random values
 	bool getRandomBool(uint);
 


Commit: 104a141840a71f2cee51d85dd09f57fa28b9a61b
    https://github.com/scummvm/scummvm/commit/104a141840a71f2cee51d85dd09f57fa28b9a61b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: state variables, more actions and improved video playback

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/grammar.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/lexer.l


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 137fdbddd4..7747670fd9 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -48,6 +48,7 @@ typedef Common::List<Action*> Actions;
 class Hotspot;
 typedef Common::Array<Hotspot> Hotspots;
 typedef Common::Array<Hotspots *> HotspotsStack;
+typedef Common::List<Common::String> Movies;
 
 class Hotspot { 
   public:
@@ -55,6 +56,7 @@ class Hotspot {
     Common::String stype;
 	Common::String stypeFlag;
 	Common::Rect rect;
+	Common::String setting;
 	Actions actions;
 	Hotspots *smenu;
 };
@@ -87,16 +89,45 @@ class Overlay : public Action {
 class Escape : public Action {
 };
 
+class Quit : public Action {
+};
+
 class Cutscene : public Action {
   public:
 	Common::String path;
 };
 
+class Play : public Action {
+  public:
+	Common::String path;
+	Common::Point origin;
+	Common::String condition;
+	Common::String flag;
+};
+
+class WalN : public Action {
+  public:
+	Common::String path;
+	Common::Point origin;
+	Common::String condition;
+	Common::String flag;
+};
+
+class Global : public Action {
+  public:
+	Common::String variable;
+	Common::String command;
+};
 
-typedef Common::HashMap<Common::String, Hotspots> Settings;
+class Level {
+  public:
+	Hotspots hots;
+	Movies intros;
+};
 
+typedef Common::HashMap<Common::String, Level> Levels;
 extern Hotspots *g_parsedHots;
-extern Settings g_settings;
+//extern Settings g_settings;
 
 } // End of namespace Hypno
 
diff --git a/engines/hypno/grammar.y b/engines/hypno/grammar.y
index 40cbfe14ce..5519f5bb7f 100644
--- a/engines/hypno/grammar.y
+++ b/engines/hypno/grammar.y
@@ -82,13 +82,13 @@ using namespace Hypno;
 	int i;	         	/* integer value */
 }
 
-%token<s> NAME FILENAME FLAG COMMENT GSSWITCH
+%token<s> NAME FILENAME FLAG COMMENT GSSWITCH COMMAND
 %token<i> NUM
-%token HOTSTOK CUTSTOK BITMAPTOK BACKTOK RETTOK  TIMETOK PALETOK BBOXTOK OVERTOK WALNTOK MICETOK PLAYTOK ENDTOK 
+%token HOTSTOK CUTSTOK BACKTOK RETTOK  TIMETOK PALETOK BBOXTOK OVERTOK WALNTOK MICETOK PLAYTOK ENDTOK 
 %token MENUTOK SMENTOK ESCPTOK NRTOK
 %token GLOBTOK TONTOK TOFFTOK
 
-%type<s> gsswitch
+%type<s> gsswitch flag
 
 %%
 
@@ -162,8 +162,25 @@ line:    MENUTOK NAME mflag  {
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
 		}
-      |  GLOBTOK gsswitch command                  { debug("GLOB."); }
-	  |  PLAYTOK FILENAME NUM NUM gsswitch flag    { debug("PLAY %s.", $2); }
+      |  GLOBTOK GSSWITCH NAME  { 
+		    Global *a = new Global();
+			a->variable = $2;
+			a->command = $3;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+			debug("GLOB."); 
+		}
+	  |  PLAYTOK FILENAME NUM NUM gsswitch flag { 
+			Play *a = new Play();
+			a->path = $2;
+			a->origin = Common::Point($3, $4);
+			a->condition = $5;
+			a->flag = $6;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);		  
+		    debug("PLAY %s.", $2); }
       |  OVERTOK FILENAME NUM NUM flag { 
 		  	Overlay *a = new Overlay();
 			a->path = $2;
@@ -187,7 +204,16 @@ line:    MENUTOK NAME mflag  {
 			hot->actions.push_back(a);		  
 		    debug("CUTS %s.", $2); 
 		}
-	  |  WALNTOK FILENAME NUM NUM gsswitch flag    { debug("WALN %s %d %d.", $2, $3, $4); } 
+	  |  WALNTOK FILENAME NUM NUM gsswitch flag  { 
+			WalN *a = new WalN();
+			a->path = $2;
+			a->origin = Common::Point($3, $4);
+			a->condition = $5;
+			a->flag = $6;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);		  
+		    debug("WALN %s %d %d.", $2, $3, $4); } 
 	  |  MICETOK FILENAME NUM {
 		  	Mice *a = new Mice();
 			a->path = $2; 
@@ -208,14 +234,10 @@ mflag:  NRTOK
       | /*nothing*/
 	  ;
 
-flag:   BITMAPTOK                         { debug("flag: BITMAP"); }
-      | /* nothing */
+flag:   FLAG             { $$ = $1; debug("flag: %s", $1); }
+      | /* nothing */	 { $$ = scumm_strdup(""); }
 	  ;
 
-gsswitch:   GSSWITCH                      { $$ = $1; debug("flag: GS_SWITCH"); }
+gsswitch:   GSSWITCH                      { $$ = $1; debug("switch %s", $1); }
           | /* nothing */                 { $$ = scumm_strdup(""); }
-	      ;
-
-command:   TONTOK 
-         | TOFFTOK
-		 ;
\ No newline at end of file
+	      ;
\ No newline at end of file
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 70ddcd9d0c..1d3b848247 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -42,21 +42,50 @@
 namespace Hypno {
 
 Hotspots *g_parsedHots;
-Settings g_settings;
+//Settings g_settings;
+
+const static char* levelVariables[] = {
+	"GS_NONE",
+	"GS_SCTEXT",
+	"GS_AMBIENT",
+	"GS_MUSIC",
+	"GS_VOLUME",
+	"GS_MOUSESPEED",
+	"GS_MOUSEON",
+	"GS_LEVELCOMPLETE",
+	"GS_LEVELWON",
+	"GS_CHEATS",
+	"GS_SWITCH0",
+	"GS_SWITCH1",
+	"GS_SWITCH2",
+	"GS_SWITCH3",
+	"GS_SWITCH4",
+	"GS_SWITCH5",
+	"GS_SWITCH6",
+	"GS_SWITCH7",
+	"GS_SWITCH8",
+	"GS_SWITCH9",
+	"GS_SWITCH10",
+	"GS_SWITCH11",
+	"GS_SWITCH12",
+	"GS_COMBATJSON",
+	"GS_COMBATLEVEL",
+	"GS_PUZZLELEVEL",
+	NULL
+};
 
 extern int parse(const char *);
 
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	: Engine(syst), _gameDescription(gd), _image(nullptr), _videoDecoder(nullptr),
-	  _compositeSurface(nullptr), _transparentColor(0), _frame(nullptr), 
+	  _compositeSurface(nullptr), _transparentColor(0), 
 	  _nextHotsToAdd(nullptr), _nextHotsToRemove(nullptr),
 	  _screenW(640), _screenH(480) {
 	_rnd = new Common::RandomSource("hypno");
 }
 
 HypnoEngine::~HypnoEngine() {
-	// Dispose your resources here
-	delete _frame;
+	// Dispose your resources
 	delete _rnd;
 }
 
@@ -75,7 +104,9 @@ void HypnoEngine::loadMis(Common::String filename) {
 	test->read(buf, fileSize);
 	buf[fileSize] = '\0';
 	parse(buf);
-	g_settings[filename] = *g_parsedHots;
+	Level level;
+	level.hots = *g_parsedHots; 
+	_levels[filename] = level;
 	debug("Loaded hots size: %d", g_parsedHots->size());
 }
 
@@ -127,6 +158,18 @@ LibData HypnoEngine::loadLib(char *filename) {
 	return r;
 }
 
+void HypnoEngine::resetLevelState() {
+	uint32 i = 0;
+	while (levelVariables[i]) {
+		_levelState[levelVariables[i]] = 0;
+		i++;
+	}
+}
+
+bool HypnoEngine::checkLevelCompleted() {
+	return _levelState["GS_LEVELCOMPLETE"];
+}
+
 Common::Error HypnoEngine::run() {
 	_language = Common::parseLanguage(ConfMan.get("language"));
 	_platform = Common::parsePlatform(ConfMan.get("platform"));
@@ -151,10 +194,27 @@ Common::Error HypnoEngine::run() {
 		}
 	}
 	*/	
-	// Read assets file
+
+	Hotspot q;
+	q.type = MakeMenu;
+	Action *a = new Quit();
+	q.actions.push_back(a);
+	Level level;
+	Hotspots quit;
+	quit.push_back(q);
+	level.hots = quit;  
+	_levels["mis/quit.mis"] = level;
+	// Read assets from mis files
 	loadMis("mis/demo.mis");
+	_levels["mis/demo.mis"].intros.push_back("demo/dcine1.smk");
+	_levels["mis/demo.mis"].intros.push_back("demo/dcine2.smk");
+	_levels["mis/demo.mis"].hots[2].setting = "mis/alley.mis";
+	_levels["mis/demo.mis"].hots[5].setting = "mis/order.mis";
 	loadMis("mis/order.mis");
+	_levels["mis/order.mis"].hots[1].setting = "mis/quit.mis";
 	loadMis("mis/alley.mis");
+	_levels["mis/alley.mis"].intros.push_back("demo/aleyc01s.smk");
+
 	//loadMis("MIS/SHOCTALK.MIS");
 
 	// Initialize graphics
@@ -166,8 +226,6 @@ Common::Error HypnoEngine::run() {
 	_transparentColor = _pixelFormat.RGBToColor(0, 0x82, 0);
 	screenRect = Common::Rect(0, 0, _screenW, _screenH);
 	//changeCursor("default");
-	_origin = Common::Point(0, 0);
-	_image = new Image::BitmapDecoder();
 	_compositeSurface = new Graphics::ManagedSurface();
 	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
 	_compositeSurface->setTransparentColor(_transparentColor);
@@ -182,9 +240,17 @@ Common::Error HypnoEngine::run() {
 	} else {
 		_nextSetting = getGoIntroSetting();
 	}*/
-	runIntro("DEMO/DCINE1.SMK", "DEMO/DCINE2.SMK");
+
+	_nextSetting = "mis/demo.mis";
 	while (!shouldQuit()) {
-		runMis("mis/alley.mis");
+		resetLevelState();
+		if (!_nextSetting.empty()) {
+			debug("Executing setting %s", _nextSetting.c_str());
+			_currentSetting = _nextSetting;
+			_nextSetting = "";
+			runMis(_currentSetting);
+		}
+			
 	}
 	return Common::kNoError;
 }
@@ -195,19 +261,30 @@ void HypnoEngine::runMis(Common::String name) {
 	Common::Point mousePos;
 	
 	stack.clear();
-	assert(g_settings.contains(name));
-	_nextHotsToAdd = &g_settings[name];
+	assert(_levels.contains(name));
+	_nextHotsToAdd = &_levels[name].hots;
+	_nextMoviesToPlay = _levels[name].intros;
+	for (uint32 i = 0; i < _nextMoviesToPlay.size(); i++) {
+		_nextMoviesPositions.push_back(Common::Point(0, 0));
+		_nextMoviesScales.push_back(true);
+	}
+	
 	changeCursor("mouse/cursor1.smk", 0);
 
-	while (!shouldQuit()) {
+	while (!shouldQuit() && _nextSetting.empty()) {
 		
 		while (g_system->getEventManager()->pollEvent(event)) {
 			mousePos = g_system->getEventManager()->getMousePos();
 			// Events
 			switch (event.type) {
 			case Common::EVENT_KEYDOWN:
-				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder)
+				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder) {
 					skipVideo();
+					if (!stack.empty()) { 
+						runMenu(*stack.back());
+						drawScreen();
+					}
+				}
 
 				break;
 
@@ -236,29 +313,40 @@ void HypnoEngine::runMis(Common::String name) {
 		}
 
 		// Movies
-		if (!_nextMovie.empty()) {
+		if (_nextMoviesToPlay.size() > 0 && _currentMovie.empty()) {
+			debug("start playing %s", _nextMoviesToPlay.front().c_str());
 			//removeTimer();
+			assert(_nextMoviesToPlay.size() == _nextMoviesPositions.size());
 			_videoDecoder = new Video::SmackerDecoder();
-			playVideo(_nextMovie);
-			_currentMovie = _nextMovie;
-			_nextMovie = "";
+			_currentMovie = _nextMoviesToPlay.front();
+			_moviePosition = _nextMoviesPositions.front();
+			_movieScale = _nextMoviesScales.front();
+			playVideo(_currentMovie);
+			_nextMoviesToPlay.pop_front();
+			_nextMoviesPositions.pop_front();
+			_nextMoviesScales.pop_front();
 			continue;
 		}
 
 		if (_videoDecoder && !_videoDecoder->isPaused()) {
+			debug("video decoder active!");
 			if (_videoDecoder->getCurFrame() == 0)
 				stopSound(true);
 			if (_videoDecoder->endOfVideo()) {
+				debug("video still playing");
 				_videoDecoder->close();
 				delete _videoDecoder;
 				_videoDecoder = nullptr;
 				_currentMovie = "";
 
 				// refresh current scene
-				runMenu(*stack.back());
-				drawScreen();
+				if (!stack.empty()) { 
+					runMenu(*stack.back());
+					drawScreen();
+				}
 
 			} else if (_videoDecoder->needsUpdate()) {
+				debug("updating screen");
 				drawScreen();
 				g_system->delayMillis(10);
 			}
@@ -280,67 +368,14 @@ void HypnoEngine::runMis(Common::String name) {
 			drawScreen();
 		}
 
-		g_system->updateScreen();
-		g_system->delayMillis(10);
-	}
-}
-
-void HypnoEngine::runIntro(Common::String logoIntro, Common::String movieIntro) {
-	Common::Event event;
-	_nextMovie = logoIntro;
-
-	while ((_nextMovie != "" || _currentMovie != "") && !shouldQuit()) {
-			while (g_system->getEventManager()->pollEvent(event)) {
-			// Events
-			switch (event.type) {
-			case Common::EVENT_KEYDOWN:
-				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder) {
-					if (_currentMovie == logoIntro)
-						_nextMovie = movieIntro;
-					else
-					    skipVideo();
-				}
-
-				break;
-
-			default:
-				break;
-			}
-		}
-
-		// Movies
-		if (!_nextMovie.empty()) {
-			_videoDecoder = new Video::SmackerDecoder();
-			playVideo(_nextMovie);
-			_currentMovie = _nextMovie;
-			_nextMovie = "";
-			continue;
-		}
-
-		if (_videoDecoder && !_videoDecoder->isPaused()) {
-			if (_videoDecoder->getCurFrame() == 0)
-				stopSound(true);
-			if (_videoDecoder->endOfVideo()) {
-				_videoDecoder->close();
-				delete _videoDecoder;
-				_videoDecoder = nullptr;
-				if (_currentMovie == logoIntro)
-					_nextMovie = movieIntro;
-				else 
-					_nextMovie = "";
-			} else if (_videoDecoder->needsUpdate()) {
-				drawScreen();
-				g_system->delayMillis(10);
-			}
-			continue;
-		}
+		if (checkLevelCompleted())
+			_nextSetting = "mis/demo.mis";
 
 		g_system->updateScreen();
 		g_system->delayMillis(10);
 	}
 }
 
-
 //Actions
 
 void HypnoEngine::runMenu(Hotspots hs) {
@@ -350,7 +385,9 @@ void HypnoEngine::runMenu(Hotspots hs) {
 	debug("hotspot actions size: %d", h.actions.size());
 	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
 		Action *action = *itt;
-		if (typeid(*action) == typeid(Background))
+		if (typeid(*action) == typeid(Quit))
+			runQuit(h, (Quit*) action);
+		else if (typeid(*action) == typeid(Background))
 			runBackground(h, (Background*) action);
 		else if (typeid(*action) == typeid(Overlay))
 			runOverlay(h, (Overlay*) action);
@@ -358,16 +395,17 @@ void HypnoEngine::runMenu(Hotspots hs) {
 		//	runMice(h, (Mice*) action);
 	}
 
-	if (h.stype == "SINGLE_RUN")
-		loadImage("int_main/mainbutt.smk", 0, 0);
-	else if (h.stype == "AUTO_BUTTONS")
+	//if (h.stype == "SINGLE_RUN")
+	//	loadImage("int_main/mainbutt.smk", 0, 0);
+	if (h.stype == "AUTO_BUTTONS")
 		loadImage("int_main/resume.smk", 0, 0);
 }
 
 void HypnoEngine::runBackground(const Hotspot h, Background *a) {
+	if (a->condition.size() > 0 && !_levelState[a->condition])
+		return;
 	Common::Point origin = a->origin;
-	if (a->condition.size() == 0)
-		loadImage(a->path, origin.x, origin.y);
+	loadImage(a->path, origin.x, origin.y);
 }
 
 void HypnoEngine::runOverlay(const Hotspot h, Overlay *a) {
@@ -384,7 +422,49 @@ void HypnoEngine::runEscape(const Hotspot h, Escape *a) {
 }
 
 void HypnoEngine::runCutscene(const Hotspot h, Cutscene *a) {
-    _nextMovie = a->path;
+    _nextMoviesToPlay.push_back(a->path);
+	_nextMoviesPositions.push_back(Common::Point(0, 0));
+	_nextMoviesScales.push_back(true);
+}
+
+void HypnoEngine::runGlobal(const Hotspot h, Global *a) {
+    if (a->command == "TURNON")
+		_levelState[a->variable] = 1;
+	else if (a->command == "TURNOFF")
+		_levelState[a->variable] = 0;
+	else
+		error("Invalid command %s", a->command.c_str());
+}
+
+void HypnoEngine::runPlay(const Hotspot h, Play *a) {
+	if (a->condition.size() > 0 && !_levelState[a->condition])
+		return;
+	Common::Point origin = a->origin;
+
+	if (a->flag == "BITMAP")
+			loadImage(a->path, origin.x, origin.y);
+	else { 
+    	_nextMoviesToPlay.push_back(a->path);
+		_nextMoviesPositions.push_back(origin);
+		_nextMoviesScales.push_back(false);
+	}
+}
+
+void HypnoEngine::runWalN(const Hotspot h, WalN *a) {
+	if (a->condition.size() > 0 && !_levelState[a->condition])
+		return;
+	Common::Point origin = a->origin;
+	if (a->flag == "BITMAP")
+			loadImage(a->path, origin.x, origin.y);
+	else { 
+    	_nextMoviesToPlay.push_back(a->path);
+		_nextMoviesPositions.push_back(origin);
+		_nextMoviesScales.push_back(false);
+	}
+}
+
+void HypnoEngine::runQuit(const Hotspot h, Quit *a) {
+    quitGame();
 }
 
 // Hotspots
@@ -418,6 +498,9 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			_nextHotsToAdd = selected.smenu;
 		}
 
+		if (!selected.setting.empty())
+			_nextSetting = selected.setting;
+
 		debug("hotspot clicked actions size: %d", selected.actions.size());
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
@@ -425,12 +508,21 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 				runEscape(selected, (Escape*) action);
 			if (typeid(*action) == typeid(Cutscene))
 				runCutscene(selected, (Cutscene*) action);
+			if (typeid(*action) == typeid(Play))
+				runPlay(selected, (Play*) action);
+			if (typeid(*action) == typeid(WalN))
+				runWalN(selected, (WalN*) action);
+			if (typeid(*action) == typeid(Global))
+				runGlobal(selected, (Global*) action);
 		}
 
 	}
 }
 
 bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
+	if (stack.empty())
+		return false;
+
 	Hotspots *hots = stack.back();
 	Hotspot selected;
 	bool found = false;
@@ -466,7 +558,7 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 
 void HypnoEngine::loadImage(const Common::String &name, int x, int y) {
 	Graphics::Surface *surf = decodeFrame(name, 0);
-	_compositeSurface->transBlitFrom(*surf, _origin + Common::Point(x, y), _transparentColor);
+	_compositeSurface->transBlitFrom(*surf, Common::Point(x, y), _transparentColor);
 }
 
 Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, bool convert) {
@@ -476,27 +568,24 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
 
-	_videoDecoder = new Video::SmackerDecoder();
-	if (!_videoDecoder->loadStream(file))
+	Video::SmackerDecoder vd;
+	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
 
     for(int f = 0; f < n; f++) 
-		_videoDecoder->decodeNextFrame();
+		vd.decodeNextFrame();
 
-	const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
+	const Graphics::Surface *frame = vd.decodeNextFrame();
 	Graphics::Surface *rframe;
 
 	if (convert) {
-		rframe = frame->convertTo(_pixelFormat, _videoDecoder->getPalette());
+		rframe = frame->convertTo(_pixelFormat, vd.getPalette());
 	} else {
-		rframe = frame->convertTo(frame->format, _videoDecoder->getPalette());
+		rframe = frame->convertTo(frame->format, vd.getPalette());
 		//rframe->create(frame->w, frame->h, frame->format);
 		//rframe->copyRectToSurface(frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h);
 	}
 
-	delete _videoDecoder;
-	_videoDecoder = nullptr;
-
 	return rframe;
 }
 
@@ -506,21 +595,27 @@ void HypnoEngine::drawScreen() {
 
 	if (_videoDecoder && !_videoDecoder->isPaused()) {
 		const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
-		Graphics::Surface *sframe = frame->scale(_screenW, _screenH);
-		Graphics::Surface *cframe = sframe->convertTo(_pixelFormat, _videoDecoder->getPalette());
-		Common::Point center(0, 0);
-		surface->blitFrom(*cframe, center);
+		Graphics::Surface *sframe, *cframe;
+
+		if (_movieScale) {
+			sframe = frame->scale(_screenW, _screenH);
+			cframe = sframe->convertTo(_pixelFormat, _videoDecoder->getPalette());
+		} else
+			cframe = frame->convertTo(_pixelFormat, _videoDecoder->getPalette());
 
-		sframe->free();
-		delete sframe;
+		debug("Move position: %d %d", _moviePosition.x, _moviePosition.y);
+		surface->blitFrom(*cframe, _moviePosition);
+
+		if (_movieScale) { 
+			sframe->free();
+			delete sframe;
+		}
 
 		cframe->free();
 		delete cframe;
 	}
 
-	Common::Rect w(_origin.x, _origin.y, _screenW - _origin.x, _screenH - _origin.y);
-	Graphics::Surface sa = surface->getSubArea(w);
-	g_system->copyRectToScreen(sa.getPixels(), sa.pitch, _origin.x, _origin.y, sa.w, sa.h);
+	g_system->copyRectToScreen(surface->getPixels(), surface->pitch, 0, 0, _screenW, _screenH);
 	g_system->updateScreen();
 }
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 96e0d5e0c1..cdcfd79bd1 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -53,7 +53,6 @@ enum {
 	kHypnoDebugScript = 1 << 2
 };
 
-
 typedef Common::Array<byte> ByteArray;
 typedef struct LibData {
 	Common::Array<Common::String> filenames;
@@ -82,20 +81,18 @@ public:
 	Common::InstallShieldV3 _installerArchive;
 
 	Common::Error run() override;
-	void runIntro(Common::String logoIntro, Common::String movieIntro);
+	Levels _levels;
+	Common::HashMap<Common::String, int> _levelState;
+	void resetLevelState();
+	bool checkLevelCompleted();
 	void runMis(Common::String name);
 
-
 	void restartGame();
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
 	void loadMis(Common::String filename);
 	LibData loadLib(char *filename);
 
-	// Functions
-
-	void initFuncs();
-
 	// User input
 	void clickedHotspot(Common::Point);
 	bool hoverHotspot(Common::Point);
@@ -116,9 +113,6 @@ public:
 		return true;
 	}
 
-	void ignoreEvents();
-	//Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
-	//Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override;
 	void syncGameStream(Common::Serializer &s);
 
 	Common::String convertPath(const Common::String &);
@@ -128,66 +122,59 @@ public:
 	Graphics::Surface *decodeImage(const Common::String &file);
 	Graphics::Surface *decodeFrame(const Common::String &name, int frame, bool convert = true);
 	void loadImage(const Common::String &file, int x, int y);
-	void drawScreenFrame();
 
 	// Cursors
 	void changeCursor(const Common::String &, uint32);
-	Common::String getInventoryCursor();
-	Common::String getExitCursor();
 
 	// Actions
+	void runIntro();
 	void runMenu(Hotspots hs);
     void runBackground(const Hotspot h, Background *a);
 	void runOverlay(const Hotspot h, Overlay *a);
 	void runMice(const Hotspot h, Mice *a);
 	void runEscape(const Hotspot h, Escape *a);
+	void runQuit(const Hotspot h, Quit *a);
 	void runCutscene(const Hotspot h, Cutscene *a);
+	void runPlay(const Hotspot h, Play *a);
+	void runWalN(const Hotspot h, WalN *a);
+	void runGlobal(const Hotspot h, Global *a);
 
 	Graphics::ManagedSurface *_compositeSurface;
-	Graphics::Surface *loadMask(const Common::String &, int, int, bool);
-	void drawMask(Graphics::Surface *);
-	void fillRect(uint32, Common::Rect);
-	bool inMask(Graphics::Surface *, Common::Point);
 	uint32 _transparentColor;
 	Common::Rect screenRect;
-	Common::String _framePath;
-	Graphics::Surface *_frame;
-	Common::String _nextVS;
-	Common::Point _origin;
 	void drawScreen();
 
+	// intros
+	Common::HashMap<Common::String, Movies> _intros;
+
+	// settings 
+	Common::String _nextSetting;
+	Common::String _currentSetting;
+
 	// hotspots
 	Hotspots *_nextHotsToAdd;
 	Hotspots *_nextHotsToRemove;
 	HotspotsStack stack;
 
-	// movies
-	Common::String _nextMovie;
+	// Movies
+	Movies _nextMoviesToPlay;
+	Common::List<Common::Point> _nextMoviesPositions;
+	Common::List<bool> _nextMoviesScales;
+	Common::Point _moviePosition;
+	bool _movieScale;
 	Common::String _currentMovie;
 
-	// Save/Load games
-	int _mode;
-	bool _modified;
-	Common::String _repeatedMovieExit;
-
-	// Masks/Exits
-
 	// Sounds
 	void playSound(const Common::String &, uint, bool, bool);
 	void stopSound(bool);
 	bool isSoundActive();
 	bool _noStopSounds;
 
-	// Random values
-	bool getRandomBool(uint);
-
 	// Timers
 	bool installTimer(uint32, Common::String *);
 	void removeTimer();
 };
 
-//extern PrivateEngine *g_private;
-
 } // End of namespace Hypno
 
 #endif
diff --git a/engines/hypno/lexer.l b/engines/hypno/lexer.l
index f17a02dd2b..3136521abb 100644
--- a/engines/hypno/lexer.l
+++ b/engines/hypno/lexer.l
@@ -54,11 +54,8 @@ OVER                        return OVERTOK;
 SMEN                        return SMENTOK;
 ESCP                        return ESCPTOK;
 PLAY						return PLAYTOK;
-TURNON						return TONTOK;
-TURNOFF						return TOFFTOK;
 NO_RETURN                   return NRTOK;
-GS_[A-Za-z_0-9]+            HYPNO_lval.s = scumm_strdup(HYPNO_text); return GSSWITCH;
-\/BITMAP					return BITMAPTOK;
+GS_[A-Z_0-9]+           	HYPNO_lval.s = scumm_strdup(HYPNO_text); return GSSWITCH;
 \/BBOX\=					return BBOXTOK;
 \/[A-Za-z_0-9]*  			HYPNO_lval.s = scumm_strdup(HYPNO_text); return FLAG;
 [A-Za-z_][A-Za-z_0-9]*  	HYPNO_lval.s = scumm_strdup(HYPNO_text); return NAME;


Commit: e868e7bde89dd5a8ec573cb350bc8389cc795511
    https://github.com/scummvm/scummvm/commit/e868e7bde89dd5a8ec573cb350bc8389cc795511
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: parsing of data structure used for arcade sequences and refactoring

Changed paths:
  A engines/hypno/spider/grammar_arc.y
  A engines/hypno/spider/grammar_mis.y
  A engines/hypno/spider/lexer_arc.l
  A engines/hypno/spider/lexer_mis.l
  R engines/hypno/grammar.y
  R engines/hypno/lexer.l
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/module.mk


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 7747670fd9..6e153593d1 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -119,15 +119,30 @@ class Global : public Action {
 	Common::String command;
 };
 
+class Shoot {
+  public:
+	Common::String animation;
+};
+
+typedef Common::List<Shoot> Shoots;
+
+class ArcadeShooting {
+  public:
+	Common::String background;
+	Common::String player;
+	Shoots shoots;
+};
+
 class Level {
   public:
 	Hotspots hots;
 	Movies intros;
+	ArcadeShooting arcade;
 };
 
 typedef Common::HashMap<Common::String, Level> Levels;
 extern Hotspots *g_parsedHots;
-//extern Settings g_settings;
+extern ArcadeShooting g_parsedArc;
 
 } // End of namespace Hypno
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 1d3b848247..6f2fc94764 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -42,6 +42,7 @@
 namespace Hypno {
 
 Hotspots *g_parsedHots;
+ArcadeShooting g_parsedArc;
 //Settings g_settings;
 
 const static char* levelVariables[] = {
@@ -74,7 +75,8 @@ const static char* levelVariables[] = {
 	NULL
 };
 
-extern int parse(const char *);
+extern int parse_mis(const char *);
+extern int parse_arc(const char *);
 
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	: Engine(syst), _gameDescription(gd), _image(nullptr), _videoDecoder(nullptr),
@@ -103,7 +105,7 @@ void HypnoEngine::loadMis(Common::String filename) {
 	char *buf = (char *)malloc(fileSize + 1);
 	test->read(buf, fileSize);
 	buf[fileSize] = '\0';
-	parse(buf);
+	parse_mis(buf);
 	Level level;
 	level.hots = *g_parsedHots; 
 	_levels[filename] = level;
@@ -170,52 +172,76 @@ bool HypnoEngine::checkLevelCompleted() {
 	return _levelState["GS_LEVELCOMPLETE"];
 }
 
-Common::Error HypnoEngine::run() {
-	_language = Common::parseLanguage(ConfMan.get("language"));
-	_platform = Common::parsePlatform(ConfMan.get("platform"));
+void HypnoEngine::loadAssets() {
+
+	
 	LibData files = loadLib("C_MISC/MISSIONS.LIB");
-	/*uint32 i = 0;
+	uint32 i = 0;
 	uint32 j = 0;
 	uint32 k = 0;
 
+	Common::String mis;
+
 	debug("file: %s",files.filenames[j].c_str());
 	for (i = 0; i < files.data.size(); i++) {
-		debugN("%c", files.data[i]);
+		mis += files.data[i];
+		//debugN("%x/%c, ", files.data[i], files.data[i]);
 		if (files.data[i] == 'X') {
-			if (j == files.filenames.size()-1) {
-				debug("Finished at %d from %d", i, files.data.size()); 
-				for (k = i; k < files.data.size(); k++)
-					debugN("%c", files.data[k]);
-				break;
-			}
-
-			j++;
+			break;
+			//if (j == files.filenames.size()-1) {
+			//	debug("Finished at %d from %d", i, files.data.size()); 
+			//	for (k = i; k < files.data.size(); k++)
+			//		debugN("%c", files.data[k]);
+			//	break;
+			//}
+
+			//j++;
 			debugN("\n************file: %s**************",files.filenames[j].c_str());
 		}
 	}
-	*/	
+	parse_arc(mis.c_str());
+	{ 
+		Level level;
+		level.arcade = g_parsedArc;  
+		_levels[files.filenames[0]] = level;
+		debug("%s", level.arcade.background.c_str());
+	}
+
+	{ // quit level
+		Hotspot q;
+		q.type = MakeMenu;
+		Action *a = new Quit();
+		q.actions.push_back(a);
+		Level level;
+		Hotspots quit;
+		quit.push_back(q);
+		level.hots = quit;  
+		_levels["mis/quit.mis"] = level;
+	}
 
-	Hotspot q;
-	q.type = MakeMenu;
-	Action *a = new Quit();
-	q.actions.push_back(a);
-	Level level;
-	Hotspots quit;
-	quit.push_back(q);
-	level.hots = quit;  
-	_levels["mis/quit.mis"] = level;
 	// Read assets from mis files
 	loadMis("mis/demo.mis");
 	_levels["mis/demo.mis"].intros.push_back("demo/dcine1.smk");
 	_levels["mis/demo.mis"].intros.push_back("demo/dcine2.smk");
+	_levels["mis/demo.mis"].hots[1].setting = "C1.MI_";
 	_levels["mis/demo.mis"].hots[2].setting = "mis/alley.mis";
 	_levels["mis/demo.mis"].hots[5].setting = "mis/order.mis";
+
+
 	loadMis("mis/order.mis");
 	_levels["mis/order.mis"].hots[1].setting = "mis/quit.mis";
 	loadMis("mis/alley.mis");
 	_levels["mis/alley.mis"].intros.push_back("demo/aleyc01s.smk");
 
-	//loadMis("MIS/SHOCTALK.MIS");
+	//loadMis("mis/shoctalk.mis");
+
+}
+
+Common::Error HypnoEngine::run() {
+	_language = Common::parseLanguage(ConfMan.get("language"));
+	_platform = Common::parsePlatform(ConfMan.get("platform"));
+
+	//return Common::kNoError;
 
 	// Initialize graphics
 	initGraphics(_screenW, _screenH, nullptr);
@@ -240,7 +266,7 @@ Common::Error HypnoEngine::run() {
 	} else {
 		_nextSetting = getGoIntroSetting();
 	}*/
-
+	loadAssets();
 	_nextSetting = "mis/demo.mis";
 	while (!shouldQuit()) {
 		resetLevelState();
@@ -248,22 +274,102 @@ Common::Error HypnoEngine::run() {
 			debug("Executing setting %s", _nextSetting.c_str());
 			_currentSetting = _nextSetting;
 			_nextSetting = "";
-			runMis(_currentSetting);
+			runLevel(_currentSetting);
 		}
 			
 	}
 	return Common::kNoError;
 }
 
+void HypnoEngine::runLevel(Common::String name) {
+	assert(_levels.contains(name));
+	if (_levels[name].hots.size() == 0)
+		runArcade(_levels[name].arcade);
+	else
+		runScene(_levels[name].hots, _levels[name].intros);
+
+}
 
-void HypnoEngine::runMis(Common::String name) {
+void HypnoEngine::runArcade(ArcadeShooting arc) {
+	Common::Event event;
+	Common::Point mousePos;
+	
+	_nextMoviesToPlay.push_back(arc.background);
+	_nextMoviesPositions.push_back(Common::Point(0, 0));
+	_nextMoviesScales.push_back(true);
+	
+	changeCursor("mouse/cursor1.smk", 0);
+
+	while (!shouldQuit()) {
+		
+		while (g_system->getEventManager()->pollEvent(event)) {
+			mousePos = g_system->getEventManager()->getMousePos();
+			// Events
+			switch (event.type) {
+
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_LBUTTONDOWN:
+				//if (!_nextHotsToAdd || !_nextHotsToRemove)
+				// 	clickedHotspot(mousePos);
+				break;
+
+			case Common::EVENT_MOUSEMOVE:
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		// Movies
+		if (_nextMoviesToPlay.size() > 0 && _currentMovie.empty()) {
+			debug("start playing %s", _nextMoviesToPlay.front().c_str());
+			//removeTimer();
+			assert(_nextMoviesToPlay.size() == _nextMoviesPositions.size());
+			_videoDecoder = new Video::SmackerDecoder();
+			_currentMovie = _nextMoviesToPlay.front();
+			_moviePosition = _nextMoviesPositions.front();
+			_movieScale = _nextMoviesScales.front();
+			playVideo(_currentMovie);
+			_nextMoviesToPlay.pop_front();
+			_nextMoviesPositions.pop_front();
+			_nextMoviesScales.pop_front();
+			continue;
+		}
+
+		if (_videoDecoder && !_videoDecoder->isPaused()) {
+			if (_videoDecoder->getCurFrame() == 0)
+				stopSound(true);
+			if (_videoDecoder->endOfVideo()) {
+				debug("video still playing");
+				_videoDecoder->close();
+				delete _videoDecoder;
+				_videoDecoder = nullptr;
+				_currentMovie = "";
+
+			} else if (_videoDecoder->needsUpdate()) {
+				debug("updating screen");
+				drawScreen();
+				g_system->delayMillis(10);
+			}
+			continue;
+		}
+
+		g_system->updateScreen();
+		g_system->delayMillis(10);
+	}
+}
+
+void HypnoEngine::runScene(Hotspots hots, Movies intros) {
 	Common::Event event;
 	Common::Point mousePos;
 	
 	stack.clear();
-	assert(_levels.contains(name));
-	_nextHotsToAdd = &_levels[name].hots;
-	_nextMoviesToPlay = _levels[name].intros;
+	_nextHotsToAdd = &hots;
+	_nextMoviesToPlay = intros;
 	for (uint32 i = 0; i < _nextMoviesToPlay.size(); i++) {
 		_nextMoviesPositions.push_back(Common::Point(0, 0));
 		_nextMoviesScales.push_back(true);
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index cdcfd79bd1..89bbf9880f 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -85,13 +85,17 @@ public:
 	Common::HashMap<Common::String, int> _levelState;
 	void resetLevelState();
 	bool checkLevelCompleted();
-	void runMis(Common::String name);
+	void runLevel(Common::String name);
+	void runScene(Hotspots hots, Movies intros);
+	void runArcade(ArcadeShooting arc);
 
 	void restartGame();
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
+	void loadAssets();
 	void loadMis(Common::String filename);
 	LibData loadLib(char *filename);
+	Common::HashMap<Common::String, Common::String> _assets;
 
 	// User input
 	void clickedHotspot(Common::Point);
@@ -119,7 +123,6 @@ public:
 	void playVideo(const Common::String &);
 	void skipVideo();
 
-	Graphics::Surface *decodeImage(const Common::String &file);
 	Graphics::Surface *decodeFrame(const Common::String &name, int frame, bool convert = true);
 	void loadImage(const Common::String &file, int x, int y);
 
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index ed0245afd1..408ac3e428 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -3,8 +3,10 @@ MODULE := engines/hypno
 MODULE_OBJS := \
 	cursors.o \
 	metaengine.o \
-	lexer.o \
-	grammar.o \
+	spider/lexer_mis.o \
+	spider/grammar_mis.o \
+	spider/lexer_arc.o \
+	spider/grammar_arc.o \
 	hypno.o
 
 MODULE_DIRS += \
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
new file mode 100644
index 0000000000..7d141b656d
--- /dev/null
+++ b/engines/hypno/spider/grammar_arc.y
@@ -0,0 +1,137 @@
+/* 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.
+ *
+ */
+
+%require "3.0"
+%defines "engines/hypno/spider/tokens_arc.h"
+%output "engines/hypno/spider/grammar_arc.cpp"
+%define api.prefix {HYPNO_ARC_}
+
+%{
+
+#include "common/array.h"
+#include "hypno/grammar.h"
+#include <stdio.h>
+
+#undef yyerror
+#define yyerror	 HYPNO_ARC_xerror
+
+Hypno::Shoot *shoot;
+
+extern int HYPNO_ARC_lex();
+extern int HYPNO_ARC_parse();
+extern int yylineno;
+
+void HYPNO_ARC_xerror(const char *str) {
+	debug("ERROR: %s", str);
+}
+
+int HYPNO_ARC_wrap() {
+    return 1;
+}
+
+using namespace Hypno;
+
+%} 
+
+%union {
+	char *s; /* string value */
+	int i;	 /* integer value */
+}
+
+%token<s> NAME FILENAME
+%token<i> NUM
+// header
+%token CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
+%token PTOK ATOK VTOK OTOK NTOK RTOK ITOK SNTOK ZTOK
+
+// body
+%token F0TOK A0TOK B0TOK K0TOK P0TOK WTOK
+
+// end
+%token XTOK
+
+// bytes??
+%token CB3TOK C02TOK
+
+%%
+
+start: header body
+       ;
+
+
+header:  hline RETTOK header
+       | hline
+	   | RETTOK header          
+	   ; 
+
+hline:  CTOK NUM  { debug("C %d", $2); }
+      | DTOK NUM  { debug("D %d", $2); }
+      | PTOK NUM NUM { debug("P %d %d", $2, $3); }
+      | ATOK NUM NUM { debug("A %d %d", $2, $3); }
+      | VTOK NUM NUM { debug("V %d %d", $2, $3); }
+      | OTOK NUM NUM { debug("O %d %d", $2, $3); }
+	  | NTOK FILENAME  { 
+		  g_parsedArc.background = $2; 
+		  debug("N %s", $2); 
+		}
+	  | RTOK FILENAME  { debug("R %s", $2); }
+	  | ITOK FILENAME { 
+  		  g_parsedArc.player = $2; 
+		  debug("I %s", $2); 
+		}
+	  | QTOK NUM NUM { debug("Q %d %d", $2, $3); }
+	  | SNTOK FILENAME enc { debug("SN %s", $2); }
+	  | HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
+	  | HTOK CB3TOK NUM NUM { debug("H %d %d", $3, $4); }
+	  | ZTOK RETTOK { debug("Z"); }
+	  ;
+
+enc: ENCTOK
+   | /* nothing */
+   ;
+
+body: bline RETTOK body
+    | bline RETTOK XTOK
+
+bline: F0TOK FILENAME { 
+		shoot = new Shoot();
+		shoot->animation = $2;
+		debug("F0 %s", $2); 
+	 	}
+     | ITOK  NAME  { debug("I %s", $2); }
+	 | A0TOK NUM NUM { debug("A0 %d %d", $2, $3); }
+	 | B0TOK NUM NUM { debug("B0 %d %d", $2, $3); }
+	 | K0TOK NUM NUM { debug("K0 %d %d", $2, $3); }
+	 | P0TOK NUM NUM { debug("P0 %d %d", $2, $3); }
+	 | OTOK NUM NUM { debug("O %d %d", $2, $3); }
+	 | CTOK NUM  { debug("C %d", $2); } 
+	 | HTOK NUM  { debug("H %d", $2); }
+	 | WTOK NUM  { debug("W %d", $2); }
+	 | DTOK NUM  { debug("D %d", $2); }
+	 | SNTOK FILENAME enc { debug("SN %s", $2); }
+	 | ZTOK {
+		g_parsedArc.shoots.push_back(*shoot); 
+		delete shoot; 
+		shoot = nullptr;
+	    debug("Z"); 
+		}
+     ;
\ No newline at end of file
diff --git a/engines/hypno/grammar.y b/engines/hypno/spider/grammar_mis.y
similarity index 76%
rename from engines/hypno/grammar.y
rename to engines/hypno/spider/grammar_mis.y
index 5519f5bb7f..753340606d 100644
--- a/engines/hypno/grammar.y
+++ b/engines/hypno/spider/grammar_mis.y
@@ -20,56 +20,32 @@
  *
  */
 
-// Heavily inspired by hoc
-// Copyright (C) AT&T 1995
-// All Rights Reserved
-//
-// Permission to use, copy, modify, and distribute this software and
-// its documentation for any purpose and without fee is hereby
-// granted, provided that the above copyright notice appear in all
-// copies and that both that the copyright notice and this
-// permission notice and warranty disclaimer appear in supporting
-// documentation, and that the name of AT&T or any of its entities
-// not be used in advertising or publicity pertaining to
-// distribution of the software without specific, written prior
-// permission.
-//
-// AT&T DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-// IN NO EVENT SHALL AT&T OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-// SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-// THIS SOFTWARE.
-
 %require "3.0"
-%defines "engines/hypno/tokens.h"
-%output "engines/hypno/grammar.cpp"
-%define api.prefix {HYPNO_}
+%defines "engines/hypno/spider/tokens_mis.h"
+%output "engines/hypno/spider/grammar_mis.cpp"
+%define api.prefix {HYPNO_MIS_}
 
 %{
 
-//#include "private/private.h"
 #include "common/array.h"
 #include "hypno/grammar.h"
 #include <stdio.h>
 
 #undef yyerror
-#define yyerror	 HYPNO_xerror
+#define yyerror	 HYPNO_MIS_xerror
 
-extern int HYPNO_lex();
-extern int HYPNO_parse();
+extern int HYPNO_MIS_lex();
+extern int HYPNO_MIS_parse();
 extern int yylineno;
 
 Common::Array<uint32> smenu_idx;
 Hypno::HotspotsStack stack;
 
-void HYPNO_xerror(const char *str) {
+void HYPNO_MIS_xerror(const char *str) {
 	debug("ERROR: %s", str);
 }
 
-int HYPNO_wrap() {
+int HYPNO_MIS_wrap() {
     return 1;
 }
 
@@ -78,8 +54,8 @@ using namespace Hypno;
 %} 
 
 %union {
-	char *s;	     	/* string value */
-	int i;	         	/* integer value */
+	char *s; /* string value */
+	int i;	 /* integer value */
 }
 
 %token<s> NAME FILENAME FLAG COMMENT GSSWITCH COMMAND
@@ -152,8 +128,8 @@ line:    MENUTOK NAME mflag  {
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
 		  	debug("ESC SUBMENU"); }
-	  |  TIMETOK NUM                               { debug("TIME %d", $2); } 
-      |  BACKTOK FILENAME NUM NUM gsswitch flag    {
+	  |  TIMETOK NUM  { debug("TIME %d", $2); } 
+      |  BACKTOK FILENAME NUM NUM gsswitch flag {
 			Background *a = new Background();
 			a->path = $2;
 			a->origin = Common::Point($3, $4);
@@ -189,7 +165,7 @@ line:    MENUTOK NAME mflag  {
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
 	   }
-	  |  PALETOK FILENAME                          {
+	  |  PALETOK FILENAME {
 			Palette *a = new Palette();
 			a->path = $2; 
 			Hotspots *cur = stack.back();
diff --git a/engines/hypno/spider/lexer_arc.l b/engines/hypno/spider/lexer_arc.l
new file mode 100644
index 0000000000..8cf37667a2
--- /dev/null
+++ b/engines/hypno/spider/lexer_arc.l
@@ -0,0 +1,86 @@
+/* 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.
+ *
+ */
+
+%option noyywrap
+%option noinput
+%option yylineno
+%option never-interactive
+
+%option outfile="engines/hypno/spider/lexer_arc.cpp"
+%option prefix="HYPNO_ARC_"
+
+%{
+#define YY_NO_UNISTD_H
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+#include "hypno/spider/tokens_arc.h"
+
+%}
+
+%%
+C				    		return CTOK;
+D                           return DTOK;
+HE                          return HETOK;
+H                           return HTOK;
+P							return PTOK;
+A							return ATOK;
+V							return VTOK;
+O 							return OTOK;
+N 							return NTOK;
+R 							return RTOK;
+I 							return ITOK;
+Q							return QTOK;
+Z							return ZTOK;
+W							return WTOK;
+X 							return XTOK;
+F0							return F0TOK;
+S[0-9]						return SNTOK;
+A0							return A0TOK;
+B0							return B0TOK;
+K0							return K0TOK;
+P0							return P0TOK;
+22[k|K]						return ENCTOK;
+[A-Za-z_][A-Za-z_0-9]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
+[A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
+[\-]?[0-9]+		        	HYPNO_ARC_lval.i = atoi(HYPNO_ARC_text); return NUM;
+\n							return RETTOK;
+\xb3                        return CB3TOK;
+\x02                        return C02TOK;
+[ \t]+		            	/* ignore whitespace */;
+.				        	debug("notparsed: 0x%d",*yytext); return *yytext;
+%%
+
+namespace Hypno {
+
+int parse_arc(const char *code) {
+	YY_BUFFER_STATE bp;
+	yy_delete_buffer(YY_CURRENT_BUFFER);
+	bp = yy_scan_string(code);
+	yy_switch_to_buffer(bp);
+	HYPNO_ARC_parse();
+	yy_delete_buffer(bp);
+	return 0;
+}
+
+} // End of namespace Hypno
diff --git a/engines/hypno/lexer.l b/engines/hypno/spider/lexer_mis.l
similarity index 77%
rename from engines/hypno/lexer.l
rename to engines/hypno/spider/lexer_mis.l
index 3136521abb..f7d4cef2c2 100644
--- a/engines/hypno/lexer.l
+++ b/engines/hypno/spider/lexer_mis.l
@@ -25,8 +25,8 @@
 %option yylineno
 %option never-interactive
 
-%option outfile="engines/hypno/lexer.cpp"
-%option prefix="HYPNO_"
+%option outfile="engines/hypno/spider/lexer_mis.cpp"
+%option prefix="HYPNO_MIS_"
 
 %{
 #define YY_NO_UNISTD_H
@@ -34,7 +34,7 @@
 
 #include "hypno/hypno.h"
 #include "hypno/grammar.h"
-#include "hypno/tokens.h"
+#include "hypno/spider/tokens_mis.h"
 
 %}
 
@@ -55,12 +55,12 @@ SMEN                        return SMENTOK;
 ESCP                        return ESCPTOK;
 PLAY						return PLAYTOK;
 NO_RETURN                   return NRTOK;
-GS_[A-Z_0-9]+           	HYPNO_lval.s = scumm_strdup(HYPNO_text); return GSSWITCH;
+GS_[A-Z_0-9]+           	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
 \/BBOX\=					return BBOXTOK;
-\/[A-Za-z_0-9]*  			HYPNO_lval.s = scumm_strdup(HYPNO_text); return FLAG;
-[A-Za-z_][A-Za-z_0-9]*  	HYPNO_lval.s = scumm_strdup(HYPNO_text); return NAME;
-[A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_lval.s = scumm_strdup(HYPNO_text); return FILENAME;
-[\-]?[0-9]+		        	HYPNO_lval.i = atoi(HYPNO_text); return NUM;
+\/[A-Za-z_0-9]*  			HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FLAG;
+[A-Za-z_][A-Za-z_0-9]*  	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return NAME;
+[A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FILENAME;
+[\-]?[0-9]+		        	HYPNO_MIS_lval.i = atoi(HYPNO_MIS_text); return NUM;
 \r\n						return RETTOK;
 [ \t]+		            	/* ignore whitespace */;
 .				        	debug("<no match>"); return *yytext;
@@ -68,12 +68,12 @@ GS_[A-Z_0-9]+           	HYPNO_lval.s = scumm_strdup(HYPNO_text); return GSSWITC
 
 namespace Hypno {
 
-int parse(const char *code) {
+int parse_mis(const char *code) {
 	YY_BUFFER_STATE bp;
 	yy_delete_buffer(YY_CURRENT_BUFFER);
 	bp = yy_scan_string(code);
 	yy_switch_to_buffer(bp);
-	HYPNO_parse();
+	HYPNO_MIS_parse();
 	yy_delete_buffer(bp);
 	return 0;
 }


Commit: 77e9d1bc695ba3cba824503dc3bf75847dd95aac
    https://github.com/scummvm/scummvm/commit/77e9d1bc695ba3cba824503dc3bf75847dd95aac
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: parsing of list of shoots and collision detection in arcade mode

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/grammar_arc.y


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 6e153593d1..96c5f2eb1e 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -31,6 +31,8 @@
 #include "common/array.h"
 #include "common/rect.h"
 
+#include "video/smk_decoder.h"
+
 namespace Hypno {
 
 enum HotspotType {
@@ -48,7 +50,20 @@ typedef Common::List<Action*> Actions;
 class Hotspot;
 typedef Common::Array<Hotspot> Hotspots;
 typedef Common::Array<Hotspots *> HotspotsStack;
-typedef Common::List<Common::String> Movies;
+
+class MVideo {
+  public:
+    MVideo(Common::String, Common::Point, bool, bool);
+    Common::String path;
+	Common::Point position;
+	bool scaled;
+	bool transparent;
+	Video::SmackerDecoder *videoDecoder;
+	const Graphics::Surface *currentFrame;
+	uint32 finishBeforeEnd;
+};
+
+typedef Common::Array<MVideo> Videos;
 
 class Hotspot { 
   public:
@@ -121,22 +136,33 @@ class Global : public Action {
 
 class Shoot {
   public:
+    Common::String name;
 	Common::String animation;
+	Common::Point position;
+};
+
+typedef Common::Array<Shoot> Shoots;
+
+class ShootInfo {
+  public:
+    Common::String name;
+	uint32 timestamp; 
 };
 
-typedef Common::List<Shoot> Shoots;
+typedef Common::List<ShootInfo> ShootInfos;
 
 class ArcadeShooting {
   public:
 	Common::String background;
 	Common::String player;
 	Shoots shoots;
+    ~ArcadeShooting() { debug("destroying arcade shooting"); };
 };
 
 class Level {
   public:
 	Hotspots hots;
-	Movies intros;
+	Videos intros;
 	ArcadeShooting arcade;
 };
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 6f2fc94764..cf4b40b518 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -33,17 +33,29 @@
 #include "common/str.h"
 #include "common/system.h"
 #include "common/timer.h"
+#include "common/tokenizer.h"
 #include "engines/util.h"
 #include "image/bmp.h"
 
+
 #include "hypno/hypno.h"
 #include "hypno/grammar.h"
 
 namespace Hypno {
 
+
 Hotspots *g_parsedHots;
 ArcadeShooting g_parsedArc;
-//Settings g_settings;
+
+MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent, bool _scaled) {
+	path = _path;
+	position = _position;
+	scaled = _scaled;
+	transparent = _transparent;
+	videoDecoder = nullptr;
+	currentFrame = nullptr;
+	finishBeforeEnd = 0;
+}
 
 const static char* levelVariables[] = {
 	"GS_NONE",
@@ -79,7 +91,7 @@ extern int parse_mis(const char *);
 extern int parse_arc(const char *);
 
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
-	: Engine(syst), _gameDescription(gd), _image(nullptr), _videoDecoder(nullptr),
+	: Engine(syst), _gameDescription(gd), _image(nullptr),
 	  _compositeSurface(nullptr), _transparentColor(0), 
 	  _nextHotsToAdd(nullptr), _nextHotsToRemove(nullptr),
 	  _screenW(640), _screenH(480) {
@@ -95,7 +107,7 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
 }
 
-void HypnoEngine::loadMis(Common::String filename) {
+void HypnoEngine::parseLevel(Common::String filename) {
     filename = convertPath(filename);
 	Common::File *test = new Common::File();
 	assert(isDemo());
@@ -130,7 +142,7 @@ LibData HypnoEngine::loadLib(char *filename) {
 		entry.clear();
 		for (j = 0; j < 24; j++) {
 			if (cont && it[i] != 0x96 && it[i] != 0x0) {
-				entry += char(it[i]);
+				entry += tolower(char(it[i]));
 			}
 			else
 				cont = false;
@@ -172,6 +184,32 @@ bool HypnoEngine::checkLevelCompleted() {
 	return _levelState["GS_LEVELCOMPLETE"];
 }
 
+void HypnoEngine::parseShootList(Common::String name, Common::String data) {
+	Common::StringTokenizer tok(data, " S,\t\n");
+
+	Common::String t;
+	Common::String n;
+	ShootInfo si;
+	while(!tok.empty()) {
+		t = tok.nextToken();
+		n = tok.nextToken();
+		if (t == "Z")
+			break;
+		si.name = n;
+		si.timestamp = atoi(t.c_str());
+		_shootInfos.push_back(si);
+		debug("%d -> %s", si.timestamp, si.name.c_str());
+	}
+
+}
+
+void HypnoEngine::parseArcadeShooting(Common::String name, Common::String data) {
+	parse_arc(data.c_str());
+	Level level;
+	level.arcade = g_parsedArc;  
+	_levels[name] = level;
+}
+
 void HypnoEngine::loadAssets() {
 
 	
@@ -180,58 +218,49 @@ void HypnoEngine::loadAssets() {
 	uint32 j = 0;
 	uint32 k = 0;
 
-	Common::String mis;
+	Common::String arc;
+	Common::String list;
 
 	debug("file: %s",files.filenames[j].c_str());
 	for (i = 0; i < files.data.size(); i++) {
-		mis += files.data[i];
-		//debugN("%x/%c, ", files.data[i], files.data[i]);
+		arc += files.data[i];
 		if (files.data[i] == 'X') {
-			break;
-			//if (j == files.filenames.size()-1) {
-			//	debug("Finished at %d from %d", i, files.data.size()); 
-			//	for (k = i; k < files.data.size(); k++)
-			//		debugN("%c", files.data[k]);
-			//	break;
-			//}
-
-			//j++;
-			debugN("\n************file: %s**************",files.filenames[j].c_str());
+			i++;
+			for (k = i; k < files.data.size(); k++) {
+				if (files.data[k] == 'Y')
+					break;
+				list += files.data[k];
+			}
+			break; // No need to keep parsing, no more files are used in the demo
 		}
 	}
-	parse_arc(mis.c_str());
-	{ 
-		Level level;
-		level.arcade = g_parsedArc;  
-		_levels[files.filenames[0]] = level;
-		debug("%s", level.arcade.background.c_str());
-	}
 
-	{ // quit level
-		Hotspot q;
-		q.type = MakeMenu;
-		Action *a = new Quit();
-		q.actions.push_back(a);
-		Level level;
-		Hotspots quit;
-		quit.push_back(q);
-		level.hots = quit;  
-		_levels["mis/quit.mis"] = level;
-	}
+	parseArcadeShooting(files.filenames[0], arc);
+	parseShootList(files.filenames[0], list);
+
+	// quit level
+	Hotspot q;
+	q.type = MakeMenu;
+	Action *a = new Quit();
+	q.actions.push_back(a);
+	Level level;
+	Hotspots quit;
+	quit.push_back(q);
+	level.hots = quit;  
+	_levels["mis/quit.mis"] = level;
 
 	// Read assets from mis files
-	loadMis("mis/demo.mis");
-	_levels["mis/demo.mis"].intros.push_back("demo/dcine1.smk");
-	_levels["mis/demo.mis"].intros.push_back("demo/dcine2.smk");
-	_levels["mis/demo.mis"].hots[1].setting = "C1.MI_";
+	parseLevel("mis/demo.mis");
+	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine1.smk", Common::Point(0, 0), false, true));
+	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine2.smk", Common::Point(0, 0), false, true));
+	_levels["mis/demo.mis"].hots[1].setting = "c1.mi_";
 	_levels["mis/demo.mis"].hots[2].setting = "mis/alley.mis";
 	_levels["mis/demo.mis"].hots[5].setting = "mis/order.mis";
 
-
-	loadMis("mis/order.mis");
+	parseLevel("mis/order.mis");
 	_levels["mis/order.mis"].hots[1].setting = "mis/quit.mis";
-	loadMis("mis/alley.mis");
-	_levels["mis/alley.mis"].intros.push_back("demo/aleyc01s.smk");
+	parseLevel("mis/alley.mis");
+	_levels["mis/alley.mis"].intros.push_back(MVideo("demo/aleyc01s.smk", Common::Point(0, 0), false, true));
 
 	//loadMis("mis/shoctalk.mis");
 
@@ -243,23 +272,25 @@ Common::Error HypnoEngine::run() {
 
 	//return Common::kNoError;
 
+	Graphics::ModeList modes;
+	modes.push_back(Graphics::Mode(640, 480));
+	modes.push_back(Graphics::Mode(320, 200));
+    initGraphicsModes(modes);
+
 	// Initialize graphics
 	initGraphics(_screenW, _screenH, nullptr);
 	_pixelFormat = g_system->getScreenFormat();
 	if (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8())
 		return Common::kUnsupportedColorMode;
 
-	_transparentColor = _pixelFormat.RGBToColor(0, 0x82, 0);
 	screenRect = Common::Rect(0, 0, _screenW, _screenH);
 	//changeCursor("default");
 	_compositeSurface = new Graphics::ManagedSurface();
 	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
-	_compositeSurface->setTransparentColor(_transparentColor);
 
 	// Main event loop
 	Common::Event event;
 	Common::Point mousePos;
-	_videoDecoder = nullptr;
 	/*int saveSlot = ConfMan.getInt("save_slot");
 	if (saveSlot >= 0) { // load the savegame
 		loadGameState(saveSlot);
@@ -270,12 +301,14 @@ Common::Error HypnoEngine::run() {
 	_nextSetting = "mis/demo.mis";
 	while (!shouldQuit()) {
 		resetLevelState();
+		_videosPlaying.clear();
 		if (!_nextSetting.empty()) {
 			debug("Executing setting %s", _nextSetting.c_str());
 			_currentSetting = _nextSetting;
 			_nextSetting = "";
 			runLevel(_currentSetting);
 		}
+		_levels["mis/demo.mis"].intros.clear();
 			
 	}
 	return Common::kNoError;
@@ -290,15 +323,41 @@ void HypnoEngine::runLevel(Common::String name) {
 
 }
 
+void HypnoEngine::shootSpiderweb(Common::Point target) {
+	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
+	_compositeSurface->drawLine(0, 300, target.x, target.y+1, c);
+	_compositeSurface->drawLine(0, 300, target.x, target.y  , c);
+	_compositeSurface->drawLine(0, 300, target.x, target.y-1, c);
+
+	drawScreen();
+	g_system->delayMillis(2);
+}
+
 void HypnoEngine::runArcade(ArcadeShooting arc) {
+	// Move into a function
+	_screenW = 320;
+	_screenH = 200;
+
+	initGraphics(_screenW, _screenH, nullptr);
+
+	_compositeSurface->free();
+	delete _compositeSurface;
+
+	_compositeSurface = new Graphics::ManagedSurface();
+	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
+
 	Common::Event event;
 	Common::Point mousePos;
 	
-	_nextMoviesToPlay.push_back(arc.background);
-	_nextMoviesPositions.push_back(Common::Point(0, 0));
-	_nextMoviesScales.push_back(true);
-	
+	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
+	_compositeSurface->setTransparentColor(_transparentColor);
+
+	//_nextParallelVideoToPlay.push_back(MVideo(arc.background, Common::Point(0, 0), false, false));
+	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false);	
+	Graphics::Surface *sp = decodeFrame(arc.player, 2);
+
 	changeCursor("mouse/cursor1.smk", 0);
+	playVideo(background);
 
 	while (!shouldQuit()) {
 		
@@ -312,6 +371,9 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				break;
 
 			case Common::EVENT_LBUTTONDOWN:
+				shootSpiderweb(mousePos);
+				clickedShoot(mousePos);
+
 				//if (!_nextHotsToAdd || !_nextHotsToRemove)
 				// 	clickedHotspot(mousePos);
 				break;
@@ -325,56 +387,81 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		}
 
 		// Movies
-		if (_nextMoviesToPlay.size() > 0 && _currentMovie.empty()) {
-			debug("start playing %s", _nextMoviesToPlay.front().c_str());
-			//removeTimer();
-			assert(_nextMoviesToPlay.size() == _nextMoviesPositions.size());
-			_videoDecoder = new Video::SmackerDecoder();
-			_currentMovie = _nextMoviesToPlay.front();
-			_moviePosition = _nextMoviesPositions.front();
-			_movieScale = _nextMoviesScales.front();
-			playVideo(_currentMovie);
-			_nextMoviesToPlay.pop_front();
-			_nextMoviesPositions.pop_front();
-			_nextMoviesScales.pop_front();
-			continue;
+		for (Videos::iterator it = _nextParallelVideoToPlay.begin(); it != _nextParallelVideoToPlay.end(); ++it) {
+			playVideo(*it);
+			_videosPlaying.push_back(*it);
 		}
 
-		if (_videoDecoder && !_videoDecoder->isPaused()) {
-			if (_videoDecoder->getCurFrame() == 0)
-				stopSound(true);
-			if (_videoDecoder->endOfVideo()) {
-				debug("video still playing");
-				_videoDecoder->close();
-				delete _videoDecoder;
-				_videoDecoder = nullptr;
-				_currentMovie = "";
-
-			} else if (_videoDecoder->needsUpdate()) {
-				debug("updating screen");
-				drawScreen();
-				g_system->delayMillis(10);
+		if (_nextParallelVideoToPlay.size() > 0)
+			_nextParallelVideoToPlay.clear();
+
+		if (background.videoDecoder->endOfVideo()) {
+			skipVideo(background);
+			_nextSetting = "mis/demo.mis";
+			return;
+		}
+
+
+		if (background.videoDecoder->needsUpdate())
+			updateScreen(background);
+
+		if (_shootInfos.size() > 0) {
+			ShootInfo si = _shootInfos.front();
+			if (si.timestamp <= background.videoDecoder->getCurFrame()) {
+				_shootInfos.pop_front();
+				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
+					if (it->name == si.name) {
+						_nextParallelVideoToPlay.push_back(MVideo(it->animation, it->position , true, false));
+						_nextParallelVideoToPlay[0].finishBeforeEnd = 24;
+					}
+				}
 			}
-			continue;
 		}
 
-		g_system->updateScreen();
+		drawImage(*sp, 60, 129, true);
+
+		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+			if (it->videoDecoder) {
+				if (it->videoDecoder-> getCurFrame() > 0 && it->videoDecoder-> getCurFrame() >= it->videoDecoder->getFrameCount() - it->finishBeforeEnd) {
+				delete it->videoDecoder;
+				it->videoDecoder = nullptr;
+				//TODO: remove from the _videosPlaying list
+
+				} else if (it->videoDecoder->needsUpdate()) {
+					updateScreen(*it);
+				}
+			}
+		}
+
+		drawScreen();
 		g_system->delayMillis(10);
 	}
 }
 
-void HypnoEngine::runScene(Hotspots hots, Movies intros) {
+void HypnoEngine::runScene(Hotspots hots, Videos intros) {
+	// Move into a function
+	_screenW = 640;
+	_screenH = 480;
+
+	initGraphics(_screenW, _screenH, nullptr);
+
+	_compositeSurface->free();
+	delete _compositeSurface;
+
+	_compositeSurface = new Graphics::ManagedSurface();
+	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
+
+
 	Common::Event event;
 	Common::Point mousePos;
+	Common::List<uint32> videosToRemove;
+
+	_transparentColor = _pixelFormat.RGBToColor(0, 0x82, 0);
+	_compositeSurface->setTransparentColor(_transparentColor);
 	
 	stack.clear();
 	_nextHotsToAdd = &hots;
-	_nextMoviesToPlay = intros;
-	for (uint32 i = 0; i < _nextMoviesToPlay.size(); i++) {
-		_nextMoviesPositions.push_back(Common::Point(0, 0));
-		_nextMoviesScales.push_back(true);
-	}
-	
+	_nextSequentialVideoToPlay = intros;	
 	changeCursor("mouse/cursor1.smk", 0);
 
 	while (!shouldQuit() && _nextSetting.empty()) {
@@ -384,8 +471,13 @@ void HypnoEngine::runScene(Hotspots hots, Movies intros) {
 			// Events
 			switch (event.type) {
 			case Common::EVENT_KEYDOWN:
-				if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder) {
-					skipVideo();
+				if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+					for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+						if (it->videoDecoder)
+							skipVideo(*it);
+					}
+					_videosPlaying.clear();
+
 					if (!stack.empty()) { 
 						runMenu(*stack.back());
 						drawScreen();
@@ -419,46 +511,51 @@ void HypnoEngine::runScene(Hotspots hots, Movies intros) {
 		}
 
 		// Movies
-		if (_nextMoviesToPlay.size() > 0 && _currentMovie.empty()) {
-			debug("start playing %s", _nextMoviesToPlay.front().c_str());
-			//removeTimer();
-			assert(_nextMoviesToPlay.size() == _nextMoviesPositions.size());
-			_videoDecoder = new Video::SmackerDecoder();
-			_currentMovie = _nextMoviesToPlay.front();
-			_moviePosition = _nextMoviesPositions.front();
-			_movieScale = _nextMoviesScales.front();
-			playVideo(_currentMovie);
-			_nextMoviesToPlay.pop_front();
-			_nextMoviesPositions.pop_front();
-			_nextMoviesScales.pop_front();
-			continue;
+		if (_nextSequentialVideoToPlay.size() > 0 && _videosPlaying.empty()) {
+			playVideo(*_nextSequentialVideoToPlay.begin());
+			_videosPlaying.push_back(*_nextSequentialVideoToPlay.begin());
+			_nextSequentialVideoToPlay.remove_at(0);
 		}
+		uint32 i = 0;
+		videosToRemove.clear();
+		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+
+			if (it->videoDecoder) {
+				if (it->videoDecoder->endOfVideo()) {
+				it->videoDecoder->close();
+				delete it->videoDecoder;
+				it->videoDecoder = nullptr;
+				videosToRemove.push_back(i);
+
+				} else if (it->videoDecoder->needsUpdate()) {
+					updateScreen(*it);
+				}
+			}
+			i++;
+
+		}
+		if (videosToRemove.size() > 0) {
 
-		if (_videoDecoder && !_videoDecoder->isPaused()) {
-			debug("video decoder active!");
-			if (_videoDecoder->getCurFrame() == 0)
-				stopSound(true);
-			if (_videoDecoder->endOfVideo()) {
-				debug("video still playing");
-				_videoDecoder->close();
-				delete _videoDecoder;
-				_videoDecoder = nullptr;
-				_currentMovie = "";
-
-				// refresh current scene
+			for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
+				debug("removing %d from %d size", *it, _videosPlaying.size()); 
+				_videosPlaying.remove_at(*it);
+			}
+
+			// Nothing else to play
+			if (_videosPlaying.size() == 0 && _nextSequentialVideoToPlay.size() == 0){
 				if (!stack.empty()) { 
 					runMenu(*stack.back());
 					drawScreen();
 				}
-
-			} else if (_videoDecoder->needsUpdate()) {
-				debug("updating screen");
-				drawScreen();
-				g_system->delayMillis(10);
 			}
-			continue;
+
 		}
 
+		if (_videosPlaying.size() > 0 || _nextSequentialVideoToPlay.size() > 0) {
+			drawScreen();
+			continue;
+		} 
+
 		if (_nextHotsToRemove) {
 			debug("Removing a hotspot list!");
 			stack.pop_back();
@@ -504,19 +601,19 @@ void HypnoEngine::runMenu(Hotspots hs) {
 	//if (h.stype == "SINGLE_RUN")
 	//	loadImage("int_main/mainbutt.smk", 0, 0);
 	if (h.stype == "AUTO_BUTTONS")
-		loadImage("int_main/resume.smk", 0, 0);
+		loadImage("int_main/resume.smk", 0, 0, true);
 }
 
 void HypnoEngine::runBackground(const Hotspot h, Background *a) {
 	if (a->condition.size() > 0 && !_levelState[a->condition])
 		return;
 	Common::Point origin = a->origin;
-	loadImage(a->path, origin.x, origin.y);
+	loadImage(a->path, origin.x, origin.y, false);
 }
 
 void HypnoEngine::runOverlay(const Hotspot h, Overlay *a) {
 	Common::Point origin = a->origin;
-	loadImage(a->path, origin.x, origin.y);
+	loadImage(a->path, origin.x, origin.y, false);
 }
 
 void HypnoEngine::runMice(const Hotspot h, Mice *a) {
@@ -528,9 +625,7 @@ void HypnoEngine::runEscape(const Hotspot h, Escape *a) {
 }
 
 void HypnoEngine::runCutscene(const Hotspot h, Cutscene *a) {
-    _nextMoviesToPlay.push_back(a->path);
-	_nextMoviesPositions.push_back(Common::Point(0, 0));
-	_nextMoviesScales.push_back(true);
+	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true));
 }
 
 void HypnoEngine::runGlobal(const Hotspot h, Global *a) {
@@ -548,11 +643,9 @@ void HypnoEngine::runPlay(const Hotspot h, Play *a) {
 	Common::Point origin = a->origin;
 
 	if (a->flag == "BITMAP")
-			loadImage(a->path, origin.x, origin.y);
-	else { 
-    	_nextMoviesToPlay.push_back(a->path);
-		_nextMoviesPositions.push_back(origin);
-		_nextMoviesScales.push_back(false);
+			loadImage(a->path, origin.x, origin.y, false);
+	else {
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false));
 	}
 }
 
@@ -561,11 +654,9 @@ void HypnoEngine::runWalN(const Hotspot h, WalN *a) {
 		return;
 	Common::Point origin = a->origin;
 	if (a->flag == "BITMAP")
-			loadImage(a->path, origin.x, origin.y);
+			loadImage(a->path, origin.x, origin.y, false);
 	else { 
-    	_nextMoviesToPlay.push_back(a->path);
-		_nextMoviesPositions.push_back(origin);
-		_nextMoviesScales.push_back(false);
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false));
 	}
 }
 
@@ -573,6 +664,33 @@ void HypnoEngine::runQuit(const Hotspot h, Quit *a) {
     quitGame();
 }
 
+// Shoots
+
+bool HypnoEngine::clickedShoot(Common::Point mousePos) {
+	bool found = false;
+	int x;
+	int y;
+
+	Videos::iterator it = _videosPlaying.begin();
+	//it++;
+	for (; it != _videosPlaying.end(); ++it) {
+		x = mousePos.x - it->position.x;
+		y = mousePos.y - it->position.y;
+		//debug("%d %d %d %d", x, y, it->videoDecoder->getWidth(), it->videoDecoder->getHeight());
+		//assert(it->currentFrame->w == it->videoDecoder->getWidth());
+		//assert(it->currentFrame->h == it->videoDecoder->getHeight());
+		if (it->videoDecoder && x >= 0 && y >= 0 && x < it->videoDecoder->getWidth() && y < it->videoDecoder->getHeight()) {
+			uint32 c = it->currentFrame->getPixel(x, y);
+			debug("inside %x", c); 
+			if (c > 0) {
+				it->videoDecoder->rewind();
+				it->videoDecoder->start();
+			}
+		}
+	}
+	return found;
+}
+
 // Hotspots
 
 void HypnoEngine::clickedHotspot(Common::Point mousePos) {
@@ -649,7 +767,7 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 		}
 	}
 	if (found) {
-		debug("Hovered over %d %d %d %d!", selected.rect.left, selected.rect.top, selected.rect.bottom, selected.rect.right);
+		//debug("Hovered over %d %d %d %d!", selected.rect.left, selected.rect.top, selected.rect.bottom, selected.rect.right);
 
 		//debug("hotspot actions size: %d", h.actions.size());
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
@@ -662,9 +780,16 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 	return false;
 }
 
-void HypnoEngine::loadImage(const Common::String &name, int x, int y) {
+void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
 	Graphics::Surface *surf = decodeFrame(name, 0);
-	_compositeSurface->transBlitFrom(*surf, Common::Point(x, y), _transparentColor);
+	drawImage(*surf, x , y, transparent);
+}
+
+void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transparent) {
+	if (transparent)
+		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), _transparentColor);
+	else 
+		_compositeSurface->blitFrom(surf, Common::Point(x, y));
 }
 
 Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, bool convert) {
@@ -695,56 +820,63 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	return rframe;
 }
 
+void HypnoEngine::updateScreen(MVideo &video) {
+	const Graphics::Surface *frame = video.videoDecoder->decodeNextFrame();
+	video.currentFrame = frame;
+	Graphics::Surface *sframe, *cframe;
 
-void HypnoEngine::drawScreen() {
-	Graphics::ManagedSurface *surface = _compositeSurface;
+	if (video.scaled) {
+		sframe = frame->scale(_screenW, _screenH);
+		cframe = sframe->convertTo(_pixelFormat, video.videoDecoder->getPalette());
+	} else
+		cframe = frame->convertTo(_pixelFormat, video.videoDecoder->getPalette());
+	
+	if (video.transparent)
+		_compositeSurface->transBlitFrom(*cframe, video.position, _transparentColor);
+	else
+		_compositeSurface->blitFrom(*cframe, video.position);
 
-	if (_videoDecoder && !_videoDecoder->isPaused()) {
-		const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
-		Graphics::Surface *sframe, *cframe;
 
-		if (_movieScale) {
-			sframe = frame->scale(_screenW, _screenH);
-			cframe = sframe->convertTo(_pixelFormat, _videoDecoder->getPalette());
-		} else
-			cframe = frame->convertTo(_pixelFormat, _videoDecoder->getPalette());
+	if (video.scaled) { 
+		sframe->free();
+		delete sframe;
+	}
 
-		debug("Move position: %d %d", _moviePosition.x, _moviePosition.y);
-		surface->blitFrom(*cframe, _moviePosition);
+	cframe->free();
+	delete cframe;
 
-		if (_movieScale) { 
-			sframe->free();
-			delete sframe;
-		}
+}
 
-		cframe->free();
-		delete cframe;
-	}
 
-	g_system->copyRectToScreen(surface->getPixels(), surface->pitch, 0, 0, _screenW, _screenH);
+void HypnoEngine::drawScreen() {
+	g_system->copyRectToScreen(_compositeSurface->getPixels(), _compositeSurface->pitch, 0, 0, _screenW, _screenH);
 	g_system->updateScreen();
 }
 
 // Video handling
 
-void HypnoEngine::playVideo(const Common::String &name) {
+void HypnoEngine::playVideo(MVideo &video) {
 	//debugC(1, kPrivateDebugFunction, "%s(%s)", __FUNCTION__, name.c_str());
+	debug("video.path: %s", video.path.c_str());
 	Common::File *file = new Common::File();
-	Common::String path = convertPath(name);
+	Common::String path = convertPath(video.path);
 
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
 
-	if (!_videoDecoder->loadStream(file))
+	assert(video.videoDecoder == nullptr);
+	video.videoDecoder = new Video::SmackerDecoder();
+
+	if (!video.videoDecoder->loadStream(file))
 		error("unable to load video %s", path.c_str());
-	_videoDecoder->start();
+	video.videoDecoder->start();
 }
 
-void HypnoEngine::skipVideo() {
-	_videoDecoder->close();
-	delete _videoDecoder;
-	_videoDecoder = nullptr;	
-	_currentMovie = "";
+void HypnoEngine::skipVideo(MVideo &video) {
+	video.videoDecoder->close();
+	delete video.videoDecoder;
+	video.videoDecoder = nullptr;	
+	//_currentMovie = "";
 }
 
 // Sound handling
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 89bbf9880f..d73f795ebf 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -30,7 +30,7 @@
 #include "common/serializer.h"
 #include "engines/engine.h"
 #include "graphics/managed_surface.h"
-#include "video/smk_decoder.h"
+
 
 #include "hypno/grammar.h"
 
@@ -77,7 +77,6 @@ public:
 
 	Audio::SoundHandle _fgSoundHandle;
 	Audio::SoundHandle _bgSoundHandle;
-	Video::SmackerDecoder *_videoDecoder;
 	Common::InstallShieldV3 _installerArchive;
 
 	Common::Error run() override;
@@ -86,19 +85,24 @@ public:
 	void resetLevelState();
 	bool checkLevelCompleted();
 	void runLevel(Common::String name);
-	void runScene(Hotspots hots, Movies intros);
+	void runScene(Hotspots hots, Videos intros);
+	ShootInfos _shootInfos;
 	void runArcade(ArcadeShooting arc);
 
 	void restartGame();
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
 	void loadAssets();
-	void loadMis(Common::String filename);
+	void parseLevel(Common::String filename);
+	void parseArcadeShooting(Common::String name, Common::String data);
+	void parseShootList(Common::String name, Common::String data);
 	LibData loadLib(char *filename);
 	Common::HashMap<Common::String, Common::String> _assets;
 
 	// User input
 	void clickedHotspot(Common::Point);
+	void shootSpiderweb(Common::Point);
+	bool clickedShoot(Common::Point);
 	bool hoverHotspot(Common::Point);
 
 	// Cursors
@@ -120,11 +124,12 @@ public:
 	void syncGameStream(Common::Serializer &s);
 
 	Common::String convertPath(const Common::String &);
-	void playVideo(const Common::String &);
-	void skipVideo();
+	void playVideo(MVideo &video);
+	void skipVideo(MVideo &video);
 
 	Graphics::Surface *decodeFrame(const Common::String &name, int frame, bool convert = true);
-	void loadImage(const Common::String &file, int x, int y);
+	void loadImage(const Common::String &file, int x, int y, bool transparent);
+	void drawImage(Graphics::Surface &image, int x, int y, bool transparent);
 
 	// Cursors
 	void changeCursor(const Common::String &, uint32);
@@ -145,10 +150,11 @@ public:
 	Graphics::ManagedSurface *_compositeSurface;
 	uint32 _transparentColor;
 	Common::Rect screenRect;
+	void updateScreen(MVideo &video);
 	void drawScreen();
 
 	// intros
-	Common::HashMap<Common::String, Movies> _intros;
+	Common::HashMap<Common::String, Videos> _intros;
 
 	// settings 
 	Common::String _nextSetting;
@@ -160,12 +166,9 @@ public:
 	HotspotsStack stack;
 
 	// Movies
-	Movies _nextMoviesToPlay;
-	Common::List<Common::Point> _nextMoviesPositions;
-	Common::List<bool> _nextMoviesScales;
-	Common::Point _moviePosition;
-	bool _movieScale;
-	Common::String _currentMovie;
+	Videos _nextSequentialVideoToPlay;
+	Videos _nextParallelVideoToPlay;
+	Videos _videosPlaying;
 
 	// Sounds
 	void playSound(const Common::String &, uint, bool, bool);
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index 7d141b656d..5d0005d16e 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -117,12 +117,22 @@ bline: F0TOK FILENAME {
 		shoot->animation = $2;
 		debug("F0 %s", $2); 
 	 	}
-     | ITOK  NAME  { debug("I %s", $2); }
-	 | A0TOK NUM NUM { debug("A0 %d %d", $2, $3); }
+     | ITOK  NAME  { 
+		 shoot->name = $2;
+		 debug("I %s", $2); 
+	   }
+	 | A0TOK NUM NUM { 
+		 shoot->position = Common::Point($2, $3);
+		 debug("A0 %d %d", $2, $3); 
+		}
 	 | B0TOK NUM NUM { debug("B0 %d %d", $2, $3); }
 	 | K0TOK NUM NUM { debug("K0 %d %d", $2, $3); }
-	 | P0TOK NUM NUM { debug("P0 %d %d", $2, $3); }
-	 | OTOK NUM NUM { debug("O %d %d", $2, $3); }
+	 | P0TOK NUM NUM {
+		debug("P0 %d %d", $2, $3); 
+	   }
+	 | OTOK NUM NUM { 
+		debug("O %d %d", $2, $3); 
+	   }
 	 | CTOK NUM  { debug("C %d", $2); } 
 	 | HTOK NUM  { debug("H %d", $2); }
 	 | WTOK NUM  { debug("W %d", $2); }
@@ -130,8 +140,8 @@ bline: F0TOK FILENAME {
 	 | SNTOK FILENAME enc { debug("SN %s", $2); }
 	 | ZTOK {
 		g_parsedArc.shoots.push_back(*shoot); 
-		delete shoot; 
-		shoot = nullptr;
+		//delete shoot; 
+		//shoot = nullptr;
 	    debug("Z"); 
 		}
      ;
\ No newline at end of file


Commit: 43acfd7fbda44c110ecd233bdd69260977acb45d
    https://github.com/scummvm/scummvm/commit/43acfd7fbda44c110ecd233bdd69260977acb45d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: simplified code to parse lib files and first attempt to play raw sounds

Changed paths:
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/grammar_arc.y
    engines/hypno/spider/lexer_arc.l


diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index cf4b40b518..fd1021483b 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "audio/audiostream.h"
-#include "audio/decoders/wave.h"
+#include "audio/decoders/raw.h"
 #include "common/archive.h"
 #include "common/config-manager.h"
 #include "common/debug-channels.h"
@@ -34,6 +34,7 @@
 #include "common/system.h"
 #include "common/timer.h"
 #include "common/tokenizer.h"
+#include "common/memstream.h"
 #include "engines/util.h"
 #include "image/bmp.h"
 
@@ -127,48 +128,43 @@ void HypnoEngine::parseLevel(Common::String filename) {
 LibData HypnoEngine::loadLib(char *filename) {
 	Common::File libfile;
     assert(libfile.open(filename));
-	const uint32 fileSize = libfile.size();
-	byte *buf = (byte *)malloc(fileSize + 1);
-	byte *it = buf;
-	libfile.read(buf, fileSize);
 	uint32 i = 0;
-	uint32 j = 0;
-	bool cont = false;
-	Common::String entry;
+	Common::String entry = "<>";
 	LibData r;
-
-	while (true) {
-		cont = true;
-		entry.clear();
-		for (j = 0; j < 24; j++) {
-			if (cont && it[i] != 0x96 && it[i] != 0x0) {
-				entry += tolower(char(it[i]));
-			}
-			else
-				cont = false;
-			i++;			
+	FileData f;
+	f.name = "<>";
+	byte b;
+	uint32 start;
+	uint32 size;
+	uint32 pos;
+
+	while (f.name.size() > 0) {
+		f.name.clear();
+		f.data.clear();
+		for (i = 0; i < 12; i++) {
+			b = libfile.readByte();
+			if (b != 0x96 && b != 0x0)
+				f.name += tolower(char(b));
 		}
-		if (!cont && entry.size() > 0) {
-			debug("Found %s", entry.c_str());
-			r.filenames.push_back(entry);
-		}
-		else {
-			break;
+		debug("name: %s", f.name.c_str());
+		start = libfile.readUint32LE();
+		size = libfile.readUint32LE();
+		debug("field: %x", libfile.readUint32LE());
+
+		pos = libfile.pos();
+		libfile.seek(start);
+
+		for (i = 0; i < size; i++) {
+			b = libfile.readByte();
+			if (b != '\n')
+				b = b ^ 0xfe;
+			f.data.push_back(b);
 		}
+		debug("size: %d", f.data.size());
+		libfile.seek(pos);
+		r.push_back(f);
 
 	}
-
-	while (it[i] != '\n')
-	    i++;
-
-	//ByteArray *files = new ByteArray();
-
-	for (; i < fileSize; i++) {
-		if (it[i] != '\n')
-			it[i] = it[i] ^ 0xfe;
-		r.data.push_back(it[i]);
-	}
-	
 	return r;
 }
 
@@ -216,27 +212,35 @@ void HypnoEngine::loadAssets() {
 	LibData files = loadLib("C_MISC/MISSIONS.LIB");
 	uint32 i = 0;
 	uint32 j = 0;
-	uint32 k = 0;
 
 	Common::String arc;
 	Common::String list;
 
-	debug("file: %s",files.filenames[j].c_str());
-	for (i = 0; i < files.data.size(); i++) {
-		arc += files.data[i];
-		if (files.data[i] == 'X') {
+	debug("Splitting file: %s",files[0].name.c_str());
+	for (i = 0; i < files[0].data.size(); i++) {
+		arc += files[0].data[i];
+		if (files[0].data[i] == 'X') {
 			i++;
-			for (k = i; k < files.data.size(); k++) {
-				if (files.data[k] == 'Y')
+			for (j = i; j < files[0].data.size(); j++) {
+				if (files[0].data[j] == 'Y')
 					break;
-				list += files.data[k];
+				list += files[0].data[j];
 			}
 			break; // No need to keep parsing, no more files are used in the demo
 		}
 	}
 
-	parseArcadeShooting(files.filenames[0], arc);
-	parseShootList(files.filenames[0], list);
+	parseArcadeShooting(files[0].name, arc);
+	parseShootList(files[0].name, list);
+
+	//files = loadLib("C_MISC/FONTS.LIB");
+	files = loadLib("C_MISC/SOUND.LIB");
+	//ByteArray *raw = new ByteArray(files[3].data);
+
+	//Common::MemorySeekableReadWriteStream *mstream = new Common::MemorySeekableReadWriteStream(raw->data(), raw->size());
+	//Audio::LoopingAudioStream *stream;
+	//stream = new Audio::LoopingAudioStream(Audio::makeRawStream(mstream, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO), 1);
+	//_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
 
 	// quit level
 	Hotspot q;
@@ -270,8 +274,6 @@ Common::Error HypnoEngine::run() {
 	_language = Common::parseLanguage(ConfMan.get("language"));
 	_platform = Common::parsePlatform(ConfMan.get("platform"));
 
-	//return Common::kNoError;
-
 	Graphics::ModeList modes;
 	modes.push_back(Graphics::Mode(640, 480));
 	modes.push_back(Graphics::Mode(320, 200));
@@ -283,7 +285,7 @@ Common::Error HypnoEngine::run() {
 	if (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8())
 		return Common::kUnsupportedColorMode;
 
-	screenRect = Common::Rect(0, 0, _screenW, _screenH);
+	//screenRect = Common::Rect(0, 0, _screenW, _screenH);
 	//changeCursor("default");
 	_compositeSurface = new Graphics::ManagedSurface();
 	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
@@ -316,10 +318,13 @@ Common::Error HypnoEngine::run() {
 
 void HypnoEngine::runLevel(Common::String name) {
 	assert(_levels.contains(name));
-	if (_levels[name].hots.size() == 0)
+	if (_levels[name].hots.size() == 0) {
+		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
-	else
+	} else {
+		changeScreenMode("scene");
 		runScene(_levels[name].hots, _levels[name].intros);
+	}
 
 }
 
@@ -334,18 +339,6 @@ void HypnoEngine::shootSpiderweb(Common::Point target) {
 }
 
 void HypnoEngine::runArcade(ArcadeShooting arc) {
-	// Move into a function
-	_screenW = 320;
-	_screenH = 200;
-
-	initGraphics(_screenW, _screenH, nullptr);
-
-	_compositeSurface->free();
-	delete _compositeSurface;
-
-	_compositeSurface = new Graphics::ManagedSurface();
-	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
-
 	Common::Event event;
 	Common::Point mousePos;
 	
@@ -373,9 +366,6 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			case Common::EVENT_LBUTTONDOWN:
 				shootSpiderweb(mousePos);
 				clickedShoot(mousePos);
-
-				//if (!_nextHotsToAdd || !_nextHotsToRemove)
-				// 	clickedHotspot(mousePos);
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
@@ -439,19 +429,6 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 }
 
 void HypnoEngine::runScene(Hotspots hots, Videos intros) {
-	// Move into a function
-	_screenW = 640;
-	_screenH = 480;
-
-	initGraphics(_screenW, _screenH, nullptr);
-
-	_compositeSurface->free();
-	delete _compositeSurface;
-
-	_compositeSurface = new Graphics::ManagedSurface();
-	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
-
-
 	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
@@ -491,6 +468,8 @@ void HypnoEngine::runScene(Hotspots hots, Videos intros) {
 				break;
 
 			case Common::EVENT_LBUTTONDOWN:
+				if (stack.empty())
+					break;
 				if (!_nextHotsToAdd || !_nextHotsToRemove)
 				 	clickedHotspot(mousePos);
 				break;
@@ -820,6 +799,34 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	return rframe;
 }
 
+void HypnoEngine::changeScreenMode(Common::String mode) {
+	if (mode == "scene") {
+		_screenW = 640;
+		_screenH = 480;
+
+		initGraphics(_screenW, _screenH, nullptr);
+
+		_compositeSurface->free();
+		delete _compositeSurface;
+
+		_compositeSurface = new Graphics::ManagedSurface();
+		_compositeSurface->create(_screenW, _screenH, _pixelFormat);
+
+	} else if (mode == "arcade") {
+		_screenW = 320;
+		_screenH = 200;
+
+		initGraphics(_screenW, _screenH, nullptr);
+
+		_compositeSurface->free();
+		delete _compositeSurface;
+
+		_compositeSurface = new Graphics::ManagedSurface();
+		_compositeSurface->create(_screenW, _screenH, _pixelFormat);
+	} else
+		error("Unknown screen mode %s", mode.c_str());
+}
+
 void HypnoEngine::updateScreen(MVideo &video) {
 	const Graphics::Surface *frame = video.videoDecoder->decodeNextFrame();
 	video.currentFrame = frame;
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index d73f795ebf..b0c9250944 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -54,10 +54,12 @@ enum {
 };
 
 typedef Common::Array<byte> ByteArray;
-typedef struct LibData {
-	Common::Array<Common::String> filenames;
+typedef struct FileData {
+	Common::String name;
 	ByteArray data;
-} LibData;
+} FileData;
+
+typedef Common::Array<FileData> LibData;
 
 class HypnoEngine : public Engine {
 private:
@@ -75,8 +77,7 @@ public:
 	Common::Language _language;
 	Common::Platform _platform;
 
-	Audio::SoundHandle _fgSoundHandle;
-	Audio::SoundHandle _bgSoundHandle;
+	Audio::SoundHandle _soundHandle;
 	Common::InstallShieldV3 _installerArchive;
 
 	Common::Error run() override;
@@ -147,6 +148,8 @@ public:
 	void runWalN(const Hotspot h, WalN *a);
 	void runGlobal(const Hotspot h, Global *a);
 
+	// Screen
+	void changeScreenMode(Common::String mode);
 	Graphics::ManagedSurface *_compositeSurface;
 	uint32 _transparentColor;
 	Common::Rect screenRect;
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index 5d0005d16e..e033277a0b 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -60,7 +60,7 @@ using namespace Hypno;
 %token<s> NAME FILENAME
 %token<i> NUM
 // header
-%token CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
+%token YBTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
 %token PTOK ATOK VTOK OTOK NTOK RTOK ITOK SNTOK ZTOK
 
 // body
@@ -74,7 +74,7 @@ using namespace Hypno;
 
 %%
 
-start: header body
+start: YBTOK header body
        ;
 
 
diff --git a/engines/hypno/spider/lexer_arc.l b/engines/hypno/spider/lexer_arc.l
index 8cf37667a2..9d4cdfc953 100644
--- a/engines/hypno/spider/lexer_arc.l
+++ b/engines/hypno/spider/lexer_arc.l
@@ -60,6 +60,7 @@ A0							return A0TOK;
 B0							return B0TOK;
 K0							return K0TOK;
 P0							return P0TOK;
+YB							return YBTOK;
 22[k|K]						return ENCTOK;
 [A-Za-z_][A-Za-z_0-9]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
 [A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;


Commit: 559ad7d46fa2564d0057339c466e30570d791bdc
    https://github.com/scummvm/scummvm/commit/559ad7d46fa2564d0057339c466e30570d791bdc
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed use-after-free and small refactoring of code

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 96c5f2eb1e..5208573218 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -156,7 +156,7 @@ class ArcadeShooting {
 	Common::String background;
 	Common::String player;
 	Shoots shoots;
-    ~ArcadeShooting() { debug("destroying arcade shooting"); };
+    ~ArcadeShooting() { };
 };
 
 class Level {
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index fd1021483b..95fcbebe4c 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -204,6 +204,9 @@ void HypnoEngine::parseArcadeShooting(Common::String name, Common::String data)
 	Level level;
 	level.arcade = g_parsedArc;  
 	_levels[name] = level;
+	g_parsedArc.background.clear();
+	g_parsedArc.player.clear();
+	g_parsedArc.shoots.clear();
 }
 
 void HypnoEngine::loadAssets() {
@@ -341,9 +344,7 @@ void HypnoEngine::shootSpiderweb(Common::Point target) {
 void HypnoEngine::runArcade(ArcadeShooting arc) {
 	Common::Event event;
 	Common::Point mousePos;
-	
-	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
-	_compositeSurface->setTransparentColor(_transparentColor);
+	Common::List<uint32> videosToRemove;
 
 	//_nextParallelVideoToPlay.push_back(MVideo(arc.background, Common::Point(0, 0), false, false));
 	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false);	
@@ -408,18 +409,28 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			}
 		}
 
-		drawImage(*sp, 60, 129, true);
+		//drawImage(*sp, 60, 129, true);
+		uint32 i = 0;
+		videosToRemove.clear();
 
 		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
 			if (it->videoDecoder) {
 				if (it->videoDecoder-> getCurFrame() > 0 && it->videoDecoder-> getCurFrame() >= it->videoDecoder->getFrameCount() - it->finishBeforeEnd) {
 				delete it->videoDecoder;
 				it->videoDecoder = nullptr;
-				//TODO: remove from the _videosPlaying list
+				videosToRemove.push_back(i);
 
 				} else if (it->videoDecoder->needsUpdate()) {
 					updateScreen(*it);
 				}
+				i++;
+			}
+		}
+
+		if (videosToRemove.size() > 0) {
+			for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
+				debug("removing %d from %d size", *it, _videosPlaying.size()); 
+				_videosPlaying.remove_at(*it);
 			}
 		}
 
@@ -432,9 +443,6 @@ void HypnoEngine::runScene(Hotspots hots, Videos intros) {
 	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
-
-	_transparentColor = _pixelFormat.RGBToColor(0, 0x82, 0);
-	_compositeSurface->setTransparentColor(_transparentColor);
 	
 	stack.clear();
 	_nextHotsToAdd = &hots;
@@ -812,6 +820,9 @@ void HypnoEngine::changeScreenMode(Common::String mode) {
 		_compositeSurface = new Graphics::ManagedSurface();
 		_compositeSurface->create(_screenW, _screenH, _pixelFormat);
 
+		_transparentColor = _pixelFormat.RGBToColor(0, 0x82, 0);
+		_compositeSurface->setTransparentColor(_transparentColor);
+
 	} else if (mode == "arcade") {
 		_screenW = 320;
 		_screenH = 200;
@@ -823,6 +834,9 @@ void HypnoEngine::changeScreenMode(Common::String mode) {
 
 		_compositeSurface = new Graphics::ManagedSurface();
 		_compositeSurface->create(_screenW, _screenH, _pixelFormat);
+
+		_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
+		_compositeSurface->setTransparentColor(_transparentColor);
 	} else
 		error("Unknown screen mode %s", mode.c_str());
 }


Commit: d93066eb08d044a4ec46b2c5dad05e617ac1f657
    https://github.com/scummvm/scummvm/commit/d93066eb08d044a4ec46b2c5dad05e617ac1f657
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: parsing, loading and playing of background music

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/grammar_arc.y


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 5208573218..3df8bcb633 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -49,6 +49,13 @@ typedef Common::List<Action*> Actions;
 
 class Hotspot;
 typedef Common::Array<Hotspot> Hotspots;
+
+class Scene {
+  public:
+	Hotspots hots;
+	Common::String sound;
+};
+
 typedef Common::Array<Hotspots *> HotspotsStack;
 
 class MVideo {
@@ -150,18 +157,20 @@ class ShootInfo {
 };
 
 typedef Common::List<ShootInfo> ShootInfos;
+typedef Common::List<Common::String> Sounds;
 
 class ArcadeShooting {
   public:
 	Common::String background;
 	Common::String player;
 	Shoots shoots;
+	Sounds sounds;
     ~ArcadeShooting() { };
 };
 
 class Level {
   public:
-	Hotspots hots;
+	Scene scene;
 	Videos intros;
 	ArcadeShooting arcade;
 };
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 95fcbebe4c..d00fa6d1dc 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -108,7 +108,7 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
 }
 
-void HypnoEngine::parseLevel(Common::String filename) {
+void HypnoEngine::parseScene(Common::String filename) {
     filename = convertPath(filename);
 	Common::File *test = new Common::File();
 	assert(isDemo());
@@ -120,26 +120,25 @@ void HypnoEngine::parseLevel(Common::String filename) {
 	buf[fileSize] = '\0';
 	parse_mis(buf);
 	Level level;
-	level.hots = *g_parsedHots; 
+	level.scene.hots = *g_parsedHots; 
 	_levels[filename] = level;
 	debug("Loaded hots size: %d", g_parsedHots->size());
 }
 
-LibData HypnoEngine::loadLib(char *filename) {
+void HypnoEngine::loadLib(Common::String filename, LibData &r) {
 	Common::File libfile;
     assert(libfile.open(filename));
 	uint32 i = 0;
 	Common::String entry = "<>";
-	LibData r;
 	FileData f;
-	f.name = "<>";
+	f.data.push_back(0);
 	byte b;
 	uint32 start;
 	uint32 size;
 	uint32 pos;
 
-	while (f.name.size() > 0) {
-		f.name.clear();
+	do {
+		f.name = filename + "/";
 		f.data.clear();
 		for (i = 0; i < 12; i++) {
 			b = libfile.readByte();
@@ -162,10 +161,10 @@ LibData HypnoEngine::loadLib(char *filename) {
 		}
 		debug("size: %d", f.data.size());
 		libfile.seek(pos);
-		r.push_back(f);
+		if (size > 0)
+			r.push_back(f);
 
-	}
-	return r;
+	} while (size > 0);
 }
 
 void HypnoEngine::resetLevelState() {
@@ -212,7 +211,8 @@ void HypnoEngine::parseArcadeShooting(Common::String name, Common::String data)
 void HypnoEngine::loadAssets() {
 
 	
-	LibData files = loadLib("C_MISC/MISSIONS.LIB");
+	LibData files; 
+	loadLib("c_misc/missions.lib", files);
 	uint32 i = 0;
 	uint32 j = 0;
 
@@ -236,14 +236,9 @@ void HypnoEngine::loadAssets() {
 	parseArcadeShooting(files[0].name, arc);
 	parseShootList(files[0].name, list);
 
-	//files = loadLib("C_MISC/FONTS.LIB");
-	files = loadLib("C_MISC/SOUND.LIB");
-	//ByteArray *raw = new ByteArray(files[3].data);
-
-	//Common::MemorySeekableReadWriteStream *mstream = new Common::MemorySeekableReadWriteStream(raw->data(), raw->size());
-	//Audio::LoopingAudioStream *stream;
-	//stream = new Audio::LoopingAudioStream(Audio::makeRawStream(mstream, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO), 1);
-	//_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
+	loadLib("c_misc/fonts.lib", _fontFiles);
+	loadLib("demo/sound.lib", _soundFiles);
+	loadLib("c_misc/sound.lib", _soundFiles);
 
 	// quit level
 	Hotspot q;
@@ -253,21 +248,24 @@ void HypnoEngine::loadAssets() {
 	Level level;
 	Hotspots quit;
 	quit.push_back(q);
-	level.hots = quit;  
+	level.scene.hots = quit;  
 	_levels["mis/quit.mis"] = level;
 
 	// Read assets from mis files
-	parseLevel("mis/demo.mis");
+	parseScene("mis/demo.mis");
 	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine1.smk", Common::Point(0, 0), false, true));
 	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine2.smk", Common::Point(0, 0), false, true));
-	_levels["mis/demo.mis"].hots[1].setting = "c1.mi_";
-	_levels["mis/demo.mis"].hots[2].setting = "mis/alley.mis";
-	_levels["mis/demo.mis"].hots[5].setting = "mis/order.mis";
+	_levels["mis/demo.mis"].scene.hots[1].setting = "c_misc/missions.lib/c1.mi_";
+	_levels["mis/demo.mis"].scene.hots[2].setting = "mis/alley.mis";
+	_levels["mis/demo.mis"].scene.hots[5].setting = "mis/order.mis";
+	_levels["mis/demo.mis"].scene.sound = "demo/sound.lib/menu_mus.raw";
+
 
-	parseLevel("mis/order.mis");
-	_levels["mis/order.mis"].hots[1].setting = "mis/quit.mis";
-	parseLevel("mis/alley.mis");
+	parseScene("mis/order.mis");
+	_levels["mis/order.mis"].scene.hots[1].setting = "mis/quit.mis";
+	parseScene("mis/alley.mis");
 	_levels["mis/alley.mis"].intros.push_back(MVideo("demo/aleyc01s.smk", Common::Point(0, 0), false, true));
+	_levels["mis/alley.mis"].scene.sound = "demo/sound.lib/alleymus.raw";
 
 	//loadMis("mis/shoctalk.mis");
 
@@ -288,8 +286,6 @@ Common::Error HypnoEngine::run() {
 	if (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8())
 		return Common::kUnsupportedColorMode;
 
-	//screenRect = Common::Rect(0, 0, _screenW, _screenH);
-	//changeCursor("default");
 	_compositeSurface = new Graphics::ManagedSurface();
 	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
 
@@ -321,12 +317,15 @@ Common::Error HypnoEngine::run() {
 
 void HypnoEngine::runLevel(Common::String name) {
 	assert(_levels.contains(name));
-	if (_levels[name].hots.size() == 0) {
+	stopSound();
+	_music = "";
+
+	if (_levels[name].scene.hots.size() == 0) {
 		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
 	} else {
 		changeScreenMode("scene");
-		runScene(_levels[name].hots, _levels[name].intros);
+		runScene(_levels[name].scene, _levels[name].intros);
 	}
 
 }
@@ -346,7 +345,6 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
 
-	//_nextParallelVideoToPlay.push_back(MVideo(arc.background, Common::Point(0, 0), false, false));
 	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false);	
 	Graphics::Surface *sp = decodeFrame(arc.player, 2);
 
@@ -434,18 +432,23 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			}
 		}
 
+		if (_music.empty()) {
+			_music = "c_misc/sound.lib/" + arc.sounds.front();
+			playSound(_music, 0);
+		}
+
 		drawScreen();
 		g_system->delayMillis(10);
 	}
 }
 
-void HypnoEngine::runScene(Hotspots hots, Videos intros) {
+void HypnoEngine::runScene(Scene scene, Videos intros) {
 	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
 	
 	stack.clear();
-	_nextHotsToAdd = &hots;
+	_nextHotsToAdd = &scene.hots;
 	_nextSequentialVideoToPlay = intros;	
 	changeCursor("mouse/cursor1.smk", 0);
 
@@ -558,6 +561,12 @@ void HypnoEngine::runScene(Hotspots hots, Videos intros) {
 			drawScreen();
 		}
 
+		if (_music.empty()) {
+			_music = scene.sound;
+			playSound(_music, 0);
+		}
+
+
 		if (checkLevelCompleted())
 			_nextSetting = "mis/demo.mis";
 
@@ -612,6 +621,8 @@ void HypnoEngine::runEscape(const Hotspot h, Escape *a) {
 }
 
 void HypnoEngine::runCutscene(const Hotspot h, Cutscene *a) {
+	stopSound();
+	_music = "";
 	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true));
 }
 
@@ -902,15 +913,28 @@ void HypnoEngine::skipVideo(MVideo &video) {
 
 // Sound handling
 
-void HypnoEngine::stopSound(bool all) {
-	// debugC(1, kPrivateDebugFunction, "%s(%d)", __FUNCTION__, all);
+void HypnoEngine::playSound(Common::String name, uint32 loops) {
+
+	debug("playing %s", name.c_str());
+	ByteArray *raw;
+	Audio::LoopingAudioStream *stream;
+	Common::MemorySeekableReadWriteStream *mstream;
+
+	for (LibData::iterator it = _soundFiles.begin(); it != _soundFiles.end(); ++it) {
+			if (it->name == name) {
+				raw = new ByteArray(it->data);
+				stream = new Audio::LoopingAudioStream(Audio::makeRawStream(raw->data(), raw->size(), 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
+				_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
+				break;
+			}
+	}
+
+
+}
 
-	// if (all) {
-	// 	_mixer->stopHandle(_fgSoundHandle);
-	// 	_mixer->stopHandle(_bgSoundHandle);
-	// } else {
-	// 	_mixer->stopHandle(_fgSoundHandle);
-	// }
+void HypnoEngine::stopSound() {
+	debugC(1, kHypnoDebugFunction, "%s()", __FUNCTION__);
+	_mixer->stopHandle(_soundHandle);
 }
 
 // Path handling
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index b0c9250944..32b188b83a 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -82,11 +82,13 @@ public:
 
 	Common::Error run() override;
 	Levels _levels;
+	LibData _soundFiles;
+	LibData _fontFiles;
 	Common::HashMap<Common::String, int> _levelState;
 	void resetLevelState();
 	bool checkLevelCompleted();
 	void runLevel(Common::String name);
-	void runScene(Hotspots hots, Videos intros);
+	void runScene(Scene scene, Videos intros);
 	ShootInfos _shootInfos;
 	void runArcade(ArcadeShooting arc);
 
@@ -94,10 +96,10 @@ public:
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
 	void loadAssets();
-	void parseLevel(Common::String filename);
+	void parseScene(Common::String filename);
 	void parseArcadeShooting(Common::String name, Common::String data);
 	void parseShootList(Common::String name, Common::String data);
-	LibData loadLib(char *filename);
+	void loadLib(Common::String filename, LibData &r);
 	Common::HashMap<Common::String, Common::String> _assets;
 
 	// User input
@@ -174,8 +176,9 @@ public:
 	Videos _videosPlaying;
 
 	// Sounds
-	void playSound(const Common::String &, uint, bool, bool);
-	void stopSound(bool);
+	Common::String _music;
+	void playSound(Common::String name, uint32);
+	void stopSound();
 	bool isSoundActive();
 	bool _noStopSounds;
 
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index e033277a0b..683ebda644 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -99,7 +99,10 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 		  debug("I %s", $2); 
 		}
 	  | QTOK NUM NUM { debug("Q %d %d", $2, $3); }
-	  | SNTOK FILENAME enc { debug("SN %s", $2); }
+	  | SNTOK FILENAME enc {
+		  g_parsedArc.sounds.push_back($2); 
+		  debug("SN %s", $2); 
+		}
 	  | HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
 	  | HTOK CB3TOK NUM NUM { debug("H %d %d", $3, $4); }
 	  | ZTOK RETTOK { debug("Z"); }


Commit: 5165f94f3c84a001b1cfec994a240b31ba9beae1
    https://github.com/scummvm/scummvm/commit/5165f94f3c84a001b1cfec994a240b31ba9beae1
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: basic parsing of TALK sequences

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/grammar_arc.y
    engines/hypno/spider/grammar_mis.y
    engines/hypno/spider/lexer_mis.l


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 3df8bcb633..b22f8bcb85 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -60,11 +60,12 @@ typedef Common::Array<Hotspots *> HotspotsStack;
 
 class MVideo {
   public:
-    MVideo(Common::String, Common::Point, bool, bool);
+    MVideo(Common::String, Common::Point, bool, bool, bool);
     Common::String path;
 	Common::Point position;
 	bool scaled;
 	bool transparent;
+	bool loop;
 	Video::SmackerDecoder *videoDecoder;
 	const Graphics::Surface *currentFrame;
 	uint32 finishBeforeEnd;
@@ -127,6 +128,13 @@ class Play : public Action {
 	Common::String flag;
 };
 
+class Ambient : public Action {
+  public:
+	Common::String path;
+	Common::Point origin;
+	Common::String flag;
+};
+
 class WalN : public Action {
   public:
 	Common::String path;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index d00fa6d1dc..e2ea2b5500 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -48,11 +48,12 @@ namespace Hypno {
 Hotspots *g_parsedHots;
 ArcadeShooting g_parsedArc;
 
-MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent, bool _scaled) {
+MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent, bool _scaled, bool _loop) {
 	path = _path;
 	position = _position;
 	scaled = _scaled;
 	transparent = _transparent;
+	loop = _loop;
 	videoDecoder = nullptr;
 	currentFrame = nullptr;
 	finishBeforeEnd = 0;
@@ -109,6 +110,7 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 }
 
 void HypnoEngine::parseScene(Common::String filename) {
+	debug("Parsing %s", filename.c_str());
     filename = convertPath(filename);
 	Common::File *test = new Common::File();
 	assert(isDemo());
@@ -209,8 +211,6 @@ void HypnoEngine::parseArcadeShooting(Common::String name, Common::String data)
 }
 
 void HypnoEngine::loadAssets() {
-
-	
 	LibData files; 
 	loadLib("c_misc/missions.lib", files);
 	uint32 i = 0;
@@ -253,22 +253,22 @@ void HypnoEngine::loadAssets() {
 
 	// Read assets from mis files
 	parseScene("mis/demo.mis");
-	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine1.smk", Common::Point(0, 0), false, true));
-	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine2.smk", Common::Point(0, 0), false, true));
+	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine1.smk", Common::Point(0, 0), false, true, false));
+	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine2.smk", Common::Point(0, 0), false, true, false));
 	_levels["mis/demo.mis"].scene.hots[1].setting = "c_misc/missions.lib/c1.mi_";
 	_levels["mis/demo.mis"].scene.hots[2].setting = "mis/alley.mis";
+
+	_levels["mis/demo.mis"].scene.hots[4].setting = "mis/shoctalk.mis";
 	_levels["mis/demo.mis"].scene.hots[5].setting = "mis/order.mis";
 	_levels["mis/demo.mis"].scene.sound = "demo/sound.lib/menu_mus.raw";
 
-
 	parseScene("mis/order.mis");
 	_levels["mis/order.mis"].scene.hots[1].setting = "mis/quit.mis";
 	parseScene("mis/alley.mis");
-	_levels["mis/alley.mis"].intros.push_back(MVideo("demo/aleyc01s.smk", Common::Point(0, 0), false, true));
+	_levels["mis/alley.mis"].intros.push_back(MVideo("demo/aleyc01s.smk", Common::Point(0, 0), false, true, false));
 	_levels["mis/alley.mis"].scene.sound = "demo/sound.lib/alleymus.raw";
 
-	//loadMis("mis/shoctalk.mis");
-
+	parseScene("mis/shoctalk.mis");
 }
 
 Common::Error HypnoEngine::run() {
@@ -345,7 +345,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
 
-	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false);	
+	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);	
 	Graphics::Surface *sp = decodeFrame(arc.player, 2);
 
 	changeCursor("mouse/cursor1.smk", 0);
@@ -400,7 +400,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				_shootInfos.pop_front();
 				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
 					if (it->name == si.name) {
-						_nextParallelVideoToPlay.push_back(MVideo(it->animation, it->position , true, false));
+						_nextParallelVideoToPlay.push_back(MVideo(it->animation, it->position , true, false, false));
 						_nextParallelVideoToPlay[0].finishBeforeEnd = 24;
 					}
 				}
@@ -512,10 +512,15 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 
 			if (it->videoDecoder) {
 				if (it->videoDecoder->endOfVideo()) {
-				it->videoDecoder->close();
-				delete it->videoDecoder;
-				it->videoDecoder = nullptr;
-				videosToRemove.push_back(i);
+					if (it->loop) {
+						it->videoDecoder->rewind();
+						it->videoDecoder->start();
+					} else {
+						it->videoDecoder->close();
+						delete it->videoDecoder;
+						it->videoDecoder = nullptr;
+						videosToRemove.push_back(i);
+					}
 
 				} else if (it->videoDecoder->needsUpdate()) {
 					updateScreen(*it);
@@ -561,7 +566,7 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 			drawScreen();
 		}
 
-		if (_music.empty()) {
+		if (_music.empty() && !scene.sound.empty()) {
 			_music = scene.sound;
 			playSound(_music, 0);
 		}
@@ -590,6 +595,9 @@ void HypnoEngine::runMenu(Hotspots hs) {
 			runBackground(h, (Background*) action);
 		else if (typeid(*action) == typeid(Overlay))
 			runOverlay(h, (Overlay*) action);
+		else if (typeid(*action) == typeid(Ambient))
+			runAmbient(h, (Ambient*) action);
+
 		//else if (typeid(*action) == typeid(Mice))
 		//	runMice(h, (Mice*) action);
 	}
@@ -623,7 +631,7 @@ void HypnoEngine::runEscape(const Hotspot h, Escape *a) {
 void HypnoEngine::runCutscene(const Hotspot h, Cutscene *a) {
 	stopSound();
 	_music = "";
-	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true));
+	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true, false));
 }
 
 void HypnoEngine::runGlobal(const Hotspot h, Global *a) {
@@ -640,10 +648,19 @@ void HypnoEngine::runPlay(const Hotspot h, Play *a) {
 		return;
 	Common::Point origin = a->origin;
 
-	if (a->flag == "BITMAP")
+	if (a->flag == "/BITMAP")
+			loadImage(a->path, origin.x, origin.y, false);
+	else {
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
+	}
+}
+
+void HypnoEngine::runAmbient(const Hotspot h, Ambient *a) {
+	Common::Point origin = a->origin;
+	if (a->flag == "/BITMAP")
 			loadImage(a->path, origin.x, origin.y, false);
 	else {
-		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false));
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, a->flag == "/LOOP"));
 	}
 }
 
@@ -651,10 +668,10 @@ void HypnoEngine::runWalN(const Hotspot h, WalN *a) {
 	if (a->condition.size() > 0 && !_levelState[a->condition])
 		return;
 	Common::Point origin = a->origin;
-	if (a->flag == "BITMAP")
+	if (a->flag == "/BITMAP")
 			loadImage(a->path, origin.x, origin.y, false);
 	else { 
-		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false));
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
 	}
 }
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 32b188b83a..c0c74264a0 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -147,6 +147,7 @@ public:
 	void runQuit(const Hotspot h, Quit *a);
 	void runCutscene(const Hotspot h, Cutscene *a);
 	void runPlay(const Hotspot h, Play *a);
+	void runAmbient(const Hotspot h, Ambient *a);
 	void runWalN(const Hotspot h, WalN *a);
 	void runGlobal(const Hotspot h, Global *a);
 
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index 683ebda644..f5c13011a1 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -41,7 +41,7 @@ extern int HYPNO_ARC_parse();
 extern int yylineno;
 
 void HYPNO_ARC_xerror(const char *str) {
-	debug("ERROR: %s", str);
+	error("ERROR: %s", str);
 }
 
 int HYPNO_ARC_wrap() {
diff --git a/engines/hypno/spider/grammar_mis.y b/engines/hypno/spider/grammar_mis.y
index 753340606d..6a5d3654af 100644
--- a/engines/hypno/spider/grammar_mis.y
+++ b/engines/hypno/spider/grammar_mis.y
@@ -42,7 +42,7 @@ Common::Array<uint32> smenu_idx;
 Hypno::HotspotsStack stack;
 
 void HYPNO_MIS_xerror(const char *str) {
-	debug("ERROR: %s", str);
+	error("ERROR: %s", str);
 }
 
 int HYPNO_MIS_wrap() {
@@ -61,8 +61,10 @@ using namespace Hypno;
 %token<s> NAME FILENAME FLAG COMMENT GSSWITCH COMMAND
 %token<i> NUM
 %token HOTSTOK CUTSTOK BACKTOK RETTOK  TIMETOK PALETOK BBOXTOK OVERTOK WALNTOK MICETOK PLAYTOK ENDTOK 
-%token MENUTOK SMENTOK ESCPTOK NRTOK
+%token MENUTOK SMENTOK ESCPTOK NRTOK AMBITOK
 %token GLOBTOK TONTOK TOFFTOK
+%token TALKTOK INACTOK FDTOK BOXXTOK
+%token<s> PG PA PD PH PF PE PP PI
 
 %type<s> gsswitch flag
 
@@ -137,6 +139,7 @@ line:    MENUTOK NAME mflag  {
 			Hotspots *cur = stack.back();
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
+			debug("BACK");
 		}
       |  GLOBTOK GSSWITCH NAME  { 
 		    Global *a = new Global();
@@ -147,7 +150,16 @@ line:    MENUTOK NAME mflag  {
 			hot->actions.push_back(a);
 			debug("GLOB."); 
 		}
-	  |  PLAYTOK FILENAME NUM NUM gsswitch flag { 
+		|  AMBITOK FILENAME NUM NUM flag { 
+			Ambient *a = new Ambient();
+			a->path = $2;
+			a->origin = Common::Point($3, $4);
+			a->flag = $5;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);			
+			debug("AMBI %d %d.", $3, $4); }
+	    |  PLAYTOK FILENAME NUM NUM gsswitch flag { 
 			Play *a = new Play();
 			a->path = $2;
 			a->origin = Common::Point($3, $4);
@@ -171,6 +183,7 @@ line:    MENUTOK NAME mflag  {
 			Hotspots *cur = stack.back();
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
+			debug("PALE");
 		}
 	  |  CUTSTOK FILENAME { 
 		  	Cutscene *a = new Cutscene();
@@ -198,6 +211,7 @@ line:    MENUTOK NAME mflag  {
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
 	  }
+	  |  TALKTOK talk { debug("TALK"); }
 	  |  ENDTOK RETTOK { 
 		  debug("explicit END");
 		  g_parsedHots = stack.back(); 
@@ -206,6 +220,21 @@ line:    MENUTOK NAME mflag  {
 		  }   		               
 	  ;
 
+talk:   INACTOK talk { debug("inactive"); }
+      | FDTOK talk { debug("inactive"); }
+	  | BACKTOK FILENAME NUM NUM gsswitch flag { debug("BACK in TALK"); }
+	  | BOXXTOK NUM NUM { debug("BOXX %d %d", $2, $3); }
+      | PG talk { debug("%s", $1); }
+      | PH talk { debug("%s", $1); }
+      | PF talk { debug("%s", $1); }
+      | PA talk { debug("%s", $1); } 
+      | PD talk { debug("%s", $1); }
+      | PP NUM NUM talk { debug("%s %d %d", $1, $2, $3); }
+      | PI NUM NUM talk { debug("%s %d %d", $1, $2, $3); }
+	  | PE { debug("|E"); }
+      | /*nothing*/ { debug("nothing in talk"); }
+	  ;
+
 mflag:  NRTOK
       | /*nothing*/
 	  ;
diff --git a/engines/hypno/spider/lexer_mis.l b/engines/hypno/spider/lexer_mis.l
index f7d4cef2c2..ecef309710 100644
--- a/engines/hypno/spider/lexer_mis.l
+++ b/engines/hypno/spider/lexer_mis.l
@@ -41,6 +41,7 @@
 %%
 \;[A-Za-z_0-9 \t\*]*	    /* return COMMENT; */
 MENU				    	return MENUTOK;
+AMBI						return AMBITOK;
 BACK                    	return BACKTOK;
 CUTS                    	return CUTSTOK;
 GLOB						return GLOBTOK;
@@ -54,6 +55,18 @@ OVER                        return OVERTOK;
 SMEN                        return SMENTOK;
 ESCP                        return ESCPTOK;
 PLAY						return PLAYTOK;
+TALK						return TALKTOK;
+INACTIVE					return INACTOK;
+4DBOX						return FDTOK;
+BOXX						return BOXXTOK;
+\|G[A-Za-z_0-9\\\.]+		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PG;
+\|P[A-Za-z_0-9\\\.]+		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PP;
+\|I[A-Za-z_0-9\\\.]+		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PI;
+\|H[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PH;
+\|A[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PA;
+\|D[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PD;
+\|F[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PF;
+\|E							return PE;
 NO_RETURN                   return NRTOK;
 GS_[A-Z_0-9]+           	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
 \/BBOX\=					return BBOXTOK;


Commit: bd7dd0b4fef1645d857e78ab3b2d39684f5093c0
    https://github.com/scummvm/scummvm/commit/bd7dd0b4fef1645d857e78ab3b2d39684f5093c0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: basic handling of TALK sequences

Changed paths:
  A engines/hypno/spider/talk.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/module.mk
    engines/hypno/spider/grammar_mis.y


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index b22f8bcb85..c2546260b0 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -45,7 +45,7 @@ class Action {
 	virtual ~Action() {}; // needed to make Action polymorphic
 };
 
-typedef Common::List<Action*> Actions;
+typedef Common::Array<Action*> Actions;
 
 class Hotspot;
 typedef Common::Array<Hotspot> Hotspots;
@@ -149,6 +149,25 @@ class Global : public Action {
 	Common::String command;
 };
 
+class TalkCommand {
+  public:
+	Common::String command;
+	Common::String path;
+	uint32 num;
+	Common::Point position;
+};
+
+typedef Common::Array<TalkCommand> TalkCommands;
+
+class Talk : public Action {
+  public:
+	TalkCommands commands;
+	bool active;
+	Common::String background;
+	Common::Point position;
+	Common::Rect rect;
+};
+
 class Shoot {
   public:
     Common::String name;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index e2ea2b5500..d1b6305f72 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -44,7 +44,6 @@
 
 namespace Hypno {
 
-
 Hotspots *g_parsedHots;
 ArcadeShooting g_parsedArc;
 
@@ -443,6 +442,8 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 }
 
 void HypnoEngine::runScene(Scene scene, Videos intros) {
+	_refreshConversation = false;
+	_conversation.clear();
 	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
@@ -478,9 +479,22 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 			case Common::EVENT_RETURN_TO_LAUNCHER:
 				break;
 
+			case Common::EVENT_RBUTTONDOWN:
+				if (stack.empty())
+					break;
+				if (!_conversation.empty()){
+					rightClickedConversation(mousePos);
+					break;
+				}
+			break;
+
 			case Common::EVENT_LBUTTONDOWN:
 				if (stack.empty())
 					break;
+				if (!_conversation.empty()){
+					leftClickedConversation(mousePos);
+					break;
+				}
 				if (!_nextHotsToAdd || !_nextHotsToRemove)
 				 	clickedHotspot(mousePos);
 				break;
@@ -490,6 +504,9 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 				//changeCursor("default");
 				// The following functions will return true
 				// if the cursor is changed
+				if (!_conversation.empty())
+					break;
+
 				if (hoverHotspot(mousePos)) {
 				} else
 					changeCursor("mouse/cursor1.smk", 0);
@@ -500,6 +517,13 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 			}
 		}
 
+		if (_refreshConversation && !_conversation.empty() && _nextSequentialVideoToPlay.empty()) {
+			showConversation();
+			drawScreen();
+			_refreshConversation = false;
+			_videosPlaying.clear();
+		}
+
 		// Movies
 		if (_nextSequentialVideoToPlay.size() > 0 && _videosPlaying.empty()) {
 			playVideo(*_nextSequentialVideoToPlay.begin());
@@ -538,7 +562,9 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 
 			// Nothing else to play
 			if (_videosPlaying.size() == 0 && _nextSequentialVideoToPlay.size() == 0){
-				if (!stack.empty()) { 
+				if (!_conversation.empty())
+					_refreshConversation = true;
+				else if (!stack.empty()) { 
 					runMenu(*stack.back());
 					drawScreen();
 				}
@@ -604,7 +630,7 @@ void HypnoEngine::runMenu(Hotspots hs) {
 
 	//if (h.stype == "SINGLE_RUN")
 	//	loadImage("int_main/mainbutt.smk", 0, 0);
-	if (h.stype == "AUTO_BUTTONS")
+	if (h.stype == "AUTO_BUTTONS" && _conversation.empty())
 		loadImage("int_main/resume.smk", 0, 0, true);
 }
 
@@ -679,6 +705,12 @@ void HypnoEngine::runQuit(const Hotspot h, Quit *a) {
     quitGame();
 }
 
+void HypnoEngine::runTalk(const Hotspot h, Talk *a) {
+	debug("adding TALK line!");
+	_conversation.push_back(a);
+	_refreshConversation = true;
+}
+
 // Shoots
 
 bool HypnoEngine::clickedShoot(Common::Point mousePos) {
@@ -691,9 +723,6 @@ bool HypnoEngine::clickedShoot(Common::Point mousePos) {
 	for (; it != _videosPlaying.end(); ++it) {
 		x = mousePos.x - it->position.x;
 		y = mousePos.y - it->position.y;
-		//debug("%d %d %d %d", x, y, it->videoDecoder->getWidth(), it->videoDecoder->getHeight());
-		//assert(it->currentFrame->w == it->videoDecoder->getWidth());
-		//assert(it->currentFrame->h == it->videoDecoder->getHeight());
 		if (it->videoDecoder && x >= 0 && y >= 0 && x < it->videoDecoder->getWidth() && y < it->videoDecoder->getHeight()) {
 			uint32 c = it->currentFrame->getPixel(x, y);
 			debug("inside %x", c); 
@@ -745,14 +774,19 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			Action *action = *itt;
 			if (typeid(*action) == typeid(Escape))
 				runEscape(selected, (Escape*) action);
-			if (typeid(*action) == typeid(Cutscene))
+			else if (typeid(*action) == typeid(Cutscene))
 				runCutscene(selected, (Cutscene*) action);
-			if (typeid(*action) == typeid(Play))
+			else if (typeid(*action) == typeid(Play))
 				runPlay(selected, (Play*) action);
-			if (typeid(*action) == typeid(WalN))
+			else if (typeid(*action) == typeid(WalN))
 				runWalN(selected, (WalN*) action);
-			if (typeid(*action) == typeid(Global))
+			else if (typeid(*action) == typeid(Global))
 				runGlobal(selected, (Global*) action);
+			else if (typeid(*action) == typeid(Talk))
+				runTalk(selected, (Talk*) action);
+			else if (typeid(*action) == typeid(Palette))
+				debug("runPalette unimplemented");
+
 		}
 
 	}
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index c0c74264a0..0b86029e4a 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -150,6 +150,7 @@ public:
 	void runAmbient(const Hotspot h, Ambient *a);
 	void runWalN(const Hotspot h, WalN *a);
 	void runGlobal(const Hotspot h, Global *a);
+	void runTalk(const Hotspot h, Talk *a);
 
 	// Screen
 	void changeScreenMode(Common::String mode);
@@ -183,6 +184,13 @@ public:
 	bool isSoundActive();
 	bool _noStopSounds;
 
+	// Conversation
+	Actions _conversation;
+	bool _refreshConversation;
+	void showConversation();
+	bool rightClickedConversation(Common::Point mousePos);
+	bool leftClickedConversation(Common::Point mousePos);
+
 	// Timers
 	bool installTimer(uint32, Common::String *);
 	void removeTimer();
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index 408ac3e428..f08a750ed7 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
 	spider/grammar_mis.o \
 	spider/lexer_arc.o \
 	spider/grammar_arc.o \
+	spider/talk.o \
 	hypno.o
 
 MODULE_DIRS += \
diff --git a/engines/hypno/spider/grammar_mis.y b/engines/hypno/spider/grammar_mis.y
index 6a5d3654af..5526120bad 100644
--- a/engines/hypno/spider/grammar_mis.y
+++ b/engines/hypno/spider/grammar_mis.y
@@ -40,6 +40,7 @@ extern int yylineno;
 
 Common::Array<uint32> smenu_idx;
 Hypno::HotspotsStack stack;
+Hypno::Talk *talk_action = nullptr;
 
 void HYPNO_MIS_xerror(const char *str) {
 	error("ERROR: %s", str);
@@ -211,7 +212,12 @@ line:    MENUTOK NAME mflag  {
 		    Hotspot *hot = &cur->back();
 			hot->actions.push_back(a);
 	  }
-	  |  TALKTOK talk { debug("TALK"); }
+	  |  TALKTOK alloctalk talk { 
+		  Hotspots *cur = stack.back();
+		  Hotspot *hot = &cur->back();
+		  hot->actions.push_back(talk_action);
+		  talk_action = nullptr;
+		  debug("TALK"); }
 	  |  ENDTOK RETTOK { 
 		  debug("explicit END");
 		  g_parsedHots = stack.back(); 
@@ -220,17 +226,58 @@ line:    MENUTOK NAME mflag  {
 		  }   		               
 	  ;
 
-talk:   INACTOK talk { debug("inactive"); }
+alloctalk: { assert(talk_action == nullptr);
+	        talk_action = new Talk();
+		    talk_action->active = true; }
+
+talk:   INACTOK talk {
+	      talk_action->active = false; 
+	      debug("inactive"); }
       | FDTOK talk { debug("inactive"); }
-	  | BACKTOK FILENAME NUM NUM gsswitch flag { debug("BACK in TALK"); }
+	  | BACKTOK FILENAME NUM NUM gsswitch flag { 
+		  talk_action->background = $2;
+		  talk_action->position = Common::Point($3, $4);
+		  debug("BACK in TALK"); }
 	  | BOXXTOK NUM NUM { debug("BOXX %d %d", $2, $3); }
-      | PG talk { debug("%s", $1); }
+      | PG talk { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "G";
+		  talk_cmd.path = $1+2;
+		  talk_action->commands.push_back(talk_cmd); 
+	      debug("%s", $1); }
       | PH talk { debug("%s", $1); }
-      | PF talk { debug("%s", $1); }
-      | PA talk { debug("%s", $1); } 
-      | PD talk { debug("%s", $1); }
-      | PP NUM NUM talk { debug("%s %d %d", $1, $2, $3); }
-      | PI NUM NUM talk { debug("%s %d %d", $1, $2, $3); }
+      | PF talk { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "F";
+		  talk_cmd.num = atoi($1+2)-1;
+		  talk_action->commands.push_back(talk_cmd); 
+		  debug("%s", $1); }
+      | PA talk { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "A";
+		  talk_cmd.num = atoi($1+2)-1;
+		  talk_action->commands.push_back(talk_cmd); 
+		  debug("|A%d", talk_cmd.num); } 
+      | PD talk { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "D";
+		  talk_cmd.num = atoi($1+2)-1;
+		  talk_action->commands.push_back(talk_cmd); 
+		  debug("%s", $1); }
+      | PP NUM NUM talk { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "P";
+		  talk_cmd.path = $1+2;
+		  talk_cmd.position = Common::Point($2, $3);
+		  talk_action->commands.push_back(talk_cmd);
+		  debug("%s %d %d", $1, $2, $3); }
+      | PI NUM NUM talk { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "I";
+		  talk_cmd.path = $1+2;
+		  talk_cmd.position = Common::Point($2, $3);
+		  talk_action->commands.push_back(talk_cmd);		  
+		  debug("%s %d %d", $1, $2, $3); }
 	  | PE { debug("|E"); }
       | /*nothing*/ { debug("nothing in talk"); }
 	  ;
diff --git a/engines/hypno/spider/talk.cpp b/engines/hypno/spider/talk.cpp
new file mode 100644
index 0000000000..75ea1ef3a7
--- /dev/null
+++ b/engines/hypno/spider/talk.cpp
@@ -0,0 +1,92 @@
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+
+namespace Hypno {
+
+void HypnoEngine::showConversation() {	
+	uint32 x = 18;
+	uint32 y = 20;
+	Graphics::Surface *speaker = decodeFrame("dialog/speaker3.smk", 0);
+	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
+		Talk *a = (Talk*) *itt;
+		if (a->active) {
+			uint32 frame;
+			Common::String path;
+			for (TalkCommands::const_iterator it = a->commands.begin(); it != a->commands.end(); ++it) {
+				if (it->command == "F") {
+					frame = it->num;
+				} else if (it->command == "G") {
+					path = it->path;
+				}
+
+			}
+			if (!path.empty()) { 
+				frame = frame;
+				debug("decoding %s frame %d", path.c_str(), frame);
+				Graphics::Surface *surf = decodeFrame("dialog/" + path, frame);
+
+				drawImage(*speaker, x, y, false);
+				drawImage(*surf, x + speaker->w, y, false);
+				a->rect = Common::Rect(x + speaker->w, y, x + surf->w, y + surf->h);
+				y = y + surf->h;
+				//delete surf;
+				//free(surf);
+			}
+		}
+	}
+
+}
+
+bool HypnoEngine::leftClickedConversation(Common::Point mousePos) {
+	Talk *t;
+	bool activeFound = false; 
+	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
+		Talk *a = (Talk*) *itt;
+		if (a->active && a->rect.contains(mousePos)) {
+			activeFound = true;
+			a->active = false;
+			for (TalkCommands::const_iterator it = a->commands.begin(); it != a->commands.end(); ++it) {
+				if (it->command == "A") {
+					debug("Adding %d", it->num);
+					t = (Talk*) _conversation[it->num];
+					t->active = true;
+					_refreshConversation = true; 
+				} else if (it->command == "D") {
+					debug("Disabling %d", it->num);
+					t = (Talk*) _conversation[it->num];
+					t->active = false;
+					_refreshConversation = true; 
+				} else if (it->command == "P") {
+					debug("Playing %s", it->path.c_str());
+					_nextSequentialVideoToPlay.push_back(MVideo(it->path, it->position, false, false, false));
+				}
+
+			}
+		}
+		if (!a->background.empty()){
+			loadImage(a->background, a->position.x, a->position.y, false);
+		}
+	}
+	if (!activeFound) {
+		_conversation.clear();
+		runMenu(*stack.back());
+		drawScreen();
+	}
+}
+
+bool HypnoEngine::rightClickedConversation(Common::Point mousePos) {
+	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
+		Talk *a = (Talk*) *itt;
+		if (a->active && a->rect.contains(mousePos)) {
+			for (TalkCommands::const_iterator it = a->commands.begin(); it != a->commands.end(); ++it) {
+				if (it->command == "I") {
+					debug("Playing %s", it->path.c_str());
+					// Not sure why position is 50, 50 since there is only one pixel
+					_nextSequentialVideoToPlay.push_back(MVideo(it->path, Common::Point(0, 0), false, false, false));
+				}
+			}
+		}
+	}
+}
+
+}
\ No newline at end of file


Commit: f101808b43ba3c0046e43467e24c308dd3765cc7
    https://github.com/scummvm/scummvm/commit/f101808b43ba3c0046e43467e24c308dd3765cc7
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved detection and refactored arcade code

Changed paths:
  A engines/hypno/spider/arcade.cpp
    engines/hypno/detection.cpp
    engines/hypno/hypno.cpp
    engines/hypno/module.mk
    engines/hypno/spider/talk.cpp


diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index a7d86ca4c8..ea21c4ace4 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -35,6 +35,7 @@ static const DebugChannelDef debugFlagList[] = {
 namespace Hypno {
 static const PlainGameDescriptor hypnoGames[] = {
 	{ "sinister-six", "Marvel Comics Spider-Man: The Sinister Six" },
+	{ "wetlands", "Wetlands" },
 	{ 0, 0 }
 };
 
@@ -45,18 +46,27 @@ static const ADGameDescription gameDescriptions[] = {
 		AD_ENTRY2s("COMBAT.EXE", "15a6b1b3819ef002438df340509b5373", 643471,
   				   "SPIDER.EXE", "15a6b1b3819ef002438df340509b5373", 603587),
 		Common::EN_USA,
-		Common::kPlatformWindows,
+		Common::kPlatformDOS,
 		ADGF_TESTING | ADGF_DEMO,
 		GUIO1(GUIO_NOMIDI)
 	},
 	{
 		"sinister-six", // US release
-		"",
+		"Not yet implemented",
 		AD_ENTRY2s("COMBAT.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 255115,
   				   "SPIDER.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 248056),
 		Common::EN_USA,
-		Common::kPlatformWindows,
-		ADGF_TESTING,
+		Common::kPlatformDOS,
+		ADGF_UNSUPPORTED | ADGF_TESTING,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"wetlands", // Wetlands Demo Disc (November 1995)
+		"Not yet implemented",
+		AD_ENTRY1s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231),
+		Common::EN_USA,
+		Common::kPlatformDOS,
+		ADGF_TESTING | ADGF_DEMO,
 		GUIO1(GUIO_NOMIDI)
 	},
 	AD_TABLE_END_MARKER
@@ -66,6 +76,7 @@ static const ADGameDescription gameDescriptions[] = {
 static const char *const directoryGlobs[] = {
 	"sixdemo",
 	"factory",
+	"wetlands",
 	0
 };
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index d1b6305f72..d162dd7730 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -127,6 +127,7 @@ void HypnoEngine::parseScene(Common::String filename) {
 }
 
 void HypnoEngine::loadLib(Common::String filename, LibData &r) {
+	debug("Loading %s", filename.c_str());
 	Common::File libfile;
     assert(libfile.open(filename));
 	uint32 i = 0;
@@ -329,118 +330,6 @@ void HypnoEngine::runLevel(Common::String name) {
 
 }
 
-void HypnoEngine::shootSpiderweb(Common::Point target) {
-	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
-	_compositeSurface->drawLine(0, 300, target.x, target.y+1, c);
-	_compositeSurface->drawLine(0, 300, target.x, target.y  , c);
-	_compositeSurface->drawLine(0, 300, target.x, target.y-1, c);
-
-	drawScreen();
-	g_system->delayMillis(2);
-}
-
-void HypnoEngine::runArcade(ArcadeShooting arc) {
-	Common::Event event;
-	Common::Point mousePos;
-	Common::List<uint32> videosToRemove;
-
-	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);	
-	Graphics::Surface *sp = decodeFrame(arc.player, 2);
-
-	changeCursor("mouse/cursor1.smk", 0);
-	playVideo(background);
-
-	while (!shouldQuit()) {
-		
-		while (g_system->getEventManager()->pollEvent(event)) {
-			mousePos = g_system->getEventManager()->getMousePos();
-			// Events
-			switch (event.type) {
-
-			case Common::EVENT_QUIT:
-			case Common::EVENT_RETURN_TO_LAUNCHER:
-				break;
-
-			case Common::EVENT_LBUTTONDOWN:
-				shootSpiderweb(mousePos);
-				clickedShoot(mousePos);
-				break;
-
-			case Common::EVENT_MOUSEMOVE:
-				break;
-
-			default:
-				break;
-			}
-		}
-
-		// Movies
-		for (Videos::iterator it = _nextParallelVideoToPlay.begin(); it != _nextParallelVideoToPlay.end(); ++it) {
-			playVideo(*it);
-			_videosPlaying.push_back(*it);
-		}
-
-		if (_nextParallelVideoToPlay.size() > 0)
-			_nextParallelVideoToPlay.clear();
-
-		if (background.videoDecoder->endOfVideo()) {
-			skipVideo(background);
-			_nextSetting = "mis/demo.mis";
-			return;
-		}
-
-
-		if (background.videoDecoder->needsUpdate())
-			updateScreen(background);
-
-		if (_shootInfos.size() > 0) {
-			ShootInfo si = _shootInfos.front();
-			if (si.timestamp <= background.videoDecoder->getCurFrame()) {
-				_shootInfos.pop_front();
-				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
-					if (it->name == si.name) {
-						_nextParallelVideoToPlay.push_back(MVideo(it->animation, it->position , true, false, false));
-						_nextParallelVideoToPlay[0].finishBeforeEnd = 24;
-					}
-				}
-			}
-		}
-
-		//drawImage(*sp, 60, 129, true);
-		uint32 i = 0;
-		videosToRemove.clear();
-
-		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
-			if (it->videoDecoder) {
-				if (it->videoDecoder-> getCurFrame() > 0 && it->videoDecoder-> getCurFrame() >= it->videoDecoder->getFrameCount() - it->finishBeforeEnd) {
-				delete it->videoDecoder;
-				it->videoDecoder = nullptr;
-				videosToRemove.push_back(i);
-
-				} else if (it->videoDecoder->needsUpdate()) {
-					updateScreen(*it);
-				}
-				i++;
-			}
-		}
-
-		if (videosToRemove.size() > 0) {
-			for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
-				debug("removing %d from %d size", *it, _videosPlaying.size()); 
-				_videosPlaying.remove_at(*it);
-			}
-		}
-
-		if (_music.empty()) {
-			_music = "c_misc/sound.lib/" + arc.sounds.front();
-			playSound(_music, 0);
-		}
-
-		drawScreen();
-		g_system->delayMillis(10);
-	}
-}
-
 void HypnoEngine::runScene(Scene scene, Videos intros) {
 	_refreshConversation = false;
 	_conversation.clear();
@@ -711,30 +600,6 @@ void HypnoEngine::runTalk(const Hotspot h, Talk *a) {
 	_refreshConversation = true;
 }
 
-// Shoots
-
-bool HypnoEngine::clickedShoot(Common::Point mousePos) {
-	bool found = false;
-	int x;
-	int y;
-
-	Videos::iterator it = _videosPlaying.begin();
-	//it++;
-	for (; it != _videosPlaying.end(); ++it) {
-		x = mousePos.x - it->position.x;
-		y = mousePos.y - it->position.y;
-		if (it->videoDecoder && x >= 0 && y >= 0 && x < it->videoDecoder->getWidth() && y < it->videoDecoder->getHeight()) {
-			uint32 c = it->currentFrame->getPixel(x, y);
-			debug("inside %x", c); 
-			if (c > 0) {
-				it->videoDecoder->rewind();
-				it->videoDecoder->start();
-			}
-		}
-	}
-	return found;
-}
-
 // Hotspots
 
 void HypnoEngine::clickedHotspot(Common::Point mousePos) {
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index f08a750ed7..71affcfbb8 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS := \
 	spider/lexer_arc.o \
 	spider/grammar_arc.o \
 	spider/talk.o \
+	spider/arcade.o \
 	hypno.o
 
 MODULE_DIRS += \
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
new file mode 100644
index 0000000000..c2d389d562
--- /dev/null
+++ b/engines/hypno/spider/arcade.cpp
@@ -0,0 +1,148 @@
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+
+#include "common/events.h"
+#include "graphics/cursorman.h"
+
+namespace Hypno {
+
+void HypnoEngine::shootSpiderweb(Common::Point target) {
+	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
+	_compositeSurface->drawLine(0, 300, target.x, target.y+1, c);
+	_compositeSurface->drawLine(0, 300, target.x, target.y  , c);
+	_compositeSurface->drawLine(0, 300, target.x, target.y-1, c);
+
+	drawScreen();
+	g_system->delayMillis(2);
+}
+
+void HypnoEngine::runArcade(ArcadeShooting arc) {
+
+	Common::Event event;
+	Common::Point mousePos;
+	Common::List<uint32> videosToRemove;
+
+	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);	
+	Graphics::Surface *sp = decodeFrame(arc.player, 2);
+
+	CursorMan.showMouse(false);
+	changeCursor("mouse/cursor1.smk", 0);
+	playVideo(background);
+
+	while (!shouldQuit()) {
+		
+		while (g_system->getEventManager()->pollEvent(event)) {
+			mousePos = g_system->getEventManager()->getMousePos();
+			// Events
+			switch (event.type) {
+
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_LBUTTONDOWN:
+				shootSpiderweb(mousePos);
+				clickedShoot(mousePos);
+				break;
+
+			case Common::EVENT_MOUSEMOVE:
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		// Movies
+		for (Videos::iterator it = _nextParallelVideoToPlay.begin(); it != _nextParallelVideoToPlay.end(); ++it) {
+			playVideo(*it);
+			_videosPlaying.push_back(*it);
+		}
+
+		if (_nextParallelVideoToPlay.size() > 0)
+			_nextParallelVideoToPlay.clear();
+
+		if (background.videoDecoder->endOfVideo()) {
+			skipVideo(background);
+			_nextSetting = "mis/demo.mis";
+			return;
+		}
+
+
+		if (background.videoDecoder->needsUpdate())
+			updateScreen(background);
+
+		if (_shootInfos.size() > 0) {
+			ShootInfo si = _shootInfos.front();
+			if (si.timestamp <= background.videoDecoder->getCurFrame()) {
+				_shootInfos.pop_front();
+				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
+					if (it->name == si.name) {
+						_nextParallelVideoToPlay.push_back(MVideo(it->animation, it->position , true, false, false));
+						_nextParallelVideoToPlay[0].finishBeforeEnd = 24;
+					}
+				}
+			}
+		}
+
+		//drawImage(*sp, 60, 129, true);
+		uint32 i = 0;
+		videosToRemove.clear();
+
+		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+			if (it->videoDecoder) {
+				if (it->videoDecoder-> getCurFrame() > 0 && it->videoDecoder-> getCurFrame() >= it->videoDecoder->getFrameCount() - it->finishBeforeEnd) {
+				delete it->videoDecoder;
+				it->videoDecoder = nullptr;
+				videosToRemove.push_back(i);
+
+				} else if (it->videoDecoder->needsUpdate()) {
+					updateScreen(*it);
+				}
+			}
+			i++;
+		}
+
+		if (videosToRemove.size() > 0) {
+			for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
+				debug("removing %d from %d size", *it, _videosPlaying.size()); 
+				_videosPlaying.remove_at(*it);
+			}
+		}
+
+		if (_music.empty()) {
+			_music = "c_misc/sound.lib/" + arc.sounds.front();
+			playSound(_music, 0);
+		}
+
+		drawScreen();
+		g_system->delayMillis(1);
+	}
+}
+
+bool HypnoEngine::clickedShoot(Common::Point mousePos) {
+	bool found = false;
+	int x;
+	int y;
+	int i = 0;
+	//it++;
+	for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+		x = mousePos.x - it->position.x;
+		y = mousePos.y - it->position.y;
+		if (it->videoDecoder && x >= 0 && y >= 0 && x < it->videoDecoder->getWidth() && y < it->videoDecoder->getHeight()) {
+			uint32 c = it->currentFrame->getPixel(x, y);
+			debug("inside %x", c); 
+			if (c > 0) {
+				//it->videoDecoder->seekToFrame(it->finishBeforeEnd+1); 
+				delete it->videoDecoder;
+				it->videoDecoder = nullptr;
+				//videosToRemove.push_back(i);
+				//it->videoDecoder->start();
+			}
+		}
+		i++;
+	}
+	return found;
+}
+
+} // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/spider/talk.cpp b/engines/hypno/spider/talk.cpp
index 75ea1ef3a7..970b5f4828 100644
--- a/engines/hypno/spider/talk.cpp
+++ b/engines/hypno/spider/talk.cpp
@@ -89,4 +89,4 @@ bool HypnoEngine::rightClickedConversation(Common::Point mousePos) {
 	}
 }
 
-}
\ No newline at end of file
+} // End of namespace Hypno
\ No newline at end of file


Commit: 9e9aa99ea9ca9ff1418ddde4f191d0a066ce2ddc
    https://github.com/scummvm/scummvm/commit/9e9aa99ea9ca9ff1418ddde4f191d0a066ce2ddc
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: video handling code refactored

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/spider/arcade.cpp


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index c2546260b0..7d55405efd 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -66,9 +66,8 @@ class MVideo {
 	bool scaled;
 	bool transparent;
 	bool loop;
-	Video::SmackerDecoder *videoDecoder;
-	const Graphics::Surface *currentFrame;
-	uint32 finishBeforeEnd;
+	Video::SmackerDecoder *decoder = nullptr;
+	const Graphics::Surface *currentFrame = nullptr;
 };
 
 typedef Common::Array<MVideo> Videos;
@@ -173,6 +172,8 @@ class Shoot {
     Common::String name;
 	Common::String animation;
 	Common::Point position;
+	MVideo *video = nullptr;
+	uint32 explosionFrame;
 };
 
 typedef Common::Array<Shoot> Shoots;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index d162dd7730..27930d2f70 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -53,9 +53,6 @@ MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent,
 	scaled = _scaled;
 	transparent = _transparent;
 	loop = _loop;
-	videoDecoder = nullptr;
-	currentFrame = nullptr;
-	finishBeforeEnd = 0;
 }
 
 const static char* levelVariables[] = {
@@ -351,7 +348,7 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 			case Common::EVENT_KEYDOWN:
 				if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
 					for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
-						if (it->videoDecoder)
+						if (it->decoder)
 							skipVideo(*it);
 					}
 					_videosPlaying.clear();
@@ -423,19 +420,19 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 		videosToRemove.clear();
 		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
 
-			if (it->videoDecoder) {
-				if (it->videoDecoder->endOfVideo()) {
+			if (it->decoder) {
+				if (it->decoder->endOfVideo()) {
 					if (it->loop) {
-						it->videoDecoder->rewind();
-						it->videoDecoder->start();
+						it->decoder->rewind();
+						it->decoder->start();
 					} else {
-						it->videoDecoder->close();
-						delete it->videoDecoder;
-						it->videoDecoder = nullptr;
+						it->decoder->close();
+						delete it->decoder;
+						it->decoder = nullptr;
 						videosToRemove.push_back(i);
 					}
 
-				} else if (it->videoDecoder->needsUpdate()) {
+				} else if (it->decoder->needsUpdate()) {
 					updateScreen(*it);
 				}
 			}
@@ -769,15 +766,15 @@ void HypnoEngine::changeScreenMode(Common::String mode) {
 }
 
 void HypnoEngine::updateScreen(MVideo &video) {
-	const Graphics::Surface *frame = video.videoDecoder->decodeNextFrame();
+	const Graphics::Surface *frame = video.decoder->decodeNextFrame();
 	video.currentFrame = frame;
 	Graphics::Surface *sframe, *cframe;
 
 	if (video.scaled) {
 		sframe = frame->scale(_screenW, _screenH);
-		cframe = sframe->convertTo(_pixelFormat, video.videoDecoder->getPalette());
+		cframe = sframe->convertTo(_pixelFormat, video.decoder->getPalette());
 	} else
-		cframe = frame->convertTo(_pixelFormat, video.videoDecoder->getPalette());
+		cframe = frame->convertTo(_pixelFormat, video.decoder->getPalette());
 	
 	if (video.transparent)
 		_compositeSurface->transBlitFrom(*cframe, video.position, _transparentColor);
@@ -812,18 +809,18 @@ void HypnoEngine::playVideo(MVideo &video) {
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
 
-	assert(video.videoDecoder == nullptr);
-	video.videoDecoder = new Video::SmackerDecoder();
+	assert(video.decoder == nullptr);
+	video.decoder = new Video::SmackerDecoder();
 
-	if (!video.videoDecoder->loadStream(file))
+	if (!video.decoder->loadStream(file))
 		error("unable to load video %s", path.c_str());
-	video.videoDecoder->start();
+	video.decoder->start();
 }
 
 void HypnoEngine::skipVideo(MVideo &video) {
-	video.videoDecoder->close();
-	delete video.videoDecoder;
-	video.videoDecoder = nullptr;	
+	video.decoder->close();
+	delete video.decoder;
+	video.decoder = nullptr;
 	//_currentMovie = "";
 }
 
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index c2d389d562..c2d0319140 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -21,6 +21,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
+	Shoots shootsInScreen;
 
 	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);	
 	Graphics::Surface *sp = decodeFrame(arc.player, 2);
@@ -53,62 +54,60 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			}
 		}
 
-		// Movies
-		for (Videos::iterator it = _nextParallelVideoToPlay.begin(); it != _nextParallelVideoToPlay.end(); ++it) {
-			playVideo(*it);
-			_videosPlaying.push_back(*it);
-		}
-
-		if (_nextParallelVideoToPlay.size() > 0)
-			_nextParallelVideoToPlay.clear();
-
-		if (background.videoDecoder->endOfVideo()) {
+		if (background.decoder->endOfVideo()) {
 			skipVideo(background);
 			_nextSetting = "mis/demo.mis";
 			return;
 		}
 
-
-		if (background.videoDecoder->needsUpdate())
-			updateScreen(background);
-
 		if (_shootInfos.size() > 0) {
 			ShootInfo si = _shootInfos.front();
-			if (si.timestamp <= background.videoDecoder->getCurFrame()) {
+			if (si.timestamp <= background.decoder->getCurFrame()) {
 				_shootInfos.pop_front();
 				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
 					if (it->name == si.name) {
-						_nextParallelVideoToPlay.push_back(MVideo(it->animation, it->position , true, false, false));
-						_nextParallelVideoToPlay[0].finishBeforeEnd = 24;
+						Shoot s = *it;
+						s.video = new MVideo(it->animation, it->position , true, false, false);
+						playVideo(*s.video);
+						s.explosionFrame = s.video->decoder->getFrameCount() - 24;
+						shootsInScreen.push_back(s);
 					}
 				}
 			}
 		}
 
+		if (background.decoder->needsUpdate())
+			updateScreen(background);
+
 		//drawImage(*sp, 60, 129, true);
 		uint32 i = 0;
 		videosToRemove.clear();
 
-		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
-			if (it->videoDecoder) {
-				if (it->videoDecoder-> getCurFrame() > 0 && it->videoDecoder-> getCurFrame() >= it->videoDecoder->getFrameCount() - it->finishBeforeEnd) {
-				delete it->videoDecoder;
-				it->videoDecoder = nullptr;
-				videosToRemove.push_back(i);
+		for (Shoots::iterator it = shootsInScreen.begin(); it != shootsInScreen.end(); ++it) {
+			if (it->video->decoder) {
+				int frame = it->video->decoder->getCurFrame(); 
+				if (frame > 0 && frame >= it->explosionFrame) {
+					skipVideo(*it->video);
+				}
+
+				//if (it->videoDecoder-> getCurFrame() > 0 && it->videoDecoder-> getCurFrame() >= it->videoDecoder->getFrameCount() - it->finishBeforeEnd) {
+				//delete it->videoDecoder;
+				//it->videoDecoder = nullptr;
+				//videosToRemove.push_back(i);
 
-				} else if (it->videoDecoder->needsUpdate()) {
-					updateScreen(*it);
+				else if (it->video->decoder->needsUpdate()) {
+					updateScreen(*it->video);
 				}
 			}
 			i++;
 		}
 
-		if (videosToRemove.size() > 0) {
-			for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
-				debug("removing %d from %d size", *it, _videosPlaying.size()); 
-				_videosPlaying.remove_at(*it);
-			}
-		}
+		//if (videosToRemove.size() > 0) {
+		//	for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
+		//		debug("removing %d from %d size", *it, _videosPlaying.size()); 
+		//		_videosPlaying.remove_at(*it);
+		//	}
+		//}
 
 		if (_music.empty()) {
 			_music = "c_misc/sound.lib/" + arc.sounds.front();
@@ -126,7 +125,7 @@ bool HypnoEngine::clickedShoot(Common::Point mousePos) {
 	int y;
 	int i = 0;
 	//it++;
-	for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+	/*for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
 		x = mousePos.x - it->position.x;
 		y = mousePos.y - it->position.y;
 		if (it->videoDecoder && x >= 0 && y >= 0 && x < it->videoDecoder->getWidth() && y < it->videoDecoder->getHeight()) {
@@ -141,7 +140,7 @@ bool HypnoEngine::clickedShoot(Common::Point mousePos) {
 			}
 		}
 		i++;
-	}
+	}*/
 	return found;
 }
 


Commit: aa6e7d4fc89d41050bb0031fef3b7f9479c43073
    https://github.com/scummvm/scummvm/commit/aa6e7d4fc89d41050bb0031fef3b7f9479c43073
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
COMMON: added SmackerDecoder::forceSeekToFrame function

Changed paths:
    video/smk_decoder.cpp
    video/smk_decoder.h


diff --git a/video/smk_decoder.cpp b/video/smk_decoder.cpp
index f909ac5819..f364ffd16b 100644
--- a/video/smk_decoder.cpp
+++ b/video/smk_decoder.cpp
@@ -428,6 +428,45 @@ bool SmackerDecoder::rewind() {
 	return true;
 }
 
+void SmackerDecoder::forceSeekToFrame(uint frame) {
+	const uint seekFrame = MAX<uint>(frame - 10, 0);
+
+	if (!isVideoLoaded())
+		return;
+
+	if (seekFrame >= getFrameCount())
+		return;
+
+	if (!rewind())
+		return;
+
+	stopAudio();
+	SmackerVideoTrack *videoTrack = (SmackerVideoTrack *)getTrack(0);
+	uint32 startPos = _fileStream->pos();
+	uint32 offset = 0;
+	for (uint32 i = 0; i < seekFrame; i++) {
+		videoTrack->increaseCurFrame();
+		// Frames with palette data contain palette entries which use
+		// the previous palette as their base. Therefore, we need to
+		// parse all palette entries up to the requested frame
+		if (_frameTypes[videoTrack->getCurFrame()] & 1) {
+			_fileStream->seek(startPos + offset, SEEK_SET);
+			videoTrack->unpackPalette(_fileStream);
+		}
+		offset += _frameSizes[i] & ~3;
+	}
+
+	if (!_fileStream->seek(startPos + offset, SEEK_SET))
+		return;
+
+	while (getCurFrame() < (int)frame) {
+		decodeNextFrame();
+	}
+
+	_lastTimeChange = videoTrack->getFrameTime(frame);
+	_startTime = g_system->getMillis() - (_lastTimeChange.msecs() / getRate()).toInt();
+}
+
 void SmackerDecoder::readNextPacket() {
 	SmackerVideoTrack *videoTrack = (SmackerVideoTrack *)getTrack(0);
 
diff --git a/video/smk_decoder.h b/video/smk_decoder.h
index 86862f5b4a..a2189fd182 100644
--- a/video/smk_decoder.h
+++ b/video/smk_decoder.h
@@ -68,7 +68,7 @@ public:
 
 	virtual bool loadStream(Common::SeekableReadStream *stream);
 	void close();
-
+	void forceSeekToFrame(uint frame);
 	bool rewind();
 
 	Common::Rational getFrameRate() const;


Commit: 2eb12c6b3e61be99e4b08ba2c39caf9d1c9b983a
    https://github.com/scummvm/scummvm/commit/2eb12c6b3e61be99e4b08ba2c39caf9d1c9b983a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved and refactored arcade code

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/grammar_arc.y


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 7d55405efd..3c09825196 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -174,6 +174,7 @@ class Shoot {
 	Common::Point position;
 	MVideo *video = nullptr;
 	uint32 explosionFrame;
+	bool destroyed = false;
 };
 
 typedef Common::Array<Shoot> Shoots;
@@ -184,7 +185,7 @@ class ShootInfo {
 	uint32 timestamp; 
 };
 
-typedef Common::List<ShootInfo> ShootInfos;
+typedef Common::List<ShootInfo> ShootSequence;
 typedef Common::List<Common::String> Sounds;
 
 class ArcadeShooting {
@@ -192,6 +193,7 @@ class ArcadeShooting {
 	Common::String background;
 	Common::String player;
 	Shoots shoots;
+	ShootSequence shootSequence;
 	Sounds sounds;
     ~ArcadeShooting() { };
 };
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 27930d2f70..0b4b905cfc 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -178,12 +178,13 @@ bool HypnoEngine::checkLevelCompleted() {
 	return _levelState["GS_LEVELCOMPLETE"];
 }
 
-void HypnoEngine::parseShootList(Common::String name, Common::String data) {
+ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String data) {
 	Common::StringTokenizer tok(data, " S,\t\n");
 
 	Common::String t;
 	Common::String n;
 	ShootInfo si;
+	ShootSequence seq;
 	while(!tok.empty()) {
 		t = tok.nextToken();
 		n = tok.nextToken();
@@ -191,9 +192,10 @@ void HypnoEngine::parseShootList(Common::String name, Common::String data) {
 			break;
 		si.name = n;
 		si.timestamp = atoi(t.c_str());
-		_shootInfos.push_back(si);
+		seq.push_back(si);
 		debug("%d -> %s", si.timestamp, si.name.c_str());
 	}
+	return seq;
 
 }
 
@@ -230,8 +232,9 @@ void HypnoEngine::loadAssets() {
 		}
 	}
 
-	parseArcadeShooting(files[0].name, arc);
-	parseShootList(files[0].name, list);
+	Common::String arclevel = files[0].name; 
+	parseArcadeShooting(arclevel, arc);
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 
 	loadLib("c_misc/fonts.lib", _fontFiles);
 	loadLib("demo/sound.lib", _soundFiles);
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 0b86029e4a..5d5e8058f3 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -89,7 +89,6 @@ public:
 	bool checkLevelCompleted();
 	void runLevel(Common::String name);
 	void runScene(Scene scene, Videos intros);
-	ShootInfos _shootInfos;
 	void runArcade(ArcadeShooting arc);
 
 	void restartGame();
@@ -98,13 +97,12 @@ public:
 	void loadAssets();
 	void parseScene(Common::String filename);
 	void parseArcadeShooting(Common::String name, Common::String data);
-	void parseShootList(Common::String name, Common::String data);
+	ShootSequence parseShootList(Common::String name, Common::String data);
 	void loadLib(Common::String filename, LibData &r);
 	Common::HashMap<Common::String, Common::String> _assets;
 
 	// User input
 	void clickedHotspot(Common::Point);
-	void shootSpiderweb(Common::Point);
 	bool clickedShoot(Common::Point);
 	bool hoverHotspot(Common::Point);
 
@@ -184,6 +182,11 @@ public:
 	bool isSoundActive();
 	bool _noStopSounds;
 
+	// Arcade
+	void shootSpiderweb(Common::Point);
+	void drawPlayer(Common::String player, uint32 idx);
+	Shoots _shoots;
+	
 	// Conversation
 	Actions _conversation;
 	bool _refreshConversation;
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index c2d0319140..1d8bd81a10 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -8,29 +8,38 @@ namespace Hypno {
 
 void HypnoEngine::shootSpiderweb(Common::Point target) {
 	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
-	_compositeSurface->drawLine(0, 300, target.x, target.y+1, c);
-	_compositeSurface->drawLine(0, 300, target.x, target.y  , c);
-	_compositeSurface->drawLine(0, 300, target.x, target.y-1, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y+1, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y  , c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y-1, c);
+	//g_system->delayMillis(2);
+}
 
-	drawScreen();
-	g_system->delayMillis(2);
+void HypnoEngine::drawPlayer(Common::String player, uint32 idx) {
+	Graphics::Surface *image = decodeFrame(player, idx);
+	drawImage(*image, 60, 129, true);
+	image->free();
+	delete image;
 }
 
 void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 	Common::Event event;
 	Common::Point mousePos;
-	Common::List<uint32> videosToRemove;
-	Shoots shootsInScreen;
+	Common::List<uint32> shootsToRemove;
+	ShootSequence shootSequence = arc.shootSequence;
+	_shoots.clear();
 
-	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);	
-	Graphics::Surface *sp = decodeFrame(arc.player, 2);
+	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);
+	uint32 playerIdx = 0;
 
 	CursorMan.showMouse(false);
 	changeCursor("mouse/cursor1.smk", 0);
 	playVideo(background);
 
 	while (!shouldQuit()) {
+
+		if (background.decoder->needsUpdate())
+			updateScreen(background);
 		
 		while (g_system->getEventManager()->pollEvent(event)) {
 			mousePos = g_system->getEventManager()->getMousePos();
@@ -47,6 +56,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
+				playerIdx = mousePos.x / 50;
 				break;
 
 			default:
@@ -60,87 +70,82 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			return;
 		}
 
-		if (_shootInfos.size() > 0) {
-			ShootInfo si = _shootInfos.front();
+		if (shootSequence.size() > 0) {
+			ShootInfo si = shootSequence.front();
 			if (si.timestamp <= background.decoder->getCurFrame()) {
-				_shootInfos.pop_front();
+				shootSequence.pop_front();
 				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
 					if (it->name == si.name) {
 						Shoot s = *it;
 						s.video = new MVideo(it->animation, it->position , true, false, false);
 						playVideo(*s.video);
-						s.explosionFrame = s.video->decoder->getFrameCount() - 24;
-						shootsInScreen.push_back(s);
+						_shoots.push_back(s);
 					}
 				}
 			}
 		}
 
-		if (background.decoder->needsUpdate())
-			updateScreen(background);
-
-		//drawImage(*sp, 60, 129, true);
 		uint32 i = 0;
-		videosToRemove.clear();
+		shootsToRemove.clear();
 
-		for (Shoots::iterator it = shootsInScreen.begin(); it != shootsInScreen.end(); ++it) {
+		for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
 			if (it->video->decoder) {
 				int frame = it->video->decoder->getCurFrame(); 
-				if (frame > 0 && frame >= it->explosionFrame) {
+				if (frame > 0 && frame >= it->explosionFrame-3 && !it->destroyed) {
 					skipVideo(*it->video);
-				}
-
-				//if (it->videoDecoder-> getCurFrame() > 0 && it->videoDecoder-> getCurFrame() >= it->videoDecoder->getFrameCount() - it->finishBeforeEnd) {
-				//delete it->videoDecoder;
-				//it->videoDecoder = nullptr;
-				//videosToRemove.push_back(i);
-
-				else if (it->video->decoder->needsUpdate()) {
+				} else if (it->video->decoder->endOfVideo()){
+					skipVideo(*it->video);
+					shootsToRemove.push_back(i);	
+				} else if (it->video->decoder->needsUpdate()) {
 					updateScreen(*it->video);
 				}
+				
 			}
 			i++;
 		}
-
-		//if (videosToRemove.size() > 0) {
-		//	for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
-		//		debug("removing %d from %d size", *it, _videosPlaying.size()); 
-		//		_videosPlaying.remove_at(*it);
-		//	}
-		//}
+		if (shootsToRemove.size() > 0) {
+			for(Common::List<uint32>::iterator it = shootsToRemove.begin(); it != shootsToRemove.end(); ++it) {
+				//debug("removing %d from %d size", *it, _shoots.size()); 
+				_shoots.remove_at(*it);
+			}
+		}
 
 		if (_music.empty()) {
 			_music = "c_misc/sound.lib/" + arc.sounds.front();
 			playSound(_music, 0);
 		}
 
+		drawPlayer(arc.player, playerIdx);
+
 		drawScreen();
-		g_system->delayMillis(1);
+		g_system->delayMillis(10);
 	}
 }
 
 bool HypnoEngine::clickedShoot(Common::Point mousePos) {
 	bool found = false;
-	int x;
-	int y;
-	int i = 0;
-	//it++;
-	/*for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+	int x = 0;
+	int y = 0;
+	int w = 0;
+	int h = 0;
+	for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
+		if (it->destroyed || !it->video->decoder)
+			continue;
 		x = mousePos.x - it->position.x;
 		y = mousePos.y - it->position.y;
-		if (it->videoDecoder && x >= 0 && y >= 0 && x < it->videoDecoder->getWidth() && y < it->videoDecoder->getHeight()) {
-			uint32 c = it->currentFrame->getPixel(x, y);
-			debug("inside %x", c); 
+		w = it->video->decoder->getWidth();
+		h = it->video->decoder->getHeight(); 
+
+		if (it->video->decoder && x >= 0 && y >= 0 && x < w && y < h) {
+			uint32 c = it->video->currentFrame->getPixel(x, y);
+			//debug("inside %x", c); 
 			if (c > 0) {
-				//it->videoDecoder->seekToFrame(it->finishBeforeEnd+1); 
-				delete it->videoDecoder;
-				it->videoDecoder = nullptr;
-				//videosToRemove.push_back(i);
-				//it->videoDecoder->start();
+				it->destroyed = true;
+				it->video->position = Common::Point(mousePos.x - w/2, mousePos.y - h/2);
+				it->video->decoder->forceSeekToFrame(it->explosionFrame+2);
 			}
 		}
-		i++;
-	}*/
+	}
 	return found;
 }
 
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index f5c13011a1..581bbab18d 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -129,7 +129,10 @@ bline: F0TOK FILENAME {
 		 debug("A0 %d %d", $2, $3); 
 		}
 	 | B0TOK NUM NUM { debug("B0 %d %d", $2, $3); }
-	 | K0TOK NUM NUM { debug("K0 %d %d", $2, $3); }
+	 | K0TOK NUM NUM { 
+		 shoot->explosionFrame = $3;
+		 debug("K0 %d %d", $2, $3);
+		}
 	 | P0TOK NUM NUM {
 		debug("P0 %d %d", $2, $3); 
 	   }


Commit: d75d4c9be07f5e7af739f7e5bbccf64d40bda44b
    https://github.com/scummvm/scummvm/commit/d75d4c9be07f5e7af739f7e5bbccf64d40bda44b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: refactored spiderman and wetlands engines

Changed paths:
  A engines/hypno/arcade.cpp
  A engines/hypno/spider/spider.cpp
  A engines/hypno/wet/arcade.cpp
  A engines/hypno/wet/wet.cpp
    engines/hypno/cursors.cpp
    engines/hypno/detection.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/metaengine.cpp
    engines/hypno/module.mk
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/grammar_arc.y
    engines/hypno/spider/lexer_arc.l


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
new file mode 100644
index 0000000000..54a1ddeb1a
--- /dev/null
+++ b/engines/hypno/arcade.cpp
@@ -0,0 +1,153 @@
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+
+#include "common/events.h"
+#include "graphics/cursorman.h"
+
+namespace Hypno {
+
+void HypnoEngine::drawPlayer(Common::String player, uint32 idx) { error("not implemented"); }
+void HypnoEngine::drawHealth(const Graphics::Font &font) { error("not implemented"); }
+
+void HypnoEngine::drawShoot(Common::Point target) {
+	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
+	_compositeSurface->drawLine(80, 155, target.x, target.y+1, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y  , c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y-1, c);
+}
+
+void HypnoEngine::runArcade(ArcadeShooting arc) {
+
+	const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont));
+	Common::Event event;
+	Common::Point mousePos;
+	Common::List<uint32> shootsToRemove;
+	ShootSequence shootSequence = arc.shootSequence;
+	_health = arc.health;
+	_maxHealth = _health;
+	_shoots.clear();
+
+	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);
+	uint32 playerIdx = 0;
+
+	defaultCursor();
+	//changeCursor("mouse/cursor1.smk", 0);
+	playVideo(background);
+
+	while (!shouldQuit()) {
+
+		if (background.decoder->needsUpdate())
+			updateScreen(background);
+		
+		while (g_system->getEventManager()->pollEvent(event)) {
+			mousePos = g_system->getEventManager()->getMousePos();
+			// Events
+			switch (event.type) {
+
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_LBUTTONDOWN:
+				drawShoot(mousePos);
+				clickedShoot(mousePos);
+				break;
+
+			case Common::EVENT_MOUSEMOVE:
+				playerIdx = mousePos.x / 50;
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		if (background.decoder->endOfVideo() || _health < 0) {
+			skipVideo(background);
+			_nextSetting = "mis/demo.mis";
+			return;
+		}
+
+		if (shootSequence.size() > 0) {
+			ShootInfo si = shootSequence.front();
+			if (si.timestamp <= background.decoder->getCurFrame()) {
+				shootSequence.pop_front();
+				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
+					if (it->name == si.name) {
+						Shoot s = *it;
+						s.video = new MVideo(it->animation, it->position , true, false, false);
+						playVideo(*s.video);
+						_shoots.push_back(s);
+					}
+				}
+			}
+		}
+
+		uint32 i = 0;
+		shootsToRemove.clear();
+
+		for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
+			if (it->video->decoder) {
+				int frame = it->video->decoder->getCurFrame(); 
+				if (frame > 0 && frame >= it->explosionFrame-3 && !it->destroyed) {
+					_health = _health - it->damage;
+					debug("healt: %d", _health);
+					skipVideo(*it->video);
+				} else if (it->video->decoder->endOfVideo()){
+					skipVideo(*it->video);
+					shootsToRemove.push_back(i);	
+				} else if (it->video->decoder->needsUpdate()) {
+					updateScreen(*it->video);
+				}
+				
+			}
+			i++;
+		}
+		if (shootsToRemove.size() > 0) {
+			for(Common::List<uint32>::iterator it = shootsToRemove.begin(); it != shootsToRemove.end(); ++it) {
+				//debug("removing %d from %d size", *it, _shoots.size()); 
+				_shoots.remove_at(*it);
+			}
+		}
+
+		if (_music.empty()) {
+			_music = "c_misc/sound.lib/" + arc.sounds.front();
+			playSound(_music, 0);
+		}
+
+		drawPlayer(arc.player, playerIdx);
+		drawHealth(font);
+
+		drawScreen();
+		g_system->delayMillis(10);
+	}
+}
+
+bool HypnoEngine::clickedShoot(Common::Point mousePos) {
+	bool found = false;
+	int x = 0;
+	int y = 0;
+	int w = 0;
+	int h = 0;
+	for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
+		if (it->destroyed || !it->video->decoder)
+			continue;
+		x = mousePos.x - it->position.x;
+		y = mousePos.y - it->position.y;
+		w = it->video->decoder->getWidth();
+		h = it->video->decoder->getHeight(); 
+
+		if (it->video->decoder && x >= 0 && y >= 0 && x < w && y < h) {
+			uint32 c = it->video->currentFrame->getPixel(x, y);
+			//debug("inside %x", c); 
+			if (c > 0) {
+				it->destroyed = true;
+				it->video->position = Common::Point(mousePos.x - w/2, mousePos.y - h/2);
+				it->video->decoder->forceSeekToFrame(it->explosionFrame+2);
+			}
+		}
+	}
+	return found;
+}
+
+} // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index f2f79b4b8a..7090c0d5b2 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -68,10 +68,17 @@ static const CursorTable cursorTable[] = {
 	{ nullptr,      nullptr, nullptr,           0,  0,  0,  0  }
 };
 
+void HypnoEngine::defaultCursor() {
+
+	const CursorTable *entry = cursorTable;
+	CursorMan.replaceCursor(entry->buf, entry->w, entry->h, entry->hotspotX, entry->hotspotY, 0);
+	CursorMan.showMouse(true);
+}
+
+
 void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
 
 	Graphics::Surface *entry = decodeFrame(cursor, n, false);
-	//debug("cursor: %d %d", entry->w, entry->h);
 	CursorMan.replaceCursor(entry->getPixels(), entry->w, entry->h, 0, 0, 0);
 	//CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
 	CursorMan.showMouse(true);
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index ea21c4ace4..391122f71b 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -62,7 +62,7 @@ static const ADGameDescription gameDescriptions[] = {
 	},
 	{
 		"wetlands", // Wetlands Demo Disc (November 1995)
-		"Not yet implemented",
+		"Demo",
 		AD_ENTRY1s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231),
 		Common::EN_USA,
 		Common::kPlatformDOS,
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 3c09825196..62b86ba281 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -172,6 +172,7 @@ class Shoot {
     Common::String name;
 	Common::String animation;
 	Common::Point position;
+	int damage;
 	MVideo *video = nullptr;
 	uint32 explosionFrame;
 	bool destroyed = false;
@@ -192,6 +193,7 @@ class ArcadeShooting {
   public:
 	Common::String background;
 	Common::String player;
+	int health;
 	Shoots shoots;
 	ShootSequence shootSequence;
 	Sounds sounds;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 0b4b905cfc..273258a2da 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -179,7 +179,7 @@ bool HypnoEngine::checkLevelCompleted() {
 }
 
 ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String data) {
-	Common::StringTokenizer tok(data, " S,\t\n");
+	Common::StringTokenizer tok(data, " ,\t");
 
 	Common::String t;
 	Common::String n;
@@ -187,9 +187,15 @@ ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String da
 	ShootSequence seq;
 	while(!tok.empty()) {
 		t = tok.nextToken();
+		if (t[0] == '\n')
+			continue;
 		n = tok.nextToken();
+		//debug("t: %s, n: %s", t.c_str(), n.c_str());
 		if (t == "Z")
 			break;
+		
+		Common::replace(n, "\nS", "");
+		Common::replace(n, "\nZ\n", "");
 		si.name = n;
 		si.timestamp = atoi(t.c_str());
 		seq.push_back(si);
@@ -209,67 +215,7 @@ void HypnoEngine::parseArcadeShooting(Common::String name, Common::String data)
 	g_parsedArc.shoots.clear();
 }
 
-void HypnoEngine::loadAssets() {
-	LibData files; 
-	loadLib("c_misc/missions.lib", files);
-	uint32 i = 0;
-	uint32 j = 0;
-
-	Common::String arc;
-	Common::String list;
-
-	debug("Splitting file: %s",files[0].name.c_str());
-	for (i = 0; i < files[0].data.size(); i++) {
-		arc += files[0].data[i];
-		if (files[0].data[i] == 'X') {
-			i++;
-			for (j = i; j < files[0].data.size(); j++) {
-				if (files[0].data[j] == 'Y')
-					break;
-				list += files[0].data[j];
-			}
-			break; // No need to keep parsing, no more files are used in the demo
-		}
-	}
-
-	Common::String arclevel = files[0].name; 
-	parseArcadeShooting(arclevel, arc);
-	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-
-	loadLib("c_misc/fonts.lib", _fontFiles);
-	loadLib("demo/sound.lib", _soundFiles);
-	loadLib("c_misc/sound.lib", _soundFiles);
-
-	// quit level
-	Hotspot q;
-	q.type = MakeMenu;
-	Action *a = new Quit();
-	q.actions.push_back(a);
-	Level level;
-	Hotspots quit;
-	quit.push_back(q);
-	level.scene.hots = quit;  
-	_levels["mis/quit.mis"] = level;
-
-	// Read assets from mis files
-	parseScene("mis/demo.mis");
-	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine1.smk", Common::Point(0, 0), false, true, false));
-	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine2.smk", Common::Point(0, 0), false, true, false));
-	_levels["mis/demo.mis"].scene.hots[1].setting = "c_misc/missions.lib/c1.mi_";
-	_levels["mis/demo.mis"].scene.hots[2].setting = "mis/alley.mis";
-
-	_levels["mis/demo.mis"].scene.hots[4].setting = "mis/shoctalk.mis";
-	_levels["mis/demo.mis"].scene.hots[5].setting = "mis/order.mis";
-	_levels["mis/demo.mis"].scene.sound = "demo/sound.lib/menu_mus.raw";
-
-	parseScene("mis/order.mis");
-	_levels["mis/order.mis"].scene.hots[1].setting = "mis/quit.mis";
-	parseScene("mis/alley.mis");
-	_levels["mis/alley.mis"].intros.push_back(MVideo("demo/aleyc01s.smk", Common::Point(0, 0), false, true, false));
-	_levels["mis/alley.mis"].scene.sound = "demo/sound.lib/alleymus.raw";
-
-	parseScene("mis/shoctalk.mis");
-}
+void HypnoEngine::loadAssets() { error("not implemented"); }
 
 Common::Error HypnoEngine::run() {
 	_language = Common::parseLanguage(ConfMan.get("language"));
@@ -299,7 +245,6 @@ Common::Error HypnoEngine::run() {
 		_nextSetting = getGoIntroSetting();
 	}*/
 	loadAssets();
-	_nextSetting = "mis/demo.mis";
 	while (!shouldQuit()) {
 		resetLevelState();
 		_videosPlaying.clear();
@@ -320,17 +265,20 @@ void HypnoEngine::runLevel(Common::String name) {
 	stopSound();
 	_music = "";
 
+	for (Videos::iterator it = _levels[name].intros.begin(); it != _levels[name].intros.end(); ++it)
+		runIntro(*it);
+
 	if (_levels[name].scene.hots.size() == 0) {
 		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
 	} else {
 		changeScreenMode("scene");
-		runScene(_levels[name].scene, _levels[name].intros);
+		runScene(_levels[name].scene);
 	}
 
 }
 
-void HypnoEngine::runScene(Scene scene, Videos intros) {
+void HypnoEngine::runScene(Scene scene) {
 	_refreshConversation = false;
 	_conversation.clear();
 	Common::Event event;
@@ -338,8 +286,7 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 	Common::List<uint32> videosToRemove;
 	
 	stack.clear();
-	_nextHotsToAdd = &scene.hots;
-	_nextSequentialVideoToPlay = intros;	
+	_nextHotsToAdd = &scene.hots;	
 	changeCursor("mouse/cursor1.smk", 0);
 
 	while (!shouldQuit() && _nextSetting.empty()) {
@@ -495,6 +442,41 @@ void HypnoEngine::runScene(Scene scene, Videos intros) {
 	}
 }
 
+void HypnoEngine::runIntro(MVideo &video) {
+	Common::Event event;
+	stopSound();
+	playVideo(video);
+
+	while (!shouldQuit() && video.decoder) {
+			while (g_system->getEventManager()->pollEvent(event)) {
+			// Events
+			switch (event.type) {
+			case Common::EVENT_KEYDOWN:
+				if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+					skipVideo(video);
+				}
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		if (video.decoder) {
+			if (video.decoder->endOfVideo()) {
+				skipVideo(video);
+			} else if (video.decoder->needsUpdate()) {
+				updateScreen(video);
+				drawScreen();
+			}
+		}
+
+		g_system->updateScreen();
+		g_system->delayMillis(10);
+	}
+}
+
+
 //Actions
 
 void HypnoEngine::runMenu(Hotspots hs) {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 5d5e8058f3..89ccbb5f87 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -30,7 +30,8 @@
 #include "common/serializer.h"
 #include "engines/engine.h"
 #include "graphics/managed_surface.h"
-
+#include "graphics/font.h"
+#include "graphics/fontman.h"
 
 #include "hypno/grammar.h"
 
@@ -64,7 +65,6 @@ typedef Common::Array<FileData> LibData;
 class HypnoEngine : public Engine {
 private:
 	Common::RandomSource *_rnd;
-	Graphics::PixelFormat _pixelFormat;
 	Image::ImageDecoder *_image;
 	int _screenW, _screenH;
 
@@ -88,13 +88,13 @@ public:
 	void resetLevelState();
 	bool checkLevelCompleted();
 	void runLevel(Common::String name);
-	void runScene(Scene scene, Videos intros);
+	void runScene(Scene scene);
 	void runArcade(ArcadeShooting arc);
 
 	void restartGame();
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
-	void loadAssets();
+	virtual void loadAssets();
 	void parseScene(Common::String filename);
 	void parseArcadeShooting(Common::String name, Common::String data);
 	ShootSequence parseShootList(Common::String name, Common::String data);
@@ -133,10 +133,11 @@ public:
 	void drawImage(Graphics::Surface &image, int x, int y, bool transparent);
 
 	// Cursors
+	void defaultCursor();
 	void changeCursor(const Common::String &, uint32);
 
 	// Actions
-	void runIntro();
+	void runIntro(MVideo &video);
 	void runMenu(Hotspots hs);
     void runBackground(const Hotspot h, Background *a);
 	void runOverlay(const Hotspot h, Overlay *a);
@@ -151,6 +152,7 @@ public:
 	void runTalk(const Hotspot h, Talk *a);
 
 	// Screen
+	Graphics::PixelFormat _pixelFormat;
 	void changeScreenMode(Common::String mode);
 	Graphics::ManagedSurface *_compositeSurface;
 	uint32 _transparentColor;
@@ -183,10 +185,13 @@ public:
 	bool _noStopSounds;
 
 	// Arcade
-	void shootSpiderweb(Common::Point);
-	void drawPlayer(Common::String player, uint32 idx);
+	void drawShoot(Common::Point);
+	virtual void drawPlayer(Common::String player, uint32 idx);
+	virtual void drawHealth(const Graphics::Font &font);
+	int _health;
+	int _maxHealth;
 	Shoots _shoots;
-	
+
 	// Conversation
 	Actions _conversation;
 	bool _refreshConversation;
@@ -199,6 +204,27 @@ public:
 	void removeTimer();
 };
 
+class WetEngine : public HypnoEngine {
+public:
+	WetEngine(OSystem *syst, const ADGameDescription *gd);
+
+	void loadAssets() override;
+	
+	void drawPlayer(Common::String player, uint32 idx) override;
+	void drawHealth(const Graphics::Font &font) override;
+
+};
+
+class SpiderEngine : public HypnoEngine {
+public:
+	SpiderEngine(OSystem *syst, const ADGameDescription *gd);
+
+	void loadAssets() override;
+	
+	void drawPlayer(Common::String player, uint32 idx) override;
+	void drawHealth(const Graphics::Font &font) override;
+};
+
 } // End of namespace Hypno
 
 #endif
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index bad8738f9a..c4e4b9a495 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -35,9 +35,17 @@ public:
 	//void getSavegameThumbnail(Graphics::Surface &thumb) override;
 };
 
-Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
-	*engine = new Hypno::HypnoEngine(syst, gd);
-	return Common::kNoError;
+Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+	debug("gameid: %s", desc->gameId);
+    if (Common::String(desc->gameId) == "wetlands") {
+		*engine = (Engine*) new Hypno::WetEngine(syst, desc);
+	} else if (Common::String(desc->gameId) == "sinister-six") {
+		*engine = (Engine*) new Hypno::SpiderEngine(syst, desc);
+	} 
+	else 
+		return Common::kUnsupportedGameidError;
+
+    return Common::kNoError;
 }
 
 namespace Hypno {
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index 71affcfbb8..4619648cf4 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -3,12 +3,16 @@ MODULE := engines/hypno
 MODULE_OBJS := \
 	cursors.o \
 	metaengine.o \
+	arcade.o \
+	spider/spider.o \
 	spider/lexer_mis.o \
 	spider/grammar_mis.o \
 	spider/lexer_arc.o \
 	spider/grammar_arc.o \
 	spider/talk.o \
 	spider/arcade.o \
+	wet/wet.o \
+	wet/arcade.o \
 	hypno.o
 
 MODULE_DIRS += \
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 1d8bd81a10..70feaf9bde 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -6,147 +6,32 @@
 
 namespace Hypno {
 
-void HypnoEngine::shootSpiderweb(Common::Point target) {
-	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
-	_compositeSurface->drawLine(80, 155, target.x, target.y+1, c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y  , c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y-1, c);
-	//g_system->delayMillis(2);
-}
-
-void HypnoEngine::drawPlayer(Common::String player, uint32 idx) {
+void SpiderEngine::drawPlayer(Common::String player, uint32 idx) {
 	Graphics::Surface *image = decodeFrame(player, idx);
 	drawImage(*image, 60, 129, true);
 	image->free();
 	delete image;
 }
 
-void HypnoEngine::runArcade(ArcadeShooting arc) {
-
-	Common::Event event;
-	Common::Point mousePos;
-	Common::List<uint32> shootsToRemove;
-	ShootSequence shootSequence = arc.shootSequence;
-	_shoots.clear();
-
-	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);
-	uint32 playerIdx = 0;
-
-	CursorMan.showMouse(false);
-	changeCursor("mouse/cursor1.smk", 0);
-	playVideo(background);
-
-	while (!shouldQuit()) {
-
-		if (background.decoder->needsUpdate())
-			updateScreen(background);
-		
-		while (g_system->getEventManager()->pollEvent(event)) {
-			mousePos = g_system->getEventManager()->getMousePos();
-			// Events
-			switch (event.type) {
-
-			case Common::EVENT_QUIT:
-			case Common::EVENT_RETURN_TO_LAUNCHER:
-				break;
+void SpiderEngine::drawHealth(const Graphics::Font &font) {
+	Common::Rect r;
+	uint32 c;
+	int d = (22 * (_maxHealth - _health) / _maxHealth);
 
-			case Common::EVENT_LBUTTONDOWN:
-				shootSpiderweb(mousePos);
-				clickedShoot(mousePos);
-				break;
+	r = Common::Rect(256, 152 + d, 272, 174);
+	if (d >= 11)
+		c = _pixelFormat.RGBToColor(255, 0, 0);
+	else 
+		c = _pixelFormat.RGBToColor(32, 208, 32);
 
-			case Common::EVENT_MOUSEMOVE:
-				playerIdx = mousePos.x / 50;
-				break;
+	_compositeSurface->fillRect(r, c);
 
-			default:
-				break;
-			}
-		}
+	r = Common::Rect(256, 152, 272, 174);
+	c = _pixelFormat.RGBToColor(0, 0, 255);
+	_compositeSurface->frameRect(r, c);
 
-		if (background.decoder->endOfVideo()) {
-			skipVideo(background);
-			_nextSetting = "mis/demo.mis";
-			return;
-		}
-
-		if (shootSequence.size() > 0) {
-			ShootInfo si = shootSequence.front();
-			if (si.timestamp <= background.decoder->getCurFrame()) {
-				shootSequence.pop_front();
-				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
-					if (it->name == si.name) {
-						Shoot s = *it;
-						s.video = new MVideo(it->animation, it->position , true, false, false);
-						playVideo(*s.video);
-						_shoots.push_back(s);
-					}
-				}
-			}
-		}
-
-		uint32 i = 0;
-		shootsToRemove.clear();
-
-		for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
-			if (it->video->decoder) {
-				int frame = it->video->decoder->getCurFrame(); 
-				if (frame > 0 && frame >= it->explosionFrame-3 && !it->destroyed) {
-					skipVideo(*it->video);
-				} else if (it->video->decoder->endOfVideo()){
-					skipVideo(*it->video);
-					shootsToRemove.push_back(i);	
-				} else if (it->video->decoder->needsUpdate()) {
-					updateScreen(*it->video);
-				}
-				
-			}
-			i++;
-		}
-		if (shootsToRemove.size() > 0) {
-			for(Common::List<uint32>::iterator it = shootsToRemove.begin(); it != shootsToRemove.end(); ++it) {
-				//debug("removing %d from %d size", *it, _shoots.size()); 
-				_shoots.remove_at(*it);
-			}
-		}
-
-		if (_music.empty()) {
-			_music = "c_misc/sound.lib/" + arc.sounds.front();
-			playSound(_music, 0);
-		}
-
-		drawPlayer(arc.player, playerIdx);
-
-		drawScreen();
-		g_system->delayMillis(10);
-	}
+	font.drawString(_compositeSurface, "ENERGY", 248, 180, 38, c);
 }
 
-bool HypnoEngine::clickedShoot(Common::Point mousePos) {
-	bool found = false;
-	int x = 0;
-	int y = 0;
-	int w = 0;
-	int h = 0;
-	for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
-		if (it->destroyed || !it->video->decoder)
-			continue;
-		x = mousePos.x - it->position.x;
-		y = mousePos.y - it->position.y;
-		w = it->video->decoder->getWidth();
-		h = it->video->decoder->getHeight(); 
-
-		if (it->video->decoder && x >= 0 && y >= 0 && x < w && y < h) {
-			uint32 c = it->video->currentFrame->getPixel(x, y);
-			//debug("inside %x", c); 
-			if (c > 0) {
-				it->destroyed = true;
-				it->video->position = Common::Point(mousePos.x - w/2, mousePos.y - h/2);
-				it->video->decoder->forceSeekToFrame(it->explosionFrame+2);
-			}
-		}
-	}
-	return found;
-}
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index 581bbab18d..34241c9479 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -60,11 +60,11 @@ using namespace Hypno;
 %token<s> NAME FILENAME
 %token<i> NUM
 // header
-%token YBTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
-%token PTOK ATOK VTOK OTOK NTOK RTOK ITOK SNTOK ZTOK
+%token YBTOK YMTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
+%token PTOK FTOK TTOK ATOK VTOK OTOK NTOK RTOK ITOK SNTOK ZTOK
 
 // body
-%token F0TOK A0TOK B0TOK K0TOK P0TOK WTOK
+%token FNTOK NONETOK A0TOK BNTOK K0TOK P0TOK WTOK
 
 // end
 %token XTOK
@@ -74,8 +74,9 @@ using namespace Hypno;
 
 %%
 
-start: YBTOK header body
-       ;
+start:  YBTOK header body
+      | YMTOK header body
+      ;
 
 
 header:  hline RETTOK header
@@ -84,11 +85,15 @@ header:  hline RETTOK header
 	   ; 
 
 hline:  CTOK NUM  { debug("C %d", $2); }
+      | FTOK NUM { debug("F %d", $2); }
       | DTOK NUM  { debug("D %d", $2); }
       | PTOK NUM NUM { debug("P %d %d", $2, $3); }
       | ATOK NUM NUM { debug("A %d %d", $2, $3); }
       | VTOK NUM NUM { debug("V %d %d", $2, $3); }
       | OTOK NUM NUM { debug("O %d %d", $2, $3); }
+	  | TTOK FILENAME NUM { 
+		  debug("T %s %d", $2, $3); 
+		}
 	  | NTOK FILENAME  { 
 		  g_parsedArc.background = $2; 
 		  debug("N %s", $2); 
@@ -99,12 +104,17 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 		  debug("I %s", $2); 
 		}
 	  | QTOK NUM NUM { debug("Q %d %d", $2, $3); }
+	  | BNTOK FILENAME {
+		  debug("BN %s", $2); 
+		}
 	  | SNTOK FILENAME enc {
 		  g_parsedArc.sounds.push_back($2); 
 		  debug("SN %s", $2); 
 		}
 	  | HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
-	  | HTOK CB3TOK NUM NUM { debug("H %d %d", $3, $4); }
+	  | HTOK CB3TOK NUM NUM { 
+		  g_parsedArc.health = $3;
+		  debug("H %d %d", $3, $4); }
 	  | ZTOK RETTOK { debug("Z"); }
 	  ;
 
@@ -115,10 +125,20 @@ enc: ENCTOK
 body: bline RETTOK body
     | bline RETTOK XTOK
 
-bline: F0TOK FILENAME { 
+bline: FNTOK FILENAME { 
+		shoot = new Shoot();
+		shoot->animation = $2;
+		debug("FN %s", $2); 
+	 	}
+	 | FNTOK NONETOK { 
+		shoot = new Shoot();
+		shoot->animation = "NONE";
+		debug("FN NONE"); 
+	 	}
+	 | FTOK FILENAME { 
 		shoot = new Shoot();
 		shoot->animation = $2;
-		debug("F0 %s", $2); 
+		debug("FN %s", $2); 
 	 	}
      | ITOK  NAME  { 
 		 shoot->name = $2;
@@ -128,7 +148,8 @@ bline: F0TOK FILENAME {
 		 shoot->position = Common::Point($2, $3);
 		 debug("A0 %d %d", $2, $3); 
 		}
-	 | B0TOK NUM NUM { debug("B0 %d %d", $2, $3); }
+	 | RTOK NUM NUM  { debug("R %d %d", $2, $3); }
+	 | BNTOK NUM NUM { debug("BN %d %d", $2, $3); }
 	 | K0TOK NUM NUM { 
 		 shoot->explosionFrame = $3;
 		 debug("K0 %d %d", $2, $3);
@@ -142,8 +163,12 @@ bline: F0TOK FILENAME {
 	 | CTOK NUM  { debug("C %d", $2); } 
 	 | HTOK NUM  { debug("H %d", $2); }
 	 | WTOK NUM  { debug("W %d", $2); }
-	 | DTOK NUM  { debug("D %d", $2); }
+	 | DTOK NUM  { 
+		 shoot->damage = $2;
+		 debug("D %d", $2); 
+		}
 	 | SNTOK FILENAME enc { debug("SN %s", $2); }
+	 | NTOK { debug("N"); }
 	 | ZTOK {
 		g_parsedArc.shoots.push_back(*shoot); 
 		//delete shoot; 
diff --git a/engines/hypno/spider/lexer_arc.l b/engines/hypno/spider/lexer_arc.l
index 9d4cdfc953..87a1472153 100644
--- a/engines/hypno/spider/lexer_arc.l
+++ b/engines/hypno/spider/lexer_arc.l
@@ -39,6 +39,7 @@
 %}
 
 %%
+NONE						return NONETOK;
 C				    		return CTOK;
 D                           return DTOK;
 HE                          return HETOK;
@@ -54,13 +55,16 @@ Q							return QTOK;
 Z							return ZTOK;
 W							return WTOK;
 X 							return XTOK;
-F0							return F0TOK;
+T							return TTOK;
+F[0-9]						return FNTOK;
+F							return FTOK;
 S[0-9]						return SNTOK;
 A0							return A0TOK;
-B0							return B0TOK;
+B[0-9]						return BNTOK;
 K0							return K0TOK;
 P0							return P0TOK;
 YB							return YBTOK;
+YM							return YMTOK;
 22[k|K]						return ENCTOK;
 [A-Za-z_][A-Za-z_0-9]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
 [A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
new file mode 100644
index 0000000000..690016c55d
--- /dev/null
+++ b/engines/hypno/spider/spider.cpp
@@ -0,0 +1,72 @@
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+
+namespace Hypno {
+
+SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
+
+void SpiderEngine::loadAssets() {
+	LibData files; 
+	loadLib("c_misc/missions.lib", files);
+	uint32 i = 0;
+	uint32 j = 0;
+
+	Common::String arc;
+	Common::String list;
+
+	debug("Splitting file: %s",files[0].name.c_str());
+	for (i = 0; i < files[0].data.size(); i++) {
+		arc += files[0].data[i];
+		if (files[0].data[i] == 'X') {
+			i++;
+			for (j = i; j < files[0].data.size(); j++) {
+				if (files[0].data[j] == 'Y')
+					break;
+				list += files[0].data[j];
+			}
+			break; // No need to keep parsing, no more files are used in the demo
+		}
+	}
+
+	Common::String arclevel = files[0].name; 
+	parseArcadeShooting(arclevel, arc);
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+
+	loadLib("c_misc/fonts.lib", _fontFiles);
+	loadLib("c_misc/sound.lib", _soundFiles);
+	loadLib("demo/sound.lib", _soundFiles);
+
+	// quit level
+	Hotspot q;
+	q.type = MakeMenu;
+	Action *a = new Quit();
+	q.actions.push_back(a);
+	Level level;
+	Hotspots quit;
+	quit.push_back(q);
+	level.scene.hots = quit;  
+	_levels["mis/quit.mis"] = level;
+
+	// Read assets from mis files
+	parseScene("mis/demo.mis");
+	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine1.smk", Common::Point(0, 0), false, true, false));
+	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine2.smk", Common::Point(0, 0), false, true, false));
+	_levels["mis/demo.mis"].scene.hots[1].setting = "c_misc/missions.lib/c1.mi_";
+	_levels["mis/demo.mis"].scene.hots[2].setting = "mis/alley.mis";
+
+	_levels["mis/demo.mis"].scene.hots[4].setting = "mis/shoctalk.mis";
+	_levels["mis/demo.mis"].scene.hots[5].setting = "mis/order.mis";
+	_levels["mis/demo.mis"].scene.sound = "demo/sound.lib/menu_mus.raw";
+
+	parseScene("mis/order.mis");
+	_levels["mis/order.mis"].scene.hots[1].setting = "mis/quit.mis";
+	parseScene("mis/alley.mis");
+	_levels["mis/alley.mis"].intros.push_back(MVideo("demo/aleyc01s.smk", Common::Point(0, 0), false, true, false));
+	_levels["mis/alley.mis"].scene.sound = "demo/sound.lib/alleymus.raw";
+
+	parseScene("mis/shoctalk.mis");
+	_nextSetting = "mis/demo.mis";
+}
+
+
+} // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
new file mode 100644
index 0000000000..27b6b6117d
--- /dev/null
+++ b/engines/hypno/wet/arcade.cpp
@@ -0,0 +1,40 @@
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+
+#include "common/events.h"
+#include "graphics/cursorman.h"
+
+namespace Hypno {
+
+void WetEngine::drawPlayer(Common::String player, uint32 idx) {
+	_transparentColor = _pixelFormat.RGBToColor(4, 4, 0);
+	Graphics::Surface *image = decodeFrame(player, idx);
+	drawImage(*image, 0, 130, true);
+	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
+	image->free();
+	delete image;
+}
+
+void WetEngine::drawHealth(const Graphics::Font &font) {
+	/*
+	Common::Rect r;
+	uint32 c;
+	int d = (22 * (_maxHealth - _health) / _maxHealth);
+
+	r = Common::Rect(256, 152 + d, 272, 174);
+	if (d >= 11)
+		c = _pixelFormat.RGBToColor(255, 0, 0);
+	else 
+		c = _pixelFormat.RGBToColor(32, 208, 32);
+
+	_compositeSurface->fillRect(r, c);
+
+	r = Common::Rect(256, 152, 272, 174);
+	c = _pixelFormat.RGBToColor(0, 0, 255);
+	_compositeSurface->frameRect(r, c);
+
+	font.drawString(_compositeSurface, "ENERGY", 248, 180, 38, c);
+	*/
+}
+
+} // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
new file mode 100644
index 0000000000..bf03495c8b
--- /dev/null
+++ b/engines/hypno/wet/wet.cpp
@@ -0,0 +1,40 @@
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+
+namespace Hypno {
+
+WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
+
+void WetEngine::loadAssets() {
+	LibData files; 
+	loadLib("c_misc/missions.lib", files);
+	uint32 i = 0;
+	uint32 j = 0;
+
+	Common::String arc;
+	Common::String list;
+
+	debug("Splitting file: %s",files[0].name.c_str());
+	for (i = 0; i < files[0].data.size(); i++) {
+		arc += files[0].data[i];
+		if (files[0].data[i] == 'X') {
+			i++;
+			for (j = i; j < files[0].data.size(); j++) {
+				if (files[0].data[j] == 'Y')
+					break;
+				list += files[0].data[j];
+			}
+			break; // No need to keep parsing, no more files are used in the demo
+		}
+	}
+
+	Common::String arclevel = files[0].name; 
+	parseArcadeShooting(arclevel, arc);
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+
+	loadLib("c_misc/fonts.lib", _fontFiles);
+	loadLib("c_misc/sound.lib", _soundFiles);
+	_nextSetting = "c_misc/missions.lib/c31.mi_";
+}
+
+} // End of namespace Hypno


Commit: 1f61e81e83d40e938967d7d92a4d0eb543fc602d
    https://github.com/scummvm/scummvm/commit/1f61e81e83d40e938967d7d92a4d0eb543fc602d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved detection of wetlands releases

Changed paths:
    engines/hypno/detection.cpp


diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 391122f71b..fc2b709191 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -63,12 +63,23 @@ static const ADGameDescription gameDescriptions[] = {
 	{
 		"wetlands", // Wetlands Demo Disc (November 1995)
 		"Demo",
-		AD_ENTRY1s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231),
+		AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231,
+  				   "wetdemo.exe", "15a6b1b3819ef002438df340509b5373", 458319),
 		Common::EN_USA,
 		Common::kPlatformDOS,
 		ADGF_TESTING | ADGF_DEMO,
 		GUIO1(GUIO_NOMIDI)
 	},
+	{
+		"wetlands", // Wetlands (US)
+		"",
+		AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 647447,
+  				   "install.exe", "15a6b1b3819ef002438df340509b5373", 477839),
+		Common::EN_USA,
+		Common::kPlatformDOS,
+		ADGF_TESTING,
+		GUIO1(GUIO_NOMIDI)
+	},
 	AD_TABLE_END_MARKER
 };
 } // End of namespace Hypno
@@ -77,13 +88,14 @@ static const char *const directoryGlobs[] = {
 	"sixdemo",
 	"factory",
 	"wetlands",
+	"movie",
 	0
 };
 
 class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
 public:
 	HypnoMetaEngineDetection() : AdvancedMetaEngineDetection(Hypno::gameDescriptions, sizeof(ADGameDescription), Hypno::hypnoGames) {
-		_maxScanDepth = 2;
+		_maxScanDepth = 10;
 		_directoryGlobs = directoryGlobs;
 	}
 


Commit: abd5a028db621d23ca9feed983ca0f9e5b96057f
    https://github.com/scummvm/scummvm/commit/abd5a028db621d23ca9feed983ca0f9e5b96057f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: refactored engines to better parse arcade sequences

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/cursors.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/grammar_arc.y
    engines/hypno/spider/lexer_arc.l
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 54a1ddeb1a..61049482fc 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -64,7 +64,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 		if (background.decoder->endOfVideo() || _health < 0) {
 			skipVideo(background);
-			_nextSetting = "mis/demo.mis";
+			_nextLevel = "mis/demo.mis";
 			return;
 		}
 
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index 7090c0d5b2..e050180b3d 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -68,6 +68,11 @@ static const CursorTable cursorTable[] = {
 	{ nullptr,      nullptr, nullptr,           0,  0,  0,  0  }
 };
 
+
+void HypnoEngine::disableCursor() {
+	CursorMan.showMouse(false);
+}
+
 void HypnoEngine::defaultCursor() {
 
 	const CursorTable *entry = cursorTable;
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 62b86ba281..7953fbbdb7 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -50,12 +50,6 @@ typedef Common::Array<Action*> Actions;
 class Hotspot;
 typedef Common::Array<Hotspot> Hotspots;
 
-class Scene {
-  public:
-	Hotspots hots;
-	Common::String sound;
-};
-
 typedef Common::Array<Hotspots *> HotspotsStack;
 
 class MVideo {
@@ -189,21 +183,36 @@ class ShootInfo {
 typedef Common::List<ShootInfo> ShootSequence;
 typedef Common::List<Common::String> Sounds;
 
+class Transition {
+  public:
+	Common::String level;
+	Videos intros;
+};
+
+class Scene {
+  public:
+    Common::String intro;
+    Common::String prefix;
+	Hotspots hots;
+	Common::String sound;
+};
+
 class ArcadeShooting {
   public:
+    Common::String intro;
+	Common::String prefix;
 	Common::String background;
 	Common::String player;
 	int health;
 	Shoots shoots;
 	ShootSequence shootSequence;
 	Sounds sounds;
-    ~ArcadeShooting() { };
 };
 
 class Level {
   public:
+    Transition trans;
 	Scene scene;
-	Videos intros;
 	ArcadeShooting arcade;
 };
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 273258a2da..ae1d2791a2 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -105,9 +105,11 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
 }
 
-void HypnoEngine::parseScene(Common::String filename) {
+void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	debug("Parsing %s", filename.c_str());
     filename = convertPath(filename);
+	if (!prefix.empty())
+		filename = prefix + "/" + filename; 
 	Common::File *test = new Common::File();
 	assert(isDemo());
     assert(test->open(filename.c_str()));
@@ -118,6 +120,7 @@ void HypnoEngine::parseScene(Common::String filename) {
 	buf[fileSize] = '\0';
 	parse_mis(buf);
 	Level level;
+	level.scene.prefix = prefix;
 	level.scene.hots = *g_parsedHots; 
 	_levels[filename] = level;
 	debug("Loaded hots size: %d", g_parsedHots->size());
@@ -205,10 +208,11 @@ ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String da
 
 }
 
-void HypnoEngine::parseArcadeShooting(Common::String name, Common::String data) {
+void HypnoEngine::parseArcadeShooting(Common::String prefix, Common::String name, Common::String data) {
 	parse_arc(data.c_str());
 	Level level;
 	level.arcade = g_parsedArc;  
+	level.arcade.prefix = prefix;
 	_levels[name] = level;
 	g_parsedArc.background.clear();
 	g_parsedArc.player.clear();
@@ -245,16 +249,17 @@ Common::Error HypnoEngine::run() {
 		_nextSetting = getGoIntroSetting();
 	}*/
 	loadAssets();
+	_nextLevel = "<start>";
 	while (!shouldQuit()) {
+		_prefixDir = "";
 		resetLevelState();
 		_videosPlaying.clear();
-		if (!_nextSetting.empty()) {
-			debug("Executing setting %s", _nextSetting.c_str());
-			_currentSetting = _nextSetting;
-			_nextSetting = "";
-			runLevel(_currentSetting);
+		if (!_nextLevel.empty()) {
+			debug("Executing level %s", _nextLevel.c_str());
+			_currentLevel = _nextLevel;
+			_nextLevel = "";
+			runLevel(_currentLevel);
 		}
-		_levels["mis/demo.mis"].intros.clear();
 			
 	}
 	return Common::kNoError;
@@ -265,14 +270,28 @@ void HypnoEngine::runLevel(Common::String name) {
 	stopSound();
 	_music = "";
 
-	for (Videos::iterator it = _levels[name].intros.begin(); it != _levels[name].intros.end(); ++it)
-		runIntro(*it);
+	disableCursor();
 
-	if (_levels[name].scene.hots.size() == 0) {
+	if (!_levels[name].trans.level.empty()) {
+		_nextLevel = _levels[name].trans.level;
+		for (Videos::iterator it = _levels[name].trans.intros.begin(); it != _levels[name].trans.intros.end(); ++it)
+			runIntro(*it);
+
+	} else if (!_levels[name].arcade.background.empty()) {
+		_prefixDir = _levels[name].arcade.prefix;
+		if (!_levels[name].arcade.intro.empty()) {
+			MVideo v(_levels[name].arcade.intro, Common::Point(0,0), false, true, false);
+			runIntro(v);
+		}
 		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
 	} else {
-		changeScreenMode("scene");
+		_prefixDir = _levels[name].scene.prefix;
+		if (!_levels[name].scene.intro.empty()) {
+			MVideo v(_levels[name].scene.intro , Common::Point(0,0), false, true, false);
+			runIntro(v);
+		}
+		changeScreenMode("scene"); 
 		runScene(_levels[name].scene);
 	}
 
@@ -289,7 +308,7 @@ void HypnoEngine::runScene(Scene scene) {
 	_nextHotsToAdd = &scene.hots;	
 	changeCursor("mouse/cursor1.smk", 0);
 
-	while (!shouldQuit() && _nextSetting.empty()) {
+	while (!shouldQuit() && _nextLevel.empty()) {
 		
 		while (g_system->getEventManager()->pollEvent(event)) {
 			mousePos = g_system->getEventManager()->getMousePos();
@@ -435,7 +454,7 @@ void HypnoEngine::runScene(Scene scene) {
 
 
 		if (checkLevelCompleted())
-			_nextSetting = "mis/demo.mis";
+			_nextLevel = "mis/demo.mis";
 
 		g_system->updateScreen();
 		g_system->delayMillis(10);
@@ -614,7 +633,7 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 		}
 
 		if (!selected.setting.empty())
-			_nextSetting = selected.setting;
+			_nextLevel = selected.setting;
 
 		debug("hotspot clicked actions size: %d", selected.actions.size());
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
@@ -691,6 +710,8 @@ void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transpar
 Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, bool convert) {
 	Common::File *file = new Common::File();
 	Common::String path = convertPath(name);
+	if (!_prefixDir.empty())
+		path = _prefixDir + "/" + path;
 
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
@@ -790,6 +811,8 @@ void HypnoEngine::playVideo(MVideo &video) {
 	debug("video.path: %s", video.path.c_str());
 	Common::File *file = new Common::File();
 	Common::String path = convertPath(video.path);
+	if (!_prefixDir.empty())
+		path = _prefixDir + "/" + path;
 
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 89ccbb5f87..4f45c06975 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -95,8 +95,8 @@ public:
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
 	virtual void loadAssets();
-	void parseScene(Common::String filename);
-	void parseArcadeShooting(Common::String name, Common::String data);
+	void parseScene(Common::String prefix, Common::String filename);
+	void parseArcadeShooting(Common::String prefix, Common::String name, Common::String data);
 	ShootSequence parseShootList(Common::String name, Common::String data);
 	void loadLib(Common::String filename, LibData &r);
 	Common::HashMap<Common::String, Common::String> _assets;
@@ -124,6 +124,7 @@ public:
 
 	void syncGameStream(Common::Serializer &s);
 
+	Common::String _prefixDir;
 	Common::String convertPath(const Common::String &);
 	void playVideo(MVideo &video);
 	void skipVideo(MVideo &video);
@@ -133,6 +134,7 @@ public:
 	void drawImage(Graphics::Surface &image, int x, int y, bool transparent);
 
 	// Cursors
+	void disableCursor();
 	void defaultCursor();
 	void changeCursor(const Common::String &, uint32);
 
@@ -164,8 +166,8 @@ public:
 	Common::HashMap<Common::String, Videos> _intros;
 
 	// settings 
-	Common::String _nextSetting;
-	Common::String _currentSetting;
+	Common::String _nextLevel;
+	Common::String _currentLevel;
 
 	// hotspots
 	Hotspots *_nextHotsToAdd;
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index 34241c9479..c8aa83d99e 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -57,14 +57,14 @@ using namespace Hypno;
 	int i;	 /* integer value */
 }
 
-%token<s> NAME FILENAME
+%token<s> NAME FILENAME BNTOK
 %token<i> NUM
 // header
 %token YBTOK YMTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
 %token PTOK FTOK TTOK ATOK VTOK OTOK NTOK RTOK ITOK SNTOK ZTOK
 
 // body
-%token FNTOK NONETOK A0TOK BNTOK K0TOK P0TOK WTOK
+%token FNTOK NONETOK A0TOK K0TOK P0TOK WTOK
 
 // end
 %token XTOK
@@ -105,6 +105,9 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 		}
 	  | QTOK NUM NUM { debug("Q %d %d", $2, $3); }
 	  | BNTOK FILENAME {
+		  if (Common::String("B0") == $1)
+		  	g_parsedArc.intro = $2;
+		 	
 		  debug("BN %s", $2); 
 		}
 	  | SNTOK FILENAME enc {
@@ -149,7 +152,9 @@ bline: FNTOK FILENAME {
 		 debug("A0 %d %d", $2, $3); 
 		}
 	 | RTOK NUM NUM  { debug("R %d %d", $2, $3); }
-	 | BNTOK NUM NUM { debug("BN %d %d", $2, $3); }
+	 | BNTOK NUM NUM { 
+
+		 debug("BN %d %d", $2, $3); }
 	 | K0TOK NUM NUM { 
 		 shoot->explosionFrame = $3;
 		 debug("K0 %d %d", $2, $3);
diff --git a/engines/hypno/spider/lexer_arc.l b/engines/hypno/spider/lexer_arc.l
index 87a1472153..5fb317cf08 100644
--- a/engines/hypno/spider/lexer_arc.l
+++ b/engines/hypno/spider/lexer_arc.l
@@ -60,7 +60,7 @@ F[0-9]						return FNTOK;
 F							return FTOK;
 S[0-9]						return SNTOK;
 A0							return A0TOK;
-B[0-9]						return BNTOK;
+B[0-9]						HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
 K0							return K0TOK;
 P0							return P0TOK;
 YB							return YBTOK;
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 690016c55d..69a6266205 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -7,7 +7,7 @@ SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEn
 
 void SpiderEngine::loadAssets() {
 	LibData files; 
-	loadLib("c_misc/missions.lib", files);
+	loadLib("sixdemo/c_misc/missions.lib", files);
 	uint32 i = 0;
 	uint32 j = 0;
 
@@ -29,43 +29,47 @@ void SpiderEngine::loadAssets() {
 	}
 
 	Common::String arclevel = files[0].name; 
-	parseArcadeShooting(arclevel, arc);
+	parseArcadeShooting("sixdemo", arclevel, arc);
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 
-	loadLib("c_misc/fonts.lib", _fontFiles);
-	loadLib("c_misc/sound.lib", _soundFiles);
-	loadLib("demo/sound.lib", _soundFiles);
+	loadLib("sixdemo/c_misc/fonts.lib", _fontFiles);
+	loadLib("sixdemo/c_misc/sound.lib", _soundFiles);
+	loadLib("sixdemo/demo/sound.lib", _soundFiles);
+
+	// start level
+	Level start;
+	start.trans.level = "sixdemo/mis/demo.mis";
+	start.trans.intros.push_back(MVideo("sixdemo/demo/dcine1.smk", Common::Point(0, 0), false, true, false));
+	start.trans.intros.push_back(MVideo("sixdemo/demo/dcine2.smk", Common::Point(0, 0), false, true, false));
+	_levels["<start>"] = start;
 
 	// quit level
 	Hotspot q;
 	q.type = MakeMenu;
 	Action *a = new Quit();
 	q.actions.push_back(a);
-	Level level;
-	Hotspots quit;
-	quit.push_back(q);
-	level.scene.hots = quit;  
-	_levels["mis/quit.mis"] = level;
+	Level quit;
+	Hotspots hs;
+	hs.push_back(q);
+	quit.scene.hots = hs;  
+	_levels["<quit>"] = quit;
 
 	// Read assets from mis files
-	parseScene("mis/demo.mis");
-	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine1.smk", Common::Point(0, 0), false, true, false));
-	_levels["mis/demo.mis"].intros.push_back(MVideo("demo/dcine2.smk", Common::Point(0, 0), false, true, false));
-	_levels["mis/demo.mis"].scene.hots[1].setting = "c_misc/missions.lib/c1.mi_";
-	_levels["mis/demo.mis"].scene.hots[2].setting = "mis/alley.mis";
+	parseScene("sixdemo", "mis/demo.mis");
+	_levels["sixdemo/mis/demo.mis"].scene.hots[1].setting = "sixdemo/c_misc/missions.lib/c1.mi_";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[2].setting = "sixdemo/mis/alley.mis";
 
-	_levels["mis/demo.mis"].scene.hots[4].setting = "mis/shoctalk.mis";
-	_levels["mis/demo.mis"].scene.hots[5].setting = "mis/order.mis";
-	_levels["mis/demo.mis"].scene.sound = "demo/sound.lib/menu_mus.raw";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[4].setting = "sixdemo/mis/shoctalk.mis";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[5].setting = "sixdemo/mis/order.mis";
+	_levels["sixdemo/mis/demo.mis"].scene.sound = "sixdemo/demo/sound.lib/menu_mus.raw";
 
-	parseScene("mis/order.mis");
-	_levels["mis/order.mis"].scene.hots[1].setting = "mis/quit.mis";
-	parseScene("mis/alley.mis");
-	_levels["mis/alley.mis"].intros.push_back(MVideo("demo/aleyc01s.smk", Common::Point(0, 0), false, true, false));
-	_levels["mis/alley.mis"].scene.sound = "demo/sound.lib/alleymus.raw";
+	parseScene("sixdemo", "mis/order.mis");
+	_levels["sixdemo/mis/order.mis"].scene.hots[1].setting = "sixdemo/mis/quit.mis";
+	parseScene("sixdemo", "mis/alley.mis");
+	_levels["sixdemo/mis/alley.mis"].scene.intro = "demo/aleyc01s.smk";
+	_levels["sixdemo/mis/alley.mis"].scene.sound = "sixdemo/demo/sound.lib/alleymus.raw";
 
-	parseScene("mis/shoctalk.mis");
-	_nextSetting = "mis/demo.mis";
+	parseScene("sixdemo", "mis/shoctalk.mis");
 }
 
 
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index bf03495c8b..baa20dcb7e 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -7,7 +7,7 @@ WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(s
 
 void WetEngine::loadAssets() {
 	LibData files; 
-	loadLib("c_misc/missions.lib", files);
+	loadLib("wetlands/c_misc/missions.lib", files);
 	uint32 i = 0;
 	uint32 j = 0;
 
@@ -28,13 +28,20 @@ void WetEngine::loadAssets() {
 		}
 	}
 
+	Level start;
+	start.trans.level = "wetlands/c_misc/missions.lib/c31.mi_";
+	start.trans.intros.push_back(MVideo("movie/nw_logo.smk", Common::Point(0, 0), false, true, false));
+	start.trans.intros.push_back(MVideo("movie/hypnotix.smk", Common::Point(0, 0), false, true, false));
+	start.trans.intros.push_back(MVideo("movie/wetlogo.smk", Common::Point(0, 0), false, true, false));
+	_levels["<start>"] = start;
+
 	Common::String arclevel = files[0].name; 
-	parseArcadeShooting(arclevel, arc);
+	parseArcadeShooting("wetlands", arclevel, arc);
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.prefix = "wetlands";
 
-	loadLib("c_misc/fonts.lib", _fontFiles);
-	loadLib("c_misc/sound.lib", _soundFiles);
-	_nextSetting = "c_misc/missions.lib/c31.mi_";
+	loadLib("wetlands/c_misc/fonts.lib", _fontFiles);
+	loadLib("wetlands/c_misc/sound.lib", _soundFiles);
 }
 
 } // End of namespace Hypno


Commit: 51683aaa8b22535e6af9894906333efbdf6b4faa
    https://github.com/scummvm/scummvm/commit/51683aaa8b22535e6af9894906333efbdf6b4faa
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved wetlands demo support and refactored engines

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/grammar_arc.y
    engines/hypno/spider/lexer_arc.l
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 61049482fc..7ab0bd3aa3 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -6,7 +6,7 @@
 
 namespace Hypno {
 
-void HypnoEngine::drawPlayer(Common::String player, uint32 idx) { error("not implemented"); }
+void HypnoEngine::drawPlayer(Common::String player, MVideo &background) { error("not implemented"); }
 void HypnoEngine::drawHealth(const Graphics::Font &font) { error("not implemented"); }
 
 void HypnoEngine::drawShoot(Common::Point target) {
@@ -62,9 +62,15 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			}
 		}
 
-		if (background.decoder->endOfVideo() || _health < 0) {
+		if (_health <= 0 ) {
 			skipVideo(background);
-			_nextLevel = "mis/demo.mis";
+			_nextLevel = arc.levelIfLose;
+			return;
+		}
+
+		if (background.decoder->endOfVideo()) {
+			skipVideo(background);
+			_nextLevel = arc.levelIfWin;
 			return;
 		}
 
@@ -73,7 +79,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			if (si.timestamp <= background.decoder->getCurFrame()) {
 				shootSequence.pop_front();
 				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
-					if (it->name == si.name) {
+					if (it->name == si.name && it->name != "NONE") {
 						Shoot s = *it;
 						s.video = new MVideo(it->animation, it->position , true, false, false);
 						playVideo(*s.video);
@@ -115,7 +121,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			playSound(_music, 0);
 		}
 
-		drawPlayer(arc.player, playerIdx);
+		drawPlayer(arc.player, background);
 		drawHealth(font);
 
 		drawScreen();
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 7953fbbdb7..d15cd4f1b3 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -35,6 +35,9 @@
 
 namespace Hypno {
 
+typedef Common::String Filename;
+typedef Common::List<Filename> Filenames;
+
 enum HotspotType {
     MakeMenu,
  	MakeHotspot
@@ -48,14 +51,14 @@ class Action {
 typedef Common::Array<Action*> Actions;
 
 class Hotspot;
-typedef Common::Array<Hotspot> Hotspots;
 
+typedef Common::Array<Hotspot> Hotspots;
 typedef Common::Array<Hotspots *> HotspotsStack;
 
 class MVideo {
   public:
-    MVideo(Common::String, Common::Point, bool, bool, bool);
-    Common::String path;
+    MVideo(Filename, Common::Point, bool, bool, bool);
+    Filename path;
 	Common::Point position;
 	bool scaled;
 	bool transparent;
@@ -79,25 +82,25 @@ class Hotspot {
 
 class Mice : public Action {
   public:
-	Common::String path;
+	Filename path;
 	uint32 index;
 };
 
 class Palette : public Action {
   public:
-	Common::String path;
+	Filename path;
 };
 
 class Background : public Action {
   public:
-	Common::String path;
+	Filename path;
 	Common::Point origin;
 	Common::String condition;
 };
 
 class Overlay : public Action {
   public:
-	Common::String path;
+	Filename path;
 	Common::Point origin;
 	Common::String flag;
 };
@@ -110,12 +113,12 @@ class Quit : public Action {
 
 class Cutscene : public Action {
   public:
-	Common::String path;
+	Filename path;
 };
 
 class Play : public Action {
   public:
-	Common::String path;
+	Filename path;
 	Common::Point origin;
 	Common::String condition;
 	Common::String flag;
@@ -123,14 +126,14 @@ class Play : public Action {
 
 class Ambient : public Action {
   public:
-	Common::String path;
+	Filename path;
 	Common::Point origin;
 	Common::String flag;
 };
 
 class WalN : public Action {
   public:
-	Common::String path;
+	Filename path;
 	Common::Point origin;
 	Common::String condition;
 	Common::String flag;
@@ -145,7 +148,7 @@ class Global : public Action {
 class TalkCommand {
   public:
 	Common::String command;
-	Common::String path;
+	Filename path;
 	uint32 num;
 	Common::Point position;
 };
@@ -156,7 +159,7 @@ class Talk : public Action {
   public:
 	TalkCommands commands;
 	bool active;
-	Common::String background;
+	Filename background;
 	Common::Point position;
 	Common::Rect rect;
 };
@@ -186,23 +189,27 @@ typedef Common::List<Common::String> Sounds;
 class Transition {
   public:
 	Common::String level;
-	Videos intros;
+	Filenames intros;
 };
 
 class Scene {
   public:
-    Common::String intro;
+    Filename intro;
     Common::String prefix;
 	Hotspots hots;
-	Common::String sound;
+	Filename sound;
 };
 
 class ArcadeShooting {
   public:
-    Common::String intro;
-	Common::String prefix;
-	Common::String background;
-	Common::String player;
+	Common::String levelIfWin;
+	Common::String levelIfLose;
+	Filenames defeatVideos;
+	Filenames winVideos;
+    Filename intro;
+	Filename prefix;
+	Filename background;
+	Filename player;
 	int health;
 	Shoots shoots;
 	ShootSequence shootSequence;
@@ -214,9 +221,10 @@ class Level {
     Transition trans;
 	Scene scene;
 	ArcadeShooting arcade;
+
 };
 
-typedef Common::HashMap<Common::String, Level> Levels;
+typedef Common::HashMap<Filename, Level> Levels;
 extern Hotspots *g_parsedHots;
 extern ArcadeShooting g_parsedArc;
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index ae1d2791a2..7d4f6fb719 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -94,6 +94,18 @@ HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	  _nextHotsToAdd(nullptr), _nextHotsToRemove(nullptr),
 	  _screenW(640), _screenH(480) {
 	_rnd = new Common::RandomSource("hypno");
+
+
+	// Add quit level
+	Hotspot q;
+	q.type = MakeMenu;
+	Action *a = new Quit();
+	q.actions.push_back(a);
+	Level quit;
+	Hotspots hs;
+	hs.push_back(q);
+	quit.scene.hots = hs;  
+	_levels["<quit>"] = quit;
 }
 
 HypnoEngine::~HypnoEngine() {
@@ -274,8 +286,11 @@ void HypnoEngine::runLevel(Common::String name) {
 
 	if (!_levels[name].trans.level.empty()) {
 		_nextLevel = _levels[name].trans.level;
-		for (Videos::iterator it = _levels[name].trans.intros.begin(); it != _levels[name].trans.intros.end(); ++it)
-			runIntro(*it);
+		for (Filenames::iterator it = _levels[name].trans.intros.begin(); it != _levels[name].trans.intros.end(); ++it) {
+			MVideo v(*it, Common::Point(0, 0), false, true, false);
+			runIntro(v);
+		}
+			
 
 	} else if (!_levels[name].arcade.background.empty()) {
 		_prefixDir = _levels[name].arcade.prefix;
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 4f45c06975..f8a64a3d33 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -188,7 +188,7 @@ public:
 
 	// Arcade
 	void drawShoot(Common::Point);
-	virtual void drawPlayer(Common::String player, uint32 idx);
+	virtual void drawPlayer(Common::String player, MVideo &background);
 	virtual void drawHealth(const Graphics::Font &font);
 	int _health;
 	int _maxHealth;
@@ -212,7 +212,7 @@ public:
 
 	void loadAssets() override;
 	
-	void drawPlayer(Common::String player, uint32 idx) override;
+	void drawPlayer(Common::String player, MVideo &background) override;
 	void drawHealth(const Graphics::Font &font) override;
 
 };
@@ -223,7 +223,7 @@ public:
 
 	void loadAssets() override;
 	
-	void drawPlayer(Common::String player, uint32 idx) override;
+	void drawPlayer(Common::String player, MVideo &background) override;
 	void drawHealth(const Graphics::Font &font) override;
 };
 
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 70feaf9bde..640ed1cd30 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -6,7 +6,9 @@
 
 namespace Hypno {
 
-void SpiderEngine::drawPlayer(Common::String player, uint32 idx) {
+void SpiderEngine::drawPlayer(Common::String player, MVideo &background) {
+	Common::Point mousePos = g_system->getEventManager()->getMousePos();
+	uint32 idx = mousePos.x / 50;
 	Graphics::Surface *image = decodeFrame(player, idx);
 	drawImage(*image, 60, 129, true);
 	image->free();
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/spider/grammar_arc.y
index c8aa83d99e..a7b49119b4 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/spider/grammar_arc.y
@@ -60,8 +60,8 @@ using namespace Hypno;
 %token<s> NAME FILENAME BNTOK
 %token<i> NUM
 // header
-%token YBTOK YMTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
-%token PTOK FTOK TTOK ATOK VTOK OTOK NTOK RTOK ITOK SNTOK ZTOK
+%token YXTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
+%token PTOK FTOK TTOK TPTOK ATOK VTOK OTOK O1TOK NTOK RTOK ITOK SNTOK ZTOK
 
 // body
 %token FNTOK NONETOK A0TOK K0TOK P0TOK WTOK
@@ -74,8 +74,7 @@ using namespace Hypno;
 
 %%
 
-start:  YBTOK header body
-      | YMTOK header body
+start:  YXTOK header body
       ;
 
 
@@ -91,9 +90,16 @@ hline:  CTOK NUM  { debug("C %d", $2); }
       | ATOK NUM NUM { debug("A %d %d", $2, $3); }
       | VTOK NUM NUM { debug("V %d %d", $2, $3); }
       | OTOK NUM NUM { debug("O %d %d", $2, $3); }
+	  | O1TOK NUM NUM { debug("O1 %d %d", $2, $3); }
+	  | TPTOK FILENAME NUM FILENAME { 
+		  debug("Tp %s %d %s", $2, $3, $4); 
+		}
 	  | TTOK FILENAME NUM { 
 		  debug("T %s %d", $2, $3); 
 		}
+	  | TTOK NONETOK NUM { 
+		  debug("T NONE %d", $3); 
+		}
 	  | NTOK FILENAME  { 
 		  g_parsedArc.background = $2; 
 		  debug("N %s", $2); 
@@ -147,6 +153,10 @@ bline: FNTOK FILENAME {
 		 shoot->name = $2;
 		 debug("I %s", $2); 
 	   }
+     | ITOK  BNTOK  {  // Workaround for NAME == B1
+		 shoot->name = $2;
+		 debug("I %s", $2); 
+	   }
 	 | A0TOK NUM NUM { 
 		 shoot->position = Common::Point($2, $3);
 		 debug("A0 %d %d", $2, $3); 
diff --git a/engines/hypno/spider/lexer_arc.l b/engines/hypno/spider/lexer_arc.l
index 5fb317cf08..79b354a689 100644
--- a/engines/hypno/spider/lexer_arc.l
+++ b/engines/hypno/spider/lexer_arc.l
@@ -48,6 +48,7 @@ P							return PTOK;
 A							return ATOK;
 V							return VTOK;
 O 							return OTOK;
+O1							return O1TOK;
 N 							return NTOK;
 R 							return RTOK;
 I 							return ITOK;
@@ -56,6 +57,7 @@ Z							return ZTOK;
 W							return WTOK;
 X 							return XTOK;
 T							return TTOK;
+Tp							return TPTOK;
 F[0-9]						return FNTOK;
 F							return FTOK;
 S[0-9]						return SNTOK;
@@ -63,8 +65,7 @@ A0							return A0TOK;
 B[0-9]						HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
 K0							return K0TOK;
 P0							return P0TOK;
-YB							return YBTOK;
-YM							return YMTOK;
+Y[A-Z]						return YHTOK;
 22[k|K]						return ENCTOK;
 [A-Za-z_][A-Za-z_0-9]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
 [A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 69a6266205..13cf3582e6 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -11,6 +11,13 @@ void SpiderEngine::loadAssets() {
 	uint32 i = 0;
 	uint32 j = 0;
 
+	// start level
+	Level start;
+	start.trans.level = "sixdemo/mis/demo.mis";
+	start.trans.intros.push_back("sixdemo/demo/dcine1.smk");
+	start.trans.intros.push_back("sixdemo/demo/dcine2.smk");
+	_levels["<start>"] = start;
+
 	Common::String arc;
 	Common::String list;
 
@@ -36,24 +43,6 @@ void SpiderEngine::loadAssets() {
 	loadLib("sixdemo/c_misc/sound.lib", _soundFiles);
 	loadLib("sixdemo/demo/sound.lib", _soundFiles);
 
-	// start level
-	Level start;
-	start.trans.level = "sixdemo/mis/demo.mis";
-	start.trans.intros.push_back(MVideo("sixdemo/demo/dcine1.smk", Common::Point(0, 0), false, true, false));
-	start.trans.intros.push_back(MVideo("sixdemo/demo/dcine2.smk", Common::Point(0, 0), false, true, false));
-	_levels["<start>"] = start;
-
-	// quit level
-	Hotspot q;
-	q.type = MakeMenu;
-	Action *a = new Quit();
-	q.actions.push_back(a);
-	Level quit;
-	Hotspots hs;
-	hs.push_back(q);
-	quit.scene.hots = hs;  
-	_levels["<quit>"] = quit;
-
 	// Read assets from mis files
 	parseScene("sixdemo", "mis/demo.mis");
 	_levels["sixdemo/mis/demo.mis"].scene.hots[1].setting = "sixdemo/c_misc/missions.lib/c1.mi_";
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index 27b6b6117d..e9512f9fec 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -6,35 +6,23 @@
 
 namespace Hypno {
 
-void WetEngine::drawPlayer(Common::String player, uint32 idx) {
-	_transparentColor = _pixelFormat.RGBToColor(4, 4, 0);
-	Graphics::Surface *image = decodeFrame(player, idx);
-	drawImage(*image, 0, 130, true);
+void WetEngine::drawPlayer(Common::String player, MVideo &background) {
+	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
+	Graphics::Surface *image = decodeFrame(player, background.decoder->getCurFrame() % 3);
+	drawImage(*image, 0, 200-image->h+1, true);
 	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
 	image->free();
 	delete image;
 }
 
 void WetEngine::drawHealth(const Graphics::Font &font) {
-	/*
-	Common::Rect r;
+	//Common::Rect r;
 	uint32 c;
-	int d = (22 * (_maxHealth - _health) / _maxHealth);
-
-	r = Common::Rect(256, 152 + d, 272, 174);
-	if (d >= 11)
-		c = _pixelFormat.RGBToColor(255, 0, 0);
-	else 
-		c = _pixelFormat.RGBToColor(32, 208, 32);
-
-	_compositeSurface->fillRect(r, c);
-
-	r = Common::Rect(256, 152, 272, 174);
-	c = _pixelFormat.RGBToColor(0, 0, 255);
-	_compositeSurface->frameRect(r, c);
+	int p = (100 *  _health) / _maxHealth;
+	c = _pixelFormat.RGBToColor(252, 252, 0);
+	font.drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), 70, 160, 65, c);
+	font.drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), 180, 160, 71, c);
 
-	font.drawString(_compositeSurface, "ENERGY", 248, 180, 38, c);
-	*/
 }
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index baa20dcb7e..01688a6387 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -10,35 +10,55 @@ void WetEngine::loadAssets() {
 	loadLib("wetlands/c_misc/missions.lib", files);
 	uint32 i = 0;
 	uint32 j = 0;
+	uint32 k = 0;
 
 	Common::String arc;
 	Common::String list;
+	Common::String arclevel;
 
-	debug("Splitting file: %s",files[0].name.c_str());
-	for (i = 0; i < files[0].data.size(); i++) {
-		arc += files[0].data[i];
-		if (files[0].data[i] == 'X') {
-			i++;
-			for (j = i; j < files[0].data.size(); j++) {
-				if (files[0].data[j] == 'Y')
-					break;
-				list += files[0].data[j];
+	Level start;
+	start.trans.level = files[0].name;
+	start.trans.intros.push_back("movie/nw_logo.smk");
+	start.trans.intros.push_back("movie/hypnotix.smk");
+	start.trans.intros.push_back("movie/wetlogo.smk");
+	_levels["<start>"] = start;
+
+	for (k = 0; k < files.size(); k++) {
+		arc.clear();
+		list.clear();
+		arclevel = files[k].name;
+
+		debug("Parsing %s",arclevel.c_str());
+		for (i = 0; i < files[k].data.size(); i++) {
+			arc += files[k].data[i];
+			if (files[k].data[i] == 'X') {
+				i++;
+				for (j = i; j < files[k].data.size(); j++) {
+					if (files[k].data[j] == 'Y')
+						break;
+					list += files[k].data[j];
+				}
+				break; // No need to keep parsing
 			}
-			break; // No need to keep parsing, no more files are used in the demo
 		}
+
+		parseArcadeShooting("wetlands", arclevel, arc);
+		_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+		_levels[arclevel].arcade.prefix = "wetlands";
+		_levels[arclevel].arcade.levelIfLose = "<gameover>";
+		if (k < files.size()-1)
+			_levels[arclevel].arcade.levelIfWin = files[k+1].name;
 	}
 
-	Level start;
-	start.trans.level = "wetlands/c_misc/missions.lib/c31.mi_";
-	start.trans.intros.push_back(MVideo("movie/nw_logo.smk", Common::Point(0, 0), false, true, false));
-	start.trans.intros.push_back(MVideo("movie/hypnotix.smk", Common::Point(0, 0), false, true, false));
-	start.trans.intros.push_back(MVideo("movie/wetlogo.smk", Common::Point(0, 0), false, true, false));
-	_levels["<start>"] = start;
 
-	Common::String arclevel = files[0].name; 
-	parseArcadeShooting("wetlands", arclevel, arc);
-	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-	_levels[arclevel].arcade.prefix = "wetlands";
+	debug("%s", arc.c_str());
+	debug("------------------------------------");
+
+	Level over;
+	over.trans.level = "<quit>";
+	over.trans.intros.push_back("movie/gameover.smk");
+	_levels["<gameover>"] = over;
+
 
 	loadLib("wetlands/c_misc/fonts.lib", _fontFiles);
 	loadLib("wetlands/c_misc/sound.lib", _soundFiles);


Commit: fb15c9477f9d19afbd04b195680b82d7a0f8f9e3
    https://github.com/scummvm/scummvm/commit/fb15c9477f9d19afbd04b195680b82d7a0f8f9e3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: refactored both games

Changed paths:
    engines/hypno/cursors.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index e050180b3d..32b418d6eb 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -48,8 +48,8 @@ static const byte MOUSECURSOR_SCI[] = {
 
 static const byte cursorPalette[] = {
 	0x00, 0x00, 0x00,  // Black / Transparent
-	0x82, 0x00, 0x00,  // ???
-	0x00, 0x82, 0x00,  // ???
+	0xff, 0xff, 0xff,  // ???
+	0xff, 0xff, 0xff,  // ???
 	0x82, 0x82, 0x00   // ???
 };
 
@@ -74,10 +74,15 @@ void HypnoEngine::disableCursor() {
 }
 
 void HypnoEngine::defaultCursor() {
-
-	const CursorTable *entry = cursorTable;
-	CursorMan.replaceCursor(entry->buf, entry->w, entry->h, entry->hotspotX, entry->hotspotY, 0);
-	CursorMan.showMouse(true);
+	if (!_defaultCursor.empty())
+		changeCursor(_defaultCursor, 0);
+	else {
+		CursorMan.showMouse(true);
+		const CursorTable *entry = cursorTable;
+		CursorMan.replaceCursor(entry->buf, entry->w, entry->h, entry->hotspotX, entry->hotspotY, 0);
+		CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
+		CursorMan.showMouse(true);
+	}
 }
 
 
@@ -85,7 +90,6 @@ void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
 
 	Graphics::Surface *entry = decodeFrame(cursor, n, false);
 	CursorMan.replaceCursor(entry->getPixels(), entry->w, entry->h, 0, 0, 0);
-	//CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
 	CursorMan.showMouse(true);
 }
 
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index d15cd4f1b3..7dcbd811af 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -129,6 +129,7 @@ class Ambient : public Action {
 	Filename path;
 	Common::Point origin;
 	Common::String flag;
+	bool fullscreen;
 };
 
 class WalN : public Action {
@@ -164,6 +165,11 @@ class Talk : public Action {
 	Common::Rect rect;
 };
 
+class ChangeLevel : public Action {
+  public:
+	Filename level;
+};
+
 class Shoot {
   public:
     Common::String name;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 7d4f6fb719..0bf083dcc5 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -95,7 +95,7 @@ HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	  _screenW(640), _screenH(480) {
 	_rnd = new Common::RandomSource("hypno");
 
-
+	_defaultCursor = "";
 	// Add quit level
 	Hotspot q;
 	q.type = MakeMenu;
@@ -282,7 +282,7 @@ void HypnoEngine::runLevel(Common::String name) {
 	stopSound();
 	_music = "";
 
-	disableCursor();
+	//disableCursor();
 
 	if (!_levels[name].trans.level.empty()) {
 		_nextLevel = _levels[name].trans.level;
@@ -320,8 +320,9 @@ void HypnoEngine::runScene(Scene scene) {
 	Common::List<uint32> videosToRemove;
 	
 	stack.clear();
-	_nextHotsToAdd = &scene.hots;	
-	changeCursor("mouse/cursor1.smk", 0);
+	_nextHotsToAdd = &scene.hots;
+	defaultCursor();
+	//changeCursor("mouse/cursor1.smk", 0);
 
 	while (!shouldQuit() && _nextLevel.empty()) {
 		
@@ -379,7 +380,7 @@ void HypnoEngine::runScene(Scene scene) {
 
 				if (hoverHotspot(mousePos)) {
 				} else
-					changeCursor("mouse/cursor1.smk", 0);
+					; //changeCursor("mouse/cursor1.smk", 0);
 				break;
 
 			default:
@@ -521,13 +522,13 @@ void HypnoEngine::runMenu(Hotspots hs) {
 	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
 		Action *action = *itt;
 		if (typeid(*action) == typeid(Quit))
-			runQuit(h, (Quit*) action);
+			runQuit((Quit*) action);
 		else if (typeid(*action) == typeid(Background))
-			runBackground(h, (Background*) action);
+			runBackground((Background*) action);
 		else if (typeid(*action) == typeid(Overlay))
-			runOverlay(h, (Overlay*) action);
+			runOverlay((Overlay*) action);
 		else if (typeid(*action) == typeid(Ambient))
-			runAmbient(h, (Ambient*) action);
+			runAmbient((Ambient*) action);
 
 		//else if (typeid(*action) == typeid(Mice))
 		//	runMice(h, (Mice*) action);
@@ -539,33 +540,33 @@ void HypnoEngine::runMenu(Hotspots hs) {
 		loadImage("int_main/resume.smk", 0, 0, true);
 }
 
-void HypnoEngine::runBackground(const Hotspot h, Background *a) {
+void HypnoEngine::runBackground(Background *a) {
 	if (a->condition.size() > 0 && !_levelState[a->condition])
 		return;
 	Common::Point origin = a->origin;
 	loadImage(a->path, origin.x, origin.y, false);
 }
 
-void HypnoEngine::runOverlay(const Hotspot h, Overlay *a) {
+void HypnoEngine::runOverlay(Overlay *a) {
 	Common::Point origin = a->origin;
 	loadImage(a->path, origin.x, origin.y, false);
 }
 
-void HypnoEngine::runMice(const Hotspot h, Mice *a) {
+void HypnoEngine::runMice(Mice *a) {
     changeCursor(a->path, a->index);
 }
 
-void HypnoEngine::runEscape(const Hotspot h, Escape *a) {
+void HypnoEngine::runEscape(Escape *a) {
     _nextHotsToRemove = stack.back();
 }
 
-void HypnoEngine::runCutscene(const Hotspot h, Cutscene *a) {
+void HypnoEngine::runCutscene(Cutscene *a) {
 	stopSound();
 	_music = "";
 	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true, false));
 }
 
-void HypnoEngine::runGlobal(const Hotspot h, Global *a) {
+void HypnoEngine::runGlobal(Global *a) {
     if (a->command == "TURNON")
 		_levelState[a->variable] = 1;
 	else if (a->command == "TURNOFF")
@@ -574,7 +575,7 @@ void HypnoEngine::runGlobal(const Hotspot h, Global *a) {
 		error("Invalid command %s", a->command.c_str());
 }
 
-void HypnoEngine::runPlay(const Hotspot h, Play *a) {
+void HypnoEngine::runPlay(Play *a) {
 	if (a->condition.size() > 0 && !_levelState[a->condition])
 		return;
 	Common::Point origin = a->origin;
@@ -586,16 +587,16 @@ void HypnoEngine::runPlay(const Hotspot h, Play *a) {
 	}
 }
 
-void HypnoEngine::runAmbient(const Hotspot h, Ambient *a) {
+void HypnoEngine::runAmbient(Ambient *a) {
 	Common::Point origin = a->origin;
 	if (a->flag == "/BITMAP")
 			loadImage(a->path, origin.x, origin.y, false);
 	else {
-		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, a->flag == "/LOOP"));
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, a->fullscreen, a->flag == "/LOOP"));
 	}
 }
 
-void HypnoEngine::runWalN(const Hotspot h, WalN *a) {
+void HypnoEngine::runWalN(WalN *a) {
 	if (a->condition.size() > 0 && !_levelState[a->condition])
 		return;
 	Common::Point origin = a->origin;
@@ -606,11 +607,15 @@ void HypnoEngine::runWalN(const Hotspot h, WalN *a) {
 	}
 }
 
-void HypnoEngine::runQuit(const Hotspot h, Quit *a) {
-    quitGame();
+void HypnoEngine::runQuit(Quit *a) {
+	quitGame();
+}
+
+void HypnoEngine::runChangeLevel(ChangeLevel *a) {
+	_nextLevel = a->level;
 }
 
-void HypnoEngine::runTalk(const Hotspot h, Talk *a) {
+void HypnoEngine::runTalk(Talk *a) {
 	debug("adding TALK line!");
 	_conversation.push_back(a);
 	_refreshConversation = true;
@@ -647,27 +652,30 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			_nextHotsToAdd = selected.smenu;
 		}
 
-		if (!selected.setting.empty())
-			_nextLevel = selected.setting;
+		//if (!selected.setting.empty())
+		//	_nextLevel = selected.setting;
 
 		debug("hotspot clicked actions size: %d", selected.actions.size());
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
+			if (typeid(*action) == typeid(ChangeLevel))
+				runChangeLevel((ChangeLevel*) action);
 			if (typeid(*action) == typeid(Escape))
-				runEscape(selected, (Escape*) action);
+				runEscape((Escape*) action);
 			else if (typeid(*action) == typeid(Cutscene))
-				runCutscene(selected, (Cutscene*) action);
+				runCutscene((Cutscene*) action);
 			else if (typeid(*action) == typeid(Play))
-				runPlay(selected, (Play*) action);
+				runPlay((Play*) action);
 			else if (typeid(*action) == typeid(WalN))
-				runWalN(selected, (WalN*) action);
+				runWalN((WalN*) action);
 			else if (typeid(*action) == typeid(Global))
-				runGlobal(selected, (Global*) action);
+				runGlobal((Global*) action);
 			else if (typeid(*action) == typeid(Talk))
-				runTalk(selected, (Talk*) action);
+				runTalk((Talk*) action);
+			else if (typeid(*action) == typeid(Quit))
+				runQuit((Quit*) action);
 			else if (typeid(*action) == typeid(Palette))
 				debug("runPalette unimplemented");
-
 		}
 
 	}
@@ -703,7 +711,7 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
 			if (typeid(*action) == typeid(Mice))
-				runMice(selected, (Mice*) action);
+				runMice((Mice*) action);
 		}
 		return true;
 	}
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index f8a64a3d33..0aa57305f3 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -134,6 +134,7 @@ public:
 	void drawImage(Graphics::Surface &image, int x, int y, bool transparent);
 
 	// Cursors
+	Common::String _defaultCursor;
 	void disableCursor();
 	void defaultCursor();
 	void changeCursor(const Common::String &, uint32);
@@ -141,17 +142,18 @@ public:
 	// Actions
 	void runIntro(MVideo &video);
 	void runMenu(Hotspots hs);
-    void runBackground(const Hotspot h, Background *a);
-	void runOverlay(const Hotspot h, Overlay *a);
-	void runMice(const Hotspot h, Mice *a);
-	void runEscape(const Hotspot h, Escape *a);
-	void runQuit(const Hotspot h, Quit *a);
-	void runCutscene(const Hotspot h, Cutscene *a);
-	void runPlay(const Hotspot h, Play *a);
-	void runAmbient(const Hotspot h, Ambient *a);
-	void runWalN(const Hotspot h, WalN *a);
-	void runGlobal(const Hotspot h, Global *a);
-	void runTalk(const Hotspot h, Talk *a);
+    void runBackground(Background *a);
+	void runOverlay(Overlay *a);
+	void runMice(Mice *a);
+	void runEscape(Escape *a);
+	void runQuit(Quit *a);
+	void runCutscene(Cutscene *a);
+	void runPlay(Play *a);
+	void runAmbient(Ambient *a);
+	void runWalN(WalN *a);
+	void runGlobal(Global *a);
+	void runTalk(Talk *a);
+	void runChangeLevel(ChangeLevel *a);
 
 	// Screen
 	Graphics::PixelFormat _pixelFormat;
@@ -165,7 +167,7 @@ public:
 	// intros
 	Common::HashMap<Common::String, Videos> _intros;
 
-	// settings 
+	// levels 
 	Common::String _nextLevel;
 	Common::String _currentLevel;
 
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 13cf3582e6..fe2c144102 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -45,15 +45,28 @@ void SpiderEngine::loadAssets() {
 
 	// Read assets from mis files
 	parseScene("sixdemo", "mis/demo.mis");
-	_levels["sixdemo/mis/demo.mis"].scene.hots[1].setting = "sixdemo/c_misc/missions.lib/c1.mi_";
-	_levels["sixdemo/mis/demo.mis"].scene.hots[2].setting = "sixdemo/mis/alley.mis";
+	ChangeLevel *cl = new ChangeLevel();
+	cl->level = "sixdemo/c_misc/missions.lib/c1.mi_";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[1].actions.push_back(cl);
 
-	_levels["sixdemo/mis/demo.mis"].scene.hots[4].setting = "sixdemo/mis/shoctalk.mis";
-	_levels["sixdemo/mis/demo.mis"].scene.hots[5].setting = "sixdemo/mis/order.mis";
+	cl = new ChangeLevel();
+	cl->level = "sixdemo/mis/alley.mis";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[2].actions.push_back(cl);
+
+	cl = new ChangeLevel();
+	cl->level = "sixdemo/mis/shoctalk.mis";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[4].actions.push_back(cl);
+	
+	cl = new ChangeLevel();
+	cl->level = "sixdemo/mis/order.mis";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[5].actions.push_back(cl);
 	_levels["sixdemo/mis/demo.mis"].scene.sound = "sixdemo/demo/sound.lib/menu_mus.raw";
 
 	parseScene("sixdemo", "mis/order.mis");
-	_levels["sixdemo/mis/order.mis"].scene.hots[1].setting = "sixdemo/mis/quit.mis";
+	cl = new ChangeLevel();
+	cl->level = "<quit>";
+	_levels["sixdemo/mis/order.mis"].scene.hots[1].actions.push_back(cl);
+
 	parseScene("sixdemo", "mis/alley.mis");
 	_levels["sixdemo/mis/alley.mis"].scene.intro = "demo/aleyc01s.smk";
 	_levels["sixdemo/mis/alley.mis"].scene.sound = "sixdemo/demo/sound.lib/alleymus.raw";
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 01688a6387..1a8d303662 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -17,12 +17,45 @@ void WetEngine::loadAssets() {
 	Common::String arclevel;
 
 	Level start;
-	start.trans.level = files[0].name;
-	start.trans.intros.push_back("movie/nw_logo.smk");
-	start.trans.intros.push_back("movie/hypnotix.smk");
-	start.trans.intros.push_back("movie/wetlogo.smk");
+	Hotspot h;
+	Hotspots hs;
+
+	h.type = MakeMenu;
+	Ambient *a = new Ambient();
+	a->path = "movie/selector.smk";
+	a->fullscreen = true;
+	a->flag = "/LOOP";
+	a->origin = Common::Point(0, 0); 
+	h.actions.push_back(a);
+
+	hs.push_back(h);
+
+	h.type = MakeHotspot;
+	h.rect = Common::Rect(0, 424, 233, 462);
+	h.actions.clear();
+	ChangeLevel *cl = new ChangeLevel();
+	cl->level = "<intro>";
+	h.actions.push_back(cl);
+
+	hs.push_back(h);
+
+	h.rect = Common::Rect(504, 424, 637, 480);
+	Quit *q = new Quit();
+	h.actions.clear();
+	h.actions.push_back(q);
+
+	hs.push_back(h);
+
+	start.scene.hots = hs;  
 	_levels["<start>"] = start;
 
+	Level intro;
+	intro.trans.level = files[0].name;
+	intro.trans.intros.push_back("movie/nw_logo.smk");
+	intro.trans.intros.push_back("movie/hypnotix.smk");
+	intro.trans.intros.push_back("movie/wetlogo.smk");
+	_levels["<intro>"] = intro;
+
 	for (k = 0; k < files.size(); k++) {
 		arc.clear();
 		list.clear();


Commit: 2acec33542f752dd647c682145b7895581b95024
    https://github.com/scummvm/scummvm/commit/2acec33542f752dd647c682145b7895581b95024
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: implemented missing puzzle and fixes

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/cursors.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/spider/lexer_arc.l
    engines/hypno/spider/spider.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 7ab0bd3aa3..cc7ec9eb62 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -28,10 +28,8 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 	_shoots.clear();
 
 	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);
-	uint32 playerIdx = 0;
 
 	defaultCursor();
-	//changeCursor("mouse/cursor1.smk", 0);
 	playVideo(background);
 
 	while (!shouldQuit()) {
@@ -54,7 +52,6 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
-				playerIdx = mousePos.x / 50;
 				break;
 
 			default:
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index 32b418d6eb..1df00efc89 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -48,9 +48,9 @@ static const byte MOUSECURSOR_SCI[] = {
 
 static const byte cursorPalette[] = {
 	0x00, 0x00, 0x00,  // Black / Transparent
-	0xff, 0xff, 0xff,  // ???
-	0xff, 0xff, 0xff,  // ???
-	0x82, 0x82, 0x00   // ???
+	0x01, 0x01, 0x01,  // Gray
+	0xff, 0xff, 0xff,  // White
+	0xff, 0x00, 0x00   // Red
 };
 
 struct CursorTable {
@@ -87,7 +87,6 @@ void HypnoEngine::defaultCursor() {
 
 
 void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
-
 	Graphics::Surface *entry = decodeFrame(cursor, n, false);
 	CursorMan.replaceCursor(entry->getPixels(), entry->w, entry->h, 0, 0, 0);
 	CursorMan.showMouse(true);
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 7dcbd811af..4bbb639eaf 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -198,12 +198,22 @@ class Transition {
 	Filenames intros;
 };
 
+class Puzzle {
+  public:
+	Common::String name;
+	Filenames intros;
+	Common::String levelIfWin;
+	Common::String levelIfLose;
+};
+
 class Scene {
   public:
     Filename intro;
     Common::String prefix;
 	Hotspots hots;
 	Filename sound;
+	Common::String levelIfWin;
+	Common::String levelIfLose;
 };
 
 class ArcadeShooting {
@@ -227,7 +237,7 @@ class Level {
     Transition trans;
 	Scene scene;
 	ArcadeShooting arcade;
-
+	Puzzle puzzle;
 };
 
 typedef Common::HashMap<Filename, Level> Levels;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 0bf083dcc5..286cd273f6 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -263,6 +263,7 @@ Common::Error HypnoEngine::run() {
 	loadAssets();
 	_nextLevel = "<start>";
 	while (!shouldQuit()) {
+		_defaultCursor = "";
 		_prefixDir = "";
 		resetLevelState();
 		_videosPlaying.clear();
@@ -282,7 +283,7 @@ void HypnoEngine::runLevel(Common::String name) {
 	stopSound();
 	_music = "";
 
-	//disableCursor();
+	disableCursor();
 
 	if (!_levels[name].trans.level.empty()) {
 		_nextLevel = _levels[name].trans.level;
@@ -300,6 +301,12 @@ void HypnoEngine::runLevel(Common::String name) {
 		}
 		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
+	} else if (!_levels[name].puzzle.name.empty()) {
+		if (!_levels[name].arcade.intro.empty()) {
+			MVideo v(_levels[name].arcade.intro, Common::Point(0,0), false, true, false);
+			runIntro(v);
+		}
+		runPuzzle(_levels[name].puzzle);
 	} else {
 		_prefixDir = _levels[name].scene.prefix;
 		if (!_levels[name].scene.intro.empty()) {
@@ -322,7 +329,6 @@ void HypnoEngine::runScene(Scene scene) {
 	stack.clear();
 	_nextHotsToAdd = &scene.hots;
 	defaultCursor();
-	//changeCursor("mouse/cursor1.smk", 0);
 
 	while (!shouldQuit() && _nextLevel.empty()) {
 		
@@ -380,7 +386,7 @@ void HypnoEngine::runScene(Scene scene) {
 
 				if (hoverHotspot(mousePos)) {
 				} else
-					; //changeCursor("mouse/cursor1.smk", 0);
+					defaultCursor();
 				break;
 
 			default:
@@ -511,6 +517,7 @@ void HypnoEngine::runIntro(MVideo &video) {
 	}
 }
 
+void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Not implemented"); } 
 
 //Actions
 
@@ -652,9 +659,6 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			_nextHotsToAdd = selected.smenu;
 		}
 
-		//if (!selected.setting.empty())
-		//	_nextLevel = selected.setting;
-
 		debug("hotspot clicked actions size: %d", selected.actions.size());
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
@@ -748,7 +752,7 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 
 	const Graphics::Surface *frame = vd.decodeNextFrame();
 	Graphics::Surface *rframe;
-
+	//debug("decoding: %s %d %d", name.c_str(), frame->h, frame->w);
 	if (convert) {
 		rframe = frame->convertTo(_pixelFormat, vd.getPalette());
 	} else {
@@ -797,6 +801,9 @@ void HypnoEngine::changeScreenMode(Common::String mode) {
 void HypnoEngine::updateScreen(MVideo &video) {
 	const Graphics::Surface *frame = video.decoder->decodeNextFrame();
 	video.currentFrame = frame;
+	if (frame->h == 0 || frame->w == 0 || video.decoder->getPalette() == nullptr)
+		return;
+
 	Graphics::Surface *sframe, *cframe;
 
 	if (video.scaled) {
@@ -862,7 +869,6 @@ void HypnoEngine::playSound(Common::String name, uint32 loops) {
 	debug("playing %s", name.c_str());
 	ByteArray *raw;
 	Audio::LoopingAudioStream *stream;
-	Common::MemorySeekableReadWriteStream *mstream;
 
 	for (LibData::iterator it = _soundFiles.begin(); it != _soundFiles.end(); ++it) {
 			if (it->name == name) {
@@ -873,7 +879,6 @@ void HypnoEngine::playSound(Common::String name, uint32 loops) {
 			}
 	}
 
-
 }
 
 void HypnoEngine::stopSound() {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 0aa57305f3..890d08766a 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -203,6 +203,9 @@ public:
 	bool rightClickedConversation(Common::Point mousePos);
 	bool leftClickedConversation(Common::Point mousePos);
 
+	// Hardcoded puzzles
+	virtual void runPuzzle(Puzzle puzzle);
+
 	// Timers
 	bool installTimer(uint32, Common::String *);
 	void removeTimer();
@@ -227,6 +230,10 @@ public:
 	
 	void drawPlayer(Common::String player, MVideo &background) override;
 	void drawHealth(const Graphics::Font &font) override;
+	void runPuzzle(Puzzle puzzle) override;
+
+private:
+	void runMatrix(Puzzle puzzle);
 };
 
 } // End of namespace Hypno
diff --git a/engines/hypno/spider/lexer_arc.l b/engines/hypno/spider/lexer_arc.l
index 79b354a689..c831118bb1 100644
--- a/engines/hypno/spider/lexer_arc.l
+++ b/engines/hypno/spider/lexer_arc.l
@@ -65,7 +65,7 @@ A0							return A0TOK;
 B[0-9]						HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
 K0							return K0TOK;
 P0							return P0TOK;
-Y[A-Z]						return YHTOK;
+Y[A-Z0-9]					return YXTOK;
 22[k|K]						return ENCTOK;
 [A-Za-z_][A-Za-z_0-9]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
 [A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index fe2c144102..b90f3418f8 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -1,6 +1,8 @@
 #include "hypno/hypno.h"
 #include "hypno/grammar.h"
 
+#include "common/events.h"
+
 namespace Hypno {
 
 SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
@@ -53,6 +55,10 @@ void SpiderEngine::loadAssets() {
 	cl->level = "sixdemo/mis/alley.mis";
 	_levels["sixdemo/mis/demo.mis"].scene.hots[2].actions.push_back(cl);
 
+	cl = new ChangeLevel();
+	cl->level = "sixdemo/puz_matr";
+	_levels["sixdemo/mis/demo.mis"].scene.hots[3].actions.push_back(cl);	
+
 	cl = new ChangeLevel();
 	cl->level = "sixdemo/mis/shoctalk.mis";
 	_levels["sixdemo/mis/demo.mis"].scene.hots[4].actions.push_back(cl);
@@ -72,7 +78,104 @@ void SpiderEngine::loadAssets() {
 	_levels["sixdemo/mis/alley.mis"].scene.sound = "sixdemo/demo/sound.lib/alleymus.raw";
 
 	parseScene("sixdemo", "mis/shoctalk.mis");
+
+	Level matrix;
+	matrix.puzzle.name = "sixdemo/puz_matr";
+	matrix.puzzle.intros.push_back("spiderman/demo/aleyc01s.smk");
+	matrix.puzzle.levelIfWin = "sixdemo/mis/demo.mis";
+	matrix.puzzle.levelIfLose = "sixdemo/mis/demo.mis";
+	_levels["sixdemo/puz_matr"] = matrix; 
+
 }
 
+void SpiderEngine::runPuzzle(Puzzle puzzle) {
+	if (puzzle.name == "sixdemo/puz_matr")
+		runMatrix(puzzle);
+	else 
+		error("invalid puzzle");
+}
+
+void SpiderEngine::runMatrix(Puzzle puzzle) {
+	Common::Point mousePos;
+	Common::Event event;
+
+	defaultCursor();
+	bool data[10][10] = {};
+	bool solution[10][10] = { 
+		{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},  
+		{0, 0, 1, 1, 1, 1, 1, 1, 0, 0},  
+		{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},  
+		{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},  
+		{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},  
+		{0, 0, 1, 1, 1, 1, 1, 1, 0, 0},  
+		{0, 0, 1, 1, 0, 0, 1, 1, 0, 0},  
+		{0, 0, 1, 1, 0, 0, 1, 1, 0, 0},  
+		{0, 0, 0, 1, 0, 0, 1, 0, 0, 0}, 
+		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
+	Common::Rect matrix(175, 96, 461, 385);
+	Common::Rect cell(0, 0, 27, 27);
+	uint32 activeColor = _pixelFormat.RGBToColor(0, 130, 0);
+	uint32 deactiveColor = _pixelFormat.RGBToColor(0, 0, 0);
+	int x, y;
+	bool found;
+
+	loadImage("sixdemo/puz_matr/matrixbg.smk", 0, 0, false);
+	MVideo v("sixdemo/puz_matr/matintro.smk", Common::Point(0, 0), false, false, false);
+	playVideo(v);
+	while (!shouldQuit()) {
+		
+		while (g_system->getEventManager()->pollEvent(event)) {
+			mousePos = g_system->getEventManager()->getMousePos();
+			// Events
+			switch (event.type) {
+
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_LBUTTONDOWN:
+				playSound("sixdemo/demo/sound.lib/matrix.raw", 1);
+				if (matrix.contains(mousePos)) {
+					x = (mousePos.x - 175) / 29;
+					y = (mousePos.y - 96) / 29;
+					cell.moveTo(175 + 29*x + 1, 96 + 29*y + 1);
+					_compositeSurface->fillRect(cell, data[x][y] ? deactiveColor : activeColor);
+					data[x][y] = !data[x][y];
+				}
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		found = true;
+		for (x = 0; x < 10; x++) {
+			for (y = 0; y < 10; y++) {
+				if (data[x][y] != solution[y][x]) {
+					found = false;
+					break;
+				}
+			}
+			if (!found)
+				break;
+		}
+				
+		if (found) {
+			playSound("sixdemo/demo/sound.lib/matrix_2.raw", 1);
+			_nextLevel = puzzle.levelIfWin;
+			return;
+		} 
+
+		if (v.decoder->needsUpdate()) {
+			updateScreen(v);
+		}
+
+
+		drawScreen();
+		g_system->delayMillis(10);
+	}
+}
 
 } // End of namespace Hypno
\ No newline at end of file


Commit: 1753841da82737cf10ab73611784a524e911797d
    https://github.com/scummvm/scummvm/commit/1753841da82737cf10ab73611784a524e911797d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed name and original copyright

Changed paths:
    engines/hypno/detection.cpp


diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index fc2b709191..0be8448b6e 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -104,11 +104,12 @@ public:
 	}
 
 	const char *getName() const override {
-		return "Spiderman and the Sinister Six";
+		return "Hypno";
 	}
 
 	const char *getOriginalCopyright() const override {
-		return "Copyright (C) Brooklyn Multimedia";
+		return "Marvel Comics Spider-Man: The Sinister Six (C) Brooklyn Multimedia\n" \
+		       "Wetlands (C) Hypnotix, Inc.";
 	}
 
 	const DebugChannelDef *getDebugChannels() const override {


Commit: 8d244e072a5e8e2f8942f1970fdb9191f7450955
    https://github.com/scummvm/scummvm/commit/8d244e072a5e8e2f8942f1970fdb9191f7450955
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: refactoring and linting

Changed paths:
  A engines/hypno/grammar_arc.y
  A engines/hypno/grammar_mis.y
  A engines/hypno/lexer_arc.l
  A engines/hypno/lexer_mis.l
  R engines/hypno/spider/grammar_arc.y
  R engines/hypno/spider/grammar_mis.y
  R engines/hypno/spider/lexer_arc.l
  R engines/hypno/spider/lexer_mis.l
    engines/hypno/arcade.cpp
    engines/hypno/cursors.cpp
    engines/hypno/detection.cpp
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/metaengine.cpp
    engines/hypno/module.mk
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index cc7ec9eb62..8d9c4ea4dc 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -1,5 +1,5 @@
-#include "hypno/hypno.h"
 #include "hypno/grammar.h"
+#include "hypno/hypno.h"
 
 #include "common/events.h"
 #include "graphics/cursorman.h"
@@ -11,9 +11,9 @@ void HypnoEngine::drawHealth(const Graphics::Font &font) { error("not implemente
 
 void HypnoEngine::drawShoot(Common::Point target) {
 	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
-	_compositeSurface->drawLine(80, 155, target.x, target.y+1, c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y  , c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y-1, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y + 1, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y - 1, c);
 }
 
 void HypnoEngine::runArcade(ArcadeShooting arc) {
@@ -36,7 +36,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 		if (background.decoder->needsUpdate())
 			updateScreen(background);
-		
+
 		while (g_system->getEventManager()->pollEvent(event)) {
 			mousePos = g_system->getEventManager()->getMousePos();
 			// Events
@@ -59,7 +59,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			}
 		}
 
-		if (_health <= 0 ) {
+		if (_health <= 0) {
 			skipVideo(background);
 			_nextLevel = arc.levelIfLose;
 			return;
@@ -78,7 +78,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
 					if (it->name == si.name && it->name != "NONE") {
 						Shoot s = *it;
-						s.video = new MVideo(it->animation, it->position , true, false, false);
+						s.video = new MVideo(it->animation, it->position, true, false, false);
 						playVideo(*s.video);
 						_shoots.push_back(s);
 					}
@@ -91,24 +91,23 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 		for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
 			if (it->video->decoder) {
-				int frame = it->video->decoder->getCurFrame(); 
-				if (frame > 0 && frame >= it->explosionFrame-3 && !it->destroyed) {
+				int frame = it->video->decoder->getCurFrame();
+				if (frame > 0 && frame >= it->explosionFrame - 3 && !it->destroyed) {
 					_health = _health - it->damage;
 					debug("healt: %d", _health);
 					skipVideo(*it->video);
-				} else if (it->video->decoder->endOfVideo()){
+				} else if (it->video->decoder->endOfVideo()) {
 					skipVideo(*it->video);
-					shootsToRemove.push_back(i);	
+					shootsToRemove.push_back(i);
 				} else if (it->video->decoder->needsUpdate()) {
 					updateScreen(*it->video);
 				}
-				
 			}
 			i++;
 		}
 		if (shootsToRemove.size() > 0) {
-			for(Common::List<uint32>::iterator it = shootsToRemove.begin(); it != shootsToRemove.end(); ++it) {
-				//debug("removing %d from %d size", *it, _shoots.size()); 
+			for (Common::List<uint32>::iterator it = shootsToRemove.begin(); it != shootsToRemove.end(); ++it) {
+				//debug("removing %d from %d size", *it, _shoots.size());
 				_shoots.remove_at(*it);
 			}
 		}
@@ -138,15 +137,15 @@ bool HypnoEngine::clickedShoot(Common::Point mousePos) {
 		x = mousePos.x - it->position.x;
 		y = mousePos.y - it->position.y;
 		w = it->video->decoder->getWidth();
-		h = it->video->decoder->getHeight(); 
+		h = it->video->decoder->getHeight();
 
 		if (it->video->decoder && x >= 0 && y >= 0 && x < w && y < h) {
 			uint32 c = it->video->currentFrame->getPixel(x, y);
-			//debug("inside %x", c); 
+			//debug("inside %x", c);
 			if (c > 0) {
 				it->destroyed = true;
-				it->video->position = Common::Point(mousePos.x - w/2, mousePos.y - h/2);
-				it->video->decoder->forceSeekToFrame(it->explosionFrame+2);
+				it->video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
+				it->video->decoder->forceSeekToFrame(it->explosionFrame + 2);
 			}
 		}
 	}
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index 1df00efc89..97621cea10 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -28,29 +28,28 @@
 namespace Hypno {
 
 static const byte MOUSECURSOR_SCI[] = {
-	1,1,0,0,0,0,0,0,0,0,0,
-	1,2,1,0,0,0,0,0,0,0,0,
-	1,2,2,1,0,0,0,0,0,0,0,
-	1,2,2,2,1,0,0,0,0,0,0,
-	1,2,2,2,2,1,0,0,0,0,0,
-	1,2,2,2,2,2,1,0,0,0,0,
-	1,2,2,2,2,2,2,1,0,0,0,
-	1,2,2,2,2,2,2,2,1,0,0,
-	1,2,2,2,2,2,2,2,2,1,0,
-	1,2,2,2,2,2,2,2,2,2,1,
-	1,2,2,2,2,2,1,0,0,0,0,
-	1,2,1,0,1,2,2,1,0,0,0,
-	1,1,0,0,1,2,2,1,0,0,0,
-	0,0,0,0,0,1,2,2,1,0,0,
-	0,0,0,0,0,1,2,2,1,0,0,
-	0,0,0,0,0,0,1,2,2,1,0
-};
+	1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0,
+	1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0,
+	1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+	1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
+	1, 2, 1, 0, 1, 2, 2, 1, 0, 0, 0,
+	1, 1, 0, 0, 1, 2, 2, 1, 0, 0, 0,
+	0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
+	0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0};
 
 static const byte cursorPalette[] = {
-	0x00, 0x00, 0x00,  // Black / Transparent
-	0x01, 0x01, 0x01,  // Gray
-	0xff, 0xff, 0xff,  // White
-	0xff, 0x00, 0x00   // Red
+	0x00, 0x00, 0x00, // Black / Transparent
+	0x01, 0x01, 0x01, // Gray
+	0xff, 0xff, 0xff, // White
+	0xff, 0x00, 0x00  // Red
 };
 
 struct CursorTable {
@@ -64,10 +63,8 @@ struct CursorTable {
 };
 
 static const CursorTable cursorTable[] = {
-	{ "default",    "", MOUSECURSOR_SCI,        11, 16, 0,  0  },
-	{ nullptr,      nullptr, nullptr,           0,  0,  0,  0  }
-};
-
+	{"default", "", MOUSECURSOR_SCI, 11, 16, 0, 0},
+	{nullptr, nullptr, nullptr, 0, 0, 0, 0}};
 
 void HypnoEngine::disableCursor() {
 	CursorMan.showMouse(false);
@@ -85,7 +82,6 @@ void HypnoEngine::defaultCursor() {
 	}
 }
 
-
 void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
 	Graphics::Surface *entry = decodeFrame(cursor, n, false);
 	CursorMan.replaceCursor(entry->getPixels(), entry->w, entry->h, 0, 0, 0);
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 0be8448b6e..f90dccbe39 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -29,59 +29,48 @@ static const DebugChannelDef debugFlagList[] = {
 	{Hypno::kHypnoDebugFunction, "functions", "Function execution debug channel"},
 	{Hypno::kHypnoDebugCode, "code", "Code execution debug channel"},
 	{Hypno::kHypnoDebugScript, "script", "Script execution debug channel"},
-	DEBUG_CHANNEL_END
-};
+	DEBUG_CHANNEL_END};
 
 namespace Hypno {
 static const PlainGameDescriptor hypnoGames[] = {
-	{ "sinister-six", "Marvel Comics Spider-Man: The Sinister Six" },
-	{ "wetlands", "Wetlands" },
-	{ 0, 0 }
-};
+	{"sinister-six", "Marvel Comics Spider-Man: The Sinister Six"},
+	{"wetlands", "Wetlands"},
+	{0, 0}};
 
 static const ADGameDescription gameDescriptions[] = {
-	{
-		"sinister-six", // Demo from the US release
-		"Demo",
-		AD_ENTRY2s("COMBAT.EXE", "15a6b1b3819ef002438df340509b5373", 643471,
-  				   "SPIDER.EXE", "15a6b1b3819ef002438df340509b5373", 603587),
-		Common::EN_USA,
-		Common::kPlatformDOS,
-		ADGF_TESTING | ADGF_DEMO,
-		GUIO1(GUIO_NOMIDI)
-	},
-	{
-		"sinister-six", // US release
-		"Not yet implemented",
-		AD_ENTRY2s("COMBAT.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 255115,
-  				   "SPIDER.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 248056),
-		Common::EN_USA,
-		Common::kPlatformDOS,
-		ADGF_UNSUPPORTED | ADGF_TESTING,
-		GUIO1(GUIO_NOMIDI)
-	},
-	{
-		"wetlands", // Wetlands Demo Disc (November 1995)
-		"Demo",
-		AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231,
-  				   "wetdemo.exe", "15a6b1b3819ef002438df340509b5373", 458319),
-		Common::EN_USA,
-		Common::kPlatformDOS,
-		ADGF_TESTING | ADGF_DEMO,
-		GUIO1(GUIO_NOMIDI)
-	},
-	{
-		"wetlands", // Wetlands (US)
-		"",
-		AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 647447,
-  				   "install.exe", "15a6b1b3819ef002438df340509b5373", 477839),
-		Common::EN_USA,
-		Common::kPlatformDOS,
-		ADGF_TESTING,
-		GUIO1(GUIO_NOMIDI)
-	},
-	AD_TABLE_END_MARKER
-};
+	{"sinister-six", // Demo from the US release
+	 "Demo",
+	 AD_ENTRY2s("COMBAT.EXE", "15a6b1b3819ef002438df340509b5373", 643471,
+				"SPIDER.EXE", "15a6b1b3819ef002438df340509b5373", 603587),
+	 Common::EN_USA,
+	 Common::kPlatformDOS,
+	 ADGF_TESTING | ADGF_DEMO,
+	 GUIO1(GUIO_NOMIDI)},
+	{"sinister-six", // US release
+	 "Not yet implemented",
+	 AD_ENTRY2s("COMBAT.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 255115,
+				"SPIDER.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 248056),
+	 Common::EN_USA,
+	 Common::kPlatformDOS,
+	 ADGF_UNSUPPORTED | ADGF_TESTING,
+	 GUIO1(GUIO_NOMIDI)},
+	{"wetlands", // Wetlands Demo Disc (November 1995)
+	 "Demo",
+	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231,
+				"wetdemo.exe", "15a6b1b3819ef002438df340509b5373", 458319),
+	 Common::EN_USA,
+	 Common::kPlatformDOS,
+	 ADGF_TESTING | ADGF_DEMO,
+	 GUIO1(GUIO_NOMIDI)},
+	{"wetlands", // Wetlands (US)
+	 "",
+	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 647447,
+				"install.exe", "15a6b1b3819ef002438df340509b5373", 477839),
+	 Common::EN_USA,
+	 Common::kPlatformDOS,
+	 ADGF_TESTING,
+	 GUIO1(GUIO_NOMIDI)},
+	AD_TABLE_END_MARKER};
 } // End of namespace Hypno
 
 static const char *const directoryGlobs[] = {
@@ -89,8 +78,7 @@ static const char *const directoryGlobs[] = {
 	"factory",
 	"wetlands",
 	"movie",
-	0
-};
+	0};
 
 class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
 public:
@@ -108,8 +96,8 @@ public:
 	}
 
 	const char *getOriginalCopyright() const override {
-		return "Marvel Comics Spider-Man: The Sinister Six (C) Brooklyn Multimedia\n" \
-		       "Wetlands (C) Hypnotix, Inc.";
+		return "Marvel Comics Spider-Man: The Sinister Six (C) Brooklyn Multimedia\n"
+			   "Wetlands (C) Hypnotix, Inc.";
 	}
 
 	const DebugChannelDef *getDebugChannels() const override {
diff --git a/engines/hypno/spider/grammar_arc.y b/engines/hypno/grammar_arc.y
similarity index 97%
rename from engines/hypno/spider/grammar_arc.y
rename to engines/hypno/grammar_arc.y
index a7b49119b4..d3a9d92332 100644
--- a/engines/hypno/spider/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -21,8 +21,8 @@
  */
 
 %require "3.0"
-%defines "engines/hypno/spider/tokens_arc.h"
-%output "engines/hypno/spider/grammar_arc.cpp"
+%defines "engines/hypno/tokens_arc.h"
+%output "engines/hypno/grammar_arc.cpp"
 %define api.prefix {HYPNO_ARC_}
 
 %{
diff --git a/engines/hypno/spider/grammar_mis.y b/engines/hypno/grammar_mis.y
similarity index 98%
rename from engines/hypno/spider/grammar_mis.y
rename to engines/hypno/grammar_mis.y
index 5526120bad..3a249656f1 100644
--- a/engines/hypno/spider/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -21,8 +21,8 @@
  */
 
 %require "3.0"
-%defines "engines/hypno/spider/tokens_mis.h"
-%output "engines/hypno/spider/grammar_mis.cpp"
+%defines "engines/hypno/tokens_mis.h"
+%output "engines/hypno/grammar_mis.cpp"
 %define api.prefix {HYPNO_MIS_}
 
 %{
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 286cd273f6..c6acd11a09 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -29,18 +29,17 @@
 #include "common/error.h"
 #include "common/events.h"
 #include "common/file.h"
+#include "common/memstream.h"
 #include "common/savefile.h"
 #include "common/str.h"
 #include "common/system.h"
 #include "common/timer.h"
 #include "common/tokenizer.h"
-#include "common/memstream.h"
 #include "engines/util.h"
 #include "image/bmp.h"
 
-
-#include "hypno/hypno.h"
 #include "hypno/grammar.h"
+#include "hypno/hypno.h"
 
 namespace Hypno {
 
@@ -55,7 +54,7 @@ MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent,
 	loop = _loop;
 }
 
-const static char* levelVariables[] = {
+const static char *levelVariables[] = {
 	"GS_NONE",
 	"GS_SCTEXT",
 	"GS_AMBIENT",
@@ -82,15 +81,14 @@ const static char* levelVariables[] = {
 	"GS_COMBATJSON",
 	"GS_COMBATLEVEL",
 	"GS_PUZZLELEVEL",
-	NULL
-};
+	NULL};
 
 extern int parse_mis(const char *);
 extern int parse_arc(const char *);
 
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	: Engine(syst), _gameDescription(gd), _image(nullptr),
-	  _compositeSurface(nullptr), _transparentColor(0), 
+	  _compositeSurface(nullptr), _transparentColor(0),
 	  _nextHotsToAdd(nullptr), _nextHotsToRemove(nullptr),
 	  _screenW(640), _screenH(480) {
 	_rnd = new Common::RandomSource("hypno");
@@ -104,7 +102,7 @@ HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	Level quit;
 	Hotspots hs;
 	hs.push_back(q);
-	quit.scene.hots = hs;  
+	quit.scene.hots = hs;
 	_levels["<quit>"] = quit;
 }
 
@@ -119,12 +117,12 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 
 void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	debug("Parsing %s", filename.c_str());
-    filename = convertPath(filename);
+	filename = convertPath(filename);
 	if (!prefix.empty())
-		filename = prefix + "/" + filename; 
+		filename = prefix + "/" + filename;
 	Common::File *test = new Common::File();
 	assert(isDemo());
-    assert(test->open(filename.c_str()));
+	assert(test->open(filename.c_str()));
 
 	const uint32 fileSize = test->size();
 	char *buf = (char *)malloc(fileSize + 1);
@@ -133,7 +131,7 @@ void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	parse_mis(buf);
 	Level level;
 	level.scene.prefix = prefix;
-	level.scene.hots = *g_parsedHots; 
+	level.scene.hots = *g_parsedHots;
 	_levels[filename] = level;
 	debug("Loaded hots size: %d", g_parsedHots->size());
 }
@@ -141,7 +139,7 @@ void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 void HypnoEngine::loadLib(Common::String filename, LibData &r) {
 	debug("Loading %s", filename.c_str());
 	Common::File libfile;
-    assert(libfile.open(filename));
+	assert(libfile.open(filename));
 	uint32 i = 0;
 	Common::String entry = "<>";
 	FileData f;
@@ -200,7 +198,7 @@ ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String da
 	Common::String n;
 	ShootInfo si;
 	ShootSequence seq;
-	while(!tok.empty()) {
+	while (!tok.empty()) {
 		t = tok.nextToken();
 		if (t[0] == '\n')
 			continue;
@@ -208,7 +206,7 @@ ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String da
 		//debug("t: %s, n: %s", t.c_str(), n.c_str());
 		if (t == "Z")
 			break;
-		
+
 		Common::replace(n, "\nS", "");
 		Common::replace(n, "\nZ\n", "");
 		si.name = n;
@@ -217,13 +215,12 @@ ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String da
 		debug("%d -> %s", si.timestamp, si.name.c_str());
 	}
 	return seq;
-
 }
 
 void HypnoEngine::parseArcadeShooting(Common::String prefix, Common::String name, Common::String data) {
 	parse_arc(data.c_str());
 	Level level;
-	level.arcade = g_parsedArc;  
+	level.arcade = g_parsedArc;
 	level.arcade.prefix = prefix;
 	_levels[name] = level;
 	g_parsedArc.background.clear();
@@ -240,7 +237,7 @@ Common::Error HypnoEngine::run() {
 	Graphics::ModeList modes;
 	modes.push_back(Graphics::Mode(640, 480));
 	modes.push_back(Graphics::Mode(320, 200));
-    initGraphicsModes(modes);
+	initGraphicsModes(modes);
 
 	// Initialize graphics
 	initGraphics(_screenW, _screenH, nullptr);
@@ -273,7 +270,6 @@ Common::Error HypnoEngine::run() {
 			_nextLevel = "";
 			runLevel(_currentLevel);
 		}
-			
 	}
 	return Common::kNoError;
 }
@@ -291,32 +287,30 @@ void HypnoEngine::runLevel(Common::String name) {
 			MVideo v(*it, Common::Point(0, 0), false, true, false);
 			runIntro(v);
 		}
-			
 
 	} else if (!_levels[name].arcade.background.empty()) {
 		_prefixDir = _levels[name].arcade.prefix;
 		if (!_levels[name].arcade.intro.empty()) {
-			MVideo v(_levels[name].arcade.intro, Common::Point(0,0), false, true, false);
+			MVideo v(_levels[name].arcade.intro, Common::Point(0, 0), false, true, false);
 			runIntro(v);
 		}
 		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
 	} else if (!_levels[name].puzzle.name.empty()) {
 		if (!_levels[name].arcade.intro.empty()) {
-			MVideo v(_levels[name].arcade.intro, Common::Point(0,0), false, true, false);
+			MVideo v(_levels[name].arcade.intro, Common::Point(0, 0), false, true, false);
 			runIntro(v);
 		}
 		runPuzzle(_levels[name].puzzle);
 	} else {
 		_prefixDir = _levels[name].scene.prefix;
 		if (!_levels[name].scene.intro.empty()) {
-			MVideo v(_levels[name].scene.intro , Common::Point(0,0), false, true, false);
+			MVideo v(_levels[name].scene.intro, Common::Point(0, 0), false, true, false);
 			runIntro(v);
 		}
-		changeScreenMode("scene"); 
+		changeScreenMode("scene");
 		runScene(_levels[name].scene);
 	}
-
 }
 
 void HypnoEngine::runScene(Scene scene) {
@@ -325,13 +319,13 @@ void HypnoEngine::runScene(Scene scene) {
 	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> videosToRemove;
-	
+
 	stack.clear();
 	_nextHotsToAdd = &scene.hots;
 	defaultCursor();
 
 	while (!shouldQuit() && _nextLevel.empty()) {
-		
+
 		while (g_system->getEventManager()->pollEvent(event)) {
 			mousePos = g_system->getEventManager()->getMousePos();
 			// Events
@@ -344,7 +338,7 @@ void HypnoEngine::runScene(Scene scene) {
 					}
 					_videosPlaying.clear();
 
-					if (!stack.empty()) { 
+					if (!stack.empty()) {
 						runMenu(*stack.back());
 						drawScreen();
 					}
@@ -359,21 +353,21 @@ void HypnoEngine::runScene(Scene scene) {
 			case Common::EVENT_RBUTTONDOWN:
 				if (stack.empty())
 					break;
-				if (!_conversation.empty()){
+				if (!_conversation.empty()) {
 					rightClickedConversation(mousePos);
 					break;
 				}
-			break;
+				break;
 
 			case Common::EVENT_LBUTTONDOWN:
 				if (stack.empty())
 					break;
-				if (!_conversation.empty()){
+				if (!_conversation.empty()) {
 					leftClickedConversation(mousePos);
 					break;
 				}
 				if (!_nextHotsToAdd || !_nextHotsToRemove)
-				 	clickedHotspot(mousePos);
+					clickedHotspot(mousePos);
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
@@ -428,31 +422,29 @@ void HypnoEngine::runScene(Scene scene) {
 				}
 			}
 			i++;
-
 		}
 		if (videosToRemove.size() > 0) {
 
-			for(Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
-				debug("removing %d from %d size", *it, _videosPlaying.size()); 
+			for (Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
+				debug("removing %d from %d size", *it, _videosPlaying.size());
 				_videosPlaying.remove_at(*it);
 			}
 
 			// Nothing else to play
-			if (_videosPlaying.size() == 0 && _nextSequentialVideoToPlay.size() == 0){
+			if (_videosPlaying.size() == 0 && _nextSequentialVideoToPlay.size() == 0) {
 				if (!_conversation.empty())
 					_refreshConversation = true;
-				else if (!stack.empty()) { 
+				else if (!stack.empty()) {
 					runMenu(*stack.back());
 					drawScreen();
 				}
 			}
-
 		}
 
 		if (_videosPlaying.size() > 0 || _nextSequentialVideoToPlay.size() > 0) {
 			drawScreen();
 			continue;
-		} 
+		}
 
 		if (_nextHotsToRemove) {
 			debug("Removing a hotspot list!");
@@ -474,7 +466,6 @@ void HypnoEngine::runScene(Scene scene) {
 			playSound(_music, 0);
 		}
 
-
 		if (checkLevelCompleted())
 			_nextLevel = "mis/demo.mis";
 
@@ -489,7 +480,7 @@ void HypnoEngine::runIntro(MVideo &video) {
 	playVideo(video);
 
 	while (!shouldQuit() && video.decoder) {
-			while (g_system->getEventManager()->pollEvent(event)) {
+		while (g_system->getEventManager()->pollEvent(event)) {
 			// Events
 			switch (event.type) {
 			case Common::EVENT_KEYDOWN:
@@ -517,7 +508,7 @@ void HypnoEngine::runIntro(MVideo &video) {
 	}
 }
 
-void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Not implemented"); } 
+void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Not implemented"); }
 
 //Actions
 
@@ -529,13 +520,13 @@ void HypnoEngine::runMenu(Hotspots hs) {
 	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
 		Action *action = *itt;
 		if (typeid(*action) == typeid(Quit))
-			runQuit((Quit*) action);
+			runQuit((Quit *)action);
 		else if (typeid(*action) == typeid(Background))
-			runBackground((Background*) action);
+			runBackground((Background *)action);
 		else if (typeid(*action) == typeid(Overlay))
-			runOverlay((Overlay*) action);
+			runOverlay((Overlay *)action);
 		else if (typeid(*action) == typeid(Ambient))
-			runAmbient((Ambient*) action);
+			runAmbient((Ambient *)action);
 
 		//else if (typeid(*action) == typeid(Mice))
 		//	runMice(h, (Mice*) action);
@@ -560,11 +551,11 @@ void HypnoEngine::runOverlay(Overlay *a) {
 }
 
 void HypnoEngine::runMice(Mice *a) {
-    changeCursor(a->path, a->index);
+	changeCursor(a->path, a->index);
 }
 
 void HypnoEngine::runEscape(Escape *a) {
-    _nextHotsToRemove = stack.back();
+	_nextHotsToRemove = stack.back();
 }
 
 void HypnoEngine::runCutscene(Cutscene *a) {
@@ -574,7 +565,7 @@ void HypnoEngine::runCutscene(Cutscene *a) {
 }
 
 void HypnoEngine::runGlobal(Global *a) {
-    if (a->command == "TURNON")
+	if (a->command == "TURNON")
 		_levelState[a->variable] = 1;
 	else if (a->command == "TURNOFF")
 		_levelState[a->variable] = 0;
@@ -588,7 +579,7 @@ void HypnoEngine::runPlay(Play *a) {
 	Common::Point origin = a->origin;
 
 	if (a->flag == "/BITMAP")
-			loadImage(a->path, origin.x, origin.y, false);
+		loadImage(a->path, origin.x, origin.y, false);
 	else {
 		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
 	}
@@ -597,7 +588,7 @@ void HypnoEngine::runPlay(Play *a) {
 void HypnoEngine::runAmbient(Ambient *a) {
 	Common::Point origin = a->origin;
 	if (a->flag == "/BITMAP")
-			loadImage(a->path, origin.x, origin.y, false);
+		loadImage(a->path, origin.x, origin.y, false);
 	else {
 		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, a->fullscreen, a->flag == "/LOOP"));
 	}
@@ -608,8 +599,8 @@ void HypnoEngine::runWalN(WalN *a) {
 		return;
 	Common::Point origin = a->origin;
 	if (a->flag == "/BITMAP")
-			loadImage(a->path, origin.x, origin.y, false);
-	else { 
+		loadImage(a->path, origin.x, origin.y, false);
+	else {
 		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
 	}
 }
@@ -663,25 +654,24 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
 			if (typeid(*action) == typeid(ChangeLevel))
-				runChangeLevel((ChangeLevel*) action);
+				runChangeLevel((ChangeLevel *)action);
 			if (typeid(*action) == typeid(Escape))
-				runEscape((Escape*) action);
+				runEscape((Escape *)action);
 			else if (typeid(*action) == typeid(Cutscene))
-				runCutscene((Cutscene*) action);
+				runCutscene((Cutscene *)action);
 			else if (typeid(*action) == typeid(Play))
-				runPlay((Play*) action);
+				runPlay((Play *)action);
 			else if (typeid(*action) == typeid(WalN))
-				runWalN((WalN*) action);
+				runWalN((WalN *)action);
 			else if (typeid(*action) == typeid(Global))
-				runGlobal((Global*) action);
+				runGlobal((Global *)action);
 			else if (typeid(*action) == typeid(Talk))
-				runTalk((Talk*) action);
+				runTalk((Talk *)action);
 			else if (typeid(*action) == typeid(Quit))
-				runQuit((Quit*) action);
+				runQuit((Quit *)action);
 			else if (typeid(*action) == typeid(Palette))
 				debug("runPalette unimplemented");
 		}
-
 	}
 }
 
@@ -715,7 +705,7 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
 			if (typeid(*action) == typeid(Mice))
-				runMice((Mice*) action);
+				runMice((Mice *)action);
 		}
 		return true;
 	}
@@ -724,13 +714,13 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 
 void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
 	Graphics::Surface *surf = decodeFrame(name, 0);
-	drawImage(*surf, x , y, transparent);
+	drawImage(*surf, x, y, transparent);
 }
 
 void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transparent) {
 	if (transparent)
 		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), _transparentColor);
-	else 
+	else
 		_compositeSurface->blitFrom(surf, Common::Point(x, y));
 }
 
@@ -747,7 +737,7 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
 
-    for(int f = 0; f < n; f++) 
+	for (int f = 0; f < n; f++)
 		vd.decodeNextFrame();
 
 	const Graphics::Surface *frame = vd.decodeNextFrame();
@@ -811,24 +801,21 @@ void HypnoEngine::updateScreen(MVideo &video) {
 		cframe = sframe->convertTo(_pixelFormat, video.decoder->getPalette());
 	} else
 		cframe = frame->convertTo(_pixelFormat, video.decoder->getPalette());
-	
+
 	if (video.transparent)
 		_compositeSurface->transBlitFrom(*cframe, video.position, _transparentColor);
 	else
 		_compositeSurface->blitFrom(*cframe, video.position);
 
-
-	if (video.scaled) { 
+	if (video.scaled) {
 		sframe->free();
 		delete sframe;
 	}
 
 	cframe->free();
 	delete cframe;
-
 }
 
-
 void HypnoEngine::drawScreen() {
 	g_system->copyRectToScreen(_compositeSurface->getPixels(), _compositeSurface->pitch, 0, 0, _screenW, _screenH);
 	g_system->updateScreen();
@@ -871,14 +858,13 @@ void HypnoEngine::playSound(Common::String name, uint32 loops) {
 	Audio::LoopingAudioStream *stream;
 
 	for (LibData::iterator it = _soundFiles.begin(); it != _soundFiles.end(); ++it) {
-			if (it->name == name) {
-				raw = new ByteArray(it->data);
-				stream = new Audio::LoopingAudioStream(Audio::makeRawStream(raw->data(), raw->size(), 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
-				_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
-				break;
-			}
+		if (it->name == name) {
+			raw = new ByteArray(it->data);
+			stream = new Audio::LoopingAudioStream(Audio::makeRawStream(raw->data(), raw->size(), 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
+			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
+			break;
+		}
 	}
-
 }
 
 void HypnoEngine::stopSound() {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 890d08766a..01f8061d8c 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -23,15 +23,15 @@
 #ifndef HYPNO_H
 #define HYPNO_H
 
+#include "common/array.h"
 #include "common/installshieldv3_archive.h"
 #include "common/random.h"
-#include "common/str-array.h"
-#include "common/array.h"
 #include "common/serializer.h"
+#include "common/str-array.h"
 #include "engines/engine.h"
-#include "graphics/managed_surface.h"
 #include "graphics/font.h"
 #include "graphics/fontman.h"
+#include "graphics/managed_surface.h"
 
 #include "hypno/grammar.h"
 
@@ -115,7 +115,7 @@ public:
 	bool canLoadGameStateCurrently() override {
 		return true;
 	}
-	bool canSaveAutosaveCurrently() override  {
+	bool canSaveAutosaveCurrently() override {
 		return false;
 	}
 	bool canSaveGameStateCurrently() override {
@@ -142,7 +142,7 @@ public:
 	// Actions
 	void runIntro(MVideo &video);
 	void runMenu(Hotspots hs);
-    void runBackground(Background *a);
+	void runBackground(Background *a);
 	void runOverlay(Overlay *a);
 	void runMice(Mice *a);
 	void runEscape(Escape *a);
@@ -167,7 +167,7 @@ public:
 	// intros
 	Common::HashMap<Common::String, Videos> _intros;
 
-	// levels 
+	// levels
 	Common::String _nextLevel;
 	Common::String _currentLevel;
 
@@ -216,10 +216,9 @@ public:
 	WetEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
-	
+
 	void drawPlayer(Common::String player, MVideo &background) override;
 	void drawHealth(const Graphics::Font &font) override;
-
 };
 
 class SpiderEngine : public HypnoEngine {
@@ -227,7 +226,7 @@ public:
 	SpiderEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
-	
+
 	void drawPlayer(Common::String player, MVideo &background) override;
 	void drawHealth(const Graphics::Font &font) override;
 	void runPuzzle(Puzzle puzzle) override;
diff --git a/engines/hypno/spider/lexer_arc.l b/engines/hypno/lexer_arc.l
similarity index 97%
rename from engines/hypno/spider/lexer_arc.l
rename to engines/hypno/lexer_arc.l
index c831118bb1..e91cc1201d 100644
--- a/engines/hypno/spider/lexer_arc.l
+++ b/engines/hypno/lexer_arc.l
@@ -22,10 +22,11 @@
 
 %option noyywrap
 %option noinput
+%option nounput
 %option yylineno
 %option never-interactive
 
-%option outfile="engines/hypno/spider/lexer_arc.cpp"
+%option outfile="engines/hypno/lexer_arc.cpp"
 %option prefix="HYPNO_ARC_"
 
 %{
diff --git a/engines/hypno/spider/lexer_mis.l b/engines/hypno/lexer_mis.l
similarity index 98%
rename from engines/hypno/spider/lexer_mis.l
rename to engines/hypno/lexer_mis.l
index ecef309710..b2b5f89c09 100644
--- a/engines/hypno/spider/lexer_mis.l
+++ b/engines/hypno/lexer_mis.l
@@ -22,10 +22,11 @@
 
 %option noyywrap
 %option noinput
+%option nounput
 %option yylineno
 %option never-interactive
 
-%option outfile="engines/hypno/spider/lexer_mis.cpp"
+%option outfile="engines/hypno/lexer_mis.cpp"
 %option prefix="HYPNO_MIS_"
 
 %{
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index c4e4b9a495..9041a87032 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -37,15 +37,14 @@ public:
 
 Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
 	debug("gameid: %s", desc->gameId);
-    if (Common::String(desc->gameId) == "wetlands") {
-		*engine = (Engine*) new Hypno::WetEngine(syst, desc);
+	if (Common::String(desc->gameId) == "wetlands") {
+		*engine = (Engine *)new Hypno::WetEngine(syst, desc);
 	} else if (Common::String(desc->gameId) == "sinister-six") {
-		*engine = (Engine*) new Hypno::SpiderEngine(syst, desc);
-	} 
-	else 
+		*engine = (Engine *)new Hypno::SpiderEngine(syst, desc);
+	} else
 		return Common::kUnsupportedGameidError;
 
-    return Common::kNoError;
+	return Common::kNoError;
 }
 
 namespace Hypno {
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index 4619648cf4..cfb54fcc02 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -4,11 +4,11 @@ MODULE_OBJS := \
 	cursors.o \
 	metaengine.o \
 	arcade.o \
+	lexer_mis.o \
+	grammar_mis.o \
+	lexer_arc.o \
+	grammar_arc.o \
 	spider/spider.o \
-	spider/lexer_mis.o \
-	spider/grammar_mis.o \
-	spider/lexer_arc.o \
-	spider/grammar_arc.o \
 	spider/talk.o \
 	spider/arcade.o \
 	wet/wet.o \
@@ -21,8 +21,10 @@ MODULE_DIRS += \
 # HACK: Skip this when including the file for detection objects.
 ifeq "$(USE_RULES)" "1"
 hypno-grammar:
-	flex engines/hypno/lexer.l
-	bison engines/hypno/grammar.y
+	flex engines/hypno/lexer_arc.l
+	bison engines/hypno/grammar_arc.y
+	flex engines/hypno/lexer_mis.l
+	bison engines/hypno/grammar_mis.y
 endif
 
 # This module can be built as a plugin
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 640ed1cd30..1a2c3480dd 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -1,5 +1,5 @@
-#include "hypno/hypno.h"
 #include "hypno/grammar.h"
+#include "hypno/hypno.h"
 
 #include "common/events.h"
 #include "graphics/cursorman.h"
@@ -23,7 +23,7 @@ void SpiderEngine::drawHealth(const Graphics::Font &font) {
 	r = Common::Rect(256, 152 + d, 272, 174);
 	if (d >= 11)
 		c = _pixelFormat.RGBToColor(255, 0, 0);
-	else 
+	else
 		c = _pixelFormat.RGBToColor(32, 208, 32);
 
 	_compositeSurface->fillRect(r, c);
@@ -35,5 +35,4 @@ void SpiderEngine::drawHealth(const Graphics::Font &font) {
 	font.drawString(_compositeSurface, "ENERGY", 248, 180, 38, c);
 }
 
-
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index b90f3418f8..f88fb8e178 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -1,5 +1,5 @@
-#include "hypno/hypno.h"
 #include "hypno/grammar.h"
+#include "hypno/hypno.h"
 
 #include "common/events.h"
 
@@ -8,7 +8,7 @@ namespace Hypno {
 SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void SpiderEngine::loadAssets() {
-	LibData files; 
+	LibData files;
 	loadLib("sixdemo/c_misc/missions.lib", files);
 	uint32 i = 0;
 	uint32 j = 0;
@@ -23,7 +23,7 @@ void SpiderEngine::loadAssets() {
 	Common::String arc;
 	Common::String list;
 
-	debug("Splitting file: %s",files[0].name.c_str());
+	debug("Splitting file: %s", files[0].name.c_str());
 	for (i = 0; i < files[0].data.size(); i++) {
 		arc += files[0].data[i];
 		if (files[0].data[i] == 'X') {
@@ -37,7 +37,7 @@ void SpiderEngine::loadAssets() {
 		}
 	}
 
-	Common::String arclevel = files[0].name; 
+	Common::String arclevel = files[0].name;
 	parseArcadeShooting("sixdemo", arclevel, arc);
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 
@@ -57,12 +57,12 @@ void SpiderEngine::loadAssets() {
 
 	cl = new ChangeLevel();
 	cl->level = "sixdemo/puz_matr";
-	_levels["sixdemo/mis/demo.mis"].scene.hots[3].actions.push_back(cl);	
+	_levels["sixdemo/mis/demo.mis"].scene.hots[3].actions.push_back(cl);
 
 	cl = new ChangeLevel();
 	cl->level = "sixdemo/mis/shoctalk.mis";
 	_levels["sixdemo/mis/demo.mis"].scene.hots[4].actions.push_back(cl);
-	
+
 	cl = new ChangeLevel();
 	cl->level = "sixdemo/mis/order.mis";
 	_levels["sixdemo/mis/demo.mis"].scene.hots[5].actions.push_back(cl);
@@ -84,14 +84,13 @@ void SpiderEngine::loadAssets() {
 	matrix.puzzle.intros.push_back("spiderman/demo/aleyc01s.smk");
 	matrix.puzzle.levelIfWin = "sixdemo/mis/demo.mis";
 	matrix.puzzle.levelIfLose = "sixdemo/mis/demo.mis";
-	_levels["sixdemo/puz_matr"] = matrix; 
-
+	_levels["sixdemo/puz_matr"] = matrix;
 }
 
 void SpiderEngine::runPuzzle(Puzzle puzzle) {
 	if (puzzle.name == "sixdemo/puz_matr")
 		runMatrix(puzzle);
-	else 
+	else
 		error("invalid puzzle");
 }
 
@@ -101,16 +100,16 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 
 	defaultCursor();
 	bool data[10][10] = {};
-	bool solution[10][10] = { 
-		{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},  
-		{0, 0, 1, 1, 1, 1, 1, 1, 0, 0},  
-		{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},  
-		{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},  
-		{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},  
-		{0, 0, 1, 1, 1, 1, 1, 1, 0, 0},  
-		{0, 0, 1, 1, 0, 0, 1, 1, 0, 0},  
-		{0, 0, 1, 1, 0, 0, 1, 1, 0, 0},  
-		{0, 0, 0, 1, 0, 0, 1, 0, 0, 0}, 
+	bool solution[10][10] = {
+		{0, 0, 0, 1, 1, 1, 1, 0, 0, 0},
+		{0, 0, 1, 1, 1, 1, 1, 1, 0, 0},
+		{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},
+		{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
+		{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},
+		{0, 0, 1, 1, 1, 1, 1, 1, 0, 0},
+		{0, 0, 1, 1, 0, 0, 1, 1, 0, 0},
+		{0, 0, 1, 1, 0, 0, 1, 1, 0, 0},
+		{0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
 		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 	};
 	Common::Rect matrix(175, 96, 461, 385);
@@ -124,7 +123,7 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 	MVideo v("sixdemo/puz_matr/matintro.smk", Common::Point(0, 0), false, false, false);
 	playVideo(v);
 	while (!shouldQuit()) {
-		
+
 		while (g_system->getEventManager()->pollEvent(event)) {
 			mousePos = g_system->getEventManager()->getMousePos();
 			// Events
@@ -139,7 +138,7 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 				if (matrix.contains(mousePos)) {
 					x = (mousePos.x - 175) / 29;
 					y = (mousePos.y - 96) / 29;
-					cell.moveTo(175 + 29*x + 1, 96 + 29*y + 1);
+					cell.moveTo(175 + 29 * x + 1, 96 + 29 * y + 1);
 					_compositeSurface->fillRect(cell, data[x][y] ? deactiveColor : activeColor);
 					data[x][y] = !data[x][y];
 				}
@@ -161,18 +160,17 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 			if (!found)
 				break;
 		}
-				
+
 		if (found) {
 			playSound("sixdemo/demo/sound.lib/matrix_2.raw", 1);
 			_nextLevel = puzzle.levelIfWin;
 			return;
-		} 
+		}
 
 		if (v.decoder->needsUpdate()) {
 			updateScreen(v);
 		}
 
-
 		drawScreen();
 		g_system->delayMillis(10);
 	}
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index e9512f9fec..4b8c47b709 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -1,5 +1,5 @@
-#include "hypno/hypno.h"
 #include "hypno/grammar.h"
+#include "hypno/hypno.h"
 
 #include "common/events.h"
 #include "graphics/cursorman.h"
@@ -9,7 +9,7 @@ namespace Hypno {
 void WetEngine::drawPlayer(Common::String player, MVideo &background) {
 	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
 	Graphics::Surface *image = decodeFrame(player, background.decoder->getCurFrame() % 3);
-	drawImage(*image, 0, 200-image->h+1, true);
+	drawImage(*image, 0, 200 - image->h + 1, true);
 	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
 	image->free();
 	delete image;
@@ -18,11 +18,10 @@ void WetEngine::drawPlayer(Common::String player, MVideo &background) {
 void WetEngine::drawHealth(const Graphics::Font &font) {
 	//Common::Rect r;
 	uint32 c;
-	int p = (100 *  _health) / _maxHealth;
+	int p = (100 * _health) / _maxHealth;
 	c = _pixelFormat.RGBToColor(252, 252, 0);
 	font.drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), 70, 160, 65, c);
 	font.drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), 180, 160, 71, c);
-
 }
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 1a8d303662..0c3e1aa5bb 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -1,12 +1,12 @@
-#include "hypno/hypno.h"
 #include "hypno/grammar.h"
+#include "hypno/hypno.h"
 
 namespace Hypno {
 
 WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void WetEngine::loadAssets() {
-	LibData files; 
+	LibData files;
 	loadLib("wetlands/c_misc/missions.lib", files);
 	uint32 i = 0;
 	uint32 j = 0;
@@ -25,7 +25,7 @@ void WetEngine::loadAssets() {
 	a->path = "movie/selector.smk";
 	a->fullscreen = true;
 	a->flag = "/LOOP";
-	a->origin = Common::Point(0, 0); 
+	a->origin = Common::Point(0, 0);
 	h.actions.push_back(a);
 
 	hs.push_back(h);
@@ -46,7 +46,7 @@ void WetEngine::loadAssets() {
 
 	hs.push_back(h);
 
-	start.scene.hots = hs;  
+	start.scene.hots = hs;
 	_levels["<start>"] = start;
 
 	Level intro;
@@ -61,7 +61,7 @@ void WetEngine::loadAssets() {
 		list.clear();
 		arclevel = files[k].name;
 
-		debug("Parsing %s",arclevel.c_str());
+		debug("Parsing %s", arclevel.c_str());
 		for (i = 0; i < files[k].data.size(); i++) {
 			arc += files[k].data[i];
 			if (files[k].data[i] == 'X') {
@@ -79,11 +79,10 @@ void WetEngine::loadAssets() {
 		_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 		_levels[arclevel].arcade.prefix = "wetlands";
 		_levels[arclevel].arcade.levelIfLose = "<gameover>";
-		if (k < files.size()-1)
-			_levels[arclevel].arcade.levelIfWin = files[k+1].name;
+		if (k < files.size() - 1)
+			_levels[arclevel].arcade.levelIfWin = files[k + 1].name;
 	}
 
-
 	debug("%s", arc.c_str());
 	debug("------------------------------------");
 
@@ -92,7 +91,6 @@ void WetEngine::loadAssets() {
 	over.trans.intros.push_back("movie/gameover.smk");
 	_levels["<gameover>"] = over;
 
-
 	loadLib("wetlands/c_misc/fonts.lib", _fontFiles);
 	loadLib("wetlands/c_misc/sound.lib", _soundFiles);
 }


Commit: b5afc381b35354fb6469064418d563b39cdb35c9
    https://github.com/scummvm/scummvm/commit/b5afc381b35354fb6469064418d563b39cdb35c9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved parsing and sound in arcade sequences

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar_arc.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/lexer_arc.l
    engines/hypno/lexer_mis.l
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/spider/talk.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 8d9c4ea4dc..113df8056f 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -14,6 +14,7 @@ void HypnoEngine::drawShoot(Common::Point target) {
 	_compositeSurface->drawLine(80, 155, target.x, target.y + 1, c);
 	_compositeSurface->drawLine(80, 155, target.x, target.y, c);
 	_compositeSurface->drawLine(80, 155, target.x, target.y - 1, c);
+	playSound("c_misc/sound.lib/" + _shootSound, 1);
 }
 
 void HypnoEngine::runArcade(ArcadeShooting arc) {
@@ -23,6 +24,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 	Common::Point mousePos;
 	Common::List<uint32> shootsToRemove;
 	ShootSequence shootSequence = arc.shootSequence;
+	_shootSound = arc.shootSound;
 	_health = arc.health;
 	_maxHealth = _health;
 	_shoots.clear();
@@ -76,11 +78,12 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			if (si.timestamp <= background.decoder->getCurFrame()) {
 				shootSequence.pop_front();
 				for (Shoots::iterator it = arc.shoots.begin(); it != arc.shoots.end(); ++it) {
-					if (it->name == si.name && it->name != "NONE") {
+					if (it->name == si.name && it->animation != "NONE") {
 						Shoot s = *it;
 						s.video = new MVideo(it->animation, it->position, true, false, false);
 						playVideo(*s.video);
 						_shoots.push_back(s);
+						playSound("c_misc/sound.lib/" + s.startSound, 1);
 					}
 				}
 			}
@@ -94,7 +97,6 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				int frame = it->video->decoder->getCurFrame();
 				if (frame > 0 && frame >= it->explosionFrame - 3 && !it->destroyed) {
 					_health = _health - it->damage;
-					debug("healt: %d", _health);
 					skipVideo(*it->video);
 				} else if (it->video->decoder->endOfVideo()) {
 					skipVideo(*it->video);
@@ -113,7 +115,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		}
 
 		if (_music.empty()) {
-			_music = "c_misc/sound.lib/" + arc.sounds.front();
+			_music = "c_misc/sound.lib/" + arc.music;
 			playSound(_music, 0);
 		}
 
@@ -143,6 +145,7 @@ bool HypnoEngine::clickedShoot(Common::Point mousePos) {
 			uint32 c = it->video->currentFrame->getPixel(x, y);
 			//debug("inside %x", c);
 			if (c > 0) {
+				playSound("c_misc/sound.lib/" + it->endSound, 1);
 				it->destroyed = true;
 				it->video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
 				it->video->decoder->forceSeekToFrame(it->explosionFrame + 2);
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 4bbb639eaf..d0a5a2847d 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -173,7 +173,9 @@ class ChangeLevel : public Action {
 class Shoot {
   public:
     Common::String name;
-	Common::String animation;
+	Filename animation;
+	Filename startSound;
+	Filename endSound;
 	Common::Point position;
 	int damage;
 	MVideo *video = nullptr;
@@ -186,11 +188,11 @@ typedef Common::Array<Shoot> Shoots;
 class ShootInfo {
   public:
     Common::String name;
-	uint32 timestamp; 
+	uint32 timestamp;
 };
 
 typedef Common::List<ShootInfo> ShootSequence;
-typedef Common::List<Common::String> Sounds;
+typedef Common::Array<Common::String> Sounds;
 
 class Transition {
   public:
@@ -229,7 +231,9 @@ class ArcadeShooting {
 	int health;
 	Shoots shoots;
 	ShootSequence shootSequence;
-	Sounds sounds;
+	Filename shootSound;
+	Filename hitSound;
+	Filename music;
 };
 
 class Level {
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index d3a9d92332..9751a36f3f 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -57,11 +57,11 @@ using namespace Hypno;
 	int i;	 /* integer value */
 }
 
-%token<s> NAME FILENAME BNTOK
+%token<s> NAME FILENAME BNTOK SNTOK
 %token<i> NUM
 // header
 %token YXTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
-%token PTOK FTOK TTOK TPTOK ATOK VTOK OTOK O1TOK NTOK RTOK ITOK SNTOK ZTOK
+%token PTOK FTOK TTOK TPTOK ATOK VTOK OTOK O1TOK NTOK RTOK ITOK ZTOK
 
 // body
 %token FNTOK NONETOK A0TOK K0TOK P0TOK WTOK
@@ -74,13 +74,13 @@ using namespace Hypno;
 
 %%
 
-start:  YXTOK header body
+start: YXTOK header body
       ;
 
 
 header:  hline RETTOK header
        | hline
-	   | RETTOK header          
+	   | RETTOK header      
 	   ; 
 
 hline:  CTOK NUM  { debug("C %d", $2); }
@@ -117,7 +117,11 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 		  debug("BN %s", $2); 
 		}
 	  | SNTOK FILENAME enc {
-		  g_parsedArc.sounds.push_back($2); 
+		  if (Common::String("S0") == $1)
+		  	g_parsedArc.music = $2;
+		  else if (Common::String("S1") == $1)
+		  	g_parsedArc.shootSound = $2;
+		   
 		  debug("SN %s", $2); 
 		}
 	  | HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
@@ -182,7 +186,13 @@ bline: FNTOK FILENAME {
 		 shoot->damage = $2;
 		 debug("D %d", $2); 
 		}
-	 | SNTOK FILENAME enc { debug("SN %s", $2); }
+	 | SNTOK FILENAME enc { 
+		  if (Common::String("S1") == $1)
+		  	shoot->endSound = $2;
+		  else if (Common::String("S2") == $1)
+		  	shoot->startSound = $2;
+		 
+		 debug("SN %s", $2); }
 	 | NTOK { debug("N"); }
 	 | ZTOK {
 		g_parsedArc.shoots.push_back(*shoot); 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index c6acd11a09..ea3f6527d0 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -718,8 +718,9 @@ void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool trans
 }
 
 void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transparent) {
-	if (transparent)
-		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), _transparentColor);
+	if (transparent) {
+		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), surf.getPixel(0, 0));
+	}
 	else
 		_compositeSurface->blitFrom(surf, Common::Point(x, y));
 }
@@ -737,6 +738,8 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
 
+	//debug("decoding %s with %d frames", path.c_str(), vd.getFrameCount());
+
 	for (int f = 0; f < n; f++)
 		vd.decodeNextFrame();
 
@@ -853,7 +856,10 @@ void HypnoEngine::skipVideo(MVideo &video) {
 
 void HypnoEngine::playSound(Common::String name, uint32 loops) {
 
-	debug("playing %s", name.c_str());
+	name = convertPath(name);
+	if (!_prefixDir.empty())
+		name = _prefixDir + "/" + name;
+	debug("trying to play %s", name.c_str());
 	ByteArray *raw;
 	Audio::LoopingAudioStream *stream;
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 01f8061d8c..c2150ebe7f 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -66,7 +66,6 @@ class HypnoEngine : public Engine {
 private:
 	Common::RandomSource *_rnd;
 	Image::ImageDecoder *_image;
-	int _screenW, _screenH;
 
 public:
 	HypnoEngine(OSystem *syst, const ADGameDescription *gd);
@@ -156,6 +155,7 @@ public:
 	void runChangeLevel(ChangeLevel *a);
 
 	// Screen
+	int _screenW, _screenH;
 	Graphics::PixelFormat _pixelFormat;
 	void changeScreenMode(Common::String mode);
 	Graphics::ManagedSurface *_compositeSurface;
@@ -194,6 +194,7 @@ public:
 	virtual void drawHealth(const Graphics::Font &font);
 	int _health;
 	int _maxHealth;
+	Filename _shootSound;
 	Shoots _shoots;
 
 	// Conversation
diff --git a/engines/hypno/lexer_arc.l b/engines/hypno/lexer_arc.l
index e91cc1201d..85389117e6 100644
--- a/engines/hypno/lexer_arc.l
+++ b/engines/hypno/lexer_arc.l
@@ -35,7 +35,7 @@
 
 #include "hypno/hypno.h"
 #include "hypno/grammar.h"
-#include "hypno/spider/tokens_arc.h"
+#include "hypno/tokens_arc.h"
 
 %}
 
@@ -61,7 +61,7 @@ T							return TTOK;
 Tp							return TPTOK;
 F[0-9]						return FNTOK;
 F							return FTOK;
-S[0-9]						return SNTOK;
+S[0-9]						HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return SNTOK;
 A0							return A0TOK;
 B[0-9]						HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
 K0							return K0TOK;
diff --git a/engines/hypno/lexer_mis.l b/engines/hypno/lexer_mis.l
index b2b5f89c09..e361143180 100644
--- a/engines/hypno/lexer_mis.l
+++ b/engines/hypno/lexer_mis.l
@@ -35,7 +35,7 @@
 
 #include "hypno/hypno.h"
 #include "hypno/grammar.h"
-#include "hypno/spider/tokens_mis.h"
+#include "hypno/tokens_mis.h"
 
 %}
 
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 1a2c3480dd..cb52aa8d2d 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -8,7 +8,11 @@ namespace Hypno {
 
 void SpiderEngine::drawPlayer(Common::String player, MVideo &background) {
 	Common::Point mousePos = g_system->getEventManager()->getMousePos();
-	uint32 idx = mousePos.x / 50;
+	uint32 idx;
+	if (mousePos.y / (_screenH / 2) == 0)
+		idx = mousePos.x / (_screenW / 3);
+	else
+		idx = 5 - mousePos.x / (_screenW / 3);
 	Graphics::Surface *image = decodeFrame(player, idx);
 	drawImage(*image, 60, 129, true);
 	image->free();
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index f88fb8e178..1699afea15 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -36,7 +36,6 @@ void SpiderEngine::loadAssets() {
 			break; // No need to keep parsing, no more files are used in the demo
 		}
 	}
-
 	Common::String arclevel = files[0].name;
 	parseArcadeShooting("sixdemo", arclevel, arc);
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
@@ -66,7 +65,7 @@ void SpiderEngine::loadAssets() {
 	cl = new ChangeLevel();
 	cl->level = "sixdemo/mis/order.mis";
 	_levels["sixdemo/mis/demo.mis"].scene.hots[5].actions.push_back(cl);
-	_levels["sixdemo/mis/demo.mis"].scene.sound = "sixdemo/demo/sound.lib/menu_mus.raw";
+	_levels["sixdemo/mis/demo.mis"].scene.sound = "demo/sound.lib/menu_mus.raw";
 
 	parseScene("sixdemo", "mis/order.mis");
 	cl = new ChangeLevel();
@@ -75,7 +74,7 @@ void SpiderEngine::loadAssets() {
 
 	parseScene("sixdemo", "mis/alley.mis");
 	_levels["sixdemo/mis/alley.mis"].scene.intro = "demo/aleyc01s.smk";
-	_levels["sixdemo/mis/alley.mis"].scene.sound = "sixdemo/demo/sound.lib/alleymus.raw";
+	_levels["sixdemo/mis/alley.mis"].scene.sound = "demo/sound.lib/alleymus.raw";
 
 	parseScene("sixdemo", "mis/shoctalk.mis");
 
diff --git a/engines/hypno/spider/talk.cpp b/engines/hypno/spider/talk.cpp
index 970b5f4828..ce60e9a438 100644
--- a/engines/hypno/spider/talk.cpp
+++ b/engines/hypno/spider/talk.cpp
@@ -1,14 +1,14 @@
-#include "hypno/hypno.h"
 #include "hypno/grammar.h"
+#include "hypno/hypno.h"
 
 namespace Hypno {
 
-void HypnoEngine::showConversation() {	
+void HypnoEngine::showConversation() {
 	uint32 x = 18;
 	uint32 y = 20;
 	Graphics::Surface *speaker = decodeFrame("dialog/speaker3.smk", 0);
 	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
-		Talk *a = (Talk*) *itt;
+		Talk *a = (Talk *)*itt;
 		if (a->active) {
 			uint32 frame;
 			Common::String path;
@@ -18,9 +18,8 @@ void HypnoEngine::showConversation() {
 				} else if (it->command == "G") {
 					path = it->path;
 				}
-
 			}
-			if (!path.empty()) { 
+			if (!path.empty()) {
 				frame = frame;
 				debug("decoding %s frame %d", path.c_str(), frame);
 				Graphics::Surface *surf = decodeFrame("dialog/" + path, frame);
@@ -34,36 +33,34 @@ void HypnoEngine::showConversation() {
 			}
 		}
 	}
-
 }
 
 bool HypnoEngine::leftClickedConversation(Common::Point mousePos) {
 	Talk *t;
-	bool activeFound = false; 
+	bool activeFound = false;
 	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
-		Talk *a = (Talk*) *itt;
+		Talk *a = (Talk *)*itt;
 		if (a->active && a->rect.contains(mousePos)) {
 			activeFound = true;
 			a->active = false;
 			for (TalkCommands::const_iterator it = a->commands.begin(); it != a->commands.end(); ++it) {
 				if (it->command == "A") {
 					debug("Adding %d", it->num);
-					t = (Talk*) _conversation[it->num];
+					t = (Talk *)_conversation[it->num];
 					t->active = true;
-					_refreshConversation = true; 
+					_refreshConversation = true;
 				} else if (it->command == "D") {
 					debug("Disabling %d", it->num);
-					t = (Talk*) _conversation[it->num];
+					t = (Talk *)_conversation[it->num];
 					t->active = false;
-					_refreshConversation = true; 
+					_refreshConversation = true;
 				} else if (it->command == "P") {
 					debug("Playing %s", it->path.c_str());
 					_nextSequentialVideoToPlay.push_back(MVideo(it->path, it->position, false, false, false));
 				}
-
 			}
 		}
-		if (!a->background.empty()){
+		if (!a->background.empty()) {
 			loadImage(a->background, a->position.x, a->position.y, false);
 		}
 	}
@@ -76,7 +73,7 @@ bool HypnoEngine::leftClickedConversation(Common::Point mousePos) {
 
 bool HypnoEngine::rightClickedConversation(Common::Point mousePos) {
 	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
-		Talk *a = (Talk*) *itt;
+		Talk *a = (Talk *)*itt;
 		if (a->active && a->rect.contains(mousePos)) {
 			for (TalkCommands::const_iterator it = a->commands.begin(); it != a->commands.end(); ++it) {
 				if (it->command == "I") {
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 0c3e1aa5bb..e4bfc37467 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -79,6 +79,7 @@ void WetEngine::loadAssets() {
 		_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 		_levels[arclevel].arcade.prefix = "wetlands";
 		_levels[arclevel].arcade.levelIfLose = "<gameover>";
+		Common::replace(_levels[arclevel].arcade.music, "sound\\", "");
 		if (k < files.size() - 1)
 			_levels[arclevel].arcade.levelIfWin = files[k + 1].name;
 	}


Commit: 7f55b9cad0b7681b87f577cdc97927d116d14b84
    https://github.com/scummvm/scummvm/commit/7f55b9cad0b7681b87f577cdc97927d116d14b84
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved arcade sequences, pointers and basic detection of Soldier Boyz

Changed paths:
  A engines/hypno/boyz/boyz.cpp
    engines/hypno/arcade.cpp
    engines/hypno/cursors.cpp
    engines/hypno/detection.cpp
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/metaengine.cpp
    engines/hypno/module.mk
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 113df8056f..7dd0c571e3 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -7,19 +7,13 @@
 namespace Hypno {
 
 void HypnoEngine::drawPlayer(Common::String player, MVideo &background) { error("not implemented"); }
-void HypnoEngine::drawHealth(const Graphics::Font &font) { error("not implemented"); }
-
-void HypnoEngine::drawShoot(Common::Point target) {
-	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
-	_compositeSurface->drawLine(80, 155, target.x, target.y + 1, c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y, c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y - 1, c);
-	playSound("c_misc/sound.lib/" + _shootSound, 1);
-}
+void HypnoEngine::drawHealth() { error("not implemented"); }
+void HypnoEngine::drawShoot(Common::Point target) { error("not implemented"); }
+
 
 void HypnoEngine::runArcade(ArcadeShooting arc) {
 
-	const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont));
+	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
 	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> shootsToRemove;
@@ -27,11 +21,12 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 	_shootSound = arc.shootSound;
 	_health = arc.health;
 	_maxHealth = _health;
+	_defaultCursor = "arcade";
 	_shoots.clear();
 
 	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);
 
-	defaultCursor();
+	changeCursor("arcade");
 	playVideo(background);
 
 	while (!shouldQuit()) {
@@ -54,6 +49,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
+				drawCursorArcade(mousePos);
 				break;
 
 			default:
@@ -83,7 +79,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 						s.video = new MVideo(it->animation, it->position, true, false, false);
 						playVideo(*s.video);
 						_shoots.push_back(s);
-						playSound("c_misc/sound.lib/" + s.startSound, 1);
+						playSound(_soundPath + s.startSound, 1);
 					}
 				}
 			}
@@ -115,44 +111,62 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		}
 
 		if (_music.empty()) {
-			_music = "c_misc/sound.lib/" + arc.music;
+			_music = _soundPath + arc.music;
 			playSound(_music, 0);
 		}
 
 		drawPlayer(arc.player, background);
-		drawHealth(font);
+		drawHealth();
 
 		drawScreen();
 		g_system->delayMillis(10);
 	}
 }
 
-bool HypnoEngine::clickedShoot(Common::Point mousePos) {
-	bool found = false;
+int HypnoEngine::detectTarget(Common::Point mousePos) {
+	int i = -1;
 	int x = 0;
 	int y = 0;
 	int w = 0;
 	int h = 0;
 	for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
+		i++;
 		if (it->destroyed || !it->video->decoder)
 			continue;
 		x = mousePos.x - it->position.x;
 		y = mousePos.y - it->position.y;
 		w = it->video->decoder->getWidth();
 		h = it->video->decoder->getHeight();
-
 		if (it->video->decoder && x >= 0 && y >= 0 && x < w && y < h) {
-			uint32 c = it->video->currentFrame->getPixel(x, y);
-			//debug("inside %x", c);
-			if (c > 0) {
-				playSound("c_misc/sound.lib/" + it->endSound, 1);
-				it->destroyed = true;
-				it->video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
-				it->video->decoder->forceSeekToFrame(it->explosionFrame + 2);
-			}
+			if (it->video->currentFrame->getPixel(x, y) > 0)
+				return i;
 		}
 	}
-	return found;
+	return -1;
+}
+
+void HypnoEngine::drawCursorArcade(Common::Point mousePos) {
+	int i = detectTarget(mousePos);
+	if (i > 0)
+		changeCursor("target");
+	else
+		changeCursor("arcade");
+
+}
+
+bool HypnoEngine::clickedShoot(Common::Point mousePos) {
+	int i = detectTarget(mousePos);
+	int w = 0;
+	int h = 0;
+	if (i > 0) {
+		playSound(_soundPath + _shoots[i].endSound, 1);
+		w = _shoots[i].video->decoder->getWidth();
+		h = _shoots[i].video->decoder->getHeight();
+		_shoots[i].destroyed = true;
+		_shoots[i].video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
+		_shoots[i].video->decoder->forceSeekToFrame(_shoots[i].explosionFrame + 2);
+	}
+	return (i > 0);
 }
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/boyz/boyz.cpp b/engines/hypno/boyz/boyz.cpp
new file mode 100644
index 0000000000..bb82a9ee75
--- /dev/null
+++ b/engines/hypno/boyz/boyz.cpp
@@ -0,0 +1,15 @@
+#include "hypno/grammar.h"
+#include "hypno/hypno.h"
+
+#include "common/events.h"
+
+namespace Hypno {
+
+BoyzEngine::BoyzEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
+
+void BoyzEngine::loadAssets() {
+	LibData files;
+	loadLib("boyz/preload/missions.lib", files);
+}
+
+}
\ No newline at end of file
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index 97621cea10..d1c6811e40 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -45,16 +45,43 @@ static const byte MOUSECURSOR_SCI[] = {
 	0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
 	0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0};
 
+static const byte circleCursor[] {
+0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 
+0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 
+0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
+0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
+2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
+2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
+2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
+0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
+0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
+0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 
+0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0};
+
+static const byte targetCursor[] {
+0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+0, 0, 1, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0,
+0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0, 
+1, 0, 2, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 1,
+1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 1,
+1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
+1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
+1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
+1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 1,
+1, 0, 2, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 1,
+0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0,
+0, 0, 1, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0,
+0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0};
+
 static const byte cursorPalette[] = {
 	0x00, 0x00, 0x00, // Black / Transparent
-	0x01, 0x01, 0x01, // Gray
-	0xff, 0xff, 0xff, // White
-	0xff, 0x00, 0x00  // Red
+	0x00, 0x00, 0xff, // Blue
+	0xff, 0x00, 0x00, // Red
+	0x00, 0x00, 0x00  // Red
 };
 
 struct CursorTable {
 	const char *name;
-	const char *aname;
 	const void *buf;
 	int w;
 	int h;
@@ -63,8 +90,10 @@ struct CursorTable {
 };
 
 static const CursorTable cursorTable[] = {
-	{"default", "", MOUSECURSOR_SCI, 11, 16, 0, 0},
-	{nullptr, nullptr, nullptr, 0, 0, 0, 0}};
+	{"default", MOUSECURSOR_SCI, 11, 16, 0, 0},
+	{"arcade", circleCursor, 13, 11, 7, 5},
+	{"target", targetCursor, 15, 13, 8, 6},
+	{nullptr, nullptr, 0, 0, 0, 0}};
 
 void HypnoEngine::disableCursor() {
 	CursorMan.showMouse(false);
@@ -73,13 +102,22 @@ void HypnoEngine::disableCursor() {
 void HypnoEngine::defaultCursor() {
 	if (!_defaultCursor.empty())
 		changeCursor(_defaultCursor, 0);
-	else {
-		CursorMan.showMouse(true);
-		const CursorTable *entry = cursorTable;
-		CursorMan.replaceCursor(entry->buf, entry->w, entry->h, entry->hotspotX, entry->hotspotY, 0);
-		CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
-		CursorMan.showMouse(true);
+	else
+		changeCursor("default");
+}
+
+void HypnoEngine::changeCursor(const Common::String &cursor) {
+	const CursorTable *entry = cursorTable;
+	while (entry->name) {
+		if (cursor == entry->name)
+			break;
+		entry++;
 	}
+	assert(entry->name);
+
+	CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
+	CursorMan.replaceCursor(entry->buf, entry->w, entry->h, entry->hotspotX, entry->hotspotY, 0);
+	CursorMan.showMouse(true);
 }
 
 void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index f90dccbe39..72c42bbd5e 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -35,6 +35,7 @@ namespace Hypno {
 static const PlainGameDescriptor hypnoGames[] = {
 	{"sinister-six", "Marvel Comics Spider-Man: The Sinister Six"},
 	{"wetlands", "Wetlands"},
+	{"soldier-boyz", "Soldier Boyz"},
 	{0, 0}};
 
 static const ADGameDescription gameDescriptions[] = {
@@ -68,12 +69,21 @@ static const ADGameDescription gameDescriptions[] = {
 				"install.exe", "15a6b1b3819ef002438df340509b5373", 477839),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
-	 ADGF_TESTING,
+	 ADGF_UNSUPPORTED,
+	 GUIO1(GUIO_NOMIDI)},
+	{"soldier-boyz", // Solidier Boyz (US)
+	 "",
+	 AD_ENTRY2s("boyz.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 263347,
+				"setup.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 160740),
+	 Common::EN_USA,
+	 Common::kPlatformWindows,
+	 ADGF_UNSUPPORTED,
 	 GUIO1(GUIO_NOMIDI)},
 	AD_TABLE_END_MARKER};
 } // End of namespace Hypno
 
 static const char *const directoryGlobs[] = {
+	"boyz",
 	"sixdemo",
 	"factory",
 	"wetlands",
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index ea3f6527d0..94287d889c 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -860,17 +860,25 @@ void HypnoEngine::playSound(Common::String name, uint32 loops) {
 	if (!_prefixDir.empty())
 		name = _prefixDir + "/" + name;
 	debug("trying to play %s", name.c_str());
-	ByteArray *raw;
-	Audio::LoopingAudioStream *stream;
-
-	for (LibData::iterator it = _soundFiles.begin(); it != _soundFiles.end(); ++it) {
-		if (it->name == name) {
-			raw = new ByteArray(it->data);
-			stream = new Audio::LoopingAudioStream(Audio::makeRawStream(raw->data(), raw->size(), 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
-			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
-			break;
+	ByteArray *raw = nullptr;
+	Audio::LoopingAudioStream *stream = nullptr;
+
+	Common::File *file = new Common::File();
+	if (file->open(name)) {
+		stream = new Audio::LoopingAudioStream(Audio::makeRawStream(file, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
+	} else { 
+		for (LibData::iterator it = _soundFiles.begin(); it != _soundFiles.end(); ++it) {
+			if (it->name == name) {
+				raw = new ByteArray(it->data);
+				stream = new Audio::LoopingAudioStream(Audio::makeRawStream(raw->data(), raw->size(), 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
+				break;
+			}
 		}
 	}
+
+	if (stream) {
+		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
+	}
 }
 
 void HypnoEngine::stopSound() {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index c2150ebe7f..131b833f2c 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -136,7 +136,8 @@ public:
 	Common::String _defaultCursor;
 	void disableCursor();
 	void defaultCursor();
-	void changeCursor(const Common::String &, uint32);
+	void changeCursor(const Common::String &cursor, uint32 n);
+	void changeCursor(const Common::String &cursor);
 
 	// Actions
 	void runIntro(MVideo &video);
@@ -182,20 +183,24 @@ public:
 	Videos _videosPlaying;
 
 	// Sounds
-	Common::String _music;
-	void playSound(Common::String name, uint32);
+	Filename _soundPath;
+	Filename _music;
+	void playSound(Filename name, uint32);
 	void stopSound();
 	bool isSoundActive();
 	bool _noStopSounds;
 
 	// Arcade
-	void drawShoot(Common::Point);
+	int detectTarget(Common::Point mousePos);
+	virtual void drawShoot(Common::Point);
+	void drawCursorArcade(Common::Point mousePos);
 	virtual void drawPlayer(Common::String player, MVideo &background);
-	virtual void drawHealth(const Graphics::Font &font);
+	virtual void drawHealth();
 	int _health;
 	int _maxHealth;
 	Filename _shootSound;
 	Shoots _shoots;
+	const Graphics::Font *_font;
 
 	// Conversation
 	Actions _conversation;
@@ -217,9 +222,9 @@ public:
 	WetEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
-
+	void drawShoot(Common::Point) override;
 	void drawPlayer(Common::String player, MVideo &background) override;
-	void drawHealth(const Graphics::Font &font) override;
+	void drawHealth() override;
 };
 
 class SpiderEngine : public HypnoEngine {
@@ -227,15 +232,21 @@ public:
 	SpiderEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
-
+	void drawShoot(Common::Point) override;
 	void drawPlayer(Common::String player, MVideo &background) override;
-	void drawHealth(const Graphics::Font &font) override;
+	void drawHealth() override;
 	void runPuzzle(Puzzle puzzle) override;
 
 private:
 	void runMatrix(Puzzle puzzle);
 };
 
+class BoyzEngine : public HypnoEngine {
+public:
+	BoyzEngine(OSystem *syst, const ADGameDescription *gd);
+	void loadAssets() override;
+};
+
 } // End of namespace Hypno
 
 #endif
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index 9041a87032..b674f3efbc 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -36,11 +36,14 @@ public:
 };
 
 Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	debug("gameid: %s", desc->gameId);
+	bool isDemo = desc->flags & ADGF_DEMO;
 	if (Common::String(desc->gameId) == "wetlands") {
 		*engine = (Engine *)new Hypno::WetEngine(syst, desc);
 	} else if (Common::String(desc->gameId) == "sinister-six") {
 		*engine = (Engine *)new Hypno::SpiderEngine(syst, desc);
+	} else if (Common::String(desc->gameId) == "soldier-boyz") {
+		*engine = (Engine *)new Hypno::BoyzEngine(syst, desc);
+		error("Unsupported game");
 	} else
 		return Common::kUnsupportedGameidError;
 
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index cfb54fcc02..30c97719c2 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -13,6 +13,7 @@ MODULE_OBJS := \
 	spider/arcade.o \
 	wet/wet.o \
 	wet/arcade.o \
+	boyz/boyz.o \
 	hypno.o
 
 MODULE_DIRS += \
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index cb52aa8d2d..6ef05a60ff 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -1,3 +1,5 @@
+#include <algorithm>
+
 #include "hypno/grammar.h"
 #include "hypno/hypno.h"
 
@@ -6,20 +8,27 @@
 
 namespace Hypno {
 
+
+static const int frame_idx[9] = {0, 1, 2, 7, 8, 3, 6, 5, 4};
+
+void SpiderEngine::drawShoot(Common::Point target) {
+	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
+	_compositeSurface->drawLine(80, 155, target.x, target.y + 1, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y, c);
+	_compositeSurface->drawLine(80, 155, target.x, target.y - 1, c);
+	playSound(_soundPath + _shootSound, 1);
+}
+
 void SpiderEngine::drawPlayer(Common::String player, MVideo &background) {
 	Common::Point mousePos = g_system->getEventManager()->getMousePos();
-	uint32 idx;
-	if (mousePos.y / (_screenH / 2) == 0)
-		idx = mousePos.x / (_screenW / 3);
-	else
-		idx = 5 - mousePos.x / (_screenW / 3);
+	uint32 idx = frame_idx[std::min(2, mousePos.x / (_screenW / 3)) + 3 * std::min(2, mousePos.y / (_screenH / 3))];
 	Graphics::Surface *image = decodeFrame(player, idx);
 	drawImage(*image, 60, 129, true);
 	image->free();
 	delete image;
 }
 
-void SpiderEngine::drawHealth(const Graphics::Font &font) {
+void SpiderEngine::drawHealth() {
 	Common::Rect r;
 	uint32 c;
 	int d = (22 * (_maxHealth - _health) / _maxHealth);
@@ -36,7 +45,7 @@ void SpiderEngine::drawHealth(const Graphics::Font &font) {
 	c = _pixelFormat.RGBToColor(0, 0, 255);
 	_compositeSurface->frameRect(r, c);
 
-	font.drawString(_compositeSurface, "ENERGY", 248, 180, 38, c);
+	_font->drawString(_compositeSurface, "ENERGY", 248, 180, 38, c);
 }
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 1699afea15..4bd076a56f 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -84,6 +84,7 @@ void SpiderEngine::loadAssets() {
 	matrix.puzzle.levelIfWin = "sixdemo/mis/demo.mis";
 	matrix.puzzle.levelIfLose = "sixdemo/mis/demo.mis";
 	_levels["sixdemo/puz_matr"] = matrix;
+	_soundPath = "c_misc/sound.lib/";
 }
 
 void SpiderEngine::runPuzzle(Puzzle puzzle) {
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index 4b8c47b709..4efc6d840e 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -6,8 +6,36 @@
 
 namespace Hypno {
 
+void WetEngine::drawShoot(Common::Point mousePos) {
+	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
+	_compositeSurface->drawLine(0, _screenH, mousePos.x, mousePos.y, c);
+	_compositeSurface->drawLine(0, _screenH, mousePos.x-1, mousePos.y, c);
+	_compositeSurface->drawLine(0, _screenH, mousePos.x-2, mousePos.y, c);
+
+	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x, mousePos.y, c);
+	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x-1, mousePos.y, c);
+	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x-2, mousePos.y, c);
+	playSound(_soundPath + _shootSound, 1);
+}
+
 void WetEngine::drawPlayer(Common::String player, MVideo &background) {
-	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
+	uint32 c = _pixelFormat.RGBToColor(32, 208, 32);
+	_compositeSurface->drawLine(113, 1, 119, 1, c);
+	_compositeSurface->drawLine(200, 1, 206, 1, c);
+
+	_compositeSurface->drawLine(113, 1, 113, 9, c);
+	_compositeSurface->drawLine(206, 1, 206, 9, c);
+
+	_compositeSurface->drawLine(113, 9, 119, 9, c);
+	_compositeSurface->drawLine(200, 9, 206, 9, c);
+
+	c = _pixelFormat.RGBToColor(255, 0, 0);
+	Common::Point mousePos = g_system->getEventManager()->getMousePos();
+	int i = detectTarget(mousePos);
+	if (i > 0)
+		_font->drawString(_compositeSurface, "TARGET  ACQUIRED", 120, 1, 80, c);
+
+	//_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
 	Graphics::Surface *image = decodeFrame(player, background.decoder->getCurFrame() % 3);
 	drawImage(*image, 0, 200 - image->h + 1, true);
 	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
@@ -15,13 +43,11 @@ void WetEngine::drawPlayer(Common::String player, MVideo &background) {
 	delete image;
 }
 
-void WetEngine::drawHealth(const Graphics::Font &font) {
-	//Common::Rect r;
-	uint32 c;
+void WetEngine::drawHealth() {
+	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	int p = (100 * _health) / _maxHealth;
-	c = _pixelFormat.RGBToColor(252, 252, 0);
-	font.drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), 70, 160, 65, c);
-	font.drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), 180, 160, 71, c);
+	_font->drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), 70, 160, 65, c);
+	_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), 180, 160, 71, c);
 }
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index e4bfc37467..08d8b96ab5 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -79,7 +79,7 @@ void WetEngine::loadAssets() {
 		_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 		_levels[arclevel].arcade.prefix = "wetlands";
 		_levels[arclevel].arcade.levelIfLose = "<gameover>";
-		Common::replace(_levels[arclevel].arcade.music, "sound\\", "");
+		//Common::replace(_levels[arclevel].arcade.music, "sound\\", "");
 		if (k < files.size() - 1)
 			_levels[arclevel].arcade.levelIfWin = files[k + 1].name;
 	}


Commit: 87afe2d933048f502498827ebb28afcd6d1a8713
    https://github.com/scummvm/scummvm/commit/87afe2d933048f502498827ebb28afcd6d1a8713
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: refactored code, added basic debugging capabilities and fixes

Changed paths:
  A engines/hypno/actions.cpp
  A engines/hypno/scene.cpp
    engines/hypno/arcade.cpp
    engines/hypno/detection.cpp
    engines/hypno/grammar_arc.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/module.mk
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
new file mode 100644
index 0000000000..ba70fb1dcd
--- /dev/null
+++ b/engines/hypno/actions.cpp
@@ -0,0 +1,119 @@
+
+#include "common/events.h"
+
+#include "hypno/grammar.h"
+#include "hypno/hypno.h"
+
+namespace Hypno {
+
+//Actions
+
+void HypnoEngine::runMenu(Hotspots hs) {
+	const Hotspot h = *hs.begin();
+	assert(h.type == MakeMenu);
+
+	debug("hotspot actions size: %d", h.actions.size());
+	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
+		Action *action = *itt;
+		if (typeid(*action) == typeid(Quit))
+			runQuit((Quit *)action);
+		else if (typeid(*action) == typeid(Background))
+			runBackground((Background *)action);
+		else if (typeid(*action) == typeid(Overlay))
+			runOverlay((Overlay *)action);
+		else if (typeid(*action) == typeid(Ambient))
+			runAmbient((Ambient *)action);
+
+		//else if (typeid(*action) == typeid(Mice))
+		//	runMice(h, (Mice*) action);
+	}
+
+	//if (h.stype == "SINGLE_RUN")
+	//	loadImage("int_main/mainbutt.smk", 0, 0);
+	if (h.stype == "AUTO_BUTTONS" && _conversation.empty())
+		loadImage("int_main/resume.smk", 0, 0, true);
+}
+
+void HypnoEngine::runBackground(Background *a) {
+	if (a->condition.size() > 0 && !_sceneState[a->condition])
+		return;
+	Common::Point origin = a->origin;
+	loadImage(a->path, origin.x, origin.y, false);
+}
+
+void HypnoEngine::runOverlay(Overlay *a) {
+	Common::Point origin = a->origin;
+	loadImage(a->path, origin.x, origin.y, false);
+}
+
+void HypnoEngine::runMice(Mice *a) {
+	changeCursor(a->path, a->index);
+}
+
+void HypnoEngine::runEscape(Escape *a) {
+	_nextHotsToRemove = stack.back();
+}
+
+void HypnoEngine::runCutscene(Cutscene *a) {
+	stopSound();
+	disableCursor();
+	_music = "";
+	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true, false));
+}
+
+void HypnoEngine::runGlobal(Global *a) {
+	if (a->command == "TURNON")
+		_sceneState[a->variable] = 1;
+	else if (a->command == "TURNOFF")
+		_sceneState[a->variable] = 0;
+	else
+		error("Invalid command %s", a->command.c_str());
+}
+
+void HypnoEngine::runPlay(Play *a) {
+	if (a->condition.size() > 0 && !_sceneState[a->condition])
+		return;
+	Common::Point origin = a->origin;
+
+	if (a->flag == "/BITMAP")
+		loadImage(a->path, origin.x, origin.y, false);
+	else {
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
+	}
+}
+
+void HypnoEngine::runAmbient(Ambient *a) {
+	Common::Point origin = a->origin;
+	if (a->flag == "/BITMAP")
+		loadImage(a->path, origin.x, origin.y, false);
+	else {
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, a->fullscreen, a->flag == "/LOOP"));
+	}
+}
+
+void HypnoEngine::runWalN(WalN *a) {
+	if (a->condition.size() > 0 && !_sceneState[a->condition])
+		return;
+	Common::Point origin = a->origin;
+	if (a->flag == "/BITMAP")
+		loadImage(a->path, origin.x, origin.y, false);
+	else {
+		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
+	}
+}
+
+void HypnoEngine::runQuit(Quit *a) {
+	quitGame();
+}
+
+void HypnoEngine::runChangeLevel(ChangeLevel *a) {
+	_nextLevel = a->level;
+}
+
+void HypnoEngine::runTalk(Talk *a) {
+	debug("adding TALK line!");
+	_conversation.push_back(a);
+	_refreshConversation = true;
+}
+
+}
\ No newline at end of file
diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 7dd0c571e3..ae66b60d25 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -1,16 +1,55 @@
-#include "hypno/grammar.h"
-#include "hypno/hypno.h"
-
+#include "common/tokenizer.h"
 #include "common/events.h"
 #include "graphics/cursorman.h"
 
+#include "hypno/grammar.h"
+#include "hypno/hypno.h"
+
 namespace Hypno {
 
+extern int parse_arc(const char *);
+
+void HypnoEngine::parseArcadeShooting(Common::String prefix, Common::String filename, Common::String data) {
+	debugC(1, kHypnoDebugParser, "Parsing %s%s", prefix.c_str(), filename.c_str());
+	parse_arc(data.c_str());
+	Level level;
+	level.arcade = g_parsedArc;
+	level.arcade.prefix = prefix;
+	_levels[filename] = level;
+	g_parsedArc.background.clear();
+	g_parsedArc.player.clear();
+	g_parsedArc.shoots.clear();
+}
+
+ShootSequence HypnoEngine::parseShootList(Common::String filename, Common::String data) {
+	debugC(1, kHypnoDebugParser, "Parsing %s", filename.c_str());
+	Common::StringTokenizer tok(data, " ,\t");
+	Common::String t;
+	Common::String n;
+	ShootInfo si;
+	ShootSequence seq;
+	while (!tok.empty()) {
+		t = tok.nextToken();
+		if (t[0] == '\n')
+			continue;
+		n = tok.nextToken();
+		if (t == "Z")
+			break;
+
+		Common::replace(n, "\nS", "");
+		Common::replace(n, "\nZ\n", "");
+		si.name = n;
+		si.timestamp = atoi(t.c_str());
+		seq.push_back(si);
+		debugC(1, kHypnoDebugParser, "%d -> %s", si.timestamp, si.name.c_str());
+	}
+	return seq;
+}
+
 void HypnoEngine::drawPlayer(Common::String player, MVideo &background) { error("not implemented"); }
 void HypnoEngine::drawHealth() { error("not implemented"); }
 void HypnoEngine::drawShoot(Common::Point target) { error("not implemented"); }
 
-
 void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
@@ -44,8 +83,13 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				break;
 
 			case Common::EVENT_LBUTTONDOWN:
-				drawShoot(mousePos);
-				clickedShoot(mousePos);
+				if (clickedPrimaryShoot(mousePos))
+					drawShoot(mousePos);
+				break;
+
+			case Common::EVENT_RBUTTONDOWN:
+				if (clickedSecondaryShoot(mousePos))
+					drawShoot(mousePos);
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
@@ -59,12 +103,20 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 		if (_health <= 0) {
 			skipVideo(background);
+			if (!arc.defeatVideos.empty()) {
+				MVideo video(arc.defeatVideos.front(), Common::Point(0, 0), false, false, false);
+				runIntro(video);
+			}
 			_nextLevel = arc.levelIfLose;
 			return;
 		}
 
 		if (background.decoder->endOfVideo()) {
 			skipVideo(background);
+			if (!arc.winVideos.empty()) {
+				MVideo video(arc.winVideos.front(), Common::Point(0, 0), false, false, false);
+				runIntro(video);
+			}
 			_nextLevel = arc.levelIfWin;
 			return;
 		}
@@ -105,7 +157,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		}
 		if (shootsToRemove.size() > 0) {
 			for (Common::List<uint32>::iterator it = shootsToRemove.begin(); it != shootsToRemove.end(); ++it) {
-				//debug("removing %d from %d size", *it, _shoots.size());
+				debugC(1, kHypnoDebugArcade, "Removing %d from %d size", *it, _shoots.size());
 				_shoots.remove_at(*it);
 			}
 		}
@@ -154,7 +206,7 @@ void HypnoEngine::drawCursorArcade(Common::Point mousePos) {
 
 }
 
-bool HypnoEngine::clickedShoot(Common::Point mousePos) {
+bool HypnoEngine::clickedPrimaryShoot(Common::Point mousePos) {
 	int i = detectTarget(mousePos);
 	int w = 0;
 	int h = 0;
@@ -166,7 +218,11 @@ bool HypnoEngine::clickedShoot(Common::Point mousePos) {
 		_shoots[i].video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
 		_shoots[i].video->decoder->forceSeekToFrame(_shoots[i].explosionFrame + 2);
 	}
-	return (i > 0);
+	return true;
+}
+
+bool HypnoEngine::clickedSecondaryShoot(Common::Point mousePos) {
+	return false;
 }
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 72c42bbd5e..908c4c4043 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -26,9 +26,10 @@
 #include "hypno/hypno.h"
 
 static const DebugChannelDef debugFlagList[] = {
-	{Hypno::kHypnoDebugFunction, "functions", "Function execution debug channel"},
-	{Hypno::kHypnoDebugCode, "code", "Code execution debug channel"},
-	{Hypno::kHypnoDebugScript, "script", "Script execution debug channel"},
+	{Hypno::kHypnoDebugMedia, "media", "Media debug channel"},
+	{Hypno::kHypnoDebugParser, "parser", "Parser debug channel"},
+	{Hypno::kHypnoDebugScene, "scene", "Scene debug channel"},
+	{Hypno::kHypnoDebugArcade, "arcade", "Arcade debug channel"},
 	DEBUG_CHANNEL_END};
 
 namespace Hypno {
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index 9751a36f3f..5d4d8e1f0e 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -113,6 +113,10 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 	  | BNTOK FILENAME {
 		  if (Common::String("B0") == $1)
 		  	g_parsedArc.intro = $2;
+		  else if(Common::String("B1") == $1 || Common::String("B@") == $1)
+		    g_parsedArc.winVideos.push_back($2);
+		  else if(Common::String("B3") == $1 || Common::String("B3") == $1)
+		    g_parsedArc.defeatVideos.push_back($2);
 		 	
 		  debug("BN %s", $2); 
 		}
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 94287d889c..b84391b585 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -34,7 +34,6 @@
 #include "common/str.h"
 #include "common/system.h"
 #include "common/timer.h"
-#include "common/tokenizer.h"
 #include "engines/util.h"
 #include "image/bmp.h"
 
@@ -54,38 +53,6 @@ MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent,
 	loop = _loop;
 }
 
-const static char *levelVariables[] = {
-	"GS_NONE",
-	"GS_SCTEXT",
-	"GS_AMBIENT",
-	"GS_MUSIC",
-	"GS_VOLUME",
-	"GS_MOUSESPEED",
-	"GS_MOUSEON",
-	"GS_LEVELCOMPLETE",
-	"GS_LEVELWON",
-	"GS_CHEATS",
-	"GS_SWITCH0",
-	"GS_SWITCH1",
-	"GS_SWITCH2",
-	"GS_SWITCH3",
-	"GS_SWITCH4",
-	"GS_SWITCH5",
-	"GS_SWITCH6",
-	"GS_SWITCH7",
-	"GS_SWITCH8",
-	"GS_SWITCH9",
-	"GS_SWITCH10",
-	"GS_SWITCH11",
-	"GS_SWITCH12",
-	"GS_COMBATJSON",
-	"GS_COMBATLEVEL",
-	"GS_PUZZLELEVEL",
-	NULL};
-
-extern int parse_mis(const char *);
-extern int parse_arc(const char *);
-
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	: Engine(syst), _gameDescription(gd), _image(nullptr),
 	  _compositeSurface(nullptr), _transparentColor(0),
@@ -115,29 +82,8 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
 }
 
-void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
-	debug("Parsing %s", filename.c_str());
-	filename = convertPath(filename);
-	if (!prefix.empty())
-		filename = prefix + "/" + filename;
-	Common::File *test = new Common::File();
-	assert(isDemo());
-	assert(test->open(filename.c_str()));
-
-	const uint32 fileSize = test->size();
-	char *buf = (char *)malloc(fileSize + 1);
-	test->read(buf, fileSize);
-	buf[fileSize] = '\0';
-	parse_mis(buf);
-	Level level;
-	level.scene.prefix = prefix;
-	level.scene.hots = *g_parsedHots;
-	_levels[filename] = level;
-	debug("Loaded hots size: %d", g_parsedHots->size());
-}
-
 void HypnoEngine::loadLib(Common::String filename, LibData &r) {
-	debug("Loading %s", filename.c_str());
+	debugC(1, kHypnoDebugParser, "Parsing %s", filename.c_str());
 	Common::File libfile;
 	assert(libfile.open(filename));
 	uint32 i = 0;
@@ -179,55 +125,6 @@ void HypnoEngine::loadLib(Common::String filename, LibData &r) {
 	} while (size > 0);
 }
 
-void HypnoEngine::resetLevelState() {
-	uint32 i = 0;
-	while (levelVariables[i]) {
-		_levelState[levelVariables[i]] = 0;
-		i++;
-	}
-}
-
-bool HypnoEngine::checkLevelCompleted() {
-	return _levelState["GS_LEVELCOMPLETE"];
-}
-
-ShootSequence HypnoEngine::parseShootList(Common::String name, Common::String data) {
-	Common::StringTokenizer tok(data, " ,\t");
-
-	Common::String t;
-	Common::String n;
-	ShootInfo si;
-	ShootSequence seq;
-	while (!tok.empty()) {
-		t = tok.nextToken();
-		if (t[0] == '\n')
-			continue;
-		n = tok.nextToken();
-		//debug("t: %s, n: %s", t.c_str(), n.c_str());
-		if (t == "Z")
-			break;
-
-		Common::replace(n, "\nS", "");
-		Common::replace(n, "\nZ\n", "");
-		si.name = n;
-		si.timestamp = atoi(t.c_str());
-		seq.push_back(si);
-		debug("%d -> %s", si.timestamp, si.name.c_str());
-	}
-	return seq;
-}
-
-void HypnoEngine::parseArcadeShooting(Common::String prefix, Common::String name, Common::String data) {
-	parse_arc(data.c_str());
-	Level level;
-	level.arcade = g_parsedArc;
-	level.arcade.prefix = prefix;
-	_levels[name] = level;
-	g_parsedArc.background.clear();
-	g_parsedArc.player.clear();
-	g_parsedArc.shoots.clear();
-}
-
 void HypnoEngine::loadAssets() { error("not implemented"); }
 
 Common::Error HypnoEngine::run() {
@@ -251,21 +148,13 @@ Common::Error HypnoEngine::run() {
 	// Main event loop
 	Common::Event event;
 	Common::Point mousePos;
-	/*int saveSlot = ConfMan.getInt("save_slot");
-	if (saveSlot >= 0) { // load the savegame
-		loadGameState(saveSlot);
-	} else {
-		_nextSetting = getGoIntroSetting();
-	}*/
 	loadAssets();
 	_nextLevel = "<start>";
 	while (!shouldQuit()) {
 		_defaultCursor = "";
 		_prefixDir = "";
-		resetLevelState();
 		_videosPlaying.clear();
 		if (!_nextLevel.empty()) {
-			debug("Executing level %s", _nextLevel.c_str());
 			_currentLevel = _nextLevel;
 			_nextLevel = "";
 			runLevel(_currentLevel);
@@ -282,6 +171,7 @@ void HypnoEngine::runLevel(Common::String name) {
 	disableCursor();
 
 	if (!_levels[name].trans.level.empty()) {
+		debugC(1, kHypnoDebugScene, "Executing transition level %s", name.c_str());
 		_nextLevel = _levels[name].trans.level;
 		for (Filenames::iterator it = _levels[name].trans.intros.begin(); it != _levels[name].trans.intros.end(); ++it) {
 			MVideo v(*it, Common::Point(0, 0), false, true, false);
@@ -289,6 +179,7 @@ void HypnoEngine::runLevel(Common::String name) {
 		}
 
 	} else if (!_levels[name].arcade.background.empty()) {
+		debugC(1, kHypnoDebugArcade, "Executing arcade level %s", name.c_str());
 		_prefixDir = _levels[name].arcade.prefix;
 		if (!_levels[name].arcade.intro.empty()) {
 			MVideo v(_levels[name].arcade.intro, Common::Point(0, 0), false, true, false);
@@ -297,12 +188,15 @@ void HypnoEngine::runLevel(Common::String name) {
 		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
 	} else if (!_levels[name].puzzle.name.empty()) {
+		debugC(1, kHypnoDebugScene, "Executing puzzle level %s", name.c_str());
 		if (!_levels[name].arcade.intro.empty()) {
 			MVideo v(_levels[name].arcade.intro, Common::Point(0, 0), false, true, false);
 			runIntro(v);
 		}
 		runPuzzle(_levels[name].puzzle);
 	} else {
+		debugC(1, kHypnoDebugScene, "Executing scene level %s", name.c_str());
+		resetSceneState();
 		_prefixDir = _levels[name].scene.prefix;
 		if (!_levels[name].scene.intro.empty()) {
 			MVideo v(_levels[name].scene.intro, Common::Point(0, 0), false, true, false);
@@ -313,170 +207,10 @@ void HypnoEngine::runLevel(Common::String name) {
 	}
 }
 
-void HypnoEngine::runScene(Scene scene) {
-	_refreshConversation = false;
-	_conversation.clear();
-	Common::Event event;
-	Common::Point mousePos;
-	Common::List<uint32> videosToRemove;
-
-	stack.clear();
-	_nextHotsToAdd = &scene.hots;
-	defaultCursor();
-
-	while (!shouldQuit() && _nextLevel.empty()) {
-
-		while (g_system->getEventManager()->pollEvent(event)) {
-			mousePos = g_system->getEventManager()->getMousePos();
-			// Events
-			switch (event.type) {
-			case Common::EVENT_KEYDOWN:
-				if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
-					for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
-						if (it->decoder)
-							skipVideo(*it);
-					}
-					_videosPlaying.clear();
-
-					if (!stack.empty()) {
-						runMenu(*stack.back());
-						drawScreen();
-					}
-				}
-
-				break;
-
-			case Common::EVENT_QUIT:
-			case Common::EVENT_RETURN_TO_LAUNCHER:
-				break;
-
-			case Common::EVENT_RBUTTONDOWN:
-				if (stack.empty())
-					break;
-				if (!_conversation.empty()) {
-					rightClickedConversation(mousePos);
-					break;
-				}
-				break;
-
-			case Common::EVENT_LBUTTONDOWN:
-				if (stack.empty())
-					break;
-				if (!_conversation.empty()) {
-					leftClickedConversation(mousePos);
-					break;
-				}
-				if (!_nextHotsToAdd || !_nextHotsToRemove)
-					clickedHotspot(mousePos);
-				break;
-
-			case Common::EVENT_MOUSEMOVE:
-				// Reset cursor to default
-				//changeCursor("default");
-				// The following functions will return true
-				// if the cursor is changed
-				if (!_conversation.empty())
-					break;
-
-				if (hoverHotspot(mousePos)) {
-				} else
-					defaultCursor();
-				break;
-
-			default:
-				break;
-			}
-		}
-
-		if (_refreshConversation && !_conversation.empty() && _nextSequentialVideoToPlay.empty()) {
-			showConversation();
-			drawScreen();
-			_refreshConversation = false;
-			_videosPlaying.clear();
-		}
-
-		// Movies
-		if (_nextSequentialVideoToPlay.size() > 0 && _videosPlaying.empty()) {
-			playVideo(*_nextSequentialVideoToPlay.begin());
-			_videosPlaying.push_back(*_nextSequentialVideoToPlay.begin());
-			_nextSequentialVideoToPlay.remove_at(0);
-		}
-		uint32 i = 0;
-		videosToRemove.clear();
-		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
-
-			if (it->decoder) {
-				if (it->decoder->endOfVideo()) {
-					if (it->loop) {
-						it->decoder->rewind();
-						it->decoder->start();
-					} else {
-						it->decoder->close();
-						delete it->decoder;
-						it->decoder = nullptr;
-						videosToRemove.push_back(i);
-					}
-
-				} else if (it->decoder->needsUpdate()) {
-					updateScreen(*it);
-				}
-			}
-			i++;
-		}
-		if (videosToRemove.size() > 0) {
-
-			for (Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
-				debug("removing %d from %d size", *it, _videosPlaying.size());
-				_videosPlaying.remove_at(*it);
-			}
-
-			// Nothing else to play
-			if (_videosPlaying.size() == 0 && _nextSequentialVideoToPlay.size() == 0) {
-				if (!_conversation.empty())
-					_refreshConversation = true;
-				else if (!stack.empty()) {
-					runMenu(*stack.back());
-					drawScreen();
-				}
-			}
-		}
-
-		if (_videosPlaying.size() > 0 || _nextSequentialVideoToPlay.size() > 0) {
-			drawScreen();
-			continue;
-		}
-
-		if (_nextHotsToRemove) {
-			debug("Removing a hotspot list!");
-			stack.pop_back();
-			runMenu(*stack.back());
-			_nextHotsToRemove = NULL;
-			drawScreen();
-		} else if (_nextHotsToAdd) {
-			debug("Adding a hotspot list!");
-			//clearAreas();
-			stack.push_back(_nextHotsToAdd);
-			runMenu(*stack.back());
-			_nextHotsToAdd = NULL;
-			drawScreen();
-		}
-
-		if (_music.empty() && !scene.sound.empty()) {
-			_music = scene.sound;
-			playSound(_music, 0);
-		}
-
-		if (checkLevelCompleted())
-			_nextLevel = "mis/demo.mis";
-
-		g_system->updateScreen();
-		g_system->delayMillis(10);
-	}
-}
-
 void HypnoEngine::runIntro(MVideo &video) {
 	Common::Event event;
 	stopSound();
+	disableCursor();
 	playVideo(video);
 
 	while (!shouldQuit() && video.decoder) {
@@ -510,216 +244,15 @@ void HypnoEngine::runIntro(MVideo &video) {
 
 void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Not implemented"); }
 
-//Actions
-
-void HypnoEngine::runMenu(Hotspots hs) {
-	const Hotspot h = *hs.begin();
-	assert(h.type == MakeMenu);
-
-	debug("hotspot actions size: %d", h.actions.size());
-	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
-		Action *action = *itt;
-		if (typeid(*action) == typeid(Quit))
-			runQuit((Quit *)action);
-		else if (typeid(*action) == typeid(Background))
-			runBackground((Background *)action);
-		else if (typeid(*action) == typeid(Overlay))
-			runOverlay((Overlay *)action);
-		else if (typeid(*action) == typeid(Ambient))
-			runAmbient((Ambient *)action);
-
-		//else if (typeid(*action) == typeid(Mice))
-		//	runMice(h, (Mice*) action);
-	}
-
-	//if (h.stype == "SINGLE_RUN")
-	//	loadImage("int_main/mainbutt.smk", 0, 0);
-	if (h.stype == "AUTO_BUTTONS" && _conversation.empty())
-		loadImage("int_main/resume.smk", 0, 0, true);
-}
-
-void HypnoEngine::runBackground(Background *a) {
-	if (a->condition.size() > 0 && !_levelState[a->condition])
-		return;
-	Common::Point origin = a->origin;
-	loadImage(a->path, origin.x, origin.y, false);
-}
-
-void HypnoEngine::runOverlay(Overlay *a) {
-	Common::Point origin = a->origin;
-	loadImage(a->path, origin.x, origin.y, false);
-}
-
-void HypnoEngine::runMice(Mice *a) {
-	changeCursor(a->path, a->index);
-}
-
-void HypnoEngine::runEscape(Escape *a) {
-	_nextHotsToRemove = stack.back();
-}
-
-void HypnoEngine::runCutscene(Cutscene *a) {
-	stopSound();
-	_music = "";
-	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true, false));
-}
-
-void HypnoEngine::runGlobal(Global *a) {
-	if (a->command == "TURNON")
-		_levelState[a->variable] = 1;
-	else if (a->command == "TURNOFF")
-		_levelState[a->variable] = 0;
-	else
-		error("Invalid command %s", a->command.c_str());
-}
-
-void HypnoEngine::runPlay(Play *a) {
-	if (a->condition.size() > 0 && !_levelState[a->condition])
-		return;
-	Common::Point origin = a->origin;
-
-	if (a->flag == "/BITMAP")
-		loadImage(a->path, origin.x, origin.y, false);
-	else {
-		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
-	}
-}
-
-void HypnoEngine::runAmbient(Ambient *a) {
-	Common::Point origin = a->origin;
-	if (a->flag == "/BITMAP")
-		loadImage(a->path, origin.x, origin.y, false);
-	else {
-		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, a->fullscreen, a->flag == "/LOOP"));
-	}
-}
-
-void HypnoEngine::runWalN(WalN *a) {
-	if (a->condition.size() > 0 && !_levelState[a->condition])
-		return;
-	Common::Point origin = a->origin;
-	if (a->flag == "/BITMAP")
-		loadImage(a->path, origin.x, origin.y, false);
-	else {
-		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
-	}
-}
-
-void HypnoEngine::runQuit(Quit *a) {
-	quitGame();
-}
-
-void HypnoEngine::runChangeLevel(ChangeLevel *a) {
-	_nextLevel = a->level;
-}
-
-void HypnoEngine::runTalk(Talk *a) {
-	debug("adding TALK line!");
-	_conversation.push_back(a);
-	_refreshConversation = true;
-}
-
-// Hotspots
-
-void HypnoEngine::clickedHotspot(Common::Point mousePos) {
-	debug("clicked in %d %d", mousePos.x, mousePos.y);
-	Hotspots *hots = stack.back();
-	Hotspot selected;
-	bool found = false;
-	int rs = 100000000;
-	int cs = 0;
-	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
-		const Hotspot h = *it;
-		if (h.type != MakeHotspot)
-			continue;
-
-		cs = h.rect.width() * h.rect.height();
-		if (h.rect.contains(mousePos)) {
-			if (cs < rs) {
-				selected = h;
-				found = true;
-				rs = cs;
-			}
-		}
-	}
-	if (found) {
-		//debug("Hotspot found! %x", selected.smenu);
-		if (selected.smenu) {
-			debug("SMenu found!");
-			assert(selected.smenu->size() > 0);
-			_nextHotsToAdd = selected.smenu;
-		}
-
-		debug("hotspot clicked actions size: %d", selected.actions.size());
-		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
-			Action *action = *itt;
-			if (typeid(*action) == typeid(ChangeLevel))
-				runChangeLevel((ChangeLevel *)action);
-			if (typeid(*action) == typeid(Escape))
-				runEscape((Escape *)action);
-			else if (typeid(*action) == typeid(Cutscene))
-				runCutscene((Cutscene *)action);
-			else if (typeid(*action) == typeid(Play))
-				runPlay((Play *)action);
-			else if (typeid(*action) == typeid(WalN))
-				runWalN((WalN *)action);
-			else if (typeid(*action) == typeid(Global))
-				runGlobal((Global *)action);
-			else if (typeid(*action) == typeid(Talk))
-				runTalk((Talk *)action);
-			else if (typeid(*action) == typeid(Quit))
-				runQuit((Quit *)action);
-			else if (typeid(*action) == typeid(Palette))
-				debug("runPalette unimplemented");
-		}
-	}
-}
-
-bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
-	if (stack.empty())
-		return false;
-
-	Hotspots *hots = stack.back();
-	Hotspot selected;
-	bool found = false;
-	int rs = 100000000;
-	int cs = 0;
-	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
-		const Hotspot h = *it;
-		if (h.type != MakeHotspot)
-			continue;
-
-		cs = h.rect.width() * h.rect.height();
-		if (h.rect.contains(mousePos)) {
-			if (cs < rs) {
-				selected = h;
-				found = true;
-				rs = cs;
-			}
-		}
-	}
-	if (found) {
-		//debug("Hovered over %d %d %d %d!", selected.rect.left, selected.rect.top, selected.rect.bottom, selected.rect.right);
-
-		//debug("hotspot actions size: %d", h.actions.size());
-		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
-			Action *action = *itt;
-			if (typeid(*action) == typeid(Mice))
-				runMice((Mice *)action);
-		}
-		return true;
-	}
-	return false;
-}
-
 void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
+	debugC(1, kHypnoDebugMedia, "%s(%s, %d, %d, %d)", __FUNCTION__, name.c_str(), x, y, transparent);
 	Graphics::Surface *surf = decodeFrame(name, 0);
 	drawImage(*surf, x, y, transparent);
 }
 
 void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transparent) {
 	if (transparent) {
-		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), surf.getPixel(0, 0));
+		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), surf.getPixel(surf.w - 1, surf.h - 1));
 	}
 	else
 		_compositeSurface->blitFrom(surf, Common::Point(x, y));
@@ -758,6 +291,7 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 }
 
 void HypnoEngine::changeScreenMode(Common::String mode) {
+	debugC(1, kHypnoDebugMedia, "%s(%s)", __FUNCTION__, mode.c_str());
 	if (mode == "scene") {
 		_screenW = 640;
 		_screenH = 480;
@@ -827,8 +361,7 @@ void HypnoEngine::drawScreen() {
 // Video handling
 
 void HypnoEngine::playVideo(MVideo &video) {
-	//debugC(1, kPrivateDebugFunction, "%s(%s)", __FUNCTION__, name.c_str());
-	debug("video.path: %s", video.path.c_str());
+	debugC(1, kHypnoDebugMedia, "%s(%s)", __FUNCTION__, video.path.c_str());
 	Common::File *file = new Common::File();
 	Common::String path = convertPath(video.path);
 	if (!_prefixDir.empty())
@@ -846,20 +379,19 @@ void HypnoEngine::playVideo(MVideo &video) {
 }
 
 void HypnoEngine::skipVideo(MVideo &video) {
+	debugC(1, kHypnoDebugMedia, "%s()", __FUNCTION__);
 	video.decoder->close();
 	delete video.decoder;
 	video.decoder = nullptr;
-	//_currentMovie = "";
 }
 
 // Sound handling
 
 void HypnoEngine::playSound(Common::String name, uint32 loops) {
-
+	debugC(1, kHypnoDebugMedia, "%s(%s, %d)", __FUNCTION__, name.c_str(), loops);
 	name = convertPath(name);
 	if (!_prefixDir.empty())
 		name = _prefixDir + "/" + name;
-	debug("trying to play %s", name.c_str());
 	ByteArray *raw = nullptr;
 	Audio::LoopingAudioStream *stream = nullptr;
 
@@ -882,7 +414,7 @@ void HypnoEngine::playSound(Common::String name, uint32 loops) {
 }
 
 void HypnoEngine::stopSound() {
-	debugC(1, kHypnoDebugFunction, "%s()", __FUNCTION__);
+	debugC(1, kHypnoDebugMedia, "%s()", __FUNCTION__);
 	_mixer->stopHandle(_soundHandle);
 }
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 131b833f2c..9ee39fbf21 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -49,9 +49,10 @@ namespace Hypno {
 
 // debug channels
 enum {
-	kHypnoDebugFunction = 1 << 0,
-	kHypnoDebugCode = 1 << 1,
-	kHypnoDebugScript = 1 << 2
+	kHypnoDebugMedia = 1 << 0,
+	kHypnoDebugParser = 1 << 1,
+	kHypnoDebugArcade = 1 << 2,
+	kHypnoDebugScene = 1 << 3,
 };
 
 typedef Common::Array<byte> ByteArray;
@@ -83,9 +84,9 @@ public:
 	Levels _levels;
 	LibData _soundFiles;
 	LibData _fontFiles;
-	Common::HashMap<Common::String, int> _levelState;
-	void resetLevelState();
-	bool checkLevelCompleted();
+	Common::HashMap<Common::String, int> _sceneState;
+	void resetSceneState();
+	bool checkSceneCompleted();
 	void runLevel(Common::String name);
 	void runScene(Scene scene);
 	void runArcade(ArcadeShooting arc);
@@ -102,7 +103,6 @@ public:
 
 	// User input
 	void clickedHotspot(Common::Point);
-	bool clickedShoot(Common::Point);
 	bool hoverHotspot(Common::Point);
 
 	// Cursors
@@ -192,6 +192,8 @@ public:
 
 	// Arcade
 	int detectTarget(Common::Point mousePos);
+	virtual bool clickedPrimaryShoot(Common::Point);
+	virtual bool clickedSecondaryShoot(Common::Point);
 	virtual void drawShoot(Common::Point);
 	void drawCursorArcade(Common::Point mousePos);
 	virtual void drawPlayer(Common::String player, MVideo &background);
@@ -222,6 +224,8 @@ public:
 	WetEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
+	bool clickedSecondaryShoot(Common::Point) override;
+
 	void drawShoot(Common::Point) override;
 	void drawPlayer(Common::String player, MVideo &background) override;
 	void drawHealth() override;
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index 30c97719c2..d2245e4c62 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -3,6 +3,8 @@ MODULE := engines/hypno
 MODULE_OBJS := \
 	cursors.o \
 	metaengine.o \
+	actions.o \
+	scene.o \
 	arcade.o \
 	lexer_mis.o \
 	grammar_mis.o \
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
new file mode 100644
index 0000000000..8ff170c5aa
--- /dev/null
+++ b/engines/hypno/scene.cpp
@@ -0,0 +1,316 @@
+#include "common/events.h"
+
+#include "hypno/grammar.h"
+#include "hypno/hypno.h"
+
+namespace Hypno {
+
+extern int parse_mis(const char *);
+
+const static char *sceneVariables[] = {
+	"GS_NONE",
+	"GS_SCTEXT",
+	"GS_AMBIENT",
+	"GS_MUSIC",
+	"GS_VOLUME",
+	"GS_MOUSESPEED",
+	"GS_MOUSEON",
+	"GS_LEVELCOMPLETE",
+	"GS_LEVELWON",
+	"GS_CHEATS",
+	"GS_SWITCH0",
+	"GS_SWITCH1",
+	"GS_SWITCH2",
+	"GS_SWITCH3",
+	"GS_SWITCH4",
+	"GS_SWITCH5",
+	"GS_SWITCH6",
+	"GS_SWITCH7",
+	"GS_SWITCH8",
+	"GS_SWITCH9",
+	"GS_SWITCH10",
+	"GS_SWITCH11",
+	"GS_SWITCH12",
+	"GS_COMBATJSON",
+	"GS_COMBATLEVEL",
+	"GS_PUZZLELEVEL",
+	NULL};
+
+void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
+	debugC(1, kHypnoDebugParser, "Parsing %s", filename.c_str());
+	filename = convertPath(filename);
+	if (!prefix.empty())
+		filename = prefix + "/" + filename;
+	Common::File *test = new Common::File();
+	assert(isDemo());
+	assert(test->open(filename.c_str()));
+
+	const uint32 fileSize = test->size();
+	char *buf = (char *)malloc(fileSize + 1);
+	test->read(buf, fileSize);
+	buf[fileSize] = '\0';
+	parse_mis(buf);
+	Level level;
+	level.scene.prefix = prefix;
+	level.scene.hots = *g_parsedHots;
+	_levels[filename] = level;
+}
+
+void HypnoEngine::resetSceneState() {
+	uint32 i = 0;
+	while (sceneVariables[i]) {
+		_sceneState[sceneVariables[i]] = 0;
+		i++;
+	}
+}
+
+bool HypnoEngine::checkSceneCompleted() {
+	return _sceneState["GS_LEVELCOMPLETE"];
+}
+
+// Hotspots
+
+void HypnoEngine::clickedHotspot(Common::Point mousePos) {
+	Hotspots *hots = stack.back();
+	Hotspot selected;
+	bool found = false;
+	int rs = 100000000;
+	int cs = 0;
+	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
+		const Hotspot h = *it;
+		if (h.type != MakeHotspot)
+			continue;
+
+		cs = h.rect.width() * h.rect.height();
+		if (h.rect.contains(mousePos)) {
+			if (cs < rs) {
+				selected = h;
+				found = true;
+				rs = cs;
+			}
+		}
+	}
+	if (found) {
+		//debug("Hotspot found! %x", selected.smenu);
+		if (selected.smenu) {
+			assert(selected.smenu->size() > 0);
+			_nextHotsToAdd = selected.smenu;
+		}
+
+		//debug("hotspot clicked actions size: %d", selected.actions.size());
+		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
+			Action *action = *itt;
+			if (typeid(*action) == typeid(ChangeLevel))
+				runChangeLevel((ChangeLevel *)action);
+			if (typeid(*action) == typeid(Escape))
+				runEscape((Escape *)action);
+			else if (typeid(*action) == typeid(Cutscene))
+				runCutscene((Cutscene *)action);
+			else if (typeid(*action) == typeid(Play))
+				runPlay((Play *)action);
+			else if (typeid(*action) == typeid(WalN))
+				runWalN((WalN *)action);
+			else if (typeid(*action) == typeid(Global))
+				runGlobal((Global *)action);
+			else if (typeid(*action) == typeid(Talk))
+				runTalk((Talk *)action);
+			else if (typeid(*action) == typeid(Quit))
+				runQuit((Quit *)action);
+			else if (typeid(*action) == typeid(Palette))
+				debug("runPalette unimplemented");
+		}
+	}
+}
+
+bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
+	Hotspots *hots = stack.back();
+	Hotspot selected;
+	bool found = false;
+	int rs = 100000000;
+	int cs = 0;
+	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
+		const Hotspot h = *it;
+		if (h.type != MakeHotspot)
+			continue;
+
+		cs = h.rect.width() * h.rect.height();
+		if (h.rect.contains(mousePos)) {
+			if (cs < rs) {
+				selected = h;
+				found = true;
+				rs = cs;
+			}
+		}
+	}
+	if (found) {
+		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
+			Action *action = *itt;
+			if (typeid(*action) == typeid(Mice))
+				runMice((Mice *)action);
+		}
+		return true;
+	}
+	return false;
+}
+
+void HypnoEngine::runScene(Scene scene) {
+	_refreshConversation = false;
+	_conversation.clear();
+	Common::Event event;
+	Common::Point mousePos;
+	Common::List<uint32> videosToRemove;
+
+	stack.clear();
+	_nextHotsToAdd = &scene.hots;
+	defaultCursor();
+
+	while (!shouldQuit() && _nextLevel.empty()) {
+
+		while (g_system->getEventManager()->pollEvent(event)) {
+			mousePos = g_system->getEventManager()->getMousePos();
+			// Events
+			switch (event.type) {
+			case Common::EVENT_KEYDOWN:
+				if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+					for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+						if (it->decoder)
+							skipVideo(*it);
+					}
+					_videosPlaying.clear();
+
+					if (!stack.empty()) {
+						runMenu(*stack.back());
+						drawScreen();
+					}
+				}
+
+				break;
+
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_RBUTTONDOWN:
+				if (stack.empty())
+					break;
+				if (!_conversation.empty()) {
+					rightClickedConversation(mousePos);
+					break;
+				}
+				break;
+
+			case Common::EVENT_LBUTTONDOWN:
+				if (stack.empty())
+					break;
+				if (!_conversation.empty()) {
+					leftClickedConversation(mousePos);
+					break;
+				}
+				if (!_nextHotsToAdd && !_nextHotsToRemove && _videosPlaying.size() == 0)
+					clickedHotspot(mousePos);
+				break;
+
+			case Common::EVENT_MOUSEMOVE:
+				// Reset cursor to default
+				//changeCursor("default");
+				// The following functions will return true
+				// if the cursor is changed
+				if (stack.empty() || !_conversation.empty() || _videosPlaying.size() > 0)
+					break;
+
+				if (hoverHotspot(mousePos)) {
+				} else
+					defaultCursor();
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		if (_refreshConversation && !_conversation.empty() && _nextSequentialVideoToPlay.empty()) {
+			showConversation();
+			drawScreen();
+			_refreshConversation = false;
+			_videosPlaying.clear();
+		}
+
+		// Movies
+		if (_nextSequentialVideoToPlay.size() > 0 && _videosPlaying.empty()) {
+			playVideo(*_nextSequentialVideoToPlay.begin());
+			_videosPlaying.push_back(*_nextSequentialVideoToPlay.begin());
+			_nextSequentialVideoToPlay.remove_at(0);
+		}
+		uint32 i = 0;
+		videosToRemove.clear();
+		for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+
+			if (it->decoder) {
+				if (it->decoder->endOfVideo()) {
+					if (it->loop) {
+						it->decoder->rewind();
+						it->decoder->start();
+					} else {
+						it->decoder->close();
+						delete it->decoder;
+						it->decoder = nullptr;
+						videosToRemove.push_back(i);
+					}
+
+				} else if (it->decoder->needsUpdate()) {
+					updateScreen(*it);
+				}
+			}
+			i++;
+		}
+		if (videosToRemove.size() > 0) {
+
+			for (Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
+				debugC(1, kHypnoDebugScene, "removing %d from %d size", *it, _videosPlaying.size());
+				_videosPlaying.remove_at(*it);
+			}
+
+			// Nothing else to play
+			if (_videosPlaying.size() == 0 && _nextSequentialVideoToPlay.size() == 0) {
+				if (!_conversation.empty())
+					_refreshConversation = true;
+				else if (!stack.empty()) {
+					runMenu(*stack.back());
+					drawScreen();
+				}
+			}
+		}
+
+		if (_videosPlaying.size() > 0 || _nextSequentialVideoToPlay.size() > 0) {
+			drawScreen();
+			continue;
+		}
+
+		if (_nextHotsToRemove) {
+			debugC(1, kHypnoDebugScene, "Removing a hotspot list!");
+			stack.pop_back();
+			runMenu(*stack.back());
+			_nextHotsToRemove = NULL;
+			drawScreen();
+		} else if (_nextHotsToAdd) {
+			debugC(1, kHypnoDebugScene, "Adding a hotspot list!");
+			stack.push_back(_nextHotsToAdd);
+			runMenu(*stack.back());
+			_nextHotsToAdd = NULL;
+			drawScreen();
+		}
+
+		if (_music.empty() && !scene.sound.empty()) {
+			_music = scene.sound;
+			playSound(_music, 0);
+		}
+
+		if (checkSceneCompleted())
+			_nextLevel = scene.levelIfWin;
+
+		g_system->updateScreen();
+		g_system->delayMillis(10);
+	}
+}
+
+} // end of Hypno namespace
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 4bd076a56f..6857eeb914 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -75,6 +75,8 @@ void SpiderEngine::loadAssets() {
 	parseScene("sixdemo", "mis/alley.mis");
 	_levels["sixdemo/mis/alley.mis"].scene.intro = "demo/aleyc01s.smk";
 	_levels["sixdemo/mis/alley.mis"].scene.sound = "demo/sound.lib/alleymus.raw";
+	_levels["sixdemo/mis/alley.mis"].scene.levelIfWin = "sixdemo/mis/demo.mis";
+	_levels["sixdemo/mis/alley.mis"].scene.levelIfLose = "sixdemo/mis/demo.mis";
 
 	parseScene("sixdemo", "mis/shoctalk.mis");
 
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index 4efc6d840e..2c5b00953a 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -6,6 +6,10 @@
 
 namespace Hypno {
 
+bool WetEngine::clickedSecondaryShoot(Common::Point mousePos) {
+	return clickedPrimaryShoot(mousePos);
+}
+
 void WetEngine::drawShoot(Common::Point mousePos) {
 	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	_compositeSurface->drawLine(0, _screenH, mousePos.x, mousePos.y, c);
@@ -19,6 +23,7 @@ void WetEngine::drawShoot(Common::Point mousePos) {
 }
 
 void WetEngine::drawPlayer(Common::String player, MVideo &background) {
+	// TARGET ACQUIRED frame
 	uint32 c = _pixelFormat.RGBToColor(32, 208, 32);
 	_compositeSurface->drawLine(113, 1, 119, 1, c);
 	_compositeSurface->drawLine(200, 1, 206, 1, c);
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 08d8b96ab5..05e7e62457 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -78,14 +78,19 @@ void WetEngine::loadAssets() {
 		parseArcadeShooting("wetlands", arclevel, arc);
 		_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 		_levels[arclevel].arcade.prefix = "wetlands";
-		_levels[arclevel].arcade.levelIfLose = "<gameover>";
+		//_levels[arclevel].arcade.levelIfLose = "<gameover>";
 		//Common::replace(_levels[arclevel].arcade.music, "sound\\", "");
-		if (k < files.size() - 1)
+		if (k < files.size() - 1) {
 			_levels[arclevel].arcade.levelIfWin = files[k + 1].name;
+			// failing a level in the demo takes you to the next one anyway
+			_levels[arclevel].arcade.levelIfLose = files[k + 1].name; 
+		}
+			
 	}
 
-	debug("%s", arc.c_str());
-	debug("------------------------------------");
+	// After finish the second level, it's always game over
+	_levels[files[k-1].name].arcade.levelIfWin = "<gameover>";
+	_levels[files[k-1].name].arcade.levelIfLose = "<gameover>"; 
 
 	Level over;
 	over.trans.level = "<quit>";


Commit: ce723aeb60897169666000a57f31d35bf4ee2db0
    https://github.com/scummvm/scummvm/commit/ce723aeb60897169666000a57f31d35bf4ee2db0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: Improved debugging capabilities and memory management

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/metaengine.cpp
    engines/hypno/scene.cpp
    engines/hypno/spider/spider.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index ae66b60d25..95216fc3e6 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -108,7 +108,8 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				runIntro(video);
 			}
 			_nextLevel = arc.levelIfLose;
-			return;
+			debugC(1, kHypnoDebugArcade, "Losing and jumping to %s", _nextLevel.c_str());
+			break;
 		}
 
 		if (background.decoder->endOfVideo()) {
@@ -118,7 +119,8 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				runIntro(video);
 			}
 			_nextLevel = arc.levelIfWin;
-			return;
+			debugC(1, kHypnoDebugArcade, "Wining and jumping to %s", _nextLevel.c_str());
+			break;
 		}
 
 		if (shootSequence.size() > 0) {
@@ -158,6 +160,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		if (shootsToRemove.size() > 0) {
 			for (Common::List<uint32>::iterator it = shootsToRemove.begin(); it != shootsToRemove.end(); ++it) {
 				debugC(1, kHypnoDebugArcade, "Removing %d from %d size", *it, _shoots.size());
+				delete _shoots[*it].video;
 				_shoots.remove_at(*it);
 			}
 		}
@@ -173,6 +176,14 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		drawScreen();
 		g_system->delayMillis(10);
 	}
+
+	// Deallocate shoots
+	for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
+		if (it->video->decoder)
+			skipVideo(*it->video);
+		delete it->video;
+	}
+
 }
 
 int HypnoEngine::detectTarget(Common::Point mousePos) {
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index b84391b585..05347861e9 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -56,7 +56,7 @@ MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent,
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	: Engine(syst), _gameDescription(gd), _image(nullptr),
 	  _compositeSurface(nullptr), _transparentColor(0),
-	  _nextHotsToAdd(nullptr), _nextHotsToRemove(nullptr),
+	  _nextHotsToAdd(nullptr), _nextHotsToRemove(nullptr), _font(nullptr),
 	  _screenW(640), _screenH(480) {
 	_rnd = new Common::RandomSource("hypno");
 
@@ -74,7 +74,16 @@ HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 }
 
 HypnoEngine::~HypnoEngine() {
-	// Dispose your resources
+	// Deallocate actions
+	for (Levels::iterator it = _levels.begin(); it != _levels.end(); ++it) {
+		Level level = (*it)._value;
+		for (Hotspots::iterator itt = level.scene.hots.begin(); itt != level.scene.hots.end(); ++itt) {
+			Hotspot hot = *itt; 
+			for (Actions::iterator ittt = hot.actions.begin(); ittt != hot.actions.end(); ++ittt)
+				delete (*ittt);
+		}
+	}
+
 	delete _rnd;
 }
 
@@ -103,10 +112,10 @@ void HypnoEngine::loadLib(Common::String filename, LibData &r) {
 			if (b != 0x96 && b != 0x0)
 				f.name += tolower(char(b));
 		}
-		debug("name: %s", f.name.c_str());
+		debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
 		start = libfile.readUint32LE();
 		size = libfile.readUint32LE();
-		debug("field: %x", libfile.readUint32LE());
+		libfile.readUint32LE(); // some field? 
 
 		pos = libfile.pos();
 		libfile.seek(start);
@@ -117,7 +126,7 @@ void HypnoEngine::loadLib(Common::String filename, LibData &r) {
 				b = b ^ 0xfe;
 			f.data.push_back(b);
 		}
-		debug("size: %d", f.data.size());
+		debugC(1, kHypnoDebugParser, "size: %d", f.data.size());
 		libfile.seek(pos);
 		if (size > 0)
 			r.push_back(f);
@@ -142,6 +151,7 @@ Common::Error HypnoEngine::run() {
 	if (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8())
 		return Common::kUnsupportedColorMode;
 
+	assert(_compositeSurface == nullptr);
 	_compositeSurface = new Graphics::ManagedSurface();
 	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
 
@@ -271,14 +281,11 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
 
-	//debug("decoding %s with %d frames", path.c_str(), vd.getFrameCount());
-
 	for (int f = 0; f < n; f++)
 		vd.decodeNextFrame();
 
 	const Graphics::Surface *frame = vd.decodeNextFrame();
 	Graphics::Surface *rframe;
-	//debug("decoding: %s %d %d", name.c_str(), frame->h, frame->w);
 	if (convert) {
 		rframe = frame->convertTo(_pixelFormat, vd.getPalette());
 	} else {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 9ee39fbf21..bf1bbe5e77 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -111,15 +111,9 @@ public:
 	bool cursorMask(Common::Point);
 
 	//bool hasFeature(EngineFeature f) const override;
-	bool canLoadGameStateCurrently() override {
-		return true;
-	}
-	bool canSaveAutosaveCurrently() override {
-		return false;
-	}
-	bool canSaveGameStateCurrently() override {
-		return true;
-	}
+	bool canLoadGameStateCurrently() override { return false; }
+	bool canSaveAutosaveCurrently() override { return false; }
+	bool canSaveGameStateCurrently() override { return false; }
 
 	void syncGameStream(Common::Serializer &s);
 
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index b674f3efbc..fb69950582 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -36,7 +36,6 @@ public:
 };
 
 Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
-	bool isDemo = desc->flags & ADGF_DEMO;
 	if (Common::String(desc->gameId) == "wetlands") {
 		*engine = (Engine *)new Hypno::WetEngine(syst, desc);
 	} else if (Common::String(desc->gameId) == "sinister-six") {
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 8ff170c5aa..894e341045 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -54,6 +54,7 @@ void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	level.scene.prefix = prefix;
 	level.scene.hots = *g_parsedHots;
 	_levels[filename] = level;
+	free(buf);
 }
 
 void HypnoEngine::resetSceneState() {
@@ -206,7 +207,7 @@ void HypnoEngine::runScene(Scene scene) {
 					leftClickedConversation(mousePos);
 					break;
 				}
-				if (!_nextHotsToAdd && !_nextHotsToRemove && _videosPlaying.size() == 0)
+				if (!_nextHotsToAdd && !_nextHotsToRemove /*&& _videosPlaying.size() == 0*/)
 					clickedHotspot(mousePos);
 				break;
 
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 6857eeb914..e2b484e403 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -39,6 +39,8 @@ void SpiderEngine::loadAssets() {
 	Common::String arclevel = files[0].name;
 	parseArcadeShooting("sixdemo", arclevel, arc);
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.levelIfWin = "sixdemo/mis/demo.mis";
+	_levels[arclevel].arcade.levelIfLose = "sixdemo/mis/demo.mis";
 
 	loadLib("sixdemo/c_misc/fonts.lib", _fontFiles);
 	loadLib("sixdemo/c_misc/sound.lib", _soundFiles);


Commit: 1d2593d11c83d6681ad2436ae0b5d3a8ace13043
    https://github.com/scummvm/scummvm/commit/1d2593d11c83d6681ad2436ae0b5d3a8ace13043
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: Improved arcade sequences and refactored parsing code

Changed paths:
  A engines/hypno/libfile.cpp
  A engines/hypno/libfile.h
    engines/hypno/arcade.cpp
    engines/hypno/boyz/boyz.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar_arc.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/metaengine.cpp
    engines/hypno/module.mk
    engines/hypno/scene.cpp
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 95216fc3e6..da09410f55 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -1,3 +1,25 @@
+/* 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/tokenizer.h"
 #include "common/events.h"
 #include "graphics/cursorman.h"
@@ -46,10 +68,16 @@ ShootSequence HypnoEngine::parseShootList(Common::String filename, Common::Strin
 	return seq;
 }
 
-void HypnoEngine::drawPlayer(Common::String player, MVideo &background) { error("not implemented"); }
+void HypnoEngine::drawPlayer() { error("not implemented"); }
 void HypnoEngine::drawHealth() { error("not implemented"); }
 void HypnoEngine::drawShoot(Common::Point target) { error("not implemented"); }
 
+void HypnoEngine::hitPlayer() {
+	// if the player is hit, play the hit animation
+	if (_playerFrameIdx < _playerFrameSep)
+		_playerFrameIdx = _playerFrameSep;
+}
+
 void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
@@ -57,11 +85,27 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 	Common::Point mousePos;
 	Common::List<uint32> shootsToRemove;
 	ShootSequence shootSequence = arc.shootSequence;
+
+	_levelId = arc.id;
 	_shootSound = arc.shootSound;
 	_health = arc.health;
 	_maxHealth = _health;
 	_defaultCursor = "arcade";
 	_shoots.clear();
+	_playerFrames = decodeFrames(arc.player);
+	_playerFrameSep = 0;
+
+
+	for (Frames::iterator it =_playerFrames.begin(); it != _playerFrames.end(); ++it) {
+		if ((*it)->getPixel(0, 0) == _pixelFormat.RGBToColor(0, 255, 255))
+			break; 
+		_playerFrameSep++;
+	}
+
+	if(_playerFrameSep == _playerFrames.size())
+		error("No player separator frame found!");
+
+	_playerFrameIdx = -1;
 
 	MVideo background = MVideo(arc.background, Common::Point(0, 0), false, false, false);
 
@@ -70,9 +114,6 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 	while (!shouldQuit()) {
 
-		if (background.decoder->needsUpdate())
-			updateScreen(background);
-
 		while (g_system->getEventManager()->pollEvent(event)) {
 			mousePos = g_system->getEventManager()->getMousePos();
 			// Events
@@ -101,6 +142,13 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			}
 		}
 
+		if (background.decoder->needsUpdate()) {
+			drawScreen();
+			updateScreen(background);
+			drawPlayer();
+			drawHealth();
+		}
+
 		if (_health <= 0) {
 			skipVideo(background);
 			if (!arc.defeatVideos.empty()) {
@@ -133,7 +181,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 						s.video = new MVideo(it->animation, it->position, true, false, false);
 						playVideo(*s.video);
 						_shoots.push_back(s);
-						playSound(_soundPath + s.startSound, 1);
+						playSound(_soundPath + arc.enemySound, 1);
 					}
 				}
 			}
@@ -145,10 +193,14 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
 			if (it->video->decoder) {
 				int frame = it->video->decoder->getCurFrame();
+				if (frame > 0 && frame >= it->explosionFrame - 15 && !it->destroyed) {
+					hitPlayer();
+				}
+
 				if (frame > 0 && frame >= it->explosionFrame - 3 && !it->destroyed) {
-					_health = _health - it->damage;
 					skipVideo(*it->video);
-				} else if (it->video->decoder->endOfVideo()) {
+					_health = _health - it->damage;
+				} else if (frame > 0 && frame >= it->video->decoder->getFrameCount()-2) {
 					skipVideo(*it->video);
 					shootsToRemove.push_back(i);
 				} else if (it->video->decoder->needsUpdate()) {
@@ -167,13 +219,9 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 		if (_music.empty()) {
 			_music = _soundPath + arc.music;
-			playSound(_music, 0);
+			playSound(_music, 1);
 		}
 
-		drawPlayer(arc.player, background);
-		drawHealth();
-
-		drawScreen();
 		g_system->delayMillis(10);
 	}
 
@@ -214,7 +262,8 @@ void HypnoEngine::drawCursorArcade(Common::Point mousePos) {
 		changeCursor("target");
 	else
 		changeCursor("arcade");
-
+		
+	g_system->copyRectToScreen(_compositeSurface->getPixels(), _compositeSurface->pitch, 0, 0, _screenW, _screenH);
 }
 
 bool HypnoEngine::clickedPrimaryShoot(Common::Point mousePos) {
diff --git a/engines/hypno/boyz/boyz.cpp b/engines/hypno/boyz/boyz.cpp
index bb82a9ee75..7223c706f2 100644
--- a/engines/hypno/boyz/boyz.cpp
+++ b/engines/hypno/boyz/boyz.cpp
@@ -8,8 +8,7 @@ namespace Hypno {
 BoyzEngine::BoyzEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void BoyzEngine::loadAssets() {
-	LibData files;
-	loadLib("boyz/preload/missions.lib", files);
+	loadLib("", "boyz/preload/missions.lib");
 }
 
 }
\ No newline at end of file
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index d0a5a2847d..0b473b8402 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -220,6 +220,7 @@ class Scene {
 
 class ArcadeShooting {
   public:
+    uint32 id;
 	Common::String levelIfWin;
 	Common::String levelIfLose;
 	Filenames defeatVideos;
@@ -232,6 +233,7 @@ class ArcadeShooting {
 	Shoots shoots;
 	ShootSequence shootSequence;
 	Filename shootSound;
+	Filename enemySound;
 	Filename hitSound;
 	Filename music;
 };
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index 5d4d8e1f0e..cf801f7ce4 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -113,9 +113,9 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 	  | BNTOK FILENAME {
 		  if (Common::String("B0") == $1)
 		  	g_parsedArc.intro = $2;
-		  else if(Common::String("B1") == $1 || Common::String("B@") == $1)
+		  else if(Common::String("B1") == $1 || Common::String("B2") == $1)
 		    g_parsedArc.winVideos.push_back($2);
-		  else if(Common::String("B3") == $1 || Common::String("B3") == $1)
+		  else if(Common::String("B3") == $1 || Common::String("B4") == $1)
 		    g_parsedArc.defeatVideos.push_back($2);
 		 	
 		  debug("BN %s", $2); 
@@ -125,7 +125,9 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 		  	g_parsedArc.music = $2;
 		  else if (Common::String("S1") == $1)
 		  	g_parsedArc.shootSound = $2;
-		   
+		  else if (Common::String("S4") == $1)
+		    g_parsedArc.enemySound = $2; 
+
 		  debug("SN %s", $2); 
 		}
 	  | HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
@@ -193,8 +195,8 @@ bline: FNTOK FILENAME {
 	 | SNTOK FILENAME enc { 
 		  if (Common::String("S1") == $1)
 		  	shoot->endSound = $2;
-		  else if (Common::String("S2") == $1)
-		  	shoot->startSound = $2;
+		  //else if (Common::String("S2") == $1)
+		  //	shoot->startSound = $2;
 		 
 		 debug("SN %s", $2); }
 	 | NTOK { debug("N"); }
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 05347861e9..abd48bbcc3 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -83,6 +83,11 @@ HypnoEngine::~HypnoEngine() {
 				delete (*ittt);
 		}
 	}
+	// This produces a double free
+	//for (Common::List<LibFile*>::iterator it = _archive.begin(); it != _archive.end(); ++it) {
+		//(*it)->close();
+		//delete *it;
+	//}
 
 	delete _rnd;
 }
@@ -91,47 +96,12 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
 }
 
-void HypnoEngine::loadLib(Common::String filename, LibData &r) {
-	debugC(1, kHypnoDebugParser, "Parsing %s", filename.c_str());
-	Common::File libfile;
-	assert(libfile.open(filename));
-	uint32 i = 0;
-	Common::String entry = "<>";
-	FileData f;
-	f.data.push_back(0);
-	byte b;
-	uint32 start;
-	uint32 size;
-	uint32 pos;
-
-	do {
-		f.name = filename + "/";
-		f.data.clear();
-		for (i = 0; i < 12; i++) {
-			b = libfile.readByte();
-			if (b != 0x96 && b != 0x0)
-				f.name += tolower(char(b));
-		}
-		debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
-		start = libfile.readUint32LE();
-		size = libfile.readUint32LE();
-		libfile.readUint32LE(); // some field? 
-
-		pos = libfile.pos();
-		libfile.seek(start);
-
-		for (i = 0; i < size; i++) {
-			b = libfile.readByte();
-			if (b != '\n')
-				b = b ^ 0xfe;
-			f.data.push_back(b);
-		}
-		debugC(1, kHypnoDebugParser, "size: %d", f.data.size());
-		libfile.seek(pos);
-		if (size > 0)
-			r.push_back(f);
-
-	} while (size > 0);
+LibFile *HypnoEngine::loadLib(Filename prefix, Filename filename) {
+	LibFile *lib = new LibFile();
+	SearchMan.add(filename, (Common::Archive *) lib, 0, true);
+	assert(lib->open(prefix, filename));
+	_archive.push_back(lib);
+	return lib;
 }
 
 void HypnoEngine::loadAssets() { error("not implemented"); }
@@ -174,6 +144,7 @@ Common::Error HypnoEngine::run() {
 }
 
 void HypnoEngine::runLevel(Common::String name) {
+	debug("level: %s", name.c_str());
 	assert(_levels.contains(name));
 	stopSound();
 	_music = "";
@@ -297,6 +268,32 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	return rframe;
 }
 
+Frames HypnoEngine::decodeFrames(const Common::String &name) {
+	Frames frames;
+	Common::File *file = new Common::File();
+	Common::String path = convertPath(name);
+	if (!_prefixDir.empty())
+		path = _prefixDir + "/" + path;
+
+	if (!file->open(path))
+		error("unable to find video file %s", path.c_str());
+
+	Video::SmackerDecoder vd;
+	if (!vd.loadStream(file))
+		error("unable to load video %s", path.c_str());
+
+	const Graphics::Surface *frame = nullptr;
+	Graphics::Surface *rframe = nullptr;
+
+	for (int f = 0; f < vd.getFrameCount(); f++) {
+		frame = vd.decodeNextFrame();
+		rframe = frame->convertTo(_pixelFormat, vd.getPalette());
+		frames.push_back(rframe);
+	}
+	return frames;
+}
+
+
 void HypnoEngine::changeScreenMode(Common::String mode) {
 	debugC(1, kHypnoDebugMedia, "%s(%s)", __FUNCTION__, mode.c_str());
 	if (mode == "scene") {
@@ -399,23 +396,12 @@ void HypnoEngine::playSound(Common::String name, uint32 loops) {
 	name = convertPath(name);
 	if (!_prefixDir.empty())
 		name = _prefixDir + "/" + name;
-	ByteArray *raw = nullptr;
+	//ByteArray *raw = nullptr;
 	Audio::LoopingAudioStream *stream = nullptr;
 
 	Common::File *file = new Common::File();
 	if (file->open(name)) {
-		stream = new Audio::LoopingAudioStream(Audio::makeRawStream(file, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
-	} else { 
-		for (LibData::iterator it = _soundFiles.begin(); it != _soundFiles.end(); ++it) {
-			if (it->name == name) {
-				raw = new ByteArray(it->data);
-				stream = new Audio::LoopingAudioStream(Audio::makeRawStream(raw->data(), raw->size(), 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
-				break;
-			}
-		}
-	}
-
-	if (stream) {
+		stream = new Audio::LoopingAudioStream(Audio::makeRawStream(file, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO), loops);
 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
 	}
 }
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index bf1bbe5e77..63bfca2a9b 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -28,12 +28,14 @@
 #include "common/random.h"
 #include "common/serializer.h"
 #include "common/str-array.h"
+#include "common/stream.h"
 #include "engines/engine.h"
 #include "graphics/font.h"
 #include "graphics/fontman.h"
 #include "graphics/managed_surface.h"
 
 #include "hypno/grammar.h"
+#include "hypno/libfile.h"
 
 namespace Image {
 class ImageDecoder;
@@ -62,6 +64,7 @@ typedef struct FileData {
 } FileData;
 
 typedef Common::Array<FileData> LibData;
+typedef Common::Array<Graphics::Surface *> Frames;
 
 class HypnoEngine : public Engine {
 private:
@@ -79,11 +82,10 @@ public:
 
 	Audio::SoundHandle _soundHandle;
 	Common::InstallShieldV3 _installerArchive;
+	Common::List<LibFile*> _archive;
 
 	Common::Error run() override;
 	Levels _levels;
-	LibData _soundFiles;
-	LibData _fontFiles;
 	Common::HashMap<Common::String, int> _sceneState;
 	void resetSceneState();
 	bool checkSceneCompleted();
@@ -99,7 +101,7 @@ public:
 	void parseArcadeShooting(Common::String prefix, Common::String name, Common::String data);
 	ShootSequence parseShootList(Common::String name, Common::String data);
 	void loadLib(Common::String filename, LibData &r);
-	Common::HashMap<Common::String, Common::String> _assets;
+	LibFile *loadLib(Filename prefix, Filename filename);
 
 	// User input
 	void clickedHotspot(Common::Point);
@@ -123,6 +125,7 @@ public:
 	void skipVideo(MVideo &video);
 
 	Graphics::Surface *decodeFrame(const Common::String &name, int frame, bool convert = true);
+	Frames decodeFrames(const Common::String &name);
 	void loadImage(const Common::String &file, int x, int y, bool transparent);
 	void drawImage(Graphics::Surface &image, int x, int y, bool transparent);
 
@@ -165,6 +168,7 @@ public:
 	// levels
 	Common::String _nextLevel;
 	Common::String _currentLevel;
+	uint32 _levelId;
 
 	// hotspots
 	Hotspots *_nextHotsToAdd;
@@ -189,13 +193,18 @@ public:
 	virtual bool clickedPrimaryShoot(Common::Point);
 	virtual bool clickedSecondaryShoot(Common::Point);
 	virtual void drawShoot(Common::Point);
+	virtual void hitPlayer();
+
 	void drawCursorArcade(Common::Point mousePos);
-	virtual void drawPlayer(Common::String player, MVideo &background);
+	virtual void drawPlayer();
 	virtual void drawHealth();
 	int _health;
 	int _maxHealth;
 	Filename _shootSound;
 	Shoots _shoots;
+	Frames _playerFrames;
+	int _playerFrameIdx;
+	int _playerFrameSep;
 	const Graphics::Font *_font;
 
 	// Conversation
@@ -219,19 +228,17 @@ public:
 
 	void loadAssets() override;
 	bool clickedSecondaryShoot(Common::Point) override;
-
 	void drawShoot(Common::Point) override;
-	void drawPlayer(Common::String player, MVideo &background) override;
+	void drawPlayer() override;
 	void drawHealth() override;
 };
 
 class SpiderEngine : public HypnoEngine {
 public:
 	SpiderEngine(OSystem *syst, const ADGameDescription *gd);
-
 	void loadAssets() override;
 	void drawShoot(Common::Point) override;
-	void drawPlayer(Common::String player, MVideo &background) override;
+	void drawPlayer() override;
 	void drawHealth() override;
 	void runPuzzle(Puzzle puzzle) override;
 
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
new file mode 100644
index 0000000000..0afca424d9
--- /dev/null
+++ b/engines/hypno/libfile.cpp
@@ -0,0 +1,114 @@
+/* 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 "hypno/hypno.h"
+#include "hypno/libfile.h"
+
+namespace Hypno {
+
+bool LibFile::open(const Common::String &prefix, const Common::String &filename) {
+	_prefix = prefix;
+	Common::File libfile;
+	assert(libfile.open(filename));
+	uint32 i = 0;
+	Common::String entry = "<>";
+	FileEntry f;
+	f.data.push_back(0);
+	byte b;
+	uint32 start;
+	uint32 size;
+	uint32 pos;
+
+	do {
+		f.name = "";
+		f.data.clear();
+		for (i = 0; i < 12; i++) {
+			b = libfile.readByte();
+			if (b != 0x96 && b != 0x0)
+				f.name += tolower(char(b));
+		}
+		debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
+		start = libfile.readUint32LE();
+		size = libfile.readUint32LE();
+		libfile.readUint32LE(); // some field? 
+
+		pos = libfile.pos();
+		libfile.seek(start);
+
+		for (i = 0; i < size; i++) {
+			b = libfile.readByte();
+			if (b != '\n')
+				b = b ^ 0xfe;
+			f.data.push_back(b);
+		}
+		debugC(1, kHypnoDebugParser, "size: %d", f.data.size());
+		libfile.seek(pos);
+		if (size > 0)
+			_fileEntries.push_back(f);
+
+	} while (size > 0);
+	return true;
+}
+
+const FileEntry *LibFile::getEntry(const Common::String &name) const {
+        for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it) {
+				//debug("checking %s", it->name.c_str());
+                if (((_prefix + it->name).equalsIgnoreCase(name)) || it->name.equalsIgnoreCase(name))
+                        return it;
+        }
+
+        return nullptr;
+}
+
+void LibFile::close() {
+    _fileEntries.clear();
+}
+
+
+bool LibFile::hasFile(const Common::String &name) const { 
+	error("hasFile");
+    return false;
+}
+
+int LibFile::listMembers(Common::ArchiveMemberList &list) const { 
+	list.clear();
+	for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it)
+		list.push_back(getMember(it->name));
+
+	return list.size();
+}
+
+const Common::ArchiveMemberPtr LibFile::getMember(const Common::String &name) const {
+	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *LibFile::createReadStreamForMember(const Common::String &name) const {
+	//error("Not implemented %s", name.c_str());
+	const FileEntry *entry = getEntry(name);
+	Common::MemoryReadStream *stream = nullptr;
+	if (entry != nullptr)
+		stream = new Common::MemoryReadStream(entry->data.data(), entry->data.size());
+
+	return stream;
+}
+
+}
\ No newline at end of file
diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
new file mode 100644
index 0000000000..3e2f3ac92b
--- /dev/null
+++ b/engines/hypno/libfile.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.
+ *
+ * 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 HYPNO_LIBFILE_H
+#define HYPNO_LIBFILE_H
+
+#include "common/archive.h"
+#include "common/file.h"
+#include "common/array.h"
+#include "common/stream.h"
+#include "common/memstream.h"
+
+namespace Hypno {
+
+typedef Common::Array<byte> ByteArray;
+typedef struct FileEntry {
+	Common::String name;
+	ByteArray data;
+} FileEntry;
+
+class LibFile : public Common::Archive {
+public:
+        bool open(const Common::String &prefix, const Common::String &filename);
+        void close();
+
+        // Common::Archive API implementation
+        bool hasFile(const Common::String &name) const override;
+        int listMembers(Common::ArchiveMemberList &list) const override;
+        const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+        Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+private:
+        Common::String _prefix;
+        Common::Array<FileEntry> _fileEntries;
+        const FileEntry *getEntry(const Common::String &name) const;
+};
+
+} // End of namespace Hypno
+
+#endif
\ No newline at end of file
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index fb69950582..208bb8cf30 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -32,7 +32,6 @@ public:
 	}
 
 	Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
-	//void getSavegameThumbnail(Graphics::Surface &thumb) override;
 };
 
 Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index d2245e4c62..62af7a8a8f 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -1,6 +1,7 @@
 MODULE := engines/hypno
 
 MODULE_OBJS := \
+    libfile.o \
 	cursors.o \
 	metaengine.o \
 	actions.o \
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 894e341045..a3bffac96d 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -1,3 +1,25 @@
+/* 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 "hypno/grammar.h"
@@ -92,7 +114,6 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 		}
 	}
 	if (found) {
-		//debug("Hotspot found! %x", selected.smenu);
 		if (selected.smenu) {
 			assert(selected.smenu->size() > 0);
 			_nextHotsToAdd = selected.smenu;
@@ -118,7 +139,7 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			else if (typeid(*action) == typeid(Quit))
 				runQuit((Quit *)action);
 			else if (typeid(*action) == typeid(Palette))
-				debug("runPalette unimplemented");
+				debugC(1, kHypnoDebugScene, "runPalette unimplemented");
 		}
 	}
 }
@@ -303,7 +324,7 @@ void HypnoEngine::runScene(Scene scene) {
 
 		if (_music.empty() && !scene.sound.empty()) {
 			_music = scene.sound;
-			playSound(_music, 0);
+			playSound(_music, 1);
 		}
 
 		if (checkSceneCompleted())
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 6ef05a60ff..cad1648070 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -1,3 +1,25 @@
+/* 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 <algorithm>
 
 #include "hypno/grammar.h"
@@ -19,13 +41,17 @@ void SpiderEngine::drawShoot(Common::Point target) {
 	playSound(_soundPath + _shootSound, 1);
 }
 
-void SpiderEngine::drawPlayer(Common::String player, MVideo &background) {
-	Common::Point mousePos = g_system->getEventManager()->getMousePos();
-	uint32 idx = frame_idx[std::min(2, mousePos.x / (_screenW / 3)) + 3 * std::min(2, mousePos.y / (_screenH / 3))];
-	Graphics::Surface *image = decodeFrame(player, idx);
-	drawImage(*image, 60, 129, true);
-	image->free();
-	delete image;
+void SpiderEngine::drawPlayer() {
+
+	if (_playerFrameIdx < _playerFrameSep) {
+		Common::Point mousePos = g_system->getEventManager()->getMousePos();
+		_playerFrameIdx = frame_idx[std::min(2, mousePos.x / (_screenW / 3)) + 3 * std::min(2, mousePos.y / (_screenH / 3))];
+	} else {
+		_playerFrameIdx++;
+		if (_playerFrameIdx >= _playerFrames.size())
+			_playerFrameIdx = 0;
+	}
+	drawImage(*_playerFrames[_playerFrameIdx], 60, 129, true);
 }
 
 void SpiderEngine::drawHealth() {
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index e2b484e403..7061323296 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -1,15 +1,22 @@
+#include "common/events.h"
+
+
 #include "hypno/grammar.h"
 #include "hypno/hypno.h"
-
-#include "common/events.h"
+#include "hypno/libfile.h"
 
 namespace Hypno {
 
 SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void SpiderEngine::loadAssets() {
-	LibData files;
-	loadLib("sixdemo/c_misc/missions.lib", files);
+
+	LibFile *missions = loadLib("", "sixdemo/c_misc/missions.lib");
+	Common::ArchiveMemberList files;
+	assert(missions->listMembers(files) > 0);
+
+	//LibData files;
+	//loadLib("sixdemo/c_misc/missions.lib", files);
 	uint32 i = 0;
 	uint32 j = 0;
 
@@ -22,30 +29,34 @@ void SpiderEngine::loadAssets() {
 
 	Common::String arc;
 	Common::String list;
-
-	debug("Splitting file: %s", files[0].name.c_str());
-	for (i = 0; i < files[0].data.size(); i++) {
-		arc += files[0].data[i];
-		if (files[0].data[i] == 'X') {
-			i++;
-			for (j = i; j < files[0].data.size(); j++) {
-				if (files[0].data[j] == 'Y')
+	Common::String arclevel = files.front()->getName();
+	Common::SeekableReadStream *file = files.front()->createReadStream();
+	debug("Splitting file: %s", arclevel);
+	byte x;
+	while (!file->eos()) {
+		x = file->readByte();
+		arc += x;
+		if (x == 'X') {
+			while (!file->eos()) {
+				x = file->readByte();
+				if (x == 'Y')
 					break;
-				list += files[0].data[j];
+				list += x;
 			}
-			break; // No need to keep parsing, no more files are used in the demo
+			break; // No need to keep parsing
 		}
 	}
-	Common::String arclevel = files[0].name;
+
+	arclevel = "sixdemo/c_misc/missions.lib/" + arclevel;
 	parseArcadeShooting("sixdemo", arclevel, arc);
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 	_levels[arclevel].arcade.levelIfWin = "sixdemo/mis/demo.mis";
 	_levels[arclevel].arcade.levelIfLose = "sixdemo/mis/demo.mis";
 
-	loadLib("sixdemo/c_misc/fonts.lib", _fontFiles);
-	loadLib("sixdemo/c_misc/sound.lib", _soundFiles);
-	loadLib("sixdemo/demo/sound.lib", _soundFiles);
-
+	loadLib("", "sixdemo/c_misc/fonts.lib");
+	loadLib("sixdemo/c_misc/sound.lib/", "sixdemo/c_misc/sound.lib");
+	loadLib("sixdemo/demo/sound.lib/", "sixdemo/demo/sound.lib");
+	
 	// Read assets from mis files
 	parseScene("sixdemo", "mis/demo.mis");
 	ChangeLevel *cl = new ChangeLevel();
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index 2c5b00953a..6c375c7fd7 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -22,37 +22,52 @@ void WetEngine::drawShoot(Common::Point mousePos) {
 	playSound(_soundPath + _shootSound, 1);
 }
 
-void WetEngine::drawPlayer(Common::String player, MVideo &background) {
-	// TARGET ACQUIRED frame
-	uint32 c = _pixelFormat.RGBToColor(32, 208, 32);
-	_compositeSurface->drawLine(113, 1, 119, 1, c);
-	_compositeSurface->drawLine(200, 1, 206, 1, c);
-
-	_compositeSurface->drawLine(113, 1, 113, 9, c);
-	_compositeSurface->drawLine(206, 1, 206, 9, c);
-
-	_compositeSurface->drawLine(113, 9, 119, 9, c);
-	_compositeSurface->drawLine(200, 9, 206, 9, c);
-
-	c = _pixelFormat.RGBToColor(255, 0, 0);
-	Common::Point mousePos = g_system->getEventManager()->getMousePos();
-	int i = detectTarget(mousePos);
-	if (i > 0)
-		_font->drawString(_compositeSurface, "TARGET  ACQUIRED", 120, 1, 80, c);
-
-	//_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
-	Graphics::Surface *image = decodeFrame(player, background.decoder->getCurFrame() % 3);
-	drawImage(*image, 0, 200 - image->h + 1, true);
-	_transparentColor = _pixelFormat.RGBToColor(0, 0, 0);
-	image->free();
-	delete image;
+void WetEngine::drawPlayer() {
+
+	if (_playerFrameIdx < _playerFrameSep) {
+		// TARGET ACQUIRED frame
+		uint32 c = _pixelFormat.RGBToColor(32, 208, 32);
+		_compositeSurface->drawLine(113, 1, 119, 1, c);
+		_compositeSurface->drawLine(200, 1, 206, 1, c);
+
+		_compositeSurface->drawLine(113, 1, 113, 9, c);
+		_compositeSurface->drawLine(206, 1, 206, 9, c);
+
+		_compositeSurface->drawLine(113, 9, 119, 9, c);
+		_compositeSurface->drawLine(200, 9, 206, 9, c);
+
+		c = _pixelFormat.RGBToColor(255, 0, 0);
+		Common::Point mousePos = g_system->getEventManager()->getMousePos();
+		int i = detectTarget(mousePos);
+		if (i > 0)
+			_font->drawString(_compositeSurface, "TARGET  ACQUIRED", 120, 1, 80, c);
+
+		_playerFrameIdx++;
+		_playerFrameIdx = _playerFrameIdx % _playerFrameSep;
+	} else {
+		_playerFrameIdx++;
+		if (_playerFrameIdx >= _playerFrames.size())
+			_playerFrameIdx = 0;
+	}
+
+	drawImage(*_playerFrames[_playerFrameIdx], 0, 200 - _playerFrames[_playerFrameIdx]->h + 1, true);
 }
 
+static const int uiPos[2][3][2] = {
+	{ {70, 160}, {180, 160}, {220, 185} }, // c31
+	{ {60, 167}, {190, 167}, {135, 187} }, // c52
+};
+
 void WetEngine::drawHealth() {
 	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	int p = (100 * _health) / _maxHealth;
-	_font->drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), 70, 160, 65, c);
-	_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), 180, 160, 71, c);
+	if (_playerFrameIdx < _playerFrameSep) {
+		// /const int *ui[3][2] = &uiPos; 
+		uint32 id = _levelId;
+		_font->drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), uiPos[id][0][0], uiPos[id][0][1], 65, c);
+		_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), uiPos[id][1][0], uiPos[id][1][1], 72, c);
+		_font->drawString(_compositeSurface, Common::String::format("M.O.     0/0"), uiPos[id][2][0], uiPos[id][2][1], 60, c);
+	}
 }
 
 } // End of namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 05e7e62457..5ad826dede 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -1,4 +1,25 @@
-#include "hypno/grammar.h"
+/* 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 "hypno/hypno.h"
 
 namespace Hypno {
@@ -6,8 +27,19 @@ namespace Hypno {
 WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void WetEngine::loadAssets() {
-	LibData files;
-	loadLib("wetlands/c_misc/missions.lib", files);
+	//LibData files;
+	//loadLib("wetlands/c_misc/missions.lib", files);
+	LibFile *missions = loadLib("", "wetlands/c_misc/missions.lib");
+	Common::ArchiveMemberList files;
+	assert(missions->listMembers(files) > 0);
+
+	// We need the list of files in an array, instead of a list
+	Common::Array<Common::ArchiveMemberPtr> afiles;
+	for (Common::ArchiveMemberList::const_iterator it = files.begin(); it != files.end(); ++it) {
+		afiles.push_back(*it);
+	}
+
+
 	uint32 i = 0;
 	uint32 j = 0;
 	uint32 k = 0;
@@ -33,6 +65,7 @@ void WetEngine::loadAssets() {
 	h.type = MakeHotspot;
 	h.rect = Common::Rect(0, 424, 233, 462);
 	h.actions.clear();
+	h.smenu = nullptr;
 	ChangeLevel *cl = new ChangeLevel();
 	cl->level = "<intro>";
 	h.actions.push_back(cl);
@@ -50,55 +83,55 @@ void WetEngine::loadAssets() {
 	_levels["<start>"] = start;
 
 	Level intro;
-	intro.trans.level = files[0].name;
+	intro.trans.level = afiles[0]->getName();
 	intro.trans.intros.push_back("movie/nw_logo.smk");
 	intro.trans.intros.push_back("movie/hypnotix.smk");
 	intro.trans.intros.push_back("movie/wetlogo.smk");
 	_levels["<intro>"] = intro;
 
-	for (k = 0; k < files.size(); k++) {
+	byte x;
+	for (k = 0; k < afiles.size(); k++) {
 		arc.clear();
 		list.clear();
-		arclevel = files[k].name;
-
-		debug("Parsing %s", arclevel.c_str());
-		for (i = 0; i < files[k].data.size(); i++) {
-			arc += files[k].data[i];
-			if (files[k].data[i] == 'X') {
-				i++;
-				for (j = i; j < files[k].data.size(); j++) {
-					if (files[k].data[j] == 'Y')
+		arclevel = afiles[k]->getName();
+		debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
+		Common::SeekableReadStream *file = afiles[k]->createReadStream();
+		while (!file->eos()) {
+			x = file->readByte();
+			arc += x;
+			if (x == 'X') {
+				while (!file->eos()) {
+					x = file->readByte();
+					if (x == 'Y')
 						break;
-					list += files[k].data[j];
+					list += x;
 				}
 				break; // No need to keep parsing
 			}
 		}
 
 		parseArcadeShooting("wetlands", arclevel, arc);
+		_levels[arclevel].arcade.id = k;
 		_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 		_levels[arclevel].arcade.prefix = "wetlands";
-		//_levels[arclevel].arcade.levelIfLose = "<gameover>";
-		//Common::replace(_levels[arclevel].arcade.music, "sound\\", "");
 		if (k < files.size() - 1) {
-			_levels[arclevel].arcade.levelIfWin = files[k + 1].name;
+			_levels[arclevel].arcade.levelIfWin = afiles[k + 1]->getName();
 			// failing a level in the demo takes you to the next one anyway
-			_levels[arclevel].arcade.levelIfLose = files[k + 1].name; 
+			_levels[arclevel].arcade.levelIfLose = afiles[k + 1]->getName(); 
 		}
-			
 	}
 
 	// After finish the second level, it's always game over
-	_levels[files[k-1].name].arcade.levelIfWin = "<gameover>";
-	_levels[files[k-1].name].arcade.levelIfLose = "<gameover>"; 
+	_levels[afiles[k-1]->getName()].arcade.levelIfWin = "<gameover>";
+	_levels[afiles[k-1]->getName()].arcade.levelIfLose = "<gameover>"; 
 
 	Level over;
 	over.trans.level = "<quit>";
 	over.trans.intros.push_back("movie/gameover.smk");
 	_levels["<gameover>"] = over;
 
-	loadLib("wetlands/c_misc/fonts.lib", _fontFiles);
-	loadLib("wetlands/c_misc/sound.lib", _soundFiles);
+	loadLib("", "wetlands/c_misc/fonts.lib");
+	loadLib("wetlands/sound/", "wetlands/c_misc/sound.lib");
 }
 
 } // End of namespace Hypno


Commit: 0c4fdf44b4ad7f35c1e413d5d94f63aa1dff9cde
    https://github.com/scummvm/scummvm/commit/0c4fdf44b4ad7f35c1e413d5d94f63aa1dff9cde
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: Removed some memory leaks

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/cursors.cpp
    engines/hypno/hypno.cpp
    engines/hypno/scene.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index da09410f55..33738815d8 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -232,6 +232,9 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		delete it->video;
 	}
 
+	if (background.decoder)
+		skipVideo(background);
+
 }
 
 int HypnoEngine::detectTarget(Common::Point mousePos) {
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index d1c6811e40..91654a9f00 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -123,6 +123,8 @@ void HypnoEngine::changeCursor(const Common::String &cursor) {
 void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
 	Graphics::Surface *entry = decodeFrame(cursor, n, false);
 	CursorMan.replaceCursor(entry->getPixels(), entry->w, entry->h, 0, 0, 0);
+	entry->free();
+	delete entry;
 	CursorMan.showMouse(true);
 }
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index abd48bbcc3..d083e49d03 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -83,13 +83,10 @@ HypnoEngine::~HypnoEngine() {
 				delete (*ittt);
 		}
 	}
-	// This produces a double free
-	//for (Common::List<LibFile*>::iterator it = _archive.begin(); it != _archive.end(); ++it) {
-		//(*it)->close();
-		//delete *it;
-	//}
 
 	delete _rnd;
+	_compositeSurface->free();
+	delete _compositeSurface;
 }
 
 void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
@@ -396,12 +393,11 @@ void HypnoEngine::playSound(Common::String name, uint32 loops) {
 	name = convertPath(name);
 	if (!_prefixDir.empty())
 		name = _prefixDir + "/" + name;
-	//ByteArray *raw = nullptr;
-	Audio::LoopingAudioStream *stream = nullptr;
 
+	Audio::LoopingAudioStream *stream = nullptr;
 	Common::File *file = new Common::File();
 	if (file->open(name)) {
-		stream = new Audio::LoopingAudioStream(Audio::makeRawStream(file, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO), loops);
+		stream = new Audio::LoopingAudioStream(Audio::makeRawStream(file, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), loops);
 		_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
 	}
 }
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index a3bffac96d..98a549e21c 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -64,7 +64,6 @@ void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	if (!prefix.empty())
 		filename = prefix + "/" + filename;
 	Common::File *test = new Common::File();
-	assert(isDemo());
 	assert(test->open(filename.c_str()));
 
 	const uint32 fileSize = test->size();
@@ -76,6 +75,8 @@ void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	level.scene.prefix = prefix;
 	level.scene.hots = *g_parsedHots;
 	_levels[filename] = level;
+	test->close();
+	delete test;
 	free(buf);
 }
 
@@ -333,6 +334,13 @@ void HypnoEngine::runScene(Scene scene) {
 		g_system->updateScreen();
 		g_system->delayMillis(10);
 	}
+
+
+	// Deallocate videos
+	for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
+		if (it->decoder)
+			skipVideo(*it);
+	}
 }
 
 } // end of Hypno namespace
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 7061323296..1ee43bef16 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -46,6 +46,7 @@ void SpiderEngine::loadAssets() {
 			break; // No need to keep parsing
 		}
 	}
+	delete file;
 
 	arclevel = "sixdemo/c_misc/missions.lib/" + arclevel;
 	parseArcadeShooting("sixdemo", arclevel, arc);
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 5ad826dede..66171bef0d 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -109,6 +109,7 @@ void WetEngine::loadAssets() {
 				break; // No need to keep parsing
 			}
 		}
+		delete file;
 
 		parseArcadeShooting("wetlands", arclevel, arc);
 		_levels[arclevel].arcade.id = k;


Commit: a18c5f8a98b6a13d9cea55220c7aad0041e4a71d
    https://github.com/scummvm/scummvm/commit/a18c5f8a98b6a13d9cea55220c7aad0041e4a71d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: run clang-format and minor fixes

Changed paths:
    engines/hypno/actions.cpp
    engines/hypno/boyz/boyz.cpp
    engines/hypno/cursors.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/libfile.cpp
    engines/hypno/libfile.h
    engines/hypno/scene.cpp
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/spider/talk.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index ba70fb1dcd..1d562fcb80 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -11,8 +11,7 @@ namespace Hypno {
 void HypnoEngine::runMenu(Hotspots hs) {
 	const Hotspot h = *hs.begin();
 	assert(h.type == MakeMenu);
-
-	debug("hotspot actions size: %d", h.actions.size());
+	debugC(1, kHypnoDebugScene, "hotspot actions size: %d", h.actions.size());
 	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
 		Action *action = *itt;
 		if (typeid(*action) == typeid(Quit))
@@ -111,9 +110,8 @@ void HypnoEngine::runChangeLevel(ChangeLevel *a) {
 }
 
 void HypnoEngine::runTalk(Talk *a) {
-	debug("adding TALK line!");
 	_conversation.push_back(a);
 	_refreshConversation = true;
 }
 
-}
\ No newline at end of file
+} // namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/boyz/boyz.cpp b/engines/hypno/boyz/boyz.cpp
index 7223c706f2..3aca3a9b0b 100644
--- a/engines/hypno/boyz/boyz.cpp
+++ b/engines/hypno/boyz/boyz.cpp
@@ -11,4 +11,4 @@ void BoyzEngine::loadAssets() {
 	loadLib("", "boyz/preload/missions.lib");
 }
 
-}
\ No newline at end of file
+} // namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index 91654a9f00..bea49c81af 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -45,33 +45,33 @@ static const byte MOUSECURSOR_SCI[] = {
 	0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
 	0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0};
 
-static const byte circleCursor[] {
-0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 
-0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 
-0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
-0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 
-0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
-0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 
-0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 
-0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0};
+static const byte circleCursor[]{
+	0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+	0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0,
+	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+	2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+	2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+	2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+	0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0,
+	0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0};
 
-static const byte targetCursor[] {
-0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
-0, 0, 1, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0,
-0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0, 
-1, 0, 2, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 1,
-1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 1,
-1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
-1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
-1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
-1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 1,
-1, 0, 2, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 1,
-0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0,
-0, 0, 1, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0,
-0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0};
+static const byte targetCursor[]{
+	0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+	0, 0, 1, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0,
+	0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0,
+	1, 0, 2, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 1,
+	1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 1,
+	1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
+	1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
+	1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1,
+	1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 1,
+	1, 0, 2, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 0, 1,
+	0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0,
+	0, 0, 1, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0,
+	0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0};
 
 static const byte cursorPalette[] = {
 	0x00, 0x00, 0x00, // Black / Transparent
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 0b473b8402..db7fe1c965 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -23,13 +23,13 @@
 #ifndef HYPNO_GRAMMAR_H
 #define HYPNO_GRAMMAR_H
 
-#include "common/str.h"
-#include "common/hash-str.h"
+#include "common/array.h"
 #include "common/hash-ptr.h"
-#include "common/queue.h"
+#include "common/hash-str.h"
 #include "common/list.h"
-#include "common/array.h"
+#include "common/queue.h"
 #include "common/rect.h"
+#include "common/str.h"
 
 #include "video/smk_decoder.h"
 
@@ -39,16 +39,16 @@ typedef Common::String Filename;
 typedef Common::List<Filename> Filenames;
 
 enum HotspotType {
-    MakeMenu,
- 	MakeHotspot
+	MakeMenu,
+	MakeHotspot
 };
 
 class Action {
-	public:
-	virtual ~Action() {}; // needed to make Action polymorphic
+public:
+	virtual ~Action(){}; // needed to make Action polymorphic
 };
 
-typedef Common::Array<Action*> Actions;
+typedef Common::Array<Action *> Actions;
 
 class Hotspot;
 
@@ -56,9 +56,9 @@ typedef Common::Array<Hotspot> Hotspots;
 typedef Common::Array<Hotspots *> HotspotsStack;
 
 class MVideo {
-  public:
-    MVideo(Filename, Common::Point, bool, bool, bool);
-    Filename path;
+public:
+	MVideo(Filename, Common::Point, bool, bool, bool);
+	Filename path;
 	Common::Point position;
 	bool scaled;
 	bool transparent;
@@ -69,10 +69,10 @@ class MVideo {
 
 typedef Common::Array<MVideo> Videos;
 
-class Hotspot { 
-  public:
-    HotspotType type;
-    Common::String stype;
+class Hotspot {
+public:
+	HotspotType type;
+	Common::String stype;
 	Common::String stypeFlag;
 	Common::Rect rect;
 	Common::String setting;
@@ -81,25 +81,25 @@ class Hotspot {
 };
 
 class Mice : public Action {
-  public:
+public:
 	Filename path;
 	uint32 index;
 };
 
 class Palette : public Action {
-  public:
+public:
 	Filename path;
 };
 
 class Background : public Action {
-  public:
+public:
 	Filename path;
 	Common::Point origin;
 	Common::String condition;
 };
 
 class Overlay : public Action {
-  public:
+public:
 	Filename path;
 	Common::Point origin;
 	Common::String flag;
@@ -112,12 +112,12 @@ class Quit : public Action {
 };
 
 class Cutscene : public Action {
-  public:
+public:
 	Filename path;
 };
 
 class Play : public Action {
-  public:
+public:
 	Filename path;
 	Common::Point origin;
 	Common::String condition;
@@ -125,7 +125,7 @@ class Play : public Action {
 };
 
 class Ambient : public Action {
-  public:
+public:
 	Filename path;
 	Common::Point origin;
 	Common::String flag;
@@ -133,7 +133,7 @@ class Ambient : public Action {
 };
 
 class WalN : public Action {
-  public:
+public:
 	Filename path;
 	Common::Point origin;
 	Common::String condition;
@@ -141,13 +141,13 @@ class WalN : public Action {
 };
 
 class Global : public Action {
-  public:
+public:
 	Common::String variable;
 	Common::String command;
 };
 
 class TalkCommand {
-  public:
+public:
 	Common::String command;
 	Filename path;
 	uint32 num;
@@ -157,7 +157,7 @@ class TalkCommand {
 typedef Common::Array<TalkCommand> TalkCommands;
 
 class Talk : public Action {
-  public:
+public:
 	TalkCommands commands;
 	bool active;
 	Filename background;
@@ -166,13 +166,13 @@ class Talk : public Action {
 };
 
 class ChangeLevel : public Action {
-  public:
+public:
 	Filename level;
 };
 
 class Shoot {
-  public:
-    Common::String name;
+public:
+	Common::String name;
 	Filename animation;
 	Filename startSound;
 	Filename endSound;
@@ -186,8 +186,8 @@ class Shoot {
 typedef Common::Array<Shoot> Shoots;
 
 class ShootInfo {
-  public:
-    Common::String name;
+public:
+	Common::String name;
 	uint32 timestamp;
 };
 
@@ -195,13 +195,13 @@ typedef Common::List<ShootInfo> ShootSequence;
 typedef Common::Array<Common::String> Sounds;
 
 class Transition {
-  public:
+public:
 	Common::String level;
 	Filenames intros;
 };
 
 class Puzzle {
-  public:
+public:
 	Common::String name;
 	Filenames intros;
 	Common::String levelIfWin;
@@ -209,9 +209,9 @@ class Puzzle {
 };
 
 class Scene {
-  public:
-    Filename intro;
-    Common::String prefix;
+public:
+	Filename intro;
+	Common::String prefix;
 	Hotspots hots;
 	Filename sound;
 	Common::String levelIfWin;
@@ -219,13 +219,13 @@ class Scene {
 };
 
 class ArcadeShooting {
-  public:
-    uint32 id;
+public:
+	uint32 id;
 	Common::String levelIfWin;
 	Common::String levelIfLose;
 	Filenames defeatVideos;
 	Filenames winVideos;
-    Filename intro;
+	Filename intro;
 	Filename prefix;
 	Filename background;
 	Filename player;
@@ -239,8 +239,8 @@ class ArcadeShooting {
 };
 
 class Level {
-  public:
-    Transition trans;
+public:
+	Transition trans;
 	Scene scene;
 	ArcadeShooting arcade;
 	Puzzle puzzle;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index d083e49d03..06df1d1113 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -78,7 +78,7 @@ HypnoEngine::~HypnoEngine() {
 	for (Levels::iterator it = _levels.begin(); it != _levels.end(); ++it) {
 		Level level = (*it)._value;
 		for (Hotspots::iterator itt = level.scene.hots.begin(); itt != level.scene.hots.end(); ++itt) {
-			Hotspot hot = *itt; 
+			Hotspot hot = *itt;
 			for (Actions::iterator ittt = hot.actions.begin(); ittt != hot.actions.end(); ++ittt)
 				delete (*ittt);
 		}
@@ -95,7 +95,7 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 
 LibFile *HypnoEngine::loadLib(Filename prefix, Filename filename) {
 	LibFile *lib = new LibFile();
-	SearchMan.add(filename, (Common::Archive *) lib, 0, true);
+	SearchMan.add(filename, (Common::Archive *)lib, 0, true);
 	assert(lib->open(prefix, filename));
 	_archive.push_back(lib);
 	return lib;
@@ -231,8 +231,7 @@ void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool trans
 void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transparent) {
 	if (transparent) {
 		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), surf.getPixel(surf.w - 1, surf.h - 1));
-	}
-	else
+	} else
 		_compositeSurface->blitFrom(surf, Common::Point(x, y));
 }
 
@@ -290,7 +289,6 @@ Frames HypnoEngine::decodeFrames(const Common::String &name) {
 	return frames;
 }
 
-
 void HypnoEngine::changeScreenMode(Common::String mode) {
 	debugC(1, kHypnoDebugMedia, "%s(%s)", __FUNCTION__, mode.c_str());
 	if (mode == "scene") {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 63bfca2a9b..5fa8423d7d 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -210,9 +210,9 @@ public:
 	// Conversation
 	Actions _conversation;
 	bool _refreshConversation;
-	void showConversation();
-	bool rightClickedConversation(Common::Point mousePos);
-	bool leftClickedConversation(Common::Point mousePos);
+	virtual void showConversation();
+	virtual void rightClickedConversation(Common::Point mousePos);
+	virtual void leftClickedConversation(Common::Point mousePos);
 
 	// Hardcoded puzzles
 	virtual void runPuzzle(Puzzle puzzle);
@@ -242,6 +242,10 @@ public:
 	void drawHealth() override;
 	void runPuzzle(Puzzle puzzle) override;
 
+	void showConversation() override;
+	void rightClickedConversation(Common::Point mousePos) override;
+	void leftClickedConversation(Common::Point mousePos) override;
+
 private:
 	void runMatrix(Puzzle puzzle);
 };
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 0afca424d9..cefa84f480 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -20,8 +20,8 @@
  *
  */
 
-#include "hypno/hypno.h"
 #include "hypno/libfile.h"
+#include "hypno/hypno.h"
 
 namespace Hypno {
 
@@ -49,7 +49,7 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename)
 		debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
 		start = libfile.readUint32LE();
 		size = libfile.readUint32LE();
-		libfile.readUint32LE(); // some field? 
+		libfile.readUint32LE(); // some field?
 
 		pos = libfile.pos();
 		libfile.seek(start);
@@ -70,26 +70,25 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename)
 }
 
 const FileEntry *LibFile::getEntry(const Common::String &name) const {
-        for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it) {
-				//debug("checking %s", it->name.c_str());
-                if (((_prefix + it->name).equalsIgnoreCase(name)) || it->name.equalsIgnoreCase(name))
-                        return it;
-        }
+	for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it) {
+		//debug("checking %s", it->name.c_str());
+		if (((_prefix + it->name).equalsIgnoreCase(name)) || it->name.equalsIgnoreCase(name))
+			return it;
+	}
 
-        return nullptr;
+	return nullptr;
 }
 
 void LibFile::close() {
-    _fileEntries.clear();
+	_fileEntries.clear();
 }
 
-
-bool LibFile::hasFile(const Common::String &name) const { 
+bool LibFile::hasFile(const Common::String &name) const {
 	error("hasFile");
-    return false;
+	return false;
 }
 
-int LibFile::listMembers(Common::ArchiveMemberList &list) const { 
+int LibFile::listMembers(Common::ArchiveMemberList &list) const {
 	list.clear();
 	for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it)
 		list.push_back(getMember(it->name));
@@ -111,4 +110,4 @@ Common::SeekableReadStream *LibFile::createReadStreamForMember(const Common::Str
 	return stream;
 }
 
-}
\ No newline at end of file
+} // namespace Hypno
\ No newline at end of file
diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
index 3e2f3ac92b..086d4532ce 100644
--- a/engines/hypno/libfile.h
+++ b/engines/hypno/libfile.h
@@ -24,10 +24,10 @@
 #define HYPNO_LIBFILE_H
 
 #include "common/archive.h"
-#include "common/file.h"
 #include "common/array.h"
-#include "common/stream.h"
+#include "common/file.h"
 #include "common/memstream.h"
+#include "common/stream.h"
 
 namespace Hypno {
 
@@ -39,18 +39,19 @@ typedef struct FileEntry {
 
 class LibFile : public Common::Archive {
 public:
-        bool open(const Common::String &prefix, const Common::String &filename);
-        void close();
-
-        // Common::Archive API implementation
-        bool hasFile(const Common::String &name) const override;
-        int listMembers(Common::ArchiveMemberList &list) const override;
-        const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
-        Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+	bool open(const Common::String &prefix, const Common::String &filename);
+	void close();
+
+	// Common::Archive API implementation
+	bool hasFile(const Common::String &name) const override;
+	int listMembers(Common::ArchiveMemberList &list) const override;
+	const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+
 private:
-        Common::String _prefix;
-        Common::Array<FileEntry> _fileEntries;
-        const FileEntry *getEntry(const Common::String &name) const;
+	Common::String _prefix;
+	Common::Array<FileEntry> _fileEntries;
+	const FileEntry *getEntry(const Common::String &name) const;
 };
 
 } // End of namespace Hypno
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 98a549e21c..e636e9857e 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -120,7 +120,6 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			_nextHotsToAdd = selected.smenu;
 		}
 
-		//debug("hotspot clicked actions size: %d", selected.actions.size());
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
 			if (typeid(*action) == typeid(ChangeLevel))
@@ -335,7 +334,6 @@ void HypnoEngine::runScene(Scene scene) {
 		g_system->delayMillis(10);
 	}
 
-
 	// Deallocate videos
 	for (Videos::iterator it = _videosPlaying.begin(); it != _videosPlaying.end(); ++it) {
 		if (it->decoder)
@@ -343,4 +341,9 @@ void HypnoEngine::runScene(Scene scene) {
 	}
 }
 
-} // end of Hypno namespace
+void HypnoEngine::showConversation() { error("Not implemented"); }
+void HypnoEngine::rightClickedConversation(Common::Point mousePos) { error("Not implemented"); }
+void HypnoEngine::leftClickedConversation(Common::Point mousePos) { error("Not implemented"); }
+
+
+} // End of namespace Hypno
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index cad1648070..1bd39928f3 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -30,7 +30,6 @@
 
 namespace Hypno {
 
-
 static const int frame_idx[9] = {0, 1, 2, 7, 8, 3, 6, 5, 4};
 
 void SpiderEngine::drawShoot(Common::Point target) {
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 1ee43bef16..b65c347603 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -1,6 +1,5 @@
 #include "common/events.h"
 
-
 #include "hypno/grammar.h"
 #include "hypno/hypno.h"
 #include "hypno/libfile.h"
@@ -15,11 +14,6 @@ void SpiderEngine::loadAssets() {
 	Common::ArchiveMemberList files;
 	assert(missions->listMembers(files) > 0);
 
-	//LibData files;
-	//loadLib("sixdemo/c_misc/missions.lib", files);
-	uint32 i = 0;
-	uint32 j = 0;
-
 	// start level
 	Level start;
 	start.trans.level = "sixdemo/mis/demo.mis";
@@ -31,7 +25,7 @@ void SpiderEngine::loadAssets() {
 	Common::String list;
 	Common::String arclevel = files.front()->getName();
 	Common::SeekableReadStream *file = files.front()->createReadStream();
-	debug("Splitting file: %s", arclevel);
+
 	byte x;
 	while (!file->eos()) {
 		x = file->readByte();
@@ -57,7 +51,7 @@ void SpiderEngine::loadAssets() {
 	loadLib("", "sixdemo/c_misc/fonts.lib");
 	loadLib("sixdemo/c_misc/sound.lib/", "sixdemo/c_misc/sound.lib");
 	loadLib("sixdemo/demo/sound.lib/", "sixdemo/demo/sound.lib");
-	
+
 	// Read assets from mis files
 	parseScene("sixdemo", "mis/demo.mis");
 	ChangeLevel *cl = new ChangeLevel();
diff --git a/engines/hypno/spider/talk.cpp b/engines/hypno/spider/talk.cpp
index ce60e9a438..1d0075e626 100644
--- a/engines/hypno/spider/talk.cpp
+++ b/engines/hypno/spider/talk.cpp
@@ -3,7 +3,8 @@
 
 namespace Hypno {
 
-void HypnoEngine::showConversation() {
+void SpiderEngine::showConversation() {
+	debugC(1, kHypnoDebugScene, "Showing conversation");
 	uint32 x = 18;
 	uint32 y = 20;
 	Graphics::Surface *speaker = decodeFrame("dialog/speaker3.smk", 0);
@@ -21,21 +22,23 @@ void HypnoEngine::showConversation() {
 			}
 			if (!path.empty()) {
 				frame = frame;
-				debug("decoding %s frame %d", path.c_str(), frame);
 				Graphics::Surface *surf = decodeFrame("dialog/" + path, frame);
 
 				drawImage(*speaker, x, y, false);
 				drawImage(*surf, x + speaker->w, y, false);
 				a->rect = Common::Rect(x + speaker->w, y, x + surf->w, y + surf->h);
 				y = y + surf->h;
-				//delete surf;
-				//free(surf);
+				
+				surf->free();
+				delete surf;
 			}
 		}
 	}
+	speaker->free();
+	delete speaker;
 }
 
-bool HypnoEngine::leftClickedConversation(Common::Point mousePos) {
+void SpiderEngine::leftClickedConversation(Common::Point mousePos) {
 	Talk *t;
 	bool activeFound = false;
 	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
@@ -45,17 +48,17 @@ bool HypnoEngine::leftClickedConversation(Common::Point mousePos) {
 			a->active = false;
 			for (TalkCommands::const_iterator it = a->commands.begin(); it != a->commands.end(); ++it) {
 				if (it->command == "A") {
-					debug("Adding %d", it->num);
+					debugC(1, kHypnoDebugScene, "Adding option %d", it->num);
 					t = (Talk *)_conversation[it->num];
 					t->active = true;
 					_refreshConversation = true;
 				} else if (it->command == "D") {
-					debug("Disabling %d", it->num);
+					debugC(1, kHypnoDebugScene, "Disabling option %d", it->num);
 					t = (Talk *)_conversation[it->num];
 					t->active = false;
 					_refreshConversation = true;
 				} else if (it->command == "P") {
-					debug("Playing %s", it->path.c_str());
+					debugC(1, kHypnoDebugScene, "Playing %s", it->path.c_str());
 					_nextSequentialVideoToPlay.push_back(MVideo(it->path, it->position, false, false, false));
 				}
 			}
@@ -71,13 +74,13 @@ bool HypnoEngine::leftClickedConversation(Common::Point mousePos) {
 	}
 }
 
-bool HypnoEngine::rightClickedConversation(Common::Point mousePos) {
+void SpiderEngine::rightClickedConversation(Common::Point mousePos) {
 	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
 		Talk *a = (Talk *)*itt;
 		if (a->active && a->rect.contains(mousePos)) {
 			for (TalkCommands::const_iterator it = a->commands.begin(); it != a->commands.end(); ++it) {
 				if (it->command == "I") {
-					debug("Playing %s", it->path.c_str());
+					debugC(1, kHypnoDebugScene, "Playing %s", it->path.c_str());
 					// Not sure why position is 50, 50 since there is only one pixel
 					_nextSequentialVideoToPlay.push_back(MVideo(it->path, Common::Point(0, 0), false, false, false));
 				}
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index 6c375c7fd7..ec3c8d96d9 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -13,12 +13,12 @@ bool WetEngine::clickedSecondaryShoot(Common::Point mousePos) {
 void WetEngine::drawShoot(Common::Point mousePos) {
 	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	_compositeSurface->drawLine(0, _screenH, mousePos.x, mousePos.y, c);
-	_compositeSurface->drawLine(0, _screenH, mousePos.x-1, mousePos.y, c);
-	_compositeSurface->drawLine(0, _screenH, mousePos.x-2, mousePos.y, c);
+	_compositeSurface->drawLine(0, _screenH, mousePos.x - 1, mousePos.y, c);
+	_compositeSurface->drawLine(0, _screenH, mousePos.x - 2, mousePos.y, c);
 
 	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x, mousePos.y, c);
-	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x-1, mousePos.y, c);
-	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x-2, mousePos.y, c);
+	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x - 1, mousePos.y, c);
+	_compositeSurface->drawLine(_screenW, _screenH, mousePos.x - 2, mousePos.y, c);
 	playSound(_soundPath + _shootSound, 1);
 }
 
@@ -54,15 +54,14 @@ void WetEngine::drawPlayer() {
 }
 
 static const int uiPos[2][3][2] = {
-	{ {70, 160}, {180, 160}, {220, 185} }, // c31
-	{ {60, 167}, {190, 167}, {135, 187} }, // c52
+	{{70, 160}, {180, 160}, {220, 185}}, // c31
+	{{60, 167}, {190, 167}, {135, 187}}, // c52
 };
 
 void WetEngine::drawHealth() {
 	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	int p = (100 * _health) / _maxHealth;
 	if (_playerFrameIdx < _playerFrameSep) {
-		// /const int *ui[3][2] = &uiPos; 
 		uint32 id = _levelId;
 		_font->drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), uiPos[id][0][0], uiPos[id][0][1], 65, c);
 		_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), uiPos[id][1][0], uiPos[id][1][1], 72, c);
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 66171bef0d..b0464ffcf7 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -39,7 +39,6 @@ void WetEngine::loadAssets() {
 		afiles.push_back(*it);
 	}
 
-
 	uint32 i = 0;
 	uint32 j = 0;
 	uint32 k = 0;
@@ -118,13 +117,13 @@ void WetEngine::loadAssets() {
 		if (k < files.size() - 1) {
 			_levels[arclevel].arcade.levelIfWin = afiles[k + 1]->getName();
 			// failing a level in the demo takes you to the next one anyway
-			_levels[arclevel].arcade.levelIfLose = afiles[k + 1]->getName(); 
+			_levels[arclevel].arcade.levelIfLose = afiles[k + 1]->getName();
 		}
 	}
 
 	// After finish the second level, it's always game over
-	_levels[afiles[k-1]->getName()].arcade.levelIfWin = "<gameover>";
-	_levels[afiles[k-1]->getName()].arcade.levelIfLose = "<gameover>"; 
+	_levels[afiles[k - 1]->getName()].arcade.levelIfWin = "<gameover>";
+	_levels[afiles[k - 1]->getName()].arcade.levelIfLose = "<gameover>";
 
 	Level over;
 	over.trans.level = "<quit>";


Commit: a571caa306d09e4935068027f3b2231b0fbfa933
    https://github.com/scummvm/scummvm/commit/a571caa306d09e4935068027f3b2231b0fbfa933
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: removed debugs

Changed paths:
    engines/hypno/hypno.cpp
    engines/hypno/libfile.cpp


diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 06df1d1113..10ff2d8f89 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -141,7 +141,6 @@ Common::Error HypnoEngine::run() {
 }
 
 void HypnoEngine::runLevel(Common::String name) {
-	debug("level: %s", name.c_str());
 	assert(_levels.contains(name));
 	stopSound();
 	_music = "";
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index cefa84f480..9fc42e7643 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -71,7 +71,6 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename)
 
 const FileEntry *LibFile::getEntry(const Common::String &name) const {
 	for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it) {
-		//debug("checking %s", it->name.c_str());
 		if (((_prefix + it->name).equalsIgnoreCase(name)) || it->name.equalsIgnoreCase(name))
 			return it;
 	}


Commit: 18c81f9b30156c2080e28a750fafe7d85aa165ba
    https://github.com/scummvm/scummvm/commit/18c81f9b30156c2080e28a750fafe7d85aa165ba
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added typeinfo include and license in actions.cpp

Changed paths:
    engines/hypno/actions.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index 1d562fcb80..bb6a13ae46 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -1,4 +1,26 @@
-
+/* 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 <typeinfo>
 #include "common/events.h"
 
 #include "hypno/grammar.h"


Commit: a0bce5377f3b3a2d622a23e6ff26564cbd26ec7b
    https://github.com/scummvm/scummvm/commit/a0bce5377f3b3a2d622a23e6ff26564cbd26ec7b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added typeinfo include to scene.cpp

Changed paths:
    engines/hypno/scene.cpp


diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index e636e9857e..c70c0fd86c 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include <typeinfo>
 #include "common/events.h"
 
 #include "hypno/grammar.h"


Commit: 7387391aa3299359321bd195dff10e4c3c5858b8
    https://github.com/scummvm/scummvm/commit/7387391aa3299359321bd195dff10e4c3c5858b8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: removed useless override

Changed paths:
    engines/hypno/libfile.h


diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
index 086d4532ce..592587cdab 100644
--- a/engines/hypno/libfile.h
+++ b/engines/hypno/libfile.h
@@ -43,10 +43,10 @@ public:
 	void close();
 
 	// Common::Archive API implementation
-	bool hasFile(const Common::String &name) const override;
+	bool hasFile(const Common::String &name) const;
 	int listMembers(Common::ArchiveMemberList &list) const override;
-	const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
-	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+	const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
 
 private:
 	Common::String _prefix;


Commit: d5a9ef4511a9533f86e6a967029307a5baf78222
    https://github.com/scummvm/scummvm/commit/d5a9ef4511a9533f86e6a967029307a5baf78222
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: removed useless local variables

Changed paths:
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index b0464ffcf7..44fd7168f3 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -39,8 +39,6 @@ void WetEngine::loadAssets() {
 		afiles.push_back(*it);
 	}
 
-	uint32 i = 0;
-	uint32 j = 0;
 	uint32 k = 0;
 
 	Common::String arc;


Commit: 5f4e72ab9eb1186d18e52c6f0f8925d91a73df2d
    https://github.com/scummvm/scummvm/commit/5f4e72ab9eb1186d18e52c6f0f8925d91a73df2d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added pregenerated flex/lex code

Changed paths:
  A engines/hypno/grammar_arc.cpp
  A engines/hypno/grammar_mis.cpp
  A engines/hypno/lexer_arc.cpp
  A engines/hypno/lexer_mis.cpp
  A engines/hypno/tokens_arc.h
  A engines/hypno/tokens_mis.h


diff --git a/engines/hypno/grammar_arc.cpp b/engines/hypno/grammar_arc.cpp
new file mode 100644
index 0000000000..211be2d277
--- /dev/null
+++ b/engines/hypno/grammar_arc.cpp
@@ -0,0 +1,1877 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Substitute the type names.  */
+#define YYSTYPE         HYPNO_ARC_STYPE
+/* Substitute the variable and function names.  */
+#define yyparse         HYPNO_ARC_parse
+#define yylex           HYPNO_ARC_lex
+#define yyerror         HYPNO_ARC_error
+#define yydebug         HYPNO_ARC_debug
+#define yynerrs         HYPNO_ARC_nerrs
+
+#define yylval          HYPNO_ARC_lval
+#define yychar          HYPNO_ARC_char
+
+/* Copy the first part of user declarations.  */
+#line 28 "engines/hypno/grammar_arc.y" /* yacc.c:339  */
+
+
+#include "common/array.h"
+#include "hypno/grammar.h"
+#include <stdio.h>
+
+#undef yyerror
+#define yyerror	 HYPNO_ARC_xerror
+
+Hypno::Shoot *shoot;
+
+extern int HYPNO_ARC_lex();
+extern int HYPNO_ARC_parse();
+extern int yylineno;
+
+void HYPNO_ARC_xerror(const char *str) {
+	error("ERROR: %s", str);
+}
+
+int HYPNO_ARC_wrap() {
+    return 1;
+}
+
+using namespace Hypno;
+
+
+#line 102 "engines/hypno/grammar_arc.cpp" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "tokens_arc.h".  */
+#ifndef YY_HYPNO_ARC_ENGINES_HYPNO_TOKENS_ARC_H_INCLUDED
+# define YY_HYPNO_ARC_ENGINES_HYPNO_TOKENS_ARC_H_INCLUDED
+/* Debug traces.  */
+#ifndef HYPNO_ARC_DEBUG
+# if defined YYDEBUG
+#if YYDEBUG
+#   define HYPNO_ARC_DEBUG 1
+#  else
+#   define HYPNO_ARC_DEBUG 0
+#  endif
+# else /* ! defined YYDEBUG */
+#  define HYPNO_ARC_DEBUG 0
+# endif /* ! defined YYDEBUG */
+#endif  /* ! defined HYPNO_ARC_DEBUG */
+#if HYPNO_ARC_DEBUG
+extern int HYPNO_ARC_debug;
+#endif
+
+/* Token type.  */
+#ifndef HYPNO_ARC_TOKENTYPE
+# define HYPNO_ARC_TOKENTYPE
+  enum HYPNO_ARC_tokentype
+  {
+    NAME = 258,
+    FILENAME = 259,
+    BNTOK = 260,
+    SNTOK = 261,
+    NUM = 262,
+    YXTOK = 263,
+    CTOK = 264,
+    DTOK = 265,
+    HTOK = 266,
+    HETOK = 267,
+    RETTOK = 268,
+    QTOK = 269,
+    ENCTOK = 270,
+    PTOK = 271,
+    FTOK = 272,
+    TTOK = 273,
+    TPTOK = 274,
+    ATOK = 275,
+    VTOK = 276,
+    OTOK = 277,
+    O1TOK = 278,
+    NTOK = 279,
+    RTOK = 280,
+    ITOK = 281,
+    ZTOK = 282,
+    FNTOK = 283,
+    NONETOK = 284,
+    A0TOK = 285,
+    K0TOK = 286,
+    P0TOK = 287,
+    WTOK = 288,
+    XTOK = 289,
+    CB3TOK = 290,
+    C02TOK = 291
+  };
+#endif
+
+/* Value type.  */
+#if ! defined HYPNO_ARC_STYPE && ! defined HYPNO_ARC_STYPE_IS_DECLARED
+
+union HYPNO_ARC_STYPE
+{
+#line 55 "engines/hypno/grammar_arc.y" /* yacc.c:355  */
+
+	char *s; /* string value */
+	int i;	 /* integer value */
+
+#line 192 "engines/hypno/grammar_arc.cpp" /* yacc.c:355  */
+};
+
+typedef union HYPNO_ARC_STYPE HYPNO_ARC_STYPE;
+# define HYPNO_ARC_STYPE_IS_TRIVIAL 1
+# define HYPNO_ARC_STYPE_IS_DECLARED 1
+#endif
+
+
+extern HYPNO_ARC_STYPE HYPNO_ARC_lval;
+
+int HYPNO_ARC_parse (void);
+
+#endif /* !YY_HYPNO_ARC_ENGINES_HYPNO_TOKENS_ARC_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 209 "engines/hypno/grammar_arc.cpp" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined HYPNO_ARC_STYPE_IS_TRIVIAL && HYPNO_ARC_STYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  25
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   117
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  37
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  7
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  47
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  109
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   291
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36
+};
+
+#if HYPNO_ARC_DEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint8 yyrline[] =
+{
+       0,    77,    77,    81,    82,    83,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    97,   100,   103,   107,   108,
+     112,   113,   123,   133,   134,   137,   140,   141,   144,   145,
+     147,   152,   157,   162,   166,   170,   174,   175,   178,   182,
+     185,   188,   189,   190,   191,   195,   202,   203
+};
+#endif
+
+#if HYPNO_ARC_DEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "NAME", "FILENAME", "BNTOK", "SNTOK",
+  "NUM", "YXTOK", "CTOK", "DTOK", "HTOK", "HETOK", "RETTOK", "QTOK",
+  "ENCTOK", "PTOK", "FTOK", "TTOK", "TPTOK", "ATOK", "VTOK", "OTOK",
+  "O1TOK", "NTOK", "RTOK", "ITOK", "ZTOK", "FNTOK", "NONETOK", "A0TOK",
+  "K0TOK", "P0TOK", "WTOK", "XTOK", "CB3TOK", "C02TOK", "$accept", "start",
+  "header", "hline", "enc", "body", "bline", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291
+};
+# endif
+
+#define YYPACT_NINF -20
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-20)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+      -5,    56,     4,     7,    11,     1,    10,   -19,   -17,    56,
+      18,    24,    32,     5,    36,    34,    35,    38,    39,    43,
+      44,    46,    30,    27,    50,   -20,   -20,    49,   -20,   -20,
+      64,    77,   -20,    78,    79,   -20,    80,    81,    82,    83,
+      84,    85,    86,   -20,   -20,   -20,   -20,    87,    91,    89,
+      90,    92,    94,    93,   -20,    95,     9,   -20,     6,    96,
+      97,    98,    99,   -20,    88,    56,   -20,   -20,   100,   101,
+     -20,   -20,   -20,   -20,   105,   -20,   -20,   -20,   -20,   103,
+      49,   -20,   -20,   -20,   -20,   104,   106,   -20,   -20,   -20,
+     -20,   107,   108,   109,   -20,    -4,   -20,   -20,   -20,   -20,
+     -20,   -20,   -20,   -20,   -20,   -20,   -20,   -20,   -20
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     4,     1,    21,    27,     6,     8,
+       0,     0,     5,     0,     0,     7,     0,     0,     0,     0,
+       0,     0,     0,    17,    18,    19,    25,     0,     0,     0,
+       0,     0,     0,     0,    46,     0,     0,    47,     0,     0,
+       0,     0,     0,     2,     0,     0,    26,    22,     0,     0,
+      20,     9,    15,    16,     0,    10,    11,    12,    13,     0,
+      27,    41,    44,    42,    32,     0,     0,    33,    34,    30,
+      31,     0,     0,     0,    43,     0,     3,    24,    23,    14,
+      37,    45,    40,    36,    35,    38,    39,    29,    28
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -20,   -20,    -9,   -20,    37,    17,   -20
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     2,    23,    24,    67,    63,    64
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+      32,    47,    48,     1,    25,    49,    50,    51,    28,    36,
+      89,    26,    87,    52,    88,    27,    30,    29,    53,    31,
+      54,    55,    56,    57,    58,    33,    59,    60,    61,    62,
+     107,    34,    47,    48,    37,    90,    49,    50,    51,    35,
+      38,    39,    40,    46,    52,    41,    42,    43,    44,    53,
+      45,    54,    55,    56,    57,    58,    96,    59,    60,    61,
+      62,     3,     4,    65,    66,     5,     6,     7,     8,     9,
+      10,    68,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    84,    83,
+      85,    95,    86,    91,    92,    93,    94,    97,    98,    99,
+     100,   102,   108,   103,   104,   105,   106,   101
+};
+
+static const yytype_uint8 yycheck[] =
+{
+       9,     5,     6,     8,     0,     9,    10,    11,     7,     4,
+       4,     4,     3,    17,     5,     4,    35,     7,    22,    36,
+      24,    25,    26,    27,    28,     7,    30,    31,    32,    33,
+      34,     7,     5,     6,    29,    29,     9,    10,    11,     7,
+       4,     7,     7,    13,    17,     7,     7,     4,     4,    22,
+       4,    24,    25,    26,    27,    28,    65,    30,    31,    32,
+      33,     5,     6,    13,    15,     9,    10,    11,    12,    13,
+      14,     7,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,     7,     7,     7,     7,     7,     7,
+       7,     7,     7,     7,     7,     4,     7,     7,     4,     7,
+       7,    13,     7,     7,     7,     7,     7,     7,     7,     4,
+       7,     7,    95,     7,     7,     7,     7,    80
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     8,    38,     5,     6,     9,    10,    11,    12,    13,
+      14,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    39,    40,     0,     4,     4,     7,     7,
+      35,    36,    39,     7,     7,     7,     4,    29,     4,     7,
+       7,     7,     7,     4,     4,     4,    13,     5,     6,     9,
+      10,    11,    17,    22,    24,    25,    26,    27,    28,    30,
+      31,    32,    33,    42,    43,    13,    15,    41,     7,     7,
+       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       4,     7,     7,     7,     4,     7,     7,     3,     5,     4,
+      29,     7,     7,     7,     7,    13,    39,     7,     7,     4,
+       7,    41,     7,     7,     7,     7,     7,    34,    42
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    37,    38,    39,    39,    39,    40,    40,    40,    40,
+      40,    40,    40,    40,    40,    40,    40,    40,    40,    40,
+      40,    40,    40,    40,    40,    40,    41,    41,    42,    42,
+      43,    43,    43,    43,    43,    43,    43,    43,    43,    43,
+      43,    43,    43,    43,    43,    43,    43,    43
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     3,     3,     1,     2,     2,     2,     2,     3,
+       3,     3,     3,     3,     4,     3,     3,     2,     2,     2,
+       3,     2,     3,     4,     4,     2,     1,     0,     3,     3,
+       2,     2,     2,     2,     2,     3,     3,     3,     3,     3,
+       3,     2,     2,     2,     2,     3,     1,     1
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if HYPNO_ARC_DEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              );
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !HYPNO_ARC_DEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !HYPNO_ARC_DEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+{
+  YYUSE (yyvaluep);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (void)
+{
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex ();
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 6:
+#line 86 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("C %d", (yyvsp[0].i)); }
+#line 1349 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 87 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("F %d", (yyvsp[0].i)); }
+#line 1355 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 88 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("D %d", (yyvsp[0].i)); }
+#line 1361 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 89 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("P %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1367 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 90 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("A %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1373 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 91 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("V %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1379 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 92 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1385 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 93 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("O1 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1391 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 94 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		  debug("Tp %s %d %s", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].s)); 
+		}
+#line 1399 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 97 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		  debug("T %s %d", (yyvsp[-1].s), (yyvsp[0].i)); 
+		}
+#line 1407 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 100 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		  debug("T NONE %d", (yyvsp[0].i)); 
+		}
+#line 1415 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 103 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		  g_parsedArc.background = (yyvsp[0].s); 
+		  debug("N %s", (yyvsp[0].s)); 
+		}
+#line 1424 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 107 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("R %s", (yyvsp[0].s)); }
+#line 1430 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 108 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+  		  g_parsedArc.player = (yyvsp[0].s); 
+		  debug("I %s", (yyvsp[0].s)); 
+		}
+#line 1439 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 112 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("Q %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1445 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 113 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    {
+		  if (Common::String("B0") == (yyvsp[-1].s))
+		  	g_parsedArc.intro = (yyvsp[0].s);
+		  else if(Common::String("B1") == (yyvsp[-1].s) || Common::String("B2") == (yyvsp[-1].s))
+		    g_parsedArc.winVideos.push_back((yyvsp[0].s));
+		  else if(Common::String("B3") == (yyvsp[-1].s) || Common::String("B4") == (yyvsp[-1].s))
+		    g_parsedArc.defeatVideos.push_back((yyvsp[0].s));
+		 	
+		  debug("BN %s", (yyvsp[0].s)); 
+		}
+#line 1460 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 123 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    {
+		  if (Common::String("S0") == (yyvsp[-2].s))
+		  	g_parsedArc.music = (yyvsp[-1].s);
+		  else if (Common::String("S1") == (yyvsp[-2].s))
+		  	g_parsedArc.shootSound = (yyvsp[-1].s);
+		  else if (Common::String("S4") == (yyvsp[-2].s))
+		    g_parsedArc.enemySound = (yyvsp[-1].s); 
+
+		  debug("SN %s", (yyvsp[-1].s)); 
+		}
+#line 1475 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 133 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("HE %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1481 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 24:
+#line 134 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		  g_parsedArc.health = (yyvsp[-1].i);
+		  debug("H %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1489 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 25:
+#line 137 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("Z"); }
+#line 1495 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 30:
+#line 147 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		shoot = new Shoot();
+		shoot->animation = (yyvsp[0].s);
+		debug("FN %s", (yyvsp[0].s)); 
+	 	}
+#line 1505 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 31:
+#line 152 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		shoot = new Shoot();
+		shoot->animation = "NONE";
+		debug("FN NONE"); 
+	 	}
+#line 1515 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 32:
+#line 157 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		shoot = new Shoot();
+		shoot->animation = (yyvsp[0].s);
+		debug("FN %s", (yyvsp[0].s)); 
+	 	}
+#line 1525 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 33:
+#line 162 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		 shoot->name = (yyvsp[0].s);
+		 debug("I %s", (yyvsp[0].s)); 
+	   }
+#line 1534 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 34:
+#line 166 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    {  // Workaround for NAME == B1
+		 shoot->name = (yyvsp[0].s);
+		 debug("I %s", (yyvsp[0].s)); 
+	   }
+#line 1543 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 35:
+#line 170 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		 shoot->position = Common::Point((yyvsp[-1].i), (yyvsp[0].i));
+		 debug("A0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+		}
+#line 1552 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 36:
+#line 174 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("R %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1558 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 37:
+#line 175 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+
+		 debug("BN %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1566 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 38:
+#line 178 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		 shoot->explosionFrame = (yyvsp[0].i);
+		 debug("K0 %d %d", (yyvsp[-1].i), (yyvsp[0].i));
+		}
+#line 1575 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 39:
+#line 182 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    {
+		debug("P0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+	   }
+#line 1583 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 40:
+#line 185 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		debug("O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+	   }
+#line 1591 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 41:
+#line 188 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("C %d", (yyvsp[0].i)); }
+#line 1597 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 42:
+#line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("H %d", (yyvsp[0].i)); }
+#line 1603 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 43:
+#line 190 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("W %d", (yyvsp[0].i)); }
+#line 1609 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 44:
+#line 191 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		 shoot->damage = (yyvsp[0].i);
+		 debug("D %d", (yyvsp[0].i)); 
+		}
+#line 1618 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 45:
+#line 195 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { 
+		  if (Common::String("S1") == (yyvsp[-2].s))
+		  	shoot->endSound = (yyvsp[-1].s);
+		  //else if (Common::String("S2") == $1)
+		  //	shoot->startSound = $2;
+		 
+		 debug("SN %s", (yyvsp[-1].s)); }
+#line 1630 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 46:
+#line 202 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("N"); }
+#line 1636 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 47:
+#line 203 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    {
+		g_parsedArc.shoots.push_back(*shoot); 
+		//delete shoot; 
+		//shoot = nullptr;
+	    debug("Z"); 
+		}
+#line 1647 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+
+#line 1651 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
diff --git a/engines/hypno/grammar_mis.cpp b/engines/hypno/grammar_mis.cpp
new file mode 100644
index 0000000000..b7f4d197e7
--- /dev/null
+++ b/engines/hypno/grammar_mis.cpp
@@ -0,0 +1,1960 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Substitute the type names.  */
+#define YYSTYPE         HYPNO_MIS_STYPE
+/* Substitute the variable and function names.  */
+#define yyparse         HYPNO_MIS_parse
+#define yylex           HYPNO_MIS_lex
+#define yyerror         HYPNO_MIS_error
+#define yydebug         HYPNO_MIS_debug
+#define yynerrs         HYPNO_MIS_nerrs
+
+#define yylval          HYPNO_MIS_lval
+#define yychar          HYPNO_MIS_char
+
+/* Copy the first part of user declarations.  */
+#line 28 "engines/hypno/grammar_mis.y" /* yacc.c:339  */
+
+
+#include "common/array.h"
+#include "hypno/grammar.h"
+#include <stdio.h>
+
+#undef yyerror
+#define yyerror	 HYPNO_MIS_xerror
+
+extern int HYPNO_MIS_lex();
+extern int HYPNO_MIS_parse();
+extern int yylineno;
+
+Common::Array<uint32> smenu_idx;
+Hypno::HotspotsStack stack;
+Hypno::Talk *talk_action = nullptr;
+
+void HYPNO_MIS_xerror(const char *str) {
+	error("ERROR: %s", str);
+}
+
+int HYPNO_MIS_wrap() {
+    return 1;
+}
+
+using namespace Hypno;
+
+
+#line 104 "engines/hypno/grammar_mis.cpp" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "tokens_mis.h".  */
+#ifndef YY_HYPNO_MIS_ENGINES_HYPNO_TOKENS_MIS_H_INCLUDED
+# define YY_HYPNO_MIS_ENGINES_HYPNO_TOKENS_MIS_H_INCLUDED
+/* Debug traces.  */
+#ifndef HYPNO_MIS_DEBUG
+# if defined YYDEBUG
+#if YYDEBUG
+#   define HYPNO_MIS_DEBUG 1
+#  else
+#   define HYPNO_MIS_DEBUG 0
+#  endif
+# else /* ! defined YYDEBUG */
+#  define HYPNO_MIS_DEBUG 0
+# endif /* ! defined YYDEBUG */
+#endif  /* ! defined HYPNO_MIS_DEBUG */
+#if HYPNO_MIS_DEBUG
+extern int HYPNO_MIS_debug;
+#endif
+
+/* Token type.  */
+#ifndef HYPNO_MIS_TOKENTYPE
+# define HYPNO_MIS_TOKENTYPE
+  enum HYPNO_MIS_tokentype
+  {
+    NAME = 258,
+    FILENAME = 259,
+    FLAG = 260,
+    COMMENT = 261,
+    GSSWITCH = 262,
+    COMMAND = 263,
+    NUM = 264,
+    HOTSTOK = 265,
+    CUTSTOK = 266,
+    BACKTOK = 267,
+    RETTOK = 268,
+    TIMETOK = 269,
+    PALETOK = 270,
+    BBOXTOK = 271,
+    OVERTOK = 272,
+    WALNTOK = 273,
+    MICETOK = 274,
+    PLAYTOK = 275,
+    ENDTOK = 276,
+    MENUTOK = 277,
+    SMENTOK = 278,
+    ESCPTOK = 279,
+    NRTOK = 280,
+    AMBITOK = 281,
+    GLOBTOK = 282,
+    TONTOK = 283,
+    TOFFTOK = 284,
+    TALKTOK = 285,
+    INACTOK = 286,
+    FDTOK = 287,
+    BOXXTOK = 288,
+    PG = 289,
+    PA = 290,
+    PD = 291,
+    PH = 292,
+    PF = 293,
+    PE = 294,
+    PP = 295,
+    PI = 296
+  };
+#endif
+
+/* Value type.  */
+#if ! defined HYPNO_MIS_STYPE && ! defined HYPNO_MIS_STYPE_IS_DECLARED
+
+union HYPNO_MIS_STYPE
+{
+#line 57 "engines/hypno/grammar_mis.y" /* yacc.c:355  */
+
+	char *s; /* string value */
+	int i;	 /* integer value */
+
+#line 199 "engines/hypno/grammar_mis.cpp" /* yacc.c:355  */
+};
+
+typedef union HYPNO_MIS_STYPE HYPNO_MIS_STYPE;
+# define HYPNO_MIS_STYPE_IS_TRIVIAL 1
+# define HYPNO_MIS_STYPE_IS_DECLARED 1
+#endif
+
+
+extern HYPNO_MIS_STYPE HYPNO_MIS_lval;
+
+int HYPNO_MIS_parse (void);
+
+#endif /* !YY_HYPNO_MIS_ENGINES_HYPNO_TOKENS_MIS_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 216 "engines/hypno/grammar_mis.cpp" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined HYPNO_MIS_STYPE_IS_TRIVIAL && HYPNO_MIS_STYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  3
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   91
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  42
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  11
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  43
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  102
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   296
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41
+};
+
+#if HYPNO_MIS_DEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,    74,    74,    77,    80,    81,    82,    85,    88,   104,
+     113,   128,   134,   135,   145,   154,   163,   173,   181,   189,
+     197,   207,   215,   221,   229,   233,   236,   237,   241,   242,
+     248,   249,   255,   261,   267,   274,   281,   282,   285,   286,
+     289,   290,   293,   294
+};
+#endif
+
+#if HYPNO_MIS_DEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "NAME", "FILENAME", "FLAG", "COMMENT",
+  "GSSWITCH", "COMMAND", "NUM", "HOTSTOK", "CUTSTOK", "BACKTOK", "RETTOK",
+  "TIMETOK", "PALETOK", "BBOXTOK", "OVERTOK", "WALNTOK", "MICETOK",
+  "PLAYTOK", "ENDTOK", "MENUTOK", "SMENTOK", "ESCPTOK", "NRTOK", "AMBITOK",
+  "GLOBTOK", "TONTOK", "TOFFTOK", "TALKTOK", "INACTOK", "FDTOK", "BOXXTOK",
+  "PG", "PA", "PD", "PH", "PF", "PE", "PP", "PI", "$accept", "start",
+  "init", "lines", "end", "line", "alloctalk", "talk", "mflag", "flag",
+  "gsswitch", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295,   296
+};
+# endif
+
+#define YYPACT_NINF -68
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-68)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+     -68,    12,    43,   -68,    -5,     9,    10,   -68,     6,    13,
+      14,    17,    18,    20,    15,    22,   -68,   -68,    25,    19,
+     -68,   -68,    43,    21,    23,   -68,    26,   -68,   -68,    27,
+      28,    30,    50,   -68,     5,    59,    68,    11,   -68,    43,
+      63,    65,    66,    67,   -68,    69,   -68,   -68,    70,   -68,
+      73,    11,    11,    71,    11,    11,    11,    11,    11,   -68,
+      72,    74,   -68,   -68,    75,    24,    77,    24,    24,    77,
+      76,   -68,   -68,    78,   -68,   -68,   -68,   -68,   -68,    79,
+      80,    81,   -68,    77,   -68,   -68,    77,    77,   -68,    82,
+     -68,    11,    11,   -68,   -68,   -68,   -68,    24,   -68,   -68,
+      77,   -68
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       3,     0,     0,     1,     0,     0,     0,     7,     0,     0,
+       0,     0,     0,     0,     0,     0,    10,    11,     0,     0,
+      24,     2,     0,     5,     0,    19,     0,    12,    18,     0,
+       0,     0,     0,    23,    39,     0,     0,    37,     6,     0,
+       0,     0,     0,     0,    21,     0,    38,     8,     0,    14,
+       0,    37,    37,     0,    37,    37,    37,    37,    37,    36,
+       0,     0,    22,     4,     0,    43,    41,    43,    43,    41,
+       0,    25,    26,     0,    29,    32,    33,    30,    31,     0,
+       0,     0,    42,    41,    40,    17,    41,    41,    15,     0,
+      28,    37,    37,     9,    13,    20,    16,    43,    34,    35,
+      41,    27
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -68,   -68,   -68,   -12,   -68,   -68,   -68,   -51,   -68,   -67,
+     -59
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     1,     2,    21,    22,    23,    37,    62,    47,    85,
+      83
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+      71,    72,    88,    74,    75,    76,    77,    78,    86,    87,
+      38,    24,     3,    25,    26,    27,    94,    28,    29,    95,
+      96,    30,    31,    50,    32,    34,    36,    63,    33,    35,
+      46,    82,    40,   101,    39,    41,    42,    43,   100,    44,
+      98,    99,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,     4,     5,     6,     7,     8,     9,    45,
+      10,    11,    12,    13,    14,    15,    16,    17,    48,    18,
+      19,    49,    64,    20,    65,    66,    67,    70,    68,    69,
+      73,    79,    84,    80,    81,    89,     0,    90,    91,    92,
+      93,    97
+};
+
+static const yytype_int8 yycheck[] =
+{
+      51,    52,    69,    54,    55,    56,    57,    58,    67,    68,
+      22,    16,     0,     4,     4,     9,    83,     4,     4,    86,
+      87,     4,     4,    12,     4,     3,     7,    39,    13,     4,
+      25,     7,     9,   100,    13,     9,     9,     9,    97,     9,
+      91,    92,    31,    32,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    10,    11,    12,    13,    14,    15,     9,
+      17,    18,    19,    20,    21,    22,    23,    24,     9,    26,
+      27,     3,     9,    30,     9,     9,     9,     4,     9,     9,
+       9,     9,     5,     9,     9,     9,    -1,     9,     9,     9,
+       9,     9
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    43,    44,     0,    10,    11,    12,    13,    14,    15,
+      17,    18,    19,    20,    21,    22,    23,    24,    26,    27,
+      30,    45,    46,    47,    16,     4,     4,     9,     4,     4,
+       4,     4,     4,    13,     3,     4,     7,    48,    45,    13,
+       9,     9,     9,     9,     9,     9,    25,    50,     9,     3,
+      12,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    49,    45,     9,     9,     9,     9,     9,     9,
+       4,    49,    49,     9,    49,    49,    49,    49,    49,     9,
+       9,     9,     7,    52,     5,    51,    52,    52,    51,     9,
+       9,     9,     9,     9,    51,    51,    51,     9,    49,    49,
+      52,    51
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    42,    43,    44,    45,    45,    45,    46,    47,    47,
+      47,    47,    47,    47,    47,    47,    47,    47,    47,    47,
+      47,    47,    47,    47,    48,    49,    49,    49,    49,    49,
+      49,    49,    49,    49,    49,    49,    49,    49,    50,    50,
+      51,    51,    52,    52
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     2,     0,     3,     1,     2,     1,     3,     6,
+       1,     1,     2,     6,     3,     5,     6,     5,     2,     2,
+       6,     3,     3,     2,     0,     2,     2,     6,     3,     2,
+       2,     2,     2,     2,     4,     4,     1,     0,     1,     0,
+       1,     0,     1,     0
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if HYPNO_MIS_DEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              );
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !HYPNO_MIS_DEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !HYPNO_MIS_DEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+{
+  YYUSE (yyvaluep);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (void)
+{
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex ();
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 3:
+#line 77 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { smenu_idx.push_back(-1);
+	    stack.push_back(new Hotspots()); }
+#line 1358 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 85 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("implicit END"); }
+#line 1364 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 88 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    {
+	     Hotspot *hot = new Hotspot(); 
+		 hot->type = MakeMenu;
+		 hot->stype = (yyvsp[-1].s);
+		 hot->smenu = NULL;
+		 debug("MENU %d.", hot->type);
+		 Hotspots *cur = stack.back();
+		 cur->push_back(*hot);
+
+		 // We don't care about menus, only hotspots
+     	 int idx = smenu_idx.back();
+		 idx++;
+		 smenu_idx.pop_back();
+		 smenu_idx.push_back(idx);
+
+	  }
+#line 1385 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 104 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    {  
+	     Hotspot *hot = new Hotspot(); 
+		 hot->type = MakeHotspot;
+		 hot->smenu = NULL;
+		 hot->rect = Common::Rect((yyvsp[-3].i), (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i));
+		 debug("HOTS %d.", hot->type);
+		 Hotspots *cur = stack.back();
+		 cur->push_back(*hot); 
+      }
+#line 1399 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 113 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  // This should always point to a hotspot
+		  int idx = smenu_idx.back();
+		  idx++;
+		  smenu_idx.pop_back();
+		  smenu_idx.push_back(idx);
+
+		  Hotspots *cur = stack.back();
+		  Hotspot *hot = &(*cur)[idx];
+
+		  smenu_idx.push_back(-1);
+		  hot->smenu = new Hotspots();
+	      stack.push_back(hot->smenu);
+		  debug("SUBMENU"); 
+		}
+#line 1419 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 128 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    {
+			Escape *a = new Escape();
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+		  	debug("ESC SUBMENU"); }
+#line 1430 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 134 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("TIME %d", (yyvsp[0].i)); }
+#line 1436 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 135 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    {
+			Background *a = new Background();
+			a->path = (yyvsp[-4].s);
+			a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+			a->condition = (yyvsp[-1].s);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+			debug("BACK");
+		}
+#line 1451 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 145 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		    Global *a = new Global();
+			a->variable = (yyvsp[-1].s);
+			a->command = (yyvsp[0].s);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+			debug("GLOB."); 
+		}
+#line 1465 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 154 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+			Ambient *a = new Ambient();
+			a->path = (yyvsp[-3].s);
+			a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+			a->flag = (yyvsp[0].s);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);			
+			debug("AMBI %d %d.", (yyvsp[-2].i), (yyvsp[-1].i)); }
+#line 1479 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 163 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+			Play *a = new Play();
+			a->path = (yyvsp[-4].s);
+			a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+			a->condition = (yyvsp[-1].s);
+			a->flag = (yyvsp[0].s);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);		  
+		    debug("PLAY %s.", (yyvsp[-4].s)); }
+#line 1494 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 173 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  	Overlay *a = new Overlay();
+			a->path = (yyvsp[-3].s);
+			a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+	   }
+#line 1507 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 181 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    {
+			Palette *a = new Palette();
+			a->path = (yyvsp[0].s); 
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+			debug("PALE");
+		}
+#line 1520 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 189 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  	Cutscene *a = new Cutscene();
+			a->path = (yyvsp[0].s);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);		  
+		    debug("CUTS %s.", (yyvsp[0].s)); 
+		}
+#line 1533 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 197 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+			WalN *a = new WalN();
+			a->path = (yyvsp[-4].s);
+			a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+			a->condition = (yyvsp[-1].s);
+			a->flag = (yyvsp[0].s);
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);		  
+		    debug("WALN %s %d %d.", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
+#line 1548 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 207 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    {
+		  	Mice *a = new Mice();
+			a->path = (yyvsp[-1].s); 
+			a->index = (yyvsp[0].i)-1;
+			Hotspots *cur = stack.back();
+		    Hotspot *hot = &cur->back();
+			hot->actions.push_back(a);
+	  }
+#line 1561 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 215 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  Hotspots *cur = stack.back();
+		  Hotspot *hot = &cur->back();
+		  hot->actions.push_back(talk_action);
+		  talk_action = nullptr;
+		  debug("TALK"); }
+#line 1572 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 221 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  debug("explicit END");
+		  g_parsedHots = stack.back(); 
+		  stack.pop_back();
+		  smenu_idx.pop_back();
+		  }
+#line 1583 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 24:
+#line 229 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { assert(talk_action == nullptr);
+	        talk_action = new Talk();
+		    talk_action->active = true; }
+#line 1591 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 25:
+#line 233 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    {
+	      talk_action->active = false; 
+	      debug("inactive"); }
+#line 1599 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 26:
+#line 236 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("inactive"); }
+#line 1605 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 27:
+#line 237 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  talk_action->background = (yyvsp[-4].s);
+		  talk_action->position = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+		  debug("BACK in TALK"); }
+#line 1614 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 28:
+#line 241 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("BOXX %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1620 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 29:
+#line 242 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "G";
+		  talk_cmd.path = (yyvsp[-1].s)+2;
+		  talk_action->commands.push_back(talk_cmd); 
+	      debug("%s", (yyvsp[-1].s)); }
+#line 1631 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 30:
+#line 248 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("%s", (yyvsp[-1].s)); }
+#line 1637 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 31:
+#line 249 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "F";
+		  talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
+		  talk_action->commands.push_back(talk_cmd); 
+		  debug("%s", (yyvsp[-1].s)); }
+#line 1648 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 32:
+#line 255 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "A";
+		  talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
+		  talk_action->commands.push_back(talk_cmd); 
+		  debug("|A%d", talk_cmd.num); }
+#line 1659 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 33:
+#line 261 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "D";
+		  talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
+		  talk_action->commands.push_back(talk_cmd); 
+		  debug("%s", (yyvsp[-1].s)); }
+#line 1670 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 34:
+#line 267 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "P";
+		  talk_cmd.path = (yyvsp[-3].s)+2;
+		  talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+		  talk_action->commands.push_back(talk_cmd);
+		  debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
+#line 1682 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 35:
+#line 274 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		  TalkCommand talk_cmd;
+		  talk_cmd.command = "I";
+		  talk_cmd.path = (yyvsp[-3].s)+2;
+		  talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+		  talk_action->commands.push_back(talk_cmd);		  
+		  debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
+#line 1694 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 36:
+#line 281 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("|E"); }
+#line 1700 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 37:
+#line 282 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("nothing in talk"); }
+#line 1706 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 40:
+#line 289 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { (yyval.s) = (yyvsp[0].s); debug("flag: %s", (yyvsp[0].s)); }
+#line 1712 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 41:
+#line 290 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { (yyval.s) = scumm_strdup(""); }
+#line 1718 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 42:
+#line 293 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { (yyval.s) = (yyvsp[0].s); debug("switch %s", (yyvsp[0].s)); }
+#line 1724 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 43:
+#line 294 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { (yyval.s) = scumm_strdup(""); }
+#line 1730 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+
+#line 1734 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
diff --git a/engines/hypno/lexer_arc.cpp b/engines/hypno/lexer_arc.cpp
new file mode 100644
index 0000000000..0e4dd0f8bd
--- /dev/null
+++ b/engines/hypno/lexer_arc.cpp
@@ -0,0 +1,2274 @@
+#line 2 "engines/hypno/lexer_arc.cpp"
+
+#line 4 "engines/hypno/lexer_arc.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer HYPNO_ARC__create_buffer
+#define yy_delete_buffer HYPNO_ARC__delete_buffer
+#define yy_scan_buffer HYPNO_ARC__scan_buffer
+#define yy_scan_string HYPNO_ARC__scan_string
+#define yy_scan_bytes HYPNO_ARC__scan_bytes
+#define yy_init_buffer HYPNO_ARC__init_buffer
+#define yy_flush_buffer HYPNO_ARC__flush_buffer
+#define yy_load_buffer_state HYPNO_ARC__load_buffer_state
+#define yy_switch_to_buffer HYPNO_ARC__switch_to_buffer
+#define yypush_buffer_state HYPNO_ARC_push_buffer_state
+#define yypop_buffer_state HYPNO_ARC_pop_buffer_state
+#define yyensure_buffer_stack HYPNO_ARC_ensure_buffer_stack
+#define yy_flex_debug HYPNO_ARC__flex_debug
+#define yyin HYPNO_ARC_in
+#define yyleng HYPNO_ARC_leng
+#define yylex HYPNO_ARC_lex
+#define yylineno HYPNO_ARC_lineno
+#define yyout HYPNO_ARC_out
+#define yyrestart HYPNO_ARC_restart
+#define yytext HYPNO_ARC_text
+#define yywrap HYPNO_ARC_wrap
+#define yyalloc HYPNO_ARC_alloc
+#define yyrealloc HYPNO_ARC_realloc
+#define yyfree HYPNO_ARC_free
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+#ifdef yy_create_buffer
+#define HYPNO_ARC__create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer HYPNO_ARC__create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define HYPNO_ARC__delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer HYPNO_ARC__delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define HYPNO_ARC__scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer HYPNO_ARC__scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define HYPNO_ARC__scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string HYPNO_ARC__scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define HYPNO_ARC__scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes HYPNO_ARC__scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define HYPNO_ARC__init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer HYPNO_ARC__init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define HYPNO_ARC__flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer HYPNO_ARC__flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define HYPNO_ARC__load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state HYPNO_ARC__load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define HYPNO_ARC__switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer HYPNO_ARC__switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define HYPNO_ARC_push_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state HYPNO_ARC_push_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define HYPNO_ARC_pop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state HYPNO_ARC_pop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define HYPNO_ARC_ensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack HYPNO_ARC_ensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define HYPNO_ARC_lex_ALREADY_DEFINED
+#else
+#define yylex HYPNO_ARC_lex
+#endif
+
+#ifdef yyrestart
+#define HYPNO_ARC_restart_ALREADY_DEFINED
+#else
+#define yyrestart HYPNO_ARC_restart
+#endif
+
+#ifdef yylex_init
+#define HYPNO_ARC_lex_init_ALREADY_DEFINED
+#else
+#define yylex_init HYPNO_ARC_lex_init
+#endif
+
+#ifdef yylex_init_extra
+#define HYPNO_ARC_lex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra HYPNO_ARC_lex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define HYPNO_ARC_lex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy HYPNO_ARC_lex_destroy
+#endif
+
+#ifdef yyget_debug
+#define HYPNO_ARC_get_debug_ALREADY_DEFINED
+#else
+#define yyget_debug HYPNO_ARC_get_debug
+#endif
+
+#ifdef yyset_debug
+#define HYPNO_ARC_set_debug_ALREADY_DEFINED
+#else
+#define yyset_debug HYPNO_ARC_set_debug
+#endif
+
+#ifdef yyget_extra
+#define HYPNO_ARC_get_extra_ALREADY_DEFINED
+#else
+#define yyget_extra HYPNO_ARC_get_extra
+#endif
+
+#ifdef yyset_extra
+#define HYPNO_ARC_set_extra_ALREADY_DEFINED
+#else
+#define yyset_extra HYPNO_ARC_set_extra
+#endif
+
+#ifdef yyget_in
+#define HYPNO_ARC_get_in_ALREADY_DEFINED
+#else
+#define yyget_in HYPNO_ARC_get_in
+#endif
+
+#ifdef yyset_in
+#define HYPNO_ARC_set_in_ALREADY_DEFINED
+#else
+#define yyset_in HYPNO_ARC_set_in
+#endif
+
+#ifdef yyget_out
+#define HYPNO_ARC_get_out_ALREADY_DEFINED
+#else
+#define yyget_out HYPNO_ARC_get_out
+#endif
+
+#ifdef yyset_out
+#define HYPNO_ARC_set_out_ALREADY_DEFINED
+#else
+#define yyset_out HYPNO_ARC_set_out
+#endif
+
+#ifdef yyget_leng
+#define HYPNO_ARC_get_leng_ALREADY_DEFINED
+#else
+#define yyget_leng HYPNO_ARC_get_leng
+#endif
+
+#ifdef yyget_text
+#define HYPNO_ARC_get_text_ALREADY_DEFINED
+#else
+#define yyget_text HYPNO_ARC_get_text
+#endif
+
+#ifdef yyget_lineno
+#define HYPNO_ARC_get_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno HYPNO_ARC_get_lineno
+#endif
+
+#ifdef yyset_lineno
+#define HYPNO_ARC_set_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno HYPNO_ARC_set_lineno
+#endif
+
+#ifdef yywrap
+#define HYPNO_ARC_wrap_ALREADY_DEFINED
+#else
+#define yywrap HYPNO_ARC_wrap
+#endif
+
+#ifdef yyalloc
+#define HYPNO_ARC_alloc_ALREADY_DEFINED
+#else
+#define yyalloc HYPNO_ARC_alloc
+#endif
+
+#ifdef yyrealloc
+#define HYPNO_ARC_realloc_ALREADY_DEFINED
+#else
+#define yyrealloc HYPNO_ARC_realloc
+#endif
+
+#ifdef yyfree
+#define HYPNO_ARC_free_ALREADY_DEFINED
+#else
+#define yyfree HYPNO_ARC_free
+#endif
+
+#ifdef yytext
+#define HYPNO_ARC_text_ALREADY_DEFINED
+#else
+#define yytext HYPNO_ARC_text
+#endif
+
+#ifdef yyleng
+#define HYPNO_ARC_leng_ALREADY_DEFINED
+#else
+#define yyleng HYPNO_ARC_leng
+#endif
+
+#ifdef yyin
+#define HYPNO_ARC_in_ALREADY_DEFINED
+#else
+#define yyin HYPNO_ARC_in
+#endif
+
+#ifdef yyout
+#define HYPNO_ARC_out_ALREADY_DEFINED
+#else
+#define yyout HYPNO_ARC_out
+#endif
+
+#ifdef yy_flex_debug
+#define HYPNO_ARC__flex_debug_ALREADY_DEFINED
+#else
+#define yy_flex_debug HYPNO_ARC__flex_debug
+#endif
+
+#ifdef yylineno
+#define HYPNO_ARC_lineno_ALREADY_DEFINED
+#else
+#define yylineno HYPNO_ARC_lineno
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX               (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an
+ *   integer in range [0..255] for use as an array index.
+ */
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin  )
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+    
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex.
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    #define YY_LINENO_REWIND_TO(dst) \
+            do {\
+                const char *p;\
+                for ( p = yy_cp-1; p >= (dst); --p)\
+                    if ( *p == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	int yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = NULL;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart ( FILE *input_file  );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size  );
+void yy_delete_buffer ( YY_BUFFER_STATE b  );
+void yy_flush_buffer ( YY_BUFFER_STATE b  );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state ( void );
+
+static void yyensure_buffer_stack ( void );
+static void yy_load_buffer_state ( void );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file  );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len  );
+
+void *yyalloc ( yy_size_t  );
+void *yyrealloc ( void *, yy_size_t  );
+void yyfree ( void *  );
+
+#define yy_new_buffer yy_create_buffer
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define HYPNO_ARC_wrap() (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+typedef flex_uint8_t YY_CHAR;
+
+FILE *yyin = NULL, *yyout = NULL;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+int yylineno = 1;
+
+extern char *yytext;
+#ifdef yytext_ptr
+#undef yytext_ptr
+#endif
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state ( void );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state  );
+static int yy_get_next_buffer ( void );
+static void yynoreturn yy_fatal_error ( const char* msg  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+#define YY_NUM_RULES 37
+#define YY_END_OF_BUFFER 38
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static const flex_int16_t yy_accept[55] =
+    {   0,
+        0,    0,   38,   36,   34,   35,   32,   36,   31,   31,
+        7,   29,    2,    3,   29,   21,    5,   13,   29,   11,
+        9,    6,   14,   12,   29,   18,    8,   16,   17,   29,
+       15,   29,   33,   35,   31,   31,   30,   23,   29,   24,
+       20,    4,   25,   29,   10,   26,   22,   19,   27,   29,
+       28,   29,    1,    0
+    } ;
+
+static const YY_CHAR yy_ec[256] =
+    {   0,
+        1,    2,    1,    1,    1,    1,    1,    1,    3,    4,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    3,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    5,    6,    1,    7,    8,    9,
+       10,   10,   10,   10,   10,   10,   10,    1,    1,    1,
+        1,    1,    1,    1,   11,   12,   13,   14,   15,   16,
+       17,   18,   19,   17,   20,   17,   17,   21,   22,   23,
+       24,   25,   26,   27,   17,   28,   29,   30,   31,   32,
+        1,    6,    1,    1,   33,    1,   34,   34,   34,   34,
+
+       34,   34,   34,   34,   34,   34,   35,   34,   34,   34,
+       34,   36,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,    1,   37,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,   38,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static const YY_CHAR yy_meta[39] =
+    {   0,
+        1,    1,    1,    1,    1,    2,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    1,    1
+    } ;
+
+static const flex_int16_t yy_base[59] =
+    {   0,
+        0,    0,  123,  146,  146,  118,  146,   32,   36,   40,
+       45,   47,  114,  113,  112,   52,   57,  111,   58,   60,
+       61,   64,  110,  109,   67,   62,  108,  107,   98,   72,
+       97,    0,  146,   99,   76,  102,    0,   95,   94,   93,
+       91,   90,   89,   73,   87,   86,   85,   84,   82,    0,
+      146,   74,   81,  146,  138,  140,   78,  142
+    } ;
+
+static const flex_int16_t yy_def[59] =
+    {   0,
+       54,    1,   54,   54,   54,   54,   54,   54,   54,   54,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   56,
+       55,   57,   54,   54,   54,   54,   58,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   57,
+       54,   55,   55,    0,   54,   54,   54,   54
+    } ;
+
+static const flex_int16_t yy_nxt[185] =
+    {   0,
+        4,    5,    6,    7,    8,    4,    9,    9,   10,    9,
+       11,   12,   13,   14,   15,   16,   15,   17,   18,   19,
+       20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
+       30,   31,   32,   15,   15,   15,    4,   33,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35,   36,   35,
+       37,   38,   37,   40,   40,   40,   40,   37,   41,   41,
+       41,   41,   37,   37,   43,   37,   37,   37,   45,   37,
+       46,   42,   37,   47,   47,   47,   47,   37,   37,   37,
+       50,   44,   35,   35,   35,   35,   37,   37,   53,   37,
+       37,   37,   37,   52,   37,   37,   37,   48,   37,   37,
+
+       37,   34,   37,   37,   39,   39,   39,   39,   35,   35,
+       35,   35,   37,   37,   37,   37,   37,   37,   37,   37,
+       34,   51,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   51,   54,   51,   39,
+       39,   49,   49,   37,   37,    3,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54
+    } ;
+
+static const flex_int16_t yy_chk[185] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    8,    8,
+        8,    8,    9,    9,    9,    9,   10,   10,   10,   10,
+       11,   11,   12,   12,   12,   12,   12,   16,   16,   16,
+       16,   16,   17,   19,   19,   20,   21,   26,   21,   22,
+       22,   17,   25,   25,   25,   25,   25,   30,   44,   52,
+       57,   20,   35,   35,   35,   35,   53,   49,   52,   48,
+       47,   46,   45,   44,   43,   42,   41,   26,   40,   39,
+
+       38,   34,   31,   29,   30,   30,   30,   30,   36,   36,
+       36,   36,   28,   27,   24,   23,   18,   15,   14,   13,
+        6,   36,    3,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,   36,    0,   36,   55,
+       55,   56,   56,   58,   58,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static const flex_int32_t yy_rule_can_match_eol[38] =
+    {   0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,     };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "engines/hypno/lexer_arc.l"
+/* 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.
+ *
+ */
+#define YY_NO_INPUT 1
+#line 33 "engines/hypno/lexer_arc.l"
+#define YY_NO_UNISTD_H
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+#include "hypno/tokens_arc.h"
+
+#line 815 "engines/hypno/lexer_arc.cpp"
+#line 816 "engines/hypno/lexer_arc.cpp"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals ( void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy ( void );
+
+int yyget_debug ( void );
+
+void yyset_debug ( int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra ( void );
+
+void yyset_extra ( YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in ( void );
+
+void yyset_in  ( FILE * _in_str  );
+
+FILE *yyget_out ( void );
+
+void yyset_out  ( FILE * _out_str  );
+
+			int yyget_leng ( void );
+
+char *yyget_text ( void );
+
+int yyget_lineno ( void );
+
+void yyset_lineno ( int _line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap ( void );
+#else
+extern int yywrap ( void );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+    
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const char * );
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput ( void );
+#else
+static int input ( void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		int n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	yy_state_type yy_current_state;
+	char *yy_cp, *yy_bp;
+	int yy_act;
+    
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state(  );
+		}
+
+	{
+#line 42 "engines/hypno/lexer_arc.l"
+
+#line 1033 "engines/hypno/lexer_arc.cpp"
+
+	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 55 )
+					yy_c = yy_meta[yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+			++yy_cp;
+			}
+		while ( yy_current_state != 54 );
+		yy_cp = (yy_last_accepting_cpos);
+		yy_current_state = (yy_last_accepting_state);
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					
+    yylineno++;
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 43 "engines/hypno/lexer_arc.l"
+return NONETOK;
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 44 "engines/hypno/lexer_arc.l"
+return CTOK;
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 45 "engines/hypno/lexer_arc.l"
+return DTOK;
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 46 "engines/hypno/lexer_arc.l"
+return HETOK;
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 47 "engines/hypno/lexer_arc.l"
+return HTOK;
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 48 "engines/hypno/lexer_arc.l"
+return PTOK;
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 49 "engines/hypno/lexer_arc.l"
+return ATOK;
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 50 "engines/hypno/lexer_arc.l"
+return VTOK;
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 51 "engines/hypno/lexer_arc.l"
+return OTOK;
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 52 "engines/hypno/lexer_arc.l"
+return O1TOK;
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 53 "engines/hypno/lexer_arc.l"
+return NTOK;
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 54 "engines/hypno/lexer_arc.l"
+return RTOK;
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 55 "engines/hypno/lexer_arc.l"
+return ITOK;
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 56 "engines/hypno/lexer_arc.l"
+return QTOK;
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 57 "engines/hypno/lexer_arc.l"
+return ZTOK;
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 58 "engines/hypno/lexer_arc.l"
+return WTOK;
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 59 "engines/hypno/lexer_arc.l"
+return XTOK;
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 60 "engines/hypno/lexer_arc.l"
+return TTOK;
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 61 "engines/hypno/lexer_arc.l"
+return TPTOK;
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 62 "engines/hypno/lexer_arc.l"
+return FNTOK;
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 63 "engines/hypno/lexer_arc.l"
+return FTOK;
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 64 "engines/hypno/lexer_arc.l"
+HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return SNTOK;
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 65 "engines/hypno/lexer_arc.l"
+return A0TOK;
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 66 "engines/hypno/lexer_arc.l"
+HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 67 "engines/hypno/lexer_arc.l"
+return K0TOK;
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 68 "engines/hypno/lexer_arc.l"
+return P0TOK;
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 69 "engines/hypno/lexer_arc.l"
+return YXTOK;
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 70 "engines/hypno/lexer_arc.l"
+return ENCTOK;
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 71 "engines/hypno/lexer_arc.l"
+HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 72 "engines/hypno/lexer_arc.l"
+HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 73 "engines/hypno/lexer_arc.l"
+HYPNO_ARC_lval.i = atoi(HYPNO_ARC_text); return NUM;
+	YY_BREAK
+case 32:
+/* rule 32 can match eol */
+YY_RULE_SETUP
+#line 74 "engines/hypno/lexer_arc.l"
+return RETTOK;
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 75 "engines/hypno/lexer_arc.l"
+return CB3TOK;
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 76 "engines/hypno/lexer_arc.l"
+return C02TOK;
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 77 "engines/hypno/lexer_arc.l"
+/* ignore whitespace */;
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 78 "engines/hypno/lexer_arc.l"
+debug("notparsed: 0x%d",*yytext); return *yytext;
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 79 "engines/hypno/lexer_arc.l"
+ECHO;
+	YY_BREAK
+#line 1282 "engines/hypno/lexer_arc.cpp"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_last_accepting_cpos);
+				yy_current_state = (yy_last_accepting_state);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap(  ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	char *source = (yytext_ptr);
+	int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc( (void *) b->yy_ch_buf,
+							 (yy_size_t) (b->yy_buf_size + 2)  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = NULL;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+		/* "- 2" to take care of EOB's */
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	yy_state_type yy_current_state;
+	char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 55 )
+				yy_c = yy_meta[yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	int yy_is_jam;
+    	char *yy_cp = (yy_c_buf_p);
+
+	YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 55 )
+			yy_c = yy_meta[yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+	yy_is_jam = (yy_current_state == 54);
+
+		return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap(  ) )
+						return 0;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	if ( c == '\n' )
+		
+    yylineno++;
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer( yyin, YY_BUF_SIZE );
+	}
+
+	yy_init_buffer( YY_CURRENT_BUFFER, input_file );
+	yy_load_buffer_state(  );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state(  );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2)  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree( (void *) b->yy_ch_buf  );
+
+	yyfree( (void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state(  );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state(  );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state(  );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	yy_size_t num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		yy_size_t grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return NULL;
+
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = (int) (size - 2);	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = NULL;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (const char * yystr )
+{
+    
+	return yy_scan_bytes( yystr, (int) strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = (yy_size_t) (_yybytes_len + 2);
+	buf = (char *) yyalloc( n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yynoreturn yy_fatal_error (const char* msg )
+{
+			fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+    
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param _line_number line number
+ * 
+ */
+void yyset_lineno (int  _line_number )
+{
+    
+    yylineno = _line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param _in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  _in_str )
+{
+        yyin = _in_str ;
+}
+
+void yyset_out (FILE *  _out_str )
+{
+        yyout = _out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  _bdebug )
+{
+        yy_flex_debug = _bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    /* We do not touch yylineno unless the option is enabled. */
+    yylineno =  1;
+    
+    (yy_buffer_stack) = NULL;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = NULL;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = NULL;
+    yyout = NULL;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer( YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, const char * s2, int n )
+{
+		
+	int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (const char * s )
+{
+	int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+			return malloc(size);
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+		
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return realloc(ptr, size);
+}
+
+void yyfree (void * ptr )
+{
+			free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 79 "engines/hypno/lexer_arc.l"
+
+
+namespace Hypno {
+
+int parse_arc(const char *code) {
+	YY_BUFFER_STATE bp;
+	yy_delete_buffer(YY_CURRENT_BUFFER);
+	bp = yy_scan_string(code);
+	yy_switch_to_buffer(bp);
+	HYPNO_ARC_parse();
+	yy_delete_buffer(bp);
+	return 0;
+}
+
+} // End of namespace Hypno
+
diff --git a/engines/hypno/lexer_mis.cpp b/engines/hypno/lexer_mis.cpp
new file mode 100644
index 0000000000..f4d3e68295
--- /dev/null
+++ b/engines/hypno/lexer_mis.cpp
@@ -0,0 +1,2339 @@
+#line 2 "engines/hypno/lexer_mis.cpp"
+
+#line 4 "engines/hypno/lexer_mis.cpp"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer HYPNO_MIS__create_buffer
+#define yy_delete_buffer HYPNO_MIS__delete_buffer
+#define yy_scan_buffer HYPNO_MIS__scan_buffer
+#define yy_scan_string HYPNO_MIS__scan_string
+#define yy_scan_bytes HYPNO_MIS__scan_bytes
+#define yy_init_buffer HYPNO_MIS__init_buffer
+#define yy_flush_buffer HYPNO_MIS__flush_buffer
+#define yy_load_buffer_state HYPNO_MIS__load_buffer_state
+#define yy_switch_to_buffer HYPNO_MIS__switch_to_buffer
+#define yypush_buffer_state HYPNO_MIS_push_buffer_state
+#define yypop_buffer_state HYPNO_MIS_pop_buffer_state
+#define yyensure_buffer_stack HYPNO_MIS_ensure_buffer_stack
+#define yy_flex_debug HYPNO_MIS__flex_debug
+#define yyin HYPNO_MIS_in
+#define yyleng HYPNO_MIS_leng
+#define yylex HYPNO_MIS_lex
+#define yylineno HYPNO_MIS_lineno
+#define yyout HYPNO_MIS_out
+#define yyrestart HYPNO_MIS_restart
+#define yytext HYPNO_MIS_text
+#define yywrap HYPNO_MIS_wrap
+#define yyalloc HYPNO_MIS_alloc
+#define yyrealloc HYPNO_MIS_realloc
+#define yyfree HYPNO_MIS_free
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+#ifdef yy_create_buffer
+#define HYPNO_MIS__create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer HYPNO_MIS__create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define HYPNO_MIS__delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer HYPNO_MIS__delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define HYPNO_MIS__scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer HYPNO_MIS__scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define HYPNO_MIS__scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string HYPNO_MIS__scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define HYPNO_MIS__scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes HYPNO_MIS__scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define HYPNO_MIS__init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer HYPNO_MIS__init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define HYPNO_MIS__flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer HYPNO_MIS__flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define HYPNO_MIS__load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state HYPNO_MIS__load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define HYPNO_MIS__switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer HYPNO_MIS__switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define HYPNO_MIS_push_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state HYPNO_MIS_push_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define HYPNO_MIS_pop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state HYPNO_MIS_pop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define HYPNO_MIS_ensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack HYPNO_MIS_ensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define HYPNO_MIS_lex_ALREADY_DEFINED
+#else
+#define yylex HYPNO_MIS_lex
+#endif
+
+#ifdef yyrestart
+#define HYPNO_MIS_restart_ALREADY_DEFINED
+#else
+#define yyrestart HYPNO_MIS_restart
+#endif
+
+#ifdef yylex_init
+#define HYPNO_MIS_lex_init_ALREADY_DEFINED
+#else
+#define yylex_init HYPNO_MIS_lex_init
+#endif
+
+#ifdef yylex_init_extra
+#define HYPNO_MIS_lex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra HYPNO_MIS_lex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define HYPNO_MIS_lex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy HYPNO_MIS_lex_destroy
+#endif
+
+#ifdef yyget_debug
+#define HYPNO_MIS_get_debug_ALREADY_DEFINED
+#else
+#define yyget_debug HYPNO_MIS_get_debug
+#endif
+
+#ifdef yyset_debug
+#define HYPNO_MIS_set_debug_ALREADY_DEFINED
+#else
+#define yyset_debug HYPNO_MIS_set_debug
+#endif
+
+#ifdef yyget_extra
+#define HYPNO_MIS_get_extra_ALREADY_DEFINED
+#else
+#define yyget_extra HYPNO_MIS_get_extra
+#endif
+
+#ifdef yyset_extra
+#define HYPNO_MIS_set_extra_ALREADY_DEFINED
+#else
+#define yyset_extra HYPNO_MIS_set_extra
+#endif
+
+#ifdef yyget_in
+#define HYPNO_MIS_get_in_ALREADY_DEFINED
+#else
+#define yyget_in HYPNO_MIS_get_in
+#endif
+
+#ifdef yyset_in
+#define HYPNO_MIS_set_in_ALREADY_DEFINED
+#else
+#define yyset_in HYPNO_MIS_set_in
+#endif
+
+#ifdef yyget_out
+#define HYPNO_MIS_get_out_ALREADY_DEFINED
+#else
+#define yyget_out HYPNO_MIS_get_out
+#endif
+
+#ifdef yyset_out
+#define HYPNO_MIS_set_out_ALREADY_DEFINED
+#else
+#define yyset_out HYPNO_MIS_set_out
+#endif
+
+#ifdef yyget_leng
+#define HYPNO_MIS_get_leng_ALREADY_DEFINED
+#else
+#define yyget_leng HYPNO_MIS_get_leng
+#endif
+
+#ifdef yyget_text
+#define HYPNO_MIS_get_text_ALREADY_DEFINED
+#else
+#define yyget_text HYPNO_MIS_get_text
+#endif
+
+#ifdef yyget_lineno
+#define HYPNO_MIS_get_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno HYPNO_MIS_get_lineno
+#endif
+
+#ifdef yyset_lineno
+#define HYPNO_MIS_set_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno HYPNO_MIS_set_lineno
+#endif
+
+#ifdef yywrap
+#define HYPNO_MIS_wrap_ALREADY_DEFINED
+#else
+#define yywrap HYPNO_MIS_wrap
+#endif
+
+#ifdef yyalloc
+#define HYPNO_MIS_alloc_ALREADY_DEFINED
+#else
+#define yyalloc HYPNO_MIS_alloc
+#endif
+
+#ifdef yyrealloc
+#define HYPNO_MIS_realloc_ALREADY_DEFINED
+#else
+#define yyrealloc HYPNO_MIS_realloc
+#endif
+
+#ifdef yyfree
+#define HYPNO_MIS_free_ALREADY_DEFINED
+#else
+#define yyfree HYPNO_MIS_free
+#endif
+
+#ifdef yytext
+#define HYPNO_MIS_text_ALREADY_DEFINED
+#else
+#define yytext HYPNO_MIS_text
+#endif
+
+#ifdef yyleng
+#define HYPNO_MIS_leng_ALREADY_DEFINED
+#else
+#define yyleng HYPNO_MIS_leng
+#endif
+
+#ifdef yyin
+#define HYPNO_MIS_in_ALREADY_DEFINED
+#else
+#define yyin HYPNO_MIS_in
+#endif
+
+#ifdef yyout
+#define HYPNO_MIS_out_ALREADY_DEFINED
+#else
+#define yyout HYPNO_MIS_out
+#endif
+
+#ifdef yy_flex_debug
+#define HYPNO_MIS__flex_debug_ALREADY_DEFINED
+#else
+#define yy_flex_debug HYPNO_MIS__flex_debug
+#endif
+
+#ifdef yylineno
+#define HYPNO_MIS_lineno_ALREADY_DEFINED
+#else
+#define yylineno HYPNO_MIS_lineno
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX               (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an
+ *   integer in range [0..255] for use as an array index.
+ */
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin  )
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+    
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex.
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    #define YY_LINENO_REWIND_TO(dst) \
+            do {\
+                const char *p;\
+                for ( p = yy_cp-1; p >= (dst); --p)\
+                    if ( *p == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	int yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = NULL;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart ( FILE *input_file  );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size  );
+void yy_delete_buffer ( YY_BUFFER_STATE b  );
+void yy_flush_buffer ( YY_BUFFER_STATE b  );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state ( void );
+
+static void yyensure_buffer_stack ( void );
+static void yy_load_buffer_state ( void );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file  );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len  );
+
+void *yyalloc ( yy_size_t  );
+void *yyrealloc ( void *, yy_size_t  );
+void yyfree ( void *  );
+
+#define yy_new_buffer yy_create_buffer
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define HYPNO_MIS_wrap() (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+typedef flex_uint8_t YY_CHAR;
+
+FILE *yyin = NULL, *yyout = NULL;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+int yylineno = 1;
+
+extern char *yytext;
+#ifdef yytext_ptr
+#undef yytext_ptr
+#endif
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state ( void );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state  );
+static int yy_get_next_buffer ( void );
+static void yynoreturn yy_fatal_error ( const char* msg  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+#define YY_NUM_RULES 39
+#define YY_END_OF_BUFFER 40
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static const flex_int16_t yy_accept[131] =
+    {   0,
+        0,    0,   40,   38,   37,   39,   38,   38,   32,   35,
+       35,    1,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   38,   37,
+       36,   35,   32,   32,    0,    1,   34,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,    0,
+        0,   28,    0,    0,    0,    0,    0,   32,    0,   33,
+       33,   33,   33,   11,   33,   33,   33,   33,   33,   33,
+       33,   33,   33,   33,   33,   33,   33,   33,   33,   25,
+       26,   27,   21,   24,   23,   22,   32,    0,    3,    4,
+
+       20,    5,   15,    6,   30,    8,   33,    2,   10,   33,
+       13,    7,   16,   14,   17,   12,    9,   32,   19,   33,
+       33,   31,   33,   33,   33,   33,   18,   33,   29,    0
+    } ;
+
+static const YY_CHAR yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    5,    1,    1,    6,    7,    8,    9,    9,   10,
+       10,   11,   10,   10,   10,   10,   10,    1,   12,    1,
+       13,    1,    1,    1,   14,   15,   16,   17,   18,   19,
+       20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
+       23,   30,   31,   32,   33,   34,   35,   36,   37,   23,
+        1,    7,    1,    1,   38,    1,   39,   39,   39,   39,
+
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,    1,   40,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static const YY_CHAR yy_meta[41] =
+    {   0,
+        1,    2,    1,    1,    2,    1,    3,    1,    4,    4,
+        4,    1,    1,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    1
+    } ;
+
+static const flex_int16_t yy_base[140] =
+    {   0,
+        0,    0,  266,  267,  263,  267,  261,   32,  248,   35,
+       38,    0,   43,   44,   45,  255,   46,   49,   47,   52,
+       63,   54,   50,   69,   60,   81,   57,    0,   90,  259,
+      267,   80,    0,  245,  244,    0,    0,  251,   53,   80,
+       56,   86,   98,   90,   92,   91,   93,  107,   95,  110,
+       94,  106,  109,  116,  120,  121,  124,  126,    0,  126,
+      130,  267,  133,    0,  138,    0,    0,  229,  215,  138,
+      145,  146,  147,  231,  148,  149,  150,  152,  151,  154,
+      155,  156,  158,  161,  159,  163,  167,  174,  186,  188,
+      191,  194,    0,  197,    0,    0,  200,  199,  227,  226,
+
+      225,  224,  223,  222,  173,  221,  177,  220,  217,  203,
+      216,  215,  213,  211,  178,  169,  168,  159,  267,  204,
+      187,  267,  206,  208,  207,  209,  164,  210,   59,  267,
+       61,  240,  242,   58,  244,  246,  248,  250,  252
+    } ;
+
+static const flex_int16_t yy_def[140] =
+    {   0,
+      130,    1,  130,  130,  130,  130,  130,  130,  131,  130,
+      130,  132,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  134,  130,  130,
+      130,  130,  131,  131,  130,  132,  135,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  134,  130,
+      130,  130,  130,  136,  130,  137,  138,  131,  130,  133,
+      133,  133,  133,  133,  133,  133,  139,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  130,
+      130,  130,  136,  130,  137,  138,  131,  130,  133,  133,
+
+      133,  133,  133,  133,  139,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  131,  130,  133,
+      133,  130,  133,  133,  133,  133,  133,  133,  133,    0,
+      130,  130,  130,  130,  130,  130,  130,  130,  130
+    } ;
+
+static const flex_int16_t yy_nxt[308] =
+    {   0,
+        4,    5,    6,    7,    4,    8,    4,    9,   10,   10,
+       11,   12,    4,   13,   14,   15,   16,   17,   16,   18,
+       19,   20,   16,   16,   16,   21,   22,   23,   24,   16,
+       25,   26,   16,   16,   27,   16,   16,   28,   16,   29,
+       32,   32,   32,   32,   32,   32,   32,   32,   32,   37,
+       37,   37,   37,   37,   35,   37,   37,   40,   37,   37,
+       37,   59,   37,   37,   33,   37,   37,   70,   39,   37,
+       58,   41,   43,   45,   47,   37,   44,   42,   48,   46,
+       49,   51,   53,   52,   50,   55,   37,   37,   32,   32,
+       32,   72,   37,   54,   56,   71,   37,   37,   37,   37,
+
+       37,   37,   57,   60,   37,   75,   61,   62,   63,   64,
+       65,   66,   37,   37,   74,   37,   37,   73,   67,   76,
+       79,   80,   37,   83,   78,   81,   37,   37,   77,   85,
+       37,   82,   37,   84,   90,   90,   90,   86,   91,   91,
+       91,   92,   92,   92,   37,   87,   94,   94,   94,   88,
+       89,   37,   37,   37,   37,   37,   37,   37,   37,   99,
+       37,   37,   37,  104,   37,   37,  107,   37,  100,   37,
+       37,  122,  109,   37,   37,   37,  103,  102,  112,   37,
+       37,  101,  106,   37,   37,  110,  108,  111,   38,  114,
+      115,  116,   37,   37,  117,  113,   90,   90,   90,   91,
+
+       91,   91,   92,   92,   92,   94,   94,   94,  120,   37,
+       37,   38,   37,   37,   37,   37,   37,   37,  124,   37,
+      121,   37,   37,   37,  127,  123,   37,   37,   37,   37,
+       37,   37,   37,   37,  119,  118,  129,   37,  128,  125,
+      126,   36,   98,   36,   38,   38,   37,   37,   93,   93,
+       95,   95,   96,   96,  105,  105,   97,   37,   69,   68,
+       30,   37,   34,   31,   30,  130,    3,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130
+    } ;
+
+static const flex_int16_t yy_chk[308] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        8,    8,    8,   10,   10,   10,   11,   11,   11,   13,
+       14,   15,   17,   19,   11,   18,   23,   14,   20,   39,
+       22,  134,   41,   27,  131,  129,   25,   39,   13,   21,
+       27,   14,   17,   18,   19,   24,   17,   15,   20,   18,
+       21,   22,   24,   23,   21,   25,   40,   26,   32,   32,
+       32,   41,   42,   24,   26,   40,   44,   46,   45,   47,
+
+       51,   49,   26,   29,   43,   44,   29,   29,   29,   29,
+       29,   29,   52,   48,   43,   53,   50,   42,   29,   45,
+       48,   49,   54,   52,   47,   50,   55,   56,   46,   54,
+       57,   51,   58,   53,   60,   60,   60,   55,   61,   61,
+       61,   63,   63,   63,   70,   56,   65,   65,   65,   57,
+       58,   71,   72,   73,   75,   76,   77,   79,   78,   70,
+       80,   81,   82,   76,   83,   85,   79,   84,   71,   86,
+      127,  118,   81,   87,  117,  116,   75,   73,   84,  105,
+       88,   72,   78,  107,  115,   82,   80,   83,   77,   86,
+       87,   88,   89,  121,   89,   85,   90,   90,   90,   91,
+
+       91,   91,   92,   92,   92,   94,   94,   94,  107,  110,
+      120,  105,  123,  125,  124,  126,  128,  114,  121,  113,
+      110,  112,  111,  109,  125,  120,  108,  106,  104,  103,
+      102,  101,  100,   99,   98,   97,  128,   74,  126,  123,
+      124,  132,   69,  132,  133,  133,  135,  135,  136,  136,
+      137,  137,  138,  138,  139,  139,   68,   38,   35,   34,
+       30,   16,    9,    7,    5,    3,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+
+      130,  130,  130,  130,  130,  130,  130
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static const flex_int32_t yy_rule_can_match_eol[40] =
+    {   0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
+        };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "engines/hypno/lexer_mis.l"
+/* 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.
+ *
+ */
+#define YY_NO_INPUT 1
+#line 33 "engines/hypno/lexer_mis.l"
+#define YY_NO_UNISTD_H
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "hypno/hypno.h"
+#include "hypno/grammar.h"
+#include "hypno/tokens_mis.h"
+
+#line 870 "engines/hypno/lexer_mis.cpp"
+#line 871 "engines/hypno/lexer_mis.cpp"
+
+#define INITIAL 0
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals ( void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy ( void );
+
+int yyget_debug ( void );
+
+void yyset_debug ( int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra ( void );
+
+void yyset_extra ( YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in ( void );
+
+void yyset_in  ( FILE * _in_str  );
+
+FILE *yyget_out ( void );
+
+void yyset_out  ( FILE * _out_str  );
+
+			int yyget_leng ( void );
+
+char *yyget_text ( void );
+
+int yyget_lineno ( void );
+
+void yyset_lineno ( int _line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap ( void );
+#else
+extern int yywrap ( void );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+    
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const char * );
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput ( void );
+#else
+static int input ( void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		int n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	yy_state_type yy_current_state;
+	char *yy_cp, *yy_bp;
+	int yy_act;
+    
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state(  );
+		}
+
+	{
+#line 42 "engines/hypno/lexer_mis.l"
+
+#line 1088 "engines/hypno/lexer_mis.cpp"
+
+	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 131 )
+					yy_c = yy_meta[yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+			++yy_cp;
+			}
+		while ( yy_current_state != 130 );
+		yy_cp = (yy_last_accepting_cpos);
+		yy_current_state = (yy_last_accepting_state);
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					
+    yylineno++;
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 43 "engines/hypno/lexer_mis.l"
+/* return COMMENT; */
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 44 "engines/hypno/lexer_mis.l"
+return MENUTOK;
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 45 "engines/hypno/lexer_mis.l"
+return AMBITOK;
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 46 "engines/hypno/lexer_mis.l"
+return BACKTOK;
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 47 "engines/hypno/lexer_mis.l"
+return CUTSTOK;
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 48 "engines/hypno/lexer_mis.l"
+return GLOBTOK;
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 49 "engines/hypno/lexer_mis.l"
+return PALETOK;
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 50 "engines/hypno/lexer_mis.l"
+return HOTSTOK;
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 51 "engines/hypno/lexer_mis.l"
+return WALNTOK;
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 52 "engines/hypno/lexer_mis.l"
+return MICETOK;
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 53 "engines/hypno/lexer_mis.l"
+return ENDTOK;
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 54 "engines/hypno/lexer_mis.l"
+return TIMETOK;
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 55 "engines/hypno/lexer_mis.l"
+return OVERTOK;
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 56 "engines/hypno/lexer_mis.l"
+return SMENTOK;
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 57 "engines/hypno/lexer_mis.l"
+return ESCPTOK;
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 58 "engines/hypno/lexer_mis.l"
+return PLAYTOK;
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 59 "engines/hypno/lexer_mis.l"
+return TALKTOK;
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 60 "engines/hypno/lexer_mis.l"
+return INACTOK;
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 61 "engines/hypno/lexer_mis.l"
+return FDTOK;
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 62 "engines/hypno/lexer_mis.l"
+return BOXXTOK;
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 63 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PG;
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 64 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PP;
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 65 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PI;
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 66 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PH;
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 67 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PA;
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 68 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PD;
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 69 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PF;
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 70 "engines/hypno/lexer_mis.l"
+return PE;
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 71 "engines/hypno/lexer_mis.l"
+return NRTOK;
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 72 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 73 "engines/hypno/lexer_mis.l"
+return BBOXTOK;
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 74 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FLAG;
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 75 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return NAME;
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 76 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FILENAME;
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 77 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.i = atoi(HYPNO_MIS_text); return NUM;
+	YY_BREAK
+case 36:
+/* rule 36 can match eol */
+YY_RULE_SETUP
+#line 78 "engines/hypno/lexer_mis.l"
+return RETTOK;
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 79 "engines/hypno/lexer_mis.l"
+/* ignore whitespace */;
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 80 "engines/hypno/lexer_mis.l"
+debug("<no match>"); return *yytext;
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 81 "engines/hypno/lexer_mis.l"
+ECHO;
+	YY_BREAK
+#line 1347 "engines/hypno/lexer_mis.cpp"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_last_accepting_cpos);
+				yy_current_state = (yy_last_accepting_state);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap(  ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	char *source = (yytext_ptr);
+	int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc( (void *) b->yy_ch_buf,
+							 (yy_size_t) (b->yy_buf_size + 2)  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = NULL;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size  );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+		/* "- 2" to take care of EOB's */
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
+	}
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	yy_state_type yy_current_state;
+	char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 131 )
+				yy_c = yy_meta[yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	int yy_is_jam;
+    	char *yy_cp = (yy_c_buf_p);
+
+	YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 131 )
+			yy_c = yy_meta[yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+	yy_is_jam = (yy_current_state == 130);
+
+		return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap(  ) )
+						return 0;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	if ( c == '\n' )
+		
+    yylineno++;
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer( yyin, YY_BUF_SIZE );
+	}
+
+	yy_init_buffer( YY_CURRENT_BUFFER, input_file );
+	yy_load_buffer_state(  );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state(  );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2)  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree( (void *) b->yy_ch_buf  );
+
+	yyfree( (void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state(  );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state(  );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state(  );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	yy_size_t num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		yy_size_t grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		if ( ! (yy_buffer_stack) )
+			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return NULL;
+
+	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = (int) (size - 2);	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = NULL;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (const char * yystr )
+{
+    
+	return yy_scan_bytes( yystr, (int) strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = (yy_size_t) (_yybytes_len + 2);
+	buf = (char *) yyalloc( n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yynoreturn yy_fatal_error (const char* msg )
+{
+			fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+    
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param _line_number line number
+ * 
+ */
+void yyset_lineno (int  _line_number )
+{
+    
+    yylineno = _line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param _in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  _in_str )
+{
+        yyin = _in_str ;
+}
+
+void yyset_out (FILE *  _out_str )
+{
+        yyout = _out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  _bdebug )
+{
+        yy_flex_debug = _bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    /* We do not touch yylineno unless the option is enabled. */
+    yylineno =  1;
+    
+    (yy_buffer_stack) = NULL;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = NULL;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = NULL;
+    yyout = NULL;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer( YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, const char * s2, int n )
+{
+		
+	int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (const char * s )
+{
+	int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+			return malloc(size);
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+		
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return realloc(ptr, size);
+}
+
+void yyfree (void * ptr )
+{
+			free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 81 "engines/hypno/lexer_mis.l"
+
+
+namespace Hypno {
+
+int parse_mis(const char *code) {
+	YY_BUFFER_STATE bp;
+	yy_delete_buffer(YY_CURRENT_BUFFER);
+	bp = yy_scan_string(code);
+	yy_switch_to_buffer(bp);
+	HYPNO_MIS_parse();
+	yy_delete_buffer(bp);
+	return 0;
+}
+
+} // End of namespace Hypno
+
diff --git a/engines/hypno/tokens_arc.h b/engines/hypno/tokens_arc.h
new file mode 100644
index 0000000000..3324dfe21f
--- /dev/null
+++ b/engines/hypno/tokens_arc.h
@@ -0,0 +1,116 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_HYPNO_ARC_ENGINES_HYPNO_TOKENS_ARC_H_INCLUDED
+# define YY_HYPNO_ARC_ENGINES_HYPNO_TOKENS_ARC_H_INCLUDED
+/* Debug traces.  */
+#ifndef HYPNO_ARC_DEBUG
+# if defined YYDEBUG
+#if YYDEBUG
+#   define HYPNO_ARC_DEBUG 1
+#  else
+#   define HYPNO_ARC_DEBUG 0
+#  endif
+# else /* ! defined YYDEBUG */
+#  define HYPNO_ARC_DEBUG 0
+# endif /* ! defined YYDEBUG */
+#endif  /* ! defined HYPNO_ARC_DEBUG */
+#if HYPNO_ARC_DEBUG
+extern int HYPNO_ARC_debug;
+#endif
+
+/* Token type.  */
+#ifndef HYPNO_ARC_TOKENTYPE
+# define HYPNO_ARC_TOKENTYPE
+  enum HYPNO_ARC_tokentype
+  {
+    NAME = 258,
+    FILENAME = 259,
+    BNTOK = 260,
+    SNTOK = 261,
+    NUM = 262,
+    YXTOK = 263,
+    CTOK = 264,
+    DTOK = 265,
+    HTOK = 266,
+    HETOK = 267,
+    RETTOK = 268,
+    QTOK = 269,
+    ENCTOK = 270,
+    PTOK = 271,
+    FTOK = 272,
+    TTOK = 273,
+    TPTOK = 274,
+    ATOK = 275,
+    VTOK = 276,
+    OTOK = 277,
+    O1TOK = 278,
+    NTOK = 279,
+    RTOK = 280,
+    ITOK = 281,
+    ZTOK = 282,
+    FNTOK = 283,
+    NONETOK = 284,
+    A0TOK = 285,
+    K0TOK = 286,
+    P0TOK = 287,
+    WTOK = 288,
+    XTOK = 289,
+    CB3TOK = 290,
+    C02TOK = 291
+  };
+#endif
+
+/* Value type.  */
+#if ! defined HYPNO_ARC_STYPE && ! defined HYPNO_ARC_STYPE_IS_DECLARED
+
+union HYPNO_ARC_STYPE
+{
+#line 55 "engines/hypno/grammar_arc.y" /* yacc.c:1909  */
+
+	char *s; /* string value */
+	int i;	 /* integer value */
+
+#line 104 "engines/hypno/tokens_arc.h" /* yacc.c:1909  */
+};
+
+typedef union HYPNO_ARC_STYPE HYPNO_ARC_STYPE;
+# define HYPNO_ARC_STYPE_IS_TRIVIAL 1
+# define HYPNO_ARC_STYPE_IS_DECLARED 1
+#endif
+
+
+extern HYPNO_ARC_STYPE HYPNO_ARC_lval;
+
+int HYPNO_ARC_parse (void);
+
+#endif /* !YY_HYPNO_ARC_ENGINES_HYPNO_TOKENS_ARC_H_INCLUDED  */
diff --git a/engines/hypno/tokens_mis.h b/engines/hypno/tokens_mis.h
new file mode 100644
index 0000000000..9c073e386f
--- /dev/null
+++ b/engines/hypno/tokens_mis.h
@@ -0,0 +1,121 @@
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_HYPNO_MIS_ENGINES_HYPNO_TOKENS_MIS_H_INCLUDED
+# define YY_HYPNO_MIS_ENGINES_HYPNO_TOKENS_MIS_H_INCLUDED
+/* Debug traces.  */
+#ifndef HYPNO_MIS_DEBUG
+# if defined YYDEBUG
+#if YYDEBUG
+#   define HYPNO_MIS_DEBUG 1
+#  else
+#   define HYPNO_MIS_DEBUG 0
+#  endif
+# else /* ! defined YYDEBUG */
+#  define HYPNO_MIS_DEBUG 0
+# endif /* ! defined YYDEBUG */
+#endif  /* ! defined HYPNO_MIS_DEBUG */
+#if HYPNO_MIS_DEBUG
+extern int HYPNO_MIS_debug;
+#endif
+
+/* Token type.  */
+#ifndef HYPNO_MIS_TOKENTYPE
+# define HYPNO_MIS_TOKENTYPE
+  enum HYPNO_MIS_tokentype
+  {
+    NAME = 258,
+    FILENAME = 259,
+    FLAG = 260,
+    COMMENT = 261,
+    GSSWITCH = 262,
+    COMMAND = 263,
+    NUM = 264,
+    HOTSTOK = 265,
+    CUTSTOK = 266,
+    BACKTOK = 267,
+    RETTOK = 268,
+    TIMETOK = 269,
+    PALETOK = 270,
+    BBOXTOK = 271,
+    OVERTOK = 272,
+    WALNTOK = 273,
+    MICETOK = 274,
+    PLAYTOK = 275,
+    ENDTOK = 276,
+    MENUTOK = 277,
+    SMENTOK = 278,
+    ESCPTOK = 279,
+    NRTOK = 280,
+    AMBITOK = 281,
+    GLOBTOK = 282,
+    TONTOK = 283,
+    TOFFTOK = 284,
+    TALKTOK = 285,
+    INACTOK = 286,
+    FDTOK = 287,
+    BOXXTOK = 288,
+    PG = 289,
+    PA = 290,
+    PD = 291,
+    PH = 292,
+    PF = 293,
+    PE = 294,
+    PP = 295,
+    PI = 296
+  };
+#endif
+
+/* Value type.  */
+#if ! defined HYPNO_MIS_STYPE && ! defined HYPNO_MIS_STYPE_IS_DECLARED
+
+union HYPNO_MIS_STYPE
+{
+#line 57 "engines/hypno/grammar_mis.y" /* yacc.c:1909  */
+
+	char *s; /* string value */
+	int i;	 /* integer value */
+
+#line 109 "engines/hypno/tokens_mis.h" /* yacc.c:1909  */
+};
+
+typedef union HYPNO_MIS_STYPE HYPNO_MIS_STYPE;
+# define HYPNO_MIS_STYPE_IS_TRIVIAL 1
+# define HYPNO_MIS_STYPE_IS_DECLARED 1
+#endif
+
+
+extern HYPNO_MIS_STYPE HYPNO_MIS_lval;
+
+int HYPNO_MIS_parse (void);
+
+#endif /* !YY_HYPNO_MIS_ENGINES_HYPNO_TOKENS_MIS_H_INCLUDED  */


Commit: d5277d97ef72b7691318f4d8c884234c9e37b613
    https://github.com/scummvm/scummvm/commit/d5277d97ef72b7691318f4d8c884234c9e37b613
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: try to keep the compiler happy regarding LibFile class

Changed paths:
    engines/hypno/libfile.cpp
    engines/hypno/libfile.h


diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 9fc42e7643..d0da1960f7 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -25,6 +25,12 @@
 
 namespace Hypno {
 
+LibFile::LibFile() : Common::Archive() {
+}
+
+LibFile::~LibFile() {
+}
+
 bool LibFile::open(const Common::String &prefix, const Common::String &filename) {
 	_prefix = prefix;
 	Common::File libfile;
diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
index 592587cdab..b58fa8efa0 100644
--- a/engines/hypno/libfile.h
+++ b/engines/hypno/libfile.h
@@ -39,14 +39,17 @@ typedef struct FileEntry {
 
 class LibFile : public Common::Archive {
 public:
+	LibFile();
+	~LibFile() override;
+
 	bool open(const Common::String &prefix, const Common::String &filename);
 	void close();
 
 	// Common::Archive API implementation
-	bool hasFile(const Common::String &name) const;
+	bool hasFile(const Common::String &name) const override;
 	int listMembers(Common::ArchiveMemberList &list) const override;
-	const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
-	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+	const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
 
 private:
 	Common::String _prefix;


Commit: 38b3a96d60c4b6c65349e97d5bbfb0d85c9b684f
    https://github.com/scummvm/scummvm/commit/38b3a96d60c4b6c65349e97d5bbfb0d85c9b684f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added score, credits and fixed some minor issues

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar_arc.cpp
    engines/hypno/grammar_arc.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/scene.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 33738815d8..df8da59264 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -88,6 +88,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 	_levelId = arc.id;
 	_shootSound = arc.shootSound;
+	_score = 0;
 	_health = arc.health;
 	_maxHealth = _health;
 	_defaultCursor = "arcade";
@@ -111,6 +112,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 	changeCursor("arcade");
 	playVideo(background);
+	bool shooting = false;
 
 	while (!shouldQuit()) {
 
@@ -123,14 +125,22 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			case Common::EVENT_RETURN_TO_LAUNCHER:
 				break;
 
+			case Common::EVENT_KEYDOWN:
+				if (event.kbd.keycode == Common::KEYCODE_c) {
+					background.decoder->pauseVideo(true);
+					showCredits();
+					background.decoder->pauseVideo(false);
+				}
+				break;
+
 			case Common::EVENT_LBUTTONDOWN:
 				if (clickedPrimaryShoot(mousePos))
-					drawShoot(mousePos);
+					shooting = true;
 				break;
 
 			case Common::EVENT_RBUTTONDOWN:
 				if (clickedSecondaryShoot(mousePos))
-					drawShoot(mousePos);
+					shooting = true;
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
@@ -145,6 +155,11 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		if (background.decoder->needsUpdate()) {
 			drawScreen();
 			updateScreen(background);
+			if (shooting) {
+				drawShoot(mousePos);
+				shooting = false;
+			}
+
 			drawPlayer();
 			drawHealth();
 		}
@@ -160,7 +175,15 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 			break;
 		}
 
-		if (background.decoder->endOfVideo()) {
+		if (!arc.transitionVideo.empty() && background.decoder->getCurFrame() >= arc.transitionTime) {
+			debugC(1, kHypnoDebugArcade, "Playing transition %s", arc.transitionVideo.c_str());
+			arc.transitionTime = background.decoder->getFrameCount() + 1;
+			MVideo video(arc.transitionVideo, Common::Point(0, 0), false, false, false);
+			runIntro(video);
+			skipVideo(background);
+		}
+
+		if (!background.decoder || background.decoder->endOfVideo()) {
 			skipVideo(background);
 			if (!arc.winVideos.empty()) {
 				MVideo video(arc.winVideos.front(), Common::Point(0, 0), false, false, false);
@@ -199,7 +222,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 				if (frame > 0 && frame >= it->explosionFrame - 3 && !it->destroyed) {
 					skipVideo(*it->video);
-					_health = _health - it->damage;
+					//_health = _health - it->damage;
 				} else if (frame > 0 && frame >= it->video->decoder->getFrameCount()-2) {
 					skipVideo(*it->video);
 					shootsToRemove.push_back(i);
@@ -261,7 +284,7 @@ int HypnoEngine::detectTarget(Common::Point mousePos) {
 
 void HypnoEngine::drawCursorArcade(Common::Point mousePos) {
 	int i = detectTarget(mousePos);
-	if (i > 0)
+	if (i >= 0)
 		changeCursor("target");
 	else
 		changeCursor("arcade");
@@ -273,10 +296,11 @@ bool HypnoEngine::clickedPrimaryShoot(Common::Point mousePos) {
 	int i = detectTarget(mousePos);
 	int w = 0;
 	int h = 0;
-	if (i > 0) {
+	if (i >= 0) {
 		playSound(_soundPath + _shoots[i].endSound, 1);
 		w = _shoots[i].video->decoder->getWidth();
 		h = _shoots[i].video->decoder->getHeight();
+		_score++;
 		_shoots[i].destroyed = true;
 		_shoots[i].video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
 		_shoots[i].video->decoder->forceSeekToFrame(_shoots[i].explosionFrame + 2);
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index db7fe1c965..9ff7217f7d 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -223,6 +223,8 @@ public:
 	uint32 id;
 	Common::String levelIfWin;
 	Common::String levelIfLose;
+	Filename transitionVideo;
+	uint32 transitionTime;
 	Filenames defeatVideos;
 	Filenames winVideos;
 	Filename intro;
diff --git a/engines/hypno/grammar_arc.cpp b/engines/hypno/grammar_arc.cpp
index 211be2d277..0a5fbbaa55 100644
--- a/engines/hypno/grammar_arc.cpp
+++ b/engines/hypno/grammar_arc.cpp
@@ -507,10 +507,10 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint8 yyrline[] =
 {
        0,    77,    77,    81,    82,    83,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    97,   100,   103,   107,   108,
-     112,   113,   123,   133,   134,   137,   140,   141,   144,   145,
-     147,   152,   157,   162,   166,   170,   174,   175,   178,   182,
-     185,   188,   189,   190,   191,   195,   202,   203
+      90,    91,    92,    93,    94,    99,   104,   107,   111,   112,
+     116,   117,   127,   137,   138,   141,   144,   145,   148,   149,
+     151,   156,   161,   166,   170,   174,   178,   179,   182,   186,
+     189,   192,   193,   194,   195,   199,   206,   207
 };
 #endif
 
@@ -1392,60 +1392,64 @@ yyreduce:
 
   case 14:
 #line 94 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { 
+    {
+		  g_parsedArc.transitionVideo = (yyvsp[-2].s);
+		  g_parsedArc.transitionTime = (yyvsp[-1].i);
 		  debug("Tp %s %d %s", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].s)); 
 		}
-#line 1399 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1401 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 97 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 99 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
+		  g_parsedArc.transitionVideo = (yyvsp[-1].s);
+		  g_parsedArc.transitionTime = (yyvsp[0].i);
 		  debug("T %s %d", (yyvsp[-1].s), (yyvsp[0].i)); 
 		}
-#line 1407 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1411 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 100 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 104 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		  debug("T NONE %d", (yyvsp[0].i)); 
 		}
-#line 1415 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1419 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 103 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 107 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		  g_parsedArc.background = (yyvsp[0].s); 
 		  debug("N %s", (yyvsp[0].s)); 
 		}
-#line 1424 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1428 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 107 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 111 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("R %s", (yyvsp[0].s)); }
-#line 1430 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1434 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 108 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 112 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
   		  g_parsedArc.player = (yyvsp[0].s); 
 		  debug("I %s", (yyvsp[0].s)); 
 		}
-#line 1439 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1443 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 112 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 116 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("Q %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1445 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1449 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 113 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 117 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		  if (Common::String("B0") == (yyvsp[-1].s))
 		  	g_parsedArc.intro = (yyvsp[0].s);
@@ -1456,11 +1460,11 @@ yyreduce:
 		 	
 		  debug("BN %s", (yyvsp[0].s)); 
 		}
-#line 1460 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1464 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 123 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 127 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		  if (Common::String("S0") == (yyvsp[-2].s))
 		  	g_parsedArc.music = (yyvsp[-1].s);
@@ -1471,154 +1475,154 @@ yyreduce:
 
 		  debug("SN %s", (yyvsp[-1].s)); 
 		}
-#line 1475 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1479 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 133 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 137 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("HE %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1481 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1485 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 134 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 138 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		  g_parsedArc.health = (yyvsp[-1].i);
 		  debug("H %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1489 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1493 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 137 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 141 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("Z"); }
-#line 1495 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1499 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 147 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 151 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
 		debug("FN %s", (yyvsp[0].s)); 
 	 	}
-#line 1505 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1509 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 152 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 156 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = "NONE";
 		debug("FN NONE"); 
 	 	}
-#line 1515 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1519 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 157 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 161 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
 		debug("FN %s", (yyvsp[0].s)); 
 	 	}
-#line 1525 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1529 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 162 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 166 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		 shoot->name = (yyvsp[0].s);
 		 debug("I %s", (yyvsp[0].s)); 
 	   }
-#line 1534 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1538 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 166 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 170 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {  // Workaround for NAME == B1
 		 shoot->name = (yyvsp[0].s);
 		 debug("I %s", (yyvsp[0].s)); 
 	   }
-#line 1543 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1547 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 170 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 174 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		 shoot->position = Common::Point((yyvsp[-1].i), (yyvsp[0].i));
 		 debug("A0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 		}
-#line 1552 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1556 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 174 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 178 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("R %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1558 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1562 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 175 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 179 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 
 		 debug("BN %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1566 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1570 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 178 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 182 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		 shoot->explosionFrame = (yyvsp[0].i);
 		 debug("K0 %d %d", (yyvsp[-1].i), (yyvsp[0].i));
 		}
-#line 1575 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1579 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 182 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 186 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		debug("P0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	   }
-#line 1583 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1587 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 185 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		debug("O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	   }
-#line 1591 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1595 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 188 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 192 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("C %d", (yyvsp[0].i)); }
-#line 1597 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1601 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 193 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("H %d", (yyvsp[0].i)); }
-#line 1603 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1607 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 190 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 194 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("W %d", (yyvsp[0].i)); }
-#line 1609 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1613 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 191 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 195 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		 shoot->damage = (yyvsp[0].i);
 		 debug("D %d", (yyvsp[0].i)); 
 		}
-#line 1618 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1622 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 195 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 199 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		  if (Common::String("S1") == (yyvsp[-2].s))
 		  	shoot->endSound = (yyvsp[-1].s);
@@ -1626,28 +1630,28 @@ yyreduce:
 		  //	shoot->startSound = $2;
 		 
 		 debug("SN %s", (yyvsp[-1].s)); }
-#line 1630 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1634 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 202 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 206 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("N"); }
-#line 1636 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1640 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 203 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 207 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		g_parsedArc.shoots.push_back(*shoot); 
 		//delete shoot; 
 		//shoot = nullptr;
 	    debug("Z"); 
 		}
-#line 1647 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1651 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1651 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1655 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index cf801f7ce4..ec8c2787a5 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -91,10 +91,14 @@ hline:  CTOK NUM  { debug("C %d", $2); }
       | VTOK NUM NUM { debug("V %d %d", $2, $3); }
       | OTOK NUM NUM { debug("O %d %d", $2, $3); }
 	  | O1TOK NUM NUM { debug("O1 %d %d", $2, $3); }
-	  | TPTOK FILENAME NUM FILENAME { 
+	  | TPTOK FILENAME NUM FILENAME {
+		  g_parsedArc.transitionVideo = $2;
+		  g_parsedArc.transitionTime = $3;
 		  debug("Tp %s %d %s", $2, $3, $4); 
 		}
 	  | TTOK FILENAME NUM { 
+		  g_parsedArc.transitionVideo = $2;
+		  g_parsedArc.transitionTime = $3;
 		  debug("T %s %d", $2, $3); 
 		}
 	  | TTOK NONETOK NUM { 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 10ff2d8f89..8c006e679b 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -149,11 +149,7 @@ void HypnoEngine::runLevel(Common::String name) {
 
 	if (!_levels[name].trans.level.empty()) {
 		debugC(1, kHypnoDebugScene, "Executing transition level %s", name.c_str());
-		_nextLevel = _levels[name].trans.level;
-		for (Filenames::iterator it = _levels[name].trans.intros.begin(); it != _levels[name].trans.intros.end(); ++it) {
-			MVideo v(*it, Common::Point(0, 0), false, true, false);
-			runIntro(v);
-		}
+		runTransition(_levels[name].trans);
 
 	} else if (!_levels[name].arcade.background.empty()) {
 		debugC(1, kHypnoDebugArcade, "Executing arcade level %s", name.c_str());
@@ -221,6 +217,8 @@ void HypnoEngine::runIntro(MVideo &video) {
 
 void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Not implemented"); }
 
+void HypnoEngine::showCredits() { error("credits"); /* Nothing */ };
+
 void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
 	debugC(1, kHypnoDebugMedia, "%s(%s, %d, %d, %d)", __FUNCTION__, name.c_str(), x, y, transparent);
 	Graphics::Surface *surf = decodeFrame(name, 0);
@@ -377,6 +375,8 @@ void HypnoEngine::playVideo(MVideo &video) {
 }
 
 void HypnoEngine::skipVideo(MVideo &video) {
+	if (!video.decoder)
+		return;
 	debugC(1, kHypnoDebugMedia, "%s()", __FUNCTION__);
 	video.decoder->close();
 	delete video.decoder;
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 5fa8423d7d..081e4add94 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -200,6 +200,7 @@ public:
 	virtual void drawHealth();
 	int _health;
 	int _maxHealth;
+	int _score;
 	Filename _shootSound;
 	Shoots _shoots;
 	Frames _playerFrames;
@@ -217,6 +218,12 @@ public:
 	// Hardcoded puzzles
 	virtual void runPuzzle(Puzzle puzzle);
 
+	// Transitions
+	void runTransition(Transition trans);
+
+	// Credits
+	virtual void showCredits();
+
 	// Timers
 	bool installTimer(uint32, Common::String *);
 	void removeTimer();
@@ -227,6 +234,7 @@ public:
 	WetEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
+	void showCredits() override;
 	bool clickedSecondaryShoot(Common::Point) override;
 	void drawShoot(Common::Point) override;
 	void drawPlayer() override;
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index c70c0fd86c..dc0accf13a 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -176,6 +176,15 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 	return false;
 }
 
+void HypnoEngine::runTransition(Transition trans) {
+	_nextLevel = trans.level;
+	for (Filenames::iterator it = trans.intros.begin(); it != trans.intros.end(); ++it) {
+		MVideo v(*it, Common::Point(0, 0), false, true, false);
+		runIntro(v);
+	}
+}
+
+
 void HypnoEngine::runScene(Scene scene) {
 	_refreshConversation = false;
 	_conversation.clear();
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index ec3c8d96d9..d0f7fd654f 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -61,10 +61,12 @@ static const int uiPos[2][3][2] = {
 void WetEngine::drawHealth() {
 	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	int p = (100 * _health) / _maxHealth;
+	int s = _score;
 	if (_playerFrameIdx < _playerFrameSep) {
 		uint32 id = _levelId;
 		_font->drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), uiPos[id][0][0], uiPos[id][0][1], 65, c);
-		_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", 0), uiPos[id][1][0], uiPos[id][1][1], 72, c);
+		_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", s), uiPos[id][1][0], uiPos[id][1][1], 72, c);
+		// Objectives are always in the zero in the demo
 		_font->drawString(_compositeSurface, Common::String::format("M.O.     0/0"), uiPos[id][2][0], uiPos[id][2][1], 60, c);
 	}
 }
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 44fd7168f3..661a72dab4 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -132,4 +132,10 @@ void WetEngine::loadAssets() {
 	loadLib("wetlands/sound/", "wetlands/c_misc/sound.lib");
 }
 
+void WetEngine::showCredits() {
+	MVideo video("c_misc/credits.smk", Common::Point(0, 0), false, false, false);
+	runIntro(video);
+}
+
+
 } // End of namespace Hypno


Commit: 8a158c72ec18ad5afa22b0a8da474d2032c83c8a
    https://github.com/scummvm/scummvm/commit/8a158c72ec18ad5afa22b0a8da474d2032c83c8a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed secondary shoot in Wetlands and added support for static frame transitions

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/scene.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index df8da59264..884b19711c 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -112,7 +112,8 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 	changeCursor("arcade");
 	playVideo(background);
-	bool shooting = false;
+	bool shootingPrimary = false;
+	bool shootingSecondary = false;
 
 	while (!shouldQuit()) {
 
@@ -135,12 +136,16 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 			case Common::EVENT_LBUTTONDOWN:
 				if (clickedPrimaryShoot(mousePos))
-					shooting = true;
+					shootingPrimary = true;
 				break;
 
 			case Common::EVENT_RBUTTONDOWN:
 				if (clickedSecondaryShoot(mousePos))
-					shooting = true;
+					shootingSecondary = true;
+				break;
+
+			case Common::EVENT_RBUTTONUP:
+				shootingSecondary = false;
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
@@ -155,9 +160,10 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 		if (background.decoder->needsUpdate()) {
 			drawScreen();
 			updateScreen(background);
-			if (shooting) {
+			if (shootingPrimary || shootingSecondary) {
+				shoot(mousePos);
 				drawShoot(mousePos);
-				shooting = false;
+				shootingPrimary = false;
 			}
 
 			drawPlayer();
@@ -171,7 +177,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				runIntro(video);
 			}
 			_nextLevel = arc.levelIfLose;
-			debugC(1, kHypnoDebugArcade, "Losing and jumping to %s", _nextLevel.c_str());
+			debugC(1, kHypnoDebugArcade, "Losing level and jumping to %s", _nextLevel.c_str());
 			break;
 		}
 
@@ -190,7 +196,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 				runIntro(video);
 			}
 			_nextLevel = arc.levelIfWin;
-			debugC(1, kHypnoDebugArcade, "Wining and jumping to %s", _nextLevel.c_str());
+			debugC(1, kHypnoDebugArcade, "Wining level and jumping to %s", _nextLevel.c_str());
 			break;
 		}
 
@@ -292,7 +298,9 @@ void HypnoEngine::drawCursorArcade(Common::Point mousePos) {
 	g_system->copyRectToScreen(_compositeSurface->getPixels(), _compositeSurface->pitch, 0, 0, _screenW, _screenH);
 }
 
-bool HypnoEngine::clickedPrimaryShoot(Common::Point mousePos) {
+bool HypnoEngine::clickedPrimaryShoot(Common::Point mousePos) { return true; };
+
+void HypnoEngine::shoot(Common::Point mousePos) {
 	int i = detectTarget(mousePos);
 	int w = 0;
 	int h = 0;
@@ -305,7 +313,6 @@ bool HypnoEngine::clickedPrimaryShoot(Common::Point mousePos) {
 		_shoots[i].video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
 		_shoots[i].video->decoder->forceSeekToFrame(_shoots[i].explosionFrame + 2);
 	}
-	return true;
 }
 
 bool HypnoEngine::clickedSecondaryShoot(Common::Point mousePos) {
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 9ff7217f7d..f831ac157a 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -197,6 +197,8 @@ typedef Common::Array<Common::String> Sounds;
 class Transition {
 public:
 	Common::String level;
+	Filename frameImage;
+	uint32 frameNumber;
 	Filenames intros;
 };
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 8c006e679b..0374743aa2 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -44,6 +44,7 @@ namespace Hypno {
 
 Hotspots *g_parsedHots;
 ArcadeShooting g_parsedArc;
+HypnoEngine *g_hypno;
 
 MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent, bool _scaled, bool _loop) {
 	path = _path;
@@ -60,6 +61,7 @@ HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	  _screenW(640), _screenH(480) {
 	_rnd = new Common::RandomSource("hypno");
 
+	g_hypno = this;
 	_defaultCursor = "";
 	// Add quit level
 	Hotspot q;
@@ -424,4 +426,18 @@ Common::String HypnoEngine::convertPath(const Common::String &name) {
 	return path;
 }
 
+// Timers
+static void timerCallback(void *refCon) {
+	g_hypno->removeTimer();
+	g_hypno->_nextLevel = *(Common::String *)refCon;
+}
+
+bool HypnoEngine::installTimer(uint32 delay, Common::String *ns) {
+	return g_system->getTimerManager()->installTimerProc(&timerCallback, delay, (void *)ns, "timerCallback");
+}
+
+void HypnoEngine::removeTimer() {
+	g_system->getTimerManager()->removeTimerProc(&timerCallback);
+}
+
 } // End of namespace Hypno
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 081e4add94..b0891c0a0a 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -193,6 +193,7 @@ public:
 	virtual bool clickedPrimaryShoot(Common::Point);
 	virtual bool clickedSecondaryShoot(Common::Point);
 	virtual void drawShoot(Common::Point);
+	virtual void shoot(Common::Point);
 	virtual void hitPlayer();
 
 	void drawCursorArcade(Common::Point mousePos);
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index dc0accf13a..7675f28a31 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -177,11 +177,24 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 }
 
 void HypnoEngine::runTransition(Transition trans) {
-	_nextLevel = trans.level;
 	for (Filenames::iterator it = trans.intros.begin(); it != trans.intros.end(); ++it) {
 		MVideo v(*it, Common::Point(0, 0), false, true, false);
 		runIntro(v);
 	}
+
+	if (!trans.frameImage.empty()) {
+		debugC(1, kHypnoDebugScene, "Rendering %s frame in transaction", trans.frameImage.c_str());
+		Graphics::Surface *frame = decodeFrame(trans.frameImage, trans.frameNumber);
+		Graphics::Surface *sframe = frame->scale(_screenW, _screenH);
+		drawImage(*sframe, 0, 0, false);
+		drawScreen();
+		frame->free();
+		delete frame;
+		sframe->free();
+		delete sframe;
+		assert(installTimer(2 * 1000000, &trans.level));
+	} else
+		_nextLevel = trans.level;
 }
 
 
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 661a72dab4..5a314dd3ff 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -84,6 +84,8 @@ void WetEngine::loadAssets() {
 	intro.trans.intros.push_back("movie/nw_logo.smk");
 	intro.trans.intros.push_back("movie/hypnotix.smk");
 	intro.trans.intros.push_back("movie/wetlogo.smk");
+	intro.trans.frameImage = "wetlands/c_misc/c.s";
+	intro.trans.frameNumber = 0;
 	_levels["<intro>"] = intro;
 
 	byte x;


Commit: 2f5417faf695fb40e047acd3651abac86c634247
    https://github.com/scummvm/scummvm/commit/2f5417faf695fb40e047acd3651abac86c634247
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed LibFile class after rebase

Changed paths:
    engines/hypno/libfile.cpp
    engines/hypno/libfile.h


diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index d0da1960f7..769163110c 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -75,7 +75,8 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename)
 	return true;
 }
 
-const FileEntry *LibFile::getEntry(const Common::String &name) const {
+const FileEntry *LibFile::getEntry(const Common::Path &path) const {
+	Common::String name = path.toString();
 	for (Common::Array<FileEntry>::const_iterator it = _fileEntries.begin(); it != _fileEntries.end(); ++it) {
 		if (((_prefix + it->name).equalsIgnoreCase(name)) || it->name.equalsIgnoreCase(name))
 			return it;
@@ -88,9 +89,9 @@ void LibFile::close() {
 	_fileEntries.clear();
 }
 
-bool LibFile::hasFile(const Common::String &name) const {
-	error("hasFile");
-	return false;
+bool LibFile::hasFile(const Common::Path &path) const {
+	Common::String name = path.toString();
+	return getEntry(name) != nullptr;
 }
 
 int LibFile::listMembers(Common::ArchiveMemberList &list) const {
@@ -101,12 +102,13 @@ int LibFile::listMembers(Common::ArchiveMemberList &list) const {
 	return list.size();
 }
 
-const Common::ArchiveMemberPtr LibFile::getMember(const Common::String &name) const {
+const Common::ArchiveMemberPtr LibFile::getMember(const Common::Path &path) const {
+	Common::String name = path.toString();
 	return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
 }
 
-Common::SeekableReadStream *LibFile::createReadStreamForMember(const Common::String &name) const {
-	//error("Not implemented %s", name.c_str());
+Common::SeekableReadStream *LibFile::createReadStreamForMember(const Common::Path &path) const {
+	Common::String name = path.toString();
 	const FileEntry *entry = getEntry(name);
 	Common::MemoryReadStream *stream = nullptr;
 	if (entry != nullptr)
diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
index b58fa8efa0..b8e17af314 100644
--- a/engines/hypno/libfile.h
+++ b/engines/hypno/libfile.h
@@ -46,15 +46,15 @@ public:
 	void close();
 
 	// Common::Archive API implementation
-	bool hasFile(const Common::String &name) const override;
+	bool hasFile(const Common::Path &path) const override;
 	int listMembers(Common::ArchiveMemberList &list) const override;
-	const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
-	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
+	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
+	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
 
 private:
 	Common::String _prefix;
 	Common::Array<FileEntry> _fileEntries;
-	const FileEntry *getEntry(const Common::String &name) const;
+	const FileEntry *getEntry(const Common::Path &path) const;
 };
 
 } // End of namespace Hypno


Commit: 303704a71e15e96593fc482b9492b8bdeb8aec0c
    https://github.com/scummvm/scummvm/commit/303704a71e15e96593fc482b9492b8bdeb8aec0c
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved spider shoot animation

Changed paths:
    engines/hypno/spider/arcade.cpp


diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 1bd39928f3..43e43c50d9 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -30,13 +30,18 @@
 
 namespace Hypno {
 
-static const int frame_idx[9] = {0, 1, 2, 7, 8, 3, 6, 5, 4};
+static const int orientationIndex[9] = {0, 1, 2, 7, 8, 3, 6, 5, 4};
+static const int shootOriginIndex[9][2] = {
+	{41, 3}, {51, 3}, {65, 6}, {68, 9}, {71, 22}, {57, 20}, {37, 14}, {37, 11}, {57, 20}};
 
 void SpiderEngine::drawShoot(Common::Point target) {
 	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
-	_compositeSurface->drawLine(80, 155, target.x, target.y + 1, c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y, c);
-	_compositeSurface->drawLine(80, 155, target.x, target.y - 1, c);
+	uint32 idx = std::min(2, target.x / (_screenW / 3)) + 3 * std::min(2, target.y / (_screenH / 3));
+	uint32 ox = 60  + shootOriginIndex[idx][0];
+	uint32 oy = 129 + shootOriginIndex[idx][1];
+	_compositeSurface->drawLine(ox, oy, target.x + 2, target.y, c);
+	_compositeSurface->drawLine(ox, oy, target.x, target.y, c);
+	_compositeSurface->drawLine(ox, oy, target.x - 2, target.y, c);
 	playSound(_soundPath + _shootSound, 1);
 }
 
@@ -44,7 +49,8 @@ void SpiderEngine::drawPlayer() {
 
 	if (_playerFrameIdx < _playerFrameSep) {
 		Common::Point mousePos = g_system->getEventManager()->getMousePos();
-		_playerFrameIdx = frame_idx[std::min(2, mousePos.x / (_screenW / 3)) + 3 * std::min(2, mousePos.y / (_screenH / 3))];
+		uint32 idx = std::min(2, mousePos.x / (_screenW / 3)) + 3 * std::min(2, mousePos.y / (_screenH / 3));
+		_playerFrameIdx = orientationIndex[idx];
 	} else {
 		_playerFrameIdx++;
 		if (_playerFrameIdx >= _playerFrames.size())


Commit: 9df22aecbbf76c7e3d25d748e702aa5b5e0cc432
    https://github.com/scummvm/scummvm/commit/9df22aecbbf76c7e3d25d748e702aa5b5e0cc432
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: use empty() instead of size() and removed some useless allocations

Changed paths:
    engines/hypno/scene.cpp


diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 7675f28a31..4274393be0 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -64,20 +64,19 @@ void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	filename = convertPath(filename);
 	if (!prefix.empty())
 		filename = prefix + "/" + filename;
-	Common::File *test = new Common::File();
-	assert(test->open(filename.c_str()));
+	Common::File test;
+	assert(test.open(filename.c_str()));
 
-	const uint32 fileSize = test->size();
+	const uint32 fileSize = test.size();
 	char *buf = (char *)malloc(fileSize + 1);
-	test->read(buf, fileSize);
+	test.read(buf, fileSize);
+	test.close();
 	buf[fileSize] = '\0';
 	parse_mis(buf);
 	Level level;
 	level.scene.prefix = prefix;
 	level.scene.hots = *g_parsedHots;
 	_levels[filename] = level;
-	test->close();
-	delete test;
 	free(buf);
 }
 
@@ -117,7 +116,7 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 	}
 	if (found) {
 		if (selected.smenu) {
-			assert(selected.smenu->size() > 0);
+			assert(!selected.smenu->empty());
 			_nextHotsToAdd = selected.smenu;
 		}
 
@@ -251,7 +250,7 @@ void HypnoEngine::runScene(Scene scene) {
 					leftClickedConversation(mousePos);
 					break;
 				}
-				if (!_nextHotsToAdd && !_nextHotsToRemove /*&& _videosPlaying.size() == 0*/)
+				if (!_nextHotsToAdd && !_nextHotsToRemove /*&& _videosPlaying.empty()*/)
 					clickedHotspot(mousePos);
 				break;
 
@@ -260,7 +259,7 @@ void HypnoEngine::runScene(Scene scene) {
 				//changeCursor("default");
 				// The following functions will return true
 				// if the cursor is changed
-				if (stack.empty() || !_conversation.empty() || _videosPlaying.size() > 0)
+				if (stack.empty() || !_conversation.empty() || !_videosPlaying.empty())
 					break;
 
 				if (hoverHotspot(mousePos)) {
@@ -281,7 +280,7 @@ void HypnoEngine::runScene(Scene scene) {
 		}
 
 		// Movies
-		if (_nextSequentialVideoToPlay.size() > 0 && _videosPlaying.empty()) {
+		if (!_nextSequentialVideoToPlay.empty() && _videosPlaying.empty()) {
 			playVideo(*_nextSequentialVideoToPlay.begin());
 			_videosPlaying.push_back(*_nextSequentialVideoToPlay.begin());
 			_nextSequentialVideoToPlay.remove_at(0);
@@ -308,7 +307,7 @@ void HypnoEngine::runScene(Scene scene) {
 			}
 			i++;
 		}
-		if (videosToRemove.size() > 0) {
+		if (!videosToRemove.empty()) {
 
 			for (Common::List<uint32>::iterator it = videosToRemove.begin(); it != videosToRemove.end(); ++it) {
 				debugC(1, kHypnoDebugScene, "removing %d from %d size", *it, _videosPlaying.size());
@@ -316,7 +315,7 @@ void HypnoEngine::runScene(Scene scene) {
 			}
 
 			// Nothing else to play
-			if (_videosPlaying.size() == 0 && _nextSequentialVideoToPlay.size() == 0) {
+			if (_videosPlaying.empty() && _nextSequentialVideoToPlay.empty()) {
 				if (!_conversation.empty())
 					_refreshConversation = true;
 				else if (!stack.empty()) {
@@ -326,7 +325,7 @@ void HypnoEngine::runScene(Scene scene) {
 			}
 		}
 
-		if (_videosPlaying.size() > 0 || _nextSequentialVideoToPlay.size() > 0) {
+		if (!_videosPlaying.empty() || !_nextSequentialVideoToPlay.empty()) {
 			drawScreen();
 			continue;
 		}


Commit: f5b458f17575f9f00cbb7a3986eff88b6f3b26c7
    https://github.com/scummvm/scummvm/commit/f5b458f17575f9f00cbb7a3986eff88b6f3b26c7
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed grammar_arc.y and regenerated code

Changed paths:
    engines/hypno/grammar_arc.cpp
    engines/hypno/grammar_arc.y


diff --git a/engines/hypno/grammar_arc.cpp b/engines/hypno/grammar_arc.cpp
index 0a5fbbaa55..6baa6c13b2 100644
--- a/engines/hypno/grammar_arc.cpp
+++ b/engines/hypno/grammar_arc.cpp
@@ -92,7 +92,7 @@ void HYPNO_ARC_xerror(const char *str) {
 }
 
 int HYPNO_ARC_wrap() {
-    return 1;
+	return 1;
 }
 
 using namespace Hypno;
@@ -507,10 +507,10 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint8 yyrline[] =
 {
        0,    77,    77,    81,    82,    83,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    99,   104,   107,   111,   112,
-     116,   117,   127,   137,   138,   141,   144,   145,   148,   149,
-     151,   156,   161,   166,   170,   174,   178,   179,   182,   186,
-     189,   192,   193,   194,   195,   199,   206,   207
+      90,    91,    92,    93,    94,    99,   104,   105,   109,   110,
+     114,   115,   125,   135,   136,   140,   143,   144,   147,   148,
+     150,   155,   160,   165,   169,   173,   177,   178,   179,   183,
+     184,   187,   188,   189,   190,   194,   201,   202
 };
 #endif
 
@@ -1393,265 +1393,260 @@ yyreduce:
   case 14:
 #line 94 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
-		  g_parsedArc.transitionVideo = (yyvsp[-2].s);
-		  g_parsedArc.transitionTime = (yyvsp[-1].i);
-		  debug("Tp %s %d %s", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].s)); 
-		}
+		g_parsedArc.transitionVideo = (yyvsp[-2].s);
+		g_parsedArc.transitionTime = (yyvsp[-1].i);
+		debug("Tp %s %d %s", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].s)); 
+	}
 #line 1401 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
 #line 99 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		  g_parsedArc.transitionVideo = (yyvsp[-1].s);
-		  g_parsedArc.transitionTime = (yyvsp[0].i);
-		  debug("T %s %d", (yyvsp[-1].s), (yyvsp[0].i)); 
-		}
+		g_parsedArc.transitionVideo = (yyvsp[-1].s);
+		g_parsedArc.transitionTime = (yyvsp[0].i);
+		debug("T %s %d", (yyvsp[-1].s), (yyvsp[0].i)); 
+	}
 #line 1411 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
 #line 104 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { 
-		  debug("T NONE %d", (yyvsp[0].i)); 
-		}
-#line 1419 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debug("T NONE %d", (yyvsp[0].i)); }
+#line 1417 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 107 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 105 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		  g_parsedArc.background = (yyvsp[0].s); 
-		  debug("N %s", (yyvsp[0].s)); 
-		}
-#line 1428 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		g_parsedArc.background = (yyvsp[0].s); 
+		debug("N %s", (yyvsp[0].s)); 
+	}
+#line 1426 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 111 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 109 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("R %s", (yyvsp[0].s)); }
-#line 1434 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1432 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 112 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 110 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-  		  g_parsedArc.player = (yyvsp[0].s); 
-		  debug("I %s", (yyvsp[0].s)); 
+		g_parsedArc.player = (yyvsp[0].s); 
+		debug("I %s", (yyvsp[0].s)); 
 		}
-#line 1443 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1441 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 116 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 114 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("Q %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1449 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1447 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 117 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 115 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
-		  if (Common::String("B0") == (yyvsp[-1].s))
-		  	g_parsedArc.intro = (yyvsp[0].s);
-		  else if(Common::String("B1") == (yyvsp[-1].s) || Common::String("B2") == (yyvsp[-1].s))
-		    g_parsedArc.winVideos.push_back((yyvsp[0].s));
-		  else if(Common::String("B3") == (yyvsp[-1].s) || Common::String("B4") == (yyvsp[-1].s))
-		    g_parsedArc.defeatVideos.push_back((yyvsp[0].s));
-		 	
-		  debug("BN %s", (yyvsp[0].s)); 
-		}
-#line 1464 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		if (Common::String("B0") == (yyvsp[-1].s))
+			g_parsedArc.intro = (yyvsp[0].s);
+		else if(Common::String("B1") == (yyvsp[-1].s) || Common::String("B2") == (yyvsp[-1].s))
+			g_parsedArc.winVideos.push_back((yyvsp[0].s));
+		else if(Common::String("B3") == (yyvsp[-1].s) || Common::String("B4") == (yyvsp[-1].s))
+			g_parsedArc.defeatVideos.push_back((yyvsp[0].s));
+
+		debug("BN %s", (yyvsp[0].s)); 
+	}
+#line 1462 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 127 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 125 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
-		  if (Common::String("S0") == (yyvsp[-2].s))
-		  	g_parsedArc.music = (yyvsp[-1].s);
-		  else if (Common::String("S1") == (yyvsp[-2].s))
-		  	g_parsedArc.shootSound = (yyvsp[-1].s);
-		  else if (Common::String("S4") == (yyvsp[-2].s))
-		    g_parsedArc.enemySound = (yyvsp[-1].s); 
-
-		  debug("SN %s", (yyvsp[-1].s)); 
-		}
-#line 1479 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		if (Common::String("S0") == (yyvsp[-2].s))
+			g_parsedArc.music = (yyvsp[-1].s);
+		else if (Common::String("S1") == (yyvsp[-2].s))
+			g_parsedArc.shootSound = (yyvsp[-1].s);
+		else if (Common::String("S4") == (yyvsp[-2].s))
+			g_parsedArc.enemySound = (yyvsp[-1].s); 
+
+		debug("SN %s", (yyvsp[-1].s)); 
+	}
+#line 1477 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 137 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 135 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("HE %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1485 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1483 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 138 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 136 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		  g_parsedArc.health = (yyvsp[-1].i);
-		  debug("H %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1493 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		g_parsedArc.health = (yyvsp[-1].i);
+		debug("H %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+	}
+#line 1492 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 141 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 140 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("Z"); }
-#line 1499 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1498 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 151 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 150 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
 		debug("FN %s", (yyvsp[0].s)); 
-	 	}
-#line 1509 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+	}
+#line 1508 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 156 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 155 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = "NONE";
 		debug("FN NONE"); 
-	 	}
-#line 1519 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+	}
+#line 1518 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 161 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 160 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
 		debug("FN %s", (yyvsp[0].s)); 
-	 	}
-#line 1529 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+	}
+#line 1528 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 166 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 165 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		 shoot->name = (yyvsp[0].s);
-		 debug("I %s", (yyvsp[0].s)); 
-	   }
-#line 1538 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		shoot->name = (yyvsp[0].s);
+		debug("I %s", (yyvsp[0].s)); 
+	}
+#line 1537 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 170 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 169 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {  // Workaround for NAME == B1
-		 shoot->name = (yyvsp[0].s);
-		 debug("I %s", (yyvsp[0].s)); 
-	   }
-#line 1547 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		shoot->name = (yyvsp[0].s);
+		debug("I %s", (yyvsp[0].s)); 
+	}
+#line 1546 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 174 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 173 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		 shoot->position = Common::Point((yyvsp[-1].i), (yyvsp[0].i));
-		 debug("A0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
-		}
-#line 1556 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		shoot->position = Common::Point((yyvsp[-1].i), (yyvsp[0].i));
+		debug("A0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+	}
+#line 1555 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 178 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 177 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("R %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1562 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1561 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 179 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { 
-
-		 debug("BN %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1570 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 178 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("BN %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1567 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 182 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 179 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		 shoot->explosionFrame = (yyvsp[0].i);
-		 debug("K0 %d %d", (yyvsp[-1].i), (yyvsp[0].i));
-		}
-#line 1579 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		shoot->explosionFrame = (yyvsp[0].i);
+		debug("K0 %d %d", (yyvsp[-1].i), (yyvsp[0].i));
+	}
+#line 1576 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 186 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    {
-		debug("P0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
-	   }
-#line 1587 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 183 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debug("P0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1582 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 184 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		debug("O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
-	   }
-#line 1595 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+	}
+#line 1590 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 192 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 187 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("C %d", (yyvsp[0].i)); }
-#line 1601 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1596 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 193 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 188 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("H %d", (yyvsp[0].i)); }
-#line 1607 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1602 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 194 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("W %d", (yyvsp[0].i)); }
-#line 1613 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1608 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 195 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 190 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		 shoot->damage = (yyvsp[0].i);
-		 debug("D %d", (yyvsp[0].i)); 
-		}
-#line 1622 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		shoot->damage = (yyvsp[0].i);
+		debug("D %d", (yyvsp[0].i)); 
+	}
+#line 1617 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 199 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 194 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		  if (Common::String("S1") == (yyvsp[-2].s))
-		  	shoot->endSound = (yyvsp[-1].s);
-		  //else if (Common::String("S2") == $1)
-		  //	shoot->startSound = $2;
+		if (Common::String("S1") == (yyvsp[-2].s))
+			shoot->endSound = (yyvsp[-1].s);
+		//else if (Common::String("S2") == $1)
+		//	shoot->startSound = $2;
 		 
-		 debug("SN %s", (yyvsp[-1].s)); }
-#line 1634 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		debug("SN %s", (yyvsp[-1].s)); }
+#line 1629 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 206 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 201 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debug("N"); }
-#line 1640 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1635 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 207 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 202 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		g_parsedArc.shoots.push_back(*shoot); 
 		//delete shoot; 
 		//shoot = nullptr;
-	    debug("Z"); 
-		}
-#line 1651 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		debug("Z"); 
+	}
+#line 1646 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1655 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1650 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index ec8c2787a5..7914372ae9 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -45,12 +45,12 @@ void HYPNO_ARC_xerror(const char *str) {
 }
 
 int HYPNO_ARC_wrap() {
-    return 1;
+	return 1;
 }
 
 using namespace Hypno;
 
-%} 
+%}
 
 %union {
 	char *s; /* string value */
@@ -75,139 +75,134 @@ using namespace Hypno;
 %%
 
 start: YXTOK header body
-      ;
+	;
 
 
 header:  hline RETTOK header
-       | hline
-	   | RETTOK header      
-	   ; 
+	| hline
+	| RETTOK header
+	; 
 
 hline:  CTOK NUM  { debug("C %d", $2); }
-      | FTOK NUM { debug("F %d", $2); }
-      | DTOK NUM  { debug("D %d", $2); }
-      | PTOK NUM NUM { debug("P %d %d", $2, $3); }
-      | ATOK NUM NUM { debug("A %d %d", $2, $3); }
-      | VTOK NUM NUM { debug("V %d %d", $2, $3); }
-      | OTOK NUM NUM { debug("O %d %d", $2, $3); }
-	  | O1TOK NUM NUM { debug("O1 %d %d", $2, $3); }
-	  | TPTOK FILENAME NUM FILENAME {
-		  g_parsedArc.transitionVideo = $2;
-		  g_parsedArc.transitionTime = $3;
-		  debug("Tp %s %d %s", $2, $3, $4); 
+	| FTOK NUM { debug("F %d", $2); }
+	| DTOK NUM  { debug("D %d", $2); }
+	| PTOK NUM NUM { debug("P %d %d", $2, $3); }
+	| ATOK NUM NUM { debug("A %d %d", $2, $3); }
+	| VTOK NUM NUM { debug("V %d %d", $2, $3); }
+	| OTOK NUM NUM { debug("O %d %d", $2, $3); }
+	| O1TOK NUM NUM { debug("O1 %d %d", $2, $3); }
+	| TPTOK FILENAME NUM FILENAME {
+		g_parsedArc.transitionVideo = $2;
+		g_parsedArc.transitionTime = $3;
+		debug("Tp %s %d %s", $2, $3, $4); 
+	}
+	| TTOK FILENAME NUM { 
+		g_parsedArc.transitionVideo = $2;
+		g_parsedArc.transitionTime = $3;
+		debug("T %s %d", $2, $3); 
+	}
+	| TTOK NONETOK NUM { debug("T NONE %d", $3); }
+	| NTOK FILENAME  { 
+		g_parsedArc.background = $2; 
+		debug("N %s", $2); 
+	}
+	| RTOK FILENAME  { debug("R %s", $2); }
+	| ITOK FILENAME { 
+		g_parsedArc.player = $2; 
+		debug("I %s", $2); 
 		}
-	  | TTOK FILENAME NUM { 
-		  g_parsedArc.transitionVideo = $2;
-		  g_parsedArc.transitionTime = $3;
-		  debug("T %s %d", $2, $3); 
-		}
-	  | TTOK NONETOK NUM { 
-		  debug("T NONE %d", $3); 
-		}
-	  | NTOK FILENAME  { 
-		  g_parsedArc.background = $2; 
-		  debug("N %s", $2); 
-		}
-	  | RTOK FILENAME  { debug("R %s", $2); }
-	  | ITOK FILENAME { 
-  		  g_parsedArc.player = $2; 
-		  debug("I %s", $2); 
-		}
-	  | QTOK NUM NUM { debug("Q %d %d", $2, $3); }
-	  | BNTOK FILENAME {
-		  if (Common::String("B0") == $1)
-		  	g_parsedArc.intro = $2;
-		  else if(Common::String("B1") == $1 || Common::String("B2") == $1)
-		    g_parsedArc.winVideos.push_back($2);
-		  else if(Common::String("B3") == $1 || Common::String("B4") == $1)
-		    g_parsedArc.defeatVideos.push_back($2);
-		 	
-		  debug("BN %s", $2); 
-		}
-	  | SNTOK FILENAME enc {
-		  if (Common::String("S0") == $1)
-		  	g_parsedArc.music = $2;
-		  else if (Common::String("S1") == $1)
-		  	g_parsedArc.shootSound = $2;
-		  else if (Common::String("S4") == $1)
-		    g_parsedArc.enemySound = $2; 
-
-		  debug("SN %s", $2); 
-		}
-	  | HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
-	  | HTOK CB3TOK NUM NUM { 
-		  g_parsedArc.health = $3;
-		  debug("H %d %d", $3, $4); }
-	  | ZTOK RETTOK { debug("Z"); }
-	  ;
+	| QTOK NUM NUM { debug("Q %d %d", $2, $3); }
+	| BNTOK FILENAME {
+		if (Common::String("B0") == $1)
+			g_parsedArc.intro = $2;
+		else if(Common::String("B1") == $1 || Common::String("B2") == $1)
+			g_parsedArc.winVideos.push_back($2);
+		else if(Common::String("B3") == $1 || Common::String("B4") == $1)
+			g_parsedArc.defeatVideos.push_back($2);
+
+		debug("BN %s", $2); 
+	}
+	| SNTOK FILENAME enc {
+		if (Common::String("S0") == $1)
+			g_parsedArc.music = $2;
+		else if (Common::String("S1") == $1)
+			g_parsedArc.shootSound = $2;
+		else if (Common::String("S4") == $1)
+			g_parsedArc.enemySound = $2; 
+
+		debug("SN %s", $2); 
+	}
+	| HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
+	| HTOK CB3TOK NUM NUM { 
+		g_parsedArc.health = $3;
+		debug("H %d %d", $3, $4); 
+	}
+	| ZTOK RETTOK { debug("Z"); }
+	;
 
 enc: ENCTOK
-   | /* nothing */
-   ;
+	| /* nothing */
+	;
 
 body: bline RETTOK body
-    | bline RETTOK XTOK
+	| bline RETTOK XTOK
 
 bline: FNTOK FILENAME { 
 		shoot = new Shoot();
 		shoot->animation = $2;
 		debug("FN %s", $2); 
-	 	}
-	 | FNTOK NONETOK { 
+	}
+	| FNTOK NONETOK { 
 		shoot = new Shoot();
 		shoot->animation = "NONE";
 		debug("FN NONE"); 
-	 	}
-	 | FTOK FILENAME { 
+	}
+	| FTOK FILENAME { 
 		shoot = new Shoot();
 		shoot->animation = $2;
 		debug("FN %s", $2); 
-	 	}
-     | ITOK  NAME  { 
-		 shoot->name = $2;
-		 debug("I %s", $2); 
-	   }
-     | ITOK  BNTOK  {  // Workaround for NAME == B1
-		 shoot->name = $2;
-		 debug("I %s", $2); 
-	   }
-	 | A0TOK NUM NUM { 
-		 shoot->position = Common::Point($2, $3);
-		 debug("A0 %d %d", $2, $3); 
-		}
-	 | RTOK NUM NUM  { debug("R %d %d", $2, $3); }
-	 | BNTOK NUM NUM { 
-
-		 debug("BN %d %d", $2, $3); }
-	 | K0TOK NUM NUM { 
-		 shoot->explosionFrame = $3;
-		 debug("K0 %d %d", $2, $3);
-		}
-	 | P0TOK NUM NUM {
-		debug("P0 %d %d", $2, $3); 
-	   }
-	 | OTOK NUM NUM { 
+	}
+	| ITOK  NAME  { 
+		shoot->name = $2;
+		debug("I %s", $2); 
+	}
+	| ITOK  BNTOK  {  // Workaround for NAME == B1
+		shoot->name = $2;
+		debug("I %s", $2); 
+	}
+	| A0TOK NUM NUM { 
+		shoot->position = Common::Point($2, $3);
+		debug("A0 %d %d", $2, $3); 
+	}
+	| RTOK NUM NUM  { debug("R %d %d", $2, $3); }
+	| BNTOK NUM NUM { debug("BN %d %d", $2, $3); }
+	| K0TOK NUM NUM { 
+		shoot->explosionFrame = $3;
+		debug("K0 %d %d", $2, $3);
+	}
+	| P0TOK NUM NUM { debug("P0 %d %d", $2, $3); }
+	| OTOK NUM NUM { 
 		debug("O %d %d", $2, $3); 
-	   }
-	 | CTOK NUM  { debug("C %d", $2); } 
-	 | HTOK NUM  { debug("H %d", $2); }
-	 | WTOK NUM  { debug("W %d", $2); }
-	 | DTOK NUM  { 
-		 shoot->damage = $2;
-		 debug("D %d", $2); 
-		}
-	 | SNTOK FILENAME enc { 
-		  if (Common::String("S1") == $1)
-		  	shoot->endSound = $2;
-		  //else if (Common::String("S2") == $1)
-		  //	shoot->startSound = $2;
+	}
+	| CTOK NUM  { debug("C %d", $2); } 
+	| HTOK NUM  { debug("H %d", $2); }
+	| WTOK NUM  { debug("W %d", $2); }
+	| DTOK NUM  { 
+		shoot->damage = $2;
+		debug("D %d", $2); 
+	}
+	| SNTOK FILENAME enc { 
+		if (Common::String("S1") == $1)
+			shoot->endSound = $2;
+		//else if (Common::String("S2") == $1)
+		//	shoot->startSound = $2;
 		 
-		 debug("SN %s", $2); }
-	 | NTOK { debug("N"); }
-	 | ZTOK {
+		debug("SN %s", $2); }
+	| NTOK { debug("N"); }
+	| ZTOK {
 		g_parsedArc.shoots.push_back(*shoot); 
 		//delete shoot; 
 		//shoot = nullptr;
-	    debug("Z"); 
-		}
-     ;
\ No newline at end of file
+		debug("Z"); 
+	}
+	;
\ No newline at end of file


Commit: 6c0b31e33ea05ff6ee4399740b9b85a459373329
    https://github.com/scummvm/scummvm/commit/6c0b31e33ea05ff6ee4399740b9b85a459373329
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed grammar_mis.y format and regenerated code

Changed paths:
    engines/hypno/grammar_mis.cpp
    engines/hypno/grammar_mis.y


diff --git a/engines/hypno/grammar_mis.cpp b/engines/hypno/grammar_mis.cpp
index b7f4d197e7..58ba4ccbbd 100644
--- a/engines/hypno/grammar_mis.cpp
+++ b/engines/hypno/grammar_mis.cpp
@@ -94,7 +94,7 @@ void HYPNO_MIS_xerror(const char *str) {
 }
 
 int HYPNO_MIS_wrap() {
-    return 1;
+	return 1;
 }
 
 using namespace Hypno;
@@ -513,11 +513,11 @@ static const yytype_uint8 yytranslate[] =
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    74,    74,    77,    80,    81,    82,    85,    88,   104,
-     113,   128,   134,   135,   145,   154,   163,   173,   181,   189,
-     197,   207,   215,   221,   229,   233,   236,   237,   241,   242,
-     248,   249,   255,   261,   267,   274,   281,   282,   285,   286,
-     289,   290,   293,   294
+       0,    74,    74,    77,    82,    83,    84,    87,    90,   105,
+     114,   129,   135,   136,   146,   155,   164,   174,   182,   190,
+     198,   208,   216,   222,   230,   236,   239,   240,   244,   245,
+     251,   252,   258,   264,   270,   277,   284,   285,   288,   289,
+     292,   293,   296,   297
 };
 #endif
 
@@ -1352,385 +1352,382 @@ yyreduce:
     {
         case 3:
 #line 77 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { smenu_idx.push_back(-1);
-	    stack.push_back(new Hotspots()); }
-#line 1358 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    { 
+	smenu_idx.push_back(-1);
+	stack.push_back(new Hotspots());
+}
+#line 1360 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 85 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 87 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("implicit END"); }
-#line 1364 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1366 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 88 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 90 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-	     Hotspot *hot = new Hotspot(); 
-		 hot->type = MakeMenu;
-		 hot->stype = (yyvsp[-1].s);
-		 hot->smenu = NULL;
-		 debug("MENU %d.", hot->type);
-		 Hotspots *cur = stack.back();
-		 cur->push_back(*hot);
-
-		 // We don't care about menus, only hotspots
-     	 int idx = smenu_idx.back();
-		 idx++;
-		 smenu_idx.pop_back();
-		 smenu_idx.push_back(idx);
-
-	  }
-#line 1385 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Hotspot *hot = new Hotspot(); 
+		hot->type = MakeMenu;
+		hot->stype = (yyvsp[-1].s);
+		hot->smenu = NULL;
+		debug("MENU %d.", hot->type);
+		Hotspots *cur = stack.back();
+		cur->push_back(*hot);
+
+		// We don't care about menus, only hotspots
+		int idx = smenu_idx.back();
+		idx++;
+		smenu_idx.pop_back();
+		smenu_idx.push_back(idx);
+	}
+#line 1386 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 104 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 105 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {  
-	     Hotspot *hot = new Hotspot(); 
-		 hot->type = MakeHotspot;
-		 hot->smenu = NULL;
-		 hot->rect = Common::Rect((yyvsp[-3].i), (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i));
-		 debug("HOTS %d.", hot->type);
-		 Hotspots *cur = stack.back();
-		 cur->push_back(*hot); 
-      }
-#line 1399 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Hotspot *hot = new Hotspot(); 
+		hot->type = MakeHotspot;
+		hot->smenu = NULL;
+		hot->rect = Common::Rect((yyvsp[-3].i), (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i));
+		debug("HOTS %d.", hot->type);
+		Hotspots *cur = stack.back();
+		cur->push_back(*hot); 
+	}
+#line 1400 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 113 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 114 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  // This should always point to a hotspot
-		  int idx = smenu_idx.back();
-		  idx++;
-		  smenu_idx.pop_back();
-		  smenu_idx.push_back(idx);
-
-		  Hotspots *cur = stack.back();
-		  Hotspot *hot = &(*cur)[idx];
-
-		  smenu_idx.push_back(-1);
-		  hot->smenu = new Hotspots();
-	      stack.push_back(hot->smenu);
-		  debug("SUBMENU"); 
-		}
-#line 1419 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		// This should always point to a hotspot
+		int idx = smenu_idx.back();
+		idx++;
+		smenu_idx.pop_back();
+		smenu_idx.push_back(idx);
+
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &(*cur)[idx];
+
+		smenu_idx.push_back(-1);
+		hot->smenu = new Hotspots();
+		stack.push_back(hot->smenu);
+		debug("SUBMENU"); 
+	}
+#line 1420 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 128 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 129 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-			Escape *a = new Escape();
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-		  	debug("ESC SUBMENU"); }
-#line 1430 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Escape *a = new Escape();
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("ESC SUBMENU"); }
+#line 1431 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 134 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 135 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("TIME %d", (yyvsp[0].i)); }
-#line 1436 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1437 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 135 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 136 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-			Background *a = new Background();
-			a->path = (yyvsp[-4].s);
-			a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-			a->condition = (yyvsp[-1].s);
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-			debug("BACK");
-		}
-#line 1451 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Background *a = new Background();
+		a->path = (yyvsp[-4].s);
+		a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+		a->condition = (yyvsp[-1].s);
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("BACK");
+	}
+#line 1452 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 145 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 146 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		    Global *a = new Global();
-			a->variable = (yyvsp[-1].s);
-			a->command = (yyvsp[0].s);
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-			debug("GLOB."); 
-		}
-#line 1465 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Global *a = new Global();
+		a->variable = (yyvsp[-1].s);
+		a->command = (yyvsp[0].s);
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("GLOB."); 
+	}
+#line 1466 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 154 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 155 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-			Ambient *a = new Ambient();
-			a->path = (yyvsp[-3].s);
-			a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
-			a->flag = (yyvsp[0].s);
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);			
-			debug("AMBI %d %d.", (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1479 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Ambient *a = new Ambient();
+		a->path = (yyvsp[-3].s);
+		a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+		a->flag = (yyvsp[0].s);
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);			
+		debug("AMBI %d %d.", (yyvsp[-2].i), (yyvsp[-1].i)); }
+#line 1480 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 163 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 164 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-			Play *a = new Play();
-			a->path = (yyvsp[-4].s);
-			a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-			a->condition = (yyvsp[-1].s);
-			a->flag = (yyvsp[0].s);
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);		  
-		    debug("PLAY %s.", (yyvsp[-4].s)); }
-#line 1494 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Play *a = new Play();
+		a->path = (yyvsp[-4].s);
+		a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+		a->condition = (yyvsp[-1].s);
+		a->flag = (yyvsp[0].s);
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);		  
+		debug("PLAY %s.", (yyvsp[-4].s)); }
+#line 1495 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 173 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 174 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  	Overlay *a = new Overlay();
-			a->path = (yyvsp[-3].s);
-			a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-	   }
-#line 1507 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Overlay *a = new Overlay();
+		a->path = (yyvsp[-3].s);
+		a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+	}
+#line 1508 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 181 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 182 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-			Palette *a = new Palette();
-			a->path = (yyvsp[0].s); 
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-			debug("PALE");
-		}
-#line 1520 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Palette *a = new Palette();
+		a->path = (yyvsp[0].s); 
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("PALE");
+	}
+#line 1521 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 189 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 190 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  	Cutscene *a = new Cutscene();
-			a->path = (yyvsp[0].s);
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);		  
-		    debug("CUTS %s.", (yyvsp[0].s)); 
-		}
-#line 1533 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Cutscene *a = new Cutscene();
+		a->path = (yyvsp[0].s);
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);		  
+		debug("CUTS %s.", (yyvsp[0].s)); 
+	}
+#line 1534 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 197 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 198 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-			WalN *a = new WalN();
-			a->path = (yyvsp[-4].s);
-			a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-			a->condition = (yyvsp[-1].s);
-			a->flag = (yyvsp[0].s);
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);		  
-		    debug("WALN %s %d %d.", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
-#line 1548 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		WalN *a = new WalN();
+		a->path = (yyvsp[-4].s);
+		a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+		a->condition = (yyvsp[-1].s);
+		a->flag = (yyvsp[0].s);
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);		  
+		debug("WALN %s %d %d.", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
+#line 1549 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 207 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 208 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-		  	Mice *a = new Mice();
-			a->path = (yyvsp[-1].s); 
-			a->index = (yyvsp[0].i)-1;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-	  }
-#line 1561 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Mice *a = new Mice();
+		a->path = (yyvsp[-1].s); 
+		a->index = (yyvsp[0].i)-1;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+	}
+#line 1562 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 215 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 216 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  Hotspots *cur = stack.back();
-		  Hotspot *hot = &cur->back();
-		  hot->actions.push_back(talk_action);
-		  talk_action = nullptr;
-		  debug("TALK"); }
-#line 1572 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(talk_action);
+		talk_action = nullptr;
+		debug("TALK"); }
+#line 1573 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 221 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 222 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  debug("explicit END");
-		  g_parsedHots = stack.back(); 
-		  stack.pop_back();
-		  smenu_idx.pop_back();
-		  }
-#line 1583 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		debug("explicit END");
+		g_parsedHots = stack.back(); 
+		stack.pop_back();
+		smenu_idx.pop_back();
+	}
+#line 1584 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 229 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { assert(talk_action == nullptr);
-	        talk_action = new Talk();
-		    talk_action->active = true; }
-#line 1591 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 230 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+	assert(talk_action == nullptr);
+	talk_action = new Talk();
+	talk_action->active = true; 
+}
+#line 1594 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 233 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 236 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-	      talk_action->active = false; 
-	      debug("inactive"); }
-#line 1599 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		talk_action->active = false; 
+		debug("inactive"); }
+#line 1602 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
-#line 236 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 239 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("inactive"); }
-#line 1605 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1608 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 237 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 240 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  talk_action->background = (yyvsp[-4].s);
-		  talk_action->position = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-		  debug("BACK in TALK"); }
-#line 1614 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		talk_action->background = (yyvsp[-4].s);
+		talk_action->position = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
+		debug("BACK in TALK"); }
+#line 1617 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 241 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("BOXX %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1620 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1623 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 242 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 245 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "G";
-		  talk_cmd.path = (yyvsp[-1].s)+2;
-		  talk_action->commands.push_back(talk_cmd); 
-	      debug("%s", (yyvsp[-1].s)); }
-#line 1631 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		TalkCommand talk_cmd;
+		talk_cmd.command = "G";
+		talk_cmd.path = (yyvsp[-1].s)+2;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("%s", (yyvsp[-1].s)); }
+#line 1634 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 248 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 251 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("%s", (yyvsp[-1].s)); }
-#line 1637 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1640 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 249 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 252 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "F";
-		  talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
-		  talk_action->commands.push_back(talk_cmd); 
-		  debug("%s", (yyvsp[-1].s)); }
-#line 1648 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		TalkCommand talk_cmd;
+		talk_cmd.command = "F";
+		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("%s", (yyvsp[-1].s)); }
+#line 1651 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 255 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 258 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "A";
-		  talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
-		  talk_action->commands.push_back(talk_cmd); 
-		  debug("|A%d", talk_cmd.num); }
-#line 1659 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		TalkCommand talk_cmd;
+		talk_cmd.command = "A";
+		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("|A%d", talk_cmd.num); }
+#line 1662 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 261 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 264 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "D";
-		  talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
-		  talk_action->commands.push_back(talk_cmd); 
-		  debug("%s", (yyvsp[-1].s)); }
-#line 1670 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		TalkCommand talk_cmd;
+		talk_cmd.command = "D";
+		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("%s", (yyvsp[-1].s)); }
+#line 1673 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 267 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 270 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "P";
-		  talk_cmd.path = (yyvsp[-3].s)+2;
-		  talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
-		  talk_action->commands.push_back(talk_cmd);
-		  debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1682 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		TalkCommand talk_cmd;
+		talk_cmd.command = "P";
+		talk_cmd.path = (yyvsp[-3].s)+2;
+		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+		talk_action->commands.push_back(talk_cmd);
+		debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
+#line 1685 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 274 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 277 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "I";
-		  talk_cmd.path = (yyvsp[-3].s)+2;
-		  talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
-		  talk_action->commands.push_back(talk_cmd);		  
-		  debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1694 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+		TalkCommand talk_cmd;
+		talk_cmd.command = "I";
+		talk_cmd.path = (yyvsp[-3].s)+2;
+		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+		talk_action->commands.push_back(talk_cmd);		  
+		debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
+#line 1697 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 281 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 284 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("|E"); }
-#line 1700 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
-    break;
-
-  case 37:
-#line 282 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debug("nothing in talk"); }
-#line 1706 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1703 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 289 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 292 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debug("flag: %s", (yyvsp[0].s)); }
-#line 1712 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1709 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 290 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 293 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1718 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1715 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 293 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 296 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debug("switch %s", (yyvsp[0].s)); }
-#line 1724 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1721 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 294 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 297 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1730 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1727 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1734 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1731 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_mis.y b/engines/hypno/grammar_mis.y
index 3a249656f1..b5161cf6eb 100644
--- a/engines/hypno/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -47,7 +47,7 @@ void HYPNO_MIS_xerror(const char *str) {
 }
 
 int HYPNO_MIS_wrap() {
-    return 1;
+	return 1;
 }
 
 using namespace Hypno;
@@ -72,224 +72,227 @@ using namespace Hypno;
 %%
 
 start: init lines 
-       ;
+	;
 
-init: { smenu_idx.push_back(-1);
-	    stack.push_back(new Hotspots()); }
+init: { 
+	smenu_idx.push_back(-1);
+	stack.push_back(new Hotspots());
+}
 
 lines:   line RETTOK lines
-       | line
-	   | end lines            
-	   ; 
+	| line
+	| end lines            
+	; 
 
 end: RETTOK  { debug("implicit END"); }
-    ; 
-
-line:    MENUTOK NAME mflag  {
-	     Hotspot *hot = new Hotspot(); 
-		 hot->type = MakeMenu;
-		 hot->stype = $2;
-		 hot->smenu = NULL;
-		 debug("MENU %d.", hot->type);
-		 Hotspots *cur = stack.back();
-		 cur->push_back(*hot);
+	; 
 
-		 // We don't care about menus, only hotspots
-     	 int idx = smenu_idx.back();
-		 idx++;
-		 smenu_idx.pop_back();
-		 smenu_idx.push_back(idx);
+line: MENUTOK NAME mflag  {
+		Hotspot *hot = new Hotspot(); 
+		hot->type = MakeMenu;
+		hot->stype = $2;
+		hot->smenu = NULL;
+		debug("MENU %d.", hot->type);
+		Hotspots *cur = stack.back();
+		cur->push_back(*hot);
 
-	  }
-      |	 HOTSTOK BBOXTOK NUM NUM NUM NUM  {  
-	     Hotspot *hot = new Hotspot(); 
-		 hot->type = MakeHotspot;
-		 hot->smenu = NULL;
-		 hot->rect = Common::Rect($3, $4, $5, $6);
-		 debug("HOTS %d.", hot->type);
-		 Hotspots *cur = stack.back();
-		 cur->push_back(*hot); 
-      }
-	  |  SMENTOK { 
-		  // This should always point to a hotspot
-		  int idx = smenu_idx.back();
-		  idx++;
-		  smenu_idx.pop_back();
-		  smenu_idx.push_back(idx);
+		// We don't care about menus, only hotspots
+		int idx = smenu_idx.back();
+		idx++;
+		smenu_idx.pop_back();
+		smenu_idx.push_back(idx);
+	}
+	| HOTSTOK BBOXTOK NUM NUM NUM NUM  {  
+		Hotspot *hot = new Hotspot(); 
+		hot->type = MakeHotspot;
+		hot->smenu = NULL;
+		hot->rect = Common::Rect($3, $4, $5, $6);
+		debug("HOTS %d.", hot->type);
+		Hotspots *cur = stack.back();
+		cur->push_back(*hot); 
+	}
+	|  SMENTOK { 
+		// This should always point to a hotspot
+		int idx = smenu_idx.back();
+		idx++;
+		smenu_idx.pop_back();
+		smenu_idx.push_back(idx);
 
-		  Hotspots *cur = stack.back();
-		  Hotspot *hot = &(*cur)[idx];
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &(*cur)[idx];
 
-		  smenu_idx.push_back(-1);
-		  hot->smenu = new Hotspots();
-	      stack.push_back(hot->smenu);
-		  debug("SUBMENU"); 
-		}
-      |  ESCPTOK  {
-			Escape *a = new Escape();
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-		  	debug("ESC SUBMENU"); }
-	  |  TIMETOK NUM  { debug("TIME %d", $2); } 
-      |  BACKTOK FILENAME NUM NUM gsswitch flag {
-			Background *a = new Background();
-			a->path = $2;
-			a->origin = Common::Point($3, $4);
-			a->condition = $5;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-			debug("BACK");
-		}
-      |  GLOBTOK GSSWITCH NAME  { 
-		    Global *a = new Global();
-			a->variable = $2;
-			a->command = $3;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-			debug("GLOB."); 
-		}
-		|  AMBITOK FILENAME NUM NUM flag { 
-			Ambient *a = new Ambient();
-			a->path = $2;
-			a->origin = Common::Point($3, $4);
-			a->flag = $5;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);			
-			debug("AMBI %d %d.", $3, $4); }
-	    |  PLAYTOK FILENAME NUM NUM gsswitch flag { 
-			Play *a = new Play();
-			a->path = $2;
-			a->origin = Common::Point($3, $4);
-			a->condition = $5;
-			a->flag = $6;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);		  
-		    debug("PLAY %s.", $2); }
-      |  OVERTOK FILENAME NUM NUM flag { 
-		  	Overlay *a = new Overlay();
-			a->path = $2;
-			a->origin = Common::Point($3, $4);
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-	   }
-	  |  PALETOK FILENAME {
-			Palette *a = new Palette();
-			a->path = $2; 
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-			debug("PALE");
-		}
-	  |  CUTSTOK FILENAME { 
-		  	Cutscene *a = new Cutscene();
-			a->path = $2;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);		  
-		    debug("CUTS %s.", $2); 
-		}
-	  |  WALNTOK FILENAME NUM NUM gsswitch flag  { 
-			WalN *a = new WalN();
-			a->path = $2;
-			a->origin = Common::Point($3, $4);
-			a->condition = $5;
-			a->flag = $6;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);		  
-		    debug("WALN %s %d %d.", $2, $3, $4); } 
-	  |  MICETOK FILENAME NUM {
-		  	Mice *a = new Mice();
-			a->path = $2; 
-			a->index = $3-1;
-			Hotspots *cur = stack.back();
-		    Hotspot *hot = &cur->back();
-			hot->actions.push_back(a);
-	  }
-	  |  TALKTOK alloctalk talk { 
-		  Hotspots *cur = stack.back();
-		  Hotspot *hot = &cur->back();
-		  hot->actions.push_back(talk_action);
-		  talk_action = nullptr;
-		  debug("TALK"); }
-	  |  ENDTOK RETTOK { 
-		  debug("explicit END");
-		  g_parsedHots = stack.back(); 
-		  stack.pop_back();
-		  smenu_idx.pop_back();
-		  }   		               
-	  ;
+		smenu_idx.push_back(-1);
+		hot->smenu = new Hotspots();
+		stack.push_back(hot->smenu);
+		debug("SUBMENU"); 
+	}
+	|  ESCPTOK  {
+		Escape *a = new Escape();
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("ESC SUBMENU"); }
+	|  TIMETOK NUM  { debug("TIME %d", $2); } 
+	|  BACKTOK FILENAME NUM NUM gsswitch flag {
+		Background *a = new Background();
+		a->path = $2;
+		a->origin = Common::Point($3, $4);
+		a->condition = $5;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("BACK");
+	}
+	|  GLOBTOK GSSWITCH NAME  { 
+		Global *a = new Global();
+		a->variable = $2;
+		a->command = $3;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("GLOB."); 
+	}
+	|  AMBITOK FILENAME NUM NUM flag { 
+		Ambient *a = new Ambient();
+		a->path = $2;
+		a->origin = Common::Point($3, $4);
+		a->flag = $5;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);			
+		debug("AMBI %d %d.", $3, $4); }
+	|  PLAYTOK FILENAME NUM NUM gsswitch flag { 
+		Play *a = new Play();
+		a->path = $2;
+		a->origin = Common::Point($3, $4);
+		a->condition = $5;
+		a->flag = $6;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);		  
+		debug("PLAY %s.", $2); }
+	|  OVERTOK FILENAME NUM NUM flag { 
+		Overlay *a = new Overlay();
+		a->path = $2;
+		a->origin = Common::Point($3, $4);
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+	}
+	|  PALETOK FILENAME {
+		Palette *a = new Palette();
+		a->path = $2; 
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+		debug("PALE");
+	}
+	|  CUTSTOK FILENAME { 
+		Cutscene *a = new Cutscene();
+		a->path = $2;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);		  
+		debug("CUTS %s.", $2); 
+	}
+	|  WALNTOK FILENAME NUM NUM gsswitch flag  { 
+		WalN *a = new WalN();
+		a->path = $2;
+		a->origin = Common::Point($3, $4);
+		a->condition = $5;
+		a->flag = $6;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);		  
+		debug("WALN %s %d %d.", $2, $3, $4); } 
+	|  MICETOK FILENAME NUM {
+		Mice *a = new Mice();
+		a->path = $2; 
+		a->index = $3-1;
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(a);
+	}
+	|  TALKTOK alloctalk talk { 
+		Hotspots *cur = stack.back();
+		Hotspot *hot = &cur->back();
+		hot->actions.push_back(talk_action);
+		talk_action = nullptr;
+		debug("TALK"); }
+	|  ENDTOK RETTOK { 
+		debug("explicit END");
+		g_parsedHots = stack.back(); 
+		stack.pop_back();
+		smenu_idx.pop_back();
+	}   		               
+	;
 
-alloctalk: { assert(talk_action == nullptr);
-	        talk_action = new Talk();
-		    talk_action->active = true; }
+alloctalk: { 
+	assert(talk_action == nullptr);
+	talk_action = new Talk();
+	talk_action->active = true; 
+}
 
-talk:   INACTOK talk {
-	      talk_action->active = false; 
-	      debug("inactive"); }
-      | FDTOK talk { debug("inactive"); }
-	  | BACKTOK FILENAME NUM NUM gsswitch flag { 
-		  talk_action->background = $2;
-		  talk_action->position = Common::Point($3, $4);
-		  debug("BACK in TALK"); }
-	  | BOXXTOK NUM NUM { debug("BOXX %d %d", $2, $3); }
-      | PG talk { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "G";
-		  talk_cmd.path = $1+2;
-		  talk_action->commands.push_back(talk_cmd); 
-	      debug("%s", $1); }
-      | PH talk { debug("%s", $1); }
-      | PF talk { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "F";
-		  talk_cmd.num = atoi($1+2)-1;
-		  talk_action->commands.push_back(talk_cmd); 
-		  debug("%s", $1); }
-      | PA talk { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "A";
-		  talk_cmd.num = atoi($1+2)-1;
-		  talk_action->commands.push_back(talk_cmd); 
-		  debug("|A%d", talk_cmd.num); } 
-      | PD talk { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "D";
-		  talk_cmd.num = atoi($1+2)-1;
-		  talk_action->commands.push_back(talk_cmd); 
-		  debug("%s", $1); }
-      | PP NUM NUM talk { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "P";
-		  talk_cmd.path = $1+2;
-		  talk_cmd.position = Common::Point($2, $3);
-		  talk_action->commands.push_back(talk_cmd);
-		  debug("%s %d %d", $1, $2, $3); }
-      | PI NUM NUM talk { 
-		  TalkCommand talk_cmd;
-		  talk_cmd.command = "I";
-		  talk_cmd.path = $1+2;
-		  talk_cmd.position = Common::Point($2, $3);
-		  talk_action->commands.push_back(talk_cmd);		  
-		  debug("%s %d %d", $1, $2, $3); }
-	  | PE { debug("|E"); }
-      | /*nothing*/ { debug("nothing in talk"); }
-	  ;
+talk: INACTOK talk {
+		talk_action->active = false; 
+		debug("inactive"); }
+	| FDTOK talk { debug("inactive"); }
+	| BACKTOK FILENAME NUM NUM gsswitch flag { 
+		talk_action->background = $2;
+		talk_action->position = Common::Point($3, $4);
+		debug("BACK in TALK"); }
+	| BOXXTOK NUM NUM { debug("BOXX %d %d", $2, $3); }
+	| PG talk { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "G";
+		talk_cmd.path = $1+2;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("%s", $1); }
+	| PH talk { debug("%s", $1); }
+	| PF talk { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "F";
+		talk_cmd.num = atoi($1+2)-1;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("%s", $1); }
+	| PA talk { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "A";
+		talk_cmd.num = atoi($1+2)-1;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("|A%d", talk_cmd.num); } 
+	| PD talk { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "D";
+		talk_cmd.num = atoi($1+2)-1;
+		talk_action->commands.push_back(talk_cmd); 
+		debug("%s", $1); }
+	| PP NUM NUM talk { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "P";
+		talk_cmd.path = $1+2;
+		talk_cmd.position = Common::Point($2, $3);
+		talk_action->commands.push_back(talk_cmd);
+		debug("%s %d %d", $1, $2, $3); }
+	| PI NUM NUM talk { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "I";
+		talk_cmd.path = $1+2;
+		talk_cmd.position = Common::Point($2, $3);
+		talk_action->commands.push_back(talk_cmd);		  
+		debug("%s %d %d", $1, $2, $3); }
+	| PE { debug("|E"); }
+	| /*nothing*/
+	;
 
 mflag:  NRTOK
-      | /*nothing*/
-	  ;
+	| /*nothing*/
+	;
 
-flag:   FLAG             { $$ = $1; debug("flag: %s", $1); }
-      | /* nothing */	 { $$ = scumm_strdup(""); }
-	  ;
+flag:   FLAG 		{ $$ = $1; debug("flag: %s", $1); }
+	| /* nothing */	{ $$ = scumm_strdup(""); }
+	;
 
-gsswitch:   GSSWITCH                      { $$ = $1; debug("switch %s", $1); }
-          | /* nothing */                 { $$ = scumm_strdup(""); }
-	      ;
\ No newline at end of file
+gsswitch: GSSWITCH 	{ $$ = $1; debug("switch %s", $1); }
+	| /* nothing */ { $$ = scumm_strdup(""); }
+	;
\ No newline at end of file


Commit: 4486f3692d985a8109dc934bc354632f6150439f
    https://github.com/scummvm/scummvm/commit/4486f3692d985a8109dc934bc354632f6150439f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed grammar_mis.y format and regenerated code

Changed paths:
    engines/hypno/grammar_mis.y


diff --git a/engines/hypno/grammar_mis.y b/engines/hypno/grammar_mis.y
index b5161cf6eb..878f3a48aa 100644
--- a/engines/hypno/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -81,7 +81,7 @@ init: {
 
 lines:   line RETTOK lines
 	| line
-	| end lines            
+	| end lines
 	; 
 
 end: RETTOK  { debug("implicit END"); }
@@ -224,7 +224,7 @@ line: MENUTOK NAME mflag  {
 		g_parsedHots = stack.back(); 
 		stack.pop_back();
 		smenu_idx.pop_back();
-	}   		               
+	}
 	;
 
 alloctalk: { 


Commit: 01fecf214cf20f35551db81e0b59d2be7c9fdcc8
    https://github.com/scummvm/scummvm/commit/01fecf214cf20f35551db81e0b59d2be7c9fdcc8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed modules.mk format

Changed paths:
    engines/hypno/module.mk


diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index 62af7a8a8f..41a4101840 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -1,7 +1,7 @@
 MODULE := engines/hypno
 
 MODULE_OBJS := \
-    libfile.o \
+	libfile.o \
 	cursors.o \
 	metaengine.o \
 	actions.o \


Commit: 13e94f868e3517af2d745ccc975c031d74541825
    https://github.com/scummvm/scummvm/commit/13e94f868e3517af2d745ccc975c031d74541825
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: preallocate elements in the afiles array

Changed paths:
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 5a314dd3ff..4ca9560d2e 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -35,6 +35,7 @@ void WetEngine::loadAssets() {
 
 	// We need the list of files in an array, instead of a list
 	Common::Array<Common::ArchiveMemberPtr> afiles;
+	afiles.reserve(files.size());
 	for (Common::ArchiveMemberList::const_iterator it = files.begin(); it != files.end(); ++it) {
 		afiles.push_back(*it);
 	}


Commit: 7ca44fa6070aa5dcb21d8b97330279565e5c2faf
    https://github.com/scummvm/scummvm/commit/7ca44fa6070aa5dcb21d8b97330279565e5c2faf
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed lexer_arc.l format and regenerated code

Changed paths:
    engines/hypno/lexer_arc.cpp
    engines/hypno/lexer_arc.l


diff --git a/engines/hypno/lexer_arc.cpp b/engines/hypno/lexer_arc.cpp
index 0e4dd0f8bd..013e5db95b 100644
--- a/engines/hypno/lexer_arc.cpp
+++ b/engines/hypno/lexer_arc.cpp
@@ -2272,3 +2272,4 @@ int parse_arc(const char *code) {
 
 } // End of namespace Hypno
 
+
diff --git a/engines/hypno/lexer_arc.l b/engines/hypno/lexer_arc.l
index 85389117e6..1885a5523a 100644
--- a/engines/hypno/lexer_arc.l
+++ b/engines/hypno/lexer_arc.l
@@ -41,22 +41,22 @@
 
 %%
 NONE						return NONETOK;
-C				    		return CTOK;
-D                           return DTOK;
-HE                          return HETOK;
-H                           return HTOK;
+C							return CTOK;
+D							return DTOK;
+HE							return HETOK;
+H							return HTOK;
 P							return PTOK;
 A							return ATOK;
 V							return VTOK;
-O 							return OTOK;
+O							return OTOK;
 O1							return O1TOK;
-N 							return NTOK;
-R 							return RTOK;
-I 							return ITOK;
+N							return NTOK;
+R							return RTOK;
+I							return ITOK;
 Q							return QTOK;
 Z							return ZTOK;
 W							return WTOK;
-X 							return XTOK;
+X							return XTOK;
 T							return TTOK;
 Tp							return TPTOK;
 F[0-9]						return FNTOK;
@@ -68,14 +68,14 @@ K0							return K0TOK;
 P0							return P0TOK;
 Y[A-Z0-9]					return YXTOK;
 22[k|K]						return ENCTOK;
-[A-Za-z_][A-Za-z_0-9]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
-[A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
-[\-]?[0-9]+		        	HYPNO_ARC_lval.i = atoi(HYPNO_ARC_text); return NUM;
+[A-Za-z_][A-Za-z_0-9]*		HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
+[A-Za-z][A-Za-z_0-9\\\.]*	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
+[\-]?[0-9]+					HYPNO_ARC_lval.i = atoi(HYPNO_ARC_text); return NUM;
 \n							return RETTOK;
-\xb3                        return CB3TOK;
-\x02                        return C02TOK;
-[ \t]+		            	/* ignore whitespace */;
-.				        	debug("notparsed: 0x%d",*yytext); return *yytext;
+\xb3						return CB3TOK;
+\x02						return C02TOK;
+[ \t]+						/* ignore whitespace */;
+.							debug("notparsed: 0x%d",*yytext); return *yytext;
 %%
 
 namespace Hypno {
@@ -91,3 +91,4 @@ int parse_arc(const char *code) {
 }
 
 } // End of namespace Hypno
+


Commit: 2fa66d32c29fe2bd82314a5020d54f88e2e1bb8e
    https://github.com/scummvm/scummvm/commit/2fa66d32c29fe2bd82314a5020d54f88e2e1bb8e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed lexer_mis.l format and regenerated code

Changed paths:
    engines/hypno/lexer_mis.l


diff --git a/engines/hypno/lexer_mis.l b/engines/hypno/lexer_mis.l
index e361143180..fcfb8fde88 100644
--- a/engines/hypno/lexer_mis.l
+++ b/engines/hypno/lexer_mis.l
@@ -40,21 +40,21 @@
 %}
 
 %%
-\;[A-Za-z_0-9 \t\*]*	    /* return COMMENT; */
-MENU				    	return MENUTOK;
+\;[A-Za-z_0-9 \t\*]*		/* return COMMENT; */
+MENU						return MENUTOK;
 AMBI						return AMBITOK;
-BACK                    	return BACKTOK;
-CUTS                    	return CUTSTOK;
+BACK						return BACKTOK;
+CUTS						return CUTSTOK;
 GLOB						return GLOBTOK;
 PALE						return PALETOK;
-HOTS                        return HOTSTOK;
-WAL[0-1]                    return WALNTOK;
-MICE                        return MICETOK;
-END                         return ENDTOK;
+HOTS						return HOTSTOK;
+WAL[0-1]					return WALNTOK;
+MICE						return MICETOK;
+END							return ENDTOK;
 TIME						return TIMETOK;
-OVER                        return OVERTOK;
-SMEN                        return SMENTOK;
-ESCP                        return ESCPTOK;
+OVER						return OVERTOK;
+SMEN						return SMENTOK;
+ESCP						return ESCPTOK;
 PLAY						return PLAYTOK;
 TALK						return TALKTOK;
 INACTIVE					return INACTOK;
@@ -68,16 +68,16 @@ BOXX						return BOXXTOK;
 \|D[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PD;
 \|F[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PF;
 \|E							return PE;
-NO_RETURN                   return NRTOK;
-GS_[A-Z_0-9]+           	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
+NO_RETURN					return NRTOK;
+GS_[A-Z_0-9]+				HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
 \/BBOX\=					return BBOXTOK;
-\/[A-Za-z_0-9]*  			HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FLAG;
-[A-Za-z_][A-Za-z_0-9]*  	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return NAME;
-[A-Za-z][A-Za-z_0-9\\\.]*  	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FILENAME;
-[\-]?[0-9]+		        	HYPNO_MIS_lval.i = atoi(HYPNO_MIS_text); return NUM;
+\/[A-Za-z_0-9]*				HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FLAG;
+[A-Za-z_][A-Za-z_0-9]*		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return NAME;
+[A-Za-z][A-Za-z_0-9\\\.]*	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FILENAME;
+[\-]?[0-9]+					HYPNO_MIS_lval.i = atoi(HYPNO_MIS_text); return NUM;
 \r\n						return RETTOK;
-[ \t]+		            	/* ignore whitespace */;
-.				        	debug("<no match>"); return *yytext;
+[ \t]+						/* ignore whitespace */;
+.							debug("<no match>"); return *yytext;
 %%
 
 namespace Hypno {


Commit: 266939c541b08584d0df1055c0eec6e58c8c7758
    https://github.com/scummvm/scummvm/commit/266939c541b08584d0df1055c0eec6e58c8c7758
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added missing new lines

Changed paths:
    engines/hypno/actions.cpp
    engines/hypno/arcade.cpp
    engines/hypno/cursors.cpp
    engines/hypno/detection.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar_arc.y
    engines/hypno/grammar_mis.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/libfile.cpp
    engines/hypno/libfile.h
    engines/hypno/metaengine.cpp
    engines/hypno/scene.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index bb6a13ae46..57cae17a4a 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -136,4 +136,5 @@ void HypnoEngine::runTalk(Talk *a) {
 	_refreshConversation = true;
 }
 
-} // namespace Hypno
\ No newline at end of file
+} // End of namespace Hypno
+
diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 884b19711c..e6857cb8a5 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -319,4 +319,5 @@ bool HypnoEngine::clickedSecondaryShoot(Common::Point mousePos) {
 	return false;
 }
 
-} // End of namespace Hypno
\ No newline at end of file
+} // End of namespace Hypno
+
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index bea49c81af..7d255de408 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -129,3 +129,4 @@ void HypnoEngine::changeCursor(const Common::String &cursor, uint32 n) {
 }
 
 } // End of namespace Hypno
+
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 908c4c4043..103f12cae1 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -117,3 +117,4 @@ public:
 };
 
 REGISTER_PLUGIN_STATIC(HYPNO_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, HypnoMetaEngineDetection);
+
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index f831ac157a..4cb78f39eb 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -257,3 +257,4 @@ extern ArcadeShooting g_parsedArc;
 } // End of namespace Hypno
 
 #endif
+
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index 7914372ae9..90bbdac47e 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -205,4 +205,5 @@ bline: FNTOK FILENAME {
 		//shoot = nullptr;
 		debug("Z"); 
 	}
-	;
\ No newline at end of file
+	;
+
diff --git a/engines/hypno/grammar_mis.y b/engines/hypno/grammar_mis.y
index 878f3a48aa..92fb87fd0d 100644
--- a/engines/hypno/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -295,4 +295,5 @@ flag:   FLAG 		{ $$ = $1; debug("flag: %s", $1); }
 
 gsswitch: GSSWITCH 	{ $$ = $1; debug("switch %s", $1); }
 	| /* nothing */ { $$ = scumm_strdup(""); }
-	;
\ No newline at end of file
+	;
+
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 0374743aa2..7412d0a634 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -441,3 +441,4 @@ void HypnoEngine::removeTimer() {
 }
 
 } // End of namespace Hypno
+
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index b0891c0a0a..0f498c15eb 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -268,3 +268,4 @@ public:
 } // End of namespace Hypno
 
 #endif
+
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 769163110c..f2a7524e4a 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -117,4 +117,5 @@ Common::SeekableReadStream *LibFile::createReadStreamForMember(const Common::Pat
 	return stream;
 }
 
-} // namespace Hypno
\ No newline at end of file
+} // namespace Hypno
+
diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
index b8e17af314..f312ae6ac5 100644
--- a/engines/hypno/libfile.h
+++ b/engines/hypno/libfile.h
@@ -59,4 +59,5 @@ private:
 
 } // End of namespace Hypno
 
-#endif
\ No newline at end of file
+#endif
+
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index 208bb8cf30..654bd23972 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -61,3 +61,4 @@ REGISTER_PLUGIN_DYNAMIC(HYPNO, PLUGIN_TYPE_ENGINE, HypnoMetaEngine);
 #else
 REGISTER_PLUGIN_STATIC(HYPNO, PLUGIN_TYPE_ENGINE, HypnoMetaEngine);
 #endif
+
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 4274393be0..9607605312 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -367,5 +367,5 @@ void HypnoEngine::showConversation() { error("Not implemented"); }
 void HypnoEngine::rightClickedConversation(Common::Point mousePos) { error("Not implemented"); }
 void HypnoEngine::leftClickedConversation(Common::Point mousePos) { error("Not implemented"); }
 
-
 } // End of namespace Hypno
+


Commit: 51aeec71bae08af7b70e3baf9a12854646e2498f
    https://github.com/scummvm/scummvm/commit/51aeec71bae08af7b70e3baf9a12854646e2498f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed usage of hoverHotspot

Changed paths:
    engines/hypno/scene.cpp


diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 9607605312..f828a67cfa 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -262,8 +262,7 @@ void HypnoEngine::runScene(Scene scene) {
 				if (stack.empty() || !_conversation.empty() || !_videosPlaying.empty())
 					break;
 
-				if (hoverHotspot(mousePos)) {
-				} else
+				if (!hoverHotspot(mousePos))
 					defaultCursor();
 				break;
 


Commit: 53f780d8a3b9562051b18d0c04ca4c2ef1d7a7f3
    https://github.com/scummvm/scummvm/commit/53f780d8a3b9562051b18d0c04ca4c2ef1d7a7f3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: allow to read the game data directly from the CD without installing

Changed paths:
    engines/hypno/detection.cpp
    engines/hypno/spider/spider.cpp


diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 103f12cae1..75904729aa 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -42,8 +42,8 @@ static const PlainGameDescriptor hypnoGames[] = {
 static const ADGameDescription gameDescriptions[] = {
 	{"sinister-six", // Demo from the US release
 	 "Demo",
-	 AD_ENTRY2s("COMBAT.EXE", "15a6b1b3819ef002438df340509b5373", 643471,
-				"SPIDER.EXE", "15a6b1b3819ef002438df340509b5373", 603587),
+	 AD_ENTRY2s("DATA.Z",  "2a9c7cf8920ec794482f0a5873102da5", 1285960,
+				"DCINE1.SMK", "1ff3db09d148e8dd8b56d2e87e7296b8", 493752),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
 	 ADGF_TESTING | ADGF_DEMO,
@@ -86,6 +86,7 @@ static const ADGameDescription gameDescriptions[] = {
 static const char *const directoryGlobs[] = {
 	"boyz",
 	"sixdemo",
+	"demo",
 	"factory",
 	"wetlands",
 	"movie",
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index b65c347603..6f046cf492 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -10,8 +10,11 @@ SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEn
 
 void SpiderEngine::loadAssets() {
 
-	LibFile *missions = loadLib("", "sixdemo/c_misc/missions.lib");
+	assert(_installerArchive.open("DATA.Z"));
+	SearchMan.add("DATA.Z", (Common::Archive *) &_installerArchive, 0, false);
+
 	Common::ArchiveMemberList files;
+	LibFile *missions = loadLib("", "sixdemo/c_misc/missions.lib");
 	assert(missions->listMembers(files) > 0);
 
 	// start level


Commit: ceaf573ecf76a1bf938a707e2a186eb47f630167
    https://github.com/scummvm/scummvm/commit/ceaf573ecf76a1bf938a707e2a186eb47f630167
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
COMMON: extended InstallShieldV3 support to read all the files in every subdirectory

Changed paths:
    common/installshieldv3_archive.cpp
    common/installshieldv3_archive.h


diff --git a/common/installshieldv3_archive.cpp b/common/installshieldv3_archive.cpp
index dc4f77c44c..f507882b62 100644
--- a/common/installshieldv3_archive.cpp
+++ b/common/installshieldv3_archive.cpp
@@ -53,10 +53,12 @@ bool InstallShieldV3::open(const Common::String &filename) {
 	// Let's pull some relevant data from the header
 	_stream->seek(41);
 	uint32 directoryTableOffset = _stream->readUint32LE();
-	/* uint32 directoryTableSize = */ _stream->readUint32LE();
+	/*uint32 directoryTableSize =*/ _stream->readUint32LE();
 	uint16 directoryCount = _stream->readUint16LE();
-	uint32 fileTableOffset = _stream->readUint32LE();
-	/* uint32 fileTableSize = */ _stream->readUint32LE();
+	/*uint32 fileTableOffset =*/ _stream->readUint32LE();
+	/*uint32 fileTableSize =*/ _stream->readUint32LE();
+	Common::Array<Common::String> dirNames;
+	Common::Array<int> dirSizes;
 
 	// We need to have at least one directory in order for the archive to be valid
 	if (directoryCount == 0) {
@@ -64,41 +66,53 @@ bool InstallShieldV3::open(const Common::String &filename) {
 		return false;
 	}
 
-	// TODO: Currently, we only support getting files from the first directory
-	// To that end, get the number of files from that entry
+	// Get the number of files from every directory
 	_stream->seek(directoryTableOffset);
-	uint16 fileCount = _stream->readUint16LE();
-	debug(2, "File count = %d", fileCount);
+	for (int i = 0; i < directoryCount; i++) {
+		uint16 fileCount = _stream->readUint16LE();
+		uint16 chunkSize = _stream->readUint16LE();
+
+		byte nameLength = _stream->readUint16LE();
+		Common::String name;
+		while (nameLength--)
+			name += _stream->readByte();
+
+		dirNames.push_back(name);
+		dirSizes.push_back(fileCount);
+		debug(2, "Directory = %s, file count = %d", name.c_str(), fileCount);
+		_stream->skip(chunkSize - name.size() - 6);
+	}
 
 	// Following the directory table is the file table with files stored recursively
-	// by directory. Since we're only using the first directory, we can just go
-	// right to that one.
-	_stream->seek(fileTableOffset);
+	// by directory
 
-	for (uint16 i = 0; i < fileCount; i++) {
-		FileEntry entry;
+	for (int i = 0; i < directoryCount; i++) {
+		for (int j = 0; j < dirSizes[i]; j++) {
+			FileEntry entry;
 
-		_stream->skip(3); // Unknown
+			_stream->skip(3); // Unknown
 
-		entry.uncompressedSize = _stream->readUint32LE();
-		entry.compressedSize = _stream->readUint32LE();
-		entry.offset = _stream->readUint32LE();
+			entry.uncompressedSize = _stream->readUint32LE();
+			entry.compressedSize = _stream->readUint32LE();
+			entry.offset = _stream->readUint32LE();
 
-		_stream->skip(14); // Unknown
+			_stream->skip(14); // Unknown
 
-		byte nameLength = _stream->readByte();
-		Common::String name;
-		while (nameLength--)
-			name += _stream->readByte();
+			byte nameLength = _stream->readByte();
+			Common::String name;
+			while (nameLength--)
+				name += _stream->readByte();
 
-		_stream->skip(13); // Unknown
+			_stream->skip(13); // Unknown
 
-		_map[name] = entry;
+			if (!dirNames[i].empty())
+				name = dirNames[i] + "\\" + name;
 
-		debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
-				entry.offset, entry.compressedSize, entry.uncompressedSize);
+			_map[name] = entry;
+			debug(3, "Found file '%s' at 0x%08x (Comp: 0x%08x, Uncomp: 0x%08x)", name.c_str(),
+					entry.offset, entry.compressedSize, entry.uncompressedSize);
+		}
 	}
-
 	return true;
 }
 
@@ -126,6 +140,10 @@ const Common::ArchiveMemberPtr InstallShieldV3::getMember(const Common::Path &pa
 
 Common::SeekableReadStream *InstallShieldV3::createReadStreamForMember(const Common::Path &path) const {
 	Common::String name = path.toString();
+	// Make sure "/" is converted to "\"
+	while (name.contains("/"))
+		Common::replace(name, "/", "\\");
+
 	if (!_stream || !_map.contains(name))
 		return nullptr;
 
diff --git a/common/installshieldv3_archive.h b/common/installshieldv3_archive.h
index ca0183b787..e9cbba482a 100644
--- a/common/installshieldv3_archive.h
+++ b/common/installshieldv3_archive.h
@@ -59,6 +59,8 @@ private:
 
 	typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
 	FileMap _map;
+
+	Common::String convertPath(const Common::String &name);
 };
 
 } // End of namespace Common


Commit: c608f28f05f976685bfad3b9f30bc8e906d138e2
    https://github.com/scummvm/scummvm/commit/c608f28f05f976685bfad3b9f30bc8e906d138e2
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
COMMON: removed convertPath

Changed paths:
    common/installshieldv3_archive.h


diff --git a/common/installshieldv3_archive.h b/common/installshieldv3_archive.h
index e9cbba482a..ca0183b787 100644
--- a/common/installshieldv3_archive.h
+++ b/common/installshieldv3_archive.h
@@ -59,8 +59,6 @@ private:
 
 	typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
 	FileMap _map;
-
-	Common::String convertPath(const Common::String &name);
 };
 
 } // End of namespace Common


Commit: c510c683b076cdb111c9e9c4f1dc671267aa991b
    https://github.com/scummvm/scummvm/commit/c510c683b076cdb111c9e9c4f1dc671267aa991b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: use references to pass arguments and some minor fixes

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/scene.cpp
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/talk.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index e6857cb8a5..34eee35cac 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -31,7 +31,7 @@ namespace Hypno {
 
 extern int parse_arc(const char *);
 
-void HypnoEngine::parseArcadeShooting(Common::String prefix, Common::String filename, Common::String data) {
+void HypnoEngine::parseArcadeShooting(const Common::String &prefix, const Common::String &filename, const Common::String &data) {
 	debugC(1, kHypnoDebugParser, "Parsing %s%s", prefix.c_str(), filename.c_str());
 	parse_arc(data.c_str());
 	Level level;
@@ -43,7 +43,7 @@ void HypnoEngine::parseArcadeShooting(Common::String prefix, Common::String file
 	g_parsedArc.shoots.clear();
 }
 
-ShootSequence HypnoEngine::parseShootList(Common::String filename, Common::String data) {
+ShootSequence HypnoEngine::parseShootList(const Common::String &filename, const Common::String &data) {
 	debugC(1, kHypnoDebugParser, "Parsing %s", filename.c_str());
 	Common::StringTokenizer tok(data, " ,\t");
 	Common::String t;
@@ -68,9 +68,9 @@ ShootSequence HypnoEngine::parseShootList(Common::String filename, Common::Strin
 	return seq;
 }
 
-void HypnoEngine::drawPlayer() { error("not implemented"); }
-void HypnoEngine::drawHealth() { error("not implemented"); }
-void HypnoEngine::drawShoot(Common::Point target) { error("not implemented"); }
+void HypnoEngine::drawPlayer() { error("Not implemented"); }
+void HypnoEngine::drawHealth() { error("Not implemented"); }
+void HypnoEngine::drawShoot(const Common::Point &target) { error("Not implemented"); }
 
 void HypnoEngine::hitPlayer() {
 	// if the player is hit, play the hit animation
@@ -78,7 +78,7 @@ void HypnoEngine::hitPlayer() {
 		_playerFrameIdx = _playerFrameSep;
 }
 
-void HypnoEngine::runArcade(ArcadeShooting arc) {
+void HypnoEngine::runArcade(ArcadeShooting &arc) {
 
 	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
 	Common::Event event;
@@ -266,7 +266,7 @@ void HypnoEngine::runArcade(ArcadeShooting arc) {
 
 }
 
-int HypnoEngine::detectTarget(Common::Point mousePos) {
+int HypnoEngine::detectTarget(const Common::Point &mousePos) {
 	int i = -1;
 	int x = 0;
 	int y = 0;
@@ -288,7 +288,7 @@ int HypnoEngine::detectTarget(Common::Point mousePos) {
 	return -1;
 }
 
-void HypnoEngine::drawCursorArcade(Common::Point mousePos) {
+void HypnoEngine::drawCursorArcade(const Common::Point &mousePos) {
 	int i = detectTarget(mousePos);
 	if (i >= 0)
 		changeCursor("target");
@@ -298,9 +298,9 @@ void HypnoEngine::drawCursorArcade(Common::Point mousePos) {
 	g_system->copyRectToScreen(_compositeSurface->getPixels(), _compositeSurface->pitch, 0, 0, _screenW, _screenH);
 }
 
-bool HypnoEngine::clickedPrimaryShoot(Common::Point mousePos) { return true; };
+bool HypnoEngine::clickedPrimaryShoot(const Common::Point &mousePos) { return true; }
 
-void HypnoEngine::shoot(Common::Point mousePos) {
+void HypnoEngine::shoot(const Common::Point &mousePos) {
 	int i = detectTarget(mousePos);
 	int w = 0;
 	int h = 0;
@@ -315,7 +315,7 @@ void HypnoEngine::shoot(Common::Point mousePos) {
 	}
 }
 
-bool HypnoEngine::clickedSecondaryShoot(Common::Point mousePos) {
+bool HypnoEngine::clickedSecondaryShoot(const Common::Point &mousePos) {
 	return false;
 }
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 7412d0a634..5a4bc80558 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -95,7 +95,7 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
 }
 
-LibFile *HypnoEngine::loadLib(Filename prefix, Filename filename) {
+LibFile *HypnoEngine::loadLib(const Filename &prefix, const Filename &filename) {
 	LibFile *lib = new LibFile();
 	SearchMan.add(filename, (Common::Archive *)lib, 0, true);
 	assert(lib->open(prefix, filename));
@@ -142,7 +142,7 @@ Common::Error HypnoEngine::run() {
 	return Common::kNoError;
 }
 
-void HypnoEngine::runLevel(Common::String name) {
+void HypnoEngine::runLevel(Common::String &name) {
 	assert(_levels.contains(name));
 	stopSound();
 	_music = "";
@@ -219,7 +219,7 @@ void HypnoEngine::runIntro(MVideo &video) {
 
 void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Not implemented"); }
 
-void HypnoEngine::showCredits() { error("credits"); /* Nothing */ };
+void HypnoEngine::showCredits() { error("Not implemented"); }
 
 void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
 	debugC(1, kHypnoDebugMedia, "%s(%s, %d, %d, %d)", __FUNCTION__, name.c_str(), x, y, transparent);
@@ -280,7 +280,7 @@ Frames HypnoEngine::decodeFrames(const Common::String &name) {
 	const Graphics::Surface *frame = nullptr;
 	Graphics::Surface *rframe = nullptr;
 
-	for (int f = 0; f < vd.getFrameCount(); f++) {
+	while (!vd.endOfVideo()) {
 		frame = vd.decodeNextFrame();
 		rframe = frame->convertTo(_pixelFormat, vd.getPalette());
 		frames.push_back(rframe);
@@ -288,7 +288,7 @@ Frames HypnoEngine::decodeFrames(const Common::String &name) {
 	return frames;
 }
 
-void HypnoEngine::changeScreenMode(Common::String mode) {
+void HypnoEngine::changeScreenMode(const Common::String &mode) {
 	debugC(1, kHypnoDebugMedia, "%s(%s)", __FUNCTION__, mode.c_str());
 	if (mode == "scene") {
 		_screenW = 640;
@@ -387,9 +387,9 @@ void HypnoEngine::skipVideo(MVideo &video) {
 
 // Sound handling
 
-void HypnoEngine::playSound(Common::String name, uint32 loops) {
-	debugC(1, kHypnoDebugMedia, "%s(%s, %d)", __FUNCTION__, name.c_str(), loops);
-	name = convertPath(name);
+void HypnoEngine::playSound(const Common::String &filename, uint32 loops) {
+	debugC(1, kHypnoDebugMedia, "%s(%s, %d)", __FUNCTION__, filename.c_str(), loops);
+	Common::String name = convertPath(filename);
 	if (!_prefixDir.empty())
 		name = _prefixDir + "/" + name;
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 0f498c15eb..d1ba9ef839 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -57,13 +57,6 @@ enum {
 	kHypnoDebugScene = 1 << 3,
 };
 
-typedef Common::Array<byte> ByteArray;
-typedef struct FileData {
-	Common::String name;
-	ByteArray data;
-} FileData;
-
-typedef Common::Array<FileData> LibData;
 typedef Common::Array<Graphics::Surface *> Frames;
 
 class HypnoEngine : public Engine {
@@ -89,19 +82,18 @@ public:
 	Common::HashMap<Common::String, int> _sceneState;
 	void resetSceneState();
 	bool checkSceneCompleted();
-	void runLevel(Common::String name);
-	void runScene(Scene scene);
-	void runArcade(ArcadeShooting arc);
+	void runLevel(Common::String &name);
+	void runScene(Scene &scene);
+	void runArcade(ArcadeShooting &arc);
 
 	void restartGame();
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
 	virtual void loadAssets();
-	void parseScene(Common::String prefix, Common::String filename);
-	void parseArcadeShooting(Common::String prefix, Common::String name, Common::String data);
-	ShootSequence parseShootList(Common::String name, Common::String data);
-	void loadLib(Common::String filename, LibData &r);
-	LibFile *loadLib(Filename prefix, Filename filename);
+	void parseScene(const Common::String &prefix, const Common::String &filename);
+	void parseArcadeShooting(const Common::String &prefix, const Common::String &name, const Common::String &data);
+	ShootSequence parseShootList(const Common::String &name, const Common::String &data);
+	LibFile *loadLib(const Filename &prefix, const Filename &filename);
 
 	// User input
 	void clickedHotspot(Common::Point);
@@ -112,7 +104,6 @@ public:
 	bool cursorExit(Common::Point);
 	bool cursorMask(Common::Point);
 
-	//bool hasFeature(EngineFeature f) const override;
 	bool canLoadGameStateCurrently() override { return false; }
 	bool canSaveAutosaveCurrently() override { return false; }
 	bool canSaveGameStateCurrently() override { return false; }
@@ -155,7 +146,7 @@ public:
 	// Screen
 	int _screenW, _screenH;
 	Graphics::PixelFormat _pixelFormat;
-	void changeScreenMode(Common::String mode);
+	void changeScreenMode(const Common::String &mode);
 	Graphics::ManagedSurface *_compositeSurface;
 	uint32 _transparentColor;
 	Common::Rect screenRect;
@@ -183,20 +174,20 @@ public:
 	// Sounds
 	Filename _soundPath;
 	Filename _music;
-	void playSound(Filename name, uint32);
+	void playSound(const Filename &filename, uint32);
 	void stopSound();
 	bool isSoundActive();
 	bool _noStopSounds;
 
 	// Arcade
-	int detectTarget(Common::Point mousePos);
-	virtual bool clickedPrimaryShoot(Common::Point);
-	virtual bool clickedSecondaryShoot(Common::Point);
-	virtual void drawShoot(Common::Point);
-	virtual void shoot(Common::Point);
+	int detectTarget(const Common::Point &mousePos);
+	virtual bool clickedPrimaryShoot(const Common::Point &mousePos);
+	virtual bool clickedSecondaryShoot(const Common::Point &mousePos);
+	virtual void drawShoot(const Common::Point &mousePos);
+	virtual void shoot(const Common::Point &mousePos);
 	virtual void hitPlayer();
 
-	void drawCursorArcade(Common::Point mousePos);
+	void drawCursorArcade(const Common::Point &mousePos);
 	virtual void drawPlayer();
 	virtual void drawHealth();
 	int _health;
@@ -213,8 +204,8 @@ public:
 	Actions _conversation;
 	bool _refreshConversation;
 	virtual void showConversation();
-	virtual void rightClickedConversation(Common::Point mousePos);
-	virtual void leftClickedConversation(Common::Point mousePos);
+	virtual void rightClickedConversation(const Common::Point &mousePos);
+	virtual void leftClickedConversation(const Common::Point &mousePos);
 
 	// Hardcoded puzzles
 	virtual void runPuzzle(Puzzle puzzle);
@@ -236,8 +227,8 @@ public:
 
 	void loadAssets() override;
 	void showCredits() override;
-	bool clickedSecondaryShoot(Common::Point) override;
-	void drawShoot(Common::Point) override;
+	bool clickedSecondaryShoot(const Common::Point &mousePos) override;
+	void drawShoot(const Common::Point &target) override;
 	void drawPlayer() override;
 	void drawHealth() override;
 };
@@ -246,14 +237,14 @@ class SpiderEngine : public HypnoEngine {
 public:
 	SpiderEngine(OSystem *syst, const ADGameDescription *gd);
 	void loadAssets() override;
-	void drawShoot(Common::Point) override;
+	void drawShoot(const Common::Point &target) override;
 	void drawPlayer() override;
 	void drawHealth() override;
 	void runPuzzle(Puzzle puzzle) override;
 
 	void showConversation() override;
-	void rightClickedConversation(Common::Point mousePos) override;
-	void leftClickedConversation(Common::Point mousePos) override;
+	void rightClickedConversation(const Common::Point &mousePos) override;
+	void leftClickedConversation(const Common::Point &mousePos) override;
 
 private:
 	void runMatrix(Puzzle puzzle);
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index f828a67cfa..b1bd7f5653 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -59,13 +59,13 @@ const static char *sceneVariables[] = {
 	"GS_PUZZLELEVEL",
 	NULL};
 
-void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
+void HypnoEngine::parseScene(const Common::String &prefix, const Common::String &filename) {
 	debugC(1, kHypnoDebugParser, "Parsing %s", filename.c_str());
-	filename = convertPath(filename);
+	Common::String name = convertPath(filename);
 	if (!prefix.empty())
-		filename = prefix + "/" + filename;
+		name = prefix + "/" + name;
 	Common::File test;
-	assert(test.open(filename.c_str()));
+	assert(test.open(name.c_str()));
 
 	const uint32 fileSize = test.size();
 	char *buf = (char *)malloc(fileSize + 1);
@@ -76,7 +76,7 @@ void HypnoEngine::parseScene(Common::String prefix, Common::String filename) {
 	Level level;
 	level.scene.prefix = prefix;
 	level.scene.hots = *g_parsedHots;
-	_levels[filename] = level;
+	_levels[name] = level;
 	free(buf);
 }
 
@@ -197,7 +197,7 @@ void HypnoEngine::runTransition(Transition trans) {
 }
 
 
-void HypnoEngine::runScene(Scene scene) {
+void HypnoEngine::runScene(Scene &scene) {
 	_refreshConversation = false;
 	_conversation.clear();
 	Common::Event event;
@@ -363,8 +363,8 @@ void HypnoEngine::runScene(Scene scene) {
 }
 
 void HypnoEngine::showConversation() { error("Not implemented"); }
-void HypnoEngine::rightClickedConversation(Common::Point mousePos) { error("Not implemented"); }
-void HypnoEngine::leftClickedConversation(Common::Point mousePos) { error("Not implemented"); }
+void HypnoEngine::rightClickedConversation(const Common::Point &mousePos) { error("Not implemented"); }
+void HypnoEngine::leftClickedConversation(const Common::Point &mousePos) { error("Not implemented"); }
 
 } // End of namespace Hypno
 
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 43e43c50d9..5bd902ea2d 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -34,7 +34,7 @@ static const int orientationIndex[9] = {0, 1, 2, 7, 8, 3, 6, 5, 4};
 static const int shootOriginIndex[9][2] = {
 	{41, 3}, {51, 3}, {65, 6}, {68, 9}, {71, 22}, {57, 20}, {37, 14}, {37, 11}, {57, 20}};
 
-void SpiderEngine::drawShoot(Common::Point target) {
+void SpiderEngine::drawShoot(const Common::Point &target) {
 	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
 	uint32 idx = std::min(2, target.x / (_screenW / 3)) + 3 * std::min(2, target.y / (_screenH / 3));
 	uint32 ox = 60  + shootOriginIndex[idx][0];
diff --git a/engines/hypno/spider/talk.cpp b/engines/hypno/spider/talk.cpp
index 1d0075e626..42ed9fe626 100644
--- a/engines/hypno/spider/talk.cpp
+++ b/engines/hypno/spider/talk.cpp
@@ -38,7 +38,7 @@ void SpiderEngine::showConversation() {
 	delete speaker;
 }
 
-void SpiderEngine::leftClickedConversation(Common::Point mousePos) {
+void SpiderEngine::leftClickedConversation(const Common::Point &mousePos) {
 	Talk *t;
 	bool activeFound = false;
 	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
@@ -74,7 +74,7 @@ void SpiderEngine::leftClickedConversation(Common::Point mousePos) {
 	}
 }
 
-void SpiderEngine::rightClickedConversation(Common::Point mousePos) {
+void SpiderEngine::rightClickedConversation(const Common::Point &mousePos) {
 	for (Actions::const_iterator itt = _conversation.begin(); itt != _conversation.end(); ++itt) {
 		Talk *a = (Talk *)*itt;
 		if (a->active && a->rect.contains(mousePos)) {
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index d0f7fd654f..d2bc4800b4 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -6,11 +6,11 @@
 
 namespace Hypno {
 
-bool WetEngine::clickedSecondaryShoot(Common::Point mousePos) {
+bool WetEngine::clickedSecondaryShoot(const Common::Point &mousePos) {
 	return clickedPrimaryShoot(mousePos);
 }
 
-void WetEngine::drawShoot(Common::Point mousePos) {
+void WetEngine::drawShoot(const Common::Point &mousePos) {
 	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	_compositeSurface->drawLine(0, _screenH, mousePos.x, mousePos.y, c);
 	_compositeSurface->drawLine(0, _screenH, mousePos.x - 1, mousePos.y, c);
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 4ca9560d2e..5182269451 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -27,8 +27,6 @@ namespace Hypno {
 WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void WetEngine::loadAssets() {
-	//LibData files;
-	//loadLib("wetlands/c_misc/missions.lib", files);
 	LibFile *missions = loadLib("", "wetlands/c_misc/missions.lib");
 	Common::ArchiveMemberList files;
 	assert(missions->listMembers(files) > 0);


Commit: 7fd92f3a222f174a537324ea746da4082f98797d
    https://github.com/scummvm/scummvm/commit/7fd92f3a222f174a537324ea746da4082f98797d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added missing newline

Changed paths:
    engines/hypno/boyz/boyz.cpp


diff --git a/engines/hypno/boyz/boyz.cpp b/engines/hypno/boyz/boyz.cpp
index 3aca3a9b0b..3336edd8bf 100644
--- a/engines/hypno/boyz/boyz.cpp
+++ b/engines/hypno/boyz/boyz.cpp
@@ -11,4 +11,4 @@ void BoyzEngine::loadAssets() {
 	loadLib("", "boyz/preload/missions.lib");
 }
 
-} // namespace Hypno
\ No newline at end of file
+} // namespace Hypno


Commit: 267ba8d113b17dee8983041a06cb2ba51472794b
    https://github.com/scummvm/scummvm/commit/267ba8d113b17dee8983041a06cb2ba51472794b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: enabled health tracking

Changed paths:
    engines/hypno/arcade.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 34eee35cac..1f718f1e1f 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -228,7 +228,7 @@ void HypnoEngine::runArcade(ArcadeShooting &arc) {
 
 				if (frame > 0 && frame >= it->explosionFrame - 3 && !it->destroyed) {
 					skipVideo(*it->video);
-					//_health = _health - it->damage;
+					_health = _health - it->damage;
 				} else if (frame > 0 && frame >= it->video->decoder->getFrameCount()-2) {
 					skipVideo(*it->video);
 					shootsToRemove.push_back(i);


Commit: da95a4ba2e13d0e8018061fe3517b154fc7c43ef
    https://github.com/scummvm/scummvm/commit/da95a4ba2e13d0e8018061fe3517b154fc7c43ef
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed a race condition in the usage of the timer callback

Changed paths:
    engines/hypno/hypno.cpp
    engines/hypno/scene.cpp


diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 5a4bc80558..231e77c927 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -143,7 +143,8 @@ Common::Error HypnoEngine::run() {
 }
 
 void HypnoEngine::runLevel(Common::String &name) {
-	assert(_levels.contains(name));
+	if (!_levels.contains(name))
+		error("Level %s cannot be found", name.c_str());
 	stopSound();
 	_music = "";
 
@@ -429,7 +430,9 @@ Common::String HypnoEngine::convertPath(const Common::String &name) {
 // Timers
 static void timerCallback(void *refCon) {
 	g_hypno->removeTimer();
-	g_hypno->_nextLevel = *(Common::String *)refCon;
+	Common::String *level = (Common::String *)refCon;
+	g_hypno->_nextLevel = *level;
+	delete level;
 }
 
 bool HypnoEngine::installTimer(uint32 delay, Common::String *ns) {
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index b1bd7f5653..12aef052e8 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -191,7 +191,8 @@ void HypnoEngine::runTransition(Transition trans) {
 		delete frame;
 		sframe->free();
 		delete sframe;
-		assert(installTimer(2 * 1000000, &trans.level));
+		Common::String *ptr = new Common::String(trans.level);
+		assert(installTimer(2 * 1000000, ptr));
 	} else
 		_nextLevel = trans.level;
 }


Commit: 8100ee54a4bfeba38ac95c8abaaddd7cc312befc
    https://github.com/scummvm/scummvm/commit/8100ee54a4bfeba38ac95c8abaaddd7cc312befc
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed missing headers, removed C++isms and better errors among others

Changed paths:
    engines/hypno/actions.cpp
    engines/hypno/arcade.cpp
    engines/hypno/boyz/boyz.cpp
    engines/hypno/configure.engine
    engines/hypno/cursors.cpp
    engines/hypno/hypno.cpp
    engines/hypno/spider/talk.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index 57cae17a4a..71004dfeed 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -20,7 +20,6 @@
  *
  */
 
-#include <typeinfo>
 #include "common/events.h"
 
 #include "hypno/grammar.h"
@@ -58,13 +57,11 @@ void HypnoEngine::runMenu(Hotspots hs) {
 void HypnoEngine::runBackground(Background *a) {
 	if (a->condition.size() > 0 && !_sceneState[a->condition])
 		return;
-	Common::Point origin = a->origin;
-	loadImage(a->path, origin.x, origin.y, false);
+	loadImage(a->path, a->origin.x, a->origin.y, false);
 }
 
 void HypnoEngine::runOverlay(Overlay *a) {
-	Common::Point origin = a->origin;
-	loadImage(a->path, origin.x, origin.y, false);
+	loadImage(a->path, a->origin.x, a->origin.y, false);
 }
 
 void HypnoEngine::runMice(Mice *a) {
@@ -78,7 +75,7 @@ void HypnoEngine::runEscape(Escape *a) {
 void HypnoEngine::runCutscene(Cutscene *a) {
 	stopSound();
 	disableCursor();
-	_music = "";
+	_music.clear();
 	_nextSequentialVideoToPlay.push_back(MVideo(a->path, Common::Point(0, 0), false, true, false));
 }
 
@@ -94,19 +91,17 @@ void HypnoEngine::runGlobal(Global *a) {
 void HypnoEngine::runPlay(Play *a) {
 	if (a->condition.size() > 0 && !_sceneState[a->condition])
 		return;
-	Common::Point origin = a->origin;
 
 	if (a->flag == "/BITMAP")
-		loadImage(a->path, origin.x, origin.y, false);
+		loadImage(a->path, a->origin.x, a->origin.y, false);
 	else {
 		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
 	}
 }
 
 void HypnoEngine::runAmbient(Ambient *a) {
-	Common::Point origin = a->origin;
 	if (a->flag == "/BITMAP")
-		loadImage(a->path, origin.x, origin.y, false);
+		loadImage(a->path, a->origin.x, a->origin.y, false);
 	else {
 		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, a->fullscreen, a->flag == "/LOOP"));
 	}
@@ -115,9 +110,8 @@ void HypnoEngine::runAmbient(Ambient *a) {
 void HypnoEngine::runWalN(WalN *a) {
 	if (a->condition.size() > 0 && !_sceneState[a->condition])
 		return;
-	Common::Point origin = a->origin;
 	if (a->flag == "/BITMAP")
-		loadImage(a->path, origin.x, origin.y, false);
+		loadImage(a->path, a->origin.x, a->origin.y, false);
 	else {
 		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, false, false));
 	}
diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 1f718f1e1f..2403ad1161 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -68,9 +68,9 @@ ShootSequence HypnoEngine::parseShootList(const Common::String &filename, const
 	return seq;
 }
 
-void HypnoEngine::drawPlayer() { error("Not implemented"); }
-void HypnoEngine::drawHealth() { error("Not implemented"); }
-void HypnoEngine::drawShoot(const Common::Point &target) { error("Not implemented"); }
+void HypnoEngine::drawPlayer() { error("Function \"%s\" not implemented", __FUNCTION__); }
+void HypnoEngine::drawHealth() { error("Function \"%s\" not implemented", __FUNCTION__); }
+void HypnoEngine::drawShoot(const Common::Point &target) { error("Function \"%s\" not implemented", __FUNCTION__); }
 
 void HypnoEngine::hitPlayer() {
 	// if the player is hit, play the hit animation
diff --git a/engines/hypno/boyz/boyz.cpp b/engines/hypno/boyz/boyz.cpp
index 3336edd8bf..fab556967b 100644
--- a/engines/hypno/boyz/boyz.cpp
+++ b/engines/hypno/boyz/boyz.cpp
@@ -1,3 +1,25 @@
+/* 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 "hypno/grammar.h"
 #include "hypno/hypno.h"
 
diff --git a/engines/hypno/configure.engine b/engines/hypno/configure.engine
index 6428240265..d3ccb60d93 100644
--- a/engines/hypno/configure.engine
+++ b/engines/hypno/configure.engine
@@ -1,3 +1,3 @@
 # This file is included from the main "configure" script
 # add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine hypno "Hypnotix Inc." yes "" "" "highres 16bit"
+add_engine hypno "Hypnotix Inc." no "" "" "highres 16bit"
diff --git a/engines/hypno/cursors.cpp b/engines/hypno/cursors.cpp
index 7d255de408..debae0d330 100644
--- a/engines/hypno/cursors.cpp
+++ b/engines/hypno/cursors.cpp
@@ -45,7 +45,7 @@ static const byte MOUSECURSOR_SCI[] = {
 	0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
 	0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0};
 
-static const byte circleCursor[]{
+static const byte circleCursor[] = {
 	0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0,
 	0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0,
 	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,
@@ -58,7 +58,7 @@ static const byte circleCursor[]{
 	0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0,
 	0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0};
 
-static const byte targetCursor[]{
+static const byte targetCursor[] = {
 	0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
 	0, 0, 1, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 0, 0,
 	0, 1, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0,
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 231e77c927..a48af53e3b 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -103,7 +103,7 @@ LibFile *HypnoEngine::loadLib(const Filename &prefix, const Filename &filename)
 	return lib;
 }
 
-void HypnoEngine::loadAssets() { error("not implemented"); }
+void HypnoEngine::loadAssets() { error("Function \"%s\" not implemented", __FUNCTION__); }
 
 Common::Error HypnoEngine::run() {
 	_language = Common::parseLanguage(ConfMan.get("language"));
@@ -146,7 +146,7 @@ void HypnoEngine::runLevel(Common::String &name) {
 	if (!_levels.contains(name))
 		error("Level %s cannot be found", name.c_str());
 	stopSound();
-	_music = "";
+	_music.clear();
 
 	disableCursor();
 
@@ -218,9 +218,9 @@ void HypnoEngine::runIntro(MVideo &video) {
 	}
 }
 
-void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Not implemented"); }
+void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Function \"%s\" not implemented", __FUNCTION__); }
 
-void HypnoEngine::showCredits() { error("Not implemented"); }
+void HypnoEngine::showCredits() { error("Function \"%s\" not implemented", __FUNCTION__); }
 
 void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
 	debugC(1, kHypnoDebugMedia, "%s(%s, %d, %d, %d)", __FUNCTION__, name.c_str(), x, y, transparent);
diff --git a/engines/hypno/spider/talk.cpp b/engines/hypno/spider/talk.cpp
index 42ed9fe626..0b626e881c 100644
--- a/engines/hypno/spider/talk.cpp
+++ b/engines/hypno/spider/talk.cpp
@@ -1,3 +1,25 @@
+/* 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 "hypno/grammar.h"
 #include "hypno/hypno.h"
 


Commit: 2a45d0908e040a738c9aaf9958f7a2a6ef0faaed
    https://github.com/scummvm/scummvm/commit/2a45d0908e040a738c9aaf9958f7a2a6ef0faaed
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: readded typeinfo header

Changed paths:
    engines/hypno/actions.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index 71004dfeed..7dc301e0e2 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -20,6 +20,7 @@
  *
  */
 
+#include <typeinfo>
 #include "common/events.h"
 
 #include "hypno/grammar.h"


Commit: 0925d2b823665a5140fa898936e5230930b4b5e5
    https://github.com/scummvm/scummvm/commit/0925d2b823665a5140fa898936e5230930b4b5e5
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
COMMON: changed type of variable in the directory count loop

Changed paths:
    common/installshieldv3_archive.cpp


diff --git a/common/installshieldv3_archive.cpp b/common/installshieldv3_archive.cpp
index f507882b62..488ab1e3b0 100644
--- a/common/installshieldv3_archive.cpp
+++ b/common/installshieldv3_archive.cpp
@@ -68,7 +68,7 @@ bool InstallShieldV3::open(const Common::String &filename) {
 
 	// Get the number of files from every directory
 	_stream->seek(directoryTableOffset);
-	for (int i = 0; i < directoryCount; i++) {
+	for (uint32 i = 0; i < directoryCount; i++) {
 		uint16 fileCount = _stream->readUint16LE();
 		uint16 chunkSize = _stream->readUint16LE();
 


Commit: 35f970ae1eeda2d274d353adac4dc145d5921296
    https://github.com/scummvm/scummvm/commit/35f970ae1eeda2d274d353adac4dc145d5921296
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed missing headers, removed C++isms and reduced variable scopes among others

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/libfile.cpp
    engines/hypno/spider/talk.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 2403ad1161..ab27b2c691 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -268,18 +268,14 @@ void HypnoEngine::runArcade(ArcadeShooting &arc) {
 
 int HypnoEngine::detectTarget(const Common::Point &mousePos) {
 	int i = -1;
-	int x = 0;
-	int y = 0;
-	int w = 0;
-	int h = 0;
 	for (Shoots::iterator it = _shoots.begin(); it != _shoots.end(); ++it) {
 		i++;
 		if (it->destroyed || !it->video->decoder)
 			continue;
-		x = mousePos.x - it->position.x;
-		y = mousePos.y - it->position.y;
-		w = it->video->decoder->getWidth();
-		h = it->video->decoder->getHeight();
+		int x = mousePos.x - it->position.x;
+		int y = mousePos.y - it->position.y;
+		int w = it->video->decoder->getWidth();
+		int h = it->video->decoder->getHeight();
 		if (it->video->decoder && x >= 0 && y >= 0 && x < w && y < h) {
 			if (it->video->currentFrame->getPixel(x, y) > 0)
 				return i;
@@ -302,12 +298,10 @@ bool HypnoEngine::clickedPrimaryShoot(const Common::Point &mousePos) { return tr
 
 void HypnoEngine::shoot(const Common::Point &mousePos) {
 	int i = detectTarget(mousePos);
-	int w = 0;
-	int h = 0;
 	if (i >= 0) {
 		playSound(_soundPath + _shoots[i].endSound, 1);
-		w = _shoots[i].video->decoder->getWidth();
-		h = _shoots[i].video->decoder->getHeight();
+		int w = _shoots[i].video->decoder->getWidth();
+		int h = _shoots[i].video->decoder->getHeight();
 		_score++;
 		_shoots[i].destroyed = true;
 		_shoots[i].video->position = Common::Point(mousePos.x - w / 2, mousePos.y - h / 2);
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index a48af53e3b..005b79eb2e 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -219,7 +219,6 @@ void HypnoEngine::runIntro(MVideo &video) {
 }
 
 void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Function \"%s\" not implemented", __FUNCTION__); }
-
 void HypnoEngine::showCredits() { error("Function \"%s\" not implemented", __FUNCTION__); }
 
 void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index d1ba9ef839..518a0d7404 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -54,7 +54,7 @@ enum {
 	kHypnoDebugMedia = 1 << 0,
 	kHypnoDebugParser = 1 << 1,
 	kHypnoDebugArcade = 1 << 2,
-	kHypnoDebugScene = 1 << 3,
+	kHypnoDebugScene = 1 << 3
 };
 
 typedef Common::Array<Graphics::Surface *> Frames;
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index f2a7524e4a..45a9c7428b 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -35,32 +35,27 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename)
 	_prefix = prefix;
 	Common::File libfile;
 	assert(libfile.open(filename));
-	uint32 i = 0;
-	Common::String entry = "<>";
-	FileEntry f;
-	f.data.push_back(0);
 	byte b;
-	uint32 start;
 	uint32 size;
-	uint32 pos;
-
+	FileEntry f;
+	f.data.push_back(0);
 	do {
 		f.name = "";
 		f.data.clear();
-		for (i = 0; i < 12; i++) {
+		for (uint32 i = 0; i < 12; i++) {
 			b = libfile.readByte();
 			if (b != 0x96 && b != 0x0)
 				f.name += tolower(char(b));
 		}
 		debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
-		start = libfile.readUint32LE();
+		uint32 start = libfile.readUint32LE();
 		size = libfile.readUint32LE();
 		libfile.readUint32LE(); // some field?
 
-		pos = libfile.pos();
+		uint32 pos = libfile.pos();
 		libfile.seek(start);
 
-		for (i = 0; i < size; i++) {
+		for (uint32 i = 0; i < size; i++) {
 			b = libfile.readByte();
 			if (b != '\n')
 				b = b ^ 0xfe;
diff --git a/engines/hypno/spider/talk.cpp b/engines/hypno/spider/talk.cpp
index 0b626e881c..bc3eb09bd4 100644
--- a/engines/hypno/spider/talk.cpp
+++ b/engines/hypno/spider/talk.cpp
@@ -111,4 +111,4 @@ void SpiderEngine::rightClickedConversation(const Common::Point &mousePos) {
 	}
 }
 
-} // End of namespace Hypno
\ No newline at end of file
+} // End of namespace Hypno
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index d2bc4800b4..f31061f743 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -1,3 +1,25 @@
+/* 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 "hypno/grammar.h"
 #include "hypno/hypno.h"
 
@@ -71,4 +93,4 @@ void WetEngine::drawHealth() {
 	}
 }
 
-} // End of namespace Hypno
\ No newline at end of file
+} // End of namespace Hypno
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 5182269451..dc60656670 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -87,7 +87,6 @@ void WetEngine::loadAssets() {
 	intro.trans.frameNumber = 0;
 	_levels["<intro>"] = intro;
 
-	byte x;
 	for (k = 0; k < afiles.size(); k++) {
 		arc.clear();
 		list.clear();
@@ -95,7 +94,7 @@ void WetEngine::loadAssets() {
 		debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
 		Common::SeekableReadStream *file = afiles[k]->createReadStream();
 		while (!file->eos()) {
-			x = file->readByte();
+			byte x = file->readByte();
 			arc += x;
 			if (x == 'X') {
 				while (!file->eos()) {


Commit: 754afa4e7b86e680c0e0c8824cf9644d99dbcfe6
    https://github.com/scummvm/scummvm/commit/754afa4e7b86e680c0e0c8824cf9644d99dbcfe6
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: replaced asserts with better code

Changed paths:
    engines/hypno/hypno.cpp
    engines/hypno/libfile.cpp
    engines/hypno/metaengine.cpp
    engines/hypno/scene.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 005b79eb2e..ef590138ae 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -98,7 +98,8 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 LibFile *HypnoEngine::loadLib(const Filename &prefix, const Filename &filename) {
 	LibFile *lib = new LibFile();
 	SearchMan.add(filename, (Common::Archive *)lib, 0, true);
-	assert(lib->open(prefix, filename));
+	if (!lib->open(prefix, filename))
+		error("Failed to open %s%s", prefix.c_str(), filename.c_str());
 	_archive.push_back(lib);
 	return lib;
 }
@@ -120,7 +121,6 @@ Common::Error HypnoEngine::run() {
 	if (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8())
 		return Common::kUnsupportedColorMode;
 
-	assert(_compositeSurface == nullptr);
 	_compositeSurface = new Graphics::ManagedSurface();
 	_compositeSurface->create(_screenW, _screenH, _pixelFormat);
 
@@ -368,7 +368,9 @@ void HypnoEngine::playVideo(MVideo &video) {
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
 
-	assert(video.decoder == nullptr);
+	if (video.decoder != nullptr)
+		error("Video %s was not previously closed and deallocated", video.path.c_str());
+
 	video.decoder = new Video::SmackerDecoder();
 
 	if (!video.decoder->loadStream(file))
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 45a9c7428b..57239f2e95 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -34,7 +34,8 @@ LibFile::~LibFile() {
 bool LibFile::open(const Common::String &prefix, const Common::String &filename) {
 	_prefix = prefix;
 	Common::File libfile;
-	assert(libfile.open(filename));
+	if (!libfile.open(filename))
+		error("Failed to open %s", filename.c_str());
 	byte b;
 	uint32 size;
 	FileEntry f;
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index 654bd23972..1a8d58f115 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -21,7 +21,6 @@
  */
 
 #include "engines/advancedDetector.h"
-#include "graphics/scaler.h"
 
 #include "hypno/hypno.h"
 
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 12aef052e8..165f214e9b 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -65,7 +65,8 @@ void HypnoEngine::parseScene(const Common::String &prefix, const Common::String
 	if (!prefix.empty())
 		name = prefix + "/" + name;
 	Common::File test;
-	assert(test.open(name.c_str()));
+	if (!test.open(name.c_str()))
+		error("Failed to open %s", name.c_str());
 
 	const uint32 fileSize = test.size();
 	char *buf = (char *)malloc(fileSize + 1);
@@ -116,7 +117,8 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 	}
 	if (found) {
 		if (selected.smenu) {
-			assert(!selected.smenu->empty());
+			if (selected.smenu->empty())
+				error("Invalid menu selected");
 			_nextHotsToAdd = selected.smenu;
 		}
 
@@ -192,7 +194,8 @@ void HypnoEngine::runTransition(Transition trans) {
 		sframe->free();
 		delete sframe;
 		Common::String *ptr = new Common::String(trans.level);
-		assert(installTimer(2 * 1000000, ptr));
+		if (!installTimer(2 * 1000000, ptr))
+			error("Failed to install timer");
 	} else
 		_nextLevel = trans.level;
 }
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index dc60656670..8fb66f7163 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -29,7 +29,8 @@ WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(s
 void WetEngine::loadAssets() {
 	LibFile *missions = loadLib("", "wetlands/c_misc/missions.lib");
 	Common::ArchiveMemberList files;
-	assert(missions->listMembers(files) > 0);
+	if (missions->listMembers(files) == 0)
+		error("Failed to load any files from missions.lib");
 
 	// We need the list of files in an array, instead of a list
 	Common::Array<Common::ArchiveMemberPtr> afiles;


Commit: f7b2ee5d1f01108d63a8e56c99b84098d2c33612
    https://github.com/scummvm/scummvm/commit/f7b2ee5d1f01108d63a8e56c99b84098d2c33612
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: replaced asserts with better code

Changed paths:
    engines/hypno/spider/spider.cpp


diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 6f046cf492..7762a3a954 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -10,12 +10,15 @@ SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEn
 
 void SpiderEngine::loadAssets() {
 
-	assert(_installerArchive.open("DATA.Z"));
+	if (!_installerArchive.open("DATA.Z"))
+		error("Failed to open DATA.Z");
+
 	SearchMan.add("DATA.Z", (Common::Archive *) &_installerArchive, 0, false);
 
 	Common::ArchiveMemberList files;
 	LibFile *missions = loadLib("", "sixdemo/c_misc/missions.lib");
-	assert(missions->listMembers(files) > 0);
+	if (missions->listMembers(files) == 0)
+		error("Failed to load any file from missions.lib");
 
 	// start level
 	Level start;


Commit: d4c82e641c00bfd71dfc1cd4c0ba978f3f83d957
    https://github.com/scummvm/scummvm/commit/d4c82e641c00bfd71dfc1cd4c0ba978f3f83d957
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: replaced std::min with MIN macro

Changed paths:
    engines/hypno/spider/arcade.cpp


diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index 5bd902ea2d..ec66f321ff 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -20,7 +20,6 @@
  *
  */
 
-#include <algorithm>
 
 #include "hypno/grammar.h"
 #include "hypno/hypno.h"
@@ -36,7 +35,7 @@ static const int shootOriginIndex[9][2] = {
 
 void SpiderEngine::drawShoot(const Common::Point &target) {
 	uint32 c = _pixelFormat.RGBToColor(255, 255, 255);
-	uint32 idx = std::min(2, target.x / (_screenW / 3)) + 3 * std::min(2, target.y / (_screenH / 3));
+	uint32 idx = MIN(2, target.x / (_screenW / 3)) + 3 * MIN(2, target.y / (_screenH / 3));
 	uint32 ox = 60  + shootOriginIndex[idx][0];
 	uint32 oy = 129 + shootOriginIndex[idx][1];
 	_compositeSurface->drawLine(ox, oy, target.x + 2, target.y, c);
@@ -49,7 +48,7 @@ void SpiderEngine::drawPlayer() {
 
 	if (_playerFrameIdx < _playerFrameSep) {
 		Common::Point mousePos = g_system->getEventManager()->getMousePos();
-		uint32 idx = std::min(2, mousePos.x / (_screenW / 3)) + 3 * std::min(2, mousePos.y / (_screenH / 3));
+		uint32 idx = MIN(2, mousePos.x / (_screenW / 3)) + 3 * MIN(2, mousePos.y / (_screenH / 3));
 		_playerFrameIdx = orientationIndex[idx];
 	} else {
 		_playerFrameIdx++;


Commit: 713529f49a433b15f71217a18f906c5cdefe8b25
    https://github.com/scummvm/scummvm/commit/713529f49a433b15f71217a18f906c5cdefe8b25
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: reduced scope of more variables

Changed paths:
    engines/hypno/spider/spider.cpp


diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 7762a3a954..481f6df886 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -132,8 +132,6 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 	Common::Rect cell(0, 0, 27, 27);
 	uint32 activeColor = _pixelFormat.RGBToColor(0, 130, 0);
 	uint32 deactiveColor = _pixelFormat.RGBToColor(0, 0, 0);
-	int x, y;
-	bool found;
 
 	loadImage("sixdemo/puz_matr/matrixbg.smk", 0, 0, false);
 	MVideo v("sixdemo/puz_matr/matintro.smk", Common::Point(0, 0), false, false, false);
@@ -152,8 +150,8 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 			case Common::EVENT_LBUTTONDOWN:
 				playSound("sixdemo/demo/sound.lib/matrix.raw", 1);
 				if (matrix.contains(mousePos)) {
-					x = (mousePos.x - 175) / 29;
-					y = (mousePos.y - 96) / 29;
+					int x = (mousePos.x - 175) / 29;
+					int y = (mousePos.y - 96) / 29;
 					cell.moveTo(175 + 29 * x + 1, 96 + 29 * y + 1);
 					_compositeSurface->fillRect(cell, data[x][y] ? deactiveColor : activeColor);
 					data[x][y] = !data[x][y];
@@ -165,9 +163,9 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 			}
 		}
 
-		found = true;
-		for (x = 0; x < 10; x++) {
-			for (y = 0; y < 10; y++) {
+		bool found = true;
+		for (int x = 0; x < 10; x++) {
+			for (int y = 0; y < 10; y++) {
 				if (data[x][y] != solution[y][x]) {
 					found = false;
 					break;


Commit: a92ddb455a8cc5a1c24d971c45a6f9bcd731c3fe
    https://github.com/scummvm/scummvm/commit/a92ddb455a8cc5a1c24d971c45a6f9bcd731c3fe
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added support for more wetlands demo, refactored code and added some fixes

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/boyz/boyz.cpp
    engines/hypno/detection.cpp
    engines/hypno/grammar_arc.cpp
    engines/hypno/grammar_arc.y
    engines/hypno/grammar_mis.cpp
    engines/hypno/grammar_mis.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/lexer_arc.cpp
    engines/hypno/lexer_arc.l
    engines/hypno/libfile.cpp
    engines/hypno/libfile.h
    engines/hypno/spider/spider.cpp
    engines/hypno/tokens_arc.h
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index ab27b2c691..11e17d12d5 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -31,8 +31,29 @@ namespace Hypno {
 
 extern int parse_arc(const char *);
 
+void HypnoEngine::splitArcadeFile(const Common::String &filename, Common::String &arc, Common::String &list) {
+	Common::File file;
+	if (!file.open(filename.c_str()))
+		error("Failed to open %s", filename.c_str());
+
+	while (!file.eos()) {
+		byte x = file.readByte();
+		arc += x;
+		if (x == 'X') {
+			while (!file.eos()) {
+				x = file.readByte();
+				if (x == 'Y')
+					break;
+				list += x;
+			}
+			break; // No need to keep parsing
+		}
+	}
+	file.close();
+}
+
 void HypnoEngine::parseArcadeShooting(const Common::String &prefix, const Common::String &filename, const Common::String &data) {
-	debugC(1, kHypnoDebugParser, "Parsing %s%s", prefix.c_str(), filename.c_str());
+	debugC(1, kHypnoDebugParser, "Parsing %s/%s", prefix.c_str(), filename.c_str());
 	parse_arc(data.c_str());
 	Level level;
 	level.arcade = g_parsedArc;
@@ -100,11 +121,15 @@ void HypnoEngine::runArcade(ArcadeShooting &arc) {
 	for (Frames::iterator it =_playerFrames.begin(); it != _playerFrames.end(); ++it) {
 		if ((*it)->getPixel(0, 0) == _pixelFormat.RGBToColor(0, 255, 255))
 			break; 
+		if ((*it)->getPixel(0, 0) == _pixelFormat.RGBToColor(0, 0, 255))
+			break; 
+
 		_playerFrameSep++;
 	}
 
 	if(_playerFrameSep == _playerFrames.size())
 		error("No player separator frame found!");
+	debugC(1, kHypnoDebugArcade, "Separator frame found at %d", _playerFrameSep);
 
 	_playerFrameIdx = -1;
 
diff --git a/engines/hypno/boyz/boyz.cpp b/engines/hypno/boyz/boyz.cpp
index fab556967b..d2d251eb2b 100644
--- a/engines/hypno/boyz/boyz.cpp
+++ b/engines/hypno/boyz/boyz.cpp
@@ -30,7 +30,7 @@ namespace Hypno {
 BoyzEngine::BoyzEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void BoyzEngine::loadAssets() {
-	loadLib("", "boyz/preload/missions.lib");
+	loadLib("", "boyz/preload/missions.lib", true);
 }
 
 } // namespace Hypno
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 75904729aa..7055e3d52c 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -64,6 +64,23 @@ static const ADGameDescription gameDescriptions[] = {
 	 Common::kPlatformDOS,
 	 ADGF_TESTING | ADGF_DEMO,
 	 GUIO1(GUIO_NOMIDI)},
+    {"wetlands", // Personal Computer World (UK) (May 1996) - Chapter 11 demo
+	 "Demo",
+	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 553355,
+				"missions.lib", "6ffa658f22a00b6e17d7f920fcc13578", 12469),
+	 Common::EN_GRB,
+	 Common::kPlatformDOS,
+	 ADGF_TESTING | ADGF_DEMO,
+	 GUIO1(GUIO_NOMIDI)},
+     {"wetlands", // PC Gamer Disc 12 (November 1995) - Chapter 31 demo
+	 "Demo",
+	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 553355,
+				"missions.lib", "34b922fac8f64546c0690aa83f09e98e", 40891),
+	 Common::EN_USA,
+	 Common::kPlatformDOS,
+	 ADGF_TESTING | ADGF_DEMO,
+	 GUIO1(GUIO_NOMIDI)},
+
 	{"wetlands", // Wetlands (US)
 	 "",
 	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 647447,
@@ -90,6 +107,7 @@ static const char *const directoryGlobs[] = {
 	"factory",
 	"wetlands",
 	"movie",
+	"c_misc",
 	0};
 
 class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
diff --git a/engines/hypno/grammar_arc.cpp b/engines/hypno/grammar_arc.cpp
index 6baa6c13b2..a852254163 100644
--- a/engines/hypno/grammar_arc.cpp
+++ b/engines/hypno/grammar_arc.cpp
@@ -75,8 +75,7 @@
 
 
 #include "common/array.h"
-#include "hypno/grammar.h"
-#include <stdio.h>
+#include "hypno/hypno.h"
 
 #undef yyerror
 #define yyerror	 HYPNO_ARC_xerror
@@ -85,10 +84,10 @@ Hypno::Shoot *shoot;
 
 extern int HYPNO_ARC_lex();
 extern int HYPNO_ARC_parse();
-extern int yylineno;
+extern int HYPNO_ARC_lineno;
 
 void HYPNO_ARC_xerror(const char *str) {
-	error("ERROR: %s", str);
+	error("%s at line %d", str, HYPNO_ARC_lineno);
 }
 
 int HYPNO_ARC_wrap() {
@@ -98,7 +97,7 @@ int HYPNO_ARC_wrap() {
 using namespace Hypno;
 
 
-#line 102 "engines/hypno/grammar_arc.cpp" /* yacc.c:339  */
+#line 101 "engines/hypno/grammar_arc.cpp" /* yacc.c:339  */
 
 # ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -146,35 +145,36 @@ extern int HYPNO_ARC_debug;
     BNTOK = 260,
     SNTOK = 261,
     NUM = 262,
-    YXTOK = 263,
-    CTOK = 264,
-    DTOK = 265,
-    HTOK = 266,
-    HETOK = 267,
-    RETTOK = 268,
-    QTOK = 269,
-    ENCTOK = 270,
-    PTOK = 271,
-    FTOK = 272,
-    TTOK = 273,
-    TPTOK = 274,
-    ATOK = 275,
-    VTOK = 276,
-    OTOK = 277,
-    O1TOK = 278,
-    NTOK = 279,
-    RTOK = 280,
-    ITOK = 281,
-    ZTOK = 282,
-    FNTOK = 283,
-    NONETOK = 284,
-    A0TOK = 285,
-    K0TOK = 286,
-    P0TOK = 287,
-    WTOK = 288,
-    XTOK = 289,
-    CB3TOK = 290,
-    C02TOK = 291
+    COMMENT = 263,
+    YXTOK = 264,
+    CTOK = 265,
+    DTOK = 266,
+    HTOK = 267,
+    HETOK = 268,
+    RETTOK = 269,
+    QTOK = 270,
+    ENCTOK = 271,
+    PTOK = 272,
+    FTOK = 273,
+    TTOK = 274,
+    TPTOK = 275,
+    ATOK = 276,
+    VTOK = 277,
+    OTOK = 278,
+    O1TOK = 279,
+    NTOK = 280,
+    RTOK = 281,
+    ITOK = 282,
+    ZTOK = 283,
+    FNTOK = 284,
+    NONETOK = 285,
+    A0TOK = 286,
+    K0TOK = 287,
+    P0TOK = 288,
+    WTOK = 289,
+    XTOK = 290,
+    CB3TOK = 291,
+    C02TOK = 292
   };
 #endif
 
@@ -183,7 +183,7 @@ extern int HYPNO_ARC_debug;
 
 union HYPNO_ARC_STYPE
 {
-#line 55 "engines/hypno/grammar_arc.y" /* yacc.c:355  */
+#line 54 "engines/hypno/grammar_arc.y" /* yacc.c:355  */
 
 	char *s; /* string value */
 	int i;	 /* integer value */
@@ -445,23 +445,23 @@ union yyalloc
 #endif /* !YYCOPY_NEEDED */
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  25
+#define YYFINAL  26
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   117
+#define YYLAST   105
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  37
+#define YYNTOKENS  38
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  7
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  47
+#define YYNRULES  48
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  109
+#define YYNSTATES  111
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   291
+#define YYMAXUTOK   292
 
 #define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -499,18 +499,18 @@ static const yytype_uint8 yytranslate[] =
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36
+      35,    36,    37
 };
 
 #if HYPNO_ARC_DEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint8 yyrline[] =
 {
-       0,    77,    77,    81,    82,    83,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    99,   104,   105,   109,   110,
-     114,   115,   125,   135,   136,   140,   143,   144,   147,   148,
-     150,   155,   160,   165,   169,   173,   177,   178,   179,   183,
-     184,   187,   188,   189,   190,   194,   201,   202
+       0,    76,    76,    77,    80,    81,    82,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    98,   103,   104,   108,
+     109,   113,   114,   124,   134,   135,   141,   142,   145,   146,
+     147,   150,   155,   160,   165,   169,   173,   177,   178,   179,
+     183,   184,   187,   188,   189,   190,   194,   201,   202
 };
 #endif
 
@@ -520,11 +520,11 @@ static const yytype_uint8 yyrline[] =
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "NAME", "FILENAME", "BNTOK", "SNTOK",
-  "NUM", "YXTOK", "CTOK", "DTOK", "HTOK", "HETOK", "RETTOK", "QTOK",
-  "ENCTOK", "PTOK", "FTOK", "TTOK", "TPTOK", "ATOK", "VTOK", "OTOK",
-  "O1TOK", "NTOK", "RTOK", "ITOK", "ZTOK", "FNTOK", "NONETOK", "A0TOK",
-  "K0TOK", "P0TOK", "WTOK", "XTOK", "CB3TOK", "C02TOK", "$accept", "start",
-  "header", "hline", "enc", "body", "bline", YY_NULLPTR
+  "NUM", "COMMENT", "YXTOK", "CTOK", "DTOK", "HTOK", "HETOK", "RETTOK",
+  "QTOK", "ENCTOK", "PTOK", "FTOK", "TTOK", "TPTOK", "ATOK", "VTOK",
+  "OTOK", "O1TOK", "NTOK", "RTOK", "ITOK", "ZTOK", "FNTOK", "NONETOK",
+  "A0TOK", "K0TOK", "P0TOK", "WTOK", "XTOK", "CB3TOK", "C02TOK", "$accept",
+  "start", "header", "hline", "enc", "body", "bline", YY_NULLPTR
 };
 #endif
 
@@ -536,14 +536,14 @@ static const yytype_uint16 yytoknum[] =
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291
+     285,   286,   287,   288,   289,   290,   291,   292
 };
 # endif
 
-#define YYPACT_NINF -20
+#define YYPACT_NINF -60
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-20)))
+  (!!((Yystate) == (-60)))
 
 #define YYTABLE_NINF -1
 
@@ -554,17 +554,18 @@ static const yytype_uint16 yytoknum[] =
      STATE-NUM.  */
 static const yytype_int8 yypact[] =
 {
-      -5,    56,     4,     7,    11,     1,    10,   -19,   -17,    56,
-      18,    24,    32,     5,    36,    34,    35,    38,    39,    43,
-      44,    46,    30,    27,    50,   -20,   -20,    49,   -20,   -20,
-      64,    77,   -20,    78,    79,   -20,    80,    81,    82,    83,
-      84,    85,    86,   -20,   -20,   -20,   -20,    87,    91,    89,
-      90,    92,    94,    93,   -20,    95,     9,   -20,     6,    96,
-      97,    98,    99,   -20,    88,    56,   -20,   -20,   100,   101,
-     -20,   -20,   -20,   -20,   105,   -20,   -20,   -20,   -20,   103,
-      49,   -20,   -20,   -20,   -20,   104,   106,   -20,   -20,   -20,
-     -20,   107,   108,   109,   -20,    -4,   -20,   -20,   -20,   -20,
-     -20,   -20,   -20,   -20,   -20,   -20,   -20,   -20,   -20
+       1,    26,     1,     3,     7,    10,    28,    35,    -3,    17,
+      26,    48,    49,    50,     0,    54,    52,    53,    55,    56,
+      57,    60,    61,    38,    26,   -60,   -60,   -60,    51,   -60,
+     -60,    62,    63,   -60,    64,    65,   -60,    66,    67,    68,
+      69,    70,    71,    72,   -60,   -60,   -60,    73,   -60,   -60,
+     -60,    74,    75,   -60,   -60,   -60,   -60,    76,   -60,   -60,
+     -60,   -60,    -5,   -60,   -60,   -60,    77,    79,    78,    81,
+      82,    -5,    86,    84,   -60,    85,    14,   -60,     4,    87,
+      88,    89,    90,    33,    -5,    91,    51,   -60,   -60,   -60,
+     -60,   -60,    92,    93,   -60,   -60,   -60,   -60,    94,    95,
+      96,   -60,   -60,   -60,   -60,   -60,   -60,   -60,   -60,   -60,
+     -60
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -572,29 +573,30 @@ static const yytype_int8 yypact[] =
      means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     4,     1,    21,    27,     6,     8,
-       0,     0,     5,     0,     0,     7,     0,     0,     0,     0,
-       0,     0,     0,    17,    18,    19,    25,     0,     0,     0,
-       0,     0,     0,     0,    46,     0,     0,    47,     0,     0,
-       0,     0,     0,     2,     0,     0,    26,    22,     0,     0,
-      20,     9,    15,    16,     0,    10,    11,    12,    13,     0,
-      27,    41,    44,    42,    32,     0,     0,    33,    34,    30,
-      31,     0,     0,     0,    43,     0,     3,    24,    23,    14,
-      37,    45,    40,    36,    35,    38,    39,    29,    28
+       0,     6,     0,     0,     0,     0,     0,     0,     0,     0,
+       6,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     6,     3,     1,    22,    27,     7,
+       9,     0,     0,     5,     0,     0,     8,     0,     0,     0,
+       0,     0,     0,     0,    18,    19,    20,     0,     4,    26,
+      23,     0,     0,    21,    10,    16,    17,     0,    11,    12,
+      13,    14,    30,    25,    24,    15,     0,     0,     0,     0,
+       0,    30,     0,     0,    47,     0,     0,    48,     0,     0,
+       0,     0,     0,     0,    30,     0,    27,    42,    45,    43,
+      29,    33,     0,     0,    34,    35,    31,    32,     0,     0,
+       0,    44,     2,    28,    38,    46,    41,    37,    36,    39,
+      40
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -20,   -20,    -9,   -20,    37,    17,   -20
+     -60,   102,    -8,   -60,    19,   -59,   -60
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     2,    23,    24,    67,    63,    64
+      -1,     3,    23,    24,    50,    83,    84
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -602,71 +604,70 @@ static const yytype_int8 yydefgoto[] =
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-      32,    47,    48,     1,    25,    49,    50,    51,    28,    36,
-      89,    26,    87,    52,    88,    27,    30,    29,    53,    31,
-      54,    55,    56,    57,    58,    33,    59,    60,    61,    62,
-     107,    34,    47,    48,    37,    90,    49,    50,    51,    35,
-      38,    39,    40,    46,    52,    41,    42,    43,    44,    53,
-      45,    54,    55,    56,    57,    58,    96,    59,    60,    61,
-      62,     3,     4,    65,    66,     5,     6,     7,     8,     9,
-      10,    68,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    69,    70,    71,    72,    73,    74,
-      75,    76,    77,    78,    79,    80,    81,    82,    84,    83,
-      85,    95,    86,    91,    92,    93,    94,    97,    98,    99,
-     100,   102,   108,   103,   104,   105,   106,   101
+      66,    67,    33,    26,    37,    68,    69,    70,    96,    71,
+       1,    27,    90,    72,    28,     2,    48,    94,    73,    95,
+      74,    75,    76,    77,    78,   103,    79,    80,    81,    82,
+      38,     4,     5,    31,    97,    29,     6,     7,     8,     9,
+      10,    11,    30,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    32,    34,    35,    36,    39,    40,
+      41,    44,    42,    43,    45,    46,    47,    49,   102,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      65,    63,    64,    86,    85,    87,     0,    62,    88,    89,
+      91,    92,    93,     0,    98,    99,   100,   101,   104,   106,
+     107,   108,   109,   110,    25,   105
 };
 
-static const yytype_uint8 yycheck[] =
+static const yytype_int8 yycheck[] =
 {
-       9,     5,     6,     8,     0,     9,    10,    11,     7,     4,
-       4,     4,     3,    17,     5,     4,    35,     7,    22,    36,
-      24,    25,    26,    27,    28,     7,    30,    31,    32,    33,
-      34,     7,     5,     6,    29,    29,     9,    10,    11,     7,
-       4,     7,     7,    13,    17,     7,     7,     4,     4,    22,
-       4,    24,    25,    26,    27,    28,    65,    30,    31,    32,
-      33,     5,     6,    13,    15,     9,    10,    11,    12,    13,
-      14,     7,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,     7,     7,     7,     7,     7,     7,
-       7,     7,     7,     7,     7,     4,     7,     7,     4,     7,
-       7,    13,     7,     7,     7,     7,     7,     7,     7,     4,
-       7,     7,    95,     7,     7,     7,     7,    80
+       5,     6,    10,     0,     4,    10,    11,    12,     4,    14,
+       9,     4,    71,    18,     4,    14,    24,     3,    23,     5,
+      25,    26,    27,    28,    29,    84,    31,    32,    33,    34,
+      30,     5,     6,    36,    30,     7,    10,    11,    12,    13,
+      14,    15,     7,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    37,     7,     7,     7,     4,     7,
+       7,     4,     7,     7,     4,     4,    28,    16,    35,     7,
+       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       4,     7,     7,     4,     7,     7,    -1,    14,     7,     7,
+       4,     7,     7,    -1,     7,     7,     7,     7,     7,     7,
+       7,     7,     7,     7,     2,    86
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     8,    38,     5,     6,     9,    10,    11,    12,    13,
-      14,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    39,    40,     0,     4,     4,     7,     7,
-      35,    36,    39,     7,     7,     7,     4,    29,     4,     7,
-       7,     7,     7,     4,     4,     4,    13,     5,     6,     9,
-      10,    11,    17,    22,    24,    25,    26,    27,    28,    30,
-      31,    32,    33,    42,    43,    13,    15,    41,     7,     7,
-       7,     7,     7,     7,     7,     7,     7,     7,     7,     7,
-       4,     7,     7,     7,     4,     7,     7,     3,     5,     4,
-      29,     7,     7,     7,     7,    13,    39,     7,     7,     4,
-       7,    41,     7,     7,     7,     7,     7,    34,    42
+       0,     9,    14,    39,     5,     6,    10,    11,    12,    13,
+      14,    15,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    40,    41,    39,     0,     4,     4,     7,
+       7,    36,    37,    40,     7,     7,     7,     4,    30,     4,
+       7,     7,     7,     7,     4,     4,     4,    28,    40,    16,
+      42,     7,     7,     7,     7,     7,     7,     7,     7,     7,
+       7,     7,    14,     7,     7,     4,     5,     6,    10,    11,
+      12,    14,    18,    23,    25,    26,    27,    28,    29,    31,
+      32,    33,    34,    43,    44,     7,     4,     7,     7,     7,
+      43,     4,     7,     7,     3,     5,     4,    30,     7,     7,
+       7,     7,    35,    43,     7,    42,     7,     7,     7,     7,
+       7
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    37,    38,    39,    39,    39,    40,    40,    40,    40,
-      40,    40,    40,    40,    40,    40,    40,    40,    40,    40,
-      40,    40,    40,    40,    40,    40,    41,    41,    42,    42,
-      43,    43,    43,    43,    43,    43,    43,    43,    43,    43,
-      43,    43,    43,    43,    43,    43,    43,    43
+       0,    38,    39,    39,    40,    40,    40,    41,    41,    41,
+      41,    41,    41,    41,    41,    41,    41,    41,    41,    41,
+      41,    41,    41,    41,    41,    41,    42,    42,    43,    43,
+      43,    44,    44,    44,    44,    44,    44,    44,    44,    44,
+      44,    44,    44,    44,    44,    44,    44,    44,    44
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     3,     3,     1,     2,     2,     2,     2,     3,
-       3,     3,     3,     3,     4,     3,     3,     2,     2,     2,
-       3,     2,     3,     4,     4,     2,     1,     0,     3,     3,
-       2,     2,     2,     2,     2,     3,     3,     3,     3,     3,
-       3,     2,     2,     2,     2,     3,     1,     1
+       0,     2,     6,     2,     2,     2,     0,     2,     2,     2,
+       3,     3,     3,     3,     3,     4,     3,     3,     2,     2,
+       2,     3,     2,     3,     4,     4,     1,     0,     2,     2,
+       0,     2,     2,     2,     2,     2,     3,     3,     3,     3,
+       3,     3,     2,     2,     2,     2,     3,     1,     1
 };
 
 
@@ -1342,112 +1343,112 @@ yyreduce:
   YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
-        case 6:
+        case 7:
+#line 85 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "C %d", (yyvsp[0].i)); }
+#line 1350 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    break;
+
+  case 8:
 #line 86 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("C %d", (yyvsp[0].i)); }
-#line 1349 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "F %d", (yyvsp[0].i)); }
+#line 1356 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 7:
+  case 9:
 #line 87 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("F %d", (yyvsp[0].i)); }
-#line 1355 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "D %d", (yyvsp[0].i)); }
+#line 1362 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 8:
+  case 10:
 #line 88 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("D %d", (yyvsp[0].i)); }
-#line 1361 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "P %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1368 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 9:
+  case 11:
 #line 89 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("P %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1367 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "A %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1374 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 10:
+  case 12:
 #line 90 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("A %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1373 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "V %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1380 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 11:
+  case 13:
 #line 91 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("V %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1379 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1386 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 12:
+  case 14:
 #line 92 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1385 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "O1 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1392 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 13:
+  case 15:
 #line 93 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("O1 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1391 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
-    break;
-
-  case 14:
-#line 94 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		g_parsedArc.transitionVideo = (yyvsp[-2].s);
 		g_parsedArc.transitionTime = (yyvsp[-1].i);
-		debug("Tp %s %d %s", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "Tp %s %d %s", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].s)); 
 	}
-#line 1401 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1402 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 15:
-#line 99 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+  case 16:
+#line 98 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		g_parsedArc.transitionVideo = (yyvsp[-1].s);
 		g_parsedArc.transitionTime = (yyvsp[0].i);
-		debug("T %s %d", (yyvsp[-1].s), (yyvsp[0].i)); 
+		debugC(1, kHypnoDebugParser, "T %s %d", (yyvsp[-1].s), (yyvsp[0].i)); 
 	}
-#line 1411 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1412 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 16:
-#line 104 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("T NONE %d", (yyvsp[0].i)); }
-#line 1417 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+  case 17:
+#line 103 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "T NONE %d", (yyvsp[0].i)); }
+#line 1418 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 17:
-#line 105 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+  case 18:
+#line 104 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		g_parsedArc.background = (yyvsp[0].s); 
-		debug("N %s", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "N %s", (yyvsp[0].s)); 
 	}
-#line 1426 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1427 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 18:
-#line 109 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("R %s", (yyvsp[0].s)); }
-#line 1432 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+  case 19:
+#line 108 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "R %s", (yyvsp[0].s)); }
+#line 1433 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 19:
-#line 110 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+  case 20:
+#line 109 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		g_parsedArc.player = (yyvsp[0].s); 
-		debug("I %s", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "I %s", (yyvsp[0].s)); 
 		}
-#line 1441 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1442 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 20:
-#line 114 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("Q %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1447 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+  case 21:
+#line 113 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "Q %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1448 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 21:
-#line 115 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+  case 22:
+#line 114 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		if (Common::String("B0") == (yyvsp[-1].s))
 			g_parsedArc.intro = (yyvsp[0].s);
@@ -1456,13 +1457,13 @@ yyreduce:
 		else if(Common::String("B3") == (yyvsp[-1].s) || Common::String("B4") == (yyvsp[-1].s))
 			g_parsedArc.defeatVideos.push_back((yyvsp[0].s));
 
-		debug("BN %s", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "BN %s", (yyvsp[0].s)); 
 	}
-#line 1462 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1463 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 22:
-#line 125 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+  case 23:
+#line 124 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		if (Common::String("S0") == (yyvsp[-2].s))
 			g_parsedArc.music = (yyvsp[-1].s);
@@ -1471,152 +1472,146 @@ yyreduce:
 		else if (Common::String("S4") == (yyvsp[-2].s))
 			g_parsedArc.enemySound = (yyvsp[-1].s); 
 
-		debug("SN %s", (yyvsp[-1].s)); 
+		debugC(1, kHypnoDebugParser, "SN %s", (yyvsp[-1].s)); 
 	}
-#line 1477 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1478 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 23:
-#line 135 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("HE %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1483 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+  case 24:
+#line 134 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "HE %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1484 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 24:
-#line 136 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+  case 25:
+#line 135 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		g_parsedArc.health = (yyvsp[-1].i);
-		debug("H %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+		debugC(1, kHypnoDebugParser, "H %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	}
-#line 1492 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1493 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 25:
-#line 140 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("Z"); }
-#line 1498 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
-    break;
-
-  case 30:
+  case 31:
 #line 150 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
-		debug("FN %s", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "FN %s", (yyvsp[0].s)); 
 	}
-#line 1508 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1503 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 31:
+  case 32:
 #line 155 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = "NONE";
-		debug("FN NONE"); 
+		debugC(1, kHypnoDebugParser, "FN NONE"); 
 	}
-#line 1518 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1513 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 32:
+  case 33:
 #line 160 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
-		debug("FN %s", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "FN %s", (yyvsp[0].s)); 
 	}
-#line 1528 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1523 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 33:
+  case 34:
 #line 165 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->name = (yyvsp[0].s);
-		debug("I %s", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "I %s", (yyvsp[0].s)); 
 	}
-#line 1537 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1532 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 34:
+  case 35:
 #line 169 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {  // Workaround for NAME == B1
 		shoot->name = (yyvsp[0].s);
-		debug("I %s", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "I %s", (yyvsp[0].s)); 
 	}
-#line 1546 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1541 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 35:
+  case 36:
 #line 173 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->position = Common::Point((yyvsp[-1].i), (yyvsp[0].i));
-		debug("A0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+		debugC(1, kHypnoDebugParser, "A0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	}
-#line 1555 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1550 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 36:
+  case 37:
 #line 177 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("R %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1561 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "R %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1556 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 37:
+  case 38:
 #line 178 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("BN %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1567 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "BN %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1562 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 38:
+  case 39:
 #line 179 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->explosionFrame = (yyvsp[0].i);
-		debug("K0 %d %d", (yyvsp[-1].i), (yyvsp[0].i));
+		debugC(1, kHypnoDebugParser, "K0 %d %d", (yyvsp[-1].i), (yyvsp[0].i));
 	}
-#line 1576 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1571 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 39:
+  case 40:
 #line 183 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("P0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1582 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "P0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1577 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 40:
+  case 41:
 #line 184 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		debug("O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
+		debugC(1, kHypnoDebugParser, "O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	}
-#line 1590 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1585 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 41:
+  case 42:
 #line 187 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("C %d", (yyvsp[0].i)); }
-#line 1596 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "C %d", (yyvsp[0].i)); }
+#line 1591 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 42:
+  case 43:
 #line 188 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("H %d", (yyvsp[0].i)); }
-#line 1602 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "H %d", (yyvsp[0].i)); }
+#line 1597 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 43:
+  case 44:
 #line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("W %d", (yyvsp[0].i)); }
-#line 1608 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "W %d", (yyvsp[0].i)); }
+#line 1603 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 44:
+  case 45:
 #line 190 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->damage = (yyvsp[0].i);
-		debug("D %d", (yyvsp[0].i)); 
+		debugC(1, kHypnoDebugParser, "D %d", (yyvsp[0].i)); 
 	}
-#line 1617 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1612 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 45:
+  case 46:
 #line 194 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		if (Common::String("S1") == (yyvsp[-2].s))
@@ -1624,29 +1619,29 @@ yyreduce:
 		//else if (Common::String("S2") == $1)
 		//	shoot->startSound = $2;
 		 
-		debug("SN %s", (yyvsp[-1].s)); }
-#line 1629 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+		debugC(1, kHypnoDebugParser, "SN %s", (yyvsp[-1].s)); }
+#line 1624 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 46:
+  case 47:
 #line 201 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debug("N"); }
-#line 1635 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "N"); }
+#line 1630 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
-  case 47:
+  case 48:
 #line 202 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		g_parsedArc.shoots.push_back(*shoot); 
 		//delete shoot; 
 		//shoot = nullptr;
-		debug("Z"); 
+		debugC(1, kHypnoDebugParser, "Z"); 
 	}
-#line 1646 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1641 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1650 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1645 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index 90bbdac47e..4efe38bf65 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -28,8 +28,7 @@
 %{
 
 #include "common/array.h"
-#include "hypno/grammar.h"
-#include <stdio.h>
+#include "hypno/hypno.h"
 
 #undef yyerror
 #define yyerror	 HYPNO_ARC_xerror
@@ -38,10 +37,10 @@ Hypno::Shoot *shoot;
 
 extern int HYPNO_ARC_lex();
 extern int HYPNO_ARC_parse();
-extern int yylineno;
+extern int HYPNO_ARC_lineno;
 
 void HYPNO_ARC_xerror(const char *str) {
-	error("ERROR: %s", str);
+	error("%s at line %d", str, HYPNO_ARC_lineno);
 }
 
 int HYPNO_ARC_wrap() {
@@ -60,7 +59,7 @@ using namespace Hypno;
 %token<s> NAME FILENAME BNTOK SNTOK
 %token<i> NUM
 // header
-%token YXTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
+%token COMMENT YXTOK CTOK DTOK HTOK HETOK RETTOK QTOK ENCTOK
 %token PTOK FTOK TTOK TPTOK ATOK VTOK OTOK O1TOK NTOK RTOK ITOK ZTOK
 
 // body
@@ -74,44 +73,44 @@ using namespace Hypno;
 
 %%
 
-start: YXTOK header body
+start: YXTOK header ZTOK RETTOK body XTOK
+    | RETTOK start
 	;
 
-
-header:  hline RETTOK header
-	| hline
-	| RETTOK header
+header: hline header
+    | RETTOK header
+	| /* nothing */
 	; 
 
-hline:  CTOK NUM  { debug("C %d", $2); }
-	| FTOK NUM { debug("F %d", $2); }
-	| DTOK NUM  { debug("D %d", $2); }
-	| PTOK NUM NUM { debug("P %d %d", $2, $3); }
-	| ATOK NUM NUM { debug("A %d %d", $2, $3); }
-	| VTOK NUM NUM { debug("V %d %d", $2, $3); }
-	| OTOK NUM NUM { debug("O %d %d", $2, $3); }
-	| O1TOK NUM NUM { debug("O1 %d %d", $2, $3); }
+hline:  CTOK NUM  { debugC(1, kHypnoDebugParser, "C %d", $2); }
+	| FTOK NUM { debugC(1, kHypnoDebugParser, "F %d", $2); }
+	| DTOK NUM  { debugC(1, kHypnoDebugParser, "D %d", $2); }
+	| PTOK NUM NUM { debugC(1, kHypnoDebugParser, "P %d %d", $2, $3); }
+	| ATOK NUM NUM { debugC(1, kHypnoDebugParser, "A %d %d", $2, $3); }
+	| VTOK NUM NUM { debugC(1, kHypnoDebugParser, "V %d %d", $2, $3); }
+	| OTOK NUM NUM { debugC(1, kHypnoDebugParser, "O %d %d", $2, $3); }
+	| O1TOK NUM NUM { debugC(1, kHypnoDebugParser, "O1 %d %d", $2, $3); }
 	| TPTOK FILENAME NUM FILENAME {
 		g_parsedArc.transitionVideo = $2;
 		g_parsedArc.transitionTime = $3;
-		debug("Tp %s %d %s", $2, $3, $4); 
+		debugC(1, kHypnoDebugParser, "Tp %s %d %s", $2, $3, $4); 
 	}
 	| TTOK FILENAME NUM { 
 		g_parsedArc.transitionVideo = $2;
 		g_parsedArc.transitionTime = $3;
-		debug("T %s %d", $2, $3); 
+		debugC(1, kHypnoDebugParser, "T %s %d", $2, $3); 
 	}
-	| TTOK NONETOK NUM { debug("T NONE %d", $3); }
+	| TTOK NONETOK NUM { debugC(1, kHypnoDebugParser, "T NONE %d", $3); }
 	| NTOK FILENAME  { 
 		g_parsedArc.background = $2; 
-		debug("N %s", $2); 
+		debugC(1, kHypnoDebugParser, "N %s", $2); 
 	}
-	| RTOK FILENAME  { debug("R %s", $2); }
+	| RTOK FILENAME  { debugC(1, kHypnoDebugParser, "R %s", $2); }
 	| ITOK FILENAME { 
 		g_parsedArc.player = $2; 
-		debug("I %s", $2); 
+		debugC(1, kHypnoDebugParser, "I %s", $2); 
 		}
-	| QTOK NUM NUM { debug("Q %d %d", $2, $3); }
+	| QTOK NUM NUM { debugC(1, kHypnoDebugParser, "Q %d %d", $2, $3); }
 	| BNTOK FILENAME {
 		if (Common::String("B0") == $1)
 			g_parsedArc.intro = $2;
@@ -120,7 +119,7 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 		else if(Common::String("B3") == $1 || Common::String("B4") == $1)
 			g_parsedArc.defeatVideos.push_back($2);
 
-		debug("BN %s", $2); 
+		debugC(1, kHypnoDebugParser, "BN %s", $2); 
 	}
 	| SNTOK FILENAME enc {
 		if (Common::String("S0") == $1)
@@ -130,66 +129,67 @@ hline:  CTOK NUM  { debug("C %d", $2); }
 		else if (Common::String("S4") == $1)
 			g_parsedArc.enemySound = $2; 
 
-		debug("SN %s", $2); 
+		debugC(1, kHypnoDebugParser, "SN %s", $2); 
 	}
-	| HETOK C02TOK NUM NUM { debug("HE %d %d", $3, $4); }
+	| HETOK C02TOK NUM NUM { debugC(1, kHypnoDebugParser, "HE %d %d", $3, $4); }
 	| HTOK CB3TOK NUM NUM { 
 		g_parsedArc.health = $3;
-		debug("H %d %d", $3, $4); 
+		debugC(1, kHypnoDebugParser, "H %d %d", $3, $4); 
 	}
-	| ZTOK RETTOK { debug("Z"); }
 	;
 
 enc: ENCTOK
 	| /* nothing */
 	;
 
-body: bline RETTOK body
-	| bline RETTOK XTOK
+body: bline body
+	| RETTOK body
+	| /* nothing */
+	;
 
 bline: FNTOK FILENAME { 
 		shoot = new Shoot();
 		shoot->animation = $2;
-		debug("FN %s", $2); 
+		debugC(1, kHypnoDebugParser, "FN %s", $2); 
 	}
 	| FNTOK NONETOK { 
 		shoot = new Shoot();
 		shoot->animation = "NONE";
-		debug("FN NONE"); 
+		debugC(1, kHypnoDebugParser, "FN NONE"); 
 	}
 	| FTOK FILENAME { 
 		shoot = new Shoot();
 		shoot->animation = $2;
-		debug("FN %s", $2); 
+		debugC(1, kHypnoDebugParser, "FN %s", $2); 
 	}
-	| ITOK  NAME  { 
+	| ITOK NAME  { 
 		shoot->name = $2;
-		debug("I %s", $2); 
+		debugC(1, kHypnoDebugParser, "I %s", $2); 
 	}
-	| ITOK  BNTOK  {  // Workaround for NAME == B1
+	| ITOK BNTOK  {  // Workaround for NAME == B1
 		shoot->name = $2;
-		debug("I %s", $2); 
+		debugC(1, kHypnoDebugParser, "I %s", $2); 
 	}
 	| A0TOK NUM NUM { 
 		shoot->position = Common::Point($2, $3);
-		debug("A0 %d %d", $2, $3); 
+		debugC(1, kHypnoDebugParser, "A0 %d %d", $2, $3); 
 	}
-	| RTOK NUM NUM  { debug("R %d %d", $2, $3); }
-	| BNTOK NUM NUM { debug("BN %d %d", $2, $3); }
+	| RTOK NUM NUM  { debugC(1, kHypnoDebugParser, "R %d %d", $2, $3); }
+	| BNTOK NUM NUM { debugC(1, kHypnoDebugParser, "BN %d %d", $2, $3); }
 	| K0TOK NUM NUM { 
 		shoot->explosionFrame = $3;
-		debug("K0 %d %d", $2, $3);
+		debugC(1, kHypnoDebugParser, "K0 %d %d", $2, $3);
 	}
-	| P0TOK NUM NUM { debug("P0 %d %d", $2, $3); }
+	| P0TOK NUM NUM { debugC(1, kHypnoDebugParser, "P0 %d %d", $2, $3); }
 	| OTOK NUM NUM { 
-		debug("O %d %d", $2, $3); 
+		debugC(1, kHypnoDebugParser, "O %d %d", $2, $3); 
 	}
-	| CTOK NUM  { debug("C %d", $2); } 
-	| HTOK NUM  { debug("H %d", $2); }
-	| WTOK NUM  { debug("W %d", $2); }
+	| CTOK NUM  { debugC(1, kHypnoDebugParser, "C %d", $2); } 
+	| HTOK NUM  { debugC(1, kHypnoDebugParser, "H %d", $2); }
+	| WTOK NUM  { debugC(1, kHypnoDebugParser, "W %d", $2); }
 	| DTOK NUM  { 
 		shoot->damage = $2;
-		debug("D %d", $2); 
+		debugC(1, kHypnoDebugParser, "D %d", $2); 
 	}
 	| SNTOK FILENAME enc { 
 		if (Common::String("S1") == $1)
@@ -197,13 +197,13 @@ bline: FNTOK FILENAME {
 		//else if (Common::String("S2") == $1)
 		//	shoot->startSound = $2;
 		 
-		debug("SN %s", $2); }
-	| NTOK { debug("N"); }
+		debugC(1, kHypnoDebugParser, "SN %s", $2); }
+	| NTOK { debugC(1, kHypnoDebugParser, "N"); }
 	| ZTOK {
 		g_parsedArc.shoots.push_back(*shoot); 
 		//delete shoot; 
 		//shoot = nullptr;
-		debug("Z"); 
+		debugC(1, kHypnoDebugParser, "Z"); 
 	}
 	;
 
diff --git a/engines/hypno/grammar_mis.cpp b/engines/hypno/grammar_mis.cpp
index 58ba4ccbbd..b2bdc0138e 100644
--- a/engines/hypno/grammar_mis.cpp
+++ b/engines/hypno/grammar_mis.cpp
@@ -75,8 +75,8 @@
 
 
 #include "common/array.h"
-#include "hypno/grammar.h"
-#include <stdio.h>
+#include "hypno/hypno.h"
+//#include <stdio.h>
 
 #undef yyerror
 #define yyerror	 HYPNO_MIS_xerror
@@ -1361,7 +1361,7 @@ yyreduce:
 
   case 7:
 #line 87 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debug("implicit END"); }
+    { debugC(1, kHypnoDebugParser, "implicit END"); }
 #line 1366 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1372,7 +1372,7 @@ yyreduce:
 		hot->type = MakeMenu;
 		hot->stype = (yyvsp[-1].s);
 		hot->smenu = NULL;
-		debug("MENU %d.", hot->type);
+		debugC(1, kHypnoDebugParser, "MENU %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot);
 
@@ -1392,7 +1392,7 @@ yyreduce:
 		hot->type = MakeHotspot;
 		hot->smenu = NULL;
 		hot->rect = Common::Rect((yyvsp[-3].i), (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i));
-		debug("HOTS %d.", hot->type);
+		debugC(1, kHypnoDebugParser, "HOTS %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot); 
 	}
@@ -1414,7 +1414,7 @@ yyreduce:
 		smenu_idx.push_back(-1);
 		hot->smenu = new Hotspots();
 		stack.push_back(hot->smenu);
-		debug("SUBMENU"); 
+		debugC(1, kHypnoDebugParser, "SUBMENU"); 
 	}
 #line 1420 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
@@ -1426,13 +1426,13 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("ESC SUBMENU"); }
+		debugC(1, kHypnoDebugParser, "ESC SUBMENU"); }
 #line 1431 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
 #line 135 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debug("TIME %d", (yyvsp[0].i)); }
+    { debugC(1, kHypnoDebugParser, "TIME %d", (yyvsp[0].i)); }
 #line 1437 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1446,7 +1446,7 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("BACK");
+		debugC(1, kHypnoDebugParser, "BACK");
 	}
 #line 1452 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
@@ -1460,7 +1460,7 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("GLOB."); 
+		debugC(1, kHypnoDebugParser, "GLOB"); 
 	}
 #line 1466 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
@@ -1475,7 +1475,7 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);			
-		debug("AMBI %d %d.", (yyvsp[-2].i), (yyvsp[-1].i)); }
+		debugC(1, kHypnoDebugParser, "AMBI %d %d", (yyvsp[-2].i), (yyvsp[-1].i)); }
 #line 1480 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1490,7 +1490,7 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
-		debug("PLAY %s.", (yyvsp[-4].s)); }
+		debugC(1, kHypnoDebugParser, "PLAY %s.", (yyvsp[-4].s)); }
 #line 1495 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1515,7 +1515,7 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("PALE");
+		debugC(1, kHypnoDebugParser, "PALE");
 	}
 #line 1521 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
@@ -1528,7 +1528,7 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
-		debug("CUTS %s.", (yyvsp[0].s)); 
+		debugC(1, kHypnoDebugParser, "CUTS %s", (yyvsp[0].s)); 
 	}
 #line 1534 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
@@ -1544,7 +1544,7 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
-		debug("WALN %s %d %d.", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
+		debugC(1, kHypnoDebugParser, "WALN %s %d %d", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
 #line 1549 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1568,14 +1568,14 @@ yyreduce:
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(talk_action);
 		talk_action = nullptr;
-		debug("TALK"); }
+		debugC(1, kHypnoDebugParser, "TALK"); }
 #line 1573 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
 #line 222 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		debug("explicit END");
+		debugC(1, kHypnoDebugParser, "explicit END");
 		g_parsedHots = stack.back(); 
 		stack.pop_back();
 		smenu_idx.pop_back();
@@ -1597,13 +1597,13 @@ yyreduce:
 #line 236 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		talk_action->active = false; 
-		debug("inactive"); }
+		debugC(1, kHypnoDebugParser, "inactive"); }
 #line 1602 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
 #line 239 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debug("inactive"); }
+    { debugC(1, kHypnoDebugParser, "inactive"); }
 #line 1608 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1612,13 +1612,13 @@ yyreduce:
     { 
 		talk_action->background = (yyvsp[-4].s);
 		talk_action->position = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-		debug("BACK in TALK"); }
+		debugC(1, kHypnoDebugParser, "BACK in TALK"); }
 #line 1617 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
 #line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debug("BOXX %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
+    { debugC(1, kHypnoDebugParser, "BOXX %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
 #line 1623 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1629,13 +1629,13 @@ yyreduce:
 		talk_cmd.command = "G";
 		talk_cmd.path = (yyvsp[-1].s)+2;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("%s", (yyvsp[-1].s)); }
+		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
 #line 1634 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
 #line 251 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debug("%s", (yyvsp[-1].s)); }
+    { debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
 #line 1640 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1646,7 +1646,7 @@ yyreduce:
 		talk_cmd.command = "F";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("%s", (yyvsp[-1].s)); }
+		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
 #line 1651 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1657,7 +1657,7 @@ yyreduce:
 		talk_cmd.command = "A";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("|A%d", talk_cmd.num); }
+		debugC(1, kHypnoDebugParser, "|A%d", talk_cmd.num); }
 #line 1662 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1668,7 +1668,7 @@ yyreduce:
 		talk_cmd.command = "D";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("%s", (yyvsp[-1].s)); }
+		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
 #line 1673 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1680,7 +1680,7 @@ yyreduce:
 		talk_cmd.path = (yyvsp[-3].s)+2;
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);
-		debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
+		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
 #line 1685 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1692,19 +1692,19 @@ yyreduce:
 		talk_cmd.path = (yyvsp[-3].s)+2;
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);		  
-		debug("%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
+		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
 #line 1697 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
 #line 284 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debug("|E"); }
+    { debugC(1, kHypnoDebugParser, "|E"); }
 #line 1703 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
 #line 292 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { (yyval.s) = (yyvsp[0].s); debug("flag: %s", (yyvsp[0].s)); }
+    { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "flag: %s", (yyvsp[0].s)); }
 #line 1709 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
@@ -1716,7 +1716,7 @@ yyreduce:
 
   case 42:
 #line 296 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { (yyval.s) = (yyvsp[0].s); debug("switch %s", (yyvsp[0].s)); }
+    { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "switch %s", (yyvsp[0].s)); }
 #line 1721 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
diff --git a/engines/hypno/grammar_mis.y b/engines/hypno/grammar_mis.y
index 92fb87fd0d..3044e9ebf7 100644
--- a/engines/hypno/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -28,8 +28,8 @@
 %{
 
 #include "common/array.h"
-#include "hypno/grammar.h"
-#include <stdio.h>
+#include "hypno/hypno.h"
+//#include <stdio.h>
 
 #undef yyerror
 #define yyerror	 HYPNO_MIS_xerror
@@ -84,7 +84,7 @@ lines:   line RETTOK lines
 	| end lines
 	; 
 
-end: RETTOK  { debug("implicit END"); }
+end: RETTOK  { debugC(1, kHypnoDebugParser, "implicit END"); }
 	; 
 
 line: MENUTOK NAME mflag  {
@@ -92,7 +92,7 @@ line: MENUTOK NAME mflag  {
 		hot->type = MakeMenu;
 		hot->stype = $2;
 		hot->smenu = NULL;
-		debug("MENU %d.", hot->type);
+		debugC(1, kHypnoDebugParser, "MENU %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot);
 
@@ -107,7 +107,7 @@ line: MENUTOK NAME mflag  {
 		hot->type = MakeHotspot;
 		hot->smenu = NULL;
 		hot->rect = Common::Rect($3, $4, $5, $6);
-		debug("HOTS %d.", hot->type);
+		debugC(1, kHypnoDebugParser, "HOTS %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot); 
 	}
@@ -124,15 +124,15 @@ line: MENUTOK NAME mflag  {
 		smenu_idx.push_back(-1);
 		hot->smenu = new Hotspots();
 		stack.push_back(hot->smenu);
-		debug("SUBMENU"); 
+		debugC(1, kHypnoDebugParser, "SUBMENU"); 
 	}
 	|  ESCPTOK  {
 		Escape *a = new Escape();
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("ESC SUBMENU"); }
-	|  TIMETOK NUM  { debug("TIME %d", $2); } 
+		debugC(1, kHypnoDebugParser, "ESC SUBMENU"); }
+	|  TIMETOK NUM  { debugC(1, kHypnoDebugParser, "TIME %d", $2); } 
 	|  BACKTOK FILENAME NUM NUM gsswitch flag {
 		Background *a = new Background();
 		a->path = $2;
@@ -141,7 +141,7 @@ line: MENUTOK NAME mflag  {
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("BACK");
+		debugC(1, kHypnoDebugParser, "BACK");
 	}
 	|  GLOBTOK GSSWITCH NAME  { 
 		Global *a = new Global();
@@ -150,7 +150,7 @@ line: MENUTOK NAME mflag  {
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("GLOB."); 
+		debugC(1, kHypnoDebugParser, "GLOB"); 
 	}
 	|  AMBITOK FILENAME NUM NUM flag { 
 		Ambient *a = new Ambient();
@@ -160,7 +160,7 @@ line: MENUTOK NAME mflag  {
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);			
-		debug("AMBI %d %d.", $3, $4); }
+		debugC(1, kHypnoDebugParser, "AMBI %d %d", $3, $4); }
 	|  PLAYTOK FILENAME NUM NUM gsswitch flag { 
 		Play *a = new Play();
 		a->path = $2;
@@ -170,7 +170,7 @@ line: MENUTOK NAME mflag  {
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
-		debug("PLAY %s.", $2); }
+		debugC(1, kHypnoDebugParser, "PLAY %s.", $2); }
 	|  OVERTOK FILENAME NUM NUM flag { 
 		Overlay *a = new Overlay();
 		a->path = $2;
@@ -185,7 +185,7 @@ line: MENUTOK NAME mflag  {
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
-		debug("PALE");
+		debugC(1, kHypnoDebugParser, "PALE");
 	}
 	|  CUTSTOK FILENAME { 
 		Cutscene *a = new Cutscene();
@@ -193,7 +193,7 @@ line: MENUTOK NAME mflag  {
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
-		debug("CUTS %s.", $2); 
+		debugC(1, kHypnoDebugParser, "CUTS %s", $2); 
 	}
 	|  WALNTOK FILENAME NUM NUM gsswitch flag  { 
 		WalN *a = new WalN();
@@ -204,7 +204,7 @@ line: MENUTOK NAME mflag  {
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
-		debug("WALN %s %d %d.", $2, $3, $4); } 
+		debugC(1, kHypnoDebugParser, "WALN %s %d %d", $2, $3, $4); } 
 	|  MICETOK FILENAME NUM {
 		Mice *a = new Mice();
 		a->path = $2; 
@@ -218,9 +218,9 @@ line: MENUTOK NAME mflag  {
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(talk_action);
 		talk_action = nullptr;
-		debug("TALK"); }
+		debugC(1, kHypnoDebugParser, "TALK"); }
 	|  ENDTOK RETTOK { 
-		debug("explicit END");
+		debugC(1, kHypnoDebugParser, "explicit END");
 		g_parsedHots = stack.back(); 
 		stack.pop_back();
 		smenu_idx.pop_back();
@@ -235,53 +235,53 @@ alloctalk: {
 
 talk: INACTOK talk {
 		talk_action->active = false; 
-		debug("inactive"); }
-	| FDTOK talk { debug("inactive"); }
+		debugC(1, kHypnoDebugParser, "inactive"); }
+	| FDTOK talk { debugC(1, kHypnoDebugParser, "inactive"); }
 	| BACKTOK FILENAME NUM NUM gsswitch flag { 
 		talk_action->background = $2;
 		talk_action->position = Common::Point($3, $4);
-		debug("BACK in TALK"); }
-	| BOXXTOK NUM NUM { debug("BOXX %d %d", $2, $3); }
+		debugC(1, kHypnoDebugParser, "BACK in TALK"); }
+	| BOXXTOK NUM NUM { debugC(1, kHypnoDebugParser, "BOXX %d %d", $2, $3); }
 	| PG talk { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "G";
 		talk_cmd.path = $1+2;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("%s", $1); }
-	| PH talk { debug("%s", $1); }
+		debugC(1, kHypnoDebugParser, "%s", $1); }
+	| PH talk { debugC(1, kHypnoDebugParser, "%s", $1); }
 	| PF talk { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "F";
 		talk_cmd.num = atoi($1+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("%s", $1); }
+		debugC(1, kHypnoDebugParser, "%s", $1); }
 	| PA talk { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "A";
 		talk_cmd.num = atoi($1+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("|A%d", talk_cmd.num); } 
+		debugC(1, kHypnoDebugParser, "|A%d", talk_cmd.num); } 
 	| PD talk { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "D";
 		talk_cmd.num = atoi($1+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
-		debug("%s", $1); }
+		debugC(1, kHypnoDebugParser, "%s", $1); }
 	| PP NUM NUM talk { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "P";
 		talk_cmd.path = $1+2;
 		talk_cmd.position = Common::Point($2, $3);
 		talk_action->commands.push_back(talk_cmd);
-		debug("%s %d %d", $1, $2, $3); }
+		debugC(1, kHypnoDebugParser, "%s %d %d", $1, $2, $3); }
 	| PI NUM NUM talk { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "I";
 		talk_cmd.path = $1+2;
 		talk_cmd.position = Common::Point($2, $3);
 		talk_action->commands.push_back(talk_cmd);		  
-		debug("%s %d %d", $1, $2, $3); }
-	| PE { debug("|E"); }
+		debugC(1, kHypnoDebugParser, "%s %d %d", $1, $2, $3); }
+	| PE { debugC(1, kHypnoDebugParser, "|E"); }
 	| /*nothing*/
 	;
 
@@ -289,11 +289,11 @@ mflag:  NRTOK
 	| /*nothing*/
 	;
 
-flag:   FLAG 		{ $$ = $1; debug("flag: %s", $1); }
+flag:   FLAG 		{ $$ = $1; debugC(1, kHypnoDebugParser, "flag: %s", $1); }
 	| /* nothing */	{ $$ = scumm_strdup(""); }
 	;
 
-gsswitch: GSSWITCH 	{ $$ = $1; debug("switch %s", $1); }
+gsswitch: GSSWITCH 	{ $$ = $1; debugC(1, kHypnoDebugParser, "switch %s", $1); }
 	| /* nothing */ { $$ = scumm_strdup(""); }
 	;
 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index ef590138ae..03b66bf989 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -95,11 +95,12 @@ void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
 	SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
 }
 
-LibFile *HypnoEngine::loadLib(const Filename &prefix, const Filename &filename) {
+LibFile *HypnoEngine::loadLib(const Filename &prefix, const Filename &filename, bool encrypted) {
 	LibFile *lib = new LibFile();
 	SearchMan.add(filename, (Common::Archive *)lib, 0, true);
-	if (!lib->open(prefix, filename))
-		error("Failed to open %s%s", prefix.c_str(), filename.c_str());
+	if (!lib->open(prefix, filename, encrypted)) {
+		return nullptr;
+	}
 	_archive.push_back(lib);
 	return lib;
 }
@@ -229,7 +230,7 @@ void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool trans
 
 void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transparent) {
 	if (transparent) {
-		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), surf.getPixel(surf.w - 1, surf.h - 1));
+		_compositeSurface->transBlitFrom(surf, Common::Point(x, y), surf.getPixel(0, 0));
 	} else
 		_compositeSurface->blitFrom(surf, Common::Point(x, y));
 }
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 518a0d7404..dfe894e3e1 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -90,10 +90,13 @@ public:
 	void clearAreas();
 	void initializePath(const Common::FSNode &gamePath) override;
 	virtual void loadAssets();
+
+	// Parsing
+	void splitArcadeFile(const Common::String &filename, Common::String &arc, Common::String &list);
 	void parseScene(const Common::String &prefix, const Common::String &filename);
 	void parseArcadeShooting(const Common::String &prefix, const Common::String &name, const Common::String &data);
 	ShootSequence parseShootList(const Common::String &name, const Common::String &data);
-	LibFile *loadLib(const Filename &prefix, const Filename &filename);
+	LibFile *loadLib(const Filename &prefix, const Filename &filename, bool encrypted);
 
 	// User input
 	void clickedHotspot(Common::Point);
@@ -226,6 +229,9 @@ public:
 	WetEngine(OSystem *syst, const ADGameDescription *gd);
 
 	void loadAssets() override;
+	void loadAssetsDemoDisc();
+	void loadAssetsPCW();
+	void loadAssetsPCG();
 	void showCredits() override;
 	bool clickedSecondaryShoot(const Common::Point &mousePos) override;
 	void drawShoot(const Common::Point &target) override;
diff --git a/engines/hypno/lexer_arc.cpp b/engines/hypno/lexer_arc.cpp
index 013e5db95b..5f0b23b365 100644
--- a/engines/hypno/lexer_arc.cpp
+++ b/engines/hypno/lexer_arc.cpp
@@ -633,8 +633,8 @@ static void yynoreturn yy_fatal_error ( const char* msg  );
 	(yy_hold_char) = *yy_cp; \
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 37
-#define YY_END_OF_BUFFER 38
+#define YY_NUM_RULES 38
+#define YY_END_OF_BUFFER 39
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -642,37 +642,37 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static const flex_int16_t yy_accept[55] =
+static const flex_int16_t yy_accept[59] =
     {   0,
-        0,    0,   38,   36,   34,   35,   32,   36,   31,   31,
-        7,   29,    2,    3,   29,   21,    5,   13,   29,   11,
-        9,    6,   14,   12,   29,   18,    8,   16,   17,   29,
-       15,   29,   33,   35,   31,   31,   30,   23,   29,   24,
-       20,    4,   25,   29,   10,   26,   22,   19,   27,   29,
-       28,   29,    1,    0
+        0,    0,   39,   37,   34,   36,   32,   32,   37,   31,
+       31,   37,    7,   29,    2,    3,   29,   21,    5,   13,
+       29,   11,    9,    6,   14,   12,   29,   18,    8,   16,
+       17,   29,   15,   29,   33,   36,   31,   31,    0,   30,
+       23,   29,   24,   20,    4,   25,   29,   10,   26,   22,
+       19,   27,   29,   28,   35,   29,    1,    0
     } ;
 
 static const YY_CHAR yy_ec[256] =
     {   0,
         1,    2,    1,    1,    1,    1,    1,    1,    3,    4,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    5,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    3,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    5,    6,    1,    7,    8,    9,
-       10,   10,   10,   10,   10,   10,   10,    1,    1,    1,
-        1,    1,    1,    1,   11,   12,   13,   14,   15,   16,
-       17,   18,   19,   17,   20,   17,   17,   21,   22,   23,
-       24,   25,   26,   27,   17,   28,   29,   30,   31,   32,
-        1,    6,    1,    1,   33,    1,   34,   34,   34,   34,
-
-       34,   34,   34,   34,   34,   34,   35,   34,   34,   34,
-       34,   36,   34,   34,   34,   34,   34,   34,   34,   34,
-       34,   34,    1,   37,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    6,    7,    1,    8,    9,   10,
+       11,   11,   11,   11,   11,   11,   11,    1,   12,    1,
+        1,    1,    1,    1,   13,   14,   15,   16,   17,   18,
+       19,   20,   21,   19,   22,   19,   19,   23,   24,   25,
+       26,   27,   28,   29,   19,   30,   31,   32,   33,   34,
+        1,    7,    1,    1,   35,    1,   36,   36,   36,   36,
+
+       36,   36,   36,   36,   36,   36,   37,   36,   36,   36,
+       36,   38,   36,   36,   36,   36,   36,   36,   36,   36,
+       36,   36,    1,   39,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,   38,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,   40,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
 
@@ -684,87 +684,89 @@ static const YY_CHAR yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static const YY_CHAR yy_meta[39] =
+static const YY_CHAR yy_meta[41] =
     {   0,
-        1,    1,    1,    1,    1,    2,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    1,    1
+        1,    1,    1,    2,    1,    1,    3,    4,    4,    4,
+        4,    1,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
+        4,    4,    4,    4,    4,    4,    4,    4,    1,    1
     } ;
 
-static const flex_int16_t yy_base[59] =
+static const flex_int16_t yy_base[64] =
     {   0,
-        0,    0,  123,  146,  146,  118,  146,   32,   36,   40,
-       45,   47,  114,  113,  112,   52,   57,  111,   58,   60,
-       61,   64,  110,  109,   67,   62,  108,  107,   98,   72,
-       97,    0,  146,   99,   76,  102,    0,   95,   94,   93,
-       91,   90,   89,   73,   87,   86,   85,   84,   82,    0,
-      146,   74,   81,  146,  138,  140,   78,  142
+        0,    0,  127,  148,  148,  123,  148,  148,   33,   37,
+       41,    0,   46,   48,  118,  117,  116,   53,   58,  115,
+       59,   61,   62,   65,  114,  112,   69,   63,  111,  110,
+      109,   67,  108,    0,  148,  111,   73,   98,  108,    0,
+      105,  104,   93,   92,   91,   90,   87,   88,   86,   85,
+       84,   83,    0,  148,   84,   79,   81,  148,  137,  139,
+      141,   83,  143
     } ;
 
-static const flex_int16_t yy_def[59] =
+static const flex_int16_t yy_def[64] =
     {   0,
-       54,    1,   54,   54,   54,   54,   54,   54,   54,   54,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   56,
-       55,   57,   54,   54,   54,   54,   58,   55,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,   55,   57,
-       54,   55,   55,    0,   54,   54,   54,   54
+       58,    1,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   59,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   61,   60,   62,   58,   58,   58,   58,   59,   63,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   62,   58,   59,   60,   60,    0,   58,   58,
+       58,   58,   58
     } ;
 
-static const flex_int16_t yy_nxt[185] =
+static const flex_int16_t yy_nxt[189] =
     {   0,
-        4,    5,    6,    7,    8,    4,    9,    9,   10,    9,
-       11,   12,   13,   14,   15,   16,   15,   17,   18,   19,
+        4,    5,    6,    7,    8,    9,    4,   10,   10,   11,
+       10,   12,   13,   14,   15,   16,   17,   18,   17,   19,
        20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
-       30,   31,   32,   15,   15,   15,    4,   33,   35,   35,
-       35,   35,   35,   35,   35,   35,   35,   35,   36,   35,
-       37,   38,   37,   40,   40,   40,   40,   37,   41,   41,
-       41,   41,   37,   37,   43,   37,   37,   37,   45,   37,
-       46,   42,   37,   47,   47,   47,   47,   37,   37,   37,
-       50,   44,   35,   35,   35,   35,   37,   37,   53,   37,
-       37,   37,   37,   52,   37,   37,   37,   48,   37,   37,
-
-       37,   34,   37,   37,   39,   39,   39,   39,   35,   35,
-       35,   35,   37,   37,   37,   37,   37,   37,   37,   37,
-       34,   51,   54,   54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   51,   54,   51,   39,
-       39,   49,   49,   37,   37,    3,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54
+       30,   31,   32,   33,   34,   17,   17,   17,    8,   35,
+       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
+       38,   37,   40,   41,   40,   43,   43,   43,   43,   40,
+       44,   44,   44,   44,   40,   40,   46,   40,   40,   40,
+       48,   40,   49,   40,   45,   40,   50,   50,   50,   50,
+       37,   37,   37,   37,   47,   40,   53,   40,   55,   40,
+       40,   40,   40,   40,   40,   57,   40,   40,   40,   40,
+
+       51,   42,   42,   42,   42,   37,   37,   37,   37,   56,
+       40,   40,   55,   36,   40,   40,   40,   40,   40,   54,
+       40,   40,   40,   40,   40,   36,   58,   58,   58,   58,
+       58,   58,   58,   58,   54,   58,   54,   39,   58,   39,
+       39,   42,   42,   52,   52,   40,   40,    3,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58
     } ;
 
-static const flex_int16_t yy_chk[185] =
+static const flex_int16_t yy_chk[189] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    8,    8,
-        8,    8,    9,    9,    9,    9,   10,   10,   10,   10,
-       11,   11,   12,   12,   12,   12,   12,   16,   16,   16,
-       16,   16,   17,   19,   19,   20,   21,   26,   21,   22,
-       22,   17,   25,   25,   25,   25,   25,   30,   44,   52,
-       57,   20,   35,   35,   35,   35,   53,   49,   52,   48,
-       47,   46,   45,   44,   43,   42,   41,   26,   40,   39,
-
-       38,   34,   31,   29,   30,   30,   30,   30,   36,   36,
-       36,   36,   28,   27,   24,   23,   18,   15,   14,   13,
-        6,   36,    3,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   36,    0,   36,   55,
-       55,   56,   56,   58,   58,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
-       54,   54,   54,   54
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        9,    9,    9,    9,   10,   10,   10,   10,   11,   11,
+       11,   11,   13,   13,   14,   14,   14,   14,   14,   18,
+       18,   18,   18,   18,   19,   21,   21,   22,   23,   28,
+       23,   24,   24,   32,   19,   27,   27,   27,   27,   27,
+       37,   37,   37,   37,   22,   56,   62,   57,   55,   52,
+       51,   50,   49,   47,   48,   56,   46,   45,   44,   43,
+
+       28,   32,   32,   32,   32,   38,   38,   38,   38,   47,
+       42,   41,   39,   36,   33,   31,   30,   29,   26,   38,
+       25,   20,   17,   16,   15,    6,    3,    0,    0,    0,
+        0,    0,    0,    0,   38,    0,   38,   59,    0,   59,
+       59,   60,   60,   61,   61,   63,   63,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   58,   58,   58,   58,   58,   58,   58
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static const flex_int32_t yy_rule_can_match_eol[38] =
+static const flex_int32_t yy_rule_can_match_eol[39] =
     {   0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,     };
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,     };
 
 static yy_state_type yy_last_accepting_state;
 static char *yy_last_accepting_cpos;
@@ -806,13 +808,14 @@ char *yytext;
 #line 33 "engines/hypno/lexer_arc.l"
 #define YY_NO_UNISTD_H
 #define FORBIDDEN_SYMBOL_ALLOW_ALL
+#define YYERROR_VERBOSE
 
 #include "hypno/hypno.h"
 #include "hypno/grammar.h"
 #include "hypno/tokens_arc.h"
 
-#line 815 "engines/hypno/lexer_arc.cpp"
-#line 816 "engines/hypno/lexer_arc.cpp"
+#line 818 "engines/hypno/lexer_arc.cpp"
+#line 819 "engines/hypno/lexer_arc.cpp"
 
 #define INITIAL 0
 
@@ -1027,9 +1030,9 @@ YY_DECL
 		}
 
 	{
-#line 42 "engines/hypno/lexer_arc.l"
+#line 43 "engines/hypno/lexer_arc.l"
 
-#line 1033 "engines/hypno/lexer_arc.cpp"
+#line 1036 "engines/hypno/lexer_arc.cpp"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -1056,13 +1059,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 55 )
+				if ( yy_current_state >= 59 )
 					yy_c = yy_meta[yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 54 );
+		while ( yy_current_state != 58 );
 		yy_cp = (yy_last_accepting_cpos);
 		yy_current_state = (yy_last_accepting_state);
 
@@ -1094,191 +1097,196 @@ do_action:	/* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 43 "engines/hypno/lexer_arc.l"
+#line 44 "engines/hypno/lexer_arc.l"
 return NONETOK;
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 44 "engines/hypno/lexer_arc.l"
+#line 45 "engines/hypno/lexer_arc.l"
 return CTOK;
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 45 "engines/hypno/lexer_arc.l"
+#line 46 "engines/hypno/lexer_arc.l"
 return DTOK;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 46 "engines/hypno/lexer_arc.l"
+#line 47 "engines/hypno/lexer_arc.l"
 return HETOK;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 47 "engines/hypno/lexer_arc.l"
+#line 48 "engines/hypno/lexer_arc.l"
 return HTOK;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 48 "engines/hypno/lexer_arc.l"
+#line 49 "engines/hypno/lexer_arc.l"
 return PTOK;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 49 "engines/hypno/lexer_arc.l"
+#line 50 "engines/hypno/lexer_arc.l"
 return ATOK;
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 50 "engines/hypno/lexer_arc.l"
+#line 51 "engines/hypno/lexer_arc.l"
 return VTOK;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 51 "engines/hypno/lexer_arc.l"
+#line 52 "engines/hypno/lexer_arc.l"
 return OTOK;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 52 "engines/hypno/lexer_arc.l"
+#line 53 "engines/hypno/lexer_arc.l"
 return O1TOK;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 53 "engines/hypno/lexer_arc.l"
+#line 54 "engines/hypno/lexer_arc.l"
 return NTOK;
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 54 "engines/hypno/lexer_arc.l"
+#line 55 "engines/hypno/lexer_arc.l"
 return RTOK;
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 55 "engines/hypno/lexer_arc.l"
+#line 56 "engines/hypno/lexer_arc.l"
 return ITOK;
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 56 "engines/hypno/lexer_arc.l"
+#line 57 "engines/hypno/lexer_arc.l"
 return QTOK;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 57 "engines/hypno/lexer_arc.l"
+#line 58 "engines/hypno/lexer_arc.l"
 return ZTOK;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 58 "engines/hypno/lexer_arc.l"
+#line 59 "engines/hypno/lexer_arc.l"
 return WTOK;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 59 "engines/hypno/lexer_arc.l"
+#line 60 "engines/hypno/lexer_arc.l"
 return XTOK;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 60 "engines/hypno/lexer_arc.l"
+#line 61 "engines/hypno/lexer_arc.l"
 return TTOK;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 61 "engines/hypno/lexer_arc.l"
+#line 62 "engines/hypno/lexer_arc.l"
 return TPTOK;
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 62 "engines/hypno/lexer_arc.l"
+#line 63 "engines/hypno/lexer_arc.l"
 return FNTOK;
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 63 "engines/hypno/lexer_arc.l"
+#line 64 "engines/hypno/lexer_arc.l"
 return FTOK;
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 64 "engines/hypno/lexer_arc.l"
+#line 65 "engines/hypno/lexer_arc.l"
 HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return SNTOK;
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 65 "engines/hypno/lexer_arc.l"
+#line 66 "engines/hypno/lexer_arc.l"
 return A0TOK;
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 66 "engines/hypno/lexer_arc.l"
+#line 67 "engines/hypno/lexer_arc.l"
 HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 67 "engines/hypno/lexer_arc.l"
+#line 68 "engines/hypno/lexer_arc.l"
 return K0TOK;
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 68 "engines/hypno/lexer_arc.l"
+#line 69 "engines/hypno/lexer_arc.l"
 return P0TOK;
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 69 "engines/hypno/lexer_arc.l"
+#line 70 "engines/hypno/lexer_arc.l"
 return YXTOK;
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 70 "engines/hypno/lexer_arc.l"
+#line 71 "engines/hypno/lexer_arc.l"
 return ENCTOK;
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 71 "engines/hypno/lexer_arc.l"
+#line 72 "engines/hypno/lexer_arc.l"
 HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 72 "engines/hypno/lexer_arc.l"
+#line 73 "engines/hypno/lexer_arc.l"
 HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 73 "engines/hypno/lexer_arc.l"
+#line 74 "engines/hypno/lexer_arc.l"
 HYPNO_ARC_lval.i = atoi(HYPNO_ARC_text); return NUM;
 	YY_BREAK
 case 32:
 /* rule 32 can match eol */
 YY_RULE_SETUP
-#line 74 "engines/hypno/lexer_arc.l"
+#line 75 "engines/hypno/lexer_arc.l"
 return RETTOK;
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 75 "engines/hypno/lexer_arc.l"
+#line 76 "engines/hypno/lexer_arc.l"
 return CB3TOK;
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 76 "engines/hypno/lexer_arc.l"
+#line 77 "engines/hypno/lexer_arc.l"
 return C02TOK;
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 77 "engines/hypno/lexer_arc.l"
-/* ignore whitespace */;
+#line 78 "engines/hypno/lexer_arc.l"
+/* ignore comment */
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 78 "engines/hypno/lexer_arc.l"
-debug("notparsed: 0x%d",*yytext); return *yytext;
+#line 79 "engines/hypno/lexer_arc.l"
+/* ignore whitespace */;
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 79 "engines/hypno/lexer_arc.l"
+#line 80 "engines/hypno/lexer_arc.l"
+debug("notparsed: 0x%d",*yytext); return *yytext;
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 81 "engines/hypno/lexer_arc.l"
 ECHO;
 	YY_BREAK
-#line 1282 "engines/hypno/lexer_arc.cpp"
+#line 1290 "engines/hypno/lexer_arc.cpp"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -1576,7 +1584,7 @@ static int yy_get_next_buffer (void)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 55 )
+			if ( yy_current_state >= 59 )
 				yy_c = yy_meta[yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1604,11 +1612,11 @@ static int yy_get_next_buffer (void)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 55 )
+		if ( yy_current_state >= 59 )
 			yy_c = yy_meta[yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
-	yy_is_jam = (yy_current_state == 54);
+	yy_is_jam = (yy_current_state == 58);
 
 		return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2255,12 +2263,13 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 79 "engines/hypno/lexer_arc.l"
+#line 81 "engines/hypno/lexer_arc.l"
 
 
 namespace Hypno {
 
 int parse_arc(const char *code) {
+	//debug("to parse:\n%s\n END", code);
 	YY_BUFFER_STATE bp;
 	yy_delete_buffer(YY_CURRENT_BUFFER);
 	bp = yy_scan_string(code);
diff --git a/engines/hypno/lexer_arc.l b/engines/hypno/lexer_arc.l
index 1885a5523a..38aba61ab7 100644
--- a/engines/hypno/lexer_arc.l
+++ b/engines/hypno/lexer_arc.l
@@ -32,6 +32,7 @@
 %{
 #define YY_NO_UNISTD_H
 #define FORBIDDEN_SYMBOL_ALLOW_ALL
+#define YYERROR_VERBOSE
 
 #include "hypno/hypno.h"
 #include "hypno/grammar.h"
@@ -71,9 +72,10 @@ Y[A-Z0-9]					return YXTOK;
 [A-Za-z_][A-Za-z_0-9]*		HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return NAME;
 [A-Za-z][A-Za-z_0-9\\\.]*	HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return FILENAME;
 [\-]?[0-9]+					HYPNO_ARC_lval.i = atoi(HYPNO_ARC_text); return NUM;
-\n							return RETTOK;
+[\n|\r\n]					return RETTOK;
 \xb3						return CB3TOK;
 \x02						return C02TOK;
+\;.+\r						/* ignore comment */
 [ \t]+						/* ignore whitespace */;
 .							debug("notparsed: 0x%d",*yytext); return *yytext;
 %%
@@ -81,6 +83,7 @@ Y[A-Z0-9]					return YXTOK;
 namespace Hypno {
 
 int parse_arc(const char *code) {
+	//debug("to parse:\n%s\n END", code);
 	YY_BUFFER_STATE bp;
 	yy_delete_buffer(YY_CURRENT_BUFFER);
 	bp = yy_scan_string(code);
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 57239f2e95..8a953a795e 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -31,11 +31,13 @@ LibFile::LibFile() : Common::Archive() {
 LibFile::~LibFile() {
 }
 
-bool LibFile::open(const Common::String &prefix, const Common::String &filename) {
+bool LibFile::open(const Common::String &prefix, const Common::String &filename, bool encrypted) {
 	_prefix = prefix;
 	Common::File libfile;
-	if (!libfile.open(filename))
-		error("Failed to open %s", filename.c_str());
+	if (!libfile.open(filename)) {
+		warning("Failed to open %s", filename.c_str());
+		return false;
+	}
 	byte b;
 	uint32 size;
 	FileEntry f;
@@ -58,10 +60,12 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename)
 
 		for (uint32 i = 0; i < size; i++) {
 			b = libfile.readByte();
-			if (b != '\n')
+			if (encrypted && b != '\n')
 				b = b ^ 0xfe;
 			f.data.push_back(b);
 		}
+		f.data.push_back(0x0);
+		//debug("f.data: %s", f.data.data());
 		debugC(1, kHypnoDebugParser, "size: %d", f.data.size());
 		libfile.seek(pos);
 		if (size > 0)
diff --git a/engines/hypno/libfile.h b/engines/hypno/libfile.h
index f312ae6ac5..81fcb1a91f 100644
--- a/engines/hypno/libfile.h
+++ b/engines/hypno/libfile.h
@@ -42,7 +42,7 @@ public:
 	LibFile();
 	~LibFile() override;
 
-	bool open(const Common::String &prefix, const Common::String &filename);
+	bool open(const Common::String &prefix, const Common::String &filename, bool encrypted);
 	void close();
 
 	// Common::Archive API implementation
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 481f6df886..80fffe4859 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -16,8 +16,8 @@ void SpiderEngine::loadAssets() {
 	SearchMan.add("DATA.Z", (Common::Archive *) &_installerArchive, 0, false);
 
 	Common::ArchiveMemberList files;
-	LibFile *missions = loadLib("", "sixdemo/c_misc/missions.lib");
-	if (missions->listMembers(files) == 0)
+	LibFile *missions = loadLib("", "sixdemo/c_misc/missions.lib", true);
+	if (missions == nullptr || missions->listMembers(files) == 0)
 		error("Failed to load any file from missions.lib");
 
 	// start level
@@ -54,9 +54,9 @@ void SpiderEngine::loadAssets() {
 	_levels[arclevel].arcade.levelIfWin = "sixdemo/mis/demo.mis";
 	_levels[arclevel].arcade.levelIfLose = "sixdemo/mis/demo.mis";
 
-	loadLib("", "sixdemo/c_misc/fonts.lib");
-	loadLib("sixdemo/c_misc/sound.lib/", "sixdemo/c_misc/sound.lib");
-	loadLib("sixdemo/demo/sound.lib/", "sixdemo/demo/sound.lib");
+	loadLib("", "sixdemo/c_misc/fonts.lib", true);
+	loadLib("sixdemo/c_misc/sound.lib/", "sixdemo/c_misc/sound.lib", true);
+	loadLib("sixdemo/demo/sound.lib/", "sixdemo/demo/sound.lib", true);
 
 	// Read assets from mis files
 	parseScene("sixdemo", "mis/demo.mis");
diff --git a/engines/hypno/tokens_arc.h b/engines/hypno/tokens_arc.h
index 3324dfe21f..b2a4960476 100644
--- a/engines/hypno/tokens_arc.h
+++ b/engines/hypno/tokens_arc.h
@@ -58,35 +58,36 @@ extern int HYPNO_ARC_debug;
     BNTOK = 260,
     SNTOK = 261,
     NUM = 262,
-    YXTOK = 263,
-    CTOK = 264,
-    DTOK = 265,
-    HTOK = 266,
-    HETOK = 267,
-    RETTOK = 268,
-    QTOK = 269,
-    ENCTOK = 270,
-    PTOK = 271,
-    FTOK = 272,
-    TTOK = 273,
-    TPTOK = 274,
-    ATOK = 275,
-    VTOK = 276,
-    OTOK = 277,
-    O1TOK = 278,
-    NTOK = 279,
-    RTOK = 280,
-    ITOK = 281,
-    ZTOK = 282,
-    FNTOK = 283,
-    NONETOK = 284,
-    A0TOK = 285,
-    K0TOK = 286,
-    P0TOK = 287,
-    WTOK = 288,
-    XTOK = 289,
-    CB3TOK = 290,
-    C02TOK = 291
+    COMMENT = 263,
+    YXTOK = 264,
+    CTOK = 265,
+    DTOK = 266,
+    HTOK = 267,
+    HETOK = 268,
+    RETTOK = 269,
+    QTOK = 270,
+    ENCTOK = 271,
+    PTOK = 272,
+    FTOK = 273,
+    TTOK = 274,
+    TPTOK = 275,
+    ATOK = 276,
+    VTOK = 277,
+    OTOK = 278,
+    O1TOK = 279,
+    NTOK = 280,
+    RTOK = 281,
+    ITOK = 282,
+    ZTOK = 283,
+    FNTOK = 284,
+    NONETOK = 285,
+    A0TOK = 286,
+    K0TOK = 287,
+    P0TOK = 288,
+    WTOK = 289,
+    XTOK = 290,
+    CB3TOK = 291,
+    C02TOK = 292
   };
 #endif
 
@@ -95,12 +96,12 @@ extern int HYPNO_ARC_debug;
 
 union HYPNO_ARC_STYPE
 {
-#line 55 "engines/hypno/grammar_arc.y" /* yacc.c:1909  */
+#line 54 "engines/hypno/grammar_arc.y" /* yacc.c:1909  */
 
 	char *s; /* string value */
 	int i;	 /* integer value */
 
-#line 104 "engines/hypno/tokens_arc.h" /* yacc.c:1909  */
+#line 105 "engines/hypno/tokens_arc.h" /* yacc.c:1909  */
 };
 
 typedef union HYPNO_ARC_STYPE HYPNO_ARC_STYPE;
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 8fb66f7163..50e7f3c2bb 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -27,24 +27,24 @@ namespace Hypno {
 WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void WetEngine::loadAssets() {
-	LibFile *missions = loadLib("", "wetlands/c_misc/missions.lib");
+	Common::String demoVersion = "Wetlands Demo Disc";
+	if (demoVersion == "Wetlands Demo Disc")
+		loadAssetsDemoDisc();
+	else if (demoVersion == "Personal Computer World Disc")
+		loadAssetsPCW();
+	else if (demoVersion == "Personal Computer Gamer Disc")
+		loadAssetsPCG();
+	else
+		error("Invalid demo version: \"%s\"", demoVersion.c_str());
+}
+
+
+void WetEngine::loadAssetsDemoDisc() {
+	LibFile *missions = loadLib("", "wetlands/c_misc/missions.lib", true);
 	Common::ArchiveMemberList files;
 	if (missions->listMembers(files) == 0)
 		error("Failed to load any files from missions.lib");
 
-	// We need the list of files in an array, instead of a list
-	Common::Array<Common::ArchiveMemberPtr> afiles;
-	afiles.reserve(files.size());
-	for (Common::ArchiveMemberList::const_iterator it = files.begin(); it != files.end(); ++it) {
-		afiles.push_back(*it);
-	}
-
-	uint32 k = 0;
-
-	Common::String arc;
-	Common::String list;
-	Common::String arclevel;
-
 	Level start;
 	Hotspot h;
 	Hotspots hs;
@@ -69,6 +69,14 @@ void WetEngine::loadAssets() {
 
 	hs.push_back(h);
 
+	h.rect = Common::Rect(242, 424, 500, 480);
+	cl = new ChangeLevel();
+	cl->level = "<movies>";
+	h.actions.clear();
+	h.actions.push_back(cl);
+
+	hs.push_back(h);
+
 	h.rect = Common::Rect(504, 424, 637, 480);
 	Quit *q = new Quit();
 	h.actions.clear();
@@ -80,7 +88,7 @@ void WetEngine::loadAssets() {
 	_levels["<start>"] = start;
 
 	Level intro;
-	intro.trans.level = afiles[0]->getName();
+	intro.trans.level = "c31.mi_";
 	intro.trans.intros.push_back("movie/nw_logo.smk");
 	intro.trans.intros.push_back("movie/hypnotix.smk");
 	intro.trans.intros.push_back("movie/wetlogo.smk");
@@ -88,51 +96,130 @@ void WetEngine::loadAssets() {
 	intro.trans.frameNumber = 0;
 	_levels["<intro>"] = intro;
 
-	for (k = 0; k < afiles.size(); k++) {
-		arc.clear();
-		list.clear();
-		arclevel = afiles[k]->getName();
-		debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
-		Common::SeekableReadStream *file = afiles[k]->createReadStream();
-		while (!file->eos()) {
-			byte x = file->readByte();
-			arc += x;
-			if (x == 'X') {
-				while (!file->eos()) {
-					x = file->readByte();
-					if (x == 'Y')
-						break;
-					list += x;
-				}
-				break; // No need to keep parsing
-			}
-		}
-		delete file;
-
-		parseArcadeShooting("wetlands", arclevel, arc);
-		_levels[arclevel].arcade.id = k;
-		_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-		_levels[arclevel].arcade.prefix = "wetlands";
-		if (k < files.size() - 1) {
-			_levels[arclevel].arcade.levelIfWin = afiles[k + 1]->getName();
-			// failing a level in the demo takes you to the next one anyway
-			_levels[arclevel].arcade.levelIfLose = afiles[k + 1]->getName();
-		}
-	}
-
-	// After finish the second level, it's always game over
-	_levels[afiles[k - 1]->getName()].arcade.levelIfWin = "<gameover>";
-	_levels[afiles[k - 1]->getName()].arcade.levelIfLose = "<gameover>";
+	Level movies;
+	movies.trans.level = "<quit>";
+	movies.trans.intros.push_back("movie/nw_logo.smk");
+	movies.trans.intros.push_back("movie/hypnotix.smk");
+	movies.trans.intros.push_back("movie/wetlogo.smk");
+	movies.trans.intros.push_back("movie/c42e1s.smk");
+	movies.trans.intros.push_back("movie/c23e1s.smk");
+	movies.trans.intros.push_back("movie/c20o1s.smk");
+	movies.trans.intros.push_back("movie/c23d1s.smk");
+	movies.trans.intros.push_back("movie/c40o1s.smk");
+	movies.trans.intros.push_back("movie/c31d1s.smk");
+	movies.trans.intros.push_back("movie/c42d1s.smk");
+	movies.trans.intros.push_back("movie/c44d1s.smk");
+	movies.trans.intros.push_back("movie/c44e1s.smk");
+	movies.trans.intros.push_back("movie/c32d1s.smk");
+	movies.trans.intros.push_back("movie/c22e1s.smk");
+	movies.trans.intros.push_back("movie/c31e1s.smk");
+	movies.trans.intros.push_back("movie/gameover.smk");
+	movies.trans.frameImage = "";
+	movies.trans.frameNumber = 0;
+	_levels["<movies>"] = movies;
+
+	Common::String arclevel = "c31.mi_";
+	debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
+	Common::String arc;
+	Common::String list;
+	splitArcadeFile(arclevel, arc, list);
+	parseArcadeShooting("wetlands", arclevel, arc);
+	_levels[arclevel].arcade.id = 0;
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.prefix = "wetlands";
+	_levels[arclevel].arcade.levelIfWin = "c52.mi_";
+	_levels[arclevel].arcade.levelIfLose = "c52.mi_";
+
+	arclevel = "c52.mi_";
+	arc.clear();
+	list.clear();
+	splitArcadeFile(arclevel, arc, list);
+	parseArcadeShooting("wetlands", arclevel, arc);
+	_levels[arclevel].arcade.id = 1;
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.prefix = "wetlands";
+	_levels[arclevel].arcade.levelIfWin = "<gameover>";
+	_levels[arclevel].arcade.levelIfLose = "<gameover>";
 
 	Level over;
 	over.trans.level = "<quit>";
 	over.trans.intros.push_back("movie/gameover.smk");
 	_levels["<gameover>"] = over;
 
-	loadLib("", "wetlands/c_misc/fonts.lib");
-	loadLib("wetlands/sound/", "wetlands/c_misc/sound.lib");
+	loadLib("", "wetlands/c_misc/fonts.lib", true);
+	loadLib("wetlands/sound/", "wetlands/c_misc/sound.lib", true);
 }
 
+void WetEngine::loadAssetsPCW() {
+
+	LibFile *missions = loadLib("", "c_misc/missions.lib", false);
+	Common::ArchiveMemberList files;
+	if (missions->listMembers(files) == 0)
+		error("Failed to load any files from missions.lib");
+
+	Level intro;
+	intro.trans.level = "c11.mis";
+	intro.trans.intros.push_back("c_misc/nw_logo.smk");
+	intro.trans.intros.push_back("c_misc/h.s");
+	intro.trans.intros.push_back("c_misc/wet.smk");
+	intro.trans.frameImage.clear();
+	_levels["<start>"] = intro;
+
+	Common::String arclevel = "c11.mis";
+	Common::String arc;
+	Common::String list;
+	splitArcadeFile(arclevel, arc, list);
+	parseArcadeShooting("wetlands", arclevel, arc);
+	_levels[arclevel].arcade.id = 0;
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.prefix = "";
+	_levels[arclevel].arcade.levelIfWin = "<gameover>";
+	_levels[arclevel].arcade.levelIfLose = "<gameover>";
+
+	Level over;
+	over.trans.level = "<quit>";
+	over.trans.intros.push_back("movie/gameover.smk");
+	_levels["<gameover>"] = over;
+
+	loadLib("", "c_misc/sound.lib", false);
+}
+
+void WetEngine::loadAssetsPCG() {
+
+	LibFile *missions = loadLib("", "missions.lib", false);
+	Common::ArchiveMemberList files;
+	if (missions->listMembers(files) == 0)
+		error("Failed to load any files from missions.lib");
+
+	Level intro;
+	intro.trans.level = "c31.mi_";
+	intro.trans.intros.push_back("nw_logo.smk");
+	intro.trans.intros.push_back("h.s");
+	intro.trans.intros.push_back("wet.smk");
+	intro.trans.frameImage.clear();
+	_levels["<start>"] = intro;
+
+	Common::String arclevel = "c31.mi_";
+	debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
+	Common::String arc;
+	Common::String list;
+	splitArcadeFile(arclevel, arc, list);
+	parseArcadeShooting("wetlands", arclevel, arc);
+	_levels[arclevel].arcade.id = 0;
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.prefix = "";
+	_levels[arclevel].arcade.levelIfWin = "<gameover>";
+	_levels[arclevel].arcade.levelIfLose = "<gameover>";
+
+	Level over;
+	over.trans.level = "<quit>";
+	over.trans.intros.push_back("gameover.smk");
+	_levels["<gameover>"] = over;
+
+	loadLib("", "sound.lib", false);
+}
+
+
 void WetEngine::showCredits() {
 	MVideo video("c_misc/credits.smk", Common::Point(0, 0), false, false, false);
 	runIntro(video);


Commit: 5a0e34e41e5cd7bd5e0f10573fd385db263167c8
    https://github.com/scummvm/scummvm/commit/5a0e34e41e5cd7bd5e0f10573fd385db263167c8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: started basic support for full versions and some fixes

Changed paths:
    engines/hypno/boyz/boyz.cpp
    engines/hypno/detection.cpp
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/lexer_arc.cpp
    engines/hypno/lexer_arc.l
    engines/hypno/metaengine.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/boyz/boyz.cpp b/engines/hypno/boyz/boyz.cpp
index d2d251eb2b..3edeb638ae 100644
--- a/engines/hypno/boyz/boyz.cpp
+++ b/engines/hypno/boyz/boyz.cpp
@@ -30,7 +30,10 @@ namespace Hypno {
 BoyzEngine::BoyzEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void BoyzEngine::loadAssets() {
-	loadLib("", "boyz/preload/missions.lib", true);
+	LibFile *missions = loadLib("", "boyz/preload/missions.lib", true);
+	Common::ArchiveMemberList files;
+	if (missions->listMembers(files) == 0)
+		error("Failed to load any files from missions.lib");
 }
 
 } // namespace Hypno
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 7055e3d52c..1a77e7a230 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -84,10 +84,26 @@ static const ADGameDescription gameDescriptions[] = {
 	{"wetlands", // Wetlands (US)
 	 "",
 	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 647447,
-				"install.exe", "15a6b1b3819ef002438df340509b5373", 477839),
+				"missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
-	 ADGF_UNSUPPORTED,
+	 ADGF_TESTING,
+	 GUIO1(GUIO_NOMIDI)},
+	{"wetlands", // Wetlands (FR)
+	 "",
+	 AD_ENTRY2s("wetlands.exe", "edc5b0c0caf3d5b01d344cb555d9a085", 629575,
+			    "missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
+	 Common::FR_FRA,
+	 Common::kPlatformDOS,
+	 ADGF_TESTING,
+	 GUIO1(GUIO_NOMIDI)},
+	{"wetlands", // Wetlands (ES)
+	 "",
+	 AD_ENTRY2s("wetlands.exe", "8d0f3630523da827bb25e665b7d3f879", 644055,
+			    "missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
+	 Common::ES_ESP,
+	 Common::kPlatformDOS,
+	 ADGF_TESTING,
 	 GUIO1(GUIO_NOMIDI)},
 	{"soldier-boyz", // Solidier Boyz (US)
 	 "",
@@ -95,7 +111,7 @@ static const ADGameDescription gameDescriptions[] = {
 				"setup.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 160740),
 	 Common::EN_USA,
 	 Common::kPlatformWindows,
-	 ADGF_UNSUPPORTED,
+	 ADGF_TESTING,
 	 GUIO1(GUIO_NOMIDI)},
 	AD_TABLE_END_MARKER};
 } // End of namespace Hypno
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 03b66bf989..0b02e0b1c7 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -235,6 +235,31 @@ void HypnoEngine::drawImage(Graphics::Surface &surf, int x, int y, bool transpar
 		_compositeSurface->blitFrom(surf, Common::Point(x, y));
 }
 
+Common::File *HypnoEngine::fixSmackerHeader(Common::File *file) {
+	Common::String magic;
+	magic += file->readByte();
+	magic += file->readByte();
+	magic += file->readByte();
+	magic += file->readByte();
+
+	if (magic == "HYP2") {
+		ByteArray *data = new ByteArray();
+		data->push_back('S');
+		data->push_back('M');
+		data->push_back('K');
+		data->push_back('2');
+		while (!file->eos()) {
+			data->push_back(file->readByte());
+		}
+		file->close();
+		delete file;
+		file = (Common::File *) new Common::MemoryReadStream(data->data(), data->size());
+	} else 
+		file->seek(0);
+
+	return file;
+}
+
 Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, bool convert) {
 	Common::File *file = new Common::File();
 	Common::String path = convertPath(name);
@@ -244,6 +269,8 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
 
+	file = fixSmackerHeader(file);
+
 	Video::SmackerDecoder vd;
 	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
@@ -274,6 +301,8 @@ Frames HypnoEngine::decodeFrames(const Common::String &name) {
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
 
+	file = fixSmackerHeader(file);
+
 	Video::SmackerDecoder vd;
 	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
@@ -369,6 +398,8 @@ void HypnoEngine::playVideo(MVideo &video) {
 	if (!file->open(path))
 		error("unable to find video file %s", path.c_str());
 
+	file = fixSmackerHeader(file);
+
 	if (video.decoder != nullptr)
 		error("Video %s was not previously closed and deallocated", video.path.c_str());
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index dfe894e3e1..c7ad21d552 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -118,6 +118,7 @@ public:
 	void playVideo(MVideo &video);
 	void skipVideo(MVideo &video);
 
+	Common::File *fixSmackerHeader(Common::File *file);
 	Graphics::Surface *decodeFrame(const Common::String &name, int frame, bool convert = true);
 	Frames decodeFrames(const Common::String &name);
 	void loadImage(const Common::String &file, int x, int y, bool transparent);
@@ -232,6 +233,7 @@ public:
 	void loadAssetsDemoDisc();
 	void loadAssetsPCW();
 	void loadAssetsPCG();
+	void loadAssetsFullGame();
 	void showCredits() override;
 	bool clickedSecondaryShoot(const Common::Point &mousePos) override;
 	void drawShoot(const Common::Point &target) override;
diff --git a/engines/hypno/lexer_arc.cpp b/engines/hypno/lexer_arc.cpp
index 5f0b23b365..e09952bc02 100644
--- a/engines/hypno/lexer_arc.cpp
+++ b/engines/hypno/lexer_arc.cpp
@@ -694,13 +694,13 @@ static const YY_CHAR yy_meta[41] =
 
 static const flex_int16_t yy_base[64] =
     {   0,
-        0,    0,  127,  148,  148,  123,  148,  148,   33,   37,
-       41,    0,   46,   48,  118,  117,  116,   53,   58,  115,
-       59,   61,   62,   65,  114,  112,   69,   63,  111,  110,
-      109,   67,  108,    0,  148,  111,   73,   98,  108,    0,
-      105,  104,   93,   92,   91,   90,   87,   88,   86,   85,
-       84,   83,    0,  148,   84,   79,   81,  148,  137,  139,
-      141,   83,  143
+        0,    0,  133,  155,  155,  129,  155,  155,   33,   37,
+       41,    0,   46,   48,  124,  123,  122,   60,   65,  121,
+       66,   53,   69,   72,  119,  118,   76,   68,  117,  116,
+      115,   74,  114,    0,  155,  117,   80,  105,  114,    0,
+      111,  110,  100,   98,   97,   95,   85,   94,   93,   92,
+       91,   90,    0,  155,   91,   86,   88,  155,  144,  146,
+      148,   90,  150
     } ;
 
 static const flex_int16_t yy_def[64] =
@@ -714,7 +714,7 @@ static const flex_int16_t yy_def[64] =
        58,   58,   58
     } ;
 
-static const flex_int16_t yy_nxt[189] =
+static const flex_int16_t yy_nxt[196] =
     {   0,
         4,    5,    6,    7,    8,    9,    4,   10,   10,   11,
        10,   12,   13,   14,   15,   16,   17,   18,   17,   19,
@@ -722,44 +722,48 @@ static const flex_int16_t yy_nxt[189] =
        30,   31,   32,   33,   34,   17,   17,   17,    8,   35,
        37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
        38,   37,   40,   41,   40,   43,   43,   43,   43,   40,
-       44,   44,   44,   44,   40,   40,   46,   40,   40,   40,
-       48,   40,   49,   40,   45,   40,   50,   50,   50,   50,
-       37,   37,   37,   37,   47,   40,   53,   40,   55,   40,
-       40,   40,   40,   40,   40,   57,   40,   40,   40,   40,
-
-       51,   42,   42,   42,   42,   37,   37,   37,   37,   56,
-       40,   40,   55,   36,   40,   40,   40,   40,   40,   54,
-       40,   40,   40,   40,   40,   36,   58,   58,   58,   58,
-       58,   58,   58,   58,   54,   58,   54,   39,   58,   39,
-       39,   42,   42,   52,   52,   40,   40,    3,   58,   58,
+       43,   43,   43,   43,   43,   43,   40,   44,   44,   44,
+       44,   40,   40,   46,   40,   40,   47,   48,   40,   49,
+       40,   45,   40,   50,   50,   50,   50,   37,   37,   37,
+       37,   40,   40,   53,   40,   55,   40,   40,   40,   40,
+
+       40,   40,   57,   40,   40,   51,   40,   56,   42,   42,
+       42,   42,   37,   37,   37,   37,   40,   40,   55,   36,
+       40,   40,   40,   40,   40,   40,   54,   40,   40,   40,
+       40,   36,   58,   58,   58,   58,   58,   58,   58,   58,
+       58,   54,   58,   54,   39,   58,   39,   39,   42,   42,
+       52,   52,   40,   40,    3,   58,   58,   58,   58,   58,
        58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
        58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
        58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58
+       58,   58,   58,   58,   58
+
     } ;
 
-static const flex_int16_t yy_chk[189] =
+static const flex_int16_t yy_chk[196] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         9,    9,    9,    9,   10,   10,   10,   10,   11,   11,
-       11,   11,   13,   13,   14,   14,   14,   14,   14,   18,
-       18,   18,   18,   18,   19,   21,   21,   22,   23,   28,
-       23,   24,   24,   32,   19,   27,   27,   27,   27,   27,
-       37,   37,   37,   37,   22,   56,   62,   57,   55,   52,
-       51,   50,   49,   47,   48,   56,   46,   45,   44,   43,
-
-       28,   32,   32,   32,   32,   38,   38,   38,   38,   47,
-       42,   41,   39,   36,   33,   31,   30,   29,   26,   38,
-       25,   20,   17,   16,   15,    6,    3,    0,    0,    0,
-        0,    0,    0,    0,   38,    0,   38,   59,    0,   59,
-       59,   60,   60,   61,   61,   63,   63,   58,   58,   58,
+       11,   11,   13,   13,   14,   14,   14,   14,   14,   22,
+       14,   14,   14,   14,   14,   14,   18,   18,   18,   18,
+       18,   19,   21,   21,   28,   23,   22,   23,   24,   24,
+       32,   19,   27,   27,   27,   27,   27,   37,   37,   37,
+       37,   47,   56,   62,   57,   55,   52,   51,   50,   49,
+
+       48,   46,   56,   45,   44,   28,   43,   47,   32,   32,
+       32,   32,   38,   38,   38,   38,   42,   41,   39,   36,
+       33,   31,   30,   29,   26,   25,   38,   20,   17,   16,
+       15,    6,    3,    0,    0,    0,    0,    0,    0,    0,
+        0,   38,    0,   38,   59,    0,   59,   59,   60,   60,
+       61,   61,   63,   63,   58,   58,   58,   58,   58,   58,
        58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
        58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
        58,   58,   58,   58,   58,   58,   58,   58,   58,   58,
-       58,   58,   58,   58,   58,   58,   58,   58
+       58,   58,   58,   58,   58
+
     } ;
 
 /* Table of booleans, true if rule could match eol. */
@@ -814,8 +818,8 @@ char *yytext;
 #include "hypno/grammar.h"
 #include "hypno/tokens_arc.h"
 
-#line 818 "engines/hypno/lexer_arc.cpp"
-#line 819 "engines/hypno/lexer_arc.cpp"
+#line 822 "engines/hypno/lexer_arc.cpp"
+#line 823 "engines/hypno/lexer_arc.cpp"
 
 #define INITIAL 0
 
@@ -1032,7 +1036,7 @@ YY_DECL
 	{
 #line 43 "engines/hypno/lexer_arc.l"
 
-#line 1036 "engines/hypno/lexer_arc.cpp"
+#line 1040 "engines/hypno/lexer_arc.cpp"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -1286,7 +1290,7 @@ YY_RULE_SETUP
 #line 81 "engines/hypno/lexer_arc.l"
 ECHO;
 	YY_BREAK
-#line 1290 "engines/hypno/lexer_arc.cpp"
+#line 1294 "engines/hypno/lexer_arc.cpp"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
diff --git a/engines/hypno/lexer_arc.l b/engines/hypno/lexer_arc.l
index 38aba61ab7..7432e6c81a 100644
--- a/engines/hypno/lexer_arc.l
+++ b/engines/hypno/lexer_arc.l
@@ -64,7 +64,7 @@ F[0-9]						return FNTOK;
 F							return FTOK;
 S[0-9]						HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return SNTOK;
 A0							return A0TOK;
-B[0-9]						HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
+B[0-9A-F]					HYPNO_ARC_lval.s = scumm_strdup(HYPNO_ARC_text); return BNTOK;
 K0							return K0TOK;
 P0							return P0TOK;
 Y[A-Z0-9]					return YXTOK;
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index 1a8d58f115..e6cded51fc 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -40,7 +40,6 @@ Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, co
 		*engine = (Engine *)new Hypno::SpiderEngine(syst, desc);
 	} else if (Common::String(desc->gameId) == "soldier-boyz") {
 		*engine = (Engine *)new Hypno::BoyzEngine(syst, desc);
-		error("Unsupported game");
 	} else
 		return Common::kUnsupportedGameidError;
 
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 50e7f3c2bb..6128542547 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -27,6 +27,10 @@ namespace Hypno {
 WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void WetEngine::loadAssets() {
+	if (!isDemo()) {
+		loadAssetsFullGame();
+		return;
+	}
 	Common::String demoVersion = "Wetlands Demo Disc";
 	if (demoVersion == "Wetlands Demo Disc")
 		loadAssetsDemoDisc();
@@ -220,6 +224,52 @@ void WetEngine::loadAssetsPCG() {
 }
 
 
+void WetEngine::loadAssetsFullGame() {
+	LibFile *missions = loadLib("", "wetlands/c_misc/missions.lib", true);
+	Common::ArchiveMemberList files;
+	if (missions == nullptr || missions->listMembers(files) == 0)
+		error("Failed to load any files from missions.lib");
+
+	Level intro;
+	intro.trans.level = "c111.mi_";
+	intro.trans.intros.push_back("wetlands/c_misc/nw_logo.smk");
+	intro.trans.intros.push_back("wetlands/c_misc/hypnotix.smk");
+	intro.trans.intros.push_back("wetlands/c_misc/wetlogo.smk");
+	_levels["<start>"] = intro;
+
+	Common::String arclevel = "c111.mi_";
+	debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
+	Common::String arc;
+	Common::String list;
+	splitArcadeFile(arclevel, arc, list);
+	debug("%s", arc.c_str());
+	parseArcadeShooting("wetlands", arclevel, arc);
+	_levels[arclevel].arcade.id = 0;
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.prefix = "wetlands";
+	//_levels[arclevel].arcade.levelIfWin = "c52.mi_";
+	//_levels[arclevel].arcade.levelIfLose = "c52.mi_";
+
+	//arclevel = "c52.mi_";
+	// arc.clear();
+	// list.clear();
+	// splitArcadeFile(arclevel, arc, list);
+	// parseArcadeShooting("wetlands", arclevel, arc);
+	// _levels[arclevel].arcade.id = 1;
+	// _levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	// _levels[arclevel].arcade.prefix = "wetlands";
+	// _levels[arclevel].arcade.levelIfWin = "<gameover>";
+	// _levels[arclevel].arcade.levelIfLose = "<gameover>";
+
+	// Level over;
+	// over.trans.level = "<quit>";
+	// over.trans.intros.push_back("movie/gameover.smk");
+	// _levels["<gameover>"] = over;
+
+	loadLib("", "wetlands/c_misc/fonts.lib", true);
+	loadLib("wetlands/sound/", "wetlands/c_misc/sound.lib", true);
+}
+
 void WetEngine::showCredits() {
 	MVideo video("c_misc/credits.smk", Common::Point(0, 0), false, false, false);
 	runIntro(video);


Commit: b58cb9d7ca2ca750b82b08fb1f249678bad2f1e9
    https://github.com/scummvm/scummvm/commit/b58cb9d7ca2ca750b82b08fb1f249678bad2f1e9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: reduced maxScanDepth and adjusted detection tables

Changed paths:
    engines/hypno/detection.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 1a77e7a230..c11eeee600 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -58,8 +58,9 @@ static const ADGameDescription gameDescriptions[] = {
 	 GUIO1(GUIO_NOMIDI)},
 	{"wetlands", // Wetlands Demo Disc (November 1995)
 	 "Demo",
-	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231,
-				"wetdemo.exe", "15a6b1b3819ef002438df340509b5373", 458319),
+	 AD_ENTRY3s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231,
+				"wetdemo.exe", "15a6b1b3819ef002438df340509b5373", 458319,
+				"demo.exe", "15a6b1b3819ef002438df340509b5373", 533221),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
 	 ADGF_TESTING | ADGF_DEMO,
@@ -100,7 +101,7 @@ static const ADGameDescription gameDescriptions[] = {
 	{"wetlands", // Wetlands (ES)
 	 "",
 	 AD_ENTRY2s("wetlands.exe", "8d0f3630523da827bb25e665b7d3f879", 644055,
-			    "missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
+				"missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
 	 Common::ES_ESP,
 	 Common::kPlatformDOS,
 	 ADGF_TESTING,
@@ -129,7 +130,7 @@ static const char *const directoryGlobs[] = {
 class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
 public:
 	HypnoMetaEngineDetection() : AdvancedMetaEngineDetection(Hypno::gameDescriptions, sizeof(ADGameDescription), Hypno::hypnoGames) {
-		_maxScanDepth = 10;
+		_maxScanDepth = 2;
 		_directoryGlobs = directoryGlobs;
 	}
 
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 6128542547..b40704e8d2 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -225,16 +225,16 @@ void WetEngine::loadAssetsPCG() {
 
 
 void WetEngine::loadAssetsFullGame() {
-	LibFile *missions = loadLib("", "wetlands/c_misc/missions.lib", true);
+	LibFile *missions = loadLib("", "c_misc/missions.lib", true);
 	Common::ArchiveMemberList files;
 	if (missions == nullptr || missions->listMembers(files) == 0)
 		error("Failed to load any files from missions.lib");
 
 	Level intro;
 	intro.trans.level = "c111.mi_";
-	intro.trans.intros.push_back("wetlands/c_misc/nw_logo.smk");
-	intro.trans.intros.push_back("wetlands/c_misc/hypnotix.smk");
-	intro.trans.intros.push_back("wetlands/c_misc/wetlogo.smk");
+	intro.trans.intros.push_back("c_misc/nw_logo.smk");
+	intro.trans.intros.push_back("c_misc/hypnotix.smk");
+	intro.trans.intros.push_back("c_misc/wetlogo.smk");
 	_levels["<start>"] = intro;
 
 	Common::String arclevel = "c111.mi_";
@@ -243,10 +243,10 @@ void WetEngine::loadAssetsFullGame() {
 	Common::String list;
 	splitArcadeFile(arclevel, arc, list);
 	debug("%s", arc.c_str());
-	parseArcadeShooting("wetlands", arclevel, arc);
+	parseArcadeShooting("", arclevel, arc);
 	_levels[arclevel].arcade.id = 0;
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-	_levels[arclevel].arcade.prefix = "wetlands";
+	_levels[arclevel].arcade.prefix = "";
 	//_levels[arclevel].arcade.levelIfWin = "c52.mi_";
 	//_levels[arclevel].arcade.levelIfLose = "c52.mi_";
 
@@ -266,8 +266,8 @@ void WetEngine::loadAssetsFullGame() {
 	// over.trans.intros.push_back("movie/gameover.smk");
 	// _levels["<gameover>"] = over;
 
-	loadLib("", "wetlands/c_misc/fonts.lib", true);
-	loadLib("wetlands/sound/", "wetlands/c_misc/sound.lib", true);
+	loadLib("", "c_misc/fonts.lib", true);
+	loadLib("sound/", "c_misc/sound.lib", true);
 }
 
 void WetEngine::showCredits() {


Commit: d2cc36082878631aae76ffbc713815b03316554f
    https://github.com/scummvm/scummvm/commit/d2cc36082878631aae76ffbc713815b03316554f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: reduce variable scopes and some various fixed here and there

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/detection.cpp
    engines/hypno/scene.cpp
    engines/hypno/spider/arcade.cpp
    engines/hypno/spider/spider.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 11e17d12d5..4534d74213 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -101,12 +101,11 @@ void HypnoEngine::hitPlayer() {
 
 void HypnoEngine::runArcade(ArcadeShooting &arc) {
 
-	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
-	Common::Event event;
 	Common::Point mousePos;
 	Common::List<uint32> shootsToRemove;
 	ShootSequence shootSequence = arc.shootSequence;
 
+	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
 	_levelId = arc.id;
 	_shootSound = arc.shootSound;
 	_score = 0;
@@ -140,6 +139,7 @@ void HypnoEngine::runArcade(ArcadeShooting &arc) {
 	bool shootingPrimary = false;
 	bool shootingSecondary = false;
 
+	Common::Event event;
 	while (!shouldQuit()) {
 
 		while (g_system->getEventManager()->pollEvent(event)) {
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index c11eeee600..99475411bb 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -130,7 +130,7 @@ static const char *const directoryGlobs[] = {
 class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
 public:
 	HypnoMetaEngineDetection() : AdvancedMetaEngineDetection(Hypno::gameDescriptions, sizeof(ADGameDescription), Hypno::hypnoGames) {
-		_maxScanDepth = 2;
+		_maxScanDepth = 3;
 		_directoryGlobs = directoryGlobs;
 	}
 
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 165f214e9b..153c4f4a6a 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -115,34 +115,35 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			}
 		}
 	}
-	if (found) {
-		if (selected.smenu) {
-			if (selected.smenu->empty())
-				error("Invalid menu selected");
-			_nextHotsToAdd = selected.smenu;
-		}
+	if (!found)
+		return;
 
-		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
-			Action *action = *itt;
-			if (typeid(*action) == typeid(ChangeLevel))
-				runChangeLevel((ChangeLevel *)action);
-			if (typeid(*action) == typeid(Escape))
-				runEscape((Escape *)action);
-			else if (typeid(*action) == typeid(Cutscene))
-				runCutscene((Cutscene *)action);
-			else if (typeid(*action) == typeid(Play))
-				runPlay((Play *)action);
-			else if (typeid(*action) == typeid(WalN))
-				runWalN((WalN *)action);
-			else if (typeid(*action) == typeid(Global))
-				runGlobal((Global *)action);
-			else if (typeid(*action) == typeid(Talk))
-				runTalk((Talk *)action);
-			else if (typeid(*action) == typeid(Quit))
-				runQuit((Quit *)action);
-			else if (typeid(*action) == typeid(Palette))
-				debugC(1, kHypnoDebugScene, "runPalette unimplemented");
-		}
+	if (selected.smenu) {
+		if (selected.smenu->empty())
+			error("Invalid menu selected");
+		_nextHotsToAdd = selected.smenu;
+	}
+
+	for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
+		Action *action = *itt;
+		if (typeid(*action) == typeid(ChangeLevel))
+			runChangeLevel((ChangeLevel *)action);
+		if (typeid(*action) == typeid(Escape))
+			runEscape((Escape *)action);
+		else if (typeid(*action) == typeid(Cutscene))
+			runCutscene((Cutscene *)action);
+		else if (typeid(*action) == typeid(Play))
+			runPlay((Play *)action);
+		else if (typeid(*action) == typeid(WalN))
+			runWalN((WalN *)action);
+		else if (typeid(*action) == typeid(Global))
+			runGlobal((Global *)action);
+		else if (typeid(*action) == typeid(Talk))
+			runTalk((Talk *)action);
+		else if (typeid(*action) == typeid(Quit))
+			runQuit((Quit *)action);
+		else if (typeid(*action) == typeid(Palette))
+			debugC(1, kHypnoDebugScene, "runPalette unimplemented");
 	}
 }
 
@@ -151,13 +152,12 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 	Hotspot selected;
 	bool found = false;
 	int rs = 100000000;
-	int cs = 0;
 	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
 		const Hotspot h = *it;
 		if (h.type != MakeHotspot)
 			continue;
 
-		cs = h.rect.width() * h.rect.height();
+		int cs = h.rect.width() * h.rect.height();
 		if (h.rect.contains(mousePos)) {
 			if (cs < rs) {
 				selected = h;
diff --git a/engines/hypno/spider/arcade.cpp b/engines/hypno/spider/arcade.cpp
index ec66f321ff..ea8709a039 100644
--- a/engines/hypno/spider/arcade.cpp
+++ b/engines/hypno/spider/arcade.cpp
@@ -20,7 +20,6 @@
  *
  */
 
-
 #include "hypno/grammar.h"
 #include "hypno/hypno.h"
 
@@ -78,4 +77,4 @@ void SpiderEngine::drawHealth() {
 	_font->drawString(_compositeSurface, "ENERGY", 248, 180, 38, c);
 }
 
-} // End of namespace Hypno
\ No newline at end of file
+} // End of namespace Hypno
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 80fffe4859..504446f6b9 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -1,3 +1,25 @@
+/* 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 "hypno/grammar.h"
@@ -32,9 +54,8 @@ void SpiderEngine::loadAssets() {
 	Common::String arclevel = files.front()->getName();
 	Common::SeekableReadStream *file = files.front()->createReadStream();
 
-	byte x;
 	while (!file->eos()) {
-		x = file->readByte();
+		byte x = file->readByte();
 		arc += x;
 		if (x == 'X') {
 			while (!file->eos()) {
@@ -190,4 +211,4 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 	}
 }
 
-} // End of namespace Hypno
\ No newline at end of file
+} // End of namespace Hypno


Commit: f278a2fd0aa7634dfd2c6fe1e1eea7fb35065fdd
    https://github.com/scummvm/scummvm/commit/f278a2fd0aa7634dfd2c6fe1e1eea7fb35065fdd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved detection and added POTFILES file

Changed paths:
  A engines/hypno/POTFILES
    engines/hypno/detection.cpp


diff --git a/engines/hypno/POTFILES b/engines/hypno/POTFILES
new file mode 100644
index 0000000000..94c22b97d5
--- /dev/null
+++ b/engines/hypno/POTFILES
@@ -0,0 +1 @@
+engines/hypno/detection.cpp
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 99475411bb..5255eaee00 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -49,12 +49,12 @@ static const ADGameDescription gameDescriptions[] = {
 	 ADGF_TESTING | ADGF_DEMO,
 	 GUIO1(GUIO_NOMIDI)},
 	{"sinister-six", // US release
-	 "Not yet implemented",
+	 _s("Missing game code"),
 	 AD_ENTRY2s("COMBAT.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 255115,
 				"SPIDER.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 248056),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
-	 ADGF_UNSUPPORTED | ADGF_TESTING,
+	 ADGF_UNSUPPORTED,
 	 GUIO1(GUIO_NOMIDI)},
 	{"wetlands", // Wetlands Demo Disc (November 1995)
 	 "Demo",
@@ -88,7 +88,7 @@ static const ADGameDescription gameDescriptions[] = {
 				"missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
-	 ADGF_TESTING,
+	 ADGF_UNSTABLE,
 	 GUIO1(GUIO_NOMIDI)},
 	{"wetlands", // Wetlands (FR)
 	 "",
@@ -96,7 +96,7 @@ static const ADGameDescription gameDescriptions[] = {
 			    "missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
 	 Common::FR_FRA,
 	 Common::kPlatformDOS,
-	 ADGF_TESTING,
+	 ADGF_UNSTABLE,
 	 GUIO1(GUIO_NOMIDI)},
 	{"wetlands", // Wetlands (ES)
 	 "",
@@ -104,15 +104,15 @@ static const ADGameDescription gameDescriptions[] = {
 				"missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
 	 Common::ES_ESP,
 	 Common::kPlatformDOS,
-	 ADGF_TESTING,
+	 ADGF_UNSTABLE,
 	 GUIO1(GUIO_NOMIDI)},
 	{"soldier-boyz", // Solidier Boyz (US)
-	 "",
+	 _s("Missing game code"),
 	 AD_ENTRY2s("boyz.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 263347,
 				"setup.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 160740),
 	 Common::EN_USA,
 	 Common::kPlatformWindows,
-	 ADGF_TESTING,
+	 ADGF_UNSUPPORTED,
 	 GUIO1(GUIO_NOMIDI)},
 	AD_TABLE_END_MARKER};
 } // End of namespace Hypno


Commit: 65754da57ef2967594df35b4f3f5a28647ddf1db
    https://github.com/scummvm/scummvm/commit/65754da57ef2967594df35b4f3f5a28647ddf1db
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: refactored object initialization to use explicit constructors

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/hypno.cpp


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 4cb78f39eb..08833d8816 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -63,8 +63,8 @@ public:
 	bool scaled;
 	bool transparent;
 	bool loop;
-	Video::SmackerDecoder *decoder = nullptr;
-	const Graphics::Surface *currentFrame = nullptr;
+	Video::SmackerDecoder *decoder;
+	const Graphics::Surface *currentFrame;
 };
 
 typedef Common::Array<MVideo> Videos;
@@ -172,15 +172,19 @@ public:
 
 class Shoot {
 public:
+	Shoot() {
+		destroyed = false;
+		video = nullptr;
+	}
 	Common::String name;
 	Filename animation;
 	Filename startSound;
 	Filename endSound;
 	Common::Point position;
 	int damage;
-	MVideo *video = nullptr;
+	MVideo *video;
 	uint32 explosionFrame;
-	bool destroyed = false;
+	bool destroyed;
 };
 
 typedef Common::Array<Shoot> Shoots;
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 0b02e0b1c7..07869b8471 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -47,6 +47,8 @@ ArcadeShooting g_parsedArc;
 HypnoEngine *g_hypno;
 
 MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent, bool _scaled, bool _loop) {
+	decoder = nullptr;
+	currentFrame = nullptr;
 	path = _path;
 	position = _position;
 	scaled = _scaled;


Commit: 341c6f960fe7cba68f1819896774da5490c76a13
    https://github.com/scummvm/scummvm/commit/341c6f960fe7cba68f1819896774da5490c76a13
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: sorted module.mk list of objects

Changed paths:
    engines/hypno/module.mk


diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index 41a4101840..2d157a20c4 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -1,23 +1,23 @@
 MODULE := engines/hypno
 
 MODULE_OBJS := \
-	libfile.o \
-	cursors.o \
-	metaengine.o \
 	actions.o \
-	scene.o \
 	arcade.o \
-	lexer_mis.o \
+	boyz/boyz.o \
+	cursors.o \
 	grammar_mis.o \
-	lexer_arc.o \
 	grammar_arc.o \
+	hypno.o \
+	lexer_mis.o \
+	lexer_arc.o \
+	libfile.o \
+	metaengine.o \
+	scene.o \
+	spider/arcade.o \
 	spider/spider.o \
 	spider/talk.o \
-	spider/arcade.o \
-	wet/wet.o \
 	wet/arcade.o \
-	boyz/boyz.o \
-	hypno.o
+	wet/wet.o
 
 MODULE_DIRS += \
 	engines/hypno


Commit: a87c50f49875797e156168e176948c26dd869c14
    https://github.com/scummvm/scummvm/commit/a87c50f49875797e156168e176948c26dd869c14
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added functions to start implementing gameplay from full versions of Wetlands and Spiderman games as well as some fixes here and there

Changed paths:
    engines/hypno/actions.cpp
    engines/hypno/detection.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar_mis.cpp
    engines/hypno/grammar_mis.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/lexer_mis.cpp
    engines/hypno/lexer_mis.l
    engines/hypno/libfile.cpp
    engines/hypno/scene.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/tokens_mis.h
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index 7dc301e0e2..2ce49e74e7 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -85,6 +85,8 @@ void HypnoEngine::runGlobal(Global *a) {
 		_sceneState[a->variable] = 1;
 	else if (a->command == "TURNOFF")
 		_sceneState[a->variable] = 0;
+	else if (a->command == "TOGGLE")
+		_sceneState[a->variable] = !_sceneState[a->variable];
 	else
 		error("Invalid command %s", a->command.c_str());
 }
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 5255eaee00..fa8794d0fe 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -50,11 +50,19 @@ static const ADGameDescription gameDescriptions[] = {
 	 GUIO1(GUIO_NOMIDI)},
 	{"sinister-six", // US release
 	 _s("Missing game code"),
-	 AD_ENTRY2s("COMBAT.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 255115,
-				"SPIDER.EXE", "bac1d734f2606dbdd0816dfa7a5cf518", 248056),
+	 AD_ENTRY2s("DATA.Z", "a1f71005a45e6ee454bb0bf3868dff54", 8766307,
+				"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
-	 ADGF_UNSUPPORTED,
+	 ADGF_UNSTABLE | ADGF_UNSUPPORTED,
+	 GUIO1(GUIO_NOMIDI)},
+	{"sinister-six", // ES release
+	 _s("Missing game code"),
+	 AD_ENTRY2s("SPIDER.EXE", "dbd912d6f6724c6d44775fc19cfa8ca0", 483871,
+	 			"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
+	 Common::ES_ESP,
+	 Common::kPlatformDOS,
+	 ADGF_UNSTABLE | ADGF_UNSUPPORTED,
 	 GUIO1(GUIO_NOMIDI)},
 	{"wetlands", // Wetlands Demo Disc (November 1995)
 	 "Demo",
@@ -119,13 +127,15 @@ static const ADGameDescription gameDescriptions[] = {
 
 static const char *const directoryGlobs[] = {
 	"boyz",
+	"spider",
+	"wetlands",
 	"sixdemo",
 	"demo",
 	"factory",
-	"wetlands",
 	"movie",
 	"c_misc",
-	0};
+	NULL
+};
 
 class HypnoMetaEngineDetection : public AdvancedMetaEngineDetection {
 public:
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 08833d8816..a548f7b363 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -45,7 +45,7 @@ enum HotspotType {
 
 class Action {
 public:
-	virtual ~Action(){}; // needed to make Action polymorphic
+	virtual ~Action() {} // needed to make Action polymorphic
 };
 
 typedef Common::Array<Action *> Actions;
@@ -149,6 +149,7 @@ public:
 class TalkCommand {
 public:
 	Common::String command;
+	Common::String variable;
 	Filename path;
 	uint32 num;
 	Common::Point position;
diff --git a/engines/hypno/grammar_mis.cpp b/engines/hypno/grammar_mis.cpp
index b2bdc0138e..cbaad48c90 100644
--- a/engines/hypno/grammar_mis.cpp
+++ b/engines/hypno/grammar_mis.cpp
@@ -174,14 +174,20 @@ extern int HYPNO_MIS_debug;
     INACTOK = 286,
     FDTOK = 287,
     BOXXTOK = 288,
-    PG = 289,
-    PA = 290,
-    PD = 291,
-    PH = 292,
-    PF = 293,
-    PE = 294,
-    PP = 295,
-    PI = 296
+    ESCAPETOK = 289,
+    SECONDTOK = 290,
+    INTROTOK = 291,
+    DEFAULTTOK = 292,
+    PG = 293,
+    PA = 294,
+    PD = 295,
+    PH = 296,
+    PF = 297,
+    PE = 298,
+    PP = 299,
+    PI = 300,
+    PL = 301,
+    PS = 302
   };
 #endif
 
@@ -195,7 +201,7 @@ union HYPNO_MIS_STYPE
 	char *s; /* string value */
 	int i;	 /* integer value */
 
-#line 199 "engines/hypno/grammar_mis.cpp" /* yacc.c:355  */
+#line 205 "engines/hypno/grammar_mis.cpp" /* yacc.c:355  */
 };
 
 typedef union HYPNO_MIS_STYPE HYPNO_MIS_STYPE;
@@ -212,7 +218,7 @@ int HYPNO_MIS_parse (void);
 
 /* Copy the second part of user declarations.  */
 
-#line 216 "engines/hypno/grammar_mis.cpp" /* yacc.c:358  */
+#line 222 "engines/hypno/grammar_mis.cpp" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -454,21 +460,21 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   91
+#define YYLAST   107
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  42
+#define YYNTOKENS  48
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  11
+#define YYNNTS  10
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  43
+#define YYNRULES  48
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  102
+#define YYNSTATES  117
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   296
+#define YYMAXUTOK   302
 
 #define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -506,18 +512,19 @@ static const yytype_uint8 yytranslate[] =
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47
 };
 
 #if HYPNO_MIS_DEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    74,    74,    77,    82,    83,    84,    87,    90,   105,
-     114,   129,   135,   136,   146,   155,   164,   174,   182,   190,
-     198,   208,   216,   222,   230,   236,   239,   240,   244,   245,
-     251,   252,   258,   264,   270,   277,   284,   285,   288,   289,
-     292,   293,   296,   297
+       0,    74,    74,    77,    82,    83,    87,   102,   111,   126,
+     132,   133,   143,   152,   161,   171,   179,   187,   195,   205,
+     213,   219,   225,   228,   234,   237,   238,   242,   243,   244,
+     245,   246,   247,   253,   254,   260,   266,   272,   279,   286,
+     292,   293,   294,   297,   298,   301,   302,   305,   306
 };
 #endif
 
@@ -531,9 +538,9 @@ static const char *const yytname[] =
   "TIMETOK", "PALETOK", "BBOXTOK", "OVERTOK", "WALNTOK", "MICETOK",
   "PLAYTOK", "ENDTOK", "MENUTOK", "SMENTOK", "ESCPTOK", "NRTOK", "AMBITOK",
   "GLOBTOK", "TONTOK", "TOFFTOK", "TALKTOK", "INACTOK", "FDTOK", "BOXXTOK",
-  "PG", "PA", "PD", "PH", "PF", "PE", "PP", "PI", "$accept", "start",
-  "init", "lines", "end", "line", "alloctalk", "talk", "mflag", "flag",
-  "gsswitch", YY_NULLPTR
+  "ESCAPETOK", "SECONDTOK", "INTROTOK", "DEFAULTTOK", "PG", "PA", "PD",
+  "PH", "PF", "PE", "PP", "PI", "PL", "PS", "$accept", "start", "init",
+  "lines", "line", "alloctalk", "talk", "mflag", "flag", "gsswitch", YY_NULLPTR
 };
 #endif
 
@@ -546,14 +553,14 @@ static const yytype_uint16 yytoknum[] =
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296
+     295,   296,   297,   298,   299,   300,   301,   302
 };
 # endif
 
-#define YYPACT_NINF -68
+#define YYPACT_NINF -71
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-68)))
+  (!!((Yystate) == (-71)))
 
 #define YYTABLE_NINF -1
 
@@ -564,17 +571,18 @@ static const yytype_uint16 yytoknum[] =
      STATE-NUM.  */
 static const yytype_int8 yypact[] =
 {
-     -68,    12,    43,   -68,    -5,     9,    10,   -68,     6,    13,
-      14,    17,    18,    20,    15,    22,   -68,   -68,    25,    19,
-     -68,   -68,    43,    21,    23,   -68,    26,   -68,   -68,    27,
-      28,    30,    50,   -68,     5,    59,    68,    11,   -68,    43,
-      63,    65,    66,    67,   -68,    69,   -68,   -68,    70,   -68,
-      73,    11,    11,    71,    11,    11,    11,    11,    11,   -68,
-      72,    74,   -68,   -68,    75,    24,    77,    24,    24,    77,
-      76,   -68,   -68,    78,   -68,   -68,   -68,   -68,   -68,    79,
-      80,    81,   -68,    77,   -68,   -68,    77,    77,   -68,    82,
-     -68,    11,    11,   -68,   -68,   -68,   -68,    24,   -68,   -68,
-      77,   -68
+     -71,     5,    62,   -71,   -10,     8,     9,   -71,    10,    13,
+      14,    16,    18,    19,     1,    23,   -71,   -71,    25,    20,
+     -71,   -71,    62,    21,   -71,    22,   -71,   -71,    28,    29,
+      30,    31,   -71,   -71,    23,    33,    40,    24,   -71,    35,
+      37,    38,    39,   -71,    41,   -71,    42,   -71,    45,    24,
+      24,    43,   -71,    74,    83,    86,    24,    24,    24,    24,
+      24,   -71,    82,    84,    24,    24,   -71,    85,    26,    27,
+      26,    26,    27,    87,   -71,   -71,    88,    89,    90,    91,
+     -71,   -71,   -71,   -71,   -71,    92,    93,   -71,   -71,    94,
+     -71,    27,   -71,   -71,    27,    27,   -71,    95,   -71,    96,
+      97,    98,    24,    24,   -71,    27,   -71,   -71,    26,   -71,
+     -71,   -71,   -71,   -71,   -71,    27,   -71
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -582,31 +590,30 @@ static const yytype_int8 yypact[] =
      means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       3,     0,     0,     1,     0,     0,     0,     7,     0,     0,
-       0,     0,     0,     0,     0,     0,    10,    11,     0,     0,
-      24,     2,     0,     5,     0,    19,     0,    12,    18,     0,
-       0,     0,     0,    23,    39,     0,     0,    37,     6,     0,
-       0,     0,     0,     0,    21,     0,    38,     8,     0,    14,
-       0,    37,    37,     0,    37,    37,    37,    37,    37,    36,
-       0,     0,    22,     4,     0,    43,    41,    43,    43,    41,
-       0,    25,    26,     0,    29,    32,    33,    30,    31,     0,
-       0,     0,    42,    41,    40,    17,    41,    41,    15,     0,
-      28,    37,    37,     9,    13,    20,    16,    43,    34,    35,
-      41,    27
+       3,     0,     5,     1,     0,     0,     0,    22,     0,     0,
+       0,     0,     0,     0,     0,    44,     8,     9,     0,     0,
+      23,     2,     5,     0,    17,     0,    10,    16,     0,     0,
+       0,     0,    21,    43,    44,     0,     0,    42,     4,     0,
+       0,     0,     0,    19,     0,     6,     0,    12,     0,    42,
+      42,     0,    28,     0,     0,     0,    42,    42,    42,    42,
+      42,    41,     0,     0,    42,    42,    20,     0,    48,    46,
+      48,    48,    46,     0,    24,    25,     0,     0,     0,     0,
+      32,    35,    36,    33,    34,     0,     0,    40,    39,     0,
+      47,    46,    45,    15,    46,    46,    13,     0,    27,     0,
+       0,     0,    42,    42,     7,    46,    18,    14,    48,    29,
+      30,    31,    37,    38,    11,    46,    26
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -68,   -68,   -68,   -12,   -68,   -68,   -68,   -51,   -68,   -67,
-     -59
+     -71,   -71,   -71,     6,   -71,   -71,   -49,     0,   -70,   -67
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     1,     2,    21,    22,    23,    37,    62,    47,    85,
-      83
+      -1,     1,     2,    21,    22,    37,    66,    34,    93,    91
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -614,67 +621,70 @@ static const yytype_int8 yydefgoto[] =
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-      71,    72,    88,    74,    75,    76,    77,    78,    86,    87,
-      38,    24,     3,    25,    26,    27,    94,    28,    29,    95,
-      96,    30,    31,    50,    32,    34,    36,    63,    33,    35,
-      46,    82,    40,   101,    39,    41,    42,    43,   100,    44,
-      98,    99,    51,    52,    53,    54,    55,    56,    57,    58,
-      59,    60,    61,     4,     5,     6,     7,     8,     9,    45,
-      10,    11,    12,    13,    14,    15,    16,    17,    48,    18,
-      19,    49,    64,    20,    65,    66,    67,    70,    68,    69,
-      73,    79,    84,    80,    81,    89,     0,    90,    91,    92,
-      93,    97
+      74,    75,    96,    94,    95,     3,    23,    80,    81,    82,
+      83,    84,    24,    25,    32,    87,    88,    27,    28,    26,
+      29,   105,    30,    31,   106,   107,    33,    36,    38,    35,
+      39,    40,    92,    90,    45,   114,    48,    41,    42,    43,
+      44,   115,    46,    47,    67,   116,    68,    69,    70,    73,
+      71,    72,    76,   112,   113,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,     4,     5,     6,     7,     8,     9,    77,    10,
+      11,    12,    13,    14,    15,    16,    17,    78,    18,    19,
+      79,    85,    20,    86,    89,     0,    97,    98,    99,   100,
+     101,   102,   103,   104,   108,   109,   110,   111
 };
 
 static const yytype_int8 yycheck[] =
 {
-      51,    52,    69,    54,    55,    56,    57,    58,    67,    68,
-      22,    16,     0,     4,     4,     9,    83,     4,     4,    86,
-      87,     4,     4,    12,     4,     3,     7,    39,    13,     4,
-      25,     7,     9,   100,    13,     9,     9,     9,    97,     9,
-      91,    92,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    10,    11,    12,    13,    14,    15,     9,
-      17,    18,    19,    20,    21,    22,    23,    24,     9,    26,
-      27,     3,     9,    30,     9,     9,     9,     4,     9,     9,
-       9,     9,     5,     9,     9,     9,    -1,     9,     9,     9,
-       9,     9
+      49,    50,    72,    70,    71,     0,    16,    56,    57,    58,
+      59,    60,     4,     4,    13,    64,    65,     4,     4,     9,
+       4,    91,     4,     4,    94,    95,     3,     7,    22,     4,
+       9,     9,     5,     7,    34,   105,    12,     9,     9,     9,
+       9,   108,     9,     3,     9,   115,     9,     9,     9,     4,
+       9,     9,     9,   102,   103,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    10,    11,    12,    13,    14,    15,     4,    17,
+      18,    19,    20,    21,    22,    23,    24,     4,    26,    27,
+       4,     9,    30,     9,     9,    -1,     9,     9,     9,     9,
+       9,     9,     9,     9,     9,     9,     9,     9
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    43,    44,     0,    10,    11,    12,    13,    14,    15,
+       0,    49,    50,     0,    10,    11,    12,    13,    14,    15,
       17,    18,    19,    20,    21,    22,    23,    24,    26,    27,
-      30,    45,    46,    47,    16,     4,     4,     9,     4,     4,
-       4,     4,     4,    13,     3,     4,     7,    48,    45,    13,
-       9,     9,     9,     9,     9,     9,    25,    50,     9,     3,
-      12,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    49,    45,     9,     9,     9,     9,     9,     9,
-       4,    49,    49,     9,    49,    49,    49,    49,    49,     9,
-       9,     9,     7,    52,     5,    51,    52,    52,    51,     9,
-       9,     9,     9,     9,    51,    51,    51,     9,    49,    49,
-      52,    51
+      30,    51,    52,    16,     4,     4,     9,     4,     4,     4,
+       4,     4,    13,     3,    55,     4,     7,    53,    51,     9,
+       9,     9,     9,     9,     9,    55,     9,     3,    12,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    54,     9,     9,     9,
+       9,     9,     9,     4,    54,    54,     9,     4,     4,     4,
+      54,    54,    54,    54,    54,     9,     9,    54,    54,     9,
+       7,    57,     5,    56,    57,    57,    56,     9,     9,     9,
+       9,     9,     9,     9,     9,    56,    56,    56,     9,     9,
+       9,     9,    54,    54,    56,    57,    56
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    42,    43,    44,    45,    45,    45,    46,    47,    47,
-      47,    47,    47,    47,    47,    47,    47,    47,    47,    47,
-      47,    47,    47,    47,    48,    49,    49,    49,    49,    49,
-      49,    49,    49,    49,    49,    49,    49,    49,    50,    50,
-      51,    51,    52,    52
+       0,    48,    49,    50,    51,    51,    52,    52,    52,    52,
+      52,    52,    52,    52,    52,    52,    52,    52,    52,    52,
+      52,    52,    52,    53,    54,    54,    54,    54,    54,    54,
+      54,    54,    54,    54,    54,    54,    54,    54,    54,    54,
+      54,    54,    54,    55,    55,    56,    56,    57,    57
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     2,     0,     3,     1,     2,     1,     3,     6,
-       1,     1,     2,     6,     3,     5,     6,     5,     2,     2,
-       6,     3,     3,     2,     0,     2,     2,     6,     3,     2,
-       2,     2,     2,     2,     4,     4,     1,     0,     1,     0,
-       1,     0,     1,     0
+       0,     2,     2,     0,     2,     0,     3,     6,     1,     1,
+       2,     7,     3,     5,     6,     5,     2,     2,     6,     3,
+       3,     2,     1,     0,     2,     2,     6,     3,     1,     4,
+       4,     4,     2,     2,     2,     2,     2,     4,     4,     2,
+       2,     1,     0,     1,     0,     1,     0,     1,     0
 };
 
 
@@ -1356,17 +1366,11 @@ yyreduce:
 	smenu_idx.push_back(-1);
 	stack.push_back(new Hotspots());
 }
-#line 1360 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1370 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 7:
+  case 6:
 #line 87 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debugC(1, kHypnoDebugParser, "implicit END"); }
-#line 1366 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
-    break;
-
-  case 8:
-#line 90 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Hotspot *hot = new Hotspot(); 
 		hot->type = MakeMenu;
@@ -1382,11 +1386,11 @@ yyreduce:
 		smenu_idx.pop_back();
 		smenu_idx.push_back(idx);
 	}
-#line 1386 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1390 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 9:
-#line 105 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 7:
+#line 102 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {  
 		Hotspot *hot = new Hotspot(); 
 		hot->type = MakeHotspot;
@@ -1396,11 +1400,11 @@ yyreduce:
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot); 
 	}
-#line 1400 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1404 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 10:
-#line 114 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 8:
+#line 111 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		// This should always point to a hotspot
 		int idx = smenu_idx.back();
@@ -1416,43 +1420,43 @@ yyreduce:
 		stack.push_back(hot->smenu);
 		debugC(1, kHypnoDebugParser, "SUBMENU"); 
 	}
-#line 1420 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1424 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 11:
-#line 129 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 9:
+#line 126 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Escape *a = new Escape();
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "ESC SUBMENU"); }
-#line 1431 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1435 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 12:
-#line 135 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 10:
+#line 132 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "TIME %d", (yyvsp[0].i)); }
-#line 1437 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1441 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 13:
-#line 136 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 11:
+#line 133 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Background *a = new Background();
-		a->path = (yyvsp[-4].s);
-		a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-		a->condition = (yyvsp[-1].s);
+		a->path = (yyvsp[-5].s);
+		a->origin = Common::Point((yyvsp[-4].i), (yyvsp[-3].i));
+		a->condition = (yyvsp[-2].s);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "BACK");
 	}
-#line 1452 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1456 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 14:
-#line 146 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 12:
+#line 143 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Global *a = new Global();
 		a->variable = (yyvsp[-1].s);
@@ -1462,11 +1466,11 @@ yyreduce:
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "GLOB"); 
 	}
-#line 1466 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1470 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 15:
-#line 155 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 13:
+#line 152 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Ambient *a = new Ambient();
 		a->path = (yyvsp[-3].s);
@@ -1476,11 +1480,11 @@ yyreduce:
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);			
 		debugC(1, kHypnoDebugParser, "AMBI %d %d", (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1480 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1484 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 16:
-#line 164 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 14:
+#line 161 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Play *a = new Play();
 		a->path = (yyvsp[-4].s);
@@ -1491,11 +1495,11 @@ yyreduce:
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "PLAY %s.", (yyvsp[-4].s)); }
-#line 1495 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1499 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 17:
-#line 174 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 15:
+#line 171 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Overlay *a = new Overlay();
 		a->path = (yyvsp[-3].s);
@@ -1504,11 +1508,11 @@ yyreduce:
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 	}
-#line 1508 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1512 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 18:
-#line 182 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 16:
+#line 179 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Palette *a = new Palette();
 		a->path = (yyvsp[0].s); 
@@ -1517,11 +1521,11 @@ yyreduce:
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "PALE");
 	}
-#line 1521 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1525 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 19:
-#line 190 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 17:
+#line 187 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Cutscene *a = new Cutscene();
 		a->path = (yyvsp[0].s);
@@ -1530,11 +1534,11 @@ yyreduce:
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "CUTS %s", (yyvsp[0].s)); 
 	}
-#line 1534 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1538 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 20:
-#line 198 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 18:
+#line 195 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		WalN *a = new WalN();
 		a->path = (yyvsp[-4].s);
@@ -1545,11 +1549,11 @@ yyreduce:
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "WALN %s %d %d", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
-#line 1549 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1553 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 21:
-#line 208 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 19:
+#line 205 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Mice *a = new Mice();
 		a->path = (yyvsp[-1].s); 
@@ -1558,122 +1562,152 @@ yyreduce:
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 	}
-#line 1562 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1566 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 22:
-#line 216 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 20:
+#line 213 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(talk_action);
 		talk_action = nullptr;
 		debugC(1, kHypnoDebugParser, "TALK"); }
-#line 1573 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1577 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 23:
-#line 222 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 21:
+#line 219 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		debugC(1, kHypnoDebugParser, "explicit END");
 		g_parsedHots = stack.back(); 
 		stack.pop_back();
 		smenu_idx.pop_back();
 	}
-#line 1584 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1588 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 24:
-#line 230 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 22:
+#line 225 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debug("implicit END"); }
+#line 1594 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 228 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 	assert(talk_action == nullptr);
 	talk_action = new Talk();
 	talk_action->active = true; 
 }
-#line 1594 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1604 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 25:
-#line 236 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 24:
+#line 234 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		talk_action->active = false; 
 		debugC(1, kHypnoDebugParser, "inactive"); }
-#line 1602 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1612 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 26:
-#line 239 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 25:
+#line 237 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "inactive"); }
-#line 1608 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1618 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 27:
-#line 240 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 26:
+#line 238 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		talk_action->background = (yyvsp[-4].s);
 		talk_action->position = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
 		debugC(1, kHypnoDebugParser, "BACK in TALK"); }
-#line 1617 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1627 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 28:
-#line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 27:
+#line 242 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "BOXX %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1623 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1633 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 28:
+#line 243 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "ESCAPE"); }
+#line 1639 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
+#line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "SECOND %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1645 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 30:
 #line 245 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "INTRO %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1651 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 31:
+#line 246 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "DEFAULT %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
+#line 1657 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 32:
+#line 247 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "G";
 		talk_cmd.path = (yyvsp[-1].s)+2;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1634 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1668 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 30:
-#line 251 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 33:
+#line 253 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1640 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1674 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 31:
-#line 252 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 34:
+#line 254 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "F";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1651 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1685 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 32:
-#line 258 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 35:
+#line 260 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "A";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "|A%d", talk_cmd.num); }
-#line 1662 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1696 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 33:
-#line 264 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 36:
+#line 266 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "D";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1673 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1707 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 34:
-#line 270 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 37:
+#line 272 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "P";
@@ -1681,11 +1715,11 @@ yyreduce:
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);
 		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1685 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1719 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 35:
-#line 277 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 38:
+#line 279 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "I";
@@ -1693,41 +1727,70 @@ yyreduce:
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);		  
 		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1697 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1731 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 36:
-#line 284 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { debugC(1, kHypnoDebugParser, "|E"); }
-#line 1703 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+  case 39:
+#line 286 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "S";
+		talk_cmd.variable = (yyvsp[-1].s)+2;
+		talk_action->commands.push_back(talk_cmd);
+		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
+#line 1742 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
 #line 292 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
-    { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "flag: %s", (yyvsp[0].s)); }
-#line 1709 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "|L"); }
+#line 1748 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
 #line 293 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { debugC(1, kHypnoDebugParser, "|E"); }
+#line 1754 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 43:
+#line 297 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "name: %s", (yyvsp[0].s)); }
+#line 1760 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 44:
+#line 298 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1715 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1766 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 45:
+#line 301 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "flag: %s", (yyvsp[0].s)); }
+#line 1772 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 42:
-#line 296 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 46:
+#line 302 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+    { (yyval.s) = scumm_strdup(""); }
+#line 1778 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+    break;
+
+  case 47:
+#line 305 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "switch %s", (yyvsp[0].s)); }
-#line 1721 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1784 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
-  case 43:
-#line 297 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+  case 48:
+#line 306 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1727 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1790 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1731 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1794 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_mis.y b/engines/hypno/grammar_mis.y
index 3044e9ebf7..22e323e9ab 100644
--- a/engines/hypno/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -61,13 +61,13 @@ using namespace Hypno;
 
 %token<s> NAME FILENAME FLAG COMMENT GSSWITCH COMMAND
 %token<i> NUM
-%token HOTSTOK CUTSTOK BACKTOK RETTOK  TIMETOK PALETOK BBOXTOK OVERTOK WALNTOK MICETOK PLAYTOK ENDTOK 
+%token HOTSTOK CUTSTOK BACKTOK RETTOK TIMETOK PALETOK BBOXTOK OVERTOK WALNTOK MICETOK PLAYTOK ENDTOK 
 %token MENUTOK SMENTOK ESCPTOK NRTOK AMBITOK
 %token GLOBTOK TONTOK TOFFTOK
-%token TALKTOK INACTOK FDTOK BOXXTOK
-%token<s> PG PA PD PH PF PE PP PI
+%token TALKTOK INACTOK FDTOK BOXXTOK ESCAPETOK SECONDTOK INTROTOK DEFAULTTOK
+%token<s> PG PA PD PH PF PE PP PI PL PS
 
-%type<s> gsswitch flag
+%type<s> gsswitch flag mflag
 
 %%
 
@@ -79,15 +79,12 @@ init: {
 	stack.push_back(new Hotspots());
 }
 
-lines:   line RETTOK lines
-	| line
-	| end lines
+lines: line lines
+	| /* nothing */
 	; 
 
-end: RETTOK  { debugC(1, kHypnoDebugParser, "implicit END"); }
-	; 
 
-line: MENUTOK NAME mflag  {
+line: MENUTOK mflag mflag  {
 		Hotspot *hot = new Hotspot(); 
 		hot->type = MakeMenu;
 		hot->stype = $2;
@@ -133,7 +130,7 @@ line: MENUTOK NAME mflag  {
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "ESC SUBMENU"); }
 	|  TIMETOK NUM  { debugC(1, kHypnoDebugParser, "TIME %d", $2); } 
-	|  BACKTOK FILENAME NUM NUM gsswitch flag {
+	|  BACKTOK FILENAME NUM NUM gsswitch flag flag {
 		Background *a = new Background();
 		a->path = $2;
 		a->origin = Common::Point($3, $4);
@@ -225,6 +222,7 @@ line: MENUTOK NAME mflag  {
 		stack.pop_back();
 		smenu_idx.pop_back();
 	}
+	|	RETTOK { debug("implicit END"); }
 	;
 
 alloctalk: { 
@@ -242,6 +240,10 @@ talk: INACTOK talk {
 		talk_action->position = Common::Point($3, $4);
 		debugC(1, kHypnoDebugParser, "BACK in TALK"); }
 	| BOXXTOK NUM NUM { debugC(1, kHypnoDebugParser, "BOXX %d %d", $2, $3); }
+	| ESCAPETOK { debugC(1, kHypnoDebugParser, "ESCAPE"); }
+	| SECONDTOK FILENAME NUM NUM { debugC(1, kHypnoDebugParser, "SECOND %s %d %d", $2, $3, $4); }
+	| INTROTOK FILENAME NUM NUM { debugC(1, kHypnoDebugParser, "INTRO %s %d %d", $2, $3, $4); }
+	| DEFAULTTOK FILENAME NUM NUM { debugC(1, kHypnoDebugParser, "DEFAULT %s %d %d", $2, $3, $4); }
 	| PG talk { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "G";
@@ -281,12 +283,19 @@ talk: INACTOK talk {
 		talk_cmd.position = Common::Point($2, $3);
 		talk_action->commands.push_back(talk_cmd);		  
 		debugC(1, kHypnoDebugParser, "%s %d %d", $1, $2, $3); }
+	| PS talk { 
+		TalkCommand talk_cmd;
+		talk_cmd.command = "S";
+		talk_cmd.variable = $1+2;
+		talk_action->commands.push_back(talk_cmd);
+		debugC(1, kHypnoDebugParser, "%s", $1); }
+	| PL talk { debugC(1, kHypnoDebugParser, "|L"); }
 	| PE { debugC(1, kHypnoDebugParser, "|E"); }
 	| /*nothing*/
 	;
 
-mflag:  NRTOK
-	| /*nothing*/
+mflag: NAME { $$ = $1; debugC(1, kHypnoDebugParser, "name: %s", $1); }
+	| /* nothing */	{ $$ = scumm_strdup(""); }
 	;
 
 flag:   FLAG 		{ $$ = $1; debugC(1, kHypnoDebugParser, "flag: %s", $1); }
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 07869b8471..b26f7f020d 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -133,6 +133,7 @@ Common::Error HypnoEngine::run() {
 	loadAssets();
 	_nextLevel = "<start>";
 	while (!shouldQuit()) {
+		debug("nextLevel: %s", _nextLevel.c_str());
 		_defaultCursor = "";
 		_prefixDir = "";
 		_videosPlaying.clear();
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index c7ad21d552..59b1552048 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -245,6 +245,9 @@ class SpiderEngine : public HypnoEngine {
 public:
 	SpiderEngine(OSystem *syst, const ADGameDescription *gd);
 	void loadAssets() override;
+	void loadAssetsDemo();
+	void loadAssetsFullGame();
+
 	void drawShoot(const Common::Point &target) override;
 	void drawPlayer() override;
 	void drawHealth() override;
diff --git a/engines/hypno/lexer_mis.cpp b/engines/hypno/lexer_mis.cpp
index f4d3e68295..0825ef7063 100644
--- a/engines/hypno/lexer_mis.cpp
+++ b/engines/hypno/lexer_mis.cpp
@@ -633,8 +633,8 @@ static void yynoreturn yy_fatal_error ( const char* msg  );
 	(yy_hold_char) = *yy_cp; \
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 39
-#define YY_END_OF_BUFFER 40
+#define YY_NUM_RULES 45
+#define YY_END_OF_BUFFER 46
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -642,22 +642,24 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static const flex_int16_t yy_accept[131] =
+static const flex_int16_t yy_accept[144] =
     {   0,
-        0,    0,   40,   38,   37,   39,   38,   38,   32,   35,
-       35,    1,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   38,   37,
-       36,   35,   32,   32,    0,    1,   34,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,    0,
-        0,   28,    0,    0,    0,    0,    0,   32,    0,   33,
-       33,   33,   33,   11,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   25,
-       26,   27,   21,   24,   23,   22,   32,    0,    3,    4,
-
-       20,    5,   15,    6,   30,    8,   33,    2,   10,   33,
-       13,    7,   16,   14,   17,   12,    9,   32,   19,   33,
-       33,   31,   33,   33,   33,   33,   18,   33,   29,    0
+        0,    0,   46,   44,   43,   42,   42,   44,   38,   41,
+       41,   44,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   42,   43,
+       41,    0,   38,   38,    0,    1,   40,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+        0,    0,   34,    0,    0,    0,    0,   35,    0,    0,
+        2,   38,    0,   39,   39,   39,   39,   39,   12,   39,
+       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
+       39,   39,   39,   39,   39,   31,   32,   33,   27,   30,
+
+       29,   28,   26,   38,    0,    4,    5,   21,    6,   39,
+       39,   16,    7,   36,    9,   39,   39,    3,   11,   14,
+        8,   17,   39,   15,   18,   13,   10,   38,   20,   39,
+       39,   39,   24,   39,   37,   39,   22,   39,   23,   25,
+       39,   19,    0
     } ;
 
 static const YY_CHAR yy_ec[256] =
@@ -666,16 +668,16 @@ static const YY_CHAR yy_ec[256] =
         1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    2,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    5,    1,    1,    6,    7,    8,    9,    9,   10,
-       10,   11,   10,   10,   10,   10,   10,    1,   12,    1,
-       13,    1,    1,    1,   14,   15,   16,   17,   18,   19,
-       20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
-       23,   30,   31,   32,   33,   34,   35,   36,   37,   23,
-        1,    7,    1,    1,   38,    1,   39,   39,   39,   39,
-
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,    1,   40,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    5,    6,    7,    8,    8,    9,
+        9,   10,    9,    9,    9,    9,    9,    1,   11,    1,
+       12,    1,    1,    1,   13,   14,   15,   16,   17,   18,
+       19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+       22,   29,   30,   31,   32,   33,   34,   35,   36,   22,
+        1,    6,    1,    1,   37,    1,   38,   38,   38,   38,
+
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,    1,   39,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -692,134 +694,144 @@ static const YY_CHAR yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static const YY_CHAR yy_meta[41] =
+static const YY_CHAR yy_meta[40] =
     {   0,
-        1,    2,    1,    1,    2,    1,    3,    1,    4,    4,
-        4,    1,    1,    4,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    4,    4,    4,    4,    4,
-        4,    4,    4,    4,    4,    4,    4,    4,    4,    1
+        1,    1,    2,    1,    1,    3,    4,    5,    5,    5,
+        1,    1,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    1
     } ;
 
-static const flex_int16_t yy_base[140] =
+static const flex_int16_t yy_base[155] =
     {   0,
-        0,    0,  266,  267,  263,  267,  261,   32,  248,   35,
-       38,    0,   43,   44,   45,  255,   46,   49,   47,   52,
-       63,   54,   50,   69,   60,   81,   57,    0,   90,  259,
-      267,   80,    0,  245,  244,    0,    0,  251,   53,   80,
-       56,   86,   98,   90,   92,   91,   93,  107,   95,  110,
-       94,  106,  109,  116,  120,  121,  124,  126,    0,  126,
-      130,  267,  133,    0,  138,    0,    0,  229,  215,  138,
-      145,  146,  147,  231,  148,  149,  150,  152,  151,  154,
-      155,  156,  158,  161,  159,  163,  167,  174,  186,  188,
-      191,  194,    0,  197,    0,    0,  200,  199,  227,  226,
-
-      225,  224,  223,  222,  173,  221,  177,  220,  217,  203,
-      216,  215,  213,  211,  178,  169,  168,  159,  267,  204,
-      187,  267,  206,  208,  207,  209,  164,  210,   59,  267,
-       61,  240,  242,   58,  244,  246,  248,  250,  252
+        0,    0,  299,  300,  296,  300,  300,   32,   36,   36,
+       39,    0,   45,   46,   47,   48,   50,  291,   51,   55,
+       52,   66,   56,   61,   71,   78,   58,    0,   87,  294,
+       84,    0,  287,   83,  277,    0,    0,  282,   54,   80,
+       63,   95,   96,  103,  106,  104,  107,  110,  112,  114,
+      117,  116,  118,  121,  122,  129,  123,  124,  130,    0,
+      142,  147,  300,  150,    0,  153,    0,  300,    0,    0,
+        0,  138,  258,  132,  158,  133,  142,  160,  276,  161,
+      163,  164,  165,  169,  170,  172,  173,  174,  176,  177,
+      179,  181,  182,  180,  186,  200,  206,  209,    0,  212,
+
+        0,    0,    0,  189,  244,  268,  265,  260,  255,  194,
+      195,  254,  252,  192,  251,  205,  185,  250,  249,  248,
+      247,  246,  219,  245,  244,  241,  238,  220,  300,  222,
+      223,  227,  237,  225,  300,  228,  236,  229,  233,  231,
+      232,   60,  300,  259,  264,  267,   58,  272,  275,  278,
+      281,  284,  287,  290
     } ;
 
-static const flex_int16_t yy_def[140] =
+static const flex_int16_t yy_def[155] =
     {   0,
-      130,    1,  130,  130,  130,  130,  130,  130,  131,  130,
-      130,  132,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  134,  130,  130,
-      130,  130,  131,  131,  130,  132,  135,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  134,  130,
-      130,  130,  130,  136,  130,  137,  138,  131,  130,  133,
-      133,  133,  133,  133,  133,  133,  139,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  133,  133,  130,
-      130,  130,  136,  130,  137,  138,  131,  130,  133,  133,
-
-      133,  133,  133,  133,  139,  133,  133,  133,  133,  133,
-      133,  133,  133,  133,  133,  133,  133,  131,  130,  133,
-      133,  130,  133,  133,  133,  133,  133,  133,  133,    0,
-      130,  130,  130,  130,  130,  130,  130,  130,  130
+      143,    1,  143,  143,  143,  143,  143,  143,  144,  143,
+      143,  145,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  147,  143,  143,
+      143,  148,  144,  144,  143,  145,  149,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  147,
+      143,  143,  143,  143,  150,  143,  151,  143,  152,  153,
+      148,  144,  143,  146,  146,  146,  146,  146,  146,  146,
+      146,  154,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  143,  143,  143,  150,  143,
+
+      151,  152,  153,  144,  143,  146,  146,  146,  146,  146,
+      146,  146,  146,  154,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  144,  143,  146,
+      146,  146,  146,  146,  143,  146,  146,  146,  146,  146,
+      146,  146,    0,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143
     } ;
 
-static const flex_int16_t yy_nxt[308] =
+static const flex_int16_t yy_nxt[340] =
     {   0,
-        4,    5,    6,    7,    4,    8,    4,    9,   10,   10,
-       11,   12,    4,   13,   14,   15,   16,   17,   16,   18,
-       19,   20,   16,   16,   16,   21,   22,   23,   24,   16,
-       25,   26,   16,   16,   27,   16,   16,   28,   16,   29,
-       32,   32,   32,   32,   32,   32,   32,   32,   32,   37,
-       37,   37,   37,   37,   35,   37,   37,   40,   37,   37,
-       37,   59,   37,   37,   33,   37,   37,   70,   39,   37,
-       58,   41,   43,   45,   47,   37,   44,   42,   48,   46,
-       49,   51,   53,   52,   50,   55,   37,   37,   32,   32,
-       32,   72,   37,   54,   56,   71,   37,   37,   37,   37,
-
-       37,   37,   57,   60,   37,   75,   61,   62,   63,   64,
-       65,   66,   37,   37,   74,   37,   37,   73,   67,   76,
-       79,   80,   37,   83,   78,   81,   37,   37,   77,   85,
-       37,   82,   37,   84,   90,   90,   90,   86,   91,   91,
-       91,   92,   92,   92,   37,   87,   94,   94,   94,   88,
-       89,   37,   37,   37,   37,   37,   37,   37,   37,   99,
-       37,   37,   37,  104,   37,   37,  107,   37,  100,   37,
-       37,  122,  109,   37,   37,   37,  103,  102,  112,   37,
-       37,  101,  106,   37,   37,  110,  108,  111,   38,  114,
-      115,  116,   37,   37,  117,  113,   90,   90,   90,   91,
-
-       91,   91,   92,   92,   92,   94,   94,   94,  120,   37,
-       37,   38,   37,   37,   37,   37,   37,   37,  124,   37,
-      121,   37,   37,   37,  127,  123,   37,   37,   37,   37,
-       37,   37,   37,   37,  119,  118,  129,   37,  128,  125,
-      126,   36,   98,   36,   38,   38,   37,   37,   93,   93,
-       95,   95,   96,   96,  105,  105,   97,   37,   69,   68,
-       30,   37,   34,   31,   30,  130,    3,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130
+        4,    5,    6,    7,    8,    4,    9,   10,   10,   11,
+       12,    4,   13,   14,   15,   16,   17,   18,   19,   20,
+       21,   18,   18,   18,   22,   18,   23,   24,   18,   25,
+       26,   18,   18,   27,   18,   18,   28,   18,   29,   31,
+       31,   31,   32,   31,   31,   31,   31,   31,   31,   34,
+       37,   37,   37,   37,   35,   37,   37,   37,   40,   37,
+       37,   37,   60,   37,   43,   37,   37,   74,   37,   39,
+       59,   37,   41,   53,   46,   44,   37,   49,   42,   45,
+       47,   48,   50,   37,   54,   37,   51,   55,   52,  143,
+       57,   31,   31,   31,   75,   56,   72,   76,   58,   61,
+
+       37,   37,   62,   63,   64,   65,   66,   67,   37,   37,
+       68,   37,   37,   78,   69,   37,   70,   37,   79,   37,
+       80,   37,   37,   37,   84,   77,   37,   37,   37,   37,
+       81,   87,   88,   90,   37,   37,   91,   37,   37,   86,
+       83,   89,   85,   82,  143,   92,   93,   37,   94,   96,
+       96,   96,  106,   95,   97,   97,   97,   98,   98,   98,
+      100,  100,  100,   37,  104,   37,   37,  108,   37,   37,
+       37,  109,  110,  111,   37,   37,  113,   37,   37,   37,
+      107,   37,   37,  116,   37,   37,   37,   37,  112,  119,
+       37,   37,  121,  127,  115,  143,  126,   37,  117,   37,
+
+       37,   38,  120,  118,  125,  123,  124,   96,   96,   96,
+       37,  133,  122,   97,   97,   97,   98,   98,   98,  100,
+      100,  100,  131,  128,   37,  130,  143,   37,   37,   38,
+       37,  135,   37,   37,   37,  132,   37,   37,   37,  137,
+      139,   37,   37,   37,  134,  136,   37,  138,  142,   37,
+       37,   37,   37,   37,   37,   37,   37,   37,  140,   37,
+       37,  141,   33,   33,   36,   37,   36,   36,   36,   38,
+       37,   38,   71,   37,   71,   71,   71,   37,  129,   37,
+       99,   37,   99,  101,  105,  101,  102,   37,  102,  103,
+       73,  103,  114,  143,  114,   30,   37,   30,  143,    3,
+
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143
     } ;
 
-static const flex_int16_t yy_chk[308] =
+static const flex_int16_t yy_chk[340] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        8,    8,    8,   10,   10,   10,   11,   11,   11,   13,
-       14,   15,   17,   19,   11,   18,   23,   14,   20,   39,
-       22,  134,   41,   27,  131,  129,   25,   39,   13,   21,
-       27,   14,   17,   18,   19,   24,   17,   15,   20,   18,
-       21,   22,   24,   23,   21,   25,   40,   26,   32,   32,
-       32,   41,   42,   24,   26,   40,   44,   46,   45,   47,
-
-       51,   49,   26,   29,   43,   44,   29,   29,   29,   29,
-       29,   29,   52,   48,   43,   53,   50,   42,   29,   45,
-       48,   49,   54,   52,   47,   50,   55,   56,   46,   54,
-       57,   51,   58,   53,   60,   60,   60,   55,   61,   61,
-       61,   63,   63,   63,   70,   56,   65,   65,   65,   57,
-       58,   71,   72,   73,   75,   76,   77,   79,   78,   70,
-       80,   81,   82,   76,   83,   85,   79,   84,   71,   86,
-      127,  118,   81,   87,  117,  116,   75,   73,   84,  105,
-       88,   72,   78,  107,  115,   82,   80,   83,   77,   86,
-       87,   88,   89,  121,   89,   85,   90,   90,   90,   91,
-
-       91,   91,   92,   92,   92,   94,   94,   94,  107,  110,
-      120,  105,  123,  125,  124,  126,  128,  114,  121,  113,
-      110,  112,  111,  109,  125,  120,  108,  106,  104,  103,
-      102,  101,  100,   99,   98,   97,  128,   74,  126,  123,
-      124,  132,   69,  132,  133,  133,  135,  135,  136,  136,
-      137,  137,  138,  138,  139,  139,   68,   38,   35,   34,
-       30,   16,    9,    7,    5,    3,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
-
-      130,  130,  130,  130,  130,  130,  130
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    8,
+        8,    8,    9,   10,   10,   10,   11,   11,   11,    9,
+       13,   14,   15,   16,   11,   17,   19,   21,   14,   39,
+       20,   23,  147,   27,   16,  142,   24,   39,   41,   13,
+       27,   22,   14,   24,   19,   17,   25,   21,   15,   17,
+       19,   20,   22,   26,   24,   40,   22,   25,   23,   34,
+       26,   31,   31,   31,   40,   25,   34,   41,   26,   29,
+
+       42,   43,   29,   29,   29,   29,   29,   29,   44,   46,
+       29,   45,   47,   43,   29,   48,   29,   49,   44,   50,
+       45,   52,   51,   53,   49,   42,   54,   55,   57,   58,
+       46,   51,   52,   54,   56,   59,   55,   74,   76,   50,
+       48,   53,   49,   47,   72,   56,   57,   77,   58,   61,
+       61,   61,   74,   59,   62,   62,   62,   64,   64,   64,
+       66,   66,   66,   75,   72,   78,   80,   76,   81,   82,
+       83,   77,   78,   80,   84,   85,   81,   86,   87,   88,
+       75,   89,   90,   84,   91,   94,   92,   93,   80,   87,
+      117,   95,   89,   95,   83,  104,   94,  114,   85,  110,
+
+      111,   82,   88,   86,   93,   91,   92,   96,   96,   96,
+      116,  117,   90,   97,   97,   97,   98,   98,   98,  100,
+      100,  100,  111,  104,  123,  110,  128,  130,  131,  114,
+      134,  128,  132,  136,  138,  116,  140,  141,  139,  131,
+      134,  137,  133,  127,  123,  130,  126,  132,  141,  125,
+      124,  122,  121,  120,  119,  118,  115,  113,  136,  112,
+      109,  138,  144,  144,  145,  108,  145,  145,  145,  146,
+      107,  146,  148,  106,  148,  148,  148,  149,  105,  149,
+      150,   79,  150,  151,   73,  151,  152,   38,  152,  153,
+       35,  153,  154,   33,  154,   30,   18,    5,    3,  143,
+
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,
+      143,  143,  143,  143,  143,  143,  143,  143,  143
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static const flex_int32_t yy_rule_can_match_eol[40] =
+static const flex_int32_t yy_rule_can_match_eol[46] =
     {   0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
-        };
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 1, 0, 0, 0,     };
 
 static yy_state_type yy_last_accepting_state;
 static char *yy_last_accepting_cpos;
@@ -866,8 +878,8 @@ char *yytext;
 #include "hypno/grammar.h"
 #include "hypno/tokens_mis.h"
 
-#line 870 "engines/hypno/lexer_mis.cpp"
-#line 871 "engines/hypno/lexer_mis.cpp"
+#line 882 "engines/hypno/lexer_mis.cpp"
+#line 883 "engines/hypno/lexer_mis.cpp"
 
 #define INITIAL 0
 
@@ -1084,7 +1096,7 @@ YY_DECL
 	{
 #line 42 "engines/hypno/lexer_mis.l"
 
-#line 1088 "engines/hypno/lexer_mis.cpp"
+#line 1100 "engines/hypno/lexer_mis.cpp"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -1111,13 +1123,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 131 )
+				if ( yy_current_state >= 144 )
 					yy_c = yy_meta[yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 130 );
+		while ( yy_current_state != 143 );
 		yy_cp = (yy_last_accepting_cpos);
 		yy_current_state = (yy_last_accepting_state);
 
@@ -1155,195 +1167,225 @@ YY_RULE_SETUP
 case 2:
 YY_RULE_SETUP
 #line 44 "engines/hypno/lexer_mis.l"
-return MENUTOK;
+/* return COMMENT; */
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
 #line 45 "engines/hypno/lexer_mis.l"
-return AMBITOK;
+return MENUTOK;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
 #line 46 "engines/hypno/lexer_mis.l"
-return BACKTOK;
+return AMBITOK;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
 #line 47 "engines/hypno/lexer_mis.l"
-return CUTSTOK;
+return BACKTOK;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
 #line 48 "engines/hypno/lexer_mis.l"
-return GLOBTOK;
+return CUTSTOK;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
 #line 49 "engines/hypno/lexer_mis.l"
-return PALETOK;
+return GLOBTOK;
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
 #line 50 "engines/hypno/lexer_mis.l"
-return HOTSTOK;
+return PALETOK;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
 #line 51 "engines/hypno/lexer_mis.l"
-return WALNTOK;
+return HOTSTOK;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
 #line 52 "engines/hypno/lexer_mis.l"
-return MICETOK;
+return WALNTOK;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
 #line 53 "engines/hypno/lexer_mis.l"
-return ENDTOK;
+return MICETOK;
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
 #line 54 "engines/hypno/lexer_mis.l"
-return TIMETOK;
+return ENDTOK;
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
 #line 55 "engines/hypno/lexer_mis.l"
-return OVERTOK;
+return TIMETOK;
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
 #line 56 "engines/hypno/lexer_mis.l"
-return SMENTOK;
+return OVERTOK;
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
 #line 57 "engines/hypno/lexer_mis.l"
-return ESCPTOK;
+return SMENTOK;
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
 #line 58 "engines/hypno/lexer_mis.l"
-return PLAYTOK;
+return ESCPTOK;
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
 #line 59 "engines/hypno/lexer_mis.l"
-return TALKTOK;
+return PLAYTOK;
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
 #line 60 "engines/hypno/lexer_mis.l"
-return INACTOK;
+return TALKTOK;
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
 #line 61 "engines/hypno/lexer_mis.l"
-return FDTOK;
+return INACTOK;
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
 #line 62 "engines/hypno/lexer_mis.l"
-return BOXXTOK;
+return FDTOK;
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
 #line 63 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PG;
+return BOXXTOK;
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
 #line 64 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PP;
+return ESCAPETOK;
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
 #line 65 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PI;
+return SECONDTOK;
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
 #line 66 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PH;
+return INTROTOK;
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
 #line 67 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PA;
+return DEFAULTTOK;
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
 #line 68 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PD;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PS;
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
 #line 69 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PF;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PG;
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
 #line 70 "engines/hypno/lexer_mis.l"
-return PE;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PP;
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
 #line 71 "engines/hypno/lexer_mis.l"
-return NRTOK;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PI;
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
 #line 72 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PH;
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
 #line 73 "engines/hypno/lexer_mis.l"
-return BBOXTOK;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PA;
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
 #line 74 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FLAG;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PD;
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
 #line 75 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return NAME;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PF;
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
 #line 76 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FILENAME;
+return PE;
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
 #line 77 "engines/hypno/lexer_mis.l"
-HYPNO_MIS_lval.i = atoi(HYPNO_MIS_text); return NUM;
+return PL;
 	YY_BREAK
 case 36:
-/* rule 36 can match eol */
 YY_RULE_SETUP
 #line 78 "engines/hypno/lexer_mis.l"
-return RETTOK;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
 #line 79 "engines/hypno/lexer_mis.l"
-/* ignore whitespace */;
+return BBOXTOK;
 	YY_BREAK
 case 38:
 YY_RULE_SETUP
 #line 80 "engines/hypno/lexer_mis.l"
-debug("<no match>"); return *yytext;
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FLAG;
 	YY_BREAK
 case 39:
 YY_RULE_SETUP
 #line 81 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return NAME;
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 82 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FILENAME;
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 83 "engines/hypno/lexer_mis.l"
+HYPNO_MIS_lval.i = atoi(HYPNO_MIS_text); return NUM;
+	YY_BREAK
+case 42:
+/* rule 42 can match eol */
+YY_RULE_SETUP
+#line 84 "engines/hypno/lexer_mis.l"
+return RETTOK;
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 85 "engines/hypno/lexer_mis.l"
+/* ignore whitespace */;
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 86 "engines/hypno/lexer_mis.l"
+debug("<no match: %c>", *yytext); return *yytext;
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 87 "engines/hypno/lexer_mis.l"
 ECHO;
 	YY_BREAK
-#line 1347 "engines/hypno/lexer_mis.cpp"
+#line 1389 "engines/hypno/lexer_mis.cpp"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -1641,7 +1683,7 @@ static int yy_get_next_buffer (void)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 131 )
+			if ( yy_current_state >= 144 )
 				yy_c = yy_meta[yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1669,11 +1711,11 @@ static int yy_get_next_buffer (void)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 131 )
+		if ( yy_current_state >= 144 )
 			yy_c = yy_meta[yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
-	yy_is_jam = (yy_current_state == 130);
+	yy_is_jam = (yy_current_state == 143);
 
 		return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2320,7 +2362,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 81 "engines/hypno/lexer_mis.l"
+#line 87 "engines/hypno/lexer_mis.l"
 
 
 namespace Hypno {
diff --git a/engines/hypno/lexer_mis.l b/engines/hypno/lexer_mis.l
index fcfb8fde88..508e5167f3 100644
--- a/engines/hypno/lexer_mis.l
+++ b/engines/hypno/lexer_mis.l
@@ -40,7 +40,8 @@
 %}
 
 %%
-\;[A-Za-z_0-9 \t\*]*		/* return COMMENT; */
+\;.+						/* return COMMENT; */
+\/\/.+						/* return COMMENT; */
 MENU						return MENUTOK;
 AMBI						return AMBITOK;
 BACK						return BACKTOK;
@@ -60,6 +61,11 @@ TALK						return TALKTOK;
 INACTIVE					return INACTOK;
 4DBOX						return FDTOK;
 BOXX						return BOXXTOK;
+ESCAPE						return ESCAPETOK;
+SECOND						return SECONDTOK;
+INTRO						return INTROTOK;
+DEFAULT						return DEFAULTTOK;
+\|S[A-Za-z_0-9\\\.]+		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PS;
 \|G[A-Za-z_0-9\\\.]+		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PG;
 \|P[A-Za-z_0-9\\\.]+		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PP;
 \|I[A-Za-z_0-9\\\.]+		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PI;
@@ -68,16 +74,16 @@ BOXX						return BOXXTOK;
 \|D[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PD;
 \|F[0-9]+					HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return PF;
 \|E							return PE;
-NO_RETURN					return NRTOK;
+\|L							return PL;
 GS_[A-Z_0-9]+				HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return GSSWITCH;
 \/BBOX\=					return BBOXTOK;
 \/[A-Za-z_0-9]*				HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FLAG;
 [A-Za-z_][A-Za-z_0-9]*		HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return NAME;
 [A-Za-z][A-Za-z_0-9\\\.]*	HYPNO_MIS_lval.s = scumm_strdup(HYPNO_MIS_text); return FILENAME;
 [\-]?[0-9]+					HYPNO_MIS_lval.i = atoi(HYPNO_MIS_text); return NUM;
-\r\n						return RETTOK;
+[\n|\r\n]					return RETTOK;
 [ \t]+						/* ignore whitespace */;
-.							debug("<no match>"); return *yytext;
+.							debug("<no match: %c>", *yytext); return *yytext;
 %%
 
 namespace Hypno {
diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 8a953a795e..0d688dd9c8 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -38,40 +38,50 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename,
 		warning("Failed to open %s", filename.c_str());
 		return false;
 	}
-	byte b;
-	uint32 size;
-	FileEntry f;
-	f.data.push_back(0);
-	do {
-		f.name = "";
-		f.data.clear();
-		for (uint32 i = 0; i < 12; i++) {
-			b = libfile.readByte();
-			if (b != 0x96 && b != 0x0)
-				f.name += tolower(char(b));
-		}
-		debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
-		uint32 start = libfile.readUint32LE();
-		size = libfile.readUint32LE();
-		libfile.readUint32LE(); // some field?
-
-		uint32 pos = libfile.pos();
-		libfile.seek(start);
-
-		for (uint32 i = 0; i < size; i++) {
-			b = libfile.readByte();
-			if (encrypted && b != '\n')
-				b = b ^ 0xfe;
-			f.data.push_back(b);
-		}
-		f.data.push_back(0x0);
-		//debug("f.data: %s", f.data.data());
-		debugC(1, kHypnoDebugParser, "size: %d", f.data.size());
-		libfile.seek(pos);
-		if (size > 0)
+	uint32 offset = 0;
+	while (offset < libfile.size()) {
+		byte b;
+		uint32 size = 0;
+		uint32 start = 0;
+		FileEntry f;
+		libfile.seek(offset);
+		while (true) {
+			f.name = "";
+			f.data.clear();
+			for (uint32 i = 0; i < 12; i++) {
+				b = libfile.readByte();
+				if (b != 0x96 && b != 0x0)
+					f.name += tolower(char(b));
+			}
+
+			if (!Common::isAlpha(*f.name.c_str()))
+				break;
+
+			debugC(1, kHypnoDebugParser, "file: %s", f.name.c_str());
+			start = libfile.readUint32LE();
+			size = libfile.readUint32LE();
+			if (size == 0)
+				error("Trying to load an empty file");
+			libfile.readUint32LE(); // some field?
+
+			uint32 pos = libfile.pos();
+			libfile.seek(start);
+
+			for (uint32 i = 0; i < size; i++) {
+				b = libfile.readByte();
+				if (encrypted && b != '\n')
+					b = b ^ 0xfe;
+				f.data.push_back(b);
+				//debugN("%c", b);
+			}
+			f.data.push_back(0x0);
+			debugC(1, kHypnoDebugParser, "start: %d, size: %d", start, f.data.size());
+			libfile.seek(pos);
 			_fileEntries.push_back(f);
 
-	} while (size > 0);
+		};
+		offset = start + size;
+	}
 	return true;
 }
 
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 153c4f4a6a..00f7d7bbe4 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -64,6 +64,7 @@ void HypnoEngine::parseScene(const Common::String &prefix, const Common::String
 	Common::String name = convertPath(filename);
 	if (!prefix.empty())
 		name = prefix + "/" + name;
+
 	Common::File test;
 	if (!test.open(name.c_str()))
 		error("Failed to open %s", name.c_str());
@@ -73,6 +74,7 @@ void HypnoEngine::parseScene(const Common::String &prefix, const Common::String
 	test.read(buf, fileSize);
 	test.close();
 	buf[fileSize] = '\0';
+	debug("%s", buf);
 	parse_mis(buf);
 	Level level;
 	level.scene.prefix = prefix;
@@ -254,8 +256,10 @@ void HypnoEngine::runScene(Scene &scene) {
 					leftClickedConversation(mousePos);
 					break;
 				}
-				if (!_nextHotsToAdd && !_nextHotsToRemove /*&& _videosPlaying.empty()*/)
+				if (!_nextHotsToAdd && !_nextHotsToRemove /*&& _videosPlaying.empty()*/) {
 					clickedHotspot(mousePos);
+					drawScreen();
+				}
 				break;
 
 			case Common::EVENT_MOUSEMOVE:
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index 504446f6b9..bab83823fd 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "common/events.h"
+#include "common/config-manager.h"
 
 #include "hypno/grammar.h"
 #include "hypno/hypno.h"
@@ -31,6 +32,68 @@ namespace Hypno {
 SpiderEngine::SpiderEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
 
 void SpiderEngine::loadAssets() {
+	if (!isDemo())
+		loadAssetsFullGame();
+	else
+		loadAssetsDemo();
+}
+
+void SpiderEngine::loadAssetsFullGame() {
+
+	Common::Language language = Common::parseLanguage(ConfMan.get("language"));
+	if (language == Common::EN_USA) {
+		if (!_installerArchive.open("DATA.Z"))
+			error("Failed to open DATA.Z");
+
+		SearchMan.add("DATA.Z", (Common::Archive *) &_installerArchive, 0, false);
+	}
+
+	Common::ArchiveMemberList files;
+	LibFile *missions = loadLib("", "spider/c_misc/missions.lib", true);
+	if (missions == nullptr || missions->listMembers(files) == 0)
+		error("Failed to load any file from missions.lib");
+
+	parseScene("", "mainmenu.mi_");
+	_levels["mainmenu.mi_"].scene.prefix = "spider";
+
+	parseScene("", "options.mi_");
+	_levels["options.mi_"].scene.prefix = "spider";
+
+	parseScene("", "levels.mi_");
+	_levels["levels.mi_"].scene.prefix = "spider";
+	_levels["levels.mi_"].scene.levelIfWin = "mv0t.mi_";
+
+	parseScene("", "combmenu.mi_");
+	_levels["combmenu.mi_"].scene.prefix = "spider";
+
+	parseScene("", "mv0t.mi_");
+	_levels["mv0t.mi_"].scene.prefix = "spider";
+
+	// start level
+	Level start;
+	start.trans.level = "mainmenu.mi_";
+	start.trans.intros.push_back("spider/cine/dcine1.smk");
+	start.trans.intros.push_back("spider/cine/dcine2.smk");
+	_levels["<start>"] = start;
+
+	ChangeLevel *cl = new ChangeLevel();
+	cl->level = "levels.mi_";
+	_levels["mainmenu.mi_"].scene.hots[1].actions.push_back(cl);
+	
+	cl = new ChangeLevel();
+	cl->level = "options.mi_";
+	_levels["mainmenu.mi_"].scene.hots[4].actions.push_back(cl);
+
+	cl = new ChangeLevel();
+	cl->level = "<quit>";
+	_levels["mainmenu.mi_"].scene.hots[5].actions.push_back(cl);
+
+	cl = new ChangeLevel();
+	cl->level = "combmenu.mi_";
+	_levels["options.mi_"].scene.hots[1].actions.push_back(cl);
+}
+
+void SpiderEngine::loadAssetsDemo() {
 
 	if (!_installerArchive.open("DATA.Z"))
 		error("Failed to open DATA.Z");
diff --git a/engines/hypno/tokens_mis.h b/engines/hypno/tokens_mis.h
index 9c073e386f..568e0f85e1 100644
--- a/engines/hypno/tokens_mis.h
+++ b/engines/hypno/tokens_mis.h
@@ -84,14 +84,20 @@ extern int HYPNO_MIS_debug;
     INACTOK = 286,
     FDTOK = 287,
     BOXXTOK = 288,
-    PG = 289,
-    PA = 290,
-    PD = 291,
-    PH = 292,
-    PF = 293,
-    PE = 294,
-    PP = 295,
-    PI = 296
+    ESCAPETOK = 289,
+    SECONDTOK = 290,
+    INTROTOK = 291,
+    DEFAULTTOK = 292,
+    PG = 293,
+    PA = 294,
+    PD = 295,
+    PH = 296,
+    PF = 297,
+    PE = 298,
+    PP = 299,
+    PI = 300,
+    PL = 301,
+    PS = 302
   };
 #endif
 
@@ -105,7 +111,7 @@ union HYPNO_MIS_STYPE
 	char *s; /* string value */
 	int i;	 /* integer value */
 
-#line 109 "engines/hypno/tokens_mis.h" /* yacc.c:1909  */
+#line 115 "engines/hypno/tokens_mis.h" /* yacc.c:1909  */
 };
 
 typedef union HYPNO_MIS_STYPE HYPNO_MIS_STYPE;
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index b40704e8d2..71cd30062a 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -196,7 +196,7 @@ void WetEngine::loadAssetsPCG() {
 		error("Failed to load any files from missions.lib");
 
 	Level intro;
-	intro.trans.level = "c31.mi_";
+	intro.trans.level = "c31.mi_";	
 	intro.trans.intros.push_back("nw_logo.smk");
 	intro.trans.intros.push_back("h.s");
 	intro.trans.intros.push_back("wet.smk");
@@ -232,6 +232,7 @@ void WetEngine::loadAssetsFullGame() {
 
 	Level intro;
 	intro.trans.level = "c111.mi_";
+	intro.trans.intros.push_back("c_misc/logo.smk");
 	intro.trans.intros.push_back("c_misc/nw_logo.smk");
 	intro.trans.intros.push_back("c_misc/hypnotix.smk");
 	intro.trans.intros.push_back("c_misc/wetlogo.smk");


Commit: 28e84c94e522af6f63d0fa67b35ba3bef88967e4
    https://github.com/scummvm/scummvm/commit/28e84c94e522af6f63d0fa67b35ba3bef88967e4
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: code formatting in arguments, detection tables and others

Changed paths:
    engines/hypno/detection.cpp
    engines/hypno/hypno.cpp
    engines/hypno/metaengine.cpp
    engines/hypno/scene.cpp


diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index fa8794d0fe..dee8f5921d 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -34,13 +34,13 @@ static const DebugChannelDef debugFlagList[] = {
 
 namespace Hypno {
 static const PlainGameDescriptor hypnoGames[] = {
-	{"sinister-six", "Marvel Comics Spider-Man: The Sinister Six"},
+	{"sinistersix", "Marvel Comics Spider-Man: The Sinister Six"},
 	{"wetlands", "Wetlands"},
-	{"soldier-boyz", "Soldier Boyz"},
+	{"soldierboyz", "Soldier Boyz"},
 	{0, 0}};
 
 static const ADGameDescription gameDescriptions[] = {
-	{"sinister-six", // Demo from the US release
+	{"sinistersix", // Demo from the US release
 	 "Demo",
 	 AD_ENTRY2s("DATA.Z",  "2a9c7cf8920ec794482f0a5873102da5", 1285960,
 				"DCINE1.SMK", "1ff3db09d148e8dd8b56d2e87e7296b8", 493752),
@@ -48,7 +48,7 @@ static const ADGameDescription gameDescriptions[] = {
 	 Common::kPlatformDOS,
 	 ADGF_TESTING | ADGF_DEMO,
 	 GUIO1(GUIO_NOMIDI)},
-	{"sinister-six", // US release
+	{"sinistersix", // US release
 	 _s("Missing game code"),
 	 AD_ENTRY2s("DATA.Z", "a1f71005a45e6ee454bb0bf3868dff54", 8766307,
 				"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
@@ -56,7 +56,7 @@ static const ADGameDescription gameDescriptions[] = {
 	 Common::kPlatformDOS,
 	 ADGF_UNSTABLE | ADGF_UNSUPPORTED,
 	 GUIO1(GUIO_NOMIDI)},
-	{"sinister-six", // ES release
+	{"sinistersix", // ES release
 	 _s("Missing game code"),
 	 AD_ENTRY2s("SPIDER.EXE", "dbd912d6f6724c6d44775fc19cfa8ca0", 483871,
 	 			"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
@@ -114,7 +114,7 @@ static const ADGameDescription gameDescriptions[] = {
 	 Common::kPlatformDOS,
 	 ADGF_UNSTABLE,
 	 GUIO1(GUIO_NOMIDI)},
-	{"soldier-boyz", // Solidier Boyz (US)
+	{"soldierboyz", // Solidier Boyz (US)
 	 _s("Missing game code"),
 	 AD_ENTRY2s("boyz.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 263347,
 				"setup.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 160740),
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index b26f7f020d..7931180697 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -46,14 +46,14 @@ Hotspots *g_parsedHots;
 ArcadeShooting g_parsedArc;
 HypnoEngine *g_hypno;
 
-MVideo::MVideo(Common::String _path, Common::Point _position, bool _transparent, bool _scaled, bool _loop) {
+MVideo::MVideo(Common::String path_, Common::Point position_, bool transparent_, bool scaled_, bool loop_) {
 	decoder = nullptr;
 	currentFrame = nullptr;
-	path = _path;
-	position = _position;
-	scaled = _scaled;
-	transparent = _transparent;
-	loop = _loop;
+	path = path_;
+	position = position_;
+	scaled = scaled_;
+	transparent = transparent_;
+	loop = loop_;
 }
 
 HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
diff --git a/engines/hypno/metaengine.cpp b/engines/hypno/metaengine.cpp
index e6cded51fc..c2b3f7e281 100644
--- a/engines/hypno/metaengine.cpp
+++ b/engines/hypno/metaengine.cpp
@@ -36,9 +36,9 @@ public:
 Common::Error HypnoMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
 	if (Common::String(desc->gameId) == "wetlands") {
 		*engine = (Engine *)new Hypno::WetEngine(syst, desc);
-	} else if (Common::String(desc->gameId) == "sinister-six") {
+	} else if (Common::String(desc->gameId) == "sinistersix") {
 		*engine = (Engine *)new Hypno::SpiderEngine(syst, desc);
-	} else if (Common::String(desc->gameId) == "soldier-boyz") {
+	} else if (Common::String(desc->gameId) == "soldierboyz") {
 		*engine = (Engine *)new Hypno::BoyzEngine(syst, desc);
 	} else
 		return Common::kUnsupportedGameidError;
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 00f7d7bbe4..a33dd69207 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -57,7 +57,8 @@ const static char *sceneVariables[] = {
 	"GS_COMBATJSON",
 	"GS_COMBATLEVEL",
 	"GS_PUZZLELEVEL",
-	NULL};
+	NULL
+};
 
 void HypnoEngine::parseScene(const Common::String &prefix, const Common::String &filename) {
 	debugC(1, kHypnoDebugParser, "Parsing %s", filename.c_str());


Commit: dc1e09f15c7af37f6f982140cb70c17005e5c981
    https://github.com/scummvm/scummvm/commit/dc1e09f15c7af37f6f982140cb70c17005e5c981
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: correctly parse complete wetlands missions

Changed paths:
    engines/hypno/libfile.cpp


diff --git a/engines/hypno/libfile.cpp b/engines/hypno/libfile.cpp
index 0d688dd9c8..326dfb6248 100644
--- a/engines/hypno/libfile.cpp
+++ b/engines/hypno/libfile.cpp
@@ -42,9 +42,10 @@ bool LibFile::open(const Common::String &prefix, const Common::String &filename,
 	while (offset < libfile.size()) {
 		byte b;
 		uint32 size = 0;
-		uint32 start = 0;
+		uint32 start = libfile.size();
 		FileEntry f;
 		libfile.seek(offset);
+		debugC(1, kHypnoDebugParser, "parsing at offset %d", offset);
 		while (true) {
 			f.name = "";
 			f.data.clear();


Commit: 3e8117ba9df45f8420908348e90b5db52dfa7466
    https://github.com/scummvm/scummvm/commit/3e8117ba9df45f8420908348e90b5db52dfa7466
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added explicit action type and refactored affected code

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/grammar_mis.cpp
    engines/hypno/grammar_mis.y
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index a548f7b363..4f872f9b41 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -43,9 +43,26 @@ enum HotspotType {
 	MakeHotspot
 };
 
+enum ActionType {
+	MiceAction,
+	PaletteAction,
+	BackgroundAction,
+	OverlayAction,
+	EscapeAction,
+	QuitAction,
+	CutsceneAction,
+	PlayAction,
+	AmbientAction,
+	WalNAction,
+	GlobalAction,
+	TalkAction,
+	ChangeLevelAction
+};
+
 class Action {
 public:
 	virtual ~Action() {} // needed to make Action polymorphic
+	ActionType type;
 };
 
 typedef Common::Array<Action *> Actions;
@@ -82,17 +99,32 @@ public:
 
 class Mice : public Action {
 public:
+	Mice(Filename path_, uint32 index_) {
+		type = MiceAction;
+		path = path_;
+		index = index_;
+	}
 	Filename path;
 	uint32 index;
 };
 
 class Palette : public Action {
 public:
+	Palette(Filename path_) {
+		type = PaletteAction;
+		path = path_;
+	}
 	Filename path;
 };
 
 class Background : public Action {
 public:
+	Background(Filename path_, Common::Point origin_, Common::String condition_) {
+		type = BackgroundAction;
+		path = path_;
+		origin = origin_;
+		condition = condition_;
+	}
 	Filename path;
 	Common::Point origin;
 	Common::String condition;
@@ -100,24 +132,49 @@ public:
 
 class Overlay : public Action {
 public:
+	Overlay(Filename path_, Common::Point origin_, Common::String flag_) {
+		type = OverlayAction;
+		path = path_;
+		origin = origin_;
+		flag = flag_;
+	}
 	Filename path;
 	Common::Point origin;
 	Common::String flag;
 };
 
 class Escape : public Action {
+public:
+	Escape() {
+		type = EscapeAction;
+	}
 };
 
 class Quit : public Action {
+public:
+	Quit() {
+		type = QuitAction;
+	}
 };
 
 class Cutscene : public Action {
 public:
+	Cutscene(Filename path_) {
+		type = CutsceneAction;
+		path = path_;
+	}
 	Filename path;
 };
 
 class Play : public Action {
 public:
+	Play(Filename path_, Common::Point origin_, Common::String condition_, Common::String flag_) {
+		type = PlayAction;
+		path = path_;
+		origin = origin_;
+		condition = condition_;
+		flag = flag_;
+	}
 	Filename path;
 	Common::Point origin;
 	Common::String condition;
@@ -126,6 +183,13 @@ public:
 
 class Ambient : public Action {
 public:
+	Ambient(Filename path_, Common::Point origin_, Common::String flag_) {
+		type = AmbientAction;
+		path = path_;
+		origin = origin_;
+		flag = flag_;
+		// TODO fullscreen should be enable or not by default?
+	}
 	Filename path;
 	Common::Point origin;
 	Common::String flag;
@@ -134,6 +198,13 @@ public:
 
 class WalN : public Action {
 public:
+	WalN(Filename path_, Common::Point origin_, Common::String condition_, Common::String flag_) {
+		type = WalNAction;
+		path = path_;
+		origin = origin_;
+		condition = condition_;
+		flag = flag_;
+	}
 	Filename path;
 	Common::Point origin;
 	Common::String condition;
@@ -142,6 +213,11 @@ public:
 
 class Global : public Action {
 public:
+	Global(Common::String variable_, Common::String command_) {
+		type = GlobalAction;
+		variable = variable_;
+		command = command_;
+	}
 	Common::String variable;
 	Common::String command;
 };
@@ -159,6 +235,9 @@ typedef Common::Array<TalkCommand> TalkCommands;
 
 class Talk : public Action {
 public:
+	Talk()  {
+		type = TalkAction;
+	}
 	TalkCommands commands;
 	bool active;
 	Filename background;
@@ -168,6 +247,10 @@ public:
 
 class ChangeLevel : public Action {
 public:
+	ChangeLevel(Filename level_) {
+		type = ChangeLevelAction;
+		level = level_;
+	}
 	Filename level;
 };
 
diff --git a/engines/hypno/grammar_mis.cpp b/engines/hypno/grammar_mis.cpp
index cbaad48c90..9045fef65c 100644
--- a/engines/hypno/grammar_mis.cpp
+++ b/engines/hypno/grammar_mis.cpp
@@ -521,10 +521,10 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint16 yyrline[] =
 {
        0,    74,    74,    77,    82,    83,    87,   102,   111,   126,
-     132,   133,   143,   152,   161,   171,   179,   187,   195,   205,
-     213,   219,   225,   228,   234,   237,   238,   242,   243,   244,
-     245,   246,   247,   253,   254,   260,   266,   272,   279,   286,
-     292,   293,   294,   297,   298,   301,   302,   305,   306
+     132,   133,   140,   147,   153,   159,   165,   172,   179,   185,
+     191,   197,   203,   206,   212,   215,   216,   220,   221,   222,
+     223,   224,   225,   231,   232,   238,   244,   250,   257,   264,
+     270,   271,   272,   275,   276,   279,   280,   283,   284
 };
 #endif
 
@@ -1443,271 +1443,249 @@ yyreduce:
   case 11:
 #line 133 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-		Background *a = new Background();
-		a->path = (yyvsp[-5].s);
-		a->origin = Common::Point((yyvsp[-4].i), (yyvsp[-3].i));
-		a->condition = (yyvsp[-2].s);
+		Background *a = new Background((yyvsp[-5].s), Common::Point((yyvsp[-4].i), (yyvsp[-3].i)), (yyvsp[-2].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "BACK");
 	}
-#line 1456 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1453 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 143 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 140 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		Global *a = new Global();
-		a->variable = (yyvsp[-1].s);
-		a->command = (yyvsp[0].s);
+		Global *a = new Global((yyvsp[-1].s), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "GLOB"); 
 	}
-#line 1470 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1465 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 152 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 147 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		Ambient *a = new Ambient();
-		a->path = (yyvsp[-3].s);
-		a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
-		a->flag = (yyvsp[0].s);
+		Ambient *a = new Ambient((yyvsp[-3].s), Common::Point((yyvsp[-2].i), (yyvsp[-1].i)), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);			
 		debugC(1, kHypnoDebugParser, "AMBI %d %d", (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1484 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1476 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 161 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 153 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		Play *a = new Play();
-		a->path = (yyvsp[-4].s);
-		a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-		a->condition = (yyvsp[-1].s);
-		a->flag = (yyvsp[0].s);
+		Play *a = new Play((yyvsp[-4].s), Common::Point((yyvsp[-3].i), (yyvsp[-2].i)), (yyvsp[-1].s), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "PLAY %s.", (yyvsp[-4].s)); }
-#line 1499 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1487 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 171 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 159 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		Overlay *a = new Overlay();
-		a->path = (yyvsp[-3].s);
-		a->origin = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
+		Overlay *a = new Overlay((yyvsp[-3].s), Common::Point((yyvsp[-2].i), (yyvsp[-1].i)), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 	}
-#line 1512 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1498 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 179 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 165 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-		Palette *a = new Palette();
-		a->path = (yyvsp[0].s); 
+		Palette *a = new Palette((yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "PALE");
 	}
-#line 1525 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1510 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 187 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 172 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		Cutscene *a = new Cutscene();
-		a->path = (yyvsp[0].s);
+		Cutscene *a = new Cutscene((yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "CUTS %s", (yyvsp[0].s)); 
 	}
-#line 1538 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1522 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 195 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 179 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
-		WalN *a = new WalN();
-		a->path = (yyvsp[-4].s);
-		a->origin = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
-		a->condition = (yyvsp[-1].s);
-		a->flag = (yyvsp[0].s);
+		WalN *a = new WalN((yyvsp[-4].s), Common::Point((yyvsp[-3].i), (yyvsp[-2].i)), (yyvsp[-1].s), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "WALN %s %d %d", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
-#line 1553 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1533 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 205 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 185 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-		Mice *a = new Mice();
-		a->path = (yyvsp[-1].s); 
-		a->index = (yyvsp[0].i)-1;
+		Mice *a = new Mice((yyvsp[-1].s), (yyvsp[0].i)-1);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 	}
-#line 1566 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1544 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 213 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 191 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(talk_action);
 		talk_action = nullptr;
 		debugC(1, kHypnoDebugParser, "TALK"); }
-#line 1577 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1555 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 219 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 197 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		debugC(1, kHypnoDebugParser, "explicit END");
 		g_parsedHots = stack.back(); 
 		stack.pop_back();
 		smenu_idx.pop_back();
 	}
-#line 1588 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1566 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 225 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 203 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("implicit END"); }
-#line 1594 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1572 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 228 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 206 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 	assert(talk_action == nullptr);
 	talk_action = new Talk();
 	talk_action->active = true; 
 }
-#line 1604 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1582 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 234 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 212 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		talk_action->active = false; 
 		debugC(1, kHypnoDebugParser, "inactive"); }
-#line 1612 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1590 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 237 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 215 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "inactive"); }
-#line 1618 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1596 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
-#line 238 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 216 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		talk_action->background = (yyvsp[-4].s);
 		talk_action->position = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
 		debugC(1, kHypnoDebugParser, "BACK in TALK"); }
-#line 1627 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1605 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 242 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 220 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "BOXX %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1633 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1611 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 243 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 221 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "ESCAPE"); }
-#line 1639 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1617 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 222 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "SECOND %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1645 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1623 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 245 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 223 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "INTRO %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1651 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1629 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 246 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 224 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "DEFAULT %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1657 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1635 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 247 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 225 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "G";
 		talk_cmd.path = (yyvsp[-1].s)+2;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1668 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1646 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 253 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 231 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1674 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1652 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 254 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 232 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "F";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1685 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1663 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 260 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 238 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "A";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "|A%d", talk_cmd.num); }
-#line 1696 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1674 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 266 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "D";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1707 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1685 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 272 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 250 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "P";
@@ -1715,11 +1693,11 @@ yyreduce:
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);
 		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1719 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1697 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 279 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 257 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "I";
@@ -1727,70 +1705,70 @@ yyreduce:
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);		  
 		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1731 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1709 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 286 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 264 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "S";
 		talk_cmd.variable = (yyvsp[-1].s)+2;
 		talk_action->commands.push_back(talk_cmd);
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1742 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1720 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 292 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 270 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "|L"); }
-#line 1748 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1726 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 293 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 271 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "|E"); }
-#line 1754 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1732 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 297 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 275 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "name: %s", (yyvsp[0].s)); }
-#line 1760 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1738 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 298 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 276 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1766 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1744 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 301 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 279 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "flag: %s", (yyvsp[0].s)); }
-#line 1772 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1750 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 302 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 280 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1778 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1756 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 305 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 283 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "switch %s", (yyvsp[0].s)); }
-#line 1784 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1762 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 306 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 284 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1790 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1768 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1794 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1772 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_mis.y b/engines/hypno/grammar_mis.y
index 22e323e9ab..2c16429ae6 100644
--- a/engines/hypno/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -131,81 +131,59 @@ line: MENUTOK mflag mflag  {
 		debugC(1, kHypnoDebugParser, "ESC SUBMENU"); }
 	|  TIMETOK NUM  { debugC(1, kHypnoDebugParser, "TIME %d", $2); } 
 	|  BACKTOK FILENAME NUM NUM gsswitch flag flag {
-		Background *a = new Background();
-		a->path = $2;
-		a->origin = Common::Point($3, $4);
-		a->condition = $5;
+		Background *a = new Background($2, Common::Point($3, $4), $5);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "BACK");
 	}
 	|  GLOBTOK GSSWITCH NAME  { 
-		Global *a = new Global();
-		a->variable = $2;
-		a->command = $3;
+		Global *a = new Global($2, $3);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "GLOB"); 
 	}
 	|  AMBITOK FILENAME NUM NUM flag { 
-		Ambient *a = new Ambient();
-		a->path = $2;
-		a->origin = Common::Point($3, $4);
-		a->flag = $5;
+		Ambient *a = new Ambient($2, Common::Point($3, $4), $5);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);			
 		debugC(1, kHypnoDebugParser, "AMBI %d %d", $3, $4); }
 	|  PLAYTOK FILENAME NUM NUM gsswitch flag { 
-		Play *a = new Play();
-		a->path = $2;
-		a->origin = Common::Point($3, $4);
-		a->condition = $5;
-		a->flag = $6;
+		Play *a = new Play($2, Common::Point($3, $4), $5, $6);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "PLAY %s.", $2); }
 	|  OVERTOK FILENAME NUM NUM flag { 
-		Overlay *a = new Overlay();
-		a->path = $2;
-		a->origin = Common::Point($3, $4);
+		Overlay *a = new Overlay($2, Common::Point($3, $4), $5);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 	}
 	|  PALETOK FILENAME {
-		Palette *a = new Palette();
-		a->path = $2; 
+		Palette *a = new Palette($2);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "PALE");
 	}
 	|  CUTSTOK FILENAME { 
-		Cutscene *a = new Cutscene();
-		a->path = $2;
+		Cutscene *a = new Cutscene($2);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "CUTS %s", $2); 
 	}
 	|  WALNTOK FILENAME NUM NUM gsswitch flag  { 
-		WalN *a = new WalN();
-		a->path = $2;
-		a->origin = Common::Point($3, $4);
-		a->condition = $5;
-		a->flag = $6;
+		WalN *a = new WalN($2, Common::Point($3, $4), $5, $6);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "WALN %s %d %d", $2, $3, $4); } 
 	|  MICETOK FILENAME NUM {
-		Mice *a = new Mice();
-		a->path = $2; 
-		a->index = $3-1;
+		Mice *a = new Mice($2, $3-1);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index bab83823fd..ac6046600f 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -76,20 +76,16 @@ void SpiderEngine::loadAssetsFullGame() {
 	start.trans.intros.push_back("spider/cine/dcine2.smk");
 	_levels["<start>"] = start;
 
-	ChangeLevel *cl = new ChangeLevel();
-	cl->level = "levels.mi_";
+	ChangeLevel *cl = new ChangeLevel("levels.mi_");
 	_levels["mainmenu.mi_"].scene.hots[1].actions.push_back(cl);
 	
-	cl = new ChangeLevel();
-	cl->level = "options.mi_";
+	cl = new ChangeLevel("options.mi_");
 	_levels["mainmenu.mi_"].scene.hots[4].actions.push_back(cl);
 
-	cl = new ChangeLevel();
-	cl->level = "<quit>";
+	cl = new ChangeLevel("<quit>");
 	_levels["mainmenu.mi_"].scene.hots[5].actions.push_back(cl);
 
-	cl = new ChangeLevel();
-	cl->level = "combmenu.mi_";
+	cl = new ChangeLevel("combmenu.mi_");
 	_levels["options.mi_"].scene.hots[1].actions.push_back(cl);
 }
 
@@ -144,30 +140,24 @@ void SpiderEngine::loadAssetsDemo() {
 
 	// Read assets from mis files
 	parseScene("sixdemo", "mis/demo.mis");
-	ChangeLevel *cl = new ChangeLevel();
-	cl->level = "sixdemo/c_misc/missions.lib/c1.mi_";
+	ChangeLevel *cl = new ChangeLevel("sixdemo/c_misc/missions.lib/c1.mi_");
 	_levels["sixdemo/mis/demo.mis"].scene.hots[1].actions.push_back(cl);
 
-	cl = new ChangeLevel();
-	cl->level = "sixdemo/mis/alley.mis";
+	cl = new ChangeLevel("sixdemo/mis/alley.mis");
 	_levels["sixdemo/mis/demo.mis"].scene.hots[2].actions.push_back(cl);
 
-	cl = new ChangeLevel();
-	cl->level = "sixdemo/puz_matr";
+	cl = new ChangeLevel("sixdemo/puz_matr");
 	_levels["sixdemo/mis/demo.mis"].scene.hots[3].actions.push_back(cl);
 
-	cl = new ChangeLevel();
-	cl->level = "sixdemo/mis/shoctalk.mis";
+	cl = new ChangeLevel("sixdemo/mis/shoctalk.mis");
 	_levels["sixdemo/mis/demo.mis"].scene.hots[4].actions.push_back(cl);
 
-	cl = new ChangeLevel();
-	cl->level = "sixdemo/mis/order.mis";
+	cl = new ChangeLevel("sixdemo/mis/order.mis");
 	_levels["sixdemo/mis/demo.mis"].scene.hots[5].actions.push_back(cl);
 	_levels["sixdemo/mis/demo.mis"].scene.sound = "demo/sound.lib/menu_mus.raw";
 
 	parseScene("sixdemo", "mis/order.mis");
-	cl = new ChangeLevel();
-	cl->level = "<quit>";
+	cl = new ChangeLevel("<quit>");
 	_levels["sixdemo/mis/order.mis"].scene.hots[1].actions.push_back(cl);
 
 	parseScene("sixdemo", "mis/alley.mis");
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 71cd30062a..f9b8a3633b 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -54,11 +54,8 @@ void WetEngine::loadAssetsDemoDisc() {
 	Hotspots hs;
 
 	h.type = MakeMenu;
-	Ambient *a = new Ambient();
-	a->path = "movie/selector.smk";
+	Ambient *a = new Ambient("movie/selector.smk", Common::Point(0, 0), "/LOOP");
 	a->fullscreen = true;
-	a->flag = "/LOOP";
-	a->origin = Common::Point(0, 0);
 	h.actions.push_back(a);
 
 	hs.push_back(h);
@@ -67,15 +64,13 @@ void WetEngine::loadAssetsDemoDisc() {
 	h.rect = Common::Rect(0, 424, 233, 462);
 	h.actions.clear();
 	h.smenu = nullptr;
-	ChangeLevel *cl = new ChangeLevel();
-	cl->level = "<intro>";
+	ChangeLevel *cl = new ChangeLevel("<intro>");
 	h.actions.push_back(cl);
 
 	hs.push_back(h);
 
 	h.rect = Common::Rect(242, 424, 500, 480);
-	cl = new ChangeLevel();
-	cl->level = "<movies>";
+	cl = new ChangeLevel("<movies>");
 	h.actions.clear();
 	h.actions.push_back(cl);
 


Commit: 00d7a05c94ca7d504ad8c62de94118ffadf3f13e
    https://github.com/scummvm/scummvm/commit/00d7a05c94ca7d504ad8c62de94118ffadf3f13e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: replaced typeid code with enumarated type

Changed paths:
    engines/hypno/actions.cpp
    engines/hypno/scene.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index 2ce49e74e7..3d2b779b3c 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -20,7 +20,6 @@
  *
  */
 
-#include <typeinfo>
 #include "common/events.h"
 
 #include "hypno/grammar.h"
@@ -36,14 +35,23 @@ void HypnoEngine::runMenu(Hotspots hs) {
 	debugC(1, kHypnoDebugScene, "hotspot actions size: %d", h.actions.size());
 	for (Actions::const_iterator itt = h.actions.begin(); itt != h.actions.end(); ++itt) {
 		Action *action = *itt;
-		if (typeid(*action) == typeid(Quit))
-			runQuit((Quit *)action);
-		else if (typeid(*action) == typeid(Background))
-			runBackground((Background *)action);
-		else if (typeid(*action) == typeid(Overlay))
-			runOverlay((Overlay *)action);
-		else if (typeid(*action) == typeid(Ambient))
-			runAmbient((Ambient *)action);
+		switch (action->type) {
+			case QuitAction:
+				runQuit((Quit *)action);
+			break;
+			case BackgroundAction:
+				runBackground((Background *)action);
+			break;
+			case OverlayAction:
+				runOverlay((Overlay *)action);
+			break;
+			case AmbientAction: 
+				runAmbient((Ambient *)action);
+			break;
+
+			default:
+			break;
+		}
 
 		//else if (typeid(*action) == typeid(Mice))
 		//	runMice(h, (Mice*) action);
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index a33dd69207..fded092e62 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -20,7 +20,6 @@
  *
  */
 
-#include <typeinfo>
 #include "common/events.h"
 
 #include "hypno/grammar.h"
@@ -129,24 +128,45 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 
 	for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 		Action *action = *itt;
-		if (typeid(*action) == typeid(ChangeLevel))
-			runChangeLevel((ChangeLevel *)action);
-		if (typeid(*action) == typeid(Escape))
-			runEscape((Escape *)action);
-		else if (typeid(*action) == typeid(Cutscene))
-			runCutscene((Cutscene *)action);
-		else if (typeid(*action) == typeid(Play))
-			runPlay((Play *)action);
-		else if (typeid(*action) == typeid(WalN))
-			runWalN((WalN *)action);
-		else if (typeid(*action) == typeid(Global))
-			runGlobal((Global *)action);
-		else if (typeid(*action) == typeid(Talk))
-			runTalk((Talk *)action);
-		else if (typeid(*action) == typeid(Quit))
-			runQuit((Quit *)action);
-		else if (typeid(*action) == typeid(Palette))
-			debugC(1, kHypnoDebugScene, "runPalette unimplemented");
+		switch (action->type) {
+			case ChangeLevelAction:
+				runChangeLevel((ChangeLevel *)action);
+			break;
+
+			case EscapeAction:
+				runEscape((Escape *)action);
+			break;
+
+			case CutsceneAction:
+				runCutscene((Cutscene *)action);
+			break;
+
+			case PlayAction:
+				runPlay((Play *)action);
+			break;
+
+			case WalNAction:
+				runWalN((WalN *)action);
+			break;
+		
+			case GlobalAction:
+				runGlobal((Global *)action);
+			break;
+
+			case TalkAction:
+				runTalk((Talk *)action);
+			break;
+
+			case QuitAction:
+				runQuit((Quit *)action);
+			break;
+			case PaletteAction:
+				debugC(1, kHypnoDebugScene, "runPalette unimplemented");
+			break;
+
+			default:
+			break;
+		}
 	}
 }
 
@@ -172,8 +192,13 @@ bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 	if (found) {
 		for (Actions::const_iterator itt = selected.actions.begin(); itt != selected.actions.end(); ++itt) {
 			Action *action = *itt;
-			if (typeid(*action) == typeid(Mice))
-				runMice((Mice *)action);
+			switch (action->type) {
+				case MiceAction:
+					runMice((Mice *)action);
+				break;
+				default:
+				break;
+			}
 		}
 		return true;
 	}


Commit: e67832818acdc31d710ee8d4369f9f4a3e999965
    https://github.com/scummvm/scummvm/commit/e67832818acdc31d710ee8d4369f9f4a3e999965
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: refactored Hotspot

Changed paths:
    engines/hypno/grammar.h
    engines/hypno/grammar_mis.cpp
    engines/hypno/grammar_mis.y
    engines/hypno/hypno.cpp
    engines/hypno/scene.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 4f872f9b41..61cf88db28 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -88,6 +88,12 @@ typedef Common::Array<MVideo> Videos;
 
 class Hotspot {
 public:
+	Hotspot(HotspotType type_, Common::String stype_, Common::Rect rect_ = Common::Rect(0, 0, 0, 0)) {
+		type = type_;
+		stype = stype_;
+		rect = rect_;
+		smenu = nullptr;
+	}
 	HotspotType type;
 	Common::String stype;
 	Common::String stypeFlag;
diff --git a/engines/hypno/grammar_mis.cpp b/engines/hypno/grammar_mis.cpp
index 9045fef65c..b247ff427f 100644
--- a/engines/hypno/grammar_mis.cpp
+++ b/engines/hypno/grammar_mis.cpp
@@ -520,11 +520,11 @@ static const yytype_uint8 yytranslate[] =
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,    74,    74,    77,    82,    83,    87,   102,   111,   126,
-     132,   133,   140,   147,   153,   159,   165,   172,   179,   185,
-     191,   197,   203,   206,   212,   215,   216,   220,   221,   222,
-     223,   224,   225,   231,   232,   238,   244,   250,   257,   264,
-     270,   271,   272,   275,   276,   279,   280,   283,   284
+       0,    74,    74,    77,    82,    83,    87,    99,   105,   120,
+     126,   127,   134,   141,   147,   153,   159,   166,   173,   179,
+     185,   191,   197,   200,   206,   209,   210,   214,   215,   216,
+     217,   218,   219,   225,   226,   232,   238,   244,   251,   258,
+     264,   265,   266,   269,   270,   273,   274,   277,   278
 };
 #endif
 
@@ -1372,10 +1372,7 @@ yyreduce:
   case 6:
 #line 87 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
-		Hotspot *hot = new Hotspot(); 
-		hot->type = MakeMenu;
-		hot->stype = (yyvsp[-1].s);
-		hot->smenu = NULL;
+		Hotspot *hot = new Hotspot(MakeMenu, (yyvsp[-1].s)); 
 		debugC(1, kHypnoDebugParser, "MENU %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot);
@@ -1386,25 +1383,22 @@ yyreduce:
 		smenu_idx.pop_back();
 		smenu_idx.push_back(idx);
 	}
-#line 1390 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1387 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 102 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 99 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {  
-		Hotspot *hot = new Hotspot(); 
-		hot->type = MakeHotspot;
-		hot->smenu = NULL;
-		hot->rect = Common::Rect((yyvsp[-3].i), (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i));
+		Hotspot *hot = new Hotspot(MakeHotspot, "", Common::Rect((yyvsp[-3].i), (yyvsp[-2].i), (yyvsp[-1].i), (yyvsp[0].i))); 
 		debugC(1, kHypnoDebugParser, "HOTS %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot); 
 	}
-#line 1404 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1398 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 111 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 105 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		// This should always point to a hotspot
 		int idx = smenu_idx.back();
@@ -1420,28 +1414,28 @@ yyreduce:
 		stack.push_back(hot->smenu);
 		debugC(1, kHypnoDebugParser, "SUBMENU"); 
 	}
-#line 1424 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1418 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 126 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 120 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Escape *a = new Escape();
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "ESC SUBMENU"); }
-#line 1435 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1429 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 132 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 126 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "TIME %d", (yyvsp[0].i)); }
-#line 1441 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1435 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 133 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 127 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Background *a = new Background((yyvsp[-5].s), Common::Point((yyvsp[-4].i), (yyvsp[-3].i)), (yyvsp[-2].s));
 		Hotspots *cur = stack.back();
@@ -1449,11 +1443,11 @@ yyreduce:
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "BACK");
 	}
-#line 1453 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1447 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 140 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 134 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Global *a = new Global((yyvsp[-1].s), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
@@ -1461,44 +1455,44 @@ yyreduce:
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "GLOB"); 
 	}
-#line 1465 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1459 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 147 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 141 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Ambient *a = new Ambient((yyvsp[-3].s), Common::Point((yyvsp[-2].i), (yyvsp[-1].i)), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);			
 		debugC(1, kHypnoDebugParser, "AMBI %d %d", (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1476 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1470 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 153 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 147 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Play *a = new Play((yyvsp[-4].s), Common::Point((yyvsp[-3].i), (yyvsp[-2].i)), (yyvsp[-1].s), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "PLAY %s.", (yyvsp[-4].s)); }
-#line 1487 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1481 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 159 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 153 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Overlay *a = new Overlay((yyvsp[-3].s), Common::Point((yyvsp[-2].i), (yyvsp[-1].i)), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 	}
-#line 1498 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1492 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 165 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 159 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Palette *a = new Palette((yyvsp[0].s));
 		Hotspots *cur = stack.back();
@@ -1506,11 +1500,11 @@ yyreduce:
 		hot->actions.push_back(a);
 		debugC(1, kHypnoDebugParser, "PALE");
 	}
-#line 1510 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1504 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 172 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 166 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Cutscene *a = new Cutscene((yyvsp[0].s));
 		Hotspots *cur = stack.back();
@@ -1518,174 +1512,174 @@ yyreduce:
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "CUTS %s", (yyvsp[0].s)); 
 	}
-#line 1522 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1516 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 179 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 173 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		WalN *a = new WalN((yyvsp[-4].s), Common::Point((yyvsp[-3].i), (yyvsp[-2].i)), (yyvsp[-1].s), (yyvsp[0].s));
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);		  
 		debugC(1, kHypnoDebugParser, "WALN %s %d %d", (yyvsp[-4].s), (yyvsp[-3].i), (yyvsp[-2].i)); }
-#line 1533 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1527 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 185 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 179 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		Mice *a = new Mice((yyvsp[-1].s), (yyvsp[0].i)-1);
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(a);
 	}
-#line 1544 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1538 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 191 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 185 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		Hotspots *cur = stack.back();
 		Hotspot *hot = &cur->back();
 		hot->actions.push_back(talk_action);
 		talk_action = nullptr;
 		debugC(1, kHypnoDebugParser, "TALK"); }
-#line 1555 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1549 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 197 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 191 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		debugC(1, kHypnoDebugParser, "explicit END");
 		g_parsedHots = stack.back(); 
 		stack.pop_back();
 		smenu_idx.pop_back();
 	}
-#line 1566 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1560 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 203 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 197 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debug("implicit END"); }
-#line 1572 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1566 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 206 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 200 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 	assert(talk_action == nullptr);
 	talk_action = new Talk();
 	talk_action->active = true; 
 }
-#line 1582 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1576 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 212 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 206 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     {
 		talk_action->active = false; 
 		debugC(1, kHypnoDebugParser, "inactive"); }
-#line 1590 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1584 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 215 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 209 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "inactive"); }
-#line 1596 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1590 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
-#line 216 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 210 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		talk_action->background = (yyvsp[-4].s);
 		talk_action->position = Common::Point((yyvsp[-3].i), (yyvsp[-2].i));
 		debugC(1, kHypnoDebugParser, "BACK in TALK"); }
-#line 1605 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1599 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 220 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 214 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "BOXX %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1611 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1605 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 221 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 215 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "ESCAPE"); }
-#line 1617 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1611 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 222 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 216 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "SECOND %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1623 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1617 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 223 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 217 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "INTRO %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1629 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1623 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 224 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 218 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "DEFAULT %s %d %d", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1635 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1629 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 225 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 219 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "G";
 		talk_cmd.path = (yyvsp[-1].s)+2;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1646 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1640 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 231 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 225 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1652 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1646 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 232 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 226 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "F";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1663 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1657 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 238 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 232 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "A";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "|A%d", talk_cmd.num); }
-#line 1674 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1668 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 238 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "D";
 		talk_cmd.num = atoi((yyvsp[-1].s)+2)-1;
 		talk_action->commands.push_back(talk_cmd); 
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1685 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1679 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 250 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 244 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "P";
@@ -1693,11 +1687,11 @@ yyreduce:
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);
 		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1697 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1691 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 257 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 251 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "I";
@@ -1705,70 +1699,70 @@ yyreduce:
 		talk_cmd.position = Common::Point((yyvsp[-2].i), (yyvsp[-1].i));
 		talk_action->commands.push_back(talk_cmd);		  
 		debugC(1, kHypnoDebugParser, "%s %d %d", (yyvsp[-3].s), (yyvsp[-2].i), (yyvsp[-1].i)); }
-#line 1709 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1703 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 264 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 258 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { 
 		TalkCommand talk_cmd;
 		talk_cmd.command = "S";
 		talk_cmd.variable = (yyvsp[-1].s)+2;
 		talk_action->commands.push_back(talk_cmd);
 		debugC(1, kHypnoDebugParser, "%s", (yyvsp[-1].s)); }
-#line 1720 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1714 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 270 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 264 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "|L"); }
-#line 1726 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1720 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 271 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 265 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "|E"); }
-#line 1732 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1726 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 275 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 269 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "name: %s", (yyvsp[0].s)); }
-#line 1738 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1732 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 276 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 270 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1744 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1738 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 279 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 273 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "flag: %s", (yyvsp[0].s)); }
-#line 1750 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1744 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 280 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 274 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1756 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1750 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 283 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 277 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = (yyvsp[0].s); debugC(1, kHypnoDebugParser, "switch %s", (yyvsp[0].s)); }
-#line 1762 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1756 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 284 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
+#line 278 "engines/hypno/grammar_mis.y" /* yacc.c:1646  */
     { (yyval.s) = scumm_strdup(""); }
-#line 1768 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1762 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1772 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
+#line 1766 "engines/hypno/grammar_mis.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_mis.y b/engines/hypno/grammar_mis.y
index 2c16429ae6..99b0078994 100644
--- a/engines/hypno/grammar_mis.y
+++ b/engines/hypno/grammar_mis.y
@@ -85,10 +85,7 @@ lines: line lines
 
 
 line: MENUTOK mflag mflag  {
-		Hotspot *hot = new Hotspot(); 
-		hot->type = MakeMenu;
-		hot->stype = $2;
-		hot->smenu = NULL;
+		Hotspot *hot = new Hotspot(MakeMenu, $2); 
 		debugC(1, kHypnoDebugParser, "MENU %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot);
@@ -100,10 +97,7 @@ line: MENUTOK mflag mflag  {
 		smenu_idx.push_back(idx);
 	}
 	| HOTSTOK BBOXTOK NUM NUM NUM NUM  {  
-		Hotspot *hot = new Hotspot(); 
-		hot->type = MakeHotspot;
-		hot->smenu = NULL;
-		hot->rect = Common::Rect($3, $4, $5, $6);
+		Hotspot *hot = new Hotspot(MakeHotspot, "", Common::Rect($3, $4, $5, $6)); 
 		debugC(1, kHypnoDebugParser, "HOTS %d.", hot->type);
 		Hotspots *cur = stack.back();
 		cur->push_back(*hot); 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index 7931180697..ed8d529b0c 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -66,8 +66,7 @@ HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	g_hypno = this;
 	_defaultCursor = "";
 	// Add quit level
-	Hotspot q;
-	q.type = MakeMenu;
+	Hotspot q(MakeMenu, "");
 	Action *a = new Quit();
 	q.actions.push_back(a);
 	Level quit;
@@ -133,7 +132,7 @@ Common::Error HypnoEngine::run() {
 	loadAssets();
 	_nextLevel = "<start>";
 	while (!shouldQuit()) {
-		debug("nextLevel: %s", _nextLevel.c_str());
+		//debug("nextLevel: %s", _nextLevel.c_str());
 		_defaultCursor = "";
 		_prefixDir = "";
 		_videosPlaying.clear();
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index fded092e62..5bfb891b4a 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -99,7 +99,7 @@ bool HypnoEngine::checkSceneCompleted() {
 
 void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 	Hotspots *hots = stack.back();
-	Hotspot selected;
+	Hotspot selected(MakeHotspot, "");
 	bool found = false;
 	int rs = 100000000;
 	int cs = 0;
@@ -172,7 +172,7 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 
 bool HypnoEngine::hoverHotspot(Common::Point mousePos) {
 	Hotspots *hots = stack.back();
-	Hotspot selected;
+	Hotspot selected(MakeHotspot, "");
 	bool found = false;
 	int rs = 100000000;
 	for (Hotspots::const_iterator it = hots->begin(); it != hots->end(); ++it) {
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index f9b8a3633b..72971b7dcf 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -50,10 +50,8 @@ void WetEngine::loadAssetsDemoDisc() {
 		error("Failed to load any files from missions.lib");
 
 	Level start;
-	Hotspot h;
+	Hotspot h(MakeMenu, "");
 	Hotspots hs;
-
-	h.type = MakeMenu;
 	Ambient *a = new Ambient("movie/selector.smk", Common::Point(0, 0), "/LOOP");
 	a->fullscreen = true;
 	h.actions.push_back(a);


Commit: cdc58ab15f0ab2b61daf2c9dba86595f5450a2ec
    https://github.com/scummvm/scummvm/commit/cdc58ab15f0ab2b61daf2c9dba86595f5450a2ec
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: improved video decoding, implemented initial version of wetland main menu and some other fixes

Changed paths:
  A engines/hypno/video.cpp
    engines/hypno/actions.cpp
    engines/hypno/arcade.cpp
    engines/hypno/detection.cpp
    engines/hypno/grammar.h
    engines/hypno/grammar_arc.cpp
    engines/hypno/grammar_arc.y
    engines/hypno/hypno.cpp
    engines/hypno/hypno.h
    engines/hypno/module.mk
    engines/hypno/scene.cpp
    engines/hypno/spider/spider.cpp
    engines/hypno/wet/arcade.cpp
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/actions.cpp b/engines/hypno/actions.cpp
index 3d2b779b3c..ec0cdf442d 100644
--- a/engines/hypno/actions.cpp
+++ b/engines/hypno/actions.cpp
@@ -111,9 +111,16 @@ void HypnoEngine::runPlay(Play *a) {
 }
 
 void HypnoEngine::runAmbient(Ambient *a) {
-	if (a->flag == "/BITMAP")
-		loadImage(a->path, a->origin.x, a->origin.y, false);
-	else {
+	if (a->flag == "/BITMAP") {
+		Graphics::Surface *frame = decodeFrame(a->path, a->frameNumber, true);
+		Graphics::Surface *sframe;
+		if (a->fullscreen)
+			sframe = frame->scale(_screenW, _screenH);
+		else
+			sframe = frame;
+		drawImage(*sframe, a->origin.x, a->origin.y, true);
+		//loadImage(a->path, a->origin.x, a->origin.y, false, a->frameNumber);
+	} else {
 		_nextSequentialVideoToPlay.push_back(MVideo(a->path, a->origin, false, a->fullscreen, a->flag == "/LOOP"));
 	}
 }
diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 4534d74213..9d6a6fd4ea 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -56,12 +56,12 @@ void HypnoEngine::parseArcadeShooting(const Common::String &prefix, const Common
 	debugC(1, kHypnoDebugParser, "Parsing %s/%s", prefix.c_str(), filename.c_str());
 	parse_arc(data.c_str());
 	Level level;
-	level.arcade = g_parsedArc;
+	level.arcade = *g_parsedArc;
 	level.arcade.prefix = prefix;
 	_levels[filename] = level;
-	g_parsedArc.background.clear();
-	g_parsedArc.player.clear();
-	g_parsedArc.shoots.clear();
+	g_parsedArc->background.clear();
+	g_parsedArc->player.clear();
+	g_parsedArc->shoots.clear();
 }
 
 ShootSequence HypnoEngine::parseShootList(const Common::String &filename, const Common::String &data) {
diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index dee8f5921d..9d678edb51 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -49,20 +49,20 @@ static const ADGameDescription gameDescriptions[] = {
 	 ADGF_TESTING | ADGF_DEMO,
 	 GUIO1(GUIO_NOMIDI)},
 	{"sinistersix", // US release
-	 _s("Missing game code"),
+	 "",
 	 AD_ENTRY2s("DATA.Z", "a1f71005a45e6ee454bb0bf3868dff54", 8766307,
 				"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
 	 Common::EN_USA,
 	 Common::kPlatformDOS,
-	 ADGF_UNSTABLE | ADGF_UNSUPPORTED,
+	 ADGF_UNSTABLE,
 	 GUIO1(GUIO_NOMIDI)},
 	{"sinistersix", // ES release
-	 _s("Missing game code"),
+	 "",
 	 AD_ENTRY2s("SPIDER.EXE", "dbd912d6f6724c6d44775fc19cfa8ca0", 483871,
 	 			"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
 	 Common::ES_ESP,
 	 Common::kPlatformDOS,
-	 ADGF_UNSTABLE | ADGF_UNSUPPORTED,
+	 ADGF_UNSTABLE,
 	 GUIO1(GUIO_NOMIDI)},
 	{"wetlands", // Wetlands Demo Disc (November 1995)
 	 "Demo",
diff --git a/engines/hypno/grammar.h b/engines/hypno/grammar.h
index 61cf88db28..4c11e96e05 100644
--- a/engines/hypno/grammar.h
+++ b/engines/hypno/grammar.h
@@ -35,6 +35,11 @@
 
 namespace Hypno {
 
+class HypnoSmackerDecoder : public Video::SmackerDecoder {
+public:
+	bool loadStream(Common::SeekableReadStream *stream) override;
+};
+
 typedef Common::String Filename;
 typedef Common::List<Filename> Filenames;
 
@@ -80,7 +85,7 @@ public:
 	bool scaled;
 	bool transparent;
 	bool loop;
-	Video::SmackerDecoder *decoder;
+	HypnoSmackerDecoder *decoder;
 	const Graphics::Surface *currentFrame;
 };
 
@@ -194,11 +199,13 @@ public:
 		path = path_;
 		origin = origin_;
 		flag = flag_;
-		// TODO fullscreen should be enable or not by default?
+		fullscreen = false;
+		frameNumber = 0;
 	}
 	Filename path;
 	Common::Point origin;
 	Common::String flag;
+	uint32 frameNumber;
 	bool fullscreen;
 };
 
@@ -296,7 +303,7 @@ public:
 	Filenames intros;
 };
 
-class Puzzle {
+class Code {
 public:
 	Common::String name;
 	Filenames intros;
@@ -341,12 +348,12 @@ public:
 	Transition trans;
 	Scene scene;
 	ArcadeShooting arcade;
-	Puzzle puzzle;
+	Code code;
 };
 
 typedef Common::HashMap<Filename, Level> Levels;
 extern Hotspots *g_parsedHots;
-extern ArcadeShooting g_parsedArc;
+extern ArcadeShooting *g_parsedArc;
 
 } // End of namespace Hypno
 
diff --git a/engines/hypno/grammar_arc.cpp b/engines/hypno/grammar_arc.cpp
index a852254163..fdda3a3a85 100644
--- a/engines/hypno/grammar_arc.cpp
+++ b/engines/hypno/grammar_arc.cpp
@@ -506,11 +506,11 @@ static const yytype_uint8 yytranslate[] =
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint8 yyrline[] =
 {
-       0,    76,    76,    77,    80,    81,    82,    85,    86,    87,
-      88,    89,    90,    91,    92,    93,    98,   103,   104,   108,
-     109,   113,   114,   124,   134,   135,   141,   142,   145,   146,
-     147,   150,   155,   160,   165,   169,   173,   177,   178,   179,
-     183,   184,   187,   188,   189,   190,   194,   201,   202
+       0,    76,    76,    77,    80,    81,    82,    85,    88,    89,
+      90,    91,    92,    93,    94,    95,   100,   105,   106,   110,
+     111,   115,   116,   126,   136,   137,   143,   144,   147,   148,
+     149,   152,   157,   162,   167,   171,   175,   179,   180,   181,
+     185,   186,   189,   190,   191,   192,   196,   203,   204
 };
 #endif
 
@@ -1345,274 +1345,276 @@ yyreduce:
     {
         case 7:
 #line 85 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
-    { debugC(1, kHypnoDebugParser, "C %d", (yyvsp[0].i)); }
-#line 1350 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+    {
+		g_parsedArc->id = (yyvsp[0].i); 
+		debugC(1, kHypnoDebugParser, "C %d", (yyvsp[0].i)); }
+#line 1352 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 86 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 88 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "F %d", (yyvsp[0].i)); }
-#line 1356 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1358 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 87 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 89 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "D %d", (yyvsp[0].i)); }
-#line 1362 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1364 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 88 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 90 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "P %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1368 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1370 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 89 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 91 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "A %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1374 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1376 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 90 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 92 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "V %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1380 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1382 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 91 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 93 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1386 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1388 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 92 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 94 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "O1 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1392 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1394 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 93 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 95 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
-		g_parsedArc.transitionVideo = (yyvsp[-2].s);
-		g_parsedArc.transitionTime = (yyvsp[-1].i);
+		g_parsedArc->transitionVideo = (yyvsp[-2].s);
+		g_parsedArc->transitionTime = (yyvsp[-1].i);
 		debugC(1, kHypnoDebugParser, "Tp %s %d %s", (yyvsp[-2].s), (yyvsp[-1].i), (yyvsp[0].s)); 
 	}
-#line 1402 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1404 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 98 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 100 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		g_parsedArc.transitionVideo = (yyvsp[-1].s);
-		g_parsedArc.transitionTime = (yyvsp[0].i);
+		g_parsedArc->transitionVideo = (yyvsp[-1].s);
+		g_parsedArc->transitionTime = (yyvsp[0].i);
 		debugC(1, kHypnoDebugParser, "T %s %d", (yyvsp[-1].s), (yyvsp[0].i)); 
 	}
-#line 1412 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1414 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 103 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 105 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "T NONE %d", (yyvsp[0].i)); }
-#line 1418 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1420 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 104 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 106 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		g_parsedArc.background = (yyvsp[0].s); 
+		g_parsedArc->background = (yyvsp[0].s); 
 		debugC(1, kHypnoDebugParser, "N %s", (yyvsp[0].s)); 
 	}
-#line 1427 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1429 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 108 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 110 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "R %s", (yyvsp[0].s)); }
-#line 1433 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1435 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 109 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 111 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		g_parsedArc.player = (yyvsp[0].s); 
+		g_parsedArc->player = (yyvsp[0].s); 
 		debugC(1, kHypnoDebugParser, "I %s", (yyvsp[0].s)); 
 		}
-#line 1442 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1444 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 113 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 115 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "Q %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1448 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1450 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 114 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 116 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		if (Common::String("B0") == (yyvsp[-1].s))
-			g_parsedArc.intro = (yyvsp[0].s);
+			g_parsedArc->intro = (yyvsp[0].s);
 		else if(Common::String("B1") == (yyvsp[-1].s) || Common::String("B2") == (yyvsp[-1].s))
-			g_parsedArc.winVideos.push_back((yyvsp[0].s));
+			g_parsedArc->winVideos.push_back((yyvsp[0].s));
 		else if(Common::String("B3") == (yyvsp[-1].s) || Common::String("B4") == (yyvsp[-1].s))
-			g_parsedArc.defeatVideos.push_back((yyvsp[0].s));
+			g_parsedArc->defeatVideos.push_back((yyvsp[0].s));
 
 		debugC(1, kHypnoDebugParser, "BN %s", (yyvsp[0].s)); 
 	}
-#line 1463 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1465 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 124 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 126 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
 		if (Common::String("S0") == (yyvsp[-2].s))
-			g_parsedArc.music = (yyvsp[-1].s);
+			g_parsedArc->music = (yyvsp[-1].s);
 		else if (Common::String("S1") == (yyvsp[-2].s))
-			g_parsedArc.shootSound = (yyvsp[-1].s);
+			g_parsedArc->shootSound = (yyvsp[-1].s);
 		else if (Common::String("S4") == (yyvsp[-2].s))
-			g_parsedArc.enemySound = (yyvsp[-1].s); 
+			g_parsedArc->enemySound = (yyvsp[-1].s); 
 
 		debugC(1, kHypnoDebugParser, "SN %s", (yyvsp[-1].s)); 
 	}
-#line 1478 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1480 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 134 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 136 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "HE %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1484 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1486 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 135 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 137 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
-		g_parsedArc.health = (yyvsp[-1].i);
+		g_parsedArc->health = (yyvsp[-1].i);
 		debugC(1, kHypnoDebugParser, "H %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	}
-#line 1493 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1495 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 150 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 152 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
 		debugC(1, kHypnoDebugParser, "FN %s", (yyvsp[0].s)); 
 	}
-#line 1503 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1505 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 155 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 157 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = "NONE";
 		debugC(1, kHypnoDebugParser, "FN NONE"); 
 	}
-#line 1513 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1515 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 160 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 162 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot = new Shoot();
 		shoot->animation = (yyvsp[0].s);
 		debugC(1, kHypnoDebugParser, "FN %s", (yyvsp[0].s)); 
 	}
-#line 1523 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1525 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 165 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 167 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->name = (yyvsp[0].s);
 		debugC(1, kHypnoDebugParser, "I %s", (yyvsp[0].s)); 
 	}
-#line 1532 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1534 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 169 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 171 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {  // Workaround for NAME == B1
 		shoot->name = (yyvsp[0].s);
 		debugC(1, kHypnoDebugParser, "I %s", (yyvsp[0].s)); 
 	}
-#line 1541 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1543 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 173 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 175 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->position = Common::Point((yyvsp[-1].i), (yyvsp[0].i));
 		debugC(1, kHypnoDebugParser, "A0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	}
-#line 1550 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1552 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 177 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 179 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "R %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1556 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1558 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 178 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 180 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "BN %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1562 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1564 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 179 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 181 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->explosionFrame = (yyvsp[0].i);
 		debugC(1, kHypnoDebugParser, "K0 %d %d", (yyvsp[-1].i), (yyvsp[0].i));
 	}
-#line 1571 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1573 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 183 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 185 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "P0 %d %d", (yyvsp[-1].i), (yyvsp[0].i)); }
-#line 1577 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1579 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 184 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 186 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		debugC(1, kHypnoDebugParser, "O %d %d", (yyvsp[-1].i), (yyvsp[0].i)); 
 	}
-#line 1585 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1587 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 187 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "C %d", (yyvsp[0].i)); }
-#line 1591 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1593 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 188 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 190 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "H %d", (yyvsp[0].i)); }
-#line 1597 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1599 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 189 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 191 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "W %d", (yyvsp[0].i)); }
-#line 1603 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1605 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 190 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 192 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		shoot->damage = (yyvsp[0].i);
 		debugC(1, kHypnoDebugParser, "D %d", (yyvsp[0].i)); 
 	}
-#line 1612 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1614 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 194 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 196 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { 
 		if (Common::String("S1") == (yyvsp[-2].s))
 			shoot->endSound = (yyvsp[-1].s);
@@ -1620,28 +1622,28 @@ yyreduce:
 		//	shoot->startSound = $2;
 		 
 		debugC(1, kHypnoDebugParser, "SN %s", (yyvsp[-1].s)); }
-#line 1624 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1626 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 201 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 203 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     { debugC(1, kHypnoDebugParser, "N"); }
-#line 1630 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1632 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 202 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
+#line 204 "engines/hypno/grammar_arc.y" /* yacc.c:1646  */
     {
-		g_parsedArc.shoots.push_back(*shoot); 
+		g_parsedArc->shoots.push_back(*shoot); 
 		//delete shoot; 
 		//shoot = nullptr;
 		debugC(1, kHypnoDebugParser, "Z"); 
 	}
-#line 1641 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1643 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 1645 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
+#line 1647 "engines/hypno/grammar_arc.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index 4efe38bf65..5189be18ca 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -82,7 +82,9 @@ header: hline header
 	| /* nothing */
 	; 
 
-hline:  CTOK NUM  { debugC(1, kHypnoDebugParser, "C %d", $2); }
+hline:  CTOK NUM {
+		g_parsedArc->id = $2; 
+		debugC(1, kHypnoDebugParser, "C %d", $2); }
 	| FTOK NUM { debugC(1, kHypnoDebugParser, "F %d", $2); }
 	| DTOK NUM  { debugC(1, kHypnoDebugParser, "D %d", $2); }
 	| PTOK NUM NUM { debugC(1, kHypnoDebugParser, "P %d %d", $2, $3); }
@@ -91,49 +93,49 @@ hline:  CTOK NUM  { debugC(1, kHypnoDebugParser, "C %d", $2); }
 	| OTOK NUM NUM { debugC(1, kHypnoDebugParser, "O %d %d", $2, $3); }
 	| O1TOK NUM NUM { debugC(1, kHypnoDebugParser, "O1 %d %d", $2, $3); }
 	| TPTOK FILENAME NUM FILENAME {
-		g_parsedArc.transitionVideo = $2;
-		g_parsedArc.transitionTime = $3;
+		g_parsedArc->transitionVideo = $2;
+		g_parsedArc->transitionTime = $3;
 		debugC(1, kHypnoDebugParser, "Tp %s %d %s", $2, $3, $4); 
 	}
 	| TTOK FILENAME NUM { 
-		g_parsedArc.transitionVideo = $2;
-		g_parsedArc.transitionTime = $3;
+		g_parsedArc->transitionVideo = $2;
+		g_parsedArc->transitionTime = $3;
 		debugC(1, kHypnoDebugParser, "T %s %d", $2, $3); 
 	}
 	| TTOK NONETOK NUM { debugC(1, kHypnoDebugParser, "T NONE %d", $3); }
 	| NTOK FILENAME  { 
-		g_parsedArc.background = $2; 
+		g_parsedArc->background = $2; 
 		debugC(1, kHypnoDebugParser, "N %s", $2); 
 	}
 	| RTOK FILENAME  { debugC(1, kHypnoDebugParser, "R %s", $2); }
 	| ITOK FILENAME { 
-		g_parsedArc.player = $2; 
+		g_parsedArc->player = $2; 
 		debugC(1, kHypnoDebugParser, "I %s", $2); 
 		}
 	| QTOK NUM NUM { debugC(1, kHypnoDebugParser, "Q %d %d", $2, $3); }
 	| BNTOK FILENAME {
 		if (Common::String("B0") == $1)
-			g_parsedArc.intro = $2;
+			g_parsedArc->intro = $2;
 		else if(Common::String("B1") == $1 || Common::String("B2") == $1)
-			g_parsedArc.winVideos.push_back($2);
+			g_parsedArc->winVideos.push_back($2);
 		else if(Common::String("B3") == $1 || Common::String("B4") == $1)
-			g_parsedArc.defeatVideos.push_back($2);
+			g_parsedArc->defeatVideos.push_back($2);
 
 		debugC(1, kHypnoDebugParser, "BN %s", $2); 
 	}
 	| SNTOK FILENAME enc {
 		if (Common::String("S0") == $1)
-			g_parsedArc.music = $2;
+			g_parsedArc->music = $2;
 		else if (Common::String("S1") == $1)
-			g_parsedArc.shootSound = $2;
+			g_parsedArc->shootSound = $2;
 		else if (Common::String("S4") == $1)
-			g_parsedArc.enemySound = $2; 
+			g_parsedArc->enemySound = $2; 
 
 		debugC(1, kHypnoDebugParser, "SN %s", $2); 
 	}
 	| HETOK C02TOK NUM NUM { debugC(1, kHypnoDebugParser, "HE %d %d", $3, $4); }
 	| HTOK CB3TOK NUM NUM { 
-		g_parsedArc.health = $3;
+		g_parsedArc->health = $3;
 		debugC(1, kHypnoDebugParser, "H %d %d", $3, $4); 
 	}
 	;
@@ -200,7 +202,7 @@ bline: FNTOK FILENAME {
 		debugC(1, kHypnoDebugParser, "SN %s", $2); }
 	| NTOK { debugC(1, kHypnoDebugParser, "N"); }
 	| ZTOK {
-		g_parsedArc.shoots.push_back(*shoot); 
+		g_parsedArc->shoots.push_back(*shoot); 
 		//delete shoot; 
 		//shoot = nullptr;
 		debugC(1, kHypnoDebugParser, "Z"); 
diff --git a/engines/hypno/hypno.cpp b/engines/hypno/hypno.cpp
index ed8d529b0c..8d1d536b0d 100644
--- a/engines/hypno/hypno.cpp
+++ b/engines/hypno/hypno.cpp
@@ -43,7 +43,7 @@
 namespace Hypno {
 
 Hotspots *g_parsedHots;
-ArcadeShooting g_parsedArc;
+ArcadeShooting *g_parsedArc;
 HypnoEngine *g_hypno;
 
 MVideo::MVideo(Common::String path_, Common::Point position_, bool transparent_, bool scaled_, bool loop_) {
@@ -64,6 +64,7 @@ HypnoEngine::HypnoEngine(OSystem *syst, const ADGameDescription *gd)
 	_rnd = new Common::RandomSource("hypno");
 
 	g_hypno = this;
+	g_parsedArc = new ArcadeShooting();
 	_defaultCursor = "";
 	// Add quit level
 	Hotspot q(MakeMenu, "");
@@ -90,6 +91,8 @@ HypnoEngine::~HypnoEngine() {
 	delete _rnd;
 	_compositeSurface->free();
 	delete _compositeSurface;
+
+	delete g_parsedArc;
 }
 
 void HypnoEngine::initializePath(const Common::FSNode &gamePath) {
@@ -166,13 +169,14 @@ void HypnoEngine::runLevel(Common::String &name) {
 		}
 		changeScreenMode("arcade");
 		runArcade(_levels[name].arcade);
-	} else if (!_levels[name].puzzle.name.empty()) {
-		debugC(1, kHypnoDebugScene, "Executing puzzle level %s", name.c_str());
+	} else if (!_levels[name].code.name.empty()) {
+		debugC(1, kHypnoDebugScene, "Executing hardcoded level %s", name.c_str());
+		//resetSceneState(); // TODO: is this required?
 		if (!_levels[name].arcade.intro.empty()) {
 			MVideo v(_levels[name].arcade.intro, Common::Point(0, 0), false, true, false);
 			runIntro(v);
 		}
-		runPuzzle(_levels[name].puzzle);
+		runCode(_levels[name].code);
 	} else {
 		debugC(1, kHypnoDebugScene, "Executing scene level %s", name.c_str());
 		resetSceneState();
@@ -221,12 +225,12 @@ void HypnoEngine::runIntro(MVideo &video) {
 	}
 }
 
-void HypnoEngine::runPuzzle(Puzzle puzzle) { error("Function \"%s\" not implemented", __FUNCTION__); }
+void HypnoEngine::runCode(Code code) { error("Function \"%s\" not implemented", __FUNCTION__); }
 void HypnoEngine::showCredits() { error("Function \"%s\" not implemented", __FUNCTION__); }
 
-void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent) {
+void HypnoEngine::loadImage(const Common::String &name, int x, int y, bool transparent, int frameNumber) {
 	debugC(1, kHypnoDebugMedia, "%s(%s, %d, %d, %d)", __FUNCTION__, name.c_str(), x, y, transparent);
-	Graphics::Surface *surf = decodeFrame(name, 0);
+	Graphics::Surface *surf = decodeFrame(name, frameNumber);
 	drawImage(*surf, x, y, transparent);
 }
 
@@ -273,7 +277,7 @@ Graphics::Surface *HypnoEngine::decodeFrame(const Common::String &name, int n, b
 
 	file = fixSmackerHeader(file);
 
-	Video::SmackerDecoder vd;
+	HypnoSmackerDecoder vd;
 	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
 
@@ -305,7 +309,7 @@ Frames HypnoEngine::decodeFrames(const Common::String &name) {
 
 	file = fixSmackerHeader(file);
 
-	Video::SmackerDecoder vd;
+	HypnoSmackerDecoder vd;
 	if (!vd.loadStream(file))
 		error("unable to load video %s", path.c_str());
 
@@ -405,10 +409,12 @@ void HypnoEngine::playVideo(MVideo &video) {
 	if (video.decoder != nullptr)
 		error("Video %s was not previously closed and deallocated", video.path.c_str());
 
-	video.decoder = new Video::SmackerDecoder();
+	video.decoder = new HypnoSmackerDecoder();
 
 	if (!video.decoder->loadStream(file))
 		error("unable to load video %s", path.c_str());
+	
+	debugC(1, kHypnoDebugMedia, "audio track count: %d", video.decoder->getAudioTrackCount()); 
 	video.decoder->start();
 }
 
diff --git a/engines/hypno/hypno.h b/engines/hypno/hypno.h
index 59b1552048..a0164b345e 100644
--- a/engines/hypno/hypno.h
+++ b/engines/hypno/hypno.h
@@ -121,7 +121,7 @@ public:
 	Common::File *fixSmackerHeader(Common::File *file);
 	Graphics::Surface *decodeFrame(const Common::String &name, int frame, bool convert = true);
 	Frames decodeFrames(const Common::String &name);
-	void loadImage(const Common::String &file, int x, int y, bool transparent);
+	void loadImage(const Common::String &file, int x, int y, bool transparent, int frameNumber = 0);
 	void drawImage(Graphics::Surface &image, int x, int y, bool transparent);
 
 	// Cursors
@@ -190,6 +190,7 @@ public:
 	virtual void drawShoot(const Common::Point &mousePos);
 	virtual void shoot(const Common::Point &mousePos);
 	virtual void hitPlayer();
+	Common::String _difficulty; 
 
 	void drawCursorArcade(const Common::Point &mousePos);
 	virtual void drawPlayer();
@@ -211,8 +212,8 @@ public:
 	virtual void rightClickedConversation(const Common::Point &mousePos);
 	virtual void leftClickedConversation(const Common::Point &mousePos);
 
-	// Hardcoded puzzles
-	virtual void runPuzzle(Puzzle puzzle);
+	// For some menus and hardcoded puzzles
+	virtual void runCode(Code code);
 
 	// Transitions
 	void runTransition(Transition trans);
@@ -225,10 +226,17 @@ public:
 	void removeTimer();
 };
 
+struct chapterEntry {
+        int id;
+        int energyPos[2];
+		int scorePos[2];
+		int objectivesPos[2];
+};
+
 class WetEngine : public HypnoEngine {
 public:
 	WetEngine(OSystem *syst, const ADGameDescription *gd);
-
+	Common::HashMap<int, const struct chapterEntry*> _chapterTable;
 	void loadAssets() override;
 	void loadAssetsDemoDisc();
 	void loadAssetsPCW();
@@ -239,6 +247,11 @@ public:
 	void drawShoot(const Common::Point &target) override;
 	void drawPlayer() override;
 	void drawHealth() override;
+	void runCode(Code code) override;
+
+private:
+	void loadLevel(const Common::String &current, const Common::String &next, const Common::String &prefix);
+	void runMainMenu(Code code);
 };
 
 class SpiderEngine : public HypnoEngine {
@@ -251,14 +264,14 @@ public:
 	void drawShoot(const Common::Point &target) override;
 	void drawPlayer() override;
 	void drawHealth() override;
-	void runPuzzle(Puzzle puzzle) override;
+	void runCode(Code code) override;
 
 	void showConversation() override;
 	void rightClickedConversation(const Common::Point &mousePos) override;
 	void leftClickedConversation(const Common::Point &mousePos) override;
 
 private:
-	void runMatrix(Puzzle puzzle);
+	void runMatrix(Code code);
 };
 
 class BoyzEngine : public HypnoEngine {
diff --git a/engines/hypno/module.mk b/engines/hypno/module.mk
index 2d157a20c4..61007fe968 100644
--- a/engines/hypno/module.mk
+++ b/engines/hypno/module.mk
@@ -16,6 +16,7 @@ MODULE_OBJS := \
 	spider/arcade.o \
 	spider/spider.o \
 	spider/talk.o \
+	video.o \
 	wet/arcade.o \
 	wet/wet.o
 
diff --git a/engines/hypno/scene.cpp b/engines/hypno/scene.cpp
index 5bfb891b4a..6915c32637 100644
--- a/engines/hypno/scene.cpp
+++ b/engines/hypno/scene.cpp
@@ -160,6 +160,9 @@ void HypnoEngine::clickedHotspot(Common::Point mousePos) {
 			case QuitAction:
 				runQuit((Quit *)action);
 			break;
+			case AmbientAction: 
+				runAmbient((Ambient *)action);
+			break;
 			case PaletteAction:
 				debugC(1, kHypnoDebugScene, "runPalette unimplemented");
 			break;
@@ -222,7 +225,7 @@ void HypnoEngine::runTransition(Transition trans) {
 		sframe->free();
 		delete sframe;
 		Common::String *ptr = new Common::String(trans.level);
-		if (!installTimer(2 * 1000000, ptr))
+		if (!installTimer(2 * 1000000, ptr)) // 2 seconds
 			error("Failed to install timer");
 	} else
 		_nextLevel = trans.level;
diff --git a/engines/hypno/spider/spider.cpp b/engines/hypno/spider/spider.cpp
index ac6046600f..54d4a97e27 100644
--- a/engines/hypno/spider/spider.cpp
+++ b/engines/hypno/spider/spider.cpp
@@ -169,22 +169,22 @@ void SpiderEngine::loadAssetsDemo() {
 	parseScene("sixdemo", "mis/shoctalk.mis");
 
 	Level matrix;
-	matrix.puzzle.name = "sixdemo/puz_matr";
-	matrix.puzzle.intros.push_back("spiderman/demo/aleyc01s.smk");
-	matrix.puzzle.levelIfWin = "sixdemo/mis/demo.mis";
-	matrix.puzzle.levelIfLose = "sixdemo/mis/demo.mis";
+	matrix.code.name = "sixdemo/puz_matr";
+	matrix.code.intros.push_back("spiderman/demo/aleyc01s.smk");
+	matrix.code.levelIfWin = "sixdemo/mis/demo.mis";
+	matrix.code.levelIfLose = "sixdemo/mis/demo.mis";
 	_levels["sixdemo/puz_matr"] = matrix;
 	_soundPath = "c_misc/sound.lib/";
 }
 
-void SpiderEngine::runPuzzle(Puzzle puzzle) {
-	if (puzzle.name == "sixdemo/puz_matr")
-		runMatrix(puzzle);
+void SpiderEngine::runCode(Code code) {
+	if (code.name == "sixdemo/puz_matr")
+		runMatrix(code);
 	else
 		error("invalid puzzle");
 }
 
-void SpiderEngine::runMatrix(Puzzle puzzle) {
+void SpiderEngine::runMatrix(Code code) {
 	Common::Point mousePos;
 	Common::Event event;
 
@@ -251,7 +251,7 @@ void SpiderEngine::runMatrix(Puzzle puzzle) {
 
 		if (found) {
 			playSound("sixdemo/demo/sound.lib/matrix_2.raw", 1);
-			_nextLevel = puzzle.levelIfWin;
+			_nextLevel = code.levelIfWin;
 			return;
 		}
 
diff --git a/engines/hypno/video.cpp b/engines/hypno/video.cpp
new file mode 100644
index 0000000000..d854cf29f2
--- /dev/null
+++ b/engines/hypno/video.cpp
@@ -0,0 +1,22 @@
+#include "hypno/grammar.h"
+#include "hypno/hypno.h"
+
+namespace Hypno {
+
+bool HypnoSmackerDecoder::loadStream(Common::SeekableReadStream *stream) {
+	if (!SmackerDecoder::loadStream(stream))
+		return false;
+
+	// Map audio tracks to sound types
+	for (uint32 i = 0; i < 8; i++) {
+		Track *t = getTrack(i);
+		if (t && t->getTrackType() == Track::kTrackTypeAudio) {
+			AudioTrack *audio = (AudioTrack *)t;
+			audio->setMute(false);
+			audio->setSoundType(i == 7 ? Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType);
+		}
+	}
+	return true;
+}
+
+}
\ No newline at end of file
diff --git a/engines/hypno/wet/arcade.cpp b/engines/hypno/wet/arcade.cpp
index f31061f743..8205d91b88 100644
--- a/engines/hypno/wet/arcade.cpp
+++ b/engines/hypno/wet/arcade.cpp
@@ -75,21 +75,17 @@ void WetEngine::drawPlayer() {
 	drawImage(*_playerFrames[_playerFrameIdx], 0, 200 - _playerFrames[_playerFrameIdx]->h + 1, true);
 }
 
-static const int uiPos[2][3][2] = {
-	{{70, 160}, {180, 160}, {220, 185}}, // c31
-	{{60, 167}, {190, 167}, {135, 187}}, // c52
-};
-
 void WetEngine::drawHealth() {
 	uint32 c = _pixelFormat.RGBToColor(252, 252, 0);
 	int p = (100 * _health) / _maxHealth;
 	int s = _score;
 	if (_playerFrameIdx < _playerFrameSep) {
+		const chapterEntry *entry = _chapterTable[_levelId];
 		uint32 id = _levelId;
-		_font->drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), uiPos[id][0][0], uiPos[id][0][1], 65, c);
-		_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", s), uiPos[id][1][0], uiPos[id][1][1], 72, c);
+		_font->drawString(_compositeSurface, Common::String::format("ENERGY   %d%%", p), entry->energyPos[0], entry->energyPos[1], 65, c);
+		_font->drawString(_compositeSurface, Common::String::format("SCORE    %04d", s), entry->scorePos[0], entry->scorePos[1], 72, c);
 		// Objectives are always in the zero in the demo
-		_font->drawString(_compositeSurface, Common::String::format("M.O.     0/0"), uiPos[id][2][0], uiPos[id][2][1], 60, c);
+		//_font->drawString(_compositeSurface, Common::String::format("M.O.     0/0"), uiPos[id][2][0], uiPos[id][2][1], 60, c);
 	}
 }
 
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 72971b7dcf..5d113e8d1b 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -20,17 +20,37 @@
  *
  */
 
+#include "common/events.h"
+#include "common/config-manager.h"
+
 #include "hypno/hypno.h"
 
 namespace Hypno {
 
-WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {}
+static const chapterEntry rawChapterTable[] = {
+	{11, {44, 172}, {218, 172}, {0, 0}}, 		// c11
+	{31, {70, 160}, {180, 160}, {220, 185}}, 	// c31
+	{52, {60, 167}, {190, 167}, {135, 187}}, 	// c52
+	{0,  {0,  0},   {0,   0},   {0,   0}}    	// NULL
+};
+
+WetEngine::WetEngine(OSystem *syst, const ADGameDescription *gd) : HypnoEngine(syst, gd) {
+    const chapterEntry *entry = rawChapterTable;
+    while (entry->id) {
+		_chapterTable[entry->id] = entry;
+		entry++;
+    }
+
+}
 
 void WetEngine::loadAssets() {
 	if (!isDemo()) {
+		_difficulty = "1"; // Medium difficulty by default
 		loadAssetsFullGame();
 		return;
 	}
+	_difficulty = ""; // No difficulty selection in demo
+
 	Common::String demoVersion = "Wetlands Demo Disc";
 	if (demoVersion == "Wetlands Demo Disc")
 		loadAssetsDemoDisc();
@@ -115,28 +135,8 @@ void WetEngine::loadAssetsDemoDisc() {
 	movies.trans.frameNumber = 0;
 	_levels["<movies>"] = movies;
 
-	Common::String arclevel = "c31.mi_";
-	debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
-	Common::String arc;
-	Common::String list;
-	splitArcadeFile(arclevel, arc, list);
-	parseArcadeShooting("wetlands", arclevel, arc);
-	_levels[arclevel].arcade.id = 0;
-	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-	_levels[arclevel].arcade.prefix = "wetlands";
-	_levels[arclevel].arcade.levelIfWin = "c52.mi_";
-	_levels[arclevel].arcade.levelIfLose = "c52.mi_";
-
-	arclevel = "c52.mi_";
-	arc.clear();
-	list.clear();
-	splitArcadeFile(arclevel, arc, list);
-	parseArcadeShooting("wetlands", arclevel, arc);
-	_levels[arclevel].arcade.id = 1;
-	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-	_levels[arclevel].arcade.prefix = "wetlands";
-	_levels[arclevel].arcade.levelIfWin = "<gameover>";
-	_levels[arclevel].arcade.levelIfLose = "<gameover>";
+	loadLevel("c31", "c52", "wetlands");
+	loadLevel("c52", "<gameover>", "wetlands");
 
 	Level over;
 	over.trans.level = "<quit>";
@@ -167,7 +167,6 @@ void WetEngine::loadAssetsPCW() {
 	Common::String list;
 	splitArcadeFile(arclevel, arc, list);
 	parseArcadeShooting("wetlands", arclevel, arc);
-	_levels[arclevel].arcade.id = 0;
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 	_levels[arclevel].arcade.prefix = "";
 	_levels[arclevel].arcade.levelIfWin = "<gameover>";
@@ -202,7 +201,6 @@ void WetEngine::loadAssetsPCG() {
 	Common::String list;
 	splitArcadeFile(arclevel, arc, list);
 	parseArcadeShooting("wetlands", arclevel, arc);
-	_levels[arclevel].arcade.id = 0;
 	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
 	_levels[arclevel].arcade.prefix = "";
 	_levels[arclevel].arcade.levelIfWin = "<gameover>";
@@ -216,6 +214,18 @@ void WetEngine::loadAssetsPCG() {
 	loadLib("", "sound.lib", false);
 }
 
+void WetEngine::loadLevel(const Common::String &current, const Common::String &next, const Common::String &prefix) {
+	Common::String arclevel = current + _difficulty + ".mi_";
+	debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
+	Common::String arc;
+	Common::String list;
+	splitArcadeFile(arclevel, arc, list);
+	debug("%s", arc.c_str());
+	parseArcadeShooting("", arclevel, arc);
+	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
+	_levels[arclevel].arcade.prefix = prefix;
+	_levels[arclevel].arcade.levelIfWin = next + _difficulty + ".mi_";;
+}
 
 void WetEngine::loadAssetsFullGame() {
 	LibFile *missions = loadLib("", "c_misc/missions.lib", true);
@@ -224,41 +234,22 @@ void WetEngine::loadAssetsFullGame() {
 		error("Failed to load any files from missions.lib");
 
 	Level intro;
-	intro.trans.level = "c111.mi_";
+	intro.trans.level = "wetlands/main_menu.mis"; //"c11" + _difficulty + ".mi_";
 	intro.trans.intros.push_back("c_misc/logo.smk");
 	intro.trans.intros.push_back("c_misc/nw_logo.smk");
 	intro.trans.intros.push_back("c_misc/hypnotix.smk");
 	intro.trans.intros.push_back("c_misc/wetlogo.smk");
 	_levels["<start>"] = intro;
 
-	Common::String arclevel = "c111.mi_";
-	debugC(1, kHypnoDebugParser, "Parsing %s", arclevel.c_str());
-	Common::String arc;
-	Common::String list;
-	splitArcadeFile(arclevel, arc, list);
-	debug("%s", arc.c_str());
-	parseArcadeShooting("", arclevel, arc);
-	_levels[arclevel].arcade.id = 0;
-	_levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-	_levels[arclevel].arcade.prefix = "";
-	//_levels[arclevel].arcade.levelIfWin = "c52.mi_";
-	//_levels[arclevel].arcade.levelIfLose = "c52.mi_";
-
-	//arclevel = "c52.mi_";
-	// arc.clear();
-	// list.clear();
-	// splitArcadeFile(arclevel, arc, list);
-	// parseArcadeShooting("wetlands", arclevel, arc);
-	// _levels[arclevel].arcade.id = 1;
-	// _levels[arclevel].arcade.shootSequence = parseShootList(arclevel, list);
-	// _levels[arclevel].arcade.prefix = "wetlands";
-	// _levels[arclevel].arcade.levelIfWin = "<gameover>";
-	// _levels[arclevel].arcade.levelIfLose = "<gameover>";
-
-	// Level over;
-	// over.trans.level = "<quit>";
-	// over.trans.intros.push_back("movie/gameover.smk");
-	// _levels["<gameover>"] = over;
+
+	Level menu;
+	menu.code.name = "wetlands/main_menu.mis";
+	_levels["wetlands/main_menu.mis"] = menu;
+	_levels["wetlands/main_menu.mis"].code.levelIfWin = "c11" + _difficulty + ".mi_";
+
+	//loadLevel("c10", "c11", "");
+	loadLevel("c11", "c20", "");
+	loadLevel("c20", "", "");
 
 	loadLib("", "c_misc/fonts.lib", true);
 	loadLib("sound/", "c_misc/sound.lib", true);
@@ -269,5 +260,58 @@ void WetEngine::showCredits() {
 	runIntro(video);
 }
 
+void WetEngine::runCode(Code code) {
+	changeScreenMode("arcade"); // everything runs in 320x200
+	if (code.name == "wetlands/main_menu.mis")
+		runMainMenu(code);
+	else
+		error("invalid hardcoded level: %s", code.name.c_str());
+}
+
+void WetEngine::runMainMenu(Code code) {
+	Common::Event event;
+	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
+	uint32 c = _pixelFormat.RGBToColor(0, 252, 0);
+	uint32 position = 140;
+	Graphics::Surface *frame = decodeFrame("c_misc/menus.smk", 16, true);
+	Common::String _name = "";
+	//Graphics::Surface *sframe = frame->scale(_screenW, _screenH);
+	drawImage(*frame, 0, 0, false);
+	while (!shouldQuit()) {
+
+		while (g_system->getEventManager()->pollEvent(event)) {
+			// Events
+			switch (event.type) {
+
+			case Common::EVENT_QUIT:
+			case Common::EVENT_RETURN_TO_LAUNCHER:
+				break;
+
+			case Common::EVENT_KEYDOWN:
+				if (event.kbd.keycode == Common::KEYCODE_BACKSPACE)
+					_name.deleteLastChar();
+				else if (event.kbd.keycode == Common::KEYCODE_RETURN && !_name.empty()) {
+					_nextLevel = code.levelIfWin;
+					return;
+				}
+				else if (Common::isAlnum(event.kbd.keycode)) {
+					_name = _name + char(event.kbd.keycode - 32);
+				}
+
+				drawImage(*frame, 0, 0, false);
+				_font->drawString(_compositeSurface, "ENTER NAME :", 48, 50, 100, c);
+				_font->drawString(_compositeSurface, _name, 140, 50, 170, c);
+				break;
+
+
+			default:
+				break;
+			}
+		}
+
+		drawScreen();
+		g_system->delayMillis(10);
+	}
+}
 
 } // End of namespace Hypno


Commit: 8d35d2577e9c0ba8aeae1f6a99938d85e4a00afd
    https://github.com/scummvm/scummvm/commit/8d35d2577e9c0ba8aeae1f6a99938d85e4a00afd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: more code formating fixes in c++ code and grammars

Changed paths:
    engines/hypno/arcade.cpp
    engines/hypno/grammar_arc.y
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/arcade.cpp b/engines/hypno/arcade.cpp
index 9d6a6fd4ea..5feb0427b9 100644
--- a/engines/hypno/arcade.cpp
+++ b/engines/hypno/arcade.cpp
@@ -126,7 +126,7 @@ void HypnoEngine::runArcade(ArcadeShooting &arc) {
 		_playerFrameSep++;
 	}
 
-	if(_playerFrameSep == _playerFrames.size())
+	if (_playerFrameSep == _playerFrames.size())
 		error("No player separator frame found!");
 	debugC(1, kHypnoDebugArcade, "Separator frame found at %d", _playerFrameSep);
 
diff --git a/engines/hypno/grammar_arc.y b/engines/hypno/grammar_arc.y
index 5189be18ca..522b8e4b40 100644
--- a/engines/hypno/grammar_arc.y
+++ b/engines/hypno/grammar_arc.y
@@ -74,15 +74,15 @@ using namespace Hypno;
 %%
 
 start: YXTOK header ZTOK RETTOK body XTOK
-    | RETTOK start
+	| RETTOK start
 	;
 
 header: hline header
-    | RETTOK header
+	| RETTOK header
 	| /* nothing */
 	; 
 
-hline:  CTOK NUM {
+hline: 	CTOK NUM {
 		g_parsedArc->id = $2; 
 		debugC(1, kHypnoDebugParser, "C %d", $2); }
 	| FTOK NUM { debugC(1, kHypnoDebugParser, "F %d", $2); }
diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index 5d113e8d1b..dde883f365 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -272,7 +272,6 @@ void WetEngine::runMainMenu(Code code) {
 	Common::Event event;
 	_font = FontMan.getFontByUsage(Graphics::FontManager::kConsoleFont);
 	uint32 c = _pixelFormat.RGBToColor(0, 252, 0);
-	uint32 position = 140;
 	Graphics::Surface *frame = decodeFrame("c_misc/menus.smk", 16, true);
 	Common::String _name = "";
 	//Graphics::Surface *sframe = frame->scale(_screenW, _screenH);


Commit: 844aab515687448c9b9fec19dbab7a5959b7c022
    https://github.com/scummvm/scummvm/commit/844aab515687448c9b9fec19dbab7a5959b7c022
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added header and newline to video.cpp

Changed paths:
    engines/hypno/video.cpp


diff --git a/engines/hypno/video.cpp b/engines/hypno/video.cpp
index d854cf29f2..561a0d0383 100644
--- a/engines/hypno/video.cpp
+++ b/engines/hypno/video.cpp
@@ -1,3 +1,25 @@
+/* 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 "hypno/grammar.h"
 #include "hypno/hypno.h"
 
@@ -19,4 +41,4 @@ bool HypnoSmackerDecoder::loadStream(Common::SeekableReadStream *stream) {
 	return true;
 }
 
-}
\ No newline at end of file
+}


Commit: 815c0138b846ebee95a2647596ffd75643408b1a
    https://github.com/scummvm/scummvm/commit/815c0138b846ebee95a2647596ffd75643408b1a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: fixed formating for detection tables

Changed paths:
    engines/hypno/detection.cpp


diff --git a/engines/hypno/detection.cpp b/engines/hypno/detection.cpp
index 9d678edb51..fd74e52c17 100644
--- a/engines/hypno/detection.cpp
+++ b/engines/hypno/detection.cpp
@@ -40,89 +40,108 @@ static const PlainGameDescriptor hypnoGames[] = {
 	{0, 0}};
 
 static const ADGameDescription gameDescriptions[] = {
-	{"sinistersix", // Demo from the US release
-	 "Demo",
-	 AD_ENTRY2s("DATA.Z",  "2a9c7cf8920ec794482f0a5873102da5", 1285960,
+	{
+		"sinistersix", // Demo from the US release
+		"Demo",
+		AD_ENTRY2s("DATA.Z",  "2a9c7cf8920ec794482f0a5873102da5", 1285960,
 				"DCINE1.SMK", "1ff3db09d148e8dd8b56d2e87e7296b8", 493752),
-	 Common::EN_USA,
-	 Common::kPlatformDOS,
-	 ADGF_TESTING | ADGF_DEMO,
-	 GUIO1(GUIO_NOMIDI)},
-	{"sinistersix", // US release
-	 "",
-	 AD_ENTRY2s("DATA.Z", "a1f71005a45e6ee454bb0bf3868dff54", 8766307,
+		Common::EN_USA,
+		Common::kPlatformDOS,
+		ADGF_TESTING | ADGF_DEMO,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"sinistersix", // US release
+		0,
+		AD_ENTRY2s("DATA.Z", "a1f71005a45e6ee454bb0bf3868dff54", 8766307,
 				"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
-	 Common::EN_USA,
-	 Common::kPlatformDOS,
-	 ADGF_UNSTABLE,
-	 GUIO1(GUIO_NOMIDI)},
-	{"sinistersix", // ES release
-	 "",
-	 AD_ENTRY2s("SPIDER.EXE", "dbd912d6f6724c6d44775fc19cfa8ca0", 483871,
-	 			"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
-	 Common::ES_ESP,
-	 Common::kPlatformDOS,
-	 ADGF_UNSTABLE,
-	 GUIO1(GUIO_NOMIDI)},
-	{"wetlands", // Wetlands Demo Disc (November 1995)
-	 "Demo",
-	 AD_ENTRY3s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231,
+		Common::EN_USA,
+		Common::kPlatformDOS,
+		ADGF_UNSTABLE,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"sinistersix", // ES release
+		0,
+		AD_ENTRY2s("SPIDER.EXE", "dbd912d6f6724c6d44775fc19cfa8ca0", 483871,
+				"MISSIONS.LIB", "585704e26094cbaf14fbee90798e8d5d", 119945),
+		Common::ES_ESP,
+		Common::kPlatformDOS,
+		ADGF_UNSTABLE,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"wetlands", // Wetlands Demo Disc (November 1995)
+		"Demo",
+		AD_ENTRY3s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 642231,
 				"wetdemo.exe", "15a6b1b3819ef002438df340509b5373", 458319,
 				"demo.exe", "15a6b1b3819ef002438df340509b5373", 533221),
-	 Common::EN_USA,
-	 Common::kPlatformDOS,
-	 ADGF_TESTING | ADGF_DEMO,
-	 GUIO1(GUIO_NOMIDI)},
-    {"wetlands", // Personal Computer World (UK) (May 1996) - Chapter 11 demo
-	 "Demo",
-	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 553355,
+		Common::EN_USA,
+		Common::kPlatformDOS,
+		ADGF_TESTING | ADGF_DEMO,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"wetlands", // Personal Computer World (UK) (May 1996) - Chapter 11 demo
+		"Demo",
+		AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 553355,
 				"missions.lib", "6ffa658f22a00b6e17d7f920fcc13578", 12469),
-	 Common::EN_GRB,
-	 Common::kPlatformDOS,
-	 ADGF_TESTING | ADGF_DEMO,
-	 GUIO1(GUIO_NOMIDI)},
-     {"wetlands", // PC Gamer Disc 12 (November 1995) - Chapter 31 demo
-	 "Demo",
-	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 553355,
+		Common::EN_GRB,
+		Common::kPlatformDOS,
+		ADGF_TESTING | ADGF_DEMO,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"wetlands", // PC Gamer Disc 12 (November 1995) - Chapter 31 demo
+		"Demo",
+		AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 553355,
 				"missions.lib", "34b922fac8f64546c0690aa83f09e98e", 40891),
-	 Common::EN_USA,
-	 Common::kPlatformDOS,
-	 ADGF_TESTING | ADGF_DEMO,
-	 GUIO1(GUIO_NOMIDI)},
-
-	{"wetlands", // Wetlands (US)
-	 "",
-	 AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 647447,
+		Common::EN_USA,
+		Common::kPlatformDOS,
+		ADGF_TESTING | ADGF_DEMO,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"wetlands", // Wetlands (US)
+		0,
+		AD_ENTRY2s("wetlands.exe", "15a6b1b3819ef002438df340509b5373", 647447,
 				"missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
-	 Common::EN_USA,
-	 Common::kPlatformDOS,
-	 ADGF_UNSTABLE,
-	 GUIO1(GUIO_NOMIDI)},
-	{"wetlands", // Wetlands (FR)
-	 "",
-	 AD_ENTRY2s("wetlands.exe", "edc5b0c0caf3d5b01d344cb555d9a085", 629575,
+		Common::EN_USA,
+		Common::kPlatformDOS,
+		ADGF_UNSTABLE,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"wetlands", // Wetlands (FR)
+		0,
+		AD_ENTRY2s("wetlands.exe", "edc5b0c0caf3d5b01d344cb555d9a085", 629575,
 			    "missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
-	 Common::FR_FRA,
-	 Common::kPlatformDOS,
-	 ADGF_UNSTABLE,
-	 GUIO1(GUIO_NOMIDI)},
-	{"wetlands", // Wetlands (ES)
-	 "",
-	 AD_ENTRY2s("wetlands.exe", "8d0f3630523da827bb25e665b7d3f879", 644055,
+		Common::FR_FRA,
+		Common::kPlatformDOS,
+		ADGF_UNSTABLE,
+		GUIO1(GUIO_NOMIDI)
+	},
+	{
+		"wetlands", // Wetlands (ES)
+		0,
+		AD_ENTRY2s("wetlands.exe", "8d0f3630523da827bb25e665b7d3f879", 644055,
 				"missions.lib", "aeaaa8b26ab17e37f060334a311a3ff6", 309793),
-	 Common::ES_ESP,
-	 Common::kPlatformDOS,
-	 ADGF_UNSTABLE,
-	 GUIO1(GUIO_NOMIDI)},
-	{"soldierboyz", // Solidier Boyz (US)
-	 _s("Missing game code"),
-	 AD_ENTRY2s("boyz.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 263347,
-				"setup.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 160740),
-	 Common::EN_USA,
-	 Common::kPlatformWindows,
-	 ADGF_UNSUPPORTED,
-	 GUIO1(GUIO_NOMIDI)},
-	AD_TABLE_END_MARKER};
+		Common::ES_ESP,
+		Common::kPlatformDOS,
+		ADGF_UNSTABLE,
+		GUIO1(GUIO_NOMIDI)},
+	{
+		"soldierboyz", // Solidier Boyz (US)
+		_s("Missing game code"),
+		AD_ENTRY2s("boyz.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 263347,
+					"setup.exe", "bac1d734f2606dbdd0816dfa7a5cf518", 160740),
+		Common::EN_USA,
+		Common::kPlatformWindows,
+		ADGF_UNSUPPORTED,
+		GUIO1(GUIO_NOMIDI)
+	},
+	AD_TABLE_END_MARKER
+};
 } // End of namespace Hypno
 
 static const char *const directoryGlobs[] = {
@@ -153,8 +172,8 @@ public:
 	}
 
 	const char *getOriginalCopyright() const override {
-		return "Marvel Comics Spider-Man: The Sinister Six (C) Brooklyn Multimedia\n"
-			   "Wetlands (C) Hypnotix, Inc.";
+		return	"Marvel Comics Spider-Man: The Sinister Six (C) Brooklyn Multimedia\n"
+				"Wetlands (C) Hypnotix, Inc.";
 	}
 
 	const DebugChannelDef *getDebugChannels() const override {


Commit: 7b8ad76c20fc7ad0d733f6ed940aa27da19f1d31
    https://github.com/scummvm/scummvm/commit/7b8ad76c20fc7ad0d733f6ed940aa27da19f1d31
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2021-10-31T19:15:06+01:00

Commit Message:
HYPNO: added intro to wetlands full game

Changed paths:
    engines/hypno/wet/wet.cpp


diff --git a/engines/hypno/wet/wet.cpp b/engines/hypno/wet/wet.cpp
index dde883f365..2e6a77930a 100644
--- a/engines/hypno/wet/wet.cpp
+++ b/engines/hypno/wet/wet.cpp
@@ -233,19 +233,23 @@ void WetEngine::loadAssetsFullGame() {
 	if (missions == nullptr || missions->listMembers(files) == 0)
 		error("Failed to load any files from missions.lib");
 
-	Level intro;
-	intro.trans.level = "wetlands/main_menu.mis"; //"c11" + _difficulty + ".mi_";
-	intro.trans.intros.push_back("c_misc/logo.smk");
-	intro.trans.intros.push_back("c_misc/nw_logo.smk");
-	intro.trans.intros.push_back("c_misc/hypnotix.smk");
-	intro.trans.intros.push_back("c_misc/wetlogo.smk");
-	_levels["<start>"] = intro;
-
+	Level logos;
+	logos.trans.level = "wetlands/main_menu.mis"; //"c11" + _difficulty + ".mi_";
+	logos.trans.intros.push_back("c_misc/logo.smk");
+	logos.trans.intros.push_back("c_misc/nw_logo.smk");
+	logos.trans.intros.push_back("c_misc/hypnotix.smk");
+	logos.trans.intros.push_back("c_misc/wetlogo.smk");
+	_levels["<start>"] = logos;
 
 	Level menu;
 	menu.code.name = "wetlands/main_menu.mis";
 	_levels["wetlands/main_menu.mis"] = menu;
-	_levels["wetlands/main_menu.mis"].code.levelIfWin = "c11" + _difficulty + ".mi_";
+	_levels["wetlands/main_menu.mis"].code.levelIfWin = "<intro>";
+
+	Level intro;
+	intro.trans.level = "c11" + _difficulty + ".mi_";
+	intro.trans.intros.push_back("c_misc/intros.smk");
+	_levels["<intro>"] = intro;
 
 	//loadLevel("c10", "c11", "");
 	loadLevel("c11", "c20", "");
@@ -274,8 +278,8 @@ void WetEngine::runMainMenu(Code code) {
 	uint32 c = _pixelFormat.RGBToColor(0, 252, 0);
 	Graphics::Surface *frame = decodeFrame("c_misc/menus.smk", 16, true);
 	Common::String _name = "";
-	//Graphics::Surface *sframe = frame->scale(_screenW, _screenH);
 	drawImage(*frame, 0, 0, false);
+	_font->drawString(_compositeSurface, "ENTER NAME :", 48, 50, 100, c);
 	while (!shouldQuit()) {
 
 		while (g_system->getEventManager()->pollEvent(event)) {




More information about the Scummvm-git-logs mailing list