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.42 */
7 /* copyright (c) Graham Nelson 1993 - 2024 */
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);
119 #ifdef TIME_UNAVAILABLE
120 sprintf(buffer,"970000");
122 /* Write a six-digit date, null-terminated. Fall back to "970000"
124 int len = strftime(buffer,7,"%y%m%d",localtime(&tt));
126 sprintf(buffer,"970000");
131 static char percentage_buffer[64];
133 static char *show_percentage(int32 x, int32 total)
135 if (memory_map_setting < 2) {
136 percentage_buffer[0] = '\0';
139 sprintf(percentage_buffer, " ( --- )");
141 else if (memory_map_setting < 3) {
142 sprintf(percentage_buffer, " (%.1f %%)", (float)x * 100.0 / (float)total);
145 sprintf(percentage_buffer, " (%.1f %%, %d bytes)", (float)x * 100.0 / (float)total, x);
147 return percentage_buffer;
150 static char *version_name(int v)
154 { case 3: return "Standard";
155 case 4: return "Plus";
156 case 5: return "Advanced";
157 case 6: return "Graphical";
158 case 7: return "Extended Alternate";
159 case 8: return "Extended";
161 return "experimental format";
168 static int32 rough_size_of_paged_memory_z(void)
170 /* This function calculates a modest over-estimate of the amount of
171 memory required to store the Z-machine's paged memory area
172 (that is, everything up to the start of the code area). */
178 total = 64 /* header */
179 + 2 + low_strings_top
180 /* low strings pool */
181 + 6*32; /* abbreviations table */
183 total += 8; /* header extension table */
184 if (ZCODE_HEADER_EXT_WORDS>3) total += (ZCODE_HEADER_EXT_WORDS-3)*2;
186 if (alphabet_modified) total += 78; /* character set table */
188 if (zscii_defn_modified) /* Unicode translation table */
189 total += 2 + 2*zscii_high_water_mark;
191 total += 2*((version_number==3)?31:63) /* property default values */
192 + no_objects*((version_number==3)?9:14) /* object tree table */
193 + properties_table_size /* property values of objects */
195 /* class object numbers table */
196 + no_symbols*2 /* names of numerous things */
197 + individuals_length /* tables of prop variables */
198 + dynamic_array_area_size; /* variables and arrays */
200 for (i=0; i<no_Inform_verbs; i++)
201 total += 2 + 1 + /* address of grammar table, */
202 /* number of grammar lines */
203 ((grammar_version_number == 1)?
204 (8*Inform_verbs[i].lines):0); /* grammar lines */
206 if (grammar_version_number != 1)
207 total += grammar_lines_top; /* size of grammar lines area */
209 total += 2 + 4*no_adjectives /* adjectives table */
210 + 2*no_actions /* action routines */
211 + 2*no_grammar_token_routines; /* general parsing routines */
213 total += (dictionary_top) /* dictionary size */
214 + (0); /* module map */
216 total += static_array_area_size; /* static arrays */
218 total += scale_factor*0x100 /* maximum null bytes before code */
219 + 1000; /* fudge factor (in case the above is wrong) */
224 static int32 rough_size_of_paged_memory_g(void)
226 /* This function calculates a modest over-estimate of the amount of
227 memory required to store the machine's paged memory area
228 (that is, everything past the start of RAM). */
234 /* No header for us! */
235 total = 1000; /* bit of a fudge factor */
237 total += no_globals * 4; /* global variables */
238 total += dynamic_array_area_size; /* arrays */
240 total += no_objects * OBJECT_BYTE_LENGTH; /* object tables */
241 total += properties_table_size; /* property tables */
242 total += no_properties * 4; /* property defaults table */
244 total += 4 + no_classes * 4; /* class prototype object numbers */
246 total += 32; /* address/length of the identifier tables */
247 total += no_properties * 4;
248 total += (no_individual_properties-INDIV_PROP_START) * 4;
249 total += (NUM_ATTR_BYTES*8) * 4;
250 total += (no_actions + no_fake_actions) * 4;
251 total += 4 + no_arrays * 4;
253 total += 4 + no_Inform_verbs * 4; /* index of grammar tables */
254 total += grammar_lines_top; /* grammar tables */
256 total += 4 + no_actions * 4; /* actions functions table */
259 total += dictionary_top;
261 while (total % GPAGESIZE)
267 static void construct_storyfile_z(void)
269 int32 i, j, k, l, mark, objs, strings_length, code_length,
270 limit=0, excess=0, extend_offset=0, headerext_length=0;
271 int32 globals_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
272 abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
273 grammar_table_at=0, charset_at=0, headerext_at=0,
274 terminating_chars_at=0, unicode_at=0, id_names_length=0,
277 int skip_backpatching = FALSE;
278 char *output_called = "story file";
282 if (!OMIT_SYMBOL_TABLE) {
283 individual_name_strings =
284 my_calloc(sizeof(int32), no_individual_properties,
285 "identifier name strings");
286 action_name_strings =
287 my_calloc(sizeof(int32), no_actions + no_fake_actions,
288 "action name strings");
289 attribute_name_strings =
290 my_calloc(sizeof(int32), 48,
291 "attribute name strings");
293 my_calloc(sizeof(int32),
295 "array name strings");
297 write_the_identifier_names();
300 /* We now know how large the buffer to hold our construction has to be */
302 rough_size = rough_size_of_paged_memory_z();
303 zmachine_paged_memory = my_malloc(rough_size, "output buffer");
305 /* Foolish code to make this routine compile on all ANSI compilers */
307 p = (uchar *) zmachine_paged_memory;
309 /* In what follows, the "mark" will move upwards in memory: at various
310 points its value will be recorded for milestones like
311 "dictionary table start". It begins at 0x40, just after the header */
313 for (mark=0; mark<0x40; mark++)
316 /* ----------------- Low Strings and Abbreviations -------------------- */
318 p[mark]=0x80; p[mark+1]=0; mark+=2; /* Start the low strings pool
319 with a useful default string, " " */
321 for (i=0; i<low_strings_top; mark++, i++) /* Low strings pool */
322 p[0x42+i]=low_strings[i];
326 if (MAX_ABBREVS + MAX_DYNAMIC_STRINGS != 96)
327 fatalerror("MAX_ABBREVS + MAX_DYNAMIC_STRINGS is not 96");
329 /* Initially all 96 entries are set to " ". (We store half of 0x40,
330 the address of the " " we wrote above.) */
331 for (i=0; i<3*32; i++)
332 { p[mark++]=0; p[mark++]=0x20;
335 /* Entries from 0 to MAX_DYNAMIC_STRINGS (default 32) are "variable
336 strings". Write the abbreviations after these. */
337 k = abbrevs_at+2*MAX_DYNAMIC_STRINGS;
338 for (i=0; i<no_abbreviations; i++)
339 { j=abbreviations[i].value;
344 /* ------------------- Header extension table ------------------------- */
347 headerext_length = ZCODE_HEADER_EXT_WORDS;
348 if (zscii_defn_modified) {
349 /* Need at least 3 words for unicode table address */
350 if (headerext_length < 3)
351 headerext_length = 3;
353 if (ZCODE_HEADER_FLAGS_3) {
354 /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
355 if (headerext_length < 4)
356 headerext_length = 4;
358 p[mark++] = 0; p[mark++] = headerext_length;
359 for (i=0; i<headerext_length; i++)
360 { p[mark++] = 0; p[mark++] = 0;
363 /* -------------------- Z-character set table ------------------------- */
365 if (alphabet_modified)
367 for (i=0;i<3;i++) for (j=0;j<26;j++)
368 { if (alphabet[i][j] == '~') p[mark++] = '\"';
369 else p[mark++] = alphabet[i][j];
373 /* ------------------ Unicode translation table ----------------------- */
376 if (zscii_defn_modified)
378 p[mark++] = zscii_high_water_mark;
379 for (i=0;i<zscii_high_water_mark;i++)
380 { j = zscii_to_unicode(155 + i);
381 if (j < 0 || j > 0xFFFF) {
382 error("Z-machine Unicode translation table cannot contain characters beyond $FFFF.");
384 p[mark++] = j/256; p[mark++] = j%256;
388 /* -------------------- Objects and Properties ------------------------ */
390 /* The object table must be word-aligned. The Z-machine spec does not
391 require this, but the RA__Pr() veneer routine does.
393 while ((mark%2) != 0) p[mark++]=0;
395 prop_defaults_at = mark;
397 p[mark++]=0; p[mark++]=0;
399 for (i=2; i< ((version_number==3)?32:64); i++)
400 { p[mark++]=commonprops[i].default_value/256;
401 p[mark++]=commonprops[i].default_value%256;
404 object_tree_at = mark;
406 mark += ((version_number==3)?9:14)*no_objects;
408 object_props_at = mark;
410 for (i=0; i<properties_table_size; i++)
411 p[mark+i]=properties_table[i];
413 for (i=0, objs=object_tree_at; i<no_objects; i++)
415 if (version_number == 3)
416 { p[objs]=objectsz[i].atts[0];
417 p[objs+1]=objectsz[i].atts[1];
418 p[objs+2]=objectsz[i].atts[2];
419 p[objs+3]=objectsz[i].atts[3];
420 p[objs+4]=objectsz[i].parent;
421 p[objs+5]=objectsz[i].next;
422 p[objs+6]=objectsz[i].child;
428 { p[objs]=objectsz[i].atts[0];
429 p[objs+1]=objectsz[i].atts[1];
430 p[objs+2]=objectsz[i].atts[2];
431 p[objs+3]=objectsz[i].atts[3];
432 p[objs+4]=objectsz[i].atts[4];
433 p[objs+5]=objectsz[i].atts[5];
434 p[objs+6]=(objectsz[i].parent)/256;
435 p[objs+7]=(objectsz[i].parent)%256;
436 p[objs+8]=(objectsz[i].next)/256;
437 p[objs+9]=(objectsz[i].next)%256;
438 p[objs+10]=(objectsz[i].child)/256;
439 p[objs+11]=(objectsz[i].child)%256;
444 mark+=objectsz[i].propsize;
447 /* ----------- Table of Class Prototype Object Numbers ---------------- */
449 class_numbers_offset = mark;
450 for (i=0; i<no_classes; i++)
451 { p[mark++] = class_info[i].object_number/256;
452 p[mark++] = class_info[i].object_number%256;
457 /* ------------------- Table of Identifier Names ---------------------- */
459 identifier_names_offset = mark;
461 if (!OMIT_SYMBOL_TABLE)
462 { p[mark++] = no_individual_properties/256;
463 p[mark++] = no_individual_properties%256;
464 for (i=1; i<no_individual_properties; i++)
465 { p[mark++] = individual_name_strings[i]/256;
466 p[mark++] = individual_name_strings[i]%256;
469 attribute_names_offset = mark;
471 { p[mark++] = attribute_name_strings[i]/256;
472 p[mark++] = attribute_name_strings[i]%256;
475 action_names_offset = mark;
476 fake_action_names_offset = mark + 2*no_actions;
477 for (i=0; i<no_actions + no_fake_actions; i++)
478 { p[mark++] = action_name_strings[i]/256;
479 p[mark++] = action_name_strings[i]%256;
482 array_names_offset = mark;
483 global_names_offset = mark + 2*no_arrays;
484 routine_names_offset = global_names_offset + 2*no_globals;
485 constant_names_offset = routine_names_offset + 2*no_named_routines;
486 for (i=0; i<no_arrays + no_globals
487 + no_named_routines + no_named_constants; i++)
488 { if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
489 p[mark++] = array_name_strings[i]/256;
490 p[mark++] = array_name_strings[i]%256;
493 id_names_length = (mark - identifier_names_offset)/2;
496 attribute_names_offset = mark;
497 action_names_offset = mark;
498 fake_action_names_offset = mark;
499 array_names_offset = mark;
500 global_names_offset = mark;
501 routine_names_offset = mark;
502 constant_names_offset = mark;
506 routine_flags_array_offset = mark;
508 if (define_INFIX_switch)
509 { for (i=0, k=1, l=0; i<no_named_routines; i++)
510 { if (symbols[named_routine_symbols[i]].flags & STAR_SFLAG) l=l+k;
512 if (k==256) { p[mark++] = l; k=1; l=0; }
514 if (k!=1) p[mark++]=l;
517 /* ---------------- Table of Indiv Property Values -------------------- */
519 individuals_offset = mark;
520 for (i=0; i<individuals_length; i++)
521 p[mark++] = individuals_table[i];
523 /* ----------------- Variables and Dynamic Arrays --------------------- */
527 for (i=0; i<dynamic_array_area_size; i++)
528 p[mark++] = dynamic_array_area[i];
530 for (i=0; i<240; i++)
531 { j=global_initial_value[i];
532 p[globals_at+i*2] = j/256; p[globals_at+i*2+1] = j%256;
535 /* ------------------ Terminating Characters Table -------------------- */
537 if (version_number >= 5)
538 { terminating_chars_at = mark;
539 for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
543 /* ------------------------ Grammar Table ----------------------------- */
545 if (grammar_version_number > 2)
546 { warning("This version of Inform is unable to produce the grammar \
547 table format requested (producing number 2 format instead)");
548 grammar_version_number = 2;
551 grammar_table_at = mark;
553 mark = mark + no_Inform_verbs*2;
555 for (i=0; i<no_Inform_verbs; i++)
556 { p[grammar_table_at + i*2] = (mark/256);
557 p[grammar_table_at + i*2 + 1] = (mark%256);
558 if (!Inform_verbs[i].used) {
559 /* This verb was marked unused at locate_dead_grammar_lines()
560 time. Omit the grammar lines. */
564 p[mark++] = Inform_verbs[i].lines;
565 for (j=0; j<Inform_verbs[i].lines; j++)
566 { k = Inform_verbs[i].l[j];
567 if (grammar_version_number == 1)
569 p[mark+7] = grammar_lines[k+1];
570 for (m=1;m<=6;m++) p[mark + m] = 0;
571 k = k + 2; m = 1; n = 0;
572 while ((grammar_lines[k] != 15) && (m<=6))
573 { p[mark + m] = grammar_lines[k];
574 if (grammar_lines[k] < 180) n++;
582 p[mark++] = grammar_lines[k++];
583 p[mark++] = grammar_lines[k++];
585 { tok = grammar_lines[k++];
587 if (tok == 15) break;
588 p[mark++] = grammar_lines[k++];
589 p[mark++] = grammar_lines[k++];
595 /* ------------------- Actions and Preactions ------------------------- */
596 /* (The term "preactions" is traditional: Inform uses the preactions */
597 /* table for a different purpose than Infocom used to.) */
598 /* The values are written later, when the Z-code offset is known. */
599 /* -------------------------------------------------------------------- */
602 mark += no_actions*2;
604 preactions_at = mark;
605 if (grammar_version_number == 1)
606 mark += no_grammar_token_routines*2;
608 /* ----------------------- Adjectives Table --------------------------- */
610 if (grammar_version_number == 1)
611 { p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
612 adjectives_offset = mark;
613 dictionary_offset = mark + 4*no_adjectives;
615 for (i=0; i<no_adjectives; i++)
616 { j = final_dict_order[adjectives[no_adjectives-i-1]]
617 *DICT_ENTRY_BYTE_LENGTH
618 + dictionary_offset + 7;
619 p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
620 p[mark++]=(256-no_adjectives+i);
624 { p[mark]=0; p[mark+1]=0; mark+=2;
625 adjectives_offset = mark;
626 dictionary_offset = mark;
629 /* ------------------------- Dictionary ------------------------------- */
633 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
634 dictionary[2]=','; /* force words apart */
637 dictionary[4]=DICT_ENTRY_BYTE_LENGTH; /* Length of each entry */
638 dictionary[5]=(dict_entries/256); /* Number of entries */
639 dictionary[6]=(dict_entries%256);
641 for (i=0; i<7; i++) p[mark++] = dictionary[i];
643 for (i=0; i<dict_entries; i++)
644 { k = 7 + i*DICT_ENTRY_BYTE_LENGTH;
645 j = mark + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
646 for (l = 0; l<DICT_ENTRY_BYTE_LENGTH; l++)
647 p[j++] = dictionary[k++];
649 mark += dict_entries * DICT_ENTRY_BYTE_LENGTH;
651 /* ------------------------- Module Map ------------------------------- */
653 /* (no longer used) */
655 /* ------------------------ Static Arrays ----------------------------- */
657 static_arrays_at = mark;
658 for (i=0; i<static_array_area_size; i++)
659 p[mark++] = static_array_area[i];
661 /* ----------------- A gap before the code area ----------------------- */
662 /* (so that it will start at an exact packed address and so that all */
663 /* routine packed addresses are >= 256, hence long constants) */
664 /* -------------------------------------------------------------------- */
666 while ((mark%length_scale_factor) != 0) p[mark++]=0;
667 while (mark < (scale_factor*0x100)) p[mark++]=0;
668 if (oddeven_packing_switch)
669 while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
672 { error("This program has overflowed the maximum readable-memory \
673 size of the Z-machine format. See the memory map below: the start \
674 of the area marked \"above readable memory\" must be brought down to $FFFE \
676 memory_map_setting = 1;
677 /* Backpatching the grammar tables requires us to trust some of the */
678 /* addresses we've written into Z-machine memory, but they may have */
679 /* been truncated to 16 bits, so we can't do it. */
680 skip_backpatching = TRUE;
683 /* -------------------------- Code Area ------------------------------- */
684 /* (From this point on we don't write any higher into the "p" buffer.) */
685 /* -------------------------------------------------------------------- */
687 if (mark > rough_size)
688 compiler_error("Paged size exceeds rough estimate.");
690 Write_Code_At = mark;
691 if (!OMIT_UNUSED_ROUTINES) {
692 code_length = zmachine_pc;
695 if (zmachine_pc != df_total_size_before_stripping)
696 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
697 code_length = df_total_size_after_stripping;
701 /* ------------------ Another synchronising gap ----------------------- */
703 if (oddeven_packing_switch)
705 while ((mark%(scale_factor*2)) != scale_factor) mark++;
708 while ((mark%scale_factor) != 0) mark++;
710 /* ------------------------- Strings Area ----------------------------- */
712 Write_Strings_At = mark;
713 strings_length = static_strings_extent;
714 mark += strings_length;
716 /* --------------------- Module Linking Data -------------------------- */
718 /* (no longer used) */
720 /* --------------------- Is the file too big? ------------------------- */
724 switch(version_number)
725 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
727 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
730 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
736 "The %s exceeds version-%d limit (%dK) by %d bytes",
737 output_called, version_number, limit, excess);
740 /* --------------------------- Offsets -------------------------------- */
742 dictionary_offset = dictionary_at;
743 variables_offset = globals_at;
744 actions_offset = actions_at;
745 preactions_offset = preactions_at;
746 prop_defaults_offset = prop_defaults_at;
747 prop_values_offset = object_props_at;
748 static_memory_offset = grammar_table_at;
749 grammar_table_offset = grammar_table_at;
750 static_arrays_offset = static_arrays_at;
752 if (extend_memory_map)
754 if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
755 while ((extend_offset%length_scale_factor) != 0) extend_offset++;
756 /* Not sure why above line is necessary, but oddeven_packing
757 * will need extend_offset to be even */
758 code_offset = extend_offset*scale_factor;
759 if (oddeven_packing_switch)
760 strings_offset = code_offset + scale_factor;
762 strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
764 /* With the extended memory model, need to specifically check that we
765 * haven't overflowed the packed address range for routines or strings.
766 * With the standard memory model, we only need the earlier total size
769 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
773 "The code area limit has been exceeded by %d bytes",
777 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
780 if (oddeven_packing_switch)
782 "The strings area limit has been exceeded by %d bytes",
786 "The code+strings area limit has been exceeded by %d bytes. \
787 Try running Inform again with -B on the command line.",
792 { code_offset = Write_Code_At;
793 strings_offset = Write_Strings_At;
796 /* --------------------------- The Header ----------------------------- */
798 for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */
800 p[0] = version_number; /* Version number */
801 p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */
802 p[2] = (release_number/256);
803 p[3] = (release_number%256); /* Release */
804 p[4] = (Write_Code_At/256);
805 p[5] = (Write_Code_At%256); /* End of paged memory */
806 if (version_number==6)
807 { j=code_offset/scale_factor; /* Packed address of "Main__" */
808 p[6]=(j/256); p[7]=(j%256);
811 { j=Write_Code_At+1; /* Initial PC value (bytes) */
812 p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */
814 p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */
815 p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */
816 p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */
817 p[14]=(grammar_table_at/256);
818 p[15]=(grammar_table_at%256); /* Grammar */
819 for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */
820 j+=k*flags2_requirements[i]; /* unusual opcodes assembled */
821 p[16]=j/256; p[17]=j%256;
822 write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
823 p[24]=abbrevs_at/256;
824 p[25]=abbrevs_at%256; /* Abbreviations table */
825 p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */
826 p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */
828 if (extend_memory_map)
829 { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
830 p[40]=j/256; p[41]=j%256; /* Routines offset */
831 if (oddeven_packing_switch)
832 j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
833 p[42]=j/256; p[43]=j%256; /* = Strings offset */
836 if (version_number >= 5)
837 { p[46] = terminating_chars_at/256; /* Terminating characters table */
838 p[47] = terminating_chars_at%256;
841 if (alphabet_modified)
843 p[52]=j/256; p[53]=j%256; } /* Character set table address */
846 p[54] = j/256; p[55] = j%256; /* Header extension table address */
848 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
850 p[62] = '0' + ((RELEASE_NUMBER/10)%10);
851 p[63] = '0' + RELEASE_NUMBER%10;
853 /* ------------------------ Header Extension -------------------------- */
855 /* The numbering in the spec is a little weird -- it's headerext_length
856 words *after* the initial length word. We follow the spec numbering
857 in this switch statement, so the count is 1-based. */
858 for (i=1; i<=headerext_length; i++) {
861 j = unicode_at; /* Unicode translation table address */
864 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
870 p[headerext_at+2*i+0] = j / 256;
871 p[headerext_at+2*i+1] = j % 256;
874 /* ----------------- The Header: Extras for modules ------------------- */
876 /* (no longer used) */
878 /* ---- Backpatch the Z-machine, now that all information is in ------- */
880 if (!skip_backpatching)
881 { backpatch_zmachine_image_z();
883 if (!OMIT_SYMBOL_TABLE) {
884 for (i=1; i<id_names_length; i++)
885 { int32 v = 256*p[identifier_names_offset + i*2]
886 + p[identifier_names_offset + i*2 + 1];
887 if (v!=0) v += strings_offset/scale_factor;
888 p[identifier_names_offset + i*2] = v/256;
889 p[identifier_names_offset + i*2 + 1] = v%256;
894 for (i=0; i<no_actions; i++)
895 { j=actions[i].byte_offset;
896 if (OMIT_UNUSED_ROUTINES)
897 j = df_stripped_address_for_address(j);
898 j += code_offset/scale_factor;
899 p[mark++]=j/256; p[mark++]=j%256;
902 if (grammar_version_number == 1)
903 { mark = preactions_at;
904 for (i=0; i<no_grammar_token_routines; i++)
905 { j=grammar_token_routine[i];
906 if (OMIT_UNUSED_ROUTINES)
907 j = df_stripped_address_for_address(j);
908 j += code_offset/scale_factor;
909 p[mark++]=j/256; p[mark++]=j%256;
913 { for (l = 0; l<no_Inform_verbs; l++)
914 { k = grammar_table_at + 2*l;
915 i = p[k]*256 + p[k+1];
916 for (j = p[i++]; j>0; j--)
917 { int topbits; int32 value;
920 { topbits = (p[i]/0x40) & 3;
921 value = p[i+1]*256 + p[i+2];
924 value = final_dict_order[value]
925 *DICT_ENTRY_BYTE_LENGTH
926 + dictionary_offset + 7;
929 if (OMIT_UNUSED_ROUTINES)
930 value = df_stripped_address_for_address(value);
931 value += code_offset/scale_factor;
934 p[i+1] = value/256; p[i+2] = value%256;
943 /* ---- From here on, it's all reportage: construction is finished ---- */
945 if (debugfile_switch)
946 { begin_writing_debug_sections();
947 write_debug_section("abbreviations", 64);
948 write_debug_section("abbreviations table", abbrevs_at);
949 write_debug_section("header extension", headerext_at);
950 if (alphabet_modified)
951 { write_debug_section("alphabets table", charset_at);
953 if (zscii_defn_modified)
954 { write_debug_section("Unicode table", unicode_at);
956 write_debug_section("property defaults", prop_defaults_at);
957 write_debug_section("object tree", object_tree_at);
958 write_debug_section("common properties", object_props_at);
959 write_debug_section("class numbers", class_numbers_offset);
960 write_debug_section("identifier names", identifier_names_offset);
961 write_debug_section("individual properties", individuals_offset);
962 write_debug_section("global variables", globals_at);
963 write_debug_section("array space", globals_at+480);
964 write_debug_section("grammar table", grammar_table_at);
965 write_debug_section("actions table", actions_at);
966 write_debug_section("parsing routines", preactions_at);
967 write_debug_section("adjectives table", adjectives_offset);
968 write_debug_section("dictionary", dictionary_at);
969 write_debug_section("code area", Write_Code_At);
970 write_debug_section("strings area", Write_Strings_At);
971 end_writing_debug_sections(Out_Size);
974 if (memory_map_setting)
978 printf("Dynamic +---------------------+ 00000\n");
979 printf("memory | header | %s\n",
980 show_percentage(0x40, Out_Size));
981 printf(" +---------------------+ 00040\n");
982 printf(" | abbreviations | %s\n",
983 show_percentage(abbrevs_at-0x40, Out_Size));
984 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at);
985 printf(" | abbreviations table | %s\n",
986 show_percentage(headerext_at-abbrevs_at, Out_Size));
987 printf(" +---------------------+ %05lx\n", (long int) headerext_at);
988 addr = (alphabet_modified ? charset_at : (zscii_defn_modified ? unicode_at : prop_defaults_at));
989 printf(" | header extension | %s\n",
990 show_percentage(addr-headerext_at, Out_Size));
991 if (alphabet_modified)
993 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at);
994 addr = (zscii_defn_modified ? unicode_at : prop_defaults_at);
995 printf(" | alphabets table | %s\n",
996 show_percentage(addr-charset_at, Out_Size));
998 if (zscii_defn_modified)
1000 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at);
1001 printf(" | Unicode table | %s\n",
1002 show_percentage(prop_defaults_at-unicode_at, Out_Size));
1004 printf(" +---------------------+ %05lx\n",
1005 (long int) prop_defaults_at);
1006 printf(" | property defaults | %s\n",
1007 show_percentage(object_tree_at-prop_defaults_at, Out_Size));
1008 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at);
1009 printf(" | objects | %s\n",
1010 show_percentage(object_props_at-object_tree_at, Out_Size));
1011 printf(" + - - - - - - - - - - + %05lx\n",
1012 (long int) object_props_at);
1013 printf(" | object short names, |\n");
1014 printf(" | common prop values | %s\n",
1015 show_percentage(class_numbers_offset-object_props_at, Out_Size));
1016 printf(" + - - - - - - - - - - + %05lx\n",
1017 (long int) class_numbers_offset);
1018 printf(" | class numbers table | %s\n",
1019 show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
1020 printf(" + - - - - - - - - - - + %05lx\n",
1021 (long int) identifier_names_offset);
1022 printf(" | symbol names table | %s\n",
1023 show_percentage(individuals_offset-identifier_names_offset, Out_Size));
1024 printf(" + - - - - - - - - - - + %05lx\n",
1025 (long int) individuals_offset);
1026 printf(" | indiv prop values | %s\n",
1027 show_percentage(globals_at-individuals_offset, Out_Size));
1028 printf(" +---------------------+ %05lx\n", (long int) globals_at);
1029 printf(" | global variables | %s\n",
1030 show_percentage(480, Out_Size));
1031 printf(" + - - - - - - - - - - + %05lx\n",
1032 ((long int) globals_at)+480L);
1033 printf(" | arrays | %s\n",
1034 show_percentage(grammar_table_at-(globals_at+480), Out_Size));
1035 printf(" +=====================+ %05lx\n",
1036 (long int) grammar_table_at);
1037 printf("Readable| grammar table | %s\n",
1038 show_percentage(actions_at-grammar_table_at, Out_Size));
1039 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at);
1040 printf(" | actions | %s\n",
1041 show_percentage(preactions_at-actions_at, Out_Size));
1042 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at);
1043 printf(" | parsing routines | %s\n",
1044 show_percentage(adjectives_offset-preactions_at, Out_Size));
1045 printf(" + - - - - - - - - - - + %05lx\n",
1046 (long int) adjectives_offset);
1047 printf(" | adjectives | %s\n",
1048 show_percentage(dictionary_at-adjectives_offset, Out_Size));
1049 printf(" +---------------------+ %05lx\n", (long int) dictionary_at);
1050 addr = (static_array_area_size ? static_arrays_at : Write_Code_At);
1051 printf(" | dictionary | %s\n",
1052 show_percentage(addr-dictionary_at, Out_Size));
1053 if (static_array_area_size)
1055 printf(" +---------------------+ %05lx\n", (long int) static_arrays_at);
1056 printf(" | static arrays | %s\n",
1057 show_percentage(Write_Code_At-static_arrays_at, Out_Size));
1059 printf(" +=====================+ %05lx\n", (long int) Write_Code_At);
1060 printf("Above | Z-code | %s\n",
1061 show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1062 printf("readable+---------------------+ %05lx\n",
1063 (long int) Write_Strings_At);
1065 printf("memory | strings | %s\n",
1066 show_percentage(addr-Write_Strings_At, Out_Size));
1067 printf(" +---------------------+ %05lx\n", (long int) Out_Size);
1072 static void construct_storyfile_g(void)
1074 int32 i, j, k, l, mark, strings_length;
1075 int32 globals_at, dictionary_at, actions_at, preactions_at,
1076 abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1077 grammar_table_at, arrays_at, static_arrays_at;
1078 int32 threespaces, code_length;
1083 individual_name_strings =
1084 my_calloc(sizeof(int32), no_individual_properties,
1085 "identifier name strings");
1086 action_name_strings =
1087 my_calloc(sizeof(int32), no_actions + no_fake_actions,
1088 "action name strings");
1089 attribute_name_strings =
1090 my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1091 "attribute name strings");
1092 array_name_strings =
1093 my_calloc(sizeof(int32),
1095 "array name strings");
1097 write_the_identifier_names();
1098 threespaces = compile_string(" ", STRCTX_GAME);
1100 compress_game_text();
1102 /* We now know how large the buffer to hold our construction has to be */
1104 rough_size = rough_size_of_paged_memory_g();
1105 zmachine_paged_memory = my_malloc(rough_size, "output buffer");
1107 /* Foolish code to make this routine compile on all ANSI compilers */
1109 p = (uchar *) zmachine_paged_memory;
1111 /* In what follows, the "mark" will move upwards in memory: at various
1112 points its value will be recorded for milestones like
1113 "dictionary table start". It begins at 0x40, just after the header */
1115 /* Ok, our policy here will be to set the *_at values all relative
1116 to RAM. That's so we can write into zmachine_paged_memory[mark]
1117 and actually hit what we're aiming at.
1118 All the *_offset values will be set to true Glulx machine
1121 /* To get our bearings, figure out where the strings and code are. */
1122 /* We start with two words, which conventionally identify the
1123 memory layout. This is why the code starts eight bytes after
1125 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1126 if (!OMIT_UNUSED_ROUTINES) {
1127 code_length = zmachine_pc;
1130 if (zmachine_pc != df_total_size_before_stripping)
1131 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1132 code_length = df_total_size_after_stripping;
1134 Write_Strings_At = Write_Code_At + code_length;
1135 strings_length = compression_table_size + compression_string_size;
1137 static_arrays_at = Write_Strings_At + strings_length;
1139 /* Now figure out where RAM starts. */
1140 Write_RAM_At = static_arrays_at + static_array_area_size;
1141 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1142 while (Write_RAM_At % GPAGESIZE)
1145 /* Now work out all those RAM positions. */
1148 /* ----------------- Variables and Dynamic Arrays --------------------- */
1151 for (i=0; i<no_globals; i++) {
1152 j = global_initial_value[i];
1153 WriteInt32(p+mark, j);
1158 for (i=0; i<dynamic_array_area_size; i++)
1159 p[mark++] = dynamic_array_area[i];
1161 /* -------------------------- Dynamic Strings -------------------------- */
1164 WriteInt32(p+mark, no_dynamic_strings);
1166 for (i=0; i<no_dynamic_strings; i++) {
1167 j = Write_Strings_At + compressed_offsets[threespaces-1];
1168 WriteInt32(p+mark, j);
1172 /* -------------------- Objects and Properties ------------------------ */
1174 object_tree_at = mark;
1176 object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1178 for (i=0; i<no_objects; i++) {
1179 int32 objmark = mark;
1180 p[mark++] = 0x70; /* type byte -- object */
1181 for (j=0; j<NUM_ATTR_BYTES; j++) {
1182 p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1184 for (j=0; j<6; j++) {
1187 case 0: /* next object in the linked list. */
1188 if (i == no_objects-1)
1191 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1193 case 1: /* hardware name address */
1194 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1196 case 2: /* property table address */
1197 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1199 case 3: /* parent */
1200 if (objectsg[i].parent == 0)
1203 val = Write_RAM_At + object_tree_at +
1204 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1206 case 4: /* sibling */
1207 if (objectsg[i].next == 0)
1210 val = Write_RAM_At + object_tree_at +
1211 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1214 if (objectsg[i].child == 0)
1217 val = Write_RAM_At + object_tree_at +
1218 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1221 p[mark++] = (val >> 24) & 0xFF;
1222 p[mark++] = (val >> 16) & 0xFF;
1223 p[mark++] = (val >> 8) & 0xFF;
1224 p[mark++] = (val) & 0xFF;
1227 for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1232 if (object_props_at != mark)
1233 error("*** Object table was impossible length ***");
1235 for (i=0; i<properties_table_size; i++)
1236 p[mark+i]=properties_table[i];
1238 for (i=0; i<no_objects; i++) {
1239 int32 tableaddr = object_props_at + objectsg[i].propaddr;
1240 int32 tablelen = ReadInt32(p+tableaddr);
1242 for (j=0; j<tablelen; j++) {
1243 k = ReadInt32(p+tableaddr+4);
1244 k += (Write_RAM_At + object_props_at);
1245 WriteInt32(p+tableaddr+4, k);
1250 mark += properties_table_size;
1252 prop_defaults_at = mark;
1253 for (i=0; i<no_properties; i++) {
1254 k = commonprops[i].default_value;
1255 WriteInt32(p+mark, k);
1259 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1261 class_numbers_offset = mark;
1262 for (i=0; i<no_classes; i++) {
1263 j = Write_RAM_At + object_tree_at +
1264 (OBJECT_BYTE_LENGTH*(class_info[i].object_number-1));
1265 WriteInt32(p+mark, j);
1268 WriteInt32(p+mark, 0);
1271 /* -------------------- Table of Property Names ------------------------ */
1273 /* We try to format this bit with some regularity...
1274 address of common properties
1275 number of common properties
1276 address of indiv properties
1277 number of indiv properties (counted from INDIV_PROP_START)
1278 address of attributes
1279 number of attributes (always NUM_ATTR_BYTES*8)
1284 if (!OMIT_SYMBOL_TABLE) {
1285 identifier_names_offset = mark;
1286 mark += 32; /* eight pairs of values, to be filled in. */
1288 WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1289 WriteInt32(p+identifier_names_offset+4, no_properties);
1290 for (i=0; i<no_properties; i++) {
1291 j = individual_name_strings[i];
1293 j = Write_Strings_At + compressed_offsets[j-1];
1294 WriteInt32(p+mark, j);
1298 WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1299 WriteInt32(p+identifier_names_offset+12,
1300 no_individual_properties-INDIV_PROP_START);
1301 for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1302 j = individual_name_strings[i];
1304 j = Write_Strings_At + compressed_offsets[j-1];
1305 WriteInt32(p+mark, j);
1309 WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1310 WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1311 for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1312 j = attribute_name_strings[i];
1314 j = Write_Strings_At + compressed_offsets[j-1];
1315 WriteInt32(p+mark, j);
1319 WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1320 WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1321 action_names_offset = mark;
1322 fake_action_names_offset = mark + 4*no_actions;
1323 for (i=0; i<no_actions + no_fake_actions; i++) {
1324 j = action_name_strings[i];
1326 j = Write_Strings_At + compressed_offsets[j-1];
1327 WriteInt32(p+mark, j);
1331 array_names_offset = mark;
1332 WriteInt32(p+mark, no_arrays);
1334 for (i=0; i<no_arrays; i++) {
1335 j = array_name_strings[i];
1337 j = Write_Strings_At + compressed_offsets[j-1];
1338 WriteInt32(p+mark, j);
1343 identifier_names_offset = mark;
1344 action_names_offset = mark;
1345 fake_action_names_offset = mark;
1346 array_names_offset = mark;
1349 individuals_offset = mark;
1351 /* ------------------------ Grammar Table ----------------------------- */
1353 if (grammar_version_number != 2)
1354 { warning("This version of Inform is unable to produce the grammar \
1355 table format requested (producing number 2 format instead)");
1356 grammar_version_number = 2;
1359 grammar_table_at = mark;
1361 WriteInt32(p+mark, no_Inform_verbs);
1364 mark += no_Inform_verbs*4;
1366 for (i=0; i<no_Inform_verbs; i++) {
1367 j = mark + Write_RAM_At;
1368 WriteInt32(p+(grammar_table_at+4+i*4), j);
1369 if (!Inform_verbs[i].used) {
1370 /* This verb was marked unused at locate_dead_grammar_lines()
1371 time. Omit the grammar lines. */
1375 p[mark++] = Inform_verbs[i].lines;
1376 for (j=0; j<Inform_verbs[i].lines; j++) {
1378 k = Inform_verbs[i].l[j];
1379 p[mark++] = grammar_lines[k++];
1380 p[mark++] = grammar_lines[k++];
1381 p[mark++] = grammar_lines[k++];
1383 tok = grammar_lines[k++];
1385 if (tok == 15) break;
1386 p[mark++] = grammar_lines[k++];
1387 p[mark++] = grammar_lines[k++];
1388 p[mark++] = grammar_lines[k++];
1389 p[mark++] = grammar_lines[k++];
1394 /* ------------------- Actions and Preactions ------------------------- */
1397 WriteInt32(p+mark, no_actions);
1399 mark += no_actions*4;
1400 /* Values to be written in later. */
1402 if (DICT_CHAR_SIZE != 1) {
1403 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1408 preactions_at = mark;
1409 adjectives_offset = mark;
1410 dictionary_offset = mark;
1412 /* ------------------------- Dictionary ------------------------------- */
1414 dictionary_at = mark;
1416 WriteInt32(dictionary+0, dict_entries);
1418 p[mark+i] = dictionary[i];
1420 for (i=0; i<dict_entries; i++) {
1421 k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1422 j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1423 for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1424 p[j++] = dictionary[k++];
1426 mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1428 /* -------------------------- All Data -------------------------------- */
1430 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1431 while (mark % GPAGESIZE)
1436 if (RAM_Size > rough_size)
1437 compiler_error("RAM size exceeds rough estimate.");
1439 Out_Size = Write_RAM_At + RAM_Size;
1441 /* --------------------------- Offsets -------------------------------- */
1443 dictionary_offset = Write_RAM_At + dictionary_at;
1444 variables_offset = Write_RAM_At + globals_at;
1445 arrays_offset = Write_RAM_At + arrays_at;
1446 actions_offset = Write_RAM_At + actions_at;
1447 preactions_offset = Write_RAM_At + preactions_at;
1448 prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1449 object_tree_offset = Write_RAM_At + object_tree_at;
1450 prop_values_offset = Write_RAM_At + object_props_at;
1451 static_memory_offset = Write_RAM_At + grammar_table_at;
1452 grammar_table_offset = Write_RAM_At + grammar_table_at;
1453 abbreviations_offset = Write_RAM_At + abbrevs_at;
1455 code_offset = Write_Code_At;
1456 strings_offset = Write_Strings_At;
1457 static_arrays_offset = static_arrays_at;
1459 /* --------------------------- The Header ----------------------------- */
1461 /* ------ Backpatch the machine, now that all information is in ------- */
1464 { backpatch_zmachine_image_g();
1466 mark = actions_at + 4;
1467 for (i=0; i<no_actions; i++) {
1468 j = actions[i].byte_offset;
1469 if (OMIT_UNUSED_ROUTINES)
1470 j = df_stripped_address_for_address(j);
1472 WriteInt32(p+mark, j);
1476 for (l = 0; l<no_Inform_verbs; l++) {
1477 k = grammar_table_at + 4 + 4*l;
1478 i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1480 for (j = p[i++]; j>0; j--) {
1484 while (p[i] != 15) {
1485 topbits = (p[i]/0x40) & 3;
1486 value = ((p[i+1] << 24) | (p[i+2] << 16)
1487 | (p[i+3] << 8) | (p[i+4]));
1490 value = dictionary_offset + 4
1491 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1494 if (OMIT_UNUSED_ROUTINES)
1495 value = df_stripped_address_for_address(value);
1496 value += code_offset;
1499 WriteInt32(p+(i+1), value);
1508 /* ---- From here on, it's all reportage: construction is finished ---- */
1510 if (debugfile_switch)
1511 { begin_writing_debug_sections();
1512 write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1513 write_debug_section("code area", Write_Code_At);
1514 write_debug_section("string decoding table", Write_Strings_At);
1515 write_debug_section("strings area",
1516 Write_Strings_At + compression_table_size);
1517 write_debug_section("static array space", static_arrays_at);
1518 if (static_arrays_at + static_array_area_size < Write_RAM_At)
1519 { write_debug_section
1520 ("zero padding", static_arrays_at + static_array_area_size);
1523 { compiler_error("Failed assumption that globals are at start of "
1526 write_debug_section("global variables", Write_RAM_At + globals_at);
1527 write_debug_section("array space", Write_RAM_At + arrays_at);
1528 write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1529 write_debug_section("object tree", Write_RAM_At + object_tree_at);
1530 write_debug_section("common properties",
1531 Write_RAM_At + object_props_at);
1532 write_debug_section("property defaults",
1533 Write_RAM_At + prop_defaults_at);
1534 write_debug_section("class numbers",
1535 Write_RAM_At + class_numbers_offset);
1536 write_debug_section("identifier names",
1537 Write_RAM_At + identifier_names_offset);
1538 write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1539 write_debug_section("actions table", Write_RAM_At + actions_at);
1540 write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1541 if (MEMORY_MAP_EXTENSION)
1542 { write_debug_section("zero padding", Out_Size);
1544 end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1547 if (memory_map_setting)
1551 printf(" +---------------------+ 000000\n");
1552 printf("Read- | header | %s\n",
1553 show_percentage(GLULX_HEADER_SIZE, Out_Size));
1554 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE);
1555 printf("memory | memory layout id | %s\n",
1556 show_percentage(Write_Code_At-GLULX_HEADER_SIZE, Out_Size));
1557 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At);
1558 printf(" | code | %s\n",
1559 show_percentage(Write_Strings_At-Write_Code_At, Out_Size));
1560 printf(" +---------------------+ %06lx\n",
1561 (long int) Write_Strings_At);
1562 printf(" | string decode table | %s\n",
1563 show_percentage(compression_table_size, Out_Size));
1564 printf(" + - - - - - - - - - - + %06lx\n",
1565 (long int) Write_Strings_At + compression_table_size);
1566 addr = (static_array_area_size ? static_arrays_at : Write_RAM_At+globals_at);
1567 printf(" | strings | %s\n",
1568 show_percentage(addr-(Write_Strings_At + compression_table_size), Out_Size));
1569 if (static_array_area_size)
1571 printf(" +---------------------+ %06lx\n",
1572 (long int) (static_arrays_at));
1573 printf(" | static arrays | %s\n",
1574 show_percentage(Write_RAM_At+globals_at-static_arrays_at, Out_Size));
1576 printf(" +=====================+ %06lx\n",
1577 (long int) (Write_RAM_At+globals_at));
1578 printf("Dynamic | global variables | %s\n",
1579 show_percentage(arrays_at-globals_at, Out_Size));
1580 printf("memory + - - - - - - - - - - + %06lx\n",
1581 (long int) (Write_RAM_At+arrays_at));
1582 printf(" | arrays | %s\n",
1583 show_percentage(abbrevs_at-arrays_at, Out_Size));
1584 printf(" +---------------------+ %06lx\n",
1585 (long int) (Write_RAM_At+abbrevs_at));
1586 printf(" | printing variables | %s\n",
1587 show_percentage(object_tree_at-abbrevs_at, Out_Size));
1588 printf(" +---------------------+ %06lx\n",
1589 (long int) (Write_RAM_At+object_tree_at));
1590 printf(" | objects | %s\n",
1591 show_percentage(object_props_at-object_tree_at, Out_Size));
1592 printf(" + - - - - - - - - - - + %06lx\n",
1593 (long int) (Write_RAM_At+object_props_at));
1594 printf(" | property values | %s\n",
1595 show_percentage(prop_defaults_at-object_props_at, Out_Size));
1596 printf(" + - - - - - - - - - - + %06lx\n",
1597 (long int) (Write_RAM_At+prop_defaults_at));
1598 printf(" | property defaults | %s\n",
1599 show_percentage(class_numbers_offset-prop_defaults_at, Out_Size));
1600 printf(" + - - - - - - - - - - + %06lx\n",
1601 (long int) (Write_RAM_At+class_numbers_offset));
1602 printf(" | class numbers table | %s\n",
1603 show_percentage(identifier_names_offset-class_numbers_offset, Out_Size));
1604 printf(" + - - - - - - - - - - + %06lx\n",
1605 (long int) (Write_RAM_At+identifier_names_offset));
1606 printf(" | id names table | %s\n",
1607 show_percentage(grammar_table_at-identifier_names_offset, Out_Size));
1608 printf(" +---------------------+ %06lx\n",
1609 (long int) (Write_RAM_At+grammar_table_at));
1610 printf(" | grammar table | %s\n",
1611 show_percentage(actions_at-grammar_table_at, Out_Size));
1612 printf(" + - - - - - - - - - - + %06lx\n",
1613 (long int) (Write_RAM_At+actions_at));
1614 printf(" | actions | %s\n",
1615 show_percentage(dictionary_offset-(Write_RAM_At+actions_at), Out_Size));
1616 printf(" +---------------------+ %06lx\n",
1617 (long int) dictionary_offset);
1618 printf(" | dictionary | %s\n",
1619 show_percentage(Out_Size-dictionary_offset, Out_Size));
1620 if (MEMORY_MAP_EXTENSION == 0)
1622 printf(" +---------------------+ %06lx\n", (long int) Out_Size);
1626 printf(" +=====================+ %06lx\n", (long int) Out_Size);
1627 printf("Runtime | (empty) |\n"); /* no percentage */
1628 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1636 static void display_frequencies()
1640 printf("How frequently abbreviations were used, and roughly\n");
1641 printf("how many bytes they saved: ('_' denotes spaces)\n");
1643 for (i=0; i<no_abbreviations; i++) {
1647 saving = 2*((abbreviations[i].freq-1)*abbreviations[i].quality)/3;
1649 saving = (abbreviations[i].freq-1)*abbreviations[i].quality;
1651 astr = abbreviation_text(i);
1652 /* Print the abbreviation text, left-padded to ten spaces, with
1653 spaces replaced by underscores. */
1654 for (j=strlen(astr); j<10; j++) {
1657 for (j=0; astr[j]; j++) {
1658 putchar(astr[j] == ' ' ? '_' : astr[j]);
1661 printf(" %5d/%5d ", abbreviations[i].freq, saving);
1663 if ((i%3)==2) printf("\n");
1665 if ((i%3)!=0) printf("\n");
1667 if (no_abbreviations==0) printf("None were declared.\n");
1670 static void display_statistics_z()
1674 uchar *p = (uchar *) zmachine_paged_memory;
1675 char *output_called = "story file";
1678 /* Yeah, we're repeating this calculation from construct_storyfile_z() */
1679 switch(version_number)
1680 { case 3: limit = 128; break;
1682 case 5: limit = 256; break;
1685 case 8: limit = 512; break;
1688 k_long=(Out_Size/1024);
1689 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1690 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1691 if (total_bytes_trans == 0) rate = 0;
1692 else rate=total_bytes_trans*1000/total_chars_trans;
1695 %3d source code files %6d syntactic lines\n\
1696 %6d textual lines %8ld characters ",
1697 total_input_files, no_syntax_lines,
1698 total_source_line_count, (long int) total_chars_read);
1699 if (character_set_unicode) printf("(UTF-8)\n");
1700 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1702 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1703 name_of_iso_set(character_set_setting));
1706 printf("Allocated:\n\
1707 %6d symbols %8ld bytes of memory\n\
1708 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1710 (long int) malloced_bytes,
1712 version_name(version_number),
1714 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
1715 (long int) k_long, k_str);
1718 %6d classes %6d objects\n\
1719 %6d global vars (maximum 233) %6d variable/array space\n",
1723 dynamic_array_area_size);
1726 "%6d verbs %6d dictionary entries\n\
1727 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1728 %6d actions %6d attributes (maximum %2d)\n\
1729 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
1732 no_grammar_lines, grammar_version_number,
1735 no_attributes, ((version_number==3)?32:48),
1736 no_properties-3, ((version_number==3)?29:61),
1737 no_individual_properties - 64);
1739 if (track_unused_routines)
1741 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1743 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
1744 (long int) df_total_size_before_stripping, (long int) diff,
1745 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1746 100 * (float)diff / (float)df_total_size_before_stripping);
1750 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1751 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1752 %6ld instructions of Z-code %6d sequence points\n\
1753 %6ld bytes readable memory used (maximum 65536)\n\
1754 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
1755 (long int) total_chars_trans,
1756 (long int) total_bytes_trans,
1757 (total_chars_trans>total_bytes_trans)?0:1,
1759 no_abbreviations, MAX_ABBREVS,
1761 (long int) no_instructions, no_sequence_points,
1762 (long int) Write_Code_At,
1763 (long int) Out_Size,
1765 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1770 static void display_statistics_g()
1774 int32 limit = 1024*1024;
1775 int32 strings_length = compression_table_size + compression_string_size;
1776 char *output_called = "story file";
1778 k_long=(Out_Size/1024);
1779 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1780 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1782 if (strings_length == 0) rate = 0;
1783 else rate=strings_length*1000/total_chars_trans;
1786 %3d source code files %6d syntactic lines\n\
1787 %6d textual lines %8ld characters ",
1788 total_input_files, no_syntax_lines,
1789 total_source_line_count, (long int) total_chars_read);
1790 if (character_set_unicode) printf("(UTF-8)\n");
1791 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1793 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1794 name_of_iso_set(character_set_setting));
1798 write_serial_number(serialnum);
1799 printf("Allocated:\n\
1800 %6d symbols %8ld bytes of memory\n\
1801 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1803 (long int) malloced_bytes,
1804 version_name(version_number),
1807 serialnum[0], serialnum[1], serialnum[2],
1808 serialnum[3], serialnum[4], serialnum[5],
1809 (long int) k_long, k_str);
1813 %6d classes %6d objects\n\
1814 %6d global vars %6d variable/array space\n",
1818 dynamic_array_area_size);
1821 "%6d verbs %6d dictionary entries\n\
1822 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1823 %6d actions %6d attributes (maximum %2d)\n\
1824 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1827 no_grammar_lines, grammar_version_number,
1830 no_attributes, NUM_ATTR_BYTES*8,
1831 no_properties-3, INDIV_PROP_START-3,
1832 no_individual_properties - INDIV_PROP_START);
1834 if (track_unused_routines)
1836 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1838 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1839 (long int) df_total_size_before_stripping, (long int) diff,
1840 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1841 100 * (float)diff / (float)df_total_size_before_stripping);
1845 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1846 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1847 %6ld instructions of code %6d sequence points\n\
1848 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1849 %6ld bytes used in machine %10ld bytes free in machine\n",
1850 (long int) total_chars_trans,
1851 (long int) strings_length,
1852 (total_chars_trans>strings_length)?0:1,
1854 no_abbreviations, MAX_ABBREVS,
1856 (long int) no_instructions, no_sequence_points,
1857 (long int) (Out_Size - Write_RAM_At),
1858 (long int) Write_RAM_At,
1859 (long int) Out_Size,
1861 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1867 extern void construct_storyfile(void)
1870 construct_storyfile_z();
1872 construct_storyfile_g();
1874 /* Display all the trace/stats info that came out of compilation.
1876 (Except for the memory map, which uses a bunch of local variables
1877 from construct_storyfile_z/g(), so it's easier to do that inside
1881 if (frequencies_setting)
1882 display_frequencies();
1884 if (list_symbols_setting)
1885 list_symbols(list_symbols_setting);
1887 if (list_dict_setting)
1888 show_dictionary(list_dict_setting);
1890 if (list_verbs_setting)
1893 if (list_objects_setting)
1896 if (statistics_switch) {
1898 display_statistics_z();
1900 display_statistics_g();
1904 /* ========================================================================= */
1905 /* Data structure management routines */
1906 /* ------------------------------------------------------------------------- */
1908 extern void init_tables_vars(void)
1911 statusline_flag = SCORE_STYLE;
1913 zmachine_paged_memory = NULL;
1916 code_offset = 0x800;
1917 actions_offset = 0x800;
1918 preactions_offset = 0x800;
1919 dictionary_offset = 0x800;
1920 adjectives_offset = 0x800;
1921 variables_offset = 0;
1922 strings_offset = 0xc00;
1923 individuals_offset=0x800;
1924 identifier_names_offset=0x800;
1925 class_numbers_offset = 0x800;
1926 arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1927 static_arrays_offset = 0x0800;
1930 code_offset = 0x12345;
1931 actions_offset = 0x12345;
1932 preactions_offset = 0x12345;
1933 dictionary_offset = 0x12345;
1934 adjectives_offset = 0x12345;
1935 variables_offset = 0x12345;
1936 arrays_offset = 0x12345;
1937 strings_offset = 0x12345;
1938 individuals_offset=0x12345;
1939 identifier_names_offset=0x12345;
1940 class_numbers_offset = 0x12345;
1941 static_arrays_offset = 0x12345;
1945 extern void tables_begin_pass(void)
1949 extern void tables_allocate_arrays(void)
1953 extern void tables_free_arrays(void)
1955 /* Allocation for this array happens in construct_storyfile() above */
1957 my_free(&zmachine_paged_memory,"output buffer");
1960 /* ========================================================================= */