Imported Upstream version 6.33
[debian_inform6-compiler.git] / tables.c
blob0f7f485268a691e3efd784392863c8c04051b19d
1 /* ------------------------------------------------------------------------- */
2 /* "tables" : Constructs the story file or module (the output) up to the */
3 /* end of dynamic memory, gluing together all the required */
4 /* tables. */
5 /* */
6 /* Part of Inform 6.33 */
7 /* copyright (c) Graham Nelson 1993 - 2014 */
8 /* */
9 /* ------------------------------------------------------------------------- */
11 #include "header.h"
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. */
32 /* */
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 /* ------------------------------------------------------------------------- */
37 int32 code_offset,
38 actions_offset,
39 preactions_offset,
40 dictionary_offset,
41 adjectives_offset,
42 variables_offset,
43 strings_offset,
44 class_numbers_offset,
45 individuals_offset,
46 identifier_names_offset,
47 array_names_offset,
48 prop_defaults_offset,
49 prop_values_offset,
50 static_memory_offset,
51 attribute_names_offset,
52 action_names_offset,
53 fake_action_names_offset,
54 routine_names_offset,
55 constant_names_offset,
56 routines_array_offset,
57 constants_array_offset,
58 routine_flags_array_offset,
59 global_names_offset,
60 global_flags_array_offset,
61 array_flags_array_offset;
62 int32 arrays_offset,
63 object_tree_offset,
64 grammar_table_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.
85 Values are 0 or 1. */
87 /* ------------------------------------------------------------------------- */
88 /* Construct story/module file (up to code area start). */
89 /* */
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);
103 else
104 #ifdef TIME_UNAVAILABLE
105 sprintf(buffer,"970000");
106 #else
107 strftime(buffer,10,"%y%m%d",localtime(&tt));
108 #endif
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)
117 if (!glulx_mode) {
118 switch(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";
127 else {
128 return "Glulx";
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). */
138 int32 total, i;
140 ASSERT_ZCODE();
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) */
183 return(total);
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). */
192 int32 total;
194 ASSERT_GLULX();
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 */
219 total += 4;
220 total += subtract_pointers(dictionary_top, dictionary);
222 while (total % GPAGESIZE)
223 total++;
225 return(total);
228 static void construct_storyfile_z(void)
229 { uchar *p;
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";
239 ASSERT_ZCODE();
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");
250 array_name_strings =
251 my_calloc(sizeof(int32),
252 no_symbols,
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(),
260 "output buffer");
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 */
270 mark = 0x40;
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];
280 abbrevs_at = mark;
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 ------------------------- */
292 headerext_at = mark;
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)
312 { charset_at = mark;
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 ----------------------- */
321 unicode_at = 0;
322 if (zscii_defn_modified)
323 { unicode_at = mark;
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;
361 p[objs+7]=mark/256;
362 p[objs+8]=mark%256;
363 objs+=9;
365 else
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;
378 if (!module_switch)
379 { p[objs+12]=mark/256;
380 p[objs+13]=mark%256;
382 else
383 { p[objs+12]=objectsz[i].propsize/256;
384 p[objs+13]=objectsz[i].propsize%256;
386 objs+=14;
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;
397 if (module_switch)
398 { p[mark++] = class_begins_at[i]/256;
399 p[mark++] = class_begins_at[i]%256;
402 p[mark++] = 0;
403 p[mark++] = 0;
405 /* ------------------- Table of Identifier Names ---------------------- */
407 identifier_names_offset = mark;
409 if (!module_switch)
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;
418 for (i=0; i<48; i++)
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;
448 k=k*2;
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 --------------------- */
462 globals_at = mark;
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];
477 p[mark++] = 0;
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)
499 { int m, n;
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++;
506 m++; k = k + 3;
508 p[mark] = n;
509 mark = mark + 8;
511 else
512 { int tok;
513 p[mark++] = grammar_lines[k++];
514 p[mark++] = grammar_lines[k++];
515 for (;;)
516 { tok = grammar_lines[k++];
517 p[mark++] = tok;
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 /* -------------------------------------------------------------------- */
532 actions_at = mark;
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);
554 else
555 { p[mark]=0; p[mark+1]=0; mark+=2;
556 adjectives_offset = mark;
557 dictionary_offset = mark;
560 /* ------------------------- Dictionary ------------------------------- */
562 dictionary_at=mark;
564 dictionary[0]=3; dictionary[1]='.'; /* Non-space characters which */
565 dictionary[2]=','; /* force words apart */
566 dictionary[3]='"';
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 ------------------------------- */
584 if (module_switch)
585 { map_of_module = mark; /* Filled in below */
586 mark += 30;
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;
599 if (mark > 0x0FFFE)
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 \
603 or less.");
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;
619 else {
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;
624 mark += code_length;
626 /* ------------------ Another synchronising gap ----------------------- */
628 if (oddeven_packing_switch)
629 { if (module_switch)
630 while ((mark%(scale_factor*2)) != 0) mark++;
631 else
632 while ((mark%(scale_factor*2)) != scale_factor) mark++;
634 else
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 -------------------------- */
645 if (module_switch)
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? ------------------------- */
653 Out_Size = mark;
655 switch(version_number)
656 { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break;
657 case 4:
658 case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break;
659 case 6:
660 case 7:
661 case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break;
664 if (module_switch)
665 { excess = Out_Size-((int32) 0x10000L); limit=64;
668 if (excess > 0)
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)
688 { extend_offset=256;
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;
696 else
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
702 * check.
704 excess = code_length + code_offset - (scale_factor*((int32) 0x10000L));
705 if (excess > 0)
706 { char code_full_error[80];
707 sprintf(code_full_error,
708 "The code area limit has been exceeded by %d bytes",
709 excess);
710 fatalerror(code_full_error);
713 excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L));
714 if (excess > 0)
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",
719 excess);
720 else
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.",
724 excess);
725 fatalerror(strings_full_error);
728 else
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);
747 else
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)
779 { j = charset_at;
780 p[52]=j/256; p[53]=j%256; } /* Character set table address */
782 j = headerext_at;
783 p[54] = j/256; p[55] = j%256; /* Header extension table address */
785 p[60] = '0' + ((RELEASE_NUMBER/100)%10);
786 p[61] = '.';
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++) {
796 switch (i) {
797 case 3:
798 j = unicode_at; /* Unicode translation table address */
799 break;
800 case 4:
801 j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */
802 break;
803 default:
804 j = 0;
805 break;
807 p[headerext_at+2*i+0] = j / 256;
808 p[headerext_at+2*i+1] = j % 256;
811 /* ----------------- The Header: Extras for modules ------------------- */
813 if (module_switch)
814 { p[0]=p[0]+64;
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;
839 i = link_table_at;
840 p[mark++]=i/256; /* 18: Import/exports */
841 p[mark++]=i%256;
842 p[mark++]=link_data_size/256; /* 20: Size of */
843 p[mark++]=link_data_size%256;
844 i += link_data_size;
845 p[mark++]=i/256; /* 22: Code backpatch */
846 p[mark++]=i%256;
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 */
851 p[mark++]=i%256;
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;
870 mark = actions_at;
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;
889 else
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;
895 i = i + 2;
896 while (p[i] != 15)
897 { topbits = (p[i]/0x40) & 3;
898 value = p[i+1]*256 + p[i+2];
899 switch(topbits)
900 { case 1:
901 value = final_dict_order[value]
902 *((version_number==3)?7:9)
903 + dictionary_offset + 7;
904 break;
905 case 2:
906 if (OMIT_UNUSED_ROUTINES)
907 value = df_stripped_address_for_address(value);
908 value += code_offset/scale_factor;
909 break;
911 p[i+1] = value/256; p[i+2] = value%256;
912 i = i + 3;
914 i++;
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;
930 { printf("In:\
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");
937 else
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,
947 version_number,
948 version_name(version_number),
949 output_called,
950 release_number, p[18], p[19], p[20], p[21], p[22], p[23],
951 (long int) k_long, k_str);
953 printf("\
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)),
958 no_globals,
959 dynamic_array_area_size, MAX_STATIC_DATA);
961 printf(
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,
969 no_grammar_tokens,
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;
978 printf(
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);
985 printf(
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,
994 (long int) rate,
995 no_abbreviations, MAX_ABBREVS,
996 no_routines,
997 (long int) no_instructions, no_sequence_points,
998 (long int) Write_Code_At,
999 (long int) Out_Size,
1000 (long int)
1001 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1006 if (offsets_switch)
1008 { printf(
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",
1013 output_called,
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);
1026 if (module_switch)
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");
1116 if (module_switch)
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");
1127 if (module_switch)
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",
1137 output_called);
1138 percentage("Z-code", code_length,Out_Size);
1139 if (module_switch)
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)
1171 { uchar *p;
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";
1180 ASSERT_GLULX();
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),
1193 no_symbols,
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(),
1204 "output buffer");
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
1218 addresses. */
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
1223 the header. */
1224 Write_Code_At = GLULX_HEADER_SIZE + GLULX_STATIC_ROM_SIZE;
1225 if (!OMIT_UNUSED_ROUTINES) {
1226 code_length = zmachine_pc;
1228 else {
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)
1240 Write_RAM_At++;
1242 /* Now work out all those RAM positions. */
1243 mark = 0;
1245 /* ----------------- Variables and Dynamic Arrays --------------------- */
1247 globals_at = mark;
1248 for (i=0; i<no_globals; i++) {
1249 j = global_initial_value[i];
1250 WriteInt32(p+mark, j);
1251 mark += 4;
1254 arrays_at = mark;
1255 for (i=MAX_GLOBAL_VARIABLES*4; i<dynamic_array_area_size; i++)
1256 p[mark++] = dynamic_array_area[i];
1258 /* -------------------------- Dynamic Strings -------------------------- */
1260 abbrevs_at = mark;
1261 WriteInt32(p+mark, no_dynamic_strings);
1262 mark += 4;
1263 for (i=0; i<no_dynamic_strings; i++) {
1264 j = Write_Strings_At + compressed_offsets[threespaces-1];
1265 WriteInt32(p+mark, j);
1266 mark += 4;
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)
1273 charset_at = mark;
1274 unicode_at = 0;
1275 if (zscii_defn_modified)
1276 unicode_at = mark;
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++) {
1291 int32 val;
1292 switch (j) {
1293 case 0: /* next object in the linked list. */
1294 if (i == no_objects-1)
1295 val = 0;
1296 else
1297 val = Write_RAM_At + objmark + OBJECT_BYTE_LENGTH;
1298 break;
1299 case 1: /* hardware name address */
1300 val = Write_Strings_At + compressed_offsets[objectsg[i].shortname-1];
1301 break;
1302 case 2: /* property table address */
1303 val = Write_RAM_At + object_props_at + objectsg[i].propaddr;
1304 break;
1305 case 3: /* parent */
1306 if (objectsg[i].parent == 0)
1307 val = 0;
1308 else
1309 val = Write_RAM_At + object_tree_at +
1310 (OBJECT_BYTE_LENGTH*(objectsg[i].parent-1));
1311 break;
1312 case 4: /* sibling */
1313 if (objectsg[i].next == 0)
1314 val = 0;
1315 else
1316 val = Write_RAM_At + object_tree_at +
1317 (OBJECT_BYTE_LENGTH*(objectsg[i].next-1));
1318 break;
1319 case 5: /* child */
1320 if (objectsg[i].child == 0)
1321 val = 0;
1322 else
1323 val = Write_RAM_At + object_tree_at +
1324 (OBJECT_BYTE_LENGTH*(objectsg[i].child-1));
1325 break;
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++) {
1334 p[mark++] = 0;
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);
1347 tableaddr += 4;
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);
1352 tableaddr += 10;
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);
1362 mark += 4;
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);
1372 mark += 4;
1374 WriteInt32(p+mark, 0);
1375 mark += 4;
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)
1386 address of actions
1387 number of actions
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];
1397 if (j)
1398 j = Write_Strings_At + compressed_offsets[j-1];
1399 WriteInt32(p+mark, j);
1400 mark += 4;
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];
1408 if (j)
1409 j = Write_Strings_At + compressed_offsets[j-1];
1410 WriteInt32(p+mark, j);
1411 mark += 4;
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];
1418 if (j)
1419 j = Write_Strings_At + compressed_offsets[j-1];
1420 WriteInt32(p+mark, j);
1421 mark += 4;
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];
1430 if (j)
1431 j = Write_Strings_At + compressed_offsets[j-1];
1432 WriteInt32(p+mark, j);
1433 mark += 4;
1436 array_names_offset = mark;
1437 WriteInt32(p+mark, no_arrays);
1438 mark += 4;
1439 for (i=0; i<no_arrays; i++) {
1440 j = array_name_strings[i];
1441 if (j)
1442 j = Write_Strings_At + compressed_offsets[j-1];
1443 WriteInt32(p+mark, j);
1444 mark += 4;
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);
1460 mark += 4;
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++) {
1469 int tok;
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++];
1474 for (;;) {
1475 tok = grammar_lines[k++];
1476 p[mark++] = tok;
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 ------------------------- */
1488 actions_at = mark;
1489 WriteInt32(p+mark, no_actions);
1490 mark += 4;
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. */
1496 while (mark % 4)
1497 p[mark++]=0;
1500 preactions_at = mark;
1501 adjectives_offset = mark;
1502 dictionary_offset = mark;
1504 /* ------------------------- Dictionary ------------------------------- */
1506 dictionary_at = mark;
1508 WriteInt32(dictionary+0, dict_entries);
1509 for (i=0; i<4; i++)
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)
1524 p[mark++]=0;
1526 RAM_Size = mark;
1528 Out_Size = Write_RAM_At + RAM_Size;
1529 limit=1024*1024;
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 ------- */
1552 if (!module_switch)
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);
1560 j += code_offset;
1561 WriteInt32(p+mark, j);
1562 mark += 4;
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]));
1568 i -= Write_RAM_At;
1569 for (j = p[i++]; j>0; j--) {
1570 int topbits;
1571 int32 value;
1572 i = i + 3;
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]));
1577 switch(topbits) {
1578 case 1:
1579 value = dictionary_offset + 4
1580 + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH;
1581 break;
1582 case 2:
1583 if (OMIT_UNUSED_ROUTINES)
1584 value = df_stripped_address_for_address(value);
1585 value += code_offset;
1586 break;
1588 WriteInt32(p+(i+1), value);
1589 i = i + 5;
1591 i++;
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;
1607 { printf("In:\
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");
1614 else
1615 { printf("(ISO 8859-%d %s)\n", character_set_setting,
1616 name_of_iso_set(character_set_setting));
1619 {char serialnum[8];
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),
1627 output_called,
1628 release_number,
1629 serialnum[0], serialnum[1], serialnum[2],
1630 serialnum[3], serialnum[4], serialnum[5],
1631 (long int) k_long, k_str);
1634 printf("\
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);
1642 printf(
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,
1650 no_grammar_tokens,
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;
1659 printf(
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);
1666 printf(
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,
1675 (long int) rate,
1676 no_abbreviations, MAX_ABBREVS,
1677 no_routines,
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,
1682 (long int)
1683 (((long int) (limit*1024L)) - ((long int) Out_Size)));
1688 if (offsets_switch)
1690 { printf(
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",
1695 output_called,
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);
1722 if (globals_at)
1723 { compiler_error("Failed assumption that globals are at start of "
1724 "Glulx RAM");
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);
1812 else
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",
1826 output_called);
1827 percentage("Code", code_length,Out_Size);
1828 if (module_switch)
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)
1861 if (!glulx_mode)
1862 construct_storyfile_z();
1863 else
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;
1874 release_number = 1;
1875 statusline_flag = SCORE_STYLE;
1877 zmachine_paged_memory = NULL;
1879 if (!glulx_mode) {
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 */
1892 else {
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 /* ========================================================================= */