1 /* ------------------------------------------------------------------------- */
2 /* "tables" : Constructs the story file or module (the output) up to the */
3 /* end of dynamic memory, gluing together all the required */
6 /* Part of Inform 6.33 */
7 /* copyright (c) Graham Nelson 1993 - 2014 */
9 /* ------------------------------------------------------------------------- */
13 uchar
*zmachine_paged_memory
; /* Where we shall store the story file
14 constructed (contains all of paged
15 memory, i.e. all but code and the
16 static strings: allocated only when
17 we know how large it needs to be,
18 at the end of the compilation pass */
20 /* In Glulx, zmachine_paged_memory contains all of RAM -- i.e. all but
21 the header, the code, and the static strings. */
23 /* ------------------------------------------------------------------------- */
24 /* Offsets of various areas in the Z-machine: these are set to nominal */
25 /* values before the compilation pass, and to their calculated final */
26 /* values only when construct_storyfile() happens. These are then used to */
27 /* backpatch the incorrect values now existing in the Z-machine which */
28 /* used these nominal values. */
29 /* Most of the nominal values are 0x800 because this is guaranteed to */
30 /* be assembled as a long constant if it's needed in code, since the */
31 /* largest possible value of scale_factor is 8 and 0x800/8 = 256. */
33 /* In Glulx, I use 0x12345 instead of 0x800. This will always be a long */
34 /* (32-bit) constant, since there's no scale_factor. */
35 /* ------------------------------------------------------------------------- */
46 identifier_names_offset
,
51 attribute_names_offset
,
53 fake_action_names_offset
,
55 constant_names_offset
,
56 routines_array_offset
,
57 constants_array_offset
,
58 routine_flags_array_offset
,
60 global_flags_array_offset
,
61 array_flags_array_offset
;
65 abbreviations_offset
; /* Glulx */
67 int32 Out_Size
, Write_Code_At
, Write_Strings_At
;
68 int32 RAM_Size
, Write_RAM_At
; /* Glulx */
70 /* ------------------------------------------------------------------------- */
71 /* Story file header settings. (Written to in "directs.c" and "asm.c".) */
72 /* ------------------------------------------------------------------------- */
74 int release_number
, /* Release number game is to have */
75 statusline_flag
, /* Either TIME_STYLE or SCORE_STYLE */
77 serial_code_given_in_program
; /* If TRUE, a Serial directive has */
78 char serial_code_buffer
[7]; /* specified this 6-digit serial code */
79 /* (overriding the usual date-stamp) */
80 int flags2_requirements
[16]; /* An array of which bits in Flags 2 of
81 the header will need to be set:
82 e.g. if the save_undo / restore_undo
83 opcodes are ever assembled, we have
84 to set the "games want UNDO" bit.
87 /* ------------------------------------------------------------------------- */
88 /* Construct story/module file (up to code area start). */
90 /* (To understand what follows, you really need to look at the run-time */
91 /* system's specification, the Z-Machine Standards document.) */
92 /* ------------------------------------------------------------------------- */
94 extern void write_serial_number(char *buffer
)
96 /* Note that this function may require modification for "ANSI" compilers
97 which do not provide the standard time functions: what is needed is
98 the ability to work out today's date */
100 time_t tt
; tt
=time(0);
101 if (serial_code_given_in_program
)
102 strcpy(buffer
, serial_code_buffer
);
104 #ifdef TIME_UNAVAILABLE
105 sprintf(buffer
,"970000");
107 strftime(buffer
,10,"%y%m%d",localtime(&tt
));
111 static void percentage(char *name
, int32 x
, int32 total
)
112 { printf(" %-20s %2d.%d%%\n",name
,x
*100/total
,(x
*1000/total
)%10);
115 static char *version_name(int v
)
119 { case 3: return "Standard";
120 case 4: return "Plus";
121 case 5: return "Advanced";
122 case 6: return "Graphical";
123 case 8: return "Extended";
125 return "experimental format";
132 static int32
rough_size_of_paged_memory_z(void)
134 /* This function calculates a modest over-estimate of the amount of
135 memory required to store the Z-machine's paged memory area
136 (that is, everything up to the start of the code area). */
142 total
= 64 /* header */
143 + 2 + subtract_pointers(low_strings_top
, low_strings
)
144 /* low strings pool */
145 + 6*32; /* abbreviations table */
147 total
+= 8; /* header extension table */
148 if (ZCODE_HEADER_EXT_WORDS
>3) total
+= (ZCODE_HEADER_EXT_WORDS
-3)*2;
150 if (alphabet_modified
) total
+= 78; /* character set table */
152 if (zscii_defn_modified
) /* Unicode translation table */
153 total
+= 2 + 2*zscii_high_water_mark
;
155 total
+= 2*((version_number
==3)?31:63) /* property default values */
156 + no_objects
*((version_number
==3)?9:14) /* object tree table */
157 + properties_table_size
/* property values of objects */
158 + (no_classes
+1)*(module_switch
?4:2)
159 /* class object numbers table */
160 + no_symbols
*2 /* names of numerous things */
161 + individuals_length
/* tables of prop variables */
162 + dynamic_array_area_size
; /* variables and arrays */
164 for (i
=0; i
<no_Inform_verbs
; i
++)
165 total
+= 2 + 1 + /* address of grammar table, */
166 /* number of grammar lines */
167 ((grammar_version_number
== 1)?
168 (8*Inform_verbs
[i
].lines
):0); /* grammar lines */
170 if (grammar_version_number
!= 1)
171 total
+= grammar_lines_top
; /* size of grammar lines area */
173 total
+= 2 + 4*no_adjectives
/* adjectives table */
174 + 2*no_actions
/* action routines */
175 + 2*no_grammar_token_routines
; /* general parsing routines */
177 total
+= (subtract_pointers(dictionary_top
, dictionary
)) /* dictionary */
178 + ((module_switch
)?30:0); /* module map */
180 total
+= scale_factor
*0x100 /* maximum null bytes before code */
181 + 1000; /* fudge factor (in case the above is wrong) */
186 static int32
rough_size_of_paged_memory_g(void)
188 /* This function calculates a modest over-estimate of the amount of
189 memory required to store the machine's paged memory area
190 (that is, everything up to the start of the code area). */
196 /* No header for us! */
197 total
= 1000; /* bit of a fudge factor */
199 total
+= dynamic_array_area_size
; /* arrays and global variables */
201 total
+= no_objects
* OBJECT_BYTE_LENGTH
; /* object tables */
202 total
+= properties_table_size
; /* property tables */
203 total
+= no_properties
* 4; /* property defaults table */
205 total
+= 4 + no_classes
* 4; /* class prototype object numbers */
207 total
+= 32; /* address/length of the identifier tables */
208 total
+= no_properties
* 4;
209 total
+= (no_individual_properties
-INDIV_PROP_START
) * 4;
210 total
+= (NUM_ATTR_BYTES
*8) * 4;
211 total
+= (no_actions
+ no_fake_actions
) * 4;
212 total
+= 4 + no_arrays
* 4;
214 total
+= 4 + no_Inform_verbs
* 4; /* index of grammar tables */
215 total
+= grammar_lines_top
; /* grammar tables */
217 total
+= 4 + no_actions
* 4; /* actions functions table */
220 total
+= subtract_pointers(dictionary_top
, dictionary
);
222 while (total
% GPAGESIZE
)
228 static void construct_storyfile_z(void)
230 int32 i
, j
, k
, l
, mark
, objs
, strings_length
, code_length
,
231 limit
, excess
, extend_offset
, headerext_length
;
232 int32 globals_at
, link_table_at
, dictionary_at
, actions_at
, preactions_at
,
233 abbrevs_at
, prop_defaults_at
, object_tree_at
, object_props_at
,
234 map_of_module
, grammar_table_at
, charset_at
, headerext_at
,
235 terminating_chars_at
, unicode_at
, id_names_length
;
236 int skip_backpatching
= FALSE
;
237 char *output_called
= (module_switch
)?"module":"story file";
241 individual_name_strings
=
242 my_calloc(sizeof(int32
), no_individual_properties
,
243 "identifier name strings");
244 action_name_strings
=
245 my_calloc(sizeof(int32
), no_actions
+ no_fake_actions
,
246 "action name strings");
247 attribute_name_strings
=
248 my_calloc(sizeof(int32
), 48,
249 "attribute name strings");
251 my_calloc(sizeof(int32
),
253 "array name strings");
255 write_the_identifier_names();
257 /* We now know how large the buffer to hold our construction has to be */
259 zmachine_paged_memory
= my_malloc(rough_size_of_paged_memory_z(),
262 /* Foolish code to make this routine compile on all ANSI compilers */
264 p
= (uchar
*) zmachine_paged_memory
;
266 /* In what follows, the "mark" will move upwards in memory: at various
267 points its value will be recorded for milestones like
268 "dictionary table start". It begins at 0x40, just after the header */
272 /* ----------------- Low Strings and Abbreviations -------------------- */
274 p
[mark
]=0x80; p
[mark
+1]=0; mark
+=2; /* Start the low strings pool
275 with a useful default string, " " */
277 for (i
=0; i
+low_strings
<low_strings_top
; mark
++, i
++) /* Low strings pool */
278 p
[0x42+i
]=low_strings
[i
];
281 for (i
=0; i
<3*32; i
++) /* Initially all 96 entries */
282 { p
[mark
++]=0; p
[mark
++]=0x20; /* are set to " " */
284 for (i
=0; i
<no_abbreviations
; i
++) /* Write any abbreviations */
285 { j
=abbrev_values
[i
]; /* into banks 2 and 3 */
286 p
[abbrevs_at
+64+2*i
]=j
/256; /* (bank 1 is reserved for */
287 p
[abbrevs_at
+65+2*i
]=j
%256; /* "variable strings") */
290 /* ------------------- Header extension table ------------------------- */
293 headerext_length
= ZCODE_HEADER_EXT_WORDS
;
294 if (zscii_defn_modified
) {
295 /* Need at least 3 words for unicode table address */
296 if (headerext_length
< 3)
297 headerext_length
= 3;
299 if (ZCODE_HEADER_FLAGS_3
) {
300 /* Need at least 4 words for the flags-3 field (ZSpec 1.1) */
301 if (headerext_length
< 4)
302 headerext_length
= 4;
304 p
[mark
++] = 0; p
[mark
++] = headerext_length
;
305 for (i
=0; i
<headerext_length
; i
++)
306 { p
[mark
++] = 0; p
[mark
++] = 0;
309 /* -------------------- Z-character set table ------------------------- */
311 if (alphabet_modified
)
313 for (i
=0;i
<3;i
++) for (j
=0;j
<26;j
++)
314 { if (alphabet
[i
][j
] == '~') p
[mark
++] = '\"';
315 else p
[mark
++] = alphabet
[i
][j
];
319 /* ------------------ Unicode translation table ----------------------- */
322 if (zscii_defn_modified
)
324 p
[mark
++] = zscii_high_water_mark
;
325 for (i
=0;i
<zscii_high_water_mark
;i
++)
326 { j
= zscii_to_unicode(155 + i
);
327 p
[mark
++] = j
/256; p
[mark
++] = j
%256;
331 /* -------------------- Objects and Properties ------------------------ */
333 prop_defaults_at
= mark
;
335 p
[mark
++]=0; p
[mark
++]=0;
337 for (i
=2; i
< ((version_number
==3)?32:64); i
++)
338 { p
[mark
++]=prop_default_value
[i
]/256;
339 p
[mark
++]=prop_default_value
[i
]%256;
342 object_tree_at
= mark
;
344 mark
+= ((version_number
==3)?9:14)*no_objects
;
346 object_props_at
= mark
;
348 for (i
=0; i
<properties_table_size
; i
++)
349 p
[mark
+i
]=properties_table
[i
];
351 for (i
=0, objs
=object_tree_at
; i
<no_objects
; i
++)
353 if (version_number
== 3)
354 { p
[objs
]=objectsz
[i
].atts
[0];
355 p
[objs
+1]=objectsz
[i
].atts
[1];
356 p
[objs
+2]=objectsz
[i
].atts
[2];
357 p
[objs
+3]=objectsz
[i
].atts
[3];
358 p
[objs
+4]=objectsz
[i
].parent
;
359 p
[objs
+5]=objectsz
[i
].next
;
360 p
[objs
+6]=objectsz
[i
].child
;
366 { p
[objs
]=objectsz
[i
].atts
[0];
367 p
[objs
+1]=objectsz
[i
].atts
[1];
368 p
[objs
+2]=objectsz
[i
].atts
[2];
369 p
[objs
+3]=objectsz
[i
].atts
[3];
370 p
[objs
+4]=objectsz
[i
].atts
[4];
371 p
[objs
+5]=objectsz
[i
].atts
[5];
372 p
[objs
+6]=(objectsz
[i
].parent
)/256;
373 p
[objs
+7]=(objectsz
[i
].parent
)%256;
374 p
[objs
+8]=(objectsz
[i
].next
)/256;
375 p
[objs
+9]=(objectsz
[i
].next
)%256;
376 p
[objs
+10]=(objectsz
[i
].child
)/256;
377 p
[objs
+11]=(objectsz
[i
].child
)%256;
379 { p
[objs
+12]=mark
/256;
383 { p
[objs
+12]=objectsz
[i
].propsize
/256;
384 p
[objs
+13]=objectsz
[i
].propsize
%256;
388 mark
+=objectsz
[i
].propsize
;
391 /* ----------- Table of Class Prototype Object Numbers ---------------- */
393 class_numbers_offset
= mark
;
394 for (i
=0; i
<no_classes
; i
++)
395 { p
[mark
++] = class_object_numbers
[i
]/256;
396 p
[mark
++] = class_object_numbers
[i
]%256;
398 { p
[mark
++] = class_begins_at
[i
]/256;
399 p
[mark
++] = class_begins_at
[i
]%256;
405 /* ------------------- Table of Identifier Names ---------------------- */
407 identifier_names_offset
= mark
;
410 { p
[mark
++] = no_individual_properties
/256;
411 p
[mark
++] = no_individual_properties
%256;
412 for (i
=1; i
<no_individual_properties
; i
++)
413 { p
[mark
++] = individual_name_strings
[i
]/256;
414 p
[mark
++] = individual_name_strings
[i
]%256;
417 attribute_names_offset
= mark
;
419 { p
[mark
++] = attribute_name_strings
[i
]/256;
420 p
[mark
++] = attribute_name_strings
[i
]%256;
423 action_names_offset
= mark
;
424 fake_action_names_offset
= mark
+ 2*no_actions
;
425 for (i
=0; i
<no_actions
+ no_fake_actions
; i
++)
426 { p
[mark
++] = action_name_strings
[i
]/256;
427 p
[mark
++] = action_name_strings
[i
]%256;
430 array_names_offset
= mark
;
431 global_names_offset
= mark
+ 2*no_arrays
;
432 routine_names_offset
= global_names_offset
+ 2*no_globals
;
433 constant_names_offset
= routine_names_offset
+ 2*no_named_routines
;
434 for (i
=0; i
<no_arrays
+ no_globals
435 + no_named_routines
+ no_named_constants
; i
++)
436 { if ((i
== no_arrays
) && (define_INFIX_switch
== FALSE
)) break;
437 p
[mark
++] = array_name_strings
[i
]/256;
438 p
[mark
++] = array_name_strings
[i
]%256;
441 id_names_length
= (mark
- identifier_names_offset
)/2;
443 routine_flags_array_offset
= mark
;
445 if (define_INFIX_switch
)
446 { for (i
=0, k
=1, l
=0; i
<no_named_routines
; i
++)
447 { if (sflags
[named_routine_symbols
[i
]] & STAR_SFLAG
) l
=l
+k
;
449 if (k
==256) { p
[mark
++] = l
; k
=1; l
=0; }
451 if (k
!=1) p
[mark
++]=l
;
454 /* ---------------- Table of Indiv Property Values -------------------- */
456 individuals_offset
= mark
;
457 for (i
=0; i
<individuals_length
; i
++)
458 p
[mark
++] = individuals_table
[i
];
460 /* ----------------- Variables and Dynamic Arrays --------------------- */
464 for (i
=0; i
<dynamic_array_area_size
; i
++)
465 p
[mark
++] = dynamic_array_area
[i
];
467 for (i
=0; i
<240; i
++)
468 { j
=global_initial_value
[i
];
469 p
[globals_at
+i
*2] = j
/256; p
[globals_at
+i
*2+1] = j
%256;
472 /* ------------------ Terminating Characters Table -------------------- */
474 if (version_number
>= 5)
475 { terminating_chars_at
= mark
;
476 for (i
=0; i
<no_termcs
; i
++) p
[mark
++] = terminating_characters
[i
];
480 /* ------------------------ Grammar Table ----------------------------- */
482 if (grammar_version_number
> 2)
483 { warning("This version of Inform is unable to produce the grammar \
484 table format requested (producing number 2 format instead)");
485 grammar_version_number
= 2;
488 grammar_table_at
= mark
;
490 mark
= mark
+ no_Inform_verbs
*2;
492 for (i
=0; i
<no_Inform_verbs
; i
++)
493 { p
[grammar_table_at
+ i
*2] = (mark
/256);
494 p
[grammar_table_at
+ i
*2 + 1] = (mark
%256);
495 p
[mark
++] = Inform_verbs
[i
].lines
;
496 for (j
=0; j
<Inform_verbs
[i
].lines
; j
++)
497 { k
= Inform_verbs
[i
].l
[j
];
498 if (grammar_version_number
== 1)
500 p
[mark
+7] = grammar_lines
[k
+1];
501 for (m
=1;m
<=6;m
++) p
[mark
+ m
] = 0;
502 k
= k
+ 2; m
= 1; n
= 0;
503 while ((grammar_lines
[k
] != 15) && (m
<=6))
504 { p
[mark
+ m
] = grammar_lines
[k
];
505 if (grammar_lines
[k
] < 180) n
++;
513 p
[mark
++] = grammar_lines
[k
++];
514 p
[mark
++] = grammar_lines
[k
++];
516 { tok
= grammar_lines
[k
++];
518 if (tok
== 15) break;
519 p
[mark
++] = grammar_lines
[k
++];
520 p
[mark
++] = grammar_lines
[k
++];
526 /* ------------------- Actions and Preactions ------------------------- */
527 /* (The term "preactions" is traditional: Inform uses the preactions */
528 /* table for a different purpose than Infocom used to.) */
529 /* The values are written later, when the Z-code offset is known. */
530 /* -------------------------------------------------------------------- */
533 mark
+= no_actions
*2;
535 preactions_at
= mark
;
536 if (grammar_version_number
== 1)
537 mark
+= no_grammar_token_routines
*2;
539 /* ----------------------- Adjectives Table --------------------------- */
541 if (grammar_version_number
== 1)
542 { p
[mark
]=0; p
[mark
+1]=no_adjectives
; mark
+=2; /* To assist "infodump" */
543 adjectives_offset
= mark
;
544 dictionary_offset
= mark
+ 4*no_adjectives
;
546 for (i
=0; i
<no_adjectives
; i
++)
547 { j
= final_dict_order
[adjectives
[no_adjectives
-i
-1]]
548 *((version_number
==3)?7:9)
549 + dictionary_offset
+ 7;
550 p
[mark
++]=j
/256; p
[mark
++]=j
%256; p
[mark
++]=0;
551 p
[mark
++]=(256-no_adjectives
+i
);
555 { p
[mark
]=0; p
[mark
+1]=0; mark
+=2;
556 adjectives_offset
= mark
;
557 dictionary_offset
= mark
;
560 /* ------------------------- Dictionary ------------------------------- */
564 dictionary
[0]=3; dictionary
[1]='.'; /* Non-space characters which */
565 dictionary
[2]=','; /* force words apart */
568 dictionary
[4]=(version_number
==3)?7:9; /* Length of each entry */
569 dictionary
[5]=(dict_entries
/256); /* Number of entries */
570 dictionary
[6]=(dict_entries
%256);
572 for (i
=0; i
<7; i
++) p
[mark
++] = dictionary
[i
];
574 for (i
=0; i
<dict_entries
; i
++)
575 { k
= 7 + i
*((version_number
==3)?7:9);
576 j
= mark
+ final_dict_order
[i
]*((version_number
==3)?7:9);
577 for (l
= 0; l
<((version_number
==3)?7:9); l
++)
578 p
[j
++] = dictionary
[k
++];
580 mark
+= dict_entries
* ((version_number
==3)?7:9);
582 /* ------------------------- Module Map ------------------------------- */
585 { map_of_module
= mark
; /* Filled in below */
589 /* ----------------- A gap before the code area ----------------------- */
590 /* (so that it will start at an exact packed address and so that all */
591 /* routine packed addresses are >= 256, hence long constants) */
592 /* -------------------------------------------------------------------- */
594 while ((mark
%length_scale_factor
) != 0) p
[mark
++]=0;
595 while (mark
< (scale_factor
*0x100)) p
[mark
++]=0;
596 if (oddeven_packing_switch
)
597 while ((mark
%(scale_factor
*2)) != 0) p
[mark
++]=0;
600 { error("This program has overflowed the maximum readable-memory \
601 size of the Z-machine format. See the memory map below: the start \
602 of the area marked \"above readable memory\" must be brought down to $FFFE \
604 memory_map_switch
= TRUE
;
605 /* Backpatching the grammar tables requires us to trust some of the */
606 /* addresses we've written into Z-machine memory, but they may have */
607 /* been truncated to 16 bits, so we can't do it. */
608 skip_backpatching
= TRUE
;
611 /* -------------------------- Code Area ------------------------------- */
612 /* (From this point on we don't write any more into the "p" buffer.) */
613 /* -------------------------------------------------------------------- */
615 Write_Code_At
= mark
;
616 if (!OMIT_UNUSED_ROUTINES
) {
617 code_length
= zmachine_pc
;
620 if (zmachine_pc
!= df_total_size_before_stripping
)
621 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
622 code_length
= df_total_size_after_stripping
;
626 /* ------------------ Another synchronising gap ----------------------- */
628 if (oddeven_packing_switch
)
630 while ((mark
%(scale_factor
*2)) != 0) mark
++;
632 while ((mark
%(scale_factor
*2)) != scale_factor
) mark
++;
635 while ((mark
%scale_factor
) != 0) mark
++;
637 /* ------------------------- Strings Area ----------------------------- */
639 Write_Strings_At
= mark
;
640 strings_length
= static_strings_extent
;
641 mark
+= strings_length
;
643 /* --------------------- Module Linking Data -------------------------- */
646 { link_table_at
= mark
; mark
+= link_data_size
;
647 mark
+= zcode_backpatch_size
;
648 mark
+= zmachine_backpatch_size
;
651 /* --------------------- Is the file too big? ------------------------- */
655 switch(version_number
)
656 { case 3: excess
= Out_Size
-((int32
) 0x20000L
); limit
= 128; break;
658 case 5: excess
= Out_Size
-((int32
) 0x40000L
); limit
= 256; break;
661 case 8: excess
= Out_Size
-((int32
) 0x80000L
); limit
= 512; break;
665 { excess
= Out_Size
-((int32
) 0x10000L
); limit
=64;
669 { char memory_full_error
[80];
670 sprintf(memory_full_error
,
671 "The %s exceeds version-%d limit (%dK) by %d bytes",
672 output_called
, version_number
, limit
, excess
);
673 fatalerror(memory_full_error
);
676 /* --------------------------- Offsets -------------------------------- */
678 dictionary_offset
= dictionary_at
;
679 variables_offset
= globals_at
;
680 actions_offset
= actions_at
;
681 preactions_offset
= preactions_at
;
682 prop_defaults_offset
= prop_defaults_at
;
683 prop_values_offset
= object_props_at
;
684 static_memory_offset
= grammar_table_at
;
685 grammar_table_offset
= grammar_table_at
;
687 if (extend_memory_map
)
689 if (no_objects
+9 > extend_offset
) extend_offset
=no_objects
+9;
690 while ((extend_offset
%length_scale_factor
) != 0) extend_offset
++;
691 /* Not sure why above line is necessary, but oddeven_packing
692 * will need extend_offset to be even */
693 code_offset
= extend_offset
*scale_factor
;
694 if (oddeven_packing_switch
)
695 strings_offset
= code_offset
+ scale_factor
;
697 strings_offset
= code_offset
+ (Write_Strings_At
-Write_Code_At
);
699 /* With the extended memory model, need to specifically check that we
700 * haven't overflowed the packed address range for routines or strings.
701 * With the standard memory model, we only need the earlier total size
704 excess
= code_length
+ code_offset
- (scale_factor
*((int32
) 0x10000L
));
706 { char code_full_error
[80];
707 sprintf(code_full_error
,
708 "The code area limit has been exceeded by %d bytes",
710 fatalerror(code_full_error
);
713 excess
= strings_length
+ strings_offset
- (scale_factor
*((int32
) 0x10000L
));
715 { char strings_full_error
[140];
716 if (oddeven_packing_switch
)
717 sprintf(strings_full_error
,
718 "The strings area limit has been exceeded by %d bytes",
721 sprintf(strings_full_error
,
722 "The code+strings area limit has been exceeded by %d bytes. \
723 Try running Inform again with -B on the command line.",
725 fatalerror(strings_full_error
);
729 { code_offset
= Write_Code_At
;
730 strings_offset
= Write_Strings_At
;
733 /* --------------------------- The Header ----------------------------- */
735 for (i
=0; i
<=0x3f; i
++) p
[i
]=0; /* Begin with 64 blank bytes */
737 p
[0] = version_number
; /* Version number */
738 p
[1] = statusline_flag
*2; /* Bit 1 of Flags 1: statusline style */
739 p
[2] = (release_number
/256);
740 p
[3] = (release_number
%256); /* Release */
741 p
[4] = (Write_Code_At
/256);
742 p
[5] = (Write_Code_At
%256); /* End of paged memory */
743 if (version_number
==6)
744 { j
=code_offset
/scale_factor
; /* Packed address of "Main__" */
745 p
[6]=(j
/256); p
[7]=(j
%256);
748 { j
=Write_Code_At
+1; /* Initial PC value (bytes) */
749 p
[6]=(j
/256); p
[7]=(j
%256); /* (first opcode in "Main__") */
751 p
[8] = (dictionary_at
/256); p
[9]=(dictionary_at
%256); /* Dictionary */
752 p
[10]=prop_defaults_at
/256; p
[11]=prop_defaults_at
%256; /* Objects */
753 p
[12]=(globals_at
/256); p
[13]=(globals_at
%256); /* Dynamic area */
754 p
[14]=(grammar_table_at
/256);
755 p
[15]=(grammar_table_at
%256); /* Grammar */
756 for (i
=0, j
=0, k
=1;i
<16;i
++, k
=k
*2) /* Flags 2 as needed for any */
757 j
+=k
*flags2_requirements
[i
]; /* unusual opcodes assembled */
758 p
[16]=j
/256; p
[17]=j
%256;
759 write_serial_number((char *) (p
+18)); /* Serial number: 6 chars of ASCII */
760 p
[24]=abbrevs_at
/256;
761 p
[25]=abbrevs_at
%256; /* Abbreviations table */
762 p
[26]=0; p
[27]=0; /* Length of file to be filled in "files.c" */
763 p
[28]=0; p
[29]=0; /* Checksum to be filled in "files.c" */
765 if (extend_memory_map
)
766 { j
=(Write_Code_At
- extend_offset
*scale_factor
)/length_scale_factor
;
767 p
[40]=j
/256; p
[41]=j
%256; /* Routines offset */
768 if (oddeven_packing_switch
)
769 j
=(Write_Strings_At
- extend_offset
*scale_factor
)/length_scale_factor
;
770 p
[42]=j
/256; p
[43]=j
%256; /* = Strings offset */
773 if (version_number
>= 5)
774 { p
[46] = terminating_chars_at
/256; /* Terminating characters table */
775 p
[47] = terminating_chars_at
%256;
778 if (alphabet_modified
)
780 p
[52]=j
/256; p
[53]=j
%256; } /* Character set table address */
783 p
[54] = j
/256; p
[55] = j
%256; /* Header extension table address */
785 p
[60] = '0' + ((RELEASE_NUMBER
/100)%10);
787 p
[62] = '0' + ((RELEASE_NUMBER
/10)%10);
788 p
[63] = '0' + RELEASE_NUMBER
%10;
790 /* ------------------------ Header Extension -------------------------- */
792 /* The numbering in the spec is a little weird -- it's headerext_length
793 words *after* the initial length word. We follow the spec numbering
794 in this switch statement, so the count is 1-based. */
795 for (i
=1; i
<=headerext_length
; i
++) {
798 j
= unicode_at
; /* Unicode translation table address */
801 j
= ZCODE_HEADER_FLAGS_3
; /* Flags 3 word */
807 p
[headerext_at
+2*i
+0] = j
/ 256;
808 p
[headerext_at
+2*i
+1] = j
% 256;
811 /* ----------------- The Header: Extras for modules ------------------- */
815 p
[1]=MODULE_VERSION_NUMBER
;
816 p
[6]=map_of_module
/256;
817 p
[7]=map_of_module
%256;
819 mark
= map_of_module
; /* Module map format: */
821 p
[mark
++]=object_tree_at
/256; /* 0: Object tree addr */
822 p
[mark
++]=object_tree_at
%256;
823 p
[mark
++]=object_props_at
/256; /* 2: Prop values addr */
824 p
[mark
++]=object_props_at
%256;
825 p
[mark
++]=(Write_Strings_At
/scale_factor
)/256; /* 4: Static strs */
826 p
[mark
++]=(Write_Strings_At
/scale_factor
)%256;
827 p
[mark
++]=class_numbers_offset
/256; /* 6: Class nos addr */
828 p
[mark
++]=class_numbers_offset
%256;
829 p
[mark
++]=individuals_offset
/256; /* 8: Indiv prop values */
830 p
[mark
++]=individuals_offset
%256;
831 p
[mark
++]=individuals_length
/256; /* 10: Length of table */
832 p
[mark
++]=individuals_length
%256;
833 p
[mark
++]=no_symbols
/256; /* 12: No of symbols */
834 p
[mark
++]=no_symbols
%256;
835 p
[mark
++]=no_individual_properties
/256; /* 14: Max property no */
836 p
[mark
++]=no_individual_properties
%256;
837 p
[mark
++]=no_objects
/256; /* 16: No of objects */
838 p
[mark
++]=no_objects
%256;
840 p
[mark
++]=i
/256; /* 18: Import/exports */
842 p
[mark
++]=link_data_size
/256; /* 20: Size of */
843 p
[mark
++]=link_data_size
%256;
845 p
[mark
++]=i
/256; /* 22: Code backpatch */
847 p
[mark
++]=zcode_backpatch_size
/256; /* 24: Size of */
848 p
[mark
++]=zcode_backpatch_size
%256;
849 i
+= zcode_backpatch_size
;
850 p
[mark
++]=i
/256; /* 26: Image backpatch */
852 p
[mark
++]=zmachine_backpatch_size
/256; /* 28: Size of */
853 p
[mark
++]=zmachine_backpatch_size
%256;
855 /* Further space in this table is reserved for future use */
858 /* ---- Backpatch the Z-machine, now that all information is in ------- */
860 if (!module_switch
&& !skip_backpatching
)
861 { backpatch_zmachine_image_z();
862 for (i
=1; i
<id_names_length
; i
++)
863 { int32 v
= 256*p
[identifier_names_offset
+ i
*2]
864 + p
[identifier_names_offset
+ i
*2 + 1];
865 if (v
!=0) v
+= strings_offset
/scale_factor
;
866 p
[identifier_names_offset
+ i
*2] = v
/256;
867 p
[identifier_names_offset
+ i
*2 + 1] = v
%256;
871 for (i
=0; i
<no_actions
; i
++)
872 { j
=action_byte_offset
[i
];
873 if (OMIT_UNUSED_ROUTINES
)
874 j
= df_stripped_address_for_address(j
);
875 j
+= code_offset
/scale_factor
;
876 p
[mark
++]=j
/256; p
[mark
++]=j
%256;
879 if (grammar_version_number
== 1)
880 { mark
= preactions_at
;
881 for (i
=0; i
<no_grammar_token_routines
; i
++)
882 { j
=grammar_token_routine
[i
];
883 if (OMIT_UNUSED_ROUTINES
)
884 j
= df_stripped_address_for_address(j
);
885 j
+= code_offset
/scale_factor
;
886 p
[mark
++]=j
/256; p
[mark
++]=j
%256;
890 { for (l
= 0; l
<no_Inform_verbs
; l
++)
891 { k
= grammar_table_at
+ 2*l
;
892 i
= p
[k
]*256 + p
[k
+1];
893 for (j
= p
[i
++]; j
>0; j
--)
894 { int topbits
; int32 value
;
897 { topbits
= (p
[i
]/0x40) & 3;
898 value
= p
[i
+1]*256 + p
[i
+2];
901 value
= final_dict_order
[value
]
902 *((version_number
==3)?7:9)
903 + dictionary_offset
+ 7;
906 if (OMIT_UNUSED_ROUTINES
)
907 value
= df_stripped_address_for_address(value
);
908 value
+= code_offset
/scale_factor
;
911 p
[i
+1] = value
/256; p
[i
+2] = value
%256;
920 /* ---- From here on, it's all reportage: construction is finished ---- */
922 if (statistics_switch
)
923 { int32 k_long
, rate
; char *k_str
="";
924 k_long
=(Out_Size
/1024);
925 if ((Out_Size
-1024*k_long
) >= 512) { k_long
++; k_str
=""; }
926 else if ((Out_Size
-1024*k_long
) > 0) { k_str
=".5"; }
927 if (total_bytes_trans
== 0) rate
= 0;
928 else rate
=total_bytes_trans
*1000/total_chars_trans
;
931 %3d source code files %6d syntactic lines\n\
932 %6d textual lines %8ld characters ",
933 input_file
, no_syntax_lines
,
934 total_source_line_count
, (long int) total_chars_read
);
935 if (character_set_unicode
) printf("(UTF-8)\n");
936 else if (character_set_setting
== 0) printf("(plain ASCII)\n");
938 { printf("(ISO 8859-%d %s)\n", character_set_setting
,
939 name_of_iso_set(character_set_setting
));
942 printf("Allocated:\n\
943 %6d symbols (maximum %4d) %8ld bytes of memory\n\
944 Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
945 no_symbols
, MAX_SYMBOLS
,
946 (long int) malloced_bytes
,
948 version_name(version_number
),
950 release_number
, p
[18], p
[19], p
[20], p
[21], p
[22], p
[23],
951 (long int) k_long
, k_str
);
954 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
955 %6d global vars (maximum 233) %6d variable/array space (maximum %d)\n",
956 no_classes
, MAX_CLASSES
,
957 no_objects
, ((version_number
==3)?255:(MAX_OBJECTS
-1)),
959 dynamic_array_area_size
, MAX_STATIC_DATA
);
962 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
963 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
964 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
965 %6d common props (maximum %2d) %6d individual props (unlimited)\n",
966 no_Inform_verbs
, MAX_VERBS
,
967 dict_entries
, MAX_DICT_ENTRIES
,
968 no_grammar_lines
, grammar_version_number
,
970 no_actions
, MAX_ACTIONS
,
971 no_attributes
, ((version_number
==3)?32:48),
972 no_properties
-2, ((version_number
==3)?30:62),
973 no_individual_properties
- 64);
975 if (track_unused_routines
)
977 uint32 diff
= df_total_size_before_stripping
- df_total_size_after_stripping
;
979 "%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n",
980 (long int) df_total_size_before_stripping
, (long int) diff
,
981 (OMIT_UNUSED_ROUTINES
? "stripped out" : "detected"),
982 100 * (float)diff
/ (float)df_total_size_before_stripping
);
986 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
987 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
988 %6ld instructions of Z-code %6d sequence points\n\
989 %6ld bytes readable memory used (maximum 65536)\n\
990 %6ld bytes used in Z-machine %6ld bytes free in Z-machine\n",
991 (long int) total_chars_trans
,
992 (long int) total_bytes_trans
,
993 (total_chars_trans
>total_bytes_trans
)?0:1,
995 no_abbreviations
, MAX_ABBREVS
,
997 (long int) no_instructions
, no_sequence_points
,
998 (long int) Write_Code_At
,
1001 (((long int) (limit
*1024L)) - ((long int) Out_Size
)));
1009 "\nOffsets in %s:\n\
1010 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1011 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1012 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1014 (long int) abbrevs_at
,
1015 (long int) prop_defaults_at
,
1016 (long int) object_tree_at
,
1017 (long int) object_props_at
,
1018 (long int) globals_at
,
1019 (long int) grammar_table_at
,
1020 (long int) actions_at
,
1021 (long int) preactions_at
,
1022 (long int) adjectives_offset
,
1023 (long int) dictionary_at
,
1024 (long int) Write_Code_At
,
1025 (long int) Write_Strings_At
);
1027 printf("%05lx Linking data\n",(long int) link_table_at
);
1031 if (debugfile_switch
)
1032 { begin_writing_debug_sections();
1033 write_debug_section("abbreviations", 64);
1034 write_debug_section("abbreviations table", abbrevs_at
);
1035 write_debug_section("header extension", headerext_at
);
1036 if (alphabet_modified
)
1037 { write_debug_section("alphabets table", charset_at
);
1039 if (zscii_defn_modified
)
1040 { write_debug_section("Unicode table", unicode_at
);
1042 write_debug_section("property defaults", prop_defaults_at
);
1043 write_debug_section("object tree", object_tree_at
);
1044 write_debug_section("common properties", object_props_at
);
1045 write_debug_section("class numbers", class_numbers_offset
);
1046 write_debug_section("identifier names", identifier_names_offset
);
1047 write_debug_section("individual properties", individuals_offset
);
1048 write_debug_section("global variables", globals_at
);
1049 write_debug_section("array space", globals_at
+480);
1050 write_debug_section("grammar table", grammar_table_at
);
1051 write_debug_section("actions table", actions_at
);
1052 write_debug_section("parsing routines", preactions_at
);
1053 write_debug_section("adjectives table", adjectives_offset
);
1054 write_debug_section("dictionary", dictionary_at
);
1055 write_debug_section("code area", Write_Code_At
);
1056 write_debug_section("strings area", Write_Strings_At
);
1057 end_writing_debug_sections(Out_Size
);
1060 if (memory_map_switch
)
1063 printf("Dynamic +---------------------+ 00000\n");
1064 printf("memory | header |\n");
1065 printf(" +---------------------+ 00040\n");
1066 printf(" | abbreviations |\n");
1067 printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at
);
1068 printf(" | abbreviations table |\n");
1069 printf(" +---------------------+ %05lx\n", (long int) headerext_at
);
1070 printf(" | header extension |\n");
1071 if (alphabet_modified
)
1073 printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at
);
1074 printf(" | alphabets table |\n");
1076 if (zscii_defn_modified
)
1078 printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at
);
1079 printf(" | Unicode table |\n");
1081 printf(" +---------------------+ %05lx\n",
1082 (long int) prop_defaults_at
);
1083 printf(" | property defaults |\n");
1084 printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at
);
1085 printf(" | objects |\n");
1086 printf(" + - - - - - - - - - - + %05lx\n",
1087 (long int) object_props_at
);
1088 printf(" | object short names, |\n");
1089 printf(" | common prop values |\n");
1090 printf(" + - - - - - - - - - - + %05lx\n",
1091 (long int) class_numbers_offset
);
1092 printf(" | class numbers table |\n");
1093 printf(" + - - - - - - - - - - + %05lx\n",
1094 (long int) identifier_names_offset
);
1095 printf(" | symbol names table |\n");
1096 printf(" + - - - - - - - - - - + %05lx\n",
1097 (long int) individuals_offset
);
1098 printf(" | indiv prop values |\n");
1099 printf(" +---------------------+ %05lx\n", (long int) globals_at
);
1100 printf(" | global variables |\n");
1101 printf(" + - - - - - - - - - - + %05lx\n",
1102 ((long int) globals_at
)+480L);
1103 printf(" | arrays |\n");
1104 printf(" +=====================+ %05lx\n",
1105 (long int) grammar_table_at
);
1106 printf("Readable| grammar table |\n");
1107 printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at
);
1108 printf(" | actions |\n");
1109 printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at
);
1110 printf(" | parsing routines |\n");
1111 printf(" + - - - - - - - - - - + %05lx\n",
1112 (long int) adjectives_offset
);
1113 printf(" | adjectives |\n");
1114 printf(" +---------------------+ %05lx\n", (long int) dictionary_at
);
1115 printf(" | dictionary |\n");
1118 printf(" + - - - - - - - - - - + %05lx\n",
1119 (long int) map_of_module
);
1120 printf(" | map of module addrs |\n");
1122 printf(" +=====================+ %05lx\n", (long int) Write_Code_At
);
1123 printf("Above | Z-code |\n");
1124 printf("readable+---------------------+ %05lx\n",
1125 (long int) Write_Strings_At
);
1126 printf("memory | strings |\n");
1129 printf(" +=====================+ %05lx\n", (long int) link_table_at
);
1130 printf(" | module linking data |\n");
1132 printf(" +---------------------+ %05lx\n", (long int) Out_Size
);
1135 if (percentages_switch
)
1136 { printf("Approximate percentage breakdown of %s:\n",
1138 percentage("Z-code", code_length
,Out_Size
);
1140 percentage("Linking data", link_data_size
,Out_Size
);
1141 percentage("Static strings", strings_length
,Out_Size
);
1142 percentage("Dictionary", Write_Code_At
-dictionary_at
,Out_Size
);
1143 percentage("Objects", globals_at
-prop_defaults_at
,Out_Size
);
1144 percentage("Globals", grammar_table_at
-globals_at
,Out_Size
);
1145 percentage("Parsing tables", dictionary_at
-grammar_table_at
,Out_Size
);
1146 percentage("Header and synonyms", prop_defaults_at
,Out_Size
);
1147 percentage("Total of save area", grammar_table_at
,Out_Size
);
1148 percentage("Total of text", total_bytes_trans
,Out_Size
);
1150 if (frequencies_switch
)
1152 { printf("How frequently abbreviations were used, and roughly\n");
1153 printf("how many bytes they saved: ('_' denotes spaces)\n");
1154 for (i
=0; i
<no_abbreviations
; i
++)
1155 { char abbrev_string
[64];
1156 strcpy(abbrev_string
,
1157 (char *)abbreviations_at
+i
*MAX_ABBREV_LENGTH
);
1158 for (j
=0; abbrev_string
[j
]!=0; j
++)
1159 if (abbrev_string
[j
]==' ') abbrev_string
[j
]='_';
1160 printf("%10s %5d/%5d ",abbrev_string
,abbrev_freqs
[i
],
1161 2*((abbrev_freqs
[i
]-1)*abbrev_quality
[i
])/3);
1162 if ((i
%3)==2) printf("\n");
1164 if ((i
%3)!=0) printf("\n");
1165 if (no_abbreviations
==0) printf("None were declared.\n");
1170 static void construct_storyfile_g(void)
1172 int32 i
, j
, k
, l
, mark
, strings_length
, limit
;
1173 int32 globals_at
, dictionary_at
, actions_at
, preactions_at
,
1174 abbrevs_at
, prop_defaults_at
, object_tree_at
, object_props_at
,
1175 grammar_table_at
, charset_at
, headerext_at
,
1176 unicode_at
, arrays_at
;
1177 int32 threespaces
, code_length
;
1178 char *output_called
= (module_switch
)?"module":"story file";
1182 individual_name_strings
=
1183 my_calloc(sizeof(int32
), no_individual_properties
,
1184 "identifier name strings");
1185 action_name_strings
=
1186 my_calloc(sizeof(int32
), no_actions
+ no_fake_actions
,
1187 "action name strings");
1188 attribute_name_strings
=
1189 my_calloc(sizeof(int32
), NUM_ATTR_BYTES
*8,
1190 "attribute name strings");
1191 array_name_strings
=
1192 my_calloc(sizeof(int32
),
1194 "array name strings");
1196 write_the_identifier_names();
1197 threespaces
= compile_string(" ", FALSE
, FALSE
);
1199 compress_game_text();
1201 /* We now know how large the buffer to hold our construction has to be */
1203 zmachine_paged_memory
= my_malloc(rough_size_of_paged_memory_g(),
1206 /* Foolish code to make this routine compile on all ANSI compilers */
1208 p
= (uchar
*) zmachine_paged_memory
;
1210 /* In what follows, the "mark" will move upwards in memory: at various
1211 points its value will be recorded for milestones like
1212 "dictionary table start". It begins at 0x40, just after the header */
1214 /* Ok, our policy here will be to set the *_at values all relative
1215 to RAM. That's so we can write into zmachine_paged_memory[mark]
1216 and actually hit what we're aiming at.
1217 All the *_offset values will be set to true Glulx machine
1220 /* To get our bearings, figure out where the strings and code are. */
1221 /* We start with two words, which conventionally identify the
1222 memory layout. This is why the code starts eight bytes after
1224 Write_Code_At
= GLULX_HEADER_SIZE
+ GLULX_STATIC_ROM_SIZE
;
1225 if (!OMIT_UNUSED_ROUTINES
) {
1226 code_length
= zmachine_pc
;
1229 if (zmachine_pc
!= df_total_size_before_stripping
)
1230 compiler_error("Code size does not match (zmachine_pc and df_total_size).");
1231 code_length
= df_total_size_after_stripping
;
1233 Write_Strings_At
= Write_Code_At
+ code_length
;
1234 strings_length
= compression_table_size
+ compression_string_size
;
1236 /* Now figure out where RAM starts. */
1237 Write_RAM_At
= Write_Strings_At
+ strings_length
;
1238 /* The Write_RAM_At boundary must be a multiple of GPAGESIZE. */
1239 while (Write_RAM_At
% GPAGESIZE
)
1242 /* Now work out all those RAM positions. */
1245 /* ----------------- Variables and Dynamic Arrays --------------------- */
1248 for (i
=0; i
<no_globals
; i
++) {
1249 j
= global_initial_value
[i
];
1250 WriteInt32(p
+mark
, j
);
1255 for (i
=MAX_GLOBAL_VARIABLES
*4; i
<dynamic_array_area_size
; i
++)
1256 p
[mark
++] = dynamic_array_area
[i
];
1258 /* -------------------------- Dynamic Strings -------------------------- */
1261 WriteInt32(p
+mark
, no_dynamic_strings
);
1263 for (i
=0; i
<no_dynamic_strings
; i
++) {
1264 j
= Write_Strings_At
+ compressed_offsets
[threespaces
-1];
1265 WriteInt32(p
+mark
, j
);
1269 /* ---------------- Various Things I'm Not Sure About ------------------ */
1270 /* Actually, none of these are relevant to Glulx. */
1271 headerext_at
= mark
;
1272 if (alphabet_modified
)
1275 if (zscii_defn_modified
)
1278 /* -------------------- Objects and Properties ------------------------ */
1280 object_tree_at
= mark
;
1282 object_props_at
= mark
+ no_objects
*OBJECT_BYTE_LENGTH
;
1284 for (i
=0; i
<no_objects
; i
++) {
1285 int32 objmark
= mark
;
1286 p
[mark
++] = 0x70; /* type byte -- object */
1287 for (j
=0; j
<NUM_ATTR_BYTES
; j
++) {
1288 p
[mark
++] = objectatts
[i
*NUM_ATTR_BYTES
+j
];
1290 for (j
=0; j
<6; j
++) {
1293 case 0: /* next object in the linked list. */
1294 if (i
== no_objects
-1)
1297 val
= Write_RAM_At
+ objmark
+ OBJECT_BYTE_LENGTH
;
1299 case 1: /* hardware name address */
1300 val
= Write_Strings_At
+ compressed_offsets
[objectsg
[i
].shortname
-1];
1302 case 2: /* property table address */
1303 val
= Write_RAM_At
+ object_props_at
+ objectsg
[i
].propaddr
;
1305 case 3: /* parent */
1306 if (objectsg
[i
].parent
== 0)
1309 val
= Write_RAM_At
+ object_tree_at
+
1310 (OBJECT_BYTE_LENGTH
*(objectsg
[i
].parent
-1));
1312 case 4: /* sibling */
1313 if (objectsg
[i
].next
== 0)
1316 val
= Write_RAM_At
+ object_tree_at
+
1317 (OBJECT_BYTE_LENGTH
*(objectsg
[i
].next
-1));
1320 if (objectsg
[i
].child
== 0)
1323 val
= Write_RAM_At
+ object_tree_at
+
1324 (OBJECT_BYTE_LENGTH
*(objectsg
[i
].child
-1));
1327 p
[mark
++] = (val
>> 24) & 0xFF;
1328 p
[mark
++] = (val
>> 16) & 0xFF;
1329 p
[mark
++] = (val
>> 8) & 0xFF;
1330 p
[mark
++] = (val
) & 0xFF;
1333 for (j
=0; j
<GLULX_OBJECT_EXT_BYTES
; j
++) {
1338 if (object_props_at
!= mark
)
1339 error("*** Object table was impossible length ***");
1341 for (i
=0; i
<properties_table_size
; i
++)
1342 p
[mark
+i
]=properties_table
[i
];
1344 for (i
=0; i
<no_objects
; i
++) {
1345 int32 tableaddr
= object_props_at
+ objectsg
[i
].propaddr
;
1346 int32 tablelen
= ReadInt32(p
+tableaddr
);
1348 for (j
=0; j
<tablelen
; j
++) {
1349 k
= ReadInt32(p
+tableaddr
+4);
1350 k
+= (Write_RAM_At
+ object_props_at
);
1351 WriteInt32(p
+tableaddr
+4, k
);
1356 mark
+= properties_table_size
;
1358 prop_defaults_at
= mark
;
1359 for (i
=0; i
<no_properties
; i
++) {
1360 k
= prop_default_value
[i
];
1361 WriteInt32(p
+mark
, k
);
1365 /* ----------- Table of Class Prototype Object Numbers ---------------- */
1367 class_numbers_offset
= mark
;
1368 for (i
=0; i
<no_classes
; i
++) {
1369 j
= Write_RAM_At
+ object_tree_at
+
1370 (OBJECT_BYTE_LENGTH
*(class_object_numbers
[i
]-1));
1371 WriteInt32(p
+mark
, j
);
1374 WriteInt32(p
+mark
, 0);
1377 /* -------------------- Table of Property Names ------------------------ */
1379 /* We try to format this bit with some regularity...
1380 address of common properties
1381 number of common properties
1382 address of indiv properties
1383 number of indiv properties (counted from INDIV_PROP_START)
1384 address of attributes
1385 number of attributes (always NUM_ATTR_BYTES*8)
1390 identifier_names_offset
= mark
;
1391 mark
+= 32; /* eight pairs of values, to be filled in. */
1393 WriteInt32(p
+identifier_names_offset
+0, Write_RAM_At
+ mark
);
1394 WriteInt32(p
+identifier_names_offset
+4, no_properties
);
1395 for (i
=0; i
<no_properties
; i
++) {
1396 j
= individual_name_strings
[i
];
1398 j
= Write_Strings_At
+ compressed_offsets
[j
-1];
1399 WriteInt32(p
+mark
, j
);
1403 WriteInt32(p
+identifier_names_offset
+8, Write_RAM_At
+ mark
);
1404 WriteInt32(p
+identifier_names_offset
+12,
1405 no_individual_properties
-INDIV_PROP_START
);
1406 for (i
=INDIV_PROP_START
; i
<no_individual_properties
; i
++) {
1407 j
= individual_name_strings
[i
];
1409 j
= Write_Strings_At
+ compressed_offsets
[j
-1];
1410 WriteInt32(p
+mark
, j
);
1414 WriteInt32(p
+identifier_names_offset
+16, Write_RAM_At
+ mark
);
1415 WriteInt32(p
+identifier_names_offset
+20, NUM_ATTR_BYTES
*8);
1416 for (i
=0; i
<NUM_ATTR_BYTES
*8; i
++) {
1417 j
= attribute_name_strings
[i
];
1419 j
= Write_Strings_At
+ compressed_offsets
[j
-1];
1420 WriteInt32(p
+mark
, j
);
1424 WriteInt32(p
+identifier_names_offset
+24, Write_RAM_At
+ mark
);
1425 WriteInt32(p
+identifier_names_offset
+28, no_actions
+ no_fake_actions
);
1426 action_names_offset
= mark
;
1427 fake_action_names_offset
= mark
+ 4*no_actions
;
1428 for (i
=0; i
<no_actions
+ no_fake_actions
; i
++) {
1429 j
= action_name_strings
[i
];
1431 j
= Write_Strings_At
+ compressed_offsets
[j
-1];
1432 WriteInt32(p
+mark
, j
);
1436 array_names_offset
= mark
;
1437 WriteInt32(p
+mark
, no_arrays
);
1439 for (i
=0; i
<no_arrays
; i
++) {
1440 j
= array_name_strings
[i
];
1442 j
= Write_Strings_At
+ compressed_offsets
[j
-1];
1443 WriteInt32(p
+mark
, j
);
1447 individuals_offset
= mark
;
1449 /* ------------------------ Grammar Table ----------------------------- */
1451 if (grammar_version_number
!= 2)
1452 { warning("This version of Inform is unable to produce the grammar \
1453 table format requested (producing number 2 format instead)");
1454 grammar_version_number
= 2;
1457 grammar_table_at
= mark
;
1459 WriteInt32(p
+mark
, no_Inform_verbs
);
1462 mark
+= no_Inform_verbs
*4;
1464 for (i
=0; i
<no_Inform_verbs
; i
++) {
1465 j
= mark
+ Write_RAM_At
;
1466 WriteInt32(p
+(grammar_table_at
+4+i
*4), j
);
1467 p
[mark
++] = Inform_verbs
[i
].lines
;
1468 for (j
=0; j
<Inform_verbs
[i
].lines
; j
++) {
1470 k
= Inform_verbs
[i
].l
[j
];
1471 p
[mark
++] = grammar_lines
[k
++];
1472 p
[mark
++] = grammar_lines
[k
++];
1473 p
[mark
++] = grammar_lines
[k
++];
1475 tok
= grammar_lines
[k
++];
1477 if (tok
== 15) break;
1478 p
[mark
++] = grammar_lines
[k
++];
1479 p
[mark
++] = grammar_lines
[k
++];
1480 p
[mark
++] = grammar_lines
[k
++];
1481 p
[mark
++] = grammar_lines
[k
++];
1486 /* ------------------- Actions and Preactions ------------------------- */
1489 WriteInt32(p
+mark
, no_actions
);
1491 mark
+= no_actions
*4;
1492 /* Values to be written in later. */
1494 if (DICT_CHAR_SIZE
!= 1) {
1495 /* If the dictionary is Unicode, we'd like it to be word-aligned. */
1500 preactions_at
= mark
;
1501 adjectives_offset
= mark
;
1502 dictionary_offset
= mark
;
1504 /* ------------------------- Dictionary ------------------------------- */
1506 dictionary_at
= mark
;
1508 WriteInt32(dictionary
+0, dict_entries
);
1510 p
[mark
+i
] = dictionary
[i
];
1512 for (i
=0; i
<dict_entries
; i
++) {
1513 k
= 4 + i
*DICT_ENTRY_BYTE_LENGTH
;
1514 j
= mark
+ 4 + final_dict_order
[i
]*DICT_ENTRY_BYTE_LENGTH
;
1515 for (l
=0; l
<DICT_ENTRY_BYTE_LENGTH
; l
++)
1516 p
[j
++] = dictionary
[k
++];
1518 mark
+= 4 + dict_entries
* DICT_ENTRY_BYTE_LENGTH
;
1520 /* -------------------------- All Data -------------------------------- */
1522 /* The end-of-RAM boundary must be a multiple of GPAGESIZE. */
1523 while (mark
% GPAGESIZE
)
1528 Out_Size
= Write_RAM_At
+ RAM_Size
;
1531 /* --------------------------- Offsets -------------------------------- */
1533 dictionary_offset
= Write_RAM_At
+ dictionary_at
;
1534 variables_offset
= Write_RAM_At
+ globals_at
;
1535 arrays_offset
= Write_RAM_At
+ arrays_at
;
1536 actions_offset
= Write_RAM_At
+ actions_at
;
1537 preactions_offset
= Write_RAM_At
+ preactions_at
;
1538 prop_defaults_offset
= Write_RAM_At
+ prop_defaults_at
;
1539 object_tree_offset
= Write_RAM_At
+ object_tree_at
;
1540 prop_values_offset
= Write_RAM_At
+ object_props_at
;
1541 static_memory_offset
= Write_RAM_At
+ grammar_table_at
;
1542 grammar_table_offset
= Write_RAM_At
+ grammar_table_at
;
1543 abbreviations_offset
= Write_RAM_At
+ abbrevs_at
;
1545 code_offset
= Write_Code_At
;
1546 strings_offset
= Write_Strings_At
;
1548 /* --------------------------- The Header ----------------------------- */
1550 /* ------ Backpatch the machine, now that all information is in ------- */
1553 { backpatch_zmachine_image_g();
1555 mark
= actions_at
+ 4;
1556 for (i
=0; i
<no_actions
; i
++) {
1557 j
= action_byte_offset
[i
];
1558 if (OMIT_UNUSED_ROUTINES
)
1559 j
= df_stripped_address_for_address(j
);
1561 WriteInt32(p
+mark
, j
);
1565 for (l
= 0; l
<no_Inform_verbs
; l
++) {
1566 k
= grammar_table_at
+ 4 + 4*l
;
1567 i
= ((p
[k
] << 24) | (p
[k
+1] << 16) | (p
[k
+2] << 8) | (p
[k
+3]));
1569 for (j
= p
[i
++]; j
>0; j
--) {
1573 while (p
[i
] != 15) {
1574 topbits
= (p
[i
]/0x40) & 3;
1575 value
= ((p
[i
+1] << 24) | (p
[i
+2] << 16)
1576 | (p
[i
+3] << 8) | (p
[i
+4]));
1579 value
= dictionary_offset
+ 4
1580 + final_dict_order
[value
]*DICT_ENTRY_BYTE_LENGTH
;
1583 if (OMIT_UNUSED_ROUTINES
)
1584 value
= df_stripped_address_for_address(value
);
1585 value
+= code_offset
;
1588 WriteInt32(p
+(i
+1), value
);
1597 /* ---- From here on, it's all reportage: construction is finished ---- */
1599 if (statistics_switch
)
1600 { int32 k_long
, rate
; char *k_str
="";
1601 k_long
=(Out_Size
/1024);
1602 if ((Out_Size
-1024*k_long
) >= 512) { k_long
++; k_str
=""; }
1603 else if ((Out_Size
-1024*k_long
) > 0) { k_str
=".5"; }
1604 if (strings_length
== 0) rate
= 0;
1605 else rate
=strings_length
*1000/total_chars_trans
;
1608 %3d source code files %6d syntactic lines\n\
1609 %6d textual lines %8ld characters ",
1610 input_file
, no_syntax_lines
,
1611 total_source_line_count
, (long int) total_chars_read
);
1612 if (character_set_unicode
) printf("(UTF-8)\n");
1613 else if (character_set_setting
== 0) printf("(plain ASCII)\n");
1615 { printf("(ISO 8859-%d %s)\n", character_set_setting
,
1616 name_of_iso_set(character_set_setting
));
1620 write_serial_number(serialnum
);
1621 printf("Allocated:\n\
1622 %6d symbols (maximum %4d) %8ld bytes of memory\n\
1623 Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n",
1624 no_symbols
, MAX_SYMBOLS
,
1625 (long int) malloced_bytes
,
1626 version_name(version_number
),
1629 serialnum
[0], serialnum
[1], serialnum
[2],
1630 serialnum
[3], serialnum
[4], serialnum
[5],
1631 (long int) k_long
, k_str
);
1635 %6d classes (maximum %3d) %6d objects (maximum %3d)\n\
1636 %6d global vars (maximum %3d) %6d variable/array space (maximum %d)\n",
1637 no_classes
, MAX_CLASSES
,
1638 no_objects
, MAX_OBJECTS
,
1639 no_globals
, MAX_GLOBAL_VARIABLES
,
1640 dynamic_array_area_size
, MAX_STATIC_DATA
);
1643 "%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\
1644 %6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\
1645 %6d actions (maximum %3d) %6d attributes (maximum %2d)\n\
1646 %6d common props (maximum %3d) %6d individual props (unlimited)\n",
1647 no_Inform_verbs
, MAX_VERBS
,
1648 dict_entries
, MAX_DICT_ENTRIES
,
1649 no_grammar_lines
, grammar_version_number
,
1651 no_actions
, MAX_ACTIONS
,
1652 no_attributes
, NUM_ATTR_BYTES
*8,
1653 no_properties
, INDIV_PROP_START
,
1654 no_individual_properties
- INDIV_PROP_START
);
1656 if (track_unused_routines
)
1658 uint32 diff
= df_total_size_before_stripping
- df_total_size_after_stripping
;
1660 "%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n",
1661 (long int) df_total_size_before_stripping
, (long int) diff
,
1662 (OMIT_UNUSED_ROUTINES
? "stripped out" : "detected"),
1663 100 * (float)diff
/ (float)df_total_size_before_stripping
);
1667 "%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\
1668 %6d abbreviations (maximum %d) %6d routines (unlimited)\n\
1669 %6ld instructions of code %6d sequence points\n\
1670 %6ld bytes writable memory used %6ld bytes read-only memory used\n\
1671 %6ld bytes used in machine %10ld bytes free in machine\n",
1672 (long int) total_chars_trans
,
1673 (long int) strings_length
,
1674 (total_chars_trans
>strings_length
)?0:1,
1676 no_abbreviations
, MAX_ABBREVS
,
1678 (long int) no_instructions
, no_sequence_points
,
1679 (long int) (Out_Size
- Write_RAM_At
),
1680 (long int) Write_RAM_At
,
1681 (long int) Out_Size
,
1683 (((long int) (limit
*1024L)) - ((long int) Out_Size
)));
1691 "\nOffsets in %s:\n\
1692 %05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\
1693 %05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\
1694 %05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n",
1696 (long int) abbrevs_at
,
1697 (long int) prop_defaults_at
,
1698 (long int) object_tree_at
,
1699 (long int) object_props_at
,
1700 (long int) globals_at
,
1701 (long int) grammar_table_at
,
1702 (long int) actions_at
,
1703 (long int) preactions_at
,
1704 (long int) adjectives_offset
,
1705 (long int) dictionary_at
,
1706 (long int) Write_Code_At
,
1707 (long int) Write_Strings_At
);
1711 if (debugfile_switch
)
1712 { begin_writing_debug_sections();
1713 write_debug_section("memory layout id", GLULX_HEADER_SIZE
);
1714 write_debug_section("code area", Write_Code_At
);
1715 write_debug_section("string decoding table", Write_Strings_At
);
1716 write_debug_section("strings area",
1717 Write_Strings_At
+ compression_table_size
);
1718 if (Write_Strings_At
+ strings_length
< Write_RAM_At
)
1719 { write_debug_section
1720 ("zero padding", Write_Strings_At
+ strings_length
);
1723 { compiler_error("Failed assumption that globals are at start of "
1726 write_debug_section("global variables", Write_RAM_At
+ globals_at
);
1727 write_debug_section("array space", Write_RAM_At
+ arrays_at
);
1728 write_debug_section("abbreviations table", Write_RAM_At
+ abbrevs_at
);
1729 write_debug_section("object tree", Write_RAM_At
+ object_tree_at
);
1730 write_debug_section("common properties",
1731 Write_RAM_At
+ object_props_at
);
1732 write_debug_section("property defaults",
1733 Write_RAM_At
+ prop_defaults_at
);
1734 write_debug_section("class numbers",
1735 Write_RAM_At
+ class_numbers_offset
);
1736 write_debug_section("identifier names",
1737 Write_RAM_At
+ identifier_names_offset
);
1738 write_debug_section("grammar table", Write_RAM_At
+ grammar_table_at
);
1739 write_debug_section("actions table", Write_RAM_At
+ actions_at
);
1740 write_debug_section("dictionary", Write_RAM_At
+ dictionary_at
);
1741 if (MEMORY_MAP_EXTENSION
)
1742 { write_debug_section("zero padding", Out_Size
);
1744 end_writing_debug_sections(Out_Size
+ MEMORY_MAP_EXTENSION
);
1747 if (memory_map_switch
)
1751 printf(" +---------------------+ 000000\n");
1752 printf("Read- | header |\n");
1753 printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE
);
1754 printf("memory | memory layout id |\n");
1755 printf(" +---------------------+ %06lx\n", (long int) Write_Code_At
);
1756 printf(" | code |\n");
1757 printf(" +---------------------+ %06lx\n",
1758 (long int) Write_Strings_At
);
1759 printf(" | string decode table |\n");
1760 printf(" + - - - - - - - - - - + %06lx\n",
1761 (long int) Write_Strings_At
+ compression_table_size
);
1762 printf(" | strings |\n");
1763 printf(" +=====================+ %06lx\n",
1764 (long int) (Write_RAM_At
+globals_at
));
1765 printf("Dynamic | global variables |\n");
1766 printf("memory + - - - - - - - - - - + %06lx\n",
1767 (long int) (Write_RAM_At
+arrays_at
));
1768 printf(" | arrays |\n");
1769 printf(" +---------------------+ %06lx\n",
1770 (long int) (Write_RAM_At
+abbrevs_at
));
1771 printf(" | printing variables |\n");
1772 if (alphabet_modified
)
1774 printf(" + - - - - - - - - - - + %06lx\n",
1775 (long int) (Write_RAM_At
+charset_at
));
1776 printf(" | alphabets table |\n");
1778 if (zscii_defn_modified
)
1780 printf(" + - - - - - - - - - - + %06lx\n",
1781 (long int) (Write_RAM_At
+unicode_at
));
1782 printf(" | Unicode table |\n");
1784 printf(" +---------------------+ %06lx\n",
1785 (long int) (Write_RAM_At
+object_tree_at
));
1786 printf(" | objects |\n");
1787 printf(" + - - - - - - - - - - + %06lx\n",
1788 (long int) (Write_RAM_At
+object_props_at
));
1789 printf(" | property values |\n");
1790 printf(" + - - - - - - - - - - + %06lx\n",
1791 (long int) (Write_RAM_At
+prop_defaults_at
));
1792 printf(" | property defaults |\n");
1793 printf(" + - - - - - - - - - - + %06lx\n",
1794 (long int) (Write_RAM_At
+class_numbers_offset
));
1795 printf(" | class numbers table |\n");
1796 printf(" + - - - - - - - - - - + %06lx\n",
1797 (long int) (Write_RAM_At
+identifier_names_offset
));
1798 printf(" | id names table |\n");
1799 printf(" +---------------------+ %06lx\n",
1800 (long int) (Write_RAM_At
+grammar_table_at
));
1801 printf(" | grammar table |\n");
1802 printf(" + - - - - - - - - - - + %06lx\n",
1803 (long int) (Write_RAM_At
+actions_at
));
1804 printf(" | actions |\n");
1805 printf(" +---------------------+ %06lx\n",
1806 (long int) dictionary_offset
);
1807 printf(" | dictionary |\n");
1808 if (MEMORY_MAP_EXTENSION
== 0)
1810 printf(" +---------------------+ %06lx\n", (long int) Out_Size
);
1814 printf(" +=====================+ %06lx\n", (long int) Out_Size
);
1815 printf("Runtime | (empty) |\n");
1816 printf(" extn +---------------------+ %06lx\n", (long int) Out_Size
+MEMORY_MAP_EXTENSION
);
1824 if (percentages_switch
)
1825 { printf("Approximate percentage breakdown of %s:\n",
1827 percentage("Code", code_length
,Out_Size
);
1829 percentage("Linking data", link_data_size
,Out_Size
);
1830 percentage("Static strings", strings_length
,Out_Size
);
1831 percentage("Dictionary", Write_Code_At
-dictionary_at
,Out_Size
);
1832 percentage("Objects", globals_at
-prop_defaults_at
,Out_Size
);
1833 percentage("Globals", grammar_table_at
-globals_at
,Out_Size
);
1834 percentage("Parsing tables", dictionary_at
-grammar_table_at
,Out_Size
);
1835 percentage("Header and synonyms", prop_defaults_at
,Out_Size
);
1836 percentage("Total of save area", grammar_table_at
,Out_Size
);
1837 percentage("Total of text", strings_length
,Out_Size
);
1839 if (frequencies_switch
)
1841 { printf("How frequently abbreviations were used, and roughly\n");
1842 printf("how many bytes they saved: ('_' denotes spaces)\n");
1843 for (i
=0; i
<no_abbreviations
; i
++)
1844 { char abbrev_string
[64];
1845 strcpy(abbrev_string
,
1846 (char *)abbreviations_at
+i
*MAX_ABBREV_LENGTH
);
1847 for (j
=0; abbrev_string
[j
]!=0; j
++)
1848 if (abbrev_string
[j
]==' ') abbrev_string
[j
]='_';
1849 printf("%10s %5d/%5d ",abbrev_string
,abbrev_freqs
[i
],
1850 2*((abbrev_freqs
[i
]-1)*abbrev_quality
[i
])/3);
1851 if ((i
%3)==2) printf("\n");
1853 if ((i
%3)!=0) printf("\n");
1854 if (no_abbreviations
==0) printf("None were declared.\n");
1859 extern void construct_storyfile(void)
1862 construct_storyfile_z();
1864 construct_storyfile_g();
1867 /* ========================================================================= */
1868 /* Data structure management routines */
1869 /* ------------------------------------------------------------------------- */
1871 extern void init_tables_vars(void)
1873 serial_code_given_in_program
= FALSE
;
1875 statusline_flag
= SCORE_STYLE
;
1877 zmachine_paged_memory
= NULL
;
1880 code_offset
= 0x800;
1881 actions_offset
= 0x800;
1882 preactions_offset
= 0x800;
1883 dictionary_offset
= 0x800;
1884 adjectives_offset
= 0x800;
1885 variables_offset
= 0;
1886 strings_offset
= 0xc00;
1887 individuals_offset
=0x800;
1888 identifier_names_offset
=0x800;
1889 class_numbers_offset
= 0x800;
1890 arrays_offset
= 0x0800; /* only used in Glulx, but might as well set */
1893 code_offset
= 0x12345;
1894 actions_offset
= 0x12345;
1895 preactions_offset
= 0x12345;
1896 dictionary_offset
= 0x12345;
1897 adjectives_offset
= 0x12345;
1898 variables_offset
= 0x12345;
1899 arrays_offset
= 0x12345;
1900 strings_offset
= 0x12345;
1901 individuals_offset
=0x12345;
1902 identifier_names_offset
=0x12345;
1903 class_numbers_offset
= 0x12345;
1907 extern void tables_begin_pass(void)
1911 extern void tables_allocate_arrays(void)
1915 extern void tables_free_arrays(void)
1917 /* Allocation for this array happens in construct_storyfile() above */
1919 my_free(&zmachine_paged_memory
,"output buffer");
1922 /* ========================================================================= */