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 /* Copyright (c) Graham Nelson 1993 - 2020 */
8 /* This file is part of Inform. */
10 /* Inform is free software: you can redistribute it and/or modify */
11 /* it under the terms of the GNU General Public License as published by */
12 /* the Free Software Foundation, either version 3 of the License, or */
13 /* (at your option) any later version. */
15 /* Inform is distributed in the hope that it will be useful, */
16 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
17 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
18 /* GNU General Public License for more details. */
20 /* You should have received a copy of the GNU General Public License */
21 /* along with Inform. If not, see https://gnu.org/licenses/ */
23 /* ------------------------------------------------------------------------- */
27 uchar *zmachine_paged_memory; /* Where we shall store the story file
28 constructed (contains all of paged
29 memory, i.e. all but code and the
30 static strings: allocated only when
31 we know how large it needs to be,
32 at the end of the compilation pass */
34 /* In Glulx, zmachine_paged_memory contains all of RAM -- i.e. all but
35 the header, the code, the static arrays, and the static strings. */
37 /* ------------------------------------------------------------------------- */
38 /* Offsets of various areas in the Z-machine: these are set to nominal */
39 /* values before the compilation pass, and to their calculated final */
40 /* values only when construct_storyfile() happens. These are then used to */
41 /* backpatch the incorrect values now existing in the Z-machine which */
42 /* used these nominal values. */
43 /* Most of the nominal values are 0x800 because this is guaranteed to */
44 /* be assembled as a long constant if it's needed in code, since the */
45 /* largest possible value of scale_factor is 8 and 0x800/8 = 256. */
47 /* In Glulx, I use 0x12345 instead of 0x800. This will always be a long */
48 /* (32-bit) constant, since there's no scale_factor. */
49 /* ------------------------------------------------------------------------- */
60 identifier_names_offset,
65 attribute_names_offset,
67 fake_action_names_offset,
69 constant_names_offset,
70 routines_array_offset,
71 constants_array_offset,
72 routine_flags_array_offset,
74 global_flags_array_offset,
75 array_flags_array_offset,
80 abbreviations_offset; /* Glulx */
82 int32 Out_Size, Write_Code_At, Write_Strings_At;
83 int32 RAM_Size, Write_RAM_At; /* Glulx */
85 /* ------------------------------------------------------------------------- */
86 /* Story file header settings. (Written to in "directs.c" and "asm.c".) */
87 /* ------------------------------------------------------------------------- */
89 int release_number, /* Release number game is to have */
90 statusline_flag; /* Either TIME_STYLE or SCORE_STYLE */
92 int serial_code_given_in_program /* If TRUE, a Serial directive has */
93 = FALSE; /* specified this 6-digit serial code */
94 char serial_code_buffer[7]; /* (overriding the usual date-stamp) */
95 int flags2_requirements[16]; /* An array of which bits in Flags 2 of
96 the header will need to be set:
97 e.g. if the save_undo / restore_undo
98 opcodes are ever assembled, we have
99 to set the "games want UNDO" bit.
100 Values are 0 or 1. */
102 /* ------------------------------------------------------------------------- */
103 /* Construct story/module file (up to code area start). */
105 /* (To understand what follows, you really need to look at the run-time */
106 /* system's specification, the Z-Machine Standards document.) */
107 /* ------------------------------------------------------------------------- */
109 extern void write_serial_number(char *buffer)
111 /* Note that this function may require modification for "ANSI" compilers
112 which do not provide the standard time functions: what is needed is
113 the ability to work out today's date */
115 time_t tt; tt=time(0);
116 if (serial_code_given_in_program)
117 strcpy(buffer, serial_code_buffer);
119 #ifdef TIME_UNAVAILABLE
120 sprintf(buffer,"970000");
122 strftime(buffer,10,"%y%m%d",localtime(&tt));
126 static void percentage(char *name, int32 x, int32 total)
127 { printf(" %-20s %2d.%d%%\n",name,x*100/total,(x*1000/total)%10);
130 static char *version_name(int v)
134 { case 3: return "Standard";
135 case 4: return "Plus";
136 case 5: return "Advanced";
137 case 6: return "Graphical";
138 case 8: return "Extended";
140 return "experimental format";
147 static int32 rough_size_of_paged_memory_z(void)
149 /* This function calculates a modest over-estimate of the amount of
150 memory required to store the Z-machine's paged memory area
151 (that is, everything up to the start of the code area). */
157 total = 64 /* header */
158 + 2 + subtract_pointers(low_strings_top, low_strings)
159 /* low strings pool */
160 + 6*32; /* abbreviations table */
162 total += 8; /* header extension table */
163 if (ZCODE_HEADER_EXT_WORDS>3) total += (ZCODE_HEADER_EXT_WORDS-3)*2;
165 if (alphabet_modified) total += 78; /* character set table */
167 if (zscii_defn_modified) /* Unicode translation table */
168 total += 2 + 2*zscii_high_water_mark;
170 total += 2*((version_number==3)?31:63) /* property default values */
171 + no_objects*((version_number==3)?9:14) /* object tree table */
172 + properties_table_size /* property values of objects */
173 + (no_classes+1)*(module_switch?4:2)
174 /* class object numbers table */
175 + no_symbols*2 /* names of numerous things */
176 + individuals_length /* tables of prop variables */
177 + dynamic_array_area_size; /* variables and arrays */
179 for (i=0; i<no_Inform_verbs; i++)
180 total += 2 + 1 + /* address of grammar table, */
181 /* number of grammar lines */
182 ((grammar_version_number == 1)?
183 (8*Inform_verbs[i].lines):0); /* grammar lines */
185 if (grammar_version_number != 1)
186 total += grammar_lines_top; /* size of grammar lines area */
188 total += 2 + 4*no_adjectives /* adjectives table */
189 + 2*no_actions /* action routines */
190 + 2*no_grammar_token_routines; /* general parsing routines */
192 total += (subtract_pointers(dictionary_top, dictionary)) /* dictionary */
193 + ((module_switch)?30:0); /* module map */
195 total += static_array_area_size; /* static arrays */
197 total += scale_factor*0x100 /* maximum null bytes before code */
198 + 1000; /* fudge factor (in case the above is wrong) */
203 static int32 rough_size_of_paged_memory_g(void)
205 /* This function calculates a modest over-estimate of the amount of
206 memory required to store the machine's paged memory area
207 (that is, everything past the start of RAM). */
213 /* No header for us! */
214 total = 1000; /* bit of a fudge factor */
216 total += dynamic_array_area_size; /* arrays and global variables */
218 total += no_objects * OBJECT_BYTE_LENGTH; /* object tables */
219 total += properties_table_size; /* property tables */
220 total += no_properties * 4; /* property defaults table */
222 total += 4 + no_classes * 4; /* class prototype object numbers */
224 total += 32; /* address/length of the identifier tables */
225 total += no_properties * 4;
226 total += (no_individual_properties-INDIV_PROP_START) * 4;
227 total += (NUM_ATTR_BYTES*8) * 4;
228 total += (no_actions + no_fake_actions) * 4;
229 total += 4 + no_arrays * 4;
231 total += 4 + no_Inform_verbs * 4; /* index of grammar tables */
232 total += grammar_lines_top; /* grammar tables */
234 total += 4 + no_actions * 4; /* actions functions table */
237 total += subtract_pointers(dictionary_top, dictionary);
239 while (total % GPAGESIZE)
245 static void construct_storyfile_z(void)
247 int32 i, j, k, l, mark, objs, strings_length, code_length,
248 limit=0, excess=0, extend_offset=0, headerext_length=0;
249 int32 globals_at=0, link_table_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
250 abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
251 map_of_module=0, grammar_table_at=0, charset_at=0, headerext_at=0,
252 terminating_chars_at=0, unicode_at=0, id_names_length=0,
254 int skip_backpatching = FALSE;
255 char *output_called = (module_switch)?"module":"story file";
259 individual_name_strings =
260 my_calloc(sizeof(int32), no_individual_properties,
261 "identifier name strings");
262 action_name_strings =
263 my_calloc(sizeof(int32), no_actions + no_fake_actions,
264 "action name strings");
265 attribute_name_strings =
266 my_calloc(sizeof(int32), 48,
267 "attribute name strings");
269 my_calloc(sizeof(int32),
271 "array name strings");
273 write_the_identifier_names();
275 /* We now know how large the buffer to hold our construction has to be */
277 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_z(),
280 /* Foolish code to make this routine compile on all ANSI compilers */
282 p = (uchar *) zmachine_paged_memory;
284 /* In what follows, the "mark" will move upwards in memory: at various
285 points its value will be recorded for milestones like
286 "dictionary table start". It begins at 0x40, just after the header */
290 /* ----------------- Low Strings and Abbreviations -------------------- */
292 p[mark]=0x80; p[mark+1]=0; mark+=2; /* Start the low strings pool
293 with a useful default string, " " */
295 for (i=0; i+low_strings<low_strings_top; mark++, i++) /* Low strings pool */
296 p[0x42+i]=low_strings[i];
299 for (i=0; i<3*32; i++) /* Initially all 96 entries */
300 { p[mark++]=0; p[mark++]=0x20; /* are set to " " */
302 for (i=0; i<no_abbreviations; i++) /* Write any abbreviations */
303 { j=abbrev_values[i]; /* into banks 2 and 3 */
304 p[abbrevs_at+64+2*i]=j/256; /* (bank 1 is reserved for */
305 p[abbrevs_at+65+2*i]=j%256; /* "variable strings") */
308 /* ------------------- Header extension table ------------------------- */
311 headerext_length = ZCODE_HEADER_EXT_WORDS;
312 if (zscii_defn_modified) {
313 /* Need at least 3 words for unicode table address */
314 if (headerext_length < 3)
315 headerext_length = 3;
317 if (ZCODE_HEADER_FLAGS_3) {
318 /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
319 if (headerext_length < 4)
320 headerext_length = 4;
322 p[mark++] = 0; p[mark++] = headerext_length;
323 for (i=0; i<headerext_length; i++)
324 { p[mark++] = 0; p[mark++] = 0;
327 /* -------------------- Z-character set table ------------------------- */
329 if (alphabet_modified)
331 for (i=0;i<3;i++) for (j=0;j<26;j++)
332 { if (alphabet[i][j] == '~') p[mark++] = '\"';
333 else p[mark++] = alphabet[i][j];
337 /* ------------------ Unicode translation table ----------------------- */
340 if (zscii_defn_modified)
342 p[mark++] = zscii_high_water_mark;
343 for (i=0;i<zscii_high_water_mark;i++)
344 { j = zscii_to_unicode(155 + i);
345 if (j < 0 || j > 0xFFFF) {
346 error("Z-machine Unicode translation table cannot contain characters beyond $FFFF.");
348 p[mark++] = j/256; p[mark++] = j%256;
352 /* -------------------- Objects and Properties ------------------------ */
354 /* The object table must be word-aligned. The Z-machine spec does not
355 require this, but the RA__Pr() veneer routine does. See
356 http://inform7.com/mantis/view.php?id=1712.
358 while ((mark%2) != 0) p[mark++]=0;
360 prop_defaults_at = mark;
362 p[mark++]=0; p[mark++]=0;
364 for (i=2; i< ((version_number==3)?32:64); i++)
365 { p[mark++]=prop_default_value[i]/256;
366 p[mark++]=prop_default_value[i]%256;
369 object_tree_at = mark;
371 mark += ((version_number==3)?9:14)*no_objects;
373 object_props_at = mark;
375 for (i=0; i<properties_table_size; i++)
376 p[mark+i]=properties_table[i];
378 for (i=0, objs=object_tree_at; i<no_objects; i++)
380 if (version_number == 3)
381 { p[objs]=objectsz[i].atts[0];
382 p[objs+1]=objectsz[i].atts[1];
383 p[objs+2]=objectsz[i].atts[2];
384 p[objs+3]=objectsz[i].atts[3];
385 p[objs+4]=objectsz[i].parent;
386 p[objs+5]=objectsz[i].next;
387 p[objs+6]=objectsz[i].child;
393 { p[objs]=objectsz[i].atts[0];
394 p[objs+1]=objectsz[i].atts[1];
395 p[objs+2]=objectsz[i].atts[2];
396 p[objs+3]=objectsz[i].atts[3];
397 p[objs+4]=objectsz[i].atts[4];
398 p[objs+5]=objectsz[i].atts[5];
399 p[objs+6]=(objectsz[i].parent)/256;
400 p[objs+7]=(objectsz[i].parent)%256;
401 p[objs+8]=(objectsz[i].next)/256;
402 p[objs+9]=(objectsz[i].next)%256;
403 p[objs+10]=(objectsz[i].child)/256;
404 p[objs+11]=(objectsz[i].child)%256;
406 { p[objs+12]=mark/256;
410 { p[objs+12]=objectsz[i].propsize/256;
411 p[objs+13]=objectsz[i].propsize%256;
415 mark+=objectsz[i].propsize;
418 /* ----------- Table of Class Prototype Object Numbers ---------------- */
420 class_numbers_offset = mark;
421 for (i=0; i<no_classes; i++)
422 { p[mark++] = class_object_numbers[i]/256;
423 p[mark++] = class_object_numbers[i]%256;
425 { p[mark++] = class_begins_at[i]/256;
426 p[mark++] = class_begins_at[i]%256;
432 /* ------------------- Table of Identifier Names ---------------------- */
434 identifier_names_offset = mark;
437 { p[mark++] = no_individual_properties/256;
438 p[mark++] = no_individual_properties%256;
439 for (i=1; i<no_individual_properties; i++)
440 { p[mark++] = individual_name_strings[i]/256;
441 p[mark++] = individual_name_strings[i]%256;
444 attribute_names_offset = mark;
446 { p[mark++] = attribute_name_strings[i]/256;
447 p[mark++] = attribute_name_strings[i]%256;
450 action_names_offset = mark;
451 fake_action_names_offset = mark + 2*no_actions;
452 for (i=0; i<no_actions + no_fake_actions; i++)
453 { p[mark++] = action_name_strings[i]/256;
454 p[mark++] = action_name_strings[i]%256;
457 array_names_offset = mark;
458 global_names_offset = mark + 2*no_arrays;
459 routine_names_offset = global_names_offset + 2*no_globals;
460 constant_names_offset = routine_names_offset + 2*no_named_routines;
461 for (i=0; i<no_arrays + no_globals
462 + no_named_routines + no_named_constants; i++)
463 { if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
464 p[mark++] = array_name_strings[i]/256;
465 p[mark++] = array_name_strings[i]%256;
468 id_names_length = (mark - identifier_names_offset)/2;
470 routine_flags_array_offset = mark;
472 if (define_INFIX_switch)
473 { for (i=0, k=1, l=0; i<no_named_routines; i++)
474 { if (sflags[named_routine_symbols[i]] & STAR_SFLAG) l=l+k;
476 if (k==256) { p[mark++] = l; k=1; l=0; }
478 if (k!=1) p[mark++]=l;
481 /* ---------------- Table of Indiv Property Values -------------------- */
483 individuals_offset = mark;
484 for (i=0; i<individuals_length; i++)
485 p[mark++] = individuals_table[i];
487 /* ----------------- Variables and Dynamic Arrays --------------------- */
491 for (i=0; i<dynamic_array_area_size; i++)
492 p[mark++] = dynamic_array_area[i];
494 for (i=0; i<240; i++)
495 { j=global_initial_value[i];
496 p[globals_at+i*2] = j/256; p[globals_at+i*2+1] = j%256;
499 /* ------------------ Terminating Characters Table -------------------- */
501 if (version_number >= 5)
502 { terminating_chars_at = mark;
503 for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
507 /* ------------------------ Grammar Table ----------------------------- */
509 if (grammar_version_number > 2)
510 { warning("This version of Inform is unable to produce the grammar \
511 table format requested (producing number 2 format instead)");
512 grammar_version_number = 2;
515 grammar_table_at = mark;
517 mark = mark + no_Inform_verbs*2;
519 for (i=0; i<no_Inform_verbs; i++)
520 { p[grammar_table_at + i*2] = (mark/256);
521 p[grammar_table_at + i*2 + 1] = (mark%256);
522 p[mark++] = Inform_verbs[i].lines;
523 for (j=0; j<Inform_verbs[i].lines; j++)
524 { k = Inform_verbs[i].l[j];
525 if (grammar_version_number == 1)
527 p[mark+7] = grammar_lines[k+1];
528 for (m=1;m<=6;m++) p[mark + m] = 0;
529 k = k + 2; m = 1; n = 0;
530 while ((grammar_lines[k] != 15) && (m<=6))
531 { p[mark + m] = grammar_lines[k];
532 if (grammar_lines[k] < 180) n++;
540 p[mark++] = grammar_lines[k++];
541 p[mark++] = grammar_lines[k++];
543 { tok = grammar_lines[k++];
545 if (tok == 15) break;
546 p[mark++] = grammar_lines[k++];
547 p[mark++] = grammar_lines[k++];
553 /* ------------------- Actions and Preactions ------------------------- */
554 /* (The term "preactions" is traditional: Inform uses the preactions */
555 /* table for a different purpose than Infocom used to.) */
556 /* The values are written later, when the Z-code offset is known. */
557 /* -------------------------------------------------------------------- */
560 mark += no_actions*2;
562 preactions_at = mark;
563 if (grammar_version_number == 1)
564 mark += no_grammar_token_routines*2;
566 /* ----------------------- Adjectives Table --------------------------- */
568 if (grammar_version_number == 1)
569 { p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
570 adjectives_offset = mark;
571 dictionary_offset = mark + 4*no_adjectives;
573 for (i=0; i<no_adjectives; i++)
574 { j = final_dict_order[adjectives[no_adjectives-i-1]]
575 *((version_number==3)?7:9)
576 + dictionary_offset + 7;
577 p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
578 p[mark++]=(256-no_adjectives+i);
582 { p[mark]=0; p[mark+1]=0; mark+=2;
583 adjectives_offset = mark;
584 dictionary_offset = mark;
587 /* ------------------------- Dictionary ------------------------------- */
591 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
592 dictionary[2]=','; /* force words apart */
595 dictionary[4]=(version_number==3)?7:9; /* Length of each entry */
596 dictionary[5]=(dict_entries/256); /* Number of entries */
597 dictionary[6]=(dict_entries%256);
599 for (i=0; i<7; i++) p[mark++] = dictionary[i];
601 for (i=0; i<dict_entries; i++)
602 { k = 7 + i*((version_number==3)?7:9);
603 j = mark + final_dict_order[i]*((version_number==3)?7:9);
604 for (l = 0; l<((version_number==3)?7:9); l++)
605 p[j++] = dictionary[k++];
607 mark += dict_entries * ((version_number==3)?7:9);
609 /* ------------------------- Module Map ------------------------------- */
612 { map_of_module = mark; /* Filled in below */
616 /* ------------------------ Static Arrays ----------------------------- */
618 static_arrays_at = mark;
619 for (i=0; i<static_array_area_size; i++)
620 p[mark++] = static_array_area[i];
622 /* ----------------- A gap before the code area ----------------------- */
623 /* (so that it will start at an exact packed address and so that all */
624 /* routine packed addresses are >= 256, hence long constants) */
625 /* -------------------------------------------------------------------- */
627 while ((mark%length_scale_factor) != 0) p[mark++]=0;
628 while (mark < (scale_factor*0x100)) p[mark++]=0;
629 if (oddeven_packing_switch)
630 while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
633 { error("This program has overflowed the maximum readable-memory \
634 size of the Z-machine format. See the memory map below: the start \
635 of the area marked \"above readable memory\" must be brought down to $FFFE \
637 memory_map_switch = TRUE;
638 /* Backpatching the grammar tables requires us to trust some of the */
639 /* addresses we've written into Z-machine memory, but they may have */
640 /* been truncated to 16 bits, so we can't do it. */
641 skip_backpatching = TRUE;
644 /* -------------------------- Code Area ------------------------------- */
645 /* (From this point on we don't write any more into the "p" buffer.) */
646 /* -------------------------------------------------------------------- */
648 Write_Code_At = mark;
649 if (!OMIT_UNUSED_ROUTINES) {
650 code_length = zmachine_pc;
653 if (zmachine_pc != df_total_size_before_stripping)
654 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
655 code_length = df_total_size_after_stripping;
659 /* ------------------ Another synchronising gap ----------------------- */
661 if (oddeven_packing_switch)
663 while ((mark%(scale_factor*2)) != 0) mark++;
665 while ((mark%(scale_factor*2)) != scale_factor) mark++;
668 while ((mark%scale_factor) != 0) mark++;
670 /* ------------------------- Strings Area ----------------------------- */
672 Write_Strings_At = mark;
673 strings_length = static_strings_extent;
674 mark += strings_length;
676 /* --------------------- Module Linking Data -------------------------- */
679 { link_table_at = mark; mark += link_data_size;
680 mark += zcode_backpatch_size;
681 mark += zmachine_backpatch_size;
684 /* --------------------- Is the file too big? ------------------------- */
688 switch(version_number)
689 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
691 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
694 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
698 { excess = Out_Size-((int32) 0x10000L); limit=64;
702 { char memory_full_error[80];
703 sprintf(memory_full_error,
704 "The %s exceeds version-%d limit (%dK) by %d bytes",
705 output_called, version_number, limit, excess);
706 fatalerror(memory_full_error);
709 /* --------------------------- Offsets -------------------------------- */
711 dictionary_offset = dictionary_at;
712 variables_offset = globals_at;
713 actions_offset = actions_at;
714 preactions_offset = preactions_at;
715 prop_defaults_offset = prop_defaults_at;
716 prop_values_offset = object_props_at;
717 static_memory_offset = grammar_table_at;
718 grammar_table_offset = grammar_table_at;
719 static_arrays_offset = static_arrays_at;
721 if (extend_memory_map)
723 if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
724 while ((extend_offset%length_scale_factor) != 0) extend_offset++;
725 /* Not sure why above line is necessary, but oddeven_packing
726 * will need extend_offset to be even */
727 code_offset = extend_offset*scale_factor;
728 if (oddeven_packing_switch)
729 strings_offset = code_offset + scale_factor;
731 strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
733 /* With the extended memory model, need to specifically check that we
734 * haven't overflowed the packed address range for routines or strings.
735 * With the standard memory model, we only need the earlier total size
738 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
740 { char code_full_error[80];
741 sprintf(code_full_error,
742 "The code area limit has been exceeded by %d bytes",
744 fatalerror(code_full_error);
747 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
749 { char strings_full_error[140];
750 if (oddeven_packing_switch)
751 sprintf(strings_full_error,
752 "The strings area limit has been exceeded by %d bytes",
755 sprintf(strings_full_error,
756 "The code+strings area limit has been exceeded by %d bytes. \
757 Try running Inform again with -B on the command line.",
759 fatalerror(strings_full_error);
763 { code_offset = Write_Code_At;
764 strings_offset = Write_Strings_At;
767 /* --------------------------- The Header ----------------------------- */
769 for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */
771 p[0] = version_number; /* Version number */
772 p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */
773 p[2] = (release_number/256);
774 p[3] = (release_number%256); /* Release */
775 p[4] = (Write_Code_At/256);
776 p[5] = (Write_Code_At%256); /* End of paged memory */
777 if (version_number==6)
778 { j=code_offset/scale_factor; /* Packed address of "Main__" */
779 p[6]=(j/256); p[7]=(j%256);
782 { j=Write_Code_At+1; /* Initial PC value (bytes) */
783 p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */
785 p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */
786 p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */
787 p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */
788 p[14]=(grammar_table_at/256);
789 p[15]=(grammar_table_at%256); /* Grammar */
790 for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */
791 j+=k*flags2_requirements[i]; /* unusual opcodes assembled */
792 p[16]=j/256; p[17]=j%256;
793 write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
794 p[24]=abbrevs_at/256;
795 p[25]=abbrevs_at%256; /* Abbreviations table */
796 p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */
797 p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */
799 if (extend_memory_map)
800 { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
801 p[40]=j/256; p[41]=j%256; /* Routines offset */
802 if (oddeven_packing_switch)
803 j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
804 p[42]=j/256; p[43]=j%256; /* = Strings offset */
807 if (version_number >= 5)
808 { p[46] = terminating_chars_at/256; /* Terminating characters table */
809 p[47] = terminating_chars_at%256;
812 if (alphabet_modified)
814 p[52]=j/256; p[53]=j%256; } /* Character set table address */
817 p[54] = j/256; p[55] = j%256; /* Header extension table address */
819 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
821 p[62] = '0' + ((RELEASE_NUMBER/10)%10);
822 p[63] = '0' + RELEASE_NUMBER%10;
824 /* ------------------------ Header Extension -------------------------- */
826 /* The numbering in the spec is a little weird -- it's headerext_length
827 words *after* the initial length word. We follow the spec numbering
828 in this switch statement, so the count is 1-based. */
829 for (i=1; i<=headerext_length; i++) {
832 j = unicode_at; /* Unicode translation table address */
835 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
841 p[headerext_at+2*i+0] = j / 256;
842 p[headerext_at+2*i+1] = j % 256;
845 /* ----------------- The Header: Extras for modules ------------------- */
849 p[1]=MODULE_VERSION_NUMBER;
850 p[6]=map_of_module/256;
851 p[7]=map_of_module%256;
853 mark = map_of_module; /* Module map format: */
855 p[mark++]=object_tree_at/256; /* 0: Object tree addr */
856 p[mark++]=object_tree_at%256;
857 p[mark++]=object_props_at/256; /* 2: Prop values addr */
858 p[mark++]=object_props_at%256;
859 p[mark++]=(Write_Strings_At/scale_factor)/256; /* 4: Static strs */
860 p[mark++]=(Write_Strings_At/scale_factor)%256;
861 p[mark++]=class_numbers_offset/256; /* 6: Class nos addr */
862 p[mark++]=class_numbers_offset%256;
863 p[mark++]=individuals_offset/256; /* 8: Indiv prop values */
864 p[mark++]=individuals_offset%256;
865 p[mark++]=individuals_length/256; /* 10: Length of table */
866 p[mark++]=individuals_length%256;
867 p[mark++]=no_symbols/256; /* 12: No of symbols */
868 p[mark++]=no_symbols%256;
869 p[mark++]=no_individual_properties/256; /* 14: Max property no */
870 p[mark++]=no_individual_properties%256;
871 p[mark++]=no_objects/256; /* 16: No of objects */
872 p[mark++]=no_objects%256;
874 p[mark++]=i/256; /* 18: Import/exports */
876 p[mark++]=link_data_size/256; /* 20: Size of */
877 p[mark++]=link_data_size%256;
879 p[mark++]=i/256; /* 22: Code backpatch */
881 p[mark++]=zcode_backpatch_size/256; /* 24: Size of */
882 p[mark++]=zcode_backpatch_size%256;
883 i += zcode_backpatch_size;
884 p[mark++]=i/256; /* 26: Image backpatch */
886 p[mark++]=zmachine_backpatch_size/256; /* 28: Size of */
887 p[mark++]=zmachine_backpatch_size%256;
889 /* Further space in this table is reserved for future use */
892 /* ---- Backpatch the Z-machine, now that all information is in ------- */
894 if (!module_switch && !skip_backpatching)
895 { backpatch_zmachine_image_z();
896 for (i=1; i<id_names_length; i++)
897 { int32 v = 256*p[identifier_names_offset + i*2]
898 + p[identifier_names_offset + i*2 + 1];
899 if (v!=0) v += strings_offset/scale_factor;
900 p[identifier_names_offset + i*2] = v/256;
901 p[identifier_names_offset + i*2 + 1] = v%256;
905 for (i=0; i<no_actions; i++)
906 { j=action_byte_offset[i];
907 if (OMIT_UNUSED_ROUTINES)
908 j = df_stripped_address_for_address(j);
909 j += code_offset/scale_factor;
910 p[mark++]=j/256; p[mark++]=j%256;
913 if (grammar_version_number == 1)
914 { mark = preactions_at;
915 for (i=0; i<no_grammar_token_routines; i++)
916 { j=grammar_token_routine[i];
917 if (OMIT_UNUSED_ROUTINES)
918 j = df_stripped_address_for_address(j);
919 j += code_offset/scale_factor;
920 p[mark++]=j/256; p[mark++]=j%256;
924 { for (l = 0; l<no_Inform_verbs; l++)
925 { k = grammar_table_at + 2*l;
926 i = p[k]*256 + p[k+1];
927 for (j = p[i++]; j>0; j--)
928 { int topbits; int32 value;
931 { topbits = (p[i]/0x40) & 3;
932 value = p[i+1]*256 + p[i+2];
935 value = final_dict_order[value]
936 *((version_number==3)?7:9)
937 + dictionary_offset + 7;
940 if (OMIT_UNUSED_ROUTINES)
941 value = df_stripped_address_for_address(value);
942 value += code_offset/scale_factor;
945 p[i+1] = value/256; p[i+2] = value%256;
954 /* ---- From here on, it's all reportage: construction is finished ---- */
956 if (statistics_switch)
957 { int32 k_long, rate; char *k_str="";
958 k_long=(Out_Size/1024);
959 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
960 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
961 if (total_bytes_trans == 0) rate = 0;
962 else rate=total_bytes_trans*1000/total_chars_trans;
965 %3d source code files %6d syntactic lines\n\
966 %6d textual lines %8ld characters ",
967 total_input_files, no_syntax_lines,
968 total_source_line_count, (long int) total_chars_read);
969 if (character_set_unicode) printf("(UTF-8)\n");
970 else if (character_set_setting == 0) printf("(plain ASCII)\n");
972 { printf("(ISO 8859-%d %s)\n", character_set_setting,
973 name_of_iso_set(character_set_setting));
976 printf("Allocated:\n\
977 %6d symbols (maximum %4d) %8ld bytes of memory\n\
978 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
979 no_symbols, MAX_SYMBOLS,
980 (long int) malloced_bytes,
982 version_name(version_number),
984 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
985 (long int) k_long, k_str);
988 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
989 %6d global vars (maximum 233) %6d variable/array space (maximum %d)\n",
990 no_classes, MAX_CLASSES,
991 no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)),
993 dynamic_array_area_size, MAX_STATIC_DATA);
996 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
997 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
998 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
999 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
1000 no_Inform_verbs, MAX_VERBS,
1001 dict_entries, MAX_DICT_ENTRIES,
1002 no_grammar_lines, grammar_version_number,
1004 no_actions, MAX_ACTIONS,
1005 no_attributes, ((version_number==3)?32:48),
1006 no_properties-2, ((version_number==3)?30:62),
1007 no_individual_properties - 64);
1009 if (track_unused_routines)
1011 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1013 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
1014 (long int) df_total_size_before_stripping, (long int) diff,
1015 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1016 100 * (float)diff / (float)df_total_size_before_stripping);
1020 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1021 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1022 %6ld instructions of Z-code %6d sequence points\n\
1023 %6ld bytes readable memory used (maximum 65536)\n\
1024 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
1025 (long int) total_chars_trans,
1026 (long int) total_bytes_trans,
1027 (total_chars_trans>total_bytes_trans)?0:1,
1029 no_abbreviations, MAX_ABBREVS,
1031 (long int) no_instructions, no_sequence_points,
1032 (long int) Write_Code_At,
1033 (long int) Out_Size,
1035 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1043 "\nOffsets in %s:\n\
1044 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1045 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1046 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1048 (long int) abbrevs_at,
1049 (long int) prop_defaults_at,
1050 (long int) object_tree_at,
1051 (long int) object_props_at,
1052 (long int) globals_at,
1053 (long int) grammar_table_at,
1054 (long int) actions_at,
1055 (long int) preactions_at,
1056 (long int) adjectives_offset,
1057 (long int) dictionary_at,
1058 (long int) Write_Code_At,
1059 (long int) Write_Strings_At);
1061 printf("%05lx Linking data\n",(long int) link_table_at);
1065 if (debugfile_switch)
1066 { begin_writing_debug_sections();
1067 write_debug_section("abbreviations", 64);
1068 write_debug_section("abbreviations table", abbrevs_at);
1069 write_debug_section("header extension", headerext_at);
1070 if (alphabet_modified)
1071 { write_debug_section("alphabets table", charset_at);
1073 if (zscii_defn_modified)
1074 { write_debug_section("Unicode table", unicode_at);
1076 write_debug_section("property defaults", prop_defaults_at);
1077 write_debug_section("object tree", object_tree_at);
1078 write_debug_section("common properties", object_props_at);
1079 write_debug_section("class numbers", class_numbers_offset);
1080 write_debug_section("identifier names", identifier_names_offset);
1081 write_debug_section("individual properties", individuals_offset);
1082 write_debug_section("global variables", globals_at);
1083 write_debug_section("array space", globals_at+480);
1084 write_debug_section("grammar table", grammar_table_at);
1085 write_debug_section("actions table", actions_at);
1086 write_debug_section("parsing routines", preactions_at);
1087 write_debug_section("adjectives table", adjectives_offset);
1088 write_debug_section("dictionary", dictionary_at);
1089 write_debug_section("code area", Write_Code_At);
1090 write_debug_section("strings area", Write_Strings_At);
1091 end_writing_debug_sections(Out_Size);
1094 if (memory_map_switch)
1097 printf("Dynamic +---------------------+ 00000\n");
1098 printf("memory | header |\n");
1099 printf(" +---------------------+ 00040\n");
1100 printf(" | abbreviations |\n");
1101 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at);
1102 printf(" | abbreviations table |\n");
1103 printf(" +---------------------+ %05lx\n", (long int) headerext_at);
1104 printf(" | header extension |\n");
1105 if (alphabet_modified)
1107 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at);
1108 printf(" | alphabets table |\n");
1110 if (zscii_defn_modified)
1112 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at);
1113 printf(" | Unicode table |\n");
1115 printf(" +---------------------+ %05lx\n",
1116 (long int) prop_defaults_at);
1117 printf(" | property defaults |\n");
1118 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at);
1119 printf(" | objects |\n");
1120 printf(" + - - - - - - - - - - + %05lx\n",
1121 (long int) object_props_at);
1122 printf(" | object short names, |\n");
1123 printf(" | common prop values |\n");
1124 printf(" + - - - - - - - - - - + %05lx\n",
1125 (long int) class_numbers_offset);
1126 printf(" | class numbers table |\n");
1127 printf(" + - - - - - - - - - - + %05lx\n",
1128 (long int) identifier_names_offset);
1129 printf(" | symbol names table |\n");
1130 printf(" + - - - - - - - - - - + %05lx\n",
1131 (long int) individuals_offset);
1132 printf(" | indiv prop values |\n");
1133 printf(" +---------------------+ %05lx\n", (long int) globals_at);
1134 printf(" | global variables |\n");
1135 printf(" + - - - - - - - - - - + %05lx\n",
1136 ((long int) globals_at)+480L);
1137 printf(" | arrays |\n");
1138 printf(" +=====================+ %05lx\n",
1139 (long int) grammar_table_at);
1140 printf("Readable| grammar table |\n");
1141 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at);
1142 printf(" | actions |\n");
1143 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at);
1144 printf(" | parsing routines |\n");
1145 printf(" + - - - - - - - - - - + %05lx\n",
1146 (long int) adjectives_offset);
1147 printf(" | adjectives |\n");
1148 printf(" +---------------------+ %05lx\n", (long int) dictionary_at);
1149 printf(" | dictionary |\n");
1152 printf(" + - - - - - - - - - - + %05lx\n",
1153 (long int) map_of_module);
1154 printf(" | map of module addrs |\n");
1156 if (static_array_area_size)
1158 printf(" +---------------------+ %05lx\n", (long int) static_arrays_at);
1159 printf(" | static arrays |\n");
1161 printf(" +=====================+ %05lx\n", (long int) Write_Code_At);
1162 printf("Above | Z-code |\n");
1163 printf("readable+---------------------+ %05lx\n",
1164 (long int) Write_Strings_At);
1165 printf("memory | strings |\n");
1168 printf(" +=====================+ %05lx\n", (long int) link_table_at);
1169 printf(" | module linking data |\n");
1171 printf(" +---------------------+ %05lx\n", (long int) Out_Size);
1174 if (percentages_switch)
1175 { printf("Approximate percentage breakdown of %s:\n",
1177 percentage("Z-code", code_length,Out_Size);
1179 percentage("Linking data", link_data_size,Out_Size);
1180 percentage("Static strings", strings_length,Out_Size);
1181 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1182 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1183 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1184 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1185 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1186 percentage("Total of save area", grammar_table_at,Out_Size);
1187 percentage("Total of text", total_bytes_trans,Out_Size);
1189 if (frequencies_switch)
1191 { printf("How frequently abbreviations were used, and roughly\n");
1192 printf("how many bytes they saved: ('_' denotes spaces)\n");
1193 for (i=0; i<no_abbreviations; i++)
1194 { char abbrev_string[MAX_ABBREV_LENGTH];
1195 strcpy(abbrev_string,
1196 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1197 for (j=0; abbrev_string[j]!=0; j++)
1198 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1199 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1200 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1201 if ((i%3)==2) printf("\n");
1203 if ((i%3)!=0) printf("\n");
1204 if (no_abbreviations==0) printf("None were declared.\n");
1209 static void construct_storyfile_g(void)
1211 int32 i, j, k, l, mark, strings_length, limit;
1212 int32 globals_at, dictionary_at, actions_at, preactions_at,
1213 abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1214 grammar_table_at, charset_at, headerext_at,
1215 unicode_at, arrays_at, static_arrays_at;
1216 int32 threespaces, code_length;
1217 char *output_called = (module_switch)?"module":"story file";
1221 individual_name_strings =
1222 my_calloc(sizeof(int32), no_individual_properties,
1223 "identifier name strings");
1224 action_name_strings =
1225 my_calloc(sizeof(int32), no_actions + no_fake_actions,
1226 "action name strings");
1227 attribute_name_strings =
1228 my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1229 "attribute name strings");
1230 array_name_strings =
1231 my_calloc(sizeof(int32),
1233 "array name strings");
1235 write_the_identifier_names();
1236 threespaces = compile_string(" ", FALSE, FALSE);
1238 compress_game_text();
1240 /* We now know how large the buffer to hold our construction has to be */
1242 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1245 /* Foolish code to make this routine compile on all ANSI compilers */
1247 p = (uchar *) zmachine_paged_memory;
1249 /* In what follows, the "mark" will move upwards in memory: at various
1250 points its value will be recorded for milestones like
1251 "dictionary table start". It begins at 0x40, just after the header */
1253 /* Ok, our policy here will be to set the *_at values all relative
1254 to RAM. That's so we can write into zmachine_paged_memory[mark]
1255 and actually hit what we're aiming at.
1256 All the *_offset values will be set to true Glulx machine
1259 /* To get our bearings, figure out where the strings and code are. */
1260 /* We start with two words, which conventionally identify the
1261 memory layout. This is why the code starts eight bytes after
1263 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1264 if (!OMIT_UNUSED_ROUTINES) {
1265 code_length = zmachine_pc;
1268 if (zmachine_pc != df_total_size_before_stripping)
1269 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1270 code_length = df_total_size_after_stripping;
1272 Write_Strings_At = Write_Code_At + code_length;
1273 strings_length = compression_table_size + compression_string_size;
1275 static_arrays_at = Write_Strings_At + strings_length;
1277 /* Now figure out where RAM starts. */
1278 Write_RAM_At = static_arrays_at + static_array_area_size;
1279 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1280 while (Write_RAM_At % GPAGESIZE)
1283 /* Now work out all those RAM positions. */
1286 /* ----------------- Variables and Dynamic Arrays --------------------- */
1289 for (i=0; i<no_globals; i++) {
1290 j = global_initial_value[i];
1291 WriteInt32(p+mark, j);
1296 for (i=MAX_GLOBAL_VARIABLES*4; i<dynamic_array_area_size; i++)
1297 p[mark++] = dynamic_array_area[i];
1299 /* -------------------------- Dynamic Strings -------------------------- */
1302 WriteInt32(p+mark, no_dynamic_strings);
1304 for (i=0; i<no_dynamic_strings; i++) {
1305 j = Write_Strings_At + compressed_offsets[threespaces-1];
1306 WriteInt32(p+mark, j);
1310 /* ---------------- Various Things I'm Not Sure About ------------------ */
1311 /* Actually, none of these are relevant to Glulx. */
1312 headerext_at = mark;
1314 if (alphabet_modified)
1317 if (zscii_defn_modified)
1320 /* -------------------- Objects and Properties ------------------------ */
1322 object_tree_at = mark;
1324 object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1326 for (i=0; i<no_objects; i++) {
1327 int32 objmark = mark;
1328 p[mark++] = 0x70; /* type byte -- object */
1329 for (j=0; j<NUM_ATTR_BYTES; j++) {
1330 p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1332 for (j=0; j<6; j++) {
1335 case 0: /* next object in the linked list. */
1336 if (i == no_objects-1)
1339 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1341 case 1: /* hardware name address */
1342 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1344 case 2: /* property table address */
1345 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1347 case 3: /* parent */
1348 if (objectsg[i].parent == 0)
1351 val = Write_RAM_At + object_tree_at +
1352 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1354 case 4: /* sibling */
1355 if (objectsg[i].next == 0)
1358 val = Write_RAM_At + object_tree_at +
1359 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1362 if (objectsg[i].child == 0)
1365 val = Write_RAM_At + object_tree_at +
1366 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1369 p[mark++] = (val >> 24) & 0xFF;
1370 p[mark++] = (val >> 16) & 0xFF;
1371 p[mark++] = (val >> 8) & 0xFF;
1372 p[mark++] = (val) & 0xFF;
1375 for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1380 if (object_props_at != mark)
1381 error("*** Object table was impossible length ***");
1383 for (i=0; i<properties_table_size; i++)
1384 p[mark+i]=properties_table[i];
1386 for (i=0; i<no_objects; i++) {
1387 int32 tableaddr = object_props_at + objectsg[i].propaddr;
1388 int32 tablelen = ReadInt32(p+tableaddr);
1390 for (j=0; j<tablelen; j++) {
1391 k = ReadInt32(p+tableaddr+4);
1392 k += (Write_RAM_At + object_props_at);
1393 WriteInt32(p+tableaddr+4, k);
1398 mark += properties_table_size;
1400 prop_defaults_at = mark;
1401 for (i=0; i<no_properties; i++) {
1402 k = prop_default_value[i];
1403 WriteInt32(p+mark, k);
1407 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1409 class_numbers_offset = mark;
1410 for (i=0; i<no_classes; i++) {
1411 j = Write_RAM_At + object_tree_at +
1412 (OBJECT_BYTE_LENGTH*(class_object_numbers[i]-1));
1413 WriteInt32(p+mark, j);
1416 WriteInt32(p+mark, 0);
1419 /* -------------------- Table of Property Names ------------------------ */
1421 /* We try to format this bit with some regularity...
1422 address of common properties
1423 number of common properties
1424 address of indiv properties
1425 number of indiv properties (counted from INDIV_PROP_START)
1426 address of attributes
1427 number of attributes (always NUM_ATTR_BYTES*8)
1432 identifier_names_offset = mark;
1433 mark += 32; /* eight pairs of values, to be filled in. */
1435 WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1436 WriteInt32(p+identifier_names_offset+4, no_properties);
1437 for (i=0; i<no_properties; i++) {
1438 j = individual_name_strings[i];
1440 j = Write_Strings_At + compressed_offsets[j-1];
1441 WriteInt32(p+mark, j);
1445 WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1446 WriteInt32(p+identifier_names_offset+12,
1447 no_individual_properties-INDIV_PROP_START);
1448 for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1449 j = individual_name_strings[i];
1451 j = Write_Strings_At + compressed_offsets[j-1];
1452 WriteInt32(p+mark, j);
1456 WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1457 WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1458 for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1459 j = attribute_name_strings[i];
1461 j = Write_Strings_At + compressed_offsets[j-1];
1462 WriteInt32(p+mark, j);
1466 WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1467 WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1468 action_names_offset = mark;
1469 fake_action_names_offset = mark + 4*no_actions;
1470 for (i=0; i<no_actions + no_fake_actions; i++) {
1471 j = action_name_strings[i];
1473 j = Write_Strings_At + compressed_offsets[j-1];
1474 WriteInt32(p+mark, j);
1478 array_names_offset = mark;
1479 WriteInt32(p+mark, no_arrays);
1481 for (i=0; i<no_arrays; i++) {
1482 j = array_name_strings[i];
1484 j = Write_Strings_At + compressed_offsets[j-1];
1485 WriteInt32(p+mark, j);
1489 individuals_offset = mark;
1491 /* ------------------------ Grammar Table ----------------------------- */
1493 if (grammar_version_number != 2)
1494 { warning("This version of Inform is unable to produce the grammar \
1495 table format requested (producing number 2 format instead)");
1496 grammar_version_number = 2;
1499 grammar_table_at = mark;
1501 WriteInt32(p+mark, no_Inform_verbs);
1504 mark += no_Inform_verbs*4;
1506 for (i=0; i<no_Inform_verbs; i++) {
1507 j = mark + Write_RAM_At;
1508 WriteInt32(p+(grammar_table_at+4+i*4), j);
1509 p[mark++] = Inform_verbs[i].lines;
1510 for (j=0; j<Inform_verbs[i].lines; j++) {
1512 k = Inform_verbs[i].l[j];
1513 p[mark++] = grammar_lines[k++];
1514 p[mark++] = grammar_lines[k++];
1515 p[mark++] = grammar_lines[k++];
1517 tok = grammar_lines[k++];
1519 if (tok == 15) break;
1520 p[mark++] = grammar_lines[k++];
1521 p[mark++] = grammar_lines[k++];
1522 p[mark++] = grammar_lines[k++];
1523 p[mark++] = grammar_lines[k++];
1528 /* ------------------- Actions and Preactions ------------------------- */
1531 WriteInt32(p+mark, no_actions);
1533 mark += no_actions*4;
1534 /* Values to be written in later. */
1536 if (DICT_CHAR_SIZE != 1) {
1537 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1542 preactions_at = mark;
1543 adjectives_offset = mark;
1544 dictionary_offset = mark;
1546 /* ------------------------- Dictionary ------------------------------- */
1548 dictionary_at = mark;
1550 WriteInt32(dictionary+0, dict_entries);
1552 p[mark+i] = dictionary[i];
1554 for (i=0; i<dict_entries; i++) {
1555 k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1556 j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1557 for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1558 p[j++] = dictionary[k++];
1560 mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1562 /* -------------------------- All Data -------------------------------- */
1564 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1565 while (mark % GPAGESIZE)
1570 Out_Size = Write_RAM_At + RAM_Size;
1573 /* --------------------------- Offsets -------------------------------- */
1575 dictionary_offset = Write_RAM_At + dictionary_at;
1576 variables_offset = Write_RAM_At + globals_at;
1577 arrays_offset = Write_RAM_At + arrays_at;
1578 actions_offset = Write_RAM_At + actions_at;
1579 preactions_offset = Write_RAM_At + preactions_at;
1580 prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1581 object_tree_offset = Write_RAM_At + object_tree_at;
1582 prop_values_offset = Write_RAM_At + object_props_at;
1583 static_memory_offset = Write_RAM_At + grammar_table_at;
1584 grammar_table_offset = Write_RAM_At + grammar_table_at;
1585 abbreviations_offset = Write_RAM_At + abbrevs_at;
1587 code_offset = Write_Code_At;
1588 strings_offset = Write_Strings_At;
1589 static_arrays_offset = static_arrays_at;
1591 /* --------------------------- The Header ----------------------------- */
1593 /* ------ Backpatch the machine, now that all information is in ------- */
1596 { backpatch_zmachine_image_g();
1598 mark = actions_at + 4;
1599 for (i=0; i<no_actions; i++) {
1600 j = action_byte_offset[i];
1601 if (OMIT_UNUSED_ROUTINES)
1602 j = df_stripped_address_for_address(j);
1604 WriteInt32(p+mark, j);
1608 for (l = 0; l<no_Inform_verbs; l++) {
1609 k = grammar_table_at + 4 + 4*l;
1610 i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1612 for (j = p[i++]; j>0; j--) {
1616 while (p[i] != 15) {
1617 topbits = (p[i]/0x40) & 3;
1618 value = ((p[i+1] << 24) | (p[i+2] << 16)
1619 | (p[i+3] << 8) | (p[i+4]));
1622 value = dictionary_offset + 4
1623 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1626 if (OMIT_UNUSED_ROUTINES)
1627 value = df_stripped_address_for_address(value);
1628 value += code_offset;
1631 WriteInt32(p+(i+1), value);
1640 /* ---- From here on, it's all reportage: construction is finished ---- */
1642 if (statistics_switch)
1643 { int32 k_long, rate; char *k_str="";
1644 k_long=(Out_Size/1024);
1645 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1646 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1647 if (strings_length == 0) rate = 0;
1648 else rate=strings_length*1000/total_chars_trans;
1651 %3d source code files %6d syntactic lines\n\
1652 %6d textual lines %8ld characters ",
1653 total_input_files, no_syntax_lines,
1654 total_source_line_count, (long int) total_chars_read);
1655 if (character_set_unicode) printf("(UTF-8)\n");
1656 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1658 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1659 name_of_iso_set(character_set_setting));
1663 write_serial_number(serialnum);
1664 printf("Allocated:\n\
1665 %6d symbols (maximum %4d) %8ld bytes of memory\n\
1666 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1667 no_symbols, MAX_SYMBOLS,
1668 (long int) malloced_bytes,
1669 version_name(version_number),
1672 serialnum[0], serialnum[1], serialnum[2],
1673 serialnum[3], serialnum[4], serialnum[5],
1674 (long int) k_long, k_str);
1678 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
1679 %6d global vars (maximum %3d) %6d variable/array space (maximum %d)\n",
1680 no_classes, MAX_CLASSES,
1681 no_objects, MAX_OBJECTS,
1682 no_globals, MAX_GLOBAL_VARIABLES,
1683 dynamic_array_area_size, MAX_STATIC_DATA);
1686 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
1687 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1688 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
1689 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1690 no_Inform_verbs, MAX_VERBS,
1691 dict_entries, MAX_DICT_ENTRIES,
1692 no_grammar_lines, grammar_version_number,
1694 no_actions, MAX_ACTIONS,
1695 no_attributes, NUM_ATTR_BYTES*8,
1696 no_properties, INDIV_PROP_START,
1697 no_individual_properties - INDIV_PROP_START);
1699 if (track_unused_routines)
1701 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1703 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1704 (long int) df_total_size_before_stripping, (long int) diff,
1705 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1706 100 * (float)diff / (float)df_total_size_before_stripping);
1710 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1711 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1712 %6ld instructions of code %6d sequence points\n\
1713 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1714 %6ld bytes used in machine %10ld bytes free in machine\n",
1715 (long int) total_chars_trans,
1716 (long int) strings_length,
1717 (total_chars_trans>strings_length)?0:1,
1719 no_abbreviations, MAX_ABBREVS,
1721 (long int) no_instructions, no_sequence_points,
1722 (long int) (Out_Size - Write_RAM_At),
1723 (long int) Write_RAM_At,
1724 (long int) Out_Size,
1726 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1734 "\nOffsets in %s:\n\
1735 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1736 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1737 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1739 (long int) abbrevs_at,
1740 (long int) prop_defaults_at,
1741 (long int) object_tree_at,
1742 (long int) object_props_at,
1743 (long int) globals_at,
1744 (long int) grammar_table_at,
1745 (long int) actions_at,
1746 (long int) preactions_at,
1747 (long int) adjectives_offset,
1748 (long int) dictionary_at,
1749 (long int) Write_Code_At,
1750 (long int) Write_Strings_At);
1754 if (debugfile_switch)
1755 { begin_writing_debug_sections();
1756 write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1757 write_debug_section("code area", Write_Code_At);
1758 write_debug_section("string decoding table", Write_Strings_At);
1759 write_debug_section("strings area",
1760 Write_Strings_At + compression_table_size);
1761 write_debug_section("static array space", static_arrays_at);
1762 if (static_arrays_at + static_array_area_size < Write_RAM_At)
1763 { write_debug_section
1764 ("zero padding", static_arrays_at + static_array_area_size);
1767 { compiler_error("Failed assumption that globals are at start of "
1770 write_debug_section("global variables", Write_RAM_At + globals_at);
1771 write_debug_section("array space", Write_RAM_At + arrays_at);
1772 write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1773 write_debug_section("object tree", Write_RAM_At + object_tree_at);
1774 write_debug_section("common properties",
1775 Write_RAM_At + object_props_at);
1776 write_debug_section("property defaults",
1777 Write_RAM_At + prop_defaults_at);
1778 write_debug_section("class numbers",
1779 Write_RAM_At + class_numbers_offset);
1780 write_debug_section("identifier names",
1781 Write_RAM_At + identifier_names_offset);
1782 write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1783 write_debug_section("actions table", Write_RAM_At + actions_at);
1784 write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1785 if (MEMORY_MAP_EXTENSION)
1786 { write_debug_section("zero padding", Out_Size);
1788 end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1791 if (memory_map_switch)
1795 printf(" +---------------------+ 000000\n");
1796 printf("Read- | header |\n");
1797 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE);
1798 printf("memory | memory layout id |\n");
1799 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At);
1800 printf(" | code |\n");
1801 printf(" +---------------------+ %06lx\n",
1802 (long int) Write_Strings_At);
1803 printf(" | string decode table |\n");
1804 printf(" + - - - - - - - - - - + %06lx\n",
1805 (long int) Write_Strings_At + compression_table_size);
1806 printf(" | strings |\n");
1807 if (static_array_area_size)
1809 printf(" +---------------------+ %06lx\n",
1810 (long int) (static_arrays_at));
1811 printf(" | static arrays |\n");
1813 printf(" +=====================+ %06lx\n",
1814 (long int) (Write_RAM_At+globals_at));
1815 printf("Dynamic | global variables |\n");
1816 printf("memory + - - - - - - - - - - + %06lx\n",
1817 (long int) (Write_RAM_At+arrays_at));
1818 printf(" | arrays |\n");
1819 printf(" +---------------------+ %06lx\n",
1820 (long int) (Write_RAM_At+abbrevs_at));
1821 printf(" | printing variables |\n");
1822 if (alphabet_modified)
1824 printf(" + - - - - - - - - - - + %06lx\n",
1825 (long int) (Write_RAM_At+charset_at));
1826 printf(" | alphabets table |\n");
1828 if (zscii_defn_modified)
1830 printf(" + - - - - - - - - - - + %06lx\n",
1831 (long int) (Write_RAM_At+unicode_at));
1832 printf(" | Unicode table |\n");
1834 printf(" +---------------------+ %06lx\n",
1835 (long int) (Write_RAM_At+object_tree_at));
1836 printf(" | objects |\n");
1837 printf(" + - - - - - - - - - - + %06lx\n",
1838 (long int) (Write_RAM_At+object_props_at));
1839 printf(" | property values |\n");
1840 printf(" + - - - - - - - - - - + %06lx\n",
1841 (long int) (Write_RAM_At+prop_defaults_at));
1842 printf(" | property defaults |\n");
1843 printf(" + - - - - - - - - - - + %06lx\n",
1844 (long int) (Write_RAM_At+class_numbers_offset));
1845 printf(" | class numbers table |\n");
1846 printf(" + - - - - - - - - - - + %06lx\n",
1847 (long int) (Write_RAM_At+identifier_names_offset));
1848 printf(" | id names table |\n");
1849 printf(" +---------------------+ %06lx\n",
1850 (long int) (Write_RAM_At+grammar_table_at));
1851 printf(" | grammar table |\n");
1852 printf(" + - - - - - - - - - - + %06lx\n",
1853 (long int) (Write_RAM_At+actions_at));
1854 printf(" | actions |\n");
1855 printf(" +---------------------+ %06lx\n",
1856 (long int) dictionary_offset);
1857 printf(" | dictionary |\n");
1858 if (MEMORY_MAP_EXTENSION == 0)
1860 printf(" +---------------------+ %06lx\n", (long int) Out_Size);
1864 printf(" +=====================+ %06lx\n", (long int) Out_Size);
1865 printf("Runtime | (empty) |\n");
1866 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1874 if (percentages_switch)
1875 { printf("Approximate percentage breakdown of %s:\n",
1877 percentage("Code", code_length,Out_Size);
1879 percentage("Linking data", link_data_size,Out_Size);
1880 percentage("Static strings", strings_length,Out_Size);
1881 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1882 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1883 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1884 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1885 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1886 percentage("Total of save area", grammar_table_at,Out_Size);
1887 percentage("Total of text", strings_length,Out_Size);
1889 if (frequencies_switch)
1891 { printf("How frequently abbreviations were used, and roughly\n");
1892 printf("how many bytes they saved: ('_' denotes spaces)\n");
1893 for (i=0; i<no_abbreviations; i++)
1894 { char abbrev_string[MAX_ABBREV_LENGTH];
1895 strcpy(abbrev_string,
1896 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1897 for (j=0; abbrev_string[j]!=0; j++)
1898 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1899 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1900 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1901 if ((i%3)==2) printf("\n");
1903 if ((i%3)!=0) printf("\n");
1904 if (no_abbreviations==0) printf("None were declared.\n");
1909 extern void construct_storyfile(void)
1912 construct_storyfile_z();
1914 construct_storyfile_g();
1917 /* ========================================================================= */
1918 /* Data structure management routines */
1919 /* ------------------------------------------------------------------------- */
1921 extern void init_tables_vars(void)
1924 statusline_flag = SCORE_STYLE;
1926 zmachine_paged_memory = NULL;
1929 code_offset = 0x800;
1930 actions_offset = 0x800;
1931 preactions_offset = 0x800;
1932 dictionary_offset = 0x800;
1933 adjectives_offset = 0x800;
1934 variables_offset = 0;
1935 strings_offset = 0xc00;
1936 individuals_offset=0x800;
1937 identifier_names_offset=0x800;
1938 class_numbers_offset = 0x800;
1939 arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1940 static_arrays_offset = 0x0800;
1943 code_offset = 0x12345;
1944 actions_offset = 0x12345;
1945 preactions_offset = 0x12345;
1946 dictionary_offset = 0x12345;
1947 adjectives_offset = 0x12345;
1948 variables_offset = 0x12345;
1949 arrays_offset = 0x12345;
1950 strings_offset = 0x12345;
1951 individuals_offset=0x12345;
1952 identifier_names_offset=0x12345;
1953 class_numbers_offset = 0x12345;
1954 static_arrays_offset = 0x12345;
1958 extern void tables_begin_pass(void)
1962 extern void tables_allocate_arrays(void)
1966 extern void tables_free_arrays(void)
1968 /* Allocation for this array happens in construct_storyfile() above */
1970 my_free(&zmachine_paged_memory,"output buffer");
1973 /* ========================================================================= */