1 /* ------------------------------------------------------------------------- */
2 /* "tables" : Constructs the story file (the output) up to the end */
3 /* of dynamic memory, gluing together all the required */
6 /* Part of Inform 6.41 */
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 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 */
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 + (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, 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 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 = "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;
430 mark+=objectsz[i].propsize;
433 /* ----------- Table of Class Prototype Object Numbers ---------------- */
435 class_numbers_offset = mark;
436 for (i=0; i<no_classes; i++)
437 { p[mark++] = class_info[i].object_number/256;
438 p[mark++] = class_info[i].object_number%256;
443 /* ------------------- Table of Identifier Names ---------------------- */
445 identifier_names_offset = mark;
448 { p[mark++] = no_individual_properties/256;
449 p[mark++] = no_individual_properties%256;
450 for (i=1; i<no_individual_properties; i++)
451 { p[mark++] = individual_name_strings[i]/256;
452 p[mark++] = individual_name_strings[i]%256;
455 attribute_names_offset = mark;
457 { p[mark++] = attribute_name_strings[i]/256;
458 p[mark++] = attribute_name_strings[i]%256;
461 action_names_offset = mark;
462 fake_action_names_offset = mark + 2*no_actions;
463 for (i=0; i<no_actions + no_fake_actions; i++)
464 { p[mark++] = action_name_strings[i]/256;
465 p[mark++] = action_name_strings[i]%256;
468 array_names_offset = mark;
469 global_names_offset = mark + 2*no_arrays;
470 routine_names_offset = global_names_offset + 2*no_globals;
471 constant_names_offset = routine_names_offset + 2*no_named_routines;
472 for (i=0; i<no_arrays + no_globals
473 + no_named_routines + no_named_constants; i++)
474 { if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
475 p[mark++] = array_name_strings[i]/256;
476 p[mark++] = array_name_strings[i]%256;
479 id_names_length = (mark - identifier_names_offset)/2;
481 routine_flags_array_offset = mark;
483 if (define_INFIX_switch)
484 { for (i=0, k=1, l=0; i<no_named_routines; i++)
485 { if (symbols[named_routine_symbols[i]].flags & STAR_SFLAG) l=l+k;
487 if (k==256) { p[mark++] = l; k=1; l=0; }
489 if (k!=1) p[mark++]=l;
492 /* ---------------- Table of Indiv Property Values -------------------- */
494 individuals_offset = mark;
495 for (i=0; i<individuals_length; i++)
496 p[mark++] = individuals_table[i];
498 /* ----------------- Variables and Dynamic Arrays --------------------- */
502 for (i=0; i<dynamic_array_area_size; i++)
503 p[mark++] = dynamic_array_area[i];
505 for (i=0; i<240; i++)
506 { j=global_initial_value[i];
507 p[globals_at+i*2] = j/256; p[globals_at+i*2+1] = j%256;
510 /* ------------------ Terminating Characters Table -------------------- */
512 if (version_number >= 5)
513 { terminating_chars_at = mark;
514 for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
518 /* ------------------------ Grammar Table ----------------------------- */
520 if (grammar_version_number > 2)
521 { warning("This version of Inform is unable to produce the grammar \
522 table format requested (producing number 2 format instead)");
523 grammar_version_number = 2;
526 grammar_table_at = mark;
528 mark = mark + no_Inform_verbs*2;
530 for (i=0; i<no_Inform_verbs; i++)
531 { p[grammar_table_at + i*2] = (mark/256);
532 p[grammar_table_at + i*2 + 1] = (mark%256);
533 p[mark++] = Inform_verbs[i].lines;
534 for (j=0; j<Inform_verbs[i].lines; j++)
535 { k = Inform_verbs[i].l[j];
536 if (grammar_version_number == 1)
538 p[mark+7] = grammar_lines[k+1];
539 for (m=1;m<=6;m++) p[mark + m] = 0;
540 k = k + 2; m = 1; n = 0;
541 while ((grammar_lines[k] != 15) && (m<=6))
542 { p[mark + m] = grammar_lines[k];
543 if (grammar_lines[k] < 180) n++;
551 p[mark++] = grammar_lines[k++];
552 p[mark++] = grammar_lines[k++];
554 { tok = grammar_lines[k++];
556 if (tok == 15) break;
557 p[mark++] = grammar_lines[k++];
558 p[mark++] = grammar_lines[k++];
564 /* ------------------- Actions and Preactions ------------------------- */
565 /* (The term "preactions" is traditional: Inform uses the preactions */
566 /* table for a different purpose than Infocom used to.) */
567 /* The values are written later, when the Z-code offset is known. */
568 /* -------------------------------------------------------------------- */
571 mark += no_actions*2;
573 preactions_at = mark;
574 if (grammar_version_number == 1)
575 mark += no_grammar_token_routines*2;
577 /* ----------------------- Adjectives Table --------------------------- */
579 if (grammar_version_number == 1)
580 { p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
581 adjectives_offset = mark;
582 dictionary_offset = mark + 4*no_adjectives;
584 for (i=0; i<no_adjectives; i++)
585 { j = final_dict_order[adjectives[no_adjectives-i-1]]
586 *DICT_ENTRY_BYTE_LENGTH
587 + dictionary_offset + 7;
588 p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
589 p[mark++]=(256-no_adjectives+i);
593 { p[mark]=0; p[mark+1]=0; mark+=2;
594 adjectives_offset = mark;
595 dictionary_offset = mark;
598 /* ------------------------- Dictionary ------------------------------- */
602 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
603 dictionary[2]=','; /* force words apart */
606 dictionary[4]=DICT_ENTRY_BYTE_LENGTH; /* Length of each entry */
607 dictionary[5]=(dict_entries/256); /* Number of entries */
608 dictionary[6]=(dict_entries%256);
610 for (i=0; i<7; i++) p[mark++] = dictionary[i];
612 for (i=0; i<dict_entries; i++)
613 { k = 7 + i*DICT_ENTRY_BYTE_LENGTH;
614 j = mark + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
615 for (l = 0; l<DICT_ENTRY_BYTE_LENGTH; l++)
616 p[j++] = dictionary[k++];
618 mark += dict_entries * DICT_ENTRY_BYTE_LENGTH;
620 /* ------------------------- Module Map ------------------------------- */
622 /* (no longer used) */
624 /* ------------------------ Static Arrays ----------------------------- */
626 static_arrays_at = mark;
627 for (i=0; i<static_array_area_size; i++)
628 p[mark++] = static_array_area[i];
630 /* ----------------- A gap before the code area ----------------------- */
631 /* (so that it will start at an exact packed address and so that all */
632 /* routine packed addresses are >= 256, hence long constants) */
633 /* -------------------------------------------------------------------- */
635 while ((mark%length_scale_factor) != 0) p[mark++]=0;
636 while (mark < (scale_factor*0x100)) p[mark++]=0;
637 if (oddeven_packing_switch)
638 while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
641 { error("This program has overflowed the maximum readable-memory \
642 size of the Z-machine format. See the memory map below: the start \
643 of the area marked \"above readable memory\" must be brought down to $FFFE \
645 memory_map_setting = 1;
646 /* Backpatching the grammar tables requires us to trust some of the */
647 /* addresses we've written into Z-machine memory, but they may have */
648 /* been truncated to 16 bits, so we can't do it. */
649 skip_backpatching = TRUE;
652 /* -------------------------- Code Area ------------------------------- */
653 /* (From this point on we don't write any more into the "p" buffer.) */
654 /* -------------------------------------------------------------------- */
656 Write_Code_At = mark;
657 if (!OMIT_UNUSED_ROUTINES) {
658 code_length = zmachine_pc;
661 if (zmachine_pc != df_total_size_before_stripping)
662 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
663 code_length = df_total_size_after_stripping;
667 /* ------------------ Another synchronising gap ----------------------- */
669 if (oddeven_packing_switch)
671 while ((mark%(scale_factor*2)) != scale_factor) mark++;
674 while ((mark%scale_factor) != 0) mark++;
676 /* ------------------------- Strings Area ----------------------------- */
678 Write_Strings_At = mark;
679 strings_length = static_strings_extent;
680 mark += strings_length;
682 /* --------------------- Module Linking Data -------------------------- */
684 /* (no longer used) */
686 /* --------------------- Is the file too big? ------------------------- */
690 switch(version_number)
691 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
693 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
696 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
700 { char memory_full_error[80];
701 sprintf(memory_full_error,
702 "The %s exceeds version-%d limit (%dK) by %d bytes",
703 output_called, version_number, limit, excess);
704 fatalerror(memory_full_error);
707 /* --------------------------- Offsets -------------------------------- */
709 dictionary_offset = dictionary_at;
710 variables_offset = globals_at;
711 actions_offset = actions_at;
712 preactions_offset = preactions_at;
713 prop_defaults_offset = prop_defaults_at;
714 prop_values_offset = object_props_at;
715 static_memory_offset = grammar_table_at;
716 grammar_table_offset = grammar_table_at;
717 static_arrays_offset = static_arrays_at;
719 if (extend_memory_map)
721 if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
722 while ((extend_offset%length_scale_factor) != 0) extend_offset++;
723 /* Not sure why above line is necessary, but oddeven_packing
724 * will need extend_offset to be even */
725 code_offset = extend_offset*scale_factor;
726 if (oddeven_packing_switch)
727 strings_offset = code_offset + scale_factor;
729 strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
731 /* With the extended memory model, need to specifically check that we
732 * haven't overflowed the packed address range for routines or strings.
733 * With the standard memory model, we only need the earlier total size
736 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
738 { char code_full_error[80];
739 sprintf(code_full_error,
740 "The code area limit has been exceeded by %d bytes",
742 fatalerror(code_full_error);
745 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
747 { char strings_full_error[140];
748 if (oddeven_packing_switch)
749 sprintf(strings_full_error,
750 "The strings area limit has been exceeded by %d bytes",
753 sprintf(strings_full_error,
754 "The code+strings area limit has been exceeded by %d bytes. \
755 Try running Inform again with -B on the command line.",
757 fatalerror(strings_full_error);
761 { code_offset = Write_Code_At;
762 strings_offset = Write_Strings_At;
765 /* --------------------------- The Header ----------------------------- */
767 for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */
769 p[0] = version_number; /* Version number */
770 p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */
771 p[2] = (release_number/256);
772 p[3] = (release_number%256); /* Release */
773 p[4] = (Write_Code_At/256);
774 p[5] = (Write_Code_At%256); /* End of paged memory */
775 if (version_number==6)
776 { j=code_offset/scale_factor; /* Packed address of "Main__" */
777 p[6]=(j/256); p[7]=(j%256);
780 { j=Write_Code_At+1; /* Initial PC value (bytes) */
781 p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */
783 p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */
784 p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */
785 p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */
786 p[14]=(grammar_table_at/256);
787 p[15]=(grammar_table_at%256); /* Grammar */
788 for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */
789 j+=k*flags2_requirements[i]; /* unusual opcodes assembled */
790 p[16]=j/256; p[17]=j%256;
791 write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
792 p[24]=abbrevs_at/256;
793 p[25]=abbrevs_at%256; /* Abbreviations table */
794 p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */
795 p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */
797 if (extend_memory_map)
798 { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
799 p[40]=j/256; p[41]=j%256; /* Routines offset */
800 if (oddeven_packing_switch)
801 j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
802 p[42]=j/256; p[43]=j%256; /* = Strings offset */
805 if (version_number >= 5)
806 { p[46] = terminating_chars_at/256; /* Terminating characters table */
807 p[47] = terminating_chars_at%256;
810 if (alphabet_modified)
812 p[52]=j/256; p[53]=j%256; } /* Character set table address */
815 p[54] = j/256; p[55] = j%256; /* Header extension table address */
817 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
819 p[62] = '0' + ((RELEASE_NUMBER/10)%10);
820 p[63] = '0' + RELEASE_NUMBER%10;
822 /* ------------------------ Header Extension -------------------------- */
824 /* The numbering in the spec is a little weird -- it's headerext_length
825 words *after* the initial length word. We follow the spec numbering
826 in this switch statement, so the count is 1-based. */
827 for (i=1; i<=headerext_length; i++) {
830 j = unicode_at; /* Unicode translation table address */
833 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
839 p[headerext_at+2*i+0] = j / 256;
840 p[headerext_at+2*i+1] = j % 256;
843 /* ----------------- The Header: Extras for modules ------------------- */
845 /* (no longer used) */
847 /* ---- Backpatch the Z-machine, now that all information is in ------- */
849 if (!skip_backpatching)
850 { backpatch_zmachine_image_z();
851 for (i=1; i<id_names_length; i++)
852 { int32 v = 256*p[identifier_names_offset + i*2]
853 + p[identifier_names_offset + i*2 + 1];
854 if (v!=0) v += strings_offset/scale_factor;
855 p[identifier_names_offset + i*2] = v/256;
856 p[identifier_names_offset + i*2 + 1] = v%256;
860 for (i=0; i<no_actions; i++)
861 { j=actions[i].byte_offset;
862 if (OMIT_UNUSED_ROUTINES)
863 j = df_stripped_address_for_address(j);
864 j += code_offset/scale_factor;
865 p[mark++]=j/256; p[mark++]=j%256;
868 if (grammar_version_number == 1)
869 { mark = preactions_at;
870 for (i=0; i<no_grammar_token_routines; i++)
871 { j=grammar_token_routine[i];
872 if (OMIT_UNUSED_ROUTINES)
873 j = df_stripped_address_for_address(j);
874 j += code_offset/scale_factor;
875 p[mark++]=j/256; p[mark++]=j%256;
879 { for (l = 0; l<no_Inform_verbs; l++)
880 { k = grammar_table_at + 2*l;
881 i = p[k]*256 + p[k+1];
882 for (j = p[i++]; j>0; j--)
883 { int topbits; int32 value;
886 { topbits = (p[i]/0x40) & 3;
887 value = p[i+1]*256 + p[i+2];
890 value = final_dict_order[value]
891 *DICT_ENTRY_BYTE_LENGTH
892 + dictionary_offset + 7;
895 if (OMIT_UNUSED_ROUTINES)
896 value = df_stripped_address_for_address(value);
897 value += code_offset/scale_factor;
900 p[i+1] = value/256; p[i+2] = value%256;
909 /* ---- From here on, it's all reportage: construction is finished ---- */
911 if (debugfile_switch)
912 { begin_writing_debug_sections();
913 write_debug_section("abbreviations", 64);
914 write_debug_section("abbreviations table", abbrevs_at);
915 write_debug_section("header extension", headerext_at);
916 if (alphabet_modified)
917 { write_debug_section("alphabets table", charset_at);
919 if (zscii_defn_modified)
920 { write_debug_section("Unicode table", unicode_at);
922 write_debug_section("property defaults", prop_defaults_at);
923 write_debug_section("object tree", object_tree_at);
924 write_debug_section("common properties", object_props_at);
925 write_debug_section("class numbers", class_numbers_offset);
926 write_debug_section("identifier names", identifier_names_offset);
927 write_debug_section("individual properties", individuals_offset);
928 write_debug_section("global variables", globals_at);
929 write_debug_section("array space", globals_at+480);
930 write_debug_section("grammar table", grammar_table_at);
931 write_debug_section("actions table", actions_at);
932 write_debug_section("parsing routines", preactions_at);
933 write_debug_section("adjectives table", adjectives_offset);
934 write_debug_section("dictionary", dictionary_at);
935 write_debug_section("code area", Write_Code_At);
936 write_debug_section("strings area", Write_Strings_At);
937 end_writing_debug_sections(Out_Size);
940 if (memory_map_setting)
944 printf("Dynamic +---------------------+ 00000\n");
945 printf("memory | header | %s\n",
946 show_percentage(0x40, Out_Size));
947 printf(" +---------------------+ 00040\n");
948 printf(" | abbreviations | %s\n",
949 show_percentage(abbrevs_at-0x40, Out_Size));
950 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at);
951 printf(" | abbreviations table | %s\n",
952 show_percentage(headerext_at-abbrevs_at, Out_Size));
953 printf(" +---------------------+ %05lx\n", (long int) headerext_at);
954 addr = (alphabet_modified ? charset_at : (zscii_defn_modified ? unicode_at : prop_defaults_at));
955 printf(" | header extension | %s\n",
956 show_percentage(addr-headerext_at, Out_Size));
957 if (alphabet_modified)
959 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at);
960 addr = (zscii_defn_modified ? unicode_at : prop_defaults_at);
961 printf(" | alphabets table | %s\n",
962 show_percentage(addr-charset_at, Out_Size));
964 if (zscii_defn_modified)
966 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at);
967 printf(" | Unicode table | %s\n",
968 show_percentage(prop_defaults_at-unicode_at, Out_Size));
970 printf(" +---------------------+ %05lx\n",
971 (long int) prop_defaults_at);
972 printf(" | property defaults | %s\n",
973 show_percentage(object_tree_at-prop_defaults_at, Out_Size));
974 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at);
975 printf(" | objects | %s\n",
976 show_percentage(object_props_at-object_tree_at, Out_Size));
977 printf(" + - - - - - - - - - - + %05lx\n",
978 (long int) object_props_at);
979 printf(" | object short names, |\n");
980 printf(" | common prop values | %s\n",
981 show_percentage(class_numbers_offset-object_props_at, Out_Size));
982 printf(" + - - - - - - - - - - + %05lx\n",
983 (long int) class_numbers_offset);
984 printf(" | class numbers table | %s\n",
985 show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
986 printf(" + - - - - - - - - - - + %05lx\n",
987 (long int) identifier_names_offset);
988 printf(" | symbol names table | %s\n",
989 show_percentage(individuals_offset-identifier_names_offset, Out_Size));
990 printf(" + - - - - - - - - - - + %05lx\n",
991 (long int) individuals_offset);
992 printf(" | indiv prop values | %s\n",
993 show_percentage(globals_at-individuals_offset, Out_Size));
994 printf(" +---------------------+ %05lx\n", (long int) globals_at);
995 printf(" | global variables | %s\n",
996 show_percentage(480, Out_Size));
997 printf(" + - - - - - - - - - - + %05lx\n",
998 ((long int) globals_at)+480L);
999 printf(" | arrays | %s\n",
1000 show_percentage(grammar_table_at-(globals_at+480), Out_Size));
1001 printf(" +=====================+ %05lx\n",
1002 (long int) grammar_table_at);
1003 printf("Readable| grammar table | %s\n",
1004 show_percentage(actions_at-grammar_table_at, Out_Size));
1005 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at);
1006 printf(" | actions | %s\n",
1007 show_percentage(preactions_at-actions_at, Out_Size));
1008 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at);
1009 printf(" | parsing routines | %s\n",
1010 show_percentage(adjectives_offset-preactions_at, Out_Size));
1011 printf(" + - - - - - - - - - - + %05lx\n",
1012 (long int) adjectives_offset);
1013 printf(" | adjectives | %s\n",
1014 show_percentage(dictionary_at-adjectives_offset, Out_Size));
1015 printf(" +---------------------+ %05lx\n", (long int) dictionary_at);
1016 addr = (static_array_area_size ? static_arrays_at : Write_Code_At);
1017 printf(" | dictionary | %s\n",
1018 show_percentage(addr-dictionary_at, Out_Size));
1019 if (static_array_area_size)
1021 printf(" +---------------------+ %05lx\n", (long int) static_arrays_at);
1022 printf(" | static arrays | %s\n",
1023 show_percentage(Write_Code_At-static_arrays_at, Out_Size));
1025 printf(" +=====================+ %05lx\n", (long int) Write_Code_At);
1026 printf("Above | Z-code | %s\n",
1027 show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1028 printf("readable+---------------------+ %05lx\n",
1029 (long int) Write_Strings_At);
1031 printf("memory | strings | %s\n",
1032 show_percentage(addr-Write_Strings_At, Out_Size));
1033 printf(" +---------------------+ %05lx\n", (long int) Out_Size);
1038 static void construct_storyfile_g(void)
1040 int32 i, j, k, l, mark, strings_length;
1041 int32 globals_at, dictionary_at, actions_at, preactions_at,
1042 abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1043 grammar_table_at, arrays_at, static_arrays_at;
1044 int32 threespaces, code_length;
1048 individual_name_strings =
1049 my_calloc(sizeof(int32), no_individual_properties,
1050 "identifier name strings");
1051 action_name_strings =
1052 my_calloc(sizeof(int32), no_actions + no_fake_actions,
1053 "action name strings");
1054 attribute_name_strings =
1055 my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1056 "attribute name strings");
1057 array_name_strings =
1058 my_calloc(sizeof(int32),
1060 "array name strings");
1062 write_the_identifier_names();
1063 threespaces = compile_string(" ", STRCTX_GAME);
1065 compress_game_text();
1067 /* We now know how large the buffer to hold our construction has to be */
1069 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1072 /* Foolish code to make this routine compile on all ANSI compilers */
1074 p = (uchar *) zmachine_paged_memory;
1076 /* In what follows, the "mark" will move upwards in memory: at various
1077 points its value will be recorded for milestones like
1078 "dictionary table start". It begins at 0x40, just after the header */
1080 /* Ok, our policy here will be to set the *_at values all relative
1081 to RAM. That's so we can write into zmachine_paged_memory[mark]
1082 and actually hit what we're aiming at.
1083 All the *_offset values will be set to true Glulx machine
1086 /* To get our bearings, figure out where the strings and code are. */
1087 /* We start with two words, which conventionally identify the
1088 memory layout. This is why the code starts eight bytes after
1090 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1091 if (!OMIT_UNUSED_ROUTINES) {
1092 code_length = zmachine_pc;
1095 if (zmachine_pc != df_total_size_before_stripping)
1096 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1097 code_length = df_total_size_after_stripping;
1099 Write_Strings_At = Write_Code_At + code_length;
1100 strings_length = compression_table_size + compression_string_size;
1102 static_arrays_at = Write_Strings_At + strings_length;
1104 /* Now figure out where RAM starts. */
1105 Write_RAM_At = static_arrays_at + static_array_area_size;
1106 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1107 while (Write_RAM_At % GPAGESIZE)
1110 /* Now work out all those RAM positions. */
1113 /* ----------------- Variables and Dynamic Arrays --------------------- */
1116 for (i=0; i<no_globals; i++) {
1117 j = global_initial_value[i];
1118 WriteInt32(p+mark, j);
1123 for (i=0; i<dynamic_array_area_size; i++)
1124 p[mark++] = dynamic_array_area[i];
1126 /* -------------------------- Dynamic Strings -------------------------- */
1129 WriteInt32(p+mark, no_dynamic_strings);
1131 for (i=0; i<no_dynamic_strings; i++) {
1132 j = Write_Strings_At + compressed_offsets[threespaces-1];
1133 WriteInt32(p+mark, j);
1137 /* -------------------- Objects and Properties ------------------------ */
1139 object_tree_at = mark;
1141 object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1143 for (i=0; i<no_objects; i++) {
1144 int32 objmark = mark;
1145 p[mark++] = 0x70; /* type byte -- object */
1146 for (j=0; j<NUM_ATTR_BYTES; j++) {
1147 p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1149 for (j=0; j<6; j++) {
1152 case 0: /* next object in the linked list. */
1153 if (i == no_objects-1)
1156 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1158 case 1: /* hardware name address */
1159 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1161 case 2: /* property table address */
1162 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1164 case 3: /* parent */
1165 if (objectsg[i].parent == 0)
1168 val = Write_RAM_At + object_tree_at +
1169 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1171 case 4: /* sibling */
1172 if (objectsg[i].next == 0)
1175 val = Write_RAM_At + object_tree_at +
1176 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1179 if (objectsg[i].child == 0)
1182 val = Write_RAM_At + object_tree_at +
1183 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1186 p[mark++] = (val >> 24) & 0xFF;
1187 p[mark++] = (val >> 16) & 0xFF;
1188 p[mark++] = (val >> 8) & 0xFF;
1189 p[mark++] = (val) & 0xFF;
1192 for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1197 if (object_props_at != mark)
1198 error("*** Object table was impossible length ***");
1200 for (i=0; i<properties_table_size; i++)
1201 p[mark+i]=properties_table[i];
1203 for (i=0; i<no_objects; i++) {
1204 int32 tableaddr = object_props_at + objectsg[i].propaddr;
1205 int32 tablelen = ReadInt32(p+tableaddr);
1207 for (j=0; j<tablelen; j++) {
1208 k = ReadInt32(p+tableaddr+4);
1209 k += (Write_RAM_At + object_props_at);
1210 WriteInt32(p+tableaddr+4, k);
1215 mark += properties_table_size;
1217 prop_defaults_at = mark;
1218 for (i=0; i<no_properties; i++) {
1219 k = commonprops[i].default_value;
1220 WriteInt32(p+mark, k);
1224 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1226 class_numbers_offset = mark;
1227 for (i=0; i<no_classes; i++) {
1228 j = Write_RAM_At + object_tree_at +
1229 (OBJECT_BYTE_LENGTH*(class_info[i].object_number-1));
1230 WriteInt32(p+mark, j);
1233 WriteInt32(p+mark, 0);
1236 /* -------------------- Table of Property Names ------------------------ */
1238 /* We try to format this bit with some regularity...
1239 address of common properties
1240 number of common properties
1241 address of indiv properties
1242 number of indiv properties (counted from INDIV_PROP_START)
1243 address of attributes
1244 number of attributes (always NUM_ATTR_BYTES*8)
1249 identifier_names_offset = mark;
1250 mark += 32; /* eight pairs of values, to be filled in. */
1252 WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1253 WriteInt32(p+identifier_names_offset+4, no_properties);
1254 for (i=0; i<no_properties; i++) {
1255 j = individual_name_strings[i];
1257 j = Write_Strings_At + compressed_offsets[j-1];
1258 WriteInt32(p+mark, j);
1262 WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1263 WriteInt32(p+identifier_names_offset+12,
1264 no_individual_properties-INDIV_PROP_START);
1265 for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1266 j = individual_name_strings[i];
1268 j = Write_Strings_At + compressed_offsets[j-1];
1269 WriteInt32(p+mark, j);
1273 WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1274 WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1275 for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1276 j = attribute_name_strings[i];
1278 j = Write_Strings_At + compressed_offsets[j-1];
1279 WriteInt32(p+mark, j);
1283 WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1284 WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1285 action_names_offset = mark;
1286 fake_action_names_offset = mark + 4*no_actions;
1287 for (i=0; i<no_actions + no_fake_actions; i++) {
1288 j = action_name_strings[i];
1290 j = Write_Strings_At + compressed_offsets[j-1];
1291 WriteInt32(p+mark, j);
1295 array_names_offset = mark;
1296 WriteInt32(p+mark, no_arrays);
1298 for (i=0; i<no_arrays; i++) {
1299 j = array_name_strings[i];
1301 j = Write_Strings_At + compressed_offsets[j-1];
1302 WriteInt32(p+mark, j);
1306 individuals_offset = mark;
1308 /* ------------------------ Grammar Table ----------------------------- */
1310 if (grammar_version_number != 2)
1311 { warning("This version of Inform is unable to produce the grammar \
1312 table format requested (producing number 2 format instead)");
1313 grammar_version_number = 2;
1316 grammar_table_at = mark;
1318 WriteInt32(p+mark, no_Inform_verbs);
1321 mark += no_Inform_verbs*4;
1323 for (i=0; i<no_Inform_verbs; i++) {
1324 j = mark + Write_RAM_At;
1325 WriteInt32(p+(grammar_table_at+4+i*4), j);
1326 p[mark++] = Inform_verbs[i].lines;
1327 for (j=0; j<Inform_verbs[i].lines; j++) {
1329 k = Inform_verbs[i].l[j];
1330 p[mark++] = grammar_lines[k++];
1331 p[mark++] = grammar_lines[k++];
1332 p[mark++] = grammar_lines[k++];
1334 tok = grammar_lines[k++];
1336 if (tok == 15) break;
1337 p[mark++] = grammar_lines[k++];
1338 p[mark++] = grammar_lines[k++];
1339 p[mark++] = grammar_lines[k++];
1340 p[mark++] = grammar_lines[k++];
1345 /* ------------------- Actions and Preactions ------------------------- */
1348 WriteInt32(p+mark, no_actions);
1350 mark += no_actions*4;
1351 /* Values to be written in later. */
1353 if (DICT_CHAR_SIZE != 1) {
1354 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1359 preactions_at = mark;
1360 adjectives_offset = mark;
1361 dictionary_offset = mark;
1363 /* ------------------------- Dictionary ------------------------------- */
1365 dictionary_at = mark;
1367 WriteInt32(dictionary+0, dict_entries);
1369 p[mark+i] = dictionary[i];
1371 for (i=0; i<dict_entries; i++) {
1372 k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1373 j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1374 for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1375 p[j++] = dictionary[k++];
1377 mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1379 /* -------------------------- All Data -------------------------------- */
1381 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1382 while (mark % GPAGESIZE)
1387 Out_Size = Write_RAM_At + RAM_Size;
1389 /* --------------------------- Offsets -------------------------------- */
1391 dictionary_offset = Write_RAM_At + dictionary_at;
1392 variables_offset = Write_RAM_At + globals_at;
1393 arrays_offset = Write_RAM_At + arrays_at;
1394 actions_offset = Write_RAM_At + actions_at;
1395 preactions_offset = Write_RAM_At + preactions_at;
1396 prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1397 object_tree_offset = Write_RAM_At + object_tree_at;
1398 prop_values_offset = Write_RAM_At + object_props_at;
1399 static_memory_offset = Write_RAM_At + grammar_table_at;
1400 grammar_table_offset = Write_RAM_At + grammar_table_at;
1401 abbreviations_offset = Write_RAM_At + abbrevs_at;
1403 code_offset = Write_Code_At;
1404 strings_offset = Write_Strings_At;
1405 static_arrays_offset = static_arrays_at;
1407 /* --------------------------- The Header ----------------------------- */
1409 /* ------ Backpatch the machine, now that all information is in ------- */
1412 { backpatch_zmachine_image_g();
1414 mark = actions_at + 4;
1415 for (i=0; i<no_actions; i++) {
1416 j = actions[i].byte_offset;
1417 if (OMIT_UNUSED_ROUTINES)
1418 j = df_stripped_address_for_address(j);
1420 WriteInt32(p+mark, j);
1424 for (l = 0; l<no_Inform_verbs; l++) {
1425 k = grammar_table_at + 4 + 4*l;
1426 i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1428 for (j = p[i++]; j>0; j--) {
1432 while (p[i] != 15) {
1433 topbits = (p[i]/0x40) & 3;
1434 value = ((p[i+1] << 24) | (p[i+2] << 16)
1435 | (p[i+3] << 8) | (p[i+4]));
1438 value = dictionary_offset + 4
1439 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1442 if (OMIT_UNUSED_ROUTINES)
1443 value = df_stripped_address_for_address(value);
1444 value += code_offset;
1447 WriteInt32(p+(i+1), value);
1456 /* ---- From here on, it's all reportage: construction is finished ---- */
1458 if (debugfile_switch)
1459 { begin_writing_debug_sections();
1460 write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1461 write_debug_section("code area", Write_Code_At);
1462 write_debug_section("string decoding table", Write_Strings_At);
1463 write_debug_section("strings area",
1464 Write_Strings_At + compression_table_size);
1465 write_debug_section("static array space", static_arrays_at);
1466 if (static_arrays_at + static_array_area_size < Write_RAM_At)
1467 { write_debug_section
1468 ("zero padding", static_arrays_at + static_array_area_size);
1471 { compiler_error("Failed assumption that globals are at start of "
1474 write_debug_section("global variables", Write_RAM_At + globals_at);
1475 write_debug_section("array space", Write_RAM_At + arrays_at);
1476 write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1477 write_debug_section("object tree", Write_RAM_At + object_tree_at);
1478 write_debug_section("common properties",
1479 Write_RAM_At + object_props_at);
1480 write_debug_section("property defaults",
1481 Write_RAM_At + prop_defaults_at);
1482 write_debug_section("class numbers",
1483 Write_RAM_At + class_numbers_offset);
1484 write_debug_section("identifier names",
1485 Write_RAM_At + identifier_names_offset);
1486 write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1487 write_debug_section("actions table", Write_RAM_At + actions_at);
1488 write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1489 if (MEMORY_MAP_EXTENSION)
1490 { write_debug_section("zero padding", Out_Size);
1492 end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1495 if (memory_map_setting)
1499 printf(" +---------------------+ 000000\n");
1500 printf("Read- | header | %s\n",
1501 show_percentage(GLULX_HEADER_SIZE, Out_Size));
1502 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE);
1503 printf("memory | memory layout id | %s\n",
1504 show_percentage(Write_Code_At-GLULX_HEADER_SIZE, Out_Size));
1505 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At);
1506 printf(" | code | %s\n",
1507 show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1508 printf(" +---------------------+ %06lx\n",
1509 (long int) Write_Strings_At);
1510 printf(" | string decode table | %s\n",
1511 show_percentage(compression_table_size, Out_Size));
1512 printf(" + - - - - - - - - - - + %06lx\n",
1513 (long int) Write_Strings_At + compression_table_size);
1514 addr = (static_array_area_size ? static_arrays_at : Write_RAM_At+globals_at);
1515 printf(" | strings | %s\n",
1516 show_percentage(addr-(Write_Strings_At + compression_table_size), Out_Size));
1517 if (static_array_area_size)
1519 printf(" +---------------------+ %06lx\n",
1520 (long int) (static_arrays_at));
1521 printf(" | static arrays | %s\n",
1522 show_percentage(Write_RAM_At+globals_at-static_arrays_at, Out_Size));
1524 printf(" +=====================+ %06lx\n",
1525 (long int) (Write_RAM_At+globals_at));
1526 printf("Dynamic | global variables | %s\n",
1527 show_percentage(arrays_at-globals_at, Out_Size));
1528 printf("memory + - - - - - - - - - - + %06lx\n",
1529 (long int) (Write_RAM_At+arrays_at));
1530 printf(" | arrays | %s\n",
1531 show_percentage(abbrevs_at-arrays_at, Out_Size));
1532 printf(" +---------------------+ %06lx\n",
1533 (long int) (Write_RAM_At+abbrevs_at));
1534 printf(" | printing variables | %s\n",
1535 show_percentage(object_tree_at-abbrevs_at, Out_Size));
1536 printf(" +---------------------+ %06lx\n",
1537 (long int) (Write_RAM_At+object_tree_at));
1538 printf(" | objects | %s\n",
1539 show_percentage(object_props_at-object_tree_at, Out_Size));
1540 printf(" + - - - - - - - - - - + %06lx\n",
1541 (long int) (Write_RAM_At+object_props_at));
1542 printf(" | property values | %s\n",
1543 show_percentage(prop_defaults_at-object_props_at, Out_Size));
1544 printf(" + - - - - - - - - - - + %06lx\n",
1545 (long int) (Write_RAM_At+prop_defaults_at));
1546 printf(" | property defaults | %s\n",
1547 show_percentage(class_numbers_offset-prop_defaults_at, Out_Size));
1548 printf(" + - - - - - - - - - - + %06lx\n",
1549 (long int) (Write_RAM_At+class_numbers_offset));
1550 printf(" | class numbers table | %s\n",
1551 show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
1552 printf(" + - - - - - - - - - - + %06lx\n",
1553 (long int) (Write_RAM_At+identifier_names_offset));
1554 printf(" | id names table | %s\n",
1555 show_percentage(grammar_table_at-identifier_names_offset, Out_Size));
1556 printf(" +---------------------+ %06lx\n",
1557 (long int) (Write_RAM_At+grammar_table_at));
1558 printf(" | grammar table | %s\n",
1559 show_percentage(actions_at-grammar_table_at, Out_Size));
1560 printf(" + - - - - - - - - - - + %06lx\n",
1561 (long int) (Write_RAM_At+actions_at));
1562 printf(" | actions | %s\n",
1563 show_percentage(dictionary_offset-(Write_RAM_At+actions_at), Out_Size));
1564 printf(" +---------------------+ %06lx\n",
1565 (long int) dictionary_offset);
1566 printf(" | dictionary | %s\n",
1567 show_percentage(Out_Size-dictionary_offset, Out_Size));
1568 if (MEMORY_MAP_EXTENSION == 0)
1570 printf(" +---------------------+ %06lx\n", (long int) Out_Size);
1574 printf(" +=====================+ %06lx\n", (long int) Out_Size);
1575 printf("Runtime | (empty) |\n"); /* no percentage */
1576 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1584 static void display_frequencies()
1588 printf("How frequently abbreviations were used, and roughly\n");
1589 printf("how many bytes they saved: ('_' denotes spaces)\n");
1591 for (i=0; i<no_abbreviations; i++) {
1594 saving = 2*((abbreviations[i].freq-1)*abbreviations[i].quality)/3;
1596 saving = (abbreviations[i].freq-1)*abbreviations[i].quality;
1598 char abbrev_string[MAX_ABBREV_LENGTH];
1599 strcpy(abbrev_string,
1600 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1601 for (j=0; abbrev_string[j]!=0; j++)
1602 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1604 printf("%10s %5d/%5d ",abbrev_string,abbreviations[i].freq, saving);
1606 if ((i%3)==2) printf("\n");
1608 if ((i%3)!=0) printf("\n");
1610 if (no_abbreviations==0) printf("None were declared.\n");
1613 static void display_statistics_z()
1617 uchar *p = (uchar *) zmachine_paged_memory;
1618 char *output_called = "story file";
1621 /* Yeah, we're repeating this calculation from construct_storyfile_z() */
1622 switch(version_number)
1623 { case 3: limit = 128; break;
1625 case 5: limit = 256; break;
1628 case 8: limit = 512; break;
1631 k_long=(Out_Size/1024);
1632 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1633 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1634 if (total_bytes_trans == 0) rate = 0;
1635 else rate=total_bytes_trans*1000/total_chars_trans;
1638 %3d source code files %6d syntactic lines\n\
1639 %6d textual lines %8ld characters ",
1640 total_input_files, no_syntax_lines,
1641 total_source_line_count, (long int) total_chars_read);
1642 if (character_set_unicode) printf("(UTF-8)\n");
1643 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1645 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1646 name_of_iso_set(character_set_setting));
1649 printf("Allocated:\n\
1650 %6d symbols %8ld bytes of memory\n\
1651 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1653 (long int) malloced_bytes,
1655 version_name(version_number),
1657 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
1658 (long int) k_long, k_str);
1661 %6d classes %6d objects\n\
1662 %6d global vars (maximum 233) %6d variable/array space\n",
1666 dynamic_array_area_size);
1669 "%6d verbs %6d dictionary entries\n\
1670 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1671 %6d actions %6d attributes (maximum %2d)\n\
1672 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
1675 no_grammar_lines, grammar_version_number,
1678 no_attributes, ((version_number==3)?32:48),
1679 no_properties-3, ((version_number==3)?29:61),
1680 no_individual_properties - 64);
1682 if (track_unused_routines)
1684 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1686 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
1687 (long int) df_total_size_before_stripping, (long int) diff,
1688 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1689 100 * (float)diff / (float)df_total_size_before_stripping);
1693 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1694 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1695 %6ld instructions of Z-code %6d sequence points\n\
1696 %6ld bytes readable memory used (maximum 65536)\n\
1697 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
1698 (long int) total_chars_trans,
1699 (long int) total_bytes_trans,
1700 (total_chars_trans>total_bytes_trans)?0:1,
1702 no_abbreviations, MAX_ABBREVS,
1704 (long int) no_instructions, no_sequence_points,
1705 (long int) Write_Code_At,
1706 (long int) Out_Size,
1708 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1713 static void display_statistics_g()
1717 int32 limit = 1024*1024;
1718 int32 strings_length = compression_table_size + compression_string_size;
1719 char *output_called = "story file";
1721 k_long=(Out_Size/1024);
1722 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1723 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1725 if (strings_length == 0) rate = 0;
1726 else rate=strings_length*1000/total_chars_trans;
1729 %3d source code files %6d syntactic lines\n\
1730 %6d textual lines %8ld characters ",
1731 total_input_files, no_syntax_lines,
1732 total_source_line_count, (long int) total_chars_read);
1733 if (character_set_unicode) printf("(UTF-8)\n");
1734 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1736 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1737 name_of_iso_set(character_set_setting));
1741 write_serial_number(serialnum);
1742 printf("Allocated:\n\
1743 %6d symbols %8ld bytes of memory\n\
1744 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1746 (long int) malloced_bytes,
1747 version_name(version_number),
1750 serialnum[0], serialnum[1], serialnum[2],
1751 serialnum[3], serialnum[4], serialnum[5],
1752 (long int) k_long, k_str);
1756 %6d classes %6d objects\n\
1757 %6d global vars %6d variable/array space\n",
1761 dynamic_array_area_size);
1764 "%6d verbs %6d dictionary entries\n\
1765 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1766 %6d actions %6d attributes (maximum %2d)\n\
1767 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1770 no_grammar_lines, grammar_version_number,
1773 no_attributes, NUM_ATTR_BYTES*8,
1774 no_properties-3, INDIV_PROP_START-3,
1775 no_individual_properties - INDIV_PROP_START);
1777 if (track_unused_routines)
1779 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1781 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1782 (long int) df_total_size_before_stripping, (long int) diff,
1783 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1784 100 * (float)diff / (float)df_total_size_before_stripping);
1788 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1789 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1790 %6ld instructions of code %6d sequence points\n\
1791 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1792 %6ld bytes used in machine %10ld bytes free in machine\n",
1793 (long int) total_chars_trans,
1794 (long int) strings_length,
1795 (total_chars_trans>strings_length)?0:1,
1797 no_abbreviations, MAX_ABBREVS,
1799 (long int) no_instructions, no_sequence_points,
1800 (long int) (Out_Size - Write_RAM_At),
1801 (long int) Write_RAM_At,
1802 (long int) Out_Size,
1804 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1810 extern void construct_storyfile(void)
1813 construct_storyfile_z();
1815 construct_storyfile_g();
1817 /* Display all the trace/stats info that came out of compilation.
1819 (Except for the memory map, which uses a bunch of local variables
1820 from construct_storyfile_z/g(), so it's easier to do that inside
1824 if (frequencies_setting)
1825 display_frequencies();
1827 if (list_symbols_setting)
1828 list_symbols(list_symbols_setting);
1830 if (list_dict_setting)
1831 show_dictionary(list_dict_setting);
1833 if (list_verbs_setting)
1836 if (list_objects_setting)
1839 if (statistics_switch) {
1841 display_statistics_z();
1843 display_statistics_g();
1847 /* ========================================================================= */
1848 /* Data structure management routines */
1849 /* ------------------------------------------------------------------------- */
1851 extern void init_tables_vars(void)
1854 statusline_flag = SCORE_STYLE;
1856 zmachine_paged_memory = NULL;
1859 code_offset = 0x800;
1860 actions_offset = 0x800;
1861 preactions_offset = 0x800;
1862 dictionary_offset = 0x800;
1863 adjectives_offset = 0x800;
1864 variables_offset = 0;
1865 strings_offset = 0xc00;
1866 individuals_offset=0x800;
1867 identifier_names_offset=0x800;
1868 class_numbers_offset = 0x800;
1869 arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1870 static_arrays_offset = 0x0800;
1873 code_offset = 0x12345;
1874 actions_offset = 0x12345;
1875 preactions_offset = 0x12345;
1876 dictionary_offset = 0x12345;
1877 adjectives_offset = 0x12345;
1878 variables_offset = 0x12345;
1879 arrays_offset = 0x12345;
1880 strings_offset = 0x12345;
1881 individuals_offset=0x12345;
1882 identifier_names_offset=0x12345;
1883 class_numbers_offset = 0x12345;
1884 static_arrays_offset = 0x12345;
1888 extern void tables_begin_pass(void)
1892 extern void tables_allocate_arrays(void)
1896 extern void tables_free_arrays(void)
1898 /* Allocation for this array happens in construct_storyfile() above */
1900 my_free(&zmachine_paged_memory,"output buffer");
1903 /* ========================================================================= */