aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/glk/hugo/hemisc.cpp2497
-rw-r--r--engines/glk/hugo/hugo.cpp7
-rw-r--r--engines/glk/hugo/hugo.h53
-rw-r--r--engines/glk/hugo/hugo_defines.h2
-rw-r--r--engines/glk/hugo/hugo_types.h4
5 files changed, 1551 insertions, 1012 deletions
diff --git a/engines/glk/hugo/hemisc.cpp b/engines/glk/hugo/hemisc.cpp
index ac3a0d4dd0..c5a77803f7 100644
--- a/engines/glk/hugo/hemisc.cpp
+++ b/engines/glk/hugo/hemisc.cpp
@@ -26,108 +26,109 @@ namespace Glk {
namespace Hugo {
void Hugo::AP(const char *a) {
- char sticky = false, skipspchar = false, startofline = 0;
- int i, alen, plen, cwidth;
- char c = 0; /* current character */
+ char sticky = false, skipspchar = false, startofline = 0;
+ int i, alen, plen, cwidth;
+ char c = 0; /* current character */
#ifdef USE_SMARTFORMATTING
- char lastc = 0; /* for smart formatting */
+ char lastc = 0; /* for smart formatting */
#endif
- static int lastfcolor = 16, lastbgcolor = 17;
- static int lastfont = NORMAL_FONT;
- static int thisline = 0; /* width in pixels or characters */
- static int linebreaklen = 0, linebreak = 0;
- int tempfont;
- char printed_something = false;
+ static int lastfcolor = 16, lastbgcolor = 17;
+ static int lastfont = NORMAL_FONT;
+ static int thisline = 0; /* width in pixels or characters */
+ static int linebreaklen = 0, linebreak = 0;
+ int tempfont;
+ char printed_something = false;
#ifdef USE_TEXTBUFFER
- int bufferfont = currentfont;
+ int bufferfont = currentfont;
#endif
- /* Shameless little trick to override control characters in engine-
- printed text, such as MS-DOS filenames that contain '\'s:
- */
- if (a[0] == NO_CONTROLCHAR)
- {
- skipspchar = true;
- a++;
- }
- /* Semi-colon overrides LF */
- if ((strlen(a) >= 2) && a[strlen(a) - 1] == ';' && a[strlen(a) - 2] == '\\')
- {
- sticky = true;
- }
+ /* Shameless little trick to override control characters in engine-
+ printed text, such as MS-DOS filenames that contain '\'s:
+ */
+ if (a[0]==NO_CONTROLCHAR)
+ {
+ skipspchar = true;
+ a++;
+ }
+
+ /* Semi-colon overrides LF */
+ if ((strlen(a)>=2) && a[strlen(a)-1]==';' && a[strlen(a)-2]=='\\')
+ {
+ sticky = true;
+ }
- if (hugo_strlen(pbuffer))
- printed_something = true;
+ if (hugo_strlen(pbuffer))
+ printed_something = true;
- plen = strlen(pbuffer);
- if (plen == 0)
- {
- thisline = 0;
- linebreak = 0;
- linebreaklen = 0;
- lastfont = currentfont;
- startofline = true;
+ plen = strlen(pbuffer);
+ if (plen==0)
+ {
+ thisline = 0;
+ linebreak = 0;
+ linebreaklen = 0;
+ lastfont = currentfont;
+ startofline = true;
#ifdef USE_TEXTBUFFER
- bufferbreak = 0;
- bufferbreaklen = 0;
+ bufferbreak = 0;
+ bufferbreaklen = 0;
#endif
#ifdef USE_SMARTFORMATTING
- leftquote = true;
+ leftquote = true;
#endif
- }
+ }
- /* Check for color changes */
- if ((a[0]) && (lastfcolor != fcolor || lastbgcolor != bgcolor || startofline))
- {
- if (plen >= MAXBUFFER * 2 - 3) FatalError(OVERFLOW_E);
- pbuffer[plen++] = COLOR_CHANGE;
- pbuffer[plen++] = (char)(fcolor + 1);
- pbuffer[plen++] = (char)(bgcolor + 1);
- pbuffer[plen] = '\0';
- lastfcolor = fcolor;
- lastbgcolor = bgcolor;
- }
+ /* Check for color changes */
+ if ((a[0]) && (lastfcolor!=fcolor || lastbgcolor!=bgcolor || startofline))
+ {
+ if (plen >= MAXBUFFER*2-3) FatalError(OVERFLOW_E);
+ pbuffer[plen++] = COLOR_CHANGE;
+ pbuffer[plen++] = (char)(fcolor+1);
+ pbuffer[plen++] = (char)(bgcolor+1);
+ pbuffer[plen] = '\0';
+ lastfcolor = fcolor;
+ lastbgcolor = bgcolor;
+ }
- /* Check for font changes--since fonts can only get changed
- by printing, we don't check lastfont */
- if ((a[0]) && startofline)
- {
- if (plen >= MAXBUFFER * 2 - 2) FatalError(OVERFLOW_E);
- pbuffer[plen++] = FONT_CHANGE;
- pbuffer[plen++] = (char)(currentfont + 1);
- pbuffer[plen] = '\0';
- lastfont = currentfont;
- }
+ /* Check for font changes--since fonts can only get changed
+ by printing, we don't check lastfont */
+ if ((a[0]) && startofline)
+ {
+ if (plen >= MAXBUFFER*2-2) FatalError(OVERFLOW_E);
+ pbuffer[plen++] = FONT_CHANGE;
+ pbuffer[plen++] = (char)(currentfont+1);
+ pbuffer[plen] = '\0';
+ lastfont = currentfont;
+ }
- /* Begin by looping through the entire provided string: */
+ /* Begin by looping through the entire provided string: */
- alen = (int)strlen(a);
- if (sticky)
- alen -= 2;
+ alen = (int)strlen(a);
+ if (sticky)
+ alen -= 2;
- /* Not printing any actual text, so we won't need to go through
- queued font changes
- */
- if (alen == 0)
- lastfont = currentfont;
+ /* Not printing any actual text, so we won't need to go through
+ queued font changes
+ */
+ if (alen==0)
+ lastfont = currentfont;
- for (i = 0; i<alen; i++)
- {
- c = a[i];
+ for (i=0; i<alen; i++)
+ {
+ c = a[i];
+
+ /* Left-justification */
+ if (thisline==0 && c==' ' && !textto && currentpos==0)
+ continue;
- /* Left-justification */
- if (thisline == 0 && c == ' ' && !textto && currentpos == 0)
- continue;
+ /* First check control characters */
+ if (c=='\\' && !skipspchar)
+ {
+ c = a[++i];
- /* First check control characters */
- if (c == '\\' && !skipspchar)
+ switch (c)
{
- c = a[++i];
-
- switch (c)
- {
case 'n':
{
c = '\n';
@@ -171,7 +172,7 @@ void Hugo::AP(const char *a) {
case 'u':
{
currentfont &= ~UNDERLINE_FONT;
- AddFontCode:
+AddFontCode:
if (!textto)
{
int m, n;
@@ -180,43 +181,43 @@ void Hugo::AP(const char *a) {
if (!printed_something)
{
- for (m = 0; m<plen;)
+ for (m=0; m<plen;)
{
- if (pbuffer[m] == FONT_CHANGE)
+ if (pbuffer[m]==FONT_CHANGE)
{
- for (n = m; n<plen - 2; n++)
+ for (n=m; n<plen-2; n++)
{
- pbuffer[n] = pbuffer[n + 2];
+ pbuffer[n] = pbuffer[n+2];
}
- plen -= 2;
+ plen-=2;
pbuffer[plen] = '\0';
lastfont = currentfont;
}
- else if (pbuffer[m] == COLOR_CHANGE)
- m += 3;
+ else if (pbuffer[m]==COLOR_CHANGE)
+ m+=3;
else
break;
}
}
#ifdef USE_TEXTBUFFER
- if (hugo_strlen(pbuffer + bufferbreak) == 0)
+ if (hugo_strlen(pbuffer+bufferbreak)==0)
bufferfont = currentfont;
#endif
- if (plen >= MAXBUFFER * 2 - 2) FatalError(OVERFLOW_E);
- pbuffer[plen + 2] = '\0';
- pbuffer[plen + 1] = (char)(currentfont + 1);
+ if (plen >= MAXBUFFER*2-2) FatalError(OVERFLOW_E);
+ pbuffer[plen+2] = '\0';
+ pbuffer[plen+1] = (char)(currentfont+1);
pbuffer[plen] = FONT_CHANGE;
- plen += 2;
+ plen+=2;
/* Convert full if font height changes, since
- the amount of used screen real estate for
- this particular font (in terms of lines)
- will have changed:
+ the amount of used screen real estate for
+ this particular font (in terms of lines)
+ will have changed:
*/
ratio = (double)lineheight;
hugo_font(currentfont);
ratio /= (double)lineheight;
- newfull = (int)(((double)full)*ratio + 0.5);
+ newfull = (int)(((double)full)*ratio+0.5);
if (newfull) full = newfull;
}
continue;
@@ -229,618 +230,701 @@ void Hugo::AP(const char *a) {
}
default:
c = SpecialChar(a, &i);
- }
- }
- else if (game_version <= 22)
- {
- if (c == '~')
- c = '\"';
- else if (c == '^')
- c = '\n';
}
+ }
+ else if (game_version<=22)
+ {
+ if (c=='~')
+ c = '\"';
+ else if (c=='^')
+ c = '\n';
+ }
- /* Add the new character */
+ /* Add the new character */
- /* Text may be sent to an address in the array table instead
- of being output to the screen
- */
- if (textto)
- {
- /* space for array length */
- int n = (game_version>23) ? 2 : 0;
+ /* Text may be sent to an address in the array table instead
+ of being output to the screen
+ */
+ if (textto)
+ {
+ /* space for array length */
+ int n = (game_version>23)?2:0;
- if (c == '\n')
- {
- SETMEM(arraytable * 16L + textto * 2 + n, 0);
- textto++;
- }
- else if ((unsigned char)c >= ' ')
- {
- SETMEM(arraytable * 16L + textto * 2 + n, c);
- textto++;
- }
- /* Add a terminating zero in case we don't
- print any more to the array */
- SETMEM(arraytable * 16L + textto * 2 + n, 0);
+ if (c=='\n')
+ {
+ SETMEM(arraytable*16L + textto*2 + n, 0);
+ textto++;
+ }
+ else if ((unsigned char)c >= ' ')
+ {
+ SETMEM(arraytable*16L + textto*2 + n, c);
+ textto++;
+ }
+ /* Add a terminating zero in case we don't
+ print any more to the array */
+ SETMEM(arraytable*16L + textto*2 + n, 0);
- if (i >= alen) return;
+ if (i >= alen) return;
- continue; /* back to for (i=0; i<slen; i++) */
- }
+ continue; /* back to for (i=0; i<slen; i++) */
+ }
- printed_something = true;
+ printed_something = true;
- /* Handle in-text newlines */
- if (c == '\n')
- {
- hugo_font(currentfont = lastfont);
+ /* Handle in-text newlines */
+ if (c=='\n')
+ {
+ hugo_font(currentfont = lastfont);
#ifdef USE_TEXTBUFFER
- TB_AddWord(pbuffer + bufferbreak,
- current_text_x + bufferbreaklen,
- current_text_y,
- current_text_x + thisline - 1,
- current_text_y + lineheight - 1);
-#endif
- Printout(pbuffer);
- lastfont = currentfont;
+ TB_AddWord(pbuffer+bufferbreak,
+ current_text_x+bufferbreaklen,
+ current_text_y,
+ current_text_x+thisline-1,
+ current_text_y+lineheight-1);
+#endif
+ Printout(pbuffer, 0);
+ lastfont = currentfont;
#ifdef USE_TEXTBUFFER
- bufferfont = currentfont;
- bufferbreak = 0;
- bufferbreaklen = 0;
-#endif
- strcpy(pbuffer, "");
- plen = 0;
- linebreak = 0;
- linebreaklen = 0;
- thisline = 0;
+ bufferfont = currentfont;
+ bufferbreak = 0;
+ bufferbreaklen = 0;
+#endif
+ strcpy(pbuffer, "");
+ plen = 0;
+ linebreak = 0;
+ linebreaklen = 0;
+ thisline = 0;
#ifdef USE_SMARTFORMATTING
- leftquote = true;
- lastc = '\n';
+ leftquote = true;
+ lastc = '\n';
#endif
- pbuffer[plen++] = COLOR_CHANGE;
- pbuffer[plen++] = (char)(fcolor + 1);
- pbuffer[plen++] = (char)(bgcolor + 1);
- pbuffer[plen] = '\0';
+ pbuffer[plen++] = COLOR_CHANGE;
+ pbuffer[plen++] = (char)(fcolor+1);
+ pbuffer[plen++] = (char)(bgcolor+1);
+ pbuffer[plen] = '\0';
- continue;
- }
+ continue;
+ }
#ifdef USE_SMARTFORMATTING
- /* Smart formatting only for non-fixed fonts */
- if ((currentfont & PROP_FONT) && smartformatting)
+ /* Smart formatting only for non-fixed fonts */
+ if ((currentfont & PROP_FONT) && smartformatting)
+ {
+ if ((!strncmp(a+i, "--", 2)) && lastc!='-' && strncmp(a+i, "---", 3))
{
- if ((!strncmp(a + i, "--", 2)) && lastc != '-' && strncmp(a + i, "---", 3))
- {
- lastc = '-';
- c = (char)151;
- i++;
- leftquote = false;
- }
- else if (c == '\"')
- {
- if (leftquote)
- c = (char)147;
- else
- c = (char)148;
- leftquote = false;
- lastc = c;
- }
- else if (c == '\'')
- {
- if (leftquote)
- c = (char)145;
- else
- c = (char)146;
- leftquote = false;
- lastc = c;
- }
+ lastc = '-';
+ c = (char)151;
+ i++;
+ leftquote = false;
+ }
+ else if (c=='\"')
+ {
+ if (leftquote)
+ c = (char)147;
else
- {
- if (c == ' ')
- leftquote = true;
- else
- leftquote = false;
- lastc = c;
- }
+ c = (char)148;
+ leftquote = false;
+ lastc = c;
+ }
+ else if (c=='\'')
+ {
+ if (leftquote)
+ c = (char)145;
+ else
+ c = (char)146;
+ leftquote = false;
+ lastc = c;
+ }
+ else
+ {
+ if (c==' ')
+ leftquote = true;
+ else
+ leftquote = false;
+ lastc = c;
}
+ }
#endif
- /* Add the new character to the printing buffer */
- if (plen >= MAXBUFFER * 2 - 1) FatalError(OVERFLOW_E);
- pbuffer[plen + 1] = '\0';
- pbuffer[plen] = c;
- plen++;
-
- cwidth = hugo_charwidth(c);
+ /* Add the new character to the printing buffer */
+ if (plen >= MAXBUFFER*2-1) FatalError(OVERFLOW_E);
+ pbuffer[plen+1] = '\0';
+ pbuffer[plen] = c;
+ plen++;
- /* Check to see if we've overrun the current line */
+ cwidth = hugo_charwidth(c);
- if (thisline + cwidth + currentpos > physical_windowwidth)
- {
- char t;
+ /* Check to see if we've overrun the current line */
- if (!linebreak)
- {
- linebreak = plen - 1;
- linebreaklen = thisline;
- }
+ if (thisline+cwidth+currentpos > physical_windowwidth)
+ {
+ char t;
- t = pbuffer[linebreak];
- pbuffer[linebreak] = '\0';
-
- tempfont = currentfont;
- hugo_font(currentfont = lastfont);
- Printout(pbuffer);
- lastfont = currentfont;
- hugo_font(currentfont = tempfont);
-
- pbuffer[linebreak] = t;
- plen = strlen(pbuffer + linebreak);
- memmove(pbuffer, pbuffer + linebreak, plen + 1);
- thisline = thisline - linebreaklen;
- linebreak = 0;
- linebreaklen = 0;
- startofline = 0;
-#ifdef USE_TEXTBUFFER
- bufferbreak = 0;
- bufferbreaklen = 0;
-#endif
+ if (!linebreak)
+ {
+ linebreak = plen-1;
+ linebreaklen = thisline;
}
- thisline += cwidth;
+ t = pbuffer[linebreak];
+ pbuffer[linebreak] = '\0';
+ tempfont = currentfont;
+ hugo_font(currentfont = lastfont);
+ Printout(pbuffer, linebreak);
+ lastfont = currentfont;
+ hugo_font(currentfont = tempfont);
+
+ pbuffer[linebreak] = t;
+ plen = strlen(pbuffer+linebreak);
+ memmove(pbuffer, pbuffer+linebreak, plen + 1);
+ thisline = thisline - linebreaklen;
+ linebreak = 0;
+ linebreaklen = 0;
+ startofline = 0;
#ifdef USE_TEXTBUFFER
- if ((c == ' ' || c == FORCED_SPACE) ||
- (c == '/' && a[i + 1] != '/') || (c == '-' && a[i + 1] != '-'))
- {
- TB_AddWord(pbuffer + bufferbreak,
- current_text_x + bufferbreaklen,
- current_text_y,
- current_text_x + thisline - 1,
- current_text_y + lineheight - 1);
-
- bufferbreak = plen;
- bufferbreaklen = thisline;
- bufferfont = currentfont;
- }
+ bufferbreak = 0;
+ bufferbreaklen = 0;
#endif
- if ((c == ' ') || (c == '/' && a[i + 1] != '/') || (c == '-' && a[i + 1] != '-'))
- {
- linebreak = plen, linebreaklen = thisline;
- }
}
+ thisline += cwidth;
+
#ifdef USE_TEXTBUFFER
- if (!sticky || alen > 1)
+ if ((c==' ' || c==FORCED_SPACE) ||
+ (c=='/' && a[i+1]!='/') || (c=='-' && a[i+1]!='-'))
{
- tempfont = currentfont;
- currentfont = bufferfont;
-
- TB_AddWord(pbuffer + bufferbreak,
- current_text_x + bufferbreaklen,
+ TB_AddWord(pbuffer+bufferbreak,
+ current_text_x+bufferbreaklen,
current_text_y,
- current_text_x + thisline - 1,
- current_text_y + lineheight - 1);
+ current_text_x+thisline-1,
+ current_text_y+lineheight-1);
bufferbreak = plen;
bufferbreaklen = thisline;
- currentfont = tempfont;
+ bufferfont = currentfont;
}
#endif
- if (!sticky)
+ if ((c==' ') || (c=='/' && a[i+1]!='/') || (c=='-' && a[i+1]!='-'))
{
- hugo_font(currentfont = lastfont);
- Printout(pbuffer);
- lastfont = currentfont;
- strcpy(pbuffer, "");
- linebreak = 0;
- linebreaklen = 0;
- thisline = 0;
- plen = 0;
+ linebreak = plen, linebreaklen = thisline;
+ }
+ }
+
#ifdef USE_TEXTBUFFER
- bufferbreak = 0;
- bufferbreaklen = 0;
+ if (!sticky || alen > 1)
+ {
+ tempfont = currentfont;
+ currentfont = bufferfont;
+
+ TB_AddWord(pbuffer+bufferbreak,
+ current_text_x+bufferbreaklen,
+ current_text_y,
+ current_text_x+thisline-1,
+ current_text_y+lineheight-1);
+
+ bufferbreak = plen;
+ bufferbreaklen = thisline;
+ currentfont = tempfont;
+ }
+#endif
+ if (!sticky)
+ {
+ hugo_font(currentfont = lastfont);
+ Printout(pbuffer, 0);
+ lastfont = currentfont;
+ strcpy(pbuffer, "");
+ linebreak = 0;
+ linebreaklen = 0;
+ thisline = 0;
+ plen = 0;
+#ifdef USE_TEXTBUFFER
+ bufferbreak = 0;
+ bufferbreaklen = 0;
#endif
#ifdef USE_SMARTFORMATTING
- leftquote = true;
+ leftquote = true;
#endif
- }
}
+}
int Hugo::CallRoutine(unsigned int addr) {
- int arg, i;
- int val;
- int templocals[MAXLOCALS], temppass[MAXLOCALS];
- int temp_stack_depth;
- long tempptr;
- int potential_tail_recursion = tail_recursion;
+ int arg, i;
+ int val;
+ int templocals[MAXLOCALS], temppass[MAXLOCALS];
+ int temp_stack_depth;
+ long tempptr;
+ int potential_tail_recursion = tail_recursion;
#if defined (DEBUGGER)
- int tempdbnest;
+ int tempdbnest;
#endif
- arg = 0;
- tail_recursion = 0;
+ arg = 0;
+ tail_recursion = 0;
- /* Pass local variables to routine, if specified */
- if (MEM(codeptr) == OPEN_BRACKET_T)
+ /* Pass local variables to routine, if specified */
+ if (MEM(codeptr)==OPEN_BRACKET_T)
+ {
+ codeptr++;
+ while (MEM(codeptr) != CLOSE_BRACKET_T)
{
- codeptr++;
- while (MEM(codeptr) != CLOSE_BRACKET_T)
+ if (arg)
{
- if (arg)
- {
- for (i = 0; i<arg; i++)
- temppass[i] = passlocal[i];
- }
-
- passlocal[arg++] = GetValue();
+ for (i=0; i<arg; i++)
+ temppass[i] = passlocal[i];
+ }
- if (arg > 1)
- {
- for (i = 0; i<arg - 1; i++)
- passlocal[i] = temppass[i];
- }
+ passlocal[arg++] = GetValue();
- if (MEM(codeptr) == COMMA_T) codeptr++;
+ if (arg > 1)
+ {
+ for (i=0; i<arg-1; i++)
+ passlocal[i] = temppass[i];
}
- codeptr++;
- }
- /* TAIL_RECURSION_ROUTINE if we came from a routine call immediately
- following a 'return' statement...
- */
- tail_recursion = potential_tail_recursion;
- if (tail_recursion == TAIL_RECURSION_ROUTINE && MEM(codeptr) == EOL_T)
- {
- tail_recursion_addr = (long)addr*address_scale;
- PassLocals(arg);
- return 0;
- }
- /* ...but if we're not immediately followed by and end-of-line marker,
- cancel the pending tail-recursion
- */
- else
- {
- tail_recursion = 0;
+ if (MEM(codeptr)==COMMA_T) codeptr++;
}
+ codeptr++;
+ }
- for (i = 0; i<MAXLOCALS; i++)
- templocals[i] = var[MAXGLOBALS + i];
+ /* TAIL_RECURSION_ROUTINE if we came from a routine call immediately
+ following a 'return' statement...
+ */
+ tail_recursion = potential_tail_recursion;
+ if (tail_recursion==TAIL_RECURSION_ROUTINE && MEM(codeptr)==EOL_T)
+ {
+ tail_recursion_addr = (long)addr*address_scale;
PassLocals(arg);
+ return 0;
+ }
+ /* ...but if we're not immediately followed by and end-of-line marker,
+ cancel the pending tail-recursion
+ */
+ else
+ {
+ tail_recursion = 0;
+ }
- temp_stack_depth = stack_depth;
+ for (i=0; i<MAXLOCALS; i++)
+ templocals[i] = var[MAXGLOBALS+i];
+ PassLocals(arg);
- SetStackFrame(stack_depth, RUNROUTINE_BLOCK, 0, 0);
+ temp_stack_depth = stack_depth;
- tempptr = codeptr; /* store calling address */
- ret = 0;
+ SetStackFrame(stack_depth, RUNROUTINE_BLOCK, 0, 0);
+
+ tempptr = codeptr; /* store calling address */
+ ret = 0;
#if defined (DEBUGGER)
- tempdbnest = dbnest;
- DebugRunRoutine((long)addr*address_scale);
- dbnest = tempdbnest;
+ tempdbnest = dbnest;
+ DebugRunRoutine((long)addr*address_scale);
+ dbnest = tempdbnest;
#else
- RunRoutine((long)addr*address_scale);
+ RunRoutine((long)addr*address_scale);
#endif
- retflag = 0;
- val = ret;
- codeptr = tempptr;
+ retflag = 0;
+ val = ret;
+ codeptr = tempptr;
- stack_depth = temp_stack_depth;
+ stack_depth = temp_stack_depth;
- for (i = 0; i<MAXLOCALS; i++)
- var[MAXGLOBALS + i] = templocals[i];
+ for (i=0; i<MAXLOCALS; i++)
+ var[MAXGLOBALS+i] = templocals[i];
- return val;
- }
+ return val;
+}
void Hugo::ContextCommand() {
- unsigned int n;
+ unsigned int n;
- ContextCommandLoop:
+ContextCommandLoop:
- codeptr++;
-
- n = GetValue();
+ codeptr++;
+
+ n = GetValue();
#if !defined (COMPILE_V25)
- if (n == 0)
- {
- context_commands = 0;
- }
- else if (context_commands < MAX_CONTEXT_COMMANDS)
- {
- char *cc;
+ if (n==0)
+ {
+ context_commands = 0;
+ }
+ else if (context_commands < MAX_CONTEXT_COMMANDS)
+ {
+ char *cc;
- strncpy(context_command[context_commands], cc = GetWord(n), 64);
- context_command[context_commands][63] = '\0';
- if (strlen(cc) >= 64)
- sprintf(context_command[context_commands] + 60, "...");
- context_commands++;
- }
-#endif
- if (Peek(codeptr) == COMMA_T) goto ContextCommandLoop;
- codeptr++;
+ strncpy(context_command[context_commands], cc = GetWord(n), 64);
+ context_command[context_commands][63] = '\0';
+ if (strlen(cc)>=64)
+ sprintf(context_command[context_commands]+60, "...");
+ context_commands++;
}
+#endif
+ if (Peek(codeptr)==COMMA_T) goto ContextCommandLoop;
+ codeptr++;
+}
unsigned int Hugo::Dict() {
- int i, len = 256;
- unsigned int arr;
- unsigned int pos = 2, loc;
+ int i, len = 256;
+ unsigned int arr;
+ unsigned int pos = 2, loc;
- codeptr += 2; /* "(" */
+ codeptr += 2; /* "(" */
- if (MEM(codeptr) == PARSE_T || MEM(codeptr) == WORD_T)
- strcpy(line, GetWord(GetValue()));
- else
+ if (MEM(codeptr)==PARSE_T || MEM(codeptr)==WORD_T)
+ strcpy(line, GetWord(GetValue()));
+ else
+ {
+ /* Get the array address to read the to-be-
+ created dictionary entry from:
+ */
+ arr = GetValue();
+ if (game_version>=22)
{
- /* Get the array address to read the to-be-
- created dictionary entry from:
+ /* Convert the address to a word
+ value:
*/
- arr = GetValue();
- if (game_version >= 22)
- {
- /* Convert the address to a word
- value:
- */
- arr *= 2;
-
- if (game_version >= 23)
- /* space for array length */
- arr += 2;
- }
+ arr*=2;
- defseg = arraytable;
- for (i = 0; i<len && PeekWord(arr + i * 2) != 0; i++)
- line[i] = (char)PeekWord(arr + i * 2);
- defseg = gameseg;
- line[i] = '\0';
+ if (game_version>=23)
+ /* space for array length */
+ arr+=2;
}
- if (Peek(codeptr) == COMMA_T) codeptr++;
- len = GetValue();
+ defseg = arraytable;
+ for (i=0; i<len && PeekWord(arr+i*2)!=0; i++)
+ line[i] = (char)PeekWord(arr+i*2);
+ defseg = gameseg;
+ line[i] = '\0';
+ }
- if ((loc = FindWord(line)) != UNKNOWN_WORD) return loc;
+ if (Peek(codeptr)==COMMA_T) codeptr++;
+ len = GetValue();
- defseg = dicttable;
+ if ((loc = FindWord(line))!=UNKNOWN_WORD) return loc;
- for (i = 1; i <= dictcount; i++)
- pos += Peek(pos) + 1;
+ defseg = dicttable;
- loc = pos - 2;
+ for (i=1; i<=dictcount; i++)
+ pos += Peek(pos) + 1;
- if ((long)(pos + strlen(line)) > (long)(codeend - dicttable * 16L))
- {
+ loc = pos - 2;
+
+ if ((long)(pos+strlen(line)) > (long)(codeend-dicttable*16L))
+ {
#ifdef DEBUGGER
- sprintf(debug_line, "$MAXDICTEXTEND dictionary space exceeded");
- RuntimeWarning(debug_line);
+ sprintf(debug_line, "$MAXDICTEXTEND dictionary space exceeded");
+ RuntimeWarning(debug_line);
#endif
- defseg = gameseg;
- return 0;
- }
+ defseg = gameseg;
+ return 0;
+ }
- Poke(pos++, (unsigned char)strlen(line));
- for (i = 0; i<(int)strlen(line) && i<len; i++)
- Poke(pos++, (unsigned char)(line[i] + CHAR_TRANSLATION));
- PokeWord(0, ++dictcount);
+ Poke(pos++, (unsigned char)strlen(line));
+ for (i=0; i<(int)strlen(line) && i<len; i++)
+ Poke(pos++, (unsigned char)(line[i]+CHAR_TRANSLATION));
+ PokeWord(0, ++dictcount);
- defseg = gameseg;
+ defseg = gameseg;
- SaveUndo(DICT_T, strlen(line), 0, 0, 0);
+ SaveUndo(DICT_T, strlen(line), 0, 0, 0);
- return loc;
- }
+ return loc;
+}
-void Hugo::FatalError(int n){
+void Hugo::FatalError(int n) {
char fatalerrorline[64];
+#if defined (DEBUGGER)
+ hugo_stopmusic();
+ hugo_stopsample();
+
+ /* If the Debugger has already issued an error, it will
+ try to recover instead of issuing a stream of
+ identical errors.
+ */
+ if (runtime_error) return;
+#else
hugo_cleanup_screen();
+#endif
switch (n)
{
- case MEMORY_E:
- {sprintf(line, "Out of memory\n");
- break; }
+ case MEMORY_E:
+ {sprintf(line, "Out of memory\n");
+ break;}
- case OPEN_E:
- {sprintf(line, "Cannot open file\n");
- break; }
+ case OPEN_E:
+ {sprintf(line, "Cannot open file\n");
+ break;}
- case READ_E:
- {sprintf(line, "Cannot read from file\n");
- break; }
+ case READ_E:
+ {sprintf(line, "Cannot read from file\n");
+ break;}
- case WRITE_E:
- {sprintf(line, "Cannot write to save file\n");
- break; }
+ case WRITE_E:
+ {sprintf(line, "Cannot write to save file\n");
+ break;}
- case EXPECT_VAL_E:
- {sprintf(line, "Expecting value at $%s\n", PrintHex(codeptr));
- break; }
+ case EXPECT_VAL_E:
+ {sprintf(line, "Expecting value at $%s\n", PrintHex(codeptr));
+ break;}
- case UNKNOWN_OP_E:
- {sprintf(line, "Unknown operation at $%s\n", PrintHex(codeptr));
- break; }
+ case UNKNOWN_OP_E:
+ {sprintf(line, "Unknown operation at $%s\n", PrintHex(codeptr));
+ break;}
- case ILLEGAL_OP_E:
- {sprintf(line, "Illegal operation at $%s\n", PrintHex(codeptr));
- break; }
+ case ILLEGAL_OP_E:
+ {sprintf(line, "Illegal operation at $%s\n", PrintHex(codeptr));
+ break;}
- case OVERFLOW_E:
- {sprintf(line, "Overflow at $%s\n", PrintHex(codeptr));
- break; }
+ case OVERFLOW_E:
+ {sprintf(line, "Overflow at $%s\n", PrintHex(codeptr));
+ break;}
- case DIVIDE_E:
- {sprintf(line, "Divide by zero at $%s\n", PrintHex(codeptr));
- break; }
+ case DIVIDE_E:
+ {sprintf(line, "Divide by zero at $%s\n", PrintHex(codeptr));
+ break;}
}
+#if defined (DEBUGGER)
+
+ if (routines > 0)
+ {
+ SwitchtoDebugger();
+
+ if (n==MEMORY_E) DebuggerFatal(D_MEMORY_ERROR);
+
+ RuntimeWarning(line);
+ debugger_interrupt = true;
+ debugger_skip = true;
+ runtime_error = true;
+
+ if (n!=EXPECT_VAL_E)
+ RecoverLastGood();
+
+ codeptr = this_codeptr;
+
+ return;
+ }
+
+ hugo_cleanup_screen();
+#endif
+
+/* crash dump */
+/*
+if (n==UNKNOWN_OP_E || n==ILLEGAL_OP_E || n==EXPECT_VAL_E || n==OVERFLOW_E)
+{
+ for (n=-8; n<0; n++)
+ fprintf(stderr, " %c%2X", (n==-8)?'$':' ', MEM(codeptr+n));
+ fprintf(stderr, "\n");
+ for (n=-8; n<0; n++)
+ fprintf(stderr, " %3d", MEM(codeptr+n));
+ fprintf(stderr, "\n\n> %2X", MEM(codeptr));
+ for (n=1; n<8; n++)
+ fprintf(stderr, " %2X", MEM(codeptr+n));
+ fprintf(stderr, "\n");
+ fprintf(stderr, ">%3d", MEM(codeptr));
+ for (n=1; n<8; n++)
+ fprintf(stderr, " %3d", MEM(codeptr+n));
+ fprintf(stderr, "\n");
+}
+*/
sprintf(fatalerrorline, "\nFatal Error: %s", line);
- error(fatalerrorline);
+ PRINTFATALERROR(fatalerrorline);
+
+ hugo_closefiles();
+ hugo_blockfree(mem);
+ mem = NULL;
+ error("Error code: %d", (int)n);
}
void Hugo::FileIO() {
- char fileiopath[MAXPATH];
- char iotype;
- unsigned int fnameval;
- long skipaddr;
- int i, temp_stack_depth = stack_depth;
-
- iotype = MEM(codeptr++);
- skipaddr = (long)PeekWord(codeptr)*address_scale;
- codeptr += 2;
- fnameval = GetValue();
- if (game_version >= 23) codeptr++; /* eol */
-
- ioerror = 0;
-
- /* Make sure the filename is legal, 8 alphanumeric characters or less */
- strcpy(line, GetWord(fnameval));
- if (strlen(line) > 8) goto LeaveFileIO;
- for (i = 0; i<(int)strlen(line); i++)
+#ifndef GLK
+ char drive[MAXDRIVE], dir[MAXDIR], fname[MAXFILENAME], ext[MAXEXT];
+#endif
+ char fileiopath[MAXPATH];
+ char iotype;
+ unsigned int fnameval;
+ long skipaddr;
+ int i, temp_stack_depth = stack_depth;
+#if defined (DEBUGGER)
+ int tempdbnest;
+#endif
+
+ iotype = MEM(codeptr++);
+ skipaddr = (long)PeekWord(codeptr)*address_scale;
+ codeptr+=2;
+ fnameval = GetValue();
+ if (game_version>=23) codeptr++; /* eol */
+
+ ioerror = 0;
+
+ /* Make sure the filename is legal, 8 alphanumeric characters or less */
+ strcpy(line, GetWord(fnameval));
+ if (strlen(line) > 8) goto LeaveFileIO;
+ for (i=0; i<(int)strlen(line); i++)
+ {
+ if ((line[i]>='0' && line[i]<='9') || (line[i]>='A' && line[i]<='Z') ||
+ (line[i]>='a' && line[i]<='z'))
{
- if ((line[i] >= '0' && line[i] <= '9') || (line[i] >= 'A' && line[i] <= 'Z') ||
- (line[i] >= 'a' && line[i] <= 'z'))
- {
- continue;
- }
- else
- goto LeaveFileIO;
+ continue;
}
+ else
+ goto LeaveFileIO;
+ }
- if (ioblock) goto LeaveFileIO; /* can't nest file operations */
-
- strcpy(fileiopath, GetWord(fnameval));
+ if (ioblock) goto LeaveFileIO; /* can't nest file operations */
- if (iotype == WRITEFILE_T) /* "writefile" */
- {
- /* Glk implementation */
- frefid_t fref = nullptr;
-
- fref = glk_fileref_create_by_name(fileusage_Data | fileusage_BinaryMode,
- fileiopath, 0);
- io = glk_stream_open_file(fref, filemode_Write, 0);
- glk_fileref_destroy(fref);
- if (io == nullptr) goto LeaveFileIO;
+#if !defined (GLK)
+ hugo_splitpath(program_path, drive, dir, fname, ext);
+ hugo_makepath(fileiopath, drive, dir, GetWord(fnameval), "");
+#else
+ strcpy(fileiopath, GetWord(fnameval));
+#endif
- ioblock = 1;
- }
- else /* "readfile" */
- {
- /* Glk implementation */
- frefid_t fref = nullptr;
+ if (iotype==WRITEFILE_T) /* "writefile" */
+ {
+#if !defined (GLK)
+ /* stdio implementation */
+ if ((io = HUGO_FOPEN(fileiopath, "wb"))==NULL) goto LeaveFileIO;
+#else
+ /* Glk implementation */
+ frefid_t fref = NULL;
+
+ fref = glk_fileref_create_by_name(fileusage_Data | fileusage_BinaryMode,
+ fileiopath, 0);
+ io = glk_stream_open_file(fref, filemode_Write, 0);
+ glk_fileref_destroy(fref);
+ if (io==NULL) goto LeaveFileIO;
+#endif
+ ioblock = 1;
+ }
+ else /* "readfile" */
+ {
+#if !defined (GLK)
+ /* stdio implementation */
+ if ((io = HUGO_FOPEN(fileiopath, "rb"))==NULL) goto LeaveFileIO;
+#else
+ /* Glk implementation */
+ frefid_t fref = NULL;
+
+ fref = glk_fileref_create_by_name(fileusage_Data | fileusage_BinaryMode,
+ fileiopath, 0);
+ io = glk_stream_open_file(fref, filemode_Read, 0);
+ glk_fileref_destroy(fref);
+ if (io==NULL) goto LeaveFileIO;
+#endif
+ ioblock = 2;
+ }
- fref = glk_fileref_create_by_name(fileusage_Data | fileusage_BinaryMode,
- fileiopath, 0);
- if (glk_fileref_does_file_exist(fref))
- io = glk_stream_open_file(fref, filemode_Read, 0);
- else
- io = nullptr;
- glk_fileref_destroy(fref);
- if (io == nullptr) goto LeaveFileIO;
+#if defined (DEBUGGER)
+ tempdbnest = dbnest++;
+#endif
- ioblock = 2;
- }
+ SetStackFrame(stack_depth, RUNROUTINE_BLOCK, 0, 0);
- SetStackFrame(stack_depth, RUNROUTINE_BLOCK, 0, 0);
+ RunRoutine(codeptr);
- RunRoutine(codeptr);
+#if defined (DEBUGGER)
+ dbnest = tempdbnest;
+#endif
- stack_depth = temp_stack_depth;
+ stack_depth = temp_stack_depth;
- if (ioerror) retflag = 0;
+ if (ioerror) retflag = 0;
- delete io;
- io = nullptr;
- ioblock = 0;
+ hugo_fclose(io);
+ io = NULL;
+ ioblock = 0;
- LeaveFileIO:
- ioerror = 0;
- codeptr = skipaddr;
- }
+LeaveFileIO:
+ ioerror = 0;
+ codeptr = skipaddr;
+}
void Hugo::Flushpbuffer() {
- if (pbuffer[0] == '\0') return;
+ if (pbuffer[0]=='\0') return;
#ifdef USE_TEXTBUFFER
- /* For (single) characters left over from AP(), when Flushpbuffer() gets
- called, say, from RunWindow()
- */
- if (bufferbreaklen && pbuffer + bufferbreaklen && !(currentfont&PROP_FONT))
- {
- TB_AddWord(pbuffer + bufferbreak,
- current_text_x + bufferbreaklen,
- current_text_y,
- current_text_x + bufferbreaklen + FIXEDCHARWIDTH,
- current_text_y + lineheight - 1);
- }
+ /* For (single) characters left over from AP(), when Flushpbuffer() gets
+ called, say, from RunWindow()
+ */
+ if (bufferbreaklen && pbuffer+bufferbreaklen && !(currentfont&PROP_FONT))
+ {
+ TB_AddWord(pbuffer+bufferbreak,
+ current_text_x+bufferbreaklen,
+ current_text_y,
+ current_text_x+bufferbreaklen+FIXEDCHARWIDTH,
+ current_text_y+lineheight-1);
+ }
#endif
- pbuffer[strlen(pbuffer) + 1] = '\0';
- pbuffer[strlen(pbuffer)] = (char)NO_NEWLINE;
- Printout(Ltrim(pbuffer));
- currentpos = hugo_textwidth(pbuffer); /* -charwidth; */
- strcpy(pbuffer, "");
- }
+ pbuffer[strlen(pbuffer)+1] = '\0';
+ pbuffer[strlen(pbuffer)] = (char)NO_NEWLINE;
+ Printout(Ltrim(pbuffer), 0);
+ currentpos = hugo_textwidth(pbuffer); /* -charwidth; */
+ strcpy(pbuffer, "");
+}
void Hugo::GetCommand() {
- char a[256];
+ char a[256];
#ifdef USE_TEXTBUFFER
- int start, width, i, y;
+ int start, width, i, y;
#endif
- Flushpbuffer();
- AP("");
+ Flushpbuffer();
+ AP("");
- hugo_settextcolor(fcolor);
- hugo_setbackcolor(bgcolor);
- if (icolor == -1)
- icolor = fcolor; /* check unset input color */
+ hugo_settextcolor(fcolor);
+ hugo_setbackcolor(bgcolor);
+ if (icolor==-1)
+ icolor = fcolor; /* check unset input color */
- strncpy(a, GetWord(var[prompt]), 255);
- during_player_input = true;
- full = 0;
+ strncpy(a, GetWord(var[prompt]), 255);
+ during_player_input = true;
+ full = 0;
#ifdef USE_TEXTBUFFER
- /* Add the prompt to the textbuffer (using TB_Add()) */
- y = current_text_y;
- width = hugo_textwidth(GetWord(var[prompt]));
- TB_AddWord(GetWord(var[prompt]), physical_windowleft, y,
- physical_windowleft + width, y + lineheight - 1);
-
- hugo_getline(a);
-
- /* If hugo_scrollwindowup() called by hugo_getline() shifted things */
- if (current_text_y > y)
- {
- y += (current_text_y - y);
- }
+ /* Add the prompt to the textbuffer (using TB_Add()) */
+ y = current_text_y;
+ width = hugo_textwidth(GetWord(var[prompt]));
+ TB_AddWord(GetWord(var[prompt]), physical_windowleft, y,
+ physical_windowleft+width, y+lineheight-1);
+
+ hugo_getline(a);
+
+ /* If hugo_scrollwindowup() called by hugo_getline() shifted things */
+ if (current_text_y > y)
+ {
+ y += (current_text_y - y);
+ }
- /* Add each word in the input buffer */
- start = 0;
- for (i = 0; i<(int)strlen(buffer); i++)
+ /* Add each word in the input buffer */
+ start = 0;
+ for (i=0; i<(int)strlen(buffer); i++)
+ {
+ if (buffer[i]==' ')
{
- if (buffer[i] == ' ')
- {
- buffer[i] = '\0';
- TB_AddWord(buffer + start, physical_windowleft + width, y - lineheight,
- physical_windowleft + width + hugo_textwidth(buffer + start), y - 1);
- width += hugo_textwidth(buffer + start) + hugo_textwidth(" ");
- start = i + 1;
- buffer[i] = ' ';
- }
+ buffer[i] = '\0';
+ TB_AddWord(buffer+start, physical_windowleft+width, y-lineheight,
+ physical_windowleft+width+hugo_textwidth(buffer+start), y-1);
+ width += hugo_textwidth(buffer+start) + hugo_textwidth(" ");
+ start = i+1;
+ buffer[i] = ' ';
}
- /* Add the final word */
- TB_AddWord(buffer + start, physical_windowleft + width, y - lineheight,
- physical_windowleft + width + hugo_textwidth(buffer + start), y - 1);
+ }
+ /* Add the final word */
+ TB_AddWord(buffer+start, physical_windowleft+width, y-lineheight,
+ physical_windowleft+width+hugo_textwidth(buffer+start), y-1);
#else
- hugo_getline(a);
+ hugo_getline(a);
#endif
- during_player_input = false;
- strcpy(buffer, Rtrim(buffer));
+ during_player_input = false;
+ strcpy(buffer, Rtrim(buffer));
- strcpy(parseerr, "");
+ strcpy(parseerr, "");
- full = 1;
- remaining = 0;
- }
+ full = 1;
+ remaining = 0;
+}
char *Hugo::GetString(long addr) {
static char a[256];
@@ -848,9 +932,9 @@ char *Hugo::GetString(long addr) {
length = Peek(addr);
- for (i = 1; i <= length; i++)
- a[i - 1] = (char)(Peek(addr + i) - CHAR_TRANSLATION);
- a[i - 1] = '\0';
+ for (i=1; i<=length; i++)
+ a[i-1] = (char)(Peek(addr + i) - CHAR_TRANSLATION);
+ a[i-1] = '\0';
return a;
}
@@ -861,13 +945,13 @@ char *Hugo::GetText(long textaddr) {
int tdatal, tdatah, tlen; /* low byte, high byte, length */
- /* Read the string from memory... */
+ /* Read the string from memory... */
if (loaded_in_memory)
{
- tlen = MEM(codeend + textaddr) + MEM(codeend + textaddr + 1) * 256;
- for (i = 0; i<tlen; i++)
+ tlen = MEM(codeend+textaddr) + MEM(codeend+textaddr+1)*256;
+ for (i=0; i<tlen; i++)
{
- g[i] = (char)(MEM(codeend + textaddr + 2 + i) - CHAR_TRANSLATION);
+ g[i] = (char)(MEM(codeend+textaddr+2+i) - CHAR_TRANSLATION);
}
g[i] = '\0';
@@ -875,17 +959,17 @@ char *Hugo::GetText(long textaddr) {
}
/* ...Or load the string from disk */
- if (game->seek(codeend + textaddr)) FatalError(READ_E);
+ if (hugo_fseek(game, codeend+textaddr, SEEK_SET)) FatalError(READ_E);
- tdatal = game->readByte();
- tdatah = game->readByte();
- if (tdatal == EOF || tdatah == EOF || game->err()) FatalError(READ_E);
+ tdatal = hugo_fgetc(game);
+ tdatah = hugo_fgetc(game);
+ if (tdatal==EOF || tdatah==EOF || hugo_ferror(game)) FatalError(READ_E);
tlen = tdatal + tdatah * 256;
- for (i = 0; i<tlen; i++)
+ for (i=0; i<tlen; i++)
{
- if ((a = game->readByte()) == EOF) FatalError(READ_E);
+ if ((a = hugo_fgetc(game))==EOF) FatalError(READ_E);
g[i] = (char)(a - CHAR_TRANSLATION);
}
g[i] = '\0';
@@ -899,13 +983,13 @@ char *Hugo::GetWord(unsigned int w) {
a = w;
- if (a == 0) return "";
+ if (a==0) return "";
- if (a == PARSE_STRING_VAL) return parseerr;
- if (a == SERIAL_STRING_VAL) return serial;
+ if (a==PARSE_STRING_VAL) return parseerr;
+ if (a==SERIAL_STRING_VAL) return serial;
/* bounds-checking to avoid some sort of memory arena error */
- if ((long)(a + dicttable * 16L) > codeend)
+ if ((long)(a+dicttable*16L) > codeend)
{
b = "";
return b;
@@ -922,7 +1006,7 @@ void Hugo::HandleTailRecursion(long addr) {
codeptr = addr;
/* Set up proper default return value for property or routine */
- if (tail_recursion == TAIL_RECURSION_PROPERTY)
+ if (tail_recursion==TAIL_RECURSION_PROPERTY)
ret = 1;
else
ret = 0;
@@ -930,19 +1014,19 @@ void Hugo::HandleTailRecursion(long addr) {
/* Unstack until we get to any routine call that got us here */
while (stack_depth)
{
- if (code_block[stack_depth].type == RUNROUTINE_BLOCK)
+ if (code_block[stack_depth].type==RUNROUTINE_BLOCK)
break;
stack_depth--;
}
#ifdef DEBUGGER
- currentroutine = (unsigned int)(codeptr / address_scale);
- call[window[VIEW_CALLS].count - 1].addr = currentroutine;
- call[window[VIEW_CALLS].count - 1].param = true;
+ currentroutine = (unsigned int)(codeptr/address_scale);
+ call[window[VIEW_CALLS].count-1].addr = currentroutine;
+ call[window[VIEW_CALLS].count-1].param = true;
sprintf(debug_line, "Calling: %s", RoutineName(currentroutine));
/* Don't duplicate blank separator line in code window */
- if (codeline[window[CODE_WINDOW].count - 1][0] != 0)
+ if (codeline[window[CODE_WINDOW].count-1][0] != 0)
AddStringtoCodeWindow("");
AddStringtoCodeWindow(debug_line);
@@ -966,27 +1050,27 @@ void Hugo::InitGame() {
context_commands = 0;
#endif
game_reset = false;
-
+
SetStackFrame(stack_depth, RUNROUTINE_BLOCK, 0, 0);
/* Figure out which objects have either a noun or an adjective property;
- store it in obj_parselist, one bit per object */
- if ((!obj_parselist) && (obj_parselist = (char *)hugo_blockalloc(sizeof(char)*((objects + 7) / 8))))
+ store it in obj_parselist, one bit per object */
+ if ((!obj_parselist) && (obj_parselist = (char *)hugo_blockalloc(sizeof(char)*((objects+7)/8))))
{
-
- for (i = 0; i<objects; i++)
+
+ for (i=0; i<objects; i++)
{
- if (i % 8 == 0) obj_parselist[i / 8] = 0;
-
+ if (i%8==0) obj_parselist[i/8] = 0;
+
if (PropAddr(i, adjective, 0) || PropAddr(i, noun, 0))
- obj_parselist[i / 8] |= 1 << (i % 8);
+ obj_parselist[i/8] |= 1 << (i%8);
else
- obj_parselist[i / 8] &= ~(1 << (i % 8));
+ obj_parselist[i/8] &= ~(1 << (i%8));
}
}
-
+
#if defined (DEBUGGER)
- for (i = 0; i<MAXLOCALS; i++) strcpy(localname[i], "");
+ for (i=0; i<MAXLOCALS; i++) strcpy(localname[i], "");
window[VIEW_LOCALS].count = current_locals = 0;
PassLocals(0);
@@ -1010,85 +1094,135 @@ void Hugo::LoadGame() {
#ifndef LOADGAMEDATA_REPLACED
long c;
#endif
- game = &_gameFile;
- filelength = game->size();
- game->seek(0);
- if (game->err()) FatalError(READ_E);
- if ((game_version = game->readByte()) == EOF) FatalError(OPEN_E);
+#if defined (DEBUGGER)
+ if (!strcmp(gamefile, ""))
+ {
+ game = NULL;
+ strcpy(gamefile, "(no file)");
+ return;
+ }
+#endif
+
+#if !defined (GLK) /* since in Glk the game stream is always open */
+ if ((game = TrytoOpen(gamefile, "rb", "games"))==NULL)
+ {
+ if ((game = TrytoOpen(gamefile, "rb", "object"))==NULL)
+ FatalError(OPEN_E);
+ }
+#endif
+
+ hugo_fseek(game, 0, SEEK_END);
+ filelength = hugo_ftell(game);
+ hugo_fseek(game, 0, SEEK_SET);
+
+ if (hugo_ferror(game)) FatalError(READ_E);
+ if ((game_version = hugo_fgetc(game))==EOF) FatalError(OPEN_E);
/* Earlier versions of the compiler wrote the version code as
- 1 or 2 instead of 10 or 20.
+ 1 or 2 instead of 10 or 20.
*/
- if (game_version == 1 || game_version == 2)
- game_version *= 10;
+ if (game_version==1 || game_version==2)
+ game_version*=10;
if (game_version < 21) object_size = 12;
if (game_version < 31) address_scale = 4;
- check_version = HEVERSION * 10 + HEREVISION;
+ check_version = HEVERSION*10 + HEREVISION;
+#if defined (COMPILE_V25)
+ if (check_version==25 && (game_version>=30 && game_version<=39))
+ check_version = game_version;
+#endif
defseg = gameseg;
if (game_version < HEVERSION)
{
+#if defined (DEBUGGER)
+ hugo_cleanup_screen();
+ hugo_clearfullscreen();
+#endif
sprintf(line, "Hugo Compiler v%d.%d or later required.\n", HEVERSION, HEREVISION);
if (game_version>0)
- sprintf(line + strlen(line), "File \"%s\" is v%d.%d.\n", gamefile, game_version / 10, game_version % 10);
+ sprintf(line+strlen(line), "File \"%s\" is v%d.%d.\n", gamefile, game_version/10, game_version%10);
- error(line);
+#if defined (DEBUGGER_PRINTFATALERROR)
+ DEBUGGER_PRINTFATALERROR(line);
+#else
+ //debug("%s", line);
+#endif
+ hugo_closefiles();
+ hugo_blockfree(mem);
+ mem = NULL;
+
+ hugo_exit(line);
}
else if (game_version > check_version)
{
- error("File \"%s\" is incorrect or unknown version.\n", gamefile);
+#if defined (DEBUGGER)
+ hugo_cleanup_screen();
+ hugo_clearfullscreen();
+#endif
+ sprintf(line, "File \"%s\" is incorrect or unknown version.\n", gamefile);
+
+#if defined (DEBUGGER_PRINTFATALERROR)
+ DEBUGGER_PRINTFATALERROR(line);
+#else
+ //debug("%s", line);
+#endif
+ hugo_closefiles();
+ hugo_blockfree(mem);
+ mem = NULL;
+ hugo_exit(line); /* ditto */
}
- hugo_settextpos(1, physical_windowheight / lineheight);
+ hugo_settextpos(1, physical_windowheight/lineheight);
- if (game_version >= 25)
- game->seek(H_TEXTBANK, SEEK_SET);
+ if (game_version>=25)
+ hugo_fseek(game, H_TEXTBANK, SEEK_SET);
else
/* Because pre-v2.5 didn't have performaddr in the header */
- game->seek(H_TEXTBANK - 2L, SEEK_SET);
+ hugo_fseek(game, H_TEXTBANK-2L, SEEK_SET);
- data = game->readByte();
- textbank = game->readByte();
- if (data == EOF || textbank == EOF || game->err()) FatalError(READ_E);
- textbank = (textbank * 256L + (long)data) * 16L;
+ data = hugo_fgetc(game);
+ textbank = hugo_fgetc(game);
+ if (data==EOF || textbank==EOF || hugo_ferror(game)) FatalError(READ_E);
+ textbank = (textbank*256L + (long)data) * 16L;
codeend = textbank;
/* Use a 1024-byte read block */
ccount = 1024;
- if (game->seek(0, SEEK_SET)) FatalError(READ_E);
+ if (hugo_fseek(game, 0, SEEK_SET)) FatalError(READ_E);
#ifndef LOADGAMEDATA_REPLACED
/* Allocate as much memory as is required */
- if ((!loaded_in_memory) || (mem = (unsigned char *)hugo_blockalloc(filelength)) == nullptr)
+ if ((!loaded_in_memory) || (mem = (unsigned char *)hugo_blockalloc(filelength))==NULL)
{
loaded_in_memory = 0;
- if ((mem = (unsigned char *)hugo_blockalloc(codeend)) == nullptr)
+ if ((mem = (unsigned char *)hugo_blockalloc(codeend))==NULL)
FatalError(MEMORY_E);
}
c = 0;
/* Load either the entire file or just up to the start of the
- text bank
+ text bank
*/
- while (c < (loaded_in_memory ? filelength : codeend))
+ while (c < (loaded_in_memory ? filelength:codeend))
{
/* Complicated, but basically just makes sure that
- the last read (whether loaded_in_memory or not)
- doesn't override the end of the file. Shouldn't
- normally be a problem for fread(), but it caused
- a crash under MSVC++.
+ the last read (whether loaded_in_memory or not)
+ doesn't override the end of the file. Shouldn't
+ normally be a problem for fread(), but it caused
+ a crash under MSVC++.
*/
- i = game->read((unsigned char *)&mem[c],
- (loaded_in_memory) ?
- ((filelength - c>(long)ccount) ? ccount : (size_t)(filelength - c)) :
- ((codeend - c>(long)ccount) ? ccount : (size_t)(codeend - c)));
+ i = hugo_fread((unsigned char *)&mem[c], sizeof(unsigned char),
+ (loaded_in_memory)?
+ ((filelength-c>(long)ccount)?ccount:(size_t)(filelength-c)):
+ ((codeend-c>(long)ccount)?ccount:(size_t)(codeend-c)),
+ game);
if (!i) break;
c += i;
@@ -1097,36 +1231,36 @@ void Hugo::LoadGame() {
if (!LoadGameData(false)) FatalError(READ_E);
#endif
- if (game->err()) FatalError(READ_E);
+ if (hugo_ferror(game)) FatalError(READ_E);
defseg = gameseg;
/* Read header: */
id[0] = Peek(H_ID);
- id[1] = Peek(H_ID + 1);
+ id[1] = Peek(H_ID+1);
id[2] = '\0';
- for (i = 0; i<8; i++)
- serial[i] = Peek(H_SERIAL + i);
+ for (i=0; i<8; i++)
+ serial[i] = Peek(H_SERIAL+i);
serial[8] = '\0';
- codestart = PeekWord(H_CODESTART);
- objtable = PeekWord(H_OBJTABLE) + gameseg;
- proptable = PeekWord(H_PROPTABLE) + gameseg;
+ codestart = PeekWord(H_CODESTART);
+ objtable = PeekWord(H_OBJTABLE) + gameseg;
+ proptable = PeekWord(H_PROPTABLE) + gameseg;
eventtable = PeekWord(H_EVENTTABLE) + gameseg;
arraytable = PeekWord(H_ARRAYTABLE) + gameseg;
- dicttable = PeekWord(H_DICTTABLE) + gameseg;
- syntable = PeekWord(H_SYNTABLE) + gameseg;
+ dicttable = PeekWord(H_DICTTABLE) + gameseg;
+ syntable = PeekWord(H_SYNTABLE) + gameseg;
- initaddr = PeekWord(H_INIT);
- mainaddr = PeekWord(H_MAIN);
- parseaddr = PeekWord(H_PARSE);
+ initaddr = PeekWord(H_INIT);
+ mainaddr = PeekWord(H_MAIN);
+ parseaddr = PeekWord(H_PARSE);
parseerroraddr = PeekWord(H_PARSEERROR);
findobjectaddr = PeekWord(H_FINDOBJECT);
- endgameaddr = PeekWord(H_ENDGAME);
- speaktoaddr = PeekWord(H_SPEAKTO);
- performaddr = PeekWord(H_PERFORM);
+ endgameaddr = PeekWord(H_ENDGAME);
+ speaktoaddr = PeekWord(H_SPEAKTO);
+ performaddr = PeekWord(H_PERFORM);
/* Read totals: */
@@ -1151,43 +1285,163 @@ void Hugo::LoadGame() {
{
data = FindWord("(display)");
- for (i = 0; i<objects; i++)
+ for (i=0; i<objects; i++)
{
- if (GetProp(i, 0, 1, true) == data)
+ if (GetProp(i, 0, 1, true)==data)
{
display_object = i;
break;
}
}
}
-
+
/* build punctuation string (additional user-specified punctuation) */
synptr = 2;
strcpy(punc_string, "");
- for (i = 1; i <= syncount; i++)
+ for (i=1; i<=syncount; i++)
{
defseg = syntable;
- if (Peek(synptr) == 3) /* 3 = punctuation */
+ if (Peek(synptr)==3) /* 3 = punctuation */
{
- strcpy(line, GetWord(PeekWord(synptr + 1)));
+ strcpy(line, GetWord(PeekWord(synptr+1)));
if (strlen(line) + strlen(punc_string) > 63) break;
strcat(punc_string, line);
}
- synptr += 5;
+ synptr+=5;
+ }
+}
+
+#if !defined (GLK) /* ParseCommandLine() is omitted for Glk */
+
+signed char def_fcolor = DEF_FCOLOR;
+signed char def_bgcolor = DEF_BGCOLOR;
+signed char def_slfcolor = DEF_SLFCOLOR;
+signed char def_slbgcolor = DEF_SLBGCOLOR;
+
+void ParseCommandLine(int argc, char *argv[])
+{
+ char drive[MAXDRIVE], dir[MAXDIR], fname[MAXFILENAME], ext[MAXEXT];
+ char* game_file_arg = NULL;
+
+#if defined(GCC_UNIX) && defined(DO_COLOR)
+ int ch;
+ /* Parse comand line options (colour switches) */
+ while ((ch = getopt(argc, argv, "f:b:F:B:?h")) != -1) {
+ switch (ch) {
+ case 'f':
+ def_fcolor = atoi(optarg);
+ break;
+ case 'b':
+ def_bgcolor = atoi(optarg);
+ break;
+ case 'F':
+ def_slfcolor = atoi(optarg);
+ break;
+ case 'B':
+ def_slbgcolor = atoi(optarg);
+ break;
+ case 'h':
+ case '?':
+ default:
+ Banner();
+ if (mem) hugo_blockfree(mem);
+ mem = NULL;
+ exit(0);
+ }
+ }
+ if ( optind < argc ) {
+ game_file_arg = argv[optind];
+ }
+#else
+ if (argc>1) {
+ game_file_arg = argv[1];
}
+#endif
+
+ if (game_file_arg==NULL)
+ {
+ Banner();
+ if (mem) hugo_blockfree(mem);
+ mem = NULL;
+ exit(0);
+ }
+
+ hugo_splitpath(game_file_arg, drive, dir, fname, ext);
+
+ if (strcmp(ext, ""))
+ strcpy(gamefile, game_file_arg);
+ else
+ hugo_makepath(gamefile, drive, dir, fname,
+#if defined (DEBUGGER)
+ "hdx");
+#else
+ "hex");
+#endif
+
+ if (getenv("HUGO_SAVE"))
+ hugo_makepath(savefile, "", getenv("HUGO_SAVE"), fname, "sav");
+ else
+ hugo_makepath(savefile, drive, dir, fname, "sav");
+
+ if (getenv("HUGO_RECORD"))
+ hugo_makepath(recordfile, "", getenv("HUGO_RECORD"), fname, "rec");
+ else
+ hugo_makepath(recordfile, drive, dir, fname, "rec");
+
+ strcpy(scriptfile, DEF_PRN);
+
+ hugo_makepath(gamepath, drive, dir, "", "");
}
+#endif /* GLK */
+
void Hugo::PassLocals(int n) {
int i;
- for (i = 0; i<MAXLOCALS; i++)
+ for (i=0; i<MAXLOCALS; i++)
{
- var[MAXGLOBALS + i] = passlocal[i];
+ var[MAXGLOBALS+i] = passlocal[i];
passlocal[i] = 0;
}
arguments_passed = n;
}
+#ifdef NO_INLINE_MEM_FUNCTIONS
+
+/* PEEK */
+
+unsigned char Peek(long a)
+{
+ return MEM(defseg * 16L + a);
+}
+
+
+/* PEEKWORD */
+
+unsigned int PeekWord(long a)
+{
+ return (unsigned char)MEM(defseg*16L+a) + (unsigned char)MEM(defseg*16L+a+1)*256;
+}
+
+
+/* POKE */
+
+void Poke(unsigned int a, unsigned char v)
+{
+ SETMEM(defseg * 16L + a, v);
+}
+
+
+/* POKEWORD */
+
+void PokeWord(unsigned int a, unsigned int v)
+{
+ SETMEM(defseg * 16L + a, (char)(v%256));
+ SETMEM(defseg * 16L + a + 1, (char)(v/256));
+}
+
+#endif /* NO_INLINED_MEM_FUNCTIONS */
+
const char *Hugo::PrintHex(long a) {
static char hex[7];
int h = 0;
@@ -1202,12 +1456,12 @@ const char *Hugo::PrintHex(long a) {
if (a < 256L) hex[h++] = '0';
if (a < 16L) hex[h++] = '0';
- sprintf(hex + h, "%lX", a);
+ sprintf(hex+h, "%lX", a);
return hex;
}
-void Hugo::Printout(char *a) {
+void Hugo::Printout(char *a, int no_scrollback_linebreak) {
char b[2], sticky = 0, trimmed = 0;
char tempfcolor;
int i, l;
@@ -1217,20 +1471,20 @@ void Hugo::Printout(char *a) {
/* hugo_font() should do this if necessary, but just in case */
if (lineheight < FIXEDLINEHEIGHT)
lineheight = FIXEDLINEHEIGHT;
-
+
tempfcolor = fcolor;
/* The before-check of the linecount: */
if (full)
{
/* -1 here since it's before printing */
- if (full >= physical_windowheight / lineheight - 1)
+ if (full >= physical_windowheight/lineheight-1)
PromptMore();
}
- if ((a[0] != '\0') && a[strlen(a) - 1] == (char)NO_NEWLINE)
+ if ((a[0]!='\0') && a[strlen(a)-1]==(char)NO_NEWLINE)
{
- a[strlen(a) - 1] = '\0';
+ a[strlen(a)-1] = '\0';
sticky = true;
}
@@ -1238,19 +1492,19 @@ void Hugo::Printout(char *a) {
/* The easy part is just skimming <a> and processing each code
- or printed character, as the case may be:
+ or printed character, as the case may be:
*/
-
+
l = 0; /* physical length of string */
- for (i = 0; i<(int)strlen(a); i++)
+ for (i=0; i<(int)strlen(a); i++)
{
- if ((a[i] == ' ') && !trimmed && currentpos == 0)
+ if ((a[i]==' ') && !trimmed && currentpos==0)
{
continue;
}
- if ((unsigned char)a[i] > ' ' || a[i] == FORCED_SPACE)
+ if ((unsigned char)a[i] > ' ' || a[i]==FORCED_SPACE)
{
trimmed = true;
last_printed_font = currentfont;
@@ -1258,55 +1512,55 @@ void Hugo::Printout(char *a) {
switch (b[0] = a[i])
{
- case FONT_CHANGE:
- n = (int)(a[++i] - 1);
- if (currentfont != n)
- hugo_font(currentfont = n);
- break;
+ case FONT_CHANGE:
+ n = (int)(a[++i]-1);
+ if (currentfont != n)
+ hugo_font(currentfont = n);
+ break;
- case COLOR_CHANGE:
- fcolor = (char)(a[++i] - 1);
- hugo_settextcolor((int)fcolor);
- hugo_setbackcolor((int)(a[++i] - 1));
- hugo_font(currentfont);
- break;
+ case COLOR_CHANGE:
+ fcolor = (char)(a[++i]-1);
+ hugo_settextcolor((int)fcolor);
+ hugo_setbackcolor((int)(a[++i]-1));
+ hugo_font(currentfont);
+ break;
- default:
- if (b[0] == FORCED_SPACE) b[0] = ' ';
- l += hugo_charwidth(b[0]);
+ default:
+ if (b[0]==FORCED_SPACE) b[0] = ' ';
+ l += hugo_charwidth(b[0]);
- /* A minor adjustment for font changes and RunWindow() to make
- sure we're not printing unnecessarily downscreen
- */
- if ((just_left_window) && current_text_y > physical_windowbottom - lineheight)
- {
- current_text_y = physical_windowbottom - lineheight;
- }
- just_left_window = false;
+ /* A minor adjustment for font changes and RunWindow() to make
+ sure we're not printing unnecessarily downscreen
+ */
+ if ((just_left_window) && current_text_y > physical_windowbottom-lineheight)
+ {
+ current_text_y = physical_windowbottom-lineheight;
+ }
+ just_left_window = false;
- hugo_print(b);
+ hugo_print(b);
}
- if (script && (unsigned char)b[0] >= ' ')
- script->putBuffer(b, strlen(b));
+ if (script && (unsigned char)b[0]>=' ')
+ if (hugo_writetoscript(b) < 0) FatalError(WRITE_E);
#if defined (SCROLLBACK_DEFINED)
- if (!inwindow && (unsigned char)b[0] >= ' ')
+ if (!inwindow && (unsigned char)b[0]>=' ')
{
#ifdef USE_SMARTFORMATTING
/* Undo smart-formatting for ASCII scrollback */
switch ((unsigned char)b[0])
{
- case 151:
- hugo_sendtoscrollback("--");
- continue;
- case 145:
- case 146:
- b[0] = '\'';
- break;
- case 147:
- case 148:
- b[0] = '\"';
+ case 151:
+ hugo_sendtoscrollback("--");
+ continue;
+ case 145:
+ case 146:
+ b[0] = '\'';
+ break;
+ case 147:
+ case 148:
+ b[0] = '\"';
}
#endif
hugo_sendtoscrollback(b);
@@ -1315,37 +1569,37 @@ void Hugo::Printout(char *a) {
}
/* If we've got a linefeed and didn't hit the right edge of the
- window
+ window
*/
#ifdef NO_TERMINAL_LINEFEED
if (!sticky)
#else
- if (!sticky && currentpos + l < physical_windowwidth)
+ if (!sticky && currentpos+l < physical_windowwidth)
#endif
{
/* The background color may have to be temporarily set if we're
- not in a window--the reason is that full lines of the
- current background color might be printed by the OS-specific
- scrolling function. (This behavior is overridden by the
- Hugo Engine for in-window printing, which always adds new
- lines in the current background color when scrolling.)
+ not in a window--the reason is that full lines of the
+ current background color might be printed by the OS-specific
+ scrolling function. (This behavior is overridden by the
+ Hugo Engine for in-window printing, which always adds new
+ lines in the current background color when scrolling.)
*/
- hugo_setbackcolor((inwindow) ? bgcolor : default_bgcolor);
+ hugo_setbackcolor((inwindow)?bgcolor:default_bgcolor);
hugo_print("\r");
i = currentfont;
hugo_font(currentfont = last_printed_font);
#ifndef GLK
- if (currentline > physical_windowheight / lineheight)
+ if (currentline > physical_windowheight/lineheight)
{
- int full_limit = physical_windowheight / lineheight;
+ int full_limit = physical_windowheight/lineheight;
hugo_scrollwindowup();
if ((current_text_y)
- && full >= full_limit - 3
- && physical_windowbottom - current_text_y - lineheight > lineheight / 2)
+ && full >= full_limit-3
+ && physical_windowbottom-current_text_y-lineheight > lineheight/2)
{
PromptMore();
}
@@ -1353,7 +1607,7 @@ void Hugo::Printout(char *a) {
}
/* Don't scroll single-line windows before PromptMore() */
- else if (physical_windowheight / lineheight > 1)
+ else if (physical_windowheight/lineheight > 1)
#endif
{
hugo_print("\n");
@@ -1379,96 +1633,230 @@ void Hugo::Printout(char *a) {
}
/* Otherwise, take care of all the line-feeding, line-counting,
- etc.
+ etc.
*/
else
{
currentpos = 0;
- if (currentline++ > physical_windowheight / lineheight)
- currentline = physical_windowheight / lineheight;
+ if (currentline++ > physical_windowheight/lineheight)
+ currentline = physical_windowheight/lineheight;
if (!playback) skipping_more = false;
++full;
-
+
/* The after-check of the linecount: */
- if ((full) && full >= physical_windowheight / lineheight)
+ if ((full) && full >= physical_windowheight/lineheight)
{
PromptMore();
}
- if (script)
+ if (script && !no_scrollback_linebreak)
{
- script->putBuffer("\n", 1);
+ if (hugo_writetoscript("\n")<0) FatalError(WRITE_E);
}
#if defined (SCROLLBACK_DEFINED)
- if (!inwindow) hugo_sendtoscrollback("\n");
+ if (!inwindow && !no_scrollback_linebreak) hugo_sendtoscrollback("\n");
#endif
}
fcolor = tempfcolor;
}
-int Hugo::RecordCommands() {
- remaining = 0;
+#ifndef PROMPTMORE_REPLACED
+
+void Hugo::PromptMore() {
+ char temp_during_player_input;
+ int k, tempcurrentfont;
+ int temp_current_text_y = current_text_y;
+
+ if (playback && skipping_more)
+ {
+ full = 0;
+ return;
+ }
skipping_more = false;
+
+ /* Clear the key buffer */
+ while (hugo_iskeywaiting()) hugo_getkey();
- switch (Peek(codeptr))
+ temp_during_player_input = during_player_input;
+ during_player_input = false;
+
+ tempcurrentfont = currentfont;
+ hugo_font(currentfont = NORMAL_FONT);
+
+ hugo_settextpos(1, physical_windowheight/lineheight);
+
+#ifdef NO_TERMINAL_LINEFEED
+ /* For ports where it's possible, do a better "MORE..." prompt
+ without a flashing caret */
+ if (default_bgcolor!=DEF_SLBGCOLOR)
{
- case RECORDON_T:
+ /* system statusline colors */
+ hugo_settextcolor(DEF_SLFCOLOR);
+ hugo_setbackcolor(DEF_SLBGCOLOR);
+ }
+ else
{
- if (!record && !playback)
- {
- /* Glk implementation */
- frefid_t fref = nullptr;
+ /* system colors */
+ if (DEF_FCOLOR < 8)
+ hugo_settextcolor(DEF_FCOLOR+8); /* bright */
+ else
+ hugo_settextcolor(DEF_FCOLOR);
+ hugo_setbackcolor(DEF_BGCOLOR);
+ }
- fref = glk_fileref_create_by_prompt(fileusage_Transcript | fileusage_TextMode,
- filemode_Write, 0);
- record = glk_stream_open_file(fref, filemode_Write, 0);
- glk_fileref_destroy(fref);
- if (!record)
- return 0;
+ if (current_text_y)
+ current_text_y = physical_windowbottom - lineheight;
- return 1;
- }
- break;
+ /* Make sure we fit in a window */
+ if (physical_windowwidth/FIXEDCHARWIDTH >= 19)
+ hugo_print(" [MORE...] ");
+ else
+ hugo_print("[MORE...]");
+
+ if (!inwindow)
+ hugo_setbackcolor(default_bgcolor);
+ else
+ hugo_setbackcolor(bgcolor);
+
+ /* Note that hugo_iskeywaiting() must flush the printing buffer,
+ if one is being employed */
+ while (!hugo_iskeywaiting())
+ {
+ hugo_timewait(100);
}
- case RECORDOFF_T:
+ k = hugo_waitforkey();
+
+#else
+ /* The normal, with-caret way of doing it */
+ /* system colors */
+ hugo_settextcolor(16); /* DEF_FCOLOR); */
+ hugo_setbackcolor(17); /* DEF_BGCOLOR); */
+ hugo_print("[MORE...]");
+
+ k = hugo_waitforkey();
+
+ if (!inwindow)
+ hugo_setbackcolor(default_bgcolor);
+ else
+ hugo_setbackcolor(bgcolor);
+#endif
+
+ if (playback && k==27) /* if ESC is pressed during playback */
{
- if (playback) return 1;
+ if (hugo_fclose(playback))
+ FatalError(READ_E);
+ playback = NULL;
+ }
+ else if (playback && k=='+')
+ skipping_more = true;
+
+ hugo_settextpos(1, physical_windowheight/lineheight);
+#ifdef NO_TERMINAL_LINEFEED
+ current_text_y = physical_windowbottom - lineheight;
+ /* Make sure we fit in a window */
+ if (physical_windowwidth/FIXEDCHARWIDTH >= 19)
+ hugo_print(" ");
+ else
+ hugo_print(" ");
+#else
+ hugo_print(" ");
+#endif
+ hugo_font(currentfont = tempcurrentfont);
- if (record)
+ hugo_settextpos(1, physical_windowheight/lineheight);
+ current_text_y = temp_current_text_y;
+ full = 0;
+
+ hugo_settextcolor(fcolor);
+ hugo_setbackcolor(bgcolor);
+
+ during_player_input = temp_during_player_input;
+}
+
+#endif /* ifndef PROMPTMORE_REPLACED */
+
+int Hugo::RecordCommands() {
+ remaining = 0;
+ skipping_more = false;
+
+ switch (Peek(codeptr))
+ {
+ case RECORDON_T:
{
- delete record;
- record = nullptr;
- return 1;
+ if (!record && !playback)
+ {
+#if !defined (GLK)
+ /* stdio implementation */
+ hugo_getfilename("for command recording", recordfile);
+ if (!strcmp(line, ""))
+ return 0;
+ if (!hugo_overwrite(line))
+ return 0;
+ if (!(record = HUGO_FOPEN(line, "wt")))
+ return 0;
+ strcpy(recordfile, line);
+#else
+ /* Glk implementation */
+ frefid_t fref = NULL;
+
+ fref = glk_fileref_create_by_prompt(fileusage_Transcript | fileusage_TextMode,
+ filemode_Write, 0);
+ record = glk_stream_open_file(fref, filemode_Write, 0);
+ glk_fileref_destroy(fref);
+ if (!record)
+ return 0;
+#endif
+ return 1;
+ }
+ break;
}
- break;
- }
- case PLAYBACK_T:
- {
- if (!playback)
+ case RECORDOFF_T:
{
- /* Glk implementation */
- frefid_t fref = nullptr;
+ if (playback) return 1;
- fref = glk_fileref_create_by_prompt(fileusage_InputRecord | fileusage_TextMode,
- filemode_Read, 0);
- if (glk_fileref_does_file_exist(fref))
- playback = glk_stream_open_file(fref, filemode_Read, 0);
- else
- playback = nullptr;
- glk_fileref_destroy(fref);
+ if (record)
+ {
+ if (hugo_fclose(record)) return (0);
+
+ record = NULL;
+ return 1;
+ }
+ break;
+ }
+
+ case PLAYBACK_T:
+ {
if (!playback)
- return 0;
+ {
+#if !defined (GLK)
+ /* stdio implementation */
+ hugo_getfilename("for command playback", recordfile);
+ if (!strcmp(line, ""))
+ return 0;
+ if (!(playback = HUGO_FOPEN(line, "rt")))
+ return 0;
+ strcpy(recordfile, line);
+#else
+ /* Glk implementation */
+ frefid_t fref = NULL;
- return 1;
+ fref = glk_fileref_create_by_prompt(fileusage_InputRecord | fileusage_TextMode,
+ filemode_Read, 0);
+ playback = glk_stream_open_file(fref, filemode_Read, 0);
+ glk_fileref_destroy(fref);
+ if (!playback)
+ return 0;
+#endif
+ return 1;
+ }
+ break;
}
- break;
- }
}
return 0;
}
@@ -1485,43 +1873,45 @@ void Hugo::SaveUndo(int a, int b, int c, int d, int e) {
undostack[undoptr][4] = e;
/* Put zeroes at end of this operation in case
- the stack wraps around */
+ the stack wraps around */
tempptr = undoptr;
- if (++undoptr == MAXUNDO) undoptr = 0;
+ if (++undoptr==MAXUNDO) undoptr = 0;
undostack[undoptr][0] = 0;
undostack[undoptr][1] = 0;
undoptr = tempptr;
- if (++undoturn == MAXUNDO) /* turn too complex */
- {
- undoptr = 0;
+ if (++undoturn==MAXUNDO) /* turn too complex */
+ {undoptr = 0;
undoturn = MAXUNDO;
- undoinvalid = 1;
- }
+ undoinvalid = 1;}
- if (++undoptr == MAXUNDO) undoptr = 0;
+ if (++undoptr==MAXUNDO) undoptr = 0;
}
}
void Hugo::SetStackFrame(int depth, int type, long brk, long returnaddr) {
- if (depth == RESET_STACK_DEPTH) stack_depth = 0;
- else if (++stack_depth >= MAXSTACKDEPTH) FatalError(MEMORY_E);
+ if (depth==RESET_STACK_DEPTH) stack_depth = 0;
+ else if (++stack_depth>=MAXSTACKDEPTH) FatalError(MEMORY_E);
code_block[stack_depth].type = type;
code_block[stack_depth].brk = brk;
code_block[stack_depth].returnaddr = returnaddr;
+
+#if defined (DEBUGGER)
+ code_block[stack_depth].dbnest = dbnest;
+#endif
}
void Hugo::SetupDisplay() {
hugo_settextmode();
hugo_settextwindow(1, 1,
- SCREENWIDTH / FIXEDCHARWIDTH, SCREENHEIGHT / FIXEDLINEHEIGHT);
+ SCREENWIDTH/FIXEDCHARWIDTH, SCREENHEIGHT/FIXEDLINEHEIGHT);
last_window_left = 1;
last_window_top = 1;
- last_window_right = SCREENWIDTH / FIXEDCHARWIDTH;
- last_window_bottom = SCREENHEIGHT / FIXEDLINEHEIGHT;
+ last_window_right = SCREENWIDTH/FIXEDCHARWIDTH;
+ last_window_bottom = SCREENHEIGHT/FIXEDLINEHEIGHT;
hugo_settextcolor(16);
hugo_setbackcolor(17);
@@ -1534,225 +1924,272 @@ char Hugo::SpecialChar(const char *a, int *i) {
r = a[*i];
s = r;
- if (r == '\"') return r;
+ if (r=='\"') return r;
/* For a couple of versions, Hugo allowed Inform-style
- punctuation control characters; I don't remember
- exactly why.
+ punctuation control characters; I don't remember
+ exactly why.
*/
if (game_version <= 22)
- if (r == '~' || r == '^') return r;
+ if (r=='~' || r=='^') return r;
- if (r == '(')
- {
- r = a[++*i];
- skipbracket = true;
- }
+ if (r=='(')
+ {r = a[++*i];
+ skipbracket = true;}
switch (r)
{
- case '`': /* accent grave */
- {
- /* Note that the "s = '...'" characters are
- Latin-1 and may not display properly under,
- e.g., DOS */
+ case '`': /* accent grave */
+ {
+ /* Note that the "s = '...'" characters are
+ Latin-1 and may not display properly under,
+ e.g., DOS */
- s = a[++*i];
+ s = a[++*i];
#ifndef NO_LATIN1_CHARSET
- switch (s)
- {
- case 'a': s = (char)0xe0; break; /* ? */
- case 'e': s = (char)0xe8; break; /* ? */
- case 'i': s = (char)0xec; break; /* ? */
- case 'o': s = (char)0xf2; break; /* ? */
- case 'u': s = (char)0xf9; break; /* ? */
- case 'A': s = (char)0xc0; break; /* ? */
- case 'E': s = (char)0xc8; break; /* ? */
- case 'I': s = (char)0xcc; break; /* ? */
- case 'O': s = (char)0xd2; break; /* ? */
- case 'U': s = (char)0xd9; break; /* ? */
- }
+ switch (s)
+ {
+ case 'a': s = (char)0xe0; break;
+ case 'e': s = (char)0xe8; break;
+ case 'i': s = (char)0xec; break;
+ case 'o': s = (char)0xf2; break;
+ case 'u': s = (char)0xf9; break;
+ case 'A': s = (char)0xc0; break;
+ case 'E': s = (char)0xc8; break;
+ case 'I': s = (char)0xcc; break;
+ case 'O': s = (char)0xd2; break;
+ case 'U': s = (char)0xd9; break;
+ }
#endif
- break;
- }
- case '\'': /* accent acute */
- {
- s = a[++*i];
-#ifndef NO_LATIN1_CHARSET
- switch (s)
- {
- case 'a': s = (char)0xe1; break; /* ? */
- case 'e': s = (char)0xe9; break; /* ? */
- case 'i': s = (char)0xed; break; /* ? */
- case 'o': s = (char)0xf3; break; /* ? */
- case 'u': s = (char)0xfa; break; /* ? */
- case 'y': s = (char)0xfd; break;
- case 'A': s = (char)0xc1; break; /* ? */
- case 'E': s = (char)0xc9; break; /* ? */
- case 'I': s = (char)0xcd; break; /* ? */
- case 'O': s = (char)0xd3; break; /* ? */
- case 'U': s = (char)0xda; break; /* ? */
- case 'Y': s = (char)0xdd; break; /* ? */
+ break;
}
-#endif
- break;
- }
- case '~': /* tilde */
- {
- s = a[++*i];
-#ifndef NO_LATIN1_CHARSET
- switch (s)
+ case '\'': /* accent acute */
{
- case 'a': s = (char)0xe3; break; /* ? */
- case 'n': s = (char)0xf1; break; /* ? */
- case 'o': s = (char)0xf5; break; /* ? */
- case 'A': s = (char)0xc3; break; /* ? */
- case 'N': s = (char)0xd1; break; /* ? */
- case 'O': s = (char)0xd5; break; /* ? */
- }
-#endif
- break;
- }
- case '^': /* circumflex */
- {
- s = a[++*i];
+ s = a[++*i];
#ifndef NO_LATIN1_CHARSET
- switch (s)
- {
- case 'a': s = (char)0xe2; break; /* ? */
- case 'e': s = (char)0xea; break; /* ? */
- case 'i': s = (char)0xee; break; /* ? */
- case 'o': s = (char)0xf4; break; /* ? */
- case 'u': s = (char)0xfb; break; /* ? */
- case 'A': s = (char)0xc2; break; /* ? */
- case 'E': s = (char)0xca; break; /* ? */
- case 'I': s = (char)0xce; break; /* ? */
- case 'O': s = (char)0xd4; break; /* ? */
- case 'U': s = (char)0xdb; break; /* ? */
- }
+ switch (s)
+ {
+ case 'a': s = (char)0xe1; break;
+ case 'e': s = (char)0xe9; break;
+ case 'i': s = (char)0xed; break;
+ case 'o': s = (char)0xf3; break;
+ case 'u': s = (char)0xfa; break;
+ case 'y': s = (char)0xfd; break;
+ case 'A': s = (char)0xc1; break;
+ case 'E': s = (char)0xc9; break;
+ case 'I': s = (char)0xcd; break;
+ case 'O': s = (char)0xd3; break;
+ case 'U': s = (char)0xda; break;
+ case 'Y': s = (char)0xdd; break;
+ }
#endif
- break;
- }
- case ':': /* umlaut */
- {
- s = a[++*i];
-#ifndef NO_LATIN1_CHARSET
- switch (s)
- {
- case 'a': s = (char)0xe4; break; /* ? */
- case 'e': s = (char)0xeb; break; /* ? */
- case 'i': s = (char)0xef; break; /* ? */
- case 'o': s = (char)0xf6; break; /* ? */
- case 'u': s = (char)0xfc; break; /* ? */
- /* case 'y': s = (char)0xff; break; */ /* ? */
- case 'A': s = (char)0xc4; break; /* ? */
- case 'E': s = (char)0xcb; break; /* ? */
- case 'I': s = (char)0xcf; break; /* ? */
- case 'O': s = (char)0xd6; break; /* ? */
- case 'U': s = (char)0xdc; break; /* ? */
+ break;
}
+ case '~': /* tilde */
+ {
+ s = a[++*i];
+#ifndef NO_LATIN1_CHARSET
+ switch (s)
+ {
+ case 'a': s = (char)0xe3; break;
+ case 'n': s = (char)0xf1; break;
+ case 'o': s = (char)0xf5; break;
+ case 'A': s = (char)0xc3; break;
+ case 'N': s = (char)0xd1; break;
+ case 'O': s = (char)0xd5; break;
+ }
#endif
- break;
- }
- case ',': /* cedilla */
- {
- s = a[++*i];
+ break;
+ }
+ case '^': /* circumflex */
+ {
+ s = a[++*i];
#ifndef NO_LATIN1_CHARSET
- switch (s)
+ switch (s)
+ {
+ case 'a': s = (char)0xe2; break;
+ case 'e': s = (char)0xea; break;
+ case 'i': s = (char)0xee; break;
+ case 'o': s = (char)0xf4; break;
+ case 'u': s = (char)0xfb; break;
+ case 'A': s = (char)0xc2; break;
+ case 'E': s = (char)0xca; break;
+ case 'I': s = (char)0xce; break;
+ case 'O': s = (char)0xd4; break;
+ case 'U': s = (char)0xdb; break;
+ }
+#endif
+ break;
+ }
+ case ':': /* umlaut */
{
- case 'C': s = (char)0xc7; break; /* ? */
- case 'c': s = (char)0xe7; break; /* ? */
+ s = a[++*i];
+#ifndef NO_LATIN1_CHARSET
+ switch (s)
+ {
+ case 'a': s = (char)0xe4; break;
+ case 'e': s = (char)0xeb; break;
+ case 'i': s = (char)0xef; break;
+ case 'o': s = (char)0xf6; break;
+ case 'u': s = (char)0xfc; break;
+ /* case 'y': s = (char)0xff; break; */
+ case 'A': s = (char)0xc4; break;
+ case 'E': s = (char)0xcb; break;
+ case 'I': s = (char)0xcf; break;
+ case 'O': s = (char)0xd6; break;
+ case 'U': s = (char)0xdc; break;
+ }
+#endif
+ break;
}
+ case ',': /* cedilla */
+ {
+ s = a[++*i];
+#ifndef NO_LATIN1_CHARSET
+ switch (s)
+ {
+ case 'C': s = (char)0xc7; break;
+ case 'c': s = (char)0xe7; break;
+ }
#endif
- break;
- }
- case '<': /* Spanish left quotation marks */
+ break;
+ }
+ case '<': /* Spanish left quotation marks */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xab; /* ? */
+ s = (char)0xab;
#endif
- break;
- case '>': /* Spanish right quotation marks */
+ break;
+ case '>': /* Spanish right quotation marks */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xbb; /* ? */
- break;
+ s = (char)0xbb;
+ break;
#endif
- case '!': /* upside-down exclamation mark */
+ case '!': /* upside-down exclamation mark */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xa1; /* ? */
+ s = (char)0xa1;
#endif
- break;
- case '?': /* upside-down question mark */
+ break;
+ case '?': /* upside-down question mark */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xbf; /* ? */
+ s = (char)0xbf;
#endif
- break;
- case 'a': /* ae ligature */
+ break;
+ case 'a': /* ae ligature */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xe6; ++*i; /* ? */
+ s = (char)0xe6; ++*i;
#else
- s = 'e'; ++*i;
+ s = 'e'; ++*i;
#endif
- break;
- case 'A': /* AE ligature */
+ break;
+ case 'A': /* AE ligature */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xc6; ++*i; /* ? */
+ s = (char)0xc6; ++*i;
#else
- s = 'E'; ++*i;
+ s = 'E'; ++*i;
#endif
- break;
- case 'c': /* cents symbol */
+ break;
+ case 'c': /* cents symbol */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xa2; /* ? */
+ s = (char)0xa2;
#endif
- break;
- case 'L': /* British pound */
+ break;
+ case 'L': /* British pound */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xa3; /* ? */
+ s = (char)0xa3;
#endif
- break;
- case 'Y': /* Japanese Yen */
+ break;
+ case 'Y': /* Japanese Yen */
#ifndef NO_LATIN1_CHARSET
- s = (char)0xa5; /* ? */
+ s = (char)0xa5;
#endif
- break;
- case '-': /* em dash */
+ break;
+ case '-': /* em dash */
#ifndef NO_LATIN1_CHARSET
- /* s = (char)0x97; */ /* ? */
+ /* s = (char)0x97; */
#endif
- break;
- case '#': /* 3-digit decimal code */
- {
- s = (char)((a[++*i] - '0') * 100);
- s += (a[++*i] - '0') * 10;
- s += (a[++*i] - '0');
+ break;
+ case '#': /* 3-digit decimal code */
+ {
+ s = (char)((a[++*i]-'0')*100);
+ s += (a[++*i]-'0')*10;
+ s += (a[++*i]-'0');
#ifdef NO_LATIN1_CHARSET
- if ((unsigned)s>127) s = '?';
+ if ((unsigned)s>127) s = '?';
#endif
- }
+ }
}
if (skipbracket)
{
++*i;
- if (a[*i + 1] == ')')++*i;
- if (s == ')') s = r;
+ if (a[*i+1]==')') ++*i;
+ if (s==')') s = r;
}
return s;
}
+#if !defined (GLK) /* not used for Glk */
+
+HUGO_FILE TrytoOpen(char *f, char *p, char *d)
+{
+ char drive[MAXDRIVE], dir[MAXDIR], fname[MAXFILENAME], ext[MAXEXT];
+ char envvar[32];
+ HUGO_FILE tempfile; char temppath[MAXPATH];
+
+ /* Try to open the given, vanilla filename */
+ if ((strcmp(f, "")) && (tempfile = HUGO_FOPEN(f, p)))
+ {
+ return tempfile;
+ }
+
+ hugo_splitpath(f, drive, dir, fname, ext); /* file to open */
+
+ /* If the given filename doesn't already specify where to find it */
+ if (!strcmp(drive, "") && !strcmp(dir, ""))
+ {
+ /* Check gamefile directory */
+ hugo_makepath(temppath, "", gamepath, fname, ext);
+
+ if ((tempfile = HUGO_FOPEN(temppath, p)))
+ {
+ strcpy(f, temppath); /* the new pathname */
+ return tempfile;
+ }
+
+ /* Check environment variables */
+ strcpy(envvar, "hugo_"); /* the actual var. name */
+ strcat(envvar, d);
+
+ if (getenv(strupr(envvar)))
+ {
+ hugo_makepath(temppath, "", getenv(strupr(envvar)), fname, ext);
+
+ if ((tempfile = HUGO_FOPEN(temppath, p)))
+ {
+ strcpy(f, temppath); /* the new pathname */
+ return tempfile;
+ }
+ }
+ }
+
+ return NULL; /* return NULL if not openable */
+}
+
+#endif /* GLK */
+
int Hugo::Undo() {
int count = 0, n;
int turns, turncount, tempptr;
int obj, prop, attr, v;
unsigned int addr;
- if (--undoptr < 0) undoptr = MAXUNDO - 1;
+ if (--undoptr < 0) undoptr = MAXUNDO-1;
- if (undostack[undoptr][1] != 0)
+ if (undostack[undoptr][1]!=0)
{
/* Get the number of operations to be undone for
- the last turn.
+ the last turn.
*/
if ((turns = undostack[undoptr][1]) >= MAXUNDO)
goto CheckUndoFailed;
@@ -1763,121 +2200,122 @@ int Hugo::Undo() {
tempptr = undoptr;
/* Count the number of operations available to see if there
- are enough to undo the last turn (as per the number
- required in <turns>.
+ are enough to undo the last turn (as per the number
+ required in <turns>.
*/
do
{
- if (--undoptr < 0) undoptr = MAXUNDO - 1;
+ if (--undoptr < 0) undoptr = MAXUNDO-1;
turncount++;
/* if end of turn */
- if (undostack[undoptr][0] == 0)
+ if (undostack[undoptr][0]==0)
break;
- } while (true);
+ }
+ while (true);
if (turncount<turns) goto CheckUndoFailed;
undoptr = tempptr;
- if (--undoptr < 0) undoptr = MAXUNDO - 1;
+ if (--undoptr < 0) undoptr = MAXUNDO-1;
while (undostack[undoptr][0] != 0)
{
switch (undostack[undoptr][0])
{
- case MOVE_T:
- {
- MoveObj(undostack[undoptr][1], undostack[undoptr][2]);
- count++;
- break;
- }
-
- case PROP_T:
- {
- obj = undostack[undoptr][1];
- prop = undostack[undoptr][2];
- n = undostack[undoptr][3];
- v = undostack[undoptr][4];
+ case MOVE_T:
+ {
+ MoveObj(undostack[undoptr][1], undostack[undoptr][2]);
+ count++;
+ break;
+ }
- if ((addr = PropAddr(obj, prop, 0)) != 0)
+ case PROP_T:
{
- defseg = proptable;
+ obj = undostack[undoptr][1];
+ prop = undostack[undoptr][2];
+ n = undostack[undoptr][3];
+ v = undostack[undoptr][4];
- if (n == PROP_ROUTINE)
+ if ((addr = PropAddr(obj, prop, 0))!=0)
{
- Poke(addr + 1, PROP_ROUTINE);
- n = 1;
- }
+ defseg = proptable;
- /* Use this new prop count number if the
- existing one is too low or a prop routine
- */
- else if (Peek(addr + 1) == PROP_ROUTINE || Peek(addr + 1)<(unsigned char)n)
- Poke(addr + 1, (unsigned char)n);
+ if (n==PROP_ROUTINE)
+ {
+ Poke(addr+1, PROP_ROUTINE);
+ n = 1;
+ }
- /* property length */
- if (n <= (int)Peek(addr + 1))
- PokeWord(addr + 2 + (n - 1) * 2, v);
+ /* Use this new prop count number if the
+ existing one is too low or a prop routine
+ */
+ else if (Peek(addr+1)==PROP_ROUTINE || Peek(addr+1)<(unsigned char)n)
+ Poke(addr+1, (unsigned char)n);
+
+ /* property length */
+ if (n<=(int)Peek(addr+1))
+ PokeWord(addr+2+(n-1)*2, v);
+ }
+ count++;
+ break;
}
- count++;
- break;
- }
- case ATTR_T:
- {
- obj = undostack[undoptr][1];
- attr = undostack[undoptr][2];
- n = undostack[undoptr][3];
- SetAttribute(obj, attr, n);
- count++;
- break;
- }
+ case ATTR_T:
+ {
+ obj = undostack[undoptr][1];
+ attr = undostack[undoptr][2];
+ n = undostack[undoptr][3];
+ SetAttribute(obj, attr, n);
+ count++;
+ break;
+ }
- case VAR_T:
- {
- n = undostack[undoptr][1];
- v = undostack[undoptr][2];
- var[n] = v;
- count++;
- break;
- }
+ case VAR_T:
+ {
+ n = undostack[undoptr][1];
+ v = undostack[undoptr][2];
+ var[n] = v;
+ count++;
+ break;
+ }
- case ARRAYDATA_T:
- {
- defseg = arraytable;
- addr = undostack[undoptr][1];
- n = undostack[undoptr][2];
- v = undostack[undoptr][3];
+ case ARRAYDATA_T:
+ {
+ defseg = arraytable;
+ addr = undostack[undoptr][1];
+ n = undostack[undoptr][2];
+ v = undostack[undoptr][3];
/* The array length was already accounted for before calling
- SaveUndo(), so there is no adjustment of
- +2 here.
+ SaveUndo(), so there is no adjustment of
+ +2 here.
*/
- PokeWord(addr + n * 2, v);
- count++;
- break;
- }
+ PokeWord(addr+n*2, v);
+ count++;
+ break;
+ }
- case DICT_T:
- {
- defseg = dicttable;
- PokeWord(0, --dictcount);
- count++;
- break;
- }
- case WORD_T:
- {
- n = undostack[undoptr][1];
- v = undostack[undoptr][2];
- wd[n] = v;
- word[n] = GetWord(wd[n]);
- count++;
- }
+ case DICT_T:
+ {
+ defseg = dicttable;
+ PokeWord(0, --dictcount);
+ count++;
+ break;
+ }
+ case WORD_T:
+ {
+ n = undostack[undoptr][1];
+ v = undostack[undoptr][2];
+ wd[n] = v;
+ word[n] = GetWord(wd[n]);
+ count++;
+ }
}
defseg = gameseg;
- if (--undoptr < 0) undoptr = MAXUNDO - 1;
+ if (--undoptr < 0) undoptr = MAXUNDO-1;
}
}
@@ -1895,5 +2333,50 @@ CheckUndoFailed:
return 1;
}
+/*
+ * Random-number generator replacement by Andrew Plotkin:
+ *
+ */
+
+#if defined (BUILD_RANDOM)
+
+static unsigned int rand_table[55]; /* state for the RNG */
+static int rand_index1, rand_index2;
+
+int random()
+{
+ rand_index1 = (rand_index1 + 1) % 55;
+ rand_index2 = (rand_index2 + 1) % 55;
+ rand_table[rand_index1] = rand_table[rand_index1] - rand_table[rand_index2];
+ return rand_table[rand_index1];
+}
+
+void srandom(int seed)
+{
+ int k = 1;
+ int i, loop;
+
+ rand_table[54] = seed;
+ rand_index1 = 0;
+ rand_index2 = 31;
+
+ for (i = 0; i < 55; i++)
+ {
+ int ii = (21 * i) % 55;
+
+ rand_table[ii] = k;
+ k = seed - k;
+ seed = rand_table[ii];
+ }
+
+ for (loop = 0; loop < 4; loop++)
+ {
+ for (i = 0; i < 55; i++)
+ rand_table[i] = rand_table[i] - rand_table[ (1 + i + 30) % 55];
+ }
+}
+
+#endif /* BUILD_RANDOM */
+
} // End of namespace Hugo
} // End of namespace Glk
diff --git a/engines/glk/hugo/hugo.cpp b/engines/glk/hugo/hugo.cpp
index a5fbdb935f..0fca43222a 100644
--- a/engines/glk/hugo/hugo.cpp
+++ b/engines/glk/hugo/hugo.cpp
@@ -65,9 +65,10 @@ Hugo::Hugo(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gam
arrexpr(0), multiprop(0), set_value(0)
#if defined (DEBUGGER)
, debug_eval(false), debug_eval_error(false), debugger_step_over(false),
- debugger_finish(false), debugger_run(false), currentroutine(false),
- complex_prop_breakpoint(false), trace_complex_prop_routine(false), properties(0),
- current_locals(0)
+ debugger_finish(false), debugger_run(false), debugger_interrupt(false),
+ debugger_skip(false), runtime_error(false), currentroutine(false),
+ complex_prop_breakpoint(false), trace_complex_prop_routine(false), routines(0),
+ properties(0), current_locals(0), this_codeptr(0)
#endif
{
// heexpr
diff --git a/engines/glk/hugo/hugo.h b/engines/glk/hugo/hugo.h
index de64744df6..1f5aaffa3e 100644
--- a/engines/glk/hugo/hugo.h
+++ b/engines/glk/hugo/hugo.h
@@ -220,6 +220,9 @@ private:
bool debugger_step_over;
bool debugger_finish;
bool debugger_run;
+ bool debugger_interrupt;
+ bool debugger_skip;
+ bool runtime_error;
int currentroutine;
bool complex_prop_breakpoint;
bool trace_complex_prop_routine;
@@ -227,11 +230,13 @@ private:
char *propertyname[MAX_PROPERTY];
// CODE code[999];
CALL call[999];
+ int routines;
int properties;
WINDOW window[99];
int codeline[9][100];
char localname[9][100];
int current_locals;
+ long this_codeptr;
#endif
private:
/**
@@ -469,7 +474,9 @@ private:
* Print to client display taking into account cursor relocation,
* font changes, color setting, and window scrolling.
*/
- void Printout(char *a);
+ void Printout(char *a, int no_scrollback_linebreak);
+
+ void PromptMore();
int RecordCommands();
@@ -558,6 +565,12 @@ private:
const char *RoutineName(long loc) { return "Routine"; }
void AddStringtoCodeWindow(const char *str) {}
+
+ void SwitchtoDebugger() {}
+
+ void DebuggerFatal(DEBUGGER_ERROR err) { error("Debugger error"); }
+
+ void RecoverLastGood() {}
#endif
int Child(int obj);
@@ -612,6 +625,42 @@ private:
int Youngest(int obj);
/**@}*/
+
+ /**
+ * \defgroup Miscellaneous
+ * @{
+ */
+
+ int hugo_fseek(Common::SeekableReadStream *s, long int offset, int whence) {
+ return s->seek(offset, whence);
+ }
+
+ int hugo_fgetc(Common::SeekableReadStream *s) {
+ return s->readByte();
+ }
+
+ bool hugo_ferror(Common::SeekableReadStream *s) const {
+ return s->err();
+ }
+
+ long hugo_ftell(Common::SeekableReadStream *s) {
+ return s->pos();
+ }
+
+ int hugo_fclose(strid_t f) {
+ delete f;
+ return 0;
+ }
+
+ void hugo_exit(const char *msg) {
+ error("%s", line);
+ }
+
+ size_t hugo_fread(void *ptr, size_t size, size_t count, Common::SeekableReadStream *s) {
+ return s->read(ptr, size * count);
+ }
+
+ /**@}*/
private:
/**
* Allocate memory block
@@ -651,10 +700,10 @@ public:
void hugo_closefiles() {}
void RunRoutine(long v) {}
unsigned int FindWord(const char *a) { return 0; }
- void PromptMore() {}
void hugo_stopsample() {}
void hugo_stopmusic() {}
int hugo_hasgraphics() { return 0; }
+ int hugo_writetoscript(const char *s) { return 0; }
};
} // End of namespace Hugo
diff --git a/engines/glk/hugo/hugo_defines.h b/engines/glk/hugo/hugo_defines.h
index ce2d0061fd..7809ea19b8 100644
--- a/engines/glk/hugo/hugo_defines.h
+++ b/engines/glk/hugo/hugo_defines.h
@@ -153,6 +153,8 @@ browsing.
#define CODE_WINDOW 2
#endif
+#define PRINTFATALERROR(a) error(a)
+
} // End of namespace Hugo
} // End of namespace Glk
diff --git a/engines/glk/hugo/hugo_types.h b/engines/glk/hugo/hugo_types.h
index 3d7af86894..dacde03d54 100644
--- a/engines/glk/hugo/hugo_types.h
+++ b/engines/glk/hugo/hugo_types.h
@@ -120,6 +120,10 @@ struct CODE_BLOCK {
};
#if defined (DEBUGGER)
+enum DEBUGGER_ERROR {
+ D_MEMORY_ERROR
+};
+
struct CALL {
long addr;
bool param;