1 /* ------------------------------------------------------------------------- */
2 /* "tables" : Constructs the story file or module (the output) up to the */
3 /* end of dynamic memory, gluing together all the required */
6 /* Part of Inform 6.40 */
7 /* copyright (c) Graham Nelson 1993 - 2022 */
9 /* Inform is free software: you can redistribute it and/or modify */
10 /* it under the terms of the GNU General Public License as published by */
11 /* the Free Software Foundation, either version 3 of the License, or */
12 /* (at your option) any later version. */
14 /* Inform is distributed in the hope that it will be useful, */
15 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
17 /* GNU General Public License for more details. */
19 /* You should have received a copy of the GNU General Public License */
20 /* along with Inform. If not, see https://gnu.org/licenses/ */
22 /* ------------------------------------------------------------------------- */
26 uchar *zmachine_paged_memory; /* Where we shall store the story file
27 constructed (contains all of paged
28 memory, i.e. all but code and the
29 static strings: allocated only when
30 we know how large it needs to be,
31 at the end of the compilation pass */
33 /* In Glulx, zmachine_paged_memory contains all of RAM -- i.e. all but
34 the header, the code, the static arrays, and the static strings. */
36 /* ------------------------------------------------------------------------- */
37 /* Offsets of various areas in the Z-machine: these are set to nominal */
38 /* values before the compilation pass, and to their calculated final */
39 /* values only when construct_storyfile() happens. These are then used to */
40 /* backpatch the incorrect values now existing in the Z-machine which */
41 /* used these nominal values. */
42 /* Most of the nominal values are 0x800 because this is guaranteed to */
43 /* be assembled as a long constant if it's needed in code, since the */
44 /* largest possible value of scale_factor is 8 and 0x800/8 = 256. */
46 /* In Glulx, I use 0x12345 instead of 0x800. This will always be a long */
47 /* (32-bit) constant, since there's no scale_factor. */
48 /* ------------------------------------------------------------------------- */
59 identifier_names_offset,
64 attribute_names_offset,
66 fake_action_names_offset,
68 constant_names_offset,
69 routines_array_offset,
70 constants_array_offset,
71 routine_flags_array_offset,
73 global_flags_array_offset,
74 array_flags_array_offset,
79 abbreviations_offset; /* Glulx */
81 int32 Out_Size, Write_Code_At, Write_Strings_At;
82 int32 RAM_Size, Write_RAM_At; /* Glulx */
84 /* ------------------------------------------------------------------------- */
85 /* Story file header settings. (Written to in "directs.c" and "asm.c".) */
86 /* ------------------------------------------------------------------------- */
88 int release_number, /* Release number game is to have */
89 statusline_flag; /* Either TIME_STYLE or SCORE_STYLE */
91 int serial_code_given_in_program /* If TRUE, a Serial directive has */
92 = FALSE; /* specified this 6-digit serial code */
93 char serial_code_buffer[7]; /* (overriding the usual date-stamp) */
94 int flags2_requirements[16]; /* An array of which bits in Flags 2 of
95 the header will need to be set:
96 e.g. if the save_undo / restore_undo
97 opcodes are ever assembled, we have
98 to set the "games want UNDO" bit.
101 /* ------------------------------------------------------------------------- */
102 /* Construct story/module file (up to code area start). */
104 /* (To understand what follows, you really need to look at the run-time */
105 /* system's specification, the Z-Machine Standards document.) */
106 /* ------------------------------------------------------------------------- */
108 extern void write_serial_number(char *buffer)
110 /* Note that this function may require modification for "ANSI" compilers
111 which do not provide the standard time functions: what is needed is
112 the ability to work out today's date */
114 time_t tt; tt=time(0);
115 if (serial_code_given_in_program)
116 strcpy(buffer, serial_code_buffer);
118 #ifdef TIME_UNAVAILABLE
119 sprintf(buffer,"970000");
121 strftime(buffer,10,"%y%m%d",localtime(&tt));
125 static char percentage_buffer[32];
127 static char *show_percentage(int32 x, int32 total)
129 if (memory_map_setting < 2) {
130 percentage_buffer[0] = '\0';
133 sprintf(percentage_buffer, " ( --- )");
136 sprintf(percentage_buffer, " (%.1f %%)", (float)x * 100.0 / (float)total);
138 return percentage_buffer;
141 static char *version_name(int v)
145 { case 3: return "Standard";
146 case 4: return "Plus";
147 case 5: return "Advanced";
148 case 6: return "Graphical";
149 case 8: return "Extended";
151 return "experimental format";
158 static int32 rough_size_of_paged_memory_z(void)
160 /* This function calculates a modest over-estimate of the amount of
161 memory required to store the Z-machine's paged memory area
162 (that is, everything up to the start of the code area). */
168 total = 64 /* header */
169 + 2 + low_strings_top
170 /* low strings pool */
171 + 6*32; /* abbreviations table */
173 total += 8; /* header extension table */
174 if (ZCODE_HEADER_EXT_WORDS>3) total += (ZCODE_HEADER_EXT_WORDS-3)*2;
176 if (alphabet_modified) total += 78; /* character set table */
178 if (zscii_defn_modified) /* Unicode translation table */
179 total += 2 + 2*zscii_high_water_mark;
181 total += 2*((version_number==3)?31:63) /* property default values */
182 + no_objects*((version_number==3)?9:14) /* object tree table */
183 + properties_table_size /* property values of objects */
184 + (no_classes+1)*(module_switch?4:2)
185 /* class object numbers table */
186 + no_symbols*2 /* names of numerous things */
187 + individuals_length /* tables of prop variables */
188 + dynamic_array_area_size; /* variables and arrays */
190 for (i=0; i<no_Inform_verbs; i++)
191 total += 2 + 1 + /* address of grammar table, */
192 /* number of grammar lines */
193 ((grammar_version_number == 1)?
194 (8*Inform_verbs[i].lines):0); /* grammar lines */
196 if (grammar_version_number != 1)
197 total += grammar_lines_top; /* size of grammar lines area */
199 total += 2 + 4*no_adjectives /* adjectives table */
200 + 2*no_actions /* action routines */
201 + 2*no_grammar_token_routines; /* general parsing routines */
203 total += (dictionary_top) /* dictionary size */
204 + ((module_switch)?30:0); /* module map */
206 total += static_array_area_size; /* static arrays */
208 total += scale_factor*0x100 /* maximum null bytes before code */
209 + 1000; /* fudge factor (in case the above is wrong) */
214 static int32 rough_size_of_paged_memory_g(void)
216 /* This function calculates a modest over-estimate of the amount of
217 memory required to store the machine's paged memory area
218 (that is, everything past the start of RAM). */
224 /* No header for us! */
225 total = 1000; /* bit of a fudge factor */
227 total += no_globals * 4; /* global variables */
228 total += dynamic_array_area_size; /* arrays */
230 total += no_objects * OBJECT_BYTE_LENGTH; /* object tables */
231 total += properties_table_size; /* property tables */
232 total += no_properties * 4; /* property defaults table */
234 total += 4 + no_classes * 4; /* class prototype object numbers */
236 total += 32; /* address/length of the identifier tables */
237 total += no_properties * 4;
238 total += (no_individual_properties-INDIV_PROP_START) * 4;
239 total += (NUM_ATTR_BYTES*8) * 4;
240 total += (no_actions + no_fake_actions) * 4;
241 total += 4 + no_arrays * 4;
243 total += 4 + no_Inform_verbs * 4; /* index of grammar tables */
244 total += grammar_lines_top; /* grammar tables */
246 total += 4 + no_actions * 4; /* actions functions table */
249 total += dictionary_top;
251 while (total % GPAGESIZE)
257 static void construct_storyfile_z(void)
259 int32 i, j, k, l, mark, objs, strings_length, code_length,
260 limit=0, excess=0, extend_offset=0, headerext_length=0;
261 int32 globals_at=0, link_table_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
262 abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
263 map_of_module=0, grammar_table_at=0, charset_at=0, headerext_at=0,
264 terminating_chars_at=0, unicode_at=0, id_names_length=0,
266 int skip_backpatching = FALSE;
267 char *output_called = (module_switch)?"module":"story file";
271 individual_name_strings =
272 my_calloc(sizeof(int32), no_individual_properties,
273 "identifier name strings");
274 action_name_strings =
275 my_calloc(sizeof(int32), no_actions + no_fake_actions,
276 "action name strings");
277 attribute_name_strings =
278 my_calloc(sizeof(int32), 48,
279 "attribute name strings");
281 my_calloc(sizeof(int32),
283 "array name strings");
285 write_the_identifier_names();
287 /* We now know how large the buffer to hold our construction has to be */
289 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_z(),
292 /* Foolish code to make this routine compile on all ANSI compilers */
294 p = (uchar *) zmachine_paged_memory;
296 /* In what follows, the "mark" will move upwards in memory: at various
297 points its value will be recorded for milestones like
298 "dictionary table start". It begins at 0x40, just after the header */
302 /* ----------------- Low Strings and Abbreviations -------------------- */
304 p[mark]=0x80; p[mark+1]=0; mark+=2; /* Start the low strings pool
305 with a useful default string, " " */
307 for (i=0; i<low_strings_top; mark++, i++) /* Low strings pool */
308 p[0x42+i]=low_strings[i];
312 if (MAX_ABBREVS + MAX_DYNAMIC_STRINGS != 96)
313 fatalerror("MAX_ABBREVS + MAX_DYNAMIC_STRINGS is not 96");
315 /* Initially all 96 entries are set to " ". (We store half of 0x40,
316 the address of the " " we wrote above.) */
317 for (i=0; i<3*32; i++)
318 { p[mark++]=0; p[mark++]=0x20;
321 /* Entries from 0 to MAX_DYNAMIC_STRINGS (default 32) are "variable
322 strings". Write the abbreviations after these. */
323 k = abbrevs_at+2*MAX_DYNAMIC_STRINGS;
324 for (i=0; i<no_abbreviations; i++)
325 { j=abbreviations[i].value;
330 /* ------------------- Header extension table ------------------------- */
333 headerext_length = ZCODE_HEADER_EXT_WORDS;
334 if (zscii_defn_modified) {
335 /* Need at least 3 words for unicode table address */
336 if (headerext_length < 3)
337 headerext_length = 3;
339 if (ZCODE_HEADER_FLAGS_3) {
340 /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
341 if (headerext_length < 4)
342 headerext_length = 4;
344 p[mark++] = 0; p[mark++] = headerext_length;
345 for (i=0; i<headerext_length; i++)
346 { p[mark++] = 0; p[mark++] = 0;
349 /* -------------------- Z-character set table ------------------------- */
351 if (alphabet_modified)
353 for (i=0;i<3;i++) for (j=0;j<26;j++)
354 { if (alphabet[i][j] == '~') p[mark++] = '\"';
355 else p[mark++] = alphabet[i][j];
359 /* ------------------ Unicode translation table ----------------------- */
362 if (zscii_defn_modified)
364 p[mark++] = zscii_high_water_mark;
365 for (i=0;i<zscii_high_water_mark;i++)
366 { j = zscii_to_unicode(155 + i);
367 if (j < 0 || j > 0xFFFF) {
368 error("Z-machine Unicode translation table cannot contain characters beyond $FFFF.");
370 p[mark++] = j/256; p[mark++] = j%256;
374 /* -------------------- Objects and Properties ------------------------ */
376 /* The object table must be word-aligned. The Z-machine spec does not
377 require this, but the RA__Pr() veneer routine does.
379 while ((mark%2) != 0) p[mark++]=0;
381 prop_defaults_at = mark;
383 p[mark++]=0; p[mark++]=0;
385 for (i=2; i< ((version_number==3)?32:64); i++)
386 { p[mark++]=commonprops[i].default_value/256;
387 p[mark++]=commonprops[i].default_value%256;
390 object_tree_at = mark;
392 mark += ((version_number==3)?9:14)*no_objects;
394 object_props_at = mark;
396 for (i=0; i<properties_table_size; i++)
397 p[mark+i]=properties_table[i];
399 for (i=0, objs=object_tree_at; i<no_objects; i++)
401 if (version_number == 3)
402 { p[objs]=objectsz[i].atts[0];
403 p[objs+1]=objectsz[i].atts[1];
404 p[objs+2]=objectsz[i].atts[2];
405 p[objs+3]=objectsz[i].atts[3];
406 p[objs+4]=objectsz[i].parent;
407 p[objs+5]=objectsz[i].next;
408 p[objs+6]=objectsz[i].child;
414 { p[objs]=objectsz[i].atts[0];
415 p[objs+1]=objectsz[i].atts[1];
416 p[objs+2]=objectsz[i].atts[2];
417 p[objs+3]=objectsz[i].atts[3];
418 p[objs+4]=objectsz[i].atts[4];
419 p[objs+5]=objectsz[i].atts[5];
420 p[objs+6]=(objectsz[i].parent)/256;
421 p[objs+7]=(objectsz[i].parent)%256;
422 p[objs+8]=(objectsz[i].next)/256;
423 p[objs+9]=(objectsz[i].next)%256;
424 p[objs+10]=(objectsz[i].child)/256;
425 p[objs+11]=(objectsz[i].child)%256;
427 { p[objs+12]=mark/256;
431 { p[objs+12]=objectsz[i].propsize/256;
432 p[objs+13]=objectsz[i].propsize%256;
436 mark+=objectsz[i].propsize;
439 /* ----------- Table of Class Prototype Object Numbers ---------------- */
441 class_numbers_offset = mark;
442 for (i=0; i<no_classes; i++)
443 { p[mark++] = class_info[i].object_number/256;
444 p[mark++] = class_info[i].object_number%256;
446 { p[mark++] = class_info[i].begins_at/256;
447 p[mark++] = class_info[i].begins_at%256;
453 /* ------------------- Table of Identifier Names ---------------------- */
455 identifier_names_offset = mark;
458 { p[mark++] = no_individual_properties/256;
459 p[mark++] = no_individual_properties%256;
460 for (i=1; i<no_individual_properties; i++)
461 { p[mark++] = individual_name_strings[i]/256;
462 p[mark++] = individual_name_strings[i]%256;
465 attribute_names_offset = mark;
467 { p[mark++] = attribute_name_strings[i]/256;
468 p[mark++] = attribute_name_strings[i]%256;
471 action_names_offset = mark;
472 fake_action_names_offset = mark + 2*no_actions;
473 for (i=0; i<no_actions + no_fake_actions; i++)
474 { p[mark++] = action_name_strings[i]/256;
475 p[mark++] = action_name_strings[i]%256;
478 array_names_offset = mark;
479 global_names_offset = mark + 2*no_arrays;
480 routine_names_offset = global_names_offset + 2*no_globals;
481 constant_names_offset = routine_names_offset + 2*no_named_routines;
482 for (i=0; i<no_arrays + no_globals
483 + no_named_routines + no_named_constants; i++)
484 { if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
485 p[mark++] = array_name_strings[i]/256;
486 p[mark++] = array_name_strings[i]%256;
489 id_names_length = (mark - identifier_names_offset)/2;
491 routine_flags_array_offset = mark;
493 if (define_INFIX_switch)
494 { for (i=0, k=1, l=0; i<no_named_routines; i++)
495 { if (symbols[named_routine_symbols[i]].flags & STAR_SFLAG) l=l+k;
497 if (k==256) { p[mark++] = l; k=1; l=0; }
499 if (k!=1) p[mark++]=l;
502 /* ---------------- Table of Indiv Property Values -------------------- */
504 individuals_offset = mark;
505 for (i=0; i<individuals_length; i++)
506 p[mark++] = individuals_table[i];
508 /* ----------------- Variables and Dynamic Arrays --------------------- */
512 for (i=0; i<dynamic_array_area_size; i++)
513 p[mark++] = dynamic_array_area[i];
515 for (i=0; i<240; i++)
516 { j=global_initial_value[i];
517 p[globals_at+i*2] = j/256; p[globals_at+i*2+1] = j%256;
520 /* ------------------ Terminating Characters Table -------------------- */
522 if (version_number >= 5)
523 { terminating_chars_at = mark;
524 for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
528 /* ------------------------ Grammar Table ----------------------------- */
530 if (grammar_version_number > 2)
531 { warning("This version of Inform is unable to produce the grammar \
532 table format requested (producing number 2 format instead)");
533 grammar_version_number = 2;
536 grammar_table_at = mark;
538 mark = mark + no_Inform_verbs*2;
540 for (i=0; i<no_Inform_verbs; i++)
541 { p[grammar_table_at + i*2] = (mark/256);
542 p[grammar_table_at + i*2 + 1] = (mark%256);
543 p[mark++] = Inform_verbs[i].lines;
544 for (j=0; j<Inform_verbs[i].lines; j++)
545 { k = Inform_verbs[i].l[j];
546 if (grammar_version_number == 1)
548 p[mark+7] = grammar_lines[k+1];
549 for (m=1;m<=6;m++) p[mark + m] = 0;
550 k = k + 2; m = 1; n = 0;
551 while ((grammar_lines[k] != 15) && (m<=6))
552 { p[mark + m] = grammar_lines[k];
553 if (grammar_lines[k] < 180) n++;
561 p[mark++] = grammar_lines[k++];
562 p[mark++] = grammar_lines[k++];
564 { tok = grammar_lines[k++];
566 if (tok == 15) break;
567 p[mark++] = grammar_lines[k++];
568 p[mark++] = grammar_lines[k++];
574 /* ------------------- Actions and Preactions ------------------------- */
575 /* (The term "preactions" is traditional: Inform uses the preactions */
576 /* table for a different purpose than Infocom used to.) */
577 /* The values are written later, when the Z-code offset is known. */
578 /* -------------------------------------------------------------------- */
581 mark += no_actions*2;
583 preactions_at = mark;
584 if (grammar_version_number == 1)
585 mark += no_grammar_token_routines*2;
587 /* ----------------------- Adjectives Table --------------------------- */
589 if (grammar_version_number == 1)
590 { p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
591 adjectives_offset = mark;
592 dictionary_offset = mark + 4*no_adjectives;
594 for (i=0; i<no_adjectives; i++)
595 { j = final_dict_order[adjectives[no_adjectives-i-1]]
596 *DICT_ENTRY_BYTE_LENGTH
597 + dictionary_offset + 7;
598 p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
599 p[mark++]=(256-no_adjectives+i);
603 { p[mark]=0; p[mark+1]=0; mark+=2;
604 adjectives_offset = mark;
605 dictionary_offset = mark;
608 /* ------------------------- Dictionary ------------------------------- */
612 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
613 dictionary[2]=','; /* force words apart */
616 dictionary[4]=DICT_ENTRY_BYTE_LENGTH; /* Length of each entry */
617 dictionary[5]=(dict_entries/256); /* Number of entries */
618 dictionary[6]=(dict_entries%256);
620 for (i=0; i<7; i++) p[mark++] = dictionary[i];
622 for (i=0; i<dict_entries; i++)
623 { k = 7 + i*DICT_ENTRY_BYTE_LENGTH;
624 j = mark + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
625 for (l = 0; l<DICT_ENTRY_BYTE_LENGTH; l++)
626 p[j++] = dictionary[k++];
628 mark += dict_entries * DICT_ENTRY_BYTE_LENGTH;
630 /* ------------------------- Module Map ------------------------------- */
633 { map_of_module = mark; /* Filled in below */
637 /* ------------------------ Static Arrays ----------------------------- */
639 static_arrays_at = mark;
640 for (i=0; i<static_array_area_size; i++)
641 p[mark++] = static_array_area[i];
643 /* ----------------- A gap before the code area ----------------------- */
644 /* (so that it will start at an exact packed address and so that all */
645 /* routine packed addresses are >= 256, hence long constants) */
646 /* -------------------------------------------------------------------- */
648 while ((mark%length_scale_factor) != 0) p[mark++]=0;
649 while (mark < (scale_factor*0x100)) p[mark++]=0;
650 if (oddeven_packing_switch)
651 while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
654 { error("This program has overflowed the maximum readable-memory \
655 size of the Z-machine format. See the memory map below: the start \
656 of the area marked \"above readable memory\" must be brought down to $FFFE \
658 memory_map_setting = 1;
659 /* Backpatching the grammar tables requires us to trust some of the */
660 /* addresses we've written into Z-machine memory, but they may have */
661 /* been truncated to 16 bits, so we can't do it. */
662 skip_backpatching = TRUE;
665 /* -------------------------- Code Area ------------------------------- */
666 /* (From this point on we don't write any more into the "p" buffer.) */
667 /* -------------------------------------------------------------------- */
669 Write_Code_At = mark;
670 if (!OMIT_UNUSED_ROUTINES) {
671 code_length = zmachine_pc;
674 if (zmachine_pc != df_total_size_before_stripping)
675 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
676 code_length = df_total_size_after_stripping;
680 /* ------------------ Another synchronising gap ----------------------- */
682 if (oddeven_packing_switch)
684 while ((mark%(scale_factor*2)) != 0) mark++;
686 while ((mark%(scale_factor*2)) != scale_factor) mark++;
689 while ((mark%scale_factor) != 0) mark++;
691 /* ------------------------- Strings Area ----------------------------- */
693 Write_Strings_At = mark;
694 strings_length = static_strings_extent;
695 mark += strings_length;
697 /* --------------------- Module Linking Data -------------------------- */
700 { link_table_at = mark; mark += link_data_size;
701 mark += zcode_backpatch_size;
702 mark += zmachine_backpatch_size;
705 /* --------------------- Is the file too big? ------------------------- */
709 switch(version_number)
710 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
712 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
715 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
719 { excess = Out_Size-((int32) 0x10000L); limit=64;
723 { char memory_full_error[80];
724 sprintf(memory_full_error,
725 "The %s exceeds version-%d limit (%dK) by %d bytes",
726 output_called, version_number, limit, excess);
727 fatalerror(memory_full_error);
730 /* --------------------------- Offsets -------------------------------- */
732 dictionary_offset = dictionary_at;
733 variables_offset = globals_at;
734 actions_offset = actions_at;
735 preactions_offset = preactions_at;
736 prop_defaults_offset = prop_defaults_at;
737 prop_values_offset = object_props_at;
738 static_memory_offset = grammar_table_at;
739 grammar_table_offset = grammar_table_at;
740 static_arrays_offset = static_arrays_at;
742 if (extend_memory_map)
744 if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
745 while ((extend_offset%length_scale_factor) != 0) extend_offset++;
746 /* Not sure why above line is necessary, but oddeven_packing
747 * will need extend_offset to be even */
748 code_offset = extend_offset*scale_factor;
749 if (oddeven_packing_switch)
750 strings_offset = code_offset + scale_factor;
752 strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
754 /* With the extended memory model, need to specifically check that we
755 * haven't overflowed the packed address range for routines or strings.
756 * With the standard memory model, we only need the earlier total size
759 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
761 { char code_full_error[80];
762 sprintf(code_full_error,
763 "The code area limit has been exceeded by %d bytes",
765 fatalerror(code_full_error);
768 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
770 { char strings_full_error[140];
771 if (oddeven_packing_switch)
772 sprintf(strings_full_error,
773 "The strings area limit has been exceeded by %d bytes",
776 sprintf(strings_full_error,
777 "The code+strings area limit has been exceeded by %d bytes. \
778 Try running Inform again with -B on the command line.",
780 fatalerror(strings_full_error);
784 { code_offset = Write_Code_At;
785 strings_offset = Write_Strings_At;
788 /* --------------------------- The Header ----------------------------- */
790 for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */
792 p[0] = version_number; /* Version number */
793 p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */
794 p[2] = (release_number/256);
795 p[3] = (release_number%256); /* Release */
796 p[4] = (Write_Code_At/256);
797 p[5] = (Write_Code_At%256); /* End of paged memory */
798 if (version_number==6)
799 { j=code_offset/scale_factor; /* Packed address of "Main__" */
800 p[6]=(j/256); p[7]=(j%256);
803 { j=Write_Code_At+1; /* Initial PC value (bytes) */
804 p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */
806 p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */
807 p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */
808 p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */
809 p[14]=(grammar_table_at/256);
810 p[15]=(grammar_table_at%256); /* Grammar */
811 for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */
812 j+=k*flags2_requirements[i]; /* unusual opcodes assembled */
813 p[16]=j/256; p[17]=j%256;
814 write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
815 p[24]=abbrevs_at/256;
816 p[25]=abbrevs_at%256; /* Abbreviations table */
817 p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */
818 p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */
820 if (extend_memory_map)
821 { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
822 p[40]=j/256; p[41]=j%256; /* Routines offset */
823 if (oddeven_packing_switch)
824 j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
825 p[42]=j/256; p[43]=j%256; /* = Strings offset */
828 if (version_number >= 5)
829 { p[46] = terminating_chars_at/256; /* Terminating characters table */
830 p[47] = terminating_chars_at%256;
833 if (alphabet_modified)
835 p[52]=j/256; p[53]=j%256; } /* Character set table address */
838 p[54] = j/256; p[55] = j%256; /* Header extension table address */
840 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
842 p[62] = '0' + ((RELEASE_NUMBER/10)%10);
843 p[63] = '0' + RELEASE_NUMBER%10;
845 /* ------------------------ Header Extension -------------------------- */
847 /* The numbering in the spec is a little weird -- it's headerext_length
848 words *after* the initial length word. We follow the spec numbering
849 in this switch statement, so the count is 1-based. */
850 for (i=1; i<=headerext_length; i++) {
853 j = unicode_at; /* Unicode translation table address */
856 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
862 p[headerext_at+2*i+0] = j / 256;
863 p[headerext_at+2*i+1] = j % 256;
866 /* ----------------- The Header: Extras for modules ------------------- */
870 p[1]=MODULE_VERSION_NUMBER;
871 p[6]=map_of_module/256;
872 p[7]=map_of_module%256;
874 mark = map_of_module; /* Module map format: */
876 p[mark++]=object_tree_at/256; /* 0: Object tree addr */
877 p[mark++]=object_tree_at%256;
878 p[mark++]=object_props_at/256; /* 2: Prop values addr */
879 p[mark++]=object_props_at%256;
880 p[mark++]=(Write_Strings_At/scale_factor)/256; /* 4: Static strs */
881 p[mark++]=(Write_Strings_At/scale_factor)%256;
882 p[mark++]=class_numbers_offset/256; /* 6: Class nos addr */
883 p[mark++]=class_numbers_offset%256;
884 p[mark++]=individuals_offset/256; /* 8: Indiv prop values */
885 p[mark++]=individuals_offset%256;
886 p[mark++]=individuals_length/256; /* 10: Length of table */
887 p[mark++]=individuals_length%256;
888 p[mark++]=no_symbols/256; /* 12: No of symbols */
889 p[mark++]=no_symbols%256;
890 p[mark++]=no_individual_properties/256; /* 14: Max property no */
891 p[mark++]=no_individual_properties%256;
892 p[mark++]=no_objects/256; /* 16: No of objects */
893 p[mark++]=no_objects%256;
895 p[mark++]=i/256; /* 18: Import/exports */
897 p[mark++]=link_data_size/256; /* 20: Size of */
898 p[mark++]=link_data_size%256;
900 p[mark++]=i/256; /* 22: Code backpatch */
902 p[mark++]=zcode_backpatch_size/256; /* 24: Size of */
903 p[mark++]=zcode_backpatch_size%256;
904 i += zcode_backpatch_size;
905 p[mark++]=i/256; /* 26: Image backpatch */
907 p[mark++]=zmachine_backpatch_size/256; /* 28: Size of */
908 p[mark++]=zmachine_backpatch_size%256;
910 /* Further space in this table is reserved for future use */
913 /* ---- Backpatch the Z-machine, now that all information is in ------- */
915 if (!module_switch && !skip_backpatching)
916 { backpatch_zmachine_image_z();
917 for (i=1; i<id_names_length; i++)
918 { int32 v = 256*p[identifier_names_offset + i*2]
919 + p[identifier_names_offset + i*2 + 1];
920 if (v!=0) v += strings_offset/scale_factor;
921 p[identifier_names_offset + i*2] = v/256;
922 p[identifier_names_offset + i*2 + 1] = v%256;
926 for (i=0; i<no_actions; i++)
927 { j=actions[i].byte_offset;
928 if (OMIT_UNUSED_ROUTINES)
929 j = df_stripped_address_for_address(j);
930 j += code_offset/scale_factor;
931 p[mark++]=j/256; p[mark++]=j%256;
934 if (grammar_version_number == 1)
935 { mark = preactions_at;
936 for (i=0; i<no_grammar_token_routines; i++)
937 { j=grammar_token_routine[i];
938 if (OMIT_UNUSED_ROUTINES)
939 j = df_stripped_address_for_address(j);
940 j += code_offset/scale_factor;
941 p[mark++]=j/256; p[mark++]=j%256;
945 { for (l = 0; l<no_Inform_verbs; l++)
946 { k = grammar_table_at + 2*l;
947 i = p[k]*256 + p[k+1];
948 for (j = p[i++]; j>0; j--)
949 { int topbits; int32 value;
952 { topbits = (p[i]/0x40) & 3;
953 value = p[i+1]*256 + p[i+2];
956 value = final_dict_order[value]
957 *DICT_ENTRY_BYTE_LENGTH
958 + dictionary_offset + 7;
961 if (OMIT_UNUSED_ROUTINES)
962 value = df_stripped_address_for_address(value);
963 value += code_offset/scale_factor;
966 p[i+1] = value/256; p[i+2] = value%256;
975 /* ---- From here on, it's all reportage: construction is finished ---- */
977 if (debugfile_switch)
978 { begin_writing_debug_sections();
979 write_debug_section("abbreviations", 64);
980 write_debug_section("abbreviations table", abbrevs_at);
981 write_debug_section("header extension", headerext_at);
982 if (alphabet_modified)
983 { write_debug_section("alphabets table", charset_at);
985 if (zscii_defn_modified)
986 { write_debug_section("Unicode table", unicode_at);
988 write_debug_section("property defaults", prop_defaults_at);
989 write_debug_section("object tree", object_tree_at);
990 write_debug_section("common properties", object_props_at);
991 write_debug_section("class numbers", class_numbers_offset);
992 write_debug_section("identifier names", identifier_names_offset);
993 write_debug_section("individual properties", individuals_offset);
994 write_debug_section("global variables", globals_at);
995 write_debug_section("array space", globals_at+480);
996 write_debug_section("grammar table", grammar_table_at);
997 write_debug_section("actions table", actions_at);
998 write_debug_section("parsing routines", preactions_at);
999 write_debug_section("adjectives table", adjectives_offset);
1000 write_debug_section("dictionary", dictionary_at);
1001 write_debug_section("code area", Write_Code_At);
1002 write_debug_section("strings area", Write_Strings_At);
1003 end_writing_debug_sections(Out_Size);
1006 if (memory_map_setting)
1010 printf("Dynamic +---------------------+ 00000\n");
1011 printf("memory | header | %s\n",
1012 show_percentage(0x40, Out_Size));
1013 printf(" +---------------------+ 00040\n");
1014 printf(" | abbreviations | %s\n",
1015 show_percentage(abbrevs_at-0x40, Out_Size));
1016 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at);
1017 printf(" | abbreviations table | %s\n",
1018 show_percentage(headerext_at-abbrevs_at, Out_Size));
1019 printf(" +---------------------+ %05lx\n", (long int) headerext_at);
1020 addr = (alphabet_modified ? charset_at : (zscii_defn_modified ? unicode_at : prop_defaults_at));
1021 printf(" | header extension | %s\n",
1022 show_percentage(addr-headerext_at, Out_Size));
1023 if (alphabet_modified)
1025 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at);
1026 addr = (zscii_defn_modified ? unicode_at : prop_defaults_at);
1027 printf(" | alphabets table | %s\n",
1028 show_percentage(addr-charset_at, Out_Size));
1030 if (zscii_defn_modified)
1032 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at);
1033 printf(" | Unicode table | %s\n",
1034 show_percentage(prop_defaults_at-unicode_at, Out_Size));
1036 printf(" +---------------------+ %05lx\n",
1037 (long int) prop_defaults_at);
1038 printf(" | property defaults | %s\n",
1039 show_percentage(object_tree_at-prop_defaults_at, Out_Size));
1040 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at);
1041 printf(" | objects | %s\n",
1042 show_percentage(object_props_at-object_tree_at, Out_Size));
1043 printf(" + - - - - - - - - - - + %05lx\n",
1044 (long int) object_props_at);
1045 printf(" | object short names, |\n");
1046 printf(" | common prop values | %s\n",
1047 show_percentage(class_numbers_offset-object_props_at, Out_Size));
1048 printf(" + - - - - - - - - - - + %05lx\n",
1049 (long int) class_numbers_offset);
1050 printf(" | class numbers table | %s\n",
1051 show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
1052 printf(" + - - - - - - - - - - + %05lx\n",
1053 (long int) identifier_names_offset);
1054 printf(" | symbol names table | %s\n",
1055 show_percentage(individuals_offset-identifier_names_offset, Out_Size));
1056 printf(" + - - - - - - - - - - + %05lx\n",
1057 (long int) individuals_offset);
1058 printf(" | indiv prop values | %s\n",
1059 show_percentage(globals_at-individuals_offset, Out_Size));
1060 printf(" +---------------------+ %05lx\n", (long int) globals_at);
1061 printf(" | global variables | %s\n",
1062 show_percentage(480, Out_Size));
1063 printf(" + - - - - - - - - - - + %05lx\n",
1064 ((long int) globals_at)+480L);
1065 printf(" | arrays | %s\n",
1066 show_percentage(grammar_table_at-(globals_at+480), Out_Size));
1067 printf(" +=====================+ %05lx\n",
1068 (long int) grammar_table_at);
1069 printf("Readable| grammar table | %s\n",
1070 show_percentage(actions_at-grammar_table_at, Out_Size));
1071 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at);
1072 printf(" | actions | %s\n",
1073 show_percentage(preactions_at-actions_at, Out_Size));
1074 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at);
1075 printf(" | parsing routines | %s\n",
1076 show_percentage(adjectives_offset-preactions_at, Out_Size));
1077 printf(" + - - - - - - - - - - + %05lx\n",
1078 (long int) adjectives_offset);
1079 printf(" | adjectives | %s\n",
1080 show_percentage(dictionary_at-adjectives_offset, Out_Size));
1081 printf(" +---------------------+ %05lx\n", (long int) dictionary_at);
1082 addr = (module_switch ? map_of_module : (static_array_area_size ? static_arrays_at : Write_Code_At));
1083 printf(" | dictionary | %s\n",
1084 show_percentage(addr-dictionary_at, Out_Size));
1087 printf(" + - - - - - - - - - - + %05lx\n",
1088 (long int) map_of_module);
1089 addr = (static_array_area_size ? static_arrays_at : Write_Code_At);
1090 printf(" | map of module addrs | %s\n",
1091 show_percentage(addr-map_of_module, Out_Size));
1093 if (static_array_area_size)
1095 printf(" +---------------------+ %05lx\n", (long int) static_arrays_at);
1096 printf(" | static arrays | %s\n",
1097 show_percentage(Write_Code_At-static_arrays_at, Out_Size));
1099 printf(" +=====================+ %05lx\n", (long int) Write_Code_At);
1100 printf("Above | Z-code | %s\n",
1101 show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1102 printf("readable+---------------------+ %05lx\n",
1103 (long int) Write_Strings_At);
1104 addr = (module_switch ? link_table_at : Out_Size);
1105 printf("memory | strings | %s\n",
1106 show_percentage(addr-Write_Strings_At, Out_Size));
1109 printf(" +=====================+ %05lx\n", (long int) link_table_at);
1110 printf(" | module linking data | %s\n",
1111 show_percentage(Out_Size-link_table_at, Out_Size));
1113 printf(" +---------------------+ %05lx\n", (long int) Out_Size);
1118 static void construct_storyfile_g(void)
1120 int32 i, j, k, l, mark, strings_length;
1121 int32 globals_at, dictionary_at, actions_at, preactions_at,
1122 abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1123 grammar_table_at, arrays_at, static_arrays_at;
1124 int32 threespaces, code_length;
1128 individual_name_strings =
1129 my_calloc(sizeof(int32), no_individual_properties,
1130 "identifier name strings");
1131 action_name_strings =
1132 my_calloc(sizeof(int32), no_actions + no_fake_actions,
1133 "action name strings");
1134 attribute_name_strings =
1135 my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1136 "attribute name strings");
1137 array_name_strings =
1138 my_calloc(sizeof(int32),
1140 "array name strings");
1142 write_the_identifier_names();
1143 threespaces = compile_string(" ", STRCTX_GAME);
1145 compress_game_text();
1147 /* We now know how large the buffer to hold our construction has to be */
1149 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1152 /* Foolish code to make this routine compile on all ANSI compilers */
1154 p = (uchar *) zmachine_paged_memory;
1156 /* In what follows, the "mark" will move upwards in memory: at various
1157 points its value will be recorded for milestones like
1158 "dictionary table start". It begins at 0x40, just after the header */
1160 /* Ok, our policy here will be to set the *_at values all relative
1161 to RAM. That's so we can write into zmachine_paged_memory[mark]
1162 and actually hit what we're aiming at.
1163 All the *_offset values will be set to true Glulx machine
1166 /* To get our bearings, figure out where the strings and code are. */
1167 /* We start with two words, which conventionally identify the
1168 memory layout. This is why the code starts eight bytes after
1170 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1171 if (!OMIT_UNUSED_ROUTINES) {
1172 code_length = zmachine_pc;
1175 if (zmachine_pc != df_total_size_before_stripping)
1176 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1177 code_length = df_total_size_after_stripping;
1179 Write_Strings_At = Write_Code_At + code_length;
1180 strings_length = compression_table_size + compression_string_size;
1182 static_arrays_at = Write_Strings_At + strings_length;
1184 /* Now figure out where RAM starts. */
1185 Write_RAM_At = static_arrays_at + static_array_area_size;
1186 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1187 while (Write_RAM_At % GPAGESIZE)
1190 /* Now work out all those RAM positions. */
1193 /* ----------------- Variables and Dynamic Arrays --------------------- */
1196 for (i=0; i<no_globals; i++) {
1197 j = global_initial_value[i];
1198 WriteInt32(p+mark, j);
1203 for (i=0; i<dynamic_array_area_size; i++)
1204 p[mark++] = dynamic_array_area[i];
1206 /* -------------------------- Dynamic Strings -------------------------- */
1209 WriteInt32(p+mark, no_dynamic_strings);
1211 for (i=0; i<no_dynamic_strings; i++) {
1212 j = Write_Strings_At + compressed_offsets[threespaces-1];
1213 WriteInt32(p+mark, j);
1217 /* -------------------- Objects and Properties ------------------------ */
1219 object_tree_at = mark;
1221 object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1223 for (i=0; i<no_objects; i++) {
1224 int32 objmark = mark;
1225 p[mark++] = 0x70; /* type byte -- object */
1226 for (j=0; j<NUM_ATTR_BYTES; j++) {
1227 p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1229 for (j=0; j<6; j++) {
1232 case 0: /* next object in the linked list. */
1233 if (i == no_objects-1)
1236 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1238 case 1: /* hardware name address */
1239 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1241 case 2: /* property table address */
1242 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1244 case 3: /* parent */
1245 if (objectsg[i].parent == 0)
1248 val = Write_RAM_At + object_tree_at +
1249 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1251 case 4: /* sibling */
1252 if (objectsg[i].next == 0)
1255 val = Write_RAM_At + object_tree_at +
1256 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1259 if (objectsg[i].child == 0)
1262 val = Write_RAM_At + object_tree_at +
1263 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1266 p[mark++] = (val >> 24) & 0xFF;
1267 p[mark++] = (val >> 16) & 0xFF;
1268 p[mark++] = (val >> 8) & 0xFF;
1269 p[mark++] = (val) & 0xFF;
1272 for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1277 if (object_props_at != mark)
1278 error("*** Object table was impossible length ***");
1280 for (i=0; i<properties_table_size; i++)
1281 p[mark+i]=properties_table[i];
1283 for (i=0; i<no_objects; i++) {
1284 int32 tableaddr = object_props_at + objectsg[i].propaddr;
1285 int32 tablelen = ReadInt32(p+tableaddr);
1287 for (j=0; j<tablelen; j++) {
1288 k = ReadInt32(p+tableaddr+4);
1289 k += (Write_RAM_At + object_props_at);
1290 WriteInt32(p+tableaddr+4, k);
1295 mark += properties_table_size;
1297 prop_defaults_at = mark;
1298 for (i=0; i<no_properties; i++) {
1299 k = commonprops[i].default_value;
1300 WriteInt32(p+mark, k);
1304 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1306 class_numbers_offset = mark;
1307 for (i=0; i<no_classes; i++) {
1308 j = Write_RAM_At + object_tree_at +
1309 (OBJECT_BYTE_LENGTH*(class_info[i].object_number-1));
1310 WriteInt32(p+mark, j);
1313 WriteInt32(p+mark, 0);
1316 /* -------------------- Table of Property Names ------------------------ */
1318 /* We try to format this bit with some regularity...
1319 address of common properties
1320 number of common properties
1321 address of indiv properties
1322 number of indiv properties (counted from INDIV_PROP_START)
1323 address of attributes
1324 number of attributes (always NUM_ATTR_BYTES*8)
1329 identifier_names_offset = mark;
1330 mark += 32; /* eight pairs of values, to be filled in. */
1332 WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1333 WriteInt32(p+identifier_names_offset+4, no_properties);
1334 for (i=0; i<no_properties; i++) {
1335 j = individual_name_strings[i];
1337 j = Write_Strings_At + compressed_offsets[j-1];
1338 WriteInt32(p+mark, j);
1342 WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1343 WriteInt32(p+identifier_names_offset+12,
1344 no_individual_properties-INDIV_PROP_START);
1345 for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1346 j = individual_name_strings[i];
1348 j = Write_Strings_At + compressed_offsets[j-1];
1349 WriteInt32(p+mark, j);
1353 WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1354 WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1355 for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1356 j = attribute_name_strings[i];
1358 j = Write_Strings_At + compressed_offsets[j-1];
1359 WriteInt32(p+mark, j);
1363 WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1364 WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1365 action_names_offset = mark;
1366 fake_action_names_offset = mark + 4*no_actions;
1367 for (i=0; i<no_actions + no_fake_actions; i++) {
1368 j = action_name_strings[i];
1370 j = Write_Strings_At + compressed_offsets[j-1];
1371 WriteInt32(p+mark, j);
1375 array_names_offset = mark;
1376 WriteInt32(p+mark, no_arrays);
1378 for (i=0; i<no_arrays; i++) {
1379 j = array_name_strings[i];
1381 j = Write_Strings_At + compressed_offsets[j-1];
1382 WriteInt32(p+mark, j);
1386 individuals_offset = mark;
1388 /* ------------------------ Grammar Table ----------------------------- */
1390 if (grammar_version_number != 2)
1391 { warning("This version of Inform is unable to produce the grammar \
1392 table format requested (producing number 2 format instead)");
1393 grammar_version_number = 2;
1396 grammar_table_at = mark;
1398 WriteInt32(p+mark, no_Inform_verbs);
1401 mark += no_Inform_verbs*4;
1403 for (i=0; i<no_Inform_verbs; i++) {
1404 j = mark + Write_RAM_At;
1405 WriteInt32(p+(grammar_table_at+4+i*4), j);
1406 p[mark++] = Inform_verbs[i].lines;
1407 for (j=0; j<Inform_verbs[i].lines; j++) {
1409 k = Inform_verbs[i].l[j];
1410 p[mark++] = grammar_lines[k++];
1411 p[mark++] = grammar_lines[k++];
1412 p[mark++] = grammar_lines[k++];
1414 tok = grammar_lines[k++];
1416 if (tok == 15) break;
1417 p[mark++] = grammar_lines[k++];
1418 p[mark++] = grammar_lines[k++];
1419 p[mark++] = grammar_lines[k++];
1420 p[mark++] = grammar_lines[k++];
1425 /* ------------------- Actions and Preactions ------------------------- */
1428 WriteInt32(p+mark, no_actions);
1430 mark += no_actions*4;
1431 /* Values to be written in later. */
1433 if (DICT_CHAR_SIZE != 1) {
1434 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1439 preactions_at = mark;
1440 adjectives_offset = mark;
1441 dictionary_offset = mark;
1443 /* ------------------------- Dictionary ------------------------------- */
1445 dictionary_at = mark;
1447 WriteInt32(dictionary+0, dict_entries);
1449 p[mark+i] = dictionary[i];
1451 for (i=0; i<dict_entries; i++) {
1452 k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1453 j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1454 for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1455 p[j++] = dictionary[k++];
1457 mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1459 /* -------------------------- All Data -------------------------------- */
1461 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1462 while (mark % GPAGESIZE)
1467 Out_Size = Write_RAM_At + RAM_Size;
1469 /* --------------------------- Offsets -------------------------------- */
1471 dictionary_offset = Write_RAM_At + dictionary_at;
1472 variables_offset = Write_RAM_At + globals_at;
1473 arrays_offset = Write_RAM_At + arrays_at;
1474 actions_offset = Write_RAM_At + actions_at;
1475 preactions_offset = Write_RAM_At + preactions_at;
1476 prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1477 object_tree_offset = Write_RAM_At + object_tree_at;
1478 prop_values_offset = Write_RAM_At + object_props_at;
1479 static_memory_offset = Write_RAM_At + grammar_table_at;
1480 grammar_table_offset = Write_RAM_At + grammar_table_at;
1481 abbreviations_offset = Write_RAM_At + abbrevs_at;
1483 code_offset = Write_Code_At;
1484 strings_offset = Write_Strings_At;
1485 static_arrays_offset = static_arrays_at;
1487 /* --------------------------- The Header ----------------------------- */
1489 /* ------ Backpatch the machine, now that all information is in ------- */
1492 { backpatch_zmachine_image_g();
1494 mark = actions_at + 4;
1495 for (i=0; i<no_actions; i++) {
1496 j = actions[i].byte_offset;
1497 if (OMIT_UNUSED_ROUTINES)
1498 j = df_stripped_address_for_address(j);
1500 WriteInt32(p+mark, j);
1504 for (l = 0; l<no_Inform_verbs; l++) {
1505 k = grammar_table_at + 4 + 4*l;
1506 i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1508 for (j = p[i++]; j>0; j--) {
1512 while (p[i] != 15) {
1513 topbits = (p[i]/0x40) & 3;
1514 value = ((p[i+1] << 24) | (p[i+2] << 16)
1515 | (p[i+3] << 8) | (p[i+4]));
1518 value = dictionary_offset + 4
1519 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1522 if (OMIT_UNUSED_ROUTINES)
1523 value = df_stripped_address_for_address(value);
1524 value += code_offset;
1527 WriteInt32(p+(i+1), value);
1536 /* ---- From here on, it's all reportage: construction is finished ---- */
1538 if (debugfile_switch)
1539 { begin_writing_debug_sections();
1540 write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1541 write_debug_section("code area", Write_Code_At);
1542 write_debug_section("string decoding table", Write_Strings_At);
1543 write_debug_section("strings area",
1544 Write_Strings_At + compression_table_size);
1545 write_debug_section("static array space", static_arrays_at);
1546 if (static_arrays_at + static_array_area_size < Write_RAM_At)
1547 { write_debug_section
1548 ("zero padding", static_arrays_at + static_array_area_size);
1551 { compiler_error("Failed assumption that globals are at start of "
1554 write_debug_section("global variables", Write_RAM_At + globals_at);
1555 write_debug_section("array space", Write_RAM_At + arrays_at);
1556 write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1557 write_debug_section("object tree", Write_RAM_At + object_tree_at);
1558 write_debug_section("common properties",
1559 Write_RAM_At + object_props_at);
1560 write_debug_section("property defaults",
1561 Write_RAM_At + prop_defaults_at);
1562 write_debug_section("class numbers",
1563 Write_RAM_At + class_numbers_offset);
1564 write_debug_section("identifier names",
1565 Write_RAM_At + identifier_names_offset);
1566 write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1567 write_debug_section("actions table", Write_RAM_At + actions_at);
1568 write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1569 if (MEMORY_MAP_EXTENSION)
1570 { write_debug_section("zero padding", Out_Size);
1572 end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1575 if (memory_map_setting)
1579 printf(" +---------------------+ 000000\n");
1580 printf("Read- | header | %s\n",
1581 show_percentage(GLULX_HEADER_SIZE, Out_Size));
1582 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE);
1583 printf("memory | memory layout id | %s\n",
1584 show_percentage(Write_Code_At-GLULX_HEADER_SIZE, Out_Size));
1585 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At);
1586 printf(" | code | %s\n",
1587 show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1588 printf(" +---------------------+ %06lx\n",
1589 (long int) Write_Strings_At);
1590 printf(" | string decode table | %s\n",
1591 show_percentage(compression_table_size, Out_Size));
1592 printf(" + - - - - - - - - - - + %06lx\n",
1593 (long int) Write_Strings_At + compression_table_size);
1594 addr = (static_array_area_size ? static_arrays_at : Write_RAM_At+globals_at);
1595 printf(" | strings | %s\n",
1596 show_percentage(addr-(Write_Strings_At + compression_table_size), Out_Size));
1597 if (static_array_area_size)
1599 printf(" +---------------------+ %06lx\n",
1600 (long int) (static_arrays_at));
1601 printf(" | static arrays | %s\n",
1602 show_percentage(Write_RAM_At+globals_at-static_arrays_at, Out_Size));
1604 printf(" +=====================+ %06lx\n",
1605 (long int) (Write_RAM_At+globals_at));
1606 printf("Dynamic | global variables | %s\n",
1607 show_percentage(arrays_at-globals_at, Out_Size));
1608 printf("memory + - - - - - - - - - - + %06lx\n",
1609 (long int) (Write_RAM_At+arrays_at));
1610 printf(" | arrays | %s\n",
1611 show_percentage(abbrevs_at-arrays_at, Out_Size));
1612 printf(" +---------------------+ %06lx\n",
1613 (long int) (Write_RAM_At+abbrevs_at));
1614 printf(" | printing variables | %s\n",
1615 show_percentage(object_tree_at-abbrevs_at, Out_Size));
1616 printf(" +---------------------+ %06lx\n",
1617 (long int) (Write_RAM_At+object_tree_at));
1618 printf(" | objects | %s\n",
1619 show_percentage(object_props_at-object_tree_at, Out_Size));
1620 printf(" + - - - - - - - - - - + %06lx\n",
1621 (long int) (Write_RAM_At+object_props_at));
1622 printf(" | property values | %s\n",
1623 show_percentage(prop_defaults_at-object_props_at, Out_Size));
1624 printf(" + - - - - - - - - - - + %06lx\n",
1625 (long int) (Write_RAM_At+prop_defaults_at));
1626 printf(" | property defaults | %s\n",
1627 show_percentage(class_numbers_offset-prop_defaults_at, Out_Size));
1628 printf(" + - - - - - - - - - - + %06lx\n",
1629 (long int) (Write_RAM_At+class_numbers_offset));
1630 printf(" | class numbers table | %s\n",
1631 show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
1632 printf(" + - - - - - - - - - - + %06lx\n",
1633 (long int) (Write_RAM_At+identifier_names_offset));
1634 printf(" | id names table | %s\n",
1635 show_percentage(grammar_table_at-identifier_names_offset, Out_Size));
1636 printf(" +---------------------+ %06lx\n",
1637 (long int) (Write_RAM_At+grammar_table_at));
1638 printf(" | grammar table | %s\n",
1639 show_percentage(actions_at-grammar_table_at, Out_Size));
1640 printf(" + - - - - - - - - - - + %06lx\n",
1641 (long int) (Write_RAM_At+actions_at));
1642 printf(" | actions | %s\n",
1643 show_percentage(dictionary_offset-(Write_RAM_At+actions_at), Out_Size));
1644 printf(" +---------------------+ %06lx\n",
1645 (long int) dictionary_offset);
1646 printf(" | dictionary | %s\n",
1647 show_percentage(Out_Size-dictionary_offset, Out_Size));
1648 if (MEMORY_MAP_EXTENSION == 0)
1650 printf(" +---------------------+ %06lx\n", (long int) Out_Size);
1654 printf(" +=====================+ %06lx\n", (long int) Out_Size);
1655 printf("Runtime | (empty) |\n"); /* no percentage */
1656 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1664 static void display_frequencies()
1668 printf("How frequently abbreviations were used, and roughly\n");
1669 printf("how many bytes they saved: ('_' denotes spaces)\n");
1671 for (i=0; i<no_abbreviations; i++) {
1674 saving = 2*((abbreviations[i].freq-1)*abbreviations[i].quality)/3;
1676 saving = (abbreviations[i].freq-1)*abbreviations[i].quality;
1678 char abbrev_string[MAX_ABBREV_LENGTH];
1679 strcpy(abbrev_string,
1680 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1681 for (j=0; abbrev_string[j]!=0; j++)
1682 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1684 printf("%10s %5d/%5d ",abbrev_string,abbreviations[i].freq, saving);
1686 if ((i%3)==2) printf("\n");
1688 if ((i%3)!=0) printf("\n");
1690 if (no_abbreviations==0) printf("None were declared.\n");
1693 static void display_statistics_z()
1697 uchar *p = (uchar *) zmachine_paged_memory;
1698 char *output_called = (module_switch)?"module":"story file";
1701 /* Yeah, we're repeating this calculation from construct_storyfile_z() */
1702 switch(version_number)
1703 { case 3: limit = 128; break;
1705 case 5: limit = 256; break;
1708 case 8: limit = 512; break;
1711 k_long=(Out_Size/1024);
1712 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1713 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1714 if (total_bytes_trans == 0) rate = 0;
1715 else rate=total_bytes_trans*1000/total_chars_trans;
1718 %3d source code files %6d syntactic lines\n\
1719 %6d textual lines %8ld characters ",
1720 total_input_files, no_syntax_lines,
1721 total_source_line_count, (long int) total_chars_read);
1722 if (character_set_unicode) printf("(UTF-8)\n");
1723 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1725 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1726 name_of_iso_set(character_set_setting));
1729 printf("Allocated:\n\
1730 %6d symbols %8ld bytes of memory\n\
1731 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1733 (long int) malloced_bytes,
1735 version_name(version_number),
1737 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
1738 (long int) k_long, k_str);
1741 %6d classes %6d objects\n\
1742 %6d global vars (maximum 233) %6d variable/array space\n",
1746 dynamic_array_area_size);
1749 "%6d verbs %6d dictionary entries\n\
1750 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1751 %6d actions %6d attributes (maximum %2d)\n\
1752 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
1755 no_grammar_lines, grammar_version_number,
1758 no_attributes, ((version_number==3)?32:48),
1759 no_properties-3, ((version_number==3)?29:61),
1760 no_individual_properties - 64);
1762 if (track_unused_routines)
1764 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1766 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
1767 (long int) df_total_size_before_stripping, (long int) diff,
1768 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1769 100 * (float)diff / (float)df_total_size_before_stripping);
1773 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1774 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1775 %6ld instructions of Z-code %6d sequence points\n\
1776 %6ld bytes readable memory used (maximum 65536)\n\
1777 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
1778 (long int) total_chars_trans,
1779 (long int) total_bytes_trans,
1780 (total_chars_trans>total_bytes_trans)?0:1,
1782 no_abbreviations, MAX_ABBREVS,
1784 (long int) no_instructions, no_sequence_points,
1785 (long int) Write_Code_At,
1786 (long int) Out_Size,
1788 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1793 static void display_statistics_g()
1797 int32 limit = 1024*1024;
1798 int32 strings_length = compression_table_size + compression_string_size;
1799 char *output_called = (module_switch)?"module":"story file";
1801 k_long=(Out_Size/1024);
1802 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1803 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1805 if (strings_length == 0) rate = 0;
1806 else rate=strings_length*1000/total_chars_trans;
1809 %3d source code files %6d syntactic lines\n\
1810 %6d textual lines %8ld characters ",
1811 total_input_files, no_syntax_lines,
1812 total_source_line_count, (long int) total_chars_read);
1813 if (character_set_unicode) printf("(UTF-8)\n");
1814 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1816 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1817 name_of_iso_set(character_set_setting));
1821 write_serial_number(serialnum);
1822 printf("Allocated:\n\
1823 %6d symbols %8ld bytes of memory\n\
1824 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1826 (long int) malloced_bytes,
1827 version_name(version_number),
1830 serialnum[0], serialnum[1], serialnum[2],
1831 serialnum[3], serialnum[4], serialnum[5],
1832 (long int) k_long, k_str);
1836 %6d classes %6d objects\n\
1837 %6d global vars %6d variable/array space\n",
1841 dynamic_array_area_size);
1844 "%6d verbs %6d dictionary entries\n\
1845 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1846 %6d actions %6d attributes (maximum %2d)\n\
1847 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1850 no_grammar_lines, grammar_version_number,
1853 no_attributes, NUM_ATTR_BYTES*8,
1854 no_properties-3, INDIV_PROP_START-3,
1855 no_individual_properties - INDIV_PROP_START);
1857 if (track_unused_routines)
1859 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1861 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1862 (long int) df_total_size_before_stripping, (long int) diff,
1863 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1864 100 * (float)diff / (float)df_total_size_before_stripping);
1868 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1869 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1870 %6ld instructions of code %6d sequence points\n\
1871 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1872 %6ld bytes used in machine %10ld bytes free in machine\n",
1873 (long int) total_chars_trans,
1874 (long int) strings_length,
1875 (total_chars_trans>strings_length)?0:1,
1877 no_abbreviations, MAX_ABBREVS,
1879 (long int) no_instructions, no_sequence_points,
1880 (long int) (Out_Size - Write_RAM_At),
1881 (long int) Write_RAM_At,
1882 (long int) Out_Size,
1884 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1890 extern void construct_storyfile(void)
1893 construct_storyfile_z();
1895 construct_storyfile_g();
1897 /* Display all the trace/stats info that came out of compilation.
1899 (Except for the memory map, which uses a bunch of local variables
1900 from construct_storyfile_z/g(), so it's easier to do that inside
1904 if (frequencies_setting)
1905 display_frequencies();
1907 if (list_symbols_setting)
1908 list_symbols(list_symbols_setting);
1910 if (list_dict_setting)
1911 show_dictionary(list_dict_setting);
1913 if (list_verbs_setting)
1916 if (list_objects_setting)
1919 if (statistics_switch) {
1921 display_statistics_z();
1923 display_statistics_g();
1927 /* ========================================================================= */
1928 /* Data structure management routines */
1929 /* ------------------------------------------------------------------------- */
1931 extern void init_tables_vars(void)
1934 statusline_flag = SCORE_STYLE;
1936 zmachine_paged_memory = NULL;
1939 code_offset = 0x800;
1940 actions_offset = 0x800;
1941 preactions_offset = 0x800;
1942 dictionary_offset = 0x800;
1943 adjectives_offset = 0x800;
1944 variables_offset = 0;
1945 strings_offset = 0xc00;
1946 individuals_offset=0x800;
1947 identifier_names_offset=0x800;
1948 class_numbers_offset = 0x800;
1949 arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1950 static_arrays_offset = 0x0800;
1953 code_offset = 0x12345;
1954 actions_offset = 0x12345;
1955 preactions_offset = 0x12345;
1956 dictionary_offset = 0x12345;
1957 adjectives_offset = 0x12345;
1958 variables_offset = 0x12345;
1959 arrays_offset = 0x12345;
1960 strings_offset = 0x12345;
1961 individuals_offset=0x12345;
1962 identifier_names_offset=0x12345;
1963 class_numbers_offset = 0x12345;
1964 static_arrays_offset = 0x12345;
1968 extern void tables_begin_pass(void)
1972 extern void tables_allocate_arrays(void)
1976 extern void tables_free_arrays(void)
1978 /* Allocation for this array happens in construct_storyfile() above */
1980 my_free(&zmachine_paged_memory,"output buffer");
1983 /* ========================================================================= */