#!/usr/bin/env perl #--------------------------------------------------------------------- # file information #--------------------------------------------------------------------- # prfreeboom.wrapper - Wrapper for "prfreeboom" main program # License: Creative Commons CC BY-NC-SA 4.0 International # Revision: See $REVISION in the code # Note: The license indicated above applies to this file. It doesn't # apply to PRBoom or FreeDoom, or to any files derived from those # packages. #--------------------------------------------------------------------- # license information #--------------------------------------------------------------------- # This section may not be modified except as approved by the author or # licensor, or to make non-content changes such as adjustments to par- # agraph formatting or white space. # This version of this software is distributed under the following # license: # # Creative Commons CC BY-NC-SA 4.0 International # You may use, modify, and redistribute this software without fees or # royalties, but only under the terms and conditions set forth by the # license. In particular, copies and derived works cannot be used for # commercial purposes. Additionally, the license propagates to copies # and derived works. Furthermore, you must provide attribution "in the # manner specified by the author or licensor". # This is not a complete explanation of the terms and conditions in- # volved. For more information, see the official text of the license. #--------------------------------------------------------------------- # explanation #--------------------------------------------------------------------- # 1. Overview: # This program (prfreeboom) is a GUI that launches a modified version # of PRBoom using data files derived from FreeDoom. # Note: PRBoom and FreeDoom are distributed under their own licenses. # All associated modifications and/or data files are distributed under # the same PRBoom and/or FreeDoom licenses. This program (prfreeboom) # is a separate component that's distributed under its own license, as # explained previously. #--------------------------------------------------------------------- # 2. Features: The GUI allows the user to select a level and to set # various options, such as: # # Science Fiction characters vs. original characters # Alternate music vs. original music # High resolution (1024x768 and up) vs. low resolution (640x480) # etc. # Additionally, the GUI allows the user to generate entirely new le- # vels via Slige or Slump. # The GUI also displays a brief list of command keys and some back- # ground information. #--------------------------------------------------------------------- # 3. Requirements: # At the GUI level, this program requires Perl 5, Perl-Gtk2, LACSUB, # and "glxinfo". These components are standard, except for LACSUB. You # should be able to obtain LACSUB from the same place as this file. # Note: LACSUB (like this file) is distributed under a Creative Com- # mons license. # For this program to be useful, the following additional items should # be installed: # # a. A modified copy of PRBoom. You should be able to get the # source code used from the same place as this file. # # b. A modified copy of FreeDoom. You should be able to get the # data tree used from the same place as this file. # # c. "bsp", "deutex440", "slige", and "slump". These are standard # Doom 1/Doom2 utilities, with some patches applied. "deutex- # 440" is a special case: this must be "deutex" 4.4.0 exactly, # with the associated "noshrink" patch applied. You should be # able to get the complete source code for all of these utili- # ties (plus all patches) from the same place as this file. # # d. "mus2pwad". This is a new Doom 1/Doom 2 utility. You should # be able to get the complete source code used from the same # place as this file. Note: "mus2pwad" is distributed under the # same license as this file. #--------------------------------------------------------------------- # standard module setup #--------------------------------------------------------------------- require 5.16.1 ; use strict ; use Carp ; use warnings ; # Trap warnings $SIG {__WARN__} = sub { die @_; }; #--------------------------------------------------------------------- # add CPAN module(s) #--------------------------------------------------------------------- use Gtk2 '-init'; use Gtk2::SimpleList; use Gtk2::Gdk::Keysyms; use Gtk2::Pango; use Pango; #--------------------------------------------------------------------- # add LACSUB module(s) #--------------------------------------------------------------------- use LACSUB::GUI ( @LACSUB::GUI::EXPORT_OK ); #--------------------------------------------------------------------- # basic constants #--------------------------------------------------------------------- use constant ZERO => 0; # Zero use constant ONE => 1; # One use constant TWO => 2; # Two use constant FALSE => 0; # Boolean FALSE use constant TRUE => 1; # Boolean TRUE #--------------------------------------------------------------------- # program parameters #--------------------------------------------------------------------- # Presently, "prfreeboom" doesn't work well on some systems in OpenGL # mode. This may be related to XOrg video-driver and/or Mesa issues. # Until the problem can be resolved, $DISABLE_DRI should be set to # TRUE; this disables the use of OpenGL. If the problem is resolved # eventually, you can try setting $DISABLE_DRI to FALSE. my $DISABLE_DRI = TRUE; #--------------------------------------------------------------------- my $DIR_BASE = '__META_PREFIX__'; my $DIR_BIN = "$DIR_BASE/bin"; my $DIR_DATA = "$DIR_BASE/data"; my $DIR_LEVELS = "$DIR_DATA/levels"; my $FILE_FD1 = "$DIR_DATA/freedoom1.wad"; my $FILE_FD2 = "$DIR_DATA/freedoom2.wad"; my $FILE_FDALT = "$DIR_DATA/freedm.wad"; my $FILE_COMBINED = "$DIR_DATA/combined.wad"; my $ALERT_ICON_PATH = "$DIR_DATA/alert.png"; my $MAIN_WIDTH = 900; # Main-window width (in pixels) my $MAIN_HEIGHT = 610; # Main-window height (in pixels) my $MAX_DOOM2_LEVNUM = 32; # Max. Doom 2 level number (32) my $MAX_SLUMP_LEVELS = 100; # Revision (or release) string my $REVISION = '241113'; # Name of main "prfreeboom" configur- # ation file (excluding path) my $CFG_NAME_PRFREEBOOM = 'prfreeboom.cfg'; # Name of main "prboom-plus" configur- # ation file (excluding path) my $CFG_NAME_PRBOOM_PLUS = 'prboom-plus.cfg'; # Name of "slump" history file (ex- # cluding path component) my $SLUMP_HISTORY = 'slump.lst'; #--------------------------------------------------------------------- # @ProgNames specifies single-word names for one or more programs that # are associated (directly or indirectly) with this package. At least # one name should be specified. Note: List order and/or alphabetic # case don't matter. # $ProgNames contains the strings listed by @ProgNames, separated by # vertical bars. # @ProgNames isn't used after $ProgNames is constructed. $ProgNames is # used to post-process message text. my @ProgNames = qw ( bsp deutex deutex440 doom freedoom prboom prfreeboom slige slump ); my $ProgNames = join '|', @ProgNames; undef @ProgNames; #--------------------------------------------------------------------- # $DEFAULT_PATTERN should be a Perl pattern string enclosed in paren- # theses. "prfreeboom" checks WAD-file names against the specified # pattern. Note: The check is done using base filenames. For the pur- # poses of this check, pathname components and ".wad" filename exten- # sions are ignored. # If one WAD file's name matches the specified pattern (ignoring al- # phabetic case), "prfreeboom" uses the WAD file as a default level. # If there's a match for more than one file, an arbitrary selection is # made. my $DEFAULT_PATTERN = '(no-default)'; #--------------------------------------------------------------------- # $CFG_DEFAULT_PRFREEBOOM specifies the default contents of the main # "prfreeboom" configuration file. # Note: Normally, $CFG_DEFAULT_PRFREEBOOM shouldn't specify a default # setting for "video_highres". The default setting for this flag is # determined at runtime. # "END" must be double-quoted here my $CFG_DEFAULT_PRFREEBOOM = << "END"; # $CFG_NAME_PRFREEBOOM - Main "prfreeboom" configuration file [prfreeboom] alternate_music = yes characters_sf = yes save_slump = no spider_robots = no END #--------------------------------------------------------------------- # $CFG_DEFAULT_PRBOOM_PLUS specifies the default contents of the main # "prboom-plus" configuration file. # 'END' should be single-quoted here my $CFG_DEFAULT_PRBOOM_PLUS = << 'END'; # Video settings videomode "8bit" screen_width 640 screen_height 480 use_fullscreen 1 use_doublebuffer 1 translucency 1 tran_filter_pct 66 screenblocks 10 usegamma 3 uncapped_framerate 1 filter_wall 1 filter_floor 1 filter_sprite 1 filter_z 1 filter_patch 1 filter_threshold 49152 sprite_edges 0 patch_edges 0 # Key bindings key_right 0xae key_left 0xac key_up 0xad key_down 0xaf key_mlook 0x5c key_novert 0x0 key_menu_right 0xae key_menu_left 0xac key_menu_up 0xad key_menu_down 0xaf key_menu_backspace 0x7f key_menu_escape 0x1b key_menu_enter 0xd key_menu_clear 0xc8 key_setup 0x0 key_strafeleft 0x61 key_straferight 0x64 key_flyup 0x60 key_flydown 0x2c key_fire 0x9d key_use 0xb6 key_strafe 0xb8 key_speed 0x2e key_savegame 0xbc key_loadgame 0xbd key_soundvolume 0xbe key_hud 0xbf key_quicksave 0xc0 key_endgame 0xc1 key_messages 0xc2 key_quickload 0xc3 key_quit 0xc4 key_gamma 0xd7 key_spy 0xd8 key_pause 0xff key_autorun 0xba key_chat 0x74 key_backspace 0x7f key_enter 0xd key_map 0x9 key_map_right 0xae key_map_left 0xac key_map_up 0xad key_map_down 0xaf key_map_zoomin 0x3d key_map_zoomout 0x2d key_map_gobig 0x30 key_map_follow 0x66 key_map_mark 0x6d key_map_clear 0x63 key_map_grid 0x67 key_map_rotate 0x72 key_map_overlay 0x6f key_map_textured 0x0 key_reverse 0x2f key_zoomin 0x3d key_zoomout 0x2d key_chatplayer1 0x67 key_chatplayer2 0x69 key_chatplayer3 0x62 key_chatplayer4 0x72 key_weapontoggle 0x30 key_weapon1 0x31 key_weapon2 0x32 key_weapon3 0x33 key_weapon4 0x34 key_weapon5 0x35 key_weapon6 0x36 key_weapon7 0x37 key_weapon8 0x38 key_weapon9 0x39 key_nextweapon 0xeb key_prevweapon 0xec key_screenshot 0x2a END #--------------------------------------------------------------------- # $SLUMP_HEADER specifies "comment" text to be placed at the start of # a Slump history file. Note: "Comment" lines should begin with a # "#". my $SLUMP_HEADER = << "END"; # "END" must be single-quoted here # $SLUMP_HISTORY - prfreeboom/slump level-generator keys # You can use this list to reproduce "slump" levels that have been # used in the past. END #--------------------------------------------------------------------- # @SLUMP_DEFAULT_SEEDS should be a list of one or more strings for- # mated as follows: # # integer dash three-digit-integer # The first integer is interpreted as a standard Slump level-generator # seed. # The second integer may start with digit "1" or "2". "1" selects Doom # 1 and "2" selects Doom 2. # If Doom 1 is selected, the second digit of the second integer speci- # fies a Doom 1 Episode number and the third (and final) digit speci- # fies a Doom 1 Mission number. # If Doom 2 is selected, the last two digits of the second integer # specify a Doom 2 Map number (01 to 32). # Together, the two integers (plus the dash separator) specify a com- # plete prfreeboom/Slump level-generator key. # The values used may be arbitrary, or they may be the level-generator # seeds for specific prfreeboom/Slump levels that you've used in the # past. # Note: "prfreeboom's" Slump interface screen doesn't support empty # Slump history files; this would complicate the code unnecessarily. # Therefore, the @SLUMP_DEFAULT_SEEDS list must contain at least one # entry. my @SLUMP_DEFAULT_SEEDS = qw ( 1176585748-201 1176600739-201 1176607388-201 1176672985-201 ); #--------------------------------------------------------------------- # "prfreeboom" configuration-file variables #--------------------------------------------------------------------- # This section defines variables related to the main "prfreeboom" con- # figuration file (as opposed to configuration files related to # "prboom", "slump", etc.). my $CFG_PATH_PRFREEBOOM; # Absolute pathname for file my $CFG_DATA; # Contents of file # Note: The following flag settings are defaults. They may be over- # ridden by the user's "prfreeboom" configuration file and/or GUI- # level actions. #--------------------------------------------------------------------- # Associated flags. my $CFG_AltMusic = TRUE ; my $CFG_BeauDoom = TRUE ; my $CFG_Leggo = FALSE ; my $CFG_Save_Slump = TRUE ; my $CFG_SciFi = TRUE ; my $CFG_Spiders = FALSE ; my $CFG_HighRes; # This flag is handled at runtime #--------------------------------------------------------------------- # misc. global variables #--------------------------------------------------------------------- my $CFG_PATH_PRBOOM_PLUS; # Absolute pathname for "prboom-plus. # cfg" my $FlagDirectRendering; # Flag: Direct rendering is available my $FlagHighResolution; # Flag: High-resolution mode my $MainWindow; # GTK2 main window my $SLUMPFILE; # "slump" history file (pathname) my %WadMap = (); # Maps WAD descriptions to pathnames # The following variables are Perl-Gtk2 objects: my $SimpleList; # SimpleList: List of level names # Checkboxes: # my $CB_AltMusic ; # Alternate Music my $CB_HighRes ; # High resolution my $CB_Save_Slump ; # Save Slump levels my $CB_Spiders ; # Spider robots my $CB_BeauDoom ; # BeauDoom mode my $CB_Leggo ; # Leggo mode my $CB_SciFi ; # Sci-Fi mode #--------------------------------------------------------------------- # support routines #--------------------------------------------------------------------- # "by_number" is a "sort"-compatible routine that's used as follows: # # @list = sort by_number @list; # @list should contain a list of strings in the following format: # # integer or integer-string # The code shown above sorts the list into ascending numeric order # based on the leading integer. #--------------------------------------------------------------------- sub by_number { my ($s1, $s2) = ($a, $b); $s1 =~ s@-.*@@; $s2 =~ s@-.*@@; $s1 <=> $s2; } #--------------------------------------------------------------------- # "reverse_by_number" is a "sort"-compatible routine that's used as # follows: # # @list = sort reverse_by_number @list; # @list should contain a list of strings in the following format: # # integer or integer-string # The code shown above sorts the list into descending numeric order # based on the leading integer. #--------------------------------------------------------------------- sub reverse_by_number { my ($s1, $s2) = ($a, $b); $s1 =~ s@-.*@@; $s2 =~ s@-.*@@; $s2 <=> $s1; } #--------------------------------------------------------------------- # Future change: Document this routine. sub PanicDialog { my ($msg, $details) = @_; $msg = "" unless defined $msg; $msg =~ s@^\s+@@s; $msg =~ s@\s+\z@@s; $msg =~ s@\s+@ @gs; $msg = '???' unless length $msg; $msg = "#$msg" if $msg =~ m@^\d+\z@; $msg = ": $msg" unless $msg =~ m@^#@; $msg = " $msg" unless $msg =~ m@^:@; $details = "" unless defined $details; $details =~ s@^\s+@@s; $details =~ s@\s+\z@@s; $details =~ s@\s+@ @gs; if (!length ($details)) { $details = << 'END'; # 'END' must be single-quoted here This might be an I/O problem, a privileges problem, or a bug in the program. END } my $text = << "END"; # "END" must be double-quoted here

