--- /dev/null
+#!/usr/bin/perl -w
+
+# =============================================================================
+# create_element_defs.pl
+# -----------------------------------------------------------------------------
+# 2002-09-19 holger.schemel@mediaways.net
+# =============================================================================
+
+use strict;
+
+
+# =============================================================================
+# C O N F I G U R A T I O N S E C T I O N
+# =============================================================================
+
+my $base_path = ".";
+my $src_path = "$base_path/src";
+
+if (-d "../src") # we're already inside "src" directory
+{
+ $src_path = ".";
+}
+
+
+# -----------------------------------------------------------------------------
+# global variables
+# -----------------------------------------------------------------------------
+
+my $filename_header_tmpl = "$src_path/header.tmpl";
+
+my $filename_conf_gfx_h = 'conf_gfx.h';
+my $filename_conf_snd_h = 'conf_snd.h';
+my $filename_conf_mus_h = 'conf_mus.h';
+my $filename_conf_chr_c = 'conf_chr.c';
+my $filename_conf_chr_h = 'conf_chr.h';
+my $filename_conf_cus_c = 'conf_cus.c';
+my $filename_conf_cus_h = 'conf_cus.h';
+my $filename_conf_grp_c = 'conf_grp.c';
+my $filename_conf_grp_h = 'conf_grp.h';
+my $filename_conf_e2g_c = 'conf_e2g.c';
+my $filename_conf_esg_c = 'conf_esg.c';
+my $filename_conf_e2s_c = 'conf_e2s.c';
+my $filename_conf_fnt_c = 'conf_fnt.c';
+my $filename_conf_g2s_c = 'conf_g2s.c';
+my $filename_conf_g2m_c = 'conf_g2m.c';
+my $filename_conf_var_c = 'conf_var.c';
+my $filename_conf_act_c = 'conf_act.c';
+
+my $text_auto = 'this file was automatically generated -- do not edit by hand';
+my $text_gfx_h = 'values for graphics configuration (normal elements)';
+my $text_snd_h = 'values for sounds configuration';
+my $text_mus_h = 'values for music configuration';
+my $text_chr_c = 'values for graphics configuration (character elements)';
+my $text_chr_h = 'values for elements configuration (character elements)';
+my $text_cus_c = 'values for graphics configuration (custom elements)';
+my $text_cus_h = 'values for elements configuration (custom elements)';
+my $text_grp_c = 'values for graphics configuration (group elements)';
+my $text_grp_h = 'values for elements configuration (group elements)';
+my $text_e2g_c = 'values for element/graphics mapping configuration (normal)';
+my $text_esg_c = 'values for element/graphics mapping configuration (special)';
+my $text_e2s_c = 'values for element/sounds mapping configuration';
+my $text_fnt_c = 'values for font/graphics mapping configuration';
+my $text_g2s_c = 'values for gamemode/sound mapping configuration';
+my $text_g2m_c = 'values for gamemode/music mapping configuration';
+my $text_var_c = 'values for image and layout parameter configuration';
+my $text_act_c = 'values for active states of elements and fonts';
+
+my $num_custom_elements = 256;
+my $num_group_elements = 32;
+
+my $char_skip = '---[SKIP]---';
+
+my @chars =
+ (
+ 'SPACE',
+ 'EXCLAM',
+ 'QUOTEDBL',
+ 'NUMBERSIGN',
+ 'DOLLAR',
+ 'PERCENT',
+ 'AMPERSAND',
+ 'APOSTROPHE',
+ 'PARENLEFT',
+ 'PARENRIGHT',
+ 'ASTERISK',
+ 'PLUS',
+ 'COMMA',
+ 'MINUS',
+ 'PERIOD',
+ 'SLASH',
+
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'COLON',
+ 'SEMICOLON',
+ 'LESS',
+ 'EQUAL',
+ 'GREATER',
+ 'QUESTION',
+
+ 'AT',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F',
+ 'G',
+ 'H',
+ 'I',
+ 'J',
+ 'K',
+ 'L',
+ 'M',
+ 'N',
+ 'O',
+
+ 'P',
+ 'Q',
+ 'R',
+ 'S',
+ 'T',
+ 'U',
+ 'V',
+ 'W',
+ 'X',
+ 'Y',
+ 'Z',
+ 'BRACKETLEFT',
+ 'BACKSLASH',
+ 'BRACKETRIGHT',
+ 'ASCIICIRCUM',
+ 'UNDERSCORE',
+
+ 'COPYRIGHT',
+ 'AUMLAUT',
+ 'OUMLAUT',
+ 'UUMLAUT',
+ 'DEGREE',
+ 'TRADEMARK',
+ 'CURSOR',
+ $char_skip,
+ $char_skip,
+ $char_skip,
+ $char_skip,
+ $char_skip,
+ $char_skip,
+ 'BUTTON',
+ 'UP',
+ 'DOWN',
+ );
+
+
+# -----------------------------------------------------------------------------
+# start main program
+# -----------------------------------------------------------------------------
+
+main();
+exit 0;
+
+
+# =============================================================================
+# F U N C T I O N S
+# =============================================================================
+
+sub error
+{
+ my ($error_msg) = @_;
+
+ print STDERR "ERROR: ";
+ print STDERR "$error_msg\n";
+}
+
+sub fail
+{
+ my ($error_msg) = @_;
+
+ print STDERR "FATAL ";
+ error("$error_msg");
+
+ exit 1;
+}
+
+sub contains_image_file
+{
+ my ($line) = @_;
+
+ return ($line =~ /\".+\.pcx\"/ ||
+ $line =~ /UNDEFINED_FILENAME/);
+}
+
+sub contains_sound_file
+{
+ my ($line) = @_;
+
+ return ($line =~ /\".+\.wav\"/ ||
+ $line =~ /UNDEFINED_FILENAME/);
+}
+
+sub contains_music_file
+{
+ my ($line) = @_;
+
+ return ($line =~ /\".+\.wav\"/ ||
+ $line =~ /\".+\.mod\"/ ||
+ $line =~ /\".+\.mp3\"/ ||
+ $line =~ /UNDEFINED_FILENAME/);
+}
+
+sub print_file_header
+{
+ my ($filename, $comment) = @_;
+ my $filename_tmpl = 'xxxxxxxx.x';
+ my $filename_text = $filename;
+ my $filename_def = uc($filename);
+ $filename_def =~ s/\./_/;
+
+ $filename_text .= ' ' x (length($filename_tmpl) - length($filename_text));
+
+ open(FILE, "$filename_header_tmpl") ||
+ fail("cannot open file '$filename_header_tmpl' for reading");
+
+ while (<FILE>)
+ {
+ s/$filename_tmpl/$filename_text/;
+
+ print;
+ }
+
+ close FILE;
+
+ print "\n";
+ print "/* ----- $text_auto ----- */\n";
+ print "\n";
+ print "#ifndef $filename_def\n";
+ print "#define $filename_def\n";
+ print "\n";
+ print "/* $comment */\n";
+ print "\n";
+}
+
+sub print_file_footer
+{
+ my ($filename) = @_;
+ my $filename_def = uc($filename);
+ $filename_def =~ s/\./_/;
+
+ print "\n";
+ print "#endif /* $filename_def */\n";
+}
+
+sub get_tabs
+{
+ my ($text, $max_num_tabs) = @_;
+
+ my $num_tabs = $max_num_tabs - int(length($text) / 8);
+
+ if ($num_tabs < 1) # at least one tab needed as separator
+ {
+ $num_tabs = 1;
+ }
+
+ return "\t" x $num_tabs;
+}
+
+sub print_graphics_list
+{
+ my $filename = "$src_path/conf_gfx.c";
+
+ print_file_header($filename_conf_gfx_h, $text_gfx_h);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ my $max_num_tabs = 7;
+ my $i = 0;
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/^\#include "conf_chr.c"/) # dump list of character elements
+ {
+ foreach my $char (@chars)
+ {
+ my $prefix = $char;
+
+ $prefix =~ s/^/#define IMG_CHAR_/;
+
+ my $tabs = get_tabs($prefix, $max_num_tabs);
+
+ if ($char ne $char_skip)
+ {
+ print "$prefix$tabs$i\n";
+
+ $i++;
+ }
+
+ if (lc($char) eq 'space')
+ {
+ $prefix =~ s/$/_EDITOR/;
+
+ my $tabs = get_tabs($prefix, $max_num_tabs);
+
+ print "$prefix$tabs$i\n";
+
+ $i++;
+ }
+ }
+
+ foreach my $char (@chars)
+ {
+ my $prefix = $char;
+
+ $prefix =~ s/^/#define IMG_STEEL_CHAR_/;
+
+ my $tabs = get_tabs($prefix, $max_num_tabs);
+
+ if ($char ne $char_skip)
+ {
+ print "$prefix$tabs$i\n";
+
+ $i++;
+ }
+
+ if (lc($char) eq 'space')
+ {
+ $prefix =~ s/$/_EDITOR/;
+
+ my $tabs = get_tabs($prefix, $max_num_tabs);
+
+ print "$prefix$tabs$i\n";
+
+ $i++;
+ }
+ }
+ }
+
+ if (/^\#include "conf_cus.c"/) # dump list of custom elements
+ {
+ for (my $nr = 0; $nr < $num_custom_elements; $nr++)
+ {
+ my $line = sprintf("#define IMG_CUSTOM_%d", $nr + 1);
+
+ my $tabs = get_tabs($line, $max_num_tabs);
+
+ print "$line$tabs$i\n";
+
+ $i++;
+
+ $line = sprintf("#define IMG_CUSTOM_%d_EDITOR", $nr + 1);
+
+ $tabs = get_tabs($line, $max_num_tabs);
+
+ print "$line$tabs$i\n";
+
+ $i++;
+ }
+ }
+
+ if (/^\#include "conf_grp.c"/) # dump list of group elements
+ {
+ for (my $nr = 0; $nr < $num_group_elements; $nr++)
+ {
+ my $line = sprintf("#define IMG_GROUP_%d", $nr + 1);
+
+ my $tabs = get_tabs($line, $max_num_tabs);
+
+ print "$line$tabs$i\n";
+
+ $i++;
+
+ $line = sprintf("#define IMG_GROUP_%d_EDITOR", $nr + 1);
+
+ $tabs = get_tabs($line, $max_num_tabs);
+
+ print "$line$tabs$i\n";
+
+ $i++;
+ }
+ }
+
+ if (!contains_image_file($_)) # skip all lines without image file
+ {
+ next;
+ }
+
+ s/(.*)/uc($1)/eg; # convert all characters to upper case
+ s/\./_/g; # replace all '.' with '_'
+
+ s/^ \{ \"/#define IMG_/; # convert line
+ s/\",.*$//; # convert line
+
+ # dirty hack for making "ABC[DEF]" work as a "special" suffix
+ s/([^_])\[/$1_/;
+
+ # dirty hack for making "[default]" work as an element name
+ s/\[//;
+ s/\]//;
+
+ my $tabs = get_tabs($_, $max_num_tabs);
+
+ print "$_$tabs$i\n";
+
+ $i++;
+ }
+
+ my $summary = '#define NUM_IMAGE_FILES';
+ my $tabs = get_tabs($summary, $max_num_tabs);
+
+ print "\n$summary$tabs$i\n";
+
+ close FILE;
+
+ print_file_footer($filename_conf_gfx_h);
+}
+
+sub print_sounds_list
+{
+ my %known_element = get_known_element_definitions();
+
+ my $filename = "$src_path/conf_snd.c";
+
+ print_file_header($filename_conf_snd_h, $text_snd_h);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ my $max_num_tabs = 7;
+ my $i = 0;
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (!contains_sound_file($_)) # skip all lines without sound file
+ {
+ next;
+ }
+
+ if (/\[not used\]/ ||
+ / TEST / ||
+ /wav[^\}]*$/) # skip all lines without sound file
+ {
+ next;
+ }
+
+ s/(.*)/uc($1)/eg; # convert all characters to upper case
+ s/\./_/g; # replace all '.' with '_'
+
+ s/^ \{ \"//;
+ s/\",.*$//;
+
+ my $sound = $_;
+
+ if ($sound =~ /^\[.+\]/)
+ {
+ $sound =~ s/\[//; # element class sound; begin ...
+ $sound =~ s/\]//; # ... and end of definition token
+ $sound =~ s/^/CLASS_/; # add class identifier
+ }
+
+ $sound = "SND_$sound";
+
+ my $define_text = "#define $sound";
+ my $tabs = get_tabs($define_text, $max_num_tabs);
+
+ print "$define_text$tabs$i\n";
+
+ $i++;
+ }
+
+ my $summary = '#define NUM_SOUND_FILES';
+ my $tabs = get_tabs($summary, $max_num_tabs);
+
+ print "\n$summary$tabs$i\n";
+
+ close FILE;
+
+ print_file_footer($filename_conf_snd_h);
+}
+
+sub print_music_list
+{
+ my %known_prefix = get_known_music_prefix_definitions();
+
+ my $filename = "$src_path/conf_mus.c";
+
+ print_file_header($filename_conf_mus_h, $text_mus_h);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ my $max_num_tabs = 7;
+ my $i = 0;
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (!contains_music_file($_)) # skip all lines without music file
+ {
+ next;
+ }
+
+ if (/\[not used\]/ ||
+ / TEST / ||
+ /wav[^\}]*$/) # skip all lines without music file
+ {
+ next;
+ }
+
+ s/(.*)/uc($1)/eg; # convert all characters to upper case
+ s/\./_/g; # replace all '.' with '_'
+
+ s/^ \{ \"//;
+ s/\",.*$//;
+
+ my $music = $_;
+
+ $music = "MUS_$music";
+
+ my $define_text = "#define $music";
+ my $tabs = get_tabs($define_text, $max_num_tabs);
+
+ print "$define_text$tabs$i\n";
+
+ $i++;
+ }
+
+ my $summary = '#define NUM_MUSIC_FILES';
+ my $tabs = get_tabs($summary, $max_num_tabs);
+
+ print "\n$summary$tabs$i\n";
+
+ close FILE;
+
+ print_file_footer($filename_conf_mus_h);
+}
+
+sub print_chars_elements_list
+{
+ print_file_header($filename_conf_chr_h, $text_chr_h);
+
+ my $i = 0;
+
+ foreach my $char (@chars)
+ {
+ my $left = "#define EL_CHAR_$char";
+
+ my $tabs_left = get_tabs($left, 5);
+
+ my $right = sprintf("(EL_CHAR_ASCII0 + %d)", $i + 32);
+
+ if ($char ne $char_skip)
+ {
+ print "$left$tabs_left$right\n";
+ }
+
+ $i++;
+ }
+
+ $i = 0;
+
+ foreach my $char (@chars)
+ {
+ my $left = "#define EL_STEEL_CHAR_$char";
+
+ my $tabs_left = get_tabs($left, 5);
+
+ my $right = sprintf("(EL_STEEL_CHAR_ASCII0 + %d)", $i + 32);
+
+ if ($char ne $char_skip)
+ {
+ print "$left$tabs_left$right\n";
+ }
+
+ $i++;
+ }
+
+ print_file_footer($filename_conf_chr_c);
+}
+
+sub print_chars_graphics_list_line
+{
+ my ($token, $x, $y) = @_;
+
+ my @extensions =
+ (
+ '',
+ '.xpos',
+ '.ypos',
+ '.frames',
+ );
+
+ my $basename = ($token =~ /^steel_char/ ? 'RocksFontDC' : 'RocksFontEM' );
+
+ foreach my $ext (@extensions)
+ {
+ my $left = " \{ \"$token$ext\",";
+
+ my $tabs_left = get_tabs($left, 6);
+
+ my $right = ($ext eq '' ? $basename . '.pcx' :
+ $ext eq '.frames' ? '1' : '0');
+
+ if ($ext eq '.xpos')
+ {
+ $right = $x;
+ }
+ elsif ($ext eq '.ypos')
+ {
+ $right = $y;
+ }
+
+ $right = "\"$right\"";
+
+ my $tabs_right = get_tabs($right, 3);
+
+ print "$left$tabs_left$right$tabs_right},\n";
+ }
+}
+
+sub print_chars_graphics_list
+{
+ print_file_header($filename_conf_chr_c, $text_chr_c);
+
+ my $i = 0;
+
+ foreach my $char (@chars)
+ {
+ if ($char ne $char_skip)
+ {
+ my $x = $i % 16;
+ my $y = int($i / 16);
+
+ print_chars_graphics_list_line(lc("char_$char"), $x, $y);
+ }
+
+ if (lc($char) eq 'space')
+ {
+ print_chars_graphics_list_line("char_space.EDITOR", 7, 4);
+ }
+
+ if ($char ne $char_skip)
+ {
+ print "\n";
+ }
+
+ $i++;
+ }
+
+ $i = 0;
+
+ foreach my $char (@chars)
+ {
+ if ($char ne $char_skip)
+ {
+ my $x = $i % 16;
+ my $y = int($i / 16);
+
+ print_chars_graphics_list_line(lc("steel_char_$char"), $x, $y);
+ }
+
+ if (lc($char) eq 'space')
+ {
+ print_chars_graphics_list_line("steel_char_space.EDITOR", 7, 4);
+ }
+
+ if ($char ne $char_skip)
+ {
+ print "\n";
+ }
+
+ $i++;
+ }
+
+ print_file_footer($filename_conf_chr_c);
+}
+
+sub print_custom_elements_list
+{
+ print_file_header($filename_conf_cus_h, $text_cus_h);
+
+ for (my $i = 0; $i < $num_custom_elements; $i++)
+ {
+ my $left = sprintf("#define EL_CUSTOM_%d", $i + 1);
+
+ my $tabs_left = get_tabs($left, 5);
+
+ my $right = "(EL_CUSTOM_START + $i)";
+
+ print "$left$tabs_left$right\n";
+ }
+
+ print_file_footer($filename_conf_cus_c);
+}
+
+sub print_group_elements_list
+{
+ print_file_header($filename_conf_grp_h, $text_grp_h);
+
+ for (my $i = 0; $i < $num_group_elements; $i++)
+ {
+ my $left = sprintf("#define EL_GROUP_%d", $i + 1);
+
+ my $tabs_left = get_tabs($left, 5);
+
+ my $right = "(EL_GROUP_START + $i)";
+
+ print "$left$tabs_left$right\n";
+ }
+
+ print_file_footer($filename_conf_grp_c);
+}
+
+sub print_custom_graphics_list
+{
+ my @extensions1 =
+ (
+ '',
+ '.xpos',
+ '.ypos',
+ '.frames',
+ );
+ my @extensions2 =
+ (
+ '',
+ '.xpos',
+ '.ypos',
+ );
+
+ print_file_header($filename_conf_cus_c, $text_cus_c);
+
+ for (my $i = 0; $i < $num_custom_elements; $i++)
+ {
+ foreach my $ext (@extensions1)
+ {
+ my $left = sprintf(" \{ \"custom_%d$ext\",", $i + 1);
+
+ my $tabs_left = get_tabs($left, 6);
+
+ # my $right = ($ext eq '' ? 'RocksElements.pcx' :
+ my $right = ($ext eq '' ? 'RocksCE.pcx' :
+ $ext eq '.frames' ? '1' : '0');
+
+ if ($ext eq '.xpos')
+ {
+ # $right = 7;
+ $right = int($i % 16);
+ }
+ elsif ($ext eq '.ypos')
+ {
+ # $right = 9;
+ $right = int($i / 16);
+ }
+
+ $right = "\"$right\"";
+
+ my $tabs_right = get_tabs($right, 3);
+
+ print "$left$tabs_left$right$tabs_right},\n";
+ }
+
+ foreach my $ext (@extensions2)
+ {
+ my $left = sprintf(" \{ \"custom_%d.EDITOR$ext\",", $i + 1);
+
+ my $tabs_left = get_tabs($left, 6);
+
+ # my $right = ($ext eq '' ? 'RocksElements.pcx' : '0');
+ my $right = ($ext eq '' ? 'RocksCE.pcx' : '0');
+
+ if ($ext eq '.xpos')
+ {
+ # $right = 15;
+ $right = int($i % 16) + 16;
+ }
+ elsif ($ext eq '.ypos')
+ {
+ # $right = 13;
+ $right = int($i / 16);
+ }
+
+ $right = "\"$right\"";
+
+ my $tabs_right = get_tabs($right, 3);
+
+ print "$left$tabs_left$right$tabs_right},\n";
+ }
+
+ print "\n";
+ }
+
+ print_file_footer($filename_conf_cus_c);
+}
+
+sub print_group_graphics_list
+{
+ my @extensions1 =
+ (
+ '',
+ '.xpos',
+ '.ypos',
+ '.frames',
+ );
+ my @extensions2 =
+ (
+ '',
+ '.xpos',
+ '.ypos',
+ );
+
+ print_file_header($filename_conf_grp_c, $text_grp_c);
+
+ for (my $i = 0; $i < $num_group_elements; $i++)
+ {
+ foreach my $ext (@extensions1)
+ {
+ my $left = sprintf(" \{ \"group_%d$ext\",", $i + 1);
+
+ my $tabs_left = get_tabs($left, 6);
+
+ # my $right = ($ext eq '' ? 'RocksDC.pcx' :
+ my $right = ($ext eq '' ? 'RocksCE.pcx' :
+ $ext eq '.frames' ? '1' : '0');
+
+ if ($ext eq '.xpos')
+ {
+ # $right = 4;
+ $right = int($i % 16);
+ }
+ elsif ($ext eq '.ypos')
+ {
+ # $right = 15;
+ $right = int($i / 16) + int($num_custom_elements / 16);
+ }
+
+ $right = "\"$right\"";
+
+ my $tabs_right = get_tabs($right, 3);
+
+ print "$left$tabs_left$right$tabs_right},\n";
+ }
+
+ foreach my $ext (@extensions2)
+ {
+ my $left = sprintf(" \{ \"group_%d.EDITOR$ext\",", $i + 1);
+
+ my $tabs_left = get_tabs($left, 6);
+
+ # my $right = ($ext eq '' ? 'RocksDC.pcx' : '0');
+ my $right = ($ext eq '' ? 'RocksCE.pcx' : '0');
+
+ if ($ext eq '.xpos')
+ {
+ # $right = 14;
+ $right = int($i % 16) + 16;
+ }
+ elsif ($ext eq '.ypos')
+ {
+ # $right = 15;
+ $right = int($i / 16) + int($num_custom_elements / 16);
+ }
+
+ $right = "\"$right\"";
+
+ my $tabs_right = get_tabs($right, 3);
+
+ print "$left$tabs_left$right$tabs_right},\n";
+ }
+
+ print "\n";
+ }
+
+ print_file_footer($filename_conf_grp_c);
+}
+
+sub get_known_element_definitions_ALTERNATIVE
+{
+ my %known_element = ();
+
+ my $filename = "$src_path/main.h";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ # process line with element definition
+ if (/^\#define (EL_[A-Z0-9_]+)\s/)
+ {
+ $known_element{$1} = 1;
+
+ # print STDERR "known_element: '$1'\n";
+ }
+ }
+
+ close FILE;
+
+ return %known_element;
+}
+
+sub get_known_element_definitions
+{
+ my %known_element = ();
+
+ my $filename = "$src_path/main.c";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ my $element_name = '';
+ my $line_is_element_name = 0;
+ my $skip_line = 1;
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/ELEMENT_INFO_START/) # keyword to start parsing file
+ {
+ $skip_line = 0;
+ next;
+ }
+ elsif (/ELEMENT_INFO_END/) # keyword to stop parsing file
+ {
+ last;
+ }
+ elsif ($skip_line)
+ {
+ next;
+ }
+
+ if (/^\s+\{\s*$/)
+ {
+ $line_is_element_name = 1;
+ }
+ elsif ($line_is_element_name)
+ {
+ # process line with element name definition
+ if (/^\s+\"(.+)\",?\s*$/)
+ {
+ $element_name = 'EL_' . uc($1);
+
+ # dirty hack for making "[default]" work as an element name
+ $element_name =~ s/\[//;
+ $element_name =~ s/\]//;
+
+ # change '.' to '_' for elements like "dynamite.active"
+ $element_name =~ s/\./_/g;
+
+ $known_element{$element_name} = 1;
+
+ # printf STDERR "::: known element '$element_name'\n";
+ }
+
+ $line_is_element_name = 0;
+ }
+ }
+
+ close FILE;
+
+ return %known_element;
+}
+
+sub get_known_element_class_definitions
+{
+ my %known_element_class = ();
+
+ my $filename = "$src_path/main.c";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ my $element_name = '';
+ my $element_class = '';
+ my $line_is_element_name = 0;
+ my $line_is_element_class = 0;
+ my $skip_line = 1;
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/ELEMENT_INFO_START/) # keyword to start parsing file
+ {
+ $skip_line = 0;
+ next;
+ }
+ elsif (/ELEMENT_INFO_END/) # keyword to stop parsing file
+ {
+ last;
+ }
+ elsif ($skip_line)
+ {
+ next;
+ }
+
+ if (/^\s+\{\s*$/)
+ {
+ $line_is_element_name = 1;
+ }
+ elsif ($line_is_element_name)
+ {
+ # process line with element name definition
+ if (/^\s+\"(.+)\",?\s*$/)
+ {
+ $element_name = 'EL_' . uc($1);
+
+ # dirty hack for making "[default]" work as an element name
+ $element_name =~ s/\[//;
+ $element_name =~ s/\]//;
+
+ # change '.' to '_' for elements like "dynamite.active"
+ $element_name =~ s/\./_/g;
+ }
+
+ $line_is_element_name = 0;
+ $line_is_element_class = 1;
+ }
+ elsif ($line_is_element_class)
+ {
+ # process line with element class definition
+ if (/^\s+\"(.+)\",?\s*$/)
+ {
+ $element_class = 'EL_CLASS_' . uc($1);
+
+ if (!defined($known_element_class{$element_class}))
+ {
+ $known_element_class{$element_class} = $element_name;
+ }
+
+ $known_element_class{$element_name} = $element_class;
+
+ # print STDERR "known_element_class: '$element_name' => '$element_class'\n";
+ }
+
+ $line_is_element_class = 0;
+ }
+ }
+
+ close FILE;
+
+ return %known_element_class;
+}
+
+sub get_known_action_definitions
+{
+ my %known_action = ();
+
+ my $filename = "$src_path/main.h";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ # process line with action definition
+ if (/^\#define ACTION_([A-Z0-9_]+)\s/)
+ {
+ $known_action{$1} = 1;
+
+ # print STDERR "known_action: '$1'\n";
+ }
+ }
+
+ close FILE;
+
+ return %known_action;
+}
+
+sub get_known_special_arg_definitions
+{
+ my %known_special_arg = ();
+
+ my $filename = "$src_path/main.h";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ # process line with special arg definition
+ if (/^\#define GFX_SPECIAL_ARG_([A-Z0-9_]+)\s/)
+ {
+ if ($1 eq 'CRUMBLED')
+ {
+ next;
+ }
+
+ $known_special_arg{$1} = 1;
+
+ # print STDERR "known_special_arg: '$1'\n";
+ }
+ }
+
+ close FILE;
+
+ return %known_special_arg;
+}
+
+sub get_known_button_definitions
+{
+ my %known_button = ();
+
+ my $filename = "$src_path/conf_gfx.h";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ # process line with button definition
+ if (/^\#define (IMG_MENU_BUTTON[A-Z0-9_]*)\s/)
+ {
+ $known_button{$1} = 1;
+
+ # print STDERR "known_button: '$1'\n";
+ }
+ }
+
+ close FILE;
+
+ return %known_button;
+}
+
+sub get_known_font_definitions
+{
+ my %known_font = ();
+
+ my $filename = "$src_path/main.h";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ # process line with font definition
+ if (/^\#define (FONT_[A-Z0-9_]+)\s/)
+ {
+ $known_font{$1} = 1;
+
+ # print STDERR "known_font: '$1'\n";
+ }
+ }
+
+ close FILE;
+
+ return %known_font;
+}
+
+sub get_known_sound_prefix_definitions
+{
+ my %known_sound_prefix = ( 'background' => 1 );
+
+ return %known_sound_prefix;
+}
+
+sub get_known_music_prefix_definitions
+{
+ my %known_music_prefix = ();
+
+ my $filename = "$src_path/main.c";
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ my $prefix_name = '';
+ my $skip_line = 1;
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/MusicPrefixInfo/) # keyword to start parsing file
+ {
+ $skip_line = 0;
+ next;
+ }
+ elsif (/NULL/ && !$skip_line) # keyword to stop parsing file
+ {
+ last;
+ }
+ elsif ($skip_line)
+ {
+ next;
+ }
+
+ if (/^\s+{\s+\"(.+)\"/)
+ {
+ my $music_prefix = $1;
+
+ $known_music_prefix{$music_prefix} = 1;
+
+ # printf STDERR "::: known music prefix '$music_prefix'\n";
+ }
+ }
+
+ close FILE;
+
+ return %known_music_prefix;
+}
+
+sub print_element_to_graphic_entry
+{
+ my ($element, $action, $direction, $crumbled, $graphic) = @_;
+
+ my $num_tabs = 5 - int((length($element) + 4 + 1) / 8);
+ my $tabs = "\t" x $num_tabs;
+ if ($tabs eq '')
+ {
+ $tabs = ' ';
+ }
+
+ $crumbled = ($crumbled == 1 ? 'TRUE' : 'FALSE');
+
+ print " {\n";
+ print " $element,$tabs$action, $direction, $crumbled,\n";
+ print " $graphic\n";
+ print " },\n";
+}
+
+sub print_element_to_special_graphic_entry
+{
+ my ($element, $special, $graphic) = @_;
+
+ my $num_tabs = 6 - int((length($element) + 4 + 1) / 8);
+ my $tabs = "\t" x $num_tabs;
+ if ($tabs eq '')
+ {
+ $tabs = ' ';
+ }
+
+ print " {\n";
+ print " $element,$tabs$special,\n";
+ print " $graphic\n";
+ print " },\n";
+}
+
+sub print_font_to_graphic_entry
+{
+ my ($font, $special, $graphic) = @_;
+
+ my $num_tabs = 6 - int((length($font) + 4 + 1) / 8);
+ my $tabs = "\t" x $num_tabs;
+ if ($tabs eq '')
+ {
+ $tabs = ' ';
+ }
+
+ print " {\n";
+ print " $font,$tabs$special,\n";
+ print " $graphic\n";
+ print " },\n";
+}
+
+sub print_element_to_sound_entry
+{
+ my ($element, $is_class, $action, $sound) = @_;
+
+ my $element_plus_is_class = "$element, $is_class";
+
+ my $num_tabs = 6 - int((length($element_plus_is_class) + 4 + 1) / 8);
+ my $tabs = "\t" x $num_tabs;
+ if ($tabs eq '')
+ {
+ $tabs = ' ';
+ }
+
+ print " {\n";
+ print " $element_plus_is_class,$tabs$action,\n";
+ print " $sound\n";
+ print " },\n";
+}
+
+sub print_gamemode_to_sound_entry
+{
+ my ($gamemode, $sound) = @_;
+
+ print " {\n";
+ print " $gamemode,\n";
+ print " $sound\n";
+ print " },\n";
+}
+
+sub print_gamemode_to_music_entry
+{
+ my ($gamemode, $music) = @_;
+
+ print " {\n";
+ print " $gamemode,\n";
+ print " $music\n";
+ print " },\n";
+}
+
+sub print_image_config_var_entry
+{
+ my ($token, $var) = @_;
+
+ print " {\n";
+ print " $token,\n";
+ print " $var\n";
+ print " },\n";
+}
+
+sub print_active_state_entry
+{
+ my ($token, $token_active) = @_;
+
+ print " {\n";
+ print " $token,\n";
+ print " $token_active\n";
+ print " },\n";
+}
+
+sub print_element_to_graphic_list
+{
+ my %graphic_without_element =
+ (
+ 'IMG_FLAMES_1_LEFT' => 1,
+ 'IMG_FLAMES_2_LEFT' => 1,
+ 'IMG_FLAMES_3_LEFT' => 1,
+ 'IMG_FLAMES_1_RIGHT' => 1,
+ 'IMG_FLAMES_2_RIGHT' => 1,
+ 'IMG_FLAMES_3_RIGHT' => 1,
+ 'IMG_FLAMES_1_UP' => 1,
+ 'IMG_FLAMES_2_UP' => 1,
+ 'IMG_FLAMES_3_UP' => 1,
+ 'IMG_FLAMES_1_DOWN' => 1,
+ 'IMG_FLAMES_2_DOWN' => 1,
+ 'IMG_FLAMES_3_DOWN' => 1,
+ 'IMG_TWINKLE_BLUE' => 1,
+ 'IMG_TWINKLE_WHITE' => 1,
+ );
+
+ my %additional_mappings =
+ (
+ # file elements which are mapped to runtime elements when playing
+
+ # 'EL_EM_KEY_1_FILE' => 'IMG_EM_KEY_1',
+ # 'EL_EM_KEY_2_FILE' => 'IMG_EM_KEY_2',
+ # 'EL_EM_KEY_3_FILE' => 'IMG_EM_KEY_3',
+ # 'EL_EM_KEY_4_FILE' => 'IMG_EM_KEY_4',
+
+ # new elements which still have no graphic
+ # 'EL_DOOR_WHITE', => 'IMG_CHAR_QUESTION',
+ # 'EL_DOOR_WHITE_GRAY', => 'IMG_CHAR_QUESTION',
+ # 'EL_KEY_WHITE', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_RADIOACTIVITY', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_WHEELCHAIR', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_PARKING', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_ONEWAY', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_HEART', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_TRIANGLE', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_ROUND', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_EXIT', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_YINYANG', => 'IMG_CHAR_QUESTION',
+ # 'EL_SIGN_OTHER', => 'IMG_CHAR_QUESTION',
+ 'EL_SIGN_UNUSED_1', => 'IMG_CHAR_QUESTION',
+ 'EL_SIGN_UNUSED_2', => 'IMG_CHAR_QUESTION',
+ 'EL_DX_UNKNOWN_15', => 'IMG_CHAR_QUESTION',
+ 'EL_DX_UNKNOWN_42', => 'IMG_CHAR_QUESTION',
+
+ # file elements with direction which is not defined
+ 'EL_BD_BUTTERFLY_LEFT' => 'IMG_BD_BUTTERFLY',
+ 'EL_BD_BUTTERFLY_RIGHT' => 'IMG_BD_BUTTERFLY',
+ 'EL_BD_BUTTERFLY_UP' => 'IMG_BD_BUTTERFLY',
+ 'EL_BD_BUTTERFLY_DOWN' => 'IMG_BD_BUTTERFLY',
+ 'EL_BD_FIREFLY_LEFT' => 'IMG_BD_FIREFLY',
+ 'EL_BD_FIREFLY_RIGHT' => 'IMG_BD_FIREFLY',
+ 'EL_BD_FIREFLY_UP' => 'IMG_BD_FIREFLY',
+ 'EL_BD_FIREFLY_DOWN' => 'IMG_BD_FIREFLY',
+ );
+
+ my @unknown_graphics = ();
+ my %known_element = get_known_element_definitions();
+ my %known_action = get_known_action_definitions();
+ my %known_special_arg = get_known_special_arg_definitions();
+ my %known_direction =
+ (
+ 'LEFT' => 1,
+ 'RIGHT' => 1,
+ 'UP' => 1,
+ 'DOWN' => 1,
+ 'UPLEFT' => 1,
+ 'UPRIGHT' => 1,
+ 'DOWNLEFT' => 1,
+ 'DOWNRIGHT' => 1,
+ );
+
+ # ---------- read graphic file definitions ----------
+
+ my $filename = "$src_path/conf_gfx.c";
+
+ print_file_header($filename_conf_e2g_c, $text_e2g_c);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ print "static struct\n";
+ print "{\n";
+ print " int element;\n";
+ print " int action;\n";
+ print " int direction;\n";
+ print " boolean crumbled;\n";
+ print "\n";
+ print " int graphic;\n";
+ print "}\n";
+ print "element_to_graphic[] =\n";
+ print "{\n";
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/NO_MORE_ELEMENT_IMAGES/) # keyword to stop parsing file
+ {
+ last;
+ }
+
+ if (!contains_image_file($_)) # skip all lines without image file
+ {
+ next;
+ }
+
+ s/^ \{ \"//; # cut all leading ...
+ s/\",.*$//; # ... and trailing garbage
+
+ s/\[(\d+)\]/_$1/; # convert "[1]" to "_1" etc.
+
+ s/\[//; # dirty hack for making "[default]" ...
+ s/\]//; # ... work as an element name
+
+ my $token = $_;
+
+ if ($token =~ /\.([^\.]+)$/ && defined($known_special_arg{$1}))
+ {
+ next; # skip all special definitions
+ }
+
+ $token = uc($token); # convert all characters to upper case
+
+ my $gfx_action_default = '-1';
+ my $gfx_action = $gfx_action_default;
+
+ my $gfx_direction_default = '-1';
+ my $gfx_direction = $gfx_direction_default;
+
+ my $gfx_crumbled = '0';
+
+ my $object = $token;
+ my $action = '';
+ my $direction = '';
+ my $crumbled = '';
+
+ if ($object =~ /^(.*)\.([A-Z0-9]+)$/ && $2 eq 'CRUMBLED')
+ {
+ $object = $1;
+ $crumbled = $2;
+
+ $gfx_crumbled = '1';
+ }
+
+ if ($object =~ /^(.*)\.([A-Z0-9]+)$/ && defined($known_direction{$2}))
+ {
+ $object = $1;
+ $direction = $2;
+
+ $gfx_direction = "MV_BIT_$direction";
+ $gfx_direction_default = $gfx_direction;
+ }
+
+ if ($object =~ /^(.*)\.([A-Z0-9_]+)$/ && defined($known_action{$2}))
+ {
+ $object = $1;
+ $action = $2;
+
+ $gfx_action = "ACTION_$action";
+ $gfx_action_default = $gfx_action;
+ }
+
+ $token =~ s/\./_/g;
+ $object =~ s/\./_/g; # needed for "invisible_sand.active.digging"
+
+ # print STDERR "'$token' => '$object', '$action', '$direction'\n";
+
+ my $full_element = "EL_$token";
+ my $base_element = "EL_$object";
+
+ my $element = $base_element;
+ my $graphic = "IMG_$token";
+
+ my $element_without_crumbled = $full_element;
+ $element_without_crumbled =~ s/_$crumbled$//;
+
+ my $element_without_direction = $element_without_crumbled;
+ $element_without_direction =~ s/_$direction$//;
+
+ my $element_without_action = $element_without_direction;
+ $element_without_action =~ s/_$action$//;
+
+ if (defined($known_element{$full_element}))
+ {
+ $element = $full_element;
+
+ $gfx_action_default = '-1';
+ $gfx_direction_default = '-1';
+ }
+
+ if ($element_without_action eq $element || $action eq '')
+ {
+ $element_without_action = '';
+ }
+
+ if ($element_without_direction eq $element || $direction eq '')
+ {
+ $element_without_direction = '';
+ }
+
+ if ($element_without_crumbled eq $element || $crumbled eq '')
+ {
+ $element_without_crumbled = '';
+ }
+
+ if (defined($graphic_without_element{$graphic}))
+ {
+ next;
+ }
+
+ if (!defined($known_element{$element}))
+ {
+ # print STDERR "----- ERROR: unknown element '$element' -----\n";
+
+ push @unknown_graphics, $graphic;
+
+ next;
+ }
+
+ if (defined($known_element{$element}))
+ {
+ print_element_to_graphic_entry($element,
+ $gfx_action_default,
+ $gfx_direction_default,
+ $gfx_crumbled,
+ $graphic);
+ }
+
+ if (defined($known_element{$element_without_action}))
+ {
+ print_element_to_graphic_entry($element_without_action,
+ $gfx_action,
+ '-1',
+ $gfx_crumbled,
+ $graphic);
+ }
+
+ if (defined($known_element{$element_without_direction}))
+ {
+ print_element_to_graphic_entry($element_without_direction,
+ '-1',
+ $gfx_direction,
+ $gfx_crumbled,
+ $graphic);
+ }
+
+ if (defined($known_element{$element_without_crumbled}))
+ {
+ print_element_to_graphic_entry($element_without_crumbled,
+ '-1',
+ '-1',
+ $gfx_crumbled,
+ $graphic);
+ }
+ }
+
+ # dump list of additional elements
+ foreach my $element (sort keys %additional_mappings)
+ {
+ print_element_to_graphic_entry($element, '-1', '-1', '-1',
+ $additional_mappings{$element});
+ }
+
+ # dump list of character elements
+ foreach my $char (@chars)
+ {
+ my $element = "EL_CHAR_$char";
+ my $graphic = "IMG_CHAR_$char";
+
+ if ($char ne $char_skip)
+ {
+ print_element_to_graphic_entry($element, '-1', '-1', '-1',$graphic);
+ }
+ }
+ foreach my $char (@chars)
+ {
+ my $element = "EL_STEEL_CHAR_$char";
+ my $graphic = "IMG_STEEL_CHAR_$char";
+
+ if ($char ne $char_skip)
+ {
+ print_element_to_graphic_entry($element, '-1', '-1', '-1',$graphic);
+ }
+ }
+
+ # dump list of custom elements
+ for (my $i = 0; $i < $num_custom_elements; $i++)
+ {
+ my $element = sprintf("EL_CUSTOM_%d", $i + 1);
+ my $graphic = sprintf("IMG_CUSTOM_%d", $i + 1);
+
+ print_element_to_graphic_entry($element, '-1', '-1', '-1', $graphic);
+ }
+
+ # dump list of group elements
+ for (my $i = 0; $i < $num_group_elements; $i++)
+ {
+ my $element = sprintf("EL_GROUP_%d", $i + 1);
+ my $graphic = sprintf("IMG_GROUP_%d", $i + 1);
+
+ print_element_to_graphic_entry($element, '-1', '-1', '-1', $graphic);
+ }
+
+ print_element_to_graphic_entry('-1', '-1', '-1', '-1', '-1');
+
+ print "};\n";
+
+ close FILE;
+
+ if (scalar(@unknown_graphics) > 0)
+ {
+ print STDERR "-" x 79 . "\n";
+ print STDERR "The following graphics cannot be associated with any element:\n";
+
+ foreach my $graphic (@unknown_graphics)
+ {
+ print STDERR "- $graphic\n";
+ }
+
+ print STDERR "-" x 79 . "\n";
+ }
+
+ print_file_footer($filename_conf_e2g_c);
+}
+
+sub print_element_to_special_graphic_list
+{
+ my %graphic_without_element =
+ (
+ 'IMG_GLOBAL_DOOR' => 1,
+ );
+
+ my %additional_mappings =
+ (
+ # old elements which are mapped to other elements when playing
+ #'EL_BUG' => 'IMG_BUG_RIGHT',
+ #'EL_SPACESHIP' => 'IMG_SPACESHIP_RIGHT',
+ #'EL_PACMAN' => 'IMG_PACMAN_RIGHT',
+ );
+
+ my @elements_with_editor_graphic =
+ (
+ 'char_space'
+ );
+
+ my @unknown_graphics = ();
+ my %known_element = get_known_element_definitions();
+ my %known_special_arg = get_known_special_arg_definitions();
+
+ # ---------- read graphic file definitions ----------
+
+ my $filename = "$src_path/conf_gfx.c";
+
+ print_file_header($filename_conf_esg_c, $text_esg_c);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ print "static struct\n";
+ print "{\n";
+ print " int element;\n";
+ print " int special;\n";
+ print "\n";
+ print " int graphic;\n";
+ print "}\n";
+ print "element_to_special_graphic[] =\n";
+ print "{\n";
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/NO_MORE_ELEMENT_IMAGES/) # keyword to stop parsing file
+ {
+ last;
+ }
+
+ if (!contains_image_file($_)) # skip all lines without image file
+ {
+ next;
+ }
+
+ s/^ \{ \"//; # cut all leading ...
+ s/\",.*$//; # ... and trailing garbage
+
+ my $token = $_;
+ my $object;
+ my $special;
+
+ if ($token =~ /^font\./) # skip all font definitions
+ {
+ next;
+ }
+
+ if ($token =~ /^background\./) # skip all background image definitions
+ {
+ next;
+ }
+
+ if ($token =~ /^(.*)\.([^\.]+)$/ &&
+ defined($known_special_arg{$2}))
+ {
+ $object = $1;
+ $special = "GFX_SPECIAL_ARG_" . $2;
+ }
+ else
+ {
+ next; # skip all default definitions
+ }
+
+ $token =~ s/(.*)/uc($1)/eg; # convert all characters to upper case
+ $object =~ s/(.*)/uc($1)/eg; # convert all characters to upper case
+
+ $token =~ s/\./_/g;
+ $object =~ s/\./_/g;
+
+ # print STDERR "'$token' => '$object'\n";
+
+ my $element = "EL_$object";
+ my $graphic = "IMG_$token";
+
+ if (defined($graphic_without_element{$graphic}))
+ {
+ next;
+ }
+
+ if (!defined($known_element{$element}))
+ {
+ # print STDERR "----- ERROR: unknown element '$element' -----\n";
+
+ push @unknown_graphics, $graphic;
+
+ next;
+ }
+
+ print_element_to_special_graphic_entry($element,
+ $special,
+ $graphic);
+ }
+
+ # dump list of additional elements
+ foreach my $element (sort keys %additional_mappings)
+ {
+ print_element_to_special_graphic_entry($element,
+ 'GFX_SPECIAL_ARG_EDITOR',
+ $additional_mappings{$element});
+ print_element_to_special_graphic_entry($element,
+ 'GFX_SPECIAL_ARG_PREVIEW',
+ $additional_mappings{$element});
+ }
+
+ # dump list of custom element editor graphics
+ for (my $i = 0; $i < $num_custom_elements; $i++)
+ {
+ my $element = sprintf("EL_CUSTOM_%d", $i + 1);
+ my $graphic = sprintf("IMG_CUSTOM_%d_EDITOR", $i + 1);
+
+ print_element_to_special_graphic_entry($element,
+ 'GFX_SPECIAL_ARG_EDITOR',
+ $graphic);
+ }
+
+ # dump list of group element editor graphics
+ for (my $i = 0; $i < $num_group_elements; $i++)
+ {
+ my $element = sprintf("EL_GROUP_%d", $i + 1);
+ my $graphic = sprintf("IMG_GROUP_%d_EDITOR", $i + 1);
+
+ print_element_to_special_graphic_entry($element,
+ 'GFX_SPECIAL_ARG_EDITOR',
+ $graphic);
+ }
+
+ # dump other special editor graphics
+ foreach my $token (@elements_with_editor_graphic)
+ {
+ my $element = 'EL_' . uc($token);
+ my $graphic = 'IMG_' . uc($token) . '_EDITOR';
+
+ print_element_to_special_graphic_entry($element,
+ 'GFX_SPECIAL_ARG_EDITOR',
+ $graphic);
+ }
+
+ print_element_to_special_graphic_entry('-1', '-1', '-1');
+
+ print "};\n";
+
+ close FILE;
+
+ if (scalar(@unknown_graphics) > 0)
+ {
+ print STDERR "-" x 79 . "\n";
+ print STDERR "The following graphics cannot be associated with any element:\n";
+
+ foreach my $graphic (@unknown_graphics)
+ {
+ print STDERR "- $graphic\n";
+ }
+
+ print STDERR "-" x 79 . "\n";
+ }
+
+ print_file_footer($filename_conf_esg_c);
+}
+
+sub print_element_to_sound_list
+{
+ my %sound_without_action =
+ (
+ 'SND_AMOEBA_TURNING_TO_GEM' => 1,
+ 'SND_AMOEBA_TURNING_TO_ROCK' => 1,
+ 'SND_BD_AMOEBA_TURNING_TO_GEM' => 1,
+ 'SND_BD_AMOEBA_TURNING_TO_ROCK' => 1,
+
+ # no special case anymore after adding action ".splashing"
+ # 'SND_ACID_SPLASHING' => 1,
+ );
+
+ my @unknown_sounds = ();
+ my %known_element = get_known_element_definitions();
+ my %known_element_class = get_known_element_class_definitions();
+ my %known_action = get_known_action_definitions();
+
+ # ---------- read sound file definitions ----------
+
+ my $filename = "$src_path/conf_snd.c";
+
+ print_file_header($filename_conf_e2s_c, $text_e2s_c);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ print "static struct\n";
+ print "{\n";
+ print " int element;\n";
+ print " boolean is_class;\n";
+ print " int action;\n";
+ print "\n";
+ print " int sound;\n";
+ print "}\n";
+ print "element_to_sound[] =\n";
+ print "{\n";
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/NO_MORE_ELEMENT_SOUNDS/) # keyword to stop parsing file
+ {
+ last;
+ }
+
+ if (!contains_sound_file($_)) # skip all lines without sound file
+ {
+ next;
+ }
+
+ s/^ \{ \"//; # cut all leading ...
+ s/\",.*$//; # ... and trailing garbage
+
+ my $token = $_;
+
+ $token = uc($token); # convert all characters to upper case
+
+ my $snd_action_default = '-1';
+ my $snd_action = $snd_action_default;
+
+ my $object = $token;
+ my $action = '';
+
+ if ($object =~ /^(.*)\.([A-Z0-9_]+)$/ && defined($known_action{$2}))
+ {
+ $object = $1;
+ $action = $2;
+
+ $snd_action = "ACTION_$action";
+ $snd_action_default = $snd_action;
+ }
+
+ $token =~ s/\./_/g;
+ $object =~ s/\./_/g; # needed for "invisible_sand.active.digging"
+
+ if ($object =~ /^\[(.+)\]$/)
+ {
+ $object = 'CLASS_' . $1;
+ }
+
+ # print STDERR "'$token' => '$object', '$action'\n";
+
+ my $full_element = "EL_$token";
+ my $base_element = "EL_$object";
+
+ my $element = $base_element;
+ my $sound = $token;
+
+ if ($sound =~ /^\[.+\]/)
+ {
+ $sound =~ s/\[//; # element class sound; begin ...
+ $sound =~ s/\]//; # ... and end of definition token
+ $sound =~ s/^/CLASS_/; # add class identifier
+ }
+
+ $sound = "SND_$sound";
+
+ my $element_without_action = $full_element;
+ $element_without_action =~ s/_$action$//;
+
+ my $element_class_without_action = $full_element;
+ $element_without_action =~ s/_$action$//;
+
+ if (defined($known_element_class{$full_element}))
+ {
+ $element = $full_element;
+
+ $snd_action_default = '-1';
+ }
+
+ if ($element_without_action eq $element || $action eq '')
+ {
+ $element_without_action = '';
+ }
+
+ if (defined($sound_without_action{$sound}))
+ {
+ next;
+ }
+
+ if (!defined($known_element{$element}) &&
+ !defined($known_element_class{$element}))
+ {
+ # print STDERR "----- ERROR: unknown element '$element' -----\n";
+
+ push @unknown_sounds, $sound;
+
+ next;
+ }
+
+ if (!($element =~ /_CLASS_/) &&
+ defined($known_element{$element}))
+ {
+ print_element_to_sound_entry($element, "FALSE",
+ $snd_action_default,
+ $sound);
+ }
+
+ if (!($element =~ /_CLASS_/) &&
+ defined($known_element{$element_without_action}))
+ {
+ print_element_to_sound_entry($element_without_action, "FALSE",
+ $snd_action,
+ $sound);
+ }
+
+ if ($element =~ /_CLASS_/ &&
+ defined($known_element_class{$element}))
+ {
+ my $class_element = $known_element_class{$element};
+
+ print_element_to_sound_entry($class_element, "TRUE",
+ $snd_action_default,
+ $sound);
+ }
+
+ if ($element =~ /_CLASS_/ &&
+ defined($known_element_class{$element_without_action}))
+ {
+ my $class_element = $known_element_class{$element_without_action};
+
+ print_element_to_sound_entry($class_element, "TRUE",
+ $snd_action,
+ $sound);
+ }
+ }
+
+ print_element_to_sound_entry('-1', '-1', '-1', '-1');
+
+ print "};\n";
+
+ close FILE;
+
+ if (scalar(@unknown_sounds) > 0)
+ {
+ print STDERR "-" x 79 . "\n";
+ print STDERR "The following sounds cannot be associated with any element or element class:\n";
+
+ foreach my $sound (@unknown_sounds)
+ {
+ print STDERR "- $sound\n";
+ }
+
+ print STDERR "-" x 79 . "\n";
+ }
+
+ print_file_footer($filename_conf_e2s_c);
+}
+
+sub print_font_to_graphic_list
+{
+ my @unknown_graphics = ();
+ my %known_font = get_known_font_definitions();
+ my %known_special_arg = get_known_special_arg_definitions();
+
+ # ---------- read graphic file definitions ----------
+
+ my $filename = "$src_path/conf_gfx.c";
+
+ print_file_header($filename_conf_fnt_c, $text_fnt_c);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ print "static struct\n";
+ print "{\n";
+ print " int font_nr;\n";
+ print " int special;\n";
+ print "\n";
+ print " int graphic;\n";
+ print "}\n";
+ print "font_to_graphic[] =\n";
+ print "{\n";
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (!contains_image_file($_)) # skip all lines without image file
+ {
+ next;
+ }
+
+ s/^ \{ \"//; # cut all leading ...
+ s/\",.*$//; # ... and trailing garbage
+
+ my $token = $_;
+ my $font;
+ my $special;
+ my $graphic;
+
+ if ($token =~ /^(font\..*)$/)
+ {
+ $font = $token;
+ $special = '-1';
+
+ if ($token =~ /^(.*)\.([^\.]+)$/ &&
+ defined($known_special_arg{$2}))
+ {
+ $font = $1;
+ $special = "GFX_SPECIAL_ARG_" . $2;
+ }
+ }
+ else
+ {
+ next; # skip all non-font definitions
+ }
+
+ $token =~ s/(.*)/uc($1)/eg; # convert all characters to upper case
+ $font =~ s/(.*)/uc($1)/eg; # convert all characters to upper case
+
+ $token =~ s/\./_/g;
+ $font =~ s/\./_/g;
+
+ # print STDERR "'$token' => '$font'\n";
+
+ $graphic = "IMG_$token";
+
+ if (!defined($known_font{$font}))
+ {
+ # print STDERR "----- ERROR: unknown font '$font' -----\n";
+
+ push @unknown_graphics, $graphic;
+
+ next;
+ }
+
+ print_font_to_graphic_entry($font,
+ $special,
+ $graphic);
+ }
+
+ print_font_to_graphic_entry('-1', '-1', '-1');
+
+ print "};\n";
+
+ close FILE;
+
+ if (scalar(@unknown_graphics) > 0)
+ {
+ print STDERR "-" x 79 . "\n";
+ print STDERR "The following graphics cannot be associated with any font:\n";
+
+ foreach my $graphic (@unknown_graphics)
+ {
+ print STDERR "- $graphic\n";
+ }
+
+ print STDERR "-" x 79 . "\n";
+ }
+
+ print_file_footer($filename_conf_fnt_c);
+}
+
+sub print_gamemode_to_sound_list
+{
+ my %known_prefix = get_known_sound_prefix_definitions();
+ my %known_special_arg = get_known_special_arg_definitions();
+
+ # ---------- read music file definitions ----------
+
+ my $filename = "$src_path/conf_snd.c";
+
+ print_file_header($filename_conf_g2s_c, $text_g2s_c);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ print "static struct\n";
+ print "{\n";
+ print " int gamemode;\n";
+ print "\n";
+ print " int sound;\n";
+ print "}\n";
+ print "gamemode_to_sound[] =\n";
+ print "{\n";
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (!contains_sound_file($_)) # skip all lines without sound file
+ {
+ next;
+ }
+
+ if (/\[not used\]/)
+ {
+ next;
+ }
+
+ s/^ \{ \"//; # cut all leading ...
+ s/\",.*$//; # ... and trailing garbage
+
+ my $token = $_;
+ my $gamemode = -1;
+ # my $level = -1; # ???
+
+ if (defined($known_prefix{$token}))
+ {
+ # no special arg defined
+ }
+ elsif ($token =~ /^(.*)\.([^\.]+)$/ &&
+ defined($known_prefix{$1}) &&
+ defined($known_special_arg{$2}))
+ {
+ $gamemode = "GFX_SPECIAL_ARG_" . $2;
+ }
+ else
+ {
+ next;
+ }
+
+# if ($token =~ /^(.*)\./ &&
+# !defined($known_prefix{$1}))
+# {
+# next;
+# }
+#
+# if ($token =~ /^(.*)\.([^\.]+)$/ &&
+# defined($known_special_arg{$2}))
+# {
+# $gamemode = "GFX_SPECIAL_ARG_" . $2;
+# }
+
+ $token =~ s/(.*)/uc($1)/eg; # convert all characters to upper case
+ $token =~ s/\./_/g;
+
+ my $sound = "SND_$token";
+
+ # print STDERR "'$token' => '$sound'\n";
+
+ print_gamemode_to_sound_entry($gamemode, $sound);
+ }
+
+ print_gamemode_to_sound_entry('-1', '-1');
+
+ print "};\n";
+
+ close FILE;
+
+ print_file_footer($filename_conf_g2s_c);
+}
+
+sub print_gamemode_to_music_list
+{
+ my %known_prefix = get_known_music_prefix_definitions();
+ my %known_special_arg = get_known_special_arg_definitions();
+
+ # ---------- read music file definitions ----------
+
+ my $filename = "$src_path/conf_mus.c";
+
+ print_file_header($filename_conf_g2m_c, $text_g2m_c);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ print "static struct\n";
+ print "{\n";
+ print " int gamemode;\n";
+ print "\n";
+ print " int music;\n";
+ print "}\n";
+ print "gamemode_to_music[] =\n";
+ print "{\n";
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (!contains_music_file($_)) # skip all lines without music file
+ {
+ next;
+ }
+
+ s/^ \{ \"//; # cut all leading ...
+ s/\",.*$//; # ... and trailing garbage
+
+ my $token = $_;
+ my $gamemode = -1;
+
+ if (defined($known_prefix{$token}))
+ {
+ # no special arg defined
+ }
+ elsif ($token =~ /^(.*)\.([^\.]+)$/ &&
+ defined($known_prefix{$1}) &&
+ defined($known_special_arg{$2}))
+ {
+ $gamemode = "GFX_SPECIAL_ARG_" . $2;
+ }
+ else
+ {
+ next;
+ }
+
+# my $prefix = $token;
+# $prefix =~ s/\..*$//;
+#
+## if ($token =~ /^(.*)\./ &&
+## !defined($known_prefix{$1}))
+# if (!defined($known_prefix{$prefix}))
+# {
+# next;
+# }
+#
+# if ($token =~ /^(.*)\.([^\.]+)$/ &&
+# defined($known_special_arg{$2}))
+# {
+# $gamemode = "GFX_SPECIAL_ARG_" . $2;
+# }
+
+ $token =~ s/(.*)/uc($1)/eg; # convert all characters to upper case
+ $token =~ s/\./_/g;
+
+ my $music = "MUS_$token";
+
+ # print STDERR "'$token' => '$music'\n";
+
+ print_gamemode_to_music_entry($gamemode, $music);
+ }
+
+ print_gamemode_to_music_entry('-1', '-1');
+
+ print "};\n";
+
+ close FILE;
+
+ print_file_footer($filename_conf_g2m_c);
+}
+
+sub print_image_config_vars
+{
+ # ---------- read graphic file definitions ----------
+
+ my $filename = "$src_path/conf_gfx.c";
+
+ print_file_header($filename_conf_var_c, $text_var_c);
+
+ open(FILE, "$filename") ||
+ fail("cannot open file '$filename' for reading");
+
+ print "struct TokenIntPtrInfo image_config_vars[] =\n";
+ print "{\n";
+
+ my $start_parsing = 0;
+
+ while (<FILE>)
+ {
+ chomp; # cut trailing newline
+
+ if (/CONFIG_VARS_START/) # keyword to start parsing file
+ {
+ $start_parsing = 1;
+ }
+
+ if (!$start_parsing)
+ {
+ next;
+ }
+
+ if (/^\s*\{\s*\"([^\"]+)\"/) # config token found
+ {
+ my $token = $1;
+ my $var = $token;
+
+ # --- some prefix replacements ---
+
+ $var =~ s/^main\./menu.main./;
+ $var =~ s/^\[player\]\./game.player_/;
+ $var =~ s/^\[title_initial\]/title_initial_default/;
+ $var =~ s/^\[title\]/title_default/;
+ $var =~ s/^\[titlemessage_initial\]/titlemessage_initial_default/;
+ $var =~ s/^\[titlemessage\]/titlemessage_default/;
+
+ if ($var =~ /^titlemessage.*(\d)/ ||
+ $var =~ /^game.panel.key_(\d)/ ||
+ $var =~ /^game.panel.inventory_first_(\d)/ ||
+ $var =~ /^game.panel.inventory_last_(\d)/ ||
+ $var =~ /^game.panel.conveyor_belt_(\d)\./ ||
+ $var =~ /^game.panel.element_(\d)\./ ||
+ $var =~ /^game.panel.graphic_(\d)\./ ||
+ $var =~ /^game.panel.ce_score_(\d)\./)
+ {
+ my $number = $1;
+ my $array_pos = int($number) - 1;
+ $var =~ s/_$number/\[$array_pos\]/;
+ }
+ elsif ($var =~ /^game.panel.conveyor_belt_(\d)(_switch)/ ||
+ $var =~ /^game.panel.element_(\d)(_count)/ ||
+ $var =~ /^game.panel.ce_score_(\d)(_element)/)
+ {
+ my $number = $1;
+ my $suffix = $2;
+ my $array_pos = int($number) - 1;
+ $var =~ s/_$number$suffix/$suffix\[$array_pos\]/;
+ }
+
+ # --- some suffix replacements ---
+
+ $var =~ s/^(menu\.main\..*)\.chars$/$1.size/;
+ $var =~ s/^(game\.panel\..*)\.chars$/$1.size/;
+ $var =~ s/^(game\.panel\..*)\.tile_size$/$1.size/;
+ $var =~ s/\.digits$/.size/;
+ $var =~ s/\.element$/.id/;
+ $var =~ s/\.draw_order$/.sort_priority/;
+
+ $var =~ s/\.font_[a-z]+$/.font_alt/;
+ $var =~ s/\.INFO\[([A-Z]+)\]$/_info\[GFX_SPECIAL_ARG_INFO_$1\]/;
+ $var =~ s/\.SETUP\[([A-Z0-9_]+)\]$/_setup\[GFX_SPECIAL_ARG_SETUP_$1\]/;
+ $var =~ s/\.([A-Z]+)$/\[GFX_SPECIAL_ARG_$1\]/;
+ $var =~ s/\.([A-Z]+)\./\[GFX_SPECIAL_ARG_$1\]./;
+
+ if ($var =~ /^(menu.(enter|leave)_screen)(.[a-z_]+)$/)
+ {
+ $var = $1 . "[GFX_SPECIAL_ARG_DEFAULT]" . $3;
+ }
+
+ if ($var =~ /^menu.(draw_[xy]offset|list_size)$/)
+ {
+ $var .= "[GFX_SPECIAL_ARG_DEFAULT]";
+ }
+
+ if ($var =~ /^(viewport.(playfield|door_[12]))(.[a-z_]+)$/)
+ {
+ $var = $1 . "[GFX_SPECIAL_ARG_DEFAULT]" . $3;
+ }
+
+ print_image_config_var_entry("\"$token\"", "&$var");
+ }
+ }
+
+ print_image_config_var_entry('NULL', 'NULL');
+
+ print "};\n";
+
+ close FILE;
+
+ print_file_footer($filename_conf_var_c);
+}
+
+sub print_active_states
+{
+ # ---------- read graphic file definitions ----------
+
+ my %known_element = get_known_element_definitions();
+ my %known_button = get_known_button_definitions();
+ my %known_font = get_known_font_definitions();
+
+ print_file_header($filename_conf_act_c, $text_act_c);
+
+ print "static struct\n";
+ print "{\n";
+ print " int element;\n";
+ print " int element_active;\n";
+ print "}\n";
+ print "element_with_active_state[] =\n";
+ print "{\n";
+
+ foreach my $element (sort keys %known_element)
+ {
+ my $element_active = $element . '_ACTIVE';
+
+ if (defined($known_element{$element_active}))
+ {
+ print_active_state_entry($element, $element_active);
+ }
+ }
+
+ print_active_state_entry('-1', '-1');
+
+ print "};\n";
+
+ print "\n";
+ print "\n";
+ print "static struct\n";
+ print "{\n";
+ print " int button;\n";
+ print " int button_active;\n";
+ print "}\n";
+ print "button_with_active_state[] =\n";
+ print "{\n";
+
+ foreach my $button (sort keys %known_button)
+ {
+ my $button_active = $button . '_ACTIVE';
+
+ if (defined($known_button{$button_active}))
+ {
+ print_active_state_entry($button, $button_active);
+ }
+ }
+
+ print_active_state_entry('-1', '-1');
+
+ print "};\n";
+
+ print "\n";
+ print "\n";
+ print "static struct\n";
+ print "{\n";
+ print " int font_nr;\n";
+ print " int font_nr_active;\n";
+ print "}\n";
+ print "font_with_active_state[] =\n";
+ print "{\n";
+
+ foreach my $font (sort keys %known_font)
+ {
+ my $font_active = $font . '_ACTIVE';
+
+ if (defined($known_font{$font_active}))
+ {
+ print_active_state_entry($font, $font_active);
+ }
+ }
+
+ print_active_state_entry('-1', '-1');
+
+ print "};\n";
+
+ print_file_footer($filename_conf_act_c);
+}
+
+
+# =============================================================================
+# M A I N - P R O G R A M
+# =============================================================================
+
+sub main
+{
+ my $argc = scalar(@ARGV);
+
+ if ($argc == 0 || $ARGV[0] eq '-h' || $ARGV[0] eq '--help')
+ {
+ print "Usage: $0 <file>\n\n";
+ print "Choose <file> from the following list:\n";
+ print "- '$filename_conf_gfx_h'\n";
+ print "- '$filename_conf_snd_h'\n";
+ print "- '$filename_conf_mus_h'\n";
+ print "- '$filename_conf_chr_c'\n";
+ print "- '$filename_conf_chr_h'\n";
+ print "- '$filename_conf_cus_c'\n";
+ print "- '$filename_conf_cus_h'\n";
+ print "- '$filename_conf_grp_c'\n";
+ print "- '$filename_conf_grp_h'\n";
+ print "- '$filename_conf_e2g_c'\n";
+ print "- '$filename_conf_esg_c'\n";
+ print "- '$filename_conf_fnt_c'\n";
+ print "- '$filename_conf_g2s_c'\n";
+ print "- '$filename_conf_g2m_c'\n";
+ print "- '$filename_conf_var_c'\n";
+ print "- '$filename_conf_act_c'\n";
+
+ exit 1;
+ }
+
+ if ($ARGV[0] eq $filename_conf_gfx_h)
+ {
+ print_graphics_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_snd_h)
+ {
+ print_sounds_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_mus_h)
+ {
+ print_music_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_chr_c)
+ {
+ print_chars_graphics_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_chr_h)
+ {
+ print_chars_elements_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_cus_c)
+ {
+ print_custom_graphics_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_cus_h)
+ {
+ print_custom_elements_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_grp_c)
+ {
+ print_group_graphics_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_grp_h)
+ {
+ print_group_elements_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_e2g_c)
+ {
+ print_element_to_graphic_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_esg_c)
+ {
+ print_element_to_special_graphic_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_e2s_c)
+ {
+ print_element_to_sound_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_fnt_c)
+ {
+ print_font_to_graphic_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_g2s_c)
+ {
+ print_gamemode_to_sound_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_g2m_c)
+ {
+ print_gamemode_to_music_list();
+ }
+ elsif ($ARGV[0] eq $filename_conf_var_c)
+ {
+ print_image_config_vars();
+ }
+ elsif ($ARGV[0] eq $filename_conf_act_c)
+ {
+ print_active_states();
+ }
+ else
+ {
+ print "Unknown option '$ARGV[0]'.\n";
+
+ exit 1;
+ }
+
+ exit 0;
+}