Holds game configuration settings
 public GameHandler(ref GameConfiguration gameConfig, Boolean inArcadeMode)
 {
     if (inArcadeMode)
         beginInArcadeMode(ref gameConfig);
     else
         begin(ref gameConfig);
 }
 //TODO: need better boolean naming, use anonymous type to pass GUI parameters? Nah, use a struct.
 public GameHandler(ref GameConfiguration gameConfig, String joyToKeyConfigPath, Boolean arcadeMode, Boolean fullScreen, Boolean hideMouse)
 {
     if (arcadeMode)
         beginInArcadeMode(ref gameConfig, joyToKeyConfigPath, arcadeMode, fullScreen, hideMouse);
     else
         begin(ref gameConfig, joyToKeyConfigPath, arcadeMode, fullScreen, hideMouse);
 }
        /// <returns>true upon success</returns>
        private Boolean downloadGame(ref GameConfiguration gameConfig)
        {
            //String portableFolderPath = General.ProgramFilesx86Path() + @"\TrollKit\Portable Games\"; //permissions error =(
            String filename = Path.GetFileName(gameConfig.DownloadUrl);
            String savePath = portableFolderPath + filename;

            Directory.CreateDirectory(Path.GetDirectoryName(savePath));

            //TODO: do this asynchronously and display a progress bar and a cancel button
            try
            {
                using (WebClient webClient = new WebClient())
                {
                    byte[] data = webClient.DownloadData(gameConfig.DownloadUrl);
                    System.IO.File.WriteAllBytes(savePath, data);
                    return true;
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message + "\n\nTry downloading it yourself from " + gameConfig.DownloadUrl,
                    "Failed to download the game");
                //TODO: later, should log failed downloads and send them to to our server, to update broken links
                return false;
            }
        }
        private void begin(ref GameConfiguration gameConfig)
        {
            //run JoyToKey
            runJoyToKey(ref gameConfig);

            //run game
            Process.Start(gameConfig.GamePath);

            //TODO: need to close JoyToKey after game exits, in begin and beginInArcadeMode
        }
        private void beginInArcadeMode(ref GameConfiguration gameConfig)
        {
            Boolean closed = true;
            Boolean stopRunner = false;
            Process game = new Process();
            Process joyToKey = new Process();
            GlobalMouseKeyboard globalMouseKeyboard = new GlobalMouseKeyboard();

            runJoyToKey(ref gameConfig);

            while (!stopRunner)
            {
                if (globalMouseKeyboard.F2IsPressed)
                {
                    //restart the game
                    game.Kill();
                    closed = true;
                    globalMouseKeyboard.F2IsPressed = false;
                }

                if (globalMouseKeyboard.F4IsPressed)
                {
                    //end arcade mode
                    game.Kill();
                    stopRunner = true;
                    globalMouseKeyboard.Dispose();
                }

                if (closed)
                {
                    if (gameConfig.HideMouse)
                        Cursor.Position = new Point(2000, 2000); //work around
                        //another work around, set the cursor graphic to a transparent one, http://forums.whirlpool.net.au/archive/1172326

                    ProcessStartInfo psi = new ProcessStartInfo(gameConfig.GamePath);
                    if (gameConfig.FullScreen)
                        psi.WindowStyle = ProcessWindowStyle.Maximized; //TODO: only maximizes fully if the taskbar is set to auto-hide
                    game = Process.Start(psi);

                    closed = false;
                }

                game.WaitForExit(100); //? to reduce cpu usage?

                if (game.HasExited)
                {
                    closed = true;
                }
            }
        }
        private Process runGame(GameConfiguration gameConfig, Boolean hideMouse, Boolean fullScreen)
        {
            if (hideMouse)
                Cursor.Position = new Point(2000, 2000); //work around
            //another work around, set the cursor graphic to a transparent one, http://forums.whirlpool.net.au/archive/1172326

            ProcessStartInfo psi = new ProcessStartInfo(gameConfig.Path);
            psi.WorkingDirectory = Path.GetDirectoryName(gameConfig.Path);

            if (fullScreen)
                psi.WindowStyle = ProcessWindowStyle.Maximized; //TODO: only maximizes fully if the taskbar is set to auto-hide

            return Process.Start(psi);
        }
        private void beginInArcadeMode(ref GameConfiguration gameConfig, String joyToKeyConfigPath, Boolean inArcadeMode, Boolean fullScreen, Boolean hideMouse)
        {
            Boolean closed = true;
            Boolean stopRunner = false;
            Process game = new Process();
            Process joyToKey = new Process();
            GlobalMouseKeyboard globalMouseKeyboard = new GlobalMouseKeyboard();

            runJoyToKey(ref gameConfig, joyToKeyConfigPath);

            while (!stopRunner) {
                if (globalMouseKeyboard.F2IsPressed) {
                    //restart the game
                    game.Kill();
                    closed = true;
                    globalMouseKeyboard.F2IsPressed = false;
                }

                if (globalMouseKeyboard.F4IsPressed) {
                    //end arcade mode
                    game.Kill();
                    stopRunner = true;
                    globalMouseKeyboard.Dispose();
                    Rahil.Shared.tryKillProcess("JoyToKey");
                }

                if (closed) {
                    game = runGame(gameConfig, hideMouse, fullScreen);
                    closed = false;
                }

                game.WaitForExit(100); //? to reduce cpu usage?

                if (game.HasExited) {
                    closed = true;
                }
            }
        }
        private void runJoyToKey(ref GameConfiguration gameConfig)
        {
            //close JoyToKey
            //TODO: should open a different config file instead of restarting the application
            General.tryKillProcess("JoyToKey");

            if (gameConfig.UsesJoyToKey)
            {
                //run JoyToKey
                #if (DEBUG)
                String joyToKeyFileName = @"..\..\JoyToKey\JoyToKey.exe";
                String joyToKeyPath = @"..\..\JoyToKey\";
                #else
                String joyToKeyFileName = @"JoyToKey\JoyToKey.exe";
                String joyToKeyPath = @"JoyToKey\";
                #endif

                //String joyToKeyFileName = @"JoyToKey\JoyToKey.exe";
                //String joyToKeyPath = @"JoyToKey\";

                ProcessStartInfo joyToKeyPsi = new ProcessStartInfo(joyToKeyFileName, '"' + gameConfig.GameName + ".cfg" + '"');
                joyToKeyPsi.WorkingDirectory = joyToKeyPath;
                joyToKeyPsi.WindowStyle = ProcessWindowStyle.Minimized; //TODO: not working
                System.Windows.Forms.MessageBox.Show(joyToKeyPsi.FileName); //TODO: STOPPED HERE
                Process.Start(joyToKeyPsi);
            }
        }
        private void runJoyToKey(ref GameConfiguration gameConfig, String joyToKeyConfigPath)
        {
            //close JoyToKey
            //TODO: figure out how to open a different config file instead of restarting the application
            Rahil.Shared.tryKillProcess("JoyToKey");

            if (joyToKeyConfigPath != String.Empty) {
                //run JoyToKey
                String joyToKeyFolderPath = Global.JoyToKeyFolderPath;
                String joyToKeyFilePath = joyToKeyFolderPath + @"\JoyToKey.exe";

                ProcessStartInfo joyToKeyPsi = new ProcessStartInfo(joyToKeyFilePath, '"' + Path.GetFileNameWithoutExtension(joyToKeyConfigPath) + '"');
                joyToKeyPsi.WorkingDirectory = joyToKeyFolderPath;
                //joyToKeyPsi.WindowStyle = ProcessWindowStyle.Minimized; //TODO: not working
                //MinimizeWindow.minimize("JoyToKey"); //fail
                Process.Start(joyToKeyPsi);
            }
        }
 private void begin(ref GameConfiguration gameConfig, String joyToKeyConfigPath, Boolean arcadeMode, Boolean fullScreen, Boolean hideMouse)
 {
     runJoyToKey(ref gameConfig, joyToKeyConfigPath);
     runGame(gameConfig, hideMouse, fullScreen);
     //TODO: need to close JoyToKey after game exits
 }
        private void extractGame(ref GameConfiguration gameConfig)
        {
            //String portableFolderPath = General.ProgramFilesx86Path() + @"\TrollKit\Portable Games\"; //permissions error =(
            String filename = Path.GetFileName(gameConfig.DownloadUrl);
            String archivePath = portableFolderPath + filename;
            String extractionPath = portableFolderPath + @"\" + gameConfig.GameName + @"\"; //add a folder in case the archive does not have a top level folder
            //TODO: later, a better solution would be to check if the archive has one top level folder, then extract depending on that

            //extract the archive
            using (ZipFile zip = ZipFile.Read(archivePath))
            {
                zip.ExtractAll(extractionPath); //creates the folder if it does not exist?
            }

            //delete the archive file
            File.Delete(archivePath);
        }