Internal error$msg

$details

END my %args = ( -dimensions => '550x225' , -text => $text , -title => 'Internal error' , -action_quit => "quit" , -top_space => 2 ); $args {-icon_path} = $ALERT_ICON_PATH if defined ($ALERT_ICON_PATH) && (-f $ALERT_ICON_PATH) && (-r $ALERT_ICON_PATH) && (-B $ALERT_ICON_PATH); &SimpleDialogBox (%args); undef; } #--------------------------------------------------------------------- # "CheckDirectRendering" checks the status of direct rendering and # sets the associated global flag appropriately. Note: If the flag in # question has already been set, this code simply returns. sub CheckDirectRendering { return if defined $FlagDirectRendering; my $str; # Scratch $str = `glxinfo 2>&1`; $str = "" unless defined $str; # Is direct rendering supported? if ($str =~ m@direct rendering: Yes@) { # Yes $FlagDirectRendering = TRUE; } else { # No $FlagDirectRendering = FALSE; } undef; } #--------------------------------------------------------------------- # Future change: Document this routine. sub LocateSlumpHistory { my $str; # Scratch my $HOME = $ENV {HOME}; &PanicDialog ("#$REVISION-0001") unless defined ($HOME); $str = "$HOME/.prboom-plus"; system "mkdir -p $str" unless -d $str; $SLUMPFILE = "$str/$SLUMP_HISTORY" if -d $str; if ((!-f $SLUMPFILE) || (-z $SLUMPFILE)) { open (OFD, ">>$SLUMPFILE") || &PanicDialog ("#$REVISION-0002"); $SLUMP_HEADER =~ s@\s*\z@\n\n@; print OFD $SLUMP_HEADER; @SLUMP_DEFAULT_SEEDS = sort by_number @SLUMP_DEFAULT_SEEDS; for (@SLUMP_DEFAULT_SEEDS) { print OFD "$_\n"; } close (OFD) || &PanicDialog ("#$REVISION-0003"); } undef; } #--------------------------------------------------------------------- # Future change: Document this routine. sub Load_CFG_PRFREEBOOM { my $data; # Data buffer my $str; # Scratch #--------------------------------------------------------------------- # Initial setup. my $HOME = $ENV {HOME}; &PanicDialog ("#$REVISION-0004") unless defined ($HOME); $str = "$HOME/.prboom-plus"; system "mkdir -p $str" unless -d $str; &PanicDialog ("#$REVISION-0005") unless -d $str; # Absolute pathname for config. file $CFG_PATH_PRFREEBOOM = "$str/$CFG_NAME_PRFREEBOOM"; &CheckDirectRendering(); # Check status of direct rendering # Code may override this setting at a # later point $CFG_HighRes = $FlagDirectRendering; #--------------------------------------------------------------------- # Create configuration file (if necessary). if ((!-f $CFG_PATH_PRFREEBOOM) || (-z $CFG_PATH_PRFREEBOOM)) { open (OFD, ">$CFG_PATH_PRFREEBOOM") || &PanicDialog ("#$REVISION-0006"); $CFG_DEFAULT_PRFREEBOOM =~ s@\s*\z@\n@; print OFD $CFG_DEFAULT_PRFREEBOOM; close (OFD) || &PanicDialog ("#$REVISION-0007"); } #--------------------------------------------------------------------- # Read (entire) configuration file. open (IFD, "<$CFG_PATH_PRFREEBOOM") || &PanicDialog ("#$REVISION-0008"); undef $/; binmode IFD; $data = ; $data = "" unless defined $data; close IFD; #--------------------------------------------------------------------- # Save a global copy. $CFG_DATA = $data; #--------------------------------------------------------------------- # Apply settings. $data =~ y/\011\040/ /s; $data =~ s@ *#[^\012]*@@g; $data =~ s@ *= *(0|no?|off|zero|false)\b@=no@gi; $data =~ s@ *= *(1|y|yes|one?|true)\b@=yes@gi; if ($data =~ m@\nalternate_music=(\w+)@) { $CFG_AltMusic = ($1 eq 'yes') ? TRUE : FALSE; } if ($data =~ m@\nbeautiful=(\w+)@) { $CFG_BeauDoom = ($1 eq 'yes') ? TRUE : FALSE; } if ($data =~ m@\ncharacters_sf=(\w+)@) { $CFG_SciFi = ($1 eq 'yes') ? TRUE : FALSE; } if ($data =~ m@\nleggo=(\w+)@) { $CFG_Leggo = ($1 eq 'yes') ? TRUE : FALSE; } if ($data =~ m@\nsave_slump=(\w+)@) { $CFG_Save_Slump = ($1 eq 'yes') ? TRUE : FALSE; } if ($data =~ m@\nspider_robots=(\w+)@) { $CFG_Spiders = ($1 eq 'yes') ? TRUE : FALSE; } if ($data =~ m@\nvideo_highres=(\w+)@) { $CFG_HighRes = ($1 eq 'yes') ? TRUE : FALSE; } undef; } #--------------------------------------------------------------------- # Future change: Document this routine. sub Update_CFG_PRFREEBOOM { my $data; # Data buffer my $str; # Scratch #--------------------------------------------------------------------- # Initial setup. &PanicDialog ("#$REVISION-0009") unless defined ($CFG_PATH_PRFREEBOOM) && defined ($CFG_DATA); #--------------------------------------------------------------------- # Adjust in-memory contents based on GUI settings. my $V_AltMusic = $CB_AltMusic ->get_active ? 'yes' : 'no'; my $V_BeauDoom = $CB_BeauDoom ->get_active ? 'yes' : 'no'; my $V_HighRes = $CB_HighRes ->get_active ? 'yes' : 'no'; my $V_Leggo = $CB_Leggo ->get_active ? 'yes' : 'no'; my $V_Save_Slump = $CB_Save_Slump ->get_active ? 'yes' : 'no'; my $V_SciFi = $CB_SciFi ->get_active ? 'yes' : 'no'; my $V_Spiders = $CB_Spiders ->get_active ? 'yes' : 'no'; my $BlockPat = '\[prfreeboom\][^\012]*\n'; my $WSZ = '[\011\040]*'; my $EQWSZ = "$WSZ=$WSZ"; my $OrigData = $CFG_DATA; if ($CFG_DATA !~ s@(\nalternate_music$EQWSZ)\w+@$1$V_AltMusic@i) { $str = "alternate_music=$V_AltMusic\n"; $CFG_DATA =~ s@\nalternate_music$EQWSZ[^\012]*@@gi; $CFG_DATA =~ s@($BlockPat)@$1$str@i; } if ($CFG_DATA !~ s@(\ncharacters_sf$EQWSZ)\w+@$1$V_SciFi@i) { $str = "characters_sf=$V_SciFi\n"; $CFG_DATA =~ s@\ncharacters_sf$EQWSZ[^\012]*@@gi; $CFG_DATA =~ s@($BlockPat)@$1$str@i; } if ($CFG_DATA !~ s@(\nbeautiful$EQWSZ)\w+@$1$V_BeauDoom@i) { $str = "beautiful=$V_BeauDoom\n"; $CFG_DATA =~ s@\nbeautiful$EQWSZ[^\012]*@@gi; $CFG_DATA =~ s@($BlockPat)@$1$str@i; } if ($CFG_DATA !~ s@(\nleggo$EQWSZ)\w+@$1$V_Leggo@i) { $str = "leggo=$V_Leggo\n"; $CFG_DATA =~ s@\nleggo$EQWSZ[^\012]*@@gi; $CFG_DATA =~ s@($BlockPat)@$1$str@i; } if ($CFG_DATA !~ s@(\nsave_slump$EQWSZ)\w+@$1$V_Save_Slump@i) { $str = "save_slump=$V_Save_Slump\n"; $CFG_DATA =~ s@\nsave_slump$EQWSZ[^\012]*@@gi; $CFG_DATA =~ s@($BlockPat)@$1$str@i; } if ($CFG_DATA !~ s@(\nspider_robots$EQWSZ)\w+@$1$V_Spiders@i) { $str = "spider_robots=$V_Spiders\n"; $CFG_DATA =~ s@\nspider_robots$EQWSZ[^\012]*@@gi; $CFG_DATA =~ s@($BlockPat)@$1$str@i; } if ($CFG_DATA !~ s@(\nvideo_highres$EQWSZ)\w+@$1$V_HighRes@i) { $str = "video_highres=$V_HighRes\n"; $CFG_DATA =~ s@\nvideo_highres$EQWSZ[^\012]*@@gi; $CFG_DATA =~ s@($BlockPat)@$1$str@i; } $CFG_DATA =~ s@\s*\z@\n@; #--------------------------------------------------------------------- # Update disk copy. if ($CFG_DATA ne $OrigData) { open (OFD, ">$CFG_PATH_PRFREEBOOM") || &PanicDialog ("#$REVISION-0010"); binmode OFD; print OFD $CFG_DATA; close (OFD) || &PanicDialog ("#$REVISION-0011"); } undef; } #--------------------------------------------------------------------- # Future change: Document this routine. sub Update_CFG_PRBOOM_PLUS { my $data; # Data buffer my $orig_data; # Copy of original data my $str; # Scratch #--------------------------------------------------------------------- # Initial setup. my $HOME = $ENV {HOME}; &PanicDialog ("#$REVISION-0012") unless defined ($HOME); $str = "$HOME/.prboom-plus"; system "mkdir -p $str" unless -d $str; &PanicDialog ("#$REVISION-0013") unless -d $str; &CheckDirectRendering(); # Check status of direct rendering # Absolute pathname for config. file $CFG_PATH_PRBOOM_PLUS = "$str/$CFG_NAME_PRBOOM_PLUS"; #--------------------------------------------------------------------- # Create configuration file (if necessary). if ((!-f $CFG_PATH_PRBOOM_PLUS) || (-z $CFG_PATH_PRBOOM_PLUS)) { open (OFD, ">$CFG_PATH_PRBOOM_PLUS") || &PanicDialog ("#$REVISION-0014"); $CFG_DEFAULT_PRBOOM_PLUS =~ s@\s*\z@\n@; print OFD $CFG_DEFAULT_PRBOOM_PLUS; close (OFD) || &PanicDialog ("#$REVISION-0015"); } #--------------------------------------------------------------------- # Read (entire) configuration file. open (IFD, "<$CFG_PATH_PRBOOM_PLUS") || &PanicDialog ("#$REVISION-0016"); undef $/; binmode IFD; $data = ; $data = "" unless defined $data; $orig_data = $data; close IFD; #--------------------------------------------------------------------- # Make necessary adjustment(s). # Note: We don't need to adjust screen width or height at the config- # uration-file level. ExecTarget sets these two parameters appropri- # ately at the CLI level. if ($DISABLE_DRI) { $str = $FlagHighResolution ? "16bit" : "8bit"; } else { $str = ($FlagHighResolution && $FlagDirectRendering) ? "OpenGL" : "8bit"; } $data =~ s@(^|\n)(\s*videomode[\011\040]+)("[^"]*")@$1$2"$str"@i; #--------------------------------------------------------------------- # Write data back to configuration file (if necessary). if ($data ne $orig_data) # Did we change anything? { # Yes open (OFD, ">$CFG_PATH_PRBOOM_PLUS") || &PanicDialog ("#$REVISION-0017"); print OFD $data; close (OFD) || &PanicDialog ("#$REVISION-0018"); } undef; } #--------------------------------------------------------------------- # "ExecTarget" runs the target program or passes control to a new # screen. The details are as follows: # "ExecTarget" assumes that $SimpleList is the current selection list # and that the user has selected one of the entries in $SimpleList. # This version of "ExecTarget" supports two entry types: # # a. Level-generator strings of the following form: # # Slump \d+-\d+ # # Note: For an explanation of the "\d+-\d+" format shown here, # see the comments preceding the definition of @SLUMP_DEFAULT_ # SEEDS. # # b. Any string that's a valid %WadMap key. # In case (a), "ExecTarget" creates the specified prfreeboom/Slump le- # vel (including alternate music) and runs it. To create the level # (and alternate music), "bsp", "deutex440", "slump", and a package- # specific utility named "mus2pwad" are used. To run the level, modi- # fied copies of "prboom" and "freedoom" are used. # In case (b), "ExecTarget" looks up the specified string using "%Wad- # Map". Five result types are supported: # # b1. String "__META_FREEDM__". This result tells "ExecTarget" to # play FreeDoom. # # b2. String "__META_SLIGE__". This result tells "ExecTarget" to # create and run a new Slige level. # # b3. String "__META_SLUMP__". This result tells "ExecTarget" to # create and run a new Slump level. # # b4. A WAD-file pathname. This result tells "ExecTarget" to run # the level stored in the specified file. # # b5. String "__META_OLDSLUMP__". This result tells "ExecTarget" # to start a Slump saved-levels selection screen. Note: The # selection screen in question may call "ExecTarget", in turn, # to trigger case (a) (which was discussed previously). # "ExecTarget" supports alternate music for cases (b2) through (b4). # Additionally, for case (b3), it saves the level-generator key used # for future use (unless the user has disabled this feature). # "ExecTarget" uses "system" (as opposed to "exec") to start "prboom". # This allows "ExecTarget" to clean up temporary files after the lat- # ter program exits. # Note: You should be able to obtain source code for the following # utilities and/or datasets from the same place as this file: bsp, # deutex440, freedoom, midi2pwad, prboom, slige, and slump. #--------------------------------------------------------------------- sub ExecTarget { my $n; # Scratch (integer) my $str; # Scratch (string ) my $FlagDoom2; # Flag: Doom 2 (as opposed to Doom 1) my $MapSelector; # Slump map selector (either -E#M# or # -map##, where each "#" is a single # digit) my $wad; # WAD-file pathname (or a meta-symbol # that selects a WAD-file mode) my ($width, $height); # Display width/height used my @tmpfiles = (); # Temporary-file pathnames #--------------------------------------------------------------------- # "prfreeboom" uses two kinds of level-generator keys: # # a. Standard Slump seeds of the form \d+ # b. High-level "prfreeboom/Slump" keys of the form \d+-\d+ # Note: For an explanation of the "prfreeboom/Slump" level-generator # key format, see the comments preceding the definition of @SLUMP_ # DEFAULT_SEEDS. # If $OldLevel is defined, it specifies a standard Slump seed (as op- # posed to a "prfreeboom/Slump" level-generator key). my $OldLevel; #--------------------------------------------------------------------- # Initial setup. $FlagHighResolution = $CB_HighRes->get_active ? TRUE : FALSE; &Update_CFG_PRFREEBOOM(); # Update "prfreeboom" config. file &Update_CFG_PRBOOM_PLUS(); # Update "prboom-plus" config. file #--------------------------------------------------------------------- # Identify selected level (or mode). my ($model, $iter) = $SimpleList->get_selection->get_selected; my $selected = $model->get ($iter, ZERO); if ($selected =~ m@Play FreeDoom@) { # The rest of this case is handled by # the __META_FREEDM__ support code $wad = '__META_FREEDM__'; } elsif ($selected =~ m@^Slump (\d+)-(\d)(\d)(\d)\b@) { # See notes preceding this routine $OldLevel = $1; # This part is a standard Slump seed if ($2 eq '1') { # Doom 1 mode is selected $FlagDoom2 = FALSE; $MapSelector = "-E$3M$4"; # Consistency check &PanicDialog ("#$REVISION-0019") if ($3 < 1) || ($3 > 3) || ($4 < 1); } elsif ($2 eq '2') { # Doom 2 mode is selected $FlagDoom2 = TRUE; $MapSelector = "-map$3$4"; } else { # Internal error &PanicDialog ("#$REVISION-0020"); } # The rest of this case is handled by # the __META_SLUMP__ support code $wad = '__META_SLUMP__'; } elsif ($selected =~ m@^Slump@) { # Internal error &PanicDialog ("#$REVISION-0021"); } else { # See notes preceding this routine $wad = $WadMap {$selected}; } # Consistency check &PanicDialog ("#$REVISION-0022") unless defined $wad; #--------------------------------------------------------------------- # Handle a special case. # For more information on the PRFREESKULL variable used below, see the # code in "slump.spcpat". You should be able to obtain the latter # file from the same place as this file. if ($CB_SciFi->get_active && !$CB_Spiders->get_active) { # S.F. characters are enabled and Spi- # der Robots are disabled $ENV {PRFREESKULL} = 'no'; } else { delete $ENV {PRFREESKULL}; } #--------------------------------------------------------------------- # Handle the various WAD-file modes. my $GeneratedLevel = FALSE; # Flag: Generated a level if ($wad eq '__META_SLIGE__') { # See notes preceding this routine my $xtmpbase = "/var/tmp/prfreeboom-$>-$$-slige"; $wad = "$xtmpbase.wad"; push (@tmpfiles, $wad); # Build appropriate command sequence $str = << "END"; # "END" must be double-quoted here slige $xtmpbase.dat -doom2 bsp $xtmpbase.dat $wad rm $xtmpbase.dat END print $str; # Print the commands to be used system $str; # Run them $GeneratedLevel = TRUE; # Assert that we generated a level } elsif ($wad eq '__META_SLUMP__') { # See notes preceding this routine my $seed = defined ($OldLevel) ? $OldLevel : time; my $xtmpbase = "/var/tmp/prfreeboom-$>-$$-slump"; $wad = "$xtmpbase.wad"; push (@tmpfiles, $wad); &PanicDialog ("#$REVISION-0023") unless defined $SLUMPFILE; &PanicDialog ("#$REVISION-0024") unless -f $SLUMPFILE; &PanicDialog ("#$REVISION-0025") if -z $SLUMPFILE; if (!defined $FlagDoom2) { # Select Doom 1 or Doom 2 mode # This code picks Doom 2 about 80% of # the time $FlagDoom2 = TRUE; $FlagDoom2 = FALSE if rand (100) < 20; # Consistency check &PanicDialog ("#$REVISION-0026") if defined ($MapSelector); } else { # Doom 1 vs. Doom 2 is already decided # Consistency check &PanicDialog ("#$REVISION-0027") unless defined ($MapSelector); } # Do we have a Slump map selector? if (!defined $MapSelector) { # No - Create one if ($FlagDoom2) { # Doom 2 mode $n = ONE + int (rand ($MAX_DOOM2_LEVNUM)); $n = sprintf ('%02d', $n); $MapSelector = "-map$n"; } else { # Doom 1 mode my ($n1, $n2); $n1 = ONE + int (rand (3)); $n2 = ONE + int (rand (9)); $MapSelector = "-E${n1}M${n2}"; } } if (!defined ($OldLevel) && $CB_Save_Slump->get_active && open (OFD, ">>$SLUMPFILE")) { # Save prfreeboom/Slump level-genera- # tor key for future use my ($v1, $v2); $v1 = $FlagDoom2 ? TWO : ONE; $v2 = "$1$2" if $MapSelector =~ m@(\d)[a-z]?(\d)\z@i; &PanicDialog ("#$REVISION-0028") unless defined ($v1); &PanicDialog ("#$REVISION-0029") unless defined ($v2); print OFD "$seed-$v1$v2\n"; } # Build appropriate command sequence $str = $FlagDoom2 ? " -doom2" : ""; $str = ""; # Doom2 mode no longer works here $str = << "END"; # "END" must be double-quoted here slump $xtmpbase.dat$str -levels 1 -seed $seed $MapSelector bsp $xtmpbase.dat $wad rm $xtmpbase.dat END print $str; # Print the commands to be used system $str; # Run them $GeneratedLevel = TRUE; # Assert that we generated a level } elsif ($wad eq '__META_OLDSLUMP__') { # See notes preceding this routine &ReplayOldSlump(); exit (ZERO); } #--------------------------------------------------------------------- # Get initial display dimensions (if possible). my $X11DIM; $str = `getx11dim 2>&1`; $str = "" unless defined $str; $str =~ s@\s+\z@@s; $X11DIM = $str if $str =~ m@^\d+x\d+\z@; #--------------------------------------------------------------------- # Set up "prboom" command-line argument list. if (!-f $FILE_COMBINED) # Do a basic configuration check { # Error - Explain things to the user $str = << 'END'; prfreeboom requires modified copies of PRBoom, FreeDoom, and Slump. You should be able to get source code from the same place as this program. END $str =~ s@\b($ProgNames)('s|[\.,;]|\b)@@gi; &PanicDialog ('Invalid setup', $str); } my @ARGS = # Start argument list ( '-iwad', $FILE_COMBINED, '-file', $wad ); $str = $wad; die unless $str =~ s@\.wad\z@.deh@; push (@ARGS, $str) if -f $str; #ifdef NOTDEF # @ARGS = ('-iwad', $FILE_FDALT) if $wad eq '__META_FREEDM__'; #endif if (TRUE) { my @FileMUS = (); my $FileMUS; $str = $wad; $str =~ s@\.wad\z@.mus@i; $FileMUS = $str; if ($CB_AltMusic->get_active && (!-f $str) && opendir (DIR, $DIR_LEVELS)) { while (defined ($_ = readdir (DIR))) { next unless m@^_slump\S*\.mus\z@i; $str = "$DIR_LEVELS/$_"; next unless -f $str; push (@FileMUS, $str); } closedir DIR; if (scalar @FileMUS) { $n = rand ($#FileMUS + ONE); $FileMUS = $FileMUS [$n]; } } if (-f $FileMUS) # Is a ".mus" file selected? { # Yes - Translate it to PWAD format my $tmpwad = "/var/tmp/prfreeboom-$>-$$-delete.wad"; unlink $tmpwad; system << "END"; mus2pwad --music=$FileMUS --level=$wad --output=$tmpwad END if (-f $tmpwad) { print "Using alternate music file\n"; push (@ARGS , $tmpwad); push (@tmpfiles , $tmpwad); } } } if ($CB_BeauDoom ->get_active && ($wad !~ m@(^|)tc_@i)) { # BeauDoom mode push (@ARGS, "$DIR_DATA/beautiful.wad" ); } if ($CB_Leggo ->get_active && ($wad !~ m@(^|/)tc_@i)) { # Leggo mode push (@ARGS, "$DIR_DATA/leggo.wad"); } if ($CB_SciFi ->get_active && ($wad !~ m@(^|)tc_@i)) { # Science Fiction mode push (@ARGS, "$DIR_DATA/monsters.wad" ); push (@ARGS, "$DIR_DATA/monsters.deh" ); } if ($FlagHighResolution) { # Use high resolution if possible my ($cw, $ch) = $X11DIM =~ m@^(\d+)x(\d+)@; &PanicDialog ("#$REVISION-0030") unless defined $ch; ($width, $height) = ( 640, 480 ); ($width, $height) = ( 1024, 768 ) if ($cw >= 1024) && ($ch >= 768); ($width, $height) = ( 1280, 900 ) if ($cw >= 1280) && ($ch >= 900); ($width, $height) = ( 1280, 1024 ) if ($cw >= 1280) && ($ch >= 1024); $FlagHighResolution = FALSE if $width < 1024; } else { # Use low resolution ($width, $height) = ( 640, 480 ); } # Finish argument list push (@ARGS, ('-warp', 'x', '-width', $width, '-height', $height)); #--------------------------------------------------------------------- # Shut down menu level. undef $SimpleList; if (defined $MainWindow) { Gtk2->main_quit; $MainWindow->destroy; undef $MainWindow; } #--------------------------------------------------------------------- # Run the target program. $SIG {CHLD} = "IGNORE"; system "$DIR_BASE/bin/prboom", @ARGS; #--------------------------------------------------------------------- # Fix resulting display problems (if necessary). if (defined ($X11DIM)) { $str = `getx11dim 2>&1`; $str = "" unless defined $str; $str =~ s@\s+\z@@s; system "/laclin/lacutil/setx11dim --fast $X11DIM" unless $str eq $X11DIM; #ifdef NOTDEF # system "xclockmove"; #endif } #--------------------------------------------------------------------- # Wrap it up. unlink @tmpfiles; undef; } #--------------------------------------------------------------------- # special-key handler #--------------------------------------------------------------------- sub SpecialKeyHandler { my $widget = shift; my $event = shift; my $keypress = $event->keyval; if ($keypress == $Gtk2::Gdk::Keysyms {Escape}) { Gtk2->main_quit; $MainWindow->destroy; exit (ONE); } if ($keypress == $Gtk2::Gdk::Keysyms {KP_Enter} || $keypress == $Gtk2::Gdk::Keysyms {Return }) { &ExecTarget(); exit ZERO; # Shouldn't get here &PanicDialog ("#$REVISION-0031"); #ifdef NOTDEF # Not presently used # return TRUE; # Consume the event #endif } return FALSE; # Pass the event on to GTK2 } #--------------------------------------------------------------------- # selection-window setup routine #--------------------------------------------------------------------- # Future change: Document this routine. sub RunSelectionWindow { my (%args) = @_; # Argument list my $str; # Scratch #--------------------------------------------------------------------- # Extract arguments. my $ref_list = $args { -ref_list }; my $text = $args { -text }; my $title_list = $args { -title_list }; my $title_main = $args { -title_main }; &PanicDialog ("#$REVISION-0032") unless defined ($ref_list ) || !defined ($text) || !defined ($title_list) || !defined ($title_main); my $slump_checkbox = TRUE; if (defined ($str = $args {-slump_checkbox}) && ($str =~ m@^(0|zero|n|no|false)\z@i)) { $slump_checkbox = FALSE; } #--------------------------------------------------------------------- # Close old window (if necessary). if (defined $MainWindow) { Gtk2->main_quit; $MainWindow->destroy; undef $MainWindow; } #--------------------------------------------------------------------- # Create main window. $MainWindow = Gtk2::Window->new; $MainWindow->set_position ('GTK_WIN_POS_CENTER'); $MainWindow->set_title ($title_main); $MainWindow->signal_connect (delete_event => sub { Gtk2->main_quit; TRUE; }); $MainWindow->set_default_size ($MAIN_WIDTH, $MAIN_HEIGHT); my $white = Gtk2::Gdk::Color->new (0xFFFF,0xFFFF,0xFFFF); $MainWindow->modify_bg ('normal', $white); $MainWindow->signal_connect ('key_release_event' => \&SpecialKeyHandler); #--------------------------------------------------------------------- # Create some regions. my $vbox = Gtk2::VBox->new (FALSE, 6); $MainWindow->add ($vbox); my $frame2 = Gtk2::Frame->new(); $vbox->pack_start ($frame2, TRUE, TRUE, ZERO); $frame2->set_border_width (3); #--------------------------------------------------------------------- # Create a Gtk2 "SimpleList" for the level-name list. my $font_desc = Pango::FontDescription->from_string ('Liberation Sans Bold 14') ; $SimpleList = Gtk2::SimpleList->new ($title_list => 'text'); $SimpleList->modify_font ($font_desc); for (@$ref_list) { $str = $_; $WadMap {$_} = $WadMap {$str} if s@^=\d+@=@; $WadMap {$_} = $WadMap {$str} if s@^= default level\z@(default level)@; } # This part is admittedly complicated @{$SimpleList->{data}} = map { $_ = [ $_ ]; } @$ref_list; $SimpleList->signal_connect (row_activated => \&ExecTarget); $SimpleList->select (ZERO); #--------------------------------------------------------------------- # Put the "SimpleList" in a Gtk2 "ScrolledWindow". my $ListWindow = Gtk2::ScrolledWindow->new (undef, undef); $ListWindow -> set_policy ('automatic', 'automatic'); $ListWindow -> add ($SimpleList); if ($FlagDirectRendering) { $text .= << 'END'; You seem to have a modern graphics card, so high-resolution mode is recommended. You can also use a low-resolution mode. The second mode is fuzzier, but it'll work on most systems that don't support the first mode.

