Compiling without veneer and symbol strings?

When I output the gametext.txt file with the option $TRANSCRIPT_FORMAT=1 and -~S I still get the veneer and symbol strings with the names of attributes and arrays in the final z-file. Are they still needed for the final release version of the game or is there a compile option that I can set that will omit them?

2 Likes

Good question. I forget what they’re used for. Lemme see.

You’re talking about the section labelled “symbol names table” in the -z compiler output, and then the compressed string data referred to by that table. Right?

(This table contains property names, attribute names, fake action names, array names.)

This data is needed for the #identifiers_table system constant.

What uses that system constant? A lot of #ifdef DEBUG library code. (E.g. the implementation of the SHOWOBJ debug verb, the output of ACTIONS, and so on.)

It is also used by the I6 print statement which prints a property name:

print (property) propid;

This is probably only used by debug code, but it’s hard to be sure of that.

It would be nice to omit the table when DEBUG is not set (-~D). Unfortunately this looks hard to arrange in a safe way. The code that implements print (property) would print garbage (or maybe crash) if the table does not exist.

I guess we could put that code itself (the veneer code for Print__PName) under #ifdef DEBUG? That would break what was previously valid code, though.

Another possibility is to have a separate compiler switch to omit the table. Then any use of #identifiers_table would throw a compiler error. Using the switch together with -D would also be an error. It might require library changes too. I feel like this is too much hassle to get into.

2 Likes

You could make it just print the property number if DEBUG isn’t defined.

2 Likes

That’s still breaking behavior. print (property) isn’t documented in the DM4, but it’s been used since forever in library code and it’s a stretch to say that it should behave differently in non-DEBUG mode.

EDIT: I see it is mentioned in the solution to ex96 in the DM4.

1 Like

Would it be possible to have a setting $OMIT_SYMBOL_LOOKUP (analogues to $OMIT_UNUSED_ROUTINES) that you could use at your own dicretion? Using this setting would exclude the symbol-strings and the symbol lookup-array (that I guess is needed?) from the outputed file. I have a hard time seeing that the strings are needed outside of debugging.

I’m not familiar enough with the Inform6 source code to see where this is done, but would this be complicated?

Example with Minimal.inf for PunyInform 4.3:

Compiled with: 
inform641 -v3 -xrs~Se +include_path=lib,.\ $TRANSCRIPT_FORMAT=1 $OMIT_UNUSED_ROUTINES=1 $ZCODE_LESS_DICT_DATA=1 $MAX_ABBREVS=96 minimal.inf minimal_release.z3

::#####################################################################################
In:  7 source code files              5886 syntactic lines
  8569 textual lines                240996 characters (ISO 8859-1 Latin1)
Allocated:
   924 symbols                      616537 bytes of memory
Out:   Version 3 "Standard" story file 1.230216 (24.5K long):
     4 classes                           8 objects
    86 global vars (maximum 233)      1282 variable/array space
    58 verbs                           186 dictionary entries
   119 grammar lines (version 2)       228 grammar tokens (unlimited)
    64 actions                          28 attributes (maximum 32)
    26 common props (maximum 29)         9 individual props (unlimited)
 18450 bytes of Z-code                 352 unused bytes stripped out (1.9%)
  5801 characters used in text        3560 bytes compressed (rate 0.613)
    64 abbreviations (maximum 96)      207 routines (unlimited)
  4342 instructions of Z-code         2709 sequence points
  5086 bytes readable memory used (maximum 65536)
 25016 bytes used in Z-machine      106056 bytes free in Z-machine
Completed in 0.028 seconds

Gives a file of 25015 bytes.
The 150 generated symbol strings start at 24156, potential saving 859 bytes.
There should also be a lookup-array of 300 bytes that could be removed?

EDIT: I saw above that the array I’m looking for is the constant identifiers_table so maybe $OMIT_IDENTIFIERS_TABLE for the setting?

1 Like

Ok, I did a simple test…

I changed the construct_storyfile_z in table.c (and reused OMIT_UNUSED_ROUTINES) as below:

static void construct_storyfile_z(void)
{   uchar *p;
    int32 i, j, k, l, mark, objs, strings_length, code_length,
          limit=0, excess=0, extend_offset=0, headerext_length=0;
    int32 globals_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
          abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
          grammar_table_at=0, charset_at=0, headerext_at=0,
          terminating_chars_at=0, unicode_at=0, id_names_length=0,
          static_arrays_at=0;
    int skip_backpatching = FALSE;
    char *output_called = "story file";

    ASSERT_ZCODE();

	if (!OMIT_UNUSED_ROUTINES) {
		individual_name_strings =
			my_calloc(sizeof(int32), no_individual_properties,
				"identifier name strings");
		action_name_strings =
			my_calloc(sizeof(int32), no_actions + no_fake_actions,
				"action name strings");
		attribute_name_strings =
			my_calloc(sizeof(int32), 48,
				"attribute name strings");
		array_name_strings =
			my_calloc(sizeof(int32),
				no_symbols,
				"array name strings");

		write_the_identifier_names();
	} else
	{
		individual_name_strings =
			my_calloc(sizeof(int32), 1,
				"identifier name strings");
		action_name_strings =
			my_calloc(sizeof(int32), 1,
				"action name strings");
		attribute_name_strings =
			my_calloc(sizeof(int32), 1,
				"attribute name strings");
		array_name_strings =
			my_calloc(sizeof(int32),
				1,
				"array name strings");	
	}

This made the minimal.inf ca 850 bytes smaller (24178 bytes instead of 25015). I also tested it on the reverse engineered version of Curses! where it went from 257.636 bytes to 255.412 bytes. I could play Curses! all the way through to the end without any side-effects.

1 Like

It’s possible, but like I said, it’s a great deal of hassle.

This change would affect other system constants as well: #action_names_array, #array_names_array, #fake_action_names_array, #attribute_names_array, #global_names_array, #routine_names_array, #constant_names_array.

Also, to do it right, you’d want to skip generating those strings from the string table as well as skipping the identifiers table.

Tracking down all of those corners and making sure the compiler emits an error or error-generating code, in every instance, for all combinations of -D and -S – this is a very complicated change we’re talking about.

1 Like

I added a feature request issue as Option to skip the symbol names table · Issue #204 · DavidKinder/Inform6 · GitHub , summarizing this thread.

3 Likes

Update: I got this working. It’s now in the I6 repo and will be in the next I6 release.

The compiler option is $OMIT_SYMBOL_TABLE=1. At a quick benchmark, it saves 3120 bytes when compiling Advent.z5 with the 6/12 library. When compiling Library of Horror to z3 with PunyLib, it saves 1666 bytes.

I dealt with the debug messages by just having the compiler throw an error if you refer to the #identifiers_table system constant, or any of its ilk.

Error: OMIT_SYMBOL_TABLE omits system constant “identifiers_table”

The practical result is that you can’t use -D debug mode and $OMIT_SYMBOL_TABLE=1 at the same time. Both the standard library and PunyLib try to print symbol names in their debug verbs, and the point of $OMIT_SYMBOL_TABLE=1 is that the symbols just ain’t there.

The libraries could be updated to be smart about this case, but I’m not sure it’s worth the effort. The current behavior is reasonable – this is an option for release mode only.

3 Likes