449 lines
9.3 KiB
Objective-C
449 lines
9.3 KiB
Objective-C
//
|
|
// Copyright(C) 2005-2014 Simon Howard
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <AppKit/AppKit.h>
|
|
#include "IWADController.h"
|
|
#include "IWADLocation.h"
|
|
|
|
typedef enum
|
|
{
|
|
IWAD_DOOM1,
|
|
IWAD_DOOM2,
|
|
IWAD_TNT,
|
|
IWAD_PLUTONIA,
|
|
IWAD_CHEX,
|
|
IWAD_HERETIC,
|
|
IWAD_HEXEN,
|
|
IWAD_STRIFE,
|
|
NUM_IWAD_TYPES
|
|
} IWAD;
|
|
|
|
static NSString *IWADLabels[NUM_IWAD_TYPES] =
|
|
{
|
|
@"Doom",
|
|
@"Doom II: Hell on Earth",
|
|
@"Final Doom: TNT: Evilution",
|
|
@"Final Doom: Plutonia Experiment",
|
|
@"Chex Quest",
|
|
@"Heretic",
|
|
@"Hexen",
|
|
@"Strife"
|
|
};
|
|
|
|
static NSString *IWADFilenames[NUM_IWAD_TYPES + 1] =
|
|
{
|
|
@"doom.wad",
|
|
@"doom2.wad",
|
|
@"tnt.wad",
|
|
@"plutonia.wad",
|
|
@"chex.wad",
|
|
@"heretic.wad",
|
|
@"hexen.wad",
|
|
@"strife.wad",
|
|
@"undefined"
|
|
};
|
|
|
|
@implementation IWADController
|
|
|
|
- (void) getIWADList: (IWADLocation **) iwadList
|
|
{
|
|
iwadList[IWAD_DOOM1] = self->doom1;
|
|
iwadList[IWAD_DOOM2] = self->doom2;
|
|
iwadList[IWAD_TNT] = self->tnt;
|
|
iwadList[IWAD_PLUTONIA] = self->plutonia;
|
|
iwadList[IWAD_CHEX] = self->chex;
|
|
iwadList[IWAD_HERETIC] = self->heretic;
|
|
iwadList[IWAD_HEXEN] = self->hexen;
|
|
iwadList[IWAD_STRIFE] = self->strife;
|
|
}
|
|
|
|
- (IWAD) getSelectedIWAD
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i=0; i<NUM_IWAD_TYPES; ++i)
|
|
{
|
|
if ([self->iwadSelector titleOfSelectedItem] == IWADLabels[i])
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return NUM_IWAD_TYPES;
|
|
}
|
|
|
|
// Get the location of the selected IWAD.
|
|
|
|
- (NSString *) getIWADLocation
|
|
{
|
|
IWAD selectedIWAD;
|
|
IWADLocation *iwadList[NUM_IWAD_TYPES];
|
|
|
|
selectedIWAD = [self getSelectedIWAD];
|
|
|
|
if (selectedIWAD == NUM_IWAD_TYPES)
|
|
{
|
|
return nil;
|
|
}
|
|
else
|
|
{
|
|
[self getIWADList: iwadList];
|
|
|
|
return [iwadList[selectedIWAD] getLocation];
|
|
}
|
|
}
|
|
|
|
static const char *NameForIWAD(IWAD iwad)
|
|
{
|
|
switch (iwad)
|
|
{
|
|
case IWAD_HERETIC:
|
|
return "heretic";
|
|
|
|
case IWAD_HEXEN:
|
|
return "hexen";
|
|
|
|
case IWAD_STRIFE:
|
|
return "strife";
|
|
|
|
default:
|
|
return "doom";
|
|
}
|
|
}
|
|
|
|
// Get the name used for the executable for the selected IWAD.
|
|
|
|
- (const char *) getGameName
|
|
{
|
|
return NameForIWAD([self getSelectedIWAD]);
|
|
}
|
|
|
|
- (void) setIWADConfig
|
|
{
|
|
IWADLocation *iwadList[NUM_IWAD_TYPES];
|
|
NSUserDefaults *defaults;
|
|
NSString *key;
|
|
NSString *value;
|
|
unsigned int i;
|
|
|
|
[self getIWADList: iwadList];
|
|
|
|
// Load IWAD filename paths
|
|
|
|
defaults = [NSUserDefaults standardUserDefaults];
|
|
|
|
for (i=0; i<NUM_IWAD_TYPES; ++i)
|
|
{
|
|
key = IWADFilenames[i];
|
|
value = [defaults stringForKey:key];
|
|
|
|
if (value != nil)
|
|
{
|
|
[iwadList[i] setLocation:value];
|
|
}
|
|
}
|
|
}
|
|
|
|
// On startup, set the selected item in the IWAD dropdown
|
|
|
|
- (void) setDropdownSelection
|
|
{
|
|
NSUserDefaults *defaults;
|
|
NSString *selected;
|
|
unsigned int i;
|
|
|
|
defaults = [NSUserDefaults standardUserDefaults];
|
|
selected = [defaults stringForKey: @"selected_iwad"];
|
|
|
|
if (selected == nil)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Find this IWAD in the filenames list, and select it.
|
|
|
|
for (i=0; i<NUM_IWAD_TYPES; ++i)
|
|
{
|
|
if ([selected isEqualToString:IWADFilenames[i]])
|
|
{
|
|
[self->iwadSelector selectItemWithTitle:IWADLabels[i]];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set the dropdown list to include an entry for each IWAD that has
|
|
// been configured. Returns true if at least one IWAD is configured.
|
|
|
|
- (BOOL) setDropdownList
|
|
{
|
|
IWADLocation *iwadList[NUM_IWAD_TYPES];
|
|
BOOL have_wads;
|
|
id location;
|
|
unsigned int i;
|
|
unsigned int enabled_wads;
|
|
|
|
// Build the new list.
|
|
|
|
[self getIWADList: iwadList];
|
|
[self->iwadSelector removeAllItems];
|
|
|
|
enabled_wads = 0;
|
|
|
|
for (i=0; i<NUM_IWAD_TYPES; ++i)
|
|
{
|
|
location = [iwadList[i] getLocation];
|
|
|
|
if (location != nil && [location length] > 0)
|
|
{
|
|
[self->iwadSelector addItemWithTitle: IWADLabels[i]];
|
|
++enabled_wads;
|
|
}
|
|
}
|
|
|
|
// Enable/disable the dropdown depending on whether there
|
|
// were any configured IWADs.
|
|
|
|
have_wads = enabled_wads > 0;
|
|
[self->iwadSelector setEnabled: have_wads];
|
|
|
|
// Restore the old selection.
|
|
|
|
[self setDropdownSelection];
|
|
|
|
return have_wads;
|
|
}
|
|
|
|
- (void) saveConfig
|
|
{
|
|
IWADLocation *iwadList[NUM_IWAD_TYPES];
|
|
IWAD selectedIWAD;
|
|
NSUserDefaults *defaults;
|
|
NSString *key;
|
|
NSString *value;
|
|
unsigned int i;
|
|
|
|
[self getIWADList: iwadList];
|
|
|
|
// Store all IWAD locations to user defaults.
|
|
|
|
defaults = [NSUserDefaults standardUserDefaults];
|
|
|
|
for (i=0; i<NUM_IWAD_TYPES; ++i)
|
|
{
|
|
key = IWADFilenames[i];
|
|
value = [iwadList[i] getLocation];
|
|
|
|
[defaults setObject:value forKey:key];
|
|
}
|
|
|
|
// Save currently selected IWAD.
|
|
|
|
selectedIWAD = [self getSelectedIWAD];
|
|
[defaults setObject:IWADFilenames[selectedIWAD]
|
|
forKey:@"selected_iwad"];
|
|
}
|
|
|
|
// Callback method invoked when the configuration button in the main
|
|
// window is clicked.
|
|
|
|
- (void) openConfigWindow: (id)sender
|
|
{
|
|
if (![self->configWindow isVisible])
|
|
{
|
|
[self->configWindow makeKeyAndOrderFront: sender];
|
|
}
|
|
}
|
|
|
|
// Callback method invoked when the close button is clicked.
|
|
|
|
- (void) closeConfigWindow: (id)sender
|
|
{
|
|
[self->configWindow orderOut: sender];
|
|
[self saveConfig];
|
|
[self setDropdownList];
|
|
}
|
|
|
|
- (void) awakeFromNib
|
|
{
|
|
[self->configWindow center];
|
|
|
|
// Set configuration for all IWADs from configuration file.
|
|
|
|
[self setIWADConfig];
|
|
|
|
// Populate the dropdown IWAD list.
|
|
|
|
if ([self setDropdownList])
|
|
{
|
|
[self setDropdownSelection];
|
|
}
|
|
}
|
|
|
|
// Generate a value to set for the DOOMWADPATH environment variable
|
|
// that contains each of the configured IWAD files.
|
|
|
|
- (char *) doomWadPath
|
|
{
|
|
IWADLocation *iwadList[NUM_IWAD_TYPES];
|
|
NSString *location;
|
|
unsigned int i;
|
|
BOOL first;
|
|
char *env;
|
|
size_t env_len;
|
|
|
|
[self getIWADList: iwadList];
|
|
|
|
// Calculate length of environment string.
|
|
|
|
env_len = 0;
|
|
|
|
for (i=0; i<NUM_IWAD_TYPES; ++i)
|
|
{
|
|
location = [iwadList[i] getLocation];
|
|
|
|
if (location != nil && [location length] > 0)
|
|
{
|
|
env_len += [location length] + 1;
|
|
}
|
|
}
|
|
|
|
// Build string.
|
|
|
|
env = malloc(env_len);
|
|
strlcpy(env, "", env_len);
|
|
|
|
first = YES;
|
|
|
|
for (i=0; i<NUM_IWAD_TYPES; ++i)
|
|
{
|
|
location = [iwadList[i] getLocation];
|
|
|
|
if (location != nil && [location length] > 0)
|
|
{
|
|
if (!first)
|
|
{
|
|
strlcat(env, ":", env_len);
|
|
}
|
|
|
|
strlcat(env, [location UTF8String], env_len);
|
|
first = NO;
|
|
}
|
|
}
|
|
|
|
return env;
|
|
}
|
|
|
|
// Set the DOOMWADPATH environment variable to contain the path to each
|
|
// of the configured IWAD files.
|
|
|
|
- (void) setEnvironment
|
|
{
|
|
char *doomwadpath;
|
|
char *env;
|
|
|
|
// Get the value for the path.
|
|
|
|
doomwadpath = [self doomWadPath];
|
|
|
|
asprintf(&env, "DOOMWADPATH=%s", doomwadpath);
|
|
|
|
free(doomwadpath);
|
|
|
|
// Load into environment:
|
|
|
|
putenv(env);
|
|
|
|
//free(env);
|
|
}
|
|
|
|
// Examine a path to a WAD and determine whether it is an IWAD file.
|
|
// If so, it is added to the IWAD configuration, and true is returned.
|
|
|
|
- (BOOL) addIWADPath: (NSString *) path
|
|
{
|
|
IWADLocation *iwadList[NUM_IWAD_TYPES];
|
|
NSArray *pathComponents;
|
|
NSString *filename;
|
|
unsigned int i;
|
|
|
|
[self getIWADList: iwadList];
|
|
|
|
// Find an IWAD file that matches the filename in the path that we
|
|
// have been given.
|
|
|
|
pathComponents = [path pathComponents];
|
|
filename = [pathComponents objectAtIndex: [pathComponents count] - 1];
|
|
|
|
for (i = 0; i < NUM_IWAD_TYPES; ++i)
|
|
{
|
|
if ([filename caseInsensitiveCompare: IWADFilenames[i]] == 0)
|
|
{
|
|
// Configure this IWAD.
|
|
|
|
[iwadList[i] setLocation: path];
|
|
|
|
// Rebuild dropdown list and select the new IWAD.
|
|
|
|
[self setDropdownList];
|
|
[self->iwadSelector selectItemWithTitle:IWADLabels[i]];
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
// No IWAD found with this name.
|
|
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL) selectGameByName: (const char *) name
|
|
{
|
|
IWADLocation *iwadList[NUM_IWAD_TYPES];
|
|
NSString *location;
|
|
const char *name2;
|
|
int i;
|
|
|
|
// Already selected an IWAD of the desired type? Just return
|
|
// success.
|
|
if (!strcmp(name, [self getGameName]))
|
|
{
|
|
return YES;
|
|
}
|
|
|
|
// Search through the configured IWADs and try to select the
|
|
// desired game.
|
|
[self getIWADList: iwadList];
|
|
|
|
for (i = 0; i < NUM_IWAD_TYPES; ++i)
|
|
{
|
|
location = [iwadList[i] getLocation];
|
|
name2 = NameForIWAD(i);
|
|
|
|
if (!strcmp(name, name2)
|
|
&& location != nil && [location length] > 0)
|
|
{
|
|
[self->iwadSelector selectItemWithTitle:IWADLabels[i]];
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
// User hasn't configured any WAD(s) for the desired game type.
|
|
return NO;
|
|
}
|
|
|
|
@end
|
|
|