END } else { $text .= << 'END'; This distro doesn't support accelerated graphics for your video card, so 640x480 mode is recommended.

END } #--------------------------------------------------------------------- # Create a Gtk2 "TextView" for the message text. my $textview = &LACGTK2_CreateTextView ( -text => $text , -top_space => ONE ); #--------------------------------------------------------------------- # Create option checkboxes. $CB_AltMusic = new Gtk2::CheckButton -> new_with_label ('Alt Music' ); ($CB_AltMusic ->get_children) [0] -> modify_font ($font_desc); $CB_HighRes = new Gtk2::CheckButton -> new_with_label ('HighRes' ); ($CB_HighRes ->get_children) [0] -> modify_font ($font_desc); # The underscore here is intentional. It reduces an issue that occurs # when the Spiders checkbox appears or disappears. $CB_BeauDoom = new Gtk2::CheckButton -> new_with_label ('Beautiful' ); ($CB_BeauDoom ->get_children) [0] -> modify_font ($font_desc); $CB_Leggo = new Gtk2::CheckButton -> new_with_label ('Leggo_' ); ($CB_Leggo ->get_children) [0] -> modify_font ($font_desc); $CB_Save_Slump = new Gtk2::CheckButton -> new_with_label ('Save Slump' ); ($CB_Save_Slump ->get_children) [0] -> modify_font ($font_desc); $CB_SciFi = new Gtk2::CheckButton -> new_with_label ('SciFi' ); ($CB_SciFi ->get_children) [0] -> modify_font ($font_desc); $CB_Spiders = new Gtk2::CheckButton -> new_with_label ('Spiders' ); ($CB_Spiders ->get_children) [0] -> modify_font ($font_desc); #--------------------------------------------------------------------- # Set default checkbox states. $CFG_Leggo = FALSE if $CFG_SciFi ; $CFG_SciFi = FALSE if $CFG_Leggo ; $CB_AltMusic -> set_active ($CFG_AltMusic ); $CB_BeauDoom -> set_active ($CFG_BeauDoom ); $CB_HighRes -> set_active ($CFG_HighRes ); $CB_Leggo -> set_active ($CFG_Leggo ); $CB_Save_Slump -> set_active ($CFG_Save_Slump ); $CB_SciFi -> set_active ($CFG_SciFi ); $CB_Spiders -> set_active ($CFG_Spiders ); #--------------------------------------------------------------------- # Add option radio buttons/checkboxes to a table. my $OptTable = Gtk2::Table->new (6, 2, FALSE); $OptTable -> attach_defaults ($CB_SciFi , 0, 2, 0, 1); $OptTable -> attach_defaults ($CB_AltMusic , 0, 2, 1, 2); $OptTable -> attach_defaults ($CB_Leggo , 2, 4, 0, 1); $OptTable -> attach_defaults ($CB_Spiders , 2, 4, 1, 2); $OptTable -> attach_defaults ($CB_BeauDoom , 4, 6, 0, 1); #ifdef NOTDEF # $OptTable -> attach_defaults ($CB_HighRes , 2, 3, 0, 1); # $OptTable -> attach_defaults ($CB_Save_Slump , 2, 3, 1, 2) # if $slump_checkbox; #endif #--------------------------------------------------------------------- # Assemble all the pieces. my $FrameText = Gtk2::Frame->new ('Instructions'); $FrameText -> set_border_width (3); $FrameText -> add ($textview); my $FrameOptions = Gtk2::Frame->new ('Options'); $FrameOptions -> set_border_width (3); $FrameOptions -> add ($OptTable); my $RightSide = Gtk2::VBox->new (FALSE, 6); $RightSide -> pack_start ($FrameText , TRUE , 1, 0); $RightSide -> pack_start ($FrameOptions , FALSE, 0, 4); my $MainTable = Gtk2::Table->new (1, 4, TRUE); $MainTable -> attach_defaults ($ListWindow , 0, 1, 0, 1); $MainTable -> attach_defaults ($RightSide , 1, 4, 0, 1); $frame2->add ($MainTable); #--------------------------------------------------------------------- # Add OK/Quit buttons. &LACGTK2_AddButtons ( -vbox => $vbox , -action_ok => '&ExecTarget' , -action_quit => 'quit' ); #--------------------------------------------------------------------- # Make everything visible. $MainWindow->show_all; #--------------------------------------------------------------------- # Handle character-mode side effects. # If S.F. characters are selected (at startup time or afterwards), # this code makes the "Spiders" checkbox visible. # If S.F. characters are deselected (at startup time or afterwards), # this code makes the "Spiders" checkbox invisible. #--------------------------------------------------------------------- if ($CFG_SciFi) { $CB_Spiders -> show_all; } else { $CB_Spiders -> hide_all; } #--------------------------------------------------------------------- $CB_BeauDoom -> signal_connect ( clicked => sub { if ($CB_BeauDoom->get_active) { $CFG_BeauDoom = TRUE ; } else { $CFG_BeauDoom = FALSE ; } } ); #--------------------------------------------------------------------- $CB_Leggo -> signal_connect ( clicked => sub { if ($CB_Leggo->get_active) { $CB_SciFi -> set_active (FALSE); $CB_Spiders -> hide_all; $CFG_Leggo = TRUE ; $CFG_SciFi = FALSE ; } else { $CFG_Leggo = FALSE; } } ); #--------------------------------------------------------------------- $CB_SciFi -> signal_connect ( clicked => sub { if ($CB_SciFi->get_active) { $CB_Leggo -> set_active (FALSE); $CB_Spiders -> show_all; $CFG_Leggo = FALSE ; $CFG_SciFi = TRUE ; } else { $CFG_SciFi = FALSE ; $CB_Spiders -> hide_all; } } ); #--------------------------------------------------------------------- # Wrap it up. Gtk2->main; # Start Gtk2 main loop undef; } #--------------------------------------------------------------------- # Slump-selection screen #--------------------------------------------------------------------- # "ReplayOldSlump" displays a screen that allows the user to select # an old Slump level and play it. sub ReplayOldSlump { my $data; # Data buffer my @list = (); # List of Slump level-generation keys my $str; # Scratch #--------------------------------------------------------------------- # Initial setup. &Load_CFG_PRFREEBOOM(); # Load "prfreeboom.cfg" settings &CheckDirectRendering(); # Check status of direct rendering &LocateSlumpHistory(); # Locate Slump history file #--------------------------------------------------------------------- # Build list of old "Slump" levels. open (IFD, "<$SLUMPFILE") || &PanicDialog ("#$REVISION-0033"); undef $/; binmode IFD; $data = ; $data = "" unless defined $data; close IFD; $data =~ s@#[^\012]*@@g; $data =~ s@^\s+@@s; $data =~ s@\s+\z@@s; $data =~ s@\s+@ @gs; @list = sort reverse_by_number split (/\s+/, $data); for (@list) { s@^(\d+)\b@Slump $1@; } if ((scalar @list) > $MAX_SLUMP_LEVELS) { splice (@list, $MAX_SLUMP_LEVELS); } #--------------------------------------------------------------------- # Define message text (with tags). # Note: The message text can use certain HTML-like tags, but HTML per # se isn't supported. For more information, see the LACSUB code. my $text = << 'END'; # 'END' must be single-quoted here

