[Scummvm-git-logs] scummvm master -> 6b6670caf9812a980a9aa4049bf6931aa943b79b

dreammaster paulfgilbert at gmail.com
Sun May 12 02:26:10 CEST 2019


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

Summary:
4113183f5b GLK: HUGO: Added heset
98f6315366 GLK: HUGO: Removed unneeded method stubs
6b6670caf9 GLK: HUGO: Added hemedia & heres


Commit: 4113183f5b3cc707c54b5723413c7e69b0f8f37c
    https://github.com/scummvm/scummvm/commit/4113183f5b3cc707c54b5723413c7e69b0f8f37c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-05-12T10:19:47+10:00

Commit Message:
GLK: HUGO: Added heset

Changed paths:
  A engines/glk/hugo/heset.cpp
    engines/glk/hugo/hugo.h
    engines/glk/module.mk


diff --git a/engines/glk/hugo/heset.cpp b/engines/glk/hugo/heset.cpp
new file mode 100644
index 0000000..b7e40e0
--- /dev/null
+++ b/engines/glk/hugo/heset.cpp
@@ -0,0 +1,583 @@
+/* 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 "glk/hugo/hugo.h"
+
+namespace Glk {
+namespace Hugo {
+
+void Hugo::RunSet(int gotvalue) {
+	char inc = 0;                   /* increment/decrement */
+	char temparrexpr, propval = 0;
+	int a = 0, t = 0, obj = 0;
+	int newl = 0;                   /* new length */
+	int newp = 0;			/* new property val */
+	unsigned int element = 0;		/* of an array */
+
+	unsigned short n, m, v;		/* must be 16 bits */
+
+	inobj = 0;
+
+	if (gotvalue!=-1)
+	{
+		obj = gotvalue;
+		t = SetCompound(t);
+		goto StoreVal;
+	}
+
+	t = MEM(codeptr);
+
+	switch (t)
+	{
+		case OBJECTNUM_T:
+		{
+			codeptr++;
+			obj = PeekWord(codeptr);
+			codeptr += 2;
+			t = SetCompound(t);
+			break;
+		}
+
+		case VAR_T:
+		{
+			a = MEM(codeptr + 1);
+
+			/* Check for ++, --, +=, etc. */
+			inc = IsIncrement(codeptr+2);
+
+			if (MEM(codeptr + 2)==EQUALS_T || inc)
+			{
+				if (a < MAXGLOBALS) SaveUndo(VAR_T, a, var[a], 0, 0);
+
+				/* anonymous function */
+				if (!inc && MEM(codeptr+3)==EOL_T)
+				{
+					var[a] = GetAnonymousFunction(codeptr+4);
+					return;
+				}
+
+				if (inc)
+				{
+					var[a] = (Increment(var[a], inc)) + incdec;
+
+					/* backward-compatibility tweak */
+					if ((game_version<23) && MEM(codeptr)!=CLOSE_BRACE_T) codeptr--;
+
+					codeptr++;      /* eol */
+				}
+				else
+				{
+					codeptr += 3;
+					inexpr = 1;
+					SetupExpr();
+					inexpr = 0;
+					v = EvalExpr(0);
+					var[a] = v;
+				}
+
+				/* If a global variable */
+				if (a < MAXGLOBALS)
+				{
+					if (a==wordcount) words = var[wordcount];
+				}
+
+				return;
+			}
+
+			obj = var[a];
+			codeptr += 2;
+			t = SetCompound(t);
+
+			break;
+		}
+
+		case WORD_T:			/* "word" */
+		{
+			codeptr += 2;           /* skip "[" */
+			n = GetValue();
+#if defined (DEBUGGER)
+			if ((debug_eval) && debug_eval_error)
+				return;
+#endif
+			codeptr += 2;           /* skip "] =" */
+			inexpr = 1;
+			SetupExpr();
+			inexpr = 0;
+
+GetNextWord:
+			if (n >= MAXWORDS) n = MAXWORDS-1;
+			SaveUndo(WORD_T, n, wd[n], 0, 0);
+			wd[n] = EvalExpr(0);
+
+			if (MEM(codeptr)==COMMA_T)
+			{
+				codeptr++;
+				n++;
+				goto GetNextWord;
+			}
+
+			/* Have to (rather unfortunately) rebuild the entire
+			   input buffer and word array here
+			*/
+			strcpy(buffer, "");
+			t = 0;
+			for (a=1; a<=(int)MAXWORDS; a++)
+			{
+				if ((unsigned short)wd[a]!=UNKNOWN_WORD)
+					strcpy(buffer+t, GetWord(wd[a]));
+				else
+					itoa(parsed_number, buffer+t, 10);
+			        word[a] = buffer + t;
+				t+=strlen(word[a])+1;
+			}
+
+			if (n>(unsigned)var[wordcount])
+				var[wordcount] = n;
+
+			return;
+		}
+
+		case ARRAYDATA_T:
+		case ARRAY_T:
+		{
+			char af_flag = false;
+			/* array[n]... */
+			if (t==ARRAYDATA_T)
+			{
+				m = PeekWord(codeptr + 1);
+				codeptr += 4;   /* "[" */
+				n = GetValue();
+#if defined (DEBUGGER)
+				if ((debug_eval) && debug_eval_error)
+					return;
+#endif
+				codeptr++;      /* "]" */
+			}
+
+			/* ...or array val[n] */
+			else
+			{
+				codeptr++;
+				m = GetValue();
+#if defined (DEBUGGER)
+				if ((debug_eval) && debug_eval_error)
+					return;
+#endif
+				codeptr++;      /* "[" */
+				n = GetValue();
+#if defined (DEBUGGER)
+				if ((debug_eval) && debug_eval_error)
+					return;
+#endif
+				codeptr++;      /* "]" */
+			}
+
+			if (game_version>=22)
+			{
+				/* Convert to word value */
+				m*=2;
+
+				if (game_version>=23)
+					/* Space for array length */
+					a = 2;
+			}
+
+#if defined (DEBUGGER)
+			CheckinRange(m+a+n*2, debug_workspace, "array data");
+#endif
+			/* Check for ++, --, +=, etc. */
+			inc = IsIncrement(codeptr);
+			if (inc)
+			{
+				defseg = arraytable;
+				v = PeekWord(m+a+n*2);
+				defseg = gameseg;
+				v = (Increment(v, inc)) + incdec;
+
+				codeptr++;      /* eol */
+
+				element = m+a+n*2;
+
+				goto WriteArrayValue;
+			}
+
+			if (MEM(codeptr)==EQUALS_T)
+			{
+				codeptr++;
+
+				do
+				{
+					element = m+a+n*2;
+
+					temparrexpr = arrexpr;
+					arrexpr = true;
+
+					/* anonymous function */
+					if (!inc && MEM(codeptr)==EOL_T)
+					{
+						v = GetAnonymousFunction(codeptr+1);
+						af_flag = true;
+					}
+					else
+					{
+						v = GetValue();
+					}
+#if defined (DEBUGGER)
+					if ((debug_eval) && debug_eval_error)
+						return;
+#endif
+					if (arrexpr==false && MEM(codeptr-1)==76)
+						codeptr--;
+					arrexpr = temparrexpr;
+
+					if (!af_flag && (MEM(codeptr)==COMMA_T || MEM(codeptr)==CLOSE_BRACKET_T))
+						codeptr++;
+WriteArrayValue:
+					defseg = arraytable;
+
+					/* Make sure the value to be written is within range */
+					if ((element>0) && (element < (unsigned)(dicttable-arraytable)*16))
+					{
+						SaveUndo(ARRAYDATA_T, m+a, n, PeekWord(element), 0);
+
+						PokeWord(element, (unsigned int)v);
+					}
+
+					defseg = gameseg;
+
+					if (inc || af_flag) return;
+
+					n++;
+				}
+				while (MEM(codeptr)!=EOL_T);
+
+				codeptr++;
+				return;
+			}
+
+			defseg = arraytable;
+			obj = PeekWord((unsigned int)(m+a + n*2));
+			defseg = gameseg;
+			t = SetCompound(t);
+
+			break;
+		}
+	}
+
+
+StoreVal:
+
+	/* Now store the evaluated expression in the appropriate place... */
+
+	/*
+		t = 1:  property
+		t = 2:  attribute
+		t = 3:  not attribute
+		t = 4:  property reference
+	*/
+
+	n = 1;
+
+	if (t==4)
+	{
+		inobj = true;
+		n = GetValue();
+
+#if defined (DEBUGGER)
+		if ((debug_eval) && debug_eval_error)
+			return;
+#endif
+		inobj = false;
+
+LoopBack:
+		if (MEM(codeptr)==IS_T || MEM(codeptr)==DECIMAL_T)
+		{
+			obj = GetProp(obj, set_value, n, 0);
+			t = SetCompound(t);
+			goto LoopBack;
+		}
+		/* Don't set t = 1 if it changed above before going back
+		   to LoopBack:
+		*/
+		else if (t==4)
+			t = 1;          /* Just a property */
+	}
+	else if (t==1)
+	{
+		while (MEM(codeptr)==IS_T || MEM(codeptr)==DECIMAL_T)
+		{
+			obj = GetProp(obj, set_value, n, 0);
+			t = SetCompound(t);
+		}
+	}
+
+	switch (t)
+	{
+		case 1:
+		{
+			incdec = 0;
+
+			if (MEM(codeptr) != EQUALS_T)
+			{
+				/* Check for ++, --, +=, etc. */
+				if (!(inc = IsIncrement(codeptr)))
+				{
+#if defined (DEBUGGER)
+					if (debug_eval)
+					{
+						debug_eval_error = true;
+						return;
+					}
+#endif
+					FatalError(ILLEGAL_OP_E);
+				}
+				else if (MEM(codeptr)==EOL_T)
+				{
+					goto GetNextPropVal;
+				}
+			}
+			else
+				codeptr++;
+
+			/* Property routine (anonymous function)... */
+			if (MEM(codeptr)==EOL_T)
+			{
+				/* m = skipptr to the end of the property
+				   routine block (i.e., the next statement
+				   following it)
+				*/
+				m = PeekWord(codeptr + 1);
+
+				newl = PROP_ROUTINE;
+				newp =(unsigned int)(((codeptr + 4)+(codeptr + 4)%address_scale)/address_scale);
+				codeptr = (long)m*address_scale;
+				m = PropAddr(obj, set_value, 0);
+			}
+
+			/* ...or not */
+			else
+			{
+GetNextPropVal:
+				inexpr = false;
+				temparrexpr = multiprop;
+				multiprop = true;
+				propval = true;
+				if (!inc) newp = GetValue();
+#if defined (DEBUGGER)
+				if ((debug_eval) && debug_eval_error)
+					return;
+#endif
+
+				if (!multiprop)
+					codeptr--;
+				multiprop = temparrexpr;
+
+				m = PropAddr(obj, set_value, 0);
+				if (m)
+				{
+					defseg = proptable;
+					newl = Peek((unsigned int)m + 1);
+					if (newl==PROP_ROUTINE) newl = 1;
+				}
+
+				/* Deal with setting built-in display object
+				   properties
+				*/
+				else if ((obj==display_object) && n==1)
+				{
+					if (set_value==title_caption)
+					{
+						strncpy(game_title, GetWord(newp), MAX_GAME_TITLE);
+						hugo_setgametitle(game_title);
+					}
+					else if (set_value==needs_repaint)
+					{
+						display_needs_repaint = (char)newp;
+					}
+				}
+#if defined (DEBUGGER)
+/*
+				else if (runtime_warnings)
+				{
+					RuntimeWarning("Setting non-existent property");
+				}
+*/
+#endif
+			}
+
+			/* Write property obj.z = newl words of newp */
+
+			if (m && (int)n <= 0)
+			{
+#if defined (DEBUGGER)
+				RuntimeWarning("Property element <= 0");
+#endif
+				if (inc) codeptr++;
+			}
+			else if (m && (int)n <= newl)
+			{
+				defseg = proptable;
+
+#if defined (DEBUGGER)
+				CheckinRange((unsigned)n, (unsigned)Peek(m+1), "property element");
+#endif
+				/* Check to make sure this property value is within range */
+				if ((unsigned)(m+2+(n-1)*2)<(unsigned)(eventtable-proptable)*16)
+				{
+					SaveUndo(PROP_T, obj, (unsigned int)set_value, n, PeekWord((unsigned int)(m+2+(n-1)*2)));
+
+					/* Save the (possibly changed) length) */
+					Poke((unsigned int)m + 1, (unsigned char)newl);
+
+					/* An assignment such as obj.prop++ or
+					   obj.prop += ...
+					*/
+					if (inc)
+					{
+						PokeWord((unsigned int)(m+2+(n-1)*2), Increment(PeekWord((unsigned int)(m+2+(n-1)*2)), inc) + incdec);
+						codeptr++;      /* eol */
+					}
+
+					/* A regular obj.prop = ... assignment */
+					else
+						PokeWord((unsigned int)(m+2+(n-1)*2), newp);
+				}
+			}
+			else if (inc) codeptr++;	/* eol */
+
+			defseg = gameseg;
+
+			if (inc) return;
+
+			if (propval && MEM(codeptr)==COMMA_T)
+				{n++;
+				codeptr++;
+				goto GetNextPropVal;}
+
+			if (propval) codeptr++;
+			if (MEM(codeptr)==EOL_T) codeptr++;
+			return;
+		}
+
+		case 2:
+		case 3:
+		{
+ModifyAttribute:
+
+#if defined (DEBUGGER)
+			CheckinRange((unsigned int)set_value, (unsigned)attributes, "attribute");
+#endif
+			SaveUndo(ATTR_T, obj, (unsigned int)set_value, TestAttribute(obj, (unsigned int)set_value, 0), 0);
+
+			SetAttribute(obj, set_value, (t==2));
+			t = 2;	/* reset after 'not' */
+
+			if (MEM(codeptr++)==EOL_T) return;
+
+			/* Allow multiple attributes, comma-separated */
+			if (MEM(codeptr)==COMMA_T)
+				codeptr++;
+
+			if (MEM(codeptr)==NOT_T)
+			{
+				t = 3;
+				codeptr++;
+			}
+
+			set_value = GetValue();
+			goto ModifyAttribute;
+		}
+
+		default:
+		{
+#if defined (DEBUGGER)
+			if (debug_eval)
+			{
+				debug_eval_error = true;
+				return;
+			}
+#endif
+			/* Not any sort of variable data type */
+			FatalError(ILLEGAL_OP_E);
+		}
+	}
+}
+
+unsigned int Hugo::GetAnonymousFunction(long addr) {
+	long skipaddr;
+	unsigned int af_addr;
+	
+	skipaddr = PeekWord(addr);
+	/* The address of the anonymous function is the next address boundary,
+	   calculated as:
+	   (((addr+2)/address_scale+1)*address_scale)/address_scale */
+	af_addr =(unsigned int)((addr+2)/address_scale+1);
+	codeptr = (long)skipaddr*address_scale;
+	return af_addr;
+}
+
+int Hugo::SetCompound(int t) {
+	if (Peek(codeptr)==DECIMAL_T)		/* obj.property */
+	{
+		codeptr++;
+		inobj = 1;
+		set_value = GetValue();		/* the prop. # */
+		inobj = 0;
+
+		if (Peek(codeptr)==POUND_T)	/* if obj.prop #... */
+		{
+			codeptr++;
+			return 4;
+		}
+		return 1;
+	}
+
+	if (Peek(codeptr)==IS_T)		/* obj is ... */
+	{
+		inobj = 1;
+		if (Peek(codeptr+1)==NOT_T)
+		{
+			codeptr += 2;
+                        set_value = GetValue();	/* the attr. # */
+			inobj = 0;
+			return 3;
+		}
+
+		codeptr++;
+		set_value = GetValue();		/* the attr. # */
+		inobj = 0;
+		return 2;
+	}
+
+#if defined (DEBUGGER)
+	if (debug_eval)
+		debug_eval_error = true;
+	else
+#endif
+
+	FatalError(ILLEGAL_OP_E);
+
+	return 0;
+}
+
+} // End of namespace Hugo
+} // End of namespace Glk
diff --git a/engines/glk/hugo/hugo.h b/engines/glk/hugo/hugo.h
index 98fbf90..046b665 100644
--- a/engines/glk/hugo/hugo.h
+++ b/engines/glk/hugo/hugo.h
@@ -916,6 +916,23 @@ private:
 	/**@}*/
 
 	/**
+	 * \defgroup heglk
+	 * @{
+	 */
+
+	/**
+	 * If gotvalue is passed as -1, then no value has already been as the (potential) object, etc.
+	 * comprising the first part of the object.property, for example, to be set.
+	 */
+	void RunSet(int gotvalue);
+
+	unsigned int GetAnonymousFunction(long addr);
+
+	int SetCompound(int t);
+
+	 /**@}*/
+
+	/**
 	* \defgroup Miscellaneous
 	* @{
 	*/
