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 - 2021 */
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];
299 if (MAX_ABBREVS + MAX_DYNAMIC_STRINGS != 96)
300 fatalerror("MAX_ABBREVS + MAX_DYNAMIC_STRINGS is not 96");
302 /* Initially all 96 entries are set to " ". (We store half of 0x40,
303 the address of the " " we wrote above.) */
304 for (i=0; i<3*32; i++)
305 { p[mark++]=0; p[mark++]=0x20;
308 /* Entries from 0 to MAX_DYNAMIC_STRINGS (default 32) are "variable
309 strings". Write the abbreviations after these. */
310 k = abbrevs_at+2*MAX_DYNAMIC_STRINGS;
311 for (i=0; i<no_abbreviations; i++)
312 { j=abbrev_values[i];
317 /* ------------------- Header extension table ------------------------- */
320 headerext_length = ZCODE_HEADER_EXT_WORDS;
321 if (zscii_defn_modified) {
322 /* Need at least 3 words for unicode table address */
323 if (headerext_length < 3)
324 headerext_length = 3;
326 if (ZCODE_HEADER_FLAGS_3) {
327 /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
328 if (headerext_length < 4)
329 headerext_length = 4;
331 p[mark++] = 0; p[mark++] = headerext_length;
332 for (i=0; i<headerext_length; i++)
333 { p[mark++] = 0; p[mark++] = 0;
336 /* -------------------- Z-character set table ------------------------- */
338 if (alphabet_modified)
340 for (i=0;i<3;i++) for (j=0;j<26;j++)
341 { if (alphabet[i][j] == '~') p[mark++] = '\"';
342 else p[mark++] = alphabet[i][j];
346 /* ------------------ Unicode translation table ----------------------- */
349 if (zscii_defn_modified)
351 p[mark++] = zscii_high_water_mark;
352 for (i=0;i<zscii_high_water_mark;i++)
353 { j = zscii_to_unicode(155 + i);
354 if (j < 0 || j > 0xFFFF) {
355 error("Z-machine Unicode translation table cannot contain characters beyond $FFFF.");
357 p[mark++] = j/256; p[mark++] = j%256;
361 /* -------------------- Objects and Properties ------------------------ */
363 /* The object table must be word-aligned. The Z-machine spec does not
364 require this, but the RA__Pr() veneer routine does. See
365 http://inform7.com/mantis/view.php?id=1712.
367 while ((mark%2) != 0) p[mark++]=0;
369 prop_defaults_at = mark;
371 p[mark++]=0; p[mark++]=0;
373 for (i=2; i< ((version_number==3)?32:64); i++)
374 { p[mark++]=prop_default_value[i]/256;
375 p[mark++]=prop_default_value[i]%256;
378 object_tree_at = mark;
380 mark += ((version_number==3)?9:14)*no_objects;
382 object_props_at = mark;
384 for (i=0; i<properties_table_size; i++)
385 p[mark+i]=properties_table[i];
387 for (i=0, objs=object_tree_at; i<no_objects; i++)
389 if (version_number == 3)
390 { p[objs]=objectsz[i].atts[0];
391 p[objs+1]=objectsz[i].atts[1];
392 p[objs+2]=objectsz[i].atts[2];
393 p[objs+3]=objectsz[i].atts[3];
394 p[objs+4]=objectsz[i].parent;
395 p[objs+5]=objectsz[i].next;
396 p[objs+6]=objectsz[i].child;
402 { p[objs]=objectsz[i].atts[0];
403 p[objs+1]=objectsz[i].atts[1];
404 p[objs+2]=objectsz[i].atts[2];
405 p[objs+3]=objectsz[i].atts[3];
406 p[objs+4]=objectsz[i].atts[4];
407 p[objs+5]=objectsz[i].atts[5];
408 p[objs+6]=(objectsz[i].parent)/256;
409 p[objs+7]=(objectsz[i].parent)%256;
410 p[objs+8]=(objectsz[i].next)/256;
411 p[objs+9]=(objectsz[i].next)%256;
412 p[objs+10]=(objectsz[i].child)/256;
413 p[objs+11]=(objectsz[i].child)%256;
415 { p[objs+12]=mark/256;
419 { p[objs+12]=objectsz[i].propsize/256;
420 p[objs+13]=objectsz[i].propsize%256;
424 mark+=objectsz[i].propsize;
427 /* ----------- Table of Class Prototype Object Numbers ---------------- */
429 class_numbers_offset = mark;
430 for (i=0; i<no_classes; i++)
431 { p[mark++] = class_object_numbers[i]/256;
432 p[mark++] = class_object_numbers[i]%256;
434 { p[mark++] = class_begins_at[i]/256;
435 p[mark++] = class_begins_at[i]%256;
441 /* ------------------- Table of Identifier Names ---------------------- */
443 identifier_names_offset = mark;
446 { p[mark++] = no_individual_properties/256;
447 p[mark++] = no_individual_properties%256;
448 for (i=1; i<no_individual_properties; i++)
449 { p[mark++] = individual_name_strings[i]/256;
450 p[mark++] = individual_name_strings[i]%256;
453 attribute_names_offset = mark;
455 { p[mark++] = attribute_name_strings[i]/256;
456 p[mark++] = attribute_name_strings[i]%256;
459 action_names_offset = mark;
460 fake_action_names_offset = mark + 2*no_actions;
461 for (i=0; i<no_actions + no_fake_actions; i++)
462 { p[mark++] = action_name_strings[i]/256;
463 p[mark++] = action_name_strings[i]%256;
466 array_names_offset = mark;
467 global_names_offset = mark + 2*no_arrays;
468 routine_names_offset = global_names_offset + 2*no_globals;
469 constant_names_offset = routine_names_offset + 2*no_named_routines;
470 for (i=0; i<no_arrays + no_globals
471 + no_named_routines + no_named_constants; i++)
472 { if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
473 p[mark++] = array_name_strings[i]/256;
474 p[mark++] = array_name_strings[i]%256;
477 id_names_length = (mark - identifier_names_offset)/2;
479 routine_flags_array_offset = mark;
481 if (define_INFIX_switch)
482 { for (i=0, k=1, l=0; i<no_named_routines; i++)
483 { if (sflags[named_routine_symbols[i]] & STAR_SFLAG) l=l+k;
485 if (k==256) { p[mark++] = l; k=1; l=0; }
487 if (k!=1) p[mark++]=l;
490 /* ---------------- Table of Indiv Property Values -------------------- */
492 individuals_offset = mark;
493 for (i=0; i<individuals_length; i++)
494 p[mark++] = individuals_table[i];
496 /* ----------------- Variables and Dynamic Arrays --------------------- */
500 for (i=0; i<dynamic_array_area_size; i++)
501 p[mark++] = dynamic_array_area[i];
503 for (i=0; i<240; i++)
504 { j=global_initial_value[i];
505 p[globals_at+i*2] = j/256; p[globals_at+i*2+1] = j%256;
508 /* ------------------ Terminating Characters Table -------------------- */
510 if (version_number >= 5)
511 { terminating_chars_at = mark;
512 for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
516 /* ------------------------ Grammar Table ----------------------------- */
518 if (grammar_version_number > 2)
519 { warning("This version of Inform is unable to produce the grammar \
520 table format requested (producing number 2 format instead)");
521 grammar_version_number = 2;
524 grammar_table_at = mark;
526 mark = mark + no_Inform_verbs*2;
528 for (i=0; i<no_Inform_verbs; i++)
529 { p[grammar_table_at + i*2] = (mark/256);
530 p[grammar_table_at + i*2 + 1] = (mark%256);
531 p[mark++] = Inform_verbs[i].lines;
532 for (j=0; j<Inform_verbs[i].lines; j++)
533 { k = Inform_verbs[i].l[j];
534 if (grammar_version_number == 1)
536 p[mark+7] = grammar_lines[k+1];
537 for (m=1;m<=6;m++) p[mark + m] = 0;
538 k = k + 2; m = 1; n = 0;
539 while ((grammar_lines[k] != 15) && (m<=6))
540 { p[mark + m] = grammar_lines[k];
541 if (grammar_lines[k] < 180) n++;
549 p[mark++] = grammar_lines[k++];
550 p[mark++] = grammar_lines[k++];
552 { tok = grammar_lines[k++];
554 if (tok == 15) break;
555 p[mark++] = grammar_lines[k++];
556 p[mark++] = grammar_lines[k++];
562 /* ------------------- Actions and Preactions ------------------------- */
563 /* (The term "preactions" is traditional: Inform uses the preactions */
564 /* table for a different purpose than Infocom used to.) */
565 /* The values are written later, when the Z-code offset is known. */
566 /* -------------------------------------------------------------------- */
569 mark += no_actions*2;
571 preactions_at = mark;
572 if (grammar_version_number == 1)
573 mark += no_grammar_token_routines*2;
575 /* ----------------------- Adjectives Table --------------------------- */
577 if (grammar_version_number == 1)
578 { p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
579 adjectives_offset = mark;
580 dictionary_offset = mark + 4*no_adjectives;
582 for (i=0; i<no_adjectives; i++)
583 { j = final_dict_order[adjectives[no_adjectives-i-1]]
584 *((version_number==3)?7:9)
585 + dictionary_offset + 7;
586 p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
587 p[mark++]=(256-no_adjectives+i);
591 { p[mark]=0; p[mark+1]=0; mark+=2;
592 adjectives_offset = mark;
593 dictionary_offset = mark;
596 /* ------------------------- Dictionary ------------------------------- */
600 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
601 dictionary[2]=','; /* force words apart */
604 dictionary[4]=(version_number==3)?7:9; /* Length of each entry */
605 dictionary[5]=(dict_entries/256); /* Number of entries */
606 dictionary[6]=(dict_entries%256);
608 for (i=0; i<7; i++) p[mark++] = dictionary[i];
610 for (i=0; i<dict_entries; i++)
611 { k = 7 + i*((version_number==3)?7:9);
612 j = mark + final_dict_order[i]*((version_number==3)?7:9);
613 for (l = 0; l<((version_number==3)?7:9); l++)
614 p[j++] = dictionary[k++];
616 mark += dict_entries * ((version_number==3)?7:9);
618 /* ------------------------- Module Map ------------------------------- */
621 { map_of_module = mark; /* Filled in below */
625 /* ------------------------ Static Arrays ----------------------------- */
627 static_arrays_at = mark;
628 for (i=0; i<static_array_area_size; i++)
629 p[mark++] = static_array_area[i];
631 /* ----------------- A gap before the code area ----------------------- */
632 /* (so that it will start at an exact packed address and so that all */
633 /* routine packed addresses are >= 256, hence long constants) */
634 /* -------------------------------------------------------------------- */
636 while ((mark%length_scale_factor) != 0) p[mark++]=0;
637 while (mark < (scale_factor*0x100)) p[mark++]=0;
638 if (oddeven_packing_switch)
639 while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
642 { error("This program has overflowed the maximum readable-memory \
643 size of the Z-machine format. See the memory map below: the start \
644 of the area marked \"above readable memory\" must be brought down to $FFFE \
646 memory_map_switch = TRUE;
647 /* Backpatching the grammar tables requires us to trust some of the */
648 /* addresses we've written into Z-machine memory, but they may have */
649 /* been truncated to 16 bits, so we can't do it. */
650 skip_backpatching = TRUE;
653 /* -------------------------- Code Area ------------------------------- */
654 /* (From this point on we don't write any more into the "p" buffer.) */
655 /* -------------------------------------------------------------------- */
657 Write_Code_At = mark;
658 if (!OMIT_UNUSED_ROUTINES) {
659 code_length = zmachine_pc;
662 if (zmachine_pc != df_total_size_before_stripping)
663 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
664 code_length = df_total_size_after_stripping;
668 /* ------------------ Another synchronising gap ----------------------- */
670 if (oddeven_packing_switch)
672 while ((mark%(scale_factor*2)) != 0) mark++;
674 while ((mark%(scale_factor*2)) != scale_factor) mark++;
677 while ((mark%scale_factor) != 0) mark++;
679 /* ------------------------- Strings Area ----------------------------- */
681 Write_Strings_At = mark;
682 strings_length = static_strings_extent;
683 mark += strings_length;
685 /* --------------------- Module Linking Data -------------------------- */
688 { link_table_at = mark; mark += link_data_size;
689 mark += zcode_backpatch_size;
690 mark += zmachine_backpatch_size;
693 /* --------------------- Is the file too big? ------------------------- */
697 switch(version_number)
698 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
700 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
703 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
707 { excess = Out_Size-((int32) 0x10000L); limit=64;
711 { char memory_full_error[80];
712 sprintf(memory_full_error,
713 "The %s exceeds version-%d limit (%dK) by %d bytes",
714 output_called, version_number, limit, excess);
715 fatalerror(memory_full_error);
718 /* --------------------------- Offsets -------------------------------- */
720 dictionary_offset = dictionary_at;
721 variables_offset = globals_at;
722 actions_offset = actions_at;
723 preactions_offset = preactions_at;
724 prop_defaults_offset = prop_defaults_at;
725 prop_values_offset = object_props_at;
726 static_memory_offset = grammar_table_at;
727 grammar_table_offset = grammar_table_at;
728 static_arrays_offset = static_arrays_at;
730 if (extend_memory_map)
732 if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
733 while ((extend_offset%length_scale_factor) != 0) extend_offset++;
734 /* Not sure why above line is necessary, but oddeven_packing
735 * will need extend_offset to be even */
736 code_offset = extend_offset*scale_factor;
737 if (oddeven_packing_switch)
738 strings_offset = code_offset + scale_factor;
740 strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
742 /* With the extended memory model, need to specifically check that we
743 * haven't overflowed the packed address range for routines or strings.
744 * With the standard memory model, we only need the earlier total size
747 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
749 { char code_full_error[80];
750 sprintf(code_full_error,
751 "The code area limit has been exceeded by %d bytes",
753 fatalerror(code_full_error);
756 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
758 { char strings_full_error[140];
759 if (oddeven_packing_switch)
760 sprintf(strings_full_error,
761 "The strings area limit has been exceeded by %d bytes",
764 sprintf(strings_full_error,
765 "The code+strings area limit has been exceeded by %d bytes. \
766 Try running Inform again with -B on the command line.",
768 fatalerror(strings_full_error);
772 { code_offset = Write_Code_At;
773 strings_offset = Write_Strings_At;
776 /* --------------------------- The Header ----------------------------- */
778 for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */
780 p[0] = version_number; /* Version number */
781 p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */
782 p[2] = (release_number/256);
783 p[3] = (release_number%256); /* Release */
784 p[4] = (Write_Code_At/256);
785 p[5] = (Write_Code_At%256); /* End of paged memory */
786 if (version_number==6)
787 { j=code_offset/scale_factor; /* Packed address of "Main__" */
788 p[6]=(j/256); p[7]=(j%256);
791 { j=Write_Code_At+1; /* Initial PC value (bytes) */
792 p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */
794 p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */
795 p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */
796 p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */
797 p[14]=(grammar_table_at/256);
798 p[15]=(grammar_table_at%256); /* Grammar */
799 for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */
800 j+=k*flags2_requirements[i]; /* unusual opcodes assembled */
801 p[16]=j/256; p[17]=j%256;
802 write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
803 p[24]=abbrevs_at/256;
804 p[25]=abbrevs_at%256; /* Abbreviations table */
805 p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */
806 p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */
808 if (extend_memory_map)
809 { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
810 p[40]=j/256; p[41]=j%256; /* Routines offset */
811 if (oddeven_packing_switch)
812 j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
813 p[42]=j/256; p[43]=j%256; /* = Strings offset */
816 if (version_number >= 5)
817 { p[46] = terminating_chars_at/256; /* Terminating characters table */
818 p[47] = terminating_chars_at%256;
821 if (alphabet_modified)
823 p[52]=j/256; p[53]=j%256; } /* Character set table address */
826 p[54] = j/256; p[55] = j%256; /* Header extension table address */
828 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
830 p[62] = '0' + ((RELEASE_NUMBER/10)%10);
831 p[63] = '0' + RELEASE_NUMBER%10;
833 /* ------------------------ Header Extension -------------------------- */
835 /* The numbering in the spec is a little weird -- it's headerext_length
836 words *after* the initial length word. We follow the spec numbering
837 in this switch statement, so the count is 1-based. */
838 for (i=1; i<=headerext_length; i++) {
841 j = unicode_at; /* Unicode translation table address */
844 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
850 p[headerext_at+2*i+0] = j / 256;
851 p[headerext_at+2*i+1] = j % 256;
854 /* ----------------- The Header: Extras for modules ------------------- */
858 p[1]=MODULE_VERSION_NUMBER;
859 p[6]=map_of_module/256;
860 p[7]=map_of_module%256;
862 mark = map_of_module; /* Module map format: */
864 p[mark++]=object_tree_at/256; /* 0: Object tree addr */
865 p[mark++]=object_tree_at%256;
866 p[mark++]=object_props_at/256; /* 2: Prop values addr */
867 p[mark++]=object_props_at%256;
868 p[mark++]=(Write_Strings_At/scale_factor)/256; /* 4: Static strs */
869 p[mark++]=(Write_Strings_At/scale_factor)%256;
870 p[mark++]=class_numbers_offset/256; /* 6: Class nos addr */
871 p[mark++]=class_numbers_offset%256;
872 p[mark++]=individuals_offset/256; /* 8: Indiv prop values */
873 p[mark++]=individuals_offset%256;
874 p[mark++]=individuals_length/256; /* 10: Length of table */
875 p[mark++]=individuals_length%256;
876 p[mark++]=no_symbols/256; /* 12: No of symbols */
877 p[mark++]=no_symbols%256;
878 p[mark++]=no_individual_properties/256; /* 14: Max property no */
879 p[mark++]=no_individual_properties%256;
880 p[mark++]=no_objects/256; /* 16: No of objects */
881 p[mark++]=no_objects%256;
883 p[mark++]=i/256; /* 18: Import/exports */
885 p[mark++]=link_data_size/256; /* 20: Size of */
886 p[mark++]=link_data_size%256;
888 p[mark++]=i/256; /* 22: Code backpatch */
890 p[mark++]=zcode_backpatch_size/256; /* 24: Size of */
891 p[mark++]=zcode_backpatch_size%256;
892 i += zcode_backpatch_size;
893 p[mark++]=i/256; /* 26: Image backpatch */
895 p[mark++]=zmachine_backpatch_size/256; /* 28: Size of */
896 p[mark++]=zmachine_backpatch_size%256;
898 /* Further space in this table is reserved for future use */
901 /* ---- Backpatch the Z-machine, now that all information is in ------- */
903 if (!module_switch && !skip_backpatching)
904 { backpatch_zmachine_image_z();
905 for (i=1; i<id_names_length; i++)
906 { int32 v = 256*p[identifier_names_offset + i*2]
907 + p[identifier_names_offset + i*2 + 1];
908 if (v!=0) v += strings_offset/scale_factor;
909 p[identifier_names_offset + i*2] = v/256;
910 p[identifier_names_offset + i*2 + 1] = v%256;
914 for (i=0; i<no_actions; i++)
915 { j=action_byte_offset[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;
922 if (grammar_version_number == 1)
923 { mark = preactions_at;
924 for (i=0; i<no_grammar_token_routines; i++)
925 { j=grammar_token_routine[i];
926 if (OMIT_UNUSED_ROUTINES)
927 j = df_stripped_address_for_address(j);
928 j += code_offset/scale_factor;
929 p[mark++]=j/256; p[mark++]=j%256;
933 { for (l = 0; l<no_Inform_verbs; l++)
934 { k = grammar_table_at + 2*l;
935 i = p[k]*256 + p[k+1];
936 for (j = p[i++]; j>0; j--)
937 { int topbits; int32 value;
940 { topbits = (p[i]/0x40) & 3;
941 value = p[i+1]*256 + p[i+2];
944 value = final_dict_order[value]
945 *((version_number==3)?7:9)
946 + dictionary_offset + 7;
949 if (OMIT_UNUSED_ROUTINES)
950 value = df_stripped_address_for_address(value);
951 value += code_offset/scale_factor;
954 p[i+1] = value/256; p[i+2] = value%256;
963 /* ---- From here on, it's all reportage: construction is finished ---- */
965 if (statistics_switch)
966 { int32 k_long, rate; char *k_str="";
967 k_long=(Out_Size/1024);
968 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
969 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
970 if (total_bytes_trans == 0) rate = 0;
971 else rate=total_bytes_trans*1000/total_chars_trans;
974 %3d source code files %6d syntactic lines\n\
975 %6d textual lines %8ld characters ",
976 total_input_files, no_syntax_lines,
977 total_source_line_count, (long int) total_chars_read);
978 if (character_set_unicode) printf("(UTF-8)\n");
979 else if (character_set_setting == 0) printf("(plain ASCII)\n");
981 { printf("(ISO 8859-%d %s)\n", character_set_setting,
982 name_of_iso_set(character_set_setting));
985 printf("Allocated:\n\
986 %6d symbols (maximum %4d) %8ld bytes of memory\n\
987 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
988 no_symbols, MAX_SYMBOLS,
989 (long int) malloced_bytes,
991 version_name(version_number),
993 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
994 (long int) k_long, k_str);
997 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
998 %6d global vars (maximum 233) %6d variable/array space (maximum %d)\n",
999 no_classes, MAX_CLASSES,
1000 no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)),
1002 dynamic_array_area_size, MAX_STATIC_DATA);
1005 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
1006 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1007 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
1008 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
1009 no_Inform_verbs, MAX_VERBS,
1010 dict_entries, MAX_DICT_ENTRIES,
1011 no_grammar_lines, grammar_version_number,
1013 no_actions, MAX_ACTIONS,
1014 no_attributes, ((version_number==3)?32:48),
1015 no_properties-2, ((version_number==3)?30:62),
1016 no_individual_properties - 64);
1018 if (track_unused_routines)
1020 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1022 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
1023 (long int) df_total_size_before_stripping, (long int) diff,
1024 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1025 100 * (float)diff / (float)df_total_size_before_stripping);
1029 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1030 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1031 %6ld instructions of Z-code %6d sequence points\n\
1032 %6ld bytes readable memory used (maximum 65536)\n\
1033 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
1034 (long int) total_chars_trans,
1035 (long int) total_bytes_trans,
1036 (total_chars_trans>total_bytes_trans)?0:1,
1038 no_abbreviations, MAX_ABBREVS,
1040 (long int) no_instructions, no_sequence_points,
1041 (long int) Write_Code_At,
1042 (long int) Out_Size,
1044 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1052 "\nOffsets in %s:\n\
1053 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1054 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1055 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1057 (long int) abbrevs_at,
1058 (long int) prop_defaults_at,
1059 (long int) object_tree_at,
1060 (long int) object_props_at,
1061 (long int) globals_at,
1062 (long int) grammar_table_at,
1063 (long int) actions_at,
1064 (long int) preactions_at,
1065 (long int) adjectives_offset,
1066 (long int) dictionary_at,
1067 (long int) Write_Code_At,
1068 (long int) Write_Strings_At);
1070 printf("%05lx Linking data\n",(long int) link_table_at);
1074 if (debugfile_switch)
1075 { begin_writing_debug_sections();
1076 write_debug_section("abbreviations", 64);
1077 write_debug_section("abbreviations table", abbrevs_at);
1078 write_debug_section("header extension", headerext_at);
1079 if (alphabet_modified)
1080 { write_debug_section("alphabets table", charset_at);
1082 if (zscii_defn_modified)
1083 { write_debug_section("Unicode table", unicode_at);
1085 write_debug_section("property defaults", prop_defaults_at);
1086 write_debug_section("object tree", object_tree_at);
1087 write_debug_section("common properties", object_props_at);
1088 write_debug_section("class numbers", class_numbers_offset);
1089 write_debug_section("identifier names", identifier_names_offset);
1090 write_debug_section("individual properties", individuals_offset);
1091 write_debug_section("global variables", globals_at);
1092 write_debug_section("array space", globals_at+480);
1093 write_debug_section("grammar table", grammar_table_at);
1094 write_debug_section("actions table", actions_at);
1095 write_debug_section("parsing routines", preactions_at);
1096 write_debug_section("adjectives table", adjectives_offset);
1097 write_debug_section("dictionary", dictionary_at);
1098 write_debug_section("code area", Write_Code_At);
1099 write_debug_section("strings area", Write_Strings_At);
1100 end_writing_debug_sections(Out_Size);
1103 if (memory_map_switch)
1106 printf("Dynamic +---------------------+ 00000\n");
1107 printf("memory | header |\n");
1108 printf(" +---------------------+ 00040\n");
1109 printf(" | abbreviations |\n");
1110 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at);
1111 printf(" | abbreviations table |\n");
1112 printf(" +---------------------+ %05lx\n", (long int) headerext_at);
1113 printf(" | header extension |\n");
1114 if (alphabet_modified)
1116 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at);
1117 printf(" | alphabets table |\n");
1119 if (zscii_defn_modified)
1121 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at);
1122 printf(" | Unicode table |\n");
1124 printf(" +---------------------+ %05lx\n",
1125 (long int) prop_defaults_at);
1126 printf(" | property defaults |\n");
1127 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at);
1128 printf(" | objects |\n");
1129 printf(" + - - - - - - - - - - + %05lx\n",
1130 (long int) object_props_at);
1131 printf(" | object short names, |\n");
1132 printf(" | common prop values |\n");
1133 printf(" + - - - - - - - - - - + %05lx\n",
1134 (long int) class_numbers_offset);
1135 printf(" | class numbers table |\n");
1136 printf(" + - - - - - - - - - - + %05lx\n",
1137 (long int) identifier_names_offset);
1138 printf(" | symbol names table |\n");
1139 printf(" + - - - - - - - - - - + %05lx\n",
1140 (long int) individuals_offset);
1141 printf(" | indiv prop values |\n");
1142 printf(" +---------------------+ %05lx\n", (long int) globals_at);
1143 printf(" | global variables |\n");
1144 printf(" + - - - - - - - - - - + %05lx\n",
1145 ((long int) globals_at)+480L);
1146 printf(" | arrays |\n");
1147 printf(" +=====================+ %05lx\n",
1148 (long int) grammar_table_at);
1149 printf("Readable| grammar table |\n");
1150 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at);
1151 printf(" | actions |\n");
1152 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at);
1153 printf(" | parsing routines |\n");
1154 printf(" + - - - - - - - - - - + %05lx\n",
1155 (long int) adjectives_offset);
1156 printf(" | adjectives |\n");
1157 printf(" +---------------------+ %05lx\n", (long int) dictionary_at);
1158 printf(" | dictionary |\n");
1161 printf(" + - - - - - - - - - - + %05lx\n",
1162 (long int) map_of_module);
1163 printf(" | map of module addrs |\n");
1165 if (static_array_area_size)
1167 printf(" +---------------------+ %05lx\n", (long int) static_arrays_at);
1168 printf(" | static arrays |\n");
1170 printf(" +=====================+ %05lx\n", (long int) Write_Code_At);
1171 printf("Above | Z-code |\n");
1172 printf("readable+---------------------+ %05lx\n",
1173 (long int) Write_Strings_At);
1174 printf("memory | strings |\n");
1177 printf(" +=====================+ %05lx\n", (long int) link_table_at);
1178 printf(" | module linking data |\n");
1180 printf(" +---------------------+ %05lx\n", (long int) Out_Size);
1183 if (percentages_switch)
1184 { printf("Approximate percentage breakdown of %s:\n",
1186 percentage("Z-code", code_length,Out_Size);
1188 percentage("Linking data", link_data_size,Out_Size);
1189 percentage("Static strings", strings_length,Out_Size);
1190 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1191 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1192 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1193 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1194 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1195 percentage("Total of save area", grammar_table_at,Out_Size);
1196 percentage("Total of text", total_bytes_trans,Out_Size);
1198 if (frequencies_switch)
1200 { printf("How frequently abbreviations were used, and roughly\n");
1201 printf("how many bytes they saved: ('_' denotes spaces)\n");
1202 for (i=0; i<no_abbreviations; i++)
1203 { char abbrev_string[MAX_ABBREV_LENGTH];
1204 strcpy(abbrev_string,
1205 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1206 for (j=0; abbrev_string[j]!=0; j++)
1207 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1208 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1209 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1210 if ((i%3)==2) printf("\n");
1212 if ((i%3)!=0) printf("\n");
1213 if (no_abbreviations==0) printf("None were declared.\n");
1218 static void construct_storyfile_g(void)
1220 int32 i, j, k, l, mark, strings_length, limit;
1221 int32 globals_at, dictionary_at, actions_at, preactions_at,
1222 abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1223 grammar_table_at, charset_at, headerext_at,
1224 unicode_at, arrays_at, static_arrays_at;
1225 int32 threespaces, code_length;
1226 char *output_called = (module_switch)?"module":"story file";
1230 individual_name_strings =
1231 my_calloc(sizeof(int32), no_individual_properties,
1232 "identifier name strings");
1233 action_name_strings =
1234 my_calloc(sizeof(int32), no_actions + no_fake_actions,
1235 "action name strings");
1236 attribute_name_strings =
1237 my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1238 "attribute name strings");
1239 array_name_strings =
1240 my_calloc(sizeof(int32),
1242 "array name strings");
1244 write_the_identifier_names();
1245 threespaces = compile_string(" ", STRCTX_GAME);
1247 compress_game_text();
1249 /* We now know how large the buffer to hold our construction has to be */
1251 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1254 /* Foolish code to make this routine compile on all ANSI compilers */
1256 p = (uchar *) zmachine_paged_memory;
1258 /* In what follows, the "mark" will move upwards in memory: at various
1259 points its value will be recorded for milestones like
1260 "dictionary table start". It begins at 0x40, just after the header */
1262 /* Ok, our policy here will be to set the *_at values all relative
1263 to RAM. That's so we can write into zmachine_paged_memory[mark]
1264 and actually hit what we're aiming at.
1265 All the *_offset values will be set to true Glulx machine
1268 /* To get our bearings, figure out where the strings and code are. */
1269 /* We start with two words, which conventionally identify the
1270 memory layout. This is why the code starts eight bytes after
1272 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1273 if (!OMIT_UNUSED_ROUTINES) {
1274 code_length = zmachine_pc;
1277 if (zmachine_pc != df_total_size_before_stripping)
1278 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1279 code_length = df_total_size_after_stripping;
1281 Write_Strings_At = Write_Code_At + code_length;
1282 strings_length = compression_table_size + compression_string_size;
1284 static_arrays_at = Write_Strings_At + strings_length;
1286 /* Now figure out where RAM starts. */
1287 Write_RAM_At = static_arrays_at + static_array_area_size;
1288 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1289 while (Write_RAM_At % GPAGESIZE)
1292 /* Now work out all those RAM positions. */
1295 /* ----------------- Variables and Dynamic Arrays --------------------- */
1298 for (i=0; i<no_globals; i++) {
1299 j = global_initial_value[i];
1300 WriteInt32(p+mark, j);
1305 for (i=MAX_GLOBAL_VARIABLES*4; i<dynamic_array_area_size; i++)
1306 p[mark++] = dynamic_array_area[i];
1308 /* -------------------------- Dynamic Strings -------------------------- */
1311 WriteInt32(p+mark, no_dynamic_strings);
1313 for (i=0; i<no_dynamic_strings; i++) {
1314 j = Write_Strings_At + compressed_offsets[threespaces-1];
1315 WriteInt32(p+mark, j);
1319 /* ---------------- Various Things I'm Not Sure About ------------------ */
1320 /* Actually, none of these are relevant to Glulx. */
1321 headerext_at = mark;
1323 if (alphabet_modified)
1326 if (zscii_defn_modified)
1329 /* -------------------- Objects and Properties ------------------------ */
1331 object_tree_at = mark;
1333 object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1335 for (i=0; i<no_objects; i++) {
1336 int32 objmark = mark;
1337 p[mark++] = 0x70; /* type byte -- object */
1338 for (j=0; j<NUM_ATTR_BYTES; j++) {
1339 p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1341 for (j=0; j<6; j++) {
1344 case 0: /* next object in the linked list. */
1345 if (i == no_objects-1)
1348 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1350 case 1: /* hardware name address */
1351 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1353 case 2: /* property table address */
1354 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1356 case 3: /* parent */
1357 if (objectsg[i].parent == 0)
1360 val = Write_RAM_At + object_tree_at +
1361 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1363 case 4: /* sibling */
1364 if (objectsg[i].next == 0)
1367 val = Write_RAM_At + object_tree_at +
1368 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1371 if (objectsg[i].child == 0)
1374 val = Write_RAM_At + object_tree_at +
1375 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1378 p[mark++] = (val >> 24) & 0xFF;
1379 p[mark++] = (val >> 16) & 0xFF;
1380 p[mark++] = (val >> 8) & 0xFF;
1381 p[mark++] = (val) & 0xFF;
1384 for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1389 if (object_props_at != mark)
1390 error("*** Object table was impossible length ***");
1392 for (i=0; i<properties_table_size; i++)
1393 p[mark+i]=properties_table[i];
1395 for (i=0; i<no_objects; i++) {
1396 int32 tableaddr = object_props_at + objectsg[i].propaddr;
1397 int32 tablelen = ReadInt32(p+tableaddr);
1399 for (j=0; j<tablelen; j++) {
1400 k = ReadInt32(p+tableaddr+4);
1401 k += (Write_RAM_At + object_props_at);
1402 WriteInt32(p+tableaddr+4, k);
1407 mark += properties_table_size;
1409 prop_defaults_at = mark;
1410 for (i=0; i<no_properties; i++) {
1411 k = prop_default_value[i];
1412 WriteInt32(p+mark, k);
1416 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1418 class_numbers_offset = mark;
1419 for (i=0; i<no_classes; i++) {
1420 j = Write_RAM_At + object_tree_at +
1421 (OBJECT_BYTE_LENGTH*(class_object_numbers[i]-1));
1422 WriteInt32(p+mark, j);
1425 WriteInt32(p+mark, 0);
1428 /* -------------------- Table of Property Names ------------------------ */
1430 /* We try to format this bit with some regularity...
1431 address of common properties
1432 number of common properties
1433 address of indiv properties
1434 number of indiv properties (counted from INDIV_PROP_START)
1435 address of attributes
1436 number of attributes (always NUM_ATTR_BYTES*8)
1441 identifier_names_offset = mark;
1442 mark += 32; /* eight pairs of values, to be filled in. */
1444 WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1445 WriteInt32(p+identifier_names_offset+4, no_properties);
1446 for (i=0; i<no_properties; i++) {
1447 j = individual_name_strings[i];
1449 j = Write_Strings_At + compressed_offsets[j-1];
1450 WriteInt32(p+mark, j);
1454 WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1455 WriteInt32(p+identifier_names_offset+12,
1456 no_individual_properties-INDIV_PROP_START);
1457 for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1458 j = individual_name_strings[i];
1460 j = Write_Strings_At + compressed_offsets[j-1];
1461 WriteInt32(p+mark, j);
1465 WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1466 WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1467 for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1468 j = attribute_name_strings[i];
1470 j = Write_Strings_At + compressed_offsets[j-1];
1471 WriteInt32(p+mark, j);
1475 WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1476 WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1477 action_names_offset = mark;
1478 fake_action_names_offset = mark + 4*no_actions;
1479 for (i=0; i<no_actions + no_fake_actions; i++) {
1480 j = action_name_strings[i];
1482 j = Write_Strings_At + compressed_offsets[j-1];
1483 WriteInt32(p+mark, j);
1487 array_names_offset = mark;
1488 WriteInt32(p+mark, no_arrays);
1490 for (i=0; i<no_arrays; i++) {
1491 j = array_name_strings[i];
1493 j = Write_Strings_At + compressed_offsets[j-1];
1494 WriteInt32(p+mark, j);
1498 individuals_offset = mark;
1500 /* ------------------------ Grammar Table ----------------------------- */
1502 if (grammar_version_number != 2)
1503 { warning("This version of Inform is unable to produce the grammar \
1504 table format requested (producing number 2 format instead)");
1505 grammar_version_number = 2;
1508 grammar_table_at = mark;
1510 WriteInt32(p+mark, no_Inform_verbs);
1513 mark += no_Inform_verbs*4;
1515 for (i=0; i<no_Inform_verbs; i++) {
1516 j = mark + Write_RAM_At;
1517 WriteInt32(p+(grammar_table_at+4+i*4), j);
1518 p[mark++] = Inform_verbs[i].lines;
1519 for (j=0; j<Inform_verbs[i].lines; j++) {
1521 k = Inform_verbs[i].l[j];
1522 p[mark++] = grammar_lines[k++];
1523 p[mark++] = grammar_lines[k++];
1524 p[mark++] = grammar_lines[k++];
1526 tok = grammar_lines[k++];
1528 if (tok == 15) break;
1529 p[mark++] = grammar_lines[k++];
1530 p[mark++] = grammar_lines[k++];
1531 p[mark++] = grammar_lines[k++];
1532 p[mark++] = grammar_lines[k++];
1537 /* ------------------- Actions and Preactions ------------------------- */
1540 WriteInt32(p+mark, no_actions);
1542 mark += no_actions*4;
1543 /* Values to be written in later. */
1545 if (DICT_CHAR_SIZE != 1) {
1546 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1551 preactions_at = mark;
1552 adjectives_offset = mark;
1553 dictionary_offset = mark;
1555 /* ------------------------- Dictionary ------------------------------- */
1557 dictionary_at = mark;
1559 WriteInt32(dictionary+0, dict_entries);
1561 p[mark+i] = dictionary[i];
1563 for (i=0; i<dict_entries; i++) {
1564 k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1565 j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1566 for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1567 p[j++] = dictionary[k++];
1569 mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1571 /* -------------------------- All Data -------------------------------- */
1573 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1574 while (mark % GPAGESIZE)
1579 Out_Size = Write_RAM_At + RAM_Size;
1582 /* --------------------------- Offsets -------------------------------- */
1584 dictionary_offset = Write_RAM_At + dictionary_at;
1585 variables_offset = Write_RAM_At + globals_at;
1586 arrays_offset = Write_RAM_At + arrays_at;
1587 actions_offset = Write_RAM_At + actions_at;
1588 preactions_offset = Write_RAM_At + preactions_at;
1589 prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1590 object_tree_offset = Write_RAM_At + object_tree_at;
1591 prop_values_offset = Write_RAM_At + object_props_at;
1592 static_memory_offset = Write_RAM_At + grammar_table_at;
1593 grammar_table_offset = Write_RAM_At + grammar_table_at;
1594 abbreviations_offset = Write_RAM_At + abbrevs_at;
1596 code_offset = Write_Code_At;
1597 strings_offset = Write_Strings_At;
1598 static_arrays_offset = static_arrays_at;
1600 /* --------------------------- The Header ----------------------------- */
1602 /* ------ Backpatch the machine, now that all information is in ------- */
1605 { backpatch_zmachine_image_g();
1607 mark = actions_at + 4;
1608 for (i=0; i<no_actions; i++) {
1609 j = action_byte_offset[i];
1610 if (OMIT_UNUSED_ROUTINES)
1611 j = df_stripped_address_for_address(j);
1613 WriteInt32(p+mark, j);
1617 for (l = 0; l<no_Inform_verbs; l++) {
1618 k = grammar_table_at + 4 + 4*l;
1619 i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1621 for (j = p[i++]; j>0; j--) {
1625 while (p[i] != 15) {
1626 topbits = (p[i]/0x40) & 3;
1627 value = ((p[i+1] << 24) | (p[i+2] << 16)
1628 | (p[i+3] << 8) | (p[i+4]));
1631 value = dictionary_offset + 4
1632 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1635 if (OMIT_UNUSED_ROUTINES)
1636 value = df_stripped_address_for_address(value);
1637 value += code_offset;
1640 WriteInt32(p+(i+1), value);
1649 /* ---- From here on, it's all reportage: construction is finished ---- */
1651 if (statistics_switch)
1652 { int32 k_long, rate; char *k_str="";
1653 k_long=(Out_Size/1024);
1654 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1655 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1656 if (strings_length == 0) rate = 0;
1657 else rate=strings_length*1000/total_chars_trans;
1660 %3d source code files %6d syntactic lines\n\
1661 %6d textual lines %8ld characters ",
1662 total_input_files, no_syntax_lines,
1663 total_source_line_count, (long int) total_chars_read);
1664 if (character_set_unicode) printf("(UTF-8)\n");
1665 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1667 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1668 name_of_iso_set(character_set_setting));
1672 write_serial_number(serialnum);
1673 printf("Allocated:\n\
1674 %6d symbols (maximum %4d) %8ld bytes of memory\n\
1675 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1676 no_symbols, MAX_SYMBOLS,
1677 (long int) malloced_bytes,
1678 version_name(version_number),
1681 serialnum[0], serialnum[1], serialnum[2],
1682 serialnum[3], serialnum[4], serialnum[5],
1683 (long int) k_long, k_str);
1687 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
1688 %6d global vars (maximum %3d) %6d variable/array space (maximum %d)\n",
1689 no_classes, MAX_CLASSES,
1690 no_objects, MAX_OBJECTS,
1691 no_globals, MAX_GLOBAL_VARIABLES,
1692 dynamic_array_area_size, MAX_STATIC_DATA);
1695 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
1696 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1697 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
1698 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1699 no_Inform_verbs, MAX_VERBS,
1700 dict_entries, MAX_DICT_ENTRIES,
1701 no_grammar_lines, grammar_version_number,
1703 no_actions, MAX_ACTIONS,
1704 no_attributes, NUM_ATTR_BYTES*8,
1705 no_properties, INDIV_PROP_START,
1706 no_individual_properties - INDIV_PROP_START);
1708 if (track_unused_routines)
1710 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1712 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1713 (long int) df_total_size_before_stripping, (long int) diff,
1714 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1715 100 * (float)diff / (float)df_total_size_before_stripping);
1719 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1720 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1721 %6ld instructions of code %6d sequence points\n\
1722 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1723 %6ld bytes used in machine %10ld bytes free in machine\n",
1724 (long int) total_chars_trans,
1725 (long int) strings_length,
1726 (total_chars_trans>strings_length)?0:1,
1728 no_abbreviations, MAX_ABBREVS,
1730 (long int) no_instructions, no_sequence_points,
1731 (long int) (Out_Size - Write_RAM_At),
1732 (long int) Write_RAM_At,
1733 (long int) Out_Size,
1735 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1743 "\nOffsets in %s:\n\
1744 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1745 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1746 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1748 (long int) abbrevs_at,
1749 (long int) prop_defaults_at,
1750 (long int) object_tree_at,
1751 (long int) object_props_at,
1752 (long int) globals_at,
1753 (long int) grammar_table_at,
1754 (long int) actions_at,
1755 (long int) preactions_at,
1756 (long int) adjectives_offset,
1757 (long int) dictionary_at,
1758 (long int) Write_Code_At,
1759 (long int) Write_Strings_At);
1763 if (debugfile_switch)
1764 { begin_writing_debug_sections();
1765 write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1766 write_debug_section("code area", Write_Code_At);
1767 write_debug_section("string decoding table", Write_Strings_At);
1768 write_debug_section("strings area",
1769 Write_Strings_At + compression_table_size);
1770 write_debug_section("static array space", static_arrays_at);
1771 if (static_arrays_at + static_array_area_size < Write_RAM_At)
1772 { write_debug_section
1773 ("zero padding", static_arrays_at + static_array_area_size);
1776 { compiler_error("Failed assumption that globals are at start of "
1779 write_debug_section("global variables", Write_RAM_At + globals_at);
1780 write_debug_section("array space", Write_RAM_At + arrays_at);
1781 write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1782 write_debug_section("object tree", Write_RAM_At + object_tree_at);
1783 write_debug_section("common properties",
1784 Write_RAM_At + object_props_at);
1785 write_debug_section("property defaults",
1786 Write_RAM_At + prop_defaults_at);
1787 write_debug_section("class numbers",
1788 Write_RAM_At + class_numbers_offset);
1789 write_debug_section("identifier names",
1790 Write_RAM_At + identifier_names_offset);
1791 write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1792 write_debug_section("actions table", Write_RAM_At + actions_at);
1793 write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1794 if (MEMORY_MAP_EXTENSION)
1795 { write_debug_section("zero padding", Out_Size);
1797 end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1800 if (memory_map_switch)
1804 printf(" +---------------------+ 000000\n");
1805 printf("Read- | header |\n");
1806 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE);
1807 printf("memory | memory layout id |\n");
1808 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At);
1809 printf(" | code |\n");
1810 printf(" +---------------------+ %06lx\n",
1811 (long int) Write_Strings_At);
1812 printf(" | string decode table |\n");
1813 printf(" + - - - - - - - - - - + %06lx\n",
1814 (long int) Write_Strings_At + compression_table_size);
1815 printf(" | strings |\n");
1816 if (static_array_area_size)
1818 printf(" +---------------------+ %06lx\n",
1819 (long int) (static_arrays_at));
1820 printf(" | static arrays |\n");
1822 printf(" +=====================+ %06lx\n",
1823 (long int) (Write_RAM_At+globals_at));
1824 printf("Dynamic | global variables |\n");
1825 printf("memory + - - - - - - - - - - + %06lx\n",
1826 (long int) (Write_RAM_At+arrays_at));
1827 printf(" | arrays |\n");
1828 printf(" +---------------------+ %06lx\n",
1829 (long int) (Write_RAM_At+abbrevs_at));
1830 printf(" | printing variables |\n");
1831 if (alphabet_modified)
1833 printf(" + - - - - - - - - - - + %06lx\n",
1834 (long int) (Write_RAM_At+charset_at));
1835 printf(" | alphabets table |\n");
1837 if (zscii_defn_modified)
1839 printf(" + - - - - - - - - - - + %06lx\n",
1840 (long int) (Write_RAM_At+unicode_at));
1841 printf(" | Unicode table |\n");
1843 printf(" +---------------------+ %06lx\n",
1844 (long int) (Write_RAM_At+object_tree_at));
1845 printf(" | objects |\n");
1846 printf(" + - - - - - - - - - - + %06lx\n",
1847 (long int) (Write_RAM_At+object_props_at));
1848 printf(" | property values |\n");
1849 printf(" + - - - - - - - - - - + %06lx\n",
1850 (long int) (Write_RAM_At+prop_defaults_at));
1851 printf(" | property defaults |\n");
1852 printf(" + - - - - - - - - - - + %06lx\n",
1853 (long int) (Write_RAM_At+class_numbers_offset));
1854 printf(" | class numbers table |\n");
1855 printf(" + - - - - - - - - - - + %06lx\n",
1856 (long int) (Write_RAM_At+identifier_names_offset));
1857 printf(" | id names table |\n");
1858 printf(" +---------------------+ %06lx\n",
1859 (long int) (Write_RAM_At+grammar_table_at));
1860 printf(" | grammar table |\n");
1861 printf(" + - - - - - - - - - - + %06lx\n",
1862 (long int) (Write_RAM_At+actions_at));
1863 printf(" | actions |\n");
1864 printf(" +---------------------+ %06lx\n",
1865 (long int) dictionary_offset);
1866 printf(" | dictionary |\n");
1867 if (MEMORY_MAP_EXTENSION == 0)
1869 printf(" +---------------------+ %06lx\n", (long int) Out_Size);
1873 printf(" +=====================+ %06lx\n", (long int) Out_Size);
1874 printf("Runtime | (empty) |\n");
1875 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1883 if (percentages_switch)
1884 { printf("Approximate percentage breakdown of %s:\n",
1886 percentage("Code", code_length,Out_Size);
1888 percentage("Linking data", link_data_size,Out_Size);
1889 percentage("Static strings", strings_length,Out_Size);
1890 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1891 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1892 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1893 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1894 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1895 percentage("Total of save area", grammar_table_at,Out_Size);
1896 percentage("Total of text", strings_length,Out_Size);
1898 if (frequencies_switch)
1900 { printf("How frequently abbreviations were used, and roughly\n");
1901 printf("how many bytes they saved: ('_' denotes spaces)\n");
1902 for (i=0; i<no_abbreviations; i++)
1903 { char abbrev_string[MAX_ABBREV_LENGTH];
1904 strcpy(abbrev_string,
1905 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1906 for (j=0; abbrev_string[j]!=0; j++)
1907 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1908 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1909 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1910 if ((i%3)==2) printf("\n");
1912 if ((i%3)!=0) printf("\n");
1913 if (no_abbreviations==0) printf("None were declared.\n");
1918 extern void construct_storyfile(void)
1921 construct_storyfile_z();
1923 construct_storyfile_g();
1926 /* ========================================================================= */
1927 /* Data structure management routines */
1928 /* ------------------------------------------------------------------------- */
1930 extern void init_tables_vars(void)
1933 statusline_flag = SCORE_STYLE;
1935 zmachine_paged_memory = NULL;
1938 code_offset = 0x800;
1939 actions_offset = 0x800;
1940 preactions_offset = 0x800;
1941 dictionary_offset = 0x800;
1942 adjectives_offset = 0x800;
1943 variables_offset = 0;
1944 strings_offset = 0xc00;
1945 individuals_offset=0x800;
1946 identifier_names_offset=0x800;
1947 class_numbers_offset = 0x800;
1948 arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1949 static_arrays_offset = 0x0800;
1952 code_offset = 0x12345;
1953 actions_offset = 0x12345;
1954 preactions_offset = 0x12345;
1955 dictionary_offset = 0x12345;
1956 adjectives_offset = 0x12345;
1957 variables_offset = 0x12345;
1958 arrays_offset = 0x12345;
1959 strings_offset = 0x12345;
1960 individuals_offset=0x12345;
1961 identifier_names_offset=0x12345;
1962 class_numbers_offset = 0x12345;
1963 static_arrays_offset = 0x12345;
1967 extern void tables_begin_pass(void)
1971 extern void tables_allocate_arrays(void)
1975 extern void tables_free_arrays(void)
1977 /* Allocation for this array happens in construct_storyfile() above */
1979 my_free(&zmachine_paged_memory,"output buffer");
1982 /* ========================================================================= */