Use the box on the left to select a Slump level. Left-click on a level name and press

Enter
or click
OK.
Or you can just double-click. To quit at this point, press
Escape
or
alt-Q,
or click
Quit.

Default controls:
   (after the game starts)
1 to 5: Select weapon. L-CTRL - Fire selected weapon. Arrow keys: Move or turn. Space: Jump. R-Shift: Open a door or activate a switch (or a lift). Tab: Toggle Map mode. Escape: Quit.

Background:
  Presently, you can replay the __META_MAX_SLUMP_LEVELS__ most recent Slump levels. There's no provision for naming Slump levels or saving them permanently, but these features may be added in the future.

END $text =~ s@\b(Slump)\b@@g; $text =~ s@__META_MAX_SLUMP_LEVELS__@100@g; #--------------------------------------------------------------------- # Create/run selection window. my $title_list = 'Old Slump Levels'; my $title_main = 'Replay old Slump level'; &RunSelectionWindow ( -ref_list => \@list , -text => $text , -title_list => $title_list , -title_main => $title_main , -slump_checkbox => FALSE ); undef; } #--------------------------------------------------------------------- # normal level-selection screen #--------------------------------------------------------------------- sub NormalScreen { my $dirent; # Directory entry my $str; # Scratch #--------------------------------------------------------------------- # Initial setup. &CheckDirectRendering(); # Check status of direct rendering &LocateSlumpHistory(); # Locate Slump history file #--------------------------------------------------------------------- # Build list of levels. my $DEFAULT_PATH; opendir (DIR, $DIR_LEVELS) || &PanicDialog ("#$REVISION-0034"); while (defined ($dirent = readdir (DIR))) { next unless $dirent =~ m@^([a-z0-9_\-]+)\.wad\z@i; my $basename = $1; my $path = "$DIR_LEVELS/$dirent"; next unless -f $path; $str = $path; $str =~ s@\.wad\z@.note@i; my $note = ""; if (open (IFD, "<$str")) { $note = ; close (IFD); $note =~ s@^\s+@@s; $note =~ s@\s+\z@@s; $note =~ s@\s+@ @g;; $note =~ s@^({.20}).+@$1...@; } $str = $basename; $str =~ s@^tc_@=9 TC: @i; $str =~ s@_+@ @g; # Note: The following block makes adjustments to specific WAD-file # names. The WAD files in question may (or may not) be present. How- # ever, if they're not present, this code shouldn't cause any prob- # lems. $str =~ s@^(The)(pits|tower|zoo)@$1 $2@i; $str =~ s@^contain\z@Containment@i; $str =~ s@^castle5\z@Castle-5@i; $str =~ s@^castlem\z@Castle-M@i; $str =~ s@(^| )([a-z])@$1 . uc ($2)@geis; $str .= " - $note" if length $note; $WadMap {$str} = $path; $str = $dirent; $str =~ s@\.wad\z@@i; $DEFAULT_PATH = $path if $str =~ m@$DEFAULT_PATTERN@i; } closedir DIR; $WadMap {'=0 default level'} = $DEFAULT_PATH if defined $DEFAULT_PATH; #ifdef NOTDEF # $WadMap {'=1 Play FreeDoom' } = '__META_FREEDM__' ; #endif $WadMap {'=2 Create a Slump level' } = '__META_SLUMP__' ; $WadMap {'=3 Create a Slige level' } = '__META_SLIGE__' ; # This feature is disabled for now because there are two glitches: # (a) Selecting this mode launches the first saved level without the # opportunity to select a level. (b) There should be a way to delete # old levels. if (FALSE && (-f $SLUMPFILE) && (!-z $SLUMPFILE)) { $WadMap {'=4 replay old Slump levels'} = '__META_OLDSLUMP__'; } #--------------------------------------------------------------------- # Define message text (with tags). # Notes: # # a. The message text can use certain HTML-like tags, but HTML per se # isn't supported. For more information, see the LACSUB code. # # b.

