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 - 2018 */
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, 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;
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 += scale_factor*0x100 /* maximum null bytes before code */
195 + 1000; /* fudge factor (in case the above is wrong) */
200 static int32 rough_size_of_paged_memory_g(void)
202 /* This function calculates a modest over-estimate of the amount of
203 memory required to store the machine's paged memory area
204 (that is, everything up to the start of the code area). */
210 /* No header for us! */
211 total = 1000; /* bit of a fudge factor */
213 total += dynamic_array_area_size; /* arrays and global variables */
215 total += no_objects * OBJECT_BYTE_LENGTH; /* object tables */
216 total += properties_table_size; /* property tables */
217 total += no_properties * 4; /* property defaults table */
219 total += 4 + no_classes * 4; /* class prototype object numbers */
221 total += 32; /* address/length of the identifier tables */
222 total += no_properties * 4;
223 total += (no_individual_properties-INDIV_PROP_START) * 4;
224 total += (NUM_ATTR_BYTES*8) * 4;
225 total += (no_actions + no_fake_actions) * 4;
226 total += 4 + no_arrays * 4;
228 total += 4 + no_Inform_verbs * 4; /* index of grammar tables */
229 total += grammar_lines_top; /* grammar tables */
231 total += 4 + no_actions * 4; /* actions functions table */
234 total += subtract_pointers(dictionary_top, dictionary);
236 while (total % GPAGESIZE)
242 static void construct_storyfile_z(void)
244 int32 i, j, k, l, mark, objs, strings_length, code_length,
245 limit=0, excess=0, extend_offset=0, headerext_length=0;
246 int32 globals_at=0, link_table_at=0, dictionary_at=0, actions_at=0, preactions_at=0,
247 abbrevs_at=0, prop_defaults_at=0, object_tree_at=0, object_props_at=0,
248 map_of_module=0, grammar_table_at=0, charset_at=0, headerext_at=0,
249 terminating_chars_at=0, unicode_at=0, id_names_length=0;
250 int skip_backpatching = FALSE;
251 char *output_called = (module_switch)?"module":"story file";
255 individual_name_strings =
256 my_calloc(sizeof(int32), no_individual_properties,
257 "identifier name strings");
258 action_name_strings =
259 my_calloc(sizeof(int32), no_actions + no_fake_actions,
260 "action name strings");
261 attribute_name_strings =
262 my_calloc(sizeof(int32), 48,
263 "attribute name strings");
265 my_calloc(sizeof(int32),
267 "array name strings");
269 write_the_identifier_names();
271 /* We now know how large the buffer to hold our construction has to be */
273 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_z(),
276 /* Foolish code to make this routine compile on all ANSI compilers */
278 p = (uchar *) zmachine_paged_memory;
280 /* In what follows, the "mark" will move upwards in memory: at various
281 points its value will be recorded for milestones like
282 "dictionary table start". It begins at 0x40, just after the header */
286 /* ----------------- Low Strings and Abbreviations -------------------- */
288 p[mark]=0x80; p[mark+1]=0; mark+=2; /* Start the low strings pool
289 with a useful default string, " " */
291 for (i=0; i+low_strings<low_strings_top; mark++, i++) /* Low strings pool */
292 p[0x42+i]=low_strings[i];
295 for (i=0; i<3*32; i++) /* Initially all 96 entries */
296 { p[mark++]=0; p[mark++]=0x20; /* are set to " " */
298 for (i=0; i<no_abbreviations; i++) /* Write any abbreviations */
299 { j=abbrev_values[i]; /* into banks 2 and 3 */
300 p[abbrevs_at+64+2*i]=j/256; /* (bank 1 is reserved for */
301 p[abbrevs_at+65+2*i]=j%256; /* "variable strings") */
304 /* ------------------- Header extension table ------------------------- */
307 headerext_length = ZCODE_HEADER_EXT_WORDS;
308 if (zscii_defn_modified) {
309 /* Need at least 3 words for unicode table address */
310 if (headerext_length < 3)
311 headerext_length = 3;
313 if (ZCODE_HEADER_FLAGS_3) {
314 /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
315 if (headerext_length < 4)
316 headerext_length = 4;
318 p[mark++] = 0; p[mark++] = headerext_length;
319 for (i=0; i<headerext_length; i++)
320 { p[mark++] = 0; p[mark++] = 0;
323 /* -------------------- Z-character set table ------------------------- */
325 if (alphabet_modified)
327 for (i=0;i<3;i++) for (j=0;j<26;j++)
328 { if (alphabet[i][j] == '~') p[mark++] = '\"';
329 else p[mark++] = alphabet[i][j];
333 /* ------------------ Unicode translation table ----------------------- */
336 if (zscii_defn_modified)
338 p[mark++] = zscii_high_water_mark;
339 for (i=0;i<zscii_high_water_mark;i++)
340 { j = zscii_to_unicode(155 + i);
341 if (j < 0 || j > 0xFFFF) {
342 error("Z-machine Unicode translation table cannot contain characters beyond $FFFF.");
344 p[mark++] = j/256; p[mark++] = j%256;
348 /* -------------------- Objects and Properties ------------------------ */
350 /* The object table must be word-aligned. The Z-machine spec does not
351 require this, but the RA__Pr() veneer routine does. See
352 http://inform7.com/mantis/view.php?id=1712.
354 while ((mark%2) != 0) p[mark++]=0;
356 prop_defaults_at = mark;
358 p[mark++]=0; p[mark++]=0;
360 for (i=2; i< ((version_number==3)?32:64); i++)
361 { p[mark++]=prop_default_value[i]/256;
362 p[mark++]=prop_default_value[i]%256;
365 object_tree_at = mark;
367 mark += ((version_number==3)?9:14)*no_objects;
369 object_props_at = mark;
371 for (i=0; i<properties_table_size; i++)
372 p[mark+i]=properties_table[i];
374 for (i=0, objs=object_tree_at; i<no_objects; i++)
376 if (version_number == 3)
377 { p[objs]=objectsz[i].atts[0];
378 p[objs+1]=objectsz[i].atts[1];
379 p[objs+2]=objectsz[i].atts[2];
380 p[objs+3]=objectsz[i].atts[3];
381 p[objs+4]=objectsz[i].parent;
382 p[objs+5]=objectsz[i].next;
383 p[objs+6]=objectsz[i].child;
389 { p[objs]=objectsz[i].atts[0];
390 p[objs+1]=objectsz[i].atts[1];
391 p[objs+2]=objectsz[i].atts[2];
392 p[objs+3]=objectsz[i].atts[3];
393 p[objs+4]=objectsz[i].atts[4];
394 p[objs+5]=objectsz[i].atts[5];
395 p[objs+6]=(objectsz[i].parent)/256;
396 p[objs+7]=(objectsz[i].parent)%256;
397 p[objs+8]=(objectsz[i].next)/256;
398 p[objs+9]=(objectsz[i].next)%256;
399 p[objs+10]=(objectsz[i].child)/256;
400 p[objs+11]=(objectsz[i].child)%256;
402 { p[objs+12]=mark/256;
406 { p[objs+12]=objectsz[i].propsize/256;
407 p[objs+13]=objectsz[i].propsize%256;
411 mark+=objectsz[i].propsize;
414 /* ----------- Table of Class Prototype Object Numbers ---------------- */
416 class_numbers_offset = mark;
417 for (i=0; i<no_classes; i++)
418 { p[mark++] = class_object_numbers[i]/256;
419 p[mark++] = class_object_numbers[i]%256;
421 { p[mark++] = class_begins_at[i]/256;
422 p[mark++] = class_begins_at[i]%256;
428 /* ------------------- Table of Identifier Names ---------------------- */
430 identifier_names_offset = mark;
433 { p[mark++] = no_individual_properties/256;
434 p[mark++] = no_individual_properties%256;
435 for (i=1; i<no_individual_properties; i++)
436 { p[mark++] = individual_name_strings[i]/256;
437 p[mark++] = individual_name_strings[i]%256;
440 attribute_names_offset = mark;
442 { p[mark++] = attribute_name_strings[i]/256;
443 p[mark++] = attribute_name_strings[i]%256;
446 action_names_offset = mark;
447 fake_action_names_offset = mark + 2*no_actions;
448 for (i=0; i<no_actions + no_fake_actions; i++)
449 { p[mark++] = action_name_strings[i]/256;
450 p[mark++] = action_name_strings[i]%256;
453 array_names_offset = mark;
454 global_names_offset = mark + 2*no_arrays;
455 routine_names_offset = global_names_offset + 2*no_globals;
456 constant_names_offset = routine_names_offset + 2*no_named_routines;
457 for (i=0; i<no_arrays + no_globals
458 + no_named_routines + no_named_constants; i++)
459 { if ((i == no_arrays) && (define_INFIX_switch == FALSE)) break;
460 p[mark++] = array_name_strings[i]/256;
461 p[mark++] = array_name_strings[i]%256;
464 id_names_length = (mark - identifier_names_offset)/2;
466 routine_flags_array_offset = mark;
468 if (define_INFIX_switch)
469 { for (i=0, k=1, l=0; i<no_named_routines; i++)
470 { if (sflags[named_routine_symbols[i]] & STAR_SFLAG) l=l+k;
472 if (k==256) { p[mark++] = l; k=1; l=0; }
474 if (k!=1) p[mark++]=l;
477 /* ---------------- Table of Indiv Property Values -------------------- */
479 individuals_offset = mark;
480 for (i=0; i<individuals_length; i++)
481 p[mark++] = individuals_table[i];
483 /* ----------------- Variables and Dynamic Arrays --------------------- */
487 for (i=0; i<dynamic_array_area_size; i++)
488 p[mark++] = dynamic_array_area[i];
490 for (i=0; i<240; i++)
491 { j=global_initial_value[i];
492 p[globals_at+i*2] = j/256; p[globals_at+i*2+1] = j%256;
495 /* ------------------ Terminating Characters Table -------------------- */
497 if (version_number >= 5)
498 { terminating_chars_at = mark;
499 for (i=0; i<no_termcs; i++) p[mark++] = terminating_characters[i];
503 /* ------------------------ Grammar Table ----------------------------- */
505 if (grammar_version_number > 2)
506 { warning("This version of Inform is unable to produce the grammar \
507 table format requested (producing number 2 format instead)");
508 grammar_version_number = 2;
511 grammar_table_at = mark;
513 mark = mark + no_Inform_verbs*2;
515 for (i=0; i<no_Inform_verbs; i++)
516 { p[grammar_table_at + i*2] = (mark/256);
517 p[grammar_table_at + i*2 + 1] = (mark%256);
518 p[mark++] = Inform_verbs[i].lines;
519 for (j=0; j<Inform_verbs[i].lines; j++)
520 { k = Inform_verbs[i].l[j];
521 if (grammar_version_number == 1)
523 p[mark+7] = grammar_lines[k+1];
524 for (m=1;m<=6;m++) p[mark + m] = 0;
525 k = k + 2; m = 1; n = 0;
526 while ((grammar_lines[k] != 15) && (m<=6))
527 { p[mark + m] = grammar_lines[k];
528 if (grammar_lines[k] < 180) n++;
536 p[mark++] = grammar_lines[k++];
537 p[mark++] = grammar_lines[k++];
539 { tok = grammar_lines[k++];
541 if (tok == 15) break;
542 p[mark++] = grammar_lines[k++];
543 p[mark++] = grammar_lines[k++];
549 /* ------------------- Actions and Preactions ------------------------- */
550 /* (The term "preactions" is traditional: Inform uses the preactions */
551 /* table for a different purpose than Infocom used to.) */
552 /* The values are written later, when the Z-code offset is known. */
553 /* -------------------------------------------------------------------- */
556 mark += no_actions*2;
558 preactions_at = mark;
559 if (grammar_version_number == 1)
560 mark += no_grammar_token_routines*2;
562 /* ----------------------- Adjectives Table --------------------------- */
564 if (grammar_version_number == 1)
565 { p[mark]=0; p[mark+1]=no_adjectives; mark+=2; /* To assist "infodump" */
566 adjectives_offset = mark;
567 dictionary_offset = mark + 4*no_adjectives;
569 for (i=0; i<no_adjectives; i++)
570 { j = final_dict_order[adjectives[no_adjectives-i-1]]
571 *((version_number==3)?7:9)
572 + dictionary_offset + 7;
573 p[mark++]=j/256; p[mark++]=j%256; p[mark++]=0;
574 p[mark++]=(256-no_adjectives+i);
578 { p[mark]=0; p[mark+1]=0; mark+=2;
579 adjectives_offset = mark;
580 dictionary_offset = mark;
583 /* ------------------------- Dictionary ------------------------------- */
587 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
588 dictionary[2]=','; /* force words apart */
591 dictionary[4]=(version_number==3)?7:9; /* Length of each entry */
592 dictionary[5]=(dict_entries/256); /* Number of entries */
593 dictionary[6]=(dict_entries%256);
595 for (i=0; i<7; i++) p[mark++] = dictionary[i];
597 for (i=0; i<dict_entries; i++)
598 { k = 7 + i*((version_number==3)?7:9);
599 j = mark + final_dict_order[i]*((version_number==3)?7:9);
600 for (l = 0; l<((version_number==3)?7:9); l++)
601 p[j++] = dictionary[k++];
603 mark += dict_entries * ((version_number==3)?7:9);
605 /* ------------------------- Module Map ------------------------------- */
608 { map_of_module = mark; /* Filled in below */
612 /* ----------------- A gap before the code area ----------------------- */
613 /* (so that it will start at an exact packed address and so that all */
614 /* routine packed addresses are >= 256, hence long constants) */
615 /* -------------------------------------------------------------------- */
617 while ((mark%length_scale_factor) != 0) p[mark++]=0;
618 while (mark < (scale_factor*0x100)) p[mark++]=0;
619 if (oddeven_packing_switch)
620 while ((mark%(scale_factor*2)) != 0) p[mark++]=0;
623 { error("This program has overflowed the maximum readable-memory \
624 size of the Z-machine format. See the memory map below: the start \
625 of the area marked \"above readable memory\" must be brought down to $FFFE \
627 memory_map_switch = TRUE;
628 /* Backpatching the grammar tables requires us to trust some of the */
629 /* addresses we've written into Z-machine memory, but they may have */
630 /* been truncated to 16 bits, so we can't do it. */
631 skip_backpatching = TRUE;
634 /* -------------------------- Code Area ------------------------------- */
635 /* (From this point on we don't write any more into the "p" buffer.) */
636 /* -------------------------------------------------------------------- */
638 Write_Code_At = mark;
639 if (!OMIT_UNUSED_ROUTINES) {
640 code_length = zmachine_pc;
643 if (zmachine_pc != df_total_size_before_stripping)
644 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
645 code_length = df_total_size_after_stripping;
649 /* ------------------ Another synchronising gap ----------------------- */
651 if (oddeven_packing_switch)
653 while ((mark%(scale_factor*2)) != 0) mark++;
655 while ((mark%(scale_factor*2)) != scale_factor) mark++;
658 while ((mark%scale_factor) != 0) mark++;
660 /* ------------------------- Strings Area ----------------------------- */
662 Write_Strings_At = mark;
663 strings_length = static_strings_extent;
664 mark += strings_length;
666 /* --------------------- Module Linking Data -------------------------- */
669 { link_table_at = mark; mark += link_data_size;
670 mark += zcode_backpatch_size;
671 mark += zmachine_backpatch_size;
674 /* --------------------- Is the file too big? ------------------------- */
678 switch(version_number)
679 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
681 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
684 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
688 { excess = Out_Size-((int32) 0x10000L); limit=64;
692 { char memory_full_error[80];
693 sprintf(memory_full_error,
694 "The %s exceeds version-%d limit (%dK) by %d bytes",
695 output_called, version_number, limit, excess);
696 fatalerror(memory_full_error);
699 /* --------------------------- Offsets -------------------------------- */
701 dictionary_offset = dictionary_at;
702 variables_offset = globals_at;
703 actions_offset = actions_at;
704 preactions_offset = preactions_at;
705 prop_defaults_offset = prop_defaults_at;
706 prop_values_offset = object_props_at;
707 static_memory_offset = grammar_table_at;
708 grammar_table_offset = grammar_table_at;
710 if (extend_memory_map)
712 if (no_objects+9 > extend_offset) extend_offset=no_objects+9;
713 while ((extend_offset%length_scale_factor) != 0) extend_offset++;
714 /* Not sure why above line is necessary, but oddeven_packing
715 * will need extend_offset to be even */
716 code_offset = extend_offset*scale_factor;
717 if (oddeven_packing_switch)
718 strings_offset = code_offset + scale_factor;
720 strings_offset = code_offset + (Write_Strings_At-Write_Code_At);
722 /* With the extended memory model, need to specifically check that we
723 * haven't overflowed the packed address range for routines or strings.
724 * With the standard memory model, we only need the earlier total size
727 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
729 { char code_full_error[80];
730 sprintf(code_full_error,
731 "The code area limit has been exceeded by %d bytes",
733 fatalerror(code_full_error);
736 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
738 { char strings_full_error[140];
739 if (oddeven_packing_switch)
740 sprintf(strings_full_error,
741 "The strings area limit has been exceeded by %d bytes",
744 sprintf(strings_full_error,
745 "The code+strings area limit has been exceeded by %d bytes. \
746 Try running Inform again with -B on the command line.",
748 fatalerror(strings_full_error);
752 { code_offset = Write_Code_At;
753 strings_offset = Write_Strings_At;
756 /* --------------------------- The Header ----------------------------- */
758 for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */
760 p[0] = version_number; /* Version number */
761 p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */
762 p[2] = (release_number/256);
763 p[3] = (release_number%256); /* Release */
764 p[4] = (Write_Code_At/256);
765 p[5] = (Write_Code_At%256); /* End of paged memory */
766 if (version_number==6)
767 { j=code_offset/scale_factor; /* Packed address of "Main__" */
768 p[6]=(j/256); p[7]=(j%256);
771 { j=Write_Code_At+1; /* Initial PC value (bytes) */
772 p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */
774 p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */
775 p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */
776 p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */
777 p[14]=(grammar_table_at/256);
778 p[15]=(grammar_table_at%256); /* Grammar */
779 for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */
780 j+=k*flags2_requirements[i]; /* unusual opcodes assembled */
781 p[16]=j/256; p[17]=j%256;
782 write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */
783 p[24]=abbrevs_at/256;
784 p[25]=abbrevs_at%256; /* Abbreviations table */
785 p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */
786 p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */
788 if (extend_memory_map)
789 { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor;
790 p[40]=j/256; p[41]=j%256; /* Routines offset */
791 if (oddeven_packing_switch)
792 j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor;
793 p[42]=j/256; p[43]=j%256; /* = Strings offset */
796 if (version_number >= 5)
797 { p[46] = terminating_chars_at/256; /* Terminating characters table */
798 p[47] = terminating_chars_at%256;
801 if (alphabet_modified)
803 p[52]=j/256; p[53]=j%256; } /* Character set table address */
806 p[54] = j/256; p[55] = j%256; /* Header extension table address */
808 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
810 p[62] = '0' + ((RELEASE_NUMBER/10)%10);
811 p[63] = '0' + RELEASE_NUMBER%10;
813 /* ------------------------ Header Extension -------------------------- */
815 /* The numbering in the spec is a little weird -- it's headerext_length
816 words *after* the initial length word. We follow the spec numbering
817 in this switch statement, so the count is 1-based. */
818 for (i=1; i<=headerext_length; i++) {
821 j = unicode_at; /* Unicode translation table address */
824 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
830 p[headerext_at+2*i+0] = j / 256;
831 p[headerext_at+2*i+1] = j % 256;
834 /* ----------------- The Header: Extras for modules ------------------- */
838 p[1]=MODULE_VERSION_NUMBER;
839 p[6]=map_of_module/256;
840 p[7]=map_of_module%256;
842 mark = map_of_module; /* Module map format: */
844 p[mark++]=object_tree_at/256; /* 0: Object tree addr */
845 p[mark++]=object_tree_at%256;
846 p[mark++]=object_props_at/256; /* 2: Prop values addr */
847 p[mark++]=object_props_at%256;
848 p[mark++]=(Write_Strings_At/scale_factor)/256; /* 4: Static strs */
849 p[mark++]=(Write_Strings_At/scale_factor)%256;
850 p[mark++]=class_numbers_offset/256; /* 6: Class nos addr */
851 p[mark++]=class_numbers_offset%256;
852 p[mark++]=individuals_offset/256; /* 8: Indiv prop values */
853 p[mark++]=individuals_offset%256;
854 p[mark++]=individuals_length/256; /* 10: Length of table */
855 p[mark++]=individuals_length%256;
856 p[mark++]=no_symbols/256; /* 12: No of symbols */
857 p[mark++]=no_symbols%256;
858 p[mark++]=no_individual_properties/256; /* 14: Max property no */
859 p[mark++]=no_individual_properties%256;
860 p[mark++]=no_objects/256; /* 16: No of objects */
861 p[mark++]=no_objects%256;
863 p[mark++]=i/256; /* 18: Import/exports */
865 p[mark++]=link_data_size/256; /* 20: Size of */
866 p[mark++]=link_data_size%256;
868 p[mark++]=i/256; /* 22: Code backpatch */
870 p[mark++]=zcode_backpatch_size/256; /* 24: Size of */
871 p[mark++]=zcode_backpatch_size%256;
872 i += zcode_backpatch_size;
873 p[mark++]=i/256; /* 26: Image backpatch */
875 p[mark++]=zmachine_backpatch_size/256; /* 28: Size of */
876 p[mark++]=zmachine_backpatch_size%256;
878 /* Further space in this table is reserved for future use */
881 /* ---- Backpatch the Z-machine, now that all information is in ------- */
883 if (!module_switch && !skip_backpatching)
884 { backpatch_zmachine_image_z();
885 for (i=1; i<id_names_length; i++)
886 { int32 v = 256*p[identifier_names_offset + i*2]
887 + p[identifier_names_offset + i*2 + 1];
888 if (v!=0) v += strings_offset/scale_factor;
889 p[identifier_names_offset + i*2] = v/256;
890 p[identifier_names_offset + i*2 + 1] = v%256;
894 for (i=0; i<no_actions; i++)
895 { j=action_byte_offset[i];
896 if (OMIT_UNUSED_ROUTINES)
897 j = df_stripped_address_for_address(j);
898 j += code_offset/scale_factor;
899 p[mark++]=j/256; p[mark++]=j%256;
902 if (grammar_version_number == 1)
903 { mark = preactions_at;
904 for (i=0; i<no_grammar_token_routines; i++)
905 { j=grammar_token_routine[i];
906 if (OMIT_UNUSED_ROUTINES)
907 j = df_stripped_address_for_address(j);
908 j += code_offset/scale_factor;
909 p[mark++]=j/256; p[mark++]=j%256;
913 { for (l = 0; l<no_Inform_verbs; l++)
914 { k = grammar_table_at + 2*l;
915 i = p[k]*256 + p[k+1];
916 for (j = p[i++]; j>0; j--)
917 { int topbits; int32 value;
920 { topbits = (p[i]/0x40) & 3;
921 value = p[i+1]*256 + p[i+2];
924 value = final_dict_order[value]
925 *((version_number==3)?7:9)
926 + dictionary_offset + 7;
929 if (OMIT_UNUSED_ROUTINES)
930 value = df_stripped_address_for_address(value);
931 value += code_offset/scale_factor;
934 p[i+1] = value/256; p[i+2] = value%256;
943 /* ---- From here on, it's all reportage: construction is finished ---- */
945 if (statistics_switch)
946 { int32 k_long, rate; char *k_str="";
947 k_long=(Out_Size/1024);
948 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
949 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
950 if (total_bytes_trans == 0) rate = 0;
951 else rate=total_bytes_trans*1000/total_chars_trans;
954 %3d source code files %6d syntactic lines\n\
955 %6d textual lines %8ld characters ",
956 total_input_files, no_syntax_lines,
957 total_source_line_count, (long int) total_chars_read);
958 if (character_set_unicode) printf("(UTF-8)\n");
959 else if (character_set_setting == 0) printf("(plain ASCII)\n");
961 { printf("(ISO 8859-%d %s)\n", character_set_setting,
962 name_of_iso_set(character_set_setting));
965 printf("Allocated:\n\
966 %6d symbols (maximum %4d) %8ld bytes of memory\n\
967 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
968 no_symbols, MAX_SYMBOLS,
969 (long int) malloced_bytes,
971 version_name(version_number),
973 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
974 (long int) k_long, k_str);
977 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
978 %6d global vars (maximum 233) %6d variable/array space (maximum %d)\n",
979 no_classes, MAX_CLASSES,
980 no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)),
982 dynamic_array_area_size, MAX_STATIC_DATA);
985 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
986 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
987 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
988 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
989 no_Inform_verbs, MAX_VERBS,
990 dict_entries, MAX_DICT_ENTRIES,
991 no_grammar_lines, grammar_version_number,
993 no_actions, MAX_ACTIONS,
994 no_attributes, ((version_number==3)?32:48),
995 no_properties-2, ((version_number==3)?30:62),
996 no_individual_properties - 64);
998 if (track_unused_routines)
1000 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1002 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
1003 (long int) df_total_size_before_stripping, (long int) diff,
1004 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1005 100 * (float)diff / (float)df_total_size_before_stripping);
1009 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1010 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1011 %6ld instructions of Z-code %6d sequence points\n\
1012 %6ld bytes readable memory used (maximum 65536)\n\
1013 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
1014 (long int) total_chars_trans,
1015 (long int) total_bytes_trans,
1016 (total_chars_trans>total_bytes_trans)?0:1,
1018 no_abbreviations, MAX_ABBREVS,
1020 (long int) no_instructions, no_sequence_points,
1021 (long int) Write_Code_At,
1022 (long int) Out_Size,
1024 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1032 "\nOffsets in %s:\n\
1033 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1034 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1035 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1037 (long int) abbrevs_at,
1038 (long int) prop_defaults_at,
1039 (long int) object_tree_at,
1040 (long int) object_props_at,
1041 (long int) globals_at,
1042 (long int) grammar_table_at,
1043 (long int) actions_at,
1044 (long int) preactions_at,
1045 (long int) adjectives_offset,
1046 (long int) dictionary_at,
1047 (long int) Write_Code_At,
1048 (long int) Write_Strings_At);
1050 printf("%05lx Linking data\n",(long int) link_table_at);
1054 if (debugfile_switch)
1055 { begin_writing_debug_sections();
1056 write_debug_section("abbreviations", 64);
1057 write_debug_section("abbreviations table", abbrevs_at);
1058 write_debug_section("header extension", headerext_at);
1059 if (alphabet_modified)
1060 { write_debug_section("alphabets table", charset_at);
1062 if (zscii_defn_modified)
1063 { write_debug_section("Unicode table", unicode_at);
1065 write_debug_section("property defaults", prop_defaults_at);
1066 write_debug_section("object tree", object_tree_at);
1067 write_debug_section("common properties", object_props_at);
1068 write_debug_section("class numbers", class_numbers_offset);
1069 write_debug_section("identifier names", identifier_names_offset);
1070 write_debug_section("individual properties", individuals_offset);
1071 write_debug_section("global variables", globals_at);
1072 write_debug_section("array space", globals_at+480);
1073 write_debug_section("grammar table", grammar_table_at);
1074 write_debug_section("actions table", actions_at);
1075 write_debug_section("parsing routines", preactions_at);
1076 write_debug_section("adjectives table", adjectives_offset);
1077 write_debug_section("dictionary", dictionary_at);
1078 write_debug_section("code area", Write_Code_At);
1079 write_debug_section("strings area", Write_Strings_At);
1080 end_writing_debug_sections(Out_Size);
1083 if (memory_map_switch)
1086 printf("Dynamic +---------------------+ 00000\n");
1087 printf("memory | header |\n");
1088 printf(" +---------------------+ 00040\n");
1089 printf(" | abbreviations |\n");
1090 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at);
1091 printf(" | abbreviations table |\n");
1092 printf(" +---------------------+ %05lx\n", (long int) headerext_at);
1093 printf(" | header extension |\n");
1094 if (alphabet_modified)
1096 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at);
1097 printf(" | alphabets table |\n");
1099 if (zscii_defn_modified)
1101 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at);
1102 printf(" | Unicode table |\n");
1104 printf(" +---------------------+ %05lx\n",
1105 (long int) prop_defaults_at);
1106 printf(" | property defaults |\n");
1107 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at);
1108 printf(" | objects |\n");
1109 printf(" + - - - - - - - - - - + %05lx\n",
1110 (long int) object_props_at);
1111 printf(" | object short names, |\n");
1112 printf(" | common prop values |\n");
1113 printf(" + - - - - - - - - - - + %05lx\n",
1114 (long int) class_numbers_offset);
1115 printf(" | class numbers table |\n");
1116 printf(" + - - - - - - - - - - + %05lx\n",
1117 (long int) identifier_names_offset);
1118 printf(" | symbol names table |\n");
1119 printf(" + - - - - - - - - - - + %05lx\n",
1120 (long int) individuals_offset);
1121 printf(" | indiv prop values |\n");
1122 printf(" +---------------------+ %05lx\n", (long int) globals_at);
1123 printf(" | global variables |\n");
1124 printf(" + - - - - - - - - - - + %05lx\n",
1125 ((long int) globals_at)+480L);
1126 printf(" | arrays |\n");
1127 printf(" +=====================+ %05lx\n",
1128 (long int) grammar_table_at);
1129 printf("Readable| grammar table |\n");
1130 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at);
1131 printf(" | actions |\n");
1132 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at);
1133 printf(" | parsing routines |\n");
1134 printf(" + - - - - - - - - - - + %05lx\n",
1135 (long int) adjectives_offset);
1136 printf(" | adjectives |\n");
1137 printf(" +---------------------+ %05lx\n", (long int) dictionary_at);
1138 printf(" | dictionary |\n");
1141 printf(" + - - - - - - - - - - + %05lx\n",
1142 (long int) map_of_module);
1143 printf(" | map of module addrs |\n");
1145 printf(" +=====================+ %05lx\n", (long int) Write_Code_At);
1146 printf("Above | Z-code |\n");
1147 printf("readable+---------------------+ %05lx\n",
1148 (long int) Write_Strings_At);
1149 printf("memory | strings |\n");
1152 printf(" +=====================+ %05lx\n", (long int) link_table_at);
1153 printf(" | module linking data |\n");
1155 printf(" +---------------------+ %05lx\n", (long int) Out_Size);
1158 if (percentages_switch)
1159 { printf("Approximate percentage breakdown of %s:\n",
1161 percentage("Z-code", code_length,Out_Size);
1163 percentage("Linking data", link_data_size,Out_Size);
1164 percentage("Static strings", strings_length,Out_Size);
1165 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1166 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1167 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1168 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1169 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1170 percentage("Total of save area", grammar_table_at,Out_Size);
1171 percentage("Total of text", total_bytes_trans,Out_Size);
1173 if (frequencies_switch)
1175 { printf("How frequently abbreviations were used, and roughly\n");
1176 printf("how many bytes they saved: ('_' denotes spaces)\n");
1177 for (i=0; i<no_abbreviations; i++)
1178 { char abbrev_string[MAX_ABBREV_LENGTH];
1179 strcpy(abbrev_string,
1180 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1181 for (j=0; abbrev_string[j]!=0; j++)
1182 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1183 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1184 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1185 if ((i%3)==2) printf("\n");
1187 if ((i%3)!=0) printf("\n");
1188 if (no_abbreviations==0) printf("None were declared.\n");
1193 static void construct_storyfile_g(void)
1195 int32 i, j, k, l, mark, strings_length, limit;
1196 int32 globals_at, dictionary_at, actions_at, preactions_at,
1197 abbrevs_at, prop_defaults_at, object_tree_at, object_props_at,
1198 grammar_table_at, charset_at, headerext_at,
1199 unicode_at, arrays_at;
1200 int32 threespaces, code_length;
1201 char *output_called = (module_switch)?"module":"story file";
1205 individual_name_strings =
1206 my_calloc(sizeof(int32), no_individual_properties,
1207 "identifier name strings");
1208 action_name_strings =
1209 my_calloc(sizeof(int32), no_actions + no_fake_actions,
1210 "action name strings");
1211 attribute_name_strings =
1212 my_calloc(sizeof(int32), NUM_ATTR_BYTES*8,
1213 "attribute name strings");
1214 array_name_strings =
1215 my_calloc(sizeof(int32),
1217 "array name strings");
1219 write_the_identifier_names();
1220 threespaces = compile_string(" ", FALSE, FALSE);
1222 compress_game_text();
1224 /* We now know how large the buffer to hold our construction has to be */
1226 zmachine_paged_memory = my_malloc(rough_size_of_paged_memory_g(),
1229 /* Foolish code to make this routine compile on all ANSI compilers */
1231 p = (uchar *) zmachine_paged_memory;
1233 /* In what follows, the "mark" will move upwards in memory: at various
1234 points its value will be recorded for milestones like
1235 "dictionary table start". It begins at 0x40, just after the header */
1237 /* Ok, our policy here will be to set the *_at values all relative
1238 to RAM. That's so we can write into zmachine_paged_memory[mark]
1239 and actually hit what we're aiming at.
1240 All the *_offset values will be set to true Glulx machine
1243 /* To get our bearings, figure out where the strings and code are. */
1244 /* We start with two words, which conventionally identify the
1245 memory layout. This is why the code starts eight bytes after
1247 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1248 if (!OMIT_UNUSED_ROUTINES) {
1249 code_length = zmachine_pc;
1252 if (zmachine_pc != df_total_size_before_stripping)
1253 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1254 code_length = df_total_size_after_stripping;
1256 Write_Strings_At = Write_Code_At + code_length;
1257 strings_length = compression_table_size + compression_string_size;
1259 /* Now figure out where RAM starts. */
1260 Write_RAM_At = Write_Strings_At + strings_length;
1261 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1262 while (Write_RAM_At % GPAGESIZE)
1265 /* Now work out all those RAM positions. */
1268 /* ----------------- Variables and Dynamic Arrays --------------------- */
1271 for (i=0; i<no_globals; i++) {
1272 j = global_initial_value[i];
1273 WriteInt32(p+mark, j);
1278 for (i=MAX_GLOBAL_VARIABLES*4; i<dynamic_array_area_size; i++)
1279 p[mark++] = dynamic_array_area[i];
1281 /* -------------------------- Dynamic Strings -------------------------- */
1284 WriteInt32(p+mark, no_dynamic_strings);
1286 for (i=0; i<no_dynamic_strings; i++) {
1287 j = Write_Strings_At + compressed_offsets[threespaces-1];
1288 WriteInt32(p+mark, j);
1292 /* ---------------- Various Things I'm Not Sure About ------------------ */
1293 /* Actually, none of these are relevant to Glulx. */
1294 headerext_at = mark;
1296 if (alphabet_modified)
1299 if (zscii_defn_modified)
1302 /* -------------------- Objects and Properties ------------------------ */
1304 object_tree_at = mark;
1306 object_props_at = mark + no_objects*OBJECT_BYTE_LENGTH;
1308 for (i=0; i<no_objects; i++) {
1309 int32 objmark = mark;
1310 p[mark++] = 0x70; /* type byte -- object */
1311 for (j=0; j<NUM_ATTR_BYTES; j++) {
1312 p[mark++] = objectatts[i*NUM_ATTR_BYTES+j];
1314 for (j=0; j<6; j++) {
1317 case 0: /* next object in the linked list. */
1318 if (i == no_objects-1)
1321 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1323 case 1: /* hardware name address */
1324 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1326 case 2: /* property table address */
1327 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1329 case 3: /* parent */
1330 if (objectsg[i].parent == 0)
1333 val = Write_RAM_At + object_tree_at +
1334 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1336 case 4: /* sibling */
1337 if (objectsg[i].next == 0)
1340 val = Write_RAM_At + object_tree_at +
1341 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1344 if (objectsg[i].child == 0)
1347 val = Write_RAM_At + object_tree_at +
1348 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1351 p[mark++] = (val >> 24) & 0xFF;
1352 p[mark++] = (val >> 16) & 0xFF;
1353 p[mark++] = (val >> 8) & 0xFF;
1354 p[mark++] = (val) & 0xFF;
1357 for (j=0; j<GLULX_OBJECT_EXT_BYTES; j++) {
1362 if (object_props_at != mark)
1363 error("*** Object table was impossible length ***");
1365 for (i=0; i<properties_table_size; i++)
1366 p[mark+i]=properties_table[i];
1368 for (i=0; i<no_objects; i++) {
1369 int32 tableaddr = object_props_at + objectsg[i].propaddr;
1370 int32 tablelen = ReadInt32(p+tableaddr);
1372 for (j=0; j<tablelen; j++) {
1373 k = ReadInt32(p+tableaddr+4);
1374 k += (Write_RAM_At + object_props_at);
1375 WriteInt32(p+tableaddr+4, k);
1380 mark += properties_table_size;
1382 prop_defaults_at = mark;
1383 for (i=0; i<no_properties; i++) {
1384 k = prop_default_value[i];
1385 WriteInt32(p+mark, k);
1389 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1391 class_numbers_offset = mark;
1392 for (i=0; i<no_classes; i++) {
1393 j = Write_RAM_At + object_tree_at +
1394 (OBJECT_BYTE_LENGTH*(class_object_numbers[i]-1));
1395 WriteInt32(p+mark, j);
1398 WriteInt32(p+mark, 0);
1401 /* -------------------- Table of Property Names ------------------------ */
1403 /* We try to format this bit with some regularity...
1404 address of common properties
1405 number of common properties
1406 address of indiv properties
1407 number of indiv properties (counted from INDIV_PROP_START)
1408 address of attributes
1409 number of attributes (always NUM_ATTR_BYTES*8)
1414 identifier_names_offset = mark;
1415 mark += 32; /* eight pairs of values, to be filled in. */
1417 WriteInt32(p+identifier_names_offset+0, Write_RAM_At + mark);
1418 WriteInt32(p+identifier_names_offset+4, no_properties);
1419 for (i=0; i<no_properties; i++) {
1420 j = individual_name_strings[i];
1422 j = Write_Strings_At + compressed_offsets[j-1];
1423 WriteInt32(p+mark, j);
1427 WriteInt32(p+identifier_names_offset+8, Write_RAM_At + mark);
1428 WriteInt32(p+identifier_names_offset+12,
1429 no_individual_properties-INDIV_PROP_START);
1430 for (i=INDIV_PROP_START; i<no_individual_properties; i++) {
1431 j = individual_name_strings[i];
1433 j = Write_Strings_At + compressed_offsets[j-1];
1434 WriteInt32(p+mark, j);
1438 WriteInt32(p+identifier_names_offset+16, Write_RAM_At + mark);
1439 WriteInt32(p+identifier_names_offset+20, NUM_ATTR_BYTES*8);
1440 for (i=0; i<NUM_ATTR_BYTES*8; i++) {
1441 j = attribute_name_strings[i];
1443 j = Write_Strings_At + compressed_offsets[j-1];
1444 WriteInt32(p+mark, j);
1448 WriteInt32(p+identifier_names_offset+24, Write_RAM_At + mark);
1449 WriteInt32(p+identifier_names_offset+28, no_actions + no_fake_actions);
1450 action_names_offset = mark;
1451 fake_action_names_offset = mark + 4*no_actions;
1452 for (i=0; i<no_actions + no_fake_actions; i++) {
1453 j = action_name_strings[i];
1455 j = Write_Strings_At + compressed_offsets[j-1];
1456 WriteInt32(p+mark, j);
1460 array_names_offset = mark;
1461 WriteInt32(p+mark, no_arrays);
1463 for (i=0; i<no_arrays; i++) {
1464 j = array_name_strings[i];
1466 j = Write_Strings_At + compressed_offsets[j-1];
1467 WriteInt32(p+mark, j);
1471 individuals_offset = mark;
1473 /* ------------------------ Grammar Table ----------------------------- */
1475 if (grammar_version_number != 2)
1476 { warning("This version of Inform is unable to produce the grammar \
1477 table format requested (producing number 2 format instead)");
1478 grammar_version_number = 2;
1481 grammar_table_at = mark;
1483 WriteInt32(p+mark, no_Inform_verbs);
1486 mark += no_Inform_verbs*4;
1488 for (i=0; i<no_Inform_verbs; i++) {
1489 j = mark + Write_RAM_At;
1490 WriteInt32(p+(grammar_table_at+4+i*4), j);
1491 p[mark++] = Inform_verbs[i].lines;
1492 for (j=0; j<Inform_verbs[i].lines; j++) {
1494 k = Inform_verbs[i].l[j];
1495 p[mark++] = grammar_lines[k++];
1496 p[mark++] = grammar_lines[k++];
1497 p[mark++] = grammar_lines[k++];
1499 tok = grammar_lines[k++];
1501 if (tok == 15) break;
1502 p[mark++] = grammar_lines[k++];
1503 p[mark++] = grammar_lines[k++];
1504 p[mark++] = grammar_lines[k++];
1505 p[mark++] = grammar_lines[k++];
1510 /* ------------------- Actions and Preactions ------------------------- */
1513 WriteInt32(p+mark, no_actions);
1515 mark += no_actions*4;
1516 /* Values to be written in later. */
1518 if (DICT_CHAR_SIZE != 1) {
1519 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1524 preactions_at = mark;
1525 adjectives_offset = mark;
1526 dictionary_offset = mark;
1528 /* ------------------------- Dictionary ------------------------------- */
1530 dictionary_at = mark;
1532 WriteInt32(dictionary+0, dict_entries);
1534 p[mark+i] = dictionary[i];
1536 for (i=0; i<dict_entries; i++) {
1537 k = 4 + i*DICT_ENTRY_BYTE_LENGTH;
1538 j = mark + 4 + final_dict_order[i]*DICT_ENTRY_BYTE_LENGTH;
1539 for (l=0; l<DICT_ENTRY_BYTE_LENGTH; l++)
1540 p[j++] = dictionary[k++];
1542 mark += 4 + dict_entries * DICT_ENTRY_BYTE_LENGTH;
1544 /* -------------------------- All Data -------------------------------- */
1546 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1547 while (mark % GPAGESIZE)
1552 Out_Size = Write_RAM_At + RAM_Size;
1555 /* --------------------------- Offsets -------------------------------- */
1557 dictionary_offset = Write_RAM_At + dictionary_at;
1558 variables_offset = Write_RAM_At + globals_at;
1559 arrays_offset = Write_RAM_At + arrays_at;
1560 actions_offset = Write_RAM_At + actions_at;
1561 preactions_offset = Write_RAM_At + preactions_at;
1562 prop_defaults_offset = Write_RAM_At + prop_defaults_at;
1563 object_tree_offset = Write_RAM_At + object_tree_at;
1564 prop_values_offset = Write_RAM_At + object_props_at;
1565 static_memory_offset = Write_RAM_At + grammar_table_at;
1566 grammar_table_offset = Write_RAM_At + grammar_table_at;
1567 abbreviations_offset = Write_RAM_At + abbrevs_at;
1569 code_offset = Write_Code_At;
1570 strings_offset = Write_Strings_At;
1572 /* --------------------------- The Header ----------------------------- */
1574 /* ------ Backpatch the machine, now that all information is in ------- */
1577 { backpatch_zmachine_image_g();
1579 mark = actions_at + 4;
1580 for (i=0; i<no_actions; i++) {
1581 j = action_byte_offset[i];
1582 if (OMIT_UNUSED_ROUTINES)
1583 j = df_stripped_address_for_address(j);
1585 WriteInt32(p+mark, j);
1589 for (l = 0; l<no_Inform_verbs; l++) {
1590 k = grammar_table_at + 4 + 4*l;
1591 i = ((p[k] << 24) | (p[k+1] << 16) | (p[k+2] << 8) | (p[k+3]));
1593 for (j = p[i++]; j>0; j--) {
1597 while (p[i] != 15) {
1598 topbits = (p[i]/0x40) & 3;
1599 value = ((p[i+1] << 24) | (p[i+2] << 16)
1600 | (p[i+3] << 8) | (p[i+4]));
1603 value = dictionary_offset + 4
1604 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1607 if (OMIT_UNUSED_ROUTINES)
1608 value = df_stripped_address_for_address(value);
1609 value += code_offset;
1612 WriteInt32(p+(i+1), value);
1621 /* ---- From here on, it's all reportage: construction is finished ---- */
1623 if (statistics_switch)
1624 { int32 k_long, rate; char *k_str="";
1625 k_long=(Out_Size/1024);
1626 if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
1627 else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
1628 if (strings_length == 0) rate = 0;
1629 else rate=strings_length*1000/total_chars_trans;
1632 %3d source code files %6d syntactic lines\n\
1633 %6d textual lines %8ld characters ",
1634 total_input_files, no_syntax_lines,
1635 total_source_line_count, (long int) total_chars_read);
1636 if (character_set_unicode) printf("(UTF-8)\n");
1637 else if (character_set_setting == 0) printf("(plain ASCII)\n");
1639 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1640 name_of_iso_set(character_set_setting));
1644 write_serial_number(serialnum);
1645 printf("Allocated:\n\
1646 %6d symbols (maximum %4d) %8ld bytes of memory\n\
1647 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1648 no_symbols, MAX_SYMBOLS,
1649 (long int) malloced_bytes,
1650 version_name(version_number),
1653 serialnum[0], serialnum[1], serialnum[2],
1654 serialnum[3], serialnum[4], serialnum[5],
1655 (long int) k_long, k_str);
1659 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
1660 %6d global vars (maximum %3d) %6d variable/array space (maximum %d)\n",
1661 no_classes, MAX_CLASSES,
1662 no_objects, MAX_OBJECTS,
1663 no_globals, MAX_GLOBAL_VARIABLES,
1664 dynamic_array_area_size, MAX_STATIC_DATA);
1667 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
1668 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1669 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
1670 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1671 no_Inform_verbs, MAX_VERBS,
1672 dict_entries, MAX_DICT_ENTRIES,
1673 no_grammar_lines, grammar_version_number,
1675 no_actions, MAX_ACTIONS,
1676 no_attributes, NUM_ATTR_BYTES*8,
1677 no_properties, INDIV_PROP_START,
1678 no_individual_properties - INDIV_PROP_START);
1680 if (track_unused_routines)
1682 uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping;
1684 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1685 (long int) df_total_size_before_stripping, (long int) diff,
1686 (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"),
1687 100 * (float)diff / (float)df_total_size_before_stripping);
1691 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1692 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1693 %6ld instructions of code %6d sequence points\n\
1694 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1695 %6ld bytes used in machine %10ld bytes free in machine\n",
1696 (long int) total_chars_trans,
1697 (long int) strings_length,
1698 (total_chars_trans>strings_length)?0:1,
1700 no_abbreviations, MAX_ABBREVS,
1702 (long int) no_instructions, no_sequence_points,
1703 (long int) (Out_Size - Write_RAM_At),
1704 (long int) Write_RAM_At,
1705 (long int) Out_Size,
1707 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1715 "\nOffsets in %s:\n\
1716 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1717 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1718 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1720 (long int) abbrevs_at,
1721 (long int) prop_defaults_at,
1722 (long int) object_tree_at,
1723 (long int) object_props_at,
1724 (long int) globals_at,
1725 (long int) grammar_table_at,
1726 (long int) actions_at,
1727 (long int) preactions_at,
1728 (long int) adjectives_offset,
1729 (long int) dictionary_at,
1730 (long int) Write_Code_At,
1731 (long int) Write_Strings_At);
1735 if (debugfile_switch)
1736 { begin_writing_debug_sections();
1737 write_debug_section("memory layout id", GLULX_HEADER_SIZE);
1738 write_debug_section("code area", Write_Code_At);
1739 write_debug_section("string decoding table", Write_Strings_At);
1740 write_debug_section("strings area",
1741 Write_Strings_At + compression_table_size);
1742 if (Write_Strings_At + strings_length < Write_RAM_At)
1743 { write_debug_section
1744 ("zero padding", Write_Strings_At + strings_length);
1747 { compiler_error("Failed assumption that globals are at start of "
1750 write_debug_section("global variables", Write_RAM_At + globals_at);
1751 write_debug_section("array space", Write_RAM_At + arrays_at);
1752 write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at);
1753 write_debug_section("object tree", Write_RAM_At + object_tree_at);
1754 write_debug_section("common properties",
1755 Write_RAM_At + object_props_at);
1756 write_debug_section("property defaults",
1757 Write_RAM_At + prop_defaults_at);
1758 write_debug_section("class numbers",
1759 Write_RAM_At + class_numbers_offset);
1760 write_debug_section("identifier names",
1761 Write_RAM_At + identifier_names_offset);
1762 write_debug_section("grammar table", Write_RAM_At + grammar_table_at);
1763 write_debug_section("actions table", Write_RAM_At + actions_at);
1764 write_debug_section("dictionary", Write_RAM_At + dictionary_at);
1765 if (MEMORY_MAP_EXTENSION)
1766 { write_debug_section("zero padding", Out_Size);
1768 end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION);
1771 if (memory_map_switch)
1775 printf(" +---------------------+ 000000\n");
1776 printf("Read- | header |\n");
1777 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE);
1778 printf("memory | memory layout id |\n");
1779 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At);
1780 printf(" | code |\n");
1781 printf(" +---------------------+ %06lx\n",
1782 (long int) Write_Strings_At);
1783 printf(" | string decode table |\n");
1784 printf(" + - - - - - - - - - - + %06lx\n",
1785 (long int) Write_Strings_At + compression_table_size);
1786 printf(" | strings |\n");
1787 printf(" +=====================+ %06lx\n",
1788 (long int) (Write_RAM_At+globals_at));
1789 printf("Dynamic | global variables |\n");
1790 printf("memory + - - - - - - - - - - + %06lx\n",
1791 (long int) (Write_RAM_At+arrays_at));
1792 printf(" | arrays |\n");
1793 printf(" +---------------------+ %06lx\n",
1794 (long int) (Write_RAM_At+abbrevs_at));
1795 printf(" | printing variables |\n");
1796 if (alphabet_modified)
1798 printf(" + - - - - - - - - - - + %06lx\n",
1799 (long int) (Write_RAM_At+charset_at));
1800 printf(" | alphabets table |\n");
1802 if (zscii_defn_modified)
1804 printf(" + - - - - - - - - - - + %06lx\n",
1805 (long int) (Write_RAM_At+unicode_at));
1806 printf(" | Unicode table |\n");
1808 printf(" +---------------------+ %06lx\n",
1809 (long int) (Write_RAM_At+object_tree_at));
1810 printf(" | objects |\n");
1811 printf(" + - - - - - - - - - - + %06lx\n",
1812 (long int) (Write_RAM_At+object_props_at));
1813 printf(" | property values |\n");
1814 printf(" + - - - - - - - - - - + %06lx\n",
1815 (long int) (Write_RAM_At+prop_defaults_at));
1816 printf(" | property defaults |\n");
1817 printf(" + - - - - - - - - - - + %06lx\n",
1818 (long int) (Write_RAM_At+class_numbers_offset));
1819 printf(" | class numbers table |\n");
1820 printf(" + - - - - - - - - - - + %06lx\n",
1821 (long int) (Write_RAM_At+identifier_names_offset));
1822 printf(" | id names table |\n");
1823 printf(" +---------------------+ %06lx\n",
1824 (long int) (Write_RAM_At+grammar_table_at));
1825 printf(" | grammar table |\n");
1826 printf(" + - - - - - - - - - - + %06lx\n",
1827 (long int) (Write_RAM_At+actions_at));
1828 printf(" | actions |\n");
1829 printf(" +---------------------+ %06lx\n",
1830 (long int) dictionary_offset);
1831 printf(" | dictionary |\n");
1832 if (MEMORY_MAP_EXTENSION == 0)
1834 printf(" +---------------------+ %06lx\n", (long int) Out_Size);
1838 printf(" +=====================+ %06lx\n", (long int) Out_Size);
1839 printf("Runtime | (empty) |\n");
1840 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION);
1848 if (percentages_switch)
1849 { printf("Approximate percentage breakdown of %s:\n",
1851 percentage("Code", code_length,Out_Size);
1853 percentage("Linking data", link_data_size,Out_Size);
1854 percentage("Static strings", strings_length,Out_Size);
1855 percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size);
1856 percentage("Objects", globals_at-prop_defaults_at,Out_Size);
1857 percentage("Globals", grammar_table_at-globals_at,Out_Size);
1858 percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size);
1859 percentage("Header and synonyms", prop_defaults_at,Out_Size);
1860 percentage("Total of save area", grammar_table_at,Out_Size);
1861 percentage("Total of text", strings_length,Out_Size);
1863 if (frequencies_switch)
1865 { printf("How frequently abbreviations were used, and roughly\n");
1866 printf("how many bytes they saved: ('_' denotes spaces)\n");
1867 for (i=0; i<no_abbreviations; i++)
1868 { char abbrev_string[MAX_ABBREV_LENGTH];
1869 strcpy(abbrev_string,
1870 (char *)abbreviations_at+i*MAX_ABBREV_LENGTH);
1871 for (j=0; abbrev_string[j]!=0; j++)
1872 if (abbrev_string[j]==' ') abbrev_string[j]='_';
1873 printf("%10s %5d/%5d ",abbrev_string,abbrev_freqs[i],
1874 2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
1875 if ((i%3)==2) printf("\n");
1877 if ((i%3)!=0) printf("\n");
1878 if (no_abbreviations==0) printf("None were declared.\n");
1883 extern void construct_storyfile(void)
1886 construct_storyfile_z();
1888 construct_storyfile_g();
1891 /* ========================================================================= */
1892 /* Data structure management routines */
1893 /* ------------------------------------------------------------------------- */
1895 extern void init_tables_vars(void)
1898 statusline_flag = SCORE_STYLE;
1900 zmachine_paged_memory = NULL;
1903 code_offset = 0x800;
1904 actions_offset = 0x800;
1905 preactions_offset = 0x800;
1906 dictionary_offset = 0x800;
1907 adjectives_offset = 0x800;
1908 variables_offset = 0;
1909 strings_offset = 0xc00;
1910 individuals_offset=0x800;
1911 identifier_names_offset=0x800;
1912 class_numbers_offset = 0x800;
1913 arrays_offset = 0x0800; /* only used in Glulx, but might as well set */
1916 code_offset = 0x12345;
1917 actions_offset = 0x12345;
1918 preactions_offset = 0x12345;
1919 dictionary_offset = 0x12345;
1920 adjectives_offset = 0x12345;
1921 variables_offset = 0x12345;
1922 arrays_offset = 0x12345;
1923 strings_offset = 0x12345;
1924 individuals_offset=0x12345;
1925 identifier_names_offset=0x12345;
1926 class_numbers_offset = 0x12345;
1930 extern void tables_begin_pass(void)
1934 extern void tables_allocate_arrays(void)
1938 extern void tables_free_arrays(void)
1940 /* Allocation for this array happens in construct_storyfile() above */
1942 my_free(&zmachine_paged_memory,"output buffer");
1945 /* ========================================================================= */