! Some utility routines for the DecInf compilator system_file; [ decSaveUndo saveflag; @save_undo saveflag; if(saveflag==2) print "Last turn undone.^"; return saveflag; ]; [ decRestoreUndo saveflag; @restore_undo saveflag; if(saveflag==0) print "Undo failed.^"; return saveflag; ]; [ decSaveGame saveflag; @save -> saveflag; switch (saveflag) { 0: print "Save failed.^"; 1: print "Saved.^"; 2: print "Restored.^"; } return saveflag; ]; [ decRestoreGame; restore restoreOK; print "Load failed.^"; return 0; .restoreOK; quit; ! never reached ]; ! decInitConsoleWindow and decPrintString provides a solution for printing ! backspace on the text output (should delete the last character). Because ofclass ! limitations in the Inform screen model this only works in v6 games. Other versions ! can only set the cursor in window 1, but this window cannot format the text properly. ! ! v6: deletes the character by overwriting the last charachter with a space, and must ! use a fixed width font since we cannot check what was written before. ! other versions: silently ignores backspace. Array pos-->2; Global charWidth; [ decInitConsoleWindow x y w f; #iftrue (#version_number == 6); f=4; ! fixed courier size (to enable backspace) @set_font -> f; @get_cursor pos; w=-3; y=pos-->0; x=pos-->1; print " "; @get_cursor pos; charWidth=pos-->1-x; @set_cursor y x w; #ifnot; x=0; y=0; w=0; f=0; #Message "This is a version 5 story file. Backspaces in the output will be silently removed."; #endif; ]; [ decPrintString str backspaceChar i x y w; for(i=0:i<(str-->0):i++) { if(str->(i+2)==backspaceChar) { #iftrue (#version_number == 6); @get_cursor pos; w=-3; y=pos-->0; x=pos-->1-charWidth; @set_cursor y x w; print " "; @set_cursor y x w; #ifnot; x=0; y=0; w=0; #endif; } else { print (char) str->(i+2); } } return i-2; ]; [ decStrCmp str1 str2; if(str1-->0==0 && str2-->0==0) { return 0; } if(str1-->0==0 && str2-->0~=0) { return 1; } if(str1-->0~=0 && str2-->0==0) { return -1; } return StrCmp(str1, str2); ]; [ decGetChar result backspaceChar pkey; if(backspaceChar==0) backspaceChar=20; ! C64 backspace #ifdef TARGET_ZCODE; @read_char 1 1 Interrupt -> pkey; ! call Interrupt after 10ms if no key pressed #ifnot; pkey=KeyCharPrimitive(); #endif; ! Translate backspace to Basic code if(pkey==8) pkey=backspaceChar; if(pkey==0) { result-->0=0; } else { result-->0=1; result->2=pkey; } return result; ]; [ Interrupt; rtrue; ]; [ decIntAndExpression value bexpr; if(bexpr) return value; return 0; ]; ! SPACE$: create string of spaces [ decSpace str len i; str-->0=len; for(i=0: i(i+2)=32; return str; ]; [ decInstr start str1 str2 x; x=StrStr(str1, str2, start-1); if(x>0) { return x; } return 0; ]; [ decInstr2 str1 str2; return StrStr(str1, str2); ]; ! WriteString that returns the string variable [ decWriteString str1 str2; WriteString(str1, str2); return str1; ]; ! StrCat that returns the concatenated string [ decStrCat str1 str2; StrCat(str1, str2); return str1; ]; ! StrCpy that returns the string [ decStrCpy str1 str2; StrCpy(str1, str2); return str1; ]; [ decAscii str; return str->2; ]; [ decVal str i r; i=2; if(str->i=='-') { i=i+1; } while((i<(str-->0)+2) && (str->i)<='9' && (str->i)>='0') { r=r*10+str->i-'0'; i=i+1; } if(str->2=='-') r=-r; return r; ]; [ decMidString result string start length i; start=start-1; if(length==-1) { length=string-->0-start; } for(i=0: i(i+2)=string->(start+i+2); } result-->0=length; return result; ]; [ decLeftString result string length; StrCpy(result, string); if(length0) { result-->0=length; } return result; ]; [ decRightString result string length i x; x=string-->0-length+2; for(i=0: i(i+2)=string->(i+x); } result-->0=length; return result; ]; ! Dec Basic command ECHO just means "Echo everything the user types to the terminal with this number." ! Not possible and probably not necessary to implement in Inform. [ decEcho parameter; return 0*parameter; ]; [ decAbs i; if(i<0) return -i; return i; ]; [ decStrString result int_value i x; i=2; if(int_value<0) { int_value=-int_value; result->i='-'; i=i+1; } while((int_value/10)>0) { x=int_value/10; result->i='0'+x; int_value=int_value-10*x; i=i+1; } result->i='0'+int_value; i=i+1; result-->0=i-2; return result; ]; [ decTab result int_value; return decSpace(result,int_value); ]; Array s_Date->20; Array s_Time->20; [ decTime result; return decStrCpy(result,s_Time); ]; [ decDate result; return decStrCpy(result,s_Date); ]; [ decChrString result char; result->2=char; result-->0=1; return result; ]; ! TODO [ decCrt arg; return 0*arg; ]; Global sleep_save_cr; Global sleep_timer; [_decSleepTimer; if((--sleep_timer)>0) rfalse; ]; [ decSleep time_in_seconds result; ! print ""; sleep_save_cr=0; input_buffer->0=100; input_buffer->1=0; ! if(sleep_save_cr) rtrue; sleep_timer=time_in_seconds; @aread input_buffer 0 10 _decSleepTimer -> result; sleep_save_cr=result; ! print ""; if(result==0) rfalse; rtrue; ]; Array input_buffer buffer 100; [decInputStr prompt qmark input_var x; if(prompt ofclass String) print (string) prompt; if(qmark) print "? "; input_buffer->0=100; if(sleep_save_cr) jump done; for(x=2:x1+2:x++) print (char) input_buffer->x; #ifdef TARGET_ZCODE; read input_buffer 0; #ifnot; KeyboardPrimitive(input_buffer); #endif; .done; sleep_save_cr=0; x=input_buffer->1; input_buffer-->0=x; StrCpy(input_var,input_buffer); input_buffer->0=100; input_buffer->1=0; ]; #ifdef TARGET_ZCODE; #ifnot; ! ! Copied from Inform 6.10 libraries. ! #Stub InitGlkWindow 1; #Stub HandleGlkEvent 2; Global gg_mainwin = 0; Array gg_event --> 4; Array gg_arguments --> 8; Constant GG_MAINWIN_ROCK 201; Array buff->103; [ initglk; @setiosys 2 0; InitGlkWindow(0); if (gg_mainwin == 0) { if(InitGlkWindow(GG_MAINWIN_ROCK)==0) { gg_mainwin = glk($0023, 0, 0, 0, 3, GG_MAINWIN_ROCK); ! window_open } } if (gg_mainwin == 0) quit; glk($002F, gg_mainwin); ! set_window InitGlkWindow(1); ]; [ KeyCharPrimitive win nostat done res ix jx ch; jx = ch; ! squash compiler warnings if (win == 0) win = gg_mainwin; done = false; glk($00D2, win); ! request_char_event while (~~done) { glk($00C0, gg_event); ! select switch (gg_event-->0) { 5: ! evtype_Arrange if (nostat) { glk($00D3, win); ! cancel_char_event res = $80000000; done = true; break; } 2: ! evtype_CharInput if (gg_event-->1 == win) { res = gg_event-->2; done = true; } } ix = HandleGlkEvent(gg_event, 1, gg_arguments); if (ix == 2) { res = gg_arguments-->0; done = true; } else if (ix == -1) { done = false; } } .KCPContinue; return res; ]; [ KeyboardPrimitive a_buffer done ix; done = false; glk($00D0, gg_mainwin, a_buffer+2, 100, 0); ! request_line_event while (~~done) { glk($00C0, gg_event); ! select switch (gg_event-->0) { 5: ! evtype_Arrange 3: ! evtype_LineInput if (gg_event-->1 == gg_mainwin) { a_buffer-->0 = gg_event-->2; done = true; } } ix = HandleGlkEvent(gg_event, 0, a_buffer); if (ix == 2) { done = true; } else if (ix == -1) { done = false; } } ]; #endif;