diff -c inform63-opcodeg/asm.c inform/asm.c *** inform63-opcodeg/asm.c 2006-10-26 16:08:32.000000000 -0400 --- inform/asm.c 2006-11-04 19:44:05.000000000 -0500 *************** *** 287,292 **** --- 287,294 ---- /* Codes for any unusual operand assembly rules */ + /* Z-code: */ + #define VARIAB 1 /* First operand expected to be a variable name and assembled to a short constant: the variable number */ #define TEXT 2 /* One text operand, to be Z-encoded into the program */ *************** *** 295,300 **** --- 297,306 ---- as long constant (the routine's packed address): as if the name were prefixed by #r$ */ + /* Glulx: (bit flags for Glulx VM features) */ + + #define GOP_Unicode 1 /* uses_unicode_features */ + /* Codes for the number of operands */ #define TWO 1 /* 2 (with certain types of operand, compiled as VAR) */ *************** *** 555,561 **** { (uchar *) "callfi", 0x0161, St, 0, 3 }, { (uchar *) "callfii", 0x0162, St, 0, 4 }, { (uchar *) "callfiii", 0x0163, St, 0, 5 }, ! { (uchar *) "streamunichar", 0x73, 0, 0, 1 }, }; static opcodeg custom_opcode_g; --- 561,567 ---- { (uchar *) "callfi", 0x0161, St, 0, 3 }, { (uchar *) "callfii", 0x0162, St, 0, 4 }, { (uchar *) "callfiii", 0x0163, St, 0, 5 }, ! { (uchar *) "streamunichar", 0x73, 0, GOP_Unicode, 1 }, }; static opcodeg custom_opcode_g; *************** *** 980,986 **** execution_never_reaches_here = ((opco.flags & Rf) != 0); ! if (AI->internal_number == streamunichar_gc) { uses_unicode_features = TRUE; } --- 986,992 ---- execution_never_reaches_here = ((opco.flags & Rf) != 0); ! if (opco.op_rules & GOP_Unicode) { uses_unicode_features = TRUE; } diff -c inform63-opcodeg/directs.c inform/directs.c *** inform63-opcodeg/directs.c 2006-10-26 14:55:45.000000000 -0400 --- inform/directs.c 2006-10-27 17:59:21.000000000 -0400 *************** *** 806,811 **** --- 806,818 ---- AO = parse_expression(CONSTANT_CONTEXT); if (module_switch && (AO.marker != 0)) error("A definite value must be given as version number"); + else + if (glulx_mode) + { + warning("The Version directive does not work in Glulx. Use \ + -vX.Y.Z instead, as either a command-line argument or a header comment."); + break; + } else { i = AO.value; if ((i<3) || (i>8)) diff -c inform63-opcodeg/files.c inform/files.c *** inform63-opcodeg/files.c 2006-10-26 14:56:44.000000000 -0400 --- inform/files.c 2006-11-04 19:43:26.000000000 -0500 *************** *** 477,483 **** static void output_file_g(void) { FILE *fin; char new_name[PATHLEN]; int32 size, i, j; ! int32 val; ASSERT_GLULX(); --- 477,483 ---- static void output_file_g(void) { FILE *fin; char new_name[PATHLEN]; int32 size, i, j; ! int32 VersionNum; ASSERT_GLULX(); *************** *** 499,504 **** --- 499,526 ---- checksum_long = 0; checksum_count = 0; + /* Determine the version number. */ + + VersionNum = 0x00020000; + + /* Increase for various features the game may have used. */ + if (no_unicode_chars != 0 || (uses_unicode_features)) { + VersionNum = 0x00030000; + } + + /* And check if the user has requested a specific version. */ + if (requested_glulx_version) { + if (requested_glulx_version < VersionNum) { + static char error_message_buff[256]; + sprintf(error_message_buff, "Version 0x%08lx requested, but \ + game features require version 0x%08lx", requested_glulx_version, VersionNum); + warning(error_message_buff); + } + else { + VersionNum = requested_glulx_version; + } + } + /* (1) Output the header. We use sf_put here, instead of fputc, because the header is included in the checksum. */ *************** *** 508,521 **** sf_put('u'); sf_put('l'); /* Version number. */ ! if (no_unicode_chars == 0 && (!uses_unicode_features)) ! val = 0x00020000; ! else ! val = 0x00030000; ! sf_put((val >> 24)); ! sf_put((val >> 16)); ! sf_put((val >> 8)); ! sf_put((val)); /* RAMSTART */ sf_put((Write_RAM_At >> 24)); sf_put((Write_RAM_At >> 16)); --- 530,539 ---- sf_put('u'); sf_put('l'); /* Version number. */ ! sf_put((VersionNum >> 24)); ! sf_put((VersionNum >> 16)); ! sf_put((VersionNum >> 8)); ! sf_put((VersionNum)); /* RAMSTART */ sf_put((Write_RAM_At >> 24)); sf_put((Write_RAM_At >> 16)); *************** *** 531,543 **** sf_put((Out_Size >> 16)); sf_put((Out_Size >> 8)); sf_put((Out_Size)); ! /* STACKSIZE, which we guess at 4096. That's about enough for 90 ! nested function calls with 8 locals each -- the same capacity ! as the Z-Spec's suggestion for Z-machine stack size. */ ! sf_put(0x00); ! sf_put(0x00); ! sf_put(0x10); ! sf_put(0x00); /* Initial function to call. Inform sets things up so that this is the start of the executable-code area. */ sf_put((Write_Code_At >> 24)); --- 549,559 ---- sf_put((Out_Size >> 16)); sf_put((Out_Size >> 8)); sf_put((Out_Size)); ! /* STACKSIZE */ ! sf_put((MAX_STACK_SIZE >> 24)); ! sf_put((MAX_STACK_SIZE >> 16)); ! sf_put((MAX_STACK_SIZE >> 8)); ! sf_put((MAX_STACK_SIZE)); /* Initial function to call. Inform sets things up so that this is the start of the executable-code area. */ sf_put((Write_Code_At >> 24)); diff -c inform63-opcodeg/header.h inform/header.h *** inform63-opcodeg/header.h 2006-10-26 14:55:45.000000000 -0400 --- inform/header.h 2006-11-04 19:43:41.000000000 -0500 *************** *** 2285,2290 **** --- 2285,2291 ---- extern int oddeven_packing_switch; extern int glulx_mode, compression_switch; + extern int32 requested_glulx_version; extern int error_format, store_the_text, asm_trace_setting, double_space_setting, trace_fns_setting, character_set_setting, *************** *** 2383,2389 **** extern int32 MAX_STATIC_STRINGS, MAX_ZCODE_SIZE, MAX_LINK_DATA_SIZE, MAX_TRANSCRIPT_SIZE, MAX_INDIV_PROP_TABLE_SIZE, ! MAX_NUM_STATIC_STRINGS, MAX_UNICODE_CHARS; extern int32 MAX_OBJ_PROP_COUNT, MAX_OBJ_PROP_TABLE_SIZE; extern int MAX_LOCAL_VARIABLES, MAX_GLOBAL_VARIABLES; --- 2384,2391 ---- extern int32 MAX_STATIC_STRINGS, MAX_ZCODE_SIZE, MAX_LINK_DATA_SIZE, MAX_TRANSCRIPT_SIZE, MAX_INDIV_PROP_TABLE_SIZE, ! MAX_NUM_STATIC_STRINGS, MAX_UNICODE_CHARS, ! MAX_STACK_SIZE; extern int32 MAX_OBJ_PROP_COUNT, MAX_OBJ_PROP_TABLE_SIZE; extern int MAX_LOCAL_VARIABLES, MAX_GLOBAL_VARIABLES; diff -c inform63-opcodeg/inform.c inform/inform.c *** inform63-opcodeg/inform.c 2006-10-26 14:55:45.000000000 -0400 --- inform/inform.c 2006-10-27 18:04:44.000000000 -0400 *************** *** 24,33 **** /* Version control */ /* ------------------------------------------------------------------------- */ ! /* This stuff is Z-code only, for now. It might handle multiple Glulx ! versions someday, if needed. */ ! ! int version_number, /* 3 to 8 */ instruction_set_number, /* 3 to 6: versions 7 and 8 use instruction set of version 5 */ --- 24,30 ---- /* Version control */ /* ------------------------------------------------------------------------- */ ! int version_number, /* 3 to 8 (Z-code) */ instruction_set_number, /* 3 to 6: versions 7 and 8 use instruction set of version 5 */ *************** *** 35,40 **** --- 32,39 ---- int32 scale_factor, /* packed address multiplier */ length_scale_factor; /* length-in-header multiplier */ + int32 requested_glulx_version; + extern void select_version(int vn) { version_number = vn; extend_memory_map = FALSE; *************** *** 51,56 **** --- 50,80 ---- if ((version_number==7)||(version_number==8)) instruction_set_number = 5; } + static int select_glulx_version(char *str) + { + /* Parse an "X.Y.Z" style version number, and store it for later use. */ + char *cx = str; + int major=0, minor=0, patch=0; + + while (isdigit(*cx)) + major = major*10 + ((*cx++)-'0'); + if (*cx == '.') { + cx++; + while (isdigit(*cx)) + minor = minor*10 + ((*cx++)-'0'); + if (*cx == '.') { + cx++; + while (isdigit(*cx)) + patch = patch*10 + ((*cx++)-'0'); + } + } + + requested_glulx_version = ((major & 0x7FFF) << 16) + + ((minor & 0xFF) << 8) + + (patch & 0xFF); + return (cx - str); + } + /* ------------------------------------------------------------------------- */ /* Target: variables which vary between the Z-machine and Glulx */ /* ------------------------------------------------------------------------- */ *************** *** 250,255 **** --- 274,280 ---- compression_switch = TRUE; glulx_mode = FALSE; + requested_glulx_version = 0; } /* ------------------------------------------------------------------------- */ *************** *** 1237,1243 **** case 's': statistics_switch = state; break; case 't': asm_trace_setting=2; break; case 'u': optimise_switch = state; break; ! case 'v': if ((cmode==0) && (version_set_switch)) { s=2; break; } version_set_switch = TRUE; s=2; switch(p[i+1]) { case '3': select_version(3); break; --- 1262,1269 ---- case 's': statistics_switch = state; break; case 't': asm_trace_setting=2; break; case 'u': optimise_switch = state; break; ! case 'v': if (glulx_mode) { s = select_glulx_version(p+i+1)+1; break; } ! if ((cmode==0) && (version_set_switch)) { s=2; break; } version_set_switch = TRUE; s=2; switch(p[i+1]) { case '3': select_version(3); break; diff -c inform63-opcodeg/memory.c inform/memory.c *** inform63-opcodeg/memory.c 2006-10-26 14:55:45.000000000 -0400 --- inform/memory.c 2006-10-26 16:53:56.000000000 -0400 *************** *** 175,180 **** --- 175,181 ---- int NUM_ATTR_BYTES; int32 MAX_NUM_STATIC_STRINGS; int32 MAX_UNICODE_CHARS; + int32 MAX_STACK_SIZE; /* The way memory sizes are set causes great nuisance for those parameters which have different defaults under Z-code and Glulx. We have to get *************** *** 212,236 **** printf("| %25s = %-7d |\n","MAX_LABELS",MAX_LABELS); printf("| %25s = %-7d |\n","MAX_LINESPACE",MAX_LINESPACE); printf("| %25s = %-7d |\n","MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE); ! printf("| %25s = %-7d |\n","MAX_LOCAL_VARIABLES",MAX_LOCAL_VARIABLES); printf("| %25s = %-7d |\n","MAX_LOW_STRINGS",MAX_LOW_STRINGS); ! printf("| %25s = %-7d |\n","MAX_NUM_STATIC_STRINGS",MAX_NUM_STATIC_STRINGS); printf("| %25s = %-7d |\n","MAX_OBJECTS",MAX_OBJECTS); ! printf("| %25s = %-7d |\n","MAX_OBJ_PROP_COUNT", MAX_OBJ_PROP_COUNT); ! printf("| %25s = %-7d |\n","MAX_OBJ_PROP_TABLE_SIZE", MAX_OBJ_PROP_TABLE_SIZE); printf("| %25s = %-7d |\n","MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE); printf("| %25s = %-7d |\n","MAX_QTEXT_SIZE",MAX_QTEXT_SIZE); printf("| %25s = %-7d |\n","MAX_SOURCE_FILES",MAX_SOURCE_FILES); ! printf("| %25s = %-7d |\n","MAX_SYMBOLS",MAX_SYMBOLS); printf("| %25s = %-7d |\n","MAX_STATIC_DATA",MAX_STATIC_DATA); printf("| %25s = %-7ld |\n","MAX_STATIC_STRINGS", (long int) MAX_STATIC_STRINGS); printf("| %25s = %-7d |\n","SYMBOLS_CHUNK_SIZE",SYMBOLS_CHUNK_SIZE); printf("| %25s = %-7ld |\n","MAX_TRANSCRIPT_SIZE", (long int) MAX_TRANSCRIPT_SIZE); ! printf("| %25s = %-7ld |\n","MAX_UNICODE_CHARS", (long int) MAX_UNICODE_CHARS); printf("| %25s = %-7d |\n","MAX_VERBS",MAX_VERBS); printf("| %25s = %-7d |\n","MAX_VERBSPACE",MAX_VERBSPACE); --- 213,246 ---- printf("| %25s = %-7d |\n","MAX_LABELS",MAX_LABELS); printf("| %25s = %-7d |\n","MAX_LINESPACE",MAX_LINESPACE); printf("| %25s = %-7d |\n","MAX_LINK_DATA_SIZE",MAX_LINK_DATA_SIZE); ! if (glulx_mode) ! printf("| %25s = %-7d |\n","MAX_LOCAL_VARIABLES",MAX_LOCAL_VARIABLES); printf("| %25s = %-7d |\n","MAX_LOW_STRINGS",MAX_LOW_STRINGS); ! if (glulx_mode) ! printf("| %25s = %-7d |\n","MAX_NUM_STATIC_STRINGS", ! MAX_NUM_STATIC_STRINGS); printf("| %25s = %-7d |\n","MAX_OBJECTS",MAX_OBJECTS); ! if (glulx_mode) ! printf("| %25s = %-7d |\n","MAX_OBJ_PROP_COUNT", MAX_OBJ_PROP_COUNT); ! if (glulx_mode) ! printf("| %25s = %-7d |\n","MAX_OBJ_PROP_TABLE_SIZE", MAX_OBJ_PROP_TABLE_SIZE); printf("| %25s = %-7d |\n","MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE); printf("| %25s = %-7d |\n","MAX_QTEXT_SIZE",MAX_QTEXT_SIZE); printf("| %25s = %-7d |\n","MAX_SOURCE_FILES",MAX_SOURCE_FILES); ! if (glulx_mode) ! printf("| %25s = %-7ld |\n","MAX_STACK_SIZE", ! (long int) MAX_STACK_SIZE); printf("| %25s = %-7d |\n","MAX_STATIC_DATA",MAX_STATIC_DATA); printf("| %25s = %-7ld |\n","MAX_STATIC_STRINGS", (long int) MAX_STATIC_STRINGS); + printf("| %25s = %-7d |\n","MAX_SYMBOLS",MAX_SYMBOLS); printf("| %25s = %-7d |\n","SYMBOLS_CHUNK_SIZE",SYMBOLS_CHUNK_SIZE); printf("| %25s = %-7ld |\n","MAX_TRANSCRIPT_SIZE", (long int) MAX_TRANSCRIPT_SIZE); ! if (glulx_mode) ! printf("| %25s = %-7ld |\n","MAX_UNICODE_CHARS", (long int) MAX_UNICODE_CHARS); printf("| %25s = %-7d |\n","MAX_VERBS",MAX_VERBS); printf("| %25s = %-7d |\n","MAX_VERBSPACE",MAX_VERBSPACE); *************** *** 396,401 **** --- 406,417 ---- NUM_ATTR_BYTES_z = 6; NUM_ATTR_BYTES_g = 7; MAX_UNICODE_CHARS = 64; + /* We estimate the default Glulx stack size at 4096. That's about + enough for 90 nested function calls with 8 locals each -- the + same capacity as the Z-Spec's suggestion for Z-machine stack + size. Note that Inform 7 wants more stack, so if you're + compiling an I7 game, crank this up. */ + MAX_STACK_SIZE = 4096; adjust_memory_sizes(); } *************** *** 656,661 **** --- 672,684 ---- (Glulx only)\n"); return; } + if (strcmp(command,"MAX_STACK_SIZE")==0) + { + printf( + " MAX_STACK_SIZE is the maximum size (in bytes) of the interpreter stack \n\ + during gameplay. (Glulx only)\n"); + return; + } printf("No such memory setting as \"%s\"\n",command); *************** *** 791,796 **** --- 814,825 ---- } if (strcmp(command,"MAX_UNICODE_CHARS")==0) MAX_UNICODE_CHARS=j, flag=1; + if (strcmp(command,"MAX_STACK_SIZE")==0) + { + MAX_STACK_SIZE=j, flag=1; + /* Adjust up to a 256-byte boundary. */ + MAX_STACK_SIZE = (MAX_STACK_SIZE + 0xFF) & (~0xFF); + } if (flag==0) printf("No such memory setting as \"%s\"\n", command);