Welcome to prfreeboom. Use the box on the left to select a game or level. Left-click on a name and press

Enter
or click
OK.
Or you can just double-click.
TC:
lines are Doom Total Conversions. The
Avactor
TC is slow to load. To quit this screen, press
Escape
or
alt-Q,
or click
Quit.
The
Create level
commands will create simple new levels. Slump is recommended for this, but Slige is included as well.

SciFi
characters are used by default except in Total Conversions. To turn this off, or to turn the
Leggo
or
Beautiful
modes on, use the checkboxes below.
Alt Music
enables random music. Some games or levels will play fixed or random music regardless.

Default controls
(after the game starts):     1 to 5: Select weapon. L-CTRL - Fire selected weapon. Arrow keys: Move or turn. Space: Jump. R-Shift: Open a door or activate a switch (or a lift). Tab: Toggle Map mode. Escape: Quit.

Background:
  prfreeboom is a FOSS wrapper for PRBoom-Plus, FreeDoom, Slump, Slige, bsp, and deutex. This package can play most Doom and levels because it replaces proprietary components.

END $text =~ s@\b($ProgNames)('s|[\.,;]|\b)@@gi; $text =~ s@__META_FREEDOOM__@FreeDoom@g; #--------------------------------------------------------------------- # Create/run selection window. my @list = sort keys %WadMap; my $title_list = 'Levels'; my $title_main = "prfreeboom $REVISION"; &RunSelectionWindow ( -ref_list => \@list , -text => $text , -title_list => $title_list , -title_main => $title_main ); undef; } #--------------------------------------------------------------------- # main routine #--------------------------------------------------------------------- sub Main { my $str; # Scratch #--------------------------------------------------------------------- # Create default config file. my $HOME = $ENV {'HOME'}; my $CDIR = "$HOME/.prboom-plus"; system "mkdir $CDIR" unless -d $CDIR; die unless -d $CDIR; my $CFILE = #--------------------------------------------------------------------- # Verify that program isn't already running. &VerifyNotRunning ( -icon_path => $ALERT_ICON_PATH , -name => 'prfreeboom' , -pattern_this => ':\d\d\s(perl |)(\S+/|)prfreeboom\s' , -pattern_next => ':\d\d\s(\S+/|)prboom\s' ); #--------------------------------------------------------------------- # Abort if user is connected through VNC. &AbortIfVNC ( -icon_path => $ALERT_ICON_PATH , -name => 'prfreeboom' ); #--------------------------------------------------------------------- # Adjust PATH. $str = $ENV {PATH}; $str = "" unless defined $str; $str = "$DIR_BIN:$str"; $str =~ s@:+\z@@; $ENV {PATH} = $str; #--------------------------------------------------------------------- # Additional setup. &Load_CFG_PRFREEBOOM(); # Load "prfreeboom.cfg" settings srand (time() ^ ($$ + ($$ << 15))); my $FlagSlump = FALSE; for (@ARGV) { $FlagSlump = TRUE if m@^-*(old|)slump@i; } #--------------------------------------------------------------------- # Display appropriate screen. if ($FlagSlump) { &ReplayOldSlump(); } else { &NormalScreen(); } undef; } #--------------------------------------------------------------------- # main program #--------------------------------------------------------------------- &Main(); # Call the main routine exit ZERO; # Normal exit