From 6b6670caf9812a980a9aa4049bf6931aa943b79b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 11 May 2019 19:20:40 +1000 Subject: GLK: HUGO: Added hemedia & heres --- engines/glk/hugo/hemedia.cpp | 204 +++++++++++++++++ engines/glk/hugo/heparse.cpp | 4 +- engines/glk/hugo/heres.cpp | 472 ++++++++++++++++++++++++++++++++++++++++ engines/glk/hugo/hugo.cpp | 12 + engines/glk/hugo/hugo.h | 100 ++++++++- engines/glk/hugo/hugo_defines.h | 13 ++ engines/glk/hugo/hugo_types.h | 13 ++ engines/glk/module.mk | 2 + 8 files changed, 807 insertions(+), 13 deletions(-) create mode 100644 engines/glk/hugo/hemedia.cpp create mode 100644 engines/glk/hugo/heres.cpp (limited to 'engines') diff --git a/engines/glk/hugo/hemedia.cpp b/engines/glk/hugo/hemedia.cpp new file mode 100644 index 0000000000..19c9874ed4 --- /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 0369385398..da01810a8e 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 0000000000..606f712f0c --- /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 bd8575b080..8d85c68606 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 eeb65a29be..8d2d18b749 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 @@ -618,6 +629,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 * @{ @@ -839,6 +879,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 02cfab1882..1fb6892fca 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 fcdaa8ed27..a6d9658258 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 fcb47149c1..d84d542825 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 \ -- cgit v1.2.3