diff --git a/src/drivers/common/SConscript b/src/drivers/common/SConscript
index 94f47a8e..64fadbe7 100644
--- a/src/drivers/common/SConscript
+++ b/src/drivers/common/SConscript
@@ -8,6 +8,7 @@ scale2x.cpp
 scale3x.cpp
 scalebit.cpp
 vidblit.cpp
+configSys.cpp
 """)
 
 for x in range(len(my_list)):
diff --git a/src/drivers/common/configSys.cpp b/src/drivers/common/configSys.cpp
new file mode 100644
index 00000000..a40f12b8
--- /dev/null
+++ b/src/drivers/common/configSys.cpp
@@ -0,0 +1,409 @@
+#include <iostream>
+#include <fstream>
+#include <stdio.h>
+
+#include "configSys.h"
+
+/**
+ * Add a given option.  The option is specified as a short command
+ * line (-f), long command line (--foo), option name (Foo), its type
+ * (integer or string).
+ */
+int
+Config::_addOption(char shortArg,
+                   const std::string &longArg,
+                   const std::string &name,
+                   int type)
+{
+    // make sure we have a valid type
+    if(type != INTEGER && type != STRING) {
+        return -1;
+    }
+
+    // check if the option already exists
+    if(_shortArgMap.find(shortArg) != _shortArgMap.end() ||
+       _longArgMap.find(longArg) != _longArgMap.end() ||
+       (type == INTEGER && _intOptMap.find(name) != _intOptMap.end()) ||
+       (type == STRING  && _strOptMap.find(name) != _strOptMap.end())) {
+        return -1;
+    }
+
+    // add the option
+    switch(type) {
+    case(INTEGER):
+        _intOptMap[name] = 0;
+        break;
+    case(STRING):
+        _strOptMap[name] = "";
+        break;
+    default:
+        break;
+    } 
+    _shortArgMap[shortArg] = name;
+    _longArgMap[longArg] = name;
+
+    return 0;
+}
+
+/**
+ * Add a given option and sets its default value.  The option is
+ * specified as a short command line (-f), long command line (--foo),
+ * option name (Foo), its type (integer or string), and its default
+ * value.
+ */
+int
+Config::addOption(char shortArg,
+                  const std::string &longArg,
+                  const std::string &name,
+                  int type,
+                  int defaultValue)
+{
+    int error;
+
+    // add the option to the config system
+    error = _addOption(shortArg, longArg, name, type);
+    if(error) {
+        return error;
+    }
+
+    // set the option to the default value
+    error = setOption(name, defaultValue);
+    if(error) {
+        return error;
+    }
+
+    return 0;
+}
+
+/**
+ * Add a given option and sets its default value.  The option is
+ * specified as a short command line (-f), long command line (--foo),
+ * option name (Foo), its type (integer or string), and its default
+ * value.
+ */
+int
+Config::addOption(char shortArg,
+                  const std::string &longArg,
+                  const std::string &name,
+                  int type,
+                  const std::string &defaultValue)
+{
+    int error;
+
+    // add the option to the config system
+    error = _addOption(shortArg, longArg, name, type);
+    if(error) {
+        return error;
+    }
+
+    // set the option to the default value
+    error = setOption(name, defaultValue);
+    if(error) {
+        return error;
+    }
+
+    return 0;
+}
+
+/**
+ * Sets the specified option to the given integer value.
+ */
+int
+Config::setOption(const std::string &name,
+                  int value)
+{
+    std::map<std::string, int>::iterator opt_i;
+
+    // confirm that the option exists
+    opt_i = _intOptMap.find(name);
+    if(opt_i == _intOptMap.end()) {
+        return -1;
+    }
+
+    // set the option
+    opt_i->second = value;
+    return 0;
+}
+
+/**
+ * Sets the specified option to the given string value.
+ */
+int
+Config::setOption(const std::string &name,
+                  const std::string &value)
+{
+    std::map<std::string, std::string>::iterator opt_i;
+
+    // confirm that the option exists
+    opt_i = _strOptMap.find(name);
+    if(opt_i == _strOptMap.end()) {
+        return -1;
+    }
+
+    // set the option
+    opt_i->second = value;
+    return 0;
+}
+
+int
+Config::getOption(const std::string &name,
+                  std::string *value)
+{
+    std::map<std::string, std::string>::iterator opt_i;
+
+    // confirm that the option exists
+    opt_i = _strOptMap.find(name);
+    if(opt_i == _strOptMap.end()) {
+        return -1;
+    }
+
+    // get the option
+    (*value) = opt_i->second;
+    return 0;
+}
+
+int
+Config::getOption(const std::string &name,
+                  const char **value)
+{
+    std::map<std::string, std::string>::iterator opt_i;
+
+    // confirm that the option exists
+    opt_i = _strOptMap.find(name);
+    if(opt_i == _strOptMap.end()) {
+        return -1;
+    }
+
+    // get the option
+    (*value) = opt_i->second.c_str();
+    return 0;
+}
+
+int
+Config::getOption(const std::string &name,
+                  int *value)
+{
+    std::map<std::string, int>::iterator opt_i;
+
+    // confirm that the option exists
+    opt_i = _intOptMap.find(name);
+    if(opt_i == _intOptMap.end()) {
+        return -1;
+    }
+
+    // get the option
+    (*value) = opt_i->second;
+    return 0;
+}
+
+
+/**
+ * Parses the command line arguments.  Short args are of the form -f
+ * <opt>, long args are of the form --foo <opt>.  Returns < 0 on error,
+ * or the index of the rom file in argv.
+ */
+int
+Config::_parseArgs(int argc,
+                   char **argv)
+{
+    int retval = 0;
+    std::map<std::string, std::string>::iterator long_i, str_i;
+    std::map<char, std::string>::iterator short_i;
+    std::map<std::string, int>::iterator int_i;
+    std::string arg, opt, value;
+
+    for(int i = 1; i < argc; i++) {
+        arg = argv[i];
+        if(arg[0] != '-') {
+            // must be a rom name?
+            retval = i;
+            continue;
+        }
+
+        if(arg.size() < 2) {
+            // XXX invalid argument
+            return -1;
+        }
+
+        // parse the argument and get the option name
+        if(arg[1] == '-') {
+            // long arg
+            long_i = _longArgMap.find(arg.substr(2));
+            if(long_i == _longArgMap.end()) {
+                // XXX invalid argument
+                return -1;
+            }
+
+            opt = long_i->second;
+        } else {
+            // short arg
+            short_i = _shortArgMap.find(arg[1]);
+            if(short_i == _shortArgMap.end()) {
+                // XXX invalid argument
+                return -1;
+            }
+
+            opt = short_i->second;
+        }
+
+        // make sure we've got a value
+        if(i + 1 >= argc) {
+            // XXX missing value
+            return -1;
+        }
+        i++;
+
+        // now, find the appropriate option entry, and update it
+        str_i = _strOptMap.find(opt);
+        int_i = _intOptMap.find(opt);
+        if(str_i != _strOptMap.end()) {
+            str_i->second = argv[i];
+        } else if(int_i != _intOptMap.end()) {
+            int_i->second = atol(argv[i]);
+        } else {
+            // XXX invalid option?  shouldn't happen
+            return -1;
+        }
+    }
+
+    // if we didn't get a rom-name, return error
+    return (retval) ? retval : -1;
+}
+
+
+/**
+ * Parses first the configuration file, and then overrides with any
+ * command-line options that were specified.
+ */
+int
+Config::parse(int argc,
+              char **argv)
+{
+    int error;
+
+    // read the config file
+    error = _load();
+    if(error) {
+        return error;
+    }
+
+    // parse the arguments
+    error = _parseArgs(argc, argv);
+    if(error) {
+        return error;
+    }
+
+    return 0;
+}
+
+
+/**
+ * Read each line of the config file and put the variables into the
+ * config maps.  Valid configuration lines are of the form:
+ *
+ * <option name> = <option value>
+ *
+ * Lines beginning with # are ignored.
+ */
+int
+Config::_load()
+{
+    int error;
+    unsigned int pos, eqPos;
+    std::fstream config;
+    std::map<std::string, int>::iterator int_i;
+    std::map<std::string, std::string>::iterator str_i;
+    std::string configFile = _dir + "/fceu.cfg";
+    std::string line, name, value;
+    char buf[1024];
+
+    // set the exception handling to catch i/o errors
+    config.exceptions(std::fstream::badbit);
+
+    try {
+        // open the file for reading (create if it doesn't exist)
+        config.open(configFile.c_str(), std::ios::in | std::ios::out);
+
+        while(!config.eof()) {
+            // read a line
+            config.getline(buf, 1024);
+            line = buf;
+
+            // check line validity
+            eqPos = line.find("=");
+            if(line[0] == '#' || eqPos == std::string::npos) {
+                // skip this line
+                continue;
+            }
+
+            // get the name and value for the option
+            pos = line.find(" ");
+            name = line.substr(0, (pos > eqPos) ? eqPos : pos);
+            pos = line.find_first_not_of(" ", eqPos + 1);
+            value = line.substr(pos);
+
+            // check if the option exists, and if so, set it appropriately
+            str_i = _strOptMap.find(name);
+            int_i = _intOptMap.find(name);
+            if(str_i != _strOptMap.end()) {
+                str_i->second = value;
+            } else if(int_i != _intOptMap.end()) {
+                int_i->second = atol(value.c_str());
+            }
+        }
+
+        // close the file
+        config.close();
+    } catch(std::fstream::failure e) {
+        std::cerr << e.what() << std::endl;
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * Writes the configuration file with the current configuration settings.
+ */
+int
+Config::save()
+{
+    int error;
+    std::fstream config;
+    std::map<std::string, int>::iterator int_i;
+    std::map<std::string, std::string>::iterator str_i;
+    std::string configFile = _dir + "/fceu.cfg";
+    char buf[1024];
+
+    // set the exception handling to catch i/o errors
+    config.exceptions(std::ios::failbit | std::ios::badbit);
+
+    try {
+        // open the file, truncate and for write
+        config.open(configFile.c_str(), std::ios::out | std::ios::trunc);
+
+        // write a warning
+        strcpy(buf, "# Auto-generated\n");
+        config.write(buf, strlen(buf));
+
+        // write each configuration setting
+        for(int_i = _intOptMap.begin(); int_i != _intOptMap.end(); int_i++) {
+            snprintf(buf, 1024, "%s = %d\n",
+                     int_i->first.c_str(), int_i->second);
+            config.write(buf, strlen(buf));
+        }
+        for(str_i = _strOptMap.begin(); str_i != _strOptMap.end(); str_i++) {
+            snprintf(buf, 1024, "%s = %s\n",
+                     str_i->first.c_str(), str_i->second.c_str());
+            config.write(buf, strlen(buf));
+        }
+
+        // close the file
+        config.close();
+    } catch(std::fstream::failure e) {
+        std::cerr << e.what() << std::endl;
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/src/drivers/common/configSys.h b/src/drivers/common/configSys.h
new file mode 100644
index 00000000..da72c959
--- /dev/null
+++ b/src/drivers/common/configSys.h
@@ -0,0 +1,62 @@
+#ifndef __CONFIGSYS_H
+#define __CONFIGSYS_H
+
+#include <map>
+#include <string>
+
+class Config {
+private:
+    std::string _dir;
+
+    std::map<std::string, std::string> _strOptMap;
+    std::map<std::string, int>         _intOptMap;
+
+    std::map<char, std::string>        _shortArgMap;
+    std::map<std::string, std::string> _longArgMap;
+
+private:
+    int _addOption(char, const std::string &, const std::string &, int);
+    int _load(void);
+    int _parseArgs(int, char **);
+
+public:
+    const static int STRING  = 1;
+    const static int INTEGER = 2;
+
+public:
+    Config(std::string d) : _dir(d) { }
+    ~Config() { }
+
+    /**
+     * Adds a configuration option.  All options must be added before
+     * parse().
+     */
+    int addOption(char, const std::string &,
+                  const std::string &, int, int);
+    int addOption(char, const std::string &,
+                  const std::string &, int, const std::string &);
+
+    /**
+     * Sets a configuration option.  Can be called at any time.
+     */
+    int setOption(const std::string &, int);
+    int setOption(const std::string &, const std::string &);
+
+    int getOption(const std::string &, std::string *);
+    int getOption(const std::string &, const char **);
+    int getOption(const std::string &, int *);
+
+    /**
+     * Parse the arguments.  Also read in the configuration file and
+     * set the variables accordingly.
+     */
+    int parse(int, char **);
+
+    /**
+     * Save all of the current configuration options to the
+     * configuration file.
+     */
+    int save();
+};
+
+#endif // !__CONFIGSYS_H