1 /* ------------------------------------------------------------------------- */
2 /* "tables" : Constructs the story file or module (the output) up to the */
3 /* end of dynamic memory, gluing together all the required */
6 /* Part of Inform 6.35 */
7 /* copyright (c) Graham Nelson 1993 - 2020 */
9 /* Inform is free software: you can redistribute it and/or modify */
10 /* it under the terms of the GNU General Public License as published by */
11 /* the Free Software Foundation, either version 3 of the License, or */
12 /* (at your option) any later version. */
14 /* Inform is distributed in the hope that it will be useful, */
15 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
17 /* GNU General Public License for more details. */
19 /* You should have received a copy of the GNU General Public License */
20 /* along with Inform. If not, see https://gnu.org/licenses/ *
22 /* ------------------------------------------------------------------------- */
26 uchar *zmachine_paged_memory; /* Where we shall store the story file
27 constructed (contains all of paged
28 memory, i.e. all but code and the
29 static strings: allocated only when
30 we know how large it needs to be,
31 at the end of the compilation pass */
33 /* In Glulx, zmachine_paged_memory contains all of RAM -- i.e. all but
34 the header, the code, the static arrays, and the static strings. */
36 /* ------------------------------------------------------------------------- */
37 /* Offsets of various areas in the Z-machine: these are set to nominal */
38 /* values before the compilation pass, and to their calculated final */
39 /* values only when construct_storyfile() happens. These are then used to */
40 /* backpatch the incorrect values now existing in the Z-machine which */
41 /* used these nominal values. */
42 /* Most of the nominal values are 0x800 because this is guaranteed to */
43 /* be assembled as a long constant if it's needed in code, since the */
44 /* largest possible value of scale_factor is 8 and 0x800/8 = 256. */
46 /* In Glulx, I use 0x12345 instead of 0x800. This will always be a long */
47 /* (32-bit) constant, since there's no scale_factor. */
48 /* ------------------------------------------------------------------------- */
59 identifier_names_offset,
64 attribute_names_offset,
66 fake_action_names_offset,
68 constant_names_offset,
69 routines_array_offset,
70 constants_array_offset,
71 routine_flags_array_offset,
73 global_flags_array_offset,
74 array_flags_array_offset,
79 abbreviations_offset; /* Glulx */
81 int32 Out_Size, Write_Code_At, Write_Strings_At;
82 int32 RAM_Size, Write_RAM_At; /* Glulx */
84 /* ------------------------------------------------------------------------- */
85 /* Story file header settings. (Written to in "directs.c" and "asm.c".) */
86 /* ------------------------------------------------------------------------- */
88 int release_number, /* Release number game is to have */
89 statusline_flag; /* Either TIME_STYLE or SCORE_STYLE */
91 int serial_code_given_in_program /* If TRUE, a Serial directive has */
92 = FALSE; /* specified this 6-digit serial code */
93 char serial_code_buffer[7]; /* (overriding the usual date-stamp) */
94 int flags2_requirements[16]; /* An array of which bits in Flags 2 of
95 the header will need to be set:
96 e.g. if the save_undo / restore_undo
97 opcodes are ever assembled, we have
98 to set the "games want UNDO" bit.
101 /* ------------------------------------------------------------------------- */
102 /* Construct story/module file (up to code area start). */
104 /* (To understand what follows, you really need to look at the run-time */
105 /* system's specification, the Z-Machine Standards document.) */
106 /* ------------------------------------------------------------------------- */
108 extern void write_serial_number(char *buffer)
110 /* Note that this function may require modification for "ANSI" compilers
111 which do not provide the standard time functions: what is needed is
112 the ability to work out today's date */
114 time_t tt; tt=time(0);
115 if (serial_code_given_in_program)
116 strcpy(buffer, serial_code_buffer);
118 #ifdef TIME_UNAVAILABLE
119 sprintf(buffer,"970000");
121 strftime(buffer,10,"%y%m%d",localtime(&tt));
125 static void percentage(char *name, int32 x, int32 total)
126 { printf(" %-20s %2d.%d%%\n",name,x*100/total,(x*1000/total)%10);
129 static char *version_name(int v)
133 { case 3: return "Standard";
134 case 4: return "Plus";
135 case 5: return "Advanced";
136 case 6: return "Graphical";
137 case 8: return "Extended";
139 return "experimental format";
146 static int32 rough_size_of_paged_memory_z(void)
148 /* This function calculates a modest over-estimate of the amount of
149 memory required to store the Z-machine's paged memory area
150 (that is, everything up to the start of the code area). */
156 total = 64 /* header */
157 + 2 + subtract_pointers(low_strings_top, low_strings)
158 /* low strings pool */
159 + 6*32; /* abbreviations table */
161 total += 8; /* header extension table */
162 if (ZCODE_HEADER_EXT_WORDS>3) total += (ZCODE_HEADER_EXT_WORDS-3)*2;
164 if (alphabet_modified) total += 78; /* character set table */
166 if (zscii_defn_modified) /* Unicode translation table */
167 total += 2 + 2*zscii_high_water_mark;
169 total += 2*((version_number==3)?31:63) /* property default values */
170 + no_objects*((version_number==3)?9:14) /* object tree table */
171 + properties_table_size /* property values of objects */
172 + (no_classes+1)*(module_switch?4:2)
173 /* class object numbers table */
174 + no_symbols*2 /* names of numerous things */
175 + individuals_length /* tables of prop variables */
176 + dynamic_array_area_size; /* variables and arrays */
178 for (i=0; i<no_Inform_verbs; i++)
179 total += 2 + 1 + /* address of grammar table, */
180 /* number of grammar lines */
181 ((grammar_version_number == 1)?
182 (8*Inform_verbs[i].lines):0); /* grammar lines */
184 if (grammar_version_number != 1)
185 total += grammar_lines_top; /* size of grammar lines area */
187 total += 2 + 4*no_adjectives /* adjectives table */
188 + 2*no_actions /* action routines */
189 + 2*no_grammar_token_routines; /* general parsing routines */
191 total += (subtract_pointers(dictionary_top, dictionary)) /* dictionary */
192 + ((module_switch)?30:0); /* module map */
194 total += static_array_area_size; /* static arrays */
196 total += scale_factor*0x100 /* maximum null bytes before code */
197 + 1000; /* fudge factor (in case the above is wrong) */
202 static int32 rough_size_of_paged_memory_g(void)
204 /* This function calculates a modest over-estimate of the amount of
205 memory required to store the machine's paged memory area
206 (that is, everything past the start of RAM). */
212 /* No header for us! */
213 total = 1000; /* bit of a fudge factor */
215 total += dynamic_array_area_size; /* arrays and global variables */
217 total += no_objects * OBJECT_BYTE_LENGTH; /* object tables */
218 total += properties_table_size; /* property tables */
219 total += no_properties * 4; /* property defaults table */
221 total += 4 + no_classes * 4; /* class prototype object numbers */
223 total += 32; /* address/length of the identifier tables */
224 total += no_properties * 4;
225 total += (no_individual_properties-INDIV_PROP_START) * 4;
226 total += (NUM_ATTR_BYTES*8) * 4;
227 total += (no_actions + no_fake_actions) * 4;
228 total += 4 + no_arrays * 4;
230 total += 4 + no_Inform_verbs * 4; /* index of grammar tables */
231 total += grammar_lines_top; /* grammar tables */
233 total += 4 + no_actions * 4; /* actions functions table */
236 total += subtract_pointers(dictionary_top, dictionary);
238 while (total % GPAGESIZE)
244 static void construct_storyfile_z(void)
246 int32 i, j, k, l, mark, objs, strings_length, code_length,
247 limit=0, excess=0, extend_offset=0, headerext_length=0;
248 int32 globals_at=0, link_table_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
249 abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
250 map_of_module=0, grammar_table_at=0, charset_at=0, headerext_at=0,
251 terminating_chars_at=0, unicode_at=0, id_names_length=0,
253 int skip_backpatching = FALSE;
254 char *output_called = (module_switch)?"module":"story file";
258 individual_name_strings =
259 my_calloc(sizeof(int32), no_individual_properties,
260 "identifier name strings");
261 action_name_strings =
262 my_calloc(sizeof(int32), no_actions + no_fake_actions,
263 "action name strings");
264 attribute_name_strings =
265 my_calloc(sizeof(int32), 48,
266 "attribute name strings");
268 my_calloc(sizeof(int32),
270 "array name strings");
272 write_the_identifier_names();
274 /* We now know how large the buffer to hold our construction has to be */
276 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_z(),
279 /* Foolish code to make this routine compile on all ANSI compilers */
281 p = (uchar *) zmachine_paged_memory;
283 /* In what follows, the "mark" will move upwards in memory: at various
284 points its value will be recorded for milestones like
285 "dictionary table start". It begins at 0x40, just after the header */
289 /* ----------------- Low Strings and Abbreviations -------------------- */
291 p[mark]=0x80; p[mark+1]=0; mark+=2; /* Start the low strings pool
292 with a useful default string, " " */
294 for (i=0; i+low_strings<low_strings_top; mark++, i++) /* Low strings pool */
295 p[0x42+i]=low_strings[i];
298 for (i=0; i<3*32; i++) /* Initially all 96 entries */
299 { p[mark++]=0; p[mark++]=0x20; /* are set to " " */
301 for (i=0; i<no_abbreviations; i++) /* Write any abbreviations */
302 { j=abbrev_values[i]; /* into banks 2 and 3 */
303 p[abbrevs_at+64+2*i]=j/256; /* (bank 1 is reserved for */
304 p[abbrevs_at+65+2*i]=j%256; /* "variable strings") */
307 /* ------------------- Header extension table ------------------------- */
310 headerext_length = ZCODE_HEADER_EXT_WORDS;
311 if (zscii_defn_modified) {
312 /* Need at least 3 words for unicode table address */
313 if (headerext_length < 3)
314 headerext_length = 3;
316 if (ZCODE_HEADER_FLAGS_3) {
317 /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
318 if (headerext_length < 4)
319 headerext_length = 4;
321 p[mark++] = 0; p[mark++] = headerext_length;
322 for (i=0; i<headerext_length; i++)
323 { p[mark++] = 0; p[mark++] = 0;
326 /* -------------------- Z-character set table ------------------------- */
328 if (alphabet_modified)
330 for (i=0;i<3;i++) for (j=0;j<26;j++)
331 { if (alphabet[i][j] == '~') p[mark++] = '\"';
332 else p[mark++] = alphabet[i][j];
336 /* ------------------ Unicode translation table ----------------------- */
339 if (zscii_defn_modified)
341 p[mark++] = zscii_high_water_mark;
342 for (i=0;i<zscii_high_water_mark;i++)
343 { j = zscii_to_unicode(155 + i);
344 if (j < 0 || j > 0xFFFF) {
345 error("Z-machine Unicode translation table cannot contain characters beyond $FFFF.");
347 p[mark++] = j/256; p[mark++] = j%256;
351 /* -------------------- Objects and Properties ------------------------ */
353 /* The object table must be word-aligned. The Z-machine spec does not
354 require this, but the RA__Pr() veneer routine does. See
355 http://inform7.com/mantis/view.php?id=1712.
357 while ((mark%2) != 0) p[mark++]=0;
359 prop_defaults_at = mark;
361 p[mark++]=0; p[mark++]=0;
363 for (i=2; i< ((version_number==3)?32:64); i++)
364 { p[mark++]=prop_default_value[i]/256;
365 p[mark++]=prop_default_value[i]%256;
368 object_tree_at = mark;
370 mark += ((version_number==3)?9:14)*no_objects;
372 object_props_at = mark;
374 for (i=0; i<properties_table_size; i++)
375 p[mark+i]=properties_table[i];
377 for (i=0, objs=object_tree_at; i<no_objects; i++)
379 if (version_number == 3)
380 { p[objs]=objectsz[i].atts[0];
381 p[objs+1]=objectsz[i].atts[1];
382 p[objs+2]=objectsz[i].atts[2];
383 p[objs+3]=objectsz[i].atts[3];
384 p[objs+4]=objectsz[i].parent;
385 p[objs+5]=objectsz[i].next;
386 p[objs+6]=objectsz[i].child;
392 { p[objs]=objectsz[i].atts[0];
393 p[objs+1]=objectsz[i].atts[1];
394 p[objs+2]=objectsz[i].atts[2];
395 p[objs+3]=objectsz[i].atts[3];
396 p[objs+4]=objectsz[i].atts[4];
397 p[objs+5]=objectsz[i].atts[5];
398 p[objs+6]=(objectsz[i].parent)/256;
399 p[objs+7]=(objectsz[i].parent)%256;
400 p[objs+8]=(objectsz[i].next)/256;
401 p[objs+9]=(objectsz[i].next)%256;
402 p[objs+10]=(objectsz[i].child)/256;
403 p[objs+11]=(objectsz[i].child)%256;
405 { p[objs+12]=mark/256;
409 { p[objs+12]=objectsz[i].propsize/256;
410 p[objs+13]=objectsz[i].propsize%256;
414 mark+=objectsz[i].propsize;
417 /* ----------- Table of Class Prototype Object Numbers ---------------- */
419 class_numbers_offset = mark;
420 for (i=0; i<no_classes; i++)
421 { p[mark++] = class_object_numbers[i]/256;
422 p[mark++] = class_object_numbers[i]%256;
424 { p[mark++] = class_begins_at[i]/256;
425 p[mark++] = class_begins_at[i]%256;
431 /* ------------------- Table of Identifier Names ---------------------- */
433 identifier_names_offset = mark;
436 { p[mark++] = no_individual_properties/256;
437 p[mark++] = no_individual_properties%256;
438 for (i=1; i<no_individual_properties; i++)
439 { p[mark++] = individual_name_strings[i]/256;
440 p[mark++] = individual_name_strings[i]%256;
443 attribute_names_offset = mark;
445 { p[mark++] = attribute_name_strings[i]/256;
446 p[mark++] = attribute_name_strings[i]%256;
449 action_names_offset = mark;
450 fake_action_names_offset = mark + 2*no_actions;
451 for (i=0; i<no_actions + no_fake_actions; i++)
452 { p[mark++] = action_name_strings[i]/256;
453 p[mark++] = action_name_strings[i]%256;
456 array_names_offset = mark;
457 global_names_offset = mark + 2*no_arrays;
458 routine_names_offset = global_names_offset + 2*no_globals;
459 constant_names_offset = routine_names_offset + 2*no_named_routines;
460 for (i=0; i<no_arrays + no_globals
461 + no_named_routines + no_named_constants; i++)
462 { if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
463 p[mark++] = array_name_strings[i]/256;
464 p[mark++] = array_name_strings[i]%256;
467 id_names_length = (mark - identifier_names_offset)/2;
469 routine_flags_array_offset = mark;
471 if (define_INFIX_switch)
472 { for (i=0, k=1, l=0; i<no_named_routines; i++)
473 { if (sflags[named_routine_symbols[i]] & STAR_SFLAG) l=l+k;
475 if (k==256) { p[mark++] = l; k=1; l=0; }
477 if (k!=1) p[mark++]=l;
480 /* ---------------- Table of Indiv Property Values -------------------- */
482 individuals_offset = mark;
483 for (i=0; i<individuals_length; i++)
484 p[mark++] = individuals_table[i];
486 /* ----------------- Variables and Dynamic Arrays --------------------- */
490 for (i=0; i<dynamic_array_area_size; i++)
491 p[mark++] = dynamic_array_area[i];
493 for (i=0; i<240; i++)
494 { j=global_initial_value[i];
495 p[globals_at+i*2] = j/256; p[globals_at+i*2+1] = j%256;
498 /* ------------------ Terminating Characters Table -------------------- */
500 if (version_number >= 5)
501 { terminating_chars_at = mark;
502 for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
506 /* ------------------------ Grammar Table ----------------------------- */
508 if (grammar_version_number > 2)
509 { warning("This version of Inform is unable to produce the grammar \
510 table format requested (producing number 2 format instead)");
511 grammar_version_number = 2;
514 grammar_table_at = mark;
516 mark = mark + no_Inform_verbs*2;
518 for (i=0; i<no_Inform_verbs; i++)
519 { p[grammar_table_at + i*2] = (mark/256);
520 p[grammar_table_at + i*2 + 1] = (mark%256);
521 p[mark++] = Inform_verbs[i].lines;
522 for (j=0; j<Inform_verbs[i].lines; j++)
523 { k = Inform_verbs[i].l[j];
524 if (grammar_version_number == 1)
526 p[mark+7] = grammar_lines[k+1];
527 for (m=1;m<=6;m++) p[mark + m] = 0;
528 k = k + 2; m = 1; n = 0;
529 while ((grammar_lines[k] != 15) && (m<=6))
530 { p[mark + m] = grammar_lines[k];
531 if (grammar_lines[k] < 180) n++;
539 p[mark++] = grammar_lines[k++];
540 p[mark++] = grammar_lines[k++];
542 { tok = grammar_lines[k++];
544 if (tok == 15) break;
545 p[mark++] = grammar_lines[k++];
546 p[mark++] = grammar_lines[k++];
552 /* ------------------- Actions and Preactions ------------------------- */
553 /* (The term "preactions" is traditional: Inform uses the preactions */
554 /* table for a different purpose than Infocom used to.) */
555 /* The values are written later, when the Z-code offset is known. */
556 /* -------------------------------------------------------------------- */
559 mark += no_actions*2;
561 preactions_at = mark;
562 if (grammar_version_number == 1)
563 mark += no_grammar_token_routines*2;
565 /* ----------------------- Adjectives Table --------------------------- */
567 if (grammar_version_number == 1)
568 { p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
569 adjectives_offset = mark;
570 dictionary_offset = mark + 4*no_adjectives;
572 for (i=0; i<no_adjectives; i++)
573 { j = final_dict_order[adjectives[no_adjectives-i-1]]
574 *((version_number==3)?7:9)
575 + dictionary_offset + 7;
576 p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
577 p[mark++]=(256-no_adjectives+i);
581 { p[mark]=0; p[mark+1]=0; mark+=2;
582 adjectives_offset = mark;
583 dictionary_offset = mark;
586 /* ------------------------- Dictionary ------------------------------- */
590 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
591 dictionary[2]=','; /* force words apart */
594 dictionary[4]=(version_number==3)?7:9; /* Length of each entry */
595 dictionary[5]=(dict_entries/256); /* Number of entries */
596 dictionary[6]=(dict_entries%256);
598 for (i=0; i<7; i++) p[mark++] = dictionary[i];
600 for (i=0; i<dict_entries; i++)
601 { k = 7 + i*((version_number==3)?7:9);
602 j = mark + final_dict_order[i]*((version_number==3)?7:9);
603 for (l = 0; l<((version_number==3)?7:9); l++)
604 p[j++] = dictionary[k++];
606 mark += dict_entries * ((version_number==3)?7:9);
608 /* ------------------------- Module Map ------------------------------- */
611 { map_of_module = mark; /* Filled in below */
615 /* ------------------------ Static Arrays ----------------------------- */
617 static_arrays_at = mark;
618 for (i=0; i<static_array_area_size; i++)
619 p[mark++] = static_array_area[i];
621 /* ----------------- A gap before the code area ----------------------- */
622 /* (so that it will start at an exact packed address and so that all */
623 /* routine packed addresses are >= 256, hence long constants) */
624 /* -------------------------------------------------------------------- */
626 while ((mark%length_scale_factor) != 0) p[mark++]=0;
627 while (mark < (scale_factor*0x100)) p[mark++]=0;
628 if (oddeven_packing_switch)
629 while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
632 { error("This program has overflowed the maximum readable-memory \
633 size of the Z-machine format. See the memory map below: the start \
634 of the area marked \"above readable memory\" must be brought down to $FFFE \
636 memory_map_switch = TRUE;
637 /* Backpatching the grammar tables requires us to trust some of the */
638 /* addresses we've written into Z-machine memory, but they may have */
639 /* been truncated to 16 bits, so we can't do it. */
640 skip_backpatching = TRUE;
643 /* -------------------------- Code Area ------------------------------- */
644 /* (From this point on we don't write any more into the "p" buffer.) */
645 /* -------------------------------------------------------------------- */
647 Write_Code_At = mark;
648 if (!OMIT_UNUSED_ROUTINES) {
649 code_length = zmachine_pc;
652 if (zmachine_pc != df_total_size_before_stripping)
653 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
654 code_length = df_total_size_after_stripping;
658 /* ------------------ Another synchronising gap ----------------------- */
660 if (oddeven_packing_switch)
662 while ((mark%(scale_factor*2)) != 0) mark++;
664 while ((mark%(scale_factor*2)) != scale_factor) mark++;
667 while ((mark%scale_factor) != 0) mark++;
669 /* ------------------------- Strings Area ----------------------------- */
671 Write_Strings_At = mark;
672 strings_length = static_strings_extent;
673 mark += strings_length;
675 /* --------------------- Module Linking Data -------------------------- */
678 { link_table_at = mark; mark += link_data_size;
679 mark += zcode_backpatch_size;
680 mark += zmachine_backpatch_size;
683 /* --------------------- Is the file too big? ------------------------- */
687 switch(version_number)
688 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
690 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
693 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
697 { excess = Out_Size-((int32) 0x10000L); limit=64;
701 { char memory_full_error[80];
702 sprintf(memory_full_error,
703 "The %s exceeds version-%d limit (%dK) by %d bytes",
704 output_called, version_number, limit, excess);
705 fatalerror(memory_full_error);
708 /* --------------------------- Offsets -------------------------------- */
710 dictionary_offset = dictionary_at;
711 variables_offset = globals_at;
712 actions_offset = actions_at;
713 preactions_offset = preactions_at;
714 prop_defaults_offset = prop_defaults_at;
715 prop_values_offset = object_props_at;
716 static_memory_offset = grammar_table_at;
717 grammar_table_offset = grammar_table_at;
718 static_arrays_offset = static_arrays_at;
720 if (extend_memory_map)
722 if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
723 while ((extend_offset%length_scale_factor) != 0) extend_offset++;
724 /* Not sure why above line is necessary, but oddeven_packing
725 * will need extend_offset to be even */
726 code_offset = extend_offset*scale_factor;
727 if (oddeven_packing_switch)
728 strings_offset = code_offset + scale_factor;
730 strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
732 /* With the extended memory model, need to specifically check that we
733 * haven't overflowed the packed address range for routines or strings.
734 * With the standard memory model, we only need the earlier total size
737 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
739 { char code_full_error[80];
740 sprintf(code_full_error,
741 "The code area limit has been exceeded by %d bytes",
743 fatalerror(code_full_error);
746 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
748 { char strings_full_error[140];
749 if (oddeven_packing_switch)
750 sprintf(strings_full_error,
751 "The strings area limit has been exceeded by %d bytes",
754 sprintf(strings_full_error,
755 "The code+strings area limit has been exceeded by %d bytes. \
756 Try running Inform again with -B on the command line.",
758 fatalerror(strings_full_error);
762 { code_offset = Write_Code_At;
763 strings_offset = Write_Strings_At;
766 /* --------------------------- The Header ----------------------------- */
768 for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */
770 p[0] = version_number; /* Version number */
771 p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */
772 p[2] = (release_number/256);
773 p[3] = (release_number%256); /* Release */
774 p[4] = (Write_Code_At/256);
775 p[5] = (Write_Code_At%256); /* End of paged memory */
776 if (version_number==6)
777 { j=code_offset/scale_factor; /* Packed address of "Main__" */
778 p[6]=(j/256); p[7]=(j%256);
781 { j=Write_Code_At+1; /* Initial PC value (bytes) */
782 p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */
784 p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */
785 p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */
786 p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */
787 p[14]=(grammar_table_at/256);
788 p[15]=(grammar_table_at%256); /* Grammar */
789 for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */
790 j+=k*flags2_requirements[i]; /* unusual opcodes assembled */
791 p[16]=j/256; p[17]=j%256;
792 write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
793 p[24]=abbrevs_at/256;
794 p[25]=abbrevs_at%256; /* Abbreviations table */
795 p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */
796 p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */
798 if (extend_memory_map)
799 { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
800 p[40]=j/256; p[41]=j%256; /* Routines offset */
801 if (oddeven_packing_switch)
802 j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
803 p[42]=j/256; p[43]=j%256; /* = Strings offset */
806 if (version_number >= 5)
807 { p[46] = terminating_chars_at/256; /* Terminating characters table */
808 p[47] = terminating_chars_at%256;
811 if (alphabet_modified)
813 p[52]=j/256; p[53]=j%256; } /* Character set table address */
816 p[54] = j/256; p[55] = j%256; /* Header extension table address */
818 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
820 p[62] = '0' + ((RELEASE_NUMBER/10)%10);
821 p[63] = '0' + RELEASE_NUMBER%10;
823 /* ------------------------ Header Extension -------------------------- */
825 /* The numbering in the spec is a little weird -- it's headerext_length
826 words *after* the initial length word. We follow the spec numbering
827 in this switch statement, so the count is 1-based. */
828 for (i=1; i<=headerext_length; i++) {
831 j = unicode_at; /* Unicode translation table address */
834 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
840 p[headerext_at+2*i+0] = j / 256;
841 p[headerext_at+2*i+1] = j % 256;
844 /* ----------------- The Header: Extras for modules ------------------- */
848 p[1]=MODULE_VERSION_NUMBER;
849 p[6]=map_of_module/256;
850 p[7]=map_of_module%256;
852 mark = map_of_module; /* Module map format: */
854 p[mark++]=object_tree_at/256; /* 0: Object tree addr */
855 p[mark++]=object_tree_at%256;
856 p[mark++]=object_props_at/256; /* 2: Prop values addr */
857 p[mark++]=object_props_at%256;
858 p[mark++]=(Write_Strings_At/scale_factor)/256; /* 4: Static strs */
859 p[mark++]=(Write_Strings_At/scale_factor)%256;
860 p[mark++]=class_numbers_offset/256; /* 6: Class nos addr */
861 p[mark++]=class_numbers_offset%256;
862 p[mark++]=individuals_offset/256; /* 8: Indiv prop values */
863 p[mark++]=individuals_offset%256;
864 p[mark++]=individuals_length/256; /* 10: Length of table */
865 p[mark++]=individuals_length%256;
866 p[mark++]=no_symbols/256; /* 12: No of symbols */
867 p[mark++]=no_symbols%256;
868 p[mark++]=no_individual_properties/256; /* 14: Max property no */
869 p[mark++]=no_individual_properties%256;
870 p[mark++]=no_objects/256; /* 16: No of objects */
871 p[mark++]=no_objects%256;
873 p[mark++]=i/256; /* 18: Import/exports */
875 p[mark++]=link_data_size/256; /* 20: Size of */
876 p[mark++]=link_data_size%256;
878 p[mark++]=i/256; /* 22: Code backpatch */
880 p[mark++]=zcode_backpatch_size/256; /* 24: Size of */
881 p[mark++]=zcode_backpatch_size%256;
882 i += zcode_backpatch_size;
883 p[mark++]=i/256; /* 26: Image backpatch */
885 p[mark++]=zmachine_backpatch_size/256; /* 28: Size of */
886 p[mark++]=zmachine_backpatch_size%256;
888 /* Further space in this table is reserved for future use */
891 /* ---- Backpatch the Z-machine, now that all information is in ------- */
893 if (!module_switch && !skip_backpatching)
894 { backpatch_zmachine_image_z();
895 for (i=1; i<id_names_length; i++)
896 { int32 v = 256*p[identifier_names_offset + i*2]
897 + p[identifier_names_offset + i*2 + 1];
898 if (v!=0) v += strings_offset/scale_factor;
899 p[identifier_names_offset + i*2] = v/256;
900 p[identifier_names_offset + i*2 + 1] = v%256;
904 for (i=0; i<no_actions; i++)
905 { j=action_byte_offset[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;
912 if (grammar_version_number == 1)
913 { mark = preactions_at;
914 for (i=0; i<no_grammar_token_routines; i++)
915 { j=grammar_token_routine[i];
916 if (OMIT_UNUSED_ROUTINES)
917 j = df_stripped_address_for_address(j);
918 j += code_offset/scale_factor;
919 p[mark++]=j/256; p[mark++]=j%256;
923 { for (l = 0; l<no_Inform_verbs; l++)
924 { k = grammar_table_at + 2*l;
925 i = p[k]*256 + p[k+1];
926 for (j = p[i++]; j>0; j--)
927 { int topbits; int32 value;
930 { topbits = (p[i]/0x40) & 3;
931 value = p[i+1]*256 + p[i+2];
934 value = final_dict_order[value]
935 *((version_number==3)?7:9)
936 + dictionary_offset + 7;
939 if (OMIT_UNUSED_ROUTINES)
940 value = df_stripped_address_for_address(value);
941 value += code_offset/scale_factor;
944 p[i+1] = value/256; p[i+2] = value%256;
953 /* ---- From here on, it's all reportage: construction is finished ---- */
955 if (statistics_switch)
956 { int32 k_long, rate; char *k_str="";
957 k_long=(Out_Size/1024);
958 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
959 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
960 if (total_bytes_trans == 0) rate = 0;
961 else rate=total_bytes_trans*1000/total_chars_trans;
964 %3d source code files %6d syntactic lines\n\
965 %6d textual lines %8ld characters ",
966 total_input_files, no_syntax_lines,
967 total_source_line_count, (long int) total_chars_read);
968 if (character_set_unicode) printf("(UTF-8)\n");
969 else if (character_set_setting == 0) printf("(plain ASCII)\n");
971 { printf("(ISO 8859-%d %s)\n", character_set_setting,
972 name_of_iso_set(character_set_setting));
975 printf("Allocated:\n\
976 %6d symbols (maximum %4d) %8ld bytes of memory\n\
977 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
978 no_symbols, MAX_SYMBOLS,
979 (long int) malloced_bytes,
981 version_name(version_number),
983 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
984 (long int) k_long, k_str);
987 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
988 %6d global vars (maximum 233) %6d variable/array space (maximum %d)\n",
989 no_classes, MAX_CLASSES,
990 no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)),
992 dynamic_array_area_size, MAX_STATIC_DATA);
995 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
996 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
997 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
998 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
999 no_Inform_verbs, MAX_VERBS,
1000 dict_entries, MAX_DICT_ENTRIES,
1001 no_grammar_lines, grammar_version_number,
1003 no_actions, MAX_ACTIONS,
1004 no_attributes, ((version_number==3)?32:48),
1005 no_properties-2, ((version_number==3)?30:62),
1006 no_individual_properties - 64);
1008 if (track_unused_routines)
1010 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1012 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
1013 (long int) df_total_size_before_stripping, (long int) diff,
1014 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1015 100 * (float)diff / (float)df_total_size_before_stripping);
1019 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1020 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1021 %6ld instructions of Z-code %6d sequence points\n\
1022 %6ld bytes readable memory used (maximum 65536)\n\
1023 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
1024 (long int) total_chars_trans,
1025 (long int) total_bytes_trans,
1026 (total_chars_trans>total_bytes_trans)?0:1,
1028 no_abbreviations, MAX_ABBREVS,
1030 (long int) no_instructions, no_sequence_points,
1031 (long int) Write_Code_At,
1032 (long int) Out_Size,
1034 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1042 "\nOffsets in %s:\n\
1043 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1044 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1045 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1047 (long int) abbrevs_at,
1048 (long int) prop_defaults_at,
1049 (long int) object_tree_at,
1050 (long int) object_props_at,
1051 (long int) globals_at,
1052 (long int) grammar_table_at,
1053 (long int) actions_at,
1054 (long int) preactions_at,
1055 (long int) adjectives_offset,
1056 (long int) dictionary_at,
1057 (long int) Write_Code_At,
1058 (long int) Write_Strings_At);
1060 printf("%05lx Linking data\n",(long int) link_table_at);
1064 if (debugfile_switch)
1065 { begin_writing_debug_sections();
1066 write_debug_section("abbreviations", 64);
1067 write_debug_section("abbreviations table", abbrevs_at);
1068 write_debug_section("header extension", headerext_at);
1069 if (alphabet_modified)
1070 { write_debug_section("alphabets table", charset_at);
1072 if (zscii_defn_modified)
1073 { write_debug_section("Unicode table", unicode_at);
1075 write_debug_section("property defaults", prop_defaults_at);
1076 write_debug_section("object tree", object_tree_at);
1077 write_debug_section("common properties", object_props_at);
1078 write_debug_section("class numbers", class_numbers_offset);
1079 write_debug_section("identifier names", identifier_names_offset);
1080 write_debug_section("individual properties", individuals_offset);
1081 write_debug_section("global variables", globals_at);
1082 write_debug_section("array space", globals_at+480);
1083 write_debug_section("grammar table", grammar_table_at);
1084 write_debug_section("actions table", actions_at);
1085 write_debug_section("parsing routines", preactions_at);
1086 write_debug_section("adjectives table", adjectives_offset);
1087 write_debug_section("dictionary", dictionary_at);
1088 write_debug_section("code area", Write_Code_At);
1089 write_debug_section("strings area", Write_Strings_At);
1090 end_writing_debug_sections(Out_Size);
1093 if (memory_map_switch)
1096 printf("Dynamic +---------------------+ 00000\n");
1097 printf("memory | header |\n");
1098 printf(" +---------------------+ 00040\n");
1099 printf(" | abbreviations |\n");
1100 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at);
1101 printf(" | abbreviations table |\n");
1102 printf(" +---------------------+ %05lx\n", (long int) headerext_at);
1103 printf(" | header extension |\n");
1104 if (alphabet_modified)
1106 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at);
1107 printf(" | alphabets table |\n");
1109 if (zscii_defn_modified)
1111 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at);
1112 printf(" | Unicode table |\n");
1114 printf(" +---------------------+ %05lx\n",
1115 (long int) prop_defaults_at);
1116 printf(" | property defaults |\n");
1117 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at);
1118 printf(" | objects |\n");
1119 printf(" + - - - - - - - - - - + %05lx\n",
1120 (long int) object_props_at);
1121 printf(" | object short names, |\n");
1122 printf(" | common prop values |\n");
1123 printf(" + - - - - - - - - - - + %05lx\n",
1124 (long int) class_numbers_offset);
1125 printf(" | class numbers table |\n");
1126 printf(" + - - - - - - - - - - + %05lx\n",
1127 (long int) identifier_names_offset);
1128 printf(" | symbol names table |\n");
1129 printf(" + - - - - - - - - - - + %05lx\n",
1130 (long int) individuals_offset);
1131 printf(" | indiv prop values |\n");
1132 printf(" +---------------------+ %05lx\n", (long int) globals_at);
1133 printf(" | global variables |\n");
1134 printf(" + - - - - - - - - - - + %05lx\n",
1135 ((long int) globals_at)+480L);
1136 printf(" | arrays |\n");
1137 printf(" +=====================+ %05lx\n",
1138 (long int) grammar_table_at);
1139 printf("Readable| grammar table |\n");
1140 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at);
1141 printf(" | actions |\n");
1142 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at);
1143 printf(" | parsing routines |\n");
1144 printf(" + - - - - - - - - - - + %05lx\n",
1145 (long int) adjectives_offset);
1146 printf(" | adjectives |\n");
1147 printf(" +---------------------+ %05lx\n", (long int) dictionary_at);
1148 printf(" | dictionary |\n");
1151 printf(" + - - - - - - - - - - + %05lx\n",
1152 (long int) map_of_module);
1153 printf(" | map of module addrs |\n");
1155 if (static_array_area_size)
1157 printf(" +---------------------+ %05lx\n", (long int) static_arrays_at);
1158 printf(" | static arrays |\n");
1160 printf(" +=====================+ %05lx\n", (long int) Write_Code_At);
1161 printf("Above | Z-code |\n");
1162 printf("readable+---------------------+ %05lx\n",
1163 (long int) Write_Strings_At);
1164 printf("memory | strings |\n");
1167 printf(" +=====================+ %05lx\n", (long int) link_table_at);
1168 printf(" | module linking data |\n");
1170 printf(" +---------------------+ %05lx\n", (long int) Out_Size);
1173 if (percentages_switch)
1174 { printf("Approximate percentage breakdown of %s:\n",
1176 percentage("Z-code", code_length,Out_Size);
1178 percentage("Linking data", link_data_size,Out_Size);
1179 percentage("Static strings", strings_length,Out_Size);
1180 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1181 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1182 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1183 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1184 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1185 percentage("Total of save area", grammar_table_at,Out_Size);
1186 percentage("Total of text", total_bytes_trans,Out_Size);
1188 if (frequencies_switch)
1190 { printf("How frequently abbreviations were used, and roughly\n");
1191 printf("how many bytes they saved: ('_' denotes spaces)\n");
1192 for (i=0; i<no_abbreviations; i++)
1193 { char abbrev_string[MAX_ABBREV_LENGTH];
1194 strcpy(abbrev_string,
1195 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1196 for (j=0; abbrev_string[j]!=0; j++)
1197 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1198 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1199 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1200 if ((i%3)==2) printf("\n");
1202 if ((i%3)!=0) printf("\n");
1203 if (no_abbreviations==0) printf("None were declared.\n");
1208 static void construct_storyfile_g(void)
1210 int32 i, j, k, l, mark, strings_length, limit;
1211 int32 globals_at, dictionary_at, actions_at, preactions_at,
1212 abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1213 grammar_table_at, charset_at, headerext_at,
1214 unicode_at, arrays_at, static_arrays_at;
1215 int32 threespaces, code_length;
1216 char *output_called = (module_switch)?"module":"story file";
1220 individual_name_strings =
1221 my_calloc(sizeof(int32), no_individual_properties,
1222 "identifier name strings");
1223 action_name_strings =
1224 my_calloc(sizeof(int32), no_actions + no_fake_actions,
1225 "action name strings");
1226 attribute_name_strings =
1227 my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1228 "attribute name strings");
1229 array_name_strings =
1230 my_calloc(sizeof(int32),
1232 "array name strings");
1234 write_the_identifier_names();
1235 threespaces = compile_string(" ", FALSE, FALSE);
1237 compress_game_text();
1239 /* We now know how large the buffer to hold our construction has to be */
1241 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1244 /* Foolish code to make this routine compile on all ANSI compilers */
1246 p = (uchar *) zmachine_paged_memory;
1248 /* In what follows, the "mark" will move upwards in memory: at various
1249 points its value will be recorded for milestones like
1250 "dictionary table start". It begins at 0x40, just after the header */
1252 /* Ok, our policy here will be to set the *_at values all relative
1253 to RAM. That's so we can write into zmachine_paged_memory[mark]
1254 and actually hit what we're aiming at.
1255 All the *_offset values will be set to true Glulx machine
1258 /* To get our bearings, figure out where the strings and code are. */
1259 /* We start with two words, which conventionally identify the
1260 memory layout. This is why the code starts eight bytes after
1262 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1263 if (!OMIT_UNUSED_ROUTINES) {
1264 code_length = zmachine_pc;
1267 if (zmachine_pc != df_total_size_before_stripping)
1268 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1269 code_length = df_total_size_after_stripping;
1271 Write_Strings_At = Write_Code_At + code_length;
1272 strings_length = compression_table_size + compression_string_size;
1274 static_arrays_at = Write_Strings_At + strings_length;
1276 /* Now figure out where RAM starts. */
1277 Write_RAM_At = static_arrays_at + static_array_area_size;
1278 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1279 while (Write_RAM_At % GPAGESIZE)
1282 /* Now work out all those RAM positions. */
1285 /* ----------------- Variables and Dynamic Arrays --------------------- */
1288 for (i=0; i<no_globals; i++) {
1289 j = global_initial_value[i];
1290 WriteInt32(p+mark, j);
1295 for (i=MAX_GLOBAL_VARIABLES*4; i<dynamic_array_area_size; i++)
1296 p[mark++] = dynamic_array_area[i];
1298 /* -------------------------- Dynamic Strings -------------------------- */
1301 WriteInt32(p+mark, no_dynamic_strings);
1303 for (i=0; i<no_dynamic_strings; i++) {
1304 j = Write_Strings_At + compressed_offsets[threespaces-1];
1305 WriteInt32(p+mark, j);
1309 /* ---------------- Various Things I'm Not Sure About ------------------ */
1310 /* Actually, none of these are relevant to Glulx. */
1311 headerext_at = mark;
1313 if (alphabet_modified)
1316 if (zscii_defn_modified)
1319 /* -------------------- Objects and Properties ------------------------ */
1321 object_tree_at = mark;
1323 object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1325 for (i=0; i<no_objects; i++) {
1326 int32 objmark = mark;
1327 p[mark++] = 0x70; /* type byte -- object */
1328 for (j=0; j<NUM_ATTR_BYTES; j++) {
1329 p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1331 for (j=0; j<6; j++) {
1334 case 0: /* next object in the linked list. */
1335 if (i == no_objects-1)
1338 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1340 case 1: /* hardware name address */
1341 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1343 case 2: /* property table address */
1344 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1346 case 3: /* parent */
1347 if (objectsg[i].parent == 0)
1350 val = Write_RAM_At + object_tree_at +
1351 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1353 case 4: /* sibling */
1354 if (objectsg[i].next == 0)
1357 val = Write_RAM_At + object_tree_at +
1358 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1361 if (objectsg[i].child == 0)
1364 val = Write_RAM_At + object_tree_at +
1365 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1368 p[mark++] = (val >> 24) & 0xFF;
1369 p[mark++] = (val >> 16) & 0xFF;
1370 p[mark++] = (val >> 8) & 0xFF;
1371 p[mark++] = (val) & 0xFF;
1374 for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1379 if (object_props_at != mark)
1380 error("*** Object table was impossible length ***");
1382 for (i=0; i<properties_table_size; i++)
1383 p[mark+i]=properties_table[i];
1385 for (i=0; i<no_objects; i++) {
1386 int32 tableaddr = object_props_at + objectsg[i].propaddr;
1387 int32 tablelen = ReadInt32(p+tableaddr);
1389 for (j=0; j<tablelen; j++) {
1390 k = ReadInt32(p+tableaddr+4);
1391 k += (Write_RAM_At + object_props_at);
1392 WriteInt32(p+tableaddr+4, k);
1397 mark += properties_table_size;
1399 prop_defaults_at = mark;
1400 for (i=0; i<no_properties; i++) {
1401 k = prop_default_value[i];
1402 WriteInt32(p+mark, k);
1406 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1408 class_numbers_offset = mark;
1409 for (i=0; i<no_classes; i++) {
1410 j = Write_RAM_At + object_tree_at +
1411 (OBJECT_BYTE_LENGTH*(class_object_numbers[i]-1));
1412 WriteInt32(p+mark, j);
1415 WriteInt32(p+mark, 0);
1418 /* -------------------- Table of Property Names ------------------------ */
1420 /* We try to format this bit with some regularity...
1421 address of common properties
1422 number of common properties
1423 address of indiv properties
1424 number of indiv properties (counted from INDIV_PROP_START)
1425 address of attributes
1426 number of attributes (always NUM_ATTR_BYTES*8)
1431 identifier_names_offset = mark;
1432 mark += 32; /* eight pairs of values, to be filled in. */
1434 WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1435 WriteInt32(p+identifier_names_offset+4, no_properties);
1436 for (i=0; i<no_properties; i++) {
1437 j = individual_name_strings[i];
1439 j = Write_Strings_At + compressed_offsets[j-1];
1440 WriteInt32(p+mark, j);
1444 WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1445 WriteInt32(p+identifier_names_offset+12,
1446 no_individual_properties-INDIV_PROP_START);
1447 for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1448 j = individual_name_strings[i];
1450 j = Write_Strings_At + compressed_offsets[j-1];
1451 WriteInt32(p+mark, j);
1455 WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1456 WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1457 for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1458 j = attribute_name_strings[i];
1460 j = Write_Strings_At + compressed_offsets[j-1];
1461 WriteInt32(p+mark, j);
1465 WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1466 WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1467 action_names_offset = mark;
1468 fake_action_names_offset = mark + 4*no_actions;
1469 for (i=0; i<no_actions + no_fake_actions; i++) {
1470 j = action_name_strings[i];
1472 j = Write_Strings_At + compressed_offsets[j-1];
1473 WriteInt32(p+mark, j);
1477 array_names_offset = mark;
1478 WriteInt32(p+mark, no_arrays);
1480 for (i=0; i<no_arrays; i++) {
1481 j = array_name_strings[i];
1483 j = Write_Strings_At + compressed_offsets[j-1];
1484 WriteInt32(p+mark, j);
1488 individuals_offset = mark;
1490 /* ------------------------ Grammar Table ----------------------------- */
1492 if (grammar_version_number != 2)
1493 { warning("This version of Inform is unable to produce the grammar \
1494 table format requested (producing number 2 format instead)");
1495 grammar_version_number = 2;
1498 grammar_table_at = mark;
1500 WriteInt32(p+mark, no_Inform_verbs);
1503 mark += no_Inform_verbs*4;
1505 for (i=0; i<no_Inform_verbs; i++) {
1506 j = mark + Write_RAM_At;
1507 WriteInt32(p+(grammar_table_at+4+i*4), j);
1508 p[mark++] = Inform_verbs[i].lines;
1509 for (j=0; j<Inform_verbs[i].lines; j++) {
1511 k = Inform_verbs[i].l[j];
1512 p[mark++] = grammar_lines[k++];
1513 p[mark++] = grammar_lines[k++];
1514 p[mark++] = grammar_lines[k++];
1516 tok = grammar_lines[k++];
1518 if (tok == 15) break;
1519 p[mark++] = grammar_lines[k++];
1520 p[mark++] = grammar_lines[k++];
1521 p[mark++] = grammar_lines[k++];
1522 p[mark++] = grammar_lines[k++];
1527 /* ------------------- Actions and Preactions ------------------------- */
1530 WriteInt32(p+mark, no_actions);
1532 mark += no_actions*4;
1533 /* Values to be written in later. */
1535 if (DICT_CHAR_SIZE != 1) {
1536 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1541 preactions_at = mark;
1542 adjectives_offset = mark;
1543 dictionary_offset = mark;
1545 /* ------------------------- Dictionary ------------------------------- */
1547 dictionary_at = mark;
1549 WriteInt32(dictionary+0, dict_entries);
1551 p[mark+i] = dictionary[i];
1553 for (i=0; i<dict_entries; i++) {
1554 k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1555 j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1556 for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1557 p[j++] = dictionary[k++];
1559 mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1561 /* -------------------------- All Data -------------------------------- */
1563 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1564 while (mark % GPAGESIZE)
1569 Out_Size = Write_RAM_At + RAM_Size;
1572 /* --------------------------- Offsets -------------------------------- */
1574 dictionary_offset = Write_RAM_At + dictionary_at;
1575 variables_offset = Write_RAM_At + globals_at;
1576 arrays_offset = Write_RAM_At + arrays_at;
1577 actions_offset = Write_RAM_At + actions_at;
1578 preactions_offset = Write_RAM_At + preactions_at;
1579 prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1580 object_tree_offset = Write_RAM_At + object_tree_at;
1581 prop_values_offset = Write_RAM_At + object_props_at;
1582 static_memory_offset = Write_RAM_At + grammar_table_at;
1583 grammar_table_offset = Write_RAM_At + grammar_table_at;
1584 abbreviations_offset = Write_RAM_At + abbrevs_at;
1586 code_offset = Write_Code_At;
1587 strings_offset = Write_Strings_At;
1588 static_arrays_offset = static_arrays_at;
1590 /* --------------------------- The Header ----------------------------- */
1592 /* ------ Backpatch the machine, now that all information is in ------- */
1595 { backpatch_zmachine_image_g();
1597 mark = actions_at + 4;
1598 for (i=0; i<no_actions; i++) {
1599 j = action_byte_offset[i];
1600 if (OMIT_UNUSED_ROUTINES)
1601 j = df_stripped_address_for_address(j);
1603 WriteInt32(p+mark, j);
1607 for (l = 0; l<no_Inform_verbs; l++) {
1608 k = grammar_table_at + 4 + 4*l;
1609 i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1611 for (j = p[i++]; j>0; j--) {
1615 while (p[i] != 15) {
1616 topbits = (p[i]/0x40) & 3;
1617 value = ((p[i+1] << 24) | (p[i+2] << 16)
1618 | (p[i+3] << 8) | (p[i+4]));
1621 value = dictionary_offset + 4
1622 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1625 if (OMIT_UNUSED_ROUTINES)
1626 value = df_stripped_address_for_address(value);
1627 value += code_offset;
1630 WriteInt32(p+(i+1), value);
1639 /* ---- From here on, it's all reportage: construction is finished ---- */
1641 if (statistics_switch)
1642 { int32 k_long, rate; char *k_str="";
1643 k_long=(Out_Size/1024);
1644 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1645 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1646 if (strings_length == 0) rate = 0;
1647 else rate=strings_length*1000/total_chars_trans;
1650 %3d source code files %6d syntactic lines\n\
1651 %6d textual lines %8ld characters ",
1652 total_input_files, no_syntax_lines,
1653 total_source_line_count, (long int) total_chars_read);
1654 if (character_set_unicode) printf("(UTF-8)\n");
1655 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1657 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1658 name_of_iso_set(character_set_setting));
1662 write_serial_number(serialnum);
1663 printf("Allocated:\n\
1664 %6d symbols (maximum %4d) %8ld bytes of memory\n\
1665 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1666 no_symbols, MAX_SYMBOLS,
1667 (long int) malloced_bytes,
1668 version_name(version_number),
1671 serialnum[0], serialnum[1], serialnum[2],
1672 serialnum[3], serialnum[4], serialnum[5],
1673 (long int) k_long, k_str);
1677 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
1678 %6d global vars (maximum %3d) %6d variable/array space (maximum %d)\n",
1679 no_classes, MAX_CLASSES,
1680 no_objects, MAX_OBJECTS,
1681 no_globals, MAX_GLOBAL_VARIABLES,
1682 dynamic_array_area_size, MAX_STATIC_DATA);
1685 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
1686 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1687 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
1688 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1689 no_Inform_verbs, MAX_VERBS,
1690 dict_entries, MAX_DICT_ENTRIES,
1691 no_grammar_lines, grammar_version_number,
1693 no_actions, MAX_ACTIONS,
1694 no_attributes, NUM_ATTR_BYTES*8,
1695 no_properties, INDIV_PROP_START,
1696 no_individual_properties - INDIV_PROP_START);
1698 if (track_unused_routines)
1700 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1702 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1703 (long int) df_total_size_before_stripping, (long int) diff,
1704 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1705 100 * (float)diff / (float)df_total_size_before_stripping);
1709 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1710 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1711 %6ld instructions of code %6d sequence points\n\
1712 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1713 %6ld bytes used in machine %10ld bytes free in machine\n",
1714 (long int) total_chars_trans,
1715 (long int) strings_length,
1716 (total_chars_trans>strings_length)?0:1,
1718 no_abbreviations, MAX_ABBREVS,
1720 (long int) no_instructions, no_sequence_points,
1721 (long int) (Out_Size - Write_RAM_At),
1722 (long int) Write_RAM_At,
1723 (long int) Out_Size,
1725 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1733 "\nOffsets in %s:\n\
1734 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1735 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1736 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1738 (long int) abbrevs_at,
1739 (long int) prop_defaults_at,
1740 (long int) object_tree_at,
1741 (long int) object_props_at,
1742 (long int) globals_at,
1743 (long int) grammar_table_at,
1744 (long int) actions_at,
1745 (long int) preactions_at,
1746 (long int) adjectives_offset,
1747 (long int) dictionary_at,
1748 (long int) Write_Code_At,
1749 (long int) Write_Strings_At);
1753 if (debugfile_switch)
1754 { begin_writing_debug_sections();
1755 write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1756 write_debug_section("code area", Write_Code_At);
1757 write_debug_section("string decoding table", Write_Strings_At);
1758 write_debug_section("strings area",
1759 Write_Strings_At + compression_table_size);
1760 write_debug_section("static array space", static_arrays_at);
1761 if (static_arrays_at + static_array_area_size < Write_RAM_At)
1762 { write_debug_section
1763 ("zero padding", static_arrays_at + static_array_area_size);
1766 { compiler_error("Failed assumption that globals are at start of "
1769 write_debug_section("global variables", Write_RAM_At + globals_at);
1770 write_debug_section("array space", Write_RAM_At + arrays_at);
1771 write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1772 write_debug_section("object tree", Write_RAM_At + object_tree_at);
1773 write_debug_section("common properties",
1774 Write_RAM_At + object_props_at);
1775 write_debug_section("property defaults",
1776 Write_RAM_At + prop_defaults_at);
1777 write_debug_section("class numbers",
1778 Write_RAM_At + class_numbers_offset);
1779 write_debug_section("identifier names",
1780 Write_RAM_At + identifier_names_offset);
1781 write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1782 write_debug_section("actions table", Write_RAM_At + actions_at);
1783 write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1784 if (MEMORY_MAP_EXTENSION)
1785 { write_debug_section("zero padding", Out_Size);
1787 end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1790 if (memory_map_switch)
1794 printf(" +---------------------+ 000000\n");
1795 printf("Read- | header |\n");
1796 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE);
1797 printf("memory | memory layout id |\n");
1798 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At);
1799 printf(" | code |\n");
1800 printf(" +---------------------+ %06lx\n",
1801 (long int) Write_Strings_At);
1802 printf(" | string decode table |\n");
1803 printf(" + - - - - - - - - - - + %06lx\n",
1804 (long int) Write_Strings_At + compression_table_size);
1805 printf(" | strings |\n");
1806 if (static_array_area_size)
1808 printf(" +---------------------+ %06lx\n",
1809 (long int) (static_arrays_at));
1810 printf(" | static arrays |\n");
1812 printf(" +=====================+ %06lx\n",
1813 (long int) (Write_RAM_At+globals_at));
1814 printf("Dynamic | global variables |\n");
1815 printf("memory + - - - - - - - - - - + %06lx\n",
1816 (long int) (Write_RAM_At+arrays_at));
1817 printf(" | arrays |\n");
1818 printf(" +---------------------+ %06lx\n",
1819 (long int) (Write_RAM_At+abbrevs_at));
1820 printf(" | printing variables |\n");
1821 if (alphabet_modified)
1823 printf(" + - - - - - - - - - - + %06lx\n",
1824 (long int) (Write_RAM_At+charset_at));
1825 printf(" | alphabets table |\n");
1827 if (zscii_defn_modified)
1829 printf(" + - - - - - - - - - - + %06lx\n",
1830 (long int) (Write_RAM_At+unicode_at));
1831 printf(" | Unicode table |\n");
1833 printf(" +---------------------+ %06lx\n",
1834 (long int) (Write_RAM_At+object_tree_at));
1835 printf(" | objects |\n");
1836 printf(" + - - - - - - - - - - + %06lx\n",
1837 (long int) (Write_RAM_At+object_props_at));
1838 printf(" | property values |\n");
1839 printf(" + - - - - - - - - - - + %06lx\n",
1840 (long int) (Write_RAM_At+prop_defaults_at));
1841 printf(" | property defaults |\n");
1842 printf(" + - - - - - - - - - - + %06lx\n",
1843 (long int) (Write_RAM_At+class_numbers_offset));
1844 printf(" | class numbers table |\n");
1845 printf(" + - - - - - - - - - - + %06lx\n",
1846 (long int) (Write_RAM_At+identifier_names_offset));
1847 printf(" | id names table |\n");
1848 printf(" +---------------------+ %06lx\n",
1849 (long int) (Write_RAM_At+grammar_table_at));
1850 printf(" | grammar table |\n");
1851 printf(" + - - - - - - - - - - + %06lx\n",
1852 (long int) (Write_RAM_At+actions_at));
1853 printf(" | actions |\n");
1854 printf(" +---------------------+ %06lx\n",
1855 (long int) dictionary_offset);
1856 printf(" | dictionary |\n");
1857 if (MEMORY_MAP_EXTENSION == 0)
1859 printf(" +---------------------+ %06lx\n", (long int) Out_Size);
1863 printf(" +=====================+ %06lx\n", (long int) Out_Size);
1864 printf("Runtime | (empty) |\n");
1865 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1873 if (percentages_switch)
1874 { printf("Approximate percentage breakdown of %s:\n",
1876 percentage("Code", code_length,Out_Size);
1878 percentage("Linking data", link_data_size,Out_Size);
1879 percentage("Static strings", strings_length,Out_Size);
1880 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1881 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1882 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1883 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1884 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1885 percentage("Total of save area", grammar_table_at,Out_Size);
1886 percentage("Total of text", strings_length,Out_Size);
1888 if (frequencies_switch)
1890 { printf("How frequently abbreviations were used, and roughly\n");
1891 printf("how many bytes they saved: ('_' denotes spaces)\n");
1892 for (i=0; i<no_abbreviations; i++)
1893 { char abbrev_string[MAX_ABBREV_LENGTH];
1894 strcpy(abbrev_string,
1895 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1896 for (j=0; abbrev_string[j]!=0; j++)
1897 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1898 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1899 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1900 if ((i%3)==2) printf("\n");
1902 if ((i%3)!=0) printf("\n");
1903 if (no_abbreviations==0) printf("None were declared.\n");
1908 extern void construct_storyfile(void)
1911 construct_storyfile_z();
1913 construct_storyfile_g();
1916 /* ========================================================================= */
1917 /* Data structure management routines */
1918 /* ------------------------------------------------------------------------- */
1920 extern void init_tables_vars(void)
1923 statusline_flag = SCORE_STYLE;
1925 zmachine_paged_memory = NULL;
1928 code_offset = 0x800;
1929 actions_offset = 0x800;
1930 preactions_offset = 0x800;
1931 dictionary_offset = 0x800;
1932 adjectives_offset = 0x800;
1933 variables_offset = 0;
1934 strings_offset = 0xc00;
1935 individuals_offset=0x800;
1936 identifier_names_offset=0x800;
1937 class_numbers_offset = 0x800;
1938 arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1939 static_arrays_offset = 0x0800;
1942 code_offset = 0x12345;
1943 actions_offset = 0x12345;
1944 preactions_offset = 0x12345;
1945 dictionary_offset = 0x12345;
1946 adjectives_offset = 0x12345;
1947 variables_offset = 0x12345;
1948 arrays_offset = 0x12345;
1949 strings_offset = 0x12345;
1950 individuals_offset=0x12345;
1951 identifier_names_offset=0x12345;
1952 class_numbers_offset = 0x12345;
1953 static_arrays_offset = 0x12345;
1957 extern void tables_begin_pass(void)
1961 extern void tables_allocate_arrays(void)
1965 extern void tables_free_arrays(void)
1967 /* Allocation for this array happens in construct_storyfile() above */
1969 my_free(&zmachine_paged_memory,"output buffer");
1972 /* ========================================================================= */