@@ -1066,8 +1083,6 @@ private:
 	void SetupWatchEval(int num) {}
 
 	bool EvalWatch() { return false; }
-
-	void RunSet(int v) {}
 #endif
 public:
 	/**
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 00641dd..fcb4714 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -78,6 +78,7 @@ MODULE_OBJS := \
 	hugo/heobject.o \
 	hugo/heparse.o \
 	hugo/herun.o \
+	hugo/heset.o \
 	hugo/htokens.o \
 	hugo/hugo.o \
 	hugo/stringfn.o \


Commit: 98f6315366eafc0568d46ee4d9cba8d0d6495950
    https://github.com/scummvm/scummvm/commit/98f6315366eafc0568d46ee4d9cba8d0d6495950
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-05-12T10:19:47+10:00

Commit Message:
GLK: HUGO: Removed unneeded method stubs

Changed paths:
    engines/glk/hugo/hemisc.cpp
    engines/glk/hugo/hugo.h


diff --git a/engines/glk/hugo/hemisc.cpp b/engines/glk/hugo/hemisc.cpp
index c380fbb..4115abe 100644
--- a/engines/glk/hugo/hemisc.cpp
+++ b/engines/glk/hugo/hemisc.cpp
@@ -1544,7 +1544,7 @@ void Hugo::Printout(char *a, int no_scrollback_linebreak) {
 		}
 
 		if (script && (unsigned char)b[0]>=' ')
-			if (hugo_writetoscript(b) < 0) FatalError(WRITE_E);
+			if (hugo_fprintf(script, "%s", b) < 0) FatalError(WRITE_E);
 
 #if defined (SCROLLBACK_DEFINED)
 		if (!inwindow && (unsigned char)b[0]>=' ')
@@ -1655,7 +1655,8 @@ void Hugo::Printout(char *a, int no_scrollback_linebreak) {
 
 		if (script && !no_scrollback_linebreak)
 		{
-			if (hugo_writetoscript("\n")<0) FatalError(WRITE_E);
+			if (hugo_fprintf(script, "%s", "\n")<0)
+				FatalError(WRITE_E);
 		}
 
 #if defined (SCROLLBACK_DEFINED)
diff --git a/engines/glk/hugo/hugo.h b/engines/glk/hugo/hugo.h
index 046b665..eeb65a2 100644
--- a/engines/glk/hugo/hugo.h
+++ b/engines/glk/hugo/hugo.h
@@ -333,6 +333,10 @@ private:
 		// No implementation
 	}
 
+	void hugo_closefiles() {
+		// Glk closes all files on exit
+	}
+
 	int hugo_getkey() const {
 		// Not needed here--single-character events are handled solely by hugo_waitforkey(), below
 		return 0;
@@ -1111,12 +1115,9 @@ public:
 	virtual Common::Error saveGameData(strid_t file, const Common::String &desc) override;
 
 	// TODO: Stubs to be Properly implemented
-	void hugo_closefiles() {}
-	unsigned int FindWord(const char *a) { return 0; }
 	void hugo_stopsample() {}
 	void hugo_stopmusic() {}
 	int hugo_hasgraphics() { return 0; }
-	int hugo_writetoscript(const char *s) { return 0; }
 	void DisplayPicture() {}
 	void PlayMusic() {}
 	void PlaySample() {}


Commit: 6b6670caf9812a980a9aa4049bf6931aa943b79b
    https://github.com/scummvm/scummvm/commit/6b6670caf9812a980a9aa4049bf6931aa943b79b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2019-05-12T10:19:48+10:00

Commit Message:
GLK: HUGO: Added hemedia & heres

Changed paths:
  A engines/glk/hugo/hemedia.cpp
  A engines/glk/hugo/heres.cpp
    engines/glk/hugo/heparse.cpp
    engines/glk/hugo/hugo.cpp
    engines/glk/hugo/hugo.h
    engines/glk/hugo/hugo_defines.h
    engines/glk/hugo/hugo_types.h
    engines/glk/module.mk


diff --git a/engines/glk/hugo/hemedia.cpp b/engines/glk/hugo/hemedia.cpp
new file mode 100644
index 0000000..19c9874
--- /dev/null
+++ b/engines/glk/hugo/hemedia.cpp
@@ -0,0 +1,204 @@
+/* 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 "glk/hugo/hugo.h"
+
+namespace Glk {
+namespace Hugo {
+
+int Hugo::loadres(HUGO_FILE infile, int reslen, int type) {
+	char buf[4096];
+	frefid_t fileref;
+	strid_t stream;
+	long offset;
+	int idVal;
+	int i, n;
+
+	offset = hugo_ftell(infile);
+	for (i = 0; i < numres[type]; i++)
+		if (resids[type][i] == offset)
+			return i;
+
+	/* Too many resources loaded... */
+	if (numres[type] + 1 == MAXRES)
+		return -1;
+
+	idVal = numres[type]++;
+	sprintf(buf, "%s%d", type == PIC ? "PIC" : "SND", idVal);
+	resids[type][idVal] = offset;
+
+	fileref = glk_fileref_create_by_name(fileusage_Data, buf, 0);
+	if (!fileref)
+	{
+		return -1;
+	}
+
+	stream = glk_stream_open_file(fileref, filemode_Write, 0);
+	if (!stream)
+	{
+		glk_fileref_destroy(fileref);
+		return -1;
+	}
+
+	glk_fileref_destroy(fileref);
+
+	while (reslen > 0)
+	{
+		n = hugo_fread(buf, 1, reslen < sizeof buf ? reslen : sizeof buf, infile);
+		if (n <= 0)
+			break;
+		glk_put_buffer_stream(stream, buf, n);
+		reslen -= n;
+	}
+
+	glk_stream_close(stream, NULL);
+
+	return idVal;
+}
+
+int Hugo::hugo_hasgraphics() {
+	/* Returns true if the current display is capable of graphics display */
+	return glk_gestalt(gestalt_Graphics, 0)
+		&& glk_gestalt(gestalt_DrawImage, glk_window_get_type(mainwin));
+}
+
+int Hugo::hugo_displaypicture(HUGO_FILE infile, long reslen) {
+	int idVal;
+
+	/* Ignore the call if the current window is set elsewhere. */
+	if (currentwin != NULL && currentwin != mainwin)
+	{
+		hugo_fclose(infile);
+		return false;
+	}
+
+	idVal = loadres(infile, reslen, PIC);
+	if (idVal < 0)
+	{
+		hugo_fclose(infile);
+		return false;
+	}
+
+#if 0
+	/* Get picture width and height for scaling. */
+	glui32 width, height;
+	if (glk_image_get_info(idVal, &width, &height))
+	{
+		/* Scale large images. */
+		if (width > PIC_MAX_WIDTH)
+		{
+			height = height * PIC_MAX_WIDTH / width;
+			width = PIC_MAX_WIDTH;
+		}
+		if (height > PIC_MAX_HEIGHT)
+		{
+			width = width * PIC_MAX_HEIGHT / height;
+			height = PIC_MAX_HEIGHT;
+		}
+	}
+#endif
+
+	hugo_fclose(infile);
+
+	/* Draw, then move cursor down to the next line. */
+	glk_image_draw(mainwin, idVal, imagealign_InlineUp, 0);
+	glk_put_char('\n');
+
+	return true;
+}
+
+void Hugo::initsound() {
+	if (!glk_gestalt(gestalt_Sound, 0))
+		return;
+	schannel = glk_schannel_create(0);
+}
+
+void Hugo::initmusic() {
+	if (!glk_gestalt(gestalt_Sound, 0) || !glk_gestalt(gestalt_SoundMusic, 0))
+		return;
+	mchannel = glk_schannel_create(0);
+}
+
+int Hugo::hugo_playmusic(HUGO_FILE infile, long reslen, char loop_flag) {
+	int idVal;
+
+	if (!mchannel)
+		initmusic();
+	if (mchannel)
+	{
+		idVal = loadres(infile, reslen, SND);
+		if (idVal < 0)
+		{
+			hugo_fclose(infile);
+			return false;
+		}
+		glk_schannel_play_ext(mchannel, idVal, loop_flag ? -1 : 1, 0);
+	}
+
+	hugo_fclose(infile);
+	return true;
+}
+
+void Hugo::hugo_musicvolume(int vol) {
+	if (!mchannel) initmusic();
+	if (!mchannel) return;
+	glk_schannel_set_volume(mchannel, (vol * 0x10000) / 100);
+}
+
+void Hugo::hugo_stopmusic() {
+	if (!mchannel) initmusic();
+	if (!mchannel) return;
+	glk_schannel_stop(mchannel);
+}
+
+int Hugo::hugo_playsample(HUGO_FILE infile, long reslen, char loop_flag) {
+	int idVal;
+
+	if (schannel)
+	{
+		idVal = loadres(infile, reslen, SND);
+		if (idVal < 0)
+		{
+			hugo_fclose(infile);
+			return false;
+		}
+		glk_schannel_play_ext(schannel, idVal, loop_flag ? -1 : 1, 0);
+	}
+
+	hugo_fclose(infile);
+	return true;
+}
+
+void Hugo::hugo_samplevolume(int vol) {
+	if (!schannel) initsound();
+	if (!schannel) return;
+	glk_schannel_set_volume(schannel, (vol * 0x10000) / 100);
+}
+
+void Hugo::hugo_stopsample() {
+	if (!schannel) initsound();
+	if (!schannel) return;
+	glk_schannel_stop(schannel);
+}
+
+} // End of namespace Hugo
+} // End of namespace Glk
diff --git a/engines/glk/hugo/heparse.cpp b/engines/glk/hugo/heparse.cpp
index 0369385..da01810 100644
--- a/engines/glk/hugo/heparse.cpp
+++ b/engines/glk/hugo/heparse.cpp
@@ -2104,8 +2104,8 @@ NextSyn:
 		{
 			if (strcmp(word[i+1], "~and"))
 			{
-				static char *END = "~and";
-				word[i] = END;
+				static char AND[5] = "~and";
+				word[i] = AND;
 				wd[i] = FindWord("~and");
 			}
 			else
diff --git a/engines/glk/hugo/heres.cpp b/engines/glk/hugo/heres.cpp
new file mode 100644
index 0000000..606f712
--- /dev/null
+++ b/engines/glk/hugo/heres.cpp
@@ -0,0 +1,472 @@
+/* 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 "glk/hugo/hugo.h"
+
+namespace Glk {
+namespace Hugo {
+
+void Hugo::DisplayPicture() {
+	char filename[MAX_RES_PATH], resname[MAX_RES_PATH];
+	long reslength;
+
+	GetResourceParameters(filename, resname, PICTURE_T);
+	
+	if (!hugo_hasgraphics())
+	{
+		var[system_status] = STAT_UNAVAILABLE;
+		return;
+	}
+
+	/* If filename is empty, no resource file was specified and
+	   the line[] array simply holds the path of the file to be loaded
+	   as a resource
+	*/
+	if (!(reslength = FindResource(filename, resname)))
+		return;
+
+	/* Find out what type of image resource this is */
+	resource_type = (char)((hugo_fgetc(resource_file)==0xff) ? JPEG_R : UNKNOWN_R);
+	hugo_fseek(resource_file, -1, SEEK_CUR);
+
+	/* If FindResource() is successful, the resource file is already
+	   open and positioned; hugo_displaypicture() is responsible for
+	   closing resource_file before returning regardless of success
+	   or failure
+	*/
+	if (!hugo_displaypicture(resource_file, reslength))
+		var[system_status] = STAT_LOADERROR;
+}
+
+void Hugo::PlayMusic() {
+	char filename[MAX_RES_PATH], resname[MAX_RES_PATH];
+	char loop_flag = 0;
+	long resstart, reslength;
+
+	if (MEM(codeptr+1)==REPEAT_T) loop_flag = true, codeptr++;
+
+	hugo_stopmusic();
+
+	/* If a 0 parameter is passed, i.e. "music 0" */
+	if (!GetResourceParameters(filename, resname, MUSIC_T))
+	{
+		return;
+	}
+
+	if (extra_param>=0)
+	{
+		if (extra_param > 100) extra_param = 100;
+		hugo_musicvolume(extra_param);
+	}
+
+	if (!(reslength = FindResource(filename, resname)))
+		return;
+
+	/* Find out what type of music resource this is */
+	resstart = hugo_ftell(resource_file);
+
+	/* Check for MIDI */
+	hugo_fseek(resource_file, resstart, SEEK_SET);
+	hugo_fread(resname, 4, 1, resource_file);
+	if (!memcmp(resname, "MThd", 4))
+	{
+		resource_type = MIDI_R;
+		goto Identified;
+	}
+
+	/* Check for XM */
+	hugo_fseek(resource_file, resstart, SEEK_SET);
+	hugo_fread(resname, 17, 1, resource_file);
+	if (!memcmp(resname, "Extended Module: ", 17))
+	{
+		resource_type = XM_R;
+		goto Identified;
+	}
+
+	/* Check for S3M */
+	hugo_fseek(resource_file, resstart+0x2c, SEEK_SET);
+	hugo_fread(resname, 4, 1, resource_file);
+	if (!memcmp(resname, "SCRM", 4))
+	{
+		resource_type = S3M_R;
+		goto Identified;
+	}
+
+	/* Check for MOD */
+	hugo_fseek(resource_file, resstart+1080, SEEK_SET);
+	hugo_fread(resname, 4, 1, resource_file);
+	resname[4] = '\0';
+	/* There are a whole bunch of different MOD identifiers: */
+	if (!strcmp(resname+1, "CHN") ||	/* 4CHN, 6CHN, 8CHN */
+	    !strcmp(resname+2, "CN") ||		/* 16CN, 32CN */
+	    !strcmp(resname, "M.K.") || !strcmp(resname, "M!K!") ||
+	    !strcmp(resname, "FLT4") || !strcmp(resname, "CD81") ||
+	    !strcmp(resname, "OKTA") || !strcmp(resname, "    "))
+	{
+		resource_type = MOD_R;
+		goto Identified;
+	}
+
+	/* Check for MP3 */
+/* Assume for now that otherwise unidentified is MP3 */
+	else
+	{
+		resource_type = MP3_R;
+		goto Identified;
+	}
+
+	/* No file type identified */
+	resource_type = UNKNOWN_R;
+
+Identified:
+	hugo_fseek(resource_file, resstart, SEEK_SET);
+
+	if (!hugo_playmusic(resource_file, reslength, loop_flag))
+		var[system_status] = STAT_LOADERROR;
+}
+
+void Hugo::PlaySample() {
+	char filename[MAX_RES_PATH], resname[MAX_RES_PATH];
+	char loop_flag = 0;
+	long reslength;
+
+	if (MEM(codeptr+1)==REPEAT_T) loop_flag = true, codeptr++;
+
+	hugo_stopsample();
+
+	/* If a 0 parameter is passed, i.e. "sound 0" */
+	if (!GetResourceParameters(filename, resname, SOUND_T))
+	{
+		return;
+	}
+
+	if (extra_param>=0)
+	{
+		if (extra_param > 100) extra_param = 100;
+		hugo_samplevolume(extra_param);
+	}
+
+	if (!(reslength = FindResource(filename, resname)))
+		return;
+
+	/* Find out what kind of audio sample this is */
+	hugo_fread(resname, 4, 1, resource_file);
+	if (!memcmp(resname, "WAVE", 4))
+		resource_type = WAVE_R;
+	else
+		resource_type = UNKNOWN_R;
+
+	hugo_fseek(resource_file, -4, SEEK_CUR);
+
+	if (!hugo_playsample(resource_file, reslength, loop_flag))
+		var[system_status] = STAT_LOADERROR;
+}
+
+void Hugo::PlayVideo() {
+	char filename[MAX_RES_PATH], resname[MAX_RES_PATH];
+	char loop_flag = 0, background = 0;
+	int volume = 100;
+	long resstart, reslength;
+
+#if defined (COMPILE_V25)
+	var[system_status] = STAT_UNAVAILABLE;
+#endif
+	if (MEM(codeptr+1)==REPEAT_T) loop_flag = true, codeptr++;
+
+#if !defined (COMPILE_V25)
+	hugo_stopvideo();
+#endif
+
+	/* If a 0 parameter is passed, i.e. "video 0" */
+	if (!GetResourceParameters(filename, resname, VIDEO_T))
+	{
+		return;
+	}
+
+	if (MEM(codeptr-1)==COMMA_T)
+	{
+		background = (char)GetValue();
+		codeptr++;	/* eol */
+	}
+
+	if (extra_param>=0)
+	{
+		if (extra_param > 100) extra_param = 100;
+		volume = extra_param;
+	}
+
+	if (!(reslength = FindResource(filename, resname)))
+		return;
+
+	/* Find out what type of video resource this is */
+	resstart = hugo_ftell(resource_file);
+
+	/* Check for MPEG */
+	hugo_fseek(resource_file, resstart, SEEK_SET);
+	hugo_fread(resname, 4, 1, resource_file);
+	if (resname[2]==0x01 && (unsigned char)resname[3]==0xba)
+	{
+		resource_type = MPEG_R;
+		goto Identified;
+	}
+
+	/* Check for AVI */
+	hugo_fseek(resource_file, resstart+8, SEEK_SET);
+	hugo_fread(resname, 4, 1, resource_file);
+	if (!memcmp(resname, "AVI ", 4))
+	{
+		resource_type = AVI_R;
+		goto Identified;
+	}
+
+	/* No file type identified */
+	resource_type = UNKNOWN_R;
+
+Identified:
+	hugo_fseek(resource_file, resstart, SEEK_SET);
+
+#if !defined (COMPILE_V25)
+	if (!hugo_playvideo(resource_file, reslength, loop_flag, background, volume))
+		var[system_status] = STAT_LOADERROR;
+#else
+	fclose(resource_file);
+	resource_file = nullptr;
+#endif
+}
+
+long Hugo::FindResource(char *filename, char *resname) {
+	char resource_in_file[MAX_RES_PATH];
+	int i, len;
+	int rescount;
+	unsigned int startofdata;
+	long resposition, reslength;
+#if defined (GLK)
+	frefid_t fref;
+#endif
+/* Previously, resource positions were written as 24 bits, which meant that
+   a given resource couldn't start after 16,777,216 bytes or be more than
+   that length.  The new resource file format (designated by 'r') corrects this. */
+	int res_32bits = true;
+
+	resource_file = nullptr;
+
+	strcpy(loaded_filename, filename);
+	strcpy(loaded_resname, resname);
+	if (!strcmp(filename, "")) strcpy(loaded_filename, resname);
+
+	/* See if the file is supposed to be in a resourcefile to
+	   begin with
+	*/
+	if (!strcmp(filename, ""))
+		goto NotinResourceFile;
+
+
+	/* Open the resourcefile */
+	strupr(filename);
+
+#if !defined (GLK)
+	/* stdio implementation */
+	if (!(resource_file = TrytoOpen(filename, "rb", "games")))
+		if (!(resource_file = TrytoOpen(filename, "rb", "object")))
+		{
+			var[system_status] = STAT_NOFILE;
+			return 0;
+		}
+#else
+	/* Glk implementation */
+	fref = glk_fileref_create_by_name(fileusage_Data | fileusage_BinaryMode,
+		filename, 0);
+	if (glk_fileref_does_file_exist(fref))
+		resource_file = glk_stream_open_file(fref, filemode_Read, 0);
+	else
+		resource_file = nullptr;
+	glk_fileref_destroy(fref);
+	if (!resource_file)
+	{
+		var[system_status] = STAT_NOFILE;
+		return 0;
+	}
+#endif
+
+	/* Read the resourcefile header */
+	/* if (fgetc(resource_file)!='R') goto ResfileError; */
+	i = hugo_fgetc(resource_file);
+	if (i=='r')
+		res_32bits = true;
+	else if (i=='R')
+		res_32bits = false;
+	else
+		goto ResfileError;
+	/* Read and ignore the resource file version. */
+	hugo_fgetc(resource_file);
+	rescount = hugo_fgetc(resource_file);
+	rescount += hugo_fgetc(resource_file)*256;
+	startofdata = hugo_fgetc(resource_file);
+	startofdata += (unsigned int)hugo_fgetc(resource_file)*256;
+	if (hugo_ferror(resource_file))
+		goto ResfileError;
+
+
+	/* Now skim through the list of resources in the resourcefile to
+	   see if we have a match
+	*/
+	for (i=1; i<=rescount; i++)
+	{
+		len = hugo_fgetc(resource_file);
+		if (hugo_ferror(resource_file))
+			goto ResfileError;
+
+		if (!(hugo_fgets(resource_in_file, len+1, resource_file)))
+			goto ResfileError;
+
+		resposition = (long)hugo_fgetc(resource_file);
+		resposition += (long)hugo_fgetc(resource_file)*256L;
+		resposition += (long)hugo_fgetc(resource_file)*65536L;
+		if (res_32bits)
+		{
+			resposition += (long)hugo_fgetc(resource_file)*16777216L;
+		}
+
+		reslength = (long)hugo_fgetc(resource_file);
+		reslength += (long)hugo_fgetc(resource_file)*256L;
+		reslength += (long)hugo_fgetc(resource_file)*65536L;
+		if (res_32bits)
+		{
+			reslength += (long)hugo_fgetc(resource_file)*16777216L;
+		}
+		if (hugo_ferror(resource_file)) goto ResfileError;
+
+		if (!strcmp(resname, resource_in_file))
+		{
+			if (hugo_fseek(resource_file, (long)startofdata+resposition, SEEK_SET))
+				goto ResfileError;
+			return reslength;
+		}
+	}
+
+ResfileError:
+
+	var[system_status] = STAT_NORESOURCE;
+
+#if defined (DEBUGGER)
+	SwitchtoDebugger();
+	sprintf(debug_line, "Unable to find \"%s\" in \"%s\"", resname, filename);
+	DebugMessageBox("Resource Error", debug_line);
+	SwitchtoGame();
+#endif
+	hugo_fclose(resource_file);
+	resource_file = nullptr;
+
+
+	/* If we get here, we've either been unable to find the named
+	   resource in the given resourcefile, or no resourcefile was
+	   given
+	*/
+NotinResourceFile:
+
+#if !defined (GLK)
+	/* stdio implementation */
+	if (!(resource_file = TrytoOpen(resname, "rb", "resource")))
+		if (!(resource_file = TrytoOpen(resname, "rb", "source")))
+		{
+			if (!strcmp(filename, ""))
+				var[system_status] = STAT_NOFILE;
+			else
+				var[system_status] = STAT_NORESOURCE;
+			return 0;
+		}
+#else
+	/* Glk implementation */
+	fref = glk_fileref_create_by_name(fileusage_Data | fileusage_BinaryMode,
+		resname, 0);
+	if (glk_fileref_does_file_exist(fref))
+		resource_file = glk_stream_open_file(fref, filemode_Read, 0);
+	else
+		resource_file = nullptr;
+	glk_fileref_destroy(fref);
+	if (!resource_file)
+	{
+		if (!strcmp(filename, ""))
+			var[system_status] = STAT_NOFILE;
+		else
+			var[system_status] = STAT_NORESOURCE;
+		return 0;
+	}
+#endif
+
+	/* resource_file here refers to a resource in an individual
+	   on-disk file, not a consolidated resource file
+	*/
+	hugo_fseek(resource_file, 0, SEEK_END);
+	reslength = hugo_ftell(resource_file);
+	hugo_fseek(resource_file, 0, SEEK_SET);
+	if (hugo_ferror(resource_file))
+	{
+		hugo_fclose(resource_file);
+		resource_file = nullptr;
+		return false;
+	}
+
+	return reslength;
+}
+
+int Hugo::GetResourceParameters(char *filename, char *resname, int restype) {
+	int f;
+	
+	var[system_status] = 0;
+
+	extra_param = -1;
+
+	codeptr++;		/* token--i.e., 'picture', etc. */
+
+	f = GetValue();
+
+	/* If a 0 parameter is passed for "music 0", etc. */
+	if (!f && MEM(codeptr)!=COMMA_T)
+	{
+		++codeptr;
+		return 0;
+	}
+
+	strcpy(filename, GetWord((unsigned int)f));
+
+	if (MEM(codeptr++)!=EOL_T)	/* two or more parameters */
+	{
+		strupr(filename);
+		strcpy(resname, GetWord(GetValue()));
+		if (MEM(codeptr++)==COMMA_T)
+		{
+			extra_param = GetValue();
+			codeptr++;
+		}
+	}
+	else				/* only one parameter */
+	{
+		strcpy(resname, filename);
+		strcpy(filename, "");
+	}
+
+	return true;
+}
+
+} // End of namespace Hugo
+} // End of namespace Glk
diff --git a/engines/glk/hugo/hugo.cpp b/engines/glk/hugo/hugo.cpp
index bd8575b..8d85c68 100644
--- a/engines/glk/hugo/hugo.cpp
+++ b/engines/glk/hugo/hugo.cpp
@@ -31,6 +31,8 @@ Hugo::Hugo(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gam
 		SCREENWIDTH(0), SCREENHEIGHT(0), FIXEDCHARWIDTH(0), FIXEDLINEHEIGHT(0),
 		// heexpr
 		evalcount(0), incdec(0), getaddress(0), inexpr(0), inobj(0),
+		// hemedia
+		mchannel(nullptr), schannel(nullptr),
 		// hemisc
 		game_version(0), object_size(0), game(nullptr), script(nullptr), save(nullptr),
 		playback(nullptr), record(nullptr), io(nullptr), ioblock('\0'), ioerror('\0'),
@@ -56,6 +58,8 @@ Hugo::Hugo(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gam
 		objgrammar(0), objstart(0), objfinish(0), addflag(false), speaking(0), oopscount(0),
 		parse_called_twice(0), reparse_everything(0), full_buffer(false), recursive_call(false),
 		parse_location(0),
+		// heres
+		resource_file(nullptr), extra_param(0), resource_type(0),
 		// herun
 		arguments_passed(0), ret(0), retflag(0), during_player_input(false), override_full(0),
 		game_reset(false), stack_depth(0), tail_recursion(0), tail_recursion_addr(0),
@@ -78,6 +82,10 @@ Hugo::Hugo(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gam
 	Common::fill(&eval[0], &eval[MAX_EVAL_ELEMENTS], 0);
 	Common::fill(&var[0], &var[MAXLOCALS + MAXGLOBALS], 0);
 
+	// hemedia
+	Common::fill(&resids[0][0], &resids[2][MAXRES], 0);
+	numres[0] = numres[1] = 0;
+
 	// hemisc		
 	Common::fill(&context_command[0][0], &context_command[MAX_CONTEXT_COMMANDS][64], 0);
 	Common::fill(&id[0], &id[3], '\0');
@@ -98,6 +106,10 @@ Hugo::Hugo(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gam
 	Common::fill(&oops[0], &oops[MAXBUFFER + 1], '\0');
 	Common::fill(&punc_string[0], &punc_string[64], '\0');
 
+	// heres
+	Common::fill(&loaded_filename[0], &loaded_filename[MAX_RES_PATH], '\0');
+	Common::fill(&loaded_resname[0], &loaded_resname[MAX_RES_PATH], '\0');
+
 	// herun
 	Common::fill(&passlocal[0], &passlocal[MAXLOCALS], 0);
 
diff --git a/engines/glk/hugo/hugo.h b/engines/glk/hugo/hugo.h
index eeb65a2..8d2d18b 100644
--- a/engines/glk/hugo/hugo.h
+++ b/engines/glk/hugo/hugo.h
@@ -62,12 +62,16 @@ private:
 
 	int last_precedence;
 
+	// hemedia
+	schanid_t mchannel;
+	schanid_t schannel;
+	long resids[2][MAXRES];
+	int numres[2];
 
 	// hemisc
 	char gamefile[255];
 	int game_version;
 	int object_size;
-	//HUGO_FILE game;
 	Common::SeekableReadStream *game;
 	HUGO_FILE script;
 	HUGO_FILE save;
@@ -188,6 +192,13 @@ private:
 	char recursive_call;
 	int parse_location;						///< usually var[location]
 
+	// heres
+	HUGO_FILE resource_file;
+	int extra_param;
+	char loaded_filename[MAX_RES_PATH];
+	char loaded_resname[MAX_RES_PATH];
+	char resource_type = 0;
+
 	// herun
 	int passlocal[MAXLOCALS];		///< locals passed to routine
 	int arguments_passed;			///< when calling routine
@@ -619,6 +630,35 @@ private:
 	/**@}*/
 
 	/**
+	 * \defgroup hemedia
+	 * @{
+	 */
+
+	int loadres(HUGO_FILE infile, int reslen, int type);
+
+	int hugo_hasgraphics();
+
+	int hugo_displaypicture(HUGO_FILE infile, long reslen);
+
+	void initsound();
+
+	void initmusic();
+
+	int hugo_playmusic(HUGO_FILE infile, long reslen, char loop_flag);
+
+	void hugo_musicvolume(int vol);
+
+	void hugo_stopmusic();
+
+	int hugo_playsample(HUGO_FILE infile, long reslen, char loop_flag);
+
+	void hugo_samplevolume(int vol);
+
+	void hugo_stopsample();
+
+	/**@}*/
+
+	/**
 	 * \defgroup heobject - Object/property/attribute management functions
 	 * @{
 	 */
@@ -840,6 +880,41 @@ private:
 	/**@}*/
 
 	/**
+	 * \defgroup heres
+	 * @{
+	 */
+
+	void DisplayPicture();
+
+	void PlayMusic();
+
+	void PlaySample();
+
+	void PlayVideo();
+
+	/**
+	 * Assumes that filename/resname contain a resourcefile name and a resource name.
+	 * If resname is "", filename contains the path of the resource on disk.
+	 * Returns the length of the resource if if the named resource is found.
+	 *
+	 * If FindResource() returns non-zero, the file is hot, i.e., it is open and positioned
+	 * to the start of the resource.
+	 *
+	 * Note that resourcefiles are expected to be in (if not the current directory) "object" or "games",
+	 * and on-disk resources in (if not the given directory) "source" or "resource" (where these are the
+	 * environment variables "HUGO_...", not actual on-disk directories).
+	 */
+	long FindResource(char *filename, char *resname);
+
+	/**
+	 * Processes resourcefile/filename (and resource, if applicable).
+	 * Returns 0 if a valid 0 parameter is passed as in "music 0" or "sound 0".
+	 */
+	int GetResourceParameters(char *filename, char *resname, int restype);
+
+	/**@}*/
+
+	/**
 	* \defgroup herun
 	* @{
 	*/
@@ -934,7 +1009,7 @@ private:
 
 	int SetCompound(int t);
 
-	 /**@}*/
+	/**@}*/
 
 	/**
 	* \defgroup Miscellaneous
@@ -944,6 +1019,10 @@ private:
 	int hugo_fseek(Common::SeekableReadStream *s, long int offset, int whence) {
 		return s->seek(offset, whence);
 	}
+	int hugo_fseek(strid_t s, long int offset, int whence) {
+		Common::SeekableReadStream *rs = *s;
+		return hugo_fseek(rs, offset, whence);
+	}
 
 	int hugo_fgetc(Common::SeekableReadStream *s) {
 		return s->readByte();
@@ -977,6 +1056,10 @@ private:
 	size_t hugo_fread(void *ptr, size_t size, size_t count, Common::SeekableReadStream *s) {
 		return s->read(ptr, size * count);
 	}
+	size_t hugo_fread(void *ptr, size_t size, size_t count, strid_t s) {
+		Common::SeekableReadStream *rs = *s;
+		return hugo_fread(ptr, size, count, rs);
+	}
 
 	int hugo_fprintf(Common::WriteStream *s, const char *fmt, ...) {
 		va_list va;
@@ -1017,6 +1100,10 @@ private:
 	long hugo_ftell(Common::SeekableReadStream *s) {
 		return s->pos();
 	}
+	long hugo_ftell(strid_t s) {
+		Common::SeekableReadStream *rs = *s;
+		return hugo_ftell(rs);
+	}
 
 	int hugo_fclose(strid_t f) {
 		delete f;
@@ -1113,15 +1200,6 @@ public:
 	 * Save the game to the passed stream
 	 */
 	virtual Common::Error saveGameData(strid_t file, const Common::String &desc) override;
-
-	// TODO: Stubs to be Properly implemented
-	void hugo_stopsample() {}
-	void hugo_stopmusic() {}
-	int hugo_hasgraphics() { return 0; }
-	void DisplayPicture() {}
-	void PlayMusic() {}
-	void PlaySample() {}
-	void PlayVideo() {}
 };
 
 } // End of namespace Hugo
diff --git a/engines/glk/hugo/hugo_defines.h b/engines/glk/hugo/hugo_defines.h
index 02cfab1..1fb6892 100644
--- a/engines/glk/hugo/hugo_defines.h
+++ b/engines/glk/hugo/hugo_defines.h
@@ -31,8 +31,12 @@ namespace Hugo {
 #define HEVERSION 3
 #define HEREVISION 3
 #define HEINTERIM ".0"
+
 #define GLK
 #define DEBUGGER 1
+#define GRAPHICS_SUPPORTED
+#define SOUND_SUPPORTED
+#define SETTITLE_SUPPORTED
 
 #define MAXOBJLIST 32
 #define MAX_CONTEXT_COMMANDS	32
@@ -47,6 +51,8 @@ namespace Hugo {
 #define MAXCALLS 99
 #define MAXBREAKPOINTS 99
 #define MAX_CODE_HISTORY 99
+#define MAX_RES_PATH 255
+#define MAXRES 1024
 #define CHARWIDTH 1
 
 #define HUGO_FILE	strid_t
@@ -150,7 +156,11 @@ browsing.
 #define TAIL_RECURSION_ROUTINE          (-1)
 #define TAIL_RECURSION_PROPERTY         (-2)
 
+/* For system_status: */
 #define STAT_UNAVAILABLE	((short)-1)
+#define STAT_NOFILE 		101
+#define STAT_NORESOURCE		102
+#define STAT_LOADERROR		103
 
 #define PRINTFATALERROR(a)	error("%s", a)
 
@@ -163,6 +173,9 @@ browsing.
 
 #define FORCE_REDRAW 1
 
+#define PIC 0
+#define SND 1
+
 #endif
 
 } // End of namespace Hugo
diff --git a/engines/glk/hugo/hugo_types.h b/engines/glk/hugo/hugo_types.h
index fcdaa8e..a6d9658 100644
--- a/engines/glk/hugo/hugo_types.h
+++ b/engines/glk/hugo/hugo_types.h
@@ -90,6 +90,19 @@ enum ERROR_TYPE {
 	DIVIDE_E		///< divide by zero
 };
 
+enum RESOURCE_TYPE {
+	JPEG_R,			///< JPEG image
+	WAVE_R,			///< RIFF WAVE audio sample
+	MOD_R,			///< MOD music module
+	S3M_R,			///< S3M music module
+	XM_R,			///< XM music module
+	MIDI_R,			///< MIDI music
+	MP3_R,			///< MP3 audio layer
+	AVI_R,			///< Video for Windows
+	MPEG_R,			///< MPEG video
+	UNKNOWN_R
+};
+
 /**
  * A structure used for disambiguation in MatchObject()
  */
diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index fcb4714..d84d542 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -74,9 +74,11 @@ MODULE_OBJS := \
 	hugo/detection.o \
 	hugo/heexpr.o \
 	hugo/heglk.o \
+	hugo/hemedia.o \
 	hugo/hemisc.o \
 	hugo/heobject.o \
 	hugo/heparse.o \
+	hugo/heres.o \
 	hugo/herun.o \
 	hugo/heset.o \
 	hugo/htokens.o \





More information about the Scummvm-git-logs mailing list