08d4e946f2c5ebff89cd2ec93724a839d6be19f6
[rocksndiamonds.git] / build-scripts / create_element_defs.pl
1 #!/usr/bin/perl -w
2
3 # =============================================================================
4 # Rocks'n'Diamonds - McDuffin Strikes Back!
5 # -----------------------------------------------------------------------------
6 # (c) 1995-2014 by Artsoft Entertainment
7 #                  Holger Schemel
8 #                  info@artsoft.org
9 #                  https://www.artsoft.org/
10 # -----------------------------------------------------------------------------
11 # create_element_defs.pl
12 # =============================================================================
13
14 use strict;
15
16
17 # =============================================================================
18 # C O N F I G U R A T I O N   S E C T I O N
19 # =============================================================================
20
21 my $base_path = ".";
22 my $src_path = "$base_path/src";
23
24 if (-d "../src")        # we're already inside "src" directory
25 {
26     $src_path = ".";
27 }
28
29
30 # -----------------------------------------------------------------------------
31 # global variables
32 # -----------------------------------------------------------------------------
33
34 my $filename_header_tmpl = "$src_path/header.tmpl";
35
36 my $filename_conf_gfx_h = 'conf_gfx.h';
37 my $filename_conf_snd_h = 'conf_snd.h';
38 my $filename_conf_mus_h = 'conf_mus.h';
39 my $filename_conf_chr_c = 'conf_chr.c';
40 my $filename_conf_chr_h = 'conf_chr.h';
41 my $filename_conf_cus_c = 'conf_cus.c';
42 my $filename_conf_cus_h = 'conf_cus.h';
43 my $filename_conf_grp_c = 'conf_grp.c';
44 my $filename_conf_grp_h = 'conf_grp.h';
45 my $filename_conf_emp_c = 'conf_emp.c';
46 my $filename_conf_emp_h = 'conf_emp.h';
47 my $filename_conf_e2g_c = 'conf_e2g.c';
48 my $filename_conf_esg_c = 'conf_esg.c';
49 my $filename_conf_e2s_c = 'conf_e2s.c';
50 my $filename_conf_fnt_c = 'conf_fnt.c';
51 my $filename_conf_g2s_c = 'conf_g2s.c';
52 my $filename_conf_g2m_c = 'conf_g2m.c';
53 my $filename_conf_var_c = 'conf_var.c';
54 my $filename_conf_act_c = 'conf_act.c';
55
56 my $text_auto = 'this file was automatically generated -- do not edit by hand';
57 my $text_gfx_h = 'values for graphics configuration (normal elements)';
58 my $text_snd_h = 'values for sounds configuration';
59 my $text_mus_h = 'values for music configuration';
60 my $text_chr_c = 'values for graphics configuration (character elements)';
61 my $text_chr_h = 'values for elements configuration (character elements)';
62 my $text_cus_c = 'values for graphics configuration (custom elements)';
63 my $text_cus_h = 'values for elements configuration (custom elements)';
64 my $text_grp_c = 'values for graphics configuration (group elements)';
65 my $text_grp_h = 'values for elements configuration (group elements)';
66 my $text_emp_c = 'values for graphics configuration (empty elements)';
67 my $text_emp_h = 'values for elements configuration (empty elements)';
68 my $text_e2g_c = 'values for element/graphics mapping configuration (normal)';
69 my $text_esg_c = 'values for element/graphics mapping configuration (special)';
70 my $text_e2s_c = 'values for element/sounds mapping configuration';
71 my $text_fnt_c = 'values for font/graphics mapping configuration';
72 my $text_g2s_c = 'values for gamemode/sound mapping configuration';
73 my $text_g2m_c = 'values for gamemode/music mapping configuration';
74 my $text_var_c = 'values for graphics and sound parameter configuration';
75 my $text_act_c = 'values for active states of elements and fonts';
76
77 my $num_custom_elements = 256;
78 my $num_group_elements = 32;
79 my $num_empty_elements = 16;
80
81 my $char_skip = '---[SKIP]---';
82
83 my @chars =
84     (
85      'SPACE',
86      'EXCLAM',
87      'QUOTEDBL',
88      'NUMBERSIGN',
89      'DOLLAR',
90      'PERCENT',
91      'AMPERSAND',
92      'APOSTROPHE',
93      'PARENLEFT',
94      'PARENRIGHT',
95      'ASTERISK',
96      'PLUS',
97      'COMMA',
98      'MINUS',
99      'PERIOD',
100      'SLASH',
101
102      '0',
103      '1',
104      '2',
105      '3',
106      '4',
107      '5',
108      '6',
109      '7',
110      '8',
111      '9',
112      'COLON',
113      'SEMICOLON',
114      'LESS',
115      'EQUAL',
116      'GREATER',
117      'QUESTION',
118
119      'AT',
120      'A',
121      'B',
122      'C',
123      'D',
124      'E',
125      'F',
126      'G',
127      'H',
128      'I',
129      'J',
130      'K',
131      'L',
132      'M',
133      'N',
134      'O',
135
136      'P',
137      'Q',
138      'R',
139      'S',
140      'T',
141      'U',
142      'V',
143      'W',
144      'X',
145      'Y',
146      'Z',
147      'BRACKETLEFT',
148      'BACKSLASH',
149      'BRACKETRIGHT',
150      'ASCIICIRCUM',
151      'UNDERSCORE',
152
153      'COPYRIGHT',
154      'AUMLAUT',
155      'OUMLAUT',
156      'UUMLAUT',
157      'DEGREE',
158      'TRADEMARK',
159      'CURSOR',
160      $char_skip,
161      $char_skip,
162      $char_skip,
163      $char_skip,
164      $char_skip,
165      $char_skip,
166      'BUTTON',
167      'UP',
168      'DOWN',
169      );
170
171
172 # -----------------------------------------------------------------------------
173 # start main program
174 # -----------------------------------------------------------------------------
175
176 main();
177 exit 0;
178
179
180 # =============================================================================
181 # F U N C T I O N S
182 # =============================================================================
183
184 sub error
185 {
186     my ($error_msg) = @_;
187
188     print STDERR "ERROR: ";
189     print STDERR "$error_msg\n";
190 }
191
192 sub fail
193 {
194     my ($error_msg) = @_;
195
196     print STDERR "FATAL ";
197     error("$error_msg");
198
199     exit 1;
200 }
201
202 sub contains_image_file
203 {
204     my ($line) = @_;
205
206     return ($line =~ /\".+\.png\"/ ||
207             $line =~ /UNDEFINED_FILENAME/);
208 }
209
210 sub contains_sound_file
211 {
212     my ($line) = @_;
213
214     return ($line =~ /\".+\.wav\"/ ||
215             $line =~ /UNDEFINED_FILENAME/);
216 }
217
218 sub contains_music_file
219 {
220     my ($line) = @_;
221
222     return ($line =~ /\".+\.wav\"/ ||
223             $line =~ /\".+\.mod\"/ ||
224             $line =~ /\".+\.mp3\"/ ||
225             $line =~ /UNDEFINED_FILENAME/);
226 }
227
228 sub print_file_header
229 {
230     my ($filename, $comment) = @_;
231     my $filename_tmpl = 'xxxxxxxx.x';
232     my $filename_text = $filename;
233     my $filename_def = uc($filename);
234     $filename_def =~ s/\./_/;
235
236     $filename_text .= ' ' x (length($filename_tmpl) - length($filename_text));
237
238     open(FILE, "$filename_header_tmpl") ||
239         fail("cannot open file '$filename_header_tmpl' for reading");
240
241     while (<FILE>)
242     {
243         s/$filename_tmpl/$filename_text/;
244
245         print;
246     }
247
248     close FILE;
249
250     print "\n";
251     print "// ------- $text_auto -------\n";
252     print "\n";
253     print "#ifndef $filename_def\n";
254     print "#define $filename_def\n";
255     print "\n";
256     print "// $comment\n";
257     print "\n";
258 }
259
260 sub print_file_footer
261 {
262     my ($filename) = @_;
263     my $filename_def = uc($filename);
264     $filename_def =~ s/\./_/;
265
266     print "\n";
267     print "#endif       // $filename_def\n";
268 }
269
270 sub get_tabs
271 {
272     my ($text, $max_num_tabs) = @_;
273
274     my $num_tabs = $max_num_tabs - int(length($text) / 8);
275
276     if ($num_tabs < 1)  # at least one tab needed as separator
277     {
278         $num_tabs = 1;
279     }
280
281     return "\t" x $num_tabs;
282 }
283
284 sub print_graphics_list
285 {
286     my $filename = "$src_path/conf_gfx.c";
287
288     print_file_header($filename_conf_gfx_h, $text_gfx_h);
289
290     open(FILE, "$filename") ||
291         fail("cannot open file '$filename' for reading");
292
293     my $max_num_tabs = 7;
294     my $i = 0;
295
296     while (<FILE>)
297     {
298         chomp;                          # cut trailing newline
299
300         if (/^\#include "conf_chr.c"/)  # dump list of character elements
301         {
302             foreach my $char (@chars)
303             {
304                 my $prefix = $char;
305
306                 $prefix =~ s/^/#define IMG_CHAR_/;
307
308                 my $tabs = get_tabs($prefix, $max_num_tabs);
309
310                 if ($char ne $char_skip)
311                 {
312                     print "$prefix$tabs$i\n";
313
314                     $i++;
315                 }
316
317                 if (lc($char) eq 'space')
318                 {
319                     $prefix =~ s/$/_EDITOR/;
320
321                     my $tabs = get_tabs($prefix, $max_num_tabs);
322
323                     print "$prefix$tabs$i\n";
324
325                     $i++;
326                 }
327             }
328
329             foreach my $char (@chars)
330             {
331                 my $prefix = $char;
332
333                 $prefix =~ s/^/#define IMG_STEEL_CHAR_/;
334
335                 my $tabs = get_tabs($prefix, $max_num_tabs);
336
337                 if ($char ne $char_skip)
338                 {
339                     print "$prefix$tabs$i\n";
340
341                     $i++;
342                 }
343
344                 if (lc($char) eq 'space')
345                 {
346                     $prefix =~ s/$/_EDITOR/;
347
348                     my $tabs = get_tabs($prefix, $max_num_tabs);
349
350                     print "$prefix$tabs$i\n";
351
352                     $i++;
353                 }
354             }
355         }
356
357         if (/^\#include "conf_cus.c"/)  # dump list of custom elements
358         {
359             for (my $nr = 0; $nr < $num_custom_elements; $nr++)
360             {
361                 my $line = sprintf("#define IMG_CUSTOM_%d", $nr + 1);
362
363                 my $tabs = get_tabs($line, $max_num_tabs);
364
365                 print "$line$tabs$i\n";
366
367                 $i++;
368
369                 $line = sprintf("#define IMG_CUSTOM_%d_EDITOR", $nr + 1);
370
371                 $tabs = get_tabs($line, $max_num_tabs);
372
373                 print "$line$tabs$i\n";
374
375                 $i++;
376             }
377         }
378
379         if (/^\#include "conf_grp.c"/)  # dump list of group elements
380         {
381             for (my $nr = 0; $nr < $num_group_elements; $nr++)
382             {
383                 my $line = sprintf("#define IMG_GROUP_%d", $nr + 1);
384
385                 my $tabs = get_tabs($line, $max_num_tabs);
386
387                 print "$line$tabs$i\n";
388
389                 $i++;
390
391                 $line = sprintf("#define IMG_GROUP_%d_EDITOR", $nr + 1);
392
393                 $tabs = get_tabs($line, $max_num_tabs);
394
395                 print "$line$tabs$i\n";
396
397                 $i++;
398             }
399         }
400
401         if (/^\#include "conf_emp.c"/)  # dump list of empty elements
402         {
403             for (my $nr = 0; $nr < $num_empty_elements; $nr++)
404             {
405                 my $line = sprintf("#define IMG_EMPTY_SPACE_%d", $nr + 1);
406
407                 my $tabs = get_tabs($line, $max_num_tabs);
408
409                 print "$line$tabs$i\n";
410
411                 $i++;
412
413                 $line = sprintf("#define IMG_EMPTY_SPACE_%d_EDITOR", $nr + 1);
414
415                 $tabs = get_tabs($line, $max_num_tabs);
416
417                 print "$line$tabs$i\n";
418
419                 $i++;
420             }
421         }
422
423         if (!contains_image_file($_))   # skip all lines without image file
424         {
425             next;
426         }
427
428         s/(.*)/uc($1)/eg;               # convert all characters to upper case
429         s/\./_/g;                       # replace all '.' with '_'
430
431         s/^  \{ \"/#define IMG_/;       # convert line
432         s/\",.*$//;                     # convert line
433
434         # dirty hack for making "ABC[DEF]" work as a "special" suffix
435         s/([^_])\[/$1_/;
436
437         # dirty hack for making "[default]" work as an element name
438         s/\[//;
439         s/\]//;
440
441         my $tabs = get_tabs($_, $max_num_tabs);
442
443         print "$_$tabs$i\n";
444
445         $i++;
446     }
447
448     my $summary = '#define NUM_IMAGE_FILES';
449     my $tabs = get_tabs($summary, $max_num_tabs);
450
451     print "\n$summary$tabs$i\n";
452
453     close FILE;
454
455     print_file_footer($filename_conf_gfx_h);
456 }
457
458 sub print_sounds_list
459 {
460     my %known_element = get_known_element_definitions();
461
462     my $filename = "$src_path/conf_snd.c";
463
464     print_file_header($filename_conf_snd_h, $text_snd_h);
465
466     open(FILE, "$filename") ||
467         fail("cannot open file '$filename' for reading");
468
469     my $max_num_tabs = 7;
470     my $i = 0;
471
472     while (<FILE>)
473     {
474         chomp;                          # cut trailing newline
475
476         if (!contains_sound_file($_))   # skip all lines without sound file
477         {
478             next;
479         }
480
481         if (/\[not used\]/ ||
482             / TEST / ||
483             /wav[^\}]*$/)               # skip all lines without sound file
484         {
485             next;
486         }
487
488         s/(.*)/uc($1)/eg;               # convert all characters to upper case
489         s/\./_/g;                       # replace all '.' with '_'
490
491         s/^  \{ \"//;
492         s/\",.*$//;
493
494         my $sound = $_;
495
496         if ($sound =~ /^\[.+\]/)
497         {
498             $sound =~ s/\[//;           # element class sound; begin ...
499             $sound =~ s/\]//;           # ... and end of definition token
500             $sound =~ s/^/CLASS_/;      # add class identifier
501         }
502
503         # dirty hack for making "ABC[DEF]" work as a "special" suffix
504         $sound =~ s/([^_])\[/$1_/;
505         $sound =~ s/\[//;
506         $sound =~ s/\]//;
507
508         $sound = "SND_$sound";
509
510         my $define_text = "#define $sound";
511         my $tabs = get_tabs($define_text, $max_num_tabs);
512
513         print "$define_text$tabs$i\n";
514
515         $i++;
516     }
517
518     my $summary = '#define NUM_SOUND_FILES';
519     my $tabs = get_tabs($summary, $max_num_tabs);
520
521     print "\n$summary$tabs$i\n";
522
523     close FILE;
524
525     print_file_footer($filename_conf_snd_h);
526 }
527
528 sub print_music_list
529 {
530     my %known_prefix = get_known_music_prefix_definitions();
531
532     my $filename = "$src_path/conf_mus.c";
533
534     print_file_header($filename_conf_mus_h, $text_mus_h);
535
536     open(FILE, "$filename") ||
537         fail("cannot open file '$filename' for reading");
538
539     my $max_num_tabs = 7;
540     my $i = 0;
541
542     while (<FILE>)
543     {
544         chomp;                          # cut trailing newline
545
546         if (!contains_music_file($_))   # skip all lines without music file
547         {
548             next;
549         }
550
551         if (/\[not used\]/ ||
552             / TEST / ||
553             /wav[^\}]*$/)               # skip all lines without music file
554         {
555             next;
556         }
557
558         s/(.*)/uc($1)/eg;               # convert all characters to upper case
559         s/\./_/g;                       # replace all '.' with '_'
560
561         s/^  \{ \"//;
562         s/\",.*$//;
563
564         my $music = $_;
565
566         # dirty hack for making "ABC[DEF]" work as a "special" suffix
567         $music =~ s/([^_])\[/$1_/;
568         $music =~ s/\[//;
569         $music =~ s/\]//;
570
571         $music = "MUS_$music";
572
573         my $define_text = "#define $music";
574         my $tabs = get_tabs($define_text, $max_num_tabs);
575
576         print "$define_text$tabs$i\n";
577
578         $i++;
579     }
580
581     my $summary = '#define NUM_MUSIC_FILES';
582     my $tabs = get_tabs($summary, $max_num_tabs);
583
584     print "\n$summary$tabs$i\n";
585
586     close FILE;
587
588     print_file_footer($filename_conf_mus_h);
589 }
590
591 sub print_chars_elements_list
592 {
593     print_file_header($filename_conf_chr_h, $text_chr_h);
594
595     my $i = 0;
596
597     foreach my $char (@chars)
598     {
599         my $left = "#define EL_CHAR_$char";
600
601         my $tabs_left = get_tabs($left, 5);
602
603         my $right = sprintf("(EL_CHAR_ASCII0 + %d)", $i + 32);
604
605         if ($char ne $char_skip)
606         {
607             print "$left$tabs_left$right\n";
608         }
609
610         $i++;
611     }
612
613     $i = 0;
614
615     foreach my $char (@chars)
616     {
617         my $left = "#define EL_STEEL_CHAR_$char";
618
619         my $tabs_left = get_tabs($left, 5);
620
621         my $right = sprintf("(EL_STEEL_CHAR_ASCII0 + %d)", $i + 32);
622
623         if ($char ne $char_skip)
624         {
625             print "$left$tabs_left$right\n";
626         }
627
628         $i++;
629     }
630
631     print_file_footer($filename_conf_chr_c);
632 }
633
634 sub print_chars_graphics_list_line
635 {
636     my ($token, $x, $y) = @_;
637
638     my @extensions =
639         (
640          '',
641          '.xpos',
642          '.ypos',
643          '.frames',
644          );
645
646     my $basename = ($token =~ /^steel_char/ ? 'RocksFontDC' : 'RocksFontEM' );
647
648     foreach my $ext (@extensions)
649     {
650         my $left = "  \{ \"$token$ext\",";
651
652         my $tabs_left = get_tabs($left, 6);
653
654         my $right = ($ext eq '' ? $basename . '.png' :
655                      $ext eq '.frames' ? '1' : '0');
656
657         if ($ext eq '.xpos')
658         {
659             $right = $x;
660         }
661         elsif ($ext eq '.ypos')
662         {
663             $right = $y;
664         }
665
666         $right = "\"$right\"";
667
668         my $tabs_right = get_tabs($right, 3);
669
670         print "$left$tabs_left$right$tabs_right},\n";
671     }
672 }
673
674 sub print_chars_graphics_list
675 {
676     print_file_header($filename_conf_chr_c, $text_chr_c);
677
678     my $i = 0;
679
680     foreach my $char (@chars)
681     {
682         if ($char ne $char_skip)
683         {
684             my $x = $i % 16;
685             my $y = int($i / 16);
686
687             print_chars_graphics_list_line(lc("char_$char"), $x, $y);
688         }
689
690         if (lc($char) eq 'space')
691         {
692             print_chars_graphics_list_line("char_space.EDITOR", 7, 4);
693         }
694
695         if ($char ne $char_skip)
696         {
697             print "\n";
698         }
699
700         $i++;
701     }
702
703     $i = 0;
704
705     foreach my $char (@chars)
706     {
707         if ($char ne $char_skip)
708         {
709             my $x = $i % 16;
710             my $y = int($i / 16);
711
712             print_chars_graphics_list_line(lc("steel_char_$char"), $x, $y);
713         }
714
715         if (lc($char) eq 'space')
716         {
717             print_chars_graphics_list_line("steel_char_space.EDITOR", 7, 4);
718         }
719
720         if ($char ne $char_skip)
721         {
722             print "\n";
723         }
724
725         $i++;
726     }
727
728     print_file_footer($filename_conf_chr_c);
729 }
730
731 sub print_custom_elements_list
732 {
733     print_file_header($filename_conf_cus_h, $text_cus_h);
734
735     for (my $i = 0; $i < $num_custom_elements; $i++)
736     {
737         my $left = sprintf("#define EL_CUSTOM_%d", $i + 1);
738
739         my $tabs_left = get_tabs($left, 5);
740
741         my $right = "(EL_CUSTOM_START + $i)";
742
743         print "$left$tabs_left$right\n";
744     }
745
746     print_file_footer($filename_conf_cus_c);
747 }
748
749 sub print_group_elements_list
750 {
751     print_file_header($filename_conf_grp_h, $text_grp_h);
752
753     for (my $i = 0; $i < $num_group_elements; $i++)
754     {
755         my $left = sprintf("#define EL_GROUP_%d", $i + 1);
756
757         my $tabs_left = get_tabs($left, 5);
758
759         my $right = "(EL_GROUP_START + $i)";
760
761         print "$left$tabs_left$right\n";
762     }
763
764     print_file_footer($filename_conf_grp_c);
765 }
766
767 sub print_empty_elements_list
768 {
769     print_file_header($filename_conf_emp_h, $text_emp_h);
770
771     for (my $i = 0; $i < $num_empty_elements; $i++)
772     {
773         my $left = sprintf("#define EL_EMPTY_SPACE_%d", $i + 1);
774
775         my $tabs_left = get_tabs($left, 5);
776
777         my $right = "(EL_EMPTY_SPACE_START + $i)";
778
779         print "$left$tabs_left$right\n";
780     }
781
782     print_file_footer($filename_conf_emp_c);
783 }
784
785 sub print_custom_graphics_list
786 {
787     my @extensions1 =
788         (
789          '',
790          '.xpos',
791          '.ypos',
792          '.frames',
793          );
794     my @extensions2 =
795         (
796          '',
797          '.xpos',
798          '.ypos',
799          );
800
801     print_file_header($filename_conf_cus_c, $text_cus_c);
802
803     for (my $i = 0; $i < $num_custom_elements; $i++)
804     {
805         foreach my $ext (@extensions1)
806         {
807             my $left = sprintf("  \{ \"custom_%d$ext\",", $i + 1);
808
809             my $tabs_left = get_tabs($left, 6);
810
811             # my $right = ($ext eq '' ? 'RocksElements.png' :
812             my $right = ($ext eq '' ? 'RocksCE.png' :
813                          $ext eq '.frames' ? '1' : '0');
814
815             if ($ext eq '.xpos')
816             {
817                 # $right = 7;
818                 $right = int($i % 16);
819             }
820             elsif ($ext eq '.ypos')
821             {
822                 # $right = 9;
823                 $right = int($i / 16);
824             }
825
826             $right = "\"$right\"";
827
828             my $tabs_right = get_tabs($right, 3);
829
830             print "$left$tabs_left$right$tabs_right},\n";
831         }
832
833         foreach my $ext (@extensions2)
834         {
835             my $left = sprintf("  \{ \"custom_%d.EDITOR$ext\",", $i + 1);
836
837             my $tabs_left = get_tabs($left, 6);
838
839             # my $right = ($ext eq '' ? 'RocksElements.png' : '0');
840             my $right = ($ext eq '' ? 'RocksCE.png' : '0');
841
842             if ($ext eq '.xpos')
843             {
844                 # $right = 15;
845                 $right = int($i % 16) + 16;
846             }
847             elsif ($ext eq '.ypos')
848             {
849                 # $right = 13;
850                 $right = int($i / 16);
851             }
852
853             $right = "\"$right\"";
854
855             my $tabs_right = get_tabs($right, 3);
856
857             print "$left$tabs_left$right$tabs_right},\n";
858         }
859
860         print "\n";
861     }
862
863     print_file_footer($filename_conf_cus_c);
864 }
865
866 sub print_group_graphics_list
867 {
868     my @extensions1 =
869         (
870          '',
871          '.xpos',
872          '.ypos',
873          '.frames',
874          );
875     my @extensions2 =
876         (
877          '',
878          '.xpos',
879          '.ypos',
880          );
881
882     print_file_header($filename_conf_grp_c, $text_grp_c);
883
884     for (my $i = 0; $i < $num_group_elements; $i++)
885     {
886         foreach my $ext (@extensions1)
887         {
888             my $left = sprintf("  \{ \"group_%d$ext\",", $i + 1);
889
890             my $tabs_left = get_tabs($left, 6);
891
892             # my $right = ($ext eq '' ? 'RocksDC.png' :
893             my $right = ($ext eq '' ? 'RocksCE.png' :
894                          $ext eq '.frames' ? '1' : '0');
895
896             if ($ext eq '.xpos')
897             {
898                 # $right = 4;
899                 $right = int($i % 16);
900             }
901             elsif ($ext eq '.ypos')
902             {
903                 # $right = 15;
904                 $right = int($i / 16) + int($num_custom_elements / 16);
905             }
906
907             $right = "\"$right\"";
908
909             my $tabs_right = get_tabs($right, 3);
910
911             print "$left$tabs_left$right$tabs_right},\n";
912         }
913
914         foreach my $ext (@extensions2)
915         {
916             my $left = sprintf("  \{ \"group_%d.EDITOR$ext\",", $i + 1);
917
918             my $tabs_left = get_tabs($left, 6);
919
920             # my $right = ($ext eq '' ? 'RocksDC.png' : '0');
921             my $right = ($ext eq '' ? 'RocksCE.png' : '0');
922
923             if ($ext eq '.xpos')
924             {
925                 # $right = 14;
926                 $right = int($i % 16) + 16;
927             }
928             elsif ($ext eq '.ypos')
929             {
930                 # $right = 15;
931                 $right = int($i / 16) + int($num_custom_elements / 16);
932             }
933
934             $right = "\"$right\"";
935
936             my $tabs_right = get_tabs($right, 3);
937
938             print "$left$tabs_left$right$tabs_right},\n";
939         }
940
941         print "\n";
942     }
943
944     print_file_footer($filename_conf_grp_c);
945 }
946
947 sub print_empty_graphics_list
948 {
949     my @extensions1 =
950         (
951          '',
952          '.xpos',
953          '.ypos',
954          '.frames',
955          );
956     my @extensions2 =
957         (
958          '',
959          '.xpos',
960          '.ypos',
961          );
962
963     my $num_non_empty_elements = $num_custom_elements + $num_group_elements;
964
965     print_file_header($filename_conf_emp_c, $text_emp_c);
966
967     for (my $i = 0; $i < $num_empty_elements; $i++)
968     {
969         foreach my $ext (@extensions1)
970         {
971             my $left = sprintf("  \{ \"empty_space_%d$ext\",", $i + 1);
972
973             my $tabs_left = get_tabs($left, 6);
974
975             # my $right = ($ext eq '' ? 'RocksDC.png' :
976             my $right = ($ext eq '' ? 'RocksCE.png' :
977                          $ext eq '.frames' ? '1' : '0');
978
979             if ($ext eq '.xpos')
980             {
981                 # $right = 4;
982                 $right = int($i % 16);
983             }
984             elsif ($ext eq '.ypos')
985             {
986                 # $right = 15;
987                 $right = int($i / 16) + int($num_non_empty_elements / 16);
988             }
989
990             $right = "\"$right\"";
991
992             my $tabs_right = get_tabs($right, 3);
993
994             print "$left$tabs_left$right$tabs_right},\n";
995         }
996
997         foreach my $ext (@extensions2)
998         {
999             my $left = sprintf("  \{ \"empty_space_%d.EDITOR$ext\",", $i + 1);
1000
1001             my $tabs_left = get_tabs($left, 6);
1002
1003             # my $right = ($ext eq '' ? 'RocksDC.png' : '0');
1004             my $right = ($ext eq '' ? 'RocksCE.png' : '0');
1005
1006             if ($ext eq '.xpos')
1007             {
1008                 # $right = 14;
1009                 $right = int($i % 16) + 16;
1010             }
1011             elsif ($ext eq '.ypos')
1012             {
1013                 # $right = 15;
1014                 $right = int($i / 16) + int($num_non_empty_elements / 16);
1015             }
1016
1017             $right = "\"$right\"";
1018
1019             my $tabs_right = get_tabs($right, 3);
1020
1021             print "$left$tabs_left$right$tabs_right},\n";
1022         }
1023
1024         print "\n";
1025     }
1026
1027     print_file_footer($filename_conf_emp_c);
1028 }
1029
1030 sub get_known_element_definitions_ALTERNATIVE
1031 {
1032     my %known_element = ();
1033
1034     my $filename = "$src_path/main.h";
1035
1036     open(FILE, "$filename") ||
1037         fail("cannot open file '$filename' for reading");
1038
1039     while (<FILE>)
1040     {
1041         chomp;                          # cut trailing newline
1042
1043         # process line with element definition
1044         if (/^\#define (EL_[A-Z0-9_]+)\s/)
1045         {
1046             $known_element{$1} = 1;
1047
1048             # print STDERR "known_element: '$1'\n";
1049         }
1050     }
1051
1052     close FILE;
1053
1054     return %known_element;
1055 }
1056
1057 sub get_known_element_definitions
1058 {
1059     my %known_element = ();
1060
1061     my $filename = "$src_path/main.c";
1062
1063     open(FILE, "$filename") ||
1064         fail("cannot open file '$filename' for reading");
1065
1066     my $element_name = '';
1067     my $line_is_element_name = 0;
1068     my $skip_line = 1;
1069
1070     while (<FILE>)
1071     {
1072         chomp;                          # cut trailing newline
1073
1074         if (/ELEMENT_INFO_START/)       # keyword to start parsing file
1075         {
1076             $skip_line = 0;
1077             next;
1078         }
1079         elsif (/ELEMENT_INFO_END/)      # keyword to stop parsing file
1080         {
1081             last;
1082         }
1083         elsif ($skip_line)
1084         {
1085             next;
1086         }
1087
1088         if (/^\s+\{\s*$/)
1089         {
1090             $line_is_element_name = 1;
1091         }
1092         elsif ($line_is_element_name)
1093         {
1094             # process line with element name definition
1095             if (/^\s+\"(.+)\",?\s*$/)
1096             {
1097                 $element_name = 'EL_' . uc($1);
1098
1099                 # dirty hack for making "[default]" work as an element name
1100                 $element_name =~ s/\[//;
1101                 $element_name =~ s/\]//;
1102
1103                 # change '.' to '_' for elements like "dynamite.active"
1104                 $element_name =~ s/\./_/g;
1105
1106                 $known_element{$element_name} = 1;
1107
1108                 # printf STDERR "::: known element '$element_name'\n";
1109             }
1110
1111             $line_is_element_name = 0;
1112         }
1113     }
1114
1115     close FILE;
1116
1117     return %known_element;
1118 }
1119
1120 sub get_known_element_class_definitions
1121 {
1122     my %known_element_class = ();
1123
1124     my $filename = "$src_path/main.c";
1125
1126     open(FILE, "$filename") ||
1127         fail("cannot open file '$filename' for reading");
1128
1129     my $element_name = '';
1130     my $element_class = '';
1131     my $line_is_element_name = 0;
1132     my $line_is_element_class = 0;
1133     my $skip_line = 1;
1134
1135     while (<FILE>)
1136     {
1137         chomp;                          # cut trailing newline
1138
1139         if (/ELEMENT_INFO_START/)       # keyword to start parsing file
1140         {
1141             $skip_line = 0;
1142             next;
1143         }
1144         elsif (/ELEMENT_INFO_END/)      # keyword to stop parsing file
1145         {
1146             last;
1147         }
1148         elsif ($skip_line)
1149         {
1150             next;
1151         }
1152
1153         if (/^\s+\{\s*$/)
1154         {
1155             $line_is_element_name = 1;
1156         }
1157         elsif ($line_is_element_name)
1158         {
1159             # process line with element name definition
1160             if (/^\s+\"(.+)\",?\s*$/)
1161             {
1162                 $element_name = 'EL_' . uc($1);
1163
1164                 # dirty hack for making "[default]" work as an element name
1165                 $element_name =~ s/\[//;
1166                 $element_name =~ s/\]//;
1167
1168                 # change '.' to '_' for elements like "dynamite.active"
1169                 $element_name =~ s/\./_/g;
1170             }
1171
1172             $line_is_element_name = 0;
1173             $line_is_element_class = 1;
1174         }
1175         elsif ($line_is_element_class)
1176         {
1177             # process line with element class definition
1178             if (/^\s+\"(.+)\",?\s*$/)
1179             {
1180                 $element_class = 'EL_CLASS_' . uc($1);
1181
1182                 if (!defined($known_element_class{$element_class}))
1183                 {
1184                     $known_element_class{$element_class} = $element_name;
1185                 }
1186
1187                 $known_element_class{$element_name} = $element_class;
1188
1189                 # print STDERR "known_element_class: '$element_name' => '$element_class'\n";
1190             }
1191
1192             $line_is_element_class = 0;
1193         }
1194     }
1195
1196     close FILE;
1197
1198     return %known_element_class;
1199 }
1200
1201 sub get_known_action_definitions
1202 {
1203     my %known_action = ();
1204
1205     my $filename = "$src_path/main.h";
1206
1207     open(FILE, "$filename") ||
1208         fail("cannot open file '$filename' for reading");
1209
1210     while (<FILE>)
1211     {
1212         chomp;                          # cut trailing newline
1213
1214         # process line with action definition
1215         if (/^  ACTION_([A-Z0-9_]+)[, ]/)
1216         {
1217             $known_action{$1} = 1;
1218
1219             # print STDERR "known_action: '$1'\n";
1220         }
1221     }
1222
1223     close FILE;
1224
1225     return %known_action;
1226 }
1227
1228 sub get_known_special_arg_definitions
1229 {
1230     my %known_special_arg = ();
1231
1232     my $filename = "$src_path/main.h";
1233
1234     open(FILE, "$filename") ||
1235         fail("cannot open file '$filename' for reading");
1236
1237     while (<FILE>)
1238     {
1239         chomp;                          # cut trailing newline
1240
1241         # process line with special arg definition
1242         if (/^  GFX_SPECIAL_ARG_([A-Z0-9_]+)[, ]/)
1243         {
1244             if ($1 eq 'CRUMBLED')
1245             {
1246                 next;
1247             }
1248
1249             $known_special_arg{$1} = 1;
1250
1251             # print STDERR "known_special_arg: '$1'\n";
1252         }
1253     }
1254
1255     close FILE;
1256
1257     return %known_special_arg;
1258 }
1259
1260 sub get_known_button_definitions
1261 {
1262     my %known_button = ();
1263
1264     my $filename = "$src_path/conf_gfx.h";
1265
1266     open(FILE, "$filename") ||
1267         fail("cannot open file '$filename' for reading");
1268
1269     while (<FILE>)
1270     {
1271         chomp;                          # cut trailing newline
1272
1273         # process line with button definition
1274         if (/^\#define (IMG_MENU_BUTTON[A-Z0-9_]*)\s/)
1275         {
1276             $known_button{$1} = 1;
1277
1278             # print STDERR "known_button: '$1'\n";
1279         }
1280     }
1281
1282     close FILE;
1283
1284     return %known_button;
1285 }
1286
1287 sub get_known_font_definitions
1288 {
1289     my %known_font = ();
1290
1291     my $filename = "$src_path/main.h";
1292
1293     open(FILE, "$filename") ||
1294         fail("cannot open file '$filename' for reading");
1295
1296     while (<FILE>)
1297     {
1298         chomp;                          # cut trailing newline
1299
1300         # process line with font definition
1301         if (/^  (FONT_[A-Z0-9_]+)[, ]/)
1302         {
1303             $known_font{$1} = 1;
1304
1305             # print STDERR "known_font: '$1'\n";
1306         }
1307     }
1308
1309     close FILE;
1310
1311     return %known_font;
1312 }
1313
1314 sub get_known_sound_prefix_definitions
1315 {
1316     my %known_sound_prefix = ( 'background'     => 1 );
1317
1318     return %known_sound_prefix;
1319 }
1320
1321 sub get_known_music_prefix_definitions
1322 {
1323     my %known_music_prefix = ();
1324
1325     my $filename = "$src_path/main.c";
1326
1327     open(FILE, "$filename") ||
1328         fail("cannot open file '$filename' for reading");
1329
1330     my $prefix_name = '';
1331     my $skip_line = 1;
1332
1333     while (<FILE>)
1334     {
1335         chomp;                          # cut trailing newline
1336
1337         if (/MusicPrefixInfo/)          # keyword to start parsing file
1338         {
1339             $skip_line = 0;
1340             next;
1341         }
1342         elsif (/NULL/ && !$skip_line)   # keyword to stop parsing file
1343         {
1344             last;
1345         }
1346         elsif ($skip_line)
1347         {
1348             next;
1349         }
1350
1351         if (/^\s+{\s+\"(.+)\"/)
1352         {
1353             my $music_prefix = $1;
1354
1355             $known_music_prefix{$music_prefix} = 1;
1356
1357             # printf STDERR "::: known music prefix '$music_prefix'\n";
1358         }
1359     }
1360
1361     close FILE;
1362
1363     return %known_music_prefix;
1364 }
1365
1366 sub print_element_to_graphic_entry
1367 {
1368     my ($element, $action, $direction, $crumbled, $graphic) = @_;
1369
1370     my $num_tabs = 5 - int((length($element) + 4 + 1) / 8);
1371     my $tabs = "\t" x $num_tabs;
1372     if ($tabs eq '')
1373     {
1374         $tabs = ' ';
1375     }
1376
1377     $crumbled = ($crumbled == 1 ? 'TRUE' : 'FALSE');
1378
1379     print "  {\n";
1380     print "    $element,$tabs$action, $direction, $crumbled,\n";
1381     print "    $graphic\n";
1382     print "  },\n";
1383 }
1384
1385 sub print_element_to_special_graphic_entry
1386 {
1387     my ($element, $special, $graphic) = @_;
1388
1389     my $num_tabs = 6 - int((length($element) + 4 + 1) / 8);
1390     my $tabs = "\t" x $num_tabs;
1391     if ($tabs eq '')
1392     {
1393         $tabs = ' ';
1394     }
1395
1396     print "  {\n";
1397     print "    $element,$tabs$special,\n";
1398     print "    $graphic\n";
1399     print "  },\n";
1400 }
1401
1402 sub print_font_to_graphic_entry
1403 {
1404     my ($font, $special, $graphic) = @_;
1405
1406     my $num_tabs = 6 - int((length($font) + 4 + 1) / 8);
1407     my $tabs = "\t" x $num_tabs;
1408     if ($tabs eq '')
1409     {
1410         $tabs = ' ';
1411     }
1412
1413     print "  {\n";
1414     print "    $font,$tabs$special,\n";
1415     print "    $graphic\n";
1416     print "  },\n";
1417 }
1418
1419 sub print_element_to_sound_entry
1420 {
1421     my ($element, $is_class, $action, $sound) = @_;
1422
1423     my $element_plus_is_class = "$element, $is_class";
1424
1425     my $num_tabs = 6 - int((length($element_plus_is_class) + 4 + 1) / 8);
1426     my $tabs = "\t" x $num_tabs;
1427     if ($tabs eq '')
1428     {
1429         $tabs = ' ';
1430     }
1431
1432     print "  {\n";
1433     print "    $element_plus_is_class,$tabs$action,\n";
1434     print "    $sound\n";
1435     print "  },\n";
1436 }
1437
1438 sub print_gamemode_to_sound_entry
1439 {
1440     my ($gamemode, $sound) = @_;
1441
1442     print "  {\n";
1443     print "    $gamemode,\n";
1444     print "    $sound\n";
1445     print "  },\n";
1446 }
1447
1448 sub print_gamemode_to_music_entry
1449 {
1450     my ($gamemode, $music) = @_;
1451
1452     print "  {\n";
1453     print "    $gamemode,\n";
1454     print "    $music\n";
1455     print "  },\n";
1456 }
1457
1458 sub print_config_var_entry
1459 {
1460     my ($token, $var) = @_;
1461
1462     print "  {\n";
1463     print "    $token,\n";
1464     print "    $var\n";
1465     print "  },\n";
1466 }
1467
1468 sub print_active_state_entry
1469 {
1470     my ($token, $token_active) = @_;
1471
1472     print "  {\n";
1473     print "    $token,\n";
1474     print "    $token_active\n";
1475     print "  },\n";
1476 }
1477
1478 sub print_element_to_graphic_list
1479 {
1480     my %graphic_without_element =
1481         (
1482          'IMG_FLAMES_1_LEFT'            => 1,
1483          'IMG_FLAMES_2_LEFT'            => 1,
1484          'IMG_FLAMES_3_LEFT'            => 1,
1485          'IMG_FLAMES_1_RIGHT'           => 1,
1486          'IMG_FLAMES_2_RIGHT'           => 1,
1487          'IMG_FLAMES_3_RIGHT'           => 1,
1488          'IMG_FLAMES_1_UP'              => 1,
1489          'IMG_FLAMES_2_UP'              => 1,
1490          'IMG_FLAMES_3_UP'              => 1,
1491          'IMG_FLAMES_1_DOWN'            => 1,
1492          'IMG_FLAMES_2_DOWN'            => 1,
1493          'IMG_FLAMES_3_DOWN'            => 1,
1494          'IMG_TWINKLE_BLUE'             => 1,
1495          'IMG_TWINKLE_WHITE'            => 1,
1496          );
1497
1498     my %additional_mappings =
1499         (
1500          # file elements which are mapped to runtime elements when playing
1501
1502          # 'EL_EM_KEY_1_FILE'           => 'IMG_EM_KEY_1',
1503          # 'EL_EM_KEY_2_FILE'           => 'IMG_EM_KEY_2',
1504          # 'EL_EM_KEY_3_FILE'           => 'IMG_EM_KEY_3',
1505          # 'EL_EM_KEY_4_FILE'           => 'IMG_EM_KEY_4',
1506
1507          # new elements which still have no graphic
1508          # 'EL_DOOR_WHITE',             => 'IMG_CHAR_QUESTION',
1509          # 'EL_DOOR_WHITE_GRAY',        => 'IMG_CHAR_QUESTION',
1510          # 'EL_KEY_WHITE',              => 'IMG_CHAR_QUESTION',
1511          # 'EL_SIGN_RADIOACTIVITY',     => 'IMG_CHAR_QUESTION',
1512          # 'EL_SIGN_WHEELCHAIR',        => 'IMG_CHAR_QUESTION',
1513          # 'EL_SIGN_PARKING',           => 'IMG_CHAR_QUESTION',
1514          # 'EL_SIGN_ONEWAY',            => 'IMG_CHAR_QUESTION',
1515          # 'EL_SIGN_HEART',             => 'IMG_CHAR_QUESTION',
1516          # 'EL_SIGN_TRIANGLE',          => 'IMG_CHAR_QUESTION',
1517          # 'EL_SIGN_ROUND',             => 'IMG_CHAR_QUESTION',
1518          # 'EL_SIGN_EXIT',              => 'IMG_CHAR_QUESTION',
1519          # 'EL_SIGN_YINYANG',           => 'IMG_CHAR_QUESTION',
1520          # 'EL_SIGN_OTHER',             => 'IMG_CHAR_QUESTION',
1521          'EL_SIGN_UNUSED_1',            => 'IMG_CHAR_QUESTION',
1522          'EL_SIGN_UNUSED_2',            => 'IMG_CHAR_QUESTION',
1523          'EL_DX_UNKNOWN_15',            => 'IMG_CHAR_QUESTION',
1524          'EL_DX_UNKNOWN_42',            => 'IMG_CHAR_QUESTION',
1525
1526          # file elements with direction which is not defined
1527          'EL_BD_BUTTERFLY_LEFT'         => 'IMG_BD_BUTTERFLY',
1528          'EL_BD_BUTTERFLY_RIGHT'        => 'IMG_BD_BUTTERFLY',
1529          'EL_BD_BUTTERFLY_UP'           => 'IMG_BD_BUTTERFLY',
1530          'EL_BD_BUTTERFLY_DOWN'         => 'IMG_BD_BUTTERFLY',
1531          'EL_BD_FIREFLY_LEFT'           => 'IMG_BD_FIREFLY',
1532          'EL_BD_FIREFLY_RIGHT'          => 'IMG_BD_FIREFLY',
1533          'EL_BD_FIREFLY_UP'             => 'IMG_BD_FIREFLY',
1534          'EL_BD_FIREFLY_DOWN'           => 'IMG_BD_FIREFLY',
1535          );
1536
1537     my @unknown_graphics = ();
1538     my %known_element     = get_known_element_definitions();
1539     my %known_action      = get_known_action_definitions();
1540     my %known_special_arg = get_known_special_arg_definitions();
1541     my %known_direction =
1542         (
1543          'LEFT'         => 1,
1544          'RIGHT'        => 1,
1545          'UP'           => 1,
1546          'DOWN'         => 1,
1547          'UPLEFT'       => 1,
1548          'UPRIGHT'      => 1,
1549          'DOWNLEFT'     => 1,
1550          'DOWNRIGHT'    => 1,
1551          );
1552
1553     # ---------- read graphic file definitions ----------
1554
1555     my $filename = "$src_path/conf_gfx.c";
1556
1557     print_file_header($filename_conf_e2g_c, $text_e2g_c);
1558
1559     open(FILE, "$filename") ||
1560         fail("cannot open file '$filename' for reading");
1561
1562     print "static struct\n";
1563     print "{\n";
1564     print "  int element;\n";
1565     print "  int action;\n";
1566     print "  int direction;\n";
1567     print "  boolean crumbled;\n";
1568     print "\n";
1569     print "  int graphic;\n";
1570     print "}\n";
1571     print "element_to_graphic[] =\n";
1572     print "{\n";
1573
1574     while (<FILE>)
1575     {
1576         chomp;                          # cut trailing newline
1577
1578         if (/NO_MORE_ELEMENT_IMAGES/)   # keyword to stop parsing file
1579         {
1580             last;
1581         }
1582
1583         if (!contains_image_file($_))   # skip all lines without image file
1584         {
1585             next;
1586         }
1587
1588         s/^  \{ \"//;                   # cut all leading ...
1589         s/\",.*$//;                     # ... and trailing garbage
1590
1591         s/\[(\d+)\]/_$1/;               # convert "[1]" to "_1" etc.
1592
1593         s/\[//;                         # dirty hack for making "[default]" ...
1594         s/\]//;                         # ... work as an element name
1595
1596         my $token = $_;
1597
1598         if ($token =~ /\.([^\.]+)$/ && defined($known_special_arg{$1}))
1599         {
1600             next;                       # skip all special definitions
1601         }
1602
1603         $token = uc($token);            # convert all characters to upper case
1604
1605         my $gfx_action_default = '-1';
1606         my $gfx_action = $gfx_action_default;
1607
1608         my $gfx_direction_default = '-1';
1609         my $gfx_direction = $gfx_direction_default;
1610
1611         my $gfx_crumbled = '0';
1612
1613         my $object = $token;
1614         my $action = '';
1615         my $direction = '';
1616         my $crumbled = '';
1617
1618         if ($object =~ /^(.*)\.([A-Z0-9]+)$/ && $2 eq 'CRUMBLED')
1619         {
1620             $object = $1;
1621             $crumbled = $2;
1622
1623             $gfx_crumbled = '1';
1624         }
1625
1626         if ($object =~ /^(.*)\.([A-Z0-9]+)$/ && defined($known_direction{$2}))
1627         {
1628             $object = $1;
1629             $direction = $2;
1630
1631             $gfx_direction = "MV_BIT_$direction";
1632             $gfx_direction_default = $gfx_direction;
1633         }
1634
1635         if ($object =~ /^(.*)\.([A-Z0-9_]+)$/ && defined($known_action{$2}))
1636         {
1637             $object = $1;
1638             $action = $2;
1639
1640             $gfx_action = "ACTION_$action";
1641             $gfx_action_default = $gfx_action;
1642         }
1643
1644         $token =~ s/\./_/g;
1645         $object =~ s/\./_/g;    # needed for "invisible_sand.active.digging"
1646
1647         # print STDERR "'$token' => '$object', '$action', '$direction'\n";
1648
1649         my $full_element = "EL_$token";
1650         my $base_element = "EL_$object";
1651
1652         my $element = $base_element;
1653         my $graphic = "IMG_$token";
1654
1655         my $element_without_crumbled = $full_element;
1656         $element_without_crumbled =~ s/_$crumbled$//;
1657
1658         my $element_without_direction = $element_without_crumbled;
1659         $element_without_direction =~ s/_$direction$//;
1660
1661         my $element_without_action = $element_without_direction;
1662         $element_without_action =~ s/_$action$//;
1663
1664         if (defined($known_element{$full_element}))
1665         {
1666             $element = $full_element;
1667
1668             $gfx_action_default = '-1';
1669             $gfx_direction_default = '-1';
1670         }
1671
1672         if ($element_without_action eq $element || $action eq '')
1673         {
1674             $element_without_action = '';
1675         }
1676
1677         if ($element_without_direction eq $element || $direction eq '')
1678         {
1679             $element_without_direction = '';
1680         }
1681
1682         if ($element_without_crumbled eq $element || $crumbled eq '')
1683         {
1684             $element_without_crumbled = '';
1685         }
1686
1687         if (defined($graphic_without_element{$graphic}))
1688         {
1689             next;
1690         }
1691
1692         if (!defined($known_element{$element}))
1693         {
1694             # print STDERR "----- ERROR: unknown element '$element' -----\n";
1695
1696             push @unknown_graphics, $graphic;
1697
1698             next;
1699         }
1700
1701         if (defined($known_element{$element}))
1702         {
1703             print_element_to_graphic_entry($element,
1704                                            $gfx_action_default,
1705                                            $gfx_direction_default,
1706                                            $gfx_crumbled,
1707                                            $graphic);
1708         }
1709
1710         if (defined($known_element{$element_without_action}))
1711         {
1712             print_element_to_graphic_entry($element_without_action,
1713                                            $gfx_action,
1714                                            $gfx_direction,
1715                                            $gfx_crumbled,
1716                                            $graphic);
1717         }
1718
1719         if (defined($known_element{$element_without_direction}))
1720         {
1721             print_element_to_graphic_entry($element_without_direction,
1722                                            '-1',
1723                                            $gfx_direction,
1724                                            $gfx_crumbled,
1725                                            $graphic);
1726         }
1727
1728         if (defined($known_element{$element_without_crumbled}))
1729         {
1730             print_element_to_graphic_entry($element_without_crumbled,
1731                                            '-1',
1732                                            '-1',
1733                                            $gfx_crumbled,
1734                                            $graphic);
1735         }
1736     }
1737
1738     # dump list of additional elements
1739     foreach my $element (sort keys %additional_mappings)
1740     {
1741         print_element_to_graphic_entry($element, '-1', '-1', '-1',
1742                                        $additional_mappings{$element});
1743     }
1744
1745     # dump list of character elements
1746     foreach my $char (@chars)
1747     {
1748         my $element = "EL_CHAR_$char";
1749         my $graphic = "IMG_CHAR_$char";
1750
1751         if ($char ne $char_skip)
1752         {
1753             print_element_to_graphic_entry($element, '-1', '-1', '-1',$graphic);
1754         }
1755     }
1756     foreach my $char (@chars)
1757     {
1758         my $element = "EL_STEEL_CHAR_$char";
1759         my $graphic = "IMG_STEEL_CHAR_$char";
1760
1761         if ($char ne $char_skip)
1762         {
1763             print_element_to_graphic_entry($element, '-1', '-1', '-1',$graphic);
1764         }
1765     }
1766
1767     # dump list of custom elements
1768     for (my $i = 0; $i < $num_custom_elements; $i++)
1769     {
1770         my $element = sprintf("EL_CUSTOM_%d", $i + 1);
1771         my $graphic = sprintf("IMG_CUSTOM_%d", $i + 1);
1772
1773         print_element_to_graphic_entry($element, '-1', '-1', '-1', $graphic);
1774     }
1775
1776     # dump list of group elements
1777     for (my $i = 0; $i < $num_group_elements; $i++)
1778     {
1779         my $element = sprintf("EL_GROUP_%d", $i + 1);
1780         my $graphic = sprintf("IMG_GROUP_%d", $i + 1);
1781
1782         print_element_to_graphic_entry($element, '-1', '-1', '-1', $graphic);
1783     }
1784
1785     # dump list of empty elements
1786     for (my $i = 0; $i < $num_empty_elements; $i++)
1787     {
1788         my $element = sprintf("EL_EMPTY_SPACE_%d", $i + 1);
1789         my $graphic = sprintf("IMG_EMPTY_SPACE_%d", $i + 1);
1790
1791         print_element_to_graphic_entry($element, '-1', '-1', '-1', $graphic);
1792     }
1793
1794     print_element_to_graphic_entry('-1', '-1', '-1', '-1', '-1');
1795
1796     print "};\n";
1797
1798     close FILE;
1799
1800     if (scalar(@unknown_graphics) > 0)
1801     {
1802         print STDERR "-" x 79 . "\n";
1803         print STDERR "The following graphics cannot be associated with any element:\n";
1804
1805         foreach my $graphic (@unknown_graphics)
1806         {
1807             print STDERR "- $graphic\n";
1808         }
1809
1810         print STDERR "-" x 79 . "\n";
1811     }
1812
1813     print_file_footer($filename_conf_e2g_c);
1814 }
1815
1816 sub print_element_to_special_graphic_list
1817 {
1818     my %graphic_without_element =
1819         (
1820          'IMG_GLOBAL_DOOR'              => 1,
1821          );
1822
1823     my %additional_mappings =
1824         (
1825          # old elements which are mapped to other elements when playing
1826          #'EL_BUG'                      => 'IMG_BUG_RIGHT',
1827          #'EL_SPACESHIP'                => 'IMG_SPACESHIP_RIGHT',
1828          #'EL_PACMAN'                   => 'IMG_PACMAN_RIGHT',
1829          );
1830
1831     my @elements_with_editor_graphic =
1832         (
1833          'char_space',
1834          'steel_char_space'
1835          );
1836
1837     my @unknown_graphics = ();
1838     my %known_element     = get_known_element_definitions();
1839     my %known_special_arg = get_known_special_arg_definitions();
1840
1841     # ---------- read graphic file definitions ----------
1842
1843     my $filename = "$src_path/conf_gfx.c";
1844
1845     print_file_header($filename_conf_esg_c, $text_esg_c);
1846
1847     open(FILE, "$filename") ||
1848         fail("cannot open file '$filename' for reading");
1849
1850     print "static struct\n";
1851     print "{\n";
1852     print "  int element;\n";
1853     print "  int special;\n";
1854     print "\n";
1855     print "  int graphic;\n";
1856     print "}\n";
1857     print "element_to_special_graphic[] =\n";
1858     print "{\n";
1859
1860     while (<FILE>)
1861     {
1862         chomp;                          # cut trailing newline
1863
1864         if (/NO_MORE_ELEMENT_IMAGES/)   # keyword to stop parsing file
1865         {
1866             last;
1867         }
1868
1869         if (!contains_image_file($_))   # skip all lines without image file
1870         {
1871             next;
1872         }
1873
1874         s/^  \{ \"//;                   # cut all leading ...
1875         s/\",.*$//;                     # ... and trailing garbage
1876
1877         my $token = $_;
1878         my $object;
1879         my $special;
1880
1881         if ($token =~ /^font\./)        # skip all font definitions
1882         {
1883             next;
1884         }
1885
1886         if ($token =~ /^background\./)  # skip all background image definitions
1887         {
1888             next;
1889         }
1890
1891         if ($token =~ /^(.*)\.([^\.]+)$/ &&
1892             defined($known_special_arg{$2}))
1893         {
1894             $object = $1;
1895             $special = "GFX_SPECIAL_ARG_" . $2;
1896         }
1897         else
1898         {
1899             next;                       # skip all default definitions
1900         }
1901
1902         $token  =~ s/(.*)/uc($1)/eg;    # convert all characters to upper case
1903         $object =~ s/(.*)/uc($1)/eg;    # convert all characters to upper case
1904
1905         $token  =~ s/\./_/g;
1906         $object =~ s/\./_/g;
1907
1908         # print STDERR "'$token' => '$object'\n";
1909
1910         my $element = "EL_$object";
1911         my $graphic = "IMG_$token";
1912
1913         if (defined($graphic_without_element{$graphic}))
1914         {
1915             next;
1916         }
1917
1918         if (!defined($known_element{$element}))
1919         {
1920             # print STDERR "----- ERROR: unknown element '$element' -----\n";
1921
1922             push @unknown_graphics, $graphic;
1923
1924             next;
1925         }
1926
1927         print_element_to_special_graphic_entry($element,
1928                                                $special,
1929                                                $graphic);
1930     }
1931
1932     # dump list of additional elements
1933     foreach my $element (sort keys %additional_mappings)
1934     {
1935         print_element_to_special_graphic_entry($element,
1936                                                'GFX_SPECIAL_ARG_EDITOR',
1937                                                $additional_mappings{$element});
1938         print_element_to_special_graphic_entry($element,
1939                                                'GFX_SPECIAL_ARG_PREVIEW',
1940                                                $additional_mappings{$element});
1941     }
1942
1943     # dump list of custom element editor graphics
1944     for (my $i = 0; $i < $num_custom_elements; $i++)
1945     {
1946         my $element = sprintf("EL_CUSTOM_%d", $i + 1);
1947         my $graphic = sprintf("IMG_CUSTOM_%d_EDITOR", $i + 1);
1948
1949         print_element_to_special_graphic_entry($element,
1950                                                'GFX_SPECIAL_ARG_EDITOR',
1951                                                $graphic);
1952     }
1953
1954     # dump list of group element editor graphics
1955     for (my $i = 0; $i < $num_group_elements; $i++)
1956     {
1957         my $element = sprintf("EL_GROUP_%d", $i + 1);
1958         my $graphic = sprintf("IMG_GROUP_%d_EDITOR", $i + 1);
1959
1960         print_element_to_special_graphic_entry($element,
1961                                                'GFX_SPECIAL_ARG_EDITOR',
1962                                                $graphic);
1963     }
1964
1965     # dump list of empty element editor graphics
1966     for (my $i = 0; $i < $num_empty_elements; $i++)
1967     {
1968         my $element = sprintf("EL_EMPTY_SPACE_%d", $i + 1);
1969         my $graphic = sprintf("IMG_EMPTY_SPACE_%d_EDITOR", $i + 1);
1970
1971         print_element_to_special_graphic_entry($element,
1972                                                'GFX_SPECIAL_ARG_EDITOR',
1973                                                $graphic);
1974     }
1975
1976     # dump other special editor graphics
1977     foreach my $token (@elements_with_editor_graphic)
1978     {
1979         my $element = 'EL_'  . uc($token);
1980         my $graphic = 'IMG_' . uc($token) . '_EDITOR';
1981
1982         print_element_to_special_graphic_entry($element,
1983                                                'GFX_SPECIAL_ARG_EDITOR',
1984                                                $graphic);
1985     }
1986
1987     print_element_to_special_graphic_entry('-1', '-1', '-1');
1988
1989     print "};\n";
1990
1991     close FILE;
1992
1993     if (scalar(@unknown_graphics) > 0)
1994     {
1995         print STDERR "-" x 79 . "\n";
1996         print STDERR "The following graphics cannot be associated with any element:\n";
1997
1998         foreach my $graphic (@unknown_graphics)
1999         {
2000             print STDERR "- $graphic\n";
2001         }
2002
2003         print STDERR "-" x 79 . "\n";
2004     }
2005
2006     print_file_footer($filename_conf_esg_c);
2007 }
2008
2009 sub print_element_to_sound_list
2010 {
2011     my %sound_without_action =
2012         (
2013          'SND_AMOEBA_TURNING_TO_GEM'            => 1,
2014          'SND_AMOEBA_TURNING_TO_ROCK'           => 1,
2015          'SND_BD_AMOEBA_TURNING_TO_GEM'         => 1,
2016          'SND_BD_AMOEBA_TURNING_TO_ROCK'        => 1,
2017
2018          # no special case anymore after adding action ".splashing"
2019          # 'SND_ACID_SPLASHING'                 => 1,
2020          );
2021
2022     my @unknown_sounds = ();
2023     my %known_element       = get_known_element_definitions();
2024     my %known_element_class = get_known_element_class_definitions();
2025     my %known_action        = get_known_action_definitions();
2026
2027     # ---------- read sound file definitions ----------
2028
2029     my $filename = "$src_path/conf_snd.c";
2030
2031     print_file_header($filename_conf_e2s_c, $text_e2s_c);
2032
2033     open(FILE, "$filename") ||
2034         fail("cannot open file '$filename' for reading");
2035
2036     print "static struct\n";
2037     print "{\n";
2038     print "  int element;\n";
2039     print "  boolean is_class;\n";
2040     print "  int action;\n";
2041     print "\n";
2042     print "  int sound;\n";
2043     print "}\n";
2044     print "element_to_sound[] =\n";
2045     print "{\n";
2046
2047     while (<FILE>)
2048     {
2049         chomp;                          # cut trailing newline
2050
2051         if (/NO_MORE_ELEMENT_SOUNDS/)   # keyword to stop parsing file
2052         {
2053             last;
2054         }
2055
2056         if (!contains_sound_file($_))   # skip all lines without sound file
2057         {
2058             next;
2059         }
2060
2061         s/^  \{ \"//;                   # cut all leading ...
2062         s/\",.*$//;                     # ... and trailing garbage
2063
2064         my $token = $_;
2065
2066         $token = uc($token);            # convert all characters to upper case
2067
2068         my $snd_action_default = '-1';
2069         my $snd_action = $snd_action_default;
2070
2071         my $object = $token;
2072         my $action = '';
2073
2074         if ($object =~ /^(.*)\.([A-Z0-9_]+)$/ && defined($known_action{$2}))
2075         {
2076             $object = $1;
2077             $action = $2;
2078
2079             $snd_action = "ACTION_$action";
2080             $snd_action_default = $snd_action;
2081         }
2082
2083         $token =~ s/\./_/g;
2084         $object =~ s/\./_/g;    # needed for "invisible_sand.active.digging"
2085
2086         if ($object =~ /^\[(.+)\]$/)
2087         {
2088             $object = 'CLASS_' . $1;
2089         }
2090
2091         # print STDERR "'$token' => '$object', '$action'\n";
2092
2093         my $full_element = "EL_$token";
2094         my $base_element = "EL_$object";
2095
2096         my $element = $base_element;
2097         my $sound = $token;
2098
2099         if ($sound =~ /^\[.+\]/)
2100         {
2101             $sound =~ s/\[//;           # element class sound; begin ...
2102             $sound =~ s/\]//;           # ... and end of definition token
2103             $sound =~ s/^/CLASS_/;      # add class identifier
2104         }
2105
2106         $sound = "SND_$sound";
2107
2108         my $element_without_action = $full_element;
2109         $element_without_action =~ s/_$action$//;
2110
2111         my $element_class_without_action = $full_element;
2112         $element_without_action =~ s/_$action$//;
2113
2114         if (defined($known_element_class{$full_element}))
2115         {
2116             $element = $full_element;
2117
2118             $snd_action_default = '-1';
2119         }
2120
2121         if ($element_without_action eq $element || $action eq '')
2122         {
2123             $element_without_action = '';
2124         }
2125
2126         if (defined($sound_without_action{$sound}))
2127         {
2128             next;
2129         }
2130
2131         if (!defined($known_element{$element}) &&
2132             !defined($known_element_class{$element}))
2133         {
2134             # print STDERR "----- ERROR: unknown element '$element' -----\n";
2135
2136             push @unknown_sounds, $sound;
2137
2138             next;
2139         }
2140
2141         if (!($element =~ /_CLASS_/) &&
2142             defined($known_element{$element}))
2143         {
2144             print_element_to_sound_entry($element, "FALSE",
2145                                          $snd_action_default,
2146                                          $sound);
2147         }
2148
2149         if (!($element =~ /_CLASS_/) &&
2150             defined($known_element{$element_without_action}))
2151         {
2152             print_element_to_sound_entry($element_without_action, "FALSE",
2153                                          $snd_action,
2154                                          $sound);
2155         }
2156
2157         if ($element =~ /_CLASS_/ &&
2158             defined($known_element_class{$element}))
2159         {
2160             my $class_element = $known_element_class{$element};
2161
2162             print_element_to_sound_entry($class_element, "TRUE",
2163                                          $snd_action_default,
2164                                          $sound);
2165         }
2166
2167         if ($element =~ /_CLASS_/ &&
2168             defined($known_element_class{$element_without_action}))
2169         {
2170             my $class_element = $known_element_class{$element_without_action};
2171
2172             print_element_to_sound_entry($class_element, "TRUE",
2173                                          $snd_action,
2174                                          $sound);
2175         }
2176     }
2177
2178     print_element_to_sound_entry('-1', '-1', '-1', '-1');
2179
2180     print "};\n";
2181
2182     close FILE;
2183
2184     if (scalar(@unknown_sounds) > 0)
2185     {
2186         print STDERR "-" x 79 . "\n";
2187         print STDERR "The following sounds cannot be associated with any element or element class:\n";
2188
2189         foreach my $sound (@unknown_sounds)
2190         {
2191             print STDERR "- $sound\n";
2192         }
2193
2194         print STDERR "-" x 79 . "\n";
2195     }
2196
2197     print_file_footer($filename_conf_e2s_c);
2198 }
2199
2200 sub print_font_to_graphic_list
2201 {
2202     my @unknown_graphics = ();
2203     my %known_font        = get_known_font_definitions();
2204     my %known_special_arg = get_known_special_arg_definitions();
2205
2206     # ---------- read graphic file definitions ----------
2207
2208     my $filename = "$src_path/conf_gfx.c";
2209
2210     print_file_header($filename_conf_fnt_c, $text_fnt_c);
2211
2212     open(FILE, "$filename") ||
2213         fail("cannot open file '$filename' for reading");
2214
2215     print "static struct\n";
2216     print "{\n";
2217     print "  int font_nr;\n";
2218     print "  int special;\n";
2219     print "\n";
2220     print "  int graphic;\n";
2221     print "}\n";
2222     print "font_to_graphic[] =\n";
2223     print "{\n";
2224
2225     while (<FILE>)
2226     {
2227         chomp;                          # cut trailing newline
2228
2229         if (!contains_image_file($_))   # skip all lines without image file
2230         {
2231             next;
2232         }
2233
2234         s/^  \{ \"//;                   # cut all leading ...
2235         s/\",.*$//;                     # ... and trailing garbage
2236
2237         my $token = $_;
2238         my $font;
2239         my $special;
2240         my $graphic;
2241
2242         if ($token =~ /^(font\..*)$/)
2243         {
2244             $font = $token;
2245             $special = '-1';
2246
2247             if ($token =~ /^(.*)\.([^\.]+)$/ &&
2248                 defined($known_special_arg{$2}))
2249             {
2250                 $font = $1;
2251                 $special = "GFX_SPECIAL_ARG_" . $2;
2252             }
2253         }
2254         else
2255         {
2256             next;                       # skip all non-font definitions
2257         }
2258
2259         $token =~ s/(.*)/uc($1)/eg;     # convert all characters to upper case
2260         $font  =~ s/(.*)/uc($1)/eg;     # convert all characters to upper case
2261
2262         $token =~ s/\./_/g;
2263         $font  =~ s/\./_/g;
2264
2265         # print STDERR "'$token' => '$font'\n";
2266
2267         $graphic = "IMG_$token";
2268
2269         if (!defined($known_font{$font}))
2270         {
2271             # print STDERR "----- ERROR: unknown font '$font' -----\n";
2272
2273             push @unknown_graphics, $graphic;
2274
2275             next;
2276         }
2277
2278         print_font_to_graphic_entry($font,
2279                                     $special,
2280                                     $graphic);
2281     }
2282
2283     print_font_to_graphic_entry('-1', '-1', '-1');
2284
2285     print "};\n";
2286
2287     close FILE;
2288
2289     if (scalar(@unknown_graphics) > 0)
2290     {
2291         print STDERR "-" x 79 . "\n";
2292         print STDERR "The following graphics cannot be associated with any font:\n";
2293
2294         foreach my $graphic (@unknown_graphics)
2295         {
2296             print STDERR "- $graphic\n";
2297         }
2298
2299         print STDERR "-" x 79 . "\n";
2300     }
2301
2302     print_file_footer($filename_conf_fnt_c);
2303 }
2304
2305 sub print_gamemode_to_sound_list
2306 {
2307     my %known_prefix = get_known_sound_prefix_definitions();
2308     my %known_special_arg = get_known_special_arg_definitions();
2309
2310     # ---------- read music file definitions ----------
2311
2312     my $filename = "$src_path/conf_snd.c";
2313
2314     print_file_header($filename_conf_g2s_c, $text_g2s_c);
2315
2316     open(FILE, "$filename") ||
2317         fail("cannot open file '$filename' for reading");
2318
2319     print "static struct\n";
2320     print "{\n";
2321     print "  int gamemode;\n";
2322     print "\n";
2323     print "  int sound;\n";
2324     print "}\n";
2325     print "gamemode_to_sound[] =\n";
2326     print "{\n";
2327
2328     while (<FILE>)
2329     {
2330         chomp;                          # cut trailing newline
2331
2332         if (!contains_sound_file($_))   # skip all lines without sound file
2333         {
2334             next;
2335         }
2336
2337         if (/\[not used\]/)
2338         {
2339             next;
2340         }
2341
2342         s/^  \{ \"//;                   # cut all leading ...
2343         s/\",.*$//;                     # ... and trailing garbage
2344
2345         my $token = $_;
2346         my $gamemode = -1;
2347         # my $level = -1;               # ???
2348
2349         if (defined($known_prefix{$token}))
2350         {
2351             # no special arg defined
2352         }
2353         elsif ($token =~ /^(.*)\.([^\.]+)$/ &&
2354                defined($known_prefix{$1}) &&
2355                defined($known_special_arg{$2}))
2356         {
2357             $gamemode = "GFX_SPECIAL_ARG_" . $2;
2358         }
2359         else
2360         {
2361             next;
2362         }
2363
2364 #       if ($token =~ /^(.*)\./ &&
2365 #           !defined($known_prefix{$1}))
2366 #       {
2367 #           next;
2368 #       }
2369 #
2370 #       if ($token =~ /^(.*)\.([^\.]+)$/ &&
2371 #           defined($known_special_arg{$2}))
2372 #       {
2373 #           $gamemode = "GFX_SPECIAL_ARG_" . $2;
2374 #       }
2375
2376         $token =~ s/(.*)/uc($1)/eg;     # convert all characters to upper case
2377         $token =~ s/\./_/g;
2378
2379         my $sound = "SND_$token";
2380
2381         # print STDERR "'$token' => '$sound'\n";
2382
2383         print_gamemode_to_sound_entry($gamemode, $sound);
2384     }
2385
2386     print_gamemode_to_sound_entry('-1', '-1');
2387
2388     print "};\n";
2389
2390     close FILE;
2391
2392     print_file_footer($filename_conf_g2s_c);
2393 }
2394
2395 sub print_gamemode_to_music_list
2396 {
2397     my %known_prefix = get_known_music_prefix_definitions();
2398     my %known_special_arg = get_known_special_arg_definitions();
2399
2400     # ---------- read music file definitions ----------
2401
2402     my $filename = "$src_path/conf_mus.c";
2403
2404     print_file_header($filename_conf_g2m_c, $text_g2m_c);
2405
2406     open(FILE, "$filename") ||
2407         fail("cannot open file '$filename' for reading");
2408
2409     print "static struct\n";
2410     print "{\n";
2411     print "  int gamemode;\n";
2412     print "\n";
2413     print "  int music;\n";
2414     print "}\n";
2415     print "gamemode_to_music[] =\n";
2416     print "{\n";
2417
2418     while (<FILE>)
2419     {
2420         chomp;                          # cut trailing newline
2421
2422         if (!contains_music_file($_))   # skip all lines without music file
2423         {
2424             next;
2425         }
2426
2427         s/^  \{ \"//;                   # cut all leading ...
2428         s/\",.*$//;                     # ... and trailing garbage
2429
2430         my $token = $_;
2431         my $gamemode = -1;
2432
2433         if (defined($known_prefix{$token}))
2434         {
2435             # no special arg defined
2436         }
2437         elsif ($token =~ /^(.*)\.([^\.]+)$/ &&
2438                defined($known_prefix{$1}) &&
2439                defined($known_special_arg{$2}))
2440         {
2441             $gamemode = "GFX_SPECIAL_ARG_" . $2;
2442         }
2443         else
2444         {
2445             next;
2446         }
2447
2448 #       my $prefix = $token;
2449 #       $prefix =~ s/\..*$//;
2450 #
2451 ##      if ($token =~ /^(.*)\./ &&
2452 ##          !defined($known_prefix{$1}))
2453 #       if (!defined($known_prefix{$prefix}))
2454 #       {
2455 #           next;
2456 #       }
2457 #
2458 #       if ($token =~ /^(.*)\.([^\.]+)$/ &&
2459 #           defined($known_special_arg{$2}))
2460 #       {
2461 #           $gamemode = "GFX_SPECIAL_ARG_" . $2;
2462 #       }
2463
2464         $token =~ s/(.*)/uc($1)/eg;     # convert all characters to upper case
2465         $token =~ s/\./_/g;
2466
2467         my $music = "MUS_$token";
2468
2469         # print STDERR "'$token' => '$music'\n";
2470
2471         print_gamemode_to_music_entry($gamemode, $music);
2472     }
2473
2474     print_gamemode_to_music_entry('-1', '-1');
2475
2476     print "};\n";
2477
2478     close FILE;
2479
2480     print_file_footer($filename_conf_g2m_c);
2481 }
2482
2483 sub print_config_vars
2484 {
2485     # ---------- read graphic file definitions ----------
2486
2487     my $filename = "$src_path/conf_gfx.c";
2488
2489     print_file_header($filename_conf_var_c, $text_var_c);
2490
2491     open(FILE, "$filename") ||
2492         fail("cannot open file '$filename' for reading");
2493
2494     print "struct TokenIntPtrInfo image_config_vars[] =\n";
2495     print "{\n";
2496
2497     my $start_parsing = 0;
2498
2499     while (<FILE>)
2500     {
2501         chomp;                          # cut trailing newline
2502
2503         if (/CONFIG_VARS_START/)        # keyword to start parsing file
2504         {
2505             $start_parsing = 1;
2506         }
2507
2508         if (!$start_parsing)
2509         {
2510             next;
2511         }
2512
2513         if (/^\s*\{\s*\"([^\"]+)\"/)    # config token found
2514         {
2515             my $token = $1;
2516             my $var = $token;
2517
2518             # --- some prefix replacements ---
2519
2520             $var =~ s/^main\./menu.main./;
2521             $var =~ s/^setup\./menu.setup./;
2522             $var =~ s/^scores\./menu.scores./;
2523             $var =~ s/^\[player\]\./game.player_/;
2524             $var =~ s/^\[title_initial\]/title_initial_default/;
2525             $var =~ s/^\[title\]/title_default/;
2526             $var =~ s/^\[titlescreen_initial\]/titlescreen_initial_default/;
2527             $var =~ s/^\[titlescreen\]/titlescreen_default/;
2528             $var =~ s/^\[titlemessage_initial\]/titlemessage_initial_default/;
2529             $var =~ s/^\[titlemessage\]/titlemessage_default/;
2530
2531             if ($var =~ /^titlescreen.*(\d)/ ||
2532                 $var =~ /^titlemessage.*(\d)/ ||
2533                 $var =~ /^game.panel.key_(\d)/ ||
2534                 $var =~ /^game.panel.inventory_first_(\d)/ ||
2535                 $var =~ /^game.panel.inventory_last_(\d)/ ||
2536                 $var =~ /^game.panel.conveyor_belt_(\d)\./ ||
2537                 $var =~ /^game.panel.element_(\d)\./ ||
2538                 $var =~ /^game.panel.graphic_(\d)\./ ||
2539                 $var =~ /^game.panel.ce_score_(\d)\./)
2540             {
2541                 my $number = $1;
2542                 my $array_pos = int($number) - 1;
2543                 $var =~ s/_$number/\[$array_pos\]/;
2544             }
2545             elsif ($var =~ /^game.panel.conveyor_belt_(\d)(_switch)/ ||
2546                    $var =~ /^game.panel.element_(\d)(_count)/ ||
2547                    $var =~ /^game.panel.ce_score_(\d)(_element)/)
2548             {
2549                 my $number = $1;
2550                 my $suffix = $2;
2551                 my $array_pos = int($number) - 1;
2552                 $var =~ s/_$number$suffix/$suffix\[$array_pos\]/;
2553             }
2554
2555             # --- some suffix replacements ---
2556
2557             $var =~ s/^(menu\.main\..*)\.chars$/$1.size/;
2558             $var =~ s/^(tape\.text\..*)\.chars$/$1.size/;
2559             $var =~ s/^(game\.panel\..*)\.chars$/$1.size/;
2560             $var =~ s/^(game\.panel\..*)\.tile_size$/$1.size/;
2561             $var =~ s/^(request\.button\..*)\.tile_size$/$1.size/;
2562             $var =~ s/\.digits$/.size/;
2563             $var =~ s/\.2nd_offset$/.offset2/;
2564             $var =~ s/\.2nd_xoffset$/.xoffset2/;
2565             $var =~ s/\.2nd_yoffset$/.yoffset2/;
2566             $var =~ s/\.element$/.id/;
2567             $var =~ s/\.draw_order$/.sort_priority/;
2568
2569             $var =~ s/\.font_[a-z]+$/.font_alt/;
2570             $var =~ s/\.INFO\[([A-Z]+)\](.*)$/_info\[GFX_SPECIAL_ARG_INFO_$1\]$2/;
2571             $var =~ s/\.SETUP\[([A-Z0-9_]+)\](.*)$/_setup\[GFX_SPECIAL_ARG_SETUP_$1\]$2/;
2572             $var =~ s/\.([A-Z]+)$/\[GFX_SPECIAL_ARG_$1\]/;
2573             $var =~ s/\.([A-Z]+)\./\[GFX_SPECIAL_ARG_$1\]./;
2574
2575             if ($var =~ /^(menu.(enter|leave|next)_screen)(.[a-z_]+)$/)
2576             {
2577                 $var = $1 . "[GFX_SPECIAL_ARG_DEFAULT]" . $3;
2578             }
2579
2580             if ($var =~ /^menu.(draw_[xy]offset|list_size)$/)
2581             {
2582                 $var .= "[GFX_SPECIAL_ARG_DEFAULT]";
2583             }
2584
2585             if ($var =~ /^(viewport.(window|playfield|door_[12]))(.[a-z_]+)$/)
2586             {
2587                 $var = $1 . "[GFX_SPECIAL_ARG_DEFAULT]" . $3;
2588             }
2589
2590             print_config_var_entry("\"$token\"", "&$var");
2591
2592             if ($var =~ /^(title)_default/ ||
2593                 $var =~ /^(title_initial)_default/ ||
2594                 $var =~ /^(titlescreen.*)\[\d\]/ ||
2595                 $var =~ /^(titlemessage.*)\[\d\]/)
2596             {
2597                 my $prefix = $1;
2598                 $var =~ s/^$prefix/${prefix}_first/;
2599
2600                 print_config_var_entry("\"$token\"", "&$var");
2601             }
2602         }
2603     }
2604
2605     print_config_var_entry('NULL', 'NULL');
2606
2607     print "};\n";
2608
2609     close FILE;
2610
2611
2612     # ---------- read sound file definitions ----------
2613
2614     $filename = "$src_path/conf_snd.c";
2615
2616     open(FILE, "$filename") ||
2617         fail("cannot open file '$filename' for reading");
2618
2619     print "struct TokenIntPtrInfo sound_config_vars[] =\n";
2620     print "{\n";
2621
2622     $start_parsing = 0;
2623
2624     while (<FILE>)
2625     {
2626         chomp;                          # cut trailing newline
2627
2628         if (/CONFIG_VARS_START/)        # keyword to start parsing file
2629         {
2630             $start_parsing = 1;
2631         }
2632
2633         if (!$start_parsing)
2634         {
2635             next;
2636         }
2637
2638         if (/^\s*\{\s*\"([^\"]+)\"/)    # config token found
2639         {
2640             my $token = $1;
2641             my $var = $token;
2642
2643             print_config_var_entry("\"$token\"", "&$var");
2644         }
2645     }
2646
2647     print_config_var_entry('NULL', 'NULL');
2648
2649     print "};\n";
2650
2651     close FILE;
2652
2653     print_file_footer($filename_conf_var_c);
2654 }
2655
2656 sub print_active_states
2657 {
2658     # ---------- read graphic file definitions ----------
2659
2660     my %known_element = get_known_element_definitions();
2661     my %known_button  = get_known_button_definitions();
2662     my %known_font    = get_known_font_definitions();
2663
2664     print_file_header($filename_conf_act_c, $text_act_c);
2665
2666     print "static struct\n";
2667     print "{\n";
2668     print "  int element;\n";
2669     print "  int element_active;\n";
2670     print "}\n";
2671     print "element_with_active_state[] =\n";
2672     print "{\n";
2673
2674     foreach my $element (sort keys %known_element)
2675     {
2676         my $element_active = $element . '_ACTIVE';
2677
2678         if (defined($known_element{$element_active}))
2679         {
2680             print_active_state_entry($element, $element_active);
2681         }
2682     }
2683
2684     print_active_state_entry('-1', '-1');
2685
2686     print "};\n";
2687
2688     print "\n";
2689     print "\n";
2690     print "static struct\n";
2691     print "{\n";
2692     print "  int button;\n";
2693     print "  int button_active;\n";
2694     print "}\n";
2695     print "button_with_active_state[] =\n";
2696     print "{\n";
2697
2698     foreach my $button (sort keys %known_button)
2699     {
2700         my $button_active = $button . '_ACTIVE';
2701
2702         if (defined($known_button{$button_active}))
2703         {
2704             print_active_state_entry($button, $button_active);
2705         }
2706     }
2707
2708     print_active_state_entry('-1', '-1');
2709
2710     print "};\n";
2711
2712     print "\n";
2713     print "\n";
2714     print "static struct\n";
2715     print "{\n";
2716     print "  int font_nr;\n";
2717     print "  int font_nr_active;\n";
2718     print "}\n";
2719     print "font_with_active_state[] =\n";
2720     print "{\n";
2721
2722     foreach my $font (sort keys %known_font)
2723     {
2724         my $font_active = $font . '_ACTIVE';
2725
2726         if (defined($known_font{$font_active}))
2727         {
2728             print_active_state_entry($font, $font_active);
2729         }
2730     }
2731
2732     print_active_state_entry('-1', '-1');
2733
2734     print "};\n";
2735
2736     print_file_footer($filename_conf_act_c);
2737 }
2738
2739
2740 # =============================================================================
2741 # M A I N - P R O G R A M
2742 # =============================================================================
2743
2744 sub main
2745 {
2746     my $argc = scalar(@ARGV);
2747
2748     if ($argc == 0 || $ARGV[0] eq '-h' || $ARGV[0] eq '--help')
2749     {
2750         print "Usage: $0 <file>\n\n";
2751         print "Choose <file> from the following list:\n";
2752         print "- '$filename_conf_gfx_h'\n";
2753         print "- '$filename_conf_snd_h'\n";
2754         print "- '$filename_conf_mus_h'\n";
2755         print "- '$filename_conf_chr_c'\n";
2756         print "- '$filename_conf_chr_h'\n";
2757         print "- '$filename_conf_cus_c'\n";
2758         print "- '$filename_conf_cus_h'\n";
2759         print "- '$filename_conf_grp_c'\n";
2760         print "- '$filename_conf_grp_h'\n";
2761         print "- '$filename_conf_emp_c'\n";
2762         print "- '$filename_conf_emp_h'\n";
2763         print "- '$filename_conf_e2g_c'\n";
2764         print "- '$filename_conf_esg_c'\n";
2765         print "- '$filename_conf_fnt_c'\n";
2766         print "- '$filename_conf_g2s_c'\n";
2767         print "- '$filename_conf_g2m_c'\n";
2768         print "- '$filename_conf_var_c'\n";
2769         print "- '$filename_conf_act_c'\n";
2770
2771         exit 1;
2772     }
2773
2774     if ($ARGV[0] eq $filename_conf_gfx_h)
2775     {
2776         print_graphics_list();
2777     }
2778     elsif ($ARGV[0] eq $filename_conf_snd_h)
2779     {
2780         print_sounds_list();
2781     }
2782     elsif ($ARGV[0] eq $filename_conf_mus_h)
2783     {
2784         print_music_list();
2785     }
2786     elsif ($ARGV[0] eq $filename_conf_chr_c)
2787     {
2788         print_chars_graphics_list();
2789     }
2790     elsif ($ARGV[0] eq $filename_conf_chr_h)
2791     {
2792         print_chars_elements_list();
2793     }
2794     elsif ($ARGV[0] eq $filename_conf_cus_c)
2795     {
2796         print_custom_graphics_list();
2797     }
2798     elsif ($ARGV[0] eq $filename_conf_cus_h)
2799     {
2800         print_custom_elements_list();
2801     }
2802     elsif ($ARGV[0] eq $filename_conf_grp_c)
2803     {
2804         print_group_graphics_list();
2805     }
2806     elsif ($ARGV[0] eq $filename_conf_grp_h)
2807     {
2808         print_group_elements_list();
2809     }
2810     elsif ($ARGV[0] eq $filename_conf_emp_c)
2811     {
2812         print_empty_graphics_list();
2813     }
2814     elsif ($ARGV[0] eq $filename_conf_emp_h)
2815     {
2816         print_empty_elements_list();
2817     }
2818     elsif ($ARGV[0] eq $filename_conf_e2g_c)
2819     {
2820         print_element_to_graphic_list();
2821     }
2822     elsif ($ARGV[0] eq $filename_conf_esg_c)
2823     {
2824         print_element_to_special_graphic_list();
2825     }
2826     elsif ($ARGV[0] eq $filename_conf_e2s_c)
2827     {
2828         print_element_to_sound_list();
2829     }
2830     elsif ($ARGV[0] eq $filename_conf_fnt_c)
2831     {
2832         print_font_to_graphic_list();
2833     }
2834     elsif ($ARGV[0] eq $filename_conf_g2s_c)
2835     {
2836         print_gamemode_to_sound_list();
2837     }
2838     elsif ($ARGV[0] eq $filename_conf_g2m_c)
2839     {
2840         print_gamemode_to_music_list();
2841     }
2842     elsif ($ARGV[0] eq $filename_conf_var_c)
2843     {
2844         print_config_vars();
2845     }
2846     elsif ($ARGV[0] eq $filename_conf_act_c)
2847     {
2848         print_active_states();
2849     }
2850     else
2851     {
2852         print "Unknown option '$ARGV[0]'.\n";
2853
2854         exit 1;
2855     }
2856
2857     exit 0;
2858 }